dockerfiles/anylink/dtls-2.0.9/conn_go_test.go

170 lines
3.8 KiB
Go

// +build !js
package dtls
import (
"bytes"
"context"
"crypto/tls"
"net"
"testing"
"time"
"github.com/pion/dtls/v2/internal/net/dpipe"
"github.com/pion/dtls/v2/pkg/crypto/selfsign"
"github.com/pion/transport/test"
)
func TestContextConfig(t *testing.T) {
// Limit runtime in case of deadlocks
lim := test.TimeOut(time.Second * 20)
defer lim.Stop()
report := test.CheckRoutines(t)
defer report()
addrListen, err := net.ResolveUDPAddr("udp", "localhost:0")
if err != nil {
t.Fatalf("Unexpected error: %v", err)
}
// Dummy listener
listen, err := net.ListenUDP("udp", addrListen)
if err != nil {
t.Fatalf("Unexpected error: %v", err)
}
defer func() {
_ = listen.Close()
}()
addr := listen.LocalAddr().(*net.UDPAddr)
cert, err := selfsign.GenerateSelfSigned()
if err != nil {
t.Fatalf("Unexpected error: %v", err)
}
config := &Config{
ConnectContextMaker: func() (context.Context, func()) {
return context.WithTimeout(context.Background(), 40*time.Millisecond)
},
Certificates: []tls.Certificate{cert},
}
dials := map[string]struct {
f func() (func() (net.Conn, error), func())
order []byte
}{
"Dial": {
f: func() (func() (net.Conn, error), func()) {
return func() (net.Conn, error) {
return Dial("udp", addr, config)
}, func() {
}
},
order: []byte{0, 1, 2},
},
"DialWithContext": {
f: func() (func() (net.Conn, error), func()) {
ctx, cancel := context.WithTimeout(context.Background(), 80*time.Millisecond)
return func() (net.Conn, error) {
return DialWithContext(ctx, "udp", addr, config)
}, func() {
cancel()
}
},
order: []byte{0, 2, 1},
},
"Client": {
f: func() (func() (net.Conn, error), func()) {
ca, _ := dpipe.Pipe()
return func() (net.Conn, error) {
return Client(ca, config)
}, func() {
_ = ca.Close()
}
},
order: []byte{0, 1, 2},
},
"ClientWithContext": {
f: func() (func() (net.Conn, error), func()) {
ctx, cancel := context.WithTimeout(context.Background(), 80*time.Millisecond)
ca, _ := dpipe.Pipe()
return func() (net.Conn, error) {
return ClientWithContext(ctx, ca, config)
}, func() {
cancel()
_ = ca.Close()
}
},
order: []byte{0, 2, 1},
},
"Server": {
f: func() (func() (net.Conn, error), func()) {
ca, _ := dpipe.Pipe()
return func() (net.Conn, error) {
return Server(ca, config)
}, func() {
_ = ca.Close()
}
},
order: []byte{0, 1, 2},
},
"ServerWithContext": {
f: func() (func() (net.Conn, error), func()) {
ctx, cancel := context.WithTimeout(context.Background(), 80*time.Millisecond)
ca, _ := dpipe.Pipe()
return func() (net.Conn, error) {
return ServerWithContext(ctx, ca, config)
}, func() {
cancel()
_ = ca.Close()
}
},
order: []byte{0, 2, 1},
},
}
for name, dial := range dials {
dial := dial
t.Run(name, func(t *testing.T) {
done := make(chan struct{})
go func() {
d, cancel := dial.f()
conn, err := d()
defer cancel()
if netErr, ok := err.(net.Error); !ok || !netErr.Timeout() {
t.Errorf("Client error exp(Temporary network error) failed(%v)", err)
close(done)
return
}
done <- struct{}{}
if err == nil {
_ = conn.Close()
}
}()
var order []byte
early := time.After(20 * time.Millisecond)
late := time.After(60 * time.Millisecond)
func() {
for len(order) < 3 {
select {
case <-early:
order = append(order, 0)
case _, ok := <-done:
if !ok {
return
}
order = append(order, 1)
case <-late:
order = append(order, 2)
}
}
}()
if !bytes.Equal(dial.order, order) {
t.Errorf("Invalid cancel timing, expected: %v, got: %v", dial.order, order)
}
})
}
}