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 <algorithm>
17#include <fstream>
18#include <iostream>
19#include <unistd.h>
20#include <sys/mman.h>
21#include <gtest/gtest.h>
22#include "directory_ex.h"
23#include "securec.h"
24#include "hilog/log.h"
25#include "parcel.h"
26#include "refbase.h"
27#include "ashmem.h"
28
29using namespace testing::ext;
30using namespace std;
31
32namespace OHOS {
33namespace {
34const int MAX_PARCEL_SIZE = 1000;
35char g_data[MAX_PARCEL_SIZE];
36const int32_t MEMORY_SIZE = 1024;
37const std::string MEMORY_CONTENT = "HelloWorld2020\0";
38const std::string MEMORY_NAME = "Test SharedMemory\0";
39static constexpr HiviewDFX::HiLogLabel label = { LOG_CORE, 0xD003D00, "UtilsAshmemTest" };
40#define UTILS_LOGF(...) (void)OHOS::HiviewDFX::HiLog::Fatal(label, __VA_ARGS__)
41#define UTILS_LOGE(...) (void)OHOS::HiviewDFX::HiLog::Error(label, __VA_ARGS__)
42#define UTILS_LOGW(...) (void)OHOS::HiviewDFX::HiLog::Warn(label, __VA_ARGS__)
43#define UTILS_LOGI(...) (void)OHOS::HiviewDFX::HiLog::Info(label, __VA_ARGS__)
44#define UTILS_LOGD(...) (void)OHOS::HiviewDFX::HiLog::Debug(label, __VA_ARGS__)
45
46class UtilsAshmemTest : public testing::Test {
47public:
48    static void TearDownTestCase(void);
49};
50
51void UtilsAshmemTest::TearDownTestCase(void)
52{
53    for (int i = 0; i < MAX_PARCEL_SIZE; i++) {
54        g_data[i] = 0;
55    }
56}
57
58/**
59 * @tc.name: test_ashmem_WriteAndRead_001
60 * @tc.desc: create and map ashmem
61 * @tc.type: FUNC
62 */
63HWTEST_F(UtilsAshmemTest, test_ashmem_WriteAndRead_001, TestSize.Level0)
64{
65    UTILS_LOGI("test_ashmem_WriteAndRead_001");
66
67    sptr<Ashmem> ashmem = Ashmem::CreateAshmem(MEMORY_NAME.c_str(), MEMORY_SIZE);
68    ASSERT_TRUE(ashmem != nullptr);
69    ASSERT_TRUE(ashmem->GetAshmemSize() == MEMORY_SIZE);
70
71    bool ret = ashmem->MapAshmem(PROT_READ | PROT_WRITE);
72    ASSERT_TRUE(ret);
73
74    ashmem->UnmapAshmem();
75    ashmem->CloseAshmem();
76}
77
78/**
79 * @tc.name: test_ashmem_WriteAndRead_002
80 * @tc.desc: write to and read from ashmem
81 * @tc.type: FUNC
82 */
83HWTEST_F(UtilsAshmemTest, test_ashmem_WriteAndRead_002, TestSize.Level0)
84{
85    sptr<Ashmem> ashmem = Ashmem::CreateAshmem(MEMORY_NAME.c_str(), MEMORY_SIZE);
86    ASSERT_TRUE(ashmem != nullptr);
87
88    bool ret = ashmem->MapReadAndWriteAshmem();
89    ASSERT_TRUE(ret);
90
91    ret = ashmem->WriteToAshmem(MEMORY_CONTENT.c_str(), sizeof(MEMORY_CONTENT), 0);
92    ASSERT_TRUE(ret);
93
94    ret = ashmem->WriteToAshmem(MEMORY_CONTENT.c_str(), sizeof(MEMORY_CONTENT), sizeof(MEMORY_CONTENT));
95    ASSERT_TRUE(ret);
96
97    auto readData = ashmem->ReadFromAshmem(sizeof(MEMORY_CONTENT), 0);
98    ASSERT_TRUE(readData != nullptr);
99
100    const char *readContent = reinterpret_cast<const char *>(readData);
101    EXPECT_EQ(memcmp(MEMORY_CONTENT.c_str(), readContent, sizeof(MEMORY_CONTENT)), 0);
102
103    readData = ashmem->ReadFromAshmem(sizeof(MEMORY_CONTENT), sizeof(MEMORY_CONTENT));
104    ASSERT_TRUE(readData != nullptr);
105
106    readContent = reinterpret_cast<const char *>(readData);
107    EXPECT_EQ(memcmp(MEMORY_CONTENT.c_str(), readContent, sizeof(MEMORY_CONTENT)), 0);
108
109    ashmem->UnmapAshmem();
110    ashmem->CloseAshmem();
111}
112
113/**
114 * @tc.name: test_ashmem_WriteAndRead_003
115 * @tc.desc: test read-only ashmem
116 * @tc.type: FUNC
117 */
118HWTEST_F(UtilsAshmemTest, test_ashmem_WriteAndRead_003, TestSize.Level0)
119{
120    sptr<Ashmem> ashmem = Ashmem::CreateAshmem(MEMORY_NAME.c_str(), MEMORY_SIZE);
121    ASSERT_TRUE(ashmem != nullptr);
122
123    bool ret = ashmem->MapReadAndWriteAshmem();
124    ASSERT_TRUE(ret);
125
126    ret = ashmem->WriteToAshmem(MEMORY_CONTENT.c_str(), sizeof(MEMORY_CONTENT), 0);
127    ASSERT_TRUE(ret);
128
129    ashmem->UnmapAshmem();
130
131    ret = ashmem->MapReadOnlyAshmem();
132    ASSERT_TRUE(ret);
133
134    ret = ashmem->WriteToAshmem(MEMORY_CONTENT.c_str(), sizeof(MEMORY_CONTENT), sizeof(MEMORY_CONTENT));
135    ASSERT_FALSE(ret);
136
137    auto readData = ashmem->ReadFromAshmem(sizeof(MEMORY_CONTENT), 0);
138    ASSERT_TRUE(readData != nullptr);
139
140    const char *readContent = reinterpret_cast<const char *>(readData);
141    EXPECT_EQ(memcmp(MEMORY_CONTENT.c_str(), readContent, sizeof(MEMORY_CONTENT)), 0);
142
143    ashmem->UnmapAshmem();
144    ashmem->CloseAshmem();
145}
146
147/**
148 * @tc.name: test_ashmem_WriteAndRead_004
149 * @tc.desc: set read-only protection and map again
150 * @tc.type: FUNC
151 */
152HWTEST_F(UtilsAshmemTest, test_ashmem_WriteAndRead_004, TestSize.Level0)
153{
154    sptr<Ashmem> ashmem = Ashmem::CreateAshmem(MEMORY_NAME.c_str(), MEMORY_SIZE);
155    ASSERT_TRUE(ashmem != nullptr);
156
157    bool ret = ashmem->MapReadAndWriteAshmem();
158    ASSERT_TRUE(ret);
159
160    ret = ashmem->WriteToAshmem(MEMORY_CONTENT.c_str(), sizeof(MEMORY_CONTENT), 0);
161    ASSERT_TRUE(ret);
162
163    ashmem->UnmapAshmem();
164
165    ret = ashmem->SetProtection(PROT_READ);
166    ASSERT_TRUE(ret);
167
168    ret = ashmem->MapReadAndWriteAshmem();
169    ASSERT_FALSE(ret);
170
171    ret = ashmem->MapReadOnlyAshmem();
172    ASSERT_TRUE(ret);
173
174    auto readData = ashmem->ReadFromAshmem(sizeof(MEMORY_CONTENT), 0);
175    ASSERT_TRUE(readData != nullptr);
176
177    const char *readContent = reinterpret_cast<const char *>(readData);
178    EXPECT_EQ(memcmp(MEMORY_CONTENT.c_str(), readContent, sizeof(MEMORY_CONTENT)), 0);
179
180    ashmem->UnmapAshmem();
181    ashmem->CloseAshmem();
182}
183
184/**
185 * @tc.name: test_ashmem_WriteAndRead_005
186 * @tc.desc: set read-only protection without mapping again
187 * @tc.type: FUNC
188 */
189HWTEST_F(UtilsAshmemTest, test_ashmem_WriteAndRead_005, TestSize.Level0)
190{
191    sptr<Ashmem> ashmem = Ashmem::CreateAshmem(MEMORY_NAME.c_str(), MEMORY_SIZE);
192    ASSERT_TRUE(ashmem != nullptr);
193
194    bool ret = ashmem->MapReadAndWriteAshmem();
195    ASSERT_TRUE(ret);
196
197    ret = ashmem->WriteToAshmem(MEMORY_CONTENT.c_str(), sizeof(MEMORY_CONTENT), 0);
198    ASSERT_TRUE(ret);
199
200    ret = ashmem->SetProtection(PROT_READ);
201    ASSERT_TRUE(ret);
202
203    ret = ashmem->WriteToAshmem(MEMORY_CONTENT.c_str(), sizeof(MEMORY_CONTENT), 0);
204    ASSERT_FALSE(ret);
205
206    auto readData = ashmem->ReadFromAshmem(sizeof(MEMORY_CONTENT), 0);
207    ASSERT_TRUE(readData != nullptr);
208
209    const char *readContent = reinterpret_cast<const char *>(readData);
210    EXPECT_EQ(memcmp(MEMORY_CONTENT.c_str(), readContent, sizeof(MEMORY_CONTENT)), 0);
211
212    ashmem->UnmapAshmem();
213    ashmem->CloseAshmem();
214}
215
216/**
217 * @tc.name: test_ashmem_InvalidOperation_001
218 * @tc.desc: create invalid-size ashmem or set invalid protection type
219 * @tc.type: FUNC
220 */
221HWTEST_F(UtilsAshmemTest, test_ashmem_InvalidOperation_001, TestSize.Level0)
222{
223    sptr<Ashmem> ashmem = Ashmem::CreateAshmem(MEMORY_NAME.c_str(), -1);
224    ASSERT_TRUE(ashmem == nullptr);
225
226    ashmem = Ashmem::CreateAshmem(MEMORY_NAME.c_str(), MEMORY_SIZE);
227    ASSERT_TRUE(ashmem != nullptr);
228
229    bool ret = ashmem->SetProtection(-1);
230    ASSERT_FALSE(ret);
231
232    ashmem->CloseAshmem();
233}
234
235/**
236 * @tc.name: test_ashmem_InvalidOperation_002
237 * @tc.desc: map after closing ashmem
238 * @tc.type: FUNC
239 */
240HWTEST_F(UtilsAshmemTest, test_ashmem_InvalidOperation_002, TestSize.Level0)
241{
242    sptr<Ashmem> ashmem = Ashmem::CreateAshmem(MEMORY_NAME.c_str(), MEMORY_SIZE);
243    ASSERT_TRUE(ashmem != nullptr);
244
245    ashmem->CloseAshmem();
246
247    bool ret = ashmem->MapReadAndWriteAshmem();
248    ASSERT_FALSE(ret);
249}
250
251/**
252 * @tc.name: test_ashmem_InvalidOperation_003
253 * @tc.desc: write or read after closing ashmem
254 * @tc.type: FUNC
255 */
256HWTEST_F(UtilsAshmemTest, test_ashmem_InvalidOperation_003, TestSize.Level0)
257{
258    sptr<Ashmem> ashmem = Ashmem::CreateAshmem(MEMORY_NAME.c_str(), MEMORY_SIZE);
259    ASSERT_TRUE(ashmem != nullptr);
260
261    bool ret = ashmem->MapReadAndWriteAshmem();
262    ASSERT_TRUE(ret);
263
264    ashmem->CloseAshmem();
265
266    ret = ashmem->WriteToAshmem(MEMORY_CONTENT.c_str(), sizeof(MEMORY_CONTENT), 0);
267    ASSERT_FALSE(ret);
268
269    auto readData = ashmem->ReadFromAshmem(sizeof(MEMORY_CONTENT), 0);
270    ASSERT_TRUE(readData == nullptr);
271}
272
273/**
274 * @tc.name: test_ashmem_InvalidOperation_004
275 * @tc.desc: write or read after unmapping ashmem
276 * @tc.type: FUNC
277 */
278HWTEST_F(UtilsAshmemTest, test_ashmem_InvalidOperation_004, TestSize.Level0)
279{
280    sptr<Ashmem> ashmem = Ashmem::CreateAshmem(MEMORY_NAME.c_str(), MEMORY_SIZE);
281    ASSERT_TRUE(ashmem != nullptr);
282
283    bool ret = ashmem->MapReadAndWriteAshmem();
284    ASSERT_TRUE(ret);
285
286    ashmem->UnmapAshmem();
287
288    ret = ashmem->WriteToAshmem(MEMORY_CONTENT.c_str(), sizeof(MEMORY_CONTENT), 0);
289    ASSERT_FALSE(ret);
290
291    auto readData = ashmem->ReadFromAshmem(sizeof(MEMORY_CONTENT), 0);
292    ASSERT_TRUE(readData == nullptr);
293
294    ashmem->CloseAshmem();
295}
296
297/**
298 * @tc.name: test_ashmem_InvalidOperation_005
299 * @tc.desc: expand protection type
300 * @tc.type: FUNC
301 */
302HWTEST_F(UtilsAshmemTest, test_ashmem_InvalidOperation_005, TestSize.Level0)
303{
304    sptr<Ashmem> ashmem = Ashmem::CreateAshmem(MEMORY_NAME.c_str(), MEMORY_SIZE);
305    ASSERT_TRUE(ashmem != nullptr);
306
307    bool ret = ashmem->SetProtection(PROT_WRITE);
308    ASSERT_TRUE(ret);
309
310    ret = ashmem->SetProtection(PROT_READ);
311    ASSERT_FALSE(ret);
312
313    ret = ashmem->SetProtection(PROT_READ | PROT_WRITE);
314    ASSERT_FALSE(ret);
315
316    ret = ashmem->SetProtection(PROT_NONE);
317    ASSERT_TRUE(ret);
318
319    ret = ashmem->SetProtection(PROT_READ);
320    ASSERT_FALSE(ret);
321
322    ashmem->CloseAshmem();
323}
324
325/**
326 * @tc.name: test_ashmem_InvalidOperation_006
327 * @tc.desc: test invalid input or test invalid operation
328 * @tc.type: FUNC
329 */
330HWTEST_F(UtilsAshmemTest, test_ashmem_InvalidOperation_006, TestSize.Level0)
331{
332    sptr<Ashmem> ashmem = Ashmem::CreateAshmem(MEMORY_NAME.c_str(), MEMORY_SIZE);
333    ASSERT_TRUE(ashmem != nullptr);
334
335    bool ret = ashmem->MapReadAndWriteAshmem();
336    ASSERT_TRUE(ret);
337
338    ret = ashmem->WriteToAshmem(nullptr, sizeof(MEMORY_CONTENT), 0);
339    EXPECT_FALSE(ret);
340
341    ret = ashmem->WriteToAshmem(MEMORY_CONTENT.c_str(), sizeof(MEMORY_CONTENT), MEMORY_SIZE+1);
342    EXPECT_FALSE(ret);
343
344    ret = ashmem->WriteToAshmem(MEMORY_CONTENT.c_str(), sizeof(MEMORY_CONTENT), -1);
345    EXPECT_FALSE(ret);
346
347    ret = ashmem->WriteToAshmem(MEMORY_CONTENT.c_str(), MEMORY_SIZE+1, 0);
348    EXPECT_FALSE(ret);
349
350    ret = ashmem->WriteToAshmem(MEMORY_CONTENT.c_str(), -1, 0);
351    EXPECT_FALSE(ret);
352
353    ret = ashmem->WriteToAshmem(MEMORY_CONTENT.c_str(), sizeof(MEMORY_CONTENT), MEMORY_SIZE);
354    EXPECT_FALSE(ret);
355
356    ashmem->UnmapAshmem();
357    ashmem->CloseAshmem();
358
359    ashmem->GetAshmemSize();
360    EXPECT_FALSE(ret);
361
362    ashmem->GetProtection();
363    EXPECT_FALSE(ret);
364
365    ashmem->UnmapAshmem();
366    EXPECT_FALSE(ret);
367
368    ashmem->CloseAshmem();
369    EXPECT_FALSE(ret);
370}
371}  // namespace
372}  // namespace OHOS