1 /*
2 * Copyright (c) 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 <thread>
17 #include <gtest/gtest.h>
18 #include "audio_utils.h"
19
20 using namespace testing::ext;
21 using namespace std;
22 namespace OHOS {
23 namespace AudioStandard {
24
25 constexpr int32_t SUCCESS = 0;
26 constexpr unsigned int QUEUE_SLOTS = 10;
27 constexpr unsigned int THREAD_NUM = QUEUE_SLOTS + 1;
28 class AudioUtilsUnitTest : public testing::Test {
29 public:
30 static void SetUpTestCase(void);
31 static void TearDownTestCase(void);
32 void SetUp();
33 void TearDown();
34 };
35
SetUpTestCase(void)36 void AudioUtilsUnitTest::SetUpTestCase(void)
37 {
38 // input testsuit setup step,setup invoked before all testcases
39 }
40
TearDownTestCase(void)41 void AudioUtilsUnitTest::TearDownTestCase(void)
42 {
43 // input testsuit teardown step,teardown invoked after all testcases
44 }
45
SetUp(void)46 void AudioUtilsUnitTest::SetUp(void)
47 {
48 // input testcase setup step,setup invoked before each testcases
49 }
50
TearDown(void)51 void AudioUtilsUnitTest::TearDown(void)
52 {
53 // input testcase teardown step,teardown invoked after each testcases
54 }
55
56 /**
57 * @tc.name : Test ClockTime API
58 * @tc.type : FUNC
59 * @tc.number: ClockTime_001
60 * @tc.desc : Test ClockTime interface.
61 */
62 HWTEST(AudioUtilsUnitTest, ClockTime_001, TestSize.Level1)
63 {
64 const int64_t CLOCK_TIME = 0;
65 int32_t ret = -1;
66 ret = ClockTime::AbsoluteSleep(CLOCK_TIME);
67 EXPECT_EQ(SUCCESS - 1, ret);
68
69 int64_t nanoTime = 1000;
70 ret = ClockTime::AbsoluteSleep(nanoTime);
71 EXPECT_EQ(SUCCESS, ret);
72
73 ret = ClockTime::RelativeSleep(CLOCK_TIME);
74 EXPECT_EQ(SUCCESS - 1, ret);
75
76 ret = ClockTime::RelativeSleep(nanoTime);
77 EXPECT_EQ(SUCCESS, ret);
78 }
79
80 /**
81 * @tc.name : Test Trace API
82 * @tc.type : FUNC
83 * @tc.number: Trace_001
84 * @tc.desc : Test Trace interface.
85 */
86 HWTEST(AudioUtilsUnitTest, Trace_001, TestSize.Level1)
87 {
88 std::string value = "Test";
89 std::shared_ptr<Trace> trace = std::make_shared<Trace>(value);
90 trace->End();
91 int64_t count = 1;
92 Trace::Count(value, count);
93 }
94
95 /**
96 * @tc.name : Test PermissionUtil API
97 * @tc.type : FUNC
98 * @tc.number: PermissionUtil_001
99 * @tc.desc : Test PermissionUtil interface.
100 */
101 HWTEST(AudioUtilsUnitTest, PermissionUtil_001, TestSize.Level1)
102 {
103 bool ret1 = PermissionUtil::VerifyIsSystemApp();
104 EXPECT_EQ(false, ret1);
105 bool ret2 = PermissionUtil::VerifySelfPermission();
106 EXPECT_EQ(true, ret2);
107 bool ret3 = PermissionUtil::VerifySystemPermission();
108 EXPECT_EQ(true, ret3);
109 }
110
111 /**
112 * @tc.name : Test AdjustStereoToMonoForPCM API
113 * @tc.type : FUNC
114 * @tc.number: AdjustStereoToMonoForPCM_001
115 * @tc.desc : Test AdjustStereoToMonoForPCM interface.
116 */
117 HWTEST(AudioUtilsUnitTest, AdjustStereoToMonoForPCM_001, TestSize.Level1)
118 {
119 uint64_t len = 2;
120
121 const int8_t BitRET = 1;
122 int8_t arr1[2] = {1, 2};
123 int8_t *data1 = &arr1[0];
124 AdjustStereoToMonoForPCM8Bit(data1, len);
125 EXPECT_EQ(BitRET, data1[0]);
126 EXPECT_EQ(BitRET, data1[1]);
127
128 len = 4;
129 const int16_t Bit16RET = 1;
130 int16_t arr2[2] = {1, 2};
131 int16_t *data2 = &arr2[0];
132 AdjustStereoToMonoForPCM16Bit(data2, len);
133 EXPECT_EQ(Bit16RET, data2[0]);
134 EXPECT_EQ(Bit16RET, data2[1]);
135
136 len = 8;
137 const int32_t Bit32RET = 1;
138 int32_t arr4[2] = {1, 2};
139 int32_t *data4 = &arr4[0];
140 AdjustStereoToMonoForPCM32Bit(data4, len);
141 EXPECT_EQ(Bit32RET, data4[0]);
142 EXPECT_EQ(Bit32RET, data4[1]);
143 }
144
145 /**
146 * @tc.name : Test AdjustAudioBalanceForPCM API
147 * @tc.type : FUNC
148 * @tc.number: AdjustAudioBalanceForPCM_001
149 * @tc.desc : Test AdjustAudioBalanceForPCM interface.
150 */
151 HWTEST(AudioUtilsUnitTest, AdjustAudioBalanceForPCM_001, TestSize.Level1)
152 {
153 float left = 2.0;
154 float right = 2.0;
155 uint64_t len = 2;
156
157 const int8_t Bit8RET1 = 2;
158 const int8_t Bit8RET2 = 4;
159 int8_t arr1[2] = {1, 2};
160 int8_t *data1 = &arr1[0];
161 AdjustAudioBalanceForPCM8Bit(data1, len, left, right);
162 EXPECT_EQ(Bit8RET1, data1[0]);
163 EXPECT_EQ(Bit8RET2, data1[1]);
164
165 len = 4;
166 const int16_t Bit16RET1 = 2;
167 const int16_t Bit16RET2 = 4;
168 int16_t arr2[2] = {1, 2};
169 int16_t *data2 = &arr2[0];
170 AdjustAudioBalanceForPCM16Bit(data2, len, left, right);
171 EXPECT_EQ(Bit16RET1, data2[0]);
172 EXPECT_EQ(Bit16RET2, data2[1]);
173
174 len = 8;
175 const int32_t Bit32RET = 2;
176 int32_t arr4[2] = {1, 2};
177 int32_t *data4 = &arr4[0];
178 AdjustAudioBalanceForPCM32Bit(data4, len, left, right);
179 EXPECT_EQ(Bit32RET, data4[0]);
180 EXPECT_EQ(Bit32RET * 2, data4[1]);
181 }
182
183 /**
184 * @tc.name : Test GetSysPara API
185 * @tc.type : FUNC
186 * @tc.number: GetSysPara_001
187 * @tc.desc : Test GetSysPara interface.
188 */
189 HWTEST(AudioUtilsUnitTest, GetSysPara_001, TestSize.Level1)
190 {
191 const char *invaildKey = nullptr;
192 int32_t value32 = 2;
193 bool result = GetSysPara(invaildKey, value32);
194 EXPECT_EQ(false, result);
195 const char *key = "debug.audio_service.testmodeon";
196 bool result1 = GetSysPara(key, value32);
197 EXPECT_EQ(true, result1);
198 uint32_t valueU32 = 3;
199 bool result2 = GetSysPara(key, valueU32);
200 EXPECT_EQ(true, result2);
201 int64_t value64 = 0;
202 bool result3 = GetSysPara(key, value64);
203 EXPECT_EQ(true, result3);
204 std::string strValue = "100";
205 bool result4 = GetSysPara(key, strValue);
206 EXPECT_EQ(true, result4);
207 }
208
209 class DemoThreadData {
210 public:
DemoThreadData()211 DemoThreadData()
212 {
213 putStatus = false;
214 getStatus = false;
215 }
216 bool putStatus;
217 bool getStatus;
218 static AudioSafeBlockQueue<int> shareQueue;
219
Put(int j)220 void Put(int j)
221 {
222 shareQueue.Push(j);
223 putStatus = true;
224 }
225
Get()226 void Get()
227 {
228 shareQueue.Pop();
229 getStatus = true;
230 }
231 };
232
233 AudioSafeBlockQueue<int> DemoThreadData::shareQueue(QUEUE_SLOTS);
234
PutHandleThreadData(DemoThreadData & q,int i)235 void PutHandleThreadData(DemoThreadData& q, int i)
236 {
237 q.Put(i);
238 }
239
GetThreadDatePushedStatus(std::array<DemoThreadData,THREAD_NUM> & demoDatas,unsigned int & pushedIn,unsigned int & unpushedIn)240 void GetThreadDatePushedStatus(std::array<DemoThreadData, THREAD_NUM>& demoDatas, unsigned int& pushedIn,
241 unsigned int& unpushedIn)
242 {
243 pushedIn = 0;
244 unpushedIn = 0;
245 for (auto& t : demoDatas) {
246 if (t.putStatus) {
247 pushedIn++;
248 } else {
249 unpushedIn++;
250 }
251 }
252 }
253
GetThreadDateGetedStatus(std::array<DemoThreadData,THREAD_NUM> & demoDatas,unsigned int & getedOut,unsigned int & ungetedOut)254 void GetThreadDateGetedStatus(std::array<DemoThreadData, THREAD_NUM>& demoDatas,
255 unsigned int& getedOut, unsigned int& ungetedOut)
256 {
257 getedOut = 0;
258 ungetedOut = 0;
259 for (auto& t : demoDatas) {
260 if (t.getStatus) {
261 getedOut++;
262 } else {
263 ungetedOut++;
264 }
265 }
266 }
267
PutHandleThreadDataTime(DemoThreadData & q,int i,std::chrono::system_clock::time_point absTime)268 void PutHandleThreadDataTime(DemoThreadData& q, int i, std::chrono::system_clock::time_point absTime)
269 {
270 cout << "thread-" << std::this_thread::get_id() << " run time: "
271 << std::chrono::system_clock::to_time_t(absTime) << endl;
272 std::this_thread::sleep_until(absTime);
273
274 q.Put(i);
275 }
276
GetHandleThreadDataTime(DemoThreadData & q,int i,std::chrono::system_clock::time_point absTime)277 void GetHandleThreadDataTime(DemoThreadData& q, int i, std::chrono::system_clock::time_point absTime)
278 {
279 cout << "thread-" << std::this_thread::get_id() << " run time: "
280 << std::chrono::system_clock::to_time_t(absTime) << endl;
281 std::this_thread::sleep_until(absTime);
282
283 q.Get();
284 }
285
286 /*
287 * @tc.name: testPut001
288 * @tc.desc: Single-threaded call put and get to determine that the normal scenario
289 */
290 HWTEST(AudioUtilsUnitTest, testPut001, TestSize.Level0)
291 {
292 AudioSafeBlockQueue<int> qi(10);
293 int i = 1;
294 qi.Push(i);
295 EXPECT_EQ(static_cast<unsigned>(1), qi.Size());
296 }
297
298 /*
299 * @tc.name: testGet001
300 * @tc.desc: Single-threaded call put and get to determine that the normal scenario
301 */
302 HWTEST(AudioUtilsUnitTest, testGet001, TestSize.Level0)
303 {
304 AudioSafeBlockQueue<int> qi(10);
305 for (int i = 0; i < 3; i++) {
306 qi.Push(i);
307 }
308 EXPECT_EQ(static_cast<unsigned>(3), qi.Size());
309 int t = qi.Pop();
310 ASSERT_EQ(t, 0);
311 }
312
ThreadsJoin(std::thread (& threads)[THREAD_NUM])313 static void ThreadsJoin(std::thread (&threads)[THREAD_NUM])
314 {
315 for (auto& t : threads) {
316 t.join();
317 }
318 }
319
CheckFullQueueStatus(std::array<DemoThreadData,THREAD_NUM> & demoDatas,unsigned int & pushedIn,unsigned int & unpushedIn,unsigned int & getedOut,unsigned int & ungetedOut)320 static void CheckFullQueueStatus(std::array<DemoThreadData, THREAD_NUM>& demoDatas, unsigned int& pushedIn,
321 unsigned int& unpushedIn, unsigned int& getedOut, unsigned int& ungetedOut)
322 {
323 ASSERT_TRUE(DemoThreadData::shareQueue.IsFull());
324 GetThreadDatePushedStatus(demoDatas, pushedIn, unpushedIn);
325 GetThreadDateGetedStatus(demoDatas, getedOut, ungetedOut);
326 ASSERT_EQ(pushedIn, THREAD_NUM);
327 ASSERT_EQ(getedOut, THREAD_NUM - QUEUE_SLOTS);
328 }
329
330 /*
331 * @tc.name: testMutilthreadPutAndBlock001
332 * @tc.desc: Multiple threads put until blocking runs, one thread gets, all threads finish running normally
333 */
334 HWTEST(AudioUtilsUnitTest, testMutilthreadPutAndBlock001, TestSize.Level0)
335 {
336 std::thread threads[THREAD_NUM];
337
338 std::array<DemoThreadData, THREAD_NUM> demoDatas;
339 demoDatas.fill(DemoThreadData());
340
341 for (unsigned int i = 0; i < THREAD_NUM; i++) {
342 threads[i] = std::thread(PutHandleThreadData, std::ref(demoDatas[i]), i);
343 }
344
345 // 1. queue is full and some threads is blocked
346 std::this_thread::sleep_for(std::chrono::seconds(2));
347 ASSERT_TRUE(DemoThreadData::shareQueue.IsFull());
348
349 unsigned int pushedIn = 0, unpushedIn = 0, getedOut = 0, ungetedOut = 0;
350 GetThreadDatePushedStatus(demoDatas, pushedIn, unpushedIn);
351
352 ASSERT_EQ(pushedIn, QUEUE_SLOTS);
353 ASSERT_EQ(unpushedIn, THREAD_NUM - QUEUE_SLOTS);
354
355 // 2. get one out and wait some put in
356 for (unsigned int i = 0; i < THREAD_NUM - QUEUE_SLOTS; i++) {
357 demoDatas[0].Get();
358 }
359
360 std::this_thread::sleep_for(std::chrono::seconds(2));
361 // queue is full and some threads is blocked and is not joined
362 CheckFullQueueStatus(demoDatas, pushedIn, unpushedIn, getedOut, ungetedOut);
363 ThreadsJoin(threads);
364
365 while (!DemoThreadData::shareQueue.IsEmpty()) {
366 demoDatas[0].Get();
367 }
368
369 // here means all thread end ok or if some operation blocked and the testcase blocked
370 }
371
GetTimeAddTwoSeconds()372 static std::time_t GetTimeAddTwoSeconds()
373 {
374 using std::chrono::system_clock;
375 std::time_t timeT = system_clock::to_time_t(system_clock::now());
376 cout << "start time: " << timeT << endl;
377 const int twoSec = 2;
378 timeT += twoSec;
379 return timeT;
380 }
381
382 /*
383 * @tc.name: testMutilthreadConcurrentPutAndBlockInblankqueue001
384 * @tc.desc: Multi-threaded put() on the empty queue. When n threads are waiting to reach a certain
385 * time-point, everyone puts concurrent to see the status of the queue and the state of the thread.
386 */
387 HWTEST(AudioUtilsUnitTest, testMutilthreadConcurrentPutAndBlockInblankqueue001, TestSize.Level0)
388 {
389 // 1. prepare
390 std::thread threads[THREAD_NUM];
391 std::array<DemoThreadData, THREAD_NUM> demoDatas;
392 demoDatas.fill(DemoThreadData());
393
394 using std::chrono::system_clock;
395
396 std::time_t timeT = GetTimeAddTwoSeconds();
397 // 2. start thread
398 ASSERT_TRUE(DemoThreadData::shareQueue.IsEmpty());
399 for (unsigned int i = 0; i < THREAD_NUM; i++) {
400 threads[i] = std::thread(PutHandleThreadDataTime, std::ref(demoDatas[i]), i, system_clock::from_time_t(timeT));
401 }
402
403 // 1. queue is full and some threads is blocked
404 std::this_thread::sleep_for(std::chrono::seconds(4));
405 ASSERT_TRUE(DemoThreadData::shareQueue.IsFull());
406
407 unsigned int pushedIn = 0;
408 unsigned int unpushedIn = 0;
409 unsigned int getedOut = 0;
410 unsigned int ungetedOut = 0;
411 GetThreadDatePushedStatus(demoDatas, pushedIn, unpushedIn);
412
413 ASSERT_EQ(pushedIn, QUEUE_SLOTS);
414 ASSERT_EQ(unpushedIn, THREAD_NUM - QUEUE_SLOTS);
415
416 // 2. get one out and wait some put in
417 for (unsigned int i = 0; i < THREAD_NUM - QUEUE_SLOTS; i++) {
418 demoDatas[0].Get();
419 }
420
421 std::this_thread::sleep_for(std::chrono::seconds(2));
422 // queue is full and some threads is blocked and is not joined
423 CheckFullQueueStatus(demoDatas, pushedIn, unpushedIn, getedOut, ungetedOut);
424 ThreadsJoin(threads);
425
426 while (!DemoThreadData::shareQueue.IsEmpty()) {
427 demoDatas[0].Get();
428 }
429 // here means all thread end ok or if some operation blocked and the testcase blocked
430 }
431
QueuePushInfull()432 static void QueuePushInfull()
433 {
434 for (unsigned int i = 0; i < QUEUE_SLOTS; i++) {
435 int t = i;
436 DemoThreadData::shareQueue.Push(t);
437 }
438 }
439
QueuePushInnotfull(const unsigned int remain)440 static void QueuePushInnotfull(const unsigned int remain)
441 {
442 for (unsigned int i = 0; i < QUEUE_SLOTS - remain; i++) {
443 int t = i;
444 DemoThreadData::shareQueue.Push(t);
445 }
446 }
447
448 /*
449 * @tc.name: testMutilthreadConcurrentPutAndBlockInfullqueue001
450 * @tc.desc: Multi-threaded put() on the full queue. When n threads are waiting to reach a certain
451 * time-point, everyone puts concurrent to see the status of the queue and the state of the thread.
452 */
453 HWTEST(AudioUtilsUnitTest, testMutilthreadConcurrentPutAndBlockInfullqueue001, TestSize.Level0)
454 {
455 // 1. prepare
456 std::thread threads[THREAD_NUM];
457 std::array<DemoThreadData, THREAD_NUM> demoDatas;
458 demoDatas.fill(DemoThreadData());
459
460 using std::chrono::system_clock;
461
462 std::time_t timeT = GetTimeAddTwoSeconds();
463 ASSERT_TRUE(DemoThreadData::shareQueue.IsEmpty());
464 QueuePushInfull();
465 ASSERT_TRUE(DemoThreadData::shareQueue.IsFull());
466
467 // 2. start thread put in full queue
468 for (unsigned int i = 0; i < THREAD_NUM; i++) {
469 threads[i] = std::thread(PutHandleThreadDataTime, std::ref(demoDatas[i]), i, system_clock::from_time_t(timeT));
470 }
471
472 std::this_thread::sleep_for(std::chrono::seconds(3));
473 // 3. now thread is running and all is blocked
474 unsigned int pushedIn = 0;
475 unsigned int unpushedIn = 0;
476 GetThreadDatePushedStatus(demoDatas, pushedIn, unpushedIn);
477 ASSERT_EQ(pushedIn, static_cast<unsigned int>(0));
478 ASSERT_EQ(unpushedIn, THREAD_NUM);
479 ASSERT_TRUE(DemoThreadData::shareQueue.IsFull());
480 for (unsigned int i = 0; i < THREAD_NUM; i++) {
481 cout << "get out one and then the queue is full" << endl;
482 DemoThreadData::shareQueue.Pop();
483 std::this_thread::sleep_for(std::chrono::seconds(1));
484 ASSERT_TRUE(DemoThreadData::shareQueue.IsFull());
485 GetThreadDatePushedStatus(demoDatas, pushedIn, unpushedIn);
486 ASSERT_EQ(pushedIn, i + 1);
487 ASSERT_EQ(unpushedIn, THREAD_NUM - (i + 1));
488 }
489
490 ThreadsJoin(threads);
491 while (!DemoThreadData::shareQueue.IsEmpty()) {
492 demoDatas[0].Get();
493 }
494 }
495
496 /*
497 * @tc.name: testMutilthreadConcurrentGetAndBlockInblankqueue001
498 * @tc.desc: Multi-threaded get() on the empty queue. When n threads are waiting to reach a certain
499 * time-point, everyone gets concurrent to see the status of the queue and the state of the thread.
500 */
501 HWTEST(AudioUtilsUnitTest, testMutilthreadConcurrentGetAndBlockInblankqueue001, TestSize.Level0)
502 {
503 // 1. prepare
504 std::thread threads[THREAD_NUM];
505 std::array<DemoThreadData, THREAD_NUM> demoDatas;
506 demoDatas.fill(DemoThreadData());
507
508 using std::chrono::system_clock;
509
510 std::time_t timeT = GetTimeAddTwoSeconds();
511 ASSERT_TRUE(DemoThreadData::shareQueue.IsEmpty());
512
513 // 2. start thread put in empty queue
514 for (unsigned int i = 0; i < THREAD_NUM; i++) {
515 threads[i] = std::thread(GetHandleThreadDataTime,
516 std::ref(demoDatas[i]), i, system_clock::from_time_t(timeT));
517 }
518 std::this_thread::sleep_for(std::chrono::seconds(3));
519
520 // 3. now thread is running and all is blocked
521 unsigned int getedOut = 0;
522 unsigned int ungetedOut = 0;
523 GetThreadDateGetedStatus(demoDatas, getedOut, ungetedOut);
524 ASSERT_EQ(getedOut, static_cast<unsigned int>(0));
525 ASSERT_EQ(ungetedOut, THREAD_NUM);
526 ASSERT_TRUE(DemoThreadData::shareQueue.IsEmpty());
527
528 int value = 1;
529
530 for (unsigned int i = 0; i < THREAD_NUM; i++) {
531 cout << "put in one and then the queue is empty" << endl;
532 DemoThreadData::shareQueue.Push(value);
533 std::this_thread::sleep_for(std::chrono::seconds(1));
534 ASSERT_TRUE(DemoThreadData::shareQueue.IsEmpty());
535 GetThreadDateGetedStatus(demoDatas, getedOut, ungetedOut);
536 ASSERT_EQ(getedOut, i + 1);
537 ASSERT_EQ(ungetedOut, THREAD_NUM - (i + 1));
538 }
539
540 ThreadsJoin(threads);
541 while (!DemoThreadData::shareQueue.IsEmpty()) {
542 demoDatas[0].Get();
543 }
544 }
545 /*
546 * @tc.name: testMutilthreadConcurrentGetAndBlockInfullqueue001
547 * @tc.desc: Multi-threaded get() on the full queue. When n threads are waiting to reach a certain
548 * time-point, everyone gets concurrent to see the status of the queue and the state of the thread.
549 */
550 HWTEST(AudioUtilsUnitTest, testMutilthreadConcurrentGetAndBlockInfullqueue001, TestSize.Level0)
551 {
552 // 1. prepare
553 std::thread threads[THREAD_NUM];
554 std::array<DemoThreadData, THREAD_NUM> demoDatas;
555 demoDatas.fill(DemoThreadData());
556
557 using std::chrono::system_clock;
558
559 std::time_t timeT = GetTimeAddTwoSeconds();
560 ASSERT_TRUE(DemoThreadData::shareQueue.IsEmpty());
561 int t = 1;
562 for (unsigned int i = 0; i < QUEUE_SLOTS; i++) {
563 DemoThreadData::shareQueue.Push(t);
564 }
565 ASSERT_TRUE(DemoThreadData::shareQueue.IsFull());
566
567 // 2. start thread put in full queue
568 for (unsigned int i = 0; i < THREAD_NUM; i++) {
569 threads[i] = std::thread(GetHandleThreadDataTime, std::ref(demoDatas[i]), i, system_clock::from_time_t(timeT));
570 }
571
572 std::this_thread::sleep_for(std::chrono::seconds(4));
573 // 3. start judge
574 ASSERT_TRUE(DemoThreadData::shareQueue.IsEmpty());
575
576 unsigned int getedOut = 0;
577 unsigned int ungetedOut = 0;
578 GetThreadDateGetedStatus(demoDatas, getedOut, ungetedOut);
579
580 ASSERT_EQ(getedOut, QUEUE_SLOTS);
581 ASSERT_EQ(ungetedOut, THREAD_NUM - QUEUE_SLOTS);
582
583 // 2. put one in and wait some get out
584 for (unsigned int i = 0; i < THREAD_NUM - QUEUE_SLOTS; i++) {
585 demoDatas[0].Put(t);
586 }
587
588 std::this_thread::sleep_for(std::chrono::seconds(2));
589 // queue is full and some threads is blocked and is not joined
590 ASSERT_TRUE(DemoThreadData::shareQueue.IsEmpty());
591 GetThreadDateGetedStatus(demoDatas, getedOut, ungetedOut);
592 ASSERT_EQ(getedOut, THREAD_NUM);
593 ASSERT_EQ(ungetedOut, static_cast<unsigned int>(0));
594
595 ThreadsJoin(threads);
596 while (!DemoThreadData::shareQueue.IsEmpty()) {
597 demoDatas[0].Get();
598 }
599 }
600
601 /*
602 * @tc.name: testMutilthreadConcurrentGetAndBlockInnotfullqueue001
603 * @tc.desc: Multi-threaded get() on the notfull queue. When n threads are waiting to reach a certain
604 * time-point, everyone get concurrent to see the status of the queue and the state of the thread.
605 */
606 HWTEST(AudioUtilsUnitTest, testMutilthreadConcurrentGetAndBlockInnotfullqueue001, TestSize.Level0)
607 {
608 // 1. prepare
609 std::thread threads[THREAD_NUM];
610 std::array<DemoThreadData, THREAD_NUM> demoDatas;
611 demoDatas.fill(DemoThreadData());
612
613 using std::chrono::system_clock;
614
615 const unsigned int REMAIN_SLOTS = 5;
616 std::time_t timeT = GetTimeAddTwoSeconds();
617 ASSERT_TRUE(DemoThreadData::shareQueue.IsEmpty());
618 QueuePushInnotfull(REMAIN_SLOTS);
619
620 // 2. start thread put in not full queue
621 for (unsigned int i = 0; i < THREAD_NUM; i++) {
622 threads[i] = std::thread(GetHandleThreadDataTime,
623 std::ref(demoDatas[i]), i, system_clock::from_time_t(timeT));
624 }
625
626 std::this_thread::sleep_for(std::chrono::seconds(3));
627
628 unsigned int getedOut = 0;
629 unsigned int ungetedOut = 0;
630 GetThreadDateGetedStatus(demoDatas, getedOut, ungetedOut);
631 ASSERT_EQ(getedOut, QUEUE_SLOTS - REMAIN_SLOTS);
632 ASSERT_EQ(ungetedOut, THREAD_NUM - (QUEUE_SLOTS - REMAIN_SLOTS));
633
634 // 3. put ungetedOut
635 for (unsigned int i = 0; i < ungetedOut; i++) {
636 int t = i;
637 DemoThreadData::shareQueue.Push(t);
638 }
639
640 std::this_thread::sleep_for(std::chrono::seconds(1));
641 GetThreadDateGetedStatus(demoDatas, getedOut, ungetedOut);
642 ASSERT_EQ(getedOut, THREAD_NUM);
643 ASSERT_EQ(ungetedOut, static_cast<unsigned int>(0));
644
645 ThreadsJoin(threads);
646 while (!DemoThreadData::shareQueue.IsEmpty()) {
647 demoDatas[0].Get();
648 }
649 }
650
651 /*
652 * @tc.name: testMutilthreadConcurrentPutAndBlockInnotfullqueue001
653 * @tc.desc: Multi-threaded put() on the not full queue. When n threads are waiting to reach a certain
654 * time-point, everyone puts concurrent to see the status of the queue and the state of the thread.
655 */
656 HWTEST(AudioUtilsUnitTest, testMutilthreadConcurrentPutAndBlockInnotfullqueue001, TestSize.Level0)
657 {
658 // 1. prepare
659 std::thread threads[THREAD_NUM];
660 std::array<DemoThreadData, THREAD_NUM> demoDatas;
661 demoDatas.fill(DemoThreadData());
662
663 using std::chrono::system_clock;
664
665 const unsigned int REMAIN_SLOTS = 5;
666 std::time_t timeT = GetTimeAddTwoSeconds();
667 ASSERT_TRUE(DemoThreadData::shareQueue.IsEmpty());
668 QueuePushInnotfull(REMAIN_SLOTS);
669
670 // 2. start thread put in not full queue
671 for (unsigned int i = 0; i < THREAD_NUM; i++) {
672 threads[i] = std::thread(PutHandleThreadDataTime,
673 std::ref(demoDatas[i]), i, system_clock::from_time_t(timeT));
674 }
675
676 std::this_thread::sleep_for(std::chrono::seconds(3));
677
678 unsigned int putedin = 0;
679 unsigned int unputedin = 0;
680 GetThreadDatePushedStatus(demoDatas, putedin, unputedin);
681 ASSERT_EQ(putedin, REMAIN_SLOTS);
682 ASSERT_EQ(unputedin, THREAD_NUM - REMAIN_SLOTS);
683
684 // 3. put ungetedOut
685 for (unsigned int i = 0; i < unputedin; i++) {
686 DemoThreadData::shareQueue.Pop();
687 }
688
689 std::this_thread::sleep_for(std::chrono::seconds(1));
690 GetThreadDatePushedStatus(demoDatas, putedin, unputedin);
691 ASSERT_EQ(putedin, THREAD_NUM);
692 ASSERT_EQ(unputedin, static_cast<unsigned int>(0));
693
694 ThreadsJoin(threads);
695 while (!DemoThreadData::shareQueue.IsEmpty()) {
696 demoDatas[0].Get();
697 }
698 }
699
CheckQueueStatus(std::array<DemoThreadData,THREAD_NUM> & demoDatas)700 static void CheckQueueStatus(std::array<DemoThreadData, THREAD_NUM>& demoDatas)
701 {
702 unsigned int getedOut = 0;
703 unsigned int ungetedOut = 0;
704 unsigned int pushedIn = 0;
705 unsigned int unpushedIn = 0;
706 GetThreadDateGetedStatus(demoDatas, getedOut, ungetedOut);
707 GetThreadDatePushedStatus(demoDatas, pushedIn, unpushedIn);
708
709 ASSERT_EQ(pushedIn, THREAD_NUM);
710 ASSERT_EQ(getedOut, THREAD_NUM);
711 }
712
713 /*
714 * @tc.name: testMutilthreadConcurrentGetAndPopInblankqueue001
715 * @tc.desc: Multi-threaded put() and Multi-threaded get() on the empty queue. When all threads are waiting to reach
716 * a certain time-point, everyone run concurrently to see the status of the queue and the state of the thread.
717 */
718 HWTEST(AudioUtilsUnitTest, testMutilthreadConcurrentGetAndPopInblankqueue001, TestSize.Level0)
719 {
720 // 1. prepare
721 std::thread threadsout[THREAD_NUM];
722 std::array<DemoThreadData, THREAD_NUM> demoDatas;
723 demoDatas.fill(DemoThreadData());
724
725 std::thread threadsin[THREAD_NUM];
726
727 using std::chrono::system_clock;
728
729 std::time_t timeT = GetTimeAddTwoSeconds();
730 ASSERT_TRUE(DemoThreadData::shareQueue.IsEmpty());
731
732 // 2. start thread put and get in empty queue
733
734 for (unsigned int i = 0; i < THREAD_NUM; i++) {
735 threadsout[i] = std::thread(GetHandleThreadDataTime,
736 std::ref(demoDatas[i]), i, system_clock::from_time_t(timeT));
737 }
738
739 for (unsigned int i = 0; i < THREAD_NUM; i++) {
740 threadsin[i] = std::thread(PutHandleThreadDataTime,
741 std::ref(demoDatas[i]), i, system_clock::from_time_t(timeT));
742 }
743
744 std::this_thread::sleep_for(std::chrono::seconds(3));
745
746 ASSERT_TRUE(DemoThreadData::shareQueue.IsEmpty());
747 CheckQueueStatus(demoDatas);
748
749 ThreadsJoin(threadsout);
750 ThreadsJoin(threadsin);
751
752 while (!DemoThreadData::shareQueue.IsEmpty()) {
753 demoDatas[0].Get();
754 }
755 }
756
757 /*
758 * @tc.name: testMutilthreadConcurrentGetAndPopInfullqueue001
759 * @tc.desc: Multi-threaded put() and Multi-threaded get() on the full queue.
760 * When all threads are waiting to reach a certain
761 * time-point, everyone run concurrently to see the status of the queue and the state of the thread.
762 */
763 HWTEST(AudioUtilsUnitTest, testMutilthreadConcurrentGetAndPopInfullqueue001, TestSize.Level0)
764 {
765 // 1. prepare
766 std::thread threadsout[THREAD_NUM];
767 std::array<DemoThreadData, THREAD_NUM> demoDatas;
768 demoDatas.fill(DemoThreadData());
769
770 std::thread threadsin[THREAD_NUM];
771
772 using std::chrono::system_clock;
773
774 std::time_t timeT = GetTimeAddTwoSeconds();
775 ASSERT_TRUE(DemoThreadData::shareQueue.IsEmpty());
776 int t = 1;
777 for (unsigned int i = 0; i < QUEUE_SLOTS; i++) {
778 DemoThreadData::shareQueue.Push(t);
779 }
780 ASSERT_TRUE(DemoThreadData::shareQueue.IsFull());
781 // 2. start thread put in not full queue
782 for (unsigned int i = 0; i < THREAD_NUM; i++) {
783 threadsin[i] = std::thread(PutHandleThreadDataTime,
784 std::ref(demoDatas[i]), i, system_clock::from_time_t(timeT));
785 }
786
787 for (unsigned int i = 0; i < THREAD_NUM; i++) {
788 threadsout[i] = std::thread(GetHandleThreadDataTime,
789 std::ref(demoDatas[i]), i, system_clock::from_time_t(timeT));
790 }
791
792 std::this_thread::sleep_for(std::chrono::seconds(3));
793
794 ASSERT_TRUE(DemoThreadData::shareQueue.IsFull());
795 CheckQueueStatus(demoDatas);
796
797 ThreadsJoin(threadsout);
798 ThreadsJoin(threadsin);
799
800 while (!DemoThreadData::shareQueue.IsEmpty()) {
801 demoDatas[0].Get();
802 }
803 }
804 } // namespace AudioStandard
805 } // namespace OHOS