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  }