blob: 976dc3795b9e9e6587d15a35da97af6c4097a42c [file] [log] [blame]
Christopher Wileyb5e698c2015-10-17 09:32:22 -07001/*
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 <iostream>
Christopher Wileyd6130f22015-10-26 10:24:35 -070018#include <vector>
Christopher Wileyb5e698c2015-10-17 09:32:22 -070019
Casey Dahlina4ba4b62015-11-02 15:43:30 -080020#include <errno.h>
21#include <string.h>
22#include <unistd.h>
23
24#include <nativehelper/ScopedFd.h>
Christopher Wileyb5e698c2015-10-17 09:32:22 -070025#include <binder/IServiceManager.h>
Christopher Wileyd6130f22015-10-26 10:24:35 -070026#include <utils/String8.h>
Christopher Wileyb5e698c2015-10-17 09:32:22 -070027#include <utils/String16.h>
28#include <utils/StrongPointer.h>
29
Christopher Wiley521bb612015-10-22 11:40:30 -070030#include "android/aidl/tests/ITestService.h"
Casey Dahlin7ecd69f2015-11-03 13:52:38 -080031#include "android/aidl/tests/INamedCallback.h"
Christopher Wileyb5e698c2015-10-17 09:32:22 -070032
33// libutils:
34using android::OK;
35using android::sp;
36using android::status_t;
37using android::String16;
Christopher Wileyd6130f22015-10-26 10:24:35 -070038using android::String8;
Christopher Wileyb5e698c2015-10-17 09:32:22 -070039
40// libbinder:
41using android::getService;
Casey Dahlin7ecd69f2015-11-03 13:52:38 -080042using android::IBinder;
Christopher Wiley433c8bb2015-11-12 14:20:46 -080043using android::binder::Status;
Christopher Wileyb5e698c2015-10-17 09:32:22 -070044
45// generated
Christopher Wiley521bb612015-10-22 11:40:30 -070046using android::aidl::tests::ITestService;
Casey Dahlin7ecd69f2015-11-03 13:52:38 -080047using android::aidl::tests::INamedCallback;
Christopher Wiley95d44b02015-11-19 07:11:30 -080048using android::aidl::tests::SimpleParcelable;
Christopher Wileyb5e698c2015-10-17 09:32:22 -070049
50using std::cerr;
51using std::cout;
52using std::endl;
Casey Dahlina4ba4b62015-11-02 15:43:30 -080053using std::string;
Christopher Wileyd6130f22015-10-26 10:24:35 -070054using std::vector;
Christopher Wileyb5e698c2015-10-17 09:32:22 -070055
56namespace {
57
Christopher Wiley521bb612015-10-22 11:40:30 -070058const char kServiceName[] = "android.aidl.tests.ITestService";
Christopher Wileyb5e698c2015-10-17 09:32:22 -070059
Christopher Wiley521bb612015-10-22 11:40:30 -070060bool GetService(sp<ITestService>* service) {
61 cout << "Retrieving test service binder" << endl;
Christopher Wiley33ad81e2015-10-21 14:41:11 -070062 status_t status = getService(String16(kServiceName), service);
63 if (status != OK) {
64 cerr << "Failed to get service binder: '" << kServiceName
65 << "' status=" << status << endl;
66 return false;
67 }
68 return true;
69}
70
Christopher Wileyd6130f22015-10-26 10:24:35 -070071template <typename T>
72bool RepeatPrimitive(const sp<ITestService>& service,
Christopher Wiley433c8bb2015-11-12 14:20:46 -080073 Status(ITestService::*func)(T, T*),
Christopher Wileyd6130f22015-10-26 10:24:35 -070074 const T input) {
75 T reply;
Christopher Wiley433c8bb2015-11-12 14:20:46 -080076 Status status = (*service.*func)(input, &reply);
77 if (!status.isOk() || input != reply) {
78 cerr << "Failed to repeat primitive. status=" << status.toString8()
79 << "." << endl;
Christopher Wileyd6130f22015-10-26 10:24:35 -070080 return false;
81 }
82 return true;
83}
84
85bool ConfirmPrimitiveRepeat(const sp<ITestService>& s) {
Christopher Wiley8949f832015-10-27 15:32:03 -070086 cout << "Confirming passing and returning primitives works." << endl;
Christopher Wileyd6130f22015-10-26 10:24:35 -070087
88 if (!RepeatPrimitive(s, &ITestService::RepeatBoolean, true) ||
89 !RepeatPrimitive(s, &ITestService::RepeatByte, int8_t{-128}) ||
90 !RepeatPrimitive(s, &ITestService::RepeatChar, char16_t{'A'}) ||
91 !RepeatPrimitive(s, &ITestService::RepeatInt, int32_t{1 << 30}) ||
92 !RepeatPrimitive(s, &ITestService::RepeatLong, int64_t{1ll << 60}) ||
93 !RepeatPrimitive(s, &ITestService::RepeatFloat, float{1.0f/3.0f}) ||
94 !RepeatPrimitive(s, &ITestService::RepeatDouble, double{1.0/3.0})) {
95 return false;
96 }
97
98 vector<String16> inputs = {
99 String16("Deliver us from evil."),
100 String16(),
101 String16("\0\0", 2),
102 };
103 for (const auto& input : inputs) {
104 String16 reply;
Christopher Wiley433c8bb2015-11-12 14:20:46 -0800105 Status status = s->RepeatString(input, &reply);
106 if (!status.isOk() || input != reply) {
Christopher Wileyd6130f22015-10-26 10:24:35 -0700107 cerr << "Failed while requesting service to repeat String16=\""
108 << String8(input).string()
Christopher Wiley433c8bb2015-11-12 14:20:46 -0800109 << "\". Got status=" << status.toString8() << endl;
Christopher Wileyd6130f22015-10-26 10:24:35 -0700110 return false;
111 }
112 }
113 return true;
114}
115
Christopher Wiley8949f832015-10-27 15:32:03 -0700116template <typename T>
117bool ReverseArray(const sp<ITestService>& service,
Christopher Wiley433c8bb2015-11-12 14:20:46 -0800118 Status(ITestService::*func)(const vector<T>&,
119 vector<T>*,
120 vector<T>*),
Christopher Wiley8949f832015-10-27 15:32:03 -0700121 vector<T> input) {
122 vector<T> actual_reversed;
123 vector<T> actual_repeated;
Christopher Wiley433c8bb2015-11-12 14:20:46 -0800124 Status status = (*service.*func)(input, &actual_repeated, &actual_reversed);
125 if (!status.isOk()) {
126 cerr << "Failed to repeat array. status=" << status.toString8() << "."
127 << endl;
Christopher Wiley8949f832015-10-27 15:32:03 -0700128 return false;
129 }
130 if (input != actual_repeated) {
131 cerr << "Repeated version of array did not match" << endl;
132 cerr << "input.size()=" << input.size()
133 << " repeated.size()=" << actual_repeated.size() << endl;
134 return false;
135 }
136 std::reverse(input.begin(), input.end());
137 if (input != actual_reversed) {
138 cerr << "Reversed version of array did not match" << endl;
139 return false;
140 }
141 return true;
142}
143
144bool ConfirmReverseArrays(const sp<ITestService>& s) {
145 cout << "Confirming passing and returning arrays works." << endl;
146
147 if (!ReverseArray(s, &ITestService::ReverseBoolean,
148 {true, false, false}) ||
149 !ReverseArray(s, &ITestService::ReverseByte,
150 {int8_t{-128}, int8_t{0}, int8_t{127}}) ||
151 !ReverseArray(s, &ITestService::ReverseChar,
152 {char16_t{'A'}, char16_t{'B'}, char16_t{'C'}}) ||
153 !ReverseArray(s, &ITestService::ReverseInt,
154 {1, 2, 3}) ||
155 !ReverseArray(s, &ITestService::ReverseLong,
156 {-1ll, 0ll, int64_t{1ll << 60}}) ||
157 !ReverseArray(s, &ITestService::ReverseFloat,
158 {-0.3f, -0.7f, 8.0f}) ||
159 !ReverseArray(s, &ITestService::ReverseDouble,
160 {1.0/3.0, 1.0/7.0, 42.0}) ||
161 !ReverseArray(s, &ITestService::ReverseString,
162 {String16{"f"}, String16{"a"}, String16{"b"}})) {
163 return false;
164 }
165
166 return true;
167}
168
Christopher Wiley56c9bf32015-10-30 10:41:12 -0700169bool ConfirmReverseLists(const sp<ITestService>& s) {
170 cout << "Confirming passing and returning List<T> works." << endl;
171
172 if (!ReverseArray(s, &ITestService::ReverseStringList,
173 {String16{"f"}, String16{"a"}, String16{"b"}})) {
174 return false;
175 }
176
177 return true;
178}
Casey Dahlin7ecd69f2015-11-03 13:52:38 -0800179
Christopher Wiley95d44b02015-11-19 07:11:30 -0800180bool ConfirmParcelables(const sp<ITestService>& s) {
181 cout << "Confirming passing and returning Parcelables works." << endl;
182
183 SimpleParcelable input("Booya", 42);
184 SimpleParcelable out_param, returned;
185 Status status = s->RepeatParcelable(input, &out_param, &returned);
186 if (!status.isOk()) {
187 cout << "Binder call failed." << endl;
188 return false;
189 }
190 if (input != out_param || input != returned) {
191 cout << "Failed to repeat parcelables." << endl;
192 return false;
193 }
194
195 cout << "Attempting to reverse an array of parcelables." << endl;
196 const vector<SimpleParcelable> original{SimpleParcelable("first", 0),
197 SimpleParcelable("second", 1),
198 SimpleParcelable("third", 2)};
199 vector<SimpleParcelable> repeated;
200 vector<SimpleParcelable> reversed;
201 status = s->ReverseParcelables(original, &repeated, &reversed);
202 if (!status.isOk()) {
203 cout << "Binder call failed." << endl;
204 return false;
205 }
206 std::reverse(reversed.begin(), reversed.end());
207 if (repeated != original || reversed != original) {
208 cout << "Failed to reverse an array of parcelables." << endl;
209 return false;
210 }
211
212 return true;
213}
214
Casey Dahlin7ecd69f2015-11-03 13:52:38 -0800215bool ConfirmReverseBinderLists(const sp<ITestService>& s) {
Christopher Wiley433c8bb2015-11-12 14:20:46 -0800216 Status status;
Casey Dahlin7ecd69f2015-11-03 13:52:38 -0800217 cout << "Confirming passing and returning List<T> works with binders." << endl;
218
219 vector<String16> names = {
220 String16{"Larry"},
221 String16{"Curly"},
222 String16{"Moe"}
223 };
224
225 vector<sp<IBinder>> input;
226
227 for (int i = 0; i < 3; i++) {
228 sp<INamedCallback> got;
229
230 status = s->GetOtherTestService(names[i], &got);
Christopher Wiley433c8bb2015-11-12 14:20:46 -0800231 if (!status.isOk()) {
Casey Dahlin7ecd69f2015-11-03 13:52:38 -0800232 cerr << "Could not retrieve service for test." << endl;
233 return false;
234 }
235
236 input.push_back(INamedCallback::asBinder(got));
237 }
238
239 vector<sp<IBinder>> output;
240 vector<sp<IBinder>> reversed;
241
242 status = s->ReverseNamedCallbackList(input, &output, &reversed);
Christopher Wiley433c8bb2015-11-12 14:20:46 -0800243 if (!status.isOk()) {
244 cerr << "Failed to reverse named callback list." << endl;
245 }
Casey Dahlin7ecd69f2015-11-03 13:52:38 -0800246
247 if (output.size() != 3) {
248 cerr << "ReverseNamedCallbackList gave repetition with wrong length." << endl;
249 return false;
250 }
251
252 if (reversed.size() != 3) {
253 cerr << "ReverseNamedCallbackList gave reversal with wrong length." << endl;
254 return false;
255 }
256
257 for (int i = 0; i < 3; i++) {
258 String16 ret;
259 sp<INamedCallback> named_callback =
260 android::interface_cast<INamedCallback>(output[i]);
261 status = named_callback->GetName(&ret);
262
Christopher Wiley433c8bb2015-11-12 14:20:46 -0800263 if (!status.isOk()) {
Casey Dahlin7ecd69f2015-11-03 13:52:38 -0800264 cerr << "Could not query INamedCallback from output" << endl;
265 return false;
266 }
267
268 if (ret != names[i]) {
269 cerr << "Output had wrong INamedCallback" << endl;
270 return false;
271 }
272 }
273
274 for (int i = 0; i < 3; i++) {
275 String16 ret;
276 sp<INamedCallback> named_callback =
277 android::interface_cast<INamedCallback>(reversed[i]);
278 status = named_callback->GetName(&ret);
279
Christopher Wiley433c8bb2015-11-12 14:20:46 -0800280 if (!status.isOk()) {
Casey Dahlin7ecd69f2015-11-03 13:52:38 -0800281 cerr << "Could not query INamedCallback from reversed output" << endl;
282 return false;
283 }
284
285 if (ret != names[2 - i]) {
286 cerr << "Reversed output had wrong INamedCallback" << endl;
287 return false;
288 }
289 }
290
291 return true;
292}
Casey Dahlina4ba4b62015-11-02 15:43:30 -0800293
294#define FdByName(_fd) #_fd, _fd
295
296bool DoWrite(string name, const ScopedFd& fd, const string& buf) {
297 int wrote;
298
299 while ((wrote = write(fd.get(), buf.data(), buf.size())) < 0 && errno == EINTR);
300
301 if (wrote == (signed)buf.size()) {
302 return true;
303 }
304
305 if (wrote < 0) {
306 cerr << "Error writing to file descriptor '" << name << "': "
307 << strerror(errno) << endl;
308 } else {
309 cerr << "File descriptor '" << name << "'accepted short data." << endl;
310 }
311
312 return false;
313}
314
315bool DoRead(string name, const ScopedFd& fd, const string& expected) {
316 size_t length = expected.size();
317 int got;
318 string buf;
319 buf.resize(length);
320
321 while ((got = read(fd.get(), &buf[0], length)) < 0 && errno == EINTR);
322
323 if (got < 0) {
324 cerr << "Error reading from '" << name << "': " << strerror(errno) << endl;
325 return false;
326 }
327
328 if (buf != expected) {
329 cerr << "Expected '" << expected << "' got '" << buf << "'" << endl;
330 return false;
331 }
332
333 return true;
334}
335
336bool DoPipe(ScopedFd* read_side, ScopedFd* write_side) {
337 int fds[2];
338 ScopedFd return_fd;
339
340 if (pipe(fds)) {
341 cout << "Error creating pipes: " << strerror(errno) << endl;
342 return false;
343 }
344
345 read_side->reset(fds[0]);
346 write_side->reset(fds[1]);
347 return true;
348}
349
350bool ConfirmFileDescriptors(const sp<ITestService>& s) {
351 Status status;
352 cout << "Confirming passing and returning file descriptors works." << endl;
353
354 ScopedFd return_fd;
355 ScopedFd read_fd;
356 ScopedFd write_fd;
357
358 if (!DoPipe(&read_fd, &write_fd)) {
359 return false;
360 }
361
362 status = s->RepeatFileDescriptor(write_fd, &return_fd);
363
364 if (!status.isOk()) {
365 cerr << "Could not repeat file descriptors." << endl;
366 return false;
367 }
368
369 /* A note on some of the spookier stuff going on here: IIUC writes to pipes
370 * should be atomic and non-blocking so long as the total size doesn't exceed
371 * PIPE_BUF. We thus play a bit fast and loose with failure modes here.
372 */
373
374 bool ret =
375 DoWrite(FdByName(return_fd), "ReturnString") &&
376 DoRead(FdByName(read_fd), "ReturnString");
377
378 return ret;
379}
380
381bool ConfirmFileDescriptorArrays(const sp<ITestService>& s) {
382 Status status;
383 cout << "Confirming passing and returning file descriptor arrays works." << endl;
384
385 vector<ScopedFd> array;
386 array.resize(2);
387
388 if (!DoPipe(&array[0], &array[1])) {
389 return false;
390 }
391
392 vector<ScopedFd> repeated;
393 vector<ScopedFd> reversed;
394
395 status = s->ReverseFileDescriptorArray(array, &repeated, &reversed);
396
397 if (!status.isOk()) {
398 cerr << "Could not reverse file descriptor array." << endl;
399 return false;
400 }
401
402 bool ret =
403 DoWrite(FdByName(array[1]), "First") &&
404 DoWrite(FdByName(repeated[1]), "Second") &&
405 DoWrite(FdByName(reversed[0]), "Third") &&
406 DoRead(FdByName(reversed[1]), "FirstSecondThird");
407
408 return ret;
409}
Christopher Wileyb5e698c2015-10-17 09:32:22 -0700410} // namespace
411
Brian Carlstromad3b8062015-10-21 08:54:48 -0700412int main(int /* argc */, char * /* argv */ []) {
Christopher Wiley521bb612015-10-22 11:40:30 -0700413 sp<ITestService> service;
Christopher Wileyb5e698c2015-10-17 09:32:22 -0700414
Christopher Wiley33ad81e2015-10-21 14:41:11 -0700415 if (!GetService(&service)) return 1;
416
Christopher Wileyd6130f22015-10-26 10:24:35 -0700417 if (!ConfirmPrimitiveRepeat(service)) return 1;
Christopher Wileyb5e698c2015-10-17 09:32:22 -0700418
Christopher Wiley8949f832015-10-27 15:32:03 -0700419 if (!ConfirmReverseArrays(service)) return 1;
420
Christopher Wiley56c9bf32015-10-30 10:41:12 -0700421 if (!ConfirmReverseLists(service)) return 1;
422
Christopher Wiley95d44b02015-11-19 07:11:30 -0800423 if (!ConfirmParcelables(service)) return 1;
424
Casey Dahlin7ecd69f2015-11-03 13:52:38 -0800425 if (!ConfirmReverseBinderLists(service)) return 1;
426
Casey Dahlina4ba4b62015-11-02 15:43:30 -0800427 if (!ConfirmFileDescriptors(service)) return 1;
428
429 if (!ConfirmFileDescriptorArrays(service)) return 1;
430
Christopher Wileyb5e698c2015-10-17 09:32:22 -0700431 return 0;
432}