|
|
|
@ -16,6 +16,8 @@ |
|
|
|
|
|
|
|
|
|
#include <stddef.h> |
|
|
|
|
|
|
|
|
|
#include <array> |
|
|
|
|
|
|
|
|
|
#include "absl/status/status.h" |
|
|
|
|
#include "absl/strings/string_view.h" |
|
|
|
|
#include "gtest/gtest.h" |
|
|
|
@ -40,25 +42,107 @@ class PickFirstTest : public LoadBalancingPolicyTest { |
|
|
|
|
OrphanablePtr<LoadBalancingPolicy> lb_policy_; |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
TEST_F(PickFirstTest, Basic) { |
|
|
|
|
constexpr absl::string_view kAddressUri = "ipv4:127.0.0.1:443"; |
|
|
|
|
// Send an update containing one address.
|
|
|
|
|
absl::Status status = |
|
|
|
|
ApplyUpdate(BuildUpdate({kAddressUri}), lb_policy_.get()); |
|
|
|
|
TEST_F(PickFirstTest, FirstAddressWorks) { |
|
|
|
|
// Send an update containing two addresses.
|
|
|
|
|
constexpr std::array<absl::string_view, 2> kAddresses = { |
|
|
|
|
"ipv4:127.0.0.1:443", "ipv4:127.0.0.1:444"}; |
|
|
|
|
absl::Status status = ApplyUpdate(BuildUpdate(kAddresses), lb_policy_.get()); |
|
|
|
|
EXPECT_TRUE(status.ok()) << status; |
|
|
|
|
// LB policy should have created a subchannel for both addresses with
|
|
|
|
|
// the GRPC_ARG_INHIBIT_HEALTH_CHECKING channel arg.
|
|
|
|
|
auto* subchannel = FindSubchannel( |
|
|
|
|
kAddresses[0], ChannelArgs().Set(GRPC_ARG_INHIBIT_HEALTH_CHECKING, true)); |
|
|
|
|
ASSERT_NE(subchannel, nullptr); |
|
|
|
|
auto* subchannel2 = FindSubchannel( |
|
|
|
|
kAddresses[1], ChannelArgs().Set(GRPC_ARG_INHIBIT_HEALTH_CHECKING, true)); |
|
|
|
|
ASSERT_NE(subchannel2, nullptr); |
|
|
|
|
// When the LB policy receives the first subchannel's initial connectivity
|
|
|
|
|
// state notification (IDLE), it will request a connection.
|
|
|
|
|
EXPECT_TRUE(subchannel->ConnectionRequested()); |
|
|
|
|
// This causes the subchannel to start to connect, so it reports CONNECTING.
|
|
|
|
|
subchannel->SetConnectivityState(GRPC_CHANNEL_CONNECTING); |
|
|
|
|
// LB policy should have reported CONNECTING state.
|
|
|
|
|
ExpectConnectingUpdate(); |
|
|
|
|
// The second subchannel should not be connecting.
|
|
|
|
|
EXPECT_FALSE(subchannel2->ConnectionRequested()); |
|
|
|
|
// When the first subchannel becomes connected, it reports READY.
|
|
|
|
|
subchannel->SetConnectivityState(GRPC_CHANNEL_READY); |
|
|
|
|
// The LB policy will report CONNECTING some number of times (doesn't
|
|
|
|
|
// matter how many) and then report READY.
|
|
|
|
|
auto picker = WaitForConnected(); |
|
|
|
|
ASSERT_NE(picker, nullptr); |
|
|
|
|
// Picker should return the same subchannel repeatedly.
|
|
|
|
|
for (size_t i = 0; i < 3; ++i) { |
|
|
|
|
EXPECT_EQ(ExpectPickComplete(picker.get()), kAddresses[0]); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
TEST_F(PickFirstTest, FirstAddressFails) { |
|
|
|
|
// Send an update containing two addresses.
|
|
|
|
|
constexpr std::array<absl::string_view, 2> kAddresses = { |
|
|
|
|
"ipv4:127.0.0.1:443", "ipv4:127.0.0.1:444"}; |
|
|
|
|
absl::Status status = ApplyUpdate(BuildUpdate(kAddresses), lb_policy_.get()); |
|
|
|
|
EXPECT_TRUE(status.ok()) << status; |
|
|
|
|
// LB policy should have created a subchannel for both addresses with
|
|
|
|
|
// the GRPC_ARG_INHIBIT_HEALTH_CHECKING channel arg.
|
|
|
|
|
auto* subchannel = FindSubchannel( |
|
|
|
|
kAddresses[0], ChannelArgs().Set(GRPC_ARG_INHIBIT_HEALTH_CHECKING, true)); |
|
|
|
|
ASSERT_NE(subchannel, nullptr); |
|
|
|
|
auto* subchannel2 = FindSubchannel( |
|
|
|
|
kAddresses[1], ChannelArgs().Set(GRPC_ARG_INHIBIT_HEALTH_CHECKING, true)); |
|
|
|
|
ASSERT_NE(subchannel2, nullptr); |
|
|
|
|
// When the LB policy receives the first subchannel's initial connectivity
|
|
|
|
|
// state notification (IDLE), it will request a connection.
|
|
|
|
|
EXPECT_TRUE(subchannel->ConnectionRequested()); |
|
|
|
|
// This causes the subchannel to start to connect, so it reports CONNECTING.
|
|
|
|
|
subchannel->SetConnectivityState(GRPC_CHANNEL_CONNECTING); |
|
|
|
|
// LB policy should have reported CONNECTING state.
|
|
|
|
|
ExpectConnectingUpdate(); |
|
|
|
|
// The second subchannel should not be connecting.
|
|
|
|
|
EXPECT_FALSE(subchannel2->ConnectionRequested()); |
|
|
|
|
// The first subchannel's connection attempt fails.
|
|
|
|
|
subchannel->SetConnectivityState(GRPC_CHANNEL_TRANSIENT_FAILURE, |
|
|
|
|
absl::UnavailableError("failed to connect")); |
|
|
|
|
// The LB policy will start a connection attempt on the second subchannel.
|
|
|
|
|
EXPECT_TRUE(subchannel2->ConnectionRequested()); |
|
|
|
|
// This causes the subchannel to start to connect, so it reports CONNECTING.
|
|
|
|
|
subchannel2->SetConnectivityState(GRPC_CHANNEL_CONNECTING); |
|
|
|
|
// The connection attempt succeeds.
|
|
|
|
|
subchannel2->SetConnectivityState(GRPC_CHANNEL_READY); |
|
|
|
|
// The LB policy will report CONNECTING some number of times (doesn't
|
|
|
|
|
// matter how many) and then report READY.
|
|
|
|
|
auto picker = WaitForConnected(); |
|
|
|
|
ASSERT_NE(picker, nullptr); |
|
|
|
|
// Picker should return the same subchannel repeatedly.
|
|
|
|
|
for (size_t i = 0; i < 3; ++i) { |
|
|
|
|
EXPECT_EQ(ExpectPickComplete(picker.get()), kAddresses[1]); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
TEST_F(PickFirstTest, GoesIdleWhenConnectionFailsThenCanReconnect) { |
|
|
|
|
// Send an update containing two addresses.
|
|
|
|
|
constexpr std::array<absl::string_view, 2> kAddresses = { |
|
|
|
|
"ipv4:127.0.0.1:443", "ipv4:127.0.0.1:444"}; |
|
|
|
|
absl::Status status = ApplyUpdate(BuildUpdate(kAddresses), lb_policy_.get()); |
|
|
|
|
EXPECT_TRUE(status.ok()) << status; |
|
|
|
|
// LB policy should have created a subchannel for the address with the
|
|
|
|
|
// GRPC_ARG_INHIBIT_HEALTH_CHECKING channel arg.
|
|
|
|
|
// LB policy should have created a subchannel for both addresses with
|
|
|
|
|
// the GRPC_ARG_INHIBIT_HEALTH_CHECKING channel arg.
|
|
|
|
|
auto* subchannel = FindSubchannel( |
|
|
|
|
kAddressUri, ChannelArgs().Set(GRPC_ARG_INHIBIT_HEALTH_CHECKING, true)); |
|
|
|
|
kAddresses[0], ChannelArgs().Set(GRPC_ARG_INHIBIT_HEALTH_CHECKING, true)); |
|
|
|
|
ASSERT_NE(subchannel, nullptr); |
|
|
|
|
// When the LB policy receives the subchannel's initial connectivity
|
|
|
|
|
auto* subchannel2 = FindSubchannel( |
|
|
|
|
kAddresses[1], ChannelArgs().Set(GRPC_ARG_INHIBIT_HEALTH_CHECKING, true)); |
|
|
|
|
ASSERT_NE(subchannel2, nullptr); |
|
|
|
|
// When the LB policy receives the first subchannel's initial connectivity
|
|
|
|
|
// state notification (IDLE), it will request a connection.
|
|
|
|
|
EXPECT_TRUE(subchannel->ConnectionRequested()); |
|
|
|
|
// This causes the subchannel to start to connect, so it reports CONNECTING.
|
|
|
|
|
subchannel->SetConnectivityState(GRPC_CHANNEL_CONNECTING); |
|
|
|
|
// LB policy should have reported CONNECTING state.
|
|
|
|
|
ExpectConnectingUpdate(); |
|
|
|
|
// When the subchannel becomes connected, it reports READY.
|
|
|
|
|
// The second subchannel should not be connecting.
|
|
|
|
|
EXPECT_FALSE(subchannel2->ConnectionRequested()); |
|
|
|
|
// When the first subchannel becomes connected, it reports READY.
|
|
|
|
|
subchannel->SetConnectivityState(GRPC_CHANNEL_READY); |
|
|
|
|
// The LB policy will report CONNECTING some number of times (doesn't
|
|
|
|
|
// matter how many) and then report READY.
|
|
|
|
@ -66,7 +150,30 @@ TEST_F(PickFirstTest, Basic) { |
|
|
|
|
ASSERT_NE(picker, nullptr); |
|
|
|
|
// Picker should return the same subchannel repeatedly.
|
|
|
|
|
for (size_t i = 0; i < 3; ++i) { |
|
|
|
|
EXPECT_EQ(ExpectPickComplete(picker.get()), kAddressUri); |
|
|
|
|
EXPECT_EQ(ExpectPickComplete(picker.get()), kAddresses[0]); |
|
|
|
|
} |
|
|
|
|
// Connection fails.
|
|
|
|
|
subchannel->SetConnectivityState(GRPC_CHANNEL_IDLE); |
|
|
|
|
// We should see a re-resolution request.
|
|
|
|
|
ExpectReresolutionRequest(); |
|
|
|
|
// LB policy reports IDLE with a queueing picker.
|
|
|
|
|
ExpectStateAndQueuingPicker(GRPC_CHANNEL_IDLE); |
|
|
|
|
// By checking the picker, we told the LB policy to trigger a new
|
|
|
|
|
// connection attempt, so it should start over with the first
|
|
|
|
|
// subchannel.
|
|
|
|
|
EXPECT_TRUE(subchannel->ConnectionRequested()); |
|
|
|
|
// The subchannel starts connecting.
|
|
|
|
|
subchannel->SetConnectivityState(GRPC_CHANNEL_CONNECTING); |
|
|
|
|
// LB policy should have reported CONNECTING state.
|
|
|
|
|
ExpectConnectingUpdate(); |
|
|
|
|
// Subchannel succeeds in connecting.
|
|
|
|
|
subchannel->SetConnectivityState(GRPC_CHANNEL_READY); |
|
|
|
|
// LB policy reports READY.
|
|
|
|
|
picker = WaitForConnected(); |
|
|
|
|
ASSERT_NE(picker, nullptr); |
|
|
|
|
// Picker should return the same subchannel repeatedly.
|
|
|
|
|
for (size_t i = 0; i < 3; ++i) { |
|
|
|
|
EXPECT_EQ(ExpectPickComplete(picker.get()), kAddresses[0]); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|