diff options
| author | Rob Pike <r@golang.org> | 2009-06-09 09:53:44 -0700 |
|---|---|---|
| committer | Rob Pike <r@golang.org> | 2009-06-09 09:53:44 -0700 |
| commit | d90e7cbac65c5792ce312ee82fbe03a5dfc98c6f (patch) | |
| tree | 7032a11d0cac2ae4d3e90f7a189b575b5a50f848 /src/lib/io | |
| parent | bf5c0c957c3c3ea9add6cfd51b90c463cb4814b5 (diff) | |
| download | go-d90e7cbac65c5792ce312ee82fbe03a5dfc98c6f.tar.xz | |
mv src/lib to src/pkg
tests: all.bash passes, gobuild still works, godoc still works.
R=rsc
OCL=30096
CL=30102
Diffstat (limited to 'src/lib/io')
| -rw-r--r-- | src/lib/io/Makefile | 70 | ||||
| -rw-r--r-- | src/lib/io/bytebuffer.go | 109 | ||||
| -rw-r--r-- | src/lib/io/bytebuffer_test.go | 158 | ||||
| -rw-r--r-- | src/lib/io/io.go | 223 | ||||
| -rw-r--r-- | src/lib/io/pipe.go | 226 | ||||
| -rw-r--r-- | src/lib/io/pipe_test.go | 225 | ||||
| -rw-r--r-- | src/lib/io/utils.go | 29 | ||||
| -rw-r--r-- | src/lib/io/utils_test.go | 37 |
8 files changed, 0 insertions, 1077 deletions
diff --git a/src/lib/io/Makefile b/src/lib/io/Makefile deleted file mode 100644 index 219ea776be..0000000000 --- a/src/lib/io/Makefile +++ /dev/null @@ -1,70 +0,0 @@ -# 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= - -include $(GOROOT)/src/Make.$(GOARCH) -AR=gopack - -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) -I_obj $*.go - -%.$O: %.c - $(CC) $*.c - -%.$O: %.s - $(AS) $*.s - -O1=\ - bytebuffer.$O\ - io.$O\ - -O2=\ - pipe.$O\ - utils.$O\ - - -phases: a1 a2 -_obj$D/io.a: phases - -a1: $(O1) - $(AR) grc _obj$D/io.a bytebuffer.$O io.$O - rm -f $(O1) - -a2: $(O2) - $(AR) grc _obj$D/io.a pipe.$O utils.$O - rm -f $(O2) - - -newpkg: clean - mkdir -p _obj$D - $(AR) grc _obj$D/io.a - -$(O1): newpkg -$(O2): a1 -$(O3): a2 - -nuke: clean - rm -f $(GOROOT)/pkg/$(GOOS)_$(GOARCH)$D/io.a - -packages: _obj$D/io.a - -install: packages - test -d $(GOROOT)/pkg && mkdir -p $(GOROOT)/pkg/$(GOOS)_$(GOARCH)$D - cp _obj$D/io.a $(GOROOT)/pkg/$(GOOS)_$(GOARCH)$D/io.a diff --git a/src/lib/io/bytebuffer.go b/src/lib/io/bytebuffer.go deleted file mode 100644 index 921ddb17ae..0000000000 --- a/src/lib/io/bytebuffer.go +++ /dev/null @@ -1,109 +0,0 @@ -// 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 io - -// Simple byte buffer for marshaling data. - -import ( - "io"; - "os"; -) - -func bytecopy(dst []byte, doff int, src []byte, soff int, count int) { - for ; count > 0; count-- { - dst[doff] = src[soff]; - doff++; - soff++; - } -} - -// A ByteBuffer is a simple implementation of the io.Read and io.Write interfaces -// connected to a buffer of bytes. -// The zero value for ByteBuffer is an empty buffer ready to use. -type ByteBuffer struct { - buf []byte; // contents are the bytes buf[off : len(buf)] - off int; // read at &buf[off], write at &buf[len(buf)] -} - -// Data returns the contents of the unread portion of the buffer; -// len(b.Data()) == b.Len(). -func (b *ByteBuffer) Data() []byte { - return b.buf[b.off : len(b.buf)] -} - -// Len returns the number of bytes of the unread portion of the buffer; -// b.Len() == len(b.Data()). -func (b *ByteBuffer) Len() int { - return len(b.buf) - b.off -} - -// 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(). -func (b *ByteBuffer) Truncate(n int) { - if n == 0 { - // Reuse buffer space. - b.off = 0; - } - b.buf = b.buf[0 : b.off + n]; -} - -// Reset resets the buffer so it has no content. -// b.Reset() is the same as b.Truncate(0). -func (b *ByteBuffer) Reset() { - b.Truncate(0); -} - -// Write appends the contents of p to the buffer. The return -// value n is the length of p; err is always nil. -func (b *ByteBuffer) Write(p []byte) (n int, err os.Error) { - m := b.Len(); - n = len(p); - - if len(b.buf) + n > cap(b.buf) { - // not enough space at end - buf := b.buf; - if m + n > cap(b.buf) { - // not enough space anywhere - buf = make([]byte, 2*cap(b.buf) + n) - } - bytecopy(buf, 0, b.buf, b.off, m); - b.buf = buf; - b.off = 0 - } - - b.buf = b.buf[0 : b.off + m + n]; - bytecopy(b.buf, b.off + m, p, 0, n); - return n, nil -} - -// WriteByte appends the byte c to the buffer. -// The returned error is always nil, but is included -// to match bufio.Writer's WriteByte. -func (b *ByteBuffer) WriteByte(c byte) os.Error { - b.Write([]byte{c}); - return nil; -} - -// Read reads the next len(p) bytes from the buffer or until the buffer -// is drained. The return value n is the number of bytes read; err is always nil. -func (b *ByteBuffer) Read(p []byte) (n int, err os.Error) { - m := b.Len(); - n = len(p); - - if n > m { - // more bytes requested than available - n = m - } - - bytecopy(p, 0, b.buf, b.off, n); - b.off += n; - return n, nil -} - -// NewByteBufferFromArray creates and initializes a new ByteBuffer -// with buf as its initial contents. -func NewByteBufferFromArray(buf []byte) *ByteBuffer { - return &ByteBuffer{buf, 0}; -} diff --git a/src/lib/io/bytebuffer_test.go b/src/lib/io/bytebuffer_test.go deleted file mode 100644 index 5a54322237..0000000000 --- a/src/lib/io/bytebuffer_test.go +++ /dev/null @@ -1,158 +0,0 @@ -// 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 io - -import ( - "io"; - "rand"; - "testing"; -) - - -const N = 10000; // make this bigger for a larger (and slower) test -var data []byte; // test data for write tests - - -func init() { - data = make([]byte, N); - for i := 0; i < len(data); i++ { - data[i] = 'a' + byte(i % 26) - } -} - - -// Verify that contents of buf match the string s. -func check(t *testing.T, testname string, buf *ByteBuffer, s string) { - if buf.Len() != len(buf.Data()) { - t.Errorf("%s: buf.Len() == %d, len(buf.Data()) == %d\n", testname, buf.Len(), len(buf.Data())) - } - - if buf.Len() != len(s) { - t.Errorf("%s: buf.Len() == %d, len(s) == %d\n", testname, buf.Len(), len(s)) - } - - if string(buf.Data()) != s { - t.Errorf("%s: string(buf.Data()) == %q, s == %q\n", testname, string(buf.Data()), s) - } -} - - -// Fill buf through n writes of fub. -// The initial contents of buf corresponds to the string s; -// the result is the final contents of buf returned as a string. -func fill(t *testing.T, testname string, buf *ByteBuffer, s string, n int, fub []byte) string { - check(t, testname + " (fill 1)", buf, s); - for ; n > 0; n-- { - m, err := buf.Write(fub); - if m != len(fub) { - t.Errorf(testname + " (fill 2): m == %d, expected %d\n", m, len(fub)); - } - if err != nil { - t.Errorf(testname + " (fill 3): err should always be nil, found err == %s\n", err); - } - s += string(fub); - check(t, testname + " (fill 4)", buf, s); - } - return s; -} - - -// Empty buf through repeated reads into fub. -// The initial contents of buf corresponds to the string s. -func empty(t *testing.T, testname string, buf *ByteBuffer, s string, fub []byte) { - check(t, testname + " (empty 1)", buf, s); - - for { - n, err := buf.Read(fub); - if n == 0 { - break; - } - if err != nil { - t.Errorf(testname + " (empty 2): err should always be nil, found err == %s\n", err); - } - s = s[n : len(s)]; - check(t, testname + " (empty 3)", buf, s); - } - - check(t, testname + " (empty 4)", buf, ""); -} - - -func TestBasicOperations(t *testing.T) { - var buf ByteBuffer; - - for i := 0; i < 5; i++ { - check(t, "TestBasicOperations (1)", &buf, ""); - - buf.Reset(); - check(t, "TestBasicOperations (2)", &buf, ""); - - buf.Truncate(0); - check(t, "TestBasicOperations (3)", &buf, ""); - - n, err := buf.Write(data[0 : 1]); - if n != 1 { - t.Errorf("wrote 1 byte, but n == %d\n", n); - } - if err != nil { - t.Errorf("err should always be nil, but err == %s\n", err); - } - check(t, "TestBasicOperations (4)", &buf, "a"); - - buf.WriteByte(data[1]); - check(t, "TestBasicOperations (5)", &buf, "ab"); - - n, err = buf.Write(data[2 : 26]); - if n != 24 { - t.Errorf("wrote 25 bytes, but n == %d\n", n); - } - check(t, "TestBasicOperations (6)", &buf, string(data[0 : 26])); - - buf.Truncate(26); - check(t, "TestBasicOperations (7)", &buf, string(data[0 : 26])); - - buf.Truncate(20); - check(t, "TestBasicOperations (8)", &buf, string(data[0 : 20])); - - empty(t, "TestBasicOperations (9)", &buf, string(data[0 : 20]), make([]byte, 5)); - empty(t, "TestBasicOperations (10)", &buf, "", make([]byte, 100)); - } -} - - -func TestLargeWrites(t *testing.T) { - var buf ByteBuffer; - for i := 3; i < 30; i += 3 { - s := fill(t, "TestLargeWrites (1)", &buf, "", 5, data); - empty(t, "TestLargeWrites (2)", &buf, s, make([]byte, len(data)/i)); - } - check(t, "TestLargeWrites (3)", &buf, ""); -} - - -func TestLargeReads(t *testing.T) { - var buf ByteBuffer; - for i := 3; i < 30; i += 3 { - s := fill(t, "TestLargeReads (1)", &buf, "", 5, data[0 : len(data)/i]); - empty(t, "TestLargeReads (2)", &buf, s, make([]byte, len(data))); - } - check(t, "TestLargeReads (3)", &buf, ""); -} - - -func TestMixedReadsAndWrites(t *testing.T) { - var buf ByteBuffer; - s := ""; - for i := 0; i < 50; i++ { - wlen := rand.Intn(len(data)); - s = fill(t, "TestMixedReadsAndWrites (1)", &buf, s, 1, data[0 : wlen]); - - rlen := rand.Intn(len(data)); - fub := make([]byte, rlen); - n, err := buf.Read(fub); - s = s[n : len(s)]; - } - empty(t, "TestMixedReadsAndWrites (2)", &buf, s, make([]byte, buf.Len())); -} diff --git a/src/lib/io/io.go b/src/lib/io/io.go deleted file mode 100644 index ba0449ac17..0000000000 --- a/src/lib/io/io.go +++ /dev/null @@ -1,223 +0,0 @@ -// 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. - -// This package provides basic interfaces to I/O primitives. -// Its primary job is to wrap existing implementations of such primitives, -// such as those in package os, into shared public interfaces that -// abstract the functionality. -// It also provides buffering primitives and some other basic operations. -package io - -import ( - "bytes"; - "os"; -) - -// Error represents an unexpected I/O behavior. -type Error struct { - os.ErrorString -} - -// ErrEOF means that data was expected, but a read got EOF instead. -var ErrEOF os.Error = &Error{"EOF"} - -// ErrShortWrite means that a write accepted fewer bytes than requested -// but failed to return an explicit error. -var ErrShortWrite os.Error = &Error{"short write"} - - -// Reader is the interface that wraps the basic Read method. -// An implementation of Read is allowed to use all of p for -// scratch space during the call, even if it eventually returns -// n < len(p). -type Reader interface { - Read(p []byte) (n int, err os.Error); -} - -// Writer is the interface that wraps the basic Write method. -type Writer interface { - Write(p []byte) (n int, err os.Error); -} - -// Closer is the interface that wraps the basic Close method. -type Closer interface { - Close() os.Error; -} - -// ReadWrite is the interface that groups the basic Read and Write methods. -type ReadWriter interface { - Reader; - Writer; -} - -// ReadCloser is the interface that groups the basic Read and Close methods. -type ReadCloser interface { - Reader; - Closer; -} - -// WriteCloser is the interface that groups the basic Write and Close methods. -type WriteCloser interface { - Writer; - Closer; -} - -// ReadWriteCloser is the interface that groups the basic Read, Write and Close methods. -type ReadWriteCloser interface { - Reader; - Writer; - Closer; -} - -// Convert a string to an array of bytes for easy marshaling. -func StringBytes(s string) []byte { - b := make([]byte, len(s)); - for i := 0; i < len(s); i++ { - b[i] = s[i]; - } - return b; -} - -// WriteString writes the contents of the string s to w, which accepts an array of bytes. -func WriteString(w Writer, s string) (n int, err os.Error) { - return w.Write(StringBytes(s)) -} - -// ReadAtLeast reads r into buf until at least min bytes have been read, -// or until EOF or error. -func ReadAtLeast(r Reader, buf []byte, min int) (n int, err os.Error) { - n = 0; - for n < min { - nn, e := r.Read(buf[n:len(buf)]); - if nn > 0 { - n += nn - } - if e != nil { - return n, e - } - if nn <= 0 { - return n, ErrEOF // no error but insufficient data - } - } - return n, nil -} - -// FullRead reads r until the buffer buf is full, or until EOF or error. -func FullRead(r Reader, buf []byte) (n int, err os.Error) { - // TODO(rsc): 6g bug prevents obvious return - n, err = ReadAtLeast(r, buf, len(buf)); - return; -} - -// Convert something that implements Read into something -// whose Reads are always FullReads -type fullRead struct { - r Reader; -} - -func (fr *fullRead) Read(p []byte) (n int, err os.Error) { - n, err = FullRead(fr.r, p); - return n, err -} - -// MakeFullReader takes r, an implementation of Read, and returns an object -// that still implements Read but always calls FullRead underneath. -func MakeFullReader(r Reader) Reader { - if fr, ok := r.(*fullRead); ok { - // already a fullRead - return r - } - return &fullRead{r} -} - -// Copy n copies n bytes (or until EOF is reached) from src to dst. -// It returns the number of bytes copied and the error, if any. -func Copyn(src Reader, dst Writer, n int64) (written int64, err os.Error) { - buf := make([]byte, 32*1024); - for written < n { - l := len(buf); - if d := n - written; d < int64(l) { - l = int(d); - } - nr, er := src.Read(buf[0 : l]); - if nr > 0 { - nw, ew := dst.Write(buf[0 : nr]); - if nw > 0 { - written += int64(nw); - } - if ew != nil { - err = ew; - break; - } - if nr != nw { - err = os.EIO; - break; - } - } - if er != nil { - err = er; - break; - } - if nr == 0 { - err = ErrEOF; - break; - } - } - return written, err -} - -// Copy copies from src to dst until EOF is reached. -// It returns the number of bytes copied and the error, if any. -func Copy(src Reader, dst Writer) (written int64, err os.Error) { - buf := make([]byte, 32*1024); - for { - nr, er := src.Read(buf); - if nr > 0 { - nw, ew := dst.Write(buf[0:nr]); - if nw > 0 { - written += int64(nw); - } - if ew != nil { - err = ew; - break; - } - if nr != nw { - err = os.EIO; - break; - } - } - if er != nil { - err = er; - break; - } - if nr == 0 { - break; - } - } - 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); - } - bytes.Copy(p, b[0:n]); - *b = b[n:len(b)]; - return n, nil; -} - -// NewByteReader returns a new ByteReader reading from data. -func NewByteReader(data []byte) ByteReader { - return ByteReader{ &data }; -} - diff --git a/src/lib/io/pipe.go b/src/lib/io/pipe.go deleted file mode 100644 index 1a443ddcec..0000000000 --- a/src/lib/io/pipe.go +++ /dev/null @@ -1,226 +0,0 @@ -// 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. - -// Pipe adapter to connect code expecting an io.Read -// with code expecting an io.Write. - -package io - -import ( - "io"; - "os"; - "sync"; -) - -type pipeReturn struct { - n int; - err os.Error; -} - -// Shared pipe structure. -type pipe struct { - rclosed bool; // Read end closed? - rerr os.Error; // Error supplied to CloseReader - wclosed bool; // Write end closed? - werr os.Error; // Error supplied to CloseWriter - wpend []byte; // Written data waiting to be read. - wtot int; // Bytes consumed so far in current write. - cr chan []byte; // Write sends data here... - cw chan pipeReturn; // ... and reads the n, err back from here. -} - -func (p *pipe) Read(data []byte) (n int, err os.Error) { - if p == nil || p.rclosed { - return 0, os.EINVAL; - } - - // Wait for next write block if necessary. - if p.wpend == nil { - if !p.wclosed { - p.wpend = <-p.cr; - } - if p.wpend == nil { - return 0, p.werr; - } - p.wtot = 0; - } - - // Read from current write block. - n = len(data); - if n > len(p.wpend) { - n = len(p.wpend); - } - for i := 0; i < n; i++ { - data[i] = p.wpend[i]; - } - p.wtot += n; - p.wpend = p.wpend[n:len(p.wpend)]; - - // If write block is done, finish the write. - if len(p.wpend) == 0 { - p.wpend = nil; - p.cw <- pipeReturn{p.wtot, nil}; - p.wtot = 0; - } - - return n, nil; -} - -func (p *pipe) Write(data []byte) (n int, err os.Error) { - if p == nil || p.wclosed { - return 0, os.EINVAL; - } - if p.rclosed { - return 0, p.rerr; - } - - // Send data to reader. - p.cr <- data; - - // Wait for reader to finish copying it. - res := <-p.cw; - return res.n, res.err; -} - -func (p *pipe) CloseReader(rerr os.Error) os.Error { - if p == nil || p.rclosed { - return os.EINVAL; - } - - // Stop any future writes. - p.rclosed = true; - if rerr == nil { - rerr = os.EPIPE; - } - p.rerr = rerr; - - // Stop the current write. - if !p.wclosed { - p.cw <- pipeReturn{p.wtot, rerr}; - } - - return nil; -} - -func (p *pipe) CloseWriter(werr os.Error) os.Error { - if p == nil || p.wclosed { - return os.EINVAL; - } - - // Stop any future reads. - p.wclosed = true; - p.werr = werr; - - // Stop the current read. - if !p.rclosed { - p.cr <- nil; - } - - return nil; -} - -// Read/write halves of the pipe. -// They are separate structures for two reasons: -// 1. If one end becomes garbage without being Closed, -// its finisher can Close so that the other end -// does not hang indefinitely. -// 2. Clients cannot use interface conversions on the -// read end to find the Write method, and vice versa. - -// A PipeReader is the read half of a pipe. -type PipeReader struct { - lock sync.Mutex; - p *pipe; -} - -// Read implements the standard Read interface: -// it reads data from the pipe, blocking until a writer -// arrives or the write end is closed. -// If the write end is closed with an error, that error is -// returned as err; otherwise err is nil. -func (r *PipeReader) Read(data []byte) (n int, err os.Error) { - r.lock.Lock(); - defer r.lock.Unlock(); - - return r.p.Read(data); -} - -// Close closes the reader; subsequent writes to the -// write half of the pipe will return the error os.EPIPE. -func (r *PipeReader) Close() os.Error { - r.lock.Lock(); - defer r.lock.Unlock(); - - return r.p.CloseReader(nil); -} - -// CloseWithError closes the reader; subsequent writes -// to the write half of the pipe will return the error rerr. -func (r *PipeReader) CloseWithError(rerr os.Error) os.Error { - r.lock.Lock(); - defer r.lock.Unlock(); - - return r.p.CloseReader(rerr); -} - -func (r *PipeReader) finish() { - r.Close(); -} - -// Write half of pipe. -type PipeWriter struct { - lock sync.Mutex; - p *pipe; -} - -// Write implements the standard Write interface: -// it writes data to the pipe, blocking until readers -// have consumed all the data or the read end is closed. -// If the read end is closed with an error, that err is -// returned as err; otherwise err is os.EPIPE. -func (w *PipeWriter) Write(data []byte) (n int, err os.Error) { - w.lock.Lock(); - defer w.lock.Unlock(); - - return w.p.Write(data); -} - -// Close closes the writer; subsequent reads from the -// read half of the pipe will return no bytes and a nil error. -func (w *PipeWriter) Close() os.Error { - w.lock.Lock(); - defer w.lock.Unlock(); - - return w.p.CloseWriter(nil); -} - -// CloseWithError closes the writer; subsequent reads from the -// read half of the pipe will return no bytes and the error werr. -func (w *PipeWriter) CloseWithError(werr os.Error) os.Error { - w.lock.Lock(); - defer w.lock.Unlock(); - - return w.p.CloseWriter(werr); -} - -func (w *PipeWriter) finish() { - w.Close(); -} - -// Pipe creates a synchronous in-memory pipe. -// It can be used to connect code expecting an io.Reader -// with code expecting an io.Writer. -// Reads on one end are matched with writes on the other, -// copying data directly between the two; there is no internal buffering. -func Pipe() (*PipeReader, *PipeWriter) { - p := new(pipe); - p.cr = make(chan []byte, 1); - p.cw = make(chan pipeReturn, 1); - r := new(PipeReader); - r.p = p; - w := new(PipeWriter); - w.p = p; - return r, w; -} - diff --git a/src/lib/io/pipe_test.go b/src/lib/io/pipe_test.go deleted file mode 100644 index 277f445250..0000000000 --- a/src/lib/io/pipe_test.go +++ /dev/null @@ -1,225 +0,0 @@ -// 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 io - -import ( - "fmt"; - "io"; - "os"; - "testing"; - "time"; -) - -func checkWrite(t *testing.T, w Writer, data []byte, c chan int) { - n, err := w.Write(data); - if err != nil { - t.Errorf("write: %v", err); - } - if n != len(data) { - t.Errorf("short write: %d != %d", n, len(data)); - } - c <- 0; -} - -// Test a single read/write pair. -func TestPipe1(t *testing.T) { - c := make(chan int); - r, w := Pipe(); - var buf = make([]byte, 64); - go checkWrite(t, w, StringBytes("hello, world"), c); - n, err := r.Read(buf); - if err != nil { - t.Errorf("read: %v", err); - } - else if n != 12 || string(buf[0:12]) != "hello, world" { - t.Errorf("bad read: got %q", buf[0:n]); - } - <-c; - r.Close(); - w.Close(); -} - -func reader(t *testing.T, r Reader, c chan int) { - var buf = make([]byte, 64); - for { - n, err := r.Read(buf); - if err != nil { - t.Errorf("read: %v", err); - } - c <- n; - if n == 0 { - break; - } - } -} - -// Test a sequence of read/write pairs. -func TestPipe2(t *testing.T) { - c := make(chan int); - r, w := Pipe(); - go reader(t, r, c); - var buf = make([]byte, 64); - for i := 0; i < 5; i++ { - p := buf[0:5+i*10]; - n, err := w.Write(p); - if n != len(p) { - t.Errorf("wrote %d, got %d", len(p), n); - } - if err != nil { - t.Errorf("write: %v", err); - } - nn := <-c; - if nn != n { - t.Errorf("wrote %d, read got %d", n, nn); - } - } - w.Close(); - nn := <-c; - if nn != 0 { - t.Errorf("final read got %d", nn); - } -} - -// Test a large write that requires multiple reads to satisfy. -func writer(w WriteCloser, buf []byte, c chan pipeReturn) { - n, err := w.Write(buf); - w.Close(); - c <- pipeReturn{n, err}; -} - -func TestPipe3(t *testing.T) { - c := make(chan pipeReturn); - r, w := Pipe(); - var wdat = make([]byte, 128); - for i := 0; i < len(wdat); i++ { - wdat[i] = byte(i); - } - go writer(w, wdat, c); - var rdat = make([]byte, 1024); - tot := 0; - for n := 1; n <= 256; n *= 2 { - nn, err := r.Read(rdat[tot:tot+n]); - if err != nil { - t.Fatalf("read: %v", err); - } - - // only final two reads should be short - 1 byte, then 0 - expect := n; - if n == 128 { - expect = 1; - } else if n == 256 { - expect = 0; - } - if nn != expect { - t.Fatalf("read %d, expected %d, got %d", n, expect, nn); - } - tot += nn; - } - pr := <-c; - if pr.n != 128 || pr.err != nil { - t.Fatalf("write 128: %d, %v", pr.n, pr.err); - } - if tot != 128 { - t.Fatalf("total read %d != 128", tot); - } - for i := 0; i < 128; i++ { - if rdat[i] != byte(i) { - t.Fatalf("rdat[%d] = %d", i, rdat[i]); - } - } -} - -// Test read after/before writer close. - -type closer interface { - CloseWithError(os.Error) os.Error; - Close() os.Error; -} - -type pipeTest struct { - async bool; - err os.Error; - closeWithError bool; -} - -func (p pipeTest) String() string { - return fmt.Sprintf("async=%v err=%v closeWithError=%v", p.async, p.err, p.closeWithError); -} - -var pipeTests = []pipeTest { - pipeTest{ true, nil, false }, - pipeTest{ true, nil, true }, - pipeTest{ true, io.ErrShortWrite, true }, - pipeTest{ false, nil, false }, - pipeTest{ false, nil, true }, - pipeTest{ false, io.ErrShortWrite, true }, -} - -func delayClose(t *testing.T, cl closer, ch chan int, tt pipeTest) { - time.Sleep(1e6); // 1 ms - var err os.Error; - if tt.closeWithError { - err = cl.CloseWithError(tt.err); - } else { - err = cl.Close(); - } - if err != nil { - t.Errorf("delayClose: %v", err); - } - ch <- 0; -} - -func TestPipeReadClose(t *testing.T) { - for _, tt := range pipeTests { - c := make(chan int, 1); - r, w := Pipe(); - if tt.async { - go delayClose(t, w, c, tt); - } else { - delayClose(t, w, c, tt); - } - var buf = make([]byte, 64); - n, err := r.Read(buf); - <-c; - if err != tt.err { - t.Errorf("read from closed pipe: %v want %v", err, tt.err); - } - if n != 0 { - t.Errorf("read on closed pipe returned %d", n); - } - if err = r.Close(); err != nil { - t.Errorf("r.Close: %v", err); - } - } -} - -// Test write after/before reader close. - -func TestPipeWriteClose(t *testing.T) { - for _, tt := range pipeTests { - c := make(chan int, 1); - r, w := Pipe(); - if tt.async { - go delayClose(t, r, c, tt); - } else { - delayClose(t, r, c, tt); - } - n, err := WriteString(w, "hello, world"); - <-c; - expect := tt.err; - if expect == nil { - expect = os.EPIPE; - } - if err != expect { - t.Errorf("write on closed pipe: %v want %v", err, expect); - } - if n != 0 { - t.Errorf("write on closed pipe returned %d", n); - } - if err = w.Close(); err != nil { - t.Errorf("w.Close: %v", err); - } - } -} diff --git a/src/lib/io/utils.go b/src/lib/io/utils.go deleted file mode 100644 index a4cbb2d9aa..0000000000 --- a/src/lib/io/utils.go +++ /dev/null @@ -1,29 +0,0 @@ -// 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. - -// Utility functions. - -package io - -import ( - "io"; - "os"; -) - -// ReadAll reads from r until an error or EOF and returns the data it read. -func ReadAll(r Reader) ([]byte, os.Error) { - var buf ByteBuffer; - n, err := io.Copy(r, &buf); - return buf.Data(), err; -} - -// ReadFile reads the file named by filename and returns the contents. -func ReadFile(filename string) ([]byte, os.Error) { - f, err := os.Open(filename, os.O_RDONLY, 0); - if err != nil { - return nil, err; - } - defer f.Close(); - return ReadAll(f); -} diff --git a/src/lib/io/utils_test.go b/src/lib/io/utils_test.go deleted file mode 100644 index f35dad60c9..0000000000 --- a/src/lib/io/utils_test.go +++ /dev/null @@ -1,37 +0,0 @@ -// 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 io - -import ( - "io"; - "os"; - "testing"; -) - -func checkSize(t *testing.T, path string, size uint64) { - dir, err := os.Stat(path); - if err != nil { - t.Fatalf("Stat %q (looking for size %d): %s", path, size, err); - } - if dir.Size != size { - t.Errorf("Stat %q: size %d want %d", path, dir.Size, size); - } -} - -func TestReadFile(t *testing.T) { - filename := "rumpelstilzchen"; - contents, err := ReadFile(filename); - if err == nil { - t.Fatalf("ReadFile %s: error expected, none found", filename); - } - - filename = "utils_test.go"; - contents, err = ReadFile(filename); - if err != nil { - t.Fatalf("ReadFile %s: %v", filename, err); - } - - checkSize(t, filename, uint64(len(contents))); -} |
