/****************************************************************************** * Copyright (c) 2000-2020 Ericsson Telecom AB * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v2.0 * which accompanies this distribution, and is available at * https://www.eclipse.org/org/documents/epl-2.0/EPL-2.0.html * * Contributors: * Baji, Laszlo * Balasko, Jeno * Baranyi, Botond * Delic, Adam * Forstner, Matyas * Kovacs, Ferenc * Raduly, Csaba * Szabados, Kristof * Szabo, Bence Janos * Szabo, Janos Zoltan – initial implementation * Zalanyi, Balazs Andor * ******************************************************************************/ #ifndef RUNTIME_HH #define RUNTIME_HH #include <sys/types.h> #include <time.h> #include "Types.h" class Text_Buf; class COMPONENT; class VERDICTTYPE; class CHARSTRING; class INTEGER; class FLOAT; class PORT; class Map_Params; extern "C" { typedef void (*signal_handler_type)(int); } /** @brief */ class TTCN_Runtime { public: enum executor_state_enum { UNDEFINED_STATE, // 0 SINGLE_CONTROLPART, SINGLE_TESTCASE, // 1,2 HC_INITIAL, HC_IDLE, HC_CONFIGURING, HC_ACTIVE, HC_OVERLOADED, // 3-7 HC_OVERLOADED_TIMEOUT, HC_EXIT, // 8-9 MTC_INITIAL, MTC_IDLE, MTC_CONTROLPART, MTC_TESTCASE, // 10-13 MTC_TERMINATING_TESTCASE, MTC_TERMINATING_EXECUTION, MTC_PAUSED, // 14-16 MTC_CREATE, MTC_START, MTC_STOP, MTC_KILL, MTC_RUNNING, MTC_ALIVE, // 17-22 MTC_DONE, MTC_KILLED, MTC_CONNECT, MTC_DISCONNECT, MTC_MAP, MTC_UNMAP, // 23-28 MTC_CONFIGURING, MTC_EXIT, // 30 PTC_INITIAL, PTC_IDLE, PTC_FUNCTION, PTC_CREATE, PTC_START, PTC_STOP, // 31-36 PTC_KILL, PTC_RUNNING, PTC_ALIVE, PTC_DONE, PTC_KILLED, PTC_CONNECT, // 37-42 PTC_DISCONNECT, PTC_MAP, PTC_UNMAP, PTC_STOPPED, PTC_EXIT // 43-47 }; private: static executor_state_enum executor_state; static qualified_name component_type; static qualified_name system_type; static char *component_name; static boolean is_alive; static const char *control_module_name; static qualified_name testcase_name; static timeval start_time; static char *host_name; static verdicttype local_verdict; static unsigned int verdict_count[5], control_error_count; static CHARSTRING verdict_reason; /** TTCN_TryBlock uses the private member in_ttcn_try_block */ friend class TTCN_TryBlock; /** true if execution is currently inside a TTCN-3 try{} */ static boolean in_ttcn_try_block; static char *begin_controlpart_command, *end_controlpart_command, *begin_testcase_command, *end_testcase_command; static component create_done_killed_compref; static boolean running_alive_result; static alt_status any_component_done_status, all_component_done_status, any_component_killed_status, all_component_killed_status; static int component_status_table_size; static component component_status_table_offset; struct component_status_table_struct; static component_status_table_struct *component_status_table; struct component_process_struct; static component_process_struct **components_by_compref, **components_by_pid; // Translation count is increased before each port translation function called, // and decreased after each port translation function. // Need to count because we can now send and receive in translation // functions and can call another translation function. static int translation_count; // The port which state will be changed by change_port_state static PORT* p; public: inline static executor_state_enum get_state() { return executor_state; } inline static void set_state(executor_state_enum new_state) { executor_state = new_state; } /** @name Identifying the type * @{ */ inline static boolean is_hc() { return executor_state >= HC_INITIAL && executor_state <= HC_EXIT; } inline static boolean is_mtc() { return executor_state >= MTC_INITIAL && executor_state <= MTC_EXIT; } inline static boolean is_ptc() { return executor_state >= PTC_INITIAL && executor_state <= PTC_EXIT; } inline static boolean is_tc() { return executor_state >= MTC_INITIAL && executor_state <= PTC_EXIT; } inline static boolean is_single() { return executor_state >= SINGLE_CONTROLPART && executor_state <= SINGLE_TESTCASE; } inline static boolean is_undefined() /* e.g.: when listing test cases (<EXE> -l) */ { return executor_state == UNDEFINED_STATE; } static boolean is_idle(); inline static boolean is_overloaded() { return executor_state == HC_OVERLOADED || executor_state == HC_OVERLOADED_TIMEOUT; } /** @} */ static boolean is_in_ttcn_try_block() { return in_ttcn_try_block; } static void set_port_state(const INTEGER& state, const CHARSTRING& info, boolean by_system); static void set_translation_mode(boolean enabled, PORT* port); static PORT* get_translation_port(); private: inline static boolean in_controlpart() { return executor_state == SINGLE_CONTROLPART || executor_state == MTC_CONTROLPART; } /** Whether verdict operations are allowed */ static boolean verdict_enabled(); static void wait_for_state_change(); static void clear_qualified_name(qualified_name& q_name); static void initialize_component_type(); static void terminate_component_type(); public: static void clean_up(); static void set_component_type(const char *component_type_module, const char *component_type_name); static void set_system_type(const char* system_type_module, const char* system_type_name); static void set_component_name(const char *new_component_name); inline static void set_alive_flag(boolean par_is_alive) { is_alive = par_is_alive; } static void set_testcase_name(const char *par_module_name, const char *par_testcase_name); inline static const char *get_component_type() { return component_type.definition_name; } inline static const char *get_component_name() { return component_name; } inline static const char *get_testcase_name() { return testcase_name.definition_name; } /// Returns a string which must not be freed. static const char *get_host_name(); static CHARSTRING get_host_address(const CHARSTRING& type); static CHARSTRING get_testcase_id_macro(); static CHARSTRING get_testcasename(); static FLOAT now(); static void load_logger_plugins(); static void set_logger_parameters(); static const char *get_signal_name(int signal_number); private: static void set_signal_handler(int signal_number, const char *signal_name, signal_handler_type signal_handler); static void restore_default_handler(int signal_number, const char *signal_name); static void ignore_signal(int signal_number, const char *signal_name); static void enable_interrupt_handler(); static void disable_interrupt_handler(); public: static void install_signal_handlers(); static void restore_signal_handlers(); public: static int hc_main(const char *local_addr, const char *MC_addr, unsigned short MC_port); static int mtc_main(); static int ptc_main(); static void initialize_system_port(const char* port_name); static component create_component(const char *created_component_type_module, const char *created_component_type_name, const char *created_component_name, const char *created_component_location, boolean created_component_alive); static void prepare_start_component(const COMPONENT& component_reference, const char *module_name, const char *function_name, Text_Buf& text_buf); static void send_start_component(Text_Buf& text_buf); static void start_function(const char *module_name, const char *function_name, Text_Buf& text_buf); static void function_started(Text_Buf& text_buf); static void prepare_function_finished(const char *return_type, Text_Buf& text_buf); static void send_function_finished(Text_Buf& text_buf); static void function_finished(const char *function_name); static alt_status component_done(component component_reference, verdicttype* ptc_verdict = NULL); static alt_status component_done(component component_reference, const char *return_type, Text_Buf*& text_buf); static alt_status component_killed(component component_reference); static boolean component_running(component component_reference); static boolean component_alive(component component_reference); static void stop_component(component component_reference); static void stop_execution() __attribute__ ((__noreturn__)); static void kill_component(component component_reference); static void kill_execution() __attribute__ ((__noreturn__)); private: static alt_status ptc_done(component component_reference, verdicttype* ptc_verdict); static alt_status any_component_done(); static alt_status all_component_done(); static alt_status ptc_killed(component component_reference); static alt_status any_component_killed(); static alt_status all_component_killed(); static boolean ptc_running(component component_reference); static boolean any_component_running(); static boolean all_component_running(); static boolean ptc_alive(component component_reference); static boolean any_component_alive(); static boolean all_component_alive(); static void stop_mtc() __attribute__ ((__noreturn__)); static void stop_ptc(component component_reference); static void stop_all_component(); static void kill_ptc(component component_reference); static void kill_all_component(); static void check_port_name(const char *port_name, const char *operation_name, const char *which_argument); public: static void connect_port( const COMPONENT& src_compref, const char *src_port, const COMPONENT& dst_compref, const char *dst_port); static void disconnect_port( const COMPONENT& src_compref, const char *src_port, const COMPONENT& dst_compref, const char *dst_port); static void map_port( const COMPONENT& src_compref, const char *src_port, const COMPONENT& dst_compref, const char *dst_port, Map_Params& params, boolean translation = FALSE); static void unmap_port( const COMPONENT& src_compref, const char *src_port, const COMPONENT& dst_compref, const char *dst_port, Map_Params& params, boolean translation = FALSE); static void begin_controlpart(const char *module_name); static void end_controlpart(); static void check_begin_testcase(boolean has_timer, double timer_value); static void begin_testcase( const char *par_module_name, const char *par_testcase_name, const char *mtc_comptype_module, const char *mtc_comptype_name, const char *system_comptype_module, const char *system_comptype_name, boolean has_timer, double timer_value); static verdicttype end_testcase(); static void log_verdict_statistics(); static void begin_action(); static void end_action(); static void setverdict(verdicttype new_value, const char* reason = ""); static void setverdict(const VERDICTTYPE& new_value, const char* reason = ""); static void set_error_verdict(); static verdicttype getverdict(); private: static void setverdict_internal(verdicttype new_value, const char* reason = ""); public: /** @name Manipulating external commands * @{ */ static void set_begin_controlpart_command(const char *new_command); static void set_end_controlpart_command(const char *new_command); static void set_begin_testcase_command(const char *new_command); static void set_end_testcase_command(const char *new_command); static void clear_external_commands(); /** @} */ private: static char *shell_escape(const char *command_str); static void execute_command(const char *command_name, const char *argument_string); public: static void process_create_mtc(); static void process_create_ptc(component component_reference, const char *component_type_module, const char *component_type_name, const char *system_type_module, const char *system_type_name, const char *par_component_name, boolean par_is_alive, const char *current_testcase_module, const char *current_testcase_name, timeval testcase_start_time); static void process_create_ack(component new_component); static void process_running(boolean result_value); static void process_alive(boolean result_value); static void process_done_ack(boolean done_status, verdicttype ptc_verdict, const char *return_type, int return_value_len, const void *return_value); static void process_killed_ack(boolean killed_status); static void process_ptc_verdict(Text_Buf& text_buf); static void process_kill(); static void process_kill_process(component component_reference); static void set_component_done(component component_reference, verdicttype ptc_verdict, const char *return_type, int return_value_len, const void *return_value); static void set_component_killed(component component_reference); static void cancel_component_done(component component_reference); private: static int get_component_status_table_index(component component_reference); static alt_status get_killed_status(component component_reference); static boolean in_component_status_table(component component_reference); static void clear_component_status_table(); static void initialize_component_process_tables(); static void add_component(component component_reference, pid_t process_id); static void remove_component(component_process_struct *comp); static component_process_struct *get_component_by_compref(component component_reference); static component_process_struct *get_component_by_pid(pid_t process_id); static void clear_component_process_tables(); static void successful_process_creation(); static void failed_process_creation(); public: static void wait_terminated_processes(); static void check_overload(); }; /** TTCN_TryBlock must be used only as a local variable of a TTCN-3 try{} block. It handles the value of TTCN_Runtime::in_ttcn_try_block using C++'s RAII feature */ class TTCN_TryBlock { boolean outmost_try; public: TTCN_TryBlock() { if (TTCN_Runtime::in_ttcn_try_block) { outmost_try = FALSE; } else { outmost_try = TRUE; TTCN_Runtime::in_ttcn_try_block = TRUE; } } ~TTCN_TryBlock() { if (outmost_try) { TTCN_Runtime::in_ttcn_try_block = FALSE; } } }; #endif