mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
add io.ByteReader.
add testing/iotest package. make bufio return error on short write. R=r DELTA=423 (208 added, 154 deleted, 61 changed) OCL=28997 CL=28999
This commit is contained in:
parent
6b942c68cc
commit
be869ba4d6
7 changed files with 269 additions and 210 deletions
|
|
@ -45,6 +45,7 @@ DIRS=\
|
||||||
tabwriter\
|
tabwriter\
|
||||||
template\
|
template\
|
||||||
testing\
|
testing\
|
||||||
|
testing/iotest\
|
||||||
time\
|
time\
|
||||||
unicode\
|
unicode\
|
||||||
utf8\
|
utf8\
|
||||||
|
|
@ -115,6 +116,7 @@ nuke: nuke.dirs
|
||||||
|
|
||||||
bignum.install: fmt.install
|
bignum.install: fmt.install
|
||||||
bufio.install: io.install os.install
|
bufio.install: io.install os.install
|
||||||
|
crypto/aes.install: os.install
|
||||||
exec.install: os.install strings.install
|
exec.install: os.install strings.install
|
||||||
exvar.install: fmt.install http.install log.install strconv.install sync.install
|
exvar.install: fmt.install http.install log.install strconv.install sync.install
|
||||||
flag.install: fmt.install os.install strconv.install
|
flag.install: fmt.install os.install strconv.install
|
||||||
|
|
@ -123,7 +125,7 @@ path.install: io.install
|
||||||
once.install: sync.install
|
once.install: sync.install
|
||||||
strings.install: utf8.install
|
strings.install: utf8.install
|
||||||
testing.install: flag.install fmt.install runtime.install
|
testing.install: flag.install fmt.install runtime.install
|
||||||
|
testing/iotest.install: io.install os.install
|
||||||
fmt.install: io.install reflect.install strconv.install
|
fmt.install: io.install reflect.install strconv.install
|
||||||
GODEPS=fmt.install io.install once.install regexp.install sort.install \
|
GODEPS=fmt.install io.install once.install regexp.install sort.install \
|
||||||
strconv.install strings.install unicode.install utf8.install container/vector.install
|
strconv.install strings.install unicode.install utf8.install container/vector.install
|
||||||
|
|
|
||||||
|
|
@ -421,21 +421,17 @@ func (b *Writer) Flush() os.Error {
|
||||||
if b.err != nil {
|
if b.err != nil {
|
||||||
return b.err
|
return b.err
|
||||||
}
|
}
|
||||||
n := 0;
|
n, e := b.wr.Write(b.buf[0:b.n]);
|
||||||
for n < b.n {
|
if n < b.n && e == nil {
|
||||||
m, e := b.wr.Write(b.buf[n:b.n]);
|
e = io.ErrShortWrite;
|
||||||
n += m;
|
}
|
||||||
if m == 0 && e == nil {
|
if e != nil {
|
||||||
e = io.ErrShortWrite
|
if n > 0 && n < b.n {
|
||||||
}
|
copySlice(b.buf[0:b.n-n], b.buf[n:b.n])
|
||||||
if e != nil {
|
|
||||||
if n < b.n {
|
|
||||||
copySlice(b.buf[0:b.n-n], b.buf[n:b.n])
|
|
||||||
}
|
|
||||||
b.n -= n;
|
|
||||||
b.err = e;
|
|
||||||
return e
|
|
||||||
}
|
}
|
||||||
|
b.n -= n;
|
||||||
|
b.err = e;
|
||||||
|
return e
|
||||||
}
|
}
|
||||||
b.n = 0;
|
b.n = 0;
|
||||||
return nil
|
return nil
|
||||||
|
|
@ -505,14 +501,14 @@ func (b *Writer) WriteByte(c byte) os.Error {
|
||||||
|
|
||||||
// buffered input and output
|
// buffered input and output
|
||||||
|
|
||||||
// ReadWriter stores (a pointer to) a Reader and a Writer.
|
// ReadWriter stores pointers to a Reader and a Writer.
|
||||||
// It implements io.ReadWriter.
|
// It implements io.ReadWriter.
|
||||||
type ReadWriter struct {
|
type ReadWriter struct {
|
||||||
*Reader;
|
*Reader;
|
||||||
*Writer;
|
*Writer;
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewReadWriter allocates a new ReadWriter holding r and w.
|
// NewReadWriter allocates a new ReadWriter that dispatches to r and w.
|
||||||
func NewReadWriter(r *Reader, w *Writer) *ReadWriter {
|
func NewReadWriter(r *Reader, w *Writer) *ReadWriter {
|
||||||
return &ReadWriter{r, w}
|
return &ReadWriter{r, w}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -10,61 +10,9 @@ import (
|
||||||
"io";
|
"io";
|
||||||
"os";
|
"os";
|
||||||
"testing";
|
"testing";
|
||||||
|
"testing/iotest";
|
||||||
)
|
)
|
||||||
|
|
||||||
// Should be in language!
|
|
||||||
func copy(p []byte, q []byte) {
|
|
||||||
for i := 0; i < len(p); i++ {
|
|
||||||
p[i] = q[i]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Reads from p.
|
|
||||||
type byteReader struct {
|
|
||||||
p []byte
|
|
||||||
}
|
|
||||||
|
|
||||||
func newByteReader(p []byte) io.Reader {
|
|
||||||
b := new(byteReader);
|
|
||||||
b.p = p;
|
|
||||||
return b
|
|
||||||
}
|
|
||||||
|
|
||||||
func (b *byteReader) Read(p []byte) (int, os.Error) {
|
|
||||||
n := len(p);
|
|
||||||
if n > len(b.p) {
|
|
||||||
n = len(b.p)
|
|
||||||
}
|
|
||||||
copy(p[0:n], b.p[0:n]);
|
|
||||||
b.p = b.p[n:len(b.p)];
|
|
||||||
return n, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Reads from p but only returns half of what you asked for.
|
|
||||||
type halfByteReader struct {
|
|
||||||
p []byte
|
|
||||||
}
|
|
||||||
|
|
||||||
func newHalfByteReader(p []byte) io.Reader {
|
|
||||||
b := new(halfByteReader);
|
|
||||||
b.p = p;
|
|
||||||
return b
|
|
||||||
}
|
|
||||||
|
|
||||||
func (b *halfByteReader) Read(p []byte) (int, os.Error) {
|
|
||||||
n := len(p)/2;
|
|
||||||
if n == 0 && len(p) > 0 {
|
|
||||||
n = 1
|
|
||||||
}
|
|
||||||
if n > len(b.p) {
|
|
||||||
n = len(b.p)
|
|
||||||
}
|
|
||||||
copy(p[0:n], b.p[0:n]);
|
|
||||||
b.p = b.p[n:len(b.p)];
|
|
||||||
return n, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Reads from a reader and rot13s the result.
|
// Reads from a reader and rot13s the result.
|
||||||
type rot13Reader struct {
|
type rot13Reader struct {
|
||||||
r io.Reader
|
r io.Reader
|
||||||
|
|
@ -82,24 +30,56 @@ func (r13 *rot13Reader) Read(p []byte) (int, os.Error) {
|
||||||
return n, e
|
return n, e
|
||||||
}
|
}
|
||||||
for i := 0; i < n; i++ {
|
for i := 0; i < n; i++ {
|
||||||
if 'a' <= p[i] && p[i] <= 'z' || 'A' <= p[i] && p[i] <= 'Z' {
|
c := p[i] | 0x20; // lowercase byte
|
||||||
if 'a' <= p[i] && p[i] <= 'm' || 'A' <= p[i] && p[i] <= 'M' {
|
if 'a' <= c && c <= 'm' {
|
||||||
p[i] += 13;
|
p[i] += 13;
|
||||||
} else {
|
} else if 'n' <= c && c <= 'z' {
|
||||||
p[i] -= 13;
|
p[i] -= 13;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return n, nil
|
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 == io.ErrEOF {
|
||||||
|
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 {
|
type readMaker struct {
|
||||||
name string;
|
name string;
|
||||||
fn func([]byte) io.Reader;
|
fn func(io.Reader) io.Reader;
|
||||||
}
|
}
|
||||||
var readMakers = []readMaker {
|
var readMakers = []readMaker {
|
||||||
readMaker{ "full", func(p []byte) io.Reader { return newByteReader(p) } },
|
readMaker{ "full", func(r io.Reader) io.Reader { return r } },
|
||||||
readMaker{ "half", func(p []byte) io.Reader { return newHalfByteReader(p) } },
|
readMaker{ "byte", iotest.OneByteReader },
|
||||||
|
readMaker{ "half", iotest.HalfReader },
|
||||||
}
|
}
|
||||||
|
|
||||||
// Call ReadLineString (which ends up calling everything else)
|
// Call ReadLineString (which ends up calling everything else)
|
||||||
|
|
@ -119,25 +99,6 @@ func readLines(b *Reader) string {
|
||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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 == io.ErrEOF {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
if e != nil {
|
|
||||||
panic("GetBytes: "+e.String())
|
|
||||||
}
|
|
||||||
b[nb] = c;
|
|
||||||
nb++;
|
|
||||||
}
|
|
||||||
// BUG return string(b[0:nb]) ?
|
|
||||||
return string(b[0:nb])
|
|
||||||
}
|
|
||||||
|
|
||||||
// Call Read to accumulate the text of a file
|
// Call Read to accumulate the text of a file
|
||||||
func reads(buf *Reader, m int) string {
|
func reads(buf *Reader, m int) string {
|
||||||
var b [1000]byte;
|
var b [1000]byte;
|
||||||
|
|
@ -172,18 +133,6 @@ var bufsizes = []int {
|
||||||
23, 32, 46, 64, 93, 128, 1024, 4096
|
23, 32, 46, 64, 93, 128, 1024, 4096
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestReaderSimple(t *testing.T) {
|
|
||||||
b := NewReader(newByteReader(io.StringBytes("hello world")));
|
|
||||||
if s := readBytes(b); s != "hello world" {
|
|
||||||
t.Errorf("simple hello world test failed: got %q", s);
|
|
||||||
}
|
|
||||||
|
|
||||||
b = NewReader(newRot13Reader(newByteReader(io.StringBytes("hello world"))));
|
|
||||||
if s := readBytes(b); s != "uryyb jbeyq" {
|
|
||||||
t.Error("rot13 hello world test failed: got %q", s);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestReader(t *testing.T) {
|
func TestReader(t *testing.T) {
|
||||||
var texts [31]string;
|
var texts [31]string;
|
||||||
str := "";
|
str := "";
|
||||||
|
|
@ -204,7 +153,7 @@ func TestReader(t *testing.T) {
|
||||||
readmaker := readMakers[i];
|
readmaker := readMakers[i];
|
||||||
bufreader := bufreaders[j];
|
bufreader := bufreaders[j];
|
||||||
bufsize := bufsizes[k];
|
bufsize := bufsizes[k];
|
||||||
read := readmaker.fn(textbytes);
|
read := readmaker.fn(io.NewByteReader(textbytes));
|
||||||
buf, e := NewReaderSize(read, bufsize);
|
buf, e := NewReaderSize(read, bufsize);
|
||||||
s := bufreader.fn(buf);
|
s := bufreader.fn(buf);
|
||||||
if s != text {
|
if s != text {
|
||||||
|
|
@ -217,122 +166,92 @@ func TestReader(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type writeBuffer interface {
|
|
||||||
Write(p []byte) (int, os.Error);
|
|
||||||
GetBytes() []byte
|
|
||||||
}
|
|
||||||
|
|
||||||
// Accumulates bytes into a byte array.
|
|
||||||
type byteWriter struct {
|
|
||||||
p []byte;
|
|
||||||
n int
|
|
||||||
}
|
|
||||||
|
|
||||||
func newByteWriter() writeBuffer {
|
|
||||||
return new(byteWriter)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *byteWriter) Write(p []byte) (int, os.Error) {
|
|
||||||
if w.p == nil {
|
|
||||||
w.p = make([]byte, len(p)+100)
|
|
||||||
} else if w.n + len(p) >= len(w.p) {
|
|
||||||
newp := make([]byte, len(w.p)*2 + len(p));
|
|
||||||
copy(newp[0:w.n], w.p[0:w.n]);
|
|
||||||
w.p = newp
|
|
||||||
}
|
|
||||||
copy(w.p[w.n:w.n+len(p)], p);
|
|
||||||
w.n += len(p);
|
|
||||||
return len(p), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *byteWriter) GetBytes() []byte {
|
|
||||||
return w.p[0:w.n]
|
|
||||||
}
|
|
||||||
|
|
||||||
// Accumulates bytes written into a byte array
|
|
||||||
// but Write only takes half of what you give it.
|
|
||||||
// TODO: Could toss this -- Write() is not supposed to do that.
|
|
||||||
type halfByteWriter struct {
|
|
||||||
bw writeBuffer
|
|
||||||
}
|
|
||||||
|
|
||||||
func newHalfByteWriter() writeBuffer {
|
|
||||||
w := new(halfByteWriter);
|
|
||||||
w.bw = newByteWriter();
|
|
||||||
return w
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *halfByteWriter) Write(p []byte) (int, os.Error) {
|
|
||||||
n := (len(p)+1) / 2;
|
|
||||||
// BUG return w.bw.Write(p[0:n])
|
|
||||||
r, e := w.bw.Write(p[0:n]);
|
|
||||||
return r, e
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *halfByteWriter) GetBytes() []byte {
|
|
||||||
return w.bw.GetBytes()
|
|
||||||
}
|
|
||||||
|
|
||||||
type writeMaker struct {
|
|
||||||
name string;
|
|
||||||
fn func()writeBuffer;
|
|
||||||
}
|
|
||||||
func TestWriter(t *testing.T) {
|
func TestWriter(t *testing.T) {
|
||||||
var data [8192]byte;
|
var data [8192]byte;
|
||||||
|
|
||||||
var writers = []writeMaker {
|
|
||||||
writeMaker{ "full", newByteWriter },
|
|
||||||
writeMaker{ "half", newHalfByteWriter },
|
|
||||||
};
|
|
||||||
|
|
||||||
for i := 0; i < len(data); i++ {
|
for i := 0; i < len(data); i++ {
|
||||||
data[i] = byte(' '+ i%('~'-' '));
|
data[i] = byte(' '+ i%('~'-' '));
|
||||||
}
|
}
|
||||||
|
w := new(io.ByteBuffer);
|
||||||
for i := 0; i < len(bufsizes); i++ {
|
for i := 0; i < len(bufsizes); i++ {
|
||||||
for j := 0; j < len(bufsizes); j++ {
|
for j := 0; j < len(bufsizes); j++ {
|
||||||
for k := 0; k < len(writers); k++ {
|
nwrite := bufsizes[i];
|
||||||
nwrite := bufsizes[i];
|
bs := bufsizes[j];
|
||||||
bs := bufsizes[j];
|
|
||||||
|
|
||||||
// Write nwrite bytes using buffer size bs.
|
// Write nwrite bytes using buffer size bs.
|
||||||
// Check that the right amount makes it out
|
// Check that the right amount makes it out
|
||||||
// and that the data is correct.
|
// and that the data is correct.
|
||||||
|
|
||||||
write := writers[k].fn();
|
w.Reset();
|
||||||
buf, e := NewWriterSize(write, bs);
|
buf, e := NewWriterSize(w, bs);
|
||||||
context := fmt.Sprintf("write=%s nwrite=%d bufsize=%d", writers[k].name, nwrite, bs);
|
context := fmt.Sprintf("nwrite=%d bufsize=%d", nwrite, bs);
|
||||||
if e != nil {
|
if e != nil {
|
||||||
t.Errorf("%s: NewWriterSize %d: %v", context, bs, e);
|
t.Errorf("%s: NewWriterSize %d: %v", context, bs, e);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
n, e1 := buf.Write(data[0:nwrite]);
|
n, e1 := buf.Write(data[0:nwrite]);
|
||||||
if e1 != nil || n != nwrite {
|
if e1 != nil || n != nwrite {
|
||||||
t.Errorf("%s: buf.Write %d = %d, %v", context, nwrite, n, e1);
|
t.Errorf("%s: buf.Write %d = %d, %v", context, nwrite, n, e1);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if e = buf.Flush(); e != nil {
|
if e = buf.Flush(); e != nil {
|
||||||
t.Errorf("%s: buf.Flush = %v", context, e);
|
t.Errorf("%s: buf.Flush = %v", context, e);
|
||||||
}
|
}
|
||||||
|
|
||||||
written := write.GetBytes();
|
written := w.Data();
|
||||||
if len(written) != nwrite {
|
if len(written) != nwrite {
|
||||||
t.Errorf("%s: %d bytes written", context, len(written));
|
t.Errorf("%s: %d bytes written", context, len(written));
|
||||||
}
|
}
|
||||||
for l := 0; l < len(written); l++ {
|
for l := 0; l < len(written); l++ {
|
||||||
if written[i] != data[i] {
|
if written[i] != data[i] {
|
||||||
t.Errorf("%s: wrong bytes written");
|
t.Errorf("%s: wrong bytes written");
|
||||||
t.Errorf("want=%s", data[0:len(written)]);
|
t.Errorf("want=%s", data[0:len(written)]);
|
||||||
t.Errorf("have=%s", 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) {
|
func TestNewReaderSizeIdempotent(t *testing.T) {
|
||||||
const BufSize = 1000;
|
const BufSize = 1000;
|
||||||
b, err := NewReaderSize(newByteReader(io.StringBytes("hello world")), BufSize);
|
b, err := NewReaderSize(io.NewByteReader(io.StringBytes("hello world")), BufSize);
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error("NewReaderSize create fail", err);
|
t.Error("NewReaderSize create fail", err);
|
||||||
}
|
}
|
||||||
|
|
@ -356,7 +275,7 @@ func TestNewReaderSizeIdempotent(t *testing.T) {
|
||||||
|
|
||||||
func TestNewWriterSizeIdempotent(t *testing.T) {
|
func TestNewWriterSizeIdempotent(t *testing.T) {
|
||||||
const BufSize = 1000;
|
const BufSize = 1000;
|
||||||
b, err := NewWriterSize(newByteWriter(), BufSize);
|
b, err := NewWriterSize(new(io.ByteBuffer), BufSize);
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error("NewWriterSize create fail", err);
|
t.Error("NewWriterSize create fail", err);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -42,13 +42,17 @@ func (b *ByteBuffer) Len() int {
|
||||||
// Truncate discards all but the first n unread bytes from the buffer.
|
// Truncate discards all but the first n unread bytes from the buffer.
|
||||||
// It is an error to call b.Truncate(n) with n > b.Len().
|
// It is an error to call b.Truncate(n) with n > b.Len().
|
||||||
func (b *ByteBuffer) Truncate(n int) {
|
func (b *ByteBuffer) Truncate(n int) {
|
||||||
|
if n == 0 {
|
||||||
|
// Reuse buffer space.
|
||||||
|
b.off = 0;
|
||||||
|
}
|
||||||
b.buf = b.buf[0 : b.off + n];
|
b.buf = b.buf[0 : b.off + n];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reset resets the buffer so it has no content.
|
// Reset resets the buffer so it has no content.
|
||||||
// b.Reset() is the same as b.Truncate(0).
|
// b.Reset() is the same as b.Truncate(0).
|
||||||
func (b *ByteBuffer) Reset() {
|
func (b *ByteBuffer) Reset() {
|
||||||
b.buf = b.buf[0 : b.off];
|
b.Truncate(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write appends the contents of p to the buffer. The return
|
// Write appends the contents of p to the buffer. The return
|
||||||
|
|
|
||||||
|
|
@ -185,3 +185,29 @@ func Copy(src Reader, dst Writer) (written int64, err os.Error) {
|
||||||
}
|
}
|
||||||
return written, err
|
return written, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// A ByteReader satisfies Reads by consuming data from a slice of bytes.
|
||||||
|
// Clients can call NewByteReader to create one or wrap pointers
|
||||||
|
// to their own slices: r := ByteReader{&data}.
|
||||||
|
type ByteReader struct {
|
||||||
|
Data *[]byte
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r ByteReader) Read(p []byte) (int, os.Error) {
|
||||||
|
n := len(p);
|
||||||
|
b := r.Data;
|
||||||
|
if n > len(b) {
|
||||||
|
n = len(b);
|
||||||
|
}
|
||||||
|
for i := 0; i < n; i++ {
|
||||||
|
p[i] = b[i];
|
||||||
|
}
|
||||||
|
*b = b[n:len(b)];
|
||||||
|
return n, nil;
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewByteReader returns a new ByteReader reading from data.
|
||||||
|
func NewByteReader(data []byte) ByteReader {
|
||||||
|
return ByteReader{ &data };
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
||||||
68
src/lib/testing/iotest/Makefile
Normal file
68
src/lib/testing/iotest/Makefile
Normal file
|
|
@ -0,0 +1,68 @@
|
||||||
|
# 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.
|
||||||
|
|
||||||
|
# DO NOT EDIT. Automatically generated by gobuild.
|
||||||
|
# gobuild -m >Makefile
|
||||||
|
|
||||||
|
D=/testing/
|
||||||
|
|
||||||
|
O_arm=5
|
||||||
|
O_amd64=6
|
||||||
|
O_386=8
|
||||||
|
OS=568vq
|
||||||
|
|
||||||
|
O=$(O_$(GOARCH))
|
||||||
|
GC=$(O)g -I_obj
|
||||||
|
CC=$(O)c -FVw
|
||||||
|
AS=$(O)a
|
||||||
|
AR=6ar
|
||||||
|
|
||||||
|
default: packages
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -rf *.[$(OS)] *.a [$(OS)].out _obj
|
||||||
|
|
||||||
|
test: packages
|
||||||
|
gotest
|
||||||
|
|
||||||
|
coverage: packages
|
||||||
|
gotest
|
||||||
|
6cov -g `pwd` | grep -v '_test\.go:'
|
||||||
|
|
||||||
|
%.$O: %.go
|
||||||
|
$(GC) $*.go
|
||||||
|
|
||||||
|
%.$O: %.c
|
||||||
|
$(CC) $*.c
|
||||||
|
|
||||||
|
%.$O: %.s
|
||||||
|
$(AS) $*.s
|
||||||
|
|
||||||
|
O1=\
|
||||||
|
reader.$O\
|
||||||
|
|
||||||
|
|
||||||
|
phases: a1
|
||||||
|
_obj$D/iotest.a: phases
|
||||||
|
|
||||||
|
a1: $(O1)
|
||||||
|
$(AR) grc _obj$D/iotest.a reader.$O
|
||||||
|
rm -f $(O1)
|
||||||
|
|
||||||
|
|
||||||
|
newpkg: clean
|
||||||
|
mkdir -p _obj$D
|
||||||
|
$(AR) grc _obj$D/iotest.a
|
||||||
|
|
||||||
|
$(O1): newpkg
|
||||||
|
$(O2): a1
|
||||||
|
|
||||||
|
nuke: clean
|
||||||
|
rm -f $(GOROOT)/pkg$D/iotest.a
|
||||||
|
|
||||||
|
packages: _obj$D/iotest.a
|
||||||
|
|
||||||
|
install: packages
|
||||||
|
test -d $(GOROOT)/pkg && mkdir -p $(GOROOT)/pkg$D
|
||||||
|
cp _obj$D/iotest.a $(GOROOT)/pkg$D/iotest.a
|
||||||
44
src/lib/testing/iotest/reader.go
Normal file
44
src/lib/testing/iotest/reader.go
Normal file
|
|
@ -0,0 +1,44 @@
|
||||||
|
// 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.
|
||||||
|
|
||||||
|
// The iotest package implements Readers and Writers
|
||||||
|
// useful only for testing.
|
||||||
|
package iotest
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io";
|
||||||
|
"os";
|
||||||
|
)
|
||||||
|
|
||||||
|
type oneByteReader struct {
|
||||||
|
r io.Reader;
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *oneByteReader) Read(p []byte) (int, os.Error) {
|
||||||
|
if len(p) == 0 {
|
||||||
|
return 0, nil;
|
||||||
|
}
|
||||||
|
return r.r.Read(p[0:1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// OneByteReader returns a Reader that implements
|
||||||
|
// each non-empty Read by reading one byte from r.
|
||||||
|
func OneByteReader(r io.Reader) io.Reader {
|
||||||
|
return &oneByteReader{r};
|
||||||
|
}
|
||||||
|
|
||||||
|
type halfReader struct {
|
||||||
|
r io.Reader;
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *halfReader) Read(p []byte) (int, os.Error) {
|
||||||
|
return r.r.Read(p[0:(len(p)+1)/2]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// HalfReader returns a Reader that implements Read
|
||||||
|
// by reading half as many requested bytes from r.
|
||||||
|
func HalfReader(r io.Reader) io.Reader {
|
||||||
|
return &halfReader{r};
|
||||||
|
}
|
||||||
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue