OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [libgo/] [go/] [old/] [netchan/] [netchan_test.go] - Blame information for rev 747

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 747 jeremybenn
// 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
        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(250 * time.Millisecond)
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(500 * time.Millisecond)
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
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.