|
|
@ -1,7 +1,9 @@ |
|
|
|
package privval |
|
|
|
|
|
|
|
import ( |
|
|
|
"io/ioutil" |
|
|
|
"net" |
|
|
|
"os" |
|
|
|
"testing" |
|
|
|
"time" |
|
|
|
|
|
|
@ -18,67 +20,114 @@ func newPrivKey() ed25519.PrivKeyEd25519 { |
|
|
|
//-------------------------------------------
|
|
|
|
// tests
|
|
|
|
|
|
|
|
func TestTCPListenerAcceptDeadline(t *testing.T) { |
|
|
|
type listenerTestCase struct { |
|
|
|
description string // For test reporting purposes.
|
|
|
|
listener net.Listener |
|
|
|
dialer Dialer |
|
|
|
} |
|
|
|
|
|
|
|
// testUnixAddr will attempt to obtain a platform-independent temporary file
|
|
|
|
// name for a Unix socket
|
|
|
|
func testUnixAddr() (string, error) { |
|
|
|
f, err := ioutil.TempFile("", "tendermint-privval-test") |
|
|
|
if err != nil { |
|
|
|
return "", err |
|
|
|
} |
|
|
|
addr := f.Name() |
|
|
|
f.Close() |
|
|
|
os.Remove(addr) |
|
|
|
return addr, nil |
|
|
|
} |
|
|
|
|
|
|
|
func tcpListenerTestCase(t *testing.T, acceptDeadline, connectDeadline time.Duration) listenerTestCase { |
|
|
|
ln, err := net.Listen("tcp", "127.0.0.1:0") |
|
|
|
if err != nil { |
|
|
|
t.Fatal(err) |
|
|
|
} |
|
|
|
|
|
|
|
tcpLn := NewTCPListener(ln, newPrivKey()) |
|
|
|
TCPListenerAcceptDeadline(time.Millisecond)(tcpLn) |
|
|
|
TCPListenerConnDeadline(time.Second)(tcpLn) |
|
|
|
|
|
|
|
_, err = tcpLn.Accept() |
|
|
|
opErr, ok := err.(*net.OpError) |
|
|
|
if !ok { |
|
|
|
t.Fatalf("have %v, want *net.OpError", err) |
|
|
|
} |
|
|
|
|
|
|
|
if have, want := opErr.Op, "accept"; have != want { |
|
|
|
t.Errorf("have %v, want %v", have, want) |
|
|
|
TCPListenerAcceptDeadline(acceptDeadline)(tcpLn) |
|
|
|
TCPListenerConnDeadline(connectDeadline)(tcpLn) |
|
|
|
return listenerTestCase{ |
|
|
|
description: "TCP", |
|
|
|
listener: tcpLn, |
|
|
|
dialer: DialTCPFn(ln.Addr().String(), testConnDeadline, newPrivKey()), |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
func TestTCPListenerConnDeadline(t *testing.T) { |
|
|
|
ln, err := net.Listen("tcp", "127.0.0.1:0") |
|
|
|
func unixListenerTestCase(t *testing.T, acceptDeadline, connectDeadline time.Duration) listenerTestCase { |
|
|
|
addr, err := testUnixAddr() |
|
|
|
if err != nil { |
|
|
|
t.Fatal(err) |
|
|
|
} |
|
|
|
ln, err := net.Listen("unix", addr) |
|
|
|
if err != nil { |
|
|
|
t.Fatal(err) |
|
|
|
} |
|
|
|
|
|
|
|
tcpLn := NewTCPListener(ln, newPrivKey()) |
|
|
|
TCPListenerAcceptDeadline(time.Second)(tcpLn) |
|
|
|
TCPListenerConnDeadline(time.Millisecond)(tcpLn) |
|
|
|
|
|
|
|
readyc := make(chan struct{}) |
|
|
|
donec := make(chan struct{}) |
|
|
|
go func(ln net.Listener) { |
|
|
|
defer close(donec) |
|
|
|
|
|
|
|
c, err := ln.Accept() |
|
|
|
if err != nil { |
|
|
|
t.Fatal(err) |
|
|
|
} |
|
|
|
<-readyc |
|
|
|
unixLn := NewUnixListener(ln) |
|
|
|
UnixListenerAcceptDeadline(acceptDeadline)(unixLn) |
|
|
|
UnixListenerConnDeadline(connectDeadline)(unixLn) |
|
|
|
return listenerTestCase{ |
|
|
|
description: "Unix", |
|
|
|
listener: unixLn, |
|
|
|
dialer: DialUnixFn(addr), |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
time.Sleep(2 * time.Millisecond) |
|
|
|
func listenerTestCases(t *testing.T, acceptDeadline, connectDeadline time.Duration) []listenerTestCase { |
|
|
|
return []listenerTestCase{ |
|
|
|
tcpListenerTestCase(t, acceptDeadline, connectDeadline), |
|
|
|
unixListenerTestCase(t, acceptDeadline, connectDeadline), |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
msg := make([]byte, 200) |
|
|
|
_, err = c.Read(msg) |
|
|
|
func TestListenerAcceptDeadlines(t *testing.T) { |
|
|
|
for _, tc := range listenerTestCases(t, time.Millisecond, time.Second) { |
|
|
|
_, err := tc.listener.Accept() |
|
|
|
opErr, ok := err.(*net.OpError) |
|
|
|
if !ok { |
|
|
|
t.Fatalf("have %v, want *net.OpError", err) |
|
|
|
t.Fatalf("for %s listener, have %v, want *net.OpError", tc.description, err) |
|
|
|
} |
|
|
|
|
|
|
|
if have, want := opErr.Op, "read"; have != want { |
|
|
|
t.Errorf("have %v, want %v", have, want) |
|
|
|
if have, want := opErr.Op, "accept"; have != want { |
|
|
|
t.Errorf("for %s listener, have %v, want %v", tc.description, have, want) |
|
|
|
} |
|
|
|
}(tcpLn) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
dialer := DialTCPFn(ln.Addr().String(), testConnDeadline, newPrivKey()) |
|
|
|
_, err = dialer() |
|
|
|
if err != nil { |
|
|
|
t.Fatal(err) |
|
|
|
func TestListenerConnectDeadlines(t *testing.T) { |
|
|
|
for _, tc := range listenerTestCases(t, time.Second, time.Millisecond) { |
|
|
|
readyc := make(chan struct{}) |
|
|
|
donec := make(chan struct{}) |
|
|
|
go func(ln net.Listener) { |
|
|
|
defer close(donec) |
|
|
|
|
|
|
|
c, err := ln.Accept() |
|
|
|
if err != nil { |
|
|
|
t.Fatal(err) |
|
|
|
} |
|
|
|
<-readyc |
|
|
|
|
|
|
|
time.Sleep(2 * time.Millisecond) |
|
|
|
|
|
|
|
msg := make([]byte, 200) |
|
|
|
_, err = c.Read(msg) |
|
|
|
opErr, ok := err.(*net.OpError) |
|
|
|
if !ok { |
|
|
|
t.Fatalf("for %s listener, have %v, want *net.OpError", tc.description, err) |
|
|
|
} |
|
|
|
|
|
|
|
if have, want := opErr.Op, "read"; have != want { |
|
|
|
t.Errorf("for %s listener, have %v, want %v", tc.description, have, want) |
|
|
|
} |
|
|
|
}(tc.listener) |
|
|
|
|
|
|
|
_, err := tc.dialer() |
|
|
|
if err != nil { |
|
|
|
t.Fatal(err) |
|
|
|
} |
|
|
|
close(readyc) |
|
|
|
<-donec |
|
|
|
} |
|
|
|
close(readyc) |
|
|
|
<-donec |
|
|
|
} |