From 3290c944e8818cc7894fe5d6456a2d3efb9a8886 Mon Sep 17 00:00:00 2001 From: Paul Szczepanek Date: Sun, 6 Jun 2021 11:25:38 +0100 Subject: [PATCH 1/8] add fake event queue for unittests --- UNITTESTS/CMakeLists.txt | 2 + UNITTESTS/fakes/CMakeLists.txt | 4 + UNITTESTS/fakes/events/CMakeLists.txt | 20 +++ UNITTESTS/fakes/events/events/EventQueue.cpp | 120 ++++++++++++++++ UNITTESTS/fakes/events/events/EventQueue.h | 137 +++++++++++++++++++ 5 files changed, 283 insertions(+) create mode 100644 UNITTESTS/fakes/CMakeLists.txt create mode 100644 UNITTESTS/fakes/events/CMakeLists.txt create mode 100644 UNITTESTS/fakes/events/events/EventQueue.cpp create mode 100644 UNITTESTS/fakes/events/events/EventQueue.h diff --git a/UNITTESTS/CMakeLists.txt b/UNITTESTS/CMakeLists.txt index bb00da96e39..469cb320a67 100644 --- a/UNITTESTS/CMakeLists.txt +++ b/UNITTESTS/CMakeLists.txt @@ -58,3 +58,5 @@ if (VALGRIND) endif(VALGRIND) add_subdirectory(stubs) +add_subdirectory(fakes) + diff --git a/UNITTESTS/fakes/CMakeLists.txt b/UNITTESTS/fakes/CMakeLists.txt new file mode 100644 index 00000000000..1e50c44a9e0 --- /dev/null +++ b/UNITTESTS/fakes/CMakeLists.txt @@ -0,0 +1,4 @@ +# Copyright (c) 2020 ARM Limited. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 + +add_subdirectory(events) diff --git a/UNITTESTS/fakes/events/CMakeLists.txt b/UNITTESTS/fakes/events/CMakeLists.txt new file mode 100644 index 00000000000..e50f30ac10f --- /dev/null +++ b/UNITTESTS/fakes/events/CMakeLists.txt @@ -0,0 +1,20 @@ +# Copyright (c) 2020 ARM Limited. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 + +add_library(mbed-fakes-event-queue) + +target_sources(mbed-fakes-event-queue + PRIVATE + events/EventQueue.cpp +) + +target_include_directories(mbed-fakes-event-queue + PUBLIC + . +) + +target_link_libraries(mbed-fakes-event-queue + PRIVATE + mbed-headers + gcov +) diff --git a/UNITTESTS/fakes/events/events/EventQueue.cpp b/UNITTESTS/fakes/events/events/EventQueue.cpp new file mode 100644 index 00000000000..4f937c240cb --- /dev/null +++ b/UNITTESTS/fakes/events/events/EventQueue.cpp @@ -0,0 +1,120 @@ +/* mbed Microcontroller Library + * Copyright (c) 2020 ARM Limited + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "EventQueue.h" + +namespace events { + +handle_t EventQueue::call_handler(function_t handler) +{ + return call_handler_in(0, handler); +} + +handle_t EventQueue::call_handler_in(tick_t ms, function_t handler) +{ + _handler_id++; + + _handlers.push_back( + internal_event{ + std::unique_ptr(new function_t(handler)), + _now + ms, + _handler_id + } + ); + + return _handler_id; +} + +bool EventQueue::cancel_handler(handle_t handle) +{ + if (!handle) { + return false; + } + + auto found = std::remove_if( + _handlers.begin(), + _handlers.end(), + [handle](internal_event& element) -> bool { + return (handle == element.handle); + } + ); + + if (found != _handlers.end()) { + _handlers.erase( + found, + _handlers.end() + ); + return true; + } + + return false; +} + +void EventQueue::process_events(tick_t duration_ms) +{ + // execute all events during the duration + for (uint64_t i = 0; i < duration_ms; ++i) { + process_events(); + _now++; + } + + // last round to execute immediate events + process_events(); +} + +void EventQueue::process_events() { + while (true) { + if (_handlers.empty()) { + return; + } + + /* to guarantee order we only dispatch one tick at a time*/ + auto smallest = std::min_element( + _handlers.begin(), + _handlers.end(), + [](internal_event& element, internal_event& smallest){ + return (element.tick < smallest.tick); + } + ); + tick_t earliest_tick = smallest->tick; + + /* stop if all elements happen later */ + if (earliest_tick > _now) { + return; + } + + /* dispatch all handlers that happen at this time */ + auto found = std::remove_if( + _handlers.begin(), + _handlers.end(), + [earliest_tick](internal_event& element) -> bool { + if (earliest_tick >= element.tick) { + (*(element.handler))(); + return true; + } else { + return false; + } + } + ); + + if (found != _handlers.end()) { + _handlers.erase(found, _handlers.end()); + } + } +} + +} diff --git a/UNITTESTS/fakes/events/events/EventQueue.h b/UNITTESTS/fakes/events/events/EventQueue.h new file mode 100644 index 00000000000..6958298654f --- /dev/null +++ b/UNITTESTS/fakes/events/events/EventQueue.h @@ -0,0 +1,137 @@ +/* mbed Microcontroller Library + * Copyright (c) 2020 ARM Limited + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef EVENTQUEUE_FAKE_H +#define EVENTQUEUE_FAKE_H + +#include +#include +#include +#include +#include +#include "events/EventQueue.h" +#include +#include + +namespace events { + +typedef int handle_t; +typedef std::function function_t; +typedef unsigned tick_t; + +class EventQueue { + using duration = std::chrono::duration; + +public: + EventQueue(unsigned size = 0, unsigned char *buffer = NULL) { delete buffer; }; + + ~EventQueue() { }; + + /** This will advence time by given amount of milliseonds and then dispatch all events that were set to happen in that time. + * + * @param ms number of miliseconds to advance time + */ + void dispatch(int milliseconds = -1) { + if (milliseconds > 0) { + process_events(milliseconds); + } else { + _now = (tick_t)-1; + process_events(); + _now = 0; + } + }; + + tick_t tick() { + return _now; + }; + + bool cancel(handle_t id) { + return cancel_handler(id); + }; + + /** Get number of events in queue. + * + * @return Number of events waiting in the queue. + */ + size_t size() const { + return _handlers.size(); + } + + template + handle_t call(F f, ArgTs... args) { + return call_handler( + [f, args = mstd::make_tuple(args...)]() { + mstd::apply(f, args); + } + ); + } + + template + handle_t call_in(duration ms, F f, ArgTs... args) { + return call_handler_in( + ms.count(), + [f, args = mstd::make_tuple(args...)]() { + mstd::apply(f, args); + } + ); + } + + template + int call(T *obj, R(T::*method)(ArgTs...), ArgTs... args) { + return call_handler( + [obj, method, args = mstd::make_tuple(args...)]() { + mstd::apply(method, obj, args); + } + ); + } + + template + int call_in(duration ms, T *obj, R(T::*method)(ArgTs...), ArgTs... args) { + return call_handler_in( + ms.count(), + [obj, method, args = mstd::make_tuple(args...)]() { + mstd::apply(method, obj, args); + } + ); + } + +private: + handle_t call_handler(function_t handler); + + handle_t call_handler_in(tick_t ms, function_t handler); + + bool cancel_handler(handle_t handle); + + void process_events(tick_t duration_ms); + + void process_events(); + +private: + struct internal_event { + std::unique_ptr handler; + tick_t tick; + handle_t handle; + }; + + std::vector _handlers; + tick_t _now = 0; + handle_t _handler_id = 0; +}; + +} + +#endif //EVENTQUEUE_FAKE_H From 2975c7cfe900998e8c7663dc57f5631e298626b0 Mon Sep 17 00:00:00 2001 From: Paul Szczepanek Date: Sun, 6 Jun 2021 11:26:09 +0100 Subject: [PATCH 2/8] add fake googlemock BLE API for unittests --- UNITTESTS/fakes/CMakeLists.txt | 1 + UNITTESTS/fakes/ble/BLE.cpp | 163 +++++++++ UNITTESTS/fakes/ble/CMakeLists.txt | 41 +++ UNITTESTS/fakes/ble/GapImpl_mock.h | 91 +++++ UNITTESTS/fakes/ble/GattClientImpl_mock.h | 62 ++++ UNITTESTS/fakes/ble/GattServerImpl_mock.h | 105 ++++++ .../fakes/ble/SecurityManagerImpl_mock.h | 73 ++++ UNITTESTS/fakes/ble/ble_mocks.h | 45 +++ UNITTESTS/fakes/ble/source/GattServerImpl.h | 137 ++++++++ .../fakes/ble/source/GattServerImpl_mock.cpp | 96 ++++++ UNITTESTS/fakes/ble/source/generic/GapImpl.h | 317 ++++++++++++++++++ .../fakes/ble/source/generic/GattClientImpl.h | 133 ++++++++ .../ble/source/generic/SecurityManagerImpl.h | 186 ++++++++++ 13 files changed, 1450 insertions(+) create mode 100644 UNITTESTS/fakes/ble/BLE.cpp create mode 100644 UNITTESTS/fakes/ble/CMakeLists.txt create mode 100644 UNITTESTS/fakes/ble/GapImpl_mock.h create mode 100644 UNITTESTS/fakes/ble/GattClientImpl_mock.h create mode 100644 UNITTESTS/fakes/ble/GattServerImpl_mock.h create mode 100644 UNITTESTS/fakes/ble/SecurityManagerImpl_mock.h create mode 100644 UNITTESTS/fakes/ble/ble_mocks.h create mode 100644 UNITTESTS/fakes/ble/source/GattServerImpl.h create mode 100644 UNITTESTS/fakes/ble/source/GattServerImpl_mock.cpp create mode 100644 UNITTESTS/fakes/ble/source/generic/GapImpl.h create mode 100644 UNITTESTS/fakes/ble/source/generic/GattClientImpl.h create mode 100644 UNITTESTS/fakes/ble/source/generic/SecurityManagerImpl.h diff --git a/UNITTESTS/fakes/CMakeLists.txt b/UNITTESTS/fakes/CMakeLists.txt index 1e50c44a9e0..538093dd785 100644 --- a/UNITTESTS/fakes/CMakeLists.txt +++ b/UNITTESTS/fakes/CMakeLists.txt @@ -2,3 +2,4 @@ # SPDX-License-Identifier: Apache-2.0 add_subdirectory(events) +add_subdirectory(ble) diff --git a/UNITTESTS/fakes/ble/BLE.cpp b/UNITTESTS/fakes/ble/BLE.cpp new file mode 100644 index 00000000000..337558ed57c --- /dev/null +++ b/UNITTESTS/fakes/ble/BLE.cpp @@ -0,0 +1,163 @@ +/* mbed Microcontroller Library + * Copyright (c) 2020 ARM Limited + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ble/BLE.h" +#include "GattServerImpl_mock.h" +#include "GattClientImpl_mock.h" +#include "GapImpl_mock.h" +#include "SecurityManagerImpl_mock.h" +#include "ble/GattClient.h" +#include "ble/GattServer.h" +#include "ble/SecurityManager.h" +#include "ble/Gap.h" +#include "ble_mocks.h" + +namespace ble { + +static GapMock *gap_impl = nullptr; +static GattServerMock *gatt_server_impl = nullptr; +static GattClientMock *gatt_client_impl = nullptr; +static SecurityManagerMock *security_manager_impl = nullptr; + +static Gap *gap = nullptr; +static GattServer *gatt_server = nullptr; +static GattClient *gatt_client = nullptr; +static SecurityManager *security_manager = nullptr; + +GapMock& gap_mock() { + return *ble::gap_impl; +} + +GattServerMock& gatt_server_mock() { + return *ble::gatt_server_impl; +} + +GattClientMock& gatt_client_mock() { + return *ble::gatt_client_impl; +} + +SecurityManagerMock& security_manager_mock() { + return *ble::security_manager_impl; +} + +void init_mocks() { + if (gap_impl) { + /* we are already initialised */ + return; + } + + /* mocks */ + gap_impl = new GapMock(); + gatt_server_impl = new GattServerMock(); + gatt_client_impl = new GattClientMock(); + security_manager_impl = new SecurityManagerMock(); + /* user APIS */ + gap = new Gap(gap_impl); + gatt_server = new GattServer(gatt_server_impl); + gatt_client = new GattClient(gatt_client_impl); + security_manager = new SecurityManager(security_manager_impl); +} + +void delete_mocks() { + delete gap; + delete gap_impl; + delete gatt_server; + delete gatt_server_impl; + delete gatt_client; + delete gatt_client_impl; + delete security_manager; + delete security_manager_impl; + + gap = nullptr; + gap_impl = nullptr; + gatt_server = nullptr; + gatt_server_impl = nullptr; + gatt_client = nullptr; + gatt_client_impl = nullptr; + security_manager = nullptr; + security_manager_impl = nullptr; +} + +class BLEInstanceBase { +}; + +BLE::BLE(ble::BLEInstanceBase &transport) : transport(transport) +{ +} + +BLE& BLE::Instance() +{ + static ble::BLEInstanceBase transport; + static BLE instance(transport); + init_mocks(); + return instance; +} + +ble::Gap &BLE::gap() +{ + init_mocks(); + return *ble::gap; +} + +ble::GattServer &BLE::gattServer() +{ + init_mocks(); + return *ble::gatt_server; +} + +ble::GattClient &BLE::gattClient() +{ + init_mocks(); + return *ble::gatt_client; +} + +ble::SecurityManager &BLE::securityManager() +{ + init_mocks(); + return *ble::security_manager; +} + +const ble::Gap &BLE::gap() const +{ + auto &self = const_cast(*this); + return const_cast(self.gap()); +} + +const ble::GattServer &BLE::gattServer() const +{ + auto &self = const_cast(*this); + return const_cast(self.gattServer()); +} + +const ble::GattClient &BLE::gattClient() const +{ + auto &self = const_cast(*this); + return const_cast(self.gattClient()); +} + +const ble::SecurityManager &BLE::securityManager() const +{ + auto &self = const_cast(*this); + return const_cast(self.securityManager()); +} + +void BLE::processEvents() +{ + +} + +} \ No newline at end of file diff --git a/UNITTESTS/fakes/ble/CMakeLists.txt b/UNITTESTS/fakes/ble/CMakeLists.txt new file mode 100644 index 00000000000..c8fb84935de --- /dev/null +++ b/UNITTESTS/fakes/ble/CMakeLists.txt @@ -0,0 +1,41 @@ +# Copyright (c) 2020 ARM Limited. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 + +add_library(mbed-fakes-ble) + +target_include_directories(mbed-fakes-ble + PUBLIC + ${mbed-os_SOURCE_DIR}/UNITTESTS/fakes/ble/ + ${mbed-os_SOURCE_DIR}/connectivity/FEATURE_BLE/include + ${mbed-os_SOURCE_DIR}/connectivity/FEATURE_BLE/include/ble + ${mbed-os_SOURCE_DIR}/connectivity/FEATURE_BLE/source + PRIVATE + ${gtest_SOURCE_DIR}/include + ${gmock_SOURCE_DIR}/include +) + +target_sources(mbed-fakes-ble + PRIVATE + ${mbed-os_SOURCE_DIR}/connectivity/FEATURE_BLE/source/gap/AdvertisingDataBuilder.cpp + ${mbed-os_SOURCE_DIR}/connectivity/FEATURE_BLE/source/gap/AdvertisingParameters.cpp + ${mbed-os_SOURCE_DIR}/connectivity/FEATURE_BLE/source/gap/ConnectionParameters.cpp + ${mbed-os_SOURCE_DIR}/connectivity/FEATURE_BLE/source/gatt/DiscoveredCharacteristic.cpp + ${mbed-os_SOURCE_DIR}/connectivity/FEATURE_BLE/source/Gap.cpp + ${mbed-os_SOURCE_DIR}/connectivity/FEATURE_BLE/source/GattClient.cpp + ${mbed-os_SOURCE_DIR}/connectivity/FEATURE_BLE/source/GattServer.cpp + ${mbed-os_SOURCE_DIR}/connectivity/FEATURE_BLE/source/SecurityManager.cpp + ${mbed-os_SOURCE_DIR}/UNITTESTS/fakes/ble/BLE.cpp + ${mbed-os_SOURCE_DIR}/UNITTESTS/fakes/ble/source/GattServerImpl_mock.cpp + ${mbed-os_SOURCE_DIR}/UNITTESTS/fakes/ble/ble_mocks.h + ${mbed-os_SOURCE_DIR}/UNITTESTS/fakes/ble/GapImpl_mock.h + ${mbed-os_SOURCE_DIR}/UNITTESTS/fakes/ble/GattClientImpl_mock.h + ${mbed-os_SOURCE_DIR}/UNITTESTS/fakes/ble/GattServerImpl_mock.h + ${mbed-os_SOURCE_DIR}/UNITTESTS/fakes/ble/SecurityManagerImpl_mock.h +) + +target_link_libraries(mbed-fakes-ble + PRIVATE + mbed-headers + mbed-stubs-headers + gcov +) diff --git a/UNITTESTS/fakes/ble/GapImpl_mock.h b/UNITTESTS/fakes/ble/GapImpl_mock.h new file mode 100644 index 00000000000..b59461da140 --- /dev/null +++ b/UNITTESTS/fakes/ble/GapImpl_mock.h @@ -0,0 +1,91 @@ +/* mbed Microcontroller Library + * Copyright (c) 2020 ARM Limited + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef BLE_GAPMOCK_H +#define BLE_GAPMOCK_H + +#include "gmock/gmock.h" +#include "source/generic/GapImpl.h" + +namespace ble { + +class GapMock : public ble::impl::Gap { +public: + GapMock() {}; + GapMock(const GapMock&) = delete; + GapMock& operator=(const GapMock&) = delete; + virtual ~GapMock() {}; + + MOCK_METHOD((ble_error_t), reset, (), (override)); + MOCK_METHOD(void, setEventHandler, (EventHandler *handler), (override)); + MOCK_METHOD(bool, isFeatureSupported, (controller_supported_features_t feature), (override)); + MOCK_METHOD(uint8_t, getMaxAdvertisingSetNumber, (), (override)); + MOCK_METHOD(uint16_t, getMaxAdvertisingDataLength, (), (override)); + MOCK_METHOD(uint16_t, getMaxConnectableAdvertisingDataLength, (), (override)); + MOCK_METHOD(uint16_t, getMaxActiveSetAdvertisingDataLength, (), (override)); + MOCK_METHOD(ble_error_t, createAdvertisingSet, (advertising_handle_t *handle, const AdvertisingParameters ¶meters), (override)); + MOCK_METHOD(ble_error_t, destroyAdvertisingSet, (advertising_handle_t handle), (override)); + MOCK_METHOD(ble_error_t, setAdvertisingParameters, (advertising_handle_t handle, const AdvertisingParameters ¶ms), (override)); + MOCK_METHOD(ble_error_t, setAdvertisingPayload, (advertising_handle_t handle, mbed::Span payload), (override)); + MOCK_METHOD(ble_error_t, setAdvertisingScanResponse, (advertising_handle_t handle, mbed::Span response), (override)); + MOCK_METHOD(ble_error_t, startAdvertising, (advertising_handle_t handle, adv_duration_t maxDuration, uint8_t maxEvents), (override)); + MOCK_METHOD(ble_error_t, stopAdvertising, (advertising_handle_t handle), (override)); + MOCK_METHOD(bool, isAdvertisingActive, (advertising_handle_t handle), (override)); + MOCK_METHOD(ble_error_t, setPeriodicAdvertisingParameters, (advertising_handle_t handle, periodic_interval_t periodicAdvertisingIntervalMin, periodic_interval_t periodicAdvertisingIntervalMax, bool advertiseTxPower), (override)); + MOCK_METHOD(ble_error_t, setPeriodicAdvertisingPayload, (advertising_handle_t handle, mbed::Span payload), (override)); + MOCK_METHOD(ble_error_t, startPeriodicAdvertising, (advertising_handle_t handle), (override)); + MOCK_METHOD(ble_error_t, stopPeriodicAdvertising, (advertising_handle_t handle), (override)); + MOCK_METHOD(bool, isPeriodicAdvertisingActive, (advertising_handle_t handle), (override)); + MOCK_METHOD(ble_error_t, setScanParameters, (const ScanParameters ¶ms), (override)); + MOCK_METHOD(ble_error_t, startScan, (scan_duration_t duration, duplicates_filter_t filtering, scan_period_t period), (override)); + MOCK_METHOD(ble_error_t, initiate_scan, (), (override)); + MOCK_METHOD(ble_error_t, stopScan, (), (override)); + MOCK_METHOD(ble_error_t, createSync, (peer_address_type_t peerAddressType, const address_t &peerAddress, uint8_t sid, slave_latency_t maxPacketSkip, sync_timeout_t timeout), (override)); + MOCK_METHOD(ble_error_t, createSync, (slave_latency_t maxPacketSkip, sync_timeout_t timeout), (override)); + MOCK_METHOD(ble_error_t, cancelCreateSync, (), (override)); + MOCK_METHOD(ble_error_t, terminateSync, (periodic_sync_handle_t handle), (override)); + MOCK_METHOD(ble_error_t, addDeviceToPeriodicAdvertiserList, (peer_address_type_t peerAddressType, const address_t &peerAddress, advertising_sid_t sid), (override)); + MOCK_METHOD(ble_error_t, removeDeviceFromPeriodicAdvertiserList, (peer_address_type_t peerAddressType, const address_t &peerAddress, advertising_sid_t sid), (override)); + MOCK_METHOD(ble_error_t, clearPeriodicAdvertiserList, (), (override)); + MOCK_METHOD(ble_error_t, connect, (peer_address_type_t peerAddressType, const address_t &peerAddress, const ConnectionParameters &connectionParams), (override)); + MOCK_METHOD(ble_error_t, cancelConnect, (), (override)); + MOCK_METHOD(ble_error_t, updateConnectionParameters, (connection_handle_t connectionHandle, conn_interval_t minConnectionInterval, conn_interval_t maxConnectionInterval, slave_latency_t slaveLatency, supervision_timeout_t supervision_timeout, conn_event_length_t minConnectionEventLength, conn_event_length_t maxConnectionEventLength), (override)); + MOCK_METHOD(ble_error_t, manageConnectionParametersUpdateRequest, (bool userManageConnectionUpdateRequest), (override)); + MOCK_METHOD(ble_error_t, acceptConnectionParametersUpdate, (connection_handle_t connectionHandle, conn_interval_t minConnectionInterval, conn_interval_t maxConnectionInterval, slave_latency_t slaveLatency, supervision_timeout_t supervision_timeout, conn_event_length_t minConnectionEventLength, conn_event_length_t maxConnectionEventLength), (override)); + MOCK_METHOD(ble_error_t, rejectConnectionParametersUpdate, (connection_handle_t connectionHandle), (override)); + MOCK_METHOD(ble_error_t, disconnect, (connection_handle_t connectionHandle, local_disconnection_reason_t reason), (override)); + MOCK_METHOD(ble_error_t, readPhy, (connection_handle_t connection), (override)); + MOCK_METHOD(ble_error_t, setPreferredPhys, (const phy_set_t *txPhys, const phy_set_t *rxPhys), (override)); + MOCK_METHOD(ble_error_t, setPhy, (connection_handle_t connection, const phy_set_t *txPhys, const phy_set_t *rxPhys, coded_symbol_per_bit_t codedSymbol), (override)); + MOCK_METHOD(ble_error_t, enablePrivacy, (bool enable), (override)); + MOCK_METHOD(ble_error_t, setPeripheralPrivacyConfiguration, (const peripheral_privacy_configuration_t *configuration), (override)); + MOCK_METHOD(ble_error_t, getPeripheralPrivacyConfiguration, (peripheral_privacy_configuration_t *configuration), (override)); + MOCK_METHOD(ble_error_t, setCentralPrivacyConfiguration, (const central_privacy_configuration_t *configuration), (override)); + MOCK_METHOD(ble_error_t, getCentralPrivacyConfiguration, (central_privacy_configuration_t *configuration), (override)); + MOCK_METHOD(uint8_t, getMaxWhitelistSize, (), (const, override)); + MOCK_METHOD(ble_error_t, getWhitelist, (whitelist_t &whitelist), (const, override)); + MOCK_METHOD(ble_error_t, setWhitelist, (const whitelist_t &whitelist), (override)); + MOCK_METHOD(ble_error_t, getAddress, (own_address_type_t &typeP, address_t &address), (override)); + MOCK_METHOD(void, onShutdown, (const GapShutdownCallback_t &callback), (override)); + MOCK_METHOD(GapShutdownCallbackChain_t&, onShutdown, (), (override)); + MOCK_METHOD(ble_error_t, setRandomStaticAddress, (const ble::address_t &address), (override)); + MOCK_METHOD(ble::address_t, getRandomStaticAddress, (), (override)); +}; + +} + +#endif //BLE_GAPMOCK_H diff --git a/UNITTESTS/fakes/ble/GattClientImpl_mock.h b/UNITTESTS/fakes/ble/GattClientImpl_mock.h new file mode 100644 index 00000000000..6150ad1697e --- /dev/null +++ b/UNITTESTS/fakes/ble/GattClientImpl_mock.h @@ -0,0 +1,62 @@ +/* mbed Microcontroller Library + * Copyright (c) 2020 ARM Limited + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef BLE_GATTCLIENTMOCK_H +#define BLE_GATTCLIENTMOCK_H + +#include "gmock/gmock.h" +#include "source/generic/GattClientImpl.h" + +namespace ble { + +class GattClientMock : public ble::impl::GattClient { +public: + GattClientMock() {}; + GattClientMock(const GattClientMock&) = delete; + GattClientMock& operator=(const GattClientMock&) = delete; + virtual ~GattClientMock() {}; + + MOCK_METHOD(ble_error_t, reset, (), (override)); + MOCK_METHOD(void, setEventHandler, (EventHandler *handler), (override)); + MOCK_METHOD(ble_error_t, launchServiceDiscovery, (ble::connection_handle_t connectionHandle, ServiceDiscovery::ServiceCallback_t sc, ServiceDiscovery::CharacteristicCallback_t cc, const UUID &matchingServiceUUID, const UUID &matchingCharacteristicUUIDIn), (override)); + MOCK_METHOD(ble_error_t, discoverServices, (ble::connection_handle_t connectionHandle, ServiceDiscovery::ServiceCallback_t callback, const UUID &matchingServiceUUID), (override)); + MOCK_METHOD(ble_error_t, discoverServices, (ble::connection_handle_t connectionHandle, ServiceDiscovery::ServiceCallback_t callback, GattAttribute::Handle_t startHandle, GattAttribute::Handle_t endHandle), (override)); + MOCK_METHOD(bool, isServiceDiscoveryActive, (), (const, override)); + MOCK_METHOD(void, terminateServiceDiscovery, (), (override)); + MOCK_METHOD(ble_error_t, read, (ble::connection_handle_t connHandle, GattAttribute::Handle_t attributeHandle, uint16_t offset), (const, override)); + MOCK_METHOD(ble_error_t, write, (GattClient::WriteOp_t cmd, ble::connection_handle_t connHandle, GattAttribute::Handle_t attributeHandle, size_t length, const uint8_t *value), (const, override)); + MOCK_METHOD(void, onDataRead, (ReadCallback_t callback), (override)); + MOCK_METHOD(ReadCallbackChain_t&, onDataRead, (), (override)); + MOCK_METHOD(void, onDataWritten, (WriteCallback_t callback), (override)); + MOCK_METHOD(WriteCallbackChain_t&, onDataWritten, (), (override)); + MOCK_METHOD(void, onServiceDiscoveryTermination, (ServiceDiscovery::TerminationCallback_t callback), (override)); + MOCK_METHOD(ble_error_t, discoverCharacteristicDescriptors, (const DiscoveredCharacteristic &characteristic, const CharacteristicDescriptorDiscovery::DiscoveryCallback_t &discoveryCallback, const CharacteristicDescriptorDiscovery::TerminationCallback_t &terminationCallback), (override)); + MOCK_METHOD(bool, isCharacteristicDescriptorDiscoveryActive, (const DiscoveredCharacteristic &characteristic), (const, override)); + MOCK_METHOD(void, terminateCharacteristicDescriptorDiscovery, (const DiscoveredCharacteristic &characteristic), (override)); + MOCK_METHOD(ble_error_t, negotiateAttMtu, (ble::connection_handle_t connection), (override)); + MOCK_METHOD(void, onHVX, (HVXCallback_t callback), (override)); + MOCK_METHOD(void, onShutdown, (const GattClientShutdownCallback_t &callback), (override)); + MOCK_METHOD(GattClientShutdownCallbackChain_t&, onShutdown, (), (override)); + MOCK_METHOD(HVXCallbackChain_t&, onHVX, (), (override)); + MOCK_METHOD(void, processReadResponse, (const GattReadCallbackParams *params), (override)); + MOCK_METHOD(void, processWriteResponse, (const GattWriteCallbackParams *params), (override)); + MOCK_METHOD(void, processHVXEvent, (const GattHVXCallbackParams *params), (override)); +}; + +} + +#endif //BLE_GATTCLIENTMOCK_H diff --git a/UNITTESTS/fakes/ble/GattServerImpl_mock.h b/UNITTESTS/fakes/ble/GattServerImpl_mock.h new file mode 100644 index 00000000000..bfafb524005 --- /dev/null +++ b/UNITTESTS/fakes/ble/GattServerImpl_mock.h @@ -0,0 +1,105 @@ +/* mbed Microcontroller Library + * Copyright (c) 2020 ARM Limited + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef BLE_GATTSERVERMOCK_H +#define BLE_GATTSERVERMOCK_H + +#include "gmock/gmock.h" +#include "source/GattServerImpl.h" + +namespace ble { + +class GattServerMock : public ble::impl::GattServer { +public: + GattServerMock(); + GattServerMock(const GattServerMock&) = delete; + GattServerMock& operator=(const GattServerMock&) = delete; + virtual ~GattServerMock(); + + MOCK_METHOD(ble_error_t, reset, (ble::GattServer* server), (override)); + MOCK_METHOD(void, setEventHandler, (EventHandler *handler), (override)); + MOCK_METHOD(ble_error_t, addService, (GattService &service), (override)); + MOCK_METHOD(ble_error_t, read, (GattAttribute::Handle_t attributeHandle, uint8_t buffer[], uint16_t *lengthP), (override)); + MOCK_METHOD(ble_error_t, read, (ble::connection_handle_t connectionHandle, GattAttribute::Handle_t attributeHandle, uint8_t *buffer, uint16_t *lengthP), (override)); + MOCK_METHOD(ble_error_t, write, (GattAttribute::Handle_t attributeHandle, const uint8_t *value, uint16_t size, bool localOnly), (override)); + MOCK_METHOD(ble_error_t, write, (ble::connection_handle_t connectionHandle, GattAttribute::Handle_t attributeHandle, const uint8_t *value, uint16_t size, bool localOnly), (override)); + MOCK_METHOD(ble_error_t, areUpdatesEnabled, (const GattCharacteristic &characteristic, bool *enabledP), (override)); + MOCK_METHOD(ble_error_t, areUpdatesEnabled, (ble::connection_handle_t connectionHandle, const GattCharacteristic &characteristic, bool *enabledP), (override)); + MOCK_METHOD(ble::Gap::PreferredConnectionParams_t, getPreferredConnectionParams, (), (override)); + MOCK_METHOD(void, setPreferredConnectionParams, (const ble::Gap::PreferredConnectionParams_t ¶ms), (override)); + MOCK_METHOD(bool, isOnDataReadAvailable, (), (const, override)); + MOCK_METHOD(void, onDataSent, (const DataSentCallback_t &callback), (override)); + MOCK_METHOD(DataSentCallbackChain_t&, onDataSent, (), (override)); + MOCK_METHOD(void, onDataWritten, (const DataWrittenCallback_t &callback), (override)); + MOCK_METHOD(DataWrittenCallbackChain_t&, onDataWritten, (), (override)); + MOCK_METHOD(ble_error_t, onDataRead, (const DataReadCallback_t &callback), (override)); + MOCK_METHOD(DataReadCallbackChain_t&, onDataRead, (), (override)); + MOCK_METHOD(void, onShutdown, (const GattServerShutdownCallback_t &callback), (override)); + MOCK_METHOD(GattServerShutdownCallbackChain_t&, onShutdown, (), (override)); + MOCK_METHOD(void, onUpdatesEnabled, (EventCallback_t callback), (override)); + MOCK_METHOD(void, onUpdatesDisabled, (EventCallback_t callback), (override)); + MOCK_METHOD(void, onConfirmationReceived, (EventCallback_t callback), (override)); + MOCK_METHOD(void, handleDataWrittenEvent, (const GattWriteCallbackParams *params), (override)); + MOCK_METHOD(void, handleDataReadEvent, (const GattReadCallbackParams *params), (override)); + MOCK_METHOD(void, handleEvent, (GattServerEvents::gattEvent_e type, ble::connection_handle_t connHandle, GattAttribute::Handle_t attributeHandle), (override)); + MOCK_METHOD(void, handleDataSentEvent, (unsigned count), (override)); + + // Fake part + // Descriptor representation of a descriptor registered with ble::test::register_services + struct descriptor_t { + UUID uuid; + ble::attribute_handle_t handle; + ble::att_security_requirement_t read_security = ble::att_security_requirement_t::NONE; + ble::att_security_requirement_t write_security = ble::att_security_requirement_t::NONE; + bool is_readable; + bool is_writable; + std::vector value; // Use capacity to determine the max size. + }; + + // Characteristic representation of a characteristic registered with ble::test::register_services + struct characteristic_t { + UUID uuid; + ble::attribute_handle_t value_handle; + uint8_t properties; + ble::att_security_requirement_t read_security = ble::att_security_requirement_t::NONE; + ble::att_security_requirement_t write_security = ble::att_security_requirement_t::NONE; + ble::att_security_requirement_t update_security = ble::att_security_requirement_t::NONE; + FunctionPointerWithContext + read_cb; + FunctionPointerWithContext + write_cb; + bool has_variable_len; + std::vector value; // Use capacity to determine the max size. + std::vector descriptors; + }; + + // Service representation of a service registered with ble::test::register_services + struct service_t { + UUID uuid; + ble::attribute_handle_t handle; + std::vector characteristics; + }; + + void fake_register_services(GattService& gattService); + + std::vector services; + ble::attribute_handle_t current_handle = 1; +}; + +} + +#endif //BLE_GATTSERVERMOCK_H diff --git a/UNITTESTS/fakes/ble/SecurityManagerImpl_mock.h b/UNITTESTS/fakes/ble/SecurityManagerImpl_mock.h new file mode 100644 index 00000000000..3f1007e4fa5 --- /dev/null +++ b/UNITTESTS/fakes/ble/SecurityManagerImpl_mock.h @@ -0,0 +1,73 @@ +/* mbed Microcontroller Library + * Copyright (c) 2020 ARM Limited + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef SECURITYMANAGERMOCK_H +#define SECURITYMANAGERMOCK_H + +#include "gmock/gmock.h" +#include "source/generic/SecurityManagerImpl.h" + +namespace ble { + +class SecurityManagerMock : public ble::impl::SecurityManager { +public: + SecurityManagerMock() {}; + SecurityManagerMock(const GattServerMock&) = delete; + SecurityManagerMock& operator=(const GattServerMock&) = delete; + virtual ~SecurityManagerMock() {}; + + MOCK_METHOD(ble_error_t, reset, (), (override)); + MOCK_METHOD(ble_error_t, init, (bool enableBonding, bool requireMITM, SecurityIOCapabilities_t iocaps, const Passkey_t passkey, bool signing, const char *dbFilepath), (override)); + MOCK_METHOD(ble_error_t, setDatabaseFilepath, (const char *dbFilepath), (override)); + MOCK_METHOD(ble_error_t, preserveBondingStateOnReset, (bool enable), (override)); + MOCK_METHOD(ble_error_t, purgeAllBondingState, (), (override)); + MOCK_METHOD(ble_error_t, generateWhitelistFromBondTable, (::ble::whitelist_t *whitelist), (const, override)); + MOCK_METHOD(ble_error_t, requestPairing, (ble::connection_handle_t connectionHandle), (override)); + MOCK_METHOD(ble_error_t, acceptPairingRequest, (ble::connection_handle_t connectionHandle), (override)); + MOCK_METHOD(ble_error_t, cancelPairingRequest, (ble::connection_handle_t connectionHandle), (override)); + MOCK_METHOD(ble_error_t, setPairingRequestAuthorisation, (bool required), (override)); + MOCK_METHOD(ble_error_t, getPeerIdentity, (ble::connection_handle_t connectionHandle), (override)); + MOCK_METHOD(ble_error_t, allowLegacyPairing, (bool allow), (override)); + MOCK_METHOD(ble_error_t, getSecureConnectionsSupport, (bool *enabled), (override)); + MOCK_METHOD(ble_error_t, setIoCapability, (SecurityIOCapabilities_t iocaps), (override)); + MOCK_METHOD(ble_error_t, setDisplayPasskey, (const Passkey_t passkey), (override)); + MOCK_METHOD(ble_error_t, setLinkSecurity, (ble::connection_handle_t connectionHandle, SecurityMode_t securityMode), (override)); + MOCK_METHOD(ble_error_t, setKeypressNotification, (bool enabled), (override)); + MOCK_METHOD(ble_error_t, enableSigning, (ble::connection_handle_t connectionHandle, bool enabled), (override)); + MOCK_METHOD(ble_error_t, setHintFutureRoleReversal, (bool enable), (override)); + MOCK_METHOD(ble_error_t, getLinkEncryption, (ble::connection_handle_t connectionHandle, ble::link_encryption_t *encryption), (override)); + MOCK_METHOD(ble_error_t, setLinkEncryption, (ble::connection_handle_t connectionHandle, ble::link_encryption_t encryption), (override)); + MOCK_METHOD(ble_error_t, setEncryptionKeyRequirements, (uint8_t minimumByteSize, uint8_t maximumByteSize), (override)); + MOCK_METHOD(ble_error_t, getEncryptionKeySize, (connection_handle_t connectionHandle, uint8_t *size), (override)); + MOCK_METHOD(ble_error_t, requestAuthentication, (ble::connection_handle_t connectionHandle), (override)); + MOCK_METHOD(ble_error_t, generateOOB, (const ble::address_t *address), (override)); + MOCK_METHOD(ble_error_t, setOOBDataUsage, (ble::connection_handle_t connectionHandle, bool useOOB, bool OOBProvidesMITM), (override)); + MOCK_METHOD(ble_error_t, passkeyEntered, (ble::connection_handle_t connectionHandle, Passkey_t passkey), (override)); + MOCK_METHOD(ble_error_t, legacyPairingOobReceived, (const ble::address_t *address, const ble::oob_tk_t *tk), (override)); + MOCK_METHOD(ble_error_t, confirmationEntered, (ble::connection_handle_t connectionHandle, bool confirmation), (override)); + MOCK_METHOD(ble_error_t, sendKeypressNotification, (ble::connection_handle_t connectionHandle, ble::Keypress_t keypress), (override)); + MOCK_METHOD(ble_error_t, oobReceived, (const ble::address_t *address, const ble::oob_lesc_value_t *random, const ble::oob_confirm_t *confirm), (override)); + MOCK_METHOD(ble_error_t, getSigningKey, (ble::connection_handle_t connectionHandle, bool authenticated), (override)); + MOCK_METHOD(ble_error_t, setPrivateAddressTimeout, (uint16_t timeout_in_seconds), (override)); + MOCK_METHOD(void, onShutdown, (const SecurityManagerShutdownCallback_t &callback), (override)); + MOCK_METHOD(SecurityManagerShutdownCallbackChain_t&, onShutdown, (), (override)); + MOCK_METHOD(void, setSecurityManagerEventHandler, (EventHandler *handler), (override)); +}; + +} + +#endif //SECURITYMANAGERMOCK_H diff --git a/UNITTESTS/fakes/ble/ble_mocks.h b/UNITTESTS/fakes/ble/ble_mocks.h new file mode 100644 index 00000000000..efeac598c14 --- /dev/null +++ b/UNITTESTS/fakes/ble/ble_mocks.h @@ -0,0 +1,45 @@ +/* mbed Microcontroller Library + * Copyright (c) 2020 ARM Limited + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef BLE_MOCKS_H +#define BLE_MOCKS_H + +#include "GattServerImpl_mock.h" +#include "GattClientImpl_mock.h" +#include "GapImpl_mock.h" +#include "SecurityManagerImpl_mock.h" + +/*** + * You must use delete_mocks() at the end of the test. BLE::Instance(), ble::gap() etc. inits the mocks. Do not cache + * pointers between tests. Call BLE::Instance() at the start of the tests, otherwise call init_mocks() yourself. + * To access mocks use: + * gap_mock(), gatt_server_mock(), gatt_client_mock(), security_manager_mock(). + * All functions are in namespace ble. + */ +namespace ble { + +void init_mocks(); +void delete_mocks(); + +GapMock& gap_mock(); +GattServerMock& gatt_server_mock(); +GattClientMock& gatt_client_mock(); +SecurityManagerMock& security_manager_mock(); + +} + +#endif // BLE_MOCKS_H \ No newline at end of file diff --git a/UNITTESTS/fakes/ble/source/GattServerImpl.h b/UNITTESTS/fakes/ble/source/GattServerImpl.h new file mode 100644 index 00000000000..d4b43490d37 --- /dev/null +++ b/UNITTESTS/fakes/ble/source/GattServerImpl.h @@ -0,0 +1,137 @@ +/* mbed Microcontroller Library + * Copyright (c) 2020 ARM Limited + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef BLE_GATTSERVERSTUB_H +#define BLE_GATTSERVERSTUB_H + +#include "ble/GattServer.h" +#include "generic/GattServerEvents.h" +#include "ble/Gap.h" + +namespace ble { +namespace impl { + +class GattServer { +public: + GattServer() {}; + GattServer(const GattServer&) = delete; + GattServer& operator=(const GattServer&) = delete; + virtual ~GattServer() {}; + + using EventHandler = ble::GattServer::EventHandler; + using DataSentCallback_t = ble::GattServer::DataSentCallback_t ; + using DataSentCallbackChain_t = ble::GattServer::DataSentCallbackChain_t ; + using DataWrittenCallback_t = ble::GattServer::DataWrittenCallback_t ; + using DataWrittenCallbackChain_t = ble::GattServer::DataWrittenCallbackChain_t ; + using DataReadCallback_t = ble::GattServer::DataReadCallback_t; + using DataReadCallbackChain_t = ble::GattServer::DataReadCallbackChain_t; + using GattServerShutdownCallback_t = ble::GattServer::GattServerShutdownCallback_t; + using GattServerShutdownCallbackChain_t = ble::GattServer::GattServerShutdownCallbackChain_t; + using EventCallback_t = ble::GattServer::EventCallback_t; + + virtual void setEventHandler(EventHandler *handler) { }; + + virtual ble_error_t reset(ble::GattServer* server) { return BLE_ERROR_NONE; }; + + virtual ble_error_t addService(GattService &service) { return BLE_ERROR_NONE; }; + + virtual ble_error_t read( + GattAttribute::Handle_t attributeHandle, + uint8_t buffer[], + uint16_t *lengthP + ) { return BLE_ERROR_NONE; }; + + virtual ble_error_t read( + ble::connection_handle_t connectionHandle, + GattAttribute::Handle_t attributeHandle, + uint8_t *buffer, + uint16_t *lengthP + ) { return BLE_ERROR_NONE; }; + + virtual ble_error_t write( + GattAttribute::Handle_t attributeHandle, + const uint8_t *value, + uint16_t size, + bool localOnly = false + ) { return BLE_ERROR_NONE; }; + + virtual ble_error_t write( + ble::connection_handle_t connectionHandle, + GattAttribute::Handle_t attributeHandle, + const uint8_t *value, + uint16_t size, + bool localOnly = false + ) { return BLE_ERROR_NONE; }; + + virtual ble_error_t areUpdatesEnabled( + const GattCharacteristic &characteristic, + bool *enabledP + ) { return BLE_ERROR_NONE; }; + + virtual ble_error_t areUpdatesEnabled( + ble::connection_handle_t connectionHandle, + const GattCharacteristic &characteristic, + bool *enabledP + ) { return BLE_ERROR_NONE; }; + + virtual ble::Gap::PreferredConnectionParams_t getPreferredConnectionParams() { + ble::Gap::PreferredConnectionParams_t params = {0}; return params; + }; + + virtual void setPreferredConnectionParams(const ble::Gap::PreferredConnectionParams_t ¶ms) { }; + + virtual bool isOnDataReadAvailable() const { return true; }; + + virtual void onDataSent(const DataSentCallback_t &callback) { }; + + virtual DataSentCallbackChain_t &onDataSent() { static DataSentCallbackChain_t chain; return chain; }; + + virtual void onDataWritten(const DataWrittenCallback_t &callback) { }; + + virtual DataWrittenCallbackChain_t &onDataWritten() { static DataWrittenCallbackChain_t chain; return chain; }; + + virtual ble_error_t onDataRead(const DataReadCallback_t &callback) { return BLE_ERROR_NONE; }; + + virtual DataReadCallbackChain_t &onDataRead() { static DataReadCallbackChain_t chain; return chain; }; + + virtual void onShutdown(const GattServerShutdownCallback_t &callback) { }; + + virtual GattServerShutdownCallbackChain_t &onShutdown() { static GattServerShutdownCallbackChain_t chain; return chain; }; + + virtual void onUpdatesEnabled(EventCallback_t callback) { }; + + virtual void onUpdatesDisabled(EventCallback_t callback) { }; + + virtual void onConfirmationReceived(EventCallback_t callback) { }; + + virtual void handleDataWrittenEvent(const GattWriteCallbackParams *params) { }; + + virtual void handleDataReadEvent(const GattReadCallbackParams *params) { }; + + virtual void handleEvent( + GattServerEvents::gattEvent_e type, + ble::connection_handle_t connHandle, + GattAttribute::Handle_t attributeHandle + ) { }; + + virtual void handleDataSentEvent(unsigned count) { }; +}; + +} +} + +#endif //BLE_GATTSERVERSTUB_H diff --git a/UNITTESTS/fakes/ble/source/GattServerImpl_mock.cpp b/UNITTESTS/fakes/ble/source/GattServerImpl_mock.cpp new file mode 100644 index 00000000000..baf6d0c8a6f --- /dev/null +++ b/UNITTESTS/fakes/ble/source/GattServerImpl_mock.cpp @@ -0,0 +1,96 @@ +/* mbed Microcontroller Library + * Copyright (c) 2021 ARM Limited + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "GattServerImpl_mock.h" + +namespace ble { + +GattServerMock::GattServerMock() +{ + ON_CALL(*this, addService).WillByDefault([this](GattService &service) { + // Fake registration, it populates the handles of the input and store its + // representation in the services field. + fake_register_services(service); + return BLE_ERROR_NONE; + }); +} + +GattServerMock::~GattServerMock() {}; + +void GattServerMock::fake_register_services(GattService& gattService) +{ + gattService.setHandle(current_handle++); + service_t result { + gattService.getUUID(), + gattService.getHandle() + }; + + for (size_t i = 0; i < gattService.getCharacteristicCount(); ++i) { + current_handle++; // Increment for the characteristic declaration handle + auto& ref = *gattService.getCharacteristic(i); + ref.getValueAttribute().setHandle(current_handle++); + + characteristic_t c; + c.uuid = ref.getValueAttribute().getUUID(); + c.value_handle = ref.getValueHandle(); + c.properties = ref.getProperties(); + c.read_security = ref.getReadSecurityRequirement(); + c.write_security = ref.getWriteSecurityRequirement(); + c.update_security = ref.getUpdateSecurityRequirement(); + c.read_cb = ref.getReadAuthorizationCallback(); + c.write_cb = ref.getWriteAuthorizationCallback(); + c.value.reserve(ref.getValueAttribute().getMaxLength()); + c.value.resize(ref.getValueAttribute().getLength()); + { + auto value_ptr = ref.getValueAttribute().getValuePtr(); + if (value_ptr) { + std::copy(value_ptr, value_ptr + c.value.size(), c.value.begin()); + } + } + c.has_variable_len = ref.getValueAttribute().hasVariableLength(); + + for (size_t j = 0; j < ref.getDescriptorCount(); ++j) { + auto& ref_desc = *ref.getDescriptor(j); + ref_desc.setHandle(current_handle++); + + descriptor_t d; + d.uuid = ref_desc.getUUID(); + d.handle = ref_desc.getHandle(); + d.read_security = ref_desc.getReadSecurityRequirement(); + d.write_security = ref_desc.getWriteSecurityRequirement(); + d.is_readable = ref_desc.isReadAllowed(); + d.is_writable = ref_desc.isWriteAllowed(); + d.value.reserve(ref_desc.getMaxLength()); + d.value.resize(ref_desc.getLength()); + { + auto value_ptr = ref_desc.getValuePtr(); + if (value_ptr) { + std::copy(value_ptr, value_ptr + d.value.size(), d.value.begin()); + } + } + + c.descriptors.push_back(d); + } + + result.characteristics.push_back(c); + } + + services.push_back(result); +} + + +} diff --git a/UNITTESTS/fakes/ble/source/generic/GapImpl.h b/UNITTESTS/fakes/ble/source/generic/GapImpl.h new file mode 100644 index 00000000000..6cd3bbf41f9 --- /dev/null +++ b/UNITTESTS/fakes/ble/source/generic/GapImpl.h @@ -0,0 +1,317 @@ +/* mbed Microcontroller Library + * Copyright (c) 2020 ARM Limited + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef BLE_GAPSTUB_H +#define BLE_GAPSTUB_H + +namespace ble { +namespace impl { + +class Gap { +public: + Gap() {}; + Gap(const Gap&) = delete; + Gap& operator=(const Gap&) = delete; + virtual ~Gap() {}; + + using EventHandler = ::ble::Gap::EventHandler; + using GapShutdownCallback_t = ::ble::Gap::GapShutdownCallback_t; + using GapShutdownCallbackChain_t = ::ble::Gap::GapShutdownCallbackChain_t ; + using PreferredConnectionParams_t = ::ble::Gap::PreferredConnectionParams_t ; + +#if BLE_FEATURE_PRIVACY +#if BLE_ROLE_BROADCASTER + static const peripheral_privacy_configuration_t default_peripheral_privacy_configuration; +#endif // BLE_ROLE_BROADCASTER + +#if BLE_ROLE_OBSERVER + /** + * Default peripheral privacy configuration. + */ + static const central_privacy_configuration_t default_central_privacy_configuration; +#endif // BLE_ROLE_OBSERVER +#endif // BLE_FEATURE_PRIVACY + +public: + virtual void setEventHandler(EventHandler *handler) { }; + + virtual bool isFeatureSupported(controller_supported_features_t feature) { return true; }; + + /* advertising */ +#if BLE_ROLE_BROADCASTER + + virtual uint8_t getMaxAdvertisingSetNumber() { return 1; }; + + virtual uint16_t getMaxAdvertisingDataLength() { return 23; }; + + virtual uint16_t getMaxConnectableAdvertisingDataLength() { return 21; }; + + virtual uint16_t getMaxActiveSetAdvertisingDataLength() { return 21; }; + +#if BLE_FEATURE_EXTENDED_ADVERTISING + + virtual ble_error_t createAdvertisingSet( + advertising_handle_t *handle, + const AdvertisingParameters ¶meters + ) { return BLE_ERROR_NONE; }; + + virtual ble_error_t destroyAdvertisingSet(advertising_handle_t handle) { return BLE_ERROR_NONE; }; + +#endif // BLE_FEATURE_EXTENDED_ADVERTISING + + virtual ble_error_t setAdvertisingParameters( + advertising_handle_t handle, + const AdvertisingParameters ¶ms + ) { return BLE_ERROR_NONE; }; + + virtual ble_error_t setAdvertisingPayload( + advertising_handle_t handle, + mbed::Span payload + ) { return BLE_ERROR_NONE; }; + + virtual ble_error_t setAdvertisingScanResponse( + advertising_handle_t handle, + mbed::Span response + ) { return BLE_ERROR_NONE; }; + + virtual ble_error_t startAdvertising( + advertising_handle_t handle, + adv_duration_t maxDuration = adv_duration_t::forever(), + uint8_t maxEvents = 0 + ) { return BLE_ERROR_NONE; }; + + virtual ble_error_t stopAdvertising(advertising_handle_t handle) { return BLE_ERROR_NONE; }; + + virtual bool isAdvertisingActive(advertising_handle_t handle) { return true; }; + +#endif // BLE_ROLE_BROADCASTER + +#if BLE_ROLE_BROADCASTER +#if BLE_FEATURE_PERIODIC_ADVERTISING + + virtual ble_error_t setPeriodicAdvertisingParameters( + advertising_handle_t handle, + periodic_interval_t periodicAdvertisingIntervalMin, + periodic_interval_t periodicAdvertisingIntervalMax, + bool advertiseTxPower = true + ) { return BLE_ERROR_NONE; }; + + virtual ble_error_t setPeriodicAdvertisingPayload( + advertising_handle_t handle, + mbed::Span payload + ) { return BLE_ERROR_NONE; }; + + virtual ble_error_t startPeriodicAdvertising(advertising_handle_t handle) { return BLE_ERROR_NONE; }; + + virtual ble_error_t stopPeriodicAdvertising(advertising_handle_t handle) { return BLE_ERROR_NONE; }; + + virtual bool isPeriodicAdvertisingActive(advertising_handle_t handle) { return true; }; + +#endif // BLE_ROLE_BROADCASTER +#endif // BLE_FEATURE_PERIODIC_ADVERTISING + + /* scanning */ +#if BLE_ROLE_OBSERVER + + virtual ble_error_t setScanParameters(const ScanParameters ¶ms) { return BLE_ERROR_NONE; }; + + virtual ble_error_t startScan( + scan_duration_t duration = scan_duration_t::forever(), + duplicates_filter_t filtering = duplicates_filter_t::DISABLE, + scan_period_t period = scan_period_t(0) + ) { return BLE_ERROR_NONE; }; + + virtual ble_error_t initiate_scan() { return BLE_ERROR_NONE; }; + + virtual ble_error_t stopScan() { return BLE_ERROR_NONE; }; + +#endif // BLE_ROLE_OBSERVER + +#if BLE_ROLE_OBSERVER +#if BLE_FEATURE_PERIODIC_ADVERTISING + + virtual ble_error_t createSync( + peer_address_type_t peerAddressType, + const address_t &peerAddress, + uint8_t sid, + slave_latency_t maxPacketSkip, + sync_timeout_t timeout + ) { return BLE_ERROR_NONE; }; + + virtual ble_error_t createSync( + slave_latency_t maxPacketSkip, + sync_timeout_t timeout + ) { return BLE_ERROR_NONE; }; + + virtual ble_error_t cancelCreateSync() { return BLE_ERROR_NONE; }; + + virtual ble_error_t terminateSync(periodic_sync_handle_t handle) { return BLE_ERROR_NONE; }; + + virtual ble_error_t addDeviceToPeriodicAdvertiserList( + peer_address_type_t peerAddressType, + const address_t &peerAddress, + advertising_sid_t sid + ) { return BLE_ERROR_NONE; }; + + virtual ble_error_t removeDeviceFromPeriodicAdvertiserList( + peer_address_type_t peerAddressType, + const address_t &peerAddress, + advertising_sid_t sid + ) { return BLE_ERROR_NONE; }; + + virtual ble_error_t clearPeriodicAdvertiserList() { return BLE_ERROR_NONE; }; + + uint8_t getMaxPeriodicAdvertiserListSize() { return 1; }; + +#endif // BLE_ROLE_OBSERVER +#endif // BLE_FEATURE_PERIODIC_ADVERTISING + +#if BLE_ROLE_CENTRAL + + virtual ble_error_t connect( + peer_address_type_t peerAddressType, + const address_t &peerAddress, + const ConnectionParameters &connectionParams + ) { return BLE_ERROR_NONE; }; + + virtual ble_error_t cancelConnect() { return BLE_ERROR_NONE; }; + +#endif // BLE_ROLE_CENTRAL + +#if BLE_FEATURE_CONNECTABLE + + virtual ble_error_t updateConnectionParameters( + connection_handle_t connectionHandle, + conn_interval_t minConnectionInterval, + conn_interval_t maxConnectionInterval, + slave_latency_t slaveLatency, + supervision_timeout_t supervision_timeout, + conn_event_length_t minConnectionEventLength = conn_event_length_t(0), + conn_event_length_t maxConnectionEventLength = conn_event_length_t(0) + ) { return BLE_ERROR_NONE; }; + + virtual ble_error_t manageConnectionParametersUpdateRequest( + bool userManageConnectionUpdateRequest + ) { return BLE_ERROR_NONE; }; + + virtual ble_error_t acceptConnectionParametersUpdate( + connection_handle_t connectionHandle, + conn_interval_t minConnectionInterval, + conn_interval_t maxConnectionInterval, + slave_latency_t slaveLatency, + supervision_timeout_t supervision_timeout, + conn_event_length_t minConnectionEventLength = conn_event_length_t(0), + conn_event_length_t maxConnectionEventLength = conn_event_length_t(0) + ) { return BLE_ERROR_NONE; }; + + virtual ble_error_t rejectConnectionParametersUpdate( + connection_handle_t connectionHandle + ) { return BLE_ERROR_NONE; }; + + virtual ble_error_t disconnect( + connection_handle_t connectionHandle, + local_disconnection_reason_t reason + ) { return BLE_ERROR_NONE; }; + +#endif // BLE_FEATURE_CONNECTABLE +#if BLE_FEATURE_PHY_MANAGEMENT + + virtual ble_error_t readPhy(connection_handle_t connection) { return BLE_ERROR_NONE; }; + + virtual ble_error_t setPreferredPhys( + const phy_set_t *txPhys, + const phy_set_t *rxPhys + ) { return BLE_ERROR_NONE; }; + + virtual ble_error_t setPhy( + connection_handle_t connection, + const phy_set_t *txPhys, + const phy_set_t *rxPhys, + coded_symbol_per_bit_t codedSymbol + ) { return BLE_ERROR_NONE; }; + +#endif // BLE_FEATURE_PHY_MANAGEMENT + +#if BLE_FEATURE_PRIVACY + + virtual ble_error_t enablePrivacy(bool enable) { return BLE_ERROR_NONE; }; + +#if BLE_ROLE_BROADCASTER + + virtual ble_error_t setPeripheralPrivacyConfiguration( + const peripheral_privacy_configuration_t *configuration + ) { return BLE_ERROR_NONE; }; + + virtual ble_error_t getPeripheralPrivacyConfiguration( + peripheral_privacy_configuration_t *configuration + ) { return BLE_ERROR_NONE; }; + +#endif // BLE_ROLE_BROADCASTER + +#if BLE_ROLE_OBSERVER + + virtual ble_error_t setCentralPrivacyConfiguration( + const central_privacy_configuration_t *configuration + ) { return BLE_ERROR_NONE; }; + + virtual ble_error_t getCentralPrivacyConfiguration( + central_privacy_configuration_t *configuration + ) { return BLE_ERROR_NONE; }; + +#endif // BLE_ROLE_OBSERVER +#endif // BLE_FEATURE_PRIVACY + +#if BLE_FEATURE_WHITELIST + + virtual uint8_t getMaxWhitelistSize() const { return 1; }; + + virtual ble_error_t getWhitelist(whitelist_t &whitelist) const { return BLE_ERROR_NONE; }; + + virtual ble_error_t setWhitelist(const whitelist_t &whitelist) { return BLE_ERROR_NONE; }; + +#endif // BLE_FEATURE_WHITELIST + + virtual ble_error_t getAddress( + own_address_type_t &typeP, + address_t &address + ) { return BLE_ERROR_NONE; }; + + static ble_error_t getRandomAddressType( + ble::address_t address, + ble::random_address_type_t *addressType + ) { return BLE_ERROR_NONE;}; + + virtual ble_error_t reset() { return BLE_ERROR_NONE; }; + + virtual void onShutdown(const GapShutdownCallback_t &callback) { }; + + virtual GapShutdownCallbackChain_t &onShutdown() { static GapShutdownCallbackChain_t chain; return chain; }; + + /* + * API reserved for the controller driver to set the random static address. + * Setting a new random static address while the controller is operating is + * forbidden by the Bluetooth specification. + */ + virtual ble_error_t setRandomStaticAddress(const ble::address_t &address) { return BLE_ERROR_NONE; }; + + virtual ble::address_t getRandomStaticAddress() { return ble::address_t(); }; +}; + +} +} + +#endif //BLE_GAPSTUB_H diff --git a/UNITTESTS/fakes/ble/source/generic/GattClientImpl.h b/UNITTESTS/fakes/ble/source/generic/GattClientImpl.h new file mode 100644 index 00000000000..2795ffeec9e --- /dev/null +++ b/UNITTESTS/fakes/ble/source/generic/GattClientImpl.h @@ -0,0 +1,133 @@ +/* mbed Microcontroller Library + * Copyright (c) 2020 ARM Limited + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef BLE_GATTCLIENTSTUB_H +#define BLE_GATTCLIENTSTUB_H + +#include "events/EventQueue.h" + +namespace ble { +namespace impl { + +class GattClient { +public: + using EventHandler = ble::GattClient::EventHandler; + using WriteOp_t = ble::GattClient::WriteOp_t; + using HVXCallback_t = ble::GattClient::HVXCallback_t ; + using GattClientShutdownCallback_t = ble::GattClient::GattClientShutdownCallback_t ; + using GattClientShutdownCallbackChain_t = ble::GattClient::GattClientShutdownCallbackChain_t ; + using HVXCallbackChain_t = ble::GattClient::HVXCallbackChain_t ; + using ReadCallbackChain_t = ble::GattClient::ReadCallbackChain_t ; + using WriteCallbackChain_t = ble::GattClient::WriteCallbackChain_t ; + + GattClient() {}; + GattClient(const GattClient&) = delete; + GattClient& operator=(const GattClient&) = delete; + virtual ~GattClient() {}; + + virtual void setEventHandler(EventHandler *handler) { }; + + virtual ble_error_t launchServiceDiscovery( + ble::connection_handle_t connectionHandle, + ServiceDiscovery::ServiceCallback_t sc = nullptr, + ServiceDiscovery::CharacteristicCallback_t cc = nullptr, + const UUID &matchingServiceUUID = UUID::ShortUUIDBytes_t(BLE_UUID_UNKNOWN), + const UUID &matchingCharacteristicUUIDIn = UUID::ShortUUIDBytes_t(BLE_UUID_UNKNOWN) + ) { return BLE_ERROR_NONE; }; + + virtual ble_error_t discoverServices( + ble::connection_handle_t connectionHandle, + ServiceDiscovery::ServiceCallback_t callback, + const UUID &matchingServiceUUID = UUID::ShortUUIDBytes_t(BLE_UUID_UNKNOWN) + ) { return BLE_ERROR_NONE; }; + + virtual ble_error_t discoverServices( + ble::connection_handle_t connectionHandle, + ServiceDiscovery::ServiceCallback_t callback, + GattAttribute::Handle_t startHandle, + GattAttribute::Handle_t endHandle + ) { return BLE_ERROR_NONE; }; + + virtual bool isServiceDiscoveryActive(void) const { return true; }; + + virtual void terminateServiceDiscovery(void) { }; + + virtual ble_error_t read( + ble::connection_handle_t connHandle, + GattAttribute::Handle_t attributeHandle, + uint16_t offset + ) const { return BLE_ERROR_NONE; }; + + virtual ble_error_t write( + GattClient::WriteOp_t cmd, + ble::connection_handle_t connHandle, + GattAttribute::Handle_t attributeHandle, + size_t length, + const uint8_t *value + ) const { return BLE_ERROR_NONE; }; + + /* Event callback handlers. */ + + virtual void onDataRead(ReadCallback_t callback) { }; + + virtual ReadCallbackChain_t &onDataRead() { static ReadCallbackChain_t chain; return chain; }; + + virtual void onDataWritten(WriteCallback_t callback) { }; + + virtual WriteCallbackChain_t &onDataWritten() { static WriteCallbackChain_t chain; return chain; }; + + virtual void onServiceDiscoveryTermination( + ServiceDiscovery::TerminationCallback_t callback + ) { }; + + virtual ble_error_t discoverCharacteristicDescriptors( + const DiscoveredCharacteristic &characteristic, + const CharacteristicDescriptorDiscovery::DiscoveryCallback_t &discoveryCallback, + const CharacteristicDescriptorDiscovery::TerminationCallback_t &terminationCallback + ) { return BLE_ERROR_NONE; }; + + virtual bool isCharacteristicDescriptorDiscoveryActive( + const DiscoveredCharacteristic &characteristic + ) const { return true; }; + + virtual void terminateCharacteristicDescriptorDiscovery( + const DiscoveredCharacteristic &characteristic + ) { }; + + virtual ble_error_t negotiateAttMtu(ble::connection_handle_t connection) { return BLE_ERROR_NONE; }; + + virtual void onHVX(HVXCallback_t callback) { }; + + virtual void onShutdown(const GattClientShutdownCallback_t &callback) { }; + + virtual GattClientShutdownCallbackChain_t &onShutdown() { static GattClientShutdownCallbackChain_t chain; return chain; }; + + virtual HVXCallbackChain_t &onHVX() { static HVXCallbackChain_t chain; return chain; }; + + virtual ble_error_t reset(void) { return BLE_ERROR_NONE; }; + + virtual void processReadResponse(const GattReadCallbackParams *params) { }; + + virtual void processWriteResponse(const GattWriteCallbackParams *params) { }; + + virtual void processHVXEvent(const GattHVXCallbackParams *params) { }; +}; + +} +} + +#endif //BLE_GATTCLIENTSTUB_H diff --git a/UNITTESTS/fakes/ble/source/generic/SecurityManagerImpl.h b/UNITTESTS/fakes/ble/source/generic/SecurityManagerImpl.h new file mode 100644 index 00000000000..35e4de51178 --- /dev/null +++ b/UNITTESTS/fakes/ble/source/generic/SecurityManagerImpl.h @@ -0,0 +1,186 @@ +/* mbed Microcontroller Library + * Copyright (c) 2020 ARM Limited + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef SECURITYMANAGERSTUB_H +#define SECURITYMANAGERSTUB_H + +namespace ble { +namespace impl { + +class SecurityManager { +public: + SecurityManager() {}; + SecurityManager(const SecurityManager&) = delete; + SecurityManager& operator=(const SecurityManager&) = delete; + virtual ~SecurityManager() {}; + + using SecurityIOCapabilities_t = ble::SecurityManager::SecurityIOCapabilities_t; + using SecurityMode_t = ble::SecurityManager::SecurityMode_t; + using SecurityManagerShutdownCallback_t = ble::SecurityManager::SecurityManagerShutdownCallback_t; + using SecurityManagerShutdownCallbackChain_t = ble::SecurityManager::SecurityManagerShutdownCallbackChain_t; + using EventHandler = ble::SecurityManager::EventHandler; + using Passkey_t = ble::SecurityManager::Passkey_t ; + + static auto constexpr IO_CAPS_NONE = ble::SecurityManager::IO_CAPS_NONE; + + virtual ble_error_t init( + bool enableBonding = true, + bool requireMITM = true, + SecurityIOCapabilities_t iocaps = IO_CAPS_NONE, + const Passkey_t passkey = nullptr, + bool signing = true, + const char *dbFilepath = nullptr + ) { return BLE_ERROR_NONE; }; + + virtual ble_error_t setDatabaseFilepath(const char *dbFilepath = nullptr) { return BLE_ERROR_NONE; }; + + virtual ble_error_t reset() { return BLE_ERROR_NONE; }; + + virtual ble_error_t preserveBondingStateOnReset(bool enable) { return BLE_ERROR_NONE; }; + + //////////////////////////////////////////////////////////////////////////// + // List management + // + + virtual ble_error_t purgeAllBondingState() { return BLE_ERROR_NONE; }; + + virtual ble_error_t generateWhitelistFromBondTable(::ble::whitelist_t *whitelist) const { return BLE_ERROR_NONE; }; + + //////////////////////////////////////////////////////////////////////////// + // Pairing + // + +#if BLE_ROLE_CENTRAL + virtual ble_error_t requestPairing(ble::connection_handle_t connectionHandle) { return BLE_ERROR_NONE; }; +#endif // BLE_ROLE_CENTRAL + +#if BLE_ROLE_PERIPHERAL + virtual ble_error_t acceptPairingRequest(ble::connection_handle_t connectionHandle) { return BLE_ERROR_NONE; }; +#endif // BLE_ROLE_PERIPHERAL + + virtual ble_error_t cancelPairingRequest(ble::connection_handle_t connectionHandle) { return BLE_ERROR_NONE; }; + + virtual ble_error_t setPairingRequestAuthorisation(bool required = true) { return BLE_ERROR_NONE; }; + + virtual ble_error_t getPeerIdentity(ble::connection_handle_t connectionHandle) { return BLE_ERROR_NONE; }; + + //////////////////////////////////////////////////////////////////////////// + // Feature support + // +#if BLE_FEATURE_SECURE_CONNECTIONS + virtual ble_error_t allowLegacyPairing(bool allow = true) { return BLE_ERROR_NONE; }; + + virtual ble_error_t getSecureConnectionsSupport(bool *enabled) { return BLE_ERROR_NONE; }; +#endif // BLE_FEATURE_SECURE_CONNECTIONS + + //////////////////////////////////////////////////////////////////////////// + // Security settings + // + + virtual ble_error_t setIoCapability(SecurityIOCapabilities_t iocaps) { return BLE_ERROR_NONE; }; + + virtual ble_error_t setDisplayPasskey(const Passkey_t passkey) { return BLE_ERROR_NONE; }; + + virtual ble_error_t setLinkSecurity(ble::connection_handle_t connectionHandle, SecurityMode_t securityMode) { return BLE_ERROR_NONE; }; + + virtual ble_error_t setKeypressNotification(bool enabled = true) { return BLE_ERROR_NONE; }; + +#if BLE_FEATURE_SIGNING + + virtual ble_error_t enableSigning(ble::connection_handle_t connectionHandle, bool enabled = true) { return BLE_ERROR_NONE; }; + +#endif // BLE_FEATURE_SIGNING + + virtual ble_error_t setHintFutureRoleReversal(bool enable = true) { return BLE_ERROR_NONE; }; + + //////////////////////////////////////////////////////////////////////////// + // Encryption + // + + virtual ble_error_t getLinkEncryption(ble::connection_handle_t connectionHandle, ble::link_encryption_t *encryption) { return BLE_ERROR_NONE; }; + + virtual ble_error_t setLinkEncryption(ble::connection_handle_t connectionHandle, ble::link_encryption_t encryption) { return BLE_ERROR_NONE; }; + + virtual ble_error_t setEncryptionKeyRequirements(uint8_t minimumByteSize, uint8_t maximumByteSize) { return BLE_ERROR_NONE; }; + + virtual ble_error_t getEncryptionKeySize( + connection_handle_t connectionHandle, + uint8_t *size + ) { return BLE_ERROR_NONE; }; + + //////////////////////////////////////////////////////////////////////////// + // Authentication + // + + virtual ble_error_t requestAuthentication(ble::connection_handle_t connectionHandle) { return BLE_ERROR_NONE; }; + + //////////////////////////////////////////////////////////////////////////// + // MITM + // + + virtual ble_error_t generateOOB(const ble::address_t *address) { return BLE_ERROR_NONE; }; + + virtual ble_error_t setOOBDataUsage(ble::connection_handle_t connectionHandle, bool useOOB, bool OOBProvidesMITM = true) { return BLE_ERROR_NONE; }; + + virtual ble_error_t passkeyEntered(ble::connection_handle_t connectionHandle, Passkey_t passkey) { return BLE_ERROR_NONE; }; + + virtual ble_error_t legacyPairingOobReceived(const ble::address_t *address, const ble::oob_tk_t *tk) { return BLE_ERROR_NONE; }; +#if BLE_FEATURE_SECURE_CONNECTIONS + virtual ble_error_t confirmationEntered(ble::connection_handle_t connectionHandle, bool confirmation) { return BLE_ERROR_NONE; }; + + virtual ble_error_t sendKeypressNotification(ble::connection_handle_t connectionHandle, ble::Keypress_t keypress) { return BLE_ERROR_NONE; }; + + virtual ble_error_t oobReceived( + const ble::address_t *address, + const ble::oob_lesc_value_t *random, + const ble::oob_confirm_t *confirm + ) { return BLE_ERROR_NONE; }; +#endif // BLE_FEATURE_SECURE_CONNECTIONS + + //////////////////////////////////////////////////////////////////////////// + // Keys + // +#if BLE_FEATURE_SIGNING + virtual ble_error_t getSigningKey(ble::connection_handle_t connectionHandle, bool authenticated) { return BLE_ERROR_NONE; }; +#endif // BLE_FEATURE_SIGNING + //////////////////////////////////////////////////////////////////////////// + // Privacy + // + +#if BLE_FEATURE_PRIVACY + virtual ble_error_t setPrivateAddressTimeout( + uint16_t timeout_in_seconds + ) { return BLE_ERROR_NONE; }; +#endif // BLE_FEATURE_PRIVACY + + /* Event callback handlers. */ +public: + + virtual void onShutdown(const SecurityManagerShutdownCallback_t &callback) { }; + + template + void onShutdown(T *objPtr, void (T::*memberPtr)(const SecurityManager *)) { }; + + virtual SecurityManagerShutdownCallbackChain_t &onShutdown() { static SecurityManagerShutdownCallbackChain_t chain; return chain; }; + + virtual void setSecurityManagerEventHandler(EventHandler *handler) { }; +}; + +} +} + +#endif //SECURITYMANAGERSTUB_H From 0515408f2166c43602591eb80cb88640b859c8ec Mon Sep 17 00:00:00 2001 From: Paul Szczepanek Date: Sun, 6 Jun 2021 11:39:54 +0100 Subject: [PATCH 3/8] add default BLE roles configuration in case no json present --- .../FEATURE_BLE/include/ble/common/BLERoles.h | 44 +++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/connectivity/FEATURE_BLE/include/ble/common/BLERoles.h b/connectivity/FEATURE_BLE/include/ble/common/BLERoles.h index 2c28eadbd5b..7ef8d63b827 100644 --- a/connectivity/FEATURE_BLE/include/ble/common/BLERoles.h +++ b/connectivity/FEATURE_BLE/include/ble/common/BLERoles.h @@ -19,6 +19,50 @@ #ifndef MBED_BLE_ROLES_H__ #define MBED_BLE_ROLES_H__ +/* we provide default values if no configuration is present (e.g. in unittests) */ +#if !defined(BLE_ROLE_OBSERVER) +#define BLE_ROLE_OBSERVER 1 +#endif +#if !defined(BLE_ROLE_BROADCASTER) +#define BLE_ROLE_BROADCASTER 1 +#endif +#if !defined(BLE_ROLE_CENTRAL) +#define BLE_ROLE_CENTRAL 1 +#endif +#if !defined(BLE_ROLE_PERIPHERAL) +#define BLE_ROLE_PERIPHERAL 1 +#endif +#if !defined(BLE_FEATURE_GATT_CLIENT) +#define BLE_FEATURE_GATT_CLIENT 1 +#endif +#if !defined(BLE_FEATURE_GATT_SERVER) +#define BLE_FEATURE_GATT_SERVER 1 +#endif +#if !defined(BLE_FEATURE_SECURITY) +#define BLE_FEATURE_SECURITY 1 +#endif +#if !defined(BLE_FEATURE_SECURE_CONNECTIONS) +#define BLE_FEATURE_SECURE_CONNECTIONS 1 +#endif +#if !defined(BLE_FEATURE_SIGNING) +#define BLE_FEATURE_SIGNING 1 +#endif +#if !defined(BLE_FEATURE_WHITELIST) +#define BLE_FEATURE_WHITELIST 1 +#endif +#if !defined(BLE_FEATURE_PRIVACY) +#define BLE_FEATURE_PRIVACY 1 +#endif +#if !defined(BLE_FEATURE_PHY_MANAGEMENT) +#define BLE_FEATURE_PHY_MANAGEMENT 1 +#endif +#if !defined(BLE_FEATURE_EXTENDED_ADVERTISING) +#define BLE_FEATURE_EXTENDED_ADVERTISING 1 +#endif +#if !defined(BLE_FEATURE_PERIODIC_ADVERTISING) +#define BLE_FEATURE_PERIODIC_ADVERTISING 1 +#endif + #if !(BLE_ROLE_OBSERVER) && !(BLE_ROLE_BROADCASTER) #error "BLE requires at least one role 'BROADCASTER' or 'OBSERVER' to be enabled" #endif From cc0729a6784b7f3cd1d5e730e11a69e57b5f0c9b Mon Sep 17 00:00:00 2001 From: Paul Szczepanek Date: Sun, 6 Jun 2021 11:42:20 +0100 Subject: [PATCH 4/8] add missing tuple c++ replacement for unittests --- .../target_h/platform/cxxsupport/mstd_tuple | 93 +++++++++++++++++++ 1 file changed, 93 insertions(+) create mode 100644 UNITTESTS/target_h/platform/cxxsupport/mstd_tuple diff --git a/UNITTESTS/target_h/platform/cxxsupport/mstd_tuple b/UNITTESTS/target_h/platform/cxxsupport/mstd_tuple new file mode 100644 index 00000000000..d9e926aa57d --- /dev/null +++ b/UNITTESTS/target_h/platform/cxxsupport/mstd_tuple @@ -0,0 +1,93 @@ +/* mbed Microcontroller Library + * Copyright (c) 2019 ARM Limited + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES LEOR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef MSTD_TUPLE_ +#define MSTD_TUPLE_ + +/* + * + * - includes toolchain's + * - For all toolchains, C++17 backports: + * - mstd::apply + * - mstd::make_from_tuple + */ + +#include + +#if __cpp_lib_apply < 201603 || __cpp_lib_make_from_tuple < 201606 +#include // integer_sequence +#endif +#if __cpp_lib_apply < 201603 +#include // invoke +#endif + +namespace mstd { +using std::tuple; +using std::ignore; +using std::make_tuple; +using std::forward_as_tuple; +using std::tie; +using std::tuple_cat; +using std::tuple_size; +using std::tuple_element; +using std::tuple_element_t; +using std::get; + +// [tuple.apply] +#if __cpp_lib_apply >= 201603 +using std::apply; +#else +namespace impl { +template +invoke_result_t...> apply(F&& f, Tuple&& t, std::index_sequence) +{ + return mstd::invoke(std::forward(f), std::get(std::forward(t))...); +} +} + +// apply - works also for tuple-like objects such as array or pair +// user-defined types can specialize std::get and std::tuple_size to make this work +template +auto apply(F&& f, Tuple&& t) -> +decltype(impl::apply(std::forward(f), std::forward(t), std::make_index_sequence>::value>{})) +{ + return impl::apply(std::forward(f), std::forward(t), + std::make_index_sequence>::value>{}); +} +#endif + +#if __cpp_lib_make_from_tuple >= 201606 +using std::make_from_tuple; +#else +namespace impl { +template +T make_from_tuple(Tuple&& t, std::index_sequence) +{ + return T(std::get(std::forward(t))...); +} +} + +template +T make_from_tuple(Tuple&& t) +{ + return impl::make_from_tuple(std::forward(t), + std::make_index_sequence>::value>{}); +} +#endif + +} // namespace mstd + +#endif // MSTD_TUPLE_ From 8557529ae3b15634fad81bf8b49e25e524676440 Mon Sep 17 00:00:00 2001 From: Paul Szczepanek Date: Mon, 7 Jun 2021 16:30:35 +0100 Subject: [PATCH 5/8] missing newlines --- UNITTESTS/fakes/ble/BLE.cpp | 2 +- UNITTESTS/fakes/ble/ble_mocks.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/UNITTESTS/fakes/ble/BLE.cpp b/UNITTESTS/fakes/ble/BLE.cpp index 337558ed57c..57eb53d52b1 100644 --- a/UNITTESTS/fakes/ble/BLE.cpp +++ b/UNITTESTS/fakes/ble/BLE.cpp @@ -160,4 +160,4 @@ void BLE::processEvents() } -} \ No newline at end of file +} diff --git a/UNITTESTS/fakes/ble/ble_mocks.h b/UNITTESTS/fakes/ble/ble_mocks.h index efeac598c14..d92904e1738 100644 --- a/UNITTESTS/fakes/ble/ble_mocks.h +++ b/UNITTESTS/fakes/ble/ble_mocks.h @@ -42,4 +42,4 @@ SecurityManagerMock& security_manager_mock(); } -#endif // BLE_MOCKS_H \ No newline at end of file +#endif // BLE_MOCKS_H From 3fa779692cf855affcfe3ff5de23fb65edefc437 Mon Sep 17 00:00:00 2001 From: Paul Szczepanek Date: Mon, 7 Jun 2021 16:44:34 +0100 Subject: [PATCH 6/8] Add a readme to unit tests --- UNITTESTS/README.md | 65 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 65 insertions(+) create mode 100644 UNITTESTS/README.md diff --git a/UNITTESTS/README.md b/UNITTESTS/README.md new file mode 100644 index 00000000000..53d8b11ec79 --- /dev/null +++ b/UNITTESTS/README.md @@ -0,0 +1,65 @@ +## Stubs, mocks and fakes in Mbed OS + +To make unit testing easier, Mbed OS provides some ready-made CMake libraries you can add in your `target_link_libraries`. +Libraries can be object files that contain stubs, mocks and fakes but also sets of include paths - this way you can gain access to normal headers from Mbed OS. + +All the libraries available are in the `CMakeLists.txt` files in `mbed-os/UNITTESTS/stubs` and `mbed-os/UNITTESTS/fakes`. + +The most common ones you might need are `mbed-os-fakes-ble` and `mbed-os-fakes-event-queue`. + +### Fakes + +While stubs are self explanatory and don't offer anything beyond empty implementations, fakes allow for more complex unittests that can simulate whole subsystems. + +#### mbed-os-fakes-ble + +This library provides a fake BLE implementation that uses mocks instead of real BLE components for `Gap`, `GattServer`, `GattClient`, `SecurityManager`. + +There is no need to initialise a fake BLE instance; it is ready to go and can be used just like a normal BLE instance: + +```c++ +BLE *ble = &BLE::Instance(); +``` + +This call also initialises mocks. +Do no cache the BLE instance pointer, or pointer to `GAP`, `GattServer` etc. between tests. +You must get the instance fresh at the start of the test. + +You can retrieve all the BLE APIs from the instance just like with a normal one: + +```c++ +Gap &gap = ble->gap(); +GattClient &client = ble->gattClient(); +GattServer &server = ble->gattServer(); +SecurityManager &sm = ble->securityManager(); +``` + +Whenever an API call is made, the implementation will be called. +These are replaced in the fake BLE with google mocks. +This means you can set expectations on them. + +```c++ +EXPECT_CALL(ble::gap_mock(), reset()); +``` + +This will set up an expectation that at some point during the test the `Gap::reset` method will be called. + +The way GoogleTest works means that if you set expectations on your mocks they must be destroyed at the end of each test. +This is done through the fake BLE instance special method: + +```c++ +ble::delete_mocks(); +``` + +#### mbed-os-fakes-event-queue + +This is a fake event queue that doesn't bring in any dependencies from mbed-os. +Its API is simplified and it only offers limited functionality. + +If you choose to use it you must not also include a library that brings in real headers for the event queue as they would conflict. + +The API calls supported are for simple calls `call`, `call_in` and the `cancel` method. + +The event queue is not run in real time and must be progressed manually. +You may use `dispatch(int milliseconds)` and `dispatch_forever()` to process events in the queue. +This way you can simulate the passage of time in your test. From 36d9b86d466538f826555a151c7bf15c93b43411 Mon Sep 17 00:00:00 2001 From: Paul Szczepanek Date: Thu, 10 Jun 2021 11:56:16 +0100 Subject: [PATCH 7/8] fix typos Co-authored-by: Chris Swinchatt --- UNITTESTS/fakes/events/events/EventQueue.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/UNITTESTS/fakes/events/events/EventQueue.h b/UNITTESTS/fakes/events/events/EventQueue.h index 6958298654f..0e09cfe4342 100644 --- a/UNITTESTS/fakes/events/events/EventQueue.h +++ b/UNITTESTS/fakes/events/events/EventQueue.h @@ -41,7 +41,7 @@ class EventQueue { ~EventQueue() { }; - /** This will advence time by given amount of milliseonds and then dispatch all events that were set to happen in that time. + /** This will advance time by given amount of milliseconds and then dispatch all events that were set to happen in that time. * * @param ms number of miliseconds to advance time */ From 86426102ec4ba54db06f541b4d83f6a23bd0e5a4 Mon Sep 17 00:00:00 2001 From: Paul Szczepanek Date: Fri, 11 Jun 2021 10:44:38 +0100 Subject: [PATCH 8/8] remove unittest readme --- UNITTESTS/README.md | 65 --------------------------------------------- 1 file changed, 65 deletions(-) delete mode 100644 UNITTESTS/README.md diff --git a/UNITTESTS/README.md b/UNITTESTS/README.md deleted file mode 100644 index 53d8b11ec79..00000000000 --- a/UNITTESTS/README.md +++ /dev/null @@ -1,65 +0,0 @@ -## Stubs, mocks and fakes in Mbed OS - -To make unit testing easier, Mbed OS provides some ready-made CMake libraries you can add in your `target_link_libraries`. -Libraries can be object files that contain stubs, mocks and fakes but also sets of include paths - this way you can gain access to normal headers from Mbed OS. - -All the libraries available are in the `CMakeLists.txt` files in `mbed-os/UNITTESTS/stubs` and `mbed-os/UNITTESTS/fakes`. - -The most common ones you might need are `mbed-os-fakes-ble` and `mbed-os-fakes-event-queue`. - -### Fakes - -While stubs are self explanatory and don't offer anything beyond empty implementations, fakes allow for more complex unittests that can simulate whole subsystems. - -#### mbed-os-fakes-ble - -This library provides a fake BLE implementation that uses mocks instead of real BLE components for `Gap`, `GattServer`, `GattClient`, `SecurityManager`. - -There is no need to initialise a fake BLE instance; it is ready to go and can be used just like a normal BLE instance: - -```c++ -BLE *ble = &BLE::Instance(); -``` - -This call also initialises mocks. -Do no cache the BLE instance pointer, or pointer to `GAP`, `GattServer` etc. between tests. -You must get the instance fresh at the start of the test. - -You can retrieve all the BLE APIs from the instance just like with a normal one: - -```c++ -Gap &gap = ble->gap(); -GattClient &client = ble->gattClient(); -GattServer &server = ble->gattServer(); -SecurityManager &sm = ble->securityManager(); -``` - -Whenever an API call is made, the implementation will be called. -These are replaced in the fake BLE with google mocks. -This means you can set expectations on them. - -```c++ -EXPECT_CALL(ble::gap_mock(), reset()); -``` - -This will set up an expectation that at some point during the test the `Gap::reset` method will be called. - -The way GoogleTest works means that if you set expectations on your mocks they must be destroyed at the end of each test. -This is done through the fake BLE instance special method: - -```c++ -ble::delete_mocks(); -``` - -#### mbed-os-fakes-event-queue - -This is a fake event queue that doesn't bring in any dependencies from mbed-os. -Its API is simplified and it only offers limited functionality. - -If you choose to use it you must not also include a library that brings in real headers for the event queue as they would conflict. - -The API calls supported are for simple calls `call`, `call_in` and the `cancel` method. - -The event queue is not run in real time and must be progressed manually. -You may use `dispatch(int milliseconds)` and `dispatch_forever()` to process events in the queue. -This way you can simulate the passage of time in your test.