-
Notifications
You must be signed in to change notification settings - Fork 5.5k
[fuzz] Added random load balancer fuzz #13400
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 14 commits
b4bb682
8df52a8
7ee7b14
9e8d678
b977914
1cfaa5d
73c24ed
54d5b67
d5f072f
8c00f14
810eb49
413214c
b5619fe
c4a53c0
6bcb394
ea0264a
e43bb2c
6e3c420
a7d7e88
5c6bdaf
92666c1
6ee35db
a81eabe
31a5668
91e5738
794918b
c1c8e29
741b3a0
52cbbd5
4bec47d
11a7f74
4675237
d07db49
ff8e22f
d71c5d1
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,37 @@ | ||
| syntax = "proto3"; | ||
|
|
||
| package test.common.upstream; | ||
|
|
||
| import "validate/validate.proto"; | ||
| import "envoy/config/cluster/v3/cluster.proto"; | ||
| import "google/protobuf/empty.proto"; | ||
|
|
||
| message UpdateHealthFlags { | ||
| bool failover_host_set = 1; | ||
|
zasweq marked this conversation as resolved.
Outdated
|
||
| uint32 num_healthy_hosts = 2; | ||
|
zasweq marked this conversation as resolved.
|
||
| uint32 num_degraded_hosts = 3; | ||
| uint32 num_excluded_hosts = 4; | ||
| } | ||
|
|
||
| message LbAction { | ||
| oneof action_selector { | ||
| option (validate.required) = true; | ||
| UpdateHealthFlags update_health_flags = 1; | ||
| google.protobuf.Empty prefetch = 2; | ||
|
zasweq marked this conversation as resolved.
|
||
| google.protobuf.Empty choose_host = 3; | ||
| } | ||
| } | ||
|
|
||
| //This message represents what LoadBalancerFuzzBase will interact with, performing setup of host sets and calling into load balancers. | ||
|
zasweq marked this conversation as resolved.
Outdated
|
||
| //The logic that this message represents and the base class for load balancing fuzzing will be logic that maps to all types of load balancing | ||
| //and can be modularly used at the highest level for each load balancer. | ||
| message LoadBalancerTestCase { | ||
| envoy.config.cluster.v3.Cluster.CommonLbConfig common_lb_config = 1 | ||
| [(validate.rules).message.required = true]; | ||
| repeated LbAction actions = 2; | ||
| //This is capped at the max port value on an ip address - 80 | ||
|
zasweq marked this conversation as resolved.
Outdated
|
||
| uint32 num_hosts_in_priority_set = 3 [(validate.rules).uint32.lt = 65455]; | ||
| uint32 num_hosts_in_failover_set = 4 [(validate.rules).uint32.lt = 65455]; | ||
| repeated uint64 bytestring_for_random_calls = 5 | ||
|
zasweq marked this conversation as resolved.
Outdated
|
||
| [(validate.rules).repeated = {min_items: 1, max_items: 50}]; | ||
|
zasweq marked this conversation as resolved.
Outdated
|
||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,115 @@ | ||
| #include "test/common/upstream/load_balancer_fuzz_base.h" | ||
|
|
||
| #include "test/common/upstream/utility.h" | ||
|
|
||
| namespace Envoy { | ||
|
|
||
| namespace Random { | ||
| uint64_t FakeRandomGenerator::random() { | ||
| uint8_t index_of_data = counter % bytestring_.size(); | ||
| ++counter; | ||
| ENVOY_LOG_MISC(trace, "random() returned: {}", bytestring_.at(index_of_data)); | ||
| return bytestring_.at(index_of_data); | ||
| } | ||
| } // namespace Random | ||
|
|
||
| namespace Upstream { | ||
|
|
||
| // Anonymous namespace for helper functions | ||
| namespace { | ||
| std::vector<uint64_t> | ||
| constructByteVectorForRandom(const Protobuf::RepeatedField<uint64_t>& byteString) { | ||
| std::vector<uint64_t> byteVector; | ||
| for (int i = 0; i < byteString.size(); ++i) { | ||
| byteVector.push_back(byteString.at(i)); | ||
| } | ||
| return byteVector; | ||
| } | ||
| } // namespace | ||
|
|
||
| void LoadBalancerFuzzBase::initializeFixedHostSets(uint32_t num_hosts_in_priority_set, | ||
| uint32_t num_hosts_in_failover_set) { | ||
| int port = 80; | ||
|
zasweq marked this conversation as resolved.
Outdated
|
||
| for (uint32_t i = 0; i < num_hosts_in_priority_set; ++i) { | ||
| host_set_.hosts_.push_back(makeTestHost(info_, "tcp://127.0.0.1:" + std::to_string(port))); | ||
| ++port; | ||
| } | ||
| for (uint32_t i = 0; i < num_hosts_in_failover_set; ++i) { | ||
| failover_host_set_.hosts_.push_back( | ||
| makeTestHost(info_, "tcp://127.0.0.1:" + std::to_string(port))); | ||
| ++port; | ||
| } | ||
| // TODO: More than two hosts? | ||
|
zasweq marked this conversation as resolved.
Outdated
|
||
| } | ||
|
|
||
| // Initializes random and fixed host sets | ||
| void LoadBalancerFuzzBase::initializeLbComponents( | ||
| test::common::upstream::LoadBalancerTestCase input) { | ||
| random_.bytestring_ = constructByteVectorForRandom(input.bytestring_for_random_calls()); | ||
| initializeFixedHostSets(input.num_hosts_in_priority_set(), input.num_hosts_in_failover_set()); | ||
| } | ||
|
|
||
| // Updating host sets is shared amongst all the load balancer tests. Since logically, we're just | ||
| // setting the mock priority set to have certain values, and all load balancers interface with host | ||
| // sets and their health statuses, this action maps to all load balancers. | ||
| void LoadBalancerFuzzBase::updateHealthFlagsForAHostSet(bool failover_host_set, | ||
| uint32_t num_healthy_hosts, | ||
| uint32_t num_degraded_hosts, | ||
| uint32_t num_excluded_hosts) { | ||
| MockHostSet& host_set = *priority_set_.getMockHostSet(int(failover_host_set)); | ||
| uint32_t i = 0; | ||
| for (; i < num_healthy_hosts && i < host_set.hosts_.size(); ++i) { | ||
|
zasweq marked this conversation as resolved.
Outdated
|
||
| host_set.healthy_hosts_.push_back(host_set.hosts_[i]); | ||
| } | ||
| for (; i < (num_healthy_hosts + num_degraded_hosts) && i < host_set.hosts_.size(); ++i) { | ||
| host_set.degraded_hosts_.push_back(host_set.hosts_[i]); | ||
| } | ||
|
|
||
| for (; i < (num_healthy_hosts + num_degraded_hosts + num_excluded_hosts) && | ||
|
zasweq marked this conversation as resolved.
Outdated
|
||
| i < host_set.hosts_.size(); | ||
| ++i) { | ||
| host_set.excluded_hosts_.push_back(host_set.hosts_[i]); | ||
| } | ||
|
|
||
| host_set.runCallbacks({}, {}); | ||
|
zasweq marked this conversation as resolved.
zasweq marked this conversation as resolved.
|
||
| } | ||
|
|
||
| void LoadBalancerFuzzBase::prefetch() { | ||
| // TODO: context, could generate it in proto action | ||
| lb_->peekAnotherHost(nullptr); | ||
| } | ||
|
|
||
| void LoadBalancerFuzzBase::chooseHost() { | ||
| // TODO: context, could generate it in proto action | ||
| lb_->chooseHost(nullptr); | ||
| } | ||
|
|
||
| void LoadBalancerFuzzBase::replay( | ||
| const Protobuf::RepeatedPtrField<test::common::upstream::LbAction>& actions) { | ||
| constexpr auto max_actions = 64; | ||
| for (int i = 0; i < std::min(max_actions, actions.size()); ++i) { | ||
| const auto& event = actions.at(i); | ||
| ENVOY_LOG_MISC(trace, "Action: {}", event.DebugString()); | ||
| switch (event.action_selector_case()) { | ||
| case test::common::upstream::LbAction::kUpdateHealthFlags: { | ||
| updateHealthFlagsForAHostSet(event.update_health_flags().failover_host_set(), | ||
| event.update_health_flags().num_degraded_hosts(), | ||
| event.update_health_flags().num_excluded_hosts()); | ||
| break; | ||
| } | ||
| case test::common::upstream::LbAction::kPrefetch: { | ||
| prefetch(); | ||
| break; | ||
| } | ||
| case test::common::upstream::LbAction::kChooseHost: { | ||
| chooseHost(); | ||
| break; | ||
| } | ||
| default: | ||
| break; | ||
| } | ||
| } | ||
| } | ||
|
|
||
| } // namespace Upstream | ||
| } // namespace Envoy | ||
Uh oh!
There was an error while loading. Please reload this page.