func TestActiveCallReq(t *testing.T) { t.Skip("Test skipped due to unreliable way to test for protocol errors") ctx, cancel := NewContext(time.Second) defer cancel() // Note: This test cannot use log verification as the duplicate ID causes a log. // It does not use a verified server, as it leaks a message exchange due to the // modification of IDs in the relay. opts := testutils.NewOpts().DisableLogVerification() testutils.WithServer(t, opts, func(ch *Channel, hostPort string) { gotCall := make(chan struct{}) unblock := make(chan struct{}) testutils.RegisterFunc(ch, "blocked", func(ctx context.Context, args *raw.Args) (*raw.Res, error) { gotCall <- struct{}{} <-unblock return &raw.Res{}, nil }) relayFunc := func(outgoing bool, frame *Frame) *Frame { if outgoing && frame.Header.ID == 3 { frame.Header.ID = 2 } return frame } relayHostPort, closeRelay := testutils.FrameRelay(t, hostPort, relayFunc) defer closeRelay() firstComplete := make(chan struct{}) go func() { // This call will block until we close unblock. raw.Call(ctx, ch, relayHostPort, ch.PeerInfo().ServiceName, "blocked", nil, nil) close(firstComplete) }() // Wait for the first call to be received by the server <-gotCall // Make a new call, which should fail _, _, _, err := raw.Call(ctx, ch, relayHostPort, ch.PeerInfo().ServiceName, "blocked", nil, nil) assert.Error(t, err, "Expect error") assert.True(t, strings.Contains(err.Error(), "already active"), "expected already active error, got %v", err) close(unblock) <-firstComplete }) }
func TestActiveCallReq(t *testing.T) { ctx, cancel := NewContext(time.Second) defer cancel() // Note: This test leaks a message exchange due to the modification of IDs in the relay. require.NoError(t, testutils.WithServer(nil, func(ch *Channel, hostPort string) { gotCall := make(chan struct{}) unblock := make(chan struct{}) testutils.RegisterFunc(t, ch, "blocked", func(ctx context.Context, args *raw.Args) (*raw.Res, error) { gotCall <- struct{}{} <-unblock return &raw.Res{}, nil }) relayFunc := func(outgoing bool, frame *Frame) *Frame { if outgoing && frame.Header.ID == 2 { frame.Header.ID = 3 } return frame } relayHostPort, closeRelay := testutils.FrameRelay(t, hostPort, relayFunc) defer closeRelay() go func() { // This call will block until we close unblock. raw.Call(ctx, ch, relayHostPort, ch.PeerInfo().ServiceName, "blocked", nil, nil) }() // Wait for the first call to be received by the server <-gotCall // Make a new call, which should fail _, _, _, err := raw.Call(ctx, ch, relayHostPort, ch.PeerInfo().ServiceName, "blocked", nil, nil) assert.Error(t, err, "Expect error") assert.True(t, strings.Contains(err.Error(), "already active"), "expected already active error, got %v", err) close(unblock) })) }
func TestConnectTimeout(t *testing.T) { opts := testutils.NewOpts().DisableLogVerification() testutils.WithTestServer(t, opts, func(ts *testutils.TestServer) { // Set up a relay that will delay the initial init req. testComplete := make(chan struct{}) relayFunc := func(outgoing bool, f *Frame) *Frame { select { case <-time.After(testutils.Timeout(200 * time.Millisecond)): return f case <-testComplete: // TODO: We should be able to forward the frame and have this test not fail. // Currently, it fails since the sequence of events is: // Server receives a TCP connection // Channel.Close() is called on the server // Server's TCP connection receives an init req // Since we don't currently track pending connections, the open TCP connection is not closed, and // we process the init req. This leaves an open connection at the end of the test. return nil } } relay, shutdown := testutils.FrameRelay(t, ts.HostPort(), relayFunc) defer shutdown() // Make a call with a long timeout, but short connect timeout. // We expect the call to fall almost immediately with ErrTimeout. ctx, cancel := NewContextBuilder(2 * time.Second). SetConnectTimeout(testutils.Timeout(100 * time.Millisecond)). Build() defer cancel() client := ts.NewClient(opts) err := client.Ping(ctx, relay) assert.Equal(t, ErrTimeout, err, "Ping should timeout due to timeout relay") // Note: we do not defer this, as we need to close(testComplete) before // we call shutdown since shutdown waits for the relay to close, which // is stuck waiting inside of our custom relay function. close(testComplete) }) }