@cryptotaxi247 / kubo / commits / baf254123

p2p/net/swarm: extensive dial tests

Juan Batiz-Benet committed Jan 13, 2015 at 08:15 UTC baf254123786b7b91a1f5aa65f460bcbaf88bdd0
2 files changed +427 -43
p2p/net/swarm/dial_test.go new
+427
@@ -0,0 +1,427 @@
1 +package swarm
2 +
3 +import (
4 + "net"
5 + "sync"
6 + "testing"
7 + "time"
8 +
9 + addrutil "github.com/jbenet/go-ipfs/p2p/net/swarm/addr"
10 + peer "github.com/jbenet/go-ipfs/p2p/peer"
11 + testutil "github.com/jbenet/go-ipfs/util/testutil"
12 +
13 + context "github.com/jbenet/go-ipfs/Godeps/_workspace/src/code.google.com/p/go.net/context"
14 + ma "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-multiaddr"
15 + manet "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-multiaddr-net"
16 +)
17 +
18 +func acceptAndHang(l net.Listener) {
19 + conns := make([]net.Conn, 0, 10)
20 + for {
21 + c, err := l.Accept()
22 + if err != nil {
23 + break
24 + }
25 + if c != nil {
26 + conns = append(conns, c)
27 + }
28 + }
29 + for _, c := range conns {
30 + c.Close()
31 + }
32 +}
33 +
34 +func TestSimultDials(t *testing.T) {
35 + // t.Skip("skipping for another test")
36 + t.Parallel()
37 +
38 + ctx := context.Background()
39 + swarms := makeSwarms(ctx, t, 2)
40 +
41 + // connect everyone
42 + {
43 + var wg sync.WaitGroup
44 + connect := func(s *Swarm, dst peer.ID, addr ma.Multiaddr) {
45 + // copy for other peer
46 + log.Debugf("TestSimultOpen: connecting: %s --> %s (%s)", s.local, dst, addr)
47 + s.peers.AddAddress(dst, addr)
48 + if _, err := s.Dial(ctx, dst); err != nil {
49 + t.Fatal("error swarm dialing to peer", err)
50 + }
51 + wg.Done()
52 + }
53 +
54 + ifaceAddrs0, err := swarms[0].InterfaceListenAddresses()
55 + if err != nil {
56 + t.Fatal(err)
57 + }
58 + ifaceAddrs1, err := swarms[1].InterfaceListenAddresses()
59 + if err != nil {
60 + t.Fatal(err)
61 + }
62 +
63 + log.Info("Connecting swarms simultaneously.")
64 + for i := 0; i < 10; i++ { // connect 10x for each.
65 + wg.Add(2)
66 + go connect(swarms[0], swarms[1].local, ifaceAddrs1[0])
67 + go connect(swarms[1], swarms[0].local, ifaceAddrs0[0])
68 + }
69 + wg.Wait()
70 + }
71 +
72 + // should still just have 1, at most 2 connections :)
73 + c01l := len(swarms[0].ConnectionsToPeer(swarms[1].local))
74 + if c01l > 2 {
75 + t.Error("0->1 has", c01l)
76 + }
77 + c10l := len(swarms[1].ConnectionsToPeer(swarms[0].local))
78 + if c10l > 2 {
79 + t.Error("1->0 has", c10l)
80 + }
81 +
82 + for _, s := range swarms {
83 + s.Close()
84 + }
85 +}
86 +
87 +func newSilentPeer(t *testing.T) (peer.ID, ma.Multiaddr, net.Listener) {
88 + dst := testutil.RandPeerIDFatal(t)
89 + lst, err := net.Listen("tcp", ":0")
90 + if err != nil {
91 + t.Fatal(err)
92 + }
93 + addr, err := manet.FromNetAddr(lst.Addr())
94 + if err != nil {
95 + t.Fatal(err)
96 + }
97 + addrs := []ma.Multiaddr{addr}
98 + addrs, err = addrutil.ResolveUnspecifiedAddresses(addrs, nil)
99 + if err != nil {
100 + t.Fatal(err)
101 + }
102 + t.Log("new silent peer:", dst, addrs[0])
103 + return dst, addrs[0], lst
104 +}
105 +
106 +func TestDialWait(t *testing.T) {
107 + // t.Skip("skipping for another test")
108 + t.Parallel()
109 +
110 + ctx := context.Background()
111 + swarms := makeSwarms(ctx, t, 1)
112 + s1 := swarms[0]
113 + defer s1.Close()
114 +
115 + s1.dialT = time.Millisecond * 300 // lower timeout for tests.
116 +
117 + // dial to a non-existent peer.
118 + s2p, s2addr, s2l := newSilentPeer(t)
119 + go acceptAndHang(s2l)
120 + defer s2l.Close()
121 + s1.peers.AddAddress(s2p, s2addr)
122 +
123 + before := time.Now()
124 + if c, err := s1.Dial(ctx, s2p); err == nil {
125 + defer c.Close()
126 + t.Fatal("error swarm dialing to unknown peer worked...", err)
127 + } else {
128 + t.Log("correctly got error:", err)
129 + }
130 + duration := time.Now().Sub(before)
131 +
132 + dt := s1.dialT
133 + if duration < dt*dialAttempts {
134 + t.Error("< DialTimeout * dialAttempts not being respected", duration, dt*dialAttempts)
135 + }
136 + if duration > 2*dt*dialAttempts {
137 + t.Error("> 2*DialTimeout * dialAttempts not being respected", duration, 2*dt*dialAttempts)
138 + }
139 +
140 + if !s1.backf.Backoff(s2p) {
141 + t.Error("s2 should now be on backoff")
142 + }
143 +}
144 +
145 +func TestDialBackoff(t *testing.T) {
146 + // t.Skip("skipping for another test")
147 + t.Parallel()
148 +
149 + ctx := context.Background()
150 + swarms := makeSwarms(ctx, t, 2)
151 + s1 := swarms[0]
152 + s2 := swarms[1]
153 + defer s1.Close()
154 + defer s2.Close()
155 +
156 + s1.dialT = time.Millisecond * 500 // lower timeout for tests.
157 + s2.dialT = time.Millisecond * 500 // lower timeout for tests.
158 +
159 + s2addrs, err := s2.InterfaceListenAddresses()
160 + if err != nil {
161 + t.Fatal(err)
162 + }
163 + s1.peers.AddAddresses(s2.local, s2addrs)
164 +
165 + // dial to a non-existent peer.
166 + s3p, s3addr, s3l := newSilentPeer(t)
167 + go acceptAndHang(s3l)
168 + defer s3l.Close()
169 + s1.peers.AddAddress(s3p, s3addr)
170 +
171 + // in this test we will:
172 + // 1) dial 10x to each node.
173 + // 2) all dials should hang
174 + // 3) s1->s2 should succeed.
175 + // 4) s1->s3 should not (and should place s3 on backoff)
176 + // 5) disconnect entirely
177 + // 6) dial 10x to each node again
178 + // 7) s3 dials should all return immediately (except 1)
179 + // 8) s2 dials should all hang, and succeed
180 + // 9) last s3 dial ends, unsuccessful
181 +
182 + dialOnlineNode := func(dst peer.ID, times int) <-chan bool {
183 + ch := make(chan bool)
184 + for i := 0; i < times; i++ {
185 + go func() {
186 + if _, err := s1.Dial(ctx, dst); err != nil {
187 + t.Error("error dialing", dst, err)
188 + ch <- false
189 + } else {
190 + ch <- true
191 + }
192 + }()
193 + }
194 + return ch
195 + }
196 +
197 + dialOfflineNode := func(dst peer.ID, times int) <-chan bool {
198 + ch := make(chan bool)
199 + for i := 0; i < times; i++ {
200 + go func() {
201 + if c, err := s1.Dial(ctx, dst); err != nil {
202 + ch <- false
203 + } else {
204 + t.Error("succeeded in dialing", dst)
205 + ch <- true
206 + c.Close()
207 + }
208 + }()
209 + }
210 + return ch
211 + }
212 +
213 + {
214 + // 1) dial 10x to each node.
215 + N := 10
216 + s2done := dialOnlineNode(s2.local, N)
217 + s3done := dialOfflineNode(s3p, N)
218 +
219 + // when all dials should be done by:
220 + dialTimeout1x := time.After(s1.dialT)
221 + dialTimeout1Ax := time.After(s1.dialT * dialAttempts)
222 + dialTimeout10Ax := time.After(s1.dialT * dialAttempts * 10)
223 +
224 + // 2) all dials should hang
225 + select {
226 + case <-s2done:
227 + t.Error("s2 should not happen immediately")
228 + case <-s3done:
229 + t.Error("s3 should not happen yet")
230 + case <-time.After(time.Millisecond):
231 + // s2 may finish very quickly, so let's get out.
232 + }
233 +
234 + // 3) s1->s2 should succeed.
235 + for i := 0; i < N; i++ {
236 + select {
237 + case r := <-s2done:
238 + if !r {
239 + t.Error("s2 should not fail")
240 + }
241 + case <-s3done:
242 + t.Error("s3 should not happen yet")
243 + case <-dialTimeout1x:
244 + t.Error("s2 took too long")
245 + }
246 + }
247 +
248 + select {
249 + case <-s2done:
250 + t.Error("s2 should have no more")
251 + case <-s3done:
252 + t.Error("s3 should not happen yet")
253 + case <-dialTimeout1x: // let it pass
254 + }
255 +
256 + // 4) s1->s3 should not (and should place s3 on backoff)
257 + // N-1 should finish before dialTimeout1Ax
258 + for i := 0; i < N; i++ {
259 + select {
260 + case <-s2done:
261 + t.Error("s2 should have no more")
262 + case r := <-s3done:
263 + if r {
264 + t.Error("s3 should not succeed")
265 + }
266 + case <-dialTimeout1Ax:
267 + if i < (N - 1) {
268 + t.Fatal("s3 took too long")
269 + }
270 + t.Log("dialTimeout1Ax hit for last peer")
271 + case <-dialTimeout10Ax:
272 + t.Fatal("s3 took too long")
273 + }
274 + }
275 +
276 + // check backoff state
277 + if s1.backf.Backoff(s2.local) {
278 + t.Error("s2 should not be on backoff")
279 + }
280 + if !s1.backf.Backoff(s3p) {
281 + t.Error("s3 should be on backoff")
282 + }
283 +
284 + // 5) disconnect entirely
285 +
286 + for _, c := range s1.Connections() {
287 + c.Close()
288 + }
289 + for i := 0; i < 100 && len(s1.Connections()) > 0; i++ {
290 + <-time.After(time.Millisecond)
291 + }
292 + if len(s1.Connections()) > 0 {
293 + t.Fatal("s1 conns must exit")
294 + }
295 + }
296 +
297 + {
298 + // 6) dial 10x to each node again
299 + N := 10
300 + s2done := dialOnlineNode(s2.local, N)
301 + s3done := dialOfflineNode(s3p, N)
302 +
303 + // when all dials should be done by:
304 + dialTimeout1x := time.After(s1.dialT)
305 + dialTimeout1Ax := time.After(s1.dialT * dialAttempts)
306 + dialTimeout10Ax := time.After(s1.dialT * dialAttempts * 10)
307 +
308 + // 7) s3 dials should all return immediately (except 1)
309 + for i := 0; i < N-1; i++ {
310 + select {
311 + case <-s2done:
312 + t.Error("s2 should not succeed yet")
313 + case r := <-s3done:
314 + if r {
315 + t.Error("s3 should not succeed")
316 + }
317 + case <-dialTimeout1x:
318 + t.Fatal("s3 took too long")
319 + }
320 + }
321 +
322 + // 8) s2 dials should all hang, and succeed
323 + for i := 0; i < N; i++ {
324 + select {
325 + case r := <-s2done:
326 + if !r {
327 + t.Error("s2 should succeed")
328 + }
329 + // case <-s3done:
330 + case <-dialTimeout1Ax:
331 + t.Fatal("s3 took too long")
332 + }
333 + }
334 +
335 + // 9) the last s3 should return, failed.
336 + select {
337 + case <-s2done:
338 + t.Error("s2 should have no more")
339 + case r := <-s3done:
340 + if r {
341 + t.Error("s3 should not succeed")
342 + }
343 + case <-dialTimeout10Ax:
344 + t.Fatal("s3 took too long")
345 + }
346 +
347 + // check backoff state (the same)
348 + if s1.backf.Backoff(s2.local) {
349 + t.Error("s2 should not be on backoff")
350 + }
351 + if !s1.backf.Backoff(s3p) {
352 + t.Error("s3 should be on backoff")
353 + }
354 +
355 + }
356 +}
357 +
358 +func TestDialBackoffClears(t *testing.T) {
359 + // t.Skip("skipping for another test")
360 + t.Parallel()
361 +
362 + ctx := context.Background()
363 + swarms := makeSwarms(ctx, t, 2)
364 + s1 := swarms[0]
365 + s2 := swarms[1]
366 + defer s1.Close()
367 + defer s2.Close()
368 + s1.dialT = time.Millisecond * 300 // lower timeout for tests.
369 + s2.dialT = time.Millisecond * 300 // lower timeout for tests.
370 +
371 + // use another address first, that accept and hang on conns
372 + _, s2bad, s2l := newSilentPeer(t)
373 + go acceptAndHang(s2l)
374 + defer s2l.Close()
375 +
376 + // phase 1 -- dial to non-operational addresses
377 + s1.peers.AddAddress(s2.local, s2bad)
378 +
379 + before := time.Now()
380 + if c, err := s1.Dial(ctx, s2.local); err == nil {
381 + t.Fatal("dialing to broken addr worked...", err)
382 + defer c.Close()
383 + } else {
384 + t.Log("correctly got error:", err)
385 + }
386 + duration := time.Now().Sub(before)
387 +
388 + dt := s1.dialT
389 + if duration < dt*dialAttempts {
390 + t.Error("< DialTimeout * dialAttempts not being respected", duration, dt*dialAttempts)
391 + }
392 + if duration > 2*dt*dialAttempts {
393 + t.Error("> 2*DialTimeout * dialAttempts not being respected", duration, 2*dt*dialAttempts)
394 + }
395 +
396 + if !s1.backf.Backoff(s2.local) {
397 + t.Error("s2 should now be on backoff")
398 + } else {
399 + t.Log("correctly added to backoff")
400 + }
401 +
402 + // phase 2 -- add the working address. dial should succeed.
403 + ifaceAddrs1, err := swarms[1].InterfaceListenAddresses()
404 + if err != nil {
405 + t.Fatal(err)
406 + }
407 + s1.peers.AddAddresses(s2.local, ifaceAddrs1)
408 +
409 + before = time.Now()
410 + if c, err := s1.Dial(ctx, s2.local); err != nil {
411 + t.Fatal(err)
412 + } else {
413 + c.Close()
414 + t.Log("correctly connected")
415 + }
416 + duration = time.Now().Sub(before)
417 +
418 + if duration >= dt {
419 + // t.Error("took too long", duration, dt)
420 + }
421 +
422 + if s1.backf.Backoff(s2.local) {
423 + t.Error("s2 should no longer be on backoff")
424 + } else {
425 + t.Log("correctly cleared backoff")
426 + }
427 +}
p2p/net/swarm/simul_test.go
-43
@@ -11,49 +11,6 @@ import (
11 ma "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-multiaddr"
12 )
13
14 -func TestSimultDials(t *testing.T) {
15 - // t.Skip("skipping for another test")
16 -
17 - ctx := context.Background()
18 - swarms := makeSwarms(ctx, t, 2)
19 -
20 - // connect everyone
21 - {
22 - var wg sync.WaitGroup
23 - connect := func(s *Swarm, dst peer.ID, addr ma.Multiaddr) {
24 - // copy for other peer
25 - log.Debugf("TestSimultOpen: connecting: %s --> %s (%s)", s.local, dst, addr)
26 - s.peers.AddAddress(dst, addr)
27 - if _, err := s.Dial(ctx, dst); err != nil {
28 - t.Fatal("error swarm dialing to peer", err)
29 - }
30 - wg.Done()
31 - }
32 -
33 - log.Info("Connecting swarms simultaneously.")
34 - for i := 0; i < 10; i++ { // connect 10x for each.
35 - wg.Add(2)
36 - go connect(swarms[0], swarms[1].local, swarms[1].ListenAddresses()[0])
37 - go connect(swarms[1], swarms[0].local, swarms[0].ListenAddresses()[0])
38 - }
39 - wg.Wait()
40 - }
41 -
42 - // should still just have 1, at most 2 connections :)
43 - c01l := len(swarms[0].ConnectionsToPeer(swarms[1].local))
44 - if c01l > 2 {
45 - t.Error("0->1 has", c01l)
46 - }
47 - c10l := len(swarms[1].ConnectionsToPeer(swarms[0].local))
48 - if c10l > 2 {
49 - t.Error("1->0 has", c10l)
50 - }
51 -
52 - for _, s := range swarms {
53 - s.Close()
54 - }
55 -}
56 -
14 func TestSimultOpen(t *testing.T) {
15 // t.Skip("skipping for another test")
16