+func TestTCPClientReadTimeoutStartsAfterRequestWrite(t *testing.T) {
+ synctest.Test(t, func(t *testing.T) {
+ conn, peer := net.Pipe()
+ c := &tcpClient{conn: conn, unit: 1}
+ t.Cleanup(func() {
+ require.NoError(t, c.Close())
+ require.NoError(t, peer.Close())
+ })
+
+ done := make(chan error, 1)
+ go func() {
+ time.Sleep(500 * time.Millisecond)
+
+ var request [12]byte
+
+ _, err := io.ReadFull(peer, request[:])
+ done <- err
+ }()
+
+ started := time.Now()
+ _, err := c.ReadCoils(t.Context(), 1)
+ require.Error(t, err)
+ require.NoError(t, <-done)
+ require.Equal(t, 2500*time.Millisecond, time.Since(started))
+ })
+}
+
+func TestTCPClientStopsAfterCancelledRequestWrite(t *testing.T) {
+ synctest.Test(t, func(t *testing.T) {
+ conn, peer := net.Pipe()
+ t.Cleanup(func() {
+ require.NoError(t, peer.Close())
+ })
+
+ ctx, cancel := context.WithCancel(t.Context())
+ defer cancel()
+
+ transport := &interruptConn{
+ Conn: conn,
+ cancel: cancel,
+ interrupted: make(chan struct{}),
+ }
+ c := &tcpClient{conn: transport, unit: 1}
+ t.Cleanup(func() {
+ require.NoError(t, c.Close())
+ })
+
+ _, err := c.ReadCoils(ctx, 1)
+ require.ErrorIs(t, err, context.Canceled)
+ require.NotErrorIs(t, err, os.ErrDeadlineExceeded)
+ })
+}
+