Home | History | Annotate | Download | only in tests
      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 "aidl_test_client_nullables.h"
     18 
     19 #include <utils/String16.h>
     20 
     21 #include <iostream>
     22 #include <memory>
     23 #include <string>
     24 #include <vector>
     25 
     26 // libutils:
     27 using android::sp;
     28 using android::String16;
     29 
     30 // libbinder:
     31 using android::binder::Status;
     32 
     33 // generated
     34 using android::aidl::tests::ITestService;
     35 using android::aidl::tests::SimpleParcelable;
     36 
     37 using std::string;
     38 using std::unique_ptr;
     39 using std::vector;
     40 using std::cout;
     41 using std::cerr;
     42 using std::endl;
     43 
     44 namespace android {
     45 namespace aidl {
     46 namespace tests {
     47 namespace client {
     48 
     49 namespace {
     50 template<typename T>
     51 bool ValuesEqual(const unique_ptr<T>& in, const unique_ptr<T>& out) {
     52   return *in == *out;
     53 }
     54 
     55 template<>
     56 bool ValuesEqual<vector<unique_ptr<String16>>>(
     57     const unique_ptr<vector<unique_ptr<String16>>>& in,
     58     const unique_ptr<vector<unique_ptr<String16>>>& out) {
     59   if (!in) {
     60     return !out;
     61   }
     62 
     63   if (!out) {
     64     return false;
     65   }
     66 
     67   if (in->size() != out->size()) {
     68     return false;
     69   }
     70 
     71   for (size_t i = 0; i < in->size(); i++) {
     72     const unique_ptr<String16>& a = (*in)[i];
     73     const unique_ptr<String16>& b = (*out)[i];
     74 
     75     if (!(a || b)) {
     76       continue;
     77     }
     78 
     79     if (!(a && b)) {
     80       return false;
     81     }
     82 
     83     if (*a != *b) {
     84       return false;
     85     }
     86   }
     87 
     88   return true;
     89 }
     90 
     91 template<typename T>
     92 bool ConfirmNullableType(const sp<ITestService>& s, const string& type_name,
     93                          unique_ptr<T> in,
     94                          Status(ITestService::*func)(const unique_ptr<T>&,
     95                                                      unique_ptr<T>*)) {
     96   cout << "... Confirming nullables for " << type_name << " ..." << endl;
     97   Status status;
     98   unique_ptr<T> out;
     99 
    100   status = (*s.*func)(in, &out);
    101 
    102   if (!status.isOk()) {
    103     cerr << "Could not repeat nullable " << type_name << "." << endl;
    104     return false;
    105   }
    106 
    107   if (!out) {
    108     cerr << "Got back null when repeating " << type_name << "." << endl;
    109     return false;
    110   }
    111 
    112   if (!ValuesEqual(in, out)) {
    113     cerr << "Got back a non-matching value when repeating " << type_name
    114          << "." << endl;
    115     return false;
    116   }
    117 
    118   in.reset();
    119   status = (*s.*func)(in, &out);
    120 
    121   if (!status.isOk()) {
    122     cerr << "Could not repeat null as " << type_name << "." << endl;
    123     return false;
    124   }
    125 
    126   if (out) {
    127     cerr << "Got back a value when sent null for " << type_name << "."
    128          << endl;
    129     return false;
    130   }
    131 
    132   return true;
    133 }
    134 
    135 bool CheckAppropriateIBinderHandling(const sp<ITestService>& s) {
    136 
    137   Status status;
    138   sp<IBinder> binder = new BBinder();
    139   sp<IBinder> null_binder = nullptr;
    140   unique_ptr<vector<sp<IBinder>>> list_with_nulls(
    141       new vector<sp<IBinder>>{binder, null_binder});
    142   unique_ptr<vector<sp<IBinder>>> list_without_nulls(
    143       new vector<sp<IBinder>>{binder, binder});
    144 
    145   // Methods without @nullable throw up when given null binders
    146   if (s->TakesAnIBinder(null_binder).exceptionCode() !=
    147       binder::Status::EX_NULL_POINTER) {
    148     cerr << "Did not receive expected null exception on line: "
    149          << __LINE__ << endl;
    150     return false;
    151   }
    152   if (s->TakesAnIBinderList(*list_with_nulls).exceptionCode() !=
    153       binder::Status::EX_NULL_POINTER) {
    154     cerr << "Did not receive expected null exception on line: "
    155          << __LINE__ << endl;
    156     return false;
    157   }
    158 
    159   // But those same methods are fine with valid binders
    160   if (!s->TakesAnIBinder(binder).isOk()) {
    161     cerr << "Received unexpected exception on line "
    162          << __LINE__ << endl;
    163     return false;
    164   }
    165   if (!s->TakesAnIBinderList(*list_without_nulls).isOk()) {
    166     cerr << "Received unexpected exception on line "
    167          << __LINE__ << endl;
    168     return false;
    169   }
    170 
    171   // And methods with @nullable don't care.
    172   if (!s->TakesANullableIBinder(null_binder).isOk()) {
    173     cerr << "Received unexpected exception on line "
    174          << __LINE__ << endl;
    175     return false;
    176   }
    177   if (!s->TakesANullableIBinder(binder).isOk()) {
    178     cerr << "Received unexpected exception on line "
    179          << __LINE__ << endl;
    180     return false;
    181   }
    182   if (!s->TakesANullableIBinderList(list_with_nulls).isOk()) {
    183     cerr << "Received unexpected exception on line "
    184          << __LINE__ << endl;
    185     return false;
    186   }
    187   if (!s->TakesANullableIBinderList(list_without_nulls).isOk()) {
    188     cerr << "Received unexpected exception on line "
    189          << __LINE__ << endl;
    190     return false;
    191   }
    192 
    193   return true;
    194 }
    195 
    196 bool CheckAppropriateIInterfaceHandling(const sp<ITestService>& s) {
    197 
    198   sp<INamedCallback> callback;
    199   if (!s->GetCallback(false, &callback).isOk()) {
    200     cerr << "Received unexpected exception on line "
    201          << __LINE__ << endl;
    202     return false;
    203   }
    204   if (callback.get() == nullptr) {
    205     cerr << "Expected to receive a non-null binder on line: "
    206          << __LINE__ << endl;
    207     return false;
    208   }
    209   if (!s->GetCallback(true, &callback).isOk()) {
    210     cerr << "Received unexpected exception on line "
    211          << __LINE__ << endl;
    212     return false;
    213   }
    214   if (callback.get() != nullptr) {
    215     cerr << "Expected to receive a null binder on line: "
    216          << __LINE__ << endl;
    217     return false;
    218   }
    219   return true;
    220 }
    221 
    222 }  // namespace
    223 
    224 bool ConfirmNullables(const sp<ITestService>& s) {
    225   Status status;
    226   cout << "Confirming passing and returning nullable values works." << endl;
    227 
    228   if (!ConfirmNullableType(s, "integer array",
    229                            unique_ptr<vector<int32_t>>(
    230                                new vector<int32_t>({1,2,3})),
    231                            &ITestService::RepeatNullableIntArray)) {
    232     return false;
    233   }
    234 
    235   if (!ConfirmNullableType(s, "string",
    236                            unique_ptr<String16>(new String16("Blooob")),
    237                            &ITestService::RepeatNullableString)) {
    238     return false;
    239   }
    240 
    241   unique_ptr<vector<unique_ptr<String16>>> test_string_array(
    242       new vector<unique_ptr<String16>>());
    243   test_string_array->push_back(unique_ptr<String16>(new String16("Wat")));
    244   test_string_array->push_back(unique_ptr<String16>(
    245       new String16("Blooob")));
    246   test_string_array->push_back(unique_ptr<String16>(new String16("Wat")));
    247   test_string_array->push_back(unique_ptr<String16>(nullptr));
    248   test_string_array->push_back(unique_ptr<String16>(new String16("YEAH")));
    249   test_string_array->push_back(unique_ptr<String16>(
    250       new String16("OKAAAAY")));
    251 
    252   if (!ConfirmNullableType(s, "string array", std::move(test_string_array),
    253                            &ITestService::RepeatNullableStringList)) {
    254     return false;
    255   }
    256 
    257   if (!ConfirmNullableType(s, "parcelable",
    258                            unique_ptr<SimpleParcelable>(
    259                                new SimpleParcelable("Booya", 42)),
    260                            &ITestService::RepeatNullableParcelable)) {
    261     return false;
    262   }
    263 
    264   if (!CheckAppropriateIBinderHandling(s)) {
    265     cerr << "Handled null IBinders poorly." << endl;
    266     return false;
    267   }
    268 
    269   if (!CheckAppropriateIInterfaceHandling(s)) {
    270     cerr << "Handled nullable IInterface instances poorly." << endl;
    271     return false;
    272   }
    273 
    274   return true;
    275 }
    276 
    277 }  // namespace client
    278 }  // namespace tests
    279 }  // namespace aidl
    280 }  // namespace android
    281