Skip to content

Commit dce6347

Browse files
committed
Add tests for getOrCreateThreadLocalPlugin.
Signed-off-by: Takeshi Yoneda <[email protected]>
1 parent b029b24 commit dce6347

File tree

8 files changed

+171
-72
lines changed

8 files changed

+171
-72
lines changed

test/BUILD

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -78,9 +78,13 @@ cc_test(
7878
)
7979

8080
cc_test(
81-
name = "context_test",
82-
srcs = ["context_test.cc"],
81+
name = "wasm_test",
82+
srcs = ["wasm_test.cc"],
83+
data = [
84+
"//test/test_data:abi_export.wasm",
85+
],
8386
deps = [
87+
":utility_lib",
8488
"//:lib",
8589
"@com_google_googletest//:gtest",
8690
"@com_google_googletest//:gtest_main",

test/bytecode_util_test.cc

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,14 @@ TEST(TestBytecodeUtil, getFunctionNameIndex) {
5959
// OK.
6060
EXPECT_TRUE(BytecodeUtil::getFunctionNameIndex(source, actual));
6161
EXPECT_FALSE(actual.empty());
62-
EXPECT_EQ(actual.find(0)->second, "proxy_abi_version_0_2_0");
62+
bool abi_version_found = false;
63+
for (auto it : actual) {
64+
if (it.second == "proxy_abi_version_0_2_0") {
65+
abi_version_found = true;
66+
break;
67+
}
68+
}
69+
EXPECT_TRUE(abi_version_found);
6370

6471
// Fail due to the corrupted bytecode.
6572
// TODO(@mathetake): here we haven't covered all the parsing failure branches. Add more cases.

test/context_test.cc

Lines changed: 0 additions & 35 deletions
This file was deleted.

test/exports_test.cc

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -49,10 +49,10 @@ class TestContext : public ContextBase {
4949

5050
TEST_P(TestVM, Environment) {
5151
std::unordered_map<std::string, std::string> envs = {{"KEY1", "VALUE1"}, {"KEY2", "VALUE2"}};
52-
initialize("env.wasm");
52+
auto source = readTestWasmFile("env.wasm");
5353

5454
auto wasm_base = WasmBase(std::move(vm_), "vm_id", "", "", envs, {});
55-
ASSERT_TRUE(wasm_base.wasm_vm()->load(source_, {}, {}));
55+
ASSERT_TRUE(wasm_base.wasm_vm()->load(source, {}, {}));
5656

5757
TestContext context(&wasm_base);
5858
current_context_ = &context;
@@ -72,9 +72,9 @@ TEST_P(TestVM, Environment) {
7272
}
7373

7474
TEST_P(TestVM, WithoutEnvironment) {
75-
initialize("env.wasm");
75+
auto source = readTestWasmFile("env.wasm");
7676
auto wasm_base = WasmBase(std::move(vm_), "vm_id", "", "", {}, {});
77-
ASSERT_TRUE(wasm_base.wasm_vm()->load(source_, {}, {}));
77+
ASSERT_TRUE(wasm_base.wasm_vm()->load(source, {}, {}));
7878

7979
TestContext context(&wasm_base);
8080
current_context_ = &context;
@@ -92,9 +92,9 @@ TEST_P(TestVM, WithoutEnvironment) {
9292
}
9393

9494
TEST_P(TestVM, Clock) {
95-
initialize("clock.wasm");
95+
auto source = readTestWasmFile("clock.wasm");
9696
auto wasm_base = WasmBase(std::move(vm_), "vm_id", "", "", {}, {});
97-
ASSERT_TRUE(wasm_base.wasm_vm()->load(source_, {}, {}));
97+
ASSERT_TRUE(wasm_base.wasm_vm()->load(source, {}, {}));
9898

9999
TestContext context(&wasm_base);
100100
current_context_ = &context;

test/runtime_test.cc

Lines changed: 21 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -47,8 +47,8 @@ TEST_P(TestVM, Basic) {
4747
}
4848

4949
TEST_P(TestVM, Memory) {
50-
initialize("abi_export.wasm");
51-
ASSERT_TRUE(vm_->load(source_, {}, {}));
50+
auto source = readTestWasmFile("abi_export.wasm");
51+
ASSERT_TRUE(vm_->load(source, {}, {}));
5252
ASSERT_TRUE(vm_->link(""));
5353

5454
Word word;
@@ -68,8 +68,8 @@ TEST_P(TestVM, Clone) {
6868
if (vm_->cloneable() == proxy_wasm::Cloneable::NotCloneable) {
6969
return;
7070
}
71-
initialize("abi_export.wasm");
72-
ASSERT_TRUE(vm_->load(source_, {}, {}));
71+
auto source = readTestWasmFile("abi_export.wasm");
72+
ASSERT_TRUE(vm_->load(source, {}, {}));
7373
ASSERT_TRUE(vm_->link(""));
7474
const auto address = 0x2000;
7575
Word word;
@@ -113,8 +113,10 @@ TEST_P(TestVM, StraceLogLevel) {
113113
// See https://github.com/proxy-wasm/proxy-wasm-cpp-host/issues/120.
114114
return;
115115
}
116-
initialize("callback.wasm");
117-
ASSERT_TRUE(vm_->load(source_, {}, {}));
116+
117+
auto integration = static_cast<DummyIntegration *>(vm_->integration().get());
118+
auto source = readTestWasmFile("callback.wasm");
119+
ASSERT_TRUE(vm_->load(source, {}, {}));
118120
vm_->registerCallback("env", "callback", &nopCallback,
119121
&ConvertFunctionWordToUint32<decltype(nopCallback),
120122
nopCallback>::convertFunctionWordToUint32);
@@ -128,16 +130,16 @@ TEST_P(TestVM, StraceLogLevel) {
128130

129131
run(nullptr);
130132
// no trace message found since DummyIntegration's log_level_ defaults to LogLevel::info
131-
EXPECT_EQ(integration_->trace_message_, "");
133+
EXPECT_EQ(integration->trace_message_, "");
132134

133-
integration_->log_level_ = LogLevel::trace;
135+
integration->log_level_ = LogLevel::trace;
134136
run(nullptr);
135-
EXPECT_NE(integration_->trace_message_, "");
137+
EXPECT_NE(integration->trace_message_, "");
136138
}
137139

138140
TEST_P(TestVM, Callback) {
139-
initialize("callback.wasm");
140-
ASSERT_TRUE(vm_->load(source_, {}, {}));
141+
auto source = readTestWasmFile("callback.wasm");
142+
ASSERT_TRUE(vm_->load(source, {}, {}));
141143

142144
TestContext context;
143145

@@ -166,16 +168,17 @@ TEST_P(TestVM, Callback) {
166168
}
167169

168170
TEST_P(TestVM, Trap) {
169-
initialize("trap.wasm");
170-
ASSERT_TRUE(vm_->load(source_, {}, {}));
171+
auto source = readTestWasmFile("trap.wasm");
172+
ASSERT_TRUE(vm_->load(source, {}, {}));
171173
ASSERT_TRUE(vm_->link(""));
172174
TestContext context;
173175
WasmCallVoid<0> trigger;
174176
vm_->getFunction("trigger", &trigger);
175177
EXPECT_TRUE(trigger != nullptr);
176178
trigger(&context);
177179
std::string exp_message = "Function: trigger failed";
178-
ASSERT_TRUE(integration_->error_message_.find(exp_message) != std::string::npos);
180+
auto integration = static_cast<DummyIntegration *>(vm_->integration().get());
181+
ASSERT_TRUE(integration->error_message_.find(exp_message) != std::string::npos);
179182
}
180183

181184
TEST_P(TestVM, Trap2) {
@@ -185,16 +188,17 @@ TEST_P(TestVM, Trap2) {
185188
// WAVM::Runtime::describeCallStack. Needs further investigation.
186189
return;
187190
}
188-
initialize("trap.wasm");
189-
ASSERT_TRUE(vm_->load(source_, {}, {}));
191+
auto source = readTestWasmFile("trap.wasm");
192+
ASSERT_TRUE(vm_->load(source, {}, {}));
190193
ASSERT_TRUE(vm_->link(""));
191194
TestContext context;
192195
WasmCallWord<1> trigger2;
193196
vm_->getFunction("trigger2", &trigger2);
194197
EXPECT_TRUE(trigger2 != nullptr);
195198
trigger2(&context, 0);
196199
std::string exp_message = "Function: trigger2 failed";
197-
ASSERT_TRUE(integration_->error_message_.find(exp_message) != std::string::npos);
200+
auto integration = static_cast<DummyIntegration *>(vm_->integration().get());
201+
ASSERT_TRUE(integration->error_message_.find(exp_message) != std::string::npos);
198202
}
199203

200204
} // namespace

test/test_data/abi_export.rs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,3 +14,21 @@
1414

1515
#[no_mangle]
1616
pub extern "C" fn proxy_abi_version_0_2_0() {}
17+
18+
#[no_mangle]
19+
pub extern "C" fn proxy_on_vm_start(_: u32, _: usize) -> bool {
20+
true
21+
}
22+
23+
#[no_mangle]
24+
pub extern "C" fn proxy_on_context_create(_: u32, _: u32) {}
25+
26+
#[no_mangle]
27+
pub extern "C" fn proxy_on_memory_allocate(size: usize) -> *mut u8 {
28+
let mut vec: Vec<u8> = Vec::with_capacity(size);
29+
unsafe {
30+
vec.set_len(size);
31+
}
32+
let slice = vec.into_boxed_slice();
33+
Box::into_raw(slice) as *mut u8
34+
}

test/utility.h

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -67,37 +67,39 @@ class TestVM : public testing::TestWithParam<std::string> {
6767
public:
6868
std::unique_ptr<proxy_wasm::WasmVm> vm_;
6969

70-
TestVM() : integration_(new DummyIntegration{}) {
70+
TestVM() {
7171
runtime_ = GetParam();
72+
vm_ = newVm();
73+
}
74+
75+
std::unique_ptr<proxy_wasm::WasmVm> newVm() {
76+
std::unique_ptr<proxy_wasm::WasmVm> vm;
7277
if (runtime_ == "") {
7378
EXPECT_TRUE(false) << "runtime must not be empty";
7479
#if defined(PROXY_WASM_HAS_RUNTIME_V8)
7580
} else if (runtime_ == "v8") {
76-
vm_ = proxy_wasm::createV8Vm();
81+
vm = proxy_wasm::createV8Vm();
7782
#endif
7883
#if defined(PROXY_WASM_HAS_RUNTIME_WAVM)
7984
} else if (runtime_ == "wavm") {
80-
vm_ = proxy_wasm::createWavmVm();
85+
vm = proxy_wasm::createWavmVm();
8186
#endif
8287
#if defined(PROXY_WASM_HAS_RUNTIME_WASMTIME)
8388
} else if (runtime_ == "wasmtime") {
84-
vm_ = proxy_wasm::createWasmtimeVm();
89+
vm = proxy_wasm::createWasmtimeVm();
8590
#endif
8691
#if defined(PROXY_WASM_HAS_RUNTIME_WAMR)
8792
} else if (runtime_ == "wamr") {
88-
vm_ = proxy_wasm::createWamrVm();
93+
vm = proxy_wasm::createWamrVm();
8994
#endif
9095
} else {
9196
EXPECT_TRUE(false) << "compiled without support for the requested \"" << runtime_
9297
<< "\" runtime";
9398
}
94-
vm_->integration().reset(integration_);
95-
}
96-
97-
void initialize(std::string filename) { source_ = readTestWasmFile(filename); }
99+
vm->integration().reset(new DummyIntegration{});
100+
return vm;
101+
};
98102

99-
DummyIntegration *integration_;
100-
std::string source_;
101103
std::string runtime_;
102104
};
103105
} // namespace proxy_wasm

test/wasm_test.cc

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
// Copyright 2020 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 "include/proxy-wasm/wasm.h"
16+
17+
#include "gtest/gtest.h"
18+
19+
#include "test/utility.h"
20+
21+
namespace proxy_wasm {
22+
23+
auto test_values = testing::ValuesIn(getRuntimes());
24+
25+
INSTANTIATE_TEST_SUITE_P(Runtimes, TestVM, test_values);
26+
27+
// Failcallbacks only used for runtimes - not available for nullvm.
28+
TEST_P(TestVM, GetOrCreateThreadLocalWasmFailCallbacks) {
29+
const auto plugin_name = "plugin_name";
30+
const auto root_id = "root_id";
31+
const auto vm_id = "vm_id";
32+
const auto plugin_config = "plugin_config";
33+
const auto fail_open = false;
34+
35+
// Create a plugin.
36+
const auto plugin = std::make_shared<PluginBase>(plugin_name, root_id, vm_id, runtime_,
37+
plugin_config, fail_open, "plugin_key");
38+
39+
// Define callbacks.
40+
WasmHandleFactory wasm_handle_factory =
41+
[this](std::string_view vm_key) -> std::shared_ptr<WasmHandleBase> {
42+
auto base_wasm = std::make_shared<WasmBase>(newVm(), "vm_id", "vm_config", vm_key,
43+
std::unordered_map<std::string, std::string>{},
44+
AllowedCapabilitiesMap{});
45+
return std::make_shared<WasmHandleBase>(base_wasm);
46+
};
47+
48+
WasmHandleCloneFactory wasm_handle_clone_factory =
49+
[this](std::shared_ptr<WasmHandleBase> base_wasm_handle) -> std::shared_ptr<WasmHandleBase> {
50+
auto wasm = std::make_shared<WasmBase>(base_wasm_handle,
51+
[this]() -> std::unique_ptr<WasmVm> { return newVm(); });
52+
return std::make_shared<WasmHandleBase>(wasm);
53+
};
54+
55+
PluginHandleFactory plugin_handle_factory =
56+
[](std::shared_ptr<WasmHandleBase> base_wasm,
57+
std::shared_ptr<PluginBase> plugin) -> std::shared_ptr<PluginHandleBase> {
58+
return std::make_shared<PluginHandleBase>(base_wasm, plugin);
59+
};
60+
61+
// Read the minimal loadable binary.
62+
auto source = readTestWasmFile("abi_export.wasm");
63+
64+
// Create base Wasm via createWasm.
65+
auto base_wasm_handle =
66+
createWasm("vm_key", source, plugin, wasm_handle_factory, wasm_handle_clone_factory, false);
67+
ASSERT_TRUE(base_wasm_handle && base_wasm_handle->wasm());
68+
69+
// Create a thread local plugin.
70+
auto thread_local_plugin = getOrCreateThreadLocalPlugin(
71+
base_wasm_handle, plugin, wasm_handle_clone_factory, plugin_handle_factory);
72+
ASSERT_TRUE(thread_local_plugin && thread_local_plugin->plugin());
73+
74+
// Cause runtime crash.
75+
thread_local_plugin->wasm()->wasm_vm()->fail(FailState::RuntimeError, "runtime error msg");
76+
ASSERT_TRUE(thread_local_plugin->wasm()->isFailed());
77+
78+
// Create another thread local plugin with the same configuration.
79+
// This one should not end up using the failed VM.
80+
auto thread_local_plugin_new = getOrCreateThreadLocalPlugin(
81+
base_wasm_handle, plugin, wasm_handle_clone_factory, plugin_handle_factory);
82+
ASSERT_TRUE(thread_local_plugin_new && thread_local_plugin_new->plugin());
83+
ASSERT_FALSE(thread_local_plugin_new->wasm()->isFailed());
84+
85+
// Cause runtime crash again.
86+
thread_local_plugin_new->wasm()->wasm_vm()->fail(FailState::RuntimeError, "runtime error msg");
87+
ASSERT_TRUE(thread_local_plugin_new->wasm()->isFailed());
88+
89+
// This time, create another thread local plugin with *different* plugin key for the same vm_key.
90+
// This one also should not end up using the failed VM.
91+
const auto plugin2 = std::make_shared<PluginBase>(plugin_name, root_id, vm_id, runtime_,
92+
plugin_config, fail_open, "another_plugin_key");
93+
auto thread_local_plugin_new2 = getOrCreateThreadLocalPlugin(
94+
base_wasm_handle, plugin2, wasm_handle_clone_factory, plugin_handle_factory);
95+
ASSERT_TRUE(thread_local_plugin_new2 && thread_local_plugin_new2->plugin());
96+
ASSERT_FALSE(thread_local_plugin_new2->wasm()->isFailed());
97+
}
98+
99+
} // namespace proxy_wasm

0 commit comments

Comments
 (0)