Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
wine-mirror
GitHub Repository: wine-mirror/wine
Path: blob/master/dlls/bluetoothapis/tests/sdp.c
5968 views
1
/* Tests for bluetoothapis.dll's SDP API
2
*
3
* Copyright 2024 Vibhav Pant
4
*
5
* This library is free software; you can redistribute it and/or
6
* modify it under the terms of the GNU Lesser General Public
7
* License as published by the Free Software Foundation; either
8
* version 2.1 of the License, or (at your option) any later version.
9
*
10
* This library is distributed in the hope that it will be useful,
11
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13
* Lesser General Public License for more details.
14
*
15
* You should have received a copy of the GNU Lesser General Public
16
* License along with this library; if not, write to the Free Software
17
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
18
*
19
*/
20
21
#include <stdarg.h>
22
#include <windef.h>
23
#include <winbase.h>
24
25
#include "bthsdpdef.h"
26
#include "bluetoothapis.h"
27
28
#include "wine/test.h"
29
30
static const char *debugstr_SDP_ELEMENT_DATA( const SDP_ELEMENT_DATA *data )
31
{
32
return wine_dbg_sprintf( "{%#x %#x {%I64u %I64u}}", data->type, data->specificType,
33
data->data.uint128.LowPart, data->data.uint128.HighPart );
34
}
35
36
/* Returns the exact number of bytes we need to compare to test equality between the 'data' fields of two
37
* SDP_ELEMENT_DATA. */
38
static SIZE_T sdp_type_size( SDP_TYPE type, SDP_SPECIFICTYPE st )
39
{
40
41
switch (type)
42
{
43
case SDP_TYPE_NIL:
44
return 0;
45
case SDP_TYPE_BOOLEAN:
46
return sizeof( UCHAR );
47
case SDP_TYPE_INT:
48
case SDP_TYPE_UINT:
49
case SDP_TYPE_UUID:
50
return 1 << ((st >> 8) & 0x7);
51
default: /* Container/Sequence-like types. */
52
return sizeof( BYTE * ) + sizeof( ULONG );
53
}
54
}
55
56
static void test_BluetoothSdpGetElementData( BYTE *stream, SIZE_T size, DWORD error,
57
const SDP_ELEMENT_DATA *sdp_data )
58
{
59
DWORD ret;
60
SDP_ELEMENT_DATA result = {0};
61
62
ret = BluetoothSdpGetElementData( stream, size, &result );
63
ok( ret == error, "%ld != %ld.\n", error, ret );
64
if (ret == error && error == ERROR_SUCCESS)
65
{
66
ok( result.type == sdp_data->type, "%#x != %#x.\n", sdp_data->type, result.type );
67
ok( result.specificType == sdp_data->specificType,
68
"%#x != %#x.\n", sdp_data->specificType,
69
result.specificType );
70
ok( !memcmp( &sdp_data->data, &result.data, sdp_type_size( result.type, result.specificType ) ),
71
"%s != %s.\n", debugstr_SDP_ELEMENT_DATA( sdp_data ),
72
debugstr_SDP_ELEMENT_DATA( &result ) );
73
}
74
}
75
76
static void test_BluetoothSdpGetElementData_invalid( void )
77
{
78
SDP_ELEMENT_DATA data;
79
BYTE stream[] = {0};
80
DWORD ret;
81
82
ret = BluetoothSdpGetElementData( NULL, 10, &data );
83
ok( ret == ERROR_INVALID_PARAMETER, "%d != %ld.\n", ERROR_INVALID_PARAMETER, ret );
84
85
ret = BluetoothSdpGetElementData( stream, 1, NULL );
86
ok( ret == ERROR_INVALID_PARAMETER, "%d != %ld.\n", ERROR_INVALID_PARAMETER, ret );
87
88
ret = BluetoothSdpGetElementData( stream, 0, &data );
89
ok( ret == ERROR_INVALID_PARAMETER, "%d != %ld.\n", ERROR_INVALID_PARAMETER, ret );
90
91
ret = BluetoothSdpGetElementData( NULL, 0, NULL );
92
ok( ret == ERROR_INVALID_PARAMETER, "%d != %ld.\n", ERROR_INVALID_PARAMETER, ret );
93
}
94
95
static void test_BluetoothSdpGetElementData_nil( void )
96
{
97
struct
98
{
99
BYTE data_elem;
100
DWORD error;
101
SDP_ELEMENT_DATA data;
102
} test_cases[] = {
103
{0x0, ERROR_SUCCESS, {.type = SDP_TYPE_NIL, .specificType = SDP_ST_NONE }},
104
{0x1, ERROR_INVALID_PARAMETER},
105
{0x3, ERROR_INVALID_PARAMETER},
106
{0x4, ERROR_INVALID_PARAMETER},
107
};
108
SIZE_T i;
109
110
for (i = 0; i < ARRAY_SIZE( test_cases ); i++)
111
{
112
winetest_push_context( "test_cases nil %d", (int)i );
113
test_BluetoothSdpGetElementData( &test_cases[i].data_elem, 1, test_cases[i].error,
114
&test_cases[i].data );
115
winetest_pop_context();
116
}
117
}
118
119
#define SDP_TYPE_DESC_INT8 (0x10)
120
#define SDP_TYPE_DESC_UINT8 (0x8)
121
#define SDP_TYPE_DESC_INT16 (0x11)
122
#define SDP_TYPE_DESC_UINT16 (0x9)
123
#define SDP_TYPE_DESC_INT32 (0x12)
124
#define SDP_TYPE_DESC_UINT32 (0xa)
125
#define SDP_TYPE_DESC_INT64 (0x13)
126
#define SDP_TYPE_DESC_UINT64 (0xb)
127
#define SDP_TYPE_DESC_INT128 (0x14)
128
#define SDP_TYPE_DESC_UINT128 (0xc)
129
130
#define SDP_TYPE_DESC_STR8 (0x25)
131
#define SDP_TYPE_DESC_STR16 (0x26)
132
#define SDP_TYPE_DESC_STR32 (0x27)
133
134
#define SDP_TYPE_DESC_SEQ8 (0x35)
135
#define SDP_TYPE_DESC_SEQ16 (0x36)
136
#define SDP_TYPE_DESC_SEQ32 (0x37)
137
138
static void test_BluetoothSdpGetElementData_ints( void )
139
{
140
struct
141
{
142
BYTE data_elem[17];
143
SIZE_T size;
144
DWORD error;
145
SDP_ELEMENT_DATA data;
146
} test_cases[] = {
147
{
148
{SDP_TYPE_DESC_INT8, 0xde},
149
2,
150
ERROR_SUCCESS,
151
{SDP_TYPE_INT, SDP_ST_INT8, {.int8 = 0xde}}
152
},
153
{
154
{SDP_TYPE_DESC_UINT8, 0xde},
155
2,
156
ERROR_SUCCESS,
157
{SDP_TYPE_UINT, SDP_ST_UINT8, {.uint8 = 0xde}},
158
},
159
{
160
{SDP_TYPE_DESC_INT16, 0xde, 0xad},
161
3,
162
ERROR_SUCCESS,
163
{SDP_TYPE_INT, SDP_ST_INT16, {.int16 = 0xdead}},
164
},
165
{
166
{SDP_TYPE_DESC_UINT16, 0xde, 0xad },
167
3,
168
ERROR_SUCCESS,
169
{SDP_TYPE_UINT, SDP_ST_UINT16, {.uint16 = 0xdead}},
170
},
171
{
172
{SDP_TYPE_DESC_INT32, 0xde, 0xad, 0xbe, 0xef},
173
5,
174
ERROR_SUCCESS,
175
{SDP_TYPE_INT, SDP_ST_INT32, {.int32 = 0xdeadbeef}},
176
},
177
{
178
{SDP_TYPE_DESC_UINT32, 0xde, 0xad, 0xbe, 0xef},
179
5,
180
ERROR_SUCCESS,
181
{SDP_TYPE_UINT, SDP_ST_UINT32, {.uint32 = 0xdeadbeef}},
182
},
183
{
184
{SDP_TYPE_DESC_INT64, 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef},
185
9,
186
ERROR_SUCCESS,
187
{SDP_TYPE_INT, SDP_ST_INT64, {.int64 = 0xdeadbeefdeadbeef}},
188
},
189
{
190
{SDP_TYPE_DESC_UINT64, 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef},
191
9,
192
ERROR_SUCCESS,
193
{SDP_TYPE_UINT, SDP_ST_UINT64, {.uint64 = 0xdeadbeefdeadbeef}},
194
},
195
{
196
{SDP_TYPE_DESC_INT64, 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef},
197
9,
198
ERROR_SUCCESS,
199
{SDP_TYPE_INT, SDP_ST_INT64, {.int64 = 0xdeadbeefdeadbeef}},
200
},
201
{
202
{SDP_TYPE_DESC_UINT64, 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef},
203
9,
204
ERROR_SUCCESS,
205
{SDP_TYPE_UINT, SDP_ST_UINT64, {.uint64 = 0xdeadbeefdeadbeef}},
206
},
207
{
208
{SDP_TYPE_DESC_INT128, 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef },
209
17,
210
ERROR_SUCCESS,
211
{SDP_TYPE_INT, SDP_ST_INT128, {.int128 = {0xdeadbeefdeadbeef, 0xdeadbeefdeadbeef}}},
212
},
213
{
214
{SDP_TYPE_DESC_UINT128, 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef},
215
17,
216
ERROR_SUCCESS,
217
{SDP_TYPE_UINT, SDP_ST_UINT128, {.uint128 = {0xdeadbeefdeadbeef, 0xdeadbeefdeadbeef}}},
218
}
219
};
220
SIZE_T i;
221
222
for (i = 0; i < ARRAY_SIZE( test_cases ); i++)
223
{
224
winetest_push_context( "test_cases int %d", (int)i );
225
test_BluetoothSdpGetElementData( test_cases[i].data_elem, test_cases[i].size,
226
test_cases[i].error, &test_cases[i].data );
227
winetest_pop_context();
228
}
229
}
230
231
static void test_BluetoothSdpGetElementData_str( void )
232
{
233
struct {
234
BYTE stream[11];
235
SIZE_T size;
236
DWORD error;
237
SDP_ELEMENT_DATA data;
238
const char *string;
239
} test_cases[] = {
240
{
241
{SDP_TYPE_DESC_STR8, 0x06, 'f', 'o', 'o', 'b', 'a', 'r'},
242
8,
243
ERROR_SUCCESS,
244
{SDP_TYPE_STRING, SDP_ST_NONE, {.string = {&test_cases[0].stream[2], 6}}},
245
"foobar",
246
},
247
{
248
{SDP_TYPE_DESC_STR16, 0x00, 0x06, 'f', 'o', 'o', 'b', 'a', 'r'},
249
9,
250
ERROR_SUCCESS,
251
{SDP_TYPE_STRING, SDP_ST_NONE, {.string = {&test_cases[1].stream[3], 6}}},
252
"foobar",
253
},
254
{
255
{SDP_TYPE_DESC_STR32, 0x00, 0x00, 0x00, 0x06, 'f', 'o', 'o', 'b', 'a', 'r'},
256
11,
257
ERROR_SUCCESS,
258
{SDP_TYPE_STRING, SDP_ST_NONE, {.string = {&test_cases[2].stream[5], 6}}},
259
"foobar",
260
}
261
};
262
SIZE_T i;
263
264
for (i = 0; i < ARRAY_SIZE( test_cases ); i++)
265
{
266
winetest_push_context( "test_cases str %d", (int)i );
267
test_BluetoothSdpGetElementData( test_cases[i].stream, test_cases[i].size,
268
test_cases[i].error, &test_cases[i].data );
269
if (test_cases[i].error == ERROR_SUCCESS)
270
{
271
SDP_ELEMENT_DATA result = {0};
272
if (!BluetoothSdpGetElementData( test_cases[i].stream, test_cases[i].size, &result ))
273
{
274
ok( strlen( test_cases[i].string ) == result.data.string.length, "%s != %s.\n",
275
debugstr_a( test_cases[i].string ),
276
debugstr_an( (const char *)result.data.string.value,
277
result.data.string.length ) );
278
ok( !memcmp( result.data.string.value, test_cases[i].string,
279
result.data.string.length ),
280
"%s != %s.\n", debugstr_a( test_cases[i].string ),
281
debugstr_an( (const char *)result.data.string.value,
282
result.data.string.length ) );
283
}
284
}
285
winetest_pop_context();
286
}
287
}
288
289
static void test_BluetoothSdpGetContainerElementData( void )
290
{
291
struct {
292
BYTE stream[11];
293
SIZE_T size;
294
DWORD error;
295
SDP_ELEMENT_DATA data;
296
SDP_ELEMENT_DATA sequence[6];
297
SIZE_T container_size;
298
} test_cases[] = {
299
{
300
{SDP_TYPE_DESC_SEQ8, 0x06, SDP_TYPE_DESC_UINT8, 0xde, SDP_TYPE_DESC_UINT8, 0xad, SDP_TYPE_DESC_UINT8, 0xbe},
301
8,
302
ERROR_SUCCESS,
303
{SDP_TYPE_SEQUENCE, SDP_ST_NONE, {.sequence = {&test_cases[0].stream[0], 8}}},
304
{
305
{SDP_TYPE_UINT, SDP_ST_UINT8, {.uint8 = 0xde}},
306
{SDP_TYPE_UINT, SDP_ST_UINT8, {.uint8 = 0xad}},
307
{SDP_TYPE_UINT, SDP_ST_UINT8, {.uint8 = 0xbe}}
308
},
309
3
310
},
311
{
312
{SDP_TYPE_DESC_SEQ16, 0x00, 0x06, SDP_TYPE_DESC_UINT8, 0xde, SDP_TYPE_DESC_UINT8, 0xad, SDP_TYPE_DESC_UINT8, 0xbe},
313
9,
314
ERROR_SUCCESS,
315
{SDP_TYPE_SEQUENCE, SDP_ST_NONE, {.sequence = {&test_cases[1].stream[0], 9}}},
316
{
317
{SDP_TYPE_UINT, SDP_ST_UINT8, {.uint8 = 0xde}},
318
{SDP_TYPE_UINT, SDP_ST_UINT8, {.uint8 = 0xad}},
319
{SDP_TYPE_UINT, SDP_ST_UINT8, {.uint8 = 0xbe}}
320
},
321
3
322
},
323
{
324
{SDP_TYPE_DESC_SEQ32, 0x00, 0x00, 0x00, 0x06, SDP_TYPE_DESC_UINT8, 0xde, SDP_TYPE_DESC_UINT8, 0xad, SDP_TYPE_DESC_UINT8, 0xbe},
325
11,
326
ERROR_SUCCESS,
327
{SDP_TYPE_SEQUENCE, SDP_ST_NONE, {.sequence = {&test_cases[2].stream[0], 11}}},
328
{
329
{SDP_TYPE_UINT, SDP_ST_UINT8, {.uint8 = 0xde}},
330
{SDP_TYPE_UINT, SDP_ST_UINT8, {.uint8 = 0xad}},
331
{SDP_TYPE_UINT, SDP_ST_UINT8, {.uint8 = 0xbe}}
332
},
333
3
334
},
335
{
336
{SDP_TYPE_DESC_SEQ8, SDP_TYPE_DESC_UINT8, 0xde, SDP_TYPE_DESC_UINT8, 0xad, SDP_TYPE_DESC_UINT8, 0xbe},
337
1,
338
ERROR_INVALID_PARAMETER,
339
},
340
};
341
SIZE_T i;
342
343
for (i = 0; i < ARRAY_SIZE( test_cases ); i++)
344
{
345
SIZE_T n = 0;
346
HBLUETOOTH_CONTAINER_ELEMENT handle = NULL;
347
DWORD ret;
348
349
winetest_push_context( "test_cases seq-like %d", (int)i );
350
test_BluetoothSdpGetElementData( test_cases[i].stream, test_cases[i].size,
351
test_cases[i].error, &test_cases[i].data );
352
if (test_cases[i].error != ERROR_SUCCESS)
353
{
354
winetest_pop_context();
355
continue;
356
}
357
358
while (n < test_cases[i].container_size)
359
{
360
SDP_ELEMENT_DATA container_elem = {0};
361
362
winetest_push_context( "test_cases[%d].sequence[%d]", (int)i, (int)n );
363
ret = BluetoothSdpGetContainerElementData( test_cases[i].data.data.sequence.value,
364
test_cases[i].data.data.sequence.length,
365
&handle, &container_elem );
366
if (ret == ERROR_NO_MORE_ITEMS)
367
{
368
ok( n == test_cases[i].container_size, "%d != %d.\n",
369
(int)test_cases[i].container_size, (int)n );
370
winetest_pop_context();
371
break;
372
}
373
ok( ret == ERROR_SUCCESS, "BluetoothSdpGetContainerElementData failed: %ld.\n", ret );
374
if (ret == ERROR_SUCCESS)
375
{
376
ok( !memcmp( &test_cases[i].sequence[n], &container_elem,
377
sizeof( container_elem ) ),
378
"%s != %s.\n", debugstr_SDP_ELEMENT_DATA( &test_cases[i].sequence[n] ),
379
debugstr_SDP_ELEMENT_DATA( &container_elem ) );
380
}
381
n++;
382
winetest_pop_context();
383
}
384
winetest_pop_context();
385
}
386
}
387
388
struct attr_callback_data
389
{
390
const ULONG *attrs_id;
391
const SDP_ELEMENT_DATA *attrs;
392
const SIZE_T attrs_n;
393
SIZE_T i;
394
};
395
396
static BYTE sdp_record_bytes[] = {
397
0x35, 0x48, 0x09, 0x00, 0x00, 0x0a, 0x00, 0x01, 0x00, 0x00, 0x09, 0x00, 0x01, 0x35, 0x03,
398
0x19, 0x12, 0x00, 0x09, 0x00, 0x05, 0x35, 0x03, 0x19, 0x10, 0x02, 0x09, 0x00, 0x09, 0x35,
399
0x08, 0x35, 0x06, 0x19, 0x12, 0x00, 0x09, 0x01, 0x03, 0x09, 0x02, 0x00, 0x09, 0x01, 0x03,
400
0x09, 0x02, 0x01, 0x09, 0x1d, 0x6b, 0x09, 0x02, 0x02, 0x09, 0x02, 0x46, 0x09, 0x02, 0x03,
401
0x09, 0x05, 0x4d, 0x09, 0x02, 0x04, 0x28, 0x01, 0x09, 0x02, 0x05, 0x09, 0x00, 0x02 };
402
403
static BOOL WINAPI enum_attr_callback( ULONG attr_id, BYTE *stream, ULONG stream_size, void *param )
404
{
405
struct attr_callback_data *params = param;
406
winetest_push_context( "attributes %d", (int)params->i );
407
if (params->i < params->attrs_n)
408
{
409
SDP_ELEMENT_DATA data = {0}, data2 = {0};
410
DWORD result;
411
412
ok( attr_id == params->attrs_id[params->i], "Expected attribute id %lu, got %lu.\n",
413
params->attrs_id[params->i], attr_id );
414
result = BluetoothSdpGetElementData( stream, stream_size, &data );
415
ok( result == ERROR_SUCCESS, "BluetoothSdpGetElementData failed: %ld.\n", result );
416
ok( !memcmp( &params->attrs[params->i], &data, sizeof( data ) ), "Expected %s, got %s.\n",
417
debugstr_SDP_ELEMENT_DATA( &params->attrs[params->i] ),
418
debugstr_SDP_ELEMENT_DATA( &data ) );
419
420
result = BluetoothSdpGetAttributeValue( sdp_record_bytes, ARRAY_SIZE( sdp_record_bytes ),
421
params->attrs_id[params->i], &data2 );
422
ok( result == ERROR_SUCCESS, "BluetoothSdpGetAttributeValue failed: %ld.\n", result );
423
ok( !memcmp( &params->attrs[params->i], &data2, sizeof( data2 ) ), "Expected %s, got %s.\n",
424
debugstr_SDP_ELEMENT_DATA( &params->attrs[params->i] ),
425
debugstr_SDP_ELEMENT_DATA( &data2 ) );
426
427
params->i++;
428
}
429
winetest_pop_context();
430
return TRUE;
431
}
432
433
static void test_BluetoothSdpEnumAttributes( void )
434
{
435
SDP_ELEMENT_DATA attributes[] = {
436
{SDP_TYPE_UINT, SDP_ST_UINT32, {.uint32 = 0x10000}},
437
{SDP_TYPE_SEQUENCE, SDP_ST_NONE, {.sequence = {&sdp_record_bytes[13], 5}}},
438
{SDP_TYPE_SEQUENCE, SDP_ST_NONE, {.sequence = {&sdp_record_bytes[21], 5}}},
439
{SDP_TYPE_SEQUENCE, SDP_ST_NONE, {.sequence = {&sdp_record_bytes[29], 10}}},
440
{SDP_TYPE_UINT, SDP_ST_UINT16, {.uint16 = 0x0103}},
441
{SDP_TYPE_UINT, SDP_ST_UINT16, {.uint16 = 0x1d6b}},
442
{SDP_TYPE_UINT, SDP_ST_UINT16, {.uint16 = 0x0246}},
443
{SDP_TYPE_UINT, SDP_ST_UINT16, {.uint16 = 0x054d}},
444
{SDP_TYPE_BOOLEAN, SDP_ST_NONE, {.booleanVal = 1}},
445
{SDP_TYPE_UINT, SDP_ST_UINT16, {.uint16 = 0x02}},
446
};
447
const ULONG attrs_id[] = {0x0, 0x1, 0x5, 0x9, 0x200, 0x201, 0x202, 0x203, 0x204, 0x205};
448
struct attr_callback_data data = {attrs_id, attributes, ARRAY_SIZE( attributes ), 0};
449
SDP_ELEMENT_DATA elem_data = {0};
450
DWORD result;
451
452
BOOL ret;
453
454
SetLastError( 0xdeadbeef );
455
ret = BluetoothSdpEnumAttributes( sdp_record_bytes, ARRAY_SIZE( sdp_record_bytes ), enum_attr_callback,
456
&data );
457
ok( ret, "BluetoothSdpEnumAttributes failed with %ld.\n", GetLastError() );
458
ok( data.i == data.attrs_n, "%d != %d\n", (int)data.i, (int)data.attrs_n );
459
460
result = BluetoothSdpGetAttributeValue( sdp_record_bytes, ARRAY_SIZE( sdp_record_bytes ), 0xff,
461
&elem_data );
462
ok( result == ERROR_FILE_NOT_FOUND, "%d != %ld.\n", ERROR_FILE_NOT_FOUND, result );
463
}
464
465
START_TEST( sdp )
466
{
467
test_BluetoothSdpGetElementData_nil();
468
test_BluetoothSdpGetElementData_ints();
469
test_BluetoothSdpGetElementData_invalid();
470
test_BluetoothSdpGetElementData_str();
471
test_BluetoothSdpGetContainerElementData();
472
test_BluetoothSdpEnumAttributes();
473
}
474
475