2 This file is part of GNUnet.
3 Copyright (C) 2001, 2002, 2004, 2005, 2006, 2007, 2009 GNUnet e.V.
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
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 Affero General Public License for more details.
17 * @file testing/gnunet-testing.c
18 * @brief tool to use testing functionality from cmd line
19 * @author Christian Grothoff
22 #include "gnunet_util_lib.h"
23 #include "gnunet_testing_lib.h"
26 #define LOG(kind,...) \
27 GNUNET_log_from (kind, "gnunet-testing", __VA_ARGS__)
36 * Filename of the hostkey file we should write,
37 * null if we should not write a hostkey file.
39 static char *create_hostkey;
42 * Non-zero if we should create config files.
44 static int create_cfg;
47 * Number of config files to create.
49 static unsigned int create_no;
52 * Filename of the config template to be written.
54 static char *create_cfg_template;
57 * Service we are supposed to run.
59 static char *run_service_name;
62 * File handle to STDIN, for reading restart/quit commands.
64 static struct GNUNET_DISK_FileHandle *fh;
67 * Temporary filename, used with '-r' to write the configuration to.
69 static char *tmpfilename;
72 * Task identifier of the task that waits for stdin.
74 static struct GNUNET_SCHEDULER_Task *tid;
77 * Peer started for '-r'.
79 static struct GNUNET_TESTING_Peer *my_peer;
84 create_unique_cfgs (const char * template, const unsigned int no)
86 struct GNUNET_TESTING_System *system;
90 struct GNUNET_CONFIGURATION_Handle *cfg_new;
91 struct GNUNET_CONFIGURATION_Handle *cfg_tmpl;
93 if (GNUNET_NO == GNUNET_DISK_file_test(template))
95 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Configuration template `%s': file not found\n", create_cfg_template);
98 cfg_tmpl = GNUNET_CONFIGURATION_create();
101 if ((create_cfg_template != NULL) && (GNUNET_OK != GNUNET_CONFIGURATION_load(cfg_tmpl, create_cfg_template)))
103 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Could not load template `%s'\n", create_cfg_template);
104 GNUNET_CONFIGURATION_destroy (cfg_tmpl);
109 if (GNUNET_OK != GNUNET_CONFIGURATION_load (cfg_tmpl, NULL))
111 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Could not load template `%s'\n", create_cfg_template);
112 GNUNET_CONFIGURATION_destroy (cfg_tmpl);
117 system = GNUNET_TESTING_system_create ("testing", NULL /* controller */,
119 for (cur = 0; cur < no; cur++)
121 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Creating configuration no. %u \n", cur);
122 if (create_cfg_template != NULL)
123 GNUNET_asprintf (&cur_file,"%04u-%s",cur, create_cfg_template);
125 GNUNET_asprintf (&cur_file,"%04u%s",cur, ".conf");
127 cfg_new = GNUNET_CONFIGURATION_dup (cfg_tmpl);
129 GNUNET_TESTING_configuration_create (system, cfg_new))
131 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Could not create another configuration\n");
132 GNUNET_CONFIGURATION_destroy (cfg_new);
136 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
137 "Writing configuration no. %u to file `%s' \n", cur, cur_file);
138 if (GNUNET_OK != GNUNET_CONFIGURATION_write(cfg_new, cur_file))
140 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to write configuration no. %u \n", cur);
143 GNUNET_CONFIGURATION_destroy (cfg_new);
144 GNUNET_free (cur_file);
145 if (GNUNET_YES == fail)
148 GNUNET_CONFIGURATION_destroy(cfg_tmpl);
149 GNUNET_TESTING_system_destroy (system, GNUNET_NO);
150 if (GNUNET_YES == fail)
157 create_hostkeys (const unsigned int no)
159 struct GNUNET_TESTING_System *system;
160 struct GNUNET_PeerIdentity id;
161 struct GNUNET_DISK_FileHandle *fd;
162 struct GNUNET_CRYPTO_EddsaPrivateKey *pk;
164 system = GNUNET_TESTING_system_create ("testing", NULL, NULL, NULL);
165 pk = GNUNET_TESTING_hostkey_get (system, create_no, &id);
168 fprintf (stderr, _("Could not extract hostkey %u (offset too large?)\n"), create_no);
169 GNUNET_TESTING_system_destroy (system, GNUNET_YES);
172 (void) GNUNET_DISK_directory_create_for_file (create_hostkey);
173 fd = GNUNET_DISK_file_open (create_hostkey,
174 GNUNET_DISK_OPEN_READWRITE |
175 GNUNET_DISK_OPEN_CREATE,
176 GNUNET_DISK_PERM_USER_READ |
177 GNUNET_DISK_PERM_USER_WRITE);
178 GNUNET_assert (fd != NULL);
179 ret = GNUNET_DISK_file_write (fd, pk,
180 sizeof (struct GNUNET_CRYPTO_EddsaPrivateKey));
181 GNUNET_assert (GNUNET_OK == GNUNET_DISK_file_close (fd));
182 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "transport-testing",
183 "Wrote hostkey to file: `%s'\n", create_hostkey);
185 GNUNET_TESTING_system_destroy (system, GNUNET_YES);
191 * Cleanup called by signal handlers and when stdin is closed.
192 * Removes the temporary file.
199 if (NULL != tmpfilename)
201 if (0 != UNLINK (tmpfilename))
202 GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, "unlink", tmpfilename);
206 GNUNET_SCHEDULER_cancel (tid);
211 GNUNET_DISK_file_close (fh);
218 * Called whenever we can read stdin non-blocking
233 GNUNET_SCHEDULER_shutdown ();
236 if (GNUNET_OK != GNUNET_TESTING_peer_stop (my_peer))
237 LOG (GNUNET_ERROR_TYPE_ERROR, "Failed to stop the peer\n");
238 if (GNUNET_OK != GNUNET_TESTING_peer_start (my_peer))
239 LOG (GNUNET_ERROR_TYPE_ERROR, "Failed to start the peer\n");
240 printf ("restarted\n");
245 /* ignore whitespace */
248 fprintf (stderr, _("Unknown command, use 'q' to quit or 'r' to restart peer\n"));
251 tid = GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL,
258 * Main function called by the testing library.
259 * Executed inside a running scheduler.
262 * @param cfg configuration of the peer that was started
263 * @param peer handle to the peer
266 testing_main (void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg,
267 struct GNUNET_TESTING_Peer *peer)
270 if (NULL == (tmpfilename = GNUNET_DISK_mktemp ("gnunet-testing")))
273 GNUNET_SCHEDULER_shutdown ();
277 GNUNET_CONFIGURATION_write ((struct GNUNET_CONFIGURATION_Handle *) cfg,
283 printf("ok\n%s\n", tmpfilename);
285 GNUNET_SCHEDULER_add_shutdown (&cleanup, NULL);
286 fh = GNUNET_DISK_get_handle_from_native (stdin);
287 tid = GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL,
295 * Main function that will be running without scheduler.
298 * @param args remaining command-line arguments
299 * @param cfgfile name of the configuration file used (for saving, can be NULL!)
300 * @param cfg configuration
303 run_no_scheduler (void *cls, char *const *args, const char *cfgfile,
304 const struct GNUNET_CONFIGURATION_Handle *cfg)
306 if (NULL != run_service_name)
308 ret = GNUNET_TESTING_service_run ("gnunet_service_test", run_service_name,
309 cfgfile, &testing_main, NULL);
313 if (GNUNET_YES == create_cfg)
317 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
318 "Creating %u configuration files based on template `%s'\n", create_no, create_cfg_template);
319 ret = create_unique_cfgs (create_cfg_template, create_no);
323 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Missing arguments! \n");
327 if (NULL != create_hostkey)
329 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Extracting hostkey %u\n", create_no);
330 ret = create_hostkeys (create_no);
332 GNUNET_free_non_null (create_cfg_template);
339 * @param argc number of arguments from the command line
340 * @param argv command line arguments
341 * @return 0 ok, 1 on error
344 main (int argc, char *const *argv)
346 struct GNUNET_GETOPT_CommandLineOption options[] = {
347 GNUNET_GETOPT_option_flag ('C',
349 gettext_noop ("create unique configuration files"),
351 GNUNET_GETOPT_option_string ('k',
354 gettext_noop ("extract hostkey file from pre-computed hostkey list"),
357 GNUNET_GETOPT_option_uint ('n',
360 gettext_noop ("number of unique configuration files to create, or number of the hostkey to extract"),
364 GNUNET_GETOPT_option_string ('t',
367 gettext_noop ("configuration template"),
368 &create_cfg_template),
370 GNUNET_GETOPT_option_string ('r',
373 gettext_noop ("run the given service, wait on stdin for 'r' (restart) or 'q' (quit)"),
375 GNUNET_GETOPT_OPTION_END
377 if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv))
380 /* Run without scheduler, because we may want to call
381 * GNUNET_TESTING_service_run, which starts the scheduler on its own.
382 * Furthermore, the other functionality currently does not require the scheduler, too,
383 * but beware when extending gnunet-testing. */
385 GNUNET_PROGRAM_run2 (argc, argv, "gnunet-testing",
386 gettext_noop ("Command line tool to access the testing library"), options, &run_no_scheduler,
387 NULL, GNUNET_YES)) ? ret : 1;
388 GNUNET_free ((void*) argv);
392 /* end of gnunet-testing.c */