test_testbed_api.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509
  1. /*
  2. This file is part of GNUnet
  3. Copyright (C) 2008--2013 GNUnet e.V.
  4. GNUnet is free software: you can redistribute it and/or modify it
  5. under the terms of the GNU Affero General Public License as published
  6. by the Free Software Foundation, either version 3 of the License,
  7. or (at your option) any later version.
  8. GNUnet is distributed in the hope that it will be useful, but
  9. WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  11. Affero General Public License for more details.
  12. You should have received a copy of the GNU Affero General Public License
  13. along with this program. If not, see <http://www.gnu.org/licenses/>.
  14. SPDX-License-Identifier: AGPL3.0-or-later
  15. */
  16. /**
  17. * @file testbed/test_testbed_api.c
  18. * @brief testcases for the testbed api
  19. * @author Sree Harsha Totakura
  20. */
  21. #include "platform.h"
  22. #include "gnunet_util_lib.h"
  23. #include "gnunet_arm_service.h"
  24. #include "gnunet_testing_lib.h"
  25. #include "gnunet_testbed_service.h"
  26. /**
  27. * Generic logging shortcut
  28. */
  29. #define LOG(kind,...) \
  30. GNUNET_log (kind, __VA_ARGS__)
  31. /**
  32. * Relative time seconds shorthand
  33. */
  34. #define TIME_REL_SECS(sec) \
  35. GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, sec)
  36. /**
  37. * Our localhost
  38. */
  39. static struct GNUNET_TESTBED_Host *host;
  40. /**
  41. * The controller process
  42. */
  43. static struct GNUNET_TESTBED_ControllerProc *cp;
  44. /**
  45. * The controller handle
  46. */
  47. static struct GNUNET_TESTBED_Controller *controller;
  48. /**
  49. * A neighbouring host
  50. */
  51. static struct GNUNET_TESTBED_Host *neighbour;
  52. /**
  53. * Handle for neighbour registration
  54. */
  55. static struct GNUNET_TESTBED_HostRegistrationHandle *reg_handle;
  56. /**
  57. * Handle for a peer
  58. */
  59. static struct GNUNET_TESTBED_Peer *peer;
  60. /**
  61. * Handle to configuration
  62. */
  63. static struct GNUNET_CONFIGURATION_Handle *cfg;
  64. /**
  65. * Handle to operation
  66. */
  67. static struct GNUNET_TESTBED_Operation *operation;
  68. /**
  69. * Handle to peer's ARM service
  70. */
  71. static struct GNUNET_ARM_Handle *arm_handle;
  72. /**
  73. * Abort task identifier
  74. */
  75. static struct GNUNET_SCHEDULER_Task *abort_task;
  76. /**
  77. * The testing result
  78. */
  79. static int result;
  80. /**
  81. * Enumeration of sub testcases
  82. */
  83. enum Test
  84. {
  85. /**
  86. * Test cases which are not covered by the below ones
  87. */
  88. OTHER,
  89. /**
  90. * Test where we get a peer config from controller
  91. */
  92. PEER_GETCONFIG,
  93. /**
  94. * Test where we connect to a service running on the peer
  95. */
  96. PEER_SERVICE_CONNECT,
  97. /**
  98. * Test where we get a peer's identity from controller
  99. */
  100. PEER_DESTROY
  101. };
  102. /**
  103. * Testing status
  104. */
  105. static enum Test sub_test;
  106. /**
  107. * Shutdown nicely
  108. *
  109. * @param cls NULL
  110. * @param tc the task context
  111. */
  112. static void
  113. do_shutdown (void *cls)
  114. {
  115. LOG (GNUNET_ERROR_TYPE_DEBUG, "Shutting down...\n");
  116. if (NULL != abort_task)
  117. GNUNET_SCHEDULER_cancel (abort_task);
  118. if (NULL != reg_handle)
  119. GNUNET_TESTBED_cancel_registration (reg_handle);
  120. if (NULL != controller)
  121. GNUNET_TESTBED_controller_disconnect (controller);
  122. if (NULL != cfg)
  123. GNUNET_CONFIGURATION_destroy (cfg);
  124. if (NULL != cp)
  125. GNUNET_TESTBED_controller_stop (cp);
  126. if (NULL != neighbour)
  127. GNUNET_TESTBED_host_destroy (neighbour);
  128. if (NULL != host)
  129. GNUNET_TESTBED_host_destroy (host);
  130. }
  131. /**
  132. * shortcut to exit during failure
  133. */
  134. #define FAIL_TEST(cond, ret) do { \
  135. if (!(cond)) { \
  136. GNUNET_break(0); \
  137. if (NULL != abort_task) \
  138. GNUNET_SCHEDULER_cancel (abort_task); \
  139. abort_task = NULL; \
  140. GNUNET_SCHEDULER_add_now (do_shutdown, NULL); \
  141. ret; \
  142. } \
  143. } while (0)
  144. /**
  145. * abort task to run on test timed out
  146. *
  147. * @param cls NULL
  148. * @param tc the task context
  149. */
  150. static void
  151. do_abort (void *cls)
  152. {
  153. LOG (GNUNET_ERROR_TYPE_WARNING, "Test timedout -- Aborting\n");
  154. abort_task = NULL;
  155. do_shutdown (cls);
  156. }
  157. /**
  158. * Adapter function called to establish a connection to
  159. * a service.
  160. *
  161. * @param cls closure
  162. * @param cfg configuration of the peer to connect to; will be available until
  163. * GNUNET_TESTBED_operation_done() is called on the operation returned
  164. * from GNUNET_TESTBED_service_connect()
  165. * @return service handle to return in 'op_result', NULL on error
  166. */
  167. static void *
  168. arm_connect_adapter (void *cls,
  169. const struct GNUNET_CONFIGURATION_Handle *cfg)
  170. {
  171. FAIL_TEST (NULL == cls, return NULL);
  172. FAIL_TEST (OTHER == sub_test, return NULL);
  173. sub_test = PEER_SERVICE_CONNECT;
  174. arm_handle = GNUNET_ARM_connect (cfg, NULL, NULL);
  175. return arm_handle;
  176. }
  177. /**
  178. * Adapter function called to destroy a connection to
  179. * a service.
  180. *
  181. * @param cls closure
  182. * @param op_result service handle returned from the connect adapter
  183. */
  184. static void
  185. arm_disconnect_adapter (void *cls,
  186. void *op_result)
  187. {
  188. FAIL_TEST (NULL != op_result, return);
  189. FAIL_TEST (op_result == arm_handle, return);
  190. GNUNET_ARM_disconnect (arm_handle);
  191. arm_handle = NULL;
  192. FAIL_TEST (PEER_SERVICE_CONNECT == sub_test, return);
  193. FAIL_TEST (NULL != operation, return);
  194. operation = GNUNET_TESTBED_peer_stop (NULL, peer, NULL, NULL);
  195. FAIL_TEST (NULL != operation, return);
  196. }
  197. /**
  198. * Callback to be called when a service connect operation is completed
  199. *
  200. * @param cls the callback closure from functions generating an operation
  201. * @param op the operation that has been finished
  202. * @param ca_result the service handle returned from GNUNET_TESTBED_ConnectAdapter()
  203. * @param emsg error message in case the operation has failed; will be NULL if
  204. * operation has executed successfully.
  205. */
  206. static void
  207. service_connect_comp_cb (void *cls,
  208. struct GNUNET_TESTBED_Operation *op,
  209. void *ca_result,
  210. const char *emsg)
  211. {
  212. switch (sub_test)
  213. {
  214. case PEER_SERVICE_CONNECT:
  215. FAIL_TEST (operation == op, return);
  216. FAIL_TEST (NULL == emsg, return);
  217. FAIL_TEST (NULL == cls, return);
  218. FAIL_TEST (ca_result == arm_handle, return);
  219. GNUNET_TESTBED_operation_done (operation); /* This results in call to
  220. * disconnect adapter */
  221. break;
  222. default:
  223. FAIL_TEST (0, return);
  224. }
  225. }
  226. /**
  227. * Callback to be called when the requested peer information is available
  228. *
  229. * @param cb_cls the closure from GNUNET_TETSBED_peer_get_information()
  230. * @param op the operation this callback corresponds to
  231. * @param pinfo the result; will be NULL if the operation has failed
  232. * @param emsg error message if the operation has failed; will be NULL if the
  233. * operation is successfull
  234. */
  235. static void
  236. peerinfo_cb (void *cb_cls,
  237. struct GNUNET_TESTBED_Operation *op,
  238. const struct GNUNET_TESTBED_PeerInformation *pinfo,
  239. const char *emsg)
  240. {
  241. switch (sub_test)
  242. {
  243. case PEER_GETCONFIG:
  244. FAIL_TEST (NULL != pinfo, return);
  245. FAIL_TEST (NULL == emsg, return);
  246. FAIL_TEST (NULL == cb_cls, return);
  247. FAIL_TEST (operation == op, return);
  248. FAIL_TEST (GNUNET_TESTBED_PIT_CONFIGURATION == pinfo->pit, return);
  249. FAIL_TEST (NULL != pinfo->result.cfg, return);
  250. sub_test = PEER_DESTROY;
  251. GNUNET_TESTBED_operation_done (operation);
  252. operation = GNUNET_TESTBED_peer_destroy (peer);
  253. break;
  254. default:
  255. FAIL_TEST (0, return);
  256. }
  257. }
  258. /**
  259. * Signature of the event handler function called by the
  260. * respective event controller.
  261. *
  262. * @param cls closure
  263. * @param event information about the event
  264. */
  265. static void
  266. controller_cb (void *cls,
  267. const struct GNUNET_TESTBED_EventInformation *event)
  268. {
  269. switch (event->type)
  270. {
  271. case GNUNET_TESTBED_ET_OPERATION_FINISHED:
  272. switch (sub_test)
  273. {
  274. case PEER_DESTROY:
  275. FAIL_TEST (event->op == operation, return);
  276. FAIL_TEST (NULL == event->op_cls, return);
  277. FAIL_TEST (NULL == event->details.operation_finished.emsg, return);
  278. FAIL_TEST (NULL == event->details.operation_finished.generic, return);
  279. GNUNET_TESTBED_operation_done (operation);
  280. GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
  281. break;
  282. case PEER_SERVICE_CONNECT:
  283. FAIL_TEST (event->op == operation, return);
  284. FAIL_TEST (NULL == event->op_cls, return);
  285. FAIL_TEST (NULL == event->details.operation_finished.emsg, return);
  286. FAIL_TEST (NULL != arm_handle, return);
  287. FAIL_TEST (event->details.operation_finished.generic == arm_handle, return);
  288. break;
  289. default:
  290. FAIL_TEST (0, return);
  291. break;
  292. }
  293. break;
  294. case GNUNET_TESTBED_ET_PEER_START:
  295. FAIL_TEST (event->details.peer_start.host == host, return);
  296. FAIL_TEST (event->details.peer_start.peer == peer, return);
  297. FAIL_TEST (OTHER == sub_test, return);
  298. GNUNET_TESTBED_operation_done (operation);
  299. operation =
  300. GNUNET_TESTBED_service_connect (NULL, peer, "dht",
  301. &service_connect_comp_cb, NULL,
  302. &arm_connect_adapter,
  303. &arm_disconnect_adapter, NULL);
  304. FAIL_TEST (NULL != operation, return);
  305. break;
  306. case GNUNET_TESTBED_ET_PEER_STOP:
  307. FAIL_TEST (event->details.peer_stop.peer == peer, return);
  308. FAIL_TEST (PEER_SERVICE_CONNECT == sub_test, return);
  309. result = GNUNET_YES;
  310. sub_test = PEER_GETCONFIG;
  311. GNUNET_TESTBED_operation_done (operation);
  312. operation =
  313. GNUNET_TESTBED_peer_get_information (peer,
  314. GNUNET_TESTBED_PIT_CONFIGURATION,
  315. &peerinfo_cb, NULL);
  316. break;
  317. default:
  318. FAIL_TEST (0, return); /* We should never reach this state */
  319. }
  320. }
  321. /**
  322. * Functions of this signature are called when a peer has been successfully
  323. * created
  324. *
  325. * @param cls the closure from GNUNET_TESTBED_peer_create()
  326. * @param peer the handle for the created peer; NULL on any error during
  327. * creation
  328. * @param emsg NULL if peer is not NULL; else MAY contain the error description
  329. */
  330. static void
  331. peer_create_cb (void *cls,
  332. struct GNUNET_TESTBED_Peer *peer,
  333. const char *emsg)
  334. {
  335. struct GNUNET_TESTBED_Peer **peer_ptr;
  336. peer_ptr = cls;
  337. FAIL_TEST (NULL != peer, return);
  338. FAIL_TEST (NULL != peer_ptr, return);
  339. *peer_ptr = peer;
  340. GNUNET_TESTBED_operation_done (operation);
  341. operation = GNUNET_TESTBED_peer_start (NULL,
  342. peer,
  343. NULL,
  344. NULL);
  345. FAIL_TEST (NULL != operation, return);
  346. }
  347. /**
  348. * Callback which will be called to after a host registration succeeded or failed
  349. *
  350. * @param cls the host which has been registered
  351. * @param emsg the error message; NULL if host registration is successful
  352. */
  353. static void
  354. registration_comp (void *cls,
  355. const char *emsg)
  356. {
  357. FAIL_TEST (cls == neighbour, return);
  358. reg_handle = NULL;
  359. operation =
  360. GNUNET_TESTBED_peer_create (controller,
  361. host,
  362. cfg,
  363. &peer_create_cb,
  364. &peer);
  365. FAIL_TEST (NULL != operation, return);
  366. }
  367. /**
  368. * Callback to signal successfull startup of the controller process
  369. *
  370. * @param cls the closure from GNUNET_TESTBED_controller_start()
  371. * @param cfg the configuration with which the controller has been started;
  372. * NULL if status is not #GNUNET_OK
  373. * @param status #GNUNET_OK if the startup is successfull; #GNUNET_SYSERR if not,
  374. * GNUNET_TESTBED_controller_stop() shouldn't be called in this case
  375. */
  376. static void
  377. status_cb (void *cls,
  378. const struct GNUNET_CONFIGURATION_Handle *cfg_,
  379. int status)
  380. {
  381. uint64_t event_mask;
  382. if (GNUNET_OK != status)
  383. {
  384. cp = NULL;
  385. FAIL_TEST (0, return);
  386. return;
  387. }
  388. event_mask = 0;
  389. event_mask |= (1L << GNUNET_TESTBED_ET_PEER_START);
  390. event_mask |= (1L << GNUNET_TESTBED_ET_PEER_STOP);
  391. event_mask |= (1L << GNUNET_TESTBED_ET_CONNECT);
  392. event_mask |= (1L << GNUNET_TESTBED_ET_OPERATION_FINISHED);
  393. controller =
  394. GNUNET_TESTBED_controller_connect (host, event_mask, &controller_cb,
  395. NULL);
  396. FAIL_TEST (NULL != controller, return);
  397. neighbour = GNUNET_TESTBED_host_create ("localhost", NULL, cfg, 0);
  398. FAIL_TEST (NULL != neighbour, return);
  399. reg_handle =
  400. GNUNET_TESTBED_register_host (controller, neighbour, &registration_comp,
  401. neighbour);
  402. FAIL_TEST (NULL != reg_handle, return);
  403. }
  404. /**
  405. * Main run function.
  406. *
  407. * @param cls NULL
  408. * @param args arguments passed to #GNUNET_PROGRAM_run()
  409. * @param cfgfile the path to configuration file
  410. * @param cfg the configuration file handle
  411. */
  412. static void
  413. run (void *cls,
  414. char *const *args,
  415. const char *cfgfile,
  416. const struct GNUNET_CONFIGURATION_Handle *config)
  417. {
  418. cfg = GNUNET_CONFIGURATION_dup (config);
  419. host = GNUNET_TESTBED_host_create (NULL, NULL, cfg, 0);
  420. FAIL_TEST (NULL != host, return);
  421. cp = GNUNET_TESTBED_controller_start ("127.0.0.1", host,
  422. &status_cb,
  423. NULL);
  424. abort_task =
  425. GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
  426. (GNUNET_TIME_UNIT_MINUTES, 5),
  427. &do_abort,
  428. NULL);
  429. }
  430. /**
  431. * Main function
  432. */
  433. int
  434. main (int argc, char **argv)
  435. {
  436. int ret;
  437. char *const argv2[] = { "test_testbed_api",
  438. "-c", "test_testbed_api.conf",
  439. NULL
  440. };
  441. struct GNUNET_GETOPT_CommandLineOption options[] = {
  442. GNUNET_GETOPT_OPTION_END
  443. };
  444. result = GNUNET_SYSERR;
  445. ret =
  446. GNUNET_PROGRAM_run ((sizeof (argv2) / sizeof (char *)) - 1, argv2,
  447. "test_testbed_api", "nohelp", options, &run, NULL);
  448. if ((GNUNET_OK != ret) || (GNUNET_OK != result))
  449. return 1;
  450. return 0;
  451. }
  452. /* end of test_testbed_api.c */