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#include <stdio.h> 16#include <string.h> 17#include <limits.h> 18#include <semaphore.h> 19#include <pthread.h> 20#include <gtest/gtest.h> 21#include "utils.h" 22#include "log.h" 23 24using namespace testing::ext; 25 26static const unsigned int KERNEL_NS_PER_SECOND = 1000000000; 27static const unsigned int KERNEL_100MS_BY_NS = 100000000; 28 29class SemTest : public::testing::Test { 30}; 31 32/** 33 * @tc.number SUB_KERNEL_IPC_SEM_INIT_0100 34 * @tc.name Use sem_init initialize the semaphore with 0 35 * @tc.desc [C- SOFTWARE -0200] 36 */ 37HWTEST_F(SemTest, testSemInitA, Function | MediumTest | Level2) 38{ 39 sem_t sem; 40 int semValue = 0; 41 int testValue = 0; 42 43 EXPECT_NE(sem_init(&sem, 0, testValue), -1) << "> sem_init errno = " << errno; 44 EXPECT_EQ(sem_getvalue(&sem, &semValue), 0) << "> sem_getvalue errno = " << errno; 45 EXPECT_TRUE(semValue == testValue); 46 EXPECT_EQ(sem_destroy(&sem), 0) << "> sem_destroy errno = " << errno; 47} 48 49/** 50 * @tc.number SUB_KERNEL_IPC_SEM_INIT_0110 51 * @tc.name Use sem_init initialize the semaphore with 1 52 * @tc.desc [C- SOFTWARE -0200] 53 */ 54HWTEST_F(SemTest, testSemInitB, Function | MediumTest | Level2) 55{ 56 sem_t sem; 57 int semValue = 0; 58 int testValue = 1; 59 60 EXPECT_NE(sem_init(&sem, 0, testValue), -1) << "> sem_init errno = " << errno; 61 EXPECT_EQ(sem_getvalue(&sem, &semValue), 0) << "> sem_getvalue errno = " << errno; 62 EXPECT_EQ(semValue, testValue); 63 EXPECT_EQ(sem_destroy(&sem), 0) << "> sem_destroy errno = " << errno; 64} 65 66/** 67 * @tc.number SUB_KERNEL_IPC_SEM_INIT_0120 68 * @tc.name Use sem_init initialize the semaphore with 100 69 * @tc.desc [C- SOFTWARE -0200] 70 */ 71HWTEST_F(SemTest, testSemInitC, Function | MediumTest | Level2) 72{ 73 sem_t sem; 74 int semValue = 0; 75 int testValue = 10; 76 77 EXPECT_NE(sem_init(&sem, 0, testValue), -1) << "> sem_init errno = " << errno; 78 EXPECT_EQ(sem_getvalue(&sem, &semValue), 0) << "> sem_getvalue errno = " << errno; 79 EXPECT_EQ(semValue, testValue); 80 EXPECT_EQ(sem_destroy(&sem), 0) << "> sem_destroy errno = " << errno; 81} 82 83/** 84 * @tc.number SUB_KERNEL_IPC_SEM_POST_0100 85 * @tc.name sem_post increases the semaphore count 86 * @tc.desc [C- SOFTWARE -0200] 87 */ 88HWTEST_F(SemTest, testSemPost, Function | MediumTest | Level2) 89{ 90 sem_t sem; 91 int semValue = 0; 92 93 ASSERT_NE(sem_init(&sem, 0, 0), -1) << "> sem_init errno = " << errno; 94 EXPECT_EQ(sem_getvalue(&sem, &semValue), 0) << "> sem_getvalue errno = " << errno; 95 EXPECT_EQ(semValue, 0); 96 97 EXPECT_EQ(sem_post(&sem), 0) << "> sem_post errno = " << errno; 98 EXPECT_EQ(sem_getvalue(&sem, &semValue), 0) << "> sem_getvalue errno = " << errno; 99 EXPECT_EQ(semValue, 1); 100 101 EXPECT_EQ(sem_post(&sem), 0) << "> sem_post errno = " << errno; 102 EXPECT_EQ(sem_post(&sem), 0) << "> sem_post errno = " << errno; 103 EXPECT_EQ(sem_getvalue(&sem, &semValue), 0) << "> sem_getvalue errno = " << errno; 104 EXPECT_EQ(semValue, 3); 105 106 EXPECT_EQ(sem_destroy(&sem), 0) << "> sem_destroy errno = " << errno; 107} 108 109/** 110 * @tc.number SUB_KERNEL_IPC_SEM_WAIT_0100 111 * @tc.name sem_wait get semaphore 112 * @tc.desc [C- SOFTWARE -0200] 113 */ 114HWTEST_F(SemTest, testSemWait, Function | MediumTest | Level2) 115{ 116 sem_t sem; 117 int semValue = 0; 118 119 ASSERT_NE(sem_init(&sem, 0, 3), -1) << "> sem_init errno = " << errno; 120 EXPECT_EQ(sem_getvalue(&sem, &semValue), 0) << "> sem_getvalue errno = " << errno; 121 EXPECT_EQ(semValue, 3); 122 123 EXPECT_EQ(sem_wait(&sem), 0) << "> sem_wait errno = " << errno; 124 EXPECT_EQ(sem_getvalue(&sem, &semValue), 0) << "> sem_getvalue errno = " << errno; 125 EXPECT_EQ(semValue, 2); 126 127 EXPECT_EQ(sem_wait(&sem), 0) << "> sem_wait errno = " << errno; 128 EXPECT_EQ(sem_wait(&sem), 0) << "> sem_wait errno = " << errno; 129 EXPECT_EQ(sem_getvalue(&sem, &semValue), 0) << "> sem_getvalue errno = " << errno; 130 EXPECT_EQ(semValue, 0); 131 132 EXPECT_EQ(sem_destroy(&sem), 0) << "> sem_destroy errno = " << errno; 133} 134 135/** 136 * @tc.number SUB_KERNEL_IPC_SEM_TRYWAIT_0100 137 * @tc.name sem_trywait get semaphore 138 * @tc.desc [C- SOFTWARE -0200] 139 */ 140HWTEST_F(SemTest, testSemTryWait, Function | MediumTest | Level2) 141{ 142 sem_t sem; 143 int semValue = 0; 144 145 ASSERT_NE(sem_init(&sem, 0, 3), -1) << "> sem_init errno = " << errno; 146 EXPECT_EQ(sem_getvalue(&sem, &semValue), 0) << "> sem_getvalue errno = " << errno; 147 EXPECT_EQ(semValue, 3); 148 149 EXPECT_EQ(sem_trywait(&sem), 0) << "> sem_trywait errno = " << errno; 150 EXPECT_EQ(sem_getvalue(&sem, &semValue), 0) << "> sem_getvalue errno = " << errno; 151 EXPECT_EQ(semValue, 2); 152 153 EXPECT_EQ(sem_trywait(&sem), 0) << "> sem_trywait errno = " << errno; 154 EXPECT_EQ(sem_trywait(&sem), 0) << "> sem_trywait errno = " << errno; 155 EXPECT_EQ(sem_getvalue(&sem, &semValue), 0) << "> sem_getvalue errno = " << errno; 156 EXPECT_EQ(semValue, 0); 157 EXPECT_EQ(sem_destroy(&sem), 0) << "> sem_destroy errno = " << errno; 158} 159 160/** 161 * @tc.number SUB_KERNEL_IPC_SEM_DESTROY_0100 162 * @tc.name check sem_destroy function 163 * @tc.desc [C- SOFTWARE -0200] 164 */ 165HWTEST_F(SemTest, testSemdestroy, Function | MediumTest | Level3) 166{ 167 sem_t sem; 168 ASSERT_EQ(sem_init(&sem, 0, 0), 0) << "> sem_init errno = " << errno; 169 EXPECT_EQ(sem_destroy(&sem), 0) << "> sem_destroy errno = " << errno; 170} 171 172void *ThreadChat(void *arg) 173{ 174 sem_t *sem = (sem_t*)arg; 175 int semValue = 0; 176 177 EXPECT_EQ(sem_getvalue(sem, &semValue), 0) << "sem_getvalue errno = " << errno; 178 EXPECT_EQ(semValue, 0); 179 EXPECT_EQ(sem_wait(sem), 0) << "sem_wait errno = " << errno; 180 return nullptr; 181} 182 183/** 184 * @tc.number SUB_KERNEL_IPC_SEM_CHAT_0100 185 * @tc.name Inter-thread communication, check sem_wait function 186 * @tc.desc [C- SOFTWARE -0200] 187 */ 188HWTEST_F(SemTest, testThreadChat, Function | MediumTest | Level3) 189{ 190 pthread_t tid; 191 sem_t sem; 192 int reInt = 0; 193 int semValue = 0; 194 195 ASSERT_EQ(sem_init(&sem, 0, 0), 0) << "> sem_init errno = " << errno; 196 197 reInt = pthread_create(&tid, nullptr, ThreadChat, (void*)&sem); 198 ASSERT_EQ(reInt, 0) << "> pthread_create errno, reInt = " << reInt; 199 200 Msleep(20); 201 EXPECT_EQ(sem_getvalue(&sem, &semValue), 0) << "> sem_getvalue errno = " << errno; 202 EXPECT_EQ(semValue, 0); 203 204 EXPECT_EQ(sem_post(&sem), 0) << "sem_post errno = " << errno; 205 EXPECT_EQ(sem_post(&sem), 0) << "sem_post errno = " << errno; 206 207 Msleep(20); 208 EXPECT_EQ(sem_getvalue(&sem, &semValue), 0) << "> sem_getvalue errno = " << errno; 209 EXPECT_EQ(semValue, 1); 210 211 reInt = pthread_join(tid, nullptr); 212 EXPECT_EQ(reInt, 0) << "pthread_join failed, errno=" << reInt; 213 EXPECT_EQ(sem_destroy(&sem), 0) << "> sem_destroy errno = " << errno; 214} 215 216void *ThreadSemTryWait(void *arg) 217{ 218 sem_t *sem = (sem_t*)arg; 219 int semValue = 0; 220 int loop = 10; 221 222 EXPECT_EQ(sem_getvalue(sem, &semValue), 0) << "sem_getvalue errno = " << errno; 223 EXPECT_EQ(semValue, 0); 224 for (int i = 0; i < loop; i++) { 225 if (sem_trywait(sem) == 0) { 226 break; 227 228 } 229 Msleep(10); 230 } 231 return nullptr; 232} 233 234/** 235 * @tc.number SUB_KERNEL_IPC_SEM_CHAT_0200 236 * @tc.name basic function test : Inter-thread communication, check sem_trywait function 237 * @tc.desc [C- SOFTWARE -0200] 238 */ 239HWTEST_F(SemTest, testThreadSemTryWait, Function | MediumTest | Level3) 240{ 241 sem_t sem; 242 int reInt = 0; 243 int semValue = 0; 244 245 ASSERT_EQ(sem_init(&sem, 0, 0), 0) << "> sem_init errno = " << errno; 246 247 pthread_t tid; 248 reInt = pthread_create(&tid, nullptr, ThreadSemTryWait, (void*)&sem); 249 ASSERT_EQ(reInt, 0) << "> pthread_create errno, reInt = " << reInt; 250 251 Msleep(20); 252 EXPECT_EQ(sem_getvalue(&sem, &semValue), 0) << "> sem_getvalue errno = " << errno; 253 EXPECT_EQ(semValue, 0); 254 255 EXPECT_EQ(sem_post(&sem), 0) << "sem_post errno = " << errno; 256 EXPECT_EQ(sem_post(&sem), 0) << "sem_post errno = " << errno; 257 258 reInt = pthread_join(tid, nullptr); 259 EXPECT_EQ(sem_getvalue(&sem, &semValue), 0) << "> sem_getvalue errno = " << errno; 260 261 if (semValue == 1 || semValue == 2) { 262 EXPECT_TRUE(true); 263 LOG("semValue = %d", semValue); 264 } else { 265 EXPECT_TRUE(false); 266 LOG("semValue errno, semValue = %d", semValue); 267 } 268 269 EXPECT_EQ(reInt, 0) << "pthread_join failed, errno=" << reInt; 270 EXPECT_EQ(sem_destroy(&sem), 0) << "> sem_destroy errno = " << errno; 271} 272 273void *ThreadSemTimedWait(void *arg) 274{ 275 struct timespec ts = {0}; 276 sem_t *sem = (sem_t*)arg; 277 int semValue = 0; 278 279 EXPECT_EQ(sem_getvalue(sem, &semValue), 0) << "sem_getvalue errno = " << errno; 280 EXPECT_EQ(semValue, 0); 281 282 clock_gettime(CLOCK_REALTIME, &ts); 283 ts.tv_sec = ts.tv_sec + (ts.tv_nsec + KERNEL_100MS_BY_NS) / KERNEL_NS_PER_SECOND; 284 ts.tv_nsec = (ts.tv_nsec + KERNEL_100MS_BY_NS) % KERNEL_NS_PER_SECOND; 285 Msleep(50); 286 EXPECT_EQ(sem_timedwait(sem, &ts), 0) << "sem_timedwait errno = " << errno; 287 EXPECT_EQ(sem_getvalue(sem, &semValue), 0) << "sem_getvalue errno = " << errno; 288 289 Msleep(100); 290 EXPECT_EQ(semValue, 1); 291 return nullptr; 292} 293 294/** 295 * @tc.number SUB_KERNEL_IPC_SEM_CHAT_0300 296 * @tc.name Inter-thread communication, check sem_timedwait function 297 * @tc.desc [C- SOFTWARE -0200] 298 */ 299HWTEST_F(SemTest, testThreadSemTimedWait, Function | MediumTest | Level3) 300{ 301 pthread_t tid; 302 sem_t sem; 303 int reInt = 0; 304 int semValue = 0; 305 306 ASSERT_EQ(sem_init(&sem, 0, 0), 0) << "> sem_init errno = " << errno; 307 308 reInt = pthread_create(&tid, nullptr, ThreadSemTimedWait, (void*)&sem); 309 ASSERT_EQ(reInt, 0) << "> pthread_create errno, reInt = " << reInt; 310 311 Msleep(10); 312 EXPECT_EQ(sem_getvalue(&sem, &semValue), 0) << "> sem_getvalue errno = " << errno; 313 EXPECT_EQ(semValue, 0); 314 EXPECT_EQ(sem_post(&sem), 0) << "> sem_post errno = " << errno; 315 EXPECT_EQ(sem_post(&sem), 0) << "> sem_post errno = " << errno; 316 317 reInt = pthread_join(tid, nullptr); 318 EXPECT_EQ(sem_getvalue(&sem, &semValue), 0) << "> sem_getvalue errno = " << errno; 319 EXPECT_EQ(semValue, 1); 320 EXPECT_EQ(reInt, 0) << "pthread_join failed, errno=" << reInt; 321 EXPECT_EQ(sem_destroy(&sem), 0) << "> sem_destroy errno = " << errno; 322} 323 324void *ThreadNThreadWait1(void *arg) 325{ 326 sem_t *sem = (sem_t*)arg; 327 int semValue = 0; 328 329 Msleep(100); 330 EXPECT_EQ(sem_getvalue(sem, &semValue), 0) << "sem_getvalue errno = " << errno; 331 EXPECT_EQ(semValue, 0); 332 EXPECT_EQ(sem_wait(sem), 0) << "sem_wait errno = " << errno; 333 return nullptr; 334} 335 336void *ThreadNThreadWait2(void *arg) 337{ 338 sem_t *sem = (sem_t*)arg; 339 int semValue = 0; 340 EXPECT_EQ(sem_getvalue(sem, &semValue), 0) << "sem_getvalue errno = " << errno; 341 EXPECT_EQ(semValue, 0); 342 343 Msleep(300); 344 EXPECT_EQ(sem_getvalue(sem, &semValue), 0) << "sem_getvalue errno = " << errno; 345 EXPECT_EQ(semValue, 0); 346 347 Msleep(200); 348 EXPECT_EQ(sem_getvalue(sem, &semValue), 0) << "sem_getvalue errno = " << errno; 349 EXPECT_EQ(semValue, 1); 350 EXPECT_EQ(sem_wait(sem), 0) << "sem_wait errno = " << errno; 351 return nullptr; 352} 353 354/** 355 * @tc.number SUB_KERNEL_IPC_SEM_CHAT_0400 356 * @tc.name N threads wait, main thread post 357 * @tc.desc [C- SOFTWARE -0200] 358 */ 359HWTEST_F(SemTest, testNThreadWait, Function | MediumTest | Level4) 360{ 361 pthread_t tid1; 362 pthread_t tid2; 363 sem_t sem; 364 int reInt = 0; 365 int semValue = 0; 366 367 ASSERT_EQ(sem_init(&sem, 0, 0), 0) << "> sem_init errno = " << errno; 368 369 reInt = pthread_create(&tid1, nullptr, ThreadNThreadWait1, (void*)&sem); 370 ASSERT_EQ(reInt, 0) << "> pthread_create errno, reInt = " << reInt; 371 372 reInt = pthread_create(&tid2, nullptr, ThreadNThreadWait2, (void*)&sem); 373 ASSERT_EQ(reInt, 0) << "> pthread_create errno, reInt = " << reInt; 374 375 Msleep(200); 376 EXPECT_EQ(sem_getvalue(&sem, &semValue), 0) << "sem_getvalue errno = " << errno; 377 EXPECT_EQ(semValue, 0); 378 EXPECT_EQ(sem_post(&sem), 0) << "sem_post errno = " << errno; 379 380 Msleep(20); 381 EXPECT_EQ(sem_getvalue(&sem, &semValue), 0) << "sem_getvalue errno = " << errno; 382 EXPECT_EQ(semValue, 0); 383 384 Msleep(200); 385 EXPECT_EQ(sem_getvalue(&sem, &semValue), 0) << "sem_getvalue errno = " << errno; 386 EXPECT_EQ(semValue, 0); 387 EXPECT_EQ(sem_post(&sem), 0) << "sem_post errno = " << errno; 388 389 Msleep(20); 390 EXPECT_EQ(sem_getvalue(&sem, &semValue), 0) << "sem_getvalue errno = " << errno; 391 EXPECT_EQ(semValue, 1); 392 393 reInt = pthread_join(tid1, nullptr); 394 EXPECT_EQ(reInt, 0) << "pthread_join failed, errno=" << reInt; 395 reInt = pthread_join(tid2, nullptr); 396 EXPECT_EQ(reInt, 0) << "pthread_join failed, errno=" << reInt; 397 EXPECT_EQ(sem_destroy(&sem), 0) << "> sem_destroy errno = " << errno; 398} 399 400void *ThreadNThreadPost1(void *arg) 401{ 402 sem_t *sem = (sem_t*)arg; 403 int semValue = 0; 404 405 Msleep(200); 406 EXPECT_EQ(sem_post(sem), 0) << "sem_post errno = " << errno; 407 Msleep(20); 408 EXPECT_EQ(sem_getvalue(sem, &semValue), 0) << "sem_getvalue errno = " << errno; 409 EXPECT_EQ(semValue, 0); 410 return nullptr; 411} 412 413void *ThreadNThreadPost2(void *arg) 414{ 415 sem_t *sem = (sem_t*)arg; 416 int semValue = 0; 417 418 Msleep(300); 419 EXPECT_EQ(sem_post(sem), 0) << "sem_post errno = " << errno; 420 Msleep(20); 421 EXPECT_EQ(sem_getvalue(sem, &semValue), 0) << "sem_getvalue errno = " << errno; 422 EXPECT_EQ(semValue, 1); 423 return nullptr; 424} 425 426/** 427 * @tc.number SUB_KERNEL_IPC_SEM_CHAT_0500 428 * @tc.name N threads post, main thread wait 429 * @tc.desc [C- SOFTWARE -0200] 430 */ 431HWTEST_F(SemTest, testNThreadPost, Function | MediumTest | Level4) 432{ 433 pthread_t tid1; 434 pthread_t tid2; 435 struct timespec ts = {0}; 436 sem_t sem; 437 int reInt = 0; 438 int semValue = 0; 439 440 ASSERT_EQ(sem_init(&sem, 0, 0), 0) << "> sem_init errno = " << errno; 441 442 reInt = pthread_create(&tid1, nullptr, ThreadNThreadPost1, (void*)&sem); 443 ASSERT_EQ(reInt, 0) << "> pthread_create errno, reInt = " << reInt; 444 445 reInt = pthread_create(&tid2, nullptr, ThreadNThreadPost2, (void*)&sem); 446 ASSERT_EQ(reInt, 0) << "> pthread_create errno, reInt = " << reInt; 447 448 Msleep(100); 449 clock_gettime(CLOCK_REALTIME, &ts); 450 ts.tv_sec = ts.tv_sec + 1; 451 EXPECT_EQ(sem_timedwait(&sem, &ts), 0) << "> sem_timedwait errno = " << errno; 452 453 Msleep(400); 454 EXPECT_EQ(sem_getvalue(&sem, &semValue), 0) << "sem_getvalue errno = " << errno; 455 EXPECT_EQ(semValue, 1); 456 EXPECT_EQ(sem_trywait(&sem), 0) << "> sem_trywait errno = " << errno; 457 EXPECT_EQ(sem_getvalue(&sem, &semValue), 0) << "sem_getvalue errno = " << errno; 458 EXPECT_EQ(semValue, 0); 459 460 reInt = pthread_join(tid1, nullptr); 461 EXPECT_EQ(reInt, 0) << "pthread_join failed, errno=" << reInt; 462 reInt = pthread_join(tid2, nullptr); 463 EXPECT_EQ(reInt, 0) << "pthread_join failed, errno=" << reInt; 464 EXPECT_EQ(sem_destroy(&sem), 0) << "> sem_destroy errno = " << errno; 465} 466