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 <stdlib.h> 17#include <string.h> 18#include <stdlib.h> 19#include <limits.h> 20#include <sys/shm.h> 21#include <assert.h> 22#include <unistd.h> 23#include <gtest/gtest.h> 24#include "utils.h" 25#include "mt_utils.h" 26#include "log.h" 27#include "KernelConstants.h" 28 29using namespace testing::ext; 30 31class ProcessTest : public::testing::Test { 32}; 33 34/** 35 * @tc.number SUB_KERNEL_PROCESS_LINE_BIGEXIT_0100 36 * @tc.name Basic test about _Exit 37 * @tc.desc [C- SOFTWARE -0200] 38 */ 39HWTEST_F(ProcessTest, testLineBigExit, Function | MediumTest | Level2) 40{ 41 int exitCode; 42 pid_t pid; 43 int reInt[4] = {0, 1, 100, 255}; 44 45 for (int i = 0; i < sizeof(reInt) / sizeof(int); i++) { 46 pid = fork(); 47 ASSERT_TRUE(pid >= 0) << "> parent: fork errno = " << errno; 48 if (pid == 0) { 49 _Exit(reInt[i]); 50 } 51 Msleep(50); 52 exitCode = 0; 53 ASSERT_EQ(CheckProcStatus(pid, &exitCode, 0), 1); 54 ASSERT_EQ(exitCode, reInt[i]); 55 } 56} 57 58/** 59 * @tc.number SUB_KERNEL_PROCESS_LINE_BIGEXIT_0200 60 * @tc.name Test _Exit about IO flush 61 * @tc.desc [C- SOFTWARE -0200] 62 */ 63HWTEST_F(ProcessTest, testLineBigExitFlush, Function | MediumTest | Level3) 64{ 65 const char* testFile = "TEST_FILE.txt"; 66 char writeBuf[] = "this is a file"; 67 char readBuf[20] = {0}; 68 pid_t pid; 69 70 pid = fork(); 71 ASSERT_TRUE(pid >= 0) << "> parent: fork errno = " << errno; 72 if (pid == 0) { 73 74 // write 75 FILE *fp = fopen(testFile, "w+"); 76 if (fp == nullptr) { 77 LOG("> child fopen errno = %d", errno); 78 _Exit(1); 79 } 80 fwrite(writeBuf, sizeof(writeBuf), 1, fp); 81 _Exit(0); 82 } 83 84 WaitProcExitedOK(pid); 85 86 // read 87 FILE *fp = fopen(testFile, "r+"); 88 ASSERT_NE(fp, nullptr) << "> fopen errno = " << errno; 89 EXPECT_EQ(fread(readBuf, sizeof(writeBuf), 1, fp), 0); 90 EXPECT_STRNE(writeBuf, readBuf) << "> writeBuf = " << writeBuf\ 91 << "\n> readBuf = " << readBuf; 92 EXPECT_NE(fclose(fp), -1) << "> fclose errno =" <<errno; 93 remove(testFile); 94} 95 96int g_shmid0; 97 98void AtexitCallback0(void) 99{ 100 LOG("> AtexitCallback0"); 101 pid_t *shared = (int*)shmat(g_shmid0, nullptr, 0); 102 if (shared == (void *)-1) { 103 LOG("> AtexitCallback0 shmat errno = %d", errno); 104 _Exit(1); 105 } 106 *shared = getppid(); 107 if ((shmdt(shared)) == -1) { 108 LOG("> AtexitCallback0 shmdt errno = %d", errno); 109 _Exit(1); 110 } 111 LOG("> 333"); 112} 113 114/** 115 * @tc.number SUB_KERNEL_PROCESS_LINE_BIGEXIT_0300 116 * @tc.name Test _Exit about call functions registered with atexit 117 * @tc.desc [C- SOFTWARE -0200] 118 */ 119HWTEST_F(ProcessTest, testLineBigExitAtexit, Function | MediumTest | Level3) 120{ 121 const int memSize = 1024; 122 g_shmid0 = shmget(IPC_PRIVATE, memSize, 0666 | IPC_CREAT); 123 ASSERT_NE(g_shmid0, -1) << "> parent: shmid errno = " << errno; 124 pid_t pid = fork(); 125 ASSERT_TRUE(pid >= 0) << "> parent: fork errno = " << errno; 126 if (pid == 0) { 127 Msleep(20); 128 if (atexit(AtexitCallback0) != 0) { 129 _Exit(1); 130 } 131 LOG("> 222"); 132 _Exit(0); 133 } 134 pid_t *shared = (int*)shmat(g_shmid0, nullptr, 0); 135 LOG("> 111"); 136 WaitProcExitedOK(pid); 137 LOG("> 444"); 138 ASSERT_NE(shared, (void*)-1) << "> shmat errno = " << errno; 139 EXPECT_NE(*shared, getpid()); 140 ASSERT_NE(shmdt(shared), -1) << "> parent: shmdt errno = " << errno; 141 ASSERT_NE(shmctl(g_shmid0, IPC_RMID, nullptr), -1) << "> shmctl : IPC_RMID : errno = " << errno; 142} 143 144/** 145 * @tc.number SUB_KERNEL_PROCESS_LINE_EXIT_0100 146 * @tc.name Basic test about _exit 147 * @tc.desc [C- SOFTWARE -0200] 148 */ 149HWTEST_F(ProcessTest, testLineExit, Function | MediumTest | Level2) 150{ 151 int exitCode; 152 pid_t pid; 153 int reInt[4] = {0, 1, 100, 255}; 154 155 for (int i = 0; i < sizeof(reInt) / sizeof(int); i++) { 156 pid = fork(); 157 ASSERT_TRUE(pid >= 0) << "> parent: fork errno = " << errno; 158 if (pid == 0) { 159 _exit(reInt[i]); 160 } 161 Msleep(50); 162 exitCode = 0; 163 ASSERT_EQ(CheckProcStatus(pid, &exitCode, 0), 1); 164 ASSERT_EQ(exitCode, reInt[i]); 165 } 166} 167 168/** 169 * @tc.number SUB_KERNEL_PROCESS_LINE_EXIT_0200 170 * @tc.name Test _exit about IO flush 171 * @tc.desc [C- SOFTWARE -0200] 172 */ 173HWTEST_F(ProcessTest, testLineExitFlush, Function | MediumTest | Level3) 174{ 175 const char* testFile = "TEST_FILE.txt"; 176 char writeBuf[] = "this is a file"; 177 char readBuf[20] = {0}; 178 pid_t pid; 179 180 pid = fork(); 181 ASSERT_TRUE(pid >= 0) << "> parent: fork errno = " << errno; 182 if (pid == 0) { 183 184 // write 185 FILE *fp = fopen(testFile, "w+"); 186 if (fp == nullptr) { 187 LOG("> child fopen errno = %d", errno); 188 _exit(1); 189 } 190 fwrite(writeBuf, sizeof(writeBuf), 1, fp); 191 _exit(0); 192 } 193 194 WaitProcExitedOK(pid); 195 196 // read 197 FILE *fp = fopen(testFile, "r+"); 198 ASSERT_NE(fp, nullptr) << "> fopen errno = " << errno; 199 EXPECT_EQ(fread(readBuf, sizeof(writeBuf), 1, fp), 0); 200 EXPECT_STRNE(writeBuf, readBuf) << "> writeBuf = " << writeBuf\ 201 << "\n> readBuf = " << readBuf; 202 EXPECT_NE(fclose(fp), -1) << "> fclose errno =" <<errno; 203 remove(testFile); 204} 205 206int g_shmid1; 207 208void AtexitCallback1(void) 209{ 210 LOG("> AtexitCallback0"); 211 pid_t *shared = (int*)shmat(g_shmid1, nullptr, 0); 212 if (shared == (void *)-1) { 213 LOG("> AtexitCallback0 shmat errno = %d", errno); 214 _exit(1); 215 } 216 *shared = getppid(); 217 if ((shmdt(shared)) == -1) { 218 LOG("> AtexitCallback0 shmdt errno = %d", errno); 219 _exit(1); 220 } 221 LOG("> 333"); 222} 223 224/** 225 * @tc.number SUB_KERNEL_PROCESS_LINE_EXIT_0300 226 * @tc.name Test _exit about call functions registered with atexit 227 * @tc.desc [C- SOFTWARE -0200] 228 */ 229HWTEST_F(ProcessTest, testLineExitAtexit, Function | MediumTest | Level3) 230{ 231 const int memSize = 1024; 232 g_shmid1 = shmget(IPC_PRIVATE, memSize, 0666 | IPC_CREAT); 233 ASSERT_NE(g_shmid1, -1) << "> parent: shmid errno = " << errno; 234 pid_t pid = fork(); 235 ASSERT_TRUE(pid >= 0) << "> parent: fork errno = " << errno; 236 if (pid == 0) { 237 Msleep(20); 238 if (atexit(AtexitCallback1) != 0) { 239 _exit(1); 240 } 241 LOG("> 222"); 242 _exit(0); 243 } 244 pid_t *shared = (int*)shmat(g_shmid1, nullptr, 0); 245 LOG("> 111"); 246 WaitProcExitedOK(pid); 247 LOG("> 444"); 248 ASSERT_NE(shared, (void*)-1) << "> shmat errno = " << errno; 249 EXPECT_NE(*shared, getpid()); 250 ASSERT_NE(shmdt(shared), -1) << "> parent: shmdt errno = " << errno; 251 ASSERT_NE(shmctl(g_shmid1, IPC_RMID, nullptr), -1) << "> shmctl : IPC_RMID : errno = " << errno; 252} 253 254/** 255 * @tc.number SUB_KERNEL_PROCESS_EXIT_0100 256 * @tc.name Basic test about exit 257 * @tc.desc [C- SOFTWARE -0200] 258 */ 259HWTEST_F(ProcessTest, testExit, Function | MediumTest | Level2) 260{ 261 int exitCode; 262 pid_t pid; 263 int reInt[4] = {0, 1, 100, 255}; 264 265 for (int i = 0; i < sizeof(reInt) / sizeof(int); i++) { 266 pid = fork(); 267 ASSERT_TRUE(pid >= 0) << "> parent: fork errno = " << errno; 268 if (pid == 0) { 269 exit(reInt[i]); 270 } 271 Msleep(50); 272 exitCode = 0; 273 ASSERT_EQ(CheckProcStatus(pid, &exitCode, 0), 1); 274 ASSERT_EQ(exitCode, reInt[i]); 275 } 276} 277/** 278 * @tc.number SUB_KERNEL_PROCESS_ASSERT_0100 279 * @tc.name Basic test about assert true 280 * @tc.desc [C- SOFTWARE -0200] 281 */ 282HWTEST_F(ProcessTest, testAssertTrue, Function | MediumTest | Level3) 283{ 284 pid_t pid = fork(); 285 ASSERT_TRUE(pid >= 0) << "> parent: fork errno = " << errno; 286 if (pid == 0) { 287 assert(true); 288 exit(0); 289 } 290 Msleep(50); 291 WaitProcExitedOK(pid); 292} 293 294int FunctionAssertFalse(void) 295{ 296 pid_t pid = fork(); 297 if (pid < 0) { 298 LOG("> fork errno = %d", errno); 299 return 0; 300 } else if (pid == 0) { 301 assert(false); 302 LOG("> child not stop"); 303 exit(0); 304 } 305 Msleep(50); 306 int exitCode = 0; 307 int reInt = CheckProcStatus(pid, &exitCode, 0); 308 if ((reInt == 2) && (exitCode == SIGABRT)) { 309 LOG("> Success"); 310 return 1; 311 } 312 LOG("> Fail"); 313 return 0; 314} 315 316/** 317 * @tc.number SUB_KERNEL_PROCESS_ASSERT_0200 318 * @tc.name Basic test about assert false 319 * @tc.desc [C- SOFTWARE -0200] 320 */ 321HWTEST_F(ProcessTest, testAssertFalse, Function | MediumTest | Level3) 322{ 323 pid_t pid = fork(); 324 ASSERT_TRUE(pid >= 0) << "> parent: fork errno = " << errno; 325 if (pid == 0) { 326 assert(false); 327 LOG("> child not stop"); 328 exit(0); 329 } 330 Msleep(50); 331 int exitCode = 0; 332 ASSERT_EQ(CheckProcStatus(pid, &exitCode, 0), 2); 333 ASSERT_EQ(exitCode, SIGABRT); 334} 335 336int g_shmid; 337 338void AtexitCallback(void) 339{ 340 LOG("> AtexitCallback"); 341 pid_t *shared = (int*)shmat(g_shmid, nullptr, 0); 342 if (shared == (void *)-1) { 343 LOG("> AtexitCallback shmat errno = %d", errno); 344 exit(1); 345 } 346 *shared = getppid(); 347 if ((shmdt(shared)) == -1) { 348 LOG("> AtexitCallback shmdt errno = %d", errno); 349 exit(1); 350 } 351} 352 353/** 354 * @tc.number SUB_KERNEL_PROCESS_ATEXIT_0100 355 * @tc.name Basic test about atexit 356 * @tc.desc [C- SOFTWARE -0200] 357 */ 358HWTEST_F(ProcessTest, testAtexit, Function | MediumTest | Level3) 359{ 360 const int memSize = 1024; 361 g_shmid = shmget(IPC_PRIVATE, memSize, 0666 | IPC_CREAT); 362 ASSERT_NE(g_shmid, -1) << "> parent: shmid errno = " << errno; 363 pid_t pid = fork(); 364 ASSERT_TRUE(pid >= 0) << "> parent: fork errno = " << errno; 365 if (pid == 0) { 366 Msleep(20); 367 if (atexit(AtexitCallback) != 0) { 368 LOG("> atexit errno = %d", errno); 369 exit(1); 370 } 371 exit(0); 372 } 373 pid_t *shared = (int*)shmat(g_shmid, nullptr, 0); 374 375 WaitProcExitedOK(pid); 376 ASSERT_NE(shared, (void*)-1) << "> shmat errno = " << errno; 377 EXPECT_EQ(*shared, getpid()); 378 ASSERT_NE(shmdt(shared), -1) << "> parent: shmdt errno = " << errno; 379 ASSERT_NE(shmctl(g_shmid, IPC_RMID, nullptr), -1) << "> shmctl : IPC_RMID : errno = " << errno; 380} 381 382/** 383 * @tc.number SUB_KERNEL_PROCESS_WAIT_0100 384 * @tc.name test wait return 385 * @tc.desc [C- SOFTWARE -0200] 386 */ 387HWTEST_F(ProcessTest, testWaitReturn, Function | MediumTest | Level3) 388{ 389 InitGlobalVariable(); 390 pid_t pid = fork(); 391 ASSERT_TRUE(pid >= 0) << "> fork errno = " << errno; 392 if (pid == 0) { 393 int myPid = (int)getpid(); 394 LOG("> child pid = %d", myPid); 395 SetGlobalVariable(myPid); 396 exit(0); 397 } 398 Msleep(20); 399 int pidChild = (int)wait(nullptr); 400 LOG("> pidChild = %d", pidChild); 401 int expectPid = GetGlobalVariable(); 402 EXPECT_EQ(pidChild, expectPid); 403 DeleteGlobalVariable(); 404} 405 406 407/** 408 * @tc.number SUB_KERNEL_PROCESS_WAIT_0200 409 * @tc.name test wait parameter 410 * @tc.desc [C- SOFTWARE -0200] 411 */ 412HWTEST_F(ProcessTest, testWaitTest, Function | MediumTest | Level3) 413{ 414 int childReturn = GetRandom(256) - 1; 415 LOG("> childReturn = %d", childReturn); 416 417 pid_t pid = fork(); 418 ASSERT_TRUE(pid >= 0) << "> fork errno = " << errno; 419 if (pid == 0) { 420 exit(childReturn); 421 } 422 Msleep(20); 423 int status = 0; 424 int pidChild = (int)wait(&status); 425 EXPECT_NE(pidChild, -1); 426 EXPECT_TRUE(WIFEXITED(status)); 427 EXPECT_EQ(WEXITSTATUS(status), childReturn); 428} 429 430/** 431 * @tc.number SUB_KERNEL_PROCESS_WAIT_0300 432 * @tc.name test wait killed by SIGABRT 433 * @tc.desc [C- SOFTWARE -0200] 434 */ 435HWTEST_F(ProcessTest, testWaitKilled, Function | MediumTest | Level3) 436{ 437 pid_t pid = fork(); 438 ASSERT_TRUE(pid >= 0) << "> fork errno = " << errno; 439 if (pid == 0) { 440 Msleep(40); 441 exit(0); 442 } 443 Msleep(20); 444 kill(pid, SIGABRT); 445 int status = 0; 446 int pidChild = (int)wait(&status); 447 EXPECT_NE(pidChild, -1); 448 EXPECT_TRUE(WIFSIGNALED(status)); 449 EXPECT_EQ(WTERMSIG(status), SIGABRT); 450} 451 452/** 453 * @tc.number SUB_KERNEL_PROCESS_WAITPID_0100 454 * @tc.name waitpid basic test 455 * @tc.desc [C- SOFTWARE -0200] 456 */ 457HWTEST_F(ProcessTest, testWaitPidBasic, Function | MediumTest | Level3) 458{ 459 int childReturn = GetRandom(128) - 1; 460 LOG("> childReturn = %d", childReturn); 461 462 pid_t pid = fork(); 463 ASSERT_TRUE(pid >= 0) << "> fork errno = " << errno; 464 if (pid == 0) { 465 exit(childReturn); 466 } 467 Msleep(20); 468 int status = 0; 469 int pidChild = (int)waitpid(pid, &status, 0); 470 EXPECT_NE(pidChild, -1); 471 EXPECT_TRUE(WIFEXITED(status)); 472 EXPECT_EQ(WEXITSTATUS(status), childReturn); 473} 474 475/** 476 * @tc.number SUB_KERNEL_PROCESS_WAITPID_0200 477 * @tc.name test waitpid with WNOHANG 478 * @tc.desc [C- SOFTWARE -0200] 479 */ 480HWTEST_F(ProcessTest, testWaitPidTest, Function | MediumTest | Level3) 481{ 482 InitGlobalVariable(); 483 SetGlobalVariable(1); 484 pid_t pid = fork(); 485 ASSERT_TRUE(pid >= 0) << "> fork errno = " << errno; 486 if (pid == 0) { 487 Msleep(50); 488 SetGlobalVariable(2); 489 exit(0); 490 } 491 Msleep(20); 492 int status = 0; 493 int pidChild = (int)waitpid(pid, &status, WNOHANG); 494 int expectPid = GetGlobalVariable(); 495 EXPECT_EQ(expectPid, 1); 496 EXPECT_EQ(pidChild, 0); 497 Msleep(50); 498 WaitProcExitedOK(pid); 499 DeleteGlobalVariable(); 500} 501