summaryrefslogtreecommitdiff
path: root/src/pkg/netchan/netchan_test.go
diff options
context:
space:
mode:
Diffstat (limited to 'src/pkg/netchan/netchan_test.go')
-rw-r--r--src/pkg/netchan/netchan_test.go329
1 files changed, 303 insertions, 26 deletions
diff --git a/src/pkg/netchan/netchan_test.go b/src/pkg/netchan/netchan_test.go
index 6b5c67c3c..766c4c474 100644
--- a/src/pkg/netchan/netchan_test.go
+++ b/src/pkg/netchan/netchan_test.go
@@ -4,38 +4,67 @@
package netchan
-import "testing"
+import (
+ "strings"
+ "testing"
+ "time"
+)
const count = 10 // number of items in most tests
const closeCount = 5 // number of items when sender closes early
+const base = 23
+
func exportSend(exp *Exporter, n int, t *testing.T) {
ch := make(chan int)
err := exp.Export("exportedSend", ch, Send)
if err != nil {
t.Fatal("exportSend:", err)
}
- for i := 0; i < n; i++ {
- ch <- 23+i
- }
- close(ch)
+ go func() {
+ for i := 0; i < n; i++ {
+ ch <- base+i
+ }
+ close(ch)
+ }()
}
-func exportReceive(exp *Exporter, t *testing.T) {
+func exportReceive(exp *Exporter, t *testing.T, expDone chan bool) {
ch := make(chan int)
err := exp.Export("exportedRecv", ch, Recv)
+ expDone <- true
if err != nil {
t.Fatal("exportReceive:", err)
}
for i := 0; i < count; i++ {
v := <-ch
- if v != 45+i {
- t.Errorf("export Receive: bad value: expected 4%d; got %d", 45+i, v)
+ if closed(ch) {
+ if i != closeCount {
+ t.Errorf("exportReceive expected close at %d; got one at %d", closeCount, i)
+ }
+ break
+ }
+ if v != base+i {
+ t.Errorf("export Receive: bad value: expected %d+%d=%d; got %d", base, i, base+i, v)
}
}
}
-func importReceive(imp *Importer, t *testing.T) {
+func importSend(imp *Importer, n int, t *testing.T) {
+ ch := make(chan int)
+ err := imp.ImportNValues("exportedRecv", ch, Send, count)
+ if err != nil {
+ t.Fatal("importSend:", err)
+ }
+ go func() {
+ for i := 0; i < n; i++ {
+ ch <- base+i
+ }
+ close(ch)
+ }()
+}
+
+func importReceive(imp *Importer, t *testing.T, done chan bool) {
ch := make(chan int)
err := imp.ImportNValues("exportedSend", ch, Recv, count)
if err != nil {
@@ -45,28 +74,33 @@ func importReceive(imp *Importer, t *testing.T) {
v := <-ch
if closed(ch) {
if i != closeCount {
- t.Errorf("expected close at %d; got one at %d\n", closeCount, i)
+ t.Errorf("importReceive expected close at %d; got one at %d", closeCount, i)
}
break
}
if v != 23+i {
- t.Errorf("importReceive: bad value: expected %d; got %+d", 23+i, v)
+ t.Errorf("importReceive: bad value: expected %d+%d=%d; got %+d", base, i, base+i, v)
}
}
+ if done != nil {
+ done <- true
+ }
}
-func importSend(imp *Importer, t *testing.T) {
- ch := make(chan int)
- err := imp.ImportNValues("exportedRecv", ch, Send, count)
+func TestExportSendImportReceive(t *testing.T) {
+ exp, err := NewExporter("tcp", "127.0.0.1:0")
if err != nil {
- t.Fatal("importSend:", err)
+ t.Fatal("new exporter:", err)
}
- for i := 0; i < count; i++ {
- ch <- 45+i
+ imp, err := NewImporter("tcp", exp.Addr().String())
+ if err != nil {
+ t.Fatal("new importer:", err)
}
+ exportSend(exp, count, t)
+ importReceive(imp, t, nil)
}
-func TestExportSendImportReceive(t *testing.T) {
+func TestExportReceiveImportSend(t *testing.T) {
exp, err := NewExporter("tcp", "127.0.0.1:0")
if err != nil {
t.Fatal("new exporter:", err)
@@ -75,11 +109,18 @@ func TestExportSendImportReceive(t *testing.T) {
if err != nil {
t.Fatal("new importer:", err)
}
- go exportSend(exp, count, t)
- importReceive(imp, t)
+ expDone := make(chan bool)
+ done := make(chan bool)
+ go func() {
+ exportReceive(exp, t, expDone)
+ done <- true
+ }()
+ <-expDone
+ importSend(imp, count, t)
+ <-done
}
-func TestExportReceiveImportSend(t *testing.T) {
+func TestClosingExportSendImportReceive(t *testing.T) {
exp, err := NewExporter("tcp", "127.0.0.1:0")
if err != nil {
t.Fatal("new exporter:", err)
@@ -88,11 +129,92 @@ func TestExportReceiveImportSend(t *testing.T) {
if err != nil {
t.Fatal("new importer:", err)
}
- go importSend(imp, t)
- exportReceive(exp, t)
+ exportSend(exp, closeCount, t)
+ importReceive(imp, t, nil)
}
-func TestClosingExportSendImportReceive(t *testing.T) {
+func TestClosingImportSendExportReceive(t *testing.T) {
+ exp, err := NewExporter("tcp", "127.0.0.1:0")
+ if err != nil {
+ t.Fatal("new exporter:", err)
+ }
+ imp, err := NewImporter("tcp", exp.Addr().String())
+ if err != nil {
+ t.Fatal("new importer:", err)
+ }
+ expDone := make(chan bool)
+ done := make(chan bool)
+ go func() {
+ exportReceive(exp, t, expDone)
+ done <- true
+ }()
+ <-expDone
+ importSend(imp, closeCount, t)
+ <-done
+}
+
+func TestErrorForIllegalChannel(t *testing.T) {
+ exp, err := NewExporter("tcp", "127.0.0.1:0")
+ if err != nil {
+ t.Fatal("new exporter:", err)
+ }
+ imp, err := NewImporter("tcp", exp.Addr().String())
+ if err != nil {
+ t.Fatal("new importer:", err)
+ }
+ // Now export a channel.
+ ch := make(chan int, 1)
+ err = exp.Export("aChannel", ch, Send)
+ if err != nil {
+ t.Fatal("export:", err)
+ }
+ ch <- 1234
+ close(ch)
+ // Now try to import a different channel.
+ ch = make(chan int)
+ err = imp.Import("notAChannel", ch, Recv)
+ if err != nil {
+ t.Fatal("import:", err)
+ }
+ // Expect an error now. Start a timeout.
+ timeout := make(chan bool, 1) // buffered so closure will not hang around.
+ go func() {
+ time.Sleep(10e9) // very long, to give even really slow machines a chance.
+ timeout <- true
+ }()
+ select {
+ case err = <-imp.Errors():
+ if strings.Index(err.String(), "no such channel") < 0 {
+ t.Error("wrong error for nonexistent channel:", err)
+ }
+ case <-timeout:
+ t.Error("import of nonexistent channel did not receive an error")
+ }
+}
+
+// Not a great test but it does at least invoke Drain.
+func TestExportDrain(t *testing.T) {
+ exp, err := NewExporter("tcp", "127.0.0.1:0")
+ if err != nil {
+ t.Fatal("new exporter:", err)
+ }
+ imp, err := NewImporter("tcp", exp.Addr().String())
+ if err != nil {
+ t.Fatal("new importer:", err)
+ }
+ done := make(chan bool)
+ go func() {
+ exportSend(exp, closeCount, t)
+ done <- true
+ }()
+ <-done
+ go importReceive(imp, t, done)
+ exp.Drain(0)
+ <-done
+}
+
+// Not a great test but it does at least invoke Sync.
+func TestExportSync(t *testing.T) {
exp, err := NewExporter("tcp", "127.0.0.1:0")
if err != nil {
t.Fatal("new exporter:", err)
@@ -101,6 +223,161 @@ func TestClosingExportSendImportReceive(t *testing.T) {
if err != nil {
t.Fatal("new importer:", err)
}
- go exportSend(exp, closeCount, t)
- importReceive(imp, t)
+ done := make(chan bool)
+ exportSend(exp, closeCount, t)
+ go importReceive(imp, t, done)
+ exp.Sync(0)
+ <-done
+}
+
+// Test hanging up the send side of an export.
+// TODO: test hanging up the receive side of an export.
+func TestExportHangup(t *testing.T) {
+ exp, err := NewExporter("tcp", "127.0.0.1:0")
+ if err != nil {
+ t.Fatal("new exporter:", err)
+ }
+ imp, err := NewImporter("tcp", exp.Addr().String())
+ if err != nil {
+ t.Fatal("new importer:", err)
+ }
+ ech := make(chan int)
+ err = exp.Export("exportedSend", ech, Send)
+ if err != nil {
+ t.Fatal("export:", err)
+ }
+ // Prepare to receive two values. We'll actually deliver only one.
+ ich := make(chan int)
+ err = imp.ImportNValues("exportedSend", ich, Recv, 2)
+ if err != nil {
+ t.Fatal("import exportedSend:", err)
+ }
+ // Send one value, receive it.
+ const Value = 1234
+ ech <- Value
+ v := <-ich
+ if v != Value {
+ t.Fatal("expected", Value, "got", v)
+ }
+ // Now hang up the channel. Importer should see it close.
+ exp.Hangup("exportedSend")
+ v = <-ich
+ if !closed(ich) {
+ t.Fatal("expected channel to be closed; got value", v)
+ }
+}
+
+// Test hanging up the send side of an import.
+// TODO: test hanging up the receive side of an import.
+func TestImportHangup(t *testing.T) {
+ exp, err := NewExporter("tcp", "127.0.0.1:0")
+ if err != nil {
+ t.Fatal("new exporter:", err)
+ }
+ imp, err := NewImporter("tcp", exp.Addr().String())
+ if err != nil {
+ t.Fatal("new importer:", err)
+ }
+ ech := make(chan int)
+ err = exp.Export("exportedRecv", ech, Recv)
+ if err != nil {
+ t.Fatal("export:", err)
+ }
+ // Prepare to Send two values. We'll actually deliver only one.
+ ich := make(chan int)
+ err = imp.ImportNValues("exportedRecv", ich, Send, 2)
+ if err != nil {
+ t.Fatal("import exportedRecv:", err)
+ }
+ // Send one value, receive it.
+ const Value = 1234
+ ich <- Value
+ v := <-ech
+ if v != Value {
+ t.Fatal("expected", Value, "got", v)
+ }
+ // Now hang up the channel. Exporter should see it close.
+ imp.Hangup("exportedRecv")
+ v = <-ech
+ if !closed(ech) {
+ t.Fatal("expected channel to be closed; got value", v)
+ }
+}
+
+// This test cross-connects a pair of exporter/importer pairs.
+type value struct {
+ i int
+ source string
+}
+
+func TestCrossConnect(t *testing.T) {
+ e1, err := NewExporter("tcp", "127.0.0.1:0")
+ if err != nil {
+ t.Fatal("new exporter:", err)
+ }
+ i1, err := NewImporter("tcp", e1.Addr().String())
+ if err != nil {
+ t.Fatal("new importer:", err)
+ }
+
+ e2, err := NewExporter("tcp", "127.0.0.1:0")
+ if err != nil {
+ t.Fatal("new exporter:", err)
+ }
+ i2, err := NewImporter("tcp", e2.Addr().String())
+ if err != nil {
+ t.Fatal("new importer:", err)
+ }
+
+ go crossExport(e1, e2, t)
+ crossImport(i1, i2, t)
+}
+
+// Export side of cross-traffic.
+func crossExport(e1, e2 *Exporter, t *testing.T) {
+ s := make(chan value)
+ err := e1.Export("exportedSend", s, Send)
+ if err != nil {
+ t.Fatal("exportSend:", err)
+ }
+
+ r := make(chan value)
+ err = e2.Export("exportedReceive", r, Recv)
+ if err != nil {
+ t.Fatal("exportReceive:", err)
+ }
+
+ crossLoop("export", s, r, t)
+}
+
+// Import side of cross-traffic.
+func crossImport(i1, i2 *Importer, t *testing.T) {
+ s := make(chan value)
+ err := i2.Import("exportedReceive", s, Send)
+ if err != nil {
+ t.Fatal("import of exportedReceive:", err)
+ }
+
+ r := make(chan value)
+ err = i1.Import("exportedSend", r, Recv)
+ if err != nil {
+ t.Fatal("import of exported Send:", err)
+ }
+
+ crossLoop("import", s, r, t)
+}
+
+// Cross-traffic: send and receive 'count' numbers.
+func crossLoop(name string, s, r chan value, t *testing.T) {
+ for si, ri := 0, 0; si < count && ri < count; {
+ select {
+ case s <- value{si, name}:
+ si++
+ case v := <-r:
+ if v.i != ri {
+ t.Errorf("loop: bad value: expected %d, hello; got %+v", ri, v)
+ }
+ ri++
+ }
+ }
}