133eb0b6dSopenharmony_ci/* 233eb0b6dSopenharmony_ci * Copyright (c) 2021-2022 Huawei Device Co., Ltd. 333eb0b6dSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 433eb0b6dSopenharmony_ci * you may not use this file except in compliance with the License. 533eb0b6dSopenharmony_ci * You may obtain a copy of the License at 633eb0b6dSopenharmony_ci * 733eb0b6dSopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 833eb0b6dSopenharmony_ci * 933eb0b6dSopenharmony_ci * Unless required by applicable law or agreed to in writing, software 1033eb0b6dSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 1133eb0b6dSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1233eb0b6dSopenharmony_ci * See the License for the specific language governing permissions and 1333eb0b6dSopenharmony_ci * limitations under the License. 1433eb0b6dSopenharmony_ci */ 1533eb0b6dSopenharmony_ci 1633eb0b6dSopenharmony_ci#include "ark_interop_external.h" 1733eb0b6dSopenharmony_ci#include "ark_interop_hitrace.h" 1833eb0b6dSopenharmony_ci#include "ark_interop_internal.h" 1933eb0b6dSopenharmony_ci#include "ark_interop_log.h" 2033eb0b6dSopenharmony_ci#include "ark_interop_napi.h" 2133eb0b6dSopenharmony_ci#include "gtest/gtest.h" 2233eb0b6dSopenharmony_ci#include "uv_loop_handler.h" 2333eb0b6dSopenharmony_ci 2433eb0b6dSopenharmony_ci#include <cmath> 2533eb0b6dSopenharmony_ci#include <thread> 2633eb0b6dSopenharmony_ci 2733eb0b6dSopenharmony_ciusing namespace testing; 2833eb0b6dSopenharmony_ciusing namespace testing::ext; 2933eb0b6dSopenharmony_ci 3033eb0b6dSopenharmony_cistruct ARKTS_ModuleCallbacks { 3133eb0b6dSopenharmony_ci ARKTS_Value (*exportModule)(ARKTS_Env env, const char* dllName, ARKTS_Value exports) = nullptr; 3233eb0b6dSopenharmony_ci bool (*hasModuleHandle)(const char* dllName) = nullptr; 3333eb0b6dSopenharmony_ci void (*throwJSError)(ARKTS_Env env, ARKTS_Value) = nullptr; 3433eb0b6dSopenharmony_ci void (*throwNativeError)(const char*) = nullptr; 3533eb0b6dSopenharmony_ci void (*deleteArrayBufferRawData)(void* buffer, int64_t lambdaId) = nullptr; 3633eb0b6dSopenharmony_ci void (*deleteExternal)(int64_t id, ARKTS_Env env) = nullptr; 3733eb0b6dSopenharmony_ci ARKTS_Value (*invokerLambda)(ARKTS_CallInfo, int64_t lambdaId) = nullptr; 3833eb0b6dSopenharmony_ci void (*deleteLambda)(ARKTS_Env env, int64_t lambdaId) = nullptr; 3933eb0b6dSopenharmony_ci void (*invokeAsyncLambda)(ARKTS_Env env, int64_t lambdaId) = nullptr; 4033eb0b6dSopenharmony_ci void (*deleteJSContext)(ARKTS_Env env) = nullptr; 4133eb0b6dSopenharmony_ci}; 4233eb0b6dSopenharmony_ci 4333eb0b6dSopenharmony_cinamespace { 4433eb0b6dSopenharmony_ciARKTS_Engine engine_ = nullptr; 4533eb0b6dSopenharmony_ci 4633eb0b6dSopenharmony_ciclass ArkInteropTest : public testing::Test {}; 4733eb0b6dSopenharmony_ci 4833eb0b6dSopenharmony_ciTEST_F(ArkInteropTest, Prime) 4933eb0b6dSopenharmony_ci{ 5033eb0b6dSopenharmony_ci auto env = ARKTS_GetContext(engine_); 5133eb0b6dSopenharmony_ci auto scope = ARKTS_OpenScope(env); 5233eb0b6dSopenharmony_ci 5333eb0b6dSopenharmony_ci auto jsUDef = ARKTS_CreateUndefined(); 5433eb0b6dSopenharmony_ci EXPECT_TRUE(ARKTS_IsUndefined(jsUDef)); 5533eb0b6dSopenharmony_ci EXPECT_EQ(ARKTS_GetValueType(env, jsUDef), N_UNDEFINED); 5633eb0b6dSopenharmony_ci 5733eb0b6dSopenharmony_ci auto jsNull = ARKTS_CreateNull(); 5833eb0b6dSopenharmony_ci EXPECT_TRUE(ARKTS_IsNull(jsNull)); 5933eb0b6dSopenharmony_ci EXPECT_EQ(ARKTS_GetValueType(env, jsNull), N_NULL); 6033eb0b6dSopenharmony_ci 6133eb0b6dSopenharmony_ci ARKTS_Value jsBools[] { 6233eb0b6dSopenharmony_ci ARKTS_CreateBool(true), 6333eb0b6dSopenharmony_ci ARKTS_CreateBool(false) 6433eb0b6dSopenharmony_ci }; 6533eb0b6dSopenharmony_ci EXPECT_TRUE(ARKTS_IsBool(jsBools[0])); 6633eb0b6dSopenharmony_ci EXPECT_EQ(ARKTS_GetValueType(env, jsBools[0]), N_BOOL); 6733eb0b6dSopenharmony_ci EXPECT_TRUE(ARKTS_GetValueBool(jsBools[0])); 6833eb0b6dSopenharmony_ci EXPECT_FALSE(ARKTS_GetValueBool(jsBools[1])); 6933eb0b6dSopenharmony_ci 7033eb0b6dSopenharmony_ci ARKTS_CloseScope(env, scope); 7133eb0b6dSopenharmony_ci} 7233eb0b6dSopenharmony_ci 7333eb0b6dSopenharmony_ciTEST_F(ArkInteropTest, Number) 7433eb0b6dSopenharmony_ci{ 7533eb0b6dSopenharmony_ci auto env = ARKTS_GetContext(engine_); 7633eb0b6dSopenharmony_ci auto scope = ARKTS_OpenScope(env); 7733eb0b6dSopenharmony_ci double origins[] { 7833eb0b6dSopenharmony_ci 0.1, 7933eb0b6dSopenharmony_ci -12.1, 8033eb0b6dSopenharmony_ci 12456.126546 8133eb0b6dSopenharmony_ci }; 8233eb0b6dSopenharmony_ci constexpr auto totalCases = std::size(origins); 8333eb0b6dSopenharmony_ci ARKTS_Value jsValues[totalCases]; 8433eb0b6dSopenharmony_ci double received[totalCases]; 8533eb0b6dSopenharmony_ci 8633eb0b6dSopenharmony_ci for (size_t i = 0;i < totalCases; i++) { 8733eb0b6dSopenharmony_ci jsValues[i] = ARKTS_CreateF64(origins[i]); 8833eb0b6dSopenharmony_ci EXPECT_EQ(ARKTS_GetValueType(env, jsValues[i]), N_NUMBER); 8933eb0b6dSopenharmony_ci EXPECT_TRUE(ARKTS_IsNumber(jsValues[i])); 9033eb0b6dSopenharmony_ci received[i] = ARKTS_GetValueNumber(jsValues[i]); 9133eb0b6dSopenharmony_ci EXPECT_EQ(origins[i], received[i]); 9233eb0b6dSopenharmony_ci } 9333eb0b6dSopenharmony_ci 9433eb0b6dSopenharmony_ci auto jsNan = ARKTS_CreateF64(NAN); 9533eb0b6dSopenharmony_ci auto nNan = ARKTS_GetValueNumber(jsNan); 9633eb0b6dSopenharmony_ci EXPECT_TRUE(std::isnan(nNan)); 9733eb0b6dSopenharmony_ci ARKTS_CloseScope(env, scope); 9833eb0b6dSopenharmony_ci} 9933eb0b6dSopenharmony_ci 10033eb0b6dSopenharmony_ciTEST_F(ArkInteropTest, String) 10133eb0b6dSopenharmony_ci{ 10233eb0b6dSopenharmony_ci auto env = ARKTS_GetContext(engine_); 10333eb0b6dSopenharmony_ci auto scope = ARKTS_OpenScope(env); 10433eb0b6dSopenharmony_ci const char* origins[] { 10533eb0b6dSopenharmony_ci "a plain text", 10633eb0b6dSopenharmony_ci "`~!@#$%^&*()_+[]\\", 10733eb0b6dSopenharmony_ci "中文字符", 10833eb0b6dSopenharmony_ci "❤️", 10933eb0b6dSopenharmony_ci }; 11033eb0b6dSopenharmony_ci ARKTS_Value jsValues[] { 11133eb0b6dSopenharmony_ci ARKTS_CreateUtf8(env, origins[0], strlen(origins[0])), 11233eb0b6dSopenharmony_ci ARKTS_CreateUtf8(env, origins[1], strlen(origins[1])), 11333eb0b6dSopenharmony_ci ARKTS_CreateUtf8(env, origins[2], strlen(origins[2])), 11433eb0b6dSopenharmony_ci ARKTS_CreateUtf8(env, origins[3], strlen(origins[3])), 11533eb0b6dSopenharmony_ci }; 11633eb0b6dSopenharmony_ci EXPECT_TRUE(ARKTS_IsString(env, jsValues[0])); 11733eb0b6dSopenharmony_ci EXPECT_TRUE(ARKTS_IsHeapObject(jsValues[0])); 11833eb0b6dSopenharmony_ci EXPECT_EQ(ARKTS_GetValueType(env, jsValues[0]), N_STRING); 11933eb0b6dSopenharmony_ci for (auto i = 0;i < sizeof(jsValues)/sizeof(ARKTS_Value); i++) { 12033eb0b6dSopenharmony_ci auto size = ARKTS_GetValueUtf8Size(env, jsValues[i]); 12133eb0b6dSopenharmony_ci std::string result; 12233eb0b6dSopenharmony_ci result.resize(size - 1); 12333eb0b6dSopenharmony_ci ARKTS_GetValueUtf8(env, jsValues[i], size - 1, result.data()); 12433eb0b6dSopenharmony_ci EXPECT_EQ(result, origins[i]); 12533eb0b6dSopenharmony_ci 12633eb0b6dSopenharmony_ci auto cStr = ARKTS_GetValueCString(env, jsValues[i]); 12733eb0b6dSopenharmony_ci result = cStr; 12833eb0b6dSopenharmony_ci EXPECT_EQ(result, origins[i]); 12933eb0b6dSopenharmony_ci ARKTS_FreeCString(cStr); 13033eb0b6dSopenharmony_ci } 13133eb0b6dSopenharmony_ci ARKTS_CloseScope(env, scope); 13233eb0b6dSopenharmony_ci} 13333eb0b6dSopenharmony_ci 13433eb0b6dSopenharmony_ciTEST_F(ArkInteropTest, Object) 13533eb0b6dSopenharmony_ci{ 13633eb0b6dSopenharmony_ci auto env = ARKTS_GetContext(engine_); 13733eb0b6dSopenharmony_ci auto scope = ARKTS_OpenScope(env); 13833eb0b6dSopenharmony_ci auto obj = ARKTS_CreateObject(env); 13933eb0b6dSopenharmony_ci EXPECT_TRUE(ARKTS_IsHeapObject(obj)); 14033eb0b6dSopenharmony_ci EXPECT_TRUE(ARKTS_IsObject(env, obj)); 14133eb0b6dSopenharmony_ci EXPECT_EQ(ARKTS_GetValueType(env, obj), N_OBJECT); 14233eb0b6dSopenharmony_ci auto keyA = ARKTS_CreateUtf8(env, "a", 1); 14333eb0b6dSopenharmony_ci EXPECT_FALSE(ARKTS_HasOwnProperty(env, obj, keyA)); 14433eb0b6dSopenharmony_ci auto valueA = ARKTS_GetProperty(env, obj, keyA); 14533eb0b6dSopenharmony_ci EXPECT_TRUE(ARKTS_IsUndefined(valueA)); 14633eb0b6dSopenharmony_ci valueA = ARKTS_CreateBool(true); 14733eb0b6dSopenharmony_ci ARKTS_SetProperty(env, obj, keyA, valueA); 14833eb0b6dSopenharmony_ci EXPECT_TRUE(ARKTS_HasOwnProperty(env, obj, keyA)); 14933eb0b6dSopenharmony_ci auto receivedA = ARKTS_GetProperty(env, obj, keyA); 15033eb0b6dSopenharmony_ci EXPECT_TRUE(ARKTS_IsBool(receivedA)); 15133eb0b6dSopenharmony_ci EXPECT_TRUE(ARKTS_GetValueBool(receivedA)); 15233eb0b6dSopenharmony_ci auto keys = ARKTS_EnumOwnProperties(env, obj); 15333eb0b6dSopenharmony_ci EXPECT_TRUE(ARKTS_IsArray(env, keys)); 15433eb0b6dSopenharmony_ci EXPECT_EQ(ARKTS_GetArrayLength(env, keys), 1); 15533eb0b6dSopenharmony_ci auto key = ARKTS_GetElement(env, keys, 0); 15633eb0b6dSopenharmony_ci EXPECT_TRUE(ARKTS_IsString(env, key)); 15733eb0b6dSopenharmony_ci EXPECT_TRUE(ARKTS_StrictEqual(env, keyA, key)); 15833eb0b6dSopenharmony_ci ARKTS_CloseScope(env, scope); 15933eb0b6dSopenharmony_ci} 16033eb0b6dSopenharmony_ci 16133eb0b6dSopenharmony_cistruct PropCase { 16233eb0b6dSopenharmony_ci char k; 16333eb0b6dSopenharmony_ci bool writable; 16433eb0b6dSopenharmony_ci bool enumerable; 16533eb0b6dSopenharmony_ci bool configurable; 16633eb0b6dSopenharmony_ci}; 16733eb0b6dSopenharmony_ci 16833eb0b6dSopenharmony_ciTEST_F(ArkInteropTest, DefineProperty) 16933eb0b6dSopenharmony_ci{ 17033eb0b6dSopenharmony_ci auto env = ARKTS_GetContext(engine_); 17133eb0b6dSopenharmony_ci auto scope = ARKTS_OpenScope(env); 17233eb0b6dSopenharmony_ci auto obj = ARKTS_CreateObject(env); 17333eb0b6dSopenharmony_ci PropCase cases[] { 17433eb0b6dSopenharmony_ci {'a', false, false, false}, {'b', true, false, false}, {'c', false, true, false}, {'d', false, false, true}, 17533eb0b6dSopenharmony_ci {'e', true, true, false}, {'f', true, false, true}, {'g', false, true, true}, {'h', true, true, true} 17633eb0b6dSopenharmony_ci }; 17733eb0b6dSopenharmony_ci constexpr auto totalCases = std::size(cases); 17833eb0b6dSopenharmony_ci auto valueT = ARKTS_CreateBool(true), valueF = ARKTS_CreateBool(false); 17933eb0b6dSopenharmony_ci ARKTS_Value keys[totalCases]; 18033eb0b6dSopenharmony_ci for (auto i = 0; i < totalCases; i++) { 18133eb0b6dSopenharmony_ci keys[i] = ARKTS_CreateUtf8(env, &cases[i].k, 1); 18233eb0b6dSopenharmony_ci ARKTS_DefineOwnProperty(env, obj, keys[i], valueF, static_cast<ARKTS_PropertyFlag>( 18333eb0b6dSopenharmony_ci (cases[i].writable ? N_WRITABLE : 0) | 18433eb0b6dSopenharmony_ci (cases[i].enumerable ? N_ENUMERABLE : 0) | 18533eb0b6dSopenharmony_ci (cases[i].configurable ? N_CONFIGURABLE : 0) 18633eb0b6dSopenharmony_ci )); 18733eb0b6dSopenharmony_ci } 18833eb0b6dSopenharmony_ci constexpr int expectKeys = 4; 18933eb0b6dSopenharmony_ci auto jsKeys = ARKTS_EnumOwnProperties(env, obj); 19033eb0b6dSopenharmony_ci EXPECT_TRUE(ARKTS_IsArray(env, jsKeys)); 19133eb0b6dSopenharmony_ci EXPECT_EQ(ARKTS_GetArrayLength(env, jsKeys), expectKeys); 19233eb0b6dSopenharmony_ci for (auto i = 0; i < expectKeys; i++) { 19333eb0b6dSopenharmony_ci auto jsKey = ARKTS_GetElement(env, jsKeys, i); 19433eb0b6dSopenharmony_ci EXPECT_TRUE(ARKTS_IsString(env, jsKey)); 19533eb0b6dSopenharmony_ci char buffer = 0; 19633eb0b6dSopenharmony_ci ARKTS_GetValueUtf8(env, jsKey, 1, &buffer); 19733eb0b6dSopenharmony_ci EXPECT_TRUE(buffer == 'c' || buffer == 'e' || buffer == 'g' || buffer == 'h'); 19833eb0b6dSopenharmony_ci } 19933eb0b6dSopenharmony_ci for (auto i = 0; i < totalCases; i++) { // writable 20033eb0b6dSopenharmony_ci if (cases[i].writable && cases[i].configurable) { 20133eb0b6dSopenharmony_ci ARKTS_SetProperty(env, obj, keys[i], valueT); 20233eb0b6dSopenharmony_ci auto receivedJS = ARKTS_GetProperty(env, obj, keys[i]); 20333eb0b6dSopenharmony_ci auto recievedN = ARKTS_GetValueBool(receivedJS); 20433eb0b6dSopenharmony_ci EXPECT_TRUE(recievedN); 20533eb0b6dSopenharmony_ci } 20633eb0b6dSopenharmony_ci } 20733eb0b6dSopenharmony_ci for (auto i = 0;i < totalCases; ++i) { // configurable 20833eb0b6dSopenharmony_ci if (cases[i].configurable) { 20933eb0b6dSopenharmony_ci ARKTS_DefineOwnProperty(env, obj, keys[i], valueT, 21033eb0b6dSopenharmony_ci static_cast<ARKTS_PropertyFlag>(N_WRITABLE | N_ENUMERABLE | N_CONFIGURABLE)); 21133eb0b6dSopenharmony_ci } 21233eb0b6dSopenharmony_ci } 21333eb0b6dSopenharmony_ci jsKeys = ARKTS_EnumOwnProperties(env, obj); 21433eb0b6dSopenharmony_ci constexpr int expectLength = 6; 21533eb0b6dSopenharmony_ci EXPECT_EQ(ARKTS_GetArrayLength(env, jsKeys), expectLength); 21633eb0b6dSopenharmony_ci ARKTS_CloseScope(env, scope); 21733eb0b6dSopenharmony_ci} 21833eb0b6dSopenharmony_ci 21933eb0b6dSopenharmony_ciHWTEST_F(ArkInteropTest, ArkTSInteropNapiInstanceOf, TestSize.Level1) 22033eb0b6dSopenharmony_ci{ 22133eb0b6dSopenharmony_ci ARKTS_Env env = ARKTS_GetContext(engine_); 22233eb0b6dSopenharmony_ci auto global = ARKTS_GetGlobalConstant(env); 22333eb0b6dSopenharmony_ci char clError[] = "Error"; 22433eb0b6dSopenharmony_ci auto jError = ARKTS_CreateUtf8(env, clError, sizeof(clError) - 1); 22533eb0b6dSopenharmony_ci auto errorCls = ARKTS_GetProperty(env, global, jError); 22633eb0b6dSopenharmony_ci auto errorObJ = ARKTS_New(env, errorCls, 0, nullptr); 22733eb0b6dSopenharmony_ci auto isError = ARKTS_InstanceOf(env, errorObJ, errorCls); 22833eb0b6dSopenharmony_ci EXPECT_TRUE(isError); 22933eb0b6dSopenharmony_ci auto jObj = ARKTS_CreateObject(env); 23033eb0b6dSopenharmony_ci EXPECT_FALSE(ARKTS_InstanceOf(env, jObj, errorCls)); 23133eb0b6dSopenharmony_ci} 23233eb0b6dSopenharmony_ci 23333eb0b6dSopenharmony_ciHWTEST_F(ArkInteropTest, ArkTSInteropNapiCreateEngineNew, TestSize.Level1) 23433eb0b6dSopenharmony_ci{ 23533eb0b6dSopenharmony_ci auto engine = ARKTS_CreateEngineWithNewThread(); 23633eb0b6dSopenharmony_ci 23733eb0b6dSopenharmony_ci auto curTid = ARKTS_GetPosixThreadId(); 23833eb0b6dSopenharmony_ci auto engineTid = ARKTS_GetThreadIdOfEngine(engine); 23933eb0b6dSopenharmony_ci 24033eb0b6dSopenharmony_ci EXPECT_NE(curTid, engineTid); 24133eb0b6dSopenharmony_ci 24233eb0b6dSopenharmony_ci ARKTS_DestroyEngine(engine); 24333eb0b6dSopenharmony_ci} 24433eb0b6dSopenharmony_ci} // namespace 24533eb0b6dSopenharmony_ci 24633eb0b6dSopenharmony_ciint main(int argc, char** argv) 24733eb0b6dSopenharmony_ci{ 24833eb0b6dSopenharmony_ci LOGI("main in"); 24933eb0b6dSopenharmony_ci testing::GTEST_FLAG(output) = "xml:./"; 25033eb0b6dSopenharmony_ci testing::InitGoogleTest(&argc, argv); 25133eb0b6dSopenharmony_ci 25233eb0b6dSopenharmony_ci auto runner = OHOS::AppExecFwk::EventRunner::Create(true); 25333eb0b6dSopenharmony_ci EXPECT_TRUE(runner); 25433eb0b6dSopenharmony_ci auto handler = std::make_shared<OHOS::AppExecFwk::EventHandler>(runner); 25533eb0b6dSopenharmony_ci EXPECT_TRUE(handler); 25633eb0b6dSopenharmony_ci 25733eb0b6dSopenharmony_ci int ret = -1; 25833eb0b6dSopenharmony_ci std::condition_variable cv; 25933eb0b6dSopenharmony_ci 26033eb0b6dSopenharmony_ci auto success = handler->PostTask([&ret, &cv] { 26133eb0b6dSopenharmony_ci engine_ = ARKTS_CreateEngine(); 26233eb0b6dSopenharmony_ci 26333eb0b6dSopenharmony_ci ret = testing::UnitTest::GetInstance()->Run(); 26433eb0b6dSopenharmony_ci cv.notify_all(); 26533eb0b6dSopenharmony_ci }); 26633eb0b6dSopenharmony_ci 26733eb0b6dSopenharmony_ci EXPECT_TRUE(success); 26833eb0b6dSopenharmony_ci 26933eb0b6dSopenharmony_ci std::mutex mutex; 27033eb0b6dSopenharmony_ci std::unique_lock<std::mutex> lock(mutex); 27133eb0b6dSopenharmony_ci auto status = cv.wait_for(lock, std::chrono::seconds(10)); 27233eb0b6dSopenharmony_ci 27333eb0b6dSopenharmony_ci EXPECT_EQ(status, std::cv_status::no_timeout); 27433eb0b6dSopenharmony_ci 27533eb0b6dSopenharmony_ci ARKTS_DestroyEngine(engine_); 27633eb0b6dSopenharmony_ci engine_ = nullptr; 27733eb0b6dSopenharmony_ci runner->Stop(); 27833eb0b6dSopenharmony_ci 27933eb0b6dSopenharmony_ci LOGI("main out"); 28033eb0b6dSopenharmony_ci return ret; 28133eb0b6dSopenharmony_ci} 282