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 16 #include <stdio.h> 17 #include <string.h> 18 #include <stdlib.h> 19 #include <sys/types.h> 20 #include <sys/shm.h> 21 #include <sys/ipc.h> 22 #include <unistd.h> 23 #include <gtest/gtest.h> 24 #include "utils.h" 25 #include "log.h" 26 27 using namespace testing::ext; 28 29 class ShmTest : public ::testing::Test 30 { 31 public: 32 static const char SHM_TEST_STR[]; 33 static const int SHM_TEST_STR_LEN; 34 }; 35 36 const char ShmTest::SHM_TEST_STR[] = "hello shmem"; 37 const int ShmTest::SHM_TEST_STR_LEN = sizeof(SHM_TEST_STR); 38 39 /** 40 * @tc.number SUB_KERNEL_IPC_SHM_ALL_0100 41 * @tc.name basic function test : hello world 42 * @tc.desc [C- SOFTWARE -0200] 43 */ 44 HWTEST_F(ShmTest, testShmBasic, Function | MediumTest | Level0) 45 { 46 const int memSize = 1024; 47 int shmid; 48 char *shared = nullptr; 49 50 shmid = shmget(static_cast<key_t> IPC_PRIVATE, memSize, 0666 | IPC_CREAT); 51 if (shmid == -1) { 52 LOG("shmget errno ,errno = %d", errno); 53 ADD_FAILURE(); 54 } 55 pid_t pid = fork(); 56 if (pid < 0) { 57 LOG("fork errno ,errno = %d", errno); 58 ADD_FAILURE(); 59 } 60 if (pid == 0) { 61 int exitCode = 0; 62 Msleep(40); 63 shared = static_cast<char*>(shmat(shmid, nullptr, 0)); 64 if (shared == reinterpret_cast<char*>(-1)) { 65 LOG("> child: shmat errno = %d", errno); 66 exit(1); 67 } 68 if (strncmp(shared, SHM_TEST_STR, SHM_TEST_STR_LEN) != 0) { 69 LOG("> child: error strncmp() shared = %s", shared); 70 exitCode = 1; 71 } 72 if ((shmdt(shared)) == -1) { 73 LOG("> child: shmdt errno = %d", errno); 74 exit(1); 75 } 76 if (shmctl(shmid, IPC_RMID, nullptr) == -1) { 77 LOG("> child: shmctl errno = %d", errno); 78 exit(1); 79 } 80 exit(exitCode); 81 } 82 // parent 83 shared = static_cast<char*>(shmat(shmid, nullptr, 0)); 84 if (shared == (void*)-1) { 85 LOG("shmat errno ,errno = %d", errno); 86 ADD_FAILURE(); 87 } 88 strncpy(shared, SHM_TEST_STR, SHM_TEST_STR_LEN); 89 if (shmdt(shared) == -1) { 90 LOG("shmdt errno ,errno = %d", errno); 91 ADD_FAILURE(); 92 } 93 Msleep(50); 94 WaitProcExitedOK(pid); 95 } 96 97 /** 98 * @tc.number SUB_KERNEL_IPC_SHM_ALL_0300 99 * @tc.name Single-process test 100 * @tc.desc [C- SOFTWARE -0200] 101 */ 102 HWTEST_F(ShmTest, testShmSingleProcess, Function | MediumTest | Level1) 103 { 104 const int memSize = 1024; 105 char *shared = nullptr; 106 107 int shmid = shmget(static_cast<key_t> IPC_PRIVATE, memSize, 0666 | IPC_CREAT); 108 if (shmid == -1) { 109 LOG("shmget errno ,errno = %d", errno); 110 ADD_FAILURE(); 111 } 112 113 shared = static_cast<char*>(shmat(shmid, nullptr, 0)); 114 ASSERT_NE(shared, (void*)-1) << "> shmat errno = " << errno; 115 strncpy(shared, SHM_TEST_STR, SHM_TEST_STR_LEN); 116 117 int re = shmdt(shared); 118 ASSERT_NE(re, -1) << "> shmdt errno = " << errno; 119 120 re = shmctl(shmid, IPC_RMID, nullptr); 121 ASSERT_NE(re, -1) << "> shmctl errno = " << errno; 122 } 123 124 /** 125 * @tc.number SUB_KERNEL_IPC_SHM_SHMGET_0100 126 * @tc.name shmat basic function test 127 * @tc.desc [C- SOFTWARE -0200] 128 */ 129 HWTEST_F(ShmTest, testShmget, Function | MediumTest | Level0) 130 { 131 const int memSize = 1024; 132 int tmp; 133 int shmid; 134 int shmidTmp; 135 int tmpKey = GetRandom(2147483647); 136 LOG("> tmpKey = %d", tmpKey); 137 138 shmid = shmget(IPC_PRIVATE, memSize, 0666 | IPC_CREAT); 139 ASSERT_NE(shmid, -1) << "> shmget : errno = " << errno; 140 tmp = shmctl(shmid, IPC_RMID, nullptr); 141 ASSERT_NE(tmp, -1) << "shmctl : error : IPC_RMID "; 142 143 // make sure tmpKey free 144 shmid = shmget(key_t(tmpKey), memSize, 0666 | IPC_CREAT); 145 ASSERT_NE(shmid, -1) << "> shmget : errno = " << errno; 146 tmp = shmctl(shmid, IPC_RMID, nullptr); 147 ASSERT_NE(tmp, -1) << "shmctl : error : IPC_RMID "; 148 149 shmid = shmget(key_t(tmpKey), memSize, IPC_EXCL | IPC_CREAT); 150 ASSERT_NE(shmid, -1) << "> shmget : errno = " << errno; 151 152 shmidTmp = shmid; 153 shmidTmp = shmget(key_t(tmpKey), memSize, IPC_EXCL | IPC_CREAT); 154 ASSERT_EQ(shmidTmp, -1) << "> shmget : errno = " << errno; 155 156 tmp = shmctl(shmid, IPC_RMID, nullptr); 157 ASSERT_NE(tmp, -1) << "> shmctl : error : IPC_RMID "; 158 159 shmid = shmget(key_t(tmpKey), memSize, 0); 160 ASSERT_EQ(shmid, -1) << "> shmget : errno = " << errno; 161 162 shmid = shmget(IPC_PRIVATE, 0, 0666 | IPC_CREAT); 163 ASSERT_EQ(shmid, -1) << "> shmget : errno = " << errno; 164 165 shmid = shmget(IPC_PRIVATE, memSize, 0666 | IPC_CREAT); 166 ASSERT_NE(shmid, -1) << "> shmget : errno = " << errno; 167 168 tmp = shmctl(shmid, IPC_RMID, nullptr); 169 ASSERT_NE(tmp, -1) << "> shmctl : error : IPC_RMID"; 170 } 171 172 /** 173 * @tc.number SUB_KERNEL_IPC_SHM_SHMAT_0100 174 * @tc.name shmat: SHM_REMAP function test 175 * @tc.desc [C- SOFTWARE -0200] 176 */ 177 HWTEST_F(ShmTest, testShmatSHM_REMAP, Function | MediumTest | Level1) 178 { 179 const int memSize = 1024; 180 int shmid; 181 char *shared = nullptr; 182 183 shmid = shmget(static_cast<key_t> IPC_PRIVATE, memSize, 0666 | IPC_CREAT); 184 if (shmid == -1) { 185 LOG("shmget errno ,errno = %d", errno); 186 ADD_FAILURE(); 187 } 188 189 pid_t pid = fork(); 190 if (shmid < 0) { 191 LOG("fork errno ,errno = %d", errno); 192 ADD_FAILURE(); 193 } 194 if (pid == 0) { 195 Msleep(10); 196 int exitCode = 0; 197 shared = static_cast<char*>(shmat(shmid, nullptr, 0)); 198 if (shared == reinterpret_cast<char*>(-1)) { 199 LOG("> child: shmat 1 : errno = %d", errno); 200 exit(1); 201 } 202 if (shmdt(shared) == -1) { 203 LOG("> child: shmdt: errno = %d", errno); 204 exit(1); 205 } 206 shared = static_cast<char*>(shmat(shmid, shared, SHM_REMAP)); 207 if (shared == reinterpret_cast<char*>(-1)) { 208 LOG("> child: shmat 2 : errno = %d", errno); 209 exit(1); 210 } 211 if (strncmp(shared, SHM_TEST_STR, SHM_TEST_STR_LEN) != 0) { 212 LOG("> child: error strncmp() shared = %s", shared); 213 exitCode = 1; 214 } 215 if ((shmdt(shared)) == -1) { 216 LOG("> child: shmdt : errno = %d", errno); 217 exit(1); 218 } 219 exit(exitCode); 220 } 221 // parent 222 shared = static_cast<char*>(shmat(shmid, nullptr, 0)); 223 ASSERT_NE(shared, (void*)-1) << "> shmat 1 : errno = " << errno; 224 ASSERT_NE(shmdt(shared), -1) << "> shmdt 1 : errno = " << errno; 225 shared = static_cast<char*>(shmat(shmid, shared, SHM_REMAP)); 226 ASSERT_NE(shared, (void*)-1) << "> parent: shmat 2 : errno = " << errno; 227 strncpy(shared, SHM_TEST_STR, SHM_TEST_STR_LEN); 228 ASSERT_NE(shmdt(shared), -1) << "> parent: shmdt 2 : errno = " << errno; 229 Msleep(50); 230 WaitProcExitedOK(pid); 231 232 Msleep(50); 233 ASSERT_NE(shmctl(shmid, IPC_RMID, nullptr), -1) << "> parent: shmctl : errno = " << errno; 234 } 235 236 /** 237 * @tc.number SUB_KERNEL_IPC_SHM_SHMAT_0200 238 * @tc.name shmat: SHM_RDONLY function test 239 * @tc.desc [C- SOFTWARE -0200] 240 */ 241 HWTEST_F(ShmTest, testShmatSHM_RDONLY, Function | MediumTest | Level0) 242 { 243 const int memSize = 1024; 244 int shmid; 245 char *shared = nullptr; 246 247 shmid = shmget(IPC_PRIVATE, memSize, 0666 | IPC_CREAT); 248 if (shmid == -1) { 249 LOG("shmget errno ,errno = %d", errno); 250 ADD_FAILURE(); 251 } 252 pid_t pid = fork(); 253 if (pid < 0) { 254 LOG("fork errno ,errno = %d", errno); 255 ADD_FAILURE(); 256 } 257 if (pid == 0) { 258 int exitCode = 0; 259 Msleep(10); 260 shared = static_cast<char*>(shmat(shmid, nullptr, SHM_RDONLY)); 261 if (shared == reinterpret_cast<char*>(-1)){ 262 LOG("> child: shmat : errno = %d", errno); 263 exitCode = 1; 264 } 265 if (strncmp(shared, SHM_TEST_STR, SHM_TEST_STR_LEN) != 0) { 266 LOG("> child: error strncmp()"); 267 exitCode = 1; 268 } 269 shared[0] = '1'; // segment error 270 if (shmdt(shared) == -1) { 271 LOG("> child: shmdt : errno = %d", errno); 272 exitCode = 1; 273 } 274 exit(exitCode); 275 } 276 shared = static_cast<char*>(shmat(shmid, nullptr, 0)); 277 EXPECT_NE(shared, (char*)-1) << "shmat : errno = " << errno; 278 strncpy(shared, SHM_TEST_STR, SHM_TEST_STR_LEN); 279 280 int exitCode; 281 int procStat = CheckProcStatus(pid, &exitCode, 0); 282 EXPECT_EQ(procStat, 2); 283 EXPECT_EQ(exitCode, 12) << "target process should exited 255."; 284 285 EXPECT_NE(shmdt(shared), -1) << "> shmdt : errno = " << errno; 286 EXPECT_NE(shmctl(shmid, IPC_RMID, nullptr), -1) << "> shmctl : IPC_RMID errno = " << errno; 287 } 288 289 /** 290 * @tc.number SUB_KERNEL_IPC_SHM_SHMAT_0300 291 * @tc.name shmat: SHM_RND function test 292 * @tc.desc [C- SOFTWARE -0200] 293 */ 294 HWTEST_F(ShmTest, testShmatSHM_RND, Function | MediumTest | Level0) 295 { 296 const int memSize = 1024; 297 int tmp; 298 int shmid; 299 void *shared = nullptr; 300 301 Msleep(10); 302 shmid = shmget(IPC_PRIVATE, memSize, 0666 | IPC_CREAT); 303 if (shmid == -1) { 304 LOG("shmget failed+++"); 305 ADD_FAILURE(); 306 } 307 EXPECT_NE(shmid, -1) << "shmget : errno = " << errno; 308 309 shared = shmat(shmid, nullptr, 0); 310 EXPECT_NE(shared, (void*)-1) << "> shmat : errno = " << errno; 311 int re = shmdt(shared); 312 EXPECT_NE(re, -1) << "> shmdt : errno = " << errno; 313 314 void *sharedTmp = shared; 315 sharedTmp = shmat(shmid, sharedTmp, SHM_RND); 316 EXPECT_NE(sharedTmp, (void*)-1) << "> shmat : error : sharedTmp = " << sharedTmp << "shared = " << shared; 317 strncpy(static_cast<char*>(sharedTmp), SHM_TEST_STR, SHM_TEST_STR_LEN); 318 re = shmdt(sharedTmp); 319 EXPECT_NE(re, -1) << "> shmdt : errno = " << errno; 320 321 tmp = shmctl(shmid, IPC_RMID, nullptr); 322 EXPECT_NE(tmp, -1) << "> shmctl : IPC_RMID errno = " << errno; 323 } 324 325 /** 326 * @tc.number SUB_KERNEL_IPC_SHM_SHMCTL_0100 327 * @tc.name shmctl: IPC_STAT and IPC_SET function test 328 * @tc.desc [C- SOFTWARE -0200] 329 */ 330 HWTEST_F(ShmTest, testShmctl, Function | MediumTest | Level1) 331 { 332 const int memSize = 4096; 333 struct shmid_ds shmPerm = {0}; 334 int tmp; 335 int shmid; 336 337 LOG("> getuid = %d", getuid()); 338 LOG("> getgid = %d", getgid()); 339 LOG("> getpid = %d", getpid()); 340 341 Msleep(10); 342 shmid = shmget(IPC_PRIVATE, memSize, 0666 | IPC_CREAT); 343 if (shmid == -1) { 344 LOG("shmget errno = %d \n",errno); 345 ADD_FAILURE(); 346 } 347 348 tmp = shmctl(shmid, IPC_STAT, &shmPerm); 349 EXPECT_NE(tmp, -1) << "> shmctl : IPC_STAT1 :erron = " << errno; 350 EXPECT_EQ(shmPerm.shm_lpid, 0); // PID of last shmat/shmdt 351 EXPECT_EQ(shmPerm.shm_nattch, 0); // No. of current attaches 352 353 char *shared = static_cast<char*>(shmat(shmid, nullptr, 0)); 354 EXPECT_NE(shared, (void*)-1) << "> shmat : errno = " << errno; 355 356 tmp = shmctl(shmid, IPC_STAT, &shmPerm); 357 ASSERT_NE(tmp, -1) << "> shmctl : IPC_STAT2 :erron = " << errno; 358 EXPECT_EQ(shmPerm.shm_perm.__key, 0); // Key supplied to shmget 359 EXPECT_EQ(shmPerm.shm_perm.cuid, geteuid()); // Effective UID of creator 360 EXPECT_EQ(shmPerm.shm_perm.uid, geteuid()); // Effective UID of owne 361 EXPECT_EQ(shmPerm.shm_perm.cgid, getegid()); // Effective GID of creator 362 EXPECT_EQ(shmPerm.shm_perm.gid, getegid()); // Effective GID of owner 363 EXPECT_EQ(shmPerm.shm_perm.mode, 0666); // Permissions + SHM_DEST and SHM_LOCKED flags 364 LOG("> last shmat() time %lld", shmPerm.shm_atime); // Last attach time 365 LOG("> last shmdt() time %lld", shmPerm.shm_dtime); // Last detach time 366 EXPECT_EQ(shmPerm.shm_segsz, memSize); // Size of segment (bytes) 367 EXPECT_EQ(shmPerm.shm_cpid, getpid()); // PID of creator 368 EXPECT_EQ(shmPerm.shm_lpid, getpid()); // PID of last shmat/shmdt 369 EXPECT_EQ(shmPerm.shm_nattch, 1); // No. of current attaches 370 371 tmp = shmctl(shmid, IPC_SET, &shmPerm); 372 EXPECT_NE(shared, (void*)-1) << "> shmat : errno = " << errno; 373 374 tmp = shmdt(shared); 375 ASSERT_NE(tmp, -1) << "> shmdt : errno = " << errno; 376 377 tmp = shmctl(shmid, IPC_RMID, nullptr); 378 ASSERT_NE(tmp, -1) << "> shmctl : IPC_RMID : errno = " << errno; 379 } 380 381 /** 382 * @tc.number SUB_KERNEL_IPC_SHM_SHMCTL_0200 383 * @tc.name shmctl: IPC_INFO and SHM_INFO function test 384 * @tc.desc [C- SOFTWARE -0200] 385 */ 386 HWTEST_F(ShmTest, testShmctlINFO, Function | MediumTest | Level0) 387 { 388 int tmp; 389 struct shminfo buf = {0}; 390 tmp = shmctl(0, IPC_INFO, (struct shmid_ds *) &buf); 391 EXPECT_NE(tmp, -1) << "shmctl : IPC_INFO errno = " << errno; 392 LOG("> shminfo.shmmax = %lu", buf.shmmax); // Maximum segment size 42428800 393 EXPECT_EQ(buf.shmmin, 1) << "> shminfo.shmmin = " << buf.shmmin; // Minimum segment size 1 394 LOG("> shminfo.shmmni = %lu", buf.shmmni); // Maximum number of segments 192 395 LOG("> shminfo.shmseg = %lu", buf.shmseg); // Maximum number of segments that a process can attach 128 396 LOG("> shminfo.shmall = %lu", buf.shmall); // Maximum number of pages of shared memory, system-wide 12800 397 398 // Describes the system resource information for Shared memory 399 struct shm_info info = {0}; 400 tmp = shmctl(0, SHM_INFO, (struct shmid_ds *) &info); 401 EXPECT_NE(tmp, -1) << "shmctl : SHM_INFO errno = " << errno; 402 LOG("> shm_info.used_ids = %d", info.used_ids); // Currently existing segments 403 LOG("> shm_info.shm_tot = %lu", info.shm_tot); // Total number of shared memory pages 404 LOG("> shm_info.shm_rss = %lu", info.shm_rss); // Resident shared memory pages 405 LOG("> shm_info.shm_swp = %lu", info.shm_swp); // Swapped shared memory pages 406 LOG("> shm_info.__swap_attempts = %ld", info.__swap_attempts); // Number of exchange attempts 407 LOG("> shm_info.__swap_successes = %ld", info.__swap_successes); // Number of successful exchanges 408 } 409