1 /*
2 * Copyright (C) 2024 HiHope Open Source Organization.
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 <cerrno>
17 #include <cstdio>
18 #include <cstdlib>
19 #include <string>
20 #include <vector>
21 #include <fcntl.h>
22 #include <unistd.h>
23 #include <gtest/gtest.h>
24 #include <sys/mman.h>
25 #include <sys/stat.h>
26 #include <sys/types.h>
27 #include "securec.h"
28
29
30 using namespace testing::ext;
31 using namespace std;
32
33 static const int PAGE_SIZE = 4096;
34 static const int PAGE_NUM = 4;
35
36 class MincoreApiTest : public testing::Test {
37 public:
38 static void SetUpTestCase();
39 static void TearDownTestCase();
40 void SetUp();
41 void TearDown();
42 private:
43 };
SetUp()44 void MincoreApiTest::SetUp()
45 {
46 }
TearDown()47 void MincoreApiTest::TearDown()
48 {
49 }
SetUpTestCase()50 void MincoreApiTest::SetUpTestCase()
51 {
52 }
TearDownTestCase()53 void MincoreApiTest::TearDownTestCase()
54 {
55 }
56
CheckStatus(unsigned char * vec)57 static int CheckStatus(unsigned char *vec)
58 {
59 int ret = 4;
60 for (int i = 0; i < PAGE_NUM; i++) {
61 int a = vec[i] & 0x1;
62 if (a == 0) {
63 ret = ret - 1;
64 }
65 }
66 return ret;
67 }
68
Touch(void * addr)69 static int Touch(void *addr)
70 {
71 char *buffer1 = static_cast<char *>(addr);
72 int ret1 = memset_s(buffer1, PAGE_SIZE, 'A', PAGE_SIZE);
73 if (ret1 != EOK) {
74 return ret1;
75 }
76
77 char *buffer2 = static_cast<char *>(addr) + 2 * PAGE_SIZE;
78 int ret2 = memset_s(buffer2, PAGE_SIZE, 'A', PAGE_SIZE);
79 if (ret2 != EOK) {
80 return ret2;
81 }
82
83 int ret = ret1 + ret2;
84 return ret;
85 }
86
87
88 /*
89 * @tc.number : SUB_KERNEL_SYSCALL_MINCORE_0100
90 * @tc.name : MincoreCheckPageInMemorySuccess_0001
91 * @tc.desc : Mincore determine whether page are resident in memory.
92 * @tc.size : MediumTest
93 * @tc.type : Function
94 * @tc.level : Level 1
95 */
96 HWTEST_F(MincoreApiTest, MincoreCheckPageInMemorySuccess_0001, Function | MediumTest | Level1)
97 {
98 int ret;
99 size_t length = PAGE_SIZE * PAGE_NUM;
100 unsigned char *vec = new unsigned char[(length / PAGE_SIZE) + 1]();
101
102 void *addr = mmap(nullptr, length, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
103 EXPECT_NE(addr, MAP_FAILED);
104
105 ret = mincore(addr, length, vec);
106 EXPECT_EQ(ret, 0);
107 ret = CheckStatus(vec);
108 EXPECT_EQ(ret, 0);
109
110 ret = Touch(addr);
111 EXPECT_EQ(ret, 0);
112
113 ret = mincore(addr, length, vec);
114 EXPECT_EQ(ret, 0);
115 ret = CheckStatus(vec);
116 EXPECT_EQ(ret, 2);
117
118 munmap(addr, length);
119 delete [] vec;
120 }
121
122 /*
123 * @tc.number : SUB_KERNEL_SYSCALL_MINCORE_0200
124 * @tc.name : MincoreCheckPageInvalidAddrFail_0002
125 * @tc.desc : Mincore determine whether page are resident in invalid memory addr fail.
126 * @tc.size : MediumTest
127 * @tc.type : Function
128 * @tc.level : Level 2
129 */
130 HWTEST_F(MincoreApiTest, MincoreCheckPageInMemoryFail_0002, Function | MediumTest | Level2)
131 {
132 int ret;
133 size_t length = PAGE_SIZE * PAGE_NUM;
134 unsigned char *vec = new unsigned char[(length / PAGE_SIZE) + 1]();
135
136 errno = 0;
137 ret = mincore(MAP_FAILED, length, vec);
138 EXPECT_EQ(ret, -1);
139 EXPECT_EQ(errno, EINVAL);
140 delete [] vec;
141 }
142
143 /*
144 * @tc.number : SUB_KERNEL_SYSCALL_MINCORE_0300
145 * @tc.name : MincoreCheckPageInvalidLengthFail_0003
146 * @tc.desc : Mincore determine whether page are resident in invalid memory addr fail.
147 * @tc.size : MediumTest
148 * @tc.type : Function
149 * @tc.level : Level 2
150 */
151 HWTEST_F(MincoreApiTest, MincoreCheckPageInvalidLengthFail_0003, Function | MediumTest | Level2)
152 {
153 int ret;
154 size_t length = PAGE_SIZE * PAGE_NUM;
155 unsigned char *vec = new unsigned char[(length / PAGE_SIZE) + 1]();
156 void *addr = mmap(nullptr, length, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
157 EXPECT_NE(addr, MAP_FAILED);
158
159 errno = 0;
160 ret = mincore(MAP_FAILED, 0, vec);
161 EXPECT_EQ(ret, -1);
162 EXPECT_EQ(errno, EINVAL);
163 munmap(addr, length);
164 delete [] vec;
165 }
166
167 /*
168 * @tc.number : SUB_KERNEL_SYSCALL_MINCORE_0400
169 * @tc.name : MincoreCheckPageInMemorySuccess_0004
170 * @tc.desc : Mincore MAP_SHARED.
171 * @tc.size : MediumTest
172 * @tc.type : Function
173 * @tc.level : Level 2
174 */
175 HWTEST_F(MincoreApiTest, MincoreCheckPageInMemorySuccess_0004, Function | MediumTest | Level2)
176 {
177 int ret;
178 size_t length = PAGE_SIZE * PAGE_NUM;
179 unsigned char *vec = new unsigned char[(length / PAGE_SIZE) + 1]();
180
181 void *addr = mmap(nullptr, length, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0);
182 EXPECT_NE(addr, MAP_FAILED);
183
184 ret = mincore(addr, length, vec);
185 EXPECT_EQ(ret, 0);
186 ret = CheckStatus(vec);
187 EXPECT_EQ(ret, 0);
188
189 ret = Touch(addr);
190 EXPECT_EQ(ret, 0);
191
192 ret = mincore(addr, length, vec);
193 EXPECT_EQ(ret, 0);
194 ret = CheckStatus(vec);
195 EXPECT_EQ(ret, 2);
196
197 munmap(addr, length);
198 delete [] vec;
199 }
200
201 /*
202 * @tc.number : SUB_KERNEL_SYSCALL_MINCORE_0500
203 * @tc.name : MincoreCheckPageInMemorySuccess_0005
204 * @tc.desc : Mincore MAP_PRIVATE FILE.
205 * @tc.size : MediumTest
206 * @tc.type : Function
207 * @tc.level : Level 2
208 */
209 HWTEST_F(MincoreApiTest, MincoreCheckPageInMemorySuccess_0005, Function | MediumTest | Level2)
210 {
211 int ret;
212 const char *filename = "testfile";
213 size_t length = PAGE_SIZE * PAGE_NUM;
214 unsigned char *vec = new unsigned char[(length / PAGE_SIZE) + 1]();
215
216 int fd = open(filename, O_RDWR | O_CREAT | O_TRUNC, 0644);
217 EXPECT_GE(fd, 0);
218
219 ret = ftruncate(fd, PAGE_SIZE * PAGE_NUM);
220 EXPECT_NE(ret, -1);
221
222 void *addr = mmap(nullptr, length, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
223 EXPECT_NE(addr, MAP_FAILED);
224
225 ret = mincore(addr, length, vec);
226 EXPECT_EQ(ret, 0);
227 ret = CheckStatus(vec);
228 EXPECT_EQ(ret, 0);
229
230 ret = Touch(addr);
231 EXPECT_EQ(ret, 0);
232
233 ret = mincore(addr, length, vec);
234 EXPECT_EQ(ret, 0);
235 ret = CheckStatus(vec);
236 EXPECT_EQ(ret, 4);
237
238 munmap(addr, length);
239 close(fd);
240 unlink(filename);
241 delete [] vec;
242 }
243
244 /*
245 * @tc.number : SUB_KERNEL_SYSCALL_MINCORE_0600
246 * @tc.name : MincoreCheckPageInMemorySuccess_0006
247 * @tc.desc : Mincore MAP_SHARED FILE.
248 * @tc.size : MediumTest
249 * @tc.type : Function
250 * @tc.level : Level 2
251 */
252 HWTEST_F(MincoreApiTest, MincoreCheckPageInMemorySuccess_0006, Function | MediumTest | Level2)
253 {
254 int ret;
255 const char *filename = "testfile";
256 size_t length = PAGE_SIZE * PAGE_NUM;
257 unsigned char *vec = new unsigned char[(length / PAGE_SIZE) + 1]();
258
259 int fd = open(filename, O_RDWR | O_CREAT | O_TRUNC, 0644);
260 EXPECT_GE(fd, 0);
261
262 ret = ftruncate(fd, PAGE_SIZE * PAGE_NUM);
263 EXPECT_NE(ret, -1);
264
265 void *addr = mmap(nullptr, length, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
266 EXPECT_NE(addr, MAP_FAILED);
267
268 ret = mincore(addr, length, vec);
269 EXPECT_EQ(ret, 0);
270 ret = CheckStatus(vec);
271 EXPECT_EQ(ret, 0);
272
273 ret = Touch(addr);
274 EXPECT_EQ(ret, 0);
275
276 ret = mincore(addr, length, vec);
277 EXPECT_EQ(ret, 0);
278 ret = CheckStatus(vec);
279 EXPECT_EQ(ret, 4);
280
281 munmap(addr, length);
282 close(fd);
283 unlink(filename);
284 delete [] vec;
285 }