test_helper.h 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339
  1. /*
  2. * Copyright (C) 2019 Intel Corporation. All rights reserved.
  3. * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  4. */
  5. #pragma once
  6. #include "wasm_export.h"
  7. #include "gtest/gtest.h"
  8. #include <iostream>
  9. #include <memory>
  10. #include <fstream>
  11. #include <limits.h>
  12. #include <string>
  13. #include <unistd.h>
  14. static inline std::string
  15. get_test_binary_dir()
  16. {
  17. char cwd[PATH_MAX] = { 0 };
  18. if (!getcwd(cwd, sizeof(cwd))) {
  19. return std::string();
  20. }
  21. return std::string(cwd);
  22. }
  23. template<int Size = 512 * 1024>
  24. class WAMRRuntimeRAII
  25. {
  26. private:
  27. char global_heap_buf[Size];
  28. RuntimeInitArgs init_args;
  29. public:
  30. WAMRRuntimeRAII()
  31. {
  32. memset(&init_args, 0, sizeof(RuntimeInitArgs));
  33. init_args.mem_alloc_type = Alloc_With_Pool;
  34. init_args.mem_alloc_option.pool.heap_buf = global_heap_buf;
  35. init_args.mem_alloc_option.pool.heap_size = sizeof(global_heap_buf);
  36. wasm_runtime_full_init(&init_args);
  37. }
  38. ~WAMRRuntimeRAII() { wasm_runtime_destroy(); }
  39. };
  40. class WAMRModule
  41. {
  42. private:
  43. wasm_module_t module_;
  44. public:
  45. WAMRModule(uint8_t *buffer, uint32_t size)
  46. {
  47. module_ = wasm_runtime_load(buffer, size, NULL, 0);
  48. }
  49. ~WAMRModule() { wasm_runtime_unload(module_); }
  50. wasm_module_t get() const { return module_; }
  51. };
  52. class WAMRInstance
  53. {
  54. private:
  55. wasm_module_inst_t module_inst_;
  56. public:
  57. WAMRInstance(WAMRModule &module, uint32_t stack_size = 8192,
  58. uint32_t heap_size = 8192)
  59. {
  60. module_inst_ = wasm_runtime_instantiate(module.get(), stack_size,
  61. heap_size, NULL, 0);
  62. }
  63. ~WAMRInstance() { wasm_runtime_deinstantiate(module_inst_); }
  64. wasm_module_inst_t get() const { return module_inst_; }
  65. };
  66. class WAMRExecEnv
  67. {
  68. private:
  69. wasm_exec_env_t exec_env_;
  70. public:
  71. WAMRExecEnv(WAMRInstance &instance, uint32_t stack_size = 8192)
  72. {
  73. exec_env_ = wasm_runtime_create_exec_env(instance.get(), stack_size);
  74. }
  75. ~WAMRExecEnv() { wasm_runtime_destroy_exec_env(exec_env_); }
  76. wasm_exec_env_t get() const { return exec_env_; }
  77. wasm_module_inst_t get_inst() const
  78. {
  79. return wasm_runtime_get_module_inst(exec_env_);
  80. }
  81. };
  82. static uint8_t dummy_wasm_buffer[] = {
  83. 0x00, 0x61, 0x73, 0x6D, 0x01, 0x00, 0x00, 0x00, 0x05, 0x03, 0x01, 0x00,
  84. 0x02, 0x06, 0x08, 0x01, 0x7F, 0x01, 0x41, 0x80, 0x88, 0x04, 0x0B, 0x07,
  85. 0x0A, 0x01, 0x06, 0x6D, 0x65, 0x6D, 0x6F, 0x72, 0x79, 0x02, 0x00, 0x00,
  86. 0x19, 0x04, 0x6E, 0x61, 0x6D, 0x65, 0x07, 0x12, 0x01, 0x00, 0x0F, 0x5F,
  87. 0x5F, 0x73, 0x74, 0x61, 0x63, 0x6B, 0x5F, 0x70, 0x6F, 0x69, 0x6E, 0x74,
  88. 0x65, 0x72, 0x00, 0x76, 0x09, 0x70, 0x72, 0x6F, 0x64, 0x75, 0x63, 0x65,
  89. 0x72, 0x73, 0x01, 0x0C, 0x70, 0x72, 0x6F, 0x63, 0x65, 0x73, 0x73, 0x65,
  90. 0x64, 0x2D, 0x62, 0x79, 0x01, 0x05, 0x63, 0x6C, 0x61, 0x6E, 0x67, 0x56,
  91. 0x31, 0x33, 0x2E, 0x30, 0x2E, 0x30, 0x20, 0x28, 0x68, 0x74, 0x74, 0x70,
  92. 0x73, 0x3A, 0x2F, 0x2F, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2E, 0x63,
  93. 0x6F, 0x6D, 0x2F, 0x6C, 0x6C, 0x76, 0x6D, 0x2F, 0x6C, 0x6C, 0x76, 0x6D,
  94. 0x2D, 0x70, 0x72, 0x6F, 0x6A, 0x65, 0x63, 0x74, 0x20, 0x66, 0x64, 0x31,
  95. 0x64, 0x38, 0x63, 0x32, 0x66, 0x30, 0x34, 0x64, 0x64, 0x65, 0x32, 0x33,
  96. 0x62, 0x65, 0x65, 0x30, 0x66, 0x62, 0x33, 0x61, 0x37, 0x64, 0x30, 0x36,
  97. 0x39, 0x61, 0x39, 0x62, 0x31, 0x30, 0x34, 0x36, 0x64, 0x61, 0x39, 0x37,
  98. 0x39, 0x29
  99. };
  100. class DummyExecEnv
  101. {
  102. private:
  103. std::shared_ptr<WAMRExecEnv> dummy_exec_env_;
  104. std::shared_ptr<WAMRInstance> inst_;
  105. std::shared_ptr<WAMRModule> mod_;
  106. std::vector<uint8_t> my_wasm_buffer;
  107. private:
  108. void construct(uint8_t *buf, uint32_t len)
  109. {
  110. std::vector<uint8_t> buffer(buf, buf + len);
  111. my_wasm_buffer = buffer;
  112. mod_ = std::make_shared<WAMRModule>(my_wasm_buffer.data(),
  113. my_wasm_buffer.size());
  114. EXPECT_NE(mod_.get(), nullptr);
  115. inst_ = std::make_shared<WAMRInstance>(*mod_);
  116. EXPECT_NE(inst_.get(), nullptr);
  117. dummy_exec_env_ = std::make_shared<WAMRExecEnv>(*inst_);
  118. EXPECT_NE(dummy_exec_env_.get(), nullptr);
  119. }
  120. public:
  121. DummyExecEnv() { construct(dummy_wasm_buffer, sizeof(dummy_wasm_buffer)); }
  122. DummyExecEnv(uint8_t *buf, uint32_t len) { construct(buf, len); }
  123. DummyExecEnv(std::string filename)
  124. {
  125. std::ifstream wasm_file(filename, std::ios::binary);
  126. std::vector<uint8_t> buffer(std::istreambuf_iterator<char>(wasm_file),
  127. {});
  128. construct(buffer.data(), buffer.size());
  129. }
  130. ~DummyExecEnv() {}
  131. wasm_exec_env_t get() const { return dummy_exec_env_->get(); }
  132. void *app_to_native(uint32_t app_addr) const
  133. {
  134. return wasm_runtime_addr_app_to_native(inst_->get(), app_addr);
  135. }
  136. uint32_t native_to_app(void *ptr) const
  137. {
  138. return wasm_runtime_addr_native_to_app(inst_->get(), ptr);
  139. }
  140. const char *get_exception() const
  141. {
  142. return wasm_runtime_get_exception(inst_->get());
  143. }
  144. void set_exception(std::string str) const
  145. {
  146. wasm_runtime_set_exception(inst_->get(), str.c_str());
  147. }
  148. void clear_exception() const { wasm_runtime_clear_exception(inst_->get()); }
  149. bool execute(const char *func_name, uint32_t argc, uint32_t argv[])
  150. {
  151. wasm_function_inst_t func;
  152. if (!(func = wasm_runtime_lookup_function(inst_->get(), func_name))) {
  153. return false;
  154. }
  155. return wasm_runtime_call_wasm(dummy_exec_env_->get(), func, argc, argv);
  156. }
  157. };
  158. class WAMRVaList
  159. {
  160. private:
  161. void *buffer_;
  162. uint32_t current_loc_;
  163. uint32_t capacity_;
  164. wasm_exec_env_t exec_env_;
  165. void _append(void *ptr, uint32_t size)
  166. {
  167. if (current_loc_ + size >= capacity_) {
  168. capacity_ *= 2;
  169. buffer_ = realloc(buffer_, capacity_);
  170. ASSERT_NE(buffer_, nullptr);
  171. }
  172. memcpy((void *)((uintptr_t)buffer_ + current_loc_), ptr, size);
  173. current_loc_ += size;
  174. }
  175. public:
  176. explicit WAMRVaList(wasm_exec_env_t exec_env)
  177. : exec_env_(exec_env)
  178. {
  179. capacity_ = 64;
  180. buffer_ = malloc(capacity_);
  181. EXPECT_NE(buffer_, nullptr);
  182. current_loc_ = 0;
  183. }
  184. ~WAMRVaList()
  185. {
  186. current_loc_ = 0;
  187. free(buffer_);
  188. }
  189. template<typename T>
  190. void add(T arg)
  191. {
  192. if (std::is_floating_point<T>::value) {
  193. /* float data should be 8 bytes aligned */
  194. current_loc_ = ((current_loc_ + 7) & ~7);
  195. _append(&arg, sizeof(T));
  196. }
  197. else if (std::is_integral<T>::value) {
  198. if (sizeof(T) > 4) {
  199. current_loc_ = ((current_loc_ + 7) & ~7);
  200. }
  201. _append(&arg, sizeof(T));
  202. }
  203. }
  204. void add(std::string arg)
  205. {
  206. void *native_addr;
  207. auto inst = wasm_runtime_get_module_inst(exec_env_);
  208. uint32_t addr =
  209. wasm_runtime_module_malloc(inst, arg.size() + 1, &native_addr);
  210. ASSERT_NE(addr, 0);
  211. memcpy(native_addr, arg.data(), arg.size());
  212. *(char *)((uintptr_t)native_addr + arg.size()) = 0;
  213. _append(&addr, sizeof(uint32_t));
  214. }
  215. void add(const char *arg) { add(std::string(arg)); }
  216. char *get() const
  217. {
  218. auto inst = wasm_runtime_get_module_inst(exec_env_);
  219. uint32_t addr = wasm_runtime_module_dup_data(
  220. inst, (const char *)buffer_, current_loc_);
  221. EXPECT_NE(addr, 0);
  222. return (char *)wasm_runtime_addr_app_to_native(inst, addr);
  223. }
  224. };
  225. /* Get memory space in app */
  226. class AppMemory
  227. {
  228. private:
  229. wasm_exec_env_t exec_env_;
  230. void *native_addr_;
  231. uint32_t app_addr_;
  232. public:
  233. AppMemory(wasm_exec_env_t exec_env, uint32_t size)
  234. : exec_env_(exec_env)
  235. {
  236. app_addr_ = wasm_runtime_module_malloc(get_module_inst(exec_env_), size,
  237. &native_addr_);
  238. }
  239. ~AppMemory()
  240. {
  241. wasm_runtime_module_free(get_module_inst(exec_env_), app_addr_);
  242. }
  243. void *get_native_addr() const
  244. {
  245. return wasm_runtime_addr_app_to_native(get_module_inst(exec_env_),
  246. app_addr_);
  247. }
  248. uint32_t get_app_addr() const { return app_addr_; }
  249. };
  250. /* Put the data to app */
  251. class AppData
  252. {
  253. private:
  254. wasm_exec_env_t exec_env_;
  255. void *native_addr_;
  256. uint32_t app_addr_;
  257. public:
  258. AppData(wasm_exec_env_t exec_env, void *data, uint32_t size)
  259. : exec_env_(exec_env)
  260. {
  261. app_addr_ = wasm_runtime_module_dup_data(get_module_inst(exec_env_),
  262. (const char *)data, size);
  263. }
  264. AppData(wasm_exec_env_t exec_env, std::string str)
  265. : exec_env_(exec_env)
  266. {
  267. app_addr_ = wasm_runtime_module_dup_data(get_module_inst(exec_env_),
  268. (const char *)str.c_str(),
  269. str.size() + 1);
  270. }
  271. ~AppData()
  272. {
  273. wasm_runtime_module_free(get_module_inst(exec_env_), app_addr_);
  274. }
  275. void *get_native_addr() const
  276. {
  277. return wasm_runtime_addr_app_to_native(get_module_inst(exec_env_),
  278. app_addr_);
  279. }
  280. uint32_t get_app_addr() const { return app_addr_; }
  281. };