예제 #1
0
func TestPeerSelectionConnClosed(t *testing.T) {
	ctx, cancel := NewContext(time.Second)
	defer cancel()

	WithVerifiedServer(t, nil, func(server *Channel, hostPort string) {
		client := testutils.NewServer(t, nil)
		defer client.Close()

		// Ping will create an outbound connection from client -> server.
		require.NoError(t, testutils.Ping(client, server), "Ping failed")

		waitTillInboundEmpty(t, server, client.PeerInfo().HostPort, func() {
			peer, ok := client.RootPeers().Get(server.PeerInfo().HostPort)
			require.True(t, ok, "Client has no peer for %v", server.PeerInfo())

			conn, err := peer.GetConnection(ctx)
			require.NoError(t, err, "Failed to get a connection")
			conn.Close()
		})

		// Make sure the closed connection is not used.
		for i := 0; i < 10; i++ {
			require.NoError(t, testutils.Ping(client, server), "Ping failed")
		}
	})
}
예제 #2
0
// TestCloseSendError tests that system errors are not attempted to be sent when
// a connection is closed, and ensures there's no race conditions such as the error
// frame being added to the channel just as it is closed.
func TestCloseSendError(t *testing.T) {
	var (
		closed  atomic.Uint32
		counter atomic.Uint32
	)

	opts := testutils.NewOpts().DisableLogVerification()
	serverCh := testutils.NewServer(t, opts)
	testutils.RegisterEcho(serverCh, func() {
		if counter.Inc() > 10 {
			// Close the server in a goroutine to possibly trigger more race conditions.
			go func() {
				closed.Inc()
				serverCh.Close()
			}()
		}
	})

	clientCh := testutils.NewClient(t, opts)

	// Create a connection that will be shared.
	require.NoError(t, testutils.Ping(clientCh, serverCh), "Ping from client to server failed")

	var wg sync.WaitGroup
	for i := 0; i < 100; i++ {
		wg.Add(1)
		go func() {
			time.Sleep(time.Duration(rand.Intn(1000)) * time.Microsecond)
			err := testutils.CallEcho(clientCh, serverCh.PeerInfo().HostPort, serverCh.ServiceName(), nil)
			if err != nil && closed.Load() == 0 {
				t.Errorf("Call failed: %v", err)
			}
			wg.Done()
		}()
	}

	// Wait for all the goroutines to end
	wg.Wait()

	clientCh.Close()
	goroutines.VerifyNoLeaks(t, nil)
}
예제 #3
0
// TestCloseSendError tests that system errors are not attempted to be sent when
// a connection is closed, and ensures there's no race conditions such as the error
// frame being added to the channel just as it is closed.
// TODO(prashant): This test is waiting for timeout, but socket close shouldn't wait for timeout.
func TestCloseSendError(t *testing.T) {
	closed := uint32(0)
	counter := uint32(0)

	serverCh := testutils.NewServer(t, nil)
	testutils.RegisterEcho(serverCh, func() {
		if atomic.AddUint32(&counter, 1) > 10 {
			// Close the server in a goroutine to possibly trigger more race conditions.
			go func() {
				atomic.AddUint32(&closed, 1)
				serverCh.Close()
			}()
		}
	})

	clientCh := testutils.NewClient(t, nil)

	// Create a connection that will be shared.
	require.NoError(t, testutils.Ping(clientCh, serverCh), "Ping from client to server failed")

	var wg sync.WaitGroup
	for i := 0; i < 100; i++ {
		wg.Add(1)
		go func() {
			time.Sleep(time.Duration(rand.Intn(1000)) * time.Microsecond)
			err := testutils.CallEcho(clientCh, serverCh, nil)
			if err != nil && atomic.LoadUint32(&closed) == 0 {
				t.Errorf("Call failed: %v", err)
			}
			wg.Done()
		}()
	}

	// Wait for all the goroutines to end
	wg.Wait()

	clientCh.Close()
	goroutines.VerifyNoLeaks(t, nil)
}