1 #include <gtest/gtest.h>
2 #include <wasmtime.hh>
3 
4 using namespace wasmtime;
5 
unwrap(Result<T,E> result)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 
TEST(Engine,Smoke)14 TEST(Engine, Smoke) {
15   Engine engine;
16   Config config;
17   engine = Engine(std::move(config));
18 }
19 
TEST(wat2wasm,Smoke)20 TEST(wat2wasm, Smoke) {
21   wat2wasm("(module)").ok();
22   wat2wasm("xxx").err();
23 }
24 
TEST(Module,Smoke)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 
TEST(Module,Serialize)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 
TEST(ExternRef,Smoke)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 = b;
67 }
68 
TEST(Caller,Smoke)69 TEST(Caller, Smoke) {
70   Engine engine;
71   Store store(engine);
72   Func f(store, FuncType({}, {}),
73          [](auto caller, auto params, auto results) -> auto {
74            EXPECT_FALSE(caller.get_export("foo"));
75            return std::monostate();
76          });
77   unwrap(f.call(store, {}));
78 
79   Module m = unwrap(Module::compile(engine, "(module "
80                                             "(import \"\" \"\" (func))"
81                                             "(memory (export \"m\") 1)"
82                                             "(func (export \"f\") call 0)"
83                                             ")"));
84   Func f2(store, FuncType({}, {}),
85           [](auto caller, auto params, auto results) -> auto {
86             EXPECT_FALSE(caller.get_export("foo"));
87             EXPECT_TRUE(caller.get_export("m"));
88             EXPECT_TRUE(caller.get_export("f"));
89             Memory m = std::get<Memory>(*caller.get_export("m"));
90             EXPECT_EQ(m.type(caller)->min(), 1);
91             return std::monostate();
92           });
93   Instance i = unwrap(Instance::create(store, m, {f2}));
94   f = std::get<Func>(*i.get(store, "f"));
95   unwrap(f.call(store, {}));
96 }
97 
TEST(Func,Smoke)98 TEST(Func, Smoke) {
99   Engine engine;
100   Store store(engine);
101   Func f(store, FuncType({}, {}),
102          [](auto caller, auto params, auto results) -> auto {
103            return std::monostate();
104          });
105   unwrap(f.call(store, {}));
106 
107   Func f2(store, FuncType({}, {}),
108           [](auto caller, auto params, auto results) -> auto {
109             return Trap("message");
110           });
111   EXPECT_EQ(f2.call(store, {}).err().message(), "message");
112 }
113 
TEST(Data,Smoke)114 TEST(Data, Smoke) {
115 
116   Engine engine;
117   Store store(engine);
118   store.context().set_data(10);
119   Func f0(store, FuncType({}, {}),
120           [](auto caller, auto params,
121              auto results) -> Result<std::monostate, Trap> {
122             auto data = std::any_cast<int>(caller.context().get_data());
123             if (data != 10) {
124               return Trap("message");
125             }
126             return std::monostate();
127           });
128   unwrap(f0.call(store, {}));
129 
130   store.context().set_data(std::make_pair<int, int>(10, -3));
131   Func f1(store, FuncType({}, {}),
132           [](auto caller, auto params,
133              auto results) -> Result<std::monostate, Trap> {
134             auto data =
135                 std::any_cast<std::pair<int, int>>(caller.context().get_data());
136             if (data.first != 10 || data.second != -3) {
137               return Trap("message");
138             }
139             return std::monostate();
140           });
141   unwrap(f1.call(store, {}));
142 
143   store.context().set_data(std::string("hello world"));
144   Func f2(store, FuncType({}, {}),
145           [](auto caller, auto params,
146              auto results) -> Result<std::monostate, Trap> {
147             auto data = std::any_cast<std::string>(caller.context().get_data());
148             if (data != "hello world") {
149               return Trap("message");
150             }
151             return std::monostate();
152           });
153   unwrap(f2.call(store, {}));
154 
155   struct test_object {
156     test_object() : v(nullptr) {}
157     test_object(int i) : v(new int(i)) {}
158     test_object(const test_object &other)
159         : v((other.v) ? new int(*other.v) : nullptr) {}
160     test_object(test_object &&other) : v(other.v) { other.v = nullptr; }
161     ~test_object() {
162       if (v) {
163         delete v;
164         v = nullptr;
165       }
166     }
167     int *v;
168   };
169 
170   test_object data(7);
171   store.context().set_data(&data); // by pointer
172   Func f3(store, FuncType({}, {}),
173           [](auto caller, auto params,
174              auto results) -> Result<std::monostate, Trap> {
175             auto data =
176                 std::any_cast<test_object *>(caller.context().get_data());
177             if (*data->v != 7) {
178               return Trap("message");
179             }
180             return std::monostate();
181           });
182   unwrap(f3.call(store, {}));
183   EXPECT_EQ(*data.v, 7);
184 
185   store.context().set_data(data); // by copy
186   Func f4(store, FuncType({}, {}),
187           [](auto caller, auto params,
188              auto results) -> Result<std::monostate, Trap> {
189             auto data =
190                 std::any_cast<test_object &>(caller.context().get_data());
191             if (*data.v != 7) {
192               return Trap("message");
193             }
194             return std::monostate();
195           });
196   unwrap(f4.call(store, {}));
197   EXPECT_EQ(*data.v, 7);
198 
199   store.context().set_data(std::move(data)); // by move
200   Func f5(store, FuncType({}, {}),
201           [](auto caller, auto params,
202              auto results) -> Result<std::monostate, Trap> {
203             auto data =
204                 std::any_cast<test_object &>(caller.context().get_data());
205             if (*data.v != 7) {
206               return Trap("message");
207             }
208             return std::monostate();
209           });
210   unwrap(f5.call(store, {}));
211   EXPECT_EQ(data.v, nullptr);
212 }
213