@ -58,6 +58,7 @@
# include "src/core/lib/security/credentials/fake/fake_credentials.h"
# include "src/core/lib/service_config/service_config.h"
# include "src/core/lib/service_config/service_config_impl.h"
# include "src/core/lib/surface/server.h"
# include "src/cpp/client/secure_credentials.h"
# include "src/cpp/server/secure_server_credentials.h"
# include "src/proto/grpc/testing/echo.grpc.pb.h"
@ -324,8 +325,7 @@ class ClientLbEnd2endTest : public ::testing::Test {
const bool success =
SendRpc ( stub , & response , 2000 , & status , wait_for_ready ) ;
ASSERT_TRUE ( success ) < < " From " < < location . file ( ) < < " : " < < location . line ( )
< < " \n "
< < " Error: " < < status . error_message ( ) < < " "
< < " \n Error: " < < status . error_message ( ) < < " "
< < status . error_details ( ) ;
ASSERT_EQ ( response . message ( ) , kRequestMessage )
< < " From " < < location . file ( ) < < " : " < < location . line ( ) ;
@ -399,20 +399,44 @@ class ClientLbEnd2endTest : public ::testing::Test {
for ( const auto & server : servers_ ) server - > service_ . ResetCounters ( ) ;
}
void WaitForServer (
bool SeenAllServers ( size_t start_index , size_t stop_index ) {
for ( size_t i = start_index ; i < stop_index ; + + i ) {
if ( servers_ [ i ] - > service_ . request_count ( ) = = 0 ) return false ;
}
return true ;
}
void WaitForServers (
const std : : unique_ptr < grpc : : testing : : EchoTestService : : Stub > & stub ,
size_t server_idx , const grpc_core : : DebugLocation & location ,
bool ignore_failure = false ) {
do {
size_t start_index , size_t stop_index ,
const grpc_core : : DebugLocation & location , bool ignore_failure = false ) {
auto deadline =
absl : : Now ( ) + ( absl : : Seconds ( 30 ) * grpc_test_slowdown_factor ( ) ) ;
gpr_log ( GPR_INFO ,
" ========= WAITING FOR BACKENDS [% " PRIuPTR " , % " PRIuPTR
" ) ========== " ,
start_index , stop_index ) ;
while ( ! SeenAllServers ( start_index , stop_index ) ) {
if ( ignore_failure ) {
SendRpc ( stub ) ;
} else {
CheckRpcSendOk ( stub , location , true ) ;
}
} while ( servers_ [ server_idx ] - > service_ . request_count ( ) = = 0 ) ;
EXPECT_LE ( absl : : Now ( ) , deadline )
< < " at " < < location . file ( ) < < " : " < < location . line ( ) ;
if ( absl : : Now ( ) > = deadline ) break ;
}
ResetCounters ( ) ;
}
void WaitForServer (
const std : : unique_ptr < grpc : : testing : : EchoTestService : : Stub > & stub ,
size_t server_index , const grpc_core : : DebugLocation & location ,
bool ignore_failure = false ) {
WaitForServers ( stub , server_index , server_index + 1 , location ,
ignore_failure ) ;
}
bool WaitForChannelState (
Channel * channel ,
const std : : function < bool ( grpc_connectivity_state ) > & predicate ,
@ -494,7 +518,42 @@ TEST_F(ClientLbEnd2endTest, ChannelStateConnectingWhenResolving) {
EXPECT_TRUE ( WaitForChannelReady ( channel . get ( ) ) ) ;
}
TEST_F ( ClientLbEnd2endTest , PickFirst ) {
TEST_F ( ClientLbEnd2endTest , ChannelIdleness ) {
// Start server.
const int kNumServers = 1 ;
StartServers ( kNumServers ) ;
// Set max idle time and build the channel.
ChannelArguments args ;
args . SetInt ( GRPC_ARG_CLIENT_IDLE_TIMEOUT_MS , 1000 ) ;
auto response_generator = BuildResolverResponseGenerator ( ) ;
auto channel = BuildChannel ( " " , response_generator , args ) ;
auto stub = BuildStub ( channel ) ;
// The initial channel state should be IDLE.
EXPECT_EQ ( channel - > GetState ( false ) , GRPC_CHANNEL_IDLE ) ;
// After sending RPC, channel state should be READY.
gpr_log ( GPR_INFO , " *** SENDING RPC, CHANNEL SHOULD CONNECT *** " ) ;
response_generator . SetNextResolution ( GetServersPorts ( ) ) ;
CheckRpcSendOk ( stub , DEBUG_LOCATION ) ;
EXPECT_EQ ( channel - > GetState ( false ) , GRPC_CHANNEL_READY ) ;
// After a period time not using the channel, the channel state should switch
// to IDLE.
gpr_log ( GPR_INFO , " *** WAITING FOR CHANNEL TO GO IDLE *** " ) ;
gpr_sleep_until ( grpc_timeout_milliseconds_to_deadline ( 1200 ) ) ;
EXPECT_EQ ( channel - > GetState ( false ) , GRPC_CHANNEL_IDLE ) ;
// Sending a new RPC should awake the IDLE channel.
gpr_log ( GPR_INFO , " *** SENDING ANOTHER RPC, CHANNEL SHOULD RECONNECT *** " ) ;
response_generator . SetNextResolution ( GetServersPorts ( ) ) ;
CheckRpcSendOk ( stub , DEBUG_LOCATION ) ;
EXPECT_EQ ( channel - > GetState ( false ) , GRPC_CHANNEL_READY ) ;
}
//
// pick_first tests
//
using PickFirstTest = ClientLbEnd2endTest ;
TEST_F ( PickFirstTest , Basic ) {
// Start servers and send one RPC per server.
const int kNumServers = 3 ;
StartServers ( kNumServers ) ;
@ -521,7 +580,7 @@ TEST_F(ClientLbEnd2endTest, PickFirst) {
EXPECT_EQ ( " pick_first " , channel - > GetLoadBalancingPolicyName ( ) ) ;
}
TEST_F ( ClientLbEnd2end Test, PickFirst ProcessPending) {
TEST_F ( PickFirst Test, ProcessPending ) {
StartServers ( 1 ) ; // Single server
auto response_generator = BuildResolverResponseGenerator ( ) ;
auto channel = BuildChannel (
@ -541,7 +600,7 @@ TEST_F(ClientLbEnd2endTest, PickFirstProcessPending) {
CheckRpcSendOk ( second_stub , DEBUG_LOCATION ) ;
}
TEST_F ( ClientLbEnd2end Test, PickFirst SelectsReadyAtStartup) {
TEST_F ( PickFirst Test, SelectsReadyAtStartup ) {
ChannelArguments args ;
constexpr int kInitialBackOffMs = 5000 ;
args . SetInt ( GRPC_ARG_INITIAL_RECONNECT_BACKOFF_MS , kInitialBackOffMs ) ;
@ -567,7 +626,7 @@ TEST_F(ClientLbEnd2endTest, PickFirstSelectsReadyAtStartup) {
EXPECT_TRUE ( WaitForChannelReady ( channel2 . get ( ) , 1 /* timeout_seconds */ ) ) ;
}
TEST_F ( ClientLbEnd2end Test, PickFirst BackOffInitialReconnect) {
TEST_F ( PickFirst Test, BackOffInitialReconnect ) {
ChannelArguments args ;
constexpr int kInitialBackOffMs = 100 ;
args . SetInt ( GRPC_ARG_INITIAL_RECONNECT_BACKOFF_MS , kInitialBackOffMs ) ;
@ -599,7 +658,7 @@ TEST_F(ClientLbEnd2endTest, PickFirstBackOffInitialReconnect) {
0 ) ;
}
TEST_F ( ClientLbEnd2end Test, PickFirst BackOffMinReconnect) {
TEST_F ( PickFirst Test, BackOffMinReconnect ) {
ChannelArguments args ;
constexpr int kMinReconnectBackOffMs = 1000 ;
args . SetInt ( GRPC_ARG_MIN_RECONNECT_BACKOFF_MS , kMinReconnectBackOffMs ) ;
@ -625,7 +684,7 @@ TEST_F(ClientLbEnd2endTest, PickFirstBackOffMinReconnect) {
EXPECT_GE ( waited . millis ( ) , kMinReconnectBackOffMs - 1 ) ;
}
TEST_F ( ClientLbEnd2end Test, PickFirst ResetConnectionBackoff) {
TEST_F ( PickFirst Test, ResetConnectionBackoff ) {
ChannelArguments args ;
constexpr int kInitialBackOffMs = 1000 ;
args . SetInt ( GRPC_ARG_INITIAL_RECONNECT_BACKOFF_MS , kInitialBackOffMs ) ;
@ -660,7 +719,7 @@ TEST_F(ClientLbEnd2endTest, PickFirstResetConnectionBackoff) {
}
TEST_F ( ClientLbEnd2endTest ,
PickFirst ResetConnectionBackoffNextAttemptStartsImmediately) {
ResetConnectionBackoffNextAttemptStartsImmediately ) {
ChannelArguments args ;
constexpr int kInitialBackOffMs = 1000 ;
args . SetInt ( GRPC_ARG_INITIAL_RECONNECT_BACKOFF_MS , kInitialBackOffMs ) ;
@ -707,7 +766,7 @@ TEST_F(ClientLbEnd2endTest,
EXPECT_LT ( waited . millis ( ) , kWaitMs ) ;
}
TEST_F ( ClientLbEnd2end Test, PickFirst Updates) {
TEST_F ( PickFirst Test, Updates ) {
// Start servers and send one RPC per server.
const int kNumServers = 3 ;
StartServers ( kNumServers ) ;
@ -756,7 +815,7 @@ TEST_F(ClientLbEnd2endTest, PickFirstUpdates) {
EXPECT_EQ ( " pick_first " , channel - > GetLoadBalancingPolicyName ( ) ) ;
}
TEST_F ( ClientLbEnd2end Test, PickFirst UpdateSuperset) {
TEST_F ( PickFirst Test, UpdateSuperset ) {
// Start servers and send one RPC per server.
const int kNumServers = 3 ;
StartServers ( kNumServers ) ;
@ -789,7 +848,7 @@ TEST_F(ClientLbEnd2endTest, PickFirstUpdateSuperset) {
EXPECT_EQ ( " pick_first " , channel - > GetLoadBalancingPolicyName ( ) ) ;
}
TEST_F ( ClientLbEnd2end Test, PickFirst UpdateToUnconnected) {
TEST_F ( PickFirst Test, UpdateToUnconnected ) {
const int kNumServers = 2 ;
CreateServers ( kNumServers ) ;
StartServer ( 0 ) ;
@ -822,7 +881,7 @@ TEST_F(ClientLbEnd2endTest, PickFirstUpdateToUnconnected) {
EXPECT_TRUE ( WaitForChannelReady ( channel . get ( ) ) ) ;
}
TEST_F ( ClientLbEnd2end Test, PickFirst GlobalSubchannelPool) {
TEST_F ( PickFirst Test, GlobalSubchannelPool ) {
// Start one server.
const int kNumServers = 1 ;
StartServers ( kNumServers ) ;
@ -847,7 +906,7 @@ TEST_F(ClientLbEnd2endTest, PickFirstGlobalSubchannelPool) {
EXPECT_EQ ( 1UL , servers_ [ 0 ] - > service_ . clients ( ) . size ( ) ) ;
}
TEST_F ( ClientLbEnd2end Test, PickFirst LocalSubchannelPool) {
TEST_F ( PickFirst Test, LocalSubchannelPool ) {
// Start one server.
const int kNumServers = 1 ;
StartServers ( kNumServers ) ;
@ -874,7 +933,7 @@ TEST_F(ClientLbEnd2endTest, PickFirstLocalSubchannelPool) {
EXPECT_EQ ( 2UL , servers_ [ 0 ] - > service_ . clients ( ) . size ( ) ) ;
}
TEST_F ( ClientLbEnd2end Test, PickFirst ManyUpdates) {
TEST_F ( PickFirst Test, ManyUpdates ) {
const int kNumUpdates = 1000 ;
const int kNumServers = 3 ;
StartServers ( kNumServers ) ;
@ -894,7 +953,7 @@ TEST_F(ClientLbEnd2endTest, PickFirstManyUpdates) {
EXPECT_EQ ( " pick_first " , channel - > GetLoadBalancingPolicyName ( ) ) ;
}
TEST_F ( ClientLbEnd2end Test, PickFirst ReresolutionNoSelected) {
TEST_F ( PickFirst Test, ReresolutionNoSelected ) {
// Prepare the ports for up servers and down servers.
const int kNumServers = 3 ;
const int kNumAliveServers = 1 ;
@ -926,7 +985,7 @@ TEST_F(ClientLbEnd2endTest, PickFirstReresolutionNoSelected) {
EXPECT_EQ ( " pick_first " , channel - > GetLoadBalancingPolicyName ( ) ) ;
}
TEST_F ( ClientLbEnd2end Test, PickFirst ReconnectWithoutNewResolverResult) {
TEST_F ( PickFirst Test, ReconnectWithoutNewResolverResult ) {
std : : vector < int > ports = { grpc_pick_unused_port_or_die ( ) } ;
StartServers ( 1 , ports ) ;
auto response_generator = BuildResolverResponseGenerator ( ) ;
@ -943,8 +1002,7 @@ TEST_F(ClientLbEnd2endTest, PickFirstReconnectWithoutNewResolverResult) {
WaitForServer ( stub , 0 , DEBUG_LOCATION ) ;
}
TEST_F ( ClientLbEnd2endTest ,
PickFirstReconnectWithoutNewResolverResultStartsFromTopOfList ) {
TEST_F ( PickFirstTest , ReconnectWithoutNewResolverResultStartsFromTopOfList ) {
std : : vector < int > ports = { grpc_pick_unused_port_or_die ( ) ,
grpc_pick_unused_port_or_die ( ) } ;
CreateServers ( 2 , ports ) ;
@ -963,7 +1021,7 @@ TEST_F(ClientLbEnd2endTest,
WaitForServer ( stub , 0 , DEBUG_LOCATION ) ;
}
TEST_F ( ClientLbEnd2end Test, PickFirst CheckStateBeforeStartWatch) {
TEST_F ( PickFirst Test, CheckStateBeforeStartWatch ) {
std : : vector < int > ports = { grpc_pick_unused_port_or_die ( ) } ;
StartServers ( 1 , ports ) ;
auto response_generator = BuildResolverResponseGenerator ( ) ;
@ -1003,7 +1061,7 @@ TEST_F(ClientLbEnd2endTest, PickFirstCheckStateBeforeStartWatch) {
EXPECT_EQ ( " pick_first " , channel_2 - > GetLoadBalancingPolicyName ( ) ) ;
}
TEST_F ( ClientLbEnd2end Test, PickFirst IdleOnDisconnect) {
TEST_F ( PickFirst Test, IdleOnDisconnect ) {
// Start server, send RPC, and make sure channel is READY.
const int kNumServers = 1 ;
StartServers ( kNumServers ) ;
@ -1022,7 +1080,7 @@ TEST_F(ClientLbEnd2endTest, PickFirstIdleOnDisconnect) {
servers_ . clear ( ) ;
}
TEST_F ( ClientLbEnd2end Test, PickFirst PendingUpdateAndSelectedSubchannelFails) {
TEST_F ( PickFirst Test, PendingUpdateAndSelectedSubchannelFails ) {
auto response_generator = BuildResolverResponseGenerator ( ) ;
auto channel =
BuildChannel ( " " , response_generator ) ; // pick_first is the default.
@ -1071,7 +1129,7 @@ TEST_F(ClientLbEnd2endTest, PickFirstPendingUpdateAndSelectedSubchannelFails) {
WaitForServer ( stub , 1 , DEBUG_LOCATION , true /* ignore_failure */ ) ;
}
TEST_F ( ClientLbEnd2end Test, PickFirst StaysIdleUponEmptyUpdate) {
TEST_F ( PickFirst Test, StaysIdleUponEmptyUpdate ) {
// Start server, send RPC, and make sure channel is READY.
const int kNumServers = 1 ;
StartServers ( kNumServers ) ;
@ -1099,8 +1157,8 @@ TEST_F(ClientLbEnd2endTest, PickFirstStaysIdleUponEmptyUpdate) {
EXPECT_EQ ( channel - > GetState ( false ) , GRPC_CHANNEL_READY ) ;
}
TEST_F ( ClientLbEnd2end Test,
PickFirst StaysTransientFailureOnFailedConnectionAttemptUntilReady) {
TEST_F ( PickFirst Test,
StaysTransientFailureOnFailedConnectionAttemptUntilReady ) {
// Allocate 3 ports, with no servers running.
std : : vector < int > ports = { grpc_pick_unused_port_or_die ( ) ,
grpc_pick_unused_port_or_die ( ) ,
@ -1127,7 +1185,13 @@ TEST_F(ClientLbEnd2endTest,
CheckRpcSendOk ( stub , DEBUG_LOCATION ) ;
}
TEST_F ( ClientLbEnd2endTest , RoundRobin ) {
//
// round_robin tests
//
using RoundRobinTest = ClientLbEnd2endTest ;
TEST_F ( RoundRobinTest , Basic ) {
// Start servers and send one RPC per server.
const int kNumServers = 3 ;
StartServers ( kNumServers ) ;
@ -1156,7 +1220,7 @@ TEST_F(ClientLbEnd2endTest, RoundRobin) {
EXPECT_EQ ( " round_robin " , channel - > GetLoadBalancingPolicyName ( ) ) ;
}
TEST_F ( ClientLbEnd2end Test, RoundRobin ProcessPending) {
TEST_F ( RoundRobin Test, ProcessPending ) {
StartServers ( 1 ) ; // Single server
auto response_generator = BuildResolverResponseGenerator ( ) ;
auto channel = BuildChannel ( " round_robin " , response_generator ) ;
@ -1175,17 +1239,16 @@ TEST_F(ClientLbEnd2endTest, RoundRobinProcessPending) {
CheckRpcSendOk ( second_stub , DEBUG_LOCATION ) ;
}
TEST_F ( ClientLbEnd2end Test, RoundRobin Updates) {
// Start servers and send one RPC per server .
TEST_F ( RoundRobin Test, Updates ) {
// Start servers.
const int kNumServers = 3 ;
StartServers ( kNumServers ) ;
auto response_generator = BuildResolverResponseGenerator ( ) ;
auto channel = BuildChannel ( " round_robin " , response_generator ) ;
auto stub = BuildStub ( channel ) ;
std : : vector < int > ports ;
// Start with a single server.
gpr_log ( GPR_INFO , " *** FIRST BACKEND *** " ) ;
ports . emplace_back ( servers_ [ 0 ] - > port_ ) ;
std : : vector < int > ports = { servers_ [ 0 ] - > port_ } ;
response_generator . SetNextResolution ( ports ) ;
WaitForServer ( stub , 0 , DEBUG_LOCATION ) ;
// Send RPCs. They should all go servers_[0]
@ -1193,7 +1256,7 @@ TEST_F(ClientLbEnd2endTest, RoundRobinUpdates) {
EXPECT_EQ ( 10 , servers_ [ 0 ] - > service_ . request_count ( ) ) ;
EXPECT_EQ ( 0 , servers_ [ 1 ] - > service_ . request_count ( ) ) ;
EXPECT_EQ ( 0 , servers_ [ 2 ] - > service_ . request_count ( ) ) ;
servers_ [ 0 ] - > service_ . ResetCounters ( ) ;
ResetCounters ( ) ;
// And now for the second server.
gpr_log ( GPR_INFO , " *** SECOND BACKEND *** " ) ;
ports . clear ( ) ;
@ -1207,7 +1270,7 @@ TEST_F(ClientLbEnd2endTest, RoundRobinUpdates) {
EXPECT_EQ ( 0 , servers_ [ 0 ] - > service_ . request_count ( ) ) ;
EXPECT_EQ ( 10 , servers_ [ 1 ] - > service_ . request_count ( ) ) ;
EXPECT_EQ ( 0 , servers_ [ 2 ] - > service_ . request_count ( ) ) ;
servers_ [ 1 ] - > service_ . ResetCounters ( ) ;
ResetCounters ( ) ;
// ... and for the last server.
gpr_log ( GPR_INFO , " *** THIRD BACKEND *** " ) ;
ports . clear ( ) ;
@ -1218,7 +1281,7 @@ TEST_F(ClientLbEnd2endTest, RoundRobinUpdates) {
EXPECT_EQ ( 0 , servers_ [ 0 ] - > service_ . request_count ( ) ) ;
EXPECT_EQ ( 0 , servers_ [ 1 ] - > service_ . request_count ( ) ) ;
EXPECT_EQ ( 10 , servers_ [ 2 ] - > service_ . request_count ( ) ) ;
servers_ [ 2 ] - > service_ . ResetCounters ( ) ;
ResetCounters ( ) ;
// Back to all servers.
gpr_log ( GPR_INFO , " *** ALL BACKENDS *** " ) ;
ports . clear ( ) ;
@ -1226,23 +1289,19 @@ TEST_F(ClientLbEnd2endTest, RoundRobinUpdates) {
ports . emplace_back ( servers_ [ 1 ] - > port_ ) ;
ports . emplace_back ( servers_ [ 2 ] - > port_ ) ;
response_generator . SetNextResolution ( ports ) ;
WaitForServer ( stub , 0 , DEBUG_LOCATION ) ;
WaitForServer ( stub , 1 , DEBUG_LOCATION ) ;
WaitForServer ( stub , 2 , DEBUG_LOCATION ) ;
WaitForServers ( stub , 0 , 3 , DEBUG_LOCATION ) ;
// Send three RPCs, one per server.
for ( size_t i = 0 ; i < 3 ; + + i ) CheckRpcSendOk ( stub , DEBUG_LOCATION ) ;
EXPECT_EQ ( 1 , servers_ [ 0 ] - > service_ . request_count ( ) ) ;
EXPECT_EQ ( 1 , servers_ [ 1 ] - > service_ . request_count ( ) ) ;
EXPECT_EQ ( 1 , servers_ [ 2 ] - > service_ . request_count ( ) ) ;
ResetCounters ( ) ;
// An empty update will result in the channel going into TRANSIENT_FAILURE.
gpr_log ( GPR_INFO , " *** NO BACKENDS *** " ) ;
ports . clear ( ) ;
response_generator . SetNextResolution ( ports ) ;
grpc_connectivity_state channel_state ;
do {
channel_state = channel - > GetState ( true /* try to connect */ ) ;
} while ( channel_state = = GRPC_CHANNEL_READY ) ;
ASSERT_NE ( channel_state , GRPC_CHANNEL_READY ) ;
WaitForChannelNotReady ( channel . get ( ) ) ;
CheckRpcSendFailure ( stub ) ;
servers_ [ 0 ] - > service_ . ResetCounters ( ) ;
// Next update introduces servers_[1], making the channel recover.
gpr_log ( GPR_INFO , " *** BACK TO SECOND BACKEND *** " ) ;
@ -1250,13 +1309,12 @@ TEST_F(ClientLbEnd2endTest, RoundRobinUpdates) {
ports . emplace_back ( servers_ [ 1 ] - > port_ ) ;
response_generator . SetNextResolution ( ports ) ;
WaitForServer ( stub , 1 , DEBUG_LOCATION ) ;
channel_state = channel - > GetState ( false /* try to connect */ ) ;
ASSERT_EQ ( channel_state , GRPC_CHANNEL_READY ) ;
EXPECT_EQ ( GRPC_CHANNEL_READY , channel - > GetState ( /*try_to_connect=*/ false ) ) ;
// Check LB policy name for the channel.
EXPECT_EQ ( " round_robin " , channel - > GetLoadBalancingPolicyName ( ) ) ;
}
TEST_F ( ClientLbEnd2end Test, RoundRobin UpdateInError) {
TEST_F ( RoundRobin Test, UpdateInError ) {
const int kNumServers = 3 ;
StartServers ( kNumServers ) ;
auto response_generator = BuildResolverResponseGenerator ( ) ;
@ -1286,7 +1344,7 @@ TEST_F(ClientLbEnd2endTest, RoundRobinUpdateInError) {
EXPECT_EQ ( 0 , servers_ [ 1 ] - > service_ . request_count ( ) ) ;
}
TEST_F ( ClientLbEnd2end Test, RoundRobin ManyUpdates) {
TEST_F ( RoundRobin Test, ManyUpdates ) {
// Start servers and send one RPC per server.
const int kNumServers = 3 ;
StartServers ( kNumServers ) ;
@ -1304,66 +1362,33 @@ TEST_F(ClientLbEnd2endTest, RoundRobinManyUpdates) {
EXPECT_EQ ( " round_robin " , channel - > GetLoadBalancingPolicyName ( ) ) ;
}
TEST_F ( ClientLbEnd2endTest , RoundRobinConcurrentUpdates ) {
// TODO(dgq): replicate the way internal testing exercises the concurrent
// update provisions of RR.
}
TEST_F ( ClientLbEnd2endTest , RoundRobinReresolve ) {
// Start servers and send one RPC per server.
const int kNumServers = 3 ;
std : : vector < int > first_ports ;
std : : vector < int > second_ports ;
first_ports . reserve ( kNumServers ) ;
for ( int i = 0 ; i < kNumServers ; + + i ) {
first_ports . push_back ( grpc_pick_unused_port_or_die ( ) ) ;
}
second_ports . reserve ( kNumServers ) ;
for ( int i = 0 ; i < kNumServers ; + + i ) {
second_ports . push_back ( grpc_pick_unused_port_or_die ( ) ) ;
}
StartServers ( kNumServers , first_ports ) ;
TEST_F ( RoundRobinTest , ReresolveOnSubchannelConnectionFailure ) {
// Start 3 servers.
StartServers ( 3 ) ;
// Create channel.
auto response_generator = BuildResolverResponseGenerator ( ) ;
auto channel = BuildChannel ( " round_robin " , response_generator ) ;
auto stub = BuildStub ( channel ) ;
response_generator . SetNextResolution ( first_ports ) ;
// Send a number of RPCs, which succeed.
for ( size_t i = 0 ; i < 100 ; + + i ) {
CheckRpcSendOk ( stub , DEBUG_LOCATION ) ;
}
// Kill all servers
gpr_log ( GPR_INFO , " ****** ABOUT TO KILL SERVERS ******* " ) ;
for ( size_t i = 0 ; i < servers_ . size ( ) ; + + i ) {
servers_ [ i ] - > Shutdown ( ) ;
// Initially, tell the channel about only the first two servers.
std : : vector < int > ports = { servers_ [ 0 ] - > port_ , servers_ [ 1 ] - > port_ } ;
response_generator . SetNextResolution ( ports ) ;
// Wait for both servers to be seen.
WaitForServers ( stub , 0 , 2 , DEBUG_LOCATION ) ;
// Tell the fake resolver to send an update that adds the last server, but
// only when the LB policy requests re-resolution.
ports . push_back ( servers_ [ 2 ] - > port_ ) ;
response_generator . SetNextResolutionUponError ( ports ) ;
// Have server 0 send a GOAWAY. This should trigger a re-resolution.
gpr_log ( GPR_INFO , " ****** SENDING GOAWAY FROM SERVER 0 ******* " ) ;
{
grpc_core : : ExecCtx exec_ctx ;
grpc_core : : Server : : FromC ( servers_ [ 0 ] - > server_ - > c_server ( ) ) - > SendGoaways ( ) ;
}
gpr_log ( GPR_INFO , " ****** SERVERS KILLED ******* " ) ;
gpr_log ( GPR_INFO , " ****** SENDING DOOMED REQUESTS ******* " ) ;
// Client requests should fail. Send enough to tickle all subchannels.
for ( size_t i = 0 ; i < servers_ . size ( ) ; + + i ) CheckRpcSendFailure ( stub ) ;
gpr_log ( GPR_INFO , " ****** DOOMED REQUESTS SENT ******* " ) ;
// Bring servers back up on a different set of ports. We need to do this to be
// sure that the eventual success is *not* due to subchannel reconnection
// attempts and that an actual re-resolution has happened as a result of the
// RR policy going into transient failure when all its subchannels become
// unavailable (in transient failure as well).
gpr_log ( GPR_INFO , " ****** RESTARTING SERVERS ******* " ) ;
StartServers ( kNumServers , second_ports ) ;
// Don't notify of the update. Wait for the LB policy's re-resolution to
// "pull" the new ports.
response_generator . SetNextResolutionUponError ( second_ports ) ;
gpr_log ( GPR_INFO , " ****** SERVERS RESTARTED ******* " ) ;
gpr_log ( GPR_INFO , " ****** SENDING REQUEST TO SUCCEED ******* " ) ;
// Client request should eventually (but still fairly soon) succeed.
const gpr_timespec deadline = grpc_timeout_seconds_to_deadline ( 5 ) ;
gpr_timespec now = gpr_now ( GPR_CLOCK_MONOTONIC ) ;
while ( gpr_time_cmp ( deadline , now ) > 0 ) {
if ( SendRpc ( stub ) ) break ;
now = gpr_now ( GPR_CLOCK_MONOTONIC ) ;
}
ASSERT_GT ( gpr_time_cmp ( deadline , now ) , 0 ) ;
// Wait for the client to see server 2.
WaitForServer ( stub , 2 , DEBUG_LOCATION ) ;
}
TEST_F ( ClientLbEnd2end Test, RoundRobin TransientFailure) {
TEST_F ( RoundRobinTest , TransientFailure ) {
// Start servers and create channel. Channel should go to READY state.
const int kNumServers = 3 ;
StartServers ( kNumServers ) ;
@ -1391,7 +1416,7 @@ TEST_F(ClientLbEnd2endTest, RoundRobinTransientFailure) {
EXPECT_TRUE ( WaitForChannelState ( channel . get ( ) , predicate ) ) ;
}
TEST_F ( ClientLbEnd2end Test, RoundRobin TransientFailureAtStartup) {
TEST_F ( RoundRobin Test, TransientFailureAtStartup ) {
// Create channel and return servers that don't exist. Channel should
// quickly transition into TRANSIENT_FAILURE.
// TODO(roth): This test should ideally check that even when the
@ -1420,7 +1445,146 @@ TEST_F(ClientLbEnd2endTest, RoundRobinTransientFailureAtStartup) {
EXPECT_TRUE ( WaitForChannelState ( channel . get ( ) , predicate , true ) ) ;
}
TEST_F ( ClientLbEnd2endTest , RoundRobinSingleReconnect ) {
TEST_F ( RoundRobinTest , DoesNotFailRpcsUponDisconnection ) {
// A connection attempt injector that allows us to control timing.
class ConnectionInjector : public ConnectionAttemptInjector {
public :
explicit ConnectionInjector ( int port ) : port_ ( port ) { }
void InterceptNextAttempt ( ) {
grpc_core : : MutexLock lock ( & mu_ ) ;
intercept_next_attempt_ = true ;
}
void WaitForAttemptToStart ( ) {
grpc_core : : MutexLock lock ( & mu_ ) ;
while ( queued_attempt_ = = nullptr ) {
start_cond_ . Wait ( & mu_ ) ;
}
}
void ResumeAttempt ( ) {
grpc_core : : ExecCtx exec_ctx ;
std : : unique_ptr < QueuedAttempt > attempt ;
{
grpc_core : : MutexLock lock ( & mu_ ) ;
attempt = std : : move ( queued_attempt_ ) ;
}
attempt - > Resume ( ) ;
}
void WaitForAttemptComplete ( ) {
grpc_core : : MutexLock lock ( & mu_ ) ;
while ( ! attempt_complete_ ) {
complete_cond_ . Wait ( & mu_ ) ;
}
}
void HandleConnection ( grpc_closure * closure , grpc_endpoint * * ep ,
grpc_pollset_set * interested_parties ,
const grpc_channel_args * channel_args ,
const grpc_resolved_address * addr ,
grpc_core : : Timestamp deadline ) override {
const int port = grpc_sockaddr_get_port ( addr ) ;
gpr_log ( GPR_INFO , " ==> HandleConnection(): port=%d " , port ) ;
if ( port = = port_ ) {
grpc_core : : MutexLock lock ( & mu_ ) ;
if ( intercept_next_attempt_ ) {
gpr_log ( GPR_INFO , " *** INTERCEPTING CONNECTION ATTEMPT " ) ;
original_closure_ = closure ;
closure = GRPC_CLOSURE_INIT ( & closure_ , OnComplete , this , nullptr ) ;
intercept_next_attempt_ = false ;
queued_attempt_ = absl : : make_unique < QueuedAttempt > (
closure , ep , interested_parties , channel_args , addr , deadline ) ;
start_cond_ . Signal ( ) ;
return ;
}
}
AttemptConnection ( closure , ep , interested_parties , channel_args , addr ,
deadline ) ;
}
private :
static void OnComplete ( void * arg , grpc_error_handle error ) {
auto * self = static_cast < ConnectionInjector * > ( arg ) ;
{
grpc_core : : MutexLock lock ( & self - > mu_ ) ;
self - > attempt_complete_ = true ;
self - > complete_cond_ . Signal ( ) ;
}
grpc_core : : Closure : : Run ( DEBUG_LOCATION , self - > original_closure_ ,
GRPC_ERROR_REF ( error ) ) ;
}
const int port_ ;
grpc_core : : Mutex mu_ ;
bool intercept_next_attempt_ ABSL_GUARDED_BY ( mu_ ) = false ;
grpc_core : : CondVar start_cond_ ;
std : : unique_ptr < QueuedAttempt > queued_attempt_ ABSL_GUARDED_BY ( mu_ ) ;
grpc_closure * original_closure_ = nullptr ;
grpc_closure closure_ ;
grpc_core : : CondVar complete_cond_ ;
bool attempt_complete_ ABSL_GUARDED_BY ( mu_ ) = false ;
} ;
// Start server.
StartServers ( 1 ) ;
ConnectionInjector injector ( servers_ [ 0 ] - > port_ ) ;
injector . Start ( ) ;
// Create channel.
auto response_generator = BuildResolverResponseGenerator ( ) ;
auto channel = BuildChannel ( " round_robin " , response_generator ) ;
auto stub = BuildStub ( channel ) ;
response_generator . SetNextResolution ( GetServersPorts ( ) ) ;
// Start a thread constantly sending RPCs in a loop.
gpr_log ( GPR_ERROR , " === STARTING CLIENT THREAD === " ) ;
std : : atomic < bool > shutdown { false } ;
gpr_event ev ;
gpr_event_init ( & ev ) ;
std : : thread thd ( [ & ] ( ) {
gpr_log ( GPR_INFO , " sending first RPC " ) ;
CheckRpcSendOk ( stub , DEBUG_LOCATION ) ;
gpr_event_set ( & ev , reinterpret_cast < void * > ( 1 ) ) ;
while ( ! shutdown . load ( ) ) {
gpr_log ( GPR_INFO , " sending RPC " ) ;
CheckRpcSendOk ( stub , DEBUG_LOCATION ) ;
}
} ) ;
// Wait for first RPC to complete.
gpr_log ( GPR_ERROR , " === WAITING FOR FIRST RPC TO COMPLETE === " ) ;
ASSERT_EQ ( reinterpret_cast < void * > ( 1 ) ,
gpr_event_wait ( & ev , grpc_timeout_seconds_to_deadline ( 1 ) ) ) ;
// Channel should now be READY.
ASSERT_EQ ( GRPC_CHANNEL_READY , channel - > GetState ( false ) ) ;
// Tell injector to intercept the next connection attempt.
injector . InterceptNextAttempt ( ) ;
// Now kill the server. The subchannel should report IDLE and be
// immediately reconnected to, but this should not cause any test
// failures.
gpr_log ( GPR_ERROR , " === SHUTTING DOWN SERVER === " ) ;
{
grpc_core : : ExecCtx exec_ctx ;
grpc_core : : Server : : FromC ( servers_ [ 0 ] - > server_ - > c_server ( ) ) - > SendGoaways ( ) ;
}
gpr_sleep_until ( grpc_timeout_seconds_to_deadline ( 1 ) ) ;
servers_ [ 0 ] - > Shutdown ( ) ;
// Wait for next attempt to start.
gpr_log ( GPR_ERROR , " === WAITING FOR RECONNECTION ATTEMPT === " ) ;
injector . WaitForAttemptToStart ( ) ;
// Start server and allow attempt to continue.
gpr_log ( GPR_ERROR , " === RESTARTING SERVER === " ) ;
StartServer ( 0 ) ;
injector . ResumeAttempt ( ) ;
// Wait for next attempt to complete.
gpr_log ( GPR_ERROR , " === WAITING FOR RECONNECTION ATTEMPT TO COMPLETE === " ) ;
injector . WaitForAttemptComplete ( ) ;
// Now shut down the thread.
gpr_log ( GPR_ERROR , " === SHUTTING DOWN CLIENT THREAD === " ) ;
shutdown . store ( true ) ;
thd . join ( ) ;
}
TEST_F ( RoundRobinTest , SingleReconnect ) {
const int kNumServers = 3 ;
StartServers ( kNumServers ) ;
const auto ports = GetServersPorts ( ) ;
@ -1464,8 +1628,7 @@ TEST_F(ClientLbEnd2endTest, RoundRobinSingleReconnect) {
// If health checking is required by client but health checking service
// is not running on the server, the channel should be treated as healthy.
TEST_F ( ClientLbEnd2endTest ,
RoundRobinServersHealthCheckingUnimplementedTreatedAsHealthy ) {
TEST_F ( RoundRobinTest , ServersHealthCheckingUnimplementedTreatedAsHealthy ) {
StartServers ( 1 ) ; // Single server
ChannelArguments args ;
args . SetServiceConfigJSON (
@ -1479,7 +1642,7 @@ TEST_F(ClientLbEnd2endTest,
CheckRpcSendOk ( stub , DEBUG_LOCATION ) ;
}
TEST_F ( ClientLbEnd2end Test, RoundRobinWith HealthChecking) {
TEST_F ( RoundRobin Test, HealthChecking ) {
EnableDefaultHealthCheckService ( true ) ;
// Start servers.
const int kNumServers = 3 ;
@ -1553,8 +1716,7 @@ TEST_F(ClientLbEnd2endTest, RoundRobinWithHealthChecking) {
EnableDefaultHealthCheckService ( false ) ;
}
TEST_F ( ClientLbEnd2endTest ,
RoundRobinWithHealthCheckingHandlesSubchannelFailure ) {
TEST_F ( RoundRobinTest , HealthCheckingHandlesSubchannelFailure ) {
EnableDefaultHealthCheckService ( true ) ;
// Start servers.
const int kNumServers = 3 ;
@ -1581,7 +1743,7 @@ TEST_F(ClientLbEnd2endTest,
}
}
TEST_F ( ClientLbEnd2end Test, RoundRobin WithHealthCheckingInhibitPerChannel) {
TEST_F ( RoundRobin Test, WithHealthCheckingInhibitPerChannel ) {
EnableDefaultHealthCheckService ( true ) ;
// Start server.
const int kNumServers = 1 ;
@ -1618,7 +1780,7 @@ TEST_F(ClientLbEnd2endTest, RoundRobinWithHealthCheckingInhibitPerChannel) {
EnableDefaultHealthCheckService ( false ) ;
}
TEST_F ( ClientLbEnd2end Test, RoundRobinWith HealthCheckingServiceNamePerChannel) {
TEST_F ( RoundRobin Test, HealthCheckingServiceNamePerChannel ) {
EnableDefaultHealthCheckService ( true ) ;
// Start server.
const int kNumServers = 1 ;
@ -1661,8 +1823,8 @@ TEST_F(ClientLbEnd2endTest, RoundRobinWithHealthCheckingServiceNamePerChannel) {
EnableDefaultHealthCheckService ( false ) ;
}
TEST_F ( ClientLbEnd2end Test,
RoundRobinWith HealthCheckingServiceNameChangesAfterSubchannelsCreated) {
TEST_F ( RoundRobin Test,
HealthCheckingServiceNameChangesAfterSubchannelsCreated ) {
EnableDefaultHealthCheckService ( true ) ;
// Start server.
const int kNumServers = 1 ;
@ -1689,34 +1851,9 @@ TEST_F(ClientLbEnd2endTest,
EnableDefaultHealthCheckService ( false ) ;
}
TEST_F ( ClientLbEnd2endTest , ChannelIdleness ) {
// Start server.
const int kNumServers = 1 ;
StartServers ( kNumServers ) ;
// Set max idle time and build the channel.
ChannelArguments args ;
args . SetInt ( GRPC_ARG_CLIENT_IDLE_TIMEOUT_MS , 1000 ) ;
auto response_generator = BuildResolverResponseGenerator ( ) ;
auto channel = BuildChannel ( " " , response_generator , args ) ;
auto stub = BuildStub ( channel ) ;
// The initial channel state should be IDLE.
EXPECT_EQ ( channel - > GetState ( false ) , GRPC_CHANNEL_IDLE ) ;
// After sending RPC, channel state should be READY.
gpr_log ( GPR_INFO , " *** SENDING RPC, CHANNEL SHOULD CONNECT *** " ) ;
response_generator . SetNextResolution ( GetServersPorts ( ) ) ;
CheckRpcSendOk ( stub , DEBUG_LOCATION ) ;
EXPECT_EQ ( channel - > GetState ( false ) , GRPC_CHANNEL_READY ) ;
// After a period time not using the channel, the channel state should switch
// to IDLE.
gpr_log ( GPR_INFO , " *** WAITING FOR CHANNEL TO GO IDLE *** " ) ;
gpr_sleep_until ( grpc_timeout_milliseconds_to_deadline ( 1200 ) ) ;
EXPECT_EQ ( channel - > GetState ( false ) , GRPC_CHANNEL_IDLE ) ;
// Sending a new RPC should awake the IDLE channel.
gpr_log ( GPR_INFO , " *** SENDING ANOTHER RPC, CHANNEL SHOULD RECONNECT *** " ) ;
response_generator . SetNextResolution ( GetServersPorts ( ) ) ;
CheckRpcSendOk ( stub , DEBUG_LOCATION ) ;
EXPECT_EQ ( channel - > GetState ( false ) , GRPC_CHANNEL_READY ) ;
}
//
// LB policy pick args
//
class ClientLbPickArgsTest : public ClientLbEnd2endTest {
protected :
@ -1795,6 +1932,10 @@ TEST_F(ClientLbPickArgsTest, Basic) {
< < ArgsSeenListString ( pick_args_seen_list ) ;
}
//
// tests that LB policies can get the call's trailing metadata
//
xds : : data : : orca : : v3 : : OrcaLoadReport BackendMetricDataToOrcaLoadReport (
const grpc_core : : LoadBalancingPolicy : : BackendMetricAccessor : :
BackendMetricData & backend_metric_data ) {
@ -2053,6 +2194,10 @@ TEST_F(ClientLbInterceptTrailingMetadataTest, BackendMetricData) {
EXPECT_EQ ( kNumRpcs , trailers_intercepted ( ) ) ;
}
//
// tests that address attributes from the resolver are visible to the LB policy
//
class ClientLbAddressTest : public ClientLbEnd2endTest {
protected :
static const char * kAttributeKey ;
@ -2131,6 +2276,10 @@ TEST_F(ClientLbAddressTest, Basic) {
EXPECT_EQ ( addresses_seen ( ) , expected ) ;
}
//
// tests OOB backend metric API
//
class OobBackendMetricTest : public ClientLbEnd2endTest {
protected :
using BackendMetricReport =
@ -2239,7 +2388,9 @@ TEST_F(OobBackendMetricTest, Basic) {
int main ( int argc , char * * argv ) {
: : testing : : InitGoogleTest ( & argc , argv ) ;
grpc : : testing : : TestEnvironment env ( & argc , argv ) ;
grpc_init ( ) ;
grpc : : testing : : ConnectionAttemptInjector : : Init ( ) ;
const auto result = RUN_ALL_TESTS ( ) ;
grpc_shutdown ( ) ;
return result ;
}