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
29 using namespace testing::ext;
30
31 class 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 */
39 HWTEST_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 */
63 HWTEST_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
96 int g_shmid0;
97
AtexitCallback0(void)98 void 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 */
119 HWTEST_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 */
149 HWTEST_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 */
173 HWTEST_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
206 int g_shmid1;
207
AtexitCallback1(void)208 void 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 */
229 HWTEST_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 */
259 HWTEST_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 #if 0
278 /**
279 * @tc.number SUB_KERNEL_PROCESS_EXIT_0200
280 * @tc.name Test exit about IO flush
281 * @tc.desc [C- SOFTWARE -0200]
282 */
283 HWTEST_F(ProcessTest, testExitFlush, Function | MediumTest | Level3)
284 {
285 const char* testFile = "TEST_FILE.txt";
286 char writeBuf[] = "this is a file";
287 char readBuf[20] = {0};
288 pid_t pid;
289
290 pid = fork();
291 ASSERT_TRUE(pid >= 0) << "> parent: fork errno = " << errno;
292 if (pid == 0) {
293
294 // write
295 FILE *fp = fopen(testFile, "w+");
296 if (fp == nullptr) {
297 LOG("> child fopen errno = %d", errno);
298 exit(1);
299 }
300 fwrite(writeBuf, sizeof(writeBuf), 1, fp);
301 exit(0);
302 }
303
304 WaitProcExitedOK(pid);
305
306 // read
307 FILE *fp = fopen(testFile, "r+");
308 ASSERT_NE(fp, nullptr) << "> fopen errno = " << errno;
309 EXPECT_NE(fread(readBuf, sizeof(writeBuf), 1, fp), 0);
310 EXPECT_STREQ(writeBuf, readBuf) << "> writeBuf = " << writeBuf\
311 << "\n> readBuf = " << readBuf;
312 EXPECT_NE(fclose(fp), -1) << "> fclose errno =" <<errno;
313 remove(testFile);
314 }
315 #endif
316 /**
317 * @tc.number SUB_KERNEL_PROCESS_ASSERT_0100
318 * @tc.name Basic test about assert true
319 * @tc.desc [C- SOFTWARE -0200]
320 */
321 HWTEST_F(ProcessTest, testAssertTrue, Function | MediumTest | Level3)
322 {
323 pid_t pid = fork();
324 ASSERT_TRUE(pid >= 0) << "> parent: fork errno = " << errno;
325 if (pid == 0) {
326 assert(true);
327 exit(0);
328 }
329 Msleep(50);
330 WaitProcExitedOK(pid);
331 }
332
FunctionAssertFalse(void)333 int FunctionAssertFalse(void)
334 {
335 pid_t pid = fork();
336 if (pid < 0) {
337 LOG("> fork errno = %d", errno);
338 return 0;
339 } else if (pid == 0) {
340 assert(false);
341 LOG("> child not stop");
342 exit(0);
343 }
344 Msleep(50);
345 int exitCode = 0;
346 int reInt = CheckProcStatus(pid, &exitCode, 0);
347 if ((reInt == 2) && (exitCode == SIGABRT)) {
348 LOG("> Success");
349 return 1;
350 }
351 LOG("> Fail");
352 return 0;
353 }
354
355 /**
356 * @tc.number SUB_KERNEL_PROCESS_ASSERT_0200
357 * @tc.name Basic test about assert false
358 * @tc.desc [C- SOFTWARE -0200]
359 */
360 HWTEST_F(ProcessTest, testAssertFalse, Function | MediumTest | Level3)
361 {
362 pid_t pid = fork();
363 ASSERT_TRUE(pid >= 0) << "> parent: fork errno = " << errno;
364 if (pid == 0) {
365 assert(false);
366 LOG("> child not stop");
367 exit(0);
368 }
369 Msleep(50);
370 int exitCode = 0;
371 ASSERT_EQ(CheckProcStatus(pid, &exitCode, 0), 2);
372 ASSERT_EQ(exitCode, SIGABRT);
373 }
374
375 int g_shmid;
376
AtexitCallback(void)377 void AtexitCallback(void)
378 {
379 LOG("> AtexitCallback");
380 pid_t *shared = (int*)shmat(g_shmid, nullptr, 0);
381 if (shared == (void *)-1) {
382 LOG("> AtexitCallback shmat errno = %d", errno);
383 exit(1);
384 }
385 *shared = getppid();
386 if ((shmdt(shared)) == -1) {
387 LOG("> AtexitCallback shmdt errno = %d", errno);
388 exit(1);
389 }
390 }
391
392 /**
393 * @tc.number SUB_KERNEL_PROCESS_ATEXIT_0100
394 * @tc.name Basic test about atexit
395 * @tc.desc [C- SOFTWARE -0200]
396 */
397 HWTEST_F(ProcessTest, testAtexit, Function | MediumTest | Level3)
398 {
399 const int memSize = 1024;
400 g_shmid = shmget(IPC_PRIVATE, memSize, 0666 | IPC_CREAT);
401 ASSERT_NE(g_shmid, -1) << "> parent: shmid errno = " << errno;
402 pid_t pid = fork();
403 ASSERT_TRUE(pid >= 0) << "> parent: fork errno = " << errno;
404 if (pid == 0) {
405 Msleep(20);
406 if (atexit(AtexitCallback) != 0) {
407 LOG("> atexit errno = %d", errno);
408 exit(1);
409 }
410 exit(0);
411 }
412 pid_t *shared = (int*)shmat(g_shmid, nullptr, 0);
413
414 WaitProcExitedOK(pid);
415 ASSERT_NE(shared, (void*)-1) << "> shmat errno = " << errno;
416 EXPECT_EQ(*shared, getpid());
417 ASSERT_NE(shmdt(shared), -1) << "> parent: shmdt errno = " << errno;
418 ASSERT_NE(shmctl(g_shmid, IPC_RMID, nullptr), -1) << "> shmctl : IPC_RMID : errno = " << errno;
419 }
420
421 /**
422 * @tc.number SUB_KERNEL_PROCESS_WAIT_0100
423 * @tc.name test wait return
424 * @tc.desc [C- SOFTWARE -0200]
425 */
426 HWTEST_F(ProcessTest, testWaitReturn, Function | MediumTest | Level3)
427 {
428 InitGlobalVariable();
429 pid_t pid = fork();
430 ASSERT_TRUE(pid >= 0) << "> fork errno = " << errno;
431 if (pid == 0) {
432 int myPid = (int)getpid();
433 LOG("> child pid = %d", myPid);
434 SetGlobalVariable(myPid);
435 exit(0);
436 }
437 Msleep(20);
438 int pidChild = (int)wait(nullptr);
439 LOG("> pidChild = %d", pidChild);
440 int expectPid = GetGlobalVariable();
441 EXPECT_EQ(pidChild, expectPid);
442 DeleteGlobalVariable();
443 }
444
445
446 /**
447 * @tc.number SUB_KERNEL_PROCESS_WAIT_0200
448 * @tc.name test wait parameter
449 * @tc.desc [C- SOFTWARE -0200]
450 */
451 HWTEST_F(ProcessTest, testWaitTest, Function | MediumTest | Level3)
452 {
453 int childReturn = GetRandom(256) - 1;
454 LOG("> childReturn = %d", childReturn);
455
456 pid_t pid = fork();
457 ASSERT_TRUE(pid >= 0) << "> fork errno = " << errno;
458 if (pid == 0) {
459 exit(childReturn);
460 }
461 Msleep(20);
462 int status = 0;
463 int pidChild = (int)wait(&status);
464 EXPECT_NE(pidChild, -1);
465 EXPECT_TRUE(WIFEXITED(status));
466 EXPECT_EQ(WEXITSTATUS(status), childReturn);
467 }
468
469 /**
470 * @tc.number SUB_KERNEL_PROCESS_WAIT_0300
471 * @tc.name test wait killed by SIGABRT
472 * @tc.desc [C- SOFTWARE -0200]
473 */
474 HWTEST_F(ProcessTest, testWaitKilled, Function | MediumTest | Level3)
475 {
476 pid_t pid = fork();
477 ASSERT_TRUE(pid >= 0) << "> fork errno = " << errno;
478 if (pid == 0) {
479 Msleep(40);
480 exit(0);
481 }
482 Msleep(20);
483 kill(pid, SIGABRT);
484 int status = 0;
485 int pidChild = (int)wait(&status);
486 EXPECT_NE(pidChild, -1);
487 EXPECT_TRUE(WIFSIGNALED(status));
488 EXPECT_EQ(WTERMSIG(status), SIGABRT);
489 }
490
491 /**
492 * @tc.number SUB_KERNEL_PROCESS_WAITPID_0100
493 * @tc.name waitpid basic test
494 * @tc.desc [C- SOFTWARE -0200]
495 */
496 HWTEST_F(ProcessTest, testWaitPidBasic, Function | MediumTest | Level3)
497 {
498 int childReturn = GetRandom(128) - 1;
499 LOG("> childReturn = %d", childReturn);
500
501 pid_t pid = fork();
502 ASSERT_TRUE(pid >= 0) << "> fork errno = " << errno;
503 if (pid == 0) {
504 exit(childReturn);
505 }
506 Msleep(20);
507 int status = 0;
508 int pidChild = (int)waitpid(pid, &status, 0);
509 EXPECT_NE(pidChild, -1);
510 EXPECT_TRUE(WIFEXITED(status));
511 EXPECT_EQ(WEXITSTATUS(status), childReturn);
512 }
513
514 /**
515 * @tc.number SUB_KERNEL_PROCESS_WAITPID_0200
516 * @tc.name test waitpid with WNOHANG
517 * @tc.desc [C- SOFTWARE -0200]
518 */
519 HWTEST_F(ProcessTest, testWaitPidTest, Function | MediumTest | Level3)
520 {
521 InitGlobalVariable();
522 SetGlobalVariable(1);
523 pid_t pid = fork();
524 ASSERT_TRUE(pid >= 0) << "> fork errno = " << errno;
525 if (pid == 0) {
526 Msleep(50);
527 SetGlobalVariable(2);
528 exit(0);
529 }
530 Msleep(20);
531 int status = 0;
532 int pidChild = (int)waitpid(pid, &status, WNOHANG);
533 int expectPid = GetGlobalVariable();
534 EXPECT_EQ(expectPid, 1);
535 EXPECT_EQ(pidChild, 0);
536 Msleep(50);
537 WaitProcExitedOK(pid);
538 DeleteGlobalVariable();
539 }
540