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