Skip to content

Commit 5574daf

Browse files
authored
Test an example stream context with a logging plugin (#348)
* Allow StreamContext testing via TestContext Signed-off-by: Martijn Stevenson <mstevenson@google.com> * Test an example Stream Context. HTTP handlers, logging only, no headers. Signed-off-by: Martijn Stevenson <mstevenson@google.com> * Add missing license header. Signed-off-by: Martijn Stevenson <mstevenson@google.com> * Attempt to fix clang-tidy Signed-off-by: Martijn Stevenson <mstevenson@google.com> * Make newVm a static method for broader utility. Signed-off-by: Martijn Stevenson <mstevenson@google.com> * Code review cleanups. Signed-off-by: Martijn Stevenson <mstevenson@google.com> * Remove unnecessary pointer / heap allocation Signed-off-by: Martijn Stevenson <mstevenson@google.com> --------- Signed-off-by: Martijn Stevenson <mstevenson@google.com>
1 parent 491915a commit 5574daf

File tree

6 files changed

+148
-18
lines changed

6 files changed

+148
-18
lines changed

test/BUILD

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,21 @@ cc_test(
117117
],
118118
)
119119

120+
cc_test(
121+
name = "logging_test",
122+
srcs = ["logging_test.cc"],
123+
data = [
124+
"//test/test_data:http_logging.wasm",
125+
],
126+
linkstatic = 1,
127+
deps = [
128+
":utility_lib",
129+
"//:lib",
130+
"@com_google_googletest//:gtest",
131+
"@com_google_googletest//:gtest_main",
132+
],
133+
)
134+
120135
cc_test(
121136
name = "security_test",
122137
srcs = ["security_test.cc"],

test/logging_test.cc

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
// Copyright 2023 Google LLC
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
#include "gtest/gtest.h"
16+
#include "include/proxy-wasm/wasm.h"
17+
#include "test/utility.h"
18+
19+
namespace proxy_wasm {
20+
21+
INSTANTIATE_TEST_SUITE_P(WasmEngines, TestVm, testing::ValuesIn(getWasmEngines()),
22+
[](const testing::TestParamInfo<std::string> &info) {
23+
return info.param;
24+
});
25+
26+
// TestVm is parameterized for each engine and creates a VM on construction.
27+
TEST_P(TestVm, HttpLogging) {
28+
// Read the wasm source.
29+
auto source = readTestWasmFile("http_logging.wasm");
30+
ASSERT_FALSE(source.empty());
31+
32+
// Create a WasmBase and load the plugin.
33+
auto wasm = std::make_shared<TestWasm>(std::move(vm_));
34+
ASSERT_TRUE(wasm->load(source, /*allow_precompiled=*/false));
35+
ASSERT_TRUE(wasm->initialize());
36+
37+
// Create a plugin.
38+
const auto plugin = std::make_shared<PluginBase>(
39+
/*name=*/"test", /*root_id=*/"", /*vm_id=*/"",
40+
/*engine=*/wasm->wasm_vm()->getEngineName(), /*plugin_config=*/"",
41+
/*fail_open=*/false, /*key=*/"");
42+
43+
// Create root context, call onStart().
44+
ContextBase *root_context = wasm->start(plugin);
45+
ASSERT_TRUE(root_context != nullptr);
46+
47+
// On the root context, call onConfigure().
48+
ASSERT_TRUE(wasm->configure(root_context, plugin));
49+
50+
// Create a stream context.
51+
{
52+
auto wasm_handle = std::make_shared<WasmHandleBase>(wasm);
53+
auto plugin_handle = std::make_shared<PluginHandleBase>(wasm_handle, plugin);
54+
auto stream_context = TestContext(wasm.get(), root_context->id(), plugin_handle);
55+
stream_context.onCreate();
56+
EXPECT_TRUE(stream_context.isLogged("onCreate called"));
57+
stream_context.onRequestHeaders(/*headers=*/0, /*end_of_stream=*/false);
58+
EXPECT_TRUE(stream_context.isLogged("onRequestHeaders called"));
59+
stream_context.onResponseHeaders(/*headers=*/0, /*end_of_stream=*/false);
60+
EXPECT_TRUE(stream_context.isLogged("onResponseHeaders called"));
61+
stream_context.onDone();
62+
EXPECT_TRUE(stream_context.isLogged("onDone called"));
63+
stream_context.onDelete();
64+
EXPECT_TRUE(stream_context.isLogged("onDelete called"));
65+
}
66+
EXPECT_FALSE(wasm->isFailed());
67+
}
68+
69+
} // namespace proxy_wasm

test/test_data/BUILD

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,3 +84,8 @@ proxy_wasm_cc_binary(
8484
name = "canary_check.wasm",
8585
srcs = ["canary_check.cc"],
8686
)
87+
88+
proxy_wasm_cc_binary(
89+
name = "http_logging.wasm",
90+
srcs = ["http_logging.cc"],
91+
)

test/test_data/http_logging.cc

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
// Copyright 2023 Google LLC
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
#include "proxy_wasm_intrinsics.h"
16+
17+
class LoggingContext : public Context {
18+
public:
19+
explicit LoggingContext(uint32_t id, RootContext *root) : Context(id, root) {}
20+
21+
void onCreate() override { LOG_INFO("onCreate called"); }
22+
void onDelete() override { LOG_INFO("onDelete called"); }
23+
void onDone() override { LOG_INFO("onDone called"); }
24+
25+
FilterHeadersStatus onRequestHeaders(uint32_t headers, bool end_of_stream) override {
26+
LOG_INFO("onRequestHeaders called");
27+
return FilterHeadersStatus::Continue;
28+
}
29+
30+
FilterHeadersStatus onResponseHeaders(uint32_t headers, bool end_of_stream) override {
31+
LOG_INFO("onResponseHeaders called");
32+
return FilterHeadersStatus::Continue;
33+
}
34+
};
35+
36+
static RegisterContextFactory register_StaticContext(CONTEXT_FACTORY(LoggingContext),
37+
ROOT_FACTORY(RootContext));

test/utility.h

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,9 @@ class TestContext : public ContextBase {
9393
TestContext(WasmBase *wasm) : ContextBase(wasm) {}
9494
TestContext(WasmBase *wasm, const std::shared_ptr<PluginBase> &plugin)
9595
: ContextBase(wasm, plugin) {}
96+
TestContext(WasmBase *wasm, uint32_t parent_context_id,
97+
std::shared_ptr<PluginHandleBase> &plugin_handle)
98+
: ContextBase(wasm, parent_context_id, plugin_handle) {}
9699

97100
WasmResult log(uint32_t /*log_level*/, std::string_view message) override {
98101
auto new_log = std::string(message) + "\n";
@@ -156,39 +159,39 @@ class TestVm : public testing::TestWithParam<std::string> {
156159
public:
157160
TestVm() {
158161
engine_ = GetParam();
159-
vm_ = newVm();
162+
vm_ = makeVm(engine_);
160163
}
161164

162-
std::unique_ptr<proxy_wasm::WasmVm> newVm() {
165+
static std::unique_ptr<proxy_wasm::WasmVm> makeVm(const std::string &engine) {
163166
std::unique_ptr<proxy_wasm::WasmVm> vm;
164-
if (engine_.empty()) {
167+
if (engine.empty()) {
165168
ADD_FAILURE() << "engine must not be empty";
166169
#if defined(PROXY_WASM_HOST_ENGINE_V8)
167-
} else if (engine_ == "v8") {
170+
} else if (engine == "v8") {
168171
vm = proxy_wasm::createV8Vm();
169172
#endif
170173
#if defined(PROXY_WASM_HOST_ENGINE_WAVM)
171-
} else if (engine_ == "wavm") {
174+
} else if (engine == "wavm") {
172175
vm = proxy_wasm::createWavmVm();
173176
#endif
174177
#if defined(PROXY_WASM_HOST_ENGINE_WASMTIME)
175-
} else if (engine_ == "wasmtime") {
178+
} else if (engine == "wasmtime") {
176179
vm = proxy_wasm::createWasmtimeVm();
177180
#endif
178181
#if defined(PROXY_WASM_HOST_ENGINE_WASMEDGE)
179-
} else if (engine_ == "wasmedge") {
182+
} else if (engine == "wasmedge") {
180183
vm = proxy_wasm::createWasmEdgeVm();
181184
#endif
182185
#if defined(PROXY_WASM_HOST_ENGINE_WAMR)
183-
} else if (engine_ == "wamr") {
186+
} else if (engine == "wamr") {
184187
vm = proxy_wasm::createWamrVm();
185188
#endif
186189
} else {
187-
ADD_FAILURE() << "compiled without support for the requested \"" << engine_ << "\" engine";
190+
ADD_FAILURE() << "compiled without support for the requested \"" << engine << "\" engine";
188191
}
189192
vm->integration() = std::make_unique<TestIntegration>();
190193
return vm;
191-
};
194+
}
192195

193196
std::unique_ptr<proxy_wasm::WasmVm> vm_;
194197
std::string engine_;

test/wasm_test.cc

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ TEST_P(TestVm, GetOrCreateThreadLocalWasmFailCallbacks) {
4343
// Define callbacks.
4444
WasmHandleFactory wasm_handle_factory =
4545
[this, vm_id, vm_config](std::string_view vm_key) -> std::shared_ptr<WasmHandleBase> {
46-
auto base_wasm = std::make_shared<WasmBase>(newVm(), vm_id, vm_config, vm_key,
46+
auto base_wasm = std::make_shared<WasmBase>(makeVm(engine_), vm_id, vm_config, vm_key,
4747
std::unordered_map<std::string, std::string>{},
4848
AllowedCapabilitiesMap{});
4949
return std::make_shared<WasmHandleBase>(base_wasm);
@@ -52,8 +52,8 @@ TEST_P(TestVm, GetOrCreateThreadLocalWasmFailCallbacks) {
5252
WasmHandleCloneFactory wasm_handle_clone_factory =
5353
[this](const std::shared_ptr<WasmHandleBase> &base_wasm_handle)
5454
-> std::shared_ptr<WasmHandleBase> {
55-
auto wasm = std::make_shared<WasmBase>(base_wasm_handle,
56-
[this]() -> std::unique_ptr<WasmVm> { return newVm(); });
55+
auto wasm = std::make_shared<WasmBase>(
56+
base_wasm_handle, [this]() -> std::unique_ptr<WasmVm> { return makeVm(engine_); });
5757
return std::make_shared<WasmHandleBase>(wasm);
5858
};
5959

@@ -133,8 +133,8 @@ TEST_P(TestVm, AlwaysApplyCanary) {
133133
WasmHandleCloneFactory wasm_handle_clone_factory_for_canary =
134134
[&canary_count, this](const std::shared_ptr<WasmHandleBase> &base_wasm_handle)
135135
-> std::shared_ptr<WasmHandleBase> {
136-
auto wasm = std::make_shared<TestWasm>(base_wasm_handle,
137-
[this]() -> std::unique_ptr<WasmVm> { return newVm(); });
136+
auto wasm = std::make_shared<TestWasm>(
137+
base_wasm_handle, [this]() -> std::unique_ptr<WasmVm> { return makeVm(engine_); });
138138
canary_count++;
139139
return std::make_shared<WasmHandleBase>(wasm);
140140
};
@@ -150,8 +150,9 @@ TEST_P(TestVm, AlwaysApplyCanary) {
150150

151151
WasmHandleFactory wasm_handle_factory_baseline =
152152
[this, vm_ids, vm_configs](std::string_view vm_key) -> std::shared_ptr<WasmHandleBase> {
153-
auto base_wasm = std::make_shared<TestWasm>(
154-
newVm(), std::unordered_map<std::string, std::string>(), vm_ids[0], vm_configs[0], vm_key);
153+
auto base_wasm =
154+
std::make_shared<TestWasm>(makeVm(engine_), std::unordered_map<std::string, std::string>(),
155+
vm_ids[0], vm_configs[0], vm_key);
155156
return std::make_shared<WasmHandleBase>(base_wasm);
156157
};
157158

@@ -184,7 +185,7 @@ TEST_P(TestVm, AlwaysApplyCanary) {
184185
[this, vm_id,
185186
vm_config](std::string_view vm_key) -> std::shared_ptr<WasmHandleBase> {
186187
auto base_wasm = std::make_shared<TestWasm>(
187-
newVm(), std::unordered_map<std::string, std::string>(), vm_id, vm_config,
188+
makeVm(engine_), std::unordered_map<std::string, std::string>(), vm_id, vm_config,
188189
vm_key);
189190
return std::make_shared<WasmHandleBase>(base_wasm);
190191
};

0 commit comments

Comments
 (0)