-added test_stream_local.c to standard checks
[oweals/gnunet.git] / src / stream / test_stream_2peers_halfclose.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 stream/test_stream_2peers_halfclose.c
23  * @brief Testcases for Stream API halfclosed connections between 2 peers
24  * @author Sree Harsha Totakura
25  */
26
27 #include <string.h>
28
29 #include "platform.h"
30 #include "gnunet_util_lib.h"
31 #include "gnunet_mesh_service.h"
32 #include "gnunet_stream_lib.h"
33 #include "gnunet_testing_lib.h"
34 #include "gnunet_scheduler_lib.h"
35
36 #define VERBOSE 1
37
38 /**
39  * Number of peers
40  */
41 #define NUM_PEERS 2
42
43 /**
44  * Structure for holding peer's sockets and IO Handles
45  */
46 struct PeerData
47 {
48   /**
49    * Peer's stream socket
50    */
51   struct GNUNET_STREAM_Socket *socket;
52
53   /**
54    * Peer's io write handle
55    */
56   struct GNUNET_STREAM_IOWriteHandle *io_write_handle;
57
58   /**
59    * Peer's io read handle
60    */
61   struct GNUNET_STREAM_IOReadHandle *io_read_handle;
62
63   /**
64    * Peer's shutdown handle
65    */
66   struct GNUNET_STREAM_ShutdownHandle *shutdown_handle;
67
68   /**
69    * Our Peer id
70    */
71   struct GNUNET_PeerIdentity our_id;
72
73   /**
74    * Bytes the peer has written
75    */
76   unsigned int bytes_wrote;
77
78   /**
79    * Byte the peer has read
80    */
81   unsigned int bytes_read;
82
83   /**
84    * GNUNET_YES if the peer has successfully completed the current test
85    */
86   unsigned int test_ok;
87
88   /**
89    * The shutdown operation that has to be used by the stream_shutdown_task
90    */
91   int shutdown_operation;
92 };
93
94 /**
95  * The current peer group
96  */
97 static struct GNUNET_TESTING_PeerGroup *pg;
98
99 /**
100  * Peer 1 daemon
101  */
102 static struct GNUNET_TESTING_Daemon *d1;
103
104 /**
105  * Peer 2 daemon
106  */
107 static struct GNUNET_TESTING_Daemon *d2;
108
109
110 /**
111  * Peer1 writes first and then calls for SHUT_WR
112  * Peer2 reads first and then calls for SHUT_RD
113  * Attempt to write again by Peer1 should be rejected
114  * Attempt to read again by Peer2 should be rejected
115  * Peer1 then reads from Peer2 which writes
116  */
117 static struct PeerData peer1;
118 static struct PeerData peer2;
119 static struct GNUNET_STREAM_ListenSocket *peer2_listen_socket;
120 static struct GNUNET_CONFIGURATION_Handle *config;
121
122 static GNUNET_SCHEDULER_TaskIdentifier abort_task;
123 static GNUNET_SCHEDULER_TaskIdentifier read_task;
124
125 static char *data = "ABCD";
126 static int result;
127
128 /**
129  * Enumeration for various tests that are to be passed in the same order as
130  * below
131  */
132 enum Test
133   {
134     /**
135      * Peer1 writing; Peer2 reading
136      */
137     PEER1_WRITE,
138
139     /**
140      * Peer1 write shutdown; Peer2 should get an error when it tries to read;
141      */
142     PEER1_WRITE_SHUTDOWN,
143
144     /**
145      * Peer1 reads; Peer2 writes (connection is halfclosed)
146      */
147     PEER1_HALFCLOSE_READ,
148
149     /**
150      * Peer1 attempts to write; Should fail with stream already shutdown error
151      */
152     PEER1_HALFCLOSE_WRITE_FAIL,
153
154     /**
155      * Peer1 read shutdown; Peer2 should get stream shutdown error during write
156      */
157     PEER1_READ_SHUTDOWN,
158
159     /**
160      * All tests successfully finished
161      */
162     SUCCESS
163   };
164
165 /**
166  * Current running test
167  */
168 enum Test current_test;
169
170 /**
171  * Input processor
172  *
173  * @param cls the closure from GNUNET_STREAM_write/read
174  * @param status the status of the stream at the time this function is called
175  * @param data traffic from the other side
176  * @param size the number of bytes available in data read 
177  * @return number of bytes of processed from 'data' (any data remaining should be
178  *         given to the next time the read processor is called).
179  */
180 static size_t
181 input_processor (void *cls,
182                  enum GNUNET_STREAM_Status status,
183                  const void *input_data,
184                  size_t size);
185
186
187 /**
188  * The transition function; responsible for the transitions among tests
189  */
190 static void
191 transition();
192
193
194 /**
195  * Task for calling STREAM_read
196  *
197  * @param cls the peer data entity
198  * @param tc the task context
199  */
200 static void
201 stream_read_task (void *cls,
202                   const struct GNUNET_SCHEDULER_TaskContext *tc)
203 {
204   struct PeerData *peer = cls;
205   
206   peer->io_read_handle = GNUNET_STREAM_read (peer->socket,
207                                              GNUNET_TIME_relative_multiply
208                                              (GNUNET_TIME_UNIT_SECONDS, 5),
209                                              &input_processor,
210                                              cls);
211   switch (current_test)
212     {
213     case PEER1_WRITE_SHUTDOWN:
214       GNUNET_assert (&peer2 == peer);
215       GNUNET_assert (NULL == peer->io_read_handle);
216       transition ();            /* to PEER1_HALFCLOSE_READ */
217       break;
218     default:
219       GNUNET_assert (NULL != peer->io_read_handle);
220     }
221 }
222
223
224 /**
225  * The write completion function; called upon writing some data to stream or
226  * upon error
227  *
228  * @param cls the closure from GNUNET_STREAM_write/read
229  * @param status the status of the stream at the time this function is called
230  * @param size the number of bytes read or written
231  */
232 static void 
233 write_completion (void *cls,
234                   enum GNUNET_STREAM_Status status,
235                   size_t size);
236
237
238 /**
239  * Task for calling STREAM_write
240  *
241  * @param cls the peer data entity
242  * @param tc the task context
243  */
244 static void
245 stream_write_task (void *cls,
246                    const struct GNUNET_SCHEDULER_TaskContext *tc)
247 {
248   struct PeerData *peer = cls;
249   
250   peer->io_write_handle = 
251     GNUNET_STREAM_write (peer->socket,
252                          (void *) data,
253                          strlen(data) - peer->bytes_wrote,
254                          GNUNET_TIME_relative_multiply
255                          (GNUNET_TIME_UNIT_SECONDS, 5),
256                          &write_completion,
257                          peer);
258   switch (current_test)
259     {
260     case PEER1_HALFCLOSE_WRITE_FAIL:
261       GNUNET_assert (&peer1 == peer);
262       GNUNET_assert (NULL == peer->io_write_handle);
263       transition();             /* To PEER1_READ_SHUTDOWN */
264       break;
265     case PEER1_READ_SHUTDOWN:
266       GNUNET_assert (&peer2 == peer);
267       GNUNET_assert (NULL == peer->io_write_handle);
268       transition ();            /* To SUCCESS */
269       break;
270     default:
271         GNUNET_assert (NULL != peer->io_write_handle);
272     }
273 }
274
275
276 /**
277  * Check whether peers successfully shut down.
278  */
279 static void
280 peergroup_shutdown_callback (void *cls, const char *emsg)
281 {
282   if (emsg != NULL)
283   {
284     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
285                 "Shutdown of peers failed!\n");
286   }
287   else
288   {
289     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
290                 "All peers successfully shut down!\n");
291   }
292   GNUNET_CONFIGURATION_destroy (config);
293 }
294
295
296 /**
297  * Close sockets and stop testing deamons nicely
298  */
299 static void
300 do_close (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
301 {
302   if (NULL != peer1.socket)
303     GNUNET_STREAM_close (peer1.socket);
304   if (NULL != peer2.socket)
305     GNUNET_STREAM_close (peer2.socket);
306   if (NULL != peer2_listen_socket)
307     GNUNET_STREAM_listen_close (peer2_listen_socket);
308
309   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: shutdown\n");
310   if (0 != abort_task)
311   {
312     GNUNET_SCHEDULER_cancel (abort_task);
313   }
314
315   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: Wait\n");
316
317   GNUNET_TESTING_daemons_stop (pg,
318                                GNUNET_TIME_relative_multiply
319                                (GNUNET_TIME_UNIT_SECONDS, 5),
320                                &peergroup_shutdown_callback,
321                                NULL);
322 }
323
324
325 /**
326  * Completion callback for shutdown
327  *
328  * @param cls the closure from GNUNET_STREAM_shutdown call
329  * @param operation the operation that was shutdown (SHUT_RD, SHUT_WR,
330  *          SHUT_RDWR) 
331  */
332 void 
333 shutdown_completion (void *cls,
334                      int operation)
335 {
336   switch (current_test)
337     {
338     case PEER1_WRITE:
339       GNUNET_assert (0);
340     case PEER1_WRITE_SHUTDOWN:
341       peer1.test_ok = GNUNET_YES;
342       /* Peer2 should read with error */
343       peer2.bytes_read = 0;
344       GNUNET_SCHEDULER_add_now (&stream_read_task, &peer2);
345       break;
346     case PEER1_READ_SHUTDOWN:
347       peer1.test_ok = GNUNET_YES;
348       peer2.bytes_wrote = 0;
349       GNUNET_SCHEDULER_add_now (&stream_write_task, &peer2);
350       break;
351     case PEER1_HALFCLOSE_READ:
352     case PEER1_HALFCLOSE_WRITE_FAIL:
353     case SUCCESS:
354       GNUNET_assert (0);        /* We shouldn't reach here */
355     }
356 }
357
358
359 /**
360  * Task for calling STREAM_shutdown
361  *
362  * @param cls the peer entity
363  * @param tc the TaskContext
364  */
365 static void
366 stream_shutdown_task (void *cls,
367                       const struct GNUNET_SCHEDULER_TaskContext *tc)
368 {
369   struct PeerData *peer = cls;
370
371   peer->shutdown_handle = GNUNET_STREAM_shutdown (peer->socket,
372                                                   peer->shutdown_operation,
373                                                   &shutdown_completion,
374                                                   peer);
375   GNUNET_assert (NULL != peer->shutdown_handle);
376 }
377
378
379 /**
380  * Something went wrong and timed out. Kill everything and set error flag
381  */
382 static void
383 do_abort (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
384 {
385   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: ABORT\n");
386   if (0 != read_task)
387     {
388       GNUNET_SCHEDULER_cancel (read_task);
389     }
390   result = GNUNET_SYSERR;
391   abort_task = 0;
392   do_close (cls, tc);  
393 }
394
395
396 /**
397  * The transition function; responsible for the transitions among tests
398  */
399 static void
400 transition()
401 {
402   if ((GNUNET_YES == peer1.test_ok) && (GNUNET_YES == peer2.test_ok))
403     {
404       peer1.test_ok = GNUNET_NO;
405       peer2.test_ok = GNUNET_NO;
406       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
407                   "TEST %d SUCCESSFULL\n", current_test);
408       switch (current_test)
409         {
410         case PEER1_WRITE:
411           current_test = PEER1_WRITE_SHUTDOWN;
412           /* Peer1 should shutdown writing */
413           peer1.shutdown_operation = SHUT_WR;
414           GNUNET_SCHEDULER_add_now (&stream_shutdown_task, &peer1);
415           break;
416         case PEER1_WRITE_SHUTDOWN:
417           current_test = PEER1_HALFCLOSE_READ;
418           /* Peer2 should be able to write successfully */
419           peer2.bytes_wrote = 0;
420           GNUNET_SCHEDULER_add_now (&stream_write_task, &peer2);
421           
422           /* Peer1 should be able to read successfully */
423           peer1.bytes_read = 0;
424           GNUNET_SCHEDULER_add_now (&stream_read_task, &peer1);
425           break;
426         case PEER1_HALFCLOSE_READ:
427           current_test = PEER1_HALFCLOSE_WRITE_FAIL;
428           peer1.bytes_wrote = 0;
429           peer2.bytes_read = 0;
430           peer2.test_ok = GNUNET_YES;
431           GNUNET_SCHEDULER_add_now (&stream_write_task, &peer1);
432           break;
433         case PEER1_HALFCLOSE_WRITE_FAIL:
434           current_test = PEER1_READ_SHUTDOWN;
435           peer1.shutdown_operation = SHUT_RD;
436           GNUNET_SCHEDULER_add_now (&stream_shutdown_task, &peer1);
437           break;
438         case PEER1_READ_SHUTDOWN:
439           current_test = SUCCESS;
440           GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
441                       "All tests successful\n");
442           GNUNET_SCHEDULER_add_now (&do_close, NULL);
443           break;
444         case SUCCESS:
445           GNUNET_assert (0);    /* We shouldn't reach here */
446           
447         }
448     }
449 }
450
451 /**
452  * The write completion function; called upon writing some data to stream or
453  * upon error
454  *
455  * @param cls the closure from GNUNET_STREAM_write/read
456  * @param status the status of the stream at the time this function is called
457  * @param size the number of bytes read or written
458  */
459 static void 
460 write_completion (void *cls,
461                   enum GNUNET_STREAM_Status status,
462                   size_t size)
463 {
464   struct PeerData *peer = cls;
465
466   switch (current_test)
467     {
468     case PEER1_WRITE:
469     case PEER1_HALFCLOSE_READ:
470
471     GNUNET_assert (GNUNET_STREAM_OK == status);
472     GNUNET_assert (size <= strlen (data));
473     peer->bytes_wrote += size;
474
475     if (peer->bytes_wrote < strlen(data)) /* Have more data to send */
476       {
477         GNUNET_SCHEDULER_add_now (&stream_write_task, peer);
478       }
479     else
480       {
481         GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
482                     "Writing completed\n");
483
484         if (&peer1 == peer)
485           {
486             peer1.test_ok = GNUNET_YES;
487             transition ();       /* to PEER1_WRITE_SHUTDOWN */
488           }
489         else            /* This will happen during PEER1_HALFCLOSE_READ */
490           {
491             peer2.test_ok = GNUNET_YES;
492             transition ();      /* to PEER1_HALFCLOSE_WRITE_FAIL */
493           }
494       }
495     break;
496     case PEER1_HALFCLOSE_WRITE_FAIL:
497       GNUNET_assert (peer == &peer1);
498       GNUNET_assert (GNUNET_STREAM_SHUTDOWN == status);
499       GNUNET_assert (0 == size);
500       peer1.test_ok = GNUNET_YES;
501       break;
502     case PEER1_READ_SHUTDOWN:
503       GNUNET_assert (peer == &peer2);
504       GNUNET_assert (GNUNET_STREAM_SHUTDOWN == status);
505       GNUNET_assert (0 == size);
506       peer2.test_ok = GNUNET_YES;
507       break;
508     case PEER1_WRITE_SHUTDOWN:
509     case SUCCESS:
510       GNUNET_assert (0);        /* We shouldn't reach here */
511     } 
512 }
513
514
515 /**
516  * Function executed after stream has been established
517  *
518  * @param cls the closure from GNUNET_STREAM_open
519  * @param socket socket to use to communicate with the other side (read/write)
520  */
521 static void 
522 stream_open_cb (void *cls,
523                 struct GNUNET_STREAM_Socket *socket)
524 {
525   struct PeerData *peer;
526
527   GNUNET_assert (socket == peer1.socket);
528   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
529               "%s: Stream established from peer1\n",
530               GNUNET_i2s (&peer1.our_id));
531   peer = (struct PeerData *) cls;
532   peer->bytes_wrote = 0;
533   GNUNET_assert (socket == peer1.socket);
534   GNUNET_assert (socket == peer->socket);
535   peer1.test_ok = GNUNET_NO;
536   peer2.test_ok = GNUNET_NO;
537   current_test = PEER1_WRITE;
538   GNUNET_SCHEDULER_add_now (&stream_write_task, peer);
539 }
540
541
542 /**
543  * Input processor
544  *
545  * @param cls the closure from GNUNET_STREAM_write/read
546  * @param status the status of the stream at the time this function is called
547  * @param data traffic from the other side
548  * @param size the number of bytes available in data read 
549  * @return number of bytes of processed from 'data' (any data remaining should be
550  *         given to the next time the read processor is called).
551  */
552 static size_t
553 input_processor (void *cls,
554                  enum GNUNET_STREAM_Status status,
555                  const void *input_data,
556                  size_t size)
557 {
558   struct PeerData *peer;
559
560   peer = (struct PeerData *) cls;
561
562   switch (current_test)
563     {
564     case PEER1_WRITE:
565     case PEER1_HALFCLOSE_READ:
566       if (GNUNET_STREAM_TIMEOUT == status)
567         {
568           GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
569                       "Read operation timedout - reading again!\n");
570           GNUNET_assert (0 == size);
571           GNUNET_SCHEDULER_add_now (&stream_read_task, peer);
572           return 0;
573         }
574
575       GNUNET_assert (GNUNET_STREAM_OK == status);
576       GNUNET_assert (size <= strlen (data));
577       GNUNET_assert (0 == strncmp ((const char *) data + peer->bytes_read,
578                                    (const char *) input_data,
579                                    size));
580       peer->bytes_read += size;
581   
582       if (peer->bytes_read < strlen (data))
583         {
584           GNUNET_SCHEDULER_add_now (&stream_read_task, peer);
585         }
586       else  
587         {
588           if (&peer2 == peer) /* Peer2 has completed reading; should write */
589             {
590               peer2.test_ok = GNUNET_YES;
591               transition ();    /* Transition to PEER1_WRITE_SHUTDOWN */
592             }
593           else         /* Peer1 has completed reading. End of tests */
594             {
595               peer1.test_ok = GNUNET_YES;
596               transition ();    /* to PEER1_HALFCLOSE_WRITE_FAIL */
597             }
598         }
599       break;
600     case PEER1_WRITE_SHUTDOWN:
601       GNUNET_assert (GNUNET_STREAM_SHUTDOWN == status);
602       peer2.test_ok = GNUNET_YES;
603       break;
604     case PEER1_HALFCLOSE_WRITE_FAIL:
605     case PEER1_READ_SHUTDOWN:
606     case SUCCESS:
607       GNUNET_assert (0);        /* We shouldn't reach here */
608     }
609   
610   return size;
611 }
612
613   
614 /**
615  * Scheduler call back; to be executed when a new stream is connected
616  * Called from listen connect for peer2
617  */
618 static void
619 stream_read (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
620 {
621   read_task = GNUNET_SCHEDULER_NO_TASK;
622   GNUNET_assert (NULL != cls);
623   peer2.bytes_read = 0;
624   GNUNET_SCHEDULER_add_now (&stream_read_task, &peer2);
625 }
626
627
628 /**
629  * Functions of this type are called upon new stream connection from other peers
630  *
631  * @param cls the closure from GNUNET_STREAM_listen
632  * @param socket the socket representing the stream
633  * @param initiator the identity of the peer who wants to establish a stream
634  *            with us
635  * @return GNUNET_OK to keep the socket open, GNUNET_SYSERR to close the
636  *             stream (the socket will be invalid after the call)
637  */
638 static int
639 stream_listen_cb (void *cls,
640                   struct GNUNET_STREAM_Socket *socket,
641                   const struct GNUNET_PeerIdentity *initiator)
642 {
643   GNUNET_assert (NULL != socket);
644   GNUNET_assert (NULL != initiator);
645   GNUNET_assert (socket != peer1.socket);
646
647   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
648               "%s: Peer connected: %s\n",
649               GNUNET_i2s (&peer2.our_id),
650               GNUNET_i2s(initiator));
651
652   peer2.socket = socket;
653   /* FIXME: reading should be done right now instead of a scheduled call */
654   read_task = GNUNET_SCHEDULER_add_now (&stream_read, (void *) socket);
655   return GNUNET_OK;
656 }
657
658
659 /**
660  * Callback to be called when testing peer group is ready
661  *
662  * @param cls NULL
663  * @param emsg NULL on success
664  */
665 void
666 peergroup_ready (void *cls, const char *emsg)
667 {
668   if (NULL != emsg)
669     {
670       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
671                   "Starting peer group failed: %s\n", emsg);
672       return;
673     }
674   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
675               "Peer group is now ready\n");
676   
677   GNUNET_assert (2 == GNUNET_TESTING_daemons_running (pg));
678   
679   d1 = GNUNET_TESTING_daemon_get (pg, 0);
680   GNUNET_assert (NULL != d1);
681   
682   d2 = GNUNET_TESTING_daemon_get (pg, 1);
683   GNUNET_assert (NULL != d2);
684
685   GNUNET_TESTING_get_peer_identity (d1->cfg,
686                                     &peer1.our_id);
687   GNUNET_TESTING_get_peer_identity (d2->cfg,
688                                     &peer2.our_id);
689   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
690               "%s : %s\n",
691               GNUNET_i2s (&peer1.our_id),
692               GNUNET_i2s (&d1->id));
693   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
694               "%s : %s\n",
695               GNUNET_i2s (&peer2.our_id),
696               GNUNET_i2s (&d2->id));
697
698   peer2_listen_socket = GNUNET_STREAM_listen (d2->cfg,
699                                               10, /* App port */
700                                               &stream_listen_cb,
701                                               NULL);
702   GNUNET_assert (NULL != peer2_listen_socket);
703
704   /* Connect to stream library */
705   peer1.socket = GNUNET_STREAM_open (d1->cfg,
706                                      &d2->id,         /* Null for local peer? */
707                                      10,           /* App port */
708                                      &stream_open_cb,
709                                      &peer1);
710   GNUNET_assert (NULL != peer1.socket);
711 }
712
713
714 /**
715  * Initialize framework and start test
716  */
717 static void
718 run (void *cls, char *const *args, const char *cfgfile,
719      const struct GNUNET_CONFIGURATION_Handle *cfg)
720 {
721   struct GNUNET_TESTING_Host *hosts; /* FIXME: free hosts (DLL) */
722
723   /* GNUNET_log_setup ("test_stream_local", */
724   /*                   "DEBUG", */
725   /*                   NULL); */
726
727   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
728               "Starting test\n");
729   /* Duplicate the configuration */
730   config = GNUNET_CONFIGURATION_dup (cfg);
731
732   hosts = GNUNET_TESTING_hosts_load (config);
733   
734   pg = GNUNET_TESTING_peergroup_start (config,
735                                        2,
736                                        GNUNET_TIME_relative_multiply
737                                        (GNUNET_TIME_UNIT_SECONDS, 3),
738                                        NULL,
739                                        &peergroup_ready,
740                                        NULL,
741                                        hosts);
742   GNUNET_assert (NULL != pg);
743                                        
744   abort_task =
745     GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
746                                   (GNUNET_TIME_UNIT_SECONDS, 40), &do_abort,
747                                   NULL);
748 }
749
750 /**
751  * Main function
752  */
753 int main (int argc, char **argv)
754 {
755   int ret;
756
757   char *argv2[] = { "test-stream-2peers-halfclose",
758                     "-L", "DEBUG",
759                     "-c", "test_stream_local.conf",
760                     NULL};
761   
762   struct GNUNET_GETOPT_CommandLineOption options[] = {
763     GNUNET_GETOPT_OPTION_END
764   };
765
766   ret =
767       GNUNET_PROGRAM_run ((sizeof (argv2) / sizeof (char *)) - 1, argv2,
768                           "test-stream-2peers-halfclose", "nohelp", options, &run, NULL);
769
770   if (GNUNET_OK != ret)
771   {
772     GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "run failed with error code %d\n",
773                 ret);
774     return 1;
775   }
776   if (GNUNET_SYSERR == result)
777   {
778     GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "test failed\n");
779     return 1;
780   }
781   GNUNET_log (GNUNET_ERROR_TYPE_INFO, "test ok\n");
782   return 0;
783 }