• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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