1 /*
2 * Copyright (C) 2021 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 <aidl/android/aidl/loggable/ILoggableInterface.h>
18
19 #include <functional>
20
21 #include <android/binder_auto_utils.h>
22 #include <android/binder_manager.h>
23 #include <binder/ProcessState.h>
24 #include <gtest/gtest.h>
25
26 #include <aidl/android/aidl/fixedsizearray/FixedSizeArrayExample.h>
27 #include <aidl/android/aidl/tests/ITestService.h>
28 #include <aidl/android/aidl/tests/RecursiveList.h>
29 #include <aidl/android/aidl/tests/Union.h>
30
31 using aidl::android::aidl::fixedsizearray::FixedSizeArrayExample;
32 using BnRepeatFixedSizeArray =
33 aidl::android::aidl::fixedsizearray::FixedSizeArrayExample::BnRepeatFixedSizeArray;
34 using BpRepeatFixedSizeArray =
35 aidl::android::aidl::fixedsizearray::FixedSizeArrayExample::BpRepeatFixedSizeArray;
36 using IntParcelable = aidl::android::aidl::fixedsizearray::FixedSizeArrayExample::IntParcelable;
37 using IRepeatFixedSizeArray =
38 aidl::android::aidl::fixedsizearray::FixedSizeArrayExample::IRepeatFixedSizeArray;
39 using BnEmptyInterface =
40 aidl::android::aidl::fixedsizearray::FixedSizeArrayExample::BnEmptyInterface;
41 using aidl::android::aidl::tests::BackendType;
42 using aidl::android::aidl::tests::ITestService;
43 using aidl::android::aidl::tests::RecursiveList;
44 using aidl::android::aidl::tests::SimpleParcelable;
45 using aidl::android::aidl::tests::Union;
46 using android::OK;
47 using ndk::AParcel_readData;
48 using ndk::AParcel_writeData;
49 using ndk::ScopedAStatus;
50 using ndk::SharedRefBase;
51 using ndk::SpAIBinder;
52
53 struct AidlTest : testing::Test {
54 template <typename T>
getServiceAidlTest55 std::shared_ptr<T> getService() {
56 android::ProcessState::self()->setThreadPoolMaxThreadCount(1);
57 android::ProcessState::self()->startThreadPool();
58 ndk::SpAIBinder binder = ndk::SpAIBinder(AServiceManager_waitForService(T::descriptor));
59 return T::fromBinder(binder);
60 }
61 };
62
63 // TODO(b/196454897): copy more tests from aidl_test_client
64
TEST_F(AidlTest,RepeatSimpleParcelable)65 TEST_F(AidlTest, RepeatSimpleParcelable) {
66 SimpleParcelable input("foo", 42);
67 SimpleParcelable out_param, returned;
68 auto status = getService<ITestService>()->RepeatSimpleParcelable(input, &out_param, &returned);
69 ASSERT_TRUE(status.isOk());
70 EXPECT_EQ(input, out_param) << input.toString() << " " << out_param.toString();
71 EXPECT_EQ(input, returned) << input.toString() << " " << returned.toString();
72 }
73
TEST_F(AidlTest,ReverseSimpleParcelable)74 TEST_F(AidlTest, ReverseSimpleParcelable) {
75 BackendType backend;
76 auto status = getService<ITestService>()->getBackendType(&backend);
77 ASSERT_TRUE(status.isOk());
78
79 const std::vector<SimpleParcelable> original{SimpleParcelable("a", 1), SimpleParcelable("b", 2),
80 SimpleParcelable("c", 3)};
81 std::vector<SimpleParcelable> repeated;
82 if (backend == BackendType::JAVA) {
83 repeated = std::vector<SimpleParcelable>(original.size());
84 }
85 std::vector<SimpleParcelable> reversed;
86 status = getService<ITestService>()->ReverseSimpleParcelables(original, &repeated, &reversed);
87 ASSERT_TRUE(status.isOk());
88
89 EXPECT_EQ(repeated, original);
90
91 std::reverse(reversed.begin(), reversed.end());
92 EXPECT_EQ(reversed, original);
93 }
94
TEST_F(AidlTest,ReverseRecursiveList)95 TEST_F(AidlTest, ReverseRecursiveList) {
96 std::unique_ptr<RecursiveList> head;
97 for (int i = 0; i < 10; i++) {
98 auto node = std::make_unique<RecursiveList>();
99 node->value = i;
100 node->next = std::move(head);
101 head = std::move(node);
102 }
103 // head: [9, 8, ... 0]
104
105 RecursiveList reversed;
106 auto status = getService<ITestService>()->ReverseList(*head, &reversed);
107 ASSERT_TRUE(status.isOk());
108
109 // reversed should be [0, 1, .. 9]
110 RecursiveList* cur = &reversed;
111 for (int i = 0; i < 10; i++) {
112 EXPECT_EQ(i, cur->value);
113 cur = cur->next.get();
114 }
115 EXPECT_EQ(nullptr, cur);
116 }
117
TEST_F(AidlTest,GetUnionTags)118 TEST_F(AidlTest, GetUnionTags) {
119 std::vector<Union> unions;
120 std::vector<Union::Tag> tags;
121 // test empty
122 auto status = getService<ITestService>()->GetUnionTags(unions, &tags);
123 ASSERT_TRUE(status.isOk());
124 EXPECT_EQ(tags, (std::vector<Union::Tag>{}));
125 // test non-empty
126 unions.push_back(Union::make<Union::n>());
127 unions.push_back(Union::make<Union::ns>());
128 status = getService<ITestService>()->GetUnionTags(unions, &tags);
129 ASSERT_TRUE(status.isOk());
130 EXPECT_EQ(tags, (std::vector<Union::Tag>{Union::n, Union::ns}));
131 }
132
TEST_F(AidlTest,FixedSizeArray)133 TEST_F(AidlTest, FixedSizeArray) {
134 auto parcel = AParcel_create();
135
136 FixedSizeArrayExample p;
137 p.byteMatrix[0][0] = 0;
138 p.byteMatrix[0][1] = 1;
139 p.byteMatrix[1][0] = 2;
140 p.byteMatrix[1][1] = 3;
141 p.floatMatrix[0][0] = 0.f;
142 p.floatMatrix[0][1] = 1.f;
143 p.floatMatrix[1][0] = 2.f;
144 p.floatMatrix[1][1] = 3.f;
145 EXPECT_EQ(OK, p.writeToParcel(parcel));
146
147 AParcel_setDataPosition(parcel, 0);
148
149 FixedSizeArrayExample q;
150 EXPECT_EQ(OK, q.readFromParcel(parcel));
151 EXPECT_EQ(p, q);
152
153 AParcel_delete(parcel);
154 }
155
TEST_F(AidlTest,FixedSizeArrayWithValuesAtNullableFields)156 TEST_F(AidlTest, FixedSizeArrayWithValuesAtNullableFields) {
157 auto parcel = AParcel_create();
158
159 FixedSizeArrayExample p;
160 p.boolNullableArray = std::array<bool, 2>{true, false};
161 p.byteNullableArray = std::array<uint8_t, 2>{42, 0};
162 p.stringNullableArray = std::array<std::optional<std::string>, 2>{"hello", "world"};
163
164 p.boolNullableMatrix.emplace();
165 p.boolNullableMatrix->at(0) = std::array<bool, 2>{true, false};
166 p.byteNullableMatrix.emplace();
167 p.byteNullableMatrix->at(0) = std::array<uint8_t, 2>{42, 0};
168 p.stringNullableMatrix.emplace();
169 p.stringNullableMatrix->at(0) = std::array<std::optional<std::string>, 2>{"hello", "world"};
170
171 EXPECT_EQ(OK, p.writeToParcel(parcel));
172
173 AParcel_setDataPosition(parcel, 0);
174
175 FixedSizeArrayExample q;
176 EXPECT_EQ(OK, q.readFromParcel(parcel));
177 EXPECT_EQ(p, q);
178
179 AParcel_delete(parcel);
180 }
181
TEST_F(AidlTest,FixedSizeArrayOfBytesShouldBePacked)182 TEST_F(AidlTest, FixedSizeArrayOfBytesShouldBePacked) {
183 auto parcel = AParcel_create();
184
185 std::array<std::array<uint8_t, 3>, 2> byte_array;
186 byte_array[0] = {1, 2, 3};
187 byte_array[1] = {4, 5, 6};
188 EXPECT_EQ(OK, AParcel_writeData(parcel, byte_array));
189
190 AParcel_setDataPosition(parcel, 0);
191
192 int32_t len;
193 EXPECT_EQ(OK, AParcel_readData(parcel, &len));
194 EXPECT_EQ(2, len);
195 std::vector<uint8_t> byte_vector;
196 EXPECT_EQ(OK, AParcel_readData(parcel, &byte_vector));
197 EXPECT_EQ(byte_vector, (std::vector<uint8_t>{1, 2, 3}));
198 EXPECT_EQ(OK, AParcel_readData(parcel, &byte_vector));
199 EXPECT_EQ(byte_vector, (std::vector<uint8_t>{4, 5, 6}));
200
201 AParcel_delete(parcel);
202 }
203
204 template <typename Service, typename MemFn, typename Input>
CheckRepeat(Service service,MemFn fn,Input input)205 void CheckRepeat(Service service, MemFn fn, Input input) {
206 Input out1, out2;
207 EXPECT_TRUE(std::invoke(fn, service, input, &out1, &out2).isOk());
208 EXPECT_EQ(input, out1);
209 EXPECT_EQ(input, out2);
210 }
211
212 template <typename T>
Make2dArray(std::initializer_list<T> values)213 std::array<std::array<T, 3>, 2> Make2dArray(std::initializer_list<T> values) {
214 std::array<std::array<T, 3>, 2> arr = {};
215 auto it = std::begin(values);
216 for (auto& row : arr) {
217 for (auto& el : row) {
218 if (it == std::end(values)) break;
219 el = *it++;
220 }
221 }
222 return arr;
223 }
224
TEST_F(AidlTest,FixedSizeArrayOverBinder)225 TEST_F(AidlTest, FixedSizeArrayOverBinder) {
226 auto service = getService<IRepeatFixedSizeArray>();
227
228 CheckRepeat(service, &IRepeatFixedSizeArray::RepeatBytes, (std::array<uint8_t, 3>{1, 2, 3}));
229
230 CheckRepeat(service, &IRepeatFixedSizeArray::RepeatInts, (std::array<int32_t, 3>{1, 2, 3}));
231
232 auto binder1 = SharedRefBase::make<BnEmptyInterface>()->asBinder();
233 auto binder2 = SharedRefBase::make<BnEmptyInterface>()->asBinder();
234 auto binder3 = SharedRefBase::make<BnEmptyInterface>()->asBinder();
235 CheckRepeat(service, &IRepeatFixedSizeArray::RepeatBinders,
236 (std::array<SpAIBinder, 3>{binder1, binder2, binder3}));
237
238 IntParcelable p1, p2, p3;
239 p1.value = 1;
240 p2.value = 2;
241 p3.value = 3;
242 CheckRepeat(service, &IRepeatFixedSizeArray::RepeatParcelables,
243 (std::array<IntParcelable, 3>{p1, p2, p3}));
244
245 CheckRepeat(service, &IRepeatFixedSizeArray::Repeat2dBytes, Make2dArray<uint8_t>({1, 2, 3}));
246
247 CheckRepeat(service, &IRepeatFixedSizeArray::Repeat2dInts, Make2dArray<int32_t>({1, 2, 3}));
248
249 // Not-nullable
250 CheckRepeat(service, &IRepeatFixedSizeArray::Repeat2dBinders,
251 Make2dArray<SpAIBinder>({binder1, binder2, binder3, binder1, binder2, binder3}));
252
253 CheckRepeat(service, &IRepeatFixedSizeArray::Repeat2dParcelables,
254 Make2dArray<IntParcelable>({p1, p2, p3}));
255 }
256