mirror of https://github.com/grpc/grpc.git
outlier detection: add basic unit test (#31346)
* outlier detection: add basic unit test * iwyupull/31160/head^2
parent
cece68cf3e
commit
2f2662c462
6 changed files with 344 additions and 15 deletions
@ -0,0 +1,188 @@ |
||||
//
|
||||
// Copyright 2022 gRPC authors.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
|
||||
#include <stddef.h> |
||||
#include <stdint.h> |
||||
|
||||
#include <algorithm> |
||||
#include <map> |
||||
#include <memory> |
||||
#include <string> |
||||
#include <utility> |
||||
#include <vector> |
||||
|
||||
#include "absl/status/status.h" |
||||
#include "absl/status/statusor.h" |
||||
#include "absl/strings/string_view.h" |
||||
#include "gtest/gtest.h" |
||||
|
||||
#include <grpc/grpc.h> |
||||
|
||||
#include "src/core/ext/filters/client_channel/subchannel_pool_interface.h" |
||||
#include "src/core/lib/channel/channel_args.h" |
||||
#include "src/core/lib/gprpp/orphanable.h" |
||||
#include "src/core/lib/gprpp/ref_counted_ptr.h" |
||||
#include "src/core/lib/gprpp/time.h" |
||||
#include "src/core/lib/iomgr/resolved_address.h" |
||||
#include "src/core/lib/json/json.h" |
||||
#include "src/core/lib/load_balancing/lb_policy.h" |
||||
#include "src/core/lib/resolver/server_address.h" |
||||
#include "test/core/client_channel/lb_policy/lb_policy_test_lib.h" |
||||
#include "test/core/util/test_config.h" |
||||
|
||||
namespace grpc_core { |
||||
namespace testing { |
||||
namespace { |
||||
|
||||
class OutlierDetectionTest : public LoadBalancingPolicyTest { |
||||
protected: |
||||
class ConfigBuilder { |
||||
public: |
||||
ConfigBuilder() { |
||||
SetChildPolicy(Json::Object{{"round_robin", Json::Object()}}); |
||||
} |
||||
|
||||
ConfigBuilder& SetInterval(Duration duration) { |
||||
json_["interval"] = duration.ToJsonString(); |
||||
return *this; |
||||
} |
||||
ConfigBuilder& SetBaseEjectionTime(Duration duration) { |
||||
json_["baseEjectionTime"] = duration.ToJsonString(); |
||||
return *this; |
||||
} |
||||
ConfigBuilder& SetMaxEjectionTime(Duration duration) { |
||||
json_["maxEjectionTime"] = duration.ToJsonString(); |
||||
return *this; |
||||
} |
||||
ConfigBuilder& SetMaxEjectionPercent(uint32_t value) { |
||||
json_["maxEjectionPercent"] = value; |
||||
return *this; |
||||
} |
||||
ConfigBuilder& SetChildPolicy(Json::Object child_policy) { |
||||
json_["childPolicy"] = Json::Array{std::move(child_policy)}; |
||||
return *this; |
||||
} |
||||
|
||||
ConfigBuilder& SetSuccessRateStdevFactor(uint32_t value) { |
||||
GetSuccessRate()["stdevFactor"] = value; |
||||
return *this; |
||||
} |
||||
ConfigBuilder& SetSuccessRateEnforcementPercentage(uint32_t value) { |
||||
GetSuccessRate()["enforcementPercentage"] = value; |
||||
return *this; |
||||
} |
||||
ConfigBuilder& SetSuccessRateMinHosts(uint32_t value) { |
||||
GetSuccessRate()["minimumHosts"] = value; |
||||
return *this; |
||||
} |
||||
ConfigBuilder& SetSuccessRateRequestVolume(uint32_t value) { |
||||
GetSuccessRate()["requestVolume"] = value; |
||||
return *this; |
||||
} |
||||
|
||||
ConfigBuilder& SetFailurePercentageThreshold(uint32_t value) { |
||||
GetFailurePercentage()["threshold"] = value; |
||||
return *this; |
||||
} |
||||
ConfigBuilder& SetFailurePercentageEnforcementPercentage(uint32_t value) { |
||||
GetFailurePercentage()["enforcementPercentage"] = value; |
||||
return *this; |
||||
} |
||||
ConfigBuilder& SetFailurePercentageMinimumHosts(uint32_t value) { |
||||
GetFailurePercentage()["minimumHosts"] = value; |
||||
return *this; |
||||
} |
||||
ConfigBuilder& SetFailurePercentageRequestVolume(uint32_t value) { |
||||
GetFailurePercentage()["requestVolume"] = value; |
||||
return *this; |
||||
} |
||||
|
||||
RefCountedPtr<LoadBalancingPolicy::Config> Build() { |
||||
Json config = |
||||
Json::Array{Json::Object{{"outlier_detection_experimental", json_}}}; |
||||
return MakeConfig(config); |
||||
} |
||||
|
||||
private: |
||||
Json::Object& GetSuccessRate() { |
||||
auto it = json_.emplace("successRateEjection", Json::Object()).first; |
||||
return *it->second.mutable_object(); |
||||
} |
||||
|
||||
Json::Object& GetFailurePercentage() { |
||||
auto it = |
||||
json_.emplace("failurePercentageEjection", Json::Object()).first; |
||||
return *it->second.mutable_object(); |
||||
} |
||||
|
||||
Json::Object json_; |
||||
}; |
||||
|
||||
OutlierDetectionTest() |
||||
: lb_policy_(MakeLbPolicy("outlier_detection_experimental")) {} |
||||
|
||||
OrphanablePtr<LoadBalancingPolicy> lb_policy_; |
||||
}; |
||||
|
||||
TEST_F(OutlierDetectionTest, Basic) { |
||||
constexpr absl::string_view kAddressUri = "ipv4:127.0.0.1:443"; |
||||
const grpc_resolved_address address = MakeAddress(kAddressUri); |
||||
// Send an update containing one address.
|
||||
LoadBalancingPolicy::UpdateArgs update_args; |
||||
update_args.config = ConfigBuilder().Build(); |
||||
update_args.addresses.emplace(); |
||||
update_args.addresses->emplace_back(address, ChannelArgs()); |
||||
absl::Status status = ApplyUpdate(std::move(update_args), lb_policy_.get()); |
||||
EXPECT_TRUE(status.ok()) << status; |
||||
// LB policy should have reported CONNECTING state.
|
||||
auto picker = ExpectState(GRPC_CHANNEL_CONNECTING); |
||||
ExpectPickQueued(picker.get()); |
||||
// LB policy should have created a subchannel for the address.
|
||||
SubchannelKey key(address, ChannelArgs()); |
||||
auto it = subchannel_pool_.find(key); |
||||
ASSERT_NE(it, subchannel_pool_.end()); |
||||
auto& subchannel_state = it->second; |
||||
// LB policy should have requested a connection on this subchannel.
|
||||
EXPECT_TRUE(subchannel_state.ConnectionRequested()); |
||||
// Tell subchannel to report CONNECTING.
|
||||
subchannel_state.SetConnectivityState(GRPC_CHANNEL_CONNECTING, |
||||
absl::OkStatus()); |
||||
// LB policy should again report CONNECTING.
|
||||
picker = ExpectState(GRPC_CHANNEL_CONNECTING); |
||||
ExpectPickQueued(picker.get()); |
||||
// Tell subchannel to report READY.
|
||||
subchannel_state.SetConnectivityState(GRPC_CHANNEL_READY, absl::OkStatus()); |
||||
// LB policy should eventually report READY.
|
||||
picker = WaitForConnected(); |
||||
ASSERT_NE(picker, nullptr); |
||||
// Picker should return the same subchannel repeatedly.
|
||||
for (size_t i = 0; i < 3; ++i) { |
||||
ExpectPickComplete(picker.get(), kAddressUri); |
||||
} |
||||
} |
||||
|
||||
} // namespace
|
||||
} // namespace testing
|
||||
} // namespace grpc_core
|
||||
|
||||
int main(int argc, char** argv) { |
||||
::testing::InitGoogleTest(&argc, argv); |
||||
grpc::testing::TestEnvironment env(&argc, argv); |
||||
grpc_init(); |
||||
int ret = RUN_ALL_TESTS(); |
||||
grpc_shutdown(); |
||||
return ret; |
||||
} |
Loading…
Reference in new issue