• 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 #include <unistd.h>
16 #include <sys/syscall.h>
17 
18 #include <ctime>
19 #include <latch>
20 #include <thread>
21 #include <gtest/gtest.h>
22 
23 #include "ark_native_engine.h"
24 #include "condition/condition_manager.h"
25 #include "condition/condition_variable.h"
26 
27 using namespace Commonlibrary::Concurrent::Condition;
28 
29 class ConditionTest : public testing::Test {
30 public:
SetUpTestSuite()31     static void SetUpTestSuite()
32     {
33         InitializeEngine();
34     }
35 
TearDownTestSuite()36     static void TearDownTestSuite()
37     {
38         DestroyEngine();
39     }
40 
InitializeEngine()41     static void InitializeEngine()
42     {
43         panda::RuntimeOption option;
44         option.SetGcType(panda::RuntimeOption::GC_TYPE::GEN_GC);
45 
46         const int64_t poolSize = 0x1000000;  // 16M
47         option.SetGcPoolSize(poolSize);
48 
49         option.SetLogLevel(panda::RuntimeOption::LOG_LEVEL::ERROR);
50         option.SetDebuggerLibraryPath("");
51         vm_ = panda::JSNApi::CreateJSVM(option);
52         ASSERT_TRUE(vm_ != nullptr);
53 
54         engine_ = new ArkNativeEngine(vm_, nullptr);
55     }
56 
DestroyEngine()57     static void DestroyEngine()
58     {
59         delete engine_;
60         engine_ = nullptr;
61         panda::JSNApi::DestroyJSVM(vm_);
62     }
63 
GetEnv()64     static napi_env GetEnv()
65     {
66         return reinterpret_cast<napi_env>(engine_);
67     }
68 
CreateFunction(const char * name,napi_value (* callback)(napi_env,napi_callback_info),void * data=nullptr)69     static napi_value CreateFunction(const char *name, napi_value (*callback)(napi_env, napi_callback_info),
70         void *data = nullptr)
71     {
72         napi_value result;
73         napi_status status = napi_create_function(GetEnv(), name, NAPI_AUTO_LENGTH, callback, data, &result);
74         EXPECT_EQ(status, napi_ok);
75         return result;
76     }
77 
78 protected:
79     static thread_local NativeEngine *engine_;
80     static thread_local EcmaVM *vm_;
81 };
82 
83 thread_local NativeEngine *ConditionTest::engine_ = nullptr;
84 thread_local EcmaVM *ConditionTest::vm_ = nullptr;
85 
CreateConditionVariableInstances(napi_env env)86 static napi_value CreateConditionVariableInstances(napi_env env)
87 {
88     napi_value exports;
89     napi_create_object(env, &exports);
90     napi_value exportsResult = Commonlibrary::Concurrent::Condition::ConditionManager::Init(env, exports);
91     napi_value locks;
92     napi_status status = napi_get_named_property(env, exportsResult, "locks", &locks);
93     if (status != napi_ok) {
94         return nullptr;
95     }
96 
97     napi_value conditionClass;
98     status = napi_get_named_property(env, locks, "ConditionVariable", &conditionClass);
99     if (status != napi_ok) {
100         return nullptr;
101     }
102 
103     napi_value instance;
104     status = napi_new_instance(env, conditionClass, 0, nullptr, &instance);
105     if (status != napi_ok) {
106         return nullptr;
107     }
108 
109     napi_ref napi_ref;
110     status = napi_create_reference(env, instance, 1, &napi_ref);
111     if (status != napi_ok) {
112         return nullptr;
113     }
114 
115     napi_value thisVar;
116     status = napi_get_reference_value(env, napi_ref, &thisVar);
117     if (status != napi_ok) {
118         return nullptr;
119     }
120 
121     return thisVar;
122 }
123 
TEST_F(ConditionTest,WaitTest)124 TEST_F(ConditionTest, WaitTest)
125 {
126     ConditionTest::InitializeEngine();
127     napi_env env = ConditionTest::GetEnv();
128     ASSERT_NE(env, nullptr);
129     napi_value thisVar = CreateConditionVariableInstances(env);
130     ASSERT_NE(thisVar, nullptr);
131 
132     // 调用 wait 方法
133     napi_value waitFn;
134     napi_status status = napi_get_named_property(env, thisVar, "wait", &waitFn);
135     ASSERT_EQ(status, napi_ok);
136     napi_value promise;
137     status = napi_call_function(env, thisVar, waitFn, 0, nullptr, &promise);
138     ASSERT_EQ(status, napi_ok);
139     ASSERT_TRUE(promise != nullptr);
140     bool isPromise = false;
141     napi_is_promise(env, promise, &isPromise);
142     ASSERT_TRUE(isPromise);
143 
144     // 调用notify 方法
145     napi_value notifyFn;
146     status = napi_get_named_property(env, thisVar, "notifyAll", &notifyFn);
147     ASSERT_EQ(status, napi_ok);
148     status = napi_call_function(env, thisVar, notifyFn, 0, nullptr, nullptr);
149     ASSERT_EQ(status, napi_ok);
150 
151     // 调用notify 方法
152     status = napi_call_function(env, thisVar, notifyFn, 0, nullptr, nullptr);
153     ASSERT_EQ(status, napi_ok);
154 }
155 
TEST_F(ConditionTest,WaitForTest)156 TEST_F(ConditionTest, WaitForTest)
157 {
158     ConditionTest::InitializeEngine();
159     napi_env env = ConditionTest::GetEnv();
160     ASSERT_NE(env, nullptr);
161     napi_value thisVar = CreateConditionVariableInstances(env);
162     ASSERT_NE(thisVar, nullptr);
163 
164     // 调用 wait 方法
165     napi_value waitFn;
166     napi_status status = napi_get_named_property(env, thisVar, "waitFor", &waitFn);
167     ASSERT_EQ(status, napi_ok);
168     napi_value promise;
169     napi_value milliseconds = nullptr;
170     double millis = 3000;
171     napi_create_double(env, millis, &milliseconds);
172     napi_value argv[] = {milliseconds};
173     status = napi_call_function(env, thisVar, waitFn, 1, argv, &promise);
174     ASSERT_EQ(status, napi_ok);
175     ASSERT_TRUE(promise != nullptr);
176     bool isPromise = false;
177     napi_is_promise(env, promise, &isPromise);
178     ASSERT_TRUE(isPromise);
179 
180     // 调用notifyOne 方法
181     napi_value notifyFn;
182     status = napi_get_named_property(env, thisVar, "notifyOne", &notifyFn);
183     ASSERT_EQ(status, napi_ok);
184     status = napi_call_function(env, thisVar, notifyFn, 0, nullptr, nullptr);
185     ASSERT_EQ(status, napi_ok);
186 
187     // 调用notifyOne 方法
188     status = napi_call_function(env, thisVar, notifyFn, 0, nullptr, nullptr);
189     ASSERT_EQ(status, napi_ok);
190 }
191 
TEST_F(ConditionTest,NotifyOneTest)192 TEST_F(ConditionTest, NotifyOneTest)
193 {
194     ConditionTest::InitializeEngine();
195     napi_env env = ConditionTest::GetEnv();
196     ASSERT_NE(env, nullptr);
197     napi_value thisVar = CreateConditionVariableInstances(env);
198     ASSERT_NE(thisVar, nullptr);
199 
200     // 调用notify 方法
201     napi_value notifyFn;
202     napi_status status = napi_get_named_property(env, thisVar, "notifyOne", &notifyFn);
203     ASSERT_EQ(status, napi_ok);
204     status = napi_call_function(env, thisVar, notifyFn, 0, nullptr, nullptr);
205     ASSERT_EQ(status, napi_ok);
206 
207     // 调用notify 方法
208     status = napi_call_function(env, thisVar, notifyFn, 0, nullptr, nullptr);
209     ASSERT_EQ(status, napi_ok);
210 }
211 
TEST_F(ConditionTest,NotifyAllTest)212 TEST_F(ConditionTest, NotifyAllTest)
213 {
214     ConditionTest::InitializeEngine();
215     napi_env env = ConditionTest::GetEnv();
216     ASSERT_NE(env, nullptr);
217     napi_value thisVar = CreateConditionVariableInstances(env);
218     ASSERT_NE(thisVar, nullptr);
219 
220     // 调用notify 方法
221     napi_value notifyFn;
222     napi_status status = napi_get_named_property(env, thisVar, "notifyAll", &notifyFn);
223     ASSERT_EQ(status, napi_ok);
224     status = napi_call_function(env, thisVar, notifyFn, 0, nullptr, nullptr);
225     ASSERT_EQ(status, napi_ok);
226 
227     // 调用notify 方法
228     status = napi_call_function(env, thisVar, notifyFn, 0, nullptr, nullptr);
229     ASSERT_EQ(status, napi_ok);
230 }
231 
TEST_F(ConditionTest,ConstructorTest)232 TEST_F(ConditionTest, ConstructorTest)
233 {
234     ConditionTest::InitializeEngine();
235     napi_env env = ConditionTest::GetEnv();
236     ASSERT_NE(env, nullptr);
237     napi_value thisVar = CreateConditionVariableInstances(env);
238     ASSERT_NE(thisVar, nullptr);
239 }
240 
TEST_F(ConditionTest,ConstructorTest2)241 TEST_F(ConditionTest, ConstructorTest2)
242 {
243     ConditionTest::InitializeEngine();
244     napi_env env = ConditionTest::GetEnv();
245     ASSERT_NE(env, nullptr);
246     ConditionVariable *cond = new ConditionVariable();
247     ASSERT_NE(cond, nullptr);
248 }
249 
TEST_F(ConditionTest,RquestTest)250 TEST_F(ConditionTest, RquestTest)
251 {
252     ConditionTest::InitializeEngine();
253     napi_env env = ConditionTest::GetEnv();
254     ASSERT_NE(env, nullptr);
255     napi_value exports;
256     napi_create_object(env, &exports);
257     napi_value exportsResult = Commonlibrary::Concurrent::Condition::ConditionManager::Init(env, exports);
258     napi_value locks;
259     napi_status status = napi_get_named_property(env, exportsResult, "locks", &locks);
260     ASSERT_EQ(status, napi_ok);
261     napi_value conditionClass;
262     status = napi_get_named_property(env, locks, "ConditionVariable", &conditionClass);
263     ASSERT_EQ(status, napi_ok);
264 
265     napi_value constructorArgs1[1] = { 0 };
266     std::string name = "condName1";
267     napi_create_string_utf8(env, name.c_str(), name.size(), &constructorArgs1[0]);
268 
269     // 调用request 方法
270     napi_value notifyFn;
271     status = napi_get_named_property(env, conditionClass, "request", &notifyFn);
272     ASSERT_EQ(status, napi_ok);
273     napi_value condRequest = nullptr;
274     napi_value undefine = nullptr;
275     status = napi_call_function(env, undefine, notifyFn, 1, constructorArgs1, &condRequest);
276     ASSERT_EQ(status, napi_ok);
277     ASSERT_NE(condRequest, nullptr);
278     napi_ref napi_ref;
279     status = napi_create_reference(env, condRequest, 1, &napi_ref);
280     ASSERT_EQ(status, napi_ok);
281     napi_value thisVar;
282     status = napi_get_reference_value(env, napi_ref, &thisVar);
283     ASSERT_EQ(status, napi_ok);
284 
285     // 调用 wait 方法
286     napi_value waitFn;
287     status = napi_get_named_property(env, thisVar, "wait", &waitFn);
288     ASSERT_EQ(status, napi_ok);
289     napi_value promise;
290     status = napi_call_function(env, thisVar, waitFn, 0, nullptr, &promise);
291     ASSERT_EQ(status, napi_ok);
292     ASSERT_TRUE(promise != nullptr);
293     bool isPromise = false;
294     napi_is_promise(env, promise, &isPromise);
295     ASSERT_TRUE(isPromise);
296 
297     // 调用notify 方法
298     status = napi_get_named_property(env, thisVar, "notifyAll", &notifyFn);
299     ASSERT_EQ(status, napi_ok);
300     status = napi_call_function(env, thisVar, notifyFn, 0, nullptr, nullptr);
301     ASSERT_EQ(status, napi_ok);
302 }
303 
TEST_F(ConditionTest,NotifyAfterEnvDestroyedTest)304 TEST_F(ConditionTest, NotifyAfterEnvDestroyedTest)
305 {
306     ConditionTest::InitializeEngine();
307     napi_env env = ConditionTest::GetEnv();
308     ASSERT_NE(env, nullptr);
309     napi_value thisVar = CreateConditionVariableInstances(env);
310     ASSERT_NE(thisVar, nullptr);
311 
312     // 调用 wait 方法
313     napi_value waitFn;
314     napi_status status = napi_get_named_property(env, thisVar, "wait", &waitFn);
315     ASSERT_EQ(status, napi_ok);
316     napi_value promise;
317     status = napi_call_function(env, thisVar, waitFn, 0, nullptr, &promise);
318     ASSERT_EQ(status, napi_ok);
319     ASSERT_TRUE(promise != nullptr);
320     bool isPromise = false;
321     napi_is_promise(env, promise, &isPromise);
322     ASSERT_TRUE(isPromise);
323 
324     std::thread t([&thisVar]() {
325         ConditionTest::InitializeEngine();
326         napi_env env = ConditionTest::GetEnv();
327         napi_value notifyFn;
328         napi_status status = napi_get_named_property(env, thisVar, "notifyOne", &notifyFn);
329         ASSERT_EQ(status, napi_ok);
330         napi_value result;
331         status = napi_call_function(env, thisVar, notifyFn, 0, nullptr, &result);
332         ASSERT_EQ(status, napi_ok);
333         ConditionTest::DestroyEngine();
334     });
335     t.join();
336 
337     napi_value notifyFn;
338     status = napi_get_named_property(env, thisVar, "notifyAll", &notifyFn);
339     ASSERT_EQ(status, napi_ok);
340     status = napi_call_function(env, thisVar, notifyFn, 0, nullptr, nullptr);
341     ASSERT_EQ(status, napi_ok);
342 }
343 
TEST_F(ConditionTest,NotifyOneAfterEnvDestroyedTest)344 TEST_F(ConditionTest, NotifyOneAfterEnvDestroyedTest)
345 {
346     ConditionTest::InitializeEngine();
347     napi_env env = ConditionTest::GetEnv();
348     ASSERT_NE(env, nullptr);
349     napi_value thisVar = CreateConditionVariableInstances(env);
350     ASSERT_NE(thisVar, nullptr);
351 
352     // 调用 wait 方法
353     napi_value waitFn;
354     napi_status status = napi_get_named_property(env, thisVar, "waitFor", &waitFn);
355     ASSERT_EQ(status, napi_ok);
356     napi_value promise;
357     napi_value milliseconds = nullptr;
358     double millis = 500;
359     napi_create_double(env, millis, &milliseconds);
360     napi_value argv[] = {milliseconds};
361     status = napi_call_function(env, thisVar, waitFn, 1, argv, &promise);
362     ASSERT_EQ(status, napi_ok);
363     ASSERT_TRUE(promise != nullptr);
364     bool isPromise = false;
365     napi_is_promise(env, promise, &isPromise);
366     ASSERT_TRUE(isPromise);
367 
368     std::thread t([&thisVar]() {
369         ConditionTest::InitializeEngine();
370         napi_env env = ConditionTest::GetEnv();
371         napi_value notifyFn;
372         napi_status status = napi_get_named_property(env, thisVar, "notifyOne", &notifyFn);
373         ASSERT_EQ(status, napi_ok);
374         napi_value result;
375         status = napi_call_function(env, thisVar, notifyFn, 0, nullptr, &result);
376         ASSERT_EQ(status, napi_ok);
377         ConditionTest::DestroyEngine();
378     });
379     t.join();
380 }
381