From d45057a96130063fa9d75c48cf4ca425d087b065 Mon Sep 17 00:00:00 2001 From: Adam Knapp Date: Tue, 5 Apr 2022 10:30:45 +0200 Subject: [PATCH 1/5] Lengthto semantic check update for bit- and octetstring (issue #554) Signed-off-by: Adam Knapp --- compiler2/Type.cc | 40 ++++++++++++++++--- .../TTCN3_SA_ttcn3adhoc_TD.script | 4 +- 2 files changed, 36 insertions(+), 8 deletions(-) diff --git a/compiler2/Type.cc b/compiler2/Type.cc index 3f59a33bc..2a0232760 100644 --- a/compiler2/Type.cc +++ b/compiler2/Type.cc @@ -2611,14 +2611,42 @@ namespace Common { case T_INT: case T_INT_A: break; + case T_BSTR: + case T_BSTR_A: + case T_OSTR: + if ((rawpar->fieldlength < 1 && ft->get_sub_type() == NULL) || + (rawpar->fieldlength < 1 && ft->get_sub_type()->get_length_restriction() < 1)) { + error("The length of `%s' field must be specified either with `length()` " + "subtyping or with the `FIELDLENGTH` attribute", + field_id.get_dispname().c_str()); + } + break; case T_CHOICE_T: case T_CHOICE_A: for (size_t fi = 0; fi < ft->get_nof_comps(); fi++) { - typetype_t uftt = ft->get_comp_byIndex(fi)->get_type() - ->get_typetype(); - if (uftt != T_INT && uftt != T_INT_A) - error("The union type LENGTHTO field must contain only " - "integer fields"); + Type *uft = ft->get_comp_byIndex(fi)->get_type(); + typetype_t uftt = uft->get_typetype(); + switch (uftt) { + case T_INT: + case T_INT_A: + break; + case T_BSTR: + case T_BSTR_A: + case T_OSTR: + if ((uft->rawattrib == NULL && ft->get_sub_type() == NULL) || + (uft->rawattrib == NULL && ft->get_sub_type()->get_length_restriction() < 1) || + (uft->rawattrib->fieldlength < 1 && ft->get_sub_type() == NULL) || + (uft->rawattrib->fieldlength < 1 && ft->get_sub_type()->get_length_restriction() < 1)) { + error("The length of `%s' field must be specified either with `length()` " + "subtyping or with the `FIELDLENGTH` attribute", + ft->get_comp_byIndex(fi)->get_name().get_dispname().c_str()); + } + break; + default: + error("The union type LENGTHTO field must contain only " + "integer, bitstring or octetstring fields"); + break; + } } break; case T_ANYTYPE: @@ -2630,7 +2658,7 @@ namespace Common { if (rawpar->lengthindex) break; // Will be checked in the next step. // Else continue with default. default: - error("The LENGTHTO field must be an integer or union type " + error("The LENGTHTO field must be an integer, bitstring, octetstring or union type " "instead of `%s'", ft->get_typename().c_str()); break; } diff --git a/function_test/Semantic_Analyser/TTCN3_SA_ttcn3adhoc_TD.script b/function_test/Semantic_Analyser/TTCN3_SA_ttcn3adhoc_TD.script index d2731de4a..4e2073434 100644 --- a/function_test/Semantic_Analyser/TTCN3_SA_ttcn3adhoc_TD.script +++ b/function_test/Semantic_Analyser/TTCN3_SA_ttcn3adhoc_TD.script @@ -7756,10 +7756,10 @@ type record myr5 { (?is)\berror: The union type LENGTHTO field must contain only integer fields -(?is)\berror: The LENGTHTO field must be an integer or union type instead of `\@Temp.mylist' +(?is)\berror: The LENGTHTO field must be an integer, bitstring, octetstring or union type instead of `\@Temp.mylist' -(?is)\berror: The LENGTHTO field must be an integer or union type instead of `charstring' +(?is)\berror: The LENGTHTO field must be an integer, bitstring, octetstring or union type instead of `charstring' (?is)\berror: -- GitLab From 3f3ebe946e4288724d2eede629726194bb9c7237 Mon Sep 17 00:00:00 2001 From: Adam Knapp Date: Tue, 5 Apr 2022 10:50:42 +0200 Subject: [PATCH 2/5] Lengthto codegen and runtime update for bit/octetstring (issue #554) Signed-off-by: Adam Knapp --- compiler2/record.c | 101 +++++++++++++++++++++++++------------------- core/Bitstring.cc | 16 +++++++ core/Bitstring.hh | 3 ++ core/Integer.hh | 2 + core/Octetstring.cc | 15 +++++++ core/Octetstring.hh | 3 ++ 6 files changed, 96 insertions(+), 44 deletions(-) diff --git a/compiler2/record.c b/compiler2/record.c index 956522295..6237c8a81 100644 --- a/compiler2/record.c +++ b/compiler2/record.c @@ -751,6 +751,9 @@ char* generate_raw_coding(char* src, } src = mputprintf(src, " if (myleaf.body.node.nodes[%lu]->body.node.nodes[%d]) {\n" + " myleaf.body.node.nodes[%lu]->body.node.nodes[%d] = " + "new RAW_enc_tree(TRUE, myleaf.body.node.nodes[%lu], " + "&(myleaf.body.node.nodes[%lu]->curr_pos), %d, %s_descr_.raw);\n" " myleaf.body.node.nodes[%lu]->body.node.nodes[%d]->" "calc = CALC_LENGTH;\n" " myleaf.body.node.nodes[%lu]->body.node.nodes[%d]->" @@ -766,6 +769,9 @@ char* generate_raw_coding(char* src, "init_lengthto_fields_list(%d);\n", (unsigned long)i, sdef->elements[i].raw.lengthindex->nthfield, (unsigned long)i, sdef->elements[i].raw.lengthindex->nthfield, + (unsigned long)i, (unsigned long)i, + sdef->elements[i].raw.lengthindex->nthfield, sdef->elements[i].raw.lengthindex->typedescr, + (unsigned long)i, sdef->elements[i].raw.lengthindex->nthfield, (unsigned long)i, sdef->elements[i].raw.lengthindex->nthfield, sdef->elements[i].raw.lengthindex->typedescr, (unsigned long)i, sdef->elements[i].raw.lengthindex->nthfield, @@ -823,9 +829,16 @@ char* generate_raw_coding(char* src, " int sel_field = 0;\n" " while (myleaf.body.node.nodes[%lu]->body.node.nodes[sel_field] == NULL) " "{ sel_field++; }\n" + " const TTCN_Typedescriptor_t* tmpTypeDesc = myleaf.body.node.nodes[%lu]->" + "body.node.nodes[sel_field]->coding_descr;\n" + " myleaf.body.node.nodes[%lu]->body.node.nodes[sel_field] = " + "new RAW_enc_tree(TRUE, myleaf.body.node.nodes[%lu], " + "&(myleaf.body.node.nodes[%lu]->curr_pos), sel_field, tmpTypeDesc->raw);\n" " myleaf.body.node.nodes[%lu]->body.node.nodes[sel_field]->" "calc = CALC_LENGTH;\n" " myleaf.body.node.nodes[%lu]->body.node.nodes[sel_field]->" + "coding_descr = tmpTypeDesc;\n" + " myleaf.body.node.nodes[%lu]->body.node.nodes[sel_field]->" "calcof.lengthto.num_of_fields = %d;\n" " myleaf.body.node.nodes[%lu]->body.node.nodes[sel_field]->" "calcof.lengthto.unit = %d;\n" @@ -833,7 +846,8 @@ char* generate_raw_coding(char* src, "calcof.lengthto.offset = %d;\n" " myleaf.body.node.nodes[%lu]->body.node.nodes[sel_field]->" "calcof.lengthto.fields = init_lengthto_fields_list(%d);\n", - (unsigned long)i,(unsigned long)i, + (unsigned long)i,(unsigned long)i,(unsigned long)i,(unsigned long)i, + (unsigned long)i,(unsigned long)i,(unsigned long)i, (unsigned long)i,sdef->elements[i].raw.lengthto_num, (unsigned long)i,sdef->elements[i].raw.unit, (unsigned long)i,sdef->elements[i].raw.lengthto_offset, @@ -5636,23 +5650,20 @@ static char *genRawDecodeRecordField(char *src, const struct_def *sdef, ,sdef->elements[i].raw.lengthindex->nthfieldname ); } + src = mputprintf(src, " INTEGER tmp = field_%s%s.%s%s().convert_to_Integer(%s_descr_);\n", + sdef->elements[i].name, sdef->elements[i].isOptional ? "()" : "", + sdef->elements[i].raw.lengthindex->nthfieldname, + sdef->elements[i].raw.lengthindex->fieldtype == OPTIONAL_FIELD ? "()" : "", + sdef->elements[i].raw.lengthindex->typedescr); if (sdef->elements[i].raw.lengthto_offset != 0) { - src = mputprintf(src, " field_%s%s.%s%s() = field_%s%s.%s%s() - %d;\n", - sdef->elements[i].name, sdef->elements[i].isOptional ? "()" : "", - sdef->elements[i].raw.lengthindex->nthfieldname, - sdef->elements[i].raw.lengthindex->fieldtype == OPTIONAL_FIELD ? "()" : "", - sdef->elements[i].name, sdef->elements[i].isOptional ? "()" : "", - sdef->elements[i].raw.lengthindex->nthfieldname, - sdef->elements[i].raw.lengthindex->fieldtype == OPTIONAL_FIELD ? "()" : "", - sdef->elements[i].raw.lengthto_offset); + src = mputprintf(src, " tmp = tmp - %d;\n", sdef->elements[i].raw.lengthto_offset); } - src=mputprintf(src, - " value_of_length_field%d+=field_%s%s.%s%s().get_long_long_val()*%d;\n" - ,i,sdef->elements[i].name,sdef->elements[i].isOptional?"()":"" - ,sdef->elements[i].raw.lengthindex->nthfieldname - ,sdef->elements[i].raw.lengthindex->fieldtype == OPTIONAL_FIELD?"()":"" - ,sdef->elements[i].raw.unit==-1?1:sdef->elements[i].raw.unit - ); + src = mputprintf(src, " field_%s%s.%s%s() = tmp;\n", + sdef->elements[i].name, sdef->elements[i].isOptional ? "()" : "", + sdef->elements[i].raw.lengthindex->nthfieldname, + sdef->elements[i].raw.lengthindex->fieldtype == OPTIONAL_FIELD ? "()" : ""); + src = mputprintf(src, " value_of_length_field%d += tmp.get_long_long_val() * %d;\n", + i, sdef->elements[i].raw.unit == -1 ? 1 : sdef->elements[i].raw.unit); if(sdef->elements[i].raw.lengthindex->fieldtype == OPTIONAL_FIELD){ src=mputstr(src, " }\n" @@ -5662,41 +5673,43 @@ static char *genRawDecodeRecordField(char *src, const struct_def *sdef, else if(sdef->elements[i].raw.union_member_num){ int m; src = mputprintf(src, " switch (field_%s%s.get_selection()) {\n", - sdef->elements[i].name, sdef->elements[i].isOptional ? "()" : ""); + sdef->elements[i].name, sdef->elements[i].isOptional ? "()" : ""); for (m = 1; m < sdef->elements[i].raw.union_member_num + 1; m++) { - src = mputprintf(src, " case %s%s%s:\n", sdef->elements[i].raw.member_name[0], - "::ALT_", sdef->elements[i].raw.member_name[m]); - if (sdef->elements[i].raw.lengthto_offset != 0) { - src = mputprintf(src, " field_%s%s.%s() = field_%s%s.%s() - %d;\n", - sdef->elements[i].name, - sdef->elements[i].isOptional ? "()" : "", - sdef->elements[i].raw.member_name[m], sdef->elements[i].name, - sdef->elements[i].isOptional ? "()" : "", - sdef->elements[i].raw.member_name[m], sdef->elements[i].raw.lengthto_offset); - } - src = mputprintf(src, - " value_of_length_field%d += field_%s%s.%s().get_long_long_val() * %d;\n" - " break;\n", i, sdef->elements[i].name, - sdef->elements[i].isOptional ? "()" : "", - sdef->elements[i].raw.member_name[m], - sdef->elements[i].raw.unit == -1 ? 1 : sdef->elements[i].raw.unit); + src = mputprintf(src, " case %s%s%s: {\n", sdef->elements[i].raw.member_name[0], + "::ALT_", sdef->elements[i].raw.member_name[m]); + src = mputprintf(src, " INTEGER tmp%d = field_%s%s.%s().convert_to_Integer(%s_%s_descr_);\n", + m, sdef->elements[i].name, sdef->elements[i].isOptional ? "()" : "", + sdef->elements[i].raw.member_name[m], sdef->elements[i].type, + sdef->elements[i].raw.member_name[m]); + if (sdef->elements[i].raw.lengthto_offset != 0) { + src = mputprintf(src, " tmp%d = tmp%d - %d;\n", + m, m, sdef->elements[i].raw.lengthto_offset); + } + src = mputprintf(src, " field_%s%s.%s() = tmp%d;\n", + sdef->elements[i].name, sdef->elements[i].isOptional ? "()" : "", + sdef->elements[i].raw.member_name[m], m); + src = mputprintf(src, + " value_of_length_field%d += tmp%d.get_long_long_val() * %d;\n" + " break; }\n", + i, m, sdef->elements[i].raw.unit == -1 ? 1 : sdef->elements[i].raw.unit); } src = mputprintf(src, " default:\n" - " value_of_length_field%d = 0;\n" - " }\n", i); + " value_of_length_field%d = 0;\n" + " }\n", i); } else{ + src = mputprintf(src, " INTEGER tmp%d = field_%s%s.convert_to_Integer(%s_descr_);\n", + i, sdef->elements[i].name, + sdef->elements[i].isOptional ? "()" : "", sdef->elements[i].typedescrname); if (sdef->elements[i].raw.lengthto_offset != 0) { - src = mputprintf(src, " field_%s%s = field_%s%s - %d;\n", - sdef->elements[i].name, sdef->elements[i].isOptional ? "()" : "", - sdef->elements[i].name, sdef->elements[i].isOptional ? "()" : "", - sdef->elements[i].raw.lengthto_offset); + src = mputprintf(src, " tmp%d = tmp%d - %d;\n", + i, i, sdef->elements[i].raw.lengthto_offset); } - src=mputprintf(src, - " value_of_length_field%d+=field_%s%s.get_long_long_val()*%d;\n" - ,i,sdef->elements[i].name,sdef->elements[i].isOptional?"()":"" - ,sdef->elements[i].raw.unit==-1?1:sdef->elements[i].raw.unit - ); + src = mputprintf(src, " field_%s%s = tmp%d;\n", + sdef->elements[i].name, sdef->elements[i].isOptional ? "()" : "", i); + src = mputprintf(src, + " value_of_length_field%d += tmp%d.get_long_long_val() * %d;\n", + i, i, sdef->elements[i].raw.unit == -1 ? 1 : sdef->elements[i].raw.unit); } } if(raw_options[i].pointerto){ /* store the start of pointed field*/ diff --git a/core/Bitstring.cc b/core/Bitstring.cc index 70a2b39ea..5bc0e6618 100644 --- a/core/Bitstring.cc +++ b/core/Bitstring.cc @@ -164,6 +164,11 @@ BITSTRING& BITSTRING::operator=(const BITSTRING_ELEMENT& other_value) return *this; } +BITSTRING& BITSTRING::operator=(const INTEGER& other_value) +{ + return this->operator=(int2bit(other_value, val_ptr->n_bits)); +} + boolean BITSTRING::operator==(const BITSTRING& other_value) const { must_bound("Unbound left operand of bitstring comparison."); @@ -559,6 +564,17 @@ void BITSTRING::log() const } else TTCN_Logger::log_event_unbound(); } +INTEGER BITSTRING::convert_to_Integer(const TTCN_Typedescriptor_t& p_td) +{ + TTCN_EncDec_ErrorContext ec("While converting to integer type '%s': ", p_td.name); + TTCN_Buffer ttcn_buf; + encode(p_td, ttcn_buf, TTCN_EncDec::CT_RAW, 0); + raw_order_t order = p_td.raw->top_bit_order == TOP_BIT_LEFT ? ORDER_LSB : ORDER_MSB; + INTEGER integer; + integer.RAW_decode(p_td, ttcn_buf, ttcn_buf.get_len() * 8, order); + return integer; +} + void BITSTRING::set_param(Module_Param& param) { param.basic_check(Module_Param::BC_VALUE|Module_Param::BC_LIST, "bitstring value"); Module_Param_Ptr mp = ¶m; diff --git a/core/Bitstring.hh b/core/Bitstring.hh index b6301a292..8677626f5 100644 --- a/core/Bitstring.hh +++ b/core/Bitstring.hh @@ -101,6 +101,7 @@ public: BITSTRING& operator=(const BITSTRING& other_value); BITSTRING& operator=(const BITSTRING_ELEMENT& other_value); + BITSTRING& operator=(const INTEGER& other_value); boolean operator==(const BITSTRING& other_value) const; boolean operator==(const BITSTRING_ELEMENT& other_value) const; @@ -146,6 +147,8 @@ public: void log() const; + INTEGER convert_to_Integer(const TTCN_Typedescriptor_t&); + #ifdef TITAN_RUNTIME_2 boolean is_equal(const Base_Type* other_value) const { return *this == *(static_cast(other_value)); } void set_value(const Base_Type* other_value) { *this = *(static_cast(other_value)); } diff --git a/core/Integer.hh b/core/Integer.hh index 25d0f9aa0..1ffe2aadf 100644 --- a/core/Integer.hh +++ b/core/Integer.hh @@ -137,6 +137,8 @@ public: void log() const; + inline INTEGER convert_to_Integer(const TTCN_Typedescriptor_t&) { return *this; } + #ifdef TITAN_RUNTIME_2 boolean is_equal(const Base_Type* other_value) const { return *this == *(static_cast(other_value)); } void set_value(const Base_Type* other_value) { *this = *(static_cast(other_value)); } diff --git a/core/Octetstring.cc b/core/Octetstring.cc index 49d67a2af..3bbef5e25 100644 --- a/core/Octetstring.cc +++ b/core/Octetstring.cc @@ -142,6 +142,11 @@ OCTETSTRING& OCTETSTRING::operator=(const OCTETSTRING_ELEMENT& other_value) return *this; } +OCTETSTRING& OCTETSTRING::operator=(const INTEGER& other_value) +{ + return this->operator=(int2oct(other_value, val_ptr->n_octets)); +} + boolean OCTETSTRING::operator==(const OCTETSTRING& other_value) const { must_bound("Unbound left operand of octetstring comparison."); @@ -517,6 +522,16 @@ void OCTETSTRING::log() const } else TTCN_Logger::log_event_unbound(); } +INTEGER OCTETSTRING::convert_to_Integer(const TTCN_Typedescriptor_t& p_td) +{ + TTCN_EncDec_ErrorContext ec("While converting to integer type '%s': ", p_td.name); + TTCN_Buffer ttcn_buf(*this); + raw_order_t order = p_td.raw->top_bit_order == TOP_BIT_LEFT ? ORDER_LSB : ORDER_MSB; + INTEGER integer; + integer.RAW_decode(p_td, ttcn_buf, ttcn_buf.get_len() * 8, order); + return integer; +} + void OCTETSTRING::set_param(Module_Param& param) { param.basic_check(Module_Param::BC_VALUE|Module_Param::BC_LIST, "octetstring value"); Module_Param_Ptr mp = ¶m; diff --git a/core/Octetstring.hh b/core/Octetstring.hh index 99390f2dd..7b3495496 100644 --- a/core/Octetstring.hh +++ b/core/Octetstring.hh @@ -80,6 +80,7 @@ public: OCTETSTRING& operator=(const OCTETSTRING& other_value); OCTETSTRING& operator=(const OCTETSTRING_ELEMENT& other_value); + OCTETSTRING& operator=(const INTEGER& other_value); boolean operator==(const OCTETSTRING& other_value) const; boolean operator==(const OCTETSTRING_ELEMENT& other_value) const; @@ -127,6 +128,8 @@ public: operator const unsigned char*() const; void dump () const; + INTEGER convert_to_Integer(const TTCN_Typedescriptor_t&); + #ifdef TITAN_RUNTIME_2 boolean is_equal(const Base_Type* other_value) const { return *this == *(static_cast(other_value)); } void set_value(const Base_Type* other_value) { *this = *(static_cast(other_value)); } -- GitLab From fda35ebc473383b3cb8242b956aac8f0cbb725c9 Mon Sep 17 00:00:00 2001 From: Adam Knapp Date: Tue, 5 Apr 2022 10:54:55 +0200 Subject: [PATCH 3/5] Lengthto regression tests update for bit/octetstring (issue #554) Signed-off-by: Adam Knapp --- .../EncodeDecode/RAW/Bug546231/Bug546231.ttcn | 72 ++ .../EncodeDecode/RAW/Bug572603/Bug572603.ttcn | 6 +- .../RAW/Lengthto_Offset/Lengthto_Offset.ttcn | 197 +++++ .../EncodeDecode/RAW/RAW_EncDec/Makefile | 2 +- .../RAW/RAW_EncDec/RAW_EncDec.cfg | 3 +- .../RAW/RAW_EncDec/RAW_EncDec_1.ttcn | 16 +- .../RAW/RAW_EncDec/RAW_EncDec_8.ttcn | 86 +- .../RAW/RAW_EncDec/RAW_EncDec_Lengthto.ttcn | 812 ++++++++++++++++++ .../RAW/RAW_repeat/RAW_repeat_test.ttcn | 53 +- 9 files changed, 1206 insertions(+), 41 deletions(-) create mode 100644 regression_test/EncodeDecode/RAW/RAW_EncDec/RAW_EncDec_Lengthto.ttcn diff --git a/regression_test/EncodeDecode/RAW/Bug546231/Bug546231.ttcn b/regression_test/EncodeDecode/RAW/Bug546231/Bug546231.ttcn index 39577bf50..130c46e5f 100644 --- a/regression_test/EncodeDecode/RAW/Bug546231/Bug546231.ttcn +++ b/regression_test/EncodeDecode/RAW/Bug546231/Bug546231.ttcn @@ -16,6 +16,12 @@ module Bug546231 { external function dec_R2(in octetstring stream) return R2 with { extension "prototype(convert)" extension "decode(RAW)" } +external function dec_R2_Octet(in octetstring stream) return R2_Octet +with { extension "prototype(convert)" extension "decode(RAW)" } + +external function dec_R2_Bit(in octetstring stream) return R2_Bit +with { extension "prototype(convert)" extension "decode(RAW)" } + type record R2 { integer lengthfield, record of integer listfield, @@ -25,6 +31,24 @@ type record R2 { variant (lengthfield) "UNIT(elements)" } +type record R2_Octet { + octetstring lengthfield length(1), + record of integer listfield, + integer last_field +} with { + variant (lengthfield) "LENGTHTO(listfield)" + variant (lengthfield) "UNIT(elements)" +} + +type record R2_Bit { + bitstring lengthfield length(8), + record of integer listfield, + integer last_field +} with { + variant (lengthfield) "LENGTHTO(listfield)" + variant (lengthfield) "UNIT(elements)" +} + type component CT {}; testcase tc1() runs on CT { @@ -49,9 +73,57 @@ testcase tc2() runs on CT { } } +testcase tc1_Octet() runs on CT { + var R2_Octet res := dec_R2_Octet('0000'O); + var R2_Octet exp := { lengthfield := '00'O, listfield := { }, last_field := 0 }; + if (res == exp) { + setverdict(pass); + } + else { + setverdict(fail, "Got: ", res, ", expected: ", exp); + } +} + +testcase tc2_Octet() runs on CT { + var R2_Octet res := dec_R2_Octet('010102'O); + var R2_Octet exp := { lengthfield := '01'O, listfield := { 1 }, last_field := 2 }; + if (res == exp) { + setverdict(pass); + } + else { + setverdict(fail, "Got: ", res, ", expected: ", exp); + } +} + +testcase tc1_Bit() runs on CT { + var R2_Bit res := dec_R2_Bit('0000'O); + var R2_Bit exp := { lengthfield := '00000000'B, listfield := { }, last_field := 0 }; + if (res == exp) { + setverdict(pass); + } + else { + setverdict(fail, "Got: ", res, ", expected: ", exp); + } +} + +testcase tc2_Bit() runs on CT { + var R2_Bit res := dec_R2_Bit('010102'O); + var R2_Bit exp := { lengthfield := '00000001'B, listfield := { 1 }, last_field := 2 }; + if (res == exp) { + setverdict(pass); + } + else { + setverdict(fail, "Got: ", res, ", expected: ", exp); + } +} + control { execute(tc1()); execute(tc2()); + execute(tc1_Octet()); + execute(tc2_Octet()); + execute(tc1_Bit()); + execute(tc2_Bit()); } } with { diff --git a/regression_test/EncodeDecode/RAW/Bug572603/Bug572603.ttcn b/regression_test/EncodeDecode/RAW/Bug572603/Bug572603.ttcn index fbfc34947..7338b4400 100644 --- a/regression_test/EncodeDecode/RAW/Bug572603/Bug572603.ttcn +++ b/regression_test/EncodeDecode/RAW/Bug572603/Bug572603.ttcn @@ -14,7 +14,7 @@ module Bug572603 { type record UnknownIE { integer ie_code, - integer ie_length, + octetstring ie_length length(1), octetstring ie_data } with { variant (ie_length) "LENGTHTO(ie_data)" @@ -46,7 +46,7 @@ type record of IE2 IE2_list type record IE3 { integer ie_code, - integer ie_length, + bitstring ie_length length(8), octetstring ie_data } with { variant "PRESENCE(ie_code = 3)" @@ -75,7 +75,7 @@ with { extension "prototype(convert)" extension "decode(RAW)" } type component CT {} testcase tc_bug572603() runs on CT { - var PDU v_pdu1 := { f_ie1 := { 1, 1, 'AA'O }, f_ie2_list := { { 2, 1, 'BB'O }, { 2, 1, 'BB'O } }, f_ie3 := { 3, 1, 'CC'O }, f_other := { { 4, 1, 'DD'O } } } + var PDU v_pdu1 := { f_ie1 := { 1, 1, 'AA'O }, f_ie2_list := { { 2, 1, 'BB'O }, { 2, 1, 'BB'O } }, f_ie3 := { 3, '00000001'B, 'CC'O }, f_other := { { 4, '01'O, 'DD'O } } } var PDU v_pdu2 var octetstring v_oct := '0101AA0201BB0401DD0201BB0301CC'O; v_pdu2 := dec_PDU(v_oct); diff --git a/regression_test/EncodeDecode/RAW/Lengthto_Offset/Lengthto_Offset.ttcn b/regression_test/EncodeDecode/RAW/Lengthto_Offset/Lengthto_Offset.ttcn index 90c27c07c..aca0e983e 100644 --- a/regression_test/EncodeDecode/RAW/Lengthto_Offset/Lengthto_Offset.ttcn +++ b/regression_test/EncodeDecode/RAW/Lengthto_Offset/Lengthto_Offset.ttcn @@ -42,6 +42,64 @@ testcase tc1() runs on CT { setverdict(pass); } +type record Rec1_Octet { + octetstring len, + octetstring data +} +with { + variant (len) "LENGTHTO(data) + 1"; + variant (len) "FIELDLENGTH(1)" +} + +testcase tc1_Octet() runs on CT { + var Rec1_Octet val := { '00'O, '12345678'O }; + var bitstring enc_exp := oct2bit('0512345678'O); + var bitstring enc := encvalue(val); + if (enc_exp != enc) { + setverdict(fail, "Encoding failed. Expected: ", bit2oct(enc_exp), ", got: ", bit2oct(enc)); + } + + var Rec1_Octet dec_exp := { int2oct(lengthof(val.data), 1), val.data }; + var Rec1_Octet dec; + var integer res := decvalue(enc_exp, dec); + if (res != 0) { + setverdict(fail, "Invalid decoding result: ", res); + } + else if (dec_exp != dec) { + setverdict(fail, "Decoding failed. Expected: ", dec_exp, ", got: ", dec); + } + setverdict(pass); +} + +type record Rec1_Bit { + bitstring len, + octetstring data +} +with { + variant (len) "LENGTHTO(data) + 1"; + variant (len) "FIELDLENGTH(8)" +} + +testcase tc1_Bit() runs on CT { + var Rec1_Bit val := { '00000000'B, '12345678'O }; + var bitstring enc_exp := oct2bit('0512345678'O); + var bitstring enc := encvalue(val); + if (enc_exp != enc) { + setverdict(fail, "Encoding failed. Expected: ", bit2oct(enc_exp), ", got: ", bit2oct(enc)); + } + + var Rec1_Bit dec_exp := { int2bit(lengthof(val.data), 8), val.data }; + var Rec1_Bit dec; + var integer res := decvalue(enc_exp, dec); + if (res != 0) { + setverdict(fail, "Invalid decoding result: ", res); + } + else if (dec_exp != dec) { + setverdict(fail, "Decoding failed. Expected: ", dec_exp, ", got: ", dec); + } + setverdict(pass); +} + type record Rec2 { integer len, bitstring data1, @@ -72,6 +130,69 @@ testcase tc2() runs on CT { setverdict(pass); } +type record Rec2_Octet { + octetstring len, + bitstring data1, + octetstring data2 +} +with { + variant (len) "LENGTHTO(data1, data2) - 2"; + variant (len) "FIELDLENGTH(1)"; + variant (data1) "FIELDLENGTH(8)"; +} + + +testcase tc2_Octet() runs on CT { + var Rec2_Octet val := { '00'O, '10010101'B, '12345678'O }; + var bitstring enc_exp := oct2bit('039512345678'O); + var bitstring enc := encvalue(val); + if (enc_exp != enc) { + setverdict(fail, "Encoding failed. Expected: ", bit2oct(enc_exp), ", got: ", bit2oct(enc)); + } + + var Rec2_Octet dec_exp := { int2oct(lengthof(val.data1) / 8 + lengthof(val.data2), 1), val.data1, val.data2 }; + var Rec2_Octet dec; + var integer res := decvalue(enc_exp, dec); + if (res != 0) { + setverdict(fail, "Invalid decoding result: ", res); + } + else if (dec_exp != dec) { + setverdict(fail, "Decoding failed. Expected: ", dec_exp, ", got: ", dec); + } + setverdict(pass); +} + +type record Rec2_Bit { + bitstring len, + bitstring data1, + octetstring data2 +} +with { + variant (len) "LENGTHTO(data1, data2) - 2"; + variant (len) "FIELDLENGTH(8)"; + variant (data1) "FIELDLENGTH(8)"; +} + +testcase tc2_Bit() runs on CT { + var Rec2_Bit val := { '00000000'B, '10010101'B, '12345678'O }; + var bitstring enc_exp := oct2bit('039512345678'O); + var bitstring enc := encvalue(val); + if (enc_exp != enc) { + setverdict(fail, "Encoding failed. Expected: ", bit2oct(enc_exp), ", got: ", bit2oct(enc)); + } + + var Rec2_Bit dec_exp := { int2bit(lengthof(val.data1) / 8 + lengthof(val.data2), 8), val.data1, val.data2 }; + var Rec2_Bit dec; + var integer res := decvalue(enc_exp, dec); + if (res != 0) { + setverdict(fail, "Invalid decoding result: ", res); + } + else if (dec_exp != dec) { + setverdict(fail, "Decoding failed. Expected: ", dec_exp, ", got: ", dec); + } + setverdict(pass); +} + type record Rec3 { union { integer i1, integer i2 } len, bitstring data1, @@ -102,10 +223,86 @@ testcase tc3() runs on CT { setverdict(pass); } +type union length_octet { octetstring i1, octetstring i2 } with { + variant (i1) "FIELDLENGTH(1)"; + variant (i2) "FIELDLENGTH(2)"; +} + +type record Rec3_Octet { + length_octet len, + bitstring data1, + octetstring data2 +} +with { + variant (len) "LENGTHTO(data1, data2) + 10"; + variant (data1) "FIELDLENGTH(8)"; +} + +testcase tc3_Octet() runs on CT { + var Rec3_Octet val := { { i1 := '00'O }, '10010101'B, '12345678'O }; + var bitstring enc_exp := oct2bit('0F9512345678'O); + var bitstring enc := encvalue(val); + if (enc_exp != enc) { + setverdict(fail, "Encoding failed. Expected: ", bit2oct(enc_exp), ", got: ", bit2oct(enc)); + } + + var Rec3_Octet dec_exp := { { i1 := int2oct(lengthof(val.data1) / 8 + lengthof(val.data2), 1) }, val.data1, val.data2 }; + var Rec3_Octet dec; + var integer res := decvalue(enc_exp, dec); + if (res != 0) { + setverdict(fail, "Invalid decoding result: ", res); + } + else if (dec_exp != dec) { + setverdict(fail, "Decoding failed. Expected: ", dec_exp, ", got: ", dec); + } + setverdict(pass); +} + +type union length_bit { bitstring i1, bitstring i2 } with { + variant (i1) "FIELDLENGTH(8)"; + variant (i2) "FIELDLENGTH(12)"; +} + +type record Rec3_Bit { + length_bit len, + bitstring data1, + octetstring data2 +} +with { + variant (len) "LENGTHTO(data1, data2) + 10"; + variant (data1) "FIELDLENGTH(8)"; +} + +testcase tc3_Bit() runs on CT { + var Rec3_Bit val := { { i1 := '00000000'B }, '10010101'B, '12345678'O }; + var bitstring enc_exp := oct2bit('0F9512345678'O); + var bitstring enc := encvalue(val); + if (enc_exp != enc) { + setverdict(fail, "Encoding failed. Expected: ", bit2oct(enc_exp), ", got: ", bit2oct(enc)); + } + + var Rec3_Bit dec_exp := { { i1 := int2bit(lengthof(val.data1) / 8 + lengthof(val.data2), 8) }, val.data1, val.data2 }; + var Rec3_Bit dec; + var integer res := decvalue(enc_exp, dec); + if (res != 0) { + setverdict(fail, "Invalid decoding result: ", res); + } + else if (dec_exp != dec) { + setverdict(fail, "Decoding failed. Expected: ", dec_exp, ", got: ", dec); + } + setverdict(pass); +} + control { execute(tc1()); execute(tc2()); execute(tc3()); + execute(tc1_Octet()); + execute(tc2_Octet()); + execute(tc3_Octet()); + execute(tc1_Bit()); + execute(tc2_Bit()); + execute(tc3_Bit()); } } diff --git a/regression_test/EncodeDecode/RAW/RAW_EncDec/Makefile b/regression_test/EncodeDecode/RAW/RAW_EncDec/Makefile index 3a947d229..0fa79a65b 100644 --- a/regression_test/EncodeDecode/RAW/RAW_EncDec/Makefile +++ b/regression_test/EncodeDecode/RAW/RAW_EncDec/Makefile @@ -24,7 +24,7 @@ include $(TOPDIR)/Makefile.regression TTCN3_LIB = ttcn3$(RT2_SUFFIX)$(DYNAMIC_SUFFIX) -TTCN3_MODULES = RAW_EncDec_1.ttcn RAW_EncDec_2.ttcn RAW_EncDec_3.ttcn RAW_EncDec_4.ttcn RAW_EncDec_5.ttcn RAW_EncDec_6.ttcn RAW_EncDec_7.ttcn RAW_EncDec_8.ttcn +TTCN3_MODULES = RAW_EncDec_1.ttcn RAW_EncDec_2.ttcn RAW_EncDec_3.ttcn RAW_EncDec_4.ttcn RAW_EncDec_5.ttcn RAW_EncDec_6.ttcn RAW_EncDec_7.ttcn RAW_EncDec_8.ttcn RAW_EncDec_Lengthto.ttcn ASN1_MODULES = diff --git a/regression_test/EncodeDecode/RAW/RAW_EncDec/RAW_EncDec.cfg b/regression_test/EncodeDecode/RAW/RAW_EncDec/RAW_EncDec.cfg index 11b98d3fd..9ca99bb87 100644 --- a/regression_test/EncodeDecode/RAW/RAW_EncDec/RAW_EncDec.cfg +++ b/regression_test/EncodeDecode/RAW/RAW_EncDec/RAW_EncDec.cfg @@ -24,4 +24,5 @@ RAW_EncDec_4 RAW_EncDec_5 RAW_EncDec_6 RAW_EncDec_7 -RAW_EncDec_8 \ No newline at end of file +RAW_EncDec_8 +RAW_EncDec_Lengthto \ No newline at end of file diff --git a/regression_test/EncodeDecode/RAW/RAW_EncDec/RAW_EncDec_1.ttcn b/regression_test/EncodeDecode/RAW/RAW_EncDec/RAW_EncDec_1.ttcn index 771d5bbb7..8dae2a5a8 100644 --- a/regression_test/EncodeDecode/RAW/RAW_EncDec/RAW_EncDec_1.ttcn +++ b/regression_test/EncodeDecode/RAW/RAW_EncDec/RAW_EncDec_1.ttcn @@ -4819,7 +4819,7 @@ with {variant (paramLength) "LENGTHTO(octstr , bit7 , bit1 , hexstr , int )" } type record Param2 { ParamName paramName , - integer paramLength , + octetstring paramLength length(1), OCT3_ octstr , BIT7_ bit7 , BIT1_ bit1 , @@ -4829,7 +4829,7 @@ with {variant (paramLength) "LENGTHTO(octstr , bit7 , bit1 , hexstr , int )" } type record Param3 { ParamName paramName , - integer paramLength , + bitstring paramLength length(8), OCT3_ octstr , BIT7_ bit7 , BIT1_ bit1 , @@ -5017,7 +5017,7 @@ testcase TC_structured_types_10() runs on TempComp{ int := 1 } , param3 := { paramName := name3 , - paramLength := 6 , + paramLength := '00000110'B , octstr := '123456'O , bit7 := '0000000'B , bit1 := '1'B , @@ -5025,7 +5025,7 @@ testcase TC_structured_types_10() runs on TempComp{ int := 1 } , param2 := { paramName := name2 , - paramLength := 6 , + paramLength := '06'O , octstr := '123456'O , bit7 := '0000000'B , bit1 := '1'B , @@ -5105,7 +5105,7 @@ testcase TC_structured_types_12() runs on TempComp{ int := 1 } , param3 := { paramName := name3 , - paramLength := 6 , + paramLength := '00000110'B , octstr := '123456'O , bit7 := '0000000'B , bit1 := '1'B , @@ -5151,7 +5151,7 @@ testcase TC_structured_types_13() runs on TempComp{ param4 := omit , param3 := { paramName := name3 , - paramLength := 6 , + paramLength := '00000110'B , octstr := '123456'O , bit7 := '0000000'B , bit1 := '1'B , @@ -5432,7 +5432,7 @@ testcase TC_structured_types_14() runs on TempComp{ int := 1 } , param3 := { paramName := name3 , - paramLength := 6 , + paramLength := '00000110'B , octstr := '123456'O , bit7 := '0000000'B , bit1 := '1'B , @@ -5482,7 +5482,7 @@ testcase TC_structured_types_15() runs on TempComp{ int := 1 } , param3 := { paramName := name3 , - paramLength := 6 , + paramLength := '00000110'B , octstr := '123456'O , bit7 := '0000000'B , bit1 := '1'B , diff --git a/regression_test/EncodeDecode/RAW/RAW_EncDec/RAW_EncDec_8.ttcn b/regression_test/EncodeDecode/RAW/RAW_EncDec/RAW_EncDec_8.ttcn index 065542159..087556a98 100644 --- a/regression_test/EncodeDecode/RAW/RAW_EncDec/RAW_EncDec_8.ttcn +++ b/regression_test/EncodeDecode/RAW/RAW_EncDec/RAW_EncDec_8.ttcn @@ -23,8 +23,29 @@ module RAW_EncDec_8 { extension "prototype(convert)" extension "decode(RAW)" } - - type octetstring OCT2 length(2); + + external function enc_U_Octet(in U_Octet pl_pdu) return octetstring + with { + extension "prototype(convert)" + extension "encode(RAW)" + }; + external function dec_U_Octet(in octetstring pl_octetstring) return U_Octet + with { + extension "prototype(convert)" + extension "decode(RAW)" + } + + external function enc_U_Bit(in U_Bit pl_pdu) return octetstring + with { + extension "prototype(convert)" + extension "encode(RAW)" + }; + external function dec_U_Bit(in octetstring pl_octetstring) return U_Bit + with { + extension "prototype(convert)" + extension "decode(RAW)" + } + type record R1 { integer f1, @@ -44,6 +65,43 @@ module RAW_EncDec_8 { variant "" } + type record R1_Octet { + octetstring f1, + octetstring f2, + integer f3 + } with { + encode "RAW" + variant (f1) "FIELDLENGTH(8)" + variant (f1) "LENGTHTO(f2)" + } + + type union U_Octet { + R1_Octet u1, + octetstring u2 length(8) + } with { + encode "RAW" + variant "" + } + + type record R1_Bit { + bitstring f1, + octetstring f2, + integer f3 + } with { + encode "RAW" + variant (f1) "FIELDLENGTH(64)" + variant (f1) "LENGTHTO(f2)" + } + + type union U_Bit { + R1_Bit u1, + octetstring u2 length(8) + } with { + encode "RAW" + variant "" + } + + testcase TC_01() runs on Test_CT{ var U pl_u, pl_u_result; pl_u.u2 := 'FFFFFFFFFFFFFFFF'O; @@ -55,8 +113,32 @@ testcase TC_01() runs on Test_CT{ setverdict(pass); } +testcase TC_01_Octet() runs on Test_CT{ + var U_Octet pl_u, pl_u_result; + pl_u.u2 := 'FFFFFFFFFFFFFFFF'O; + var octetstring os := enc_U_Octet(pl_u); + pl_u_result := dec_U_Octet(os); + if (pl_u != pl_u_result) { + setverdict(fail); + } + setverdict(pass); +} + +testcase TC_01_Bit() runs on Test_CT{ + var U_Bit pl_u, pl_u_result; + pl_u.u2 := 'FFFFFFFFFFFFFFFF'O; + var octetstring os := enc_U_Bit(pl_u); + pl_u_result := dec_U_Bit(os); + if (pl_u != pl_u_result) { + setverdict(fail); + } + setverdict(pass); +} + control{ execute(TC_01()); + execute(TC_01_Octet()); + execute(TC_01_Bit()); } } diff --git a/regression_test/EncodeDecode/RAW/RAW_EncDec/RAW_EncDec_Lengthto.ttcn b/regression_test/EncodeDecode/RAW/RAW_EncDec/RAW_EncDec_Lengthto.ttcn new file mode 100644 index 000000000..08ca51564 --- /dev/null +++ b/regression_test/EncodeDecode/RAW/RAW_EncDec/RAW_EncDec_Lengthto.ttcn @@ -0,0 +1,812 @@ +module RAW_EncDec_Lengthto { + +type component TempComp {} + +type bitstring BIT1_ +with { variant "FIELDLENGTH(1)" } ; + +type bitstring BIT7_ +with { variant "FIELDLENGTH(7)" } ; + +type octetstring OCT3_ +with { variant "FIELDLENGTH(3)" } ; + + +type record Rec1 +{ BIT7_ data , + BIT1_ extensionbit } + with { variant "EXTENSION_BIT (yes)"}; + + +type record Rec2 +{ BIT7_ data , + BIT1_ extensionbit } + with { variant "EXTENSION_BIT (yes)"}; + + +type record Rec3 +{ BIT7_ data , + BIT1_ extensionbit } + with { variant "EXTENSION_BIT (yes)"}; + + +type record Octet1 +{ BIT7_ data , + BIT1_ extensionbit , + Rec1 rec1 , + octetstring more_extension optional } + with { variant "EXTENSION_BIT (yes)"; + variant (more_extension) "EXTENSION_BIT (yes)"}; + + +type record Octet2 +{ BIT7_ data , + BIT1_ extensionbit , + Rec2 rec2 , + octetstring more_extension optional } + with { variant "EXTENSION_BIT (yes)"; + variant (more_extension) "EXTENSION_BIT (yes)"}; + + +type record Octet3 +{ BIT7_ data , + BIT1_ extensionbit , + Rec3 rec3 , + octetstring more_extension optional } + with { variant "EXTENSION_BIT (yes)"; + variant (more_extension) "EXTENSION_BIT (yes)"}; + + +type record RAW_PDU_127_Octet +{ OCT3_ octstr , + octetstring length1 , + Octet1 oct1 , + Octet2 oct2 optional , + Octet3 oct3 optional } +with { variant (length1) "LENGTHTO(oct1, oct2, oct3)"; + variant (length1) "FIELDLENGTH(1)" } + +external function enc_RAW_PDU_127_Octet(in RAW_PDU_127_Octet pdu) return octetstring with { extension "prototype(convert) encode(RAW)" } +external function dec_RAW_PDU_127_Octet(in octetstring stream) return RAW_PDU_127_Octet with { extension "prototype(convert) decode(RAW)" } + +type record RAW_PDU_127_Bit +{ OCT3_ octstr , + bitstring length1 , + Octet1 oct1 , + Octet2 oct2 optional , + Octet3 oct3 optional } +with { variant (length1) "LENGTHTO(oct1, oct2, oct3)"; + variant (length1) "FIELDLENGTH(8)" } + +external function enc_RAW_PDU_127_Bit(in RAW_PDU_127_Bit pdu) return octetstring with { extension "prototype(convert) encode(RAW)" } +external function dec_RAW_PDU_127_Bit(in octetstring stream) return RAW_PDU_127_Bit with { extension "prototype(convert) decode(RAW)" } + +testcase TC_record_with_EXTENSION_BIT_1_Octet() runs on TempComp { + + const RAW_PDU_127_Octet + i := { octstr := '123456'O , + length1 := '0F'O , + oct1 := + { data := '0000001'B , + extensionbit := '0'B , + rec1 := + { data := '0000001'B , + extensionbit := '0'B } , + more_extension := '000080'O } , + oct2 := + { data := '0000010'B , + extensionbit := '0'B , + rec2 := + { data := '0000010'B , + extensionbit := '0'B } , + more_extension := '000080'O } , + oct3 := + { data := '0000011'B , + extensionbit := '0'B , + rec3 := + { data := '0000011'B , + extensionbit := '0'B } , + more_extension := '000080'O } } + + const octetstring o :='1234560F010100008002020000800303000080'O + + if ((enc_RAW_PDU_127_Octet(i) == o)and(dec_RAW_PDU_127_Octet(o) == i )) {setverdict(pass);} + else {setverdict(fail,"enc_RAW_PDU_127_Octet(i)= ", enc_RAW_PDU_127_Octet(i), "; dec_RAW_PDU_127_Octet(o)= ", dec_RAW_PDU_127_Octet(o));} +} + +testcase TC_record_with_EXTENSION_BIT_1_Bit() runs on TempComp { + + const RAW_PDU_127_Bit + i := { octstr := '123456'O , + length1 := '00001111'B , + oct1 := + { data := '0000001'B , + extensionbit := '0'B , + rec1 := + { data := '0000001'B , + extensionbit := '0'B } , + more_extension := '000080'O } , + oct2 := + { data := '0000010'B , + extensionbit := '0'B , + rec2 := + { data := '0000010'B , + extensionbit := '0'B } , + more_extension := '000080'O } , + oct3 := + { data := '0000011'B , + extensionbit := '0'B , + rec3 := + { data := '0000011'B , + extensionbit := '0'B } , + more_extension := '000080'O } } + + const octetstring o :='1234560F010100008002020000800303000080'O + + if ((enc_RAW_PDU_127_Bit(i) == o)and(dec_RAW_PDU_127_Bit(o) == i )) {setverdict(pass);} + else {setverdict(fail,"enc_RAW_PDU_127_Bit(i)= ", enc_RAW_PDU_127_Bit(i), "; dec_RAW_PDU_127_Bit(o)= ", dec_RAW_PDU_127_Bit(o));} +} + +// Test of record with EXTENSION_BIT 2 +testcase TC_record_with_EXTENSION_BIT_2_Octet() runs on TempComp { + const RAW_PDU_127_Octet + i := { octstr := '123456'O , + length1 := '0C'O , + oct1 := + { data := '0000001'B , + extensionbit := '0'B , + rec1 := + { data := '0000001'B , + extensionbit := '0'B } , + more_extension := '000080'O } , + oct2 := + { data := '0000010'B , + extensionbit := '0'B , + rec2 := + { data := '0000010'B , + extensionbit := '1'B } , + more_extension := omit } , + oct3 := + { data := '0000011'B , + extensionbit := '0'B , + rec3 := + { data := '0000011'B , + extensionbit := '0'B } , + more_extension := '000080'O } } + + + const octetstring o :='1234560C010100008002820303000080'O + + if ((enc_RAW_PDU_127_Octet(i) == o)and(dec_RAW_PDU_127_Octet(o) == i )) {setverdict(pass);} + else {setverdict(fail,"enc_RAW_PDU_127_Octet(i)= ", enc_RAW_PDU_127_Octet(i), "; dec_RAW_PDU_127_Octet(o)= ", dec_RAW_PDU_127_Octet(o));} +} + +testcase TC_record_with_EXTENSION_BIT_2_Bit() runs on TempComp { + const RAW_PDU_127_Bit + i := { octstr := '123456'O , + length1 := '00001100'B , + oct1 := + { data := '0000001'B , + extensionbit := '0'B , + rec1 := + { data := '0000001'B , + extensionbit := '0'B } , + more_extension := '000080'O } , + oct2 := + { data := '0000010'B , + extensionbit := '0'B , + rec2 := + { data := '0000010'B , + extensionbit := '1'B } , + more_extension := omit } , + oct3 := + { data := '0000011'B , + extensionbit := '0'B , + rec3 := + { data := '0000011'B , + extensionbit := '0'B } , + more_extension := '000080'O } } + + + const octetstring o :='1234560C010100008002820303000080'O + + if ((enc_RAW_PDU_127_Bit(i) == o)and(dec_RAW_PDU_127_Bit(o) == i )) {setverdict(pass);} + else {setverdict(fail,"enc_RAW_PDU_127_Bit(i)= ", enc_RAW_PDU_127_Bit(i), "; dec_RAW_PDU_127_Bit(o)= ", dec_RAW_PDU_127_Bit(o));} +} + +// Test of record with EXTENSION_BIT 3 +testcase TC_record_with_EXTENSION_BIT_3_Octet() runs on TempComp { + const RAW_PDU_127_Octet + i := { octstr := '123456'O , + length1 := '09'O , + oct1 := + { data := '0000001'B , + extensionbit := '0'B , + rec1 := + { data := '0000001'B , + extensionbit := '0'B } , + more_extension := '000080'O } , + oct2 := + { data := '0000010'B , + extensionbit := '0'B , + rec2 := + { data := '0000010'B , + extensionbit := '1'B } , + more_extension := omit } , + oct3 := + { data := '0000011'B , + extensionbit := '0'B , + rec3 := + { data := '0000011'B , + extensionbit := '1'B } , + more_extension := omit } } + + const octetstring o :='12345609010100008002820383'O + + if ((enc_RAW_PDU_127_Octet(i) == o)and(dec_RAW_PDU_127_Octet(o) == i )) {setverdict(pass);} + else {setverdict(fail,"enc_RAW_PDU_127_Octet(i)= ", enc_RAW_PDU_127_Octet(i), "; dec_RAW_PDU_127_Octet(o)= ", dec_RAW_PDU_127_Octet(o));} +} + +testcase TC_record_with_EXTENSION_BIT_3_Bit() runs on TempComp { + const RAW_PDU_127_Bit + i := { octstr := '123456'O , + length1 := '00001001'B , + oct1 := + { data := '0000001'B , + extensionbit := '0'B , + rec1 := + { data := '0000001'B , + extensionbit := '0'B } , + more_extension := '000080'O } , + oct2 := + { data := '0000010'B , + extensionbit := '0'B , + rec2 := + { data := '0000010'B , + extensionbit := '1'B } , + more_extension := omit } , + oct3 := + { data := '0000011'B , + extensionbit := '0'B , + rec3 := + { data := '0000011'B , + extensionbit := '1'B } , + more_extension := omit } } + + const octetstring o :='12345609010100008002820383'O + + if ((enc_RAW_PDU_127_Bit(i) == o)and(dec_RAW_PDU_127_Bit(o) == i )) {setverdict(pass);} + else {setverdict(fail,"enc_RAW_PDU_127_Bit(i)= ", enc_RAW_PDU_127_Bit(i), "; dec_RAW_PDU_127_Bit(o)= ", dec_RAW_PDU_127_Bit(o));} +} + +// Test of record with EXTENSION_BIT 4 +testcase TC_record_with_EXTENSION_BIT_4_Octet() runs on TempComp { + const RAW_PDU_127_Octet + i := { octstr := '123456'O , + length1 := '06'O , + oct1 := + { data := '0000001'B , + extensionbit := '0'B , + rec1 := + { data := '0000001'B , + extensionbit := '1'B } , + more_extension := omit } , + oct2 := + { data := '0000010'B , + extensionbit := '0'B , + rec2 := + { data := '0000010'B , + extensionbit := '1'B } , + more_extension := omit } , + oct3 := + { data := '0000011'B , + extensionbit := '0'B , + rec3 := + { data := '0000011'B , + extensionbit := '1'B } , + more_extension := omit } } + + const octetstring o :='12345606018102820383'O + + if ((enc_RAW_PDU_127_Octet(i) == o)and(dec_RAW_PDU_127_Octet(o) == i )) {setverdict(pass);} + else {setverdict(fail,"enc_RAW_PDU_127_Octet(i)= ", enc_RAW_PDU_127_Octet(i), "; dec_RAW_PDU_127_Octet(o)= ", dec_RAW_PDU_127_Octet(o));} +} + +testcase TC_record_with_EXTENSION_BIT_4_Bit() runs on TempComp { + const RAW_PDU_127_Bit + i := { octstr := '123456'O , + length1 := '00000110'B , + oct1 := + { data := '0000001'B , + extensionbit := '0'B , + rec1 := + { data := '0000001'B , + extensionbit := '1'B } , + more_extension := omit } , + oct2 := + { data := '0000010'B , + extensionbit := '0'B , + rec2 := + { data := '0000010'B , + extensionbit := '1'B } , + more_extension := omit } , + oct3 := + { data := '0000011'B , + extensionbit := '0'B , + rec3 := + { data := '0000011'B , + extensionbit := '1'B } , + more_extension := omit } } + + const octetstring o :='12345606018102820383'O + + if ((enc_RAW_PDU_127_Bit(i) == o)and(dec_RAW_PDU_127_Bit(o) == i )) {setverdict(pass);} + else {setverdict(fail,"enc_RAW_PDU_127_Bit(i)= ", enc_RAW_PDU_127_Bit(i), "; dec_RAW_PDU_127_Bit(o)= ", dec_RAW_PDU_127_Bit(o));} +} + +// Test of record with EXTENSION_BIT 5 +testcase TC_record_with_EXTENSION_BIT_5_Octet() runs on TempComp { + const RAW_PDU_127_Octet + i := { octstr := '123456'O , + length1 := '04'O , + oct1 := + { data := '0000001'B , + extensionbit := '0'B , + rec1 := + { data := '0000001'B , + extensionbit := '1'B } , + more_extension := omit } , + oct2 := + { data := '0000010'B , + extensionbit := '0'B , + rec2 := + { data := '0000010'B , + extensionbit := '1'B } , + more_extension := omit } , + oct3 := omit } + + const octetstring o :='1234560401810282'O + + + if ((enc_RAW_PDU_127_Octet(i) == o)and(dec_RAW_PDU_127_Octet(o) == i )) {setverdict(pass);} + else {setverdict(fail,"enc_RAW_PDU_127_Octet(i)= ", enc_RAW_PDU_127_Octet(i), "; dec_RAW_PDU_127_Octet(o)= ", dec_RAW_PDU_127_Octet(o));} +} + +testcase TC_record_with_EXTENSION_BIT_5_Bit() runs on TempComp { + const RAW_PDU_127_Bit + i := { octstr := '123456'O , + length1 := '00000100'B , + oct1 := + { data := '0000001'B , + extensionbit := '0'B , + rec1 := + { data := '0000001'B , + extensionbit := '1'B } , + more_extension := omit } , + oct2 := + { data := '0000010'B , + extensionbit := '0'B , + rec2 := + { data := '0000010'B , + extensionbit := '1'B } , + more_extension := omit } , + oct3 := omit } + + const octetstring o :='1234560401810282'O + + + if ((enc_RAW_PDU_127_Bit(i) == o)and(dec_RAW_PDU_127_Bit(o) == i )) {setverdict(pass);} + else {setverdict(fail,"enc_RAW_PDU_127_Bit(i)= ", enc_RAW_PDU_127_Bit(i), "; dec_RAW_PDU_127_Bit(o)= ", dec_RAW_PDU_127_Bit(o));} +} + +// Test of record with EXTENSION_BIT 6 +testcase TC_record_with_EXTENSION_BIT_6_Octet() runs on TempComp { + const RAW_PDU_127_Octet + i := { octstr := '123456'O , + length1 := '02'O , + oct1 := + { data := '0000001'B , + extensionbit := '0'B , + rec1 := + { data := '0000001'B , + extensionbit := '1'B } , + more_extension := omit } , + oct2 := omit , + oct3 := omit } + + const octetstring o :='123456020181'O + + if ((enc_RAW_PDU_127_Octet(i) == o)and(dec_RAW_PDU_127_Octet(o) == i )) {setverdict(pass);} + else {setverdict(fail,"enc_RAW_PDU_127_Octet(i)= ", enc_RAW_PDU_127_Octet(i), "; dec_RAW_PDU_127_Octet(o)= ", dec_RAW_PDU_127_Octet(o));} +} + +testcase TC_record_with_EXTENSION_BIT_6_Bit() runs on TempComp { + const RAW_PDU_127_Bit + i := { octstr := '123456'O , + length1 := '00000010'B , + oct1 := + { data := '0000001'B , + extensionbit := '0'B , + rec1 := + { data := '0000001'B , + extensionbit := '1'B } , + more_extension := omit } , + oct2 := omit , + oct3 := omit } + + const octetstring o :='123456020181'O + + if ((enc_RAW_PDU_127_Bit(i) == o)and(dec_RAW_PDU_127_Bit(o) == i )) {setverdict(pass);} + else {setverdict(fail,"enc_RAW_PDU_127_Bit(i)= ", enc_RAW_PDU_127_Bit(i), "; dec_RAW_PDU_127_Bit(o)= ", dec_RAW_PDU_127_Bit(o));} +} + +// Test of record with EXTENSION_BIT 7 +testcase TC_record_with_EXTENSION_BIT_7_Octet() runs on TempComp { + const RAW_PDU_127_Octet + i := { octstr := '123456'O , + length1 := '0F'O , + oct1 := + { data := '0000001'B , + extensionbit := '0'B , + rec1 := + { data := '0000001'B , + extensionbit := '0'B } , + more_extension := '000080'O } , + oct2 := + { data := '0000010'B , + extensionbit := '0'B , + rec2 := + { data := '0000010'B , + extensionbit := '0'B } , + more_extension := '000080'O } , + oct3 := + { data := '0000011'B , + extensionbit := '0'B , + rec3 := + { data := '0000011'B , + extensionbit := '0'B } , + more_extension := '000080'O } } + + const octetstring o :='1234560F010100008002020000800303000080'O + + if ((enc_RAW_PDU_127_Octet(i) == o)and(dec_RAW_PDU_127_Octet(o) == i )) {setverdict(pass);} + else {setverdict(fail,"enc_RAW_PDU_127_Octet(i)= ", enc_RAW_PDU_127_Octet(i), "; dec_RAW_PDU_127_Octet(o)= ", dec_RAW_PDU_127_Octet(o));} +} + +testcase TC_record_with_EXTENSION_BIT_7_Bit() runs on TempComp { + const RAW_PDU_127_Bit + i := { octstr := '123456'O , + length1 := '00001111'B , + oct1 := + { data := '0000001'B , + extensionbit := '0'B , + rec1 := + { data := '0000001'B , + extensionbit := '0'B } , + more_extension := '000080'O } , + oct2 := + { data := '0000010'B , + extensionbit := '0'B , + rec2 := + { data := '0000010'B , + extensionbit := '0'B } , + more_extension := '000080'O } , + oct3 := + { data := '0000011'B , + extensionbit := '0'B , + rec3 := + { data := '0000011'B , + extensionbit := '0'B } , + more_extension := '000080'O } } + + const octetstring o :='1234560F010100008002020000800303000080'O + + if ((enc_RAW_PDU_127_Bit(i) == o)and(dec_RAW_PDU_127_Bit(o) == i )) {setverdict(pass);} + else {setverdict(fail,"enc_RAW_PDU_127_Bit(i)= ", enc_RAW_PDU_127_Bit(i), "; dec_RAW_PDU_127_Bit(o)= ", dec_RAW_PDU_127_Bit(o));} +} + +// Test of record with EXTENSION_BIT 8 +testcase TC_record_with_EXTENSION_BIT_8_Octet() runs on TempComp { + const RAW_PDU_127_Octet + i := { octstr := '123456'O , + length1 := '05'O , + oct1 := + { data := '0000001'B , + extensionbit := '0'B , + rec1 := + { data := '0000001'B , + extensionbit := '0'B } , + more_extension := '000080'O } , + oct2 := omit , + oct3 := omit } + + const octetstring o :='123456050101000080'O + + if ((enc_RAW_PDU_127_Octet(i) == o)and(dec_RAW_PDU_127_Octet(o) == i )) {setverdict(pass);} + else {setverdict(fail,"enc_RAW_PDU_127_Octet(i)= ", enc_RAW_PDU_127_Octet(i), "; dec_RAW_PDU_127_Octet(o)= ", dec_RAW_PDU_127_Octet(o));} +} + +testcase TC_record_with_EXTENSION_BIT_8_Bit() runs on TempComp { + const RAW_PDU_127_Bit + i := { octstr := '123456'O , + length1 := '00000101'B , + oct1 := + { data := '0000001'B , + extensionbit := '0'B , + rec1 := + { data := '0000001'B , + extensionbit := '0'B } , + more_extension := '000080'O } , + oct2 := omit , + oct3 := omit } + + const octetstring o :='123456050101000080'O + + if ((enc_RAW_PDU_127_Bit(i) == o)and(dec_RAW_PDU_127_Bit(o) == i )) {setverdict(pass);} + else {setverdict(fail,"enc_RAW_PDU_127_Bit(i)= ", enc_RAW_PDU_127_Bit(i), "; dec_RAW_PDU_127_Bit(o)= ", dec_RAW_PDU_127_Bit(o));} +} + +// Test of record with EXTENSION_BIT 9 +testcase TC_record_with_EXTENSION_BIT_9_Octet() runs on TempComp { + const RAW_PDU_127_Octet + i := { octstr := '123456'O , + length1 := '0A'O , + oct1 := + { data := '0000001'B , + extensionbit := '0'B , + rec1 := + { data := '0000001'B , + extensionbit := '0'B } , + more_extension := '000080'O } , + oct2 := + { data := '0000010'B , + extensionbit := '0'B , + rec2 := + { data := '0000010'B , + extensionbit := '0'B } , + more_extension := '000080'O } , + oct3 := omit } + + const octetstring o :='1234560A01010000800202000080'O + + if ((enc_RAW_PDU_127_Octet(i) == o)and(dec_RAW_PDU_127_Octet(o) == i )) {setverdict(pass);} + else {setverdict(fail,"enc_RAW_PDU_127_Octet(i)= ", enc_RAW_PDU_127_Octet(i), "; dec_RAW_PDU_127_Octet(o)= ", dec_RAW_PDU_127_Octet(o));} +} + +testcase TC_record_with_EXTENSION_BIT_9_Bit() runs on TempComp { + const RAW_PDU_127_Bit + i := { octstr := '123456'O , + length1 := '00001010'B , + oct1 := + { data := '0000001'B , + extensionbit := '0'B , + rec1 := + { data := '0000001'B , + extensionbit := '0'B } , + more_extension := '000080'O } , + oct2 := + { data := '0000010'B , + extensionbit := '0'B , + rec2 := + { data := '0000010'B , + extensionbit := '0'B } , + more_extension := '000080'O } , + oct3 := omit } + + const octetstring o :='1234560A01010000800202000080'O + + if ((enc_RAW_PDU_127_Bit(i) == o)and(dec_RAW_PDU_127_Bit(o) == i )) {setverdict(pass);} + else {setverdict(fail,"enc_RAW_PDU_127_Bit(i)= ", enc_RAW_PDU_127_Bit(i), "; dec_RAW_PDU_127_Bit(o)= ", dec_RAW_PDU_127_Bit(o));} +} + + +// Tests with units +type record Rec1_Bit { + bitstring len length(64), + octetstring data +} +with { + variant (len) "LENGTHTO(data)"; + variant (len) "UNIT(bits)" +} + +type record Rec1_Octet { + octetstring len length(8), + octetstring data +} +with { + variant (len) "LENGTHTO(data)"; + variant (len) "UNIT(bits)" +} + +testcase TC_with_units_1() runs on TempComp { + var Rec1_Bit val := { int2bit(0, 64), '01FF'O }; + var bitstring enc_exp := oct2bit('100000000000000001FF'O); + var bitstring enc := encvalue(val); + if (enc_exp != enc) { + setverdict(fail, "Encoding failed. Expected: ", bit2oct(enc_exp), ", got: ", bit2oct(enc)); + } + var Rec1_Bit dec_exp := { int2bit(lengthof(val.data) * 8, 64), val.data }; + var Rec1_Bit dec; + var integer res := decvalue(enc_exp, dec); + if (res != 0) { + setverdict(fail, "Invalid decoding result: ", res); + } else if (dec_exp != dec) { + setverdict(fail, "Decoding failed. Expected: ", dec_exp, ", got: ", dec); + } + setverdict(pass); +} + +testcase TC_with_units_2() runs on TempComp { + var Rec1_Octet val := { int2oct(0, 8), '01FF'O }; + var bitstring enc_exp := oct2bit('100000000000000001FF'O); + var bitstring enc := encvalue(val); + if (enc_exp != enc) { + setverdict(fail, "Encoding failed. Expected: ", bit2oct(enc_exp), ", got: ", bit2oct(enc)); + } + var Rec1_Octet dec_exp := { int2oct(lengthof(val.data) * 8, 8), val.data }; + var Rec1_Octet dec; + var integer res := decvalue(enc_exp, dec); + if (res != 0) { + setverdict(fail, "Invalid decoding result: ", res); + } else if (dec_exp != dec) { + setverdict(fail, "Decoding failed. Expected: ", dec_exp, ", got: ", dec); + } + setverdict(pass); +} + + +// Tests with LENGTHINDEX +type integer INT1 +with { + variant "FIELDLENGTH(8)" +} + +type record InnerRec { + INT1 len +} +with { variant "" } + +type record OuterRec { + InnerRec lengthRec, + octetstring field +} +with { + variant (lengthRec) "LENGTHTO(field)"; + variant (lengthRec) "LENGTHINDEX(len)" +} + +testcase TC_with_lengthindex_1() runs on TempComp { + var OuterRec val := { { 0 }, '01FF'O }; + var bitstring enc_exp := oct2bit('0201FF'O); + var bitstring enc := encvalue(val); + log(bit2oct(enc_exp)); + log(bit2oct(enc)); + if (enc_exp != enc) { + setverdict(fail, "Encoding failed. Expected: ", bit2oct(enc_exp), ", got: ", bit2oct(enc)); + } + + var OuterRec dec_exp := { { 2 }, val.field }; + var OuterRec dec; + var integer res := decvalue(enc_exp, dec); + if (res != 0) { + setverdict(fail, "Invalid decoding result: ", res); + } + else if (dec_exp != dec) { + setverdict(fail, "Decoding failed. Expected: ", dec_exp, ", got: ", dec); + } + setverdict(pass); +} + +type octetstring OCT1 +with { + variant "FIELDLENGTH(1)" +} + +type record InnerRecOct { + OCT1 len +} +with { variant "" } + +type record OuterRecOct { + InnerRecOct lengthRec, + octetstring field +} +with { + variant (lengthRec) "LENGTHTO(field)"; + variant (lengthRec) "LENGTHINDEX(len)" +} + +testcase TC_with_lengthindex_2() runs on TempComp { + var OuterRecOct val := { { '00'O }, '01FF'O }; + var bitstring enc_exp := oct2bit('0201FF'O); + var bitstring enc := encvalue(val); + log(bit2oct(enc_exp)); + log(bit2oct(enc)); + if (enc_exp != enc) { + setverdict(fail, "Encoding failed. Expected: ", bit2oct(enc_exp), ", got: ", bit2oct(enc)); + } + + var OuterRecOct dec_exp := { { '02'O }, val.field }; + var OuterRecOct dec; + var integer res := decvalue(enc_exp, dec); + if (res != 0) { + setverdict(fail, "Invalid decoding result: ", res); + } + else if (dec_exp != dec) { + setverdict(fail, "Decoding failed. Expected: ", dec_exp, ", got: ", dec); + } + setverdict(pass); +} + +type bitstring BIT8 +with { + variant "FIELDLENGTH(8)" +} + +type record InnerRecBit { + BIT8 len +} +with { variant "" } + +type record OuterRecBit { + InnerRecBit lengthRec, + octetstring field +} +with { + variant (lengthRec) "LENGTHTO(field)"; + variant (lengthRec) "LENGTHINDEX(len)" +} + +testcase TC_with_lengthindex_3() runs on TempComp { + var OuterRecBit val := { { '00000000'B }, '01FF'O }; + var bitstring enc_exp := oct2bit('0201FF'O); + var bitstring enc := encvalue(val); + log(bit2oct(enc_exp)); + log(bit2oct(enc)); + if (enc_exp != enc) { + setverdict(fail, "Encoding failed. Expected: ", bit2oct(enc_exp), ", got: ", bit2oct(enc)); + } + + var OuterRecBit dec_exp := { { '00000010'B }, val.field }; + var OuterRecBit dec; + var integer res := decvalue(enc_exp, dec); + if (res != 0) { + setverdict(fail, "Invalid decoding result: ", res); + } + else if (dec_exp != dec) { + setverdict(fail, "Decoding failed. Expected: ", dec_exp, ", got: ", dec); + } + setverdict(pass); +} + +//=========================================== +// CONTROL PART +//=========================================== +control { + execute(TC_record_with_EXTENSION_BIT_1_Octet()); + execute(TC_record_with_EXTENSION_BIT_2_Octet()); + execute(TC_record_with_EXTENSION_BIT_3_Octet()); + execute(TC_record_with_EXTENSION_BIT_4_Octet()); + execute(TC_record_with_EXTENSION_BIT_5_Octet()); + execute(TC_record_with_EXTENSION_BIT_6_Octet()); + execute(TC_record_with_EXTENSION_BIT_7_Octet()); + execute(TC_record_with_EXTENSION_BIT_8_Octet()); + execute(TC_record_with_EXTENSION_BIT_9_Octet()); + execute(TC_record_with_EXTENSION_BIT_1_Bit()); + execute(TC_record_with_EXTENSION_BIT_2_Bit()); + execute(TC_record_with_EXTENSION_BIT_3_Bit()); + execute(TC_record_with_EXTENSION_BIT_4_Bit()); + execute(TC_record_with_EXTENSION_BIT_5_Bit()); + execute(TC_record_with_EXTENSION_BIT_6_Bit()); + execute(TC_record_with_EXTENSION_BIT_7_Bit()); + execute(TC_record_with_EXTENSION_BIT_8_Bit()); + execute(TC_record_with_EXTENSION_BIT_9_Bit()); + execute(TC_with_units_1()); + execute(TC_with_units_2()); + execute(TC_with_lengthindex_1()); + execute(TC_with_lengthindex_2()); + execute(TC_with_lengthindex_3()); +} + +} with { encode "RAW" } diff --git a/regression_test/EncodeDecode/RAW/RAW_repeat/RAW_repeat_test.ttcn b/regression_test/EncodeDecode/RAW/RAW_repeat/RAW_repeat_test.ttcn index df8af22b1..b4cd62674 100644 --- a/regression_test/EncodeDecode/RAW/RAW_repeat/RAW_repeat_test.ttcn +++ b/regression_test/EncodeDecode/RAW/RAW_repeat/RAW_repeat_test.ttcn @@ -29,13 +29,22 @@ type record IE1{ type record IE2{ OCT1 ie_type, - integer len, + octetstring len length(1), octetstring data } with { variant "PRESENCE(ie_type = '02'O)" variant (len) "LENGTHTO(data)" } +type record IE3{ + OCT1 ie_type, + bitstring len length(8), + octetstring data +} with { + variant "PRESENCE(ie_type = '03'O)" + variant (len) "LENGTHTO(data)" +} + type record unknown_IE{ OCT1 ie_type, integer len, @@ -49,6 +58,7 @@ type record of unknown_IE unknown_IE_list type set PDU{ IE1 ie1_field, IE2 ie2_field optional, + IE3 ie3_field optional, unknown_IE_list unknown_ies optional } with { variant (unknown_ies) "REPEATABLE(yes)" @@ -59,24 +69,20 @@ with { extension "prototype(backtrack) decode(RAW)" } // no spread record of testcase tc_1() runs on CT { - var octetstring stream; + var octetstring stream := '010100020100030100040100050100'O ; // IE1, IE2, IE3, unknown IE var PDU pdu_decoded; var PDU pdu_expected := { ie1_field := { ie_type := '01'O, len:=1, data := '00'O }, - ie2_field := { ie_type := '02'O, len:=1, data := '00'O }, + ie2_field := { ie_type := '02'O, len:='01'O, data := '00'O }, + ie3_field := { ie_type := '03'O, len:='00000001'B, data := '00'O }, unknown_ies := { - { ie_type := '03'O, len:=1, data := '00'O}, - { ie_type := '04'O, len:=1, data := '00'O} + { ie_type := '04'O, len:=1, data := '00'O}, + { ie_type := '05'O, len:=1, data := '00'O} } } - var integer result; - stream := '010100020100030100040100'O // IE1, IE2, unknown IE + var integer result; result:=dec_PDU_backtrack(stream,pdu_decoded); - log(stream); - log(result) // { ie1_field := { ie_type := '01'O, len := 1, data := '00'O }, ie2_field := { ie_type := '02'O, len := 1, data := '00'O }, unknown_ies := { { ie_type := '03'O, len := 1, data := '00'O }, { ie_type := '04'O, len := 1, data := '00'O } } } - log(pdu_decoded); - if (result != 0) { setverdict(fail, "decoding failed"); } else if ( pdu_decoded != pdu_expected) { @@ -90,22 +96,19 @@ testcase tc_1() runs on CT { // spread record of testcase tc_2() runs on CT { - var octetstring stream := '010100030100020100040100'O // IE1, unknown IE, IE2 -> IE2 added to the unknown_ies + var octetstring stream := '010100030100040100020100050100'O // IE1, IE3, unknown IE, IE2 -> IE2 added to the unknown_ies var PDU pdu_decoded; var PDU pdu_expected := { ie1_field := { ie_type := '01'O, len:=1, data := '00'O }, - ie2_field := { ie_type := '02'O, len:=1, data := '00'O }, + ie2_field := { ie_type := '02'O, len:='01'O, data := '00'O }, + ie3_field := { ie_type := '03'O, len:='00000001'B, data := '00'O }, unknown_ies := { - { ie_type := '03'O, len:=1, data := '00'O}, - { ie_type := '04'O, len:=1, data := '00'O} + { ie_type := '04'O, len:=1, data := '00'O}, + { ie_type := '05'O, len:=1, data := '00'O} } } var integer result; - // stream := '010100030100020100040100'O // IE1, unknown IE, IE2 -> IE2 added to the unknown_ies result:=dec_PDU_backtrack(stream,pdu_decoded); - log(stream) - log(result) // { ie1_field := { ie_type := '01'O, len := 1, data := '00'O }, ie2_field := omit, unknown_ies := { { ie_type := '03'O, len := 1, data := '00'O }, { ie_type := '02'O, len := 1, data := '00'O }, { ie_type := '04'O, len := 1, data := '00'O } } } - log(pdu_decoded) if (result != 0) { setverdict(fail, "decoding failed"); } else if ( pdu_decoded != pdu_expected) { @@ -119,24 +122,22 @@ testcase tc_2() runs on CT { // spread record of testcase tc_3() runs on CT { - var octetstring stream := '010100030100020100020100040100020100'O; // IE1, unknown IE, IE2 , IE2, unknown IE, IE2 which should be at the unknown_ies list. The ie2_field is not repeatable + var octetstring stream := '010100030100040100020100020100050100020100'O; // IE1, IE3, unknown IE, IE2 , IE2, unknown IE, IE2 which should be at the unknown_ies list. The ie2_field is not repeatable var PDU pdu_decoded; var PDU pdu_expected := { ie1_field := { ie_type := '01'O, len:=1, data := '00'O }, - ie2_field := { ie_type := '02'O, len:=1, data := '00'O }, + ie2_field := { ie_type := '02'O, len:='01'O, data := '00'O }, + ie3_field := { ie_type := '03'O, len:='00000001'B, data := '00'O }, unknown_ies := { - { ie_type := '03'O, len:=1, data := '00'O}, - { ie_type := '02'O, len:=1, data := '00'O}, { ie_type := '04'O, len:=1, data := '00'O}, + { ie_type := '02'O, len:=1, data := '00'O}, + { ie_type := '05'O, len:=1, data := '00'O}, { ie_type := '02'O, len:=1, data := '00'O} } } var integer result; result:=dec_PDU_backtrack(stream,pdu_decoded); - log(stream) - log(result) // { ie1_field := { ie_type := '01'O, len := 1, data := '00'O }, ie2_field := omit, unknown_ies := { { ie_type := '03'O, len := 1, data := '00'O }, { ie_type := '02'O, len := 1, data := '00'O }, { ie_type := '04'O, len := 1, data := '00'O } } } - log(pdu_decoded) if (result != 0) { setverdict(fail, "decoding failed"); } else if ( pdu_decoded != pdu_expected) { -- GitLab From da7b29f620be0d9c0c0581bba9c4a0bb39cfa72f Mon Sep 17 00:00:00 2001 From: Adam Knapp Date: Tue, 5 Apr 2022 11:09:27 +0200 Subject: [PATCH 4/5] Documentation update with lengthto and dynamic encoding Signed-off-by: Adam Knapp --- .../4-ttcn3_language_extensions.adoc | 48 +++++++++++++++---- 1 file changed, 38 insertions(+), 10 deletions(-) diff --git a/usrguide/referenceguide/4-ttcn3_language_extensions.adoc b/usrguide/referenceguide/4-ttcn3_language_extensions.adoc index 104f27c51..48a7a4846 100644 --- a/usrguide/referenceguide/4-ttcn3_language_extensions.adoc +++ b/usrguide/referenceguide/4-ttcn3_language_extensions.adoc @@ -1381,8 +1381,9 @@ Differences from the legacy method: * `encode` and `variant` attributes can be defined for types as described in the TTCN-3 standard (although the type restrictions for built-in codecs still apply); * a type can have multiple `encode` attributes (this provides the option to choose from multiple codecs, even user-defined ones, when encoding values of that type); * ASN.1 types automatically have `BER`, `JSON`, `PER` (see section <>), and XML (if the compiler option `-a` is set) encoding (they are treated as if they had the corresponding `encode` attributes); -* encoding-specific `variant` attributes are supported(e.g.: `variant "XML"."untagged"`); -* the parameters `encoding_info/decoding_info` and `dynamic_encoding` of predefined functions `encvalue`, `decvalue`, `encvalue_unichar` and `decvalue_unichar` are supported (the `dynamic_encoding` parameter can be used for choosing the codec to use for values of types with multiple encodings; the `encoding_info`/`decoding_info` parameters are currently ignored); +* encoding-specific `variant` attributes are supported (e.g.: `variant "XML"."untagged"`); +* the parameters `encoding_info/decoding_info` and `dynamic_encoding` of predefined functions `encvalue`, `decvalue`, `encvalue_unichar` and `decvalue_unichar` are supported (the `encoding_info`/`decoding_info` parameters are currently ignored, see also the next point) +* the `dynamic_encoding` parameter can be used for choosing the codec to use for values of types with multiple encodings, the following values are available: `BER:2002`, `CER:2002`, `DER:2002`, `JSON`, `OER`, `RAW`, `TEXT`, `XER`, `XML`; * the `self.setencode` version of the `setencode` operation is supported (it can be used for choosing the codec to use for types with multiple encodings within the scope of the current component); * the `@local` modifier is supported for `encode` attributes; * a type's the default codec (used by `decmatch` templates, the @decoded modifier, and the predefined functions `encvalue`, `decvalue`, `encvalue_unichar` and `decvalue_unichar` when no dynamic encoding parameter is given) is: @@ -1794,7 +1795,7 @@ The TTCN-3 standard defines a mechanism using `attributes` to define, among othe ==== General Rules -If an `attribute` can be assigned to a given type, it can also almost always be assigned to the same type of fields in a `record`, set or `union`. Attributes belonging to a `record` or `set` field overwrites the effect of the same attributes specified for the type of the field. +If an `attribute` can be assigned to a given type, it can also almost always be assigned to the same type of fields in a `record`, `set` or `union`. Attributes belonging to a `record` or `set` field overwrites the effect of the same attributes specified for the type of the field. The location of an attribute is evaluated before the attribute itself. This means that if an attribute is overwritten thanks to its qualification or the overwriting rules, or both, its validity at the given location will not be checked. @@ -2982,7 +2983,7 @@ Description: The encoder is able to calculate the encoded length of one or sever If the offset is present, it is added to or subtracted from (the operation specified in the attribute is performed) the calculated length during encoding. During decoding, the offset is subtracted from or added to (the opposite operation to the one specified in the attribute is performed) the decoded value of the length field. -NOTE: The length is expressed in units defined by the attribute UNIT The default unit is octet. The length field should be a TTCN-3 `integer` or `union` type. Special union containing only integer fields can be used for variable length field. It must not be used with `LENGTHINDEX`. The length field can be included in to the sum of the lengths of multiple fields (e.g. `lengthField` + `field2` + `field3`). The `union` field is NOT selected by the encoder. So the suitable field must be selected before encoding! The fields included in the length computing need not be continuous. +NOTE: The length is expressed in units defined by the attribute UNIT The default unit is octet. The length field should be a TTCN-3 `integer`, `bitstring`, `octetstring` or `union` type. Special union containing only `integer`, `bitstring` or `octetstring` fields can be used for variable length field. It must not be used with `LENGTHINDEX`. The length field can be included in to the sum of the lengths of multiple fields (e.g. `lengthField` + `field2` + `field3`). The `union` field is NOT selected by the encoder. So the suitable field must be selected before encoding! The fields included in the length computing need not be continuous. If `bitstring` or `octetstring` type is used, the length of the field must be specified either with `length()` subtyping or with the `FIELDLENGTH` variant. Examples: [source] @@ -2995,7 +2996,7 @@ octetstring field2 } with { -variant (len) "LENGTHTO(field1); +variant (len) "LENGTHTO(field1)"; variant (len) "UNIT(bits)" } @@ -3008,7 +3009,7 @@ octetstring field2 } with { -variant (len) "LENGTHTO(len, field1, field2) +variant (len) "LENGTHTO(len, field1, field2)" } //Example number 3) @@ -3016,12 +3017,12 @@ variant (len) "LENGTHTO(len, field1, field2) type record Rec3 { INT1 len, OCT3 field1, -OCT1 field2 +OCT1 field2, octetstring field3 } with { -variant (len) "LENGTHTO(field1, field3) +variant (len) "LENGTHTO(field1, field3)" // field2 is excluded! } @@ -3040,7 +3041,7 @@ length_union length_field, octetstring data } with { variant (length_field) -"CROSSTAG(short_length_field, flag = '0'B +"CROSSTAG(short_length_field, flag = '0'B; long_length_field, flag = '1'B)"; variant (length_field) "LENGTHTO(data)" } @@ -3091,6 +3092,31 @@ variant (len) "LENGTHTO(field) - 2" // (1 is added to the length of `field') // and '0212345678'O would be decoded into { len := 4, field := '12345678'O } // (1 is subtracted from the decoded value of `len') + +//Example number 7): octetstring +type record Rec7 { +octetstring len length(1), // length of this field in octet +OCT3 field1, +octetstring field2 +} + +with { +variant (len) "LENGTHTO(field1)"; +variant (len) "UNIT(bits)" +} + +//Example number 8): bitstring +type record Rec8 { +btstring len, +OCT3 field1, +octetstring field2 +} + +with { +variant (len) "FIELDLENGTH(8)"; // length of this field in bits +variant (len) "LENGTHTO(field1)"; +variant (len) "UNIT(bits)" +} ---- *LENGTHINDEX* @@ -3108,7 +3134,8 @@ Can be used with: fields of a `record`. Description: This attribute extends the `LENGTHTO` attribute with the identification of the nested field containing the length value within the field of the corresponding `LENGTHTO` attribute. Comment: See also the description of the `LENGTHTO` attribute. -NOTE: The field named by `LENGTHINDEX` attribute should be a TTCN-3 integer type. + +NOTE: The field named by `LENGTHINDEX` attribute should be a TTCN-3 `integer`, `bitstring` or `octetstring` type. Example (see also example of `LENGTHTO` attribute). [source] @@ -3147,6 +3174,7 @@ Can be used with: fields of a `record`. Description: Some record fields contain the distance to another encoded field. Records can be encoded in the form of: `ptr1`, `ptr2`, `ptr3`, `field1`, `field2`, `field3`, where the position of fieldN within the encoded stream can be determined from the value and position of field ptrN. The distance of the pointed field from the base field will be `ptrN` * `UNIT` + `PTROFFSET`. The default base field is the pointer itself. The base field can be set by the PTROFFSET attribute. When the pointed field is optional, the pointer value 0 indicates the absence of the pointed field. Comment: See also the description of `UNIT` (0) and `PTROFFSET` (0) attributes. + NOTE: Pointer fields should be TTCN-3 `integer` type. Examples: -- GitLab From 7d3aee850f8789c4342a59ce00a9ab92ebf45f09 Mon Sep 17 00:00:00 2001 From: Adam Knapp Date: Tue, 5 Apr 2022 11:10:23 +0200 Subject: [PATCH 5/5] Fixing missing cases Signed-off-by: Adam Knapp --- core/Template.cc | 3 +++ 1 file changed, 3 insertions(+) diff --git a/core/Template.cc b/core/Template.cc index 53a9f3f05..eaaf18cb7 100644 --- a/core/Template.cc +++ b/core/Template.cc @@ -2181,6 +2181,9 @@ int Set_Of_Template::n_elem() const case VALUE_RANGE: case STRING_PATTERN: case DECODE_MATCH: + case CONJUNCTION_MATCH: + case IMPLICATION_MATCH: + case DYNAMIC_MATCH: break; } TTCN_error("Performing n_elem() operation on an uninitialized/unsupported " -- GitLab