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