/proc/self/cwd/test/test_common/test_runtime.h
Line | Count | Source (jump to first uncovered line) |
1 | | #pragma once |
2 | | |
3 | | // A simple test utility to easily allow for runtime feature overloads in unit tests. |
4 | | // |
5 | | // As long as this class is in scope one can do runtime feature overrides: |
6 | | // |
7 | | // TestScopedRuntime scoped_runtime; |
8 | | // scoped_runtime.mergeValues( |
9 | | // {{"envoy.reloadable_features.test_feature_true", "false"}}); |
10 | | // |
11 | | // TestScopedRuntime depends on the admin interface being compiled into the binary. |
12 | | // For build options where the admin interface is not available (particularly, Envoy Mobile), use |
13 | | // TestScopedStaticReloadableFeaturesRuntime. As the name suggests, it only works with reloadable |
14 | | // features: |
15 | | // |
16 | | // TestScopedStaticReloadableFeaturesRuntime scoped_runtime( |
17 | | // {{"dfp_mixed_cache", false}, {"always_use_v6", true}}); |
18 | | // |
19 | | // This will translate to envoy.reloadable_features.dfp_mixed_cache being set to false and |
20 | | // envoy.reloadable_features.always_use_v6 being set to true in the static runtime layer. |
21 | | |
22 | | #include "envoy/config/bootstrap/v3/bootstrap.pb.h" |
23 | | |
24 | | #include "source/common/runtime/runtime_impl.h" |
25 | | #include "source/common/stats/isolated_store_impl.h" |
26 | | |
27 | | #include "test/mocks/common.h" |
28 | | #include "test/mocks/event/mocks.h" |
29 | | #include "test/mocks/init/mocks.h" |
30 | | #include "test/mocks/local_info/mocks.h" |
31 | | #include "test/mocks/protobuf/mocks.h" |
32 | | #include "test/mocks/runtime/mocks.h" |
33 | | #include "test/mocks/thread_local/mocks.h" |
34 | | |
35 | | #include "gmock/gmock.h" |
36 | | |
37 | | namespace Envoy { |
38 | | |
39 | | class TestScopedRuntime { |
40 | | public: |
41 | 50.8k | TestScopedRuntime() : api_(Api::createApiForTest()) { |
42 | 50.8k | envoy::config::bootstrap::v3::LayeredRuntime config; |
43 | | // The existence of an admin layer is required for mergeValues() to work. |
44 | 50.8k | config.add_layers()->mutable_admin_layer(); |
45 | | |
46 | 50.8k | absl::StatusOr<std::unique_ptr<Runtime::LoaderImpl>> loader = Runtime::LoaderImpl::create( |
47 | 50.8k | dispatcher_, tls_, config, local_info_, store_, generator_, validation_visitor_, *api_); |
48 | 50.8k | THROW_IF_NOT_OK(loader.status()); |
49 | | // This will ignore values set in test, but just use flag defaults! |
50 | 50.8k | runtime_ = std::move(loader.value()); |
51 | 50.8k | } |
52 | | |
53 | 42.2k | Runtime::Loader& loader() { return *runtime_; } |
54 | | |
55 | 39.9k | void mergeValues(const absl::node_hash_map<std::string, std::string>& values) { |
56 | 39.9k | THROW_IF_NOT_OK(loader().mergeValues(values)); |
57 | 39.9k | } |
58 | | |
59 | | protected: |
60 | | absl::FlagSaver saver_; |
61 | | Event::MockDispatcher dispatcher_; |
62 | | testing::NiceMock<ThreadLocal::MockInstance> tls_; |
63 | | Stats::TestUtil::TestStore store_; |
64 | | Random::MockRandomGenerator generator_; |
65 | | Api::ApiPtr api_; |
66 | | testing::NiceMock<LocalInfo::MockLocalInfo> local_info_; |
67 | | testing::NiceMock<ProtobufMessage::MockValidationVisitor> validation_visitor_; |
68 | | std::unique_ptr<Runtime::Loader> runtime_; |
69 | | }; |
70 | | |
71 | | class TestScopedStaticReloadableFeaturesRuntime { |
72 | | public: |
73 | | TestScopedStaticReloadableFeaturesRuntime(const std::vector<std::pair<std::string, bool>>& values) |
74 | 0 | : api_(Api::createApiForTest()) { |
75 | 0 | envoy::config::bootstrap::v3::LayeredRuntime config; |
76 | 0 | // Set up runtime. |
77 | 0 | auto* runtime = config.add_layers(); |
78 | 0 | runtime->set_name("test_static_layer_test_runtime"); |
79 | 0 | ProtobufWkt::Struct envoy_layer; |
80 | 0 | ProtobufWkt::Struct& runtime_values = |
81 | 0 | *(*envoy_layer.mutable_fields())["envoy"].mutable_struct_value(); |
82 | 0 | ProtobufWkt::Struct& flags = |
83 | 0 | *(*runtime_values.mutable_fields())["reloadable_features"].mutable_struct_value(); |
84 | 0 | for (const auto& [key, value] : values) { |
85 | 0 | (*flags.mutable_fields())[key].set_bool_value(value); |
86 | 0 | } |
87 | 0 | runtime->mutable_static_layer()->MergeFrom(envoy_layer); |
88 | 0 |
|
89 | 0 | absl::StatusOr<std::unique_ptr<Runtime::LoaderImpl>> loader = Runtime::LoaderImpl::create( |
90 | 0 | dispatcher_, tls_, config, local_info_, store_, generator_, validation_visitor_, *api_); |
91 | 0 | THROW_IF_NOT_OK(loader.status()); |
92 | 0 | // This will ignore values set in test, but just use flag defaults! |
93 | 0 | runtime_ = std::move(loader.value()); |
94 | 0 | } |
95 | | |
96 | | protected: |
97 | | absl::FlagSaver saver_; |
98 | | Event::MockDispatcher dispatcher_; |
99 | | testing::NiceMock<ThreadLocal::MockInstance> tls_; |
100 | | Stats::TestUtil::TestStore store_; |
101 | | Random::MockRandomGenerator generator_; |
102 | | Api::ApiPtr api_; |
103 | | testing::NiceMock<LocalInfo::MockLocalInfo> local_info_; |
104 | | testing::NiceMock<ProtobufMessage::MockValidationVisitor> validation_visitor_; |
105 | | std::unique_ptr<Runtime::Loader> runtime_; |
106 | | }; |
107 | | |
108 | | class TestDeprecatedV2Api : public TestScopedRuntime { |
109 | | public: |
110 | 2.35k | TestDeprecatedV2Api() { allowDeprecatedV2(); } |
111 | 2.35k | void allowDeprecatedV2() { |
112 | 2.35k | THROW_IF_NOT_OK(loader().mergeValues({ |
113 | 2.35k | {"envoy.test_only.broken_in_production.enable_deprecated_v2_api", "true"}, |
114 | 2.35k | {"envoy.features.enable_all_deprecated_features", "true"}, |
115 | 2.35k | })); |
116 | 2.35k | } |
117 | | }; |
118 | | |
119 | | } // namespace Envoy |