Coverage Report

Created: 2024-09-19 09:45

/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