/****************************************************************************** * Copyright (c) 2000-2014 Ericsson Telecom AB * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html ******************************************************************************/ module dual2 { /*** *** *** *** PDU *** *** *** ***/ type record PDU1 { charstring s } with { variant "" } type record PDU2 { charstring s } with { variant (s) "FIELDLENGTH(8)" } /*** *** *** *** Ports *** *** *** ***/ type port UNDER message { inout octetstring } with { extension "provider" } type port SENDER message { out PDU1; } with { extension "user UNDER out(PDU1 -> octetstring : function(p1o)) in (octetstring -> - : discard) " } type port RECEIVER message { in PDU2 } with { extension "user UNDER //out(PDU1 -> - : discard) in (octetstring -> PDU2 : function(op2sl)) " } /*** *** *** *** mapper functions *** *** *** ***/ // A "prototype(fast)" implemented in TTCN function p1o(in PDU1 p, out octetstring o) { o:= char2oct(p.s); } with { extension "prototype(fast)" } function op2(in octetstring o, out PDU2 p) { p.s := oct2char(o); } with { extension "prototype(fast)" } // A "prototype(sliding)" implemented in TTCN function op2sl(inout octetstring o, out PDU2 p) return integer { //log(">>> op2sl ", o); var integer lo := lengthof(o); // octets, 'ABCD' = 2 if (lo < 8) { //log("<<< return 2: not enough:", lo) return 2; } //else { log("=== length is ", lo) } p.s := oct2char(substr(o, 0, 8)); // "decode" the PDU o := substr(o, 8, lo-8); // return the rest //log(">>> res=", p.s); //log(">>> rem=", o); //log(">>> return 0"); return 0; } with { extension "prototype(sliding)" } /*** *** *** *** Components *** *** *** ***/ type component D2 { port SENDER stringport; port RECEIVER reverseport; port SENDER another_stringport; } type component SYS { //port PT1 SYSTEM_PORT2; } /*** *** *** *** Testcases *** *** *** ***/ // Intrernal communication with mapped ports testcase intern() runs on D2 { connect (mtc:stringport, mtc:reverseport); var PDU1 cr := { "howdy!" } stringport.send(cr); alt { [] reverseport.receive /* anything */ { setverdict(fail, "premature receive"); } [else] { setverdict(pass); } // less than eight bytes: shouldn't receive anything } stringport.send(PDU1 : { "??" }) // the missing two bytes alt { [] reverseport.receive(PDU2 : {"howdy!??"}) { setverdict(pass); } [] reverseport.receive { setverdict(fail, "wrong receive"); } [else] { setverdict(fail, "no receive"); } } disconnect(mtc:stringport, mtc:reverseport); } type set PDU3 { //charstring s, octetstring s, // EXTENSION_BIT not implemented for charstring integer i } with { variant ""; /*FIELDLENGTH(8)*/ variant (s) "EXTENSION_BIT(yes)"; variant (i) "FIELDLENGTH(24)"; // bits } external function enc3(in PDU3 p) return octetstring with { extension "prototype(convert) encode(RAW)" } external function dec3(in octetstring o) return PDU3 with { extension "prototype(convert) decode(RAW)" } external function dec3sl(inout octetstring o, out PDU3 p) return integer with { extension "prototype(sliding) decode(RAW) errorbehavior(INVAL_MSG:WARNING,INCOMPL_MSG:WARNING)" } // Try to elicit various return values from the decoder function testcase errored() runs on D2 system D2 { connect(mtc:stringport, mtc:reverseport); var PDU1 p1 := { "yay....." } stringport.send(p1); alt { [] reverseport.receive(PDU2 : ?) { setverdict(pass, "got PDU2"); } [else] { setverdict(fail, "no receive at ", __LINE__); } } var octetstring three := char2oct("three!!!"); var PDU3 p0 := { s := three, i := 3 }; var octetstring o := enc3(p0); var octetstring incompl; var integer retval; { var PDU3 p; log("=== === === === encoded as ", o); incompl := '74687265652121A11B0000'O; // "three!!!" //p := dec3(incompl); retval := dec3sl(incompl, p); if (retval == 0) { setverdict(pass) } else { setverdict(fail, "nonzero at ", __LINE__); } } { var PDU3 p; log("___ string only ___"); incompl := '74687265652121A1'O; retval := dec3sl(incompl, p); if (retval == 2) { setverdict(pass) } else { setverdict(fail, "not 2 at ", __LINE__); } } { var PDU3 p; log("___ plus nine ___"); incompl := hex2oct('74687265652121A130'H); retval := dec3sl(incompl, p); if (retval == 1) { setverdict(pass) } else { setverdict(fail, "not 1 at ", __LINE__); } } disconnect(mtc:stringport, mtc:reverseport); } // Test sliding decoding with multiple connections testcase two_conn() runs on D2 { connect(mtc:stringport, mtc:reverseport); connect(mtc:another_stringport, mtc:reverseport); var PDU1 p1a := { "ABCD" }, p1e := { "EFGH" } stringport.send(p1a); // first half alt { [] reverseport.receive /* anything */{ setverdict(fail, "It wasn't supposed to receive anything yet"); } [else] /* nothing received */ { setverdict(pass); } } another_stringport.send(p1a); // send first half on another connection alt { [] reverseport.receive /* anything */{ // If the different connections were not properly separated, // a message would appear at this point (eight characters => one message) setverdict(fail, "It STILL wasn't supposed to receive anything yet"); } [else] /* nothing received */ { setverdict(pass); } } stringport.send(p1e); // send second half on the first connection alt { [] reverseport.receive( PDU2 : {"ABCDEFGH"} ) { setverdict(pass); } [else] { setverdict(fail, "no receive"); } } another_stringport.send(p1e); // send second half on the second connection alt { [] reverseport.receive( PDU2 : {"ABCDEFGH"} ) { setverdict(pass); } [else] { setverdict(fail, "no receive"); } } disconnect(mtc:stringport, mtc:reverseport); disconnect(mtc:another_stringport, mtc:reverseport); } control { execute(intern()); execute(errored()); execute(two_conn()); } } // end of module with { encode "RAW" }