1 /*
2 * Copyright (c) 2021 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 <cstdlib>
17 #include <cstring>
18 #include <iostream>
19 #include "client_stub.h"
20 #include "gtest/gtest.h"
21 #include "log.h"
22 #include "napi/native_api.h"
23 #include "napi/native_node_api.h"
24 #include "node_api.h"
25 #include "node_api_types.h"
26 #include "securec.h"
27 #include "update_client.h"
28 #include "update_helper.h"
29 #include "update_session.h"
30
31 using namespace updateClient;
32 using namespace std;
33 using namespace OHOS::update_engine;
34 static constexpr int NUMBER_2 = 2;
35
36 TestNApiValue g_callback(napi_function, nullptr);
37
38 uint32_t g_testSessionId = 0;
39 UpdateClient* g_testClient = nullptr;
40 static int32_t g_undefined = 100;
41 bool g_callbackFuncationCalled = false;
42
43 static UpdatePolicy g_updatePolicy = {
44 true,
45 true,
46 INSTALLMODE_AUTO,
47 AUTOUPGRADECONDITION_IDLE,
48 {1000, 1000}
49 };
50
51 TestNApiEnv g_testEnv;
52
CreateNapiValue(int type,const void * value)53 static napi_value CreateNapiValue(int type, const void *value)
54 {
55 auto testValue = new TestNApiValue(type, value);
56 g_testEnv.testValueList.push_back(testValue);
57 return (napi_value)testValue;
58 }
59
FreeAllNapiValues()60 void FreeAllNapiValues()
61 {
62 auto iter = g_testEnv.testValueList.begin();
63 while (iter != g_testEnv.testValueList.end()) {
64 auto value = *iter;
65 g_testEnv.testValueList.erase(iter);
66 delete value;
67 iter = g_testEnv.testValueList.begin();
68 }
69 }
70
TestNApiValue(int type,const void * value)71 TestNApiValue::TestNApiValue(int type, const void *value)
72 {
73 type_ = type;
74 switch (type) {
75 case napi_boolean:
76 bValue = *static_cast<bool*>(const_cast<void*>(value));
77 break;
78 case napi_number:
79 intValue = *static_cast<int*>(const_cast<void*>(value));
80 break;
81 case napi_string:
82 strValue = std::string(static_cast<char*>(const_cast<void*>(value)));
83 break;
84 case napi_bigint:
85 int64Value = *static_cast<int64_t*>(const_cast<void*>(value));
86 break;
87 default:
88 break;
89 }
90 }
91
TestGetUpdateSession()92 UpdateSession *TestGetUpdateSession()
93 {
94 printf(" TestGetUpdateSession g_testSessionId %u\n", g_testSessionId);
95 if (g_testClient != nullptr) {
96 return g_testClient->GetUpdateSession(g_testSessionId);
97 }
98 return nullptr;
99 }
100
101 #ifdef __cplusplus
102 extern "C" {
103 #endif
104
napi_create_string_utf8(napi_env env,const char * str,size_t length,napi_value * result)105 napi_status napi_create_string_utf8(napi_env env, const char *str, size_t length, napi_value *result)
106 {
107 *result = CreateNapiValue(napi_string, str);
108 return napi_status::napi_ok;
109 }
110
napi_typeof(napi_env env,napi_value value,napi_valuetype * result)111 napi_status napi_typeof(napi_env env, napi_value value, napi_valuetype *result)
112 {
113 if (((TestNApiValue*)value)->GetType() == TEST_NVALUE_TYPE_CONTEXT) {
114 *result = napi_object;
115 } else if (((TestNApiValue*)value)->GetType() == TEST_NVALUE_TYPE_UPGRADE) {
116 *result = napi_object;
117 } else if (((TestNApiValue*)value)->GetType() == TEST_NVALUE_TYPE_UPDATE_POLICY) {
118 *result = napi_object;
119 } else {
120 *result = (napi_valuetype)((TestNApiValue*)value)->GetType();
121 }
122 return napi_status::napi_ok;
123 }
124
napi_create_reference(napi_env env,napi_value value,uint32_t initial_refcount,napi_ref * result)125 napi_status napi_create_reference(napi_env env, napi_value value, uint32_t initial_refcount,
126 napi_ref* result)
127 {
128 return napi_status::napi_ok;
129 }
130
napi_get_reference_value(napi_env env,napi_ref ref,napi_value * result)131 napi_status napi_get_reference_value(napi_env env, napi_ref ref, napi_value* result)
132 {
133 return napi_status::napi_ok;
134 }
135
napi_delete_reference(napi_env env,napi_ref ref)136 napi_status napi_delete_reference(napi_env env, napi_ref ref)
137 {
138 return napi_status::napi_ok;
139 }
140
napi_call_function(napi_env env,napi_value recv,napi_value func,size_t argc,const napi_value * argv,napi_value * result)141 napi_status napi_call_function(napi_env env, napi_value recv,
142 napi_value func, size_t argc, const napi_value *argv, napi_value *result)
143 {
144 g_callbackFuncationCalled = true;
145 return napi_status::napi_ok;
146 }
147
napi_delete_async_work(napi_env env,napi_async_work work)148 napi_status napi_delete_async_work(napi_env env, napi_async_work work)
149 {
150 return napi_status::napi_ok;
151 }
152
napi_queue_async_work(napi_env env,napi_async_work work)153 napi_status napi_queue_async_work(napi_env env, napi_async_work work)
154 {
155 return napi_status::napi_ok;
156 }
157
napi_cancel_async_work(napi_env env,napi_async_work work)158 napi_status napi_cancel_async_work(napi_env env, napi_async_work work)
159 {
160 return napi_status::napi_ok;
161 }
162
napi_create_object(napi_env env,napi_value * result)163 napi_status napi_create_object(napi_env env, napi_value* result)
164 {
165 *result = CreateNapiValue(napi_object, nullptr);
166 return napi_status::napi_ok;
167 }
168
napi_set_element(napi_env env,napi_value object,uint32_t index,napi_value value)169 napi_status napi_set_element(napi_env env, napi_value object, uint32_t index, napi_value value)
170 {
171 return napi_status::napi_ok;
172 }
173
napi_create_array_with_length(napi_env env,size_t length,napi_value * result)174 napi_status napi_create_array_with_length(napi_env env, size_t length, napi_value* result)
175 {
176 *result = CreateNapiValue(napi_object, nullptr);
177 return napi_status::napi_ok;
178 }
179
napi_create_int32(napi_env env,int32_t value,napi_value * result)180 napi_status napi_create_int32(napi_env env, int32_t value, napi_value* result)
181 {
182 *result = CreateNapiValue(napi_number, &value);
183 return napi_status::napi_ok;
184 }
185
napi_create_uint32(napi_env env,uint32_t value,napi_value * result)186 napi_status napi_create_uint32(napi_env env, uint32_t value, napi_value* result)
187 {
188 *result = CreateNapiValue(napi_number, &value);
189 return napi_status::napi_ok;
190 }
191
napi_get_undefined(napi_env env,napi_value * result)192 napi_status napi_get_undefined(napi_env env, napi_value* result)
193 {
194 *result = (napi_value)&g_undefined;
195 return napi_status::napi_ok;
196 }
197
napi_create_int64(napi_env env,int64_t value,napi_value * result)198 napi_status napi_create_int64(napi_env env, int64_t value, napi_value* result)
199 {
200 *result = CreateNapiValue(napi_bigint, &value);
201 return napi_status::napi_ok;
202 }
203
napi_throw_error(napi_env env,const char * code,const char * msg)204 napi_status napi_throw_error(napi_env env, const char* code, const char* msg)
205 {
206 return napi_status::napi_ok;
207 }
napi_is_exception_pending(napi_env env,bool * result)208 napi_status napi_is_exception_pending(napi_env env, bool* result)
209 {
210 return napi_status::napi_ok;
211 }
212
napi_get_last_error_info(napi_env env,const napi_extended_error_info ** result)213 napi_status napi_get_last_error_info(napi_env env, const napi_extended_error_info** result)
214 {
215 return napi_status::napi_ok;
216 }
217
napi_define_properties(napi_env env,napi_value object,size_t property_count,const napi_property_descriptor * properties)218 napi_status napi_define_properties(napi_env env, napi_value object,
219 size_t property_count, const napi_property_descriptor *properties)
220 {
221 return napi_status::napi_ok;
222 }
223
napi_module_register(napi_module * mod)224 void napi_module_register(napi_module* mod) {}
225
napi_has_named_property(napi_env env,napi_value object,const char * utf8name,bool * result)226 napi_status napi_has_named_property(napi_env env, napi_value object, const char *utf8name,
227 bool *result)
228 {
229 *result = false;
230 TestNApiValue* testValue = (TestNApiValue*)object;
231 if (testValue->GetType() == TEST_NVALUE_TYPE_CONTEXT) {
232 *result = true;
233 } else if (testValue->GetType() == TEST_NVALUE_TYPE_UPGRADE ||
234 testValue->GetType() == TEST_NVALUE_TYPE_UPDATE_POLICY) {
235 *result = true;
236 }
237 return napi_status::napi_ok;
238 }
239
napi_get_named_property(napi_env env,napi_value object,const char * utf8name,napi_value * result)240 napi_status napi_get_named_property(napi_env env, napi_value object, const char* utf8name,
241 napi_value* result)
242 {
243 TestNApiEnv* testEnv = (TestNApiEnv*)env;
244 TestNApiValue* testValue = (TestNApiValue*)object;
245
246 if (testValue->GetType() == TEST_NVALUE_TYPE_CONTEXT) {
247 if (strcmp(utf8name, "serverAddr") == 0) {
248 *result = CreateNapiValue(napi_string, "10.50.40.92");
249 } else if (strcmp(utf8name, "upgradeDevId") == 0) {
250 *result = CreateNapiValue(napi_string, testEnv->clientContext.upgradeDevId.c_str());
251 } else if (strcmp(utf8name, "controlDevId") == 0) {
252 *result = CreateNapiValue(napi_string, testEnv->clientContext.controlDevId.c_str());
253 } else if (strcmp(utf8name, "upgradeApp") == 0) {
254 *result = CreateNapiValue(napi_string, testEnv->clientContext.upgradeApp.c_str());
255 } else if (strcmp(utf8name, "type") == 0) {
256 *result = CreateNapiValue(napi_number, &testEnv->clientContext.type);
257 }
258 } else if (testValue->GetType() == TEST_NVALUE_TYPE_UPGRADE) {
259 if (strcmp(utf8name, "versionName") == 0) {
260 *result = CreateNapiValue(napi_string, testEnv->pakcageInfo.result[0].versionName.c_str());
261 } else if (strcmp(utf8name, "versionCode") == 0) {
262 *result = CreateNapiValue(napi_string, testEnv->pakcageInfo.result[0].versionCode.c_str());
263 } else if (strcmp(utf8name, "verifyInfo") == 0) {
264 *result = CreateNapiValue(napi_string, testEnv->pakcageInfo.result[0].verifyInfo.c_str());
265 } else if (strcmp(utf8name, "descriptPackageId") == 0) {
266 *result = CreateNapiValue(napi_string, testEnv->pakcageInfo.result[0].descriptPackageId.c_str());
267 } else if (strcmp(utf8name, "packageType") == 0) {
268 *result = CreateNapiValue(napi_number, &testEnv->pakcageInfo.result[0].packageType);
269 } else if (strcmp(utf8name, "size") == 0) {
270 *result = CreateNapiValue(napi_bigint, &testEnv->pakcageInfo.result[0].size);
271 }
272 } else if (testValue->GetType() == TEST_NVALUE_TYPE_UPDATE_POLICY) {
273 if (strcmp(utf8name, "autoDownload") == 0) {
274 *result = CreateNapiValue(napi_number, (void*)&g_updatePolicy.autoDownload);
275 } else if (strcmp(utf8name, "autoDownloadNet") == 0) {
276 *result = CreateNapiValue(napi_string, (void*)&g_updatePolicy.autoDownloadNet);
277 } else if (strcmp(utf8name, "mode") == 0) {
278 *result = CreateNapiValue(napi_string, (void*)&g_updatePolicy.mode);
279 } else if (strcmp(utf8name, "autoUpgradeCondition") == 0) {
280 *result = CreateNapiValue(napi_string, (void*)&g_updatePolicy.autoUpgradeCondition);
281 }
282 }
283 return napi_status::napi_ok;
284 }
285
napi_get_value_string_utf8(napi_env env,napi_value value,char * buf,size_t bufsize,size_t * result)286 napi_status napi_get_value_string_utf8(napi_env env, napi_value value, char* buf,
287 size_t bufsize, size_t* result)
288 {
289 TestNApiValue* testValue = (TestNApiValue*)value;
290 if (buf != nullptr) {
291 memcpy_s(buf, bufsize, testValue->strValue.data(), testValue->strValue.size());
292 }
293 printf("napi_get_value_string_utf8 %s bufsize %zu %zu \n",
294 testValue->strValue.c_str(), bufsize, testValue->strValue.size());
295 *result = testValue->strValue.size();
296 return napi_status::napi_ok;
297 }
298
napi_get_value_int32(napi_env env,napi_value value,int32_t * result)299 napi_status napi_get_value_int32(napi_env env, napi_value value, int32_t* result)
300 {
301 TestNApiValue* testValue = (TestNApiValue*)value;
302 *result = testValue->intValue;
303 return napi_status::napi_ok;
304 }
305
napi_get_value_uint32(napi_env env,napi_value value,uint32_t * result)306 napi_status napi_get_value_uint32(napi_env env, napi_value value, uint32_t* result)
307 {
308 TestNApiValue* testValue = (TestNApiValue*)value;
309 *result = static_cast<uint32_t>(testValue->intValue);
310 return napi_status::napi_ok;
311 }
312
napi_get_value_int64(napi_env env,napi_value value,int64_t * result)313 napi_status napi_get_value_int64(napi_env env, napi_value value, int64_t* result)
314 {
315 TestNApiValue* testValue = (TestNApiValue*)value;
316 *result = testValue->int64Value;
317 return napi_status::napi_ok;
318 }
319
napi_set_named_property(napi_env env,napi_value object,const char * utf8name,napi_value value)320 napi_status napi_set_named_property(napi_env env, napi_value object, const char *utf8name,
321 napi_value value)
322 {
323 TestNApiEnv* testEnv = (TestNApiEnv*)env;
324 TestNApiValue* testValue = (TestNApiValue*)value;
325 if (testValue == nullptr) {
326 return napi_status::napi_ok;
327 }
328 if (testValue->GetType() == napi_string) {
329 if (testValue->strValue.empty()) {
330 return napi_status::napi_ok;
331 }
332 if (strcmp(utf8name, "versionName") == 0) {
333 testEnv->pakcageInfo.result[0].versionName = testValue->strValue;
334 } else if (strcmp(utf8name, "versionCode") == 0) {
335 testEnv->pakcageInfo.result[0].versionCode = testValue->strValue;
336 } else if (strcmp(utf8name, "verifyInfo") == 0) {
337 testEnv->pakcageInfo.result[0].verifyInfo = testValue->strValue;
338 } else if (strcmp(utf8name, "descriptPackageId") == 0) {
339 if (testValue->strValue.size() > 0) {
340 testEnv->pakcageInfo.result[0].descriptPackageId = testValue->strValue;
341 }
342 } else if (strcmp(utf8name, "errMsg") == 0) {
343 testEnv->errorMsg = testValue->strValue;
344 }
345 } else if (testValue->GetType() == napi_number) {
346 if (strcmp(utf8name, "packageType") == 0) {
347 testEnv->pakcageInfo.result[0].packageType = (PackageType)testValue->intValue;
348 } else if (strcmp(utf8name, "status") == 0) {
349 testEnv->progress.status = (UpgradeStatus)testValue->intValue;
350 } else if (strcmp(utf8name, "percent") == 0) {
351 testEnv->progress.percent = testValue->intValue;
352 }
353 } else if (testValue->GetType() == napi_bigint) {
354 if (strcmp(utf8name, "size") == 0 && testValue->int64Value != 0) {
355 testEnv->pakcageInfo.result[0].size = (size_t)testValue->int64Value;
356 }
357 }
358 return napi_status::napi_ok;
359 }
360
361 // Asynchronous execution
napi_create_async_work(napi_env env,napi_value async_resource,napi_value async_resource_name,napi_async_execute_callback execute,napi_async_complete_callback complete,void * data,napi_async_work * result)362 napi_status napi_create_async_work(napi_env env, napi_value async_resource,
363 napi_value async_resource_name, napi_async_execute_callback execute,
364 napi_async_complete_callback complete, void *data, napi_async_work *result)
365 {
366 UpdateSession *sess = static_cast<UpdateSession *>(data);
367 g_testSessionId = sess->GetSessionId();
368 printf(" g_testSessionId %u\n", g_testSessionId);
369 *result = (napi_async_work)CreateNapiValue(0, nullptr);
370 return napi_status::napi_ok;
371 }
372
napi_get_cb_info(napi_env env,napi_callback_info cbinfo,size_t * argc,napi_value * argv,napi_value * this_arg,void ** data)373 napi_status napi_get_cb_info(
374 napi_env env, // [in] NAPI environment handle
375 napi_callback_info cbinfo, // [in] Opaque callback-info handle
376 size_t *argc, // [in-out] Specifies the size of the provided argv array
377 // and receives the actual count of args.
378 napi_value *argv, // [out] Array of values
379 napi_value *this_arg, // [out] Receives the JS 'this' arg for the call
380 void **data) // [out] Receives the data pointer for the callback.
381 {
382 TestNApiEnv* testEnv = (TestNApiEnv*)env;
383 printf("++++++++++++++ napi_get_cb_info argc %zu testStage %d \n", *argc, testEnv->testStage);
384 switch (testEnv->testStage) {
385 case SESSION_GET_UPDATER: {
386 if (*argc > 1) {
387 *argc = (testEnv->engineType != 0) ? NUMBER_2 : 1;
388 argv[0] = CreateNapiValue(napi_string, testEnv->eventType.c_str());
389 argv[1] = CreateNapiValue(napi_string, "OTA");
390 } else {
391 argv[0] = CreateNapiValue(napi_string, "OTA");
392 *argc = 1;
393 }
394 break;
395 }
396 case SESSION_VERIFY_PACKAGE:{
397 if (*argc > 1) {
398 argv[0] = CreateNapiValue(napi_string, "/data/updater/updater/updater_success.zip");
399 argv[1] = CreateNapiValue(napi_string, "/data/updater/src/signing_cert.crt");
400 }
401 *argc = NUMBER_2;
402 break;
403 }
404 case SESSION_SET_POLICY: {
405 argv[0] = CreateNapiValue(TEST_NVALUE_TYPE_UPDATE_POLICY, nullptr);
406 if (*argc > 1) {
407 argv[1] = CreateNapiValue(napi_function, nullptr);
408 }
409 *argc = testEnv->testAsyncorPermose ? 1 : NUMBER_2;
410 break;
411 }
412 case SESSION_SUBSCRIBE:
413 case SESSION_UNSUBSCRIBE: {
414 argv[0] = CreateNapiValue(napi_string, testEnv->eventType.c_str());
415 if (*argc > 1) {
416 argv[1] = CreateNapiValue(napi_function, nullptr);
417 }
418 *argc = testEnv->testAsyncorPermose ? 1 : NUMBER_2;
419 break;
420 }
421 default:{
422 *argc = testEnv->testAsyncorPermose ? 0 : 1;
423 *argv = CreateNapiValue(napi_function, nullptr);
424 break;
425 }
426 }
427 return napi_status::napi_ok;
428 }
429
napi_is_array(napi_env env,napi_value value,bool * result)430 napi_status napi_is_array(napi_env env, napi_value value, bool *result)
431 {
432 *result = true;
433 return napi_status::napi_ok;
434 }
435
napi_get_array_length(napi_env env,napi_value value,uint32_t * result)436 napi_status napi_get_array_length(napi_env env, napi_value value, uint32_t *result)
437 {
438 *result = sizeof(g_updatePolicy.autoUpgradeInterval) / sizeof(g_updatePolicy.autoUpgradeInterval[0]);
439 return napi_status::napi_ok;
440 }
441
napi_get_element(napi_env env,napi_value object,uint32_t index,napi_value * result)442 napi_status napi_get_element(napi_env env, napi_value object, uint32_t index, napi_value *result)
443 {
444 if (index >= sizeof(g_updatePolicy.autoUpgradeInterval) / sizeof(g_updatePolicy.autoUpgradeInterval[0])) {
445 *result = nullptr;
446 return napi_status::napi_ok;
447 }
448 *result = CreateNapiValue(napi_number, &g_updatePolicy.autoUpgradeInterval[index]);
449 return napi_status::napi_ok;
450 }
451
napi_open_handle_scope(napi_env env,napi_handle_scope * result)452 napi_status napi_open_handle_scope(napi_env env, napi_handle_scope* result)
453 {
454 return napi_status::napi_ok;
455 }
456
napi_close_handle_scope(napi_env env,napi_handle_scope scope)457 napi_status napi_close_handle_scope(napi_env env, napi_handle_scope scope)
458 {
459 return napi_status::napi_ok;
460 }
461
napi_get_value_bool(napi_env env,napi_value value,bool * result)462 napi_status napi_get_value_bool(napi_env env, napi_value value, bool* result)
463 {
464 *result = true;
465 return napi_status::napi_ok;
466 }
467
napi_strict_equals(napi_env env,napi_value lhs,napi_value rhs,bool * result)468 napi_status napi_strict_equals(napi_env env, napi_value lhs, napi_value rhs, bool* result)
469 {
470 *result = true;
471 return napi_status::napi_ok;
472 }
473
napi_create_promise(napi_env env,napi_deferred * deferred,napi_value * promise)474 napi_status napi_create_promise(napi_env env, napi_deferred* deferred, napi_value* promise)
475 {
476 *promise = CreateNapiValue(napi_object, nullptr);
477 return napi_status::napi_ok;
478 }
479
napi_resolve_deferred(napi_env env,napi_deferred deferred,napi_value resolution)480 napi_status napi_resolve_deferred(napi_env env, napi_deferred deferred, napi_value resolution)
481 {
482 return napi_status::napi_ok;
483 }
484
napi_reject_deferred(napi_env env,napi_deferred deferred,napi_value rejection)485 napi_status napi_reject_deferred(napi_env env, napi_deferred deferred, napi_value rejection)
486 {
487 return napi_status::napi_ok;
488 }
489
490 // Methods to work with external data objects
napi_wrap(napi_env env,napi_value jsObject,void * native_object,napi_finalize finalize_cb,void * finalize_hint,napi_ref * result)491 napi_status napi_wrap(napi_env env, napi_value jsObject,
492 void* native_object, napi_finalize finalize_cb, void* finalize_hint, napi_ref* result)
493 {
494 return napi_status::napi_ok;
495 }
496
napi_unwrap(napi_env env,napi_value jsObject,void ** result)497 napi_status napi_unwrap(napi_env env, napi_value jsObject, void** result)
498 {
499 TestNApiEnv* testEnv = (TestNApiEnv*)env;
500 if (testEnv->testStage && testEnv->noneClient) {
501 *result = nullptr;
502 testEnv->noneClient = false;
503 return napi_status::napi_ok;
504 }
505 if (g_testClient == nullptr) {
506 g_testClient = new UpdateClient(env, jsObject);
507 }
508 *result = g_testClient;
509 return napi_status::napi_ok;
510 }
511
napi_define_class(napi_env env,const char * utf8name,size_t length,napi_callback constructor,void * data,size_t property_count,const napi_property_descriptor * properties,napi_value * result)512 napi_status napi_define_class(napi_env env, const char* utf8name, size_t length, napi_callback constructor,
513 void* data, size_t property_count, const napi_property_descriptor* properties, napi_value* result)
514 {
515 std::function<napi_value(napi_env env, napi_callback_info info)> func = constructor;
516 func(env, nullptr);
517 return napi_status::napi_ok;
518 }
519
napi_new_instance(napi_env env,napi_value constructor,size_t argc,const napi_value * argv,napi_value * result)520 napi_status napi_new_instance(napi_env env, napi_value constructor, size_t argc, const napi_value* argv,
521 napi_value* result)
522 {
523 return napi_status::napi_ok;
524 }
525
napi_remove_wrap(napi_env env,napi_value js_object,void ** result)526 napi_status napi_remove_wrap(napi_env env, napi_value js_object, void** result)
527 {
528 return napi_status::napi_ok;
529 }
530
531 #ifdef __cplusplus
532 }
533 #endif