diff --git a/src/wasm.cc b/src/wasm.cc index c2dba732b..c7bcfcdd8 100644 --- a/src/wasm.cc +++ b/src/wasm.cc @@ -249,7 +249,9 @@ bool WasmBase::load(const std::string &code, bool allow_precompiled) { fail(FailState::UnableToInitializeCode, message); return false; } - wasm_vm_->integration()->trace(message); + if (!message.empty()) { + wasm_vm_->integration()->trace(message); + } // Get ABI version from the module. if (!BytecodeUtil::getAbiVersion(code, abi_version_)) { diff --git a/test/BUILD b/test/BUILD index 46514b982..ced9dbd37 100644 --- a/test/BUILD +++ b/test/BUILD @@ -56,6 +56,7 @@ cc_test( data = [ "//test/test_data:abi_export.wasm", "//test/test_data:callback.wasm", + "//test/test_data:clock.wasm", "//test/test_data:infinite_loop.wasm", "//test/test_data:trap.wasm", ], diff --git a/test/exports_test.cc b/test/exports_test.cc index aab95fcab..40e0359d1 100644 --- a/test/exports_test.cc +++ b/test/exports_test.cc @@ -30,89 +30,63 @@ namespace proxy_wasm { namespace { -INSTANTIATE_TEST_SUITE_P(WasmEngines, TestVM, testing::ValuesIn(getWasmEngines()), +INSTANTIATE_TEST_SUITE_P(WasmEngines, TestVm, testing::ValuesIn(getWasmEngines()), [](const testing::TestParamInfo &info) { return info.param; }); -class TestContext : public ContextBase { -public: - TestContext(WasmBase *base) : ContextBase(base){}; - WasmResult log(uint32_t /*log_level*/, std::string_view msg) override { - log_ += std::string(msg) + "\n"; - return WasmResult::Ok; - } - std::string &log_msg() { return log_; } - -private: - std::string log_; -}; - -TEST_P(TestVM, Environment) { +TEST_P(TestVm, Environment) { std::unordered_map envs = {{"KEY1", "VALUE1"}, {"KEY2", "VALUE2"}}; auto source = readTestWasmFile("env.wasm"); - - auto wasm_base = WasmBase(std::move(vm_), "vm_id", "", "", envs, {}); - ASSERT_TRUE(wasm_base.wasm_vm()->load(source, {}, {})); - - TestContext context(&wasm_base); - current_context_ = &context; - - wasm_base.registerCallbacks(); - - ASSERT_TRUE(wasm_base.wasm_vm()->link("")); + ASSERT_FALSE(source.empty()); + auto wasm = TestWasm(std::move(vm_), envs); + ASSERT_TRUE(wasm.load(source, false)); + ASSERT_TRUE(wasm.initialize()); WasmCallVoid<0> run; - wasm_base.wasm_vm()->getFunction("run", &run); - - run(current_context_); - - auto msg = context.log_msg(); - EXPECT_NE(std::string::npos, msg.find("KEY1: VALUE1\n")) << msg; - EXPECT_NE(std::string::npos, msg.find("KEY2: VALUE2\n")) << msg; + wasm.wasm_vm()->getFunction("run", &run); + ASSERT_TRUE(run != nullptr); + run(wasm.vm_context()); + + // Check application logs. + auto *context = dynamic_cast(wasm.vm_context()); + EXPECT_TRUE(context->isLogged("KEY1: VALUE1\n")); + EXPECT_TRUE(context->isLogged("KEY2: VALUE2\n")); } -TEST_P(TestVM, WithoutEnvironment) { +TEST_P(TestVm, WithoutEnvironment) { auto source = readTestWasmFile("env.wasm"); - auto wasm_base = WasmBase(std::move(vm_), "vm_id", "", "", {}, {}); - ASSERT_TRUE(wasm_base.wasm_vm()->load(source, {}, {})); - - TestContext context(&wasm_base); - current_context_ = &context; - - wasm_base.registerCallbacks(); - - ASSERT_TRUE(wasm_base.wasm_vm()->link("")); + ASSERT_FALSE(source.empty()); + auto wasm = TestWasm(std::move(vm_), {}); + ASSERT_TRUE(wasm.load(source, false)); + ASSERT_TRUE(wasm.initialize()); WasmCallVoid<0> run; - wasm_base.wasm_vm()->getFunction("run", &run); - - run(current_context_); + wasm.wasm_vm()->getFunction("run", &run); + ASSERT_TRUE(run != nullptr); + run(wasm.vm_context()); - EXPECT_EQ(context.log_msg(), ""); + // Check application logs. + auto *context = dynamic_cast(wasm.vm_context()); + EXPECT_TRUE(context->isLogEmpty()); } -TEST_P(TestVM, Clock) { +TEST_P(TestVm, Clock) { auto source = readTestWasmFile("clock.wasm"); - auto wasm_base = WasmBase(std::move(vm_), "vm_id", "", "", {}, {}); - ASSERT_TRUE(wasm_base.wasm_vm()->load(source, {}, {})); - - TestContext context(&wasm_base); - current_context_ = &context; - - wasm_base.registerCallbacks(); - - ASSERT_TRUE(wasm_base.wasm_vm()->link("")); + ASSERT_FALSE(source.empty()); + auto wasm = TestWasm(std::move(vm_)); + ASSERT_TRUE(wasm.load(source, false)); + ASSERT_TRUE(wasm.initialize()); WasmCallVoid<0> run; - wasm_base.wasm_vm()->getFunction("run", &run); - ASSERT_TRUE(run); - run(current_context_); - - // Check logs. - auto msg = context.log_msg(); - EXPECT_NE(std::string::npos, msg.find("monotonic: ")) << msg; - EXPECT_NE(std::string::npos, msg.find("realtime: ")) << msg; + wasm.wasm_vm()->getFunction("run", &run); + ASSERT_TRUE(run != nullptr); + run(wasm.vm_context()); + + // Check application logs. + auto *context = dynamic_cast(wasm.vm_context()); + EXPECT_TRUE(context->isLogged("monotonic: ")); + EXPECT_TRUE(context->isLogged("realtime: ")); } } // namespace diff --git a/test/runtime_test.cc b/test/runtime_test.cc index 132f8247d..3b7effcab 100644 --- a/test/runtime_test.cc +++ b/test/runtime_test.cc @@ -30,12 +30,12 @@ namespace proxy_wasm { namespace { -INSTANTIATE_TEST_SUITE_P(WasmEngines, TestVM, testing::ValuesIn(getWasmEngines()), +INSTANTIATE_TEST_SUITE_P(WasmEngines, TestVm, testing::ValuesIn(getWasmEngines()), [](const testing::TestParamInfo &info) { return info.param; }); -TEST_P(TestVM, Basic) { +TEST_P(TestVm, Basic) { if (engine_ == "wamr") { EXPECT_EQ(vm_->cloneable(), proxy_wasm::Cloneable::NotCloneable); } else if (engine_ == "wasmtime" || engine_ == "v8") { @@ -48,7 +48,7 @@ TEST_P(TestVM, Basic) { EXPECT_EQ(vm_->getEngineName(), engine_); } -TEST_P(TestVM, Memory) { +TEST_P(TestVm, Memory) { auto source = readTestWasmFile("abi_export.wasm"); ASSERT_TRUE(vm_->load(source, {}, {})); ASSERT_TRUE(vm_->link("")); @@ -66,7 +66,7 @@ TEST_P(TestVM, Memory) { ASSERT_EQ(200, static_cast(word.u64_)); } -TEST_P(TestVM, Clone) { +TEST_P(TestVm, Clone) { if (vm_->cloneable() == proxy_wasm::Cloneable::NotCloneable) { return; } @@ -95,7 +95,7 @@ TEST_P(TestVM, Clone) { #if defined(__linux__) && defined(__x86_64__) -TEST_P(TestVM, CloneUntilOutOfMemory) { +TEST_P(TestVm, CloneUntilOutOfMemory) { if (vm_->cloneable() == proxy_wasm::Cloneable::NotCloneable) { return; } @@ -141,154 +141,167 @@ TEST_P(TestVM, CloneUntilOutOfMemory) { #endif -class TestContext : public ContextBase { +class TestCounterContext : public TestContext { public: - TestContext() = default; + TestCounterContext(WasmBase *wasm) : TestContext(wasm) {} + void increment() { counter++; } - int64_t counter = 0; + size_t getCount() { return counter; } + +private: + size_t counter = 0; }; -void nopCallback() {} +class TestCounterWasm : public TestWasm { +public: + TestCounterWasm(std::unique_ptr wasm_vm) : TestWasm(std::move(wasm_vm)) {} + + ContextBase *createVmContext() override { return new TestCounterContext(this); }; +}; void callback() { - auto *context = dynamic_cast(contextOrEffectiveContext()); + auto *context = dynamic_cast(contextOrEffectiveContext()); context->increment(); } Word callback2(Word val) { return val + 100; } -TEST_P(TestVM, StraceLogLevel) { +TEST_P(TestVm, StraceLogLevel) { if (engine_ == "wavm") { // TODO(mathetake): strace is yet to be implemented for WAVM. // See https://github.com/proxy-wasm/proxy-wasm-cpp-host/issues/120. return; } - auto *integration = dynamic_cast(vm_->integration().get()); - auto source = readTestWasmFile("callback.wasm"); - ASSERT_TRUE(vm_->load(source, {}, {})); - vm_->registerCallback("env", "callback", &nopCallback, - &ConvertFunctionWordToUint32::convertFunctionWordToUint32); - vm_->registerCallback( - "env", "callback2", &callback2, - &ConvertFunctionWordToUint32::convertFunctionWordToUint32); - ASSERT_TRUE(vm_->link("")); + auto source = readTestWasmFile("clock.wasm"); + ASSERT_FALSE(source.empty()); + auto wasm = TestWasm(std::move(vm_)); + ASSERT_TRUE(wasm.load(source, false)); + ASSERT_TRUE(wasm.initialize()); WasmCallVoid<0> run; - vm_->getFunction("run", &run); - - run(nullptr); - // no trace message found since DummyIntegration's log_level_ defaults to LogLevel::info - EXPECT_EQ(integration->trace_message_, ""); - - integration->log_level_ = LogLevel::trace; - run(nullptr); - EXPECT_NE(integration->trace_message_, ""); + wasm.wasm_vm()->getFunction("run", &run); + ASSERT_TRUE(run != nullptr); + + auto *host = dynamic_cast(wasm.wasm_vm()->integration().get()); + host->setLogLevel(LogLevel::info); + run(wasm.vm_context()); + EXPECT_TRUE(host->isTraceLogEmpty()); + + host->setLogLevel(LogLevel::trace); + run(wasm.vm_context()); + EXPECT_TRUE(host->isTraceLogged("[host->vm] run()")); + EXPECT_TRUE(host->isTraceLogged("[vm->host] wasi_snapshot_preview1.clock_time_get(1, 1, ")); + EXPECT_TRUE(host->isTraceLogged("[vm<-host] wasi_snapshot_preview1.clock_time_get return: 0")); + EXPECT_TRUE(host->isTraceLogged("[host<-vm] run return: void")); } -TEST_P(TestVM, BadExportFunction) { - auto source = readTestWasmFile("callback.wasm"); - ASSERT_TRUE(vm_->load(source, {}, {})); - - TestContext context; - vm_->registerCallback( - "env", "callback", &callback, - &ConvertFunctionWordToUint32::convertFunctionWordToUint32); - vm_->registerCallback( - "env", "callback2", &callback2, - &ConvertFunctionWordToUint32::convertFunctionWordToUint32); - ASSERT_TRUE(vm_->link("")); +TEST_P(TestVm, BadExportFunction) { + auto source = readTestWasmFile("clock.wasm"); + ASSERT_FALSE(source.empty()); + auto wasm = TestWasm(std::move(vm_)); + ASSERT_TRUE(wasm.load(source, false)); + ASSERT_TRUE(wasm.initialize()); - WasmCallVoid<0> run; - vm_->getFunction("non-existent", &run); - EXPECT_TRUE(run == nullptr); + WasmCallVoid<0> non_existent; + wasm.wasm_vm()->getFunction("non_existent", &non_existent); + EXPECT_TRUE(non_existent == nullptr); WasmCallWord<2> bad_signature_run; - vm_->getFunction("run", &bad_signature_run); + wasm.wasm_vm()->getFunction("run", &bad_signature_run); EXPECT_TRUE(bad_signature_run == nullptr); - vm_->getFunction("run", &run); - EXPECT_TRUE(run != nullptr); - for (auto i = 0; i < 100; i++) { - run(&context); - } - ASSERT_EQ(context.counter, 100); + WasmCallVoid<0> run; + wasm.wasm_vm()->getFunction("run", &run); + ASSERT_TRUE(run != nullptr); } -TEST_P(TestVM, Callback) { +TEST_P(TestVm, Callback) { auto source = readTestWasmFile("callback.wasm"); - ASSERT_TRUE(vm_->load(source, {}, {})); + ASSERT_FALSE(source.empty()); + auto wasm = TestCounterWasm(std::move(vm_)); + ASSERT_TRUE(wasm.load(source, false)); - TestContext context; - - vm_->registerCallback( + wasm.wasm_vm()->registerCallback( "env", "callback", &callback, &ConvertFunctionWordToUint32::convertFunctionWordToUint32); - vm_->registerCallback( + wasm.wasm_vm()->registerCallback( "env", "callback2", &callback2, &ConvertFunctionWordToUint32::convertFunctionWordToUint32); - ASSERT_TRUE(vm_->link("")); + ASSERT_TRUE(wasm.initialize()); WasmCallVoid<0> run; - vm_->getFunction("run", &run); - EXPECT_TRUE(run != nullptr); - for (auto i = 0; i < 100; i++) { - run(&context); + wasm.wasm_vm()->getFunction("run", &run); + ASSERT_TRUE(run != nullptr); + for (auto i = 0; i < 5; i++) { + run(wasm.vm_context()); } - ASSERT_EQ(context.counter, 100); + auto *context = dynamic_cast(wasm.vm_context()); + EXPECT_EQ(context->getCount(), 5); WasmCallWord<1> run2; - vm_->getFunction("run2", &run2); - Word res = run2(&context, Word{0}); - ASSERT_EQ(res.u32(), 100100); // 10000 (global) + 100(in callback) + wasm.wasm_vm()->getFunction("run2", &run2); + ASSERT_TRUE(run2 != nullptr); + Word res = run2(wasm.vm_context(), Word{0}); + EXPECT_EQ(res.u32(), 100100); // 10000 (global) + 100 (in callback) } -TEST_P(TestVM, TerminateExecution) { +TEST_P(TestVm, TerminateExecution) { // TODO(chaoqin-li1123): implement execution termination for other runtime. if (engine_ != "v8") { return; } auto source = readTestWasmFile("infinite_loop.wasm"); - ASSERT_TRUE(vm_->load(source, {}, {})); - - TestContext context; + ASSERT_FALSE(source.empty()); + auto wasm = TestWasm(std::move(vm_)); + ASSERT_TRUE(wasm.load(source, false)); + ASSERT_TRUE(wasm.initialize()); std::thread terminate([&]() { - std::this_thread::sleep_for(std::chrono::seconds(3)); - vm_->terminate(); + std::this_thread::sleep_for(std::chrono::seconds(1)); + wasm.wasm_vm()->terminate(); }); - ASSERT_TRUE(vm_->link("")); WasmCallVoid<0> infinite_loop; - vm_->getFunction("infinite_loop", &infinite_loop); + wasm.wasm_vm()->getFunction("infinite_loop", &infinite_loop); ASSERT_TRUE(infinite_loop != nullptr); - infinite_loop(&context); + infinite_loop(wasm.vm_context()); terminate.join(); - std::string exp_message = "Function: infinite_loop failed: Uncaught Error: termination_exception"; - auto *integration = dynamic_cast(vm_->integration().get()); - ASSERT_TRUE(integration->error_message_.find(exp_message) != std::string::npos); + // Check integration logs. + auto *host = dynamic_cast(wasm.wasm_vm()->integration().get()); + EXPECT_TRUE(host->isErrorLogged("Function: infinite_loop failed")); + if (engine_ == "v8") { + EXPECT_TRUE(host->isErrorLogged("Uncaught Error: termination_exception")); + } } -TEST_P(TestVM, Trap) { +TEST_P(TestVm, Trap) { auto source = readTestWasmFile("trap.wasm"); - ASSERT_TRUE(vm_->load(source, {}, {})); - ASSERT_TRUE(vm_->link("")); - TestContext context; + ASSERT_FALSE(source.empty()); + auto wasm = TestWasm(std::move(vm_)); + ASSERT_TRUE(wasm.load(source, false)); + ASSERT_TRUE(wasm.initialize()); + WasmCallVoid<0> trigger; - vm_->getFunction("trigger", &trigger); - EXPECT_TRUE(trigger != nullptr); - trigger(&context); - std::string exp_message = "Function: trigger failed"; - auto *integration = dynamic_cast(vm_->integration().get()); - ASSERT_TRUE(integration->error_message_.find(exp_message) != std::string::npos); + wasm.wasm_vm()->getFunction("trigger", &trigger); + ASSERT_TRUE(trigger != nullptr); + trigger(wasm.vm_context()); + + // Check integration logs. + auto *host = dynamic_cast(wasm.wasm_vm()->integration().get()); + EXPECT_TRUE(host->isErrorLogged("Function: trigger failed")); + if (engine_ == "v8") { + EXPECT_TRUE(host->isErrorLogged("Uncaught RuntimeError: unreachable")); + EXPECT_TRUE(host->isErrorLogged("Proxy-Wasm plugin in-VM backtrace:")); + EXPECT_TRUE(host->isErrorLogged(" - trigger")); + } } -TEST_P(TestVM, Trap2) { +TEST_P(TestVm, Trap2) { if (engine_ == "wavm") { // TODO(mathetake): Somehow WAVM exits with 'munmap_chunk(): invalid pointer' on unidentified // build condition in 'libstdc++ abi::__cxa_demangle' originally from @@ -296,16 +309,24 @@ TEST_P(TestVM, Trap2) { return; } auto source = readTestWasmFile("trap.wasm"); - ASSERT_TRUE(vm_->load(source, {}, {})); - ASSERT_TRUE(vm_->link("")); - TestContext context; + ASSERT_FALSE(source.empty()); + auto wasm = TestWasm(std::move(vm_)); + ASSERT_TRUE(wasm.load(source, false)); + ASSERT_TRUE(wasm.initialize()); + WasmCallWord<1> trigger2; - vm_->getFunction("trigger2", &trigger2); - EXPECT_TRUE(trigger2 != nullptr); - trigger2(&context, 0); - std::string exp_message = "Function: trigger2 failed"; - auto *integration = dynamic_cast(vm_->integration().get()); - ASSERT_TRUE(integration->error_message_.find(exp_message) != std::string::npos); + wasm.wasm_vm()->getFunction("trigger2", &trigger2); + ASSERT_TRUE(trigger2 != nullptr); + trigger2(wasm.vm_context(), 0); + + // Check integration logs. + auto *host = dynamic_cast(wasm.wasm_vm()->integration().get()); + EXPECT_TRUE(host->isErrorLogged("Function: trigger2 failed")); + if (engine_ == "v8") { + EXPECT_TRUE(host->isErrorLogged("Uncaught RuntimeError: unreachable")); + EXPECT_TRUE(host->isErrorLogged("Proxy-Wasm plugin in-VM backtrace:")); + EXPECT_TRUE(host->isErrorLogged(" - trigger2")); + } } } // namespace diff --git a/test/test_data/callback.rs b/test/test_data/callback.rs index 0c142a8ec..cab0141c4 100644 --- a/test/test_data/callback.rs +++ b/test/test_data/callback.rs @@ -12,6 +12,14 @@ // See the License for the specific language governing permissions and // limitations under the License. +#[no_mangle] +pub extern "C" fn proxy_abi_version_0_2_0() {} + +#[no_mangle] +pub extern "C" fn proxy_on_memory_allocate(_: usize) -> *mut u8 { + std::ptr::null_mut() +} + #[no_mangle] pub extern "C" fn run() { unsafe { @@ -32,4 +40,3 @@ extern "C" { fn callback(); fn callback2(val: i32) -> i32; } - diff --git a/test/test_data/clock.rs b/test/test_data/clock.rs index 480a2b1bd..e2697a949 100644 --- a/test/test_data/clock.rs +++ b/test/test_data/clock.rs @@ -14,6 +14,14 @@ use std::time::{Instant, SystemTime}; +#[no_mangle] +pub extern "C" fn proxy_abi_version_0_2_0() {} + +#[no_mangle] +pub extern "C" fn proxy_on_memory_allocate(_: usize) -> *mut u8 { + std::ptr::null_mut() +} + #[no_mangle] pub extern "C" fn run() { println!("monotonic: {:?}", Instant::now()); diff --git a/test/test_data/env.rs b/test/test_data/env.rs index 59bf2cc72..63d345ee1 100644 --- a/test/test_data/env.rs +++ b/test/test_data/env.rs @@ -13,14 +13,26 @@ // limitations under the License. extern "C" { - fn __wasilibc_initialize_environ(); + fn __wasm_call_ctors(); } #[no_mangle] -pub extern "C" fn run() { +pub extern "C" fn _initialize() { unsafe { - __wasilibc_initialize_environ(); + __wasm_call_ctors(); } +} + +#[no_mangle] +pub extern "C" fn proxy_abi_version_0_2_0() {} + +#[no_mangle] +pub extern "C" fn proxy_on_memory_allocate(_: usize) -> *mut u8 { + std::ptr::null_mut() +} + +#[no_mangle] +pub extern "C" fn run() { for (key, value) in std::env::vars() { println!("{}: {}\n", key, value); } diff --git a/test/test_data/infinite_loop.rs b/test/test_data/infinite_loop.rs index c502be879..371443e68 100644 --- a/test/test_data/infinite_loop.rs +++ b/test/test_data/infinite_loop.rs @@ -12,6 +12,14 @@ // See the License for the specific language governing permissions and // limitations under the License. +#[no_mangle] +pub extern "C" fn proxy_abi_version_0_2_0() {} + +#[no_mangle] +pub extern "C" fn proxy_on_memory_allocate(_: usize) -> *mut u8 { + std::ptr::null_mut() +} + #[no_mangle] pub extern "C" fn infinite_loop() { let mut _count: u64 = 0; diff --git a/test/test_data/trap.rs b/test/test_data/trap.rs index fe6f71f62..467397206 100644 --- a/test/test_data/trap.rs +++ b/test/test_data/trap.rs @@ -12,6 +12,14 @@ // See the License for the specific language governing permissions and // limitations under the License. +#[no_mangle] +pub extern "C" fn proxy_abi_version_0_2_0() {} + +#[no_mangle] +pub extern "C" fn proxy_on_memory_allocate(_: usize) -> *mut u8 { + std::ptr::null_mut() +} + #[no_mangle] pub extern "C" fn trigger() { one(); diff --git a/test/utility.h b/test/utility.h index 36dceef1f..311481021 100644 --- a/test/utility.h +++ b/test/utility.h @@ -18,6 +18,7 @@ #include #include #include +#include #include #include "include/proxy-wasm/context.h" @@ -41,34 +42,77 @@ namespace proxy_wasm { std::vector getWasmEngines(); std::string readTestWasmFile(const std::string &filename); -struct DummyIntegration : public WasmVmIntegration { - ~DummyIntegration() override = default; - WasmVmIntegration *clone() override { return new DummyIntegration{}; } +class TestIntegration : public WasmVmIntegration { +public: + ~TestIntegration() override = default; + WasmVmIntegration *clone() override { return new TestIntegration{}; } + + void setLogLevel(LogLevel level) { log_level_ = level; } + + LogLevel getLogLevel() override { return log_level_; } + void error(std::string_view message) override { std::cout << "ERROR from integration: " << message << std::endl; - error_message_ = message; + error_log_ += std::string(message) + "\n"; + } + + bool isErrorLogEmpty() { return error_log_.empty(); } + + bool isErrorLogged(std::string_view message) { + return error_log_.find(message) != std::string::npos; } + void trace(std::string_view message) override { std::cout << "TRACE from integration: " << message << std::endl; - trace_message_ = message; + trace_log_ += std::string(message) + "\n"; } + + bool isTraceLogEmpty() { return trace_log_.empty(); } + + bool isTraceLogged(std::string_view message) { + return trace_log_.find(message) != std::string::npos; + } + bool getNullVmFunction(std::string_view /*function_name*/, bool /*returns_word*/, int /*number_of_arguments*/, NullPlugin * /*plugin*/, void * /*ptr_to_function_return*/) override { return false; }; - LogLevel getLogLevel() override { return log_level_; } - std::string error_message_; - std::string trace_message_; - LogLevel log_level_ = LogLevel::info; +private: + std::string error_log_; + std::string trace_log_; + LogLevel log_level_ = LogLevel::trace; }; -class TestVM : public testing::TestWithParam { +class TestContext : public ContextBase { public: - std::unique_ptr vm_; + TestContext(WasmBase *wasm) : ContextBase(wasm) {} + + WasmResult log(uint32_t /*log_level*/, std::string_view message) override { + log_ += std::string(message) + "\n"; + return WasmResult::Ok; + } + + bool isLogEmpty() { return log_.empty(); } + + bool isLogged(std::string_view message) { return log_.find(message) != std::string::npos; } + +private: + std::string log_; +}; - TestVM() { +class TestWasm : public WasmBase { +public: + TestWasm(std::unique_ptr wasm_vm, std::unordered_map envs = {}) + : WasmBase(std::move(wasm_vm), "", "", "", std::move(envs), {}) {} + + ContextBase *createVmContext() override { return new TestContext(this); }; +}; + +class TestVm : public testing::TestWithParam { +public: + TestVm() { engine_ = GetParam(); vm_ = newVm(); } @@ -76,7 +120,7 @@ class TestVM : public testing::TestWithParam { std::unique_ptr newVm() { std::unique_ptr vm; if (engine_.empty()) { - EXPECT_TRUE(false) << "engine must not be empty"; + ADD_FAILURE() << "engine must not be empty"; #if defined(PROXY_WASM_HOST_ENGINE_V8) } else if (engine_ == "v8") { vm = proxy_wasm::createV8Vm(); @@ -94,13 +138,13 @@ class TestVM : public testing::TestWithParam { vm = proxy_wasm::createWamrVm(); #endif } else { - EXPECT_TRUE(false) << "compiled without support for the requested \"" << engine_ - << "\" engine"; + ADD_FAILURE() << "compiled without support for the requested \"" << engine_ << "\" engine"; } - vm->integration() = std::make_unique(); + vm->integration() = std::make_unique(); return vm; }; + std::unique_ptr vm_; std::string engine_; }; diff --git a/test/wasm_test.cc b/test/wasm_test.cc index 4fc509c8e..51026b559 100644 --- a/test/wasm_test.cc +++ b/test/wasm_test.cc @@ -20,13 +20,13 @@ namespace proxy_wasm { -INSTANTIATE_TEST_SUITE_P(WasmEngines, TestVM, testing::ValuesIn(getWasmEngines()), +INSTANTIATE_TEST_SUITE_P(WasmEngines, TestVm, testing::ValuesIn(getWasmEngines()), [](const testing::TestParamInfo &info) { return info.param; }); // Fail callbacks only used for WasmVMs - not available for NullVM. -TEST_P(TestVM, GetOrCreateThreadLocalWasmFailCallbacks) { +TEST_P(TestVm, GetOrCreateThreadLocalWasmFailCallbacks) { const auto *const plugin_name = "plugin_name"; const auto *const root_id = "root_id"; const auto *const vm_id = "vm_id";