test-hfp.c 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853
  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. /*
  3. *
  4. * BlueZ - Bluetooth protocol stack for Linux
  5. *
  6. * Copyright (C) 2014 Intel Corporation. All rights reserved.
  7. *
  8. *
  9. */
  10. #include <sys/socket.h>
  11. #include <unistd.h>
  12. #include <stdint.h>
  13. #include <stdio.h>
  14. #include <string.h>
  15. #include <glib.h>
  16. #include "src/shared/hfp.h"
  17. #include "src/shared/tester.h"
  18. struct context {
  19. guint watch_id;
  20. int fd_server;
  21. int fd_client;
  22. struct hfp_gw *hfp;
  23. struct hfp_hf *hfp_hf;
  24. const struct test_data *data;
  25. unsigned int pdu_offset;
  26. };
  27. struct test_pdu {
  28. bool valid;
  29. uint8_t *data;
  30. size_t size;
  31. enum hfp_gw_cmd_type type;
  32. bool fragmented;
  33. };
  34. struct test_data {
  35. char *test_name;
  36. struct test_pdu *pdu_list;
  37. hfp_result_func_t result_func;
  38. hfp_response_func_t response_func;
  39. hfp_hf_result_func_t hf_result_func;
  40. GIOFunc test_handler;
  41. };
  42. #define data(args...) ((const unsigned char[]) { args })
  43. #define raw_pdu(args...) \
  44. { \
  45. .valid = true, \
  46. .data = g_memdup(data(args), sizeof(data(args))), \
  47. .size = sizeof(data(args)), \
  48. }
  49. #define data_end() \
  50. { \
  51. .valid = false, \
  52. }
  53. #define type_pdu(cmd_type, args...) \
  54. { \
  55. .valid = true, \
  56. .data = g_memdup(data(args), sizeof(data(args))), \
  57. .size = sizeof(data(args)), \
  58. .type = cmd_type, \
  59. }
  60. #define frg_pdu(args...) \
  61. { \
  62. .valid = true, \
  63. .data = g_memdup(data(args), sizeof(data(args))), \
  64. .size = sizeof(data(args)), \
  65. .fragmented = true, \
  66. }
  67. #define define_test(name, function, result_function, args...) \
  68. do { \
  69. const struct test_pdu pdus[] = { \
  70. args, { } \
  71. }; \
  72. static struct test_data data; \
  73. data.test_name = g_strdup(name); \
  74. data.pdu_list = g_memdup(pdus, sizeof(pdus)); \
  75. data.result_func = result_function; \
  76. tester_add(name, &data, NULL, function, NULL); \
  77. data.test_handler = test_handler; \
  78. } while (0)
  79. #define define_hf_test(name, function, result_func, response_function, \
  80. args...)\
  81. do { \
  82. const struct test_pdu pdus[] = { \
  83. args, { } \
  84. }; \
  85. static struct test_data data; \
  86. data.test_name = g_strdup(name); \
  87. data.pdu_list = g_memdup(pdus, sizeof(pdus)); \
  88. data.hf_result_func = result_func; \
  89. data.response_func = response_function; \
  90. tester_add(name, &data, NULL, function, NULL); \
  91. data.test_handler = test_hf_handler; \
  92. } while (0)
  93. static void test_free(gconstpointer user_data)
  94. {
  95. const struct test_data *data = user_data;
  96. struct test_pdu *pdu;
  97. int i;
  98. for (i = 0; (pdu = &data->pdu_list[i]) && pdu->valid; i++)
  99. g_free(pdu->data);
  100. g_free(data->test_name);
  101. g_free(data->pdu_list);
  102. }
  103. static void destroy_context(struct context *context)
  104. {
  105. if (context->watch_id)
  106. g_source_remove(context->watch_id);
  107. test_free(context->data);
  108. if (context->hfp)
  109. hfp_gw_unref(context->hfp);
  110. if (context->hfp_hf)
  111. hfp_hf_unref(context->hfp_hf);
  112. g_free(context);
  113. }
  114. static gboolean context_quit(gpointer user_data)
  115. {
  116. struct context *context = user_data;
  117. if (context == NULL)
  118. return FALSE;
  119. destroy_context(context);
  120. tester_test_passed();
  121. return FALSE;
  122. }
  123. static gboolean test_handler(GIOChannel *channel, GIOCondition cond,
  124. gpointer user_data)
  125. {
  126. struct context *context = user_data;
  127. const struct test_pdu *pdu;
  128. pdu = &context->data->pdu_list[context->pdu_offset++];
  129. g_assert(!pdu->valid);
  130. context->watch_id = 0;
  131. context_quit(context);
  132. return FALSE;
  133. }
  134. static gboolean send_pdu(gpointer user_data)
  135. {
  136. struct context *context = user_data;
  137. const struct test_pdu *pdu;
  138. ssize_t len;
  139. pdu = &context->data->pdu_list[context->pdu_offset++];
  140. if (!pdu || !pdu->valid)
  141. return FALSE;
  142. len = write(context->fd_server, pdu->data, pdu->size);
  143. g_assert_cmpint(len, ==, pdu->size);
  144. pdu = &context->data->pdu_list[context->pdu_offset];
  145. if (pdu->fragmented)
  146. g_idle_add(send_pdu, context);
  147. return FALSE;
  148. }
  149. static gboolean test_hf_handler(GIOChannel *channel, GIOCondition cond,
  150. gpointer user_data)
  151. {
  152. struct context *context = user_data;
  153. gchar buf[60];
  154. gsize bytes_read;
  155. GError *error = NULL;
  156. if (cond & (G_IO_HUP | G_IO_ERR | G_IO_NVAL))
  157. goto done;
  158. /* dummy read */
  159. g_io_channel_read_chars(channel, buf, 60, &bytes_read, &error);
  160. send_pdu(context);
  161. return TRUE;
  162. done:
  163. context->watch_id = 0;
  164. context_quit(context);
  165. return FALSE;
  166. }
  167. static void cmd_handler(const char *command, void *user_data)
  168. {
  169. struct context *context = user_data;
  170. const struct test_pdu *pdu;
  171. unsigned int cmd_len = strlen(command);
  172. pdu = &context->data->pdu_list[context->pdu_offset++];
  173. g_assert(cmd_len == pdu->size);
  174. g_assert(!memcmp(command, pdu->data, cmd_len));
  175. hfp_gw_send_result(context->hfp, HFP_RESULT_ERROR);
  176. }
  177. static void prefix_handler(struct hfp_context *result,
  178. enum hfp_gw_cmd_type type, void *user_data)
  179. {
  180. struct context *context = user_data;
  181. const struct test_pdu *pdu;
  182. pdu = &context->data->pdu_list[context->pdu_offset++];
  183. g_assert(type == pdu->type);
  184. hfp_gw_send_result(context->hfp, HFP_RESULT_ERROR);
  185. }
  186. static struct context *create_context(gconstpointer data)
  187. {
  188. struct context *context = g_new0(struct context, 1);
  189. GIOChannel *channel;
  190. int err, sv[2];
  191. const struct test_data *d = data;
  192. err = socketpair(AF_UNIX, SOCK_SEQPACKET | SOCK_CLOEXEC, 0, sv);
  193. g_assert(err == 0);
  194. channel = g_io_channel_unix_new(sv[1]);
  195. g_io_channel_set_close_on_unref(channel, TRUE);
  196. g_io_channel_set_encoding(channel, NULL, NULL);
  197. g_io_channel_set_buffered(channel, FALSE);
  198. context->watch_id = g_io_add_watch(channel,
  199. G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
  200. d->test_handler, context);
  201. g_assert(context->watch_id > 0);
  202. g_io_channel_unref(channel);
  203. context->fd_server = sv[1];
  204. context->fd_client = sv[0];
  205. context->data = data;
  206. return context;
  207. }
  208. static void test_init(gconstpointer data)
  209. {
  210. struct context *context = create_context(data);
  211. context->hfp = hfp_gw_new(context->fd_client);
  212. g_assert(context->hfp);
  213. g_assert(hfp_gw_set_close_on_unref(context->hfp, true));
  214. hfp_gw_unref(context->hfp);
  215. context->hfp = NULL;
  216. context_quit(context);
  217. }
  218. static void test_command_handler(gconstpointer data)
  219. {
  220. struct context *context = create_context(data);
  221. const struct test_pdu *pdu;
  222. ssize_t len;
  223. bool ret;
  224. context->hfp = hfp_gw_new(context->fd_client);
  225. g_assert(context->hfp);
  226. pdu = &context->data->pdu_list[context->pdu_offset++];
  227. ret = hfp_gw_set_close_on_unref(context->hfp, true);
  228. g_assert(ret);
  229. ret = hfp_gw_set_command_handler(context->hfp, cmd_handler,
  230. context, NULL);
  231. g_assert(ret);
  232. len = write(context->fd_server, pdu->data, pdu->size);
  233. g_assert_cmpint(len, ==, pdu->size);
  234. context_quit(context);
  235. }
  236. static void test_register(gconstpointer data)
  237. {
  238. struct context *context = create_context(data);
  239. const struct test_pdu *pdu;
  240. ssize_t len;
  241. bool ret;
  242. context->hfp = hfp_gw_new(context->fd_client);
  243. g_assert(context->hfp);
  244. pdu = &context->data->pdu_list[context->pdu_offset++];
  245. ret = hfp_gw_set_close_on_unref(context->hfp, true);
  246. g_assert(ret);
  247. if (context->data->result_func) {
  248. ret = hfp_gw_register(context->hfp, context->data->result_func,
  249. (char *)pdu->data, context, NULL);
  250. g_assert(ret);
  251. }
  252. pdu = &context->data->pdu_list[context->pdu_offset++];
  253. len = write(context->fd_server, pdu->data, pdu->size);
  254. g_assert_cmpint(len, ==, pdu->size);
  255. context_quit(context);
  256. }
  257. static void test_fragmented(gconstpointer data)
  258. {
  259. struct context *context = create_context(data);
  260. bool ret;
  261. context->hfp = hfp_gw_new(context->fd_client);
  262. g_assert(context->hfp);
  263. ret = hfp_gw_set_close_on_unref(context->hfp, true);
  264. g_assert(ret);
  265. g_idle_add(send_pdu, context);
  266. }
  267. static void test_send_and_close(gconstpointer data)
  268. {
  269. struct context *context = create_context(data);
  270. bool ret;
  271. context->hfp = hfp_gw_new(context->fd_client);
  272. g_assert(context->hfp);
  273. ret = hfp_gw_set_close_on_unref(context->hfp, true);
  274. g_assert(ret);
  275. send_pdu(context);
  276. hfp_gw_unref(context->hfp);
  277. context->hfp = NULL;
  278. context_quit(context);
  279. }
  280. static void check_ustring_1(struct hfp_context *result,
  281. enum hfp_gw_cmd_type type, void *user_data)
  282. {
  283. struct context *context = user_data;
  284. const struct test_pdu *pdu;
  285. unsigned int i = 3, j = 0;
  286. char str[10];
  287. pdu = &context->data->pdu_list[context->pdu_offset++];
  288. g_assert(type == pdu->type);
  289. g_assert(hfp_context_get_unquoted_string(result, str, sizeof(str)));
  290. while (context->data->pdu_list[1].data[i] != '\r') {
  291. g_assert(j < sizeof(str));
  292. g_assert(str[j] == context->data->pdu_list[1].data[i]);
  293. i++;
  294. j++;
  295. }
  296. g_assert(str[j] == '\0');
  297. hfp_gw_send_result(context->hfp, HFP_RESULT_ERROR);
  298. }
  299. static void check_ustring_2(struct hfp_context *result,
  300. enum hfp_gw_cmd_type type, void *user_data)
  301. {
  302. struct context *context = user_data;
  303. const struct test_pdu *pdu;
  304. char str[10];
  305. memset(str, 'X', sizeof(str));
  306. pdu = &context->data->pdu_list[context->pdu_offset++];
  307. g_assert(type == pdu->type);
  308. g_assert(!hfp_context_get_unquoted_string(result, str, 3));
  309. g_assert(str[3] == 'X');
  310. hfp_gw_send_result(context->hfp, HFP_RESULT_ERROR);
  311. }
  312. static void check_string_1(struct hfp_context *result,
  313. enum hfp_gw_cmd_type type, void *user_data)
  314. {
  315. struct context *context = user_data;
  316. const struct test_pdu *pdu;
  317. unsigned int i = 4, j = 0;
  318. char str[10];
  319. pdu = &context->data->pdu_list[context->pdu_offset++];
  320. g_assert(type == pdu->type);
  321. g_assert(hfp_context_get_string(result, str, sizeof(str)));
  322. while (context->data->pdu_list[1].data[i] != '\"') {
  323. g_assert(j < sizeof(str));
  324. g_assert(str[j] == context->data->pdu_list[1].data[i]);
  325. i++;
  326. j++;
  327. }
  328. g_assert(context->data->pdu_list[1].data[i] == '\"');
  329. g_assert(str[j] == '\0');
  330. hfp_gw_send_result(context->hfp, HFP_RESULT_ERROR);
  331. }
  332. static void check_string_2(struct hfp_context *result,
  333. enum hfp_gw_cmd_type type, void *user_data)
  334. {
  335. struct context *context = user_data;
  336. const struct test_pdu *pdu;
  337. char str[10];
  338. memset(str, 'X', sizeof(str));
  339. pdu = &context->data->pdu_list[context->pdu_offset++];
  340. g_assert(type == pdu->type);
  341. g_assert(!hfp_context_get_string(result, str, 3));
  342. g_assert(str[3] == 'X');
  343. hfp_gw_send_result(context->hfp, HFP_RESULT_ERROR);
  344. }
  345. static void check_string_3(struct hfp_context *result,
  346. enum hfp_gw_cmd_type type, void *user_data)
  347. {
  348. struct context *context = user_data;
  349. const struct test_pdu *pdu;
  350. pdu = &context->data->pdu_list[context->pdu_offset++];
  351. g_assert(type == pdu->type);
  352. hfp_gw_send_result(context->hfp, HFP_RESULT_ERROR);
  353. }
  354. static void test_hf_init(gconstpointer data)
  355. {
  356. struct context *context = create_context(data);
  357. context->hfp_hf = hfp_hf_new(context->fd_client);
  358. g_assert(context->hfp_hf);
  359. g_assert(hfp_hf_set_close_on_unref(context->hfp_hf, true));
  360. hfp_hf_unref(context->hfp_hf);
  361. context->hfp_hf = NULL;
  362. context_quit(context);
  363. }
  364. static bool unsolicited_resp = false;
  365. static void hf_unsolicited_resp_cb(struct hfp_context *context,
  366. void *user_data) {
  367. unsolicited_resp = true;
  368. }
  369. static void hf_response_with_data(enum hfp_result res,
  370. enum hfp_error cme_err,
  371. void *user_data)
  372. {
  373. struct context *context = user_data;
  374. g_assert(unsolicited_resp);
  375. unsolicited_resp = false;
  376. hfp_hf_disconnect(context->hfp_hf);
  377. }
  378. static void hf_cme_error_response_cb(enum hfp_result res,
  379. enum hfp_error cme_err,
  380. void *user_data)
  381. {
  382. struct context *context = user_data;
  383. g_assert_cmpint(res, ==, HFP_RESULT_CME_ERROR);
  384. g_assert_cmpint(cme_err, ==, 30);
  385. hfp_hf_disconnect(context->hfp_hf);
  386. }
  387. static void hf_response_cb(enum hfp_result res, enum hfp_error cme_err,
  388. void *user_data)
  389. {
  390. struct context *context = user_data;
  391. hfp_hf_disconnect(context->hfp_hf);
  392. }
  393. static void test_hf_send_command(gconstpointer data)
  394. {
  395. struct context *context = create_context(data);
  396. const struct test_pdu *pdu;
  397. bool ret;
  398. context->hfp_hf = hfp_hf_new(context->fd_client);
  399. g_assert(context->hfp_hf);
  400. ret = hfp_hf_set_close_on_unref(context->hfp_hf, true);
  401. g_assert(ret);
  402. if (context->data->response_func) {
  403. if (context->data->hf_result_func) {
  404. pdu = &context->data->pdu_list[context->pdu_offset++];
  405. ret = hfp_hf_register(context->hfp_hf,
  406. context->data->hf_result_func,
  407. (char *)pdu->data,
  408. NULL, NULL);
  409. g_assert(ret);
  410. }
  411. pdu = &context->data->pdu_list[context->pdu_offset++];
  412. ret = hfp_hf_send_command(context->hfp_hf,
  413. context->data->response_func,
  414. context, (char *)pdu->data);
  415. g_assert(ret);
  416. }
  417. context_quit(context);
  418. }
  419. static void hf_chld_result_handler(struct hfp_context *hf_context,
  420. void *user_data)
  421. {
  422. struct context *context = user_data;
  423. char str[3];
  424. g_assert(hf_context);
  425. g_assert(hfp_context_get_unquoted_string(hf_context, str,
  426. sizeof(str)));
  427. g_assert_cmpstr(str, ==, "1");
  428. g_assert(hfp_context_get_unquoted_string(hf_context, str,
  429. sizeof(str)));
  430. g_assert_cmpstr(str, ==, "2x");
  431. hfp_hf_disconnect(context->hfp_hf);
  432. }
  433. static void hf_chld_skip_field(struct hfp_context *hf_context,
  434. void *user_data)
  435. {
  436. struct context *context = user_data;
  437. char str[3];
  438. g_assert(hf_context);
  439. hfp_context_skip_field(hf_context);
  440. g_assert(hfp_context_get_unquoted_string(hf_context, str,
  441. sizeof(str)));
  442. g_assert_cmpstr(str, ==, "2x");
  443. hfp_hf_disconnect(context->hfp_hf);
  444. }
  445. static void hf_clcc_result_handler(struct hfp_context *hf_context,
  446. void *user_data)
  447. {
  448. struct context *context = user_data;
  449. char name[10];
  450. uint32_t val1, val2;
  451. g_assert(hf_context);
  452. g_assert(hfp_context_open_container(hf_context));
  453. g_assert(hfp_context_get_string(hf_context, name, sizeof(name)));
  454. g_assert_cmpstr(name, ==, "call");
  455. g_assert(hfp_context_open_container(hf_context));
  456. g_assert(hfp_context_get_number(hf_context, &val1));
  457. g_assert_cmpint(val1, ==, 0);
  458. g_assert(hfp_context_get_number(hf_context, &val1));
  459. g_assert_cmpint(val1, ==, 1);
  460. g_assert(hfp_context_close_container(hf_context));
  461. g_assert(hfp_context_close_container(hf_context));
  462. g_assert(hfp_context_open_container(hf_context));
  463. g_assert(hfp_context_get_string(hf_context, name, sizeof(name)));
  464. g_assert_cmpstr(name, ==, "callsetup");
  465. g_assert(hfp_context_open_container(hf_context));
  466. g_assert(hfp_context_get_range(hf_context, &val1, &val2));
  467. g_assert_cmpint(val1, ==, 0);
  468. g_assert_cmpint(val2, ==, 3);
  469. g_assert(hfp_context_close_container(hf_context));
  470. g_assert(hfp_context_close_container(hf_context));
  471. hfp_hf_disconnect(context->hfp_hf);
  472. }
  473. static void hf_result_handler(struct hfp_context *result,
  474. void *user_data)
  475. {
  476. struct context *context = user_data;
  477. hfp_hf_disconnect(context->hfp_hf);
  478. }
  479. static void test_hf_unsolicited(gconstpointer data)
  480. {
  481. struct context *context = create_context(data);
  482. bool ret;
  483. context->hfp_hf = hfp_hf_new(context->fd_client);
  484. g_assert(context->hfp_hf);
  485. ret = hfp_hf_set_close_on_unref(context->hfp_hf, true);
  486. g_assert(ret);
  487. if (context->data->hf_result_func) {
  488. const struct test_pdu *pdu;
  489. pdu = &context->data->pdu_list[context->pdu_offset++];
  490. ret = hfp_hf_register(context->hfp_hf,
  491. context->data->hf_result_func,
  492. (char *)pdu->data, context,
  493. NULL);
  494. g_assert(ret);
  495. }
  496. send_pdu(context);
  497. }
  498. static void test_hf_robustness(gconstpointer data)
  499. {
  500. struct context *context = create_context(data);
  501. bool ret;
  502. context->hfp_hf = hfp_hf_new(context->fd_client);
  503. g_assert(context->hfp_hf);
  504. ret = hfp_hf_set_close_on_unref(context->hfp_hf, true);
  505. g_assert(ret);
  506. send_pdu(context);
  507. hfp_hf_unref(context->hfp_hf);
  508. context->hfp_hf = NULL;
  509. context_quit(context);
  510. }
  511. int main(int argc, char *argv[])
  512. {
  513. tester_init(&argc, &argv);
  514. define_test("/hfp/test_init", test_init, NULL, data_end());
  515. define_test("/hfp/test_cmd_handler_1", test_command_handler, NULL,
  516. raw_pdu('A', 'T', '+', 'B', 'R', 'S', 'F', '\r'),
  517. raw_pdu('A', 'T', '+', 'B', 'R', 'S', 'F'),
  518. data_end());
  519. define_test("/hfp/test_cmd_handler_2", test_command_handler, NULL,
  520. raw_pdu('A', 'T', 'D', '1', '2', '3', '4', '\r'),
  521. raw_pdu('A', 'T', 'D', '1', '2', '3', '4'),
  522. data_end());
  523. define_test("/hfp/test_register_1", test_register, prefix_handler,
  524. raw_pdu('+', 'B', 'R', 'S', 'F', '\0'),
  525. raw_pdu('A', 'T', '+', 'B', 'R', 'S', 'F', '\r'),
  526. type_pdu(HFP_GW_CMD_TYPE_COMMAND, 0),
  527. data_end());
  528. define_test("/hfp/test_register_2", test_register, prefix_handler,
  529. raw_pdu('+', 'B', 'R', 'S', 'F', '\0'),
  530. raw_pdu('A', 'T', '+', 'B', 'R', 'S', 'F', '=', '\r'),
  531. type_pdu(HFP_GW_CMD_TYPE_SET, 0),
  532. data_end());
  533. define_test("/hfp/test_register_3", test_register, prefix_handler,
  534. raw_pdu('+', 'B', 'R', 'S', 'F', '\0'),
  535. raw_pdu('A', 'T', '+', 'B', 'R', 'S', 'F', '?', '\r'),
  536. type_pdu(HFP_GW_CMD_TYPE_READ, 0),
  537. data_end());
  538. define_test("/hfp/test_register_4", test_register, prefix_handler,
  539. raw_pdu('+', 'B', 'R', 'S', 'F', '\0'),
  540. raw_pdu('A', 'T', '+', 'B', 'R', 'S', 'F', '=', '?',
  541. '\r'),
  542. type_pdu(HFP_GW_CMD_TYPE_TEST, 0),
  543. data_end());
  544. define_test("/hfp/test_register_5", test_register, prefix_handler,
  545. raw_pdu('D', '\0'),
  546. raw_pdu('A', 'T', 'D', '1', '2', '3', '4', '5', '\r'),
  547. type_pdu(HFP_GW_CMD_TYPE_SET, 0),
  548. data_end());
  549. define_test("/hfp/test_fragmented_1", test_fragmented, NULL,
  550. frg_pdu('A'), frg_pdu('T'), frg_pdu('+'), frg_pdu('B'),
  551. frg_pdu('R'), frg_pdu('S'), frg_pdu('F'), frg_pdu('\r'),
  552. data_end());
  553. define_test("/hfp/test_ustring_1", test_register, check_ustring_1,
  554. raw_pdu('D', '\0'),
  555. raw_pdu('A', 'T', 'D', '0', '1', '2', '3', '\r'),
  556. type_pdu(HFP_GW_CMD_TYPE_SET, 0),
  557. data_end());
  558. define_test("/hfp/test_ustring_2", test_register, check_ustring_2,
  559. raw_pdu('D', '\0'),
  560. raw_pdu('A', 'T', 'D', '0', '1', '2', '3', '\r'),
  561. type_pdu(HFP_GW_CMD_TYPE_SET, 0),
  562. data_end());
  563. define_test("/hfp/test_string_1", test_register, check_string_1,
  564. raw_pdu('D', '\0'),
  565. raw_pdu('A', 'T', 'D', '\"', '0', '1', '2', '3', '\"',
  566. '\r'),
  567. type_pdu(HFP_GW_CMD_TYPE_SET, 0),
  568. data_end());
  569. define_test("/hfp/test_string_2", test_register, check_string_2,
  570. raw_pdu('D', '\0'),
  571. raw_pdu('A', 'T', 'D', '\"', '0', '1', '2', '3', '\"',
  572. '\r'),
  573. type_pdu(HFP_GW_CMD_TYPE_SET, 0),
  574. data_end());
  575. define_test("/hfp/test_corrupted_1", test_register, check_string_3,
  576. raw_pdu('D', '\0'),
  577. raw_pdu('\r', 'A', 'T', 'D', '\"', '0', '1', '2', '3',
  578. '\"', '\r'),
  579. type_pdu(HFP_GW_CMD_TYPE_SET, 0),
  580. data_end());
  581. define_test("/hfp/test_empty", test_send_and_close, NULL,
  582. raw_pdu('\r'),
  583. data_end());
  584. define_hf_test("/hfp_hf/test_init", test_hf_init, NULL, NULL,
  585. data_end());
  586. define_hf_test("/hfp_hf/test_send_command_1", test_hf_send_command,
  587. NULL, hf_response_cb,
  588. raw_pdu('A', 'T', '+', 'B', 'R', 'S', 'F', '\0'),
  589. raw_pdu('\r', '\n', 'O', 'k', '\r', '\n'),
  590. data_end());
  591. define_hf_test("/hfp_hf/test_send_command_2", test_hf_send_command,
  592. hf_unsolicited_resp_cb,
  593. hf_response_with_data,
  594. raw_pdu('+', 'B', 'R', 'S', 'F', '\0'),
  595. raw_pdu('A', 'T', '+', 'B', 'R', 'S', 'F', '\0'),
  596. frg_pdu('\r', '\n', '+', 'B', 'R', 'S', 'F', '\r',
  597. '\n'),
  598. frg_pdu('\r', '\n', 'O', 'k', '\r', '\n'),
  599. data_end());
  600. define_hf_test("/hfp_hf/test_send_command_3", test_hf_send_command,
  601. NULL, hf_cme_error_response_cb,
  602. raw_pdu('A', 'T', '+', 'C', 'H', 'L', 'D', '=',
  603. '1', '\0'),
  604. frg_pdu('\r', '\n', '+', 'C', 'M', 'E', ' ', 'E'),
  605. frg_pdu('R', 'R', 'O', 'R', ':', '3', '0', '\r', '\n'),
  606. data_end());
  607. define_hf_test("/hfp_hf/test_unsolicited_1", test_hf_unsolicited,
  608. hf_result_handler, NULL,
  609. raw_pdu('+', 'C', 'L', 'C', 'C', '\0'),
  610. frg_pdu('\r', '\n', '+', 'C', 'L', 'C'),
  611. frg_pdu('C', '\r', '\n'),
  612. data_end());
  613. define_hf_test("/hfp_hf/test_unsolicited_2", test_hf_unsolicited,
  614. hf_result_handler, NULL,
  615. raw_pdu('+', 'C', 'L', 'C', 'C', '\0'),
  616. frg_pdu('\r', '\n', '+', 'C', 'L', 'C', 'C', ':', '1'),
  617. frg_pdu(',', '3', ',', '0', '\r', '\n'),
  618. data_end());
  619. define_hf_test("/hfp_hf/test_unsolicited_3", test_hf_unsolicited,
  620. hf_result_handler, NULL,
  621. raw_pdu('+', 'C', 'L', 'C', 'C', '\0'),
  622. frg_pdu('\r'), frg_pdu('\n'), frg_pdu('+'),
  623. frg_pdu('C'), frg_pdu('L'), frg_pdu('C'), frg_pdu('C'),
  624. frg_pdu(':'), frg_pdu('1'), frg_pdu(','), frg_pdu('3'),
  625. frg_pdu(','), frg_pdu('0'), frg_pdu('\r'),
  626. frg_pdu('\n'),
  627. data_end());
  628. define_hf_test("/hfp_hf/test_corrupted_1", test_hf_unsolicited,
  629. hf_result_handler, NULL,
  630. raw_pdu('+', 'C', 'L', 'C', 'C', '\0'),
  631. frg_pdu('\r', 'X', '\r', '\n'),
  632. frg_pdu('+', 'C', 'L', 'C', 'C', ':', '1', ',', '3'),
  633. frg_pdu(',', '0', '\r', '\n'),
  634. data_end());
  635. define_hf_test("/hfp_hf/test_corrupted_2", test_hf_unsolicited,
  636. hf_result_handler, NULL,
  637. raw_pdu('+', 'C', 'L', 'C', 'C', '\0'),
  638. raw_pdu('+', 'C', 'L', 'C', 'C', '\r', '\n'),
  639. data_end());
  640. define_hf_test("/hfp_hf/test_empty", test_hf_robustness, NULL, NULL,
  641. raw_pdu('\r'), data_end());
  642. define_hf_test("/hfp_hf/test_unknown", test_hf_robustness, NULL, NULL,
  643. raw_pdu('\r', '\n', 'B', 'R', '\r', '\n'),
  644. data_end());
  645. define_hf_test("/hfp_hf/test_context_parser_1", test_hf_unsolicited,
  646. hf_clcc_result_handler, NULL,
  647. raw_pdu('+', 'C', 'L', 'C', 'C', '\0'),
  648. frg_pdu('+', 'C', 'L', 'C', 'C', ':'),
  649. frg_pdu('(', '\"', 'c', 'a', 'l', 'l', '\"'),
  650. frg_pdu('(', '0', ',', '1', ')', ')', ','),
  651. frg_pdu('(', '\"', 'c', 'a', 'l', 'l', 's', 'e', 't'),
  652. frg_pdu('u', 'p', '\"', ',', '(', '0', '-', '3', ')'),
  653. frg_pdu(')', '\r', '\n'),
  654. data_end());
  655. define_hf_test("/hfp_hf/test_context_parser_2", test_hf_unsolicited,
  656. hf_chld_result_handler, NULL,
  657. raw_pdu('+', 'C', 'H', 'L', 'D', '\0'),
  658. frg_pdu('+', 'C', 'H', 'L', 'D', ':'),
  659. frg_pdu('1', ',', '2', 'x', '\r', '\n'),
  660. data_end());
  661. define_hf_test("/hfp_hf/test_context_skip_field", test_hf_unsolicited,
  662. hf_chld_skip_field, NULL,
  663. raw_pdu('+', 'C', 'H', 'L', 'D', '\0'),
  664. frg_pdu('+', 'C', 'H', 'L', 'D', ':'),
  665. frg_pdu('1', ',', '2', 'x', '\r', '\n'),
  666. data_end());
  667. return tester_run();
  668. }