1414
1515#include " gtest/gtest.h"
1616
17- #include < fstream>
18- #include < iostream>
1917#include < memory>
20- #include < sstream>
2118#include < string>
2219#include < thread>
23- #include < vector>
2420
2521#include " include/proxy-wasm/context.h"
2622#include " include/proxy-wasm/wasm.h"
@@ -35,137 +31,26 @@ INSTANTIATE_TEST_SUITE_P(WasmEngines, TestVm, testing::ValuesIn(getWasmEngines()
3531 return info.param ;
3632 });
3733
38- TEST_P (TestVm, Basic) {
39- if (engine_ == " wamr" ) {
40- EXPECT_EQ (vm_->cloneable (), proxy_wasm::Cloneable::NotCloneable);
41- } else if (engine_ == " wasmtime" || engine_ == " v8" ) {
42- EXPECT_EQ (vm_->cloneable (), proxy_wasm::Cloneable::CompiledBytecode);
43- } else if (engine_ == " wavm" ) {
44- EXPECT_EQ (vm_->cloneable (), proxy_wasm::Cloneable::InstantiatedModule);
45- } else {
46- FAIL ();
47- }
48- EXPECT_EQ (vm_->getEngineName (), engine_);
49- }
50-
51- TEST_P (TestVm, Memory) {
52- auto source = readTestWasmFile (" abi_export.wasm" );
53- ASSERT_TRUE (vm_->load (source, {}, {}));
54- ASSERT_TRUE (vm_->link (" " ));
55-
56- Word word;
57- ASSERT_TRUE (vm_->setWord (0x2000 , Word (100 )));
58- ASSERT_TRUE (vm_->getWord (0x2000 , &word));
59- ASSERT_EQ (100 , word.u64_ );
60-
61- uint32_t data[2 ] = {htowasm (static_cast <uint32_t >(-1 )), htowasm (200 )};
62- ASSERT_TRUE (vm_->setMemory (0x200 , sizeof (int32_t ) * 2 , static_cast <void *>(data)));
63- ASSERT_TRUE (vm_->getWord (0x200 , &word));
64- ASSERT_EQ (-1 , static_cast <int32_t >(word.u64_ ));
65- ASSERT_TRUE (vm_->getWord (0x204 , &word));
66- ASSERT_EQ (200 , static_cast <int32_t >(word.u64_ ));
67- }
68-
69- TEST_P (TestVm, Clone) {
70- if (vm_->cloneable () == proxy_wasm::Cloneable::NotCloneable) {
71- return ;
72- }
73- auto source = readTestWasmFile (" abi_export.wasm" );
74- ASSERT_TRUE (vm_->load (source, {}, {}));
75- ASSERT_TRUE (vm_->link (" " ));
76- const auto address = 0x2000 ;
77- Word word;
78- {
79- auto clone = vm_->clone ();
80- ASSERT_TRUE (clone != nullptr );
81- ASSERT_NE (vm_, clone);
82- if (clone->cloneable () != proxy_wasm::Cloneable::InstantiatedModule) {
83- ASSERT_TRUE (clone->link (" " ));
84- }
85-
86- ASSERT_TRUE (clone->setWord (address, Word (100 )));
87- ASSERT_TRUE (clone->getWord (address, &word));
88- ASSERT_EQ (100 , word.u64_ );
89- }
90-
91- // check memory arrays are not overrapped
92- ASSERT_TRUE (vm_->getWord (address, &word));
93- ASSERT_NE (100 , word.u64_ );
94- }
95-
96- #if defined(__linux__) && defined(__x86_64__)
97-
98- TEST_P (TestVm, CloneUntilOutOfMemory) {
99- if (vm_->cloneable () == proxy_wasm::Cloneable::NotCloneable) {
100- return ;
101- }
102- if (engine_ == " wavm" ) {
103- // TODO(PiotrSikora): Figure out why this fails on the CI.
104- return ;
105- }
106-
107- auto source = readTestWasmFile (" abi_export.wasm" );
108- ASSERT_TRUE (vm_->load (source, {}, {}));
109- ASSERT_TRUE (vm_->link (" " ));
110-
111- size_t max_clones = 100000 ;
112- #if defined(__has_feature)
113- #if __has_feature(address_sanitizer)
114- max_clones = 1000 ;
115- #endif
116- #endif
117-
118- std::vector<std::unique_ptr<WasmVm>> clones;
119- for (size_t i = 0 ; i < max_clones; i++) {
120- auto clone = vm_->clone ();
121- if (clone == nullptr ) {
122- break ;
123- }
124- if (clone->cloneable () != proxy_wasm::Cloneable::InstantiatedModule) {
125- if (!clone->link (" " )) {
126- break ;
127- }
128- }
129- // Prevent clone from droping out of scope and freeing memory.
130- clones.push_back (std::move (clone));
131- }
132-
133- size_t min_clones = 1000 ;
134- #if defined(__has_feature)
135- #if __has_feature(thread_sanitizer)
136- min_clones = 100 ;
137- #endif
138- #endif
139- EXPECT_GE (clones.size (), min_clones);
140- }
141-
142- #endif
143-
144- class TestCounterContext : public TestContext {
145- public:
146- TestCounterContext (WasmBase *wasm) : TestContext(wasm) {}
147-
148- void increment () { counter++; }
149- size_t getCount () { return counter; }
150-
151- private:
152- size_t counter = 0 ;
153- };
34+ TEST_P (TestVm, BadSignature) {
35+ auto source = readTestWasmFile (" clock.wasm" );
36+ ASSERT_FALSE (source.empty ());
37+ auto wasm = TestWasm (std::move (vm_));
38+ ASSERT_TRUE (wasm.load (source, false ));
39+ ASSERT_TRUE (wasm.initialize ());
15440
155- class TestCounterWasm : public TestWasm {
156- public:
157- TestCounterWasm (std::unique_ptr<WasmVm> wasm_vm) : TestWasm(std::move(wasm_vm)) {}
41+ WasmCallVoid< 0 > non_existent;
42+ wasm. wasm_vm ()-> getFunction ( " non_existent " , &non_existent);
43+ EXPECT_TRUE (non_existent == nullptr );
15844
159- ContextBase *createVmContext () override { return new TestCounterContext (this ); };
160- };
45+ WasmCallWord<2 > bad_signature_run;
46+ wasm.wasm_vm ()->getFunction (" run" , &bad_signature_run);
47+ EXPECT_TRUE (bad_signature_run == nullptr );
16148
162- void callback () {
163- auto *context = dynamic_cast <TestCounterContext *>( contextOrEffectiveContext () );
164- context-> increment ( );
49+ WasmCallVoid< 0 > run;
50+ wasm. wasm_vm ()-> getFunction ( " run " , &run );
51+ ASSERT_TRUE (run != nullptr );
16552}
16653
167- Word callback2 (Word val) { return val + 100 ; }
168-
16954TEST_P (TestVm, StraceLogLevel) {
17055 if (engine_ == " wavm" ) {
17156 // TODO(mathetake): strace is yet to be implemented for WAVM.
@@ -196,58 +81,6 @@ TEST_P(TestVm, StraceLogLevel) {
19681 EXPECT_TRUE (host->isTraceLogged (" [host<-vm] run return: void" ));
19782}
19883
199- TEST_P (TestVm, BadExportFunction) {
200- auto source = readTestWasmFile (" clock.wasm" );
201- ASSERT_FALSE (source.empty ());
202- auto wasm = TestWasm (std::move (vm_));
203- ASSERT_TRUE (wasm.load (source, false ));
204- ASSERT_TRUE (wasm.initialize ());
205-
206- WasmCallVoid<0 > non_existent;
207- wasm.wasm_vm ()->getFunction (" non_existent" , &non_existent);
208- EXPECT_TRUE (non_existent == nullptr );
209-
210- WasmCallWord<2 > bad_signature_run;
211- wasm.wasm_vm ()->getFunction (" run" , &bad_signature_run);
212- EXPECT_TRUE (bad_signature_run == nullptr );
213-
214- WasmCallVoid<0 > run;
215- wasm.wasm_vm ()->getFunction (" run" , &run);
216- ASSERT_TRUE (run != nullptr );
217- }
218-
219- TEST_P (TestVm, Callback) {
220- auto source = readTestWasmFile (" callback.wasm" );
221- ASSERT_FALSE (source.empty ());
222- auto wasm = TestCounterWasm (std::move (vm_));
223- ASSERT_TRUE (wasm.load (source, false ));
224-
225- wasm.wasm_vm ()->registerCallback (
226- " env" , " callback" , &callback,
227- &ConvertFunctionWordToUint32<decltype (callback), callback>::convertFunctionWordToUint32);
228-
229- wasm.wasm_vm ()->registerCallback (
230- " env" , " callback2" , &callback2,
231- &ConvertFunctionWordToUint32<decltype (callback2), callback2>::convertFunctionWordToUint32);
232-
233- ASSERT_TRUE (wasm.initialize ());
234-
235- WasmCallVoid<0 > run;
236- wasm.wasm_vm ()->getFunction (" run" , &run);
237- ASSERT_TRUE (run != nullptr );
238- for (auto i = 0 ; i < 5 ; i++) {
239- run (wasm.vm_context ());
240- }
241- auto *context = dynamic_cast <TestCounterContext *>(wasm.vm_context ());
242- EXPECT_EQ (context->getCount (), 5 );
243-
244- WasmCallWord<1 > run2;
245- wasm.wasm_vm ()->getFunction (" run2" , &run2);
246- ASSERT_TRUE (run2 != nullptr );
247- Word res = run2 (wasm.vm_context (), Word{0 });
248- EXPECT_EQ (res.u32 (), 100100 ); // 10000 (global) + 100 (in callback)
249- }
250-
25184TEST_P (TestVm, TerminateExecution) {
25285 // TODO(chaoqin-li1123): implement execution termination for other runtime.
25386 if (engine_ != " v8" ) {
@@ -329,5 +162,62 @@ TEST_P(TestVm, Trap2) {
329162 }
330163}
331164
165+ class TestCounterContext : public TestContext {
166+ public:
167+ TestCounterContext (WasmBase *wasm) : TestContext(wasm) {}
168+
169+ void increment () { counter++; }
170+ size_t getCount () { return counter; }
171+
172+ private:
173+ size_t counter = 0 ;
174+ };
175+
176+ class TestCounterWasm : public TestWasm {
177+ public:
178+ TestCounterWasm (std::unique_ptr<WasmVm> wasm_vm) : TestWasm(std::move(wasm_vm)) {}
179+
180+ ContextBase *createVmContext () override { return new TestCounterContext (this ); };
181+ };
182+
183+ void callback () {
184+ auto *context = dynamic_cast <TestCounterContext *>(contextOrEffectiveContext ());
185+ context->increment ();
186+ }
187+
188+ Word callback2 (Word val) { return val + 100 ; }
189+
190+ TEST_P (TestVm, Callback) {
191+ auto source = readTestWasmFile (" callback.wasm" );
192+ ASSERT_FALSE (source.empty ());
193+ auto wasm = TestCounterWasm (std::move (vm_));
194+ ASSERT_TRUE (wasm.load (source, false ));
195+
196+ wasm.wasm_vm ()->registerCallback (
197+ " env" , " callback" , &callback,
198+ &ConvertFunctionWordToUint32<decltype (callback), callback>::convertFunctionWordToUint32);
199+
200+ wasm.wasm_vm ()->registerCallback (
201+ " env" , " callback2" , &callback2,
202+ &ConvertFunctionWordToUint32<decltype (callback2), callback2>::convertFunctionWordToUint32);
203+
204+ ASSERT_TRUE (wasm.initialize ());
205+
206+ WasmCallVoid<0 > run;
207+ wasm.wasm_vm ()->getFunction (" run" , &run);
208+ ASSERT_TRUE (run != nullptr );
209+ for (auto i = 0 ; i < 5 ; i++) {
210+ run (wasm.vm_context ());
211+ }
212+ auto *context = dynamic_cast <TestCounterContext *>(wasm.vm_context ());
213+ EXPECT_EQ (context->getCount (), 5 );
214+
215+ WasmCallWord<1 > run2;
216+ wasm.wasm_vm ()->getFunction (" run2" , &run2);
217+ ASSERT_TRUE (run2 != nullptr );
218+ Word res = run2 (wasm.vm_context (), Word{0 });
219+ EXPECT_EQ (res.u32 (), 100100 ); // 10000 (global) + 100 (in callback)
220+ }
221+
332222} // namespace
333223} // namespace proxy_wasm
0 commit comments