rps tests: remove assertion
[oweals/gnunet.git] / src / rps / test_rps.c
1 /*
2      This file is part of GNUnet.
3      Copyright (C) 2009, 2012 GNUnet e.V.
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., 51 Franklin Street, Fifth Floor,
18      Boston, MA 02110-1301, USA.
19 */
20 /**
21  * @file rps/test_rps.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
31 #include "gnunet_rps_service.h"
32 #include "rps-test_util.h"
33 #include "gnunet-service-rps_sampler_elem.h"
34
35 #include <inttypes.h>
36
37
38 /**
39  * How many peers do we start?
40  */
41 static uint32_t num_peers;
42
43 /**
44  * How long do we run the test?
45  */
46 //#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 30)
47 static struct GNUNET_TIME_Relative timeout;
48
49
50 /**
51  * Portion of malicious peers
52  */
53 static double portion = .1;
54
55 /**
56  * Type of malicious peer to test
57  */
58 static unsigned int mal_type = 0;
59
60 /**
61  * Handles to all of the running peers
62  */
63 static struct GNUNET_TESTBED_Peer **testbed_peers;
64
65 /**
66  * @brief Indicates whether peer should go off- or online
67  */
68 enum PEER_ONLINE_DELTA {
69   /**
70    * @brief Indicates peer going online
71    */
72   PEER_GO_ONLINE = 1,
73   /**
74    * @brief Indicates peer going offline
75    */
76   PEER_GO_OFFLINE = -1,
77 };
78
79 /**
80  * Operation map entry
81  */
82 struct OpListEntry
83 {
84   /**
85    * DLL next ptr
86    */
87   struct OpListEntry *next;
88
89   /**
90    * DLL prev ptr
91    */
92   struct OpListEntry *prev;
93
94   /**
95    * The testbed operation
96    */
97   struct GNUNET_TESTBED_Operation *op;
98
99   /**
100    * Depending on whether we start or stop RPS service at the peer, set this to
101    * #PEER_GO_ONLINE (1) or #PEER_GO_OFFLINE (-1)
102    */
103   enum PEER_ONLINE_DELTA delta;
104
105   /**
106    * Index of the regarding peer
107    */
108   unsigned int index;
109 };
110
111 /**
112  * OpList DLL head
113  */
114 static struct OpListEntry *oplist_head;
115
116 /**
117  * OpList DLL tail
118  */
119 static struct OpListEntry *oplist_tail;
120
121
122 /**
123  * A pending reply: A request was sent and the reply is pending.
124  */
125 struct PendingReply
126 {
127   /**
128    * DLL next,prev ptr
129    */
130   struct PendingReply *next;
131   struct PendingReply *prev;
132
133   /**
134    * Handle to the request we are waiting for
135    */
136   struct GNUNET_RPS_Request_Handle *req_handle;
137
138   /**
139    * The peer that requested
140    */
141   struct RPSPeer *rps_peer;
142 };
143
144
145 /**
146  * A pending request: A request was not made yet but is scheduled for later.
147  */
148 struct PendingRequest
149 {
150   /**
151    * DLL next,prev ptr
152    */
153   struct PendingRequest *next;
154   struct PendingRequest *prev;
155
156   /**
157    * Handle to the request we are waiting for
158    */
159   struct GNUNET_SCHEDULER_Task *request_task;
160
161   /**
162    * The peer that requested
163    */
164   struct RPSPeer *rps_peer;
165 };
166
167
168 /**
169  * Information we track for each peer.
170  */
171 struct RPSPeer
172 {
173   /**
174    * Index of the peer.
175    */
176   unsigned int index;
177
178   /**
179    * Handle for RPS connect operation.
180    */
181   struct GNUNET_TESTBED_Operation *op;
182
183   /**
184    * Handle to RPS service.
185    */
186   struct GNUNET_RPS_Handle *rps_handle;
187
188   /**
189    * ID of the peer.
190    */
191   struct GNUNET_PeerIdentity *peer_id;
192
193   /**
194    * A request handle to check for an request
195    */
196   //struct GNUNET_RPS_Request_Handle *req_handle;
197
198   /**
199    * Peer on- or offline?
200    */
201   int online;
202
203   /**
204    * Number of Peer IDs to request during the whole test
205    */
206   unsigned int num_ids_to_request;
207
208   /**
209    * Pending requests DLL
210    */
211   struct PendingRequest *pending_req_head;
212   struct PendingRequest *pending_req_tail;
213
214   /**
215    * Number of pending requests
216    */
217   unsigned int num_pending_reqs;
218
219   /**
220    * Pending replies DLL
221    */
222   struct PendingReply *pending_rep_head;
223   struct PendingReply *pending_rep_tail;
224
225   /**
226    * Number of pending replies
227    */
228   unsigned int num_pending_reps;
229
230   /**
231    * Number of received PeerIDs
232    */
233   unsigned int num_recv_ids;
234
235   /**
236    * Pending operation on that peer
237    */
238   const struct OpListEntry *entry_op_manage;
239 };
240
241
242 /**
243  * Information for all the peers.
244  */
245 static struct RPSPeer *rps_peers;
246
247 /**
248  * Peermap to get the index of a given peer ID quick.
249  */
250 static struct GNUNET_CONTAINER_MultiPeerMap *peer_map;
251
252 /**
253  * IDs of the peers.
254  */
255 static struct GNUNET_PeerIdentity *rps_peer_ids;
256
257 /**
258  * ID of the targeted peer.
259  */
260 static struct GNUNET_PeerIdentity *target_peer;
261
262 /**
263  * ID of the peer that requests for the evaluation.
264  */
265 static struct RPSPeer *eval_peer;
266
267 /**
268  * Number of online peers.
269  */
270 static unsigned int num_peers_online;
271
272 /**
273  * Return value from 'main'.
274  */
275 static int ok;
276
277 /**
278  * Identifier for the churn task that runs periodically
279  */
280 static struct GNUNET_SCHEDULER_Task *shutdown_task;
281
282 /**
283  * Identifier for the churn task that runs periodically
284  */
285 static struct GNUNET_SCHEDULER_Task *churn_task;
286
287 /**
288  * Called to initialise the given RPSPeer
289  */
290 typedef void (*InitPeer) (struct RPSPeer *rps_peer);
291
292 /**
293  * @brief Called directly after connecting to the service
294  *
295  * @param rps_peer Specific peer the function is called on
296  * @param h the handle to the rps service
297  */
298 typedef void (*PreTest) (struct RPSPeer *rps_peer, struct GNUNET_RPS_Handle *h);
299
300 /**
301  * @brief Executes functions to test the api/service for a given peer
302  *
303  * Called from within #rps_connect_complete_cb ()
304  * Implemented by #churn_test_cb, #profiler_cb, #mal_cb, #single_req_cb,
305  * #delay_req_cb, #seed_big_cb, #single_peer_seed_cb, #seed_cb, #req_cancel_cb
306  *
307  * @param rps_peer the peer the task runs on
308  */
309 typedef void (*MainTest) (struct RPSPeer *rps_peer);
310
311 /**
312  * Callback called once the requested random peers are available
313  */
314 typedef void (*ReplyHandle) (void *cls,
315                              uint64_t n,
316                              const struct GNUNET_PeerIdentity *recv_peers);
317
318 /**
319  * Called directly before disconnecting from the service
320  */
321 typedef void (*PostTest) (void *cls, struct GNUNET_RPS_Handle *h);
322
323 /**
324  * Function called after disconnect to evaluate test success
325  */
326 typedef int (*EvaluationCallback) (void);
327
328
329 /**
330  * Structure to define a single test
331  */
332 struct SingleTestRun
333 {
334   /**
335    * Name of the test
336    */
337   char *name;
338
339   /**
340    * Called with a single peer in order to initialise that peer
341    */
342   InitPeer init_peer;
343
344   /**
345    * Called directly after connecting to the service
346    */
347   PreTest pre_test;
348
349   /**
350    * Main function for each peer
351    */
352   MainTest main_test;
353
354   /**
355    * Callback called once the requested peers are available
356    */
357   ReplyHandle reply_handle;
358
359   /**
360    * Called directly before disconnecting from the service
361    */
362   PostTest post_test;
363
364   /**
365    * Function to evaluate the test results
366    */
367   EvaluationCallback eval_cb;
368
369   /**
370    * Request interval
371    */
372   uint32_t request_interval;
373
374   /**
375    * Number of Requests to make.
376    */
377   uint32_t num_requests;
378
379   /**
380    * Run with churn
381    */
382   int have_churn;
383 } cur_test_run;
384
385 /**
386  * Are we shutting down?
387  */
388 static int in_shutdown;
389
390 /**
391  * Append arguments to file
392  */
393 static void
394 tofile_ (const char *file_name, const char *line)
395 {
396   struct GNUNET_DISK_FileHandle *f;
397   /* char output_buffer[512]; */
398   size_t size;
399   /* int size; */
400   size_t size2;
401
402   if (NULL == (f = GNUNET_DISK_file_open (file_name,
403                                           GNUNET_DISK_OPEN_APPEND |
404                                           GNUNET_DISK_OPEN_WRITE |
405                                           GNUNET_DISK_OPEN_CREATE,
406                                           GNUNET_DISK_PERM_USER_READ |
407                                           GNUNET_DISK_PERM_USER_WRITE |
408                                           GNUNET_DISK_PERM_GROUP_READ |
409                                           GNUNET_DISK_PERM_OTHER_READ)))
410   {
411     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
412                 "Not able to open file %s\n",
413                 file_name);
414     return;
415   }
416   /* size = GNUNET_snprintf (output_buffer,
417                           sizeof (output_buffer),
418                           "%llu %s\n",
419                           GNUNET_TIME_absolute_get ().abs_value_us,
420                           line);
421   if (0 > size)
422   {
423     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
424                 "Failed to write string to buffer (size: %i)\n",
425                 size);
426     return;
427   } */
428
429   size = strlen (line) * sizeof (char);
430
431   size2 = GNUNET_DISK_file_write (f, line, size);
432   if (size != size2)
433   {
434     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
435                 "Unable to write to file! (Size: %lu, size2: %lu)\n",
436                 size,
437                 size2);
438     if (GNUNET_YES != GNUNET_DISK_file_close (f))
439     {
440       GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
441                   "Unable to close file\n");
442     }
443     return;
444   }
445
446   if (GNUNET_YES != GNUNET_DISK_file_close (f))
447   {
448     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
449                 "Unable to close file\n");
450   }
451 }
452
453 /**
454  * This function is used to facilitate writing important information to disk
455  */
456 #define tofile(file_name, ...) do {\
457   char tmp_buf[512];\
458     int size;\
459     size = GNUNET_snprintf(tmp_buf,sizeof(tmp_buf),__VA_ARGS__);\
460     if (0 > size)\
461       GNUNET_log (GNUNET_ERROR_TYPE_WARNING,\
462                      "Failed to create tmp_buf\n");\
463     else\
464       tofile_(file_name,tmp_buf);\
465   } while (0);
466
467
468 /**
469  * Write the ids and their according index in the given array to a file
470  * Unused
471  */
472 /* static void
473 ids_to_file (char *file_name,
474              struct GNUNET_PeerIdentity *peer_ids,
475              unsigned int num_peer_ids)
476 {
477   unsigned int i;
478
479   for (i=0 ; i < num_peer_ids ; i++)
480   {
481     to_file (file_name,
482              "%u\t%s",
483              i,
484              GNUNET_i2s_full (&peer_ids[i]));
485   }
486 } */
487
488 /**
489  * Test the success of a single test
490  */
491 static int
492 evaluate (void)
493 {
494   unsigned int i;
495   int tmp_ok;
496
497   tmp_ok = 1;
498
499   for (i = 0; i < num_peers; i++)
500   {
501     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
502         "%u. peer [%s] received %u of %u expected peer_ids: %i\n",
503         i,
504         GNUNET_i2s (rps_peers[i].peer_id),
505         rps_peers[i].num_recv_ids,
506         rps_peers[i].num_ids_to_request,
507         (rps_peers[i].num_ids_to_request == rps_peers[i].num_recv_ids));
508     tmp_ok &= (rps_peers[i].num_ids_to_request == rps_peers[i].num_recv_ids);
509   }
510   return tmp_ok? 0 : 1;
511 }
512
513
514 /**
515  * Creates an oplist entry and adds it to the oplist DLL
516  */
517 static struct OpListEntry *
518 make_oplist_entry ()
519 {
520   struct OpListEntry *entry;
521
522   entry = GNUNET_new (struct OpListEntry);
523   GNUNET_CONTAINER_DLL_insert_tail (oplist_head, oplist_tail, entry);
524   return entry;
525 }
526
527
528 /**
529  * Task run on timeout to shut everything down.
530  */
531 static void
532 shutdown_op (void *cls)
533 {
534   unsigned int i;
535
536   GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
537               "Shutdown task scheduled, going down.\n");
538   in_shutdown = GNUNET_YES;
539   if (NULL != churn_task)
540   {
541     GNUNET_SCHEDULER_cancel (churn_task);
542     churn_task = NULL;
543   }
544   for (i = 0; i < num_peers; i++)
545     if (NULL != rps_peers[i].op)
546       GNUNET_TESTBED_operation_done (rps_peers[i].op);
547   GNUNET_SCHEDULER_shutdown ();
548 }
549
550
551 /**
552  * Seed peers.
553  */
554 static void
555 seed_peers (void *cls)
556 {
557   struct RPSPeer *peer = cls;
558   unsigned int amount;
559   unsigned int i;
560
561   // TODO if malicious don't seed mal peers
562   amount = round (.5 * num_peers);
563
564   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Seeding peers:\n");
565   for (i = 0 ; i < amount ; i++)
566     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Seeding %u. peer: %s\n",
567                 i,
568                 GNUNET_i2s (&rps_peer_ids[i]));
569
570   GNUNET_RPS_seed_ids (peer->rps_handle, amount, rps_peer_ids);
571 }
572
573
574 /**
575  * Seed peers.
576  */
577 static void
578 seed_peers_big (void *cls)
579 {
580   struct RPSPeer *peer = cls;
581   unsigned int seed_msg_size;
582   uint32_t num_peers_max;
583   unsigned int amount;
584   unsigned int i;
585
586   seed_msg_size = 8; /* sizeof (struct GNUNET_RPS_CS_SeedMessage) */
587   num_peers_max = (GNUNET_MAX_MESSAGE_SIZE - seed_msg_size) /
588     sizeof (struct GNUNET_PeerIdentity);
589   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
590       "Peers that fit in one seed msg; %u\n",
591       num_peers_max);
592   amount = num_peers_max + (0.5 * num_peers_max);
593   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
594       "Seeding many (%u) peers:\n",
595       amount);
596   struct GNUNET_PeerIdentity ids_to_seed[amount];
597   for (i = 0; i < amount; i++)
598   {
599     ids_to_seed[i] = *peer->peer_id;
600     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Seeding %u. peer: %s\n",
601                 i,
602                 GNUNET_i2s (&ids_to_seed[i]));
603   }
604
605   GNUNET_RPS_seed_ids (peer->rps_handle, amount, ids_to_seed);
606 }
607
608 /**
609  * Get the id of peer i.
610  */
611   void
612 info_cb (void *cb_cls,
613          struct GNUNET_TESTBED_Operation *op,
614          const struct GNUNET_TESTBED_PeerInformation *pinfo,
615          const char *emsg)
616 {
617   struct OpListEntry *entry = (struct OpListEntry *) cb_cls;
618
619   if (GNUNET_YES == in_shutdown)
620   {
621     return;
622   }
623
624   if (NULL == pinfo || NULL != emsg)
625   {
626     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Got Error: %s\n", emsg);
627     GNUNET_TESTBED_operation_done (entry->op);
628     return;
629   }
630
631   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
632               "Peer %u is %s\n",
633               entry->index,
634               GNUNET_i2s (pinfo->result.id));
635
636   rps_peer_ids[entry->index] = *(pinfo->result.id);
637   rps_peers[entry->index].peer_id = &rps_peer_ids[entry->index];
638
639   GNUNET_assert (GNUNET_OK ==
640       GNUNET_CONTAINER_multipeermap_put (peer_map,
641         &rps_peer_ids[entry->index],
642         &rps_peers[entry->index],
643         GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
644   tofile ("/tmp/rps/peer_ids",
645            "%u\t%s\n",
646            entry->index,
647            GNUNET_i2s_full (&rps_peer_ids[entry->index]));
648
649   GNUNET_CONTAINER_DLL_remove (oplist_head, oplist_tail, entry);
650   GNUNET_TESTBED_operation_done (entry->op);
651   GNUNET_free (entry);
652 }
653
654
655 /**
656  * Callback to be called when RPS service connect operation is completed
657  *
658  * @param cls the callback closure from functions generating an operation
659  * @param op the operation that has been finished
660  * @param ca_result the RPS service handle returned from rps_connect_adapter
661  * @param emsg error message in case the operation has failed; will be NULL if
662  *          operation has executed successfully.
663  */
664 static void
665 rps_connect_complete_cb (void *cls,
666                          struct GNUNET_TESTBED_Operation *op,
667                          void *ca_result,
668                          const char *emsg)
669 {
670   struct RPSPeer *rps_peer = cls;
671   struct GNUNET_RPS_Handle *rps = ca_result;
672
673   if (GNUNET_YES == in_shutdown)
674   {
675     return;
676   }
677
678   rps_peer->rps_handle = rps;
679   rps_peer->online = GNUNET_YES;
680   num_peers_online++;
681
682   GNUNET_assert (op == rps_peer->op);
683   if (NULL != emsg)
684   {
685     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
686                 "Failed to connect to RPS service: %s\n",
687                 emsg);
688     ok = 1;
689     GNUNET_SCHEDULER_shutdown ();
690     return;
691   }
692
693   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Started client successfully\n");
694
695   cur_test_run.main_test (rps_peer);
696 }
697
698
699 /**
700  * Adapter function called to establish a connection to
701  * the RPS service.
702  *
703  * @param cls closure
704  * @param cfg configuration of the peer to connect to; will be available until
705  *          GNUNET_TESTBED_operation_done() is called on the operation returned
706  *          from GNUNET_TESTBED_service_connect()
707  * @return service handle to return in 'op_result', NULL on error
708  */
709 static void *
710 rps_connect_adapter (void *cls,
711                                  const struct GNUNET_CONFIGURATION_Handle *cfg)
712 {
713   struct GNUNET_RPS_Handle *h;
714
715   h = GNUNET_RPS_connect (cfg);
716
717   if (NULL != cur_test_run.pre_test)
718     cur_test_run.pre_test (cls, h);
719
720   return h;
721 }
722
723
724 /**
725  * Adapter function called to destroy connection to
726  * RPS service.
727  *
728  * @param cls closure
729  * @param op_result service handle returned from the connect adapter
730  */
731 static void
732 rps_disconnect_adapter (void *cls,
733                                           void *op_result)
734 {
735   struct RPSPeer *peer = cls;
736   struct GNUNET_RPS_Handle *h = op_result;
737   GNUNET_assert (NULL != peer);
738   GNUNET_RPS_disconnect (h);
739   peer->rps_handle = NULL;
740 }
741
742
743 /***********************************************************************
744  * Definition of tests
745 ***********************************************************************/
746
747 // TODO check whether tests can be stopped earlier
748 static int
749 default_eval_cb (void)
750 {
751   return evaluate ();
752 }
753
754 static int
755 no_eval (void)
756 {
757   return 0;
758 }
759
760 /**
761  * Initialise given RPSPeer
762  */
763 static void default_init_peer (struct RPSPeer *rps_peer)
764 {
765   rps_peer->num_ids_to_request = 1;
766 }
767
768 /**
769  * Callback to call on receipt of a reply
770  *
771  * @param cls closure
772  * @param n number of peers
773  * @param recv_peers the received peers
774  */
775 static void
776 default_reply_handle (void *cls,
777                       uint64_t n,
778                       const struct GNUNET_PeerIdentity *recv_peers)
779 {
780   struct RPSPeer *rps_peer;
781   struct PendingReply *pending_rep = (struct PendingReply *) cls;
782   unsigned int i;
783
784   rps_peer = pending_rep->rps_peer;
785   GNUNET_CONTAINER_DLL_remove (rps_peer->pending_rep_head,
786                                rps_peer->pending_rep_tail,
787                                pending_rep);
788   rps_peer->num_pending_reps--;
789   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
790               "[%s] got %" PRIu64 " peers:\n",
791               GNUNET_i2s (rps_peer->peer_id),
792               n);
793
794   for (i = 0; i < n; i++)
795   {
796     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
797                 "%u: %s\n",
798                 i,
799                 GNUNET_i2s (&recv_peers[i]));
800
801     rps_peer->num_recv_ids++;
802   }
803
804   if (0 == evaluate ())
805   {
806     GNUNET_assert (NULL != shutdown_task);
807     GNUNET_SCHEDULER_cancel (shutdown_task);
808     shutdown_task = GNUNET_SCHEDULER_add_now (&shutdown_op, NULL);
809     GNUNET_assert (NULL!= shutdown_task);
810   }
811 }
812
813 /**
814  * Request random peers.
815  */
816 static void
817 request_peers (void *cls)
818 {
819   struct PendingRequest *pending_req = cls;
820   struct RPSPeer *rps_peer;
821   struct PendingReply *pending_rep;
822
823   if (GNUNET_YES == in_shutdown)
824     return;
825   rps_peer = pending_req->rps_peer;
826   GNUNET_assert (1 <= rps_peer->num_pending_reqs);
827   GNUNET_CONTAINER_DLL_remove (rps_peer->pending_req_head,
828                                rps_peer->pending_req_tail,
829                                pending_req);
830   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
831               "Requesting one peer\n");
832   pending_rep = GNUNET_new (struct PendingReply);
833   pending_rep->rps_peer = rps_peer;
834   pending_rep->req_handle = GNUNET_RPS_request_peers (rps_peer->rps_handle,
835       1,
836       cur_test_run.reply_handle,
837       pending_rep);
838   GNUNET_CONTAINER_DLL_insert_tail (rps_peer->pending_rep_head,
839                                     rps_peer->pending_rep_tail,
840                                     pending_rep);
841   rps_peer->num_pending_reps++;
842   rps_peer->num_pending_reqs--;
843 }
844
845 static void
846 cancel_pending_req (struct PendingRequest *pending_req)
847 {
848   struct RPSPeer *rps_peer;
849
850   rps_peer = pending_req->rps_peer;
851   GNUNET_CONTAINER_DLL_remove (rps_peer->pending_req_head,
852                                rps_peer->pending_req_tail,
853                                pending_req);
854   rps_peer->num_pending_reqs--;
855   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
856               "Cancelling pending request\n");
857   GNUNET_SCHEDULER_cancel (pending_req->request_task);
858   GNUNET_free (pending_req);
859 }
860
861 static void
862 cancel_request (struct PendingReply *pending_rep)
863 {
864   struct RPSPeer *rps_peer;
865
866   rps_peer = pending_rep->rps_peer;
867   GNUNET_CONTAINER_DLL_remove (rps_peer->pending_rep_head,
868                                rps_peer->pending_rep_tail,
869                                pending_rep);
870   rps_peer->num_pending_reps--;
871   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
872               "Cancelling request\n");
873   GNUNET_RPS_request_cancel (pending_rep->req_handle);
874   GNUNET_free (pending_rep);
875 }
876
877 /**
878  * Cancel a request.
879  */
880 static void
881 cancel_request_cb (void *cls)
882 {
883   struct RPSPeer *rps_peer = cls;
884   struct PendingReply *pending_rep;
885
886   if (GNUNET_YES == in_shutdown)
887     return;
888   pending_rep = rps_peer->pending_rep_head;
889   GNUNET_assert (1 <= rps_peer->num_pending_reps);
890   cancel_request (pending_rep);
891 }
892
893
894 /**
895  * Schedule requests for peer @a rps_peer that have neither been scheduled, nor
896  * issued, nor replied
897  */
898 void
899 schedule_missing_requests (struct RPSPeer *rps_peer)
900 {
901   unsigned int i;
902   struct PendingRequest *pending_req;
903
904   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
905       "Scheduling %u - %u missing requests\n",
906       rps_peer->num_ids_to_request,
907       rps_peer->num_pending_reqs + rps_peer->num_pending_reps);
908   GNUNET_assert (rps_peer->num_pending_reqs + rps_peer->num_pending_reps <=
909       rps_peer->num_ids_to_request);
910   for (i = rps_peer->num_pending_reqs + rps_peer->num_pending_reps;
911        i < rps_peer->num_ids_to_request; i++)
912   {
913     pending_req = GNUNET_new (struct PendingRequest);
914     pending_req->rps_peer = rps_peer;
915     pending_req->request_task = GNUNET_SCHEDULER_add_delayed (
916         GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS,
917           cur_test_run.request_interval * i),
918         request_peers,
919         pending_req);
920     GNUNET_CONTAINER_DLL_insert_tail (rps_peer->pending_req_head,
921                                       rps_peer->pending_req_tail,
922                                       pending_req);
923     rps_peer->num_pending_reqs++;
924   }
925 }
926
927 void
928 cancel_pending_req_rep (struct RPSPeer *rps_peer)
929 {
930   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
931       "Cancelling all (pending) requests.\n");
932   while (NULL != rps_peer->pending_req_head)
933     cancel_pending_req (rps_peer->pending_req_head);
934   GNUNET_assert (0 == rps_peer->num_pending_reqs);
935   while (NULL != rps_peer->pending_rep_head)
936     cancel_request (rps_peer->pending_rep_head);
937   GNUNET_assert (0 == rps_peer->num_pending_reps);
938 }
939
940 /***********************************
941  * MALICIOUS
942 ***********************************/
943
944 /**
945  * Initialise only non-mal RPSPeers
946  */
947 static void mal_init_peer (struct RPSPeer *rps_peer)
948 {
949   if (rps_peer->index >= round (portion * num_peers))
950     rps_peer->num_ids_to_request = 1;
951 }
952
953
954 /**
955  * @brief Set peers to (non-)malicious before execution
956  *
957  * Of signature #PreTest
958  *
959  * @param rps_peer the peer to set (non-) malicious
960  * @param h the handle to the service
961  */
962 static void
963 mal_pre (struct RPSPeer *rps_peer, struct GNUNET_RPS_Handle *h)
964 {
965   #ifdef ENABLE_MALICIOUS
966   uint32_t num_mal_peers;
967
968   GNUNET_assert ( (1 >= portion) &&
969                   (0 <  portion) );
970   num_mal_peers = round (portion * num_peers);
971
972   if (rps_peer->index < num_mal_peers)
973   {
974     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
975                 "%u. peer [%s] of %" PRIu32 " malicious peers turning malicious\n",
976                 rps_peer->index,
977                 GNUNET_i2s (rps_peer->peer_id),
978                 num_mal_peers);
979
980     GNUNET_RPS_act_malicious (h, mal_type, num_mal_peers,
981                               rps_peer_ids, target_peer);
982   }
983   #endif /* ENABLE_MALICIOUS */
984 }
985
986 static void
987 mal_cb (struct RPSPeer *rps_peer)
988 {
989   uint32_t num_mal_peers;
990
991   if (GNUNET_YES == in_shutdown)
992   {
993     return;
994   }
995
996   #ifdef ENABLE_MALICIOUS
997   GNUNET_assert ( (1 >= portion) &&
998                   (0 <  portion) );
999   num_mal_peers = round (portion * num_peers);
1000
1001   if (rps_peer->index >= num_mal_peers)
1002   { /* It's useless to ask a malicious peer about a random sample -
1003        it's not sampling */
1004     GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 2),
1005                                   seed_peers, rps_peer);
1006     schedule_missing_requests (rps_peer);
1007   }
1008   #endif /* ENABLE_MALICIOUS */
1009 }
1010
1011
1012 /***********************************
1013  * SINGLE_REQUEST
1014 ***********************************/
1015 static void
1016 single_req_cb (struct RPSPeer *rps_peer)
1017 {
1018   if (GNUNET_YES == in_shutdown)
1019   {
1020     return;
1021   }
1022
1023   schedule_missing_requests (rps_peer);
1024 }
1025
1026 /***********************************
1027  * DELAYED_REQUESTS
1028 ***********************************/
1029 static void
1030 delay_req_cb (struct RPSPeer *rps_peer)
1031 {
1032   if (GNUNET_YES == in_shutdown)
1033   {
1034     return;
1035   }
1036
1037   schedule_missing_requests (rps_peer);
1038 }
1039
1040 /***********************************
1041  * SEED
1042 ***********************************/
1043 static void
1044 seed_cb (struct RPSPeer *rps_peer)
1045 {
1046   if (GNUNET_YES == in_shutdown)
1047   {
1048     return;
1049   }
1050
1051   GNUNET_SCHEDULER_add_delayed (
1052       GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 10),
1053       seed_peers, rps_peer);
1054 }
1055
1056 /***********************************
1057  * SEED_BIG
1058 ***********************************/
1059 static void
1060 seed_big_cb (struct RPSPeer *rps_peer)
1061 {
1062   if (GNUNET_YES == in_shutdown)
1063   {
1064     return;
1065   }
1066
1067   // TODO test seeding > GNUNET_MAX_MESSAGE_SIZE peers
1068   GNUNET_SCHEDULER_add_delayed (
1069       GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 2),
1070       seed_peers_big, rps_peer);
1071 }
1072
1073 /***********************************
1074  * SINGLE_PEER_SEED
1075 ***********************************/
1076 static void
1077 single_peer_seed_cb (struct RPSPeer *rps_peer)
1078 {
1079   // TODO
1080 }
1081
1082 /***********************************
1083  * SEED_REQUEST
1084 ***********************************/
1085 static void
1086 seed_req_cb (struct RPSPeer *rps_peer)
1087 {
1088   if (GNUNET_YES == in_shutdown)
1089   {
1090     return;
1091   }
1092
1093   GNUNET_SCHEDULER_add_delayed (
1094       GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 2),
1095       seed_peers, rps_peer);
1096   schedule_missing_requests (rps_peer);
1097 }
1098
1099 //TODO start big mal
1100
1101 /***********************************
1102  * REQUEST_CANCEL
1103 ***********************************/
1104 static void
1105 req_cancel_cb (struct RPSPeer *rps_peer)
1106 {
1107   if (GNUNET_YES == in_shutdown)
1108   {
1109     return;
1110   }
1111
1112   schedule_missing_requests (rps_peer);
1113   GNUNET_SCHEDULER_add_delayed (
1114       GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS,
1115                                      (cur_test_run.request_interval + 1)),
1116       cancel_request_cb, rps_peer);
1117 }
1118
1119 /***********************************
1120  * CHURN
1121 ***********************************/
1122
1123 static void
1124 churn (void *cls);
1125
1126 /**
1127  * @brief Starts churn
1128  *
1129  * Has signature of #MainTest
1130  *
1131  * This is not implemented too nicely as this is called for each peer, but we
1132  * only need to call it once. (Yes we check that we only schedule the task
1133  * once.)
1134  *
1135  * @param rps_peer The peer it's called for
1136  */
1137 static void
1138 churn_test_cb (struct RPSPeer *rps_peer)
1139 {
1140   if (GNUNET_YES == in_shutdown)
1141   {
1142     return;
1143   }
1144
1145   /* Start churn */
1146   if (GNUNET_YES == cur_test_run.have_churn && NULL == churn_task)
1147   {
1148     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1149                 "Starting churn task\n");
1150     churn_task = GNUNET_SCHEDULER_add_delayed (
1151           GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5),
1152           churn,
1153           NULL);
1154   } else {
1155     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1156                 "Not starting churn task\n");
1157   }
1158
1159   schedule_missing_requests (rps_peer);
1160 }
1161
1162 /***********************************
1163  * PROFILER
1164 ***********************************/
1165
1166 /**
1167  * Callback to be called when RPS service is started or stopped at peers
1168  *
1169  * @param cls NULL
1170  * @param op the operation handle
1171  * @param emsg NULL on success; otherwise an error description
1172  */
1173 static void
1174 churn_cb (void *cls,
1175           struct GNUNET_TESTBED_Operation *op,
1176           const char *emsg)
1177 {
1178   // FIXME
1179   struct OpListEntry *entry = cls;
1180
1181   if (GNUNET_YES == in_shutdown)
1182   {
1183     return;
1184   }
1185
1186   GNUNET_TESTBED_operation_done (entry->op);
1187   if (NULL != emsg)
1188   {
1189     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to start/stop RPS at a peer\n");
1190     GNUNET_SCHEDULER_shutdown ();
1191     return;
1192   }
1193   GNUNET_assert (0 != entry->delta);
1194
1195   num_peers_online += entry->delta;
1196
1197   if (PEER_GO_OFFLINE == entry->delta)
1198   { /* Peer hopefully just went offline */
1199     if (GNUNET_YES != rps_peers[entry->index].online)
1200     {
1201       GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1202                   "peer %s was expected to go offline but is still marked as online\n",
1203                   GNUNET_i2s (rps_peers[entry->index].peer_id));
1204       GNUNET_break (0);
1205     }
1206     else
1207     {
1208       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1209                   "peer %s probably went offline as expected\n",
1210                   GNUNET_i2s (rps_peers[entry->index].peer_id));
1211     }
1212     rps_peers[entry->index].online = GNUNET_NO;
1213   }
1214
1215   else if (PEER_GO_ONLINE < entry->delta)
1216   { /* Peer hopefully just went online */
1217     if (GNUNET_NO != rps_peers[entry->index].online)
1218     {
1219       GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1220                   "peer %s was expected to go online but is still marked as offline\n",
1221                   GNUNET_i2s (rps_peers[entry->index].peer_id));
1222       GNUNET_break (0);
1223     }
1224     else
1225     {
1226       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1227                   "peer %s probably went online as expected\n",
1228                   GNUNET_i2s (rps_peers[entry->index].peer_id));
1229       if (NULL != cur_test_run.pre_test)
1230       {
1231         cur_test_run.pre_test (&rps_peers[entry->index],
1232             rps_peers[entry->index].rps_handle);
1233         schedule_missing_requests (&rps_peers[entry->index]);
1234       }
1235     }
1236     rps_peers[entry->index].online = GNUNET_YES;
1237   }
1238   else
1239   {
1240     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1241         "Invalid value for delta: %i\n", entry->delta);
1242     GNUNET_break (0);
1243   }
1244
1245   GNUNET_CONTAINER_DLL_remove (oplist_head, oplist_tail, entry);
1246   rps_peers[entry->index].entry_op_manage = NULL;
1247   GNUNET_free (entry);
1248   //if (num_peers_in_round[current_round] == peers_running)
1249   //  run_round ();
1250 }
1251
1252 /**
1253  * @brief Set the rps-service up or down for a specific peer
1254  *
1255  * @param i index of action
1256  * @param j index of peer
1257  * @param delta (#PEER_ONLINE_DELTA) down (-1) or up (1)
1258  * @param prob_go_on_off the probability of the action
1259  */
1260 static void
1261 manage_service_wrapper (unsigned int i, unsigned int j,
1262                         enum PEER_ONLINE_DELTA delta,
1263                         double prob_go_on_off)
1264 {
1265   struct OpListEntry *entry;
1266   uint32_t prob;
1267
1268   /* make sure that management operation is not already scheduled */
1269   if (NULL != rps_peers[j].entry_op_manage)
1270   {
1271     return;
1272   }
1273
1274   prob = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
1275                                    UINT32_MAX);
1276   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1277               "%u. selected peer (%u: %s) is %s.\n",
1278               i,
1279               j,
1280               GNUNET_i2s (rps_peers[j].peer_id),
1281               (PEER_GO_ONLINE == delta) ? "online" : "offline");
1282   if (prob < prob_go_on_off * UINT32_MAX)
1283   {
1284     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1285                 "%s goes %s\n",
1286                 GNUNET_i2s (rps_peers[j].peer_id),
1287                 (PEER_GO_OFFLINE == delta) ? "offline" : "online");
1288
1289     if (PEER_GO_OFFLINE == delta)
1290       cancel_pending_req_rep (&rps_peers[j]);
1291     entry = make_oplist_entry ();
1292     entry->delta = delta;
1293     entry->index = j;
1294     entry->op = GNUNET_TESTBED_peer_manage_service (NULL,
1295                                                     testbed_peers[j],
1296                                                     "rps",
1297                                                     &churn_cb,
1298                                                     entry,
1299                                                     (PEER_GO_OFFLINE == delta) ? 0 : 1);
1300   }
1301   rps_peers[j].entry_op_manage = entry;
1302 }
1303
1304
1305 static void
1306 churn (void *cls)
1307 {
1308   unsigned int i;
1309   unsigned int j;
1310   double portion_online;
1311   unsigned int *permut;
1312   double prob_go_offline;
1313   double portion_go_online;
1314   double portion_go_offline;
1315
1316   if (GNUNET_YES == in_shutdown)
1317   {
1318     return;
1319   }
1320   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1321               "Churn function executing\n");
1322
1323   churn_task = NULL; /* Should be invalid by now */
1324
1325   /* Compute the probability for an online peer to go offline
1326    * this round */
1327   portion_online = num_peers_online * 1.0 / num_peers;
1328   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1329               "Portion online: %f\n",
1330               portion_online);
1331   portion_go_online = ((1 - portion_online) * .5 * .66);
1332   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1333               "Portion that should go online: %f\n",
1334               portion_go_online);
1335   portion_go_offline = (portion_online + portion_go_online) - .75;
1336   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1337               "Portion that probably goes offline: %f\n",
1338               portion_go_offline);
1339   prob_go_offline = portion_go_offline / (portion_online * .5);
1340   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1341               "Probability of a selected online peer to go offline: %f\n",
1342               prob_go_offline);
1343
1344   permut = GNUNET_CRYPTO_random_permute (GNUNET_CRYPTO_QUALITY_WEAK,
1345                                          (unsigned int) num_peers);
1346
1347   /* Go over 50% randomly chosen peers */
1348   for (i = 0; i < .5 * num_peers; i++)
1349   {
1350     j = permut[i];
1351
1352     /* If online, shut down with certain probability */
1353     if (GNUNET_YES == rps_peers[j].online)
1354     {
1355       manage_service_wrapper (i, j, -1, prob_go_offline);
1356     }
1357
1358     /* If offline, restart with certain probability */
1359     else if (GNUNET_NO == rps_peers[j].online)
1360     {
1361       manage_service_wrapper (i, j, 1, 0.66);
1362     }
1363   }
1364
1365   GNUNET_free (permut);
1366
1367   churn_task = GNUNET_SCHEDULER_add_delayed (
1368         GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 2),
1369         churn,
1370         NULL);
1371 }
1372
1373
1374 /**
1375  * Initialise given RPSPeer
1376  */
1377 static void profiler_init_peer (struct RPSPeer *rps_peer)
1378 {
1379   if (num_peers - 1 == rps_peer->index)
1380     rps_peer->num_ids_to_request = cur_test_run.num_requests;
1381 }
1382
1383
1384 /**
1385  * Callback to call on receipt of a reply
1386  *
1387  * @param cls closure
1388  * @param n number of peers
1389  * @param recv_peers the received peers
1390  */
1391 static void
1392 profiler_reply_handle (void *cls,
1393                       uint64_t n,
1394                       const struct GNUNET_PeerIdentity *recv_peers)
1395 {
1396   struct RPSPeer *rps_peer;
1397   struct RPSPeer *rcv_rps_peer;
1398   char *file_name;
1399   char *file_name_dh;
1400   unsigned int i;
1401   struct PendingReply *pending_rep = (struct PendingReply *) cls;
1402
1403   rps_peer = pending_rep->rps_peer;
1404   file_name = "/tmp/rps/received_ids";
1405   file_name_dh = "/tmp/rps/diehard_input";
1406   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1407               "[%s] got %" PRIu64 " peers:\n",
1408               GNUNET_i2s (rps_peer->peer_id),
1409               n);
1410   for (i = 0; i < n; i++)
1411   {
1412     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1413                 "%u: %s\n",
1414                 i,
1415                 GNUNET_i2s (&recv_peers[i]));
1416     tofile (file_name,
1417              "%s\n",
1418              GNUNET_i2s_full (&recv_peers[i]));
1419     rcv_rps_peer = GNUNET_CONTAINER_multipeermap_get (peer_map, &recv_peers[i]);
1420     GNUNET_assert (NULL != rcv_rps_peer);
1421     tofile (file_name_dh,
1422              "%" PRIu32 "\n",
1423              (uint32_t) rcv_rps_peer->index);
1424   }
1425   default_reply_handle (cls, n, recv_peers);
1426 }
1427
1428
1429 static void
1430 profiler_cb (struct RPSPeer *rps_peer)
1431 {
1432   if (GNUNET_YES == in_shutdown)
1433   {
1434     return;
1435   }
1436
1437   /* Start churn */
1438   if (GNUNET_YES == cur_test_run.have_churn && NULL == churn_task)
1439   {
1440     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1441                 "Starting churn task\n");
1442     churn_task = GNUNET_SCHEDULER_add_delayed (
1443           GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5),
1444           churn,
1445           NULL);
1446   } else {
1447     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1448                 "Not starting churn task\n");
1449   }
1450
1451   /* Only request peer ids at one peer.
1452    * (It's the before-last because last one is target of the focussed attack.)
1453    */
1454   if (eval_peer == rps_peer)
1455     schedule_missing_requests (rps_peer);
1456 }
1457
1458 /**
1459  * Function called from #profiler_eval with a filename.
1460  *
1461  * @param cls closure
1462  * @param filename complete filename (absolute path)
1463  * @return #GNUNET_OK to continue to iterate,
1464  *  #GNUNET_NO to stop iteration with no error,
1465  *  #GNUNET_SYSERR to abort iteration with error!
1466  */
1467 int
1468 file_name_cb (void *cls, const char *filename)
1469 {
1470   if (NULL != strstr (filename, "sampler_el"))
1471   {
1472     struct RPS_SamplerElement *s_elem;
1473     struct GNUNET_CRYPTO_AuthKey auth_key;
1474     const char *key_char;
1475     uint32_t i;
1476
1477     key_char = filename + 20; /* Length of "/tmp/rps/sampler_el-" */
1478     tofile (filename, "--------------------------\n");
1479
1480     auth_key = string_to_auth_key (key_char);
1481     s_elem = RPS_sampler_elem_create ();
1482     RPS_sampler_elem_set (s_elem, auth_key);
1483
1484     for (i = 0; i < num_peers; i++)
1485     {
1486       RPS_sampler_elem_next (s_elem, &rps_peer_ids[i]);
1487     }
1488     RPS_sampler_elem_destroy (s_elem);
1489   }
1490   return GNUNET_OK;
1491 }
1492
1493 /**
1494  * This is run after the test finished.
1495  *
1496  * Compute all perfect samples.
1497  */
1498 int
1499 profiler_eval (void)
1500 {
1501   /* Compute perfect sample for each sampler element */
1502   if (-1 == GNUNET_DISK_directory_scan ("/tmp/rps/", file_name_cb, NULL))
1503   {
1504     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Scan of directory failed\n");
1505   }
1506
1507   return evaluate ();
1508 }
1509
1510
1511 /***********************************************************************
1512  * /Definition of tests
1513 ***********************************************************************/
1514
1515
1516 /**
1517  * Actual "main" function for the testcase.
1518  *
1519  * @param cls closure
1520  * @param h the run handle
1521  * @param n_peers number of peers in 'peers'
1522  * @param peers handle to peers run in the testbed
1523  * @param links_succeeded the number of overlay link connection attempts that
1524  *          succeeded
1525  * @param links_failed the number of overlay link connection attempts that
1526  *          failed
1527  */
1528 static void
1529 run (void *cls,
1530      struct GNUNET_TESTBED_RunHandle *h,
1531      unsigned int n_peers,
1532      struct GNUNET_TESTBED_Peer **peers,
1533      unsigned int links_succeeded,
1534      unsigned int links_failed)
1535 {
1536   unsigned int i;
1537   struct OpListEntry *entry;
1538   uint32_t num_mal_peers;
1539
1540   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "RUN was called\n");
1541
1542   /* Check whether we timed out */
1543   if (n_peers != num_peers ||
1544       NULL == peers ||
1545       0 == links_succeeded)
1546   {
1547     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Going down due to args (eg. timeout)\n");
1548     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "\tn_peers: %u\n", n_peers);
1549     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "\tnum_peers: %" PRIu32 "\n", num_peers);
1550     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "\tpeers: %p\n", peers);
1551     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "\tlinks_succeeded: %u\n", links_succeeded);
1552     GNUNET_SCHEDULER_shutdown ();
1553     return;
1554   }
1555
1556
1557   /* Initialize peers */
1558   testbed_peers = peers;
1559   num_peers_online = 0;
1560   for (i = 0; i < num_peers; i++)
1561   {
1562     entry = make_oplist_entry ();
1563     entry->index = i;
1564     rps_peers[i].index = i;
1565     if (NULL != cur_test_run.init_peer)
1566       cur_test_run.init_peer (&rps_peers[i]);
1567     entry->op = GNUNET_TESTBED_peer_get_information (peers[i],
1568                                                      GNUNET_TESTBED_PIT_IDENTITY,
1569                                                      &info_cb,
1570                                                      entry);
1571   }
1572
1573   /* Bring peers up */
1574   num_mal_peers = round (portion * num_peers);
1575   GNUNET_assert (num_peers == n_peers);
1576   for (i = 0; i < n_peers; i++)
1577   {
1578     rps_peers[i].index = i;
1579     if ( (rps_peers[i].num_recv_ids < rps_peers[i].num_ids_to_request) ||
1580          (i < num_mal_peers) )
1581     {
1582       rps_peers[i].op =
1583         GNUNET_TESTBED_service_connect (&rps_peers[i],
1584                                         peers[i],
1585                                         "rps",
1586                                         &rps_connect_complete_cb,
1587                                         &rps_peers[i],
1588                                         &rps_connect_adapter,
1589                                         &rps_disconnect_adapter,
1590                                         &rps_peers[i]);
1591     }
1592   }
1593
1594   if (NULL != churn_task)
1595     GNUNET_SCHEDULER_cancel (churn_task);
1596   shutdown_task = GNUNET_SCHEDULER_add_delayed (timeout, &shutdown_op, NULL);
1597 }
1598
1599
1600 /**
1601  * Entry point for the testcase, sets up the testbed.
1602  *
1603  * @param argc unused
1604  * @param argv unused
1605  * @return 0 on success
1606  */
1607 int
1608 main (int argc, char *argv[])
1609 {
1610   int ret_value;
1611
1612   num_peers = 5;
1613   cur_test_run.name = "test-rps-default";
1614   cur_test_run.init_peer = default_init_peer;
1615   cur_test_run.pre_test = NULL;
1616   cur_test_run.reply_handle = default_reply_handle;
1617   cur_test_run.eval_cb = default_eval_cb;
1618   cur_test_run.have_churn = GNUNET_YES;
1619   churn_task = NULL;
1620   timeout = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 30);
1621
1622   if (strstr (argv[0], "malicious") != NULL)
1623   {
1624     cur_test_run.pre_test = mal_pre;
1625     cur_test_run.main_test = mal_cb;
1626     cur_test_run.init_peer = mal_init_peer;
1627
1628     if (strstr (argv[0], "_1") != NULL)
1629     {
1630       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Test malicious peer type 1\n");
1631       cur_test_run.name = "test-rps-malicious_1";
1632       mal_type = 1;
1633     }
1634     else if (strstr (argv[0], "_2") != NULL)
1635     {
1636       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Test malicious peer type 2\n");
1637       cur_test_run.name = "test-rps-malicious_2";
1638       mal_type = 2;
1639     }
1640     else if (strstr (argv[0], "_3") != NULL)
1641     {
1642       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Test malicious peer type 3\n");
1643       cur_test_run.name = "test-rps-malicious_3";
1644       mal_type = 3;
1645     }
1646   }
1647
1648   else if (strstr (argv[0], "_single_req") != NULL)
1649   {
1650     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Test single request\n");
1651     cur_test_run.name = "test-rps-single-req";
1652     cur_test_run.main_test = single_req_cb;
1653     cur_test_run.have_churn = GNUNET_NO;
1654   }
1655
1656   else if (strstr (argv[0], "_delayed_reqs") != NULL)
1657   {
1658     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Test delayed requests\n");
1659     cur_test_run.name = "test-rps-delayed-reqs";
1660     cur_test_run.main_test = delay_req_cb;
1661     cur_test_run.have_churn = GNUNET_NO;
1662   }
1663
1664   else if (strstr (argv[0], "_seed_big") != NULL)
1665   {
1666     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Test seeding (num_peers > GNUNET_MAX_MESSAGE_SIZE)\n");
1667     num_peers = 1;
1668     cur_test_run.name = "test-rps-seed-big";
1669     cur_test_run.main_test = seed_big_cb;
1670     cur_test_run.eval_cb = no_eval;
1671     cur_test_run.have_churn = GNUNET_NO;
1672     timeout = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 10);
1673   }
1674
1675   else if (strstr (argv[0], "_single_peer_seed") != NULL)
1676   {
1677     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Test seeding and requesting on a single peer\n");
1678     cur_test_run.name = "test-rps-single-peer-seed";
1679     cur_test_run.main_test = single_peer_seed_cb;
1680     cur_test_run.have_churn = GNUNET_NO;
1681   }
1682
1683   else if (strstr (argv[0], "_seed_request") != NULL)
1684   {
1685     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Test seeding and requesting on multiple peers\n");
1686     cur_test_run.name = "test-rps-seed-request";
1687     cur_test_run.main_test = seed_req_cb;
1688     cur_test_run.have_churn = GNUNET_NO;
1689   }
1690
1691   else if (strstr (argv[0], "_seed") != NULL)
1692   {
1693     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Test seeding\n");
1694     cur_test_run.name = "test-rps-seed";
1695     cur_test_run.main_test = seed_cb;
1696     cur_test_run.eval_cb = no_eval;
1697     cur_test_run.have_churn = GNUNET_NO;
1698   }
1699
1700   else if (strstr (argv[0], "_req_cancel") != NULL)
1701   {
1702     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Test cancelling a request\n");
1703     cur_test_run.name = "test-rps-req-cancel";
1704     num_peers = 1;
1705     cur_test_run.main_test = req_cancel_cb;
1706     cur_test_run.eval_cb = no_eval;
1707     cur_test_run.have_churn = GNUNET_NO;
1708     timeout = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 10);
1709   }
1710
1711   else if (strstr (argv[0], "_churn") != NULL)
1712   {
1713     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Test churn\n");
1714     cur_test_run.name = "test-rps-churn";
1715     num_peers = 5;
1716     cur_test_run.init_peer = default_init_peer;
1717     cur_test_run.main_test = churn_test_cb;
1718     cur_test_run.reply_handle = default_reply_handle;
1719     cur_test_run.eval_cb = default_eval_cb;
1720     cur_test_run.have_churn = GNUNET_YES;
1721     timeout = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 10);
1722   }
1723
1724   else if (strstr (argv[0], "profiler") != NULL)
1725   {
1726     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "This is the profiler\n");
1727     cur_test_run.name = "test-rps-profiler";
1728     num_peers = 10;
1729     mal_type = 3;
1730     cur_test_run.init_peer = profiler_init_peer;
1731     cur_test_run.pre_test = mal_pre;
1732     cur_test_run.main_test = profiler_cb;
1733     cur_test_run.reply_handle = profiler_reply_handle;
1734     cur_test_run.eval_cb = profiler_eval;
1735     cur_test_run.request_interval = 2;
1736     cur_test_run.num_requests = 5;
1737     cur_test_run.have_churn = GNUNET_YES;
1738     timeout = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 90);
1739
1740     /* 'Clean' directory */
1741     (void) GNUNET_DISK_directory_remove ("/tmp/rps/");
1742     GNUNET_DISK_directory_create ("/tmp/rps/");
1743   }
1744
1745   rps_peers = GNUNET_new_array (num_peers, struct RPSPeer);
1746   peer_map = GNUNET_CONTAINER_multipeermap_create (num_peers, GNUNET_NO);
1747   rps_peer_ids = GNUNET_new_array (num_peers, struct GNUNET_PeerIdentity);
1748   if ( (2 == mal_type) ||
1749        (3 == mal_type))
1750     target_peer = &rps_peer_ids[num_peers - 2];
1751   if (profiler_eval == cur_test_run.eval_cb)
1752     eval_peer = &rps_peers[num_peers - 1];    /* FIXME: eval_peer could be a
1753                                                  malicious peer if not careful
1754                                                  with the malicious portion */
1755
1756   ok = 1;
1757   ret_value = GNUNET_TESTBED_test_run (cur_test_run.name,
1758                                        "test_rps.conf",
1759                                        num_peers,
1760                                        0, NULL, NULL,
1761                                        &run, NULL);
1762   GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1763               "_test_run returned.\n");
1764   if (GNUNET_OK != ret_value)
1765   {
1766     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1767                 "Test did not run successfully!\n");
1768   }
1769
1770   ret_value = cur_test_run.eval_cb();
1771   GNUNET_free (rps_peers);
1772   GNUNET_free (rps_peer_ids);
1773   GNUNET_CONTAINER_multipeermap_destroy (peer_map);
1774   return ret_value;
1775 }
1776
1777 /* end of test_rps.c */