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