Commit 0e2041a9 authored by Steven Allen's avatar Steven Allen

more tests

parent b7421d5f
...@@ -5,176 +5,229 @@ import ( ...@@ -5,176 +5,229 @@ import (
"testing" "testing"
ma "github.com/multiformats/go-multiaddr" ma "github.com/multiformats/go-multiaddr"
manet "github.com/multiformats/go-multiaddr-net"
) )
func TestNoneAndSingle(t *testing.T) { var loopback, _ = ma.NewMultiaddr("/ip4/127.0.0.1/tcp/0")
var trA Transport var unspec, _ = ma.NewMultiaddr("/ip4/0.0.0.0/tcp/0")
var trB Transport
laddr, _ := ma.NewMultiaddr("/ip4/127.0.0.1/tcp/0") var global ma.Multiaddr
listenerA, err := trA.Listen(laddr)
func init() {
addrs, err := manet.InterfaceMultiaddrs()
if err != nil { if err != nil {
t.Fatal(err) return
} }
defer listenerA.Close() for _, addr := range addrs {
if !manet.IsIP6LinkLocal(addr) && !manet.IsIPLoopback(addr) {
tcp, _ := ma.NewMultiaddr("/tcp/0")
global = addr.Encapsulate(tcp)
return
}
}
}
func acceptOne(t *testing.T, listener manet.Listener) <-chan struct{} {
t.Helper()
done := make(chan struct{}) done := make(chan struct{})
go func() { go func() {
defer close(done) defer close(done)
c, err := listenerA.Accept() c, err := listener.Accept()
if err != nil { if err != nil {
t.Fatal(err) t.Error(err)
return
} }
c.Close() c.Close()
}() }()
return done
}
c, err := trB.Dial(listenerA.Multiaddr()) func dialOne(t *testing.T, tr *Transport, listener manet.Listener, expected ...int) int {
t.Helper()
done := acceptOne(t, listener)
c, err := tr.Dial(listener.Multiaddr())
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
port := c.LocalAddr().(*net.TCPAddr).Port
<-done <-done
c.Close() c.Close()
if len(expected) == 0 {
listenerB, err := trB.Listen(laddr) return port
if err != nil {
t.Fatal(err)
} }
defer listenerB.Close() for _, p := range expected {
if p == port {
return port
}
}
t.Errorf("dialed from %d, expected to dial from one of %v", port, expected)
return 0
}
done = make(chan struct{}) func TestNoneAndSingle(t *testing.T) {
go func() { var trA Transport
defer close(done) var trB Transport
c, err := listenerA.Accept() listenerA, err := trA.Listen(loopback)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
c.Close() defer listenerA.Close()
}()
dialOne(t, &trB, listenerA)
c, err = trB.Dial(listenerA.Multiaddr()) listenerB, err := trB.Listen(loopback)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
actual := c.LocalAddr().(*net.TCPAddr).Port defer listenerB.Close()
expected := listenerB.Addr().(*net.TCPAddr).Port
if actual != expected { dialOne(t, &trB, listenerA, listenerB.Addr().(*net.TCPAddr).Port)
t.Errorf("expected to use port %d, used port %d", expected, actual)
}
<-done
c.Close()
} }
func TestTwoLocal(t *testing.T) { func TestTwoLocal(t *testing.T) {
var trA Transport var trA Transport
var trB Transport var trB Transport
laddr, _ := ma.NewMultiaddr("/ip4/127.0.0.1/tcp/0") listenerA, err := trA.Listen(loopback)
listenerA, err := trA.Listen(laddr)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
defer listenerA.Close() defer listenerA.Close()
listenerB1, err := trB.Listen(laddr) listenerB1, err := trB.Listen(loopback)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
defer listenerB1.Close() defer listenerB1.Close()
listenerB2, err := trB.Listen(laddr) listenerB2, err := trB.Listen(loopback)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
defer listenerB2.Close() defer listenerB2.Close()
done := make(chan struct{}) dialOne(t, &trB, listenerA,
go func() { listenerB1.Addr().(*net.TCPAddr).Port,
defer close(done) listenerB2.Addr().(*net.TCPAddr).Port)
c, err := listenerA.Accept() }
func TestGlobalPreference(t *testing.T) {
if global == nil {
t.Skip("no global addresses configured")
return
}
testPrefer(t, loopback, loopback, global)
testPrefer(t, loopback, unspec, global)
testPrefer(t, global, unspec, global)
testPrefer(t, global, unspec, loopback)
}
func TestLoopbackPreference(t *testing.T) {
testPrefer(t, loopback, loopback, unspec)
}
func testPrefer(t *testing.T, listen, prefer, avoid ma.Multiaddr) {
var trA Transport
var trB Transport
listenerA, err := trA.Listen(listen)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
c.Close() defer listenerA.Close()
}()
c, err := trB.Dial(listenerA.Multiaddr()) listenerB1, err := trB.Listen(avoid)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
localPort := c.LocalAddr().(*net.TCPAddr).Port defer listenerB1.Close()
if localPort != listenerB1.Addr().(*net.TCPAddr).Port &&
localPort != listenerB2.Addr().(*net.TCPAddr).Port { dialOne(t, &trB, listenerA, listenerB1.Addr().(*net.TCPAddr).Port)
t.Fatal("didn't dial from one of our listener ports")
listenerB2, err := trB.Listen(prefer)
if err != nil {
t.Fatal(err)
} }
<-done defer listenerB2.Close()
c.Close()
dialOne(t, &trB, listenerA, listenerB2.Addr().(*net.TCPAddr).Port)
// Closing the listener should reset the dialer.
listenerB2.Close()
dialOne(t, &trB, listenerA, listenerB1.Addr().(*net.TCPAddr).Port)
} }
func TestLocalAndUnspecified(t *testing.T) { func TestGlobalToGlobal(t *testing.T) {
if global == nil {
t.Skip("no global addresses configured")
return
}
var trA Transport var trA Transport
var trB Transport var trB Transport
laddr, _ := ma.NewMultiaddr("/ip4/127.0.0.1/tcp/0") listenerA, err := trA.Listen(global)
unspec, _ := ma.NewMultiaddr("/ip4/0.0.0.0/tcp/0")
listenerA, err := trA.Listen(laddr)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
defer listenerA.Close() defer listenerA.Close()
listenerB1, err := trB.Listen(laddr) listenerB1, err := trB.Listen(loopback)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
defer listenerB1.Close() defer listenerB1.Close()
listenerB2, err := trB.Listen(unspec) // It works (random port)
dialOne(t, &trB, listenerA)
listenerB2, err := trB.Listen(global)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
defer listenerB2.Close() defer listenerB2.Close()
done := make(chan struct{}) // Uses global port.
go func() { dialOne(t, &trB, listenerA, listenerB2.Addr().(*net.TCPAddr).Port)
defer close(done)
c, err := listenerA.Accept() // Closing the listener should reset the dialer.
if err != nil { listenerB2.Close()
t.Fatal(err)
// It still works.
dialOne(t, &trB, listenerA)
}
func TestDuplicateGlobal(t *testing.T) {
if global == nil {
t.Skip("no global addresses configured")
return
} }
c.Close()
}()
c, err := trB.Dial(listenerA.Multiaddr()) var trA Transport
var trB Transport
listenerA, err := trA.Listen(global)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
actual := c.LocalAddr().(*net.TCPAddr).Port defer listenerA.Close()
expected := listenerB1.Addr().(*net.TCPAddr).Port
if actual != expected {
t.Errorf("expected to use port %d, used port %d", expected, actual)
}
<-done
c.Close()
// Closing the listener should reset the dialer.
listenerB1.Close()
done = make(chan struct{}) listenerB1, err := trB.Listen(global)
go func() {
defer close(done)
c, err := listenerA.Accept()
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
c.Close() defer listenerB1.Close()
}()
c, err = trB.Dial(listenerA.Multiaddr()) listenerB2, err := trB.Listen(global)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
actual = c.LocalAddr().(*net.TCPAddr).Port defer listenerB2.Close()
expected = listenerB2.Addr().(*net.TCPAddr).Port
if actual != expected { // Check which port we're using
t.Errorf("expected to use port %d, used port %d", expected, actual) port := dialOne(t, &trB, listenerA)
// Check consistency
for i := 0; i < 10; i++ {
dialOne(t, &trB, listenerA, port)
} }
<-done
c.Close()
} }
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment