blob: 32a70e5b1101ba79be4c13d70f3545a6f12c06ef [file] [log] [blame]
Steven Morelandcefba612020-11-05 22:57:06 +00001/*
2 * Copyright (C) 2020 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Steven Morelandcefba612020-11-05 22:57:06 +000017#include <binder/IPCThreadState.h>
Steven Morelandf80809b2021-10-07 18:09:20 -070018#include <binder/Parcel.h>
Jooyung Hand23f9502021-12-23 14:39:57 +090019#include <binder/Status.h>
Steven Morelandf80809b2021-10-07 18:09:20 -070020#include <cutils/ashmem.h>
Steven Morelandcefba612020-11-05 22:57:06 +000021#include <gtest/gtest.h>
22
Steven Moreland4b2f18d2022-03-24 00:32:25 +000023using android::BBinder;
24using android::IBinder;
Steven Morelandcefba612020-11-05 22:57:06 +000025using android::IPCThreadState;
sandeepbandaruaa9d3a32024-02-22 17:16:53 +000026using android::NO_ERROR;
Steven Morelandcefba612020-11-05 22:57:06 +000027using android::OK;
28using android::Parcel;
Steven Moreland4b2f18d2022-03-24 00:32:25 +000029using android::sp;
Jooyung Hand23f9502021-12-23 14:39:57 +090030using android::status_t;
Steven Morelandcefba612020-11-05 22:57:06 +000031using android::String16;
32using android::String8;
Jooyung Hand23f9502021-12-23 14:39:57 +090033using android::binder::Status;
Tomasz Wasilczyk639490b2023-11-01 13:49:41 -070034using android::binder::unique_fd;
Steven Morelandcefba612020-11-05 22:57:06 +000035
Steven Moreland8f39fa02020-11-18 00:35:25 +000036TEST(Parcel, NonNullTerminatedString8) {
37 String8 kTestString = String8("test-is-good");
38
39 // write non-null terminated string
40 Parcel p;
41 p.writeString8(kTestString);
42 p.setDataPosition(0);
43 // BAD! assumption of wire format for test
44 // write over length of string
45 p.writeInt32(kTestString.size() - 2);
46
47 p.setDataPosition(0);
48 String8 output;
49 EXPECT_NE(OK, p.readString8(&output));
50 EXPECT_EQ(output.size(), 0);
51}
52
53TEST(Parcel, NonNullTerminatedString16) {
54 String16 kTestString = String16("test-is-good");
55
56 // write non-null terminated string
57 Parcel p;
58 p.writeString16(kTestString);
59 p.setDataPosition(0);
60 // BAD! assumption of wire format for test
61 // write over length of string
62 p.writeInt32(kTestString.size() - 2);
63
64 p.setDataPosition(0);
65 String16 output;
66 EXPECT_NE(OK, p.readString16(&output));
67 EXPECT_EQ(output.size(), 0);
68}
69
Jooyung Hand23f9502021-12-23 14:39:57 +090070TEST(Parcel, EnforceNoDataAvail) {
71 const int32_t kTestInt = 42;
72 const String8 kTestString = String8("test-is-good");
73 Parcel p;
74 p.writeInt32(kTestInt);
75 p.writeString8(kTestString);
76 p.setDataPosition(0);
77 EXPECT_EQ(kTestInt, p.readInt32());
78 EXPECT_EQ(p.enforceNoDataAvail().exceptionCode(), Status::Exception::EX_BAD_PARCELABLE);
79 EXPECT_EQ(kTestString, p.readString8());
80 EXPECT_EQ(p.enforceNoDataAvail().exceptionCode(), Status::Exception::EX_NONE);
81}
82
Steven Moreland4b2f18d2022-03-24 00:32:25 +000083TEST(Parcel, DebugReadAllBinders) {
84 sp<IBinder> binder1 = sp<BBinder>::make();
85 sp<IBinder> binder2 = sp<BBinder>::make();
86
87 Parcel p;
88 p.writeInt32(4);
89 p.writeStrongBinder(binder1);
90 p.writeStrongBinder(nullptr);
91 p.writeInt32(4);
92 p.writeStrongBinder(binder2);
93 p.writeInt32(4);
94
95 auto ret = p.debugReadAllStrongBinders();
96
97 ASSERT_EQ(ret.size(), 2);
98 EXPECT_EQ(ret[0], binder1);
99 EXPECT_EQ(ret[1], binder2);
100}
101
102TEST(Parcel, DebugReadAllFds) {
103 Parcel p;
104 p.writeInt32(4);
105 p.writeFileDescriptor(STDOUT_FILENO, false /*takeOwnership*/);
106 p.writeInt32(4);
107 p.writeFileDescriptor(STDIN_FILENO, false /*takeOwnership*/);
108 p.writeInt32(4);
109
110 auto ret = p.debugReadAllFileDescriptors();
111
112 ASSERT_EQ(ret.size(), 2);
113 EXPECT_EQ(ret[0], STDOUT_FILENO);
114 EXPECT_EQ(ret[1], STDIN_FILENO);
115}
116
Steven Morelanda2f835d2023-06-15 16:50:05 +0000117TEST(Parcel, AppendFromEmpty) {
118 Parcel p1;
119 Parcel p2;
120 p2.writeInt32(2);
121
122 ASSERT_EQ(OK, p1.appendFrom(&p2, 0, p2.dataSize()));
123
124 p1.setDataPosition(0);
125 ASSERT_EQ(2, p1.readInt32());
126
127 p2.setDataPosition(0);
128 ASSERT_EQ(2, p2.readInt32());
129}
130
131TEST(Parcel, AppendPlainData) {
132 Parcel p1;
133 p1.writeInt32(1);
134 Parcel p2;
135 p2.writeInt32(2);
136
137 ASSERT_EQ(OK, p1.appendFrom(&p2, 0, p2.dataSize()));
138
139 p1.setDataPosition(0);
140 ASSERT_EQ(1, p1.readInt32());
141 ASSERT_EQ(2, p1.readInt32());
142
143 p2.setDataPosition(0);
144 ASSERT_EQ(2, p2.readInt32());
145}
146
147TEST(Parcel, AppendPlainDataPartial) {
148 Parcel p1;
149 p1.writeInt32(1);
150 Parcel p2;
151 p2.writeInt32(2);
152 p2.writeInt32(3);
153 p2.writeInt32(4);
154
155 // only copy 8 bytes (two int32's worth)
156 ASSERT_EQ(OK, p1.appendFrom(&p2, 0, 8));
157
158 p1.setDataPosition(0);
159 ASSERT_EQ(1, p1.readInt32());
160 ASSERT_EQ(2, p1.readInt32());
161 ASSERT_EQ(3, p1.readInt32());
162 ASSERT_EQ(0, p1.readInt32()); // not 4, end of Parcel
163
164 p2.setDataPosition(0);
165 ASSERT_EQ(2, p2.readInt32());
166}
167
sandeepbandaruaa9d3a32024-02-22 17:16:53 +0000168TEST(Parcel, HasBinders) {
169 sp<IBinder> b1 = sp<BBinder>::make();
170
171 Parcel p1;
172 p1.writeInt32(1);
173 p1.writeStrongBinder(b1);
174
175 bool result = false;
176 ASSERT_EQ(NO_ERROR, p1.hasBinders(&result));
177 ASSERT_EQ(true, result);
178
179 p1.setDataSize(0); // clear data
180 result = false;
181 ASSERT_EQ(NO_ERROR, p1.hasBinders(&result));
182 ASSERT_EQ(false, result);
183 p1.writeStrongBinder(b1); // reset with binder data
184 result = false;
185 ASSERT_EQ(NO_ERROR, p1.hasBinders(&result));
186 ASSERT_EQ(true, result);
187
188 Parcel p3;
189 p3.appendFrom(&p1, 0, p1.dataSize());
190 result = false;
191 ASSERT_EQ(NO_ERROR, p1.hasBinders(&result));
192 ASSERT_EQ(true, result);
193}
194
195TEST(Parcel, HasBindersInRange) {
196 sp<IBinder> b1 = sp<BBinder>::make();
197 Parcel p1;
198 p1.writeStrongBinder(b1);
199 bool result = false;
200 ASSERT_EQ(NO_ERROR, p1.hasBindersInRange(0, p1.dataSize(), &result));
201 ASSERT_EQ(true, result);
202 result = false;
203 ASSERT_EQ(NO_ERROR, p1.hasBinders(&result));
204 ASSERT_EQ(true, result);
205}
206
Steven Morelanda2f835d2023-06-15 16:50:05 +0000207TEST(Parcel, AppendWithBinder) {
208 sp<IBinder> b1 = sp<BBinder>::make();
209 sp<IBinder> b2 = sp<BBinder>::make();
210
211 Parcel p1;
212 p1.writeInt32(1);
213 p1.writeStrongBinder(b1);
214 Parcel p2;
215 p2.writeInt32(2);
216 p2.writeStrongBinder(b2);
217
218 ASSERT_EQ(OK, p1.appendFrom(&p2, 0, p2.dataSize()));
219
220 p1.setDataPosition(0);
221 ASSERT_EQ(1, p1.readInt32());
222 ASSERT_EQ(b1, p1.readStrongBinder());
223 ASSERT_EQ(2, p1.readInt32());
224 ASSERT_EQ(b2, p1.readStrongBinder());
225 ASSERT_EQ(2, p1.objectsCount());
226
227 p2.setDataPosition(0);
228 ASSERT_EQ(2, p2.readInt32());
229 ASSERT_EQ(b2, p2.readStrongBinder());
230}
231
232TEST(Parcel, AppendWithBinderPartial) {
233 sp<IBinder> b1 = sp<BBinder>::make();
234 sp<IBinder> b2 = sp<BBinder>::make();
235
236 Parcel p1;
237 p1.writeInt32(1);
238 p1.writeStrongBinder(b1);
239 Parcel p2;
240 p2.writeInt32(2);
241 p2.writeStrongBinder(b2);
242
243 ASSERT_EQ(OK, p1.appendFrom(&p2, 0, 8)); // BAD: 4 bytes into strong binder
244
245 p1.setDataPosition(0);
246 ASSERT_EQ(1, p1.readInt32());
247 ASSERT_EQ(b1, p1.readStrongBinder());
248 ASSERT_EQ(2, p1.readInt32());
249 ASSERT_EQ(1935813253, p1.readInt32()); // whatever garbage that is there (ABI)
250 ASSERT_EQ(1, p1.objectsCount());
251
252 p2.setDataPosition(0);
253 ASSERT_EQ(2, p2.readInt32());
254 ASSERT_EQ(b2, p2.readStrongBinder());
255}
256
257TEST(Parcel, AppendWithFd) {
258 unique_fd fd1 = unique_fd(dup(0));
259 unique_fd fd2 = unique_fd(dup(0));
260
261 Parcel p1;
262 p1.writeInt32(1);
263 p1.writeDupFileDescriptor(0); // with ownership
264 p1.writeFileDescriptor(fd1.get()); // without ownership
265 Parcel p2;
266 p2.writeInt32(2);
267 p2.writeDupFileDescriptor(0); // with ownership
268 p2.writeFileDescriptor(fd2.get()); // without ownership
269
270 ASSERT_EQ(OK, p1.appendFrom(&p2, 0, p2.dataSize()));
271
272 p1.setDataPosition(0);
273 ASSERT_EQ(1, p1.readInt32());
274 ASSERT_NE(-1, p1.readFileDescriptor());
275 ASSERT_NE(-1, p1.readFileDescriptor());
276 ASSERT_EQ(2, p1.readInt32());
277 ASSERT_NE(-1, p1.readFileDescriptor());
278 ASSERT_NE(-1, p1.readFileDescriptor());
279 ASSERT_EQ(4, p1.objectsCount());
280
281 p2.setDataPosition(0);
282 ASSERT_EQ(2, p2.readInt32());
283 ASSERT_NE(-1, p1.readFileDescriptor());
284 ASSERT_NE(-1, p1.readFileDescriptor());
285}
286
287TEST(Parcel, AppendWithFdPartial) {
288 unique_fd fd1 = unique_fd(dup(0));
289 unique_fd fd2 = unique_fd(dup(0));
290
291 Parcel p1;
292 p1.writeInt32(1);
293 p1.writeDupFileDescriptor(0); // with ownership
294 p1.writeFileDescriptor(fd1.get()); // without ownership
295 Parcel p2;
296 p2.writeInt32(2);
297 p2.writeDupFileDescriptor(0); // with ownership
298 p2.writeFileDescriptor(fd2.get()); // without ownership
299
300 ASSERT_EQ(OK, p1.appendFrom(&p2, 0, 8)); // BAD: 4 bytes into binder
301
302 p1.setDataPosition(0);
303 ASSERT_EQ(1, p1.readInt32());
304 ASSERT_NE(-1, p1.readFileDescriptor());
305 ASSERT_NE(-1, p1.readFileDescriptor());
306 ASSERT_EQ(2, p1.readInt32());
307 ASSERT_EQ(1717840517, p1.readInt32()); // whatever garbage that is there (ABI)
308 ASSERT_EQ(2, p1.objectsCount());
309
310 p2.setDataPosition(0);
311 ASSERT_EQ(2, p2.readInt32());
312 ASSERT_NE(-1, p1.readFileDescriptor());
313 ASSERT_NE(-1, p1.readFileDescriptor());
314}
315
Steven Morelandcefba612020-11-05 22:57:06 +0000316// Tests a second operation results in a parcel at the same location as it
317// started.
318void parcelOpSameLength(const std::function<void(Parcel*)>& a, const std::function<void(Parcel*)>& b) {
319 Parcel p;
320 a(&p);
321 size_t end = p.dataPosition();
322 p.setDataPosition(0);
323 b(&p);
324 EXPECT_EQ(end, p.dataPosition());
325}
326
327TEST(Parcel, InverseInterfaceToken) {
328 const String16 token = String16("asdf");
329 parcelOpSameLength([&] (Parcel* p) {
330 p->writeInterfaceToken(token);
331 }, [&] (Parcel* p) {
332 EXPECT_TRUE(p->enforceInterface(token, IPCThreadState::self()));
333 });
334}
335
336TEST(Parcel, Utf8FromUtf16Read) {
337 const char* token = "asdf";
338 parcelOpSameLength([&] (Parcel* p) {
339 p->writeString16(String16(token));
340 }, [&] (Parcel* p) {
341 std::string s;
342 EXPECT_EQ(OK, p->readUtf8FromUtf16(&s));
343 EXPECT_EQ(token, s);
344 });
345}
346
347TEST(Parcel, Utf8AsUtf16Write) {
348 std::string token = "asdf";
349 parcelOpSameLength([&] (Parcel* p) {
350 p->writeUtf8AsUtf16(token);
351 }, [&] (Parcel* p) {
352 String16 s;
353 EXPECT_EQ(OK, p->readString16(&s));
354 EXPECT_EQ(s, String16(token.c_str()));
355 });
356}
357
358template <typename T>
359using readFunc = status_t (Parcel::*)(T* out) const;
360template <typename T>
361using writeFunc = status_t (Parcel::*)(const T& in);
362template <typename T>
363using copyWriteFunc = status_t (Parcel::*)(T in);
364
365template <typename T, typename WRITE_FUNC>
366void readWriteInverse(std::vector<T>&& ts, readFunc<T> r, WRITE_FUNC w) {
367 for (const T& value : ts) {
368 parcelOpSameLength([&] (Parcel* p) {
369 (*p.*w)(value);
370 }, [&] (Parcel* p) {
371 T outValue;
372 EXPECT_EQ(OK, (*p.*r)(&outValue));
373 EXPECT_EQ(value, outValue);
374 });
375 }
376}
377
378template <typename T>
379void readWriteInverse(std::vector<T>&& ts, readFunc<T> r, writeFunc<T> w) {
380 readWriteInverse<T, writeFunc<T>>(std::move(ts), r, w);
381}
382template <typename T>
383void readWriteInverse(std::vector<T>&& ts, readFunc<T> r, copyWriteFunc<T> w) {
384 readWriteInverse<T, copyWriteFunc<T>>(std::move(ts), r, w);
385}
386
387#define TEST_READ_WRITE_INVERSE(type, name, ...) \
388 TEST(Parcel, Inverse##name) { \
389 readWriteInverse<type>(__VA_ARGS__, &Parcel::read##name, &Parcel::write##name); \
390 }
391
392TEST_READ_WRITE_INVERSE(int32_t, Int32, {-2, -1, 0, 1, 2});
393TEST_READ_WRITE_INVERSE(uint32_t, Uint32, {0, 1, 2});
394TEST_READ_WRITE_INVERSE(int64_t, Int64, {-2, -1, 0, 1, 2});
395TEST_READ_WRITE_INVERSE(uint64_t, Uint64, {0, 1, 2});
396TEST_READ_WRITE_INVERSE(float, Float, {-1.0f, 0.0f, 3.14f});
397TEST_READ_WRITE_INVERSE(double, Double, {-1.0, 0.0, 3.14});
398TEST_READ_WRITE_INVERSE(bool, Bool, {true, false});
399TEST_READ_WRITE_INVERSE(char16_t, Char, {u'a', u'\0'});
400TEST_READ_WRITE_INVERSE(int8_t, Byte, {-1, 0, 1});
401TEST_READ_WRITE_INVERSE(String8, String8, {String8(), String8("a"), String8("asdf")});
402TEST_READ_WRITE_INVERSE(String16, String16, {String16(), String16("a"), String16("asdf")});
Steven Morelandf80809b2021-10-07 18:09:20 -0700403
404TEST(Parcel, GetOpenAshmemSize) {
405 constexpr size_t kSize = 1024;
406 constexpr size_t kCount = 3;
407
408 Parcel p;
409
410 for (size_t i = 0; i < kCount; i++) {
411 int fd = ashmem_create_region("test-getOpenAshmemSize", kSize);
412 ASSERT_GE(fd, 0);
413 ASSERT_EQ(OK, p.writeFileDescriptor(fd, true /* take ownership */));
414
415 ASSERT_EQ((kSize * (i + 1)), p.getOpenAshmemSize());
416 }
417}