synced API definitions again
[oweals/gnunet.git] / src / scalarproduct / test_scalarproduct_api_regression.c
1 /*
2      This file is part of GNUnet.
3      (C) 2013 Christian Grothoff (and other contributing authors)
4
5      GNUnet is free software; you can redistribute it and/or modify
6      it under the terms of the GNU General Public License as published
7      by the Free Software Foundation; either version 3, or (at your
8      option) any later version.
9
10      GNUnet is distributed in the hope that it will be useful, but
11      WITHOUT ANY WARRANTY; without even the implied warranty of
12      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13      General Public License for more details.
14
15      You should have received a copy of the GNU General Public License
16      along with GNUnet; see the file COPYING.  If not, write to the
17      Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18      Boston, MA 02111-1307, USA.
19  */
20
21 /**
22  * @file scalarproduct/test_scalarproduct_api_regression.c
23  * @brief VectorProduct API regression test
24  * @author Gaurav Kukreja
25  * @author Christian Fuchs
26  */
27
28 /**
29  * AIM of the regression test
30  * 
31  * This test tries to check whether the service can handle abrupt client disconnect.
32  * 
33  * 1. We create a responder peer, and ask the service to prepare_response. After this,
34  *    we disconnect responder peer from service.
35  * 
36  * 2. Then we create a requester peer, and ask service to request another peer. We
37  *    should check that the service on responder peer is still active and receives
38  *    request from the requester. We then disconnect requester peer from service. Both
39  *    the requester and responder service should handle this cleanly.
40  */
41
42 #include <string.h>
43
44 #include <inttypes.h>
45 #include "platform.h"
46 #include "gnunet_util_lib.h"
47 #include "gnunet_testbed_service.h"
48 #include "gnunet_common.h"
49 #include "gnunet_scalarproduct_service.h"
50 #include "gnunet_protocols.h"
51
52 #define LOG(kind,...) GNUNET_log_from (kind, "test-scalarproduct-api-regression",__VA_ARGS__)
53 #define NUM_PEERS 2
54
55 /**
56  * Structure for holding peer's sockets and IO Handles
57  */
58 struct PeerData
59 {
60   /**
61    * Handle to testbed peer
62    */
63   struct GNUNET_TESTBED_Peer *peer;
64
65   /**
66    * The service connect operation to stream
67    */
68   struct GNUNET_TESTBED_Operation *op;
69
70   /**
71    * Our Peer id
72    */
73   struct GNUNET_PeerIdentity our_id;
74
75   /**
76    * Pointer to Vector Product Handle
77    */
78   struct GNUNET_SCALARPRODUCT_Handle *vh;
79 };
80
81 /**
82  * Different states in test setup
83  */
84 enum SetupState
85 {
86   /**
87    * Get the identity of peer 1
88    */
89   PEER1_GET_IDENTITY,
90
91   /**
92    * Get the identity of peer 2
93    */
94   PEER2_GET_IDENTITY,
95
96   /**
97    * Connect to stream service of peer 1
98    */
99   PEER1_SCALARPRODUCT_CONNECT,
100
101   /**
102    * Connect to stream service of peer 2
103    */
104   PEER2_SCALARPRODUCT_CONNECT
105
106 };
107
108 /******************************************************************************
109  *** Global Variables                            *****************************
110  ******************************************************************************/
111
112 /**
113  * Maximum allowed message-ids we can check in one go (with one GNUNET_message)
114  */
115 static unsigned int max_mids;
116
117 /**
118  * Session Key used by both the test peers
119  */
120 char input_key[103] = "helloworldhelloworldhelloworldhelloworldhelloworldhelloworldhelloworldhelloworldhelloworldhelloworldhe";
121
122 /**
123  * Input elements for peer1
124  */
125 //char input_elements_peer1[] = "11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11";
126 char input_elements_peer1[] = "11,11,11";
127
128 /**
129  * Input Mask for peer 1
130  */
131 //char input_mask_peer1[] = "1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1";
132 char input_mask_peer1[] = "1,1,1";
133
134 /**
135  * the array of converted message IDs to send to our service
136  */
137 static int32_t * elements_peer1 = NULL;
138
139 /**
140  * Input elements for peer2
141  */
142 //char input_elements_peer2[] = "11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11";
143 char input_elements_peer2[] = "11,11,11";
144 /**
145  * Input Mask for peer 2
146  */
147 //char input_mask_peer2[] = "1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1";
148 char input_mask_peer2[] = "1,1,1";
149 /**
150  * the array of converted message IDs to send to our service
151  */
152 static int32_t * elements_peer2 = NULL;
153
154 /**
155  * the array of converted message IDs to send to our service
156  */
157 static unsigned char * mask_peer2 = NULL;
158
159 /**
160  * Data context for peer 1
161  */
162 static struct PeerData peer1;
163
164 /**
165  * Data context for peer 2
166  */
167 static struct PeerData peer2;
168
169 /**
170  * Various states during test setup
171  */
172 static enum SetupState setup_state;
173
174 /**
175  * Testbed operation handle
176  */
177 static struct GNUNET_TESTBED_Operation *op;
178
179 /**
180  * Return value of the test.
181  */
182 static int ok;
183
184 /**
185  * Abort Task for timeout
186  */
187 static GNUNET_SCHEDULER_TaskIdentifier abort_task;
188 /******************************************************************************
189  *** Static Functions                             *****************************
190  ******************************************************************************/
191
192 /**
193  * Helper function to shutdown a test peer
194  * 
195  * @param cls void* to struct PeerData of the peer to be disconnected
196  * @param tc Task Context
197  */
198 static void
199 do_shutdown (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc);
200
201
202 /**
203  * Helper function to connect a test peer
204  * 
205  * @param cls void* to struct PeerData of the peer to be connected
206  * @param tc Task Context
207  */
208 static void
209 connect_peer (void *cls,
210               const struct GNUNET_SCHEDULER_TaskContext * tc);
211
212
213 /**
214  * Close sockets and stop testing deamons nicely
215  */
216 static void
217 do_close (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
218 {
219
220   if (peer1.op != NULL)
221     do_shutdown (&peer1, NULL);
222
223   if (peer2.op != NULL)
224     do_shutdown (&peer2, NULL);
225
226   if (GNUNET_SCHEDULER_NO_TASK != abort_task)
227     GNUNET_SCHEDULER_cancel (abort_task);
228
229   GNUNET_SCHEDULER_shutdown (); /* For shutting down testbed */
230 }
231
232
233 /**
234  * Helper function to shutdown a test peer
235  * 
236  * @param cls void* to struct PeerData of the peer to be disconnected
237  * @param tc Task Context
238  */
239 static void
240 do_shutdown (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
241 {
242   static int shutdown;
243   shutdown++;
244   struct PeerData* peer = (struct PeerData*) cls;
245
246   if (peer == &peer1)
247     LOG (GNUNET_ERROR_TYPE_DEBUG, "Disconnecting Peer1\n\n");
248   else if (peer == &peer2)
249     LOG (GNUNET_ERROR_TYPE_DEBUG, "Disconnecting Peer2\n\n");
250
251   // peer->op contains handle to the TESTBED_connect_service operation
252   // calling operation done, leads to call to scalarproduct_da
253   if (peer->op != NULL)
254     {
255       GNUNET_TESTBED_operation_done (peer->op);
256       peer->op = NULL;
257     }
258
259   if (shutdown >= 2)
260     GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, 10), &do_close, NULL);
261 }
262
263
264 /**
265  * Something went wrong and timed out. Kill everything and set error flag
266  */
267 static void
268 do_abort (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
269 {
270   GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "test: ABORT due to Timeout\n");
271   ok = GNUNET_SYSERR;
272   abort_task = 0;
273   do_close (cls, tc);
274 }
275
276
277 /**
278  * Controller event callback
279  *
280  * @param cls NULL
281  * @param event the controller event
282  */
283 static void
284 controller_event_cb (void *cls,
285                      const struct GNUNET_TESTBED_EventInformation *event)
286 {
287   switch (event->type)
288     {
289     case GNUNET_TESTBED_ET_OPERATION_FINISHED:
290       switch (setup_state)
291         {
292         case PEER1_SCALARPRODUCT_CONNECT:
293         case PEER2_SCALARPRODUCT_CONNECT:
294           GNUNET_assert (NULL == event->details.operation_finished.emsg);
295           break;
296         default:
297           GNUNET_assert (0);
298         }
299       break;
300     default:
301       GNUNET_assert (0);
302     }
303 }
304
305
306 /**
307  * Callback function called for the responder peer i.e. peer1
308  * 
309  * @param cls 
310  * @param key Session key
311  * @param status Status of the message
312  */
313 static void
314 responder_callback (void *cls,
315                     const struct GNUNET_HashCode * key,
316                     enum GNUNET_SCALARPRODUCT_ResponseStatus status)
317 {
318   if (status == GNUNET_SCALARPRODUCT_Status_Failure)
319     {
320       LOG (GNUNET_ERROR_TYPE_WARNING, "Responder Client received status failure\n");
321       ok = -1;
322     }
323   else if (status == GNUNET_SCALARPRODUCT_Status_InvalidResponse)
324     {
325       LOG (GNUNET_ERROR_TYPE_WARNING, "Responder Client received status invalid response\n");
326       ok = -1;
327     }
328   else if (GNUNET_SCALARPRODUCT_Status_Timeout == status)
329     {
330       LOG (GNUNET_ERROR_TYPE_WARNING, "Responder Client received timeout occured\n");
331       ok = -1;
332     }
333   else if (GNUNET_SCALARPRODUCT_Status_ServiceDisconnected == status)
334     {
335       LOG (GNUNET_ERROR_TYPE_WARNING, "Responder Client received service disconnected!!\n");
336       ok = 1;
337     }
338   else if (GNUNET_SCALARPRODUCT_Status_Success == status)
339     {
340       LOG (GNUNET_ERROR_TYPE_DEBUG, "Responder Client expected response received!\n");
341       ok = -1;
342     }
343   else
344     {
345       LOG (GNUNET_ERROR_TYPE_WARNING, "Responder Client status = %d!\n", (int) status);
346       ok = -1;
347     }
348
349   // Not shutting down this time, only for this regression test. We have shutdown explicitly earlier.
350   // Shutting down again is causing problems.
351
352   //  if(peer1.vh != NULL)
353   //  {
354   //    GNUNET_SCHEDULER_add_now(&do_shutdown, &peer1);
355   //  }
356   return;
357 }
358
359
360 /**
361  * Callback function called for the requester peer i.e. peer2
362  * 
363  * @param cls 
364  * @param key Session key
365  * @param status Status of the message
366  */
367 static void
368 requester_callback (void *cls,
369         const struct GNUNET_HashCode * key,
370         const struct GNUNET_PeerIdentity * peer,
371         enum GNUNET_SCALARPRODUCT_ResponseStatus status,
372         const struct GNUNET_SCALARPRODUCT_client_response *msg)
373 {
374   uint32_t product_len;
375
376   if (status == GNUNET_SCALARPRODUCT_Status_Failure)
377     {
378       LOG (GNUNET_ERROR_TYPE_WARNING, "Requester Client received status failure\n");
379       ok = -1;
380     }
381   else if (status == GNUNET_SCALARPRODUCT_Status_InvalidResponse)
382     {
383       LOG (GNUNET_ERROR_TYPE_WARNING, "Requester Client received status invalid response\n");
384       ok = -1;
385     }
386   else if (GNUNET_SCALARPRODUCT_Status_Timeout == status)
387     {
388       LOG (GNUNET_ERROR_TYPE_WARNING, "Requester Client timeout occured\n");
389       ok = -1;
390     }
391   else if (GNUNET_SCALARPRODUCT_Status_ServiceDisconnected == status)
392     {
393       LOG (GNUNET_ERROR_TYPE_WARNING, "Requester Client service disconnected!!\n");
394       ok = 1;
395     }
396   else if (GNUNET_SCALARPRODUCT_Status_Success != status)
397     {
398       LOG (GNUNET_ERROR_TYPE_DEBUG, "Requester Client Status = %d\n", (int) status);
399       ok = -1;
400     }
401   else if (GNUNET_SCALARPRODUCT_Status_Success == status)
402     {
403       product_len = ntohl (msg->product_length);
404
405       if (0 < product_len)
406         {
407           gcry_mpi_t result;
408           gcry_error_t ret = 0;
409           size_t read = 0;
410
411           ret = gcry_mpi_scan (&result, GCRYMPI_FMT_USG, (void *) &msg[1], product_len, &read);
412
413           if (0 != ret)
414             {
415               GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Could not convert to mpi to value!\n");
416             }
417           else
418             {
419               gcry_mpi_dump (result);
420               gcry_mpi_release (result);
421             }
422           ok = -1;
423         }
424       else
425         { //currently not used, but if we get more info due to MESH we will need this
426           LOG (GNUNET_ERROR_TYPE_WARNING, "Error during computation of vector product, return code: %d\n", product_len);
427           ok = -1;
428         }
429     }
430
431   // Not shutting down this time, only for this regression test. We have shutdown explicitly earlier.
432   // Shutting down again is causing problems.
433
434   //  if(peer2.vh != NULL)
435   //  {
436   //    GNUNET_SCHEDULER_add_now(&do_shutdown, &peer2);
437   //  }
438   return;
439 }
440
441
442 static void
443 requester_request (void *cls,
444                    const struct GNUNET_SCHEDULER_TaskContext * tc)
445 {
446   GNUNET_assert (peer2.vh != NULL);
447
448   unsigned int i;
449   uint16_t element_count = 0;
450   uint16_t mask_length = 0;
451   char * begin = input_elements_peer2;
452   char * end;
453   int32_t element;
454   struct GNUNET_SCALARPRODUCT_QueueEntry *qe;
455   struct GNUNET_HashCode key;
456   int exit_loop = 0;
457   
458   GNUNET_CRYPTO_hash (input_key, strlen (input_key), &key);
459
460   /* Read input_elements_peer2, and put in elements_peer2 array */
461   exit_loop = 0;
462   do
463     {
464       unsigned int mcount = element_count;
465       //ignore empty rows of ,,,,,,
466       while (*begin == ',')
467         begin++;
468       // get the length of the current element and replace , with null
469       for (end = begin; *end && *end != ','; end++);
470
471       if (*end == '\0')
472         exit_loop = 1;
473
474       if (1 != sscanf (begin, "%" SCNd32, &element))
475         {
476           FPRINTF (stderr, _ ("Could not convert `%s' to int32_t.\n"), begin);
477           ok = -1;
478           return;
479         }
480
481       GNUNET_array_append (elements_peer2, mcount, element);
482       element_count++;
483
484       begin = ++end;
485     }
486   while (!exit_loop && element_count < max_mids);
487   GNUNET_assert (elements_peer2 != NULL);
488   GNUNET_assert (element_count >= 1);
489   
490   /* Read input_mask_peer2 and read in mask_peer2 array */
491   mask_length = element_count / 8 + (element_count % 8 ? 1 : 0);
492   mask_peer2 = GNUNET_malloc ((element_count / 8) + 2);
493   GNUNET_assert (NULL != mask_peer2);
494   if (NULL != input_mask_peer2)
495     {
496       begin = input_mask_peer2;
497       unsigned short mask_count = 0;
498       exit_loop = 0;
499
500       do
501         {
502           //ignore empty rows of ,,,,,,
503           while (* begin == ',')
504             begin++;
505           // get the length of the current element and replace , with null
506           // gnunet_ascii-armor uses base32, thus we can use , as separator!
507           for (end = begin; *end && *end != ','; end++);
508
509           if (*end == '\0')
510             exit_loop = 1;
511
512           if (1 != sscanf (begin, "%" SCNd32, &element))
513             {
514               FPRINTF (stderr, _ ("Could not convert `%s' to int32_t.\n"), begin);
515               ok = -1;
516               return;
517             }
518
519           GNUNET_assert (mask_count <= element_count);
520
521           if (element)
522             mask_peer2[mask_count / 8] = mask_peer2[mask_count / 8] | 1 << (mask_count % 8);
523
524           mask_count++;
525           begin = ++end;
526         }
527       while (!exit_loop);
528       // +1 to see if we would have more data, which would indicate malformed/superficial input
529       GNUNET_assert (mask_count == element_count);
530     }
531   else
532     {
533       for (i = 0; i <= mask_length; i++)
534         mask_peer2[i] = UCHAR_MAX; // all 1's
535     }
536
537   GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Responder peer key %s\n", &peer1.our_id);
538
539   qe = GNUNET_SCALARPRODUCT_request (peer2.vh,
540                                      &key,
541                                      &peer1.our_id,
542                                      element_count,
543                                      mask_length,
544                                      elements_peer2, mask_peer2,
545                                      GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 10),
546                                      &requester_callback,
547                                      NULL);
548
549   if (qe == NULL)
550     {
551       FPRINTF (stderr, "%s", _ ("Could not send request to scalarproduct service! Exitting!"));
552       ok = -1;
553       return;
554     }
555
556   /**
557    * For regression, we shutdown the initiator peer, peer2, one second after
558    * issuing a request. Hopefully, peer1 notices that the tunnel has been
559    * been destroyed, and will shutdown cleanly.
560    */  
561   GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS, &do_shutdown, &peer2);
562
563   return;
564 }
565
566
567 /**
568  * Function prepares the message to be sent by peer1 to its scalarproduct service
569  * to prepare response, and wait for a request session to be initiated by peer1
570  */
571 static void
572 responder_prepare_response (void *cls,
573                             const struct GNUNET_SCHEDULER_TaskContext * tc)
574 {
575   GNUNET_assert (peer1.vh != NULL);
576
577   uint16_t element_count = 0;
578   char * begin = input_elements_peer1;
579   char * end;
580   int32_t element;
581
582   struct GNUNET_SCALARPRODUCT_QueueEntry *qe;
583
584   struct GNUNET_HashCode key;
585   GNUNET_CRYPTO_hash (input_key, strlen (input_key), &key);
586
587   int exit_loop = 0;
588   /* Read input_elements_peer1, and put in elements_peer1 array */
589   do
590     {
591       unsigned int mcount = element_count;
592       //ignore empty rows of ,,,,,,
593       while (*begin == ',')
594         begin++;
595       // get the length of the current element and replace , with null
596       for (end = begin; *end && *end != ','; end++);
597
598       if (*end == '\0')
599         exit_loop = 1;
600
601       if (1 != sscanf (begin, "%" SCNd32, &element))
602         {
603           FPRINTF (stderr, _ ("Could not convert `%s' to int32_t.\n"), begin);
604           ok = -1;
605           return;
606         }
607
608       GNUNET_array_append (elements_peer1, mcount, element);
609       element_count++;
610
611       begin = ++end;
612     }
613   while (!exit_loop && element_count < max_mids);
614
615   GNUNET_assert (elements_peer1 != NULL);
616   GNUNET_assert (element_count >= 1);
617
618   qe = GNUNET_SCALARPRODUCT_prepare_response (peer1.vh,
619                                               &key,
620                                               element_count,
621                                               elements_peer1,
622                                               GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 10),
623                                               &responder_callback,
624                                               NULL);
625
626   if (qe == NULL)
627     {
628       FPRINTF (stderr, "%s", _ ("Could not send request to scalarproduct service! Exitting!"));
629       ok = -1;
630       return;
631     }
632
633   // connect the second peer
634   setup_state = PEER2_SCALARPRODUCT_CONNECT;
635   GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 1), &connect_peer, &peer2);
636
637   // while the service is waiting for a matching request, disconnect the test client
638   GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS, &do_shutdown, &peer1);
639
640   return;
641 }
642
643
644 /**
645  * Adapter function called to destroy a connection to
646  * a service. This function is called when GNUNET_TESTBED_operation_done is
647  * called for peer->op, which holds the handle for GNUNET_TESTBED_service_connect
648  * operation.
649  * 
650  * @param cls closure
651  * @param op_result service handle returned from the connect adapter
652  */
653 static void
654 scalarproduct_da (void *cls, void *op_result)
655 {
656   struct PeerData* peer = (struct PeerData*) cls;
657
658   GNUNET_SCALARPRODUCT_cancel (peer->vh);
659   peer->vh = NULL;
660   return;
661 }
662
663
664 /**
665  * Adapter function called to establish a connection to
666  * a service. This function is called to by GNUNET_TESTBED_service_connect.
667  * 
668  * @param cls closure
669  * @param cfg configuration of the peer to connect to; will be available until
670  *          GNUNET_TESTBED_operation_done() is called on the operation returned
671  *          from GNUNET_TESTBED_service_connect()
672  * @return service handle to return in 'op_result', NULL on error
673  */
674 static void *
675 scalarproduct_ca (void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg)
676 {
677   struct PeerData *p = cls;
678
679   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Peer %u (`%s') started\n", (&peer1 == p) ? 1 : 2,
680               GNUNET_i2s (&p->our_id));
681
682   switch (setup_state)
683     {
684     case PEER1_SCALARPRODUCT_CONNECT:
685       peer1.vh = GNUNET_SCALARPRODUCT_connect (cfg);
686
687       if (peer1.vh != NULL)
688         {
689           /* prepare_response from peer1 */
690           GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_MILLISECONDS, &responder_prepare_response, NULL);
691         }
692       else
693         {
694           ok = -1;
695           return NULL;
696         }
697
698       return peer1.vh;
699
700     case PEER2_SCALARPRODUCT_CONNECT:
701       /* Actually connect peer 2 to scalarproduct service */
702       peer2.vh = GNUNET_SCALARPRODUCT_connect (cfg);
703
704       if (peer2.vh != NULL)
705         {
706           /* initiate request from peer2 */
707           GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_MILLISECONDS, &requester_request, NULL);
708         }
709       else
710         {
711           ok = -1;
712           return NULL;
713         }
714
715       return peer2.vh;
716     default:
717       GNUNET_assert (0);
718     }
719 }
720
721
722 /**
723  * Helper function to connect a test peer
724  * 
725  * @param cls void* to struct PeerData of the peer to be connected
726  * @param tc Task Context
727  */
728 static void
729 connect_peer (void *cls,
730               const struct GNUNET_SCHEDULER_TaskContext * tc)
731 {
732   struct PeerData *peer = cls;
733
734   peer->op = GNUNET_TESTBED_service_connect (peer, peer->peer, "scalarproduct",
735                                              NULL, NULL, scalarproduct_ca,
736                                              scalarproduct_da, peer);
737
738 }
739
740
741 /**
742  * Callback to be called when the requested peer information is available
743  *
744  * @param cb_cls the closure from GNUNET_TETSBED_peer_get_information()
745  * @param op the operation this callback corresponds to
746  * @param pinfo the result; will be NULL if the operation has failed
747  * @param emsg error message if the operation has failed; will be NULL if the
748  *          operation is successfull
749  */
750 static void
751 peerinfo_cb (void *cb_cls, struct GNUNET_TESTBED_Operation *op_,
752              const struct GNUNET_TESTBED_PeerInformation *pinfo,
753              const char *emsg)
754 {
755   GNUNET_assert (NULL == emsg);
756   GNUNET_assert (op == op_);
757   
758   switch (setup_state)
759     {
760     case PEER1_GET_IDENTITY:
761       {
762         memcpy (&peer1.our_id, pinfo->result.id,
763                 sizeof (struct GNUNET_PeerIdentity));
764         GNUNET_TESTBED_operation_done (op);
765
766         GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Peer 1 id: %s\n", GNUNET_i2s_full
767                     (&peer1.our_id));
768
769         /* Request for peer id of peer 2*/
770         setup_state = PEER2_GET_IDENTITY;
771         op = GNUNET_TESTBED_peer_get_information (peer2.peer,
772                                                   GNUNET_TESTBED_PIT_IDENTITY,
773                                                   &peerinfo_cb, NULL);
774       }
775       break;
776     case PEER2_GET_IDENTITY:
777       {
778         memcpy (&peer2.our_id, pinfo->result.id,
779                 sizeof (struct GNUNET_PeerIdentity));
780         GNUNET_TESTBED_operation_done (op);
781
782         GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Peer 2 id: %s\n", GNUNET_i2s_full
783                     (&peer2.our_id));
784
785         /* Connect peer 1 to scalarproduct service */
786         setup_state = PEER1_SCALARPRODUCT_CONNECT;
787         GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_MILLISECONDS, &connect_peer, &peer1);
788       }
789       break;
790     default:
791       GNUNET_assert (0);
792     }
793 }
794
795
796 /**
797  * Signature of a main function for a testcase.
798  *
799  * @param cls closure
800  * @param num_peers number of peers in 'peers'
801  * @param peers handle to peers run in the testbed
802  */
803 static void
804 test_master (void *cls, unsigned int num_peers,
805              struct GNUNET_TESTBED_Peer **peers)
806 {
807   GNUNET_assert (NULL != peers);
808   GNUNET_assert (NULL != peers[0]);
809   GNUNET_assert (NULL != peers[1]);
810   peer1.peer = peers[0];
811   peer2.peer = peers[1];
812
813   /* Get the peer identity and configuration of peer 1 */
814   setup_state = PEER1_GET_IDENTITY;
815   op = GNUNET_TESTBED_peer_get_information (peer1.peer,
816                                             GNUNET_TESTBED_PIT_IDENTITY,
817                                             &peerinfo_cb, NULL);
818
819   abort_task =
820           GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
821                                         (GNUNET_TIME_UNIT_SECONDS, 20), &do_abort,
822                                         NULL);
823 }
824
825
826 /**
827  * Main function
828  */
829 int
830 main (int argc, char **argv)
831 {
832   uint64_t event_mask;
833
834   ok = GNUNET_NO;
835   event_mask = 0;
836   event_mask |= (1LL << GNUNET_TESTBED_ET_OPERATION_FINISHED);
837   max_mids = (GNUNET_SERVER_MAX_MESSAGE_SIZE - sizeof (struct GNUNET_MessageHeader))
838           / sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded) - 1;
839
840   (void) GNUNET_TESTBED_test_run ("test_scalarproduct_api_regression",
841                                   "test_scalarproduct_api_data.conf",
842                                   NUM_PEERS, event_mask, &controller_event_cb,
843                                   NULL,
844                                   &test_master, NULL);
845
846   if (GNUNET_SYSERR == ok)
847     return 1;
848   return 0;
849 }
850
851