1 // Copyright 2023 The Pigweed Authors
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License"); you may not
4 // use this file except in compliance with the License. You may obtain a copy of
5 // the License at
6 //
7 //     https://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, WITHOUT
11 // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12 // License for the specific language governing permissions and limitations under
13 // the License.
14 
15 #pragma once
16 #include "pw_async/heap_dispatcher.h"
17 #include "pw_bluetooth_sapphire/internal/host/att/error.h"
18 #include "pw_bluetooth_sapphire/internal/host/gatt/client.h"
19 
20 namespace bt::gatt::testing {
21 
22 class FakeClient final : public Client {
23  public:
24   explicit FakeClient(pw::async::Dispatcher& pw_dispatcher);
25   ~FakeClient() override = default;
26 
set_server_mtu(uint16_t mtu)27   void set_server_mtu(uint16_t mtu) { server_mtu_ = mtu; }
set_exchange_mtu_status(att::Result<> status)28   void set_exchange_mtu_status(att::Result<> status) {
29     exchange_mtu_status_ = status;
30   }
31 
set_services(std::vector<ServiceData> services)32   void set_services(std::vector<ServiceData> services) {
33     services_ = std::move(services);
34   }
35 
set_characteristics(std::vector<CharacteristicData> chrcs)36   void set_characteristics(std::vector<CharacteristicData> chrcs) {
37     chrcs_ = std::move(chrcs);
38   }
39 
set_descriptors(std::vector<DescriptorData> descs)40   void set_descriptors(std::vector<DescriptorData> descs) {
41     descs_ = std::move(descs);
42   }
43 
set_characteristic_discovery_status(att::Result<> status)44   void set_characteristic_discovery_status(att::Result<> status) {
45     chrc_discovery_status_ = status;
46   }
47 
48   // If |count| is set to a non-zero value, |status| only applies to |count|th
49   // request and all other requests will succeed. Otherwise, |status| applies to
50   // all requests.
51   void set_descriptor_discovery_status(att::Result<> status, size_t count = 0) {
52     desc_discovery_status_target_ = count;
53     desc_discovery_status_ = status;
54   }
55 
last_chrc_discovery_start_handle()56   att::Handle last_chrc_discovery_start_handle() const {
57     return last_chrc_discovery_start_handle_;
58   }
59 
last_chrc_discovery_end_handle()60   att::Handle last_chrc_discovery_end_handle() const {
61     return last_chrc_discovery_end_handle_;
62   }
63 
last_desc_discovery_start_handle()64   att::Handle last_desc_discovery_start_handle() const {
65     return last_desc_discovery_start_handle_;
66   }
67 
last_desc_discovery_end_handle()68   att::Handle last_desc_discovery_end_handle() const {
69     return last_desc_discovery_end_handle_;
70   }
71 
chrc_discovery_count()72   size_t chrc_discovery_count() const { return chrc_discovery_count_; }
desc_discovery_count()73   size_t desc_discovery_count() const { return desc_discovery_count_; }
74 
75   // Sets a callback which will run when DiscoverServices gets called.
76   using DiscoverServicesCallback = fit::function<att::Result<>(ServiceKind)>;
set_discover_services_callback(DiscoverServicesCallback callback)77   void set_discover_services_callback(DiscoverServicesCallback callback) {
78     discover_services_callback_ = std::move(callback);
79   }
80 
81   // Sets a callback which will run when ReadRequest gets called.
82   using ReadRequestCallback = fit::function<void(att::Handle, ReadCallback)>;
set_read_request_callback(ReadRequestCallback callback)83   void set_read_request_callback(ReadRequestCallback callback) {
84     read_request_callback_ = std::move(callback);
85   }
86 
87   // Sets a callback which will run when ReadByTypeRequest gets called.
88   using ReadByTypeRequestCallback = fit::function<void(const UUID& type,
89                                                        att::Handle start_handle,
90                                                        att::Handle end_handle,
91                                                        ReadByTypeCallback)>;
set_read_by_type_request_callback(ReadByTypeRequestCallback callback)92   void set_read_by_type_request_callback(ReadByTypeRequestCallback callback) {
93     read_by_type_request_callback_ = std::move(callback);
94   }
95 
96   // Sets a callback which will run when ReadBlobRequest gets called.
97   using ReadBlobRequestCallback =
98       fit::function<void(att::Handle, uint16_t offset, ReadCallback)>;
set_read_blob_request_callback(ReadBlobRequestCallback callback)99   void set_read_blob_request_callback(ReadBlobRequestCallback callback) {
100     read_blob_request_callback_ = std::move(callback);
101   }
102 
103   // Sets a callback which will run when WriteRequest gets called.
104   using WriteRequestCallback = fit::function<void(
105       att::Handle, const ByteBuffer&, att::ResultFunction<>)>;
set_write_request_callback(WriteRequestCallback callback)106   void set_write_request_callback(WriteRequestCallback callback) {
107     write_request_callback_ = std::move(callback);
108   }
109 
110   using ExecutePrepareWritesCallback =
111       fit::function<void(att::PrepareWriteQueue prep_write_queue,
112                          ReliableMode,
113                          att::ResultFunction<>)>;
set_execute_prepare_writes_callback(ExecutePrepareWritesCallback callback)114   void set_execute_prepare_writes_callback(
115       ExecutePrepareWritesCallback callback) {
116     execute_prepare_writes_callback_ = std::move(callback);
117   }
118 
119   // Sets a callback which will run when PrepareWriteRequest gets called.
120   using PrepareWriteRequestCallback = fit::function<void(
121       att::Handle, uint16_t offset, const ByteBuffer&, PrepareCallback)>;
set_prepare_write_request_callback(PrepareWriteRequestCallback callback)122   void set_prepare_write_request_callback(
123       PrepareWriteRequestCallback callback) {
124     prepare_write_request_callback_ = std::move(callback);
125   }
126 
127   // Sets a callback which will run when ExecuteWriteRequest gets called.
128   using ExecuteWriteRequestCallback =
129       fit::function<void(att::ExecuteWriteFlag flag, att::ResultFunction<>)>;
set_execute_write_request_callback(ExecuteWriteRequestCallback callback)130   void set_execute_write_request_callback(
131       ExecuteWriteRequestCallback callback) {
132     execute_write_request_callback_ = std::move(callback);
133   }
134 
135   // Sets a callback which will run when WriteWithoutResponse gets called.
136   using WriteWithoutResponseCallback = fit::function<void(
137       att::Handle, const ByteBuffer&, att::ResultFunction<>)>;
set_write_without_rsp_callback(WriteWithoutResponseCallback callback)138   void set_write_without_rsp_callback(WriteWithoutResponseCallback callback) {
139     write_without_rsp_callback_ = std::move(callback);
140   }
141 
142   // Emulates the receipt of a notification or indication PDU.
143   void SendNotification(bool indicate,
144                         att::Handle handle,
145                         const ByteBuffer& value,
146                         bool maybe_truncated);
147 
148   // Methods to obtain a weak pointer to both FakeClient and the base class
149   // types.
GetWeakPtr()150   Client::WeakPtr GetWeakPtr() override { return weak_self_.GetWeakPtr(); }
151   using WeakPtr = WeakSelf<FakeClient>::WeakPtr;
AsFakeWeakPtr()152   FakeClient::WeakPtr AsFakeWeakPtr() { return weak_fake_.GetWeakPtr(); }
153 
154   // Client overrides:
155   uint16_t mtu() const override;
156 
157  private:
158   // Client overrides:
159   void ExchangeMTU(MTUCallback callback) override;
160   void DiscoverServices(ServiceKind kind,
161                         ServiceCallback svc_callback,
162                         att::ResultFunction<> status_callback) override;
163   void DiscoverServicesInRange(ServiceKind kind,
164                                att::Handle start,
165                                att::Handle end,
166                                ServiceCallback svc_callback,
167                                att::ResultFunction<> status_callback) override;
168   void DiscoverCharacteristics(att::Handle range_start,
169                                att::Handle range_end,
170                                CharacteristicCallback chrc_callback,
171                                att::ResultFunction<> status_callback) override;
172   void DiscoverDescriptors(att::Handle range_start,
173                            att::Handle range_end,
174                            DescriptorCallback desc_callback,
175                            att::ResultFunction<> status_callback) override;
176   void DiscoverServicesWithUuids(ServiceKind kind,
177                                  ServiceCallback svc_callback,
178                                  att::ResultFunction<> status_callback,
179                                  std::vector<UUID> uuids) override;
180   void DiscoverServicesWithUuidsInRange(ServiceKind kind,
181                                         att::Handle start,
182                                         att::Handle end,
183                                         ServiceCallback svc_callback,
184                                         att::ResultFunction<> status_callback,
185                                         std::vector<UUID> uuids) override;
186   void ReadRequest(att::Handle handle, ReadCallback callback) override;
187   void ReadByTypeRequest(const UUID& type,
188                          att::Handle start_handle,
189                          att::Handle end_handle,
190                          ReadByTypeCallback callback) override;
191   void ReadBlobRequest(att::Handle handle,
192                        uint16_t offset,
193                        ReadCallback callback) override;
194   void WriteRequest(att::Handle handle,
195                     const ByteBuffer& value,
196                     att::ResultFunction<> callback) override;
197   void ExecutePrepareWrites(att::PrepareWriteQueue prep_write_queue,
198                             ReliableMode reliable_mode,
199                             att::ResultFunction<> callback) override;
200   void PrepareWriteRequest(att::Handle handle,
201                            uint16_t offset,
202                            const ByteBuffer& part_value,
203                            PrepareCallback callback) override;
204   void ExecuteWriteRequest(att::ExecuteWriteFlag flag,
205                            att::ResultFunction<> callback) override;
206   void WriteWithoutResponse(att::Handle handle,
207                             const ByteBuffer& value,
208                             att::ResultFunction<> callback) override;
209   void SetNotificationHandler(NotificationCallback callback) override;
210 
211   // All callbacks will be posted on this dispatcher to emulate asynchronous
212   // behavior.
213   pw::async::HeapDispatcher heap_dispatcher_;
214 
215   // Value to return for MTU exchange.
216   uint16_t server_mtu_ = att::kLEMinMTU;
217 
218   // Data used for DiscoveryPrimaryServices().
219   std::vector<ServiceData> services_;
220 
221   // Fake status values to return for GATT procedures.
222   att::Result<> exchange_mtu_status_ = fit::ok();
223   att::Result<> primary_service_discovery_status_ = fit::ok();
224   att::Result<> secondary_service_discovery_status_ = fit::ok();
225   att::Result<> chrc_discovery_status_ = fit::ok();
226 
227   size_t desc_discovery_status_target_ = 0;
228   att::Result<> desc_discovery_status_ = fit::ok();
229 
230   // Data used for DiscoverCharacteristics().
231   std::vector<CharacteristicData> chrcs_;
232   att::Handle last_chrc_discovery_start_handle_ = 0;
233   att::Handle last_chrc_discovery_end_handle_ = 0;
234   size_t chrc_discovery_count_ = 0;
235 
236   // Data used for DiscoverDescriptors().
237   std::vector<DescriptorData> descs_;
238   att::Handle last_desc_discovery_start_handle_ = 0;
239   att::Handle last_desc_discovery_end_handle_ = 0;
240   size_t desc_discovery_count_ = 0;
241 
242   DiscoverServicesCallback discover_services_callback_;
243   ReadRequestCallback read_request_callback_;
244   ReadByTypeRequestCallback read_by_type_request_callback_;
245   ReadBlobRequestCallback read_blob_request_callback_;
246   WriteRequestCallback write_request_callback_;
247   ExecutePrepareWritesCallback execute_prepare_writes_callback_;
248   PrepareWriteRequestCallback prepare_write_request_callback_;
249   ExecuteWriteRequestCallback execute_write_request_callback_;
250 
251   WriteWithoutResponseCallback write_without_rsp_callback_;
252   NotificationCallback notification_callback_;
253 
254   WeakSelf<Client> weak_self_;
255   WeakSelf<FakeClient> weak_fake_;
256 
257   BT_DISALLOW_COPY_AND_ASSIGN_ALLOW_MOVE(FakeClient);
258 };
259 
260 }  // namespace bt::gatt::testing
261