github.com/varialus/godfly@v0.0.0-20130904042352-1934f9f095ab/src/pkg/io/pipe_test.go (about)

     1  // Copyright 2009 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package io_test
     6  
     7  import (
     8  	"fmt"
     9  	. "io"
    10  	"testing"
    11  	"time"
    12  )
    13  
    14  func checkWrite(t *testing.T, w Writer, data []byte, c chan int) {
    15  	n, err := w.Write(data)
    16  	if err != nil {
    17  		t.Errorf("write: %v", err)
    18  	}
    19  	if n != len(data) {
    20  		t.Errorf("short write: %d != %d", n, len(data))
    21  	}
    22  	c <- 0
    23  }
    24  
    25  // Test a single read/write pair.
    26  func TestPipe1(t *testing.T) {
    27  	c := make(chan int)
    28  	r, w := Pipe()
    29  	var buf = make([]byte, 64)
    30  	go checkWrite(t, w, []byte("hello, world"), c)
    31  	n, err := r.Read(buf)
    32  	if err != nil {
    33  		t.Errorf("read: %v", err)
    34  	} else if n != 12 || string(buf[0:12]) != "hello, world" {
    35  		t.Errorf("bad read: got %q", buf[0:n])
    36  	}
    37  	<-c
    38  	r.Close()
    39  	w.Close()
    40  }
    41  
    42  func reader(t *testing.T, r Reader, c chan int) {
    43  	var buf = make([]byte, 64)
    44  	for {
    45  		n, err := r.Read(buf)
    46  		if err == EOF {
    47  			c <- 0
    48  			break
    49  		}
    50  		if err != nil {
    51  			t.Errorf("read: %v", err)
    52  		}
    53  		c <- n
    54  	}
    55  }
    56  
    57  // Test a sequence of read/write pairs.
    58  func TestPipe2(t *testing.T) {
    59  	c := make(chan int)
    60  	r, w := Pipe()
    61  	go reader(t, r, c)
    62  	var buf = make([]byte, 64)
    63  	for i := 0; i < 5; i++ {
    64  		p := buf[0 : 5+i*10]
    65  		n, err := w.Write(p)
    66  		if n != len(p) {
    67  			t.Errorf("wrote %d, got %d", len(p), n)
    68  		}
    69  		if err != nil {
    70  			t.Errorf("write: %v", err)
    71  		}
    72  		nn := <-c
    73  		if nn != n {
    74  			t.Errorf("wrote %d, read got %d", n, nn)
    75  		}
    76  	}
    77  	w.Close()
    78  	nn := <-c
    79  	if nn != 0 {
    80  		t.Errorf("final read got %d", nn)
    81  	}
    82  }
    83  
    84  type pipeReturn struct {
    85  	n   int
    86  	err error
    87  }
    88  
    89  // Test a large write that requires multiple reads to satisfy.
    90  func writer(w WriteCloser, buf []byte, c chan pipeReturn) {
    91  	n, err := w.Write(buf)
    92  	w.Close()
    93  	c <- pipeReturn{n, err}
    94  }
    95  
    96  func TestPipe3(t *testing.T) {
    97  	c := make(chan pipeReturn)
    98  	r, w := Pipe()
    99  	var wdat = make([]byte, 128)
   100  	for i := 0; i < len(wdat); i++ {
   101  		wdat[i] = byte(i)
   102  	}
   103  	go writer(w, wdat, c)
   104  	var rdat = make([]byte, 1024)
   105  	tot := 0
   106  	for n := 1; n <= 256; n *= 2 {
   107  		nn, err := r.Read(rdat[tot : tot+n])
   108  		if err != nil && err != EOF {
   109  			t.Fatalf("read: %v", err)
   110  		}
   111  
   112  		// only final two reads should be short - 1 byte, then 0
   113  		expect := n
   114  		if n == 128 {
   115  			expect = 1
   116  		} else if n == 256 {
   117  			expect = 0
   118  			if err != EOF {
   119  				t.Fatalf("read at end: %v", err)
   120  			}
   121  		}
   122  		if nn != expect {
   123  			t.Fatalf("read %d, expected %d, got %d", n, expect, nn)
   124  		}
   125  		tot += nn
   126  	}
   127  	pr := <-c
   128  	if pr.n != 128 || pr.err != nil {
   129  		t.Fatalf("write 128: %d, %v", pr.n, pr.err)
   130  	}
   131  	if tot != 128 {
   132  		t.Fatalf("total read %d != 128", tot)
   133  	}
   134  	for i := 0; i < 128; i++ {
   135  		if rdat[i] != byte(i) {
   136  			t.Fatalf("rdat[%d] = %d", i, rdat[i])
   137  		}
   138  	}
   139  }
   140  
   141  // Test read after/before writer close.
   142  
   143  type closer interface {
   144  	CloseWithError(error) error
   145  	Close() error
   146  }
   147  
   148  type pipeTest struct {
   149  	async          bool
   150  	err            error
   151  	closeWithError bool
   152  }
   153  
   154  func (p pipeTest) String() string {
   155  	return fmt.Sprintf("async=%v err=%v closeWithError=%v", p.async, p.err, p.closeWithError)
   156  }
   157  
   158  var pipeTests = []pipeTest{
   159  	{true, nil, false},
   160  	{true, nil, true},
   161  	{true, ErrShortWrite, true},
   162  	{false, nil, false},
   163  	{false, nil, true},
   164  	{false, ErrShortWrite, true},
   165  }
   166  
   167  func delayClose(t *testing.T, cl closer, ch chan int, tt pipeTest) {
   168  	time.Sleep(1 * time.Millisecond)
   169  	var err error
   170  	if tt.closeWithError {
   171  		err = cl.CloseWithError(tt.err)
   172  	} else {
   173  		err = cl.Close()
   174  	}
   175  	if err != nil {
   176  		t.Errorf("delayClose: %v", err)
   177  	}
   178  	ch <- 0
   179  }
   180  
   181  func TestPipeReadClose(t *testing.T) {
   182  	for _, tt := range pipeTests {
   183  		c := make(chan int, 1)
   184  		r, w := Pipe()
   185  		if tt.async {
   186  			go delayClose(t, w, c, tt)
   187  		} else {
   188  			delayClose(t, w, c, tt)
   189  		}
   190  		var buf = make([]byte, 64)
   191  		n, err := r.Read(buf)
   192  		<-c
   193  		want := tt.err
   194  		if want == nil {
   195  			want = EOF
   196  		}
   197  		if err != want {
   198  			t.Errorf("read from closed pipe: %v want %v", err, want)
   199  		}
   200  		if n != 0 {
   201  			t.Errorf("read on closed pipe returned %d", n)
   202  		}
   203  		if err = r.Close(); err != nil {
   204  			t.Errorf("r.Close: %v", err)
   205  		}
   206  	}
   207  }
   208  
   209  // Test close on Read side during Read.
   210  func TestPipeReadClose2(t *testing.T) {
   211  	c := make(chan int, 1)
   212  	r, _ := Pipe()
   213  	go delayClose(t, r, c, pipeTest{})
   214  	n, err := r.Read(make([]byte, 64))
   215  	<-c
   216  	if n != 0 || err != ErrClosedPipe {
   217  		t.Errorf("read from closed pipe: %v, %v want %v, %v", n, err, 0, ErrClosedPipe)
   218  	}
   219  }
   220  
   221  // Test write after/before reader close.
   222  
   223  func TestPipeWriteClose(t *testing.T) {
   224  	for _, tt := range pipeTests {
   225  		c := make(chan int, 1)
   226  		r, w := Pipe()
   227  		if tt.async {
   228  			go delayClose(t, r, c, tt)
   229  		} else {
   230  			delayClose(t, r, c, tt)
   231  		}
   232  		n, err := WriteString(w, "hello, world")
   233  		<-c
   234  		expect := tt.err
   235  		if expect == nil {
   236  			expect = ErrClosedPipe
   237  		}
   238  		if err != expect {
   239  			t.Errorf("write on closed pipe: %v want %v", err, expect)
   240  		}
   241  		if n != 0 {
   242  			t.Errorf("write on closed pipe returned %d", n)
   243  		}
   244  		if err = w.Close(); err != nil {
   245  			t.Errorf("w.Close: %v", err)
   246  		}
   247  	}
   248  }
   249  
   250  func TestWriteEmpty(t *testing.T) {
   251  	r, w := Pipe()
   252  	go func() {
   253  		w.Write([]byte{})
   254  		w.Close()
   255  	}()
   256  	var b [2]byte
   257  	ReadFull(r, b[0:2])
   258  	r.Close()
   259  }
   260  
   261  func TestWriteNil(t *testing.T) {
   262  	r, w := Pipe()
   263  	go func() {
   264  		w.Write(nil)
   265  		w.Close()
   266  	}()
   267  	var b [2]byte
   268  	ReadFull(r, b[0:2])
   269  	r.Close()
   270  }
   271  
   272  func TestWriteAfterWriterClose(t *testing.T) {
   273  	r, w := Pipe()
   274  
   275  	done := make(chan bool)
   276  	var writeErr error
   277  	go func() {
   278  		_, err := w.Write([]byte("hello"))
   279  		if err != nil {
   280  			t.Errorf("got error: %q; expected none", err)
   281  		}
   282  		w.Close()
   283  		_, writeErr = w.Write([]byte("world"))
   284  		done <- true
   285  	}()
   286  
   287  	buf := make([]byte, 100)
   288  	var result string
   289  	n, err := ReadFull(r, buf)
   290  	if err != nil && err != ErrUnexpectedEOF {
   291  		t.Fatalf("got: %q; want: %q", err, ErrUnexpectedEOF)
   292  	}
   293  	result = string(buf[0:n])
   294  	<-done
   295  
   296  	if result != "hello" {
   297  		t.Errorf("got: %q; want: %q", result, "hello")
   298  	}
   299  	if writeErr != ErrClosedPipe {
   300  		t.Errorf("got: %q; want: %q", writeErr, ErrClosedPipe)
   301  	}
   302  }