reconnect p2p/ tests
Juan Batiz-Benet committed
Jan 7, 2015 at 18:56 UTC
84a2a591556e8fe724649e882832581d0b5d53cb
2 files changed
+236
p2p/test/reconnects/reconnect.go
new
+2
@@ -0,0 +1,2 @@
1
+// Package reconnect tests connect -> disconnect -> reconnect works
2
+package reconnect
p2p/test/reconnects/reconnect_test.go
new
+234
@@ -0,0 +1,234 @@
1
+package reconnect
2
+
3
+import (
4
+ crand "crypto/rand"
5
+ "io"
6
+ "math/rand"
7
+ "sync"
8
+ "testing"
9
+ "time"
10
+
11
+ host "github.com/jbenet/go-ipfs/p2p/host"
12
+ inet "github.com/jbenet/go-ipfs/p2p/net"
13
+ swarm "github.com/jbenet/go-ipfs/p2p/net/swarm"
14
+ protocol "github.com/jbenet/go-ipfs/p2p/protocol"
15
+ testutil "github.com/jbenet/go-ipfs/p2p/test/util"
16
+ eventlog "github.com/jbenet/go-ipfs/util/eventlog"
17
+
18
+ context "github.com/jbenet/go-ipfs/Godeps/_workspace/src/code.google.com/p/go.net/context"
19
+ ps "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-peerstream"
20
+)
21
+
22
+func init() {
23
+ // change the garbage collect timeout for testing.
24
+ ps.GarbageCollectTimeout = 10 * time.Millisecond
25
+}
26
+
27
+var log = eventlog.Logger("reconnect")
28
+
29
+func EchoStreamHandler(stream inet.Stream) {
30
+ c := stream.Conn()
31
+ log.Debugf("%s echoing %s", c.LocalPeer(), c.RemotePeer())
32
+ go func() {
33
+ defer stream.Close()
34
+ io.Copy(stream, stream)
35
+ }()
36
+}
37
+
38
+type sendChans struct {
39
+ send chan struct{}
40
+ sent chan struct{}
41
+ read chan struct{}
42
+ close_ chan struct{}
43
+ closed chan struct{}
44
+}
45
+
46
+func newSendChans() sendChans {
47
+ return sendChans{
48
+ send: make(chan struct{}),
49
+ sent: make(chan struct{}),
50
+ read: make(chan struct{}),
51
+ close_: make(chan struct{}),
52
+ closed: make(chan struct{}),
53
+ }
54
+}
55
+
56
+func newSender() (chan sendChans, func(s inet.Stream)) {
57
+ scc := make(chan sendChans)
58
+ return scc, func(s inet.Stream) {
59
+ sc := newSendChans()
60
+ scc <- sc
61
+
62
+ defer func() {
63
+ s.Close()
64
+ sc.closed <- struct{}{}
65
+ }()
66
+
67
+ buf := make([]byte, 65536)
68
+ buf2 := make([]byte, 65536)
69
+ crand.Read(buf)
70
+
71
+ for {
72
+ select {
73
+ case <-sc.close_:
74
+ return
75
+ case <-sc.send:
76
+ }
77
+
78
+ // send a randomly sized subchunk
79
+ from := rand.Intn(len(buf) / 2)
80
+ to := rand.Intn(len(buf) / 2)
81
+ sendbuf := buf[from : from+to]
82
+
83
+ log.Debugf("sender sending %d bytes", len(sendbuf))
84
+ n, err := s.Write(sendbuf)
85
+ if err != nil {
86
+ log.Debug("sender error. exiting:", err)
87
+ return
88
+ }
89
+
90
+ log.Debugf("sender wrote %d bytes", n)
91
+ sc.sent <- struct{}{}
92
+
93
+ if n, err = io.ReadFull(s, buf2[:len(sendbuf)]); err != nil {
94
+ log.Debug("sender error. failed to read:", err)
95
+ return
96
+ }
97
+
98
+ log.Debugf("sender read %d bytes", n)
99
+ sc.read <- struct{}{}
100
+ }
101
+ }
102
+}
103
+
104
+// TestReconnect tests whether hosts are able to disconnect and reconnect.
105
+func TestReconnect2(t *testing.T) {
106
+ ctx := context.Background()
107
+ h1 := testutil.GenHostSwarm(t, ctx)
108
+ h2 := testutil.GenHostSwarm(t, ctx)
109
+ hosts := []host.Host{h1, h2}
110
+
111
+ h1.SetStreamHandler(protocol.TestingID, EchoStreamHandler)
112
+ h2.SetStreamHandler(protocol.TestingID, EchoStreamHandler)
113
+
114
+ rounds := 10
115
+ if testing.Short() {
116
+ rounds = 4
117
+ }
118
+ for i := 0; i < rounds; i++ {
119
+ log.Debugf("TestReconnect: %d/%d\n", i, rounds)
120
+ SubtestConnSendDisc(t, hosts)
121
+ }
122
+}
123
+
124
+// TestReconnect tests whether hosts are able to disconnect and reconnect.
125
+func TestReconnect5(t *testing.T) {
126
+ ctx := context.Background()
127
+ h1 := testutil.GenHostSwarm(t, ctx)
128
+ h2 := testutil.GenHostSwarm(t, ctx)
129
+ h3 := testutil.GenHostSwarm(t, ctx)
130
+ h4 := testutil.GenHostSwarm(t, ctx)
131
+ h5 := testutil.GenHostSwarm(t, ctx)
132
+ hosts := []host.Host{h1, h2, h3, h4, h5}
133
+
134
+ h1.SetStreamHandler(protocol.TestingID, EchoStreamHandler)
135
+ h2.SetStreamHandler(protocol.TestingID, EchoStreamHandler)
136
+ h3.SetStreamHandler(protocol.TestingID, EchoStreamHandler)
137
+ h4.SetStreamHandler(protocol.TestingID, EchoStreamHandler)
138
+ h5.SetStreamHandler(protocol.TestingID, EchoStreamHandler)
139
+
140
+ rounds := 10
141
+ if testing.Short() {
142
+ rounds = 4
143
+ }
144
+ for i := 0; i < rounds; i++ {
145
+ log.Debugf("TestReconnect: %d/%d\n", i, rounds)
146
+ SubtestConnSendDisc(t, hosts)
147
+ }
148
+}
149
+
150
+func SubtestConnSendDisc(t *testing.T, hosts []host.Host) {
151
+
152
+ ctx := context.Background()
153
+ numStreams := 3 * len(hosts)
154
+ numMsgs := 10
155
+
156
+ if testing.Short() {
157
+ numStreams = 5 * len(hosts)
158
+ numMsgs = 4
159
+ }
160
+
161
+ ss, sF := newSender()
162
+
163
+ for _, h1 := range hosts {
164
+ for _, h2 := range hosts {
165
+ if h1.ID() >= h2.ID() {
166
+ continue
167
+ }
168
+
169
+ h2pi := h2.Peerstore().PeerInfo(h2.ID())
170
+ log.Debugf("dialing %s", h2pi.Addrs)
171
+ if err := h1.Connect(ctx, h2pi); err != nil {
172
+ t.Fatalf("Failed to connect:", err)
173
+ }
174
+ }
175
+ }
176
+
177
+ var wg sync.WaitGroup
178
+ for i := 0; i < numStreams; i++ {
179
+ h1 := hosts[i%len(hosts)]
180
+ h2 := hosts[(i+1)%len(hosts)]
181
+ s, err := h1.NewStream(protocol.TestingID, h2.ID())
182
+ if err != nil {
183
+ t.Error(err)
184
+ }
185
+
186
+ wg.Add(1)
187
+ go func(j int) {
188
+ defer wg.Done()
189
+
190
+ go sF(s)
191
+ log.Debugf("getting handle %d", i)
192
+ sc := <-ss // wait to get handle.
193
+ log.Debugf("spawning worker %d", i)
194
+
195
+ for i := 0; i < numMsgs; i++ {
196
+ sc.send <- struct{}{}
197
+ <-sc.sent
198
+ log.Debugf("%d sent %d", j, i)
199
+ <-sc.read
200
+ log.Debugf("%d read %d", j, i)
201
+ }
202
+ sc.close_ <- struct{}{}
203
+ <-sc.closed
204
+ log.Debugf("closed %d", j)
205
+ }(i)
206
+ }
207
+ wg.Wait()
208
+
209
+ for i, h1 := range hosts {
210
+ log.Debugf("host %d has %d conns", i, len(h1.Network().Conns()))
211
+ }
212
+
213
+ for _, h1 := range hosts {
214
+ // close connection
215
+ cs := h1.Network().Conns()
216
+ for _, c := range cs {
217
+ sc := c.(*swarm.Conn)
218
+ if sc.LocalPeer() > sc.RemotePeer() {
219
+ continue // only close it on one side.
220
+ }
221
+
222
+ log.Debugf("closing: %s", sc.RawConn())
223
+ sc.Close()
224
+ }
225
+ }
226
+
227
+ <-time.After(20 * time.Millisecond)
228
+
229
+ for i, h := range hosts {
230
+ if len(h.Network().Conns()) > 0 {
231
+ t.Fatalf("host %d %s has %d conns! not zero.", i, h.ID(), len(h.Network().Conns()))
232
+ }
233
+ }
234
+}