github.com/keltia/go-ipfs@v0.3.8-0.20150909044612-210793031c63/p2p/net/swarm/swarm_notif_test.go (about) 1 package swarm 2 3 import ( 4 "testing" 5 "time" 6 7 ma "github.com/ipfs/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-multiaddr" 8 context "github.com/ipfs/go-ipfs/Godeps/_workspace/src/golang.org/x/net/context" 9 10 inet "github.com/ipfs/go-ipfs/p2p/net" 11 peer "github.com/ipfs/go-ipfs/p2p/peer" 12 ) 13 14 func TestNotifications(t *testing.T) { 15 ctx := context.Background() 16 swarms := makeSwarms(ctx, t, 5) 17 defer func() { 18 for _, s := range swarms { 19 s.Close() 20 } 21 }() 22 23 timeout := 5 * time.Second 24 25 // signup notifs 26 notifiees := make([]*netNotifiee, len(swarms)) 27 for i, swarm := range swarms { 28 n := newNetNotifiee() 29 swarm.Notify(n) 30 notifiees[i] = n 31 } 32 33 connectSwarms(t, ctx, swarms) 34 35 <-time.After(time.Millisecond) 36 // should've gotten 5 by now. 37 38 // test everyone got the correct connection opened calls 39 for i, s := range swarms { 40 n := notifiees[i] 41 notifs := make(map[peer.ID][]inet.Conn) 42 for j, s2 := range swarms { 43 if i == j { 44 continue 45 } 46 47 // this feels a little sketchy, but its probably okay 48 for len(s.ConnectionsToPeer(s2.LocalPeer())) != len(notifs[s2.LocalPeer()]) { 49 select { 50 case c := <-n.connected: 51 nfp := notifs[c.RemotePeer()] 52 notifs[c.RemotePeer()] = append(nfp, c) 53 case <-time.After(timeout): 54 t.Fatal("timeout") 55 } 56 } 57 } 58 59 for p, cons := range notifs { 60 expect := s.ConnectionsToPeer(p) 61 if len(expect) != len(cons) { 62 t.Fatal("got different number of connections") 63 } 64 65 for _, c := range cons { 66 var found bool 67 for _, c2 := range expect { 68 if c == c2 { 69 found = true 70 break 71 } 72 } 73 74 if !found { 75 t.Fatal("connection not found!") 76 } 77 } 78 } 79 } 80 81 complement := func(c inet.Conn) (*Swarm, *netNotifiee, *Conn) { 82 for i, s := range swarms { 83 for _, c2 := range s.Connections() { 84 if c.LocalMultiaddr().Equal(c2.RemoteMultiaddr()) && 85 c2.LocalMultiaddr().Equal(c.RemoteMultiaddr()) { 86 return s, notifiees[i], c2 87 } 88 } 89 } 90 t.Fatal("complementary conn not found", c) 91 return nil, nil, nil 92 } 93 94 testOCStream := func(n *netNotifiee, s inet.Stream) { 95 var s2 inet.Stream 96 select { 97 case s2 = <-n.openedStream: 98 t.Log("got notif for opened stream") 99 case <-time.After(timeout): 100 t.Fatal("timeout") 101 } 102 if s != s2 { 103 t.Fatal("got incorrect stream", s.Conn(), s2.Conn()) 104 } 105 106 select { 107 case s2 = <-n.closedStream: 108 t.Log("got notif for closed stream") 109 case <-time.After(timeout): 110 t.Fatal("timeout") 111 } 112 if s != s2 { 113 t.Fatal("got incorrect stream", s.Conn(), s2.Conn()) 114 } 115 } 116 117 streams := make(chan inet.Stream) 118 for _, s := range swarms { 119 s.SetStreamHandler(func(s inet.Stream) { 120 streams <- s 121 s.Close() 122 }) 123 } 124 125 // open a streams in each conn 126 for i, s := range swarms { 127 for _, c := range s.Connections() { 128 _, n2, _ := complement(c) 129 130 st1, err := c.NewStream() 131 if err != nil { 132 t.Error(err) 133 } else { 134 st1.Write([]byte("hello")) 135 st1.Close() 136 testOCStream(notifiees[i], st1) 137 st2 := <-streams 138 testOCStream(n2, st2) 139 } 140 } 141 } 142 143 // close conns 144 for i, s := range swarms { 145 n := notifiees[i] 146 for _, c := range s.Connections() { 147 _, n2, c2 := complement(c) 148 c.Close() 149 c2.Close() 150 151 var c3, c4 inet.Conn 152 select { 153 case c3 = <-n.disconnected: 154 case <-time.After(timeout): 155 t.Fatal("timeout") 156 } 157 if c != c3 { 158 t.Fatal("got incorrect conn", c, c3) 159 } 160 161 select { 162 case c4 = <-n2.disconnected: 163 case <-time.After(timeout): 164 t.Fatal("timeout") 165 } 166 if c2 != c4 { 167 t.Fatal("got incorrect conn", c, c2) 168 } 169 } 170 } 171 } 172 173 type netNotifiee struct { 174 listen chan ma.Multiaddr 175 listenClose chan ma.Multiaddr 176 connected chan inet.Conn 177 disconnected chan inet.Conn 178 openedStream chan inet.Stream 179 closedStream chan inet.Stream 180 } 181 182 func newNetNotifiee() *netNotifiee { 183 return &netNotifiee{ 184 listen: make(chan ma.Multiaddr), 185 listenClose: make(chan ma.Multiaddr), 186 connected: make(chan inet.Conn), 187 disconnected: make(chan inet.Conn), 188 openedStream: make(chan inet.Stream), 189 closedStream: make(chan inet.Stream), 190 } 191 } 192 193 func (nn *netNotifiee) Listen(n inet.Network, a ma.Multiaddr) { 194 nn.listen <- a 195 } 196 func (nn *netNotifiee) ListenClose(n inet.Network, a ma.Multiaddr) { 197 nn.listenClose <- a 198 } 199 func (nn *netNotifiee) Connected(n inet.Network, v inet.Conn) { 200 nn.connected <- v 201 } 202 func (nn *netNotifiee) Disconnected(n inet.Network, v inet.Conn) { 203 nn.disconnected <- v 204 } 205 func (nn *netNotifiee) OpenedStream(n inet.Network, v inet.Stream) { 206 nn.openedStream <- v 207 } 208 func (nn *netNotifiee) ClosedStream(n inet.Network, v inet.Stream) { 209 nn.closedStream <- v 210 }