1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356
|
/******************************************************************************
* Copyright (c) 2000-2021 Ericsson Telecom AB
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/org/documents/epl-2.0/EPL-2.0.html
*
* Contributors:
* Baji, Laszlo
* Balasko, Jeno
* Beres, Szabolcs
* Delic, Adam
* Feher, Csaba
* Kovacs, Ferenc
* Lovassy, Arpad
* Raduly, Csaba
* Szabados, Kristof
* Szabo, Janos Zoltan – initial implementation
* Szalai, Gabor
* Zalanyi, Balazs Andor
* Pandi, Krisztian
*
******************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include "../common/dbgnew.hh"
#include "../common/version_internal.h"
#include "Logger.hh"
#include "Snapshot.hh"
#include "Port.hh"
#include "Module_list.hh"
#include "Runtime.hh"
#include "Component.hh"
#include "Encdec.hh"
#include "TitanLoggerApi.hh"
#include "TCov.hh"
#if defined(LINUX) && !defined(ALPINE_LINUX)
#include <execinfo.h>
#endif
#ifdef LICENSE
#include "../common/license.h"
#endif
#include <signal.h>
const char * stored_argv = "Unidentified program";
static const char segfault[] = ": Segmentation fault occurred\n";
static const char abortcall[] = ": Abort was called\n";
void signal_handler(int signum)
{
int retval;
retval = write(STDERR_FILENO, stored_argv, strlen(stored_argv));
if(signum==SIGSEGV){
retval = write(STDERR_FILENO, segfault , sizeof(segfault)-1); // sizeof includes \0
} else {
retval = write(STDERR_FILENO, abortcall , sizeof(abortcall)-1); // sizeof includes \0
}
#if defined(LINUX) && !defined(ALPINE_LINUX)
int nptrs;
void *buffer[100];
nptrs = backtrace(buffer, 100);
backtrace_symbols_fd(buffer, nptrs, STDERR_FILENO);
fflush(stderr);
#endif
(void)retval;
TTCN_Logger::close_file();
signal(SIGABRT, SIG_DFL);
abort();
}
static void usage(const char* program_name)
{
fprintf(stderr, "\n"
"usage: %s [-h] [-b file] configuration_file\n"
" or %s -l\n"
" or %s -p\n"
" or %s -v\n"
"\n"
"OPTIONS:\n"
" -b file: run specified batch file at start (debugger must be activated)\n"
" -h: automatically halt execution at start (debugger must be activated)\n"
" -l: list startable test cases and control parts\n"
" -p: list module parameters\n"
" -v: show version and module information\n",
program_name, program_name, program_name, program_name);
}
int main(int argc, char *argv[])
{
stored_argv = argv[0];
struct sigaction act;
act.sa_handler = signal_handler;
sigemptyset(&act.sa_mask);
act.sa_flags = 0;
sigaction(SIGSEGV, &act, 0);
sigaction(SIGABRT, &act, 0);
#ifdef MEMORY_DEBUG
debug_new_counter.set_program_name(argv[0]);
#endif
errno = 0;
int c, i, ret_val = EXIT_SUCCESS;
boolean bflag = FALSE, hflag = FALSE, lflag = FALSE, vflag = FALSE, pflag = FALSE,
errflag = FALSE;
const char *config_file = NULL;
TTCN_Module *only_runnable = Module_List::single_control_part();
while ((c = getopt(argc, argv, "b:hlvp")) != -1) {
switch (c) {
case 'b':
if (bflag || lflag || vflag || pflag) errflag = TRUE; // duplicate or conflicting
else {
bflag = TRUE;
ttcn3_debugger.set_initial_batch_file(optarg);
}
break;
case 'h':
if (hflag || lflag || vflag || pflag) errflag = TRUE; // duplicate or conflicting
else {
hflag = TRUE;
ttcn3_debugger.set_halt_at_start();
}
break;
case 'l':
if (lflag || vflag || pflag || bflag || hflag) errflag = TRUE; // duplicate or conflicting
else lflag = TRUE;
break;
case 'p':
if (pflag || lflag || vflag || bflag || hflag) errflag = TRUE; // duplicate or conflicting
else pflag = TRUE;
break;
case 'v':
if (lflag || vflag || pflag || bflag || hflag) errflag = TRUE; // duplicate or conflicting
else vflag = TRUE;
break;
default:
errflag = TRUE;
}
}
if (!errflag) {
if (lflag || vflag || pflag) {
if (optind != argc) errflag = TRUE; // -l, -p or -v and non-option arg
} else {
if (optind > argc - 1) { // no config file argument
errflag = (only_runnable == 0);
}
else config_file = argv[optind];
}
}
if (errflag) {
if (argc == 1) fputs("TTCN-3 Test Executor (single mode), version "
PRODUCT_NUMBER "\n", stderr);
usage(argv[0]);
TCov::close_file();
return EXIT_FAILURE;
} else if (lflag || pflag) {
try {
// create buffer for error messages
TTCN_Logger::initialize_logger();
Module_List::pre_init_modules();
if (lflag) {
Module_List::list_testcases();
}
else { // pflag
Module_List::list_modulepars();
}
} catch (...) {
ret_val = EXIT_FAILURE;
}
TTCN_Logger::terminate_logger();
TCov::close_file();
return ret_val;
} else if (vflag) {
fputs("TTCN-3 Test Executor (single mode)\n"
"Version: " VERSION_STRING "\n"
"Build date (Base Library): " __DATE__ " " __TIME__ "\n"
"Base Library was compiled with: " C_COMPILER_VERSION, stderr);
if (strlen(GIT_COMMIT_ID)) {
fputs("\nCommit id: ", stderr);
fputs(GIT_COMMIT_ID, stderr);
}
fputs("\n\n" COPYRIGHT_STRING "\n\n", stderr);
#ifdef LICENSE
print_license_info();
putc('\n', stderr);
#endif
fputs("Module information:\n", stderr);
Module_List::print_version();
TCov::close_file();
return EXIT_SUCCESS;
}
fputs("TTCN-3 Test Executor (single mode), version " PRODUCT_NUMBER "\n",
stderr);
#ifdef LICENSE
init_openssl();
license_struct lstr;
load_license(&lstr);
if (!verify_license(&lstr)) {
free_license(&lstr);
free_openssl();
exit(EXIT_FAILURE);
}
if (!check_feature(&lstr, FEATURE_SINGLE)) {
fputs("The license key does not allow test execution in single mode.\n",
stderr);
TCov::close_file();
return EXIT_FAILURE;
}
free_license(&lstr);
free_openssl();
#endif
self = MTC_COMPREF;
TTCN_Runtime::set_state(TTCN_Runtime::SINGLE_CONTROLPART);
TTCN_Runtime::install_signal_handlers();
TTCN_Snapshot::initialize();
TTCN_Logger::initialize_logger();
TTCN_Logger::set_executable_name(argv[0]);
TTCN_Logger::set_start_time();
try {
TTCN_Logger::log_executor_runtime(
TitanLoggerApi::ExecutorRuntime_reason::executor__start__single__mode);
Module_List::pre_init_modules();
if (config_file != 0) {
fprintf(stderr, "Using configuration file: `%s'\n", config_file);
TTCN_Logger::log_configdata(
TitanLoggerApi::ExecutorConfigdata_reason::using__config__file, config_file);
}
TTCN_Snapshot::check_fd_setsize();
boolean config_file_failure =
config_file && !process_config_file(config_file);
TTCN_Runtime::load_logger_plugins();
// Quick return if no config file.
TTCN_Runtime::set_logger_parameters();
TTCN_Logger::open_file();
TTCN_Logger::write_logger_settings();
if (config_file_failure) goto fail;
// Config file parsed or no config file: we may be able to run.
if (config_file) {
if (++optind != argc) {
// There are further commandline arguments after config file.
// Override testcase list.
// First, throw away the old list parsed from the config file.
for (i = 0; i < execute_list_len; i++) {
Free(execute_list[i].module_name);
Free(execute_list[i].testcase_name);
}
// The new execute list length is known in advance.
execute_list_len = argc - optind;
execute_list = (execute_list_item *)Realloc(
execute_list, execute_list_len * sizeof(*execute_list));
expstring_t testcase_names = memptystr(); // collects names for printout
for (i = optind; i < argc; ++i) {
testcase_names = mputstr(testcase_names, argv[i]);
testcase_names = mputc(testcase_names, '\t');
char *dot = strchr(argv[i], '.');
if (dot != 0) {
*dot++ = '\0'; // cut the string into two
if (!strcmp(dot, "control"))
dot = 0;
}
execute_list[i-optind].module_name = mcopystr(argv[i]);
execute_list[i-optind].testcase_name = dot ? mcopystr(dot) : dot;
// do not copy NULL pointer, it results in non-0 empty string
} // next i
fprintf(stderr, "Overriding testcase list: %s\n", testcase_names);
TTCN_Logger::log_configdata(
TitanLoggerApi::ExecutorConfigdata_reason::overriding__testcase__list,
testcase_names);
Free(testcase_names);
}
}
if (execute_list_len == 0 && only_runnable) {
// No config file or correct config file without EXECUTE section,
// AND precisely one control part: run that one.
execute_list_len = 1;
execute_list = (execute_list_item *)Malloc(sizeof(*execute_list));
execute_list[0].module_name = mcopystr(only_runnable->get_name());
execute_list[0].testcase_name = 0; // control part
}
if (execute_list_len > 0) { // we have something to run
Module_List::log_param();
Module_List::post_init_modules();
for (i = 0; i < execute_list_len; i++) {
if (ttcn3_debugger.is_exiting()) {
break;
}
if (execute_list[i].testcase_name == NULL)
Module_List::execute_control(execute_list[i].module_name);
else if (!strcmp(execute_list[i].testcase_name, "*"))
Module_List::execute_all_testcases(
execute_list[i].module_name);
else
Module_List::execute_testcase(execute_list[i].module_name,
execute_list[i].testcase_name);
}
} else {
TTCN_warning("Nothing to run!");
fail:
ret_val = EXIT_FAILURE;
}
} catch (...) {
TTCN_Logger::log_str(TTCN_Logger::ERROR_UNQUALIFIED,
"Fatal error. Aborting execution.");
ret_val = EXIT_FAILURE;
}
TTCN_Runtime::restore_signal_handlers();
TTCN_Runtime::log_verdict_statistics();
TTCN_Logger::log_executor_runtime(
TitanLoggerApi::ExecutorRuntime_reason::executor__finish__single__mode);
TTCN_Logger::close_file();
TCov::close_file();
// close_file() must be called before the information is lost
// close_file() WRITES to log
TTCN_Logger::clear_parameters();
PORT::clear_parameters();
COMPONENT::clear_component_names();
TTCN_EncDec::clear_error();
for (i = 0; i < execute_list_len; i++) {
Free(execute_list[i].module_name);
Free(execute_list[i].testcase_name);
}
Free(execute_list);
TTCN_Logger::terminate_logger();
TTCN_Snapshot::terminate();
TTCN_Runtime::clean_up();
return ret_val;
}
|