xref: /btstack/test/att_db/att_db_test.cpp (revision 6fc08a499bec60bdcd9ce5e4f5d33a20a984d7d9)
14902524cSMatthias Ringwald /*
24902524cSMatthias Ringwald  * Copyright (C) 2014 BlueKitchen GmbH
34902524cSMatthias Ringwald  *
44902524cSMatthias Ringwald  * Redistribution and use in source and binary forms, with or without
54902524cSMatthias Ringwald  * modification, are permitted provided that the following conditions
64902524cSMatthias Ringwald  * are met:
74902524cSMatthias Ringwald  *
84902524cSMatthias Ringwald  * 1. Redistributions of source code must retain the above copyright
94902524cSMatthias Ringwald  *    notice, this list of conditions and the following disclaimer.
104902524cSMatthias Ringwald  * 2. Redistributions in binary form must reproduce the above copyright
114902524cSMatthias Ringwald  *    notice, this list of conditions and the following disclaimer in the
124902524cSMatthias Ringwald  *    documentation and/or other materials provided with the distribution.
134902524cSMatthias Ringwald  * 3. Neither the name of the copyright holders nor the names of
144902524cSMatthias Ringwald  *    contributors may be used to endorse or promote products derived
154902524cSMatthias Ringwald  *    from this software without specific prior written permission.
164902524cSMatthias Ringwald  * 4. Any redistribution, use, or modification is done solely for
174902524cSMatthias Ringwald  *    personal benefit and not for any commercial purpose or for
184902524cSMatthias Ringwald  *    monetary gain.
194902524cSMatthias Ringwald  *
204902524cSMatthias Ringwald  * THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS
214902524cSMatthias Ringwald  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
224902524cSMatthias Ringwald  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
234902524cSMatthias Ringwald  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MATTHIAS
244902524cSMatthias Ringwald  * RINGWALD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
254902524cSMatthias Ringwald  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
264902524cSMatthias Ringwald  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
274902524cSMatthias Ringwald  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
284902524cSMatthias Ringwald  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
294902524cSMatthias Ringwald  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
304902524cSMatthias Ringwald  * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
314902524cSMatthias Ringwald  * SUCH DAMAGE.
324902524cSMatthias Ringwald  *
334902524cSMatthias Ringwald  * Please inquire about commercial licensing options at
344902524cSMatthias Ringwald  * [email protected]
354902524cSMatthias Ringwald  *
364902524cSMatthias Ringwald  */
374902524cSMatthias Ringwald 
384902524cSMatthias Ringwald 
394902524cSMatthias Ringwald #include <stdint.h>
404902524cSMatthias Ringwald #include <stdio.h>
414902524cSMatthias Ringwald #include <stdlib.h>
424902524cSMatthias Ringwald #include <string.h>
434902524cSMatthias Ringwald 
444902524cSMatthias Ringwald #include "CppUTest/TestHarness.h"
454902524cSMatthias Ringwald #include "CppUTest/CommandLineTestRunner.h"
464902524cSMatthias Ringwald 
474902524cSMatthias Ringwald #include "hci.h"
484902524cSMatthias Ringwald #include "ble/att_db.h"
494902524cSMatthias Ringwald #include "ble/att_db_util.h"
504902524cSMatthias Ringwald #include "btstack_util.h"
514902524cSMatthias Ringwald #include "bluetooth.h"
524902524cSMatthias Ringwald 
534902524cSMatthias Ringwald #include "btstack_crypto.h"
544902524cSMatthias Ringwald #include "bluetooth_gatt.h"
554902524cSMatthias Ringwald 
564902524cSMatthias Ringwald typedef enum {
574902524cSMatthias Ringwald 	READ_CALLBACK_MODE_RETURN_DEFAULT = 0,
584902524cSMatthias Ringwald 	READ_CALLBACK_MODE_RETURN_ONE_BYTE,
594902524cSMatthias Ringwald 	READ_CALLBACK_MODE_RETURN_PENDING
604902524cSMatthias Ringwald } read_callback_mode_t;
614902524cSMatthias Ringwald 
624902524cSMatthias Ringwald typedef enum {
634902524cSMatthias Ringwald 	WRITE_CALLBACK_MODE_RETURN_DEFAULT = 0,
644902524cSMatthias Ringwald 	WRITE_CALLBACK_MODE_RETURN_ERROR_WRITE_RESPONSE_PENDING,
654902524cSMatthias Ringwald 	WRITE_CALLBACK_MODE_RETURN_INVALID_ATTRIBUTE_VALUE_LENGTH
664902524cSMatthias Ringwald } write_callback_mode_t;
674902524cSMatthias Ringwald 
684902524cSMatthias Ringwald 
694902524cSMatthias Ringwald static uint8_t battery_level = 100;
70*6fc08a49SMilanka Ringwald static uint8_t cgm_status = 0;
71*6fc08a49SMilanka Ringwald 
724902524cSMatthias Ringwald static uint8_t att_request[200];
734902524cSMatthias Ringwald static uint8_t att_response[1000];
744902524cSMatthias Ringwald 
754902524cSMatthias Ringwald static read_callback_mode_t read_callback_mode   = READ_CALLBACK_MODE_RETURN_DEFAULT;
764902524cSMatthias Ringwald static write_callback_mode_t write_callback_mode = WRITE_CALLBACK_MODE_RETURN_DEFAULT;
774902524cSMatthias Ringwald 
784902524cSMatthias Ringwald // these can be tweaked to report errors or some data as needed by test case
att_read_callback(hci_con_handle_t con_handle,uint16_t attribute_handle,uint16_t offset,uint8_t * buffer,uint16_t buffer_size)794902524cSMatthias Ringwald static uint16_t att_read_callback(hci_con_handle_t con_handle, uint16_t attribute_handle, uint16_t offset, uint8_t * buffer, uint16_t buffer_size){
804902524cSMatthias Ringwald 	switch (read_callback_mode){
814902524cSMatthias Ringwald 		case READ_CALLBACK_MODE_RETURN_ONE_BYTE:
824902524cSMatthias Ringwald 			return att_read_callback_handle_byte(0x55, offset, buffer, buffer_size);
834902524cSMatthias Ringwald 		case READ_CALLBACK_MODE_RETURN_PENDING:
844902524cSMatthias Ringwald 			return ATT_READ_RESPONSE_PENDING;
854902524cSMatthias Ringwald 		default:
864902524cSMatthias Ringwald 			return 0;
874902524cSMatthias Ringwald 	}
884902524cSMatthias Ringwald }
894902524cSMatthias Ringwald 
att_write_callback(hci_con_handle_t con_handle,uint16_t attribute_handle,uint16_t transaction_mode,uint16_t offset,uint8_t * buffer,uint16_t buffer_size)904902524cSMatthias Ringwald static int att_write_callback(hci_con_handle_t con_handle, uint16_t attribute_handle, uint16_t transaction_mode, uint16_t offset, uint8_t *buffer, uint16_t buffer_size){
914902524cSMatthias Ringwald 	switch (write_callback_mode){
924902524cSMatthias Ringwald 		case WRITE_CALLBACK_MODE_RETURN_ERROR_WRITE_RESPONSE_PENDING:
934902524cSMatthias Ringwald 			return ATT_ERROR_WRITE_RESPONSE_PENDING;
944902524cSMatthias Ringwald 		case WRITE_CALLBACK_MODE_RETURN_INVALID_ATTRIBUTE_VALUE_LENGTH:
954902524cSMatthias Ringwald 			return ATT_ERROR_INVALID_ATTRIBUTE_VALUE_LENGTH;
964902524cSMatthias Ringwald 		default:
974902524cSMatthias Ringwald 			return 0;
984902524cSMatthias Ringwald 	}
994902524cSMatthias Ringwald }
1004902524cSMatthias Ringwald 
att_read_multiple_request(uint16_t num_value_handles,uint16_t * value_handles)1014902524cSMatthias Ringwald static uint16_t att_read_multiple_request(uint16_t num_value_handles, uint16_t * value_handles){
1024902524cSMatthias Ringwald     att_request[0] = ATT_READ_MULTIPLE_REQUEST;
1034902524cSMatthias Ringwald     int i;
1044902524cSMatthias Ringwald     int offset = 1;
1054902524cSMatthias Ringwald     for (i=0;i<num_value_handles;i++){
1064902524cSMatthias Ringwald         little_endian_store_16(att_request, offset, value_handles[i]);
1074902524cSMatthias Ringwald         offset += 2;
1084902524cSMatthias Ringwald     }
1094902524cSMatthias Ringwald 	return offset;
1104902524cSMatthias Ringwald }
1114902524cSMatthias Ringwald 
att_write_request(uint16_t request_type,uint16_t attribute_handle,uint16_t value_length,const uint8_t * value)1124902524cSMatthias Ringwald static uint16_t att_write_request(uint16_t request_type, uint16_t attribute_handle, uint16_t value_length, const uint8_t * value){
1134902524cSMatthias Ringwald     att_request[0] = request_type;
1144902524cSMatthias Ringwald     little_endian_store_16(att_request, 1, attribute_handle);
1154902524cSMatthias Ringwald     (void)memcpy(&att_request[3], value, value_length);
1164902524cSMatthias Ringwald     return 3 + value_length;
1174902524cSMatthias Ringwald }
1184902524cSMatthias Ringwald 
att_prepare_write_request(uint16_t request_type,uint16_t attribute_handle,uint16_t value_offset)1194902524cSMatthias Ringwald static uint16_t att_prepare_write_request(uint16_t request_type, uint16_t attribute_handle, uint16_t value_offset){
1204902524cSMatthias Ringwald     att_request[0] = request_type;
1214902524cSMatthias Ringwald     little_endian_store_16(att_request, 1, attribute_handle);
1224902524cSMatthias Ringwald     little_endian_store_16(att_request, 3, value_offset);
1234902524cSMatthias Ringwald     return 5;
1244902524cSMatthias Ringwald }
1254902524cSMatthias Ringwald 
1264902524cSMatthias Ringwald // ignore for now
btstack_crypto_aes128_cmac_generator(btstack_crypto_aes128_cmac_t * request,const uint8_t * key,uint16_t size,uint8_t (* get_byte_callback)(uint16_t pos),uint8_t * hash,void (* callback)(void * arg),void * callback_arg)1274902524cSMatthias Ringwald extern "C" void btstack_crypto_aes128_cmac_generator(btstack_crypto_aes128_cmac_t * request, const uint8_t * key, uint16_t size, uint8_t (*get_byte_callback)(uint16_t pos), uint8_t * hash, void (* callback)(void * arg), void * callback_arg){
1284902524cSMatthias Ringwald }
1294902524cSMatthias Ringwald 
TEST_GROUP(AttDb)1304902524cSMatthias Ringwald TEST_GROUP(AttDb){
1314902524cSMatthias Ringwald 	att_connection_t att_connection;
1324902524cSMatthias Ringwald 	uint16_t att_request_len;
1334902524cSMatthias Ringwald 	uint16_t att_response_len;
1344902524cSMatthias Ringwald 	uint8_t  callback_buffer[10];
1354902524cSMatthias Ringwald 
1364902524cSMatthias Ringwald     void setup(void){
1374902524cSMatthias Ringwald     	memset(&callback_buffer, 0, sizeof(callback_buffer));
1384902524cSMatthias Ringwald 
1394902524cSMatthias Ringwald     	read_callback_mode = READ_CALLBACK_MODE_RETURN_ONE_BYTE;
1404902524cSMatthias Ringwald     	memset(&att_connection, 0, sizeof(att_connection));
1414902524cSMatthias Ringwald     	att_connection.max_mtu = 150;
1424902524cSMatthias Ringwald 		att_connection.mtu = ATT_DEFAULT_MTU;
1434902524cSMatthias Ringwald 
1444902524cSMatthias Ringwald 		write_callback_mode = WRITE_CALLBACK_MODE_RETURN_DEFAULT;
1454902524cSMatthias Ringwald 		read_callback_mode  = READ_CALLBACK_MODE_RETURN_DEFAULT;
1464902524cSMatthias Ringwald 
1474902524cSMatthias Ringwald     	// init att db util and add a service and characteristic
1484902524cSMatthias Ringwald 		att_db_util_init();
1494902524cSMatthias Ringwald 		// 0x180F
1504902524cSMatthias Ringwald 		att_db_util_add_service_uuid16(ORG_BLUETOOTH_SERVICE_BATTERY_SERVICE);
1514902524cSMatthias Ringwald 		// 0x2A19
1524902524cSMatthias Ringwald 		att_db_util_add_characteristic_uuid16(ORG_BLUETOOTH_CHARACTERISTIC_BATTERY_LEVEL,       ATT_PROPERTY_WRITE | ATT_PROPERTY_READ | ATT_PROPERTY_NOTIFY, ATT_SECURITY_NONE, ATT_SECURITY_NONE, &battery_level, 1);
1534902524cSMatthias Ringwald 		// 0x2A1B
1544902524cSMatthias Ringwald 		att_db_util_add_characteristic_uuid16(ORG_BLUETOOTH_CHARACTERISTIC_BATTERY_LEVEL_STATE, ATT_PROPERTY_NOTIFY, ATT_SECURITY_NONE, ATT_SECURITY_NONE, &battery_level, 1);
1554902524cSMatthias Ringwald 		// 0x2A1A
1564902524cSMatthias Ringwald 		att_db_util_add_characteristic_uuid16(ORG_BLUETOOTH_CHARACTERISTIC_BATTERY_POWER_STATE, ATT_PROPERTY_READ | ATT_PROPERTY_NOTIFY, ATT_SECURITY_AUTHENTICATED, ATT_SECURITY_AUTHENTICATED, &battery_level, 1);
1574902524cSMatthias Ringwald 		// 0x2A49
1584902524cSMatthias Ringwald 		att_db_util_add_characteristic_uuid16(ORG_BLUETOOTH_CHARACTERISTIC_BLOOD_PRESSURE_FEATURE, ATT_PROPERTY_DYNAMIC | ATT_PROPERTY_READ | ATT_PROPERTY_NOTIFY, ATT_SECURITY_NONE, ATT_SECURITY_NONE, &battery_level, 1);
1594902524cSMatthias Ringwald 		// 0x2A35
1604902524cSMatthias Ringwald 		att_db_util_add_characteristic_uuid16(ORG_BLUETOOTH_CHARACTERISTIC_BLOOD_PRESSURE_MEASUREMENT, ATT_PROPERTY_WRITE | ATT_PROPERTY_DYNAMIC, ATT_SECURITY_AUTHENTICATED, ATT_SECURITY_AUTHENTICATED, &battery_level, 1);
1614902524cSMatthias Ringwald 		// 0x2A38
1624902524cSMatthias Ringwald 		att_db_util_add_characteristic_uuid16(ORG_BLUETOOTH_CHARACTERISTIC_BODY_SENSOR_LOCATION, ATT_PROPERTY_WRITE | ATT_PROPERTY_DYNAMIC | ATT_PROPERTY_NOTIFY, ATT_SECURITY_NONE, ATT_SECURITY_NONE, &battery_level, 1);
1634902524cSMatthias Ringwald 
1644902524cSMatthias Ringwald 		const uint8_t uuid128[] = {0x00, 0x00, 0xFF, 0x11, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0x80, 0x5F, 0x9B, 0x34, 0xFB};
1654902524cSMatthias Ringwald 		att_db_util_add_characteristic_uuid128(uuid128, ATT_PROPERTY_WRITE | ATT_PROPERTY_DYNAMIC | ATT_PROPERTY_NOTIFY, ATT_SECURITY_NONE, ATT_SECURITY_NONE, &battery_level, 1);
1664902524cSMatthias Ringwald 
1674902524cSMatthias Ringwald 		// 0x2AA7
1684902524cSMatthias Ringwald 		att_db_util_add_characteristic_uuid16(ORG_BLUETOOTH_CHARACTERISTIC_CGM_MEASUREMENT, ATT_PROPERTY_WRITE_WITHOUT_RESPONSE | ATT_PROPERTY_DYNAMIC | ATT_PROPERTY_NOTIFY, ATT_SECURITY_AUTHENTICATED, ATT_SECURITY_AUTHENTICATED, &battery_level, 1);
1694902524cSMatthias Ringwald 
1704902524cSMatthias Ringwald 		// 0x2AAB
1714902524cSMatthias Ringwald 		att_db_util_add_characteristic_uuid16(ORG_BLUETOOTH_CHARACTERISTIC_CGM_SESSION_RUN_TIME, ATT_PROPERTY_WRITE_WITHOUT_RESPONSE | ATT_PROPERTY_DYNAMIC | ATT_PROPERTY_NOTIFY, ATT_SECURITY_NONE, ATT_SECURITY_NONE, &battery_level, 1);
172*6fc08a49SMilanka Ringwald 		// 0x2A5C
173*6fc08a49SMilanka Ringwald         att_db_util_add_characteristic_uuid16(ORG_BLUETOOTH_CHARACTERISTIC_CSC_FEATURE, ATT_PROPERTY_AUTHENTICATED_SIGNED_WRITE | ATT_PROPERTY_DYNAMIC, ATT_SECURITY_NONE, ATT_SECURITY_NONE, &battery_level, 1);
1744902524cSMatthias Ringwald 
175*6fc08a49SMilanka Ringwald         const uint8_t uuid128_service[] = {0xAA, 0xBB, 0xFF, 0x11, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0x80, 0x5F, 0x9B, 0x34, 0xFB};
176*6fc08a49SMilanka Ringwald         att_db_util_add_service_uuid128(uuid128_service);
177*6fc08a49SMilanka Ringwald         // 0x2AA9
178*6fc08a49SMilanka Ringwald 		att_db_util_add_characteristic_uuid16(ORG_BLUETOOTH_CHARACTERISTIC_CGM_STATUS, ATT_PROPERTY_WRITE_WITHOUT_RESPONSE | ATT_PROPERTY_DYNAMIC | ATT_PROPERTY_NOTIFY, ATT_SECURITY_NONE, ATT_SECURITY_NONE, &cgm_status, 1);
179*6fc08a49SMilanka Ringwald 
180*6fc08a49SMilanka Ringwald 		const uint8_t uuid128_chr_no_notify[] = {0xAA, 0xCC, 0xFF, 0x11, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0x80, 0x5F, 0x9B, 0x34, 0xFB};
181*6fc08a49SMilanka Ringwald 		att_db_util_add_characteristic_uuid128(uuid128_chr_no_notify, ATT_PROPERTY_WRITE | ATT_PROPERTY_DYNAMIC, ATT_SECURITY_NONE, ATT_SECURITY_NONE, &battery_level, 1);
182*6fc08a49SMilanka Ringwald 
183*6fc08a49SMilanka Ringwald 		att_db_util_add_included_service_uuid16(0x50, 0x51, 0xAACC);
184*6fc08a49SMilanka Ringwald 
185*6fc08a49SMilanka Ringwald 		// const uint8_t uuid128_incl_service[] = {0xAA, 0xEE, 0xFF, 0x11, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0x80, 0x5F, 0x9B, 0x34, 0xFB};
186*6fc08a49SMilanka Ringwald 		// att_db_util_add_included_service_uuid128(0x50, 0x51, uuid128_incl_service);
1874902524cSMatthias Ringwald 		// set callbacks
1884902524cSMatthias Ringwald 		att_set_db(att_db_util_get_address());
1894902524cSMatthias Ringwald 		att_set_read_callback(&att_read_callback);
1904902524cSMatthias Ringwald 		att_set_write_callback(&att_write_callback);
1914902524cSMatthias Ringwald 	}
1924902524cSMatthias Ringwald };
1934902524cSMatthias Ringwald 
TEST(AttDb,SetDB_NullAddress)194*6fc08a49SMilanka Ringwald TEST(AttDb, SetDB_NullAddress){
195*6fc08a49SMilanka Ringwald 	// test some function
196*6fc08a49SMilanka Ringwald 	att_set_db(NULL);
197*6fc08a49SMilanka Ringwald }
198*6fc08a49SMilanka Ringwald 
199*6fc08a49SMilanka Ringwald 
TEST(AttDb,MtuExchange)2004902524cSMatthias Ringwald TEST(AttDb, MtuExchange){
2014902524cSMatthias Ringwald 	// test some function
2024902524cSMatthias Ringwald 	att_request_len = 3;
2034902524cSMatthias Ringwald 	const uint8_t att_request[3] = { ATT_EXCHANGE_MTU_REQUEST, 0, att_connection.max_mtu};
2044902524cSMatthias Ringwald 	att_response_len = att_handle_request(&att_connection, (uint8_t *) att_request, att_request_len, att_response);
2054902524cSMatthias Ringwald 	CHECK_EQUAL(att_request_len, att_response_len);
2064902524cSMatthias Ringwald 	const uint8_t expected_response[] = { ATT_EXCHANGE_MTU_RESPONSE, att_connection.max_mtu, 0};
2074902524cSMatthias Ringwald 	MEMCMP_EQUAL(expected_response, att_response, att_response_len);
2084902524cSMatthias Ringwald }
2094902524cSMatthias Ringwald 
2104902524cSMatthias Ringwald 
TEST(AttDb,handle_read_multiple_request)2114902524cSMatthias Ringwald TEST(AttDb, handle_read_multiple_request){
2124902524cSMatthias Ringwald 	uint16_t value_handles[2];
2134902524cSMatthias Ringwald 	uint16_t num_value_handles;
2144902524cSMatthias Ringwald 
2154902524cSMatthias Ringwald 	// less then two values
2164902524cSMatthias Ringwald 	num_value_handles = 0;
2174902524cSMatthias Ringwald 	memset(&value_handles, 0, sizeof(value_handles));
2184902524cSMatthias Ringwald 	{
2194902524cSMatthias Ringwald 		att_request_len = att_read_multiple_request(num_value_handles, value_handles);
2204902524cSMatthias Ringwald 		CHECK_EQUAL(1 + 2 * num_value_handles, att_request_len);
2214902524cSMatthias Ringwald 		att_response_len = att_handle_request(&att_connection, (uint8_t *) att_request, att_request_len, att_response);
2224902524cSMatthias Ringwald 		const uint8_t expected_response[] = {ATT_ERROR_RESPONSE, ATT_READ_MULTIPLE_REQUEST, 0, 0, ATT_ERROR_INVALID_PDU};
2234902524cSMatthias Ringwald 		CHECK_EQUAL(sizeof(expected_response), att_response_len);
2244902524cSMatthias Ringwald 		MEMCMP_EQUAL(expected_response, att_response, att_response_len);
2254902524cSMatthias Ringwald 	}
2264902524cSMatthias Ringwald 
2274902524cSMatthias Ringwald 	num_value_handles = 1;
2284902524cSMatthias Ringwald 	value_handles[0] = 0x1;
2294902524cSMatthias Ringwald 	{
2304902524cSMatthias Ringwald 		att_request_len = att_read_multiple_request(num_value_handles, value_handles);
2314902524cSMatthias Ringwald 		CHECK_EQUAL(1 + 2 * num_value_handles, att_request_len);
2324902524cSMatthias Ringwald 		att_response_len = att_handle_request(&att_connection, (uint8_t *) att_request, att_request_len, att_response);
2334902524cSMatthias Ringwald 		const uint8_t expected_response[] = {ATT_ERROR_RESPONSE, ATT_READ_MULTIPLE_REQUEST, 0, 0, ATT_ERROR_INVALID_PDU};
2344902524cSMatthias Ringwald 		CHECK_EQUAL(sizeof(expected_response), att_response_len);
2354902524cSMatthias Ringwald 		MEMCMP_EQUAL(expected_response, att_response, att_response_len);
2364902524cSMatthias Ringwald 	}
2374902524cSMatthias Ringwald 
2384902524cSMatthias Ringwald 	// invalid handle
2394902524cSMatthias Ringwald 	num_value_handles = 2;
2404902524cSMatthias Ringwald 	value_handles[0] = 0x0;
2414902524cSMatthias Ringwald 	{
2424902524cSMatthias Ringwald 		att_request_len = att_read_multiple_request(num_value_handles, value_handles);
2434902524cSMatthias Ringwald 		CHECK_EQUAL(1 + 2 * num_value_handles, att_request_len);
2444902524cSMatthias Ringwald 		att_response_len = att_handle_request(&att_connection, (uint8_t *) att_request, att_request_len, att_response);
2454902524cSMatthias Ringwald 		const uint8_t expected_response[] = {ATT_ERROR_RESPONSE, ATT_READ_MULTIPLE_REQUEST, 0, 0, ATT_ERROR_INVALID_HANDLE};
2464902524cSMatthias Ringwald 		CHECK_EQUAL(sizeof(expected_response), att_response_len);
2474902524cSMatthias Ringwald 		MEMCMP_EQUAL(expected_response, att_response, att_response_len);
2484902524cSMatthias Ringwald 	}
2494902524cSMatthias Ringwald 
2504902524cSMatthias Ringwald 	num_value_handles = 2;
2514902524cSMatthias Ringwald 	value_handles[0] = 0xF1;
2524902524cSMatthias Ringwald 	value_handles[1] = 0xF2;
2534902524cSMatthias Ringwald 	{
2544902524cSMatthias Ringwald 		att_request_len = att_read_multiple_request(num_value_handles, value_handles);
2554902524cSMatthias Ringwald 		CHECK_EQUAL(1 + 2 * num_value_handles, att_request_len);
2564902524cSMatthias Ringwald 		att_response_len = att_handle_request(&att_connection, (uint8_t *) att_request, att_request_len, att_response);
2574902524cSMatthias Ringwald 		const uint8_t expected_response[] = {ATT_ERROR_RESPONSE, ATT_READ_MULTIPLE_REQUEST, value_handles[0], 0, ATT_ERROR_INVALID_HANDLE};
2584902524cSMatthias Ringwald 		CHECK_EQUAL(sizeof(expected_response), att_response_len);
2594902524cSMatthias Ringwald 		MEMCMP_EQUAL(expected_response, att_response, att_response_len);
2604902524cSMatthias Ringwald 	}
2614902524cSMatthias Ringwald 
2624902524cSMatthias Ringwald 	// handle read not permitted
2634902524cSMatthias Ringwald 	num_value_handles = 2;
2644902524cSMatthias Ringwald 	value_handles[0] = 0x05;
2654902524cSMatthias Ringwald 	value_handles[1] = 0x06;
2664902524cSMatthias Ringwald 	{
2674902524cSMatthias Ringwald 		att_request_len = att_read_multiple_request(num_value_handles, value_handles);
2684902524cSMatthias Ringwald 		CHECK_EQUAL(1 + 2 * num_value_handles, att_request_len);
2694902524cSMatthias Ringwald 		att_response_len = att_handle_request(&att_connection, (uint8_t *) att_request, att_request_len, att_response);
2704902524cSMatthias Ringwald 		const uint8_t expected_response[] = {ATT_ERROR_RESPONSE, ATT_READ_MULTIPLE_REQUEST, value_handles[1], 0, ATT_ERROR_READ_NOT_PERMITTED};
2714902524cSMatthias Ringwald 		CHECK_EQUAL(sizeof(expected_response), att_response_len);
2724902524cSMatthias Ringwald 		MEMCMP_EQUAL(expected_response, att_response, att_response_len);
2734902524cSMatthias Ringwald 	}
2744902524cSMatthias Ringwald 
2754902524cSMatthias Ringwald 	// security validation (single case)
2764902524cSMatthias Ringwald 	num_value_handles = 2;
2774902524cSMatthias Ringwald 	value_handles[0] = 0x05;
2784902524cSMatthias Ringwald 	value_handles[1] = 0x09;
2794902524cSMatthias Ringwald 	{
2804902524cSMatthias Ringwald 		att_request_len = att_read_multiple_request(num_value_handles, value_handles);
2814902524cSMatthias Ringwald 		CHECK_EQUAL(1 + 2 * num_value_handles, att_request_len);
2824902524cSMatthias Ringwald 		att_response_len = att_handle_request(&att_connection, (uint8_t *) att_request, att_request_len, att_response);
2834902524cSMatthias Ringwald 		const uint8_t expected_response[] = {ATT_ERROR_RESPONSE, ATT_READ_MULTIPLE_REQUEST, value_handles[1], 0, ATT_ERROR_INSUFFICIENT_AUTHENTICATION};
2844902524cSMatthias Ringwald 		CHECK_EQUAL(sizeof(expected_response), att_response_len);
2854902524cSMatthias Ringwald 		MEMCMP_EQUAL(expected_response, att_response, att_response_len);
2864902524cSMatthias Ringwald 	}
2874902524cSMatthias Ringwald 
2884902524cSMatthias Ringwald 
2894902524cSMatthias Ringwald 	// static read
2904902524cSMatthias Ringwald 	num_value_handles = 2;
2914902524cSMatthias Ringwald 	value_handles[0] = 0x03;
2924902524cSMatthias Ringwald 	value_handles[1] = 0x05;
2934902524cSMatthias Ringwald 	{
2944902524cSMatthias Ringwald 		read_callback_mode = READ_CALLBACK_MODE_RETURN_ONE_BYTE;
2954902524cSMatthias Ringwald 
2964902524cSMatthias Ringwald 		att_request_len = att_read_multiple_request(num_value_handles, value_handles);
2974902524cSMatthias Ringwald 		CHECK_EQUAL(1 + 2 * num_value_handles, att_request_len);
2984902524cSMatthias Ringwald 		att_response_len = att_handle_request(&att_connection, (uint8_t *) att_request, att_request_len, att_response);
2994902524cSMatthias Ringwald 		const uint8_t expected_response[] = {ATT_READ_MULTIPLE_RESPONSE, 0x64, 0x10, 0x06, 0x00, 0x1B, 0x2A};
3004902524cSMatthias Ringwald 		CHECK_EQUAL(sizeof(expected_response), att_response_len);
3014902524cSMatthias Ringwald 		MEMCMP_EQUAL(expected_response, att_response, att_response_len);
3024902524cSMatthias Ringwald 
3034902524cSMatthias Ringwald 		read_callback_mode = READ_CALLBACK_MODE_RETURN_DEFAULT;
3044902524cSMatthias Ringwald 	}
3054902524cSMatthias Ringwald 
3064902524cSMatthias Ringwald #ifdef ENABLE_ATT_DELAYED_RESPONSE
3074902524cSMatthias Ringwald 	// dynamic read
3084902524cSMatthias Ringwald 	num_value_handles = 2;
3094902524cSMatthias Ringwald 	value_handles[0] = 0x03;
3104902524cSMatthias Ringwald 	value_handles[1] = 0x0c;
3114902524cSMatthias Ringwald 	{
3124902524cSMatthias Ringwald 		read_callback_mode = READ_CALLBACK_MODE_RETURN_PENDING;
3134902524cSMatthias Ringwald 
3144902524cSMatthias Ringwald 		att_request_len = att_read_multiple_request(num_value_handles, value_handles);
3154902524cSMatthias Ringwald 		CHECK_EQUAL(1 + 2 * num_value_handles, att_request_len);
3164902524cSMatthias Ringwald 		att_response_len = att_handle_request(&att_connection, (uint8_t *) att_request, att_request_len, att_response);
3174902524cSMatthias Ringwald 		const uint8_t expected_response[] = {ATT_READ_MULTIPLE_RESPONSE, 0x64};
3184902524cSMatthias Ringwald 		CHECK_EQUAL(sizeof(expected_response), att_response_len);
3194902524cSMatthias Ringwald 		MEMCMP_EQUAL(expected_response, att_response, att_response_len);
3204902524cSMatthias Ringwald 
3214902524cSMatthias Ringwald 		read_callback_mode = READ_CALLBACK_MODE_RETURN_DEFAULT;
3224902524cSMatthias Ringwald 	}
3234902524cSMatthias Ringwald #endif
3244902524cSMatthias Ringwald }
3254902524cSMatthias Ringwald 
TEST(AttDb,handle_write_request)3264902524cSMatthias Ringwald TEST(AttDb, handle_write_request){
3274902524cSMatthias Ringwald 	uint16_t attribute_handle = 0x03;
3284902524cSMatthias Ringwald 
3294902524cSMatthias Ringwald 	// not sufficient request length
3304902524cSMatthias Ringwald 	{
3314902524cSMatthias Ringwald 		att_request[0] = ATT_WRITE_REQUEST;
3324902524cSMatthias Ringwald 		att_request_len = 1;
3334902524cSMatthias Ringwald 		att_response_len = att_handle_request(&att_connection, (uint8_t *) att_request, att_request_len, att_response);
3344902524cSMatthias Ringwald 		const uint8_t expected_response[] = {ATT_ERROR_RESPONSE, att_request[0], 0x00, 0x00, ATT_ERROR_INVALID_PDU};
3354902524cSMatthias Ringwald 		MEMCMP_EQUAL(expected_response, att_response, att_response_len);
3364902524cSMatthias Ringwald 		CHECK_EQUAL(sizeof(expected_response), att_response_len);
3374902524cSMatthias Ringwald 	}
3384902524cSMatthias Ringwald 
3394902524cSMatthias Ringwald 	{
3404902524cSMatthias Ringwald 		att_request[0] = ATT_WRITE_REQUEST;
3414902524cSMatthias Ringwald 		att_request[1] = 0x03;
3424902524cSMatthias Ringwald 		att_request_len = 2;
3434902524cSMatthias Ringwald 		att_response_len = att_handle_request(&att_connection, (uint8_t *) att_request, att_request_len, att_response);
3444902524cSMatthias Ringwald 		const uint8_t expected_response[] = {ATT_ERROR_RESPONSE, att_request[0], 0x00, 0x00, ATT_ERROR_INVALID_PDU};
3454902524cSMatthias Ringwald 		MEMCMP_EQUAL(expected_response, att_response, att_response_len);
3464902524cSMatthias Ringwald 		CHECK_EQUAL(sizeof(expected_response), att_response_len);
3474902524cSMatthias Ringwald 	}
3484902524cSMatthias Ringwald 
3494902524cSMatthias Ringwald 	// invalid handle
3504902524cSMatthias Ringwald 	{
3514902524cSMatthias Ringwald 		att_request[0] = ATT_WRITE_REQUEST;
3524902524cSMatthias Ringwald 		att_request[1] = 0;
3534902524cSMatthias Ringwald 		att_request[2] = 0;
3544902524cSMatthias Ringwald 		att_request_len = 3;
3554902524cSMatthias Ringwald 		att_response_len = att_handle_request(&att_connection, (uint8_t *) att_request, att_request_len, att_response);
3564902524cSMatthias Ringwald 		const uint8_t expected_response[] = {ATT_ERROR_RESPONSE, att_request[0], att_request[1], att_request[2], ATT_ERROR_INVALID_HANDLE};
3574902524cSMatthias Ringwald 		MEMCMP_EQUAL(expected_response, att_response, att_response_len);
3584902524cSMatthias Ringwald 		CHECK_EQUAL(sizeof(expected_response), att_response_len);
3594902524cSMatthias Ringwald 	}
3604902524cSMatthias Ringwald 
3614902524cSMatthias Ringwald 	// write not permited: invalid write callback
3624902524cSMatthias Ringwald 	{
3634902524cSMatthias Ringwald 		att_set_write_callback(NULL);
3644902524cSMatthias Ringwald 
3654902524cSMatthias Ringwald 		const uint8_t value[] = {0x50};
3664902524cSMatthias Ringwald 		att_request_len = att_write_request(ATT_WRITE_REQUEST, attribute_handle, sizeof(value), value);
3674902524cSMatthias Ringwald 		CHECK_EQUAL(3 + sizeof(value), att_request_len);
3684902524cSMatthias Ringwald 		att_response_len = att_handle_request(&att_connection, (uint8_t *) att_request, att_request_len, att_response);
3694902524cSMatthias Ringwald 		const uint8_t expected_response[] = {ATT_ERROR_RESPONSE, att_request[0], att_request[1], att_request[2], ATT_ERROR_WRITE_NOT_PERMITTED};
3704902524cSMatthias Ringwald 		MEMCMP_EQUAL(expected_response, att_response, att_response_len);
3714902524cSMatthias Ringwald 		CHECK_EQUAL(sizeof(expected_response), att_response_len);
3724902524cSMatthias Ringwald 
3734902524cSMatthias Ringwald 		att_set_write_callback(&att_write_callback);
3744902524cSMatthias Ringwald 	}
3754902524cSMatthias Ringwald 
3764902524cSMatthias Ringwald 	// write not permited: no ATT_PROPERTY_WRITE
3774902524cSMatthias Ringwald 	{
3784902524cSMatthias Ringwald 		const uint8_t value[] = {0x50};
3794902524cSMatthias Ringwald 		attribute_handle = 0x000c; // 0x2A49
3804902524cSMatthias Ringwald 		att_request_len = att_write_request(ATT_WRITE_REQUEST, attribute_handle, sizeof(value), value);
3814902524cSMatthias Ringwald 		CHECK_EQUAL(3 + sizeof(value), att_request_len);
3824902524cSMatthias Ringwald 		att_response_len = att_handle_request(&att_connection, (uint8_t *) att_request, att_request_len, att_response);
3834902524cSMatthias Ringwald 		const uint8_t expected_response[] = {ATT_ERROR_RESPONSE, att_request[0], att_request[1], att_request[2], ATT_ERROR_WRITE_NOT_PERMITTED};
3844902524cSMatthias Ringwald 		MEMCMP_EQUAL(expected_response, att_response, att_response_len);
3854902524cSMatthias Ringwald 		CHECK_EQUAL(sizeof(expected_response), att_response_len);
3864902524cSMatthias Ringwald 	}
3874902524cSMatthias Ringwald 
3884902524cSMatthias Ringwald 	// write not permited: no ATT_PROPERTY_DYNAMIC
3894902524cSMatthias Ringwald 	{
3904902524cSMatthias Ringwald 		const uint8_t value[] = {0x50};
3914902524cSMatthias Ringwald 		attribute_handle = 0x0003;
3924902524cSMatthias Ringwald 		att_request_len = att_write_request(ATT_WRITE_REQUEST, attribute_handle, sizeof(value), value);
3934902524cSMatthias Ringwald 		CHECK_EQUAL(3 + sizeof(value), att_request_len);
3944902524cSMatthias Ringwald 		att_response_len = att_handle_request(&att_connection, (uint8_t *) att_request, att_request_len, att_response);
3954902524cSMatthias Ringwald 		const uint8_t expected_response[] = {ATT_ERROR_RESPONSE, att_request[0], att_request[1], att_request[2], ATT_ERROR_WRITE_NOT_PERMITTED};
3964902524cSMatthias Ringwald 		MEMCMP_EQUAL(expected_response, att_response, att_response_len);
3974902524cSMatthias Ringwald 		CHECK_EQUAL(sizeof(expected_response), att_response_len);
3984902524cSMatthias Ringwald 	}
3994902524cSMatthias Ringwald 
4004902524cSMatthias Ringwald 	// security validation
4014902524cSMatthias Ringwald 	{
4024902524cSMatthias Ringwald 		const uint8_t value[] = {0x50};
4034902524cSMatthias Ringwald 		attribute_handle = 0x000f; // 0x2A35
4044902524cSMatthias Ringwald 		att_request_len = att_write_request(ATT_WRITE_REQUEST, attribute_handle, sizeof(value), value);
4054902524cSMatthias Ringwald 		CHECK_EQUAL(3 + sizeof(value), att_request_len);
4064902524cSMatthias Ringwald 		att_response_len = att_handle_request(&att_connection, (uint8_t *) att_request, att_request_len, att_response);
4074902524cSMatthias Ringwald 		const uint8_t expected_response[] = {ATT_ERROR_RESPONSE, att_request[0], att_request[1], att_request[2], ATT_ERROR_INSUFFICIENT_AUTHENTICATION};
4084902524cSMatthias Ringwald 		MEMCMP_EQUAL(expected_response, att_response, att_response_len);
4094902524cSMatthias Ringwald 		CHECK_EQUAL(sizeof(expected_response), att_response_len);
4104902524cSMatthias Ringwald 	}
4114902524cSMatthias Ringwald 
4124902524cSMatthias Ringwald 	// att_persistent_ccc_cache: ATT_PROPERTY_UUID16
4134902524cSMatthias Ringwald 	// att_persistent_ccc_cache: ATT_PROPERTY_UUID128
4144902524cSMatthias Ringwald 
4154902524cSMatthias Ringwald 	// some callback error other then ATT_INTERNAL_WRITE_RESPONSE_PENDING
4164902524cSMatthias Ringwald 	{
4174902524cSMatthias Ringwald 		write_callback_mode = WRITE_CALLBACK_MODE_RETURN_INVALID_ATTRIBUTE_VALUE_LENGTH;
4184902524cSMatthias Ringwald 
4194902524cSMatthias Ringwald 		const uint8_t value[] = {0x50};
4204902524cSMatthias Ringwald 		attribute_handle = 0x0011; // 0x2A38
4214902524cSMatthias Ringwald 		att_request_len = att_write_request(ATT_WRITE_REQUEST, attribute_handle, sizeof(value), value);
4224902524cSMatthias Ringwald 		CHECK_EQUAL(3 + sizeof(value), att_request_len);
4234902524cSMatthias Ringwald 		att_response_len = att_handle_request(&att_connection, (uint8_t *) att_request, att_request_len, att_response);
4244902524cSMatthias Ringwald 		const uint8_t expected_response[] = {ATT_ERROR_RESPONSE, att_request[0], att_request[1], att_request[2], ATT_ERROR_INVALID_ATTRIBUTE_VALUE_LENGTH};
4254902524cSMatthias Ringwald 		MEMCMP_EQUAL(expected_response, att_response, att_response_len);
4264902524cSMatthias Ringwald 		CHECK_EQUAL(sizeof(expected_response), att_response_len);
4274902524cSMatthias Ringwald 
4284902524cSMatthias Ringwald 		write_callback_mode = WRITE_CALLBACK_MODE_RETURN_DEFAULT;
4294902524cSMatthias Ringwald 	}
4304902524cSMatthias Ringwald 
4314902524cSMatthias Ringwald #ifdef ENABLE_ATT_DELAYED_RESPONSE
4324902524cSMatthias Ringwald 	// delayed response
4334902524cSMatthias Ringwald 	{
4344902524cSMatthias Ringwald 		write_callback_mode = WRITE_CALLBACK_MODE_RETURN_ERROR_WRITE_RESPONSE_PENDING;
4354902524cSMatthias Ringwald 
4364902524cSMatthias Ringwald 		const uint8_t value[] = {0x50};
4374902524cSMatthias Ringwald 		attribute_handle = 0x0011; // 0x2A38
4384902524cSMatthias Ringwald 		att_request_len = att_write_request(ATT_WRITE_REQUEST, attribute_handle, sizeof(value), value);
4394902524cSMatthias Ringwald 		CHECK_EQUAL(3 + sizeof(value), att_request_len);
4404902524cSMatthias Ringwald 		att_response_len = att_handle_request(&att_connection, (uint8_t *) att_request, att_request_len, att_response);
4414902524cSMatthias Ringwald 		CHECK_EQUAL(ATT_INTERNAL_WRITE_RESPONSE_PENDING, att_response_len);
4424902524cSMatthias Ringwald 
4434902524cSMatthias Ringwald 		write_callback_mode = WRITE_CALLBACK_MODE_RETURN_DEFAULT;
4444902524cSMatthias Ringwald 	}
4454902524cSMatthias Ringwald #endif
4464902524cSMatthias Ringwald 
4474902524cSMatthias Ringwald 	// correct write
4484902524cSMatthias Ringwald 	{
4494902524cSMatthias Ringwald 		const uint8_t value[] = {0x50};
4504902524cSMatthias Ringwald 		attribute_handle = 0x0011;
4514902524cSMatthias Ringwald 		att_request_len = att_write_request(ATT_WRITE_REQUEST, attribute_handle, sizeof(value), value);
4524902524cSMatthias Ringwald 		CHECK_EQUAL(3 + sizeof(value), att_request_len);
4534902524cSMatthias Ringwald 		att_response_len = att_handle_request(&att_connection, (uint8_t *) att_request, att_request_len, att_response);
4544902524cSMatthias Ringwald 		const uint8_t expected_response[] = {ATT_WRITE_RESPONSE};
4554902524cSMatthias Ringwald 		MEMCMP_EQUAL(expected_response, att_response, att_response_len);
4564902524cSMatthias Ringwald 		CHECK_EQUAL(sizeof(expected_response), att_response_len);
4574902524cSMatthias Ringwald 	}
4584902524cSMatthias Ringwald }
4594902524cSMatthias Ringwald 
TEST(AttDb,handle_prepare_write_request)4604902524cSMatthias Ringwald TEST(AttDb, handle_prepare_write_request){
4614902524cSMatthias Ringwald 	uint16_t attribute_handle = 0x0011;
4624902524cSMatthias Ringwald 	uint16_t value_offset = 0x10;
4634902524cSMatthias Ringwald 
4644902524cSMatthias Ringwald 	// not sufficient request length
4654902524cSMatthias Ringwald 	{
4664902524cSMatthias Ringwald 		att_request[0] = ATT_PREPARE_WRITE_REQUEST;
4674902524cSMatthias Ringwald 		att_request_len = 1;
4684902524cSMatthias Ringwald 		att_response_len = att_handle_request(&att_connection, (uint8_t *) att_request, att_request_len, att_response);
4694902524cSMatthias Ringwald 		const uint8_t expected_response[] = {ATT_ERROR_RESPONSE, att_request[0], 0x00, 0x00, ATT_ERROR_INVALID_PDU};
4704902524cSMatthias Ringwald 		MEMCMP_EQUAL(expected_response, att_response, att_response_len);
4714902524cSMatthias Ringwald 		CHECK_EQUAL(sizeof(expected_response), att_response_len);
4724902524cSMatthias Ringwald 	}
4734902524cSMatthias Ringwald 
4744902524cSMatthias Ringwald 	// write not permited: invalid write callback
4754902524cSMatthias Ringwald 	{
4764902524cSMatthias Ringwald 		att_set_write_callback(NULL);
4774902524cSMatthias Ringwald 
4784902524cSMatthias Ringwald 		att_request_len = att_prepare_write_request(ATT_PREPARE_WRITE_REQUEST, attribute_handle, value_offset);
4794902524cSMatthias Ringwald 		CHECK_EQUAL(5, att_request_len);
4804902524cSMatthias Ringwald 		att_response_len = att_handle_request(&att_connection, (uint8_t *) att_request, att_request_len, att_response);
4814902524cSMatthias Ringwald 		const uint8_t expected_response[] = {ATT_ERROR_RESPONSE, att_request[0], att_request[1], att_request[2], ATT_ERROR_WRITE_NOT_PERMITTED};
4824902524cSMatthias Ringwald 		MEMCMP_EQUAL(expected_response, att_response, att_response_len);
4834902524cSMatthias Ringwald 		CHECK_EQUAL(sizeof(expected_response), att_response_len);
4844902524cSMatthias Ringwald 
4854902524cSMatthias Ringwald 		att_set_write_callback(&att_write_callback);
4864902524cSMatthias Ringwald 	}
4874902524cSMatthias Ringwald 
4884902524cSMatthias Ringwald 	// invalid handle
4894902524cSMatthias Ringwald 	{
4904902524cSMatthias Ringwald 		att_request_len = att_prepare_write_request(ATT_PREPARE_WRITE_REQUEST, 0, 0);
4914902524cSMatthias Ringwald 		CHECK_EQUAL(5, att_request_len);
4924902524cSMatthias Ringwald 		att_response_len = att_handle_request(&att_connection, (uint8_t *) att_request, att_request_len, att_response);
4934902524cSMatthias Ringwald 		const uint8_t expected_response[] = {ATT_ERROR_RESPONSE, att_request[0], att_request[1], att_request[2], ATT_ERROR_INVALID_HANDLE};
4944902524cSMatthias Ringwald 		MEMCMP_EQUAL(expected_response, att_response, att_response_len);
4954902524cSMatthias Ringwald 		CHECK_EQUAL(sizeof(expected_response), att_response_len);
4964902524cSMatthias Ringwald 	}
4974902524cSMatthias Ringwald 
4984902524cSMatthias Ringwald 	// write not permited: no ATT_PROPERTY_WRITE
4994902524cSMatthias Ringwald 	{
5004902524cSMatthias Ringwald 		attribute_handle = 0x000c; // 0x2A49
5014902524cSMatthias Ringwald 		att_request_len = att_prepare_write_request(ATT_PREPARE_WRITE_REQUEST, attribute_handle, value_offset);
5024902524cSMatthias Ringwald 		CHECK_EQUAL(5, att_request_len);
5034902524cSMatthias Ringwald 		att_response_len = att_handle_request(&att_connection, (uint8_t *) att_request, att_request_len, att_response);
5044902524cSMatthias Ringwald 
5054902524cSMatthias Ringwald 		const uint8_t expected_response[] = {ATT_ERROR_RESPONSE, att_request[0], att_request[1], att_request[2], ATT_ERROR_WRITE_NOT_PERMITTED};
5064902524cSMatthias Ringwald 		MEMCMP_EQUAL(expected_response, att_response, att_response_len);
5074902524cSMatthias Ringwald 		CHECK_EQUAL(sizeof(expected_response), att_response_len);
5084902524cSMatthias Ringwald 	}
5094902524cSMatthias Ringwald 
5104902524cSMatthias Ringwald 
5114902524cSMatthias Ringwald 	// write not permited: no ATT_PROPERTY_DYNAMIC
5124902524cSMatthias Ringwald 	{
5134902524cSMatthias Ringwald 		attribute_handle = 0x0003;
5144902524cSMatthias Ringwald 		att_request_len = att_prepare_write_request(ATT_PREPARE_WRITE_REQUEST, attribute_handle, value_offset);
5154902524cSMatthias Ringwald 		CHECK_EQUAL(5, att_request_len);
5164902524cSMatthias Ringwald 		att_response_len = att_handle_request(&att_connection, (uint8_t *) att_request, att_request_len, att_response);
5174902524cSMatthias Ringwald 		const uint8_t expected_response[] = {ATT_ERROR_RESPONSE, att_request[0], att_request[1], att_request[2], ATT_ERROR_WRITE_NOT_PERMITTED};
5184902524cSMatthias Ringwald 		MEMCMP_EQUAL(expected_response, att_response, att_response_len);
5194902524cSMatthias Ringwald 		CHECK_EQUAL(sizeof(expected_response), att_response_len);
5204902524cSMatthias Ringwald 	}
5214902524cSMatthias Ringwald 
5224902524cSMatthias Ringwald 	// security validation
5234902524cSMatthias Ringwald 	{
5244902524cSMatthias Ringwald 		attribute_handle = 0x000f; // 0x2A35
5254902524cSMatthias Ringwald 		att_request_len = att_prepare_write_request(ATT_PREPARE_WRITE_REQUEST, attribute_handle, value_offset);
5264902524cSMatthias Ringwald 		CHECK_EQUAL(5, att_request_len);
5274902524cSMatthias Ringwald 		att_response_len = att_handle_request(&att_connection, (uint8_t *) att_request, att_request_len, att_response);
5284902524cSMatthias Ringwald 		const uint8_t expected_response[] = {ATT_ERROR_RESPONSE, att_request[0], att_request[1], att_request[2], ATT_ERROR_INSUFFICIENT_AUTHENTICATION};
5294902524cSMatthias Ringwald 		MEMCMP_EQUAL(expected_response, att_response, att_response_len);
5304902524cSMatthias Ringwald 		CHECK_EQUAL(sizeof(expected_response), att_response_len);
5314902524cSMatthias Ringwald 	}
5324902524cSMatthias Ringwald 
5334902524cSMatthias Ringwald 	// some callback error other then ATT_INTERNAL_WRITE_RESPONSE_PENDING
5344902524cSMatthias Ringwald 	{
5354902524cSMatthias Ringwald 		write_callback_mode = WRITE_CALLBACK_MODE_RETURN_INVALID_ATTRIBUTE_VALUE_LENGTH;
5364902524cSMatthias Ringwald 
5374902524cSMatthias Ringwald 		attribute_handle = 0x0011; // 0x2A38
5384902524cSMatthias Ringwald 
5394902524cSMatthias Ringwald 		// prepare write
5404902524cSMatthias Ringwald 		att_request_len = att_prepare_write_request(ATT_PREPARE_WRITE_REQUEST, attribute_handle, value_offset);
5414902524cSMatthias Ringwald 		CHECK_EQUAL(5, att_request_len);
5424902524cSMatthias Ringwald 
5434902524cSMatthias Ringwald 		att_response_len = att_handle_request(&att_connection, (uint8_t *) att_request, att_request_len, att_response);
5444902524cSMatthias Ringwald 		const uint8_t expected_response_prepare_write[] = {ATT_PREPARE_WRITE_RESPONSE, 0x11, 0x00, 0x10, 0x00};
5454902524cSMatthias Ringwald 		MEMCMP_EQUAL(expected_response_prepare_write, att_response, att_response_len);
5464902524cSMatthias Ringwald 		CHECK_EQUAL(sizeof(expected_response_prepare_write), att_response_len);
5474902524cSMatthias Ringwald 
5484902524cSMatthias Ringwald 		// execute write
5494902524cSMatthias Ringwald 		att_request_len = att_prepare_write_request(ATT_EXECUTE_WRITE_REQUEST, attribute_handle, value_offset);
5504902524cSMatthias Ringwald 		CHECK_EQUAL(5, att_request_len);
5514902524cSMatthias Ringwald 
5524902524cSMatthias Ringwald 		att_response_len = att_handle_request(&att_connection, (uint8_t *) att_request, att_request_len, att_response);
5534902524cSMatthias Ringwald 		const uint8_t expected_response_write_execute[] = {ATT_ERROR_RESPONSE, att_request[0], att_request[1], att_request[2], ATT_ERROR_INVALID_ATTRIBUTE_VALUE_LENGTH};
5544902524cSMatthias Ringwald 		MEMCMP_EQUAL(expected_response_write_execute, att_response, att_response_len);
5554902524cSMatthias Ringwald 		CHECK_EQUAL(sizeof(expected_response_write_execute), att_response_len);
5564902524cSMatthias Ringwald 
5574902524cSMatthias Ringwald 		write_callback_mode = WRITE_CALLBACK_MODE_RETURN_DEFAULT;
5584902524cSMatthias Ringwald 	}
5594902524cSMatthias Ringwald 
5604902524cSMatthias Ringwald #ifdef ENABLE_ATT_DELAYED_RESPONSE
5614902524cSMatthias Ringwald 	// delayed response
5624902524cSMatthias Ringwald 	{
5634902524cSMatthias Ringwald 		write_callback_mode = WRITE_CALLBACK_MODE_RETURN_ERROR_WRITE_RESPONSE_PENDING;
5644902524cSMatthias Ringwald 
5654902524cSMatthias Ringwald 		attribute_handle = 0x0011; // 0x2A38
5664902524cSMatthias Ringwald 		att_request_len = att_prepare_write_request(ATT_PREPARE_WRITE_REQUEST, attribute_handle, value_offset);
5674902524cSMatthias Ringwald 		CHECK_EQUAL(5, att_request_len);
5684902524cSMatthias Ringwald 		att_response_len = att_handle_request(&att_connection, (uint8_t *) att_request, att_request_len, att_response);
5694902524cSMatthias Ringwald 
5704902524cSMatthias Ringwald 
5714902524cSMatthias Ringwald 		CHECK_EQUAL(ATT_INTERNAL_WRITE_RESPONSE_PENDING, att_response_len);
5724902524cSMatthias Ringwald 
5734902524cSMatthias Ringwald 		write_callback_mode = WRITE_CALLBACK_MODE_RETURN_DEFAULT;
5744902524cSMatthias Ringwald 	}
5754902524cSMatthias Ringwald #endif
5764902524cSMatthias Ringwald 
5774902524cSMatthias Ringwald 	// correct write
5784902524cSMatthias Ringwald 	{
5794902524cSMatthias Ringwald 		attribute_handle = 0x0011;
5804902524cSMatthias Ringwald 		att_request_len = att_prepare_write_request(ATT_PREPARE_WRITE_REQUEST, attribute_handle, value_offset);
5814902524cSMatthias Ringwald 		CHECK_EQUAL(5, att_request_len);
5824902524cSMatthias Ringwald 		att_response_len = att_handle_request(&att_connection, (uint8_t *) att_request, att_request_len, att_response);
5834902524cSMatthias Ringwald 		const uint8_t expected_response[] = {ATT_PREPARE_WRITE_RESPONSE, 0x11, 0x00, 0x10, 0x00};
5844902524cSMatthias Ringwald 		MEMCMP_EQUAL(expected_response, att_response, att_response_len);
5854902524cSMatthias Ringwald 		CHECK_EQUAL(sizeof(expected_response), att_response_len);
5864902524cSMatthias Ringwald 	}
5874902524cSMatthias Ringwald }
5884902524cSMatthias Ringwald 
TEST(AttDb,att_uuid_for_handle)5894902524cSMatthias Ringwald TEST(AttDb, att_uuid_for_handle){
5904902524cSMatthias Ringwald 	// existing attribute handle
5914902524cSMatthias Ringwald 	uint16_t uuid = att_uuid_for_handle(0x0011);
5924902524cSMatthias Ringwald 	uint16_t expected_response = 0x2A38;
5934902524cSMatthias Ringwald 	CHECK_EQUAL(expected_response, uuid);
5944902524cSMatthias Ringwald 
5954902524cSMatthias Ringwald 	// unknown attribute handle
5964902524cSMatthias Ringwald 	uuid = att_uuid_for_handle(0xFF00);
5974902524cSMatthias Ringwald 	expected_response = 0;
5984902524cSMatthias Ringwald 	CHECK_EQUAL(expected_response, uuid);
5994902524cSMatthias Ringwald 
6004902524cSMatthias Ringwald 	// attribute handle for uuid128
6014902524cSMatthias Ringwald 	uuid = att_uuid_for_handle(0x0014);
6024902524cSMatthias Ringwald 	expected_response = 0;
6034902524cSMatthias Ringwald 	CHECK_EQUAL(expected_response, uuid);
6044902524cSMatthias Ringwald }
6054902524cSMatthias Ringwald 
TEST(AttDb,gatt_server_get_handle_range)606*6fc08a49SMilanka Ringwald TEST(AttDb, gatt_server_get_handle_range){
607*6fc08a49SMilanka Ringwald 	uint16_t start_handle;
608*6fc08a49SMilanka Ringwald 	uint16_t end_handle;
609*6fc08a49SMilanka Ringwald 
610*6fc08a49SMilanka Ringwald 	bool service_exists = gatt_server_get_handle_range_for_service_with_uuid16(0x00, &start_handle, &end_handle);
611*6fc08a49SMilanka Ringwald 	CHECK_EQUAL(false, service_exists);
612*6fc08a49SMilanka Ringwald 
613*6fc08a49SMilanka Ringwald 	uint16_t attribute_handle = gatt_server_get_value_handle_for_characteristic_with_uuid16(0, 0xffff, 0x00);
614*6fc08a49SMilanka Ringwald 	CHECK_EQUAL(0x00, attribute_handle);
615*6fc08a49SMilanka Ringwald 
616*6fc08a49SMilanka Ringwald 	attribute_handle = gatt_server_get_value_handle_for_characteristic_with_uuid16(0, 0xffff, ORG_BLUETOOTH_CHARACTERISTIC_BATTERY_LEVEL);
617*6fc08a49SMilanka Ringwald 	uint16_t configuration_handle = gatt_server_get_server_configuration_handle_for_characteristic_with_uuid16(0, 0xffff, attribute_handle);
618*6fc08a49SMilanka Ringwald 	CHECK_EQUAL(0x00, configuration_handle);
619*6fc08a49SMilanka Ringwald }
620*6fc08a49SMilanka Ringwald 
TEST(AttDb,gatt_server_get_handle_range_for_service)621*6fc08a49SMilanka Ringwald TEST(AttDb, gatt_server_get_handle_range_for_service){
622*6fc08a49SMilanka Ringwald 	uint16_t start_handle;
623*6fc08a49SMilanka Ringwald 	uint16_t end_handle;
624*6fc08a49SMilanka Ringwald 
625*6fc08a49SMilanka Ringwald 	const uint8_t uuid128_1[] = {0x00, 0x00, 0xFF, 0x11, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0x80, 0x5F, 0x9B, 0x34, 0xFB};
626*6fc08a49SMilanka Ringwald 	const uint8_t uuid128_2[] = {0xAA, 0xBB, 0xFF, 0x11, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0x80, 0x5F, 0x9B, 0x34, 0xFB};
627*6fc08a49SMilanka Ringwald 	const uint8_t uuid128_3[] = {0xAA, 0xDD, 0xFF, 0x11, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0x80, 0x5F, 0x9B, 0x34, 0xFB};
628*6fc08a49SMilanka Ringwald 
629*6fc08a49SMilanka Ringwald 
630*6fc08a49SMilanka Ringwald 	bool service_exists = gatt_server_get_handle_range_for_service_with_uuid128(uuid128_1, &start_handle, &end_handle);
631*6fc08a49SMilanka Ringwald 	CHECK_EQUAL(false, service_exists);
632*6fc08a49SMilanka Ringwald 
633*6fc08a49SMilanka Ringwald 	service_exists = gatt_server_get_handle_range_for_service_with_uuid128(uuid128_2, &start_handle, &end_handle);
634*6fc08a49SMilanka Ringwald 	CHECK_EQUAL(true, service_exists);
635*6fc08a49SMilanka Ringwald 
636*6fc08a49SMilanka Ringwald 	uint16_t out_included_service_handle;
637*6fc08a49SMilanka Ringwald 	uint16_t out_included_service_start_handle;
638*6fc08a49SMilanka Ringwald 	uint16_t out_included_service_end_handle;
639*6fc08a49SMilanka Ringwald 
640*6fc08a49SMilanka Ringwald 	service_exists = gatt_server_get_included_service_with_uuid16(0, 0xffff, 0xAA,
641*6fc08a49SMilanka Ringwald 		&out_included_service_handle, &out_included_service_start_handle, &out_included_service_end_handle);
642*6fc08a49SMilanka Ringwald 	CHECK_EQUAL(false, service_exists);
643*6fc08a49SMilanka Ringwald 
644*6fc08a49SMilanka Ringwald 	service_exists = gatt_server_get_included_service_with_uuid16(0, 0, 0xAA,
645*6fc08a49SMilanka Ringwald 		&out_included_service_handle, &out_included_service_start_handle, &out_included_service_end_handle);
646*6fc08a49SMilanka Ringwald 	CHECK_EQUAL(false, service_exists);
647*6fc08a49SMilanka Ringwald 
648*6fc08a49SMilanka Ringwald 	service_exists = gatt_server_get_included_service_with_uuid16(0, 0xffff, 0xAACC,
649*6fc08a49SMilanka Ringwald 		&out_included_service_handle, &out_included_service_start_handle, &out_included_service_end_handle);
650*6fc08a49SMilanka Ringwald 	CHECK_EQUAL(true, service_exists);
651*6fc08a49SMilanka Ringwald }
652*6fc08a49SMilanka Ringwald 
653*6fc08a49SMilanka Ringwald 
TEST(AttDb,gatt_server_get_value_handle_for_characteristic_with_uuid128)654*6fc08a49SMilanka Ringwald TEST(AttDb, gatt_server_get_value_handle_for_characteristic_with_uuid128){
655*6fc08a49SMilanka Ringwald 	const uint8_t uuid128_1[] = {0x00, 0x00, 0xFF, 0x11, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0x80, 0x5F, 0x9B, 0x34, 0xFB};
656*6fc08a49SMilanka Ringwald 	const uint8_t uuid128_2[] = {0xAA, 0xBB, 0xFF, 0x11, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0x80, 0x5F, 0x9B, 0x34, 0xFB};
657*6fc08a49SMilanka Ringwald 
658*6fc08a49SMilanka Ringwald 	uint16_t value_handle = gatt_server_get_value_handle_for_characteristic_with_uuid128(0, 0xffff, uuid128_1);
659*6fc08a49SMilanka Ringwald 	CHECK_EQUAL(20, value_handle);
660*6fc08a49SMilanka Ringwald 	CHECK_EQUAL(false, att_is_persistent_ccc(value_handle));
661*6fc08a49SMilanka Ringwald 	CHECK_EQUAL(false, att_is_persistent_ccc(0x60));
662*6fc08a49SMilanka Ringwald 
663*6fc08a49SMilanka Ringwald 	value_handle = gatt_server_get_value_handle_for_characteristic_with_uuid128(0, 0xffff, uuid128_2);
664*6fc08a49SMilanka Ringwald 	CHECK_EQUAL(0, value_handle);
665*6fc08a49SMilanka Ringwald 
666*6fc08a49SMilanka Ringwald 	value_handle = gatt_server_get_value_handle_for_characteristic_with_uuid128(0, 0, uuid128_2);
667*6fc08a49SMilanka Ringwald 	CHECK_EQUAL(0, value_handle);
668*6fc08a49SMilanka Ringwald 
669*6fc08a49SMilanka Ringwald 	value_handle = gatt_server_get_value_handle_for_characteristic_with_uuid128(0xffff, 0, uuid128_2);
670*6fc08a49SMilanka Ringwald 	CHECK_EQUAL(0, value_handle);
671*6fc08a49SMilanka Ringwald }
672*6fc08a49SMilanka Ringwald 
673*6fc08a49SMilanka Ringwald 
TEST(AttDb,gatt_server_get_client_configuration_handle_for_characteristic)674*6fc08a49SMilanka Ringwald TEST(AttDb, gatt_server_get_client_configuration_handle_for_characteristic){
675*6fc08a49SMilanka Ringwald 	const uint8_t uuid128_1[] = {0x00, 0x00, 0xFF, 0x11, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0x80, 0x5F, 0x9B, 0x34, 0xFB};
676*6fc08a49SMilanka Ringwald 	const uint8_t uuid128_2[] = {0xAA, 0xBB, 0xFF, 0x11, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0x80, 0x5F, 0x9B, 0x34, 0xFB};
677*6fc08a49SMilanka Ringwald 	const uint8_t uuid128_3[] = {0xAA, 0xCC, 0xFF, 0x11, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0x80, 0x5F, 0x9B, 0x34, 0xFB};
678*6fc08a49SMilanka Ringwald 
679*6fc08a49SMilanka Ringwald 	uint16_t value_handle = gatt_server_get_client_configuration_handle_for_characteristic_with_uuid128(0, 0xffff, uuid128_1);
680*6fc08a49SMilanka Ringwald 	CHECK_EQUAL(21, value_handle);
681*6fc08a49SMilanka Ringwald 
682*6fc08a49SMilanka Ringwald 	value_handle = gatt_server_get_client_configuration_handle_for_characteristic_with_uuid128(0, 0xffff, uuid128_2);
683*6fc08a49SMilanka Ringwald 	CHECK_EQUAL(0, value_handle);
684*6fc08a49SMilanka Ringwald 
685*6fc08a49SMilanka Ringwald 	value_handle = gatt_server_get_client_configuration_handle_for_characteristic_with_uuid128(0, 0, uuid128_2);
686*6fc08a49SMilanka Ringwald 	CHECK_EQUAL(0, value_handle);
687*6fc08a49SMilanka Ringwald 
688*6fc08a49SMilanka Ringwald 	value_handle = gatt_server_get_client_configuration_handle_for_characteristic_with_uuid128(0xffff, 0, uuid128_2);
689*6fc08a49SMilanka Ringwald 	CHECK_EQUAL(0, value_handle);
690*6fc08a49SMilanka Ringwald 
691*6fc08a49SMilanka Ringwald 	value_handle = gatt_server_get_client_configuration_handle_for_characteristic_with_uuid128(0xffff, 0, uuid128_3);
692*6fc08a49SMilanka Ringwald 	CHECK_EQUAL(0, value_handle);
693*6fc08a49SMilanka Ringwald 
694*6fc08a49SMilanka Ringwald 
695*6fc08a49SMilanka Ringwald 	value_handle = gatt_server_get_descriptor_handle_for_characteristic_with_uuid16(0, 0xffff, ORG_BLUETOOTH_CHARACTERISTIC_BLOOD_PRESSURE_MEASUREMENT, GATT_SERVER_CHARACTERISTICS_CONFIGURATION);
696*6fc08a49SMilanka Ringwald 	CHECK_EQUAL(0, value_handle);
697*6fc08a49SMilanka Ringwald 
698*6fc08a49SMilanka Ringwald 	value_handle = gatt_server_get_descriptor_handle_for_characteristic_with_uuid16(0, 0xffff, ORG_BLUETOOTH_CHARACTERISTIC_BATTERY_LEVEL, GATT_SERVER_CHARACTERISTICS_CONFIGURATION);
699*6fc08a49SMilanka Ringwald 	CHECK_EQUAL(0, value_handle);
700*6fc08a49SMilanka Ringwald 
701*6fc08a49SMilanka Ringwald 	value_handle = gatt_server_get_descriptor_handle_for_characteristic_with_uuid16(0, 0, ORG_BLUETOOTH_CHARACTERISTIC_BATTERY_LEVEL, GATT_SERVER_CHARACTERISTICS_CONFIGURATION);
702*6fc08a49SMilanka Ringwald 	CHECK_EQUAL(0, value_handle);
703*6fc08a49SMilanka Ringwald }
704*6fc08a49SMilanka Ringwald 
705*6fc08a49SMilanka Ringwald 
TEST(AttDb,handle_signed_write_command)706*6fc08a49SMilanka Ringwald TEST(AttDb, handle_signed_write_command){
707*6fc08a49SMilanka Ringwald 	uint16_t attribute_handle = gatt_server_get_value_handle_for_characteristic_with_uuid16(0, 0xffff, ORG_BLUETOOTH_CHARACTERISTIC_CSC_FEATURE);
708*6fc08a49SMilanka Ringwald 
709*6fc08a49SMilanka Ringwald 	att_request[0] = ATT_SIGNED_WRITE_COMMAND;
710*6fc08a49SMilanka Ringwald 	att_request_len = 1;
711*6fc08a49SMilanka Ringwald 	att_response_len = att_handle_request(&att_connection, (uint8_t *) att_request, att_request_len, att_response);
712*6fc08a49SMilanka Ringwald 	CHECK_EQUAL(0, att_response_len);
713*6fc08a49SMilanka Ringwald }
714*6fc08a49SMilanka Ringwald 
TEST(AttDb,handle_write_command)7154902524cSMatthias Ringwald TEST(AttDb, handle_write_command){
7164902524cSMatthias Ringwald 	uint16_t attribute_handle = 0x03;
7174902524cSMatthias Ringwald 	att_dump_attributes();
7184902524cSMatthias Ringwald 
7194902524cSMatthias Ringwald 	// not sufficient request length
7204902524cSMatthias Ringwald 	{
7214902524cSMatthias Ringwald 		att_request[0] = ATT_WRITE_COMMAND;
7224902524cSMatthias Ringwald 		att_request_len = 1;
7234902524cSMatthias Ringwald 		att_response_len = att_handle_request(&att_connection, (uint8_t *) att_request, att_request_len, att_response);
7244902524cSMatthias Ringwald 		CHECK_EQUAL(0, att_response_len);
7254902524cSMatthias Ringwald 	}
7264902524cSMatthias Ringwald 
7274902524cSMatthias Ringwald 	{
7284902524cSMatthias Ringwald 		att_request[0] = ATT_WRITE_COMMAND;
7294902524cSMatthias Ringwald 		att_request[1] = 0x03;
7304902524cSMatthias Ringwald 		att_request_len = 2;
7314902524cSMatthias Ringwald 		att_response_len = att_handle_request(&att_connection, (uint8_t *) att_request, att_request_len, att_response);
7324902524cSMatthias Ringwald 		CHECK_EQUAL(0, att_response_len);
7334902524cSMatthias Ringwald 	}
7344902524cSMatthias Ringwald 
7354902524cSMatthias Ringwald 	// invalid write callback
7364902524cSMatthias Ringwald 	{
7374902524cSMatthias Ringwald 		att_set_write_callback(NULL);
7384902524cSMatthias Ringwald 
7394902524cSMatthias Ringwald 		const uint8_t value[] = {0x50};
7404902524cSMatthias Ringwald 		att_request_len = att_write_request(ATT_WRITE_COMMAND, attribute_handle, sizeof(value), value);
7414902524cSMatthias Ringwald 		CHECK_EQUAL(3 + sizeof(value), att_request_len);
7424902524cSMatthias Ringwald 
7434902524cSMatthias Ringwald 		att_response_len = att_handle_request(&att_connection, (uint8_t *) att_request, att_request_len, att_response);
7444902524cSMatthias Ringwald 		CHECK_EQUAL(0, att_response_len);
7454902524cSMatthias Ringwald 
7464902524cSMatthias Ringwald 		att_set_write_callback(&att_write_callback);
7474902524cSMatthias Ringwald 	}
7484902524cSMatthias Ringwald 
7494902524cSMatthias Ringwald 	// invalid handle
7504902524cSMatthias Ringwald 	{
7514902524cSMatthias Ringwald 		att_request[0] = ATT_WRITE_COMMAND;
7524902524cSMatthias Ringwald 		att_request[1] = 0;
7534902524cSMatthias Ringwald 		att_request[2] = 0;
7544902524cSMatthias Ringwald 		att_request_len = 3;
7554902524cSMatthias Ringwald 		att_response_len = att_handle_request(&att_connection, (uint8_t *) att_request, att_request_len, att_response);
7564902524cSMatthias Ringwald 		CHECK_EQUAL(0, att_response_len);
7574902524cSMatthias Ringwald 	}
7584902524cSMatthias Ringwald 
7594902524cSMatthias Ringwald 	// write not permited: no ATT_PROPERTY_DYNAMIC
7604902524cSMatthias Ringwald 	{
7614902524cSMatthias Ringwald 		const uint8_t value[] = {0x50};
7624902524cSMatthias Ringwald 		attribute_handle = 0x0003;
7634902524cSMatthias Ringwald 		att_request_len = att_write_request(ATT_WRITE_COMMAND, attribute_handle, sizeof(value), value);
7644902524cSMatthias Ringwald 		CHECK_EQUAL(3 + sizeof(value), att_request_len);
7654902524cSMatthias Ringwald 		att_response_len = att_handle_request(&att_connection, (uint8_t *) att_request, att_request_len, att_response);
7664902524cSMatthias Ringwald 		CHECK_EQUAL(0, att_response_len);
7674902524cSMatthias Ringwald 	}
7684902524cSMatthias Ringwald 
7694902524cSMatthias Ringwald 	// write not permited: no ATT_PROPERTY_WRITE_WITHOUT_RESPONSE
7704902524cSMatthias Ringwald 	{
7714902524cSMatthias Ringwald 		const uint8_t value[] = {0x50};
7724902524cSMatthias Ringwald 		attribute_handle = 0x000c; // 0x2A49
7734902524cSMatthias Ringwald 		att_request_len = att_write_request(ATT_WRITE_COMMAND, attribute_handle, sizeof(value), value);
7744902524cSMatthias Ringwald 		CHECK_EQUAL(3 + sizeof(value), att_request_len);
7754902524cSMatthias Ringwald 		att_response_len = att_handle_request(&att_connection, (uint8_t *) att_request, att_request_len, att_response);
7764902524cSMatthias Ringwald 		CHECK_EQUAL(0, att_response_len);
7774902524cSMatthias Ringwald 	}
7784902524cSMatthias Ringwald 
7794902524cSMatthias Ringwald 	// security validation
7804902524cSMatthias Ringwald 	{
7814902524cSMatthias Ringwald 		const uint8_t value[] = {0x50};
7824902524cSMatthias Ringwald 		attribute_handle = 0x0017; // 0x2AA7
7834902524cSMatthias Ringwald 		att_request_len = att_write_request(ATT_WRITE_COMMAND, attribute_handle, sizeof(value), value);
7844902524cSMatthias Ringwald 		CHECK_EQUAL(3 + sizeof(value), att_request_len);
7854902524cSMatthias Ringwald 		att_response_len = att_handle_request(&att_connection, (uint8_t *) att_request, att_request_len, att_response);
7864902524cSMatthias Ringwald 		CHECK_EQUAL(0, att_response_len);
7874902524cSMatthias Ringwald 	}
7884902524cSMatthias Ringwald 
7894902524cSMatthias Ringwald 	// correct write
7904902524cSMatthias Ringwald 	{
7914902524cSMatthias Ringwald 		const uint8_t value[] = {0x50};
7924902524cSMatthias Ringwald 		attribute_handle = 0x001A; // 0x2AAB
7934902524cSMatthias Ringwald 		att_request_len = att_write_request(ATT_WRITE_COMMAND, attribute_handle, sizeof(value), value);
7944902524cSMatthias Ringwald 		CHECK_EQUAL(3 + sizeof(value), att_request_len);
7954902524cSMatthias Ringwald 		att_response_len = att_handle_request(&att_connection, (uint8_t *) att_request, att_request_len, att_response);
7964902524cSMatthias Ringwald 		CHECK_EQUAL(0, att_response_len);
7974902524cSMatthias Ringwald 	}
7984902524cSMatthias Ringwald }
7994902524cSMatthias Ringwald 
TEST(AttDb,att_read_callback_handle_blob)8004902524cSMatthias Ringwald TEST(AttDb, att_read_callback_handle_blob){
8014902524cSMatthias Ringwald 	{
8024902524cSMatthias Ringwald 		const uint8_t blob[] = {0x44, 0x55};
8034902524cSMatthias Ringwald 		uint16_t blob_size = att_read_callback_handle_blob(blob, sizeof(blob), 0, NULL, 0);
8044902524cSMatthias Ringwald 		CHECK_EQUAL(2, blob_size);
8054902524cSMatthias Ringwald 	}
8064902524cSMatthias Ringwald 
8074902524cSMatthias Ringwald 	{
8084902524cSMatthias Ringwald 		const uint8_t blob[] = {};
8094902524cSMatthias Ringwald 		uint16_t blob_size = att_read_callback_handle_blob(blob, sizeof(blob), 0, callback_buffer, sizeof(callback_buffer));
8104902524cSMatthias Ringwald 		CHECK_EQUAL(0, blob_size);
8114902524cSMatthias Ringwald 	}
8124902524cSMatthias Ringwald 
8134902524cSMatthias Ringwald 	{
8144902524cSMatthias Ringwald 		const uint8_t blob[] = {};
8154902524cSMatthias Ringwald 		uint16_t blob_size = att_read_callback_handle_blob(blob, sizeof(blob), 10, callback_buffer, sizeof(callback_buffer));
8164902524cSMatthias Ringwald 		CHECK_EQUAL(0, blob_size);
8174902524cSMatthias Ringwald 	}
8184902524cSMatthias Ringwald 
8194902524cSMatthias Ringwald 	{
8204902524cSMatthias Ringwald 		const uint8_t blob[] = {0x55};
8214902524cSMatthias Ringwald 		uint16_t blob_size = att_read_callback_handle_blob(blob, sizeof(blob), 0, callback_buffer, sizeof(callback_buffer));
8224902524cSMatthias Ringwald 		CHECK_EQUAL(1, blob_size);
8234902524cSMatthias Ringwald 	}
8244902524cSMatthias Ringwald 
8254902524cSMatthias Ringwald 	{
8264902524cSMatthias Ringwald 		const uint8_t blob[] = {0x55};
8274902524cSMatthias Ringwald 		uint16_t blob_size = att_read_callback_handle_blob(blob, sizeof(blob), 10, callback_buffer, sizeof(callback_buffer));
8284902524cSMatthias Ringwald 		CHECK_EQUAL(0, blob_size);
8294902524cSMatthias Ringwald 	}
8304902524cSMatthias Ringwald 
8314902524cSMatthias Ringwald 	{
8324902524cSMatthias Ringwald 		const uint8_t blob[] = {0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA};
8334902524cSMatthias Ringwald 		uint16_t blob_size = att_read_callback_handle_blob(blob, sizeof(blob), 0, callback_buffer, sizeof(callback_buffer));
8344902524cSMatthias Ringwald 		CHECK_EQUAL(10, blob_size);
8354902524cSMatthias Ringwald 	}
8364902524cSMatthias Ringwald 
8374902524cSMatthias Ringwald 	{
8384902524cSMatthias Ringwald 		const uint8_t blob[] = {0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA};
8394902524cSMatthias Ringwald 		uint16_t blob_size = att_read_callback_handle_blob(blob, sizeof(blob), 1, callback_buffer, sizeof(callback_buffer));
8404902524cSMatthias Ringwald 		CHECK_EQUAL(9, blob_size);
8414902524cSMatthias Ringwald 	}
8424902524cSMatthias Ringwald 
8434902524cSMatthias Ringwald 	{
8444902524cSMatthias Ringwald 		const uint8_t blob[] = {0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA};
8454902524cSMatthias Ringwald 		uint16_t blob_size = att_read_callback_handle_blob(blob, sizeof(blob), 10, callback_buffer, sizeof(callback_buffer));
8464902524cSMatthias Ringwald 		CHECK_EQUAL(0, blob_size);
8474902524cSMatthias Ringwald 	}
8484902524cSMatthias Ringwald }
8494902524cSMatthias Ringwald 
TEST(AttDb,att_read_callback_handle_byte)8504902524cSMatthias Ringwald TEST(AttDb, att_read_callback_handle_byte){
8514902524cSMatthias Ringwald 	{
8524902524cSMatthias Ringwald 		uint16_t blob_size = att_read_callback_handle_byte(0x55, 0, NULL, 0);
8534902524cSMatthias Ringwald 		CHECK_EQUAL(1, blob_size);
8544902524cSMatthias Ringwald 	}
8554902524cSMatthias Ringwald 
8564902524cSMatthias Ringwald 	{
8574902524cSMatthias Ringwald 		uint16_t blob_size = att_read_callback_handle_byte(0x55, 10, callback_buffer, sizeof(callback_buffer));
8584902524cSMatthias Ringwald 		CHECK_EQUAL(0, blob_size);
8594902524cSMatthias Ringwald 	}
8604902524cSMatthias Ringwald 
8614902524cSMatthias Ringwald 	{
8624902524cSMatthias Ringwald 		uint16_t blob_size = att_read_callback_handle_byte(0x55, 0, callback_buffer, sizeof(callback_buffer));
8634902524cSMatthias Ringwald 		CHECK_EQUAL(1, blob_size);
8644902524cSMatthias Ringwald 	}
8654902524cSMatthias Ringwald }
8664902524cSMatthias Ringwald 
TEST(AttDb,att_read_callback_handle_little_endian_16)8674902524cSMatthias Ringwald TEST(AttDb, att_read_callback_handle_little_endian_16){
8684902524cSMatthias Ringwald 	{
8694902524cSMatthias Ringwald 		uint16_t blob_size = att_read_callback_handle_little_endian_16(0x1122, 0, NULL, 0);
8704902524cSMatthias Ringwald 		CHECK_EQUAL(2, blob_size);
8714902524cSMatthias Ringwald 	}
8724902524cSMatthias Ringwald 
8734902524cSMatthias Ringwald 	{
8744902524cSMatthias Ringwald 		uint16_t blob_size = att_read_callback_handle_little_endian_16(0x1122, 10, callback_buffer, sizeof(callback_buffer));
8754902524cSMatthias Ringwald 		CHECK_EQUAL(0, blob_size);
8764902524cSMatthias Ringwald 	}
8774902524cSMatthias Ringwald 
8784902524cSMatthias Ringwald 	{
8794902524cSMatthias Ringwald 		uint16_t blob_size = att_read_callback_handle_little_endian_16(0x1122, 1, callback_buffer, sizeof(callback_buffer));
8804902524cSMatthias Ringwald 		CHECK_EQUAL(1, blob_size);
8814902524cSMatthias Ringwald 	}
8824902524cSMatthias Ringwald 
8834902524cSMatthias Ringwald 	{
8844902524cSMatthias Ringwald 		uint16_t blob_size = att_read_callback_handle_little_endian_16(0x1122, 0, callback_buffer, sizeof(callback_buffer));
8854902524cSMatthias Ringwald 		CHECK_EQUAL(2, blob_size);
8864902524cSMatthias Ringwald 	}
8874902524cSMatthias Ringwald }
8884902524cSMatthias Ringwald 
TEST(AttDb,att_read_callback_handle_little_endian_32)8894902524cSMatthias Ringwald TEST(AttDb, att_read_callback_handle_little_endian_32){
8904902524cSMatthias Ringwald 	{
8914902524cSMatthias Ringwald 		uint16_t blob_size = att_read_callback_handle_little_endian_32(0x11223344, 0, NULL, 0);
8924902524cSMatthias Ringwald 		CHECK_EQUAL(4, blob_size);
8934902524cSMatthias Ringwald 	}
8944902524cSMatthias Ringwald 
8954902524cSMatthias Ringwald 	{
8964902524cSMatthias Ringwald 		uint16_t blob_size = att_read_callback_handle_little_endian_32(0x11223344, 10, callback_buffer, sizeof(callback_buffer));
8974902524cSMatthias Ringwald 		CHECK_EQUAL(0, blob_size);
8984902524cSMatthias Ringwald 	}
8994902524cSMatthias Ringwald 
9004902524cSMatthias Ringwald 	{
9014902524cSMatthias Ringwald 		uint16_t blob_size = att_read_callback_handle_little_endian_32(0x11223344, 3, callback_buffer, sizeof(callback_buffer));
9024902524cSMatthias Ringwald 		CHECK_EQUAL(1, blob_size);
9034902524cSMatthias Ringwald 	}
9044902524cSMatthias Ringwald 
9054902524cSMatthias Ringwald 	{
9064902524cSMatthias Ringwald 		uint16_t blob_size = att_read_callback_handle_little_endian_32(0x11223344, 0, callback_buffer, sizeof(callback_buffer));
9074902524cSMatthias Ringwald 		CHECK_EQUAL(4, blob_size);
9084902524cSMatthias Ringwald 	}
9094902524cSMatthias Ringwald }
9104902524cSMatthias Ringwald 
9114902524cSMatthias Ringwald 
main(int argc,const char * argv[])9124902524cSMatthias Ringwald int main (int argc, const char * argv[]){
9134902524cSMatthias Ringwald     return CommandLineTestRunner::RunAllTests(argc, argv);
9144902524cSMatthias Ringwald }
915