Operation Semantics
Operation Semantics
1 (2012-04)
ETSI Standard
Methods for Testing and Specification (MTS); The Testing and Test Control Notation version 3; Part 4: TTCN-3 Operational Semantics
Reference
RES/MTS-136-4 T3 ed441 OS
Keywords
interoperability, language, methodology, MTS, testing, TTCN
ETSI
650 Route des Lucioles F-06921 Sophia Antipolis Cedex - FRANCE Tel.: +33 4 92 94 42 00 Fax: +33 4 93 65 47 16
Siret N 348 623 562 00017 - NAF 742 C Association but non lucratif enregistre la Sous-Prfecture de Grasse (06) N 7803/88
Important notice
Individual copies of the present document can be downloaded from: http://www.etsi.org The present document may be made available in more than one electronic version or in print. In any case of existing or perceived difference in contents between such versions, the reference version is the Portable Document Format (PDF). In case of dispute, the reference shall be the printing on ETSI printers of the PDF version kept on a specific network drive within ETSI Secretariat. Users of the present document should be aware that the document may be subject to revision or change of status. Information on the current status of this and other ETSI documents is available at http://portal.etsi.org/tb/status/status.asp If you find errors in the present document, please send your comment to one of the following services: http://portal.etsi.org/chaircor/ETSI_support.asp
Copyright Notification
No part may be reproduced except as authorized by written permission. The copyright and the foregoing restriction extend to reproduction in all media. European Telecommunications Standards Institute 2012. All rights reserved. DECT , PLUGTESTS , UMTS and the ETSI logo are Trade Marks of ETSI registered for the benefit of its Members. TM 3GPP and LTE are Trade Marks of ETSI registered for the benefit of its Members and of the 3GPP Organizational Partners. GSM and the GSM logo are Trade Marks registered and owned by the GSM Association.
TM TM TM
ETSI
Contents
Intellectual Property Rights ................................................................................................................................7 Foreword.............................................................................................................................................................7 1 2
2.1 2.2
3
3.1 3.2
4 5 6 7
7.1 7.2 7.3 7.4 7.5 7.6 7.7 7.8 7.9 7.10 7.11
Introduction ..............................................................................................................................................8 Structure of the present document ............................................................................................................9 Restrictions ...............................................................................................................................................9 Replacement of short forms ...................................................................................................................10
Order of replacement steps ............................................................................................................................... 10 Replacement of global constants and module parameters ................................................................................ 11 Embedding single receiving operations into alt statements .............................................................................. 11 Embedding stand-alone altstep calls into alt statements ................................................................................... 12 Replacement of interleave statements .............................................................................................................. 12 Replacement of trigger operations .................................................................................................................... 25 Replacement of select-case statements ............................................................................................................. 25 Replacement of simple break statements.......................................................................................................... 27 Replacement of continue statements ................................................................................................................ 27 Adding default parameters to disconnect and unmap operations without parameters ...................................... 28 Adding default values of parameters ................................................................................................................ 28
8.1 Flow graphs ...................................................................................................................................................... 29 8.1.1 Flow graph frame ........................................................................................................................................ 29 8.1.2 Flow graph nodes ........................................................................................................................................ 29 8.1.2.1 Start nodes ............................................................................................................................................. 29 8.1.2.2 End nodes .............................................................................................................................................. 29 8.1.2.3 Basic nodes ........................................................................................................................................... 29 8.1.2.4 Reference nodes .................................................................................................................................... 30 8.1.2.4.1 OR combination of reference nodes ................................................................................................ 30 8.1.2.4.2 Multiple occurrences of reference nodes ......................................................................................... 30 8.1.3 Flow lines ................................................................................................................................................... 31 8.1.4 Flow graph segments .................................................................................................................................. 31 8.1.5 Comments ................................................................................................................................................... 32 8.1.6 Handling of flow graph descriptions ........................................................................................................... 33 8.2 Flow graph representation of TTCN-3 behaviour ............................................................................................ 33 8.2.1 Flow graph construction procedure ............................................................................................................ 33 8.2.2 Flow graph representation of module control ............................................................................................. 34 8.2.3 Flow graph representation of test cases ...................................................................................................... 35 8.2.4 Flow graph representation of functions ...................................................................................................... 35 8.2.5 Flow graph representation of altsteps ......................................................................................................... 36 8.2.6 Flow graph representation of component type definitions .......................................................................... 37 8.2.7 Retrieval of start nodes of flow graphs ....................................................................................................... 38 8.3 State definitions for TTCN-3 modules ............................................................................................................. 38 8.3.1 Module state................................................................................................................................................ 38 8.3.1.1 Accessing the module state ................................................................................................................... 39 8.3.1a Configuration state ...................................................................................................................................... 39 8.3.1a.1 Accessing the configuration state .......................................................................................................... 39
ETSI
8.3.2 8.3.2.1 8.3.2.2 8.3.2.3 8.3.2.4 8.3.2.5 8.3.2.6 8.3.2.7 8.3.3 8.3.3.1 8.3.3.2 8.3.4 8.4 8.4.1 8.4.2 8.4.3 8.4.4 8.4.5 8.4.6 8.5 8.5.1 8.6 8.6.1 8.6.1.1 8.6.1.2 8.6.1.3 8.6.1.4 8.6.2
Entity states ................................................................................................................................................. 40 Accessing entity states .......................................................................................................................... 41 Data state and variable binding ............................................................................................................. 43 Accessing data states ............................................................................................................................. 43 Timer state and timer binding ............................................................................................................... 44 Accessing timer states ........................................................................................................................... 45 Port references and port binding ........................................................................................................... 46 Accessing port references ..................................................................................................................... 47 Port states .................................................................................................................................................... 47 Handling of connections among ports ................................................................................................... 48 Handling of port states .......................................................................................................................... 48 General functions for the handling of module states .................................................................................. 49 Messages, procedure calls, replies and exceptions ........................................................................................... 50 Messages ..................................................................................................................................................... 50 Procedure calls and replies ......................................................................................................................... 50 Exceptions................................................................................................................................................... 51 Construction of messages, procedure calls, replies and exceptions ............................................................ 51 Matching of messages, procedure calls, replies and exceptions ................................................................. 51 Retrieval of information from received items ............................................................................................. 52 Call records for functions, altsteps and test cases............................................................................................. 52 Handling of call records .............................................................................................................................. 52 The evaluation procedure for a TTCN-3 module ............................................................................................. 53 Evaluation phases ....................................................................................................................................... 53 Phase I: Initialization............................................................................................................................. 53 Phase II: Update .................................................................................................................................... 54 Phase III: Selection ............................................................................................................................... 54 Phase IV: Execution .............................................................................................................................. 54 Global functions.......................................................................................................................................... 54
9
9.1 9.2 9.2a 9.2a.1 9.2a.2 9.3 9.3.1 9.3.2 9.3.3 9.3.4 9.3.5 9.4 9.5 9.5a 9.6 9.6.1 9.6.1a 9.6.2 9.6.3 9.6.4 9.6.5 9.6.6 9.7 9.8 9.8.1 9.8.2 9.8a 9.8a.1 9.8a.2 9.9 9.10 9.11
ETSI
9.12 9.13 9.13.1 9.13.2 9.14 9.14.1 9.14.2 9.14.3 9.14.4 9.14.5 9.15 9.16 9.17 9.17.1 9.17.2 9.17.3 9.18 9.18.1 9.18.2 9.18.3 9.18.4 9.19 9.20 9.20a 9.20b 9.21 9.22 9.23 9.24 9.24.1 9.24.2 9.24.3 9.24.3a 9.24.4 9.24.5 9.25 9.26 9.27 9.28 9.28a 9.29 9.29a 9.29a.1 9.29a.2 9.29a.3 9.29b 9.29b.1 9.29c 9.30 9.31 9.32 9.33 9.34 9.35 9.35.1 9.35.1a 9.35.2 9.36 9.37 9.37.1 9.37.2 9.37.3
Create operation ............................................................................................................................................... 83 Deactivate statement......................................................................................................................................... 84 Flow graph segment <deactivate-one-default> ........................................................................................... 85 Flow graph segment <deactivate-all-defaults> ........................................................................................... 85 Disconnect operation ........................................................................................................................................ 86 Flow graph segment <disconnect-one-par-pair> ........................................................................................ 86 Flow graph segment <disconnect-all> ........................................................................................................ 88 Flow graph segment <disconnect-comp> ................................................................................................... 89 Flow graph segment <disconnect-port>...................................................................................................... 90 Flow graph segment <disconnect-two-par-pairs>....................................................................................... 90 Do-while statement........................................................................................................................................... 91 Done component operation............................................................................................................................... 92 Execute statement ............................................................................................................................................. 94 Flow graph segment <execute-without-timeout> ....................................................................................... 95 Flow graph segment <execute-timeout> ..................................................................................................... 96 Flow graph segment <dynamic-error>........................................................................................................ 97 Expression ........................................................................................................................................................ 97 Flow graph segment <lit-value> ................................................................................................................. 98 Flow graph segment <var-value> ............................................................................................................... 98 Flow graph segment <func-op-call> ........................................................................................................... 99 Flow graph segment <operator-appl> ......................................................................................................... 99 Flow graph segment <finalize-component-init> ............................................................................................ 100 Flow graph segment <init-component-scope> ............................................................................................... 100 Flow graph segment <init-scope-with-runs-on> ............................................................................................ 101 Flow graph segment <init-scope-without-runs-on> ....................................................................................... 101 Flow graph segment <parameter-handling> ................................................................................................... 102 Flow graph segment <statement-block> ........................................................................................................ 102 For statement .................................................................................................................................................. 103 Function call ................................................................................................................................................... 104 Flow graph segment <value-par-calculation>........................................................................................... 106 Flow graph segment <ref-par-var-calc> ................................................................................................... 106 Flow graph segment <ref-par-timer-calc> ................................................................................................ 107 Flow graph segment <ref-par-port-calc> .................................................................................................. 107 Flow graph segment <user-def-func-call> ................................................................................................ 108 Flow graph segment <predef-ext-func-call>............................................................................................. 109 Getcall operation ............................................................................................................................................ 109 Getreply operation .......................................................................................................................................... 109 Getverdict operation ....................................................................................................................................... 110 Goto statement................................................................................................................................................ 110 Halt port operation.......................................................................................................................................... 111 If-else statement ............................................................................................................................................. 111 Kill component operation ............................................................................................................................... 112 Flow graph segment <kill-mtc> ................................................................................................................ 114 Flow graph segment <kill-component> .................................................................................................... 115 Flow graph segment <kill-all-comp>........................................................................................................ 116 Kill execution statement ................................................................................................................................. 116 Flow graph segment <kill-control> .......................................................................................................... 117 Killed component operation ........................................................................................................................... 118 Label statement .............................................................................................................................................. 119 Log statement ................................................................................................................................................. 119 Map operation ................................................................................................................................................ 120 Mtc operation ................................................................................................................................................. 120 Port declaration .............................................................................................................................................. 121 Raise operation ............................................................................................................................................... 121 Flow graph segment <raise-with-one-receiver-op> .................................................................................. 122 Flow graph segment <raise-with-multiple-receivers-op> ......................................................................... 122 Flow graph segment <raise-without-receiver-op> .................................................................................... 124 Read timer operation ...................................................................................................................................... 125 Receive operation ........................................................................................................................................... 126 Flow graph segment <receive-with-sender> ............................................................................................. 127 Flow graph segment <receive-without-sender> ........................................................................................ 128 Flow graph segment <receive-assignment> .............................................................................................. 129
ETSI
9.38 9.39 9.39.1 9.39.1a 9.39.2 9.40 9.40.1 9.40.2 9.41 9.41.1 9.41.2 9.42 9.43 9.44 9.44.1 9.44.1a 9.44.2 9.45 9.46 9.47 9.48 9.48.1 9.48.2 9.49 9.49.1 9.49.2 9.49.3 9.50 9.51 9.52 9.53 9.53a 9.54 9.54.1 9.54.2 9.55 9.56 9.56.1 9.56.2 9.56.3 9.57 9.57.1 9.57.2 9.58
Repeat statement ............................................................................................................................................ 129 Reply operation .............................................................................................................................................. 130 Flow graph segment <reply-with-one-receiver-op> ................................................................................. 131 Flow graph segment <reply-with-multiple-receivers-op> ........................................................................ 131 Flow graph segment <reply-without-receiver-op> ................................................................................... 133 Return statement ............................................................................................................................................. 133 Flow graph segment <return-with-value>................................................................................................. 135 Flow graph segment <return-without-value> ........................................................................................... 136 Running component operation ....................................................................................................................... 137 Flow graph segment <running-comp-act> ................................................................................................ 138 Flow graph segment <running-comp-snap> ............................................................................................. 139 Running timer operation ................................................................................................................................. 140 Self operation ................................................................................................................................................. 141 Send operation ................................................................................................................................................ 141 Flow graph segment <send-with-one-receiver-op> .................................................................................. 142 Flow graph segment <send-with-multiple-receivers-op> ......................................................................... 142 Flow graph segment <send-without-receiver-op> .................................................................................... 144 Setverdict operation ........................................................................................................................................ 144 Start component operation.............................................................................................................................. 145 Start port operation ......................................................................................................................................... 147 Start timer operation ....................................................................................................................................... 147 Flow graph segment <start-timer-op-default> .......................................................................................... 148 Flow graph segment <start-timer-op-duration> ........................................................................................ 149 Stop component operation .............................................................................................................................. 149 Void .......................................................................................................................................................... 151 Flow graph segment <stop-alive-component> .......................................................................................... 151 Flow graph segment <stop-all-comp> ...................................................................................................... 152 Stop execution statement ................................................................................................................................ 153 Stop port operation ......................................................................................................................................... 154 Stop timer operation ....................................................................................................................................... 155 System operation ............................................................................................................................................ 155 Test case stop operation ................................................................................................................................. 156 Timer declaration ........................................................................................................................................... 156 Flow graph segment <timer-decl-default> ................................................................................................ 157 Flow graph segment <timer-decl-no-def> ................................................................................................ 157 Timeout timer operation ................................................................................................................................. 158 Unmap operation ............................................................................................................................................ 159 Flow graph segment <unmap-all> ............................................................................................................ 161 Flow graph segment <unmap-comp> ....................................................................................................... 162 Flow graph segment <unmap-port> .......................................................................................................... 163 Variable declaration ....................................................................................................................................... 163 Flow graph segment <var-declaration-init> .............................................................................................. 164 Flow graph segment <var-declaration-undef> .......................................................................................... 165 While statement .............................................................................................................................................. 165 Functions and states........................................................................................................................................ 166 Special keywords ............................................................................................................................................ 167 Flow graphs of TTCN-3 behaviour descriptions ............................................................................................ 168 Flow graph segments ...................................................................................................................................... 168
10
10.1 10.2 10.3 10.4
History ............................................................................................................................................................171
ETSI
Foreword
This ETSI Standard (ES) has been produced by ETSI Technical Committee Methods for Testing and Specification (MTS). The present document is part 4 of a multi-part deliverable. Full details of the entire series can be found in part 1 [1].
ETSI
Scope
The present document defines the operational semantics of TTCN-3. The present document is based on the TTCN-3 core language defined in ES 201 873-1 [1].
References
References are either specific (identified by date of publication and/or edition number or version number) or non-specific. For specific references, only the cited version applies. For non-specific references, the latest version of the reference document (including any amendments) applies. Referenced documents which are not found to be publicly available in the expected location might be found at http://docbox.etsi.org/Reference. NOTE: While any hyperlinks included in this clause were valid at the time of publication ETSI cannot guarantee their long term validity.
2.1
[1]
Normative references
ETSI ES 201 873-1: "Methods for Testing and Specification (MTS); The Testing and Test Control Notation version 3; Part 1: TTCN-3 Core Language".
The following referenced documents are necessary for the application of the present document.
2.2
Informative references
The following referenced documents are not necessary for the application of the present document but they assist the user with regard to a particular subject area. Not applicable.
3
3.1
For the purposes of the present document, the terms and definitions given in ES 201 873-1 [1] apply.
3.2
BNF MTC SUT TTCN
Abbreviations
Backus-Nauer Form Master Test Component System Under Test Testing and Test Control Notation
For the purposes of the present document, the following abbreviations apply:
Introduction
This clause defines the meaning of TTCN-3 behaviour in an intuitive and unambiguous manner. The operational semantics is not meant to be formal and therefore the ability to perform mathematical proofs based on this semantics is very limited.
ETSI
This operational semantics provides a state oriented view on the execution of a TTCN module. Different kinds of states are introduced and the meaning of the different TTCN-3 constructs is described by: 1) 2) using state information to define the preconditions for the execution of a construct; and defining how the execution of a construct will change a state.
The operational semantics is restricted to the meaning of behaviour in TTCN-3, i.e. functions, altsteps, test cases, module control and language constructs for defining test behaviour, e.g. send and receive operations, if-else-, or while- statements. The meaning of some TTCN-3 constructs is explained by replacing them with other language constructs. For example, interleave statements are short forms for series of nested alt statements and the meaning of each interleave statement is explained by its replacement with a corresponding series of nested alt statements. In most cases, the definition of the semantics of a language is based on an abstract syntax tree of the code that shall be described. This semantics does not work on an abstract syntax tree but requires a graphical representation of TTCN-3 behaviour descriptions in form of flow graphs. A flow graph describes the flow of control in a function, alt step, test case or the module control. The mapping of TTCN-3 behaviour descriptions onto flow graphs is straightforward. NOTE: The mapping of TTCN-3 statements onto flow graphs is an informal step and is not defined by using the BNF rules in ES 201 873-1 [1]. The reason for this is that the BNF rules are not optimal for an intuitive mapping because several static semantic rules are coded into BNF rules in order to allow static semantic checks during the syntax check.
5
1) 2)
3) 4)
6
a) b) c)
Restrictions
A semantics for the data aspects of TTCN-3. This includes aspects like encoding, decoding and the usage of data imported from non-TTCN-3 specifications. A semantics for the grouping mechanism. Grouping is related to the definitions part of a TTCN-3 module and has no behavioural aspects. A semantics for the import statement. The import of definitions has to be done in the definitions part of a TTCN-3 module. The operational semantics handles imported definitions as if they are defined in the importing module.
The operational semantics only covers behavioural aspects of TTCN-3, i.e. it describes the meaning of statements and operations. It does not provide:
ETSI
10
Short forms have to be expanded by the corresponding complete definitions on a textual level before this operational semantics can be used for the explanation of TTCN-3 behaviour. TTCN-3 short forms are: lists of module parameter, constant and variable declarations of the same type and lists of timer declarations; stand-alone receiving operations; stand-alone altsteps calls; trigger operations; missing return and stop statements at the end of function and test case definitions; missing stop execution statements; interleave statements; select-case statements; break and continue statements; disconnect and unmap operations without parameters; and default values of missing actual parameters.
In addition to the handling of short forms, the operational semantics requires a special handling for module parameters, global constants, i.e. constants that are defined in the module definitions part, and pre-processing macros. All references to module parameters, global constants and pre-processing macros shall be replaced by concrete values. This means, it is assumed that the value of module parameters, global constants and pre-processing macros can be determined before the operational semantics becomes relevant. NOTE 1: The handling of module parameters and global constants in the operational semantics will be different from their handling in a TTCN-3 compiler. The operational semantics describes the meaning of TTCN-3 behaviour and is not a guideline for the implementation of a TTCN-3 compiler. NOTE 2: The operational semantics handles parameters of and local constants in test components, test cases, functions and module control like variables. The wrong usage of local constants or in, out and inout parameters has to be checked statically.
7.1
The textual replacements of short forms, global constants and module parameters have to be done in the following order: 1) 2) 3) 4) 5) 6) 7) replacement of lists of module parameter, constant, variable and timer declarations with individual declarations; replacement of global constants and module parameters by concrete values; replacement of all select-case statements by equivalent nested if-else statements; embedding stand-alone receiving operations into alt statements; embedding stand-alone altstep calls into alt statements; expansion of interleave statements; replacement of all trigger operations by equivalent receive operations and repeat statements;
ETSI
11
8) 9)
adding return at the end of functions without return statement, adding self.stop operations at the end of testcase definitions without a stop statement; adding stop at the end a module control part without stop statement;
10) expansion of break statements; 11) expansion of continue statements; 12) adding default parameters to disconnect and unmap operations without parameters; and 13) adding default values of parameters. NOTE: Without keeping this order of replacement steps, the result of the replacements would not represent the defined behaviour.
7.2
Constants declared in the module definitions part are global for module control and all test components that are created during the execution of a TTCN-3 module. Module parameters are meant to be global constants at run-time. All references to global constants and module parameters shall be replaced by the actual values before the operational semantics starts the interpretation of the module. If the value of a constant or module parameter is given in form of an expression, the expression has to be evaluated. Then, the result of the evaluation shall replace all references of the constant or module parameter.
7.3
TTCN-3 receiving operations are: receive, trigger, getcall, getreply, catch, check, timeout, and done. NOTE: The operations receive, trigger, getcall, getreply, catch and check operate on ports and they allow branching due to the reception of messages, procedure calls, replies and exceptions. The operations timeout and done are not real receiving operations, but they can be used in the same manner as receiving operations, i.e. as alternatives in alt statements. Therefore, the operational semantics handles timeout and done like receiving operations.
A receiving operation can be used as stand-alone statement in a function, an altstep or a test case. The timeout operation can also be used as stand-alone statement in module control. In such a case the receiving operation as considered to be shorthand for an alt statement with only one alternative defined by the receiving operation. For the operational semantics an alt statement in which the receiving statement is embedded shall replace all stand-alone occurrences of receiving operations. EXAMPLE:
// The stand-alone occurrence of : MyCL.trigger(MyType:?); : // shall be replaced by : alt { [] MyCL.trigger (MyType:?) { } } : // or : MyPTC.done; : // shall be replaced by : alt { [] MyPTC.done { }
ETSI
12
} :
7.4
TTCN-3 allows calling altsteps like functions in functions, altsteps, test cases and module control. The meaning of a stand-alone call of an altstep is given by an alt statement with one branch only that calls the altstep. The alt statement is responsible for the snapshot that is evaluated within the altstep and for the invocation of the default mechanism if none of the alternatives in the altstep can be chosen. NOTE: An altsteps used in module control can only include alternatives with timeout operations and an else branch.
EXAMPLE:
// The stand-alone occurrence of : myAltstep(MyPar1Val); : // shall be replaced by : alt { [] myAltstep(MyPar1Val) { } } :
7.5
The meaning of an interleave statement is defined by its replacement by a series of nested alt statements that has the same meaning. The algorithm for the construction of the replacement for an interleave statement is described in this clause. The replacement shall be made on a syntactical level. Within an interleave statement it is not allowed: 1) 2) 3) 4) 5) to use the control transfer statements for, while, do-while, goto, activate, deactivate, stop, repeat and return; to call altsteps; to call user-defined functions which include communication operations; to guard branches of the interleave statement with Boolean expressions; and to specify else branches.
Due to these restrictions, all not mentioned stand-alone statements (e.g. assignment, log, send or reply), blocking call operations and the compound statements interleave, if-else and alt can be used within an interleave statement. NOTE 1: Blocking call operations and if-else statements can be treated like stand-alone statements if they have no embedded alt statements. In case of embedded alt statements, the alternatives contribute to the interleave statement and need a special handling. For simplicity, the algorithm below does not distinguish between these two cases. NOTE 2: Non-blocking call operations are also allowed in interleave statements, they are considered to be stand-alone statements. The algorithm described in this clause only works for interleave statements without embedded interleave statements. In case of an interleave statement that has embedded interleave statements, the embedded interleave statements have to be replaced before the algorithm can be applied. NOTE 3: Due to restrictions 1 to 5, it is always possible to find finite replacements for nested embeddings of interleave statements.
ETSI
13
The replacement algorithm works on a graph representation of an interleave statement and transforms it into a semantically equivalent tree structure describing a series of nested alt statements. For this, a graph representation of stand-alone statements, the compound statements if-else, blocking call, alt and interleave is needed. A stand-alone statement is described by a node with the statement as inscription. A sequence of stand-alone statements is described by a set of nodes connected by a flow lines. This is shown in figure 1.
P1.send(MyVar);
P1.send(MyVar);
P1.send(MyVar); x := 7 + 5; x := 7 + 5;
Figure 1: Graph representation of TTCN-3 stand-alone statements The graph representation of an if-else statement is shown in figure 2. An if-else statement is represented by an IF node with two flow lines connected to the first statement in the two alternatives. An if-else statement without ELSE branch is represented in the same manner, if there are statements following the if-else statement. In this case the flow line representing the else branch is connected to the first statement following the if-else statement. An if-else statement without ELSE branch and without following statements is represented by an IF node with one flow line only. NOTE 4: The inscriptions on the flow lines in figure 1 are introduced for readability purposes only. The algorithm only uses the relation expressed by the flow line and not the inscription.
IF
(x < 7)
ELSE
P1.send(MyVar);
x := 7 + 5;
x := x * 2;
if (x < 7) { P1.send(MyVar); } x := x * 2
ELSE P1.send(MyVar);
x := x * 2;
ETSI
14
The graph representation of a blocking call statement is shown in figure 3. A blocking call statement is represented by a BLOCKING-CALL node with flow lines connected to the getreply and catch statements of the different alternatives.
P1.call (MyProc:{-, true}, 20E-3) { [] P1.getreply(MyProc:{?,-} { setverdict(pass); } [] P1.catch(MyProc, MyException) {} [] P1.catch(timeout) { setverdict(fail); } } x := 7 + 5;
P1.getreply(MyProc:{?,-})
P1.catch(timeout)
P1.catch(MyProc, MyException)
setverdict(pass);
setverdict(fail);
x := 7 + 5;
Figure 3: Graph representation of a TTCN-3 blocking call statement The graph representation of an alt statement is shown in figure 4. An alt statement is represented by an alt-node with several flow lines connected to the different alternatives.
ETSI
15
P1.receive(MyMessageOne)
T1.timeout
P1.receive(MyMessageTwo)
setverdict(pass);
setverdict(fail);
x := 7 + 5;
Figure 4: Graph representation of a TTCN-3 alt statement In general, the graph representations of if-else, blocking call and alt statements are directed graphs without loops where the flow lines of the different alternatives join when leaving the statement. By means of duplication, it is possible to transform such directed graphs into a semantically equivalent tree representation. This is shown in figure 5 for the alt statement in figure 4. The algorithm described below will construct such tree representations.
ETSI
16
P1.receive(MyMessageOne)
T1.timeout
P1.receive(MyMessageTwo)
setverdict(pass);
setverdict(fail);
x := 7 + 5;
x := 7 + 5;
x := 7 + 5;
ETSI
17
An interleave statement can be described by a graph that consists of a set of directed sub-graphs, each of which is constructed by means of stand-alone statements and the compound statements if-else, blocking call and alt. The directed sub-graphs describe the interleaved flows of control. An example is shown in figure 6. The node inscriptions in figure 6 (b) refer to the labels of the TTCN-3 statements in figure 6(a).
interleave { [] P1.receive(M1} { alt { [] P1.receive(M3) { setverdict(pass); } [] T1.timeout { } } } [] P2.receive(M2) { if (x < 5 ) { alt { [] P2.receive(M4) { setverdict(pass); } [] Comp1.done { } } x := 7 + 5; } else { P3.call(MyProcTempl, 20E-3) { [] P3.getreply(ReplyTempl) { alt { [] P2.receive(M5) { } [] P2.receive(M6) { } } } [] P3.catch(timeout) { setverdict(fail); } } } } } // // // // L1 ALT L2 L3
// L4
// // // // //
L5 IF ALT L6 L7
// L8 // L9
// L13 // L14
ALT
IF
L2
L4
ALT
BC
L3
L6
L8
L10
L13
L7
ALT
L14
L9
L11
L12
ETSI
18
Formally, an interleave statement can be described by a graph GI = (St, F) where: St F (St St) is the set of allowed TTCN-3 statements; and describes the flow relation.
The term allowed TTCN-3 statements refers to the static restrictions 1-5 above. For the construction algorithm the following functions need to be defined: The REACHABLE function returns all statements that are reachable from a statement s in a graph GI = (St, F): REACHABLE (s, GI) = { s } { stmt | stmt St ( s = x1, x2, , xn = stmt) where xi St, i {1n} (xi, xi+1) F}
The SUCCESSORS function returns all successors of a statement s in a graph GI = (St, F): SUCCESSORS (s, GI) = { stmt | stmt St (s, stmt) F}
The ENABLED function returns all statements of a graph GI = (St, F) which have no predecessors: ENABLED (GI) = { stmt | stmt St (F (S {s}) = )}
The KIND function returns the kind or type of a TTCN-3 statement in a graph representing an interleave statement. The DISCARD function deletes a statement s or a set of statements S from a graph GI = (St, F) and returns the resulting graph GI'= (St', F'): For single nodes: DISCARD For sets of nodes: DISCARD (S, GI) = GI' where: GI' = (St', F'), with St' = St\S and F' = F (St\S St\S). (s, GI) = GI' where: GI' = (St', F'), with St' = St\{s} and F' = F (St\{s} St\{s}).
The RECEIVING function takes a set of statements of a graph GI and returns all receiving statements: RECEIVING (S) = { stmt | stmt St KIND(stmt) {receive, trigger, getcall, getreply, catch, check, done, timeout}}
The RANDOM function selects randomly an element s from a given set S and returns s. RANDOM (S) = s where s S
The construction algorithm (see figure 7) of the tree is a recursive procedure where in each recursive call the successor nodes for a given node is constructed. The procedure is provided in a C-like pseudo-code notation that uses the functions defined above and some additional mathematical notation.
ETSI
19
CONSTRUCT-SUCCESSORS (statementType *predecessor, graphType GI) { // - statementType refers to the type of a node of the tree that is constructed // - *predecessor refers to the last node that has been created // - graphType denotes type of the graph of TTCN-3 statements // - GI is called by value and refers to the subgraph consisting of all remaining TTCN-3 // statements that have to be taken into consideration var graphType myGraph; var statementType i, myStmt; var statementType *newStmt, *firstInBranch; // pointers for new statement nodes in the // tree that is constructed recursively // Retrieving sets of TTCN-3 statements that have no predecessors in 'GI' var statementSet enabStmts := ENABLED(GI); // all statements without predecessor var statementSet enabRecStmts := RECEIVING(enabStmts); // receiving statements in 'enabStmts' var statementSet enabNonRecStmts := enabStmts\enabRecStmts; // non receiving statements in 'enabStmts' if (GI.St == ) { // We assume that GI.St refers to the set of statements in GI return; // No statements are left, termination criterion of Recursion } elseif (enabNonRecStmts != ) { // Handling of non receiving statements in 'enabStmts' myStmt := RANDOM(enabNonRecStmts); // There can only be one statement in 'enabNonRec', because the Algorithm // continues the construction until there is a branch that contributes to // the interlave statement. newStmt := create(myStmt, predecessor); // Creation of a new tree node representing 'myStmt' in the tree // and update of pointers in 'newStmt' and 'predecessor'. if (KIND(myStmt) == IF || KIND(myStmt) == BLOCKING_CALL) { for each i in SUCCESSORS(myStmt, GI) { firstInBranch := create(i, newStmt); // Creation of a second node for the first statement of in a branch due to // an if-else statement. // Note, this create statement will be used to create tree nodes // representing the receiving statements in blocking call operations. myGraph := // // // DISCARD({i, myStmt} REACHABLE(myStmt, GI)\REACHABLE(i, GI)) Removal of i, myStmt and all statements that are reachable from myStmt but not reachable from i. The latter considers the branching of a flow of control in a subgraph of GI. // NEXT RECURSION STEP
CONSTRUCT-SUCCESSORS(mystmt, DISCARD(REACHABLE(myStmt, GI)\REACHABLE(i, GI))); // NEXT RECURSION STEP, the DISCARD(REACHABLE(myStmt, GI)\REACHABLE(i, GI)) // argument considers the branching of a flow of control due to different // receiving events. } } else { // mystmt is a stand-alone statement CONSTRUCT-SUCCESSORS(newSonNode, DISCARD(myStmt, GI)); // NEXT RECURSION STEP } } else { // Handling of receiving events that interleave if (KIND(predecessor) != ALT) { // an alt node is missing and has to be created, if the // interleaving is not influenced by an embedded alt statement predecessor := create(ALT, predecessor); } for each i in enabRecStmts) { newStmt := create(i, predecessor); CONSTRUCT-SUCCESSORS(newStmt, DISCARD(i, GI)); } } }
ETSI
20
Initially, the CONSTRUCT-SUCCESSORS function (see figure 7) will be called with a root node of an empty tree and the graph of TTCN-3 statements describing the interleave statement that shall be replaced. After termination, the root node can be used to access the constructed tree. The application of the CONSTRUCT-SUCCESSORS function to the interleave statement shown in figure 6 leads to the tree shown in figure 8. The labels refer to the statements in figure 6(a). Multiple labels are the result of the duplication of code. The TTCN-3 code that corresponds to the tree in figure 8 is shown in figure 9. NOTE 5: The example for the application of the algorithm in figure 7 (see figures 6, 8 and 9) is very comprehensive. This example is provided in order to show most of the special situations, i.e. branching and joining of flow lines, an embedded alt statement, a blocking call statement and an if-else statement.
ETSI
21
ALT
L1
L5
ALT
IF
L2
L4
L5
ALT
BC
L3
ALT
L6
L8
L2
L4
L10
L13
L5
L7
L9
L3
ALT
L14
IF
L9
ALT
L11
L12
L1
ALT
ALT
BC
ALT
L6
L8
ALT
ALT
L1
ALT
L6
L8
L10
L13
L1
L7
L9
L1
L1
ALT
L5
L7
L9
ALT
L14
ALT
L9
ALT
L2
L4
IF
L9
L11
L12
L2
L4
L2
L4
L3
ALT
BC
L3
ALT
L3
ALT
L6
L8
L10
L13
L1
ALT
L2
L4
L7
L9
ALT
L14
ALT
L6
L8
L3
ALT
L9
L11
L12
IF
L2
L4
L7
L9
L2
L4
L11
L12
ALT
L3
L9
L3
ALT
L6
L8
L2
L4
BC
ALT
L2
L4
L7
L9
L3
L10
L13
L11
L12
L3
ALT
L9
ALT
ALT
L14
ALT
L2
L4
ALT
L6
L8
L2
L4
L11
L12
ALT
L11
L12
L3
L2
L4
L7
L9
L3
ALT
L2
L4
L3
L9
ALT
ALT
L2
L4
L3
ALT
L6
L8
L11
L12
L3
ALT
L2
L4
L7
L9
ALT
L2
L4
L3
L9
L11
L12
L3
Figure 8: Result of applying the algorithm in figure 7 to the interleave statement in figure 6
ETSI
22
alt { []
[]
[]
[]
} } else { P3.call(MyProcTempl, 20E-3) { // BC (= BLOCKING CALL) [] P3.getreply(ReplyTempl) { // L10 alt { // ALT [] P2.receive(M5) { } // L11 [] P2.receive(M6) { } // L12 } } [] P3.catch(timeout) { // L13 setverdict(fail); // L14 } } } } } } T1.timeout { // L4 alt { // ALT [] P2.receive(M2) { // L5 if (x < 5 ) { // IF alt { // ALT [] P2.receive(M4) { // L6 setverdict(pass); // L7 x := 7 + 5; // L9 } [] Comp1.done { // L8 x := 7 + 5; // L9 } } } else { P3.call(MyProcTempl, 20E-3) { // BC (= BLOCKING CALL) [] P3.getreply(ReplyTempl) { // L10 alt { // ALT [] P2.receive(M5) { } // L11 [] P2.receive(M6) { } // L12 } } [] P3.catch(timeout) { // L13 setverdict(fail); // L14 } } } } } } P2.receive(M2) { // L5 if (x < 5 ) { // IF alt { // ALT [] P2.receive(M4) { // L6 setverdict(pass); // L7 x := 7 + 5; // L9 alt { // ALT // L2 [] P1.receive(M3) { setverdict(pass); // L3 } [] T1.timeout { } // L4 } } [] Comp1.done { // L8 x := 7 + 5; // L9 alt { // ALT // L2 [] P1.receive(M3) { setverdict(pass); // L3 } [] T1.timeout { } // L4 } } // L2 [] P1.receive(M3) { setverdict(pass); // L3 alt { // ALT [] P2.receive(M4) { // L6 setverdict(pass); // L7 x := 7 + 5; // L9 } [] Comp1.done { // L8 x := 7 + 5; // L9 } } }
// L8 // L9
ETSI
23
[]
[]
} } else { P3.call(MyProcTempl, 20E-3) { // BC (= BLOCKING CALL) [] P3.getreply(ReplyTempl) { // L10 alt { // ALT // L2 [] P1.receive(M3) { setverdict(pass); // L3 alt { // ALT [] P2.receive(M5) { } // L11 [] P2.receive(M6) { } // L12 } } [] T1.timeout { // L4 alt { // ALT [] P2.receive(M5) { } // L11 [] P2.receive(M6) { } // L12 } } [] P2.receive(M5) { // L11 alt { // ALT // L2 [] P1.receive(M3) { setverdict(pass); // L3 } [] T1.timeout { } // L4 } } [] P2.receive(M6) { // L12 alt { // ALT // L2 [] P1.receive(M3) { setverdict(pass); // L3 } [] T1.timeout { } // L4 } } } } [] P3.catch(timeout) { // L13 setverdict(fail); // L14 alt { // ALT // L2 [] P1.receive(M3) { setverdict(pass); // L3 } [] T1.timeout { } // L4 } } } } } } } P2.receive(M2) { // L5 if (x < 5 ) { // IF alt { // ALT [] P2.receive(M4) { // L6 setverdict(pass); // L7 x := 7 + 5; // L9 alt { // ALT [] P1.receive(M1} { // L1 alt { // ALT // L2 [] P1.receive(M3) { setverdict(pass); // L3 } [] T1.timeout { } // L4 } } } } [] Comp1.done { // L8 x := 7 + 5; // L9 alt { // ALT [] P1.receive(M1} { // L1 alt { // ALT // L2 [] P1.receive(M3) { setverdict(pass); // L3 } [] T1.timeout { } // L4 } } } } // L2 [] P1.receive(M3) { setverdict(pass); // L3 alt { // ALT [] P2.receive(M4) { // L6 setverdict(pass); // L7 x := 7 + 5; // L9 } [] Comp1.done { // L8
// L8 // L9
ETSI
24
x := 7 + 5; } } } T1.timeout { alt { [] P2.receive(M4) { setverdict(pass); x := 7 + 5; } [] Comp1.done { x := 7 + 5; } } }
[]
// L8 // L9
} } else { P3.call(MyProcTempl, 20E-3) { // BC (= BLOCKING CALL) [] P3.getreply(ReplyTempl) { // L10 alt { // ALT [] P2.receive(M5) { // L11 alt { // ALT [] P1.receive(M1} { // L1 alt { // ALT [] P1.receive(M3) { // L2 setverdict(pass); // L3 } [] T1.timeout { } // L4 } } } } [] P2.receive(M6) { // L12 alt { // ALT [] P1.receive(M1} { // L1 alt { // ALT [] P1.receive(M3) { // L2 setverdict(pass); // L3 } [] T1.timeout { } // L4 } } } } [] P1.receive(M1} { // L1 alt { // ALT // L2 [] P1.receive(M3) { setverdict(pass); // L3 alt { // ALT [] P2.receive(M5) { } // L11 [] P2.receive(M6) { } // L12 } } [] T1.timeout { // L4 alt { // ALT [] P2.receive(M5) { } // L11 [] P2.receive(M6) { } // L12 } } [] P2.receive(M5) { // L11 alt { // ALT [] P1.receive(M3) { // L2 setverdict(pass); // L3 } [] T1.timeout { } // L4 } } [] P2.receive(M6) { // L12 alt { // ALT // L2 [] P1.receive(M3) { setverdict(pass); // L3 } [] T1.timeout { } // L4 } } } } } } [] P3.catch(timeout) { // L13 setverdict(fail); // L14 alt { // ALT [] P1.receive(M1} { // L1 alt { // ALT [] P1.receive(M3) { // L2 setverdict(pass); // L3 } [] T1.timeout { } // L4 } } } } } }
Figure 9: Semantically equivalent TTCN-3 code for the interleave statement in figure 6
ETSI
25
7.6
The trigger operation filters messages with a certain matching criterion from a stream of messages on a given port. The semantics of the trigger operation can be described by its replacement with two receive operations and a goto statement. The operational semantics assumes that this replacement is done on the syntactical level. EXAMPLE 1:
// The following trigger operation alt { [] }
MyCL.trigger (MyType:?) { }
If the trigger statement is used in a more complex alt statement, the replacement is done in the same manner. EXAMPLE 2:
// The following alt statement includes a trigger statement alt { []
[] []
[] []
[]
7.7
The select-case statement is an alternative to using a set of nested if-else statements when comparing a value (defined by a select-expression following the select keyword) to one or several other values (defined by template instances in the case branches). Therefore, the semantics of a select-case statement can be described by its replacement with a set of nested if-else statements. To avoid a multiple evaluation of the select-expression, the set of nested if-else statements has to be placed into a statement block and value of the expression has to be stored in a variable at the beginning of the statement block. The operational semantics assumes that this replacement is done on the syntactical level.
ETSI
26
The syntactical replacement of the schematic select-case statement by nested if-else statements looks as follows:
{ var <expression>Type myTempVar := <expression>; // temporary variable for storing the // value of the expression if (match(myTempVar, <templateInst1a>) or or match(myTempVar, <templateInst1n>)) <statementblock1> else { if (match(myTempVar, <templateInst2a>) or or match(myTempVar, <templateInst2n>)) <statementblock2> else { if (match(myTempVar, <templateInstxa>) or or match(myTempVar, <templateInstxn>)) <statementblockx> else <statementblockx+1> } } }
EXAMPLE:
// The following select-case statement: select (MyModulePar) { // where MyModulePar is of charstring type case ("firstValue") { log ("The first branch is selected"); } case (MyCharstingVar, MyCharstringConst) { log ("The second branch is selected"); } case else { log ("The else branch is selected"); } } // is semantically equivalent to: { var charstring myTempVar := MyModulePar; if (match(myTempVar, "firstValue")) { log ("The first branch is selected"); } else { if (match(myTempVar, MyCharstingVar) or match(myTempVar, MyCharstingConst)) { log ("The second branch is selected"); } else { log ("The else branch is selected"); } } }
ETSI
27
7.8
"Simple" break statements are break statements used for leaving loops, interleave statements and alt statements. Such simple break statements are considered to be a short-hand form for using a pair of goto-label statements. For each break statement a label statement is added after the loop, alt statement or expanded interleave statement. The label statement shall have an unused label. The break statement is replaced by a goto statement to this specific label. Note, that interleave statements are explained already. Therefore the limitation that goto statements cannot be used within interleave statements does not hold. NOTE: The semantics for the break statement used to leave an altstep is defined in clause 9.5a.
EXAMPLE:
// The following loop with a break statement: while (cond1) { // cond1 is a Boolean condition guarding the loop if(cond2) { break; }; } // is semantically equivalent to: while (cond1) { // cond1 is a Boolean condition guarding the loop if(cond2) { goto break_12345; // break_12345 is a unique label }; } label break_12345;
7.9
The continue statement is a short-hand form for using a pair of goto-label statements. For each continue statement a label statement is added at the end of the loop body. The label statement shall have an unused label. The continue statement is replaced by a goto statement to this specific label. EXAMPLE:
// The following loop with a continue statement: while (cond1) { // cond1 is a Boolean condition guarding the loop if(cond2) { continue; }; }
// is semantically equivalent to: while (cond1) { // cond1 is a Boolean condition guarding the loop if(cond2) { goto continue_12345; // continue_12345 is a unique label }; label continue_12345; }
ETSI
28
7.10
The usage of a disconnect or unmap operation without any parameters is a shorthand form for using the operation with the parameter self:all port. It disconnects or unmaps all ports of the component that calls the operation. For the operational semantics the parameter self:all port shall be added to all occurrences of disconnect and unmap operations without parameters. EXAMPLE:
// each occurrence of disconnect; // shall be expanded in the following manner: disconnect(self:all port); // and // each occurrence of unmap; // shall be expanded in the following manner: unmap(self:all port);
7.11
Formal parameters may have default values. If no actual parameter is provided in a specific invocation, then the default value is added to the actual parameter list. If list notation has been used for the actual parameter list, then the default value is inserted according to the order in the formal parameter list. If assignment notation has been used for the actual parameter list, then the default values are appended to the actual parameters, the order among the default values corresponds to their order in the formal parameter list. EXAMPLE:
function f_comp (in integer p_int1, in integer p_int2 := 3) return integer { var integer v := p_int1 + p_int2; : return v; } // Each occurrence of f_comp(1) // shall be expanded to f_comp(1, 3); // Each occurrence of f_comp(p_int1 := 1) // shall be expanded to f_comp(p_int1 := 1, p_int2 := 3);
The operational semantics of TTCN-3 is based on the interpretation of flow graphs. In this clause flow graphs are introduced (see clause 8.1), the construction of flow graphs representing TTCN-3 module control, test cases, altsteps, functions and component type definitions is explained (see clause 8.2), module and component states for the description of the execution states of a TTCN-3 module are defined (see clause 8.3), the handling of messages, remote procedure calls, replies to remote procedure calls and exceptions is described (see clause 8.4) and the evaluation procedure of module control and test cases is explained (see clause 8.6).
ETSI
29
8.1
Flow graphs
A flow graph is a directed graph that consists of labelled nodes and labelled edges. Traversing a flow graph describes the possible flow of control during the execution of a represented behaviour description.
8.1.1
A flow graph shall be put into a frame defining the border of the flow graph. The name of flow graph follows the keywords flow graph (these are not TTCN-3 core language keywords) and shall be put into the upper left corner of the flow graph. As convention it is assumed that the flow graph name refers to the TTCN behaviour description represented by the flow graph. A simple flow graph is shown in figure 10.
inscription
8.1.2
Flow graphs consist of start nodes, end nodes, basic nodes and reference nodes.
8.1.2.1
Start nodes
Start nodes describe the starting point of a flow graph. A flow graph shall only have one start node. A start node is shown in figure 11(a).
8.1.2.2
End nodes
End nodes describe end points of a flow graph. A flow graph may have several end nodes or in case of loops no end node. Basic nodes (see clause 8.1.2.3) and reference nodes (see clause 8.1.2.4) that have no successor nodes shall be connected to an end node to indicate that they describe the last action of a path through a flow graph. An end node is shown in figure 11(b).
8.1.2.3
Basic nodes
A basic node describes an execution unit, i.e. it is executed in one step. A basic node has a type and, depending on the type, may have an associated list of attributes. Two basic nodes are shown in figure 12. In the inscription of a basic node the attributes of a node follow the node type and are put into round parentheses. Type and attributes are used to determine the action to be performed during execution of the represented language construct. The attributes describe information to be retrieved from the corresponding TTCN-3 construct.
ETSI
30
Attributes have values and the operational semantics will retrieve these values by referring to the attribute name. If required, it is allowed to assign explicit values in basic nodes by using assignment ":=". An example is shown in figure 12(b).
8.1.2.4
Reference nodes
Reference nodes refer to flow graph segments (see clause 8.1.4) that are sub-flow graphs. The meaning of a reference node is defined by its replacement by the referenced flow graph segment in the flow graph. The node inscription of the reference node provides the reference to a flow graph segment. A reference node is shown in figure 13(a).
segment-reference
8.1.2.4.1
In some cases several flow graph segments may replace a reference node. For these cases an OR operator may be used to refer to several flow graph segments (see figure 13(b)). In the actual flow graph representing the module control, a test case or a function, one alternative is determined by the represented construct.
8.1.2.4.2
In some cases the same kind of reference node may occur zero, one or more times in a flow graph. In regular expressions the possible repetition of parts of a regular expression is described by using the operator symbols "+" (one or more repetitions) and "*" (zero or more repetitions). As shown in figure 14, these operators have been adopted to flow graphs by introducing double-framed reference nodes with associated operator symbols. A single flow (see clause 8.1.3) line shall replace a reference node, in case of zero occurrences (using a double-framed reference node with "*"-operator).
*
segment-reference
+
segment-reference
Figure 14: Repetition of reference nodes An upper bound of possible repetitions of a reference node can be given in form of an integer number in round parenthesis following the "*" or "+" symbol in the double framed reference node. The segment reference shown in figure 15 may occur from zero up to 5 times.
ETSI
31
*(5)
segment-reference
Figure 15: Restricted repetition of a reference node
8.1.3
Flow lines
Flow lines are represented by means of arrows. A flow line has an inscription of true or false which indicates a condition under which the flow line is chosen during the flow graph interpretation. As a short hand notation it is allowed to omit the true inscription. Examples of flow lines are shown below:
false
true
which is identical to
To support the joining of several flow lines into one flow line on a graphical level, a special join node is introduced. The join node and an example for its usage are shown below:
join node:
Drawing long flow lines in big diagrams as it is, for example, necessary to model the TTCN-3 constructs goto and label, is awkward. For this purpose, labels for outgoing and incoming flow lines can be used. Examples are shown below:
Incoming flow line with label: Outgoing flow line with label:
in-label
out-label
An outgoing flow line with a label is connected with an incoming flow line with a label, if the labels are identical. The flow line labels for the incoming flow lines shall be unique. If there are several outgoing flow lines with the same label, this is considered to be a join of lines to the incoming flow line with an identical label.
8.1.4
Flow graph segments are sub-flow graphs. They are referenced in reference nodes and define the meaning of that reference node. Flow graph segments may include further reference nodes. As shown in figure 16, flow graph segments have precise interfaces that consist of incoming and outgoing flow lines. There is only one unlabeled incoming and one or none unlabeled outgoing flow lines. In addition there might exist several labelled incoming and outgoing flow lines. For example, the labelled incoming and outgoing flow lines are needed to describe the meaning of TTCN-3 statements goto and alt.
ETSI
32
Flow graph segments are put into a frame and the name of the flow graph segment shall follow the keyword segment followed by the segment name in the upper left corner of the frame. The flow lines describing the flow graph segment interface shall cross the flow graph segment frame.
segment SegmentName
LI1 LIn
inscription
segment-ref
LO1
LO2
LOm
8.1.5
Comments
To improve readability and coherence a special comment symbol can be used to associate comments to flow graph nodes and flow lines. The comment symbol and its usage are shown in figure 17.
inscription
This is a comment in a comment symbol
ETSI
33
8.1.6
The evaluation procedure of the operational semantics traverses flow graphs that only consist of basic nodes, i.e. all reference nodes have to be expanded by the corresponding flow graph segment definitions. The NEXT function is required to support this traversal. NEXT is defined in the following manner: actualNodeRef.NEXT(bool) := successorNodeRef where: actualNodeRef successorNodeRef bool is the reference of a basic flow graph node; is the reference of a successor node of the node referenced by actualNodeRef; is a Boolean specifying whether the true or the false successor is returned (see clause 8.1.3).
8.2
The operational semantics assumes that TTCN-3 behaviour descriptions are provided in form of a set of flow graphs, i.e. for each TTCN-3 behaviour description a separate flow graph has to be constructed. The operational semantics interprets the following kinds of TTCN-3 definitions as behaviour descriptions: a) b) c) d) e) module control; test case definitions; function definitions; altstep definitions; component type definitions.
The module control specifies the test campaign, i.e. the execution order (possibly repetitious) of the actual test cases. Test case definitions define the behaviour of the MTC. Functions structure behaviour. They are executed by the module control or by the test components. Altsteps are used for the definition of default behaviour or in a function-like manner to structure behaviour. Component type definitions are assumed to be behaviour descriptions because they specify the creation, declaration and initialization of ports, constants, variables and timers during the creation of an instance of a component type.
8.2.1
The flow graphs presented in the figures 18 to 22 and the flow graph segments presented in clause 8 are only templates. They include placeholders for information that has to be provided in order to produce a concrete flow graph or flow graph segment. The placeholders are marked with "<" and ">" parenthesis. The construction of a flow graph representation of a TTCN-3 module is done in three steps: 1) 2) 3) For each TTCN-3 statement in module control, test cases, altsteps, functions and component type definitions a concrete flow graph segment is constructed. For the module control and for each test case, altstep, function and component type definition a concrete flow graph (with reference nodes) is constructed. In a stepwise procedure all reference nodes in the concrete flow graphs are replaced by corresponding flow graph segment definitions until all flow graphs only include one start node, end nodes and basic flow graph nodes.
NOTE 1: Basic flow graph nodes describe basic indivisible execution units. The operational semantics for TTCN-3 behaviour is based on the interpretation of basic flow graph nodes. Clause 8.6 presents execution methods for basic flow graph nodes only.
ETSI
34
The replacement of a reference node by the corresponding flow graph segment definition may lead to unconnected parts in a flow graph, i.e. parts which cannot be reached from the start node by traversing through the flow graph along the flow lines. The operational semantics will ignore unconnected parts of a flow graph. NOTE 2: An unconnected part of a flow graph is a result of the mechanical replacement procedure. For the construction of an optimal flow graph representation the different combinations of TTCN-3 statements also has to be taken into consideration. However, the goal of the present document is to provide a correct and complete semantics, not an optimal flow graph representation.
8.2.2
For the flow graph behaviour representation the following information is relevant only:
module <identifier> <statement-block>
This is comparable to a function definition and therefore the flow graph representation of module control is similar to the flow graph representation of a function (see clause 8.2.4). The semantics will access the flow graph representing the module control by using the module name. NOTE: The meaning of the module definitions part is outside the scope of this operational semantics. Module parameters are defined as global constants at run-time. References to module parameters have to be replaced by their concrete values on a syntactical level (see clause 8.3).
The scheme of the flow graph representation of the module control is shown in figure 18. The flow graph name control identifies the flow graph representing the module control. The nodes of the flow graph have associated comments describing the meaning of the different nodes. The reference node <stop-entity-op> covers the case where no explicit stop operation is specified, i.e. the operational semantics assumes that a stop operation is implicitly added.
<init-component-scope>
// The module control behaves like a // component and therefore, its scope // has to be initialised.
<statement-block>
*(1)
<stop-entity-op>
// For the case that an explicit stop // operation is missing at the end of // module control
ETSI
35
8.2.3
The <testcase-interface> above refers to the (mandatory) runs on and the (optional) system clauses in the test case definition. The flow graph description of a test case describes the behaviour of the MTC. Variables, timers and constants defined and declared in the component type definition are made visible to the MTC behaviour by the runs on clause in the <testcase-interface>. The system clause is not relevant for the MTC and is therefore not represented in the flow graph representation of a test case. The scheme of the flow graph representation of a test case is shown in figure 19. The flow graph name <identifier> refers to the name of the represented test case. The nodes of the flow graph have associated comments describing the meaning of the different nodes. The reference node <stop-entity-op> covers the case where no explicit stop operation for the MTC is specified, i.e. the operational semantics assumes that a stop operation is implicitly added.
<init-scope-with-runs-on>
// Considers scope information provided // by the runs-on clause in the // interface of the test case. // // - Actual parameter values are // assumed to be in the value stack // // - Formal parameters are handled // like local variables and local // timers
<parameter-handling>
<statement-block>
// The body of the test case specifies // the statements to be executed // by the MTC.
*(1)
<stop-mtc>
// For the case that an explicit stop // operation is missing at the end of // the test case
8.2.4
The optional <function-interface> above refers to the (optional) runs on and the (optional) return clauses in the function definition.
ETSI
36
The scheme of the flow graph representation of a function is shown in figure 20. The flow graph name <identifier> refers to the name of the represented function. Variables, timers, constants and ports defined and declared in the component type definition are made visible to within the function by the runs on clause in the <function-interface>. A missing runs on clause means that definitions within the component type definition are not known within the scope of the function. The operational semantics distinguishes these two cases by the reference nodes <init-scope-with-runs-on> and <init-scope-without-runs-on>. The reference node <return-without-value> covers the case where no explicit return statement is specified, i.e. the operational semantics assumes that a return statement is implicitly added.
<init-scope-with-runs-on> OR <init-scope-without-runs-on>
<parameter-handling>
// - Actual parameter values are // assumed to be in the value stack // // - Formal parameters are handled // like local variables and local // timers
<statement-block>
// The body of the function specifies // the statements to be executed // by the component.
*(1)
<return-without-value>
// For the case that an explicit // return statement is missing at the // end of the function.
8.2.5
NOTE:
Only the alternatives up to the first else branch and the first else branch are taken into consideration. Branches following the first else branch are unreachable.
The optional <altstep-interface> above refers to the runs on clause in the altstep definition.
ETSI
37
The scheme of the flow graph representation of an altstep is shown in figure 21. The flow graph name <identifier> refers to the name of the represented altstep. Variables, timers, constants and ports defined and declared in the component type definition are made visible to within the function by the runs on clause in the <function-interface>. A missing runs on clause means that definitions made within the component type definition are not known within the scope of the function. The operational semantics distinguishes these two cases by the reference nodes <init-scope-with-runs-on> and <init-scope-without-runs-on>. The reference node <return-without-value> covers the case where no else-branch is specified and none of the alternatives can be selected.
<init-scope-with-runs-on> OR <init-scope-without-runs-
<parameter-handling>
// - Actual parameter values are // assumed to be in the value stack // // - Formal parameters are handled // like local variables and local // timers
// Alternative // branches
*(1)
<return-without-value>
// For the case where no else branch // is specified and none of the // alternatives can be selected.
8.2.6
The semantics will access flow graphs representing types by using the component type names. The scheme of the flow graph representation of a component type definition is shown in figure 22. The flow graph name <identifier> refers to the name of the represented component type.
ETSI
38
*
<port-declaration> OR <constant-definition> OR <variable-declaration> OR <timer-declaration> // Ports are created // Constants, variables and timers // are declared and initialised
// The 'father' component waits for the // completion of the component creation, // i.e., is in a 'blocking' state. <finalise-component-init> // The created component gives the // control back to the 'father' component. // The new component goes into a // 'blocking' state and waits to be // started.
8.2.7
For the retrieval of the start node reference of a flow graph the following function is required:
The GET-FLOW-GRAPH function:
The function returns a reference to the start node of a flow graph with the name flow-graph-identifier. The flow-graph-identifier refers to the module name for the control, to test case names, to function names, to altstep names and to component type names.
8.3
During the interpretation of flow graphs representing TTCN-3 behaviour, module states are manipulated. A module state is a structured state that consists of several sub-states describing the states of module control and the different test configurations. A test configuration state describes the states of test components and ports. Module states, configuration states, component states and port states are introduced in this clause. In addition, functions to retrieve information from and to manipulate states are defined.
8.3.1
Module state
As shown in figure 23 a module state is structured into a module CONTROL state and a TEST-CONFIGURATION state. The module CONTROL state describes the state of the module control. Module control is handled like a test component, i.e. CONTROL is an entitiy state as defined in clause 8.3.2. The TEST-CONFIGURATION state represents the test configurations that is instantiated when a test case is executed by module control.
CONTROL TEST-CONFIGURATION
ETSI
39
8.3.1.1
The CONTROL state and the TEST-CONFIGURATION state of the module state can be addressed by using their names, i.e. CONTROL and TEST-CONFIGURATION.
8.3.1a
Configuration state
As shown in figure 23a the configuration state is structured into ALL-ENTITY-STATES, ALL-PORT-STATES, TC-VERDICT, DONE and KILLED. ALL-ENTITY-STATES represents the states of all instantiated test components during the execution of a test case. The first element of ALL-ENTITY-STATES is the reference to the MTC of the configuration. ALL-PORT-STATES describes the states of the different ports. TC-VERDICT stores the actual global test verdict of a test case, DONE is a list of all currently stopped test components during test case execution and KILLED is a list of all terminated test components during test case execution. NOTE 1: The number of updates of TC-VERDICT is identical to the number of test components that have terminated. NOTE 2: An alive-type test component is put into the DONE list each time when it is stopped and removed from the DONE list each time when it is started. It is put into the KILL and the DONE list when it is killed. NOTE 3: Port states may be considered to be part of the entity states. By connect and map ports are made visible for other components and therefore, this operational semantics handles ports on the top level of the configuration state.
ALL-ENTITY-STATES MTC ES1 ESn ALL-PORT-STATES P1 Pn TC-VERDICT DONE KILLED
8.3.1a.1
The TC-VERDICT and the lists ALL-ENTITY-STATES, ALL-PORT-STATES, DONE and KILLED can be accessed like variables by their name. For the handling of lists, e.g. ALL-ENTITY-STATES, ALL-PORT-STATES, DONE and KILLED in module states, the list operations add, append, delete, member, first, last, length, next, random and change can be used. They have the following meaning: myList.add(item) adds item as first element into the list myList and myList.add(sublist) adds the list sublist to list myList, i.e. add can be used to add single elements or lists to lists; myList.append(item) appends item as last element into the list myList and myList.append(sublist) appends the list sublist to list myList, i.e. append can be used to append single elements or lists to lists; myList.delete(item) deletes item from the list myList; myList.member(item) returns true if item is an element of the list myList, otherwise false; myList.first() returns the first element of myList; myList.last() returns the last element of myList; myList.length() returns the length of myList; myList.next(item) returns the element that follows item in myList, or NULL if item is the last element in myList; myList.random(<condition>) returns randomly an element of myList, which fulfils the Boolean condition <condition> or NULL, if no element of myList fulfils <condition>; myList.change(<operation>) allows to apply <operation> on all elements of myList. The operations random and change are not common list operations. They are introduced to explain the meaning of the keywords all and any in TTCN-3 operations.
NOTE:
ETSI
40
Additionally, a general copy operation is available. The copy operation copies and returns an item instead of returning a reference to an item: copy(item) returns a copy of item.
8.3.2
Entity states
Entity states are used to describe the actual states of module control and test components. In the module state, CONTROL is an entity state and in the configuration state, the test component states are handled in the list ALL-ENTITY-STATES. The structure of an entity state is shown in figure 24.
STATUS CONTROL-STACK DEFAULT-LIST DEFAULT-POINTER VALUE-STACK E-VERDICT TIMER-GUARD DATA-STATE TIMER-STATE PORT-REF SNAP-ALIVE SNAP-DONE SNAP-KILLED KEEP-ALIVE
Figure 24: Structure of an entity state The STATUS describes whether the module control or a test component is ACTIVE, BREAK, SNAPSHOT, REPEAT or BLOCKED. Module control is blocked during the execution of a test case. Test components are blocked during the creation of other test components, i.e. when they call a create operation, and when they wait for being started. The status SNAPSHOT indicates that the component is active, but in the evaluation phase of a snapshot. The status REPEAT denotes that the component is active and in an alt statement that should be re-evaluated due to a repeat statement. The BREAK status is set when a break statement is executed for leaving altstep. In this case, the alt statement in which the altstep was directly or indirectly (i.e. by means of the default mechanism) called is immediately left. The CONTROL-STACK is a stack of flow graph node references. The top element in CONTROL-STACK is the flow graph node that has to be interpreted next. The stack is required to model function calls in an adequate manner. The DEFAULT-LIST is a list of activated defaults, i.e. it is a list of pointers that refer to the start nodes of activated defaults. The list is in the reverse order of activation, i.e. the default that has been activated first is the last element in the list. During the execution of the default mechanism, the DEFAULT-POINTER refers to the next default that has to be evaluated if the actual default terminates unsuccessfully. The VALUE-STACK is a stack of values of all possible types that allows an intermediate storage of final or intermediate results of operations, functions and statements. For example, the result of the evaluation of an expression or the result of the mtc operation will be pushed onto the VALUE-STACK. In addition to the values of all data types known in a module we define the special value MARK to be part of the stack alphabet. When leaving a scope unit, the MARK is used to clean VALUE-STACK. The E-VERDICT stores the actual local verdict of a test component. The E-VERDICT is ignored if an entity state represents the module control. The TIMER-GUARD represents the special timer, which is necessary to guard the execution time of test cases and the duration of call operations. The TIMER-GUARD is modelled as a timer binding (see clause 8.3.2.4 and figure 28).
ETSI
41
The DATA-STATE is considered to be a list of lists of variable bindings. The list of lists structure reflects nested scope units due to nested function and altstep calls. Each list in the list of lists of variable bindings describes the variables declared in a certain scope unit and their values. Entering or leaving a scope unit corresponds to adding or deleting a list of variable bindings from the DATA-STATE. A description of the DATA-STATE part of an entity state can be found in clause 8.3.2.2. The TIMER-STATE is considered to be a list of lists of timer bindings. The list of lists structure reflects nested scope units due to nested function and altstep calls. Each list in the list of lists of timer bindings describes the known timers and their status in a certain scope unit. Entering or leaving a scope unit corresponds to adding or deleting a list of timer bindings from the TIMER-STATE. A description of the TIMER-STATE part of an entity state can be found in clause 8.3.2.4. The PORT-REF is considered to be a list of lists of port bindings. The list of lists structure reflects nested scope units due to nested function and altstep calls. Nested scope units for ports are the result of port parameters in functions and altsteps. Each list in the list of lists of port bindings identifies the known ports in a certain scope unit. Entering or leaving a scope unit corresponds to adding or deleting a list of port bindings from the PORT-REF. A description of the PORT-REF part of an entity state can be found in clause 8.3.2.6. NOTE: The TTCN-3 semantics administrates ports globally in the module state. Due to port parameterization, a test component may access a port by using different names in different scopes. The PORT-REF part of an entity state is used to identify port states uniquely in the module state.
The SNAP-ALIVE supports the snapshot semantics of test components. When a snapshot is taken, a copy of the ALL-ENTITY-STATES list of the module state will be assigned to SNAP-ALIVE, i.e. SNAP-ALIVE includes all entities (test components and test control) which are alive in the test system. The SNAP-DONE supports the snapshot semantics of test components. When a snapshot is taken, a copy of the DONE list of the module state will be assigned to SNAP-DONE, i.e. SNAP-DONE is a list of component identifiers of stopped components. The SNAP-KILLED supports the snapshot semantics of test components. When a snapshot is taken, a copy of the KILLED list of the module state will be assigned to SNAP-KILL, i.e. SNAP-DONE is a list of component identifiers of terminated components. The KEEP-ALIVE field indicates whether the entity can be restarted after its termination or not. It is set to true if the entity can be restarted. Otherwise it is set to false.
8.3.2.1
The STATUS, DEFAULT-POINTER, E-VERDICT and TIMER-GUARD parts of an entity state are handled like variables that are globally visible, i.e. the values of STATUS, DEFAULT-POINTER and E-VERDICT can be retrieved or changed by using the "dot" notation, e.g. myEntity.STATUS, myEntity.DEFAULT-POINTER and myEntity.E-VERDICT, where myEntity refers to an entity state. NOTE: In the following, we assume that we can use the "dot" notation by using references and unique identifiers. For example, in myEntity.STATUS, myEntityState may be pointer to an entity state or be the value of the <identifier> field.
The CONTROL-STACK, DEFAULT-LIST and VALUE-STACK of an entity state myEntity can be addressed by using the "dot" notation myEntity.CONTROL-STACK, myEntity.DEFAULT-LIST and myEntity.VALUE-STACK. CONTROL-STACK and VALUE-STACK can be accessed and manipulated by using the stack operations push, pop, top, clear and clear-until. The stack operations have the following meaning: myStack.push(item) pushes item onto myStack; myStack.pop() pops the top item from myStack; myStack.top() returns the top element of myStack or NULL if myStack is empty; myStack.clear() clears myStack, i.e. pops all items from myStack; myStack.clear-until(item) pops items from myStack until item is found or myStack is empty.
ETSI
42
DEFAULT-LIST can be accessed and manipulated by using the list operations add, append, delete, member, first, length, next, random and change. The meaning of these list operations is defined in clause 8.3.1a.1. For the creation of a new entity state the function NEW-ENTITY is assumed to be available: NEW-ENTITY (flow-graph-node-reference, keep-alive);
creates a new entity state and returns its reference. The components of the new entity state have the following values: STATUS is set to ACTIVE; flow-graph-node-reference is the only (top) element in CONTROL-STACK; DEFAULT-LIST is an empty list; DEFAULT-POINTER has the value NULL; VALUE-STACK is an empty stack; E-VERDICT is set to none; TIMER-GUARD is a new timer binding (see clause 8.3.2.4) with name GUARD, status IDLE and no default duration; DATA-STATE is an empty list; TIMER-STATE is an empty list; PORT-REF is an empty list; SNAP-ALIVE is an empty list; SNAP-DONE is an empty list; SNAP-KILLED is an empty list; KEEP-ALIVE is set to the value of the keep-alive parameter.
During the traversal of a flow graph the CONTROL-STACK changes its value often in the same manner: the top element is popped from and the successor node of the popped node is pushed onto CONTROL-STACK. This series of stack operations is encapsulated in the NEXT-CONTROL function:
myEntity.NEXT-CONTROL(myBool) { successorNode := myEntity.CONTROL-STACK.NEXT(myBool).top(); myEntity.CONTROL-STACK.pop(); myEntity.CONTROL-STACK.push(successorNode); }
ETSI
43
8.3.2.2
As shown in figure 25, the data state DATA-STATE of an entity state is a list of lists of variable bindings. Each list of variable bindings defines the variable bindings in a certain scope unit. Adding a new list of variable bindings corresponds to entering a new scope unit, e.g. a function is called. Deleting a list of variable bindings corresponds to leaving a scope unit, e.g. a function executes a return statement.
root
VariableBinding1
VariableBinding1
VariableBindingn
VariableBindingx
Figure 25: Structure of the DATA-STATE part of an entity state The structure of a variable binding is shown in figure 26. A variable has a name, a <location> and a VALUE. VAR NAME identifies a variable in a scope unit. The <location> is a unique identifier of the storage location of the value of the variable. The VALUE part of a variable binding describes the actual value of a variable. NOTE: Unique location identifiers should be provided automatically when a variable is declared. VAR-NAME <location> VALUE
Figure 26: Structure of a variable binding The distinction between variable name and location has been made to model function calls and the execution of test cases with value and reference parameterization in an appropriate manner: a) A parameter passed in by value is handled like the declaration of a new variable, i.e. a new variable binding is appended to the list of variable bindings of the scope of the called function or executed test case. The new variable binding uses the formal parameter name as VAR-NAME, receives a new location and gets the value that is passed into the function or test case. A parameter passed in by reference also leads to a new variable binding in the scope of the called function or executed test case. The new variable binding also uses the formal parameter name as VAR-NAME, but receives no new location and no new value. The new variable binding gets a copy of <location> and VALUE of the variable that is passed in by reference.
b)
When updating a variable value, e.g. in case of an assignment to a variable, the variable name is used to identify a location and all variable bindings with the same location are updated at the same time. Thus, when leaving the scope unit, the list of variables belonging to this scope unit can be deleted without further update. Due to the update procedure, variables passed in by reference automatically have the correct value.
8.3.2.3
The value of a variable can be retrieved by using the "dot" notation myEntity.myVar.VALUE, where myEntity refers to an entity state and myVar is the name of a variable. For the handling of variables and variable scope the following functions are considered to be defined: a) The VAR-SET function: myEntity.VAR-SET (myVar, myValue)
sets the VALUE part of variable myVar in the actual scope of an entity myEntity to myVal. In addition, the VALUE part of all variables with the same location as variable myVar will also be set to myVal.
ETSI
44
b)
creates a new variable binding for a variable myVar with the initial value myVal in the actual scope unit of an entity myEntity. Using the keyword NONE as myVal means that a variable with undefined initial value is created. A new and unique <location> value is automatically created. c) The GET-VAR-LOC function: myEntity.GET-VAR-LOC (myVar)
retrieves the location of variable myVar owned by myEntity. d) The INIT-VAR-LOC function: myEntity.INIT-VAR-LOC (myVar,myLoc)
creates a new variable binding for a variable myVar with the location myLoc in the actual scope unit of myEntity. The variable will be initialized with the value of another variable with the location myLoc. NOTE: Variables with the same location are a result of parameterization by reference. Due to the handling of reference parameters as described in clause 8.3.2.2 all variables with the same location will have identical values during their lifetime. myEntity.INIT-VAR-SCOPE ()
e)
initializes a new variable scope in the data state of entity myEntity, i.e. an empty list is added as first list in the list of lists of variable bindings. f) The DEL-VAR-SCOPE function: myEntity.DEL-VAR-SCOPE ()
deletes a variable scope of the data state of myEntity, i.e. the first list in the list of lists of variable bindings is deleted.
8.3.2.4
As shown in figures 27 and 25 the timer state TIMER-STATE and the data state DATA-STATE of an entity state are comparable. Both are a list of lists of bindings and each list of bindings defines the valid bindings in a certain scope. Adding a new list corresponds to entering a new scope unit and deleting a list of bindings corresponds to leaving a scope unit.
root
TimerBinding1
TimerBinding1
TimerBindingn
TimerBindingx
Figure 27: Structure of the TIMER-STATE part of an entity state The structure of a timer binding is shown in figure 28. The meaning of TIMER-NAME and <location> is similar to the meaning of VAR-NAME and <location> for a variable binding (figure 26).
TIMER-NAME STATUS DEF-DURATION ACT-DURATION TIME-LEFT SNAP-VALUE SNAP-STATUS
<location>
ETSI
45
STATUS denotes whether a timer is active, inactive or has timed out. The corresponding STATUS values are IDLE, RUNNING and TIMEOUT. DEF-DURATION describes the default duration of a timer. ACT-DURATION stores the actual duration with which a running timer has been started. TIME-LEFT describes the actual duration that a running timer has to run before it times out. NOTE: DEF-DURATION is undefined if a timer is declared without default duration. ACT-DURATION and TIME-LEFT are set to 0.0 if a timer is stopped or times out. If a timer is started without duration, the value of DEF-DURATION is copied into ACT-DURATION. A dynamic error occurs if a timer is started without a defined duration.
SNAP-VALUE and SNAP-STATUS are needed to support the snapshot semantics of TTCN-3. When taking a snapshot, SNAP-VALUE gets the actual value of ACT-DURATION TIME-LEFT. And SNAP-STATUS gets the same value as STATUS. The evaluation of a snapshot will only be based on the values in SNAP-VALUE and SNAP-STATUS. Timer can be only passed by reference into functions, i.e. the mechanism is similar to the mechanism for variables described in clause 8.3.2.2. This means a new timer binding (with the formal parameter name) is created which gets copies of <location>, STATUS, DEF-DURATION, ACT-DURATION, TIME-LEFT, SNAP-VALUE and SNAP-STATUS from the timer that is passed in by reference. When updating a timer all timer bindings with the same <location> value are updated at the same time.
8.3.2.5
The values of STATUS, DEF-DURATION, ACT-DURATION, TIME-LEFT, SNAP-VALUE and SNAP-STATUS of a timer myTimer can be retrieved by using the dot notation: myEntity.myTimer.STATUS; myEntity.myTimer.DEF-DURATION; myEntity.myTimer.ACT-DURATION; myEntity.myTimer.TIME-LEFT; myEntity.myTimer.SNAP-VALUE; myEntity.myTimer.SNAP-STATUS.
The myEntity in the dot notation refers to an entity state representing the state of a test component or module control that owns the timer myTimer. For changing the values of STATUS, DEF-DURATION, ACT-DURATION, TIME-LEFT, SNAP-VALUE and SNAP-STATUS of a timer timer-name, the generic TIMER-SET operation has to be used, for example: myEntity.TIMER-SET(myTimer, STATUS, myVal)
sets the STATUS value of timer myTimer in the actual scope of myEntity to the value myVal. In addition, the STATUS of all timers with the same location as timer myTimer will also be set to myVal. The TIMER-SET function can also be used to change the values of DEF-DURATION, ACT-DURATION, TIME-LEFT, SNAP-VALUE and SNAP-STATUS. For the handling of timers, timer scope and snapshot the following functions have to be defined: a) The INIT-TIMER function: myEntity.INIT-TIMER (myTimer, myDuration)
creates a new timer binding for a timer myTimer with the default duration myDuration in the actual scope of an entity myEntity. Using the keyword NONE as myDuration means that a timer without default duration is created. b) The GET-TIMER-LOC function: myEntity.GET-TIMER-LOC (myTimer)
ETSI
46
c)
creates a new timer binding for a timer myTimer with the location myLocation in the actual scope unit of myEntity. The timer will be initialized with the values of STATUS, DEF-DURATION, ACT-DURATION and TIME-LEFT of another timer with the location <location>. NOTE: Timers with the same location are a result of parameterization by reference. Due to the handling of timer reference parameters as described in clause 8.3.2.3 all timers with the same location will have identical values for STATUS, DEF-DURATION, ACT-DURATION and TIME-LEFT during their lifetime. myEntity.INIT-TIMER-SCOPE ()
d)
initializes a new timer scope in the timer state of entity myEntity, i.e. an empty list is added as first list in the list of lists of timer bindings. e) The DEL-TIMER-SCOPE function: myEntity.DEL-TIMER-SCOPE ()
deletes a timer scope of the timer state of entity myEntity, i.e. the first list in the list of lists of timer bindings is deleted. f) The SNAP-TIMER function: myEntity.SNAP-TIMER ()
makes an update of SNAP-VALUE and SNAP-STATUS, in all timers owned by myEntity , i.e.:
myEntity.SNAP-TIMERS () { for all myTimer in TIMER-STATE { myEntity.myTimer.SNAP-VALUE := myEntity.myTimer.ACT-DURATION myEntity.myTimer.TIME-LEFT; myEntity.myTimer.SNAP-STATUS := myEntity.myTimer.STATUS; }
8.3.2.6
As shown in figures 28a, 27 and 25 the port references PORT-REF, the timer state TIMER-STATE and the data state DATA-STATE of an entity state are comparable. All three are a list of lists of bindings and each list of bindings defines the valid bindings in a certain scope. Adding a new list corresponds to entering a new scope unit and deleting a list of bindings corresponds to leaving a scope unit.
root
PortBinding1
PortBinding1
PortBindingn
PortBindingx
Figure 28a: Structure of the PORT-REF part of an entity state The structure of a port binding is shown in figure 28b. A port has two names. PORT-NAME identifies a port in a scope unit. COMP-PORT-NAME is the port name given in the component type to a port.
PORT-NAME COMP-PORT-NAME
Figure 28b: Structure of a port binding NOTE: PORT-NAME and COMP-PORT-NAME are equal directly after the creation of a component.
ETSI
47
Ports can be only passed by reference into functions and altsteps, i.e. the mechanism is similar to the mechanism for variables described in clause 8.3.2.2. This means a new port binding (with the formal parameter name) is created which gets a copy of COMP-PORT-NAME from the port that is passed in by reference. When accessing a port which is passed in by reference, the corresponding port binding is used to retrieve the port name declared in the component type definition.
8.3.2.7
The value of COMP-PORT-NAME can be retrieved by using the dot notation: myEntity.myport.COMP-PORT-NAME
The myEntity in the dot notation refers to an entity state representing the state of a test component that owns the port myPort. For the handling of port parameters and port scopes the following functions have to be defined: a) The INIT-PORT function: myEntity.INIT-PORT (myPort, myCompPortName)
creates a new port binding for a port myPort with myCompPortName as value for COMP-PORT-NAME in the actual scope of an entity myEntity. b) The INIT-PORT-SCOPE function: myEntity.INIT-PORT-SCOPE ()
initializes a new port scope in the port references of entity myEntity, i.e. an empty list is added as first list in the list of lists of port bindings. c) The DEL-PORT-SCOPE function: myEntity.DEL-PORT-SCOPE ()
deletes a port scope of the port references of entity myEntity, i.e. the first list in the list of lists of port bindings is deleted.
8.3.3
Port states
Port states are used to describe the actual states of ports. Within a module state, the port states are handled in the ALL-PORT-STATES list (see figure 23). The structure of a port state is shown in figure 29. The COMP-PORT-NAME refers to the port name that is used to declare the port in the component type definition of the test component OWNER that owns the port. STATUS provides the actual status of the port. A port may either be STARTED, HALTED or STOPPED. NOTE: A port in a test system is uniquely identified by the owning test component and by the port name used in the component type definition to declare the port.
The CONNECTIONS-LIST of a port state keeps track of the connections between the different ports in the test system. The mechanism is explained in clause 8.3.3.1. The VALUE-QUEUE in a port state stores the messages, calls, replies and exceptions that are received at this port but have not yet been consumed. The SNAP-VALUE supports the TTCN-3 snapshot mechanism. When a snapshot is taken, the first element in VALUE-QUEUE is copied into SNAP-VALUE. SNAP-VALUE will get the value NULL if VALUE-QUEUE is empty or STATUS is STOPPED.
COMP-PORT-NAME
OWNER
STATUS
CONNECTIONS-LIST
VALUE-QUEUE
SNAP-VALUE
ETSI
48
8.3.3.1
A connection between two test components is made by connecting two of their ports by means of a connect operation. Thus, a component can afterwards use its local port name to address the remote queue. As shown in figure 30, connection is represented in the states of both connected queues by a pair of REMOTE-ENTITY and REMOTE-PORT-NAME. The REMOTE-ENTITY is the unique identifier of the test component that owns the remote port. The REMOTE-PORT-NAME refers to the port name that is used to declare the port in the component type definition of the test component REMOTE-ENTITY. TTCN-3 supports one-to-many connections of ports and therefore all connections of a port are organized in a list. NOTE 1: Connections made by map operations are also handled in the list of connections. The map operation: map(PTC1:MyPort, system.PCO1) leads to a new connection (system, PCO1) in the port state of MyPort owned by PTC1. The remote side to which PCO1 is connected to, resides inside the SUT. Its behaviour is outside the scope of this semantics. NOTE 2: The operational semantics handles the keyword system as a symbolic address. A connection (system, myPort) in the list of connections of a port it indicates that the port is mapped onto the port myPort in the test system interface.
REMOTE-ENTITY REMOTE-PORT-NAME
8.3.3.2
The queue of values in a port state can be accessed and manipulated by using the known queue operations enqueue, dequeue, first and clear. Using a GET-PORT or a GET-REMOTE-PORT function references the queue that shall be accessed. NOTE 1: The queue operations enqueue, dequeue, first and clear have the following meaning: myQueue.enqueue(item) puts item as last item into myQueue; myQueue.dequeue() deletes the first item from myQueue; myQueue.first() returns the first item in myQueue or NULL if myQueue is empty; myQueue.clear() removes all elements from myQueue. The handling of port states is supported by the following functions: a) The NEW-PORT function: NEW-PORT (myEntity, myPort)
creates a new port and returns its reference. The OWNER entry of the new port is set to myEntity and COMP-PORT-NAME has the value myPort. The status of the new port is STARTED. The CONNECTIONS-LIST and the VALUE-QUEUE are empty. The SNAP-VALUE has the value NULL (i.e. the input queue of the new port is empty). b) The GET-PORT function: GET-PORT (myEntity, myPort)
returns a reference to the port identified by OWNER myEntity and COMP-PORT-NAME myPort. c) The GET-REMOTE-PORT function: GET-REMOTE-PORT (myEntity, myPort, myRemoteEntity)
returns the reference to the port that is owned by test component myRemoteEntity and connected to a port identified by OWNER myEntity and COMP-PORT-NAME myPort. The symbolic address SYSTEM is returned, if the remote port is mapped onto a port in the test system interface. NOTE 2: GET-REMOTE-PORT returns NULL if there is no remote port or if the remote port cannot be identified uniquely. The special value NONE can be used as value for the myRemoteEntity parameter if the remote entity is not known or not required, i.e. there exists only a one-to-one connection for this port.
ETSI
49
d)
The STATUS of a port is handled like a variable. It can be addressed by qualifying STATUS with a GET-PORT call: GET-PORT(myEntity, myPort).STATUS.
e)
adds a connection (myRemoteEntity, myRemotePort) to the list of connections of the port identified by OWNER myEntity and COMP-PORT-NAME myPort. f) The DEL-CON function: DEL-CON (myEntity, myPort, myRemoteEntity, myRemotePort)
removes a connection (myRemoteEntity, myRemotePort) from the list of connections of the port identified by OWNER myEntity and COMP-PORT-NAME myPort. g) The SNAP-PORTS function: SNAP-PORTS (myEntity)
NOTE 3: The SNAP-PORTS function handles the HALT-MARKER that may be put by a halt port operation into the port queue. If such a marker is found, the marker is removed, the SNAP-VALUE of the port is set to NULL and the status of the port is changed to STOPPED.
8.3.4
The operational semantics assumes the existence of the following functions for the handling of module states. NOTE 1: During the interpretation of a TTCN-3 module, there only exists one module state. It is assumed that the components of the module state are stored in global variables and not in a complex data object. Thus, the following functions are assumed to work on global variables and do not address a specific module state object. a) The DEL-ENTITY function: DEL-ENTITY(myEntity) deletes an entity with the unique identifier myEntity. The deletion comprises: b) the deletion of the entity state of myEntity; deletion of all ports owned by myEntity; deletion of all connections in which myEntity is involved.
The UPDATE-REMOTE-REFERENCES function: UPDATE-REMOTE-REFERENCES (source, target) the UPDATE-REMOTE-REFERENCES updates variables and timers with the same location in both entities. The values that will be used for the update are the values of variables and timers owned by source.
ETSI
50
NOTE 2: The UPDATE-REMOTE-REFERENCES is used during the termination of test cases. It allows updating of variables of module control, which are passed as reference parameters to test cases.
8.4
The exchange of information among test components and between test components and the SUT is related to messages, procedure calls, replies to procedure calls and exceptions. For communication purposes these items have to be constructed, encoded and decoded. The concrete encoding, i.e. mapping of TTCN-3 data types to bits and bytes, and decoding, i.e. mapping of bits and bytes to TTCN-3 data types, is outside the scope of the operational semantics. In the present document messages, procedure calls, replies to procedure calls and exceptions are handled on a conceptual level.
8.4.1
Messages
Messages are related to message-based communication. Values of all (pre- and user-defined) data types can be exchanged among the entities that communicate. As shown in figure 31, the operational semantics handles a message as structured object that consist of a sender a type and a value part. The sender part identifies the sender entity of a message, the type part specifies the type of a message and the value part defines the message value.
sender type value
Figure 31: Structure of a message NOTE: The operational semantics only presents a model for the concepts of TTCN-3. Whether and how the sender information is or has to be sent and/or received depends on the implementation of the test system, e.g. in some cases the sender information may be part of the value part of a message and therefore is no separate part of the message structure.
8.4.2
Procedure calls and replies to procedures are related to procedure-based communication. They are defined like values of a record with components representing the parameters. The operational semantics also handles procedure calls and replies to procedure calls like values in structured types. The structure of a procedure call and the structure of a reply are presented in figures 32 and 33. The sender and the procedure-reference parts have the same meaning in both figures. The sender part refers to the sender entity of a call or the reply to a procedure call. The procedure-reference refers to the procedure to which call and reply belong. The parameter-part of the procedure call in figure 32 refers to the in parameters and inout parameters and the parameter- part of the reply in figure 33 refers to the inout parameters and out parameters of the procedure to which call and reply belong. In addition, the reply has a value part for the return values in the reply to a procedure. NOTE 1: As stated in the previous note, the operational semantics only presents a model for the concepts of TTCN-3. Whether and how the information described in figures 32 and 33 is or has to be sent and/or received depends on the implementation of the test system. NOTE 2: For a procedure call, out parameters are of no relevance and are omitted in figure 32. For a reply to a procedure call, in parameters are of no relevance and are omitted in figure 33. NOTE 3: The types of parameters and the type of the return value can always be derived unanimously from the related signature definition.
sender procedure-reference parameter-part in-or-inout-parameter1 in-or-inout-parametern
ETSI
51
sender
procedure-reference
value
8.4.3
Exceptions
Exceptions are also related to procedure-based communication. The structure of an exception is shown in figure 34. It consists of four parts. The sender part identifies the sender of the exception; the procedure-reference part refers to the procedure to which the exception belongs, the type part identifies the type of the exception and the value part provides the value of the exception. The procedure signature referred to in the procedure reference part defines the list of allowed types of exceptions. A received exception shall comply with one of the listed types. In general it can be of any pre- or user-defined TTCN-3 data type.
sender procedure-reference type value
8.4.4
The operations for sending a message, a procedure call, a reply to a procedure call or an exception are send, call, reply and raise. All these sending operations are built up in the same manner:
<port-name>.<sending-operation>(<send-specification>) [to <receiver>]
The <port-name> and <sending-operation> define port and operation used for sending an item. In case of one-to-many connections a <receiver> entity needs to be specified. The item to be sent is constructed by using the <send-specification>. The send specification may use concrete values, template references, variable values, constants, expressions, functions, etc. to construct and encode the item to be sent. The operational semantics assumes that there exists a generic CONSTRUCT-ITEM function: CONSTRUCT-ITEM (myEntity, <sending-operation>, <send-specification>) returns a message, a procedure call, a reply to a procedure call or an exception depending on the <sending-operation> and the <send-specification> (both, <sending-operation> and the <send-specification> refer to the corresponding parts in the TTCN-3 sending operation). The entity reference myEntity is the sender of the item to be sent. This sender information is also assumed to be part of the item to be sent (figures 31 to 34).
8.4.5
The operations for receiving a message, a procedure call, a reply to a procedure call or an exception are receive, getcall, getreply and catch. All these receiving operations are built up in the same manner:
<port-name>.<receiving-operation>(<matching-part>) [from <sender>] [<assignment-part>]
The <port-name> and <receiving-operation> define port and operation used for the reception of an item. In case of one-to-many connections a from-clause can be used to select a specific sender entity <sender>. The item to be received has to fulfil the conditions specified in the <matching-part>, i.e. it has to match. The <matchingpart> may use concrete values, template references, variable values, constants, expressions, functions, etc. to specify the matching conditions.
ETSI
52
The operational semantics assumes that there exists a generic MATCH-ITEM function: MATCH-ITEM (myItem, <matching-part>, <sender>) returns true if myItem fulfils the conditions of <matching-part> and if myItem has been sent by <sender>, otherwise it returns false.
8.4.6
Information from received messages, procedure calls, replies to procedure calls and exceptions can be retrieved in the <assignment-part> (see clause 8.4.5) of the receiving functions receive, getcall, getreply and catch. The <assignment-part> describes how the parameters of procedure calls and replies, return values encoded in replies, messages, exceptions and the identifier of the <sender> entity are assigned to variables. The operational semantics assumes that there exists a generic RETRIEVE-INFO function: RETRIEVE-INFO (myItem, <assignment-part>) all values to be retrieved according to the <assignment-part> are retrieved and assigned to the variables listed in the assignment part. Assignments are done by means of the VAR-SET operation, i.e. variables with the same location are updated at the same time.
8.5
Functions, altsteps and test cases are called (or executed) by their name and a list of actual parameters. The actual parameters provide references for reference parameter and concrete values for the value parameter as defined by the formal parameters in the corresponding function, altstep or test case definition. The operational semantics handles calls of functions, altsteps and test cases by using call records as shown in figure 35. The value of BEHAVIOUR-ID is the name of a function or test case, value parameters provide concrete values <parId1> <parIdn> for the formal parameters <parId1> <parIdn>. Variable and timer reference parameters provide references to locations of existing variables and timers. Port reference parameters provide the port names declared in the component type definition of the test component that calls the function or altstep. Before a function or test case can be executed an appropriate call record has to be constructed. NOTE: Port reference parameters can only appear in functions and altsteps which are executed on a test component.
behaviour-id value-parameters variable and timer reference-parameters parIdn parIdr locn locr port reference-parameters parIds parIdz names namez
8.5.1
The function, altstep or test case name and the actual parameter values can be retrieved by using the dot notation, e.g. myCallRecord.parIdn or myCallRecord.behaviour-id where myCallRecord is a pointer to a call record. For the construction of a call the function NEW-CALL-RECORD is assumed to be available: NEW-CALL-RECORD(myBehaviour) creates a new call record for function, altstep or test case myBehaviour and returns a pointer to the new record. The parameter fields of the new call record have undefined values.
ETSI
53
myEntity.INIT-CALL-RECORD(myCallRecord) creates variables, timers and port references for the handling of value and reference parameters in the actual scope of the test component or module control myEntity. The variables for the handling of value parameters are initialized with the corresponding values provided in the call record. The variables and timers for the handling of reference parameters get the provided location. In addition, they get a value of an existing variable or timer in another scope unit of the component in which the call record was created. Port references get the provided name as value for the COMP-PORT-NAME field.
8.6
8.6.1
(1) (2) (3) (4)
The phases (2), (3) and (4) are repeated until module control terminates. The evaluation procedure is described by means of a mixture of informal text, pseudo-code and the functions introduced in the previous clauses.
8.6.1.1
Phase I: Initialization
The initialization phase includes the following actions: a) Declaration and initialization of variables: INIT-FLOW-GRAPHS(); Entity := NULL; MTC := NULL; // Initialization of flow graph handling. INIT-FLOW-GRAPHS is // explained in clause 8.6.2. // Entity will be used to refer to an entity state. An entity state either // represents module control or a test component. // MTC will be used to refer to the entity state of the main test component of // a test case during test case execution.
NOTE 1: The global variable CONTROL form the control state of a module state during the interpretation of a TTCN-3 module (see clause 8.3.1). CONTROL := NULL; // CONTROL will be used to refer to the control state of a module state.
NOTE 2: The following global variables ALL-ENTITY-STATES, ALL-PORT-STATES, TC-VERDICT, DONE and KILLED form the test configuration state of a module state during the interpretation of a TTCN-3 module (see clause 8.3.1). ALL-ENTITY-STATES := NULL; ALL-PORT-STATES := NULL; TC-VERDICT := none; DONE := NULL; KILLED := NULL;
ETSI
54
b)
Creation and initialization of module control: CONTROL := NEW-ENTITY (GET-FLOW-GRAPH (<moduleId>), false); // A new entity state is created and initialized with the start node of // the flow graph representing the behaviour of the control of the // module with the name <moduleId>. The Boolean parameter // indicates that module control cannot be restarted after it is // stopped. CONTROL.INIT-VAR-SCOPE(); CONTROL.INIT-TIMER-SCOPE(); // New variable scope // New timer scope
8.6.1.2
The update phase is related to all actions that are outside the scope of the operational semantics but influence the interpretation of a TTCN-3 module. The update phase comprises the following actions: a) Time progress: All running timers are updated, i.e. the TIME-LEFT values of running timers are (possibly) decreased, and if due to the update a timer expires, the corresponding timer bindings are updated, i.e. TIME-LEFT is set to 0.0 and STATUS is set to TIMEOUT.
NOTE 1: The update of timers includes the update of all running TIMER-GUARD timers in module states. TIMER-GUARD timers are used to guard the execution of test cases and call operations. b) Behaviour of the SUT: Messages, remote procedure calls, replies to remote procedure calls and exceptions (possibly) received from the SUT are put into the port queues at which the corresponding receptions shall take place.
NOTE 2: This operational semantics makes no assumptions about time progress and the behaviour of the SUT.
8.6.1.3
The selection phase consists of the following two actions: a) b) Selection: Select a non-blocked entity, i.e. an entity that has not the STATUS value BLOCKED. The entity may be CONTROL, i.e. module control, or an element in , i.e. ALL-ENTITY-STATES, a test component. Storage: Store the identifier of the selected entity in the global variable Entity.
8.6.1.4
The execution phase consists of the following two actions: a) b) Execution step of the selected entity: Execute the top flow graph node in the CONTROL-STACK of Entity. Check termination criterion: Stop execution if module control has terminated, i.e. CONTROL is NULL. Otherwise continue with Phase II. The execution step of the selected entity can be seen as a procedure call. The check of the termination criterion is done when the execution step terminates, i.e. returns the control.
NOTE:
8.6.2
a)
Global functions
INIT-FLOW-GRAPHS is assumed to be the function that initializes the flow graph handling. The handling may include the creation of the flow graphs and the handling of the pointers to the flow graphs and flow graph nodes.
ETSI
55
The pseudo-code used the following clauses to describe execution of flow graph nodes use the functions CONTINUE-COMPONENT, RETURN, ***DYNAMIC-ERROR***: b) c) d) CONTINUE-COMPONENT the actual test component continues its execution with the node lying on top of the control stack, i.e. the control is not given back to the module evaluation procedure described in this clause. RETURN returns the control back to the module evaluation procedure described in this clause. The RETURN is the last action of the "execution step of the selected entity" of the execution phase. ***DYNAMIC-ERROR*** refers to the occurrence of a dynamic error. The error handling procedure itself is outside the scope of the operational semantics. If a dynamic error occurs all following behaviour of the test case is meant to be undefined. In this case resources allocated to the test case shall be cleared and the error verdict is assigned to the test case. Control is given to the statement in the control part following the execute statement in which the error occurred. This is modelled by the flow graph segment <dynamic-error> (clause 9.18.5). The occurrence of a dynamic error is related to test behaviour. A dynamic error as specified by the operational semantics denotes a problem in the usage of TTCN-3, e.g. wrong usage or race condition.
NOTE: e)
APPLY-OPERATOR used as generic function for describing the evaluation of operators (e.g. +, *, / or -) in expressions (see clause 9.18.4).
The operational semantics represents TTCN-3 behaviour in form of flow graphs. The construction algorithm for the flow graphs representing behaviour is described in clause 8.2. It is based on templates for flow graphs and flow graph segments that have to be used for the construction of concrete flow graphs for module control, test cases, altsteps, functions and component type definitions defined in a TTCN-3 module. The definitions of the templates for the flow graph segments can be found in this clause. They are presented in an alphabetical order and not in a logical order. The flow graph segment definitions are provided in the form of figures. The flow graph nodes are presented on the left side of the figures and comments associated to nodes and flow lines are shown on the right side. Descriptive comments are presented for reference nodes and comments in form of pseudo-code are associated to basic nodes. The pseudo-code describes how a basic node is interpreted, i.e. changes the module state. It makes use of the functions defined in clause 8 and the global variables declared and initialized in the evaluation procedure for TTCN-3 modules (see clause 8.6). An overall view of all functions and keywords used by the pseudo-code can be found in clause 8.
9.1
Action statement
The flow graph segment <action-stmt> in figure 36 defines the execution of the action statement.
nop
NOTE:
The <informal description> parameter of the action statement has no meaning for the operational semantics and is therefore not represented in the flow graph segment.
ETSI
56
9.2
Activate statement
The <altstep-name> denotes to the name of an altstep that is activated as default behaviour, and <act-par-descr1>, , <act-par-descrn> describe the actual parameter values of the altstep at the time of its activation. It is assumed that for each <act-par-desc1> the corresponding formal parameter identifier <f-par-Id1> is known, i.e. we can extend the syntactical structure above to:
activate(<altstep-name>((<f-par-Id1>,<act-par-desc1>), , (<f-par-Idn>,<act-par-descn>)))
The flow graph segment <activate-stmt> in figure 37 defines the execution of the activate statement. The execution is structured into three steps. In the first step, a call record for the altstep <function-name> is created. In the second step the values of the actual parameter are calculated and assigned to the corresponding field in the call record. In the third step, the call record is put as first element in the DEFAULT-LIST of the entity that activates the default. NOTE: For altsteps that are activated as default behaviour, only value parameters are allowed. In figure 37, the handling of the value parameters is described by the flow graph segment <value-par-calculation>, which is defined in clause 9.24.1.
segment <activate-stmt>
construct-call-record (altstep-name)
*
<value-par-calculation>
// // // // //
For each pair (<f-par-Idi>, <act-parameter-desci>) the value of <act-parameter-desci is calculated and assigned to the corresponding field <f-par-Idi> in the call record. The call record is assumed to be the top element in the value stack.
activate-default
Entity.DEFAULT-LIST.add(Entity.VALUE-STACK.top()); // We assume that only a reference to the call record has // been pushed onto the value stack. This reference has // not been removed from the value stack. It is the result // of the activate statement. Entity.NEXT-CONTROL(true); RETURN;
9.2a
ETSI
57
The alive component operation checks whether a component has been created and is ready to execute or is already executing a behaviour function. The component to be checked is identified by a component reference, which may be provided in form of a variable or value returning function, i.e. is an expression. For simplicity, the keywords "all component" and "any component" are considered to be special expressions. The alive component operation distinguishes between its usage in a Boolean guard of an alt statement or blocking call operation and all other cases. If used in a Boolean guard, the result of alive component operation is based on the actual snapshot. In all other cases the alive component operation evaluates directly the module state information. The result of the alive component operation is pushed onto the value stack of the entity, which called the operation. The flow graph segment <alive-component-op> in figure 37a defines the execution of the running component operation.
segment <alive-component-op> <expression> // The expression shall evaluate // to a component reference. The // result is pushed onto VALUE-STACK
decision
true
<alive-comp-act>
<alive-comp-snap>
ETSI
58
9.2a.1
The flow graph segment <alive-comp-act> in figure 37b describes the execution of the alive component operation outside a snapshot, i.e. the entity is in the status ACTIVE.
segment <alive-comp-act>
alive-comp-act
if (Entity.VALUE-STACK.top() == 'all component') { if (Entity != MTC) { ***DYNAMIC-ERROR*** // 'all component' is not allowed } else { if (KILLED.length() == 0) { // no entity has terminated Entity.VALUE-STACK.push(true); } else { // at least one component has terminated Entity.VALUE-STACK.push(false); } } } else { if (Entity.VALUE-STACK.top() == 'any component') { if (Entity != MTC) { ***DYNAMIC-ERROR*** // 'any component' is not allowed } else { if (ALL-ENTITY-STATES.length() > 1) { // at least one PTC is alive Entity.VALUE-STACK.push(true); } else { Entity.VALUE-STACK.push(false); } } } else { if (ALL-ENTITY-STATES.member(Entity.VALUE-STACK.top())) { // Specified component is alive Entity.VALUE-STACK.push(true); } else { Entity.VALUE-STACK.push(false); } } } Entity.NEXT-CONTROL(true); RETURN;
ETSI
59
9.2a.2
The flow graph segment <alive-comp-snap> in figure 37c describes the execution of the alive component operation during the evaluation of a snapshot, i.e. the entity is in the status SNAPSHOT.
segment <alive-comp-snap>
alive-comp-snap
if (Entity.VALUE-STACK.top() == 'all component') { if (Entity != MTC) { ***DYNAMIC-ERROR*** // 'all component' is not allowed } else { if (Entity.SNAP-KILLED.length() == 0) { Entity.VALUE-STACK.push(true); } else { Entity.VALUE-STACK.push(false); } } } else { if (Entity.VALUE-STACK.top() == 'any component') { if (Entity != MTC ) { ***DYNAMIC-ERROR*** // 'any component' is not allowed } else { if (Entity.SNAP-ALIVE.length() > 1) { // at least one PTC was alive when the // snapshot has been taken Entity.VALUE-STACK.push(true); } else { Entity.VALUE-STACK.push(false); } } } else { if (Entity.SNAP-ALIVE.member(Entity.VALUE-STACK.top())) { // Component was alive when the snapshot was taken Entity.VALUE-STACK.push(true); } else { // Component was not alive when the snapshot was taken Entity.VALUE-STACK.push(true); } } } Entity.NEXT-CONTROL(true); RETURN;
9.3
Alt statement
The alt statement is the most complicated and important statement of TTCN-3. It implements the snapshot semantics and specifies the branching due to the reception of messages, replies, calls and exceptions, due to the occurrence of timeouts and due to the termination of components. In addition, the evocation of the TTCN-3 default mechanism is also related to the alt statement. The flow graph representation of the alt statement in figure 38. The different alternatives due to the reception of messages, replies, calls and exceptions, due to the occurrence of timeouts and due to the termination of components are hidden in the flow graph segment <receiving-branch>.
ETSI
60
segment <alt-stmt>
<take-snapshot>
// A snapshot is taken
// The default mechanism may // be evoked. <default-evocation> if ( Entity .STATUS == ACTIVE) { Entity .NEXT-CONTROL( true ); } else { if ( Entity .STATUS == BREAK ) { // altstep is left via a break statement. Entity .STATUS ( ACTIVE ); Entity .NEXT-CONTROL( true ); } else { // A new snapshot needs to be taken, the // status of the entity is SNAPSHOT (none // of the alternatives could be selected // and executed) or REPEAT (due to a // repeat statement) Entity .NEXT-CONTROL( false ); } } RETURN ;
ETSI
61
9.3.1
The flow graph segment <take-snapshot> in figure 39 describes the procedure of taking a snapshot. The snapshot records values of ports, timers and stopped components.
Entity.SNAP-ALIVE := copy(ALL-ENTITY-STATES); // ALIVE Entity.SNAP-DONE := copy(DONE); // DONE Entity.SNAP-KILLED := copy(KILLED); // KILLED take-snapshot Entity.STATUS := SNAPSHOT; // new component status Entity.DEFAULT-POINTER := Entity.DEFAULT-LIST.first(); Entity.NEXT-CONTROL(true); RETURN;
ETSI
62
9.3.2
The execution of the flow graph segment <receiving-branch> is shown in figure 40.
segment <receiving-branch> // The receiving branch is only evaluated, // if the entity is in status SNAPSHOT if (Entity.STATUS == SNAPSHOT) { Entity.NEXT-CONTROL(true); } else { Entity.NEXT-CONTROL(false); } RETURN;
<expression>
// The operations may change the status of // Entity, if the operation is successful.
<statement-block> true
ETSI
63
9.3.3
The invocation of an altstep within an alt statement is described by the flow graph segment <altstep-call-branch> in figure 41.
segment <altstep-call-branch>
// The branch is only evaluated, // if the entity is in status SNAPSHOT if ( Entity . STATUS == SNAPSHOT ) { Entity . NEXT-CONTROL ( true ); } else { Entity . NEXT-CONTROL ( false ); } RETURN ;
<expression>
<altstep-call>
// // // //
The altstep is called, the status of the entity may be changed inside the altstep by the different alternatives in the altstep.
decision
// // // if
true false
STATUS of Entity is ACTIVE if one of the alternatives in the altstep has been executed ( Entity . STATUS == ACTIVE ) { Entity . NEXT-CONTROL ( true );
*(1
<statement-block> // Execution of optional statement // block
ETSI
64
9.3.4
The execution of an else branch within an alt statement is described by the flow graph segment <else-branch> in figure 42.
segment <else-branch> // The branch is only evaluated, // if the entity is in status SNAPSHOT if (Entity.STATUS == SNAPSHOT) { Entity.NEXT-CONTROL(true); } else { Entity.NEXT-CONTROL(false); } RETURN;
else-part
// An else-branch is always selected, i.e., // status of Entity will be set of ACTIVE Entity.STATUS := ACTIVE;
<statement-block>
ETSI
65
9.3.5
The evocation of defaults behaviour at the end of alt statements is described by the flow graph segment <default-evocation> in figure 43.
segment <default-evocation>
default-in
// A default is only evoked, if the // entity is in status SNAPSHOT if (Entity.STATUS == SNAPSHOT) { Entity.NEXT-CONTROL(true); } else { Entity.NEXT-CONTROL(false); } RETURN;
// // // // // // //
A call record in DEFAULT-LIST, identified by DEFAULT-POINTER is pushed onto the VALUE-STACK of Entity. Afterwards DEFAULT-POINTER is updated, i.e., will point to the next record in DEFAULT-LIST. If DEFAULT-POINTER is NULL, the Entity status will not change and, thus, a new SNAPSHOT will be initiated in <alt-stmt>
if (Entity.DEFAULT-POINTER == NULL) { Entity.NEXT-CONTROL(false); } else { Entity.VALUE-STACK.push(Entity.DEFAULT-POINTER); Entity.DEFAULT-POINTER := Entity.DEFAULT-LIST.next(Entity.DEFAULT-POINTER); Entity.NEXT-CONTROL(true); } RETURN; // The actual default altstep is invoked // or called like a user defined function.
<user-def-func-call>
// Jump back to the beginning of the segment // to check if the next default behaviour has // to be invoked. default-in
ETSI
66
9.4
Altstep call
As shown in figure 44, the call of an altstep is handled like a function call.
segment <altstep-call>
<function-call>
9.5
Assignment statement
The value of the expression <expression> is assigned to variable <varId>. The execution of an assignment statement is defined by the flow graph segment <assignment-stmt> in figure 45.
segment <assignment-stmt>
<expression>
// The expression is evaluated and the // result is pushed onto the value stack
assignment-stmt (varId)
Entity.NEXT-CONTROL(true); RETURN;
9.5a
break
NOTE:
The semantics of a break statement used for leaving a loop, an interleave or an alt statement is defined in clause 7.8 as a shorthand form for using a pair of goto-label statements.
ETSI
67
Basically, the break statement used for leaving an altstep is a return statement without return value, which also changes the entity status to BREAK. The status BREAK prevents the re-evaluation of the alt statement in which the altstep has been called statement has been called and also prevents the execution of the optional statement block following the altstep call in the alt statement. The break statement also works for altsteps called indirectly by the default mechanism. In this case, the alt statement that invokes the default mechanism is left. The flow graph segment <break-altstep-stmt> shown in figure 45a defines the execution of the break statement for leaving an altstep.
break-altstep-stmt
<return-without-value>
9.6
Call operation
The optional <blocking-info> consists of either the keyword nowait or a duration for a timeout exception. The optional <receiver-spec> in the to clause refers to the receivers of the call. In case of a one-to one communication, the <receiver-spec> addresses a single entity (including the SUT or an entity within the SUT). In case of multicast or broadcast communication, the <receiver-spec> specifies a set or all test components connected via the specified port with the calling component. The optional <call-reception-part> denotes the alternative receptions in case of a blocking call operation. The operational semantics distinguishes between blocking and non-blocking call operations. A call is non-blocking if the keyword nowait is used in the call operation, or if the called procedure is non-blocking, i.e. defined by using the keyword noblock. A blocking call has a <call-reception-part>. The flow graph segment <call-op> in figure 46 defines the execution of a call operation. It reflects the distinction between blocking and non-blocking calls.
segment <call-op>
<blocking-call-op> OR <non-blocking-call-op>
Figure 46: Flow graph segment <call-op> For blocking and non-blocking call operations a receiver entity may be specified in form of an expression. The possibilities are shown in figures 47 and 48.
ETSI
68
segment <blocking-call-op>
<b-call-without-duration> OR <b-call-with-duration>
// A non-blocking call may address one, // multiple (multicast and broadcast) or // no receiver entities.
ETSI
69
9.6.1
The flow graph segment <nb-call-with-one-receiver> in figure 49 defines the execution of a non-blocking call operation where one receiver is specified in form of an expression.
segment <nb-call-with-one-receiver>
<expression>
let { var receiver := Entity.VALUE-STACK.top(); var remotePort := GET-REMOTE-PORT(Entity, Entity.portId.COMP-PORT-NAME, receiver); if (remotePort == NULL) { ***DYNAMIC-ERROR***; // Remote port cannot be found } if (remotePort == SYSTEM) { // Port is mapped onto a port of the test system // reception of the reply by the SUT is outside // the scope of the operational semantics } else { // sending of call remotePort.enqueue(CONSTRUCT-ITEM(Entity, call, callSpec)); } } // end of scope of receiver and remotePort Entity.VALUE-STACK.pop(); Entity.NEXT-CONTROL(true); RETURN; // clean value stack
9.6.1a
The flow graph segment <nb-call-with-multiple-receivers> in figure 49a defines the execution of a non-blocking call operation where multiple receivers are addressed. In case of broadcast communication the keyword all component is used as receiver specification. In case of multicast communication a list of expressions is provided which shall evaluate to component references or address values. The component references or address values of the addressed entities (or the keyword all component) are pushed onto the value stack of the calling entity. The number of references or address values stored in the value stack is considered to be known, i.e. it is the parameter number of the basic flow graph node nb-call-with-multiple-receivers in figure 49a. The number parameter is 1 in case of broadcast communication, i.e. the keyword all component is top element in the value stack.
ETSI
70
segment <nb-call-with-multiple-receivers>
+(number) <expression> // Each expression shall evaluate // to a component reference or // address value
// i; // loop counter variable connection; // variable for connections in port states receiver; // variable for receiver component references or // receiver address values var localPort, remotePort; // variables for port references localPort := Entity.portId.COMP-PORT-NAME; // local port
if (Entity.VALUE-STACK.top() == all component) { connection := localPort.CONNECTIONS-LIST.next(connection); while (connection != NULL) { remotePort := connection.REMOTE-PORT-NAME; if (remotePort == SYSTEM) { // Port is mapped onto a port of the test system // reception of the reply by the SUT is outside // the scope of the operational semantics } else { // sending of call remotePort.enqueue(CONSTRUCT-ITEM(Entity, call, callSpec)); } connection := localPort.CONNECTIONS-LIST.next(connection); } } else { for (i == 1; i <= number; i := i+1) { receiver := Entity.VALUE-STACK.top(); Entity.VALUE-STACK.pop(); // clean value stack remotePort := GET-REMOTE-PORT(Entity, localPort, receiver); if (remotePort == NULL) { ***DYNAMIC-ERROR***; // Remote port cannot be found } if (remotePort == SYSTEM) { // Port is mapped onto a port of the test system // reception of the reply by the SUT is outside // the scope of the operational semantics } else { // sending of call remotePort.enqueue(CONSTRUCT-ITEM(Entity, call, callSpec)); } } } } // end of local scope Entity.NEXT-CONTROL(true); RETURN;
ETSI
71
9.6.2
The flow graph segment <nb-call-without-receiver> in figure 50 defines the execution of a non-blocking call operation without a to-clause.
segment <nb-call-without-receiver-op>
let { var remotePort := GET-REMOTE-PORT(Entity, Entity.portId.COMP-PORT-NAME, NONE); if (remotePort == NULL) { ***DYNAMIC-ERROR***; // Remote port cannot be found } if (remotePort == SYSTEM) { // Port is mapped onto a port of the test system // reception of the reply by the SUT is outside // the scope of the operational semantics } else { // sending of call remotePort.enqueue(CONSTRUCT-ITEM(Entity, call, callSpec)); } } // end of scope of remotePort
Entity.NEXT-CONTROL(true); RETURN;
9.6.3
Blocking calls are modelled by a non-blocking call followed by the body of the call, which handles the replies and exceptions. The flow graph segment <b-call-without-duration> shown in figure 51 describes the execution of a blocking call without a given duration as time guard.
segment <b-call-without-duration>
<call-reception-part>
ETSI
72
9.6.4
The flow graph segment <b-call-with-duration> (see figure 52) describes the execution of a blocking call with a duration as time guard.
segment <b-call-with-duration> // // // // The expression shall evaluate to a float value which defines the duration of the guarding timer.
<expression>
set-timer-guard
<call-reception-part>
ETSI
73
9.6.5
The flow graph segment <call-reception-part> (see figure 53) describes the handling of replies, exceptions and the timeout exception of a blocking call operation.
segment <call-reception-part>
<take-snapshot>
// A snapshot is taken
+ <receiving-branch> OR <catch-timeout-exception>
// // // // //
Branches with getcall and catch operations related to the call and a timeout exception (if the call is guarded by a duration) are handled by this node
if ( Entity.STATUS == ACTIVE) { Entity.NEXT-CONTROL(true); // To assure a defined state of Entity Entity.TIMER-GUARD.STATUS := IDLE; } else { // A new snapshot needs to be taken, the // status of the entity is SNAPSHOT (none // of the alternatives could be selected // and executed) Entity.NEXT-CONTROL(false); } RETURN;
ETSI
74
9.6.6
The flow graph segment <catch-timeout-exception> (see figure 54) is for the handling of a timeout exception of a blocking call operation that is guarded by a duration.
segment <catch-timeout-exception>
if (Entity.TIMER-GUARD.STATUS == TIMEOUT) { Entity.NEXT-CONTROL(true); // To assure a defined state of Entity Entity.STATUS := ACTIVE; } else { // continue evaluation Entity.NEXT-CONTROL(false); } RETURN;
<statement-block>
9.7
Catch operation
Apart from the catch keyword this syntactical structure is identical to the syntactical structure of the receive operation. Therefore, the operational semantics handles the catch operation in the same manner as the receive operation. This is also shown in the flow graph segment <catch-op> (figure 55), which defines the execution of a catch operation. The figure refers to flow graph segments related to the receive operation (see clause 9.37).
segment <catch-op>
<receive-with-sender> OR <receive-without-sender>
ETSI
75
9.8
Check operation
The optional <component-expression> in the from clause refers to the sender entity. It may be provided in form of a variable value or the return value of a function, i.e. it is assumed to be an expression. The optional <assignmentPart> denotes the assignment of received information if the received information matches to the matching specification <matchingSpec> and to the (optional) from clause. The operational semantics handles the operations receive, getcall, catch and getreply in the same manner, i.e. they are described by referencing the same flow graph segments <receive-with-sender> and <receive-without-sender>. The check operation also handles the different operations in the same manner. Thus the flow graph segment <check-op> in figure 56, which defines the execution of the check operation, also references only two flow graph segments. The only difference to the flow graph segments <receive-with-sender> and <receive-without-sender> is that the received items are not deleted after the match.
segment <check-op>
<check-with-sender> OR <check-without-sender>
ETSI
76
9.8.1
The flow graph segment <check-with-sender> in figure 57 defines the execution of a check operation where the sender entity is specified in form of an expression.
// // // //
The Expression shall evaluate to a component reference or address value. The result is pushed onto the VALUE-STACK.
let { // local scope for portRef and sender var portRef := NULL; var sender := Entity.VALUE-STACK.top(); // Sender // Clean value stack Entity.VALUE-STACK.pop(); if (portID == any port) { portRef := ALL-PORT-STATES.random(MATCH-ITEM(SNAP-VALUE,matchingSpec,sender) && OWNER == Entity); if (portRef == NULL) { // no 'matching' port found Entity.NEXT-CONTROL(false); RETURN; } } else { portRef := GET-PORT(Entity, Entity.portId.COMP-PORT-NAME) // Specified port } // MATCHING if (PortRef.first() == NULL) { // Port queue is empty, no match Entity.NEXT-CONTROL(false); RETURN; } else { if ( MATCH-ITEM(portRef.SNAP-VALUE, matchingSpec, sender)) { // The message in the queue matches Entity.VALUE-STACK.push(portRef); // Saving port reference Entity.STATUS := ACTIVE; // successful match, Entity status is changed // from SNAPSHOT to ACTIVE Entity.NEXT-CONTROL(true); } else { // The top item in the queue does not match Entity.NEXT-CONTROL(false); } RETURN; } } // End of scope of portRef and sender
check-with-sender (portId, matchingSpec) true *(1) <receive-assignment> Entity.VALUE-STACK.pop(); clean-value-stack Entity.NEXT-CONTROL(true); RETURN; // optional value // assignemt
false
true
ETSI
77
9.8.2
The flow graph segment <check-without-sender> in figure 58 defines the execution of a check operation without a from clause.
segment <check-without-sender>
let { // local scope var portRef := NULL; if (portID == any port) { portRef := ALL-PORT-STATES.random(MATCH-ITEM(SNAP-VALUE, matchingSpec, NONE) && OWNER == Entity); if (portRef == NULL) { // no 'matching' port found Entity.NEXT-CONTROL(false); RETURN; } } else { portRef := GET-PORT(Entity, Entity.portId.COMP-PORT-NAME) // Specified port } // MATCHING if (PortRef.first() == NULL) { // Port queue is empty, no match Entity.NEXT-CONTROL(false); RETURN; } else { if ( MATCH-ITEM(portRef.SNAP-VALUE, matchingSpec, NONE)) { // The message in the queue matches Entity.VALUE-STACK.push(portRef); // Saving port reference Entity.STATUS := ACTIVE; // successful match, Entity status is changed // from SNAPSHOT to ACTIVE Entity.NEXT-CONTROL(true); } else { // The first item in the queue does not match Entity.NEXT-CONTROL(false); } RETURN; } } // End of scope
check-without-sender (portId, matchingSpec) true *(1) <receive-assignment> Entity.VALUE-STACK.pop(); clean-value-stack Entity.NEXT-CONTROL(true); RETURN; // optional value // assignemt
false
true
ETSI
78
9.8a
The checkstate port operation allows to examine the state of a port. If a port is in the state specified by the charstring parameter, the checkstate operation returns the Boolean value true. If the port is not in the specified state, the checkstate operation returns the Boolean value false. Calling the checkstate operation with an invalid argument leads to an error. For simplicity, the keywords "all port" and "any port" are considered to be special values of <portId>. The result of the checkstate port operation is pushed onto the value stack of the entity, which called the operation. The flow graph segment <checkstate-port-op> in figure 58a defines the execution of the running component operation.
segment <checkstate-port-op> // The expression shall evaluate // to a charstring value. The // result is pushed onto VALUE-STACK
<expression>
let { //local scope var portState := Entity.VALUE-STACK.top(); Entity.Value-STACK.push(portId); kind-of-state (portId) if (portState == Started or portState == Halted or portState == Stopped) { Entity.NEXT-CONTROL(true);
true
false
} elseif (portState == Connected or portState == Mapped or portState == Linked) { Entity.NEXT-CONTROL(false); } else { ***DYNAMIC-ERROR*** // invalid state } } // end local scope RETURN;
<check-port-status>
<check-port-connection>
ETSI
79
9.8a.1
The flow graph segment <check-port-status> in figure 58b describes the execution of the checkstate component operation by checking for the STATUS field in port states (cf. clause 8.3.3).
segment <check-port-status>
let { // local scope var portId ; var checkstate-par; var checkState ; var result ; var port ;
// // // //
for storing the portId checkstate parameter to be checked for port state to be checked for Boolean for intermediate results
check-port-status
portId := Entity. VALUE-STACK. top (); Entity .VALUE-STACK .pop(); checkstate-par := Entity .VALUE-STACK. top (); Entity .VALUE-STACK .pop(); if ( checkstate-par if ( checkstate-par if ( checkstate-par == Started) checkState := STARTED ; == Halted) checkState := HALTED; == Stopped) checkState := STOPPED ;
if ( Entity.PORT-REF == NULL) { // Entity has no ports result := false ; } else if (portId == 'all port ') { port := ALL-PORT-STATES . first (); result := true; while ( port != NULL and result == true ) { if (port .OWNER == Entity) { if ( port .STATUS != checkState) result := false ; } port := ALL-PORT-STATES.next (); } } else if (portId == 'any port ') { port := ALL-PORT-STATES . first (); result := false ; while ( port != NULL and result == false ) { if (port .OWNER == Entity) { if ( port .STATUS == checkState) result := true ; } port := ALL-PORT-STATES.next (); } } else { port := Entity. portId .COMP-PORT-NAME; if ( port == NULL ) { ***DYNAMIC-ERROR*** // port cannot be retrieved } else { if (port .STATUS == checkState ) result := true; if (port .STATUS != checkState ) result := false } } Entity .VALUE-STACK. push (result); } Entity .NEXT-CONTROL( true ); RETURN ;
9.8a.2
The flow graph segment <check-port-connection> in figure 58c describes the execution of the checkstate component operation by investigating the CONNECTIONS-LIST in port states (cf. clause 8.3.3).
ETSI
80
let { // local scope var portId; // for storing the portId var checkstate-par; // checkstate parameter to be checked for var result; // Boolean for intermediate results var isNotLinked := false; // Boolean for intermediate results var isMapped := false; // Boolean for intermediate results var isConnected := false; // Boolean for intermediate results var singleport := false; // Boolean for intermediate results var port; portId := Entity.VALUE-STACK.top(); Entity.VALUE-STACK.pop(); checkstate-par := Entity.VALUE-STACK.top(); Entity.VALUE-STACK.pop(); if (portId == 'any port' or portId == 'all port') { singleport := false; port := ALL-PORT-STATES.first(); } else { singleport := true; port := Entity.portId.COMP-PORT-NAME; } while (port != NULL) { if (port.OWNER == Entity) { if (port.CONNECTIONS-LIST == NULL) { isNotLinked := true; // unlinked port } if (port.CONNECTIONS-LIST.length() == 1) { if (GET-REMOTE-PORT(Entity,port,NONE) == SYSTEM) { isMapped := true; // mapped port } else { isConnected := true; // connected port } } else { // more than one connection isConnected := true; // connected port } } if (singleport == false) port := ALL-PORT-STATES.next(); if (singleport == true) port := NULL; } if (portId == 'any port') { if (checkstate-par == "Connected") result := isconnected; if (checkstate-par == "Mapped") result := ismapped; if (checkstate-par == "Linked") result := (ismapped or isconnected); } else { // portId is a single port or 'all port' if (checkstate-par == "Connected") { result := (isconnected and not(ismapped or isNotLinked)); } else if (checkstate-par == "Mapped") { result := (ismapped and not(isconnected or isNotLinked)); } else { // checkstate-par == "Linked" result := (ismapped or isconnected) and not(isNotLinked); } } Entity.VALUE-STACK.push(result); } Entity.NEXT-CONTROL(true); RETURN;
ETSI
81
9.9
The flow graph segment <clear-port-op> in figure 59 defines the execution of the clear port operation.
segment <clear-port-op> let { // Begin of local scope var portRef := NULL var portState := NULL; clear-port-op (portId) if (portId == all port) { portState := ALL-PORT-STATES.first(); while (portState != NULL) { if (portState.OWNER == Entity) { portState.VALUE-QUEUE.clear(); } portState := ALL-PORT-STATES.next(portState); } } else { portRef := Entity.portId.COMP-PORT-NAME; GET-PORT(Entity, portRef).clear(); } // End of socpe Entity.NEXT-CONTROL(true); RETURN;
9.10
Connect operation
The identifiers <portId1> and <portId2> are considered to be port identifiers of the corresponding test components. The components to which the ports belong are referenced by means of the component references <component-expression1> and <component-expression2>. The references may be stored in variables or is returned by a function, i.e. they are expressions, which evaluate to component references. The value stack is used for storing the component references. The execution of the connect operation is defined by the flow graph segment <connect-op> shown in figure 60. In the flow graph description the first expression to be evaluated refers to <component-expression1> and the second expression to <component-expression2>, i.e. the <component-expression2> is on top of the value stack when the connect-op node is executed.
ETSI
82
segment <connect-op>
<expression>
<expression>
connect-op (portId1,portId2)
let { // begin of a local scope var portOne, portTwo; // voriables for ports var comp2 := Entity.VALUE-STACK.top(); Entity.VALUE-STACK.pop(); var comp1 := Entity.VALUE-STACK.top(); Entity.VALUE-STACK.pop(); if (comp1 == Entity) { portOne := comp1.portId1.COMP-PORT-NAME; } else { portOne := portId1; } if (comp2 == Entity) { portTwo := comp2.portId2.COMP-PORT-NAME; } else { portTwo := portId2; } ADD-CON(comp1, portOne, comp2, portTwo); ADD-CON(comp2, portTwo, comp1, portOne); } // end of local scope Entity.NEXT-CONTROL(true); RETURN;
9.11
Constant definition
The value of a constant is considered to be an expression that evaluates to a value of the type of the constant. NOTE: Global constants are replaced by their values in a pre-processing step before this semantics is applied (see clause 9.2). Local constants are treated like variable declarations with initialization. The correct usage of constants, i.e. constants should never occur on the left side of an assignment, should be checked during the static semantics analysis of a TTCN-3 module.
The flow graph segment <constant-definition> in figure 61 defines the execution of a constant declaration where the value of the constant is provided in form of an expression.
ETSI
83
segment <constant-definition>
<expression>
// The expression shall evaluate // to a value of the type of the // constant that is defined.
// NOTE: A constant definition is treated like a // variable with inititialisation value Entity.INIT-VAR(constId, Entity.VALUE-STACK.top()); Entity.VALUE-STACK.pop(); Entity.NEXT-CONTROL(true); RETURN;
var-declaration-init (constId)
9.12
Create operation
A present alive clause indicates that the created component can be restarted after it has been stopped. Presence and absence of the alive clause is handled as a Boolean flag in the operational semantics (see alive parameter of the basic flow graph node create-op in figure 62). The flow graph segment <create-op> in figure 62 defines the execution of the create operation.
ETSI
84
segment <create-op>
let { // Local scope var newEntity := NEW-ENTITY(componentTypeID, alive); // Creation of the entity state for the // new entity. // The reference to the new entity is pushed onto the value stack of the // father' entity. Entity. VALUE-STACK.push(newEntity); // // // // // // The identifier of the 'father' entity is pushed onto the value stack of the new entity. The identifier is needed to restore the status of the 'father' entity after completion of the entity creation. The 'father' entity is blocked until all ports, variables, timers specified in the component type definition are instantiated. This instantiation is done by executing the flow graph that represents 'componentTypeID' by the new entity.
newEntity. VALUE-STACK. push( Entity); // The new entity is put into the module state ALL-ENTITY-STATES. append(newEntity); } // End local scope // The actual status of the 'father' entity is saved and the 'father' entity goes // into a blocking state. Note the restoration of the status of the father entity // is described in flow graph segment <finalize-component-init>. Entity. VALUE-STACK. push(Entity. STATUS); // Saving the actual status Entity. STATUS := BLOCKED; Entity. NEXT-CONTROL(true); // Return of control RETURN;
9.13
Deactivate statement
The deactivate statement specifies the deactivation of one or all active defaults of the entity that executes the deactivate statement. If one default shall be deactivated, the optional <default-expression> shall evaluate to a default reference which identifies the default to be deactivated. The call of a deactivate statement without <default-expression> deactivates all active defaults. The execution of a deactivate statement is defined by the flow graph segment <deactivate-stmt> in figure 63a.
ETSI
85
segment <deactivate-stmt>
<deactivate-one-default> OR <deactivate-all-defaults>
9.13.1
The flow graph segment <deactivate-one-default> in figure 63b specifies the deactivation of one active default. The value of the expression <default-expression> shall evaluate to a default reference. The expression may be provided in form of a variable value or value returning function. The deactivate statement removes the specified default from the DEFAULT-LIST of the entity that executes the deactivate statement.
segment <deactivate-one-default>
<expression>
// The expression shall evaluate to a // default reference, which is pushed // pushed onto the value stack.
9.13.2
The flow graph segment <deactivate-all-defaults> in figure 63c specifies the deactivation of all active defaults. The deactivate statement clears the DEFAULT-LIST of the entity that executes the deactivate statement.
segment <deactivate-all-defaults>
deactivate-all-defaults
ETSI
86
9.14
Disconnect operation
The identifiers <portId1> and <portId2> are considered to be port identifiers of the corresponding test components. The components to which the ports belong are referenced by means of the component references <component-expression1> and <component-expression2>. The references may be stored in variables or are returned by functions, i.e. they are expressions, which evaluate to component references. The value stack is used for storing the component references. The disconnect operation can be used with one parameter pair and with two parameters pairs. The usage of the disconnect operation with one parameter pair may disconnect connections for one component or, if executed by the MTC for all components. The usage of the disconnect operation with two parameter pairs allows to disconnect specific connections. Both usages are distinguished in the flow graph segment <disconnect-op> shown in figure 64, which defines the execution of the disconnect operation.
segment <disconnect-op>
// // // //
Distinction due to the usage of disconnect with one parameter pair and its usage with two parameter pairs.
9.14.1
The flow graph segment <disconnect-one-par-pair> shown in figure 64a defines the execution of the disconnect operation with one parameter pair. In the flow graph segment three cases are distinguished: 1) 2) 3) the mtc disconnects all connections of all components; all connections of one component are disconnected; and all connections of one port of one component are disconnected. In the flow graph segment the expression to be evaluated refers to <component-expression1> (see syntactical structure of the disconnect operation in clause 9.14).
ETSI
87
// The Expression shall evaluate // to a component reference. The // result is pushed onto VALUE-STACK
<disconnect-all>
if (Entity . VALUE-STACK . top () == all component) { if ( ( Entity != MTC ) OR (Entity == MTC && portId != all port) ) { ***DYNAMIC-ERROR*** } else { Entity . VALUE-STACK . pop (); Entity . NEXT-CONTROL ( true ); } } else { Entity . VALUE-STACK . push (portId); Entity . NEXT-CONTROL ( false); } RETURN ;
<disconnect-comp>
if (Entity . VALUE-STACK . top () == all port ) { Entity . VALUE-STACK . pop (); Entity . NEXT-CONTROL ( true ); } else { Entity . NEXT-CONTROL ( false); } RETURN ;
<disconnect-port>
ETSI
88
9.14.2
The flow segment <disconnect-all> defines the disconnection of all components at all connected ports.
segment <disconnect-all>
disconnect-all
let { // local scope var port := ALL-PORT-STATES.first(); var connection; while (port != NULL) { connection := port.CONNECTIONS.first(); while (connection != NULL) { if (connection.REMOTE-ENTITY == system) { connection := NULL; // mapped port } else { port.CONNECTIONS.delete(connection); connection := port.CONNECTIONS.first(); } } port := ALL-PORT-STATES.next(port); } } // End of local scope Entity.NEXT-CONTROL(true); RETURN;
ETSI
89
9.14.3
The flow segment <disconnect-comp> defines the disconnection of all ports of a specified component.
segment <disconnect-comp>
disconnect-comp
let { // local scope var comp := Entity.VALUE-STACK.top(); var connection; var port := ALL-PORT-STATES.first(); while (port != NULL) { connection := port.CONNECTIONS.first(); while (connection != NULL) { if (connection.REMOTE-ENTITY == system) { connection := port.CONNECTIONS.next(connection); } else if (connection.REMOTE-ENTITY == comp or (port.OWNER == comp) { port.CONNECTIONS.delete(connection); connection := port.CONNECTIONS.first(); } else { connection := port.CONNECTIONS.next(connection); } } port := ALL-PORT-STATES.next(port); } // clear value stack Entity.VALUE-STACK.pop(); } // End of local scope Entity.NEXT-CONTROL(true); RETURN;
ETSI
90
9.14.4
segment <disconnect-port>
disconnect-port
let { // local scope var portId, rPortId ; var comp, rComp ; var port; portId := Entity .VALUE-STACK .top (); Entity . VALUE-STACK . pop (); comp := Entity . VALUE-STACK . top (); Entity . VALUE-STACK . pop (); port := GET-PORT (comp, portId); var connection := port . CONNECTIONS . first (); while ( connection != NULL) { if (connection . REMOTE-ENTITY == SYSTEM) { ***DYNAMIC-ERROR*** // port is not a connected port } else { rComp := connection.REMOTE-ENTITY ; rPortId := connection.REMOTE-PORT-NAME; DEL-CON ( comp , portId , rComp, rPortId); DEL-CON (rComp, rPortId, comp , portId ); connection := port . CONNECTIONS . first (); } } } // End of local scope Entity . NEXT-CONTROL ( true ); RETURN ;
9.14.5
The flow graph segment <disconnect-two-par-pairs> shown in figure 64e defines the execution of the disconnect operation with two parameter pairs which disconnects specific connections. In the flow graph segment the first expression to be evaluated refers to <component-expression1> (see syntactical structure of the disconnect operation in clause 9.14)and the second expression to <component-expression2>, i.e. the <component-expression2> is on top of the value stack when the disconnect-two node is executed.
ETSI
91
segment <disconnect-two-par-pairs>
<expression>
<expression>
disconnect-two (portId1,portId2)
let { // begin of a local scope var portOne, portTwo; // voriables for ports var comp2 := Entity .VALUE-STACK. top(); Entity. VALUE-STACK . pop (); var comp1 := Entity .VALUE-STACK. top(); Entity. VALUE-STACK . pop (); if (comp1 == SYSTEM ) { ***DYNAMIC-ERROR*** // mapped port } else { portOne := comp1. portId1 .COMP-PORT-NAME ; } if (comp2 == SYSTEM ) { ***DYNAMIC-ERROR*** // mapped port } else { portTwo := comp2. portId2 .COMP-PORT-NAME ; } DEL-CON ( comp1 , portOne , comp2 , portTwo ); DEL-CON ( comp2 , portTwo , comp1 , portOne ); } // end of local scope Entity . NEXT-CONTROL( true); RETURN ;
9.15
Do-while statement
The execution of a do-while statement is defined by the flow graph segment <do-while-stmt> shown in figure 65.
segment <do-while-stmt>
<statement-block>
// The expression shall evaluate to // a Boolean value. <expression> if (Entity.VALUE-STACK.top()) { Entity.NEXT-CONTROL(true); } else { Entity.NEXT-CONTROL(false); } Entity.VALUE-STACK.pop(); RETURN;
ETSI
92
9.16
The done component operation checks whether a component is running or has stopped. Depending on whether a checked component is running or has stopped the done operation decides how the flow of control continues. Using a component reference identifies the component to be checked. The reference may be stored in a variable or be returned by a function, i.e. it is an expression. For simplicity, the keywords "all component" and "any component" are considered to be special expressions. The flow graph segment <done-op> in figure 66 defines the execution of the done component operation.
ETSI
93
segment <done-op>
<expression>
// The Expression shall evaluate // to a component reference. The // result is pushed onto VALUE-STACK
done-component-op
let { // local scope var aliveNr := Entity .SNAP-ALIVE . length(); var doneNr := Entity. SNAP-DONE. length (); var killedNr := Entity. SNAP-KILLED.length(); var nonWaitingNr := aliveNr doneNr killedNr ; // nonWaitingNr is the number of entities which are // alive and are executing a behaviour or neither have // stopped and nor have terminated. if ( Entity.VALUE-STACK. top () == ' all component') { if ( Entity != MTC ) { ***DYNAMIC-ERROR*** // 'all component' is not allowed } else { if (nonWaitingNr == 1) { // MTC is the Entity in the // test configuration Entity . NEXT-CONTROL (true); Entity . STATUS := ACTIVE; // DONE is successful } else { Entity . NEXT-CONTROL (false ); } } } else { if ( Entity .VALUE-STACK .top() == ' any component ') { if (Entity != MTC) { ***DYNAMIC-ERROR*** // 'any component' not allowed } else { if ( doneNr > 0 ) { Entity. NEXT-CONTROL(true); Entity. STATUS := ACTIVE; // DONE is successful } else { Entity. NEXT-CONTROL(false); } } } else { if (Entity . SNAP-DONE . member(Entity . VALUE-STACK. top())) { Entity . NEXT-CONTROL (true); Entity . STATUS := ACTIVE; // DONE is successful } else { Entity . NEXT-CONTROL (false ); } } } } // end of local scope
true
false
ETSI
94
9.17
Execute statement
The execute statement describes the execution of a test case <testCaseId> with the (optional) actual parameters <act-par1>, , <act-parn>. Optionally the execute statement may be guarded by a duration provided in form of an expression that evaluates to a float. If within the specified duration the test case does not return a verdict, a timeout exception occurs, the test case is stopped and an error verdict is returned. NOTE: The operational semantics models the stopping of the test case by a stop of the MTC. In reality, other mechanisms may be more appropriate.
If no timeout exception occurs, the MTC is created, the control instance (representing the control part of the TTCN-3 module) is blocked until the test case terminates, and for the further test case execution the flow of control is given to the MTC. The flow of control is given back to the control instance when the MTC terminates. The flow graph segment <execute-stmt> in figure 67 defines the execution of an execute statement.
segment <execute-stmt>
<execute-without-timeout> OR <execute-timeout>
ETSI
95
9.17.1
The execution of a test case starts with the creation of the mtc. Then the mtc is started with the behaviour defined in the test case definition. Afterwards, the module control waits until the test case terminates. The creation and the start of the MTC can be described by using create and start statements:
var mtcType MyMTC := mtcType.create; MyMTC.start(TestCaseName(P1Pn));
The flow graph segment <execute-without-timeout> in figure 68 defines the execution of an execute statement without the occurrence of a timeout exception by using the flow graph segments of the operations create and the start.
<start-component-op>
// Start of MTC
wait-for-termination
Entity.STATUS := BLOCKED; // MTC will set status to ACTIVE // before it terminates Entity.NEXT-CONTROL(true); RETURN;
ETSI
96
9.17.2
The flow graph segment <execute-timeout> in figure 69 defines the execution of an execute statement that is guarded by a timeout value. The flow graph segment also models the creation and start of the MTC by a create and a start operation. In addition, TIMER-GUARD guards the termination.
segment <execute -timeout> <expression> // The Expression shall evaluate to a // a float value. This value defines // the duration of TIMER-GUARD
set-timer-guard
init-test-case-state
prepare-wait
Entity.STATUS := SNAPSHOT; // MTC will set status to ACTIVE // before it terminates Entity.TIMER-GUARD.STATUS := RUNNING; Entity.NEXT-CONTROL(true); RETURN;
active-waiting
true
false
Entity.STATUS == SNAPSHOT and if ( Entity.TIMER-GUARD.STATUS != TIMEOUT) { // Control waits Entity.NEXT-CONTROL(true); } else { // Test case terminated or // timer guard timed out Entity.NEXT-CONTROL(true); } RETURN;
stop-or-timeout if (Entity.STATUS != SNAPSHOT) { // normal termination Entity.TIMER-GUARD.STATUS := IDLE; Entity.NEXT-CONTROL(true); } else { // guarding timer timed out Entity.NEXT-CONTROL(false); }
RETURN;
true
false
ETSI
97
9.17.3
In case of a dynamic error the flow graph segment <dynamic-error> is invoked by the test system. In addition, the flow graph segment <dynamic-error> is also used for describing the behaviour of the test case stop operation (clause 9.53a). All resources allocated to the test case are cleared and the error verdict is assigned to the test case. Control is given to the statement in the control part following the execute statement in which the error occurred. The flow graph segment <dynamic-error> is invoked by the module control in case that a test case does not terminate within the specified time limit (clause 9.17.2).
// Reset of configuration state ALL-ENTITY-STATES := NULL; ALL-PORT-STATES := NULL; MTC := NULL; TC-VERDICT := error; DONE := NULL; KILLED := NULL; // Update of the entity state of module control Control.TIMER-GUARD.STATUS := IDLE; Control.STATUS := ACTIVE; // Push error verdict (result of test case execution) onto // the stack of module control Control.VALUE-STACK.push(error); Entity.NEXT-CONTROL(true); RETURN;
9.18
a) b) c) d)
Expression
the expression is a literal value (or a constant); the expression is a variable; the expression is an operator applied to one or more operands; the expression is a function or operation call.
For the handling of expressions, the following four cases have to be distinguished:
ETSI
98
<func-op-call>
<operator-appl> denotes the application of arithmetic operators like +, -, not, etc. The execution of an expression is defined by the flow graph segment <expression> shown in figure 70.
segment <expression> <lit-value> OR <var-value> OR <func-op-call> OR <operator-appl> // // // // // // The four alternatives describe the four possibilities for expressions as described in this section.
9.18.1
The flow graph segment <lit-value> in figure 71 pushes a literal value onto the value stack of an entity.
9.18.2
The flow graph segment <var-value> in figure 72 pushes the value of a variable onto the value stack of an entity.
ETSI
99
9.18.3
The flow graph segment <func-op-call> in figure 73 refers to calls of functions and operations, which return a value that is pushed onto the value stack of an entity. All these calls are considered to be expressions.
segment <func-op-call> <activate-stmt> OR <create-op> OR <function-call> OR <mtc-op> OR <read-timer-op> OR <running-timer-op> OR <running-component-op> OR <self-op> OR <system-op> OR <verdict.get-op> OR <execute-stmt>
9.18.4
The flow graph representation in figure 74 directly refers to the assumption that reverse polish notation is used to evaluate operator expressions. The operands of the operator are calculated and pushed onto the evaluation stack. For the application of the operator, the operands are popped from the evaluation stack and the operator is applied. The result of the operator application is finally pushed onto the evaluation stack. Both, the popping of operands and the pushing the result are considered to be part of the operator application (Entity.APPLY-OPERATOR(operator) statement in figure 74), i.e. are not modelled by the operational semantics.
segment <operator-appl>
+
<expression>
// // // // //
For an n-nary operator, n operands in form of evaluated expressions have to be pushed onto the value stack
Entity.APPLY-OPERATOR(operator);
operator-appl (operator)
Entity.NEXT-CONTROL(true); RETURN;
ETSI
100
9.19
The flow graph segment <finalize-component-init> is part of the flow graph representing the behaviour of a component type definition. Its execution is defined in figure 75.
// The status of the father entity is restored. The identifier of the 'father' // entity is deleted from the VALUE-STACK. Entity.VALUE-STACK.top().STATUS := Entity.VALUE-STACK.top().VALUE-STACK.top(); Entity.VALUE-STACK.top().VALUE-STACK.pop(); Entity.VALUE-STACK.pop(); // A mark is pushed on the value stack, the entity goes into a blocking state, // i.e.,waits for being started) and control is given back to the module // evaluation procedure Entity.VALUE-STACK.push(MARK); Entity.STATUS := BLOCKED; Entity.NEXT-CONTROL(true); RETURN;
9.20
The flow graph segment <init-component-scope> is part of the flow graph representing the behaviour of a component type definition. Its execution is defined in figure 76.
segment <init-component-scope> // New scopes for variables, timers // and ports are created Entity.INIT-VAR-SCOPE(); Entity.INIT-TIMER-SCOPE(); Entity.INIT-PORT-SCOPE();
init-component-scope
Entity.NEXT-CONTROL(true); RETURN;
ETSI
101
9.20a
The flow graph segment <init-scope-with-runs-on> is part of the flow graph representing the behaviour of function and altstep definitions. It creates new scopes for variables, timers and ports, which include the names and values declared in the component type definition referred to in the runs on-clause. The execution of the flow graph segment is defined in figure 76a.
segment <init-scope-with-runs-on>
init-scope-with-runs-on
let { // local scope var actVarScope := copy(Entity.DATA-STATE.first()); var actTimerScope := copy(Entity.TIMER-STATE.first()); var actPORTScope := copy(Entity.PORT-REF.first()); Entity.INIT-VAR-SCOPE(); Entity.DATA-STATE.first().add(actVarScope); Entity.INIT-TIMER-SCOPE(); Entity.DATA-TIMER.first().add(actTimerScope); Entity.INIT-PORT-SCOPE(); Entity.PORT-REF.first().add(actPortScope) Entity.VALUE-STACK.push(MARK); }
Entity.NEXT-CONTROL(true); RETURN;
9.20b
The flow graph segment <init-scope-without-runs-on> is part of the flow graph representing the behaviour of function and altstep definitions. It creates new empty scopes for variables, timers and ports. Functions and altsteps without runs on-clause do not know the names and values declared in the component type definition of the invoking component. The execution of the flow graph segment is defined in figure 76b.
init-scope-without-runs-on
ETSI
102
9.21
The flow graph-segment <parameter-handling> is used in the beginning of flow graphs representing test cases, altsteps and functions. It initializes a new scope and creates variables and timers for the handling of parameters. The flow graph-segment <parameter-handling> assumes that the call record of the called test case, altstep or function is the top of the value stack. The execution of flow graph-segment <parameter-handling> is shown in figure 77.
segment <parameter-handling>
Entity.INIT-CALL-RECORD(VALUE-STACK.top()); // parameters are initialized Entity.VALUE-STACK.pop(); // removal of call record Entity.VALUE-STACK.push(MARK); // for scope Entity.NEXT-CONTROL(true); RETURN;
parameter-handling
9.22
A statement block is a scope unit. When entering a scope unit, new scopes for variables, timers and the value stack have to be initialized. When leaving a scope unit, all variables, timers and stack values of this scope have to be destroyed. NOTE 1: A Statement block can be embedded in another statement blocks or can occur as body of functions, altsteps, test cases and module control, and within compound statements, e.g. alt, if-else or do-while. NOTE 2: Receiving operations and altstep calls cannot appear in statement blocks, they are embedded in alt statements or call operations. NOTE 3: The operational semantics also handles operations and declarations like statements, i.e. they are allowed in statement blocks. NOTE 4: Some TTCN-3 functions, like e.g. system or self, are considered to be expressions, which are not useful as stand-alone statements in statement blocks. Their flow graph representations are not listed in figure 78. The flow graph segment <statement-block> in figure 78 defines the execution of a statement block.
ETSI
103
segment <statement-block> let { // local scope var actVarScope := copy(Entity.DATA-STATE.first()); var actTimerScope := copy(Entity.TIMER-STATE.first()); Entity.INIT-VAR-SCOPE(); Entity.DATA-STATE.first().add(actVarScope); Entity.INIT-TIMER-SCOPE(); Entity.DATA-TIMER.first().add(actTimerScope); Entity.VALUE-STACK.push(MARK); } Entity.NEXT-CONTROL(true); RETURN;
enter-scope-unit
*
<action-stmt> OR <activate-stmt> OR <alt-stmt> OR <assignment-stmt> OR <call-op> OR <clear-port-op> OR <connect-op> OR <create-op> OR <deactivate-stmt> OR <disconnect-op> OR <do-while-stmt> OR <execute-stmt> OR <for-stmt> OR <function-call> OR <getverdict-op> OR <goto-stmt> OR <if-else-stmt> OR <kill-component-op> OR <kill-exec-stmt> OR <label-stmt> OR <log-stmt> OR <map-op> OR <raise-op> OR <repeat-stmt> OR <reply-op> OR <return-stmt> OR <send-op> OR <setverdict-op> OR <start-component-op> OR <start-port-op> OR <start-timer-op> OR <stop-component-op> OR <stop-exec-stmt> OR <stop-port-op> OR <stop-timer-op> OR <unmap-op> OR <while-stmt> OR <statement-block>
// List of flow graph segments // representing all possible // statements and operations
exit-scope-unit
9.23
For statement
The initialization of the index variable and the corresponding manipulation of the index variable are considered to be assignments to the index variable. It is also allowed to declare and initialize the index variable directly in the for statement. The <boolean-expression> describes the termination criterion of the loop specified by the for-statement and the <statement-block> describes the loop body.
ETSI
104
The execution of the for statement is defined by the flow graph segment <for-stmt> shown in figure 79. The initial <assignment> or alternative variable declaration with assignment <var-declaration-init> (see clause 9.57.1) describes the initialization of the index variable. The <assignment> in the true branch of the decision node describes the manipulation of the index variable. The for statement is a scope unit for a newly declared index variable, this is modelled by means of the nodes enter-var-scope and exit-var-scope.
<assignment> OR <var-declaration-init>
// // // //
The index variable is only initialised (<assignment>) or declared and initialised (<var-declaration-init>)
<assignment>
9.24
Function call
The <function-name> denotes to the name of a function and <act-par-descr1>, , <act-par-descrn> describe the description of the actual parameter values of the function call. NOTE 1: A function call and an altstep call are handled in the same manner. Therefore, the altstep call (see clause 9.4) refers to this clause.
ETSI
105
It is assumed that for each <act-par-desc1> the corresponding formal parameter identifier <f-par-Id1> is known, i.e. we can extend the syntactical structure above to:
<function-name>((<f-par-Id1>,<act-par-desc1>), , (<f-par-Idn>,<act-par-descn>))
The flow graph segment <function-call> in figure 80 defines the execution of a function call. The execution is structured into three steps. In the first step a call record for the function <function-name> is created. In the second step the values of the actual parameter are calculated and assigned to the corresponding field in the call record. In the third step, two situations have to be distinguished: the called function is a user-defined function (<user-def-func-call>), i.e. there exists a flow graph representation for the function, or the called function is a pre-defined or external function (<predef-ext-func-call>). In case of a user-defined function call, the control is given to the called function. In case of a pre-defined or external function, it is assumed that the call record can be used to execute the function in one step. The correct handling of reference parameters and return value (has to be pushed onto the value stack) is in the responsibility of the called function, i.e. is outside the scope of this operational semantics. NOTE 2: If the function call models an altstep call, only the <user-def-func-call> branch will be chosen, because there exists a flow graph representation of the called altstep. NOTE 3: The <function call> segment is also used to describe the start of the MTC in an execute statement. In this case, a call record for the test case is constructed and only the <user-def-func-call> branch will be chosen.
construct-call-record (function-name)
*
<value-par-calculation>
// // // // //
For each pair (<f-par-Idi>, <act-parameter-desci>) the value of <act-parameter-desci is calculated and assigned to the corresponding field <f-par-Idi> in the call record. The call record is assumed to be the top element in the value stack.
*
<ref-var-par-calc> OR <ref-timer-par-calc> OR <ref-port-par-calc>
// Retrieves the locations for variables and timers // used as reference parameters and declared names of // port parameters
<predef-ext-func-call> OR <user-def-func-call>
// The called function may either be an external or // predefined function, or a user-defined function.
ETSI
106
9.24.1
The flow graph-segment <value-par-calculation> is used to calculate actual parameter values and to assign them to the corresponding fields in call records for functions, altsteps and test cases. It is assumed that a call record is the top element of the value stack and that a pair of:
(<f-par-Idi>, <act-parameter-desci>)
has to be handled. <act-parameter-desci> that has to be evaluated and <f-par-Idi> is the identifier of a formal parameter that has a corresponding field in the call record in the value stack. The execution of flow graph-segment <value-par-calculation> is shown in figure 81.
segment <value-par-calculation> // The expression represents <act-parameter-desci> // The result of the evaluation of the expression // is pushed onto the value stack.
<expression>
unit for parVal = Entity.VALUE-STACK.top(); parVal is a local variable that stores the value of the expression
Entity.VALUE-STACK.pop(); // Removal of expression value. // Afterwards the call record is // again top of the value stack Entity.VALUE-STACK.top().f-par-Id := parVal; // Value assignment to call record } // end of scope for parVal Entity.NEXT-CONTROL(true); RETURN;
9.24.2
The flow graph-segment <ref-par-var-calc> is used to retrieve the locations of variables used as actual reference parameters and to assign them to the corresponding fields in call records for functions, altsteps and test cases. It is assumed that a call record is the top element of the value stack and that a pair of:
(<f-par-Idi>, <act-pari>)
has to be handled. <act-pari> is the actual parameter for which the location has to be retrieved and <f-par-Idi> is the identifier of a formal parameter that has a corresponding field in the call record in the value stack.
ETSI
107
Entity.NEXT-CONTROL(true); RETURN;
9.24.3
The flow graph-segment <ref-par-timer-calc> is used to retrieve the locations of timers used as actual reference parameters and to assign them to the corresponding fields in call records for functions, altsteps and test cases. It is assumed that a call record is the top element of the value stack and that a pair of:
(<f-par-Idi>, <act-pari>)
has to be handled. <act-pari> is the actual parameter for which the location has to be retrieved and <f-par-Idi> is the identifier of a formal parameter that has a corresponding field in the call record in the value stack. The execution of flow graph-segment <ref-par-timer-calc> is shown in figure 83.
segment <ref-par-timer-calc> // Value assignment to call record Entity.VALUE-STACK.top().f-par-Id := Entity.GET-TIMER-LOCATION(act-par); parameter-assignment (f-par-Id, act-par) Entity.NEXT-CONTROL(true); RETURN;
ETSI
108
It is assumed that a call record is the top element of the value stack and that a pair of:
(<f-par-Idi>, <act-pari>)
has to be handled. <act-pari> is the actual parameter for which the location has to be retrieved and <f-par-Idi> is the identifier of a formal parameter that has a corresponding field in the call record in the value stack. The execution of flow graph-segment <ref-par-timer-calc> is shown in figure 83a.
segment <ref-par-port-calc> // Value assignment to call record Entity.VALUE-STACK.top().f-par-Id := Entity.act-par.COMP-PORT-NAME; parameter-assignment (f-par-Id, act-par) Entity.NEXT-CONTROL(true); RETURN;
9.24.4
The flow graph-segment <user-def-func-call> (figure 84) describes the transfer of control to a called user-defined function.
segment <user-def-func-call> // Storage of return address Entity.NEXT-CONTROL(true); // Control is transferred to called function Entity.CONTROL-STACK.push(GET-FLOW-GRAPH(function-name)); user-def-func-call (function-name) RETURN;
ETSI
109
9.24.5
The flow graph-segment <predef-ext-func-call> (figure 85) describes the call of a pre-defined or external function.
segment <predef-ext-func-call> let { // scope for argument variable var argument := Entity.VALUE-STACK.top(); Entity.VALUE-STACK.pop(); // removal of call record // Application of function-name function-name(argument); } // end of scope for argument Entity.NEXT-CONTROL(true); RETURN;
<predef-ext-func-call> (function-name)
9.25
Getcall operation
Apart from the getcall keyword this syntactical structure is identical to the syntactical structure of the receive operation. Therefore, the operational semantics handles the getcall operation in the same manner as the receive operation. This is also shown in the flow graph segment <getcall-op> (see figure 86), which defines the execution of a getcall operation. The figure refers to flow graph segments related to the receive operation (see clause 9.37).
segment <getcall-op>
<receive-with-sender> OR <receive-without-sender>
9.26
Getreply operation
Apart from the getreply keyword this syntactical structure is identical to the syntactical structure of the receive operation. Therefore, the operational semantics handles the getreply operation in the same manner as the receive operation. This is also shown in the flow graph segment <getreply-op> (see figure 87), which defines the execution of a getreply operation. The figure refers to flow graph segments related to the receive operation (see clause 9.37).
ETSI
110
segment <getreply-op>
<receive-with-sender> OR <receive-without-sender>
9.27
Getverdict operation
The flow graph segment <getverdict-op> in figure 88 defines the execution of the getverdict operation.
segment <getverdict-op> getverdict-op // E-VERDICT is pushed onto VALUE-STACK Entity.VALUE-STACK.push(Entity.E-VERDICT); Entity.NEXT-CONTROL(true); RETURN;
9.28
Goto statement
The flow graph segment <goto-stmt> in figure 89 defines the execution of the goto statement.
nop
<labelId>
Figure 89: Flow graph segment <goto-stmt> NOTE: The <labelId> parameter of the goto statement indicates the transfer of control to the place at which a label <labelId> is defined (see also clause 9.30).
ETSI
111
9.28a
The flow graph segment <halt-port-op> in figure 89a defines the execution of the halt port operation.
segment <halt-port-op> let { // Begin of local scope var portRef := NULL var portState := NULL ; halt-port-op (portId) if (portId == all port ) { portState := ALL-PORT-STATES. first (); while (portState != NULL) { if (portState. OWNER == Entity ) { portState. STATUS := HALTED ; portState. enqueue ( HALT-MARKER ); } portState := ALL-PORT-STATES .next( portState ); } } else { portRef := Entity .portId. COMP-PORT-NAME ; GET-PORT ( Entity , portRef). STATUS := HALTED ; GET-PORT ( Entity , portRef). enqueue ( HALT-MARKER); } } // End of socpe Entity .NEXT-CONTROL (true); RETURN ;
Figure 89a: Flow graph segment <halt-port-op> NOTE: The HALT-MARKER that is put by a halt operation into the port queue is removed by the SNAP-PORTS function (see clause 8.3.3.2) when the marker is reached, i.e. all messages preceding the marker have been processed. The SNAP-PORTS function is called when taking a snapshot.
9.29
If-else statement
The else part of the if-else statement is optional. The flow graph segment <if-else-stmt> in figure 90 defines the execution of the if-else statement.
ETSI
112
segment <if-with-else-branch>
<statement-block>
*(1)
// Optional else part <statement-block>
9.29a
The kill component operation stops the specified component and removes it from the test system. All test components will be stopped and removed from the test system, i.e. the test case terminates, if the MTC is killed (e.g. mtc.kill) or kills itself (e.g. self.kill). The MTC may kill all parallel test components by using the all keyword, i.e. all component.kill. A component to be killed is identified by a component reference provided as expression, e.g. a value or value returning function. For simplicity, the keyword "all component" is considered to be special values of <component-expression>. The operations mtc and self are evaluated according to clauses 9.33 and 9.43. The flow graph segment <kill-component-op> in figure 90a defines the execution of the kill component operation.
ETSI
113
segment <kill-component-op> // The Expression shall evaluate // to a component reference. The // result is pushed onto VALUE-STACK
<expression>
<kill-all-comp>
if (Entity.VALUE-STACK.top() == 'all component') { Entity.VALUE-STACK.pop(); // clean value stack if (Entity != MTC) { ***DYNAMIC-ERROR*** // 'all' not allowed } else { Entity.NEXT-CONTROL(true); { } else { Entity.NEXT-CONTROL(false); } RETURN;
if (Entity.VALUE-STACK.top() == MTC) { Entity.VALUE-STACK.pop(); // clean value stack Entity.NEXT-CONTROL(true); } else { Entity.NEXT-CONTROL(false); } RETURN;
<kill-mtc> if (ALL-ENTITY-STATES.member(Entity.VALUE-STACK.top())) { Entity.NEXT-CONTROL(true); } else { if (KILLED.member(Entity.VALUE-STACK.top())){ // NULL operation, component already terminated Entity.VALUE-STACK.pop(); // clean value stack Entity.NEXT-CONTROL(false); } else { // component id has not been allocated ***DYNAMIC-ERROR*** { } RETURN;
ETSI
114
let { // local scope for variables var myEntity := ALL-ENTITY-STATES . first (); // Update test case verdict and deletion of components while (myEntity != NULL) { if (myEntitiy.E-VERDICT == fail or TC-VERDICT == fail ) { TC-VERDICT := fail; } else { if (myEntity .E-VERDICT == inconc or TC-VERDICT == inconc ) { TC-VERDICT := inconc; } else { if (myEntity . E-VERDICT == pass or TC-VERDICT == pass ) { TC-VERDICT := pass ; } } myEntity := ALL-ENTITY-STATES . next ( myEntity); } // TC-VERDICT is the result of the execute operation CONTROL.VALUE-STACK . push ( TC-VERDICT); // Update of test case reference parameters UPDATE-REMOTE-LOCATIONS( MTC , CONTROL ); // Deletion of test components, release of resources, clearing lists ALL-ENTITY-STATES := NULL ; // Deletion of Entity states ALL-PORT-STATES := NULL; DONE := NULL; KILLED := NULL; TC-VERDICT := none; MTC := NULL ; // Deletion of the last reference to the MTC CONTROL.STATUS := ACTIVE ; // Control continues } // End of local scope RETURN;
ETSI
115
segment <kill-component>
kill-component
let { // local scope for variable myEntity var myEntity := Entity.VALUE-STACK.top(); // for test continuation, if kill is executed by another component if (Entity != myEntity()) { // clean value stack Entity.VALUE-STACK.pop(); Entity.NEXT-CONTROL(true); } // Update test case verdict if (myEntitiy.E-VERDICT == fail or TC-VERDICT == fail) { TC-VERDICT := fail; } else { if (myEntity.E-VERDICT == inconc or TC-VERDICT == inconc) { TC-VERDICT := inconc; } else { if (myEntity.E-VERDICT == pass or TC-VERDICT == pass) { TC-VERDICT := pass; } } // Deletion of test component DONE.append(myEntity); KILLED.append(myEntity); DEL-ENTITY(myEntity); } // End of local scope RETURN;
ETSI
116
segment <kill-all-comp>
kill-all-comp
let { // local scope for variable myEntity var myEntity := ALL-ENTITY-STATES.next(MTC); // Update test case verdict while (myEntity != NULL) { if (myEntitiy.E-VERDICT == fail or TC-VERDICT == fail) { TC-VERDICT := fail; } else { if (myEntity.E-VERDICT == inconc or TC-VERDICT == inconc) { TC-VERDICT := inconc; } else { if (myEntity.E-VERDICT == pass or TC-VERDICT == pass) { TC-VERDICT := pass; } } myEntity := ALL-ENTITY-STATES.next(myEntity); } // Deletion of test components myEntity := ALL-ENTITY-STATES.next(MTC); while (myEntity != NULL) { DONE.append(myEntity); KILLED.append(myEntity); DEL-ENTITY(myEntity); myEntity := ALL-ENTITY-STATES.next(MTC); } } // End of local scope Entity.NEXT-CONTROL(true); RETURN;
// // // //
9.29b
kill
The effect of the kill execution statement depends on the entity that executes the kill execution statement: a) b) If kill is performed by the module control, the test campaign ends, i.e. all test components and the module control disappear from the module state. If the kill is executed by the MTC, all parallel test components and the MTC stop execution. The global test case verdict is updated and pushed onto the value stack of the module control. Finally, control is given back to the module control and the MTC terminates. If the kill is executed by a test component, the global test case verdict TC-VERDICT and the global DONE and KILLED lists are updated. Then the component disappears from the module.
c)
ETSI
117
The flow graph segment <kill-exec-stmt> in figure 90e describes the execution of the kill statement.
segment <kill-exec-stmt> decision true false if (Entity == CONTROL { Entity .NEXT-CONTROL( true); } else { Entity .NEXT-CONTROL( false ); } RETURN; if (Entity == MTC ) { Entity .NEXT-CONTROL( true); } else { Entity .VALUE-STACK .push( Entity ); Entity .NEXT-CONTROL( false ); } RETURN; false
<kill-control>
decision true
<kill-mtc>
<kill-component>
ETSI
118
9.29c
The killed component operation checks whether a component is alive or has been removed from the test system. Depending on whether a checked component is alive or has been removed from the test system, the killed operation decides how the flow of control continues. Using a component reference identifies the component to be checked. The reference may be stored in a variable or be returned by a function, i.e. it is an expression. For simplicity, the keywords "all component" and "any component" are considered to be special expressions. The flow graph segment <killed-op> in figure 90g defines the execution of the killed component operation.
segment <killed-op>
// The Expression shall evaluate // to a component reference. The // result is pushed onto VALUE-STACK <expression> if (Entity.VALUE-STACK.top() == 'all component') { if (Entity != MTC) { ***DYNAMIC-ERROR*** // 'all component' is not allowed } else { if (Entity.SNAP-ALIVE.lenght() == 1) { // MTC is alive Entity.NEXT-CONTROL(true); Entity.STATUS := ACTIVE; // KILLED is successful } else { Entity.NEXT-CONTROL(false); } } } else { if (Entity.VALUE-STACK.top() == 'any component') { if (Entity != MTC) { ***DYNAMIC-ERROR*** // 'any component' is not allowed } else { if (Entity.SNAP-KILLED.length() > 0) { Entity.NEXT-CONTROL(true); Entity.STATUS := ACTIVE; // KILLED is successful } else { Entity.NEXT-CONTROL(false); } } } else { if (Entity.SNAP-DONE.member(Entity.VALUE-STACK.top())) { Entity.NEXT-CONTROL(true); Entity.STATUS := ACTIVE; // KILLED is successful } else { Entity.NEXT-CONTROL(false); } } } Entity.VALUE-STACK.pop(); // clean value stack RETURN;
killed-component-op
true
false
ETSI
119
9.30
Label statement
The flow graph segment <label-stmt> in figure 91 defines the execution of the label statement. NOTE: The <labelId> parameter of the label statement indicates the possibility that a label can be the target for a jump by means of a goto statement (see also clause 9.28).
nop
9.31
Log statement
The flow graph segment <log-stmt> in figure 92 defines the execution of the log statement. NOTE: The <informal description> parameter of the log statement has no meaning for the operational semantics and is therefore not represented in the flow graph segment.
nop
ETSI
120
9.32
Map operation
The identifiers <portId1> and <portId2> are considered to be port identifiers of the corresponding test component and test system interface. The component to which the <portId1> belongs is referenced by means of the component reference <component-expression>. The reference may be stored in variables or is returned by a function, i.e. it is an expression, which evaluates to a component reference. The value stack is used for storing the component reference. NOTE: The map operation does not care whether the system:<portId> statement appears as first or as second parameter. For simplicity, it is assumed that it is always the second parameter.
The execution of the map operation is defined by the flow graph segment <map-op> shown in figure 93.
segment <map-op> let { // begin of a local scope var portRef; var comp1 := Entity.VALUE-STACK.top(); Entity.VALUE-STACK.pop(); if (comp1 == Entity) { portRef := Entity.portId1.COMP-PORT-NAME; } else { portRef := portId1; } ADD-CON(comp1, portRef, system, portId2); } // end of local scope Entity.NEXT-CONTROL(true); RETURN;
<expression>
map-op (portId1,portId2)
9.33
mtc
Mtc operation
The flow graph segment <mtc-op> in figure 94 defines the execution of the mtc operation.
mtc-op
ETSI
121
9.34
Port declaration
Port declarations can be found in component type definitions. The effect of a port declaration is the creation of a new port when a new component of the corresponding type is created. Furthermore, a port reference is created in the actual scope of the test component. In the newly created port reference, the values PORT-NAME and COMP-PORT-NAME are equal. The flow graph segment <port-declaration> in figure 95 defines the execution of a port declaration.
segment <port-declaration> // A new port state and a port reference // are created port-declaration (portName) ALL-PORT-STATES.append(NEW-PORT(Entity, portName); Entity.INIT-PORT(portName, portName); Entity.NEXT-CONTROL(true); RETURN;
9.35
Raise operation
The optional <receiver-spec> in the to clause refers to the receivers of the exception. In case of a one-to one communication, the <receiver-spec> addresses a single entity (including the SUT or an entity within the SUT). In case of multicast or broadcast communication, the <receiver-spec> specifies a set or all test components connected via the specified port with the calling component. The flow graph segment <raise-op> in figure 96 defines the execution of a raise operation.
segment <raise-op>
// A raise operation may adress one, // multiple (multicast and broadcast) // or no receiver entities.
ETSI
122
9.35.1
The flow graph segment <raise-with-one-receiver-op> in figure 97 defines the execution of a raise operation where the receiver is specified in form of an expression.
segment <raise-with-one-receiver-op>
<expression>
let { var receiver := Entity.VALUE-STACK.top(); var portRef := Entity.portId.COMP-PORT-NAME; var remotePort := GET-REMOTE-PORT(Entity, portref, receiver); if (remotePort == NULL) { ***DYNAMIC-ERROR***; // Remote port cannot be found } if (remotePort == SYSTEM) { // Port is mapped onto a port of the test system // reception of the reply by the SUT is outside // the scope of the operational semantics } else { // sending of exception remotePort.enqueue(CONSTRUCT-ITEM(Entity, raise, exceptSpec)); } } // end of scope of receiver and remotePort Entity.VALUE-STACK.pop(); Entity.NEXT-CONTROL(true); RETURN; // clean value stack
ETSI
123
segment <raise-with-multiple-receivers-op>
+(number) <expression>
let { // var i; // loop counter variable var connection; // variable for connections in port states var receiver; // variable for receiver component references var localPort, remotePort; // variables for port references localPort := Entity.portId.COMP-PORT-NAME; // local port if (Entity.VALUE-STACK.top() == all component) { connection := localPort.CONNECTIONS-LIST.next(connection); while (connection != NULL) { remotePort := connection.REMOTE-PORT-NAME; if (remotePort == SYSTEM) { // Port is mapped onto a port of the test system // reception of the reply by the SUT is outside // the scope of the operational semantics } else { // sending of call remotePort.enqueue(CONSTRUCT-ITEM(Entity, raise, exceptSpec)); } connection := localPort.CONNECTIONS-LIST.next(connection); } } else { for (i == 1; i <= number; i := i+1) { receiver := Entity.VALUE-STACK.top(); Entity.VALUE-STACK.pop(); // clean value stack remotePort := GET-REMOTE-PORT(Entity, localPort, receiver); if (remotePort == NULL) { ***DYNAMIC-ERROR***; // Remote port cannot be found } if (remotePort == SYSTEM) { // Port is mapped onto a port of the test system // reception of the reply by the SUT is outside // the scope of the operational semantics } else { // sending of call remotePort.enqueue(CONSTRUCT-ITEM(Entity, raise, exceptSpec)); } } } } // end of local scope Entity.NEXT-CONTROL(true); RETURN;
ETSI
124
9.35.2
The flow graph segment <raise-without-receiver-op> in figure 98 defines the execution of a raise operation without to-clause.
segment <raise-without-receiver-op>
let { var portRef := Entity.portId.COMP-PORT-NAME; var remotePort := GET-REMOTE-PORT(Entity, portRef, NONE); if (remotePort == NULL) { ***DYNAMIC-ERROR***; // Remote port cannot be found } if (remotePort == SYSTEM) { // Port is mapped onto a port of the test system // reception of the reply by the SUT is outside // the scope of the operational semantics } else { // sending of exception remotePort.enqueue(CONSTRUCT-ITEM(Entity, raise, exceptSpec)); } } // end of scope of remotePort
Entity.NEXT-CONTROL(true); RETURN;
ETSI
125
9.36
The flow graph segment <read-timer-op> in figure 99 defines the execution of the read timer operation. The read timer operation distinguishes between its usage in a Boolean guard of an alt statement or blocking call operation and all other cases. If used in a Boolean guard, the result of the read timer operation is based on the actual snapshot, i.e. the SNAP-STATUS and SNAP-VALUE entries of the timer binding, in all other cases, the STATUS, ACT-DURATION and TIME-LEFT entries of the timer binding determine the result of the operation.
let { // local scope for variable myValue var float myValue; if (Entity.STATUS == SNAPSHOT) { if (Entity.timerId.SNAP-STATUS == RUNNING) { myValue := Entity.timerId.SNAP-VALUE; } else { myValue := 0.0; } } else { if (Entity.timerId.STATUS == RUNNING) { myValue := Entity.timerId.ACT-DURATION Entity.timerId.TIME-LEFT; } else { myValue := 0.0; } } Entity.VALUE-STACK.push(myValue); } // end local scope Entity.NEXT-CONTROL(true); RETURN;
ETSI
126
9.37
Receive operation
The optional <component-expression> in the from clause refers to the sender entity. It may be provided in form of a variable value or the return value of a function, i.e. it is assumed to be an expression. The optional <assignmentPart> denotes the assignment of received information if the received message matches to the matching specification <matchingSpec> and to the (optional) from clause. The flow graph segment <receive-op> in figure 100 defines the execution of a receive operation.
segment <receive-op>
<receive-with-sender> OR <receive-without-sender>
ETSI
127
9.37.1
The flow graph segment <receive-with-sender> in figure 101 defines the execution of a receive operation where the sender is specified in form of an expression.
// // // //
The Expression shall evaluate to a component reference or an address value. The result is pushed onto the VALUE-STACK.
let { // local scope for portRef and sender var portRef := NULL; var sender := Entity.VALUE-STACK.top(); // Sender Entity.VALUE-STACK.pop(); // Clean value stack if (portID == any port) { portRef := ALL-PORT-STATES.random(MATCH-ITEM(SNAP-VALUE,matchingSpec,sender) && OWNER == Entity); if (portRef == NULL) { // no 'matching' port found Entity.NEXT-CONTROL(false); RETURN; } } else { portRef := GET-PORT(Entity, Entity.portId.COMP-PORT-NAME); // Specified port } // MATCHING if (PortRef.first() == NULL) { // Port queue is empty, no match Entity.NEXT-CONTROL(false); RETURN; } else { if ( MATCH-ITEM(portRef.SNAP-VALUE, matchingSpec, sender)) { // The message in the queue matches Entity.VALUE-STACK.push(portRef); // Saving port reference Entity.STATUS := ACTIVE; // successful match, Entity status is changed // from SNAPSHOT to ACTIVE Entity.NEXT-CONTROL(true); } else { // The top item in the queue does not match Entity.NEXT-CONTROL(false); } RETURN; } } // End of scope of portRef and sender
receive-with-sender (portId, matchingSpec) true *(1) <receive-assignment> // Removal of received item from port Entity.VALUE-STACK.top().dequeue(); Entity.VALUE-STACK.pop(); Entity.NEXT-CONTROL(true); RETURN; // optional value // assignemt
remove-from-port
false
true
ETSI
128
9.37.2
The flow graph segment <receive-without-sender> in figure 102 defines the execution of a receive operation without a from clause.
segment <receive-without-sender>
let { // local scope var portRef := NULL; if (portID == any port) { portRef := ALL-PORT-STATES.random(MATCH-ITEM(SNAP-VALUE, matchingSpec, NONE) && OWNER == Entity); if (portRef == NULL) { // no 'matching' port found Entity.NEXT-CONTROL(false); RETURN; } } else { portRef := GET-PORT(Entity, Entity.portId.COMP-PORT-NAME); // Specified port } // MATCHING if (PortRef.first() == NULL) { // Port queue is empty, no match Entity.NEXT-CONTROL(false); RETURN; } else { if ( MATCH-ITEM(portRef.SNAP-VALUE, matchingSpec, NONE)) { // The message in the queue matches Entity.VALUE-STACK.push(portRef); // Saving port reference Entity.STATUS := ACTIVE; // successful match, Entity status is changed // from SNAPSHOT to ACTIVE Entity.NEXT-CONTROL(true); } else { // The first item in the queue does not match Entity.NEXT-CONTROL(false); } RETURN; } } // End of scope
receive-without-sender (portID, matchingSpec) true *(1) <receive-assignment> // Removal of received item from port Entity.VALUE-STACK.top().dequeue(); Entity.VALUE-STACK.pop(); Entity.NEXT-CONTROL(true); RETURN; // optional value // assignemt
remove-from-port
false
true
ETSI
129
9.37.3
The flow graph segment <receive-assignment> in figure 103 defines the retrieval of information from received messages and their assignment to variables.
segment <receive-assignment>
receive-assignment (assignmentPart)
9.38
repeat
Repeat statement
Basically, the repeat statement is a return statement without return value, which also changes the entity status to REPEAT. The status REPEAT will force the re-evaluation of the alt statement in which the repeat statement has been executed. The flow graph segment <repeat-stmt> shown in figure 104 defines the execution of the repeat statement.
<return-without-value>
ETSI
130
9.39
Reply operation
The optional <receiver-spec> in the to clause refers to the receivers of the reply. In case of a one-to one communication, the <receiver-spec> addresses a single entity (including the SUT or an entity within the SUT). In case of multicast or broadcast communication, the <receiver-spec> specifies a set or all test components or entities in the SUT connected via the specified port with the calling component. The flow graph segment <reply-op> in figure 105 defines the execution of a reply operation.
segment <reply-op>
// A reply operation may adress one, // multiple (multicast and broadcast) // or no receiver entities.
ETSI
131
9.39.1
The flow graph segment <reply-with-one-receiver-op> in figure 106 defines the execution of a reply operation where the receiver is specified in form of an expression.
segment <reply-with-one-receiver-op>
<expression>
let { var receiver := Entity.VALUE-STACK.top(); var portRef := Entity.portId.COMP-PORT-NAME; var remotePort := GET-REMOTE-PORT(Entity, portRef, receiver); if (remotePort == NULL) { ***DYNAMIC-ERROR***; // Remote port cannot be found } if (remotePort == SYSTEM) { // Port is mapped onto a port of the test system // reception of the reply by the SUT is outside // the scope of the operational semantics } else { // sending of reply remotePort.enqueue(CONSTRUCT-ITEM(Entity, reply, replySpec)); } } // end of scope of receiver and remotePort Entity.VALUE-STACK.pop(); Entity.NEXT-CONTROL(true); RETURN; // clean value stack
ETSI
132
segment <reply-with-multiple-receivers-op>
+(number) <expression>
// i; // loop counter variable connection; // variable for connections in port states receiver; // variable for receiver component references or // address values var localPort, remotePort; // variables for port references localPort := Entity.portId.COMP-PORT-NAME; // local port
if (Entity.VALUE-STACK.top() == all component) { connection := localPort.CONNECTIONS-LIST.next(connection); while (connection != NULL) { remotePort := connection.REMOTE-PORT-NAME; if (remotePort == SYSTEM) { // Port is mapped onto a port of the test system // reception of the reply by the SUT is outside // the scope of the operational semantics } else { // sending of call remotePort.enqueue(CONSTRUCT-ITEM(Entity, reply, replySpec)); } connection := localPort.CONNECTIONS-LIST.next(connection); } } else { for (i == 1; i <= number; i := i+1) { receiver := Entity.VALUE-STACK.top(); // clean value stack Entity.VALUE-STACK.pop(); remotePort := GET-REMOTE-PORT(Entity, localPort, receiver); if (remotePort == NULL) { ***DYNAMIC-ERROR***; // Remote port cannot be found } if (remotePort == SYSTEM) { // Port is mapped onto a port of the test system // reception of the reply by the SUT is outside // the scope of the operational semantics } else { // sending of call remotePort.enqueue(CONSTRUCT-ITEM(Entity, reply, replySpec)); } } } } // end of local scope Entity.NEXT-CONTROL(true); RETURN;
ETSI
133
9.39.2
The flow graph segment <reply-without-receiver-op> in figure 107 defines the execution of a reply operation without to-clause.
segment <reply-receiver-op>
let { var portRef := Entity.portId.COMP-PORT-NAME; var remotePort := GET-REMOTE-PORT(Entity, portRef, NONE); if (remotePort == NULL) { ***DYNAMIC-ERROR***; // Remote port cannot be found } if (remotePort == SYSTEM) { // Port is mapped onto a port of the test system // reception of the reply by the SUT is outside // the scope of the operational semantics } else { // sending of reply remotePort.enqueue(CONSTRUCT-ITEM(Entity, reply, replySpec)); } } // end of scope of remotePort
Entity.NEXT-CONTROL(true); RETURN;
9.40
Return statement
The optional <expression> describes a possible return value of a function. The execution of a return statement means that the control leaves the actual scope unit, i.e. variables and timers only known in this scope have to be deleted and the value stack has to be updated. A return statement has the effect of a stop component operation, if it is the last statement in a behaviour description. NOTE: Test cases and module control will always end with a stop component operation. This is due to their flow graph representation (see clause 8.2). Only other test components may terminate with a return statement.
ETSI
134
The flow graph segment <return-stmt> in figure 108 defines the execution of a return statement.
segment <retun-stmt>
<return-with-value> OR <return-without-value>
ETSI
135
9.40.1
The flow graph segment <return-with-value> in figure 109 defines the execution of a return that returns a value specified in form of an expression.
segment <return-with-value>
<expression>
false
true
decision
true
<stop-alive-component>
<kill-component>
ETSI
136
9.40.2
The flow graph segment <return-without-value> in figure 110 defines the execution of a return statement that returns no value.
segment <return-without-value>
<expression>
false
true
decision
true
<stop-alive-component>
<kill-component>
ETSI
137
9.41
The running component operation checks whether a component is running or has either stopped or terminated and been removed from the test system. The component to be checked is identified by a component reference, which may be provided in form of a variable or value returning function, i.e. is an expression. For simplicity, the keywords "all component" and "any component" are considered to be special expressions. The running component operation distinguishes between its usage in a Boolean guard of an alt statement or blocking call operation and all other cases. If used in a Boolean guard, the result of running component operation is based on the actual snapshot. In all other cases evaluates directly the state information. The result of the running component operation is pushed onto the value stack of the entity, which called the operation. The flow graph segment <running-component-op> in figure 111 defines the execution of the running component operation.
segment <running-component-op> <expression> // The expression shall evaluate // to a component reference. The // result is pushed onto VALUE-STACK
decision
true
<running-comp-act>
<running-comp-snap>
ETSI
138
9.41.1
The flow graph segment <running-comp-act> in figure 112 describes the execution of the running component operation outside a snapshot, i.e. the component is in the status ACTIVE.
segment <running-comp-act>
let { // local scope var comp; // for storing a component reference var decision; // Boolean if (Entity.VALUE-STACK.top() == 'all component') { if (Entity != MTC) { ***DYNAMIC-ERROR*** // 'all component' is not allowed } else { if (DONE.length() == 0) { // all components are running Entity.VALUE-STACK.push(true); } else { // at least one component has been stopped Entity.VALUE-STACK.push(false); } } } else { if (Entity.VALUE-STACK.top() == 'any component') { if (Entity != MTC) { ***DYNAMIC-ERROR*** // 'any component' not allowed } else { comp := ALL-ENTITY-STATES.next(MTC); while (comp != NULL and decision == false) { if (comp.STATUS == ACTIVE) { decision := true; } comp := ALL-ENTITY-STATES.next(comp); } Entity.VALUE-STACK.push(decision); } } else { if (ALL-ENTITY-STATES.member(Entity.VALUE-STACK.top())) { // Specified component is alive Entity.VALUE-STACK.push(true); } else { Entity.VALUE-STACK.push(false); } } } Entity.NEXT-CONTROL(true); RETURN;
running-comp-act
ETSI
139
9.41.2
The flow graph segment <running-comp-snap> in figure 113 describes the execution of the running component operation during the evaluation of a snapshot, i.e. the component is in the status SNAPSHOT.
segment <running-comp-snap>
let { // local scope var comp; // for storing a component reference var decision; // Boolean if (Entity.VALUE-STACK.top() == 'all component') { if (Entity != MTC) { ***DYNAMIC-ERROR*** // 'all component' is not allowed } else { if (Entity.SNAP-DONE.length() == 0) { Entity.VALUE-STACK.push(true); } else { // at least one component has been stopped Entity.VALUE-STACK.push(false); } } } else { if (Entity.VALUE-STACK.top() == 'any component') { if (Entity != MTC) { ***DYNAMIC-ERROR*** // 'any component' not allowed } else { comp := Entity.SNAP-ALIVE.next(MTC); while (comp != NULL and decision == false) { if (comp.STATUS == ACTIVE) { decision := true; } comp := ALL-ENTITY-STATES.next(comp); } Entity.VALUE-STACK.push(decision); } } else { if (Entity.SNAP-ALIVE.member(Entity.VALUE-STACK.top())) { // Specified component is alive Entity.VALUE-STACK.push(true); } else { Entity.VALUE-STACK.push(false); } } } Entity.NEXT-CONTROL(true); RETURN;
running-comp-snap
ETSI
140
9.42
The flow graph segment <running-timer-op> in figure 114 defines the execution of the running timer operation. The running timer operation distinguishes between its usage in a Boolean guard of an alt statement or blocking call operation and all other cases. If used in a Boolean guard, the result of running timer operation is based on the actual snapshot, i.e. the SNAP-STATUS entry of the timer binding, in all other cases, the STATUS entry of the timer binding determines the result of the operation. The any keyword is handled as a special value of timerId.
let { // local scope for variables myStatus and myTimerList var myStatus; var myTimerList; // for storing status values of timers // for storing a list of timer Bindings
if (timerId == any timer) { myTimerList := Entity.TIMER-STATE.first(); timerId := NULL; if (Entity.STATUS) == SNAPSHOT) { while (myTimerList != NULL && timerId == NULL) { timerId := myTimerList.random(SNAP-STATUS == RUNNING); myTimerList := Entity.TIMER-STATE.next(myTimerList); { } else { while (myTimerList != NULL && timerId == NULL) { timerId := myTimerList.random(STATUS == RUNNING); myTimerList := Entity.TIMER-STATE.next(myTimerList); { } } if (timerId != NULL) { myStatus := Entity.timerId.STATUS; if (Entity.STATUS == SNAPSHOT) { myStatus := Entity.timerId.SNAP-STATUS; } if (myStatus == RUNNING) { Entity.VALUE-STACK.push(true); } else { Entity.VALUE-STACK.push(false); } } else { Entity.VALUE-STACK.push(false); } } // end local scope Entity.NEXT-CONTROL(true); RETURN;
ETSI
141
9.43
self
Self operation
The flow graph segment <self-op> in figure 115 defines the execution of the self operation.
self-op
9.44
Send operation
The optional <receiver-spec> in the to clause refers to the receivers of the message. In case of a one-to one communication, the <receiver-spec> addresses a single entity (including the SUT or an entity within the SUT). In case of multicast or broadcast communication, the <receiver-spec> specifies a set or all test components or entities in the SUT connected via the specified port with the calling component. The flow graph segment <send-op> in figure 116 defines the execution of a send operation.
segment <send-op>
// A send operation may address one, // multiple (multicast and broadcast) // or no receiver entities.
ETSI
142
9.44.1
The flow graph segment <send-with-one-receiver-op> in figure 117 defines the execution of a send operation where the receiver is specified in form of an expression.
segment <send-with-one-receiver-op>
<expression>
let { var receiver := Entity.VALUE-STACK.top(); var portRef := Entity.portId.COMP-PORT-NAME; var remotePort := GET-REMOTE-PORT(Entity, portRef, receiver); if (remotePort == NULL) { ***DYNAMIC-ERROR***; // Remote port cannot be found } if (remotePort == SYSTEM) { // Port is mapped onto a port of the test system // reception of the reply by the SUT is outside // the scope of the operational semantics } else { // sending of message remotePort.enqueue(CONSTRUCT-ITEM(Entity, send, sendSpec)); } } // end of scope of receiver and remotePort Entity.VALUE-STACK.pop(); Entity.NEXT-CONTROL(true); RETURN; // clean value stack
ETSI
143
segment <send-with-multiple-receivers-op>
+(number) <expression> // Each expression shall evaluate // to a component reference or an // address value.
// i; // loop counter variable connection; // variable for connections in port states receiver; // variable for receiver component references // or receiver address values var localPort, remotePort; // variables for port references localPort := Entity.portId.COMP-PORT-NAME; // local port
if (Entity.VALUE-STACK.top() == all component) { connection := localPort.CONNECTIONS-LIST.next(connection); while (connection != NULL) { remotePort := connection.REMOTE-PORT-NAME; if (remotePort == SYSTEM) { // Port is mapped onto a port of the test system // reception of the reply by the SUT is outside // the scope of the operational semantics } else { // sending of call remotePort.enqueue(CONSTRUCT-ITEM(Entity, send, sendSpec)); } connection := localPort.CONNECTIONS-LIST.next(connection); } } else { for (i == 1; i <= number; i := i+1) { receiver := Entity.VALUE-STACK.top(); Entity.VALUE-STACK.pop(); // clean value stack remotePort := GET-REMOTE-PORT(Entity, localPort, receiver); if (remotePort == NULL) { ***DYNAMIC-ERROR***; // Remote port cannot be found } if (remotePort == SYSTEM) { // Port is mapped onto a port of the test system // reception of the reply by the SUT is outside // the scope of the operational semantics } else { // sending of call remotePort.enqueue(CONSTRUCT-ITEM(Entity, send, sendSpec)); } } } } // end of local scope Entity.NEXT-CONTROL(true); RETURN;
ETSI
144
9.44.2
The flow graph segment <send-without-receiver-op> in figure 118 defines the execution of a send operation without to-clause.
segment <send-without-receiver-op>
let { var portRef := Entity.portId.COMP-PORT-NAME; var remotePort := GET-REMOTE-PORT(Entity, portRef, NONE); if (remotePort == NULL) { ***DYNAMIC-ERROR***; // Remote port cannot be found } if (remotePort == SYSTEM) { // Port is mapped onto a port of the test system // reception of the reply by the SUT is outside // the scope of the operational semantics } else { // sending of message remotePort.enqueue(CONSTRUCT-ITEM(Entity, send, sendSpec)); } } // end of scope of remotePort
Entity.NEXT-CONTROL(true); RETURN;
9.45
Setverdict operation
The <verdicttype-expression> parameter of the setverdict operation is an expression that shall evaluate to a value of type verdicttype, i.e. none, pass, inconc or fail. The expression is evaluated before the setverdict operation is applied. The second optional parameter allows specifying a reason for setting a verdict. This reason does not contribute to the test behaviour and is therefore not considered in the operational semantics. The flow graph segment <setverdict-op> in figure 119 defines the execution of the setverdict operation.
ETSI
145
segment <setverdict-op>
<expression>
// // // //
The expression shall evaluate to a value of type verdicttype. The result of the evaluation is pushed onto the VALUE-STACK of Entity
if ( setverdict-op
} else { if (
} else { if (
9.46
The start component operation starts a component. Using a component reference identifies the component to be started. The reference may be stored in a variable or be returned by a function, i.e. it is an expression that evaluates to a component reference. The <function-name> denotes to the name of the function that defines the behaviour of the new component and <act-par-descr1>, , <act-par-descrn> provide the description of the actual parameter values of <function-name>. The descriptions of the actual parameters are provided in form of expressions that have to be evaluated before the call can be executed. The handling of formal and actual value parameters is similar to their handling in function calls (see clause 9.24). The flow graph segment <start-component-op> in figure 120 defines the execution of the start component operation. The start component operation is executed in four steps. In the first step a call record is created. In the second step the actual parameter values are calculated. In the third step the reference of the component to be started is retrieved, and, in the fourth step, control and call record are given to the new component. NOTE: The flow graph segment in figure 120 includes the handling of reference parameters (<ref-var-par-calc>). Reference parameters are needed to explain reference parameters of test cases. The operational semantics assumes that these parameters are handled by the MTC.
ETSI
146
segment <start-component-op>
construct-call-record (function-name)
*
<value-par-calculation>
// // // // //
For each pair (<f-par-Idi>, <act-parameter-desci>) the value of <act-parameter-desci is calculated and assigned to the corresponding field <f-par-Idi> in the call record. The call record is assumed to be the top element in the value stack.
*
<ref-var-par-calc>
// // // // //
This flow graph segment is also used to explain the execute statemnt. Test cases are allowed to have reference parameters. The operational semantics assumes that these parameters are owned (and updated) by the MTC.
<expression>
// The expression shall evaluate to a component reference. // It refers to the component to be started
control-trans-to-component (function-name) let { var toBeStarted := Entity.VALUE-STACK.top(); // toBeStarted is a local variable that stores the // identifier of the component to be started Entity.VALUE-STACK.pop(); // Removal of component reference. Afterwards the // call record is on top of the value stack toBeStarted.VALUE-STACK.push(Entity.VALUE-STACK.top(); // Call record is transferred to toBeStarted. Entity.VALUE-STACK.pop(); // Removal of the call record from the value stack // of the starting component (= Entity). toBeStarted.CONTROL-STACK.push(GET-FLOW-GRAPH(function-name)); // Control stack of toBeStarted is set to // the start node of its behaviour.
toBeStarted.STATUS := ACTIVE; // Control is given to toBeStarted if (DONE.member(toBeStarted)) { // Update DONE list DONE.delete(toBeStarted); } } // end of scope for variable toBeStarted Entity.NEXT-CONTROL(true);
ETSI
147
9.47
The flow graph segment <start-port-op> in figure 121 defines the execution of the start port operation.
segment <start-port-op> let { // Begin of local scope var portRef := NULL var portState := NULL; start-port-op (portId) if (portId == all port) { portState := ALL-PORT-STATES.first(); while (portState != NULL) { if (portState.OWNER == Entity) { portState.VALUE-QUEUE.clear(); portState.STATUS := STARTED } portState := ALL-PORT-STATES.next(portState); } } else { portRef := Entity.portId.COMP-PORT-NAME; GET-PORT(Entity, portRef).clear(); GET-PORT(Entity, portRef).STATUS := STARTED; } // End of socpe Entity.NEXT-CONTROL(true); RETURN;
9.48
The optional <float-expression> parameter of the timer start operation denotes the actual duration of the timer. If it is not provided, the default duration will be used by the start operation. The expression that shall evaluate to a value of type float. If provided, the expression shall be evaluated before the start operation is applied. The result of the evaluation is pushed onto the VALUE-STACK of Entity. The flow graph segment <start-timer-op> in figure 122 defines the execution of the start timer operation.
segment <start-timer-op>
<start-timer-op-default> OR <start-timer-op-duration>
ETSI
148
9.48.1
The flow graph segment <start-timer-op-default> in figure 123 defines the execution of the start timer operation with the default value.
segment <start-timer-op-default>
start-timer-op-default (timerId)
// The timer reference <timerId> is copied into the node // attributetimerId if (Entity.timerId.DEF-DURATION == NONE) { ***DYNAMIC-ERROR*** // Timer has no default duration } else { Entity.TIMER-SET(timerId, ACT-DURATION, Entity.timerId.DEF-DURATION); Entity.TIMER-SET(timerId, TIME-LEFT, Entity.timerId.DEF-DURATION); Entity.TIMER-SET(timerId, STATUS, RUNNING); } Entity.NEXT-CONTROL(true); RETURN;
ETSI
149
9.48.2
The flow graph segment <start-timer-op-duration> in figure 124 defines the execution of the start timer operation with a provided duration.
segment <start-timer-op-duration>
<expression>
// The expression shall evaluate // to a float. The result is pushed // onto VALUE-STACK.
start-timer-op-duration (timerId)
// The timer reference <timerId> is copied into the node // attribute timerId Entity.TIMER-SET(timerId, ACT-DURATION, Entity.VALUE-STACK.top()); Entity.TIMER-SET(timerId, TIME-LEFT, Entity.VALUE-STACK.top()); Entity.TIMER-SET(timerId, STATUS, RUNNING); Entity.VALUE-STACK.pop(); Entity.NEXT-CONTROL(true); RETURN; // clean VALUE-STACK
9.49
The stop component operation stops the specified component. All test components will be stopped, i.e. the test case terminates, if the MTC is stopped (e.g. mtc.stop) or stops itself (e.g. self.stop). The MTC may stop all parallel test components by using the all keyword, i.e. all component.stop. Stopped components created with an alive clause in the create operation are not removed from the test system. They can be restarted by using a start statement. Variables, ports, constants and timers owned by such a component, i.e. declared and defined in the corresponding component type definition, keep their status. A stop operation for a component created without an alive clause is semantically equivalent to a kill operation. The component is removed from the test system. A component to be stopped is identified by a component reference provided as expression, e.g. a value or value returning function. For simplicity, the keyword "all component" is considered to be special values of <component-expression>. The operations mtc and self are evaluated according to clauses 9.33 and 9.43. The flow graph segment <stop-component-op> in figure 125 defines the execution of the stop component operation.
ETSI
150
segment <stop-component-op> // The Expression shall evaluate // to a component reference. The // result is pushed onto VALUE-STACK
<expression>
<stop-all-comp>
if (Entity.VALUE-STACK.top() == 'all component') { Entity.VALUE-STACK.pop(); // clean value stack if (Entity != MTC) { ***DYNAMIC-ERROR*** // 'all' not allowed } else { Entity.NEXT-CONTROL(true); { } else { Entity.NEXT-CONTROL(false); } RETURN;
if (Entity.VALUE-STACK.top() == MTC) { Entity.VALUE-STACK.pop(); // clean value stack Entity.NEXT-CONTROL(true); } else { Entity.NEXT-CONTROL(false); } RETURN;
<kill-mtc> if (ALL-ENTITY-STATES.member(Entity.VALUE-STACK.top())) { Entity.NEXT-CONTROL(true); } else { if (DONE.member(Entity.VALUE-STACK.top())){ // NULL operation, component already stopped // or killed. Entity.VALUE-STACK.pop(); // clean value stack Entity.NEXT-CONTROL(false); } else { // component id has not been allocated ***DYNAMIC-ERROR*** { } RETURN;
decision
if (Entity.VALUE-STACK.top().KEEP-ALIVE == true)) { Entity.NEXT-CONTROL(true); // Component is not // removed from the // test system } else { Entity.NEXT-CONTROL(false); // Component is killed } RETURN;
true
false
<stop-alive-component> <kill-component>
ETSI
151
9.49.1 9.49.2
The <stop-alive-component> flow graph segment in figure 126 describes the stopping of a parallel test component, i.e. not the MTC or module control, which has been created with an alive clause. The effect is that the test case verdict TC-VERDICT and the list of terminated test components (DONE) are updated and that the component changes its status to BLOCKED. The <stop-alive-component> flow graph assumes that the identifier of the component to be stopped is on top of the value stack of the component that executes the segment.
segment <stop-alive-component>
stop-alive-component
let { // local scope var myEntity := Entity.VALUE-STACK.top(); var compVarScope := copy(myEntity.DATA-STATE.first()); var compTimerScope := copy(myEntity.TIMER-STATE.first()); var compPortScope := copy(myEntity.PORT-REF.first()); // for test continuation, if stop is executed by another component if (Entity != myEntity()) { Entity.VALUE-STACK.pop(); // clean value stack Entity.NEXT-CONTROL(true); } // Update test case verdict if (myEntitiy.E-VERDICT == fail or TC-VERDICT == fail) { TC-VERDICT := fail; } else { if (myEntity.E-VERDICT == inconc or TC-VERDICT == inconc) { TC-VERDICT := inconc; } else { if (myEntity.E-VERDICT == pass or TC-VERDICT == pass) { TC-VERDICT := pass; } } // Update of DONE DONE.append(myEntity);
// Update of DONE
// Update of component state myEntity.STATUS := BLOCKED; myEntity.CONTROL-STACK := NULL; myEntity.DEFAULT-LIST := NULL; myEntity.VALUE-STACK := NULL; // for component scope myEntity.VALUE-STACK.push(MARK); myEntity.TIMER-GUARD.STATUS := IDLE; myEntity.DATA-STATE := NULL myEntity.DATA-STATE.add(compVarScope); myEntity.TIMER-STATE := NULL; myEntity.TIMER-STATE.add(compTimerScope); myEntity.PORT-REF := NULL myEntity.PORT-REF.add(compPortScope); myEntity.SNAP-ALIVE := NULL; myEntity.SNAP-DONE := NULL; myEntity.SNAP-KILLED := NULL;
ETSI
152
9.49.3
The <stop-all-comp> flow graph segment in figure 127 describes the stopping of all parallel test components of a test case.
segment <stop-all-comp>
let { // local scope var myEntity := ALL-ENTITY-STATES.next(MTC); Entity.VALUE-STACK.push(MARK) while (myEntity != NULL) { Entity.VALUE-STACK.push(myEntity); myEntity := ALL-ENTITY-STATES.next(myEntity); } } // End of local scope Entity.NEXT-CONTROL(true); RETURN;
prepare-stop
true
false
<stop-alive-component>
<kill-component>
if (Entity.VALUE-STACK.top() == MARK) { // clean stack Entity.VALUE-STACK.pop(); Entity.NEXT-CONTROL(true); // end of loop } else { Entity.NEXT-CONTROL(false); } RETURN;
ETSI
153
9.50
stop
The effect of the stop execution statement depends on the entity that executes the stop execution statement: a) If stop is performed by the module control, the test campaign ends, i.e. all test components and the module control disappear from the module state. This is semantically similar to the execution of a kill statement by the module control. If the stop is executed by the MTC, the test case ends. All parallel test components and the MTC stop and are removed from the test system. The global test case verdict is updated and pushed onto the value stack of the module control. Control is given back to the module control. This is semantically similar to the execution of a kill statement by the MTC. If the stop is executed by a test component, the global test case verdict TC-VERDICT and the global DONE list are updated. If the test component is created with an alive clause. The status of the component is set to BLOCKED and it may be started again. Otherwise the component is removed from the test system.
b)
c)
The flow graph segment <stop-exec-stmt> in figure 128 describes the execution of the stop statement.
segment <stop-exec-stmt> decision true false if (Entity == CONTROL) { Entity .NEXT-CONTROL( true); } else { Entity .NEXT-CONTROL( false ); } RETURN; if (Entity == MTC ) { Entity .NEXT-CONTROL( true); } else { Entity .NEXT-CONTROL( false ); } RETURN; decision true false Entity. VALUE-STACK. push ( Entity); if (Entity .KEEP-ALIVE == true ) { Entity .NEXT-CONTROL ( true ); } else { Entity .NEXT-CONTROL ( false ); } RETURN;
<kill-control>
<kill-mtc> decision
<kill-component>
<stop-alive-component>
ETSI
154
9.51
The flow graph segment <stop-port-op> in figure 129 defines the execution of the stop port operation.
segment <stop-port-op> let { // Begin of local scope var portRef := NULL var portState := NULL; stop-port-op (portId) if (portId == all port) { portState := ALL-PORT-STATES.first(); while (portState != NULL) { if (portState.OWNER == Entity) { portState.STATUS := STOPPED } portState := ALL-PORT-STATES.next(portState); } } else { portRef := Entity.portId.COMP-PORT-NAME; GET-PORT(Entity, portRef).STATUS := STOPPED; } // End of socpe Entity.NEXT-CONTROL(true); RETURN;
ETSI
155
9.52
The flow graph segment <stop-timer-op> in figure 130 defines the execution of the stop timer operation. The all keyword is handled as a special value of timerId.
segment <stop-timer-op>
// The timer reference <timerId> is copied // into the node attribute timerId stop-timer-op (timerId) if (timerId == all timer) { Entity.TIMER-STATE.change.change(TIMER-SET(, STATUS, IDLE)); Entity.TIMER-STATE.change.change(TIMER-SET(, ACT-DURATION, 0.0); Entity.TIMER-STATE.change.change(TIMER-SET(, TIME-LEFT, 0.0); // Note, the first parameter of the TIMER-SET function is // ommitted, because it is applied to all timers in the // actual scope unit. } else { Entity.TIMER-SET(timerId, STATUS, IDLE); Entity.TIMER-SET(timerId, ACT-DURATION, 0.0); Entity.TIMER-SET(timerId, TIME-LEFT, 0.0); } Entity.NEXT-CONTROL(true); RETURN;
9.53
system
System operation
The flow graph segment <system-op> in figure 131 defines the execution of the system operation.
system-op
ETSI
156
9.53a
The behaviour of the test case stop operation is identical to the execution of a log statement (clause 9.31) followed by a dynamic error (clause 9.17.3). Flow graph segment <test-case-stop-op> in figure 131a defines the execution of the test case stop operation.
segment <test-case-stop-op>
<log-stmt>
<dynamic-error>
9.54
Timer declaration
The effect of a timer declaration is the creation of a new timer binding. The declaration of a default duration is optional. The default value is considered to be an expression that evaluates to a value of the type float. The flow graph segment <timer-declaration> in figure 132 defines the execution of a timer declaration.
segment <timer-declaration> <timer-decl-default> OR <timer-decl-no-def> // A timer may be declared with // or without a default duration
ETSI
157
9.54.1
The flow graph segment <timer-decl-default> in figure 133 defines the execution of a timer declaration where a default duration in form of an expression is provided.
segment <timer-decl-default>
<expression>
9.54.2
The flow graph segment <timer-decl-no-def> in figure 134 defines the execution of a timer declaration where no default duration is provided, i.e. the default duration of the timer is undefined.
ETSI
158
9.55
The flow graph segment <timeout-timer-op> in figure 135 defines the execution of the timeout timer operation.
segment <timeout-timer-op>
timeout-timer-op (timerId) // The timer reference <timerId> is copied // into the node attribute timerId let { // local scope for variable myTimerList var myTimerList; // to store a list of timer Bindings if (timerId == any timer) { myTimerList := Entity.TIMER-STATE.first(); timerId := NULL; while (myTimerList != NULL && timerId == NULL) { timerId := myTimerList.random(SNAP-STATUS == TIMEOUT); myTimerList := Entity.TIMER-STATE.next(myTimerList); { } if (timerId != NULL && Entity.timerId.SNAP-STATUS == TIMEOUT) { Entity.TIMER-SET(timerId, STATUS, IDLE); Entity.TIMER-SET(timerId, ACT-DURATION, 0.0); Entity.TIMER-SET(timerId, TIME-LEFT, 0.0); Entity.STATUS := ACTIVE; Entity.NEXT-CONTROL(true); } else { Entity.NEXT-CONTROL(false); } } // end of local scope
RETURN;
true
false
NOTE 1: A timeout operation is embedded in an alt statement. Its evaluation is based on the actual snapshot, i.e. the decision is based on the SNAP-STATUS entry in the timer binding. If the timeout operation is successful, i.e. SNAP-STATUS == TIMEOUT, the timer is set into an IDLE state and the component state changes from SNAPSHOT to ACTIVE. NOTE 2: When the timeout evaluates to true or false, either execution continues with the statement that follows the timeout operation (true branch), or the next alternative in the alt statement has to be checked (false branch). NOTE 3: The any keyword is treated like as special value of timerId.
ETSI
159
9.56
Unmap operation
The identifiers <portId1> and <portId2> are considered to be port identifiers of the corresponding test component and test system interface. The components to which the <portId1> belongs is referenced by means of the component reference <component-expression>. The reference may be stored in variables or is returned by a function, i.e. it is an expression, which evaluates to a component reference. The value stack is used for storing the component reference. The unmap operation can be used with one parameter pair and with two parameters pairs. The usage of the unmap operation with one parameter pair may unmap port mappings for one component or, if executed by the MTC for all components. The usage of the unmap operation with two parameter pairs allows to unmap one specific mapped port. The operational semantics does not model the ports in the abstract test system interface. Therefore, only the parameter pair that identifies the component (or components, if the all component keyword is used) and the corresponding port (or ports, if the all port keyword is used) has to be considered here. In the flow graph segment three cases are distinguished: 1) 2) 3) the mtc unmaps all mapped ports of all components; all mapped ports of one component are unmapped; and one port of one component is unmapped.
ETSI
160
The execution of the unmap operation is defined by the flow graph segment <unmap-op> shown in figure 136.
// The Expression shall evaluate // to a component reference. The // result is pushed onto VALUE-STACK
<unmap-all>
if (Entity . VALUE-STACK . top () == all component) { if ( ( Entity != MTC ) OR (Entity == MTC && portId != all port) ) { ***DYNAMIC-ERROR*** } else { Entity . VALUE-STACK . pop (); Entity . NEXT-CONTROL ( true ); } } else { Entity . VALUE-STACK . push (portId); Entity . NEXT-CONTROL ( false); } RETURN ;
<unmap-comp>
if (Entity . VALUE-STACK . top () != all port ) { Entity . VALUE-STACK . pop (); Entity . NEXT-CONTROL ( true ); } else { Entity . NEXT-CONTROL ( false); } RETURN ;
<unmap-port>
ETSI
161
9.56.1
The flow segment <unmap-all> defines the unmapping of all components at all mapped ports.
segment <unmap-all>
unmap-all
let { // local scope var port := ALL-PORT-STATES.first(); var connection; while (port != NULL) { connection := port.CONNECTIONS.first(); while (connection != NULL) { if (connection.REMOTE-ENTITY == system) { port.CONNECTIONS.delete(connection); connection := port.CONNECTIONS.first(); } else { connection := NULL; // connected port } } port := ALL-PORT-STATES.next(port) } } // End of local scope
Entity.NEXT-CONTROL(true); RETURN;
ETSI
162
9.56.2
The flow segment <unmap-comp> defines the unmapping of all mapped ports of a specified component.
segment <unmap-comp>
unmap-comp
let { // local scope var comp := Entity.VALUE-STACK.top(); var connection; var port := ALL-PORT-STATES.first(); while (port != NULL) { if (port.OWNER == comp) { // port of comp connection := port.CONNECTIONS.first(); if (connection.REMOTE-ENTITY == system) { // mapped port of comp port.CONNECTIONS.delete(connection); } } port := ALL-PORT-STATES.next(port); } // clear value stack Entity.VALUE-STACK.pop(); } // End of local scope Entity.NEXT-CONTROL(true); RETURN;
ETSI
163
9.56.3
The flow segment <unmap-port> defines the unmap operation for a specific mapped port.
segment <unmap-port>
unmap-port
let { // local scope var portId ; var comp; var port; var connection ; portId := Entity .VALUE-STACK .top (); Entity . VALUE-STACK . pop (); comp := Entity . VALUE-STACK . top (); Entity . VALUE-STACK . pop (); port := GET-PORT (comp, portId); connection := port . CONNECTIONS . first (); if (connection . REMOTE-ENTITY != SYSTEM ) { ***DYNAMIC-ERROR*** // port is not a mapped port } else if ( connection != NULL ){ port. CONNECTIONS .delete ( connection ); } else { ) // do nothing, port is neither connected nor mapped } // End of local scope Entity . NEXT-CONTROL ( true ); RETURN ;
9.57
Variable declaration
The initialization of a variable by providing an initial value (in form of an expression) is optional. The initial value is considered to be an expression that evaluates to a value of the type of the variable.
ETSI
164
The flow graph segment <variable-declaration> in figure 137 defines the execution of the declaration of a variable.
segment <variable-declaration> <var-declaration-init> OR <var-declaration-undef> // A variable may be declared with // or without initial value
9.57.1
The flow graph segment <var-declaration-init> in figure 138 defines the execution of a variable declaration where an initial value in form of an expression is provided.
segment <var-declaration-init>
<expression>
// The expression shall evaluate // to a value of the type of the // variable that is declared.
ETSI
165
9.57.2
The flow graph segment <var-declaration-undef> in figure 139 defines the execution of a variable declaration where no initial value is provided, i.e. the value of the variable is undefined.
9.58
While statement
<statement-block>
The execution of a while statement is defined by the flow graph segment <while-stmt> shown in figure 140.
segment <while-stmt>
<expression>
<statement-block>
ETSI
166
10
10.1
Name ACT-DURATION add ADD-CON ALL-ENTITY-STATES ALL-PORT-STATES append APPLY-OPERATOR change clear clear clear-until CONNECTIONS-LIST CONSTRUCT-ITEM CONTINUECOMPONENT CONTROL-STACK DATA-STATE DEF-DURATION DEFAULT-LIST DEFAULT-POINTER DEL-CON DEL-ENTITY DEL-TIMER-SCOPE DEL-VAR-SCOPE delete dequeue DONE E-VERDICT enqueue first first GET-FLOW-GRAPH GET-PORT GET-REMOTE-PORT GET-TIMER-LOC GET-UNIQUE-ID GET-VAR-LOC INIT-CALL-RECORD INIT-FLOW-GRAPHS INIT-TIMER INIT-TIMER-LOC INIT-TIMER-SCOPE INIT-VAR INIT-VAR-LOC INIT-VAR-SCOPE length M-CONTROL MATCH-ITEM member MTC NEW-CALL-RECORD NEW-ENTITY NEW-PORT NEXT next
ETSI
ETSI ES 201 873-4 V4.4.1 (2012-04) Clause 8.3.2.1 8.3.3 8.3.2.1 8.3.3 8.3.2.1 8.3.1a.1 8.3.3.1 8.3.3.1 8.4.6 8.6.2 8.3.2 8.3.3.2 8.3.2.4 8.3.2.5 8.3.2.4 8.3.3 8.3.2 8.3.2.4 8.3.3 8.3.1 8.3.2.4 8.3.2 8.3.2.4 8.3.2.5 8.3.2 8.3.2.1 8.3.4 8.3.2.2 8.3.3 8.3.2 8.3.2.2 8.3.2.3 8.6.2 8.3.2 8.3.2.2, 8.3.2.4
Description Pops the top flow graph node from the control stack and pushes the next flow graph node onto the control stack. OWNER Owner of a port pop Stack operation "pop": pops an item from a stack PORT-NAME Name of a port push Stack operation "push": pushes an item onto a stack random List operation: returns randomly an element of a list REMOTE-ENTITY Remote entity in a connection in a port state REMOTE-PORT-NAME Name of a port in a connection in a port state RETRIEVE-INFO Retrieves information from a received message, call, reply or exception RETURN Returns the control to the module evaluation procedure SNAP-DONE List of terminated test components at the time when a snapshot is taken SNAP-PORTS Provides the snapshot functionality, i.e. updates the SNAP-VALUE SNAP-STATUS Snapshot status of a timer SNAP-TIMER Provides the snapshot functionality and updates SNAP-VALUE and SNAPSTATUS SNAP-VALUE Snapshot value of a timer SNAP-VALUE For snapshot semantics, updated when a snapshot is taken Status (ACTIVE, BREAK, SNAPSHOT, REPEAT or BLOCKED) of module STATUS control or a test component Status (IDLE, RUNNING or TIMEOUT) of a timer STATUS Status (STARTED, HALTED or STOPPED) of a port STATUS TC-VERDICT Test case verdict in module state TIME-LEFT Time a running timer has left to run before it times out Timer that guards execute statements and call operations TIMER-GUARD TIMER-NAME Name of a timer TIMER-SET Setting values of a timer TIMER-STATE Timer state in an entity state top Stack operation "top": returns the top item from a stack UPDATE-REMOTEUpdates timers and variables with the same location in different entities to REFERENCES the same value VALUE Value of a variable. VALUE-QUEUE Port queue VALUE-STACK Stack of values for the storage of results of expressions, operands, operations and functions VAR-NAME Name of a variable VAR-SET Setting the value of a variable ***DYNAMIC-ERROR*** Describes the occurrence of a dynamic error <identifier> Unique identifier of a test component <location> Supports scope units, reference and timer parameters. Represents a storage location for timers and variables
10.2
Special keywords
Description STATUS of an entity state STATUS of an entity state STATUS of an entity state STATUS of a port Used as marker in a port queue STATUS of a timer state Used as mark for VALUE-STACK Used to describe an undefined value Symbolic value for pointer and pointer-like types to indicate that nothing is addressed STATUS of an entity state STATUS of a timer state STATUS of an entity state STATUS of a port STATUS of a port STATUS of a timer state Clause 8.3.2 8.3.2 8.3.2 8.3.3 8.3.3, 9.28a 8.3.2.4 8.3.2 8.3.2.3, 8.3.2.5, 8.3.3.2 8.3.1a.1, 8.3.2.1, 8.3.3, 8.3.3.2, 8.6.1.1 8.3.2 8.3.2.4 8.3.2 8.3.3 8.3.3 8.3.2.4
Keyword ACTIVE BLOCKED BREAK HALTED HALT-MARKER IDLE MARK NONE NULL REPEAT RUNNING SNAPSHOT, STARTED STOPPED TIMEOUT
ETSI
168
10.3
10.4
<action-stmt> <activate-stmt> <alive-component-op> <alive-comp-act> <alive-comp-snap> <alt-stmt> <altstep-call> <altstep-call-branch> <assignment-stmt> <b-call-with-duration> <b-call-without-duration> <blocking-call-op> <break-altstep-stmt> <call-op> <call-reception-part> <catch-op> <catch-timeout-exception> <check-op> <check-with-sender> <check-without-sender> <checkstate-port-op> <check-port-status> <check-port-connection> <clear-port-op> <connect-op> <constant-definition> <create-op> <deactivate-all-defaults> <deactivate-one-default> <deactivate-stmt> <default-evocation> <disconnect-op> <disconnect-one-par-pair> <disconnect-all> <disconnect-comp> <disconnect-port> <disconnect-two-par-pairs> <do-while-stmt> <done-op> <dynamic-error> <else-branch> <execute-stmt> <execute-timeout> <execute-without-timeout> <expression> <finalize-component-init>
ETSI
ETSI ES 201 873-4 V4.4.1 (2012-04) Reference Figure Clause 79 9.23 73 9.18.3 80 9.24 86 9.25 87 9.26 88 9.27 89 9.28 89a 9.28a 90 9.29 76 9.20 76a 9.20a 76b 9.20b 90d 9.29a.3 90c 9.29a.2 90a 9.29a 90f 9.29b.1 90e 9.29b 90b 9.29a.1 90g 9.29c 91 9.30 71 9.18.1 92 9.31 93 9.32 94 9.33 50 9.6.2 49 9.6.1 49a 9.6.1a 48 74 77 95 85 96 97 97a 98 99 103 100 101 102 40 83a 83 82 104 105 106 106a 107 108 109 110 111 112 113 114 9.6 9.18.4 9.21 9.34 9.24.5 9.35 9.35.1 9.35.1a 9.35.2 9.36 9.37.3 9.37 9.37.1 9.37.2 9.3.2 9.24.3.a 9.24.3 9.24.2 9.38 9.39 9.39.1 9.39.1a 9.39.2 9.40 9.40.1 9.40.2 9.41 9.41.1 9.41.2 9.42
Related TTCN-3 construct for statement expression call of a function getcall operation getreply operation getverdict operation goto statement halt port operation if-else statement used in component type definitions used in function and altstep definitions used in function and altstep definitions kill component operation kill component operation kill component operation kill execution statement kill execution statement kill component operation killed component operation label statement expression log statement map operation mtc operation call operation call operation call operation call operation expression handling of parameters of functions, altsteps and test cases port declaration call of a function (call of a pre-defined or external function) raise operation raise operation raise operation raise operation read timer operation receive operation receive operation receive operation receive operation alt statement call of a function (handling of port parameters) call of a function (handling of timer parameters) call of a function (handling of reference parameters) repeat statement reply operation reply operation reply operation reply operation return statement return statement return statement component running operation component running operation component running operation timer running operation
<if-else-stmt> <init-component-scope> <init-scope-with-runs-on> <init-scope-without-runs-on> <kill-all-comp> <kill-component> <kill-component-op> <kill-control> <kill-exec-stmt> <kill-mtc> <killed-op> <label-stmt> <lit-value> <log-stmt> <map-op> <mtc-op> <nb-call-without-receiver> <nb-call-with-one-receiver> <nb-call-with-multiplereceivers> <non-blocking-call-op> <operator-appl> <parameter-handling> <port-declaration> <predef-ext-func-call> <raise-op> <raise-with-one-receiver-op> <raise-with-multiple-receiversop> <raise-without-receiver-op> <read-timer-op> <receive-assignment> <receive-op> <receive-with-sender> <receive-without-sender> <receiving-branch> <ref-par-port-calc> <ref-par-timer-calc> <ref-par-var-calc> <repeat-stmt> <reply-op> <reply-with-one-receiver-op> <reply-with-multiple-receiversop> <reply-without-receiver-op> <return-stmt> <return-with-value> <return-without-value> <running-component-op> <running-comp-act> <running-comp-snap> <running-timer-op>
ETSI
170 Identifier <self-op> <send-op> <send-with-one-receiver-op> <send-with-multiple-receiversop> <send-without-receiver-op> <setverdict-op> <start-component-op> <start-port-op> <start-timer-op> <start-timer-op-default> <start-timer-op-duration> <statement-block> <stop-component-op> <stop-alive-component> <stop-all-comp> <stop-exec-stmt> <stop-port-op> <stop-timer-op> <system-op> <take-snapshot> <test-case-stop-op> <timer-declaration> <timer-decl-default> <timer-decl-no-def> <timeout-timer-op> <unmap-op> <unmap-all> <unmap-comp> <unmap-port> <user-def-func-call> <value-par-calculation> <var-declaration-init> <var-declaration-undef> <var-value> <variable-declaration> <while-stmt> self operation send operation send operation send operation send operation setverdict operation start component operation start port operation start timer operation start timer operation start timer operation block of statements in compound statements stop component operation stop component operation stop component operation (all component.stop) stop execution statement stop port operation stop timer operation system operation alt statement test case stop operation timer declaration timer declaration timer declaration timeout operation unmap operation unmap operation unmap operation unmap operation call of a function (call of a user-defined function) call of a function (handling of value parameters) variable declaration variable declaration expression variable declaration while statement Related TTCN-3 construct
ETSI ES 201 873-4 V4.4.1 (2012-04) Reference Figure Clause 115 9.43 116 9.44 117 9.44.1 117a 9.44.1a 118 119 120 121 122 123 124 78 125 126 127 128 129 130 131 39 131a 132 133 134 135 136 136a 136b 136c 84 81 138 139 72 137 140 9.44.2 9.45 9.46 9.47 9.48 9.48.1 9.48.2 9.22 9.49 9.49.2 9.49.3 9.50 9.51 9.52 9.53 9.3.1 9.53a 9.54 9.54.1 9.54.2 9.55 9.56 9.56.1 9.56.2 9.56.3 9.24.4 9.24.1 9.57.1 9.57.2 9.18.2 9.57 9.58
ETSI
171
History
Document history
V2.2.1 V3.1.1 V3.2.1 V3.3.1 V3.4.1 V4.1.1 V4.2.1 V4.4.0 V4.4.1 February 2003 June 2005 February 2007 April 2008 September 2008 June 2009 July 2010 February 2012 April 2012 Publication Publication Publication Publication Publication Publication Publication Membership Approval Procedure Publication MV 20120401: 2012-02-01 to 2012-04-02
ETSI