32bce40986a52b6e5ee836cf4cc401015260695a
[oweals/gnunet.git] / src / rps / test_rps.c
1 /*
2      This file is part of GNUnet.
3      Copyright (C) 2009, 2012 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 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.
26  */
27 #include "platform.h"
28 #include "gnunet_util_lib.h"
29 #include "gnunet_testbed_service.h"
30 #include "gnunet_rps_service.h"
31
32 #include <inttypes.h>
33
34
35 /**
36  * How many peers do we start?
37  */
38 uint32_t num_peers;
39
40 /**
41  * How long do we run the test?
42  */
43 //#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 30)
44 static struct GNUNET_TIME_Relative timeout;
45
46
47 /**
48  * Portion of malicious peers
49  */
50 static double portion = .1;
51
52 /**
53  * Type of malicious peer to test
54  */
55 static unsigned int mal_type = 0;
56
57 /**
58  * Handles to all of the running peers
59  */
60 static struct GNUNET_TESTBED_Peer **testbed_peers;
61
62
63 /**
64  * Operation map entry
65  */
66 struct OpListEntry
67 {
68   /**
69    * DLL next ptr
70    */
71   struct OpListEntry *next;
72
73   /**
74    * DLL prev ptr
75    */
76   struct OpListEntry *prev;
77
78   /**
79    * The testbed operation
80    */
81   struct GNUNET_TESTBED_Operation *op;
82
83   /**
84    * Depending on whether we start or stop NSE service at the peer set this to 1
85    * or -1
86    */
87   int delta;
88
89   /**
90    * Index of the regarding peer
91    */
92   unsigned int index;
93 };
94
95 /**
96  * OpList DLL head
97  */
98 static struct OpListEntry *oplist_head;
99
100 /**
101  * OpList DLL tail
102  */
103 static struct OpListEntry *oplist_tail;
104
105
106 /**
107  * Information we track for each peer.
108  */
109 struct RPSPeer
110 {
111   /**
112    * Index of the peer.
113    */
114   unsigned int index;
115
116   /**
117    * Handle for RPS connect operation.
118    */
119   struct GNUNET_TESTBED_Operation *op;
120
121   /**
122    * Handle to RPS service.
123    */
124   struct GNUNET_RPS_Handle *rps_handle;
125
126   /**
127    * ID of the peer.
128    */
129   struct GNUNET_PeerIdentity *peer_id;
130
131   /**
132    * A request handle to check for an request
133    */
134   //struct GNUNET_RPS_Request_Handle *req_handle;
135
136   /**
137    * Peer on- or offline?
138    */
139   int online;
140
141   /**
142    * Received PeerIDs
143    */
144   struct GNUNET_PeerIdentity *rec_ids;
145
146   /**
147    * Number of received PeerIDs
148    */
149   unsigned int num_rec_ids;
150 };
151
152
153 /**
154  * Information for all the peers.
155  */
156 static struct RPSPeer *rps_peers;
157
158 /**
159  * IDs of the peers.
160  */
161 static struct GNUNET_PeerIdentity *rps_peer_ids;
162
163 /**
164  * Number of online peers.
165  */
166 static unsigned int num_peers_online;
167
168 /**
169  * Return value from 'main'.
170  */
171 static int ok;
172
173
174 /**
175  * Identifier for the churn task that runs periodically
176  */
177 static struct GNUNET_SCHEDULER_Task *churn_task;
178
179
180 /**
181  * Called directly after connecting to the service
182  */
183 typedef void (*PreTest) (void *cls, struct GNUNET_RPS_Handle *h);
184
185 /**
186  * Called from within #rps_connect_complete_cb ()
187  * Executes functions to test the api/service
188  */
189 typedef void (*MainTest) (struct RPSPeer *rps_peer);
190
191 /**
192  * Called directly before disconnecting from the service
193  */
194 typedef void (*PostTest) (void *cls, struct GNUNET_RPS_Handle *h);
195
196 /**
197  * Function called after disconnect to evaluate test success
198  */
199 typedef int (*EvaluationCallback) (void);
200
201
202 /**
203  * Structure to define a single test
204  */
205 struct SingleTestRun
206 {
207   /**
208    * Name of the test
209    */
210   char *name;
211
212   /**
213    * Called directly after connecting to the service
214    */
215   PreTest pre_test;
216
217   /**
218    * Function to execute the functions to be tested
219    */
220   MainTest main_test;
221
222   /**
223    * Called directly before disconnecting from the service
224    */
225   PostTest post_test;
226
227   /**
228    * Function to evaluate the test results
229    */
230   EvaluationCallback eval_cb;
231 } cur_test_run;
232
233
234 /**
235  * Test the success of a single test
236  */
237 static int
238 evaluate (struct RPSPeer *loc_rps_peers,
239           unsigned int num_loc_rps_peers,
240           unsigned int expected_recv)
241 {
242   unsigned int i;
243   int tmp_ok;
244
245   tmp_ok = (1 == loc_rps_peers[0].num_rec_ids);
246
247   for (i = 0 ; i < num_loc_rps_peers ; i++)
248   {
249     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
250                 "%u. peer [%s] received %u of %u expected peer_ids: %i\n",
251                 i,
252                 GNUNET_i2s (loc_rps_peers[i].peer_id),
253                 loc_rps_peers[i].num_rec_ids,
254                 expected_recv,
255                 (1 == loc_rps_peers[i].num_rec_ids));
256     tmp_ok &= (1 == loc_rps_peers[i].num_rec_ids);
257   }
258   return tmp_ok? 0 : 1;
259 }
260
261
262 /**
263  * Creates an oplist entry and adds it to the oplist DLL
264  */
265 static struct OpListEntry *
266 make_oplist_entry ()
267 {
268   struct OpListEntry *entry;
269
270   entry = GNUNET_new (struct OpListEntry);
271   GNUNET_CONTAINER_DLL_insert_tail (oplist_head, oplist_tail, entry);
272   return entry;
273 }
274
275
276 /**
277  * Callback to be called when NSE service is started or stopped at peers
278  *
279  * @param cls NULL
280  * @param op the operation handle
281  * @param emsg NULL on success; otherwise an error description
282  */
283 static void
284 churn_cb (void *cls,
285           struct GNUNET_TESTBED_Operation *op,
286           const char *emsg)
287 {
288   // FIXME
289   struct OpListEntry *entry = cls;
290
291   GNUNET_TESTBED_operation_done (entry->op);
292   if (NULL != emsg)
293   {
294     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to start/stop RPS at a peer\n");
295     GNUNET_SCHEDULER_shutdown ();
296     return;
297   }
298   GNUNET_assert (0 != entry->delta);
299
300   num_peers_online += entry->delta;
301
302   if (0 > entry->delta)
303   { /* Peer hopefully just went offline */
304     if (GNUNET_YES != rps_peers[entry->index].online)
305     {
306       GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
307                   "peer %s was expected to go offline but is still marked as online\n",
308                   GNUNET_i2s (rps_peers[entry->index].peer_id));
309       GNUNET_break (0);
310     }
311     else
312     {
313       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
314                   "peer %s probably went offline as expected\n",
315                   GNUNET_i2s (rps_peers[entry->index].peer_id));
316     }
317     rps_peers[entry->index].online = GNUNET_NO;
318   }
319
320   else if (0 < entry->delta)
321   { /* Peer hopefully just went online */
322     if (GNUNET_NO != rps_peers[entry->index].online)
323     {
324       GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
325                   "peer %s was expected to go online but is still marked as offline\n",
326                   GNUNET_i2s (rps_peers[entry->index].peer_id));
327       GNUNET_break (0);
328     }
329     else
330     {
331       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
332                   "peer %s probably went online as expected\n",
333                   GNUNET_i2s (rps_peers[entry->index].peer_id));
334     }
335     rps_peers[entry->index].online = GNUNET_YES;
336   }
337
338   GNUNET_CONTAINER_DLL_remove (oplist_head, oplist_tail, entry);
339   GNUNET_free (entry);
340   //if (num_peers_in_round[current_round] == peers_running)
341   //  run_round ();
342 }
343
344
345 /**
346  * Task run on timeout to shut everything down.
347  */
348 static void
349 shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
350 {
351   unsigned int i;
352
353   if (NULL != churn_task)
354     GNUNET_SCHEDULER_cancel (churn_task);
355
356   for (i = 0 ; i < num_peers ; i++)
357     GNUNET_TESTBED_operation_done (rps_peers[i].op);
358   GNUNET_SCHEDULER_shutdown ();
359 }
360
361
362 /**
363  * Callback to call on receipt of a reply
364  *
365  * @param cls closure
366  * @param n number of peers
367  * @param recv_peers the received peers
368  */
369 static void
370 handle_reply (void *cls, uint64_t n, const struct GNUNET_PeerIdentity *recv_peers)
371 {
372   struct RPSPeer *rps_peer = (struct RPSPeer *) cls;
373   unsigned int i;
374
375   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
376               "[%s] got %" PRIu64 " peers:\n",
377               GNUNET_i2s (rps_peer->peer_id),
378               n);
379   
380   for (i = 0 ; i < n ; i++)
381   {
382     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
383                 "%u: %s\n",
384                 i,
385                 GNUNET_i2s (&recv_peers[i]));
386
387     GNUNET_array_append (rps_peer->rec_ids, rps_peer->num_rec_ids, recv_peers[i]);
388   }
389 }
390
391
392 /**
393  * Request random peers.
394  */
395   void
396 request_peers (void *cls,
397                const struct GNUNET_SCHEDULER_TaskContext *tc)
398 {
399   struct RPSPeer *rps_peer = (struct RPSPeer *) cls;
400
401   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
402               "Requesting one peer\n");
403
404   (void) GNUNET_RPS_request_peers (rps_peer->rps_handle, 1, handle_reply, rps_peer);
405   //rps_peer->req_handle = GNUNET_RPS_request_peers (rps_peer->rps_handle, 1, handle_reply, rps_peer);
406 }
407
408
409 /**
410  * Seed peers.
411  */
412   void
413 seed_peers (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
414 {
415   unsigned int amount;
416   struct RPSPeer *peer = (struct RPSPeer *) cls;
417   unsigned int i;
418
419   // TODO if malicious don't seed mal peers
420   amount = round (.5 * num_peers);
421
422   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Seeding peers:\n");
423   for (i = 0 ; i < amount ; i++)
424     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Seeding %u. peer: %s\n",
425                 i,
426                 GNUNET_i2s (&rps_peer_ids[i]));
427
428   GNUNET_RPS_seed_ids (peer->rps_handle, amount, rps_peer_ids);
429 }
430
431
432 /**
433  * Get the id of peer i.
434  */
435   void
436 info_cb (void *cb_cls,
437          struct GNUNET_TESTBED_Operation *op,
438          const struct GNUNET_TESTBED_PeerInformation *pinfo,
439          const char *emsg)
440 {
441   struct OpListEntry *entry = (struct OpListEntry *) cb_cls;
442
443   if (NULL == pinfo || NULL != emsg)
444   {
445     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Got Error: %s\n", emsg);
446     return;
447   }
448
449   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
450               "Peer %u is %s\n",
451               entry->index,
452               GNUNET_i2s (pinfo->result.id));
453
454   rps_peer_ids[entry->index] = *(pinfo->result.id);
455   rps_peers[entry->index].peer_id = &rps_peer_ids[entry->index];
456   rps_peers[entry->index].rec_ids = NULL;
457   rps_peers[entry->index].num_rec_ids = 0;
458
459   GNUNET_TESTBED_operation_done (entry->op);
460
461   GNUNET_CONTAINER_DLL_remove (oplist_head, oplist_tail, entry);
462   GNUNET_free (entry);
463 }
464
465
466 /**
467  * Callback to be called when RPS service connect operation is completed
468  *
469  * @param cls the callback closure from functions generating an operation
470  * @param op the operation that has been finished
471  * @param ca_result the RPS service handle returned from rps_connect_adapter
472  * @param emsg error message in case the operation has failed; will be NULL if
473  *          operation has executed successfully.
474  */
475 static void
476 rps_connect_complete_cb (void *cls,
477                          struct GNUNET_TESTBED_Operation *op,
478                          void *ca_result,
479                          const char *emsg)
480 {
481   struct RPSPeer *rps_peer = cls;
482   struct GNUNET_RPS_Handle *rps = ca_result;
483
484   rps_peer->rps_handle = rps;
485   rps_peer->online = GNUNET_YES;
486   num_peers_online++;
487
488   GNUNET_assert (op == rps_peer->op);
489   if (NULL != emsg)
490   {
491     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
492                 "Failed to connect to RPS service: %s\n",
493                 emsg);
494     ok = 1;
495     GNUNET_SCHEDULER_shutdown ();
496     return;
497   }
498
499   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Started client successfully\n");
500
501   cur_test_run.main_test (rps_peer);
502 }
503
504
505 /**
506  * Adapter function called to establish a connection to
507  * the RPS service.
508  *
509  * @param cls closure
510  * @param cfg configuration of the peer to connect to; will be available until
511  *          GNUNET_TESTBED_operation_done() is called on the operation returned
512  *          from GNUNET_TESTBED_service_connect()
513  * @return service handle to return in 'op_result', NULL on error
514  */
515 static void *
516 rps_connect_adapter (void *cls,
517                                  const struct GNUNET_CONFIGURATION_Handle *cfg)
518 {
519   struct GNUNET_RPS_Handle *h;
520
521   h = GNUNET_RPS_connect (cfg);
522
523   if (NULL != cur_test_run.pre_test)
524     cur_test_run.pre_test (cls, h);
525
526   return h;
527 }
528
529
530 /**
531  * Adapter function called to destroy connection to
532  * RPS service.
533  *
534  * @param cls closure
535  * @param op_result service handle returned from the connect adapter
536  */
537 static void
538 rps_disconnect_adapter (void *cls,
539                                           void *op_result)
540 {
541   struct GNUNET_RPS_Handle *h = op_result;
542   GNUNET_RPS_disconnect (h);
543 }
544
545
546 /***********************************************************************
547  * Definition of tests
548 ***********************************************************************/
549
550 static int
551 default_eval_cb (void)
552 {
553   return evaluate (rps_peers, num_peers, 1);
554 }
555
556 static int
557 no_eval (void)
558 {
559   return 1;
560 }
561
562 /***********************************
563  * MALICIOUS
564 ***********************************/
565 static void
566 mal_pre (void *cls, struct GNUNET_RPS_Handle *h)
567 {
568   #ifdef ENABLE_MALICIOUS
569   uint32_t num_mal_peers;
570   struct RPSPeer *rps_peer = (struct RPSPeer *) cls;
571
572   GNUNET_assert (1 >= portion
573                  && 0 <  portion);
574   num_mal_peers = round (portion * num_peers);
575
576   if (rps_peer->index < num_mal_peers)
577   {
578     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
579                 "%u. peer [%s] of %" PRIu32 " malicious peers turning malicious\n",
580                 rps_peer->index,
581                 GNUNET_i2s (rps_peer->peer_id),
582                 num_mal_peers);
583
584     GNUNET_RPS_act_malicious (h, mal_type, num_mal_peers, rps_peer_ids);
585   }
586   #endif /* ENABLE_MALICIOUS */
587 }
588
589 static void
590 mal_cb (struct RPSPeer *rps_peer)
591 {
592   uint32_t num_mal_peers;
593
594   #ifdef ENABLE_MALICIOUS
595   GNUNET_assert (1 >= portion
596                  && 0 <  portion);
597   num_mal_peers = round (portion * num_peers);
598
599   if (rps_peer->index >= num_mal_peers)
600   { /* It's useless to ask a malicious peer about a random sample -
601        it's not sampling */
602     GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 2),
603                                   seed_peers, rps_peer);
604     GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 10),
605                                   request_peers, rps_peer);
606   }
607   #endif /* ENABLE_MALICIOUS */
608 }
609
610 static int
611 mal_eval (void)
612 {
613   unsigned int num_mal_peers;
614
615   num_mal_peers = round (num_peers * portion);
616   return evaluate (&rps_peers[num_mal_peers],
617                    num_peers - (num_mal_peers),
618                    1);
619 }
620
621
622 /***********************************
623  * SINGLE_REQUEST
624 ***********************************/
625 static void
626 single_req_cb (struct RPSPeer *rps_peer)
627 {
628   GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5),
629                                 request_peers, rps_peer);
630 }
631
632 /***********************************
633  * DELAYED_REQUESTS
634 ***********************************/
635 static void
636 delay_req_cb (struct RPSPeer *rps_peer)
637 {
638   GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5),
639                                 request_peers, rps_peer);
640   GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 10),
641                                 request_peers, rps_peer);
642 }
643
644 /***********************************
645  * SEED
646 ***********************************/
647 static void
648 seed_cb (struct RPSPeer *rps_peer)
649 {
650   GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 10),
651                                 seed_peers, rps_peer);
652 }
653
654 /***********************************
655  * SEED_BIG
656 ***********************************/
657 static void
658 seed_big_cb (struct RPSPeer *rps_peer)
659 {
660   // TODO test seeding > GNUNET_SERVER_MAX_MESSAGE_SIZE peers
661 }
662
663 /***********************************
664  * SINGLE_PEER_SEED
665 ***********************************/
666 static void
667 single_peer_seed_cb (struct RPSPeer *rps_peer)
668 {
669   // TODO
670 }
671
672 /***********************************
673  * SEED_REQUEST
674 ***********************************/
675 static void
676 seed_req_cb (struct RPSPeer *rps_peer)
677 {
678   GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 2),
679                                 seed_peers, rps_peer);
680   GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 15),
681                                 request_peers, rps_peer);
682 }
683
684 //TODO start big mal
685
686 /***********************************
687  * REQUEST_CANCEL
688 ***********************************/
689 static void
690 req_cancel_cb (struct RPSPeer *rps_peer)
691 {
692   // TODO
693 }
694
695 /***********************************
696  * PROFILER
697 ***********************************/
698 static void
699 churn (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
700 {
701   struct OpListEntry *entry;
702   unsigned int i;
703   unsigned int j;
704   double portion_online;
705   unsigned int *permut;
706   double prob_go_offline;
707   double portion_go_online;
708   double portion_go_offline;
709   uint32_t prob;
710
711   /* Compute the probability for an online peer to go offline
712    * this round */
713   portion_online = num_peers_online * 1.0 / num_peers;
714   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
715               "Portion online: %f\n",
716               portion_online);
717   portion_go_online = ((1 - portion_online) * .5 * .66);
718   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
719               "Portion that should go online: %f\n",
720               portion_go_online);
721   portion_go_offline = (portion_online + portion_go_online) - .75;
722   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
723               "Portion that probably goes offline: %f\n",
724               portion_go_offline);
725   prob_go_offline = portion_go_offline / (portion_online * .5);
726   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
727               "Probability of a selected online peer to go offline: %f\n",
728               prob_go_offline);
729
730   permut = GNUNET_CRYPTO_random_permute (GNUNET_CRYPTO_QUALITY_WEAK,
731                                          (unsigned int) num_peers);
732
733   /* Go over 50% randomly chosen peers */
734   for (i = 0 ; i < .5 * num_peers ; i++)
735   {
736     j = permut[i];
737
738     /* If online, shut down with certain probability */
739     if (GNUNET_YES == rps_peers[j].online)
740     {
741       prob = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
742                                        UINT32_MAX);
743       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
744                   "%u. selected peer (%u: %s) is online.\n",
745                   i,
746                   j,
747                   GNUNET_i2s (rps_peers[j].peer_id));
748       if (prob < prob_go_offline * UINT32_MAX)
749       {
750         GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
751                     "%s goes offline\n",
752                     GNUNET_i2s (rps_peers[j].peer_id));
753
754         entry = make_oplist_entry ();
755         entry->delta = -1;
756         entry->index = j;
757         entry->op = GNUNET_TESTBED_peer_manage_service (NULL,
758                                                         testbed_peers[j],
759                                                         "rps",
760                                                         &churn_cb,
761                                                         entry,
762                                                         0);
763       }
764    }
765
766    /* If offline, restart with certain probability */
767    else if (GNUNET_NO == rps_peers[j].online)
768    {
769      prob = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
770                                       UINT32_MAX);
771      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
772                  "%u. selected peer (%u: %s) is offline.\n",
773                  i,
774                  j,
775                  GNUNET_i2s (rps_peers[j].peer_id));
776      if (prob < .66 * UINT32_MAX)
777      {
778        GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
779                    "%s goes online\n",
780                    GNUNET_i2s (rps_peers[j].peer_id));
781
782        entry = make_oplist_entry ();
783        entry->delta = 1;
784        entry->index = j;
785        entry->op = GNUNET_TESTBED_peer_manage_service (NULL,
786                                                        testbed_peers[j],
787                                                        "rps",
788                                                        &churn_cb,
789                                                        entry,
790                                                        1);
791      }
792    }
793   }
794
795   churn_task = GNUNET_SCHEDULER_add_delayed (
796         GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 2),
797         churn,
798         NULL);
799 }
800
801
802 static void
803 profiler_pre (void *cls, struct GNUNET_RPS_Handle *h)
804 {
805   //churn_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS,
806   //                                                                          10),
807   //                                           churn, NULL);
808   mal_pre (cls, h);
809
810   if (NULL == churn_task)
811   {
812     churn_task = GNUNET_SCHEDULER_add_delayed (
813           GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 10),
814           churn,
815           NULL);
816   }
817 }
818
819 static void
820 profiler_cb (struct RPSPeer *rps_peer)
821 {
822   // We're not requesting peers
823   // TODO maybe seed
824 }
825
826
827 /***********************************************************************
828  * /Definition of tests
829 ***********************************************************************/
830
831
832 /**
833  * Actual "main" function for the testcase.
834  *
835  * @param cls closure
836  * @param h the run handle
837  * @param n_peers number of peers in 'peers'
838  * @param peers handle to peers run in the testbed
839  * @param links_succeeded the number of overlay link connection attempts that
840  *          succeeded
841  * @param links_failed the number of overlay link connection attempts that
842  *          failed
843  */
844 static void
845 run (void *cls,
846      struct GNUNET_TESTBED_RunHandle *h,
847      unsigned int n_peers,
848      struct GNUNET_TESTBED_Peer **peers,
849      unsigned int links_succeeded,
850      unsigned int links_failed)
851 {
852   unsigned int i;
853   struct OpListEntry *entry;
854
855   testbed_peers = peers;
856   num_peers_online = 0;
857
858   for (i = 0 ; i < num_peers ; i++)
859   {
860     entry = make_oplist_entry ();
861     entry->index = i;
862     entry->op = GNUNET_TESTBED_peer_get_information (peers[i],
863                                                      GNUNET_TESTBED_PIT_IDENTITY,
864                                                      &info_cb,
865                                                      entry);
866   }
867
868
869   // This seems not to work
870   //if (NULL != strstr (cur_test_run.name, "profiler"))
871   //{
872   //  churn_task = GNUNET_SCHEDULER_add_delayed (
873   //      GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5),
874   //      churn,
875   //      NULL);
876   //}
877
878   GNUNET_assert (num_peers == n_peers);
879   for (i = 0 ; i < n_peers ; i++)
880   {
881     rps_peers[i].index = i;
882     rps_peers[i].op =
883       GNUNET_TESTBED_service_connect (&rps_peers[i],
884                                                                           peers[i],
885                                                                           "rps",
886                                                                           &rps_connect_complete_cb,
887                                                                           &rps_peers[i],
888                                                                           &rps_connect_adapter,
889                                                                           &rps_disconnect_adapter,
890                                                                           &rps_peers[i]);
891   }
892
893   if (NULL != churn_task)
894     GNUNET_SCHEDULER_cancel (churn_task);
895
896   //GNUNET_SCHEDULER_add_delayed (TIMEOUT, &shutdown_task, NULL);
897   GNUNET_SCHEDULER_add_delayed (timeout, &shutdown_task, NULL);
898 }
899
900
901 /**
902  * Entry point for the testcase, sets up the testbed.
903  *
904  * @param argc unused
905  * @param argv unused
906  * @return 0 on success
907  */
908 int
909 main (int argc, char *argv[])
910 {
911   cur_test_run.pre_test = NULL;
912   cur_test_run.eval_cb = default_eval_cb;
913   churn_task = NULL;
914
915   if (strstr (argv[0], "malicious") != NULL)
916   {
917     cur_test_run.pre_test = mal_pre;
918     cur_test_run.main_test = mal_cb;
919     cur_test_run.eval_cb = mal_eval;
920
921     if (strstr (argv[0], "_1") != NULL)
922     {
923       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Test malicious peer type 1\n");
924       mal_type = 1;
925     }
926     else if (strstr (argv[0], "_2") != NULL)
927     {
928       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Test malicious peer type 2\n");
929       mal_type = 2;
930     }
931     else if (strstr (argv[0], "_3") != NULL)
932     {
933       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Test malicious peer type 3\n");
934       mal_type = 3;
935     }
936   }
937
938   else if (strstr (argv[0], "_single_req") != NULL)
939   {
940     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Test single request\n");
941     cur_test_run.main_test = single_req_cb;
942   }
943   else if (strstr (argv[0], "_delayed_reqs") != NULL)
944   {
945     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Test delayed requests\n");
946     cur_test_run.main_test = delay_req_cb;
947   }
948   else if (strstr (argv[0], "_seed_big") != NULL)
949   {
950     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Test seeding (num_peers > GNUNET_SERVER_MAX_MESSAGE_SIZE)\n");
951     cur_test_run.main_test = seed_big_cb;
952   }
953   else if (strstr (argv[0], "_single_peer_seed") != NULL)
954   {
955     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Test seeding and requesting on a single peer\n");
956     cur_test_run.main_test = single_peer_seed_cb;
957   }
958   else if (strstr (argv[0], "_seed_request") != NULL)
959   {
960     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Test seeding and requesting on multiple peers\n");
961     cur_test_run.main_test = seed_req_cb;
962   }
963   else if (strstr (argv[0], "_seed") != NULL)
964   {
965     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Test seeding\n");
966     cur_test_run.main_test = seed_cb;
967     cur_test_run.eval_cb = seed_eval;
968   }
969   else if (strstr (argv[0], "_req_cancel") != NULL)
970   {
971     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Test cancelling a request\n");
972     cur_test_run.main_test = req_cancel_cb;
973   }
974   else if (strstr (argv[0], "profiler") != NULL)
975   {
976     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "This is the profiler\n");
977     mal_type = 3;
978     cur_test_run.pre_test = profiler_pre;
979     cur_test_run.main_test = profiler_cb;
980     churn_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS,
981                                                                               10),
982                                                churn, NULL);
983   }
984
985   ok = 1;
986   (void) GNUNET_TESTBED_test_run ("test-rps-multipeer",
987                                   "test_rps.conf",
988                                   NUM_PEERS,
989                                   0, NULL, NULL,
990                                   &run, NULL);
991
992   if (NULL != churn_task)
993     GNUNET_SCHEDULER_cancel (churn_task);
994
995   return cur_test_run.eval_cb();
996 }
997
998 /* end of test_rps_multipeer.c */