1/* 2 * Copyright (c) 2020-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// tested api in this file: getpid getppid getpgrp setpgrp getpgid setpgid 17 18#include <unistd.h> 19#include <sys/types.h> 20#include <sys/shm.h> 21#include <gtest/gtest.h> 22#include "log.h" 23#include "utils.h" 24#include "KernelConstants.h" 25 26using namespace testing::ext; 27 28class PidTest : public testing::Test { 29protected: 30 const char* mChildELF = RES_DIR_KERNEL "process/executor"; 31}; 32 33/** 34 * @tc.number SUB_KERNEL_PM_PID_Getppid_0100 35 * @tc.name getpid and getppid test 36 * @tc.desc [C- SOFTWARE -0200] 37 */ 38HWTEST_F(PidTest, testGetPpid, Function | MediumTest | Level1) 39{ 40 pid_t parentPid = getpid(); 41 pid_t pid = fork(); 42 ASSERT_TRUE(pid >= 0) << "======== Fork Error! ========="; 43 if (pid == 0) { // child 44 pid_t pPid = getppid(); 45 if (pPid != parentPid) { 46 LOG("getppid fail, expect:%d, but get:%d", parentPid, pPid); 47 exit(1); 48 } 49 exit(0); 50 } else { // parent 51 Msleep(20); 52 WaitProcExitedOK(pid); 53 } 54} 55 56/** 57 * @tc.number SUB_KERNEL_PM_PID_Getppid_0200 58 * @tc.name test that a orphaned process will inherite by init. 59 * @tc.desc [C- SOFTWARE -0200] 60 */ 61HWTEST_F(PidTest, testOrphanProcess, Function | MediumTest | Level1) 62{ 63 const int retPass = 1; 64 const int retFail = 2; 65 const int memSize = 32; 66 int shmID = shmget(IPC_PRIVATE, memSize, 0666 | IPC_CREAT); 67 ASSERT_NE(shmID, -1) << "get share mem fail, errno = " << errno; 68 int *shared = (int*)(shmat(shmID, nullptr, 0)); 69 ASSERT_NE(shared, reinterpret_cast<int*>(-1)) << "shmat fail, errno = " << errno; 70 shared[0] = retPass; 71 shared[1] = 0; 72 73 LOG("parent process id:%d", getpid()); 74 pid_t pid = fork(); 75 EXPECT_TRUE(pid >= 0) << "======== Fork Error! ========="; 76 if (pid == 0) { // child 77 LOG("sub parent process id:%d", getpid()); 78 pid_t pid2 = fork(); 79 if (pid2 < 0) { 80 LOG("======== Fork Error! ========="); 81 exit(1); 82 } 83 84 if (pid2 == 0) { // child 85 LOG("orphane process id:%d", getpid()); 86 int *shmAddr = (int*)(shmat(shmID, nullptr, 0)); 87 LOG("before while child child %d", shmAddr[1]); 88 while (shmAddr[1] != 1) { 89 Msleep(50); 90 } 91 LOG("after while child child %d", shmAddr[1]); 92 pid_t pPid = getppid(); 93 if (pPid != 1) { 94 LOG("getppid orphaned process fail, expect:1, but get:%d", pPid); 95 // transfer result to main process 96 shmAddr[0] = retFail; 97 } 98 shmAddr[1] =2; 99 LOG("child child exit %d", shmAddr[1]); 100 shmdt(shmAddr); 101 exit(0); 102 } else { // sub parent 103 exit(0); 104 } 105 } 106 // parent 107 WaitProcExitedOK(pid); 108 shared[1] = 1; 109 Msleep(200); 110 EXPECT_EQ(shared[0], retPass); 111 LOG("before while paret %d", shared[1]); 112 while (shared[1] != 2) { 113 Msleep(50); 114 } 115 shmdt(shared); 116 shmctl(shmID, IPC_RMID, nullptr); 117} 118 119/** 120 * @tc.number SUB_KERNEL_PM_PID_SetGetPgrp_0100 121 * @tc.name setpgrp and getpgrp test 122 * @tc.desc [C- SOFTWARE -0200] 123 */ 124HWTEST_F(PidTest, testSetGetPgrp, Function | MediumTest | Level1) 125{ 126 pid_t parentPid = getpid(); 127 int rt = setpgrp(); 128 ASSERT_EQ(rt, 0); 129 130 pid_t pgid = getpgrp(); 131 ASSERT_EQ(pgid, parentPid); 132 133 pid_t pid = fork(); 134 ASSERT_TRUE(pid >= 0) << "======== Fork Error! ========="; 135 if (pid == 0) { // child 136 pid_t childPgid = getpgrp(); 137 if (childPgid != pgid) { 138 LOG("child getpgrp fail, expect:%d, but get:%d", pgid, childPgid); 139 exit(1); 140 } 141 exit(0); 142 } else { // parent 143 Msleep(20); 144 WaitProcExitedOK(pid); 145 } 146} 147 148/** 149 * @tc.number SUB_KERNEL_PM_PID_SetGetPgid_0100 150 * @tc.name setpgid and getpgid basic test 151 * @tc.desc [C- SOFTWARE -0200] 152 */ 153HWTEST_F(PidTest, testSetGetPgid, Function | MediumTest | Level1) 154{ 155 pid_t parentPid = getpid(); 156 int rt = setpgid(0, parentPid); 157 ASSERT_EQ(rt, 0); 158 rt = setpgid(0, 0); 159 ASSERT_EQ(rt, 0); 160 161 pid_t pgid = getpgid(0); 162 ASSERT_EQ(pgid, parentPid); 163 164 pid_t pid1 = fork(); 165 ASSERT_TRUE(pid1 >= 0) << "======== Fork Error! ========="; 166 if (pid1 == 0) { // child 167 pid_t childPgid = getpgid(0); 168 if (childPgid != pgid) { 169 LOG("child getpgid fail, expect:%d, but get:%d", pgid, childPgid); 170 exit(1); 171 } 172 Msleep(40); 173 childPgid = getpgid(0); 174 pid_t childPid = getpid(); 175 if (childPgid != childPid) { 176 LOG("child new pgid check fail, pid=%d, pgid:%d", childPid, childPgid); 177 exit(1); 178 } 179 exit(0); 180 } else { // parent 181 Msleep(30); 182 rt = setpgid(pid1, pid1); 183 ASSERT_EQ(rt, 0); 184 pid_t pgid2 = getpgid(pid1); 185 ASSERT_EQ(pgid2, pid1); 186 Msleep(50); 187 WaitProcExitedOK(pid1); 188 } 189} 190/** 191 * @tc.number SUB_KERNEL_PM_PID_SetGetPgid_0200 192 * @tc.name setpgid and getpgid test for sibling process 193 * @tc.desc [C- SOFTWARE -0200] 194 */ 195HWTEST_F(PidTest, testSetGetSiblingPgid, Function | MediumTest | Level1) 196{ 197 pid_t parentPid = getpid(); 198 int rt = setpgid(0, parentPid); 199 ASSERT_EQ(rt, 0); 200 rt = setpgid(0, 0); 201 ASSERT_EQ(rt, 0); 202 pid_t pgid = getpgid(0); 203 ASSERT_EQ(pgid, parentPid); 204 205 pid_t pid1 = fork(); 206 ASSERT_TRUE(pid1 >= 0) << "======== Fork Error! ========="; 207 if (pid1 == 0) { // child1 208 Msleep(20); 209 exit(0); 210 } else { // parent 211 pid_t pid2 = fork(); 212 ASSERT_TRUE(pid2 >= 0) << "======== Fork Error! ========="; 213 if (pid2 == 0) { // child2 214 int exitCode = 0; 215 pid_t siblingPgid = getpgid(pid1); 216 if (siblingPgid != parentPid) { 217 LOG("child2: get sibling pgid fail, rt=%d, errno=%d", siblingPgid, errno); 218 exitCode = 1; 219 } 220 rt = setpgid(pid1, pid1); 221 if (rt != -1) { 222 LOG("child2: setpgid for sibling should fail"); 223 exitCode = 1; 224 } 225 if (errno != ESRCH) { 226 LOG("child2: setpgid errno fail, expected %d, but get %d", ESRCH, errno); 227 exitCode = 1; 228 } 229 exit(exitCode); 230 } 231 // parent 232 Msleep(50); 233 WaitProcExitedOK(pid1); 234 WaitProcExitedOK(pid2); 235 } 236} 237/** 238 * @tc.number SUB_KERNEL_PM_PID_SetGetPgid_0300 239 * @tc.name getpgid fail test 240 * @tc.desc [C- SOFTWARE -0200] 241 */ 242HWTEST_F(PidTest, testGetpgidFail, Function | MediumTest | Level3) 243{ 244 pid_t pgid = getpgid(-1); 245 EXPECT_EQ(pgid, -1); 246 EXPECT_EQ(errno, EINVAL); 247 248 pgid = getpgid(-1000001); 249 EXPECT_EQ(pgid, -1); 250 EXPECT_EQ(errno, EINVAL); 251 252 pid_t nonExitPid = GetNonExistPid(); // valid but not exist pid 253 if (nonExitPid != -1) { 254 pgid = getpgid(nonExitPid); 255 EXPECT_EQ(pgid, -1); 256 EXPECT_EQ(errno, ESRCH); 257 } 258 259 pgid = getpgid(MAX_PROCESS_NUMBER + 1); 260 EXPECT_EQ(pgid, -1); 261 EXPECT_EQ(errno, EINVAL); 262 263 pgid = getpgid(100000); 264 EXPECT_EQ(pgid, -1); 265 EXPECT_EQ(errno, EINVAL); 266 267 pgid = getpgid(1); 268 EXPECT_EQ(pgid, 1) << "get init process-groups-ID fail\n"; 269} 270 271/** 272 * @tc.number SUB_KERNEL_PM_PID_SetGetPgid_0400 273 * @tc.name setpgid fail test 274 * @tc.desc [C- SOFTWARE -0200] 275 */ 276HWTEST_F(PidTest, testSetpgidFail, Function | MediumTest | Level3) 277{ 278 pid_t pid = getpid(); 279 int rt = setpgrp(); 280 ASSERT_EQ(rt, 0); 281 282 LOG("invalid pid test..."); 283 rt = setpgid(-1, 0); 284 EXPECT_EQ(rt, -1); 285 EXPECT_EQ(errno, EINVAL); 286 287 rt = setpgid(-1000001, 0); 288 EXPECT_EQ(rt, -1); 289 EXPECT_EQ(errno, EINVAL); 290 291 pid_t nonExitPid = GetNonExistPid(); // valid but not exist pid 292 if (nonExitPid != -1) { 293 rt = setpgid(nonExitPid, 0); 294 EXPECT_EQ(rt, -1); 295 EXPECT_EQ(errno, ESRCH); 296 } 297 298 rt = setpgid(MAX_PROCESS_NUMBER + 1, 0); 299 EXPECT_EQ(rt, -1); 300 EXPECT_EQ(errno, EINVAL); 301 302 rt = setpgid(100000, 0); 303 EXPECT_EQ(rt, -1); 304 EXPECT_EQ(errno, EINVAL); 305 306 rt = setpgid(1, pid); // init 307 EXPECT_EQ(rt, -1); 308 EXPECT_EQ(errno, EPERM); 309 310 rt = setpgid(2, pid); // kProcess 311 EXPECT_EQ(rt, -1); 312 EXPECT_EQ(errno, EPERM); 313 314 LOG("invalid pgid test..."); 315 rt = setpgid(0, -1); 316 EXPECT_EQ(rt, -1); 317 EXPECT_EQ(errno, EINVAL); 318 319 nonExitPid = GetNonExistPid(); // valid but not exist pid 320 if (nonExitPid != -1) { 321 rt = setpgid(0, nonExitPid); 322 EXPECT_EQ(rt, -1); 323 EXPECT_EQ(errno, EPERM); 324 } 325 326 rt = setpgid(0, 10001); 327 EXPECT_EQ(rt, -1); 328 EXPECT_EQ(errno, EINVAL); 329 330 rt = setpgid(0, 1); // init 331 EXPECT_EQ(rt, -1); 332 EXPECT_EQ(errno, EPERM); 333 334 rt = setpgid(0, 2); // kProcess 335 EXPECT_EQ(rt, -1); 336 EXPECT_EQ(errno, EPERM); 337} 338 339/** 340 * @tc.number SUB_KERNEL_PM_PID_SetGetPgid_0500 341 * @tc.name setpgid fail test: EACCES 342 * @tc.desc [C- SOFTWARE -0200] 343 */ 344HWTEST_F(PidTest, testSetpgidFailEACCES, Function | MediumTest | Level3) 345{ 346 pid_t pid = fork(); 347 ASSERT_TRUE(pid >= 0) << "======== Fork Error! ========="; 348 if (pid == 0) { // child 349 int rt = execve(mChildELF, NULL, NULL); 350 if (rt == -1) { 351 LOG("ERROR: execve return -1, errno=%d, err=%s\n", errno, strerror(errno)); 352 } 353 exit(1); 354 } else { // parent 355 sleep(2); 356 AssertProcAlive(pid); 357 int rt = setpgid(pid, pid); 358 EXPECT_EQ(rt, -1) << "setpgid should fail after child execve."; 359 EXPECT_EQ(errno, EACCES) << "set errno fail."; 360 361 // recycle child 362 int status; 363 waitpid(pid, &status, 0); 364 } 365} 366