1 /**
2 * Copyright (c) 2021-2023 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
16 #include "ets_interop_js_gtest.h"
17 #include <iostream>
18 #include <memory>
19
20 #ifdef PANDA_TARGET_OHOS
21 // napi_fatal_exception() is not implemented it libace_napi.z.so,
22 // so let's implement it ourselves
napi_fatal_exception(napi_env env,napi_value err)23 extern "C" napi_status napi_fatal_exception([[maybe_unused]] napi_env env, [[maybe_unused]] napi_value err)
24 {
25 std::cerr << "ETS_INTEROP_GTEST_PLUGIN: " << __func__ << " is not implemented" << std::endl;
26 std::abort();
27 return napi_ok;
28 }
29 #endif // PANDA_TARGET_OHOS
30
31 namespace panda::ets::interop::js::testing {
32
33 napi_env EtsInteropTest::jsEnv_ = {};
34
35 class JsEnvAccessor {
36 public:
SetJsEnv(napi_env env)37 static void SetJsEnv(napi_env env)
38 {
39 EtsInteropTest::jsEnv_ = env;
40 }
41
ResetJsEnv()42 static void ResetJsEnv()
43 {
44 EtsInteropTest::jsEnv_ = {};
45 }
46 };
47
Main(napi_env env,napi_callback_info info)48 static napi_value Main(napi_env env, napi_callback_info info)
49 {
50 size_t jsArgc = 0;
51 [[maybe_unused]] napi_status status = napi_get_cb_info(env, info, &jsArgc, nullptr, nullptr, nullptr);
52 ASSERT(status == napi_ok);
53
54 if (jsArgc != 1) {
55 std::cerr << "ETS_INTEROP_GTEST_PLUGIN: Incorrect argc, argc=" << jsArgc << std::endl;
56 std::abort();
57 }
58
59 std::vector<napi_value> jsArgv(jsArgc);
60
61 napi_value thisArg = nullptr;
62 void *data = nullptr;
63 status = napi_get_cb_info(env, info, &jsArgc, jsArgv.data(), &thisArg, &data);
64 ASSERT(status == napi_ok);
65
66 napi_value jsArray = jsArgv.front();
67 uint32_t jsArrayLength = 0;
68 status = napi_get_array_length(env, jsArray, &jsArrayLength);
69 ASSERT(status == napi_ok);
70
71 std::vector<std::string> argv;
72 for (uint32_t i = 0; i < jsArrayLength; ++i) {
73 napi_value jsArrayElement;
74 status = napi_get_element(env, jsArray, i, &jsArrayElement);
75 ASSERT(status == napi_ok);
76
77 size_t strLength = 0;
78 status = napi_get_value_string_utf8(env, jsArrayElement, nullptr, 0, &strLength);
79 ASSERT(status == napi_ok);
80
81 std::string utf8Str(++strLength, '\0');
82 size_t copied = 0;
83 status = napi_get_value_string_utf8(env, jsArrayElement, utf8Str.data(), utf8Str.size(), &copied);
84 ASSERT(status == napi_ok);
85
86 argv.emplace_back(std::move(utf8Str));
87 }
88
89 int argc = jsArrayLength;
90 std::vector<char *> argvChar;
91 argvChar.reserve(argv.size());
92
93 for (auto &arg : argv) {
94 argvChar.emplace_back(arg.data());
95 }
96
97 ASSERT(size_t(argc) == argvChar.size());
98 ::testing::InitGoogleTest(&argc, argvChar.data());
99
100 // Run tests
101 JsEnvAccessor::SetJsEnv(env);
102 int retValue = RUN_ALL_TESTS();
103 JsEnvAccessor::ResetJsEnv();
104
105 napi_value jsRetValue;
106 status = napi_create_int32(env, retValue, &jsRetValue);
107 ASSERT(status == napi_ok);
108 return jsRetValue;
109 }
110
Init(napi_env env,napi_value exports)111 static napi_value Init(napi_env env, napi_value exports)
112 {
113 const std::array desc = {
114 napi_property_descriptor {"main", 0, Main, 0, 0, 0, napi_enumerable, 0},
115 };
116
117 [[maybe_unused]] napi_status status = napi_define_properties(env, exports, desc.size(), desc.data());
118 ASSERT(status == napi_ok);
119
120 return exports;
121 }
122
123 } // namespace panda::ets::interop::js::testing
124
125 NAPI_MODULE(GTEST_ADDON, panda::ets::interop::js::testing::Init)
126