OSDN Git Service

Add sparc fmaf test.
[pf3gnuchains/gcc-fork.git] / libgo / go / old / netchan / netchan_test.go
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(10e9) // 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.String(), "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         exp, imp := pair(t)
295
296         exportLoopback(exp, t)
297
298         importSend(imp, count, t, nil)
299         done := make(chan bool)
300         go importReceive(imp, t, done)
301
302         // wait for export side to try to deliver some values.
303         time.Sleep(0.25e9)
304
305         ctlch := make(chan int)
306         if err := imp.ImportNValues("exportedCtl", ctlch, Send, 1, 1); err != nil {
307                 t.Fatal("importSend:", err)
308         }
309         ctlch <- 0
310
311         <-done
312 }
313
314 // This test cross-connects a pair of exporter/importer pairs.
315 type value struct {
316         I      int
317         Source string
318 }
319
320 func TestCrossConnect(t *testing.T) {
321         e1, i1 := pair(t)
322         e2, i2 := pair(t)
323
324         crossExport(e1, e2, t)
325         crossImport(i1, i2, t)
326 }
327
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)
332         if err != nil {
333                 t.Fatal("exportSend:", err)
334         }
335
336         r := make(chan value)
337         err = e2.Export("exportedReceive", r, Recv)
338         if err != nil {
339                 t.Fatal("exportReceive:", err)
340         }
341
342         go crossLoop("export", s, r, t)
343 }
344
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)
349         if err != nil {
350                 t.Fatal("import of exportedReceive:", err)
351         }
352
353         r := make(chan value)
354         err = i1.Import("exportedSend", r, Recv, 2)
355         if err != nil {
356                 t.Fatal("import of exported Send:", err)
357         }
358
359         crossLoop("import", s, r, t)
360 }
361
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; {
365                 select {
366                 case s <- value{si, name}:
367                         si++
368                 case v := <-r:
369                         if v.I != ri {
370                                 t.Errorf("loop: bad value: expected %d, hello; got %+v", ri, v)
371                         }
372                         ri++
373                 }
374         }
375 }
376
377 const flowCount = 100
378
379 // test flow control from exporter to importer.
380 func TestExportFlowControl(t *testing.T) {
381         exp, imp := pair(t)
382
383         sendDone := make(chan bool, 1)
384         exportSend(exp, flowCount, t, sendDone)
385
386         ch := make(chan int)
387         err := imp.ImportNValues("exportedSend", ch, Recv, 20, -1)
388         if err != nil {
389                 t.Fatal("importReceive:", err)
390         }
391
392         testFlow(sendDone, ch, flowCount, t)
393 }
394
395 // test flow control from importer to exporter.
396 func TestImportFlowControl(t *testing.T) {
397         exp, imp := pair(t)
398
399         ch := make(chan int)
400         err := exp.Export("exportedRecv", ch, Recv)
401         if err != nil {
402                 t.Fatal("importReceive:", err)
403         }
404
405         sendDone := make(chan bool, 1)
406         importSend(imp, flowCount, t, sendDone)
407         testFlow(sendDone, ch, flowCount, t)
408 }
409
410 func testFlow(sendDone chan bool, ch <-chan int, N int, t *testing.T) {
411         go func() {
412                 time.Sleep(0.5e9)
413                 sendDone <- false
414         }()
415
416         if <-sendDone {
417                 t.Fatal("send did not block")
418         }
419         n := 0
420         for i := range ch {
421                 t.Log("after blocking, got value ", i)
422                 n++
423         }
424         if n != N {
425                 t.Fatalf("expected %d values; got %d", N, n)
426         }
427 }
428
429 func pair(t *testing.T) (*Exporter, *Importer) {
430         c0, c1 := net.Pipe()
431         exp := NewExporter()
432         go exp.ServeConn(c0)
433         imp := NewImporter(c1)
434         return exp, imp
435 }