Merge pull request #62 from BenceJanosSzabo/master
[deliverable/titan.core.git] / core / Single_main.cc
CommitLineData
d44e3c4f 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 ******************************************************************************/
970ed795
EL
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"
a38c6d4c 41#ifdef LINUX
42#include <execinfo.h>
43#endif
970ed795
EL
44
45#ifdef LICENSE
46#include "../common/license.h"
47#endif
48
49#include <signal.h>
50
51const char * stored_argv = "Unidentified program";
52
53static const char segfault[] = ": Segmentation fault occurred\n";
a38c6d4c 54static const char abortcall[] = ": Abort was called\n";
970ed795 55
a38c6d4c 56void signal_handler(int signum)
970ed795
EL
57{
58 int retval;
59 retval = write(STDERR_FILENO, stored_argv, strlen(stored_argv));
a38c6d4c 60 if(signum==SIGSEGV){
970ed795 61 retval = write(STDERR_FILENO, segfault , sizeof(segfault)-1); // sizeof includes \0
a38c6d4c 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
970ed795
EL
73 (void)retval;
74 TTCN_Logger::close_file();
75
a38c6d4c 76 signal(SIGABRT, SIG_DFL);
970ed795
EL
77 abort();
78}
79
80static void usage(const char* program_name)
81{
82 fprintf(stderr, "\n"
83 "usage: %s configuration_file\n"
84 " or %s -l\n"
85 " or %s -v\n"
86 "\n"
87 "OPTIONS:\n"
88 " -l: list startable test cases and control parts\n"
89 " -v: show version and module information\n",
90 program_name, program_name, program_name);
91}
92
93int main(int argc, char *argv[])
94{
95 stored_argv = argv[0];
96 struct sigaction act;
97 act.sa_handler = signal_handler;
98 sigemptyset(&act.sa_mask);
99 act.sa_flags = 0;
100 sigaction(SIGSEGV, &act, 0);
a38c6d4c 101 sigaction(SIGABRT, &act, 0);
970ed795
EL
102
103#ifdef MEMORY_DEBUG
104 debug_new_counter.set_program_name(argv[0]);
105#endif
106 errno = 0;
107 int c, i, ret_val = EXIT_SUCCESS;
108 boolean lflag = FALSE, vflag = FALSE, errflag = FALSE;
109 const char *config_file = NULL;
110 TTCN_Module *only_runnable = Module_List::single_control_part();
111
112 while ((c = getopt(argc, argv, "lv")) != -1) {
113 switch (c) {
114 case 'l':
115 if (lflag || vflag) errflag = TRUE; // duplicate or conflicting
116 else lflag = TRUE;
117 break;
118 case 'v':
119 if (lflag || vflag) errflag = TRUE; // duplicate or conflicting
120 else vflag = TRUE;
121 break;
122 default:
123 errflag = TRUE;
124 }
125 }
126
127 if (lflag || vflag) {
128 if (optind != argc) errflag = TRUE; // -l or -v and non-option arg
129 } else {
130 if (optind > argc - 1) { // no config file argument
131 errflag = (only_runnable == 0);
132 }
133 else config_file = argv[optind];
134 }
135
136 if (errflag) {
137 if (argc == 1) fputs("TTCN-3 Test Executor (single mode), version "
138 PRODUCT_NUMBER "\n", stderr);
139 usage(argv[0]);
140 TCov::close_file();
141 return EXIT_FAILURE;
142 } else if (lflag) {
143 try {
144 // create buffer for error messages
145 TTCN_Logger::initialize_logger();
146 Module_List::pre_init_modules();
147 Module_List::list_testcases();
148 } catch (...) {
149 ret_val = EXIT_FAILURE;
150 }
151 TTCN_Logger::terminate_logger();
152 TCov::close_file();
153 return ret_val;
154 } else if (vflag) {
155 fputs("TTCN-3 Test Executor (single mode)\n"
156 "Product number: " PRODUCT_NUMBER "\n"
157 "Build date (Base Library): " __DATE__ " " __TIME__ "\n"
158 "Base Library was compiled with: " C_COMPILER_VERSION "\n\n"
159 COPYRIGHT_STRING "\n\n", stderr);
160#ifdef LICENSE
161 print_license_info();
162 putc('\n', stderr);
163#endif
164 fputs("Module information:\n", stderr);
165 Module_List::print_version();
166 TCov::close_file();
167 return EXIT_SUCCESS;
168 }
169
170 fputs("TTCN-3 Test Executor (single mode), version " PRODUCT_NUMBER "\n",
171 stderr);
172
173#ifdef LICENSE
174 init_openssl();
175 license_struct lstr;
176 load_license(&lstr);
177 if (!verify_license(&lstr)) {
178 free_license(&lstr);
179 free_openssl();
180 exit(EXIT_FAILURE);
181 }
182 if (!check_feature(&lstr, FEATURE_SINGLE)) {
183 fputs("The license key does not allow test execution in single mode.\n",
184 stderr);
185 TCov::close_file();
186 return EXIT_FAILURE;
187 }
188 free_license(&lstr);
189 free_openssl();
190#endif
191
192 self = MTC_COMPREF;
193 TTCN_Runtime::set_state(TTCN_Runtime::SINGLE_CONTROLPART);
194 TTCN_Runtime::install_signal_handlers();
195 TTCN_Snapshot::initialize();
196 TTCN_Logger::initialize_logger();
197 TTCN_Logger::set_executable_name(argv[0]);
198 TTCN_Logger::set_start_time();
199
200 try {
201 TTCN_Logger::log_executor_runtime(
202 TitanLoggerApi::ExecutorRuntime_reason::executor__start__single__mode);
203 Module_List::pre_init_modules();
204
205 if (config_file != 0) {
206 fprintf(stderr, "Using configuration file: `%s'\n", config_file);
207 TTCN_Logger::log_configdata(
208 TitanLoggerApi::ExecutorConfigdata_reason::using__config__file, config_file);
209 }
210
211 TTCN_Snapshot::check_fd_setsize();
212
213 boolean config_file_failure =
214 config_file && !process_config_file(config_file);
215 TTCN_Runtime::load_logger_plugins();
216 // Quick return if no config file.
217 TTCN_Runtime::set_logger_parameters();
218 TTCN_Logger::open_file();
219 TTCN_Logger::write_logger_settings();
220 if (config_file_failure) goto fail;
221 // Config file parsed or no config file: we may be able to run.
222 if (config_file) {
223 if (++optind != argc) {
224 // There are further commandline arguments after config file.
225 // Override testcase list.
226 // First, throw away the old list parsed from the config file.
227 for (i = 0; i < execute_list_len; i++) {
228 Free(execute_list[i].module_name);
229 Free(execute_list[i].testcase_name);
230 }
231
232 // The new execute list length is known in advance.
233 execute_list_len = argc - optind;
234 execute_list = (execute_list_item *)Realloc(
235 execute_list, execute_list_len * sizeof(*execute_list));
236
237 expstring_t testcase_names = memptystr(); // collects names for printout
238
239 for (i = optind; i < argc; ++i) {
240 testcase_names = mputstr(testcase_names, argv[i]);
241 testcase_names = mputc(testcase_names, '\t');
242
243 char *dot = strchr(argv[i], '.');
244 if (dot != 0) {
245 *dot++ = '\0'; // cut the string into two
246 if (!strcmp(dot, "control"))
247 dot = 0;
248 }
249 execute_list[i-optind].module_name = mcopystr(argv[i]);
250 execute_list[i-optind].testcase_name = dot ? mcopystr(dot) : dot;
251 // do not copy NULL pointer, it results in non-0 empty string
252 } // next i
253 fprintf(stderr, "Overriding testcase list: %s\n", testcase_names);
254 TTCN_Logger::log_configdata(
255 TitanLoggerApi::ExecutorConfigdata_reason::overriding__testcase__list,
256 testcase_names);
257 Free(testcase_names);
258 }
259 }
260
261 if (execute_list_len == 0 && only_runnable) {
262 // No config file or correct config file without EXECUTE section,
263 // AND precisely one control part: run that one.
264 execute_list_len = 1;
265 execute_list = (execute_list_item *)Malloc(sizeof(*execute_list));
266 execute_list[0].module_name = mcopystr(only_runnable->get_name());
267 execute_list[0].testcase_name = 0; // control part
268 }
269
270 if (execute_list_len > 0) { // we have something to run
271 Module_List::log_param();
272 Module_List::post_init_modules();
273
274 for (i = 0; i < execute_list_len; i++) {
275 if (execute_list[i].testcase_name == NULL)
276 Module_List::execute_control(execute_list[i].module_name);
277 else if (!strcmp(execute_list[i].testcase_name, "*"))
278 Module_List::execute_all_testcases(
279 execute_list[i].module_name);
280 else
281 Module_List::execute_testcase(execute_list[i].module_name,
282 execute_list[i].testcase_name);
283 }
284 } else {
285 TTCN_warning("Nothing to run!");
286fail:
287 ret_val = EXIT_FAILURE;
288 }
289 } catch (...) {
290 TTCN_Logger::log_str(TTCN_Logger::ERROR_UNQUALIFIED,
291 "Fatal error. Aborting execution.");
292 ret_val = EXIT_FAILURE;
293 }
294 TTCN_Runtime::restore_signal_handlers();
295 TTCN_Runtime::log_verdict_statistics();
296 TTCN_Logger::log_executor_runtime(
297 TitanLoggerApi::ExecutorRuntime_reason::executor__finish__single__mode);
298 TTCN_Logger::close_file();
299 TCov::close_file();
300 // close_file() must be called before the information is lost
301 // close_file() WRITES to log
302
303 TTCN_Logger::clear_parameters();
304 PORT::clear_parameters();
305 COMPONENT::clear_component_names();
306 TTCN_EncDec::clear_error();
307
308 for (i = 0; i < execute_list_len; i++) {
309 Free(execute_list[i].module_name);
310 Free(execute_list[i].testcase_name);
311 }
312 Free(execute_list);
313
314 TTCN_Logger::terminate_logger();
315 TTCN_Snapshot::terminate();
316
317 return ret_val;
318}
This page took 0.035255 seconds and 5 git commands to generate.