forked from envoyproxy/envoy
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathfilesystem_subscription_test_harness.h
143 lines (121 loc) · 5.68 KB
/
filesystem_subscription_test_harness.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
#pragma once
#include <fstream>
#include "envoy/config/endpoint/v3/endpoint.pb.h"
#include "envoy/config/endpoint/v3/endpoint.pb.validate.h"
#include "envoy/service/discovery/v3/discovery.pb.h"
#include "source/common/config/filesystem_subscription_impl.h"
#include "source/common/config/utility.h"
#include "source/common/event/dispatcher_impl.h"
#include "source/common/protobuf/utility.h"
#include "test/common/config/subscription_test_harness.h"
#include "test/mocks/config/mocks.h"
#include "test/mocks/event/mocks.h"
#include "test/mocks/filesystem/mocks.h"
#include "test/mocks/protobuf/mocks.h"
#include "test/test_common/environment.h"
#include "test/test_common/utility.h"
#include "gmock/gmock.h"
#include "gtest/gtest.h"
using testing::_;
using testing::InvokeWithoutArgs;
using testing::NiceMock;
namespace Envoy {
namespace Config {
class FilesystemSubscriptionTestHarness : public SubscriptionTestHarness {
public:
FilesystemSubscriptionTestHarness()
: path_(makePathConfigSource(TestEnvironment::temporaryPath("eds.json"))),
api_(Api::createApiForTest(stats_store_, simTime())), dispatcher_(setupDispatcher()),
subscription_(*dispatcher_, path_, callbacks_, resource_decoder_, stats_,
validation_visitor_, *api_) {}
~FilesystemSubscriptionTestHarness() override { TestEnvironment::removePath(path_.path()); }
Event::DispatcherPtr setupDispatcher() {
auto dispatcher = std::make_unique<Event::MockDispatcher>();
EXPECT_CALL(*dispatcher, createFilesystemWatcher_()).WillOnce(InvokeWithoutArgs([this] {
Filesystem::MockWatcher* mock_watcher = new Filesystem::MockWatcher();
EXPECT_CALL(*mock_watcher, addWatch(path_.path(), Filesystem::Watcher::Events::MovedTo, _))
.WillOnce(Invoke([this](absl::string_view, uint32_t,
Filesystem::Watcher::OnChangedCb cb) { on_changed_cb_ = cb; }));
return mock_watcher;
}));
return dispatcher;
}
void startSubscription(const std::set<std::string>& cluster_names) override {
std::ifstream config_file(path_.path());
file_at_start_ = config_file.good();
subscription_.start(flattenResources(cluster_names));
}
void updateResourceInterest(const std::set<std::string>& cluster_names) override {
subscription_.updateResourceInterest(flattenResources(cluster_names));
}
void updateFile(const std::string& json, bool run_dispatcher = true) {
// Write JSON contents to file, rename to path_ and invoke on change callback
const std::string temp_path = TestEnvironment::writeStringToFileForTest("eds.json.tmp", json);
TestEnvironment::renameFile(temp_path, path_.path());
if (run_dispatcher) {
on_changed_cb_(Filesystem::Watcher::Events::MovedTo);
}
}
void expectSendMessage(const std::set<std::string>& cluster_names, const std::string& version,
bool expect_node) override {
UNREFERENCED_PARAMETER(cluster_names);
UNREFERENCED_PARAMETER(version);
UNREFERENCED_PARAMETER(expect_node);
}
void deliverConfigUpdate(const std::vector<std::string>& cluster_names,
const std::string& version, bool accept) override {
std::string file_json = "{\"versionInfo\":\"" + version + "\",\"resources\":[";
for (const auto& cluster : cluster_names) {
file_json += "{\"@type\":\"type.googleapis.com/"
"envoy.config.endpoint.v3.ClusterLoadAssignment\",\"clusterName\":\"" +
cluster + "\"},";
}
file_json.pop_back();
file_json += "]}";
envoy::service::discovery::v3::DiscoveryResponse response_pb;
TestUtility::loadFromJson(file_json, response_pb);
const auto decoded_resources =
TestUtility::decodeResources<envoy::config::endpoint::v3::ClusterLoadAssignment>(
response_pb, "cluster_name");
EXPECT_CALL(callbacks_, onConfigUpdate(DecodedResourcesEq(decoded_resources.refvec_), version))
.WillOnce(ThrowOnRejectedConfig(accept));
if (accept) {
version_ = version;
} else {
EXPECT_CALL(callbacks_, onConfigUpdateFailed(_, _));
}
updateFile(file_json);
}
AssertionResult statsAre(uint32_t attempt, uint32_t success, uint32_t rejected, uint32_t failure,
uint32_t init_fetch_timeout, uint64_t update_time, uint64_t version,
absl::string_view version_text) override {
// The first attempt always fail unless there was a file there to begin with.
return SubscriptionTestHarness::statsAre(attempt, success, rejected,
failure + (file_at_start_ ? 0 : 1), init_fetch_timeout,
update_time, version, version_text);
}
void expectConfigUpdateFailed() override { stats_.update_failure_.inc(); }
void expectEnableInitFetchTimeoutTimer(std::chrono::milliseconds) override {
// initial_fetch_timeout not implemented.
}
void expectDisableInitFetchTimeoutTimer() override {
// initial_fetch_timeout not implemented
}
void callInitFetchTimeoutCb() override {
// initial_fetch_timeout not implemented
}
const envoy::config::core::v3::PathConfigSource path_;
std::string version_;
Stats::IsolatedStoreImpl stats_store_;
NiceMock<ProtobufMessage::MockValidationVisitor> validation_visitor_;
Api::ApiPtr api_;
Event::DispatcherPtr dispatcher_;
Filesystem::Watcher::OnChangedCb on_changed_cb_;
NiceMock<Config::MockSubscriptionCallbacks> callbacks_;
TestUtility::TestOpaqueResourceDecoderImpl<envoy::config::endpoint::v3::ClusterLoadAssignment>
resource_decoder_{"cluster_name"};
FilesystemSubscriptionImpl subscription_;
bool file_at_start_{false};
};
} // namespace Config
} // namespace Envoy