renamed test_regex_big / fixes
[oweals/gnunet.git] / src / regex / gnunet-regex-profiler.c
1 /*
2      This file is part of GNUnet.
3      (C) 2011, 2012 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 regex/gnunet-regex-profiler.c
23  * @brief Stream API testing between 2 peers using testing API
24  * @author Bart Polot
25  * @author Max Szengel
26  */
27
28 #include <string.h>
29
30 #include "platform.h"
31 #include "gnunet_util_lib.h"
32 #include "gnunet_mesh_service.h"
33 #include "gnunet_stream_lib.h"
34 #include "gnunet_testbed_service.h"
35
36
37 #define NUM_HOSTS 2
38
39 #define PEER_PER_HOST 1
40
41 #define TOTAL_PEERS (NUM_HOSTS * PEER_PER_HOST)
42
43 /**
44  * Shorthand for Relative time in seconds
45  */
46 #define TIME_REL_SECS(sec) \
47   GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, sec)
48
49 /**
50  * Structure for holding peer's sockets and IO Handles
51  */
52 struct PeerData
53 {
54   /**
55    * Handle to testbed peer
56    */
57   struct GNUNET_TESTBED_Peer *peer;
58
59   /**
60    * Peer's stream socket
61    */
62   struct GNUNET_STREAM_Socket *socket;
63
64   /**
65    * Peer's io write handle
66    */
67   struct GNUNET_STREAM_IOWriteHandle *io_write_handle;
68
69   /**
70    * Peer's io read handle
71    */
72   struct GNUNET_STREAM_IOReadHandle *io_read_handle;
73
74   /**
75    * Peer's shutdown handle
76    */
77   struct GNUNET_STREAM_ShutdownHandle *shutdown_handle;
78
79   /**
80    * The service connect operation to stream
81    */
82   struct GNUNET_TESTBED_Operation *op;
83
84   /**
85    * Our Peer id
86    */
87   struct GNUNET_PeerIdentity our_id;
88
89   /**
90    * Bytes the peer has written
91    */
92   unsigned int bytes_wrote;
93
94   /**
95    * Byte the peer has read
96    */
97   unsigned int bytes_read;
98 };
99
100
101 /**
102  * Different states in test setup
103  */
104 enum SetupState
105 {
106   /**
107    * The initial state
108    */
109   INIT,
110
111   /**
112    * Connecting to slave controller
113    */
114   LINKING,
115
116   CREATING_PEER,
117
118   STARTING_PEER
119 };
120
121
122 /**
123  * Event Mask for operation callbacks
124  */
125 uint64_t event_mask;
126
127 /**
128  * Testbed operation handle
129  */
130 static struct GNUNET_TESTBED_Operation *op[NUM_HOSTS];
131
132 static enum SetupState state[NUM_HOSTS];
133
134 static GNUNET_SCHEDULER_TaskIdentifier abort_task;
135
136 /**
137  * Global test result
138  */
139 static int result;
140
141 /**
142  * Hosts successfully registered
143  */
144 static unsigned int host_registered;
145
146 /**
147  * Peers successfully started
148  */
149 static unsigned int peers_started;
150
151 /**
152  * The master controller host
153  */
154 struct GNUNET_TESTBED_Host *master_host;
155
156 /**
157  * The master controller process
158  */
159 static struct GNUNET_TESTBED_ControllerProc *master_proc;
160
161 /**
162  * Handle to master controller
163  */
164 static struct GNUNET_TESTBED_Controller *master_ctrl;
165
166 /**
167  * Slave host IP addresses
168  */
169
170 static char *slave_ips[NUM_HOSTS] = { "192.168.1.33", "192.168.1.34" };
171
172 /**
173  * The slave hosts
174  */
175 struct GNUNET_TESTBED_Host *slave_hosts[NUM_HOSTS];
176
177 /**
178  * Slave host registration handles
179  */
180 static struct GNUNET_TESTBED_HostRegistrationHandle *rh;
181
182 /**
183  * The peers
184  */
185 struct GNUNET_TESTBED_Peer *peers[TOTAL_PEERS];
186
187 /**
188  * Handle to global configuration
189  */
190 static struct GNUNET_CONFIGURATION_Handle *cfg;
191
192
193 /**
194  * Completion callback for shutdown
195  *
196  * @param cls the closure from GNUNET_STREAM_shutdown call
197  * @param operation the operation that was shutdown (SHUT_RD, SHUT_WR,
198  *          SHUT_RDWR)
199  */
200 // static void
201 // shutdown_completion (void *cls,
202 //                      int operation)
203 // {
204 //   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "STREAM shutdown successful\n");
205 //   GNUNET_SCHEDULER_add_now (&do_close, cls);
206 // }
207
208
209
210 /**
211  * Shutdown sockets gracefully
212  */
213 // static void
214 // do_shutdown (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
215 // {
216 //   result = GNUNET_OK;
217 //   peer1.shutdown_handle = GNUNET_STREAM_shutdown (peer1.socket, SHUT_RDWR,
218 //                                                   &shutdown_completion, cls);
219 // }
220
221
222 /**
223  * Something went wrong and timed out. Kill everything and set error flag
224  */
225 static void
226 do_abort (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
227 {
228   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: ABORT\n");
229   result = GNUNET_SYSERR;
230   abort_task = 0;
231 }
232
233
234 /**
235  * Adapter function called to destroy a connection to
236  * a service.
237  *
238  * @param cls closure
239  * @param op_result service handle returned from the connect adapter
240  */
241 // static void
242 // stream_da (void *cls, void *op_result)
243 // {
244 //   struct GNUNET_STREAM_ListenSocket *lsocket;
245 //   struct GNUNET_STREAM_Socket *socket;
246 //
247 //   if (&peer1 == cls)
248 //   {
249 //     lsocket = op_result;
250 //     GNUNET_STREAM_listen_close (lsocket);
251 //     GNUNET_TESTBED_operation_done (peer2.op);
252 //     return;
253 //   }
254 //   if (&peer2 == cls)
255 //   {
256 //     socket = op_result;
257 //     GNUNET_STREAM_close (socket);
258 //     GNUNET_SCHEDULER_shutdown (); /* Exit point of the test */
259 //     return;
260 //   }
261 //   GNUNET_assert (0);
262 // }
263
264
265 /**
266  * Adapter function called to establish a connection to
267  * a service.
268  *
269  * @param cls closure
270  * @param cfg configuration of the peer to connect to; will be available until
271  *          GNUNET_TESTBED_operation_done() is called on the operation returned
272  *          from GNUNET_TESTBED_service_connect()
273  * @return service handle to return in 'op_result', NULL on error
274  */
275 // static void *
276 // stream_ca (void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg)
277 // {
278 //   struct GNUNET_STREAM_ListenSocket *lsocket;
279 //
280 //   switch (setup_state)
281 //   {
282 //   case PEER1_STREAM_CONNECT:
283 //     lsocket = GNUNET_STREAM_listen (cfg, 10, &stream_listen_cb, NULL,
284 //                                     GNUNET_STREAM_OPTION_SIGNAL_LISTEN_SUCCESS,
285 //                                     &stream_connect, GNUNET_STREAM_OPTION_END);
286 //     return lsocket;
287 //   case PEER2_STREAM_CONNECT:
288 //     peer2.socket = GNUNET_STREAM_open (cfg, &peer1.our_id, 10, &stream_open_cb,
289 //                                        &peer2, GNUNET_STREAM_OPTION_END);
290 //     return peer2.socket;
291 //   default:
292 //     GNUNET_assert (0);
293 //   }
294 // }
295
296
297 /**
298  * Listen success callback; connects a peer to stream as client
299  */
300 // static void
301 // stream_connect (void)
302 // {
303 //   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Stream listen open successful\n");
304 //   peer2.op = GNUNET_TESTBED_service_connect (&peer2, peer2.peer, "stream",
305 //                                              NULL, NULL,
306 //                                              stream_ca, stream_da, &peer2);
307 //   setup_state = PEER2_STREAM_CONNECT;
308 // }
309
310
311 /**
312  * Callback to be called when the requested peer information is available
313  *
314  * @param cb_cls the closure from GNUNET_TETSBED_peer_get_information()
315  * @param op the operation this callback corresponds to
316  * @param pinfo the result; will be NULL if the operation has failed
317  * @param emsg error message if the operation has failed; will be NULL if the
318  *          operation is successfull
319  */
320 // static void
321 // peerinfo_cb (void *cb_cls, struct GNUNET_TESTBED_Operation *op_,
322 //              const struct GNUNET_TESTBED_PeerInformation *pinfo,
323 //              const char *emsg)
324 // {
325 //   GNUNET_assert (NULL == emsg);
326 //   GNUNET_assert (op == op_);
327 //   switch (setup_state)
328 //     {
329 //     case PEER1_GET_IDENTITY:
330 //       memcpy (&peer1.our_id, pinfo->result.id,
331 //               sizeof (struct GNUNET_PeerIdentity));
332 //       GNUNET_TESTBED_operation_done (op);
333 //       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Peer 1 id: %s\n", GNUNET_i2s
334 //                   (&peer1.our_id));
335 //       op = GNUNET_TESTBED_peer_get_information (peer2.peer,
336 //                                                 GNUNET_TESTBED_PIT_IDENTITY,
337 //                                                 &peerinfo_cb, NULL);
338 //       setup_state = PEER2_GET_IDENTITY;
339 //       break;
340 //     case PEER2_GET_IDENTITY:
341 //       memcpy (&peer2.our_id, pinfo->result.id,
342 //               sizeof (struct GNUNET_PeerIdentity));
343 //       GNUNET_TESTBED_operation_done (op);
344 //       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Peer 2 id: %s\n", GNUNET_i2s
345 //                   (&peer2.our_id));
346 //       peer1.op = GNUNET_TESTBED_service_connect (&peer1, peer1.peer, "stream",
347 //                                                  NULL, NULL, stream_ca,
348 //                                                  stream_da, &peer1);
349 //       setup_state = PEER1_STREAM_CONNECT;
350 //       break;
351 //     default:
352 //       GNUNET_assert (0);
353 //     }
354 // }
355
356
357 /**
358  * Controller event callback
359  *
360  * @param cls NULL
361  * @param event the controller event
362  */
363 // static void
364 // controller_event_cb (void *cls,
365 //                      const struct GNUNET_TESTBED_EventInformation *event)
366 // {
367 //   switch (event->type)
368 //   {
369 //   case GNUNET_TESTBED_ET_CONNECT:
370 //     GNUNET_assert (INIT == setup_state);
371 //     GNUNET_TESTBED_operation_done (op);
372 //     /* Get the peer identity and configuration of peers */
373 //     op = GNUNET_TESTBED_peer_get_information (peer1.peer,
374 //                                               GNUNET_TESTBED_PIT_IDENTITY,
375 //                                               &peerinfo_cb, NULL);
376 //     setup_state = PEER1_GET_IDENTITY;
377 //     break;
378 //   case GNUNET_TESTBED_ET_OPERATION_FINISHED:
379 //     switch (setup_state)
380 //     {
381 //     case PEER1_STREAM_CONNECT:
382 //     case PEER2_STREAM_CONNECT:
383 //       GNUNET_assert (NULL == event->details.operation_finished.emsg);
384 //       break;
385 //     default:
386 //       GNUNET_assert (0);
387 //     }
388 //     break;
389 //   default:
390 //     GNUNET_assert (0);
391 //   }
392 // }
393
394
395 /**
396  * Signature of a main function for a testcase.
397  *
398  * @param cls closure
399  * @param num_peers number of peers in 'peers'
400  * @param peers handle to peers run in the testbed
401  */
402 // static void
403 // test_master (void *cls, unsigned int num_peers,
404 //              struct GNUNET_TESTBED_Peer **peers)
405 // {
406 //   GNUNET_assert (NULL != peers);
407 //   GNUNET_assert (NULL != peers[0]);
408 //   GNUNET_assert (NULL != peers[1]);
409 //   peer1.peer = peers[0];
410 //   peer2.peer = peers[1];
411 //   op = GNUNET_TESTBED_overlay_connect (NULL, NULL, NULL, peer2.peer, peer1.peer);
412 //   setup_state = INIT;
413 //   abort_task =
414 //     GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
415 //                                   (GNUNET_TIME_UNIT_SECONDS, 40), &do_abort,
416 //                                   NULL);
417 // }
418
419 /**
420  * Functions of this signature are called when a peer has been successfully
421  * started or stopped.
422  *
423  * @param cls the closure from GNUNET_TESTBED_peer_start/stop()
424  * @param emsg NULL on success; otherwise an error description
425  */
426 static void
427 peer_start_cb (void *cls, const char *emsg)
428 {
429   long i = (long) cls;
430
431   GNUNET_TESTBED_operation_done (op[i]);
432   peers_started++;
433   // FIXME create and start rest of PEERS_PER_HOST
434   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " %u peer(s) started\n", peers_started);
435
436   if (TOTAL_PEERS == peers_started)
437   {
438     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "ok\n");
439   }
440 }
441
442
443 /**
444  * Functions of this signature are called when a peer has been successfully
445  * created
446  *
447  * @param cls the closure from GNUNET_TESTBED_peer_create()
448  * @param peer the handle for the created peer; NULL on any error during
449  *          creation
450  * @param emsg NULL if peer is not NULL; else MAY contain the error description
451  */
452 static void
453 peer_create_cb (void *cls, struct GNUNET_TESTBED_Peer *peer, const char *emsg)
454 {
455   long i = (long) cls;
456   long peer_id;
457
458 //   GNUNET_TESTBED_operation_done(op[i]);
459   peer_id = i;                  // FIXME  A * i + B
460   peers[peer_id] = peer;
461   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " Peer %i created\n", peer_id);
462   op[i] = GNUNET_TESTBED_peer_start (NULL, peer, peer_start_cb, (void *) i);
463 }
464
465
466 /**
467  * Signature of the event handler function called by the
468  * respective event controller.
469  *
470  * @param cls closure
471  * @param event information about the event
472  */
473 static void
474 controller_cb (void *cls, const struct GNUNET_TESTBED_EventInformation *event)
475 {
476   long i;
477
478   switch (event->type)
479   {
480   case GNUNET_TESTBED_ET_PEER_START:
481     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " Peer started\n");
482     /* event->details.peer_start.peer; */
483     /* event->details.peer_start.host; */
484
485     break;
486   case GNUNET_TESTBED_ET_PEER_STOP:
487   case GNUNET_TESTBED_ET_CONNECT:
488     break;
489   case GNUNET_TESTBED_ET_OPERATION_FINISHED:
490     if (NULL != event->details.operation_finished.emsg)
491     {
492       GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Testbed error: %s\n",
493                   event->details.operation_finished.emsg);
494       GNUNET_assert (0);
495     }
496     GNUNET_TESTBED_operation_done (event->details.operation_finished.operation);
497     //GNUNET_assert (NULL != event->details.operation_finished.op_cls);
498     i = (long) event->details.operation_finished.op_cls;
499     op[i] = NULL;
500     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  Operation %u finished\n", i);
501     switch (state[i])
502     {
503     case INIT:
504       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  Init: %u\n", i);
505       break;
506     case LINKING:
507       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "   Linked host %i\n", i);
508       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "   Creating peer...\n");
509
510       state[i] = CREATING_PEER;
511       op[i] =
512           GNUNET_TESTBED_peer_create (master_ctrl, slave_hosts[i], cfg,
513                                       peer_create_cb, (void *) i);
514       break;
515     case CREATING_PEER:
516       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  Peer create\n");
517       break;
518     default:
519       GNUNET_break (0);
520     }
521     break;
522   default:
523     GNUNET_break (0);
524   }
525 }
526
527 /**
528  * Callback which will be called to after a host registration succeeded or failed
529  *
530  * @param cls the host which has been registered
531  * @param emsg the error message; NULL if host registration is successful
532  */
533 static void
534 registration_cont (void *cls, const char *emsg)
535 {
536   if (NULL != emsg)
537   {
538     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "%s\n", emsg);
539     GNUNET_assert (0);
540   }
541   state[host_registered] = LINKING;
542   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " Linking host %u\n", host_registered);
543   op[host_registered] =
544       GNUNET_TESTBED_controller_link ((void *) (long) host_registered,
545                                       master_ctrl, slave_hosts[host_registered],
546                                       NULL, cfg, GNUNET_YES);
547   host_registered++;
548   if (NUM_HOSTS != host_registered)
549   {
550     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " Registering host %u\n",
551                 host_registered);
552     rh = GNUNET_TESTBED_register_host (master_ctrl,
553                                        slave_hosts[host_registered],
554                                        &registration_cont, NULL);
555     return;
556   }
557 }
558
559 /**
560  * Callback to signal successfull startup of the controller process
561  *
562  * @param cls the closure from GNUNET_TESTBED_controller_start()
563  * @param cfg the configuration with which the controller has been started;
564  *          NULL if status is not GNUNET_OK
565  * @param status GNUNET_OK if the startup is successfull; GNUNET_SYSERR if not,
566  *          GNUNET_TESTBED_controller_stop() shouldn't be called in this case
567  */
568 static void
569 status_cb (void *cls, const struct GNUNET_CONFIGURATION_Handle *config,
570            int status)
571 {
572   unsigned int i;
573
574   if (NULL == config || GNUNET_OK != status)
575     return;
576
577   event_mask = 0;
578   event_mask |= (1L << GNUNET_TESTBED_ET_PEER_START);
579   event_mask |= (1L << GNUNET_TESTBED_ET_PEER_STOP);
580   event_mask |= (1L << GNUNET_TESTBED_ET_CONNECT);
581   event_mask |= (1L << GNUNET_TESTBED_ET_OPERATION_FINISHED);
582   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connecting to master controller\n");
583   master_ctrl =
584       GNUNET_TESTBED_controller_connect (config, master_host, event_mask,
585                                          &controller_cb, NULL);
586   GNUNET_assert (NULL != master_ctrl);
587
588   for (i = 0; i < NUM_HOSTS; i++)
589   {
590     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " Creating host %u\n", i);
591     slave_hosts[i] = GNUNET_TESTBED_host_create (slave_ips[i], NULL, 0);
592     GNUNET_assert (NULL != slave_hosts[i]);
593   }
594   host_registered = 0;
595   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " Registering host %u\n",
596               host_registered);
597   rh = GNUNET_TESTBED_register_host (master_ctrl, slave_hosts[0],
598                                      &registration_cont, NULL);
599   GNUNET_assert (NULL != rh);
600 }
601
602
603 /**
604  * Main run function.
605  *
606  * @param cls NULL
607  * @param args arguments passed to GNUNET_PROGRAM_run
608  * @param cfgfile the path to configuration file
609  * @param cfg the configuration file handle
610  */
611 static void
612 run (void *cls, char *const *args, const char *cfgfile,
613      const struct GNUNET_CONFIGURATION_Handle *config)
614 {
615   master_host = GNUNET_TESTBED_host_create ("192.168.1.33", NULL, 0);
616   GNUNET_assert (NULL != master_host);
617   cfg = GNUNET_CONFIGURATION_dup (config);
618   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Starting master controller\n");
619   master_proc =
620       GNUNET_TESTBED_controller_start ("192.168.1.33", master_host, cfg,
621                                        status_cb, NULL);
622   abort_task =
623       GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
624                                     (GNUNET_TIME_UNIT_MINUTES, 60), &do_abort,
625                                     NULL);
626 }
627
628 /**
629  * Main function
630  */
631 int
632 main (int argc, char **argv)
633 {
634   int ret;
635   int test_hosts;
636   unsigned int i;
637
638   struct GNUNET_GETOPT_CommandLineOption options[] = {
639     GNUNET_GETOPT_OPTION_END
640   };
641   char *const argv2[] = { "gnunet-regex-profiler",
642     "-c", "regex_profiler_test.conf",
643     NULL
644   };
645
646   test_hosts = GNUNET_OK;
647   for (i = 0; i < NUM_HOSTS; i++)
648   {
649     char *const remote_args[] = {
650       "ssh", "-o", "BatchMode=yes", slave_ips[i],
651       "gnunet-helper-testbed --help > /dev/null", NULL
652     };
653     struct GNUNET_OS_Process *auxp;
654     enum GNUNET_OS_ProcessStatusType type;
655     unsigned long code;
656
657     fprintf (stderr, "Testing host %i\n", i);
658     auxp =
659         GNUNET_OS_start_process_vap (GNUNET_NO, GNUNET_OS_INHERIT_STD_ALL, NULL,
660                                      NULL, "ssh", remote_args);
661     GNUNET_assert (NULL != auxp);
662     do
663     {
664       ret = GNUNET_OS_process_status (auxp, &type, &code);
665       GNUNET_assert (GNUNET_SYSERR != ret);
666       (void) usleep (300);
667     }
668     while (GNUNET_NO == ret);
669     (void) GNUNET_OS_process_wait (auxp);
670     GNUNET_OS_process_destroy (auxp);
671     if (0 != code)
672     {
673       fprintf (stderr,
674                "Unable to run the test as this system is not configured "
675                "to use password less SSH logins to host %s.\n", slave_ips[i]);
676       test_hosts = GNUNET_SYSERR;
677     }
678   }
679   if (test_hosts != GNUNET_OK)
680   {
681     fprintf (stderr, "Some hosts have failed the ssh check. Exiting.\n");
682     return 1;
683   }
684   fprintf (stderr, "START.\n");
685
686   result = GNUNET_SYSERR;
687
688   ret =
689       GNUNET_PROGRAM_run ((sizeof (argv2) / sizeof (char *)) - 1, argv2,
690                           "test_regex_big", "nohelp", options, &run, NULL);
691
692   fprintf (stderr, "END.\n");
693
694   if (GNUNET_SYSERR == result || GNUNET_OK != ret)
695     return 1;
696   return 0;
697 }