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