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 Affero 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.
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
20 * @file testing/gnunet-testing.c
21 * @brief tool to use testing functionality from cmd line
22 * @author Christian Grothoff
25 #include "gnunet_util_lib.h"
26 #include "gnunet_testing_lib.h"
29 #define LOG(kind,...) \
30 GNUNET_log_from (kind, "gnunet-testing", __VA_ARGS__)
39 * Filename of the hostkey file we should write,
40 * null if we should not write a hostkey file.
42 static char *create_hostkey;
45 * Non-zero if we should create config files.
47 static int create_cfg;
50 * Number of config files to create.
52 static unsigned int create_no;
55 * Filename of the config template to be written.
57 static char *create_cfg_template;
60 * Service we are supposed to run.
62 static char *run_service_name;
65 * File handle to STDIN, for reading restart/quit commands.
67 static struct GNUNET_DISK_FileHandle *fh;
70 * Temporary filename, used with '-r' to write the configuration to.
72 static char *tmpfilename;
75 * Task identifier of the task that waits for stdin.
77 static struct GNUNET_SCHEDULER_Task *tid;
80 * Peer started for '-r'.
82 static struct GNUNET_TESTING_Peer *my_peer;
87 create_unique_cfgs (const char * template, const unsigned int no)
89 struct GNUNET_TESTING_System *system;
93 struct GNUNET_CONFIGURATION_Handle *cfg_new;
94 struct GNUNET_CONFIGURATION_Handle *cfg_tmpl;
96 if (GNUNET_NO == GNUNET_DISK_file_test(template))
98 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Configuration template `%s': file not found\n", create_cfg_template);
101 cfg_tmpl = GNUNET_CONFIGURATION_create();
104 if ((create_cfg_template != NULL) && (GNUNET_OK != GNUNET_CONFIGURATION_load(cfg_tmpl, create_cfg_template)))
106 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Could not load template `%s'\n", create_cfg_template);
107 GNUNET_CONFIGURATION_destroy (cfg_tmpl);
112 if (GNUNET_OK != GNUNET_CONFIGURATION_load (cfg_tmpl, NULL))
114 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Could not load template `%s'\n", create_cfg_template);
115 GNUNET_CONFIGURATION_destroy (cfg_tmpl);
120 system = GNUNET_TESTING_system_create ("testing", NULL /* controller */,
122 for (cur = 0; cur < no; cur++)
124 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Creating configuration no. %u \n", cur);
125 if (create_cfg_template != NULL)
126 GNUNET_asprintf (&cur_file,"%04u-%s",cur, create_cfg_template);
128 GNUNET_asprintf (&cur_file,"%04u%s",cur, ".conf");
130 cfg_new = GNUNET_CONFIGURATION_dup (cfg_tmpl);
132 GNUNET_TESTING_configuration_create (system, cfg_new))
134 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Could not create another configuration\n");
135 GNUNET_CONFIGURATION_destroy (cfg_new);
139 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
140 "Writing configuration no. %u to file `%s' \n", cur, cur_file);
141 if (GNUNET_OK != GNUNET_CONFIGURATION_write(cfg_new, cur_file))
143 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to write configuration no. %u \n", cur);
146 GNUNET_CONFIGURATION_destroy (cfg_new);
147 GNUNET_free (cur_file);
148 if (GNUNET_YES == fail)
151 GNUNET_CONFIGURATION_destroy(cfg_tmpl);
152 GNUNET_TESTING_system_destroy (system, GNUNET_NO);
153 if (GNUNET_YES == fail)
160 create_hostkeys (const unsigned int no)
162 struct GNUNET_TESTING_System *system;
163 struct GNUNET_PeerIdentity id;
164 struct GNUNET_DISK_FileHandle *fd;
165 struct GNUNET_CRYPTO_EddsaPrivateKey *pk;
167 system = GNUNET_TESTING_system_create ("testing", NULL, NULL, NULL);
168 pk = GNUNET_TESTING_hostkey_get (system, create_no, &id);
171 fprintf (stderr, _("Could not extract hostkey %u (offset too large?)\n"), create_no);
172 GNUNET_TESTING_system_destroy (system, GNUNET_YES);
175 (void) GNUNET_DISK_directory_create_for_file (create_hostkey);
176 fd = GNUNET_DISK_file_open (create_hostkey,
177 GNUNET_DISK_OPEN_READWRITE |
178 GNUNET_DISK_OPEN_CREATE,
179 GNUNET_DISK_PERM_USER_READ |
180 GNUNET_DISK_PERM_USER_WRITE);
181 GNUNET_assert (fd != NULL);
182 ret = GNUNET_DISK_file_write (fd, pk,
183 sizeof (struct GNUNET_CRYPTO_EddsaPrivateKey));
184 GNUNET_assert (GNUNET_OK == GNUNET_DISK_file_close (fd));
185 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "transport-testing",
186 "Wrote hostkey to file: `%s'\n", create_hostkey);
188 GNUNET_TESTING_system_destroy (system, GNUNET_YES);
194 * Cleanup called by signal handlers and when stdin is closed.
195 * Removes the temporary file.
202 if (NULL != tmpfilename)
204 if (0 != UNLINK (tmpfilename))
205 GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, "unlink", tmpfilename);
209 GNUNET_SCHEDULER_cancel (tid);
214 GNUNET_DISK_file_close (fh);
221 * Called whenever we can read stdin non-blocking
236 GNUNET_SCHEDULER_shutdown ();
239 if (GNUNET_OK != GNUNET_TESTING_peer_stop (my_peer))
240 LOG (GNUNET_ERROR_TYPE_ERROR, "Failed to stop the peer\n");
241 if (GNUNET_OK != GNUNET_TESTING_peer_start (my_peer))
242 LOG (GNUNET_ERROR_TYPE_ERROR, "Failed to start the peer\n");
243 printf ("restarted\n");
248 /* ignore whitespace */
251 fprintf (stderr, _("Unknown command, use 'q' to quit or 'r' to restart peer\n"));
254 tid = GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL,
261 * Main function called by the testing library.
262 * Executed inside a running scheduler.
265 * @param cfg configuration of the peer that was started
266 * @param peer handle to the peer
269 testing_main (void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg,
270 struct GNUNET_TESTING_Peer *peer)
273 if (NULL == (tmpfilename = GNUNET_DISK_mktemp ("gnunet-testing")))
276 GNUNET_SCHEDULER_shutdown ();
280 GNUNET_CONFIGURATION_write ((struct GNUNET_CONFIGURATION_Handle *) cfg,
286 printf("ok\n%s\n", tmpfilename);
288 GNUNET_SCHEDULER_add_shutdown (&cleanup, NULL);
289 fh = GNUNET_DISK_get_handle_from_native (stdin);
290 tid = GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL,
298 * Main function that will be running without scheduler.
301 * @param args remaining command-line arguments
302 * @param cfgfile name of the configuration file used (for saving, can be NULL!)
303 * @param cfg configuration
306 run_no_scheduler (void *cls, char *const *args, const char *cfgfile,
307 const struct GNUNET_CONFIGURATION_Handle *cfg)
309 if (NULL != run_service_name)
311 ret = GNUNET_TESTING_service_run ("gnunet_service_test", run_service_name,
312 cfgfile, &testing_main, NULL);
316 if (GNUNET_YES == create_cfg)
320 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
321 "Creating %u configuration files based on template `%s'\n", create_no, create_cfg_template);
322 ret = create_unique_cfgs (create_cfg_template, create_no);
326 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Missing arguments! \n");
330 if (NULL != create_hostkey)
332 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Extracting hostkey %u\n", create_no);
333 ret = create_hostkeys (create_no);
335 GNUNET_free_non_null (create_cfg_template);
342 * @param argc number of arguments from the command line
343 * @param argv command line arguments
344 * @return 0 ok, 1 on error
347 main (int argc, char *const *argv)
349 struct GNUNET_GETOPT_CommandLineOption options[] = {
350 GNUNET_GETOPT_option_flag ('C',
352 gettext_noop ("create unique configuration files"),
354 GNUNET_GETOPT_option_string ('k',
357 gettext_noop ("extract hostkey file from pre-computed hostkey list"),
360 GNUNET_GETOPT_option_uint ('n',
363 gettext_noop ("number of unique configuration files to create, or number of the hostkey to extract"),
367 GNUNET_GETOPT_option_string ('t',
370 gettext_noop ("configuration template"),
371 &create_cfg_template),
373 GNUNET_GETOPT_option_string ('r',
376 gettext_noop ("run the given service, wait on stdin for 'r' (restart) or 'q' (quit)"),
378 GNUNET_GETOPT_OPTION_END
380 if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv))
383 /* Run without scheduler, because we may want to call
384 * GNUNET_TESTING_service_run, which starts the scheduler on its own.
385 * Furthermore, the other functionality currently does not require the scheduler, too,
386 * but beware when extending gnunet-testing. */
388 GNUNET_PROGRAM_run2 (argc, argv, "gnunet-testing",
389 gettext_noop ("Command line tool to access the testing library"), options, &run_no_scheduler,
390 NULL, GNUNET_YES)) ? ret : 1;
391 GNUNET_free ((void*) argv);
395 /* end of gnunet-testing.c */