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