1 /*
2 * Copyright (C) 2015 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
17 #include <android/aidl/tests/ParcelableForToString.h>
18 #include <android/aidl/tests/extension/MyExt.h>
19 #include <android/aidl/tests/extension/MyExt2.h>
20 #include <android/aidl/tests/extension/MyExtLike.h>
21 #include <android/aidl/tests/unions/EnumUnion.h>
22 #include "aidl_test_client.h"
23
24 #include <string>
25 #include <vector>
26
27 using android::IInterface;
28 using android::sp;
29 using android::String16;
30 using android::aidl::tests::ConstantExpressionEnum;
31 using android::aidl::tests::GenericStructuredParcelable;
32 using android::aidl::tests::INamedCallback;
33 using android::aidl::tests::IntEnum;
34 using android::aidl::tests::ITestService;
35 using android::aidl::tests::OtherParcelableForToString;
36 using android::aidl::tests::ParcelableForToString;
37 using android::aidl::tests::SimpleParcelable;
38 using android::aidl::tests::StructuredParcelable;
39 using android::aidl::tests::Union;
40 using android::aidl::tests::extension::ExtendableParcelable;
41 using android::aidl::tests::extension::MyExt;
42 using android::aidl::tests::extension::MyExt2;
43 using android::aidl::tests::extension::MyExtLike;
44 using android::aidl::tests::unions::EnumUnion;
45 using android::binder::Status;
46 using android::os::PersistableBundle;
47 using std::string;
48 using std::vector;
49
TEST_F(AidlTest,RepeatSimpleParcelable)50 TEST_F(AidlTest, RepeatSimpleParcelable) {
51 if (!cpp_java_tests) GTEST_SKIP() << "Service does not support the CPP/Java-only tests.";
52
53 SimpleParcelable input("Booya", 42);
54 SimpleParcelable out_param, returned;
55 Status status = cpp_java_tests->RepeatSimpleParcelable(input, &out_param, &returned);
56 ASSERT_TRUE(status.isOk()) << status.toString8();
57 EXPECT_EQ(input, out_param) << input.toString() << " " << out_param.toString();
58 EXPECT_EQ(input, returned) << input.toString() << " " << returned.toString();
59 }
60
TEST_F(AidlTest,RepeatGenericStructureParcelable)61 TEST_F(AidlTest, RepeatGenericStructureParcelable) {
62 if (!cpp_java_tests) GTEST_SKIP() << "Service does not support the CPP/Java-only tests.";
63
64 GenericStructuredParcelable<int32_t, StructuredParcelable, IntEnum> input, out_param, returned;
65 input.a = 41;
66 input.b = 42;
67 Status status = cpp_java_tests->RepeatGenericParcelable(input, &out_param, &returned);
68 ASSERT_TRUE(status.isOk()) << status.toString8();
69 EXPECT_EQ(input, out_param);
70 EXPECT_EQ(input, returned);
71 }
72
TEST_F(AidlTest,ReverseSimpleParcelable)73 TEST_F(AidlTest, ReverseSimpleParcelable) {
74 if (!cpp_java_tests) GTEST_SKIP() << "Service does not support the CPP/Java-only tests.";
75
76 const vector<SimpleParcelable> original{SimpleParcelable("first", 0),
77 SimpleParcelable("second", 1),
78 SimpleParcelable("third", 2)};
79 vector<SimpleParcelable> repeated;
80 if (backend == BackendType::JAVA) {
81 repeated = vector<SimpleParcelable>(original.size());
82 }
83 vector<SimpleParcelable> reversed;
84 Status status = cpp_java_tests->ReverseSimpleParcelables(original, &repeated, &reversed);
85 ASSERT_TRUE(status.isOk()) << status.toString8();
86
87 EXPECT_EQ(repeated, original);
88
89 std::reverse(reversed.begin(), reversed.end());
90 EXPECT_EQ(reversed, original);
91 }
92
TEST_F(AidlTest,ConfirmPersistableBundles)93 TEST_F(AidlTest, ConfirmPersistableBundles) {
94 if (!cpp_java_tests) GTEST_SKIP() << "Service does not support the CPP/Java-only tests.";
95
96 PersistableBundle empty_bundle, returned;
97 Status status = cpp_java_tests->RepeatPersistableBundle(empty_bundle, &returned);
98 ASSERT_TRUE(status.isOk()) << status.toString8();
99 EXPECT_EQ(empty_bundle, returned);
100 }
101
TEST_F(AidlTest,ConfirmPersistableBundlesNonEmpty)102 TEST_F(AidlTest, ConfirmPersistableBundlesNonEmpty) {
103 if (!cpp_java_tests) GTEST_SKIP() << "Service does not support the CPP/Java-only tests.";
104
105 PersistableBundle non_empty_bundle, returned;
106 non_empty_bundle.putBoolean(String16("test_bool"), false);
107 non_empty_bundle.putInt(String16("test_int"), 33);
108 non_empty_bundle.putLong(String16("test_long"), 34359738368L);
109 non_empty_bundle.putDouble(String16("test_double"), 1.1);
110 non_empty_bundle.putString(String16("test_string"), String16("Woot!"));
111 non_empty_bundle.putBooleanVector(String16("test_bool_vector"),
112 {true, false, true});
113 non_empty_bundle.putIntVector(String16("test_int_vector"), {33, 44, 55, 142});
114 non_empty_bundle.putLongVector(String16("test_long_vector"),
115 {34L, 8371L, 34359738375L});
116 non_empty_bundle.putDoubleVector(String16("test_double_vector"), {2.2, 5.4});
117 non_empty_bundle.putStringVector(String16("test_string_vector"),
118 {String16("hello"), String16("world!")});
119 PersistableBundle nested_bundle;
120 nested_bundle.putInt(String16("test_nested_int"), 345);
121 non_empty_bundle.putPersistableBundle(String16("test_persistable_bundle"),
122 nested_bundle);
123
124 Status status = cpp_java_tests->RepeatPersistableBundle(non_empty_bundle, &returned);
125 ASSERT_TRUE(status.isOk()) << status.toString8();
126 EXPECT_EQ(non_empty_bundle, returned);
127 }
128
TEST_F(AidlTest,ReversePersistableBundles)129 TEST_F(AidlTest, ReversePersistableBundles) {
130 if (!cpp_java_tests) GTEST_SKIP() << "Service does not support the CPP/Java-only tests.";
131
132 PersistableBundle first;
133 PersistableBundle second;
134 PersistableBundle third;
135 first.putInt(String16("test_int"), 1231);
136 second.putLong(String16("test_long"), 222222L);
137 third.putDouble(String16("test_double"), 10.8);
138 const vector<PersistableBundle> original{first, second, third};
139
140 vector<PersistableBundle> repeated;
141 if (backend == BackendType::JAVA) {
142 repeated = vector<PersistableBundle>(original.size());
143 }
144 vector<PersistableBundle> reversed;
145 Status status = cpp_java_tests->ReversePersistableBundles(original, &repeated, &reversed);
146 ASSERT_TRUE(status.isOk()) << status.toString8();
147
148 EXPECT_EQ(repeated, original);
149
150 std::reverse(reversed.begin(), reversed.end());
151 EXPECT_EQ(reversed, original);
152 }
153
TEST_F(AidlTest,ReverseUnion)154 TEST_F(AidlTest, ReverseUnion) {
155 if (!cpp_java_tests) GTEST_SKIP() << "Service does not support the CPP/Java-only tests.";
156
157 Union original = Union::make<Union::ns>({1, 2, 3});
158 Union repeated, reversed;
159 Status status = cpp_java_tests->ReverseUnion(original, &repeated, &reversed);
160 ASSERT_TRUE(status.isOk()) << status.toString8();
161
162 EXPECT_EQ(repeated, original);
163
164 std::reverse(reversed.get<Union::ns>().begin(), reversed.get<Union::ns>().end());
165 EXPECT_EQ(reversed, original);
166 }
167
TEST_F(AidlTest,UnionUsage)168 TEST_F(AidlTest, UnionUsage) {
169 // default ctor inits with first member's default value
170 EXPECT_EQ(Union::make<Union::ns>(), Union());
171
172 // make<tag>(...) to create a value for a tag.
173 Union one_two_three = Union::make<Union::ns>({1, 2, 3});
174
175 // getTag() queries the tag of the content
176 EXPECT_EQ(Union::ns, one_two_three.getTag());
177
178 // Ctor(...) works if a target tag has a unique type among fields.
179 EXPECT_EQ(one_two_three, Union(std::vector{1, 2, 3}));
180 EXPECT_EQ(one_two_three, std::vector<int>({1, 2, 3}));
181
182 // Use std::in_place_index<tag> to avoid "move"
183 // Note that make<tag>(...) involves "move" of the content value
184 EXPECT_EQ(Union::make<Union::ns>(3, 0), Union(std::in_place_index<Union::ns>, 3, 0));
185
186 Union one_two = one_two_three;
187 // get<tag> can be used to modify the content
188 one_two.get<Union::ns>().pop_back();
189 EXPECT_EQ(one_two, std::vector<int>({1, 2}));
190 // get<tag> can be lvalue
191 one_two.get<Union::ns>() = std::vector<int>{1, 2};
192 EXPECT_EQ(one_two, std::vector<int>({1, 2}));
193
194 // abort with a bad access
195 EXPECT_DEATH(one_two.get<Union::n>(), "bad access");
196
197 // set<tag>(...) overwrites the content with a new tag
198 one_two_three.set<Union::s>("123");
199 EXPECT_EQ(one_two_three, std::string("123"));
200
201 // Or, you can simply assign a new value.
202 // note that this works only if the target type is unique
203 one_two_three = std::vector<std::string>{"1", "2", "3"};
204 EXPECT_EQ(Union::ss, one_two_three.getTag());
205 }
206
TEST_F(AidlTest,UnionDefaultConstructorInitializeWithFirstMember)207 TEST_F(AidlTest, UnionDefaultConstructorInitializeWithFirstMember) {
208 EXPECT_EQ(Union::make<Union::ns>(), Union()); // int[] ns
209 EXPECT_EQ(EnumUnion::make<EnumUnion::intEnum>(IntEnum::FOO),
210 EnumUnion()); // IntEnum intEnum = IntEnum.FOO
211 }
212
TEST_F(AidlTest,StructuredParcelableEquality)213 TEST_F(AidlTest, StructuredParcelableEquality) {
214 // TODO: break up equality tests, these are hard to read, because you need to
215 // keep the state of the parcelables in mind
216 StructuredParcelable parcelable1;
217 StructuredParcelable parcelable2;
218
219 parcelable1.f = 11;
220 parcelable2.f = 11;
221
222 service->FillOutStructuredParcelable(&parcelable1);
223 service->FillOutStructuredParcelable(&parcelable2);
224
225 sp<INamedCallback> callback1;
226 sp<INamedCallback> callback2;
227 service->GetOtherTestService(String16("callback1"), &callback1);
228 service->GetOtherTestService(String16("callback2"), &callback2);
229
230 parcelable1.ibinder = IInterface::asBinder(callback1);
231 parcelable2.ibinder = IInterface::asBinder(callback1);
232
233 EXPECT_EQ(parcelable1, parcelable2);
234
235 parcelable1.f = 0;
236 EXPECT_LT(parcelable1, parcelable2);
237 parcelable1.f = 11;
238
239 parcelable1.shouldBeJerry = "Jarry";
240 EXPECT_LT(parcelable1, parcelable2);
241 parcelable1.shouldBeJerry = "Jerry";
242
243 parcelable2.shouldContainThreeFs = {};
244 EXPECT_GT(parcelable1, parcelable2);
245 parcelable2.shouldContainThreeFs = {parcelable2.f, parcelable2.f, parcelable2.f};
246
247 parcelable2.shouldBeIntBar = IntEnum::FOO;
248 EXPECT_GT(parcelable1, parcelable2);
249 parcelable2.shouldBeIntBar = IntEnum::BAR;
250
251 parcelable2.ibinder = IInterface::asBinder(callback2);
252 EXPECT_NE(parcelable1, parcelable2);
253 }
254
TEST_F(AidlTest,ConfirmStructuredParcelables)255 TEST_F(AidlTest, ConfirmStructuredParcelables) {
256 constexpr int kDesiredValue = 23;
257
258 StructuredParcelable parcelable;
259 parcelable.f = kDesiredValue;
260
261 EXPECT_EQ(parcelable.stringDefaultsToFoo, String16("foo"));
262 EXPECT_EQ(parcelable.byteDefaultsToFour, 4);
263 EXPECT_EQ(parcelable.intDefaultsToFive, 5);
264 EXPECT_EQ(parcelable.longDefaultsToNegativeSeven, -7);
265 EXPECT_EQ(parcelable.booleanDefaultsToTrue, true);
266 EXPECT_EQ(parcelable.charDefaultsToC, 'C');
267 EXPECT_TRUE(parcelable.floatDefaultsToPi == 3.14f) << parcelable.floatDefaultsToPi;
268 EXPECT_TRUE(parcelable.doubleWithDefault == -3.14e17) << parcelable.doubleWithDefault;
269
270 EXPECT_EQ(parcelable.boolDefault, false);
271 EXPECT_EQ(parcelable.byteDefault, 0);
272 EXPECT_EQ(parcelable.intDefault, 0);
273 EXPECT_EQ(parcelable.longDefault, 0);
274 EXPECT_EQ(parcelable.floatDefault, 0.0f);
275 EXPECT_EQ(parcelable.doubleDefault, 0.0);
276
277 ASSERT_EQ(parcelable.arrayDefaultsTo123.size(), 3u);
278 EXPECT_EQ(parcelable.arrayDefaultsTo123[0], 1);
279 EXPECT_EQ(parcelable.arrayDefaultsTo123[1], 2);
280 EXPECT_EQ(parcelable.arrayDefaultsTo123[2], 3);
281 EXPECT_TRUE(parcelable.arrayDefaultsToEmpty.empty());
282
283 EXPECT_EQ(parcelable.defaultWithFoo, IntEnum::FOO);
284
285 service->FillOutStructuredParcelable(&parcelable);
286
287 ASSERT_EQ(parcelable.shouldContainThreeFs.size(), 3u);
288 EXPECT_EQ(parcelable.shouldContainThreeFs[0], kDesiredValue);
289 EXPECT_EQ(parcelable.shouldContainThreeFs[1], kDesiredValue);
290 EXPECT_EQ(parcelable.shouldContainThreeFs[2], kDesiredValue);
291
292 EXPECT_EQ(parcelable.shouldBeJerry, "Jerry");
293 EXPECT_EQ(parcelable.int32_min, INT32_MIN);
294 EXPECT_EQ(parcelable.int32_max, INT32_MAX);
295 EXPECT_EQ(parcelable.int64_max, INT64_MAX);
296 EXPECT_EQ(parcelable.hexInt32_neg_1, -1);
297
298 for (size_t ndx = 0; ndx < parcelable.int32_1.size(); ndx++) {
299 EXPECT_EQ(parcelable.int32_1[ndx], 1) << ndx;
300 }
301
302 for (size_t ndx = 0; ndx < parcelable.int64_1.size(); ndx++) {
303 EXPECT_EQ(parcelable.int64_1[ndx], 1) << ndx;
304 }
305
306 EXPECT_EQ(parcelable.hexInt32_pos_1, 1);
307 EXPECT_EQ(parcelable.hexInt64_pos_1, 1);
308
309 EXPECT_EQ(static_cast<int>(parcelable.const_exprs_1), 1);
310 EXPECT_EQ(static_cast<int>(parcelable.const_exprs_2), 1);
311 EXPECT_EQ(static_cast<int>(parcelable.const_exprs_3), 1);
312 EXPECT_EQ(static_cast<int>(parcelable.const_exprs_4), 1);
313 EXPECT_EQ(static_cast<int>(parcelable.const_exprs_5), 1);
314 EXPECT_EQ(static_cast<int>(parcelable.const_exprs_6), 1);
315 EXPECT_EQ(static_cast<int>(parcelable.const_exprs_7), 1);
316 EXPECT_EQ(static_cast<int>(parcelable.const_exprs_8), 1);
317 EXPECT_EQ(static_cast<int>(parcelable.const_exprs_9), 1);
318 EXPECT_EQ(static_cast<int>(parcelable.const_exprs_10), 1);
319
320 EXPECT_EQ(parcelable.addString1, "hello world!");
321 EXPECT_EQ(parcelable.addString2, "The quick brown fox jumps over the lazy dog.");
322
323 EXPECT_EQ(StructuredParcelable::BIT0 | StructuredParcelable::BIT2,
324 parcelable.shouldSetBit0AndBit2);
325
326 EXPECT_EQ(parcelable.u->get<Union::ns>(), vector<int32_t>({1, 2, 3}));
327 EXPECT_EQ(parcelable.shouldBeConstS1->get<Union::s>(), Union::S1());
328 }
329
TEST_F(AidlTest,EmptyParcelableHolder)330 TEST_F(AidlTest, EmptyParcelableHolder) {
331 using namespace android::aidl::tests::extension;
332 android::Parcel parcel;
333 {
334 ExtendableParcelable ep;
335 ep.writeToParcel(&parcel);
336 std::shared_ptr<MyExt> emptyExt;
337 ep.ext.getParcelable(&emptyExt);
338 EXPECT_FALSE(emptyExt);
339 }
340 {
341 parcel.setDataPosition(0);
342 ExtendableParcelable ep;
343 ep.readFromParcel(&parcel);
344 std::shared_ptr<MyExt> emptyExt;
345 ep.ext.getParcelable(&emptyExt);
346 EXPECT_FALSE(emptyExt);
347 }
348 }
349
TEST_F(AidlTest,ParcelableHolderEqualityOperator)350 TEST_F(AidlTest, ParcelableHolderEqualityOperator) {
351 auto ph1 = android::os::ParcelableHolder(android::Parcelable::Stability::STABILITY_LOCAL);
352 auto ph2 = android::os::ParcelableHolder(android::Parcelable::Stability::STABILITY_LOCAL);
353 auto ph3 = android::os::ParcelableHolder(android::Parcelable::Stability::STABILITY_LOCAL);
354 auto ptr1 = std::make_shared<MyExt>();
355 auto ptr2 = std::make_shared<MyExt>();
356 ptr1->a = 1;
357 ptr1->b = "a";
358 ptr2->a = 1;
359 ptr2->b = "a";
360
361 ph1.setParcelable(ptr1);
362 ph2.setParcelable(ptr1);
363 ph3.setParcelable(ptr2);
364
365 // ParcelableHolder always uses its address as a comparison criterion.
366 EXPECT_TRUE(ph1 != ph2);
367 EXPECT_TRUE(ph2 != ph3);
368 EXPECT_TRUE(ph1 == ph1);
369 EXPECT_TRUE(ph2 == ph2);
370 EXPECT_TRUE(ph3 == ph3);
371
372 android::Parcel parcel;
373 ph1.writeToParcel(&parcel);
374 ph2.writeToParcel(&parcel);
375 ph3.writeToParcel(&parcel);
376 parcel.setDataPosition(0);
377
378 ph1.readFromParcel(&parcel);
379 ph2.readFromParcel(&parcel);
380 ph3.readFromParcel(&parcel);
381
382 // ParcelableHolder always uses its address as a comparison criterion.
383 EXPECT_TRUE(ph1 != ph2);
384 EXPECT_TRUE(ph2 != ph3);
385 EXPECT_TRUE(ph1 == ph1);
386 EXPECT_TRUE(ph2 == ph2);
387 EXPECT_TRUE(ph3 == ph3);
388 }
389
TEST_F(AidlTest,NativeExtednableParcelable)390 TEST_F(AidlTest, NativeExtednableParcelable) {
391 using namespace android::aidl::tests::extension;
392 MyExt ext;
393 ext.a = 42;
394 ext.b = "EXT";
395
396 MyExt2 ext2;
397 ext2.a = 42;
398 ext2.b.a = 24;
399 ext2.b.b = "INEXT";
400 ext2.c = "EXT2";
401 android::Parcel parcel;
402 {
403 ExtendableParcelable ep;
404 ep.a = 1;
405 ep.b = "a";
406 ep.c = 42L;
407
408 EXPECT_TRUE(ep.ext.setParcelable(ext) == android::OK);
409 EXPECT_TRUE(ep.ext2.setParcelable(ext2) == android::OK);
410
411 std::shared_ptr<MyExtLike> extLike;
412 ep.ext.getParcelable(&extLike);
413 EXPECT_FALSE(extLike) << "The extension type must be MyExt, so it has to fail even though "
414 "MyExtLike has the same structure as MyExt.";
415
416 std::shared_ptr<MyExt> actualExt;
417 ep.ext.getParcelable(&actualExt);
418 std::shared_ptr<MyExt2> actualExt2;
419 ep.ext2.getParcelable(&actualExt2);
420
421 EXPECT_TRUE(actualExt);
422 EXPECT_TRUE(actualExt2);
423
424 EXPECT_EQ(ext, *actualExt);
425 EXPECT_EQ(ext2, *actualExt2);
426
427 ep.writeToParcel(&parcel);
428 }
429
430 parcel.setDataPosition(0);
431 {
432 ExtendableParcelable ep;
433 ep.readFromParcel(&parcel);
434
435 std::shared_ptr<MyExtLike> extLike;
436 ep.ext.getParcelable(&extLike);
437 EXPECT_FALSE(extLike) << "The extension type must be MyExt, so it has to fail even though "
438 "MyExtLike has the same structure as MyExt.";
439
440 std::shared_ptr<MyExt> actualExt;
441 ep.ext.getParcelable(&actualExt);
442 std::shared_ptr<MyExt2> actualExt2;
443 ep.ext2.getParcelable(&actualExt2);
444
445 std::shared_ptr<MyExt> emptyExt;
446 ep.ext2.getParcelable(&emptyExt);
447 EXPECT_FALSE(emptyExt);
448
449 EXPECT_TRUE(actualExt);
450 EXPECT_TRUE(actualExt2);
451
452 EXPECT_EQ(ext, *actualExt);
453 EXPECT_EQ(ext2, *actualExt2);
454 }
455 }
456
TEST_F(AidlTest,ParcelableToString)457 TEST_F(AidlTest, ParcelableToString) {
458 ParcelableForToString p;
459 p.intValue = 10;
460 p.intArray = {20, 30};
461 p.longValue = 100L;
462 p.longArray = {200L, 300L};
463 p.doubleValue = 3.14;
464 p.doubleArray = {1.1, 1.2};
465 p.floatValue = 3.14f;
466 p.floatArray = {1.1f, 1.2f};
467 p.byteValue = 3;
468 p.byteArray = {5, 6};
469 p.booleanValue = true;
470 p.booleanArray = {true, false};
471 p.stringValue = String16("this is a string");
472 p.stringArray = {String16("hello"), String16("world")};
473 p.stringList = {String16("alice"), String16("bob")};
474 OtherParcelableForToString op;
475 op.field = String16("other");
476 p.parcelableValue = op;
477 p.parcelableArray = {op, op};
478 p.enumValue = IntEnum::FOO;
479 p.enumArray = {IntEnum::FOO, IntEnum::BAR};
480 // p.nullArray = null;
481 // p.nullList = null;
482 GenericStructuredParcelable<int32_t, StructuredParcelable, IntEnum> gen;
483 gen.a = 1;
484 gen.b = 2;
485 p.parcelableGeneric = gen;
486 p.unionValue = Union(std::vector<std::string>{"union", "value"});
487
488 const string expected =
489 "ParcelableForToString{"
490 "intValue: 10, "
491 "intArray: [20, 30], "
492 "longValue: 100, "
493 "longArray: [200, 300], "
494 "doubleValue: 3.140000, "
495 "doubleArray: [1.100000, 1.200000], "
496 "floatValue: 3.140000, "
497 "floatArray: [1.100000, 1.200000], "
498 "byteValue: 3, "
499 "byteArray: [5, 6], "
500 "booleanValue: true, "
501 "booleanArray: [true, false], "
502 "stringValue: this is a string, "
503 "stringArray: [hello, world], "
504 "stringList: [alice, bob], "
505 "parcelableValue: OtherParcelableForToString{field: other}, "
506 "parcelableArray: ["
507 "OtherParcelableForToString{field: other}, "
508 "OtherParcelableForToString{field: other}], "
509 "enumValue: FOO, "
510 "enumArray: [FOO, BAR], "
511 "nullArray: [], "
512 "nullList: [], "
513 "parcelableGeneric: GenericStructuredParcelable{a: 1, b: 2}, "
514 "unionValue: Union{ss: [union, value]}"
515 "}";
516
517 EXPECT_EQ(expected, p.toString());
518 }
519