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 = b; 67 } 68 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 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 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