• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2024 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 #ifdef TEST_WASM
16 #include <fstream>
17 #include <iostream>
18 
19 #if defined(OHOS_JSVMTEST_XTS)
20 #define USE_HEADER_WASM
21 #endif
22 
23 #include "jsvmtest.h"
24 #include "securec.h"
25 #ifdef USE_HEADER_WASM
26 #include <unordered_map>
27 
28 #include "add.wasm.def"
29 #include "ammo.wasm.def"
30 #include "bfs.wasm.def"
31 #include "cJSON.wasm.def"
32 #include "global.wasm.def"
33 #include "illegal.wasm.def"
34 #include "illegal2.wasm.def"
35 #include "imports.wasm.def"
36 #include "laya.physics3D.wasm.def"
37 #include "math.wasm.def"
38 #include "memory.wasm.def"
39 #include "newton.wasm.def"
40 #include "reloc_info.wasm.def"
41 #include "simple.wasm.def"
42 #include "table.wasm.def"
43 #include "table2.wasm.def"
44 #endif
45 
46 #if defined(USE_HEADER_WASM)
47 static const std::string wasmPath = "";
48 
49 using WasmMap = std::unordered_map<std::string, std::pair<unsigned char *, unsigned int>>;
InitWasmMap()50 const WasmMap &InitWasmMap()
51 {
52     static WasmMap wasmMap{};
53     if (wasmMap.size() == 0) {
54         wasmMap["add.wasm"] = std::pair<unsigned char *, unsigned int>(add_wasm, add_wasm_len);
55         wasmMap["ammo.wasm.wasm"] = std::pair<unsigned char *, unsigned int>(ammo_wasm_wasm, ammo_wasm_wasm_len);
56         wasmMap["bfs.wasm"] = std::pair<unsigned char *, unsigned int>(bfs_wasm, bfs_wasm_len);
57         wasmMap["cJSON.wasm"] = std::pair<unsigned char *, unsigned int>(cJSON_wasm, cJSON_wasm_len);
58         wasmMap["global.wasm"] = std::pair<unsigned char *, unsigned int>(global_wasm, global_wasm_len);
59         wasmMap["illegal2.wasm"] = std::pair<unsigned char *, unsigned int>(illegal2_wasm, illegal2_wasm_len);
60         wasmMap["illegal.wasm"] = std::pair<unsigned char *, unsigned int>(illegal_wasm, illegal_wasm_len);
61         wasmMap["imports.wasm"] = std::pair<unsigned char *, unsigned int>(imports_wasm, imports_wasm_len);
62         wasmMap["laya.physics3D.wasm.wasm"] =
63             std::pair<unsigned char *, unsigned int>(laya_physics3D_wasm_wasm, laya_physics3D_wasm_wasm_len);
64         wasmMap["math.wasm"] = std::pair<unsigned char *, unsigned int>(math_wasm, math_wasm_len);
65         wasmMap["memory.wasm"] = std::pair<unsigned char *, unsigned int>(memory_wasm, memory_wasm_len);
66         wasmMap["newton.wasm"] = std::pair<unsigned char *, unsigned int>(newton_wasm, newton_wasm_len);
67         wasmMap["reloc_info.wasm"] = std::pair<unsigned char *, unsigned int>(reloc_info_wasm, reloc_info_wasm_len);
68         wasmMap["simple.wasm"] = std::pair<unsigned char *, unsigned int>(simple_wasm, simple_wasm_len);
69         wasmMap["table2.wasm"] = std::pair<unsigned char *, unsigned int>(table2_wasm, table2_wasm_len);
70         wasmMap["table.wasm"] = std::pair<unsigned char *, unsigned int>(table_wasm, table_wasm_len);
71     }
72     return wasmMap;
73 }
74 
75 #elif defined(OHOS_JSVM_HAP)
76 static const std::string wasmPath = "/data/storage/el1/base/wasm/";
77 #else
78 static const std::string wasmPath = "./unittests/wasm/";
79 #endif
80 
GetInstanceExports(JSVM_Value wasmInstance)81 static JSVM_Value GetInstanceExports(JSVM_Value wasmInstance)
82 {
83     CHECK(jsvm::IsWebAssemblyInstance(wasmInstance));
84     auto exports = jsvm::GetProperty(wasmInstance, "exports");
85     CHECK(jsvm::IsObject(exports));
86     return exports;
87 }
88 
ReadBinaryFile(const char * path,std::vector<uint8_t> & buffer)89 static void ReadBinaryFile(const char *path, std::vector<uint8_t> &buffer)
90 {
91 #if !defined(USE_HEADER_WASM)
92     std::ifstream infile(path, std::ifstream::binary);
93     CHECK_FATAL(infile.good(), "can not access file: %s\n", path);
94     infile.seekg(0, std::ifstream::end);
95     size_t size = infile.tellg();
96     infile.seekg(0);
97     buffer.resize(size);
98     infile.read(reinterpret_cast<char *>(&buffer[0]), size);
99     infile.close();
100 #else
101     const auto &wasmMap = InitWasmMap();
102     auto it = wasmMap.find(path);
103     if (it == wasmMap.end()) {
104         CHECK_FATAL(false, "can not find file: %s", path);
105     }
106     auto p = it->second;
107     std::vector<uint8_t> newBuffer((uint8_t *)p.first, p.first + p.second);
108     buffer.swap(newBuffer);
109 #endif
110 }
111 
ReadBinaryFile(const std::string & path,std::vector<uint8_t> & buffer)112 static void ReadBinaryFile(const std::string &path, std::vector<uint8_t> &buffer)
113 {
114     ReadBinaryFile(path.c_str(), buffer);
115 }
116 
WriteBinaryFile(const char * path,const uint8_t * data,size_t byteLength)117 static void WriteBinaryFile(const char *path, const uint8_t *data, size_t byteLength)
118 {
119     std::ofstream outfile(path, std::ofstream::binary);
120     outfile.write(reinterpret_cast<const char *>(data), byteLength);
121 }
122 
ReadTextFile(const char * path,std::string & content)123 static void ReadTextFile(const char *path, std::string &content)
124 {
125     std::ifstream infile(path);
126     CHECK_FATAL(infile.good(), "can not access file: %s\n", path);
127     std::ostringstream oss;
128     oss << infile.rdbuf();
129     content = oss.str();
130 }
131 
ReadTextFile(const std::string & path,std::string & content)132 [[maybe_unused]] static void ReadTextFile(const std::string &path, std::string &content)
133 {
134     ReadTextFile(path.c_str(), content);
135 }
136 
CompileWasmModule(const char * path)137 static JSVM_Value CompileWasmModule(const char *path)
138 {
139     std::vector<uint8_t> buffer;
140     ReadBinaryFile(path, buffer);
141     CHECK(buffer.size() > 0);
142     JSVM_Value wasmModule;
143     JSVMTEST_CALL(OH_JSVM_CompileWasmModule(jsvm_env, buffer.data(), buffer.size(), NULL, 0, NULL, &wasmModule));
144     CHECK(jsvm::IsWasmModuleObject(wasmModule));
145     return wasmModule;
146 }
147 
CompileWasmModule(const std::string & path)148 static JSVM_Value CompileWasmModule(const std::string &path)
149 {
150     return CompileWasmModule(path.c_str());
151 }
152 
InstantiateWasmModule(JSVM_Value wasmModule,JSVM_Value importedObject)153 static JSVM_Value InstantiateWasmModule(JSVM_Value wasmModule, JSVM_Value importedObject)
154 {
155     auto globalThis = jsvm::Global();
156     auto WebAssembly = jsvm::GetProperty(globalThis, "WebAssembly");
157     CHECK(jsvm::IsObject(WebAssembly));
158     auto WebAssemblyInstance = jsvm::GetProperty(WebAssembly, "Instance");
159     CHECK(jsvm::IsFunction(WebAssemblyInstance));
160     JSVM_Value wasmInstance;
161     JSVM_Value argv[] = {wasmModule, importedObject};
162     constexpr size_t argc = 2;
163     JSVMTEST_CALL(OH_JSVM_NewInstance(jsvm_env, WebAssemblyInstance, argc, argv, &wasmInstance));
164     CHECK(jsvm::IsWebAssemblyInstance(wasmInstance));
165     return wasmInstance;
166 }
167 
168 // [begin, end)
BatchCompileWasmFunctions(JSVM_Value wasmModule,size_t begin,size_t end)169 static void BatchCompileWasmFunctions(JSVM_Value wasmModule, size_t begin, size_t end)
170 {
171     CHECK(jsvm::IsWasmModuleObject(wasmModule));
172     for (size_t i = begin; i < end; ++i) {
173         JSVM_WasmOptLevel level = (i % 2 == 0 ? JSVM_WASM_OPT_BASELINE : JSVM_WASM_OPT_HIGH);
174         JSVMTEST_CALL(OH_JSVM_CompileWasmFunction(jsvm_env, wasmModule, i, level));
175     }
176 }
177 
178 // 验证 wasm instance 功能 (add 模块)
VerifyAddWasmInstance(JSVM_Value instance)179 static void VerifyAddWasmInstance(JSVM_Value instance)
180 {
181     CHECK(jsvm::IsWebAssemblyInstance(instance));
182     // 实例化之后,就能使用 WebAssembly module 定义的函数了
183     auto exports = jsvm::GetProperty(instance, jsvm::Str("exports"));
184     CHECK(jsvm::IsObject(exports));
185     auto add = jsvm::GetProperty(exports, jsvm::Str("add"));
186     CHECK(jsvm::IsFunction(add));
187     auto result = jsvm::Call(add, jsvm::Undefined(), {jsvm::Run("1"), jsvm::Run("2")});
188     CHECK(jsvm::IsNumber(result));
189     constexpr int kExpectedResult = 3;
190     CHECK(jsvm::ToNumber(result) == kExpectedResult);
191 }
192 
WebAssemblyDemo()193 static void WebAssemblyDemo()
194 {
195     std::string path = wasmPath + "add.wasm";
196     std::vector<uint8_t> buffer;
197     // 从文件中读取 wasm 字节码
198     ReadBinaryFile(path, buffer);
199     JSVM_Status status = JSVM_OK;
200 
201     JSVM_Value wasmModule;
202     // 将 wasm 字节码编译为 WebAssembly module
203     status = OH_JSVM_CompileWasmModule(jsvm_env, buffer.data(), buffer.size(), NULL, 0, NULL, &wasmModule);
204     CHECK(status == JSVM_OK);
205 
206     bool isWasmModule;
207     // 检查编译结果确实是一个 WebAssembly module
208     status = OH_JSVM_IsWasmModuleObject(jsvm_env, wasmModule, &isWasmModule);
209     CHECK(status == JSVM_OK);
210     CHECK(isWasmModule);
211 
212     // 对 WebAssembly module 指定编号的函数进行 high optimization level 优化
213     status = OH_JSVM_CompileWasmFunction(jsvm_env, wasmModule, 0, JSVM_WASM_OPT_HIGH);
214     CHECK(status == JSVM_OK);
215 
216     // 实例化 WebAssembly module
217     auto instance = InstantiateWasmModule(wasmModule, jsvm::Run("{}"));
218     VerifyAddWasmInstance(instance);
219 
220     // 对编译后的 WebAssembly moudle 进行序列化,创建 wasm cache
221     const uint8_t *cacheData = NULL;
222     size_t cacheLength = 0;
223     status = OH_JSVM_CreateWasmCache(jsvm_env, wasmModule, &cacheData, &cacheLength);
224     CHECK(status == JSVM_OK);
225     CHECK(cacheData != NULL);
226     CHECK(cacheLength > 0);
227 
228     // 对序列化得到的 cache data 进行持久化存储
229     const std::string wasmCachePath = path + ".cache";
230     WriteBinaryFile(wasmCachePath.c_str(), cacheData, cacheLength);
231     status = OH_JSVM_ReleaseCache(jsvm_env, cacheData, JSVM_CACHE_TYPE_WASM);
232     CHECK(status == JSVM_OK);
233 
234     // 下次使用时,直接使用 wasm cache 反序列化得到 WebAssembly module,避免编译开销
235     std::vector<uint8_t> cacheBuffer;
236     ReadBinaryFile(wasmCachePath, cacheBuffer);
237     CHECK(cacheBuffer.size() == cacheLength);
238 
239     bool cacheRejected;
240     JSVM_Value wasmModuleSerialized;
241     status = OH_JSVM_CompileWasmModule(jsvm_env, buffer.data(), buffer.size(), cacheBuffer.data(), cacheBuffer.size(),
242                                        &cacheRejected, &wasmModuleSerialized);
243     CHECK(status == JSVM_OK);
244 
245     CHECK(cacheRejected == false);
246     status = OH_JSVM_IsWasmModuleObject(jsvm_env, wasmModuleSerialized, &isWasmModule);
247     CHECK(status == JSVM_OK);
248     CHECK(isWasmModule);
249 
250     // 测试反序列化而来的 WebAssembly module 的功能
251     // 实例化 WebAssembly module
252     auto instance2 = InstantiateWasmModule(wasmModuleSerialized, jsvm::Run("var x = {}; x"));
253     VerifyAddWasmInstance(instance2);
254 }
255 
256 #if !defined(JSVM_JITLESS)
257 // test for Wasm Is Wasm Module Object
TEST(Wasm_IsWasmModuleObject)258 TEST(Wasm_IsWasmModuleObject)
259 {
260     auto number = jsvm::Run("42");
261     CHECK(!jsvm::IsWasmModuleObject(number));
262     CHECK(!jsvm::IsWasmModuleObject(jsvm::Undefined()));
263     CHECK(!jsvm::IsWasmModuleObject(jsvm::Null()));
264     CHECK(!jsvm::IsWasmModuleObject(jsvm::Str("hello")));
265 }
266 
267 #ifdef OHOS_JSVMTEST_XTS
TEST_DISABLE(Wasm_WebAssemblyDemo)268 TEST_DISABLE(Wasm_WebAssemblyDemo)
269 {
270 #else
271 TEST(Wasm_WebAssemblyDemo)
272 {
273 #endif
274     WebAssemblyDemo();
275 }
276 
277 // test for Wasm Compile Wasm Module
278 TEST(Wasm_CompileWasmModule)
279 {
280     JSVM_Value wasmModule = CompileWasmModule(wasmPath + "add.wasm");
281     JSVM_Value wasmInstance = InstantiateWasmModule(wasmModule, jsvm::Run("{}"));
282     JSVM_Value exports = jsvm::GetProperty(wasmInstance, jsvm::Str("exports"));
283     CHECK(jsvm::IsObject(exports));
284     JSVM_Value addFunc = jsvm::GetProperty(exports, jsvm::Str("add"));
285     CHECK(jsvm::IsFunction(addFunc));
286     JSVM_Value one = jsvm::Run("1");
287     JSVM_Value two = jsvm::Run("2");
288     JSVM_Value result = jsvm::Call(addFunc, jsvm::Undefined(), {one, two});
289     CHECK(jsvm::ToNumber(result) == 3);
290 
291     JSVMTEST_CALL(OH_JSVM_CompileWasmFunction(env, wasmModule, 0, JSVM_WASM_OPT_HIGH));
292 
293     const uint8_t *cacheData = nullptr;
294     size_t cacheSize = 0;
295     JSVMTEST_CALL(OH_JSVM_CreateWasmCache(env, wasmModule, &cacheData, &cacheSize));
296     CHECK(cacheData != nullptr);
297     CHECK(cacheSize > 0);
298 }
299 
300 [[maybe_unused]] static void RandomDeserialize(JSVM_Env env, const std::string &filename)
301 {
302     std::string wasmFile = wasmPath + filename;
303     std::string cacheFile = wasmPath + filename + ".test.cache";
304     std::ifstream infile(cacheFile);
305     if (!infile.good()) {
306         // CreateCodeCache
307         auto wasmModule = CompileWasmModule(wasmFile);
308         InstantiateWasmModule(wasmModule, jsvm::Undefined());
309         JSVMTEST_CALL(OH_JSVM_CompileWasmFunction(env, wasmModule, 0, JSVM_WASM_OPT_HIGH));
310         const uint8_t *data = NULL;
311         size_t length = 0;
312         JSVMTEST_CALL(OH_JSVM_CreateWasmCache(env, wasmModule, &data, &length));
313         CHECK(data != NULL);
314         CHECK(length > 0);
315         WriteBinaryFile(cacheFile.c_str(), data, length);
316         JSVMTEST_CALL(OH_JSVM_ReleaseCache(env, data, JSVM_CACHE_TYPE_WASM));
317     } else {
318         std::vector<uint8_t> buffer;
319         ReadBinaryFile(wasmFile, buffer);
320         std::vector<uint8_t> cache;
321         ReadBinaryFile(cacheFile, cache);
322         JSVM_Value wasmModule;
323         bool cacheRejected;
324         JSVMTEST_CALL(OH_JSVM_CompileWasmModule(env, buffer.data(), buffer.size(), cache.data(), cache.size(),
325                                                 &cacheRejected, &wasmModule));
326         CHECK(cacheRejected == false);
327         CHECK(jsvm::IsWasmModuleObject(wasmModule));
328         // 运行一定次数后,删除缓存
329         constexpr int kPeriodToRemoveCache = 3;
330         static int cnt = 0;
331         if (++cnt % kPeriodToRemoveCache == 0) {
332             int result = remove(cacheFile.c_str());
333             CHECK(result == 0);
334         }
335     }
336 }
337 
338 // test for Wasm Random Cache Test
339 #ifdef OHOS_JSVMTEST_XTS
340 TEST_DISABLE(Wasm_RandomCacheTest)
341 {
342 #else
343 TEST(Wasm_RandomCacheTest)
344 {
345 #endif
346     static std::vector<std::string> allFiles = {
347         "add.wasm",
348         "bfs.wasm",
349         "cJSON.wasm",
350         "math.wasm",
351     };
352     for (const std::string &filename : allFiles) {
353         for (int i = 0; i < 100; ++i) {
354             RandomDeserialize(env, filename);
355         }
356     }
357 }
358 
359 // test for Wasm Compile Wasm Function Baseline
360 TEST(Wasm_CompileWasmFunctionBaseline)
361 {
362     auto wasmModule = CompileWasmModule(wasmPath + "add.wasm");
363     InstantiateWasmModule(wasmModule, jsvm::Undefined());
364     JSVMTEST_CALL(OH_JSVM_CompileWasmFunction(env, wasmModule, 0, JSVM_WASM_OPT_BASELINE));
365     JSVMTEST_CALL(OH_JSVM_CompileWasmFunction(env, wasmModule, 0, JSVM_WASM_OPT_HIGH));
366     auto status = OH_JSVM_CompileWasmFunction(env, wasmModule, 1, JSVM_WASM_OPT_HIGH);
367     CHECK(status != JSVM_OK);
368 }
369 
370 // test for Wasm Compile Illegal Wasm Module
371 TEST(Wasm_CompileIllegalWasmModule)
372 {
373     std::vector<uint8_t> buffer;
374     std::vector<std::string> pathVec = {
375         wasmPath + "illegal.wasm",
376         wasmPath + "illegal2.wasm",
377     };
378     for (const std::string &path : pathVec) {
379         ReadBinaryFile(path, buffer);
380         CHECK(buffer.size() > 0);
381         JSVM_Value wasmModule;
382         JSVM_Status status =
383             OH_JSVM_CompileWasmModule(jsvm_env, buffer.data(), buffer.size(), NULL, 0, NULL, &wasmModule);
384         CHECK(status == JSVM_PENDING_EXCEPTION);
385     }
386 }
387 
388 // Test import global
389 static void TestImportGlobal(JSVM_Env env, JSVM_Value exports)
390 {
391     JSVM_Value testFunc;
392     JSVM_Value result;
393     testFunc = jsvm::GetProperty(exports, jsvm::Str("test_global_i32"));
394     result = jsvm::Call(testFunc, jsvm::Undefined(), {});
395     CHECK(jsvm::Equals(result, jsvm::Run("100")));
396 
397     testFunc = jsvm::GetProperty(exports, jsvm::Str("test_global_i64"));
398     result = jsvm::Call(testFunc, jsvm::Undefined(), {});
399     CHECK(jsvm::Equals(result, jsvm::Run("1000000000000000n")));
400 
401     testFunc = jsvm::GetProperty(exports, jsvm::Str("test_global_f32"));
402     result = jsvm::Call(testFunc, jsvm::Undefined(), {});
403 
404     JSVM_ValueType type;
405     OH_JSVM_Typeof(env, result, &type);
406     CHECK(jsvm::Equals(result, jsvm::Run("new Float32Array([1.3])[0]")));
407 
408     testFunc = jsvm::GetProperty(exports, jsvm::Str("test_global_f64"));
409     result = jsvm::Call(testFunc, jsvm::Undefined(), {});
410     CHECK(jsvm::Equals(result, jsvm::Run("2.7")));
411 }
412 
413 // Test import func
414 static void TestImportFunc(JSVM_Env env, JSVM_Value exports)
415 {
416     (void)env;
417     JSVM_Value testFunc;
418     JSVM_Value result;
419     testFunc = jsvm::GetProperty(exports, jsvm::Str("test_sub"));
420     result = jsvm::Call(testFunc, jsvm::Undefined(), {jsvm::Run("1"), jsvm::Run("2")});
421     CHECK(jsvm::Equals(result, jsvm::Run("-1")));
422 }
423 
424 // Test import memory
425 static void TestImportMemory(JSVM_Env env, JSVM_Value exports)
426 {
427     JSVM_Value testFunc;
428     JSVM_Value result;
429     JSVM_Status status = JSVM_OK;
430     JSVM_Value exception;
431     testFunc = jsvm::GetProperty(exports, jsvm::Str("test_memory"));
432     result = jsvm::Call(testFunc, jsvm::Undefined(), {jsvm::Run("0")});
433     CHECK(jsvm::Equals(result, jsvm::Run("0")));
434 
435     testFunc = jsvm::GetProperty(exports, jsvm::Str("test_memory"));
436     result = jsvm::Call(testFunc, jsvm::Undefined(), {jsvm::Run("10")});
437     CHECK(jsvm::Equals(result, jsvm::Run("16")));
438 
439     testFunc = jsvm::GetProperty(exports, jsvm::Str("test_memory"));
440     result = jsvm::Call(testFunc, jsvm::Undefined(), {jsvm::Run("8")});
441     CHECK(jsvm::Equals(result, jsvm::Run("1048576")));
442 
443     testFunc = jsvm::GetProperty(exports, jsvm::Str("test_memory"));
444     JSVM_Value argv[1] = {jsvm::Run("1000000")};
445     status = OH_JSVM_CallFunction(jsvm_env, jsvm::Undefined(), testFunc, 1, argv, &result);
446     CHECK(status == JSVM_PENDING_EXCEPTION);
447     status = OH_JSVM_GetAndClearLastException(env, &exception);
448 }
449 
450 // Test import table
451 static void TestImportTable(JSVM_Env env, JSVM_Value exports)
452 {
453     JSVM_Value testFunc;
454     JSVM_Value result;
455     JSVM_Status status = JSVM_OK;
456     JSVM_Value exception;
457     {
458         testFunc = jsvm::GetProperty(exports, jsvm::Str("test_table"));
459         JSVM_Value argv[1] = {jsvm::Run("0")};
460         status = OH_JSVM_CallFunction(jsvm_env, jsvm::Undefined(), testFunc, 1, argv, &result);
461         CHECK(status == JSVM_PENDING_EXCEPTION);
462         OH_JSVM_GetAndClearLastException(env, &exception);
463     }
464 
465     testFunc = jsvm::GetProperty(exports, jsvm::Str("test_table"));
466     result = jsvm::Call(testFunc, jsvm::Undefined(), {jsvm::Run("1")});
467     CHECK(jsvm::Equals(result, jsvm::Run("11")));
468 
469     testFunc = jsvm::GetProperty(exports, jsvm::Str("test_table"));
470     result = jsvm::Call(testFunc, jsvm::Undefined(), {jsvm::Run("2")});
471     CHECK(jsvm::Equals(result, jsvm::Run("22")));
472 
473     {
474         testFunc = jsvm::GetProperty(exports, jsvm::Str("test_table"));
475         JSVM_Value argv[1] = {jsvm::Run("3")};
476         status = OH_JSVM_CallFunction(jsvm_env, jsvm::Undefined(), testFunc, 1, argv, &result);
477         CHECK(status == JSVM_PENDING_EXCEPTION);
478         OH_JSVM_GetAndClearLastException(env, &exception);
479     }
480 
481     {
482         testFunc = jsvm::GetProperty(exports, jsvm::Str("test_table"));
483         JSVM_Value argv[1] = {jsvm::Run("100")};
484         status = OH_JSVM_CallFunction(jsvm_env, jsvm::Undefined(), testFunc, 1, argv, &result);
485         CHECK(status == JSVM_PENDING_EXCEPTION);
486         OH_JSVM_GetAndClearLastException(env, &exception);
487     }
488 }
489 
490 // test for Wasm Compile Wasm Module With Imports
491 TEST(Wasm_CompileWasmModuleWithImports)
492 {
493     JSVM_Value wasmModule = CompileWasmModule(wasmPath + "imports.wasm");
494     const char *importJs = R"JS(
495         var x = {
496             test: {
497                 global_i32: 100,
498                 global_i64: 1000000000000000n,
499                 global_f32: 1.3,
500                 global_f64: 2.7,
501                 sub: (a, b) => { return a - b; },
502                 memory: new WebAssembly.Memory({initial: 1, maximum: 2}),
503                 table: new WebAssembly.Table({initial: 10, maximum: 20, element: 'anyfunc'}),
504             }
505         };
506         x
507     )JS";
508 
509     JSVM_Value importedObj = jsvm::Run(importJs);
510 
511     CHECK(jsvm::IsObject(importedObj));
512     JSVM_Value wasmInstance = InstantiateWasmModule(wasmModule, importedObj);
513     JSVM_Value exports = jsvm::GetProperty(wasmInstance, jsvm::Str("exports"));
514     CHECK(jsvm::IsObject(exports));
515 
516     TestImportGlobal(env, exports);
517     TestImportFunc(env, exports);
518     TestImportMemory(env, exports);
519     TestImportTable(env, exports);
520 }
521 
522 static void CompileWasmFunctions(JSVM_Env env, JSVM_Value wasmModule,
523                                  const std::initializer_list<uint32_t> &funcIndexList, JSVM_WasmOptLevel optLevel)
524 {
525     for (uint32_t funcIndex : funcIndexList) {
526         JSVM_Status status = OH_JSVM_CompileWasmFunction(jsvm_env, wasmModule, funcIndex, optLevel);
527         CHECK(status == JSVM_OK);
528     }
529 }
530 
531 static JSVM_Value TestCacheAndRelocInfoStep1(JSVM_Env env, const std::vector<uint8_t> &buffer,
532                                              const uint8_t *&cacheData, size_t &cacheSize)
533 {
534     JSVM_Value wasmModule;
535     JSVMTEST_CALL(OH_JSVM_CompileWasmModule(jsvm_env, buffer.data(), buffer.size(), NULL, 0, NULL, &wasmModule));
536     CHECK(jsvm::IsWasmModuleObject(wasmModule));
537 
538     JSVM_Value wasmInstance =
539         InstantiateWasmModule(wasmModule, jsvm::Run("var x = { test: {func: () => { return 1; }}}; x"));
540     JSVM_Value exports = jsvm::GetProperty(wasmInstance, jsvm::Str("exports"));
541     CHECK(jsvm::IsObject(exports));
542 
543     CompileWasmFunctions(env, wasmModule, {1, 2}, JSVM_WASM_OPT_HIGH);
544 
545     JSVM_Value testFunc;
546     JSVM_Value result;
547     {
548         testFunc = jsvm::GetProperty(exports, jsvm::Str("test_wasm_call_reloc_info"));
549         CHECK(jsvm::IsFunction(testFunc));
550         result = jsvm::Call(testFunc, jsvm::Undefined(), {});
551         CHECK(jsvm::Equals(result, jsvm::Run("1")));
552 
553         testFunc = jsvm::GetProperty(exports, jsvm::Str("test_wasm_stub_call_reloc_info"));
554         CHECK(jsvm::IsFunction(testFunc));
555         result = jsvm::Call(testFunc, jsvm::Undefined(), {});
556         CHECK(jsvm::Equals(result, jsvm::Run("1")));
557     }
558     JSVMTEST_CALL(OH_JSVM_CreateWasmCache(env, wasmModule, &cacheData, &cacheSize));
559     CHECK(cacheData != nullptr);
560     CHECK(cacheSize > 0);
561     return exports;
562 }
563 
564 static void TestCacheAndRelocInfoStep2(JSVM_Env env, const std::vector<uint8_t> &buffer, const uint8_t *cacheData,
565                                        size_t cacheSize, JSVM_Value exports)
566 {
567     bool cacheRejected;
568     JSVM_Value wasmModule;
569     JSVM_Status status = OH_JSVM_CompileWasmModule(jsvm_env, buffer.data(), buffer.size(), cacheData, cacheSize,
570                                                    &cacheRejected, &wasmModule);
571     CHECK(status == JSVM_OK);
572     CHECK(cacheRejected == false);
573 
574     JSVM_Value wasmInstance =
575         InstantiateWasmModule(wasmModule, jsvm::Run("var x = { test: {func: () => { return 2; }}}; x"));
576 
577     JSVM_Value newExports = jsvm::GetProperty(wasmInstance, jsvm::Str("exports"));
578     JSVM_Value testFunc;
579     JSVM_Value result;
580 
581     {
582         testFunc = jsvm::GetProperty(newExports, jsvm::Str("test_wasm_call_reloc_info"));
583         CHECK(jsvm::IsFunction(testFunc));
584         result = jsvm::Call(testFunc, jsvm::Undefined(), {});
585         CHECK(jsvm::Equals(result, jsvm::Run("1")));
586 
587         testFunc = jsvm::GetProperty(newExports, jsvm::Str("test_wasm_stub_call_reloc_info"));
588         CHECK(jsvm::IsFunction(testFunc));
589         result = jsvm::Call(testFunc, jsvm::Undefined(), {});
590         CHECK(jsvm::Equals(result, jsvm::Run("1")));
591     }
592 
593     testFunc = jsvm::GetProperty(exports, jsvm::Str("call_import"));
594     CHECK(jsvm::IsFunction(testFunc));
595     result = jsvm::Call(testFunc, jsvm::Undefined(), {});
596     CHECK(jsvm::Equals(result, jsvm::Run("1")));
597 
598     testFunc = jsvm::GetProperty(newExports, jsvm::Str("call_import"));
599     CHECK(jsvm::IsFunction(testFunc));
600     result = jsvm::Call(testFunc, jsvm::Undefined(), {});
601     CHECK(jsvm::Equals(result, jsvm::Run("2")));
602 
603     CompileWasmFunctions(env, wasmModule, {1, 2}, JSVM_WASM_OPT_HIGH);
604     CompileWasmFunctions(env, wasmModule, {1, 2}, JSVM_WASM_OPT_HIGH);
605 
606     status = OH_JSVM_ReleaseCache(jsvm_env, cacheData, JSVM_CACHE_TYPE_WASM);
607     CHECK(status == JSVM_OK);
608 }
609 
610 // test for Wasm Compile Wasm Module With Cache And Reloc Info
611 TEST(Wasm_CompileWasmModuleWithCacheAndRelocInfo)
612 {
613     std::vector<uint8_t> buffer;
614     ReadBinaryFile(wasmPath + "reloc_info.wasm", buffer);
615     CHECK(buffer.size() > 0);
616 
617     const uint8_t *cacheData = NULL;
618     size_t cacheSize = 0;
619     JSVM_Value exports = TestCacheAndRelocInfoStep1(env, buffer, cacheData, cacheSize);
620     TestCacheAndRelocInfoStep2(env, buffer, cacheData, cacheSize, exports);
621 }
622 
623 // test for Wasm Multiple Instances
624 TEST(Wasm_MultipleInstances)
625 {
626     auto wasmModule = CompileWasmModule(wasmPath + "add.wasm");
627     {
628         auto obj = jsvm::Run("var x = { foo : 'bar' }; x");
629         CHECK(jsvm::IsObject(obj));
630         auto instance = InstantiateWasmModule(wasmModule, obj);
631         CHECK(jsvm::IsWebAssemblyInstance(instance));
632     }
633     {
634         auto obj = jsvm::Run("var x = { a : 1 }; x");
635         CHECK(jsvm::IsObject(obj));
636         auto instance = InstantiateWasmModule(wasmModule, obj);
637         CHECK(jsvm::IsWebAssemblyInstance(instance));
638     }
639     {
640         auto obj = jsvm::Run("var x = { b : 2 }; x");
641         CHECK(jsvm::IsObject(obj));
642         auto instance = InstantiateWasmModule(wasmModule, obj);
643         CHECK(jsvm::IsWebAssemblyInstance(instance));
644     }
645 }
646 
647 static std::string fakelog = "";
648 
649 static JSVM_Value FakeConsoleLog(JSVM_Env env, JSVM_CallbackInfo info)
650 {
651     size_t argc = 1;
652     JSVM_Value argv[1];
653     JSVMTEST_CALL(OH_JSVM_GetCbInfo(env, info, &argc, argv, NULL, NULL));
654     JSVM_Value x = argv[0];
655     fakelog = jsvm::ToString(x);
656     return jsvm::Undefined();
657 }
658 
659 static void InstallFakeConsoleLog(JSVM_Env env)
660 {
661     static JSVM_CallbackStruct cb = {FakeConsoleLog, NULL};
662     JSVM_Value log;
663     JSVMTEST_CALL(OH_JSVM_CreateFunction(env, "log", JSVM_AUTO_LENGTH, &cb, &log));
664     CHECK(jsvm::IsFunction(log));
665     auto console = jsvm::Global("console");
666     if (!jsvm::IsObject(console)) {
667         JSVMTEST_CALL(OH_JSVM_CreateObject(env, &console));
668         jsvm::SetProperty(jsvm::Global(), "console", console);
669     }
670     jsvm::SetProperty(console, "log", log);
671 }
672 
673 // test for Wasm MDN index
674 TEST(Wasm_MDN_index)
675 {
676     fakelog = "";
677     InstallFakeConsoleLog(env);
678     auto wasmModule = CompileWasmModule(wasmPath + "simple.wasm");
679     auto importObj = jsvm::Run(R"JS(
680         var importObject = {
681             my_namespace: {
682                 imported_func: arg => {
683                     console.log(arg);
684                 }
685             }
686         };
687         importObject;
688      )JS");
689     CHECK(jsvm::IsObject(importObj));
690     auto instance = InstantiateWasmModule(wasmModule, importObj);
691     auto exports = jsvm::GetProperty(instance, jsvm::Str("exports"));
692     auto exported_func = jsvm::GetProperty(exports, jsvm::Str("exported_func"));
693     CHECK(fakelog == "");
694     jsvm::Call(exported_func);  // expected console.log 42
695     CHECK(fakelog == "42");
696 }
697 
698 // test for Wasm MDN imports
699 TEST(Wasm_MDN_imports)
700 {
701     auto wasmModule = CompileWasmModule(wasmPath + "simple.wasm");
702     auto WebAssembly = jsvm::GetProperty(jsvm::Global(), jsvm::Str("WebAssembly"));
703     auto Module = jsvm::GetProperty(WebAssembly, jsvm::Str("Module"));
704     auto ModuleImports = jsvm::GetProperty(Module, jsvm::Str("imports"));
705     CHECK(jsvm::IsFunction(ModuleImports));
706     auto imports = jsvm::Call(ModuleImports, Module, {wasmModule});
707     CHECK(jsvm::IsArray(imports));
708     JSVM_Value element;
709     JSVMTEST_CALL(OH_JSVM_GetElement(env, imports, 0, &element));
710     CHECK(jsvm::IsObject(element));
711 }
712 
713 // test for Wasm MDN validate
714 TEST(Wasm_MDN_validate)
715 {
716     std::vector<uint8_t> buffer;
717     ReadBinaryFile(wasmPath + "simple.wasm", buffer);
718     CHECK(buffer.size() > 0);
719     void *backingStoreData = NULL;
720     JSVM_Value arraybuffer;
721     JSVMTEST_CALL(OH_JSVM_CreateArraybuffer(env, buffer.size(), &backingStoreData, &arraybuffer));
722     memcpy_s(backingStoreData, buffer.size(), buffer.data(), buffer.size());
723     CHECK(jsvm::IsArraybuffer(arraybuffer));
724 
725     auto WebAssembly = jsvm::Global("WebAssembly");
726     auto validate = jsvm::GetProperty(WebAssembly, "validate");
727     auto isValid = jsvm::Call(validate, WebAssembly, {arraybuffer});
728     CHECK(jsvm::IsBoolean(isValid));
729     CHECK(jsvm::StrictEquals(isValid, jsvm::True()));
730 }
731 
732 // test for Wasm MDN memory
733 TEST(Wasm_MDN_memory)
734 {
735     (void)jsvm::Run(R"JS(
736         var memory = new WebAssembly.Memory({
737             initial: 10,
738             maximum: 100,
739         });
740         memory
741     )JS");
742     auto x = jsvm::GetProperty(jsvm::Global(), jsvm::Str("memory"));
743     CHECK(jsvm::IsObject(x));
744     auto importObject = jsvm::Run(R"JS(
745         var importObject = {
746             js: {
747                 mem: memory
748             }
749         };
750         importObject
751     )JS");
752     auto wasmModule = CompileWasmModule(wasmPath + "memory.wasm");
753     auto instance = InstantiateWasmModule(wasmModule, importObject);
754 
755     jsvm::Run(R"JS(
756         var summands = new DataView(memory.buffer);
757         for (var i = 0; i < 10; ++i) {
758             summands.setUint32(i * 4, i, true);  // WebAssembly is little endian
759         }
760     )JS");
761 
762     auto exports = GetInstanceExports(instance);
763     auto accumulate = jsvm::GetProperty(exports, jsvm::Str("accumulate"));
764     CHECK(jsvm::IsFunction(accumulate));
765     auto result = jsvm::Call(accumulate, exports, {jsvm::Int32(0), jsvm::Int32(10)});
766     CHECK(jsvm::IsNumber(result));
767     CHECK(jsvm::ToNumber(result) == 45);
768 }
769 
770 // test for Wasm MDN table
771 TEST(Wasm_MDN_table)
772 {
773     auto table = jsvm::Run(R"JS(
774         var table = new WebAssembly.Table({
775             element: "anyfunc",
776             initial: 1,
777             maximum: 10
778         });
779         table.grow(1);
780         table;
781     )JS");
782     CHECK(jsvm::IsWebAssemblyTable(table));
783     auto wasmModule = CompileWasmModule(wasmPath + "table.wasm");
784     auto instance = InstantiateWasmModule(wasmModule, jsvm::Undefined());
785     auto exports = GetInstanceExports(instance);
786     auto tbl = jsvm::GetProperty(exports, jsvm::Str("tbl"));
787     jsvm::SetProperty(jsvm::Global(), jsvm::Str("tbl"), tbl);
788     auto r0 = jsvm::Run("tbl.get(0)()");
789     CHECK(jsvm::ToNumber(r0) == 13);
790     auto r1 = jsvm::Run("tbl.get(1)()");
791     CHECK(jsvm::ToNumber(r1) == 42);
792 }
793 
794 // test for Wasm MDN table2
795 TEST(Wasm_MDN_table2)
796 {
797     auto tbl = jsvm::Run(R"JS(
798         var tbl = new WebAssembly.Table({
799             initial: 2,
800             element: "anyfunc"
801         });
802         tbl;
803     )JS");
804     CHECK(jsvm::IsWebAssemblyTable(tbl));
805 
806     auto importObject = jsvm::Run(R"JS(
807         var importObject = {
808             js: { tbl }
809         };
810         importObject;
811     )JS");
812     CHECK(jsvm::IsObject(importObject));
813 
814     auto wasmModule = CompileWasmModule(wasmPath + "table2.wasm");
815     (void)InstantiateWasmModule(wasmModule, importObject);
816     auto r0 = jsvm::Run("tbl.get(0)()");
817     CHECK(jsvm::ToNumber(r0) == 42);
818     auto r1 = jsvm::Run("tbl.get(1)()");
819     CHECK(jsvm::ToNumber(r1) == 83);
820 }
821 
822 // test for Wasm MDN global
823 TEST(Wasm_MDN_global)
824 {
825     (void)jsvm::Run("var global = new WebAssembly.Global({ value: 'i32', mutable: true }, 0); global");
826     auto wasmModule = CompileWasmModule(wasmPath + "global.wasm");
827     auto importObject = jsvm::Run(R"JS(
828         var importObject = {
829             js: { global }
830         };
831         importObject
832     )JS");
833     auto instance = InstantiateWasmModule(wasmModule, importObject);
834     auto exports = GetInstanceExports(instance);
835     auto getGlobal = jsvm::GetProperty(exports, "getGlobal");
836     CHECK(jsvm::IsFunction(getGlobal));
837     auto r0 = jsvm::Call(getGlobal, exports, {});
838     CHECK(jsvm::ToNumber(r0) == 0);
839     jsvm::Run("global.value = 42");
840     auto r1 = jsvm::Call(getGlobal, exports, {});
841     CHECK(jsvm::ToNumber(r1) == 42);
842     auto incGlobal = jsvm::GetProperty(exports, "incGlobal");
843     jsvm::Call(incGlobal, exports, {});
844     auto r2 = jsvm::Call(getGlobal, exports, {});
845     CHECK(jsvm::ToNumber(r2) == 43);
846 }
847 
848 // test for Wasm Multiple Modules
849 TEST(Wasm_MultipleModules)
850 {
851     auto mathModule = CompileWasmModule(wasmPath + "math.wasm");
852     auto newtonModule = CompileWasmModule(wasmPath + "newton.wasm");
853     auto mathInstance = InstantiateWasmModule(mathModule, jsvm::Undefined());
854     auto mathExports = GetInstanceExports(mathInstance);
855     auto add = jsvm::GetProperty(mathExports, "add");
856     CHECK(jsvm::IsFunction(add));
857     auto sub = jsvm::GetProperty(mathExports, "sub");
858     CHECK(jsvm::IsFunction(sub));
859     jsvm::SetProperty(jsvm::Global(), jsvm::Str("add"), add);
860     jsvm::SetProperty(jsvm::Global(), jsvm::Str("sub"), sub);
861     auto mathObj = jsvm::Run(R"JS(
862         var mathObj = {
863             math: {
864                 add: add,
865                 sub, sub
866             }
867         };
868         mathObj
869     )JS");
870     CHECK(jsvm::IsObject(mathObj));
871     auto newtonInstance = InstantiateWasmModule(newtonModule, mathObj);
872     auto newtonExports = GetInstanceExports(newtonInstance);
873     auto calculate = jsvm::GetProperty(newtonExports, "calculate");
874     CHECK(jsvm::IsFunction(calculate));
875     auto result = jsvm::Call(calculate);
876     CHECK(jsvm::IsNumber(result));
877     CHECK(jsvm::ToNumber(result) == 42);
878 }
879 
880 void runCToWasm(JSVM_Env env, const std::string& filePath)
881 {
882     std::vector<uint8_t> buffer;
883     ReadBinaryFile(filePath, buffer);
884     CHECK(buffer.size() > 0);
885     JSVM_Value wasmModule;
886     JSVMTEST_CALL(OH_JSVM_CompileWasmModule(jsvm_env, buffer.data(), buffer.size(), NULL, 0, NULL, &wasmModule));
887     CHECK(jsvm::IsWasmModuleObject(wasmModule));
888 
889     JSVM_Value wasmInstance =
890         InstantiateWasmModule(wasmModule, jsvm::Run("var x = { test: {func: () => { return 1; }}}; x"));
891     JSVM_Value exports = jsvm::GetProperty(wasmInstance, jsvm::Str("exports"));
892     CHECK(jsvm::IsObject(exports));
893 
894     CompileWasmFunctions(env, wasmModule, {1, 2}, JSVM_WASM_OPT_HIGH);
895 
896     JSVM_Value testFunc;
897     JSVM_Value result;
898     {
899         testFunc = jsvm::GetProperty(exports, jsvm::Str("_start"));
900         CHECK(jsvm::IsFunction(testFunc));
901         result = jsvm::Call(testFunc, jsvm::Undefined(), {});
902         CHECK(jsvm::Equals(result, jsvm::Undefined()));
903     }
904 }
905 
906 // test for Wasm Run CTo Wasm Test
907 TEST(Wasm_RunCToWasmTest)
908 {
909     std::vector<std::string> pathVec = {
910         wasmPath + "bfs.wasm",
911         wasmPath + "cJSON.wasm",
912     };
913 
914     for (std::string &wasm : pathVec) {
915         runCToWasm(env, wasm);
916     }
917 }
918 
919 // test for Wasm Game Engine Ammo
920 TEST(Wasm_GameEngineAmmo)
921 {
922     std::string wasmFile = wasmPath + "ammo.wasm.wasm";
923     auto wasmModule = CompileWasmModule(wasmFile);
924     const char *str = R"JS(
925         var obj = {
926             f: () => {},
927             c: () => {},
928             d: () => {},
929             e: () => {},
930             b: () => {},
931             g: () => {},
932             a: () => {},
933             memory: new WebAssembly.Memory({initial: 1024, maximum: 1024}),
934             table: new WebAssembly.Table({ initial: 758, element: "anyfunc" })
935         };
936         var importObj = {
937             env: obj,
938             wasi_unstable: obj
939         };
940         importObj;
941     )JS";
942     auto importObj = jsvm::Run(str);
943     auto instance = InstantiateWasmModule(wasmModule, importObj);
944     CHECK(jsvm::IsWebAssemblyInstance(instance));
945     BatchCompileWasmFunctions(wasmModule, 7, 20);
946     BatchCompileWasmFunctions(wasmModule, 400, 420);
947     BatchCompileWasmFunctions(wasmModule, 1480, 1502);
948     auto exports = GetInstanceExports(instance);
949     CHECK(jsvm::IsObject(exports));
950 }
951 
952 // test for Wasm Game Engine Laya
953 TEST(Wasm_GameEngineLaya)
954 {
955     std::string wasmFile = wasmPath + "laya.physics3D.wasm.wasm";
956     auto wasmModule = CompileWasmModule(wasmFile);
957     const char *str = R"JS(
958         var importObj = {
959             env: {
960                 memory: new WebAssembly.Memory({initial: 2}),
961             },
962             wasi_unstable: {
963                 fd_close: () => {},
964                 fd_write: () => {},
965                 fd_seek: () => {},
966             },
967             LayaAirInteractive: {
968                 getWorldTransform: () => {},
969                 setWorldTransform: () => {},
970             }
971         };
972         importObj;
973     )JS";
974     auto importObj = jsvm::Run(str);
975     auto instance = InstantiateWasmModule(wasmModule, importObj);
976     CHECK(jsvm::IsWebAssemblyInstance(instance));
977     BatchCompileWasmFunctions(wasmModule, 5, 20);
978     BatchCompileWasmFunctions(wasmModule, 400, 420);
979     BatchCompileWasmFunctions(wasmModule, 1320, 1333);
980     auto exports = GetInstanceExports(instance);
981     CHECK(jsvm::IsObject(exports));
982 }
983 #else
984 static void GetLastErrorAndClean(JSVM_Env env)
985 {
986     JSVM_Value result = nullptr;
987     OH_JSVM_GetAndClearLastException(env, &result);
988 }
989 
990 // test for Wasm Is Wasm Module Object
991 TEST(Wasm_IsWasmModuleObject)
992 {
993     auto number = jsvm::Run("42");
994     CHECK(!jsvm::IsWasmModuleObject(number));
995     CHECK(!jsvm::IsWasmModuleObject(jsvm::Undefined()));
996     CHECK(!jsvm::IsWasmModuleObject(jsvm::Null()));
997     CHECK(!jsvm::IsWasmModuleObject(jsvm::Str("hello")));
998 }
999 
1000 // test for Wasm Compile Wasm
1001 TEST(Wasm_CompileWasmModule)
1002 {
1003     uint8_t* buffer = new uint8_t[2];
1004     buffer[0] = 0x01;
1005     buffer[1] = 0x02;
1006     JSVM_Value wasmModule = nullptr;
1007     JSVM_Status status = OH_JSVM_CompileWasmModule(jsvm_env, buffer, 2, NULL, 0, NULL, &wasmModule);
1008     delete[] buffer;
1009     CHECK(status == JSVM_JIT_MODE_EXPECTED);
1010     GetLastErrorAndClean(jsvm_env);
1011 }
1012 
1013 // test for Wasm Compile Function
1014 TEST(Wasm_CompileWasmFunction)
1015 {
1016     JSVM_Value wasmModule = nullptr;
1017     JSVM_Status status = OH_JSVM_CompileWasmFunction(jsvm_env, wasmModule, 0, JSVM_WASM_OPT_HIGH);
1018     CHECK(status == JSVM_JIT_MODE_EXPECTED);
1019     GetLastErrorAndClean(jsvm_env);
1020 }
1021 
1022 // test for Wasm Create Cache
1023 TEST(Wasm_CreateWasmCache)
1024 {
1025     const uint8_t *cacheData = nullptr;
1026     size_t cacheSize = 0;
1027     JSVM_Value wasmModule = nullptr;
1028     JSVM_Status status = OH_JSVM_CreateWasmCache(jsvm_env, wasmModule, &cacheData, &cacheSize);
1029     CHECK(status == JSVM_JIT_MODE_EXPECTED);
1030     GetLastErrorAndClean(jsvm_env);
1031 }
1032 
1033 // test for Wasm Release Cache
1034 TEST(Wasm_ReleaseWasmCache)
1035 {
1036     uint8_t* cacheData = new uint8_t[2];
1037     cacheData[0] = 0x01;
1038     cacheData[1] = 0x02;
1039     JSVM_Status status = OH_JSVM_ReleaseCache(jsvm_env, cacheData, JSVM_CACHE_TYPE_WASM);
1040     CHECK(status == JSVM_OK);
1041 }
1042 #endif  // JSVM_JITLESS
1043 #endif  // TEST_WASM
1044