Removing all the tests for the bluetooth transport plugin.
[oweals/gnunet.git] / src / transport / transport-testing.c
1 /*
2      This file is part of GNUnet.
3      (C) 2006, 2009 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 transport-testing.c
23  * @brief testing lib for transport service
24  *
25  * @author Matthias Wachs
26  */
27
28 #include "transport-testing.h"
29
30
31 static struct PeerContext *
32 find_peer_context (struct GNUNET_TRANSPORT_TESTING_handle *tth,
33                    const struct GNUNET_PeerIdentity *peer)
34 {
35   GNUNET_assert (tth != NULL);
36   struct PeerContext *t = tth->p_head;
37
38   while (t != NULL)
39   {
40     if (0 == memcmp (&t->id, peer, sizeof (struct GNUNET_PeerIdentity)))
41       break;
42     t = t->next;
43   }
44
45   return t;
46 }
47
48
49 static struct ConnectingContext *
50 find_connecting_context (struct GNUNET_TRANSPORT_TESTING_handle *tth,
51                          struct PeerContext *p1, struct PeerContext *p2)
52 {
53   GNUNET_assert (tth != NULL);
54   struct ConnectingContext *cc = tth->cc_head;
55
56   while (cc != NULL)
57   {
58     if ((cc->p1 == p1) && (cc->p2 == p2))
59       break;
60     if ((cc->p1 == p2) && (cc->p2 == p1))
61       break;
62     cc = cc->next;
63   }
64
65   return cc;
66 }
67
68
69 static void
70 notify_connect (void *cls, const struct GNUNET_PeerIdentity *peer)
71 {
72   struct PeerContext *p = cls;
73   char *p2_s;
74   struct PeerContext *p2;
75
76   GNUNET_assert (NULL != p);
77   GNUNET_assert (NULL != p->tth);
78   p2 = find_peer_context (p->tth, peer);
79   if (p->nc != NULL)
80     p->nc (p->cb_cls, peer);
81
82   if (p2 != NULL)
83     GNUNET_asprintf (&p2_s, "%u (`%s')", p2->no, GNUNET_i2s (&p2->id));
84   else
85     GNUNET_asprintf (&p2_s, "`%s'", GNUNET_i2s (peer));
86   GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "transport-testing",
87                    "Peers %s connected to peer %u (`%s')\n", p2_s, p->no,
88                    GNUNET_i2s (&p->id));
89   GNUNET_free (p2_s);
90
91   /* Find ConnectingContext */
92   struct ConnectingContext *cc = find_connecting_context (p->tth, p, p2);
93
94   if (cc == NULL)
95     return;
96
97   if (p == cc->p1)
98     cc->p1_c = GNUNET_YES;
99
100   if (p == cc->p2)
101     cc->p2_c = GNUNET_YES;
102
103   if ((cc->p1_c == GNUNET_YES) && (cc->p2_c == GNUNET_YES))
104   {
105     cc->cb (cc->p1, cc->p2, cc->cb_cls);
106     GNUNET_TRANSPORT_TESTING_connect_peers_cancel (p->tth, cc);
107   }
108 }
109
110
111 static void
112 notify_disconnect (void *cls, const struct GNUNET_PeerIdentity *peer)
113 {
114   struct PeerContext *p = cls;
115
116   /* Find PeerContext */
117   int no = 0;
118   struct PeerContext *p2 = NULL;
119
120   if (p != NULL)
121   {
122     GNUNET_assert (p->tth != NULL);
123     p2 = find_peer_context (p->tth, peer);
124     no = p->no;
125   }
126
127   char *p2_s;
128
129   if (p2 != NULL)
130     GNUNET_asprintf (&p2_s, "%u (`%s')", p2->no, GNUNET_i2s (&p2->id));
131   else
132     GNUNET_asprintf (&p2_s, "`%s'", GNUNET_i2s (peer));
133   GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "transport-testing",
134                    "Peers %s disconnected from peer %u (`%s')\n", p2_s, no,
135                    GNUNET_i2s (&p->id));
136   GNUNET_free (p2_s);
137
138   if (p == NULL)
139     return;
140   if (p->nd != NULL)
141     p->nd (p->cb_cls, peer);
142 }
143
144
145 static void
146 notify_receive (void *cls, const struct GNUNET_PeerIdentity *peer,
147                 const struct GNUNET_MessageHeader *message)
148 {
149   struct PeerContext *p = cls;
150
151   if (p == NULL)
152     return;
153   if (p->rec != NULL)
154     p->rec (p->cb_cls, peer, message);
155 }
156
157
158 static void
159 get_hello (void *cb_cls, const struct GNUNET_MessageHeader *message)
160 {
161   struct PeerContext *p = cb_cls;
162   struct GNUNET_PeerIdentity hello_id;
163
164   GNUNET_assert (message != NULL);
165   GNUNET_assert (GNUNET_OK ==
166                  GNUNET_HELLO_get_id ((const struct GNUNET_HELLO_Message *)
167                                       message, &hello_id));
168   GNUNET_assert (0 == memcmp (&hello_id, &p->id, sizeof (hello_id)));
169   GNUNET_free_non_null (p->hello);
170   p->hello = (struct GNUNET_HELLO_Message *) GNUNET_copy_message (message);
171
172   if (NULL != p->start_cb)
173   {
174     GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "transport-testing",
175                      "Peer %u (`%s') successfully started\n", p->no,
176                      GNUNET_i2s (&p->id));
177     p->start_cb (p, p->cb_cls);
178     p->start_cb = NULL;
179   }
180 }
181
182
183 static void
184 try_connect (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
185 {
186   struct ConnectingContext *cc = cls;
187   struct PeerContext *p1 = cc->p1;
188   struct PeerContext *p2 = cc->p2;
189
190   cc->tct = GNUNET_SCHEDULER_NO_TASK;
191   if ((tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN) != 0)
192     return;
193
194   GNUNET_assert (cc != NULL);
195   GNUNET_assert (cc->p1 != NULL);
196   GNUNET_assert (cc->p2 != NULL);
197
198   char *p2_s = GNUNET_strdup (GNUNET_i2s (&p2->id));
199
200   GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "transport-testing",
201                    "Asking peer %u (`%s') to connect peer %u (`%s'), providing HELLO with %u bytes\n",
202                    p1->no, GNUNET_i2s (&p1->id), p2->no, p2_s,
203                    GNUNET_HELLO_size (cc->p2->hello));
204   GNUNET_free (p2_s);
205
206   GNUNET_TRANSPORT_offer_hello (cc->th_p1,
207                                 (const struct GNUNET_MessageHeader *) cc->
208                                 p2->hello, NULL, NULL);
209   GNUNET_TRANSPORT_try_connect (cc->th_p1, &p2->id, NULL, NULL); /*FIXME TRY_CONNECT change */
210
211   cc->tct =
212       GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS, &try_connect, cc);
213 }
214
215
216 /**
217  * Start a peer with the given configuration
218  * @param tth the testing handle
219  * @param cfgname configuration file
220  * @param peer_id a unique number to identify the peer
221  * @param rec receive callback
222  * @param nc connect callback
223  * @param nd disconnect callback
224  * @param start_cb start callback
225  * @param cb_cls closure for callback
226  * @return the peer context
227  */
228 struct PeerContext *
229 GNUNET_TRANSPORT_TESTING_start_peer (struct GNUNET_TRANSPORT_TESTING_handle *tth,
230                                      const char *cfgname, int peer_id,
231                                      GNUNET_TRANSPORT_ReceiveCallback rec,
232                                      GNUNET_TRANSPORT_NotifyConnect nc,
233                                      GNUNET_TRANSPORT_NotifyDisconnect nd,
234                                      GNUNET_TRANSPORT_TESTING_start_cb start_cb,
235                                      void *cb_cls)
236 {
237   char *emsg = NULL;
238   struct GNUNET_PeerIdentity *dummy;
239
240   GNUNET_assert (NULL != tth);
241   GNUNET_assert (NULL != tth->tl_system);
242
243   if (GNUNET_DISK_file_test (cfgname) == GNUNET_NO)
244   {
245     GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, "transport-testing",
246                      "File not found: `%s' \n", cfgname);
247     return NULL;
248   }
249
250   struct PeerContext *p = GNUNET_malloc (sizeof (struct PeerContext));
251   GNUNET_CONTAINER_DLL_insert (tth->p_head, tth->p_tail, p);
252
253   /* Create configuration and call testing lib to modify it */
254   p->cfg = GNUNET_CONFIGURATION_create ();
255   GNUNET_assert (GNUNET_OK == GNUNET_CONFIGURATION_load (p->cfg, cfgname));
256
257   if (GNUNET_SYSERR == GNUNET_TESTING_configuration_create (tth->tl_system, p->cfg))
258   {
259     GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, "transport-testing",
260                      "Testing library failed to create unique configuration based on `%s'\n",
261                      cfgname);
262     GNUNET_free (p);
263     return NULL;
264   }
265
266   p->no = peer_id;
267   /* Configure peer with configuration */
268   p->peer = GNUNET_TESTING_peer_configure (tth->tl_system, p->cfg, p->no, NULL, &emsg);
269   if (NULL == p->peer)
270   {
271     GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, "transport-testing",
272                      "Testing library failed to create unique configuration based on `%s': `%s'\n",
273                      cfgname, emsg);
274     GNUNET_TRANSPORT_TESTING_stop_peer (tth, p);
275     GNUNET_free_non_null (emsg);
276     return NULL;
277   }
278   GNUNET_free_non_null (emsg);
279   if (GNUNET_OK != GNUNET_TESTING_peer_start (p->peer))
280   {
281     GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, "transport-testing",
282                      "Testing library failed to create unique configuration based on `%s'\n",
283                      cfgname);
284     GNUNET_TRANSPORT_TESTING_stop_peer (tth, p);
285     return NULL;
286   }
287
288   memset(&dummy, '\0', sizeof (dummy));
289   GNUNET_TESTING_peer_get_identity (p->peer, &p->id);
290   if (0 == memcmp (&dummy, &p->id, sizeof (struct GNUNET_PeerIdentity)))
291   {
292     GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, "transport-testing",
293                      "Testing library failed to obtain peer identity for peer %u\n",
294                      p->no);
295     GNUNET_TRANSPORT_TESTING_stop_peer (tth, p);
296     return NULL;
297   }
298   else
299   {
300     GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "transport-testing",
301                      "Peer %u configured with identity `%s'\n",
302                      p->no,
303                      GNUNET_i2s (&p->id));
304   }
305
306   p->tth = tth;
307   p->nc = nc;
308   p->nd = nd;
309   p->rec = rec;
310   p->start_cb = start_cb;
311   if (cb_cls != NULL)
312     p->cb_cls = cb_cls;
313   else
314     p->cb_cls = p;
315
316   p->th = GNUNET_TRANSPORT_connect (p->cfg, NULL, p,
317                                     &notify_receive,
318                                     &notify_connect, &notify_disconnect);
319   if (NULL == p->th)
320   {
321     GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, "transport-testing",
322                      "Failed to connect to transport service for peer  `%s': `%s'\n",
323                      cfgname, emsg);
324     GNUNET_TRANSPORT_TESTING_stop_peer (tth, p);
325     return NULL;
326   }
327
328   p->ghh = GNUNET_TRANSPORT_get_hello (p->th, &get_hello, p);
329   GNUNET_assert (p->ghh != NULL);
330
331   return p;
332 }
333
334 /**
335 * Restart the given peer
336 * @param tth testing handle
337 * @param p the peer
338 * @param cfgname the cfg file used to restart
339 * @param restart_cb callback to call when restarted
340 * @param cb_cls callback closure
341 * @return GNUNET_OK in success otherwise GNUNET_SYSERR
342 */
343 int
344 GNUNET_TRANSPORT_TESTING_restart_peer (struct GNUNET_TRANSPORT_TESTING_handle
345                                        *tth, struct PeerContext *p,
346                                        const char *cfgname,
347                                        GNUNET_TRANSPORT_TESTING_start_cb
348                                        restart_cb, void *cb_cls)
349 {
350   GNUNET_assert (tth != NULL);
351   GNUNET_assert (p != NULL);
352   GNUNET_assert (NULL != p->peer);
353
354   GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "transport-testing",
355                    "Restarting peer %u (`%s')\n", p->no, GNUNET_i2s (&p->id));
356
357   /* shutdown */
358   GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "transport-testing",
359                    "Stopping peer %u (`%s')\n", p->no, GNUNET_i2s (&p->id));
360   if (NULL != p->ghh)
361     GNUNET_TRANSPORT_get_hello_cancel (p->ghh);
362   p->ghh = NULL;
363
364   if (NULL != p->th)
365     GNUNET_TRANSPORT_disconnect (p->th);
366
367   if (GNUNET_SYSERR == GNUNET_TESTING_peer_stop(p->peer))
368   {
369     GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, "transport-testing",
370                      "Failed to stop peer %u (`%s')\n", p->no, GNUNET_i2s (&p->id));
371     return GNUNET_SYSERR;
372   }
373
374   sleep (5);
375
376   /* restart */
377   if (GNUNET_SYSERR == GNUNET_TESTING_peer_start(p->peer))
378   {
379     GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, "transport-testing",
380                      "Failed to restart peer %u (`%s')\n",
381                      p->no, GNUNET_i2s (&p->id));
382     return GNUNET_SYSERR;
383   }
384
385   GNUNET_assert (p->th != NULL);
386   GNUNET_assert (p->start_cb == NULL);
387   p->start_cb = restart_cb;
388   p->cb_cls = cb_cls;
389
390   p->th = GNUNET_TRANSPORT_connect (p->cfg, NULL, p,
391                                     &notify_receive,
392                                     &notify_connect,
393                                     &notify_disconnect);
394   GNUNET_assert (NULL != p->th);
395
396   p->ghh = GNUNET_TRANSPORT_get_hello (p->th, &get_hello, p);
397   GNUNET_assert (p->ghh != NULL);
398   return GNUNET_OK;
399 }
400
401
402 /**
403  * shutdown the given peer
404  * @param tth testing handle
405  * @param p the peer
406  */
407 void
408 GNUNET_TRANSPORT_TESTING_stop_peer (struct GNUNET_TRANSPORT_TESTING_handle *tth,
409                                     struct PeerContext *p)
410 {
411   GNUNET_assert (p != NULL);
412   if (p->ghh != NULL)
413   {
414     GNUNET_TRANSPORT_get_hello_cancel (p->ghh);
415     p->ghh = NULL;
416   }
417   if (p->th != NULL)
418   {
419     GNUNET_TRANSPORT_disconnect (p->th);
420     p->th = NULL;
421   }
422
423   if (p->peer != NULL)
424   {
425     if (GNUNET_OK != GNUNET_TESTING_peer_stop (p->peer))
426     {
427       GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "transport-testing",
428                        "Testing lib failed to stop peer %u (`%s') \n", p->no,
429                        GNUNET_i2s (&p->id));
430     }
431     GNUNET_TESTING_peer_destroy (p->peer);
432     p->peer = NULL;
433   }
434
435   if (p->hello != NULL)
436   {
437     GNUNET_free (p->hello);
438     p->hello = NULL;
439   }
440   if (p->cfg != NULL)
441   {
442     GNUNET_CONFIGURATION_destroy (p->cfg);
443     p->cfg = NULL;
444   }
445   GNUNET_CONTAINER_DLL_remove (tth->p_head, tth->p_tail, p);
446   GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "transport-testing",
447                    "Peer %u (`%s') stopped \n", p->no,
448                    GNUNET_i2s (&p->id));
449   GNUNET_free (p);
450 }
451
452
453 /**
454  * Initiate a connection from p1 to p2 by offering p1 p2's HELLO message
455  *
456  * Remarks: start_peer's notify_connect callback can be called before.
457  *
458  * @param tth transport testing handle
459  * @param p1 peer 1
460  * @param p2 peer 2
461  * @param cb the callback to call when both peers notified that they are connected
462  * @param cls callback cls
463  * @return a connect request handle
464  */
465 GNUNET_TRANSPORT_TESTING_ConnectRequest
466 GNUNET_TRANSPORT_TESTING_connect_peers (struct GNUNET_TRANSPORT_TESTING_handle *tth,
467                                         struct PeerContext *p1,
468                                         struct PeerContext *p2,
469                                         GNUNET_TRANSPORT_TESTING_connect_cb cb,
470                                         void *cls)
471 {
472   GNUNET_assert (tth != NULL);
473
474   struct ConnectingContext *cc =
475       GNUNET_malloc (sizeof (struct ConnectingContext));
476
477   GNUNET_assert (p1 != NULL);
478   GNUNET_assert (p2 != NULL);
479   cc->p1 = p1;
480   cc->p2 = p2;
481   cc->cb = cb;
482   if (cls != NULL)
483     cc->cb_cls = cls;
484   else
485     cc->cb_cls = cc;
486   cc->th_p1 = p1->th;
487   cc->th_p2 = p2->th;
488   GNUNET_assert (cc->th_p1 != NULL);
489   GNUNET_assert (cc->th_p2 != NULL);
490   GNUNET_CONTAINER_DLL_insert (tth->cc_head, tth->cc_tail, cc);
491   cc->tct = GNUNET_SCHEDULER_add_now (&try_connect, cc);
492   GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "transport-testing",
493                    "New connect request %p\n", cc);
494
495   return cc;
496 }
497
498
499 /**
500  * Cancel the request to connect two peers
501  * Tou MUST cancel the request if you stop the peers before the peers connected succesfully
502  *
503  * @param tth transport testing handle
504  * @param ccr a connect request handle
505  */
506 void
507 GNUNET_TRANSPORT_TESTING_connect_peers_cancel (struct
508                                                GNUNET_TRANSPORT_TESTING_handle
509                                                *tth,
510                                                GNUNET_TRANSPORT_TESTING_ConnectRequest
511                                                ccr)
512 {
513   struct ConnectingContext *cc = ccr;
514
515   GNUNET_assert (tth != NULL);
516
517   GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "transport-testing",
518                    "Canceling connect request %p!\n", cc);
519
520   if (cc->tct != GNUNET_SCHEDULER_NO_TASK)
521     GNUNET_SCHEDULER_cancel (cc->tct);
522   cc->tct = GNUNET_SCHEDULER_NO_TASK;
523
524   GNUNET_CONTAINER_DLL_remove (tth->cc_head, tth->cc_tail, cc);
525   GNUNET_free (cc);
526 }
527
528
529 /**
530  * Clean up the transport testing
531  * @param tth transport testing handle
532  */
533 void
534 GNUNET_TRANSPORT_TESTING_done (struct GNUNET_TRANSPORT_TESTING_handle *tth)
535 {
536   struct ConnectingContext *cc = tth->cc_head;
537   struct ConnectingContext *ct = NULL;
538   struct PeerContext *p = tth->p_head;
539   struct PeerContext *t = NULL;
540
541   GNUNET_assert (tth != NULL);
542
543   while (cc != tth->cc_tail)
544   {
545     ct = cc->next;
546     GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, "transport-testing",
547                      "Developer forgot to cancel connect request %p!\n", cc);
548     GNUNET_TRANSPORT_TESTING_connect_peers_cancel (tth, cc);
549     cc = ct;
550   }
551
552   while (p != NULL)
553   {
554     t = p->next;
555     GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, "transport-testing",
556                      "Developer forgot to stop peer!\n");
557     GNUNET_TRANSPORT_TESTING_stop_peer (tth, p);
558     p = t;
559   }
560
561   GNUNET_TESTING_system_destroy (tth->tl_system, GNUNET_YES);
562
563   GNUNET_free (tth);
564   tth = NULL;
565 }
566
567
568 /**
569  * Initialize the transport testing
570  * @return transport testing handle
571  */
572 struct GNUNET_TRANSPORT_TESTING_handle *
573 GNUNET_TRANSPORT_TESTING_init ()
574 {
575   struct GNUNET_TRANSPORT_TESTING_handle *tth;
576
577   /* prepare hostkeys */
578   tth = GNUNET_malloc (sizeof (struct GNUNET_TRANSPORT_TESTING_handle));
579
580   /* Init testing the testing lib */
581   tth->tl_system = GNUNET_TESTING_system_create ("transport-testing", NULL,
582                                                  NULL, NULL);
583   if (NULL == tth->tl_system)
584   {
585     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Failed to initialize testing library!\n"));
586     GNUNET_free (tth);
587     return NULL;
588   }
589
590   return tth;
591 }
592
593
594 /*
595  * Some utility functions
596  */
597
598 /**
599  * Removes all directory separators from absolute filename
600  * @param file the absolute file name, e.g. as found in argv[0]
601  * @return extracted file name, has to be freed by caller
602  */
603 static char *
604 extract_filename (const char *file)
605 {
606   char *pch = GNUNET_strdup (file);
607   char *backup = pch;
608   char *filename = NULL;
609   char *res;
610 #if WINDOWS
611   if ((strlen (pch) >= 3) && pch[1] == ':')
612   {
613     if (NULL != strstr (pch, "\\"))
614     {
615       pch = strtok (pch, "\\");
616       while (pch != NULL)
617       {
618         pch = strtok (NULL, "\\");
619         if (pch != NULL)
620           filename = pch;
621       }
622     }
623   }
624   if (filename != NULL)
625     pch = filename; /* If we miss the next condition, filename = pch will
626                      * not harm us.
627                      */
628 #endif
629   if (NULL != strstr (pch, "/"))
630   {
631     pch = strtok (pch, "/");
632     while (pch != NULL)
633     {
634       pch = strtok (NULL, "/");
635       if (pch != NULL)
636       {
637         filename = pch;
638       }
639     }
640   }
641   else
642     filename = pch;
643
644   res = GNUNET_strdup (filename);
645   GNUNET_free (backup);
646   return res;
647 }
648
649
650 /**
651  * Extracts the test filename from an absolute file name and removes the extension
652  * @param file absolute file name
653  * @param dest where to store result
654  */
655 void
656 GNUNET_TRANSPORT_TESTING_get_test_name (const char *file, char **dest)
657 {
658   char *filename = extract_filename (file);
659   char *backup = filename;
660   char *dotexe;
661
662   if (filename == NULL)
663     goto fail;
664
665   /* remove "lt-" */
666   filename = strstr (filename, "tes");
667   if (filename == NULL)
668     goto fail;
669
670   /* remove ".exe" */
671   if (NULL != (dotexe = strstr (filename, ".exe")))
672     dotexe[0] = '\0';
673
674   goto suc;
675
676 fail:
677   (*dest) = NULL;
678   return;
679
680 suc:
681   /* create filename */
682   GNUNET_asprintf (dest, "%s", filename);
683   GNUNET_free (backup);
684 }
685
686
687 /**
688  * Extracts the filename from an absolute file name and removes the extension
689  * @param file absolute file name
690  * @param dest where to store result
691  */
692 void
693 GNUNET_TRANSPORT_TESTING_get_test_source_name (const char *file, char **dest)
694 {
695   char *src = extract_filename (file);
696   char *split;
697
698   split = strstr (src, ".");
699   if (split != NULL)
700   {
701     split[0] = '\0';
702   }
703   GNUNET_asprintf (dest, "%s", src);
704   GNUNET_free (src);
705 }
706
707
708 /**
709  * Extracts the plugin name from an absolute file name and the test name
710  *
711  * @param file absolute file name
712  * @param test test name
713  * @param dest where to store result
714  */
715 void
716 GNUNET_TRANSPORT_TESTING_get_test_plugin_name (const char *file,
717                                                const char *test, char **dest)
718 {
719   char *filename;
720   char *dotexe;
721   char *e = extract_filename (file);
722   char *t = extract_filename (test);
723
724   if (NULL == e)
725     goto fail;
726   /* remove "lt-" */
727   filename = strstr (e, "tes");
728   if (NULL == filename)
729     goto fail;
730   /* remove ".exe" */
731   if (NULL != (dotexe = strstr (filename, ".exe")))
732     dotexe[0] = '\0';
733
734   /* find last _ */
735   filename = strstr (filename, t);
736   if (NULL == filename)
737     goto fail;
738   /* copy plugin */
739   filename += strlen (t);
740   if ('\0' != *filename)
741     filename++;
742   GNUNET_asprintf (dest, "%s", filename);
743   goto suc;
744 fail:
745   (*dest) = NULL;
746 suc:
747   GNUNET_free (t);
748   GNUNET_free (e);
749 }
750
751
752 /**
753  * This function takes the filename (e.g. argv[0), removes a "lt-"-prefix and
754  * if existing ".exe"-prefix and adds the peer-number
755  *
756  * @param file filename of the test, e.g. argv[0]
757  * @param dest where to write the filename
758  * @param count peer number
759  */
760 void
761 GNUNET_TRANSPORT_TESTING_get_config_name (const char *file, char **dest,
762                                           int count)
763 {
764   char *filename = extract_filename (file);
765   char *backup = filename;
766   char *dotexe;
767
768   if (NULL == filename)
769     goto fail;
770   /* remove "lt-" */
771   filename = strstr (filename, "tes");
772   if (NULL == filename)
773     goto fail;
774   /* remove ".exe" */
775   if (NULL != (dotexe = strstr (filename, ".exe")))
776     dotexe[0] = '\0';
777   GNUNET_asprintf (dest, "%s_peer%u.conf", filename, count);
778   GNUNET_free (backup);
779   return;
780 fail:
781   (*dest) = NULL;
782   GNUNET_free (backup);
783 }
784
785
786 /* end of transport-testing.c */