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  */
HWTEST_F(ProcessTest, testLineBigExit, Function | MediumTest | Level2)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  */
HWTEST_F(ProcessTest, testLineBigExitFlush, Function | MediumTest | Level3)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  */
HWTEST_F(ProcessTest, testLineBigExitAtexit, Function | MediumTest | Level3)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  */
HWTEST_F(ProcessTest, testLineExit, Function | MediumTest | Level2)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  */
HWTEST_F(ProcessTest, testLineExitFlush, Function | MediumTest | Level3)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  */
HWTEST_F(ProcessTest, testLineExitAtexit, Function | MediumTest | Level3)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  */
HWTEST_F(ProcessTest, testExit, Function | MediumTest | Level2)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 /**
278  * @tc.number   SUB_KERNEL_PROCESS_ASSERT_0100
279  * @tc.name     Basic test about assert true
280  * @tc.desc     [C- SOFTWARE -0200]
281  */
HWTEST_F(ProcessTest, testAssertTrue, Function | MediumTest | Level3)282 HWTEST_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 
FunctionAssertFalse(void)294 int 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  */
HWTEST_F(ProcessTest, testAssertFalse, Function | MediumTest | Level3)321 HWTEST_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 
336 int g_shmid;
337 
AtexitCallback(void)338 void 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  */
HWTEST_F(ProcessTest, testAtexit, Function | MediumTest | Level3)358 HWTEST_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  */
HWTEST_F(ProcessTest, testWaitReturn, Function | MediumTest | Level3)387 HWTEST_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  */
HWTEST_F(ProcessTest, testWaitTest, Function | MediumTest | Level3)412 HWTEST_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  */
HWTEST_F(ProcessTest, testWaitKilled, Function | MediumTest | Level3)435 HWTEST_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  */
HWTEST_F(ProcessTest, testWaitPidBasic, Function | MediumTest | Level3)457 HWTEST_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  */
HWTEST_F(ProcessTest, testWaitPidTest, Function | MediumTest | Level3)480 HWTEST_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