github.com/graybobo/golang.org-package-offline-cache@v0.0.0-20200626051047-6608995c132f/x/exp/old/netchan/netchan_test.go (about) 1 // Copyright 2010 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 netchan 6 7 import ( 8 "net" 9 "strings" 10 "testing" 11 "time" 12 ) 13 14 const count = 10 // number of items in most tests 15 const closeCount = 5 // number of items when sender closes early 16 17 const base = 23 18 19 func exportSend(exp *Exporter, n int, t *testing.T, done chan bool) { 20 ch := make(chan int) 21 err := exp.Export("exportedSend", ch, Send) 22 if err != nil { 23 t.Fatal("exportSend:", err) 24 } 25 go func() { 26 for i := 0; i < n; i++ { 27 ch <- base + i 28 } 29 close(ch) 30 if done != nil { 31 done <- true 32 } 33 }() 34 } 35 36 func exportReceive(exp *Exporter, t *testing.T, expDone chan bool) { 37 ch := make(chan int) 38 err := exp.Export("exportedRecv", ch, Recv) 39 expDone <- true 40 if err != nil { 41 t.Fatal("exportReceive:", err) 42 } 43 for i := 0; i < count; i++ { 44 v, ok := <-ch 45 if !ok { 46 if i != closeCount { 47 t.Errorf("exportReceive expected close at %d; got one at %d", closeCount, i) 48 } 49 break 50 } 51 if v != base+i { 52 t.Errorf("export Receive: bad value: expected %d+%d=%d; got %d", base, i, base+i, v) 53 } 54 } 55 } 56 57 func importSend(imp *Importer, n int, t *testing.T, done chan bool) { 58 ch := make(chan int) 59 err := imp.ImportNValues("exportedRecv", ch, Send, 3, -1) 60 if err != nil { 61 t.Fatal("importSend:", err) 62 } 63 go func() { 64 for i := 0; i < n; i++ { 65 ch <- base + i 66 } 67 close(ch) 68 if done != nil { 69 done <- true 70 } 71 }() 72 } 73 74 func importReceive(imp *Importer, t *testing.T, done chan bool) { 75 ch := make(chan int) 76 err := imp.ImportNValues("exportedSend", ch, Recv, 3, count) 77 if err != nil { 78 t.Fatal("importReceive:", err) 79 } 80 for i := 0; i < count; i++ { 81 v, ok := <-ch 82 if !ok { 83 if i != closeCount { 84 t.Errorf("importReceive expected close at %d; got one at %d", closeCount, i) 85 } 86 break 87 } 88 if v != base+i { 89 t.Errorf("importReceive: bad value: expected %d+%d=%d; got %+d", base, i, base+i, v) 90 } 91 } 92 if done != nil { 93 done <- true 94 } 95 } 96 97 func TestExportSendImportReceive(t *testing.T) { 98 exp, imp := pair(t) 99 exportSend(exp, count, t, nil) 100 importReceive(imp, t, nil) 101 } 102 103 func TestExportReceiveImportSend(t *testing.T) { 104 exp, imp := pair(t) 105 expDone := make(chan bool) 106 done := make(chan bool) 107 go func() { 108 exportReceive(exp, t, expDone) 109 done <- true 110 }() 111 <-expDone 112 importSend(imp, count, t, nil) 113 <-done 114 } 115 116 func TestClosingExportSendImportReceive(t *testing.T) { 117 exp, imp := pair(t) 118 exportSend(exp, closeCount, t, nil) 119 importReceive(imp, t, nil) 120 } 121 122 func TestClosingImportSendExportReceive(t *testing.T) { 123 exp, imp := pair(t) 124 expDone := make(chan bool) 125 done := make(chan bool) 126 go func() { 127 exportReceive(exp, t, expDone) 128 done <- true 129 }() 130 <-expDone 131 importSend(imp, closeCount, t, nil) 132 <-done 133 } 134 135 func TestErrorForIllegalChannel(t *testing.T) { 136 exp, imp := pair(t) 137 // Now export a channel. 138 ch := make(chan int, 1) 139 err := exp.Export("aChannel", ch, Send) 140 if err != nil { 141 t.Fatal("export:", err) 142 } 143 ch <- 1234 144 close(ch) 145 // Now try to import a different channel. 146 ch = make(chan int) 147 err = imp.Import("notAChannel", ch, Recv, 1) 148 if err != nil { 149 t.Fatal("import:", err) 150 } 151 // Expect an error now. Start a timeout. 152 timeout := make(chan bool, 1) // buffered so closure will not hang around. 153 go func() { 154 time.Sleep(10 * time.Second) // very long, to give even really slow machines a chance. 155 timeout <- true 156 }() 157 select { 158 case err = <-imp.Errors(): 159 if strings.Index(err.Error(), "no such channel") < 0 { 160 t.Error("wrong error for nonexistent channel:", err) 161 } 162 case <-timeout: 163 t.Error("import of nonexistent channel did not receive an error") 164 } 165 } 166 167 // Not a great test but it does at least invoke Drain. 168 func TestExportDrain(t *testing.T) { 169 exp, imp := pair(t) 170 done := make(chan bool) 171 go func() { 172 exportSend(exp, closeCount, t, nil) 173 done <- true 174 }() 175 <-done 176 go importReceive(imp, t, done) 177 exp.Drain(0) 178 <-done 179 } 180 181 // Not a great test but it does at least invoke Drain. 182 func TestImportDrain(t *testing.T) { 183 exp, imp := pair(t) 184 expDone := make(chan bool) 185 go exportReceive(exp, t, expDone) 186 <-expDone 187 importSend(imp, closeCount, t, nil) 188 imp.Drain(0) 189 } 190 191 // Not a great test but it does at least invoke Sync. 192 func TestExportSync(t *testing.T) { 193 exp, imp := pair(t) 194 done := make(chan bool) 195 exportSend(exp, closeCount, t, nil) 196 go importReceive(imp, t, done) 197 exp.Sync(0) 198 <-done 199 } 200 201 // Test hanging up the send side of an export. 202 // TODO: test hanging up the receive side of an export. 203 func TestExportHangup(t *testing.T) { 204 exp, imp := pair(t) 205 ech := make(chan int) 206 err := exp.Export("exportedSend", ech, Send) 207 if err != nil { 208 t.Fatal("export:", err) 209 } 210 // Prepare to receive two values. We'll actually deliver only one. 211 ich := make(chan int) 212 err = imp.ImportNValues("exportedSend", ich, Recv, 1, 2) 213 if err != nil { 214 t.Fatal("import exportedSend:", err) 215 } 216 // Send one value, receive it. 217 const Value = 1234 218 ech <- Value 219 v := <-ich 220 if v != Value { 221 t.Fatal("expected", Value, "got", v) 222 } 223 // Now hang up the channel. Importer should see it close. 224 exp.Hangup("exportedSend") 225 v, ok := <-ich 226 if ok { 227 t.Fatal("expected channel to be closed; got value", v) 228 } 229 } 230 231 // Test hanging up the send side of an import. 232 // TODO: test hanging up the receive side of an import. 233 func TestImportHangup(t *testing.T) { 234 exp, imp := pair(t) 235 ech := make(chan int) 236 err := exp.Export("exportedRecv", ech, Recv) 237 if err != nil { 238 t.Fatal("export:", err) 239 } 240 // Prepare to Send two values. We'll actually deliver only one. 241 ich := make(chan int) 242 err = imp.ImportNValues("exportedRecv", ich, Send, 1, 2) 243 if err != nil { 244 t.Fatal("import exportedRecv:", err) 245 } 246 // Send one value, receive it. 247 const Value = 1234 248 ich <- Value 249 v := <-ech 250 if v != Value { 251 t.Fatal("expected", Value, "got", v) 252 } 253 // Now hang up the channel. Exporter should see it close. 254 imp.Hangup("exportedRecv") 255 v, ok := <-ech 256 if ok { 257 t.Fatal("expected channel to be closed; got value", v) 258 } 259 } 260 261 // loop back exportedRecv to exportedSend, 262 // but receive a value from ctlch before starting the loop. 263 func exportLoopback(exp *Exporter, t *testing.T) { 264 inch := make(chan int) 265 if err := exp.Export("exportedRecv", inch, Recv); err != nil { 266 t.Fatal("exportRecv") 267 } 268 269 outch := make(chan int) 270 if err := exp.Export("exportedSend", outch, Send); err != nil { 271 t.Fatal("exportSend") 272 } 273 274 ctlch := make(chan int) 275 if err := exp.Export("exportedCtl", ctlch, Recv); err != nil { 276 t.Fatal("exportRecv") 277 } 278 279 go func() { 280 <-ctlch 281 for i := 0; i < count; i++ { 282 x := <-inch 283 if x != base+i { 284 t.Errorf("exportLoopback expected %d; got %d", i, x) 285 } 286 outch <- x 287 } 288 }() 289 } 290 291 // This test checks that channel operations can proceed 292 // even when other concurrent operations are blocked. 293 func TestIndependentSends(t *testing.T) { 294 if testing.Short() { 295 t.Logf("disabled test during -short") 296 return 297 } 298 exp, imp := pair(t) 299 300 exportLoopback(exp, t) 301 302 importSend(imp, count, t, nil) 303 done := make(chan bool) 304 go importReceive(imp, t, done) 305 306 // wait for export side to try to deliver some values. 307 time.Sleep(250 * time.Millisecond) 308 309 ctlch := make(chan int) 310 if err := imp.ImportNValues("exportedCtl", ctlch, Send, 1, 1); err != nil { 311 t.Fatal("importSend:", err) 312 } 313 ctlch <- 0 314 315 <-done 316 } 317 318 // This test cross-connects a pair of exporter/importer pairs. 319 type value struct { 320 I int 321 Source string 322 } 323 324 func TestCrossConnect(t *testing.T) { 325 e1, i1 := pair(t) 326 e2, i2 := pair(t) 327 328 crossExport(e1, e2, t) 329 crossImport(i1, i2, t) 330 } 331 332 // Export side of cross-traffic. 333 func crossExport(e1, e2 *Exporter, t *testing.T) { 334 s := make(chan value) 335 err := e1.Export("exportedSend", s, Send) 336 if err != nil { 337 t.Fatal("exportSend:", err) 338 } 339 340 r := make(chan value) 341 err = e2.Export("exportedReceive", r, Recv) 342 if err != nil { 343 t.Fatal("exportReceive:", err) 344 } 345 346 go crossLoop("export", s, r, t) 347 } 348 349 // Import side of cross-traffic. 350 func crossImport(i1, i2 *Importer, t *testing.T) { 351 s := make(chan value) 352 err := i2.Import("exportedReceive", s, Send, 2) 353 if err != nil { 354 t.Fatal("import of exportedReceive:", err) 355 } 356 357 r := make(chan value) 358 err = i1.Import("exportedSend", r, Recv, 2) 359 if err != nil { 360 t.Fatal("import of exported Send:", err) 361 } 362 363 crossLoop("import", s, r, t) 364 } 365 366 // Cross-traffic: send and receive 'count' numbers. 367 func crossLoop(name string, s, r chan value, t *testing.T) { 368 for si, ri := 0, 0; si < count && ri < count; { 369 select { 370 case s <- value{si, name}: 371 si++ 372 case v := <-r: 373 if v.I != ri { 374 t.Errorf("loop: bad value: expected %d, hello; got %+v", ri, v) 375 } 376 ri++ 377 } 378 } 379 } 380 381 const flowCount = 100 382 383 // test flow control from exporter to importer. 384 func TestExportFlowControl(t *testing.T) { 385 if testing.Short() { 386 t.Logf("disabled test during -short") 387 return 388 } 389 exp, imp := pair(t) 390 391 sendDone := make(chan bool, 1) 392 exportSend(exp, flowCount, t, sendDone) 393 394 ch := make(chan int) 395 err := imp.ImportNValues("exportedSend", ch, Recv, 20, -1) 396 if err != nil { 397 t.Fatal("importReceive:", err) 398 } 399 400 testFlow(sendDone, ch, flowCount, t) 401 } 402 403 // test flow control from importer to exporter. 404 func TestImportFlowControl(t *testing.T) { 405 if testing.Short() { 406 t.Logf("disabled test during -short") 407 return 408 } 409 exp, imp := pair(t) 410 411 ch := make(chan int) 412 err := exp.Export("exportedRecv", ch, Recv) 413 if err != nil { 414 t.Fatal("importReceive:", err) 415 } 416 417 sendDone := make(chan bool, 1) 418 importSend(imp, flowCount, t, sendDone) 419 testFlow(sendDone, ch, flowCount, t) 420 } 421 422 func testFlow(sendDone chan bool, ch <-chan int, N int, t *testing.T) { 423 go func() { 424 time.Sleep(500 * time.Millisecond) 425 sendDone <- false 426 }() 427 428 if <-sendDone { 429 t.Fatal("send did not block") 430 } 431 n := 0 432 for i := range ch { 433 t.Log("after blocking, got value ", i) 434 n++ 435 } 436 if n != N { 437 t.Fatalf("expected %d values; got %d", N, n) 438 } 439 } 440 441 func pair(t *testing.T) (*Exporter, *Importer) { 442 c0, c1 := net.Pipe() 443 exp := NewExporter() 444 go exp.ServeConn(c0) 445 imp := NewImporter(c1) 446 return exp, imp 447 }