aboutsummaryrefslogtreecommitdiff
path: root/src/dht/test_dht_topo.c
diff options
context:
space:
mode:
authorBart Polot <bart@net.in.tum.de>2012-02-07 16:29:51 +0000
committerBart Polot <bart@net.in.tum.de>2012-02-07 16:29:51 +0000
commit416270b1b3e583dcba89718030c1782d856f5be6 (patch)
treec99fdd8e7e02b7f51893b5e9f035bd1433363988 /src/dht/test_dht_topo.c
parent770f379eb23e8344b82431483613eaa72478bcdc (diff)
downloadgnunet-416270b1b3e583dcba89718030c1782d856f5be6.tar.gz
gnunet-416270b1b3e583dcba89718030c1782d856f5be6.zip
- Change DHT testing into common code, to allow adding further topologies
Diffstat (limited to 'src/dht/test_dht_topo.c')
-rw-r--r--src/dht/test_dht_topo.c568
1 files changed, 568 insertions, 0 deletions
diff --git a/src/dht/test_dht_topo.c b/src/dht/test_dht_topo.c
new file mode 100644
index 000000000..1db351841
--- /dev/null
+++ b/src/dht/test_dht_topo.c
@@ -0,0 +1,568 @@
1/*
2 This file is part of GNUnet.
3 (C) 2011 Christian Grothoff (and other contributing authors)
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
19*/
20/**
21 * @file dht/test_dht_2dtorus.c
22 *
23 * @brief Test for the dht service: store and retrieve in a 2d_torus.
24 * Each peer stores it own ID in the DHT and then a different peer tries to
25 * retrieve that key from it. The GET starts after a first round of PUTS has
26 * been made. Periodically, each peer stores its ID into the DHT. If after
27 * a timeout no result has been returned, the test fails.
28 */
29#include "platform.h"
30#include "gnunet_testing_lib.h"
31#include "gnunet_dht_service.h"
32
33#define VERBOSE GNUNET_EXTRA_LOGGING
34
35#define REMOVE_DIR GNUNET_YES
36
37
38/**
39 * How long until we give up on connecting the peers?
40 */
41#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 1500)
42
43#define GET_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 120)
44
45#define PUT_FREQUENCY GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5)
46
47static int ok;
48
49/**
50 * Be verbose
51 */
52static int verbose;
53
54/**
55 * Total number of peers in the test.
56 */
57static unsigned long long num_peers;
58
59/**
60 * Global configuration file
61 */
62static struct GNUNET_CONFIGURATION_Handle *testing_cfg;
63
64/**
65 * Total number of currently running peers.
66 */
67static unsigned long long peers_running;
68
69/**
70 * Total number of connections in the whole network.
71 */
72static unsigned int total_connections;
73
74/**
75 * The currently running peer group.
76 */
77static struct GNUNET_TESTING_PeerGroup *pg;
78
79/**
80 * File to report results to.
81 */
82static struct GNUNET_DISK_FileHandle *output_file;
83
84/**
85 * File to log connection info, statistics to.
86 */
87static struct GNUNET_DISK_FileHandle *data_file;
88
89/**
90 * Task called to disconnect peers.
91 */
92static GNUNET_SCHEDULER_TaskIdentifier disconnect_task;
93
94/**
95 * Task To perform tests
96 */
97static GNUNET_SCHEDULER_TaskIdentifier test_task;
98
99/**
100 * Task to do DHT_puts
101 */
102static GNUNET_SCHEDULER_TaskIdentifier put_task;
103
104/**
105 * Task called to shutdown test.
106 */
107static GNUNET_SCHEDULER_TaskIdentifier shutdown_handle;
108
109static char *topology_file;
110
111struct GNUNET_TESTING_Daemon *d1;
112
113struct GNUNET_TESTING_Daemon *d2;
114
115struct GNUNET_DHT_Handle **hs;
116
117struct GNUNET_DHT_GetHandle *get_h;
118
119struct GNUNET_DHT_GetHandle *get_h_2;
120
121struct GNUNET_DHT_GetHandle *get_h_far;
122
123unsigned int found;
124
125/**
126 * Check whether peers successfully shut down.
127 */
128static void
129shutdown_callback (void *cls, const char *emsg)
130{
131 if (emsg != NULL)
132 {
133#if VERBOSE
134 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: Shutdown of peers failed!\n");
135#endif
136 ok++;
137 }
138 else
139 {
140#if VERBOSE
141 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
142 "test: All peers successfully shut down!\n");
143#endif
144 }
145}
146
147
148static void
149shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
150{
151#if VERBOSE
152 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: Ending test.\n");
153#endif
154
155 if (disconnect_task != GNUNET_SCHEDULER_NO_TASK)
156 {
157 GNUNET_SCHEDULER_cancel (disconnect_task);
158 disconnect_task = GNUNET_SCHEDULER_NO_TASK;
159 }
160
161 if (data_file != NULL)
162 GNUNET_DISK_file_close (data_file);
163 GNUNET_TESTING_daemons_stop (pg, TIMEOUT, &shutdown_callback, NULL);
164 GNUNET_CONFIGURATION_destroy (testing_cfg);
165}
166
167
168static void
169disconnect_peers (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
170{
171 unsigned int i;
172
173 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: disconnecting peers\n");
174 disconnect_task = GNUNET_SCHEDULER_NO_TASK;
175 GNUNET_SCHEDULER_cancel (put_task);
176 if (NULL != get_h)
177 GNUNET_DHT_get_stop (get_h);
178 if (NULL != get_h_2)
179 GNUNET_DHT_get_stop (get_h_2);
180 if (NULL != get_h_far)
181 GNUNET_DHT_get_stop (get_h_far);
182 for (i = 0; i < num_peers; i++)
183 {
184 GNUNET_DHT_disconnect (hs[i]);
185 }
186 GNUNET_SCHEDULER_cancel (shutdown_handle);
187 shutdown_handle = GNUNET_SCHEDULER_add_now (&shutdown_task, NULL);
188}
189
190static void
191dht_get_id_handler (void *cls, struct GNUNET_TIME_Absolute exp,
192 const GNUNET_HashCode * key,
193 const struct GNUNET_PeerIdentity *get_path,
194 unsigned int get_path_length,
195 const struct GNUNET_PeerIdentity *put_path,
196 unsigned int put_path_length, enum GNUNET_BLOCK_Type type,
197 size_t size, const void *data)
198{
199 int i;
200
201 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
202 "test: ************* FOUND!!! ***********\n");
203 if (sizeof (GNUNET_HashCode) == size)
204 {
205 const GNUNET_HashCode *h = data;
206
207 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: Contents: %s\n",
208 GNUNET_h2s_full (h));
209
210 }
211 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: PATH: (get %u, put %u)\n",
212 get_path_length, put_path_length);
213 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: LOCAL\n");
214 for (i = get_path_length - 1; i >= 0; i--)
215 {
216 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: %s\n",
217 GNUNET_i2s (&get_path[i]));
218 }
219 for (i = put_path_length - 1; i >= 0; i--)
220 {
221 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: %s\n",
222 GNUNET_i2s (&put_path[i]));
223 }
224 found++;
225 if (found < 3)
226 return;
227 ok = 0;
228 GNUNET_SCHEDULER_cancel (disconnect_task);
229 disconnect_task = GNUNET_SCHEDULER_add_now (&disconnect_peers, NULL);
230}
231
232static void
233do_test (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
234{
235 struct GNUNET_TESTING_Daemon *d;
236 struct GNUNET_TESTING_Daemon *d2;
237 struct GNUNET_TESTING_Daemon *d_far;
238 struct GNUNET_TESTING_Daemon *o;
239 struct GNUNET_TESTING_Daemon *aux;
240 const char *id_aux;
241 const char *id_origin = "FC74";
242 const char *id_near = "9P6V";
243 const char *id_near2 = "2GDS";
244 const char *id_far = "KPST";
245 unsigned int i;
246
247 d = d2 = d_far = o = NULL;
248 for (i = 0; i < num_peers; i++)
249 {
250 aux = GNUNET_TESTING_daemon_get (pg, i);
251 id_aux = GNUNET_i2s (&aux->id);
252 if (strcmp (id_aux, id_origin) == 0)
253 o = aux;
254 if (strcmp (id_aux, id_far) == 0)
255 d_far = aux;
256 if (strcmp (id_aux, id_near) == 0)
257 d = aux;
258 if (strcmp (id_aux, id_near2) == 0)
259 d2 = aux;
260 }
261 if ((NULL == o) || (NULL == d) || (NULL == d2) || (NULL == d_far))
262 {
263 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
264 "test: Peers not found (hostkey file changed?)\n");
265 GNUNET_SCHEDULER_cancel (disconnect_task);
266 disconnect_task = GNUNET_SCHEDULER_add_now (&disconnect_peers, NULL);
267 return;
268 }
269 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: test_task\n");
270 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: looking for %s\n",
271 GNUNET_h2s_full (&d->id.hashPubKey));
272 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: looking for %s\n",
273 GNUNET_h2s_full (&d2->id.hashPubKey));
274 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: looking for %s\n",
275 GNUNET_h2s_full (&d_far->id.hashPubKey));
276 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: from %s\n",
277 GNUNET_h2s_full (&o->id.hashPubKey));
278 found = 0;
279 get_h = GNUNET_DHT_get_start (hs[0], GNUNET_TIME_UNIT_FOREVER_REL, /* timeout */
280 GNUNET_BLOCK_TYPE_TEST, /* type */
281 &d->id.hashPubKey, /*key to search */
282 4U, /* replication level */
283 GNUNET_DHT_RO_RECORD_ROUTE | GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE, NULL, /* xquery */
284 0, /* xquery bits */
285 &dht_get_id_handler, NULL);
286 get_h_2 = GNUNET_DHT_get_start (hs[0], GNUNET_TIME_UNIT_FOREVER_REL, /* timeout */
287 GNUNET_BLOCK_TYPE_TEST, /* type */
288 &d2->id.hashPubKey, /*key to search */
289 4U, /* replication level */
290 GNUNET_DHT_RO_RECORD_ROUTE | GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE, NULL, /* xquery */
291 0, /* xquery bits */
292 &dht_get_id_handler, NULL);
293 get_h_far = GNUNET_DHT_get_start (hs[0], GNUNET_TIME_UNIT_FOREVER_REL, /* timeout */
294 GNUNET_BLOCK_TYPE_TEST, /* type */
295 &d_far->id.hashPubKey, /*key to search */
296 4U, /* replication level */
297 GNUNET_DHT_RO_RECORD_ROUTE | GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE, NULL, /* xquery */
298 0, /* xquery bits */
299 &dht_get_id_handler, NULL);
300 GNUNET_SCHEDULER_cancel (disconnect_task);
301 disconnect_task =
302 GNUNET_SCHEDULER_add_delayed (GET_TIMEOUT, &disconnect_peers, NULL);
303}
304
305
306static void
307put_id (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
308{
309 struct GNUNET_TESTING_Daemon *d;
310 unsigned int i;
311
312 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: putting id's in DHT\n");
313 for (i = 0; i < num_peers; i++)
314 {
315 d = GNUNET_TESTING_daemon_get (pg, i);
316 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: putting into DHT: %s\n",
317 GNUNET_h2s_full (&d->id.hashPubKey));
318 GNUNET_DHT_put (hs[i], &d->id.hashPubKey, 10U,
319 GNUNET_DHT_RO_RECORD_ROUTE |
320 GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE,
321 GNUNET_BLOCK_TYPE_TEST, sizeof (struct GNUNET_PeerIdentity),
322 (const char *) &d->id, GNUNET_TIME_UNIT_FOREVER_ABS,
323 GNUNET_TIME_UNIT_FOREVER_REL, NULL, NULL);
324
325 }
326 put_task = GNUNET_SCHEDULER_add_delayed (PUT_FREQUENCY, &put_id, NULL);
327}
328
329
330/**
331 * peergroup_ready: start test when all peers are connected
332 * @param cls closure
333 * @param emsg error message
334 */
335static void
336peergroup_ready (void *cls, const char *emsg)
337{
338 struct GNUNET_TESTING_Daemon *d;
339 char *buf;
340 int buf_len;
341 unsigned int i;
342
343 if (emsg != NULL)
344 {
345 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
346 "test: Peergroup callback called with error, aborting test!\n");
347 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: Error from testing: `%s'\n",
348 emsg);
349 ok++;
350 GNUNET_TESTING_daemons_stop (pg, TIMEOUT, &shutdown_callback, NULL);
351 return;
352 }
353#if VERBOSE
354 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
355 "************************************************************\n");
356 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
357 "test: Peer Group started successfully!\n");
358 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: Have %u connections\n",
359 total_connections);
360#endif
361
362 if (data_file != NULL)
363 {
364 buf = NULL;
365 buf_len = GNUNET_asprintf (&buf, "CONNECTIONS_0: %u\n", total_connections);
366 if (buf_len > 0)
367 GNUNET_DISK_file_write (data_file, buf, buf_len);
368 GNUNET_free (buf);
369 }
370 peers_running = GNUNET_TESTING_daemons_running (pg);
371
372 GNUNET_assert (peers_running == num_peers);
373 hs = GNUNET_malloc (num_peers * sizeof (struct GNUNET_DHT_Handle *));
374 for (i = 0; i < num_peers; i++)
375 {
376 d = GNUNET_TESTING_daemon_get (pg, i);
377 hs[i] = GNUNET_DHT_connect (d->cfg, 32);
378 }
379
380 put_task = GNUNET_SCHEDULER_add_now (&put_id, NULL);
381 test_task =
382 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
383 (GNUNET_TIME_UNIT_SECONDS, 2), &do_test,
384 NULL);
385 disconnect_task =
386 GNUNET_SCHEDULER_add_delayed (GET_TIMEOUT, &disconnect_peers, NULL);
387
388}
389
390
391/**
392 * Function that will be called whenever two daemons are connected by
393 * the testing library.
394 *
395 * @param cls closure
396 * @param first peer id for first daemon
397 * @param second peer id for the second daemon
398 * @param distance distance between the connected peers
399 * @param first_cfg config for the first daemon
400 * @param second_cfg config for the second daemon
401 * @param first_daemon handle for the first daemon
402 * @param second_daemon handle for the second daemon
403 * @param emsg error message (NULL on success)
404 */
405static void
406connect_cb (void *cls, const struct GNUNET_PeerIdentity *first,
407 const struct GNUNET_PeerIdentity *second, uint32_t distance,
408 const struct GNUNET_CONFIGURATION_Handle *first_cfg,
409 const struct GNUNET_CONFIGURATION_Handle *second_cfg,
410 struct GNUNET_TESTING_Daemon *first_daemon,
411 struct GNUNET_TESTING_Daemon *second_daemon, const char *emsg)
412{
413
414 if (emsg == NULL)
415 {
416 total_connections++;
417 GNUNET_PEER_intern (first);
418 GNUNET_PEER_intern (second);
419 }
420 else
421 {
422 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
423 "test: Problem with new connection (%s)\n", emsg);
424 }
425
426}
427
428
429/**
430 * run: load configuration options and schedule test to run (start peergroup)
431 * @param cls closure
432 * @param args argv
433 * @param cfgfile configuration file name (can be NULL)
434 * @param cfg configuration handle
435 */
436static void
437run (void *cls, char *const *args, const char *cfgfile,
438 const struct GNUNET_CONFIGURATION_Handle *cfg)
439{
440 char *temp_str;
441 struct GNUNET_TESTING_Host *hosts;
442 char *data_filename;
443
444 ok = 1;
445 testing_cfg = GNUNET_CONFIGURATION_dup (cfg);
446
447 GNUNET_log_setup ("test_dht_2dtorus",
448#if VERBOSE
449 "DEBUG",
450#else
451 "WARNING",
452#endif
453 NULL);
454
455#if VERBOSE
456 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: Starting daemons.\n");
457 GNUNET_CONFIGURATION_set_value_string (testing_cfg, "testing",
458 "use_progressbars", "YES");
459#endif
460
461 if (GNUNET_OK !=
462 GNUNET_CONFIGURATION_get_value_number (testing_cfg, "testing",
463 "num_peers", &num_peers))
464 {
465 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
466 "Option TESTING:NUM_PEERS is required!\n");
467 return;
468 }
469
470 if (GNUNET_OK !=
471 GNUNET_CONFIGURATION_get_value_string (testing_cfg, "testing",
472 "topology_output_file",
473 &topology_file))
474 {
475 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
476 "Option test_dht_2d:topology_output_file is required!\n");
477 return;
478 }
479
480 if (GNUNET_OK ==
481 GNUNET_CONFIGURATION_get_value_string (testing_cfg, "test_dht_2dtorus",
482 "data_output_file",
483 &data_filename))
484 {
485 data_file =
486 GNUNET_DISK_file_open (data_filename,
487 GNUNET_DISK_OPEN_READWRITE |
488 GNUNET_DISK_OPEN_CREATE,
489 GNUNET_DISK_PERM_USER_READ |
490 GNUNET_DISK_PERM_USER_WRITE);
491 if (data_file == NULL)
492 {
493 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Failed to open %s for output!\n",
494 data_filename);
495 GNUNET_free (data_filename);
496 }
497 }
498
499 if (GNUNET_YES ==
500 GNUNET_CONFIGURATION_get_value_string (cfg, "test_dht_2dtorus",
501 "output_file", &temp_str))
502 {
503 output_file =
504 GNUNET_DISK_file_open (temp_str,
505 GNUNET_DISK_OPEN_READWRITE |
506 GNUNET_DISK_OPEN_CREATE,
507 GNUNET_DISK_PERM_USER_READ |
508 GNUNET_DISK_PERM_USER_WRITE);
509 if (output_file == NULL)
510 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Failed to open %s for output!\n",
511 temp_str);
512 }
513 GNUNET_free_non_null (temp_str);
514
515 hosts = GNUNET_TESTING_hosts_load (testing_cfg);
516
517 pg = GNUNET_TESTING_peergroup_start (testing_cfg, num_peers, TIMEOUT,
518 &connect_cb, &peergroup_ready, NULL,
519 hosts);
520 GNUNET_assert (pg != NULL);
521 shutdown_handle =
522 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL,
523 &shutdown_task, NULL);
524}
525
526
527
528/**
529 * test_dht_2d command line options
530 */
531static struct GNUNET_GETOPT_CommandLineOption options[] = {
532 {'V', "verbose", NULL,
533 gettext_noop ("be verbose (print progress information)"),
534 0, &GNUNET_GETOPT_set_one, &verbose},
535 GNUNET_GETOPT_OPTION_END
536};
537
538
539/**
540 * Main: start test
541 */
542int
543main (int xargc, char *xargv[])
544{
545 char *const argv[] = { "test-dht-2dtorus",
546 "-c",
547 "test_dht_2dtorus.conf",
548#if VERBOSE
549 "-L", "DEBUG",
550#endif
551 NULL
552 };
553
554 GNUNET_PROGRAM_run (sizeof (argv) / sizeof (char *) - 1, argv,
555 "test_dht_2dtorus",
556 gettext_noop ("Test dht in a small 2D torus."), options,
557 &run, NULL);
558#if REMOVE_DIR
559 GNUNET_DISK_directory_remove ("/tmp/test_dht_2dtorus");
560#endif
561 if (0 != ok)
562 {
563 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "test: FAILED!\n");
564 }
565 return ok;
566}
567
568/* end of test_dht_2dtorus.c */