1 /*
2 * Copyright (c) 2025 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 "hpae_no_lock_queue.h"
18 #include <atomic>
19 #include <thread>
20
21 using namespace testing::ext;
22 using namespace testing;
23
24 namespace OHOS {
25 namespace AudioStandard {
26 namespace HPAE {
27
28 static constexpr size_t TEST_QUEUE_SIZE = 5;
29 static constexpr size_t TEST_QUEUE_SIZE_THREE = 3;
30 static constexpr uint32_t NUM_TWO = 2;
31 static constexpr uint32_t NUM_THREE = 3;
32
33 class HpaeNoLockQueueTest : public ::testing::Test {
34 protected:
SetUp()35 void SetUp() override
36 {
37 queue_ = std::make_unique<HpaeNoLockQueue>(TEST_QUEUE_SIZE);
38 processed_count_ = 0;
39 }
40
41 std::unique_ptr<HpaeNoLockQueue> queue_;
42 std::atomic<int> processed_count_;
43 };
44
CreateCountingRequest(std::atomic<int> * count)45 auto CreateCountingRequest(std::atomic<int>* count)
46 {
47 return [count]() { (*count)++; };
48 }
49
50 HWTEST_F(HpaeNoLockQueueTest, queueConstructorInitialization, TestSize.Level0)
51 {
52 HpaeNoLockQueue queue(TEST_QUEUE_SIZE);
53 EXPECT_TRUE(queue.IsFinishProcess());
54 HpaeNoLockQueue empty_queue(0);
55 EXPECT_FALSE(empty_queue.IsFinishProcess());
56 }
57
58 HWTEST_F(HpaeNoLockQueueTest, pushRequestNormalOperation, TestSize.Level0)
59 {
60 std::atomic<int> gCount = 0;
__anon163482b60202() 61 auto countingRequest = [&gCount]() { gCount++; };
62 HpaeNoLockQueue queue(TEST_QUEUE_SIZE);
63 for (int i = 0; i < TEST_QUEUE_SIZE; ++i) {
64 queue.PushRequest(countingRequest);
65 }
66 queue.HandleRequests();
67 EXPECT_EQ(gCount, TEST_QUEUE_SIZE);
68 }
69
70 HWTEST_F(HpaeNoLockQueueTest, pushRequestCapacityLimit, TestSize.Level0)
71 {
72 std::atomic<int> gCount = 0;
__anon163482b60302() 73 auto countingRequest = [&gCount]() { gCount++; };
74 HpaeNoLockQueue queue(TEST_QUEUE_SIZE_THREE);
75 for (int i = 0; i < TEST_QUEUE_SIZE_THREE; ++i) {
76 queue.PushRequest(countingRequest);
77 }
78 queue.PushRequest(countingRequest);
79 queue.HandleRequests();
80 EXPECT_EQ(gCount, TEST_QUEUE_SIZE_THREE);
81 }
82
83 HWTEST_F(HpaeNoLockQueueTest, queueResetFunction, TestSize.Level0)
84 {
85 std::atomic<int> gCount = 0;
__anon163482b60402() 86 auto countingRequest = [&gCount]() { gCount++; };
87
88 HpaeNoLockQueue queue(TEST_QUEUE_SIZE);
89 for (int i = 0; i < TEST_QUEUE_SIZE; ++i) {
90 queue.PushRequest(countingRequest);
91 }
92 queue.Reset();
93 queue.HandleRequests();
94 EXPECT_TRUE(queue.IsFinishProcess());
95 }
96
97 HWTEST_F(HpaeNoLockQueueTest, requestExecutionOrder, TestSize.Level0)
98 {
99 std::vector<int> execution_order;
100
101 HpaeNoLockQueue queue(TEST_QUEUE_SIZE_THREE);
__anon163482b60502() 102 queue.PushRequest([&execution_order]() { execution_order.push_back(1); });
__anon163482b60602() 103 queue.PushRequest([&execution_order]() { execution_order.push_back(NUM_TWO); });
__anon163482b60702() 104 queue.PushRequest([&execution_order]() { execution_order.push_back(NUM_THREE); });
105 queue.HandleRequests();
106 ASSERT_EQ(execution_order.size(), NUM_THREE);
107 EXPECT_EQ(execution_order[0], 1);
108 EXPECT_EQ(execution_order[1], NUM_TWO);
109 EXPECT_EQ(execution_order[NUM_TWO], NUM_THREE);
110 }
111
112 HWTEST_F(HpaeNoLockQueueTest, isFinishProcessStatus, TestSize.Level0)
113 {
114 HpaeNoLockQueue queue(NUM_TWO);
115 EXPECT_TRUE(queue.IsFinishProcess());
__anon163482b60802() 116 queue.PushRequest([] () {});
117 EXPECT_FALSE(queue.IsFinishProcess());
118 queue.HandleRequests();
119 EXPECT_TRUE(queue.IsFinishProcess());
__anon163482b60902() 120 queue.PushRequest([] () {});
121 queue.Reset();
122 EXPECT_TRUE(queue.IsFinishProcess());
123 }
124
125 HWTEST_F(HpaeNoLockQueueTest, queueExhaustionBehavior, TestSize.Level0)
126 {
127 std::atomic<int> gCount = 0;
__anon163482b60a02() 128 auto countingRequest = [&gCount]() { gCount++; };
129
130 HpaeNoLockQueue queue(TEST_QUEUE_SIZE_THREE);
131 for (int i = 0; i < TEST_QUEUE_SIZE_THREE; ++i) {
132 queue.PushRequest(countingRequest);
133 }
134 queue.PushRequest(countingRequest);
135 queue.HandleRequests();
136 EXPECT_EQ(gCount, TEST_QUEUE_SIZE_THREE);
137 queue.PushRequest(countingRequest);
138 EXPECT_FALSE(queue.IsFinishProcess());
139 queue.HandleRequests();
140 EXPECT_EQ(gCount, 4); // 4: expected res
141 }
142
143 HWTEST_F(HpaeNoLockQueueTest, multiThreadedConcurrency, TestSize.Level0)
144 {
145 constexpr int threadCount = 4;
146 constexpr int requestPerThread = 100;
147
148 std::atomic<int> gCount = 0;
__anon163482b60b02() 149 auto countingRequest = [&gCount]() { gCount++; };
150
151 HpaeNoLockQueue queue(threadCount * requestPerThread + 10); // 10: additional len
152
__anon163482b60c02() 153 auto pushTask = [&queue, countingRequest]() {
154 for (int i = 0; i < requestPerThread; ++i) {
155 queue.PushRequest(countingRequest);
156 }
157 };
158 std::vector<std::thread> threads;
159 for (int i = 0; i < threadCount; ++i) {
160 threads.emplace_back(pushTask);
161 }
162 for (auto& thread : threads) {
163 thread.join();
164 }
165 queue.HandleRequests();
166 EXPECT_EQ(gCount, threadCount * requestPerThread);
167 EXPECT_TRUE(queue.IsFinishProcess());
168 }
169
170 HWTEST_F(HpaeNoLockQueueTest, maximumRequestCountHandling, TestSize.Level0)
171 {
172 constexpr size_t largeSize = 10000;
173 HpaeNoLockQueue large_queue(largeSize);
174 std::atomic<int> gCount = 0;
__anon163482b60d02() 175 auto countingRequest = [&gCount]() { gCount++; };
176
177 for (size_t i = 0; i < largeSize; ++i) {
178 large_queue.PushRequest(countingRequest);
179 }
180 large_queue.PushRequest(countingRequest);
181 large_queue.HandleRequests();
182 EXPECT_EQ(static_cast<size_t>(gCount), largeSize);
183 }
184
185 HWTEST_F(HpaeNoLockQueueTest, mixedOperations, TestSize.Level0)
186 {
187 std::atomic<int> gCount = 0;
__anon163482b60e02() 188 auto countingRequest = [&gCount]() { gCount++; };
189
190 HpaeNoLockQueue queue(10); // 10: queue size
191 for (int i = 0; i < TEST_QUEUE_SIZE; ++i) {
192 queue.PushRequest(countingRequest);
193 }
194 queue.HandleRequests();
195 EXPECT_EQ(gCount, TEST_QUEUE_SIZE);
196 queue.Reset();
197 EXPECT_TRUE(queue.IsFinishProcess());
198 for (int i = 0; i < TEST_QUEUE_SIZE_THREE; ++i) {
199 queue.PushRequest(countingRequest);
200 }
201 queue.HandleRequests();
202 EXPECT_EQ(gCount, 8); // 8: expected res
203 }
204 } // namespace HPAE
205 } // namespace AudioStandard
206 } // namespace OHOS