From 7bec2f701381d27b1a0e71247b617f82d8aa9857 Mon Sep 17 00:00:00 2001 From: BenceJanosSzabo <bence.janos.szabo@ericsson.com> Date: Tue, 18 Oct 2016 10:53:50 +0200 Subject: [PATCH] Fixed embed values are incorreclty encoded and decoded in record of records (Bug 505692) Change-Id: I906e70839019de512f79b0dc4139a02ba95480df Signed-off-by: BenceJanosSzabo <bence.janos.szabo@ericsson.com> --- compiler2/record.c | 42 +++++- compiler2/record_of.c | 3 +- core2/Basetype2.cc | 26 +++- .../XML/TTCNandXML/EmbedValues.ttcnpp | 140 +++++++++++++++++- 4 files changed, 201 insertions(+), 10 deletions(-) diff --git a/compiler2/record.c b/compiler2/record.c index 66e70ef82..fea74106c 100644 --- a/compiler2/record.c +++ b/compiler2/record.c @@ -1915,7 +1915,7 @@ void gen_xer(const struct_def *sdef, char **pdef, char **psrc) /* * * * * * * * * * XER_encode * * * * * * * * * * * * * * */ src = mputprintf(src, "int %s::XER_encode(const XERdescriptor_t& p_td, " - "TTCN_Buffer& p_buf, unsigned int p_flavor, int p_indent, embed_values_enc_struct_t*) const\n" + "TTCN_Buffer& p_buf, unsigned int p_flavor, int p_indent, embed_values_enc_struct_t* emb_val_parent) const\n" "{\n" " if (!is_bound()) TTCN_EncDec_ErrorContext::error" "(TTCN_EncDec::ET_UNBOUND, \"Encoding an unbound value.\");\n" @@ -2076,7 +2076,7 @@ void gen_xer(const struct_def *sdef, char **pdef, char **psrc) /* If the first component is a record-of with ANY-ATTRIBUTES, * it has been taken care of because it looked like an EMBED-VALUES */ if (i==0 && sdef->xerEmbedValuesPossible && (sdef->elements[i].xerAnyKind & ANY_ATTRIB_BIT)) continue ; - src = mputprintf(src, + src = mputprintf(src, " ec_1.set_msg(\"%s': \");\n" " tmp_len = field_%s.XER_encode(%s_xer_, p_buf, p_flavor, p_indent+1, 0);\n" " %ssub_len += tmp_len;\n" /* do not add if attribute and EXER */ @@ -2288,6 +2288,29 @@ void gen_xer(const struct_def *sdef, char **pdef, char **psrc) " ec_1.set_msg(\"%s': \");\n" , sdef->elements[i].dispname ); + if (i > start_at + num_attributes) { // First field's embed value is already processed + src = mputprintf(src, + "if (e_xer && (p_td.xer_bits & UNTAGGED && !(p_td.xer_bits & EMBED_VALUES) && 0 != emb_val_parent\n" + " %s%s%s)) {\n" + " if (0 != emb_val_parent->embval_array_reg) {\n" + " if (emb_val_parent->embval_index < emb_val_parent->embval_array_reg->size_of()) {\n" + " (*emb_val_parent->embval_array_reg)[emb_val_parent->embval_index].XER_encode(UNIVERSAL_CHARSTRING_xer_" + " , p_buf, p_flavor | EMBED_VALUES, p_indent+1, 0);\n" + " ++emb_val_parent->embval_index;\n" + " }\n" + " } else {\n" + " if (emb_val_parent->embval_index < emb_val_parent->embval_array_opt->size_of()) {\n" + " (*emb_val_parent->embval_array_opt)[emb_val_parent->embval_index].XER_encode(UNIVERSAL_CHARSTRING_xer_" + " , p_buf, p_flavor | EMBED_VALUES, p_indent+1, 0);\n" + " ++emb_val_parent->embval_index;\n" + " }\n" + " }\n" + "}\n" + , sdef->elements[0].isOptional ? "&& field_" : "" + , sdef->elements[0].isOptional ? sdef->elements[0].name : "" + , sdef->elements[0].isOptional ? ".ispresent()" : "" + ); + } src = mputprintf(src, " sub_len += field_%s.XER_encode(%s_xer_, p_buf, p_flavor%s, p_indent+!omit_tag, %s);\n" , sdef->elements[i].name, sdef->elements[i].typegen @@ -2383,7 +2406,7 @@ void gen_xer(const struct_def *sdef, char **pdef, char **psrc) src = mputprintf(src, /* XERSTUFF decodegen for record/SEQUENCE*/ "int %s::XER_decode(const XERdescriptor_t& p_td, XmlReaderWrap& p_reader," - " unsigned int p_flavor, unsigned int p_flavor2, embed_values_dec_struct_t*)\n" + " unsigned int p_flavor, unsigned int p_flavor2, embed_values_dec_struct_t* emb_val_parent)\n" "{\n" /* Remove XER_LIST, XER_RECOF from p_flavor. This is not required * for is_exer (which tests another bit), but for subsequent code. */ @@ -2969,6 +2992,19 @@ void gen_xer(const struct_def *sdef, char **pdef, char **psrc) " ec_1.set_msg(\"%s': \");\n" , sdef->elements[i].dispname); + src = mputprintf(src, + " if (p_td.xer_bits & UNTAGGED && 0 != emb_val_parent) {\n" + " if (p_reader.NodeType() == XML_READER_TYPE_TEXT) {\n" + " UNIVERSAL_CHARSTRING emb_ustr((const char*)p_reader.Value());\n" + " if (0 != emb_val_parent->embval_array_reg) {\n" + " (*emb_val_parent->embval_array_reg)[emb_val_parent->embval_index] = emb_ustr;\n" + " } else {\n" + " (*emb_val_parent->embval_array_opt)[emb_val_parent->embval_index] = emb_ustr;\n" + " }\n" + " ++emb_val_parent->embval_index;\n" + " }\n" + " }\n"); + if ( (sdef->elements[i].xerAnyKind & ANY_ELEM_BIT) && !strcmp(sdef->elements[i].type,"UNIVERSAL_CHARSTRING") ) { // In case the field is an optional anyElement -> check if it should be omitted diff --git a/compiler2/record_of.c b/compiler2/record_of.c index 0e8fc1ab3..eef45b375 100644 --- a/compiler2/record_of.c +++ b/compiler2/record_of.c @@ -1506,7 +1506,7 @@ void defRecordOfClass1(const struct_of_def *sdef, output_struct *output) /* The call to the non-const operator[] creates the element */ " (*this)[val_ptr->n_elements].XER_decode(*p_td.oftype_descr, p_reader, p_flavor, p_flavor2, emb_val);\n" " }\n" - " if (0 != emb_val && !own_tag && val_ptr->n_elements > 1) {\n" + " if (0 != emb_val && !own_tag && val_ptr->n_elements > 1 && !(p_td.oftype_descr->xer_bits & UNTAGGED)) {\n" " ++emb_val->embval_index;\n" " }\n" " }\n" @@ -1527,6 +1527,7 @@ void defRecordOfClass1(const struct_of_def *sdef, output_struct *output) " (*emb_val->embval_array_opt)[emb_val->embval_index] = emb_ustr;\n" " }\n" " rd_ok = p_reader.Read();\n" + " if (p_td.oftype_descr->xer_bits & UNTAGGED) ++emb_val->embval_index;\n" " }\n" " else {\n" " rd_ok = p_reader.Read();\n" diff --git a/core2/Basetype2.cc b/core2/Basetype2.cc index 9248c4b83..50e3acaba 100644 --- a/core2/Basetype2.cc +++ b/core2/Basetype2.cc @@ -2400,7 +2400,7 @@ int Record_Of_Type::XER_decode(const XERdescriptor_t& p_td, /* The call to the non-const get_at() creates the element */ get_at(get_nof_elements())->XER_decode(*p_td.oftype_descr, reader, flavor, flavor2, emb_val); } - if (0 != emb_val && !own_tag && get_nof_elements() > 1) { + if (0 != emb_val && !own_tag && get_nof_elements() > 1 && !(p_td.oftype_descr->xer_bits & UNTAGGED)) { ++emb_val->embval_index; } } @@ -2413,11 +2413,12 @@ int Record_Of_Type::XER_decode(const XERdescriptor_t& p_td, reader.Read(); // move forward one last time } break; - } + } else if (XML_READER_TYPE_TEXT == type && 0 != emb_val && !own_tag && get_nof_elements() > 0) { UNIVERSAL_CHARSTRING emb_ustr((const char*)reader.Value()); emb_val->embval_array->get_at(emb_val->embval_index)->set_value(&emb_ustr); success = reader.Read(); + if (p_td.oftype_descr->xer_bits & UNTAGGED) ++emb_val->embval_index; } else { success = reader.Read(); @@ -4114,7 +4115,7 @@ int Record_Type::get_index_byname(const char *name, const char *uri) const { } int Record_Type::XER_encode(const XERdescriptor_t& p_td, TTCN_Buffer& p_buf, - unsigned int flavor, int indent, embed_values_enc_struct_t*) const + unsigned int flavor, int indent, embed_values_enc_struct_t* emb_val_parent) const { if (err_descr) { return XER_encode_negtest(err_descr, p_td, p_buf, flavor, indent, 0); @@ -4414,7 +4415,13 @@ int Record_Type::XER_encode(const XERdescriptor_t& p_td, TTCN_Buffer& p_buf, uoe = use_order->get_at(i - begin); enm = static_cast<const Enum_Type *>(uoe); } - + if (p_td.xer_bits & UNTAGGED && i > 0 && exer && embed_values == NULL && 0 != emb_val_parent && + emb_val_parent->embval_index < emb_val_parent->embval_array->size_of()) { + emb_val_parent->embval_array->get_at(emb_val_parent->embval_index)->XER_encode(UNIVERSAL_CHARSTRING_xer_ + , p_buf, flavor | EMBED_VALUES, indent+1, 0); + ++emb_val_parent->embval_index; + } + // "actual" index, may be perturbed by USE-ORDER int ai = !(exer && (p_td.xer_bits & USE_ORDER)) ? i : enm->as_int() + useorder_base; @@ -5127,7 +5134,7 @@ int Record_Type::XER_encode_negtest(const Erroneous_descriptor_t* p_err_descr, } int Record_Type::XER_decode(const XERdescriptor_t& p_td, XmlReaderWrap& reader, - unsigned int flavor, unsigned int flavor2, embed_values_dec_struct_t*) + unsigned int flavor, unsigned int flavor2, embed_values_dec_struct_t* emb_val_parent) { int exer = is_exer(flavor); int success, type; @@ -5601,6 +5608,15 @@ int Record_Type::XER_decode(const XERdescriptor_t& p_td, XmlReaderWrap& reader, ++emb_val->embval_index; } last_embval_index = emb_val->embval_index; + } else if (p_td.xer_bits & UNTAGGED && 0 != emb_val_parent) { + if (reader.NodeType()==XML_READER_TYPE_TEXT) { + UNIVERSAL_CHARSTRING emb_ustr((const char*)reader.Value()); + emb_val_parent->embval_array->get_at(emb_val_parent->embval_index)->set_value(&emb_ustr); + } + if (last_embval_index == emb_val_parent->embval_index) { + ++emb_val_parent->embval_index; + } + last_embval_index = emb_val_parent->embval_index; } ec_1.set_msg("%s': ", fld_name(i)); if (exer && i==field_cnt-1 && p_td.dfeValue && reader.IsEmptyElement()) { diff --git a/regression_test/XML/TTCNandXML/EmbedValues.ttcnpp b/regression_test/XML/TTCNandXML/EmbedValues.ttcnpp index 39e1fbaa8..134006836 100644 --- a/regression_test/XML/TTCNandXML/EmbedValues.ttcnpp +++ b/regression_test/XML/TTCNandXML/EmbedValues.ttcnpp @@ -389,6 +389,142 @@ testcase dec_emb_opt() runs on Embedder CHECK_DECODE(exer_dec_eo, estr_test2, EmOpt, expected); } + + +/****************** EMBED-VALUES and record of record fields untagged ******************/ + +type record EmbRecordOrRecordUntagged { + record of universal charstring embed, + record of record { + universal charstring a, + boolean b + } sequence_list +} +with { + variant "embedValues" + variant "element"; + variant (sequence_list) "untagged"; + variant (sequence_list[-]) "untagged"; +} + +DECLARE_XER_ENCODERS(EmbRecordOrRecordUntagged, erecofrecuntagged); +DECLARE_EXER_ENCODERS(EmbRecordOrRecordUntagged, erecofrecuntagged); + +const EmbRecordOrRecordUntagged c_testingrecofrecuntagged := { + embed := { "a1", "b1", "a2", "b2", "end" }, + sequence_list := { + { + a := "firsta", + b := false + }, + { + a := "seconda", + b := false + } + } +} + +const universal charstring bstr_test7 := +"<EmbRecordOrRecordUntagged>\n" & +"\t<embed>\n" & +"\t\t<UNIVERSAL_CHARSTRING>a1</UNIVERSAL_CHARSTRING>\n" & +"\t\t<UNIVERSAL_CHARSTRING>b1</UNIVERSAL_CHARSTRING>\n" & +"\t\t<UNIVERSAL_CHARSTRING>a2</UNIVERSAL_CHARSTRING>\n" & +"\t\t<UNIVERSAL_CHARSTRING>b2</UNIVERSAL_CHARSTRING>\n" & +"\t\t<UNIVERSAL_CHARSTRING>end</UNIVERSAL_CHARSTRING>\n" & +"\t</embed>\n" & +"\t<sequence_list>\n" & +"\t\t<SEQUENCE>\n" & +"\t\t\t<a>firsta</a>\n" & +"\t\t\t<b><false/></b>\n" & +"\t\t</SEQUENCE>\n" & +"\t\t<SEQUENCE>\n" & +"\t\t\t<a>seconda</a>\n" & +"\t\t\t<b><false/></b>\n" & +"\t\t</SEQUENCE>\n" & +"\t</sequence_list>\n" & +"</EmbRecordOrRecordUntagged>\n\n"; + +const universal charstring estr_test7 := +"<EmbRecordOrRecordUntagged>a1" & +"<a>firsta</a>b1"& +"<b>false</b>a2"& +"<a>seconda</a>b2"& +"<b>false</b>end"& +"</EmbRecordOrRecordUntagged>\n" + + +const universal charstring bstr_test8 := +"<EmbRecordOrRecordUntagged>\n"& +"\t<embed>\n"& +"\t\t<UNIVERSAL_CHARSTRING>first</UNIVERSAL_CHARSTRING>\n"& +"\t\t<UNIVERSAL_CHARSTRING>second</UNIVERSAL_CHARSTRING>\n"& +"\t\t<UNIVERSAL_CHARSTRING>third</UNIVERSAL_CHARSTRING>\n"& +"\t</embed>\n"& +"\t<sequence_list>\n"& +"\t\t<SEQUENCE>\n"& +"\t\t\t<a>firsta</a>\n"& +"\t\t\t<b><false/></b>\n"& +"\t\t</SEQUENCE>\n"& +"\t</sequence_list>\n"& +"</EmbRecordOrRecordUntagged>\n"& +"\n" + +const universal charstring estr_test8 := +"<EmbRecordOrRecordUntagged>first"& +"<a>firsta</a>second"& +"<b>false</b>third"& +"</EmbRecordOrRecordUntagged>\n" + +const universal charstring bstr_test9 := +"<EmbRecordOrRecordUntagged>\n"& +"\t<embed>\n"& +"\t\t<UNIVERSAL_CHARSTRING>first</UNIVERSAL_CHARSTRING>\n"& +"\t\t<UNIVERSAL_CHARSTRING/>\n"& +"\t</embed>\n"& +"\t<sequence_list/>\n"& +"</EmbRecordOrRecordUntagged>\n"& +"\n" + +const universal charstring estr_test9 := +"<EmbRecordOrRecordUntagged>first"& +"</EmbRecordOrRecordUntagged>\n" + +testcase enc_emb_record_of_record_untagged() runs on Embedder +{ + var EmbRecordOrRecordUntagged testing := c_testingrecofrecuntagged; + CHECK_METHOD(bxer_enc_erecofrecuntagged, testing, bstr_test7); + CHECK_METHOD(exer_enc_erecofrecuntagged, testing, estr_test7); + + testing.sequence_list := { { a := "firsta", b := false } } + testing.embed := {"first", "second", "third"} + CHECK_METHOD(bxer_enc_erecofrecuntagged, testing, bstr_test8); + CHECK_METHOD(exer_enc_erecofrecuntagged, testing, estr_test8); + + testing.sequence_list := { } + testing.embed := {"first", ""} + CHECK_METHOD(bxer_enc_erecofrecuntagged, testing, bstr_test9); + CHECK_METHOD(exer_enc_erecofrecuntagged, testing, estr_test9); +} + +testcase dec_emb_record_of_record_untagged() runs on Embedder +{ + var EmbRecordOrRecordUntagged expected := c_testingrecofrecuntagged; + CHECK_DECODE(bxer_dec_erecofrecuntagged, bstr_test7, EmbRecordOrRecordUntagged, expected); + CHECK_DECODE(exer_dec_erecofrecuntagged, estr_test7, EmbRecordOrRecordUntagged, expected); + + expected.sequence_list := { { a := "firsta", b := false } } + expected.embed := {"first", "second", "third"} + CHECK_DECODE(bxer_dec_erecofrecuntagged, bstr_test8, EmbRecordOrRecordUntagged, expected); + CHECK_DECODE(exer_dec_erecofrecuntagged, estr_test8, EmbRecordOrRecordUntagged, expected); + + expected.sequence_list := { } + expected.embed := {"first", ""} + CHECK_DECODE(bxer_dec_erecofrecuntagged, bstr_test9, EmbRecordOrRecordUntagged, expected); + CHECK_DECODE(exer_dec_erecofrecuntagged, estr_test9, EmbRecordOrRecordUntagged, expected); +} + + /********************** Control part **********************/ control { @@ -403,8 +539,10 @@ control { execute(enc_emb_opt()); execute(dec_emb_opt()); -} + execute(enc_emb_record_of_record_untagged()); + execute(dec_emb_record_of_record_untagged()); + } } with { encode "XML" -- GitLab