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/>.
18 SPDX-License-Identifier: AGPL3.0-or-later
22 * @file testing/gnunet-testing.c
23 * @brief tool to use testing functionality from cmd line
24 * @author Christian Grothoff
27 #include "gnunet_util_lib.h"
28 #include "gnunet_testing_lib.h"
31 #define LOG(kind, ...) GNUNET_log_from (kind, "gnunet-testing", __VA_ARGS__)
40 * Filename of the hostkey file we should write,
41 * null if we should not write a hostkey file.
43 static char *create_hostkey;
46 * Non-zero if we should create config files.
48 static int create_cfg;
51 * Number of config files to create.
53 static unsigned int create_no;
56 * Filename of the config template to be written.
58 static char *create_cfg_template;
61 * Service we are supposed to run.
63 static char *run_service_name;
66 * File handle to STDIN, for reading restart/quit commands.
68 static struct GNUNET_DISK_FileHandle *fh;
71 * Temporary filename, used with '-r' to write the configuration to.
73 static char *tmpfilename;
76 * Task identifier of the task that waits for stdin.
78 static struct GNUNET_SCHEDULER_Task *tid;
81 * Peer started for '-r'.
83 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,
99 "Configuration template `%s': file not found\n",
100 create_cfg_template);
103 cfg_tmpl = GNUNET_CONFIGURATION_create ();
106 if ((create_cfg_template != NULL) &&
107 (GNUNET_OK != GNUNET_CONFIGURATION_load (cfg_tmpl, create_cfg_template)))
109 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
110 "Could not load template `%s'\n",
111 create_cfg_template);
112 GNUNET_CONFIGURATION_destroy (cfg_tmpl);
117 if (GNUNET_OK != GNUNET_CONFIGURATION_load (cfg_tmpl, NULL))
119 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
120 "Could not load template `%s'\n",
121 create_cfg_template);
122 GNUNET_CONFIGURATION_destroy (cfg_tmpl);
128 GNUNET_TESTING_system_create ("testing", NULL /* controller */, NULL, NULL);
129 for (cur = 0; cur < no; cur++)
131 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
132 "Creating configuration no. %u \n",
134 if (create_cfg_template != NULL)
135 GNUNET_asprintf (&cur_file, "%04u-%s", cur, create_cfg_template);
137 GNUNET_asprintf (&cur_file, "%04u%s", cur, ".conf");
139 cfg_new = GNUNET_CONFIGURATION_dup (cfg_tmpl);
140 if (GNUNET_OK != GNUNET_TESTING_configuration_create (system, cfg_new))
142 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
143 "Could not create another configuration\n");
144 GNUNET_CONFIGURATION_destroy (cfg_new);
148 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
149 "Writing configuration no. %u to file `%s' \n",
152 if (GNUNET_OK != GNUNET_CONFIGURATION_write (cfg_new, cur_file))
154 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
155 "Failed to write configuration no. %u \n",
159 GNUNET_CONFIGURATION_destroy (cfg_new);
160 GNUNET_free (cur_file);
161 if (GNUNET_YES == fail)
164 GNUNET_CONFIGURATION_destroy (cfg_tmpl);
165 GNUNET_TESTING_system_destroy (system, GNUNET_NO);
166 if (GNUNET_YES == fail)
173 create_hostkeys (const unsigned int no)
175 struct GNUNET_TESTING_System *system;
176 struct GNUNET_PeerIdentity id;
177 struct GNUNET_DISK_FileHandle *fd;
178 struct GNUNET_CRYPTO_EddsaPrivateKey *pk;
180 system = GNUNET_TESTING_system_create ("testing", NULL, NULL, NULL);
181 pk = GNUNET_TESTING_hostkey_get (system, create_no, &id);
185 _ ("Could not extract hostkey %u (offset too large?)\n"),
187 GNUNET_TESTING_system_destroy (system, GNUNET_YES);
190 (void) GNUNET_DISK_directory_create_for_file (create_hostkey);
192 GNUNET_DISK_file_open (create_hostkey,
193 GNUNET_DISK_OPEN_READWRITE | GNUNET_DISK_OPEN_CREATE,
194 GNUNET_DISK_PERM_USER_READ
195 | GNUNET_DISK_PERM_USER_WRITE);
196 GNUNET_assert (fd != NULL);
197 ret = GNUNET_DISK_file_write (fd,
199 sizeof(struct GNUNET_CRYPTO_EddsaPrivateKey));
200 GNUNET_assert (GNUNET_OK == GNUNET_DISK_file_close (fd));
201 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG,
203 "Wrote hostkey to file: `%s'\n",
206 GNUNET_TESTING_system_destroy (system, GNUNET_YES);
212 * Cleanup called by signal handlers and when stdin is closed.
213 * Removes the temporary file.
220 if (NULL != tmpfilename)
222 if (0 != unlink (tmpfilename))
223 GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING,
229 GNUNET_SCHEDULER_cancel (tid);
234 GNUNET_DISK_file_close (fh);
241 * Called whenever we can read stdin non-blocking
256 GNUNET_SCHEDULER_shutdown ();
260 if (GNUNET_OK != GNUNET_TESTING_peer_stop (my_peer))
261 LOG (GNUNET_ERROR_TYPE_ERROR, "Failed to stop the peer\n");
262 if (GNUNET_OK != GNUNET_TESTING_peer_start (my_peer))
263 LOG (GNUNET_ERROR_TYPE_ERROR, "Failed to start the peer\n");
264 printf ("restarted\n");
270 /* ignore whitespace */
275 _ ("Unknown command, use 'q' to quit or 'r' to restart peer\n"));
278 tid = GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL,
286 * Main function called by the testing library.
287 * Executed inside a running scheduler.
290 * @param cfg configuration of the peer that was started
291 * @param peer handle to the peer
294 testing_main (void *cls,
295 const struct GNUNET_CONFIGURATION_Handle *cfg,
296 struct GNUNET_TESTING_Peer *peer)
299 if (NULL == (tmpfilename = GNUNET_DISK_mktemp ("gnunet-testing")))
302 GNUNET_SCHEDULER_shutdown ();
306 GNUNET_CONFIGURATION_write ((struct GNUNET_CONFIGURATION_Handle *) cfg,
312 printf ("ok\n%s\n", tmpfilename);
314 GNUNET_SCHEDULER_add_shutdown (&cleanup, NULL);
315 fh = GNUNET_DISK_get_handle_from_native (stdin);
316 tid = GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL,
324 * Main function that will be running without scheduler.
327 * @param args remaining command-line arguments
328 * @param cfgfile name of the configuration file used (for saving, can be NULL!)
329 * @param cfg configuration
332 run_no_scheduler (void *cls,
335 const struct GNUNET_CONFIGURATION_Handle *cfg)
337 if (NULL != run_service_name)
339 ret = GNUNET_TESTING_service_run ("gnunet_service_test",
347 if (GNUNET_YES == create_cfg)
351 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
352 "Creating %u configuration files based on template `%s'\n",
354 create_cfg_template);
355 ret = create_unique_cfgs (create_cfg_template, create_no);
359 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Missing arguments! \n");
363 if (NULL != create_hostkey)
365 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Extracting hostkey %u\n", create_no);
366 ret = create_hostkeys (create_no);
368 GNUNET_free_non_null (create_cfg_template);
375 * @param argc number of arguments from the command line
376 * @param argv command line arguments
377 * @return 0 ok, 1 on error
380 main (int argc, char *const *argv)
382 struct GNUNET_GETOPT_CommandLineOption options[] =
383 { GNUNET_GETOPT_option_flag ('C',
386 "create unique configuration files"),
388 GNUNET_GETOPT_option_string (
392 gettext_noop ("extract hostkey file from pre-computed hostkey list"),
395 GNUNET_GETOPT_option_uint (
400 "number of unique configuration files to create, or number of the hostkey to extract"),
404 GNUNET_GETOPT_option_string ('t',
407 gettext_noop ("configuration template"),
408 &create_cfg_template),
410 GNUNET_GETOPT_option_string (
415 "run the given service, wait on stdin for 'r' (restart) or 'q' (quit)"),
417 GNUNET_GETOPT_OPTION_END };
419 if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv))
422 /* Run without scheduler, because we may want to call
423 * GNUNET_TESTING_service_run, which starts the scheduler on its own.
424 * Furthermore, the other functionality currently does not require the scheduler, too,
425 * but beware when extending gnunet-testing. */
428 GNUNET_PROGRAM_run2 (argc,
432 "Command line tool to access the testing library"),
439 GNUNET_free ((void *) argv);
443 /* end of gnunet-testing.c */