@cryptotaxi247 / kubo / commits / 444f47d7f

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