Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

transport tests: add deadline tests #2286

Merged
merged 14 commits into from
Aug 19, 2023
90 changes: 90 additions & 0 deletions p2p/test/transport/deadline_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
package transport_integration

import (
"context"
"net"
"testing"
"time"

"github.com/libp2p/go-libp2p/core/network"
"github.com/libp2p/go-libp2p/core/peer"
"github.com/stretchr/testify/require"
)

func TestReadWriteDeadlines(t *testing.T) {
// Send a lot of data so that writes have to flush (can't just buffer it all)
sendBuf := make([]byte, 10<<20)
for _, tc := range transportsToTest {
t.Run(tc.Name, func(t *testing.T) {
listener := tc.HostGenerator(t, TransportTestCaseOpts{})
defer listener.Close()
dialer := tc.HostGenerator(t, TransportTestCaseOpts{NoListen: true})
defer dialer.Close()

require.NoError(t, dialer.Connect(context.Background(), peer.AddrInfo{
ID: listener.ID(),
Addrs: listener.Addrs(),
}))

// This simply stalls
listener.SetStreamHandler("/stall", func(s network.Stream) {
time.Sleep(time.Hour)
s.Close()
})

t.Run("ReadDeadline", func(t *testing.T) {
s, err := dialer.NewStream(context.Background(), listener.ID(), "/stall")
require.NoError(t, err)
defer s.Close()

start := time.Now()
// Set a deadline
s.SetReadDeadline(time.Now().Add(10 * time.Millisecond))
buf := make([]byte, 1)
_, err = s.Read(buf)
require.Error(t, err)
require.True(t, err.(net.Error).Timeout())
require.Less(t, time.Since(start), 1*time.Second)
})

t.Run("WriteDeadline", func(t *testing.T) {
s, err := dialer.NewStream(context.Background(), listener.ID(), "/stall")
require.NoError(t, err)
defer s.Close()

// Set a deadline
s.SetWriteDeadline(time.Now().Add(10 * time.Millisecond))
start := time.Now()
_, err = s.Write(sendBuf)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why would this run into the deadline? We could just send all the data, right?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The sendBuf is 1 MiB. Unless we can send 1 MiB in 10ms at the start this would hit the deadline. I could increase the sendbuf to 10 MiB instead to make it even less likely.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

bumped to 10MiB

require.Error(t, err)
require.True(t, err.(net.Error).Timeout())
require.Less(t, time.Since(start), 1*time.Second)
})

// Like the above, but with SetDeadline
t.Run("SetDeadline", func(t *testing.T) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure if we need this test.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not? Is the thought that this is simply calling Set{Read,Write}Deadline? I don't think that is enforced and a transport could forget to implement this.

for _, op := range []string{"Read", "Write"} {
t.Run(op, func(t *testing.T) {
s, err := dialer.NewStream(context.Background(), listener.ID(), "/stall")
require.NoError(t, err)
defer s.Close()

// Set a deadline
s.SetDeadline(time.Now().Add(10 * time.Millisecond))
start := time.Now()

if op == "Read" {
buf := make([]byte, 1)
_, err = s.Read(buf)
} else {
_, err = s.Write(sendBuf)
}
require.Error(t, err)
require.True(t, err.(net.Error).Timeout())
require.Less(t, time.Since(start), 1*time.Second)
})
}
})
})
}
}