blob: 5ef3437bd241ddaac8b3b3756b488092ba57de60 [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}) ||
Casey Dahlind40e2fe2015-11-24 14:06:52 -080094 !RepeatPrimitive(s, &ITestService::RepeatDouble, double{1.0/3.0}) ||
95 !RepeatPrimitive(s, &ITestService::RepeatInt, ITestService::TEST_CONSTANT)) {
Christopher Wileyd6130f22015-10-26 10:24:35 -070096 return false;
97 }
98
99 vector<String16> inputs = {
100 String16("Deliver us from evil."),
101 String16(),
102 String16("\0\0", 2),
103 };
104 for (const auto& input : inputs) {
105 String16 reply;
Christopher Wiley433c8bb2015-11-12 14:20:46 -0800106 Status status = s->RepeatString(input, &reply);
107 if (!status.isOk() || input != reply) {
Christopher Wileyd6130f22015-10-26 10:24:35 -0700108 cerr << "Failed while requesting service to repeat String16=\""
109 << String8(input).string()
Christopher Wiley433c8bb2015-11-12 14:20:46 -0800110 << "\". Got status=" << status.toString8() << endl;
Christopher Wileyd6130f22015-10-26 10:24:35 -0700111 return false;
112 }
113 }
114 return true;
115}
116
Christopher Wiley8949f832015-10-27 15:32:03 -0700117template <typename T>
118bool ReverseArray(const sp<ITestService>& service,
Christopher Wiley433c8bb2015-11-12 14:20:46 -0800119 Status(ITestService::*func)(const vector<T>&,
120 vector<T>*,
121 vector<T>*),
Christopher Wiley8949f832015-10-27 15:32:03 -0700122 vector<T> input) {
123 vector<T> actual_reversed;
124 vector<T> actual_repeated;
Christopher Wiley433c8bb2015-11-12 14:20:46 -0800125 Status status = (*service.*func)(input, &actual_repeated, &actual_reversed);
126 if (!status.isOk()) {
127 cerr << "Failed to repeat array. status=" << status.toString8() << "."
128 << endl;
Christopher Wiley8949f832015-10-27 15:32:03 -0700129 return false;
130 }
131 if (input != actual_repeated) {
132 cerr << "Repeated version of array did not match" << endl;
133 cerr << "input.size()=" << input.size()
134 << " repeated.size()=" << actual_repeated.size() << endl;
135 return false;
136 }
137 std::reverse(input.begin(), input.end());
138 if (input != actual_reversed) {
139 cerr << "Reversed version of array did not match" << endl;
140 return false;
141 }
142 return true;
143}
144
145bool ConfirmReverseArrays(const sp<ITestService>& s) {
146 cout << "Confirming passing and returning arrays works." << endl;
147
148 if (!ReverseArray(s, &ITestService::ReverseBoolean,
149 {true, false, false}) ||
150 !ReverseArray(s, &ITestService::ReverseByte,
151 {int8_t{-128}, int8_t{0}, int8_t{127}}) ||
152 !ReverseArray(s, &ITestService::ReverseChar,
153 {char16_t{'A'}, char16_t{'B'}, char16_t{'C'}}) ||
154 !ReverseArray(s, &ITestService::ReverseInt,
155 {1, 2, 3}) ||
156 !ReverseArray(s, &ITestService::ReverseLong,
157 {-1ll, 0ll, int64_t{1ll << 60}}) ||
158 !ReverseArray(s, &ITestService::ReverseFloat,
159 {-0.3f, -0.7f, 8.0f}) ||
160 !ReverseArray(s, &ITestService::ReverseDouble,
161 {1.0/3.0, 1.0/7.0, 42.0}) ||
162 !ReverseArray(s, &ITestService::ReverseString,
163 {String16{"f"}, String16{"a"}, String16{"b"}})) {
164 return false;
165 }
166
167 return true;
168}
169
Christopher Wiley56c9bf32015-10-30 10:41:12 -0700170bool ConfirmReverseLists(const sp<ITestService>& s) {
171 cout << "Confirming passing and returning List<T> works." << endl;
172
173 if (!ReverseArray(s, &ITestService::ReverseStringList,
174 {String16{"f"}, String16{"a"}, String16{"b"}})) {
175 return false;
176 }
177
178 return true;
179}
Casey Dahlin7ecd69f2015-11-03 13:52:38 -0800180
Christopher Wiley95d44b02015-11-19 07:11:30 -0800181bool ConfirmParcelables(const sp<ITestService>& s) {
182 cout << "Confirming passing and returning Parcelables works." << endl;
183
184 SimpleParcelable input("Booya", 42);
185 SimpleParcelable out_param, returned;
186 Status status = s->RepeatParcelable(input, &out_param, &returned);
187 if (!status.isOk()) {
188 cout << "Binder call failed." << endl;
189 return false;
190 }
191 if (input != out_param || input != returned) {
192 cout << "Failed to repeat parcelables." << endl;
193 return false;
194 }
195
196 cout << "Attempting to reverse an array of parcelables." << endl;
197 const vector<SimpleParcelable> original{SimpleParcelable("first", 0),
198 SimpleParcelable("second", 1),
199 SimpleParcelable("third", 2)};
200 vector<SimpleParcelable> repeated;
201 vector<SimpleParcelable> reversed;
202 status = s->ReverseParcelables(original, &repeated, &reversed);
203 if (!status.isOk()) {
204 cout << "Binder call failed." << endl;
205 return false;
206 }
207 std::reverse(reversed.begin(), reversed.end());
208 if (repeated != original || reversed != original) {
209 cout << "Failed to reverse an array of parcelables." << endl;
210 return false;
211 }
212
213 return true;
214}
215
Casey Dahlin7ecd69f2015-11-03 13:52:38 -0800216bool ConfirmReverseBinderLists(const sp<ITestService>& s) {
Christopher Wiley433c8bb2015-11-12 14:20:46 -0800217 Status status;
Casey Dahlin7ecd69f2015-11-03 13:52:38 -0800218 cout << "Confirming passing and returning List<T> works with binders." << endl;
219
220 vector<String16> names = {
221 String16{"Larry"},
222 String16{"Curly"},
223 String16{"Moe"}
224 };
225
226 vector<sp<IBinder>> input;
227
228 for (int i = 0; i < 3; i++) {
229 sp<INamedCallback> got;
230
231 status = s->GetOtherTestService(names[i], &got);
Christopher Wiley433c8bb2015-11-12 14:20:46 -0800232 if (!status.isOk()) {
Casey Dahlin7ecd69f2015-11-03 13:52:38 -0800233 cerr << "Could not retrieve service for test." << endl;
234 return false;
235 }
236
237 input.push_back(INamedCallback::asBinder(got));
238 }
239
240 vector<sp<IBinder>> output;
241 vector<sp<IBinder>> reversed;
242
243 status = s->ReverseNamedCallbackList(input, &output, &reversed);
Christopher Wiley433c8bb2015-11-12 14:20:46 -0800244 if (!status.isOk()) {
245 cerr << "Failed to reverse named callback list." << endl;
246 }
Casey Dahlin7ecd69f2015-11-03 13:52:38 -0800247
248 if (output.size() != 3) {
249 cerr << "ReverseNamedCallbackList gave repetition with wrong length." << endl;
250 return false;
251 }
252
253 if (reversed.size() != 3) {
254 cerr << "ReverseNamedCallbackList gave reversal with wrong length." << endl;
255 return false;
256 }
257
258 for (int i = 0; i < 3; i++) {
259 String16 ret;
260 sp<INamedCallback> named_callback =
261 android::interface_cast<INamedCallback>(output[i]);
262 status = named_callback->GetName(&ret);
263
Christopher Wiley433c8bb2015-11-12 14:20:46 -0800264 if (!status.isOk()) {
Casey Dahlin7ecd69f2015-11-03 13:52:38 -0800265 cerr << "Could not query INamedCallback from output" << endl;
266 return false;
267 }
268
269 if (ret != names[i]) {
270 cerr << "Output had wrong INamedCallback" << endl;
271 return false;
272 }
273 }
274
275 for (int i = 0; i < 3; i++) {
276 String16 ret;
277 sp<INamedCallback> named_callback =
278 android::interface_cast<INamedCallback>(reversed[i]);
279 status = named_callback->GetName(&ret);
280
Christopher Wiley433c8bb2015-11-12 14:20:46 -0800281 if (!status.isOk()) {
Casey Dahlin7ecd69f2015-11-03 13:52:38 -0800282 cerr << "Could not query INamedCallback from reversed output" << endl;
283 return false;
284 }
285
286 if (ret != names[2 - i]) {
287 cerr << "Reversed output had wrong INamedCallback" << endl;
288 return false;
289 }
290 }
291
292 return true;
293}
Casey Dahlina4ba4b62015-11-02 15:43:30 -0800294
295#define FdByName(_fd) #_fd, _fd
296
297bool DoWrite(string name, const ScopedFd& fd, const string& buf) {
298 int wrote;
299
300 while ((wrote = write(fd.get(), buf.data(), buf.size())) < 0 && errno == EINTR);
301
302 if (wrote == (signed)buf.size()) {
303 return true;
304 }
305
306 if (wrote < 0) {
307 cerr << "Error writing to file descriptor '" << name << "': "
308 << strerror(errno) << endl;
309 } else {
310 cerr << "File descriptor '" << name << "'accepted short data." << endl;
311 }
312
313 return false;
314}
315
316bool DoRead(string name, const ScopedFd& fd, const string& expected) {
317 size_t length = expected.size();
318 int got;
319 string buf;
320 buf.resize(length);
321
322 while ((got = read(fd.get(), &buf[0], length)) < 0 && errno == EINTR);
323
324 if (got < 0) {
325 cerr << "Error reading from '" << name << "': " << strerror(errno) << endl;
326 return false;
327 }
328
329 if (buf != expected) {
330 cerr << "Expected '" << expected << "' got '" << buf << "'" << endl;
331 return false;
332 }
333
334 return true;
335}
336
337bool DoPipe(ScopedFd* read_side, ScopedFd* write_side) {
338 int fds[2];
339 ScopedFd return_fd;
340
341 if (pipe(fds)) {
342 cout << "Error creating pipes: " << strerror(errno) << endl;
343 return false;
344 }
345
346 read_side->reset(fds[0]);
347 write_side->reset(fds[1]);
348 return true;
349}
350
351bool ConfirmFileDescriptors(const sp<ITestService>& s) {
352 Status status;
353 cout << "Confirming passing and returning file descriptors works." << endl;
354
355 ScopedFd return_fd;
356 ScopedFd read_fd;
357 ScopedFd write_fd;
358
359 if (!DoPipe(&read_fd, &write_fd)) {
360 return false;
361 }
362
363 status = s->RepeatFileDescriptor(write_fd, &return_fd);
364
365 if (!status.isOk()) {
366 cerr << "Could not repeat file descriptors." << endl;
367 return false;
368 }
369
370 /* A note on some of the spookier stuff going on here: IIUC writes to pipes
371 * should be atomic and non-blocking so long as the total size doesn't exceed
372 * PIPE_BUF. We thus play a bit fast and loose with failure modes here.
373 */
374
375 bool ret =
376 DoWrite(FdByName(return_fd), "ReturnString") &&
377 DoRead(FdByName(read_fd), "ReturnString");
378
379 return ret;
380}
381
382bool ConfirmFileDescriptorArrays(const sp<ITestService>& s) {
383 Status status;
384 cout << "Confirming passing and returning file descriptor arrays works." << endl;
385
386 vector<ScopedFd> array;
387 array.resize(2);
388
389 if (!DoPipe(&array[0], &array[1])) {
390 return false;
391 }
392
393 vector<ScopedFd> repeated;
394 vector<ScopedFd> reversed;
395
396 status = s->ReverseFileDescriptorArray(array, &repeated, &reversed);
397
398 if (!status.isOk()) {
399 cerr << "Could not reverse file descriptor array." << endl;
400 return false;
401 }
402
403 bool ret =
404 DoWrite(FdByName(array[1]), "First") &&
405 DoWrite(FdByName(repeated[1]), "Second") &&
406 DoWrite(FdByName(reversed[0]), "Third") &&
407 DoRead(FdByName(reversed[1]), "FirstSecondThird");
408
409 return ret;
410}
Christopher Wileyb5e698c2015-10-17 09:32:22 -0700411} // namespace
412
Brian Carlstromad3b8062015-10-21 08:54:48 -0700413int main(int /* argc */, char * /* argv */ []) {
Christopher Wiley521bb612015-10-22 11:40:30 -0700414 sp<ITestService> service;
Christopher Wileyb5e698c2015-10-17 09:32:22 -0700415
Christopher Wiley33ad81e2015-10-21 14:41:11 -0700416 if (!GetService(&service)) return 1;
417
Christopher Wileyd6130f22015-10-26 10:24:35 -0700418 if (!ConfirmPrimitiveRepeat(service)) return 1;
Christopher Wileyb5e698c2015-10-17 09:32:22 -0700419
Christopher Wiley8949f832015-10-27 15:32:03 -0700420 if (!ConfirmReverseArrays(service)) return 1;
421
Christopher Wiley56c9bf32015-10-30 10:41:12 -0700422 if (!ConfirmReverseLists(service)) return 1;
423
Christopher Wiley95d44b02015-11-19 07:11:30 -0800424 if (!ConfirmParcelables(service)) return 1;
425
Casey Dahlin7ecd69f2015-11-03 13:52:38 -0800426 if (!ConfirmReverseBinderLists(service)) return 1;
427
Casey Dahlina4ba4b62015-11-02 15:43:30 -0800428 if (!ConfirmFileDescriptors(service)) return 1;
429
430 if (!ConfirmFileDescriptorArrays(service)) return 1;
431
Christopher Wileyb5e698c2015-10-17 09:32:22 -0700432 return 0;
433}