2 This file is part of GNUnet.
3 Copyright (C) 2009, 2012 Christian Grothoff (and other contributing authors)
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.
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.
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.
21 * @file rps/test_rps_multipeer.c
22 * @brief Testcase for the random peer sampling service. Starts
23 * a peergroup with a given number of peers, then waits to
24 * receive size pushes/pulls from each peer. Expects to wait
25 * for one message from each peer.
28 #include "gnunet_util_lib.h"
29 #include "gnunet_testbed_service.h"
30 #include "gnunet_rps_service.h"
36 * How many peers do we start?
41 * How long do we run the test?
43 #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 40)
47 * Different tests to run
49 #define SINGLE_REQUEST 1
50 #define DELAYED_REQUESTS 2
53 #define SINGLE_PEER_SEED 5
54 #define SEED_REQUEST 6
55 #define REQUEST_CANCEL 7
59 * What test are we running?
61 unsigned int test_type = 0;
65 * Portion of malicious peers
67 static double portion = .1;
70 * Type of malicious peer to test
72 static unsigned int mal_type = 0;
76 * Information we track for each peer.
86 * Handle for RPS connect operation.
88 struct GNUNET_TESTBED_Operation *op;
91 * Handle to RPS service.
93 struct GNUNET_RPS_Handle *rps_handle;
98 struct GNUNET_PeerIdentity *peer_id;
101 * A request handle to check for an request
103 struct GNUNET_RPS_Request_Handle *req_handle;
108 struct GNUNET_PeerIdentity *rec_ids;
111 * Number of received PeerIDs
113 unsigned int num_rec_ids;
118 * Information for all the peers.
120 static struct RPSPeer rps_peers[NUM_PEERS];
125 static struct GNUNET_PeerIdentity rps_peer_ids[NUM_PEERS];
128 * Return value from 'main'.
134 * Test the success of a single test
137 evaluate (struct RPSPeer *loc_rps_peers,
138 unsigned int num_loc_rps_peers,
139 unsigned int expected_recv)
144 tmp_ok = (1 == loc_rps_peers[0].num_rec_ids);
146 for (i = 0 ; i < num_loc_rps_peers ; i++)
148 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
149 "%u. peer [%s] received %u of %u expected peer_ids: %i\n",
151 GNUNET_i2s (loc_rps_peers[i].peer_id),
152 loc_rps_peers[i].num_rec_ids,
154 (1 == loc_rps_peers[i].num_rec_ids));
155 tmp_ok &= (1 == loc_rps_peers[i].num_rec_ids);
157 return tmp_ok? 0 : 1;
162 * Task run on timeout to shut everything down.
165 shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
169 for (i=0;i<NUM_PEERS;i++)
170 GNUNET_TESTBED_operation_done (rps_peers[i].op);
171 GNUNET_SCHEDULER_shutdown ();
176 * Callback to call when network size estimate is updated.
179 * @param timestamp server timestamp
180 * @param estimate the value of the current network size estimate
181 * @param std_dev standard deviation (rounded down to nearest integer)
182 * of the size estimation values seen
186 handle_reply (void *cls, uint64_t n, const struct GNUNET_PeerIdentity *recv_peers)
188 struct RPSPeer *rps_peer = (struct RPSPeer *) cls;
191 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
192 "[%s] got %" PRIu64 " peers:\n",
193 GNUNET_i2s (rps_peer->peer_id),
196 for (i = 0 ; i < n ; i++)
198 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
201 GNUNET_i2s (&recv_peers[i]));
203 GNUNET_array_append (rps_peer->rec_ids, rps_peer->num_rec_ids, recv_peers[i]);
209 * (Randomly) request random peers.
212 request_peers (void *cls,
213 const struct GNUNET_SCHEDULER_TaskContext *tc)
215 struct RPSPeer *rps_peer = (struct RPSPeer *) cls;
217 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
218 "Requesting one peer\n");
220 (void) GNUNET_RPS_request_peers (rps_peer->rps_handle, 1, handle_reply, rps_peer);
221 //rps_peer->req_handle = GNUNET_RPS_request_peers (rps_peer->rps_handle, 1, handle_reply, rps_peer);
229 seed_peers (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
232 struct RPSPeer *peer = (struct RPSPeer *) cls;
235 // TODO if malicious don't seed mal peers
236 amount = round (.5 * NUM_PEERS);
238 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Seeding peers:\n");
239 for (i = 0 ; i < amount ; i++)
240 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Seeding %u. peer: %s\n",
242 GNUNET_i2s (&rps_peer_ids[i]));
244 GNUNET_RPS_seed_ids (peer->rps_handle, amount, rps_peer_ids);
249 * Get the id of peer i.
252 info_cb (void *cb_cls,
253 struct GNUNET_TESTBED_Operation *op,
254 const struct GNUNET_TESTBED_PeerInformation *pinfo,
257 unsigned int i = *((unsigned int *) cb_cls);
259 if (NULL == pinfo || NULL != emsg)
261 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Got Error: %s\n", emsg);
265 GNUNET_free (cb_cls);
267 rps_peer_ids[i] = *(pinfo->result.id);
268 rps_peers[i].peer_id = &rps_peer_ids[i];
269 rps_peers[i].rec_ids = NULL;
270 rps_peers[i].num_rec_ids = 0;
276 * Callback to be called when RPS service connect operation is completed
278 * @param cls the callback closure from functions generating an operation
279 * @param op the operation that has been finished
280 * @param ca_result the RPS service handle returned from rps_connect_adapter
281 * @param emsg error message in case the operation has failed; will be NULL if
282 * operation has executed successfully.
285 rps_connect_complete_cb (void *cls,
286 struct GNUNET_TESTBED_Operation *op,
290 struct RPSPeer *rps_peer = cls;
291 struct GNUNET_RPS_Handle *rps = ca_result;
292 //struct GNUNET_RPS_Request_Handle *req_handle;
293 uint32_t num_mal_peers;
295 rps_peer->rps_handle = rps;
297 GNUNET_assert (op == rps_peer->op);
300 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
301 "Failed to connect to RPS service: %s\n",
304 GNUNET_SCHEDULER_shutdown ();
308 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Started client successfully\n");
310 #ifdef ENABLE_MALICIOUS
314 GNUNET_assert (1 >= portion
316 num_mal_peers = round (portion * NUM_PEERS);
318 if (rps_peer->index >= num_mal_peers)
319 { /* It's useless to ask a malicious peer about a random sample -
321 (void) GNUNET_RPS_request_peers (rps, 1, handle_reply, NULL);
325 #endif /* ENABLE_MALICIOUS */
327 if (SINGLE_REQUEST == test_type)
329 //(void) GNUNET_RPS_request_peers (rps, 1, handle_reply, NULL);
330 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5),
331 request_peers, rps_peer);
333 else if (DELAYED_REQUESTS == test_type)
335 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5),
336 request_peers, rps_peer);
337 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 10),
338 request_peers, rps_peer);
340 else if (SEED == test_type)
342 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 10),
343 seed_peers, rps_peer);
345 else if (SEED_BIG == test_type)
347 // TODO test seeding > GNUNET_SERVER_MAX_MESSAGE_SIZE peers
349 else if (SINGLE_PEER_SEED == test_type)
353 else if (SEED_REQUEST == test_type)
355 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 2),
356 seed_peers, rps_peer);
357 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 15),
358 request_peers, rps_peer);
360 else if (REQUEST_CANCEL == test_type)
368 * Adapter function called to establish a connection to
372 * @param cfg configuration of the peer to connect to; will be available until
373 * GNUNET_TESTBED_operation_done() is called on the operation returned
374 * from GNUNET_TESTBED_service_connect()
375 * @return service handle to return in 'op_result', NULL on error
378 rps_connect_adapter (void *cls,
379 const struct GNUNET_CONFIGURATION_Handle *cfg)
381 struct GNUNET_RPS_Handle *h;
382 #ifdef ENABLE_MALICIOUS
383 uint32_t num_mal_peers;
384 struct RPSPeer *rps_peer = (struct RPSPeer *) cls;
385 #endif /* ENABLE_MALICIOUS */
387 h = GNUNET_RPS_connect (cfg);
389 #ifdef ENABLE_MALICIOUS
390 GNUNET_assert (1 >= portion
392 num_mal_peers = round (portion * NUM_PEERS);
394 if (rps_peer->index < num_mal_peers)
396 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
397 "%u. peer [%s] of %" PRIu32 " malicious peers turning malicious\n",
399 GNUNET_i2s (rps_peer->peer_id),
402 GNUNET_RPS_act_malicious (h, mal_type, num_mal_peers, rps_peer_ids);
404 #endif /* ENABLE_MALICIOUS */
411 * Adapter function called to destroy connection to
415 * @param op_result service handle returned from the connect adapter
418 rps_disconnect_adapter (void *cls,
421 struct GNUNET_RPS_Handle *h = op_result;
422 GNUNET_RPS_disconnect (h);
427 * Actual "main" function for the testcase.
430 * @param h the run handle
431 * @param num_peers number of peers in 'peers'
432 * @param peers handle to peers run in the testbed
433 * @param links_succeeded the number of overlay link connection attempts that
435 * @param links_failed the number of overlay link connection attempts that
440 struct GNUNET_TESTBED_RunHandle *h,
441 unsigned int num_peers,
442 struct GNUNET_TESTBED_Peer **peers,
443 unsigned int links_succeeded,
444 unsigned int links_failed)
449 for (i = 0 ; i < NUM_PEERS ; i++)
451 tmp_i = GNUNET_new (unsigned int);
454 (void) GNUNET_TESTBED_peer_get_information (peers[i],
455 GNUNET_TESTBED_PIT_IDENTITY,
460 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
464 GNUNET_assert (NUM_PEERS == num_peers);
465 for (i = 0 ; i < num_peers ; i++)
467 rps_peers[i].index = i;
469 GNUNET_TESTBED_service_connect (&rps_peers[i],
472 &rps_connect_complete_cb,
474 &rps_connect_adapter,
475 &rps_disconnect_adapter,
478 GNUNET_SCHEDULER_add_delayed (TIMEOUT, &shutdown_task, NULL);
483 * Entry point for the testcase, sets up the testbed.
487 * @return 0 on success
490 main (int argc, char *argv[])
492 if (strstr (argv[0], "malicious_1") != NULL)
494 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Test malicious peer type 1\n");
497 else if (strstr (argv[0], "malicious_2") != NULL)
499 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Test malicious peer type 2\n");
502 else if (strstr (argv[0], "_single_req") != NULL)
504 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Test single request\n");
505 test_type = SINGLE_REQUEST;
507 else if (strstr (argv[0], "_delayed_reqs") != NULL)
509 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Test delayed requests\n");
510 test_type = DELAYED_REQUESTS;
512 else if (strstr (argv[0], "_seed_big") != NULL)
514 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Test seeding (num_peers > GNUNET_SERVER_MAX_MESSAGE_SIZE)\n");
515 test_type = SEED_BIG;
517 else if (strstr (argv[0], "_single_peer_seed") != NULL)
519 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Test seeding and requesting on a single peer\n");
520 test_type = SINGLE_PEER_SEED;
522 else if (strstr (argv[0], "_seed_request") != NULL)
524 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Test seeding and requesting on multiple peers\n");
525 test_type = SEED_REQUEST;
527 else if (strstr (argv[0], "_seed") != NULL)
529 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Test seeding\n");
532 else if (strstr (argv[0], "_req_cancel") != NULL)
534 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Test cancelling a request\n");
535 test_type = REQUEST_CANCEL;
539 (void) GNUNET_TESTBED_test_run ("test-rps-multipeer",
545 unsigned int num_mal_peers;
548 num_mal_peers = NUM_PEERS * portion;
549 ok = evaluate (&rps_peers[num_mal_peers],
550 NUM_PEERS - (num_mal_peers),
553 else if (2 == mal_type)
555 num_mal_peers = NUM_PEERS * portion;
556 ok = evaluate (&rps_peers[num_mal_peers],
557 NUM_PEERS - (num_mal_peers),
560 else if (SINGLE_REQUEST == test_type)
562 ok = evaluate (rps_peers, NUM_PEERS, 1);
564 else if (SEED_REQUEST == test_type)
566 ok = evaluate (rps_peers, NUM_PEERS, 1);
572 /* end of test_rps_multipeer.c */