Debugger - Stage 3 (artf511247)
[deliverable/titan.core.git] / core / Single_main.cc
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
7 *
8 * Contributors:
9 * Baji, Laszlo
10 * Balasko, Jeno
11 * Beres, Szabolcs
12 * Delic, Adam
13 * Feher, Csaba
14 * Kovacs, Ferenc
15 * Lovassy, Arpad
16 * Raduly, Csaba
17 * Szabados, Kristof
18 * Szabo, Janos Zoltan – initial implementation
19 * Szalai, Gabor
20 * Zalanyi, Balazs Andor
21 * Pandi, Krisztian
22 *
23 ******************************************************************************/
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include <errno.h>
28 #include <unistd.h>
29
30 #include "../common/dbgnew.hh"
31 #include "../common/version_internal.h"
32 #include "Logger.hh"
33 #include "Snapshot.hh"
34 #include "Port.hh"
35 #include "Module_list.hh"
36 #include "Runtime.hh"
37 #include "Component.hh"
38 #include "Encdec.hh"
39 #include "TitanLoggerApi.hh"
40 #include "TCov.hh"
41 #ifdef LINUX
42 #include <execinfo.h>
43 #endif
44
45 #ifdef LICENSE
46 #include "../common/license.h"
47 #endif
48
49 #include <signal.h>
50
51 const char * stored_argv = "Unidentified program";
52
53 static const char segfault[] = ": Segmentation fault occurred\n";
54 static const char abortcall[] = ": Abort was called\n";
55
56 void signal_handler(int signum)
57 {
58 int retval;
59 retval = write(STDERR_FILENO, stored_argv, strlen(stored_argv));
60 if(signum==SIGSEGV){
61 retval = write(STDERR_FILENO, segfault , sizeof(segfault)-1); // sizeof includes \0
62 } else {
63 retval = write(STDERR_FILENO, abortcall , sizeof(abortcall)-1); // sizeof includes \0
64 }
65 #ifdef LINUX
66 int nptrs;
67 void *buffer[100];
68 nptrs = backtrace(buffer, 100);
69 backtrace_symbols_fd(buffer, nptrs, STDERR_FILENO);
70
71 fflush(stderr);
72 #endif
73 (void)retval;
74 TTCN_Logger::close_file();
75
76 signal(SIGABRT, SIG_DFL);
77 abort();
78 }
79
80 static void usage(const char* program_name)
81 {
82 fprintf(stderr, "\n"
83 "usage: %s [-h] [-b file] configuration_file\n"
84 " or %s -l\n"
85 " or %s -v\n"
86 "\n"
87 "OPTIONS:\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);
93 }
94
95 int main(int argc, char *argv[])
96 {
97 stored_argv = argv[0];
98 struct sigaction act;
99 act.sa_handler = signal_handler;
100 sigemptyset(&act.sa_mask);
101 act.sa_flags = 0;
102 sigaction(SIGSEGV, &act, 0);
103 sigaction(SIGABRT, &act, 0);
104
105 #ifdef MEMORY_DEBUG
106 debug_new_counter.set_program_name(argv[0]);
107 #endif
108 errno = 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();
113
114 while ((c = getopt(argc, argv, "b:hlv")) != -1) {
115 switch (c) {
116 case 'b':
117 if (bflag || lflag || vflag) errflag = TRUE; // duplicate or conflicting
118 else {
119 bflag = TRUE;
120 ttcn3_debugger.set_initial_batch_file(optarg);
121 }
122 break;
123 case 'h':
124 if (hflag || lflag || vflag) errflag = TRUE; // duplicate or conflicting
125 else {
126 hflag = TRUE;
127 ttcn3_debugger.set_halt_at_start();
128 }
129 break;
130 case 'l':
131 if (lflag || vflag) errflag = TRUE; // duplicate or conflicting
132 else lflag = TRUE;
133 break;
134 case 'v':
135 if (lflag || vflag) errflag = TRUE; // duplicate or conflicting
136 else vflag = TRUE;
137 break;
138 default:
139 errflag = TRUE;
140 }
141 }
142
143 if (!errflag) {
144 if (lflag || vflag) {
145 if (optind != argc) errflag = TRUE; // -l or -v and non-option arg
146 } else {
147 if (optind > argc - 1) { // no config file argument
148 errflag = (only_runnable == 0);
149 }
150 else config_file = argv[optind];
151 }
152 }
153
154 if (errflag) {
155 if (argc == 1) fputs("TTCN-3 Test Executor (single mode), version "
156 PRODUCT_NUMBER "\n", stderr);
157 usage(argv[0]);
158 TCov::close_file();
159 return EXIT_FAILURE;
160 } else if (lflag) {
161 try {
162 // create buffer for error messages
163 TTCN_Logger::initialize_logger();
164 Module_List::pre_init_modules();
165 Module_List::list_testcases();
166 } catch (...) {
167 ret_val = EXIT_FAILURE;
168 }
169 TTCN_Logger::terminate_logger();
170 TCov::close_file();
171 return ret_val;
172 } else if (vflag) {
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);
178 #ifdef LICENSE
179 print_license_info();
180 putc('\n', stderr);
181 #endif
182 fputs("Module information:\n", stderr);
183 Module_List::print_version();
184 TCov::close_file();
185 return EXIT_SUCCESS;
186 }
187
188 fputs("TTCN-3 Test Executor (single mode), version " PRODUCT_NUMBER "\n",
189 stderr);
190
191 #ifdef LICENSE
192 init_openssl();
193 license_struct lstr;
194 load_license(&lstr);
195 if (!verify_license(&lstr)) {
196 free_license(&lstr);
197 free_openssl();
198 exit(EXIT_FAILURE);
199 }
200 if (!check_feature(&lstr, FEATURE_SINGLE)) {
201 fputs("The license key does not allow test execution in single mode.\n",
202 stderr);
203 TCov::close_file();
204 return EXIT_FAILURE;
205 }
206 free_license(&lstr);
207 free_openssl();
208 #endif
209
210 self = MTC_COMPREF;
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();
217
218 try {
219 TTCN_Logger::log_executor_runtime(
220 TitanLoggerApi::ExecutorRuntime_reason::executor__start__single__mode);
221 Module_List::pre_init_modules();
222
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);
227 }
228
229 TTCN_Snapshot::check_fd_setsize();
230
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.
240 if (config_file) {
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);
248 }
249
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));
254
255 expstring_t testcase_names = memptystr(); // collects names for printout
256
257 for (i = optind; i < argc; ++i) {
258 testcase_names = mputstr(testcase_names, argv[i]);
259 testcase_names = mputc(testcase_names, '\t');
260
261 char *dot = strchr(argv[i], '.');
262 if (dot != 0) {
263 *dot++ = '\0'; // cut the string into two
264 if (!strcmp(dot, "control"))
265 dot = 0;
266 }
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
270 } // next i
271 fprintf(stderr, "Overriding testcase list: %s\n", testcase_names);
272 TTCN_Logger::log_configdata(
273 TitanLoggerApi::ExecutorConfigdata_reason::overriding__testcase__list,
274 testcase_names);
275 Free(testcase_names);
276 }
277 }
278
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
286 }
287
288 if (execute_list_len > 0) { // we have something to run
289 Module_List::log_param();
290 Module_List::post_init_modules();
291
292 for (i = 0; i < execute_list_len; i++) {
293 if (ttcn3_debugger.is_exiting()) {
294 break;
295 }
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);
301 else
302 Module_List::execute_testcase(execute_list[i].module_name,
303 execute_list[i].testcase_name);
304 }
305 } else {
306 TTCN_warning("Nothing to run!");
307 fail:
308 ret_val = EXIT_FAILURE;
309 }
310 } catch (...) {
311 TTCN_Logger::log_str(TTCN_Logger::ERROR_UNQUALIFIED,
312 "Fatal error. Aborting execution.");
313 ret_val = EXIT_FAILURE;
314 }
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();
320 TCov::close_file();
321 // close_file() must be called before the information is lost
322 // close_file() WRITES to log
323
324 TTCN_Logger::clear_parameters();
325 PORT::clear_parameters();
326 COMPONENT::clear_component_names();
327 TTCN_EncDec::clear_error();
328
329 for (i = 0; i < execute_list_len; i++) {
330 Free(execute_list[i].module_name);
331 Free(execute_list[i].testcase_name);
332 }
333 Free(execute_list);
334
335 TTCN_Logger::terminate_logger();
336 TTCN_Snapshot::terminate();
337
338 return ret_val;
339 }
This page took 0.037411 seconds and 5 git commands to generate.