• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2018 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 #pragma once
18 
19 #include <android/binder_auto_utils.h>
20 #include <android/binder_ibinder.h>
21 #include <gtest/gtest.h>
22 #include <nativetesthelper_jni/utils.h>
23 
24 #include <functional>
25 
26 // Helpers for testing
27 
28 template <typename T>
29 static inline ::testing::AssertionResult isOk(T) = delete;
30 
31 template <>
isOk(::ndk::ScopedAStatus t)32 inline ::testing::AssertionResult isOk(::ndk::ScopedAStatus t) {
33   if (AStatus_isOk(t.get())) {
34     return ::testing::AssertionSuccess();
35   } else {
36     return ::testing::AssertionFailure()
37            << "exception: " << AStatus_getExceptionCode(t.get())
38            << " service specific: " << AStatus_getServiceSpecificError(t.get())
39            << " status: " << AStatus_getStatus(t.get());
40   }
41 }
42 
43 template <>
isOk(binder_status_t t)44 inline ::testing::AssertionResult isOk(binder_status_t t) {
45   if (t == STATUS_OK) {
46     return ::testing::AssertionSuccess();
47   }
48   return ::testing::AssertionFailure() << "Status: " << t;
49 }
50 
51 #define EXPECT_OK(THING) EXPECT_TRUE(isOk(THING))
52 #define ASSERT_OK(THING) ASSERT_TRUE(isOk(THING))
53 
54 // placeholder
55 constexpr transaction_code_t kCode = +1 + 918;
56 
57 // Usually, things at this level would be generated by the aidl compiler. This
58 // class is merely to make testing the API easier.
59 
60 struct SampleData;
61 
62 typedef std::function<void(SampleData*)> OnDestroyFunc;
63 typedef std::function<binder_status_t(transaction_code_t code,
64                                       const AParcel* in, AParcel* out)>
65     OnTransactFunc;
66 
67 typedef std::function<binder_status_t(AParcel*)> WriteParcel;
68 typedef std::function<binder_status_t(const AParcel*)> ReadParcel;
69 
WriteNothingToParcel(AParcel *)70 static inline binder_status_t WriteNothingToParcel(AParcel*) {
71   return STATUS_OK;
72 }
ReadNothingFromParcel(const AParcel *)73 static inline binder_status_t ReadNothingFromParcel(const AParcel*) {
74   return STATUS_OK;
75 }
76 
77 // There is an assert instances of this class are destroyed in NdkBinderTest
78 struct ThisShouldBeDestroyed {
79   static size_t numInstances();
80 
81   ThisShouldBeDestroyed();
82   virtual ~ThisShouldBeDestroyed();
83 };
84 
85 struct SampleData : ThisShouldBeDestroyed {
86   static const char* kDescriptor;
87   static const AIBinder_Class* kClass;
88 
89   static const char* kAnotherDescriptor;
90   static const AIBinder_Class* kAnotherClass;
91 
92   SampleData(const OnTransactFunc& oT = nullptr,
93              const OnDestroyFunc& oD = nullptr)
onTransactSampleData94       : onTransact(oT), onDestroy(oD) {}
95 
96   // This is called when the class is transacted on if non-null.
97   // Otherwise, STATUS_FAILED_TRANSACTION is returned.
98   OnTransactFunc onTransact;
99 
100   // This is called when the class is destroyed if non-null.
101   OnDestroyFunc onDestroy;
102 
103   // Automatically updated by this class whenever a transaction is received.
104   int numberTransactions = 0;
105 
106   __attribute__((warn_unused_result)) static AIBinder* newBinder(
107       OnTransactFunc onTransact = nullptr, OnDestroyFunc onDestroy = nullptr) {
108     SampleData* data = new SampleData(onTransact, onDestroy);
109     return AIBinder_new(kClass, static_cast<void*>(data));
110   };
111 
112   // Helper method to simplify transaction logic
113   static binder_status_t transact(AIBinder* binder, transaction_code_t code,
114                                   WriteParcel writeFunc = WriteNothingToParcel,
115                                   ReadParcel readFunc = ReadNothingFromParcel,
116                                   binder_flags_t flags = 0) {
117     AParcel* in;
118     binder_status_t status = AIBinder_prepareTransaction(binder, &in);
119     if (status != STATUS_OK) return status;
120 
121     status = writeFunc(in);
122     if (status != STATUS_OK) {
123       AParcel_delete(in);
124       return status;
125     }
126 
127     AParcel* out;
128     status = AIBinder_transact(binder, code, &in, &out, flags);
129     if (status != STATUS_OK) return status;
130 
131     status = readFunc(out);
132     AParcel_delete(out);
133 
134     return status;
135   }
136 };
137 
ExpectLifetimeTransactions(size_t count)138 static inline OnDestroyFunc ExpectLifetimeTransactions(size_t count) {
139   return [count](SampleData* data) {
140     EXPECT_EQ(count, data->numberTransactions)
141         << "Expected " << count
142         << " transaction(s), but over the lifetime of this object, it received "
143         << data->numberTransactions;
144   };
145 }
146 
TransactionsReturn(binder_status_t result)147 static inline OnTransactFunc TransactionsReturn(binder_status_t result) {
148   return
149       [result](transaction_code_t, const AParcel*, AParcel*) { return result; };
150 }
151 
152 class NdkBinderTest : public ::testing::Test {
153  public:
SetUp()154   void SetUp() override { instances = ThisShouldBeDestroyed::numInstances(); }
TearDown()155   void TearDown() override {
156     EXPECT_EQ(instances, ThisShouldBeDestroyed::numInstances());
157   }
158 
159  private:
160   size_t instances = 0;
161 };
162 
163 JNIEnv* GetEnv();
164