Merge pull request #6452 from ARMmbed/revert-6086-gatt-client-unit-tests

Revert "BLE: Gatt client unit tests"
pull/6467/head
Cruz Monrreal 2018-03-26 14:33:52 -05:00 committed by GitHub
commit 062164eaad
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
22 changed files with 0 additions and 4020 deletions

View File

@ -20,15 +20,6 @@ cache:
- $HOME/.cache/apt
- $HOME/gcc-arm-none-eabi-6-2017-q2-update
addons:
apt:
sources:
- ubuntu-toolchain-r-test
packages:
- gcc-6
- g++-6
- cmake
before_install:
- bash -c "$STATUS" pending "Local $NAME testing is in progress"
# Make sure pipefail
@ -143,25 +134,6 @@ matrix:
fi
- bash -c "$STATUS" success "$STATUSM"
- env:
- NAME=ble-host-tests
- BLE_HOST_TESTS=$PWD/features/FEATURE_BLE/tests
install:
# Install dependencies
- sudo apt-get install cmake
# Print versions we use
- gcc --version
- cmake --version
script:
# Compile the tests
- mkdir $BLE_HOST_TESTS/build
- cd $BLE_HOST_TESTS/build && CC=gcc-6 CXX=g++-6 cmake .. -G "Unix Makefiles"
- ls $BLE_HOST_TESTS
- ls $BLE_HOST_TESTS/build
- cd $BLE_HOST_TESTS/build && make
# Run ble host tests
- $BLE_HOST_TESTS/build/gatt-client-tests
- env:
- NAME=littlefs
- LITTLEFS=features/filesystem/littlefs

View File

@ -1,89 +0,0 @@
cmake_minimum_required(VERSION 2.8.11)
# Make PROJECT_SOURCE_DIR, PROJECT_BINARY_DIR, and PROJECT_NAME available.
set(PROJECT_NAME ble-tests)
project(${PROJECT_NAME})
set(CMAKE_CXX_STANDARD 14)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
################################
# GTEST
################################
# Download and unpack googletest at configure time
configure_file(CMakeLists.txt.in googletest-download/CMakeLists.txt)
execute_process(COMMAND ${CMAKE_COMMAND} -G "${CMAKE_GENERATOR}" .
RESULT_VARIABLE result
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/googletest-download )
if(result)
message(FATAL_ERROR "CMake step for googletest failed: ${result}")
endif()
execute_process(COMMAND ${CMAKE_COMMAND} --build .
RESULT_VARIABLE result
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/googletest-download )
if(result)
message(FATAL_ERROR "Build step for googletest failed: ${result}")
endif()
# Prevent overriding the parent project's compiler/linker
# settings on Windows
set(gtest_force_shared_crt ON CACHE BOOL "" FORCE)
# Add googletest directly to our build. This defines
# the gtest and gtest_main targets.
add_subdirectory(${CMAKE_BINARY_DIR}/googletest-src
${CMAKE_BINARY_DIR}/googletest-build
EXCLUDE_FROM_ALL)
# The gtest/gtest_main targets carry header search path
# dependencies automatically when using CMake 2.8.11 or
# later. Otherwise we have to add them here ourselves.
if (CMAKE_VERSION VERSION_LESS 2.8.11)
include_directories(BEFORE SYSTEM
"${gtest_SOURCE_DIR}/include" "${gmock_SOURCE_DIR}/include")
else()
target_include_directories(gmock_main SYSTEM BEFORE INTERFACE
"${gtest_SOURCE_DIR}/include" "${gmock_SOURCE_DIR}/include")
endif()
################################
# Testing
################################
enable_testing()
###############################
# GattClient test
###############################
add_executable(gatt-client-tests
mbed_os_stub/mbed_assert.c
generic/GattClient/mock/MockCallbacks.cpp
generic/GattClient/mock/MockPalGattClient.cpp
generic/GattClient/util/Equality.cpp
generic/GattClient/TestCharacteristicDesctiptorDiscovery.cpp
generic/GattClient/TestDiscoverAllServices.cpp
generic/GattClient/TestNoCb.cpp
generic/GattClient/TestRead.cpp
generic/GattClient/TestServerEvent.cpp
generic/GattClient/TestWrite.cpp
${PROJECT_SOURCE_DIR}/../source/generic/GenericGattClient.cpp
)
target_include_directories(gatt-client-tests PRIVATE
"${PROJECT_SOURCE_DIR}/.."
"${PROJECT_SOURCE_DIR}/../../.."
"${PROJECT_SOURCE_DIR}/generic/GattClient"
)
# Standard linking to gtest stuff.
target_link_libraries(gatt-client-tests gmock_main)
# This is so you can do 'make gatt-client-tests' to see all your tests run, instead of
# manually running the executable runUnitTests to see those specific tests.
add_test(NAME AllUnitTests COMMAND gatt-client-tests)

View File

@ -1,15 +0,0 @@
cmake_minimum_required(VERSION 2.8.11)
project(googletest-download NONE)
include(ExternalProject)
ExternalProject_Add(googletest
GIT_REPOSITORY https://github.com/google/googletest.git
GIT_TAG master
SOURCE_DIR "${CMAKE_BINARY_DIR}/googletest-src"
BINARY_DIR "${CMAKE_BINARY_DIR}/googletest-build"
CONFIGURE_COMMAND ""
BUILD_COMMAND ""
INSTALL_COMMAND ""
TEST_COMMAND ""
)

View File

@ -1,35 +0,0 @@
# mbed BLE host tests
This folder contains tests for mbed BLE that can be run on an x86 host.
## Getting started
Run the following instructions to build the tests:
```
cd features/FEATURE_BLE/tests
mkdir build
cd build
cmake ..
make
```
The various tests applications are present at the root of the test folder;
execute them to run the tests. As an examples gatt client related tests can be
run with:
```
./gatt-client-tests
```
## Requirements
These tests requires cmake on the host and a compliant C++14 compiler.
## Resources
These tests use extensively google test (gtest) and google mock. Please refer to
the documentation of each products to get more insight:
* gtest: https://github.com/google/googletest/tree/master/googletest/docs
* gmock: https://github.com/google/googletest/tree/master/googlemock/docs

View File

@ -1,669 +0,0 @@
/* mbed Microcontroller Library
* Copyright (c) 2018 ARM Limited
*
* 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 <algorithm>
#include <vector>
#include <array>
#include <initializer_list>
#include <tuple>
#include <cstdlib>
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "ble/generic/GenericGattClient.h"
#include "ble/pal/AttServerMessage.h"
#include "ble/pal/SimpleAttServerMessage.h"
#include "ble/DiscoveredService.h"
#include "mock/MockPalGattClient.h"
#include "mock/MockCallbacks.h"
#include "util/PrettyPrinter.h"
#include "util/Equality.h"
#include "util/Log.h"
// using declarations
using ble::pal::AttErrorResponse;
using ble::pal::AttributeOpcode;
using ble::pal::AttFindInformationResponse;
using ble::generic::GenericGattClient;
using ble::pal::vendor::mock::MockPalGattClient;
using ble::connection_handle_t;
using ble::attribute_handle_range;
using ble::attribute_handle_range_t;
using ::testing::_;
using ::testing::Invoke;
using ::testing::AllOf;
using ::testing::ResultOf;
using ::testing::InSequence;
using ::testing::Pointee;
using std::vector;
using std::tuple;
using std::pair;
struct ConstructibleDiscoveredCharacteristic : public DiscoveredCharacteristic {
ConstructibleDiscoveredCharacteristic(
GattClient* client,
Gap::Handle_t connection_handle,
const UUID& uuid,
uint16_t declaration_handle,
uint16_t value_handle,
uint16_t last_handle
) : DiscoveredCharacteristic() {
this->gattc = client;
this->uuid = uuid;
declHandle = declaration_handle;
valueHandle = value_handle;
lastHandle = last_handle;
connHandle = connection_handle;
}
void set_last_handle(uint16_t last_handle) {
lastHandle = last_handle;
}
void set_value_handle(uint16_t value_handle) {
valueHandle = value_handle;
}
};
/**
* Test fixture used for client descriptor discovery testing.
*/
class TestGattClientDescriptorDiscovery : public ::testing::Test {
protected:
TestGattClientDescriptorDiscovery() :
_mock_client(),
_gatt_client(&_mock_client),
_connection_handle(0xDEAD),
_attribute_handle(0x5645),
_descriptor_cb(),
_termination_cb(),
_mtu_size(23),
_characteristic(
&_gatt_client,
_connection_handle,
UUID(0xDEAF),
_attribute_handle,
_attribute_handle + 1,
_attribute_handle + 1
) {
}
virtual void SetUp() {
ON_CALL(
_mock_client, get_mtu_size(_connection_handle, _)
).WillByDefault(Invoke([&](auto, auto& size){
size = this->_mtu_size;
return BLE_ERROR_NONE;
}));
}
void set_mtu_size_stub() {
EXPECT_CALL(
_mock_client, get_mtu_size(_connection_handle, _)
).WillRepeatedly(::testing::DoDefault());
}
MockPalGattClient _mock_client;
GenericGattClient _gatt_client;
const Gap::Handle_t _connection_handle;
uint16_t _attribute_handle;
descriptor_callback_t _descriptor_cb;
descriptor_termination_callback_t _termination_cb;
uint16_t _mtu_size;
ConstructibleDiscoveredCharacteristic _characteristic;
};
// errors: Invalid handle if:
// starting handle > ending handle
// stating handle == 00
// ending handle > last handle on the server
// if no handle will be return => ATTRIBUTE NOT FOUND
// Complete when ATTRIBUTE NOT FOUND is returned or an attribute handle
// in the response is equal to the ending handle in the request.
// Find information response:
// format & [(handle, UUID)]
// format == 1 => 16 bit UUID
// format == 2 => 128 bit UUID
/*
* Given a discovered characteristic with the value handle equal to the last
* handle of the characteristic.
* When the client discover the descriptor of the characteristic
* Then:
* - no request is issued to the PAL.
* - the function doesn't return any error.
* - the termination callback is called immediately
*/
TEST_F(TestGattClientDescriptorDiscovery, descriptor_discovery_on_characteristics_without_descriptor_shall_return_immediatelly) {
_characteristic.set_last_handle(_characteristic.getValueHandle());
EXPECT_CALL(
_mock_client, discover_characteristics_descriptors(_, _)
).Times(0);
EXPECT_CALL(
_termination_cb, call(Pointee(CharacteristicDescriptorDiscovery::TerminationCallbackParams_t {
_characteristic,
BLE_ERROR_NONE,
0x00
})
)
);
ble_error_t err = _gatt_client.discoverCharacteristicDescriptors(
_characteristic,
makeFunctionPointer(&_descriptor_cb, &descriptor_callback_t::call),
makeFunctionPointer(&_termination_cb, &descriptor_termination_callback_t::call)
);
EXPECT_EQ(err, BLE_ERROR_NONE);
}
/**
* Test parameter pass into tests using TestGattClientDescriptorDiscoveryP fixture.
* - first element: value handle of the characteristic.
* - second element: last handle of the characteristic
* - third element: expected transactions; each transaction can contain multiple
* pair containing the handle of the descriptor and its UUID.
*/
typedef tuple<uint16_t, uint16_t, vector<vector<pair<uint16_t, UUID>>>> test_param_t;
/**
* Parametric fixture used for descriptor discovery testing.
*/
class TestGattClientDescriptorDiscoveryP :
public TestGattClientDescriptorDiscovery,
public ::testing::WithParamInterface<test_param_t> {
protected:
TestGattClientDescriptorDiscoveryP() :
TestGattClientDescriptorDiscovery(),
_value_handle(0),
_last_handle(0),
_descriptors() {
}
virtual void SetUp() {
TestGattClientDescriptorDiscovery::SetUp();
std::tie(_value_handle, _last_handle, _descriptors) = GetParam();
_characteristic.set_value_handle(_value_handle);
_characteristic.set_last_handle(_last_handle);
}
uint16_t _value_handle;
uint16_t _last_handle;
vector<vector<pair<uint16_t, UUID>>> _descriptors;
};
struct MockFindInformationResponse : public AttFindInformationResponse {
MockFindInformationResponse(vector<pair<uint16_t, UUID>> response) :
_response(response) { }
virtual size_t size() const {
return _response.size();
}
virtual information_data_t operator[](size_t index) const {
auto& element = _response[index];
return {
element.first,
element.second
};
}
vector<pair<uint16_t, UUID>> _response;
};
/**
* Helper returning a DiscoveredCharacteristic from a DiscoveryCallbackParams_t*
*/
static const DiscoveredCharacteristic& get_characteristic(const CharacteristicDescriptorDiscovery::DiscoveryCallbackParams_t* p) {
return p->characteristic;
}
/**
* Helper returning a DiscoveredCharacteristicDescriptor from a DiscoveryCallbackParams_t*
*/
static const DiscoveredCharacteristicDescriptor& get_descriptor(const CharacteristicDescriptorDiscovery::DiscoveryCallbackParams_t* p) {
return p->descriptor;
}
/*
* Given a discovered characteristic with the value handle not equal to the
* last handle of the characteristic.
* when the client launch the discovery of the descriptor of the characteristic.
* Then:
* - the client invoke the pal function discover_characteristics_descriptors
* with an handle range starting at characteristic value handle + 1 and ending
* at the last characteristic handle.
* - The pal will reply with a FindInformationResponse containing the
* descriptors discovered.
* The operation is repeated until the response contains an attribute with an
* handle equal to the last handle of the range or the pal reply with an error
* (attribute not found). The termination callback is then call with a status
* containing BLE_ERROR_NONE.
*/
TEST_P(TestGattClientDescriptorDiscoveryP, descriptor_discovery) {
uint16_t current_handle = _characteristic.getValueHandle() + 1;
auto descriptors = _descriptors;
InSequence seq;
while (true) {
//Log::info() << "expect discover_characteristics_descriptors(" << current_handle << ", " << _last_handle << ")" << std::endl;
EXPECT_CALL(
_mock_client, discover_characteristics_descriptors(
_connection_handle,
attribute_handle_range(current_handle, _last_handle)
)
).WillOnce(Invoke([&, descriptors, current_handle](auto connection, auto range) {
if (descriptors.empty()) {
// send an attribute not found response
_mock_client.on_server_event(
connection,
AttErrorResponse(
AttributeOpcode::FIND_INFORMATION_REQUEST,
current_handle,
AttErrorResponse::ATTRIBUTE_NOT_FOUND
)
);
} else {
_mock_client.on_server_event(
connection,
MockFindInformationResponse(descriptors.front())
);
}
return BLE_ERROR_NONE;
}));
if (descriptors.empty() == false) {
for (const auto& descriptor : descriptors.front()) {
DiscoveredCharacteristicDescriptor discovered_descriptor(
&_gatt_client,
_connection_handle,
descriptor.first,
descriptor.second
);
//Log::info() << "expect _descriptor_cb(" << _connection_handle << ", " << descriptor.first << ", " << descriptor.second << ")" << std::endl;
EXPECT_CALL(
_descriptor_cb, call(AllOf(
ResultOf(get_characteristic, _characteristic),
ResultOf(get_descriptor, discovered_descriptor)
))
);
}
}
if (descriptors.empty() ||
std::any_of(
begin(descriptors.front()),
end(descriptors.front()),
[&](auto& val) { return val.first == _last_handle; }
)
) {
//Log::info() << "expect termination" << std::endl;
EXPECT_CALL(
_termination_cb, call(Pointee(CharacteristicDescriptorDiscovery::TerminationCallbackParams_t {
_characteristic,
BLE_ERROR_NONE,
0x00
}))
);
break;
} else {
current_handle = descriptors.front().back().first + 1;
descriptors.erase(begin(descriptors));
}
}
ble_error_t err = _gatt_client.discoverCharacteristicDescriptors(
_characteristic,
makeFunctionPointer(&_descriptor_cb, &descriptor_callback_t::call),
makeFunctionPointer(&_termination_cb, &descriptor_termination_callback_t::call)
);
EXPECT_EQ(err, BLE_ERROR_NONE);
}
// Instantiation of the tests cases relying on the parametric fixture
INSTANTIATE_TEST_CASE_P(
TestGattClientDescriptorDiscoveryP_combination,
TestGattClientDescriptorDiscoveryP,
::testing::Values(
// single transaction, single 16 bit value in the transaction, ends with error
test_param_t {
0x1000,
0x1100,
{
{
{ 0x1001, UUID(0xFFAA) }
}
}
},
// single transaction, single 16 bit value in the transaction, ends without error
test_param_t {
0x1000,
0x1001,
{
{
{ 0x1001, UUID(0xFFAA) }
}
}
},
// single transaction, single 128 bit value in the transaction, ends with error
test_param_t {
0x1000,
0x1100,
{
{
{ 0x1001, UUID("1881e01d-02af-41e9-abe9-bc940c09ca65") }
}
}
},
// single transaction, single 128 bit value in the transaction, ends without error
test_param_t {
0x1000,
0x1001,
{
{
{ 0x1001, UUID("8a239fd3-61a3-44a4-8b7c-2db9a9baa3c8") }
}
}
},
// single transaction, multiple 16 bit value in the transaction, ends with error
test_param_t {
0x1000,
0x1100,
{
{
{ 0x1001, UUID(0xFFAA) },
{ 0x1020, UUID(0xFFAB) },
{ 0x1030, UUID(0xFFAC) },
{ 0x1040, UUID(0xFFAD) }
}
}
},
// single transaction, multiple 16 bit value in the transaction, ends without error
test_param_t {
0x1000,
0x1040,
{
{
{ 0x1001, UUID(0xFFAA) },
{ 0x1020, UUID(0xFFAB) },
{ 0x1030, UUID(0xFFAC) },
{ 0x1040, UUID(0xFFAD) }
}
}
},
// single transaction, multiple 128 bit value in the transaction, ends with error
test_param_t {
0x1000,
0x1100,
{
{
{ 0x1001, UUID("0b20ef0c-578b-4b8a-8c59-065d4aff5b2e") },
{ 0x1020, UUID("66ef3556-8889-4741-adfc-c89d7ff22710") },
{ 0x1030, UUID("96a16d34-46d6-4081-82c3-25420ba01e5b") },
{ 0x1040, UUID("86c7c947-c079-46e4-8bc4-7bfc011b7ffe") }
}
}
},
// single transaction, multiple 128 bit value in the transaction, ends without error
test_param_t {
0x1000,
0x1040,
{
{
{ 0x1001, UUID("0b20ef0c-578b-4b8a-8c59-065d4aff5b2e") },
{ 0x1020, UUID("66ef3556-8889-4741-adfc-c89d7ff22710") },
{ 0x1030, UUID("96a16d34-46d6-4081-82c3-25420ba01e5b") },
{ 0x1040, UUID("86c7c947-c079-46e4-8bc4-7bfc011b7ffe") }
}
}
},
// multiple transaction, single 16 bit value in the transaction, ends with error
test_param_t {
0x1000,
0x1100,
{
{
{ 0x1001, UUID(0xFFAA) }
},
{
{ 0x1020, UUID(0xFFAB) }
},
{
{ 0x1030, UUID(0xFFAC) }
}
}
},
// single transaction, single 16 bit value in the transaction, ends without error
test_param_t {
0x1000,
0x1030,
{
{
{ 0x1001, UUID(0xFFAA) }
},
{
{ 0x1020, UUID(0xFFAB) }
},
{
{ 0x1030, UUID(0xFFAC) }
}
}
},
// multiple transaction, single 128 bit value in the transaction, ends with error
test_param_t {
0x1000,
0x1100,
{
{
{ 0x1001, UUID("1881e01d-02af-41e9-abe9-bc940c09ca65") }
},
{
{ 0x1015, UUID("0eb7f338-cd2a-4220-9f41-b61d95485b8d") }
},
{
{ 0x1050, UUID("ac77d105-73eb-4cfd-959e-c191feb592b8") }
}
}
},
// multiple transaction, single 128 bit value in the transaction, ends without error
test_param_t {
0x1000,
0x1050,
{
{
{ 0x1001, UUID("1881e01d-02af-41e9-abe9-bc940c09ca65") }
},
{
{ 0x1015, UUID("0eb7f338-cd2a-4220-9f41-b61d95485b8d") }
},
{
{ 0x1050, UUID("ac77d105-73eb-4cfd-959e-c191feb592b8") }
}
}
},
// multiple transaction, multiple 16 bit value in the transaction, ends with error
test_param_t {
0x1000,
0x1100,
{
{
{ 0x1001, UUID(0xFFAA) },
{ 0x1020, UUID(0xFFAB) }
},
{
{ 0x1030, UUID(0xFFAC) },
{ 0x1040, UUID(0xFFAD) }
},
{
{ 0x1055, UUID(0xFFAE) },
{ 0x1075, UUID(0xFFAF) }
}
}
},
// multiple transaction, multiple 16 bit value in the transaction, ends without error
test_param_t {
0x1000,
0x1075,
{
{
{ 0x1001, UUID(0xFFAA) },
{ 0x1020, UUID(0xFFAB) }
},
{
{ 0x1030, UUID(0xFFAC) },
{ 0x1040, UUID(0xFFAD) }
},
{
{ 0x1055, UUID(0xFFAE) },
{ 0x1075, UUID(0xFFAF) }
}
}
},
// multiple transaction, multiple 128 bit value in the transaction, ends with error
test_param_t {
0x1000,
0x1100,
{
{
{ 0x1001, UUID("0b20ef0c-578b-4b8a-8c59-065d4aff5b2e") }
},
{
{ 0x1020, UUID("66ef3556-8889-4741-adfc-c89d7ff22710") },
{ 0x1030, UUID("96a16d34-46d6-4081-82c3-25420ba01e5b") },
},
{
{ 0x1040, UUID("86c7c947-c079-46e4-8bc4-7bfc011b7ffe") }
}
}
},
// multiple transaction, multiple 128 bit value in the transaction, ends without error
test_param_t {
0x1000,
0x1040,
{
{
{ 0x1001, UUID("0b20ef0c-578b-4b8a-8c59-065d4aff5b2e") }
},
{
{ 0x1020, UUID("66ef3556-8889-4741-adfc-c89d7ff22710") },
{ 0x1030, UUID("96a16d34-46d6-4081-82c3-25420ba01e5b") },
},
{
{ 0x1040, UUID("86c7c947-c079-46e4-8bc4-7bfc011b7ffe") }
}
}
},
// multiple transaction, mixed UUID in the transaction, ends with error
test_param_t {
0x1000,
0x1100,
{
{
{ 0x1001, UUID(0xFFAA) }
},
{
{ 0x1020, UUID("0b20ef0c-578b-4b8a-8c59-065d4aff5b2e") }
},
{
{ 0x1025, UUID("66ef3556-8889-4741-adfc-c89d7ff22710") }
},
{
{ 0x1030, UUID(0xFFAC) }
}
}
},
// multiple transaction, mixed UUID in the transaction, ends without error
test_param_t {
0x1000,
0x1030,
{
{
{ 0x1001, UUID(0xFFAA) }
},
{
{ 0x1020, UUID("0b20ef0c-578b-4b8a-8c59-065d4aff5b2e") }
},
{
{ 0x1025, UUID("66ef3556-8889-4741-adfc-c89d7ff22710") }
},
{
{ 0x1030, UUID(0xFFAC) }
}
}
},
// multiple transaction, mixed multiple UUIDs in the transaction, ends with error
test_param_t {
0x1000,
0x1100,
{
{
{ 0x1001, UUID(0xFFAA) },
{ 0x1020, UUID(0xFFAB) }
},
{
{ 0x1025, UUID("66ef3556-8889-4741-adfc-c89d7ff22710") },
{ 0x1030, UUID("96a16d34-46d6-4081-82c3-25420ba01e5b") }
},
{
{ 0x1055, UUID(0xFFAE) },
{ 0x1075, UUID(0xFFAF) }
}
}
},
// multiple transaction, mixed multiple UUIDs in the transaction, ends without error
test_param_t {
0x1000,
0x1075,
{
{
{ 0x1001, UUID(0xFFAA) },
{ 0x1020, UUID(0xFFAB) }
},
{
{ 0x1025, UUID("66ef3556-8889-4741-adfc-c89d7ff22710") },
{ 0x1030, UUID("96a16d34-46d6-4081-82c3-25420ba01e5b") }
},
{
{ 0x1055, UUID(0xFFAE) },
{ 0x1075, UUID(0xFFAF) }
}
}
}
)
);

View File

@ -1,722 +0,0 @@
/* mbed Microcontroller Library
* Copyright (c) 2018 ARM Limited
*
* 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 <algorithm>
#include <vector>
#include <array>
#include <initializer_list>
#include <tuple>
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "ble/generic/GenericGattClient.h"
#include "ble/pal/AttServerMessage.h"
#include "ble/pal/SimpleAttServerMessage.h"
#include "ble/DiscoveredService.h"
#include "mock/MockPalGattClient.h"
#include "mock/MockCallbacks.h"
#include "util/ServerDescription.h"
#include "util/PrettyPrinter.h"
#include "util/Equality.h"
#include "util/Log.h"
// imports
using ble::pal::SimpleAttFindByTypeValueResponse;
using ble::pal::SimpleAttReadByGroupTypeResponse;
using ble::pal::SimpleAttReadByTypeResponse;
using ble::pal::AttErrorResponse;
using ble::pal::AttributeOpcode;
using ble::attribute_handle_range_t;
using ble::generic::GenericGattClient;
using ble::pal::vendor::mock::MockPalGattClient;
using ble::connection_handle_t;
using ble::attribute_handle_t;
using ble::make_const_ArrayView;
using ::testing::_;
using ::testing::Invoke;
using ::testing::InvokeWithoutArgs;
using ::testing::AllOf;
using ::testing::Property;
using ::testing::InSequence;
/*
* Parametric fixture used for service discovery.
*
* Parameters are modeled by a tuple where:
* - [0] std::tuple<bool, bool>: pair of boolean indicating the presence of the
* service callback and the characteristic callback.
* - [1] UUID: UUID used for service filtering.
* - [2] UUID: UUID used for characteristic filtering.
* - [3] server_description_t: Discovered service layout.
*/
class LaunchDiscoveryNoServiceFilter : public ::testing::TestWithParam<
std::tuple<std::tuple<bool, bool>, UUID, UUID, server_description_t>
> {
protected:
LaunchDiscoveryNoServiceFilter() :
mock_client(),
gatt_client(&mock_client),
connection_handle(0xDEAD),
termination_callback(),
has_service_cb(),
service_callback(),
has_characteristic_cb(),
characteristic_callback(),
service_filter(),
characteristic_filter(),
server_stub() {
}
// setup the test environment
virtual void SetUp() {
gatt_client.onServiceDiscoveryTermination(
makeFunctionPointer(
&termination_callback,
&termination_callback_t::call
)
);
std::tuple<bool, bool> cb_combination;
std::tie(
cb_combination,
service_filter,
characteristic_filter,
server_stub
) = GetParam();
std::tie(has_service_cb, has_characteristic_cb) = cb_combination;
}
/*
* Return a closure that sends a read by group type response to a client.
* @param[in] service_transactions The services to include in the response.
*/
auto reply_read_by_group_type(const std::vector<service_description_t>& service_transactions) {
return Invoke([service_transactions, this](connection_handle_t connection, attribute_handle_t handle) -> ble_error_t {
//Log::info() << "discover primary service (" << connection << "," << handle << ")" << std::endl;
uint8_t uuid_size = service_transactions.front().uuid.getLen();
uint8_t element_size = uuid_size + 4;
size_t data_size = element_size * service_transactions.size();
std::vector<uint8_t> result(data_size);
uint8_t* data = result.data();
for (const auto& service : service_transactions) {
memcpy(data, &service.start, 2);
data += 2;
memcpy(data, &service.end, 2);
data += 2;
memcpy(data, service.uuid.getBaseUUID(), uuid_size);
data += uuid_size;
}
mock_client.on_server_event(
connection,
SimpleAttReadByGroupTypeResponse(
element_size,
make_const_ArrayView(result.data(), result.size())
)
);
return BLE_ERROR_NONE;
});
}
/*
* Return a closure that sends a find by type value response to the client.
* @param[in] service_transactions Services to include in the response sent
* to the client.
*/
auto reply_find_by_type_value(const std::vector<service_description_t>& service_transactions) {
return Invoke([service_transactions, this](connection_handle_t connection, attribute_handle_t handle, const UUID& uuid) -> ble_error_t {
//Log::info() << "discover primary service by uuid(" << connection << "," << handle << "," << uuid << ")" << std::endl;
std::vector<uint8_t> result(service_transactions.size() * 4);
uint8_t* data = result.data();
for (const auto& service : service_transactions) {
memcpy(data, &service.start, 2);
data += 2;
memcpy(data, &service.end, 2);
data += 2;
}
mock_client.on_server_event(
connection,
SimpleAttFindByTypeValueResponse(
make_const_ArrayView(result.data(), result.size())
)
);
return BLE_ERROR_NONE;
});
}
/**
* Convert a DiscoveredCharacteristic::Properties_t into an uint8_t
*/
uint8_t properties_to_byte(DiscoveredCharacteristic::Properties_t p) {
return (
p.broadcast() << 0 |
p.read() << 1 |
p.writeWoResp() << 2 |
p.write() << 3 |
p.notify() << 4 |
p.indicate() << 5 |
p.authSignedWrite() << 6
/* extented properties ignored for now */
);
}
/**
* Return a closure that sends a read by type to a client.
* @param[in] transaction Characteristics to include in the response send to
* the client.
*/
auto reply_read_by_type(const std::vector<characteristic_description_t>& transaction) {
return Invoke([transaction, this](connection_handle_t connection, attribute_handle_range_t range) -> ble_error_t {
//Log::info() << "discover characteristic(" << connection << "," << range.begin << "," << range.end << ")" << std::endl;
size_t uuid_size = transaction.front().uuid.getLen();
uint8_t element_size = uuid_size + 5;
std::vector<uint8_t> result(element_size * transaction.size());
uint8_t* data = result.data();
for (const auto& characteristic : transaction) {
memcpy(data, &characteristic.handle, 2);
data += 2;
*data++ = properties_to_byte(characteristic.properties);
memcpy(data, &characteristic.value_handle, 2);
data += 2;
memcpy(data, characteristic.uuid.getBaseUUID(), uuid_size);
data += uuid_size;
}
mock_client.on_server_event(
connection,
SimpleAttReadByTypeResponse(
element_size,
make_const_ArrayView(result.data(), result.size())
)
);
return BLE_ERROR_NONE;
});
}
/*
* Return a closure that send an error response to the client.
* @param[in] opcode Opcode that caused the error.
* @param[in] error_code Error code.
*/
auto reply_error(AttributeOpcode opcode, AttErrorResponse::AttributeErrorCode error_code) {
return InvokeWithoutArgs([this, opcode, error_code]() -> ble_error_t {
//Log::info() << "reply error: opcode = " << (uint8_t) opcode << ", error_code = " << error_code << std::endl;
mock_client.on_server_event(
connection_handle,
AttErrorResponse(opcode, error_code)
);
return BLE_ERROR_NONE;
});
}
/*
* Set service discovery expectation when the procedure discover all services
* is used.
*/
void set_discover_all_services_expectations() {
auto services_transactions = get_services_transactions();
uint16_t next_attribute_handle = 0x0001;
for (const auto& service_transactions : services_transactions) {
//Log::info() << "expect discover_primary_service(" << connection_handle << ", " << next_attribute_handle << ")" <<std::endl;
// set expectation on the discovery function
EXPECT_CALL(
mock_client, discover_primary_service(connection_handle, next_attribute_handle)
).WillOnce(
reply_read_by_group_type(service_transactions)
);
if (!has_characteristic_cb) {
set_services_callback_expectations(service_transactions);
}
next_attribute_handle = service_transactions.back().end + 1;
}
// if counter didn't wrap then send an error
if (next_attribute_handle != 0) {
// set expectation on the discovery function
//Log::info() << "expect discover_primary_service(" << connection_handle << ", " << next_attribute_handle << ") "
//<< "to fail with opcode = " << AttributeOpcode::READ_BY_GROUP_TYPE_REQUEST << " and error = " << AttErrorResponse::ATTRIBUTE_NOT_FOUND << std::endl;
EXPECT_CALL(
mock_client, discover_primary_service(connection_handle, next_attribute_handle)
).WillOnce(
reply_error(AttributeOpcode::READ_BY_GROUP_TYPE_REQUEST, AttErrorResponse::ATTRIBUTE_NOT_FOUND)
);
}
}
/*
* Set client expectations when the discover services by UUID is used.
*/
void set_discover_services_by_uuid_expectations() {
std::vector<std::vector<uint8_t>> services_response;
auto services_transactions = get_services_transactions();
uint16_t next_attribute_handle = 0x0001;
for (const auto& transaction : services_transactions) {
//Log::info() << "expect discover_primary_service_by_service_uuid(" << connection_handle << ", " << next_attribute_handle << "," << service_filter << ")" <<std::endl;
// set expectation on the discovery function
EXPECT_CALL(
mock_client, discover_primary_service_by_service_uuid(
connection_handle,
next_attribute_handle,
service_filter
)
).WillOnce(
reply_find_by_type_value(transaction)
);
if (!has_characteristic_cb) {
set_services_callback_expectations(transaction);
}
next_attribute_handle = transaction.back().end + 1;
}
// note if last service end handle was 0xFFFF do nothing
// otherwise set a discovery expectation and reply with an error
// if counter didn't wrap then send an error
if (next_attribute_handle != 0) {
// set expectation on the discovery function
//Log::info() << "expect discover_primary_service_by_service_uuid(" << connection_handle << ", " << next_attribute_handle << "," << service_filter << ") "
//<< "to fail with opcode = " << AttributeOpcode::FIND_BY_TYPE_VALUE_REQUEST << " and error = " << AttErrorResponse::ATTRIBUTE_NOT_FOUND << std::endl;
EXPECT_CALL(
mock_client, discover_primary_service_by_service_uuid(
connection_handle, next_attribute_handle, service_filter
)
).WillOnce(
reply_error(AttributeOpcode::FIND_BY_TYPE_VALUE_REQUEST, AttErrorResponse::ATTRIBUTE_NOT_FOUND)
);
}
}
/*
* Set an expectation regarding call of the service discovery callback with
* the services @p services.
*/
void set_services_callback_expectations(const std::vector<service_description_t>& services) {
if (!has_service_cb) {
return;
}
for (const auto& service : services) {
set_service_callback_expectation(service);
}
}
/*
* Set an expectation regarding call of the service discovery callback with
* the service @p service.
*/
void set_service_callback_expectation(const service_description_t& service) {
if (!has_service_cb) {
return;
}
//Log::info() << "expect service_callback(" << service.start << ", " << service.end << "," << service.uuid << ")" <<std::endl;
EXPECT_CALL(
service_callback, call(AllOf(
Property(
&DiscoveredService::getStartHandle,
service.start
),
Property(
&DiscoveredService::getEndHandle,
service.end
),
Property(
&DiscoveredService::getUUID,
service.uuid
)
))
).WillOnce(Invoke([](const DiscoveredService* service) -> void {
//Log::info() << "service_callback(" << service->getStartHandle() << ", " << service->getEndHandle() << "," << service->getUUID() << ")" <<std::endl;
}));
}
/*
* Set expectations for characteristic discovery.
*/
void set_discover_characteristics_expectations() {
auto services = get_services_discovered();
for (const auto& service : services) {
set_service_callback_expectation(service);
auto characteristic_transactions = get_characteristics_transactions(service);
uint16_t next_attribute_handle = service.start;
characteristic_description_t previous_characteristic { };
for (const auto& characteristic_transaction : characteristic_transactions) {
//Log::info() << "expect discover_characteristics_of_a_service(" << connection_handle << ", " << next_attribute_handle << "," << service.end << ")" <<std::endl;
EXPECT_CALL(
mock_client, discover_characteristics_of_a_service(
connection_handle,
attribute_handle_range_t { next_attribute_handle, service.end }
)
).WillOnce(
reply_read_by_type(characteristic_transaction)
);
set_characteristics_callbacks_expectations(
previous_characteristic,
characteristic_transaction
);
previous_characteristic = characteristic_transaction.back();
next_attribute_handle = characteristic_transaction.back().value_handle + 1;
}
if(next_attribute_handle < service.end) {
//Log::info() << "expect discover_characteristics_of_a_service(" << connection_handle << ", " << next_attribute_handle << "," << service.end << ") "
// << "to fail with opcode = " << AttributeOpcode::READ_BY_TYPE_REQUEST << " and error = " << AttErrorResponse::ATTRIBUTE_NOT_FOUND << std::endl;
EXPECT_CALL(
mock_client, discover_characteristics_of_a_service(
connection_handle,
attribute_handle_range_t { next_attribute_handle, service.end }
)
).WillOnce(
reply_error(AttributeOpcode::READ_BY_TYPE_REQUEST, AttErrorResponse::ATTRIBUTE_NOT_FOUND)
);
set_characteristic_callback_expectation(previous_characteristic);
}
}
}
void set_characteristics_callbacks_expectations(characteristic_description_t previous_characteristic, std::vector<characteristic_description_t> transaction) {
if (transaction.empty() == false) {
//Log::info() << "pop last characteristic in transaction" <<std::endl;
transaction.pop_back();
}
if (previous_characteristic != characteristic_description_t()) {
//Log::info() << "add previous characteristic" <<std::endl;
transaction.insert(transaction.begin(), previous_characteristic);
}
for (const auto& characteristic : transaction) {
set_characteristic_callback_expectation(characteristic);
}
}
void set_characteristic_callback_expectation(characteristic_description_t characteristic) {
if (!has_characteristic_cb) {
return;
}
if (characteristic_filter != UUID() && characteristic_filter != characteristic.uuid) {
return;
}
//Log::info() << "expect characteristic_callback(" << characteristic.uuid << ", " << characteristic.handle << "," << characteristic.value_handle << ")" <<std::endl;
EXPECT_CALL(
characteristic_callback,
call(AllOf(
Property(
&DiscoveredCharacteristic::getUUID,
characteristic.uuid
),
Property(
&DiscoveredCharacteristic::getDeclHandle,
characteristic.handle
),
Property(
&DiscoveredCharacteristic::getValueHandle,
characteristic.value_handle
),
Property(
&DiscoveredCharacteristic::getConnectionHandle,
connection_handle
)
))
).WillOnce(Invoke([](const DiscoveredCharacteristic* characteristic) -> void {
//Log::info() << "characteristic_callback(" << characteristic->getDeclHandle() << ", " << characteristic->getValueHandle() << "," << characteristic->getUUID() << ")" <<std::endl;
}));
}
/*
* Compute the transactions involved during the service discovery process.
*/
std::vector<std::vector<service_description_t>> get_services_transactions() {
std::vector<service_description_t> working_set = get_services_discovered();
std::vector<std::vector<service_description_t>> result;
for (const auto& service : working_set) {
if(result.empty()) {
result.push_back(std::vector<service_description_t>());
}
auto& last_group = result.back();
if (last_group.empty()) {
last_group.push_back(service);
} else {
auto last_group_uuid = last_group.front().uuid.shortOrLong();
auto last_group_size = last_group.size();
if (last_group_uuid != service.uuid.shortOrLong()) {
result.push_back(std::vector<service_description_t> { service });
} else {
if (last_group_uuid == UUID::UUID_TYPE_SHORT && last_group_size < 4) {
last_group.push_back(service);
} else {
result.push_back(std::vector<service_description_t> { service });
}
}
}
}
return result;
}
/*
* Compute the list of services discovered during service discovery.
*/
std::vector<service_description_t> get_services_discovered() {
std::vector<service_description_t> working_set;
if (service_filter != UUID()) {
for (const auto& service : server_stub.services) {
if (service.uuid == service_filter) {
working_set.push_back(service);
}
}
} else {
working_set = server_stub.services;
}
return working_set;
}
/*
* Compute the transactions present during the characteristic discovery process.
*/
std::vector<std::vector<characteristic_description_t>> get_characteristics_transactions(const service_description_t& service) {
std::vector<std::vector<characteristic_description_t>> transactions;
for (const auto& characteristic : service.characteristics) {
if(transactions.empty()) {
transactions.push_back(
std::vector<characteristic_description_t> { characteristic }
);
} else {
auto& last_group = transactions.back();
auto last_group_uuid = last_group.front().uuid.shortOrLong();
auto last_group_size = last_group.size();
if (last_group_uuid != service.uuid.shortOrLong()) {
transactions.push_back(std::vector<characteristic_description_t> { characteristic });
} else {
if (last_group_uuid == UUID::UUID_TYPE_SHORT && last_group_size < 3) {
last_group.push_back(characteristic);
} else {
transactions.push_back(std::vector<characteristic_description_t> { characteristic });
}
}
}
}
return transactions;
}
MockPalGattClient mock_client;
GenericGattClient gatt_client;
const Gap::Handle_t connection_handle;
termination_callback_t termination_callback;
bool has_service_cb;
service_callback_t service_callback;
bool has_characteristic_cb;
characteristic_callback_t characteristic_callback;
UUID service_filter;
UUID characteristic_filter;
server_description_t server_stub;
};
TEST_P(LaunchDiscoveryNoServiceFilter, regular) {
/////////////////////////////
// Install default calls
ON_CALL(
mock_client, discover_primary_service(_, _)
).WillByDefault(Invoke([](connection_handle_t connection, attribute_handle_t handle) -> ble_error_t {
//Log::info() << "default discover primary service (" << connection << "," << handle << ")" << std::endl;
return BLE_ERROR_NONE;
}));
ON_CALL(
mock_client, discover_primary_service_by_service_uuid(_, _, _)
).WillByDefault(Invoke([](connection_handle_t connection, attribute_handle_t handle, const UUID& uuid) -> ble_error_t {
//Log::info() << "default discover primary service by service uuid(" << connection << "," << handle << ", " << uuid << ")" << std::endl;
return BLE_ERROR_NONE;
}));
ON_CALL(
mock_client, discover_characteristics_of_a_service(_, _)
).WillByDefault(Invoke([](connection_handle_t connection, attribute_handle_range_t handle) -> ble_error_t {
//Log::info() << "default discover characteristic of a service(" << connection << "," << handle << ")" << std::endl;
return BLE_ERROR_NONE;
}));
if (has_service_cb) {
ON_CALL(
service_callback, call(_)
).WillByDefault(Invoke([](const DiscoveredService* service) -> void {
//Log::info() << "default service_callback(" << service->getEndHandle() << ", " << service->getEndHandle() << ", " << service->getUUID() << ")" << std::endl;
}));
}
if (has_characteristic_cb) {
ON_CALL(
characteristic_callback, call(_)
).WillByDefault(Invoke([](const DiscoveredCharacteristic* characteristic) -> void {
//Log::info() << "default characteristic_callback(" << characteristic->getDeclHandle() << ", " << characteristic->getValueHandle() << ", " << characteristic->getUUID() << ")" << std::endl;
}));
}
/////////////////////////////
// Install expectations
{
InSequence seq;
if (service_filter == UUID()) {
set_discover_all_services_expectations();
} else {
set_discover_services_by_uuid_expectations();
}
if (has_characteristic_cb) {
set_discover_characteristics_expectations();
}
EXPECT_CALL(termination_callback, call(connection_handle));
}
/////////////////////////////
// Launch the discovery process.
ble_error_t err = gatt_client.launchServiceDiscovery(
connection_handle,
has_service_cb ?
makeFunctionPointer(
&service_callback, &decltype(service_callback)::call
) : NULL,
has_characteristic_cb ?
makeFunctionPointer(
&characteristic_callback, &decltype(characteristic_callback)::call
) : NULL,
service_filter,
characteristic_filter
);
EXPECT_EQ(BLE_ERROR_NONE, err);
}
INSTANTIATE_TEST_CASE_P(
GattClient_launch_discovery_no_service_filter,
LaunchDiscoveryNoServiceFilter,
// Yield all combination of each generator
::testing::Combine(
// service cb generator
::testing::Values(
std::tuple<bool, bool>(true, false),
std::tuple<bool, bool>(false, true),
std::tuple<bool, bool>(true, true)
),
// service UUID filter generator
::testing::Values(UUID(), UUID(0x1452), UUID("a3d1495f-dba7-4441-99f2-d0a20f663422")),
// characteristic UUID filter generator
::testing::Values(UUID(), UUID(0xBEEF), UUID("1f551ee3-aef4-4719-8c52-8b419fc4ac01")),
// server layout generator.
::testing::Values(
server_description_t { },
server_description_t {
{
0x0001,
0x0030,
UUID(0xAAAA),
{
{ 0x0002, { 0 }, UUID(0xBBBA) },
{ 0x0006, { 1, 0 }, UUID(0xBBBB) },
{ 0x0012, { 1, 0 }, UUID(0xBBBC) },
{ 0x0015, { 1, 1, 1, 0 }, UUID(0xBBBD) }
},
},
{
0x0031,
0x0060,
UUID(0xAAAB),
{
{ 0x0032, { 0 }, UUID(0xCBBA) },
{ 0x0036, { 1, 0 }, UUID(0xCBBB) },
{ 0x0042, { 1, 0 }, UUID(0xCBBC) },
{ 0x0050, { 1, 1, 1, 0 }, UUID(0xCBBD) }
},
},
{
0x0061,
0x0090,
UUID(0xAAAB),
{
{ 0x0062, { 0 }, UUID(0xDBBA) },
{ 0x0066, { 1, 0 }, UUID(0xDBBB) },
{ 0x0072, { 1, 0 }, UUID(0xDBBC) },
{ 0x0082, { 1, 1, 1, 0 }, UUID(0xDBBD) }
}
}
},
server_description_t {
{
0x0001,
0x0030,
UUID(0xAAAA),
{
{ 0x0002, { 0 }, UUID(0xBBBA) },
{ 0x0006, { 1, 0 }, UUID(0xBBBB) },
{ 0x0012, { 1, 0 }, UUID(0xBBBC) },
{ 0x0024, { 1, 1, 1, 0 }, UUID(0xBBBC) }
},
},
{
0x0031,
0x0060,
UUID(0xAAAB),
{
{ 0x0032, { 0 }, UUID(0xCBBA) },
{ 0x0036, { 1, 0 }, UUID(0xCBBB) },
{ 0x0042, { 1, 0 }, UUID(0xCBBC) },
{ 0x0045, { 1, 1, 1, 0 }, UUID(0xCBBC) }
},
},
{
0x0061,
0xFFFF,
UUID(0xAAAB),
{
{ 0x0062, { 0 }, UUID(0xDBBA) },
{ 0x0066, { 1, 0 }, UUID(0xDBBB) },
{ 0x0072, { 1, 0 }, UUID(0xDBBC) },
{ 0x0082, { 1, 1, 1, 0 }, UUID(0xDBBC) }
}
}
}
)
)
);

View File

@ -1,178 +0,0 @@
/* mbed Microcontroller Library
* Copyright (c) 2018 ARM Limited
*
* 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 <vector>
#include <array>
#include <initializer_list>
#include <tuple>
#include <cstddef>
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "ble/generic/GenericGattClient.h"
#include "ble/pal/AttServerMessage.h"
#include "ble/pal/SimpleAttServerMessage.h"
#include "ble/DiscoveredService.h"
#include "mock/MockCallbacks.h"
#include "mock/MockPalGattClient.h"
using std::nullptr_t;
using ble::generic::GenericGattClient;
using ble::pal::vendor::mock::MockPalGattClient;
using ::testing::_;
/*
* Parametric fixture used to test service discovery when no callback is registered.
* Parameters are:
* - [0]: service UUID filter
* - [1]: characteristic UUID filter
*/
class LaunchDiscoveryNoCb : public ::testing::TestWithParam<std::tuple<UUID, UUID>> {
protected:
typedef std::tuple<UUID, UUID> parameters_t;
LaunchDiscoveryNoCb() :
_mock_client(),
_gatt_client(&_mock_client),
_connection_handle(0xDEAD),
_termination_callback(),
_service_cb(),
_characteristic_cb(),
_service_filter(),
_characteristic_filter() {
}
virtual void SetUp() {
_gatt_client.onServiceDiscoveryTermination(
makeFunctionPointer(
&_termination_callback,
&termination_callback_t::call
)
);
std::tie(_service_filter, _characteristic_filter) = GetParam();
}
MockPalGattClient _mock_client;
GenericGattClient _gatt_client;
const Gap::Handle_t _connection_handle;
termination_callback_t _termination_callback;
nullptr_t _service_cb;
nullptr_t _characteristic_cb;
UUID _service_filter;
UUID _characteristic_filter;
};
/* Given initialised GattClient
* When the service discovery is launched with service and characteristic
* callbacks set to NULL.
* Then
* - The function shall return BLE_ERROR_NONE
* - No call to any discovery function shall have been made
* - The termination callback shall have been called once with the connection
* handle used to launch the discovery.
*/
// no pending transaction
TEST_P(LaunchDiscoveryNoCb, shall_never_launch_any_discovery) {
EXPECT_FALSE(_gatt_client.isServiceDiscoveryActive());
// no call on _mock_client expected
EXPECT_CALL(_mock_client, discover_primary_service(_, _)).Times(0);
EXPECT_CALL(_mock_client, discover_primary_service_by_service_uuid(_, _, _)).Times(0);
EXPECT_CALL(_mock_client, find_included_service(_, _)).Times(0);
EXPECT_CALL(_mock_client, discover_characteristics_of_a_service(_, _)).Times(0);
EXPECT_CALL(_mock_client, discover_characteristics_descriptors(_, _)).Times(0);
// termination callback shall be call once with connection handle as parameter
EXPECT_CALL(_termination_callback, call(_)).Times(0);
EXPECT_CALL(_termination_callback, call(_connection_handle)).Times(1);
ble_error_t err = _gatt_client.launchServiceDiscovery(
_connection_handle,
_service_cb,
_characteristic_cb,
_service_filter,
_characteristic_filter
);
EXPECT_EQ(BLE_ERROR_NONE, err);
EXPECT_FALSE(_gatt_client.isServiceDiscoveryActive());
}
// no CB
// pending transaction
TEST_P(LaunchDiscoveryNoCb, shall_not_change_discovery_status) {
EXPECT_FALSE(_gatt_client.isServiceDiscoveryActive());
// launch a discovery on another connection
const Gap::Handle_t dummy_connection_handle = _connection_handle + 1;
void (*dummy_service_cb)(const DiscoveredService*) = [](const DiscoveredService *) { };
EXPECT_CALL(_mock_client, discover_primary_service(dummy_connection_handle, _))
.WillOnce(::testing::Return(BLE_ERROR_NONE));
_gatt_client.launchServiceDiscovery(
dummy_connection_handle,
dummy_service_cb,
NULL,
UUID((uint16_t) 0),
UUID((uint16_t) 0)
);
EXPECT_TRUE(_gatt_client.isServiceDiscoveryActive());
// no call on _mock_client expected
EXPECT_CALL(_mock_client, discover_primary_service(_, _)).Times(0);
EXPECT_CALL(_mock_client, discover_primary_service_by_service_uuid(_, _, _)).Times(0);
EXPECT_CALL(_mock_client, find_included_service(_, _)).Times(0);
EXPECT_CALL(_mock_client, discover_characteristics_of_a_service(_, _)).Times(0);
EXPECT_CALL(_mock_client, discover_characteristics_descriptors(_, _)).Times(0);
// termination callback shall be call once with connection handle as parameter
EXPECT_CALL(_termination_callback, call(_)).Times(0);
EXPECT_CALL(_termination_callback, call(_connection_handle)).Times(1);
ble_error_t err = _gatt_client.launchServiceDiscovery(
_connection_handle,
_service_cb,
_characteristic_cb,
_service_filter,
_characteristic_filter
);
EXPECT_EQ(BLE_ERROR_NONE, err);
EXPECT_TRUE(_gatt_client.isServiceDiscoveryActive());
}
// Instantiate tests cases with the given parameters
INSTANTIATE_TEST_CASE_P(
GattClient_launch_discovery_no_cb,
LaunchDiscoveryNoCb,
// Yield combination of each generator value
::testing::Combine(
// service UUID filter
::testing::Values(UUID(), UUID(0x1452), UUID("a3d1495f-dba7-4441-99f2-d0a20f663422")),
// characteristic UUID filter
::testing::Values(UUID(), UUID(0xBEEF), UUID("1f551ee3-aef4-4719-8c52-8b419fc4ac01"))
)
);

View File

@ -1,570 +0,0 @@
/* mbed Microcontroller Library
* Copyright (c) 2018 ARM Limited
*
* 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 <algorithm>
#include <vector>
#include <array>
#include <initializer_list>
#include <tuple>
#include <cstdlib>
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "ble/generic/GenericGattClient.h"
#include "ble/pal/AttServerMessage.h"
#include "ble/pal/SimpleAttServerMessage.h"
#include "ble/DiscoveredService.h"
#include "mock/MockPalGattClient.h"
#include "mock/MockCallbacks.h"
#include "util/PrettyPrinter.h"
#include "util/Equality.h"
using ble::pal::AttErrorResponse;
using ble::pal::AttributeOpcode;
using ble::pal::AttReadResponse;
using ble::pal::AttReadBlobResponse;
using ble::generic::GenericGattClient;
using ble::pal::vendor::mock::MockPalGattClient;
using ble::connection_handle_t;
using ble::attribute_handle_t;
using ble::make_const_ArrayView;
using ::testing::_;
using ::testing::Invoke;
using ::testing::InSequence;
using ::testing::Mock;
using ::testing::Pointee;
using std::vector;
using std::tuple;
static vector<uint8_t> make_char_value(uint16_t length) {
vector<uint8_t> characteristic_value(length);
for (auto& byte : characteristic_value) {
byte = std::rand();
}
return characteristic_value;
}
/*
* fixture used to test GattClient::read.
*/
class TestGattClientRead : public ::testing::Test {
protected:
TestGattClientRead() :
_mock_client(),
_gatt_client(&_mock_client),
_connection_handle(0xDEAD),
_attribute_handle(0x5645),
_read_cb(),
_mtu_size(23) {
}
virtual void SetUp() {
_gatt_client.onDataRead(
makeFunctionPointer(&_read_cb, &read_callback_t::call)
);
ON_CALL(_mock_client, get_mtu_size(_connection_handle, _)).
WillByDefault(Invoke([&](auto, auto& size){
size = this->_mtu_size;
return BLE_ERROR_NONE;
}));
}
void set_mtu_size_stub() {
EXPECT_CALL(_mock_client, get_mtu_size(_connection_handle, _))
.WillRepeatedly(::testing::DoDefault());
}
MockPalGattClient _mock_client;
GenericGattClient _gatt_client;
const Gap::Handle_t _connection_handle;
uint16_t _attribute_handle;
read_callback_t _read_cb;
uint16_t _mtu_size;
};
/*
* Given an attribute on a server with a value with a length less than ATT_MTU - 1.
* When the client issue tries to read is with GattClient::read with an offset
* of 0.
* Then:
* - The function read_attribute_value from the pal is called with
* connection handle and attribute handle used in GattClient::read.
* - The pal::GattClient fire an AttReadResponse containing the value of the
* attribute.
* - The generic GattClient invoke the read handler with a content equal to
* the value received and an error _status set to BLE_ERROR_NONE.
*/
TEST_F(TestGattClientRead, read_short_characteristic_without_offset_shall_succeed) {
uint16_t offset = 0; // force offset to 0 for this test
auto char_value = make_char_value(1000);
// iterate over possible MTU size
for (_mtu_size = 23; _mtu_size < 517; _mtu_size += 5) {
// iterate over possible characteristic value size
for (uint16_t char_len = 0; char_len < (_mtu_size - 1); ++char_len) {
set_mtu_size_stub();
InSequence seq;
EXPECT_CALL(
_mock_client, read_attribute_value(_connection_handle, _attribute_handle)
).WillOnce(Invoke([&](auto connection, auto attribute) {
_mock_client.on_server_event(
connection,
AttReadResponse(
make_const_ArrayView(char_value.data(), char_len)
)
);
return BLE_ERROR_NONE;
}));
EXPECT_CALL(_read_cb, call(Pointee(GattReadCallbackParams {
_connection_handle,
_attribute_handle,
offset,
(uint16_t) char_len,
char_value.data(),
BLE_ERROR_NONE
})));
ble_error_t err = _gatt_client.read(_connection_handle, _attribute_handle, offset);
EXPECT_EQ(err, BLE_ERROR_NONE);
bool can_continue = Mock::VerifyAndClearExpectations(&_read_cb) && Mock::VerifyAndClearExpectations(&_mock_client);
if (!can_continue) {
return;
}
}
}
}
/*
* Given an attribute on a server with a value with a length less than ATT_MTU - 1.
* When the client issue tries to reads it with GattClient::read with an offset
* not equal to 0 and in the range of the attribute length.
* Then:
* - The function read_attribute_blob from the pal is called with
* connection handle, the attribute handle and the offset used in
* GattClient::read.
* - The pal::GattClient fire an AttErrorresponse with:
* * opcode equal to READ_BLOB_REQUEST
* * _error_code equal to ATTRIBUTE_NOT_LONG
* - The generic GattClient invoke the read handler with the _status set to
* BLE_ERROR_PARAM_OUT_OF_RANGE and an _error_code set to ATTRIBUTE_NOT_LONG.
*/
TEST_F(TestGattClientRead, read_short_characteristic_with_offset_shall_fail) {
// iterate over possible MTU size
for (_mtu_size = 23; _mtu_size < 517; _mtu_size+=10) {
// iterate over possible characteristic value size
for (uint16_t char_len = 1; char_len < (_mtu_size - 1); char_len += 10) {
// iterate over possible offsets
for (uint16_t offset = 1; offset <= char_len; offset += 10) {
InSequence seq;
EXPECT_CALL(
_mock_client, read_attribute_blob(_connection_handle, _attribute_handle, offset)
).WillOnce(Invoke([&](auto connection, auto attribute, auto off) {
_mock_client.on_server_event(
connection,
AttErrorResponse(
AttributeOpcode::READ_BLOB_REQUEST,
attribute,
AttErrorResponse::ATTRIBUTE_NOT_LONG
)
);
return BLE_ERROR_NONE;
}));
EXPECT_CALL(_read_cb, call(Pointee(GattReadCallbackParams {
_connection_handle,
_attribute_handle,
offset,
AttErrorResponse::ATTRIBUTE_NOT_LONG,
NULL,
BLE_ERROR_PARAM_OUT_OF_RANGE
})));
ble_error_t err = _gatt_client.read(_connection_handle, _attribute_handle, offset);
EXPECT_EQ(err, BLE_ERROR_NONE);
bool can_continue = Mock::VerifyAndClearExpectations(&_read_cb) && Mock::VerifyAndClearExpectations(&_mock_client);
if (!can_continue) {
return;
}
}
}
}
}
/*
* Given an attribute on a server with a value with a length less than ATT_MTU - 1.
* When the client tries to reads it with GattClient::read with an offset
* out of the range of the attribute length.
* Then:
* - The function read_attribute_blob from the pal is called with
* connection handle, the attribute handle and the offset used in
* GattClient::read.
* - The pal::GattClient fire an AttErrorresponse with:
* * opcode equal to READ_BLOB_REQUEST
* * _error_code equal to INVALID_OFFSET
* - The generic GattClient invoke the read handler with the _status set to
* BLE_ERROR_PARAM_OUT_OF_RANGE and an _error_code set to INVALID_OFFSET.
*/
TEST_F(TestGattClientRead, read_with_out_of_range_offset_shall_fail) {
// iterate over possible MTU size
for (_mtu_size = 23; _mtu_size < 517; _mtu_size += 10) {
// iterate over possible characteristic value size
for (uint16_t char_len = 1; char_len < (_mtu_size - 1); char_len += 10) {
// iterate over possible offsets
for (uint16_t offset = char_len + 1; offset < 518; offset += 10) {
InSequence seq;
EXPECT_CALL(
_mock_client, read_attribute_blob(_connection_handle, _attribute_handle, offset)
).WillOnce(Invoke([&](auto connection, auto attribute, auto off) {
_mock_client.on_server_event(
connection,
AttErrorResponse(
AttributeOpcode::READ_BLOB_REQUEST,
attribute,
AttErrorResponse::INVALID_OFFSET
)
);
return BLE_ERROR_NONE;
}));
EXPECT_CALL(_read_cb, call(Pointee(GattReadCallbackParams {
_connection_handle,
_attribute_handle,
offset,
AttErrorResponse::INVALID_OFFSET,
NULL,
BLE_ERROR_PARAM_OUT_OF_RANGE,
})));
ble_error_t err = _gatt_client.read(_connection_handle, _attribute_handle, offset);
EXPECT_EQ(err, BLE_ERROR_NONE);
bool can_continue = Mock::VerifyAndClearExpectations(&_read_cb) && Mock::VerifyAndClearExpectations(&_mock_client);
if (!can_continue) {
return;
}
}
}
}
}
/*
* Parametric fixture used to test error generated during GattClient::read.
* Parameters are:
* - [0] The attribute error code
* - [1] Expected status returned in the read callback.
*/
class TestGattClientReadAttributeError :
public TestGattClientRead,
public ::testing::WithParamInterface<tuple<AttErrorResponse::AttributeErrorCode, ble_error_t>> {
protected:
TestGattClientReadAttributeError() :
TestGattClientRead(),
_error_code((AttErrorResponse::AttributeErrorCode) 0x00),
_status(BLE_ERROR_NONE) {
}
virtual void SetUp() {
TestGattClientRead::SetUp();
std::tie(_error_code, _status) = GetParam();
}
AttErrorResponse::AttributeErrorCode _error_code;
ble_error_t _status;
};
/*
* Given an attribute which cannot be read.
* When the client tries to reads it with GattClient::read with an offset
* of 0
* Then:
* - The function read_attribute_value from the pal is called with
* connection handle, the attribute handle in GattClient::read.
* - The pal::GattClient fire an AttErrorresponse with:
* * opcode equal to READ_REQUEST
* * _error_code equal to the expected error
* - The generic GattClient invoke the read handler with the _status set to
* the expected _status and an _error_code set to error code in the
* AttErrorResponse.
*/
TEST_P(TestGattClientReadAttributeError, read_no_offset) {
uint16_t offset = 0;
InSequence seq;
EXPECT_CALL(
_mock_client, read_attribute_value(_connection_handle, _attribute_handle)
).WillOnce(Invoke([&](auto connection, auto attribute) {
_mock_client.on_server_event(
connection,
AttErrorResponse(
AttributeOpcode::READ_REQUEST,
attribute,
_error_code
)
);
return BLE_ERROR_NONE;
}));
EXPECT_CALL(_read_cb, call(Pointee(GattReadCallbackParams {
_connection_handle,
_attribute_handle,
offset,
_error_code,
/* data */ NULL,
_status
})));
ble_error_t err = _gatt_client.read(_connection_handle, _attribute_handle, offset);
EXPECT_EQ(err, BLE_ERROR_NONE);
}
/*
* Given an attribute which cannot be read.
* When the client tries to reads it with GattClient::read with an offset
* of 0
* Then:
* - The function read_attribute_blob from the pal is called with
* connection handle, the attribute handle and the offset passed to
* GattClient::read.
* - The pal::GattClient fire an AttErrorresponse with:
* * opcode equal to READ_BLOB_REQUEST
* * _error_code equal to the expected error
* - The generic GattClient invoke the read handler with the _status set to
* the expected _status and an _error_code set to error code in the
* AttErrorResponse.
*/
TEST_P(TestGattClientReadAttributeError, read_with_offset) {
uint16_t offset = 10;
InSequence seq;
EXPECT_CALL(
_mock_client, read_attribute_blob(_connection_handle, _attribute_handle, offset)
).WillOnce(Invoke([&](auto connection, auto attribute, auto off) {
_mock_client.on_server_event(
connection,
AttErrorResponse(
AttributeOpcode::READ_BLOB_REQUEST,
attribute,
_error_code
)
);
return BLE_ERROR_NONE;
}));
EXPECT_CALL(_read_cb, call(Pointee(GattReadCallbackParams {
_connection_handle,
_attribute_handle,
offset,
_error_code,
/* data */ NULL,
_status
})));
ble_error_t err = _gatt_client.read(_connection_handle, _attribute_handle, offset);
EXPECT_EQ(err, BLE_ERROR_NONE);
}
// Instantiate test cases using TestGattClientReadAttributeError
INSTANTIATE_TEST_CASE_P(
TestGattClientReadAttributeError_combination,
TestGattClientReadAttributeError,
::testing::Values(
std::make_tuple(AttErrorResponse::INVALID_HANDLE, BLE_ERROR_INVALID_PARAM),
std::make_tuple(AttErrorResponse::INSUFFICIENT_AUTHORIZATION, BLE_ERROR_INVALID_STATE),
std::make_tuple(AttErrorResponse::INSUFFICIENT_AUTHENTICATION, BLE_ERROR_INVALID_STATE),
std::make_tuple(AttErrorResponse::INSUFFICIENT_ENCRYPTION_KEY_SIZE, BLE_ERROR_INVALID_STATE),
std::make_tuple(AttErrorResponse::INSUFFICIENT_ENCRYPTION, BLE_ERROR_INVALID_STATE),
std::make_tuple(AttErrorResponse::READ_NOT_PERMITTED, BLE_ERROR_OPERATION_NOT_PERMITTED)
)
);
/*
* Given a readable attribute with a value longer than ATT_MTU - 2.
* When the GattClient::read is called without offset
* Then:
* - The client call the pal function read_attribute_value with the connection
* handle and the the attribute handle used in GattClient::read.
* When the pal::GattClient fire an AttReadResponse containing the first
* (ATT_MTU - 1) bytes of the attribute value.
* Then:
* - The client call the function read_attribute_blob with the connection
* handle and the attribute handle used in GattClient::read. The offset is
* equal of the number of bytes read in the characteristic.
* When the pal::Client fire an AttReadBlobResponse containing the partial value
* of the characteristic starting at the offset requested. If the length of
* the remaining bytes is greater than ATT_MTU - 1 then the length of the
* partial value in the response shall be ATT_MTU - 1. Otherwise it is the
* length of the remaining bytes.
* Then:
* - If the value received by the client has a len greater than ATT_MTU - 1.
* Then the client issue a new read_attribute_blob with an updated index.
* - Else the read callback is called with the value of the attribute read.
*/
TEST_F(TestGattClientRead, read_long_characteristic_without_offset_shall_succeed) {
const uint16_t offset = 0; // force offset to 0 for this test
auto char_value = make_char_value(517 * 6);
// iterate over possible MTU size
for (_mtu_size = 23; _mtu_size < 517; _mtu_size += 5) {
// iterate over possible characteristic value size
for (uint16_t char_len = (_mtu_size - 1); char_len < (_mtu_size * 6); char_len += 10) {
set_mtu_size_stub();
InSequence seq;
EXPECT_CALL(
_mock_client, read_attribute_value(_connection_handle, _attribute_handle)
).WillOnce(Invoke([&](auto connection, auto attribute) {
_mock_client.on_server_event(
connection,
AttReadResponse(
make_const_ArrayView(char_value.data(), _mtu_size - 1)
)
);
return BLE_ERROR_NONE;
}));
for(uint16_t blob_offset = (_mtu_size - 1); blob_offset <= char_len; blob_offset += (_mtu_size - 1)) {
EXPECT_CALL(
_mock_client, read_attribute_blob(_connection_handle, _attribute_handle, blob_offset)
).WillOnce(Invoke([&](auto connection, auto attribute, uint16_t offset) {
_mock_client.on_server_event(
connection,
AttReadBlobResponse(
make_const_ArrayView(
char_value.data() + offset,
(char_len - offset) > (_mtu_size - 1) ? (_mtu_size - 1) : (char_len - offset)
)
)
);
return BLE_ERROR_NONE;
}));
}
EXPECT_CALL(_read_cb, call(Pointee(GattReadCallbackParams {
_connection_handle,
_attribute_handle,
offset,
(uint16_t) char_len,
char_value.data(),
BLE_ERROR_NONE
})));
ble_error_t err = _gatt_client.read(_connection_handle, _attribute_handle, offset);
EXPECT_EQ(err, BLE_ERROR_NONE);
bool can_continue = Mock::VerifyAndClearExpectations(&_mock_client) && Mock::VerifyAndClearExpectations(&_read_cb);
if (!can_continue) {
return;
}
}
}
}
/*
* Given a readable attribute with a value longer than ATT_MTU - 2.
* When the GattClient::read is called without offset
* Then:
* - The client call the pal function read_attribute_blob with the connection
* handle, the attribute handle and the offset used in GattClient::read.
* When the pal::GattClient fire an AttReadResponse containing the first bytes
* of the attribute value.
* Then:
* - If the response length is less than (ATT_MTU - 1), the read callback is
* called with the value of the attribute read.
* - The client call the function read_attribute_blob with the connection
* handle and the attribute handle used in GattClient::read. The offset is
* equal of the number of bytes read in the characteristic plus the
* first offset.
* When the pal::Client fire an AttReadBlobResponse containing the partial value
* of the characteristic starting at the offset requested. If the length of
* the remaining bytes is greater than ATT_MTU - 1 then the length of the
* partial value in the response shall be ATT_MTU - 1. Otherwise it is the
* length of the remaining bytes.
* Then:
* - If the value received by the client has a len greater than ATT_MTU - 1.
* Then the client issue a new read_attribute_blob with an updated index.
* - Else the read callback is called with the value of the attribute read.
*/
TEST_F(TestGattClientRead, read_long_characteristic_with_offset_shall_succeed) {
auto char_value = make_char_value(517 * 6);
// iterate over possible MTU size
for (_mtu_size = 23; _mtu_size < 517; _mtu_size += 35) {
// iterate over possible characteristic value size
for (uint16_t char_len = (_mtu_size - 1); char_len < (_mtu_size * 4); char_len += 30) {
for(uint16_t offset = 1; offset < char_len; offset += 20) {
set_mtu_size_stub();
InSequence seq;
for(uint16_t blob_offset = offset; blob_offset <= char_len; blob_offset += (_mtu_size - 1)) {
EXPECT_CALL(
_mock_client, read_attribute_blob(_connection_handle, _attribute_handle, blob_offset)
).WillOnce(Invoke([&](auto connection, auto attribute, auto offset) {
_mock_client.on_server_event(
connection,
AttReadBlobResponse(
make_const_ArrayView(
char_value.data() + offset,
(char_len - offset) > (_mtu_size - 1) ? (_mtu_size - 1) : (char_len - offset)
)
)
);
return BLE_ERROR_NONE;
}));
}
EXPECT_CALL(_read_cb, call(Pointee(GattReadCallbackParams {
_connection_handle,
_attribute_handle,
offset,
(uint16_t) (char_len - offset),
char_value.data() + offset,
BLE_ERROR_NONE
})));
ble_error_t err = _gatt_client.read(_connection_handle, _attribute_handle, offset);
EXPECT_EQ(err, BLE_ERROR_NONE);
bool can_continue = Mock::VerifyAndClearExpectations(&_mock_client) && Mock::VerifyAndClearExpectations(&_read_cb);
if (!can_continue) {
return;
}
}
}
}
}
// TODO: Add test for failure in the middle of the transaction

View File

@ -1,158 +0,0 @@
/* mbed Microcontroller Library
* Copyright (c) 2018 ARM Limited
*
* 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 <algorithm>
#include <vector>
#include <array>
#include <initializer_list>
#include <cstdlib>
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "ble/generic/GenericGattClient.h"
#include "ble/pal/AttServerMessage.h"
#include "ble/pal/SimpleAttServerMessage.h"
#include "ble/DiscoveredService.h"
#include "mock/MockCallbacks.h"
#include "mock/MockPalGattClient.h"
#include "util/PrettyPrinter.h"
#include "util/Equality.h"
using ble::pal::AttHandleValueIndication;
using ble::pal::AttHandleValueNotification;
using ble::generic::GenericGattClient;
using ble::pal::vendor::mock::MockPalGattClient;
using ble::connection_handle_t;
using ble::make_const_ArrayView;
using ::testing::_;
using ::testing::Invoke;
using ::testing::Pointee;
using std::vector;
static vector<uint8_t> make_char_value(uint16_t length) {
vector<uint8_t> characteristic_value(length);
for (auto& byte : characteristic_value) {
byte = std::rand();
}
return characteristic_value;
}
/*
* Fixture use to test server notification or indication.
*/
class TestGattServerEvent : public ::testing::Test {
protected:
TestGattServerEvent() :
_mock_client(),
_gatt_client(&_mock_client),
_connection_handle(0xDEAD),
_attribute_handle(0x5645),
_mtu_size(23) {
}
virtual void SetUp() {
_gatt_client.onHVX(
makeFunctionPointer(&_event_cb, &server_event_callback_t::call)
);
ON_CALL(_mock_client, get_mtu_size(_connection_handle, _)).
WillByDefault(Invoke([&](auto, auto& mtu_size ){
mtu_size = this->_mtu_size;
return BLE_ERROR_NONE;
}));
}
void set_mtu_size_stub() {
EXPECT_CALL(_mock_client, get_mtu_size(_connection_handle, _))
.WillRepeatedly(::testing::DoDefault());
}
MockPalGattClient _mock_client;
GenericGattClient _gatt_client;
const Gap::Handle_t _connection_handle;
uint16_t _attribute_handle;
server_event_callback_t _event_cb;
uint16_t _mtu_size;
};
/*
* Ensure the right callback is called with the correct parameters when an
* indication is received.
*/
TEST_F(TestGattServerEvent, event_callback_shall_be_called_on_indication) {
auto value = make_char_value(5000);
for (_mtu_size = 23; _mtu_size < 517; _mtu_size += 10) {
for (uint16_t len = 0; len < (_mtu_size - 3); len += 10) {
EXPECT_CALL(
_event_cb, call(Pointee(GattHVXCallbackParams {
_connection_handle,
_attribute_handle,
HVXType_t::BLE_HVX_INDICATION,
len,
value.data()
}))
);
_mock_client.on_server_event(
_connection_handle,
AttHandleValueIndication(
_attribute_handle,
make_const_ArrayView(value.data(), len)
)
);
}
}
}
/*
* Ensure the right callback is called with the correct parameters when a
* notification is received.
*/
TEST_F(TestGattServerEvent, event_callback_shall_be_called_on_notification) {
auto value = make_char_value(5000);
for (_mtu_size = 23; _mtu_size < 517; _mtu_size += 10) {
for (uint16_t len = 0; len < (_mtu_size - 3); len += 10) {
EXPECT_CALL(
_event_cb, call(Pointee(GattHVXCallbackParams {
_connection_handle,
_attribute_handle,
HVXType_t::BLE_HVX_NOTIFICATION,
len,
value.data()
}))
);
_mock_client.on_server_event(
_connection_handle,
AttHandleValueNotification(
_attribute_handle,
make_const_ArrayView(value.data(), len)
)
);
}
}
}

View File

@ -1,719 +0,0 @@
/* mbed Microcontroller Library
* Copyright (c) 2018 ARM Limited
*
* 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 <algorithm>
#include <vector>
#include <array>
#include <initializer_list>
#include <tuple>
#include <cstdlib>
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "ble/generic/GenericGattClient.h"
#include "ble/pal/AttServerMessage.h"
#include "ble/pal/SimpleAttServerMessage.h"
#include "ble/DiscoveredService.h"
#include "mock/MockPalGattClient.h"
#include "mock/MockCallbacks.h"
#include "util/PrettyPrinter.h"
#include "util/Equality.h"
using ble::pal::AttErrorResponse;
using ble::pal::AttributeOpcode;
using ble::pal::AttWriteResponse;
using ble::pal::AttPrepareWriteResponse;
using ble::pal::AttExecuteWriteResponse;
using ble::generic::GenericGattClient;
using ble::pal::vendor::mock::MockPalGattClient;
using ble::connection_handle_t;
using ble::attribute_handle_t;
using ble::ArrayView;
using ble::make_const_ArrayView;
using ::testing::_;
using ::testing::Invoke;
using ::testing::InSequence;
using ::testing::Mock;
using ::testing::Pointee;
using std::vector;
using std::tuple;
static vector<uint8_t> make_char_value(uint16_t length) {
vector<uint8_t> characteristic_value(length);
for (auto& byte : characteristic_value) {
byte = std::rand();
}
return characteristic_value;
}
/*
* Fixture used for GattClient::write tests.
*/
class TestGattClientWrite : public ::testing::Test {
protected:
TestGattClientWrite() :
_mock_client(),
_gatt_client(&_mock_client),
_connection_handle(0xDEAD),
_attribute_handle(0x5645),
_write_cb(),
_mtu_size(23) {
}
virtual void SetUp() {
_gatt_client.onDataWritten(
makeFunctionPointer(&_write_cb, &write_callback_t::call)
);
ON_CALL(
_mock_client, get_mtu_size(_connection_handle, _)
).WillByDefault(Invoke([&](auto, auto& mtu_size){
mtu_size = _mtu_size;
return BLE_ERROR_NONE;
}));
}
void set_mtu_size_stub() {
EXPECT_CALL(_mock_client, get_mtu_size(_connection_handle, _))
.WillRepeatedly(::testing::DoDefault());
}
MockPalGattClient _mock_client;
GenericGattClient _gatt_client;
const Gap::Handle_t _connection_handle;
uint16_t _attribute_handle;
write_callback_t _write_cb;
uint16_t _mtu_size;
};
/**
* Given a payload shorter than the current MTU size - 2.
* When the payload is sent in a write command
* Then the payload is sent to the pal without error.
*/
TEST_F(TestGattClientWrite, write_command_should_succeed_if_it_fit_in_the_payload) {
auto value = make_char_value(1000);
for (_mtu_size = 23; _mtu_size < 517; _mtu_size += 10) {
for(uint16_t len = 0; len <= (_mtu_size - 3); len += 10) {
set_mtu_size_stub();
EXPECT_CALL(
_mock_client, write_without_response(
_connection_handle,
_attribute_handle,
make_const_ArrayView(value.data(), len)
)
);
ble_error_t error = _gatt_client.write(
GattClient::GATT_OP_WRITE_CMD,
_connection_handle,
_attribute_handle,
len,
value.data()
);
EXPECT_EQ(error, BLE_ERROR_NONE);
bool can_continue =
Mock::VerifyAndClearExpectations(&_write_cb) &&
Mock::VerifyAndClearExpectations(&_mock_client);
if (!can_continue) {
return;
}
}
}
}
/**
* Given a payload with a length longer than MTU size -1
* When the payload is sent in a write command
* Then the function returns an error.
*/
TEST_F(TestGattClientWrite, write_command_should_fail_if_it_doesnt_fit_in_the_payload) {
auto value = make_char_value(1000);
for (_mtu_size = 23; _mtu_size < 517; _mtu_size += 10) {
for(size_t len = (_mtu_size - 3) + 1; len < 517; len += 10) {
set_mtu_size_stub();
ble_error_t error = _gatt_client.write(
GattClient::GATT_OP_WRITE_CMD,
_connection_handle,
_attribute_handle,
len,
value.data()
);
EXPECT_EQ(error, BLE_ERROR_PARAM_OUT_OF_RANGE);
bool can_continue =
Mock::VerifyAndClearExpectations(&_write_cb) &&
Mock::VerifyAndClearExpectations(&_mock_client) &&
(error == BLE_ERROR_PARAM_OUT_OF_RANGE);
if (!can_continue) {
return;
}
}
}
}
// TODO: test unexpected results from write_without_response
/**
* Given a payload shorter than the current MTU size - 2.
* When the payload is sent in a write request
* Then if the operation succeed the write callback shall be invoked.
*/
TEST_F(TestGattClientWrite, write_request_short_characteristics) {
auto value = make_char_value(1000);
for (_mtu_size = 23; _mtu_size < 517; _mtu_size += 10) {
for(uint16_t len = 0; len <= (_mtu_size - 3); len += 10) {
set_mtu_size_stub();
EXPECT_CALL(
_mock_client, write_attribute(
_connection_handle,
_attribute_handle,
make_const_ArrayView(value.data(), len)
)
).WillOnce(Invoke([&](auto conn_handle, auto, const auto&) {
_mock_client.on_server_event(
conn_handle,
AttWriteResponse()
);
return BLE_ERROR_NONE;
}));
EXPECT_CALL(_write_cb, call(Pointee(GattWriteCallbackParams {
_connection_handle,
_attribute_handle,
GattWriteCallbackParams::OP_WRITE_REQ,
BLE_ERROR_NONE,
/* error code */ 0,
})));
ble_error_t error = _gatt_client.write(
GattClient::GATT_OP_WRITE_REQ,
_connection_handle,
_attribute_handle,
len,
value.data()
);
EXPECT_EQ(error, BLE_ERROR_NONE);
bool can_continue =
Mock::VerifyAndClearExpectations(&_write_cb) &&
Mock::VerifyAndClearExpectations(&_mock_client);
if (!can_continue) {
return;
}
}
}
}
/*
* Fixture used to test error handling during a characteristic write.
* Parameters are:
* [0] AttErrorResponse::AttributeErrorCode The attribute error code to push in
* the AttErrorresponse sent to the client.
* [1] ble_error_t The expected error status present in the parameters received
* by the callback handling GattClient::write.
*/
class TestGattClientWriteAttributeError :
public TestGattClientWrite,
public ::testing::WithParamInterface<tuple<AttErrorResponse::AttributeErrorCode, ble_error_t>> {
protected:
TestGattClientWriteAttributeError() :
TestGattClientWrite(),
error_code((AttErrorResponse::AttributeErrorCode) 0x00),
status(BLE_ERROR_NONE) {
}
virtual void SetUp() {
TestGattClientWrite::SetUp();
std::tie(error_code, status) = GetParam();
}
AttErrorResponse::AttributeErrorCode error_code;
ble_error_t status;
};
/**
* Given a payload shorter than the current MTU size - 2.
* When the payload is sent in a write request
* Then if the operation fail the write callback shall report the error
*/
TEST_P(TestGattClientWriteAttributeError, write_request_short_characteristics) {
auto value = make_char_value(1000);
for (_mtu_size = 23; _mtu_size < 517; _mtu_size += 10) {
for(uint16_t len = 0; len <= (_mtu_size - 3); len += 10) {
set_mtu_size_stub();
EXPECT_CALL(
_mock_client, write_attribute(
_connection_handle,
_attribute_handle,
make_const_ArrayView(value.data(), len)
)
).WillOnce(Invoke([&](auto conn_handle, auto att_handle, const auto&) {
_mock_client.on_server_event(
conn_handle,
AttErrorResponse(
AttributeOpcode::WRITE_REQUEST,
att_handle,
error_code
)
);
return BLE_ERROR_NONE;
}));
EXPECT_CALL(
_write_cb, call(Pointee(GattWriteCallbackParams{
_connection_handle,
_attribute_handle,
GattWriteCallbackParams::OP_PREP_WRITE_REQ,
status,
error_code
}))
);
ble_error_t error = _gatt_client.write(
GattClient::GATT_OP_WRITE_REQ,
_connection_handle,
_attribute_handle,
len,
value.data()
);
EXPECT_EQ(error, BLE_ERROR_NONE);
bool can_continue =
Mock::VerifyAndClearExpectations(&_write_cb) &&
Mock::VerifyAndClearExpectations(&_mock_client);
if (!can_continue) {
return;
}
}
}
}
// Instantiate test cases using the TestGattClientWriteAttributeError fixture
INSTANTIATE_TEST_CASE_P(
TestGattClientWriteAttributeError_combination,
TestGattClientWriteAttributeError,
::testing::Values(
std::make_tuple(AttErrorResponse::INVALID_ATTRIBUTE_VALUE_LENGTH, BLE_ERROR_INVALID_PARAM),
std::make_tuple(AttErrorResponse::INVALID_HANDLE, BLE_ERROR_INVALID_PARAM),
std::make_tuple(AttErrorResponse::INSUFFICIENT_AUTHORIZATION, BLE_ERROR_INVALID_STATE),
std::make_tuple(AttErrorResponse::INSUFFICIENT_AUTHENTICATION, BLE_ERROR_INVALID_STATE),
std::make_tuple(AttErrorResponse::INSUFFICIENT_ENCRYPTION_KEY_SIZE, BLE_ERROR_INVALID_STATE),
std::make_tuple(AttErrorResponse::INSUFFICIENT_ENCRYPTION, BLE_ERROR_INVALID_STATE),
std::make_tuple(AttErrorResponse::WRITE_NOT_PERMITTED, BLE_ERROR_OPERATION_NOT_PERMITTED),
std::make_tuple((AttErrorResponse::AttributeErrorCode)/* application error */ 0x80, BLE_ERROR_UNSPECIFIED)
)
);
/**
* Given a payload with a length bigger than the current MTU size - 2.
* When the payload is written as using Gattclient::write
* Then the payload is split into multiple chunks of a maximum size equal to
* MTU_size - 5. Those chunks are sent sequentially using a prepare write
* request which is answered by a prepare write response by the server.
* Once all the chunks have been received by the server, the client sends an
* Execute write request. Once the client received an Execute Write request,
* the server shall invoke the write callback.
*/
TEST_F(TestGattClientWrite, write_request_long_characteristics) {
auto value = make_char_value(10000);
for (_mtu_size = 23; _mtu_size < 517; _mtu_size += 10) {
for(uint16_t len = (_mtu_size - 2); len <= (_mtu_size * 4); len += 10) {
set_mtu_size_stub();
InSequence seq;
for (uint16_t offset = 0; offset < len; offset += (_mtu_size - 5)) {
EXPECT_CALL(
_mock_client, queue_prepare_write(
_connection_handle,
_attribute_handle,
make_const_ArrayView(
value.data() + offset,
((len - offset) > (_mtu_size - 5)) ? (_mtu_size - 5) : (len - offset)
),
offset
)
).WillOnce(Invoke([&](auto conn_handle, auto att_handle, const auto& data, auto offset) {
_mock_client.on_server_event(
conn_handle,
AttPrepareWriteResponse(
att_handle,
offset,
data
)
);
return BLE_ERROR_NONE;
}));
}
EXPECT_CALL(
_mock_client, execute_write_queue(
_connection_handle,
true
)
).WillOnce(Invoke([&](auto conn_handle, bool execute) {
_mock_client.on_server_event(
conn_handle,
AttExecuteWriteResponse()
);
return BLE_ERROR_NONE;
}));
EXPECT_CALL(
_write_cb, call(Pointee(GattWriteCallbackParams{
_connection_handle,
_attribute_handle,
GattWriteCallbackParams::OP_WRITE_REQ,
BLE_ERROR_NONE,
/* error code */ 0,
}))
);
ble_error_t error = _gatt_client.write(
GattClient::GATT_OP_WRITE_REQ,
_connection_handle,
_attribute_handle,
len,
value.data()
);
EXPECT_EQ(error, BLE_ERROR_NONE);
bool can_continue =
Mock::VerifyAndClearExpectations(&_write_cb) &&
Mock::VerifyAndClearExpectations(&_mock_client);
if (!can_continue) {
return;
}
}
}
}
/*
* Fixture used to test long write errors.
* Parameter are similar to the one used in TestGattClientWriteAttributeError
*/
class TestGattClientPrepareWriteAttributeError : public TestGattClientWriteAttributeError { };
/**
* Test errors received by a client at the beginning of a long write procedure.
*/
TEST_P(TestGattClientPrepareWriteAttributeError, prepare_write_error) {
auto value = make_char_value(10000);
_mtu_size = 23;
set_mtu_size_stub();
InSequence seq;
EXPECT_CALL(
_mock_client, queue_prepare_write(
_connection_handle,
_attribute_handle,
make_const_ArrayView(
value.data(),
_mtu_size - 5
),
0
)
).WillOnce(Invoke([&](auto conn_handle, auto att_handle, const auto&, auto offset) {
_mock_client.on_server_event(
conn_handle,
AttErrorResponse(
AttributeOpcode::PREPARE_WRITE_REQUEST,
att_handle,
error_code
)
);
return BLE_ERROR_NONE;
}));
EXPECT_CALL(
_mock_client, execute_write_queue(_connection_handle, false)
).WillOnce(Invoke([&](auto conn_handle, bool execute) {
_mock_client.on_server_event(
conn_handle,
AttExecuteWriteResponse()
);
return BLE_ERROR_NONE;
}));
EXPECT_CALL(
_write_cb, call(Pointee(GattWriteCallbackParams{
_connection_handle,
_attribute_handle,
GattWriteCallbackParams::OP_WRITE_REQ,
status,
/* error code */ error_code,
}))
);
ble_error_t error = _gatt_client.write(
GattClient::GATT_OP_WRITE_REQ,
_connection_handle,
_attribute_handle,
_mtu_size * 10,
value.data()
);
EXPECT_EQ(error, BLE_ERROR_NONE);
}
// Instantiate test cases relying on TestGattClientPrepareWriteAttributeError
INSTANTIATE_TEST_CASE_P(
TestGattClientPrepareWriteAttributeError_combination,
TestGattClientPrepareWriteAttributeError,
::testing::Values(
std::make_tuple(AttErrorResponse::INSUFFICIENT_AUTHORIZATION, BLE_ERROR_INVALID_STATE),
std::make_tuple(AttErrorResponse::INSUFFICIENT_AUTHENTICATION, BLE_ERROR_INVALID_STATE),
std::make_tuple(AttErrorResponse::INSUFFICIENT_ENCRYPTION_KEY_SIZE, BLE_ERROR_INVALID_STATE),
std::make_tuple(AttErrorResponse::INSUFFICIENT_ENCRYPTION, BLE_ERROR_INVALID_STATE),
std::make_tuple(AttErrorResponse::PREPARE_QUEUE_FULL, BLE_ERROR_INVALID_STATE),
std::make_tuple(AttErrorResponse::INVALID_HANDLE, BLE_ERROR_INVALID_PARAM),
std::make_tuple(AttErrorResponse::WRITE_NOT_PERMITTED, BLE_ERROR_OPERATION_NOT_PERMITTED),
std::make_tuple((AttErrorResponse::AttributeErrorCode)/* application error */ 0x80, BLE_ERROR_UNSPECIFIED)
)
);
/*
* Fixture used to test errors in the middle of a long write transaction.
* Parameter are similar to the one used in TestGattClientWriteAttributeError
*/
class TestGattClientPrepareWriteAttributeErrorInTransaction : public TestGattClientWriteAttributeError { };
/**
* Test that errors are correctly reported to the client if an error occur in the
* middle of a long write transaction.
*/
TEST_P(TestGattClientPrepareWriteAttributeErrorInTransaction, prepare_write_error_in_transaction) {
auto value = make_char_value(10000);
_mtu_size = 23;
set_mtu_size_stub();
InSequence seq;
EXPECT_CALL(
_mock_client, queue_prepare_write(
_connection_handle,
_attribute_handle,
make_const_ArrayView(
value.data(),
_mtu_size - 5
),
/* offset */ 0
)
).WillOnce(Invoke([&](auto conn_handle, auto att_handle, const auto&, auto) {
_mock_client.on_server_event(
conn_handle,
AttPrepareWriteResponse(
att_handle,
0,
make_const_ArrayView(value.data(), _mtu_size - 5)
)
);
return BLE_ERROR_NONE;
}));
uint16_t offset = _mtu_size - 5;
EXPECT_CALL(
_mock_client, queue_prepare_write(
_connection_handle,
_attribute_handle,
make_const_ArrayView(
value.data() + offset,
_mtu_size - 5
),
offset
)
).WillOnce(Invoke([&](auto conn_handle, auto att_handle, const auto&, auto offset) {
_mock_client.on_server_event(
conn_handle,
AttErrorResponse(
AttributeOpcode::PREPARE_WRITE_REQUEST,
att_handle,
error_code
)
);
return BLE_ERROR_NONE;
}));
EXPECT_CALL(
_mock_client, execute_write_queue(_connection_handle, false)
).WillOnce(Invoke([&](auto conn_handle, bool execute) {
_mock_client.on_server_event(
conn_handle,
AttExecuteWriteResponse()
);
return BLE_ERROR_NONE;
}));
EXPECT_CALL(
_write_cb, call(Pointee(GattWriteCallbackParams{
_connection_handle,
_attribute_handle,
GattWriteCallbackParams::OP_WRITE_REQ,
status,
/* error code */ error_code,
}))
);
ble_error_t error = _gatt_client.write(
GattClient::GATT_OP_WRITE_REQ,
_connection_handle,
_attribute_handle,
_mtu_size * 10,
value.data()
);
EXPECT_EQ(error, BLE_ERROR_NONE);
}
// Instantiate test cases relying on TestGattClientPrepareWriteAttributeErrorInTransaction
INSTANTIATE_TEST_CASE_P(
TestGattClientPrepareWriteAttributeErrorInTransaction_combination,
TestGattClientPrepareWriteAttributeErrorInTransaction,
::testing::Values(
std::make_tuple(AttErrorResponse::PREPARE_QUEUE_FULL, BLE_ERROR_INVALID_STATE),
std::make_tuple((AttErrorResponse::AttributeErrorCode)/* application error */ 0x80, BLE_ERROR_UNSPECIFIED)
)
);
/*
* Fixture used to test errors at the end of a long write transaction.
* Parameter are similar to the one used in TestGattClientWriteAttributeError
*/
class TestGattClientExecuteWriteRequestError : public TestGattClientWriteAttributeError { };
/**
* Test that errors are correctly reported to the client if an error occurs when
* a write queue is executed.
*/
TEST_P(TestGattClientExecuteWriteRequestError, prepare_write_error_in_transaction) {
auto value = make_char_value(10000);
_mtu_size = 23;
set_mtu_size_stub();
const uint16_t len = _mtu_size * 5;
InSequence seq;
for (uint16_t offset = 0; offset < len; offset += (_mtu_size - 5)) {
EXPECT_CALL(
_mock_client, queue_prepare_write(
_connection_handle,
_attribute_handle,
make_const_ArrayView(
value.data() + offset,
((len - offset) > (_mtu_size - 5)) ? (_mtu_size - 5) : (len - offset)
),
offset
)
).WillOnce(Invoke([&](auto conn_handle, auto att_handle, const auto& data, auto offset) {
_mock_client.on_server_event(
conn_handle,
AttPrepareWriteResponse(
att_handle,
offset,
data
)
);
return BLE_ERROR_NONE;
}));
}
EXPECT_CALL(
_mock_client, execute_write_queue(
_connection_handle, true
)
).WillOnce(Invoke([&](connection_handle_t conn_handle, bool execute) {
_mock_client.on_server_event(
conn_handle,
AttErrorResponse(
AttributeOpcode::EXECUTE_WRITE_REQUEST,
_attribute_handle,
error_code
)
);
return BLE_ERROR_NONE;
}));
EXPECT_CALL(
_write_cb, call(Pointee(GattWriteCallbackParams{
_connection_handle,
_attribute_handle,
GattWriteCallbackParams::OP_WRITE_REQ,
status,
error_code
}))
);
ble_error_t error = _gatt_client.write(
GattClient::GATT_OP_WRITE_REQ,
_connection_handle,
_attribute_handle,
len,
value.data()
);
EXPECT_EQ(error, BLE_ERROR_NONE);
}
// Instantiate test cases relying on TestGattClientExecuteWriteRequestError
INSTANTIATE_TEST_CASE_P(
TestGattClientExecuteWriteRequestError_combination,
TestGattClientExecuteWriteRequestError,
::testing::Values(
std::make_tuple(AttErrorResponse::INVALID_HANDLE, BLE_ERROR_INVALID_PARAM),
std::make_tuple(AttErrorResponse::WRITE_NOT_PERMITTED, BLE_ERROR_OPERATION_NOT_PERMITTED),
std::make_tuple(AttErrorResponse::PREPARE_QUEUE_FULL, BLE_ERROR_INVALID_STATE),
std::make_tuple(AttErrorResponse::INVALID_OFFSET, BLE_ERROR_INVALID_PARAM),
std::make_tuple(AttErrorResponse::INVALID_ATTRIBUTE_VALUE_LENGTH, BLE_ERROR_INVALID_PARAM),
std::make_tuple(AttErrorResponse::WRITE_REQUEST_REJECTED, BLE_ERROR_OPERATION_NOT_PERMITTED),
std::make_tuple((AttErrorResponse::AttributeErrorCode)/* application error */ 0x80, BLE_ERROR_UNSPECIFIED)
)
);

View File

@ -1,47 +0,0 @@
/* mbed Microcontroller Library
* Copyright (c) 2018 ARM Limited
*
* 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 "MockCallbacks.h"
////////////////////////////////////////////////////////////////////////////////
// Constructor implementation of the mocked callbacks
//
// WARNING: Do not remove; it speedup compile time.
service_callback_t::service_callback_t() { }
service_callback_t::~service_callback_t() { }
characteristic_callback_t::characteristic_callback_t() { }
characteristic_callback_t::~characteristic_callback_t() { }
termination_callback_t::termination_callback_t() { }
termination_callback_t::~termination_callback_t() { }
read_callback_t::read_callback_t() { }
read_callback_t::~read_callback_t() { }
write_callback_t::write_callback_t() { }
write_callback_t::~write_callback_t() { }
server_event_callback_t::server_event_callback_t() { }
server_event_callback_t::~server_event_callback_t() { }
descriptor_callback_t::descriptor_callback_t() { }
descriptor_callback_t::~descriptor_callback_t() { }
descriptor_termination_callback_t::descriptor_termination_callback_t() { }
descriptor_termination_callback_t::~descriptor_termination_callback_t() { }

View File

@ -1,109 +0,0 @@
/* mbed Microcontroller Library
* Copyright (c) 2018 ARM Limited
*
* 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 TESTS_GENERIC_GATTCLIENT_MOCK_MOCKCALLBACKS_H_
#define TESTS_GENERIC_GATTCLIENT_MOCK_MOCKCALLBACKS_H_
#include "gmock/gmock.h"
#include "ble/Gap.h"
#include "ble/DiscoveredService.h"
#include "ble/DiscoveredCharacteristic.h"
#include "ble/GattCallbackParamTypes.h"
#include "ble/CharacteristicDescriptorDiscovery.h"
////////////////////////////////////////////////////////////////////////////////
// Mocks declaration for callbacks objects used in GattClient
//
/*
* Mock of the service discovery callback.
*/
struct service_callback_t {
service_callback_t();
virtual ~service_callback_t();
MOCK_METHOD1(call, void(const DiscoveredService*));
};
/*
* Mock of the characteristic discovery callback.
*/
struct characteristic_callback_t {
characteristic_callback_t();
virtual ~characteristic_callback_t();
MOCK_METHOD1(call, void(const DiscoveredCharacteristic*));
};
/*
* Mock of the discovery termination callback.
*/
struct termination_callback_t {
termination_callback_t();
virtual ~termination_callback_t();
MOCK_METHOD1(call, void(Gap::Handle_t));
};
/*
* Mock of the read attribute callback.
*/
struct read_callback_t {
read_callback_t();
virtual ~read_callback_t();
MOCK_METHOD1(call, void(const GattReadCallbackParams*));
};
/*
* Mock of the write attribute callback.
*/
struct write_callback_t {
write_callback_t();
virtual ~write_callback_t();
MOCK_METHOD1(call, void(const GattWriteCallbackParams*));
};
/*
* Mock of the server initiated events callback (notification and indication).
*/
struct server_event_callback_t {
server_event_callback_t();
virtual ~server_event_callback_t();
MOCK_METHOD1(call, void(const GattHVXCallbackParams*));
};
/*
* Mock of the characteristic descriptor discovery callback.
*/
struct descriptor_callback_t {
descriptor_callback_t();
virtual ~descriptor_callback_t();
MOCK_METHOD1(
call,
void(const CharacteristicDescriptorDiscovery::DiscoveryCallbackParams_t*)
);
};
/*
* Mock of the characteristic descriptor termination callback.
*/
struct descriptor_termination_callback_t {
descriptor_termination_callback_t();
virtual ~descriptor_termination_callback_t();
MOCK_METHOD1(
call,
void(const CharacteristicDescriptorDiscovery::TerminationCallbackParams_t*)
);
};
#endif /* TESTS_GENERIC_GATTCLIENT_MOCK_MOCKCALLBACKS_H_ */

View File

@ -1,35 +0,0 @@
/* mbed Microcontroller Library
* Copyright (c) 2018 ARM Limited
*
* 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 "MockPalGattClient.h"
namespace ble {
namespace pal {
namespace vendor {
namespace mock {
////////////////////////////////////////////////////////////////////////////////
// Constructor implementation of the mocked pal gatt client
//
// WARNING: Do not remove; it speedup compile time.
MockPalGattClient::MockPalGattClient() { }
MockPalGattClient::~MockPalGattClient() { }
} // namespace ble
} // namespace pal
} // namespace vendor
} // namespace mock

View File

@ -1,141 +0,0 @@
/* mbed Microcontroller Library
* Copyright (c) 2018 ARM Limited
*
* 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 TESTS_GENERIC_GATTCLIENT_MOCK_MOCKPALGATTCLIENT_H_
#define TESTS_GENERIC_GATTCLIENT_MOCK_MOCKPALGATTCLIENT_H_
#include "gmock/gmock.h"
#include "ble/pal/PalGattClient.h"
namespace ble {
namespace pal {
namespace vendor {
namespace mock {
/*
* Mock of ble::pal::GattClient
*/
class MockPalGattClient : public ble::pal::GattClient {
public:
MockPalGattClient();
virtual ~MockPalGattClient();
MOCK_METHOD0(initialize, ble_error_t());
MOCK_METHOD0(terminate, ble_error_t());
MOCK_METHOD1(exchange_mtu, ble_error_t(connection_handle_t));
MOCK_METHOD2(get_mtu_size, ble_error_t(connection_handle_t, uint16_t&));
MOCK_METHOD2(
discover_primary_service,
ble_error_t(connection_handle_t, attribute_handle_t)
);
MOCK_METHOD3(
discover_primary_service_by_service_uuid,
ble_error_t(connection_handle_t, attribute_handle_t, const UUID&)
);
MOCK_METHOD2(
find_included_service,
ble_error_t(connection_handle_t, attribute_handle_range_t)
);
MOCK_METHOD2(
discover_characteristics_of_a_service,
ble_error_t(connection_handle_t, attribute_handle_range_t)
);
MOCK_METHOD2(
discover_characteristics_descriptors,
ble_error_t(connection_handle_t, attribute_handle_range_t)
);
MOCK_METHOD2(
read_attribute_value,
ble_error_t(connection_handle_t, attribute_handle_t)
);
MOCK_METHOD3(
read_using_characteristic_uuid,
ble_error_t(connection_handle_t, attribute_handle_range_t, const UUID&)
);
MOCK_METHOD3(
read_attribute_blob,
ble_error_t(connection_handle_t, attribute_handle_t, uint16_t)
);
MOCK_METHOD2(
read_multiple_characteristic_values,
ble_error_t(
connection_handle_t, const ArrayView<const attribute_handle_t>&
)
);
MOCK_METHOD3(
write_without_response,
ble_error_t(
connection_handle_t,
attribute_handle_t,
const ArrayView<const uint8_t>&
)
);
MOCK_METHOD3(
signed_write_without_response,
ble_error_t(
connection_handle_t,
attribute_handle_t,
const ArrayView<const uint8_t>&
)
);
MOCK_METHOD3(
write_attribute,
ble_error_t(
connection_handle_t,
attribute_handle_t,
const ArrayView<const uint8_t>&
)
);
MOCK_METHOD4(
queue_prepare_write,
ble_error_t(
connection_handle_t,
attribute_handle_t,
const ArrayView<const uint8_t>&,
uint16_t
)
);
MOCK_METHOD2(execute_write_queue, ble_error_t(connection_handle_t, bool));
// let event injection functions be public so it can be used inside the tests.
using pal::GattClient::on_server_event;
using pal::GattClient::on_transaction_timeout;
};
} // namespace ble
} // namespace pal
} // namespace vendor
} // namespace mock
#endif /* TESTS_GENERIC_GATTCLIENT_MOCK_MOCKPALGATTCLIENT_H_ */

View File

@ -1,59 +0,0 @@
/* mbed Microcontroller Library
* Copyright (c) 2018 ARM Limited
*
* 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 TESTS_GENERIC_GATTCLIENT_UTIL_CHARACTERISTICDESCRIPTION_H_
#define TESTS_GENERIC_GATTCLIENT_UTIL_CHARACTERISTICDESCRIPTION_H_
#include <stdint.h>
#include "ble/UUID.h"
#include "ble/DiscoveredCharacteristic.h"
struct characteristic_description_t {
characteristic_description_t() :
handle(0), properties(), value_handle(0), uuid() { }
characteristic_description_t(
uint16_t handle,
DiscoveredCharacteristic::Properties_t properties,
UUID uuid
) : handle(handle),
properties(properties),
value_handle(handle + 1),
uuid(uuid) {
}
friend bool operator==(
const characteristic_description_t& lhs, const characteristic_description_t& rhs
) {
return (lhs.handle == rhs.handle)
&& (lhs.properties == rhs.properties)
&& (lhs.value_handle == rhs.value_handle)
&& (lhs.uuid == rhs.uuid);
}
friend bool operator !=(
const characteristic_description_t& lhs, const characteristic_description_t& rhs
) {
return !(lhs == rhs);
}
uint16_t handle;
DiscoveredCharacteristic::Properties_t properties;
uint16_t value_handle;
UUID uuid;
};
#endif /* TESTS_GENERIC_GATTCLIENT_UTIL_CHARACTERISTICDESCRIPTION_H_ */

View File

@ -1,127 +0,0 @@
/* mbed Microcontroller Library
* Copyright (c) 2018 ARM Limited
*
* 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/DiscoveredCharacteristic.h"
#include "ble/DiscoveredCharacteristicDescriptor.h"
#include "ble/CharacteristicDescriptorDiscovery.h"
#include "ble/GattCallbackParamTypes.h"
#include "ble/ArrayView.h"
bool operator==(
const DiscoveredCharacteristicDescriptor& lhs,
const DiscoveredCharacteristicDescriptor& rhs
) {
if (lhs.getGattClient() != rhs.getGattClient() ||
lhs.getConnectionHandle() != rhs.getConnectionHandle() ||
lhs.getUUID() != rhs.getUUID() ||
lhs.getAttributeHandle() != rhs.getAttributeHandle()
) {
return false;
}
return true;
}
bool operator!=(
const DiscoveredCharacteristicDescriptor& lhs,
const DiscoveredCharacteristicDescriptor& rhs
) {
return !(lhs == rhs);
}
bool operator==(
const CharacteristicDescriptorDiscovery::TerminationCallbackParams_t& lhs,
const CharacteristicDescriptorDiscovery::TerminationCallbackParams_t& rhs
) {
if (lhs.characteristic != rhs.characteristic ||
lhs.status != rhs.status ||
lhs.error_code != rhs.error_code
) {
return false;
}
return true;
}
bool operator!=(
const CharacteristicDescriptorDiscovery::TerminationCallbackParams_t& lhs,
const CharacteristicDescriptorDiscovery::TerminationCallbackParams_t& rhs
) {
return !(lhs == rhs);
}
bool operator==(
const CharacteristicDescriptorDiscovery::DiscoveryCallbackParams_t& lhs,
const CharacteristicDescriptorDiscovery::DiscoveryCallbackParams_t& rhs
) {
if (lhs.characteristic != rhs.characteristic ||
lhs.descriptor != rhs.descriptor
) {
return false;
}
return true;
}
bool operator!=(
const CharacteristicDescriptorDiscovery::DiscoveryCallbackParams_t& lhs,
const CharacteristicDescriptorDiscovery::DiscoveryCallbackParams_t& rhs
) {
return !(lhs == rhs);
}
bool operator==(const GattReadCallbackParams& lhs, const GattReadCallbackParams& rhs) {
if ((lhs.connHandle != rhs.connHandle) || (lhs.handle != rhs.handle) ||
(lhs.offset != rhs.offset) || (lhs.status != rhs.status)) {
return false;
}
if (lhs.status == BLE_ERROR_NONE) {
if (lhs.len != rhs.len) {
return false;
}
if (memcmp(lhs.data, rhs.data, lhs.len) != 0) {
return false;
}
} else if (lhs.error_code != rhs.error_code) {
return false;
}
return true;
}
bool operator==(const GattHVXCallbackParams& lhs, const GattHVXCallbackParams& rhs) {
if (lhs.connHandle != rhs.connHandle &&
lhs.handle != rhs.handle &&
lhs.type != rhs.type &&
ble::make_const_ArrayView(lhs.data, lhs.len) != ble::make_const_ArrayView(rhs.data, rhs.len)) {
return false;
}
return true;
}
bool operator==(const GattWriteCallbackParams& lhs, const GattWriteCallbackParams& rhs) {
if (lhs.connHandle != rhs.connHandle &&
lhs.handle != rhs.handle &&
lhs.writeOp != rhs.writeOp &&
lhs.error_code != rhs.error_code &&
lhs.status != rhs.status) {
return false;
}
return true;
}

View File

@ -1,60 +0,0 @@
/* mbed Microcontroller Library
* Copyright (c) 2018 ARM Limited
*
* 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 TESTS_GENERIC_GATTCLIENT_UTIL_EQUALITY_H_
#define TESTS_GENERIC_GATTCLIENT_UTIL_EQUALITY_H_
#include "ble/DiscoveredCharacteristicDescriptor.h"
#include "ble/CharacteristicDescriptorDiscovery.h"
#include "ble/GattCallbackParamTypes.h"
bool operator==(
const DiscoveredCharacteristicDescriptor& lhs,
const DiscoveredCharacteristicDescriptor& rhs
);
bool operator!=(
const DiscoveredCharacteristicDescriptor& lhs,
const DiscoveredCharacteristicDescriptor& rhs
);
bool operator==(
const CharacteristicDescriptorDiscovery::TerminationCallbackParams_t& lhs,
const CharacteristicDescriptorDiscovery::TerminationCallbackParams_t& rhs
);
bool operator!=(
const CharacteristicDescriptorDiscovery::TerminationCallbackParams_t& lhs,
const CharacteristicDescriptorDiscovery::TerminationCallbackParams_t& rhs
);
bool operator==(
const CharacteristicDescriptorDiscovery::DiscoveryCallbackParams_t& lhs,
const CharacteristicDescriptorDiscovery::DiscoveryCallbackParams_t& rhs
);
bool operator!=(
const CharacteristicDescriptorDiscovery::DiscoveryCallbackParams_t& lhs,
const CharacteristicDescriptorDiscovery::DiscoveryCallbackParams_t& rhs
);
bool operator==(const GattReadCallbackParams& lhs, const GattReadCallbackParams& rhs);
bool operator==(const GattHVXCallbackParams& lhs, const GattHVXCallbackParams& rhs);
bool operator==(const GattWriteCallbackParams& lhs, const GattWriteCallbackParams& rhs);
#endif /* TESTS_GENERIC_GATTCLIENT_UTIL_EQUALITY_H_ */

View File

@ -1,35 +0,0 @@
/* mbed Microcontroller Library
* Copyright (c) 2018 ARM Limited
*
* 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 TESTS_GENERIC_GATTCLIENT_UTIL_LOG_H_
#define TESTS_GENERIC_GATTCLIENT_UTIL_LOG_H_
#include <ostream>
// logger
class Log {
public:
static std::ostream& info() {
std::cout << "[info ] ";
return std::cout;
}
};
#endif /* TESTS_GENERIC_GATTCLIENT_UTIL_LOG_H_ */

View File

@ -1,124 +0,0 @@
/* mbed Microcontroller Library
* Copyright (c) 2018 ARM Limited
*
* 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 TESTS_GENERIC_GATTCLIENT_UTIL_PRETTYPRINTER_H_
#define TESTS_GENERIC_GATTCLIENT_UTIL_PRETTYPRINTER_H_
#include <ostream>
#include <ble/UUID.h>
#include <ble/GattCallbackParamTypes.h>
#include <ble/GattCallbackParamTypes.h>
/*
* UUID pretty printer
*/
inline ::std::ostream& operator<<(::std::ostream& os, const UUID& uuid) {
char str[60];
if (uuid.shortOrLong() == UUID::UUID_TYPE_SHORT) {
sprintf(str, "0x%04X", uuid.getShortUUID());
} else {
const uint8_t* data = uuid.getBaseUUID();
sprintf(
str,
"\"%02X%02X%02X%02X-%02X%02X-%02X%02X-%02X%02X-%02X%02X%02X%02X%02X%02X\"",
data[15], data[14], data[13], data[12], data[11], data[10], data[9], data[8],
data[7], data[6], data[5], data[4], data[3], data[2], data[1], data[0]
);
}
return os << str;
}
/*
* GattReadCallbackParams pretty printer
*/
inline ::std::ostream& operator<<(::std::ostream& os, const GattReadCallbackParams& p) {
os << "connection_handle: " << p.connHandle <<
", handle: " << p.handle <<
", offset: " << p.offset <<
", status: " << p.status;
if (p.status) {
os << ", error_code: " << p.error_code;
} else {
os << ", len: " << p.len;
os << ", data: ";
for (size_t i = 0; i < p.len; ++i) {
os << (int) p.data[i] << " ";
}
}
return os;
}
/*
* attribute_handle_range_t pretty printer
*/
inline ::std::ostream& operator<<(::std::ostream& os, const ble::attribute_handle_range_t& handle_range) {
return os << "(" << handle_range.begin << "," << handle_range.end << ")";
}
/*
* Pretty printer of an view to an array of uint8_t.
*/
inline ::std::ostream& operator<<(::std::ostream& os, const ble::ArrayView<const uint8_t>& array) {
os << "size: " << array.size() << " value: { ";
for (size_t i = 0; i <array.size(); ++i) {
os << (int) array[i] << " ";
}
os << " }";
return os;
}
/*
* DiscoveredCharacteristic pretty printer
*/
inline ::std::ostream& operator<<(::std::ostream& os, const DiscoveredCharacteristic& d) {
return os << "client: " << d.getGattClient() << " " <<
"connection_handle: " << d.getConnectionHandle() << " " <<
"decl_handle: " << d.getDeclHandle() << " " <<
"value_handle: " << d.getValueHandle() << " " <<
"last_handle: " << d.getLastHandle() << " " <<
"uuid: { " << d.getUUID() << " } ";
}
/*
* DiscoveredCharacteristicDescriptor pretty printer
*/
inline ::std::ostream& operator<<(::std::ostream& os, const DiscoveredCharacteristicDescriptor& d) {
return os << "client: " << d.getGattClient() << " " <<
"connection_handle: " << d.getConnectionHandle() << " " <<
"attribute_handle: " << d.getAttributeHandle() << " " <<
"uuid: { " << d.getUUID() << " }";
}
/*
* CharacteristicDescriptorDiscovery::TerminationCallbackParams_t pretty printer
*/
inline ::std::ostream& operator<<(::std::ostream& os, CharacteristicDescriptorDiscovery::TerminationCallbackParams_t& t) {
return os << "characteristic: { " << t.characteristic << " } " <<
"status: " << t.status << " " <<
"error_code: " << t.error_code;
}
/*
* CharacteristicDescriptorDiscovery::DiscoveryCallbackParams_t pretty printer
*/
inline ::std::ostream& operator<<(::std::ostream& os, const CharacteristicDescriptorDiscovery::DiscoveryCallbackParams_t& p) {
return os << "characteristic: { " << p.characteristic << " } " <<
"descriptor: { " << p.descriptor << " } ";
}
#endif /* TESTS_GENERIC_GATTCLIENT_UTIL_PRETTYPRINTER_H_ */

View File

@ -1,32 +0,0 @@
/* mbed Microcontroller Library
* Copyright (c) 2018 ARM Limited
*
* 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 TESTS_GENERIC_GATTCLIENT_UTIL_SERVERDESCRIPTION_H_
#define TESTS_GENERIC_GATTCLIENT_UTIL_SERVERDESCRIPTION_H_
#include <vector>
#include <initializer_list>
#include "ServiceDescription.h"
struct server_description_t {
server_description_t() { }
server_description_t(std::initializer_list<service_description_t> services) :
services(services) { }
std::vector<service_description_t> services;
};
#endif /* TESTS_GENERIC_GATTCLIENT_UTIL_SERVERDESCRIPTION_H_ */

View File

@ -1,44 +0,0 @@
/* mbed Microcontroller Library
* Copyright (c) 2018 ARM Limited
*
* 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 TESTS_GENERIC_GATTCLIENT_UTIL_SERVICEDESCRIPTION_H_
#define TESTS_GENERIC_GATTCLIENT_UTIL_SERVICEDESCRIPTION_H_
#include <vector>
#include <initializer_list>
#include <stdint.h>
#include "ble/UUID.h"
#include "CharacteristicDescription.h"
struct service_description_t {
service_description_t(
uint16_t start,
uint16_t end,
UUID uuid,
std::initializer_list<characteristic_description_t> characteristics
) : start(start),
end(end),
uuid(uuid),
characteristics(characteristics) {
}
uint16_t start;
uint16_t end;
UUID uuid;
std::vector<characteristic_description_t> characteristics;
};
#endif /* TESTS_GENERIC_GATTCLIENT_UTIL_SERVICEDESCRIPTION_H_ */

View File

@ -1,24 +0,0 @@
/* mbed Microcontroller Library
* Copyright (c) 2018 ARM Limited
*
* 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 <stdio.h>
#include <stdlib.h>
void mbed_assert_internal(const char *expr, const char *file, int line)
{
printf("mbed assertation failed: %s, file: %s, line %d \n", expr, file, line);
abort();
}