test_gnunet_daemon_topology.c 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298
  1. /*
  2. This file is part of GNUnet.
  3. Copyright (C) 2009, 2012 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 topology/test_gnunet_daemon_topology.c
  18. * @brief testcase for topology maintenance code
  19. * @author Christian Grothoff
  20. * @author xrs
  21. */
  22. #include "platform.h"
  23. #include "gnunet_testbed_service.h"
  24. #include "gnunet_statistics_service.h"
  25. #define NUM_PEERS 8
  26. /*
  27. * The threshold defines the number of connection that are needed
  28. * for one peer to pass the test. Be aware that setting NUM_PEERS
  29. * too high can cause bandwidth problems for the testing peers.
  30. * Normal should be 5KB/s per peer. See gnunet-config -s ats.
  31. * schanzen 12/2019: This _only_ makes sense if we connect to the
  32. * actual network as in the test we do not connect to more than 1 peer.
  33. * => reducing to 1 for now, was NUM_PEERS / 2
  34. */
  35. #define THRESHOLD 1
  36. /**
  37. * How long until we give up on connecting the peers?
  38. */
  39. #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 60)
  40. /*
  41. * Store manual connections.
  42. */
  43. static unsigned int connect_left;
  44. /*
  45. * Result of the testcase.
  46. */
  47. static int result;
  48. /*
  49. * Peers that reached the threshold of connections.
  50. */
  51. static int checked_peers;
  52. /*
  53. * Testbed operations.
  54. */
  55. struct GNUNET_TESTBED_Operation *op[NUM_PEERS];
  56. /*
  57. * Timeout for testcase.
  58. */
  59. static struct GNUNET_SCHEDULER_Task *timeout_tid;
  60. /*
  61. * Peer context for every testbed peer.
  62. */
  63. struct peerctx
  64. {
  65. int index;
  66. struct GNUNET_STATISTICS_Handle *statistics;
  67. int connections;
  68. int reported; /* GNUNET_NO | GNUNET_YES */
  69. };
  70. static void
  71. shutdown_task (void *cls)
  72. {
  73. unsigned int i;
  74. GNUNET_log (GNUNET_ERROR_TYPE_INFO,
  75. "Shutting down testcase\n");
  76. for (i = 0; i < NUM_PEERS; i++)
  77. {
  78. if (NULL != op[i])
  79. GNUNET_TESTBED_operation_done (op[i]);
  80. }
  81. if (NULL != timeout_tid)
  82. GNUNET_SCHEDULER_cancel (timeout_tid);
  83. }
  84. static void
  85. timeout_task (void *cls)
  86. {
  87. timeout_tid = NULL;
  88. GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
  89. "Testcase timeout\n");
  90. result = GNUNET_SYSERR;
  91. GNUNET_SCHEDULER_shutdown ();
  92. }
  93. /*
  94. * The function is called every time the topology of connected
  95. * peers to a peer changes.
  96. */
  97. int
  98. statistics_iterator (void *cls,
  99. const char *subsystem,
  100. const char *name,
  101. uint64_t value,
  102. int is_persistent)
  103. {
  104. struct peerctx *p_ctx = (struct peerctx*) cls;
  105. GNUNET_log (GNUNET_ERROR_TYPE_INFO,
  106. "Peer %d: %s = %llu\n",
  107. p_ctx->index,
  108. name,
  109. (unsigned long long) value);
  110. if (p_ctx->connections < value)
  111. p_ctx->connections = value;
  112. if ((THRESHOLD <= value) && (GNUNET_NO == p_ctx->reported))
  113. {
  114. p_ctx->reported = GNUNET_YES;
  115. checked_peers++;
  116. GNUNET_log (GNUNET_ERROR_TYPE_INFO,
  117. "Peer %d successfully connected to at least %d peers once.\n",
  118. p_ctx->index,
  119. THRESHOLD);
  120. if (checked_peers == NUM_PEERS)
  121. {
  122. GNUNET_log (GNUNET_ERROR_TYPE_INFO,
  123. "Test OK: All peers have connected to %d peers once.\n",
  124. THRESHOLD);
  125. result = GNUNET_YES;
  126. GNUNET_SCHEDULER_shutdown ();
  127. }
  128. }
  129. return GNUNET_YES;
  130. }
  131. static void *
  132. ca_statistics (void *cls,
  133. const struct GNUNET_CONFIGURATION_Handle *cfg)
  134. {
  135. return GNUNET_STATISTICS_create ("topology", cfg);
  136. }
  137. void
  138. da_statistics (void *cls,
  139. void *op_result)
  140. {
  141. struct peerctx *p_ctx = (struct peerctx *) cls;
  142. GNUNET_break (GNUNET_OK == GNUNET_STATISTICS_watch_cancel
  143. (p_ctx->statistics, "topology", "# peers connected",
  144. statistics_iterator, p_ctx));
  145. GNUNET_STATISTICS_destroy (p_ctx->statistics, GNUNET_NO);
  146. p_ctx->statistics = NULL;
  147. GNUNET_free (p_ctx);
  148. }
  149. static void
  150. service_connect_complete (void *cls,
  151. struct GNUNET_TESTBED_Operation *op,
  152. void *ca_result,
  153. const char *emsg)
  154. {
  155. int ret;
  156. struct peerctx *p_ctx = (struct peerctx*) cls;
  157. if (NULL == ca_result)
  158. GNUNET_SCHEDULER_shutdown ();
  159. p_ctx->statistics = ca_result;
  160. ret = GNUNET_STATISTICS_watch (ca_result,
  161. "topology",
  162. "# peers connected",
  163. statistics_iterator,
  164. p_ctx);
  165. if (GNUNET_NO == ret)
  166. GNUNET_log (GNUNET_ERROR_TYPE_INFO,
  167. "call to GNUNET_STATISTICS_watch() failed\n");
  168. }
  169. static void
  170. notify_connect_complete (void *cls,
  171. struct GNUNET_TESTBED_Operation *op,
  172. const char *emsg)
  173. {
  174. GNUNET_TESTBED_operation_done (op);
  175. if (NULL != emsg)
  176. {
  177. fprintf (stderr, "Failed to connect two peers: %s\n", emsg);
  178. result = GNUNET_SYSERR;
  179. GNUNET_SCHEDULER_shutdown ();
  180. return;
  181. }
  182. connect_left--;
  183. }
  184. static void
  185. do_connect (void *cls,
  186. struct GNUNET_TESTBED_RunHandle *h,
  187. unsigned int num_peers,
  188. struct GNUNET_TESTBED_Peer **peers,
  189. unsigned int links_succeeded,
  190. unsigned int links_failed)
  191. {
  192. unsigned int i;
  193. struct peerctx *p_ctx;
  194. GNUNET_log (GNUNET_ERROR_TYPE_INFO,
  195. "Threshold is set to %d.\n",
  196. THRESHOLD);
  197. GNUNET_assert (NUM_PEERS == num_peers);
  198. for (i = 0; i < NUM_PEERS; i++)
  199. {
  200. p_ctx = GNUNET_new (struct peerctx);
  201. p_ctx->index = i;
  202. p_ctx->connections = 0;
  203. p_ctx->reported = GNUNET_NO;
  204. if (i < NUM_PEERS - 1)
  205. {
  206. connect_left++;
  207. GNUNET_TESTBED_overlay_connect (NULL,
  208. &notify_connect_complete, NULL,
  209. peers[i], peers[i + 1]);
  210. }
  211. op[i] =
  212. GNUNET_TESTBED_service_connect (cls,
  213. peers[i],
  214. "statistics",
  215. service_connect_complete,
  216. p_ctx, /* cls of completion cb */
  217. ca_statistics, /* connect adapter */
  218. da_statistics, /* disconnect adapter */
  219. p_ctx);
  220. }
  221. GNUNET_SCHEDULER_add_shutdown (&shutdown_task, NULL);
  222. timeout_tid =
  223. GNUNET_SCHEDULER_add_delayed (TIMEOUT,
  224. &timeout_task,
  225. NULL);
  226. }
  227. int
  228. main (int argc, char *argv[])
  229. {
  230. result = GNUNET_SYSERR;
  231. checked_peers = 0;
  232. (void) GNUNET_TESTBED_test_run ("test-gnunet-daemon-topology",
  233. "test_gnunet_daemon_topology_data.conf",
  234. NUM_PEERS,
  235. 0, NULL, NULL,
  236. &do_connect, NULL);
  237. GNUNET_DISK_directory_remove ("/tmp/test-gnunet-topology");
  238. return (GNUNET_OK != result) ? 1 : 0;
  239. }
  240. /* end of test_gnunet_daemon_topology.c */