1 /*
2 * Copyright (c) 2025 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 #include <cstring>
16 #include <iostream>
17 #include <gmock/gmock.h>
18 #include <gtest/gtest.h>
19 #include <sys/mman.h>
20
21 #include "message_parcel_warp.h"
22 using namespace testing;
23 using namespace testing::ext;
24 using namespace OHOS;
25
26 namespace OHOS {
27
28 constexpr size_t MIN_RAW_SIZE = 32 * 1024; // 32k
29 class MessageParcelWarpInterface {
30 public:
MessageParcelWarpInterface()31 MessageParcelWarpInterface() {};
~MessageParcelWarpInterface()32 virtual ~MessageParcelWarpInterface() {};
33
34 virtual bool WriteInt64(int64_t value) = 0;
35 virtual int64_t ReadInt64() = 0;
36 virtual bool WriteFileDescriptor(int fd) = 0;
37 virtual int ReadFileDescriptor() = 0;
38 virtual bool WriteUnpadBuffer(const void *data, size_t size) = 0;
39 virtual uint8_t *ReadUnpadBuffer(size_t length) = 0;
40 };
41
42 class MessageParcelWarpMock : public MessageParcelWarpInterface {
43 public:
44 MessageParcelWarpMock();
45 ~MessageParcelWarpMock() override;
46
47 MOCK_METHOD1(WriteInt64, bool(int64_t value));
48 MOCK_METHOD0(ReadInt64, int64_t());
49 MOCK_METHOD1(WriteFileDescriptor, bool(int fd));
50 MOCK_METHOD0(ReadFileDescriptor, int());
51 MOCK_METHOD2(WriteUnpadBuffer, bool(const void *data, size_t size));
52 MOCK_METHOD1(ReadUnpadBuffer, uint8_t *(size_t length));
53 };
54
55 static void *g_interface = nullptr;
56
MessageParcelWarpMock()57 MessageParcelWarpMock::MessageParcelWarpMock()
58 {
59 g_interface = reinterpret_cast<void *>(this);
60 }
61
~MessageParcelWarpMock()62 MessageParcelWarpMock::~MessageParcelWarpMock()
63 {
64 g_interface = nullptr;
65 }
66
GetMessageParcelWarpInterface()67 static MessageParcelWarpInterface *GetMessageParcelWarpInterface()
68 {
69 return reinterpret_cast<MessageParcelWarpInterface *>(g_interface);
70 }
71
72 extern "C" {
WriteInt64(int64_t value)73 bool Parcel::WriteInt64(int64_t value)
74 {
75 if (GetMessageParcelWarpInterface() == nullptr) {
76 return false;
77 }
78 return GetMessageParcelWarpInterface()->WriteInt64(value);
79 }
ReadInt64()80 int64_t Parcel::ReadInt64()
81 {
82 if (GetMessageParcelWarpInterface() == nullptr) {
83 return 0;
84 }
85 return GetMessageParcelWarpInterface()->ReadInt64();
86 }
WriteFileDescriptor(int fd)87 bool MessageParcel::WriteFileDescriptor(int fd)
88 {
89 if (GetMessageParcelWarpInterface() == nullptr) {
90 return false;
91 }
92 return GetMessageParcelWarpInterface()->WriteFileDescriptor(fd);
93 }
ReadFileDescriptor()94 int MessageParcel::ReadFileDescriptor()
95 {
96 if (GetMessageParcelWarpInterface() == nullptr) {
97 return 0;
98 }
99 return GetMessageParcelWarpInterface()->ReadFileDescriptor();
100 }
WriteUnpadBuffer(const void * data,size_t size)101 bool Parcel::WriteUnpadBuffer(const void *data, size_t size)
102 {
103 if (GetMessageParcelWarpInterface() == nullptr) {
104 return false;
105 }
106 return GetMessageParcelWarpInterface()->WriteUnpadBuffer(data, size);
107 }
ReadUnpadBuffer(size_t length)108 const uint8_t *Parcel::ReadUnpadBuffer(size_t length)
109 {
110 if (GetMessageParcelWarpInterface() == nullptr) {
111 return nullptr;
112 }
113 return GetMessageParcelWarpInterface()->ReadUnpadBuffer(length);
114 }
115 }
116
117 namespace MiscServices {
118 class MessageParcelWarpTest : public testing::Test {
119 public:
120 static void SetUpTestCase(void);
121 static void TearDownTestCase(void);
122 void SetUp();
123 void TearDown();
124 };
125
SetUpTestCase(void)126 void MessageParcelWarpTest::SetUpTestCase(void) { }
127
TearDownTestCase(void)128 void MessageParcelWarpTest::TearDownTestCase(void) { }
129
SetUp(void)130 void MessageParcelWarpTest::SetUp(void) { }
131
TearDown(void)132 void MessageParcelWarpTest::TearDown(void) { }
133
134 /**
135 * @tc.name: MemcpyDataTest001
136 * @tc.desc: Test MemcpyData
137 * @tc.type: FUNC
138 * @tc.require:
139 */
140 HWTEST_F(MessageParcelWarpTest, MemcpyDataTest001, TestSize.Level0)
141 {
142 MessageParcelWarp messageParcelWarp;
143 size_t size = 1024;
144 void* ptr = mmap(nullptr, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
145 const char data[] = "Test data";
146 size_t count = strlen(data) + 1;
147
148 auto result = messageParcelWarp.MemcpyData(ptr, size, data, count);
149 EXPECT_TRUE(result);
150
151 char* resultData = static_cast<char*>(ptr);
152 EXPECT_STREQ(resultData, data);
153 munmap(ptr, size);
154 }
155
156 /**
157 * @tc.name: MemcpyDataTest002
158 * @tc.desc: Test MemcpyData
159 * @tc.type: FUNC
160 * @tc.require:
161 */
162 HWTEST_F(MessageParcelWarpTest, MemcpyDataTest002, TestSize.Level0)
163 {
164 MessageParcelWarp messageParcelWarp;
165 size_t size = 256 * 1024 * 1024 + 1;
166 void* ptr = mmap(nullptr, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
167 char* data = new char[size];
168 std::fill(data, data + size, 'A');
169
170 auto result = messageParcelWarp.MemcpyData(ptr, size, data, size);
171 EXPECT_TRUE(result);
172
173 char* resultData = static_cast<char*>(ptr);
174 EXPECT_STREQ(resultData, data);
175 munmap(ptr, size);
176 }
177
178 /**
179 * @tc.name: WriteRawDataTest001
180 * @tc.desc: Test WriteRawData
181 * @tc.type: FUNC
182 * @tc.require:
183 */
184 HWTEST_F(MessageParcelWarpTest, WriteRawDataTest001, TestSize.Level0)
185 {
186 MessageParcelWarp messageParcelWarp;
187 MessageParcel parcel;
188 const char data[] = "Test data";
189 size_t size = strlen(data) + 1;
190
191 NiceMock<MessageParcelWarpMock> mock;
192 EXPECT_CALL(mock, WriteInt64).WillOnce(testing::Return(false));
193
194 auto result = messageParcelWarp.WriteRawData(parcel, data, size);
195 EXPECT_FALSE(result);
196 }
197
198 /**
199 * @tc.name: WriteRawDataTest002
200 * @tc.desc: Test WriteRawData
201 * @tc.type: FUNC
202 * @tc.require:
203 */
204 HWTEST_F(MessageParcelWarpTest, WriteRawDataTest002, TestSize.Level0)
205 {
206 MessageParcelWarp messageParcelWarp;
207 MessageParcel parcel;
208 const char data[] = "Test data";
209 size_t size = strlen(data) + 1;
210
211 NiceMock<MessageParcelWarpMock> mock;
212 EXPECT_CALL(mock, WriteInt64).WillOnce(testing::Return(true));
213 EXPECT_CALL(mock, WriteUnpadBuffer).WillOnce(testing::Return(true));
214
215 auto result = messageParcelWarp.WriteRawData(parcel, data, size);
216 EXPECT_TRUE(result);
217 }
218
219 /**
220 * @tc.name: WriteRawDataTest003
221 * @tc.desc: Test WriteRawData
222 * @tc.type: FUNC
223 * @tc.require:
224 */
225 HWTEST_F(MessageParcelWarpTest, WriteRawDataTest003, TestSize.Level0)
226 {
227 MessageParcelWarp messageParcelWarp;
228 MessageParcel parcel;
229 size_t size = MIN_RAW_SIZE + 1;
230 const char* data = new char[size];
231 std::fill(const_cast<char*>(data), const_cast<char*>(data) + size, 'A');
232
233 NiceMock<MessageParcelWarpMock> mock;
234 EXPECT_CALL(mock, WriteInt64).WillOnce(testing::Return(true));
235 EXPECT_CALL(mock, WriteFileDescriptor).WillOnce(testing::Return(false));
236
237 auto result = messageParcelWarp.WriteRawData(parcel, data, size);
238 EXPECT_FALSE(result);
239 }
240
241 /**
242 * @tc.name: WriteRawDataTest004
243 * @tc.desc: Test WriteRawData
244 * @tc.type: FUNC
245 * @tc.require:
246 */
247 HWTEST_F(MessageParcelWarpTest, WriteRawDataTest004, TestSize.Level0)
248 {
249 MessageParcelWarp messageParcelWarp;
250 MessageParcel parcel;
251 size_t size = MIN_RAW_SIZE + 1;
252 const char* data = new char[size];
253 std::fill(const_cast<char*>(data), const_cast<char*>(data) + size, 'A');
254
255 NiceMock<MessageParcelWarpMock> mock;
256 EXPECT_CALL(mock, WriteInt64).WillOnce(testing::Return(true));
257 EXPECT_CALL(mock, WriteFileDescriptor).WillOnce(testing::Return(true));
258
259 auto result = messageParcelWarp.WriteRawData(parcel, data, size);
260 EXPECT_TRUE(result);
261 }
262
263 /**
264 * @tc.name: ReadRawDataTest001
265 * @tc.desc: Test ReadRawData
266 * @tc.type: FUNC
267 * @tc.require:
268 */
269 HWTEST_F(MessageParcelWarpTest, ReadRawDataTest001, TestSize.Level0)
270 {
271 MessageParcelWarp messageParcelWarp;
272 MessageParcel parcel;
273 size_t size = MIN_RAW_SIZE - 1;
274
275 NiceMock<MessageParcelWarpMock> mock;
276 EXPECT_CALL(mock, ReadInt64).WillOnce(testing::Return(1));
277 EXPECT_CALL(mock, ReadUnpadBuffer).WillRepeatedly(testing::Return(nullptr));
278
279 auto result = messageParcelWarp.ReadRawData(parcel, size);
280 EXPECT_EQ(result, nullptr);
281 }
282
283 /**
284 * @tc.name: ReadRawDataTest002
285 * @tc.desc: Test ReadRawData
286 * @tc.type: FUNC
287 * @tc.require:
288 */
289 HWTEST_F(MessageParcelWarpTest, ReadRawDataTest002, TestSize.Level0)
290 {
291 MessageParcelWarp messageParcelWarp;
292 messageParcelWarp.rawData_ = std::make_shared<char>('A');
293 messageParcelWarp.writeRawDataFd_ = 0;
294 MessageParcel parcel;
295 size_t size = MIN_RAW_SIZE + 1;
296
297 NiceMock<MessageParcelWarpMock> mock;
298 EXPECT_CALL(mock, ReadInt64).WillOnce(testing::Return(size));
299 EXPECT_CALL(mock, ReadFileDescriptor).WillRepeatedly(testing::Return(1));
300
301 auto result = messageParcelWarp.ReadRawData(parcel, size);
302 EXPECT_NE(result, messageParcelWarp.rawData_.get());
303 }
304
305 /**
306 * @tc.name: ReadRawDataTest003
307 * @tc.desc: Test ReadRawData
308 * @tc.type: FUNC
309 * @tc.require:
310 */
311 HWTEST_F(MessageParcelWarpTest, ReadRawDataTest003, TestSize.Level0)
312 {
313 MessageParcelWarp messageParcelWarp;
314 messageParcelWarp.rawData_ = nullptr;
315 MessageParcel parcel;
316 size_t size = MIN_RAW_SIZE + 1;
317
318 NiceMock<MessageParcelWarpMock> mock;
319 EXPECT_CALL(mock, ReadInt64).WillOnce(testing::Return(size));
320 EXPECT_CALL(mock, ReadFileDescriptor).WillRepeatedly(testing::Return(-1));
321
322 auto result = messageParcelWarp.ReadRawData(parcel, size);
323 EXPECT_EQ(result, nullptr);
324 }
325 }
326 }