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