- Big regex testcase
[oweals/gnunet.git] / src / regex / test_regex_big.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/test_regex_big.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    * Doing registration
113    */
114   REGISTERING,
115
116   /**
117    * Connecting to slave controller
118    */
119   LINKING
120 };
121
122 /**
123  * Various states during test setup
124  */
125 // static enum SetupState setup_state;
126
127
128 uint64_t event_mask;
129
130 /**
131  * Testbed operation handle
132  */
133 static struct GNUNET_TESTBED_Operation *op[NUM_HOSTS];
134
135 static enum SetupState state[NUM_HOSTS];
136
137 static GNUNET_SCHEDULER_TaskIdentifier abort_task;
138
139 /**
140  * Global test result
141  */
142 static int result;
143
144 /**
145  * Hosts successfully registered
146  */
147 static unsigned int host_registered;
148
149 /**
150  * Peers successfully started
151  */
152 static unsigned int peers_started;
153
154 /**
155  * The master controller host
156  */
157 struct GNUNET_TESTBED_Host* master_host;
158
159 /**
160  * The master controller process
161  */
162 static struct GNUNET_TESTBED_ControllerProc *master_proc;
163
164 /**
165  * Handle to master controller
166  */
167 static struct GNUNET_TESTBED_Controller *master_ctrl;
168
169 /**
170  * Slave host IP addresses
171  */
172 static char *slave_ips[NUM_HOSTS] = {"131.159.20.34", "131.159.20.59"};
173
174 /**
175  * The slave hosts
176  */
177 struct GNUNET_TESTBED_Host *slave_hosts[NUM_HOSTS];
178
179 /**
180  * Slave host registration handles
181  */
182 static struct GNUNET_TESTBED_HostRegistrationHandle *rh;
183
184 /**
185  * The peers
186  */
187 struct GNUNET_TESTBED_Peer *peers[TOTAL_PEERS];
188
189 /**
190  * Handle to global configuration
191  */
192 static struct GNUNET_CONFIGURATION_Handle *cfg;
193
194
195 /**
196  * Completion callback for shutdown
197  *
198  * @param cls the closure from GNUNET_STREAM_shutdown call
199  * @param operation the operation that was shutdown (SHUT_RD, SHUT_WR,
200  *          SHUT_RDWR) 
201  */
202 // static void 
203 // shutdown_completion (void *cls,
204 //                      int operation)
205 // {
206 //   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "STREAM shutdown successful\n");
207 //   GNUNET_SCHEDULER_add_now (&do_close, cls);
208 // }
209
210
211
212 /**
213  * Shutdown sockets gracefully
214  */
215 // static void
216 // do_shutdown (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
217 // {
218 //   result = GNUNET_OK;
219 //   peer1.shutdown_handle = GNUNET_STREAM_shutdown (peer1.socket, SHUT_RDWR,
220 //                                                   &shutdown_completion, cls);
221 // }
222
223
224 /**
225  * Something went wrong and timed out. Kill everything and set error flag
226  */
227 static void
228 do_abort (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
229 {
230   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: ABORT\n");
231   result = GNUNET_SYSERR;
232   abort_task = 0; 
233 }
234
235
236 /**
237  * Adapter function called to destroy a connection to
238  * a service.
239  * 
240  * @param cls closure
241  * @param op_result service handle returned from the connect adapter
242  */
243 // static void
244 // stream_da (void *cls, void *op_result)
245 // {
246 //   struct GNUNET_STREAM_ListenSocket *lsocket;
247 //   struct GNUNET_STREAM_Socket *socket;
248 // 
249 //   if (&peer1 == cls)
250 //   {
251 //     lsocket = op_result;
252 //     GNUNET_STREAM_listen_close (lsocket);
253 //     GNUNET_TESTBED_operation_done (peer2.op);
254 //     return;
255 //   }
256 //   if (&peer2 == cls)
257 //   {
258 //     socket = op_result;
259 //     GNUNET_STREAM_close (socket);
260 //     GNUNET_SCHEDULER_shutdown (); /* Exit point of the test */
261 //     return;
262 //   }
263 //   GNUNET_assert (0);
264 // }
265
266
267 /**
268  * Adapter function called to establish a connection to
269  * a service.
270  * 
271  * @param cls closure
272  * @param cfg configuration of the peer to connect to; will be available until
273  *          GNUNET_TESTBED_operation_done() is called on the operation returned
274  *          from GNUNET_TESTBED_service_connect()
275  * @return service handle to return in 'op_result', NULL on error
276  */
277 // static void * 
278 // stream_ca (void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg)
279 // {  
280 //   struct GNUNET_STREAM_ListenSocket *lsocket;
281 //   
282 //   switch (setup_state)
283 //   {
284 //   case PEER1_STREAM_CONNECT:
285 //     lsocket = GNUNET_STREAM_listen (cfg, 10, &stream_listen_cb, NULL,
286 //                                     GNUNET_STREAM_OPTION_SIGNAL_LISTEN_SUCCESS,
287 //                                     &stream_connect, GNUNET_STREAM_OPTION_END);
288 //     return lsocket;
289 //   case PEER2_STREAM_CONNECT:
290 //     peer2.socket = GNUNET_STREAM_open (cfg, &peer1.our_id, 10, &stream_open_cb,
291 //                                        &peer2, GNUNET_STREAM_OPTION_END);
292 //     return peer2.socket;
293 //   default:
294 //     GNUNET_assert (0);
295 //   }
296 // }
297
298
299 /**
300  * Listen success callback; connects a peer to stream as client
301  */
302 // static void
303 // stream_connect (void)
304 // { 
305 //   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Stream listen open successful\n");
306 //   peer2.op = GNUNET_TESTBED_service_connect (&peer2, peer2.peer, "stream",
307 //                                              NULL, NULL,
308 //                                              stream_ca, stream_da, &peer2);
309 //   setup_state = PEER2_STREAM_CONNECT;
310 // }
311
312
313 /**
314  * Callback to be called when the requested peer information is available
315  *
316  * @param cb_cls the closure from GNUNET_TETSBED_peer_get_information()
317  * @param op the operation this callback corresponds to
318  * @param pinfo the result; will be NULL if the operation has failed
319  * @param emsg error message if the operation has failed; will be NULL if the
320  *          operation is successfull
321  */
322 // static void 
323 // peerinfo_cb (void *cb_cls, struct GNUNET_TESTBED_Operation *op_,
324 //              const struct GNUNET_TESTBED_PeerInformation *pinfo,
325 //              const char *emsg)
326 // {
327 //   GNUNET_assert (NULL == emsg);
328 //   GNUNET_assert (op == op_);
329 //   switch (setup_state)
330 //     {
331 //     case PEER1_GET_IDENTITY:
332 //       memcpy (&peer1.our_id, pinfo->result.id, 
333 //               sizeof (struct GNUNET_PeerIdentity));
334 //       GNUNET_TESTBED_operation_done (op);
335 //       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Peer 1 id: %s\n", GNUNET_i2s
336 //                   (&peer1.our_id));
337 //       op = GNUNET_TESTBED_peer_get_information (peer2.peer,
338 //                                                 GNUNET_TESTBED_PIT_IDENTITY,
339 //                                                 &peerinfo_cb, NULL);
340 //       setup_state = PEER2_GET_IDENTITY;
341 //       break;
342 //     case PEER2_GET_IDENTITY:
343 //       memcpy (&peer2.our_id, pinfo->result.id,
344 //               sizeof (struct GNUNET_PeerIdentity));
345 //       GNUNET_TESTBED_operation_done (op);
346 //       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Peer 2 id: %s\n", GNUNET_i2s
347 //                   (&peer2.our_id));
348 //       peer1.op = GNUNET_TESTBED_service_connect (&peer1, peer1.peer, "stream",
349 //                                                  NULL, NULL, stream_ca,
350 //                                                  stream_da, &peer1);
351 //       setup_state = PEER1_STREAM_CONNECT;
352 //       break;
353 //     default:
354 //       GNUNET_assert (0);
355 //     }
356 // }
357
358
359 /**
360  * Controller event callback
361  *
362  * @param cls NULL
363  * @param event the controller event
364  */
365 // static void
366 // controller_event_cb (void *cls,
367 //                      const struct GNUNET_TESTBED_EventInformation *event)
368 // {
369 //   switch (event->type)
370 //   {
371 //   case GNUNET_TESTBED_ET_CONNECT:
372 //     GNUNET_assert (INIT == setup_state);
373 //     GNUNET_TESTBED_operation_done (op);
374 //     /* Get the peer identity and configuration of peers */
375 //     op = GNUNET_TESTBED_peer_get_information (peer1.peer,
376 //                                               GNUNET_TESTBED_PIT_IDENTITY,
377 //                                               &peerinfo_cb, NULL);
378 //     setup_state = PEER1_GET_IDENTITY;
379 //     break;
380 //   case GNUNET_TESTBED_ET_OPERATION_FINISHED:
381 //     switch (setup_state)
382 //     {    
383 //     case PEER1_STREAM_CONNECT:
384 //     case PEER2_STREAM_CONNECT:
385 //       GNUNET_assert (NULL == event->details.operation_finished.emsg);
386 //       break;
387 //     default:
388 //       GNUNET_assert (0);
389 //     }
390 //     break;
391 //   default:
392 //     GNUNET_assert (0);
393 //   }
394 // }
395
396
397 /**
398  * Signature of a main function for a testcase.
399  *
400  * @param cls closure
401  * @param num_peers number of peers in 'peers'
402  * @param peers handle to peers run in the testbed
403  */
404 // static void
405 // test_master (void *cls, unsigned int num_peers,
406 //              struct GNUNET_TESTBED_Peer **peers)
407 // {
408 //   GNUNET_assert (NULL != peers);
409 //   GNUNET_assert (NULL != peers[0]);
410 //   GNUNET_assert (NULL != peers[1]);
411 //   peer1.peer = peers[0];
412 //   peer2.peer = peers[1];
413 //   op = GNUNET_TESTBED_overlay_connect (NULL, NULL, NULL, peer2.peer, peer1.peer);
414 //   setup_state = INIT;
415 //   abort_task =
416 //     GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
417 //                                   (GNUNET_TIME_UNIT_SECONDS, 40), &do_abort,
418 //                                   NULL);
419 // }
420
421 /**
422  * Functions of this signature are called when a peer has been successfully
423  * started or stopped.
424  *
425  * @param cls the closure from GNUNET_TESTBED_peer_start/stop()
426  * @param emsg NULL on success; otherwise an error description
427  */
428 static void
429 peer_start_cb (void *cls, const char *emsg)
430 {
431   long i = (long) cls;
432   GNUNET_TESTBED_operation_done(op[i]);
433   peers_started++;
434   // FIXME create and start rest of PEERS_PER_HOST
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   op[i] = GNUNET_TESTBED_peer_start (peer, peer_start_cb, (void *) i);
462 }
463
464 /**
465  * Signature of the event handler function called by the
466  * respective event controller.
467  *
468  * @param cls closure
469  * @param event information about the event
470  */
471 static void
472 controller_cb (void *cls, const struct GNUNET_TESTBED_EventInformation *event)
473 {
474   long i;
475
476   switch (event->type)
477   {
478   case GNUNET_TESTBED_ET_PEER_START:
479     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " Peer started\n");
480 //     event->details.peer_start.peer;
481     break;
482   case GNUNET_TESTBED_ET_PEER_STOP:
483   case GNUNET_TESTBED_ET_CONNECT:
484     break;
485   case GNUNET_TESTBED_ET_OPERATION_FINISHED:
486     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  Operation finished\n");
487     if (NULL != event->details.operation_finished.emsg)
488     {
489       GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "%s\n",
490                   event->details.operation_finished.emsg);
491       GNUNET_assert (0);
492     }
493     GNUNET_TESTBED_operation_done (event->details.operation_finished.operation);
494     i = (long) event->details.operation_finished.op_cls;
495     op[i] = NULL;
496     switch (state[i])
497     {
498       case INIT:
499         GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  Init\n");
500         op[i] = GNUNET_TESTBED_peer_create (master_ctrl,
501                                             slave_hosts[i],
502                                             cfg,
503                                             peer_create_cb,
504                                             (void *) i);
505         break;
506       case REGISTERING:
507         GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  Register\n");
508         state[i] = LINKING;
509         GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " Linking host %u\n", i);
510         op[i] = GNUNET_TESTBED_controller_link (master_ctrl, slave_hosts[i],
511                                                 (void *) (long) i, cfg, GNUNET_YES);
512         break;
513       case LINKING:
514         GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  Link\n");
515         break;
516       default:
517         GNUNET_break (0);
518     }
519     break;
520   default:
521     GNUNET_break (0);
522   }
523 }
524
525 /**
526  * Callback which will be called to after a host registration succeeded or failed
527  *
528  * @param cls the host which has been registered
529  * @param emsg the error message; NULL if host registration is successful
530  */
531 static void
532 registration_cont (void *cls, const char *emsg)
533 {
534   if (NULL != emsg)
535   {
536     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "%s\n", emsg);
537     GNUNET_assert (0);
538   }
539   host_registered++;
540   if (NUM_HOSTS != host_registered)
541   {
542     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " Registering host %u\n",
543                 host_registered);
544     rh = GNUNET_TESTBED_register_host (master_ctrl,
545                                        slave_hosts[host_registered],
546                                        &registration_cont,
547                                        NULL);
548     state[host_registered] = REGISTERING;
549     return;
550   }
551 }
552
553 /**
554  * Callback to signal successfull startup of the controller process
555  *
556  * @param cls the closure from GNUNET_TESTBED_controller_start()
557  * @param cfg the configuration with which the controller has been started;
558  *          NULL if status is not GNUNET_OK
559  * @param status GNUNET_OK if the startup is successfull; GNUNET_SYSERR if not,
560  *          GNUNET_TESTBED_controller_stop() shouldn't be called in this case
561  */
562 static void
563 status_cb (void *cls, const struct GNUNET_CONFIGURATION_Handle *config,
564            int status)
565 {
566   unsigned int i;
567
568   event_mask = 0;
569   event_mask |= (1L << GNUNET_TESTBED_ET_PEER_START);
570   event_mask |= (1L << GNUNET_TESTBED_ET_PEER_STOP);
571   event_mask |= (1L << GNUNET_TESTBED_ET_CONNECT);
572   event_mask |= (1L << GNUNET_TESTBED_ET_OPERATION_FINISHED);
573   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connecting to master controller\n");
574   master_ctrl = GNUNET_TESTBED_controller_connect (config,
575                                                    master_host,
576                                                    event_mask,
577                                                    &controller_cb,
578                                                    NULL);
579   GNUNET_assert (NULL != master_ctrl);
580
581   for (i = 0; i < NUM_HOSTS; i++)
582   {
583     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " Creating host %u\n", i);
584     slave_hosts[i] = GNUNET_TESTBED_host_create_with_id (i+1, slave_ips[i], NULL, 0);
585     GNUNET_assert (NULL != slave_hosts[i]);
586   }
587   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " Registering host 0\n");
588   rh = GNUNET_TESTBED_register_host (master_ctrl, slave_hosts[0],
589                                      &registration_cont,
590                                      NULL);
591   state[0] = REGISTERING;
592   GNUNET_assert (NULL != rh);
593 }
594
595
596 /**
597  * Main run function.
598  *
599  * @param cls NULL
600  * @param args arguments passed to GNUNET_PROGRAM_run
601  * @param cfgfile the path to configuration file
602  * @param cfg the configuration file handle
603  */
604 static void
605 run (void *cls, char *const *args, const char *cfgfile,
606      const struct GNUNET_CONFIGURATION_Handle *config)
607 {
608   master_host = GNUNET_TESTBED_host_create (NULL, NULL, 0);
609   GNUNET_assert (NULL != master_host);
610   cfg = GNUNET_CONFIGURATION_dup (config);
611   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Starting master controller\n");
612   master_proc = GNUNET_TESTBED_controller_start ("127.0.0.1",
613                                                  master_host,
614                                                  cfg,
615                                                  status_cb,
616                                                  NULL);
617   abort_task =
618       GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
619                                     (GNUNET_TIME_UNIT_MINUTES, 60), &do_abort,
620                                     NULL);
621 }
622
623 /**
624  * Main function
625  */
626 int main (int argc, char **argv)
627 {
628   int ret;
629   struct GNUNET_GETOPT_CommandLineOption options[] = {
630     GNUNET_GETOPT_OPTION_END
631   };
632   char *const argv2[] = { "test_big",
633     "-c", "test_regex_big.conf",
634     NULL
635   };
636
637   result = GNUNET_SYSERR;
638
639   ret =
640       GNUNET_PROGRAM_run ((sizeof (argv2) / sizeof (char *)) - 1, argv2,
641                           "test_regex_big", "nohelp", options,
642                           &run, NULL);
643   
644   if (GNUNET_SYSERR == result || 0 != ret)
645     return 1;
646   return 0;
647 }