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  }