aboutsummaryrefslogtreecommitdiff
path: root/src/testing/testing.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/testing/testing.c')
-rw-r--r--src/testing/testing.c355
1 files changed, 337 insertions, 18 deletions
diff --git a/src/testing/testing.c b/src/testing/testing.c
index fcc8c9767..65441c188 100644
--- a/src/testing/testing.c
+++ b/src/testing/testing.c
@@ -37,7 +37,7 @@
37#include "gnunet_transport_service.h" 37#include "gnunet_transport_service.h"
38#include "gnunet_hello_lib.h" 38#include "gnunet_hello_lib.h"
39 39
40#define DEBUG_TESTING GNUNET_NO 40#define DEBUG_TESTING GNUNET_YES
41#define DEBUG_TESTING_RECONNECT GNUNET_YES 41#define DEBUG_TESTING_RECONNECT GNUNET_YES
42 42
43/** 43/**
@@ -50,7 +50,7 @@
50 * How many times are we willing to try to wait for "scp" or 50 * How many times are we willing to try to wait for "scp" or
51 * "gnunet-service-arm" to complete (waitpid) before giving up? 51 * "gnunet-service-arm" to complete (waitpid) before giving up?
52 */ 52 */
53#define MAX_EXEC_WAIT_RUNS 50 53#define MAX_EXEC_WAIT_RUNS 250
54 54
55static struct GNUNET_CORE_MessageHandler no_handlers[] = { {NULL, 0, 0} }; 55static struct GNUNET_CORE_MessageHandler no_handlers[] = { {NULL, 0, 0} };
56 56
@@ -126,7 +126,7 @@ testing_init (void *cls,
126 { 126 {
127 d->server = NULL; 127 d->server = NULL;
128 if (GNUNET_YES == d->dead) 128 if (GNUNET_YES == d->dead)
129 GNUNET_TESTING_daemon_stop (d, d->dead_cb, d->dead_cb_cls); 129 GNUNET_TESTING_daemon_stop (d, d->dead_cb, d->dead_cb_cls, GNUNET_YES);
130 else if (NULL != cb) 130 else if (NULL != cb)
131 cb (d->cb_cls, NULL, d->cfg, d, 131 cb (d->cb_cls, NULL, d->cfg, d,
132 _("Failed to connect to core service\n")); 132 _("Failed to connect to core service\n"));
@@ -141,7 +141,7 @@ testing_init (void *cls,
141 d->server = server; 141 d->server = server;
142 d->running = GNUNET_YES; 142 d->running = GNUNET_YES;
143 if (GNUNET_YES == d->dead) 143 if (GNUNET_YES == d->dead)
144 GNUNET_TESTING_daemon_stop (d, d->dead_cb, d->dead_cb_cls); 144 GNUNET_TESTING_daemon_stop (d, d->dead_cb, d->dead_cb_cls, GNUNET_YES);
145 else if (NULL != cb) 145 else if (NULL != cb)
146 cb (d->cb_cls, my_identity, d->cfg, d, NULL); 146 cb (d->cb_cls, my_identity, d->cfg, d, NULL);
147#if DEBUG_TESTING 147#if DEBUG_TESTING
@@ -155,7 +155,7 @@ testing_init (void *cls,
155 if (d->th == NULL) 155 if (d->th == NULL)
156 { 156 {
157 if (GNUNET_YES == d->dead) 157 if (GNUNET_YES == d->dead)
158 GNUNET_TESTING_daemon_stop (d, d->dead_cb, d->dead_cb_cls); 158 GNUNET_TESTING_daemon_stop (d, d->dead_cb, d->dead_cb_cls, GNUNET_YES);
159 else if (NULL != d->cb) 159 else if (NULL != d->cb)
160 d->cb (d->cb_cls, &d->id, d->cfg, d, 160 d->cb (d->cb_cls, &d->id, d->cfg, d,
161 _("Failed to connect to transport service!\n")); 161 _("Failed to connect to transport service!\n"));
@@ -180,6 +180,9 @@ start_fsm (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
180 enum GNUNET_OS_ProcessStatusType type; 180 enum GNUNET_OS_ProcessStatusType type;
181 unsigned long code; 181 unsigned long code;
182 char *dst; 182 char *dst;
183 int bytes_read;
184 static char hostkeybuf[105];
185 static const char temphostkey[104];
183 186
184#if DEBUG_TESTING 187#if DEBUG_TESTING
185 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 188 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
@@ -227,6 +230,187 @@ start_fsm (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
227 d->phase = SP_COPIED; 230 d->phase = SP_COPIED;
228 /* fall-through */ 231 /* fall-through */
229 case SP_COPIED: 232 case SP_COPIED:
233 /* Start create hostkey process */
234 d->pipe_stdout = GNUNET_DISK_pipe(GNUNET_NO);
235 if (d->pipe_stdout == NULL)
236 {
237 cb = d->cb;
238 d->cb = NULL;
239 if (NULL != cb)
240 cb (d->cb_cls,
241 NULL,
242 d->cfg,
243 d,
244 (NULL == d->hostname)
245 ? _("Failed to create pipe for `gnunet-peerinfo' process.\n")
246 : _("Failed to create pipe for `ssh' process.\n"));
247 return;
248 }
249 if (NULL == d->hostname)
250 {
251#if DEBUG_TESTING
252 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
253 "Starting `%s', with command `%s %s %s %s'.\n",
254 "gnunet-peerinfo", "gnunet-peerinfo", "-c", d->cfgfile,
255 "-sq");
256#endif
257 d->pid = GNUNET_OS_start_process (NULL, d->pipe_stdout, "gnunet-peerinfo",
258 "gnunet-peerinfo",
259 "-c", d->cfgfile,
260 "-sq", NULL);
261 GNUNET_DISK_pipe_close_end(d->pipe_stdout, GNUNET_DISK_PIPE_END_WRITE);
262 }
263 else
264 {
265 if (d->username != NULL)
266 GNUNET_asprintf (&dst, "%s@%s", d->username, d->hostname);
267 else
268 dst = GNUNET_strdup (d->hostname);
269
270#if DEBUG_TESTING
271 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
272 "Starting `%s', with command `%s %s %s %s %s %s'.\n",
273 "gnunet-peerinfo", "ssh", dst, "gnunet-peerinfo", "-c", d->cfgfile,
274 "-sq");
275#endif
276 d->pid = GNUNET_OS_start_process (NULL, d->pipe_stdout, "ssh",
277 "ssh",
278 dst,
279 "gnunet-peerinfo",
280 "-c", d->cfgfile, "-sq", NULL);
281 GNUNET_DISK_pipe_close_end(d->pipe_stdout, GNUNET_DISK_PIPE_END_WRITE);
282 GNUNET_free (dst);
283 }
284 if (-1 == d->pid)
285 {
286 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
287 _("Could not start `%s' process to create hostkey.\n"),
288 (NULL == d->hostname) ? "gnunet-peerinfo" : "ssh");
289 cb = d->cb;
290 d->cb = NULL;
291 if (NULL != cb)
292 cb (d->cb_cls,
293 NULL,
294 d->cfg,
295 d,
296 (NULL == d->hostname)
297 ? _("Failed to start `gnunet-peerinfo' process.\n")
298 : _("Failed to start `ssh' process.\n"));
299 GNUNET_DISK_pipe_close(d->pipe_stdout);
300 return;
301 }
302#if DEBUG_TESTING
303 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
304 "Started `%s', waiting for hostkey.\n",
305 "gnunet-peerinfo");
306#endif
307 d->phase = SP_HOSTKEY_CREATE;
308 d->wait_runs = 0;
309 d->task
310 = GNUNET_SCHEDULER_add_delayed (d->sched,
311 GNUNET_CONSTANTS_EXEC_WAIT,
312 &start_fsm, d);
313 break;
314 case SP_HOSTKEY_CREATE:
315
316 bytes_read = GNUNET_DISK_file_read(GNUNET_DISK_pipe_handle(d->pipe_stdout, GNUNET_DISK_PIPE_END_READ), &hostkeybuf, sizeof(hostkeybuf));
317 if (bytes_read == 104) /* Success, we have read in the hostkey */
318 {
319 if (hostkeybuf[103] == '\n')
320 hostkeybuf[103] = '\0';
321 else
322 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Malformed output from gnunet-peerinfo!\n");
323 memcpy(&temphostkey, &hostkeybuf, bytes_read);
324
325 if (GNUNET_OK != GNUNET_CRYPTO_hash_from_string (&temphostkey[0],
326 &d->id.hashPubKey))
327 {
328 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Failed to convert string to peer identity!\n");
329 }
330 else
331 {
332 GNUNET_DISK_pipe_close(d->pipe_stdout);
333 d->pipe_stdout = NULL;
334 }
335 }
336
337 if (GNUNET_OK != GNUNET_OS_process_status (d->pid, &type, &code))
338 {
339 d->wait_runs++;
340 if (d->wait_runs > MAX_EXEC_WAIT_RUNS)
341 {
342 cb = d->cb;
343 d->cb = NULL;
344 if (NULL != cb)
345 cb (d->cb_cls,
346 NULL,
347 d->cfg,
348 d,
349 (NULL == d->hostname)
350 ? _("`gnunet-peerinfo' does not seem to terminate.\n")
351 : _("`ssh' does not seem to terminate.\n"));
352
353 GNUNET_DISK_pipe_close(d->pipe_stdout);
354 return;
355 }
356 /* wait some more */
357 d->task
358 = GNUNET_SCHEDULER_add_delayed (d->sched,
359 GNUNET_CONSTANTS_EXEC_WAIT,
360 &start_fsm, d);
361 return;
362 }
363#if DEBUG_TESTING
364 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
365 "Successfully got hostkey!\n");
366#endif
367 if (d->pipe_stdout != NULL)
368 {
369 cb = d->cb;
370 d->cb = NULL;
371 if (NULL != cb)
372 cb (d->cb_cls,
373 NULL,
374 d->cfg,
375 d,
376 _("`Failed to get hostkey!\n"));
377 GNUNET_DISK_pipe_close(d->pipe_stdout);
378 return;
379 }
380
381 if (d->hostkey_callback != NULL)
382 {
383 d->hostkey_callback(d->hostkey_cls, &d->id, d, NULL);
384 d->phase = SP_HOSTKEY_CREATED;
385 }
386 else
387 {
388 d->phase = SP_TOPOLOGY_SETUP;
389 }
390
391 /* Fall through */
392 case SP_HOSTKEY_CREATED:
393 /* wait for topology finished */
394 d->wait_runs++;
395 if ((GNUNET_YES == d->dead) || (d->wait_runs > MAX_EXEC_WAIT_RUNS))
396 {
397 cb = d->cb;
398 d->cb = NULL;
399 if (NULL != cb)
400 cb (d->cb_cls,
401 NULL,
402 d->cfg,
403 d,
404 _("`Failed while waiting for topology setup!\n"));
405 return;
406 }
407
408 d->task
409 = GNUNET_SCHEDULER_add_delayed (d->sched,
410 GNUNET_CONSTANTS_EXEC_WAIT,
411 &start_fsm, d);
412 break;
413 case SP_TOPOLOGY_SETUP:
230 /* start GNUnet on remote host */ 414 /* start GNUnet on remote host */
231 if (NULL == d->hostname) 415 if (NULL == d->hostname)
232 { 416 {
@@ -283,6 +467,7 @@ start_fsm (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
283 (NULL == d->hostname) 467 (NULL == d->hostname)
284 ? _("Failed to start `gnunet-arm' process.\n") 468 ? _("Failed to start `gnunet-arm' process.\n")
285 : _("Failed to start `ssh' process.\n")); 469 : _("Failed to start `ssh' process.\n"));
470 return;
286 } 471 }
287#if DEBUG_TESTING 472#if DEBUG_TESTING
288 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 473 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
@@ -452,6 +637,19 @@ start_fsm (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
452 } 637 }
453} 638}
454 639
640/**
641 * Continues GNUnet daemon startup when user wanted to be notified
642 * once a hostkey was generated (for creating friends files, blacklists,
643 * etc.).
644 *
645 * @param daemon the daemon to finish starting
646 */
647void
648GNUNET_TESTING_daemon_continue_startup(struct GNUNET_TESTING_Daemon *daemon)
649{
650 GNUNET_assert(daemon->phase == SP_HOSTKEY_CREATED);
651 daemon->phase = SP_TOPOLOGY_SETUP;
652}
455 653
456/** 654/**
457 * Starts a GNUnet daemon. GNUnet must be installed on the target 655 * Starts a GNUnet daemon. GNUnet must be installed on the target
@@ -463,6 +661,10 @@ start_fsm (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
463 * @param cfg configuration to use 661 * @param cfg configuration to use
464 * @param hostname name of the machine where to run GNUnet 662 * @param hostname name of the machine where to run GNUnet
465 * (use NULL for localhost). 663 * (use NULL for localhost).
664 * @param hostkey_callback function to call once the hostkey has been
665 * generated for this peer, but it hasn't yet been started
666 * (NULL to start immediately, otherwise waits on GNUNET_TESTING_daemon_continue_start)
667 * @param hostkey_cls closure for hostkey callback
466 * @param cb function to call with the result 668 * @param cb function to call with the result
467 * @param cb_cls closure for cb 669 * @param cb_cls closure for cb
468 * @return handle to the daemon (actual start will be completed asynchronously) 670 * @return handle to the daemon (actual start will be completed asynchronously)
@@ -471,6 +673,8 @@ struct GNUNET_TESTING_Daemon *
471GNUNET_TESTING_daemon_start (struct GNUNET_SCHEDULER_Handle *sched, 673GNUNET_TESTING_daemon_start (struct GNUNET_SCHEDULER_Handle *sched,
472 const struct GNUNET_CONFIGURATION_Handle *cfg, 674 const struct GNUNET_CONFIGURATION_Handle *cfg,
473 const char *hostname, 675 const char *hostname,
676 GNUNET_TESTING_NotifyHostkeyCreated hostkey_callback,
677 void *hostkey_cls,
474 GNUNET_TESTING_NotifyDaemonRunning cb, 678 GNUNET_TESTING_NotifyDaemonRunning cb,
475 void *cb_cls) 679 void *cb_cls)
476{ 680{
@@ -493,6 +697,8 @@ GNUNET_TESTING_daemon_start (struct GNUNET_SCHEDULER_Handle *sched,
493 GNUNET_free (ret); 697 GNUNET_free (ret);
494 return NULL; 698 return NULL;
495 } 699 }
700 ret->hostkey_callback = hostkey_callback;
701 ret->hostkey_cls = hostkey_cls;
496 ret->cb = cb; 702 ret->cb = cb;
497 ret->cb_cls = cb_cls; 703 ret->cb_cls = cb_cls;
498 ret->cfg = GNUNET_CONFIGURATION_dup (cfg); 704 ret->cfg = GNUNET_CONFIGURATION_dup (cfg);
@@ -574,26 +780,139 @@ GNUNET_TESTING_daemon_start (struct GNUNET_SCHEDULER_Handle *sched,
574 780
575 781
576/** 782/**
783 * Restart (stop and start) a GNUnet daemon.
784 *
785 * @param d the daemon that should be restarted
786 * @param cb function called once the daemon is (re)started
787 * @param cb_cls closure for cb
788 */
789void
790GNUNET_TESTING_daemon_restart (struct GNUNET_TESTING_Daemon *d,
791 GNUNET_TESTING_NotifyDaemonRunning cb, void *cb_cls)
792{
793 char *arg;
794 char *del_arg;
795
796 del_arg = NULL;
797 if (NULL != d->cb)
798 {
799 d->dead = GNUNET_YES;
800 return;
801 }
802
803 d->cb = cb;
804 d->cb_cls = cb_cls;
805
806 if (d->phase == SP_CONFIG_UPDATE)
807 {
808 GNUNET_SCHEDULER_cancel (d->sched, d->task);
809 d->phase = SP_START_DONE;
810 }
811 if (d->server != NULL)
812 {
813 GNUNET_CORE_disconnect (d->server);
814 d->server = NULL;
815 }
816
817 if (d->th != NULL)
818 {
819 GNUNET_TRANSPORT_get_hello_cancel(d->th, &process_hello, d);
820 GNUNET_TRANSPORT_disconnect(d->th);
821 d->th = NULL;
822 }
823 /* state clean up and notifications */
824 GNUNET_free_non_null(d->hello);
825
826#if DEBUG_TESTING
827 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
828 _("Terminating peer `%4s'\n"), GNUNET_i2s (&d->id));
829#endif
830
831 d->phase = SP_START_ARMING;
832
833 /* Check if this is a local or remote process */
834 if (NULL != d->hostname)
835 {
836#if DEBUG_TESTING
837 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
838 "Stopping gnunet-arm with config `%s' on host `%s'.\n", d->cfgfile, d->hostname);
839#endif
840
841 if (d->username != NULL)
842 GNUNET_asprintf (&arg, "%s@%s", d->username, d->hostname);
843 else
844 arg = GNUNET_strdup (d->hostname);
845
846 d->pid = GNUNET_OS_start_process (NULL, NULL, "ssh", "ssh",
847 arg, "gnunet-arm",
848#if DEBUG_TESTING
849 "-L", "DEBUG",
850#endif
851 "-c", d->cfgfile, "-e", "-r", NULL);
852 /* Use -r to restart arm and all services */
853
854 GNUNET_free (arg);
855 }
856 else
857 {
858#if DEBUG_TESTING
859 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
860 "Stopping gnunet-arm with config `%s' locally.\n", d->cfgfile);
861#endif
862 d->pid = GNUNET_OS_start_process (NULL, NULL, "gnunet-arm",
863 "gnunet-arm",
864#if DEBUG_TESTING
865 "-L", "DEBUG",
866#endif
867 "-c", d->cfgfile, "-e", "-r", NULL);
868 }
869
870 GNUNET_free_non_null(del_arg);
871 d->wait_runs = 0;
872 d->task
873 = GNUNET_SCHEDULER_add_delayed (d->sched,
874 GNUNET_CONSTANTS_EXEC_WAIT,
875 &start_fsm, d);
876
877}
878
879
880/**
577 * Stops a GNUnet daemon. 881 * Stops a GNUnet daemon.
578 * 882 *
579 * @param d the daemon that should be stopped 883 * @param d the daemon that should be stopped
580 * @param cb function called once the daemon was stopped 884 * @param cb function called once the daemon was stopped
581 * @param cb_cls closure for cb 885 * @param cb_cls closure for cb
886 * @param delete_files GNUNET_YES to remove files, GNUNET_NO
887 * to leave them (i.e. for restarting at a later time,
888 * or logfile inspection once finished)
582 */ 889 */
583void 890void
584GNUNET_TESTING_daemon_stop (struct GNUNET_TESTING_Daemon *d, 891GNUNET_TESTING_daemon_stop (struct GNUNET_TESTING_Daemon *d,
585 GNUNET_TESTING_NotifyCompletion cb, void *cb_cls) 892 GNUNET_TESTING_NotifyCompletion cb, void *cb_cls,
893 int delete_files)
586{ 894{
587 char *arg; 895 char *arg;
588 896 char *del_arg;
589 d->dead_cb = cb; 897 d->dead_cb = cb;
590 d->dead_cb_cls = cb_cls; 898 d->dead_cb_cls = cb_cls;
591 899
592 if (NULL != d->cb) 900 if (NULL != d->cb)
593 { 901 {
902#if DEBUG_TESTING
903 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
904 _("Setting d->dead on peer `%4s'\n"), GNUNET_i2s (&d->id));
905#endif
594 d->dead = GNUNET_YES; 906 d->dead = GNUNET_YES;
595 return; 907 return;
596 } 908 }
909
910 del_arg = NULL;
911 if (delete_files == GNUNET_YES)
912 {
913 GNUNET_asprintf(&del_arg, "-d");
914 }
915
597 if (d->phase == SP_CONFIG_UPDATE) 916 if (d->phase == SP_CONFIG_UPDATE)
598 { 917 {
599 GNUNET_SCHEDULER_cancel (d->sched, d->task); 918 GNUNET_SCHEDULER_cancel (d->sched, d->task);
@@ -608,10 +927,9 @@ GNUNET_TESTING_daemon_stop (struct GNUNET_TESTING_Daemon *d,
608#if DEBUG_TESTING 927#if DEBUG_TESTING
609 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 928 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
610 _("Terminating peer `%4s'\n"), GNUNET_i2s (&d->id)); 929 _("Terminating peer `%4s'\n"), GNUNET_i2s (&d->id));
611 /* sleep(15); Manual check for running */
612#endif 930#endif
613 931
614 d->phase = SP_SHUTDOWN_START; 932 d->phase = SP_SHUTDOWN_START;
615 933
616 /* Check if this is a local or remote process */ 934 /* Check if this is a local or remote process */
617 if (NULL != d->hostname) 935 if (NULL != d->hostname)
@@ -627,29 +945,30 @@ GNUNET_TESTING_daemon_stop (struct GNUNET_TESTING_Daemon *d,
627 arg = GNUNET_strdup (d->hostname); 945 arg = GNUNET_strdup (d->hostname);
628 946
629 d->pid = GNUNET_OS_start_process (NULL, NULL, "ssh", "ssh", 947 d->pid = GNUNET_OS_start_process (NULL, NULL, "ssh", "ssh",
630 arg, "gnunet-arm", 948 arg, "gnunet-arm",
631#if DEBUG_TESTING 949#if DEBUG_TESTING
632 "-L", "DEBUG", 950 "-L", "DEBUG",
633#endif 951#endif
634 "-c", d->cfgfile, "-e", "-d", "-q", NULL); 952 "-c", d->cfgfile, "-e", "-q", del_arg, NULL);
635 /* Use -e to end arm, and -d to remove temp files */ 953 /* Use -e to end arm, and -d to remove temp files */
636 954
637 GNUNET_free (arg); 955 GNUNET_free (arg);
638 } 956 }
639 else 957 else
640 { 958 {
641#if DEBUG_TESTING 959#if DEBUG_TESTING
642 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 960 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
643 "Stopping gnunet-arm with config `%s' locally.\n", d->cfgfile); 961 "Stopping gnunet-arm with config `%s' locally.\n", d->cfgfile);
644#endif 962#endif
645 d->pid = GNUNET_OS_start_process (NULL, NULL, "gnunet-arm", 963 d->pid = GNUNET_OS_start_process (NULL, NULL, "gnunet-arm",
646 "gnunet-arm", 964 "gnunet-arm",
647#if DEBUG_TESTING 965#if DEBUG_TESTING
648 "-L", "DEBUG", 966 "-L", "DEBUG",
649#endif 967#endif
650 "-c", d->cfgfile, "-e", "-d", "-q", NULL); 968 "-c", d->cfgfile, "-e", "-q", del_arg, NULL);
651 } 969 }
652 970
971 GNUNET_free_non_null(del_arg);
653 d->wait_runs = 0; 972 d->wait_runs = 0;
654 d->task 973 d->task
655 = GNUNET_SCHEDULER_add_delayed (d->sched, 974 = GNUNET_SCHEDULER_add_delayed (d->sched,