1 // Copyright 2021 gRPC authors.
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
7 // http://www.apache.org/licenses/LICENSE-2.0
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.
15 // A collection of fake objects that offers in-memory simulation of data
16 // transmission from one binder to another.
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.
22 // The following diagram shows the high-level overview of how the in-memory
23 // simulation works (FakeReceiver means FakeTransactionReceiver).
28 // ---------------- ---------------- | receive
29 // | FakeBinder | | FakeReceiver | <--|----------------
30 // ---------------- ---------------- | |
31 // | ^ | ------------------------
32 // | endpoint owner | | | TransactionProcessor |
33 // | | | ------------------------
35 // ---------------- ---------------- | |
36 // | FakeEndpoint | --------> | FakeEndpoint | ---|----------------
37 // ---------------- other_end ---------------- | enqueue
39 // | | recv_endpoint | | |
41 // | | send_endpoint | |
43 // -------------------------------------------
44 // | FakeBinderTunnel |
45 // -------------------------------------------
47 #ifndef GRPC_TEST_CORE_TRANSPORT_BINDER_END2END_FAKE_BINDER_H
48 #define GRPC_TEST_CORE_TRANSPORT_BINDER_END2END_FAKE_BINDER_H
51 #include <forward_list>
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"
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"
72 namespace grpc_binder {
73 namespace end2end_testing {
75 using FakeData = std::vector<
76 absl::variant<int32_t, int64_t, void*, std::string, std::vector<int8_t>>>;
78 // A fake writable parcel.
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
83 class FakeWritableParcel final : public WritableParcel {
86 int32_t GetDataPosition() const override;
87 int32_t GetDataSize() const override;
88 absl::Status SetDataPosition(int32_t pos) override;
89 absl::Status WriteInt32(int32_t data) override;
90 absl::Status WriteInt64(int64_t data) override;
91 absl::Status WriteBinder(HasRawBinder* binder) override;
92 absl::Status WriteString(absl::string_view s) override;
93 absl::Status WriteByteArray(const int8_t* buffer, int32_t length) override;
95 FakeData MoveData() { return std::move(data_); }
99 size_t data_position_ = 0;
100 int32_t data_size_ = 0;
103 // A fake readable parcel.
105 // It takes in the data transferred from a FakeWritableParcel and provides
106 // methods to retrieve those data in the receiving end.
107 class FakeReadableParcel final : public ReadableParcel {
109 explicit FakeReadableParcel(FakeData data) : data_(std::move(data)) {
110 for (auto& d : data_) {
111 if (absl::holds_alternative<int32_t>(d)) {
113 } else if (absl::holds_alternative<int64_t>(d)) {
115 } else if (absl::holds_alternative<void*>(d)) {
117 } else if (absl::holds_alternative<std::string>(d)) {
118 data_size_ += absl::get<std::string>(d).size();
120 data_size_ += absl::get<std::vector<int8_t>>(d).size();
125 int32_t GetDataSize() const override;
126 absl::Status ReadInt32(int32_t* data) const override;
127 absl::Status ReadInt64(int64_t* data) const override;
128 absl::Status ReadBinder(std::unique_ptr<Binder>* data) const override;
129 absl::Status ReadByteArray(std::string* data) const override;
130 absl::Status ReadString(char data[111]) const override;
133 const FakeData data_;
134 mutable size_t data_position_ = 0;
135 int32_t data_size_ = 0;
139 class FakeBinderTunnel;
141 // FakeEndpoint is a simple struct that holds the pointer to the other end, a
142 // pointer to the tunnel and a pointer to its owner. This tells the owner where
143 // the data should be sent.
144 struct FakeEndpoint {
145 explicit FakeEndpoint(FakeBinderTunnel* tunnel) : tunnel(tunnel) {}
147 FakeEndpoint* other_end;
148 FakeBinderTunnel* tunnel;
149 // The owner is either a FakeBinder (the sending part) or a
150 // FakeTransactionReceiver (the receiving part). Both parts hold an endpoint
151 // with |owner| pointing back to them and |other_end| pointing to each other.
155 class PersistentFakeTransactionReceiver;
157 // A fake transaction receiver.
159 // This is the receiving part of a pair of binders. When constructed, a binder
160 // tunnle is created, and the sending part can be retrieved by calling
163 // It also provides a Receive() function to simulate the on-transaction
164 // callback of a real Android binder.
165 class FakeTransactionReceiver : public TransactionReceiver {
167 FakeTransactionReceiver(grpc_core::RefCountedPtr<WireReader> wire_reader_ref,
168 TransactionReceiver::OnTransactCb cb);
170 void* GetRawBinder() override;
172 std::unique_ptr<Binder> GetSender() const;
175 PersistentFakeTransactionReceiver* persistent_tx_receiver_;
178 // A "persistent" version of the FakeTransactionReceiver. That is, its lifetime
179 // is managed by the processor and it outlives the wire reader and
180 // grpc_binder_transport, so we can safely dereference a pointer to it in
182 class PersistentFakeTransactionReceiver {
184 PersistentFakeTransactionReceiver(
185 grpc_core::RefCountedPtr<WireReader> wire_reader_ref,
186 TransactionReceiver::OnTransactCb cb,
187 std::unique_ptr<FakeBinderTunnel> tunnel);
189 absl::Status Receive(BinderTransportTxCode tx_code,
190 const ReadableParcel* parcel) {
191 return callback_(static_cast<transaction_code_t>(tx_code), parcel);
195 grpc_core::RefCountedPtr<WireReader> wire_reader_ref_;
196 TransactionReceiver::OnTransactCb callback_;
197 std::unique_ptr<FakeBinderTunnel> tunnel_;
199 friend class FakeTransactionReceiver;
202 // The sending part of a binders pair. It provides a FakeWritableParcel to the
203 // user, and when Transact() is called, it transfers the written data to the
204 // other end of the tunnel by following the information in its endpoint.
205 class FakeBinder final : public Binder {
207 explicit FakeBinder(FakeEndpoint* endpoint) : endpoint_(endpoint) {}
209 void Initialize() override {}
210 absl::Status PrepareTransaction() override {
211 input_ = absl::make_unique<FakeWritableParcel>();
212 return absl::OkStatus();
215 absl::Status Transact(BinderTransportTxCode tx_code) override;
217 WritableParcel* GetWritableParcel() const override { return input_.get(); }
218 ReadableParcel* GetReadableParcel() const override { return output_.get(); }
220 std::unique_ptr<TransactionReceiver> ConstructTxReceiver(
221 grpc_core::RefCountedPtr<WireReader> wire_reader_ref,
222 TransactionReceiver::OnTransactCb transact_cb) const override;
224 void* GetRawBinder() override { return endpoint_->other_end; }
227 FakeEndpoint* endpoint_;
228 std::unique_ptr<FakeWritableParcel> input_;
229 std::unique_ptr<FakeReadableParcel> output_;
232 // A transaction processor.
234 // Once constructed, it'll create a another thread that deliver in-coming
235 // transactions to their destinations.
236 class TransactionProcessor {
238 explicit TransactionProcessor(absl::Duration delay = absl::ZeroDuration());
239 ~TransactionProcessor() { Terminate(); }
241 void SetDelay(absl::Duration delay);
247 // Issue a transaction with |target| pointing to the target endpoint. The
248 // transactions will be delivered in the same order they're issued, possibly
249 // with random delay to simulate real-world situation.
250 void EnQueueTransaction(FakeEndpoint* target, BinderTransportTxCode tx_code,
253 PersistentFakeTransactionReceiver& NewPersistentTxReceiver(
254 grpc_core::RefCountedPtr<WireReader> wire_reader_ref,
255 TransactionReceiver::OnTransactCb cb,
256 std::unique_ptr<FakeBinderTunnel> tunnel) {
257 grpc_core::MutexLock lock(&tx_receiver_mu_);
258 storage_.emplace_front(wire_reader_ref, cb, std::move(tunnel));
259 return storage_.front();
263 absl::Duration GetRandomDelay();
264 void WaitForNextTransaction() ABSL_EXCLUSIVE_LOCKS_REQUIRED(mu_);
266 grpc_core::Mutex mu_;
267 std::queue<std::tuple<FakeEndpoint*, BinderTransportTxCode, FakeData>>
268 tx_queue_ ABSL_GUARDED_BY(mu_);
269 absl::Time deliver_time_ ABSL_GUARDED_BY(mu_);
271 absl::BitGen bit_gen_;
272 grpc_core::Thread tx_thread_;
273 std::atomic<bool> terminated_;
275 grpc_core::Mutex tx_receiver_mu_;
276 // Use forward_list to avoid invalid pointers resulted by reallocation in
277 // containers such as std::vector.
278 std::forward_list<PersistentFakeTransactionReceiver> storage_
279 ABSL_GUARDED_BY(tx_receiver_mu_);
282 // The global (shared) processor. Test suite should be responsible of
283 // creating/deleting it.
284 extern TransactionProcessor* g_transaction_processor;
288 // It is a simple helper that creates and links two endpoints.
289 class FakeBinderTunnel {
293 void EnQueueTransaction(FakeEndpoint* target, BinderTransportTxCode tx_code,
295 g_transaction_processor->EnQueueTransaction(target, tx_code,
299 FakeEndpoint* GetSendEndpoint() const { return send_endpoint_.get(); }
300 FakeEndpoint* GetRecvEndpoint() const { return recv_endpoint_.get(); }
303 std::unique_ptr<FakeEndpoint> send_endpoint_;
304 std::unique_ptr<FakeEndpoint> recv_endpoint_;
307 // A helper function for constructing a pair of connected binders.
308 std::pair<std::unique_ptr<Binder>, std::unique_ptr<TransactionReceiver>>
309 NewBinderPair(TransactionReceiver::OnTransactCb transact_cb);
311 } // namespace end2end_testing
312 } // namespace grpc_binder
314 #endif // GRPC_TEST_CORE_TRANSPORT_BINDER_END2END_FAKE_BINDER_H