|  | // Copyright 2009 The Go Authors. All rights reserved. | 
|  | // Use of this source code is governed by a BSD-style | 
|  | // license that can be found in the LICENSE file. | 
|  |  | 
|  | package bufio | 
|  |  | 
|  | import ( | 
|  | "bufio"; | 
|  | "fmt"; | 
|  | "io"; | 
|  | "os"; | 
|  | "testing"; | 
|  | "testing/iotest"; | 
|  | ) | 
|  |  | 
|  | // Reads from a reader and rot13s the result. | 
|  | type rot13Reader struct { | 
|  | r io.Reader | 
|  | } | 
|  |  | 
|  | func newRot13Reader(r io.Reader) *rot13Reader { | 
|  | r13 := new(rot13Reader); | 
|  | r13.r = r; | 
|  | return r13 | 
|  | } | 
|  |  | 
|  | func (r13 *rot13Reader) Read(p []byte) (int, os.Error) { | 
|  | n, e := r13.r.Read(p); | 
|  | if e != nil { | 
|  | return n, e | 
|  | } | 
|  | for i := 0; i < n; i++ { | 
|  | c := p[i] | 0x20;	// lowercase byte | 
|  | if 'a' <= c && c <= 'm' { | 
|  | p[i] += 13; | 
|  | } else if 'n' <= c && c <= 'z' { | 
|  | p[i] -= 13; | 
|  | } | 
|  | } | 
|  | return n, nil | 
|  | } | 
|  |  | 
|  | // Call ReadByte to accumulate the text of a file | 
|  | func readBytes(buf *Reader) string { | 
|  | var b [1000]byte; | 
|  | nb := 0; | 
|  | for { | 
|  | c, e := buf.ReadByte(); | 
|  | if e == os.EOF { | 
|  | break | 
|  | } | 
|  | if e != nil { | 
|  | panic("Data: "+e.String()) | 
|  | } | 
|  | b[nb] = c; | 
|  | nb++; | 
|  | } | 
|  | return string(b[0:nb]) | 
|  | } | 
|  |  | 
|  | func TestReaderSimple(t *testing.T) { | 
|  | data := io.StringBytes("hello world"); | 
|  | b := NewReader(io.NewByteReader(data)); | 
|  | if s := readBytes(b); s != "hello world" { | 
|  | t.Errorf("simple hello world test failed: got %q", s); | 
|  | } | 
|  |  | 
|  | b = NewReader(newRot13Reader(io.NewByteReader(data))); | 
|  | if s := readBytes(b); s != "uryyb jbeyq" { | 
|  | t.Error("rot13 hello world test failed: got %q", s); | 
|  | } | 
|  | } | 
|  |  | 
|  |  | 
|  | type readMaker struct { | 
|  | name string; | 
|  | fn func(io.Reader) io.Reader; | 
|  | } | 
|  | var readMakers = []readMaker { | 
|  | readMaker{ "full", func(r io.Reader) io.Reader { return r } }, | 
|  | readMaker{ "byte", iotest.OneByteReader }, | 
|  | readMaker{ "half", iotest.HalfReader }, | 
|  | } | 
|  |  | 
|  | // Call ReadLineString (which ends up calling everything else) | 
|  | // to accumulate the text of a file. | 
|  | func readLines(b *Reader) string { | 
|  | s := ""; | 
|  | for { | 
|  | s1, e := b.ReadLineString('\n', true); | 
|  | if e == os.EOF { | 
|  | break | 
|  | } | 
|  | if e != nil { | 
|  | panic("GetLines: "+e.String()) | 
|  | } | 
|  | s += s1 | 
|  | } | 
|  | return s | 
|  | } | 
|  |  | 
|  | // Call Read to accumulate the text of a file | 
|  | func reads(buf *Reader, m int) string { | 
|  | var b [1000]byte; | 
|  | nb := 0; | 
|  | for { | 
|  | n, e := buf.Read(b[nb:nb+m]); | 
|  | nb += n; | 
|  | if e == os.EOF { | 
|  | break | 
|  | } | 
|  | } | 
|  | return string(b[0:nb]) | 
|  | } | 
|  |  | 
|  | type bufReader struct { | 
|  | name string; | 
|  | fn func(*Reader) string; | 
|  | } | 
|  | var bufreaders = []bufReader { | 
|  | bufReader{ "1", func(b *Reader) string { return reads(b, 1) } }, | 
|  | bufReader{ "2", func(b *Reader) string { return reads(b, 2) } }, | 
|  | bufReader{ "3", func(b *Reader) string { return reads(b, 3) } }, | 
|  | bufReader{ "4", func(b *Reader) string { return reads(b, 4) } }, | 
|  | bufReader{ "5", func(b *Reader) string { return reads(b, 5) } }, | 
|  | bufReader{ "7", func(b *Reader) string { return reads(b, 7) } }, | 
|  | bufReader{ "bytes", readBytes }, | 
|  | bufReader{ "lines", readLines }, | 
|  | } | 
|  |  | 
|  | var bufsizes = []int { | 
|  | 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, | 
|  | 23, 32, 46, 64, 93, 128, 1024, 4096 | 
|  | } | 
|  |  | 
|  | func TestReader(t *testing.T) { | 
|  | var texts [31]string; | 
|  | str := ""; | 
|  | all := ""; | 
|  | for i := 0; i < len(texts)-1; i++ { | 
|  | texts[i] = str + "\n"; | 
|  | all += texts[i]; | 
|  | str += string(i%26+'a') | 
|  | } | 
|  | texts[len(texts)-1] = all; | 
|  |  | 
|  | for h := 0; h < len(texts); h++ { | 
|  | text := texts[h]; | 
|  | textbytes := io.StringBytes(text); | 
|  | for i := 0; i < len(readMakers); i++ { | 
|  | for j := 0; j < len(bufreaders); j++ { | 
|  | for k := 0; k < len(bufsizes); k++ { | 
|  | readmaker := readMakers[i]; | 
|  | bufreader := bufreaders[j]; | 
|  | bufsize := bufsizes[k]; | 
|  | read := readmaker.fn(io.NewByteReader(textbytes)); | 
|  | buf, e := NewReaderSize(read, bufsize); | 
|  | s := bufreader.fn(buf); | 
|  | if s != text { | 
|  | t.Errorf("reader=%s fn=%s bufsize=%d want=%q got=%q", | 
|  | readmaker.name, bufreader.name, bufsize, text, s); | 
|  | } | 
|  | } | 
|  | } | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | func TestWriter(t *testing.T) { | 
|  | var data [8192]byte; | 
|  |  | 
|  | for i := 0; i < len(data); i++ { | 
|  | data[i] = byte(' '+ i%('~'-' ')); | 
|  | } | 
|  | w := new(io.ByteBuffer); | 
|  | for i := 0; i < len(bufsizes); i++ { | 
|  | for j := 0; j < len(bufsizes); j++ { | 
|  | nwrite := bufsizes[i]; | 
|  | bs := bufsizes[j]; | 
|  |  | 
|  | // Write nwrite bytes using buffer size bs. | 
|  | // Check that the right amount makes it out | 
|  | // and that the data is correct. | 
|  |  | 
|  | w.Reset(); | 
|  | buf, e := NewWriterSize(w, bs); | 
|  | context := fmt.Sprintf("nwrite=%d bufsize=%d", nwrite, bs); | 
|  | if e != nil { | 
|  | t.Errorf("%s: NewWriterSize %d: %v", context, bs, e); | 
|  | continue; | 
|  | } | 
|  | n, e1 := buf.Write(data[0:nwrite]); | 
|  | if e1 != nil || n != nwrite { | 
|  | t.Errorf("%s: buf.Write %d = %d, %v", context, nwrite, n, e1); | 
|  | continue; | 
|  | } | 
|  | if e = buf.Flush(); e != nil { | 
|  | t.Errorf("%s: buf.Flush = %v", context, e); | 
|  | } | 
|  |  | 
|  | written := w.Data(); | 
|  | if len(written) != nwrite { | 
|  | t.Errorf("%s: %d bytes written", context, len(written)); | 
|  | } | 
|  | for l := 0; l < len(written); l++ { | 
|  | if written[i] != data[i] { | 
|  | t.Errorf("%s: wrong bytes written"); | 
|  | t.Errorf("want=%s", data[0:len(written)]); | 
|  | t.Errorf("have=%s", written); | 
|  | } | 
|  | } | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | // Check that write errors are returned properly. | 
|  |  | 
|  | type errorWriterTest struct { | 
|  | n, m int; | 
|  | err os.Error; | 
|  | expect os.Error; | 
|  | } | 
|  |  | 
|  | func (w errorWriterTest) Write(p []byte) (int, os.Error) { | 
|  | return len(p)*w.n/w.m, w.err; | 
|  | } | 
|  |  | 
|  | var errorWriterTests = []errorWriterTest { | 
|  | errorWriterTest{ 0, 1, nil, io.ErrShortWrite }, | 
|  | errorWriterTest{ 1, 2, nil, io.ErrShortWrite }, | 
|  | errorWriterTest{ 1, 1, nil, nil }, | 
|  | errorWriterTest{ 0, 1, os.EPIPE, os.EPIPE }, | 
|  | errorWriterTest{ 1, 2, os.EPIPE, os.EPIPE }, | 
|  | errorWriterTest{ 1, 1, os.EPIPE, os.EPIPE }, | 
|  | } | 
|  |  | 
|  | func TestWriteErrors(t *testing.T) { | 
|  | for i, w := range errorWriterTests { | 
|  | buf := NewWriter(w); | 
|  | n, e := buf.Write(io.StringBytes("hello world")); | 
|  | if e != nil { | 
|  | t.Errorf("Write hello to %v: %v", w, e); | 
|  | continue; | 
|  | } | 
|  | e = buf.Flush(); | 
|  | if e != w.expect { | 
|  | t.Errorf("Flush %v: got %v, wanted %v", w, e, w.expect); | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | func TestNewReaderSizeIdempotent(t *testing.T) { | 
|  | const BufSize = 1000; | 
|  | b, err := NewReaderSize(io.NewByteReader(io.StringBytes("hello world")), BufSize); | 
|  | if err != nil { | 
|  | t.Error("NewReaderSize create fail", err); | 
|  | } | 
|  | // Does it recognize itself? | 
|  | b1, err2 := NewReaderSize(b, BufSize); | 
|  | if err2 != nil { | 
|  | t.Error("NewReaderSize #2 create fail", err2); | 
|  | } | 
|  | if b1 != b { | 
|  | t.Error("NewReaderSize did not detect underlying Reader"); | 
|  | } | 
|  | // Does it wrap if existing buffer is too small? | 
|  | b2, err3 := NewReaderSize(b, 2*BufSize); | 
|  | if err3 != nil { | 
|  | t.Error("NewReaderSize #3 create fail", err3); | 
|  | } | 
|  | if b2 == b { | 
|  | t.Error("NewReaderSize did not enlarge buffer"); | 
|  | } | 
|  | } | 
|  |  | 
|  | func TestNewWriterSizeIdempotent(t *testing.T) { | 
|  | const BufSize = 1000; | 
|  | b, err := NewWriterSize(new(io.ByteBuffer), BufSize); | 
|  | if err != nil { | 
|  | t.Error("NewWriterSize create fail", err); | 
|  | } | 
|  | // Does it recognize itself? | 
|  | b1, err2 := NewWriterSize(b, BufSize); | 
|  | if err2 != nil { | 
|  | t.Error("NewWriterSize #2 create fail", err2); | 
|  | } | 
|  | if b1 != b { | 
|  | t.Error("NewWriterSize did not detect underlying Writer"); | 
|  | } | 
|  | // Does it wrap if existing buffer is too small? | 
|  | b2, err3 := NewWriterSize(b, 2*BufSize); | 
|  | if err3 != nil { | 
|  | t.Error("NewWriterSize #3 create fail", err3); | 
|  | } | 
|  | if b2 == b { | 
|  | t.Error("NewWriterSize did not enlarge buffer"); | 
|  | } | 
|  | } |