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
17 * Szabo, Janos Zoltan – initial implementation
18 * Zalanyi, Balazs Andor
20 ******************************************************************************/
24 #include <sys/types.h>
33 typedef void (*signal_handler_type)(int);
40 enum executor_state_enum {
43 SINGLE_CONTROLPART, SINGLE_TESTCASE, // 1,2
45 HC_INITIAL, HC_IDLE, HC_CONFIGURING, HC_ACTIVE, HC_OVERLOADED, // 3-7
46 HC_OVERLOADED_TIMEOUT, HC_EXIT, // 8-9
48 MTC_INITIAL, MTC_IDLE, MTC_CONTROLPART, MTC_TESTCASE, // 10-13
49 MTC_TERMINATING_TESTCASE, MTC_TERMINATING_EXECUTION, MTC_PAUSED, // 14-16
50 MTC_CREATE, MTC_START, MTC_STOP, MTC_KILL, MTC_RUNNING, MTC_ALIVE, // 17-22
51 MTC_DONE, MTC_KILLED, MTC_CONNECT, MTC_DISCONNECT, MTC_MAP, MTC_UNMAP, // 23-28
54 PTC_INITIAL, PTC_IDLE, PTC_FUNCTION, PTC_CREATE, PTC_START, PTC_STOP, // 30-35
55 PTC_KILL, PTC_RUNNING, PTC_ALIVE, PTC_DONE, PTC_KILLED, PTC_CONNECT, // 36-41
56 PTC_DISCONNECT, PTC_MAP, PTC_UNMAP, PTC_STOPPED, PTC_EXIT // 42-46
59 static executor_state_enum executor_state;
61 static qualified_name component_type;
62 static char *component_name;
63 static boolean is_alive;
65 static const char *control_module_name;
66 static qualified_name testcase_name;
68 static char *host_name;
70 static verdicttype local_verdict;
71 static unsigned int verdict_count[5], control_error_count;
72 static CHARSTRING verdict_reason;
74 /** TTCN_TryBlock uses the private member in_ttcn_try_block */
75 friend class TTCN_TryBlock;
76 /** true if execution is currently inside a TTCN-3 try{} */
77 static boolean in_ttcn_try_block;
79 static char *begin_controlpart_command, *end_controlpart_command,
80 *begin_testcase_command, *end_testcase_command;
82 static component create_done_killed_compref;
83 static boolean running_alive_result;
85 static alt_status any_component_done_status, all_component_done_status,
86 any_component_killed_status, all_component_killed_status;
87 static int component_status_table_size;
88 static component component_status_table_offset;
89 struct component_status_table_struct;
90 static component_status_table_struct *component_status_table;
92 struct component_process_struct;
93 static component_process_struct **components_by_compref,
97 inline static executor_state_enum get_state() { return executor_state; }
98 inline static void set_state(executor_state_enum new_state)
99 { executor_state = new_state; }
101 /** @name Identifying the type
104 inline static boolean is_hc()
105 { return executor_state >= HC_INITIAL && executor_state <= HC_EXIT; }
106 inline static boolean is_mtc()
107 { return executor_state >= MTC_INITIAL && executor_state <= MTC_EXIT; }
108 inline static boolean is_ptc()
109 { return executor_state >= PTC_INITIAL && executor_state <= PTC_EXIT; }
110 inline static boolean is_tc()
111 { return executor_state >= MTC_INITIAL && executor_state <= PTC_EXIT; }
112 inline static boolean is_single()
113 { return executor_state >= SINGLE_CONTROLPART &&
114 executor_state <= SINGLE_TESTCASE; }
115 inline static boolean is_undefined() /* e.g.: when listing test cases (<EXE> -l) */
116 { return executor_state == UNDEFINED_STATE; }
117 static boolean is_idle();
118 inline static boolean is_overloaded()
119 { return executor_state == HC_OVERLOADED ||
120 executor_state == HC_OVERLOADED_TIMEOUT; }
123 static boolean is_in_ttcn_try_block() { return in_ttcn_try_block; }
126 inline static boolean in_controlpart()
127 { return executor_state == SINGLE_CONTROLPART ||
128 executor_state == MTC_CONTROLPART; }
129 /** Whether verdict operations are allowed */
130 static boolean verdict_enabled();
131 static void wait_for_state_change();
132 static void clear_qualified_name(qualified_name& q_name);
133 static void clean_up();
135 static void initialize_component_type();
136 static void terminate_component_type();
139 static void set_component_type(const char *component_type_module,
140 const char *component_type_name);
141 static void set_component_name(const char *new_component_name);
142 inline static void set_alive_flag(boolean par_is_alive)
143 { is_alive = par_is_alive; }
144 static void set_testcase_name(const char *par_module_name,
145 const char *par_testcase_name);
147 inline static const char *get_component_type()
148 { return component_type.definition_name; }
149 inline static const char *get_component_name()
150 { return component_name; }
151 inline static const char *get_testcase_name()
152 { return testcase_name.definition_name; }
154 /// Returns a string which must not be freed.
155 static const char *get_host_name();
157 static CHARSTRING get_testcase_id_macro();
158 static CHARSTRING get_testcasename();
160 static void load_logger_plugins();
161 static void set_logger_parameters();
163 static const char *get_signal_name(int signal_number);
165 static void set_signal_handler(int signal_number, const char *signal_name,
166 signal_handler_type signal_handler);
167 static void restore_default_handler(int signal_number,
168 const char *signal_name);
169 static void ignore_signal(int signal_number, const char *signal_name);
170 static void enable_interrupt_handler();
171 static void disable_interrupt_handler();
173 static void install_signal_handlers();
174 static void restore_signal_handlers();
177 static int hc_main(const char *local_addr, const char *MC_addr,
178 unsigned short MC_port);
179 static int mtc_main();
180 static int ptc_main();
182 static component create_component(const char *created_component_type_module,
183 const char *created_component_type_name,
184 const char *created_component_name,
185 const char *created_component_location,
186 boolean created_component_alive);
187 static void prepare_start_component(const COMPONENT& component_reference,
188 const char *module_name, const char *function_name,
190 static void send_start_component(Text_Buf& text_buf);
191 static void start_function(const char *module_name,
192 const char *function_name, Text_Buf& text_buf);
193 static void function_started(Text_Buf& text_buf);
194 static void prepare_function_finished(const char *return_type,
196 static void send_function_finished(Text_Buf& text_buf);
197 static void function_finished(const char *function_name);
199 static alt_status component_done(component component_reference);
200 static alt_status component_done(component component_reference,
201 const char *return_type, Text_Buf*& text_buf);
202 static alt_status component_killed(component component_reference);
203 static boolean component_running(component component_reference);
204 static boolean component_alive(component component_reference);
205 static void stop_component(component component_reference);
206 static void stop_execution()
207 __attribute__ ((__noreturn__));
208 static void kill_component(component component_reference);
209 static void kill_execution()
210 __attribute__ ((__noreturn__));
213 static alt_status ptc_done(component component_reference);
214 static alt_status any_component_done();
215 static alt_status all_component_done();
216 static alt_status ptc_killed(component component_reference);
217 static alt_status any_component_killed();
218 static alt_status all_component_killed();
219 static boolean ptc_running(component component_reference);
220 static boolean any_component_running();
221 static boolean all_component_running();
222 static boolean ptc_alive(component component_reference);
223 static boolean any_component_alive();
224 static boolean all_component_alive();
225 static void stop_mtc()
226 __attribute__ ((__noreturn__));
227 static void stop_ptc(component component_reference);
228 static void stop_all_component();
229 static void kill_ptc(component component_reference);
230 static void kill_all_component();
232 static void check_port_name(const char *port_name,
233 const char *operation_name, const char *which_argument);
235 static void connect_port(
236 const COMPONENT& src_compref, const char *src_port,
237 const COMPONENT& dst_compref, const char *dst_port);
238 static void disconnect_port(
239 const COMPONENT& src_compref, const char *src_port,
240 const COMPONENT& dst_compref, const char *dst_port);
241 static void map_port(
242 const COMPONENT& src_compref, const char *src_port,
243 const COMPONENT& dst_compref, const char *dst_port);
244 static void unmap_port(
245 const COMPONENT& src_compref, const char *src_port,
246 const COMPONENT& dst_compref, const char *dst_port);
248 static void begin_controlpart(const char *module_name);
249 static void end_controlpart();
250 static void check_begin_testcase(boolean has_timer, double timer_value);
251 static void begin_testcase(
252 const char *par_module_name, const char *par_testcase_name,
253 const char *mtc_comptype_module, const char *mtc_comptype_name,
254 const char *system_comptype_module, const char *system_comptype_name,
255 boolean has_timer, double timer_value);
256 static verdicttype end_testcase();
257 static void log_verdict_statistics();
259 static void begin_action();
260 static void end_action();
262 static void setverdict(verdicttype new_value, const char* reason = "");
263 static void setverdict(const VERDICTTYPE& new_value,
264 const char* reason = "");
265 static void set_error_verdict();
266 static verdicttype getverdict();
268 static void setverdict_internal(verdicttype new_value,
269 const char* reason = "");
272 /** @name Manipulating external commands
275 static void set_begin_controlpart_command(const char *new_command);
276 static void set_end_controlpart_command(const char *new_command);
277 static void set_begin_testcase_command(const char *new_command);
278 static void set_end_testcase_command(const char *new_command);
279 static void clear_external_commands();
282 static char *shell_escape(const char *command_str);
283 static void execute_command(const char *command_name,
284 const char *argument_string);
287 static void process_create_mtc();
288 static void process_create_ptc(component component_reference,
289 const char *component_type_module, const char *component_type_name,
290 const char *par_component_name, boolean par_is_alive,
291 const char *current_testcase_module, const char *current_testcase_name);
293 static void process_create_ack(component new_component);
294 static void process_running(boolean result_value);
295 static void process_alive(boolean result_value);
296 static void process_done_ack(boolean done_status,
297 const char *return_type, int return_value_len,
298 const void *return_value);
299 static void process_killed_ack(boolean killed_status);
300 static void process_ptc_verdict(Text_Buf& text_buf);
301 static void process_kill();
302 static void process_kill_process(component component_reference);
304 static void set_component_done(component component_reference,
305 const char *return_type, int return_value_len,
306 const void *return_value);
307 static void set_component_killed(component component_reference);
308 static void cancel_component_done(component component_reference);
311 static int get_component_status_table_index(component component_reference);
312 static alt_status get_killed_status(component component_reference);
313 static boolean in_component_status_table(component component_reference);
314 static void clear_component_status_table();
316 static void initialize_component_process_tables();
317 static void add_component(component component_reference, pid_t process_id);
318 static void remove_component(component_process_struct *comp);
319 static component_process_struct *get_component_by_compref(component
320 component_reference);
321 static component_process_struct *get_component_by_pid(pid_t process_id);
322 static void clear_component_process_tables();
324 static void successful_process_creation();
325 static void failed_process_creation();
328 static void wait_terminated_processes();
329 static void check_overload();
332 /** TTCN_TryBlock must be used only as a local variable of a TTCN-3 try{} block.
333 It handles the value of TTCN_Runtime::in_ttcn_try_block using C++'s RAII feature */
334 class TTCN_TryBlock {
338 if (TTCN_Runtime::in_ttcn_try_block) {
342 TTCN_Runtime::in_ttcn_try_block = TRUE;
347 TTCN_Runtime::in_ttcn_try_block = FALSE;