mock2: link map fixes
Juan Batiz-Benet committed
Dec 17, 2014 at 06:58 UTC
444f47d7f5a81f442d2d6f95b320bb0e5e4cb3cd
3 files changed
+224
-24
net/mock2/mock_link.go
+2
-2
@@ -19,8 +19,8 @@ type link struct {
19
sync.RWMutex
20
}
21
22
-func newLink(mn *mocknet) *link {
23
- return &link{mock: mn, opts: mn.linkDefaults}
22
+func newLink(mn *mocknet, opts LinkOptions) *link {
23
+ return &link{mock: mn, opts: opts}
24
}
25
26
func (l *link) newConnPair() (*conn, *conn) {
net/mock2/mock_net.go
+34
-22
@@ -164,18 +164,21 @@ func (mn *mocknet) validate(n inet.Network) (*peernet, error) {
164
}
165
166
func (mn *mocknet) LinkNets(n1, n2 inet.Network) (Link, error) {
167
- mn.Lock()
168
- defer mn.Unlock()
167
+ mn.RLock()
168
+ n1r, err1 := mn.validate(n1)
169
+ n2r, err2 := mn.validate(n1)
170
+ ld := mn.linkDefaults
171
+ mn.RUnlock()
172
170
- if _, err := mn.validate(n1); err != nil {
171
- return nil, err
173
+ if err1 != nil {
174
+ return nil, err1
175
}
173
-
174
- if _, err := mn.validate(n2); err != nil {
175
- return nil, err
176
+ if err2 != nil {
177
+ return nil, err2
178
}
179
178
- l := newLink(mn)
180
+ l := newLink(mn, ld)
181
+ l.nets = append(l.nets, n1r, n2r)
182
mn.addLink(l)
183
return l, nil
184
}
@@ -209,13 +212,31 @@ func (mn *mocknet) UnlinkNets(n1, n2 inet.Network) error {
212
return mn.UnlinkPeers(n1.LocalPeer(), n2.LocalPeer())
213
}
214
215
+// get from the links map. and lazily contruct.
216
+func (mn *mocknet) linksMapGet(p1, p2 peer.Peer) *map[*link]struct{} {
217
+ l1, found := mn.links[pid(p1)]
218
+ if !found {
219
+ mn.links[pid(p1)] = map[peerID]map[*link]struct{}{}
220
+ l1 = mn.links[pid(p1)] // so we make sure it's there.
221
+ }
222
+
223
+ l2, found := l1[pid(p2)]
224
+ if !found {
225
+ m := map[*link]struct{}{}
226
+ l1[pid(p2)] = m
227
+ l2 = l1[pid(p2)]
228
+ }
229
+
230
+ return &l2
231
+}
232
+
233
func (mn *mocknet) addLink(l *link) {
234
mn.Lock()
235
defer mn.Unlock()
236
237
n1, n2 := l.nets[0], l.nets[1]
217
- mn.links[pid(n1.peer)][pid(n2.peer)][l] = struct{}{}
218
- mn.links[pid(n2.peer)][pid(n1.peer)][l] = struct{}{}
238
+ (*mn.linksMapGet(n1.peer, n2.peer))[l] = struct{}{}
239
+ (*mn.linksMapGet(n2.peer, n1.peer))[l] = struct{}{}
240
}
241
242
func (mn *mocknet) removeLink(l *link) {
@@ -223,8 +244,8 @@ func (mn *mocknet) removeLink(l *link) {
244
defer mn.Unlock()
245
246
n1, n2 := l.nets[0], l.nets[1]
226
- delete(mn.links[pid(n1.peer)][pid(n2.peer)], l)
227
- delete(mn.links[pid(n2.peer)][pid(n1.peer)], l)
247
+ delete(*mn.linksMapGet(n1.peer, n2.peer), l)
248
+ delete(*mn.linksMapGet(n2.peer, n1.peer), l)
249
}
250
251
func (mn *mocknet) ConnectAll() error {
@@ -263,16 +284,7 @@ func (mn *mocknet) LinksBetweenPeers(p1, p2 peer.Peer) []Link {
284
mn.RLock()
285
defer mn.RUnlock()
286
266
- ls1, found := mn.links[pid(p1)]
267
- if !found {
268
- return nil
269
- }
270
-
271
- ls2, found := ls1[pid(p2)]
272
- if !found {
273
- return nil
274
- }
275
-
287
+ ls2 := *mn.linksMapGet(p1, p2)
288
cp := make([]Link, 0, len(ls2))
289
for l := range ls2 {
290
cp = append(cp, l)
net/mock2/mock_test.go
new
+188
@@ -0,0 +1,188 @@
1
+package mocknet
2
+
3
+import (
4
+ "bytes"
5
+ "io"
6
+ "math/rand"
7
+ "sync"
8
+ "testing"
9
+
10
+ inet "github.com/jbenet/go-ipfs/net"
11
+
12
+ context "github.com/jbenet/go-ipfs/Godeps/_workspace/src/code.google.com/p/go.net/context"
13
+)
14
+
15
+// func TestNetworkSetup(t *testing.T) {
16
+
17
+// p1 := testutil.RandPeer()
18
+// p2 := testutil.RandPeer()
19
+// p3 := testutil.RandPeer()
20
+// peers := []peer.Peer{p1, p2, p3}
21
+
22
+// nets, err := MakeNetworks(context.Background(), peers)
23
+// if err != nil {
24
+// t.Fatal(err)
25
+// }
26
+
27
+// // check things
28
+
29
+// if len(nets) != 3 {
30
+// t.Error("nets must be 3")
31
+// }
32
+
33
+// for i, n := range nets {
34
+// if n.local != peers[i] {
35
+// t.Error("peer mismatch")
36
+// }
37
+
38
+// if len(n.conns) != len(nets) {
39
+// t.Error("conn mismatch")
40
+// }
41
+
42
+// for _, c := range n.conns {
43
+// if c.remote.conns[n.local] == nil {
44
+// t.Error("conn other side fail")
45
+// }
46
+// if c.remote.conns[n.local].remote.local != n.local {
47
+// t.Error("conn other side fail")
48
+// }
49
+// }
50
+
51
+// }
52
+
53
+// }
54
+
55
+func TestStreams(t *testing.T) {
56
+
57
+ mn, err := FullMeshConnected(context.Background(), 3)
58
+ if err != nil {
59
+ t.Fatal(err)
60
+ }
61
+
62
+ handler := func(s inet.Stream) {
63
+ go func() {
64
+ b := make([]byte, 4)
65
+ if _, err := io.ReadFull(s, b); err != nil {
66
+ panic(err)
67
+ }
68
+ if !bytes.Equal(b, []byte("beep")) {
69
+ panic("bytes mismatch")
70
+ }
71
+ if _, err := s.Write([]byte("boop")); err != nil {
72
+ panic(err)
73
+ }
74
+ s.Close()
75
+ }()
76
+ }
77
+
78
+ nets := mn.Nets()
79
+ for _, n := range nets {
80
+ n.SetHandler(inet.ProtocolDHT, handler)
81
+ }
82
+
83
+ s, err := nets[0].NewStream(inet.ProtocolDHT, nets[1].LocalPeer())
84
+ if err != nil {
85
+ t.Fatal(err)
86
+ }
87
+
88
+ if _, err := s.Write([]byte("beep")); err != nil {
89
+ panic(err)
90
+ }
91
+ b := make([]byte, 4)
92
+ if _, err := io.ReadFull(s, b); err != nil {
93
+ panic(err)
94
+ }
95
+ if !bytes.Equal(b, []byte("boop")) {
96
+ panic("bytes mismatch 2")
97
+ }
98
+
99
+}
100
+
101
+func makePinger(st string, n int) func(inet.Stream) {
102
+ return func(s inet.Stream) {
103
+ go func() {
104
+ defer s.Close()
105
+
106
+ for i := 0; i < n; i++ {
107
+ b := make([]byte, 4+len(st))
108
+ if _, err := s.Write([]byte("ping" + st)); err != nil {
109
+ panic(err)
110
+ }
111
+ if _, err := io.ReadFull(s, b); err != nil {
112
+ panic(err)
113
+ }
114
+ if !bytes.Equal(b, []byte("pong"+st)) {
115
+ panic("bytes mismatch")
116
+ }
117
+ }
118
+ }()
119
+ }
120
+}
121
+
122
+func makePonger(st string) func(inet.Stream) {
123
+ return func(s inet.Stream) {
124
+ go func() {
125
+ defer s.Close()
126
+
127
+ for {
128
+ b := make([]byte, 4+len(st))
129
+ if _, err := io.ReadFull(s, b); err != nil {
130
+ if err == io.EOF {
131
+ return
132
+ }
133
+ panic(err)
134
+ }
135
+ if !bytes.Equal(b, []byte("ping"+st)) {
136
+ panic("bytes mismatch")
137
+ }
138
+ if _, err := s.Write([]byte("pong" + st)); err != nil {
139
+ panic(err)
140
+ }
141
+ }
142
+ }()
143
+ }
144
+}
145
+
146
+func TestStreamsStress(t *testing.T) {
147
+
148
+ mn, err := FullMeshConnected(context.Background(), 100)
149
+ if err != nil {
150
+ t.Fatal(err)
151
+ }
152
+
153
+ protos := []inet.ProtocolID{
154
+ inet.ProtocolDHT,
155
+ inet.ProtocolBitswap,
156
+ inet.ProtocolDiag,
157
+ }
158
+
159
+ nets := mn.Nets()
160
+ for _, n := range nets {
161
+ for _, p := range protos {
162
+ n.SetHandler(p, makePonger(string(p)))
163
+ }
164
+ }
165
+
166
+ var wg sync.WaitGroup
167
+ for i := 0; i < 1000; i++ {
168
+ wg.Add(1)
169
+ go func(i int) {
170
+ defer wg.Done()
171
+ from := rand.Intn(len(nets))
172
+ to := rand.Intn(len(nets))
173
+ p := rand.Intn(3)
174
+ proto := protos[p]
175
+ log.Debug("%d (%s) %d (%s) %d (%s)", from, nets[from], to, nets[to], p, protos[p])
176
+ s, err := nets[from].NewStream(protos[p], nets[to].LocalPeer())
177
+ if err != nil {
178
+ panic(err)
179
+ }
180
+
181
+ log.Infof("%d start pinging", i)
182
+ makePinger(string(proto), rand.Intn(100))(s)
183
+ log.Infof("%d done pinging", i)
184
+ }(i)
185
+ }
186
+
187
+ wg.Done()
188
+}