From 992ee5a596531b123ecf155e6af67afb35dfafeb Mon Sep 17 00:00:00 2001 From: Botond Baranyi <botond.baranyi@ericsson.com> Date: Tue, 8 May 2018 11:52:25 +0200 Subject: [PATCH] Implemented remote mapping in translation mode (bug 534266) Change-Id: I8c4e454d8ba843b983388ec8beaa134c5c9eb8cc Signed-off-by: Botond Baranyi <botond.baranyi@ericsson.com> --- compiler2/AST.cc | 30 ++++++- compiler2/Code.cc | 4 + compiler2/CodeGenHelper.cc | 1 + compiler2/CompType.cc | 31 +++++++ compiler2/ttcn3/Statement.cc | 47 +--------- compiler2/ttcn3/Statement.hh | 1 - compiler2/ttcn3/compiler.h | 1 + compiler2/ttcn3/port.c | 84 +++++++++++++----- core/Array.hh | 8 ++ core/Communication.cc | 30 ++++++- core/Module_list.cc | 22 +++++ core/Module_list.hh | 6 ++ core/Port.cc | 45 ++++++++-- core/Port.hh | 7 ++ core/Runtime.cc | 25 ++++++ core/Runtime.hh | 6 ++ mctr2/mctr/MainController.cc | 11 +-- mctr2/mctr/MainController.h | 5 +- regression_test/portTranslation/Makefile | 2 +- regression_test/portTranslation/P5.cc | 81 +++++++++++++++++ regression_test/portTranslation/P5.hh | 52 +++++++++++ regression_test/portTranslation/PT4.cc | 80 +++++++++++++++++ regression_test/portTranslation/PT4.hh | 47 ++++++++++ .../portTranslation/PortTranslation.ttcn | 88 +++++++++++++++++++ 24 files changed, 625 insertions(+), 89 deletions(-) create mode 100644 regression_test/portTranslation/P5.cc create mode 100644 regression_test/portTranslation/P5.hh create mode 100644 regression_test/portTranslation/PT4.cc create mode 100644 regression_test/portTranslation/PT4.hh diff --git a/compiler2/AST.cc b/compiler2/AST.cc index 29acfbfa3..caa95f4bd 100644 --- a/compiler2/AST.cc +++ b/compiler2/AST.cc @@ -1064,6 +1064,29 @@ namespace Common { output->functions.init_comp = NULL; has_init_comp = true; } else has_init_comp = false; + // init system port function + bool has_init_system_port; + if (output->functions.init_system_port != NULL) { + output->source.static_function_prototypes = + mputprintf(output->source.static_function_prototypes, + "%sboolean init_system_port(const char* component_type, const char* port_name);\n", + split_to_slices ? "extern " : "static "); + output->source.static_function_bodies = + mputprintf(output->source.static_function_bodies, + "%sboolean init_system_port(const char* component_type, const char* port_name)\n" + "{\n", split_to_slices ? "" : "static "); + output->source.static_function_bodies = + mputstr(output->source.static_function_bodies, output->functions.init_system_port); + output->source.static_function_bodies = + mputstr(output->source.static_function_bodies, "return FALSE;\n" + "}\n\n"); + Free(output->functions.init_system_port); + output->functions.init_system_port = NULL; + has_init_system_port = true; + } + else { + has_init_system_port = false; + } // start function bool has_start; if (output->functions.start) { @@ -1187,15 +1210,16 @@ namespace Common { } string extra_str = extra ? ( string('"') + extra + string('"') ) : string("NULL"); output->source.global_vars = mputprintf(output->source.global_vars, - ", %uU, %uU, %uU, %uU, %s, %luLU, %s, %s, %s, %s, %s, %s, %s, %s", + ", %uU, %uU, %uU, %uU, %s, %luLU, %s, %s, %s, %s, %s, %s, %s, %s, %s", suffix, release, patch, build, extra_str.c_str(), (unsigned long)num_xml_namespaces, ((num_xml_namespaces || (control_ns && control_ns_prefix)) ? "xml_namespaces" : "0"), has_post_init ? "post_init_module" : "NULL", has_set_param ? "set_module_param" : "NULL", - has_get_param ? "get_module_param" : "NULL", + has_get_param ? "get_module_param" : "NULL", has_log_param ? "log_module_param" : "NULL", has_init_comp ? "init_comp_type" : "NULL", + has_init_system_port ? "init_system_port" : "NULL", has_start ? "start_ptc_function" : "NULL", has_control ? "module_control_part" : "NULL"); } else { @@ -1210,6 +1234,8 @@ namespace Common { FATAL_ERROR("Module::generate_functions(): log_param function in ASN.1 module"); if (has_init_comp) FATAL_ERROR("Module::generate_functions(): init_comp function in ASN.1 module"); + if (has_init_system_port) + FATAL_ERROR("Module::generate_functions(): init_system_port function in ASN.1 module"); if (has_start) FATAL_ERROR("Module::generate_functions(): startable function in ASN.1 module"); if (has_control) diff --git a/compiler2/Code.cc b/compiler2/Code.cc index 740605829..5df657a95 100644 --- a/compiler2/Code.cc +++ b/compiler2/Code.cc @@ -54,6 +54,7 @@ namespace Common { output->functions.get_param = NULL; output->functions.log_param = NULL; output->functions.init_comp = NULL; + output->functions.init_system_port = NULL; output->functions.start = NULL; output->functions.control = NULL; output->intervals.pre_things_size = 0; @@ -136,6 +137,8 @@ namespace Common { mputstr(dest->functions.log_param, src->functions.log_param); dest->functions.init_comp = mputstr(dest->functions.init_comp, src->functions.init_comp); + dest->functions.init_system_port = + mputstr(dest->functions.init_system_port, src->functions.init_system_port); dest->functions.start = mputstr(dest->functions.start, src->functions.start); dest->functions.control = @@ -167,6 +170,7 @@ namespace Common { Free(output->functions.get_param); Free(output->functions.log_param); Free(output->functions.init_comp); + Free(output->functions.init_system_port); Free(output->functions.start); Free(output->functions.control); Free(output->intervals.methods); diff --git a/compiler2/CodeGenHelper.cc b/compiler2/CodeGenHelper.cc index 31c722fb7..0d27d4521 100644 --- a/compiler2/CodeGenHelper.cc +++ b/compiler2/CodeGenHelper.cc @@ -373,6 +373,7 @@ void CodeGenHelper::finalize_generation(Type* type) { transfer_value(dst.functions.get_param, src.functions.get_param); transfer_value(dst.functions.log_param, src.functions.log_param); transfer_value(dst.functions.init_comp, src.functions.init_comp); + transfer_value(dst.functions.init_system_port, src.functions.init_system_port); transfer_value(dst.functions.start, src.functions.start); transfer_value(dst.functions.control, src.functions.control); } diff --git a/compiler2/CompType.cc b/compiler2/CompType.cc index 6d425044f..65c003766 100644 --- a/compiler2/CompType.cc +++ b/compiler2/CompType.cc @@ -546,6 +546,37 @@ void ComponentTypeBody::generate_code(output_struct* target) target->functions.init_comp = mputstr(target->functions.init_comp, "return TRUE;\n" "} else "); + + // system port initializer function + bool first_port_found = false; + nof_defs = all_defs_m.size(); + for (size_t i = 0; i < nof_defs; i++) { + // go through all port definitions, including inherited ones + Ttcn::Definition* def = all_defs_m.get_nth_elem(i); + if (def->get_asstype() == Common::Assignment::A_PORT) { + if (!first_port_found) { + // only add a segment for this component if it has at least one port + first_port_found = true; + target->functions.init_system_port = mputprintf( + target->functions.init_system_port, + "%sif (!strcmp(component_type, \"%s\")) {\n", + target->functions.init_system_port == NULL ? "" : "else ", + comp_id->get_dispname().c_str()); + } + target->functions.init_system_port = mputprintf( + target->functions.init_system_port, + "if (!strcmp(port_name, \"%s\")) {\n" + "%s.safe_start();\n" + "return TRUE;\n" + "}\n", + def->get_id().get_dispname().c_str(), + def->get_genname_from_scope(my_type->get_my_scope()).c_str()); + } + } + if (first_port_found) { + target->functions.init_system_port = mputstr( + target->functions.init_system_port, "}\n"); + } } char *ComponentTypeBody::generate_code_comptype_name(char *str) diff --git a/compiler2/ttcn3/Statement.cc b/compiler2/ttcn3/Statement.cc index 3cd3fdb50..cb87d8ee4 100644 --- a/compiler2/ttcn3/Statement.cc +++ b/compiler2/ttcn3/Statement.cc @@ -1414,7 +1414,6 @@ namespace Ttcn { config_op.compref2=p_compref2; config_op.portref2=p_portref2; config_op.translate=false; - config_op.first_is_system = false; break; default: FATAL_ERROR("Statement::Statement()"); @@ -4959,9 +4958,6 @@ error: warning("Port type `%s' cannot send or receive from system port type `%s'.", pt2->get_typename().c_str(), pt1->get_typename().c_str()); } - if (config_op.translate) { - config_op.first_is_system = true; - } } else { // we have no idea which one is the system port bool first_is_mapped_to_second = !ptb1->is_legacy() && ptb1->is_translate(ptb2); @@ -4971,9 +4967,6 @@ error: error("The mapping between port types `%s' and `%s' is not consistent", pt1->get_typename().c_str(), pt2->get_typename().c_str()); } - if (config_op.translate) { - config_op.first_is_system = second_is_mapped_to_first; - } } if (!config_op.translate) { if (ptb1->is_internal()) { @@ -7624,10 +7617,8 @@ error: { expression_struct expr; Code::init_expr(&expr); - bool warning = false; if (config_op.translate == true) { if (!config_op.compref1->get_expr_governor(Type::EXPECTED_DYNAMIC_VALUE)) { - warning = true; if (strcmp(opname, "map") == 0) { config_op.compref1->warning( "Cannot determine the type of the component in the first parameter." @@ -7635,24 +7626,12 @@ error: } } if (!config_op.compref2->get_expr_governor(Type::EXPECTED_DYNAMIC_VALUE)) { - warning = true; if (strcmp(opname, "map") == 0) { config_op.compref2->warning( "Cannot determine the type of the component in the second parameter." "The port translation will not work."); } } - if (warning == false) { - Reference* portref = config_op.first_is_system ? - config_op.portref1 : config_op.portref2; - expr.expr = mputstr(expr.expr, "if (!("); - portref->generate_code_portref(&expr, my_sb); - expr.expr = mputstr(expr.expr, ".port_is_started())) {\n"); - portref->generate_code_portref(&expr, my_sb); - expr.expr = mputstr(expr.expr, ".activate_port(TRUE);\n"); - portref->generate_code_portref(&expr, my_sb); - expr.expr = mputstr(expr.expr, ".start();\n}\n"); - } } expr.expr = mputprintf(expr.expr, "TTCN_Runtime::%s_port(", opname); config_op.compref1->generate_code_expr(&expr); @@ -7680,32 +7659,10 @@ error: // a simple string shall be formed from the port name and array indices generate_code_portref(&expr, config_op.portref2); } - if (config_op.translate == true && warning == false) { - expr.expr = mputstr(expr.expr, ", TRUE"); - } - expr.expr = mputstr(expr.expr, ")"); if (config_op.translate == true) { - string funcname; - if (strcmp(opname, "map") == 0) { - funcname = "add_port"; - } else if (strcmp(opname, "unmap") == 0) { - funcname = "remove_port"; - } else { - //connect, disconnect are not supported - } - if (!funcname.empty() && warning == false) { - expr.expr = mputstr(expr.expr, ";\n"); - config_op.portref1->generate_code_portref(&expr, my_sb); - expr.expr = mputprintf(expr.expr, ".%s(&(", funcname.c_str()); - config_op.portref2->generate_code_portref(&expr, my_sb); - expr.expr = mputstr(expr.expr, "));\n"); - - config_op.portref2->generate_code_portref(&expr, my_sb); - expr.expr = mputprintf(expr.expr, ".%s(&(", funcname.c_str()); - config_op.portref1->generate_code_portref(&expr, my_sb); - expr.expr = mputstr(expr.expr, "))"); - } + expr.expr = mputstr(expr.expr, ", TRUE"); } + expr.expr = mputstr(expr.expr, ")"); return Code::merge_free_expr(str, &expr); } diff --git a/compiler2/ttcn3/Statement.hh b/compiler2/ttcn3/Statement.hh index e79e9de0f..90a0ccec0 100644 --- a/compiler2/ttcn3/Statement.hh +++ b/compiler2/ttcn3/Statement.hh @@ -348,7 +348,6 @@ namespace Ttcn { Value *compref2; Reference *portref2; bool translate; // true if a map statement enables translation mode - bool first_is_system; // true if the first operand is the system component (only used in translation mode) } config_op; ///< used by S_CONNECT, S_MAP, S_DISCONNECT, S_UNMAP struct { diff --git a/compiler2/ttcn3/compiler.h b/compiler2/ttcn3/compiler.h index 576a0bdee..78ed60abc 100644 --- a/compiler2/ttcn3/compiler.h +++ b/compiler2/ttcn3/compiler.h @@ -63,6 +63,7 @@ extern "C" { char *get_param; /**< Code for get_module_param() */ char *log_param; /**< Code for log_module_param() */ char *init_comp; /**< Code for init_comp_type() */ + char* init_system_port; /**< Code for init_system_port() */ char *start; /**< Code for start_ptc_function() */ char *control; /**< Code for module_control_part() */ } functions; diff --git a/compiler2/ttcn3/port.c b/compiler2/ttcn3/port.c index 194584412..1d6b9c24c 100644 --- a/compiler2/ttcn3/port.c +++ b/compiler2/ttcn3/port.c @@ -2136,24 +2136,35 @@ void defPortClass(const port_def* pdef, output_struct* output) if (pdef->port_type == USER && !pdef->legacy) { // add_port and remove_port is called after the map and unmap statements. + def = mputstr(def, "void add_port(PORT* p);\n"); + src = mputprintf(src, "void %s::add_port(PORT* p)\n{\n", class_name); for (i = 0; i < pdef->provider_msg_outlist.nElements; i++) { - def = mputprintf(def, "void add_port(%s* p);\n", pdef->provider_msg_outlist.elements[i].name); src = mputprintf(src, - "void %s::add_port(%s*p) {\n" + "%s* x_%i = dynamic_cast<%s*>(p);\n" + "if (x_%i != NULL) {\n" "n_%i++;\n" "p_%i = static_cast<%s**>(Realloc(p_%i, n_%i * sizeof(%s*)));\n" - "p_%i[n_%i-1] = p;\n" - "}\n\n", - class_name, pdef->provider_msg_outlist.elements[i].name, (int)i, + "p_%i[n_%i-1] = x_%i;\n" + "return;\n" + "}\n", + pdef->provider_msg_outlist.elements[i].name, (int)i, + pdef->provider_msg_outlist.elements[i].name, (int)i, (int)i, (int)i, pdef->provider_msg_outlist.elements[i].name, (int)i, (int)i, - pdef->provider_msg_outlist.elements[i].name, (int)i, (int)i); + pdef->provider_msg_outlist.elements[i].name, (int)i, (int)i, (int)i); + } + src = mputstr(src, + "TTCN_error(\"Internal error: Adding invalid port type.\");\n" + "}\n\n"); + + def = mputstr(def, "void remove_port(PORT* p);\n"); + src = mputprintf(src, "void %s::remove_port(PORT* p)\n{\n", class_name); - def = mputprintf(def, "void remove_port(%s* p);\n", pdef->provider_msg_outlist.elements[i].name); + for (i = 0; i < pdef->provider_msg_outlist.nElements; i++) { src = mputprintf(src, - "void %s::remove_port(%s* p) {\n" + "%s* x_%i = dynamic_cast<%s*>(p);\n" + "if (x_%i != NULL) {\n" "for (size_t i = 0; i < n_%i; i++) {\n" - "if (p_%i[i] == p) {\n" - "p_%i[i]->remove_port(static_cast<%s*>(this));\n" + "if (p_%i[i] == x_%i) {\n" "p_%i[i] = NULL;\n" "}\n" "}\n" @@ -2169,12 +2180,19 @@ void defPortClass(const port_def* pdef, output_struct* output) "Free(p_%i);\n" "p_%i = port_list;\n" "n_%i = size;\n" - "}\n\n", class_name, pdef->provider_msg_outlist.elements[i].name, (int)i, (int)i, - (int)i, pdef->name, (int)i, pdef->provider_msg_outlist.elements[i].name, (int)i, (int)i, + "return;\n" + "}\n", + pdef->provider_msg_outlist.elements[i].name, (int)i, + pdef->provider_msg_outlist.elements[i].name, (int)i, (int)i, (int)i, + (int)i, (int)i, pdef->provider_msg_outlist.elements[i].name, (int)i, (int)i, pdef->provider_msg_outlist.elements[i].name, pdef->provider_msg_outlist.elements[i].name, (int)i, (int)i, (int)i, (int)i); } + src = mputstr(src, + "TTCN_error(\"Internal error: Removing invalid port type.\");\n" + "}\n\n"); + // in_translation_mode returns true if one of the port type variables are not null def = mputstr(def, "boolean in_translation_mode() const;\n"); src = mputprintf(src, "boolean %s::in_translation_mode() const {\nreturn ", class_name); @@ -2211,22 +2229,35 @@ void defPortClass(const port_def* pdef, output_struct* output) if (pdef->n_mapper_name > 0) { def = mputstr(def, "public:\n"); // add_port and remove_port is called after the map and unmap statements. + def = mputstr(def, "void add_port(PORT* p);\n"); + src = mputprintf(src, "void %s::add_port(PORT* p)\n{\n", class_name); for (i = 0; i < pdef->n_mapper_name; i++) { - def = mputprintf(def, "void add_port(%s* p);\n", pdef->mapper_name[i]); src = mputprintf(src, - "void %s::add_port(%s*p) {\n" + "%s* x_%i = dynamic_cast<%s*>(p);\n" + "if (x_%i != NULL) {\n" "n_%i++;\n" "p_%i = static_cast<%s**>(Realloc(p_%i, n_%i * sizeof(%s*)));\n" - "p_%i[n_%i-1] = p;\n" - "}\n\n", class_name, pdef->mapper_name[i], (int)i, (int)i, - pdef->mapper_name[i], (int)i, (int)i, pdef->mapper_name[i], - (int)i, (int)i); + "p_%i[n_%i-1] = x_%i;\n" + "return;\n" + "}\n", + pdef->mapper_name[i], (int)i, + pdef->mapper_name[i], (int)i, (int)i, + (int)i, pdef->mapper_name[i], (int)i, (int)i, + pdef->mapper_name[i], (int)i, (int)i, (int)i); + } + src = mputstr(src, + "TTCN_error(\"Internal error: Adding invalid port type.\");\n" + "}\n\n"); + + def = mputstr(def, "void remove_port(PORT* p);\n"); + src = mputprintf(src, "void %s::remove_port(PORT* p)\n{\n", class_name); - def = mputprintf(def, "void remove_port(%s*);\n", pdef->mapper_name[i]); + for (i = 0; i < pdef->n_mapper_name; i++) { src = mputprintf(src, - "void %s::remove_port(%s* p) {\n" + "%s* x_%i = dynamic_cast<%s*>(p);\n" + "if (x_%i != NULL) {\n" "for (size_t i = 0; i < n_%i; i++) {\n" - "if (p_%i[i] == p) {\n" + "if (p_%i[i] == x_%i) {\n" "p_%i[i] = NULL;\n" "}\n" "}\n" @@ -2242,11 +2273,18 @@ void defPortClass(const port_def* pdef, output_struct* output) "Free(p_%i);\n" "p_%i = port_list;\n" "n_%i = size;\n" - "}\n\n", class_name, pdef->mapper_name[i], (int)i, - (int)i, (int)i, pdef->mapper_name[i], (int)i, (int)i, + "return;\n" + "}\n", + pdef->mapper_name[i], (int)i, pdef->mapper_name[i], (int)i, + (int)i, (int)i, (int)i, (int)i, pdef->mapper_name[i], (int)i, (int)i, pdef->mapper_name[i], pdef->mapper_name[i], (int)i, (int)i, (int)i, (int)i); } + + src = mputstr(src, + "TTCN_error(\"Internal error: Removing invalid port type.\");\n" + "}\n\n"); + def = mputstr(def, "private:\n"); // Resets all port type variables to NULL def = mputstr(def, "void reset_port_variables();\n"); diff --git a/core/Array.hh b/core/Array.hh index 4554cfad7..3178d604d 100644 --- a/core/Array.hh +++ b/core/Array.hh @@ -204,6 +204,14 @@ public: array_elements[v_index].activate_port(); } } + + // needed by the init_system_port function + void safe_start() + { + for (unsigned int v_index = 0; v_index < array_size; v_index++) { + array_elements[v_index].safe_start(); + } + } void log() const { diff --git a/core/Communication.cc b/core/Communication.cc index b8110bcc2..548ee2d93 100644 --- a/core/Communication.cc +++ b/core/Communication.cc @@ -1357,15 +1357,20 @@ void TTCN_Communication::process_create_ptc() "component reference %d.", component_reference); return; } - qualified_name component_type; + qualified_name component_type, system_type; incoming_buf.pull_qualified_name(component_type); + incoming_buf.pull_qualified_name(system_type); if (component_type.module_name == NULL || - component_type.definition_name == NULL) { + component_type.definition_name == NULL || + system_type.module_name == NULL || + system_type.definition_name == NULL) { incoming_buf.cut_message(); delete [] component_type.module_name; delete [] component_type.definition_name; + delete [] system_type.module_name; + delete [] system_type.definition_name; send_error("Message CREATE_PTC with component reference %d contains " - "an invalid component type.", component_reference); + "an invalid component type or system type.", component_reference); return; } char *component_name = incoming_buf.pull_string(); @@ -1377,12 +1382,15 @@ void TTCN_Communication::process_create_ptc() try { TTCN_Runtime::process_create_ptc(component_reference, component_type.module_name, component_type.definition_name, + system_type.module_name, system_type.definition_name, component_name, is_alive, current_testcase.module_name, current_testcase.definition_name); } catch (...) { // to prevent from memory leaks delete [] component_type.module_name; delete [] component_type.definition_name; + delete [] system_type.module_name; + delete [] system_type.definition_name; delete [] component_name; delete [] current_testcase.module_name; delete [] current_testcase.definition_name; @@ -1391,6 +1399,8 @@ void TTCN_Communication::process_create_ptc() delete [] component_type.module_name; delete [] component_type.definition_name; + delete [] system_type.module_name; + delete [] system_type.definition_name; delete [] component_name; delete [] current_testcase.module_name; delete [] current_testcase.definition_name; @@ -1759,6 +1769,13 @@ void TTCN_Communication::process_map() if (translation == TRUE) { PORT::map_port(local_port, system_port, TRUE); } + if (!TTCN_Runtime::is_single()) { + if (translation == FALSE) { + send_mapped(local_port, system_port, translation); + } else { + send_mapped(system_port, local_port, translation); + } + } } catch (...) { delete [] local_port; delete [] system_port; @@ -1798,6 +1815,13 @@ void TTCN_Communication::process_unmap() if (translation == TRUE) { PORT::unmap_port(local_port, system_port, TRUE); } + if (!TTCN_Runtime::is_single()) { + if (translation == FALSE) { + send_unmapped(local_port, system_port, translation); + } else { + send_unmapped(system_port, local_port, translation); + } + } } catch (...) { delete [] local_port; delete [] system_port; diff --git a/core/Module_list.cc b/core/Module_list.cc index c63f30373..a5b8483b9 100644 --- a/core/Module_list.cc +++ b/core/Module_list.cc @@ -155,6 +155,24 @@ void Module_List::initialize_component(const char *module_name, "module %s.", component_type, module_name); } +void Module_List::initialize_system_port(const char* module_name, + const char* component_type, const char* port_name) +{ + TTCN_Module* system_module = Module_List::lookup_module(module_name); + if (system_module == NULL) { + TTCN_error("Internal error: Module %s does not exist.", module_name); + } + if (system_module->initialize_system_port_func == NULL) { + TTCN_error("Internal error: Module %s does not have a system port " + "initializer function.", module_name); + } + if (!system_module->initialize_system_port_func(component_type, port_name)) { + TTCN_error("Internal error: Cannot find port %s in component type %s, or " + "component type %s in module %s.", port_name, component_type, + component_type, module_name); + } +} + void Module_List::set_param(Module_Param& param) { #ifndef TITAN_RUNTIME_2 @@ -786,6 +804,7 @@ TTCN_Module::TTCN_Module(const char *par_module_name, get_param_func_t par_get_param_func, log_param_func_t par_log_param_func, initialize_component_func_t par_initialize_component_func, + initialize_system_port_func_t par_initialize_system_port_func, start_func_t par_start_func, control_func_t par_control_func) : list_prev(NULL), list_next(NULL) @@ -810,6 +829,7 @@ TTCN_Module::TTCN_Module(const char *par_module_name, , get_param_func(par_get_param_func) , log_param_func(par_log_param_func) , initialize_component_func(par_initialize_component_func) +, initialize_system_port_func(par_initialize_system_port_func) , start_func(par_start_func) , control_func(par_control_func) , function_head(NULL) @@ -850,6 +870,7 @@ TTCN_Module::TTCN_Module(const char *par_module_name, , get_param_func(NULL) , log_param_func(NULL) , initialize_component_func(NULL) +, initialize_system_port_func(NULL) , start_func(NULL) , control_func(NULL) , function_head(NULL) @@ -888,6 +909,7 @@ TTCN_Module::TTCN_Module(const char *par_module_name, , set_param_func(NULL) , log_param_func(NULL) , initialize_component_func(NULL) +, initialize_system_port_func(NULL) , start_func(NULL) , control_func(NULL) , function_head(NULL) diff --git a/core/Module_list.hh b/core/Module_list.hh index 27146f5eb..b2dfa4705 100644 --- a/core/Module_list.hh +++ b/core/Module_list.hh @@ -56,6 +56,8 @@ public: static void initialize_component(const char *module_name, const char *component_type, boolean init_base_comps); + static void initialize_system_port(const char* module_name, + const char* component_type, const char* port_name); static void set_param(Module_Param& param); #ifdef TITAN_RUNTIME_2 @@ -122,6 +124,8 @@ public: typedef void (*log_param_func_t)(); typedef boolean (*initialize_component_func_t)(const char *component_type, boolean init_base_comps); + typedef boolean (*initialize_system_port_func_t)(const char* component_type, + const char* port_name); typedef boolean (*start_func_t)(const char *function_name, Text_Buf& function_arguments); typedef void (*control_func_t)(); @@ -152,6 +156,7 @@ private: get_param_func_t get_param_func; log_param_func_t log_param_func; initialize_component_func_t initialize_component_func; + initialize_system_port_func_t initialize_system_port_func; start_func_t start_func; control_func_t control_func; struct function_list_item; @@ -184,6 +189,7 @@ public: get_param_func_t par_get_param_func, log_param_func_t par_log_param_func, initialize_component_func_t par_initialize_component_func, + initialize_system_port_func_t par_initialize_system_port_func, start_func_t par_start_func, control_func_t par_control_func); TTCN_Module(const char *par_module_name, diff --git a/core/Port.cc b/core/Port.cc index 8cdd77ab9..b1f0f7a5e 100644 --- a/core/Port.cc +++ b/core/Port.cc @@ -503,6 +503,24 @@ boolean PORT::port_is_started() { return is_started; } +void PORT::safe_start() +{ + if (!is_started) { + activate_port(TRUE); + start(); + } +} + +void PORT::add_port(PORT* /*p*/) +{ + TTCN_error("Internal error: Calling PORT::add_port"); +} + +void PORT::remove_port(PORT* /*p*/) +{ + TTCN_error("Internal error: Calling PORT::remove_port"); +} + PORT* PORT::get_provider_port() { return NULL; } @@ -2493,6 +2511,9 @@ void PORT::terminate_local_connection(const char *src_port, void PORT::map_port(const char *component_port, const char *system_port, boolean translation) { + if (translation == TRUE) { + TTCN_Runtime::initialize_system_port(system_port); + } const char *port_name = translation == FALSE ? component_port : system_port; PORT *port_ptr = lookup_by_name(port_name, translation); if (port_ptr == NULL) TTCN_error("Map operation refers to " @@ -2505,17 +2526,21 @@ void PORT::map_port(const char *component_port, const char *system_port, boolean } else { port_ptr->map(component_port, translation); } - if (!TTCN_Runtime::is_single()) { - if (translation == FALSE) { - TTCN_Communication::send_mapped(component_port, system_port, translation); - } else { - TTCN_Communication::send_mapped(system_port, component_port, translation); + if (translation == TRUE) { + PORT* other_port_ptr = lookup_by_name(component_port, FALSE); + if (other_port_ptr == NULL) { + TTCN_error("Map operation refers to non-existent port %s.", port_name); } + other_port_ptr->add_port(port_ptr); + port_ptr->add_port(other_port_ptr); } } void PORT::unmap_port(const char *component_port, const char *system_port, boolean translation) { + if (translation == TRUE) { + TTCN_Runtime::initialize_system_port(system_port); + } const char *port_name = translation == FALSE ? component_port : system_port; PORT *port_ptr = lookup_by_name(port_name, translation); if (port_ptr == NULL) TTCN_error("Unmap operation refers to " @@ -2525,8 +2550,14 @@ void PORT::unmap_port(const char *component_port, const char *system_port, boole } else { port_ptr->unmap(component_port, translation); } - if (!TTCN_Runtime::is_single()) - TTCN_Communication::send_unmapped(component_port, system_port, translation); + if (translation == TRUE) { + PORT* other_port_ptr = lookup_by_name(component_port, FALSE); + if (other_port_ptr == NULL) { + TTCN_error("Unmap operation refers to non-existent port %s.", port_name); + } + other_port_ptr->remove_port(port_ptr); + port_ptr->remove_port(other_port_ptr); + } } boolean PORT::check_port_state(const CHARSTRING& type) const diff --git a/core/Port.hh b/core/Port.hh index 0d0d6a132..08578a1cc 100644 --- a/core/Port.hh +++ b/core/Port.hh @@ -138,6 +138,13 @@ public: boolean port_is_started(); + // activate and start a system port if it's not already started + // needed by the init_system_port function + void safe_start(); + + virtual void add_port(PORT* p); + virtual void remove_port(PORT* p); + // Returns the outer message port it is mapped to // when the port works in translation mode. // In the case of dual faced ports it returns the port object diff --git a/core/Runtime.cc b/core/Runtime.cc index 4f2f64596..744135032 100644 --- a/core/Runtime.cc +++ b/core/Runtime.cc @@ -74,6 +74,7 @@ TTCN_Runtime::executor_state_enum TTCN_Runtime::executor_state = UNDEFINED_STATE; qualified_name TTCN_Runtime::component_type = { NULL, NULL }; +qualified_name TTCN_Runtime::system_type = { NULL, NULL }; char *TTCN_Runtime::component_name = NULL; boolean TTCN_Runtime::is_alive = FALSE; @@ -204,6 +205,7 @@ void TTCN_Runtime::clear_qualified_name(qualified_name& q_name) void TTCN_Runtime::clean_up() { clear_qualified_name(component_type); + clear_qualified_name(system_type); Free(component_name); component_name = NULL; control_module_name = NULL; @@ -269,6 +271,20 @@ void TTCN_Runtime::set_component_type(const char *component_type_module, component_type.definition_name = mcopystr(component_type_name); } +void TTCN_Runtime::set_system_type(const char* system_type_module, + const char* system_type_name) +{ + if (system_type_module == NULL || system_type_module[0] == '\0' || + system_type_name == NULL || system_type_name[0] == '\0') { + TTCN_error("Internal error: TTCN_Runtime::set_system_type: " + "Trying to set an invalid system component type."); + } + + clear_qualified_name(system_type); + system_type.module_name = mcopystr(system_type_module); + system_type.definition_name = mcopystr(system_type_name); +} + void TTCN_Runtime::set_component_name(const char *new_component_name) { Free(component_name); @@ -626,6 +642,12 @@ int TTCN_Runtime::ptc_main() return ret_val; } +void TTCN_Runtime::initialize_system_port(const char* port_name) +{ + Module_List::initialize_system_port(system_type.module_name, + system_type.definition_name, port_name); +} + component TTCN_Runtime::create_component( const char *created_component_type_module, const char *created_component_type_name, const char *created_component_name, @@ -2042,6 +2064,7 @@ void TTCN_Runtime::begin_testcase( TIMER::save_control_timers(); TTCN_Default::save_control_defaults(); set_testcase_name(par_module_name, par_testcase_name); + set_system_type(system_comptype_module, system_comptype_name); char *command_arguments = mprintf("%s.%s", testcase_name.module_name, testcase_name.definition_name); execute_command(begin_testcase_command, command_arguments); @@ -2422,6 +2445,7 @@ void TTCN_Runtime::process_create_mtc() void TTCN_Runtime::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) { @@ -2468,6 +2492,7 @@ void TTCN_Runtime::process_create_ptc(component component_reference, TTCN_Communication::close_mc_connection(); self = component_reference; set_component_type(component_type_module, component_type_name); + set_system_type(system_type_module, system_type_name); set_component_name(par_component_name); is_alive = par_is_alive; set_testcase_name(current_testcase_module, current_testcase_name); diff --git a/core/Runtime.hh b/core/Runtime.hh index 490d544a9..7173b8012 100644 --- a/core/Runtime.hh +++ b/core/Runtime.hh @@ -62,6 +62,7 @@ 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; @@ -153,6 +154,8 @@ 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; } @@ -195,6 +198,8 @@ public: 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, @@ -306,6 +311,7 @@ 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); diff --git a/mctr2/mctr/MainController.cc b/mctr2/mctr/MainController.cc index a9c705610..3eaee3bdd 100644 --- a/mctr2/mctr/MainController.cc +++ b/mctr2/mctr/MainController.cc @@ -3232,13 +3232,14 @@ void MainController::send_create_mtc(host_struct *hc) void MainController::send_create_ptc(host_struct *hc, component component_reference, const qualified_name& component_type, - const char *component_name, boolean is_alive, - const qualified_name& current_testcase) + const qualified_name& system_type, const char *component_name, + boolean is_alive, const qualified_name& current_testcase) { Text_Buf text_buf; text_buf.push_int(MSG_CREATE_PTC); text_buf.push_int(component_reference); text_buf.push_qualified_name(component_type); + text_buf.push_qualified_name(system_type); text_buf.push_string(component_name); text_buf.push_int(is_alive ? 1 : 0); text_buf.push_qualified_name(current_testcase); @@ -3997,7 +3998,7 @@ void MainController::process_create_nak(host_struct *hc) tc->initial.location_str); if (new_host != NULL) { send_create_ptc(new_host, component_reference, tc->comp_type, - tc->comp_name, tc->is_alive, mtc->tc_fn_name); + system->comp_type, tc->comp_name, tc->is_alive, mtc->tc_fn_name); notify("PTC with component reference %d was relocated from host " "%s to %s because of overload: %s.", component_reference, hc->hostname, new_host->hostname, reason); @@ -4145,8 +4146,8 @@ void MainController::process_create_req(component_struct *tc) } component comp_ref = next_comp_ref++; - send_create_ptc(host, comp_ref, component_type, component_name, is_alive, - mtc->tc_fn_name); + send_create_ptc(host, comp_ref, component_type, system->comp_type, + component_name, is_alive, mtc->tc_fn_name); tc->tc_state = TC_CREATE; diff --git a/mctr2/mctr/MainController.h b/mctr2/mctr/MainController.h index 6d4384bb2..c67f13eec 100644 --- a/mctr2/mctr/MainController.h +++ b/mctr2/mctr/MainController.h @@ -491,8 +491,9 @@ private: static void send_exit_hc(host_struct *hc); static void send_create_mtc(host_struct *hc); static void send_create_ptc(host_struct *hc, component component_reference, - const qualified_name& component_type, const char *component_name, - boolean is_alive, const qualified_name& current_testcase); + const qualified_name& component_type, const qualified_name& system_type, + const char *component_name, boolean is_alive, + const qualified_name& current_testcase); static void send_kill_process(host_struct *hc, component component_reference); diff --git a/regression_test/portTranslation/Makefile b/regression_test/portTranslation/Makefile index f5dad0b4c..22e80bbcc 100644 --- a/regression_test/portTranslation/Makefile +++ b/regression_test/portTranslation/Makefile @@ -64,7 +64,7 @@ GENERATED_SOURCES += $(GENERATED_SOURCES2) endif # C/C++ Source & header files of Test Ports, external functions and # other modules: -USER_SOURCES = PT2.cc PT3.cc P1.cc P2.cc P3.cc P4.cc VP1.cc NVP1.cc P1Internal.cc P2Internal.cc P3Internal.cc VP1Internal.cc +USER_SOURCES = PT2.cc PT3.cc PT4.cc P1.cc P2.cc P3.cc P4.cc P5.cc VP1.cc NVP1.cc P1Internal.cc P2Internal.cc P3Internal.cc VP1Internal.cc USER_HEADERS = $(USER_SOURCES:.cc=.hh) # Object files of this project that are needed for the executable test suite: diff --git a/regression_test/portTranslation/P5.cc b/regression_test/portTranslation/P5.cc new file mode 100644 index 000000000..50f7e748a --- /dev/null +++ b/regression_test/portTranslation/P5.cc @@ -0,0 +1,81 @@ +/****************************************************************************** + * Copyright (c) 2000-2018 Ericsson Telecom AB + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Botond, Baranyi + * + ******************************************************************************/ + +#include "P5.hh" +#include "PortTranslation.hh" + +namespace PortTranslation { + +P5_PROVIDER::P5_PROVIDER(const char *par_port_name) + : PORT(par_port_name) +{ + +} + +P5_PROVIDER::~P5_PROVIDER() +{ + +} + +void P5_PROVIDER::set_parameter(const char * /*parameter_name*/, + const char * /*parameter_value*/) +{ + +} + +/*void P5_PROVIDER::Handle_Fd_Event(int fd, boolean is_readable, + boolean is_writable, boolean is_error) {}*/ + +void P5_PROVIDER::Handle_Fd_Event_Error(int /*fd*/) +{ + +} + +void P5_PROVIDER::Handle_Fd_Event_Writable(int /*fd*/) +{ + +} + +void P5_PROVIDER::Handle_Fd_Event_Readable(int /*fd*/) +{ + +} + +/*void P5_PROVIDER::Handle_Timeout(double time_since_last_call) {}*/ + +void P5_PROVIDER::user_map(const char * /*system_port*/) +{ + +} + +void P5_PROVIDER::user_unmap(const char * /*system_port*/) +{ + +} + +void P5_PROVIDER::user_start() +{ + +} + +void P5_PROVIDER::user_stop() +{ + +} + +void P5_PROVIDER::outgoing_send(const CHARSTRING& /*send_par*/) +{ + +} + +} /* end of namespace */ + diff --git a/regression_test/portTranslation/P5.hh b/regression_test/portTranslation/P5.hh new file mode 100644 index 000000000..828a9048b --- /dev/null +++ b/regression_test/portTranslation/P5.hh @@ -0,0 +1,52 @@ +/****************************************************************************** + * Copyright (c) 2000-2018 Ericsson Telecom AB + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Botond, Baranyi + * + ******************************************************************************/ + +#ifndef P5_HH +#define P5_HH + +#include <TTCN3.hh> + +// Note: Header file PortTranslation.hh must not be included into this file! +// (because it includes this file) +// Please add the declarations of message types manually. + +namespace PortTranslation { + +class P5_PROVIDER : public PORT { +public: + P5_PROVIDER(const char *par_port_name); + ~P5_PROVIDER(); + + void set_parameter(const char *parameter_name, + const char *parameter_value); + +private: + /* void Handle_Fd_Event(int fd, boolean is_readable, + boolean is_writable, boolean is_error); */ + void Handle_Fd_Event_Error(int fd); + void Handle_Fd_Event_Writable(int fd); + void Handle_Fd_Event_Readable(int fd); + /* void Handle_Timeout(double time_since_last_call); */ +protected: + void user_map(const char *system_port); + void user_unmap(const char *system_port); + + void user_start(); + void user_stop(); + + void outgoing_send(const CHARSTRING& send_par); + virtual void incoming_message(const INTEGER& incoming_par) = 0; +}; + +} /* end of namespace */ + +#endif diff --git a/regression_test/portTranslation/PT4.cc b/regression_test/portTranslation/PT4.cc new file mode 100644 index 000000000..556deab60 --- /dev/null +++ b/regression_test/portTranslation/PT4.cc @@ -0,0 +1,80 @@ +/****************************************************************************** + * Copyright (c) 2000-2018 Ericsson Telecom AB + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Botond, Baranyi + * + ******************************************************************************/ + +#include "PT4.hh" + +namespace PortTranslation { + +PT4::PT4(const char *par_port_name) + : PT4_BASE(par_port_name) +{ + +} + +PT4::~PT4() +{ + +} + +void PT4::set_parameter(const char * /*parameter_name*/, + const char * /*parameter_value*/) +{ + +} + +/*void PT4::Handle_Fd_Event(int fd, boolean is_readable, + boolean is_writable, boolean is_error) {}*/ + +void PT4::Handle_Fd_Event_Error(int /*fd*/) +{ + +} + +void PT4::Handle_Fd_Event_Writable(int /*fd*/) +{ + +} + +void PT4::Handle_Fd_Event_Readable(int /*fd*/) +{ + +} + +/*void PT4::Handle_Timeout(double time_since_last_call) {}*/ + +void PT4::user_map(const char * /*system_port*/) +{ + +} + +void PT4::user_unmap(const char * /*system_port*/) +{ + +} + +void PT4::user_start() +{ + +} + +void PT4::user_stop() +{ + +} + +void PT4::outgoing_send(const CHARSTRING& /*send_par*/) +{ + TTCN_Runtime::setverdict(FAIL, "The port mapping was not done in translation mode."); +} + +} /* end of namespace */ + diff --git a/regression_test/portTranslation/PT4.hh b/regression_test/portTranslation/PT4.hh new file mode 100644 index 000000000..4b5a5d05c --- /dev/null +++ b/regression_test/portTranslation/PT4.hh @@ -0,0 +1,47 @@ +/****************************************************************************** + * Copyright (c) 2000-2018 Ericsson Telecom AB + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Botond, Baranyi + * + ******************************************************************************/ + +#ifndef PT4_HH +#define PT4_HH + +#include "PortTranslation.hh" + +namespace PortTranslation { + +class PT4 : public PT4_BASE { +public: + PT4(const char *par_port_name = NULL); + ~PT4(); + + void set_parameter(const char *parameter_name, + const char *parameter_value); + +private: + /* void Handle_Fd_Event(int fd, boolean is_readable, + boolean is_writable, boolean is_error); */ + void Handle_Fd_Event_Error(int fd); + void Handle_Fd_Event_Writable(int fd); + void Handle_Fd_Event_Readable(int fd); + /* void Handle_Timeout(double time_since_last_call); */ +protected: + void user_map(const char *system_port); + void user_unmap(const char *system_port); + + void user_start(); + void user_stop(); + + void outgoing_send(const CHARSTRING& send_par); +}; + +} /* end of namespace */ + +#endif diff --git a/regression_test/portTranslation/PortTranslation.ttcn b/regression_test/portTranslation/PortTranslation.ttcn index f08d14dee..c820043a3 100644 --- a/regression_test/portTranslation/PortTranslation.ttcn +++ b/regression_test/portTranslation/PortTranslation.ttcn @@ -231,6 +231,26 @@ module PortTranslation { } with { extension "prototype(fast)"; } + + function int_to_int(in integer i, out integer j) port PT4 { + j := i; + port.setstate(0); + } with { + extension "prototype(fast)"; + } + + function char_to_char2(in charstring i, out charstring j) port PT4 { + j := i; + if (i == "abc") { + setverdict(pass); + } + else { + setverdict(fail, "Sending invalid message: ", i); + } + port.setstate(0); + } with { + extension "prototype(fast)"; + } /////////////////////////////////////////////////////////////////////////////// @@ -272,6 +292,13 @@ module PortTranslation { } with { extension "provider" } + + type port P5 message { + in integer + out charstring + } with { + extension "provider" + } type port PT2 message map to P1, P2 { in charstring from charstring with char_to_char() @@ -294,23 +321,32 @@ module PortTranslation { out integer, charstring out boolean to boolean with bool_to_bool_discard() } + + type port PT4 message map to P5 { + in integer from integer with int_to_int() + out charstring to charstring with char_to_char2() + } type component MyComp { port PT2 p; port PT3 p3; + port PT4 p4; // Extra port types to check if multiple map/unmaps does not make things go bad port PT2 p11; port PT2 p12; port PT2 p13; } + + type component MyComp2 {} type component System { port P1 p1 port P2 p2 port P3 p3 port P4 p4 + port P5 p5 // Extra port types to check if multiple map/unmaps does not make things go bad port P1 p11 @@ -831,6 +867,55 @@ module PortTranslation { } t.stop; } + + // Test function for remote mappings (is executed on the same PTC where the mappings take place) + function f_behavior_mapping_test(boolean mapping_required) runs on MyComp system System { + var boolean is_mapped := p4.checkstate("Mapped"); + if (is_mapped and mapping_required) { + // it's mapped and it should be + // the translation function will set the verdict + p4.send("abc"); + } + else if (not is_mapped and not mapping_required) { + // it's correctly not mapped + setverdict(pass); + } + else { + var charstring mapped_state; + if (is_mapped) { + mapped_state := "mapped"; + } + else { + mapped_state := "unmapped"; + } + setverdict(fail, "Invalid port state (port is ", mapped_state, ")."); + } + } + + // Remote mapping function + // Maps and unmaps ports (in translation mode) on a different PTC, and runs the test function. + function f_behavior_map_and_unmap() runs on MyComp2 system System { + var MyComp ct := MyComp.create alive; + map(ct:p4, system:p5); + ct.start(f_behavior_mapping_test(true)); + ct.done; + + unmap(ct:p4, system:p5); + ct.start(f_behavior_mapping_test(false)); + ct.done; + } + + // Tests remote mapping and unmapping (initiated from a PTC). + testcase tc_remote_mapping_from_ptc() runs on MyComp2 system System { + var MyComp2 ct := MyComp2.create; + ct.start(f_behavior_map_and_unmap()); + ct.done; + } + + // Tests remote mapping and unmapping (initiated from the MTC). + testcase tc_remote_mapping_from_mtc() runs on MyComp2 system System { + f_behavior_map_and_unmap(); + } control { execute(tc_send()) @@ -850,6 +935,9 @@ module PortTranslation { execute(tc_receive_fragmented()); execute(tc_receive_discarded_plus_port_ref()); + + execute(tc_remote_mapping_from_ptc()); + execute(tc_remote_mapping_from_mtc()); } } -- GitLab