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 <csignal>
20#include <string>
21#include <vector>
22#include <fcntl.h>
23#include <unistd.h>
24#include <malloc.h>
25#include <arpa/inet.h>
26#include <gtest/gtest.h>
27#include <netinet/in.h>
28#include <sys/stat.h>
29#include <sys/mman.h>
30#include <sys/socket.h>
31#include <sys/types.h>
32#include "securec.h"
33
34using namespace testing::ext;
35
36const int SIZE = 1024;
37static const char* TEST_FILE = "/data/local/tmp/test_file.txt";
38
39class HatsMsyncTest : public testing::Test {
40public:
41    static void SetUpTestCase();
42    static void TearDownTestCase();
43    void SetUp();
44    void TearDown();
45private:
46};
47void HatsMsyncTest::SetUp()
48{
49}
50
51void HatsMsyncTest::TearDown()
52{
53}
54
55void HatsMsyncTest::SetUpTestCase()
56{
57}
58
59void HatsMsyncTest::TearDownTestCase()
60{
61}
62
63/*
64 * @tc.number : SUB_KERNEL_SYSCALL_MSYNC_0100
65 * @tc.name   : MsyncInvalidateSuccess_0001
66 * @tc.desc   : Msync sets flag MS_INVALIDATE successfully.
67 * @tc.size   : MediumTest
68 * @tc.type   : Function
69 * @tc.level  : Level 1
70 */
71HWTEST_F(HatsMsyncTest, MsyncInvalidateSuccess_0001, Function | MediumTest | Level1)
72{
73    int fd = open(TEST_FILE, O_RDWR | O_CREAT, 0666);
74    EXPECT_TRUE(fd > 0);
75
76    ftruncate(fd, SIZE);
77
78    const char *initialData = "Hello, msync invalidate!";
79
80    void *addr = mmap(nullptr, SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
81    EXPECT_NE(addr, MAP_FAILED);
82
83    char *data = (char *) addr;
84    size_t numToCopy = strlen(initialData);
85    int retCpy = memcpy_s(data, SIZE, initialData, numToCopy + 1);
86    EXPECT_EQ(retCpy, 0);
87
88    int ret = msync(addr, SIZE, MS_INVALIDATE);
89    EXPECT_EQ(ret, 0);
90
91    const char *expectedData = "Hello, msync invalidate!";
92    ret = strcmp((char *)addr, expectedData);
93    EXPECT_EQ(ret, 0);
94
95    lseek(fd, 0, SEEK_SET);
96    char buffer[SIZE];
97    read(fd, buffer, SIZE);
98    EXPECT_EQ(strcmp(buffer, initialData), 0);
99
100    munmap(addr, SIZE);
101    close(fd);
102}
103
104/*
105 * @tc.number : SUB_KERNEL_SYSCALL_MSYNC_0200
106 * @tc.name   : MsyncAsyncSuccess_0002
107 * @tc.desc   : Msync sets flag MS_ASYNC successfully.
108 * @tc.size   : MediumTest
109 * @tc.type   : Function
110 * @tc.level  : Level 1
111 */
112HWTEST_F(HatsMsyncTest, MsyncAsyncSuccess_0002, Function | MediumTest | Level1)
113{
114    int fd = open(TEST_FILE, O_RDWR | O_CREAT, 0666);
115    EXPECT_TRUE(fd > 0);
116
117    ftruncate(fd, SIZE);
118
119    const char *initialData = "Hello, msync async!";
120    void *addr = mmap(nullptr, SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
121    EXPECT_NE(addr, MAP_FAILED);
122
123    char *data = (char *) addr;
124    size_t numToCopy = strlen(initialData);
125    int retCpy = memcpy_s(data, SIZE, initialData, numToCopy + 1);
126    EXPECT_EQ(retCpy, 0);
127
128    int ret = msync(addr, SIZE, MS_ASYNC);
129    EXPECT_EQ(ret, 0);
130
131    usleep(200000);
132
133    lseek(fd, 0, SEEK_SET);
134    char buffer[SIZE];
135    read(fd, buffer, SIZE);
136    EXPECT_EQ(strcmp(buffer, "Hello, msync async!"), 0);
137
138    munmap(addr, SIZE);
139    close(fd);
140}
141
142/*
143 * @tc.number : SUB_KERNEL_SYSCALL_MSYNC_0300
144 * @tc.name   : MsyncSyncSuccess_0003
145 * @tc.desc   : Msync sets flag MS_SYNC successfully.
146 * @tc.size   : MediumTest
147 * @tc.type   : Function
148 * @tc.level  : Level 1
149 */
150HWTEST_F(HatsMsyncTest, MsyncSyncSuccess_0003, Function | MediumTest | Level1)
151{
152    int fd = open(TEST_FILE, O_RDWR | O_CREAT, 0666);
153    EXPECT_TRUE(fd > 0);
154
155    ftruncate(fd, SIZE);
156
157    const char *initialData = "Hello, msync sync!";
158    void *addr = mmap(nullptr, SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
159    EXPECT_NE(addr, MAP_FAILED);
160
161    char *data = (char *) addr;
162    size_t numToCopy = strlen(initialData);
163    int retCpy = memcpy_s(data, SIZE, initialData, numToCopy + 1);
164    EXPECT_EQ(retCpy, 0);
165
166    int ret = msync(addr, SIZE, MS_SYNC);
167    EXPECT_EQ(ret, 0);
168
169    lseek(fd, 0, SEEK_SET);
170    char buffer[SIZE];
171    read(fd, buffer, SIZE);
172    EXPECT_EQ(strcmp(buffer, "Hello, msync sync!"), 0);
173
174    munmap(addr, SIZE);
175    close(fd);
176}
177
178/*
179 * @tc.number : SUB_KERNEL_SYSCALL_MSYNC_0400
180 * @tc.name   : MsyncInvalidAddrFailed_0004
181 * @tc.desc   : Msync is failed for invalid addr, errno EINVAL.
182 * @tc.size   : MediumTest
183 * @tc.type   : Function
184 * @tc.level  : Level 2
185 */
186HWTEST_F(HatsMsyncTest, MsyncInvalidAddrFailed_0004, Function | MediumTest | Level2)
187{
188    void *invalidAddr = reinterpret_cast<void *>(0x1234);
189    int ret = msync(invalidAddr, SIZE, MS_SYNC);
190    EXPECT_EQ(ret, -1);
191    EXPECT_EQ(errno, EINVAL);
192}
193
194/*
195 * @tc.number : SUB_KERNEL_SYSCALL_MSYNC_0500
196 * @tc.name   : MsyncNullAddrFailed_0005
197 * @tc.desc   : Msync is failed for null addr, errno ENOMEM.
198 * @tc.size   : MediumTest
199 * @tc.type   : Function
200 * @tc.level  : Level 2
201 */
202HWTEST_F(HatsMsyncTest, MsyncNullAddrFailed_0005, Function | MediumTest | Level2)
203{
204    char *data = nullptr;
205
206    int ret = msync(data, SIZE, MS_INVALIDATE);
207    EXPECT_EQ(ret, -1);
208    EXPECT_EQ(errno, ENOMEM);
209}
210