test-gdbus-client.c 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952
  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. /*
  3. *
  4. * BlueZ - Bluetooth protocol stack for Linux
  5. *
  6. * Copyright (C) 2011 Intel Corporation
  7. *
  8. *
  9. */
  10. #ifdef HAVE_CONFIG_H
  11. #include <config.h>
  12. #endif
  13. #include <glib.h>
  14. #include "gdbus/gdbus.h"
  15. #include "src/shared/tester.h"
  16. #define SERVICE_NAME "org.bluez.unit.test_gdbus_client"
  17. #define SERVICE_NAME1 "org.bluez.unit.test_gdbus_client1"
  18. #define SERVICE_PATH "/org/bluez/unit/test_gdbus_client"
  19. struct context {
  20. DBusConnection *dbus_conn;
  21. GDBusClient *dbus_client;
  22. GDBusProxy *proxy;
  23. void *data;
  24. gboolean client_ready;
  25. guint timeout_source;
  26. };
  27. static const GDBusMethodTable methods[] = {
  28. { }
  29. };
  30. static const GDBusSignalTable signals[] = {
  31. { }
  32. };
  33. static const GDBusPropertyTable properties[] = {
  34. { }
  35. };
  36. static struct context *create_context(void)
  37. {
  38. struct context *context = g_new0(struct context, 1);
  39. DBusError err;
  40. dbus_error_init(&err);
  41. context->dbus_conn = g_dbus_setup_private(DBUS_BUS_SESSION,
  42. SERVICE_NAME, &err);
  43. if (context->dbus_conn == NULL) {
  44. if (dbus_error_is_set(&err)) {
  45. tester_debug("D-Bus setup failed: %s", err.message);
  46. dbus_error_free(&err);
  47. }
  48. g_free(context);
  49. tester_test_abort();
  50. return NULL;
  51. }
  52. /* Avoid D-Bus library calling _exit() before next test finishes. */
  53. dbus_connection_set_exit_on_disconnect(context->dbus_conn, FALSE);
  54. g_dbus_attach_object_manager(context->dbus_conn);
  55. context->client_ready = FALSE;
  56. return context;
  57. }
  58. static void destroy_context(struct context *context)
  59. {
  60. if (context == NULL)
  61. return;
  62. tester_test_passed();
  63. if (context->timeout_source > 0)
  64. g_source_remove(context->timeout_source);
  65. g_dbus_detach_object_manager(context->dbus_conn);
  66. g_dbus_unregister_interface(context->dbus_conn,
  67. SERVICE_PATH, SERVICE_NAME);
  68. dbus_connection_flush(context->dbus_conn);
  69. dbus_connection_close(context->dbus_conn);
  70. dbus_connection_unref(context->dbus_conn);
  71. g_free(context->data);
  72. g_free(context);
  73. }
  74. static gboolean timeout_handler(gpointer user_data)
  75. {
  76. struct context *context = user_data;
  77. tester_debug("timeout triggered");
  78. context->timeout_source = 0;
  79. g_dbus_client_unref(context->dbus_client);
  80. return FALSE;
  81. }
  82. static void connect_handler(DBusConnection *connection, void *user_data)
  83. {
  84. struct context *context = user_data;
  85. tester_debug("service connected");
  86. g_dbus_client_unref(context->dbus_client);
  87. }
  88. static void disconnect_handler(DBusConnection *connection, void *user_data)
  89. {
  90. struct context *context = user_data;
  91. tester_debug("service disconnected");
  92. destroy_context(context);
  93. }
  94. static void simple_client(const void *data)
  95. {
  96. struct context *context = create_context();
  97. if (context == NULL)
  98. return;
  99. context->dbus_client = g_dbus_client_new(context->dbus_conn,
  100. SERVICE_NAME, SERVICE_PATH);
  101. g_dbus_client_set_connect_watch(context->dbus_client,
  102. connect_handler, context);
  103. g_dbus_client_set_disconnect_watch(context->dbus_client,
  104. disconnect_handler, context);
  105. }
  106. static void client_connect_disconnect(const void *data)
  107. {
  108. struct context *context = create_context();
  109. if (context == NULL)
  110. return;
  111. g_dbus_register_interface(context->dbus_conn,
  112. SERVICE_PATH, SERVICE_NAME,
  113. methods, signals, properties, NULL, NULL);
  114. context->dbus_client = g_dbus_client_new(context->dbus_conn,
  115. SERVICE_NAME, SERVICE_PATH);
  116. g_dbus_client_set_connect_watch(context->dbus_client,
  117. connect_handler, context);
  118. g_dbus_client_set_disconnect_watch(context->dbus_client,
  119. disconnect_handler, context);
  120. context->timeout_source = g_timeout_add_seconds(10, timeout_handler,
  121. context);
  122. }
  123. static gboolean get_dict(const GDBusPropertyTable *property,
  124. DBusMessageIter *iter, void *data)
  125. {
  126. DBusMessageIter dict;
  127. const char *string = "value";
  128. dbus_bool_t boolean = TRUE;
  129. dbus_message_iter_open_container(iter, DBUS_TYPE_ARRAY,
  130. DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
  131. DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING
  132. DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict);
  133. g_dbus_dict_append_entry(&dict, "String", DBUS_TYPE_STRING, &string);
  134. g_dbus_dict_append_entry(&dict, "Boolean",
  135. DBUS_TYPE_BOOLEAN, &boolean);
  136. dbus_message_iter_close_container(iter, &dict);
  137. return TRUE;
  138. }
  139. static void proxy_get_dict(GDBusProxy *proxy, void *user_data)
  140. {
  141. struct context *context = user_data;
  142. DBusMessageIter iter, dict, var1, var2, entry1, entry2;
  143. const char *string;
  144. dbus_bool_t boolean;
  145. tester_debug("proxy %s found", g_dbus_proxy_get_interface(proxy));
  146. g_assert(g_dbus_proxy_get_property(proxy, "Dict", &iter));
  147. g_assert(dbus_message_iter_get_arg_type(&iter) == DBUS_TYPE_ARRAY);
  148. dbus_message_iter_recurse(&iter, &dict);
  149. g_assert(dbus_message_iter_get_arg_type(&dict) ==
  150. DBUS_TYPE_DICT_ENTRY);
  151. dbus_message_iter_recurse(&dict, &entry1);
  152. g_assert(dbus_message_iter_get_arg_type(&entry1) == DBUS_TYPE_STRING);
  153. dbus_message_iter_get_basic(&entry1, &string);
  154. g_assert(g_strcmp0(string, "String") == 0);
  155. dbus_message_iter_next(&entry1);
  156. g_assert(dbus_message_iter_get_arg_type(&entry1) == DBUS_TYPE_VARIANT);
  157. dbus_message_iter_recurse(&entry1, &var1);
  158. g_assert(dbus_message_iter_get_arg_type(&var1) == DBUS_TYPE_STRING);
  159. dbus_message_iter_get_basic(&var1, &string);
  160. g_assert(g_strcmp0(string, "value") == 0);
  161. dbus_message_iter_next(&dict);
  162. g_assert(dbus_message_iter_get_arg_type(&dict) ==
  163. DBUS_TYPE_DICT_ENTRY);
  164. dbus_message_iter_recurse(&dict, &entry2);
  165. g_assert(dbus_message_iter_get_arg_type(&entry2) == DBUS_TYPE_STRING);
  166. dbus_message_iter_get_basic(&entry2, &string);
  167. g_assert(g_strcmp0(string, "Boolean") == 0);
  168. dbus_message_iter_next(&entry2);
  169. g_assert(dbus_message_iter_get_arg_type(&entry2) == DBUS_TYPE_VARIANT);
  170. dbus_message_iter_recurse(&entry2, &var2);
  171. g_assert(dbus_message_iter_get_arg_type(&var2) == DBUS_TYPE_BOOLEAN);
  172. dbus_message_iter_get_basic(&var2, &boolean);
  173. g_assert(boolean == TRUE);
  174. dbus_message_iter_next(&dict);
  175. g_assert(dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_INVALID);
  176. g_dbus_client_unref(context->dbus_client);
  177. }
  178. static void client_get_dict_property(const void *data)
  179. {
  180. struct context *context = create_context();
  181. static const GDBusPropertyTable dict_properties[] = {
  182. { "Dict", "a{sv}", get_dict },
  183. { },
  184. };
  185. if (context == NULL)
  186. return;
  187. g_dbus_register_interface(context->dbus_conn,
  188. SERVICE_PATH, SERVICE_NAME,
  189. methods, signals, dict_properties,
  190. NULL, NULL);
  191. context->dbus_client = g_dbus_client_new(context->dbus_conn,
  192. SERVICE_NAME, SERVICE_PATH);
  193. g_dbus_client_set_disconnect_watch(context->dbus_client,
  194. disconnect_handler, context);
  195. g_dbus_client_set_proxy_handlers(context->dbus_client, proxy_get_dict,
  196. NULL, NULL, context);
  197. }
  198. static void proxy_get_string(GDBusProxy *proxy, void *user_data)
  199. {
  200. struct context *context = user_data;
  201. DBusMessageIter iter;
  202. const char *string;
  203. tester_debug("proxy %s found", g_dbus_proxy_get_interface(proxy));
  204. g_assert(g_dbus_proxy_get_property(proxy, "String", &iter));
  205. g_assert(dbus_message_iter_get_arg_type(&iter) == DBUS_TYPE_STRING);
  206. if (context->proxy) {
  207. g_assert(context->proxy == proxy);
  208. g_dbus_proxy_unref(context->proxy);
  209. }
  210. dbus_message_iter_get_basic(&iter, &string);
  211. g_assert_cmpstr(string, ==, "value");
  212. g_dbus_client_unref(context->dbus_client);
  213. }
  214. static gboolean get_string(const GDBusPropertyTable *property,
  215. DBusMessageIter *iter, void *data)
  216. {
  217. struct context *context = data;
  218. dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &context->data);
  219. return TRUE;
  220. }
  221. static void client_get_string_property(const void *data)
  222. {
  223. struct context *context = create_context();
  224. static const GDBusPropertyTable string_properties[] = {
  225. { "String", "s", get_string },
  226. { },
  227. };
  228. if (context == NULL)
  229. return;
  230. context->data = g_strdup("value");
  231. g_dbus_register_interface(context->dbus_conn,
  232. SERVICE_PATH, SERVICE_NAME,
  233. methods, signals, string_properties,
  234. context, NULL);
  235. context->dbus_client = g_dbus_client_new(context->dbus_conn,
  236. SERVICE_NAME, SERVICE_PATH);
  237. g_dbus_client_set_disconnect_watch(context->dbus_client,
  238. disconnect_handler, context);
  239. g_dbus_client_set_proxy_handlers(context->dbus_client, proxy_get_string,
  240. NULL, NULL, context);
  241. }
  242. static void proxy_get_boolean(GDBusProxy *proxy, void *user_data)
  243. {
  244. struct context *context = user_data;
  245. DBusMessageIter iter;
  246. dbus_bool_t value;
  247. tester_debug("proxy %s found", g_dbus_proxy_get_interface(proxy));
  248. g_assert(g_dbus_proxy_get_property(proxy, "Boolean", &iter));
  249. g_assert(dbus_message_iter_get_arg_type(&iter) == DBUS_TYPE_BOOLEAN);
  250. dbus_message_iter_get_basic(&iter, &value);
  251. g_assert(value == TRUE);
  252. g_dbus_client_unref(context->dbus_client);
  253. }
  254. static gboolean get_boolean(const GDBusPropertyTable *property,
  255. DBusMessageIter *iter, void *data)
  256. {
  257. dbus_bool_t value = TRUE;
  258. dbus_message_iter_append_basic(iter, DBUS_TYPE_BOOLEAN, &value);
  259. return TRUE;
  260. }
  261. static void client_get_boolean_property(const void *data)
  262. {
  263. struct context *context = create_context();
  264. static const GDBusPropertyTable boolean_properties[] = {
  265. { "Boolean", "b", get_boolean },
  266. { },
  267. };
  268. if (context == NULL)
  269. return;
  270. g_dbus_register_interface(context->dbus_conn,
  271. SERVICE_PATH, SERVICE_NAME,
  272. methods, signals, boolean_properties,
  273. NULL, NULL);
  274. context->dbus_client = g_dbus_client_new(context->dbus_conn,
  275. SERVICE_NAME, SERVICE_PATH);
  276. g_dbus_client_set_proxy_handlers(context->dbus_client,
  277. proxy_get_boolean,
  278. NULL, NULL, context);
  279. g_dbus_client_set_disconnect_watch(context->dbus_client,
  280. disconnect_handler, context);
  281. }
  282. static void proxy_get_array(GDBusProxy *proxy, void *user_data)
  283. {
  284. struct context *context = user_data;
  285. DBusMessageIter iter, entry;
  286. const char *value1, *value2;
  287. tester_debug("proxy %s found", g_dbus_proxy_get_interface(proxy));
  288. g_assert(g_dbus_proxy_get_property(proxy, "Array", &iter));
  289. g_assert(dbus_message_iter_get_arg_type(&iter) == DBUS_TYPE_ARRAY);
  290. dbus_message_iter_recurse(&iter, &entry);
  291. g_assert(dbus_message_iter_get_arg_type(&entry) == DBUS_TYPE_STRING);
  292. dbus_message_iter_get_basic(&entry, &value1);
  293. g_assert(g_strcmp0(value1, "value1") == 0);
  294. dbus_message_iter_next(&entry);
  295. g_assert(dbus_message_iter_get_arg_type(&entry) == DBUS_TYPE_STRING);
  296. dbus_message_iter_get_basic(&entry, &value2);
  297. g_assert(g_strcmp0(value2, "value2") == 0);
  298. g_dbus_client_unref(context->dbus_client);
  299. }
  300. static gboolean get_array(const GDBusPropertyTable *property,
  301. DBusMessageIter *iter, void *data)
  302. {
  303. const char *value[2] = { "value1", "value2" };
  304. DBusMessageIter array;
  305. dbus_message_iter_open_container(iter, DBUS_TYPE_ARRAY, "s", &array);
  306. dbus_message_iter_append_basic(&array, DBUS_TYPE_STRING, &value[0]);
  307. dbus_message_iter_append_basic(&array, DBUS_TYPE_STRING, &value[1]);
  308. dbus_message_iter_close_container(iter, &array);
  309. return TRUE;
  310. }
  311. static void client_get_array_property(const void *data)
  312. {
  313. struct context *context = create_context();
  314. static const GDBusPropertyTable array_properties[] = {
  315. { "Array", "as", get_array },
  316. { },
  317. };
  318. if (context == NULL)
  319. return;
  320. g_dbus_register_interface(context->dbus_conn,
  321. SERVICE_PATH, SERVICE_NAME,
  322. methods, signals, array_properties,
  323. NULL, NULL);
  324. context->dbus_client = g_dbus_client_new(context->dbus_conn,
  325. SERVICE_NAME, SERVICE_PATH);
  326. g_dbus_client_set_proxy_handlers(context->dbus_client, proxy_get_array,
  327. NULL, NULL, context);
  328. g_dbus_client_set_disconnect_watch(context->dbus_client,
  329. disconnect_handler, context);
  330. }
  331. static void proxy_get_uint64(GDBusProxy *proxy, void *user_data)
  332. {
  333. struct context *context = user_data;
  334. DBusMessageIter iter;
  335. guint64 value;
  336. tester_debug("proxy %s found", g_dbus_proxy_get_interface(proxy));
  337. g_assert(g_dbus_proxy_get_property(proxy, "Number", &iter));
  338. g_assert(dbus_message_iter_get_arg_type(&iter) == DBUS_TYPE_UINT64);
  339. dbus_message_iter_get_basic(&iter, &value);
  340. g_assert(value == G_MAXUINT64);
  341. g_dbus_client_unref(context->dbus_client);
  342. }
  343. static gboolean get_uint64(const GDBusPropertyTable *property,
  344. DBusMessageIter *iter, void *data)
  345. {
  346. guint64 value = G_MAXUINT64;
  347. dbus_message_iter_append_basic(iter, DBUS_TYPE_UINT64, &value);
  348. return TRUE;
  349. }
  350. static void client_get_uint64_property(const void *data)
  351. {
  352. struct context *context = create_context();
  353. static const GDBusPropertyTable uint64_properties[] = {
  354. { "Number", "t", get_uint64 },
  355. { },
  356. };
  357. if (context == NULL)
  358. return;
  359. g_dbus_register_interface(context->dbus_conn,
  360. SERVICE_PATH, SERVICE_NAME,
  361. methods, signals, uint64_properties,
  362. NULL, NULL);
  363. context->dbus_client = g_dbus_client_new(context->dbus_conn,
  364. SERVICE_NAME, SERVICE_PATH);
  365. g_dbus_client_set_proxy_handlers(context->dbus_client,
  366. proxy_get_uint64,
  367. NULL, NULL, context);
  368. g_dbus_client_set_disconnect_watch(context->dbus_client,
  369. disconnect_handler, context);
  370. }
  371. static void property_set_success(const DBusError *err, void *user_data)
  372. {
  373. g_assert(!dbus_error_is_set(err));
  374. }
  375. static void proxy_set_string(GDBusProxy *proxy, void *user_data)
  376. {
  377. DBusMessageIter iter;
  378. const char *string;
  379. tester_debug("proxy %s found", g_dbus_proxy_get_interface(proxy));
  380. g_assert(g_dbus_proxy_get_property(proxy, "String", &iter));
  381. g_assert(dbus_message_iter_get_arg_type(&iter) == DBUS_TYPE_STRING);
  382. dbus_message_iter_get_basic(&iter, &string);
  383. g_assert(g_strcmp0(string, "value") == 0);
  384. string = "value1";
  385. g_assert(g_dbus_proxy_set_property_basic(proxy, "String",
  386. DBUS_TYPE_STRING, &string,
  387. property_set_success, user_data,
  388. NULL));
  389. }
  390. static void property_string_changed(GDBusProxy *proxy, const char *name,
  391. DBusMessageIter *iter, void *user_data)
  392. {
  393. struct context *context = user_data;
  394. const char *string;
  395. tester_debug("property %s changed", name);
  396. g_assert(g_strcmp0(name, "String") == 0);
  397. g_assert(dbus_message_iter_get_arg_type(iter) == DBUS_TYPE_STRING);
  398. dbus_message_iter_get_basic(iter, &string);
  399. g_assert(g_strcmp0(string, "value1") == 0);
  400. g_dbus_client_unref(context->dbus_client);
  401. }
  402. static void set_string(const GDBusPropertyTable *property,
  403. DBusMessageIter *iter, GDBusPendingPropertySet id,
  404. void *data)
  405. {
  406. struct context *context = data;
  407. const char *string;
  408. g_assert(dbus_message_iter_get_arg_type(iter) == DBUS_TYPE_STRING);
  409. dbus_message_iter_get_basic(iter, &string);
  410. g_assert(g_strcmp0(string, "value1") == 0);
  411. g_free(context->data);
  412. context->data = g_strdup(string);
  413. g_dbus_emit_property_changed(context->dbus_conn, SERVICE_PATH,
  414. SERVICE_NAME, "String");
  415. g_dbus_pending_property_success(id);
  416. }
  417. static void client_set_string_property(const void *data)
  418. {
  419. struct context *context = create_context();
  420. static const GDBusPropertyTable string_properties[] = {
  421. { "String", "s", get_string, set_string },
  422. { },
  423. };
  424. if (context == NULL)
  425. return;
  426. context->data = g_strdup("value");
  427. g_dbus_register_interface(context->dbus_conn,
  428. SERVICE_PATH, SERVICE_NAME,
  429. methods, signals, string_properties,
  430. context, NULL);
  431. context->dbus_client = g_dbus_client_new(context->dbus_conn,
  432. SERVICE_NAME, SERVICE_PATH);
  433. g_dbus_client_set_disconnect_watch(context->dbus_client,
  434. disconnect_handler, context);
  435. g_dbus_client_set_proxy_handlers(context->dbus_client, proxy_set_string,
  436. NULL, property_string_changed,
  437. context);
  438. }
  439. static gboolean string_exists(const GDBusPropertyTable *property, void *data)
  440. {
  441. struct context *context = data;
  442. return context->data != NULL;
  443. }
  444. static gboolean timeout_test(gpointer user_data)
  445. {
  446. struct context *context = user_data;
  447. tester_debug("timeout triggered");
  448. context->timeout_source = 0;
  449. g_assert_not_reached();
  450. return FALSE;
  451. }
  452. static gboolean emit_string_change(void *user_data)
  453. {
  454. struct context *context = user_data;
  455. context->data = g_strdup("value1");
  456. g_dbus_emit_property_changed(context->dbus_conn, SERVICE_PATH,
  457. SERVICE_NAME, "String");
  458. context->timeout_source = g_timeout_add_seconds(2, timeout_test,
  459. context);
  460. return FALSE;
  461. }
  462. static void proxy_string_changed(GDBusProxy *proxy, void *user_data)
  463. {
  464. struct context *context = user_data;
  465. DBusMessageIter iter;
  466. tester_debug("proxy %s found", g_dbus_proxy_get_interface(proxy));
  467. g_assert(!g_dbus_proxy_get_property(proxy, "String", &iter));
  468. g_idle_add(emit_string_change, context);
  469. }
  470. static void client_string_changed(const void *data)
  471. {
  472. struct context *context = create_context();
  473. static const GDBusPropertyTable string_properties[] = {
  474. { "String", "s", get_string, NULL, string_exists },
  475. { },
  476. };
  477. if (context == NULL)
  478. return;
  479. g_dbus_register_interface(context->dbus_conn,
  480. SERVICE_PATH, SERVICE_NAME,
  481. methods, signals, string_properties,
  482. context, NULL);
  483. context->dbus_client = g_dbus_client_new(context->dbus_conn,
  484. SERVICE_NAME, SERVICE_PATH);
  485. g_dbus_client_set_disconnect_watch(context->dbus_client,
  486. disconnect_handler, context);
  487. g_dbus_client_set_proxy_handlers(context->dbus_client,
  488. proxy_string_changed, NULL,
  489. property_string_changed,
  490. context);
  491. }
  492. static void property_check_order(const DBusError *err, void *user_data)
  493. {
  494. struct context *context = user_data;
  495. GDBusProxy *proxy = context->proxy;
  496. DBusMessageIter iter;
  497. const char *string;
  498. g_assert(!dbus_error_is_set(err));
  499. g_assert(g_dbus_proxy_get_property(proxy, "String", &iter));
  500. dbus_message_iter_get_basic(&iter, &string);
  501. g_assert(g_strcmp0(string, "value1") == 0);
  502. g_dbus_client_unref(context->dbus_client);
  503. }
  504. static void proxy_check_order(GDBusProxy *proxy, void *user_data)
  505. {
  506. struct context *context = user_data;
  507. const char *string;
  508. tester_debug("proxy %s found", g_dbus_proxy_get_interface(proxy));
  509. context->proxy = proxy;
  510. string = "value1";
  511. g_assert(g_dbus_proxy_set_property_basic(proxy, "String",
  512. DBUS_TYPE_STRING, &string,
  513. property_check_order, context,
  514. NULL));
  515. }
  516. static void client_check_order(const void *data)
  517. {
  518. struct context *context = create_context();
  519. static const GDBusPropertyTable string_properties[] = {
  520. { "String", "s", get_string, set_string, string_exists },
  521. { },
  522. };
  523. if (context == NULL)
  524. return;
  525. context->data = g_strdup("value");
  526. g_dbus_register_interface(context->dbus_conn,
  527. SERVICE_PATH, SERVICE_NAME,
  528. methods, signals, string_properties,
  529. context, NULL);
  530. context->dbus_client = g_dbus_client_new(context->dbus_conn,
  531. SERVICE_NAME, SERVICE_PATH);
  532. g_dbus_client_set_disconnect_watch(context->dbus_client,
  533. disconnect_handler, context);
  534. g_dbus_client_set_proxy_handlers(context->dbus_client,
  535. proxy_check_order, NULL, NULL,
  536. context);
  537. }
  538. static void proxy_removed(GDBusProxy *proxy, void *user_data)
  539. {
  540. struct context *context = user_data;
  541. tester_debug("proxy removed");
  542. destroy_context(context);
  543. }
  544. static void proxy_set_removed(GDBusProxy *proxy, void *user_data)
  545. {
  546. struct context *context = user_data;
  547. tester_debug("proxy %s found", g_dbus_proxy_get_interface(proxy));
  548. g_assert(g_dbus_proxy_set_removed_watch(proxy, proxy_removed, context));
  549. context->timeout_source = g_timeout_add_seconds(2, timeout_test,
  550. context);
  551. g_dbus_unregister_interface(context->dbus_conn, SERVICE_PATH,
  552. SERVICE_NAME);
  553. }
  554. static void client_proxy_removed(const void *data)
  555. {
  556. struct context *context = create_context();
  557. static const GDBusPropertyTable string_properties[] = {
  558. { "String", "s", get_string, set_string, string_exists },
  559. { },
  560. };
  561. if (context == NULL)
  562. return;
  563. g_dbus_register_interface(context->dbus_conn,
  564. SERVICE_PATH, SERVICE_NAME,
  565. methods, signals, string_properties,
  566. context, NULL);
  567. context->dbus_client = g_dbus_client_new(context->dbus_conn,
  568. SERVICE_NAME, SERVICE_PATH);
  569. g_dbus_client_set_proxy_handlers(context->dbus_client,
  570. proxy_set_removed, NULL, NULL,
  571. context);
  572. }
  573. static void client_no_object_manager(const void *data)
  574. {
  575. struct context *context = create_context();
  576. DBusMessageIter iter;
  577. static const GDBusPropertyTable string_properties[] = {
  578. { "String", "s", get_string, set_string, string_exists },
  579. { },
  580. };
  581. if (context == NULL)
  582. return;
  583. context->data = g_strdup("value");
  584. g_dbus_register_interface(context->dbus_conn,
  585. SERVICE_PATH, SERVICE_NAME,
  586. methods, signals, string_properties,
  587. context, NULL);
  588. context->dbus_client = g_dbus_client_new_full(context->dbus_conn,
  589. SERVICE_NAME, SERVICE_PATH,
  590. NULL);
  591. g_dbus_client_set_disconnect_watch(context->dbus_client,
  592. disconnect_handler, context);
  593. context->proxy = g_dbus_proxy_new(context->dbus_client, SERVICE_PATH,
  594. SERVICE_NAME);
  595. g_dbus_client_set_proxy_handlers(context->dbus_client, proxy_get_string,
  596. NULL, NULL, context);
  597. g_assert(!g_dbus_proxy_get_property(context->proxy, "String", &iter));
  598. }
  599. static void proxy_force_disconnect(GDBusProxy *proxy, void *user_data)
  600. {
  601. struct context *context = user_data;
  602. DBusConnection *conn = context->data;
  603. tester_debug("proxy %s found", g_dbus_proxy_get_interface(proxy));
  604. g_assert(g_dbus_proxy_set_removed_watch(proxy, proxy_removed, context));
  605. context->timeout_source = g_timeout_add_seconds(2, timeout_test,
  606. context);
  607. g_dbus_detach_object_manager(conn);
  608. g_dbus_unregister_interface(conn, SERVICE_PATH, SERVICE_NAME1);
  609. dbus_connection_flush(conn);
  610. dbus_connection_close(conn);
  611. dbus_connection_unref(conn);
  612. context->data = NULL;
  613. }
  614. static void client_force_disconnect(const void *data)
  615. {
  616. struct context *context = create_context();
  617. DBusConnection *conn;
  618. static const GDBusPropertyTable string_properties[] = {
  619. { "String", "s", get_string, set_string, string_exists },
  620. { },
  621. };
  622. if (context == NULL)
  623. return;
  624. conn = g_dbus_setup_private(DBUS_BUS_SESSION, SERVICE_NAME1, NULL);
  625. g_assert(conn != NULL);
  626. /* Avoid D-Bus library calling _exit() before next test finishes. */
  627. dbus_connection_set_exit_on_disconnect(conn, FALSE);
  628. g_dbus_attach_object_manager(conn);
  629. context->data = conn;
  630. g_dbus_register_interface(conn, SERVICE_PATH, SERVICE_NAME1,
  631. methods, signals, string_properties,
  632. context, NULL);
  633. context->dbus_client = g_dbus_client_new(context->dbus_conn,
  634. SERVICE_NAME1, SERVICE_PATH);
  635. g_dbus_client_set_proxy_handlers(context->dbus_client,
  636. proxy_force_disconnect, NULL, NULL,
  637. context);
  638. }
  639. static void client_ready_watch(GDBusClient *client, void *user_data)
  640. {
  641. struct context *context = user_data;
  642. context->client_ready = TRUE;
  643. }
  644. static void proxy_added(GDBusProxy *proxy, void *user_data)
  645. {
  646. struct context *context = user_data;
  647. /*
  648. * Proxy added callback should not be called after Client ready
  649. * watch. Ready means that all objects has been reported to the
  650. * upper-layer.
  651. */
  652. g_assert(context->client_ready == FALSE);
  653. destroy_context(context);
  654. }
  655. static void client_ready(const void *data)
  656. {
  657. struct context *context = create_context();
  658. static const GDBusPropertyTable string_properties[] = {
  659. { "String", "s", get_string, set_string, string_exists },
  660. { },
  661. };
  662. if (context == NULL)
  663. return;
  664. g_dbus_register_interface(context->dbus_conn,
  665. SERVICE_PATH, SERVICE_NAME,
  666. methods, signals, string_properties,
  667. context, NULL);
  668. context->dbus_client = g_dbus_client_new(context->dbus_conn,
  669. SERVICE_NAME, SERVICE_PATH);
  670. g_dbus_client_set_ready_watch(context->dbus_client, client_ready_watch,
  671. context);
  672. g_dbus_client_set_proxy_handlers(context->dbus_client,
  673. proxy_added, NULL, NULL, context);
  674. }
  675. int main(int argc, char *argv[])
  676. {
  677. tester_init(&argc, &argv);
  678. tester_add("/gdbus/simple_client", NULL, NULL, simple_client, NULL);
  679. tester_add("/gdbus/client_connect_disconnect", NULL, NULL,
  680. client_connect_disconnect, NULL);
  681. tester_add("/gdbus/client_get_string_property", NULL, NULL,
  682. client_get_string_property, NULL);
  683. tester_add("/gdbus/client_get_boolean_property", NULL, NULL,
  684. client_get_boolean_property, NULL);
  685. tester_add("/gdbus/client_get_uint64_property", NULL, NULL,
  686. client_get_uint64_property, NULL);
  687. tester_add("/gdbus/client_get_array_property", NULL, NULL,
  688. client_get_array_property, NULL);
  689. tester_add("/gdbus/client_get_dict_property", NULL, NULL,
  690. client_get_dict_property, NULL);
  691. tester_add("/gdbus/client_set_string_property", NULL, NULL,
  692. client_set_string_property, NULL);
  693. tester_add("/gdbus/client_string_changed", NULL, NULL,
  694. client_string_changed, NULL);
  695. tester_add("/gdbus/client_check_order", NULL, NULL, client_check_order,
  696. NULL);
  697. tester_add("/gdbus/client_proxy_removed", NULL, NULL,
  698. client_proxy_removed, NULL);
  699. tester_add("/gdbus/client_no_object_manager", NULL, NULL,
  700. client_no_object_manager, NULL);
  701. tester_add("/gdbus/client_force_disconnect", NULL, NULL,
  702. client_force_disconnect, NULL);
  703. tester_add("/gdbus/client_ready", NULL, NULL, client_ready, NULL);
  704. return tester_run();
  705. }