...
1
18
19
20 package testutils
21
22 import (
23 "errors"
24 "net"
25 "time"
26 )
27
28 var errClosed = errors.New("closed")
29
30 type pipeAddr struct{}
31
32 func (p pipeAddr) Network() string { return "pipe" }
33 func (p pipeAddr) String() string { return "pipe" }
34
35
36
37 type PipeListener struct {
38 c chan chan<- net.Conn
39 done chan struct{}
40 }
41
42
43 func NewPipeListener() *PipeListener {
44 return &PipeListener{
45 c: make(chan chan<- net.Conn),
46 done: make(chan struct{}),
47 }
48 }
49
50
51 func (p *PipeListener) Accept() (net.Conn, error) {
52 var connChan chan<- net.Conn
53 select {
54 case <-p.done:
55 return nil, errClosed
56 case connChan = <-p.c:
57 select {
58 case <-p.done:
59 close(connChan)
60 return nil, errClosed
61 default:
62 }
63 }
64 c1, c2 := net.Pipe()
65 connChan <- c1
66 close(connChan)
67 return c2, nil
68 }
69
70
71 func (p *PipeListener) Close() error {
72 close(p.done)
73 return nil
74 }
75
76
77 func (p *PipeListener) Addr() net.Addr {
78 return pipeAddr{}
79 }
80
81
82 func (p *PipeListener) Dialer() func(string, time.Duration) (net.Conn, error) {
83 return func(string, time.Duration) (net.Conn, error) {
84 connChan := make(chan net.Conn)
85 select {
86 case p.c <- connChan:
87 case <-p.done:
88 return nil, errClosed
89 }
90 conn, ok := <-connChan
91 if !ok {
92 return nil, errClosed
93 }
94 return conn, nil
95 }
96 }
97
View as plain text