Update README.linux
[deliverable/titan.core.git] / core / Single_main.cc
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 ///////////////////////////////////////////////////////////////////////////////
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <string.h>
11 #include <errno.h>
12 #include <unistd.h>
13
14 #include "../common/dbgnew.hh"
15 #include "../common/version_internal.h"
16 #include "Logger.hh"
17 #include "Snapshot.hh"
18 #include "Port.hh"
19 #include "Module_list.hh"
20 #include "Runtime.hh"
21 #include "Component.hh"
22 #include "Encdec.hh"
23 #include "TitanLoggerApi.hh"
24 #include "TCov.hh"
25 #ifdef LINUX
26 #include <execinfo.h>
27 #endif
28
29 #ifdef LICENSE
30 #include "../common/license.h"
31 #endif
32
33 #include <signal.h>
34
35 const char * stored_argv = "Unidentified program";
36
37 static const char segfault[] = ": Segmentation fault occurred\n";
38 static const char abortcall[] = ": Abort was called\n";
39
40 void signal_handler(int signum)
41 {
42 int retval;
43 retval = write(STDERR_FILENO, stored_argv, strlen(stored_argv));
44 if(signum==SIGSEGV){
45 retval = write(STDERR_FILENO, segfault , sizeof(segfault)-1); // sizeof includes \0
46 } else {
47 retval = write(STDERR_FILENO, abortcall , sizeof(abortcall)-1); // sizeof includes \0
48 }
49 #ifdef LINUX
50 int nptrs;
51 void *buffer[100];
52 nptrs = backtrace(buffer, 100);
53 backtrace_symbols_fd(buffer, nptrs, STDERR_FILENO);
54
55 fflush(stderr);
56 #endif
57 (void)retval;
58 TTCN_Logger::close_file();
59
60 signal(SIGABRT, SIG_DFL);
61 abort();
62 }
63
64 static void usage(const char* program_name)
65 {
66 fprintf(stderr, "\n"
67 "usage: %s configuration_file\n"
68 " or %s -l\n"
69 " or %s -v\n"
70 "\n"
71 "OPTIONS:\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);
75 }
76
77 int main(int argc, char *argv[])
78 {
79 stored_argv = argv[0];
80 struct sigaction act;
81 act.sa_handler = signal_handler;
82 sigemptyset(&act.sa_mask);
83 act.sa_flags = 0;
84 sigaction(SIGSEGV, &act, 0);
85 sigaction(SIGABRT, &act, 0);
86
87 #ifdef MEMORY_DEBUG
88 debug_new_counter.set_program_name(argv[0]);
89 #endif
90 errno = 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();
95
96 while ((c = getopt(argc, argv, "lv")) != -1) {
97 switch (c) {
98 case 'l':
99 if (lflag || vflag) errflag = TRUE; // duplicate or conflicting
100 else lflag = TRUE;
101 break;
102 case 'v':
103 if (lflag || vflag) errflag = TRUE; // duplicate or conflicting
104 else vflag = TRUE;
105 break;
106 default:
107 errflag = TRUE;
108 }
109 }
110
111 if (lflag || vflag) {
112 if (optind != argc) errflag = TRUE; // -l or -v and non-option arg
113 } else {
114 if (optind > argc - 1) { // no config file argument
115 errflag = (only_runnable == 0);
116 }
117 else config_file = argv[optind];
118 }
119
120 if (errflag) {
121 if (argc == 1) fputs("TTCN-3 Test Executor (single mode), version "
122 PRODUCT_NUMBER "\n", stderr);
123 usage(argv[0]);
124 TCov::close_file();
125 return EXIT_FAILURE;
126 } else if (lflag) {
127 try {
128 // create buffer for error messages
129 TTCN_Logger::initialize_logger();
130 Module_List::pre_init_modules();
131 Module_List::list_testcases();
132 } catch (...) {
133 ret_val = EXIT_FAILURE;
134 }
135 TTCN_Logger::terminate_logger();
136 TCov::close_file();
137 return ret_val;
138 } else if (vflag) {
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);
144 #ifdef LICENSE
145 print_license_info();
146 putc('\n', stderr);
147 #endif
148 fputs("Module information:\n", stderr);
149 Module_List::print_version();
150 TCov::close_file();
151 return EXIT_SUCCESS;
152 }
153
154 fputs("TTCN-3 Test Executor (single mode), version " PRODUCT_NUMBER "\n",
155 stderr);
156
157 #ifdef LICENSE
158 init_openssl();
159 license_struct lstr;
160 load_license(&lstr);
161 if (!verify_license(&lstr)) {
162 free_license(&lstr);
163 free_openssl();
164 exit(EXIT_FAILURE);
165 }
166 if (!check_feature(&lstr, FEATURE_SINGLE)) {
167 fputs("The license key does not allow test execution in single mode.\n",
168 stderr);
169 TCov::close_file();
170 return EXIT_FAILURE;
171 }
172 free_license(&lstr);
173 free_openssl();
174 #endif
175
176 self = MTC_COMPREF;
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();
183
184 try {
185 TTCN_Logger::log_executor_runtime(
186 TitanLoggerApi::ExecutorRuntime_reason::executor__start__single__mode);
187 Module_List::pre_init_modules();
188
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);
193 }
194
195 TTCN_Snapshot::check_fd_setsize();
196
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.
206 if (config_file) {
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);
214 }
215
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));
220
221 expstring_t testcase_names = memptystr(); // collects names for printout
222
223 for (i = optind; i < argc; ++i) {
224 testcase_names = mputstr(testcase_names, argv[i]);
225 testcase_names = mputc(testcase_names, '\t');
226
227 char *dot = strchr(argv[i], '.');
228 if (dot != 0) {
229 *dot++ = '\0'; // cut the string into two
230 if (!strcmp(dot, "control"))
231 dot = 0;
232 }
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
236 } // next i
237 fprintf(stderr, "Overriding testcase list: %s\n", testcase_names);
238 TTCN_Logger::log_configdata(
239 TitanLoggerApi::ExecutorConfigdata_reason::overriding__testcase__list,
240 testcase_names);
241 Free(testcase_names);
242 }
243 }
244
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
252 }
253
254 if (execute_list_len > 0) { // we have something to run
255 Module_List::log_param();
256 Module_List::post_init_modules();
257
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);
264 else
265 Module_List::execute_testcase(execute_list[i].module_name,
266 execute_list[i].testcase_name);
267 }
268 } else {
269 TTCN_warning("Nothing to run!");
270 fail:
271 ret_val = EXIT_FAILURE;
272 }
273 } catch (...) {
274 TTCN_Logger::log_str(TTCN_Logger::ERROR_UNQUALIFIED,
275 "Fatal error. Aborting execution.");
276 ret_val = EXIT_FAILURE;
277 }
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();
283 TCov::close_file();
284 // close_file() must be called before the information is lost
285 // close_file() WRITES to log
286
287 TTCN_Logger::clear_parameters();
288 PORT::clear_parameters();
289 COMPONENT::clear_component_names();
290 TTCN_EncDec::clear_error();
291
292 for (i = 0; i < execute_list_len; i++) {
293 Free(execute_list[i].module_name);
294 Free(execute_list[i].testcase_name);
295 }
296 Free(execute_list);
297
298 TTCN_Logger::terminate_logger();
299 TTCN_Snapshot::terminate();
300
301 return ret_val;
302 }
This page took 0.041296 seconds and 5 git commands to generate.