1 // Copyright 2021 gRPC authors. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 // A collection of fake objects that offers in-memory simulation of data 16 // transmission from one binder to another. 17 // 18 // Once the implementation of Binder is changed from BinderAndroid to 19 // FakeBinder, we'll be able to test and fuzz our end-to-end binder transport in 20 // a non-Android environment. 21 // 22 // The following diagram shows the high-level overview of how the in-memory 23 // simulation works (FakeReceiver means FakeTransactionReceiver). 24 // 25 // thread boundary 26 // | 27 // | 28 // ---------------- ---------------- | receive 29 // | FakeBinder | | FakeReceiver | <--|---------------- 30 // ---------------- ---------------- | | 31 // | ^ | ------------------------ 32 // | endpoint owner | | | TransactionProcessor | 33 // | | | ------------------------ 34 // v | | ^ 35 // ---------------- ---------------- | | 36 // | FakeEndpoint | --------> | FakeEndpoint | ---|---------------- 37 // ---------------- other_end ---------------- | enqueue 38 // | ^ ^ | | 39 // | | recv_endpoint | | | 40 // | | | | 41 // | | send_endpoint | | 42 // v | | v 43 // ------------------------------------------- 44 // | FakeBinderTunnel | 45 // ------------------------------------------- 46 47 #ifndef GRPC_TEST_CORE_TRANSPORT_BINDER_END2END_FAKE_BINDER_H 48 #define GRPC_TEST_CORE_TRANSPORT_BINDER_END2END_FAKE_BINDER_H 49 50 #include <atomic> 51 #include <forward_list> 52 #include <memory> 53 #include <queue> 54 #include <string> 55 #include <thread> 56 #include <tuple> 57 #include <utility> 58 #include <vector> 59 60 #include "absl/memory/memory.h" 61 #include "absl/random/random.h" 62 #include "absl/strings/str_format.h" 63 #include "absl/strings/string_view.h" 64 #include "absl/time/time.h" 65 #include "absl/types/variant.h" 66 67 #include "src/core/ext/transport/binder/wire_format/binder.h" 68 #include "src/core/ext/transport/binder/wire_format/wire_reader.h" 69 #include "src/core/lib/gprpp/sync.h" 70 #include "src/core/lib/gprpp/thd.h" 71 72 namespace grpc_binder { 73 namespace end2end_testing { 74 75 using FakeData = std::vector< 76 absl::variant<int32_t, int64_t, void*, std::string, std::vector<int8_t>>>; 77 78 // A fake writable parcel. 79 // 80 // It simulates the functionalities of a real writable parcel and stores all 81 // written data in memory. The data can then be transferred by calling 82 // MoveData(). 83 class FakeWritableParcel final : public WritableParcel { 84 public: 85 int32_t GetDataSize() const override; 86 absl::Status WriteInt32(int32_t data) override; 87 absl::Status WriteInt64(int64_t data) override; 88 absl::Status WriteBinder(HasRawBinder* binder) override; 89 absl::Status WriteString(absl::string_view s) override; 90 absl::Status WriteByteArray(const int8_t* buffer, int32_t length) override; 91 MoveData()92 FakeData MoveData() { return std::move(data_); } 93 94 private: 95 FakeData data_; 96 int32_t data_size_ = 0; 97 }; 98 99 // A fake readable parcel. 100 // 101 // It takes in the data transferred from a FakeWritableParcel and provides 102 // methods to retrieve those data in the receiving end. 103 class FakeReadableParcel final : public ReadableParcel { 104 public: FakeReadableParcel(FakeData data)105 explicit FakeReadableParcel(FakeData data) : data_(std::move(data)) { 106 for (auto& d : data_) { 107 if (absl::holds_alternative<int32_t>(d)) { 108 data_size_ += sizeof(int32_t); 109 } else if (absl::holds_alternative<int64_t>(d)) { 110 data_size_ += sizeof(int64_t); 111 } else if (absl::holds_alternative<void*>(d)) { 112 data_size_ += sizeof(void*); 113 } else if (absl::holds_alternative<std::string>(d)) { 114 data_size_ += absl::get<std::string>(d).size(); 115 } else { 116 data_size_ += absl::get<std::vector<int8_t>>(d).size(); 117 } 118 } 119 } 120 121 int32_t GetDataSize() const override; 122 absl::Status ReadInt32(int32_t* data) override; 123 absl::Status ReadInt64(int64_t* data) override; 124 absl::Status ReadBinder(std::unique_ptr<Binder>* data) override; 125 absl::Status ReadByteArray(std::string* data) override; 126 absl::Status ReadString(std::string* str) override; 127 128 private: 129 const FakeData data_; 130 size_t data_position_ = 0; 131 int32_t data_size_ = 0; 132 }; 133 134 class FakeBinder; 135 class FakeBinderTunnel; 136 137 // FakeEndpoint is a simple struct that holds the pointer to the other end, a 138 // pointer to the tunnel and a pointer to its owner. This tells the owner where 139 // the data should be sent. 140 struct FakeEndpoint { FakeEndpointFakeEndpoint141 explicit FakeEndpoint(FakeBinderTunnel* tunnel) : tunnel(tunnel) {} 142 143 FakeEndpoint* other_end; 144 FakeBinderTunnel* tunnel; 145 // The owner is either a FakeBinder (the sending part) or a 146 // FakeTransactionReceiver (the receiving part). Both parts hold an endpoint 147 // with |owner| pointing back to them and |other_end| pointing to each other. 148 void* owner; 149 }; 150 151 class PersistentFakeTransactionReceiver; 152 153 // A fake transaction receiver. 154 // 155 // This is the receiving part of a pair of binders. When constructed, a binder 156 // tunnle is created, and the sending part can be retrieved by calling 157 // GetSender(). 158 // 159 // It also provides a Receive() function to simulate the on-transaction 160 // callback of a real Android binder. 161 class FakeTransactionReceiver : public TransactionReceiver { 162 public: 163 FakeTransactionReceiver(grpc_core::RefCountedPtr<WireReader> wire_reader_ref, 164 TransactionReceiver::OnTransactCb cb); 165 166 void* GetRawBinder() override; 167 168 std::unique_ptr<Binder> GetSender() const; 169 170 private: 171 PersistentFakeTransactionReceiver* persistent_tx_receiver_; 172 }; 173 174 // A "persistent" version of the FakeTransactionReceiver. That is, its lifetime 175 // is managed by the processor and it outlives the wire reader and 176 // grpc_binder_transport, so we can safely dereference a pointer to it in 177 // ProcessLoop(). 178 class PersistentFakeTransactionReceiver { 179 public: 180 PersistentFakeTransactionReceiver( 181 grpc_core::RefCountedPtr<WireReader> wire_reader_ref, 182 TransactionReceiver::OnTransactCb cb, 183 std::unique_ptr<FakeBinderTunnel> tunnel); 184 Receive(BinderTransportTxCode tx_code,ReadableParcel * parcel)185 absl::Status Receive(BinderTransportTxCode tx_code, ReadableParcel* parcel) { 186 return callback_(static_cast<transaction_code_t>(tx_code), parcel, 187 /*uid=*/0); 188 } 189 190 private: 191 grpc_core::RefCountedPtr<WireReader> wire_reader_ref_; 192 TransactionReceiver::OnTransactCb callback_; 193 std::unique_ptr<FakeBinderTunnel> tunnel_; 194 195 friend class FakeTransactionReceiver; 196 }; 197 198 // The sending part of a binders pair. It provides a FakeWritableParcel to the 199 // user, and when Transact() is called, it transfers the written data to the 200 // other end of the tunnel by following the information in its endpoint. 201 class FakeBinder final : public Binder { 202 public: FakeBinder(FakeEndpoint * endpoint)203 explicit FakeBinder(FakeEndpoint* endpoint) : endpoint_(endpoint) {} 204 Initialize()205 void Initialize() override {} PrepareTransaction()206 absl::Status PrepareTransaction() override { 207 input_ = std::make_unique<FakeWritableParcel>(); 208 return absl::OkStatus(); 209 } 210 211 absl::Status Transact(BinderTransportTxCode tx_code) override; 212 GetWritableParcel()213 WritableParcel* GetWritableParcel() const override { return input_.get(); } 214 215 std::unique_ptr<TransactionReceiver> ConstructTxReceiver( 216 grpc_core::RefCountedPtr<WireReader> wire_reader_ref, 217 TransactionReceiver::OnTransactCb transact_cb) const override; 218 GetRawBinder()219 void* GetRawBinder() override { return endpoint_->other_end; } 220 221 private: 222 FakeEndpoint* endpoint_; 223 std::unique_ptr<FakeWritableParcel> input_; 224 }; 225 226 // A transaction processor. 227 // 228 // Once constructed, it'll create a another thread that deliver in-coming 229 // transactions to their destinations. 230 class TransactionProcessor { 231 public: 232 explicit TransactionProcessor(absl::Duration delay = absl::ZeroDuration()); ~TransactionProcessor()233 ~TransactionProcessor() { Terminate(); } 234 235 void SetDelay(absl::Duration delay); 236 237 void Terminate(); 238 void ProcessLoop(); 239 void Flush(); 240 241 // Issue a transaction with |target| pointing to the target endpoint. The 242 // transactions will be delivered in the same order they're issued, possibly 243 // with random delay to simulate real-world situation. 244 void EnQueueTransaction(FakeEndpoint* target, BinderTransportTxCode tx_code, 245 FakeData data); 246 NewPersistentTxReceiver(grpc_core::RefCountedPtr<WireReader> wire_reader_ref,TransactionReceiver::OnTransactCb cb,std::unique_ptr<FakeBinderTunnel> tunnel)247 PersistentFakeTransactionReceiver& NewPersistentTxReceiver( 248 grpc_core::RefCountedPtr<WireReader> wire_reader_ref, 249 TransactionReceiver::OnTransactCb cb, 250 std::unique_ptr<FakeBinderTunnel> tunnel) { 251 grpc_core::MutexLock lock(&tx_receiver_mu_); 252 storage_.emplace_front(wire_reader_ref, cb, std::move(tunnel)); 253 return storage_.front(); 254 } 255 256 private: 257 absl::Duration GetRandomDelay(); 258 void WaitForNextTransaction() ABSL_EXCLUSIVE_LOCKS_REQUIRED(mu_); 259 260 grpc_core::Mutex mu_; 261 std::queue<std::tuple<FakeEndpoint*, BinderTransportTxCode, FakeData>> 262 tx_queue_ ABSL_GUARDED_BY(mu_); 263 absl::Time deliver_time_ ABSL_GUARDED_BY(mu_); 264 int64_t delay_nsec_; 265 absl::BitGen bit_gen_; 266 grpc_core::Thread tx_thread_; 267 std::atomic<bool> terminated_; 268 269 grpc_core::Mutex tx_receiver_mu_; 270 // Use forward_list to avoid invalid pointers resulted by reallocation in 271 // containers such as std::vector. 272 std::forward_list<PersistentFakeTransactionReceiver> storage_ 273 ABSL_GUARDED_BY(tx_receiver_mu_); 274 }; 275 276 // The global (shared) processor. Test suite should be responsible of 277 // creating/deleting it. 278 extern TransactionProcessor* g_transaction_processor; 279 280 // A binder tunnel. 281 // 282 // It is a simple helper that creates and links two endpoints. 283 class FakeBinderTunnel { 284 public: 285 FakeBinderTunnel(); 286 EnQueueTransaction(FakeEndpoint * target,BinderTransportTxCode tx_code,FakeData data)287 void EnQueueTransaction(FakeEndpoint* target, BinderTransportTxCode tx_code, 288 FakeData data) { 289 g_transaction_processor->EnQueueTransaction(target, tx_code, 290 std::move(data)); 291 } 292 GetSendEndpoint()293 FakeEndpoint* GetSendEndpoint() const { return send_endpoint_.get(); } GetRecvEndpoint()294 FakeEndpoint* GetRecvEndpoint() const { return recv_endpoint_.get(); } 295 296 private: 297 std::unique_ptr<FakeEndpoint> send_endpoint_; 298 std::unique_ptr<FakeEndpoint> recv_endpoint_; 299 }; 300 301 // A helper function for constructing a pair of connected binders. 302 std::pair<std::unique_ptr<Binder>, std::unique_ptr<TransactionReceiver>> 303 NewBinderPair(TransactionReceiver::OnTransactCb transact_cb); 304 305 } // namespace end2end_testing 306 } // namespace grpc_binder 307 308 #endif // GRPC_TEST_CORE_TRANSPORT_BINDER_END2END_FAKE_BINDER_H 309