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.
14 const count = 10 // number of items in most tests
15 const closeCount = 5 // number of items when sender closes early
19 func exportSend(exp *Exporter, n int, t *testing.T, done chan bool) {
21 err := exp.Export("exportedSend", ch, Send)
23 t.Fatal("exportSend:", err)
26 for i := 0; i < n; i++ {
36 func exportReceive(exp *Exporter, t *testing.T, expDone chan bool) {
38 err := exp.Export("exportedRecv", ch, Recv)
41 t.Fatal("exportReceive:", err)
43 for i := 0; i < count; i++ {
47 t.Errorf("exportReceive expected close at %d; got one at %d", closeCount, i)
52 t.Errorf("export Receive: bad value: expected %d+%d=%d; got %d", base, i, base+i, v)
57 func importSend(imp *Importer, n int, t *testing.T, done chan bool) {
59 err := imp.ImportNValues("exportedRecv", ch, Send, 3, -1)
61 t.Fatal("importSend:", err)
64 for i := 0; i < n; i++ {
74 func importReceive(imp *Importer, t *testing.T, done chan bool) {
76 err := imp.ImportNValues("exportedSend", ch, Recv, 3, count)
78 t.Fatal("importReceive:", err)
80 for i := 0; i < count; i++ {
84 t.Errorf("importReceive expected close at %d; got one at %d", closeCount, i)
89 t.Errorf("importReceive: bad value: expected %d+%d=%d; got %+d", base, i, base+i, v)
97 func TestExportSendImportReceive(t *testing.T) {
99 exportSend(exp, count, t, nil)
100 importReceive(imp, t, nil)
103 func TestExportReceiveImportSend(t *testing.T) {
105 expDone := make(chan bool)
106 done := make(chan bool)
108 exportReceive(exp, t, expDone)
112 importSend(imp, count, t, nil)
116 func TestClosingExportSendImportReceive(t *testing.T) {
118 exportSend(exp, closeCount, t, nil)
119 importReceive(imp, t, nil)
122 func TestClosingImportSendExportReceive(t *testing.T) {
124 expDone := make(chan bool)
125 done := make(chan bool)
127 exportReceive(exp, t, expDone)
131 importSend(imp, closeCount, t, nil)
135 func TestErrorForIllegalChannel(t *testing.T) {
137 // Now export a channel.
138 ch := make(chan int, 1)
139 err := exp.Export("aChannel", ch, Send)
141 t.Fatal("export:", err)
145 // Now try to import a different channel.
147 err = imp.Import("notAChannel", ch, Recv, 1)
149 t.Fatal("import:", err)
151 // Expect an error now. Start a timeout.
152 timeout := make(chan bool, 1) // buffered so closure will not hang around.
154 time.Sleep(10e9) // very long, to give even really slow machines a chance.
158 case err = <-imp.Errors():
159 if strings.Index(err.Error(), "no such channel") < 0 {
160 t.Error("wrong error for nonexistent channel:", err)
163 t.Error("import of nonexistent channel did not receive an error")
167 // Not a great test but it does at least invoke Drain.
168 func TestExportDrain(t *testing.T) {
170 done := make(chan bool)
172 exportSend(exp, closeCount, t, nil)
176 go importReceive(imp, t, done)
181 // Not a great test but it does at least invoke Drain.
182 func TestImportDrain(t *testing.T) {
184 expDone := make(chan bool)
185 go exportReceive(exp, t, expDone)
187 importSend(imp, closeCount, t, nil)
191 // Not a great test but it does at least invoke Sync.
192 func TestExportSync(t *testing.T) {
194 done := make(chan bool)
195 exportSend(exp, closeCount, t, nil)
196 go importReceive(imp, t, done)
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) {
205 ech := make(chan int)
206 err := exp.Export("exportedSend", ech, Send)
208 t.Fatal("export:", err)
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)
214 t.Fatal("import exportedSend:", err)
216 // Send one value, receive it.
221 t.Fatal("expected", Value, "got", v)
223 // Now hang up the channel. Importer should see it close.
224 exp.Hangup("exportedSend")
227 t.Fatal("expected channel to be closed; got value", v)
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) {
235 ech := make(chan int)
236 err := exp.Export("exportedRecv", ech, Recv)
238 t.Fatal("export:", err)
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)
244 t.Fatal("import exportedRecv:", err)
246 // Send one value, receive it.
251 t.Fatal("expected", Value, "got", v)
253 // Now hang up the channel. Exporter should see it close.
254 imp.Hangup("exportedRecv")
257 t.Fatal("expected channel to be closed; got value", v)
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")
269 outch := make(chan int)
270 if err := exp.Export("exportedSend", outch, Send); err != nil {
271 t.Fatal("exportSend")
274 ctlch := make(chan int)
275 if err := exp.Export("exportedCtl", ctlch, Recv); err != nil {
276 t.Fatal("exportRecv")
281 for i := 0; i < count; i++ {
284 t.Errorf("exportLoopback expected %d; got %d", i, x)
291 // This test checks that channel operations can proceed
292 // even when other concurrent operations are blocked.
293 func TestIndependentSends(t *testing.T) {
296 exportLoopback(exp, t)
298 importSend(imp, count, t, nil)
299 done := make(chan bool)
300 go importReceive(imp, t, done)
302 // wait for export side to try to deliver some values.
305 ctlch := make(chan int)
306 if err := imp.ImportNValues("exportedCtl", ctlch, Send, 1, 1); err != nil {
307 t.Fatal("importSend:", err)
314 // This test cross-connects a pair of exporter/importer pairs.
320 func TestCrossConnect(t *testing.T) {
324 crossExport(e1, e2, t)
325 crossImport(i1, i2, t)
328 // Export side of cross-traffic.
329 func crossExport(e1, e2 *Exporter, t *testing.T) {
330 s := make(chan value)
331 err := e1.Export("exportedSend", s, Send)
333 t.Fatal("exportSend:", err)
336 r := make(chan value)
337 err = e2.Export("exportedReceive", r, Recv)
339 t.Fatal("exportReceive:", err)
342 go crossLoop("export", s, r, t)
345 // Import side of cross-traffic.
346 func crossImport(i1, i2 *Importer, t *testing.T) {
347 s := make(chan value)
348 err := i2.Import("exportedReceive", s, Send, 2)
350 t.Fatal("import of exportedReceive:", err)
353 r := make(chan value)
354 err = i1.Import("exportedSend", r, Recv, 2)
356 t.Fatal("import of exported Send:", err)
359 crossLoop("import", s, r, t)
362 // Cross-traffic: send and receive 'count' numbers.
363 func crossLoop(name string, s, r chan value, t *testing.T) {
364 for si, ri := 0, 0; si < count && ri < count; {
366 case s <- value{si, name}:
370 t.Errorf("loop: bad value: expected %d, hello; got %+v", ri, v)
377 const flowCount = 100
379 // test flow control from exporter to importer.
380 func TestExportFlowControl(t *testing.T) {
383 sendDone := make(chan bool, 1)
384 exportSend(exp, flowCount, t, sendDone)
387 err := imp.ImportNValues("exportedSend", ch, Recv, 20, -1)
389 t.Fatal("importReceive:", err)
392 testFlow(sendDone, ch, flowCount, t)
395 // test flow control from importer to exporter.
396 func TestImportFlowControl(t *testing.T) {
400 err := exp.Export("exportedRecv", ch, Recv)
402 t.Fatal("importReceive:", err)
405 sendDone := make(chan bool, 1)
406 importSend(imp, flowCount, t, sendDone)
407 testFlow(sendDone, ch, flowCount, t)
410 func testFlow(sendDone chan bool, ch <-chan int, N int, t *testing.T) {
417 t.Fatal("send did not block")
421 t.Log("after blocking, got value ", i)
425 t.Fatalf("expected %d values; got %d", N, n)
429 func pair(t *testing.T) (*Exporter, *Importer) {
433 imp := NewImporter(c1)