Commit | Line | Data |
---|---|---|
970ed795 | 1 | /****************************************************************************** |
3abe9331 | 2 | * Copyright (c) 2000-2015 Ericsson Telecom AB |
970ed795 EL |
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 FuncRef | |
9 | { | |
10 | ||
11 | type function un_oper(in integer a) return integer; | |
12 | type function bin_oper(in integer a, in integer b) return integer; | |
13 | ||
14 | function neg(in integer a) return integer { return -a; } | |
15 | ||
16 | function add(in integer a, in integer b) return integer { return a+b; } | |
17 | function sub(in integer a, in integer b) return integer { return a-b; } | |
18 | function mul(in integer a, in integer b) return integer { return a*b; } | |
19 | ||
20 | type union operator_type | |
21 | { | |
22 | un_oper unary, | |
23 | bin_oper binary | |
24 | } | |
25 | ||
26 | type record of operator_type operator_list; | |
27 | type record of integer operand_list; | |
28 | ||
29 | function calculate_expr(in operand_list operands, in operator_list operators) | |
30 | return integer | |
31 | { | |
32 | var integer operand_count := sizeof(operands); | |
33 | var integer operator_count := sizeof(operators); | |
34 | var integer i; | |
35 | var integer current_operand := 1; | |
36 | var integer result := operands[0]; | |
37 | for (i:=0; i<operator_count; i:=i+1) | |
38 | { | |
39 | if (ischosen(operators[i].unary)) | |
40 | { | |
41 | result := operators[i].unary.apply(result); | |
42 | } | |
43 | else | |
44 | { | |
45 | result := operators[i].binary.apply(result, operands[current_operand]); | |
46 | current_operand := current_operand + 1; | |
47 | } | |
48 | } | |
49 | return result; | |
50 | } | |
51 | ||
52 | type component FuncRef_comp { | |
53 | port tcport TCP1, TCP2; | |
54 | }; | |
55 | ||
56 | testcase calculationTest() runs on FuncRef_comp | |
57 | { | |
58 | var operand_list operands_1 := { 1, 2, 3 }; // -1 + 2 - 3 = -2 | |
59 | var operand_list operands_2 := { 2, 2, -6 }; // 2 * 2 + -6 = -2 | |
60 | var operator_list operators_1 := { { unary := refers(neg) }, | |
61 | { binary := refers(add) }, | |
62 | { binary := refers(sub) } }; | |
63 | var operator_list operators_2 := { { binary := refers(mul) }, | |
64 | { binary := refers(add) } }; | |
65 | var integer result_1 := calculate_expr(operands_1, operators_1); | |
66 | var integer result_2 := calculate_expr(operands_2, operators_2); | |
970ed795 EL |
67 | if (result_1 == result_2) { setverdict(pass); } |
68 | else { setverdict(fail); } | |
69 | } | |
70 | ||
71 | template bin_oper bin_oper_tmpl := (refers(add), refers(sub)); | |
72 | template bin_oper bin_oper_tmpl2 := *; | |
73 | template bin_oper bin_oper_tmpl3 := omit; | |
74 | ||
75 | testcase funcTemplateTest() runs on FuncRef_comp | |
76 | { | |
970ed795 EL |
77 | var bin_oper a := refers(add); |
78 | var bin_oper s := refers(sub); | |
79 | var bin_oper m := refers(mul); | |
80 | if ( match(a, bin_oper_tmpl) != match(s, bin_oper_tmpl) ) | |
81 | { setverdict(fail); } | |
82 | if ( match(a, bin_oper_tmpl) == match(m, bin_oper_tmpl) ) | |
83 | { setverdict(fail); } | |
84 | if ( match(s, bin_oper_tmpl) == match(m, bin_oper_tmpl) ) | |
85 | { setverdict(fail); } | |
86 | if ( match(a, bin_oper_tmpl) != match(a, bin_oper_tmpl) ) | |
87 | { setverdict(fail); } | |
88 | if ( match(s, bin_oper_tmpl) != match(s, bin_oper_tmpl) ) | |
89 | { setverdict(fail); } | |
90 | if ( match(m, bin_oper_tmpl) != match(m, bin_oper_tmpl) ) | |
91 | { setverdict(fail); } | |
92 | if (not match(m, bin_oper_tmpl2)) | |
93 | { setverdict(fail); } | |
94 | if (match(m, bin_oper_tmpl3)) | |
95 | { setverdict(fail); } | |
96 | setverdict(pass); | |
97 | } | |
98 | ||
99 | type function fn_type(); | |
100 | function fn1() { } | |
101 | function fn2() { } | |
102 | function fn_fn(in fn_type f) return fn_type { return f; } | |
103 | template fn_type fntmpl := refers(fn1); | |
104 | ||
105 | type function fn_temp_ret_type() return template integer; | |
106 | function fn_temp_ret_fn() return template integer { return 1; } | |
107 | ||
108 | testcase funcRefOperTest() runs on FuncRef_comp | |
109 | { | |
110 | var fn_type f1 := refers(fn1); | |
111 | var fn_type f2 := refers(fn2); | |
112 | const fn_type f1c := refers(fn1); | |
113 | var fn_temp_ret_type fn_temp_ret_var := refers(fn_temp_ret_fn); | |
114 | if (not(f1==f1)) { setverdict(fail); } | |
115 | if (f1==f2) { setverdict(fail); } | |
116 | if (not(f1!=f2)) { setverdict(fail); } | |
117 | if (f1!=f1) { setverdict(fail); } | |
118 | if (not(f1c==f1)) { setverdict(fail); } | |
119 | if (f1c!=f1) { setverdict(fail); } | |
120 | if (valueof(fntmpl)!=f1) { setverdict(fail); } | |
121 | if (fn_fn(f1)!=f1) { setverdict(fail); } | |
122 | if (fn_fn(valueof(f2))!=f2) { setverdict(fail); } | |
123 | if (fn_fn(valueof(f2))==f1) { setverdict(fail); } | |
124 | if(not(1 == valueof(fn_temp_ret_var.apply()))) { setverdict(fail); } | |
125 | if(not(match(valueof(fn_temp_ret_var.apply()),fn_temp_ret_var.apply()))) { setverdict(fail); } | |
126 | setverdict(pass); | |
127 | } | |
128 | ||
129 | type record my_message | |
130 | { | |
131 | fn_type f | |
132 | } | |
133 | ||
134 | type port TP message { | |
135 | inout my_message; | |
136 | } with { extension "internal" } | |
137 | ||
138 | type component main { | |
139 | port TP tp; | |
140 | port TP tp2; | |
141 | } | |
142 | ||
143 | template my_message msg_tmpl := ?; | |
144 | ||
145 | testcase transferTest() runs on main { | |
146 | connect(mtc:tp, mtc:tp2); | |
147 | const my_message sm1 := { refers(fn1) } | |
148 | const my_message sm2 := { refers(fn2) } | |
149 | var my_message rm1; | |
150 | var my_message rm2; | |
151 | tp.send(sm1); | |
152 | tp.send(sm2); | |
153 | tp2.receive(msg_tmpl) -> value rm1; | |
154 | tp2.receive(msg_tmpl) -> value rm2; | |
155 | if (rm1==rm2) { setverdict(fail); } | |
156 | setverdict(pass); | |
157 | } | |
158 | ||
159 | type function fact_func_type(in integer num, inout integer steps, | |
160 | in fact_func_type ff) return integer; | |
161 | ||
162 | function factorial1(in integer num, inout integer steps) return integer | |
163 | { | |
970ed795 EL |
164 | steps := steps + 1; |
165 | if (num<2) { return 1; } | |
166 | else { return num*factorial1(num-1,steps); } | |
167 | } | |
168 | ||
169 | ||
170 | function factorial2(in integer num, inout integer steps, in fact_func_type ff) | |
171 | return integer | |
172 | { | |
970ed795 EL |
173 | steps := steps + 1; |
174 | if (num<2) { return 1; } | |
175 | else { return num*ff.apply(num-1,steps,refers(factorial3)); } | |
176 | } | |
177 | ||
178 | function factorial3(in integer num, inout integer steps, in fact_func_type ff) | |
179 | return integer | |
180 | { | |
970ed795 EL |
181 | steps := steps + 1; |
182 | if (num<2) { return 1; } | |
183 | else { return num*ff.apply(num-1,steps,refers(factorial2)); } | |
184 | } | |
185 | ||
186 | testcase recursiveCallTest() runs on FuncRef_comp | |
187 | { | |
188 | var integer steps1 := 0; | |
189 | var integer steps2 := 0; | |
190 | if (factorial1(5,steps1) != factorial2(5,steps2,refers(factorial3))) | |
191 | { setverdict(fail); } | |
192 | if (steps1!=steps2) { setverdict(fail); } | |
193 | setverdict(pass); | |
194 | } | |
195 | ||
196 | ||
197 | type function nested_rec_func(inout rec_list rl, in nested_rec_func nrf, | |
198 | in integer depth); | |
199 | type record rec_list | |
200 | { | |
201 | nested_rec_func nrf, | |
202 | rec_list rl optional, | |
203 | integer depth | |
204 | } | |
205 | function nrf_create_list_item(inout rec_list rl, in nested_rec_func nrf, | |
206 | in integer depth) | |
207 | { | |
208 | if (depth>0) | |
209 | { | |
210 | var rec_list rl2 := { rl.nrf, omit, depth-1 } | |
211 | rl.nrf.apply(rl2, rl2.nrf, rl2.depth); | |
212 | rl.rl := rl2; | |
213 | } | |
214 | } | |
215 | ||
216 | testcase listRecursionTest() runs on FuncRef_comp | |
217 | { | |
218 | var rec_list rl := { refers(nrf_create_list_item), omit, 5 } | |
219 | rl.nrf.apply(rl, rl.nrf, rl.depth); | |
220 | var integer expected_sum := 0+1+2+3+4+5; | |
221 | var integer sum := rl.depth; | |
222 | while (ispresent(rl.rl)) | |
223 | { | |
224 | var rec_list rl2 := rl.rl; | |
225 | rl := rl2; | |
226 | sum := sum + rl.depth; | |
227 | } | |
228 | if (sum!=expected_sum) { setverdict(fail); } | |
229 | setverdict(pass); | |
230 | } | |
231 | ||
232 | ||
233 | type function fv_type_1() return integer; | |
234 | function fv_1_1() return integer { return 11; } | |
235 | function fv_1_2() return integer { return 12; } | |
236 | type function fv_type_2() return integer; | |
237 | function fv_2_1() return integer { return 21; } | |
238 | function fv_2_2() return integer { return 22; } | |
239 | // test refers and apply operations | |
240 | testcase funcRefOperationsTest() runs on FuncRef_comp | |
241 | { | |
242 | var fv_type_1 f11 := refers(fv_1_1); | |
243 | var fv_type_1 f12 := refers(fv_1_2); | |
244 | var fv_type_2 f21 := refers(fv_2_1); | |
245 | var fv_type_2 f22 := refers(fv_2_2); | |
246 | var template fv_type_1 tf11 := f11; | |
247 | var template fv_type_2 tf21 := f21; | |
248 | if (f11.apply()!=f11.apply()) { setverdict(fail); } | |
249 | if (f11.apply()==f12.apply()) { setverdict(fail); } | |
250 | var fv_type_1 f10 := valueof(tf11); | |
251 | var fv_type_2 f20 := valueof(tf21); | |
252 | if (f10.apply()!=f11.apply()) { setverdict(fail); } | |
253 | if (f10.apply()==f12.apply()) { setverdict(fail); } | |
254 | if (f10.apply()==f20.apply()) { setverdict(fail); } | |
255 | if (not match(refers(fv_1_1), tf11)) { setverdict(fail); } | |
256 | if (match(refers(fv_1_2), tf11)) { setverdict(fail); } | |
257 | if (match(refers(fv_1_1), tf21)) { setverdict(fail); } | |
258 | setverdict(pass); | |
259 | } | |
260 | ||
261 | ||
262 | type function fn_par() return fn_par; | |
263 | function fnp0() return fn_par { return refers(fnp0) } | |
264 | function fnp1() return fn_par { return refers(fnp1) } | |
265 | function fnp2() return fn_par { return refers(fnp2) } | |
266 | function fnp3() return fn_par { return refers(fnp3) } | |
267 | function fnp4() return fn_par { return refers(fnp4) } | |
268 | function fnpnull() return fn_par { return null; } | |
269 | function fn_params(fn_par p1, in fn_par p2, out fn_par p3, inout fn_par p4) | |
270 | { | |
271 | if ( p1.apply()!=refers(fnp0) or p2.apply()!=refers(fnp0) or | |
272 | p4.apply()!=refers(fnp0) ) { setverdict(fail); } | |
273 | p1 := refers(fnp1); | |
274 | p2 := refers(fnp2); | |
275 | p3 := refers(fnp3); | |
276 | p4 := refers(fnp4); | |
277 | if (p1.apply()==null) { setverdict(fail); } | |
278 | if (p1.apply()!=refers(fnp1)) { setverdict(fail); } | |
279 | if (p2.apply()!=refers(fnp2)) { setverdict(fail); } | |
280 | if (p3.apply()!=refers(fnp4)) { setverdict(fail); } | |
281 | if (p4.apply()!=refers(fnp4)) { setverdict(fail); } | |
282 | } | |
283 | testcase funcRefParamsTest() runs on FuncRef_comp | |
284 | { | |
285 | var fn_par fnp := refers(fnp0); | |
286 | if (fnp0()!=refers(fnp0)) { setverdict(fail); } | |
287 | if (fnp.apply()!=fnp0()) { setverdict(fail); } | |
288 | if (fnp.apply()==null) { setverdict(fail); } | |
289 | //fn_params(fnp,fnp,fnp,fnp); | |
290 | //if (fnp.apply()!=refers(fnp4)) { setverdict(fail); } | |
291 | ||
292 | if (fnpnull()!=null) { setverdict(fail); } | |
293 | fnp := refers(fnpnull); | |
294 | if (fnp.apply()!=null) { setverdict(fail); } | |
295 | if (fnp.apply()!=fnpnull()) { setverdict(fail); } | |
296 | ||
297 | fnp := refers(fnp0); | |
298 | if (fnp.apply().apply().apply() != fnp.apply()) { setverdict(fail); } | |
299 | if (fnp0().apply() != refers(fnp0)) { setverdict(fail); } | |
300 | ||
301 | setverdict(pass); | |
302 | } | |
303 | ||
304 | ||
305 | function fff() { } | |
306 | type union UNION | |
307 | { | |
308 | function () f1, | |
309 | function () f2, | |
310 | function () f3 | |
311 | } | |
312 | type set SET | |
313 | { | |
314 | function () f1 optional, | |
315 | function () f2 optional, | |
316 | function () f3 optional | |
317 | } | |
318 | type record REKORD | |
319 | { | |
320 | function () f1 optional, | |
321 | function () f2 optional, | |
322 | function () f3 optional | |
323 | } | |
324 | // test predefined functions: sizeof(), ispresent(), ischosen() | |
325 | testcase predefFuncOnNestedCompoundTypesTest() runs on FuncRef_comp | |
326 | { | |
327 | var REKORD v_r := { refers(fff), omit, refers(fff) } | |
328 | var SET v_s := { f1 := refers(fff), f2 := omit, f3 := refers(fff) } | |
329 | var UNION v_u := { f2 := refers(fff) } | |
330 | var template REKORD t_r := v_r; | |
331 | var template SET t_s := v_s; | |
332 | var template UNION t_u := v_u; | |
333 | if ( sizeof(v_r)!=2 or not ispresent(v_r.f1) or ispresent(v_r.f2) or | |
334 | not ispresent(v_r.f3) ) | |
335 | { setverdict(fail); } | |
336 | if ( sizeof(t_r)!=2 or not ispresent(t_r.f1) or ispresent(t_r.f2) or | |
337 | not ispresent(t_r.f3) ) | |
338 | { setverdict(fail); } | |
339 | if ( sizeof(v_s)!=2 or not ispresent(v_s.f1) or ispresent(v_s.f2) or | |
340 | not ispresent(v_s.f3) ) | |
341 | { setverdict(fail); } | |
342 | if ( sizeof(t_s)!=2 or not ispresent(t_s.f1) or ispresent(t_s.f2) or | |
343 | not ispresent(t_s.f3) ) | |
344 | { setverdict(fail); } | |
345 | if ( ischosen(v_u.f1) or not ischosen(v_u.f2) or ischosen(v_u.f3) ) | |
346 | { setverdict(fail); } | |
347 | if ( ischosen(t_u.f1) or not ischosen(t_u.f2) or ischosen(t_u.f3) ) | |
348 | { setverdict(fail); } | |
349 | setverdict(pass); | |
350 | } | |
351 | ||
352 | ||
353 | type testcase tc_type() runs on FuncRef_comp; | |
354 | type record of tc_type tc_recof; | |
355 | ||
356 | type function MyFunction_RunsOnParent() runs on Parent_CT; | |
357 | type function MyFunction_RunsOnChild() runs on Child_CT; | |
358 | type function MyFunction_RunsOnSelf() runs on self; | |
359 | ||
360 | type component Parent_CT | |
361 | { | |
362 | var MyFunction_RunsOnParent fs_parent := null; | |
363 | var MyFunction_RunsOnSelf fs_self := null; | |
364 | var charstring parent := "parent"; | |
365 | } | |
366 | ||
367 | type component Child_CT extends Parent_CT | |
368 | { | |
369 | var MyFunction_RunsOnChild fs_child := null; | |
370 | var charstring child := "child"; | |
371 | } | |
372 | ||
373 | function f_parent(in MyFunction_RunsOnSelf p_self) runs on Parent_CT | |
374 | { | |
375 | p_self.apply(); | |
376 | } | |
377 | ||
378 | function f_child() runs on Child_CT | |
379 | { | |
380 | child := "Running child function is done"; | |
381 | } | |
382 | ||
383 | testcase tc_runsonself() runs on Child_CT | |
384 | { | |
385 | fs_self := refers(f_child); | |
386 | ||
387 | f_parent(fs_self); | |
388 | ||
389 | if(child != "Running child function is done") | |
390 | { | |
391 | setverdict(fail); | |
392 | } | |
393 | else { setverdict(pass); } | |
394 | } | |
395 | ||
396 | type port tcport message { | |
397 | inout tc_recof | |
398 | } | |
399 | with { extension "internal" } | |
400 | ||
401 | testcase tc_send_tc() runs on FuncRef_comp | |
402 | { | |
403 | var tc_recof sent_testcases := { | |
404 | refers(tc_send_tc) | |
405 | }, received_testcases; | |
406 | connect(mtc:TCP1, mtc:TCP2); | |
407 | TCP1.send(sent_testcases); | |
408 | TCP2.receive(tc_recof : ?) -> value received_testcases; | |
409 | if (received_testcases == sent_testcases) { setverdict(pass); } | |
410 | else { setverdict(fail, match(received_testcases, sent_testcases)); } | |
411 | disconnect(mtc:TCP1, mtc:TCP2); | |
412 | } | |
413 | ||
414 | // For TR HL26179. | |
415 | type function f_myfunctype1(in charstring p1) runs on self | |
416 | function f_myfunc1(in charstring p1) runs on empty_ct {} | |
417 | type component empty_ct {var f_myfunctype1 v_myfuncvar1 := refers(f_myfunc1)} | |
418 | ||
419 | testcase tc_functionrefIsbound() runs on FuncRef_comp | |
420 | { | |
421 | var fv_type_1 f0; | |
422 | var fv_type_1 f1 := refers(fv_1_1); | |
423 | if ( isvalue(f0) ) { setverdict(fail); } else { setverdict(pass); }; | |
424 | if ( isvalue(f1) ) { setverdict(pass); } else { setverdict(fail); }; | |
425 | } | |
426 | ||
427 | // for TR H029700 | |
428 | type function f_FT(); | |
429 | ||
430 | function f_refers() { | |
431 | var f_FT vf := valueof(f_FT:refers(f_refers)); | |
432 | } | |
433 | ||
434 | ||
435 | control | |
436 | { | |
437 | var integer i; | |
438 | var tc_recof testcases := { | |
439 | refers(calculationTest), | |
440 | refers(funcTemplateTest), | |
441 | refers(funcRefOperTest), | |
442 | refers(recursiveCallTest), | |
443 | refers(listRecursionTest), | |
444 | refers(funcRefOperationsTest), | |
445 | refers(funcRefParamsTest), | |
446 | refers(predefFuncOnNestedCompoundTypesTest) | |
447 | } | |
448 | for(i := 0; i < sizeof(testcases); i := i+1) | |
449 | { | |
450 | execute(derefers(testcases[i])()); | |
451 | } | |
452 | execute(transferTest()); | |
453 | execute(tc_runsonself()); | |
454 | execute(tc_functionrefIsbound()); | |
455 | execute(tc_send_tc()); | |
456 | } | |
457 | } | |
458 |