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