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