OopNegativeSemanticTest.ttcn 10.8 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
/******************************************************************************
 * Copyright (c) 2000-2021 Ericsson Telecom AB
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v2.0
 * which accompanies this distribution, and is available at
 * https://www.eclipse.org/org/documents/epl-2.0/EPL-2.0.html
 *
 * Contributors:
 *   Magyari, Miklos
 *
 ******************************************************************************/

module classesNegativeSemantic { 

type component CT {
	port PT pt_PT;
}

19
20
21
22
type component CT2 {
	port PT pt2_PT;
}

23
24
25
26
27
28
29
30
31
type port PT message { inout integer; } with { extension "internal" }

type union MyUnion {
	integer a,
	charstring b
};

type class CorrectClass1 { }

32
// invalid: a class can only extend other classes
33
34
35
36
type class BadInheritance extends MyUnion {

}

37
type class MinimalClass { }
38
type class @trait BaseClass { }
39
40
41
42
43
44
45
46
type class @abstract MinimalAbstractClass { }
type class @final MinimalFinalClass { }
type class @trait MinimalTraitClass { }

type class BadExtends extends MinimalClass, MinimalAbstractClass, MinimalFinalClass, MinimalTraitClass {
	// dummy
}

47
type class @trait BadExtends2 extends MinimalClass, MinimalTraitClass {
48
49
50
	// dummy
}

Miklos Magyari's avatar
Miklos Magyari committed
51
type class BadExtends3 extends MinimalFinalClass {
52
53
54
  
}

55
type class RepeatedExtends extends MinimalClass, BaseClass, MinimalClass {
56
  
57
58
}

59
60
61
62
63
64
65
// external classes cannot be extended by normal classes
type external class ExtClass {
	
}

type class ExtendExternal extends ExtClass { }

66
67
68
69
70
// runs on compatibility
type class RunsonClass1 runs on CT { }
type class RunsonClass2 extends RunsonClass1 runs on CT { }
type class RunsonClass3 extends RunsonClass1 runs on CT2 { }

71
72
73
74
75
76
77
78
79
80
// mtc compatibility
type class MtcClass1 mtc CT { }
type class MtcClass2 extends MtcClass1 mtc CT { }
type class MtcClass3 extends MtcClass1 mtc CT2 { }

// system compatibility
type class SystemClass1 system CT { }
type class SystemClass2 extends SystemClass1 system CT2 { }
type class SystemClass3 extends SystemClass1 system CT { }

81
82
// self extend
type class @trait TC {}
83
type class AA extends DD, TC, DD { }
84
85
86
87
88
type class BB extends AA { }
type class CC extends BB { } 
type class DD extends CC { }
type class EE extends EE { }

89
90
91
92
type class @trait BadTraitClass {
	public var integer m_int := 0;
	public timer Timer;
	
Miklos Magyari's avatar
Miklos Magyari committed
93
94
95
96
	create (charstring pl_str) {
		var float vl_float := 1.0;
	}
	
97
98
99
	private function @abstract f_valid(integer pl_int);
	public function f_invalid_non_abstract(in charstring pl_cstr);
	private function @abstract f_invalid(integer pl_int) {
100
101
102
103
104
		// this should not be here
	}
	
}

105
106
107
108
109
110
111
112
113
114
115
116
type class ClassWithAbstract1 {
	function @abstract f_abs();
}

type class @final ClassWithAbstract2 {
	function @abstract f_abs();
}

type class @trait ClassWithAbstract3 {
	function @abstract f_abs();
}

117
118
119
120
121
122
123
124
125
type class @abstract ClassWithAbstract4 {
	function @abstract f_abs1(in charstring pl_str);
	function f_non_abs(in charstring pl_str) { 
		//dummy implementation
	}
	public function @abstract f_abs2();
}

type class InheritedAbstract extends ClassWithAbstract4 { }
126

127
128
type class SuperClass {
	var integer vl_a;
129
	template MyUnion t_union := { a := 10 }
130
}
131
 
132
type class SubClass extends SuperClass {
133
	public var integer vl_b;
134
135
136
137
}

type class GrandSubClass extends SubClass {
	var integer vl_c;
138
	template MyUnion t_union2 := { nonexist := 10 }		// non-existing template member
139
140
141
142
143
144
145
146
147
148
149
150
}

type class GrandSubClass2 extends SubClass {
	var charstring vl_b;
}

type class BaseFunctionClass {
	public function f_get_one() return integer {
		return 1; 
	}
}

151
152
153
154
155
// constructor
type class ConstructorClass {
	create(integer pl_i1, in integer pl_i2, inout integer pl_i3, out integer pl_i4) {}
}

156
type class OuterClass {
157
	private var integer m_int := 0; 
158
159
160
161
162
163
164

	class NestedClass {
		const charstring c_text := "abc";

		class InnerClass {
			private template MyUnion t_union;
			public var integer badInteger := "xyz";
165
166
167
168
169
170
171
			
			public class EvenDeeper {
				public const charstring chr := "abc";
				
				public class Core {			  
    				public function f_inside(in integer pl_int) return charstring {
    					return this.chr;
172
					}
173
174
				}
			}
175
176
177
178
		}
	}
}

179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
// constant initialization
type class ConstantInitialization1 {
	const integer const_int; 
	
	function f_create(integer pl_create_int) {
		const_int := pl_create_int;
	}
}

type class ConstantInitialization2 {
	const integer const_int := 0; 
	
	create(integer pl_create_int) {
		const_int := pl_create_int;
	}
}

196
197
198
199
200
201
202
203
204
205
type class ReuseClass {
	var charstring vl_orig := "abc";
	
	function f_reuse_id(in integer pl_param) {
		var integer vl_orig := 1;
		vl_orig := 2;
		vl_orig := "abc";	// type mismatch: local definition takes precedence
	}
}

206
207
const integer cg_uninitConst1;

208
209
type class SubFunctionClass extends BaseFunctionClass {  
	private const integer m_const := 1;
210
	private const integer m_uninitConst2;
211
212
213
214
215
	public function f_get_one() return integer {		// FIXME : incomplete marker
		return m_const;
	}
}

216
217
218
219
// an abstract class can have a finally block
type class @abstract FinallyClass {
	public const integer m_const := 0;
} finally {
220
	log(this.m_const);
221
222
223
224
}

// a trait class cannot have a finally block
type class @trait FinallyClass2 {
225
	public function f_pub();
226
} finally {
227
	log(this.m_const);
228
229
}

230
231
232
233
234
235
// finally blocks canot have a return clause
type class FinallyClass3 {
	public function f_pub() { }
} finally {
	return;
}
236
 
237
238
239
240
241
// bad combination of class modifiers
type class @final @abstract BadClass1 { }
type class @final @trait BadClass3 { }
type class @abstract @trait BadClass2 { }

242
243
244
// class with this
type class ClassWithThis {
	public var integer vl_a;
245
	public var integer vl_b;
246
247
248
249
250
251
252
253
254

	public function pl_dummy(in integer pl_int) return integer {
		return 1;
	}

	public function f_dummy2(in charstring pl_dummy) {
		var charstring vl_int := this.pl_dummy(1);
	}
	
255
256
257
	create (integer pl_a, float pl_b) { 
		this.vl_a := pl_a;
		this.vl_b := pl_b;
258
259
260
	}
}

261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
function f_fake_super() return charstring {
	return "abc";
}

// bad super references
function f_notinclass(in integer pl_int) {
	var charstring vl_ch := super.f_fake_super();
}

type class FuncClass extends BaseFunctionClass {
	public function f_get_one() return charstring {
		return "xyz";
	}
	
	private function f_test_super() {
	  	// type mismatches 
277
278
279
		var integer vl_int := f_get_one();			// mismatch
		var charstring vl_ok := f_get_one();		// correct
		var charstring vl_cs := super.f_get_one();	// mismatch
280
	}
281
282
283
284
285
286
	
	public function f_dummy(in integer pl_int) return float {
		return 0.1;
	}
}

287
288
289
290
291
292
293
294
295
296
297
298
299
300
// private methods can be overridden in subclass
// protected and public classes can only be overriden with the same formal param list
type class ClassWithPrivate {
	private function f_override(in float pl_float) return integer {
		return 1;
	}

	function f_override2(in float pl_float) return integer {
		return 1;
	}

	public function f_override3(in float pl_float) return integer {
		return 1;
	}
301
302
	
	public function f_override4() {
303
	
304
	}
305
306
307
308
	
	function f_override5() {
	  
	}
309
}
310
311
312
313
314
315
316
317
318
319

type class ClassOverride1 {
	private var charstring vl_chr;
	var float vl_float;
}

type class ClassOverride2 extends ClassOverride1 {
	var charstring vl_chr;
	var float vl_float;
}
320
321
322
323
324
325
 
type class ClassWithPrivateExt extends ClassWithPrivate {
	public function f_override(charstring pl_chr) return charstring {
		return pl_chr;
	}

326
327
	public function f_override2(in float pl_float) return charstring {
		return pl_float;
328
329
	}

330
331
	public function f_override3(charstring pl_float) return charstring {
		return pl_float;
332
	}
333
334
	
	function f_override4() { }
335
336
	
	private function f_override5() { }
337
338
}

Miklos Magyari's avatar
Miklos Magyari committed
339
// function with class parameter 
340
341
342
function f_class_param(FuncClass pl_fun) {
	var integer vl_int := pl_fun.f_dummy(1);		// type mismatch
	var charstring vl_chr := pl_fun.f_get_one();	// correct
343
344
}

345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
// class function with `runs on`, `mtc` and `system` clause
type class BadClauses {
	public function f_with_runson() runs on CT {
	  
	}
	
	public function f_with_mtc() mtc CT return integer {
		return 1;
	}
	
	public function f_with_system() system CT {
	  
	}
	
	public function f_with_more() runs on CT mtc CT system CT {
	  
	}
}

364
// invalid: 'value' can only be used in properties (and in some cases of advanced matching)
365
366
367
368
function f_invalid_value() {
	var integer vl_x := value;
}

369
// class with properties
370
type class PropertyClass {
371
372
373
374
375
	private var integer size_;
	private var charstring sizename_;
	var integer @property size {
		@get => size_;
		@set {
376
			size_ := value;  
377
			sizename_ := value;			// type mismatch
378
379
		}
	} 
380
	
381
382
383
384
	var integer @property nosetter {
		@get => size;
	}
	
385
	// invalid: a property without a setter cannot be initialized
386
387
	var charstring @property nosetter_init := "abc" {
		@get {
388
			return "xyz";
389
390
		}
	}
391
392
393
394
395
	
	// invalid: an empty property body is not allowed
	var float @property emptybody {
	
	}
396
397
398
399
400
401
402
403
404
405
406
407
408
409
	
	// invalid: setter properties cannot have a return statement
	var charstring @property setter_with_return {
		@set {
			return "bad";
		}
	}
	
	// invalid: getter without a return statement
	var integer @property getter_without_return {
		@get {
			var integer vl_int := 0;
		}
	}
410
411
412
	
	// invalid: bad combination of modifiers
	var float @property prop_modifiers {
413
414
415
416
417
418
		@final @abstract @get;
	}
	
	var @abstract integer @property prop_modifiers2 {
		@get {
			return 1;
419
420
		}
	}
421
422
}

423
424
425
426
427
428
429
430
431
testcase tc_basicSyntax() runs on CT {
	var GrandSubClass vl_gsc := GrandSubClass.create;
	
	var integer vl_int1 := vl_gsc.vl_c;		// correct : own class member
	var integer vl_int2 := vl_gsc.vl_b;		// correct : inherited from direct parent
	var integer vl_int3 := vl_gsc.vl_a;		// correct : inherited from upper parent
	
	var charstring vl_int4 := vl_gsc.vl_d;		// incorrect : nonexisting member
	var charstring vl_int5 := vl_gsc.vl_a;		// incorrect : type mismatch
432
433
434
435
436
437
438
439
440
	
	var OuterClass vl_outer := OuterClass.create;
	var OuterClass vl_outer2;
	if (vl_outer of OuterClass) {			
		vl_outer := vl_outer2;
	}
	
	var integer vl_integer := vl_outer of OuterClass;			// type mismatch
	var boolean vl_boolean := vl_outer of BaseFunctionClass;	// semanticall correct
441
442
443
	
	// nested class member reference
	var octetstring vl_octet := vl_outer.NestedClass.InnerClass.EvenDeeper.Core.f_inside(1)
444
445
446
447
	
	// instantiating abstract and trait classes is not allowed
	var object vl_trait := MinimalTraitClass.create;
	var MinimalAbstractClass vl_abstract := MinimalAbstractClass.create;
448
449
450
	
	var SubFunctionClass vl_sub := SubFunctionClass.create;
	var integer vl_subint := vl_sub.m_const;
451
452
	
	var PropertyClass vl_prop := PropertyClass.create;
453
454
	
	// invalid: cannot assign a value to a property that has no setter
455
	vl_prop.nosetter := 10;
456
457
}

458
}