Commit 8dc0ba7a authored by Robert Hencke's avatar Robert Hencke Committed by Russ Cox

io: fixes for Read with n > 0, os.EOF

R=rsc
CC=golang-dev
https://golang.org/cl/4271080
parent 68ed122b
...@@ -182,16 +182,16 @@ func ReadAtLeast(r Reader, buf []byte, min int) (n int, err os.Error) { ...@@ -182,16 +182,16 @@ func ReadAtLeast(r Reader, buf []byte, min int) (n int, err os.Error) {
if len(buf) < min { if len(buf) < min {
return 0, ErrShortBuffer return 0, ErrShortBuffer
} }
for n < min { for n < min && err == nil {
nn, e := r.Read(buf[n:]) var nn int
if nn > 0 { nn, err = r.Read(buf[n:])
n += nn n += nn
} }
if e != nil { if err == os.EOF {
if e == os.EOF && n > 0 { if n >= min {
e = ErrUnexpectedEOF err = nil
} } else if n > 0 {
return n, e err = ErrUnexpectedEOF
} }
} }
return return
......
...@@ -118,27 +118,50 @@ func TestCopynEOF(t *testing.T) { ...@@ -118,27 +118,50 @@ func TestCopynEOF(t *testing.T) {
func TestReadAtLeast(t *testing.T) { func TestReadAtLeast(t *testing.T) {
var rb bytes.Buffer var rb bytes.Buffer
testReadAtLeast(t, &rb)
}
// A version of bytes.Buffer that returns n > 0, os.EOF on Read
// when the input is exhausted.
type dataAndEOFBuffer struct {
bytes.Buffer
}
func (r *dataAndEOFBuffer) Read(p []byte) (n int, err os.Error) {
n, err = r.Buffer.Read(p)
if n > 0 && r.Buffer.Len() == 0 && err == nil {
err = os.EOF
}
return
}
func TestReadAtLeastWithDataAndEOF(t *testing.T) {
var rb dataAndEOFBuffer
testReadAtLeast(t, &rb)
}
func testReadAtLeast(t *testing.T, rb ReadWriter) {
rb.Write([]byte("0123")) rb.Write([]byte("0123"))
buf := make([]byte, 2) buf := make([]byte, 2)
n, err := ReadAtLeast(&rb, buf, 2) n, err := ReadAtLeast(rb, buf, 2)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
n, err = ReadAtLeast(&rb, buf, 4) n, err = ReadAtLeast(rb, buf, 4)
if err != ErrShortBuffer { if err != ErrShortBuffer {
t.Errorf("expected ErrShortBuffer got %v", err) t.Errorf("expected ErrShortBuffer got %v", err)
} }
if n != 0 { if n != 0 {
t.Errorf("expected to have read 0 bytes, got %v", n) t.Errorf("expected to have read 0 bytes, got %v", n)
} }
n, err = ReadAtLeast(&rb, buf, 1) n, err = ReadAtLeast(rb, buf, 1)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
if n != 2 { if n != 2 {
t.Errorf("expected to have read 2 bytes, got %v", n) t.Errorf("expected to have read 2 bytes, got %v", n)
} }
n, err = ReadAtLeast(&rb, buf, 2) n, err = ReadAtLeast(rb, buf, 2)
if err != os.EOF { if err != os.EOF {
t.Errorf("expected EOF, got %v", err) t.Errorf("expected EOF, got %v", err)
} }
...@@ -146,7 +169,7 @@ func TestReadAtLeast(t *testing.T) { ...@@ -146,7 +169,7 @@ func TestReadAtLeast(t *testing.T) {
t.Errorf("expected to have read 0 bytes, got %v", n) t.Errorf("expected to have read 0 bytes, got %v", n)
} }
rb.Write([]byte("4")) rb.Write([]byte("4"))
n, err = ReadAtLeast(&rb, buf, 2) n, err = ReadAtLeast(rb, buf, 2)
if err != ErrUnexpectedEOF { if err != ErrUnexpectedEOF {
t.Errorf("expected ErrUnexpectedEOF, got %v", err) t.Errorf("expected ErrUnexpectedEOF, got %v", err)
} }
......
...@@ -15,10 +15,8 @@ func (mr *multiReader) Read(p []byte) (n int, err os.Error) { ...@@ -15,10 +15,8 @@ func (mr *multiReader) Read(p []byte) (n int, err os.Error) {
n, err = mr.readers[0].Read(p) n, err = mr.readers[0].Read(p)
if n > 0 || err != os.EOF { if n > 0 || err != os.EOF {
if err == os.EOF { if err == os.EOF {
// This shouldn't happen. // Don't return EOF yet. There may be more bytes
// Well-behaved Readers should never // in the remaining readers.
// return non-zero bytes read with an
// EOF. But if so, we clean it.
err = nil err = nil
} }
return return
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment