@cryptotaxi247 / kubo / commits / 84a2a5915

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 +}