diff options
author | Tianon Gravi <admwiggin@gmail.com> | 2015-01-15 11:54:00 -0700 |
---|---|---|
committer | Tianon Gravi <admwiggin@gmail.com> | 2015-01-15 11:54:00 -0700 |
commit | f154da9e12608589e8d5f0508f908a0c3e88a1bb (patch) | |
tree | f8255d51e10c6f1e0ed69702200b966c9556a431 /src/pkg/io | |
parent | 8d8329ed5dfb9622c82a9fbec6fd99a580f9c9f6 (diff) | |
download | golang-upstream/1.4.tar.gz |
Imported Upstream version 1.4upstream/1.4
Diffstat (limited to 'src/pkg/io')
-rw-r--r-- | src/pkg/io/io.go | 493 | ||||
-rw-r--r-- | src/pkg/io/io_test.go | 341 | ||||
-rw-r--r-- | src/pkg/io/ioutil/ioutil.go | 165 | ||||
-rw-r--r-- | src/pkg/io/ioutil/ioutil_test.go | 95 | ||||
-rw-r--r-- | src/pkg/io/ioutil/tempfile.go | 95 | ||||
-rw-r--r-- | src/pkg/io/ioutil/tempfile_test.go | 53 | ||||
-rw-r--r-- | src/pkg/io/multi.go | 61 | ||||
-rw-r--r-- | src/pkg/io/multi_test.go | 115 | ||||
-rw-r--r-- | src/pkg/io/pipe.go | 193 | ||||
-rw-r--r-- | src/pkg/io/pipe_test.go | 302 |
10 files changed, 0 insertions, 1913 deletions
diff --git a/src/pkg/io/io.go b/src/pkg/io/io.go deleted file mode 100644 index 022fdb676..000000000 --- a/src/pkg/io/io.go +++ /dev/null @@ -1,493 +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 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, plus some other related primitives. -// -// Because these interfaces and primitives wrap lower-level operations with -// various implementations, unless otherwise informed clients should not -// assume they are safe for parallel execution. -package io - -import ( - "errors" -) - -// ErrShortWrite means that a write accepted fewer bytes than requested -// but failed to return an explicit error. -var ErrShortWrite = errors.New("short write") - -// ErrShortBuffer means that a read required a longer buffer than was provided. -var ErrShortBuffer = errors.New("short buffer") - -// EOF is the error returned by Read when no more input is available. -// Functions should return EOF only to signal a graceful end of input. -// If the EOF occurs unexpectedly in a structured data stream, -// the appropriate error is either ErrUnexpectedEOF or some other error -// giving more detail. -var EOF = errors.New("EOF") - -// ErrUnexpectedEOF means that EOF was encountered in the -// middle of reading a fixed-size block or data structure. -var ErrUnexpectedEOF = errors.New("unexpected EOF") - -// ErrNoProgress is returned by some clients of an io.Reader when -// many calls to Read have failed to return any data or error, -// usually the sign of a broken io.Reader implementation. -var ErrNoProgress = errors.New("multiple Read calls return no data or error") - -// Reader is the interface that wraps the basic Read method. -// -// Read reads up to len(p) bytes into p. It returns the number of bytes -// read (0 <= n <= len(p)) and any error encountered. Even if Read -// returns n < len(p), it may use all of p as scratch space during the call. -// If some data is available but not len(p) bytes, Read conventionally -// returns what is available instead of waiting for more. -// -// When Read encounters an error or end-of-file condition after -// successfully reading n > 0 bytes, it returns the number of -// bytes read. It may return the (non-nil) error from the same call -// or return the error (and n == 0) from a subsequent call. -// An instance of this general case is that a Reader returning -// a non-zero number of bytes at the end of the input stream may -// return either err == EOF or err == nil. The next Read should -// return 0, EOF regardless. -// -// Callers should always process the n > 0 bytes returned before -// considering the error err. Doing so correctly handles I/O errors -// that happen after reading some bytes and also both of the -// allowed EOF behaviors. -// -// Implementations of Read are discouraged from returning a -// zero byte count with a nil error, and callers should treat -// that situation as a no-op. -type Reader interface { - Read(p []byte) (n int, err error) -} - -// Writer is the interface that wraps the basic Write method. -// -// Write writes len(p) bytes from p to the underlying data stream. -// It returns the number of bytes written from p (0 <= n <= len(p)) -// and any error encountered that caused the write to stop early. -// Write must return a non-nil error if it returns n < len(p). -// Write must not modify the slice data, even temporarily. -type Writer interface { - Write(p []byte) (n int, err error) -} - -// Closer is the interface that wraps the basic Close method. -// -// The behavior of Close after the first call is undefined. -// Specific implementations may document their own behavior. -type Closer interface { - Close() error -} - -// Seeker is the interface that wraps the basic Seek method. -// -// Seek sets the offset for the next Read or Write to offset, -// interpreted according to whence: 0 means relative to the origin of -// the file, 1 means relative to the current offset, and 2 means -// relative to the end. Seek returns the new offset and an error, if -// any. -// -// Seeking to a negative offset is an error. Seeking to any positive -// offset is legal, but the behavior of subsequent I/O operations on -// the underlying object is implementation-dependent. -type Seeker interface { - Seek(offset int64, whence int) (int64, error) -} - -// ReadWriter 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 -} - -// ReadSeeker is the interface that groups the basic Read and Seek methods. -type ReadSeeker interface { - Reader - Seeker -} - -// WriteSeeker is the interface that groups the basic Write and Seek methods. -type WriteSeeker interface { - Writer - Seeker -} - -// ReadWriteSeeker is the interface that groups the basic Read, Write and Seek methods. -type ReadWriteSeeker interface { - Reader - Writer - Seeker -} - -// ReaderFrom is the interface that wraps the ReadFrom method. -// -// ReadFrom reads data from r until EOF or error. -// The return value n is the number of bytes read. -// Any error except io.EOF encountered during the read is also returned. -// -// The Copy function uses ReaderFrom if available. -type ReaderFrom interface { - ReadFrom(r Reader) (n int64, err error) -} - -// WriterTo is the interface that wraps the WriteTo method. -// -// WriteTo writes data to w until there's no more data to write or -// when an error occurs. The return value n is the number of bytes -// written. Any error encountered during the write is also returned. -// -// The Copy function uses WriterTo if available. -type WriterTo interface { - WriteTo(w Writer) (n int64, err error) -} - -// ReaderAt is the interface that wraps the basic ReadAt method. -// -// ReadAt reads len(p) bytes into p starting at offset off in the -// underlying input source. It returns the number of bytes -// read (0 <= n <= len(p)) and any error encountered. -// -// When ReadAt returns n < len(p), it returns a non-nil error -// explaining why more bytes were not returned. In this respect, -// ReadAt is stricter than Read. -// -// Even if ReadAt returns n < len(p), it may use all of p as scratch -// space during the call. If some data is available but not len(p) bytes, -// ReadAt blocks until either all the data is available or an error occurs. -// In this respect ReadAt is different from Read. -// -// If the n = len(p) bytes returned by ReadAt are at the end of the -// input source, ReadAt may return either err == EOF or err == nil. -// -// If ReadAt is reading from an input source with a seek offset, -// ReadAt should not affect nor be affected by the underlying -// seek offset. -// -// Clients of ReadAt can execute parallel ReadAt calls on the -// same input source. -type ReaderAt interface { - ReadAt(p []byte, off int64) (n int, err error) -} - -// WriterAt is the interface that wraps the basic WriteAt method. -// -// WriteAt writes len(p) bytes from p to the underlying data stream -// at offset off. It returns the number of bytes written from p (0 <= n <= len(p)) -// and any error encountered that caused the write to stop early. -// WriteAt must return a non-nil error if it returns n < len(p). -// -// If WriteAt is writing to a destination with a seek offset, -// WriteAt should not affect nor be affected by the underlying -// seek offset. -// -// Clients of WriteAt can execute parallel WriteAt calls on the same -// destination if the ranges do not overlap. -type WriterAt interface { - WriteAt(p []byte, off int64) (n int, err error) -} - -// ByteReader is the interface that wraps the ReadByte method. -// -// ReadByte reads and returns the next byte from the input. -// If no byte is available, err will be set. -type ByteReader interface { - ReadByte() (c byte, err error) -} - -// ByteScanner is the interface that adds the UnreadByte method to the -// basic ReadByte method. -// -// UnreadByte causes the next call to ReadByte to return the same byte -// as the previous call to ReadByte. -// It may be an error to call UnreadByte twice without an intervening -// call to ReadByte. -type ByteScanner interface { - ByteReader - UnreadByte() error -} - -// ByteWriter is the interface that wraps the WriteByte method. -type ByteWriter interface { - WriteByte(c byte) error -} - -// RuneReader is the interface that wraps the ReadRune method. -// -// ReadRune reads a single UTF-8 encoded Unicode character -// and returns the rune and its size in bytes. If no character is -// available, err will be set. -type RuneReader interface { - ReadRune() (r rune, size int, err error) -} - -// RuneScanner is the interface that adds the UnreadRune method to the -// basic ReadRune method. -// -// UnreadRune causes the next call to ReadRune to return the same rune -// as the previous call to ReadRune. -// It may be an error to call UnreadRune twice without an intervening -// call to ReadRune. -type RuneScanner interface { - RuneReader - UnreadRune() error -} - -// stringWriter is the interface that wraps the WriteString method. -type stringWriter interface { - WriteString(s string) (n int, err error) -} - -// WriteString writes the contents of the string s to w, which accepts an array of bytes. -// If w already implements a WriteString method, it is invoked directly. -func WriteString(w Writer, s string) (n int, err error) { - if sw, ok := w.(stringWriter); ok { - return sw.WriteString(s) - } - return w.Write([]byte(s)) -} - -// ReadAtLeast reads from r into buf until it has read at least min bytes. -// It returns the number of bytes copied and an error if fewer bytes were read. -// The error is EOF only if no bytes were read. -// If an EOF happens after reading fewer than min bytes, -// ReadAtLeast returns ErrUnexpectedEOF. -// If min is greater than the length of buf, ReadAtLeast returns ErrShortBuffer. -// On return, n >= min if and only if err == nil. -func ReadAtLeast(r Reader, buf []byte, min int) (n int, err error) { - if len(buf) < min { - return 0, ErrShortBuffer - } - for n < min && err == nil { - var nn int - nn, err = r.Read(buf[n:]) - n += nn - } - if n >= min { - err = nil - } else if n > 0 && err == EOF { - err = ErrUnexpectedEOF - } - return -} - -// ReadFull reads exactly len(buf) bytes from r into buf. -// It returns the number of bytes copied and an error if fewer bytes were read. -// The error is EOF only if no bytes were read. -// If an EOF happens after reading some but not all the bytes, -// ReadFull returns ErrUnexpectedEOF. -// On return, n == len(buf) if and only if err == nil. -func ReadFull(r Reader, buf []byte) (n int, err error) { - return ReadAtLeast(r, buf, len(buf)) -} - -// CopyN copies n bytes (or until an error) from src to dst. -// It returns the number of bytes copied and the earliest -// error encountered while copying. -// On return, written == n if and only if err == nil. -// -// If dst implements the ReaderFrom interface, -// the copy is implemented using it. -func CopyN(dst Writer, src Reader, n int64) (written int64, err error) { - written, err = Copy(dst, LimitReader(src, n)) - if written == n { - return n, nil - } - if written < n && err == nil { - // src stopped early; must have been EOF. - err = EOF - } - return -} - -// Copy copies from src to dst until either EOF is reached -// on src or an error occurs. It returns the number of bytes -// copied and the first error encountered while copying, if any. -// -// A successful Copy returns err == nil, not err == EOF. -// Because Copy is defined to read from src until EOF, it does -// not treat an EOF from Read as an error to be reported. -// -// If src implements the WriterTo interface, -// the copy is implemented by calling src.WriteTo(dst). -// Otherwise, if dst implements the ReaderFrom interface, -// the copy is implemented by calling dst.ReadFrom(src). -func Copy(dst Writer, src Reader) (written int64, err error) { - // If the reader has a WriteTo method, use it to do the copy. - // Avoids an allocation and a copy. - if wt, ok := src.(WriterTo); ok { - return wt.WriteTo(dst) - } - // Similarly, if the writer has a ReadFrom method, use it to do the copy. - if rt, ok := dst.(ReaderFrom); ok { - return rt.ReadFrom(src) - } - 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 = ErrShortWrite - break - } - } - if er == EOF { - break - } - if er != nil { - err = er - break - } - } - return written, err -} - -// LimitReader returns a Reader that reads from r -// but stops with EOF after n bytes. -// The underlying implementation is a *LimitedReader. -func LimitReader(r Reader, n int64) Reader { return &LimitedReader{r, n} } - -// A LimitedReader reads from R but limits the amount of -// data returned to just N bytes. Each call to Read -// updates N to reflect the new amount remaining. -type LimitedReader struct { - R Reader // underlying reader - N int64 // max bytes remaining -} - -func (l *LimitedReader) Read(p []byte) (n int, err error) { - if l.N <= 0 { - return 0, EOF - } - if int64(len(p)) > l.N { - p = p[0:l.N] - } - n, err = l.R.Read(p) - l.N -= int64(n) - return -} - -// NewSectionReader returns a SectionReader that reads from r -// starting at offset off and stops with EOF after n bytes. -func NewSectionReader(r ReaderAt, off int64, n int64) *SectionReader { - return &SectionReader{r, off, off, off + n} -} - -// SectionReader implements Read, Seek, and ReadAt on a section -// of an underlying ReaderAt. -type SectionReader struct { - r ReaderAt - base int64 - off int64 - limit int64 -} - -func (s *SectionReader) Read(p []byte) (n int, err error) { - if s.off >= s.limit { - return 0, EOF - } - if max := s.limit - s.off; int64(len(p)) > max { - p = p[0:max] - } - n, err = s.r.ReadAt(p, s.off) - s.off += int64(n) - return -} - -var errWhence = errors.New("Seek: invalid whence") -var errOffset = errors.New("Seek: invalid offset") - -func (s *SectionReader) Seek(offset int64, whence int) (int64, error) { - switch whence { - default: - return 0, errWhence - case 0: - offset += s.base - case 1: - offset += s.off - case 2: - offset += s.limit - } - if offset < s.base { - return 0, errOffset - } - s.off = offset - return offset - s.base, nil -} - -func (s *SectionReader) ReadAt(p []byte, off int64) (n int, err error) { - if off < 0 || off >= s.limit-s.base { - return 0, EOF - } - off += s.base - if max := s.limit - off; int64(len(p)) > max { - p = p[0:max] - n, err = s.r.ReadAt(p, off) - if err == nil { - err = EOF - } - return n, err - } - return s.r.ReadAt(p, off) -} - -// Size returns the size of the section in bytes. -func (s *SectionReader) Size() int64 { return s.limit - s.base } - -// TeeReader returns a Reader that writes to w what it reads from r. -// All reads from r performed through it are matched with -// corresponding writes to w. There is no internal buffering - -// the write must complete before the read completes. -// Any error encountered while writing is reported as a read error. -func TeeReader(r Reader, w Writer) Reader { - return &teeReader{r, w} -} - -type teeReader struct { - r Reader - w Writer -} - -func (t *teeReader) Read(p []byte) (n int, err error) { - n, err = t.r.Read(p) - if n > 0 { - if n, err := t.w.Write(p[:n]); err != nil { - return n, err - } - } - return -} diff --git a/src/pkg/io/io_test.go b/src/pkg/io/io_test.go deleted file mode 100644 index 57db1fbf0..000000000 --- a/src/pkg/io/io_test.go +++ /dev/null @@ -1,341 +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_test - -import ( - "bytes" - "errors" - "fmt" - . "io" - "strings" - "testing" -) - -// An version of bytes.Buffer without ReadFrom and WriteTo -type Buffer struct { - bytes.Buffer - ReaderFrom // conflicts with and hides bytes.Buffer's ReaderFrom. - WriterTo // conflicts with and hides bytes.Buffer's WriterTo. -} - -// Simple tests, primarily to verify the ReadFrom and WriteTo callouts inside Copy and CopyN. - -func TestCopy(t *testing.T) { - rb := new(Buffer) - wb := new(Buffer) - rb.WriteString("hello, world.") - Copy(wb, rb) - if wb.String() != "hello, world." { - t.Errorf("Copy did not work properly") - } -} - -func TestCopyReadFrom(t *testing.T) { - rb := new(Buffer) - wb := new(bytes.Buffer) // implements ReadFrom. - rb.WriteString("hello, world.") - Copy(wb, rb) - if wb.String() != "hello, world." { - t.Errorf("Copy did not work properly") - } -} - -func TestCopyWriteTo(t *testing.T) { - rb := new(bytes.Buffer) // implements WriteTo. - wb := new(Buffer) - rb.WriteString("hello, world.") - Copy(wb, rb) - if wb.String() != "hello, world." { - t.Errorf("Copy did not work properly") - } -} - -// Version of bytes.Buffer that checks whether WriteTo was called or not -type writeToChecker struct { - bytes.Buffer - writeToCalled bool -} - -func (wt *writeToChecker) WriteTo(w Writer) (int64, error) { - wt.writeToCalled = true - return wt.Buffer.WriteTo(w) -} - -// It's preferable to choose WriterTo over ReaderFrom, since a WriterTo can issue one large write, -// while the ReaderFrom must read until EOF, potentially allocating when running out of buffer. -// Make sure that we choose WriterTo when both are implemented. -func TestCopyPriority(t *testing.T) { - rb := new(writeToChecker) - wb := new(bytes.Buffer) - rb.WriteString("hello, world.") - Copy(wb, rb) - if wb.String() != "hello, world." { - t.Errorf("Copy did not work properly") - } else if !rb.writeToCalled { - t.Errorf("WriteTo was not prioritized over ReadFrom") - } -} - -func TestCopyN(t *testing.T) { - rb := new(Buffer) - wb := new(Buffer) - rb.WriteString("hello, world.") - CopyN(wb, rb, 5) - if wb.String() != "hello" { - t.Errorf("CopyN did not work properly") - } -} - -func TestCopyNReadFrom(t *testing.T) { - rb := new(Buffer) - wb := new(bytes.Buffer) // implements ReadFrom. - rb.WriteString("hello") - CopyN(wb, rb, 5) - if wb.String() != "hello" { - t.Errorf("CopyN did not work properly") - } -} - -func TestCopyNWriteTo(t *testing.T) { - rb := new(bytes.Buffer) // implements WriteTo. - wb := new(Buffer) - rb.WriteString("hello, world.") - CopyN(wb, rb, 5) - if wb.String() != "hello" { - t.Errorf("CopyN did not work properly") - } -} - -type noReadFrom struct { - w Writer -} - -func (w *noReadFrom) Write(p []byte) (n int, err error) { - return w.w.Write(p) -} - -type wantedAndErrReader struct{} - -func (wantedAndErrReader) Read(p []byte) (int, error) { - return len(p), errors.New("wantedAndErrReader error") -} - -func TestCopyNEOF(t *testing.T) { - // Test that EOF behavior is the same regardless of whether - // argument to CopyN has ReadFrom. - - b := new(bytes.Buffer) - - n, err := CopyN(&noReadFrom{b}, strings.NewReader("foo"), 3) - if n != 3 || err != nil { - t.Errorf("CopyN(noReadFrom, foo, 3) = %d, %v; want 3, nil", n, err) - } - - n, err = CopyN(&noReadFrom{b}, strings.NewReader("foo"), 4) - if n != 3 || err != EOF { - t.Errorf("CopyN(noReadFrom, foo, 4) = %d, %v; want 3, EOF", n, err) - } - - n, err = CopyN(b, strings.NewReader("foo"), 3) // b has read from - if n != 3 || err != nil { - t.Errorf("CopyN(bytes.Buffer, foo, 3) = %d, %v; want 3, nil", n, err) - } - - n, err = CopyN(b, strings.NewReader("foo"), 4) // b has read from - if n != 3 || err != EOF { - t.Errorf("CopyN(bytes.Buffer, foo, 4) = %d, %v; want 3, EOF", n, err) - } - - n, err = CopyN(b, wantedAndErrReader{}, 5) - if n != 5 || err != nil { - t.Errorf("CopyN(bytes.Buffer, wantedAndErrReader, 5) = %d, %v; want 5, nil", n, err) - } - - n, err = CopyN(&noReadFrom{b}, wantedAndErrReader{}, 5) - if n != 5 || err != nil { - t.Errorf("CopyN(noReadFrom, wantedAndErrReader, 5) = %d, %v; want 5, nil", n, err) - } -} - -func TestReadAtLeast(t *testing.T) { - var rb bytes.Buffer - testReadAtLeast(t, &rb) -} - -// A version of bytes.Buffer that returns n > 0, err on Read -// when the input is exhausted. -type dataAndErrorBuffer struct { - err error - bytes.Buffer -} - -func (r *dataAndErrorBuffer) Read(p []byte) (n int, err error) { - n, err = r.Buffer.Read(p) - if n > 0 && r.Buffer.Len() == 0 && err == nil { - err = r.err - } - return -} - -func TestReadAtLeastWithDataAndEOF(t *testing.T) { - var rb dataAndErrorBuffer - rb.err = EOF - testReadAtLeast(t, &rb) -} - -func TestReadAtLeastWithDataAndError(t *testing.T) { - var rb dataAndErrorBuffer - rb.err = fmt.Errorf("fake error") - testReadAtLeast(t, &rb) -} - -func testReadAtLeast(t *testing.T, rb ReadWriter) { - rb.Write([]byte("0123")) - buf := make([]byte, 2) - n, err := ReadAtLeast(rb, buf, 2) - if err != nil { - t.Error(err) - } - n, err = ReadAtLeast(rb, buf, 4) - if err != ErrShortBuffer { - t.Errorf("expected ErrShortBuffer got %v", err) - } - if n != 0 { - t.Errorf("expected to have read 0 bytes, got %v", n) - } - n, err = ReadAtLeast(rb, buf, 1) - if err != nil { - t.Error(err) - } - if n != 2 { - t.Errorf("expected to have read 2 bytes, got %v", n) - } - n, err = ReadAtLeast(rb, buf, 2) - if err != EOF { - t.Errorf("expected EOF, got %v", err) - } - if n != 0 { - t.Errorf("expected to have read 0 bytes, got %v", n) - } - rb.Write([]byte("4")) - n, err = ReadAtLeast(rb, buf, 2) - want := ErrUnexpectedEOF - if rb, ok := rb.(*dataAndErrorBuffer); ok && rb.err != EOF { - want = rb.err - } - if err != want { - t.Errorf("expected %v, got %v", want, err) - } - if n != 1 { - t.Errorf("expected to have read 1 bytes, got %v", n) - } -} - -func TestTeeReader(t *testing.T) { - src := []byte("hello, world") - dst := make([]byte, len(src)) - rb := bytes.NewBuffer(src) - wb := new(bytes.Buffer) - r := TeeReader(rb, wb) - if n, err := ReadFull(r, dst); err != nil || n != len(src) { - t.Fatalf("ReadFull(r, dst) = %d, %v; want %d, nil", n, err, len(src)) - } - if !bytes.Equal(dst, src) { - t.Errorf("bytes read = %q want %q", dst, src) - } - if !bytes.Equal(wb.Bytes(), src) { - t.Errorf("bytes written = %q want %q", wb.Bytes(), src) - } - if n, err := r.Read(dst); n != 0 || err != EOF { - t.Errorf("r.Read at EOF = %d, %v want 0, EOF", n, err) - } - rb = bytes.NewBuffer(src) - pr, pw := Pipe() - pr.Close() - r = TeeReader(rb, pw) - if n, err := ReadFull(r, dst); n != 0 || err != ErrClosedPipe { - t.Errorf("closed tee: ReadFull(r, dst) = %d, %v; want 0, EPIPE", n, err) - } -} - -func TestSectionReader_ReadAt(t *testing.T) { - dat := "a long sample data, 1234567890" - tests := []struct { - data string - off int - n int - bufLen int - at int - exp string - err error - }{ - {data: "", off: 0, n: 10, bufLen: 2, at: 0, exp: "", err: EOF}, - {data: dat, off: 0, n: len(dat), bufLen: 0, at: 0, exp: "", err: nil}, - {data: dat, off: len(dat), n: 1, bufLen: 1, at: 0, exp: "", err: EOF}, - {data: dat, off: 0, n: len(dat) + 2, bufLen: len(dat), at: 0, exp: dat, err: nil}, - {data: dat, off: 0, n: len(dat), bufLen: len(dat) / 2, at: 0, exp: dat[:len(dat)/2], err: nil}, - {data: dat, off: 0, n: len(dat), bufLen: len(dat), at: 0, exp: dat, err: nil}, - {data: dat, off: 0, n: len(dat), bufLen: len(dat) / 2, at: 2, exp: dat[2 : 2+len(dat)/2], err: nil}, - {data: dat, off: 3, n: len(dat), bufLen: len(dat) / 2, at: 2, exp: dat[5 : 5+len(dat)/2], err: nil}, - {data: dat, off: 3, n: len(dat) / 2, bufLen: len(dat)/2 - 2, at: 2, exp: dat[5 : 5+len(dat)/2-2], err: nil}, - {data: dat, off: 3, n: len(dat) / 2, bufLen: len(dat)/2 + 2, at: 2, exp: dat[5 : 5+len(dat)/2-2], err: EOF}, - {data: dat, off: 0, n: 0, bufLen: 0, at: -1, exp: "", err: EOF}, - {data: dat, off: 0, n: 0, bufLen: 0, at: 1, exp: "", err: EOF}, - } - for i, tt := range tests { - r := strings.NewReader(tt.data) - s := NewSectionReader(r, int64(tt.off), int64(tt.n)) - buf := make([]byte, tt.bufLen) - if n, err := s.ReadAt(buf, int64(tt.at)); n != len(tt.exp) || string(buf[:n]) != tt.exp || err != tt.err { - t.Fatalf("%d: ReadAt(%d) = %q, %v; expected %q, %v", i, tt.at, buf[:n], err, tt.exp, tt.err) - } - } -} - -func TestSectionReader_Seek(t *testing.T) { - // Verifies that NewSectionReader's Seeker behaves like bytes.NewReader (which is like strings.NewReader) - br := bytes.NewReader([]byte("foo")) - sr := NewSectionReader(br, 0, int64(len("foo"))) - - for whence := 0; whence <= 2; whence++ { - for offset := int64(-3); offset <= 4; offset++ { - brOff, brErr := br.Seek(offset, whence) - srOff, srErr := sr.Seek(offset, whence) - if (brErr != nil) != (srErr != nil) || brOff != srOff { - t.Errorf("For whence %d, offset %d: bytes.Reader.Seek = (%v, %v) != SectionReader.Seek = (%v, %v)", - whence, offset, brOff, brErr, srErr, srOff) - } - } - } - - // And verify we can just seek past the end and get an EOF - got, err := sr.Seek(100, 0) - if err != nil || got != 100 { - t.Errorf("Seek = %v, %v; want 100, nil", got, err) - } - - n, err := sr.Read(make([]byte, 10)) - if n != 0 || err != EOF { - t.Errorf("Read = %v, %v; want 0, EOF", n, err) - } -} - -func TestSectionReader_Size(t *testing.T) { - tests := []struct { - data string - want int64 - }{ - {"a long sample data, 1234567890", 30}, - {"", 0}, - } - - for _, tt := range tests { - r := strings.NewReader(tt.data) - sr := NewSectionReader(r, 0, int64(len(tt.data))) - if got := sr.Size(); got != tt.want { - t.Errorf("Size = %v; want %v", got, tt.want) - } - } -} diff --git a/src/pkg/io/ioutil/ioutil.go b/src/pkg/io/ioutil/ioutil.go deleted file mode 100644 index 909a81563..000000000 --- a/src/pkg/io/ioutil/ioutil.go +++ /dev/null @@ -1,165 +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 ioutil implements some I/O utility functions. -package ioutil - -import ( - "bytes" - "io" - "os" - "sort" - "sync" -) - -// readAll reads from r until an error or EOF and returns the data it read -// from the internal buffer allocated with a specified capacity. -func readAll(r io.Reader, capacity int64) (b []byte, err error) { - buf := bytes.NewBuffer(make([]byte, 0, capacity)) - // If the buffer overflows, we will get bytes.ErrTooLarge. - // Return that as an error. Any other panic remains. - defer func() { - e := recover() - if e == nil { - return - } - if panicErr, ok := e.(error); ok && panicErr == bytes.ErrTooLarge { - err = panicErr - } else { - panic(e) - } - }() - _, err = buf.ReadFrom(r) - return buf.Bytes(), err -} - -// ReadAll reads from r until an error or EOF and returns the data it read. -// A successful call returns err == nil, not err == EOF. Because ReadAll is -// defined to read from src until EOF, it does not treat an EOF from Read -// as an error to be reported. -func ReadAll(r io.Reader) ([]byte, error) { - return readAll(r, bytes.MinRead) -} - -// ReadFile reads the file named by filename and returns the contents. -// A successful call returns err == nil, not err == EOF. Because ReadFile -// reads the whole file, it does not treat an EOF from Read as an error -// to be reported. -func ReadFile(filename string) ([]byte, error) { - f, err := os.Open(filename) - if err != nil { - return nil, err - } - defer f.Close() - // It's a good but not certain bet that FileInfo will tell us exactly how much to - // read, so let's try it but be prepared for the answer to be wrong. - var n int64 - - if fi, err := f.Stat(); err == nil { - // Don't preallocate a huge buffer, just in case. - if size := fi.Size(); size < 1e9 { - n = size - } - } - // As initial capacity for readAll, use n + a little extra in case Size is zero, - // and to avoid another allocation after Read has filled the buffer. The readAll - // call will read into its allocated internal buffer cheaply. If the size was - // wrong, we'll either waste some space off the end or reallocate as needed, but - // in the overwhelmingly common case we'll get it just right. - return readAll(f, n+bytes.MinRead) -} - -// WriteFile writes data to a file named by filename. -// If the file does not exist, WriteFile creates it with permissions perm; -// otherwise WriteFile truncates it before writing. -func WriteFile(filename string, data []byte, perm os.FileMode) error { - f, err := os.OpenFile(filename, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, perm) - if err != nil { - return err - } - n, err := f.Write(data) - if err == nil && n < len(data) { - err = io.ErrShortWrite - } - if err1 := f.Close(); err == nil { - err = err1 - } - return err -} - -// byName implements sort.Interface. -type byName []os.FileInfo - -func (f byName) Len() int { return len(f) } -func (f byName) Less(i, j int) bool { return f[i].Name() < f[j].Name() } -func (f byName) Swap(i, j int) { f[i], f[j] = f[j], f[i] } - -// ReadDir reads the directory named by dirname and returns -// a list of sorted directory entries. -func ReadDir(dirname string) ([]os.FileInfo, error) { - f, err := os.Open(dirname) - if err != nil { - return nil, err - } - list, err := f.Readdir(-1) - f.Close() - if err != nil { - return nil, err - } - sort.Sort(byName(list)) - return list, nil -} - -type nopCloser struct { - io.Reader -} - -func (nopCloser) Close() error { return nil } - -// NopCloser returns a ReadCloser with a no-op Close method wrapping -// the provided Reader r. -func NopCloser(r io.Reader) io.ReadCloser { - return nopCloser{r} -} - -type devNull int - -// devNull implements ReaderFrom as an optimization so io.Copy to -// ioutil.Discard can avoid doing unnecessary work. -var _ io.ReaderFrom = devNull(0) - -func (devNull) Write(p []byte) (int, error) { - return len(p), nil -} - -func (devNull) WriteString(s string) (int, error) { - return len(s), nil -} - -var blackHolePool = sync.Pool{ - New: func() interface{} { - b := make([]byte, 8192) - return &b - }, -} - -func (devNull) ReadFrom(r io.Reader) (n int64, err error) { - bufp := blackHolePool.Get().(*[]byte) - readSize := 0 - for { - readSize, err = r.Read(*bufp) - n += int64(readSize) - if err != nil { - blackHolePool.Put(bufp) - if err == io.EOF { - return n, nil - } - return - } - } -} - -// Discard is an io.Writer on which all Write calls succeed -// without doing anything. -var Discard io.Writer = devNull(0) diff --git a/src/pkg/io/ioutil/ioutil_test.go b/src/pkg/io/ioutil/ioutil_test.go deleted file mode 100644 index c297847b4..000000000 --- a/src/pkg/io/ioutil/ioutil_test.go +++ /dev/null @@ -1,95 +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 ioutil - -import ( - "os" - "testing" -) - -func checkSize(t *testing.T, path string, size int64) { - 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 = "ioutil_test.go" - contents, err = ReadFile(filename) - if err != nil { - t.Fatalf("ReadFile %s: %v", filename, err) - } - - checkSize(t, filename, int64(len(contents))) -} - -func TestWriteFile(t *testing.T) { - f, err := TempFile("", "ioutil-test") - if err != nil { - t.Fatal(err) - } - filename := f.Name() - data := "Programming today is a race between software engineers striving to " + - "build bigger and better idiot-proof programs, and the Universe trying " + - "to produce bigger and better idiots. So far, the Universe is winning." - - if err := WriteFile(filename, []byte(data), 0644); err != nil { - t.Fatalf("WriteFile %s: %v", filename, err) - } - - contents, err := ReadFile(filename) - if err != nil { - t.Fatalf("ReadFile %s: %v", filename, err) - } - - if string(contents) != data { - t.Fatalf("contents = %q\nexpected = %q", string(contents), data) - } - - // cleanup - f.Close() - os.Remove(filename) // ignore error -} - -func TestReadDir(t *testing.T) { - dirname := "rumpelstilzchen" - _, err := ReadDir(dirname) - if err == nil { - t.Fatalf("ReadDir %s: error expected, none found", dirname) - } - - dirname = ".." - list, err := ReadDir(dirname) - if err != nil { - t.Fatalf("ReadDir %s: %v", dirname, err) - } - - foundFile := false - foundSubDir := false - for _, dir := range list { - switch { - case !dir.IsDir() && dir.Name() == "io_test.go": - foundFile = true - case dir.IsDir() && dir.Name() == "ioutil": - foundSubDir = true - } - } - if !foundFile { - t.Fatalf("ReadDir %s: io_test.go file not found", dirname) - } - if !foundSubDir { - t.Fatalf("ReadDir %s: ioutil directory not found", dirname) - } -} diff --git a/src/pkg/io/ioutil/tempfile.go b/src/pkg/io/ioutil/tempfile.go deleted file mode 100644 index 4a06e9756..000000000 --- a/src/pkg/io/ioutil/tempfile.go +++ /dev/null @@ -1,95 +0,0 @@ -// Copyright 2010 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 ioutil - -import ( - "os" - "path/filepath" - "strconv" - "sync" - "time" -) - -// Random number state. -// We generate random temporary file names so that there's a good -// chance the file doesn't exist yet - keeps the number of tries in -// TempFile to a minimum. -var rand uint32 -var randmu sync.Mutex - -func reseed() uint32 { - return uint32(time.Now().UnixNano() + int64(os.Getpid())) -} - -func nextSuffix() string { - randmu.Lock() - r := rand - if r == 0 { - r = reseed() - } - r = r*1664525 + 1013904223 // constants from Numerical Recipes - rand = r - randmu.Unlock() - return strconv.Itoa(int(1e9 + r%1e9))[1:] -} - -// TempFile creates a new temporary file in the directory dir -// with a name beginning with prefix, opens the file for reading -// and writing, and returns the resulting *os.File. -// If dir is the empty string, TempFile uses the default directory -// for temporary files (see os.TempDir). -// Multiple programs calling TempFile simultaneously -// will not choose the same file. The caller can use f.Name() -// to find the pathname of the file. It is the caller's responsibility -// to remove the file when no longer needed. -func TempFile(dir, prefix string) (f *os.File, err error) { - if dir == "" { - dir = os.TempDir() - } - - nconflict := 0 - for i := 0; i < 10000; i++ { - name := filepath.Join(dir, prefix+nextSuffix()) - f, err = os.OpenFile(name, os.O_RDWR|os.O_CREATE|os.O_EXCL, 0600) - if os.IsExist(err) { - if nconflict++; nconflict > 10 { - rand = reseed() - } - continue - } - break - } - return -} - -// TempDir creates a new temporary directory in the directory dir -// with a name beginning with prefix and returns the path of the -// new directory. If dir is the empty string, TempDir uses the -// default directory for temporary files (see os.TempDir). -// Multiple programs calling TempDir simultaneously -// will not choose the same directory. It is the caller's responsibility -// to remove the directory when no longer needed. -func TempDir(dir, prefix string) (name string, err error) { - if dir == "" { - dir = os.TempDir() - } - - nconflict := 0 - for i := 0; i < 10000; i++ { - try := filepath.Join(dir, prefix+nextSuffix()) - err = os.Mkdir(try, 0700) - if os.IsExist(err) { - if nconflict++; nconflict > 10 { - rand = reseed() - } - continue - } - if err == nil { - name = try - } - break - } - return -} diff --git a/src/pkg/io/ioutil/tempfile_test.go b/src/pkg/io/ioutil/tempfile_test.go deleted file mode 100644 index d2a132a11..000000000 --- a/src/pkg/io/ioutil/tempfile_test.go +++ /dev/null @@ -1,53 +0,0 @@ -// Copyright 2010 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 ioutil - -import ( - "os" - "path/filepath" - "regexp" - "testing" -) - -func TestTempFile(t *testing.T) { - f, err := TempFile("/_not_exists_", "foo") - if f != nil || err == nil { - t.Errorf("TempFile(`/_not_exists_`, `foo`) = %v, %v", f, err) - } - - dir := os.TempDir() - f, err = TempFile(dir, "ioutil_test") - if f == nil || err != nil { - t.Errorf("TempFile(dir, `ioutil_test`) = %v, %v", f, err) - } - if f != nil { - f.Close() - os.Remove(f.Name()) - re := regexp.MustCompile("^" + regexp.QuoteMeta(filepath.Join(dir, "ioutil_test")) + "[0-9]+$") - if !re.MatchString(f.Name()) { - t.Errorf("TempFile(`"+dir+"`, `ioutil_test`) created bad name %s", f.Name()) - } - } -} - -func TestTempDir(t *testing.T) { - name, err := TempDir("/_not_exists_", "foo") - if name != "" || err == nil { - t.Errorf("TempDir(`/_not_exists_`, `foo`) = %v, %v", name, err) - } - - dir := os.TempDir() - name, err = TempDir(dir, "ioutil_test") - if name == "" || err != nil { - t.Errorf("TempDir(dir, `ioutil_test`) = %v, %v", name, err) - } - if name != "" { - os.Remove(name) - re := regexp.MustCompile("^" + regexp.QuoteMeta(filepath.Join(dir, "ioutil_test")) + "[0-9]+$") - if !re.MatchString(name) { - t.Errorf("TempDir(`"+dir+"`, `ioutil_test`) created bad name %s", name) - } - } -} diff --git a/src/pkg/io/multi.go b/src/pkg/io/multi.go deleted file mode 100644 index e26cc53e9..000000000 --- a/src/pkg/io/multi.go +++ /dev/null @@ -1,61 +0,0 @@ -// Copyright 2010 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 - -type multiReader struct { - readers []Reader -} - -func (mr *multiReader) Read(p []byte) (n int, err error) { - for len(mr.readers) > 0 { - n, err = mr.readers[0].Read(p) - if n > 0 || err != EOF { - if err == EOF { - // Don't return EOF yet. There may be more bytes - // in the remaining readers. - err = nil - } - return - } - mr.readers = mr.readers[1:] - } - return 0, EOF -} - -// MultiReader returns a Reader that's the logical concatenation of -// the provided input readers. They're read sequentially. Once all -// inputs have returned EOF, Read will return EOF. If any of the readers -// return a non-nil, non-EOF error, Read will return that error. -func MultiReader(readers ...Reader) Reader { - r := make([]Reader, len(readers)) - copy(r, readers) - return &multiReader{r} -} - -type multiWriter struct { - writers []Writer -} - -func (t *multiWriter) Write(p []byte) (n int, err error) { - for _, w := range t.writers { - n, err = w.Write(p) - if err != nil { - return - } - if n != len(p) { - err = ErrShortWrite - return - } - } - return len(p), nil -} - -// MultiWriter creates a writer that duplicates its writes to all the -// provided writers, similar to the Unix tee(1) command. -func MultiWriter(writers ...Writer) Writer { - w := make([]Writer, len(writers)) - copy(w, writers) - return &multiWriter{w} -} diff --git a/src/pkg/io/multi_test.go b/src/pkg/io/multi_test.go deleted file mode 100644 index 56c6769a9..000000000 --- a/src/pkg/io/multi_test.go +++ /dev/null @@ -1,115 +0,0 @@ -// Copyright 2010 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_test - -import ( - "bytes" - "crypto/sha1" - "fmt" - . "io" - "io/ioutil" - "strings" - "testing" -) - -func TestMultiReader(t *testing.T) { - var mr Reader - var buf []byte - nread := 0 - withFooBar := func(tests func()) { - r1 := strings.NewReader("foo ") - r2 := strings.NewReader("") - r3 := strings.NewReader("bar") - mr = MultiReader(r1, r2, r3) - buf = make([]byte, 20) - tests() - } - expectRead := func(size int, expected string, eerr error) { - nread++ - n, gerr := mr.Read(buf[0:size]) - if n != len(expected) { - t.Errorf("#%d, expected %d bytes; got %d", - nread, len(expected), n) - } - got := string(buf[0:n]) - if got != expected { - t.Errorf("#%d, expected %q; got %q", - nread, expected, got) - } - if gerr != eerr { - t.Errorf("#%d, expected error %v; got %v", - nread, eerr, gerr) - } - buf = buf[n:] - } - withFooBar(func() { - expectRead(2, "fo", nil) - expectRead(5, "o ", nil) - expectRead(5, "bar", nil) - expectRead(5, "", EOF) - }) - withFooBar(func() { - expectRead(4, "foo ", nil) - expectRead(1, "b", nil) - expectRead(3, "ar", nil) - expectRead(1, "", EOF) - }) - withFooBar(func() { - expectRead(5, "foo ", nil) - }) -} - -func TestMultiWriter(t *testing.T) { - sha1 := sha1.New() - sink := new(bytes.Buffer) - mw := MultiWriter(sha1, sink) - - sourceString := "My input text." - source := strings.NewReader(sourceString) - written, err := Copy(mw, source) - - if written != int64(len(sourceString)) { - t.Errorf("short write of %d, not %d", written, len(sourceString)) - } - - if err != nil { - t.Errorf("unexpected error: %v", err) - } - - sha1hex := fmt.Sprintf("%x", sha1.Sum(nil)) - if sha1hex != "01cb303fa8c30a64123067c5aa6284ba7ec2d31b" { - t.Error("incorrect sha1 value") - } - - if sink.String() != sourceString { - t.Errorf("expected %q; got %q", sourceString, sink.String()) - } -} - -// Test that MultiReader copies the input slice and is insulated from future modification. -func TestMultiReaderCopy(t *testing.T) { - slice := []Reader{strings.NewReader("hello world")} - r := MultiReader(slice...) - slice[0] = nil - data, err := ioutil.ReadAll(r) - if err != nil || string(data) != "hello world" { - t.Errorf("ReadAll() = %q, %v, want %q, nil", data, err, "hello world") - } -} - -// Test that MultiWriter copies the input slice and is insulated from future modification. -func TestMultiWriterCopy(t *testing.T) { - var buf bytes.Buffer - slice := []Writer{&buf} - w := MultiWriter(slice...) - slice[0] = nil - n, err := w.Write([]byte("hello world")) - if err != nil || n != 11 { - t.Errorf("Write(`hello world`) = %d, %v, want 11, nil", n, err) - } - if buf.String() != "hello world" { - t.Errorf("buf.String() = %q, want %q", buf.String(), "hello world") - } -} diff --git a/src/pkg/io/pipe.go b/src/pkg/io/pipe.go deleted file mode 100644 index f65354a7f..000000000 --- a/src/pkg/io/pipe.go +++ /dev/null @@ -1,193 +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.Reader -// with code expecting an io.Writer. - -package io - -import ( - "errors" - "sync" -) - -// ErrClosedPipe is the error used for read or write operations on a closed pipe. -var ErrClosedPipe = errors.New("io: read/write on closed pipe") - -type pipeResult struct { - n int - err error -} - -// A pipe is the shared pipe structure underlying PipeReader and PipeWriter. -type pipe struct { - rl sync.Mutex // gates readers one at a time - wl sync.Mutex // gates writers one at a time - l sync.Mutex // protects remaining fields - data []byte // data remaining in pending write - rwait sync.Cond // waiting reader - wwait sync.Cond // waiting writer - rerr error // if reader closed, error to give writes - werr error // if writer closed, error to give reads -} - -func (p *pipe) read(b []byte) (n int, err error) { - // One reader at a time. - p.rl.Lock() - defer p.rl.Unlock() - - p.l.Lock() - defer p.l.Unlock() - for { - if p.rerr != nil { - return 0, ErrClosedPipe - } - if p.data != nil { - break - } - if p.werr != nil { - return 0, p.werr - } - p.rwait.Wait() - } - n = copy(b, p.data) - p.data = p.data[n:] - if len(p.data) == 0 { - p.data = nil - p.wwait.Signal() - } - return -} - -var zero [0]byte - -func (p *pipe) write(b []byte) (n int, err error) { - // pipe uses nil to mean not available - if b == nil { - b = zero[:] - } - - // One writer at a time. - p.wl.Lock() - defer p.wl.Unlock() - - p.l.Lock() - defer p.l.Unlock() - if p.werr != nil { - err = ErrClosedPipe - return - } - p.data = b - p.rwait.Signal() - for { - if p.data == nil { - break - } - if p.rerr != nil { - err = p.rerr - break - } - if p.werr != nil { - err = ErrClosedPipe - } - p.wwait.Wait() - } - n = len(b) - len(p.data) - p.data = nil // in case of rerr or werr - return -} - -func (p *pipe) rclose(err error) { - if err == nil { - err = ErrClosedPipe - } - p.l.Lock() - defer p.l.Unlock() - p.rerr = err - p.rwait.Signal() - p.wwait.Signal() -} - -func (p *pipe) wclose(err error) { - if err == nil { - err = EOF - } - p.l.Lock() - defer p.l.Unlock() - p.werr = err - p.rwait.Signal() - p.wwait.Signal() -} - -// A PipeReader is the read half of a pipe. -type PipeReader struct { - 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 EOF. -func (r *PipeReader) Read(data []byte) (n int, err error) { - return r.p.read(data) -} - -// Close closes the reader; subsequent writes to the -// write half of the pipe will return the error ErrClosedPipe. -func (r *PipeReader) Close() error { - return r.CloseWithError(nil) -} - -// CloseWithError closes the reader; subsequent writes -// to the write half of the pipe will return the error err. -func (r *PipeReader) CloseWithError(err error) error { - r.p.rclose(err) - return nil -} - -// A PipeWriter is the write half of a pipe. -type PipeWriter struct { - 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 ErrClosedPipe. -func (w *PipeWriter) Write(data []byte) (n int, err error) { - return w.p.write(data) -} - -// Close closes the writer; subsequent reads from the -// read half of the pipe will return no bytes and EOF. -func (w *PipeWriter) Close() error { - return w.CloseWithError(nil) -} - -// CloseWithError closes the writer; subsequent reads from the -// read half of the pipe will return no bytes and the error err. -func (w *PipeWriter) CloseWithError(err error) error { - w.p.wclose(err) - return nil -} - -// 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. -// It is safe to call Read and Write in parallel with each other or with -// Close. Close will complete once pending I/O is done. Parallel calls to -// Read, and parallel calls to Write, are also safe: -// the individual calls will be gated sequentially. -func Pipe() (*PipeReader, *PipeWriter) { - p := new(pipe) - p.rwait.L = &p.l - p.wwait.L = &p.l - r := &PipeReader{p} - w := &PipeWriter{p} - return r, w -} diff --git a/src/pkg/io/pipe_test.go b/src/pkg/io/pipe_test.go deleted file mode 100644 index b16e65306..000000000 --- a/src/pkg/io/pipe_test.go +++ /dev/null @@ -1,302 +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_test - -import ( - "fmt" - . "io" - "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, []byte("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 == EOF { - c <- 0 - break - } - if err != nil { - t.Errorf("read: %v", err) - } - c <- n - } -} - -// 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) - } -} - -type pipeReturn struct { - n int - err error -} - -// 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 && err != EOF { - 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 err != EOF { - t.Fatalf("read at end: %v", err) - } - } - 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(error) error - Close() error -} - -type pipeTest struct { - async bool - err 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{ - {true, nil, false}, - {true, nil, true}, - {true, ErrShortWrite, true}, - {false, nil, false}, - {false, nil, true}, - {false, ErrShortWrite, true}, -} - -func delayClose(t *testing.T, cl closer, ch chan int, tt pipeTest) { - time.Sleep(1 * time.Millisecond) - var err 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 - want := tt.err - if want == nil { - want = EOF - } - if err != want { - t.Errorf("read from closed pipe: %v want %v", err, want) - } - 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 close on Read side during Read. -func TestPipeReadClose2(t *testing.T) { - c := make(chan int, 1) - r, _ := Pipe() - go delayClose(t, r, c, pipeTest{}) - n, err := r.Read(make([]byte, 64)) - <-c - if n != 0 || err != ErrClosedPipe { - t.Errorf("read from closed pipe: %v, %v want %v, %v", n, err, 0, ErrClosedPipe) - } -} - -// 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 = ErrClosedPipe - } - 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) - } - } -} - -func TestWriteEmpty(t *testing.T) { - r, w := Pipe() - go func() { - w.Write([]byte{}) - w.Close() - }() - var b [2]byte - ReadFull(r, b[0:2]) - r.Close() -} - -func TestWriteNil(t *testing.T) { - r, w := Pipe() - go func() { - w.Write(nil) - w.Close() - }() - var b [2]byte - ReadFull(r, b[0:2]) - r.Close() -} - -func TestWriteAfterWriterClose(t *testing.T) { - r, w := Pipe() - - done := make(chan bool) - var writeErr error - go func() { - _, err := w.Write([]byte("hello")) - if err != nil { - t.Errorf("got error: %q; expected none", err) - } - w.Close() - _, writeErr = w.Write([]byte("world")) - done <- true - }() - - buf := make([]byte, 100) - var result string - n, err := ReadFull(r, buf) - if err != nil && err != ErrUnexpectedEOF { - t.Fatalf("got: %q; want: %q", err, ErrUnexpectedEOF) - } - result = string(buf[0:n]) - <-done - - if result != "hello" { - t.Errorf("got: %q; want: %q", result, "hello") - } - if writeErr != ErrClosedPipe { - t.Errorf("got: %q; want: %q", writeErr, ErrClosedPipe) - } -} |