github.com/spotify/syslog-redirector-golang@v0.0.0-20140320174030-4859f03d829a/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 }