Commit | Line | Data |
---|---|---|
970ed795 EL |
1 | /****************************************************************************** |
2 | * Copyright (c) 2000-2014 Ericsson Telecom AB | |
3 | * All rights reserved. This program and the accompanying materials | |
4 | * are made available under the terms of the Eclipse Public License v1.0 | |
5 | * which accompanies this distribution, and is available at | |
6 | * http://www.eclipse.org/legal/epl-v10.html | |
7 | ******************************************************************************/ | |
8 | module dual2 | |
9 | { | |
10 | ||
11 | /*** *** *** *** PDU *** *** *** ***/ | |
12 | type record PDU1 { | |
13 | charstring s | |
14 | } | |
15 | with { variant "" } | |
16 | ||
17 | type record PDU2 { | |
18 | charstring s | |
19 | } | |
20 | with { variant (s) "FIELDLENGTH(8)" } | |
21 | ||
22 | /*** *** *** *** Ports *** *** *** ***/ | |
23 | type port UNDER message { | |
24 | inout octetstring | |
25 | } | |
26 | with { extension "provider" } | |
27 | ||
28 | type port SENDER message { | |
29 | out PDU1; | |
30 | } | |
31 | with { extension "user UNDER | |
32 | out(PDU1 -> octetstring : function(p1o)) | |
33 | in (octetstring -> - : discard) | |
34 | " } | |
35 | ||
36 | type port RECEIVER message { | |
37 | in PDU2 | |
38 | } | |
39 | with { extension "user UNDER | |
40 | //out(PDU1 -> - : discard) | |
41 | in (octetstring -> PDU2 : function(op2sl)) | |
42 | " } | |
43 | ||
44 | /*** *** *** *** mapper functions *** *** *** ***/ | |
45 | ||
46 | // A "prototype(fast)" implemented in TTCN | |
47 | function p1o(in PDU1 p, out octetstring o) { | |
48 | o:= char2oct(p.s); | |
49 | } | |
50 | with { extension "prototype(fast)" } | |
51 | ||
52 | function op2(in octetstring o, out PDU2 p) { | |
53 | p.s := oct2char(o); | |
54 | } | |
55 | with { extension "prototype(fast)" } | |
56 | ||
57 | // A "prototype(sliding)" implemented in TTCN | |
58 | function op2sl(inout octetstring o, out PDU2 p) return integer { | |
59 | //log(">>> op2sl ", o); | |
60 | var integer lo := lengthof(o); // octets, 'ABCD' = 2 | |
61 | if (lo < 8) { | |
62 | //log("<<< return 2: not enough:", lo) | |
63 | return 2; | |
64 | } | |
65 | //else { log("=== length is ", lo) } | |
66 | p.s := oct2char(substr(o, 0, 8)); // "decode" the PDU | |
67 | o := substr(o, 8, lo-8); // return the rest | |
68 | //log(">>> res=", p.s); | |
69 | //log(">>> rem=", o); | |
70 | //log(">>> return 0"); | |
71 | return 0; | |
72 | } | |
73 | with { extension "prototype(sliding)" } | |
74 | ||
75 | /*** *** *** *** Components *** *** *** ***/ | |
76 | type component D2 { | |
77 | port SENDER stringport; | |
78 | port RECEIVER reverseport; | |
79 | port SENDER another_stringport; | |
80 | } | |
81 | ||
82 | type component SYS { | |
83 | //port PT1 SYSTEM_PORT2; | |
84 | } | |
85 | ||
86 | /*** *** *** *** Testcases *** *** *** ***/ | |
87 | ||
88 | // Intrernal communication with mapped ports | |
89 | testcase intern() runs on D2 | |
90 | { | |
91 | connect (mtc:stringport, mtc:reverseport); | |
92 | var PDU1 cr := { "howdy!" } | |
93 | stringport.send(cr); | |
94 | alt { | |
95 | [] reverseport.receive /* anything */ { setverdict(fail, "premature receive"); } | |
96 | [else] { setverdict(pass); } // less than eight bytes: shouldn't receive anything | |
97 | } | |
98 | ||
99 | stringport.send(PDU1 : { "??" }) // the missing two bytes | |
100 | alt { | |
101 | [] reverseport.receive(PDU2 : {"howdy!??"}) { setverdict(pass); } | |
102 | [] reverseport.receive { setverdict(fail, "wrong receive"); } | |
103 | [else] { setverdict(fail, "no receive"); } | |
104 | } | |
105 | disconnect(mtc:stringport, mtc:reverseport); | |
106 | } | |
107 | ||
108 | type set PDU3 { | |
109 | //charstring s, | |
110 | octetstring s, // EXTENSION_BIT not implemented for charstring | |
111 | integer i | |
112 | } | |
113 | with { variant ""; /*FIELDLENGTH(8)*/ | |
114 | variant (s) "EXTENSION_BIT(yes)"; | |
115 | variant (i) "FIELDLENGTH(24)"; // bits | |
116 | } | |
117 | ||
118 | external function enc3(in PDU3 p) return octetstring | |
119 | with { extension "prototype(convert) encode(RAW)" } | |
120 | ||
121 | external function dec3(in octetstring o) return PDU3 | |
122 | with { extension "prototype(convert) decode(RAW)" } | |
123 | ||
124 | external function dec3sl(inout octetstring o, out PDU3 p) return integer | |
125 | with { extension "prototype(sliding) decode(RAW) errorbehavior(INVAL_MSG:WARNING,INCOMPL_MSG:WARNING)" } | |
126 | ||
127 | // Try to elicit various return values from the decoder function | |
128 | testcase errored() runs on D2 system D2 | |
129 | { | |
130 | connect(mtc:stringport, mtc:reverseport); | |
131 | var PDU1 p1 := { "yay....." } | |
132 | stringport.send(p1); | |
133 | ||
134 | alt { | |
135 | [] reverseport.receive(PDU2 : ?) { setverdict(pass, "got PDU2"); } | |
136 | [else] { setverdict(fail, "no receive at ", __LINE__); } | |
137 | } | |
138 | ||
139 | var octetstring three := char2oct("three!!!"); | |
140 | var PDU3 p0 := { s := three, i := 3 }; | |
141 | var octetstring o := enc3(p0); | |
142 | var octetstring incompl; | |
143 | var integer retval; | |
144 | { | |
145 | var PDU3 p; | |
146 | log("=== === === === encoded as ", o); | |
147 | incompl := '74687265652121A11B0000'O; // "three!!!" | |
148 | //p := dec3(incompl); | |
149 | retval := dec3sl(incompl, p); | |
150 | ||
151 | if (retval == 0) { setverdict(pass) } | |
152 | else { setverdict(fail, "nonzero at ", __LINE__); } | |
153 | } | |
154 | ||
155 | { | |
156 | var PDU3 p; | |
157 | log("___ string only ___"); | |
158 | incompl := '74687265652121A1'O; | |
159 | retval := dec3sl(incompl, p); | |
160 | ||
161 | if (retval == 2) { setverdict(pass) } | |
162 | else { setverdict(fail, "not 2 at ", __LINE__); } | |
163 | } | |
164 | ||
165 | { | |
166 | var PDU3 p; | |
167 | log("___ plus nine ___"); | |
168 | incompl := hex2oct('74687265652121A130'H); | |
169 | retval := dec3sl(incompl, p); | |
170 | ||
171 | if (retval == 1) { setverdict(pass) } | |
172 | else { setverdict(fail, "not 1 at ", __LINE__); } | |
173 | } | |
174 | disconnect(mtc:stringport, mtc:reverseport); | |
175 | } | |
176 | ||
177 | // Test sliding decoding with multiple connections | |
178 | testcase two_conn() runs on D2 | |
179 | { | |
180 | connect(mtc:stringport, mtc:reverseport); | |
181 | connect(mtc:another_stringport, mtc:reverseport); | |
182 | ||
183 | var PDU1 p1a := { "ABCD" }, p1e := { "EFGH" } | |
184 | ||
185 | stringport.send(p1a); // first half | |
186 | alt { | |
187 | [] reverseport.receive /* anything */{ | |
188 | setverdict(fail, "It wasn't supposed to receive anything yet"); | |
189 | } | |
190 | [else] /* nothing received */ { setverdict(pass); } | |
191 | } | |
192 | ||
193 | another_stringport.send(p1a); // send first half on another connection | |
194 | alt { | |
195 | [] reverseport.receive /* anything */{ | |
196 | // If the different connections were not properly separated, | |
197 | // a message would appear at this point (eight characters => one message) | |
198 | setverdict(fail, "It STILL wasn't supposed to receive anything yet"); | |
199 | } | |
200 | [else] /* nothing received */ { setverdict(pass); } | |
201 | } | |
202 | ||
203 | stringport.send(p1e); // send second half on the first connection | |
204 | alt { | |
205 | [] reverseport.receive( PDU2 : {"ABCDEFGH"} ) { setverdict(pass); } | |
206 | [else] { setverdict(fail, "no receive"); } | |
207 | } | |
208 | ||
209 | another_stringport.send(p1e); // send second half on the second connection | |
210 | alt { | |
211 | [] reverseport.receive( PDU2 : {"ABCDEFGH"} ) { setverdict(pass); } | |
212 | [else] { setverdict(fail, "no receive"); } | |
213 | } | |
214 | ||
215 | disconnect(mtc:stringport, mtc:reverseport); | |
216 | disconnect(mtc:another_stringport, mtc:reverseport); | |
217 | } | |
218 | ||
219 | control { | |
220 | execute(intern()); | |
221 | execute(errored()); | |
222 | execute(two_conn()); | |
223 | } | |
224 | ||
225 | } // end of module | |
226 | with { | |
227 | encode "RAW" | |
228 | } |