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