Skip to content

Commit

Permalink
Add TestParallelHandshake test case
Browse files Browse the repository at this point in the history
Handshake are synchronized by a mutex, but there is a panicing
scenario when the first handshake fails.
  • Loading branch information
Danielius1922 authored and Sean-Der committed Aug 6, 2024
1 parent f3e8a9e commit fd4047a
Showing 1 changed file with 97 additions and 0 deletions.
97 changes: 97 additions & 0 deletions conn_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3614,3 +3614,100 @@ func TestConnectionState(t *testing.T) {
t.Fatal("ConnectionState should not be nil")
}
}

func TestParallelHandshake(t *testing.T) {
report := test.CheckRoutines(t)
defer report()

// Limit runtime in case of deadlocks
lim := test.TimeOut(time.Second * 10)
defer lim.Stop()

ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()

errChan := make(chan error, 2)
ca, cb := dpipe.Pipe()
serverCert, err := selfsign.GenerateSelfSigned()
if err != nil {
t.Fatal(err)
}
server, err := Server(dtlsnet.PacketConnFromConn(cb), cb.RemoteAddr(), &Config{
Certificates: []tls.Certificate{serverCert},
InsecureSkipVerify: true,
})
if err != nil {
t.Fatal(err)
}
defer func() {
_ = server.Close()
}()
go func() {
// Read from the server and always answer with "world"
for {
data := make([]byte, 8192)
_, errServer := server.Read(data) //nolint:contextcheck
if errServer != nil {
errChan <- errServer
return
}
if _, errServer := server.Write([]byte("world")); errServer != nil { //nolint:contextcheck
errChan <- errServer
return
}
}
}()

clientCert, err := selfsign.GenerateSelfSigned()
if err != nil {
t.Fatal(err)
}
client, err := Client(dtlsnet.PacketConnFromConn(ca), ca.RemoteAddr(), &Config{
Certificates: []tls.Certificate{clientCert},
// InsecureSkipVerify: true,
})
if err != nil {
t.Fatal(err)
}

clientReadChan := make(chan []byte, 1000)
go func() {
for {
data := make([]byte, 8192)
n, err := client.Read(data)
if err != nil {
errChan <- err
return
}
clientReadChan <- data[:n]
}
}()

if _, err := client.Write([]byte("hello")); err != nil {
t.Fatal(err)
}

select {
case data := <-clientReadChan:
if string(data) != "world" {
t.Fatalf("expected 'world', got '%s'", string(data))
}
_ = client.Close()
case err := <-errChan:
t.Fatal(err)
case <-ctx.Done():
t.Fatal("timeout")
}

// wait for both server and client to close
for i := 0; i < 2; i++ {
select {
case err := <-errChan:
if !errors.Is(err, io.EOF) {
t.Fatal(err)
}
case <-ctx.Done():
t.Fatal("timeout")
}
}
}

0 comments on commit fd4047a

Please sign in to comment.