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
ContainsSubstring(const std::string & s,const std::string & ss)51 inline ::testing::AssertionResult ContainsSubstring(const std::string& s, const std::string& ss) {
52 if (s.find(ss) != std::string::npos) {
53 return ::testing::AssertionSuccess();
54 } else {
55 return ::testing::AssertionFailure()
56 << "String: '" << s << "' does not contain substring: " << ss;
57 }
58 }
59
60 #define EXPECT_OK(THING) EXPECT_TRUE(isOk(THING))
61 #define ASSERT_OK(THING) ASSERT_TRUE(isOk(THING))
62
63 // placeholder
64 constexpr transaction_code_t kCode = +1 + 918;
65
66 // Usually, things at this level would be generated by the aidl compiler. This
67 // class is merely to make testing the API easier.
68
69 struct SampleData;
70
71 typedef std::function<void(SampleData*)> OnDestroyFunc;
72 typedef std::function<binder_status_t(transaction_code_t code,
73 const AParcel* in, AParcel* out)>
74 OnTransactFunc;
75
76 typedef std::function<binder_status_t(AParcel*)> WriteParcel;
77 typedef std::function<binder_status_t(const AParcel*)> ReadParcel;
78
WriteNothingToParcel(AParcel *)79 static inline binder_status_t WriteNothingToParcel(AParcel*) {
80 return STATUS_OK;
81 }
ReadNothingFromParcel(const AParcel *)82 static inline binder_status_t ReadNothingFromParcel(const AParcel*) {
83 return STATUS_OK;
84 }
85
86 // There is an assert instances of this class are destroyed in NdkBinderTest
87 struct ThisShouldBeDestroyed {
88 static size_t numInstances();
89
90 ThisShouldBeDestroyed();
91 virtual ~ThisShouldBeDestroyed();
92 };
93
94 struct SampleData : ThisShouldBeDestroyed {
95 static const char* kDescriptor;
96 static const AIBinder_Class* kClass;
97 static const AIBinder_Class* kAnotherClassWithSameDescriptor;
98
99 static const char* kAnotherDescriptor;
100 static const AIBinder_Class* kAnotherClass;
101
102 SampleData(const OnTransactFunc& oT = nullptr,
103 const OnDestroyFunc& oD = nullptr)
onTransactSampleData104 : onTransact(oT), onDestroy(oD) {}
105
106 // This is called when the class is transacted on if non-null.
107 // Otherwise, STATUS_FAILED_TRANSACTION is returned.
108 OnTransactFunc onTransact;
109
110 // This is called when the class is destroyed if non-null.
111 OnDestroyFunc onDestroy;
112
113 // Automatically updated by this class whenever a transaction is received.
114 int numberTransactions = 0;
115
116 __attribute__((warn_unused_result)) static AIBinder* newBinder(
117 OnTransactFunc onTransact = nullptr, OnDestroyFunc onDestroy = nullptr) {
118 SampleData* data = new SampleData(onTransact, onDestroy);
119 return AIBinder_new(kClass, static_cast<void*>(data));
120 };
121
122 // Helper method to simplify transaction logic
123 static binder_status_t transact(AIBinder* binder, transaction_code_t code,
124 WriteParcel writeFunc = WriteNothingToParcel,
125 ReadParcel readFunc = ReadNothingFromParcel,
126 binder_flags_t flags = 0) {
127 AParcel* in;
128 binder_status_t status = AIBinder_prepareTransaction(binder, &in);
129 if (status != STATUS_OK) return status;
130
131 status = writeFunc(in);
132 if (status != STATUS_OK) {
133 AParcel_delete(in);
134 return status;
135 }
136
137 AParcel* out;
138 status = AIBinder_transact(binder, code, &in, &out, flags);
139 if (status != STATUS_OK) return status;
140
141 status = readFunc(out);
142 AParcel_delete(out);
143
144 return status;
145 }
146 };
147
ExpectLifetimeTransactions(size_t count)148 static inline OnDestroyFunc ExpectLifetimeTransactions(size_t count) {
149 return [count](SampleData* data) {
150 EXPECT_EQ(count, data->numberTransactions)
151 << "Expected " << count
152 << " transaction(s), but over the lifetime of this object, it received "
153 << data->numberTransactions;
154 };
155 }
156
TransactionsReturn(binder_status_t result)157 static inline OnTransactFunc TransactionsReturn(binder_status_t result) {
158 return
159 [result](transaction_code_t, const AParcel*, AParcel*) { return result; };
160 }
161
162 class NdkBinderTest : public ::testing::Test {
163 public:
SetUp()164 void SetUp() override { instances = ThisShouldBeDestroyed::numInstances(); }
TearDown()165 void TearDown() override {
166 EXPECT_EQ(instances, ThisShouldBeDestroyed::numInstances());
167 }
168
169 private:
170 size_t instances = 0;
171 };
172
173 JNIEnv* GetEnv();
174 jobject callStaticJavaMethodForObject(JNIEnv* env, const std::string& clazz,
175 const std::string& method, const std::string& type);
176