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 "gtest/gtest.h"
17 #include "napi/native_api.h"
18 #include "napi/native_common.h"
19 #include "napi/native_node_api.h"
20 #include "module_checker_delegate.h"
21 #include "form_module_checker.h"
22 #include "ark_native_engine.h"
23 #include "napi/native_engine/native_utils.h"
24 #include "securec.h"
25 #include "test.h"
26 #include "test_common.h"
27 #include "utils/log.h"
28 
29 using panda::ArrayRef;
30 using panda::JSValueRef;
31 using panda::Local;
32 using panda::ObjectRef;
33 
34 class ArkApiAllowlistTest : public NativeEngineTest {
35 public:
SetUpTestCase()36     static void SetUpTestCase()
37     {
38         GTEST_LOG_(INFO) << "ArkApiAllowlistTest SetUpTestCase";
39     }
40 
TearDownTestCase()41     static void TearDownTestCase()
42     {
43         GTEST_LOG_(INFO) << "ArkApiAllowlistTest TearDownTestCase";
44     }
45 
SetUp()46     void SetUp() override {}
TearDown()47     void TearDown() override {}
48 };
49 
50 
TestFunction(napi_env env,napi_callback_info info)51 napi_value TestFunction(napi_env env, napi_callback_info info)
52 {
53     HILOG_INFO("this is TestFunction");
54     return nullptr;
55 }
56 
CheckPropertyNames(Local<ObjectRef> & obj,const EcmaVM * vm,uint32_t & filter,std::unordered_map<std::string,bool> & keyToCond)57 void CheckPropertyNames(Local<ObjectRef> &obj,
58                         const EcmaVM* vm,
59                         uint32_t &filter,
60                         std::unordered_map<std::string, bool> &keyToCond)
61 {
62     Local<ArrayRef> propertyNamesArrayVal = obj->GetAllPropertyNames(vm, filter);
63     for (uint32_t i = 0; i < propertyNamesArrayVal->Length(vm); ++i) {
64         Local<JSValueRef> nameValue = ArrayRef::GetValueAt(vm, propertyNamesArrayVal, i);
65         std::string keyname = nameValue->ToString(vm)->ToString(vm);
66         HILOG_INFO("exportCopy->system->function:%{public}s", keyname.c_str());
67         if (keyToCond.find(keyname) != keyToCond.end()) {
68             keyToCond[keyname] = true;
69         }
70     }
71 }
72 
Test001(const EcmaVM * vm,Local<ObjectRef> & exportCopy,uint32_t & filter)73 bool Test001(const EcmaVM* vm, Local<ObjectRef> &exportCopy, uint32_t &filter)
74 {
75     bool condition1 = false;
76     bool condition2 = false;
77     bool condition3 = true;
78     Local<ArrayRef> propertyNamesArrayVal = exportCopy->GetAllPropertyNames(vm, filter);
79     for (uint32_t i = 0; i < propertyNamesArrayVal->Length(vm); ++i) {
80         Local<JSValueRef> nameValue = ArrayRef::GetValueAt(vm, propertyNamesArrayVal, i);
81         std::string keyname = nameValue->ToString(vm)->ToString(vm);
82         HILOG_INFO("exportCopy->function:%{public}s", keyname.c_str());
83         if (keyname == "System") {
84             Local<ObjectRef> obj = exportCopy->Get(vm, nameValue);
85             std::unordered_map<std::string, bool> keyToCond;
86             keyToCond["getSystemLanguage"] = condition1;
87             keyToCond["is24HourClock"] = condition2;
88             CheckPropertyNames(obj, vm, filter, keyToCond);
89             condition1 = keyToCond["getSystemLanguage"];
90             condition2 = keyToCond["is24HourClock"];
91         } else {
92             condition3 = false;
93         }
94     }
95     return condition1 && condition2 && condition3;
96 }
97 
Test002(const EcmaVM * vm,Local<ObjectRef> & exportCopy,uint32_t & filter)98 bool Test002(const EcmaVM* vm, Local<ObjectRef> &exportCopy, uint32_t &filter)
99 {
100     bool condition1 = false;
101     bool condition2 = false;
102     bool condition3 = true;
103     bool condition4 = false;
104     bool condition5 = false;
105     bool condition6 = false;
106     bool condition7 = false;
107     Local<ArrayRef> propertyNamesArrayVal = exportCopy->GetAllPropertyNames(vm, filter);
108     for (uint32_t i = 0; i < propertyNamesArrayVal->Length(vm); ++i) {
109         Local<JSValueRef> nameValue = ArrayRef::GetValueAt(vm, propertyNamesArrayVal, i);
110         std::string keyname = nameValue->ToString(vm)->ToString(vm);
111         HILOG_INFO("exportCopy->function:%{public}s", keyname.c_str());
112         if (keyname == "Locale") {
113             condition1 = true;
114             Local<ObjectRef> obj = exportCopy->Get(vm, nameValue);
115             std::unordered_map<std::string, bool> keyToCond;
116             keyToCond["function001"] = condition4;
117             keyToCond["systemOtherFunction"] = condition5;
118             CheckPropertyNames(obj, vm, filter, keyToCond);
119             condition4 = keyToCond["function001"];
120             condition5 = keyToCond["systemOtherFunction"];
121         } else if (keyname == "DateTimeFormat") {
122             condition2 = true;
123             Local<ObjectRef> obj = exportCopy->Get(vm, nameValue);
124             std::unordered_map<std::string, bool> keyToCond;
125             keyToCond["function001"] = condition6;
126             keyToCond["systemOtherFunction"] = condition7;
127             CheckPropertyNames(obj, vm, filter, keyToCond);
128             condition6 = keyToCond["function001"];
129             condition7 = keyToCond["systemOtherFunction"];
130         } else if (nameValue->Typeof(vm)->ToString(vm) == "object") {
131             condition3 = false;
132         }
133     }
134     return condition1 && condition2 && condition3 && condition4 && condition5 && condition6 && condition7;
135 }
136 
137 /**
138  * @tc.name: CopyPropertyApiFilterTest002
139  * @tc.desc: Test CopyPropertyApiFilter Functional Logic.
140  * @tc.type: FUNC
141  */
142 HWTEST_F(ArkApiAllowlistTest, CopyPropertyApiFilterTest001, testing::ext::TestSize.Level1)
143 {
144     ArkNativeEngine* arkNativeEngine = static_cast<ArkNativeEngine*>(engine_);
145     const EcmaVM* vm = arkNativeEngine->GetEcmaVm();
146     napi_env env = reinterpret_cast<napi_env>(arkNativeEngine);
147     std::unique_ptr<ApiAllowListChecker> apiAllowListFilter = nullptr;
148     std::shared_ptr<FormModuleChecker> formChecker = std::make_shared<FormModuleChecker>();
149     formChecker->CheckModuleLoadable("i18n", apiAllowListFilter);
150 
151     napi_property_descriptor systemProperties[] = {
152         DECLARE_NAPI_FUNCTION("getSystemLanguage", TestFunction),
153         DECLARE_NAPI_FUNCTION("is24HourClock", TestFunction),
154         DECLARE_NAPI_FUNCTION("systemOtherFunction", TestFunction),
155     };
156     napi_value system;
157     napi_create_object(env, &system);
158     napi_define_properties(env, system, sizeof(systemProperties) / sizeof(napi_property_descriptor), systemProperties);
159 
160     napi_property_descriptor i18nProperties[] = {
161         DECLARE_NAPI_FUNCTION("getSystemLanguage", TestFunction),
162         DECLARE_NAPI_FUNCTION("i18nOtherFunction", TestFunction),
163         DECLARE_NAPI_PROPERTY("System", system),
164     };
165     napi_value i18n;
166     napi_create_object(env, &i18n);
167     napi_define_properties(env, i18n, sizeof(i18nProperties) / sizeof(napi_property_descriptor), i18nProperties);
168     Local<ObjectRef> i18nObj = LocalValueFromJsValue(i18n);
169 
170     Local<ObjectRef> exportCopy = ObjectRef::New(vm);
171 
172     if (apiAllowListFilter != nullptr) {
173         std::string apiPath = "i18n";
174         if ((*apiAllowListFilter)(apiPath)) {
175             ArkNativeEngine::CopyPropertyApiFilter(apiAllowListFilter, vm, i18nObj, exportCopy, apiPath);
176         }
177     }
178 
179     uint32_t filter = NATIVE_DEFAULT;
180     Local<ArrayRef> propertyNamesArrayVal = i18nObj->GetAllPropertyNames(vm, filter);
181     for (uint32_t i = 0; i < propertyNamesArrayVal->Length(vm); ++i) {
182         HILOG_INFO("exportObj->function:%{public}s",
183             ArrayRef::GetValueAt(vm, propertyNamesArrayVal, i)->ToString(vm)->ToString(vm).c_str());
184     }
185     ASSERT_EQ(Test001(vm, exportCopy, filter), true);
186 }
187 
188 
189 /**
190  * @tc.name: CopyPropertyApiFilterTest001
191  * @tc.desc: Test CopyPropertyApiFilter Functional Logic.
192  * @tc.type: FUNC
193  */
194 HWTEST_F(ArkApiAllowlistTest, CopyPropertyApiFilterTest002, testing::ext::TestSize.Level1)
195 {
196     ArkNativeEngine* arkNativeEngine = static_cast<ArkNativeEngine*>(engine_);
197     const EcmaVM* vm = arkNativeEngine->GetEcmaVm();
198     napi_env env = reinterpret_cast<napi_env>(arkNativeEngine);
199     std::unique_ptr<ApiAllowListChecker> apiAllowListFilter = nullptr;
200     std::shared_ptr<FormModuleChecker> formChecker = std::make_shared<FormModuleChecker>();
201     formChecker->CheckModuleLoadable("intl", apiAllowListFilter);
202 
203     napi_property_descriptor l2Properties[] = {
204         DECLARE_NAPI_FUNCTION("function001", TestFunction),
205         DECLARE_NAPI_FUNCTION("function002", TestFunction),
206         DECLARE_NAPI_FUNCTION("systemOtherFunction", TestFunction),
207     };
208     napi_value l2obj;
209     napi_create_object(env, &l2obj);
210     napi_define_properties(env, l2obj, sizeof(l2Properties) / sizeof(napi_property_descriptor), l2Properties);
211 
212     napi_property_descriptor intlProperties[] = {
213         DECLARE_NAPI_FUNCTION("getSystemLanguage", TestFunction),
214         DECLARE_NAPI_FUNCTION("i18nOtherFunction", TestFunction),
215         DECLARE_NAPI_PROPERTY("Locale2", l2obj),
216         DECLARE_NAPI_PROPERTY("Locale", l2obj),
217         DECLARE_NAPI_PROPERTY("DateTimeFormat", l2obj),
218     };
219     napi_value intl;
220     napi_create_object(env, &intl);
221     napi_define_properties(env, intl, sizeof(intlProperties) / sizeof(napi_property_descriptor), intlProperties);
222     Local<ObjectRef> intlObj = LocalValueFromJsValue(intl);
223 
224     Local<ObjectRef> exportCopy = ObjectRef::New(vm);
225 
226     if (apiAllowListFilter != nullptr) {
227         std::string apiPath = "intl";
228         if ((*apiAllowListFilter)(apiPath)) {
229             ArkNativeEngine::CopyPropertyApiFilter(apiAllowListFilter, vm, intlObj, exportCopy, apiPath);
230         }
231     }
232 
233     uint32_t filter = NATIVE_DEFAULT;
234     Local<ArrayRef> propertyNamesArrayVal = intlObj->GetAllPropertyNames(vm, filter);
235     for (uint32_t i = 0; i < propertyNamesArrayVal->Length(vm); ++i) {
236         HILOG_INFO("exportObj->function:%{public}s",
237             ArrayRef::GetValueAt(vm, propertyNamesArrayVal, i)->ToString(vm)->ToString(vm).c_str());
238     }
239     ASSERT_EQ(Test002(vm, exportCopy, filter), true);
240 }
241