diff --git a/compiler2/Type_codegen.cc b/compiler2/Type_codegen.cc index f9bb996a29e9ad680d2eab76ef47b3e8010a12a4..b57e19abeeaf9c925d092988e90493b8ba196e59 100644 --- a/compiler2/Type_codegen.cc +++ b/compiler2/Type_codegen.cc @@ -2232,24 +2232,26 @@ void Type::generate_code_done(output_struct *target) const string& dispname = get_typename(); const char *dispname_str = dispname.c_str(); // value redirect base class (interface) - target->header.class_decls = mputprintf(target->header.class_decls, - "class %s_Redirect_Interface;\n", genname_str); - target->header.class_defs = mputprintf(target->header.class_defs, - "class %s_Redirect_Interface {\n" - "public:\n" - "virtual void set_values(const %s&) = 0;\n" - "virtual ~%s_Redirect_Interface() { }\n" - "};\n\n", genname_str, genname_str, genname_str); + if (use_runtime_2) { + target->header.class_decls = mputprintf(target->header.class_decls, + "class %s_Redirect_Interface;\n", genname_str); + target->header.class_defs = mputprintf(target->header.class_defs, + "class %s_Redirect_Interface {\n" + "public:\n" + "virtual void set_values(const %s&) = 0;\n" + "virtual ~%s_Redirect_Interface() { }\n" + "};\n\n", genname_str, genname_str, genname_str); + } // the done function target->header.function_prototypes = mputprintf (target->header.function_prototypes, "extern alt_status done(const COMPONENT& component_reference, " - "const %s_template& value_template, %s_Redirect_Interface *value_redirect);\n", - genname_str, genname_str); + "const %s_template& value_template, %s%s *value_redirect);\n", + genname_str, genname_str, use_runtime_2 ? "_Redirect_Interface" : ""); target->source.function_bodies = mputprintf (target->source.function_bodies, "alt_status done(const COMPONENT& component_reference, " - "const %s_template& value_template, %s_Redirect_Interface *value_redirect)\n" + "const %s_template& value_template, %s%s *value_redirect)\n" "{\n" "if (!component_reference.is_bound()) " "TTCN_error(\"Performing a done operation on an unbound component " @@ -2263,9 +2265,18 @@ void Type::generate_code_done(output_struct *target) "%s return_value;\n" "return_value.decode_text(*text_buf);\n" "if (value_template.match(return_value)) {\n" - "if (value_redirect != NULL) {\n" - "value_redirect->set_values(return_value);\n" - "delete value_redirect;\n" + "if (value_redirect != NULL) {\n", genname_str, genname_str, + use_runtime_2 ? "_Redirect_Interface" : "", dispname_str, genname_str); + if (use_runtime_2) { + target->source.function_bodies = mputstr(target->source.function_bodies, + "value_redirect->set_values(return_value);\n" + "delete value_redirect;\n"); + } + else { + target->source.function_bodies = mputstr(target->source.function_bodies, + "*value_redirect = return_value;\n"); + } + target->source.function_bodies = mputprintf(target->source.function_bodies, "}\n" "TTCN_Logger::begin_event(TTCN_Logger::PARALLEL_PTC);\n" "TTCN_Logger::log_event_str(\"PTC with component reference \");\n" @@ -2289,8 +2300,7 @@ void Type::generate_code_done(output_struct *target) "}\n" "} else return ret_val;\n" "}\n\n", - genname_str, genname_str, dispname_str, genname_str, dispname_str, - dispname_str, omit_in_value_list ? ", TRUE" : ""); + dispname_str, dispname_str, omit_in_value_list ? ", TRUE" : ""); } bool Type::ispresent_anyvalue_embedded_field(Type* t, diff --git a/compiler2/ttcn3/Statement.cc b/compiler2/ttcn3/Statement.cc index 3a108084c5d57fd865bbde90fdc0d89bd77e3953..f696c989a4da69b8941e2b3b7abe87321ef149cf 100644 --- a/compiler2/ttcn3/Statement.cc +++ b/compiler2/ttcn3/Statement.cc @@ -8656,8 +8656,14 @@ error: if (return_type != NULL && is_out) { // the return type's value redirect object must be passed through this // class - constr_params_str = mprintf("%s_Redirect_Interface* return_redirect, ", - return_type->get_genname_value(return_type->get_my_scope()).c_str()); + if (use_runtime_2) { + constr_params_str = mprintf("%s_Redirect_Interface* return_redirect, ", + return_type->get_genname_value(return_type->get_my_scope()).c_str()); + } + else { + constr_params_str = mprintf("%s* return_redirect, ", + return_type->get_genname_value(scope).c_str()); + } base_constr_params_str = mcopystr("return_redirect"); } // store a pointer to the matched template, the decoding results from @@ -9138,9 +9144,27 @@ error: return ret_val; } + bool ValueRedirect::chk_RT1_restrictions() const + { + if (v.size() > 1) { + error("Redirecting multiple values is not supported in the Load Test " + "Runtime."); + return false; + } + if (v[0]->get_subrefs() != NULL) { + error("Redirecting parts of a value is not supported in the Load Test " + "Runtime."); + return false; + } + return true; + } + void ValueRedirect::chk_erroneous() { Error_Context cntxt(this, "In value redirect"); + if (!use_runtime_2 && !chk_RT1_restrictions()) { + return; + } for (size_t i = 0; i < v.size(); ++i) { Error_Context cntxt2(v[i], "In redirect #%d", (int)(i + 1)); v[i]->get_var_ref()->chk_variable_ref(); @@ -9153,6 +9177,9 @@ error: void ValueRedirect::chk(Type* p_type) { + if (!use_runtime_2 && !chk_RT1_restrictions()) { + return; + } bool invalid_type = p_type->get_typetype() == Type::T_ERROR; if (!invalid_type) { // initial check: redirects of fields require the value type to be a record @@ -9265,407 +9292,415 @@ error: TemplateInstance* matched_ti, string base_class_prefix) { - // a value redirect class is generated for this redirect in the expression's - // preamble and instantiated in the expression - - // the base class (interface) is type-specific, and is defined in the entity - // the new class instance is passed to (the port type for receive operations, - // the signature's reply redirect class for the return value, the signature - // exception template class for catch operations, and in the value type's - // module for done operations) - Scope* scope = v[0]->get_var_ref()->get_my_scope(); - string tmp_id = scope->get_scope_mod_gen()->get_temporary_id(); - expr->expr = mputprintf(expr->expr, "new Value_Redirect_%s(", tmp_id.c_str()); - - // go through the value redirect and gather the necessary data for the class - char* members_str = NULL; - char* constr_params_str = NULL; - char* constr_init_list_str = NULL; - char* set_values_str = NULL; - if (matched_ti != NULL && has_decoded_modifier()) { - // store a pointer to the matched template, the decoding results from - // decmatch templates might be reused to optimize decoded value redirects - expr->expr = mputprintf(expr->expr, "&(%s), ", matched_ti->get_last_gen_expr()); - members_str = mprintf("%s* ptr_matched_temp;\n", - value_type->get_genname_template(scope).c_str()); - constr_params_str = mputprintf(constr_params_str, "%s* par_matched_temp, ", - value_type->get_genname_template(scope).c_str()); - constr_init_list_str = mcopystr("ptr_matched_temp(par_matched_temp), "); - } - for (size_t i = 0; i < v.size(); ++i) { - if (i > 0) { - expr->expr = mputstr(expr->expr, ", "); - constr_params_str = mputstr(constr_params_str, ", "); - constr_init_list_str = mputstr(constr_init_list_str, ", "); - } - // pass the variable references to the new instance's constructor - expr->expr = mputstr(expr->expr, "&("); - v[i]->get_var_ref()->generate_code(expr); - expr->expr = mputc(expr->expr, ')'); - Type* redir_type = v[i]->get_subrefs() == NULL ? value_type : - value_type->get_field_type(v[i]->get_subrefs(), Type::EXPECTED_DYNAMIC_VALUE); - redir_type = redir_type->get_type_refd_last(); - Type* ref_type = v[i]->get_var_ref()->chk_variable_ref()->get_type_refd_last(); - Type* member_type = v[i]->is_decoded() ? v[i]->get_dec_type() : ref_type; - string type_str = member_type->get_genname_value(scope); - members_str = mputprintf(members_str, "%s* ptr_%d;\n", type_str.c_str(), (int)i); - constr_params_str = mputprintf(constr_params_str, "%s* par_%d", - type_str.c_str(), (int)i); - constr_init_list_str = mputprintf(constr_init_list_str, - "ptr_%d(par_%d)", (int)i, (int)i); - // generate the sub-references' code in a separate expression structure and - // insert it into the set_values function - expression_struct subrefs_expr; - Code::init_expr(&subrefs_expr); - const char* opt_suffix = ""; - if (v[i]->get_subrefs() != NULL) { - v[i]->get_subrefs()->generate_code(&subrefs_expr, value_type); - if (redir_type->get_ownertype() == Type::OT_COMP_FIELD) { - CompField* cf = (CompField*)redir_type->get_owner(); - if (cf->get_is_optional()) { - opt_suffix = "()"; + if (use_runtime_2) { + // a value redirect class is generated for this redirect in the expression's + // preamble and instantiated in the expression + + // the base class (interface) is type-specific, and is defined in the entity + // the new class instance is passed to (the port type for receive operations, + // the signature's reply redirect class for the return value, the signature + // exception template class for catch operations, and in the value type's + // module for done operations) + Scope* scope = v[0]->get_var_ref()->get_my_scope(); + string tmp_id = scope->get_scope_mod_gen()->get_temporary_id(); + expr->expr = mputprintf(expr->expr, "new Value_Redirect_%s(", tmp_id.c_str()); + + // go through the value redirect and gather the necessary data for the class + char* members_str = NULL; + char* constr_params_str = NULL; + char* constr_init_list_str = NULL; + char* set_values_str = NULL; + if (matched_ti != NULL && has_decoded_modifier()) { + // store a pointer to the matched template, the decoding results from + // decmatch templates might be reused to optimize decoded value redirects + expr->expr = mputprintf(expr->expr, "&(%s), ", matched_ti->get_last_gen_expr()); + members_str = mprintf("%s* ptr_matched_temp;\n", + value_type->get_genname_template(scope).c_str()); + constr_params_str = mputprintf(constr_params_str, "%s* par_matched_temp, ", + value_type->get_genname_template(scope).c_str()); + constr_init_list_str = mcopystr("ptr_matched_temp(par_matched_temp), "); + } + for (size_t i = 0; i < v.size(); ++i) { + if (i > 0) { + expr->expr = mputstr(expr->expr, ", "); + constr_params_str = mputstr(constr_params_str, ", "); + constr_init_list_str = mputstr(constr_init_list_str, ", "); + } + // pass the variable references to the new instance's constructor + expr->expr = mputstr(expr->expr, "&("); + v[i]->get_var_ref()->generate_code(expr); + expr->expr = mputc(expr->expr, ')'); + Type* redir_type = v[i]->get_subrefs() == NULL ? value_type : + value_type->get_field_type(v[i]->get_subrefs(), Type::EXPECTED_DYNAMIC_VALUE); + redir_type = redir_type->get_type_refd_last(); + Type* ref_type = v[i]->get_var_ref()->chk_variable_ref()->get_type_refd_last(); + Type* member_type = v[i]->is_decoded() ? v[i]->get_dec_type() : ref_type; + string type_str = member_type->get_genname_value(scope); + members_str = mputprintf(members_str, "%s* ptr_%d;\n", type_str.c_str(), (int)i); + constr_params_str = mputprintf(constr_params_str, "%s* par_%d", + type_str.c_str(), (int)i); + constr_init_list_str = mputprintf(constr_init_list_str, + "ptr_%d(par_%d)", (int)i, (int)i); + // generate the sub-references' code in a separate expression structure and + // insert it into the set_values function + expression_struct subrefs_expr; + Code::init_expr(&subrefs_expr); + const char* opt_suffix = ""; + if (v[i]->get_subrefs() != NULL) { + v[i]->get_subrefs()->generate_code(&subrefs_expr, value_type); + if (redir_type->get_ownertype() == Type::OT_COMP_FIELD) { + CompField* cf = (CompField*)redir_type->get_owner(); + if (cf->get_is_optional()) { + opt_suffix = "()"; + } } } - } - if (subrefs_expr.preamble != NULL) { - set_values_str = mputstr(set_values_str, subrefs_expr.preamble); - } - const char* subrefs_str = (subrefs_expr.expr != NULL) ? subrefs_expr.expr : ""; - if (v[i]->is_decoded()) { - // set the silent parameter to 'true', so no errors are displayed - Template* matched_temp = matched_ti != NULL ? - matched_ti->get_Template()->get_refd_sub_template(v[i]->get_subrefs(), - false, NULL, true) : NULL; - if (matched_temp != NULL) { - matched_temp = matched_temp->get_template_refd_last(); + if (subrefs_expr.preamble != NULL) { + set_values_str = mputstr(set_values_str, subrefs_expr.preamble); } - bool use_decmatch_result = matched_temp != NULL && - matched_temp->get_templatetype() == Template::DECODE_MATCH; - bool needs_decode = true; - expression_struct redir_coding_expr; - Code::init_expr(&redir_coding_expr); - if (redir_type->get_type_refd_last()->get_typetype_ttcn3() == Type::T_USTR) { - if (v[i]->get_str_enc() == NULL || !v[i]->get_str_enc()->is_unfoldable()) { - const char* redir_coding_str; - if (v[i]->get_str_enc() == NULL || - v[i]->get_str_enc()->get_val_str() == "UTF-8") { - redir_coding_str = "UTF_8"; - } - else if (v[i]->get_str_enc()->get_val_str() == "UTF-16" || - v[i]->get_str_enc()->get_val_str() == "UTF-16BE") { - redir_coding_str = "UTF16BE"; - } - else if (v[i]->get_str_enc()->get_val_str() == "UTF-16LE") { - redir_coding_str = "UTF16LE"; - } - else if (v[i]->get_str_enc()->get_val_str() == "UTF-32LE") { - redir_coding_str = "UTF32LE"; + const char* subrefs_str = (subrefs_expr.expr != NULL) ? subrefs_expr.expr : ""; + if (v[i]->is_decoded()) { + // set the silent parameter to 'true', so no errors are displayed + Template* matched_temp = matched_ti != NULL ? + matched_ti->get_Template()->get_refd_sub_template(v[i]->get_subrefs(), + false, NULL, true) : NULL; + if (matched_temp != NULL) { + matched_temp = matched_temp->get_template_refd_last(); + } + bool use_decmatch_result = matched_temp != NULL && + matched_temp->get_templatetype() == Template::DECODE_MATCH; + bool needs_decode = true; + expression_struct redir_coding_expr; + Code::init_expr(&redir_coding_expr); + if (redir_type->get_type_refd_last()->get_typetype_ttcn3() == Type::T_USTR) { + if (v[i]->get_str_enc() == NULL || !v[i]->get_str_enc()->is_unfoldable()) { + const char* redir_coding_str; + if (v[i]->get_str_enc() == NULL || + v[i]->get_str_enc()->get_val_str() == "UTF-8") { + redir_coding_str = "UTF_8"; + } + else if (v[i]->get_str_enc()->get_val_str() == "UTF-16" || + v[i]->get_str_enc()->get_val_str() == "UTF-16BE") { + redir_coding_str = "UTF16BE"; + } + else if (v[i]->get_str_enc()->get_val_str() == "UTF-16LE") { + redir_coding_str = "UTF16LE"; + } + else if (v[i]->get_str_enc()->get_val_str() == "UTF-32LE") { + redir_coding_str = "UTF32LE"; + } + else { + redir_coding_str = "UTF32BE"; + } + redir_coding_expr.expr = mprintf("CharCoding::%s", redir_coding_str); } else { - redir_coding_str = "UTF32BE"; + redir_coding_expr.preamble = mprintf( + "CharCoding::CharCodingType coding = UNIVERSAL_CHARSTRING::" + "get_character_coding(enc_fmt_%d, \"decoded parameter redirect\");\n", + (int)i); + redir_coding_expr.expr = mcopystr("coding"); } - redir_coding_expr.expr = mprintf("CharCoding::%s", redir_coding_str); - } - else { - redir_coding_expr.preamble = mprintf( - "CharCoding::CharCodingType coding = UNIVERSAL_CHARSTRING::" - "get_character_coding(enc_fmt_%d, \"decoded parameter redirect\");\n", - (int)i); - redir_coding_expr.expr = mcopystr("coding"); } - } - if (use_decmatch_result) { - // if the redirected value was matched using a decmatch template, - // then the value redirect class should use the decoding result - // from the template instead of decoding the value again - needs_decode = false; - Type* decmatch_type = matched_temp->get_decode_target()->get_expr_governor( - Type::EXPECTED_TEMPLATE)->get_type_refd_last(); - if (v[i]->get_dec_type() != decmatch_type) { - // the decmatch template and this value redirect decode two - // different types, so just decode the value - needs_decode = true; - use_decmatch_result = false; - } - else if (redir_type->get_type_refd_last()->get_typetype_ttcn3() == - Type::T_USTR) { - // for universal charstrings the situation could be trickier - // compare the string encodings - bool different_ustr_encodings = false; - bool unknown_ustr_encodings = false; - if (v[i]->get_str_enc() == NULL) { - if (matched_temp->get_string_encoding() != NULL) { - if (matched_temp->get_string_encoding()->is_unfoldable()) { - unknown_ustr_encodings = true; + if (use_decmatch_result) { + // if the redirected value was matched using a decmatch template, + // then the value redirect class should use the decoding result + // from the template instead of decoding the value again + needs_decode = false; + Type* decmatch_type = matched_temp->get_decode_target()->get_expr_governor( + Type::EXPECTED_TEMPLATE)->get_type_refd_last(); + if (v[i]->get_dec_type() != decmatch_type) { + // the decmatch template and this value redirect decode two + // different types, so just decode the value + needs_decode = true; + use_decmatch_result = false; + } + else if (redir_type->get_type_refd_last()->get_typetype_ttcn3() == + Type::T_USTR) { + // for universal charstrings the situation could be trickier + // compare the string encodings + bool different_ustr_encodings = false; + bool unknown_ustr_encodings = false; + if (v[i]->get_str_enc() == NULL) { + if (matched_temp->get_string_encoding() != NULL) { + if (matched_temp->get_string_encoding()->is_unfoldable()) { + unknown_ustr_encodings = true; + } + else if (matched_temp->get_string_encoding()->get_val_str() != "UTF-8") { + different_ustr_encodings = true; + } } - else if (matched_temp->get_string_encoding()->get_val_str() != "UTF-8") { + } + else if (v[i]->get_str_enc()->is_unfoldable()) { + unknown_ustr_encodings = true; + } + else if (matched_temp->get_string_encoding() == NULL) { + if (v[i]->get_str_enc()->get_val_str() != "UTF-8") { different_ustr_encodings = true; } } - } - else if (v[i]->get_str_enc()->is_unfoldable()) { - unknown_ustr_encodings = true; - } - else if (matched_temp->get_string_encoding() == NULL) { - if (v[i]->get_str_enc()->get_val_str() != "UTF-8") { + else if (matched_temp->get_string_encoding()->is_unfoldable()) { + unknown_ustr_encodings = true; + } + else if (v[i]->get_str_enc()->get_val_str() != + matched_temp->get_string_encoding()->get_val_str()) { different_ustr_encodings = true; } + if (unknown_ustr_encodings) { + // the decision of whether to use the decmatch result or to decode + // the value is made at runtime + needs_decode = true; + set_values_str = mputprintf(set_values_str, + "%sif (%s == (*ptr_matched_temp)%s.get_decmatch_str_enc()) {\n", + redir_coding_expr.preamble != NULL ? redir_coding_expr.preamble : "", + redir_coding_expr.expr, subrefs_str); + } + else if (different_ustr_encodings) { + // if the encodings are different, then ignore the decmatch result + // and just generate the decoding code as usual + needs_decode = true; + use_decmatch_result = false; + } } - else if (matched_temp->get_string_encoding()->is_unfoldable()) { - unknown_ustr_encodings = true; - } - else if (v[i]->get_str_enc()->get_val_str() != - matched_temp->get_string_encoding()->get_val_str()) { - different_ustr_encodings = true; + } + else { + // it might still be a decmatch template if it's not known at compile-time + bool unfoldable = matched_temp == NULL; + if (!unfoldable) { + switch (matched_temp->get_templatetype()) { + case Template::ANY_VALUE: + case Template::ANY_OR_OMIT: + case Template::BSTR_PATTERN: + case Template::CSTR_PATTERN: + case Template::HSTR_PATTERN: + case Template::OSTR_PATTERN: + case Template::USTR_PATTERN: + case Template::COMPLEMENTED_LIST: + case Template::VALUE_LIST: + case Template::VALUE_RANGE: + case Template::OMIT_VALUE: + // it's known at compile-time, and not a decmatch template + break; + default: + // needs runtime check + unfoldable = true; + break; + } } - if (unknown_ustr_encodings) { - // the decision of whether to use the decmatch result or to decode - // the value is made at runtime - needs_decode = true; + if (unfoldable && matched_ti != NULL) { + // the decmatch-check must be done at runtime + use_decmatch_result = true; + if (redir_coding_expr.preamble != NULL) { + set_values_str = mputstr(set_values_str, redir_coding_expr.preamble); + } + // before we can check whether the template at the end of the + // subreferences is a decmatch template, we must make sure that + // every prior subreference points to a specific value template + // (otherwise accessing the template at the end will result in a DTE) + set_values_str = mputstr(set_values_str, + "if (ptr_matched_temp->get_selection() == SPECIFIC_VALUE && "); + char* current_ref = mcopystr("(*ptr_matched_temp)"); + size_t len = strlen(subrefs_str); + size_t start = 0; + // go through the already generated subreference string, append + // one reference at a time, and check if the referenced template + // is a specific value + for (size_t j = 1; j < len; ++j) { + if (subrefs_str[j] == '.' || subrefs_str[j] == '[') { + current_ref = mputstrn(current_ref, subrefs_str + start, j - start); + set_values_str = mputprintf(set_values_str, + "%s.get_selection() == SPECIFIC_VALUE && ", current_ref); + start = j; + } + } + Free(current_ref); set_values_str = mputprintf(set_values_str, - "%sif (%s == (*ptr_matched_temp)%s.get_decmatch_str_enc()) {\n", - redir_coding_expr.preamble != NULL ? redir_coding_expr.preamble : "", - redir_coding_expr.expr, subrefs_str); - } - else if (different_ustr_encodings) { - // if the encodings are different, then ignore the decmatch result - // and just generate the decoding code as usual - needs_decode = true; - use_decmatch_result = false; + "(*ptr_matched_temp)%s.get_selection() == DECODE_MATCH && " + // the type the value was decoded to in the template must be the same + // as the type this value redirect would decode the redirected value to + // (this is checked by comparing the addresses of the type descriptors) + "&%s_descr_ == (*ptr_matched_temp)%s.get_decmatch_type_descr()", + subrefs_str, + v[i]->get_dec_type()->get_genname_typedescriptor(scope).c_str(), + subrefs_str); + if (redir_coding_expr.expr != NULL) { + set_values_str = mputprintf(set_values_str, + " && %s == (*ptr_matched_temp)%s.get_decmatch_str_enc()", + redir_coding_expr.expr, subrefs_str); + } + set_values_str = mputstr(set_values_str, ") {\n"); } } - } - else { - // it might still be a decmatch template if it's not known at compile-time - bool unfoldable = matched_temp == NULL; - if (!unfoldable) { - switch (matched_temp->get_templatetype()) { - case Template::ANY_VALUE: - case Template::ANY_OR_OMIT: - case Template::BSTR_PATTERN: - case Template::CSTR_PATTERN: - case Template::HSTR_PATTERN: - case Template::OSTR_PATTERN: - case Template::USTR_PATTERN: - case Template::COMPLEMENTED_LIST: - case Template::VALUE_LIST: - case Template::VALUE_RANGE: - case Template::OMIT_VALUE: - // it's known at compile-time, and not a decmatch template - break; - default: - // needs runtime check - unfoldable = true; - break; - } + Code::free_expr(&redir_coding_expr); + if (use_decmatch_result) { + set_values_str = mputprintf(set_values_str, + "*ptr_%d = *((%s*)((*ptr_matched_temp)%s.get_decmatch_dec_res()));\n", + (int)i, type_str.c_str(), subrefs_str); } - if (unfoldable && matched_ti != NULL) { - // the decmatch-check must be done at runtime - use_decmatch_result = true; - if (redir_coding_expr.preamble != NULL) { - set_values_str = mputstr(set_values_str, redir_coding_expr.preamble); + if (needs_decode) { + if (use_decmatch_result) { + set_values_str = mputstr(set_values_str, "}\nelse {\n"); } - // before we can check whether the template at the end of the - // subreferences is a decmatch template, we must make sure that - // every prior subreference points to a specific value template - // (otherwise accessing the template at the end will result in a DTE) - set_values_str = mputstr(set_values_str, - "if (ptr_matched_temp->get_selection() == SPECIFIC_VALUE && "); - char* current_ref = mcopystr("(*ptr_matched_temp)"); - size_t len = strlen(subrefs_str); - size_t start = 0; - // go through the already generated subreference string, append - // one reference at a time, and check if the referenced template - // is a specific value - for (size_t j = 1; j < len; ++j) { - if (subrefs_str[j] == '.' || subrefs_str[j] == '[') { - current_ref = mputstrn(current_ref, subrefs_str + start, j - start); + switch (redir_type->get_type_refd_last()->get_typetype_ttcn3()) { + case Type::T_OSTR: + case Type::T_CSTR: + set_values_str = mputprintf(set_values_str, + "TTCN_Buffer buff_%d(par%s%s);\n", (int)i, subrefs_str, opt_suffix); + break; + case Type::T_BSTR: + set_values_str = mputprintf(set_values_str, + "OCTETSTRING os(bit2oct(par%s%s));\n" + "TTCN_Buffer buff_%d(os);\n", subrefs_str, opt_suffix, (int)i); + break; + case Type::T_HSTR: + set_values_str = mputprintf(set_values_str, + "OCTETSTRING os(hex2oct(par%s%s));\n" + "TTCN_Buffer buff_%d(os);\n", subrefs_str, opt_suffix, (int)i); + break; + case Type::T_USTR: + set_values_str = mputprintf(set_values_str, "TTCN_Buffer buff_%d;\n", + (int)i); + if (v[i]->get_str_enc() == NULL || !v[i]->get_str_enc()->is_unfoldable()) { + // if the encoding format is missing or is known at compile-time, then + // use the appropriate string encoding function + string str_enc = (v[i]->get_str_enc() != NULL) ? + v[i]->get_str_enc()->get_val_str() : string("UTF-8"); + if (str_enc == "UTF-8") { + set_values_str = mputprintf(set_values_str, + "par%s%s.encode_utf8(buff_%d, false);\n", subrefs_str, opt_suffix, (int)i); + } + else if (str_enc == "UTF-16" || str_enc == "UTF-16LE" || + str_enc == "UTF-16BE") { + set_values_str = mputprintf(set_values_str, + "par%s%s.encode_utf16(buff_%d, CharCoding::UTF16%s);\n", subrefs_str, + opt_suffix, (int)i, (str_enc == "UTF-16LE") ? "LE" : "BE"); + } + else if (str_enc == "UTF-32" || str_enc == "UTF-32LE" || + str_enc == "UTF-32BE") { + set_values_str = mputprintf(set_values_str, + "par%s%s.encode_utf32(buff_%d, CharCoding::UTF32%s);\n", subrefs_str, + opt_suffix, (int)i, (str_enc == "UTF-32LE") ? "LE" : "BE"); + } + } + else { + // the encoding format is not known at compile-time, so an extra + // member and constructor parameter is needed to store it + expr->expr = mputstr(expr->expr, ", "); + v[i]->get_str_enc()->generate_code_expr(expr); + members_str = mputprintf(members_str, "CHARSTRING enc_fmt_%d;\n", + (int)i); + constr_params_str = mputprintf(constr_params_str, + ", CHARSTRING par_fmt_%d", (int)i); + constr_init_list_str = mputprintf(constr_init_list_str, + ", enc_fmt_%d(par_fmt_%d)", (int)i, (int)i); + if (!use_decmatch_result) { + // if the decmatch result code is generated too, then this variable + // was already generated before the main 'if' + set_values_str = mputprintf(set_values_str, + "CharCoding::CharCodingType coding = UNIVERSAL_CHARSTRING::" + "get_character_coding(enc_fmt_%d, \"decoded value redirect\");\n", + (int)i); + } set_values_str = mputprintf(set_values_str, - "%s.get_selection() == SPECIFIC_VALUE && ", current_ref); - start = j; + "switch (coding) {\n" + "case CharCoding::UTF_8:\n" + "par%s%s.encode_utf8(buff_%d, false);\n" + "break;\n" + "case CharCoding::UTF16:\n" + "case CharCoding::UTF16LE:\n" + "case CharCoding::UTF16BE:\n" + "par%s%s.encode_utf16(buff_%d, coding);\n" + "break;\n" + "case CharCoding::UTF32:\n" + "case CharCoding::UTF32LE:\n" + "case CharCoding::UTF32BE:\n" + "par%s%s.encode_utf32(buff_%d, coding);\n" + "break;\n" + "default:\n" + "break;\n" + "}\n", subrefs_str, opt_suffix, (int)i, subrefs_str, opt_suffix, + (int)i, subrefs_str, opt_suffix, (int)i); } + break; + default: + FATAL_ERROR("ValueRedirect::generate_code"); } - Free(current_ref); set_values_str = mputprintf(set_values_str, - "(*ptr_matched_temp)%s.get_selection() == DECODE_MATCH && " - // the type the value was decoded to in the template must be the same - // as the type this value redirect would decode the redirected value to - // (this is checked by comparing the addresses of the type descriptors) - "&%s_descr_ == (*ptr_matched_temp)%s.get_decmatch_type_descr()", - subrefs_str, - v[i]->get_dec_type()->get_genname_typedescriptor(scope).c_str(), - subrefs_str); - if (redir_coding_expr.expr != NULL) { - set_values_str = mputprintf(set_values_str, - " && %s == (*ptr_matched_temp)%s.get_decmatch_str_enc()", - redir_coding_expr.expr, subrefs_str); + "ptr_%d->decode(%s_descr_, buff_%d, TTCN_EncDec::CT_%s);\n" + "if (buff_%d.get_read_len() != 0) {\n" + "TTCN_error(\"Value redirect #%d failed, because the buffer was " + "not empty after decoding. Remaining octets: %%d.\", " + "(int)buff_%d.get_read_len());\n" + "}\n", + (int)i, member_type->get_genname_typedescriptor(scope).c_str(), (int)i, + member_type->get_coding(false).c_str(), (int)i, (int)(i + 1), (int)i); + if (use_decmatch_result) { + set_values_str = mputstr(set_values_str, "}\n"); } - set_values_str = mputstr(set_values_str, ") {\n"); } } - Code::free_expr(&redir_coding_expr); - if (use_decmatch_result) { - set_values_str = mputprintf(set_values_str, - "*ptr_%d = *((%s*)((*ptr_matched_temp)%s.get_decmatch_dec_res()));\n", - (int)i, type_str.c_str(), subrefs_str); - } - if (needs_decode) { - if (use_decmatch_result) { - set_values_str = mputstr(set_values_str, "}\nelse {\n"); - } - switch (redir_type->get_type_refd_last()->get_typetype_ttcn3()) { - case Type::T_OSTR: - case Type::T_CSTR: - set_values_str = mputprintf(set_values_str, - "TTCN_Buffer buff_%d(par%s%s);\n", (int)i, subrefs_str, opt_suffix); - break; - case Type::T_BSTR: - set_values_str = mputprintf(set_values_str, - "OCTETSTRING os(bit2oct(par%s%s));\n" - "TTCN_Buffer buff_%d(os);\n", subrefs_str, opt_suffix, (int)i); - break; - case Type::T_HSTR: + else { + // if the variable reference and the received value (or its specified field) + // are not of the same type, then a type conversion is needed (RT2 only) + if (use_runtime_2 && !ref_type->is_identical(redir_type)) { + Common::Module* mod = scope->get_scope_mod(); + mod->add_type_conv(new TypeConv(redir_type, ref_type, false)); set_values_str = mputprintf(set_values_str, - "OCTETSTRING os(hex2oct(par%s%s));\n" - "TTCN_Buffer buff_%d(os);\n", subrefs_str, opt_suffix, (int)i); - break; - case Type::T_USTR: - set_values_str = mputprintf(set_values_str, "TTCN_Buffer buff_%d;\n", - (int)i); - if (v[i]->get_str_enc() == NULL || !v[i]->get_str_enc()->is_unfoldable()) { - // if the encoding format is missing or is known at compile-time, then - // use the appropriate string encoding function - string str_enc = (v[i]->get_str_enc() != NULL) ? - v[i]->get_str_enc()->get_val_str() : string("UTF-8"); - if (str_enc == "UTF-8") { - set_values_str = mputprintf(set_values_str, - "par%s%s.encode_utf8(buff_%d, false);\n", subrefs_str, opt_suffix, (int)i); - } - else if (str_enc == "UTF-16" || str_enc == "UTF-16LE" || - str_enc == "UTF-16BE") { - set_values_str = mputprintf(set_values_str, - "par%s%s.encode_utf16(buff_%d, CharCoding::UTF16%s);\n", subrefs_str, - opt_suffix, (int)i, (str_enc == "UTF-16LE") ? "LE" : "BE"); - } - else if (str_enc == "UTF-32" || str_enc == "UTF-32LE" || - str_enc == "UTF-32BE") { - set_values_str = mputprintf(set_values_str, - "par%s%s.encode_utf32(buff_%d, CharCoding::UTF32%s);\n", subrefs_str, - opt_suffix, (int)i, (str_enc == "UTF-32LE") ? "LE" : "BE"); - } - } - else { - // the encoding format is not known at compile-time, so an extra - // member and constructor parameter is needed to store it - expr->expr = mputstr(expr->expr, ", "); - v[i]->get_str_enc()->generate_code_expr(expr); - members_str = mputprintf(members_str, "CHARSTRING enc_fmt_%d;\n", - (int)i); - constr_params_str = mputprintf(constr_params_str, - ", CHARSTRING par_fmt_%d", (int)i); - constr_init_list_str = mputprintf(constr_init_list_str, - ", enc_fmt_%d(par_fmt_%d)", (int)i, (int)i); - if (!use_decmatch_result) { - // if the decmatch result code is generated too, then this variable - // was already generated before the main 'if' - set_values_str = mputprintf(set_values_str, - "CharCoding::CharCodingType coding = UNIVERSAL_CHARSTRING::" - "get_character_coding(enc_fmt_%d, \"decoded value redirect\");\n", - (int)i); - } - set_values_str = mputprintf(set_values_str, - "switch (coding) {\n" - "case CharCoding::UTF_8:\n" - "par%s%s.encode_utf8(buff_%d, false);\n" - "break;\n" - "case CharCoding::UTF16:\n" - "case CharCoding::UTF16LE:\n" - "case CharCoding::UTF16BE:\n" - "par%s%s.encode_utf16(buff_%d, coding);\n" - "break;\n" - "case CharCoding::UTF32:\n" - "case CharCoding::UTF32LE:\n" - "case CharCoding::UTF32BE:\n" - "par%s%s.encode_utf32(buff_%d, coding);\n" - "break;\n" - "default:\n" - "break;\n" - "}\n", subrefs_str, opt_suffix, (int)i, subrefs_str, opt_suffix, - (int)i, subrefs_str, opt_suffix, (int)i); - } - break; - default: - FATAL_ERROR("ValueRedirect::generate_code"); + "if (!%s(*ptr_%d, par%s%s)) {\n" + "TTCN_error(\"Failed to convert redirected value #%d from type `%s' " + "to type `%s'.\");\n" + "}\n", + TypeConv::get_conv_func(redir_type, ref_type, mod).c_str(), (int)i, + subrefs_str, opt_suffix, (int)(i + 1), redir_type->get_typename().c_str(), + ref_type->get_typename().c_str()); } - set_values_str = mputprintf(set_values_str, - "ptr_%d->decode(%s_descr_, buff_%d, TTCN_EncDec::CT_%s);\n" - "if (buff_%d.get_read_len() != 0) {\n" - "TTCN_error(\"Value redirect #%d failed, because the buffer was " - "not empty after decoding. Remaining octets: %%d.\", " - "(int)buff_%d.get_read_len());\n" - "}\n", - (int)i, member_type->get_genname_typedescriptor(scope).c_str(), (int)i, - member_type->get_coding(false).c_str(), (int)i, (int)(i + 1), (int)i); - if (use_decmatch_result) { - set_values_str = mputstr(set_values_str, "}\n"); + else { + set_values_str = mputprintf(set_values_str, "*ptr_%d = par%s%s;\n", + (int)i, subrefs_str, opt_suffix); } } - } - else { - // if the variable reference and the received value (or its specified field) - // are not of the same type, then a type conversion is needed (RT2 only) - if (use_runtime_2 && !ref_type->is_identical(redir_type)) { - Common::Module* mod = scope->get_scope_mod(); - mod->add_type_conv(new TypeConv(redir_type, ref_type, false)); - set_values_str = mputprintf(set_values_str, - "if (!%s(*ptr_%d, par%s%s)) {\n" - "TTCN_error(\"Failed to convert redirected value #%d from type `%s' " - "to type `%s'.\");\n" - "}\n", - TypeConv::get_conv_func(redir_type, ref_type, mod).c_str(), (int)i, - subrefs_str, opt_suffix, (int)(i + 1), redir_type->get_typename().c_str(), - ref_type->get_typename().c_str()); - } - else { - set_values_str = mputprintf(set_values_str, "*ptr_%d = par%s%s;\n", - (int)i, subrefs_str, opt_suffix); + if (subrefs_expr.postamble != NULL) { + set_values_str = mputstr(set_values_str, subrefs_expr.postamble); } + Code::free_expr(&subrefs_expr); } - if (subrefs_expr.postamble != NULL) { - set_values_str = mputstr(set_values_str, subrefs_expr.postamble); - } - Code::free_expr(&subrefs_expr); - } - expr->expr = mputc(expr->expr, ')'); - if (!base_class_prefix.empty()) { - base_class_prefix += "::"; + expr->expr = mputc(expr->expr, ')'); + if (!base_class_prefix.empty()) { + base_class_prefix += "::"; + } + // generate the new class with the gathered data + expr->preamble = mputprintf(expr->preamble, + "class Value_Redirect_%s : public %s%s_Redirect_Interface {\n" + // member declarations; one for each variable reference + "%s" + "public:\n" + // constructor: + // stores the pointers to the target variables in the class' members + "Value_Redirect_%s(%s)\n" + ": %s { }\n" + // set_values function: assigns the whole value or a part of it to each + // variable; the redirects marked with the '@decoded' modifier are decoded + // here before they are assigned + "void set_values(const %s& par)\n" + "{\n" + "%s" + "}\n" + "};\n", tmp_id.c_str(), + base_class_prefix.empty() ? "" : base_class_prefix.c_str(), + value_type->get_genname_value(value_type->get_my_scope()).c_str(), + members_str, tmp_id.c_str(), constr_params_str, constr_init_list_str, + value_type->get_genname_value(scope).c_str(), set_values_str); + Free(members_str); + Free(constr_params_str); + Free(constr_init_list_str); + Free(set_values_str); + } + else { // RT1 + // in this case only the address of the one variable needs to be generated + expr->expr = mputstr(expr->expr, "&("); + v[0]->get_var_ref()->generate_code(expr); + expr->expr = mputc(expr->expr, ')'); } - // generate the new class with the gathered data - expr->preamble = mputprintf(expr->preamble, - "class Value_Redirect_%s : public %s%s_Redirect_Interface {\n" - // member declarations; one for each variable reference - "%s" - "public:\n" - // constructor: - // stores the pointers to the target variables in the class' members - "Value_Redirect_%s(%s)\n" - ": %s { }\n" - // set_values function: assigns the whole value or a part of it to each - // variable; the redirects marked with the '@decoded' modifier are decoded - // here before they are assigned - "void set_values(const %s& par)\n" - "{\n" - "%s" - "}\n" - "};\n", tmp_id.c_str(), - base_class_prefix.empty() ? "" : base_class_prefix.c_str(), - value_type->get_genname_value(value_type->get_my_scope()).c_str(), - members_str, tmp_id.c_str(), constr_params_str, constr_init_list_str, - value_type->get_genname_value(scope).c_str(), set_values_str); - Free(members_str); - Free(constr_params_str); - Free(constr_init_list_str); - Free(set_values_str); } bool ValueRedirect::has_decoded_modifier() const diff --git a/compiler2/ttcn3/Statement.hh b/compiler2/ttcn3/Statement.hh index 96b0f23bb4e7bb0526c185d91bbcdfb64fe80660..43466c0bccc22b2b8bb54200d716072aa9205099 100644 --- a/compiler2/ttcn3/Statement.hh +++ b/compiler2/ttcn3/Statement.hh @@ -1116,6 +1116,8 @@ namespace Ttcn { * If multiple whole-value-redirects of separate types are found, then an * error is displayed. */ Type* get_type() const; + /** Checks Runtime1 restrictions and returns false if they are not met. */ + bool chk_RT1_restrictions() const; /** Performs semantic analysis on the value redirect without knowing the * type of the redirected value. Called when the value's type cannot be * determined or is erroneous. */ diff --git a/compiler2/ttcn3/port.c b/compiler2/ttcn3/port.c index 175fdb6aad67f7b405925a4c0b1143ae8e620a49..7611bc5c9408522b6189cdb0815e2099b730f7e4 100644 --- a/compiler2/ttcn3/port.c +++ b/compiler2/ttcn3/port.c @@ -565,12 +565,13 @@ static void generate_receive(char **def_ptr, char **src_ptr, } def = mputprintf(def, "alt_status %s(const %s_template& value_template, " - "%s_Redirect_Interface *value_redirect, const %s_template& sender_template, %s " + "%s%s *value_redirect, const %s_template& sender_template, %s " "*sender_ptr);\n", function_name, message_type->name, - message_type->name_w_no_prefix, sender_type, sender_type); + use_runtime_2 ? message_type->name_w_no_prefix : message_type->name, + use_runtime_2 ? "_Redirect_Interface" : "", sender_type, sender_type); src = mputprintf(src, "alt_status %s::%s(const %s_template& " - "value_template, %s_Redirect_Interface *value_redirect, const %s_template& " + "value_template, %s%s *value_redirect, const %s_template& " "sender_template, %s *sender_ptr)\n" "{\n" "if (value_template.get_selection() == ANY_OR_OMIT) " @@ -585,7 +586,9 @@ static void generate_receive(char **def_ptr, char **src_ptr, "return ALT_NO;\n" "}\n" "} else ", class_name, function_name, message_type->name, - message_type->name_w_no_prefix, sender_type, sender_type, operation_name); + use_runtime_2 ? message_type->name_w_no_prefix : message_type->name, + use_runtime_2 ? "_Redirect_Interface" : "", sender_type, sender_type, + operation_name); if (is_address) { src = mputprintf(src, "if (my_head->sender_component != " "SYSTEM_COMPREF) {\n" @@ -660,13 +663,20 @@ static void generate_receive(char **def_ptr, char **src_ptr, if (is_trigger) src = mputstr(src, "remove_msg_queue_head();\n"); src = mputprintf(src, "return %s;\n" "} else {\n" - "if (value_redirect != NULL) {\n" - "value_redirect->set_values(*my_head->message_%lu);\n" - "delete value_redirect;\n" + "if (value_redirect != NULL) {\n", failed_status); + if (use_runtime_2) { + src = mputprintf(src, + "value_redirect->set_values(*my_head->message_%lu);\n" + "delete value_redirect;\n", (unsigned long) message_index); + } + else { + src = mputprintf(src, + "*value_redirect = *my_head->message_%lu;\n", (unsigned long) message_index); + } + src = mputprintf(src, "}\n" "if (sender_ptr != NULL) *sender_ptr = %smy_head->%s;\n", - failed_status, (unsigned long) message_index, is_address ? "*" : "", - is_address ? "sender_address" : "sender_component"); + is_address ? "*" : "", is_address ? "sender_address" : "sender_component"); if (is_address) { src = mputprintf(src, @@ -1577,7 +1587,7 @@ void defPortClass(const port_def* pdef, output_struct* output) def = mputstr(def, "public:\n"); /* value redirect base classes (interfaces) */ - if (has_msg_queue) { + if (use_runtime_2 && has_msg_queue) { for (i = 0; i < pdef->msg_in.nElements; ++i) { def = mputprintf(def, "class %s_Redirect_Interface {\n" diff --git a/compiler2/ttcn3/signature.c b/compiler2/ttcn3/signature.c index 70f57338f78154e50bb302c4d50d3c2c36b9a00a..a19f4f142203cce75718590de11e424af7ec2420 100644 --- a/compiler2/ttcn3/signature.c +++ b/compiler2/ttcn3/signature.c @@ -330,7 +330,7 @@ void defSignatureClasses(const signature_def *sdef, output_struct *output) /* class definition */ def = mputprintf(def, "class %s_reply_redirect {\n", name); - if (sdef->return_type != NULL) { + if (use_runtime_2 && sdef->return_type != NULL) { /* value redirect base class (interface) for the return value */ def = mputprintf(def, "public:\n" @@ -345,8 +345,9 @@ void defSignatureClasses(const signature_def *sdef, output_struct *output) /* parameter pointers */ if (sdef->return_type != NULL) { - def = mputprintf(def, "%s_Redirect_Interface *ret_val_redir;\n", - sdef->return_type_w_no_prefix); + def = mputprintf(def, "%s%s *ret_val_redir;\n", + use_runtime_2 ? sdef->return_type_w_no_prefix : sdef->return_type, + use_runtime_2 ? "_Redirect_Interface" : ""); } for (i = 0; i < sdef->parameters.nElements; i++) { if (sdef->parameters.elements[i].direction != PAR_IN) { @@ -363,8 +364,9 @@ void defSignatureClasses(const signature_def *sdef, output_struct *output) /* constructor */ def = mputprintf(def, "%s_reply_redirect(", name); if (sdef->return_type != NULL) { - def = mputprintf(def, "%s_Redirect_Interface *return_redirect", - sdef->return_type_w_no_prefix); + def = mputprintf(def, "%s%s *return_redirect", + use_runtime_2 ? sdef->return_type_w_no_prefix : sdef->return_type, + use_runtime_2 ? "_Redirect_Interface" : ""); first_param = FALSE; } for (i = 0; i < sdef->parameters.nElements; i++) { @@ -396,7 +398,7 @@ void defSignatureClasses(const signature_def *sdef, output_struct *output) } /* otherwise constructor is not needed */ - if (sdef->return_type != NULL) { + if (use_runtime_2 && sdef->return_type != NULL) { /* destructor (only the return redirect object needs to be deleted) */ def = mputprintf(def, "~%s_reply_redirect() { " "if (ret_val_redir != NULL) delete ret_val_redir; }\n", name); @@ -420,8 +422,13 @@ void defSignatureClasses(const signature_def *sdef, output_struct *output) } } if (sdef->return_type!=NULL) { - src = mputstr(src, "if (ret_val_redir != NULL) " - "ret_val_redir->set_values(reply_par.return_value());\n"); + src = mputstr(src, "if (ret_val_redir != NULL) "); + if (use_runtime_2) { + src = mputstr(src, "ret_val_redir->set_values(reply_par.return_value());\n"); + } + else { + src = mputstr(src, "*ret_val_redir = reply_par.return_value();\n"); + } } src = mputstr(src, "}\n\n"); } @@ -686,16 +693,18 @@ void defSignatureClasses(const signature_def *sdef, output_struct *output) "class %s_exception_template {\n" "public:\n", name); - /* value redirect base classes (interfaces) */ - for (i = 0; i < sdef->exceptions.nElements; i++) { - def = mputprintf(def, - "class %s_Redirect_Interface {\n" - "public:\n" - "virtual void set_values(const %s&) = 0;\n" - "virtual ~%s_Redirect_Interface() { }\n" - "};\n", sdef->exceptions.elements[i].name_w_no_prefix, - sdef->exceptions.elements[i].name, - sdef->exceptions.elements[i].name_w_no_prefix); + if (use_runtime_2) { + /* value redirect base classes (interfaces) */ + for (i = 0; i < sdef->exceptions.nElements; i++) { + def = mputprintf(def, + "class %s_Redirect_Interface {\n" + "public:\n" + "virtual void set_values(const %s&) = 0;\n" + "virtual ~%s_Redirect_Interface() { }\n" + "};\n", sdef->exceptions.elements[i].name_w_no_prefix, + sdef->exceptions.elements[i].name, + sdef->exceptions.elements[i].name_w_no_prefix); + } } /* data members */ @@ -714,8 +723,10 @@ void defSignatureClasses(const signature_def *sdef, output_struct *output) /* union of all possible value redirect objects */ def = mputstr(def, "union {\n"); for (i = 0; i < sdef->exceptions.nElements; i++) { - def = mputprintf(def, "%s_Redirect_Interface *%s_redir;\n", - sdef->exceptions.elements[i].name_w_no_prefix, + def = mputprintf(def, "%s%s *%s_redir;\n", + use_runtime_2 ? sdef->exceptions.elements[i].name_w_no_prefix : + sdef->exceptions.elements[i].name, + use_runtime_2 ? "_Redirect_Interface" : "", sdef->exceptions.elements[i].altname); } def = mputstr(def, "};\n" @@ -723,42 +734,48 @@ void defSignatureClasses(const signature_def *sdef, output_struct *output) /* constructors (for all possible template + redirect object pairs) */ for (i = 0; i < sdef->exceptions.nElements; i++) { def = mputprintf(def, "%s_exception_template(const %s_template& " - "init_template, %s_Redirect_Interface *value_redirect = NULL);\n", name, + "init_template, %s%s *value_redirect = NULL);\n", name, sdef->exceptions.elements[i].name, - sdef->exceptions.elements[i].name_w_no_prefix); + use_runtime_2 ? sdef->exceptions.elements[i].name_w_no_prefix : + sdef->exceptions.elements[i].name, + use_runtime_2 ? "_Redirect_Interface" : ""); src = mputprintf(src, "%s_exception_template::%s_exception_template" - "(const %s_template& init_template, %s_Redirect_Interface *value_redirect)\n" + "(const %s_template& init_template, %s%s *value_redirect)\n" "{\n" "exception_selection = %s_%s;\n" "field_%s = &init_template;\n" "%s_redir = value_redirect;\n" "}\n\n", name, name, sdef->exceptions.elements[i].name, - sdef->exceptions.elements[i].name_w_no_prefix, selection_prefix, + use_runtime_2 ? sdef->exceptions.elements[i].name_w_no_prefix : + sdef->exceptions.elements[i].name, + use_runtime_2 ? "_Redirect_Interface" : "", selection_prefix, sdef->exceptions.elements[i].altname, sdef->exceptions.elements[i].altname, sdef->exceptions.elements[i].altname); } - /* destructor */ - def = mputprintf(def, "~%s_exception_template();\n", name); - src = mputprintf(src, - "%s_exception_template::~%s_exception_template()\n" - "{\n" - "switch (exception_selection) {\n", name, name); - for (i = 0; i < sdef->exceptions.nElements; i++) { + if (use_runtime_2) { + /* destructor, RT2 only */ + def = mputprintf(def, "~%s_exception_template();\n", name); + src = mputprintf(src, + "%s_exception_template::~%s_exception_template()\n" + "{\n" + "switch (exception_selection) {\n", name, name); + for (i = 0; i < sdef->exceptions.nElements; i++) { + src = mputprintf(src, + "case %s_%s:\n" + "if (%s_redir != NULL) delete %s_redir;\n" + "break;", selection_prefix, sdef->exceptions.elements[i].altname, + sdef->exceptions.elements[i].altname, + sdef->exceptions.elements[i].altname); + } src = mputprintf(src, - "case %s_%s:\n" - "if (%s_redir != NULL) delete %s_redir;\n" - "break;", selection_prefix, sdef->exceptions.elements[i].altname, - sdef->exceptions.elements[i].altname, - sdef->exceptions.elements[i].altname); + "default:\n" + "TTCN_error(\"Internal error: Invalid selector when deleting exception " + "object for signature %s.\");\n" + "}\n" + "}\n\n", dispname); } - src = mputprintf(src, - "default:\n" - "TTCN_error(\"Internal error: Invalid selector when deleting exception " - "object for signature %s.\");\n" - "}\n" - "}\n\n", dispname); /* match function */ def = mputprintf(def, "boolean match(const %s_exception& other_value," @@ -837,12 +854,20 @@ void defSignatureClasses(const signature_def *sdef, output_struct *output) "switch (exception_selection) {\n", name, name); for (i = 0; i < sdef->exceptions.nElements; i++) { src = mputprintf(src, "case %s_%s:\n" - "if (%s_redir != NULL) %s_redir->set_values(source_value.%s_field());\n" - "return;\n", selection_prefix, - sdef->exceptions.elements[i].altname, - sdef->exceptions.elements[i].altname, + "if (%s_redir != NULL) ", selection_prefix, sdef->exceptions.elements[i].altname, sdef->exceptions.elements[i].altname); + if (use_runtime_2) { + src = mputprintf(src, "%s_redir->set_values(source_value.%s_field());\n", + sdef->exceptions.elements[i].altname, + sdef->exceptions.elements[i].altname); + } + else { + src = mputprintf(src, "*%s_redir = source_value.%s_field();\n", + sdef->exceptions.elements[i].altname, + sdef->exceptions.elements[i].altname); + } + src = mputstr(src, "return;\n"); } src = mputprintf(src, "default:\n" "break;\n" diff --git a/regression_test/commMessage/Makefile b/regression_test/commMessage/Makefile index a9eaba9605119c479bba7d5fbae50405c4ac1e26..ddb1f1a9bf18d1e686b5eae1486243d7dc0f36a8 100644 --- a/regression_test/commMessage/Makefile +++ b/regression_test/commMessage/Makefile @@ -29,6 +29,10 @@ TTCN3_LIB_SINGLE = ttcn3$(RT2_SUFFIX)$(DYNAMIC_SUFFIX) TTCN3_MODULES = TcommMessage.ttcn HS41022.ttcn +ifdef RT2 +TTCN3_MODULES += TmultipleRedirects.ttcn +endif + ASN1_MODULES = ImplMsgEncData.asn GENERATED_SOURCES = $(TTCN3_MODULES:.ttcn=.cc) $(ASN1_MODULES:.asn=.cc) @@ -70,9 +74,9 @@ dep: $(GENERATED_SOURCES) run: run-single run-parallel -run-single: $(TARGET_SINGLE) config.cfg +run-single: $(TARGET_SINGLE) config$(RT2_SUFFIX).cfg ./$^ run-parallel: $(TARGET) - $(TTCN3_DIR)/bin/ttcn3_start $(TARGET) config_parallel.cfg + $(TTCN3_DIR)/bin/ttcn3_start $(TARGET) config_parallel$(RT2_SUFFIX).cfg diff --git a/regression_test/commMessage/TcommMessage.ttcn b/regression_test/commMessage/TcommMessage.ttcn index ace360bbd1a200ccd19ba7f0076ce3d38bbf50cf..7b45f557a6275c1717fe85867ec081fd9a2f9dc8 100644 --- a/regression_test/commMessage/TcommMessage.ttcn +++ b/regression_test/commMessage/TcommMessage.ttcn @@ -1474,141 +1474,6 @@ testcase commMessageDualFacedPorts2() runs on ImplicitMessageEncodingComponent { rc.stop; } -// test for value redirect with multiple variable references and field assignments -testcase commMessageMultiValueRedirect() runs on commMessage_comp3 { - connect(mtc:Port3, mtc:Port3); - var commMessage_trecord rec_val := { x1 := 3, x2 := -1.0 }; - Port3.send(rec_val); - var commMessage_trecord redir_rec; - var integer redir_int; - var float redir_float; - timer tmr := 1.0; - tmr.start; - alt { - [] Port3.receive(rec_val) -> value (redir_rec, redir_int := x1, redir_float := x2) { - if (redir_rec != rec_val) { setverdict(fail, "Invalid record value: ", redir_rec); } - if (redir_int != rec_val.x1) { setverdict(fail, "Invalid integer value: ", redir_int); } - if (redir_float != rec_val.x2) { setverdict(fail, "Invalid float value: ", redir_float); } - } - [] Port3.receive(commMessage_trecord:?) { setverdict(fail, "Incorrect value received."); } - [] tmr.timeout { setverdict(fail, "Timeout."); } - } - setverdict(pass); -} - -type record commMessage_tPayloadRecord { - bitstring bs optional, - hexstring hs optional, - octetstring os optional, - charstring cs optional, - universal charstring ucs optional -} - -type record commMessage_tDecoded { - integer num, - charstring str -} -with { - encode "JSON"; -} - -type port commMessage_port_dec message { - inout commMessage_tPayloadRecord -} -with { extension "internal" }; - -type component commMessage_comp_dec { - port commMessage_port_dec pt -} - -// test for decoded value redirect -testcase commMessageDecodedValueRedirect() runs on commMessage_comp_dec { - connect(mtc:pt, mtc:pt); - var commMessage_tDecoded val := { num := 10, str := "abc" }; - var bitstring bs_val := encvalue(val); - var hexstring hs_val := bit2hex(encvalue(val)); - var octetstring os_val := bit2oct(encvalue(val)); - var charstring cs_val := oct2char(bit2oct(encvalue(val))); - var universal charstring ucs_val := encvalue_unichar(val, "UTF-8"); - pt.send(commMessage_tPayloadRecord: { bs_val, omit, omit, omit, omit }); - pt.send(commMessage_tPayloadRecord: { omit, hs_val, omit, omit, omit }); - pt.send(commMessage_tPayloadRecord: { omit, omit, os_val, omit, omit }); - pt.send(commMessage_tPayloadRecord: { omit, omit, omit, cs_val, omit }); - pt.send(commMessage_tPayloadRecord: { omit, omit, omit, omit, ucs_val }); - timer tmr; - var commMessage_tDecoded redir[5]; - tmr.start(1.0); - alt { - [] pt.receive(commMessage_tPayloadRecord: { decmatch val, *, *, *, * }) -> value (redir[0] := @decoded bs) { - if (redir[0] != val) { setverdict(fail, "Bitstring test - redirect failed: ", redir[0]); } - } - [] pt.receive(commMessage_tPayloadRecord: { bs_val, *, *, *, * }) { - setverdict(fail, "Bitstring test - decmatch failed."); - } - [] pt.receive(commMessage_tPayloadRecord:?) { - setverdict(fail, "Bitstring test - incorrect record received."); - } - [] tmr.timeout { setverdict(fail, "Bitstring test - timeout."); } - } - tmr.stop; - tmr.start(1.0); - alt { - [] pt.receive(commMessage_tPayloadRecord: { *, decmatch val, *, *, * }) -> value (redir[1] := @decoded hs) { - if (redir[1] != val) { setverdict(fail, "Hexstring test - redirect failed: ", redir[1]); } - } - [] pt.receive(commMessage_tPayloadRecord: { *, hs_val, *, *, * }) { - setverdict(fail, "Hexstring test - decmatch failed."); - } - [] pt.receive(commMessage_tPayloadRecord:?) { - setverdict(fail, "Hexstring test - incorrect record received."); - } - [] tmr.timeout { setverdict(fail, "Hexstring test - timeout."); } - } - tmr.stop; - tmr.start(1.0); - alt { - [] pt.receive(commMessage_tPayloadRecord: { *, *, decmatch val, *, * }) -> value (redir[2] := @decoded os) { - if (redir[2] != val) { setverdict(fail, "Octetstring test - redirect failed: ", redir[2]); } - } - [] pt.receive(commMessage_tPayloadRecord: { *, *, os_val, *, * }) { - setverdict(fail, "Octetstring test - decmatch failed."); - } - [] pt.receive(commMessage_tPayloadRecord:?) { - setverdict(fail, "Octetstring test - incorrect record received."); - } - [] tmr.timeout { setverdict(fail, "Octetstring test - timeout."); } - } - tmr.stop; - tmr.start(1.0); - alt { - [] pt.receive(commMessage_tPayloadRecord: { *, *, *, decmatch val, * }) -> value (redir[3] := @decoded cs) { - if (redir[3] != val) { setverdict(fail, "Charstring test - redirect failed: ", redir[3]); } - } - [] pt.receive(commMessage_tPayloadRecord: { *, *, *, cs_val, * }) { - setverdict(fail, "Charstring test - decmatch failed."); - } - [] pt.receive(commMessage_tPayloadRecord:?) { - setverdict(fail, "Charstring test - incorrect record received."); - } - [] tmr.timeout { setverdict(fail, "Charstring test - timeout."); } - } - tmr.stop; - tmr.start(1.0); - alt { - [] pt.receive(commMessage_tPayloadRecord: { *, *, *, *, decmatch("UTF-8") val }) -> value (redir[4] := @decoded("UTF-8") ucs) { - if (redir[4] != val) { setverdict(fail, "Universal charstring test - redirect failed: ", redir[4]); } - } - [] pt.receive(commMessage_tPayloadRecord: { *, *, *, *, ucs_val }) { - setverdict(fail, "Universal charstring test - decmatch failed."); - } - [] pt.receive(commMessage_tPayloadRecord:?) { - setverdict(fail, "Universal charstring test - incorrect record received."); - } - [] tmr.timeout { setverdict(fail, "Universal charstring test - timeout."); } - } - setverdict(pass); -} - // '*' is not allowed as a matching template in receive operations testcase commMessageReceiveAnyOrOmit() runs on commMessage_comp1 { connect(self:Port1, self:Port1); @@ -1688,8 +1553,6 @@ control { execute(commMessageInterPTCLocalConnection2()); execute(commMessageDualFacedPorts1()); execute(commMessageDualFacedPorts2()); - execute(commMessageMultiValueRedirect()); - execute(commMessageDecodedValueRedirect()); execute(commMessageReceiveAnyOrOmit()); } } diff --git a/regression_test/commMessage/TmultipleRedirects.ttcn b/regression_test/commMessage/TmultipleRedirects.ttcn new file mode 100644 index 0000000000000000000000000000000000000000..1a17fd67325a3d81e6b1f6a9202df8ee7dc69dfd --- /dev/null +++ b/regression_test/commMessage/TmultipleRedirects.ttcn @@ -0,0 +1,156 @@ +/****************************************************************************** + * Copyright (c) 2000-2016 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: + * Baranyi, Botond – initial implementation + * + ******************************************************************************/ +module TmultipleRedirects { + +import from TcommMessage all; + +// test for value redirect with multiple variable references and field assignments +testcase commMessageMultiValueRedirect() runs on commMessage_comp3 { + connect(mtc:Port3, mtc:Port3); + var commMessage_trecord rec_val := { x1 := 3, x2 := -1.0 }; + Port3.send(rec_val); + var commMessage_trecord redir_rec; + var integer redir_int; + var float redir_float; + timer tmr := 1.0; + tmr.start; + alt { + [] Port3.receive(rec_val) -> value (redir_rec, redir_int := x1, redir_float := x2) { + if (redir_rec != rec_val) { setverdict(fail, "Invalid record value: ", redir_rec); } + if (redir_int != rec_val.x1) { setverdict(fail, "Invalid integer value: ", redir_int); } + if (redir_float != rec_val.x2) { setverdict(fail, "Invalid float value: ", redir_float); } + } + [] Port3.receive(commMessage_trecord:?) { setverdict(fail, "Incorrect value received."); } + [] tmr.timeout { setverdict(fail, "Timeout."); } + } + setverdict(pass); +} + +type record commMessage_tPayloadRecord { + bitstring bs optional, + hexstring hs optional, + octetstring os optional, + charstring cs optional, + universal charstring ucs optional +} + +type record commMessage_tDecoded { + integer num, + charstring str +} +with { + encode "JSON"; +} + +type port commMessage_port_dec message { + inout commMessage_tPayloadRecord +} +with { extension "internal" }; + +type component commMessage_comp_dec { + port commMessage_port_dec pt +} + +// test for decoded value redirect +testcase commMessageDecodedValueRedirect() runs on commMessage_comp_dec { + connect(mtc:pt, mtc:pt); + var commMessage_tDecoded val := { num := 10, str := "abc" }; + var bitstring bs_val := encvalue(val); + var hexstring hs_val := bit2hex(encvalue(val)); + var octetstring os_val := bit2oct(encvalue(val)); + var charstring cs_val := oct2char(bit2oct(encvalue(val))); + var universal charstring ucs_val := encvalue_unichar(val, "UTF-8"); + pt.send(commMessage_tPayloadRecord: { bs_val, omit, omit, omit, omit }); + pt.send(commMessage_tPayloadRecord: { omit, hs_val, omit, omit, omit }); + pt.send(commMessage_tPayloadRecord: { omit, omit, os_val, omit, omit }); + pt.send(commMessage_tPayloadRecord: { omit, omit, omit, cs_val, omit }); + pt.send(commMessage_tPayloadRecord: { omit, omit, omit, omit, ucs_val }); + timer tmr; + var commMessage_tDecoded redir[5]; + tmr.start(1.0); + alt { + [] pt.receive(commMessage_tPayloadRecord: { decmatch val, *, *, *, * }) -> value (redir[0] := @decoded bs) { + if (redir[0] != val) { setverdict(fail, "Bitstring test - redirect failed: ", redir[0]); } + } + [] pt.receive(commMessage_tPayloadRecord: { bs_val, *, *, *, * }) { + setverdict(fail, "Bitstring test - decmatch failed."); + } + [] pt.receive(commMessage_tPayloadRecord:?) { + setverdict(fail, "Bitstring test - incorrect record received."); + } + [] tmr.timeout { setverdict(fail, "Bitstring test - timeout."); } + } + tmr.stop; + tmr.start(1.0); + alt { + [] pt.receive(commMessage_tPayloadRecord: { *, decmatch val, *, *, * }) -> value (redir[1] := @decoded hs) { + if (redir[1] != val) { setverdict(fail, "Hexstring test - redirect failed: ", redir[1]); } + } + [] pt.receive(commMessage_tPayloadRecord: { *, hs_val, *, *, * }) { + setverdict(fail, "Hexstring test - decmatch failed."); + } + [] pt.receive(commMessage_tPayloadRecord:?) { + setverdict(fail, "Hexstring test - incorrect record received."); + } + [] tmr.timeout { setverdict(fail, "Hexstring test - timeout."); } + } + tmr.stop; + tmr.start(1.0); + alt { + [] pt.receive(commMessage_tPayloadRecord: { *, *, decmatch val, *, * }) -> value (redir[2] := @decoded os) { + if (redir[2] != val) { setverdict(fail, "Octetstring test - redirect failed: ", redir[2]); } + } + [] pt.receive(commMessage_tPayloadRecord: { *, *, os_val, *, * }) { + setverdict(fail, "Octetstring test - decmatch failed."); + } + [] pt.receive(commMessage_tPayloadRecord:?) { + setverdict(fail, "Octetstring test - incorrect record received."); + } + [] tmr.timeout { setverdict(fail, "Octetstring test - timeout."); } + } + tmr.stop; + tmr.start(1.0); + alt { + [] pt.receive(commMessage_tPayloadRecord: { *, *, *, decmatch val, * }) -> value (redir[3] := @decoded cs) { + if (redir[3] != val) { setverdict(fail, "Charstring test - redirect failed: ", redir[3]); } + } + [] pt.receive(commMessage_tPayloadRecord: { *, *, *, cs_val, * }) { + setverdict(fail, "Charstring test - decmatch failed."); + } + [] pt.receive(commMessage_tPayloadRecord:?) { + setverdict(fail, "Charstring test - incorrect record received."); + } + [] tmr.timeout { setverdict(fail, "Charstring test - timeout."); } + } + tmr.stop; + tmr.start(1.0); + alt { + [] pt.receive(commMessage_tPayloadRecord: { *, *, *, *, decmatch("UTF-8") val }) -> value (redir[4] := @decoded("UTF-8") ucs) { + if (redir[4] != val) { setverdict(fail, "Universal charstring test - redirect failed: ", redir[4]); } + } + [] pt.receive(commMessage_tPayloadRecord: { *, *, *, *, ucs_val }) { + setverdict(fail, "Universal charstring test - decmatch failed."); + } + [] pt.receive(commMessage_tPayloadRecord:?) { + setverdict(fail, "Universal charstring test - incorrect record received."); + } + [] tmr.timeout { setverdict(fail, "Universal charstring test - timeout."); } + } + setverdict(pass); +} + +control { + execute(commMessageMultiValueRedirect()); + execute(commMessageDecodedValueRedirect()); +} + +} diff --git a/regression_test/commMessage/config-rt2.cfg b/regression_test/commMessage/config-rt2.cfg new file mode 100644 index 0000000000000000000000000000000000000000..64b54d60fc6ba1d588ecf12f5ac8f177bfe8420a --- /dev/null +++ b/regression_test/commMessage/config-rt2.cfg @@ -0,0 +1,23 @@ +############################################################################### +# Copyright (c) 2000-2016 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: +# Balasko, Jeno +# Baranyi, Botond +# Dimitrov, Peter +# +############################################################################### +[LOGGING] +LogFile := "TcommMessage_single.log" +FileMask := LOG_ALL +ConsoleMask := TTCN_ERROR | TTCN_TESTCASE | TTCN_STATISTICS + +[EXECUTE] +TcommMessage.commMessageInterPTCLocalConnection1 +TcommMessage.commMessageInterPTCLocalConnection2 +TmultipleRedirects.control + diff --git a/regression_test/commMessage/config_parallel-rt2.cfg b/regression_test/commMessage/config_parallel-rt2.cfg new file mode 100644 index 0000000000000000000000000000000000000000..d9202831f2561436b92d82aa2c8e5c8a7e16ef81 --- /dev/null +++ b/regression_test/commMessage/config_parallel-rt2.cfg @@ -0,0 +1,22 @@ +############################################################################### +# Copyright (c) 2000-2016 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: +# Balasko, Jeno +# Baranyi, Botond +# +############################################################################### +[LOGGING] +LogFile := "TcommMessage_parallel_%r.log" +FileMask := LOG_ALL +ConsoleMask := TTCN_ERROR | TTCN_TESTCASE | TTCN_STATISTICS + +[EXECUTE] +TcommMessage.control +HS41022.control +TmultipleRedirects.control + diff --git a/regression_test/commProcedure/AdvancedRedirects.ttcn b/regression_test/commProcedure/AdvancedRedirects.ttcn new file mode 100644 index 0000000000000000000000000000000000000000..ef82c150fab68735cde3b494350cf36067d1bb95 --- /dev/null +++ b/regression_test/commProcedure/AdvancedRedirects.ttcn @@ -0,0 +1,417 @@ +/****************************************************************************** +* Copyright (c) 2000-2016 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: +* Baranyi, Botond – initial implementation +* +******************************************************************************/ +module AdvancedRedirects { + +import from ProcPort all; + +// test for return value and exception redirects with multiple variable references and field assignments +testcase tc_MultiValueRedirect() runs on ProcComponent4 { + connect(mtc:Port4, mtc:Port4); + var MyRecord2 rec_val := { num := 12, str := "xyz" }; + Port4.reply(MyProc7: { "" } value rec_val); + Port4.raise(MyProc7, rec_val); + timer tmr; + var MyRecord2 redir_rec[2]; + var integer redir_int[2]; + var universal charstring redir_str[2]; + tmr.start(1.0); + alt { + [] Port4.getreply(MyProc7: { ? } value rec_val) -> value (redir_rec[0], redir_int[0] := num, redir_str[0] := str) { + if (redir_rec[0] != rec_val) { setverdict(fail, "Invalid record return value: ", redir_rec[0]); } + if (redir_int[0] != rec_val.num) { setverdict(fail, "Invalid integer return value: ", redir_int[0]); } + if (redir_str[0] != rec_val.str) { setverdict(fail, "Invalid charstring return value: ", redir_str[0]); } + } + [] Port4.getreply(MyProc7: { ? } value MyRecord2: ?) { setverdict(fail, "Return value test - invalid return value."); } + [] Port4.catch(MyProc7, MyRecord2: ?) { setverdict(fail, "Return value test - exception caught."); } + [] tmr.timeout { setverdict(fail, "Return value test - timeout"); } + } + tmr.stop; + tmr.start(1.0); + alt { + [] Port4.catch(MyProc7, rec_val) -> value (redir_rec[1], redir_int[1] := num, redir_str[1] := str) { + if (redir_rec[1] != rec_val) { setverdict(fail, "Invalid record exception: ", redir_rec[1]); } + if (redir_int[1] != rec_val.num) { setverdict(fail, "Invalid integer exception: ", redir_int[1]); } + if (redir_str[1] != rec_val.str) { setverdict(fail, "Invalid charstring exception: ", redir_str[1]); } + } + [] Port4.catch(MyProc7, MyRecord2: ?) { setverdict(fail, "Exception test - invalid exception."); } + [] Port4.getreply(MyProc7: { ? } value MyRecord2: ?) { setverdict(fail, "Exception test - reply received."); } + [] tmr.timeout { setverdict(fail, "Exception test - timeout"); } + } + setverdict(pass); +} + +// tests for decoded parameter and value redirects +// (in these tests the received parameters and values are not matched with a 'decmatch' template) +function DecodedRedirect_behav(in MyRecord2 val, in universal charstring reply_val) runs on ProcComponent4 { + timer tmr := 1.0; + var universal charstring val_enc := encvalue_unichar(val); + var MyRecord2 redir; + + // testing parameter redirect in getcall: + tmr.start; + alt { + [] Port4.getcall(MyProc7: { val_enc }) -> param (redir := @decoded x) { + if (redir != val) { setverdict(fail, "Getcall parameter redirect failed: ", redir); } + else { + var MyRecord2 reply_rec := { num := -1, str := reply_val }; + Port4.reply(MyProc7: { reply_val } value reply_rec); + Port4.raise(MyProc7, reply_rec); + } + } + [] Port4.getcall(MyProc7: { ? }) { setverdict(fail, "Invalid getcall parameter."); } + [] tmr.timeout { setverdict(fail, "Getcall timed out."); } + } +} + +testcase tc_DecodedRedirect() runs on ProcComponent4 { + var ProcComponent4 ct := ProcComponent4.create; + connect(ct:Port4, mtc:Port4); + var MyRecord2 val := { num := 4, str := "stuff" }; + // use this string instead of an actual encoded value for reply/getreply and raise/catch, + // because finding a value that can be encoded with UTF-16 or UTF-32 is difficult + // (after this string is decoded into an octetstring, only the octetstring's length is matched) + var universal charstring reply_val := "payload"; + ct.start(DecodedRedirect_behav(val, reply_val)); + var universal charstring val_enc := encvalue_unichar(val); + var MyOctetstring redir[3]; + // these encoding strings are not known at compile-time (the code generated for them is different) + var charstring str_enc8 := "UTF-8", str_enc16 := "UTF-16", str_enc32 := "UTF-32LE"; + + // testing parameter and (return) value redirect in getreply: + Port4.call(MyProc7: { val_enc }, 1.0) { + [] Port4.getreply(MyProc7: { reply_val } + value MyRecord2: { num := ?, str := reply_val }) + -> value (redir[0] := @decoded("UTF-8") str) + param (redir[1] := @decoded(str_enc16) x) { + if (redir[0] != unichar2oct(reply_val, "UTF-8")) { + setverdict(fail, "Getreply parameter redirect failed: ", redir[0]); + } + if (redir[1] != unichar2oct(reply_val, str_enc16)) { + setverdict(fail, "Getreply value redirect failed: ", redir[1]); + } + } + [] Port4.getreply(MyProc7: { decmatch(str_enc16) MyOctetstring: ? length (16) } value MyRecord2: ?) { + setverdict(fail, "Invalid getreply return value."); + } + [] Port4.getreply(MyProc7: { ? } value MyRecord2: ?) { + setverdict(fail, "Invalid getreply parameter."); + } + [] Port4.catch(MyProc7, MyRecord2: ?) { + setverdict(fail, "Exception (MyRecord2) caught in getreply test."); + } + [] Port4.catch(MyProc7, MyRecord3: ?) { + setverdict(fail, "Exception (MyRecord3) caught in getreply test."); + } + [] Port4.catch(timeout) { setverdict(fail, "Getreply test timed out."); } + } + + // testing (exception) value redirect in catch: + timer tmr := 1.0; + tmr.start; + alt { + [] Port4.catch(MyProc7, MyRecord2: { num := ?, str := reply_val }) + -> value (redir[2] := @decoded(str_enc32) str) { + if (redir[2] != unichar2oct(reply_val, str_enc32)) { + setverdict(fail, "Exception value redirect failed: ", redir[2]); + } + } + [] Port4.catch(MyProc7, MyRecord2: ?) { + setverdict(fail, "Invalid exception value caught."); + } + [] Port4.catch(MyProc7, MyRecord3: ?) { + setverdict(fail, "Invalid type of exception caught."); + } + [] Port4.getreply(MyProc7: { ? } value MyRecord2: ?) { + setverdict(fail, "Reply received in exception test."); + } + [] tmr.timeout { setverdict(fail, "Exception test timed out."); } + } + setverdict(pass); +} + +// additional tests for decoded parameter and value redirects +// (in these tests the value and parameter redirects with the '@decoded' modifier +// are optimized to reuse the decoding result in the 'decmatch' template instead of +// decoding the same string twice) +function DecodedRedirect2_behav(in MyRecord2 val, in universal charstring reply_val) runs on ProcComponent4 { + timer tmr := 1.0; + var MyRecord2 redir; + + // testing parameter redirect in getcall: + tmr.start; + alt { + [] Port4.getcall(MyProc7: { decmatch("UTF-8") MyRecord2: val }) -> param (redir := @decoded x) { + if (redir != val) { setverdict(fail, "Getcall parameter redirect failed: ", redir); } + else { + var MyRecord2 reply_rec := { num := -1, str := reply_val }; + Port4.reply(MyProc7: { reply_val } value reply_rec); + Port4.raise(MyProc7, reply_rec); + } + } + [] Port4.getcall(MyProc7: { ? }) { setverdict(fail, "Invalid getcall parameter."); } + [] tmr.timeout { setverdict(fail, "Getcall timed out."); } + } +} + +testcase tc_DecodedRedirect2() runs on ProcComponent4 { + var ProcComponent4 ct := ProcComponent4.create; + connect(ct:Port4, mtc:Port4); + var MyRecord2 val := { num := 4, str := "stuff" }; + // use this string instead of an actual encoded value for reply/getreply and raise/catch, + // because finding a value that can be encoded with UTF-16 or UTF-32 is difficult + // (after this string is decoded into an octetstring, only the octetstring's length is matched) + var universal charstring reply_val := "payload"; + ct.start(DecodedRedirect2_behav(val, reply_val)); + var universal charstring val_enc := encvalue_unichar(val); + var MyOctetstring redir[3]; + // these encoding strings are not known at compile-time (the code generated for them is different) + var charstring str_enc8 := "UTF-8", str_enc16 := "UTF-16", str_enc32 := "UTF-32LE"; + + // testing parameter and (return) value redirect in getreply: + Port4.call(MyProc7: { val_enc }, 1.0) { + [] Port4.getreply(MyProc7: { decmatch(str_enc16) MyOctetstring: ? length (16) } + value MyRecord2: { num := ?, str := decmatch(str_enc8) MyOctetstring: ? length (7) }) + -> value (redir[0] := @decoded("UTF-8") str) + param (redir[1] := @decoded(str_enc16) x) { + if (redir[0] != unichar2oct(reply_val, "UTF-8")) { + setverdict(fail, "Getreply parameter redirect failed: ", redir[0]); + } + if (redir[1] != unichar2oct(reply_val, str_enc16)) { + setverdict(fail, "Getreply value redirect failed: ", redir[1]); + } + } + [] Port4.getreply(MyProc7: { decmatch(str_enc16) MyOctetstring: ? length (16) } value MyRecord2: ?) { + setverdict(fail, "Invalid getreply return value."); + } + [] Port4.getreply(MyProc7: { ? } value MyRecord2: ?) { + setverdict(fail, "Invalid getreply parameter."); + } + [] Port4.catch(MyProc7, MyRecord2: ?) { + setverdict(fail, "Exception (MyRecord2) caught in getreply test."); + } + [] Port4.catch(MyProc7, MyRecord3: ?) { + setverdict(fail, "Exception (MyRecord3) caught in getreply test."); + } + [] Port4.catch(timeout) { setverdict(fail, "Getreply test timed out."); } + } + + // testing (exception) value redirect in catch: + timer tmr := 1.0; + tmr.start; + alt { + [] Port4.catch(MyProc7, MyRecord2: { num := ?, str := decmatch("UTF-32LE") MyOctetstring: ? length(32) }) + -> value (redir[2] := @decoded(str_enc32) str) { + if (redir[2] != unichar2oct(reply_val, str_enc32)) { + setverdict(fail, "Exception value redirect failed: ", redir[2]); + } + } + [] Port4.catch(MyProc7, MyRecord2: ?) { + setverdict(fail, "Invalid exception value caught."); + } + [] Port4.catch(MyProc7, MyRecord3: ?) { + setverdict(fail, "Invalid type of exception caught."); + } + [] Port4.getreply(MyProc7: { ? } value MyRecord2: ?) { + setverdict(fail, "Reply received in exception test."); + } + [] tmr.timeout { setverdict(fail, "Exception test timed out."); } + } + setverdict(pass); +} + +// further tests for decoded parameter and value redirects +// (in these tests the 'decmatch' templates cannot be identified at compile-time, +// so the decision of whether to decode the redirected value again or use the +// decoding result in the matched template is made at runtime) +function DecodedRedirect3_behav(in MyRecord2 val) runs on ProcComponent4 { + timer tmr := 1.0; + var MyRecord2 redir; + var template MyProc7 vt_proc7 := { x := decmatch MyRecord2: val }; + + // testing parameter redirect in getcall: + tmr.start; + alt { + [] Port4.getcall(vt_proc7) -> param (redir := @decoded x) { + if (redir != val) { setverdict(fail, "Getcall parameter redirect failed: ", redir); } + else { + var universal charstring val_enc := encvalue_unichar(val); + var MyRecord2 reply_val := { num := val.num, str := val_enc }; + var MyRecord3 raise_val := { elems := { reply_val } }; + Port4.reply(MyProc7: { val_enc } value reply_val); + Port4.raise(MyProc7, raise_val); + } + } + [] Port4.getcall(MyProc7: { ? }) { setverdict(fail, "Invalid getcall parameter."); } + [] tmr.timeout { setverdict(fail, "Getcall timed out."); } + } +} + +testcase tc_DecodedRedirect3() runs on ProcComponent4 { + var ProcComponent4 ct := ProcComponent4.create; + connect(ct:Port4, mtc:Port4); + var MyRecord2 val := { num := 4, str := "stuff" }; + ct.start(DecodedRedirect3_behav(val)); + var universal charstring val_enc := encvalue_unichar(val); + var MyRecord2 redir[3]; + var template MyRecord2 vt_rec2 := { num := ?, str := decmatch MyRecord2: val }; + var charstring str_enc8 := "UTF-8"; + + // testing parameter and (return) value redirect in getreply: + Port4.call(MyProc7: { val_enc }, 1.0) { + [] Port4.getreply(MyProc7TemplatePard(decmatch MyRecord2: val) + value modifies vt_rec2 := { num := val.num }) + -> value (redir[0] := @decoded str) + param (redir[1] := @decoded(str_enc8) x) { + if (redir[0] != val) { + setverdict(fail, "Getreply parameter redirect failed: ", redir[0]); + } + if (redir[1] != val) { + setverdict(fail, "Getreply value redirect failed: ", redir[1]); + } + } + [] Port4.getreply(MyProc7TemplatePard(decmatch MyRecord2: val) value MyRecord2: ?) { + setverdict(fail, "Invalid getreply return value."); + } + [] Port4.getreply(MyProc7: { ? } value MyRecord2: ?) { + setverdict(fail, "Invalid getreply parameter."); + } + [] Port4.catch(MyProc7, MyRecord2: ?) { + setverdict(fail, "Exception (MyRecord2) caught in getreply test."); + } + [] Port4.catch(MyProc7, MyRecord3: ?) { + setverdict(fail, "Exception (MyRecord3) caught in getreply test."); + } + [] Port4.catch(timeout) { setverdict(fail, "Getreply test timed out."); } + } + + // testing (exception) value redirect in catch: + timer tmr := 1.0; + tmr.start; + alt { + [] Port4.catch(MyProc7, MyRecord3: { elems := { vt_rec2 } }) + -> value (redir[2] := @decoded(str_enc8) elems[0].str) { + if (redir[2] != val) { + setverdict(fail, "Exception value redirect failed: ", redir[2]); + } + } + [] Port4.catch(MyProc7, MyRecord3: ?) { + setverdict(fail, "Invalid exception value caught."); + } + [] Port4.catch(MyProc7, MyRecord2: ?) { + setverdict(fail, "Invalid type of exception caught."); + } + [] Port4.getreply(MyProc7: { ? } value MyRecord2: ?) { + setverdict(fail, "Reply received in exception test."); + } + [] tmr.timeout { setverdict(fail, "Exception test timed out."); } + } + setverdict(pass); +} + +// even more tests for decoded parameter and value redirects +// (in these tests the sent/received strings are decoded into 2 different types: +// the matching 'decmatch' templates decode the strings into MyRecord2, while the +// value and parameter redirects decode the string into MyRecord4) +function DecodedRedirect4_behav(in MyRecord2 val2, in MyRecord4 val4) runs on ProcComponent4 { + timer tmr := 1.0; + var MyRecord4 redir; + + // testing parameter redirect in getcall: + tmr.start; + alt { + [] Port4.getcall(MyProc7: { decmatch MyRecord2: val2 }) -> param (redir := @decoded x) { + if (redir != val4) { + setverdict(fail, "Getcall parameter redirect failed: ", redir); + } + else { + var universal charstring val_enc := encvalue_unichar(val2); + var MyRecord2 reply_val := { num := val2.num, str := val_enc }; + var MyRecord3 raise_val := { elems := { reply_val } }; + Port4.reply(MyProc7: { val_enc } value reply_val); + Port4.raise(MyProc7, raise_val); + } + } + [] Port4.getcall(MyProc7: { ? }) { setverdict(fail, "Invalid getcall parameter."); } + [] tmr.timeout { setverdict(fail, "Getcall timed out."); } + } +} + +testcase tc_DecodedRedirect4() runs on ProcComponent4 { + var ProcComponent4 ct := ProcComponent4.create; + connect(ct:Port4, mtc:Port4); + var MyRecord2 val2 := { num := 4, str := "ADDC" }; + var MyRecord4 val4 := { attr := "4", val := 'ADDC'O }; + ct.start(DecodedRedirect4_behav(val2, val4)); + var universal charstring val_enc := encvalue_unichar(val2); + var MyRecord4 redir[3]; + + // testing parameter and (return) value redirect in getreply: + Port4.call(MyProc7: { val_enc }, 1.0) { + [] Port4.getreply(MyProc7TemplatePard(decmatch MyRecord2: val2) + value MyRecord2: { num := ?, str := decmatch MyRecord2: val2 }) + -> value (redir[0] := @decoded str) + param (redir[1] := @decoded x) { + if (redir[0] != val4) { + setverdict(fail, "Getreply parameter redirect failed: ", redir[0]); + } + if (redir[1] != val4) { + setverdict(fail, "Getreply value redirect failed: ", redir[1]); + } + } + [] Port4.getreply(MyProc7TemplatePard(decmatch MyRecord2: val2) value MyRecord2: ?) { + setverdict(fail, "Invalid getreply return value."); + } + [] Port4.getreply(MyProc7: { ? } value MyRecord2: ?) { + setverdict(fail, "Invalid getreply parameter."); + } + [] Port4.catch(MyProc7, MyRecord2: ?) { + setverdict(fail, "Exception (MyRecord2) caught in getreply test."); + } + [] Port4.catch(MyProc7, MyRecord3: ?) { + setverdict(fail, "Exception (MyRecord3) caught in getreply test."); + } + [] Port4.catch(timeout) { setverdict(fail, "Getreply test timed out."); } + } + + // testing (exception) value redirect in catch: + var template MyRecord3 vt_rec3 := { elems := { { num := ?, str := decmatch MyRecord2: val2 } } }; + timer tmr := 1.0; + tmr.start; + alt { + [] Port4.catch(MyProc7, vt_rec3) -> value (redir[2] := @decoded elems[0].str) { + if (redir[2] != val4) { + setverdict(fail, "Exception value redirect failed: ", redir[2]); + } + } + [] Port4.catch(MyProc7, MyRecord3: ?) { + setverdict(fail, "Invalid exception value caught."); + } + [] Port4.catch(MyProc7, MyRecord2: ?) { + setverdict(fail, "Invalid type of exception caught."); + } + [] Port4.getreply(MyProc7: { ? } value MyRecord2: ?) { + setverdict(fail, "Reply received in exception test."); + } + [] tmr.timeout { setverdict(fail, "Exception test timed out."); } + } + setverdict(pass); +} + +control { + execute(tc_MultiValueRedirect()); + execute(tc_DecodedRedirect()); + execute(tc_DecodedRedirect2()); + execute(tc_DecodedRedirect3()); + execute(tc_DecodedRedirect4()); +} + +} diff --git a/regression_test/commProcedure/Makefile b/regression_test/commProcedure/Makefile index 4e61d442266af7cf424c37da0ed32a9973e30ba7..66a907e6f7ca63f60d727ad322b192f3b53887b4 100644 --- a/regression_test/commProcedure/Makefile +++ b/regression_test/commProcedure/Makefile @@ -7,6 +7,7 @@ # # Contributors: # Balasko, Jeno +# Baranyi, Botond # Delic, Adam # Kovacs, Ferenc # Raduly, Csaba @@ -26,6 +27,10 @@ TTCN3_LIB := ttcn3$(RT2_SUFFIX)-parallel$(DYNAMIC_SUFFIX) TTCN3_MODULES := ProcPort.ttcn +ifdef RT2 +TTCN3_MODULES += AdvancedRedirects.ttcn +endif + GENERATED_SOURCES := $(TTCN3_MODULES:.ttcn=.cc) GENERATED_HEADERS := $(GENERATED_SOURCES:.cc=.hh) ifdef CODE_SPLIT @@ -75,7 +80,7 @@ dep: $(GENERATED_SOURCES) makedepend $(CPPFLAGS) $(USER_SOURCES) $(GENERATED_SOURCES) run: $(TARGET) - $(TTCN3_DIR)/bin/ttcn3_start $(TARGET) + $(TTCN3_DIR)/bin/ttcn3_start $(TARGET) config$(RT2_SUFFIX).cfg ExtProcPort.o: ExtProcPort.hh ProcPort.hh diff --git a/regression_test/commProcedure/ProcPort.ttcn b/regression_test/commProcedure/ProcPort.ttcn index c01431f853e96de27269df13a3ec884082fb97fa..fe80f22bcbedef621af688c73895a81faeed551c 100644 --- a/regression_test/commProcedure/ProcPort.ttcn +++ b/regression_test/commProcedure/ProcPort.ttcn @@ -706,399 +706,6 @@ testcase tc_GetReplyParameters() runs on ProcComponent3 { c.done; } -// test for return value and exception redirects with multiple variable references and field assignments -testcase tc_MultiValueRedirect() runs on ProcComponent4 { - connect(mtc:Port4, mtc:Port4); - var MyRecord2 rec_val := { num := 12, str := "xyz" }; - Port4.reply(MyProc7: { "" } value rec_val); - Port4.raise(MyProc7, rec_val); - timer tmr; - var MyRecord2 redir_rec[2]; - var integer redir_int[2]; - var universal charstring redir_str[2]; - tmr.start(1.0); - alt { - [] Port4.getreply(MyProc7: { ? } value rec_val) -> value (redir_rec[0], redir_int[0] := num, redir_str[0] := str) { - if (redir_rec[0] != rec_val) { setverdict(fail, "Invalid record return value: ", redir_rec[0]); } - if (redir_int[0] != rec_val.num) { setverdict(fail, "Invalid integer return value: ", redir_int[0]); } - if (redir_str[0] != rec_val.str) { setverdict(fail, "Invalid charstring return value: ", redir_str[0]); } - } - [] Port4.getreply(MyProc7: { ? } value MyRecord2: ?) { setverdict(fail, "Return value test - invalid return value."); } - [] Port4.catch(MyProc7, MyRecord2: ?) { setverdict(fail, "Return value test - exception caught."); } - [] tmr.timeout { setverdict(fail, "Return value test - timeout"); } - } - tmr.stop; - tmr.start(1.0); - alt { - [] Port4.catch(MyProc7, rec_val) -> value (redir_rec[1], redir_int[1] := num, redir_str[1] := str) { - if (redir_rec[1] != rec_val) { setverdict(fail, "Invalid record exception: ", redir_rec[1]); } - if (redir_int[1] != rec_val.num) { setverdict(fail, "Invalid integer exception: ", redir_int[1]); } - if (redir_str[1] != rec_val.str) { setverdict(fail, "Invalid charstring exception: ", redir_str[1]); } - } - [] Port4.catch(MyProc7, MyRecord2: ?) { setverdict(fail, "Exception test - invalid exception."); } - [] Port4.getreply(MyProc7: { ? } value MyRecord2: ?) { setverdict(fail, "Exception test - reply received."); } - [] tmr.timeout { setverdict(fail, "Exception test - timeout"); } - } - setverdict(pass); -} - -// tests for decoded parameter and value redirects -// (in these tests the received parameters and values are not matched with a 'decmatch' template) -function DecodedRedirect_behav(in MyRecord2 val, in universal charstring reply_val) runs on ProcComponent4 { - timer tmr := 1.0; - var universal charstring val_enc := encvalue_unichar(val); - var MyRecord2 redir; - - // testing parameter redirect in getcall: - tmr.start; - alt { - [] Port4.getcall(MyProc7: { val_enc }) -> param (redir := @decoded x) { - if (redir != val) { setverdict(fail, "Getcall parameter redirect failed: ", redir); } - else { - var MyRecord2 reply_rec := { num := -1, str := reply_val }; - Port4.reply(MyProc7: { reply_val } value reply_rec); - Port4.raise(MyProc7, reply_rec); - } - } - [] Port4.getcall(MyProc7: { ? }) { setverdict(fail, "Invalid getcall parameter."); } - [] tmr.timeout { setverdict(fail, "Getcall timed out."); } - } -} - -testcase tc_DecodedRedirect() runs on ProcComponent4 { - var ProcComponent4 ct := ProcComponent4.create; - connect(ct:Port4, mtc:Port4); - var MyRecord2 val := { num := 4, str := "stuff" }; - // use this string instead of an actual encoded value for reply/getreply and raise/catch, - // because finding a value that can be encoded with UTF-16 or UTF-32 is difficult - // (after this string is decoded into an octetstring, only the octetstring's length is matched) - var universal charstring reply_val := "payload"; - ct.start(DecodedRedirect_behav(val, reply_val)); - var universal charstring val_enc := encvalue_unichar(val); - var MyOctetstring redir[3]; - // these encoding strings are not known at compile-time (the code generated for them is different) - var charstring str_enc8 := "UTF-8", str_enc16 := "UTF-16", str_enc32 := "UTF-32LE"; - - // testing parameter and (return) value redirect in getreply: - Port4.call(MyProc7: { val_enc }, 1.0) { - [] Port4.getreply(MyProc7: { reply_val } - value MyRecord2: { num := ?, str := reply_val }) - -> value (redir[0] := @decoded("UTF-8") str) - param (redir[1] := @decoded(str_enc16) x) { - if (redir[0] != unichar2oct(reply_val, "UTF-8")) { - setverdict(fail, "Getreply parameter redirect failed: ", redir[0]); - } - if (redir[1] != unichar2oct(reply_val, str_enc16)) { - setverdict(fail, "Getreply value redirect failed: ", redir[1]); - } - } - [] Port4.getreply(MyProc7: { decmatch(str_enc16) MyOctetstring: ? length (16) } value MyRecord2: ?) { - setverdict(fail, "Invalid getreply return value."); - } - [] Port4.getreply(MyProc7: { ? } value MyRecord2: ?) { - setverdict(fail, "Invalid getreply parameter."); - } - [] Port4.catch(MyProc7, MyRecord2: ?) { - setverdict(fail, "Exception (MyRecord2) caught in getreply test."); - } - [] Port4.catch(MyProc7, MyRecord3: ?) { - setverdict(fail, "Exception (MyRecord3) caught in getreply test."); - } - [] Port4.catch(timeout) { setverdict(fail, "Getreply test timed out."); } - } - - // testing (exception) value redirect in catch: - timer tmr := 1.0; - tmr.start; - alt { - [] Port4.catch(MyProc7, MyRecord2: { num := ?, str := reply_val }) - -> value (redir[2] := @decoded(str_enc32) str) { - if (redir[2] != unichar2oct(reply_val, str_enc32)) { - setverdict(fail, "Exception value redirect failed: ", redir[2]); - } - } - [] Port4.catch(MyProc7, MyRecord2: ?) { - setverdict(fail, "Invalid exception value caught."); - } - [] Port4.catch(MyProc7, MyRecord3: ?) { - setverdict(fail, "Invalid type of exception caught."); - } - [] Port4.getreply(MyProc7: { ? } value MyRecord2: ?) { - setverdict(fail, "Reply received in exception test."); - } - [] tmr.timeout { setverdict(fail, "Exception test timed out."); } - } - setverdict(pass); -} - -// additional tests for decoded parameter and value redirects -// (in these tests the value and parameter redirects with the '@decoded' modifier -// are optimized to reuse the decoding result in the 'decmatch' template instead of -// decoding the same string twice) -function DecodedRedirect2_behav(in MyRecord2 val, in universal charstring reply_val) runs on ProcComponent4 { - timer tmr := 1.0; - var MyRecord2 redir; - - // testing parameter redirect in getcall: - tmr.start; - alt { - [] Port4.getcall(MyProc7: { decmatch("UTF-8") MyRecord2: val }) -> param (redir := @decoded x) { - if (redir != val) { setverdict(fail, "Getcall parameter redirect failed: ", redir); } - else { - var MyRecord2 reply_rec := { num := -1, str := reply_val }; - Port4.reply(MyProc7: { reply_val } value reply_rec); - Port4.raise(MyProc7, reply_rec); - } - } - [] Port4.getcall(MyProc7: { ? }) { setverdict(fail, "Invalid getcall parameter."); } - [] tmr.timeout { setverdict(fail, "Getcall timed out."); } - } -} - -testcase tc_DecodedRedirect2() runs on ProcComponent4 { - var ProcComponent4 ct := ProcComponent4.create; - connect(ct:Port4, mtc:Port4); - var MyRecord2 val := { num := 4, str := "stuff" }; - // use this string instead of an actual encoded value for reply/getreply and raise/catch, - // because finding a value that can be encoded with UTF-16 or UTF-32 is difficult - // (after this string is decoded into an octetstring, only the octetstring's length is matched) - var universal charstring reply_val := "payload"; - ct.start(DecodedRedirect2_behav(val, reply_val)); - var universal charstring val_enc := encvalue_unichar(val); - var MyOctetstring redir[3]; - // these encoding strings are not known at compile-time (the code generated for them is different) - var charstring str_enc8 := "UTF-8", str_enc16 := "UTF-16", str_enc32 := "UTF-32LE"; - - // testing parameter and (return) value redirect in getreply: - Port4.call(MyProc7: { val_enc }, 1.0) { - [] Port4.getreply(MyProc7: { decmatch(str_enc16) MyOctetstring: ? length (16) } - value MyRecord2: { num := ?, str := decmatch(str_enc8) MyOctetstring: ? length (7) }) - -> value (redir[0] := @decoded("UTF-8") str) - param (redir[1] := @decoded(str_enc16) x) { - if (redir[0] != unichar2oct(reply_val, "UTF-8")) { - setverdict(fail, "Getreply parameter redirect failed: ", redir[0]); - } - if (redir[1] != unichar2oct(reply_val, str_enc16)) { - setverdict(fail, "Getreply value redirect failed: ", redir[1]); - } - } - [] Port4.getreply(MyProc7: { decmatch(str_enc16) MyOctetstring: ? length (16) } value MyRecord2: ?) { - setverdict(fail, "Invalid getreply return value."); - } - [] Port4.getreply(MyProc7: { ? } value MyRecord2: ?) { - setverdict(fail, "Invalid getreply parameter."); - } - [] Port4.catch(MyProc7, MyRecord2: ?) { - setverdict(fail, "Exception (MyRecord2) caught in getreply test."); - } - [] Port4.catch(MyProc7, MyRecord3: ?) { - setverdict(fail, "Exception (MyRecord3) caught in getreply test."); - } - [] Port4.catch(timeout) { setverdict(fail, "Getreply test timed out."); } - } - - // testing (exception) value redirect in catch: - timer tmr := 1.0; - tmr.start; - alt { - [] Port4.catch(MyProc7, MyRecord2: { num := ?, str := decmatch("UTF-32LE") MyOctetstring: ? length(32) }) - -> value (redir[2] := @decoded(str_enc32) str) { - if (redir[2] != unichar2oct(reply_val, str_enc32)) { - setverdict(fail, "Exception value redirect failed: ", redir[2]); - } - } - [] Port4.catch(MyProc7, MyRecord2: ?) { - setverdict(fail, "Invalid exception value caught."); - } - [] Port4.catch(MyProc7, MyRecord3: ?) { - setverdict(fail, "Invalid type of exception caught."); - } - [] Port4.getreply(MyProc7: { ? } value MyRecord2: ?) { - setverdict(fail, "Reply received in exception test."); - } - [] tmr.timeout { setverdict(fail, "Exception test timed out."); } - } - setverdict(pass); -} - -// further tests for decoded parameter and value redirects -// (in these tests the 'decmatch' templates cannot be identified at compile-time, -// so the decision of whether to decode the redirected value again or use the -// decoding result in the matched template is made at runtime) -function DecodedRedirect3_behav(in MyRecord2 val) runs on ProcComponent4 { - timer tmr := 1.0; - var MyRecord2 redir; - var template MyProc7 vt_proc7 := { x := decmatch MyRecord2: val }; - - // testing parameter redirect in getcall: - tmr.start; - alt { - [] Port4.getcall(vt_proc7) -> param (redir := @decoded x) { - if (redir != val) { setverdict(fail, "Getcall parameter redirect failed: ", redir); } - else { - var universal charstring val_enc := encvalue_unichar(val); - var MyRecord2 reply_val := { num := val.num, str := val_enc }; - var MyRecord3 raise_val := { elems := { reply_val } }; - Port4.reply(MyProc7: { val_enc } value reply_val); - Port4.raise(MyProc7, raise_val); - } - } - [] Port4.getcall(MyProc7: { ? }) { setverdict(fail, "Invalid getcall parameter."); } - [] tmr.timeout { setverdict(fail, "Getcall timed out."); } - } -} - -testcase tc_DecodedRedirect3() runs on ProcComponent4 { - var ProcComponent4 ct := ProcComponent4.create; - connect(ct:Port4, mtc:Port4); - var MyRecord2 val := { num := 4, str := "stuff" }; - ct.start(DecodedRedirect3_behav(val)); - var universal charstring val_enc := encvalue_unichar(val); - var MyRecord2 redir[3]; - var template MyRecord2 vt_rec2 := { num := ?, str := decmatch MyRecord2: val }; - var charstring str_enc8 := "UTF-8"; - - // testing parameter and (return) value redirect in getreply: - Port4.call(MyProc7: { val_enc }, 1.0) { - [] Port4.getreply(MyProc7TemplatePard(decmatch MyRecord2: val) - value modifies vt_rec2 := { num := val.num }) - -> value (redir[0] := @decoded str) - param (redir[1] := @decoded(str_enc8) x) { - if (redir[0] != val) { - setverdict(fail, "Getreply parameter redirect failed: ", redir[0]); - } - if (redir[1] != val) { - setverdict(fail, "Getreply value redirect failed: ", redir[1]); - } - } - [] Port4.getreply(MyProc7TemplatePard(decmatch MyRecord2: val) value MyRecord2: ?) { - setverdict(fail, "Invalid getreply return value."); - } - [] Port4.getreply(MyProc7: { ? } value MyRecord2: ?) { - setverdict(fail, "Invalid getreply parameter."); - } - [] Port4.catch(MyProc7, MyRecord2: ?) { - setverdict(fail, "Exception (MyRecord2) caught in getreply test."); - } - [] Port4.catch(MyProc7, MyRecord3: ?) { - setverdict(fail, "Exception (MyRecord3) caught in getreply test."); - } - [] Port4.catch(timeout) { setverdict(fail, "Getreply test timed out."); } - } - - // testing (exception) value redirect in catch: - timer tmr := 1.0; - tmr.start; - alt { - [] Port4.catch(MyProc7, MyRecord3: { elems := { vt_rec2 } }) - -> value (redir[2] := @decoded(str_enc8) elems[0].str) { - if (redir[2] != val) { - setverdict(fail, "Exception value redirect failed: ", redir[2]); - } - } - [] Port4.catch(MyProc7, MyRecord3: ?) { - setverdict(fail, "Invalid exception value caught."); - } - [] Port4.catch(MyProc7, MyRecord2: ?) { - setverdict(fail, "Invalid type of exception caught."); - } - [] Port4.getreply(MyProc7: { ? } value MyRecord2: ?) { - setverdict(fail, "Reply received in exception test."); - } - [] tmr.timeout { setverdict(fail, "Exception test timed out."); } - } - setverdict(pass); -} - -// even more tests for decoded parameter and value redirects -// (in these tests the sent/received strings are decoded into 2 different types: -// the matching 'decmatch' templates decode the strings into MyRecord2, while the -// value and parameter redirects decode the string into MyRecord4) -function DecodedRedirect4_behav(in MyRecord2 val2, in MyRecord4 val4) runs on ProcComponent4 { - timer tmr := 1.0; - var MyRecord4 redir; - - // testing parameter redirect in getcall: - tmr.start; - alt { - [] Port4.getcall(MyProc7: { decmatch MyRecord2: val2 }) -> param (redir := @decoded x) { - if (redir != val4) { - setverdict(fail, "Getcall parameter redirect failed: ", redir); - } - else { - var universal charstring val_enc := encvalue_unichar(val2); - var MyRecord2 reply_val := { num := val2.num, str := val_enc }; - var MyRecord3 raise_val := { elems := { reply_val } }; - Port4.reply(MyProc7: { val_enc } value reply_val); - Port4.raise(MyProc7, raise_val); - } - } - [] Port4.getcall(MyProc7: { ? }) { setverdict(fail, "Invalid getcall parameter."); } - [] tmr.timeout { setverdict(fail, "Getcall timed out."); } - } -} - -testcase tc_DecodedRedirect4() runs on ProcComponent4 { - var ProcComponent4 ct := ProcComponent4.create; - connect(ct:Port4, mtc:Port4); - var MyRecord2 val2 := { num := 4, str := "ADDC" }; - var MyRecord4 val4 := { attr := "4", val := 'ADDC'O }; - ct.start(DecodedRedirect4_behav(val2, val4)); - var universal charstring val_enc := encvalue_unichar(val2); - var MyRecord4 redir[3]; - - // testing parameter and (return) value redirect in getreply: - Port4.call(MyProc7: { val_enc }, 1.0) { - [] Port4.getreply(MyProc7TemplatePard(decmatch MyRecord2: val2) - value MyRecord2: { num := ?, str := decmatch MyRecord2: val2 }) - -> value (redir[0] := @decoded str) - param (redir[1] := @decoded x) { - if (redir[0] != val4) { - setverdict(fail, "Getreply parameter redirect failed: ", redir[0]); - } - if (redir[1] != val4) { - setverdict(fail, "Getreply value redirect failed: ", redir[1]); - } - } - [] Port4.getreply(MyProc7TemplatePard(decmatch MyRecord2: val2) value MyRecord2: ?) { - setverdict(fail, "Invalid getreply return value."); - } - [] Port4.getreply(MyProc7: { ? } value MyRecord2: ?) { - setverdict(fail, "Invalid getreply parameter."); - } - [] Port4.catch(MyProc7, MyRecord2: ?) { - setverdict(fail, "Exception (MyRecord2) caught in getreply test."); - } - [] Port4.catch(MyProc7, MyRecord3: ?) { - setverdict(fail, "Exception (MyRecord3) caught in getreply test."); - } - [] Port4.catch(timeout) { setverdict(fail, "Getreply test timed out."); } - } - - // testing (exception) value redirect in catch: - var template MyRecord3 vt_rec3 := { elems := { { num := ?, str := decmatch MyRecord2: val2 } } }; - timer tmr := 1.0; - tmr.start; - alt { - [] Port4.catch(MyProc7, vt_rec3) -> value (redir[2] := @decoded elems[0].str) { - if (redir[2] != val4) { - setverdict(fail, "Exception value redirect failed: ", redir[2]); - } - } - [] Port4.catch(MyProc7, MyRecord3: ?) { - setverdict(fail, "Invalid exception value caught."); - } - [] Port4.catch(MyProc7, MyRecord2: ?) { - setverdict(fail, "Invalid type of exception caught."); - } - [] Port4.getreply(MyProc7: { ? } value MyRecord2: ?) { - setverdict(fail, "Reply received in exception test."); - } - [] tmr.timeout { setverdict(fail, "Exception test timed out."); } - } - setverdict(pass); -} - // '*' is not allowed as a matching template for the return value // in getreply operations or for the exception in catch operations testcase tc_MatchingWithAnyOrOmit() runs on ProcComponent5 { @@ -1189,11 +796,6 @@ control { execute(tc_PortAddress_external_usage1()); execute(tc_PortAddress_external_usage2()); execute(tc_GetReplyParameters()); - execute(tc_MultiValueRedirect()); - execute(tc_DecodedRedirect()); - execute(tc_DecodedRedirect2()); - execute(tc_DecodedRedirect3()); - execute(tc_DecodedRedirect4()); execute(tc_MatchingWithAnyOrOmit()); } } diff --git a/regression_test/commProcedure/config-rt2.cfg b/regression_test/commProcedure/config-rt2.cfg new file mode 100644 index 0000000000000000000000000000000000000000..8b77999383489d62ec78e983087d9601a066e68d --- /dev/null +++ b/regression_test/commProcedure/config-rt2.cfg @@ -0,0 +1,14 @@ +############################################################################### +# Copyright (c) 2000-2016 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: +# Baranyi, Botond +# +############################################################################### +[EXECUTE] +ProcPort +AdvancedRedirects diff --git a/regression_test/commProcedure/config.cfg b/regression_test/commProcedure/config.cfg new file mode 100644 index 0000000000000000000000000000000000000000..c9d10a0db3387816e1ac1c1af80157ebc43fb29b --- /dev/null +++ b/regression_test/commProcedure/config.cfg @@ -0,0 +1,13 @@ +############################################################################### +# Copyright (c) 2000-2016 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: +# Baranyi, Botond +# +############################################################################### +[EXECUTE] +ProcPort diff --git a/usrguide/referenceguide.doc b/usrguide/referenceguide.doc index b59bc15c0d7ad0dd19ec9c7e706702660face78e..8ea53900bc2bd194e7a98164c167d141472662ad 100644 Binary files a/usrguide/referenceguide.doc and b/usrguide/referenceguide.doc differ