diff options
Diffstat (limited to 'test/w3c/compound/test-ecma-all.scxml')
-rw-r--r-- | test/w3c/compound/test-ecma-all.scxml | 6012 |
1 files changed, 6012 insertions, 0 deletions
diff --git a/test/w3c/compound/test-ecma-all.scxml b/test/w3c/compound/test-ecma-all.scxml new file mode 100644 index 0000000..a6f36fb --- /dev/null +++ b/test/w3c/compound/test-ecma-all.scxml @@ -0,0 +1,6012 @@ +<scxml datamodel="ecmascript"> + + <!-- test that events are inserted into the queue in the order in which they are raised. If + foo occurs before bar, success, otherwise failure --> + <state id="144start" initial="144s0"> + <state id="144s0"> + <onentry> + <raise event="foo"/> + <raise event="bar"/> + </onentry> + <transition event="foo" target="144s1"/> + <transition event="*" target="144fail"/> + </state> + <state id="144s1"> + <transition event="bar" target="144pass"/> + <transition event="*" target="144fail"/> + </state> + <state id="144pass"> + <onentry> + <send event="test.144.done" /> + </onentry> + <transition event="test.144.done" target="147start" /> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </state> + <final id="144fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> + </state> + + <!-- test that the first clause that evaluates to true - and only that clause - is executed. + Only one event should be raised, and it should be bar --> + <state id="147start" initial="147s0"> + <datamodel> + <data id="Var1471" expr="0"/> + </datamodel> + <state id="147s0"> + <onentry> + <if cond="false"> + <raise event="foo"/> + <assign location="Var1471" expr="Var1471 + 1"/> + <elseif cond="true"/> + <raise event="bar"/> + <assign location="Var1471" expr="Var1471 + 1"/> + <else/> + <raise event="baz"/> + <assign location="Var1471" expr="Var1471 + 1"/> + </if> + <raise event="bat"/> + </onentry> + <transition event="bar" cond="Var1471==1" target="147pass"/> + <transition event="*" target="147fail"/> + </state> + <state id="147pass"> + <onentry> + <send event="test.147.done" /> + </onentry> + <transition event="test.147.done" target="148start" /> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </state> + <final id="147fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> + </state> + + <!-- test that the else clause executes if <if> and <elseif> evaluate to false. + Baz should be the only event generated by the <if>. bat is raised to catch the case where the <else> clause + fails and baz is not generated, i.e. it makes sure that the test doesn't hang. --> + <state id="148start" initial="148s0"> + <datamodel> + <data id="Var1481" expr="0"/> + </datamodel> + <state id="148s0"> + <onentry> + <if cond="false"> + <raise event="foo"/> + <assign location="Var1481" expr="Var1481 + 1"/> + <elseif cond="false"/> + <raise event="bar"/> + <assign location="Var1481" expr="Var1481 + 1"/> + <else/> + <raise event="baz"/> + <assign location="Var1481" expr="Var1481 + 1"/> + </if> + <raise event="bat"/> + </onentry> + <transition event="baz" cond="Var1481==1" target="148pass"/> + <transition event="*" target="148fail"/> + </state> + <state id="148pass"> + <onentry> + <send event="test.148.done" /> + </onentry> + <transition event="test.148.done" target="149start" /> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </state> + <final id="148fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> + </state> + + <!-- test that neither if clause executes, so that bat is the only event raised. --> + <state id="149start" initial="149s0"> + <datamodel> + <data id="Var1491" expr="0"/> + </datamodel> + <state id="149s0"> + <onentry> + <if cond="false"> + <raise event="foo"/> + <assign location="Var1491" expr="Var1491 + 1"/> + <elseif cond="false"/> + <raise event="bar"/> + <assign location="Var1491" expr="Var1491 + 1"/> + </if> + <raise event="bat"/> + </onentry> + <transition event="bat" cond="Var1491==0" target="149pass"/> + <transition event="*" target="149fail"/> + </state> + <state id="149pass"> + <onentry> + <send event="test.149.done" /> + </onentry> + <transition event="test.149.done" target="150start" /> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </state> + <final id="149fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> + </state> + + <!-- test that foreach causes a new variable to be declared if 'item' doesn't already exist. Also + test that it will use an existing var if it does exist. --> + <state id="150start" initial="150s0"> + <datamodel> + <data id="Var1501"/> + <data id="Var1502"/> + <data id="Var1503"> + [1,2,3] + </data> + </datamodel> + <state id="150s0"> + <onentry> + <!-- first use declared variables --> + <foreach item="Var1501" index="Var1502" array="Var1503"/> + <raise event="foo"/> + </onentry> + <transition event="error" target="150fail"/> + <transition event="*" target="150s1"/> + </state> + <state id="150s1"> + <onentry> + <!-- now use undeclared variables --> + <foreach item="Var1504" index="Var1505" array="Var1503"/> + <raise event="bar"/> + </onentry> + <transition event="error" target="150fail"/> + <transition event="*" target="150s2"/> + </state> + <state id="150s2"> + <!-- check that var1504 is bound --> + <transition cond="Var1504" target="150pass"/> + <transition target="150fail"/> + </state> + <state id="150pass"> + <onentry> + <send event="test.150.done" /> + </onentry> + <transition event="test.150.done" target="151start" /> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </state> + <final id="150fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> + </state> + + <!-- test that foreach causes a new variable to be declared if 'item' doesn't already exist. Also + test that it will use an existing var if it does exist. --> + <state id="151start" initial="151s0"> + <datamodel> + <data id="Var1511"/> + <data id="Var1512"/> + <data id="Var1513"> + [1,2,3] + </data> + </datamodel> + <state id="151s0"> + <onentry> + <!-- first use declared variables --> + <foreach item="Var1511" index="Var1512" array="Var1513"/> + <raise event="foo"/> + </onentry> + <transition event="error" target="151fail"/> + <transition event="*" target="151s1"/> + </state> + <state id="151s1"> + <onentry> + <!-- now use undeclared variables --> + <foreach item="Var1514" index="Var1515" array="Var1513"/> + <raise event="bar"/> + </onentry> + <transition event="error" target="151fail"/> + <transition event="*" target="151s2"/> + </state> + <state id="151s2"> + <!-- check that var1515 is bound --> + <transition cond="Var1515" target="151pass"/> + <transition target="151fail"/> + </state> + <state id="151pass"> + <onentry> + <send event="test.151.done" /> + </onentry> + <transition event="test.151.done" target="152start" /> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </state> + <final id="151fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> + </state> + + <!-- test that an illegal array or item value causes error.execution and results in executable content + not being executed. --> + <state id="152start" initial="152s0"> + <datamodel> + <data id="Var1521" expr="0"/> + <data id="Var1522"/> + <data id="Var1523"/> + <data id="Var1524" expr="7"/> + <data id="Var1525"> + [1,2,3] + </data> + </datamodel> + <state id="152s0"> + <onentry> + <!-- invalid array, legal item --> + <foreach item="Var1522" index="Var1523" array="Var1524"> + <assign location="Var1521" expr="Var1521 + 1"/> + </foreach> + <raise event="foo"/> + </onentry> + <transition event="error.execution" target="152s1"/> + <transition event="*" target="152fail"/> + </state> + <state id="152s1"> + <onentry> + <!-- illegal item, legal array --> + <foreach item="'continue'" index="Var1523" array="Var1525"> + <assign location="Var1521" expr="Var1521 + 1"/> + </foreach> + <raise event="bar"/> + </onentry> + <transition event="error.execution" target="152s2"/> + <transition event="bar" target="152fail"/> + </state> + <state id="152s2"> + <!-- check that var1521 has its original value (so executable content never got executed --> + <transition cond="Var1521==0" target="152pass"/> + <transition target="152fail"/> + </state> + <state id="152pass"> + <onentry> + <send event="test.152.done" /> + </onentry> + <transition event="test.152.done" target="153start" /> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </state> + <final id="152fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> + </state> + + <!-- test that foreach goes over the array in the right order. since the array contains 1 2 3, we compare the current + value with the previous value, which is stored in var1531. The current value should always be larger. If + it ever isn't, set Var1534 to 0, indicating failure --> + <state id="153start" initial="153s0"> + <datamodel> + <data id="Var1531" expr="0"/> + <!-- contains the previous value --> + <data id="Var1532"/> + <!-- the item which will contain the current value --> + <data id="Var1533"> + [1,2,3] + </data> + <data id="Var1534" expr="1"/> + <!-- 1 if success, 0 if failure --> + </datamodel> + <state id="153s0"> + <onentry> + <foreach item="Var1532" array="Var1533"> + <if cond="Var1531<Var1532"> + <assign location="Var1531" expr="Var1532"/> + <else/> + <!-- values are out of order, record failure --> + <assign location="Var1534" expr="0"/> + </if> + </foreach> + </onentry> + <!-- check that var1531 has its original value --> + <transition cond="Var1534==0" target="153fail"/> + <transition target="153pass"/> + </state> + <state id="153pass"> + <onentry> + <send event="test.153.done" /> + </onentry> + <transition event="test.153.done" target="155start" /> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </state> + <final id="153fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> + </state> + + <!-- test that foreach executes the executable content once for each item in the list '(1,2,3)'. The executable + content sums the items into var1551 so it should be 6 at the end --> + <state id="155start" initial="155s0"> + <datamodel> + <data id="Var1551" expr="0"/> + <data id="Var1552"/> + <data id="Var1553"> + [1,2,3] + </data> + </datamodel> + <state id="155s0"> + <onentry> + <foreach item="Var1552" array="Var1553"> + <assign location="Var1551" expr="Var1551 + Var1552"/> + </foreach> + </onentry> + <transition cond="Var1551==6" target="155pass"/> + <transition target="155fail"/> + </state> + <state id="155pass"> + <onentry> + <send event="test.155.done" /> + </onentry> + <transition event="test.155.done" target="158start" /> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </state> + <final id="155fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> + </state> + + <!-- test that executable content executes in document order. if event1 occurs then event2, succeed, otherwise fail --> + <state id="158start" initial="158s0"> + <datamodel> + <data id="Var1581" expr="0"/> + </datamodel> + <state id="158s0"> + <onentry> + <raise event="event1"/> + <raise event="event2"/> + </onentry> + <transition event="event1" target="158s1"/> + <transition event="*" target="158fail"/> + </state> + <state id="158s1"> + <transition event="event2" target="158pass"/> + <transition event="*" target="158fail"/> + </state> + <state id="158pass"> + <onentry> + <send event="test.158.done" /> + </onentry> + <transition event="test.158.done" target="159start" /> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </state> + <final id="158fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> + </state> + + <!-- test that any error raised by an element of executable content causes all subsequent elements to be skipped. + The send tag will raise an error so var1591 should not be incremented. If it is fail, otherwise succeed --> + <state id="159start" initial="159s0"> + <datamodel> + <data id="Var1591" expr="0"/> + </datamodel> + <state id="159s0"> + <onentry> + <send event="thisWillFail" target="baz"/> + <assign location="Var1591" expr="Var1591 + 1"/> + </onentry> + <transition cond="Var1591==1" target="159fail"/> + <transition target="159pass"/> + </state> + <state id="159pass"> + <onentry> + <send event="test.159.done" /> + </onentry> + <transition event="test.159.done" target="172start" /> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </state> + <final id="159fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> + </state> + + <!-- we test that eventexpr uses the current value of var1721, not its initial value --> + <state id="172start" initial="172s0"> + <datamodel> + <data id="Var1721" expr="'event1'"/> + </datamodel> + <state id="172s0"> + <onentry> + <assign location="Var1721" expr="'event2'"/> + <send eventexpr="Var1721"/> + </onentry> + <transition event="event2" target="172pass"/> + <transition event="*" target="172fail"/> + </state> + <state id="172pass"> + <onentry> + <send event="test.172.done" /> + </onentry> + <transition event="test.172.done" target="173start" /> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </state> + <final id="172fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> + </state> + + <!-- we test that targetexpr uses the current value of var1731, not its initial value + (If it uses the initial value, it will generate an error. If it uses the current value, event1 will be raised --> + <state id="173start" initial="173s0"> + <datamodel> + <data id="Var1731" expr="27"/> + </datamodel> + <state id="173s0"> + <onentry> + <assign location="Var1731" expr="'#_internal'"/> + <send targetexpr="Var1731" event="event1"/> + </onentry> + <transition event="event1" target="173pass"/> + <transition event="*" target="173fail"/> + </state> + <state id="173pass"> + <onentry> + <send event="test.173.done" /> + </onentry> + <transition event="test.173.done" target="174start" /> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </state> + <final id="173fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> + </state> + + <!-- we test that typeexpr uses the current value of var1741, not its initial value + (If it uses the initial value, it will generate an error. If it uses the current value, event1 will be raised --> + <state id="174start" initial="174s0"> + <datamodel> + <data id="Var1741" expr="27"/> + </datamodel> + <state id="174s0"> + <onentry> + <assign location="Var1741" expr="'http://www.w3.org/TR/scxml/#SCXMLEventProcessor'"/> + <send typeexpr="Var1741" event="event1"/> + </onentry> + <transition event="event1" target="174pass"/> + <transition event="*" target="174fail"/> + </state> + <state id="174pass"> + <onentry> + <send event="test.174.done" /> + </onentry> + <transition event="test.174.done" target="176start" /> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </state> + <final id="174fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> + </state> + + <!-- we test that <param> uses the current value of var1761, not its initial value. If the value of + aParam in event1 is 2 so that var1762 gets set to 2, success, otherwise failure --> + <state id="176start" initial="176s0"> + <datamodel> + <data id="Var1761" expr="1"/> + <data id="Var1762"/> + </datamodel> + <state id="176s0"> + <onentry> + <assign location="Var1761" expr="2"/> + <send event="event1"> + <param name="aParam" expr="Var1761"/> + </send> + </onentry> + <transition event="event1" target="176s1"> + <assign location="Var1762" expr="_event.data.aParam"/> + </transition> + <transition event="*" target="176fail"/> + </state> + <state id="176s1"> + <transition cond="Var1762==2" target="176pass"/> + <transition target="176fail"/> + </state> + <state id="176pass"> + <onentry> + <send event="test.176.done" /> + </onentry> + <transition event="test.176.done" target="179start" /> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </state> + <final id="176fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> + </state> + + <!-- we test that <content> can be used to populate body of a message --> + <state id="179start" initial="179s0"> + <state id="179s0"> + <onentry> + <send event="event1"> + <content>123</content> + </send> + </onentry> + <transition event="event1" cond="_event.data == 123" target="179pass"/> + <transition event="*" target="179fail"/> + </state> + <state id="179pass"> + <onentry> + <send event="test.179.done" /> + </onentry> + <transition event="test.179.done" target="183start" /> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </state> + <final id="179fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> + </state> + + <!-- we test that <send> stores the value of the sendid in idlocation. If it does, + var1831 has a value and we pass. Otherwise we fail --> + <state id="183start" initial="183s0"> + <datamodel> + <data id="Var1831"/> + </datamodel> + <state id="183s0"> + <onentry> + <send event="event1" idlocation="Var1831"/> + </onentry> + <transition cond="Var1831" target="183pass"/> + <transition target="183fail"/> + </state> + <state id="183pass"> + <onentry> + <send event="test.183.done" /> + </onentry> + <transition event="test.183.done" target="186start" /> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </state> + <final id="183fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> + </state> + + <!-- we test that <send> evals its args when it is evaluated, not when the delay interval expires and the + message is actually sent. If it does, aParam will have the value of 1 (even though var1861 has been incremented + in the interval.) If var1862 ends up == 1, we pass. Otherwise we fail --> + <state id="186start" initial="186s0"> + <datamodel> + <data id="Var1861" expr="1"/> + <data id="Var1862"/> + </datamodel> + <state id="186s0"> + <onentry> + <send event="event1" delayexpr="'0ms'"> + <param name="aParam" expr="Var1861"/> + </send> + <assign location="Var1861" expr="2"/> + </onentry> + <transition event="event1" target="186s1"> + <assign location="Var1862" expr="_event.data.aParam"/> + </transition> + <transition event="*" target="186fail"/> + </state> + <state id="186s1"> + <transition cond="Var1862==1" target="186pass"/> + <transition target="186fail"/> + </state> + <state id="186pass"> + <onentry> + <send event="test.186.done" /> + </onentry> + <transition event="test.186.done" target="189start" /> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </state> + <final id="186fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> + </state> + + <!-- we test that #_internal as a target of <send> puts the event on the internal queue. If it does, + event1 will be processed before event2, because event1 is added to the internal queue while event2 is + added to the external queue (event though event2 is generated first) --> + <state id="189start" initial="189s0"> + <state id="189s0"> + <onentry> + <!-- goes to the external queue --> + <send event="event2"/> + <!-- to the internal queue --> + <send event="event1" target="#_internal"/> + </onentry> + <!-- once we've entered the state, we should check for internal events first --> + <transition event="event1" target="189pass"/> + <transition event="event2" target="189fail"/> + </state> + <state id="189pass"> + <onentry> + <send event="test.189.done" /> + </onentry> + <transition event="test.189.done" target="190start" /> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </state> + <final id="189fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> + </state> + + <!-- we test that #_scxml_sessionid as a target of <send> puts the event on the external queue. If it does, + event1 will be processed before event2, because event1 is added to the internal queue while event2 is + added to the external queue (event though event2 is generated first). we have to make sure that event2 + is actually delivered. The delayed <send> makes sure another event is generated (so the test doesn't hang) --> + <state id="190start" initial="190s0"> + <datamodel> + <data id="Var1901" expr="'#_scxml_'"/> + <data id="Var1902" expr="_sessionid"/> + </datamodel> + <state id="190s0"> + <onentry> + <assign location="Var1901" expr="Var1901 + Var1902"/> + <!-- goes to the external queue --> + <send event="event2" targetexpr="Var1901"/> + <!-- to the internal queue --> + <raise event="event1"/> + <!-- this should get added to the external queue after event2 --> + <send event="timeout"/> + </onentry> + <!-- once we've entered the state, we should check for internal events first --> + <transition event="event1" target="190s1"/> + <transition event="*" target="190fail"/> + </state> + <!-- now check that we get event2 and not a timeout --> + <state id="190s1"> + <transition event="event2" target="190pass"/> + <transition event="*" target="190fail"/> + </state> + <state id="190pass"> + <onentry> + <send event="test.190.done" /> + </onentry> + <transition event="test.190.done" target="191start" /> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </state> + <final id="190fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> + </state> + + <!-- we test that #_parent works as a target of <send> . a subscript is invoked and sends the event + childToParent to its parent session (ths session) using #_parent as the target. If we get this event, we + pass, otherwise we fail. The timer insures that some event is generated and that the test does not hang. --> + <state id="191start" initial="191s0"> + <state id="191s0"> + <onentry> + + </onentry> + <invoke type="scxml"> + <content> + <!-- send an event to the parent session using #_parent as the target --> + <scxml initial="191sub0" datamodel="ecmascript"> + <state id="191sub0"> + <onentry> + <send event="childToParent" target="#_parent"/> + </onentry> + <transition target="191subFinal"/> + </state> + <final id="191subFinal"/> + </scxml> + </content> + </invoke> + <transition event="childToParent" target="191pass"/> + <transition event="*" target="191fail"/> + </state> + <state id="191pass"> + <onentry> + <send event="test.191.done" /> + </onentry> + <transition event="test.191.done" target="192start" /> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </state> + <final id="191fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> + </state> + + <!-- we test that #_invokeid works as a target of <send> . A child script is invoked and sends us + childToParent once its running. Then we send it the event parentToChild using its invokeid as the target. + If it receives this event, it sends sends the event eventReceived to its parent session (ths session). + If we get this event, we pass, otherwise the child script eventually times out sends invoke.done and we fail. + We also set a timeout in this process to make sure the test doesn't hang --> + <state id="192start" initial="192s0"> + <state id="192s0" initial="192s01"> + <onentry> + + </onentry> + <invoke type="scxml" id="invokedChild"> + <content> + <!-- let the parent session know we're running by sending childToParent, then wait for parentToChild. + If we get it, send eventReceived. If we don't we eventually time out --> + <scxml initial="192sub0" datamodel="ecmascript"> + <state id="192sub0"> + <onentry> + <send event="childToParent" target="#_parent"/> + + </onentry> + <transition event="parentToChild" target="192subFinal"> + <send target="#_parent" event="eventReceived"/> + </transition> + <transition event="timeout" target="192subFinal"/> + </state> + <final id="192subFinal"/> + </scxml> + </content> + </invoke> + <transition event="timeout" target="192fail"/> + <transition event="done.invoke" target="192fail"/> + <state id="192s01"> + <transition event="childToParent" target="192s02"> + <send target="#_invokedChild" event="parentToChild"/> + </transition> + </state> + <state id="192s02"> + <transition event="eventReceived" target="192pass"/> + </state> + </state> + <state id="192pass"> + <onentry> + <send event="test.192.done" /> + </onentry> + <transition event="test.192.done" target="193start" /> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </state> + <final id="192fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> + </state> + + <!-- we test that omitting target and targetexpr of <send> when using the + SCXML event i/o processor puts the event on the external queue. --> + <state id="193start" initial="193s0"> + <state id="193s0"> + <onentry> + <send event="internal"/> + <!-- this should put event1 in the external queue --> + <send event="event1" type="http://www.w3.org/TR/scxml/#SCXMLEventProcessor"/> + + </onentry> + <transition event="event1" target="193fail"/> + <transition event="internal" target="193s1"/> + </state> + <state id="193s1"> + <transition event="event1" target="193pass"/> + <transition event="timeout" target="193fail"/> + </state> + <state id="193pass"> + <onentry> + <send event="test.193.done" /> + </onentry> + <transition event="test.193.done" target="194start" /> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </state> + <final id="193fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> + </state> + + <!-- we test that specifying an illegal target for <send> causes the event error.execution to be raised. If it does, + we succeed. Otherwise we eventually timeout and fail. --> + <state id="194start" initial="194s0"> + <state id="194s0"> + <onentry> + <!-- should cause an error --> + <send target="baz" event="event2"/> + <!-- this will get added to the external event queue after the error has been raised --> + <send event="timeout"/> + </onentry> + <!-- once we've entered the state, we should check for internal events first --> + <transition event="error.execution" target="194pass"/> + <transition event="*" target="194fail"/> + </state> + <state id="194pass"> + <onentry> + <send event="test.194.done" /> + </onentry> + <transition event="test.194.done" target="198start" /> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </state> + <final id="194fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> + </state> + + <!-- we test that if type is not provided <send> uses the scxml event i/o processor. The only way to tell + what processor was used is to look at the origintype of the resulting event --> + <state id="198start" initial="198s0"> + <state id="198s0"> + <onentry> + <send event="event1"/> + <send event="timeout"/> + </onentry> + <transition event="event1" cond=" _event.origintype == 'http://www.w3.org/TR/scxml/#SCXMLEventProcessor'" target="198pass"/> + <transition event="*" target="198fail"/> + </state> + <state id="198pass"> + <onentry> + <send event="test.198.done" /> + </onentry> + <transition event="test.198.done" target="200start" /> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </state> + <final id="198fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> + </state> + + <!-- we test that the processor supports the scxml event i/o processor --> + <state id="200start" initial="200s0"> + <state id="200s0"> + <onentry> + <send type="http://www.w3.org/TR/scxml/#SCXMLEventProcessor" event="event1"/> + <send event="timeout"/> + </onentry> + <transition event="event1" target="200pass"/> + <transition event="*" target="200fail"/> + </state> + <state id="200pass"> + <onentry> + <send event="test.200.done" /> + </onentry> + <transition event="test.200.done" target="201start" /> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </state> + <final id="200fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> + </state> + + <!-- we test that the processor supports the basic http event i/o processor. This is an optional + test since platforms are not required to support basic http event i/o --> + <state id="201start" initial="201s0"> + <state id="201s0"> + <onentry> + <send type="http://www.w3.org/TR/scxml/#BasicHTTPEventProcessor" targetexpr="_ioprocessors['basichttp']['location']" event="event1"/> + <send event="timeout"/> + </onentry> + <transition event="event1" target="201pass"/> + <transition event="*" target="201fail"/> + </state> + <state id="201pass"> + <onentry> + <send event="test.201.done" /> + </onentry> + <transition event="test.201.done" target="205start" /> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </state> + <final id="201fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> + </state> + + <!-- we test that the processor doesn't change the message. We can't test that it never does this, but + at least we can check that the event name and included data are the same as we sent. --> + <state id="205start" initial="205s0"> + <datamodel> + <data id="Var2051"/> + </datamodel> + <state id="205s0"> + <onentry> + <send event="event1"> + <param name="aParam" expr="1"/> + </send> + <send event="timeout"/> + </onentry> + <transition event="event1" target="205s1"> + <assign location="Var2051" expr="_event.data.aParam"/> + </transition> + <transition event="*" target="205fail"/> + </state> + <state id="205s1"> + <transition cond="Var2051==1" target="205pass"/> + <transition target="205fail"/> + </state> + <state id="205pass"> + <onentry> + <send event="test.205.done" /> + </onentry> + <transition event="test.205.done" target="207start" /> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </state> + <final id="205fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> + </state> + + <!-- we test that that we can't cancel an event in another session. We invoke a child process. It notifies + us when it has generated a delayed event with sendid foo. We try to cancel foo. The child process sends us event + event success if the event is not cancelled, event fail otherwise. This doesn't test that there is absolutely no way to cancel an event + raised in another session, but the spec doesn't define any way to refer to an event in another process --> + <state id="207start" initial="207s0"> + <state id="207s0" initial="207s01"> + <onentry> + + </onentry> + <invoke type="scxml"> + <content> + <!-- when invoked, we raise a delayed event1 with sendid 'foo' and notify our parent. Then we wait. + If event1 occurs, the parent hasn't succeeded in canceling it and we return pass. If event2 occurs + it means event1 was canceled (because event2 is delayed longer than event1) and we return 'fail'. --> + <scxml initial="207sub0" datamodel="ecmascript"> + <state id="207sub0"> + <onentry> + <send event="event1" id="foo" delayexpr="'0ms'"/> + <send event="event2" delayexpr="'0ms'"/> + <send target="#_parent" event="childToParent"/> + </onentry> + <transition event="event1" target="207subFinal"> + <send target="#_parent" event="pass"/> + </transition> + <transition event="*" target="207subFinal"> + <send target="#_parent" event="fail"/> + </transition> + </state> + <final id="207subFinal"/> + </scxml> + </content> + </invoke> + <state id="207s01"> + <transition event="childToParent" target="207s02"> + <cancel sendid="foo"/> + </transition> + </state> + <state id="207s02"> + <transition event="pass" target="207pass"/> + <transition event="fail" target="207fail"/> + <transition event="timeout" target="207fail"/> + </state> + </state> + <state id="207pass"> + <onentry> + <send event="test.207.done" /> + </onentry> + <transition event="test.207.done" target="215start" /> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </state> + <final id="207fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> + </state> + + <!-- we test that typexpr is evaluated at runtime. If the original value of var2151 is used, the invocation + will fail (test215sub1.scxml is not of type 'foo', even if the platform supports foo as a type). If + the runtime value is used, the invocation will succeed --> + <state id="215start" initial="215s0"> + <datamodel> + <data id="Var2151" expr="'foo'"/> + </datamodel> + <state id="215s0"> + <onentry> + + <assign location="Var2151" expr="'http://www.w3.org/TR/scxml/'"/> + </onentry> + <invoke typeexpr="Var2151"> + <content> + <!-- when invoked, terminate returning done.invoke. This proves that the invocation succeeded. --> + <scxml initial="215subFinal" datamodel="ecmascript"> + <final id="215subFinal"/> + </scxml> + </content> + </invoke> + <transition event="done.invoke" target="215pass"/> + <transition event="*" target="215fail"/> + </state> + <state id="215pass"> + <onentry> + <send event="test.215.done" /> + </onentry> + <transition event="test.215.done" target="220start" /> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </state> + <final id="215fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> + </state> + + <!-- we test that the scxml type is supported. --> + <state id="220start" initial="220s0"> + <state id="220s0"> + <onentry> + + </onentry> + <invoke type="http://www.w3.org/TR/scxml/"> + <content> + <!-- when invoked, terminate returning done.invoke. This proves that the invocation succeeded. --> + <scxml initial="220subFinal" datamodel="ecmascript"> + <final id="220subFinal"/> + </scxml> + </content> + </invoke> + <transition event="done.invoke" target="220pass"/> + <transition event="*" target="220fail"/> + </state> + <state id="220pass"> + <onentry> + <send event="test.220.done" /> + </onentry> + <transition event="test.220.done" target="223start" /> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </state> + <final id="220fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> + </state> + + <!-- we test that idlocation is supported. --> + <state id="223start" initial="223s0"> + <datamodel> + <data id="Var2231"/> + </datamodel> + <state id="223s0"> + <onentry> + + </onentry> + <invoke type="http://www.w3.org/TR/scxml/" idlocation="Var2231"> + <content> + <!-- when invoked, terminate returning done.invoke. This proves that the invocation succeeded. --> + <scxml initial="223subFinal" datamodel="ecmascript"> + <final id="223subFinal"/> + </scxml> + </content> + </invoke> + <transition event="*" target="223s1"/> + </state> + <state id="223s1"> + <transition cond="Var2231" target="223pass"/> + <transition target="223fail"/> + </state> + <state id="223pass"> + <onentry> + <send event="test.223.done" /> + </onentry> + <transition event="test.223.done" target="225start" /> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </state> + <final id="223fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> + </state> + + <!-- we test that the automatically generated id is unique, we call invoke twice and compare the ids. --> + <state id="225start" initial="225s0"> + <datamodel> + <data id="Var2251"/> + <data id="Var2252"/> + </datamodel> + <state id="225s0"> + <onentry> + + </onentry> + <invoke type="http://www.w3.org/TR/scxml/" idlocation="Var2251"> + <content> + <scxml initial="225subFinal1" datamodel="ecmascript"> + <final id="225subFinal1"/> + </scxml> + </content> + </invoke> + <invoke type="http://www.w3.org/TR/scxml/" idlocation="Var2252"> + <content> + <scxml initial="225subFinal2" datamodel="ecmascript"> + <final id="225subFinal2"/> + </scxml> + </content> + </invoke> + <transition event="*" target="225s1"/> + </state> + <state id="225s1"> + <transition cond="Var2251===Var2252" target="225fail"/> + <transition target="225pass"/> + </state> + <state id="225pass"> + <onentry> + <send event="test.225.done" /> + </onentry> + <transition event="test.225.done" target="228start" /> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </state> + <final id="225fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> + </state> + + <!-- test that the invokeid is included in events returned from the invoked process. --> + <state id="228start" initial="228s0"> + <datamodel> + <data id="Var2281"/> + </datamodel> + <state id="228s0"> + <onentry> + + </onentry> + <invoke type="http://www.w3.org/TR/scxml/" id="foo"> + <content> + <scxml initial="228subFinal" datamodel="ecmascript"> + <final id="228subFinal"/> + </scxml> + </content> + </invoke> + <transition event="done.invoke" target="228s1"> + <assign location="Var2281" expr="_event.invokeid"/> + </transition> + <transition event="*" target="228fail"/> + </state> + <state id="228s1"> + <transition cond="Var2281=='foo'" target="228pass"/> + <transition target="228fail"/> + </state> + <state id="228pass"> + <onentry> + <send event="test.228.done" /> + </onentry> + <transition event="test.228.done" target="229start" /> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </state> + <final id="228fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> + </state> + + <!-- test that autofoward works. If the child process receives back a copy of the + childToParent event that it sends to this doc, it sends eventReceived, signalling success. (Note + that this doc is not required to process that event explicitly. It should be forwarded in any case.) Otherwise + it eventually times out and the done.invoke signals failure --> + <state id="229start" initial="229s0"> + <state id="229s0"> + <onentry> + + </onentry> + <invoke type="http://www.w3.org/TR/scxml/" autoforward="true"> + <content> + <!-- when invoked, send childToParent to parent. + If it is forwarded back to us, send + eventReceived to signal success and terminate. + Otherwise wait for timer to expire and terminate. --> + <scxml initial="229sub0" datamodel="ecmascript"> + <state id="229sub0"> + <onentry> + <send target="#_parent" event="childToParent"/> + + </onentry> + <transition event="childToParent" target="229subFinal"> + <send target="#_parent" event="eventReceived"/> + </transition> + <transition event="*" target="229subFinal"/> + </state> + <final id="229subFinal"/> + </scxml> + </content> + </invoke> + <transition event="childToParent"/> + <transition event="eventReceived" target="229pass"/> + <transition event="*" target="229fail"/> + </state> + <state id="229pass"> + <onentry> + <send event="test.229.done" /> + </onentry> + <transition event="test.229.done" target="232start" /> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </state> + <final id="229fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> + </state> + + <!-- test that a parent process can receive multiple events from a child process --> + <state id="232start" initial="232s0"> + <state id="232s0" initial="232s01"> + <onentry> + + </onentry> + <invoke type="http://www.w3.org/TR/scxml/"> + <content> + <scxml initial="232subFinal" datamodel="ecmascript"> + <final id="232subFinal"> + <onentry> + <send target="#_parent" event="childToParent1"/> + <send target="#_parent" event="childToParent2"/> + </onentry> + </final> + </scxml> + </content> + </invoke> + <transition event="timeout" target="232fail"/> + <state id="232s01"> + <transition event="childToParent1" target="232s02"/> + </state> + <state id="232s02"> + <transition event="childToParent2" target="232s03"/> + </state> + <state id="232s03"> + <transition event="done.invoke" target="232pass"/> + </state> + </state> + <state id="232pass"> + <onentry> + <send event="test.232.done" /> + </onentry> + <transition event="test.232.done" target="233start" /> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </state> + <final id="232fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> + </state> + + <!-- test that finalize markup runs before the event is processed. The invoked process will + return 2 in _event.data.aParam, so that new value should be in force when we select + the transtitions. --> + <state id="233start" initial="233s0"> + <datamodel> + <data id="Var2331" expr="1"/> + </datamodel> + <state id="233s0"> + <onentry> + + </onentry> + <invoke type="http://www.w3.org/TR/scxml/"> + <content> + <scxml initial="233subFinal" datamodel="ecmascript"> + <final id="233subFinal"> + <onentry> + <send target="#_parent" event="childToParent"> + <param name="aParam" expr="2"/> + </send> + </onentry> + </final> + </scxml> + </content> + <finalize> + <assign location="Var2331" expr="_event.data.aParam"/> + </finalize> + </invoke> + <transition event="childToParent" cond="Var2331==2" target="233pass"/> + <transition event="*" target="233fail"/> + </state> + <state id="233pass"> + <onentry> + <send event="test.233.done" /> + </onentry> + <transition event="test.233.done" target="234start" /> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </state> + <final id="233fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> + </state> + + <!-- test that only finalize markup in the invoking state runs. the first invoked process will + return 2 in _event.data.aParam, while second invoked process sleeps without returning any events. + Only the first finalize should execute. So when we get to s1 var2341 should have value 2 but + var2342 should still be set to 1 --> + <state id="234start" initial="234p0"> + <datamodel> + <data id="Var2341" expr="1"/> + <data id="Var2342" expr="1"/> + </datamodel> + <parallel id="234p0"> + <onentry> + + </onentry> + <transition event="timeout" target="234fail"/> + <state id="234p01"> + <invoke type="http://www.w3.org/TR/scxml/"> + <content> + <scxml initial="234subFinal1" datamodel="ecmascript"> + <final id="234subFinal1"> + <onentry> + <send target="#_parent" event="childToParent"> + <param name="aParam" expr="2"/> + </send> + </onentry> + </final> + </scxml> + </content> + <finalize> + <assign location="Var2341" expr="_event.data.aParam"/> + </finalize> + </invoke> + <transition event="childToParent" cond="Var2341==2" target="234s1"/> + <transition event="childToParent" target="234fail"/> + </state> + <state id="234p02"> + <invoke type="http://www.w3.org/TR/scxml/"> + <content> + <scxml initial="234sub0" datamodel="ecmascript"> + <state id="234sub0"> + <onentry> + + </onentry> + <transition event="timeout" target="234subFinal2"/> + </state> + <final id="234subFinal2"/> + </scxml> + </content> + <finalize> + <assign location="Var2342" expr="_event.data.aParam"/> + </finalize> + </invoke> + </state> + </parallel> + <state id="234s1"> + <transition cond="Var2342==1" target="234pass"/> + <transition target="234fail"/> + </state> + <state id="234pass"> + <onentry> + <send event="test.234.done" /> + </onentry> + <transition event="test.234.done" target="235start" /> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </state> + <final id="234fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> + </state> + + <!-- test that done.invoke.id event has the right id. the invoked child terminates immediately + and should generate done.invoke.foo --> + <state id="235start" initial="235s0"> + <state id="235s0"> + <onentry> + + </onentry> + <invoke type="http://www.w3.org/TR/scxml/" id="foo"> + <content> + <scxml initial="235subFinal" datamodel="ecmascript"> + <final id="235subFinal"/> + </scxml> + </content> + </invoke> + <transition event="done.invoke.foo" target="235pass"/> + <transition event="*" target="235fail"/> + </state> + <state id="235pass"> + <onentry> + <send event="test.235.done" /> + </onentry> + <transition event="test.235.done" target="237start" /> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </state> + <final id="235fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> + </state> + + <!-- test that cancelling works. invoked child sleeps for two seconds, then terminates. We + sleep for 1 sec in s0, then move to s1. This should cause the invocation to get cancelled. + If we receive done.invoke, the invocation wasn't cancelled, and we fail. If we receive no events by + the time timeout2 fires, success --> + <state id="237start" initial="237s0"> + <state id="237s0"> + <onentry> + <send event="timeout1" delayexpr="'0ms'"/> + </onentry> + <invoke type="http://www.w3.org/TR/scxml/"> + <content> + <!-- when invoked, sleep for 2 secs then terminate. Parent will try to cancel this session --> + <scxml initial="237sub0" datamodel="ecmascript"> + <state id="237sub0"> + <onentry> + + </onentry> + <transition event="timeout" target="237subFinal"/> + </state> + <final id="237subFinal"/> + </scxml> + </content> + </invoke> + <transition event="timeout1" target="237s1"/> + </state> + <state id="237s1"> + <onentry> + <send event="timeout2" delayexpr="'0ms'"/> + </onentry> + <!-- here we should NOT get done.invoke --> + <transition event="done.invoke" target="237fail"/> + <transition event="*" target="237pass"/> + </state> + <state id="237pass"> + <onentry> + <send event="test.237.done" /> + </onentry> + <transition event="test.237.done" target="240start" /> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </state> + <final id="237fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> + </state> + + <!-- test that datamodel values can be specified both by 'namelist' and by <param>. + invoked child will return success if its Var2401 is set to 1, failure otherwise. This + test will fail schema validation because of the multiple occurences of Var2401, but + should run correctly. --> + <state id="240start" initial="240s0"> + <datamodel> + <data id="Var2401" expr="1"/> + </datamodel> + <state id="240s0" initial="240s01"> + <onentry> + + </onentry> + <transition event="timeout" target="240fail"/> + <state id="240s01"> + <invoke type="http://www.w3.org/TR/scxml/" namelist="Var2401"> + <content> + <scxml initial="240sub01" datamodel="ecmascript"> + <datamodel> + <data id="Var2401" expr="0"/> + </datamodel> + <state id="240sub01"> + <transition cond="Var2401===1" target="240subFinal1"> + <send target="#_parent" event="success"/> + </transition> + <transition target="240subFinal1"> + <send target="#_parent" event="failure"/> + </transition> + </state> + <final id="240subFinal1"/> + </scxml> + </content> + </invoke> + <transition event="success" target="240s02"/> + <transition event="failure" target="240fail"/> + </state> + <state id="240s02"> + <invoke type="http://www.w3.org/TR/scxml/"> + <param name="Var2401" expr="1"/> + <content> + <scxml initial="240sub02" datamodel="ecmascript"> + <datamodel> + <data id="Var2401" expr="0"/> + </datamodel> + <state id="240sub02"> + <transition cond="Var2401==1" target="240subFinal2"> + <send target="#_parent" event="success"/> + </transition> + <transition target="240subFinal2"> + <send target="#_parent" event="failure"/> + </transition> + </state> + <final id="240subFinal2"/> + </scxml> + </content> + </invoke> + <transition event="success" target="240pass"/> + <transition event="failure" target="240fail"/> + </state> + </state> + <state id="240pass"> + <onentry> + <send event="test.240.done" /> + </onentry> + <transition event="test.240.done" target="241start" /> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </state> + <final id="240fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> + </state> + + <!-- The child process will return success ifits Var2411 is set to 1, failure otherwise. For this test + we try passing in Var2411 by param and by namelist and check that we either get two successes + or two failures. This test will fail schema validation due to multiple declarations of + Var2411, but should run correctly. --> + <state id="241start" initial="241s0"> + <datamodel> + <data id="Var2411" expr="1"/> + </datamodel> + <state id="241s0" initial="241s01"> + <onentry> + + </onentry> + <transition event="timeout" target="241fail"/> + <state id="241s01"> + <invoke type="http://www.w3.org/TR/scxml/" namelist="Var2411"> + <content> + <scxml initial="241sub01" datamodel="ecmascript"> + <datamodel> + <data id="Var2411" expr="0"/> + </datamodel> + <state id="241sub01"> + <transition cond="Var2411==1" target="241subFinal1"> + <send target="#_parent" event="success"/> + </transition> + <transition target="241subFinal1"> + <send target="#_parent" event="failure"/> + </transition> + </state> + <final id="241subFinal1"/> + </scxml> + </content> + </invoke> + <transition event="success" target="241s02"/> + <transition event="failure" target="241s03"/> + </state> + <state id="241s02"> + <invoke type="http://www.w3.org/TR/scxml/"> + <param name="Var2411" expr="1"/> + <content> + <scxml initial="241sub02" datamodel="ecmascript"> + <datamodel> + <data id="Var2411" expr="0"/> + </datamodel> + <state id="241sub02"> + <transition cond="Var2411==1" target="241subFinal2"> + <send target="#_parent" event="success"/> + </transition> + <transition target="241subFinal2"> + <send target="#_parent" event="failure"/> + </transition> + </state> + <final id="241subFinal2"/> + </scxml> + </content> + </invoke> + <!-- we got success in s01, so we need to do so here --> + <transition event="success" target="241pass"/> + <transition event="failure" target="241fail"/> + </state> + <state id="241s03"> + <invoke type="http://www.w3.org/TR/scxml/"> + <param name="Var2411" expr="1"/> + <content> + <scxml initial="241sub03" datamodel="ecmascript"> + <datamodel> + <data id="Var2411" expr="0"/> + </datamodel> + <state id="241sub03"> + <transition cond="Var2411==1" target="241subFinal3"> + <send target="#_parent" event="success"/> + </transition> + <transition target="241subFinal3"> + <send target="#_parent" event="failure"/> + </transition> + </state> + <final id="241subFinal3"/> + </scxml> + </content> + </invoke> + <!-- we got failure in s01, so we need to do so here --> + <transition event="failure" target="241pass"/> + <transition event="success" target="241fail"/> + </state> + </state> + <state id="241pass"> + <onentry> + <send event="test.241.done" /> + </onentry> + <transition event="test.241.done" target="242start" /> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </state> + <final id="241fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> + </state> + + <!-- test that markup specified by 'src' and by <content> is treated the same way. That means that + either we get done.invoke in both cases or in neither case (in which case we timeout) --> + <state id="242start" initial="242s0"> + <state id="242s0"> + <onentry> + <send event="timeout1" delay="0ms"/> + </onentry> + <transition event="timeout" target="242fail"/> + <invoke type="http://www.w3.org/TR/scxml/" src="file:test242sub1.scxml"/> + <transition event="done.invoke" target="242s02"/> + <transition event="timeout1" target="242s03"/> + </state> + <state id="242s02"> + <onentry> + <send event="timeout2" delay="0ms"/> + </onentry> + <invoke type="http://www.w3.org/TR/scxml/"> + <!-- identical to test242sub1.scxml. --> + <content> + <scxml initial="242subFinal1" datamodel="ecmascript"> + <final id="242subFinal1"/> + </scxml> + </content> + </invoke> + <!-- we got done.invoke last time, so we need it this time too --> + <transition event="done.invoke" target="242pass"/> + <transition event="timeout2" target="242fail"/> + </state> + <state id="242s03"> + <onentry> + <send event="timeout3" delay="0ms"/> + </onentry> + <invoke type="http://www.w3.org/TR/scxml/"> + <!-- identical to test242sub1.scxml. --> + <content> + <scxml initial="242subFinal2" datamodel="ecmascript"> + <final id="242subFinal2"/> + </scxml> + </content> + </invoke> + <!-- we got timeout last time, so we need it this time too --> + <transition event="timeout3" target="242pass"/> + <transition event="done.invoke" target="242fail"/> + </state> + <state id="242pass"> + <onentry> + <send event="test.242.done" /> + </onentry> + <transition event="test.242.done" target="243start" /> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </state> + <final id="242fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> + </state> + + <!-- test that datamodel values can be specified by param. + test240sub1 will return success ifits Var2431 is set to 1, failure otherwise. --> + <state id="243start" initial="243s0"> + <state id="243s0"> + <onentry> + + </onentry> + <invoke type="http://www.w3.org/TR/scxml/"> + <param name="Var2431" expr="1"/> + <content> + <scxml initial="243sub0" datamodel="ecmascript"> + <datamodel> + <data id="Var2431" expr="0"/> + </datamodel> + <state id="243sub0"> + <transition cond="Var2431==1" target="243subFinal"> + <send target="#_parent" event="success"/> + </transition> + <transition target="243subFinal"> + <send target="#_parent" event="failure"/> + </transition> + </state> + <final id="243subFinal"/> + </scxml> + </content> + </invoke> + <transition event="success" target="243pass"/> + <transition event="*" target="243fail"/> + </state> + <state id="243pass"> + <onentry> + <send event="test.243.done" /> + </onentry> + <transition event="test.243.done" target="244start" /> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </state> + <final id="243fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> + </state> + + <!-- test that datamodel values can be specified by namelist. + invoked child will return success ifits Var2441 is set to 1, failure otherwise. + This test will fail schema validation due to multiple occurrences of Var2441, + but should run correctly. --> + <state id="244start" initial="244s0"> + <datamodel> + <data id="Var2441" expr="1"/> + </datamodel> + <state id="244s0"> + <onentry> + + </onentry> + <invoke type="http://www.w3.org/TR/scxml/" namelist="Var2441"> + <content> + <scxml initial="244sub0" datamodel="ecmascript"> + <datamodel> + <data id="Var2441" expr="0"/> + </datamodel> + <state id="244sub0"> + <transition cond="Var2441==1" target="244subFinal"> + <send target="#_parent" event="success"/> + </transition> + <transition target="244subFinal"> + <send target="#_parent" event="failure"/> + </transition> + </state> + <final id="244subFinal"/> + </scxml> + </content> + </invoke> + <transition event="success" target="244pass"/> + <transition event="*" target="244fail"/> + </state> + <state id="244pass"> + <onentry> + <send event="test.244.done" /> + </onentry> + <transition event="test.244.done" target="245start" /> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </state> + <final id="244fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> + </state> + + <!-- test that non-existent datamodel values are not set. Var2452 is not defined in + invoked child's datamodel. It will will return success if its Var2452 remains unbound, failure otherwise. --> + <state id="245start" initial="245s0"> + <datamodel> + <data id="Var2452" expr="3"/> + </datamodel> + <state id="245s0"> + <onentry> + + </onentry> + <invoke type="http://www.w3.org/TR/scxml/" namelist="Var2452"> + <content> + <scxml initial="245sub0" datamodel="ecmascript"> + <state id="245sub0"> + <transition cond="Var2452" target="245subFinal"> + <send target="#_parent" event="failure"/> + </transition> + <transition target="245subFinal"> + <send target="#_parent" event="success"/> + </transition> + </state> + <final id="245subFinal"/> + </scxml> + </content> + </invoke> + <transition event="success" target="245pass"/> + <transition event="*" target="245fail"/> + </state> + <state id="245pass"> + <onentry> + <send event="test.245.done" /> + </onentry> + <transition event="test.245.done" target="247start" /> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </state> + <final id="245fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> + </state> + + <!-- test that we get done.invoke. timeout indicates failure --> + <state id="247start" initial="247s0"> + <state id="247s0"> + <onentry> + + </onentry> + <invoke type="http://www.w3.org/TR/scxml/"> + <content> + <scxml initial="247subFinal" datamodel="ecmascript"> + <final id="247subFinal"/> + </scxml> + </content> + </invoke> + <transition event="done.invoke" target="247pass"/> + <transition event="timeout" target="247fail"/> + </state> + <state id="247pass"> + <onentry> + <send event="test.247.done" /> + </onentry> + <transition event="test.247.done" target="253start" /> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </state> + <final id="247fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> + </state> + + <!-- test that the scxml event processor is used in both directions. If child process uses the + scxml event i/o processor to communicate with us, send it an event. It will send back success if + this process uses the scxml processor to send the message to it, otherwise failure. For this test we allow + 'scxml' as an alternative to the full url. --> + <state id="253start" initial="253s0"> + <datamodel> + <data id="Var2531"/> + </datamodel> + <state id="253s0" initial="253s01"> + <onentry> + + </onentry> + <transition event="timeout" target="253fail"/> + <invoke type="scxml" id="foo"> + <content> + <!-- inform parent we're running then wait for it to send us an event. If it uses the scxml event i/o + processor to do so, return success, otherwise return failure. --> + <scxml initial="253sub0" datamodel="ecmascript"> + <datamodel> + <data id="Var2532"/> + </datamodel> + <state id="253sub0"> + <onentry> + <send target="#_parent" event="childRunning"/> + </onentry> + <transition event="parentToChild" target="253sub1"> + <assign location="Var2532" expr="_event.origintype"/> + </transition> + </state> + <state id="253sub1"> + <transition cond="Var2532=='http://www.w3.org/TR/scxml/#SCXMLEventProcessor'" target="253subFinal"> + <send target="#_parent" event="success"/> + </transition> + <transition cond="Var2532=='scxml'" target="253subFinal"> + <send target="#_parent" event="success"/> + </transition> + <transition target="253subFinal"> + <send target="#_parent" event="failure"/> + </transition> + </state> + <final id="253subFinal"/> + </scxml> + </content> + </invoke> + <state id="253s01"> + <transition event="childRunning" target="253s02"> + <assign location="Var2531" expr="_event.origintype"/> + </transition> + </state> + <state id="253s02"> + <transition cond="Var2531=='http://www.w3.org/TR/scxml/#SCXMLEventProcessor'" target="253s03"> + <send target="#_foo" event="parentToChild"/> + </transition> + <transition cond="Var2531=='scxml'" target="253s03"> + <send target="#_foo" event="parentToChild"/> + </transition> + <transition target="253fail"/> + </state> + <state id="253s03"> + <transition event="success" target="253pass"/> + <transition event="fail" target="253fail"/> + </state> + </state> + <state id="253pass"> + <onentry> + <send event="test.253.done" /> + </onentry> + <transition event="test.253.done" target="278start" /> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </state> + <final id="253fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> + </state> + + <state id="278start" initial="278s0"> + <!-- test that a variable can be accessed from a state that is outside its lexical scope --> + <state id="278s0"> + <transition cond="Var2781==1" target="278pass"/> + <transition target="278fail"/> + </state> + <state id="278s1"> + <datamodel> + <data id="Var2781" expr="1"/> + </datamodel> + </state> + <state id="278pass"> + <onentry> + <send event="test.278.done" /> + </onentry> + <transition event="test.278.done" target="279start" /> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </state> + <final id="278fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> + </state> + + <!-- testing that in case of early binding variables are assigned values at init time, before + the state containing them is visited --> + <state id="279start" initial="279s0"> + <state id="279s0"> + <transition cond="Var2791==1" target="279pass"/> + <transition target="279fail"/> + </state> + <state id="279s1"> + <datamodel> + <data id="Var2791" expr="1"/> + </datamodel> + </state> + <state id="279pass"> + <onentry> + <send event="test.279.done" /> + </onentry> + <transition event="test.279.done" target="286start" /> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </state> + <final id="279fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> + </state> + + <!-- test that assigment to a non-declared var causes an error. the transition on foo catches the case + where no error is raised --> + <state id="286start" initial="286s0"> + <state id="286s0"> + <onentry> + <assign location="foo.bar.baz " expr="1"/> + <raise event="foo"/> + </onentry> + <transition event="error.execution" target="286pass"/> + <transition event="*" target="286fail"/> + </state> + <state id="286pass"> + <onentry> + <send event="test.286.done" /> + </onentry> + <transition event="test.286.done" target="287start" /> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </state> + <final id="286fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> + </state> + + <!-- a simple test that a legal value may be assigned to a valid data model location --> + <state id="287start" initial="287s0"> + <datamodel> + <data id="Var2871" expr="0"/> + </datamodel> + <state id="287s0"> + <onentry> + <assign location="Var2871" expr="1"/> + </onentry> + <transition cond="Var2871==1" target="287pass"/> + <transition target="287fail"/> + </state> + <state id="287pass"> + <onentry> + <send event="test.287.done" /> + </onentry> + <transition event="test.287.done" target="288start" /> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </state> + <final id="287fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> + </state> + + <!-- a simple test that a legal value may be assigned to a valid data model location + using child content --> + <state id="288start" initial="288s0"> + <datamodel> + <data id="Var2881" expr="0"/> + </datamodel> + <state id="288s0"> + <onentry> + <assign location="Var2881">123</assign> + </onentry> + <transition cond="Var2881 == 123" target="288pass"/> + <transition target="288fail"/> + </state> + <state id="288pass"> + <onentry> + <send event="test.288.done" /> + </onentry> + <transition event="test.288.done" target="294start" /> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </state> + <final id="288fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> + </state> + + <!-- test that a param inside donedata ends up in the data field of the done event and + that content inside donedata sets the full value of the event.data field --> + <state id="294start" initial="294s0"> + <datamodel> + <data id="Var2941" expr="0"/> + </datamodel> + <state id="294s0" initial="294s01"> + <transition event="done.state.294s0" cond="_event.data['Var2941']==1" target="294s1"> + </transition> + <transition event="done.state.294s0" target="294fail"> + </transition> + <state id="294s01"> + <transition target="294s02"/> + </state> + <final id="294s02"> + <donedata> + <param name="Var2941" expr="1"/> + </donedata> + </final> + </state> + <state id="294s1" initial="294s11"> + <transition event="done.state.294s1" cond="_event.data == 'foo'" target="294pass"> + </transition> + <transition event="done.state.294s1" target="294fail"> + </transition> + <state id="294s11"> + <transition target="294s12"/> + </state> + <final id="294s12"> + <donedata> + <content>foo</content> + </donedata> + </final> + </state> + <state id="294pass"> + <onentry> + <send event="test.294.done" /> + </onentry> + <transition event="test.294.done" target="298start" /> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </state> + <final id="294fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> + </state> + + <!-- reference a non-existent data model location in param in donedata and see that the right error is raised --> + <state id="298start" initial="298s0"> + <datamodel> + <data id="Var2981" expr="0"/> + </datamodel> + <state id="298s0" initial="298s01"> + <onentry> + + </onentry> + <transition event="error.execution" target="298pass"/> + <transition event="*" target="298fail"/> + <state id="298s01"> + <transition target="298s02"/> + </state> + <final id="298s02"> + <donedata> + <param name="Var2983" location="foo.bar.baz "/> + </donedata> + </final> + </state> + <state id="298pass"> + <onentry> + <send event="test.298.done" /> + </onentry> + <transition event="test.298.done" target="303start" /> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </state> + <final id="298fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> + </state> + + <!-- to test that scripts are run as part of executable content, we check that it changes the value of a var at the + right point. This test is valid only for datamodels that support scripting --> + <state id="303start" initial="303s0"> + <datamodel> + <data id="Var3031" expr="0"/> + </datamodel> + <state id="303s0"> + <onentry> + <assign location="Var3031" expr="2"/> + <script>var Var3031 = 1</script> + </onentry> + <transition cond="Var3031==1" target="303pass"/> + <transition target="303fail"/> + </state> + <state id="303pass"> + <onentry> + <send event="test.303.done" /> + </onentry> + <transition event="test.303.done" target="310start" /> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </state> + <final id="303fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> + </state> + + <!-- simple test of the in() predicate --> + <state id="310start" initial="310p"> + <parallel id="310p"> + <state id="310s0"> + <transition cond="In('310s1')" target="310pass"/> + <transition target="310fail"/> + </state> + <state id="310s1"/> + </parallel> + <state id="310pass"> + <onentry> + <send event="test.310.done" /> + </onentry> + <transition event="test.310.done" target="311start" /> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </state> + <final id="310fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> + </state> + + <!-- test that assignment to a non-existent location yields an error --> + <state id="311start" initial="311s0"> + <state id="311s0"> + <onentry> + + <assign location="foo.bar.baz " expr="1"/> + </onentry> + <transition event="error.execution" target="311pass"/> + <transition event=".*" target="311fail"/> + </state> + <state id="311pass"> + <onentry> + <send event="test.311.done" /> + </onentry> + <transition event="test.311.done" target="318start" /> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </state> + <final id="311fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> + </state> + + <!-- test that _event stays bound during the onexit and entry into the next state --> + <state id="318start" initial="318s0" name="machineName"> + <datamodel> + <data id="Var3181"/> + </datamodel> + <state id="318s0"> + <onentry> + <raise event="foo"/> + </onentry> + <transition event="foo" target="318s1"/> + </state> + <state id="318s1"> + <onentry> + <raise event="bar"/> + <!-- _event should still be bound to 'foo' at this point --> + <assign location="Var3181" expr="_event.name"/> + </onentry> + <transition cond="Var3181=='foo'" target="318pass"/> + <transition target="318fail"/> + </state> + <state id="318pass"> + <onentry> + <send event="test.318.done" /> + </onentry> + <transition event="test.318.done" target="321start" /> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </state> + <final id="318fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> + </state> + + <!-- test that _sessionid is bound on startup --> + <state id="321start" initial="321s0" name="machineName"> + <datamodel> + <data id="Var3211" expr="_sessionid"/> + </datamodel> + <state id="321s0"> + <transition cond="Var3211" target="321pass"/> + <transition cond="true" target="321fail"/> + </state> + <state id="321pass"> + <onentry> + <send event="test.321.done" /> + </onentry> + <transition event="test.321.done" target="322start" /> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </state> + <final id="321fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> + </state> + + <!-- test that _sessionid remains bound to the same value throught the session. this means that it can't + be assigned to --> + <state id="322start" initial="322s0" name="machineName"> + <datamodel> + <data id="Var3221" expr="_sessionid"/> + <data id="Var3222"/> + </datamodel> + <state id="322s0"> + <transition target="322s1"/> + </state> + <state id="322s1"> + <onentry> + <assign location="_sessionid" expr="'otherName'"/> + <raise event="foo"/> + </onentry> + <transition event="error.execution" target="322s2"/> + <transition event="*" target="322fail"/> + </state> + <state id="322s2"> + <transition cond="Var3221==_sessionid" target="322pass"/> + <transition target="322fail"/> + </state> + <state id="322pass"> + <onentry> + <send event="test.322.done" /> + </onentry> + <transition event="test.322.done" target="323start" /> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </state> + <final id="322fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> + </state> + + <!-- test that _name is bound on startup --> + <state id="323start" initial="323s0" name="machineName"> + <datamodel> + <data id="Var3231" expr="_name"/> + </datamodel> + <state id="323s0"> + <transition cond="Var3231" target="323pass"/> + <transition cond="true" target="323fail"/> + </state> + <state id="323pass"> + <onentry> + <send event="test.323.done" /> + </onentry> + <transition event="test.323.done" target="325start" /> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </state> + <final id="323fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> + </state> + + <!-- test that _ioprocessors is bound at startup. I'm not sure how to test for a set value or + how to test that the entries in it do represent I/O processors, since the set that each implementation + supports may be different. Suggestions welcome --> + <state id="325start" initial="325s0" name="machineName"> + <datamodel> + <data id="Var3251" expr="_ioprocessors"/> + </datamodel> + <state id="325s0"> + <transition cond="Var3251" target="325pass"/> + <transition target="325fail"/> + </state> + <state id="325pass"> + <onentry> + <send event="test.325.done" /> + </onentry> + <transition event="test.325.done" target="326start" /> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </state> + <final id="325fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> + </state> + + <!-- test that _ioprocessors stays bound till the session ends. This means that it cannot be assigned to --> + <state id="326start" initial="326s0" name="machineName"> + <datamodel> + <data id="Var3261" expr="_ioprocessors"/> + <data id="Var3262"/> + </datamodel> + <state id="326s0"> + <transition cond="Var3261" target="326s1"/> + <transition cond="true" target="326fail"/> + </state> + <state id="326s1"> + <onentry> + <assign location="_ioprocessors" expr="'otherName'"/> + <raise event="foo"/> + </onentry> + <transition event="error.execution" target="326s2"/> + <transition event="*" target="326fail"/> + </state> + <state id="326s2"> + <onentry> + <assign location="Var3262" expr="_ioprocessors"/> + </onentry> + <transition cond="Var3261==Var3262" target="326pass"/> + <transition target="326fail"/> + </state> + <state id="326pass"> + <onentry> + <send event="test.326.done" /> + </onentry> + <transition event="test.326.done" target="329start" /> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </state> + <final id="326fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> + </state> + + <!-- test that none of the system variables can be modified --> + <state id="329start" initial="329s0" name="machineName"> + <datamodel> + <data id="Var3291"/> + <data id="Var3292"/> + <data id="Var3293"/> + <data id="Var3294"/> + </datamodel> + <state id="329s0"> + <onentry> + <!-- get _event bound so we can use it in s1--> + <raise event="foo"/> + <assign location="Var3291" expr="_sessionid"/> + <assign location="_sessionid" expr="27"/> + </onentry> + <transition event="foo" cond="Var3291==_sessionid" target="329s1"/> + <transition event="*" target="329fail"/> + </state> + <state id="329s1"> + <onentry> + <assign location="Var3292" expr="_event"/> + <assign location="_event" expr="27"/> + </onentry> + <transition cond="Var3292==_event" target="329s2"/> + <transition target="329fail"/> + </state> + <state id="329s2"> + <onentry> + <assign location="Var3293" expr="_name"/> + <assign location="_name" expr="27"/> + </onentry> + <transition cond="Var3293==_name" target="329s3"/> + <transition target="329fail"/> + </state> + <state id="329s3"> + <onentry> + <assign location="Var3294" expr="_ioprocessors"/> + <assign location="_ioprocessors" expr="27"/> + </onentry> + <transition cond="Var3294==_ioprocessors" target="329pass"/> + <transition target="329fail"/> + </state> + <state id="329pass"> + <onentry> + <send event="test.329.done" /> + </onentry> + <transition event="test.329.done" target="330start" /> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </state> + <final id="329fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> + </state> + + <!-- check that the required fields are present in both internal and external events --> + <state id="330start" initial="330s0" name="machineName"> + <state id="330s0"> + <onentry> + <raise event="foo"/> + </onentry> + <transition event="foo" cond="'name' in _event && 'type' in _event && 'sendid' in _event && 'origin' in _event && 'invokeid' && 'data' in _event" target="330s1"/> + <transition event="*" target="330fail"/> + </state> + <state id="330s1"> + <onentry> + <send event="foo"/> + </onentry> + <transition event="foo" cond="'name' in _event && 'type' in _event && 'sendid' in _event && 'origin' in _event && 'invokeid' && 'data' in _event" target="330pass"/> + <transition event="*" target="330fail"/> + </state> + <state id="330pass"> + <onentry> + <send event="test.330.done" /> + </onentry> + <transition event="test.330.done" target="331start" /> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </state> + <final id="330fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> + </state> + + <state id="331start" initial="331s0" name="machineName"> + <!-- test that _event.type is set correctly for internal, platform, and external events --> + <datamodel> + <data id="Var3311"/> + </datamodel> + <state id="331s0"> + <onentry> + <!-- internal event --> + <raise event="foo"/> + </onentry> + <transition event="foo" target="331s1"> + <assign location="Var3311" expr="_event.type"/> + </transition> + <transition event="*" target="331fail"/> + </state> + <state id="331s1"> + <transition cond="Var3311=='internal'" target="331s2"/> + <transition target="331fail"/> + </state> + <state id="331s2"> + <onentry> + <!-- this will generate an error, which is a platform event --> + <assign location="foo.bar.baz " expr="1"/> + </onentry> + <transition event="error" target="331s3"> + <assign location="Var3311" expr="_event.type"/> + </transition> + <transition event="*" target="331fail"/> + </state> + <state id="331s3"> + <transition cond="Var3311=='platform'" target="331s4"/> + <transition target="331fail"/> + </state> + <state id="331s4"> + <onentry> + <!-- external event --> + <send event="foo"/> + </onentry> + <transition event="foo" target="331s5"> + <assign location="Var3311" expr="_event.type"/> + </transition> + <transition event="*" target="331fail"/> + </state> + <state id="331s5"> + <transition cond="Var3311=='external'" target="331pass"/> + <transition target="331fail"/> + </state> + <state id="331pass"> + <onentry> + <send event="test.331.done" /> + </onentry> + <transition event="test.331.done" target="332start" /> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </state> + <final id="331fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> + </state> + + <!-- test that sendid is present in error events triggered by send errors --> + <state id="332start" initial="332s0" name="machineName"> + <datamodel> + <data id="Var3321"/> + <data id="Var3322"/> + </datamodel> + <state id="332s0"> + <onentry> + <!-- this will raise an error and also store the sendid in var3321 --> + <send target="baz" event="foo" idlocation="Var3321"/> + </onentry> + <transition event="error" target="332s1"> + <!-- get the sendid out of the error event --> + <assign location="Var3322" expr="_event.sendid"/> + </transition> + <transition event="*" target="332fail"/> + </state> + <state id="332s1"> + <!-- make sure that the sendid in the error event matches the one generated when send executed --> + <transition cond="Var3321===Var3322" target="332pass"/> + <transition target="332fail"/> + </state> + <state id="332pass"> + <onentry> + <send event="test.332.done" /> + </onentry> + <transition event="test.332.done" target="333start" /> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </state> + <final id="332fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> + </state> + + <!-- make sure sendid is blank in a non-error event --> + <state id="333start" initial="333s0" name="machineName"> + <state id="333s0"> + <onentry> + <send event="foo"/> + </onentry> + <transition event="foo" cond="typeof _event.sendid === 'undefined' " target="333pass"/> + <transition event="*" target="333fail"/> + </state> + <state id="333pass"> + <onentry> + <send event="test.333.done" /> + </onentry> + <transition event="test.333.done" target="335start" /> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </state> + <final id="333fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> + </state> + + <!-- test that origin field is blank for internal events --> + <state id="335start" initial="335s0" name="machineName"> + <state id="335s0"> + <onentry> + <raise event="foo"/> + </onentry> + <transition event="foo" cond="typeof _event.origin === 'undefined' " target="335pass"/> + <transition event="*" target="335fail"/> + </state> + <state id="335pass"> + <onentry> + <send event="test.335.done" /> + </onentry> + <transition event="test.335.done" target="336start" /> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </state> + <final id="335fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> + </state> + + <!-- test that the origin field of an external event contains a URL that lets you send back to the originator. In + this case it's the same session, so if we get bar we succeed --> + <state id="336start" initial="336s0" name="machineName"> + <state id="336s0"> + <onentry> + <send event="foo"/> + </onentry> + <transition event="foo" target="336s1"> + <send event="bar" targetexpr="_event.origin" typeexpr="_event.origintype"/> + </transition> + <transition event="*" target="336fail"/> + </state> + <state id="336s1"> + <onentry> + <send event="baz"/> + </onentry> + <transition event="bar" target="336pass"/> + <transition event="*" target="336fail"/> + </state> + <state id="336pass"> + <onentry> + <send event="test.336.done" /> + </onentry> + <transition event="test.336.done" target="337start" /> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </state> + <final id="336fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> + </state> + + <!-- test that origintype is blank on internal events --> + <state id="337start" initial="337s0" name="machineName"> + <state id="337s0"> + <onentry> + <raise event="foo"/> + </onentry> + <transition event="foo" cond="typeof _event.origintype === 'undefined' " target="337pass"/> + <transition event="*" target="337fail"/> + </state> + <state id="337pass"> + <onentry> + <send event="test.337.done" /> + </onentry> + <transition event="test.337.done" target="338start" /> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </state> + <final id="337fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> + </state> + + <!-- test that invokeid is set correctly in events received from an invoked process. timeout event catches the + case where the invoke doesn't work correctly --> + <state id="338start" initial="338s0"> + <datamodel> + <data id="Var3381"/> + <data id="Var3382"/> + </datamodel> + <state id="338s0"> + <onentry> + + </onentry> + <invoke idlocation="Var3381" type="http://www.w3.org/TR/scxml/"> + <content> + <scxml initial="338sub0" datamodel="ecmascript" name="machineName"> + <final id="338sub0"> + <onentry> + <send target="#_parent" event="event1"/> + </onentry> + </final> + </scxml> + </content> + </invoke> + <transition event="event1" target="338s1"> + <assign location="Var3382" expr="_event.invokeid"/> + </transition> + <transition event="event0" target="338fail"/> + </state> + <state id="338s1"> + <transition cond="Var3381===Var3382" target="338pass"/> + <transition target="338fail"/> + </state> + <state id="338pass"> + <onentry> + <send event="test.338.done" /> + </onentry> + <transition event="test.338.done" target="339start" /> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </state> + <final id="338fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> + </state> + + <!-- test that invokeid is blank in an event that wasn't returned from an invoked process --> + <state id="339start" initial="339s0" name="machineName"> + <state id="339s0"> + <onentry> + <raise event="foo"/> + </onentry> + <transition event="foo" cond="typeof _event.invokeid === 'undefined' " target="339pass"/> + <transition event="*" target="339fail"/> + </state> + <state id="339pass"> + <onentry> + <send event="test.339.done" /> + </onentry> + <transition event="test.339.done" target="342start" /> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </state> + <final id="339fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> + </state> + + <!-- test that eventexpr works and sets the name field of the resulting event --> + <state id="342start" initial="342s0" name="machineName"> + <datamodel> + <data id="Var3421" expr="'foo'"/> + <data id="Var3422"/> + </datamodel> + <state id="342s0"> + <onentry> + <send eventexpr="Var3421"/> + </onentry> + <transition event="foo" target="342s1"> + <assign location="Var3422" expr="_event.name"/> + </transition> + <transition event="*" target="342fail"/> + </state> + <state id="342s1"> + <transition cond="Var3421===Var3422" target="342pass"/> + <transition target="342fail"/> + </state> + <state id="342pass"> + <onentry> + <send event="test.342.done" /> + </onentry> + <transition event="test.342.done" target="343start" /> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </state> + <final id="342fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> + </state> + + <!-- test that illegal <param> produces error.execution and empty event.data --> + <state id="343start" initial="343s0"> + <state id="343s0" initial="343s01"> + <!-- we should get the error before the done event --> + <transition event="error.execution" target="343s1"/> + <transition event="done.state.343s0" target="343fail"/> + <transition event="done.state.343s0" target="343fail"> + </transition> + <state id="343s01"> + <transition target="343s02"/> + </state> + <final id="343s02"> + <donedata> + <param location="foo.bar.baz " name="someParam"/> + </donedata> + </final> + </state> + <!-- if we get here, we received the error event. Now check that the done + event has empty event.data --> + <state id="343s1"> + <transition event="done.state.343s0" cond="typeof _event.data === 'undefined'" target="343pass"/> + <transition event="*" target="343fail"/> + </state> + <state id="343pass"> + <onentry> + <send event="test.343.done" /> + </onentry> + <transition event="test.343.done" target="346start" /> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </state> + <final id="343fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> + </state> + + <!-- test that any attempt to change the value of a system variable causes error.execution to be raised. + Event1..4 are there to catch the case where the error event is not raised. In cases where it is, we have + to dispose of eventn in the next state, hence the targetless transitions (which simply throw away the event.) --> + <state id="346start" initial="346s0" name="machineName"> + <state id="346s0"> + <onentry> + <assign location="_sessionid" expr="'otherName'"/> + <raise event="event1"/> + </onentry> + <transition event="error.execution" target="346s1"/> + <transition event="*" target="346fail"/> + </state> + <state id="346s1"> + <onentry> + <assign location="_event" expr="'otherName'"/> + <raise event="event2"/> + </onentry> + <!-- throw out event1 if it's still around --> + <transition event="event1"/> + <transition event="error.execution" target="346s2"/> + <!-- event1 would trigger this transition if we didn't drop it. We want this transition to have + a very general trigger to catch cases where the wrong error event was raised --> + <transition event="*" target="346fail"/> + </state> + <state id="346s2"> + <onentry> + <assign location="_ioprocessors" expr="'otherName'"/> + <raise event="event3"/> + </onentry> + <transition event="event2"/> + <transition event="error.execution" target="346s3"/> + <transition event="*" target="346fail"/> + </state> + <state id="346s3"> + <onentry> + <assign location="_name" expr="'otherName'"/> + <raise event="event4"/> + </onentry> + <transition event="event3"/> + <transition event="error.execution" target="346pass"/> + <transition event="*" target="346fail"/> + </state> + <state id="346pass"> + <onentry> + <send event="test.346.done" /> + </onentry> + <transition event="test.346.done" target="348start" /> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </state> + <final id="346fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> + </state> + + <state id="348start" initial="348s0"> + <!-- test that event param of send sets the name of the event --> + <state id="348s0"> + <onentry> + <send type="http://www.w3.org/TR/scxml/#SCXMLEventProcessor" event="s0Event"/> + </onentry> + <transition event="s0Event" target="348pass"/> + <transition event="*" target="348fail"/> + </state> + <state id="348pass"> + <onentry> + <send event="test.348.done" /> + </onentry> + <transition event="test.348.done" target="349start" /> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </state> + <final id="348fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> + </state> + + <!-- test that value in origin field can be used to send an event back to the sender --> + <state id="349start" initial="349s0"> + <datamodel> + <data id="Var3491"/> + </datamodel> + <state id="349s0"> + <onentry> + <send type="http://www.w3.org/TR/scxml/#SCXMLEventProcessor" event="s0Event"/> + </onentry> + <transition event="s0Event" target="349s2"> + <assign location="Var3491" expr="_event.origin"/> + </transition> + <transition event="*" target="349fail"/> + </state> + <state id="349s2"> + <onentry> + <send type="http://www.w3.org/TR/scxml/#SCXMLEventProcessor" targetexpr="Var3491" event="s0Event2"/> + </onentry> + <transition event="s0Event2" target="349pass"/> + <transition event="*" target="349fail"/> + </state> + <state id="349pass"> + <onentry> + <send event="test.349.done" /> + </onentry> + <transition event="test.349.done" target="355start" /> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </state> + <final id="349fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> + </state> + + <!-- test that default initial state is first in document order. If we enter s0 first we succeed, if s1, failure. --> + <state id="355start"> + <state id="355s0"> + <transition target="355pass"/> + </state> + <state id="355s1"> + <transition target="355fail"/> + </state> + <state id="355pass"> + <onentry> + <send event="test.355.done" /> + </onentry> + <transition event="test.355.done" target="364start" /> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </state> + <final id="355fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> + </state> + + <!-- test that default initial states are entered when a compound state is entered. First we test + the 'initial' attribute, then the initial element, then default to the first child in document order. + If we get to s01111 we succeed, if any other state, failure. --> + <state id="364start" initial="364s1"> + <state id="364s1" initial="364s11p112 364s11p122"> + <onentry> + + </onentry> + <transition event="timeout" target="364fail"/> + <state id="364s11" initial="364s111"> + <state id="364s111"/> + <parallel id="364s11p1"> + <state id="364s11p11" initial="364s11p111"> + <state id="364s11p111"/> + <state id="364s11p112"> + <onentry> + <raise event="In-s11p112"/> + </onentry> + </state> + </state> + <state id="364s11p12" initial="364s11p121"> + <state id="364s11p121"/> + <state id="364s11p122"> + <transition event="In-s11p112" target="364s2"/> + </state> + </state> + </parallel> + </state> + </state> + <state id="364s2"> + <initial> + <transition target="364s21p112 364s21p122"/> + </initial> + <transition event="timeout" target="364fail"/> + <state id="364s21" initial="364s211"> + <state id="364s211"/> + <parallel id="364s21p1"> + <state id="364s21p11" initial="364s21p111"> + <state id="364s21p111"/> + <state id="364s21p112"> + <onentry> + <raise event="In-s21p112"/> + </onentry> + </state> + </state> + <state id="364s21p12" initial="364s21p121"> + <state id="364s21p121"/> + <state id="364s21p122"> + <transition event="In-s21p112" target="364s3"/> + </state> + </state> + </parallel> + </state> + </state> + <state id="364s3"> + <transition target="364fail"/> + <state id="364s31"> + <state id="364s311"> + <state id="364s3111"> + <transition target="364pass"/> + </state> + <state id="364s3112"/> + <state id="364s312"/> + <state id="364s32"/> + </state> + </state> + </state> + <state id="364pass"> + <onentry> + <send event="test.364.done" /> + </onentry> + <transition event="test.364.done" target="372start" /> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </state> + <final id="364fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> + </state> + + <!-- test that entering a final state generates done.state.parentid after executing the onentry elements. + Var3721 should be set to 2 (but not 3) by the time the event is raised --> + <state id="372start"> + <datamodel> + <data id="Var3721" expr="1"/> + </datamodel> + <state id="372s0" initial="372s0final"> + <onentry> + + </onentry> + <transition event="done.state.372s0" cond="Var3721==2" target="372pass"/> + <transition event="*" target="372fail"/> + <final id="372s0final"> + <onentry> + <assign location="Var3721" expr="2"/> + </onentry> + <onexit> + <assign location="Var3721" expr="3"/> + </onexit> + </final> + </state> + <state id="372pass"> + <onentry> + <send event="test.372.done" /> + </onentry> + <transition event="test.372.done" target="375start" /> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </state> + <final id="372fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> + </state> + + <!-- test that onentry handlers are executed in document order. event1 should be raised before event2 --> + <state id="375start"> + <state id="375s0"> + <onentry> + <raise event="event1"/> + </onentry> + <onentry> + <raise event="event2"/> + </onentry> + <transition event="event1" target="375s1"/> + <transition event="*" target="375fail"/> + </state> + <state id="375s1"> + <transition event="event2" target="375pass"/> + <transition event="*" target="375fail"/> + </state> + <state id="375pass"> + <onentry> + <send event="test.375.done" /> + </onentry> + <transition event="test.375.done" target="376start" /> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </state> + <final id="375fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> + </state> + + <!-- test that each onentry handler is a separate block. The <send> of event1 will cause an error but + the increment to var3761 should happen anyways --> + <state id="376start"> + <datamodel> + <data id="Var3761" expr="1"/> + </datamodel> + <state id="376s0"> + <onentry> + <send target="baz" event="event1"/> + </onentry> + <onentry> + <assign location="Var3761" expr="Var3761 + 1"/> + </onentry> + <transition cond="Var3761==2" target="376pass"/> + <transition target="376fail"/> + </state> + <state id="376pass"> + <onentry> + <send event="test.376.done" /> + </onentry> + <transition event="test.376.done" target="377start" /> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </state> + <final id="376fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> + </state> + + <!-- test that onexit handlers are executed in document order. event1 should be raised before event2 --> + <state id="377start"> + <state id="377s0"> + <onexit> + <raise event="event1"/> + </onexit> + <onexit> + <raise event="event2"/> + </onexit> + <transition target="377s1"/> + </state> + <state id="377s1"> + <transition event="event1" target="377s2"/> + <transition event="*" target="377fail"/> + </state> + <state id="377s2"> + <transition event="event2" target="377pass"/> + <transition event="*" target="377fail"/> + </state> + <state id="377pass"> + <onentry> + <send event="test.377.done" /> + </onentry> + <transition event="test.377.done" target="378start" /> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </state> + <final id="377fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> + </state> + + <!-- test that each onexithandler is a separate block. The <send> of event1 will cause an error but + the increment to var3781 should happen anyways --> + <state id="378start"> + <datamodel> + <data id="Var3781" expr="1"/> + </datamodel> + <state id="378s0"> + <onexit> + <send target="baz" event="event1"/> + </onexit> + <onexit> + <assign location="Var3781" expr="Var3781 + 1"/> + </onexit> + <transition target="378s1"/> + </state> + <state id="378s1"> + <transition cond="Var3781==2" target="378pass"/> + <transition target="378fail"/> + </state> + <state id="378pass"> + <onentry> + <send event="test.378.done" /> + </onentry> + <transition event="test.378.done" target="387start" /> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </state> + <final id="378fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> + </state> + + <!-- test that the default history state works correctly. From initial state s3 we take a transition to s0's default + shallow history state. That should generate "enteringS011", which takes us to s4. In s4, we + transition to s1's default deep history state. We should end up in s122, generating "enteringS122". Otherwise failure.--> + <state id="387start" initial="387s3"> + <state id="387s0" initial="387s01"> + <transition event="enteringS011" target="387s4"/> + <transition event="*" target="387fail"/> + <history type="shallow" id="387s0HistShallow"> + <transition target="387s01"/> + </history> + <history type="deep" id="387s0HistDeep"> + <transition target="387s022"/> + </history> + <state id="387s01" initial="387s011"> + <state id="387s011"> + <onentry> + <raise event="enteringS011"/> + </onentry> + </state> + <state id="387s012"> + <onentry> + <raise event="enteringS012"/> + </onentry> + </state> + </state> + <state id="387s02" initial="387s021"> + <state id="387s021"> + <onentry> + <raise event="enteringS021"/> + </onentry> + </state> + <state id="387s022"> + <onentry> + <raise event="enteringS022"/> + </onentry> + </state> + </state> + </state> + <state id="387s1" initial="387s11"> + <transition event="enteringS122" target="387pass"/> + <transition event="*" target="387fail"/> + <history type="shallow" id="387s1HistShallow"> + <transition target="387s11"/> + </history> + <history type="deep" id="387s1HistDeep"> + <transition target="387s122"/> + </history> + <state id="387s11" initial="387s111"> + <state id="387s111"> + <onentry> + <raise event="enteringS111"/> + </onentry> + </state> + <state id="387s112"> + <onentry> + <raise event="enteringS112"/> + </onentry> + </state> + </state> + <state id="387s12" initial="387s121"> + <state id="387s121"> + <onentry> + <raise event="enteringS121"/> + </onentry> + </state> + <state id="387s122"> + <onentry> + <raise event="enteringS122"/> + </onentry> + </state> + </state> + </state> + <state id="387s3"> + <onentry> + + </onentry> + <transition target="387s0HistShallow"/> + </state> + <state id="387s4"> + <transition target="387s1HistDeep"/> + </state> + <state id="387pass"> + <onentry> + <send event="test.387.done" /> + </onentry> + <transition event="test.387.done" target="388start" /> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </state> + <final id="387fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> + </state> + + <!-- test that history states works correctly. The counter Var3881 counts how many times + we have entered s0. The initial state is s012. We then transition to s1, which transitions + to s0's deep history state. entering.s012 should be raised, otherwise failure. Then we transition + to s02, which transitions to s0's shallow history state. That should have value s01, and its initial + state is s011, so we should get entering.s011, otherwise failure.--> + <state id="388start" initial="388s012"> + <datamodel> + <data id="Var3881" expr="0"/> + </datamodel> + <state id="388s0" initial="388s01"> + <onentry> + <assign location="Var3881" expr="Var3881 + 1"/> + </onentry> + <!-- the first time through, go to s1, setting a timer just in case something hangs --> + <transition event="entering.s012" cond="Var3881==1" target="388s1"> + + </transition> + <!-- the second time, we should get entering.s012. If so, go to s2, otherwise fail --> + <transition event="entering.s012" cond="Var3881==2" target="388s2"/> + <transition event="entering" cond="Var3881==2" target="388fail"/> + <!-- the third time we should get entering-s011. If so, pass, otherwise fail --> + <transition event="entering.s011" cond="Var3881==3" target="388pass"/> + <transition event="entering" cond="Var3881==3" target="388fail"/> + <!-- if we timeout, the state machine is hung somewhere, so fail --> + <transition event="timeout" target="388fail"/> + <history type="shallow" id="388s0HistShallow"> + <transition target="388s02"/> + </history> + <history type="deep" id="388s0HistDeep"> + <transition target="388s022"/> + </history> + <state id="388s01" initial="388s011"> + <state id="388s011"> + <onentry> + <raise event="entering.s011"/> + </onentry> + </state> + <state id="388s012"> + <onentry> + <raise event="entering.s012"/> + </onentry> + </state> + </state> + <state id="388s02" initial="388s021"> + <state id="388s021"> + <onentry> + <raise event="entering.s021"/> + </onentry> + </state> + <state id="388s022"> + <onentry> + <raise event="entering.s022"/> + </onentry> + </state> + </state> + </state> + <state id="388s1"> + <transition target="388s0HistDeep"/> + </state> + <state id="388s2"> + <transition target="388s0HistShallow"/> + </state> + <state id="388pass"> + <onentry> + <send event="test.388.done" /> + </onentry> + <transition event="test.388.done" target="396start" /> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </state> + <final id="388fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> + </state> + + <!-- test that the value in _event.name matches the event name used to match against transitions --> + <state id="396start"> + <state id="396s0"> + <onentry> + <raise event="foo"/> + </onentry> + <transition event="foo" cond="_event.name == 'foo'" target="396pass"/> + <transition event="foo" target="396fail"/> + </state> + <state id="396pass"> + <onentry> + <send event="test.396.done" /> + </onentry> + <transition event="test.396.done" target="399start" /> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </state> + <final id="396fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> + </state> + + <!-- test that the event name matching works correctly, including prefix matching and the fact + that the event attribute of transition may contain multiple event designators. --> + <state id="399start" initial="399s0"> + <state id="399s0" initial="399s01"> + <onentry> + + </onentry> + <!-- this will catch the failure case --> + <transition event="timeout" target="399fail"/> + <state id="399s01"> + <onentry> + <raise event="foo"/> + </onentry> + <!-- test that an event can match against a transition with multiple descriptors --> + <transition event="foo bar" target="399s02"/> + </state> + <state id="399s02"> + <onentry> + <raise event="bar"/> + </onentry> + <!-- test that an event can match the second descriptor as well --> + <transition event="foo bar" target="399s03"/> + </state> + <state id="399s03"> + <onentry> + <raise event="foo.zoo"/> + </onentry> + <!-- test that a prefix descriptor matches --> + <transition event="foo bar" target="399s04"/> + </state> + <state id="399s04"> + <onentry> + <raise event="foos"/> + </onentry> + <!-- test that only token prefixes match --> + <transition event="foo" target="399fail"/> + <transition event="foos" target="399s05"/> + </state> + <state id="399s05"> + <onentry> + <raise event="foo.zoo"/> + </onentry> + <!-- test that .* works at the end of a descriptor --> + <transition event="foo.*" target="399s06"/> + </state> + <state id="399s06"> + <onentry> + <raise event="foo"/> + </onentry> + <!-- test that "*" works by itself --> + <transition event="*" target="399pass"/> + </state> + </state> + <state id="399pass"> + <onentry> + <send event="test.399.done" /> + </onentry> + <transition event="test.399.done" target="401start" /> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </state> + <final id="399fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> + </state> + + <!-- test that errors go in the internal event queue. We send ourselves an external event foo, then perform + and operation that raises an error. Then check that the error event is processed first, even though + it was raised second --> + <state id="401start" initial="401s0"> + <state id="401s0"> + <onentry> + <send event="foo"/> + <!-- assigning to a non-existent location should raise an error --> + <assign location="foo.bar.baz " expr="2"/> + </onentry> + <transition event="foo" target="401fail"/> + <transition event="error" target="401pass"/> + </state> + <state id="401pass"> + <onentry> + <send event="test.401.done" /> + </onentry> + <transition event="test.401.done" target="402start" /> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </state> + <final id="401fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> + </state> + + <!-- the assertion that errors are 'like any other event' is pretty broad, but we can check that they + are pulled off the internal queue in order, and that prefix matching works on them. --> + <state id="402start" initial="402s0"> + <state id="402s0" initial="402s01"> + <onentry> + <!-- catch the failure case --> + + </onentry> + <transition event="timeout" target="402fail"/> + <state id="402s01"> + <onentry> + <!-- the first internal event. The error will be the second, and event2 will be the third --> + <raise event="event1"/> + <!-- assigning to a non-existent location should raise an error --> + <assign location="foo.bar.baz " expr="2"/> + </onentry> + <transition event="event1" target="402s02"> + <raise event="event2"/> + </transition> + <transition event="*" target="402fail"/> + </state> + <state id="402s02"> + <transition event="error" target="402s03"/> + <transition event="*" target="402fail"/> + </state> + <state id="402s03"> + <transition event="event2" target="402pass"/> + <transition event="*" target="402fail"/> + </state> + </state> + <state id="402pass"> + <onentry> + <send event="test.402.done" /> + </onentry> + <transition event="test.402.done" target="404start" /> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </state> + <final id="402fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> + </state> + + <!-- test that states are exited in exit order (children before parents with reverse doc order used to break ties + before the executable content in the transitions. event1, event2, event3, event4 should be raised in that + order when s01p is exited --> + <state id="404start" initial="404s0"> + <state id="404s0" initial="404s01p"> + <parallel id="404s01p"> + <onexit> + <!-- this should be the 3rd event raised --> + <raise event="event3"/> + </onexit> + <transition target="404s02"> + <!-- this should be the fourth event raised --> + <raise event="event4"/> + </transition> + <state id="404s01p1"> + <onexit> + <!-- this should be the second event raised --> + <raise event="event2"/> + </onexit> + </state> + <state id="404s01p2"> + <!-- this should be the first event raised --> + <onexit> + <raise event="event1"/> + </onexit> + </state> + </parallel> + <state id="404s02"> + <transition event="event1" target="404s03"/> + <transition event="*" target="404fail"/> + </state> + <state id="404s03"> + <transition event="event2" target="404s04"/> + <transition event="*" target="404fail"/> + </state> + <state id="404s04"> + <transition event="event3" target="404s05"/> + <transition event="*" target="404fail"/> + </state> + <state id="404s05"> + <transition event="event4" target="404pass"/> + <transition event="*" target="404fail"/> + </state> + </state> + <state id="404pass"> + <onentry> + <send event="test.404.done" /> + </onentry> + <transition event="test.404.done" target="405start" /> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </state> + <final id="404fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> + </state> + + <!-- test that the executable content in the transitions is executed in document order after + the states are exited. event1, event2, event3, event4 should be raised in that order when the + state machine is entered --> + <state id="405start" initial="405s0"> + <state id="405s0" initial="405s01p"> + <onentry> + + </onentry> + <transition event="timeout" target="405fail"/> + <parallel id="405s01p"> + <transition event="event1" target="405s02"/> + <state id="405s01p1" initial="405s01p11"> + <state id="405s01p11"> + <onexit> + <!-- this should be the second event raised --> + <raise event="event2"/> + </onexit> + <transition target="405s01p12"> + <!-- this should be the third event raised --> + <raise event="event3"/> + </transition> + </state> + <state id="405s01p12"/> + </state> + <!-- end s01p1 --> + <state id="405s01p2" initial="405s01p21"> + <state id="405s01p21"> + <onexit> + <!-- this should be the first event raised --> + <raise event="event1"/> + </onexit> + <transition target="405s01p22"> + <!-- this should be the fourth event raised --> + <raise event="event4"/> + </transition> + </state> + <state id="405s01p22"/> + </state> + <!-- end s01p2 --> + </parallel> + <state id="405s02"> + <transition event="event2" target="405s03"/> + <transition event="*" target="405fail"/> + </state> + <state id="405s03"> + <transition event="event3" target="405s04"/> + <transition event="*" target="405fail"/> + </state> + <state id="405s04"> + <transition event="event4" target="405pass"/> + <transition event="*" target="405fail"/> + </state> + </state> + <!-- end s01 --> + <state id="405pass"> + <onentry> + <send event="test.405.done" /> + </onentry> + <transition event="test.405.done" target="406start" /> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </state> + <final id="405fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> + </state> + + <!-- Test that states are entered in entry order (parents before children with document order used to break ties) + after the executable content in the transition is executed. event1, event2, event3, event4 should be raised in that + order when the transition in s01 is taken --> + <state id="406start" initial="406s0"> + <state id="406s0" initial="406s01"> + <onentry> + + </onentry> + <transition event="timeout" target="406fail"/> + <state id="406s01"> + <transition target="406s0p2"> + <!-- this should be the first event raised --> + <raise event="event1"/> + </transition> + </state> + <parallel id="406s0p2"> + <transition event="event1" target="406s03"/> + <state id="406s01p21"> + <onentry> + <!-- third event --> + <raise event="event3"/> + </onentry> + </state> + <state id="406s01p22"> + <onentry> + <!-- the fourth event --> + <raise event="event4"/> + </onentry> + </state> + <onentry> + <!-- this should be the second event raised --> + <raise event="event2"/> + </onentry> + </parallel> + <state id="406s03"> + <transition event="event2" target="406s04"/> + <transition event="*" target="406fail"/> + </state> + <state id="406s04"> + <transition event="event3" target="406s05"/> + <transition event="*" target="406fail"/> + </state> + <state id="406s05"> + <transition event="event4" target="406pass"/> + <transition event="*" target="406fail"/> + </state> + </state> + <!-- end s0 --> + <state id="406pass"> + <onentry> + <send event="test.406.done" /> + </onentry> + <transition event="test.406.done" target="407start" /> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </state> + <final id="406fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> + </state> + + <!-- a simple test that onexit handlers work. var4071 should be incremented when we leave s0 --> + <state id="407start" initial="407s0"> + <datamodel> + <data id="Var4071" expr="0"/> + </datamodel> + <state id="407s0"> + <onexit> + <assign location="Var4071" expr="Var4071 + 1"/> + </onexit> + <transition target="407s1"/> + </state> + <state id="407s1"> + <transition cond="Var4071==1" target="407pass"/> + <transition target="407fail"/> + </state> + <state id="407pass"> + <onentry> + <send event="test.407.done" /> + </onentry> + <transition event="test.407.done" target="411start" /> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </state> + <final id="407fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> + </state> + + <!-- we test that states are added to the active states list as they are entered and before onentry handlers + are executed. When s0's onentry handler fires we should not be in s01. But when s01's onentry handler + fires, we should be in s01. Therefore event1 should not fire, but event2 should. Either event1 or + timeout also indicates failure --> + <state id="411start" initial="411s0"> + <state id="411s0" initial="411s01"> + <onentry> + + <if cond="In('411s01')"> + <raise event="event1"/> + </if> + </onentry> + <transition event="timeout" target="411fail"/> + <transition event="event1" target="411fail"/> + <transition event="event2" target="411pass"/> + <state id="411s01"> + <onentry> + <if cond="In('411s01')"> + <raise event="event2"/> + </if> + </onentry> + </state> + </state> + <!-- end s0 --> + <state id="411pass"> + <onentry> + <send event="test.411.done" /> + </onentry> + <transition event="test.411.done" target="412start" /> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </state> + <final id="411fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> + </state> + + <!-- test that executable content in the <initial> transition executes after the onentry handler on the state + and before the onentry handler of the child states. Event1, event2, and event3 should occur in that order. --> + <state id="412start" initial="412s0"> + <state id="412s0" initial="412s01"> + <onentry> + + </onentry> + <transition event="timeout" target="412fail"/> + <transition event="event1" target="412fail"/> + <transition event="event2" target="412pass"/> + <state id="412s01"> + <onentry> + <raise event="event1"/> + </onentry> + <initial> + <transition target="412s011"> + <raise event="event2"/> + </transition> + </initial> + <state id="412s011"> + <onentry> + <raise event="event3"/> + </onentry> + <transition target="412s02"/> + </state> + </state> + <state id="412s02"> + <transition event="event1" target="412s03"/> + <transition event="*" target="412fail"/> + </state> + <state id="412s03"> + <transition event="event2" target="412s04"/> + <transition event="*" target="412fail"/> + </state> + <state id="412s04"> + <transition event="event3" target="412pass"/> + <transition event="*" target="412fail"/> + </state> + </state> + <!-- end s0 --> + <state id="412pass"> + <onentry> + <send event="test.412.done" /> + </onentry> + <transition event="test.412.done" target="413start" /> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </state> + <final id="412fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> + </state> + + <!-- test that the state machine is put into the configuration specified by the initial element, without regard + to any other defaults. we should start off in s2p111 and s2p122. the atomic + states we should not enter all have immediate transitions to failure in them --> + <state id="413start" initial="413s2p112 413s2p122"> + <state id="413s1"> + <transition target="413fail"/> + </state> + <state id="413s2" initial="413s2p1"> + <parallel id="413s2p1"> + <!-- this transition will be triggered only if we end up in an illegal configuration where we're in + either s2p112 or s2p122, but not both of them --> + <transition target="413fail"/> + <state id="413s2p11" initial="413s2p111"> + <state id="413s2p111"> + <transition target="413fail"/> + </state> + <state id="413s2p112"> + <transition cond="In('413s2p122')" target="413pass"/> + </state> + </state> + <!-- end s2p11 --> + <state id="413s2p12" initial="413s2p121"> + <state id="413s2p121"> + <transition target="413fail"/> + </state> + <state id="413s2p122"> + <transition cond="In('413s2p112')" target="413pass"/> + </state> + </state> + </parallel> + </state> + <!-- end s2 --> + <state id="413pass"> + <onentry> + <send event="test.413.done" /> + </onentry> + <transition event="test.413.done" target="416start" /> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </state> + <final id="413fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> + </state> + + <!-- test that the done.state.id gets generated when we enter the final state of a compound state --> + <state id="416start" initial="416s1"> + <state id="416s1" initial="416s11"> + <onentry> + + </onentry> + <transition event="timeout" target="416fail"/> + <state id="416s11" initial="416s111"> + <transition event="done.state.416s11" target="416pass"/> + <state id="416s111"> + <transition target="416s11final"/> + </state> + <final id="416s11final"/> + </state> + </state> + <state id="416pass"> + <onentry> + <send event="test.416.done" /> + </onentry> + <transition event="test.416.done" target="417start" /> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </state> + <final id="416fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> + </state> + + <!-- test that we get the done.state.id event when all of a + parallel elements children enter final states. --> + <state id="417start" initial="417s1"> + <state id="417s1" initial="417s1p1"> + <onentry> + + </onentry> + <transition event="timeout" target="417fail"/> + <parallel id="417s1p1"> + <transition event="done.state.417s1p1" target="417pass"/> + <state id="417s1p11" initial="417s1p111"> + <state id="417s1p111"> + <transition target="417s1p11final"/> + </state> + <final id="417s1p11final"/> + </state> + <state id="417s1p12" initial="417s1p121"> + <state id="417s1p121"> + <transition target="417s1p12final"/> + </state> + <final id="417s1p12final"/> + </state> + </parallel> + </state> + <state id="417pass"> + <onentry> + <send event="test.417.done" /> + </onentry> + <transition event="test.417.done" target="419start" /> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </state> + <final id="417fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> + </state> + + <!-- test that eventless transitions take precedence over event-driven ones --> + <state id="419start" initial="419s1"> + <state id="419s1"> + <onentry> + <raise event="internalEvent"/> + <send event="externalEvent"/> + </onentry> + <transition event="*" target="419fail"/> + <transition target="419pass"/> + </state> + <state id="419pass"> + <onentry> + <send event="test.419.done" /> + </onentry> + <transition event="test.419.done" target="421start" /> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </state> + <final id="419fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> + </state> + + <!-- test that internal events take priority over external ones, and that the processor + keeps pulling off internal events until it finds one that triggers a transition --> + <state id="421start" initial="421s1"> + <state id="421s1" initial="421s11"> + <onentry> + <send event="externalEvent"/> + <raise event="internalEvent1"/> + <raise event="internalEvent2"/> + <raise event="internalEvent3"/> + <raise event="internalEvent4"/> + </onentry> + <transition event="externalEvent" target="421fail"/> + <state id="421s11"> + <transition event="internalEvent3" target="421s12"/> + </state> + <state id="421s12"> + <transition event="internalEvent4" target="421pass"/> + </state> + </state> + <state id="421pass"> + <onentry> + <send event="test.421.done" /> + </onentry> + <transition event="test.421.done" target="423start" /> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </state> + <final id="421fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> + </state> + + <!-- test that we keep pulling external events off the queue till we find one that matches a transition. --> + <state id="423start" initial="423s0"> + <state id="423s0"> + <onentry> + <send event="externalEvent1"/> + <send event="externalEvent2" delayexpr="'0ms'"/> + <raise event="internalEvent"/> + </onentry> + <!-- in this state we should process only internalEvent --> + <transition event="internalEvent" target="423s1"/> + <transition event="*" target="423fail"/> + </state> + <state id="423s1"> + <!-- in this state we ignore externalEvent1 and wait for externalEvent2 --> + <transition event="externalEvent2" target="423pass"/> + <transition event="internalEvent" target="423fail"/> + </state> + <state id="423pass"> + <onentry> + <send event="test.423.done" /> + </onentry> + <transition event="test.423.done" target="444start" /> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </state> + <final id="423fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> + </state> + + <!-- test that <data> creates a new ecmascript variable. --> + <state id="444start"> + <datamodel> + <data id="var4441" expr="1"/> + </datamodel> + <state id="444s0"> + <!-- test that var4441 can be used as an ecmascript variable --> + <transition cond="++var4441==2" target="444pass"/> + <transition target="444fail"/> + </state> + <state id="444pass"> + <onentry> + <send event="test.444.done" /> + </onentry> + <transition event="test.444.done" target="445start" /> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </state> + <final id="444fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> + </state> + + <!-- test that ecmascript objects defined by <data> have value undefined if <data> does not assign a value --> + <state id="445start"> + <datamodel> + <data id="var4451"/> + </datamodel> + <state id="445s0"> + <transition cond="var4451==undefined" target="445pass"/> + <transition target="445fail"/> + </state> + <state id="445pass"> + <onentry> + <send event="test.445.done" /> + </onentry> + <transition event="test.445.done" target="448start" /> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </state> + <final id="445fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> + </state> + + <!-- test that all ecmascript objects are placed in a single global scope --> + <state id="448start"> + <state id="448s0"> + <!-- test that a parent state can access a variable defined in a child --> + <transition cond="var4481==1" target="448s1"/> + <transition target="448fail"/> + <state id="448s01"> + <datamodel> + <data id="var4481" expr="1"/> + </datamodel> + </state> + </state> + <state id="448s1" initial="448s01p"> + <parallel id="448s01p"> + <state id="448s01p1"> + <!-- test that we can access a variable defined in a parallel sibling state --> + <transition cond="var4482==1" target="448pass"/> + <transition target="448fail"/> + </state> + <state id="448s01p2"> + <datamodel> + <data id="var4482" expr="1"/> + </datamodel> + </state> + </parallel> + </state> + <state id="448pass"> + <onentry> + <send event="test.448.done" /> + </onentry> + <transition event="test.448.done" target="449start" /> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </state> + <final id="448fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> + </state> + + <!-- test that ecmascript objects are converted to booleans inside cond --> + <state id="449start"> + <state id="449s0"> + <transition cond="'foo'" target="449pass"/> + <transition target="449fail"/> + </state> + <state id="449pass"> + <onentry> + <send event="test.449.done" /> + </onentry> + <transition event="test.449.done" target="451start" /> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </state> + <final id="449fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> + </state> + + <!-- simple test of the in() predicate --> + <state id="451start" initial="451p"> + <parallel id="451p"> + <state id="451s0"> + <transition cond="In('451s1')" target="451pass"/> + <transition target="451fail"/> + </state> + <state id="451s1"/> + </parallel> + <state id="451pass"> + <onentry> + <send event="test.451.done" /> + </onentry> + <transition event="test.451.done" target="453start" /> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </state> + <final id="451fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> + </state> + + <!-- test that we can use any ecmascript expression as a value expression. + In this case, we just test that we can assign + a function to a variable and then call it. --> + <state id="453start"> + <datamodel> + <data id="var4531" expr="function(invar) {return invar + 1;}"/> + </datamodel> + <state id="453s0"> + <onentry> + <raise event="event1"/> + </onentry> + <!-- test that we can call the function --> + <transition event="event1" cond="var4531(2) == 3" target="453pass"/> + <transition event="*" target="453fail"/> + </state> + <state id="453pass"> + <onentry> + <send event="test.453.done" /> + </onentry> + <transition event="test.453.done" target="456start" /> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </state> + <final id="453fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> + </state> + + <!-- we can't test that _any_ ecmascript is valid inside <script>, so we + just run a simple one and check that it can update the data model. --> + <state id="456start" initial="456s0"> + <datamodel> + <data id="Var4561" expr="0"/> + </datamodel> + <state id="456s0"> + <onentry> + <script> + Var4561+=1 + </script> + </onentry> + <transition cond="Var4561==1" target="456pass"/> + <transition target="456fail"/> + </state> + <state id="456pass"> + <onentry> + <send event="test.456.done" /> + </onentry> + <transition event="test.456.done" target="457start" /> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </state> + <final id="456fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> + </state> + + <!-- test that an the legal iterable collections are arrays, namely objects that satisfy instanceof(Array) in ECMAScript. + the legal values for the 'item' attribute on foreach are legal ECMAScript variable names.. --> + <state id="457start" initial="457s0"> + <datamodel> + <data id="Var4571" expr="0"/> + <data id="Var4572"/> + <data id="Var4573"/> + <data id="Var4574" expr="7"/> + <data id="Var4575" expr="[1,2,3]"/> + <data id="Var4576"/> + </datamodel> + <state id="457s0"> + <onentry> + <!-- invalid array, legal item --> + <foreach item="Var4572" index="Var4573" array="Var4574"> + <assign location="Var4571" expr="Var4571 + 1"/> + </foreach> + <raise event="foo"/> + </onentry> + <transition event="error.execution" target="457s1"/> + <transition event="*" target="457fail"/> + </state> + <state id="457s1"> + <onentry> + <!-- illegal item, legal array --> + <foreach item="'continue'" index="Var4573" array="Var4575"> + <assign location="Var4571" expr="Var4571 + 1"/> + </foreach> + <raise event="bar"/> + </onentry> + <transition event="error.execution" target="457s2"/> + <transition event="bar" target="457fail"/> + </state> + <state id="457s2"> + <!-- check that var4571 has its original value (so executable content never got executed --> + <transition cond="Var4571==0" target="457s3"/> + <transition target="457fail"/> + </state> + <!-- finally check that a legal array works properly --> + <state id="457s3"> + <onentry> + <assign location="Var4576" expr="0"/> + <foreach item="Var4572" array="Var4575"> + <assign location="Var4576" expr="Var4576 + Var4572"/> + </foreach> + </onentry> + <transition cond="Var4576==6" target="457pass"/> + <transition target="457fail"/> + </state> + <state id="457pass"> + <onentry> + <send event="test.457.done" /> + </onentry> + <transition event="test.457.done" target="459start" /> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </state> + <final id="457fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> + </state> + + <!-- test that foreach goes over the array in the right order. since the array contains 1 2 3, we compare the current + value with the previous value, which is stored in var4591. The current value should always be larger. If + it ever isn't, set Var4594 to 0, indicating failure. Also check that the final value of the index + is 2 (meaning that the initial value was 0, not 1) --> + <state id="459start" initial="459s0"> + <datamodel> + <data id="Var4591" expr="0"/> + <!-- contains the previous value --> + <data id="Var4592"/> + <!-- the item which will contain the current value --> + <data id="Var4593"/> + <!-- the index --> + <data id="Var4594" expr="[1,2,3]"/> + <data id="Var4595" expr="1"/> + <!-- 1 if success, 0 if failure --> + </datamodel> + <state id="459s0"> + <onentry> + <foreach item="Var4592" array="Var4594" index="Var4593"> + <if cond="Var4591<Var4592"> + <assign location="Var4591" expr="Var4592"/> + <else/> + <!-- values are out of order, record failure --> + <assign location="Var4595" expr="0"/> + </if> + </foreach> + </onentry> + <!-- check that var4591 has its original value --> + <transition cond="Var4594==0 | Var4593 != 2" target="459fail"/> + <transition target="459pass"/> + </state> + <state id="459pass"> + <onentry> + <send event="test.459.done" /> + </onentry> + <transition event="test.459.done" target="460start" /> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </state> + <final id="459fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> + </state> + + <!-- test that <foreach> does a shallow copy, so that modifying the array does not change + the iteration behavior. --> + <state id="460start"> + <datamodel> + <data id="Var4601" expr="[1,2,3]"/> + <data id="Var4602" expr="0"/> + <!-- counts the number of iterations --> + </datamodel> + <state id="460s0"> + <onentry> + <foreach item="Var4603" array="Var4601"> + <assign location="Var4601" expr="[].concat(Var4601, [4])"/> + <assign location="Var4602" expr="Var4602 + 1"/> + </foreach> + </onentry> + <transition cond="Var4602==3" target="460pass"/> + <transition target="460fail"/> + </state> + <state id="460pass"> + <onentry> + <send event="test.460.done" /> + </onentry> + <transition event="test.460.done" target="495start" /> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </state> + <final id="460fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> + </state> + + <!-- test that the scxml event i/o processor puts events in the correct queues.--> + <state id="495start" initial="495s0"> + <state id="495s0"> + <onentry> + <!-- default target is external queue --> + <send event="event1" type="http://www.w3.org/TR/scxml/#SCXMLEventProcessor"/> + <send event="event2" target="#_internal" type="http://www.w3.org/TR/scxml/#SCXMLEventProcessor"/> + </onentry> + <!-- we should get the internal event first --> + <transition event="event1" target="495fail"/> + <transition event="event2" target="495s1"/> + </state> + <state id="495s1"> + <transition event="event1" target="495pass"/> + <transition event="*" target="495fail"/> + </state> + <state id="495pass"> + <onentry> + <send event="test.495.done" /> + </onentry> + <transition event="test.495.done" target="496start" /> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </state> + <final id="495fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> + </state> + + <state id="496start" initial="496s0"> + <state id="496s0"> + <onentry> + <send type="http://www.w3.org/TR/scxml/#SCXMLEventProcessor" event="event" target="#_scxml_foo"/> + <raise event="foo"/> + </onentry> + <transition event="error.communication" target="496pass"/> + <transition event="*" target="496fail"/> + </state> + <state id="496pass"> + <onentry> + <send event="test.496.done" /> + </onentry> + <transition event="test.496.done" target="500start" /> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </state> + <final id="496fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> + </state> + + <!-- test that location field is found inside entry for SCXML Event I/O processor --> + <state id="500start" initial="500s0"> + <datamodel> + <data id="Var5001" expr="_ioprocessors['http://www.w3.org/TR/scxml/#SCXMLEventProcessor'].location"/> + </datamodel> + <state id="500s0"> + <transition cond="Var5001" target="500pass"/> + <transition target="500fail"/> + </state> + <state id="500pass"> + <onentry> + <send event="test.500.done" /> + </onentry> + <transition event="test.500.done" target="501start" /> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </state> + <final id="500fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> + </state> + + <!-- test that the location entry for the SCXML Event I/O processor can be used as the target for an event --> + <state id="501start" initial="501s0"> + <datamodel> + <data id="Var5011" expr="_ioprocessors['http://www.w3.org/TR/scxml/#SCXMLEventProcessor'].location"/> + </datamodel> + <state id="501s0"> + <onentry> + <send targetexpr="Var5011" event="foo"/> + + </onentry> + <transition event="foo" target="501pass"/> + <transition event="*" target="501fail"/> + </state> + <state id="501pass"> + <onentry> + <send event="test.501.done" /> + </onentry> + <transition event="test.501.done" target="503start" /> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </state> + <final id="501fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> + </state> + + <!-- test that a targetless transition does not exit and reenter its source state --> + <state id="503start" initial="503s1"> + <datamodel> + <data id="Var5031" expr="0"/> + <!-- how often we have exited s2 --> + <data id="Var5032" expr="0"/> + <!-- how often the targetless transition in s2 has been executed --> + </datamodel> + <state id="503s1"> + <onentry> + <raise event="foo"/> + <raise event="bar"/> + </onentry> + <transition target="503s2"/> + </state> + <state id="503s2"> + <onexit> + <assign location="Var5031" expr="Var5031 + 1"/> + </onexit> + <transition event="foo"> + <assign location="Var5032" expr="Var5032 + 1"/> + </transition> + <!-- make sure the transition on foo was actually taken --> + <transition event="bar" cond="Var5032==1" target="503s3"/> + <transition event="bar" target="503fail"/> + </state> + <state id="503s3"> + <!-- make sure that s2 was exited only once --> + <transition cond="Var5031==1" target="503pass"/> + <transition target="503fail"/> + </state> + <state id="503pass"> + <onentry> + <send event="test.503.done" /> + </onentry> + <transition event="test.503.done" target="504start" /> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </state> + <final id="503fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> + </state> + + <!-- test that an external transition exits all states up the the LCCA --> + <state id="504start" initial="504s1"> + <datamodel> + <data id="Var5041" expr="0"/> + <!-- how often we have exited p --> + <data id="Var5042" expr="0"/> + <!-- how often we have exited ps1 --> + <data id="Var5043" expr="0"/> + <!-- how often we have exited ps2 --> + <data id="Var5044" expr="0"/> + <!-- how often the transition for foo has been taken --> + <data id="Var5045" expr="0"/> + <!-- how often we have exited s2 --> + </datamodel> + <state id="504s1"> + <onentry> + <raise event="foo"/> + <raise event="bar"/> + </onentry> + <transition target="504p"/> + </state> + <state id="504s2"> + <onexit> + <assign location="Var5045" expr="Var5045 + 1"/> + </onexit> + <parallel id="504p"> + <onexit> + <assign location="Var5041" expr="Var5041 + 1"/> + </onexit> + <transition event="foo" target="504ps1"> + <assign location="Var5044" expr="Var5044 + 1"/> + </transition> + <!-- make sure the transition on foo was actually taken --> + <transition event="bar" cond="Var5044==1" target="504s3"/> + <transition event="bar" target="504fail"/> + <state id="504ps1"> + <onexit> + <assign location="Var5042" expr="Var5042 + 1"/> + </onexit> + </state> + <state id="504ps2"> + <onexit> + <assign location="Var5043" expr="Var5043 + 1"/> + </onexit> + </state> + </parallel> + </state> + <state id="504s3"> + <!-- make sure that p was exited twice --> + <transition cond="Var5041==2" target="504s4"/> + <transition target="504fail"/> + </state> + <state id="504s4"> + <!-- make sure that ps1 was exited twice --> + <transition cond="Var5042==2" target="504s5"/> + <transition target="504fail"/> + </state> + <state id="504s5"> + <!-- make sure that ps2 was exited twice --> + <transition cond="Var5043==2" target="504s6"/> + <transition target="504fail"/> + </state> + <state id="504s6"> + <!-- make sure that s1 was exited once --> + <transition cond="Var5045==1" target="504pass"/> + <transition target="504fail"/> + </state> + <state id="504pass"> + <onentry> + <send event="test.504.done" /> + </onentry> + <transition event="test.504.done" target="505start" /> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </state> + <final id="504fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> + </state> + + <!-- test that an internal transition does not exit its source state --> + <state id="505start" initial="505s1"> + <datamodel> + <data id="Var5051" expr="0"/> + <!-- how often we have exited s1 --> + <data id="Var5052" expr="0"/> + <!-- how often we have exited s11 --> + <data id="Var5053" expr="0"/> + <!-- how often the transition for foo has been taken --> + </datamodel> + <state id="505s1"> + <onentry> + <raise event="foo"/> + <raise event="bar"/> + </onentry> + <onexit> + <assign location="Var5051" expr="Var5051 + 1"/> + </onexit> + <transition event="foo" type="internal" target="505s11"> + <assign location="Var5053" expr="Var5053 + 1"/> + </transition> + <!-- make sure the transition on foo was actually taken --> + <transition event="bar" cond="Var5053==1" target="505s2"/> + <transition event="bar" target="505fail"/> + <state id="505s11"> + <onexit> + <assign location="Var5052" expr="Var5052 + 1"/> + </onexit> + </state> + </state> + <state id="505s2"> + <!-- make sure that s1 was exited once --> + <transition cond="Var5051==1" target="505s3"/> + <transition target="505fail"/> + </state> + <state id="505s3"> + <!-- make sure that s11 was exited twice --> + <transition cond="Var5052==2" target="505pass"/> + <transition target="505fail"/> + </state> + <state id="505pass"> + <onentry> + <send event="test.505.done" /> + </onentry> + <transition event="test.505.done" target="506start" /> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </state> + <final id="505fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> + </state> + + <!-- test that an internal transition whose targets are not proper descendants of its source state + behaves like an external transition --> + <state id="506start" initial="506s1"> + <datamodel> + <data id="Var5061" expr="0"/> + <!-- how often we have exited s2 --> + <data id="Var5062" expr="0"/> + <!-- how often we have exited s21 --> + <data id="Var5063" expr="0"/> + <!-- how often the transition for foo has been taken --> + </datamodel> + <state id="506s1"> + <onentry> + <raise event="foo"/> + <raise event="bar"/> + </onentry> + <transition target="506s2"/> + </state> + <state id="506s2" initial="506s21"> + <onexit> + <assign location="Var5061" expr="Var5061 + 1"/> + </onexit> + <transition event="foo" type="internal" target="506s2"> + <assign location="Var5063" expr="Var5063 + 1"/> + </transition> + <!-- make sure the transition on foo was actually taken --> + <transition event="bar" cond="Var5063==1" target="506s3"/> + <transition event="bar" target="506fail"/> + <state id="506s21"> + <onexit> + <assign location="Var5062" expr="Var5062 + 1"/> + </onexit> + </state> + </state> + <state id="506s3"> + <!-- make sure that s2 was exited twice --> + <transition cond="Var5061==2" target="506s4"/> + <transition target="506fail"/> + </state> + <state id="506s4"> + <!-- make sure that s21 was exited twice --> + <transition cond="Var5062==2" target="506pass"/> + <transition target="506fail"/> + </state> + <state id="506pass"> + <onentry> + <send event="test.506.done" /> + </onentry> + <transition event="test.506.done" target="509start" /> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </state> + <final id="506fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> + </state> + + <!-- test that Basic HTTP Event I/O processor uses POST method and that it can receive messages + at the accessURI --> + <state id="509start" initial="509s0"> + <state id="509s0"> + <onentry> + + <send event="test" targetexpr="_ioprocessors['basichttp']['location']" type="http://www.w3.org/TR/scxml/#BasicHTTPEventProcessor"/> + </onentry> + <!-- if the event was send by http and we get it, we succeed --> + <transition event="test" cond="_event.raw.search('POST') !== -1" target="509pass"/> + <transition event="*" target="509fail"/> + </state> + <state id="509pass"> + <onentry> + <send event="test.509.done" /> + </onentry> + <transition event="test.509.done" target="510start" /> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </state> + <final id="509fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> + </state> + + <!-- test that Basic HTTP messages go into external queue. --> + <state id="510start" initial="510s0"> + <state id="510s0"> + <onentry> + + <send event="test" targetexpr="_ioprocessors['basichttp']['location']" type="http://www.w3.org/TR/scxml/#BasicHTTPEventProcessor"/> + <!-- this creates an internal event --> + <raise event="internal"/> + </onentry> + <!-- we should get 'internal' first, then 'test' --> + <transition event="internal" target="510s1"/> + <transition event="*" target="510fail"/> + </state> + <state id="510s1"> + <transition event="test" target="510pass"/> + <transition event="*" target="510fail"/> + </state> + <state id="510pass"> + <onentry> + <send event="test.510.done" /> + </onentry> + <transition event="test.510.done" target="518start" /> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </state> + <final id="510fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> + </state> + + <!-- test that that namelist values get encoded as POST parameters. --> + <state id="518start" initial="518s0"> + <datamodel> + <data id="Var5181" expr="2"/> + </datamodel> + <state id="518s0"> + <onentry> + + <send event="test" targetexpr="_ioprocessors['basichttp']['location']" namelist="Var5181" type="http://www.w3.org/TR/scxml/#BasicHTTPEventProcessor"/> + </onentry> + <transition event="test" cond="_event.raw.search(/Var5181=2/) !== -1" target="518pass"/> + <transition event="*" target="518fail"/> + </state> + <state id="518pass"> + <onentry> + <send event="test.518.done" /> + </onentry> + <transition event="test.518.done" target="519start" /> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </state> + <final id="518fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> + </state> + + <!-- test that that <param> values get encoded as POST parameters. . --> + <state id="519start" initial="519s0"> + <state id="519s0"> + <onentry> + + <send event="test" targetexpr="_ioprocessors['basichttp']['location']" type="http://www.w3.org/TR/scxml/#BasicHTTPEventProcessor"> + <param name="param1" expr="1"/> + </send> + </onentry> + <!-- if other end sends us back this event, we succeed --> + <transition event="test" cond="_event.raw.search('param1=1') !== -1" target="519pass"/> + <transition event="*" target="519fail"/> + </state> + <state id="519pass"> + <onentry> + <send event="test.519.done" /> + </onentry> + <transition event="test.519.done" target="520start" /> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </state> + <final id="519fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> + </state> + + <!-- test that that <content> gets sent as the body of the message. --> + <state id="520start" initial="520s0"> + <state id="520s0"> + <onentry> + + <send targetexpr="_ioprocessors['basichttp']['location']" type="http://www.w3.org/TR/scxml/#BasicHTTPEventProcessor"> + <content>this is some content</content> + </send> + </onentry> + <!-- if other end sends us back this event, we succeed. Test for two common + ways of encoding --> + <transition event="HTTP.POST" cond="_event.raw.search(/this+is+some+content/) !== -1" target="520pass"/> + <transition event="HTTP.POST" cond="_event.raw.search(/this%20is%20some%20content/) !== -1" target="520pass"/> + <transition event="*" target="520fail"/> + </state> + <state id="520pass"> + <onentry> + <send event="test.520.done" /> + </onentry> + <transition event="test.520.done" target="521start" /> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </state> + <final id="520fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> + </state> + + <!-- we test that the processor raises error.communication if it cannot dispatch the event. + (To create an undispatchable event, we choose a non-existent session as target). If it raises + the error event, we succeed. Otherwise we eventually timeout and fail. --> + <state id="521start" initial="521s0"> + <state id="521s0"> + <onentry> + <!-- should cause an error --> + <send target="#_scxml_foo" event="event2"/> + <!-- this will get added to the external event queue after the error has been raised --> + <send event="timeout"/> + </onentry> + <!-- once we've entered the state, we should check for internal events first --> + <transition event="error.communication" target="521pass"/> + <transition event="*" target="521fail"/> + </state> + <state id="521pass"> + <onentry> + <send event="test.521.done" /> + </onentry> + <transition event="test.521.done" target="522start" /> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </state> + <final id="521fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> + </state> + + <!-- test that location field the entry for Basic HTTP Event I/O processor can be used + to send a message to the processor --> + <state id="522start" initial="522s0"> + <state id="522s0"> + <onentry> + + <send event="test" type="http://www.w3.org/TR/scxml/#BasicHTTPEventProcessor" targetexpr="_ioprocessors['basichttp']['location']"/> + </onentry> + <!-- the event we receive should be called 'test', but that's not actually + required for this test. Only that the send deliver some event to us. So if + we get something other than timeout or error, we call it success --> + <transition event="timeout" target="522fail"/> + <transition event="error" target="522fail"/> + <transition event="*" target="522pass"/> + </state> + <state id="522pass"> + <onentry> + <send event="test.522.done" /> + </onentry> + <transition event="test.522.done" target="525start" /> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </state> + <final id="522fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> + </state> + + <!-- test that <foreach> does a shallow copy, so that modifying the array does not change + the iteration behavior. --> + <state id="525start"> + <datamodel> + <data id="Var5251"> + [1,2,3] + </data> + <data id="Var5252" expr="0"/> + <!-- counts the number of iterations --> + </datamodel> + <state id="525s0"> + <onentry> + <foreach item="Var5253" array="Var5251"> + <assign location="Var5251" expr="[].concat(Var5251, [4])"/> + <assign location="Var5252" expr="Var5252 + 1"/> + </foreach> + </onentry> + <transition cond="Var5252==3" target="525pass"/> + <transition target="525fail"/> + </state> + <state id="525pass"> + <onentry> + <send event="test.525.done" /> + </onentry> + <transition event="test.525.done" target="527start" /> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </state> + <final id="525fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> + </state> + + <!-- simple test that 'expr' works with <content> --> + <state id="527start" initial="527s0"> + <state id="527s0" initial="527s01"> + <transition event="done.state.527s0" cond="_event.data == 'foo'" target="527pass"> + </transition> + <transition event="done.state.527s0" target="527fail"> + </transition> + <state id="527s01"> + <transition target="527s02"/> + </state> + <final id="527s02"> + <donedata> + <content expr="'foo'"/> + </donedata> + </final> + </state> + <state id="527pass"> + <onentry> + <send event="test.527.done" /> + </onentry> + <transition event="test.527.done" target="529start" /> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </state> + <final id="527fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> + </state> + + <!-- simple test that children workn with <content> --> + <state id="529start" initial="529s0"> + <state id="529s0" initial="529s01"> + <transition event="done.state.529s0" cond="_event.data == 21" target="529pass"> + </transition> + <transition event="done.state.529s0" target="529fail"> + </transition> + <state id="529s01"> + <transition target="529s02"/> + </state> + <final id="529s02"> + <donedata> + <content>21</content> + </donedata> + </final> + </state> + <state id="529pass"> + <onentry> + <send event="test.529.done" /> + </onentry> + <transition event="test.529.done" target="530start" /> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </state> + <final id="529fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> + </state> + + <!-- test that <content> child is evaluated when <invoke> is. Var5301 is initialized + with an integer value, then set to an scxml script in the onentry to s0. If <content> + is evaluated at the right time, we should get invoke.done, otherwise an error --> + <state id="530start" initial="530s0"> + <datamodel> + <data id="Var5301" expr="1"/> + </datamodel> + <state id="530s0"> + <onentry> + <assign location="Var5301"> + <scxml> + <final/> + </scxml> + </assign> + + </onentry> + <invoke type="http://www.w3.org/TR/scxml/"> + <content expr="Var5301"/> + </invoke> + <transition event="done.invoke" target="530pass"/> + <transition event="*" target="530fail"/> + </state> + <state id="530pass"> + <onentry> + <send event="test.530.done" /> + </onentry> + <transition event="test.530.done" target="531start" /> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </state> + <final id="530fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> + </state> + + <!-- test that that the value of the <param> _scxmleventname gets used as the name + of the raised event. --> + <state id="531start" initial="531s0"> + <state id="531s0"> + <onentry> + + <send targetexpr="_ioprocessors['basichttp']['location']" type="http://www.w3.org/TR/scxml/#BasicHTTPEventProcessor"> + <param name="_scxmleventname" expr="'test'"/> + </send> + </onentry> + <!-- if we get an event named 'test' we succeed. Otherwise fail --> + <transition event="test" target="531pass"/> + <transition event="*" target="531fail"/> + </state> + <state id="531pass"> + <onentry> + <send event="test.531.done" /> + </onentry> + <transition event="test.531.done" target="532start" /> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </state> + <final id="531fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> + </state> + + <!-- test that that if _scxmleventname is not present, the name of the HTTP method is used + as the name of the resulting event. --> + <state id="532start" initial="532s0"> + <state id="532s0"> + <onentry> + + <send targetexpr="_ioprocessors['basichttp']['location']" type="http://www.w3.org/TR/scxml/#BasicHTTPEventProcessor"> + <!-- this content will be ignored, but it's here to make sure we have a message body --> + <content>some content</content> + </send> + </onentry> + <transition event="HTTP.POST" target="532pass"/> + <transition event="*" target="532fail"/> + </state> + <state id="532pass"> + <onentry> + <send event="test.532.done" /> + </onentry> + <transition event="test.532.done" target="533start" /> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </state> + <final id="532fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> + </state> + + <!-- test that an internal transition whose source state is not compound does exit its source state --> + <state id="533start" initial="533s1"> + <datamodel> + <data id="Var5331" expr="0"/> + <!-- how often we have exited p --> + <data id="Var5332" expr="0"/> + <!-- how often we have exited ps1 --> + <data id="Var5333" expr="0"/> + <!-- how often we have exited ps2 --> + <data id="Var5334" expr="0"/> + <!-- how often the transition for foo has been taken --> + </datamodel> + <state id="533s1"> + <onentry> + <raise event="foo"/> + <raise event="bar"/> + </onentry> + <transition target="533p"/> + </state> + <parallel id="533p"> + <onexit> + <assign location="Var5331" expr="Var5331 + 1"/> + </onexit> + <transition event="foo" type="internal" target="533ps1"> + <assign location="Var5334" expr="Var5334 + 1"/> + </transition> + <!-- make sure the transition on foo was actually taken --> + <transition event="bar" cond="Var5334==1" target="533s2"/> + <transition event="bar" target="533fail"/> + <state id="533ps1"> + <onexit> + <assign location="Var5332" expr="Var5332 + 1"/> + </onexit> + </state> + <state id="533ps2"> + <onexit> + <assign location="Var5333" expr="Var5333 + 1"/> + </onexit> + </state> + </parallel> + <state id="533s2"> + <!-- make sure that p was exited twice --> + <transition cond="Var5331==2" target="533s3"/> + <transition target="533fail"/> + </state> + <state id="533s3"> + <!-- make sure that ps1 was exited twice --> + <transition cond="Var5332==2" target="533s4"/> + <transition target="533fail"/> + </state> + <state id="533s4"> + <!-- make sure that ps2 was exited twice --> + <transition cond="Var5333==2" target="533pass"/> + <transition target="533fail"/> + </state> + <state id="533pass"> + <onentry> + <send event="test.533.done" /> + </onentry> + <transition event="test.533.done" target="534start" /> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </state> + <final id="533fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> + </state> + + <!-- test that that <send> 'event' value gets sent as the param _scxmleventname . --> + <state id="534start" initial="534s0"> + <state id="534s0"> + <onentry> + + <send event="test" targetexpr="_ioprocessors['basichttp']['location']" type="http://www.w3.org/TR/scxml/#BasicHTTPEventProcessor"> + </send> + </onentry> + <!-- if other end sends us back this event, we succeed --> + <transition event="test" cond="_event.raw.search('_scxmleventname=test') !== -1" target="534pass"/> + <transition event="*" target="534fail"/> + </state> + <state id="534pass"> + <onentry> + <send event="test.534.done" /> + </onentry> + <transition event="test.534.done" target="550start" /> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </state> + <final id="534fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> + </state> + + <!-- test that expr can be used to assign a value to a var. This test uses early binding --> + <state id="550start" initial="550s0" binding="early"> + <state id="550s0"> + <transition cond="Var5501==2" target="550pass"/> + <transition target="550fail"/> + </state> + <state id="550s1"> + <datamodel> + <data id="Var5501" expr="2"/> + </datamodel> + </state> + <state id="550pass"> + <onentry> + <send event="test.550.done" /> + </onentry> + <transition event="test.550.done" target="551start" /> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </state> + <final id="550fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> + </state> + + <!-- test that inline content can be used to assign a value to a var. --> + <state id="551start" initial="551s0" binding="early"> + <state id="551s0"> + <transition cond="Var5511" target="551pass"/> + <transition target="551fail"/> + </state> + <state id="551s1"> + <datamodel> + <data id="Var5511"> + [1,2,3] + </data> + </datamodel> + </state> + <state id="551pass"> + <onentry> + <send event="test.551.done" /> + </onentry> + <transition event="test.551.done" target="554start" /> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </state> + <final id="551fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> + </state> + + <!-- test that if the evaluation of <invoke>'s args causes an error, the + invocation is cancelled. In this test, that means that we don't get done.invoke + before the timer goes off. --> + <state id="554start" initial="554s0"> + <state id="554s0"> + <onentry> + <send event="timer" delayexpr="'0ms'"/> + </onentry> + <!-- reference an invalid namelist --> + <invoke type="http://www.w3.org/TR/scxml/" namelist=""foo"> + <content> + <scxml initial="554subFinal" datamodel="ecmascript"> + <final id="554subFinal"/> + </scxml> + </content> + </invoke> + <transition event="timer" target="554pass"/> + <transition event="done.invoke" target="554fail"/> + </state> + <state id="554pass"> + <onentry> + <send event="test.554.done" /> + </onentry> + <transition event="test.554.done" target="560start" /> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </state> + <final id="554fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> + </state> + + <!-- in the ECMA data model, test that processor creates correct structure in + _event.data when receiving KVPs in an event --> + <state id="560start" initial="560s0"> + <state id="560s0"> + <onentry> + <send event="foo"> + <param name="aParam" expr="1"/> + </send> + </onentry> + <transition event="foo" cond="_event.data.aParam == 1" target="560pass"/> + <transition event="*" target="560fail"/> + </state> + <state id="560pass"> + <onentry> + <send event="test.560.done" /> + </onentry> + <transition event="test.560.done" target="561start" /> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </state> + <final id="560fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> + </state> + + <!-- in the ECMA data model, test that processor creates an ECMAScript DOM object + _event.data when receiving XML in an event --> + <state id="561start" initial="561s0"> + <state id="561s0"> + <onentry> + <send event="foo"> + <content> + <books xmlns=""> + <book title="title1"/> + <book title="title2"/> + </books> + </content> + </send> + </onentry> + <transition event="foo" cond="_event.data.getElementsByTagName('book')[1].getAttribute('title') == 'title2'" target="561pass"/> + <transition event="*" target="561fail"/> + </state> + <state id="561pass"> + <onentry> + <send event="test.561.done" /> + </onentry> + <transition event="test.561.done" target="562start" /> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </state> + <final id="561fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> + </state> + + <!-- in the ECMA data model, test that processor creates space normalized string in + _event.data when receiving anything other than KVPs or XML in an event --> + <state id="562start" initial="562s0"> + <state id="562s0"> + <onentry> + <send event="foo"> + <content> + this is a + string + </content> + </send> + </onentry> + <transition event="foo" cond="_event.data == 'this is a string'" target="562pass"/> + <transition event="*" target="562fail"/> + </state> + <state id="562pass"> + <onentry> + <send event="test.562.done" /> + </onentry> + <transition event="test.562.done" target="567start" /> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </state> + <final id="562fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> + </state> + + <!-- test that that any content in the message other than _scxmleventname is used to populate + _event.data. --> + <state id="567start" initial="567s0"> + <datamodel> + <data id="Var5671" expr="2"/> + </datamodel> + <state id="567s0"> + <onentry> + + <!-- in this case, 'test' will be placed in _scxmleventname. The <param> should + be used to populate _event.data --> + <send event="test" targetexpr="_ioprocessors['basichttp']['location']" type="http://www.w3.org/TR/scxml/#BasicHTTPEventProcessor"> + <param name="param1" expr="2"/> + </send> + </onentry> + <!-- if we get this event, we succeed --> + <transition event="test" target="567s1"> + <assign location="Var5671" expr="_event.data.param1"/> + </transition> + <transition event="*" target="567fail"/> + </state> + <state id="567s1"> + <transition cond="Var5671==2" target="567pass"/> + <transition target="567fail"/> + </state> + <state id="567pass"> + <onentry> + <send event="test.567.done" /> + </onentry> + <transition event="test.567.done" target="569start" /> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </state> + <final id="567fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> + </state> + + <!-- test that location field is found inside entry for SCXML Event I/O processor in the ECMAScript + data model. The tests for the relevant event i/o processors will test that it can be used to + send events. --> + <state id="569start" initial="569s0"> + <state id="569s0"> + <transition cond="_ioprocessors['scxml'].location" target="569pass"/> + <transition target="569fail"/> + </state> + <state id="569pass"> + <onentry> + <send event="test.569.done" /> + </onentry> + <transition event="test.569.done" target="570start" /> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </state> + <final id="569fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> + </state> + + <!-- test that we generate done.state.id when all a parallel state's children are in final states --> + <state id="570start" initial="570p0"> + <datamodel> + <data id="Var5701" expr="0"/> + </datamodel> + <parallel id="570p0"> + <onentry> + + <raise event="e1"/> + <raise event="e2"/> + </onentry> + <!-- record that we get the first done event --> + <transition event="done.state.570p0s1"> + <assign location="Var5701" expr="1"/> + </transition> + <!-- we should get the second done event before done.state.p0 --> + <transition event="done.state.570p0s2" target="570s1"/> + <transition event="timeout" target="570fail"/> + <state id="570p0s1" initial="570p0s11"> + <state id="570p0s11"> + <transition event="e1" target="570p0s1final"/> + </state> + <final id="570p0s1final"/> + </state> + <state id="570p0s2" initial="570p0s21"> + <state id="570p0s21"> + <transition event="e2" target="570p0s2final"/> + </state> + <final id="570p0s2final"/> + </state> + </parallel> + <state id="570s1"> + <!-- if we get done.state.p0, success --> + <transition event="done.state.570p0" cond="Var5701==1" target="570pass"/> + <transition event="*" target="570fail"/> + </state> + <state id="570pass"> + <onentry> + <send event="test.570.done" /> + </onentry> + <transition event="test.570.done" target="576start" /> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </state> + <final id="570fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> + </state> + + <!-- test that the 'initial' value of scxml is respected. We set the value to deeply nested non-default parallel siblings and + test that both are entered. --> + <state id="576start" initial="576s11p112 576s11p122"> + <state id="576s0"> + <transition target="576fail"/> + </state> + <state id="576s1"> + <onentry> + + </onentry> + <transition event="timeout" target="576fail"/> + <state id="576s11" initial="576s111"> + <state id="576s111"/> + <parallel id="576s11p1"> + <state id="576s11p11" initial="576s11p111"> + <state id="576s11p111"/> + <state id="576s11p112"> + <onentry> + <raise event="In-s11p112"/> + </onentry> + </state> + </state> + <state id="576s11p12" initial="576s11p121"> + <state id="576s11p121"/> + <state id="576s11p122"> + <transition event="In-s11p112" target="576pass"/> + </state> + </state> + </parallel> + </state> + </state> + <state id="576pass"> + <onentry> + <send event="test.576.done" /> + </onentry> + <transition event="test.576.done" target="577start" /> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </state> + <final id="576fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> + </state> + + <!-- test that that <send> without target in basichttp event i/o processor + causes error.communication to get added to internal queue . --> + <state id="577start" initial="577s0"> + <state id="577s0"> + <onentry> + <!-- sent by scxml event i/o processor, added to external queue --> + <send event="event1"/> + <!-- should put error.communication on internal queue --> + <send event="test" type="http://www.w3.org/TR/scxml/#BasicHTTPEventProcessor"/> + </onentry> + <transition event="error.communication" target="577pass"/> + <transition event="*" target="577fail"/> + </state> + <state id="577pass"> + <onentry> + <send event="test.577.done" /> + </onentry> + <transition event="test.577.done" target="578start" /> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </state> + <final id="577fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> + </state> + + <!-- in the ECMA data model, test that processor creates an ECMAScript object + _event.data when receiving JSON in an event --> + <state id="578start" initial="578s0"> + <state id="578s0"> + <onentry> + <send event="foo"> + <content>{ "productName" : "bar", "size" : 27 }</content> + </send> + </onentry> + <transition event="foo" cond="_event.data.productName == 'bar'" target="578pass"/> + <transition event="*" target="578fail"/> + </state> + <state id="578pass"> + <onentry> + <send event="test.578.done" /> + </onentry> + <transition event="test.578.done" target="579start" /> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </state> + <final id="578fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> + </state> + + <!-- test that default history content is executed correctly. The Process MUST execute any executable content in the transition after the parent state's onentry handlers, and, in the case where the history pseudo-state is the target of an <initial> transition, + the executable content inside the <initial> transition. However the Processor MUST + execute this content only if there is no stored history. Once the history state's + parent state has been visited and exited, the default history content must not be executed --> + <state id="579start" initial="579s0"> + <state id="579s0"> + <datamodel> + <data id="Var5791" expr="0"/> + </datamodel> + <initial> + <transition target="579sh1"> + <raise event="event2"/> + </transition> + </initial> + <onentry> + <send delayexpr="'0ms'" event="timeout"/> + <raise event="event1"/> + </onentry> + <onexit> + <assign location="Var5791" expr="Var5791 + 1"/> + </onexit> + <history id="579sh1"> + <transition target="579s01"> + <raise event="event3"/> + </transition> + </history> + <state id="579s01"> + <transition event="event1" target="579s02"/> + <transition event="*" target="579fail"/> + </state> + <state id="579s02"> + <transition event="event2" target="579s03"/> + <transition event="*" target="579fail"/> + </state> + <state id="579s03"> + <transition cond="Var5791==0" event="event3" target="579s0"/> + <transition cond="Var5791==1" event="event1" target="579s2"/> + <transition event="*" target="579fail"/> + </state> + </state> + <state id="579s2"> + <transition event="event2" target="579s3"/> + <transition event="*" target="579fail"/> + </state> + <state id="579s3"> + <transition event="event3" target="579fail"/> + <transition event="timeout" target="579pass"/> + </state> + <state id="579pass"> + <onentry> + <send event="test.579.done" /> + </onentry> + <transition event="test.579.done" target="580start" /> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </state> + <final id="579fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> + </state> + + <!-- test that a history state never ends up part of the configuration --> + <state id="580start" initial="580p1"> + <datamodel> + <data id="Var5801" expr="0"/> + </datamodel> + <parallel id="580p1"> + <onentry> + <send delay="0ms" event="timeout"/> + </onentry> + <state id="580s0"> + <transition cond="In('580sh1')" target="580fail"/> + <transition event="timeout" target="580fail"/> + </state> + <state id="580s1"> + <initial> + <transition target="580sh1"/> + </initial> + <history id="580sh1"> + <transition target="580s11"/> + </history> + <state id="580s11"> + <transition cond="In('580sh1')" target="580fail"/> + <transition target="580s12"/> + </state> + <state id="580s12"/> + <transition cond="In('580sh1')" target="580fail"/> + <transition cond="Var5801==0" target="580sh1"/> + <transition cond="Var5801==1" target="580pass"/> + <onexit> + <assign location="Var5801" expr="Var5801 + 1"/> + </onexit> + </state> + </parallel> + <state id="580pass"> + <onentry> + <send event="test.580.done" /> + </onentry> + <transition event="test.580.done" target="pass" /> + <onentry> + <log label="Outcome" expr="'pass'"/> + </onentry> + </state> + <final id="580fail"> + <onentry> + <log label="Outcome" expr="'fail'"/> + </onentry> + </final> + </state> + + <final id="pass" /> +</scxml> |