From 27abc22b47d5375e6f8171873c6786cff47a61f5 Mon Sep 17 00:00:00 2001 From: BenceJanosSzabo <bence.janos.szabo@ericsson.com> Date: Mon, 10 Apr 2017 12:49:19 +0200 Subject: [PATCH] Implement ports with translation capability (part5) finishing touches Change-Id: If5aff1c37233b8fa3db861bc31ef825ecd953614 Signed-off-by: BenceJanosSzabo <bence.janos.szabo@ericsson.com> --- compiler2/ttcn3/port.c | 33 ++- core/Port.cc | 12 +- regression_test/portTranslation/P1.cc | 15 +- regression_test/portTranslation/P1.hh | 2 + .../portTranslation/PortTranslation.ttcn | 239 ++++++++++++++++-- .../portTranslation/PortVariables.ttcn | 1 - 6 files changed, 272 insertions(+), 30 deletions(-) diff --git a/compiler2/ttcn3/port.c b/compiler2/ttcn3/port.c index 6f9eea304..ad6829233 100644 --- a/compiler2/ttcn3/port.c +++ b/compiler2/ttcn3/port.c @@ -81,6 +81,9 @@ static char *generate_send_mapping(char *src, const port_def *pdef, } } src = mputstr(src, ") {\n"); + // Beginning of the loop of the PARTIALLY_TRANSLATED case to process all + // messages + src = mputstr(src, "do {\n"); src = mputstr(src, "TTCN_Runtime::set_translation_mode(TRUE, this);\n"); // Set to unset src = mputstr(src, "TTCN_Runtime::set_port_state(-1, \"by test environment.\", TRUE);\n"); @@ -168,7 +171,7 @@ static char *generate_send_mapping(char *src, const port_def *pdef, if (!pdef->legacy && pdef->port_type == USER) { src = mputstr(src, "TTCN_Runtime::set_translation_mode(FALSE, NULL);\n" - "if (port_state == TRANSLATED) {\n"); + "if (port_state == TRANSLATED || port_state == PARTIALLY_TRANSLATED) {\n"); } src = mputprintf(src, "if (TTCN_Logger::log_this_event(" "TTCN_Logger::PORTEVENT_DUALSEND)) {\n" @@ -195,7 +198,13 @@ static char *generate_send_mapping(char *src, const port_def *pdef, if (pdef->testport_type != INTERNAL) src = mputstr(src, "}\n"); } if (has_condition) { + if (!pdef->legacy && pdef->port_type == USER) { + src = mputstr(src, "if (port_state != PARTIALLY_TRANSLATED) {\n"); + } src = mputstr(src, "return;\n"); + if (!pdef->legacy && pdef->port_type == USER) { + src = mputstr(src, "}\n"); + } if (pdef->legacy) { src = mputstr(src, "}\n"); } @@ -203,12 +212,16 @@ static char *generate_send_mapping(char *src, const port_def *pdef, } if (!pdef->legacy && pdef->port_type == USER) { src = mputprintf(src, + "} else if (port_state == FRAGMENTED) {\n" + "return;\n" "} else if (port_state == UNSET) {\n" "TTCN_error(\"The state of the port %%s remained unset after the mapping function %s finished.\", port_name);\n" "}\n", target->mapping.function.dispname); } if (mapped_type->nTargets > 1) src = mputstr(src, "}\n"); if (!pdef->legacy && pdef->port_type == USER) { + // End of the do while loop to process all the messages + src = mputstr(src, "} while (port_state == PARTIALLY_TRANSLATED);\n"); // end of the outgoing messages of port with mapping target check src = mputstr(src, "}\n"); } @@ -255,8 +268,11 @@ static char *generate_incoming_mapping(char *src, const port_def *pdef, /* has_buffer will be set to TRUE later */ } if (!pdef->legacy && pdef->port_type == USER) { + // Beginning of the loop of the PARTIALLY_TRANSLATED case to process all + // messages + src = mputstr(src, "do {\n"); src = mputstr(src, "TTCN_Runtime::set_translation_mode(TRUE, this);\n"); - src = mputstr(src, "port_state = UNSET;\n"); + src = mputstr(src, "TTCN_Runtime::set_port_state(-1, \"by test environment.\", TRUE);\n"); } if (mapped_type->nTargets > 1) src = mputstr(src, "{\n"); switch (target->mapping_type) { @@ -380,7 +396,7 @@ static char *generate_incoming_mapping(char *src, const port_def *pdef, "new_item->sender_component = sender_component;\n", !pdef->legacy && pdef->port_type == USER ? "TTCN_Runtime::set_translation_mode(FALSE, NULL);\n" - "if (port_state == TRANSLATED) {\n" : "", + "if (port_state == TRANSLATED || port_state == PARTIALLY_TRANSLATED) {\n" : "", target->target_dispname, (unsigned long) target->target_index, (unsigned long) target->target_index); @@ -405,6 +421,10 @@ static char *generate_incoming_mapping(char *src, const port_def *pdef, "}"); if (pdef->port_type == USER && !pdef->legacy) { src = mputprintf(src, + " else if (port_state == FRAGMENTED) {\n" + "delete mapped_par;\n" + "return;\n" + "}" " else if (port_state == UNSET) {\n" "delete mapped_par;\n" "TTCN_error(\"The state of the port %%s remained unset after the mapping function %s finished.\", port_name);\n" @@ -415,6 +435,9 @@ static char *generate_incoming_mapping(char *src, const port_def *pdef, report_error = TRUE; } if (mapped_type->nTargets > 1) src = mputstr(src, "}\n"); + if (pdef->port_type == USER && !pdef->legacy) { + src = mputstr(src, "} while (port_state == PARTIALLY_TRANSLATED);\n"); + } } /* next mapping target */ if (has_discard) { if (mapped_type->nTargets > 1) { @@ -2528,12 +2551,12 @@ void defPortClass(const port_def* pdef, output_struct* output) "}\n", mapped_type->dispname); // Print the simple mapping after the not simple mappings if (!is_simple || !pdef->legacy) { - if (!pdef->legacy) { + if (!pdef->legacy && mapped_type->nTargets > (is_simple ? 1 : 0)) { // If in translation mode then receive according to incoming mappings src = mputstr(src, "if (in_translation_mode()) {\n"); } src = generate_incoming_mapping(src, pdef, mapped_type, is_simple); - if (!pdef->legacy) { + if (!pdef->legacy && mapped_type->nTargets > (is_simple ? 1 : 0)) { src = mputstr(src, "}\n"); } } diff --git a/core/Port.cc b/core/Port.cc index 844b3ee2a..15eba7dd3 100644 --- a/core/Port.cc +++ b/core/Port.cc @@ -302,6 +302,12 @@ void PORT::activate_port() msg_tail_count = 0; proc_head_count = 0; proc_tail_count = 0; + + // Only has effect when the translation port has port variables with + // default values. Only call when it is activated. + if (n_system_mappings == 0) { + init_port_variables(); + } } } @@ -2149,12 +2155,6 @@ void PORT::map(const char *system_port) TTCN_Logger::log_port_misc( TitanLoggerApi::Port__Misc_reason::port__was__mapped__to__system, port_name, SYSTEM_COMPREF, system_port); - - // Only has effect when the translation port has port variables with - // default values. Only call when it is mapped first. - if (n_system_mappings == 0) { - init_port_variables(); - } // the mapping shall be registered in the table only if user_map() was // successful diff --git a/regression_test/portTranslation/P1.cc b/regression_test/portTranslation/P1.cc index 3fb1fd746..d5644e0b4 100644 --- a/regression_test/portTranslation/P1.cc +++ b/regression_test/portTranslation/P1.cc @@ -86,7 +86,15 @@ void P1_PROVIDER::outgoing_send(const OCTETSTRING& send_par) void P1_PROVIDER::outgoing_send(const BITSTRING& send_par) { - incoming_message(send_par); + // Test that the receive mapping handles fragmented case + if (send_par.lengthof() == 48) { + for (int i = 0; i < 48; i++) { + BITSTRING bs = send_par[i]; + incoming_message(bs); + } + } else { + incoming_message(send_par); + } } void P1_PROVIDER::outgoing_send(const CHARSTRING& send_par) @@ -99,5 +107,10 @@ void P1_PROVIDER::outgoing_send(const INTEGER& send_par) incoming_message(send_par); } +void P1_PROVIDER::outgoing_send(const HEXSTRING& send_par) +{ + incoming_message(send_par); +} + } /* end of namespace */ diff --git a/regression_test/portTranslation/P1.hh b/regression_test/portTranslation/P1.hh index 15dcee8d3..b8a430793 100644 --- a/regression_test/portTranslation/P1.hh +++ b/regression_test/portTranslation/P1.hh @@ -51,10 +51,12 @@ public: void outgoing_send(const BITSTRING& send_par); void outgoing_send(const CHARSTRING& send_par); void outgoing_send(const INTEGER& send_par); + void outgoing_send(const HEXSTRING& send_par); virtual void incoming_message(const INTEGER& incoming_par) = 0; virtual void incoming_message(const BITSTRING& incoming_par) = 0; virtual void incoming_message(const OCTETSTRING& incoming_par) = 0; virtual void incoming_message(const CHARSTRING& incoming_par) = 0; + virtual void incoming_message(const HEXSTRING& incoming_par) = 0; }; } /* end of namespace */ diff --git a/regression_test/portTranslation/PortTranslation.ttcn b/regression_test/portTranslation/PortTranslation.ttcn index d57dde601..5a9c0ef89 100644 --- a/regression_test/portTranslation/PortTranslation.ttcn +++ b/regression_test/portTranslation/PortTranslation.ttcn @@ -101,19 +101,94 @@ module PortTranslation { extension "prototype(fast)"; } - function hex_to_bit(in hexstring i, out bitstring j) { - if (lengthof(i) > 4) { - j := hex2bit(substr(i, 0, 4)); - i := substr(i, 4, lengthof(i)-4); - port.setstate(3); // partially translated, more messages to decode + function hex_to_hex(in hexstring i, out hexstring j) port PT2 { + log("asdf"); + if (lengthof(i) != 14) { + port.setstate(1, "hex_to_hex"); } else { - j := hex2bit(substr(i, 0, lengthof(i))); - port.setstate(0); // translated + if (lengthof(i) > index + 4) { + j := substr(i, index, 4); + index := index + 4; + port.setstate(3, "hex_to_hex"); // partially translated, more messages to decode + } else { + j := substr(i, index, lengthof(i) - index); + port.setstate(0); // translated + } + } + } with { + extension "prototype(fast)"; + } + + function hex_to_bit_buffer(in hexstring i, out bitstring j) port PT2 { + log("asdf2"); + if (lengthof(i) == 12 or lengthof(i) == 10) { + port.setstate(1); + } else { + if (lengthof(buffer) != 14) { + buffer := buffer & i; + port.setstate(2, "hex_to_bit_buffer"); + } + if (lengthof(buffer) == 14) { + j := hex2bit(buffer); + port.setstate(0, "hex_to_bit_buffer"); + buffer := ''H; + } + } + } with { + extension "prototype(fast)"; + } + + function hex_to_bit2(in hexstring i, out bitstring j) { + log("ff"); + j := hex2bit(i); + port.setstate(0, "hex_to_bit2"); + } with { + extension "prototype(fast)"; + } + + function bit_to_bit_buffer(in bitstring i, out bitstring j) port PT2 { + if (lengthof(i) != 1) { + port.setstate(1); + } else { + if (lengthof(bit_buffer) != 48) { + bit_buffer := bit_buffer & i; + port.setstate(2); + } + if (lengthof(bit_buffer) == 48) { + j := bit_buffer; + port.setstate(0); + bit_buffer := ''B; + } } } with { extension "prototype(fast)"; } + function bit_to_bit_fragmented(in bitstring i, out bitstring j) port PT2 { + log("a"); + if (lengthof(i) != 40) { + port.setstate(1); + } else { + if (lengthof(i) > index2 + 16) { + j := substr(i, index2, 16); + index2 := index2 + 16; + port.setstate(3); // partially translated, more messages to decode + } else { + j := substr(i, index2, lengthof(i) - index2); + port.setstate(0, "bit_to_bit_fragmented"); // translated + } + } + } with { + extension "prototype(fast)"; + } + + function bit_to_bit(in bitstring i, out bitstring j) port PT2 { + j := i; + port.setstate(0, "bit_to_bit"); + } with { + extension "prototype(fast)"; + } + function hex_to_char(in hexstring i, out charstring j) { // dummy } with { @@ -141,8 +216,8 @@ module PortTranslation { } type port P1 message { - in bitstring, octetstring, charstring - out MyRec, octetstring, bitstring, charstring + in bitstring, octetstring, charstring, hexstring + out MyRec, octetstring, bitstring, charstring, hexstring inout integer } with { extension "provider" @@ -166,8 +241,14 @@ module PortTranslation { in integer, octetstring, hexstring from charstring with char_to_hex() : charstring with char_to_hex2() out MyRec to octetstring with MyRec_to_oct() : integer with MyRec_to_int() : MyRec with MyRec_to_MyRec() : charstring with MyRec_to_char() : hexstring with MyRec_to_hex() out octetstring - inout bitstring - out hexstring to bitstring with hex_to_bit() : charstring with hex_to_char() + out bitstring + in bitstring from bitstring with bit_to_bit_buffer() : bitstring with bit_to_bit_fragmented() : bitstring with bit_to_bit() + out hexstring to hexstring with hex_to_hex() : bitstring with hex_to_bit_buffer() : bitstring with hex_to_bit2() : charstring with hex_to_char() + + var integer index := 0; + var integer index2 := 0; + var hexstring buffer := ''H; + var bitstring bit_buffer := ''B; } @@ -249,6 +330,7 @@ module PortTranslation { } t.stop; + // Send back the bitstring var bitstring bs := '010101'B; p.send(bs); t.start; @@ -461,16 +543,136 @@ module PortTranslation { map(self:p, system:p1); var hexstring hs := '12345678ABCDEF'H; p.send(hs); - // TODO: wait for port variables + timer t := 1.0; + t.start; + alt { + [] p.receive('1234'H) { setverdict(pass); } + [] p.receive(integer:?) { setverdict(fail); } + [] p.receive(octetstring:?) { setverdict(fail); } + [] t.timeout { setverdict(fail); } + } + t.stop; + + t.start; + alt { + [] p.receive('5678'H) { setverdict(pass); } + [] p.receive(integer:?) { setverdict(fail); } + [] p.receive(octetstring:?) { setverdict(fail); } + [] t.timeout { setverdict(fail); } + } + t.stop; + + t.start; + alt { + [] p.receive('ABCD'H) { setverdict(pass); } + [] p.receive(integer:?) { setverdict(fail); } + [] p.receive(octetstring:?) { setverdict(fail); } + [] t.timeout { setverdict(fail); } + } + t.stop; + + t.start; + alt { + [] p.receive('EF'H) { setverdict(pass); } + [] p.receive(integer:?) { setverdict(fail); } + [] p.receive(octetstring:?) { setverdict(fail); } + [] t.timeout { setverdict(fail); } + } + t.stop; } testcase tc_send_fragmented() runs on MyComp system System { map(self:p, system:p1); - var hexstring hs := '12345678ABCDEF'H; - p.send(hs); - // TODO: wait for port variables + + p.send('1234'H); + timer t := 0.5; + t.start; + alt { + [] p.receive(bitstring:?) { setverdict(fail); } + [] p.receive(integer:?) { setverdict(fail); } + [] p.receive(octetstring:?) { setverdict(fail); } + [] t.timeout { setverdict(pass); } + } + t.stop; + + p.send('5678'H); + t.start; + alt { + [] p.receive(bitstring:?) { setverdict(fail); } + [] p.receive(integer:?) { setverdict(fail); } + [] p.receive(octetstring:?) { setverdict(fail); } + [] t.timeout { setverdict(pass); } + } + t.stop; + + p.send('ABCD'H); + t.start; + alt { + [] p.receive(bitstring:?) { setverdict(fail); } + [] p.receive(integer:?) { setverdict(fail); } + [] p.receive(octetstring:?) { setverdict(fail); } + [] t.timeout { setverdict(pass); } + } + t.stop; + + p.send('EF'H); + t.start; + alt { + [] p.receive(hex2bit('12345678ABCDEF'H)) { setverdict(pass); } + [] p.receive(integer:?) { setverdict(fail); } + [] p.receive(octetstring:?) { setverdict(fail); } + [] t.timeout { setverdict(fail); } + } + t.stop; + } + + testcase tc_receive_fragmented() runs on MyComp system System { + map(self:p, system:p1); + + p.send('12345678ABCD'H); + timer t := 0.5; + t.start; + alt { + [] p.receive(hex2bit('12345678ABCD'H)) { setverdict(pass); } + [] p.receive(integer:?) { setverdict(fail); } + [] p.receive(octetstring:?) { setverdict(fail); } + [] t.timeout { setverdict(fail); } + } + t.stop; } + testcase tc_receive_partially_translated() runs on MyComp system System { + map(self:p, system:p1); + + p.send('12345678AB'H); + timer t := 0.5; + t.start; + alt { + [] p.receive(hex2bit('1234'H)) { setverdict(pass); } + [] p.receive(integer:?) { setverdict(fail); } + [] p.receive(octetstring:?) { setverdict(fail); } + [] t.timeout { setverdict(fail); } + } + t.stop; + + t.start; + alt { + [] p.receive(hex2bit('5678'H)) { setverdict(pass); } + [] p.receive(integer:?) { setverdict(fail); } + [] p.receive(octetstring:?) { setverdict(fail); } + [] t.timeout { setverdict(fail); } + } + t.stop; + + t.start; + alt { + [] p.receive(hex2bit('AB'H)) { setverdict(pass); } + [] p.receive(integer:?) { setverdict(fail); } + [] p.receive(octetstring:?) { setverdict(fail); } + [] t.timeout { setverdict(fail); } + } + t.stop; + } control { execute(tc_send()) @@ -481,8 +683,11 @@ module PortTranslation { execute(tc_send_and_receive_without_mapping()); - //execute(tc_send_partially_translated()); - //execute(tc_send_fragmented()); + execute(tc_send_partially_translated()); + execute(tc_send_fragmented()); + + execute(tc_receive_partially_translated()); + execute(tc_receive_fragmented()); } } \ No newline at end of file diff --git a/regression_test/portTranslation/PortVariables.ttcn b/regression_test/portTranslation/PortVariables.ttcn index 780d72310..7f8fd0278 100644 --- a/regression_test/portTranslation/PortVariables.ttcn +++ b/regression_test/portTranslation/PortVariables.ttcn @@ -292,7 +292,6 @@ module PortVariables { } t.stop; } - } control { -- GitLab