UML Checker: Formal Specification in VDM++ of the Petri Net … · 2014-10-25 · UML Checker:...

42
UML Checker: Formal Specification in VDM++ of the Petri Net-based Conformance Checking Engine TR-SDBT-2013-04, SERG, FEUP, December 2013 João Pascoal Faria 1, 2 , Ana C. R. Paiva 1 1 Software Engineering Research Group, Department of Informatics Engineering, Faculty of Engineering of the University of Porto, Porto, Portugal 2 INESC TEC, Porto, Portugal [email protected], [email protected] Contents 1 Introduction ..................................................................................................................................................... 2 2 Preliminaries .................................................................................................................................................... 2 2.1 Values ..................................................................................................................................................... 2 2.2 Variables ................................................................................................................................................. 2 2.3 Value specifications ................................................................................................................................ 3 3 Interactions (Sequence Diagrams) ................................................................................................................... 4 4 Petri Nets ......................................................................................................................................................... 7 5 Conversion of Interactions to Petri Nets .......................................................................................................... 8 5.1 Introduction and semantic options .................................................................................................................. 8 5.2 Place generation.............................................................................................................................................. 8 5.3 Transition generation .................................................................................................................................... 10 5.4 Main conversion logic .................................................................................................................................. 19 6 Petri Net Execution ........................................................................................................................................ 19 6.1 Definition of execution traces ....................................................................................................................... 19 6.2 Definition of run states ................................................................................................................................. 19 6.3 Matching and binding values and messages ................................................................................................. 20 6.4 Operations on markings ................................................................................................................................ 21 6.5 Operations on transitions .............................................................................................................................. 21 6.6 Main execution logic .................................................................................................................................... 22 7 Test Cases ...................................................................................................................................................... 24 7.1 Convenience definitions ........................................................................................................................ 24 7.2 Simple asynchronous message .............................................................................................................. 25 7.3 Weak sequencing .................................................................................................................................. 25 7.4 ATM example with synchronous messages, 'alt' and 'par' .................................................................... 27 7.5 Asynchronous user interaction .............................................................................................................. 30 7.6 Loops with synchronous messages ....................................................................................................... 31 7.7 Loops with asynchronous messages ..................................................................................................... 32 7.8 Break ..................................................................................................................................................... 34 7.9 General ordering ................................................................................................................................... 35 7.10 Co-region .............................................................................................................................................. 36 7.11 Critical region ....................................................................................................................................... 37 7.12 Interaction use ....................................................................................................................................... 39 7.13 Assert and negate fragments ................................................................................................................. 39 7.14 Consider and ignore fragments ............................................................................................................. 41 7.15 Test execution ....................................................................................................................................... 42 8 Conclusion ..................................................................................................................................................... 42 References .............................................................................................................................................................. 42

Transcript of UML Checker: Formal Specification in VDM++ of the Petri Net … · 2014-10-25 · UML Checker:...

Page 1: UML Checker: Formal Specification in VDM++ of the Petri Net … · 2014-10-25 · UML Checker: Formal Specification in VDM++ of the Petri Net-based Conformance Checking Engine TR-SDBT-2013-04,

UML Checker: Formal Specification in VDM++ of the Petri Net-based

Conformance Checking Engine

TR-SDBT-2013-04, SERG, FEUP, December 2013

João Pascoal Faria 1, 2, Ana C. R. Paiva 1

1 Software Engineering Research Group, Department of Informatics Engineering,

Faculty of Engineering of the University of Porto, Porto, Portugal 2 INESC TEC, Porto, Portugal

[email protected], [email protected]

Contents 1 Introduction ..................................................................................................................................................... 2 2 Preliminaries .................................................................................................................................................... 2

2.1 Values ..................................................................................................................................................... 2 2.2 Variables ................................................................................................................................................. 2 2.3 Value specifications ................................................................................................................................ 3

3 Interactions (Sequence Diagrams) ................................................................................................................... 4 4 Petri Nets ......................................................................................................................................................... 7 5 Conversion of Interactions to Petri Nets .......................................................................................................... 8

5.1 Introduction and semantic options .................................................................................................................. 8 5.2 Place generation.............................................................................................................................................. 8 5.3 Transition generation .................................................................................................................................... 10 5.4 Main conversion logic .................................................................................................................................. 19

6 Petri Net Execution ........................................................................................................................................ 19 6.1 Definition of execution traces ....................................................................................................................... 19 6.2 Definition of run states ................................................................................................................................. 19 6.3 Matching and binding values and messages ................................................................................................. 20 6.4 Operations on markings ................................................................................................................................ 21 6.5 Operations on transitions .............................................................................................................................. 21 6.6 Main execution logic .................................................................................................................................... 22

7 Test Cases ...................................................................................................................................................... 24 7.1 Convenience definitions ........................................................................................................................ 24 7.2 Simple asynchronous message .............................................................................................................. 25 7.3 Weak sequencing .................................................................................................................................. 25 7.4 ATM example with synchronous messages, 'alt' and 'par' .................................................................... 27 7.5 Asynchronous user interaction .............................................................................................................. 30 7.6 Loops with synchronous messages ....................................................................................................... 31 7.7 Loops with asynchronous messages ..................................................................................................... 32 7.8 Break ..................................................................................................................................................... 34 7.9 General ordering ................................................................................................................................... 35 7.10 Co-region .............................................................................................................................................. 36 7.11 Critical region ....................................................................................................................................... 37 7.12 Interaction use ....................................................................................................................................... 39 7.13 Assert and negate fragments ................................................................................................................. 39 7.14 Consider and ignore fragments ............................................................................................................. 41 7.15 Test execution ....................................................................................................................................... 42

8 Conclusion ..................................................................................................................................................... 42 References .............................................................................................................................................................. 42

Page 2: UML Checker: Formal Specification in VDM++ of the Petri Net … · 2014-10-25 · UML Checker: Formal Specification in VDM++ of the Petri Net-based Conformance Checking Engine TR-SDBT-2013-04,

UML Checker: Formal Specification in VDM++ 2

1 Introduction

This document contains a formal specification of the conformance checking engine of the UML Checker toolset

based on Extended Petri Nets presented in our paper ‎[4]. The specification is written in VDM++ ‎[2]. This

documented (RTF version) can be executed with the VDM++ Toolbox.

All the specification is organized inside a single class (classes are required by VDM++), although the specification

follows a functional style.

class UMLChecker

Whenever possible or convenient, we follow the names used in the UML specification ‎[3].

2 Preliminaries

Value specifications (‎‎[3], page 139) are used in UML sequence diagrams for specifying message parameters, target

objects, return values and guard conditions. By contrast, values occur at run-time. Value specifications are also

generated in our approach in the translating of sequence diagrams to Extended Petri Nets, to represent additional

guards in transitions and expressions in transition arcs.

2.1 Values types

-- these are the kinds of values we need ...

public Value = Primitive | Instance | OccurrenceGroupId;

public Primitive = nat | bool | real | string;

public string = seq of char;

-- a run-time instance of a class

public Instance :: className : string

object : token; -- a VDM token may contain anything

-- an identifier for a group of runtime occurrences (send/receive or call/reply

-- pair), encapsulated in a record type to be distinguishable from other nats

public OccurrenceGroupId :: id: nat;

functions

-- Checks if a type is a subtype of another type

-- Here only checks that they are same type (enough for prototyping).

private isSubtype(type1 : string, type2: string) r : bool ≜ type1 = type2;

2.2 Variables types

-- these are the kinds of variables we need ...

public Variable = Lifeline | Parameter | PNVariable;

-- a Petri Net variable used with the scope of a single transition

public PNVariable :: string;

Page 3: UML Checker: Formal Specification in VDM++ of the Petri Net … · 2014-10-25 · UML Checker: Formal Specification in VDM++ of the Petri Net-based Conformance Checking Engine TR-SDBT-2013-04,

UML Checker: Formal Specification in VDM++ 3

-- a lifeline representing a classifier or a named instance

-- (to be bound to an actual instance during execution)

public Lifeline ::

className : string

instanceName : [string];

-- an interaction parameter (identified by its name)

public Parameter ::

name: string

direction: ParameterDirectionKind;

public ParameterDirectionKind = <InParam> | <OutParam>;

-- Bindings of variables to actual values

public Bindings = map Variable to Value;

functions

-- Bind a variable to a value, updating the set of bindings

private bind(var: Variable, val: Value, b: Bindings) r: Bindings ≜

b ++ {var val};

2.3 Value specifications types

-- these are the kinds of value specifications we need ...

public ValueSpecification = Value | Variable | Expression | <Unknown>;

public Expression :: symbol: ExpSymbol

operands: seq of [ValueSpecification];

-- there are the kinds of expression symbols we need

public ExpSymbol = <Neg> | <Eq> | <Plus> | <Minus> | <Lt> | <Lte> | <Gt> | <Gte>

| <And> | <Or>;

functions

-- evaluates a value specification, given bindings of variables to values

private eval(vs: ValueSpecification, b: Bindings) r: [Value] ≜ cases true:

(is_Lifeline(vs) is_Parameter(vs)

is_PNVariable(vs)) -> if vs dom b then b(vs) else nil,

(vs = <Unknown>) -> nil, -- shouldn't be evaluated ...

(is_Expression(vs)) ->

cases vs.symbol:

<Neg> -> eval(vs.operands(1), b),

<Eq> -> eval(vs.operands(1), b) = eval(vs.operands(2), b),

<And> -> op elems vs.operands eval(op, b) = true,

<Or> -> op elems vs.operands eval(op, b) = false,

<Plus> -> eval(vs.operands(1), b) + eval(vs.operands(2), b),

<Minus> -> eval(vs.operands(1), b) - eval(vs.operands(2), b),

<Lt> -> eval(vs.operands(1), b) < eval(vs.operands(2), b),

<Lte> -> eval(vs.operands(1), b) eval(vs.operands(2), b),

<Gt> -> eval(vs.operands(1), b) > eval(vs.operands(2), b),

<Gte> -> eval(vs.operands(1), b) eval(vs.operands(2), b)

Page 4: UML Checker: Formal Specification in VDM++ of the Petri Net … · 2014-10-25 · UML Checker: Formal Specification in VDM++ of the Petri Net-based Conformance Checking Engine TR-SDBT-2013-04,

UML Checker: Formal Specification in VDM++ 4

end,

(is_OccurrenceGroupId(vs)) -> vs.id,

other -> vs -- Value

end;

-- Matches a value against a value specification, considering a set of variable

-- bindings. Returns a tuple with a success flag and the new bindings.

private matchAndBindVal(actual: [Value], expected: [ValueSpecification], b:

Bindings) r : bool Bindings ≜ cases true:

(expected = nil) -> mk_(actual = nil, b),

(expected = <Unknown>) -> mk_(true, b),

(is_Lifeline(expected))->

if actual = nil is_Instance(actual)

then mk_(false, b)

else if expected dom b

then mk_(b(expected) = actual, b)

else if isSubtype(actual.className, expected.className)

then mk_(true, bind(expected, actual, b))

else mk_(false, b),

(is_Parameter(expected) is_PNVariable(expected)) ->

if expected dom b

then mk_(b(expected) = actual, b)

else mk_(true, bind(expected, actual, b)),

others -> mk_(eval(expected, b) = actual, b)

end;

private replace(vs: ValueSpecification, rep: map ValueSpecification to

[ValueSpecification]) r: ValueSpecification ≜

if vs dom(rep) then rep(vs)

else if is_Expression(vs)

then mk_Expression(vs.symbol,[replace(vs.operands(i), rep) |

i inds vs.operands])

else vs;

3 Interactions (Sequence Diagrams)

In UML, a sequence diagram is a visual representation of an Interaction.

types

-- order number (not necesserily consecutive) for an event in a Lifeline,

-- such as send/receive message, begin/end combined fragment or operand

-- (can be assigned using the y-coordinate)

public Location = nat;

public MessageId = nat;

public Gate ::

name : nat;

public MessageSignature = string;

public LifelineLocation = Lifeline Location;

-- message sorts defined in the UML standard

public MessageSort = <synchCall> | <asynchCall> | <asynchSignal> |

<createMessage> | <reply>;

Page 5: UML Checker: Formal Specification in VDM++ of the Petri Net … · 2014-10-25 · UML Checker: Formal Specification in VDM++ of the Petri Net-based Conformance Checking Engine TR-SDBT-2013-04,

UML Checker: Formal Specification in VDM++ 5

public Message ::

id : MessageId -- connector id

groupId : nat -- to identify pairs call/reply messages

source : LifelineLocation

target : LifelineLocation

messageSort : MessageSort

signature : MessageSignature

arguments : seq of ValueSpecification; -- return value if reply message

public InteractionConstraint ::

minint : [ValueSpecification] -- loop

maxint : [ValueSpecification] -- loop

specification: [ValueSpecification] | <else>;

-- interaction operators defined in the UML standard

public InteractionOperatorKind = <seq> | <alt> | <opt> | <par> | <strict> | <loop>

| <break> | <critical> | <assert> | <neg> | <consider> | <ignore>;

public InteractionOperand ::

guard : [InteractionConstraint]

startLocations : set of LifelineLocation

finishLocations : set of LifelineLocation;

public CombinedFragment ::

id : nat

interactionOperator : InteractionOperatorKind

operands : seq1 of InteractionOperand

lifelines : set of Lifeline

inv f ≜ cases f.interactionOperator:

<loop>, <opt>, <break>, <critical>, <assert>, <neg> -> len f.operands = 1,

<alt>, <par>, <strict>, <seq> -> len f.operands 1

end

( o elems f.operands

{lf | mk_(lf, -) o.startLocations} = f.lifelines

{lf | mk_(lf, -) o.finishLocations} = f.lifelines)

( i {1, ..., len f.operands - 1}

f.operands(i+1).startLocations = f.operands(i).finishLocations);

public ConsiderIgnoreFragment::

id : nat

interactionOperator : InteractionOperatorKind -- consider ignore

lifelines : set of Lifeline

messages : set of MessageSignature

startLocations : set of LifelineLocation

finishLocations : set of LifelineLocation;

public GeneralOrdering ::

before : LifelineLocation

after : LifelineLocation;

public InteractionUse ::

id : nat

refersTo : Interaction

arguments : seq of ValueSpecification

lifelines : set of Lifeline

locations : set of LifelineLocation;

Page 6: UML Checker: Formal Specification in VDM++ of the Petri Net … · 2014-10-25 · UML Checker: Formal Specification in VDM++ of the Petri Net-based Conformance Checking Engine TR-SDBT-2013-04,

UML Checker: Formal Specification in VDM++ 6

public Interaction ::

lifelines : set of Lifeline

messages : set of Message

combinedFragments : set of CombinedFragment

generalOrderings : set of GeneralOrdering

interactionUses : set of InteractionUse

considerIgnoreFragments: set of ConsiderIgnoreFragment

parameters : seq of Parameter;

functions

-- Get all lifeline locations in an interaction

private getLifelineLocations(sd: Interaction) r: set of LifelineLocation ≜

{m.source | m sd.messages}

∪ {m.target | m sd.messages}

∪ ⋃ {⋃ {o.startLocations ∪ o.finishLocations | o elems f.operands}

| f sd.combinedFragments}

∪ ⋃ {r.locations | r sd.interactionUses};

-- Get the lifeline location that refers to a lifeline

private getLoc(locs: set of LifelineLocation, lf: Lifeline) r : LifelineLocation

≜ iota loc locs loc.#1 = lf;

private contains(f: CombinedFragment, loc: LifelineLocation) r: bool ≜

loc.#1 f.lifelines

loc.#2>getLoc(f.operands(1).startLocations, loc.#1).#2

loc.#2<getLoc(f.operands(len f.operands).finishLocations, loc.#1).#2;

private contains(f1: CombinedFragment, f2: CombinedFragment) r: bool ≜

f2.lifelines ⊆ f1.lifelines

( loc f2.operands(1).startLocations

getLoc(f1.operands(1).startLocations, loc.#1).#2 < loc.#2)

( loc f2.operands(len f2.operands).finishLocations

getLoc(f1.operands(len f1.operands).finishLocations, loc.#1).#2

> loc.#2);

private container(sd: Interaction, f: CombinedFragment) r: [CombinedFragment]

≜ let ff = {f2 | f2 sd.combinedFragments contains(f2, f)}

in if ff = {} then nil

else iota f2 ff f3 ff contains(f2, f3);

private contains(f1: ConsiderIgnoreFragment, f2: ConsiderIgnoreFragment) r:

bool ≜

f2.lifelines ⊆ f1.lifelines

( loc f2. startLocations

getLoc(f1. startLocations, loc.#1).#2 < loc.#2)

( loc f2.finishLocations

getLoc(f1.finishLocations, loc.#1).#2 > loc.#2);

private contains(f: ConsiderIgnoreFragment, loc: LifelineLocation) r: bool ≜

loc.#1 f.lifelines

Page 7: UML Checker: Formal Specification in VDM++ of the Petri Net … · 2014-10-25 · UML Checker: Formal Specification in VDM++ of the Petri Net-based Conformance Checking Engine TR-SDBT-2013-04,

UML Checker: Formal Specification in VDM++ 7

loc.#2 > getLoc(f.startLocations, loc.#1).#2

loc.#2 < getLoc(f.finishLocations, loc.#1).#2;

4 Petri Nets

In our approach, for the incremental conformance checking, we first translate sequence diagrams to Coloured Petri

Nets with inhibitor arcs, reset arcs and LIFO/FIFO places. Here we define such nets.

types

public PlaceType = <FIFOPlace> | <LIFOPlace> | <CountingPlace> | <CriticalPlace>

| <FailurePlace>;

public Place ::

id: nat

type: PlaceType;

-- The events of interest here are related with message sending and receiving.

public EventType = <Send> | <Receive> | <Call> | <Reply> | <AnyEvent> |

<AnySignatureInSet> | <AnySignatureNotInSet>;

public Event ::

type : EventType

message : [Message | set of MessageSignature]

inv e ≜ e.type = <AnyEvent> e.message = nil;

public Label ::

event : [Event]

guard : [ValueSpecification];

public Transition ::

source : map Place to [ValueSpecification]

label : [Label]

target : map Place to [ValueSpecification]

inhibitor: set of Place

resetArcs: set of Place

inv t ≜ t.source {} t.target {};

public PetriNet ::

places : set of Place

starts : Place

finish : set of Place

transitions: set of Transition

inv a ≜ a.starts a.places

a.finish ⊆ a.places

t a.transitions

dom t.source ⊆ a.places

t.inhibitor ⊆ a.places

dom t.target ⊆ a.places;

functions

private mkTransition(source: map Place to [ValueSpecification], label:

[Label],

Page 8: UML Checker: Formal Specification in VDM++ of the Petri Net … · 2014-10-25 · UML Checker: Formal Specification in VDM++ of the Petri Net-based Conformance Checking Engine TR-SDBT-2013-04,

UML Checker: Formal Specification in VDM++ 8

target : map Place to [ValueSpecification], inhibitor: set of Place) r :

Transition ≜ mk_Transition(source, label, target, inhibitor, {});

private incoming(a: PetriNet, p: Place) r: set of Transition ≜

{t | t a.transitions p dom t.target};

private outgoing(a: PetriNet, p: Place) r: set of Transition ≜

{t | t a.transitions p dom t.source};

instance variables

private static placeCounter : nat := 0;

operations

public static newPlace(type: PlaceType) res: Place ≜ (

placeCounter := placeCounter + 1;

return mk_Place(placeCounter, type)

);

5 Conversion of Interactions to Petri Nets

5.1 Introduction and semantic options

Two semantic options are supported in the conversion of Interactions to PetriNets, with without lifeline

synchronize at decision points of 'alt', 'opt', 'loop' or 'break' combined fragments.

values

public synchronizeLifelinesAtDecisionPoints : bool = false;

5.2 Place generation functions

-- auxliary function to sort locations in the same lifeline

private sortLocs(locs: set of LifelineLocation) r: seq of LifelineLocation ≜ if locs={} then []

else let loc1 locs be st loc2 locs loc2.#2 < loc1.#2

in [loc1] ↷ sortLocs(locs \ {loc1});

-- Generates a mapping of locations in a single lifeline to before/after places

private mapLocationsLf(locs: set of LifelineLocation) r: map LifelineLocation

to (Place Place) ≜

if locs = {} then {}

else let locs2 = sortLocs(locs),

places = [newPlace(<CountingPlace>) | i {1, ...,len locs2+1}]

in {locs2(i) mk_(places(i), places(i+1)) | i inds locs2};

Page 9: UML Checker: Formal Specification in VDM++ of the Petri Net … · 2014-10-25 · UML Checker: Formal Specification in VDM++ of the Petri Net-based Conformance Checking Engine TR-SDBT-2013-04,

UML Checker: Formal Specification in VDM++ 9

-- Generates a mapping of locations to before/after places

private mapLocations(locs: set of LifelineLocation) r: map LifelineLocation to

(Place Place) ≜

if locs = {} then { }

else let loc locs

in let locsLf = {l | l locs l.#1 = loc.#1}

in mapLocationsLf(locsLf) munion mapLocations(locs \ locsLf);

-- Generates a mapping from messages to related queuing places

private mapMessages(msgs: set of Message) r: map Message to Place ≜

if msgs = {} then { }

else let m msgs

in let t = if m.messageSort {<asynchCall>, <asynchSignal>}

then <FIFOPlace> else <LIFOPlace>

in {m newPlace(t)} munion mapMessages(msgs \ {m});

-- Generates a mapping from general orderings to related places

private mapGeneralOrderings(genOrd: set of GeneralOrdering) r: map

GeneralOrdering to Place ≜

if genOrd = {} then { }

else let k genOrd

in {k newPlace(<CountingPlace>)}

munion mapGeneralOrderings(genOrd \ {k});

private mapDecCf(f: CombinedFragment, lfs: set of Lifeline, n: nat) r: map

(CombinedFragment Lifeline nat) to Place ≜

if lfs = {} then { }

else let lf lfs

in {mk_(f, lf, n) newPlace(<FIFOPlace>) }

munion mapDecCf(f, lfs\ {lf}, n);

private mapDecisionPlaces(cfs: set of CombinedFragment) r: map

(CombinedFragment Lifeline nat) to Place ≜

if cfs = {} then { }

else let f cfs

in if f.interactionOperator {<opt>, <alt>, <break>, <neg>}

then mapDecCf(f, f.lifelines, 1)

munion mapDecisionPlaces(cfs \ {f})

else if f.interactionOperator = <loop>

then mapDecCf(f, f.lifelines, 1)

munion mapDecCf(f, f.lifelines, 2)

munion mapDecisionPlaces(cfs \ {f})

else mapDecisionPlaces(cfs \ {f});

-- Generates a mapping from special Fragments to places

private mapCombFrag(cfs: set of CombinedFragment) r: map CombinedFragment to

Place ≜

if cfs = {} then { }

else let f cfs

in cases f.interactionOperator:

<critical> -> {f newPlace(<CriticalPlace>)}

munion mapCombFrag(cfs \ {f}),

<loop> -> {f newPlace(<LIFOPlace>) }

munion mapCombFrag(cfs \ {f}),

Page 10: UML Checker: Formal Specification in VDM++ of the Petri Net … · 2014-10-25 · UML Checker: Formal Specification in VDM++ of the Petri Net-based Conformance Checking Engine TR-SDBT-2013-04,

UML Checker: Formal Specification in VDM++ 10

<neg> -> {f newPlace(<FailurePlace>) }

munion mapCombFrag(cfs \ {f}),

other -> mapCombFrag(cfs \ {f})

end;

-- Generates needed places for a sequence diagram, described by mappings

-- from SD features to places

private generatePlaces(sd: Interaction) r: (set of Place) Place Place (map

LifelineLocation to (Place Place)) (map Message to Place) (map

(CombinedFragment Lifeline nat) to Place) (map GeneralOrdering to Place)

(map CombinedFragment to Place) ≜ let starts = newPlace(<CountingPlace>),

finishes = newPlace(<CountingPlace>),

mapLocs = mapLocations(getLifelineLocations(sd)),

mapMsgs = mapMessages({m | m sd.messages

m.messageSort {<asynchCall>,<asynchSignal>,<reply>}}), mapDecs = mapDecisionPlaces(sd.combinedFragments),

mapFrag = mapCombFrag(sd.combinedFragments),

mapGenOrd = mapGeneralOrderings(sd.generalOrderings),

places = {starts, finishes}

∪ ⋃ {{p1, p2} | mk_(p1, p2) rng mapLocs}

∪ rng mapMsgs ∪ rng mapDecs ∪ rng mapGenOrd ∪ rng mapFrag in mk_(places,starts,finishes,mapLocs,mapMsgs,mapDecs,mapGenOrd,mapFrag);

5.3 Transition generation

-- Get the state immediatly before a lifeline location,

-- using a pre-computed mapping

private placeBefore(loc: LifelineLocation, mapping: map LifelineLocation to

(Place Place)) r : Place ≜ let ss = mapping(loc) in ss.#1;

-- Get the place immediatly after a lifeline location,

-- using a pre-computed mapping

private placeAfter(loc: LifelineLocation, mapping: map LifelineLocation to

(Place Place)) r : Place ≜ let ss = mapping(loc) in ss.#2;

-- Get the first lifeline places, using a pre-computed mapping

private getFirstLifelinePlaces(mapping: map LifelineLocation to (Place

Place)) r : set of Place ≜

{placeBefore(loc, mapping) | loc dom mapping

loc2 dom mapping loc2.#1 = loc.#1 loc2.#2 < loc.#2};

-- Get the last lifeline places, using a pre-computed mapping

private getLastLifelinePlaces(mapping: map LifelineLocation to (Place Place))

r : set of Place ≜

{ placeAfter(loc, mapping) | loc dom mapping

loc2 dom mapping loc2.#1 = loc.#1 loc2.#2 > loc.#2};

-- Get the last lifeline locations in a SD

private getLastLifelineLocs(sd: Interaction) r : set of LifelineLocation ≜ let locs = getLifelineLocations(sd)

Page 11: UML Checker: Formal Specification in VDM++ of the Petri Net … · 2014-10-25 · UML Checker: Formal Specification in VDM++ of the Petri Net-based Conformance Checking Engine TR-SDBT-2013-04,

UML Checker: Formal Specification in VDM++ 11

in {loc | loc locs

loc2 locs loc2.#1 = loc.#1 loc2.#2 > loc.#2};

-- Generate, from general ordering constraints, input arcs for a PN transition

-- related to a set of SD locations

private genOrdInputs(mapGenOrd : map GeneralOrdering to Place, locs: set of

LifelineLocation) r : map Place to nat ≜

{mapGenOrd(i) 1 | i dom mapGenOrd i.after locs};

-- Generate, from general ordering constraints, outpur arcs for a PN transition

-- related to a set of SD locations

private genOrdOutputs(mapGenOrd : map GeneralOrdering to Place, locs: set of

LifelineLocation) r : map Place to nat ≜

{mapGenOrd(i) 1 | i dom mapGenOrd i.before locs};

-- Generates transitions for a message, considering pre-computed

-- place generator mappings

private msg2trans(m: Message, mapping: map LifelineLocation to (Place Place),

mapMsg: map Message to Place, mapGenOrd : map GeneralOrdering to Place) r : set

of Transition ≜ cases m.messageSort:

<synchCall>, <createMessage> ->

let r dom mapMsg be st

r.messageSort = <reply> r.groupId = m.groupId

in {mkTransition(

{placeBefore(m.source,mapping) 1,

placeBefore(m.target,mapping) 1}

munion genOrdInputs(mapGenOrd, {m.source, m.target}),

mk_Label(mk_Event(<Call>, m), nil),

{placeAfter(m.source,mapping) 1,

placeAfter(m.target,mapping) 1,

mapMsg(r) OccurrenceGroup}

munion genOrdOutputs(mapGenOrd, {m.source, m.target}),

{})

},

<reply> ->

{mkTransition(

{placeBefore(m.source,mapping) 1,

placeBefore(m.target,mapping) 1,

mapMsg(m) OccurrenceGroup }

munion genOrdInputs(mapGenOrd, {m.source, m.target}),

mk_Label(mk_Event(<Reply>, m), nil),

{placeAfter(m.source,mapping) 1,

placeAfter(m.target,mapping) 1}

munion genOrdOutputs(mapGenOrd, {m.source, m.target}),

{})

},

<asynchCall>, <asynchSignal> ->

{mkTransition(

{placeBefore(m.source, mapping) 1}

munion genOrdInputs(mapGenOrd, {m.source}),

mk_Label(mk_Event(<Send>, m), nil),

{placeAfter(m.source, mapping) 1, mapMsg(m) OccurrenceGroup}

Page 12: UML Checker: Formal Specification in VDM++ of the Petri Net … · 2014-10-25 · UML Checker: Formal Specification in VDM++ of the Petri Net-based Conformance Checking Engine TR-SDBT-2013-04,

UML Checker: Formal Specification in VDM++ 12

munion genOrdOutputs(mapGenOrd, {m.source}),

{}),

mkTransition(

{placeBefore(m.target, mapping) 1,

mapMsg(m) OccurrenceGroup}

munion genOrdInputs(mapGenOrd, {m.target}),

mk_Label(mk_Event(<Receive>, m), nil),

{placeAfter(m.target, mapping) 1}

munion genOrdOutputs(mapGenOrd, {m.target}),

{})}

end;

private getFirstEvents(sd: Interaction, f: CombinedFragment, lf: Lifeline) res

: set of Event ≜ let loc1 = getLoc(f.operands(1).startLocations, lf).#2

in

{ mk_Event(if m.source.#1 = lf then <Send> else <Receive>, m)

| m sd.messages m.messageSort <reply>

(m.source.#1 = lf m.source.#2 > loc1

m.target.#1 = lf m.target.#2 > loc1)};

-- assumes that reply message must be in same fragment of call message

-- Generate transitions for a decision point outcome

private dec2trans(sd: Interaction, f: CombinedFragment, mapLocs: map

LifelineLocation to (Place Place), mapDec: map (CombinedFragment Lifeline

nat) to Place, guard: [ValueSpecification], extraInOut: [(map Place to

[ValueSpecification]) (map Place to [ValueSpecification])], decPointId: nat,

outcomeId: nat, startLocs : set of LifelineLocation, endLocs: set of

LifelineLocation) r: set of Transition ≜

if card f.lifelines = 1 synchronizeLifelinesAtDecisionPoints then {mkTransition(

let m = {placeBefore(loc, mapLocs) 1 | loc startLocs} in if extraInOut = nil then m else m munion extraInOut.#1,

if guard = nil then nil else mk_Label(nil, guard),

let m = {placeAfter(loc, mapLocs) 1 | loc endLocs} in if extraInOut = nil then m else m munion extraInOut.#2,

{})}

else

let decidors = {lf | lf f.lifelines

e getFirstEvents(sd, f, lf) e.type = <Send>}

in

-- as first to decide

{mkTransition(

let m = {placeBefore(getLoc(startLocs, lf), mapLocs) 1}

in if extraInOut=nil then m else m munion extraInOut.#1,

if guard = nil then nil else mk_Label(nil, guard),

(let m = {placeAfter(getLoc(endLocs, lf), mapLocs) 1}

in if extraInOut=nil then m else m munion extraInOut.#2)

munion

{mapDec(mk_(f,lf2,decPointId))outcomeId|lf2 f.lifelines\{lf}}, {mapDec(mk_(f, lf, decPointId))})

| lf decidors}

∪ -- as following others

{mkTransition(

Page 13: UML Checker: Formal Specification in VDM++ of the Petri Net … · 2014-10-25 · UML Checker: Formal Specification in VDM++ of the Petri Net-based Conformance Checking Engine TR-SDBT-2013-04,

UML Checker: Formal Specification in VDM++ 13

{placeBefore(getLoc(startLocs, lf), mapLocs) 1,

mapDec(mk_(f, lf, decPointId)) outcomeId}, nil,

{placeAfter(getLoc(endLocs, lf), mapLocs) 1},

{})

| lf f.lifelines decidors {lf}};

-- Generates transitions for a combined fragment, considering pre-computed

-- place generator mappings

private cf2trans(sd: Interaction, f: CombinedFragment, mapLocs: map

LifelineLocation to (Place Place), mapDecs: map (CombinedFragment Lifeline

nat) to Place, mapFrag: map CombinedFragment to Place) r: set of Transition

≜ cases f.interactionOperator:

<par> ->

⋃ {{mkTransition(

{placeBefore(getLoc(f.operands(1).startLocations,lf),mapLocs)1},

nil,

{placeAfter(getLoc(o.startLocations, lf), mapLocs) 1 |

o elems f.operands}, {}),

mkTransition(

{placeBefore(getLoc(o.finishLocations, lf), mapLocs) 1 |

o elems f.operands},

nil,

{placeAfter(getLoc(f.operands(len f.operands).finishLocations,lf),

mapLocs) 1}, {})}

| lf f.lifelines},

<seq>, <assert> ->

{mkTransition({placeBefore(loc, mapLocs) 1}, nil,

{placeAfter(loc, mapLocs) 1}, {})

| loc ⋃ {o.startLocations ∪ o.finishLocations |

o elems f.operands}},

<strict> ->

{mkTransition(

{placeBefore(loc, mapLocs) 1 | loc o.startLocations}, nil,

{placeAfter(loc, mapLocs) 1 | loc o.startLocations},{})

| o elems f.operands}

∪ {mkTransition(

{placeBefore(loc, mapLocs) 1 | loc o.finishLocations}, nil,

{placeAfter(loc, mapLocs) 1 | loc o.finishLocations},{})

| o elems f.operands},

<critical> ->

let o = f.operands(1)

in {mkTransition(

{placeBefore(loc, mapLocs) 1 | loc o.startLocations}, nil,

{placeAfter(loc, mapLocs) 1 | loc o.startLocations}, {}),

Page 14: UML Checker: Formal Specification in VDM++ of the Petri Net … · 2014-10-25 · UML Checker: Formal Specification in VDM++ of the Petri Net-based Conformance Checking Engine TR-SDBT-2013-04,

UML Checker: Formal Specification in VDM++ 14

mk_Transition(

{placeBefore(loc, mapLocs) 1 | loc o.finishLocations}, nil,

{placeAfter(loc, mapLocs) 1 | loc o.finishLocations}, {}, {mapFrag(f)})},

<opt> ->

let o = f.operands(1)

in -- enter fragment

dec2trans(sd, f, mapLocs, mapDecs,

if o.guard = nil then nil else o.guard.specification, nil,

1, 1, o.startLocations, o.startLocations)

∪ -- skip fragment

dec2trans(sd, f, mapLocs, mapDecs,

if o.guard = nil then nil

else mk_Expression(<Neg>, [o.guard.specification]),

nil, 1, 2, o.startLocations, o.finishLocations)

-- exit fragment

{mkTransition({placeBefore(loc, mapLocs) 1}, nil,

{placeAfter(loc, mapLocs) 1}, {})

| loc o.finishLocations},

<neg> ->

let o = f.operands(1)

in -- enter fragment

dec2trans(sd, f, mapLocs, mapDecs, nil, nil,

1, 1, o.startLocations, o.startLocations)

-- in end of frag. accept any event (while waiting for other lifelines)

∪ {mkTransition(

{placeBefore(loc, mapLocs) 1},

mk_Label(mk_Event(<AnyEvent>, nil), nil),

{placeBefore(loc, mapLocs) 1}, {})

| loc o.finishLocations}

-- exit fragment to irrevocable failure state

∪ {mkTransition(

{placeBefore(loc, mapLocs) 1 | loc o.finishLocations},

nil, {mapFrag(f) 1}, {})}

-- skip fragment

∪ dec2trans(sd, f, mapLocs, mapDecs, nil, nil,

1, 2, o.startLocations, o.finishLocations)

-- after skipping, allow any event

∪ {mkTransition(

{placeAfter(loc, mapLocs) 1},

mk_Label(mk_Event(<AnyEvent>, nil), nil),

{placeAfter(loc, mapLocs) 1}, {})

| loc o.finishLocations},

<break> ->

-- same as opt, only different in the destination of 'exit fragment'

let o = f.operands(1),

Page 15: UML Checker: Formal Specification in VDM++ of the Petri Net … · 2014-10-25 · UML Checker: Formal Specification in VDM++ of the Petri Net-based Conformance Checking Engine TR-SDBT-2013-04,

UML Checker: Formal Specification in VDM++ 15

f2 = container(sd, f),

p2 = if f2 nil f2.interactionOperator = <loop>

then mapFrag(f2) else nil,

locs2 = if f2 = nil then getLastLifelineLocs(sd)

else f2.operands(len f2.operands).finishLocations

in -- enter fragment

dec2trans(sd, f, mapLocs, mapDecs,

if o.guard = nil then nil else o.guard.specification,

if p2 = nil then nil

else mk_({p2 mk_PNVariable("$c")},{}),

1, 1, o.startLocations, o.startLocations)

∪ -- skip fragment

dec2trans(sd, f, mapLocs, mapDecs,

if o.guard = nil then nil

else mk_Expression(<Neg>, [o.guard.specification]),

nil, 1, 2, o.startLocations, o.finishLocations)

-- exit fragment

{mkTransition({placeBefore(loc, mapLocs) 1}, nil,

{placeAfter(getLoc(locs2, loc.#1), mapLocs) 1}, {})

| loc o.finishLocations},

<alt> ->

-- enter alternatives

⋃ {let o = f.operands(i)

in dec2trans(sd, f, mapLocs, mapDecs,

if o.guard = nil then nil

else if o.guard.specification = <else>

then mk_Expression(<Neg>, [mk_Expression(<Or>,

[f.operands(i).guard.specification |

i inds f.operands

f.operands(i).guard nil

f.operands(i).guard.specification <else>])]) else o.guard.specification,

nil, 1, i, f.operands(1).startLocations, o.startLocations)

| i inds f.operands}

∪ -- skip alternatives if none holds

(if op elems f.operands

op.guard = nil op.guard.specification = <else>

then {}

else

dec2trans(sd, f, mapLocs, mapDecs,

mk_Expression(<Neg>, [mk_Expression(<Or>,

[f.operands(i).guard.specification | i inds f.operands

f.operands(i).guard nil])]),

nil, 1, len f.operands + 1,

f.operands(1).startLocations,

f.operands(len f.operands).finishLocations))

∪ -- exit alternatives

⋃ {{mkTransition(

{placeBefore(getLoc(o.finishLocations, lf), mapLocs) 1},

Page 16: UML Checker: Formal Specification in VDM++ of the Petri Net … · 2014-10-25 · UML Checker: Formal Specification in VDM++ of the Petri Net-based Conformance Checking Engine TR-SDBT-2013-04,

UML Checker: Formal Specification in VDM++ 16

nil,

{placeAfter(getLoc(f.operands(len f.operands).finishLocations,

lf), mapLocs) 1}, {})

| o elems f.operands}

| lf f.lifelines},

<loop> ->

let o = f.operands(1),

c = mk_PNVariable("$c")

in -- enter loop

dec2trans(sd, f, mapLocs, mapDecs,

if o.guard = nil then nil

else mk_Expression(<And>,

[if o.guard.maxint = nil then true

else mk_Expression(<Gt>, [o.guard.maxint, 0]),

mk_Expression(<Or>,

[if o.guard.minint = nil then false

else mk_Expression(<Gt>, [o.guard.minint, 0]),

if o.guard.specification = nil then true

else o.guard.specification])]),

mk_({}, {mapFrag(f) 1}),

1, 1, o.startLocations, o.startLocations)

∪ -- skip loop dec2trans(sd, f, mapLocs, mapDecs,

if o.guard = nil then nil

else mk_Expression(<Or>,

[if o.guard.maxint = nil then false

else mk_Expression(<Eq>, [o.guard.maxint, 0]),

mk_Expression(<And>,

[if o.guard.minint = nil then true

else mk_Expression(<Eq>, [o.guard.minint, 0]),

if o.guard.specification = nil then true

else mk_Expression(<Neg>,[o.guard.specification])])]),

nil,

1, 2, o.startLocations, o.finishLocations)

∪ -- continue loop dec2trans(sd, f, mapLocs, mapDecs,

if o.guard = nil then nil

else mk_Expression(<And>,

[if o.guard.maxint = nil then true

else mk_Expression(<Lt>, [c, o.guard.maxint]),

mk_Expression(<Or>,

[if o.guard.minint = nil then false

else mk_Expression(<Lt>, [c, o.guard.minint]),

if o.guard.specification = nil then true

else o.guard.specification])]),

mk_({mapFrag(f) c},

{mapFrag(f) mk_Expression(<Plus>,[c,1])}),

2, 1, o.finishLocations, o.startLocations)

∪ -- exit loop dec2trans(sd, f, mapLocs, mapDecs,

if o.guard = nil then nil

else mk_Expression(<Or>,

[if o.guard.maxint = nil then false

else mk_Expression(<Gte>, [c, o.guard.maxint]),

mk_Expression(<And>,

[if o.guard.minint = nil then true

Page 17: UML Checker: Formal Specification in VDM++ of the Petri Net … · 2014-10-25 · UML Checker: Formal Specification in VDM++ of the Petri Net-based Conformance Checking Engine TR-SDBT-2013-04,

UML Checker: Formal Specification in VDM++ 17

else mk_Expression(<Gte>, [c, o.guard.minint]),

if o.guard.specification = nil then true

else mk_Expression(<Neg>,[o.guard.specification])])]),

mk_({mapFrag(f) c}, {}),

2, 2, o.finishLocations, o.finishLocations)

end;

private replace(pn: PetriNet, rep: map Parameter to [ValueSpecification]) r:

PetriNet ≜ let trans2 =

{mkTransition(

{p replace(t.source(p), rep) | p dom t.source},

if t.label = nil then nil

else mk_Label(

if t.label.event = nil then nil

else mk_Event(t.label.event.type,

let m = t.label.event.message

in if m = nil then nil

else mk_Message(m.id, m.groupId, m.source,

m.target, m.messageSort, m.signature,

[replace(m.arguments(i), rep) |

i inds m.arguments])),

if t.label.guard = nil then nil else replace(t.label.guard, rep)),

{p replace(t.target(p), rep) | p dom t.target},

t.inhibitor) | t pn.transitions}

in mk_PetriNet(pn.places, pn.starts, pn.finish, trans2);

-- Generate PN and transitions for an interaction use

private ref2trans(sd: Interaction, f: InteractionUse, mapLocs: map

LifelineLocation to (Place Place)) r: (set of Transition) PetriNet ≜ let refd = replace(sd2pn(f.refersTo),

{f.refersTo.parameters(i) f.arguments(i) |

i inds f.refersTo.parameters}),

trans = {mkTransition(

{placeBefore(loc, mapLocs) 1 | loc f.locations},

nil, {refd.starts 1},{}),

mkTransition({p 1 | p refd.finish}, nil,

{placeAfter(loc, mapLocs) 1 | loc f.locations},

{})}

in mk_(trans, refd);

private considerIgnore2trans(sd: Interaction, f: ConsiderIgnoreFragment,

mapLocs: map LifelineLocation to (Place Place)) r : set of Transition ≜ let etype = if f.interactionOperator = <ignore> then <AnySignatureInSet>

else <AnySignatureNotInSet>,

tlabel = mk_Label(mk_Event(etype, f.messages), nil)

in ⋃ { let p1 = placeBefore(loc, mapLocs), p2 = placeAfter(loc, mapLocs)

in {mkTransition({p1 1}, tlabel, {p1 1}, {}),

mkTransition({p2 1}, tlabel, {p2 1}, {})}

| loc dom mapLocs

contains(f, loc)

f2 sd.considerIgnoreFragments

Page 18: UML Checker: Formal Specification in VDM++ of the Petri Net … · 2014-10-25 · UML Checker: Formal Specification in VDM++ of the Petri Net-based Conformance Checking Engine TR-SDBT-2013-04,

UML Checker: Formal Specification in VDM++ 18

f2 f contains(f2, loc) contains(f, f2)};

-- Update transition because of critical places

private updateTransCrit(t: Transition, sd: Interaction, mapLocs: map

LifelineLocation to (Place Place), mapFrag : map CombinedFragment to Place)

r: Transition ≜

if t.label = nil t.label.event = nil then t

else let tlocs = {loc | loc dom mapLocs

mapLocs(loc).#1 dom t.source

mapLocs(loc).#2 dom t.target},

inhib = {mapFrag(crit) | crit dom mapFrag

crit.interactionOperator = <critical>

loc tlocs

loc.#1 crit.lifelines

let par = container(sd, crit)

in loc tlocs

contains(par, loc)

contains(crit, loc)},

setCrit = {mapFrag(crit) 1 | crit dom mapFrag crit.interactionOperator = <critical>

loc tlocs

loc.#1 crit.lifelines

loc tlocs contains(crit, loc)}

in mkTransition(t.source, t.label, t.target munion setCrit, t.inhibitor

∪ inhib);

-- Generating all transitions

private generateTransitions(sd: Interaction, starts: Place, finishes: Place,

mapLocs: map LifelineLocation to (Place Place), mapMsgs: map Message to Place,

mapDec : map (CombinedFragment Lifeline nat) to Place, mapGenOrd: map

GeneralOrdering to Place, mapFrag: map CombinedFragment to Place) r : (set of

Transition) (set of PetriNet)≜

let ref2transRes = {ref2trans(sd, f, mapLocs) | f sd.interactionUses},

trans =

{mkTransition({starts 1}, nil,

{p 1 | p getFirstLifelinePlaces(mapLocs)}, {}),

mkTransition({p 1 | p getLastLifelinePlaces(mapLocs)},

nil, {finishes 1}, {})}

∪ ⋃ {cf2trans(sd, f, mapLocs, mapDec, mapFrag) |

f sd.combinedFragments}

∪ ⋃ {considerIgnore2trans(sd, f, mapLocs) |

f sd.considerIgnoreFragments}

∪ ⋃ {trans | mk_(trans, refdpn) ref2transRes}

∪ ⋃ {msg2trans(m,mapLocs, mapMsgs, mapGenOrd) |

m sd.messages},

trans2 = if f dom mapFrag

f.interactionOperator = <critical>

then trans

else {updateTransCrit(t, sd, mapLocs, mapFrag) | t trans}

in mk_(trans2, {refdpn | mk_(trans, refdpn) ref2transRes});

Page 19: UML Checker: Formal Specification in VDM++ of the Petri Net … · 2014-10-25 · UML Checker: Formal Specification in VDM++ of the Petri Net-based Conformance Checking Engine TR-SDBT-2013-04,

UML Checker: Formal Specification in VDM++ 19

5.4 Main conversion logic -- Converts a sequence diagram (Interaction) to a PetriNet

public sd2pn(sd : Interaction) r: PetriNet ≜ let mk_(places, s0, finishes, mapping, mapMsg, mapDec, mapGenOrd, mapFrag)

= generatePlaces(sd),

mk_(trans, refdpn) = generateTransitions(sd, s0, finishes, mapping,

mapMsg, mapDec, mapGenOrd, mapFrag)

in mk_PetriNet(places ∪ ⋃ {r.places | r refdpn}, s0, {finishes},

trans ∪ ⋃ {r.transitions | r refdpn});

6 Petri Net Execution

6.1 Definition of execution traces types

public Trace = seq of Occurrence;

public Occurrence ::

id : nat

groupId : nat --identifies pairs of call/reply or send/receive occurrences

target : OccurrenceTarget

type : EventType

signature: MessageSignature

arguments: seq of Value; -- return value, in case of Reply

public OccurrenceTarget = Instance | Classifier;

public Classifier ::

className : string;

6.2 Definition of run states public RunState :: marking : Marking

bindings : Bindings

covers : set of nat;

public PNToken = Value;

public Marking = map Place to (nat | seq of PNToken);

public ConformanceMode = <LooseConf> | <StrictConf>;

values

private OccurrenceGroup = mk_PNVariable("$g");

Page 20: UML Checker: Formal Specification in VDM++ of the Petri Net … · 2014-10-25 · UML Checker: Formal Specification in VDM++ of the Petri Net-based Conformance Checking Engine TR-SDBT-2013-04,

UML Checker: Formal Specification in VDM++ 20

6.3 Matching and binding values and messages functions

-- Recursively matches a sequence of values against a sequence of value

-- specifications, considering a set of bindings of variables to actual values.

-- Returns a tuple with a success flag and new bindings

private matchAndBindSeq(actual: seq of [Value], expected: seq of

[ValueSpecification], b: Bindings) r : bool Bindings ≜

if len actual len expected

then mk_(false, b)

else if actual = [] then mk_(true, b)

else let mk_(r1, b1) = matchAndBindVal(hd actual, hd expected, b)

in if r1

then matchAndBindSeq(tl actual, tl expected, b1)

else mk_(r1, b1);

-- Similar to above, but receives a set of pairs of actual and expected values.

private matchAndBindPairs(pairs: set of ([Value] [ValueSpecification]), b:

Bindings) r : bool Bindings ≜ if pairs = {}

then mk_(true, b)

else let pair pairs

in let mk_(r1, b1) = matchAndBindVal(pair.#1, pair.#2, b)

in if r1

then matchAndBindPairs(pairs \ {pair}, b1)

else mk_(r1, b1);

-- Match and bind the target of a message

private matchAndBindTarget(o: Occurrence, e: Event, b: Bindings) r: bool

Bindings≜ let m = e.message,

mt = if o.type = <Reply> then m.source.#1 else m.target.#1

in if is_Instance(o.target)

then if mt.instanceName = nil

then mk_(false, b)

else matchAndBindVal(o.target, mt, b)

else mk_(mt.instanceName = nil, b);

-- Matches an occurrence against an event pattern, and returns a tuple with a

-- success flag and new bindings.

private matchAndBind(o: Occurrence, e: Event, b: Bindings) r: bool Bindings

≜ cases e.type:

<AnyEvent> -> mk_(true, b),

<AnySignatureInSet> -> mk_(o.signature e.message, b),

<AnySignatureNotInSet> -> mk_(o.signature e.message, b),

others -> let m = e.message

in if e.type = o.type m.signature = o.signature

then let mk_(r2, b2) = matchAndBindTarget(o, e, b)

in if r2

then matchAndBindSeq(o.arguments, m.arguments, b2)

else mk_(false, b)

else mk_(false, b)

end;

Page 21: UML Checker: Formal Specification in VDM++ of the Petri Net … · 2014-10-25 · UML Checker: Formal Specification in VDM++ of the Petri Net-based Conformance Checking Engine TR-SDBT-2013-04,

UML Checker: Formal Specification in VDM++ 21

6.4 Operations on markings -- Checks if a place contains a token in a given marking

private containsToken(m: Marking, p: Place, tok: PNToken) res: bool ≜

if p.type = <FIFOPlace> p.type = <LIFOPlace>

then tok elems m(p)

else tok {1, ..., m(p)};

-- Checks if a marking contains a token

private containsToken(m: Marking, tok: PNToken) res: bool ≜

p dom m containsToken(m, p, tok);

-- Gets the next token to come out from a non empty place p in a marking m

private getToken(m: Marking, p: Place) res : PNToken ≜

if p.type = <FIFOPlace> p.type = <LIFOPlace> then hd m(p) else 1;

-- Gets the number of tokens in a marking m for a place p

private getNumTokens(m: Marking, p: Place) res : nat ≜

if p.type = <FIFOPlace> p.type = <LIFOPlace> then len m(p) else m(p);

-- Remove from a marking one token per place in a set

private markingRmv(m: Marking, s: set of Place) r : Marking ≜

{p if p s

then if p.type = <FIFOPlace> p.type = <LIFOPlace> then tl m(p)

else m(p)-1

else m(p)

| p dom m getNumTokens(m, p) > 1 p s};

-- Reset a place (make empty) in a marking, returns the new marking

private markingReset(m: Marking, s: set of Place) r : Marking ≜ s <-: m;

-- Add to a marking one token per output place of a transition

-- returns the new marking.

private markingAdd(m: Marking, a: map Place to ValueSpecification, b: Bindings)

r : Marking ≜

{p if p dom a then if p.type = <FIFOPlace>

then if p dom m then m(p) ↷ [eval(a(p),b)]

else [eval(a(p), b)]

else if p.type = <LIFOPlace>

then if p dom m then [eval(a(p),b)] ↷ m(p)

else [eval(a(p), b)]

else if p dom m then m(p) + 1 else 1

else m(p)

| p dom m ∪ dom a};

6.5 Operations on transitions -- Gets temporary bindings of variables to actual values for a transition.

-- Variables may appear in input arcs; there is also

-- a built-in variable for the occurrence group id.

-- Returns a success flag (no inconsistent bindings) and the bindings.

Page 22: UML Checker: Formal Specification in VDM++ of the Petri Net … · 2014-10-25 · UML Checker: Formal Specification in VDM++ of the Petri Net-based Conformance Checking Engine TR-SDBT-2013-04,

UML Checker: Formal Specification in VDM++ 22

-- Matches andbinds the tokens extracted from the input places -- againts the value specfications contained in the arcs.

private getTmpBindings(t: Transition, r: RunState, o: [Occurrence]) res : (bool

Bindings) ≜ -- first performs the built-in binding, and then the input arcs

let b = if o = nil then {}

else {OccurrenceGroup mk_OccurrenceGroupId(o.groupId)}

in matchAndBindPairs(

{mk_(getToken(r.marking, s), t.source(s)) | s dom t.source}, b);

-- Check if a transition guard holds, considering current bindings of

-- variables to actual values.

private guardHolds(t: Transition, b: Bindings) r: bool ≜

t.label = nil t.label.guard = nil eval(t.label.guard, b) = true;

-- Checks if a Transition is enabled in a RunState

private isEnabled(t: Transition, r: RunState, o: [Occurrence]) res: bool ≜

dom t.source ⊆ dom r.marking

t.inhibitor ∩ dom r.marking = {}

if o = nil

then if t.label nil t.label.event nil

then false

else let mk_(res, b) = getTmpBindings(t, r, o)

in if res = false then false

else guardHolds(t, r.bindings ++ b)

else if t.label = nil t.label.event = nil

(t.label.event.type {<AnyEvent> , <AnySignatureInSet>, <AnySignatureNotInSet>}

t.label.event.type o.type)

then false

else let mk_(res, b) = getTmpBindings(t, r, o)

in if res = false then false

else let b2 = r.bindings ++ b

in guardHolds(t, b2)

matchAndBind(o, t.label.event, b2).#1;

-- Performs an automatic (o = nil) or event-driven (o nil) Transition

-- from a given RunState and returns the new RunState

private fire(t: Transition, r: RunState, o: [Occurrence]) res: RunState ≜ let tmpB = getTmpBindings(t, r, o).#2,

b1 = r.bindings ++ tmpB,

b2 = if o = nil then b1

else matchAndBind(o, t.label.event, b1).#2,

newM = markingReset(markingAdd(markingRmv(r.marking, dom t.source),

t.target, b2), t.resetArcs),

newCov = if o = nil t.label.event.type

{<AnySignatureInSet>, <AnySignatureNotInSet>, <AnyEvent>}

then r.covers

else r.covers ∪ {t.label.event.message.id} in mk_RunState(newM, dom tmpB <-: b2, newCov);

6.6 Main execution logic

Page 23: UML Checker: Formal Specification in VDM++ of the Petri Net … · 2014-10-25 · UML Checker: Formal Specification in VDM++ of the Petri Net-based Conformance Checking Engine TR-SDBT-2013-04,

UML Checker: Formal Specification in VDM++ 23

-- Decides if an event occurrence may be considered in a RunState

private mayConsider(r: RunState, o: Occurrence, mode: ConformanceMode) res:

bool ≜ if mode = <StrictConf> then true

else ((o.type = <Reply> o.type = <Receive>)

containsToken(r.marking, mk_OccurrenceGroupId(o.groupId)));

-- Decides if an occurrence may be ignored in a RunState

private mayIgnore(r: RunState, o: Occurrence, mode : ConformanceMode) res: bool

≜ if mode = <StrictConf> then false

else ((o.type=<Reply> o.type =<Receive>)

containsToken(r.marking, mk_OccurrenceGroupId(o.groupId)));

-- Recursively computes the transitive closure of a set of run states rr

-- by firing automatic transitions. Uses an accumulator of already explored

-- run states to avoid infinite loops.

private getAutoFireClosure(pn: PetriNet, rr: set of RunState, explored: set of

RunState) r: set of RunState ≜ if rr = explored then rr

else getAutoFireClosure(pn,

rr ∪ ⋃{{fire(t, r, nil) | t pn.transitions isEnabled(t, r, nil)}

| r rr \ explored},

rr ∪ explored);

-- Determines if a run state of a Petri net is a quiescent state

private isQuiescent(pn: PetriNet, r: RunState) res: bool ≜

t pn.transitions isEnabled(t, r, nil);

-- Advances run states following automatic transitions until quiescent

-- states are reached.

private auto(pn: PetriNet, rr: set of RunState) res: set of RunState ≜

{r | r getAutoFireClosure(pn, rr, {}) isQuiescent(pn, r)};

-- Performs a PetriNet step, i.e., processes a single input occurrence,

-- departing from a set of run states, and returns the new set of run states.

private step(pn: PetriNet, o: Occurrence, rr: set of RunState, mode:

ConformanceMode) r: set of RunState ≜

let newRR = ⋃ {{fire(t, r, o) | t pn.transitions isEnabled(t, r, o)}

| r rr mayConsider(r, o, mode)}

in auto(pn, newRR) ∪ {r | r rr mayIgnore(r, o, mode)};

-- Generates the initial set of run states for a PetriNet

private startPN(pn: PetriNet, params: Bindings) r: set of RunState ≜

auto(pn, {mk_RunState({pn.starts 1}, params, {})});

-- Checks if a set of (final) run states represents acceptance

private succeeded(pn: PetriNet, runStates: set of RunState) r: bool ≜

failed(pn, runStates) r runStates p dom r.marking p pn.finish;

-- Checks if a set of (intermediate final) run states represents failure

private failed(pn: PetriNet, runStates: set of RunState) r: bool ≜

runStates = {} (r runStates p dom r.marking p.type = <FailurePlace>);

-- Recursively checks if a PN accepts an execution trace in a given

-- conformance mode, departing from a given set of initial run states.

Page 24: UML Checker: Formal Specification in VDM++ of the Petri Net … · 2014-10-25 · UML Checker: Formal Specification in VDM++ of the Petri Net-based Conformance Checking Engine TR-SDBT-2013-04,

UML Checker: Formal Specification in VDM++ 24

-- Returns the final set of run states.

private steps(pn: PetriNet, trace: Trace, mode: ConformanceMode, runStates: set

of RunState) r : set of RunState ≜ if failed(pn, runStates) then runStates

else if trace = [] then runStates

else steps(pn, tl trace, mode, step(pn, hd trace, runStates, mode));

-- Checks if a PN accepts an execution trace in a given conformance mode

public accepts(pn: PetriNet, trace: Trace, params: Bindings, mode:

ConformanceMode) r: bool ≜ succeeded(pn, steps(pn, trace, mode, startPN(pn, params)));

-- Gets the run state with a maximal set of covered messages

public getBestMatch(pn: PetriNet, runStates: set of RunState) r: [RunState] ≜ if runStates = {} then nil

else let r1 runStates be st r2 runStates card r2.covers > card r1.covers

in r1;

-- Recursively checks if a PN accepts an execution trace in a given

-- conformance mode, departing from a given set of initial run states

-- and an initial bestMatch (a run state with maximal coverage).

-- Returns a pair with the final set of run states and the best match.

private stepsWithInfo(pn: PetriNet, trace: Trace, mode: ConformanceMode,

runStates: set of RunState, bestMatch: [RunState]) r : (set of RunState)

[RunState] ≜

if failed(pn, runStates) trace = [] then mk_(runStates, bestMatch)

else let newStates = step(pn, hd trace, runStates, mode),

newMatch = if bestMatch = nil

then getBestMatch(pn, newStates)

else getBestMatch(pn, {bestMatch} ∪ newStates) in stepsWithInfo(pn, tl trace, mode, newStates, newMatch);

-- Checks if a PN accepts an execution trace in a given conformance mode

-- and initial bindings, and returns a tuple with a success flag and

-- a maximal set of messages covered

public acceptsWithInfo(pn: PetriNet, trace: Trace, params: Bindings, mode:

ConformanceMode) res: bool (set of MessageId) ≜ let initRunStates = startPN(pn, params),

initBestMatch = getBestMatch(pn, initRunStates),

mk_(runStates, bestMatch) = stepsWithInfo(pn, trace, mode,

initRunStates, initBestMatch),

bestCover = if bestMatch = nil then {} else bestMatch.covers,

f = {r | r runStates p dom r.marking p.type = <FailurePlace>},

a = {r | r runStates dom r.marking ∩ pn.finish {}}

in if f {} then let r f in mk_(false, r.covers)

else if a = {} then mk_(false, bestCover)

else mk_(true, getBestMatch(pn, a).covers);

7 Test Cases

7.1 Convenience definitions operations

-- convenience operation for writing test cases (pre-condition checking

Page 25: UML Checker: Formal Specification in VDM++ of the Petri Net … · 2014-10-25 · UML Checker: Formal Specification in VDM++ of the Petri Net-based Conformance Checking Engine TR-SDBT-2013-04,

UML Checker: Formal Specification in VDM++ 25

-- must be enabled)

private Assert : bool = ()

Assert(a) ≜ return pre a;

7.2 Simple asynchronous message

operations

public testTrivial()≜ (

let l1 = mk_Lifeline("L1", nil),

l2 = mk_Lifeline("L2", nil),

m1c = mk_Message(1, 1, mk_(l1,1), mk_(l2,1), <synchCall>, "m1", []),

m1r = mk_Message(2, 1, mk_(l2,2), mk_(l1,2), <reply>, "m1", []),

sd1 = mk_Interaction({l1,l2 }, {m1c, m1r}, {}, {}, {}, {}, []),

pn1 = sd2pn(sd1),

c1 = mk_Classifier("L1"),

c2 = mk_Classifier("L2"),

sm1 = mk_Occurrence(1, 1, c2, <Call>, "m1", []),

rm1 = mk_Occurrence(2, 1, c2, <Reply>, "m1", [])

in

(

Assert(acceptsWithInfo(pn1, [], { }, <StrictConf>) = mk_(false, {}));

Assert(acceptsWithInfo(pn1, [sm1, rm1], { }, <StrictConf>) = mk_(true,

{1,2}));

)

);

7.3 Weak sequencing

The next example is adapted from Fig. 5 of our ICTSS paper. It illustrates weak sequencing, i.e., implicit

parallelism between lifelines, as well as the overall conformance checking process. It was updated to use Petri Nets

instead of Parallel Finite automata.

Page 26: UML Checker: Formal Specification in VDM++ of the Petri Net … · 2014-10-25 · UML Checker: Formal Specification in VDM++ of the Petri Net-based Conformance Checking Engine TR-SDBT-2013-04,

UML Checker: Formal Specification in VDM++ 26

sd Dynamic View

Client

o1 :C1 o2 :C2

opt

m0()

m1()

m3()

m2()

2

3

4

5

6

8

11

9

14

15

16

17

18

2

3

4

5

6

7

13

12

11

14

15

16

17

18

m0

Start

m1

m3

ret m3

m2

ret m2

ret m1

ret m0

12

1

Step 1: Generate states Step 2: Generate transitions

1

7

10

13

8

10

9

19

19

22

$g

$g

20

$g

$g

23

$g

$g

21

$g

$g

Step 3: Simplify (optional)

7

12

11

15

17

m0

Start

m1

m3

ret m3

m2

ret m2

ret m1

ret m0

1

19

22

$g

$g

20

$g

$g

23

$g

$g

21

$g

$g

6

values

public sdFig5 : Interaction =

let l1 = mk_Lifeline("Client", nil),

l2 = mk_Lifeline("C1", nil),

l3 = mk_Lifeline("C2", "o2"),

o1 = mk_InteractionOperand( nil, {mk_(l2, 3)}, {mk_(l2, 6)}),

f1 = mk_CombinedFragment(1, <opt>, [o1], {l2}),

m0C = mk_Message(1, 1, mk_(l1, 1), mk_(l2, 1), <synchCall>, "m0", []),

m0R = mk_Message(2, 1, mk_(l2, 8), mk_(l1, 2), <reply>, "m0", []),

m1C = mk_Message(3, 2, mk_(l2, 2), mk_(l3, 1), <synchCall>, "m1", []),

m1R = mk_Message(4, 2, mk_(l3, 4), mk_(l2, 7), <reply>, "m1", []),

m2C = mk_Message(5, 3, mk_(l2, 4), mk_(l2, 4), <synchCall>, "m2", []),

m2R = mk_Message(6, 3, mk_(l2, 5), mk_(l2, 5), <reply>, "m2", []),

m3C = mk_Message(7, 4, mk_(l3, 2), mk_(l3, 2), <synchCall>, "m3", []),

m3R = mk_Message(8, 4, mk_(l3, 3), mk_(l3, 3), <reply>, "m3", [])

in

mk_Interaction({l1,l2,l3},

{m0C,m0R,m1C,m1R,m2C,m2R,m3C,m3R},{f1},{},{},{}, []);

public trace1 : seq of Occurrence =

let obj1 = mk_Classifier("C1"),

obj2 = mk_Instance("C2", mk_token(2)),

obj3 = mk_Instance("C3", mk_token(3))

in

[ mk_Occurrence(1, 1, obj1, <Call>, "m0", []),

mk_Occurrence(2, 2, obj2, <Call>, "m1", []),

mk_Occurrence(3, 3, obj1, <Call>, "m2", []),

mk_Occurrence(4, 4, obj2, <Call>, "m3", []),

mk_Occurrence(5, 4, obj2, <Reply>, "m3", []),

mk_Occurrence(6, 3, obj1, <Reply>, "m2", []),

mk_Occurrence(7, 2, obj2, <Reply>, "m1", []),

mk_Occurrence(8, 1, obj1, <Reply>, "m0", []) ];

Page 27: UML Checker: Formal Specification in VDM++ of the Petri Net … · 2014-10-25 · UML Checker: Formal Specification in VDM++ of the Petri Net-based Conformance Checking Engine TR-SDBT-2013-04,

UML Checker: Formal Specification in VDM++ 27

operations

public testFig5Accept()≜ (

Assert( accepts(sd2pn(sdFig5), trace1, {}, <StrictConf>) )

);

7.4 ATM example with synchronous messages, 'alt' and 'par'

The next example was adapted from Fig.3 of our ICTSS 2013 paper. Numbers in red were added to identify lifeline

locations.

1

3

45

6

7 (ret)8

9

1011

13

12

14 (ret)15

1617

18

19

2021

2 (ret)

values

private p1 : Parameter = mk_Parameter("balance", <InParam>);

private p2 : Parameter = mk_Parameter("amount", <InParam>);

public sdFig3 : Interaction =

let l1 = mk_Lifeline("Client", nil),

l2 = mk_Lifeline("Account", "a"),

l3 = mk_Lifeline("Movement", "m"),

l4 = mk_Lifeline("Movement", "n"),

o11 = mk_InteractionOperand(mk_InteractionConstraint(nil, nil,

mk_Expression(<Lte>,[p2, p1])), {mk_(l1, 3), mk_(l2, 3), mk_(l3, 3), mk_(l4,

3)}, {mk_(l1, 18), mk_(l2, 18), mk_(l3, 18), mk_(l4, 18)}),

Page 28: UML Checker: Formal Specification in VDM++ of the Petri Net … · 2014-10-25 · UML Checker: Formal Specification in VDM++ of the Petri Net-based Conformance Checking Engine TR-SDBT-2013-04,

UML Checker: Formal Specification in VDM++ 28

o12 = mk_InteractionOperand(mk_InteractionConstraint(nil, nil,<else>),

{mk_(l1, 18), mk_(l2, 18), mk_(l3, 18), mk_(l4, 18)}, {mk_(l1, 21), mk_(l2, 21),

mk_(l3, 21), mk_(l4, 21)}),

o21 = mk_InteractionOperand(nil, {mk_(l2, 5), mk_(l3, 5), mk_(l4, 5)},

{mk_(l2, 8), mk_(l3, 8), mk_(l4, 8)}),

o22 = mk_InteractionOperand(nil, { mk_(l2, 8), mk_(l3, 8), mk_(l4, 8)},

{mk_(l2, 16), mk_(l3, 16), mk_(l4, 16)}),

o31 = mk_InteractionOperand(nil, {mk_(l2, 9), mk_(l3, 9), mk_(l4, 9)},

{mk_(l2, 12), mk_(l3, 12), mk_(l4, 12)}),

o32 = mk_InteractionOperand(nil, {mk_(l2, 12), mk_(l3, 12), mk_(l4, 12)},

{mk_(l2, 15), mk_(l3, 15), mk_(l4, 15)}),

f1 = mk_CombinedFragment(1, <alt>, [o11, o12], {l1, l2, l3, l4}),

f2 = mk_CombinedFragment(1, <par>, [o21, o22], {l2, l3, l4}),

f3 = mk_CombinedFragment(1, <alt>, [o31, o32], {l2, l3, l4}),

m0C = mk_Message(1, 1, mk_(l1, 1), mk_(l2, 1), <createMessage>, "Account",

[p1]),

m0R = mk_Message(2, 1, mk_(l2, 2), mk_(l1, 2), <reply>, "Account", [l2]),

m1C = mk_Message(3, 2, mk_(l1, 4), mk_(l2, 4), <synchCall>, "withdraw",

[p2]),

m1R = mk_Message(4, 2, mk_(l2, 17), mk_(l1, 17), <reply>, "withdraw",

["OK"]),

m2C = mk_Message(5, 3, mk_(l2, 6), mk_(l2, 6), <synchCall>, "setBalance",

[mk_Expression(<Minus>,[p1,p2])]),

m2R = mk_Message(6, 3, mk_(l2, 7), mk_(l2, 7), <reply>, "setBalance", []),

m3C = mk_Message(7, 4, mk_(l2, 10), mk_(l3, 10), <createMessage>,

"Movement", [l2, p2, "withdraw"]),

m3R = mk_Message(8, 4, mk_(l3, 11), mk_(l2, 11), <reply>, "Movement", [l3]),

m4C = mk_Message(9, 5, mk_(l2, 13), mk_(l4, 13), <createMessage>,

"Movement", [l2, mk_Expression(<Minus>, [0, p2])]),

m4R = mk_Message(10, 5, mk_(l4, 14), mk_(l2, 14), <reply>, "Movement",

[l4]),

m5C = mk_Message(11, 6, mk_(l1, 19), mk_(l2, 19), <synchCall>, "withdraw",

[p2]),

m5R = mk_Message(12, 6, mk_(l2, 20), mk_(l1, 20), <reply>, "withdraw",

["INSUF_BALANCE"])

in

mk_Interaction({l1,l2,l3, l4}, {m0C,m0R,m1C,m1R,m2C,m2R,m3C,m3R, m4C, m4R,

m5C, m5R},{f1, f2, f3}, {}, {}, {}, [p1, p2]);

Next, the resulting Petri Net (partially simplified). Underlined events are to be generated by the test harness.

Page 29: UML Checker: Formal Specification in VDM++ of the Petri Net … · 2014-10-25 · UML Checker: Formal Specification in VDM++ of the Petri Net-based Conformance Checking Engine TR-SDBT-2013-04,

UML Checker: Formal Specification in VDM++ 29

14

4

2

1

1: Account(balance)

3

1’:‎return‎a

2: a.withdraw(amount)

3: a.setBalance( balance-amount)

5

3’:‎return

12

4: Movement(a, amount,‎“withdraw”)

4’:‎return‎m

16

15

6: a.withdraw(

amount)

6’:‎return‎“INSUF_BALANCE”2’:‎return‎“Ok”

6

9

7 13

[! (amount<=balance)][amount <= balance]

10

5’:‎return‎n

5: Movement(a, -amount)

8

11

$g

$g

$g

$g

$g

$g

$g

$g $g

$g

17

$g

$x

The next execution trace corresponds to an execution trace adapted from Fig. 7 of our ICTSS 2013 paper.

1: Account(100)

1’:‎return‎a1

2: a1.withdraw(50)

3: a1.getBalance()

3’:‎return‎100

4: Movement(a1,

50, “withdraw”)

4’:‎return m1

5: a1.setBalance(50)

5’:‎return

2’:‎return‎“Ok”

≺M, L, C≻ = ≺{1↦1}, {}, {}≻

≺{2↦[1]}, {}, {1}≻

≺{4↦1}, {a↦a1},‎{1,1’}≻

≺{5↦1,17↦[2],11↦1}, {a↦a1}, {1,1’,2}≻

≺{5↦1,17↦[2],12↦[4]}, {a↦a1}, {1,1’,2,4}≻

≺{5↦1,17↦[2],13↦1},{a↦a1,m↦m1},{1,1’,2,4,4’}≻

≺{6↦[5],17↦[2],13↦1},{a↦a1,m↦m1},{1,1’,2,4,4’,3}≻

≺{7↦1,17↦[2],13↦1},{a↦a1,m↦m1},1,1’,2,4,4’,3,3’}≻

≺{16↦1}, {a↦a1,m↦m1},{1,1’,2,4,4’,3,3’,2’}≻

(unchanged, call ignored)

(unchanged, reply ignored)

Execution Trace EPN Run States(s)

P={balance ↦ 100, amount ↦ 50}

≺{5↦1,17↦[2],9↦1},{a↦a1},{1,1’,2}≻

(unchanged, call ignored)

(unchanged, reply ignored)

(unchanged, call ignored)

(unchanged, reply ignored)

≺{6↦[5],17↦[2],9↦1},{a↦a1},{1,1’,2,3}≻

≺{7↦1,17↦[2],9↦1},{a↦a1},{1,1’,2,3,3’}≻

must consider 2’, but active states don’t accept it

values

Page 30: UML Checker: Formal Specification in VDM++ of the Petri Net … · 2014-10-25 · UML Checker: Formal Specification in VDM++ of the Petri Net-based Conformance Checking Engine TR-SDBT-2013-04,

UML Checker: Formal Specification in VDM++ 30

public traceFig7 : seq of Occurrence =

let obj1 = mk_Instance("Account", mk_token(1)),

obj2 = mk_Instance("Movement", mk_token(2))

in

[ mk_Occurrence(1, 1, obj1, <Call>, "Account", [100]),

mk_Occurrence(2, 1, obj1, <Reply>, "Account", [obj1]),

mk_Occurrence(3, 3, obj1, <Call>, "withdraw", [50]),

mk_Occurrence(4, 4, obj1, <Call>, "getBalance", []),

mk_Occurrence(5, 4, obj1, <Reply>, "getBalance ", [100]),

mk_Occurrence(6, 5, obj2, <Call>, "Movement", [obj1, 50, "withdraw"]),

mk_Occurrence(7, 5, obj2, <Reply>, "Movement", [obj2]),

mk_Occurrence(8, 6, obj1, <Call>, "setBalance", [50]),

mk_Occurrence(9, 6, obj1, <Reply>, "setBalance", []),

mk_Occurrence(10, 3, obj1, <Reply>, "withdraw", ["OK"]) ];

operations

public testFig7Accept() ≜ (

Assert( acceptsWithInfo(sd2pn(sdFig3), traceFig7, {p1 100, p2 50},

<LooseConf>) = mk_(true, {1,2, 3, 4, 5, 6, 7, 8}))

);

7.5 Asynchronous user interaction

This example refers to Fig. 9 in our ICTSS 2013 paper.

sd UserInteractionTesting

Console

Simulator

Output

Blocking

Queue

Test

Driver

(thread 0)

Input

Blocking

Queue

Tracing

Aspect

AUT

(thread 1)

(wait)

(wait)

start(app, args)main(args)

scan()poll(timeout)

enter(x)put(x)

:x :x

check()poll(timeout)

print(y)put(y)

:y

:y

assertEquals(exp, y)

stop() join(timeout)

send-

display

send-

startrcv-

start

rcv-

enter

send-

enter

rcv-

display

sd InteractionTestingSpec

User

AUT

start(args)

enter(x)

display(y)

Implementation & Tracing

send-start(args)

rcv-start(args)

rcv-enter(x)

send-enter(x)

send-display(y)

rcv-display(y)

Automaton

possibly

internal

interactinos

here

SD

operations

public testAsynchUI() ≜

Page 31: UML Checker: Formal Specification in VDM++ of the Petri Net … · 2014-10-25 · UML Checker: Formal Specification in VDM++ of the Petri Net-based Conformance Checking Engine TR-SDBT-2013-04,

UML Checker: Formal Specification in VDM++ 31

(

let

x = mk_Parameter("x", <InParam>),

y = mk_Parameter("y", <InParam>),

User = mk_Lifeline("User", nil),

AUT = mk_Lifeline("AUT", nil),

m1 = mk_Message(1, 1, mk_(User, 1), mk_(AUT, 1), <asynchSignal>, "start",

[]),

m2 = mk_Message(2, 2, mk_(User, 2), mk_(AUT, 2), <asynchSignal>, "enter",

[x]),

m3 = mk_Message(3, 3, mk_(AUT, 3), mk_(User, 3), <asynchSignal>,

"display", [y]),

pn1 = sd2pn(mk_Interaction({User, AUT}, {m1, m2, m3}, {}, {}, {}, {}, [x,

y])),

U = mk_Classifier("User"),

A = mk_Classifier("AUT"),

o1 = mk_Occurrence(1, 1, A, <Send>, "start", []),

o2 = mk_Occurrence(2, 1, A, <Receive>, "start", []),

o3 = mk_Occurrence(3, 2, A, <Send>, "enter", [1]),

o4 = mk_Occurrence(4, 2, A, <Receive>, "enter", [1]),

o5 = mk_Occurrence(5, 3, U, <Send>, "display", [2]),

o6 = mk_Occurrence(6, 3, U, <Receive>, "display", [2])

in

(

Assert(accepts(pn1, [o1,o2,o3,o4,o5,o6], {x1, y2}, <StrictConf>));

Assert(accepts(pn1, [o1,o3,o2,o4,o5,o6], {x1, y2}, <StrictConf>));

Assert(acceptsWithInfo(pn1, [o1,o2,o3,o5,o4,o6], {x1, y2},

<StrictConf>) = mk_(false, {1, 2}) )

)

);

7.6 Loops with synchronous messages

operations

public testLoop() ≜ (

let l1 = mk_Lifeline("C1", "o1"),

l2 = mk_Lifeline("C2", "o2"),

o1 = mk_InteractionOperand(mk_InteractionConstraint(1, 2, nil),

{mk_(l1, 1), mk_(l2, 1)}, {mk_(l1, 4), mk_(l2, 4)}),

o2 = mk_InteractionOperand(mk_InteractionConstraint(nil, 2, nil),

{mk_(l1, 1), mk_(l2, 1)}, {mk_(l1, 4), mk_(l2, 4)}),

o3 = mk_InteractionOperand(mk_InteractionConstraint(1, nil, nil),

{mk_(l1, 1), mk_(l2, 1)}, {mk_(l1, 4), mk_(l2, 4)}),

o4 = mk_InteractionOperand(mk_InteractionConstraint(nil, nil, nil),

{mk_(l1, 1), mk_(l2, 1)}, {mk_(l1, 4), mk_(l2, 4)}),

f1 = mk_CombinedFragment(1, <loop>, [o1], {l1, l2 }),

f2 = mk_CombinedFragment(1, <loop>, [o2], {l1, l2 }),

f3 = mk_CombinedFragment(1, <loop>, [o3], {l1, l2 }),

f4 = mk_CombinedFragment(1, <loop>, [o4], {l1, l2 }),

m0C = mk_Message(1, 1, mk_(l1, 2), mk_(l2, 2), <synchCall>, "m0", []),

m0R = mk_Message(2, 1, mk_(l2, 3), mk_(l1, 3), <reply>, "m0", []),

pn1 = sd2pn(mk_Interaction({l1,l2}, {m0C, m0R},{f1}, {}, {}, {}, [])),

Page 32: UML Checker: Formal Specification in VDM++ of the Petri Net … · 2014-10-25 · UML Checker: Formal Specification in VDM++ of the Petri Net-based Conformance Checking Engine TR-SDBT-2013-04,

UML Checker: Formal Specification in VDM++ 32

pn2 = sd2pn(mk_Interaction({l1,l2}, {m0C, m0R},{f2}, {}, {}, {}, [])),

pn3 = sd2pn(mk_Interaction({l1,l2}, {m0C, m0R},{f3}, {}, {}, {}, [])),

pn4 = sd2pn(mk_Interaction({l1,l2}, {m0C, m0R},{f4}, {}, {}, {}, [])),

obj1 = mk_Instance("C1", mk_token(1)),

obj2 = mk_Instance("C2", mk_token(2)),

oc1 = mk_Occurrence(1, 1, obj2, <Call>, "m0", []),

oc2 = mk_Occurrence(2, 1, obj2, <Reply>, "m0", []),

oc3 = mk_Occurrence(3, 2, obj2, <Call>, "m0", []),

oc4 = mk_Occurrence(4, 2, obj2, <Reply>, "m0", []),

oc5 = mk_Occurrence(5, 3, obj2, <Call>, "m0", []),

oc6 = mk_Occurrence(6, 3, obj2, <Reply>, "m0", [])

in

(

-- loop(1,2)

Assert( accepts(pn1, [], {}, <StrictConf>) );

Assert(accepts(pn1, [oc1, oc2], {}, <StrictConf>) );

Assert(accepts(pn1, [oc1, oc2, oc3, oc4], {}, <StrictConf>) );

Assert( accepts(pn1, [oc1, oc2, oc3, oc4, oc5, oc6], {}, <StrictConf>));

Assert(accepts(pn1, [oc1, oc2, oc3, oc4, oc5, oc6], {}, <LooseConf>));

-- loop(nil,2)

Assert(accepts(pn2, [], {}, <StrictConf>) );

Assert(accepts(pn2, [oc1, oc2], {}, <StrictConf>) );

Assert(accepts(pn2, [oc1, oc2, oc3, oc4], {}, <StrictConf>) );

Assert( accepts(pn2, [oc1, oc2, oc3, oc4, oc5, oc6], {}, <StrictConf>));

Assert(accepts(pn2, [oc1, oc2, oc3, oc4, oc5, oc6], {}, <LooseConf>));

-- loop(1,nil)

Assert( accepts(pn3, [], {}, <StrictConf>) );

Assert(accepts(pn3, [oc1, oc2], {}, <StrictConf>) );

Assert(accepts(pn3, [oc1, oc2, oc3, oc4], {}, <StrictConf>) );

Assert(accepts(pn3, [oc1, oc2, oc3, oc4, oc5, oc6], {}, <StrictConf>));

-- loop(nil,nil)

Assert(accepts(pn4, [], {}, <StrictConf>) );

Assert(accepts(pn4, [oc1, oc2], {}, <StrictConf>) );

Assert(accepts(pn4, [oc1, oc2, oc3, oc4], {}, <StrictConf>) );

Assert(accepts(pn4, [oc1, oc2, oc3, oc4, oc5, oc6], {}, <StrictConf>))

)

);

7.7 Loops with asynchronous messages

The next figure shows an example that illustrates the need for asynchronous coordination of decisions.

Page 33: UML Checker: Formal Specification in VDM++ of the Petri Net … · 2014-10-25 · UML Checker: Formal Specification in VDM++ of the Petri Net-based Conformance Checking Engine TR-SDBT-2013-04,

UML Checker: Formal Specification in VDM++ 33

loop m2

L1 L2

send m1 rcv m1$g $g

L1 L2

m1

m3

1 1

send m2 rcv m2$g

22

send m3 rcv m3$g $g

2 2

1 1

sd pn

valid trace

start

L1 L2invalid trace

$g

operations

public testLoopAsynch() ≜ (

let l1 = mk_Lifeline("C1", nil),

l2 = mk_Lifeline("C2", nil),

o1 = mk_InteractionOperand( nil,

{mk_(l1, 2), mk_(l2, 2)}, {mk_(l1, 4), mk_(l2, 4)}),

f1 = mk_CombinedFragment(1, <loop>, [o1], {l1, l2 }),

m1 = mk_Message(1, 1, mk_(l1, 1), mk_(l2, 1), <asynchSignal>, "m1", []),

m2 = mk_Message(2, 2, mk_(l1, 3), mk_(l2, 3), <asynchSignal>, "m2", []),

m3 = mk_Message(3, 3, mk_(l1, 5), mk_(l2, 5), <asynchSignal>, "m3", []),

pn1 = sd2pn(mk_Interaction({l1,l2}, {m1, m2, m3}, {f1}, {}, {}, {}, [])),

c1 = mk_Classifier("C1"),

c2 = mk_Classifier("C2"),

oc1 = mk_Occurrence(1, 1, c2, <Send>, "m1", []),

oc2 = mk_Occurrence(2, 1, c2, <Receive>, "m1", []),

oc3 = mk_Occurrence(3, 2, c2, <Send>, "m2", []),

oc4 = mk_Occurrence(4, 2, c2, <Receive>, "m2", []),

oc5 = mk_Occurrence(5, 3, c2, <Send>, "m2", []),

oc6 = mk_Occurrence(6, 3, c2, <Receive>, "m2", []),

oc7 = mk_Occurrence(7, 4, c2, <Send>, "m3", []),

oc8 = mk_Occurrence(8, 4, c2, <Receive>, "m3", [])

in

(

Assert(accepts(pn1, [oc1, oc2, oc3, oc4, oc5, oc6, oc7, oc8], {},

<StrictConf>));

Assert( synchronizeLifelinesAtDecisionPoints

accepts(pn1, [oc1, oc3, oc2, oc5, oc4, oc7, oc6, oc8], {},

<StrictConf>));

Page 34: UML Checker: Formal Specification in VDM++ of the Petri Net … · 2014-10-25 · UML Checker: Formal Specification in VDM++ of the Petri Net-based Conformance Checking Engine TR-SDBT-2013-04,

UML Checker: Formal Specification in VDM++ 34

Assert( synchronizeLifelinesAtDecisionPoints

accepts(pn1, [oc1, oc3, oc5, oc7, oc2, oc4, oc6, oc8], {},

<StrictConf>));

Assert( accepts(pn1, [oc1, oc2, oc3, oc6, oc5, oc4, oc7, oc8], {},

<StrictConf>))

)

);

7.8 Break

break m2

L1 L2

SD

m1

m3

loop

m4

Valid trace

L1 L2

Invalid trace

L1 L2

operations

public testBreak() ≜ (

let l1 = mk_Lifeline("L1", nil),

l2 = mk_Lifeline("L2", nil),

o1 = mk_InteractionOperand(nil,

{mk_(l1, 1), mk_(l2, 1)}, {mk_(l1, 7), mk_(l2, 7)}),

f1 = mk_CombinedFragment(1, <loop>, [o1], {l1, l2}),

o2 = mk_InteractionOperand(nil,

{mk_(l1, 3), mk_(l2, 3)}, {mk_(l1, 5), mk_(l2, 5)}),

f2 = mk_CombinedFragment(2, <break>, [o2], {l1, l2}),

m1 = mk_Message(1, 1, mk_(l1, 2), mk_(l2, 2), <asynchSignal>, "m1", []),

m2 = mk_Message(2, 2, mk_(l1, 4), mk_(l2, 4), <asynchSignal>, "m2", []),

m3 = mk_Message(3, 3, mk_(l1, 6), mk_(l2, 6), <asynchSignal>, "m3", []),

m4 = mk_Message(4, 4, mk_(l1, 8), mk_(l2, 8), <asynchSignal>, "m4", []),

pn1 = sd2pn(mk_Interaction({l1,l2}, {m1, m2, m3, m4}, {f1, f2}, {}, {},

{}, [])),

c1 = mk_Classifier("L1"),

c2 = mk_Classifier("L2"),

sm1a = mk_Occurrence(1, 1, c2, <Send>, "m1", []),

rm1a = mk_Occurrence(2, 1, c2, <Receive>, "m1", []),

sm1b = mk_Occurrence(3, 2, c2, <Send>, "m1", []),

rm1b = mk_Occurrence(4, 2, c2, <Receive>, "m1", []),

Page 35: UML Checker: Formal Specification in VDM++ of the Petri Net … · 2014-10-25 · UML Checker: Formal Specification in VDM++ of the Petri Net-based Conformance Checking Engine TR-SDBT-2013-04,

UML Checker: Formal Specification in VDM++ 35

sm2a = mk_Occurrence(5, 3, c2, <Send>, "m2", []),

rm2a = mk_Occurrence(6, 3, c2, <Receive>, "m2", []),

sm3a = mk_Occurrence(7, 4, c2, <Send>, "m3", []),

rm3a = mk_Occurrence(8, 4, c2, <Receive>, "m3", []),

sm3b = mk_Occurrence(9, 5, c2, <Send>, "m3", []),

rm3b = mk_Occurrence(10, 5, c2, <Receive>, "m3", []),

sm4a = mk_Occurrence(11, 6, c2, <Send>, "m4", []),

rm4a = mk_Occurrence(12, 6, c2, <Receive>, "m4", [])

in

(

Assert(accepts(pn1, [sm1a, sm3a, rm1a, sm1b, rm3a, sm2a, rm1b, sm4a, rm2a,

rm4a], {}, <StrictConf>));

Assert( accepts(pn1, [sm1a, sm2a, rm1a, sm1b, rm2a, sm3a, rm1b, sm4a, rm3a,

rm4a], {}, <StrictConf>));

)

);

7.9 General ordering

L1 L2

SD

m1

L3 L4

m2

L1 L2

Valid trace

L3 L4

L1 L2

Invalid trace

L3 L4

operations

public testGeneralOrdering() ≜

Page 36: UML Checker: Formal Specification in VDM++ of the Petri Net … · 2014-10-25 · UML Checker: Formal Specification in VDM++ of the Petri Net-based Conformance Checking Engine TR-SDBT-2013-04,

UML Checker: Formal Specification in VDM++ 36

(

let l1 = mk_Lifeline("L1", nil),

l2 = mk_Lifeline("L2", nil),

l3 = mk_Lifeline("L3", nil),

l4 = mk_Lifeline("L4", nil),

m1 = mk_Message(1, 1, mk_(l1, 1), mk_(l2, 1), <asynchSignal>, "m1", []),

m2 = mk_Message(2, 2, mk_(l3, 2), mk_(l4, 2), <asynchSignal>, "m2", []),

g1 = mk_GeneralOrdering(mk_(l1, 1), mk_(l3, 2)),

pn1 = sd2pn(mk_Interaction({l1,l2,l3,l4}, {m1, m2 }, {}, {g1}, {}, {},

[])),

pn2 = sd2pn(mk_Interaction({l1,l2,l3,l4}, {m1, m2 }, {}, { }, {}, {}, [])),

c1 = mk_Classifier("L1"),

c2 = mk_Classifier("L2"),

c3 = mk_Classifier("L3"),

c4 = mk_Classifier("L4"),

oc1 = mk_Occurrence(1, 1, c2, <Send>, "m1", []),

oc2 = mk_Occurrence(2, 1, c2, <Receive>, "m1", []),

oc3 = mk_Occurrence(3, 2, c2, <Send>, "m2", []),

oc4 = mk_Occurrence(4, 2, c2, <Receive>, "m2", [])

in

(

Assert(accepts(pn1, [oc1, oc3, oc4, oc2], {}, <StrictConf>));

Assert( accepts(pn1, [oc3, oc1, oc2, oc4], {}, <StrictConf>));

Assert(accepts(pn2, [oc3, oc1, oc2, oc4], {}, <StrictConf>));

)

);

7.10 Co-region

L1 L2

SD

m1

m2

L1 L2

Valid trace

operations

public testCoregion() ≜ (

let l1 = mk_Lifeline("L1", nil),

l2 = mk_Lifeline("L2", nil),

o1 = mk_InteractionOperand(nil, {mk_(l2, 1)}, {mk_(l2, 3)}),

o2 = mk_InteractionOperand(nil, {mk_(l2, 3)}, {mk_(l2, 5)}),

f1 = mk_CombinedFragment(1, <par>, [o1, o2], { l2}),

m1 = mk_Message(1, 1, mk_(l1, 2), mk_(l2, 2), <asynchSignal>, "m1", []),

m2 = mk_Message(2, 2, mk_(l1, 4), mk_(l2, 4), <asynchSignal>, "m2", []),

pn1 = sd2pn(mk_Interaction({l1,l2}, {m1, m2 }, {f1 }, {}, {}, {}, [])),

c1 = mk_Classifier("L1"),

Page 37: UML Checker: Formal Specification in VDM++ of the Petri Net … · 2014-10-25 · UML Checker: Formal Specification in VDM++ of the Petri Net-based Conformance Checking Engine TR-SDBT-2013-04,

UML Checker: Formal Specification in VDM++ 37

c2 = mk_Classifier("L2"),

sm1 = mk_Occurrence(1, 1, c2, <Send>, "m1", []),

rm1 = mk_Occurrence(2, 1, c2, <Receive>, "m1", []),

sm2 = mk_Occurrence(3, 2, c2, <Send>, "m2", []),

rm2 = mk_Occurrence(4, 2, c2, <Receive>, "m2", [])

in

(

Assert(accepts(pn1, [sm1, sm2, rm2, rm1], {}, <StrictConf>));

Assert(accepts(pn1, [sm1, sm2, rm1, rm2], {}, <StrictConf>));

Assert( accepts(pn1, [sm2, sm1, rm1, rm2], {}, <StrictConf>))

)

);

7.11 Critical region

operations

public testCriticalRegion()≜ (

let l1 = mk_Lifeline("Emergency", "emergency"),

l2 = mk_Lifeline("Operator", "operator"),

l3 = mk_Lifeline("Caller", "caller"),

l4 = mk_Lifeline("Callee", "callee"),

o1 = mk_InteractionOperand(nil,

{mk_(l1, 1), mk_(l2, 1), mk_(l3, 1), mk_(l4, 1)},

{mk_(l1, 4), mk_(l2, 4), mk_(l3, 4), mk_(l4, 4)}),

o2 = mk_InteractionOperand(nil,

{mk_(l1, 4), mk_(l2, 4), mk_(l3, 4), mk_(l4, 4)},

{mk_(l1, 7), mk_(l2, 7), mk_(l3, 7), mk_(l4, 7)}),

o3 = mk_InteractionOperand(nil,

{mk_(l1, 7), mk_(l2, 7), mk_(l3, 7), mk_(l4, 7)},

Page 38: UML Checker: Formal Specification in VDM++ of the Petri Net … · 2014-10-25 · UML Checker: Formal Specification in VDM++ of the Petri Net-based Conformance Checking Engine TR-SDBT-2013-04,

UML Checker: Formal Specification in VDM++ 38

{mk_(l1, 12), mk_(l2, 12), mk_(l3, 12), mk_(l4, 12)}),

f1 = mk_CombinedFragment(1, <par>, [o1, o2, o3], {l1, l2, l3, l4}),

o4 = mk_InteractionOperand(nil,

{mk_(l1, 8), mk_(l2, 8)}, {mk_(l1, 11), mk_(l2, 11)}),

f2 = mk_CombinedFragment(2, <critical>, [o4], {l1, l2}),

m1 = mk_Message(1,1,mk_(l3,2),mk_(l2,2),<asynchSignal>,"call",[100]),

m2 = mk_Message(2,2,mk_(l2,3),mk_(l4,3),<asynchSignal>,"call",[100]),

m3 = mk_Message(3,3,mk_(l3,5),mk_(l2,5),<asynchSignal>,"call",[101]),

m4 = mk_Message(4,4,mk_(l2,6),mk_(l4,6),<asynchSignal>,"call",[101]),

m5 = mk_Message(5,5,mk_(l3,9),mk_(l2,9),<asynchSignal>,"call",[911]),

m6 =mk_Message(6,6,mk_(l2,10),mk_(l1,10),<asynchSignal>,"call",[911]),

pn1 = sd2pn(mk_Interaction({l1,l2,l3,l4}, {m1, m2, m3, m4, m5, m6}, {f1,

f2}, {}, {}, {}, [])),

o1 = mk_Instance("Emergency", mk_token(1)),

o2 = mk_Instance("Operator", mk_token(2)),

o3 = mk_Instance("Caller", mk_token(3)),

o4 = mk_Instance("Callee", mk_token(4)),

sm1 = mk_Occurrence(1, 1, o2, <Send>, "call", [100]),

rm1 = mk_Occurrence(2, 1, o2, <Receive>, "call", [100]),

sm2 = mk_Occurrence(3, 2, o4, <Send>, "call", [100]),

rm2 = mk_Occurrence(4, 2, o4, <Receive>, "call", [100]),

sm3 = mk_Occurrence(5, 3, o2, <Send>, "call", [101]),

rm3 = mk_Occurrence(6, 3, o2, <Receive>, "call", [101]),

sm4 = mk_Occurrence(7, 4, o4, <Send>, "call", [101]),

rm4 = mk_Occurrence(8, 4, o4, <Receive>, "call", [101]),

sm5 = mk_Occurrence(9, 5, o2, <Send>, "call", [911]),

rm5 = mk_Occurrence(10, 5, o2, <Receive>, "call", [911]),

sm6 = mk_Occurrence(11, 6, o1, <Send>, "call", [911]),

rm6 = mk_Occurrence(12, 6, o1, <Receive>, "call", [911])

in

(

Assert(accepts(pn1, [sm1, rm1, sm2, rm2, sm5, rm5, sm6, rm6, sm3, rm3, sm4,

rm4], {}, <StrictConf>));

Assert(accepts(pn1, [sm5, rm5, sm6, rm6, sm1, sm3, rm1, rm3, sm4, rm4, sm2,

rm2], {}, <StrictConf>));

Assert(accepts(pn1, [sm1, sm3, rm1, rm3, sm4, rm4, sm2, rm2, sm5, rm5, sm6,

rm6], {}, <StrictConf>));

Assert(accepts(pn1, [sm1, rm1, sm2, rm2, sm3, sm5, rm5, sm6, rm6, rm3, sm4,

rm4], {}, <StrictConf>));

Assert(accepts(pn1, [sm1, rm1, sm3, rm3, sm5, rm5, sm6, rm6, sm4, rm4, sm2,

rm2], {}, <StrictConf>));

Assert(accepts(pn1, [sm1, sm3, rm1, sm5, rm5, sm6, rm6, rm3, sm4, rm4, sm2,

rm2], {}, <StrictConf>));

Assert(accepts(pn1, [sm1, sm3, sm5, rm1, rm5, sm6, rm6, rm3, sm4, rm4, sm2,

rm2], {}, <StrictConf>));

Assert( accepts(pn1, [sm1, sm3, sm5, rm1, rm5, rm3, sm6, rm6, sm4, rm4,

sm2, rm2], {}, <StrictConf>));

)

);

Page 39: UML Checker: Formal Specification in VDM++ of the Petri Net … · 2014-10-25 · UML Checker: Formal Specification in VDM++ of the Petri Net-based Conformance Checking Engine TR-SDBT-2013-04,

UML Checker: Formal Specification in VDM++ 39

7.12 Interaction use

ref

sd sd1(in x, out y)

sd2(x, y)

L1 L2

m1(x)

:y

L3

sd sd2(in z, out w)

L2 L3

m2(z)

:w

L1 L2

m1(1)

:2

L3

Valid trace

m2(1)

:2

L1 L2

m1(1)

:2

L3

Invalid trace

m2(2)

:1

operations

public testInteractionUse ()≜ (

let l2 = mk_Lifeline("L2", nil),

l3 = mk_Lifeline("L3", nil),

z = mk_Parameter("z", <InParam>),

w = mk_Parameter("w", <OutParam>),

m2c = mk_Message(1, 1, mk_(l2,1), mk_(l3,1), <synchCall>, "m2", [z]),

m2r = mk_Message(2, 1, mk_(l3,2), mk_(l2,2), <reply>, "m2", [w]),

sd2 = mk_Interaction({l2,l3 }, {m2c, m2r}, {}, {}, {}, {}, [z, w]),

l1 = mk_Lifeline("L1", nil),

x = mk_Parameter("x", <InParam>),

y = mk_Parameter("y", <OutParam>),

m1c = mk_Message(3, 2, mk_(l1,1), mk_(l2,1), <synchCall>, "m1", [x]),

m1r = mk_Message(4, 2, mk_(l2,3), mk_(l1,3), <reply>, "m1", [y]),

ref1 = mk_InteractionUse(1, sd2, [x, y], {l2, l3},{mk_(l2,2),mk_(l3,2)}),

sd1 = mk_Interaction({l1, l2,l3 }, {m1c, m1r}, {}, {}, {ref1}, {}, [x,

y]),

pn1 = sd2pn(sd1),

c1 = mk_Classifier("L1"),

c2 = mk_Classifier("L2"),

c3 = mk_Classifier("L2"),

sm1 = mk_Occurrence(1, 1, c2, <Call>, "m1", [1]),

rm1 = mk_Occurrence(2, 1, c2, <Reply>, "m1", [2]),

sm2a = mk_Occurrence(3, 2, c3, <Call>, "m2", [1]),

rm2a = mk_Occurrence(4, 2, c3, <Reply>, "m2", [2]),

sm2b = mk_Occurrence(5, 3, c3, <Call>, "m2", [2]),

rm2b = mk_Occurrence(6, 3, c3, <Reply>, "m2", [1])

in

(

Assert(accepts(pn1, [sm1, sm2a, rm2a, rm1], {x1}, <StrictConf>));

Assert( accepts(pn1, [sm1, sm2b, rm2b, rm1], {x1}, <StrictConf>));

)

);

7.13 Assert and negate fragments

Assert fragments ('assert') are simply handled as weak sequencing fragments (seq), so no test was designed. More

tricky are the 'neg' combined fragments.

Page 40: UML Checker: Formal Specification in VDM++ of the Petri Net … · 2014-10-25 · UML Checker: Formal Specification in VDM++ of the Petri Net-based Conformance Checking Engine TR-SDBT-2013-04,

UML Checker: Formal Specification in VDM++ 40

neg m2

L1 L2

SD

m1

m3

m4

Valid trace

(strict mode)

L1 L2

Invalid trace

(strict mode)

L1 L2

Valid trace

(strict mode)

L1 L2

Invalid trace

(strict mode)

L1 L2

operations

public testNegative () ≜ (

let l1 = mk_Lifeline("L1", nil),

l2 = mk_Lifeline("L2", nil),

o1 = mk_InteractionOperand(nil,

{mk_(l1, 2), mk_(l2, 2)}, {mk_(l1, 5), mk_(l2, 5)}),

f1 = mk_CombinedFragment(1, <neg>, [o1], {l1, l2 }),

m1 = mk_Message(1,1,mk_(l1,1),mk_(l2,1),<asynchSignal>,"m1",[]),

m2 = mk_Message(2,2,mk_(l1,3),mk_(l2,3),<asynchSignal>,"m2",[]),

m3 = mk_Message(3,3,mk_(l1,4),mk_(l2,4),<asynchSignal>,"m3",[]),

m4 = mk_Message(4,4,mk_(l1,6),mk_(l2,6),<asynchSignal>,"m4",[]),

pn1 = sd2pn(mk_Interaction({l1,l2 }, {m1, m2, m3, m4 }, {f1 }, {}, {},

{}, [])),

c1 = mk_Classifier("L1"),

c2 = mk_Classifier("L2"),

sm1 = mk_Occurrence(1, 1, c2, <Send>, "m1", []),

rm1 = mk_Occurrence(2, 1, c2, <Receive>, "m1", []),

sm2a = mk_Occurrence(3, 2, c2, <Send>, "m2", []),

rm2a = mk_Occurrence(4, 2, c2, <Receive>, "m2", []),

sm2b = mk_Occurrence(5, 3, c2, <Send>, "m2", []),

rm2b = mk_Occurrence(6, 3, c2, <Receive>, "m2", []),

sm3 = mk_Occurrence(7, 4, c2, <Send>, "m3", []),

rm3 = mk_Occurrence(8, 4, c2, <Receive>, "m3", []),

sm4a = mk_Occurrence(9, 5, c2, <Send>, "m4", []),

rm4a = mk_Occurrence(10, 5, c2, <Receive>, "m4", []),

sm4b = mk_Occurrence(11, 6, c2, <Send>, "m4", []),

rm4b = mk_Occurrence(12, 6, c2, <Receive>, "m4", []),

sm5 = mk_Occurrence(13, 7, c2, <Send>, "m5", []),

rm5 = mk_Occurrence(14, 7, c2, <Receive>, "m5", [])

in

(

Assert(accepts(pn1, [sm1, rm1, sm4a, rm4a], {}, <StrictConf>));

Assert( accepts(pn1, [sm1, rm1, sm2a, rm2a, sm3, rm3, sm4a, rm4a], {},

<StrictConf>));

Assert(accepts(pn1, [sm1, sm4a, rm1, rm4a], {}, <StrictConf>));

Assert( accepts(pn1, [sm1, sm2a, sm3, sm4a, rm1, rm2a, rm3,

sm4a, rm4a], {}, <StrictConf>));

Page 41: UML Checker: Formal Specification in VDM++ of the Petri Net … · 2014-10-25 · UML Checker: Formal Specification in VDM++ of the Petri Net-based Conformance Checking Engine TR-SDBT-2013-04,

UML Checker: Formal Specification in VDM++ 41

Assert(accepts(pn1, [sm1, sm2a, rm1, sm2b, rm2a, sm3, rm2b, sm4a, rm3, sm4b,

rm4a, rm4b], {}, <StrictConf>));

Assert( accepts(pn1, [sm1, sm2a, rm1, sm3, rm2a, sm5, rm3, sm4a, rm5, rm4a],

{}, <StrictConf>));

)

);

7.14 Consider and ignore fragments

ignore y x

L1 L2

SD

z

Valid trace

(strict conf.)

L1 L2

Invalid trace

(strict conf.)

L1 L2

operations

public testConsiderIgnore()≜ (

let l1 = mk_Lifeline("L1", nil),

l2 = mk_Lifeline("L2", nil),

x = mk_Message(1, 1, mk_(l1,2), mk_(l2,2), <asynchSignal>, "x", []),

z = mk_Message(2, 2, mk_(l1,4), mk_(l2,4), <asynchSignal>, "z", []),

f = mk_ConsiderIgnoreFragment(1, <ignore>, {l1, l2}, {"y"},

{mk_(l1,1), mk_(l2,1)}, {mk_(l1, 3), mk_(l2, 3)}),

sd1 = mk_Interaction({l1,l2 }, {x, z}, {}, {}, {}, {f}, []),

pn1 = sd2pn(sd1),

c1 = mk_Classifier("L1"),

c2 = mk_Classifier("L2"),

sx = mk_Occurrence(1, 1, c2, <Send>, "x", []),

rx = mk_Occurrence(2, 1, c2, <Receive>, "x", []),

sya = mk_Occurrence(3, 2, c2, <Send>, "y", []),

rya = mk_Occurrence(4, 2, c2, <Receive>, "y", []),

sz = mk_Occurrence(5, 3, c2, <Send>, "z", []),

rz = mk_Occurrence(6, 3, c2, <Receive>, "z", []),

syb = mk_Occurrence(7, 4, c2, <Send>, "y", []),

ryb = mk_Occurrence(8, 4, c2, <Receive>, "y", [])

in

(

Assert(accepts(pn1, [sx, sz, rx, rz], { }, <StrictConf>));

Assert(accepts(pn1, [sya, sx, rya, syb, rx, sz, ryb, rz], { },

<StrictConf>));

Page 42: UML Checker: Formal Specification in VDM++ of the Petri Net … · 2014-10-25 · UML Checker: Formal Specification in VDM++ of the Petri Net-based Conformance Checking Engine TR-SDBT-2013-04,

UML Checker: Formal Specification in VDM++ 42

Assert( accepts(pn1, [sya, sx, rya, sz, rx, syb, rz, ryb], { },

<StrictConf>));

)

);

7.15 Test execution

public testAll() ≜ (

testTrivial();

testFig5Accept();

testFig7Accept();

testAsynchUI();

testLoop();

testLoopAsynch();

testGeneralOrdering();

testCoregion();

testBreak();

testCriticalRegion();

testNegative();

testInteractionUse();

testConsiderIgnore()

);

8 Conclusion

This concludes this report the VDM++ specification.

end UMLChecker

References [1] J. P.Faria, A. Paiva and Mário V. Castro, Techniques and Toolset for Conformance Testing against UML Sequence Diagrams, ICTSS

2013.

[2] The IFAD VDM++ Language - Revised for V6.6, IFAD, 2000

[3] OMG Unified Modeling LanguageTM (OMG UML), Superstructure, Version 2.4.1, OMG, August 2011.

[4] J. P.Faria, A. Paiva, A Toolset for Conformance Testing against UML Sequence Diagrams using Extended Petri Nets, International Journal on Software Tools for Technology Transfer, Springer , 2014 (submited)