1 #include <gtest/gtest.h>
2 #include <wasmtime.hh>
3 
4 using namespace wasmtime;
5 
6 template <typename T, typename E> T unwrap(Result<T, E> result) {
7   if (result) {
8     return result.ok();
9   }
10   std::cerr << "error: " << result.err().message() << "\n";
11   std::abort();
12 }
13 
14 TEST(Engine, Smoke) {
15   Engine engine;
16   Config config;
17   engine = Engine(std::move(config));
18 }
19 
20 TEST(wat2wasm, Smoke) {
21   wat2wasm("(module)").ok();
22   wat2wasm("xxx").err();
23 }
24 
25 TEST(Module, Smoke) {
26   Engine engine;
27   Module::compile(engine, "(module)").ok();
28   Module::compile(engine, "wat").err();
29 
30   auto wasm = wat2wasm("(module)").ok();
31   Module::compile(engine, wasm).ok();
32   std::vector<uint8_t> emptyWasm;
33   Module::compile(engine, emptyWasm).err();
34 
35   Module::validate(engine, wasm).ok();
36   Module::validate(engine, emptyWasm).err();
37 
38   Module m2 = unwrap(Module::compile(engine, "(module)"));
39   Module m3 = m2;
40   Module m4(m3);
41   m4 = m2;
42   Module m5(std::move(m3));
43   m4 = std::move(m5);
44 }
45 
46 TEST(Module, Serialize) {
47   Engine engine;
48   Module m = unwrap(Module::compile(engine, "(module)"));
49   auto bytes = unwrap(m.serialize());
50   m = unwrap(Module::deserialize(engine, bytes));
51   std::string path("test_deserialize_file.cwasm");
52   auto fh = ::fopen(path.c_str(), "wb");
53   ::fwrite(bytes.data(), sizeof(uint8_t), bytes.size(), fh);
54   ::fclose(fh);
55   m = unwrap(Module::deserialize_file(engine, path));
56   ::remove(path.c_str());
57 }
58 
59 TEST(ExternRef, Smoke) {
60   Engine engine;
61   Store store(engine);
62   ExternRef a(store, "foo");
63   ExternRef b(store, 3);
64   EXPECT_STREQ(std::any_cast<const char *>(a.data(store)), "foo");
65   EXPECT_EQ(std::any_cast<int>(b.data(store)), 3);
66   a.unroot(store);
67   a = b;
68 }
69 
70 TEST(Caller, Smoke) {
71   Engine engine;
72   Store store(engine);
73   Func f(store, FuncType({}, {}),
74          [](auto caller, auto params, auto results) -> auto {
75            EXPECT_FALSE(caller.get_export("foo"));
76            return std::monostate();
77          });
78   unwrap(f.call(store, {}));
79 
80   Module m = unwrap(Module::compile(engine, "(module "
81                                             "(import \"\" \"\" (func))"
82                                             "(memory (export \"m\") 1)"
83                                             "(func (export \"f\") call 0)"
84                                             ")"));
85   Func f2(store, FuncType({}, {}),
86           [](auto caller, auto params, auto results) -> auto {
87             EXPECT_FALSE(caller.get_export("foo"));
88             EXPECT_TRUE(caller.get_export("m"));
89             EXPECT_TRUE(caller.get_export("f"));
90             Memory m = std::get<Memory>(*caller.get_export("m"));
91             EXPECT_EQ(m.type(caller)->min(), 1);
92             return std::monostate();
93           });
94   Instance i = unwrap(Instance::create(store, m, {f2}));
95   f = std::get<Func>(*i.get(store, "f"));
96   unwrap(f.call(store, {}));
97 }
98 
99 TEST(Func, Smoke) {
100   Engine engine;
101   Store store(engine);
102   Func f(store, FuncType({}, {}),
103          [](auto caller, auto params, auto results) -> auto {
104            return std::monostate();
105          });
106   unwrap(f.call(store, {}));
107 
108   Func f2(store, FuncType({}, {}),
109           [](auto caller, auto params, auto results) -> auto {
110             return Trap("message");
111           });
112   EXPECT_EQ(f2.call(store, {}).err().message(), "message");
113 }
114 
115 TEST(Data, Smoke) {
116 
117   Engine engine;
118   Store store(engine);
119   store.context().set_data(10);
120   Func f0(store, FuncType({}, {}),
121           [](auto caller, auto params,
122              auto results) -> Result<std::monostate, Trap> {
123             auto data = std::any_cast<int>(caller.context().get_data());
124             if (data != 10) {
125               return Trap("message");
126             }
127             return std::monostate();
128           });
129   unwrap(f0.call(store, {}));
130 
131   store.context().set_data(std::make_pair<int, int>(10, -3));
132   Func f1(store, FuncType({}, {}),
133           [](auto caller, auto params,
134              auto results) -> Result<std::monostate, Trap> {
135             auto data =
136                 std::any_cast<std::pair<int, int>>(caller.context().get_data());
137             if (data.first != 10 || data.second != -3) {
138               return Trap("message");
139             }
140             return std::monostate();
141           });
142   unwrap(f1.call(store, {}));
143 
144   store.context().set_data(std::string("hello world"));
145   Func f2(store, FuncType({}, {}),
146           [](auto caller, auto params,
147              auto results) -> Result<std::monostate, Trap> {
148             auto data = std::any_cast<std::string>(caller.context().get_data());
149             if (data != "hello world") {
150               return Trap("message");
151             }
152             return std::monostate();
153           });
154   unwrap(f2.call(store, {}));
155 
156   struct test_object {
157     test_object() : v(nullptr) {}
158     test_object(int i) : v(new int(i)) {}
159     test_object(const test_object &other)
160         : v((other.v) ? new int(*other.v) : nullptr) {}
161     test_object(test_object &&other) : v(other.v) { other.v = nullptr; }
162     ~test_object() {
163       if (v) {
164         delete v;
165         v = nullptr;
166       }
167     }
168     int *v;
169   };
170 
171   test_object data(7);
172   store.context().set_data(&data); // by pointer
173   Func f3(store, FuncType({}, {}),
174           [](auto caller, auto params,
175              auto results) -> Result<std::monostate, Trap> {
176             auto data =
177                 std::any_cast<test_object *>(caller.context().get_data());
178             if (*data->v != 7) {
179               return Trap("message");
180             }
181             return std::monostate();
182           });
183   unwrap(f3.call(store, {}));
184   EXPECT_EQ(*data.v, 7);
185 
186   store.context().set_data(data); // by copy
187   Func f4(store, FuncType({}, {}),
188           [](auto caller, auto params,
189              auto results) -> Result<std::monostate, Trap> {
190             auto data =
191                 std::any_cast<test_object &>(caller.context().get_data());
192             if (*data.v != 7) {
193               return Trap("message");
194             }
195             return std::monostate();
196           });
197   unwrap(f4.call(store, {}));
198   EXPECT_EQ(*data.v, 7);
199 
200   store.context().set_data(std::move(data)); // by move
201   Func f5(store, FuncType({}, {}),
202           [](auto caller, auto params,
203              auto results) -> Result<std::monostate, Trap> {
204             auto data =
205                 std::any_cast<test_object &>(caller.context().get_data());
206             if (*data.v != 7) {
207               return Trap("message");
208             }
209             return std::monostate();
210           });
211   unwrap(f5.call(store, {}));
212   EXPECT_EQ(data.v, nullptr);
213 }
214