@cryptotaxi247 / kubo / commits / feb5e495f

use ZeroLocalTCPAddress for network tests

This commit makes all network tests use ZeroLocalTCPAddress as the initial peer address, and then relies on net.ListenAddresses() This should get rid of the tcp addr clash problems.

Juan Batiz-Benet committed Jan 1, 2015 at 21:53 UTC feb5e495f56970351f63a60f9ea14bbf0126568c
6 files changed +60 -38
p2p/net/conn/dial_test.go
+3 -2
@@ -51,7 +51,6 @@ func setupConn(t *testing.T, ctx context.Context, secure bool) (a, b Conn, p1, p
51
52 p1 = tu.RandPeerNetParamsOrFatal(t)
53 p2 = tu.RandPeerNetParamsOrFatal(t)
54 - laddr := p1.Addr
54
55 key1 := p1.PrivKey
56 key2 := p2.PrivKey
@@ -59,10 +58,11 @@ func setupConn(t *testing.T, ctx context.Context, secure bool) (a, b Conn, p1, p
58 key1 = nil
59 key2 = nil
60 }
62 - l1, err := Listen(ctx, laddr, p1.ID, key1)
61 + l1, err := Listen(ctx, p1.Addr, p1.ID, key1)
62 if err != nil {
63 t.Fatal(err)
64 }
65 + p1.Addr = l1.Multiaddr() // Addr has been determined by kernel.
66
67 d2 := &Dialer{
68 LocalPeer: p2.ID,
@@ -110,6 +110,7 @@ func testDialer(t *testing.T, secure bool) {
110 if err != nil {
111 t.Fatal(err)
112 }
113 + p1.Addr = l1.Multiaddr() // Addr has been determined by kernel.
114
115 d2 := &Dialer{
116 LocalPeer: p2.ID,
p2p/net/conn/listen.go
+12 -8
@@ -17,25 +17,24 @@ import (
17 type listener struct {
18 manet.Listener
19
20 - maddr ma.Multiaddr // Local multiaddr to listen on
21 - local peer.ID // LocalPeer is the identity of the local Peer
22 - privk ic.PrivKey // private key to use to initialize secure conns
20 + local peer.ID // LocalPeer is the identity of the local Peer
21 + privk ic.PrivKey // private key to use to initialize secure conns
22
23 cg ctxgroup.ContextGroup
24 }
25
26 func (l *listener) teardown() error {
28 - defer log.Debugf("listener closed: %s %s", l.local, l.maddr)
27 + defer log.Debugf("listener closed: %s %s", l.local, l.Multiaddr())
28 return l.Listener.Close()
29 }
30
31 func (l *listener) Close() error {
33 - log.Debugf("listener closing: %s %s", l.local, l.maddr)
32 + log.Debugf("listener closing: %s %s", l.local, l.Multiaddr())
33 return l.cg.Close()
34 }
35
36 func (l *listener) String() string {
38 - return fmt.Sprintf("<Listener %s %s>", l.local, l.maddr)
37 + return fmt.Sprintf("<Listener %s %s>", l.local, l.Multiaddr())
38 }
39
40 // Accept waits for and returns the next connection to the listener.
@@ -73,8 +72,14 @@ func (l *listener) Addr() net.Addr {
72 }
73
74 // Multiaddr is the identity of the local Peer.
75 +// If there is an error converting from net.Addr to ma.Multiaddr,
76 +// the return value will be nil.
77 func (l *listener) Multiaddr() ma.Multiaddr {
77 - return l.maddr
78 + maddr, err := manet.FromNetAddr(l.Addr())
79 + if err != nil {
80 + return nil // error
81 + }
82 + return maddr
83 }
84
85 // LocalPeer is the identity of the local Peer.
@@ -102,7 +107,6 @@ func Listen(ctx context.Context, addr ma.Multiaddr, local peer.ID, sk ic.PrivKey
107
108 l := &listener{
109 Listener: ml,
105 - maddr: addr,
110 local: local,
111 privk: sk,
112 cg: ctxgroup.WithContext(ctx),
p2p/net/swarm/simul_test.go
+4 -3
@@ -15,13 +15,14 @@ func TestSimultOpen(t *testing.T) {
15 // t.Skip("skipping for another test")
16
17 ctx := context.Background()
18 - swarms, peers := makeSwarms(ctx, t, 2)
18 + swarms := makeSwarms(ctx, t, 2)
19
20 // connect everyone
21 {
22 var wg sync.WaitGroup
23 connect := func(s *Swarm, dst peer.ID, addr ma.Multiaddr) {
24 // copy for other peer
25 + log.Debugf("TestSimultOpen: connecting: %s --> %s (%s)", s.local, dst, addr)
26 s.peers.AddAddress(dst, addr)
27 if _, err := s.Dial(ctx, dst); err != nil {
28 t.Fatal("error swarm dialing to peer", err)
@@ -31,8 +32,8 @@ func TestSimultOpen(t *testing.T) {
32
33 log.Info("Connecting swarms simultaneously.")
34 wg.Add(2)
34 - go connect(swarms[0], swarms[1].local, peers[1].Addr)
35 - go connect(swarms[1], swarms[0].local, peers[0].Addr)
35 + go connect(swarms[0], swarms[1].local, swarms[1].ListenAddresses()[0])
36 + go connect(swarms[1], swarms[0].local, swarms[0].ListenAddresses()[0])
37 wg.Wait()
38 }
39
p2p/net/swarm/swarm_test.go
+19 -22
@@ -47,20 +47,17 @@ func EchoStreamHandler(stream inet.Stream) {
47 }()
48 }
49
50 -func makeSwarms(ctx context.Context, t *testing.T, num int) ([]*Swarm, []testutil.PeerNetParams) {
50 +func makeSwarms(ctx context.Context, t *testing.T, num int) []*Swarm {
51 swarms := make([]*Swarm, 0, num)
52 - peersnp := make([]testutil.PeerNetParams, 0, num)
52
53 for i := 0; i < num; i++ {
54 localnp := testutil.RandPeerNetParamsOrFatal(t)
56 - peersnp = append(peersnp, localnp)
55
56 peerstore := peer.NewPeerstore()
59 - peerstore.AddAddress(localnp.ID, localnp.Addr)
57 peerstore.AddPubKey(localnp.ID, localnp.PubKey)
58 peerstore.AddPrivKey(localnp.ID, localnp.PrivKey)
59
63 - addrs := peerstore.Addresses(localnp.ID)
60 + addrs := []ma.Multiaddr{localnp.Addr}
61 swarm, err := NewSwarm(ctx, addrs, localnp.ID, peerstore)
62 if err != nil {
63 t.Fatal(err)
@@ -70,10 +67,10 @@ func makeSwarms(ctx context.Context, t *testing.T, num int) ([]*Swarm, []testuti
67 swarms = append(swarms, swarm)
68 }
69
73 - return swarms, peersnp
70 + return swarms
71 }
72
76 -func connectSwarms(t *testing.T, ctx context.Context, swarms []*Swarm, peersnp []testutil.PeerNetParams) {
73 +func connectSwarms(t *testing.T, ctx context.Context, swarms []*Swarm) {
74
75 var wg sync.WaitGroup
76 connect := func(s *Swarm, dst peer.ID, addr ma.Multiaddr) {
@@ -86,11 +83,11 @@ func connectSwarms(t *testing.T, ctx context.Context, swarms []*Swarm, peersnp [
83 }
84
85 log.Info("Connecting swarms simultaneously.")
89 - for _, s := range swarms {
90 - for _, p := range peersnp {
91 - if p.ID != s.local { // don't connect to self.
86 + for _, s1 := range swarms {
87 + for _, s2 := range swarms {
88 + if s2.local != s1.local { // don't connect to self.
89 wg.Add(1)
93 - connect(s, p.ID, p.Addr)
90 + connect(s1, s2.LocalPeer(), s2.ListenAddresses()[0]) // try the first.
91 }
92 }
93 }
@@ -105,10 +102,10 @@ func SubtestSwarm(t *testing.T, SwarmNum int, MsgNum int) {
102 // t.Skip("skipping for another test")
103
104 ctx := context.Background()
108 - swarms, peersnp := makeSwarms(ctx, t, SwarmNum)
105 + swarms := makeSwarms(ctx, t, SwarmNum)
106
107 // connect everyone
111 - connectSwarms(t, ctx, swarms, peersnp)
108 + connectSwarms(t, ctx, swarms)
109
110 // ping/pong
111 for _, s1 := range swarms {
@@ -118,7 +115,7 @@ func SubtestSwarm(t *testing.T, SwarmNum int, MsgNum int) {
115
116 _, cancel := context.WithCancel(ctx)
117 got := map[peer.ID]int{}
121 - errChan := make(chan error, MsgNum*len(peersnp))
118 + errChan := make(chan error, MsgNum*len(swarms))
119 streamChan := make(chan *Stream, MsgNum)
120
121 // send out "ping" x MsgNum to every peer
@@ -150,13 +147,13 @@ func SubtestSwarm(t *testing.T, SwarmNum int, MsgNum int) {
147 streamChan <- stream
148 }
149
153 - for _, p := range peersnp {
154 - if p.ID == s1.local {
150 + for _, s2 := range swarms {
151 + if s2.local == s1.local {
152 continue // dont send to self...
153 }
154
155 wg.Add(1)
159 - go send(p.ID)
156 + go send(s2.local)
157 }
158 wg.Wait()
159 }()
@@ -165,7 +162,7 @@ func SubtestSwarm(t *testing.T, SwarmNum int, MsgNum int) {
162 go func() {
163 defer close(errChan)
164 count := 0
168 - countShouldBe := MsgNum * (len(peersnp) - 1)
165 + countShouldBe := MsgNum * (len(swarms) - 1)
166 for stream := range streamChan { // one per peer
167 defer stream.Close()
168
@@ -209,8 +206,8 @@ func SubtestSwarm(t *testing.T, SwarmNum int, MsgNum int) {
206 }
207
208 log.Debugf("%s got pongs", s1.local)
212 - if (len(peersnp) - 1) != len(got) {
213 - t.Errorf("got (%d) less messages than sent (%d).", len(got), len(peersnp))
209 + if (len(swarms) - 1) != len(got) {
210 + t.Errorf("got (%d) less messages than sent (%d).", len(got), len(swarms))
211 }
212
213 for p, n := range got {
@@ -241,14 +238,14 @@ func TestConnHandler(t *testing.T) {
238 // t.Skip("skipping for another test")
239
240 ctx := context.Background()
244 - swarms, peersnp := makeSwarms(ctx, t, 5)
241 + swarms := makeSwarms(ctx, t, 5)
242
243 gotconn := make(chan struct{}, 10)
244 swarms[0].SetConnHandler(func(conn *Conn) {
245 gotconn <- struct{}{}
246 })
247
251 - connectSwarms(t, ctx, swarms, peersnp)
248 + connectSwarms(t, ctx, swarms)
249
250 <-time.After(time.Millisecond)
251 // should've gotten 5 by now.
p2p/test/util/util.go
+3 -2
@@ -10,18 +10,19 @@ import (
10 tu "github.com/jbenet/go-ipfs/util/testutil"
11
12 context "github.com/jbenet/go-ipfs/Godeps/_workspace/src/code.google.com/p/go.net/context"
13 + ma "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-multiaddr"
14 )
15
16 func GenSwarmNetwork(t *testing.T, ctx context.Context) *swarm.Network {
17 p := tu.RandPeerNetParamsOrFatal(t)
18 ps := peer.NewPeerstore()
18 - ps.AddAddress(p.ID, p.Addr)
19 ps.AddPubKey(p.ID, p.PubKey)
20 ps.AddPrivKey(p.ID, p.PrivKey)
21 - n, err := swarm.NewNetwork(ctx, ps.Addresses(p.ID), p.ID, ps)
21 + n, err := swarm.NewNetwork(ctx, []ma.Multiaddr{p.Addr}, p.ID, ps)
22 if err != nil {
23 t.Fatal(err)
24 }
25 + ps.AddAddresses(p.ID, n.ListenAddresses())
26 return n
27 }
28
util/testutil/gen.go
+19 -1
@@ -16,6 +16,19 @@ import (
16 ma "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-multiaddr"
17 )
18
19 +// ZeroLocalTCPAddress is the "zero" tcp local multiaddr. This means:
20 +// /ip4/127.0.0.1/tcp/0
21 +var ZeroLocalTCPAddress ma.Multiaddr
22 +
23 +func init() {
24 + // initialize ZeroLocalTCPAddress
25 + maddr, err := ma.NewMultiaddr("/ip4/127.0.0.1/tcp/0")
26 + if err != nil {
27 + panic(err)
28 + }
29 + ZeroLocalTCPAddress = maddr
30 +}
31 +
32 func RandKeyPair(bits int) (ci.PrivKey, ci.PubKey, error) {
33 return ci.GenerateKeyPairWithReader(ci.RSA, bits, u.NewTimeSeededRand())
34 }
@@ -48,6 +61,11 @@ func RandPeerIDFatal(t testing.TB) peer.ID {
61
62 // RandLocalTCPAddress returns a random multiaddr. it suppresses errors
63 // for nice composability-- do check the address isn't nil.
64 +//
65 +// Note: for real network tests, use ZeroLocalTCPAddress so the kernel
66 +// assigns an unused TCP port. otherwise you may get clashes. This
67 +// function remains here so that p2p/net/mock (which does not touch the
68 +// real network) can assign different addresses to peers.
69 func RandLocalTCPAddress() ma.Multiaddr {
70
71 // chances are it will work out, but it **might** fail if the port is in use
@@ -123,7 +141,7 @@ func RandPeerNetParamsOrFatal(t *testing.T) PeerNetParams {
141 func RandPeerNetParams() (*PeerNetParams, error) {
142 var p PeerNetParams
143 var err error
126 - p.Addr = RandLocalTCPAddress()
144 + p.Addr = ZeroLocalTCPAddress
145 p.PrivKey, p.PubKey, err = RandKeyPair(512)
146 if err != nil {
147 return nil, err