route/vendor/github.com/bifurcation/mint/tls_test.go

245 lines
5.9 KiB
Go

package mint
import (
"fmt"
"net"
"strings"
"testing"
"time"
)
func newLocalListener(t *testing.T) net.Listener {
ln, err := net.Listen("tcp", "127.0.0.1:0")
if err != nil {
ln, err = net.Listen("tcp6", "[::1]:0")
}
if err != nil {
t.Fatal(err)
}
return ln
}
func TestDialTimeout(t *testing.T) {
if testing.Short() {
t.Skip("skipping in short mode")
}
listener := newLocalListener(t)
addr := listener.Addr().String()
defer listener.Close()
complete := make(chan bool)
defer close(complete)
go func() {
conn, err := listener.Accept()
if err != nil {
t.Error(err)
return
}
<-complete
conn.Close()
}()
dialer := &net.Dialer{
Timeout: 10 * time.Millisecond,
}
var err error
if _, err = DialWithDialer(dialer, "tcp", addr, nil); err == nil {
t.Fatal("DialWithTimeout completed successfully")
}
if !strings.Contains(err.Error(), "timed out") {
t.Errorf("resulting error not a timeout: %s", err)
}
}
func TestDialNonBlocking(t *testing.T) {
config := &Config{NonBlocking: true}
_, err := Dial("tcp", "localhost:1234", config)
assertEquals(t, err.Error(), "dialing not possible in non-blocking mode")
_, err = DialWithDialer(&net.Dialer{}, "tcp", "localhost:1234", config)
assertEquals(t, err.Error(), "dialing not possible in non-blocking mode")
}
func TestListenNonBlocking(t *testing.T) {
config := &Config{
NonBlocking: true,
Certificates: certificates,
}
_, err := Listen("tcp", "localhost:1234", config)
assertEquals(t, err.Error(), "listening not possible in non-blocking mode")
_, err = NewListener(newLocalListener(t), config)
assertEquals(t, err.Error(), "listening not possible in non-blocking mode")
}
// tests that Conn.Read returns (non-zero, io.EOF) instead of
// (non-zero, nil) when a Close (alertCloseNotify) is sitting right
// behind the application data in the buffer.
func DISABLEDTestConnReadNonzeroAndEOF(t *testing.T) {
// This test is racy: it assumes that after a write to a
// localhost TCP connection, the peer TCP connection can
// immediately read it. Because it's racy, we skip this test
// in short mode, and then retry it several times with an
// increasing sleep in between our final write (via srv.Close
// below) and the following read.
if testing.Short() {
t.Skip("skipping in short mode")
}
var err error
for delay := time.Millisecond; delay <= 64*time.Millisecond; delay *= 2 {
if err = testConnReadNonzeroAndEOF(t, delay); err == nil {
return
}
}
t.Error(err)
}
func testConnReadNonzeroAndEOF(t *testing.T, delay time.Duration) error {
ln := newLocalListener(t)
defer ln.Close()
srvCh := make(chan *Conn, 1)
var serr error
go func() {
sconn, err := ln.Accept()
if err != nil {
serr = err
srvCh <- nil
return
}
serverConfig := Config{ServerName: "example.com"}
srv := Server(sconn, &serverConfig)
if alert := srv.Handshake(); alert != AlertNoAlert {
serr = fmt.Errorf("handshake: %v", alert)
srvCh <- nil
return
}
srvCh <- srv
}()
clientConfig := Config{ServerName: "example.com"}
conn, err := Dial("tcp", ln.Addr().String(), &clientConfig)
if err != nil {
t.Fatal(err)
}
defer conn.Close()
srv := <-srvCh
if srv == nil {
return serr
}
buf := make([]byte, 16)
buf = buf[0:6]
// Consume NST.
zeroBuf := []byte{}
conn.Read(zeroBuf)
srv.Write([]byte("foobar"))
n, err := conn.Read(buf)
if n != 6 || err != nil || string(buf) != "foobar" {
return fmt.Errorf("Read = %d, %v, data %q; want 6, nil, foobar", n, err, buf)
}
srv.Write([]byte("foobartoo"))
n, err = conn.Read(buf)
if n != 6 || err != nil || string(buf) != "foobar" {
return fmt.Errorf("Read = %d, %v, data %q; want 6, nil, foobar", n, err, buf)
}
n, err = conn.Read(buf)
if n != 3 || err != nil || string(buf[0:3]) != "too" {
return fmt.Errorf("Read = %d, %v, data %q; want 3, nil, too", n, err, buf)
}
srv.Write([]byte("four"))
n, err = conn.Read(buf)
if n != 4 || err != nil || string(buf[0:4]) != "four" {
return fmt.Errorf("Read = %d, %v, data %q; want 4, nil, foor", n, err, buf)
}
srv.Write([]byte("abcdefgh"))
srv.Close()
time.Sleep(delay)
n, err = conn.Read(buf)
if n != 6 || string(buf) != "abcdef" {
return fmt.Errorf("Read = %d, buf= %q; want 6, abcdef", n, buf)
}
if err != nil {
return fmt.Errorf("First Read error = %v; want nil", err)
}
n, err = conn.Read(buf)
if n != 2 || string(buf[0:2]) != "gh" {
return fmt.Errorf("Read = %d, buf= %q; want 2, gh", n, buf)
}
return nil
}
func TestExchangeData(t *testing.T) {
ln := newLocalListener(t)
defer ln.Close()
srvCh := make(chan *Conn, 1)
var serr error
go func() {
sconn, err := ln.Accept()
if err != nil {
serr = err
srvCh <- nil
return
}
serverConfig := Config{ServerName: "example.com"}
srv := Server(sconn, &serverConfig)
if alert := srv.Handshake(); alert != AlertNoAlert {
serr = fmt.Errorf("handshake: %v", alert)
srvCh <- nil
return
}
srvCh <- srv
}()
clientConfig := Config{ServerName: "example.com"}
conn, err := Dial("tcp", ln.Addr().String(), &clientConfig)
if err != nil {
t.Fatal(err)
}
defer conn.Close()
srv := <-srvCh
assertNotNil(t, srv, "Server should have completed handshake")
buf := make([]byte, 16)
buf = buf[0:6]
srv.Write([]byte("foobar"))
n, err := conn.Read(buf)
if n != 6 || err != nil || string(buf) != "foobar" {
t.Fatalf("Read = %d, %v, data %q; want 6, nil, foobar", n, err, buf)
return
}
srv.Write([]byte("foobartoo"))
n, err = conn.Read(buf)
if n != 6 || err != nil || string(buf) != "foobar" {
t.Fatalf("Read = %d, %v, data %q; want 6, nil, foobar", n, err, buf)
return
}
n, err = conn.Read(buf)
if n != 3 || err != nil || string(buf[0:3]) != "too" {
t.Fatalf("Read = %d, %v, data %q; want 3, nil, too", n, err, buf)
return
}
srv.Write([]byte("four"))
n, err = conn.Read(buf)
if n != 4 || err != nil || string(buf[0:4]) != "four" {
t.Fatalf("Read = %d, %v, data %q; want 4, nil, four", n, err, buf)
return
}
return
}