1 ///////////////////////////////////////////////////////////////////////////////
2 // Copyright (c) 2000-2014 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
7 ///////////////////////////////////////////////////////////////////////////////
14 #include "../common/dbgnew.hh"
15 #include "../common/version_internal.h"
17 #include "Snapshot.hh"
19 #include "Module_list.hh"
21 #include "Component.hh"
23 #include "TitanLoggerApi.hh"
30 #include "../common/license.h"
35 const char * stored_argv
= "Unidentified program";
37 static const char segfault
[] = ": Segmentation fault occurred\n";
38 static const char abortcall
[] = ": Abort was called\n";
40 void signal_handler(int signum
)
43 retval
= write(STDERR_FILENO
, stored_argv
, strlen(stored_argv
));
45 retval
= write(STDERR_FILENO
, segfault
, sizeof(segfault
)-1); // sizeof includes \0
47 retval
= write(STDERR_FILENO
, abortcall
, sizeof(abortcall
)-1); // sizeof includes \0
52 nptrs
= backtrace(buffer
, 100);
53 backtrace_symbols_fd(buffer
, nptrs
, STDERR_FILENO
);
58 TTCN_Logger::close_file();
60 signal(SIGABRT
, SIG_DFL
);
64 static void usage(const char* program_name
)
67 "usage: %s configuration_file\n"
72 " -l: list startable test cases and control parts\n"
73 " -v: show version and module information\n",
74 program_name
, program_name
, program_name
);
77 int main(int argc
, char *argv
[])
79 stored_argv
= argv
[0];
81 act
.sa_handler
= signal_handler
;
82 sigemptyset(&act
.sa_mask
);
84 sigaction(SIGSEGV
, &act
, 0);
85 sigaction(SIGABRT
, &act
, 0);
88 debug_new_counter
.set_program_name(argv
[0]);
91 int c
, i
, ret_val
= EXIT_SUCCESS
;
92 boolean lflag
= FALSE
, vflag
= FALSE
, errflag
= FALSE
;
93 const char *config_file
= NULL
;
94 TTCN_Module
*only_runnable
= Module_List::single_control_part();
96 while ((c
= getopt(argc
, argv
, "lv")) != -1) {
99 if (lflag
|| vflag
) errflag
= TRUE
; // duplicate or conflicting
103 if (lflag
|| vflag
) errflag
= TRUE
; // duplicate or conflicting
111 if (lflag
|| vflag
) {
112 if (optind
!= argc
) errflag
= TRUE
; // -l or -v and non-option arg
114 if (optind
> argc
- 1) { // no config file argument
115 errflag
= (only_runnable
== 0);
117 else config_file
= argv
[optind
];
121 if (argc
== 1) fputs("TTCN-3 Test Executor (single mode), version "
122 PRODUCT_NUMBER
"\n", stderr
);
128 // create buffer for error messages
129 TTCN_Logger::initialize_logger();
130 Module_List::pre_init_modules();
131 Module_List::list_testcases();
133 ret_val
= EXIT_FAILURE
;
135 TTCN_Logger::terminate_logger();
139 fputs("TTCN-3 Test Executor (single mode)\n"
140 "Product number: " PRODUCT_NUMBER
"\n"
141 "Build date (Base Library): " __DATE__
" " __TIME__
"\n"
142 "Base Library was compiled with: " C_COMPILER_VERSION
"\n\n"
143 COPYRIGHT_STRING
"\n\n", stderr
);
145 print_license_info();
148 fputs("Module information:\n", stderr
);
149 Module_List::print_version();
154 fputs("TTCN-3 Test Executor (single mode), version " PRODUCT_NUMBER
"\n",
161 if (!verify_license(&lstr
)) {
166 if (!check_feature(&lstr
, FEATURE_SINGLE
)) {
167 fputs("The license key does not allow test execution in single mode.\n",
177 TTCN_Runtime::set_state(TTCN_Runtime::SINGLE_CONTROLPART
);
178 TTCN_Runtime::install_signal_handlers();
179 TTCN_Snapshot::initialize();
180 TTCN_Logger::initialize_logger();
181 TTCN_Logger::set_executable_name(argv
[0]);
182 TTCN_Logger::set_start_time();
185 TTCN_Logger::log_executor_runtime(
186 TitanLoggerApi::ExecutorRuntime_reason::executor__start__single__mode
);
187 Module_List::pre_init_modules();
189 if (config_file
!= 0) {
190 fprintf(stderr
, "Using configuration file: `%s'\n", config_file
);
191 TTCN_Logger::log_configdata(
192 TitanLoggerApi::ExecutorConfigdata_reason::using__config__file
, config_file
);
195 TTCN_Snapshot::check_fd_setsize();
197 boolean config_file_failure
=
198 config_file
&& !process_config_file(config_file
);
199 TTCN_Runtime::load_logger_plugins();
200 // Quick return if no config file.
201 TTCN_Runtime::set_logger_parameters();
202 TTCN_Logger::open_file();
203 TTCN_Logger::write_logger_settings();
204 if (config_file_failure
) goto fail
;
205 // Config file parsed or no config file: we may be able to run.
207 if (++optind
!= argc
) {
208 // There are further commandline arguments after config file.
209 // Override testcase list.
210 // First, throw away the old list parsed from the config file.
211 for (i
= 0; i
< execute_list_len
; i
++) {
212 Free(execute_list
[i
].module_name
);
213 Free(execute_list
[i
].testcase_name
);
216 // The new execute list length is known in advance.
217 execute_list_len
= argc
- optind
;
218 execute_list
= (execute_list_item
*)Realloc(
219 execute_list
, execute_list_len
* sizeof(*execute_list
));
221 expstring_t testcase_names
= memptystr(); // collects names for printout
223 for (i
= optind
; i
< argc
; ++i
) {
224 testcase_names
= mputstr(testcase_names
, argv
[i
]);
225 testcase_names
= mputc(testcase_names
, '\t');
227 char *dot
= strchr(argv
[i
], '.');
229 *dot
++ = '\0'; // cut the string into two
230 if (!strcmp(dot
, "control"))
233 execute_list
[i
-optind
].module_name
= mcopystr(argv
[i
]);
234 execute_list
[i
-optind
].testcase_name
= dot
? mcopystr(dot
) : dot
;
235 // do not copy NULL pointer, it results in non-0 empty string
237 fprintf(stderr
, "Overriding testcase list: %s\n", testcase_names
);
238 TTCN_Logger::log_configdata(
239 TitanLoggerApi::ExecutorConfigdata_reason::overriding__testcase__list
,
241 Free(testcase_names
);
245 if (execute_list_len
== 0 && only_runnable
) {
246 // No config file or correct config file without EXECUTE section,
247 // AND precisely one control part: run that one.
248 execute_list_len
= 1;
249 execute_list
= (execute_list_item
*)Malloc(sizeof(*execute_list
));
250 execute_list
[0].module_name
= mcopystr(only_runnable
->get_name());
251 execute_list
[0].testcase_name
= 0; // control part
254 if (execute_list_len
> 0) { // we have something to run
255 Module_List::log_param();
256 Module_List::post_init_modules();
258 for (i
= 0; i
< execute_list_len
; i
++) {
259 if (execute_list
[i
].testcase_name
== NULL
)
260 Module_List::execute_control(execute_list
[i
].module_name
);
261 else if (!strcmp(execute_list
[i
].testcase_name
, "*"))
262 Module_List::execute_all_testcases(
263 execute_list
[i
].module_name
);
265 Module_List::execute_testcase(execute_list
[i
].module_name
,
266 execute_list
[i
].testcase_name
);
269 TTCN_warning("Nothing to run!");
271 ret_val
= EXIT_FAILURE
;
274 TTCN_Logger::log_str(TTCN_Logger::ERROR_UNQUALIFIED
,
275 "Fatal error. Aborting execution.");
276 ret_val
= EXIT_FAILURE
;
278 TTCN_Runtime::restore_signal_handlers();
279 TTCN_Runtime::log_verdict_statistics();
280 TTCN_Logger::log_executor_runtime(
281 TitanLoggerApi::ExecutorRuntime_reason::executor__finish__single__mode
);
282 TTCN_Logger::close_file();
284 // close_file() must be called before the information is lost
285 // close_file() WRITES to log
287 TTCN_Logger::clear_parameters();
288 PORT::clear_parameters();
289 COMPONENT::clear_component_names();
290 TTCN_EncDec::clear_error();
292 for (i
= 0; i
< execute_list_len
; i
++) {
293 Free(execute_list
[i
].module_name
);
294 Free(execute_list
[i
].testcase_name
);
298 TTCN_Logger::terminate_logger();
299 TTCN_Snapshot::terminate();