1 /******************************************************************************
2 * Copyright (c) 2000-2016 Ericsson Telecom AB
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Eclipse Public License v1.0
5 * which accompanies this distribution, and is available at
6 * http://www.eclipse.org/legal/epl-v10.html
18 * Szabo, Janos Zoltan – initial implementation
20 * Zalanyi, Balazs Andor
23 ******************************************************************************/
30 #include "../common/dbgnew.hh"
31 #include "../common/version_internal.h"
33 #include "Snapshot.hh"
35 #include "Module_list.hh"
37 #include "Component.hh"
39 #include "TitanLoggerApi.hh"
46 #include "../common/license.h"
51 const char * stored_argv
= "Unidentified program";
53 static const char segfault
[] = ": Segmentation fault occurred\n";
54 static const char abortcall
[] = ": Abort was called\n";
56 void signal_handler(int signum
)
59 retval
= write(STDERR_FILENO
, stored_argv
, strlen(stored_argv
));
61 retval
= write(STDERR_FILENO
, segfault
, sizeof(segfault
)-1); // sizeof includes \0
63 retval
= write(STDERR_FILENO
, abortcall
, sizeof(abortcall
)-1); // sizeof includes \0
68 nptrs
= backtrace(buffer
, 100);
69 backtrace_symbols_fd(buffer
, nptrs
, STDERR_FILENO
);
74 TTCN_Logger::close_file();
76 signal(SIGABRT
, SIG_DFL
);
80 static void usage(const char* program_name
)
83 "usage: %s [-h] [-b file] configuration_file\n"
88 " -b file: run specified batch file at start (debugger must be activated)\n"
89 " -h: automatically halt execution at start (debugger must be activated)\n"
90 " -l: list startable test cases and control parts\n"
91 " -v: show version and module information\n",
92 program_name
, program_name
, program_name
);
95 int main(int argc
, char *argv
[])
97 stored_argv
= argv
[0];
99 act
.sa_handler
= signal_handler
;
100 sigemptyset(&act
.sa_mask
);
102 sigaction(SIGSEGV
, &act
, 0);
103 sigaction(SIGABRT
, &act
, 0);
106 debug_new_counter
.set_program_name(argv
[0]);
109 int c
, i
, ret_val
= EXIT_SUCCESS
;
110 boolean bflag
= FALSE
, hflag
= FALSE
, lflag
= FALSE
, vflag
= FALSE
, errflag
= FALSE
;
111 const char *config_file
= NULL
;
112 TTCN_Module
*only_runnable
= Module_List::single_control_part();
114 while ((c
= getopt(argc
, argv
, "b:hlv")) != -1) {
117 if (bflag
|| lflag
|| vflag
) errflag
= TRUE
; // duplicate or conflicting
120 ttcn3_debugger
.set_initial_batch_file(optarg
);
124 if (hflag
|| lflag
|| vflag
) errflag
= TRUE
; // duplicate or conflicting
127 ttcn3_debugger
.set_halt_at_start();
131 if (lflag
|| vflag
) errflag
= TRUE
; // duplicate or conflicting
135 if (lflag
|| vflag
) errflag
= TRUE
; // duplicate or conflicting
144 if (lflag
|| vflag
) {
145 if (optind
!= argc
) errflag
= TRUE
; // -l or -v and non-option arg
147 if (optind
> argc
- 1) { // no config file argument
148 errflag
= (only_runnable
== 0);
150 else config_file
= argv
[optind
];
155 if (argc
== 1) fputs("TTCN-3 Test Executor (single mode), version "
156 PRODUCT_NUMBER
"\n", stderr
);
162 // create buffer for error messages
163 TTCN_Logger::initialize_logger();
164 Module_List::pre_init_modules();
165 Module_List::list_testcases();
167 ret_val
= EXIT_FAILURE
;
169 TTCN_Logger::terminate_logger();
173 fputs("TTCN-3 Test Executor (single mode)\n"
174 "Product number: " PRODUCT_NUMBER
"\n"
175 "Build date (Base Library): " __DATE__
" " __TIME__
"\n"
176 "Base Library was compiled with: " C_COMPILER_VERSION
"\n\n"
177 COPYRIGHT_STRING
"\n\n", stderr
);
179 print_license_info();
182 fputs("Module information:\n", stderr
);
183 Module_List::print_version();
188 fputs("TTCN-3 Test Executor (single mode), version " PRODUCT_NUMBER
"\n",
195 if (!verify_license(&lstr
)) {
200 if (!check_feature(&lstr
, FEATURE_SINGLE
)) {
201 fputs("The license key does not allow test execution in single mode.\n",
211 TTCN_Runtime::set_state(TTCN_Runtime::SINGLE_CONTROLPART
);
212 TTCN_Runtime::install_signal_handlers();
213 TTCN_Snapshot::initialize();
214 TTCN_Logger::initialize_logger();
215 TTCN_Logger::set_executable_name(argv
[0]);
216 TTCN_Logger::set_start_time();
219 TTCN_Logger::log_executor_runtime(
220 TitanLoggerApi::ExecutorRuntime_reason::executor__start__single__mode
);
221 Module_List::pre_init_modules();
223 if (config_file
!= 0) {
224 fprintf(stderr
, "Using configuration file: `%s'\n", config_file
);
225 TTCN_Logger::log_configdata(
226 TitanLoggerApi::ExecutorConfigdata_reason::using__config__file
, config_file
);
229 TTCN_Snapshot::check_fd_setsize();
231 boolean config_file_failure
=
232 config_file
&& !process_config_file(config_file
);
233 TTCN_Runtime::load_logger_plugins();
234 // Quick return if no config file.
235 TTCN_Runtime::set_logger_parameters();
236 TTCN_Logger::open_file();
237 TTCN_Logger::write_logger_settings();
238 if (config_file_failure
) goto fail
;
239 // Config file parsed or no config file: we may be able to run.
241 if (++optind
!= argc
) {
242 // There are further commandline arguments after config file.
243 // Override testcase list.
244 // First, throw away the old list parsed from the config file.
245 for (i
= 0; i
< execute_list_len
; i
++) {
246 Free(execute_list
[i
].module_name
);
247 Free(execute_list
[i
].testcase_name
);
250 // The new execute list length is known in advance.
251 execute_list_len
= argc
- optind
;
252 execute_list
= (execute_list_item
*)Realloc(
253 execute_list
, execute_list_len
* sizeof(*execute_list
));
255 expstring_t testcase_names
= memptystr(); // collects names for printout
257 for (i
= optind
; i
< argc
; ++i
) {
258 testcase_names
= mputstr(testcase_names
, argv
[i
]);
259 testcase_names
= mputc(testcase_names
, '\t');
261 char *dot
= strchr(argv
[i
], '.');
263 *dot
++ = '\0'; // cut the string into two
264 if (!strcmp(dot
, "control"))
267 execute_list
[i
-optind
].module_name
= mcopystr(argv
[i
]);
268 execute_list
[i
-optind
].testcase_name
= dot
? mcopystr(dot
) : dot
;
269 // do not copy NULL pointer, it results in non-0 empty string
271 fprintf(stderr
, "Overriding testcase list: %s\n", testcase_names
);
272 TTCN_Logger::log_configdata(
273 TitanLoggerApi::ExecutorConfigdata_reason::overriding__testcase__list
,
275 Free(testcase_names
);
279 if (execute_list_len
== 0 && only_runnable
) {
280 // No config file or correct config file without EXECUTE section,
281 // AND precisely one control part: run that one.
282 execute_list_len
= 1;
283 execute_list
= (execute_list_item
*)Malloc(sizeof(*execute_list
));
284 execute_list
[0].module_name
= mcopystr(only_runnable
->get_name());
285 execute_list
[0].testcase_name
= 0; // control part
288 if (execute_list_len
> 0) { // we have something to run
289 Module_List::log_param();
290 Module_List::post_init_modules();
292 for (i
= 0; i
< execute_list_len
; i
++) {
293 if (ttcn3_debugger
.is_exiting()) {
296 if (execute_list
[i
].testcase_name
== NULL
)
297 Module_List::execute_control(execute_list
[i
].module_name
);
298 else if (!strcmp(execute_list
[i
].testcase_name
, "*"))
299 Module_List::execute_all_testcases(
300 execute_list
[i
].module_name
);
302 Module_List::execute_testcase(execute_list
[i
].module_name
,
303 execute_list
[i
].testcase_name
);
306 TTCN_warning("Nothing to run!");
308 ret_val
= EXIT_FAILURE
;
311 TTCN_Logger::log_str(TTCN_Logger::ERROR_UNQUALIFIED
,
312 "Fatal error. Aborting execution.");
313 ret_val
= EXIT_FAILURE
;
315 TTCN_Runtime::restore_signal_handlers();
316 TTCN_Runtime::log_verdict_statistics();
317 TTCN_Logger::log_executor_runtime(
318 TitanLoggerApi::ExecutorRuntime_reason::executor__finish__single__mode
);
319 TTCN_Logger::close_file();
321 // close_file() must be called before the information is lost
322 // close_file() WRITES to log
324 TTCN_Logger::clear_parameters();
325 PORT::clear_parameters();
326 COMPONENT::clear_component_names();
327 TTCN_EncDec::clear_error();
329 for (i
= 0; i
< execute_list_len
; i
++) {
330 Free(execute_list
[i
].module_name
);
331 Free(execute_list
[i
].testcase_name
);
335 TTCN_Logger::terminate_logger();
336 TTCN_Snapshot::terminate();