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 "hc_condition_test.h"
17
18 #include <hctest.h>
19 #include <parameter.h>
20 #include <pthread.h>
21 #include <securec.h>
22 #include <semaphore.h>
23 #include <stdlib.h>
24 #include <unistd.h>
25
26 #include "print_log.h"
27 #include "test_timer.h"
28
29 #ifdef __cplusplus
30 extern "C" {
31 #endif
32
33 typedef struct {
34 pthread_cond_t *cond;
35 pthread_mutex_t *mutex;
36 sem_t *sem;
37 int32_t semState;
38 int32_t condState;
39 } ThreadTestArgs;
40
41 #define REQUIRED_SEM_DEFAULT_COUNT 20
42 #define REQUIRED_SEM_COUNT 20
43 #define REQUIRED_ATTR_DEFAULT_COUNT 20
44 #define REQUIRED_ATTR_COUNT 20
45
46 /* sem_wait thread test */
ThreadSemWait(void * args)47 static void *ThreadSemWait(void *args)
48 {
49 LOGI("into ThreadSemWait");
50 int res;
51 ThreadTestArgs *semArgs = (ThreadTestArgs *)args;
52 TEST_ASSERT_NOT_NULL(semArgs->sem);
53 TEST_ASSERT_NOT_EQUAL(0, semArgs->semState);
54 RUN_AND_PRINT_ELAPSED_TIME(res, sem_wait((sem_t *)semArgs->sem));
55 // after sem_post
56 LOGI("sem_wait result = %d", res);
57 TEST_ASSERT_EQUAL(0, res);
58 semArgs->semState = 0;
59 return args;
60 }
61
62 /* sem_post thread test */
ThreadSemPost(void * args)63 static void *ThreadSemPost(void *args)
64 {
65 LOGI("into ThreadSemPost");
66 int res;
67 ThreadTestArgs *semArgs = (ThreadTestArgs *)args;
68 TEST_ASSERT_NOT_NULL(semArgs->sem);
69 RUN_AND_PRINT_ELAPSED_TIME(res, sem_post((sem_t *)semArgs->sem));
70 LOGI("sem_post result = %d", res);
71 TEST_ASSERT_EQUAL(0, res);
72 return args;
73 }
74
75 /* pthread_cond_wait thread test */
ThreadCondWait(void * args)76 static void *ThreadCondWait(void *args)
77 {
78 LOGI("into ThreadCondWait");
79 int res;
80 ThreadTestArgs *condArgs = (ThreadTestArgs *)args;
81 TEST_ASSERT_NOT_NULL(condArgs->cond);
82 TEST_ASSERT_NOT_NULL(condArgs->mutex);
83 TEST_ASSERT_NOT_EQUAL(0, condArgs->condState);
84 RUN_AND_PRINT_ELAPSED_TIME(res, pthread_cond_wait(condArgs->cond, condArgs->mutex));
85 // after pthread_cond_signal
86 LOGI("pthread_cond_wait result = %d", res);
87 TEST_ASSERT_EQUAL(0, res);
88 condArgs->condState = 0;
89 return args;
90 }
91
92 /* pthread_cond_signal thread test */
ThreadCondSignal(void * args)93 static void *ThreadCondSignal(void *args)
94 {
95 LOGI("into ThreadCondSignal");
96 int res;
97 ThreadTestArgs *testArgs = (ThreadTestArgs *)args;
98 TEST_ASSERT_NOT_NULL(testArgs->cond);
99 TEST_ASSERT_NOT_NULL(testArgs->mutex);
100 RUN_AND_PRINT_ELAPSED_TIME(res, pthread_cond_signal(testArgs->cond));
101 LOGI("pthread_cond_signal result = %d", res);
102 return args;
103 }
104
105 /* sem_init and sem_destroy test */
TestSemInit(int count)106 static void TestSemInit(int count)
107 {
108 int res;
109 sem_t sem[count];
110 res = memset_s(sem, sizeof(sem), 0, sizeof(sem));
111 TEST_ASSERT_EQUAL(0, res);
112
113 for (int i = 0; i < count; ++i) {
114 RUN_AND_PRINT_ELAPSED_TIME(res, sem_init(&sem[i], 0, 0));
115 LOGI("sem_init result = %d", res);
116 TEST_ASSERT_EQUAL(0, res);
117 }
118 for (int i = 0; i < count; ++i) {
119 RUN_AND_PRINT_ELAPSED_TIME(res, sem_destroy(&sem[i]));
120 LOGI("sem_destroy result = %d", res);
121 TEST_ASSERT_EQUAL(0, res);
122 }
123 }
124
125 /* sem_wait test */
TestSemWait(int count)126 static void TestSemWait(int count)
127 {
128 int res;
129 pthread_attr_t attr;
130 pthread_t threads[count];
131
132 res = memset_s(threads, sizeof(threads), 0, sizeof(threads));
133 TEST_ASSERT_EQUAL(0, res);
134
135 sem_t sem = {0};
136 TEST_ASSERT_EQUAL(0, res);
137
138 RUN_AND_PRINT_ELAPSED_TIME(res, pthread_attr_init(&attr));
139 TEST_ASSERT_EQUAL(0, res);
140
141 for (int i = 0; i < count; ++i) {
142 RUN_AND_PRINT_ELAPSED_TIME(res, sem_init(&sem, 0, 0));
143 LOGI("sem_init result = %d", res);
144 ThreadTestArgs args = {
145 .sem = &sem,
146 .semState = -1,
147 };
148 TEST_ASSERT_EQUAL(0, res);
149 /* create phread to wait */
150 RUN_AND_PRINT_ELAPSED_TIME(res, pthread_create(&threads[i], &attr, ThreadSemWait, &args));
151 LOGI("create sem_wait thread result = %d", res);
152 int sleepSeconds = rand() % (WAIT_IN_SEM_SECONDS_MAX - WAIT_IN_SEM_SECONDS_MIN) + WAIT_IN_SEM_SECONDS_MIN;
153 sleep(sleepSeconds);
154 /* sleep seconds then create thread to post */
155 RUN_AND_PRINT_ELAPSED_TIME(res, pthread_create(&threads[i], &attr, ThreadSemPost, &args));
156 LOGI("create sem_post thread result = %d", res);
157 TEST_ASSERT_EQUAL(0, res);
158 sleep(sleepSeconds);
159 TEST_ASSERT_EQUAL(0, args.semState);
160 }
161 }
162
163 /* sem_post test */
TestSemPost(int count)164 static void TestSemPost(int count)
165 {
166 int res;
167 sem_t sem[count];
168 res = memset_s(sem, sizeof(sem), 0, sizeof(sem));
169 TEST_ASSERT_EQUAL(0, res);
170
171 for (int i = 0; i < count; ++i) {
172 RUN_AND_PRINT_ELAPSED_TIME(res, sem_init(&sem[i], 0, 0));
173 LOGI("sem_init int TestSemPost result = %d", res);
174 TEST_ASSERT_EQUAL(0, res);
175 RUN_AND_PRINT_ELAPSED_TIME(res, sem_post(&sem[i]));
176 LOGI("sem_post result = %d", res);
177 TEST_ASSERT_EQUAL(0, res);
178 }
179 for (int i = 0; i < count; ++i) {
180 RUN_AND_PRINT_ELAPSED_TIME(res, sem_post(&sem[i]));
181 LOGI("sem_post result = %d", res);
182 TEST_ASSERT_EQUAL(0, res);
183 }
184 for (int i = 0; i < count; ++i) {
185 RUN_AND_PRINT_ELAPSED_TIME(res, sem_destroy(&sem[i]));
186 LOGI("sem_destroy in TestSemPost result = %d", res);
187 TEST_ASSERT_EQUAL(0, res);
188 }
189 }
190
191 /* pthread_condattr_init and pthread_condattr_destroy test */
TestAttrConInit(int count)192 static void TestAttrConInit(int count)
193 {
194 int res;
195 pthread_condattr_t attr[count];
196 res = memset_s(attr, sizeof(attr), 0, sizeof(attr));
197 TEST_ASSERT_EQUAL(0, res);
198 for (int i = 0; i < count; ++i) {
199 RUN_AND_PRINT_ELAPSED_TIME(res, pthread_condattr_init(&attr[i]));
200 LOGI("pthread_condattr_init result = %d", res);
201 TEST_ASSERT_EQUAL(0, res);
202 }
203
204 for (int i = 0; i < count; ++i) {
205 RUN_AND_PRINT_ELAPSED_TIME(res, pthread_condattr_destroy(&attr[i]));
206 LOGI("pthread_condattr_destroy result = %d", res);
207 TEST_ASSERT_EQUAL(0, res);
208 }
209 }
210
211 /* pthread_cond_init and pthread_cond_destroy test */
TestConInit(int count)212 static void TestConInit(int count)
213 {
214 int res;
215 pthread_condattr_t attr = {0};
216 pthread_cond_t cond[count];
217 RUN_AND_PRINT_ELAPSED_TIME(res, pthread_condattr_init(&attr));
218 LOGI("pthread_condattr_init in TestConInit result = %d", res);
219 TEST_ASSERT_EQUAL(0, res);
220 res = memset_s(cond, sizeof(cond), 0, sizeof(cond));
221 TEST_ASSERT_EQUAL(0, res);
222
223 for (int i = 0; i < count; ++i) {
224 RUN_AND_PRINT_ELAPSED_TIME(res, pthread_cond_init(&cond[i], &attr));
225 LOGI("pthread_cond_init result = %d", res);
226 TEST_ASSERT_EQUAL(0, res);
227 }
228 for (int i = 0; i < count; ++i) {
229 RUN_AND_PRINT_ELAPSED_TIME(res, pthread_cond_destroy(&cond[i]));
230 LOGI("pthread_cond_destroy result = %d", res);
231 TEST_ASSERT_EQUAL(0, res);
232 }
233 }
234
235 /* pthread_cond_wait and pthread_cond_signal test */
TestConWait(int count)236 static void TestConWait(int count)
237 {
238 int res;
239 pthread_attr_t pthreadAttr;
240 pthread_condattr_t attr = {0};
241 pthread_cond_t cond;
242 pthread_mutex_t mutex;
243 pthread_t threads[count];
244 res = memset_s(&mutex, sizeof(mutex), 0, sizeof(mutex));
245 TEST_ASSERT_EQUAL(0, res);
246 res = memset_s(threads, sizeof(threads), 0, sizeof(threads));
247 TEST_ASSERT_EQUAL(0, res);
248 RUN_AND_PRINT_ELAPSED_TIME(res, pthread_attr_init(&pthreadAttr));
249 TEST_ASSERT_EQUAL(0, res);
250 // init attr and cond and mutex
251 RUN_AND_PRINT_ELAPSED_TIME(res, pthread_condattr_init(&attr));
252 LOGI("pthread_condattr_init in TestConWait result = %d", res);
253 RUN_AND_PRINT_ELAPSED_TIME(res, pthread_cond_init(&cond, &attr));
254 LOGI("pthread_cond_init in TestConWait result = %d", res);
255
256 for (int i = 0; i < count; ++i) {
257 ThreadTestArgs args = {
258 .cond = &cond,
259 .mutex = &mutex,
260 .condState = -1,
261 };
262 /* create phread to wait */
263 RUN_AND_PRINT_ELAPSED_TIME(res, pthread_create(&threads[i], &pthreadAttr, ThreadCondWait, &args));
264 LOGI("create pthread_cond_wait thread result = %d", res);
265 TEST_ASSERT_EQUAL(0, res);
266 int sleepSeconds = rand() % (WAIT_IN_SEM_SECONDS_MAX - WAIT_IN_SEM_SECONDS_MIN) + WAIT_IN_SEM_SECONDS_MIN;
267 sleep(sleepSeconds);
268 /* sleep seconds then create thread to send signal */
269 RUN_AND_PRINT_ELAPSED_TIME(res, pthread_create(&threads[i], &pthreadAttr, ThreadCondSignal, &args));
270 LOGI("create pthread_cond_signal thread result = %d", res);
271 TEST_ASSERT_EQUAL(0, res);
272 sleep(sleepSeconds);
273 TEST_ASSERT_EQUAL(0, args.condState);
274 }
275 }
276
277 /* pthread_cond_signal test */
TestConSignal(int count)278 static void TestConSignal(int count)
279 {
280 int res;
281 pthread_condattr_t attr = {0};
282 pthread_cond_t cond;
283 RUN_AND_PRINT_ELAPSED_TIME(res, pthread_cond_init(&cond, &attr));
284 LOGI("pthread_cond_init in TestConWait result = %d", res);
285 TEST_ASSERT_EQUAL(0, res);
286 for (int i = 0; i < count; ++i) {
287 RUN_AND_PRINT_ELAPSED_TIME(res, pthread_cond_signal(&cond));
288 LOGI("pthread_cond_signal result = %d", res);
289 TEST_ASSERT_EQUAL(0, res);
290 }
291 }
292
293 /* test semaphore with sem series */
TestHcSemCondition(void)294 void TestHcSemCondition(void)
295 {
296 TestSemInit(REQUIRED_SEM_DEFAULT_COUNT);
297 TestSemPost(REQUIRED_SEM_DEFAULT_COUNT);
298 TestSemWait(REQUIRED_SEM_DEFAULT_COUNT);
299 }
300
301 /* test semaphore with phread cond */
TestHcPthreadCondition(void)302 void TestHcPthreadCondition(void)
303 {
304 TestConWait(REQUIRED_ATTR_DEFAULT_COUNT);
305 TestAttrConInit(REQUIRED_ATTR_DEFAULT_COUNT);
306 TestConInit(REQUIRED_ATTR_DEFAULT_COUNT);
307 TestConSignal(REQUIRED_ATTR_DEFAULT_COUNT);
308 }
309
310 #ifdef __cplusplus
311 }
312 #endif
313