xref: /btstack/test/att_db/att_db_test.cpp (revision 98f1394d9d4c33f501ec5dcff54d145a92013c5e)
1 /*
2  * Copyright (C) 2014 BlueKitchen GmbH
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  *
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  * 3. Neither the name of the copyright holders nor the names of
14  *    contributors may be used to endorse or promote products derived
15  *    from this software without specific prior written permission.
16  * 4. Any redistribution, use, or modification is done solely for
17  *    personal benefit and not for any commercial purpose or for
18  *    monetary gain.
19  *
20  * THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS
21  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MATTHIAS
24  * RINGWALD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
26  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
27  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
28  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
29  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
30  * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31  * SUCH DAMAGE.
32  *
33  * Please inquire about commercial licensing options at
34  * [email protected]
35  *
36  */
37 
38 
39 #include <stdint.h>
40 #include <stdio.h>
41 #include <stdlib.h>
42 #include <string.h>
43 
44 #include "CppUTest/TestHarness.h"
45 #include "CppUTest/CommandLineTestRunner.h"
46 
47 #include "hci.h"
48 #include "ble/att_db.h"
49 #include "ble/att_db_util.h"
50 #include "btstack_util.h"
51 #include "bluetooth.h"
52 
53 #include "btstack_crypto.h"
54 #include "bluetooth_gatt.h"
55 
56 typedef enum {
57 	READ_CALLBACK_MODE_RETURN_DEFAULT = 0,
58 	READ_CALLBACK_MODE_RETURN_ONE_BYTE,
59 	READ_CALLBACK_MODE_RETURN_PENDING
60 } read_callback_mode_t;
61 
62 typedef enum {
63 	WRITE_CALLBACK_MODE_RETURN_DEFAULT = 0,
64 	WRITE_CALLBACK_MODE_RETURN_ERROR_WRITE_RESPONSE_PENDING,
65 	WRITE_CALLBACK_MODE_RETURN_INVALID_ATTRIBUTE_VALUE_LENGTH
66 } write_callback_mode_t;
67 
68 
69 static uint8_t battery_level = 100;
70 static uint8_t att_request[200];
71 static uint8_t att_response[1000];
72 
73 static read_callback_mode_t read_callback_mode   = READ_CALLBACK_MODE_RETURN_DEFAULT;
74 static write_callback_mode_t write_callback_mode = WRITE_CALLBACK_MODE_RETURN_DEFAULT;
75 
76 // these can be tweaked to report errors or some data as needed by test case
77 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){
78 	switch (read_callback_mode){
79 		case READ_CALLBACK_MODE_RETURN_ONE_BYTE:
80 			return att_read_callback_handle_byte(0x55, offset, buffer, buffer_size);
81 		case READ_CALLBACK_MODE_RETURN_PENDING:
82 			return ATT_READ_RESPONSE_PENDING;
83 		default:
84 			return 0;
85 	}
86 }
87 
88 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){
89 	switch (write_callback_mode){
90 		case WRITE_CALLBACK_MODE_RETURN_ERROR_WRITE_RESPONSE_PENDING:
91 			return ATT_ERROR_WRITE_RESPONSE_PENDING;
92 		case WRITE_CALLBACK_MODE_RETURN_INVALID_ATTRIBUTE_VALUE_LENGTH:
93 			return ATT_ERROR_INVALID_ATTRIBUTE_VALUE_LENGTH;
94 		default:
95 			return 0;
96 	}
97 }
98 
99 static uint16_t att_read_multiple_request(uint16_t num_value_handles, uint16_t * value_handles){
100     att_request[0] = ATT_READ_MULTIPLE_REQUEST;
101     int i;
102     int offset = 1;
103     for (i=0;i<num_value_handles;i++){
104         little_endian_store_16(att_request, offset, value_handles[i]);
105         offset += 2;
106     }
107 	return offset;
108 }
109 
110 static uint16_t att_write_request(uint16_t request_type, uint16_t attribute_handle, uint16_t value_length, const uint8_t * value){
111     att_request[0] = request_type;
112     little_endian_store_16(att_request, 1, attribute_handle);
113     (void)memcpy(&att_request[3], value, value_length);
114     return 3 + value_length;
115 }
116 
117 static uint16_t att_prepare_write_request(uint16_t request_type, uint16_t attribute_handle, uint16_t value_offset){
118     att_request[0] = request_type;
119     little_endian_store_16(att_request, 1, attribute_handle);
120     little_endian_store_16(att_request, 3, value_offset);
121     return 5;
122 }
123 
124 // ignore for now
125 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){
126 }
127 
128 TEST_GROUP(AttDb){
129 	att_connection_t att_connection;
130 	uint16_t att_request_len;
131 	uint16_t att_response_len;
132 	uint8_t  callback_buffer[10];
133 
134     void setup(void){
135     	memset(&callback_buffer, 0, sizeof(callback_buffer));
136 
137     	read_callback_mode = READ_CALLBACK_MODE_RETURN_ONE_BYTE;
138     	memset(&att_connection, 0, sizeof(att_connection));
139     	att_connection.max_mtu = 150;
140 		att_connection.mtu = ATT_DEFAULT_MTU;
141 
142 		write_callback_mode = WRITE_CALLBACK_MODE_RETURN_DEFAULT;
143 		read_callback_mode  = READ_CALLBACK_MODE_RETURN_DEFAULT;
144 
145     	// init att db util and add a service and characteristic
146 		att_db_util_init();
147 		// 0x180F
148 		att_db_util_add_service_uuid16(ORG_BLUETOOTH_SERVICE_BATTERY_SERVICE);
149 		// 0x2A19
150 		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);
151 		// 0x2A1B
152 		att_db_util_add_characteristic_uuid16(ORG_BLUETOOTH_CHARACTERISTIC_BATTERY_LEVEL_STATE, ATT_PROPERTY_NOTIFY, ATT_SECURITY_NONE, ATT_SECURITY_NONE, &battery_level, 1);
153 		// 0x2A1A
154 		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);
155 		// 0x2A49
156 		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);
157 		// 0x2A35
158 		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);
159 		// 0x2A38
160 		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);
161 
162 		const uint8_t uuid128[] = {0x00, 0x00, 0xFF, 0x11, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0x80, 0x5F, 0x9B, 0x34, 0xFB};
163 		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);
164 
165 		// 0x2AA7
166 		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);
167 
168 		// 0x2AAB
169 		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);
170 
171 		// set callbacks
172 		att_set_db(att_db_util_get_address());
173 		att_set_read_callback(&att_read_callback);
174 		att_set_write_callback(&att_write_callback);
175 	}
176 };
177 
178 TEST(AttDb, MtuExchange){
179 	// test some function
180 	att_request_len = 3;
181 	const uint8_t att_request[3] = { ATT_EXCHANGE_MTU_REQUEST, 0, att_connection.max_mtu};
182 	att_response_len = att_handle_request(&att_connection, (uint8_t *) att_request, att_request_len, att_response);
183 	CHECK_EQUAL(att_request_len, att_response_len);
184 	const uint8_t expected_response[] = { ATT_EXCHANGE_MTU_RESPONSE, att_connection.max_mtu, 0};
185 	MEMCMP_EQUAL(expected_response, att_response, att_response_len);
186 }
187 
188 
189 TEST(AttDb, handle_read_multiple_request){
190 	uint16_t value_handles[2];
191 	uint16_t num_value_handles;
192 
193 	// less then two values
194 	num_value_handles = 0;
195 	memset(&value_handles, 0, sizeof(value_handles));
196 	{
197 		att_request_len = att_read_multiple_request(num_value_handles, value_handles);
198 		CHECK_EQUAL(1 + 2 * num_value_handles, att_request_len);
199 		att_response_len = att_handle_request(&att_connection, (uint8_t *) att_request, att_request_len, att_response);
200 		const uint8_t expected_response[] = {ATT_ERROR_RESPONSE, ATT_READ_MULTIPLE_REQUEST, 0, 0, ATT_ERROR_INVALID_PDU};
201 		CHECK_EQUAL(sizeof(expected_response), att_response_len);
202 		MEMCMP_EQUAL(expected_response, att_response, att_response_len);
203 	}
204 
205 	num_value_handles = 1;
206 	value_handles[0] = 0x1;
207 	{
208 		att_request_len = att_read_multiple_request(num_value_handles, value_handles);
209 		CHECK_EQUAL(1 + 2 * num_value_handles, att_request_len);
210 		att_response_len = att_handle_request(&att_connection, (uint8_t *) att_request, att_request_len, att_response);
211 		const uint8_t expected_response[] = {ATT_ERROR_RESPONSE, ATT_READ_MULTIPLE_REQUEST, 0, 0, ATT_ERROR_INVALID_PDU};
212 		CHECK_EQUAL(sizeof(expected_response), att_response_len);
213 		MEMCMP_EQUAL(expected_response, att_response, att_response_len);
214 	}
215 
216 	// invalid handle
217 	num_value_handles = 2;
218 	value_handles[0] = 0x0;
219 	{
220 		att_request_len = att_read_multiple_request(num_value_handles, value_handles);
221 		CHECK_EQUAL(1 + 2 * num_value_handles, att_request_len);
222 		att_response_len = att_handle_request(&att_connection, (uint8_t *) att_request, att_request_len, att_response);
223 		const uint8_t expected_response[] = {ATT_ERROR_RESPONSE, ATT_READ_MULTIPLE_REQUEST, 0, 0, ATT_ERROR_INVALID_HANDLE};
224 		CHECK_EQUAL(sizeof(expected_response), att_response_len);
225 		MEMCMP_EQUAL(expected_response, att_response, att_response_len);
226 	}
227 
228 	num_value_handles = 2;
229 	value_handles[0] = 0xF1;
230 	value_handles[1] = 0xF2;
231 	{
232 		att_request_len = att_read_multiple_request(num_value_handles, value_handles);
233 		CHECK_EQUAL(1 + 2 * num_value_handles, att_request_len);
234 		att_response_len = att_handle_request(&att_connection, (uint8_t *) att_request, att_request_len, att_response);
235 		const uint8_t expected_response[] = {ATT_ERROR_RESPONSE, ATT_READ_MULTIPLE_REQUEST, value_handles[0], 0, ATT_ERROR_INVALID_HANDLE};
236 		CHECK_EQUAL(sizeof(expected_response), att_response_len);
237 		MEMCMP_EQUAL(expected_response, att_response, att_response_len);
238 	}
239 
240 	// handle read not permitted
241 	num_value_handles = 2;
242 	value_handles[0] = 0x05;
243 	value_handles[1] = 0x06;
244 	{
245 		att_request_len = att_read_multiple_request(num_value_handles, value_handles);
246 		CHECK_EQUAL(1 + 2 * num_value_handles, att_request_len);
247 		att_response_len = att_handle_request(&att_connection, (uint8_t *) att_request, att_request_len, att_response);
248 		const uint8_t expected_response[] = {ATT_ERROR_RESPONSE, ATT_READ_MULTIPLE_REQUEST, value_handles[1], 0, ATT_ERROR_READ_NOT_PERMITTED};
249 		CHECK_EQUAL(sizeof(expected_response), att_response_len);
250 		MEMCMP_EQUAL(expected_response, att_response, att_response_len);
251 	}
252 
253 	// security validation (single case)
254 	num_value_handles = 2;
255 	value_handles[0] = 0x05;
256 	value_handles[1] = 0x09;
257 	{
258 		att_request_len = att_read_multiple_request(num_value_handles, value_handles);
259 		CHECK_EQUAL(1 + 2 * num_value_handles, att_request_len);
260 		att_response_len = att_handle_request(&att_connection, (uint8_t *) att_request, att_request_len, att_response);
261 		const uint8_t expected_response[] = {ATT_ERROR_RESPONSE, ATT_READ_MULTIPLE_REQUEST, value_handles[1], 0, ATT_ERROR_INSUFFICIENT_AUTHENTICATION};
262 		CHECK_EQUAL(sizeof(expected_response), att_response_len);
263 		MEMCMP_EQUAL(expected_response, att_response, att_response_len);
264 	}
265 
266 
267 	// static read
268 	num_value_handles = 2;
269 	value_handles[0] = 0x03;
270 	value_handles[1] = 0x05;
271 	{
272 		read_callback_mode = READ_CALLBACK_MODE_RETURN_ONE_BYTE;
273 
274 		att_request_len = att_read_multiple_request(num_value_handles, value_handles);
275 		CHECK_EQUAL(1 + 2 * num_value_handles, att_request_len);
276 		att_response_len = att_handle_request(&att_connection, (uint8_t *) att_request, att_request_len, att_response);
277 		const uint8_t expected_response[] = {ATT_READ_MULTIPLE_RESPONSE, 0x64, 0x10, 0x06, 0x00, 0x1B, 0x2A};
278 		CHECK_EQUAL(sizeof(expected_response), att_response_len);
279 		MEMCMP_EQUAL(expected_response, att_response, att_response_len);
280 
281 		read_callback_mode = READ_CALLBACK_MODE_RETURN_DEFAULT;
282 	}
283 
284 #ifdef ENABLE_ATT_DELAYED_RESPONSE
285 	// dynamic read
286 	num_value_handles = 2;
287 	value_handles[0] = 0x03;
288 	value_handles[1] = 0x0c;
289 	{
290 		read_callback_mode = READ_CALLBACK_MODE_RETURN_PENDING;
291 
292 		att_request_len = att_read_multiple_request(num_value_handles, value_handles);
293 		CHECK_EQUAL(1 + 2 * num_value_handles, att_request_len);
294 		att_response_len = att_handle_request(&att_connection, (uint8_t *) att_request, att_request_len, att_response);
295 		const uint8_t expected_response[] = {ATT_READ_MULTIPLE_RESPONSE, 0x64};
296 		CHECK_EQUAL(sizeof(expected_response), att_response_len);
297 		MEMCMP_EQUAL(expected_response, att_response, att_response_len);
298 
299 		read_callback_mode = READ_CALLBACK_MODE_RETURN_DEFAULT;
300 	}
301 #endif
302 }
303 
304 TEST(AttDb, handle_write_request){
305 	uint16_t attribute_handle = 0x03;
306 
307 	// not sufficient request length
308 	{
309 		att_request[0] = ATT_WRITE_REQUEST;
310 		att_request_len = 1;
311 		att_response_len = att_handle_request(&att_connection, (uint8_t *) att_request, att_request_len, att_response);
312 		const uint8_t expected_response[] = {ATT_ERROR_RESPONSE, att_request[0], 0x00, 0x00, ATT_ERROR_INVALID_PDU};
313 		MEMCMP_EQUAL(expected_response, att_response, att_response_len);
314 		CHECK_EQUAL(sizeof(expected_response), att_response_len);
315 	}
316 
317 	{
318 		att_request[0] = ATT_WRITE_REQUEST;
319 		att_request[1] = 0x03;
320 		att_request_len = 2;
321 		att_response_len = att_handle_request(&att_connection, (uint8_t *) att_request, att_request_len, att_response);
322 		const uint8_t expected_response[] = {ATT_ERROR_RESPONSE, att_request[0], 0x00, 0x00, ATT_ERROR_INVALID_PDU};
323 		MEMCMP_EQUAL(expected_response, att_response, att_response_len);
324 		CHECK_EQUAL(sizeof(expected_response), att_response_len);
325 	}
326 
327 	// invalid handle
328 	{
329 		att_request[0] = ATT_WRITE_REQUEST;
330 		att_request[1] = 0;
331 		att_request[2] = 0;
332 		att_request_len = 3;
333 		att_response_len = att_handle_request(&att_connection, (uint8_t *) att_request, att_request_len, att_response);
334 		const uint8_t expected_response[] = {ATT_ERROR_RESPONSE, att_request[0], att_request[1], att_request[2], ATT_ERROR_INVALID_HANDLE};
335 		MEMCMP_EQUAL(expected_response, att_response, att_response_len);
336 		CHECK_EQUAL(sizeof(expected_response), att_response_len);
337 	}
338 
339 	// write not permited: invalid write callback
340 	{
341 		att_set_write_callback(NULL);
342 
343 		const uint8_t value[] = {0x50};
344 		att_request_len = att_write_request(ATT_WRITE_REQUEST, attribute_handle, sizeof(value), value);
345 		CHECK_EQUAL(3 + sizeof(value), att_request_len);
346 		att_response_len = att_handle_request(&att_connection, (uint8_t *) att_request, att_request_len, att_response);
347 		const uint8_t expected_response[] = {ATT_ERROR_RESPONSE, att_request[0], att_request[1], att_request[2], ATT_ERROR_WRITE_NOT_PERMITTED};
348 		MEMCMP_EQUAL(expected_response, att_response, att_response_len);
349 		CHECK_EQUAL(sizeof(expected_response), att_response_len);
350 
351 		att_set_write_callback(&att_write_callback);
352 	}
353 
354 	// write not permited: no ATT_PROPERTY_WRITE
355 	{
356 		const uint8_t value[] = {0x50};
357 		attribute_handle = 0x000c; // 0x2A49
358 		att_request_len = att_write_request(ATT_WRITE_REQUEST, attribute_handle, sizeof(value), value);
359 		CHECK_EQUAL(3 + sizeof(value), att_request_len);
360 		att_response_len = att_handle_request(&att_connection, (uint8_t *) att_request, att_request_len, att_response);
361 		const uint8_t expected_response[] = {ATT_ERROR_RESPONSE, att_request[0], att_request[1], att_request[2], ATT_ERROR_WRITE_NOT_PERMITTED};
362 		MEMCMP_EQUAL(expected_response, att_response, att_response_len);
363 		CHECK_EQUAL(sizeof(expected_response), att_response_len);
364 	}
365 
366 	// write not permited: no ATT_PROPERTY_DYNAMIC
367 	{
368 		const uint8_t value[] = {0x50};
369 		attribute_handle = 0x0003;
370 		att_request_len = att_write_request(ATT_WRITE_REQUEST, attribute_handle, sizeof(value), value);
371 		CHECK_EQUAL(3 + sizeof(value), att_request_len);
372 		att_response_len = att_handle_request(&att_connection, (uint8_t *) att_request, att_request_len, att_response);
373 		const uint8_t expected_response[] = {ATT_ERROR_RESPONSE, att_request[0], att_request[1], att_request[2], ATT_ERROR_WRITE_NOT_PERMITTED};
374 		MEMCMP_EQUAL(expected_response, att_response, att_response_len);
375 		CHECK_EQUAL(sizeof(expected_response), att_response_len);
376 	}
377 
378 	// security validation
379 	{
380 		const uint8_t value[] = {0x50};
381 		attribute_handle = 0x000f; // 0x2A35
382 		att_request_len = att_write_request(ATT_WRITE_REQUEST, attribute_handle, sizeof(value), value);
383 		CHECK_EQUAL(3 + sizeof(value), att_request_len);
384 		att_response_len = att_handle_request(&att_connection, (uint8_t *) att_request, att_request_len, att_response);
385 		const uint8_t expected_response[] = {ATT_ERROR_RESPONSE, att_request[0], att_request[1], att_request[2], ATT_ERROR_INSUFFICIENT_AUTHENTICATION};
386 		MEMCMP_EQUAL(expected_response, att_response, att_response_len);
387 		CHECK_EQUAL(sizeof(expected_response), att_response_len);
388 	}
389 
390 	// att_persistent_ccc_cache: ATT_PROPERTY_UUID16
391 	// att_persistent_ccc_cache: ATT_PROPERTY_UUID128
392 
393 	// some callback error other then ATT_INTERNAL_WRITE_RESPONSE_PENDING
394 	{
395 		write_callback_mode = WRITE_CALLBACK_MODE_RETURN_INVALID_ATTRIBUTE_VALUE_LENGTH;
396 
397 		const uint8_t value[] = {0x50};
398 		attribute_handle = 0x0011; // 0x2A38
399 		att_request_len = att_write_request(ATT_WRITE_REQUEST, attribute_handle, sizeof(value), value);
400 		CHECK_EQUAL(3 + sizeof(value), att_request_len);
401 		att_response_len = att_handle_request(&att_connection, (uint8_t *) att_request, att_request_len, att_response);
402 		const uint8_t expected_response[] = {ATT_ERROR_RESPONSE, att_request[0], att_request[1], att_request[2], ATT_ERROR_INVALID_ATTRIBUTE_VALUE_LENGTH};
403 		MEMCMP_EQUAL(expected_response, att_response, att_response_len);
404 		CHECK_EQUAL(sizeof(expected_response), att_response_len);
405 
406 		write_callback_mode = WRITE_CALLBACK_MODE_RETURN_DEFAULT;
407 	}
408 
409 #ifdef ENABLE_ATT_DELAYED_RESPONSE
410 	// delayed response
411 	{
412 		write_callback_mode = WRITE_CALLBACK_MODE_RETURN_ERROR_WRITE_RESPONSE_PENDING;
413 
414 		const uint8_t value[] = {0x50};
415 		attribute_handle = 0x0011; // 0x2A38
416 		att_request_len = att_write_request(ATT_WRITE_REQUEST, attribute_handle, sizeof(value), value);
417 		CHECK_EQUAL(3 + sizeof(value), att_request_len);
418 		att_response_len = att_handle_request(&att_connection, (uint8_t *) att_request, att_request_len, att_response);
419 		CHECK_EQUAL(ATT_INTERNAL_WRITE_RESPONSE_PENDING, att_response_len);
420 
421 		write_callback_mode = WRITE_CALLBACK_MODE_RETURN_DEFAULT;
422 	}
423 #endif
424 
425 	// correct write
426 	{
427 		const uint8_t value[] = {0x50};
428 		attribute_handle = 0x0011;
429 		att_request_len = att_write_request(ATT_WRITE_REQUEST, attribute_handle, sizeof(value), value);
430 		CHECK_EQUAL(3 + sizeof(value), att_request_len);
431 		att_response_len = att_handle_request(&att_connection, (uint8_t *) att_request, att_request_len, att_response);
432 		const uint8_t expected_response[] = {ATT_WRITE_RESPONSE};
433 		MEMCMP_EQUAL(expected_response, att_response, att_response_len);
434 		CHECK_EQUAL(sizeof(expected_response), att_response_len);
435 	}
436 }
437 
438 TEST(AttDb, handle_prepare_write_request){
439 	uint16_t attribute_handle = 0x0011;
440 	uint16_t value_offset = 0x10;
441 
442 	// not sufficient request length
443 	{
444 		att_request[0] = ATT_PREPARE_WRITE_REQUEST;
445 		att_request_len = 1;
446 		att_response_len = att_handle_request(&att_connection, (uint8_t *) att_request, att_request_len, att_response);
447 		const uint8_t expected_response[] = {ATT_ERROR_RESPONSE, att_request[0], 0x00, 0x00, ATT_ERROR_INVALID_PDU};
448 		MEMCMP_EQUAL(expected_response, att_response, att_response_len);
449 		CHECK_EQUAL(sizeof(expected_response), att_response_len);
450 	}
451 
452 	// write not permited: invalid write callback
453 	{
454 		att_set_write_callback(NULL);
455 
456 		att_request_len = att_prepare_write_request(ATT_PREPARE_WRITE_REQUEST, attribute_handle, value_offset);
457 		CHECK_EQUAL(5, att_request_len);
458 		att_response_len = att_handle_request(&att_connection, (uint8_t *) att_request, att_request_len, att_response);
459 		const uint8_t expected_response[] = {ATT_ERROR_RESPONSE, att_request[0], att_request[1], att_request[2], ATT_ERROR_WRITE_NOT_PERMITTED};
460 		MEMCMP_EQUAL(expected_response, att_response, att_response_len);
461 		CHECK_EQUAL(sizeof(expected_response), att_response_len);
462 
463 		att_set_write_callback(&att_write_callback);
464 	}
465 
466 	// invalid handle
467 	{
468 		att_request_len = att_prepare_write_request(ATT_PREPARE_WRITE_REQUEST, 0, 0);
469 		CHECK_EQUAL(5, att_request_len);
470 		att_response_len = att_handle_request(&att_connection, (uint8_t *) att_request, att_request_len, att_response);
471 		const uint8_t expected_response[] = {ATT_ERROR_RESPONSE, att_request[0], att_request[1], att_request[2], ATT_ERROR_INVALID_HANDLE};
472 		MEMCMP_EQUAL(expected_response, att_response, att_response_len);
473 		CHECK_EQUAL(sizeof(expected_response), att_response_len);
474 	}
475 
476 	// write not permited: no ATT_PROPERTY_WRITE
477 	{
478 		attribute_handle = 0x000c; // 0x2A49
479 		att_request_len = att_prepare_write_request(ATT_PREPARE_WRITE_REQUEST, attribute_handle, value_offset);
480 		CHECK_EQUAL(5, att_request_len);
481 		att_response_len = att_handle_request(&att_connection, (uint8_t *) att_request, att_request_len, att_response);
482 
483 		const uint8_t expected_response[] = {ATT_ERROR_RESPONSE, att_request[0], att_request[1], att_request[2], ATT_ERROR_WRITE_NOT_PERMITTED};
484 		MEMCMP_EQUAL(expected_response, att_response, att_response_len);
485 		CHECK_EQUAL(sizeof(expected_response), att_response_len);
486 	}
487 
488 
489 	// write not permited: no ATT_PROPERTY_DYNAMIC
490 	{
491 		attribute_handle = 0x0003;
492 		att_request_len = att_prepare_write_request(ATT_PREPARE_WRITE_REQUEST, attribute_handle, value_offset);
493 		CHECK_EQUAL(5, att_request_len);
494 		att_response_len = att_handle_request(&att_connection, (uint8_t *) att_request, att_request_len, att_response);
495 		const uint8_t expected_response[] = {ATT_ERROR_RESPONSE, att_request[0], att_request[1], att_request[2], ATT_ERROR_WRITE_NOT_PERMITTED};
496 		MEMCMP_EQUAL(expected_response, att_response, att_response_len);
497 		CHECK_EQUAL(sizeof(expected_response), att_response_len);
498 	}
499 
500 	// security validation
501 	{
502 		attribute_handle = 0x000f; // 0x2A35
503 		att_request_len = att_prepare_write_request(ATT_PREPARE_WRITE_REQUEST, attribute_handle, value_offset);
504 		CHECK_EQUAL(5, att_request_len);
505 		att_response_len = att_handle_request(&att_connection, (uint8_t *) att_request, att_request_len, att_response);
506 		const uint8_t expected_response[] = {ATT_ERROR_RESPONSE, att_request[0], att_request[1], att_request[2], ATT_ERROR_INSUFFICIENT_AUTHENTICATION};
507 		MEMCMP_EQUAL(expected_response, att_response, att_response_len);
508 		CHECK_EQUAL(sizeof(expected_response), att_response_len);
509 	}
510 
511 	// some callback error other then ATT_INTERNAL_WRITE_RESPONSE_PENDING
512 	{
513 		write_callback_mode = WRITE_CALLBACK_MODE_RETURN_INVALID_ATTRIBUTE_VALUE_LENGTH;
514 
515 		attribute_handle = 0x0011; // 0x2A38
516 
517 		// prepare write
518 		att_request_len = att_prepare_write_request(ATT_PREPARE_WRITE_REQUEST, attribute_handle, value_offset);
519 		CHECK_EQUAL(5, att_request_len);
520 
521 		att_response_len = att_handle_request(&att_connection, (uint8_t *) att_request, att_request_len, att_response);
522 		const uint8_t expected_response_prepare_write[] = {ATT_PREPARE_WRITE_RESPONSE, 0x11, 0x00, 0x10, 0x00};
523 		MEMCMP_EQUAL(expected_response_prepare_write, att_response, att_response_len);
524 		CHECK_EQUAL(sizeof(expected_response_prepare_write), att_response_len);
525 
526 		// execute write
527 		att_request_len = att_prepare_write_request(ATT_EXECUTE_WRITE_REQUEST, attribute_handle, value_offset);
528 		CHECK_EQUAL(5, att_request_len);
529 
530 		att_response_len = att_handle_request(&att_connection, (uint8_t *) att_request, att_request_len, att_response);
531 		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};
532 		MEMCMP_EQUAL(expected_response_write_execute, att_response, att_response_len);
533 		CHECK_EQUAL(sizeof(expected_response_write_execute), att_response_len);
534 
535 		write_callback_mode = WRITE_CALLBACK_MODE_RETURN_DEFAULT;
536 	}
537 
538 #ifdef ENABLE_ATT_DELAYED_RESPONSE
539 	// delayed response
540 	{
541 		write_callback_mode = WRITE_CALLBACK_MODE_RETURN_ERROR_WRITE_RESPONSE_PENDING;
542 
543 		attribute_handle = 0x0011; // 0x2A38
544 		att_request_len = att_prepare_write_request(ATT_PREPARE_WRITE_REQUEST, attribute_handle, value_offset);
545 		CHECK_EQUAL(5, att_request_len);
546 		att_response_len = att_handle_request(&att_connection, (uint8_t *) att_request, att_request_len, att_response);
547 
548 
549 		CHECK_EQUAL(ATT_INTERNAL_WRITE_RESPONSE_PENDING, att_response_len);
550 
551 		write_callback_mode = WRITE_CALLBACK_MODE_RETURN_DEFAULT;
552 	}
553 #endif
554 
555 	// correct write
556 	{
557 		attribute_handle = 0x0011;
558 		att_request_len = att_prepare_write_request(ATT_PREPARE_WRITE_REQUEST, attribute_handle, value_offset);
559 		CHECK_EQUAL(5, att_request_len);
560 		att_response_len = att_handle_request(&att_connection, (uint8_t *) att_request, att_request_len, att_response);
561 		const uint8_t expected_response[] = {ATT_PREPARE_WRITE_RESPONSE, 0x11, 0x00, 0x10, 0x00};
562 		MEMCMP_EQUAL(expected_response, att_response, att_response_len);
563 		CHECK_EQUAL(sizeof(expected_response), att_response_len);
564 	}
565 }
566 
567 TEST(AttDb, att_uuid_for_handle){
568 	// existing attribute handle
569 	uint16_t uuid = att_uuid_for_handle(0x0011);
570 	uint16_t expected_response = 0x2A38;
571 	CHECK_EQUAL(expected_response, uuid);
572 
573 	// unknown attribute handle
574 	uuid = att_uuid_for_handle(0xFF00);
575 	expected_response = 0;
576 	CHECK_EQUAL(expected_response, uuid);
577 
578 	// attribute handle for uuid128
579 	uuid = att_uuid_for_handle(0x0014);
580 	expected_response = 0;
581 	CHECK_EQUAL(expected_response, uuid);
582 }
583 
584 TEST(AttDb, handle_write_command){
585 	uint16_t attribute_handle = 0x03;
586 	att_dump_attributes();
587 
588 	// not sufficient request length
589 	{
590 		att_request[0] = ATT_WRITE_COMMAND;
591 		att_request_len = 1;
592 		att_response_len = att_handle_request(&att_connection, (uint8_t *) att_request, att_request_len, att_response);
593 		CHECK_EQUAL(0, att_response_len);
594 	}
595 
596 	{
597 		att_request[0] = ATT_WRITE_COMMAND;
598 		att_request[1] = 0x03;
599 		att_request_len = 2;
600 		att_response_len = att_handle_request(&att_connection, (uint8_t *) att_request, att_request_len, att_response);
601 		CHECK_EQUAL(0, att_response_len);
602 	}
603 
604 	// invalid write callback
605 	{
606 		att_set_write_callback(NULL);
607 
608 		const uint8_t value[] = {0x50};
609 		att_request_len = att_write_request(ATT_WRITE_COMMAND, attribute_handle, sizeof(value), value);
610 		CHECK_EQUAL(3 + sizeof(value), att_request_len);
611 
612 		att_response_len = att_handle_request(&att_connection, (uint8_t *) att_request, att_request_len, att_response);
613 		CHECK_EQUAL(0, att_response_len);
614 
615 		att_set_write_callback(&att_write_callback);
616 	}
617 
618 	// invalid handle
619 	{
620 		att_request[0] = ATT_WRITE_COMMAND;
621 		att_request[1] = 0;
622 		att_request[2] = 0;
623 		att_request_len = 3;
624 		att_response_len = att_handle_request(&att_connection, (uint8_t *) att_request, att_request_len, att_response);
625 		CHECK_EQUAL(0, att_response_len);
626 	}
627 
628 	// write not permited: no ATT_PROPERTY_DYNAMIC
629 	{
630 		const uint8_t value[] = {0x50};
631 		attribute_handle = 0x0003;
632 		att_request_len = att_write_request(ATT_WRITE_COMMAND, attribute_handle, sizeof(value), value);
633 		CHECK_EQUAL(3 + sizeof(value), att_request_len);
634 		att_response_len = att_handle_request(&att_connection, (uint8_t *) att_request, att_request_len, att_response);
635 		CHECK_EQUAL(0, att_response_len);
636 	}
637 
638 	// write not permited: no ATT_PROPERTY_WRITE_WITHOUT_RESPONSE
639 	{
640 		const uint8_t value[] = {0x50};
641 		attribute_handle = 0x000c; // 0x2A49
642 		att_request_len = att_write_request(ATT_WRITE_COMMAND, attribute_handle, sizeof(value), value);
643 		CHECK_EQUAL(3 + sizeof(value), att_request_len);
644 		att_response_len = att_handle_request(&att_connection, (uint8_t *) att_request, att_request_len, att_response);
645 		CHECK_EQUAL(0, att_response_len);
646 	}
647 
648 	// security validation
649 	{
650 		const uint8_t value[] = {0x50};
651 		attribute_handle = 0x0017; // 0x2AA7
652 		att_request_len = att_write_request(ATT_WRITE_COMMAND, attribute_handle, sizeof(value), value);
653 		CHECK_EQUAL(3 + sizeof(value), att_request_len);
654 		att_response_len = att_handle_request(&att_connection, (uint8_t *) att_request, att_request_len, att_response);
655 		CHECK_EQUAL(0, att_response_len);
656 	}
657 
658 	// correct write
659 	{
660 		const uint8_t value[] = {0x50};
661 		attribute_handle = 0x001A; // 0x2AAB
662 		att_request_len = att_write_request(ATT_WRITE_COMMAND, attribute_handle, sizeof(value), value);
663 		CHECK_EQUAL(3 + sizeof(value), att_request_len);
664 		att_response_len = att_handle_request(&att_connection, (uint8_t *) att_request, att_request_len, att_response);
665 		CHECK_EQUAL(0, att_response_len);
666 	}
667 }
668 
669 TEST(AttDb, att_read_callback_handle_blob){
670 	{
671 		const uint8_t blob[] = {0x44, 0x55};
672 		uint16_t blob_size = att_read_callback_handle_blob(blob, sizeof(blob), 0, NULL, 0);
673 		CHECK_EQUAL(2, blob_size);
674 	}
675 
676 	{
677 		const uint8_t blob[] = {};
678 		uint16_t blob_size = att_read_callback_handle_blob(blob, sizeof(blob), 0, callback_buffer, sizeof(callback_buffer));
679 		CHECK_EQUAL(0, blob_size);
680 	}
681 
682 	{
683 		const uint8_t blob[] = {};
684 		uint16_t blob_size = att_read_callback_handle_blob(blob, sizeof(blob), 10, callback_buffer, sizeof(callback_buffer));
685 		CHECK_EQUAL(0, blob_size);
686 	}
687 
688 	{
689 		const uint8_t blob[] = {0x55};
690 		uint16_t blob_size = att_read_callback_handle_blob(blob, sizeof(blob), 0, callback_buffer, sizeof(callback_buffer));
691 		CHECK_EQUAL(1, blob_size);
692 	}
693 
694 	{
695 		const uint8_t blob[] = {0x55};
696 		uint16_t blob_size = att_read_callback_handle_blob(blob, sizeof(blob), 10, callback_buffer, sizeof(callback_buffer));
697 		CHECK_EQUAL(0, blob_size);
698 	}
699 
700 	{
701 		const uint8_t blob[] = {0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA};
702 		uint16_t blob_size = att_read_callback_handle_blob(blob, sizeof(blob), 0, callback_buffer, sizeof(callback_buffer));
703 		CHECK_EQUAL(10, blob_size);
704 	}
705 
706 	{
707 		const uint8_t blob[] = {0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA};
708 		uint16_t blob_size = att_read_callback_handle_blob(blob, sizeof(blob), 1, callback_buffer, sizeof(callback_buffer));
709 		CHECK_EQUAL(9, blob_size);
710 	}
711 
712 	{
713 		const uint8_t blob[] = {0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA};
714 		uint16_t blob_size = att_read_callback_handle_blob(blob, sizeof(blob), 10, callback_buffer, sizeof(callback_buffer));
715 		CHECK_EQUAL(0, blob_size);
716 	}
717 }
718 
719 TEST(AttDb, att_read_callback_handle_byte){
720 	{
721 		uint16_t blob_size = att_read_callback_handle_byte(0x55, 0, NULL, 0);
722 		CHECK_EQUAL(1, blob_size);
723 	}
724 
725 	{
726 		uint16_t blob_size = att_read_callback_handle_byte(0x55, 10, callback_buffer, sizeof(callback_buffer));
727 		CHECK_EQUAL(0, blob_size);
728 	}
729 
730 	{
731 		uint16_t blob_size = att_read_callback_handle_byte(0x55, 0, callback_buffer, sizeof(callback_buffer));
732 		CHECK_EQUAL(1, blob_size);
733 	}
734 }
735 
736 TEST(AttDb, att_read_callback_handle_little_endian_16){
737 	{
738 		uint16_t blob_size = att_read_callback_handle_little_endian_16(0x1122, 0, NULL, 0);
739 		CHECK_EQUAL(2, blob_size);
740 	}
741 
742 	{
743 		uint16_t blob_size = att_read_callback_handle_little_endian_16(0x1122, 10, callback_buffer, sizeof(callback_buffer));
744 		CHECK_EQUAL(0, blob_size);
745 	}
746 
747 	{
748 		uint16_t blob_size = att_read_callback_handle_little_endian_16(0x1122, 1, callback_buffer, sizeof(callback_buffer));
749 		CHECK_EQUAL(1, blob_size);
750 	}
751 
752 	{
753 		uint16_t blob_size = att_read_callback_handle_little_endian_16(0x1122, 0, callback_buffer, sizeof(callback_buffer));
754 		CHECK_EQUAL(2, blob_size);
755 	}
756 }
757 
758 TEST(AttDb, att_read_callback_handle_little_endian_32){
759 	{
760 		uint16_t blob_size = att_read_callback_handle_little_endian_32(0x11223344, 0, NULL, 0);
761 		CHECK_EQUAL(4, blob_size);
762 	}
763 
764 	{
765 		uint16_t blob_size = att_read_callback_handle_little_endian_32(0x11223344, 10, callback_buffer, sizeof(callback_buffer));
766 		CHECK_EQUAL(0, blob_size);
767 	}
768 
769 	{
770 		uint16_t blob_size = att_read_callback_handle_little_endian_32(0x11223344, 3, callback_buffer, sizeof(callback_buffer));
771 		CHECK_EQUAL(1, blob_size);
772 	}
773 
774 	{
775 		uint16_t blob_size = att_read_callback_handle_little_endian_32(0x11223344, 0, callback_buffer, sizeof(callback_buffer));
776 		CHECK_EQUAL(4, blob_size);
777 	}
778 }
779 
780 
781 int main (int argc, const char * argv[]){
782     return CommandLineTestRunner::RunAllTests(argc, argv);
783 }
784