From defaf05b818e358d3f2ecaff6d5ca4519d347164 Mon Sep 17 00:00:00 2001 From: JohnnyT Date: Fri, 8 Aug 2025 17:56:59 -0600 Subject: [PATCH 01/18] Adds files from generating new mix application --- .formatter.exs | 4 ++++ README.md | 21 +++++++++++++++++++++ lib/sc.ex | 18 ++++++++++++++++++ mix.exs | 28 ++++++++++++++++++++++++++++ test/sc_test.exs | 8 ++++++++ test/test_helper.exs | 1 + 6 files changed, 80 insertions(+) create mode 100644 .formatter.exs create mode 100644 README.md create mode 100644 lib/sc.ex create mode 100644 mix.exs create mode 100644 test/sc_test.exs create mode 100644 test/test_helper.exs diff --git a/.formatter.exs b/.formatter.exs new file mode 100644 index 0000000..d2cda26 --- /dev/null +++ b/.formatter.exs @@ -0,0 +1,4 @@ +# Used by "mix format" +[ + inputs: ["{mix,.formatter}.exs", "{config,lib,test}/**/*.{ex,exs}"] +] diff --git a/README.md b/README.md new file mode 100644 index 0000000..8aa3cfe --- /dev/null +++ b/README.md @@ -0,0 +1,21 @@ +# SC + +**TODO: Add description** + +## Installation + +If [available in Hex](https://hex.pm/docs/publish), the package can be installed +by adding `sc` to your list of dependencies in `mix.exs`: + +```elixir +def deps do + [ + {:sc, "~> 0.1.0"} + ] +end +``` + +Documentation can be generated with [ExDoc](https://github.com/elixir-lang/ex_doc) +and published on [HexDocs](https://hexdocs.pm). Once published, the docs can +be found at . + diff --git a/lib/sc.ex b/lib/sc.ex new file mode 100644 index 0000000..cf6c077 --- /dev/null +++ b/lib/sc.ex @@ -0,0 +1,18 @@ +defmodule SC do + @moduledoc """ + Documentation for `SC`. + """ + + @doc """ + Hello world. + + ## Examples + + iex> SC.hello() + :world + + """ + def hello do + :world + end +end diff --git a/mix.exs b/mix.exs new file mode 100644 index 0000000..50fa76c --- /dev/null +++ b/mix.exs @@ -0,0 +1,28 @@ +defmodule SC.MixProject do + use Mix.Project + + def project do + [ + app: :sc, + version: "0.1.0", + elixir: "~> 1.18", + start_permanent: Mix.env() == :prod, + deps: deps() + ] + end + + # Run "mix help compile.app" to learn about applications. + def application do + [ + extra_applications: [:logger] + ] + end + + # Run "mix help deps" to learn about dependencies. + defp deps do + [ + # {:dep_from_hexpm, "~> 0.3.0"}, + # {:dep_from_git, git: "https://github.com/elixir-lang/my_dep.git", tag: "0.1.0"} + ] + end +end diff --git a/test/sc_test.exs b/test/sc_test.exs new file mode 100644 index 0000000..32fd1eb --- /dev/null +++ b/test/sc_test.exs @@ -0,0 +1,8 @@ +defmodule SCTest do + use ExUnit.Case + doctest SC + + test "greets the world" do + assert SC.hello() == :world + end +end diff --git a/test/test_helper.exs b/test/test_helper.exs new file mode 100644 index 0000000..869559e --- /dev/null +++ b/test/test_helper.exs @@ -0,0 +1 @@ +ExUnit.start() From a7f36ec743525445d5808ae94c84b9237adce994 Mon Sep 17 00:00:00 2001 From: JohnnyT Date: Tue, 12 Aug 2025 06:41:15 -0600 Subject: [PATCH 02/18] Add SCXML and SCION test cases --- mix.exs | 4 + test/scion_tests/actionSend/send1_test.exs | 47 +++++++ test/scion_tests/actionSend/send2_test.exs | 50 +++++++ test/scion_tests/actionSend/send3_test.exs | 50 +++++++ test/scion_tests/actionSend/send4_test.exs | 68 +++++++++ test/scion_tests/actionSend/send4b_test.exs | 50 +++++++ test/scion_tests/actionSend/send7_test.exs | 61 +++++++++ test/scion_tests/actionSend/send7b_test.exs | 51 +++++++ test/scion_tests/actionSend/send8_test.exs | 58 ++++++++ test/scion_tests/actionSend/send8b_test.exs | 51 +++++++ test/scion_tests/actionSend/send9_test.exs | 63 +++++++++ .../assign-current-small-step/test0_test.exs | 67 +++++++++ .../assign-current-small-step/test1_test.exs | 55 ++++++++ .../assign-current-small-step/test2_test.exs | 75 ++++++++++ .../assign-current-small-step/test3_test.exs | 83 +++++++++++ .../assign-current-small-step/test4_test.exs | 73 ++++++++++ .../assign/assign_invalid_test.exs | 47 +++++++ .../assign/assign_obj_literal_test.exs | 46 +++++++ .../scion_tests/atom3-basic-tests/m0_test.exs | 29 ++++ .../scion_tests/atom3-basic-tests/m1_test.exs | 31 +++++ .../scion_tests/atom3-basic-tests/m2_test.exs | 36 +++++ .../scion_tests/atom3-basic-tests/m3_test.exs | 50 +++++++ test/scion_tests/basic/basic0_test.exs | 36 +++++ test/scion_tests/basic/basic1_test.exs | 39 ++++++ test/scion_tests/basic/basic2_test.exs | 42 ++++++ .../TestConditionalTransition_test.exs | 115 ++++++++++++++++ test/scion_tests/cond-js/test0_test.exs | 39 ++++++ test/scion_tests/cond-js/test1_test.exs | 42 ++++++ test/scion_tests/cond-js/test2_test.exs | 39 ++++++ test/scion_tests/data/data_invalid_test.exs | 46 +++++++ .../data/data_obj_literal_test.exs | 45 ++++++ .../default-initial-state/initial1_test.exs | 40 ++++++ .../default-initial-state/initial2_test.exs | 40 ++++++ test/scion_tests/delayedSend/send1_test.exs | 49 +++++++ test/scion_tests/delayedSend/send2_test.exs | 52 +++++++ test/scion_tests/delayedSend/send3_test.exs | 52 +++++++ .../documentOrder/documentOrder0_test.exs | 41 ++++++ test/scion_tests/error/error_test.exs | 92 +++++++++++++ test/scion_tests/foreach/test1_test.exs | 61 +++++++++ .../hierarchy+documentOrder/test0_test.exs | 50 +++++++ .../hierarchy+documentOrder/test1_test.exs | 50 +++++++ test/scion_tests/hierarchy/hier0_test.exs | 43 ++++++ test/scion_tests/hierarchy/hier1_test.exs | 47 +++++++ test/scion_tests/hierarchy/hier2_test.exs | 47 +++++++ test/scion_tests/history/history0_test.exs | 60 ++++++++ test/scion_tests/history/history1_test.exs | 64 +++++++++ test/scion_tests/history/history2_test.exs | 64 +++++++++ test/scion_tests/history/history3_test.exs | 68 +++++++++ test/scion_tests/history/history4_test.exs | 114 ++++++++++++++++ test/scion_tests/history/history4b_test.exs | 114 ++++++++++++++++ test/scion_tests/history/history5_test.exs | 87 ++++++++++++ test/scion_tests/history/history6_test.exs | 91 ++++++++++++ test/scion_tests/if-else/test0_test.exs | 117 ++++++++++++++++ test/scion_tests/in/TestInPredicate_test.exs | 129 ++++++++++++++++++ .../internal-transitions/test0.scxml.bak | 56 ++++++++ .../internal-transitions/test0_test.exs | 67 +++++++++ .../internal-transitions/test1_test.exs | 103 ++++++++++++++ test/scion_tests/misc/deep-initial_test.exs | 29 ++++ test/scion_tests/more-parallel/test0_test.exs | 41 ++++++ .../scion_tests/more-parallel/test10_test.exs | 75 ++++++++++ .../more-parallel/test10b_test.exs | 75 ++++++++++ test/scion_tests/more-parallel/test1_test.exs | 52 +++++++ test/scion_tests/more-parallel/test2_test.exs | 54 ++++++++ .../scion_tests/more-parallel/test2b_test.exs | 54 ++++++++ test/scion_tests/more-parallel/test3_test.exs | 54 ++++++++ .../scion_tests/more-parallel/test3b_test.exs | 54 ++++++++ test/scion_tests/more-parallel/test4_test.exs | 54 ++++++++ test/scion_tests/more-parallel/test5_test.exs | 54 ++++++++ test/scion_tests/more-parallel/test6_test.exs | 66 +++++++++ .../scion_tests/more-parallel/test6b_test.exs | 66 +++++++++ test/scion_tests/more-parallel/test7_test.exs | 66 +++++++++ test/scion_tests/more-parallel/test8_test.exs | 63 +++++++++ test/scion_tests/more-parallel/test9_test.exs | 63 +++++++++ .../test1_test.exs | 51 +++++++ .../parallel+interrupt/test0_test.exs | 52 +++++++ .../parallel+interrupt/test10_test.exs | 60 ++++++++ .../parallel+interrupt/test11_test.exs | 48 +++++++ .../parallel+interrupt/test12_test.exs | 62 +++++++++ .../parallel+interrupt/test13_test.exs | 64 +++++++++ .../parallel+interrupt/test14_test.exs | 77 +++++++++++ .../parallel+interrupt/test15_test.exs | 78 +++++++++++ .../parallel+interrupt/test16_test.exs | 55 ++++++++ .../parallel+interrupt/test17_test.exs | 55 ++++++++ .../parallel+interrupt/test18_test.exs | 48 +++++++ .../parallel+interrupt/test19_test.exs | 57 ++++++++ .../parallel+interrupt/test1_test.exs | 56 ++++++++ .../parallel+interrupt/test20_test.exs | 57 ++++++++ .../parallel+interrupt/test21_test.exs | 58 ++++++++ .../parallel+interrupt/test21b_test.exs | 59 ++++++++ .../parallel+interrupt/test21c_test.exs | 60 ++++++++ .../parallel+interrupt/test22_test.exs | 59 ++++++++ .../parallel+interrupt/test23_test.exs | 48 +++++++ .../parallel+interrupt/test24_test.exs | 57 ++++++++ .../parallel+interrupt/test25_test.exs | 57 ++++++++ .../parallel+interrupt/test27_test.exs | 61 +++++++++ .../parallel+interrupt/test28_test.exs | 55 ++++++++ .../parallel+interrupt/test29_test.exs | 55 ++++++++ .../parallel+interrupt/test2_test.exs | 60 ++++++++ .../parallel+interrupt/test30_test.exs | 62 +++++++++ .../parallel+interrupt/test31_test.exs | 65 +++++++++ .../parallel+interrupt/test3_test.exs | 50 +++++++ .../parallel+interrupt/test4_test.exs | 69 ++++++++++ .../parallel+interrupt/test5_test.exs | 67 +++++++++ .../parallel+interrupt/test6_test.exs | 71 ++++++++++ .../parallel+interrupt/test7_test.exs | 72 ++++++++++ .../parallel+interrupt/test7b_test.exs | 72 ++++++++++ .../parallel+interrupt/test8_test.exs | 59 ++++++++ .../parallel+interrupt/test9_test.exs | 58 ++++++++ test/scion_tests/parallel/test0_test.exs | 40 ++++++ test/scion_tests/parallel/test1_test.exs | 60 ++++++++ test/scion_tests/parallel/test2_test.exs | 73 ++++++++++ test/scion_tests/parallel/test3_test.exs | 88 ++++++++++++ test/scion_tests/script-src/script-0-0.js | 1 + test/scion_tests/script-src/script-1-0.js | 1 + test/scion_tests/script-src/script-1-1.js | 1 + test/scion_tests/script-src/script-2-0.js | 1 + test/scion_tests/script-src/script-2-1.js | 1 + test/scion_tests/script-src/script-2-2.js | 1 + test/scion_tests/script-src/script-2-3.js | 1 + test/scion_tests/script-src/script-3-0.js | 3 + test/scion_tests/script-src/test0_test.exs | 53 +++++++ test/scion_tests/script-src/test1_test.exs | 53 +++++++ test/scion_tests/script-src/test2_test.exs | 72 ++++++++++ test/scion_tests/script-src/test3_test.exs | 57 ++++++++ test/scion_tests/script/test0_test.exs | 55 ++++++++ test/scion_tests/script/test1_test.exs | 56 ++++++++ test/scion_tests/script/test2_test.exs | 80 +++++++++++ .../star0_test.exs | 44 ++++++ .../test0_test.exs | 68 +++++++++ .../test1_test.exs | 73 ++++++++++ test/scion_tests/send-data/send1_test.exs | 91 ++++++++++++ .../send-idlocation/test0_test.exs | 55 ++++++++ test/scion_tests/send-internal/test0_test.exs | 77 +++++++++++ .../targetless-transition/test0_test.exs | 50 +++++++ .../targetless-transition/test1_test.exs | 53 +++++++ .../targetless-transition/test2_test.exs | 56 ++++++++ .../targetless-transition/test3_test.exs | 84 ++++++++++++ .../test158_test.exs | 42 ++++++ .../test159_test.exs | 38 ++++++ .../SelectingTransitions/test403a_test.exs | 49 +++++++ .../SelectingTransitions/test403b_test.exs | 49 +++++++ .../SelectingTransitions/test403c_test.exs | 64 +++++++++ .../SelectingTransitions/test404_test.exs | 63 +++++++++ .../SelectingTransitions/test405_test.exs | 70 ++++++++++ .../SelectingTransitions/test406_test.exs | 66 +++++++++ .../SelectingTransitions/test407_test.exs | 40 ++++++ .../SelectingTransitions/test409_test.exs | 45 ++++++ .../SelectingTransitions/test411_test.exs | 45 ++++++ .../SelectingTransitions/test412_test.exs | 63 +++++++++ .../SelectingTransitions/test413_test.exs | 51 +++++++ .../SelectingTransitions/test416_test.exs | 40 ++++++ .../SelectingTransitions/test417_test.exs | 48 +++++++ .../SelectingTransitions/test419_test.exs | 35 +++++ .../SelectingTransitions/test421_test.exs | 43 ++++++ .../SelectingTransitions/test422_test.exs | 86 ++++++++++++ .../SelectingTransitions/test423_test.exs | 40 ++++++ .../SelectingTransitions/test503_test.exs | 51 +++++++ .../SelectingTransitions/test504_test.exs | 84 ++++++++++++ .../SelectingTransitions/test505_test.exs | 60 ++++++++ .../SelectingTransitions/test506_test.exs | 63 +++++++++ .../SelectingTransitions/test533_test.exs | 73 ++++++++++ .../mandatory/data/test276_test.exs | 34 +++++ .../mandatory/data/test276sub1_test.exs | 29 ++++ .../mandatory/data/test277_test.exs | 44 ++++++ .../mandatory/data/test279_test.exs | 37 +++++ .../mandatory/data/test280_test.exs | 45 ++++++ .../mandatory/data/test550_test.exs | 36 +++++ .../mandatory/data/test551_test.exs | 38 ++++++ .../mandatory/events/test396_test.exs | 34 +++++ .../mandatory/events/test399_test.exs | 70 ++++++++++ .../mandatory/events/test401_test.exs | 34 +++++ .../mandatory/events/test402_test.exs | 50 +++++++ .../mandatory/final/test372_test.exs | 45 ++++++ .../mandatory/final/test570_test.exs | 58 ++++++++ .../mandatory/foreach/test150_test.exs | 54 ++++++++ .../mandatory/foreach/test151_test.exs | 54 ++++++++ .../mandatory/foreach/test152_test.exs | 60 ++++++++ .../mandatory/foreach/test153_test.exs | 48 +++++++ .../mandatory/foreach/test155_test.exs | 43 ++++++ .../mandatory/foreach/test156_test.exs | 44 ++++++ .../mandatory/foreach/test525_test.exs | 43 ++++++ .../mandatory/history/test387_test.exs | 104 ++++++++++++++ .../mandatory/history/test388_test.exs | 79 +++++++++++ .../mandatory/history/test579_test.exs | 74 ++++++++++ .../mandatory/history/test580_test.exs | 61 +++++++++ .../scxml_tests/mandatory/if/test147_test.exs | 47 +++++++ .../scxml_tests/mandatory/if/test148_test.exs | 47 +++++++ .../scxml_tests/mandatory/if/test149_test.exs | 44 ++++++ .../mandatory/onentry/test375_test.exs | 41 ++++++ .../mandatory/onentry/test376_test.exs | 40 ++++++ .../mandatory/onexit/test377_test.exs | 44 ++++++ .../mandatory/onexit/test378_test.exs | 43 ++++++ .../mandatory/raise/test144_test.exs | 39 ++++++ .../mandatory/scxml/test355_test.exs | 33 +++++ .../mandatory/scxml/test576_test.exs | 55 ++++++++ .../mandatory/state/test364_test.exs | 90 ++++++++++++ test/support/sc_case.ex | 54 ++++++++ 197 files changed, 10851 insertions(+) create mode 100644 test/scion_tests/actionSend/send1_test.exs create mode 100644 test/scion_tests/actionSend/send2_test.exs create mode 100644 test/scion_tests/actionSend/send3_test.exs create mode 100644 test/scion_tests/actionSend/send4_test.exs create mode 100644 test/scion_tests/actionSend/send4b_test.exs create mode 100644 test/scion_tests/actionSend/send7_test.exs create mode 100644 test/scion_tests/actionSend/send7b_test.exs create mode 100644 test/scion_tests/actionSend/send8_test.exs create mode 100644 test/scion_tests/actionSend/send8b_test.exs create mode 100644 test/scion_tests/actionSend/send9_test.exs create mode 100644 test/scion_tests/assign-current-small-step/test0_test.exs create mode 100644 test/scion_tests/assign-current-small-step/test1_test.exs create mode 100644 test/scion_tests/assign-current-small-step/test2_test.exs create mode 100644 test/scion_tests/assign-current-small-step/test3_test.exs create mode 100644 test/scion_tests/assign-current-small-step/test4_test.exs create mode 100644 test/scion_tests/assign/assign_invalid_test.exs create mode 100644 test/scion_tests/assign/assign_obj_literal_test.exs create mode 100644 test/scion_tests/atom3-basic-tests/m0_test.exs create mode 100644 test/scion_tests/atom3-basic-tests/m1_test.exs create mode 100644 test/scion_tests/atom3-basic-tests/m2_test.exs create mode 100644 test/scion_tests/atom3-basic-tests/m3_test.exs create mode 100644 test/scion_tests/basic/basic0_test.exs create mode 100644 test/scion_tests/basic/basic1_test.exs create mode 100644 test/scion_tests/basic/basic2_test.exs create mode 100644 test/scion_tests/cond-js/TestConditionalTransition_test.exs create mode 100644 test/scion_tests/cond-js/test0_test.exs create mode 100644 test/scion_tests/cond-js/test1_test.exs create mode 100644 test/scion_tests/cond-js/test2_test.exs create mode 100644 test/scion_tests/data/data_invalid_test.exs create mode 100644 test/scion_tests/data/data_obj_literal_test.exs create mode 100644 test/scion_tests/default-initial-state/initial1_test.exs create mode 100644 test/scion_tests/default-initial-state/initial2_test.exs create mode 100644 test/scion_tests/delayedSend/send1_test.exs create mode 100644 test/scion_tests/delayedSend/send2_test.exs create mode 100644 test/scion_tests/delayedSend/send3_test.exs create mode 100644 test/scion_tests/documentOrder/documentOrder0_test.exs create mode 100644 test/scion_tests/error/error_test.exs create mode 100644 test/scion_tests/foreach/test1_test.exs create mode 100644 test/scion_tests/hierarchy+documentOrder/test0_test.exs create mode 100644 test/scion_tests/hierarchy+documentOrder/test1_test.exs create mode 100644 test/scion_tests/hierarchy/hier0_test.exs create mode 100644 test/scion_tests/hierarchy/hier1_test.exs create mode 100644 test/scion_tests/hierarchy/hier2_test.exs create mode 100644 test/scion_tests/history/history0_test.exs create mode 100644 test/scion_tests/history/history1_test.exs create mode 100644 test/scion_tests/history/history2_test.exs create mode 100644 test/scion_tests/history/history3_test.exs create mode 100644 test/scion_tests/history/history4_test.exs create mode 100644 test/scion_tests/history/history4b_test.exs create mode 100644 test/scion_tests/history/history5_test.exs create mode 100644 test/scion_tests/history/history6_test.exs create mode 100644 test/scion_tests/if-else/test0_test.exs create mode 100644 test/scion_tests/in/TestInPredicate_test.exs create mode 100644 test/scion_tests/internal-transitions/test0.scxml.bak create mode 100644 test/scion_tests/internal-transitions/test0_test.exs create mode 100644 test/scion_tests/internal-transitions/test1_test.exs create mode 100644 test/scion_tests/misc/deep-initial_test.exs create mode 100644 test/scion_tests/more-parallel/test0_test.exs create mode 100644 test/scion_tests/more-parallel/test10_test.exs create mode 100644 test/scion_tests/more-parallel/test10b_test.exs create mode 100644 test/scion_tests/more-parallel/test1_test.exs create mode 100644 test/scion_tests/more-parallel/test2_test.exs create mode 100644 test/scion_tests/more-parallel/test2b_test.exs create mode 100644 test/scion_tests/more-parallel/test3_test.exs create mode 100644 test/scion_tests/more-parallel/test3b_test.exs create mode 100644 test/scion_tests/more-parallel/test4_test.exs create mode 100644 test/scion_tests/more-parallel/test5_test.exs create mode 100644 test/scion_tests/more-parallel/test6_test.exs create mode 100644 test/scion_tests/more-parallel/test6b_test.exs create mode 100644 test/scion_tests/more-parallel/test7_test.exs create mode 100644 test/scion_tests/more-parallel/test8_test.exs create mode 100644 test/scion_tests/more-parallel/test9_test.exs create mode 100644 test/scion_tests/multiple-events-per-transition/test1_test.exs create mode 100644 test/scion_tests/parallel+interrupt/test0_test.exs create mode 100644 test/scion_tests/parallel+interrupt/test10_test.exs create mode 100644 test/scion_tests/parallel+interrupt/test11_test.exs create mode 100644 test/scion_tests/parallel+interrupt/test12_test.exs create mode 100644 test/scion_tests/parallel+interrupt/test13_test.exs create mode 100644 test/scion_tests/parallel+interrupt/test14_test.exs create mode 100644 test/scion_tests/parallel+interrupt/test15_test.exs create mode 100644 test/scion_tests/parallel+interrupt/test16_test.exs create mode 100644 test/scion_tests/parallel+interrupt/test17_test.exs create mode 100644 test/scion_tests/parallel+interrupt/test18_test.exs create mode 100644 test/scion_tests/parallel+interrupt/test19_test.exs create mode 100644 test/scion_tests/parallel+interrupt/test1_test.exs create mode 100644 test/scion_tests/parallel+interrupt/test20_test.exs create mode 100644 test/scion_tests/parallel+interrupt/test21_test.exs create mode 100644 test/scion_tests/parallel+interrupt/test21b_test.exs create mode 100644 test/scion_tests/parallel+interrupt/test21c_test.exs create mode 100644 test/scion_tests/parallel+interrupt/test22_test.exs create mode 100644 test/scion_tests/parallel+interrupt/test23_test.exs create mode 100644 test/scion_tests/parallel+interrupt/test24_test.exs create mode 100644 test/scion_tests/parallel+interrupt/test25_test.exs create mode 100644 test/scion_tests/parallel+interrupt/test27_test.exs create mode 100644 test/scion_tests/parallel+interrupt/test28_test.exs create mode 100644 test/scion_tests/parallel+interrupt/test29_test.exs create mode 100644 test/scion_tests/parallel+interrupt/test2_test.exs create mode 100644 test/scion_tests/parallel+interrupt/test30_test.exs create mode 100644 test/scion_tests/parallel+interrupt/test31_test.exs create mode 100644 test/scion_tests/parallel+interrupt/test3_test.exs create mode 100644 test/scion_tests/parallel+interrupt/test4_test.exs create mode 100644 test/scion_tests/parallel+interrupt/test5_test.exs create mode 100644 test/scion_tests/parallel+interrupt/test6_test.exs create mode 100644 test/scion_tests/parallel+interrupt/test7_test.exs create mode 100644 test/scion_tests/parallel+interrupt/test7b_test.exs create mode 100644 test/scion_tests/parallel+interrupt/test8_test.exs create mode 100644 test/scion_tests/parallel+interrupt/test9_test.exs create mode 100644 test/scion_tests/parallel/test0_test.exs create mode 100644 test/scion_tests/parallel/test1_test.exs create mode 100644 test/scion_tests/parallel/test2_test.exs create mode 100644 test/scion_tests/parallel/test3_test.exs create mode 100644 test/scion_tests/script-src/script-0-0.js create mode 100644 test/scion_tests/script-src/script-1-0.js create mode 100644 test/scion_tests/script-src/script-1-1.js create mode 100644 test/scion_tests/script-src/script-2-0.js create mode 100644 test/scion_tests/script-src/script-2-1.js create mode 100644 test/scion_tests/script-src/script-2-2.js create mode 100644 test/scion_tests/script-src/script-2-3.js create mode 100644 test/scion_tests/script-src/script-3-0.js create mode 100644 test/scion_tests/script-src/test0_test.exs create mode 100644 test/scion_tests/script-src/test1_test.exs create mode 100644 test/scion_tests/script-src/test2_test.exs create mode 100644 test/scion_tests/script-src/test3_test.exs create mode 100644 test/scion_tests/script/test0_test.exs create mode 100644 test/scion_tests/script/test1_test.exs create mode 100644 test/scion_tests/script/test2_test.exs create mode 100644 test/scion_tests/scxml-prefix-event-name-matching/star0_test.exs create mode 100644 test/scion_tests/scxml-prefix-event-name-matching/test0_test.exs create mode 100644 test/scion_tests/scxml-prefix-event-name-matching/test1_test.exs create mode 100644 test/scion_tests/send-data/send1_test.exs create mode 100644 test/scion_tests/send-idlocation/test0_test.exs create mode 100644 test/scion_tests/send-internal/test0_test.exs create mode 100644 test/scion_tests/targetless-transition/test0_test.exs create mode 100644 test/scion_tests/targetless-transition/test1_test.exs create mode 100644 test/scion_tests/targetless-transition/test2_test.exs create mode 100644 test/scion_tests/targetless-transition/test3_test.exs create mode 100644 test/scxml_tests/mandatory/EvaluationofExecutableContent/test158_test.exs create mode 100644 test/scxml_tests/mandatory/EvaluationofExecutableContent/test159_test.exs create mode 100644 test/scxml_tests/mandatory/SelectingTransitions/test403a_test.exs create mode 100644 test/scxml_tests/mandatory/SelectingTransitions/test403b_test.exs create mode 100644 test/scxml_tests/mandatory/SelectingTransitions/test403c_test.exs create mode 100644 test/scxml_tests/mandatory/SelectingTransitions/test404_test.exs create mode 100644 test/scxml_tests/mandatory/SelectingTransitions/test405_test.exs create mode 100644 test/scxml_tests/mandatory/SelectingTransitions/test406_test.exs create mode 100644 test/scxml_tests/mandatory/SelectingTransitions/test407_test.exs create mode 100644 test/scxml_tests/mandatory/SelectingTransitions/test409_test.exs create mode 100644 test/scxml_tests/mandatory/SelectingTransitions/test411_test.exs create mode 100644 test/scxml_tests/mandatory/SelectingTransitions/test412_test.exs create mode 100644 test/scxml_tests/mandatory/SelectingTransitions/test413_test.exs create mode 100644 test/scxml_tests/mandatory/SelectingTransitions/test416_test.exs create mode 100644 test/scxml_tests/mandatory/SelectingTransitions/test417_test.exs create mode 100644 test/scxml_tests/mandatory/SelectingTransitions/test419_test.exs create mode 100644 test/scxml_tests/mandatory/SelectingTransitions/test421_test.exs create mode 100644 test/scxml_tests/mandatory/SelectingTransitions/test422_test.exs create mode 100644 test/scxml_tests/mandatory/SelectingTransitions/test423_test.exs create mode 100644 test/scxml_tests/mandatory/SelectingTransitions/test503_test.exs create mode 100644 test/scxml_tests/mandatory/SelectingTransitions/test504_test.exs create mode 100644 test/scxml_tests/mandatory/SelectingTransitions/test505_test.exs create mode 100644 test/scxml_tests/mandatory/SelectingTransitions/test506_test.exs create mode 100644 test/scxml_tests/mandatory/SelectingTransitions/test533_test.exs create mode 100644 test/scxml_tests/mandatory/data/test276_test.exs create mode 100644 test/scxml_tests/mandatory/data/test276sub1_test.exs create mode 100644 test/scxml_tests/mandatory/data/test277_test.exs create mode 100644 test/scxml_tests/mandatory/data/test279_test.exs create mode 100644 test/scxml_tests/mandatory/data/test280_test.exs create mode 100644 test/scxml_tests/mandatory/data/test550_test.exs create mode 100644 test/scxml_tests/mandatory/data/test551_test.exs create mode 100644 test/scxml_tests/mandatory/events/test396_test.exs create mode 100644 test/scxml_tests/mandatory/events/test399_test.exs create mode 100644 test/scxml_tests/mandatory/events/test401_test.exs create mode 100644 test/scxml_tests/mandatory/events/test402_test.exs create mode 100644 test/scxml_tests/mandatory/final/test372_test.exs create mode 100644 test/scxml_tests/mandatory/final/test570_test.exs create mode 100644 test/scxml_tests/mandatory/foreach/test150_test.exs create mode 100644 test/scxml_tests/mandatory/foreach/test151_test.exs create mode 100644 test/scxml_tests/mandatory/foreach/test152_test.exs create mode 100644 test/scxml_tests/mandatory/foreach/test153_test.exs create mode 100644 test/scxml_tests/mandatory/foreach/test155_test.exs create mode 100644 test/scxml_tests/mandatory/foreach/test156_test.exs create mode 100644 test/scxml_tests/mandatory/foreach/test525_test.exs create mode 100644 test/scxml_tests/mandatory/history/test387_test.exs create mode 100644 test/scxml_tests/mandatory/history/test388_test.exs create mode 100644 test/scxml_tests/mandatory/history/test579_test.exs create mode 100644 test/scxml_tests/mandatory/history/test580_test.exs create mode 100644 test/scxml_tests/mandatory/if/test147_test.exs create mode 100644 test/scxml_tests/mandatory/if/test148_test.exs create mode 100644 test/scxml_tests/mandatory/if/test149_test.exs create mode 100644 test/scxml_tests/mandatory/onentry/test375_test.exs create mode 100644 test/scxml_tests/mandatory/onentry/test376_test.exs create mode 100644 test/scxml_tests/mandatory/onexit/test377_test.exs create mode 100644 test/scxml_tests/mandatory/onexit/test378_test.exs create mode 100644 test/scxml_tests/mandatory/raise/test144_test.exs create mode 100644 test/scxml_tests/mandatory/scxml/test355_test.exs create mode 100644 test/scxml_tests/mandatory/scxml/test576_test.exs create mode 100644 test/scxml_tests/mandatory/state/test364_test.exs create mode 100644 test/support/sc_case.ex diff --git a/mix.exs b/mix.exs index 50fa76c..0b3e0a8 100644 --- a/mix.exs +++ b/mix.exs @@ -6,6 +6,7 @@ defmodule SC.MixProject do app: :sc, version: "0.1.0", elixir: "~> 1.18", + elixirc_paths: elixirc_paths(Mix.env()), start_permanent: Mix.env() == :prod, deps: deps() ] @@ -18,6 +19,9 @@ defmodule SC.MixProject do ] end + defp elixirc_paths(:test), do: ["test/support", "lib"] + defp elixirc_paths(_), do: ["lib"] + # Run "mix help deps" to learn about dependencies. defp deps do [ diff --git a/test/scion_tests/actionSend/send1_test.exs b/test/scion_tests/actionSend/send1_test.exs new file mode 100644 index 0000000..1ce4b2c --- /dev/null +++ b/test/scion_tests/actionSend/send1_test.exs @@ -0,0 +1,47 @@ +defmodule SCIONTest.ActionSend.Send1Test do + use SC.Case + @tag :scion + @tag spec: "action_send" + test "send1" do + xml = """ + + + + + + + + + + + + + + + + + + + """ + + test_scxml(xml, "", ["a"], [{%{"name" => "t"}, ["c"]}]) + end +end diff --git a/test/scion_tests/actionSend/send2_test.exs b/test/scion_tests/actionSend/send2_test.exs new file mode 100644 index 0000000..a353cad --- /dev/null +++ b/test/scion_tests/actionSend/send2_test.exs @@ -0,0 +1,50 @@ +defmodule SCIONTest.ActionSend.Send2Test do + use SC.Case + @tag :scion + @tag spec: "action_send" + test "send2" do + xml = """ + + + + + + + + + + + + + + + + + + + + + + """ + + test_scxml(xml, "", ["a"], [{%{"name" => "t"}, ["c"]}]) + end +end diff --git a/test/scion_tests/actionSend/send3_test.exs b/test/scion_tests/actionSend/send3_test.exs new file mode 100644 index 0000000..9840826 --- /dev/null +++ b/test/scion_tests/actionSend/send3_test.exs @@ -0,0 +1,50 @@ +defmodule SCIONTest.ActionSend.Send3Test do + use SC.Case + @tag :scion + @tag spec: "action_send" + test "send3" do + xml = """ + + + + + + + + + + + + + + + + + + + + + + """ + + test_scxml(xml, "", ["a"], [{%{"name" => "t"}, ["c"]}]) + end +end diff --git a/test/scion_tests/actionSend/send4_test.exs b/test/scion_tests/actionSend/send4_test.exs new file mode 100644 index 0000000..25f2da3 --- /dev/null +++ b/test/scion_tests/actionSend/send4_test.exs @@ -0,0 +1,68 @@ +defmodule SCIONTest.ActionSend.Send4Test do + use SC.Case + @tag :scion + @tag spec: "action_send" + test "send4" do + xml = """ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + """ + + test_scxml(xml, "", ["a"], [{%{"name" => "t"}, ["f1"]}]) + end +end diff --git a/test/scion_tests/actionSend/send4b_test.exs b/test/scion_tests/actionSend/send4b_test.exs new file mode 100644 index 0000000..5e4dcab --- /dev/null +++ b/test/scion_tests/actionSend/send4b_test.exs @@ -0,0 +1,50 @@ +defmodule SCIONTest.ActionSend.Send4bTest do + use SC.Case + @tag :scion + @tag spec: "action_send" + test "send4b" do + xml = """ + + + + + + + + + + + + + + + + + + + + + + """ + + test_scxml(xml, "", ["a"], [{%{"name" => "t"}, ["c"]}]) + end +end diff --git a/test/scion_tests/actionSend/send7_test.exs b/test/scion_tests/actionSend/send7_test.exs new file mode 100644 index 0000000..ebf8f0d --- /dev/null +++ b/test/scion_tests/actionSend/send7_test.exs @@ -0,0 +1,61 @@ +defmodule SCIONTest.ActionSend.Send7Test do + use SC.Case + @tag :scion + @tag spec: "action_send" + test "send7" do + xml = """ + + + + + + + + + + + + + + + + + + + + + + + + + """ + + test_scxml(xml, "", ["a"], [{%{"name" => "t"}, ["b3"]}]) + end +end diff --git a/test/scion_tests/actionSend/send7b_test.exs b/test/scion_tests/actionSend/send7b_test.exs new file mode 100644 index 0000000..43c08e5 --- /dev/null +++ b/test/scion_tests/actionSend/send7b_test.exs @@ -0,0 +1,51 @@ +defmodule SCIONTest.ActionSend.Send7bTest do + use SC.Case + @tag :scion + @tag spec: "action_send" + test "send7b" do + xml = """ + + + + + + + + + + + + + + + + + + + + + + + """ + + test_scxml(xml, "", ["a"], [{%{"name" => "t"}, ["b2"]}]) + end +end diff --git a/test/scion_tests/actionSend/send8_test.exs b/test/scion_tests/actionSend/send8_test.exs new file mode 100644 index 0000000..74496d8 --- /dev/null +++ b/test/scion_tests/actionSend/send8_test.exs @@ -0,0 +1,58 @@ +defmodule SCIONTest.ActionSend.Send8Test do + use SC.Case + @tag :scion + @tag spec: "action_send" + test "send8" do + xml = """ + + + + + + + + + + + + + + + + + + + + + + + + + """ + + test_scxml(xml, "", ["a"], [{%{"name" => "t"}, ["b3"]}]) + end +end diff --git a/test/scion_tests/actionSend/send8b_test.exs b/test/scion_tests/actionSend/send8b_test.exs new file mode 100644 index 0000000..c0eae42 --- /dev/null +++ b/test/scion_tests/actionSend/send8b_test.exs @@ -0,0 +1,51 @@ +defmodule SCIONTest.ActionSend.Send8bTest do + use SC.Case + @tag :scion + @tag spec: "action_send" + test "send8b" do + xml = """ + + + + + + + + + + + + + + + + + + + + + + + """ + + test_scxml(xml, "", ["a"], [{%{"name" => "t"}, ["b2"]}]) + end +end diff --git a/test/scion_tests/actionSend/send9_test.exs b/test/scion_tests/actionSend/send9_test.exs new file mode 100644 index 0000000..2e1e57b --- /dev/null +++ b/test/scion_tests/actionSend/send9_test.exs @@ -0,0 +1,63 @@ +defmodule SCIONTest.ActionSend.Send9Test do + use SC.Case + @tag :scion + @tag spec: "action_send" + test "send9" do + xml = """ + + + + + + + + + + + + + + + + + + + + + + + + + + + + """ + + test_scxml(xml, "", ["a"], [{%{"name" => "t"}, ["b3"]}]) + end +end diff --git a/test/scion_tests/assign-current-small-step/test0_test.exs b/test/scion_tests/assign-current-small-step/test0_test.exs new file mode 100644 index 0000000..09c5c69 --- /dev/null +++ b/test/scion_tests/assign-current-small-step/test0_test.exs @@ -0,0 +1,67 @@ +defmodule SCIONTest.AssignCurrentSmallStep.Test0Test do + use SC.Case + @tag :scion + @tag spec: "assign_current_small_step" + test "test0" do + xml = """ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + """ + + test_scxml(xml, "", ["a"], [{%{"name" => "t"}, ["c"]}]) + end +end diff --git a/test/scion_tests/assign-current-small-step/test1_test.exs b/test/scion_tests/assign-current-small-step/test1_test.exs new file mode 100644 index 0000000..96d0e3b --- /dev/null +++ b/test/scion_tests/assign-current-small-step/test1_test.exs @@ -0,0 +1,55 @@ +defmodule SCIONTest.AssignCurrentSmallStep.Test1Test do + use SC.Case + @tag :scion + @tag spec: "assign_current_small_step" + test "test1" do + xml = """ + + + + + + + + + + + + + + + + + + + + + + + + + + """ + + test_scxml(xml, "", ["a"], [{%{"name" => "t"}, ["c"]}]) + end +end diff --git a/test/scion_tests/assign-current-small-step/test2_test.exs b/test/scion_tests/assign-current-small-step/test2_test.exs new file mode 100644 index 0000000..bf4fa28 --- /dev/null +++ b/test/scion_tests/assign-current-small-step/test2_test.exs @@ -0,0 +1,75 @@ +defmodule SCIONTest.AssignCurrentSmallStep.Test2Test do + use SC.Case + @tag :scion + @tag spec: "assign_current_small_step" + test "test2" do + xml = """ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + """ + + test_scxml(xml, "", ["a"], [{%{"name" => "t"}, ["e"]}]) + end +end diff --git a/test/scion_tests/assign-current-small-step/test3_test.exs b/test/scion_tests/assign-current-small-step/test3_test.exs new file mode 100644 index 0000000..c4c337f --- /dev/null +++ b/test/scion_tests/assign-current-small-step/test3_test.exs @@ -0,0 +1,83 @@ +defmodule SCIONTest.AssignCurrentSmallStep.Test3Test do + use SC.Case + @tag :scion + @tag spec: "assign_current_small_step" + test "test3" do + xml = """ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + """ + + test_scxml(xml, "", ["a"], [ + {%{"name" => "t1"}, ["b1", "c1"]}, + {%{"name" => "t2"}, ["b2", "c2"]}, + {%{"name" => "t3"}, ["d"]} + ]) + end +end diff --git a/test/scion_tests/assign-current-small-step/test4_test.exs b/test/scion_tests/assign-current-small-step/test4_test.exs new file mode 100644 index 0000000..cf685d7 --- /dev/null +++ b/test/scion_tests/assign-current-small-step/test4_test.exs @@ -0,0 +1,73 @@ +defmodule SCIONTest.AssignCurrentSmallStep.Test4Test do + use SC.Case + @tag :scion + @tag spec: "assign_current_small_step" + test "test4" do + xml = """ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + """ + + test_scxml(xml, "", ["a"], [{%{"name" => "t"}, ["c"]}]) + end +end diff --git a/test/scion_tests/assign/assign_invalid_test.exs b/test/scion_tests/assign/assign_invalid_test.exs new file mode 100644 index 0000000..2927e44 --- /dev/null +++ b/test/scion_tests/assign/assign_invalid_test.exs @@ -0,0 +1,47 @@ +defmodule SCIONTest.Assign.AssignInvalidTest do + use SC.Case + @tag :scion + @tag spec: "assign" + test "assign_invalid" do + xml = """ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + """ + + test_scxml(xml, "", ["pass"], []) + end +end diff --git a/test/scion_tests/assign/assign_obj_literal_test.exs b/test/scion_tests/assign/assign_obj_literal_test.exs new file mode 100644 index 0000000..ee21bd7 --- /dev/null +++ b/test/scion_tests/assign/assign_obj_literal_test.exs @@ -0,0 +1,46 @@ +defmodule SCIONTest.Assign.AssignObjLiteralTest do + use SC.Case + @tag :scion + @tag spec: "assign" + test "assign_obj_literal" do + xml = """ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + """ + + test_scxml(xml, "", ["s1"], [{%{"name" => "pass"}, ["pass"]}]) + end +end diff --git a/test/scion_tests/atom3-basic-tests/m0_test.exs b/test/scion_tests/atom3-basic-tests/m0_test.exs new file mode 100644 index 0000000..5f072da --- /dev/null +++ b/test/scion_tests/atom3-basic-tests/m0_test.exs @@ -0,0 +1,29 @@ +defmodule SCIONTest.Atom3BasicTests.M0Test do + use SC.Case + @tag :scion + @tag spec: "atom3_basic_tests" + test "m0" do + xml = """ + + + + + + + + + + + + + + + + + """ + + test_scxml(xml, "", ["A"], [{%{"name" => "e1"}, ["B"]}, {%{"name" => "e2"}, ["A"]}]) + end +end diff --git a/test/scion_tests/atom3-basic-tests/m1_test.exs b/test/scion_tests/atom3-basic-tests/m1_test.exs new file mode 100644 index 0000000..f55199a --- /dev/null +++ b/test/scion_tests/atom3-basic-tests/m1_test.exs @@ -0,0 +1,31 @@ +defmodule SCIONTest.Atom3BasicTests.M1Test do + use SC.Case + @tag :scion + @tag spec: "atom3_basic_tests" + test "m1" do + xml = """ + + + + + + + + + + + + + + + + + + + """ + + test_scxml(xml, "", ["A"], [{%{"name" => "e1"}, ["B"]}, {%{"name" => "e2"}, ["A"]}]) + end +end diff --git a/test/scion_tests/atom3-basic-tests/m2_test.exs b/test/scion_tests/atom3-basic-tests/m2_test.exs new file mode 100644 index 0000000..8428537 --- /dev/null +++ b/test/scion_tests/atom3-basic-tests/m2_test.exs @@ -0,0 +1,36 @@ +defmodule SCIONTest.Atom3BasicTests.M2Test do + use SC.Case + @tag :scion + @tag spec: "atom3_basic_tests" + test "m2" do + xml = """ + + + + + + + + + + + + + + + + + + + + + + + + """ + + test_scxml(xml, "", ["A"], [{%{"name" => "e1"}, ["B"]}, {%{"name" => "e2"}, ["A"]}]) + end +end diff --git a/test/scion_tests/atom3-basic-tests/m3_test.exs b/test/scion_tests/atom3-basic-tests/m3_test.exs new file mode 100644 index 0000000..05c980d --- /dev/null +++ b/test/scion_tests/atom3-basic-tests/m3_test.exs @@ -0,0 +1,50 @@ +defmodule SCIONTest.Atom3BasicTests.M3Test do + use SC.Case + @tag :scion + @tag spec: "atom3_basic_tests" + test "m3" do + xml = """ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + """ + + test_scxml(xml, "", ["A"], [ + {%{"name" => "e1"}, ["B"]}, + {%{"name" => "e2"}, ["A"]}, + {%{"name" => "e1"}, ["B"]}, + {%{"name" => "e1"}, ["C"]} + ]) + end +end diff --git a/test/scion_tests/basic/basic0_test.exs b/test/scion_tests/basic/basic0_test.exs new file mode 100644 index 0000000..42917bf --- /dev/null +++ b/test/scion_tests/basic/basic0_test.exs @@ -0,0 +1,36 @@ +defmodule SCIONTest.Basic.Basic0Test do + use SC.Case + @tag :scion + @tag spec: "basic" + test "basic0" do + xml = """ + + + + + + + + """ + + test_scxml(xml, "", ["a"], []) + end +end diff --git a/test/scion_tests/basic/basic1_test.exs b/test/scion_tests/basic/basic1_test.exs new file mode 100644 index 0000000..8a7c892 --- /dev/null +++ b/test/scion_tests/basic/basic1_test.exs @@ -0,0 +1,39 @@ +defmodule SCIONTest.Basic.Basic1Test do + use SC.Case + @tag :scion + @tag spec: "basic" + test "basic1" do + xml = """ + + + + + + + + + + + + """ + + test_scxml(xml, "", ["a"], [{%{"name" => "t"}, ["b"]}]) + end +end diff --git a/test/scion_tests/basic/basic2_test.exs b/test/scion_tests/basic/basic2_test.exs new file mode 100644 index 0000000..7c56dc9 --- /dev/null +++ b/test/scion_tests/basic/basic2_test.exs @@ -0,0 +1,42 @@ +defmodule SCIONTest.Basic.Basic2Test do + use SC.Case + @tag :scion + @tag spec: "basic" + test "basic2" do + xml = """ + + + + + + + + + + + + + + + + """ + + test_scxml(xml, "", ["a"], [{%{"name" => "t"}, ["b"]}, {%{"name" => "t2"}, ["c"]}]) + end +end diff --git a/test/scion_tests/cond-js/TestConditionalTransition_test.exs b/test/scion_tests/cond-js/TestConditionalTransition_test.exs new file mode 100644 index 0000000..9ebb159 --- /dev/null +++ b/test/scion_tests/cond-js/TestConditionalTransition_test.exs @@ -0,0 +1,115 @@ +defmodule SCIONTest.CondJs.TestConditionalTransitionTest do + use SC.Case + @tag :scion + @tag spec: "cond_js" + test "TestConditionalTransition" do + xml = """ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + """ + + test_scxml(xml, "", ["b"], [ + {%{"name" => "t1"}, ["d1"]}, + {%{"name" => "t2"}, ["e1"]}, + {%{"name" => "t3"}, ["f2"]}, + {%{"name" => "t4"}, ["h"]}, + {%{"name" => "t5"}, ["i"]}, + {%{"name" => "t5"}, ["last"]} + ]) + end +end diff --git a/test/scion_tests/cond-js/test0_test.exs b/test/scion_tests/cond-js/test0_test.exs new file mode 100644 index 0000000..dc3ddbb --- /dev/null +++ b/test/scion_tests/cond-js/test0_test.exs @@ -0,0 +1,39 @@ +defmodule SCIONTest.CondJs.Test0Test do + use SC.Case + @tag :scion + @tag spec: "cond_js" + test "test0" do + xml = """ + + + + + + + + + + + + """ + + test_scxml(xml, "", ["a"], [{%{"name" => "t"}, ["b"]}]) + end +end diff --git a/test/scion_tests/cond-js/test1_test.exs b/test/scion_tests/cond-js/test1_test.exs new file mode 100644 index 0000000..d2c453d --- /dev/null +++ b/test/scion_tests/cond-js/test1_test.exs @@ -0,0 +1,42 @@ +defmodule SCIONTest.CondJs.Test1Test do + use SC.Case + @tag :scion + @tag spec: "cond_js" + test "test1" do + xml = """ + + + + + + + + + + + + + + + """ + + test_scxml(xml, "", ["a"], [{%{"name" => "t"}, ["b"]}]) + end +end diff --git a/test/scion_tests/cond-js/test2_test.exs b/test/scion_tests/cond-js/test2_test.exs new file mode 100644 index 0000000..f2b0d91 --- /dev/null +++ b/test/scion_tests/cond-js/test2_test.exs @@ -0,0 +1,39 @@ +defmodule SCIONTest.CondJs.Test2Test do + use SC.Case + @tag :scion + @tag spec: "cond_js" + test "test2" do + xml = """ + + + + + + + + + + + + """ + + test_scxml(xml, "", ["a"], [{%{"name" => "t"}, ["b"]}]) + end +end diff --git a/test/scion_tests/data/data_invalid_test.exs b/test/scion_tests/data/data_invalid_test.exs new file mode 100644 index 0000000..5403c2e --- /dev/null +++ b/test/scion_tests/data/data_invalid_test.exs @@ -0,0 +1,46 @@ +defmodule SCIONTest.Data.DataInvalidTest do + use SC.Case + @tag :scion + @tag spec: "data" + test "data_invalid" do + xml = """ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + """ + + test_scxml(xml, "", ["pass"], []) + end +end diff --git a/test/scion_tests/data/data_obj_literal_test.exs b/test/scion_tests/data/data_obj_literal_test.exs new file mode 100644 index 0000000..df9d223 --- /dev/null +++ b/test/scion_tests/data/data_obj_literal_test.exs @@ -0,0 +1,45 @@ +defmodule SCIONTest.Data.DataObjLiteralTest do + use SC.Case + @tag :scion + @tag spec: "data" + test "data_obj_literal" do + xml = """ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + """ + + test_scxml(xml, "", ["s1"], [{%{"name" => "pass"}, ["pass"]}]) + end +end diff --git a/test/scion_tests/default-initial-state/initial1_test.exs b/test/scion_tests/default-initial-state/initial1_test.exs new file mode 100644 index 0000000..ccb09e3 --- /dev/null +++ b/test/scion_tests/default-initial-state/initial1_test.exs @@ -0,0 +1,40 @@ +defmodule SCIONTest.DefaultInitialState.Initial1Test do + use SC.Case + @tag :scion + @tag spec: "default_initial_state" + test "initial1" do + xml = """ + + + + + + + + + + + + + """ + + test_scxml(xml, "", ["a"], [{%{"name" => "t"}, ["b"]}]) + end +end diff --git a/test/scion_tests/default-initial-state/initial2_test.exs b/test/scion_tests/default-initial-state/initial2_test.exs new file mode 100644 index 0000000..1fc1ddb --- /dev/null +++ b/test/scion_tests/default-initial-state/initial2_test.exs @@ -0,0 +1,40 @@ +defmodule SCIONTest.DefaultInitialState.Initial2Test do + use SC.Case + @tag :scion + @tag spec: "default_initial_state" + test "initial2" do + xml = """ + + + + + + + + + + + + """ + + test_scxml(xml, "", ["a"], [{%{"name" => "t"}, ["b"]}]) + end +end diff --git a/test/scion_tests/delayedSend/send1_test.exs b/test/scion_tests/delayedSend/send1_test.exs new file mode 100644 index 0000000..b2472c6 --- /dev/null +++ b/test/scion_tests/delayedSend/send1_test.exs @@ -0,0 +1,49 @@ +defmodule SCIONTest.DelayedSend.Send1Test do + use SC.Case + @tag :scion + @tag spec: "delayed_send" + test "send1" do + xml = """ + + + + + + + + + + + + + + + + + + + + + + """ + + test_scxml(xml, "", ["a"], [{%{"name" => "t1"}, ["b"]}, {%{"name" => "t2"}, ["d"]}]) + end +end diff --git a/test/scion_tests/delayedSend/send2_test.exs b/test/scion_tests/delayedSend/send2_test.exs new file mode 100644 index 0000000..7044c85 --- /dev/null +++ b/test/scion_tests/delayedSend/send2_test.exs @@ -0,0 +1,52 @@ +defmodule SCIONTest.DelayedSend.Send2Test do + use SC.Case + @tag :scion + @tag spec: "delayed_send" + test "send2" do + xml = """ + + + + + + + + + + + + + + + + + + + + + + + + + """ + + test_scxml(xml, "", ["a"], [{%{"name" => "t1"}, ["b"]}, {%{"name" => "t2"}, ["d"]}]) + end +end diff --git a/test/scion_tests/delayedSend/send3_test.exs b/test/scion_tests/delayedSend/send3_test.exs new file mode 100644 index 0000000..31753a0 --- /dev/null +++ b/test/scion_tests/delayedSend/send3_test.exs @@ -0,0 +1,52 @@ +defmodule SCIONTest.DelayedSend.Send3Test do + use SC.Case + @tag :scion + @tag spec: "delayed_send" + test "send3" do + xml = """ + + + + + + + + + + + + + + + + + + + + + + + + + """ + + test_scxml(xml, "", ["a"], [{%{"name" => "t1"}, ["b"]}, {%{"name" => "t2"}, ["d"]}]) + end +end diff --git a/test/scion_tests/documentOrder/documentOrder0_test.exs b/test/scion_tests/documentOrder/documentOrder0_test.exs new file mode 100644 index 0000000..d40deef --- /dev/null +++ b/test/scion_tests/documentOrder/documentOrder0_test.exs @@ -0,0 +1,41 @@ +defmodule SCIONTest.DocumentOrder.DocumentOrder0Test do + use SC.Case + @tag :scion + @tag spec: "document_order" + test "documentOrder0" do + xml = """ + + + + + + + + + + + + + + """ + + test_scxml(xml, "", ["a"], [{%{"name" => "t"}, ["b"]}]) + end +end diff --git a/test/scion_tests/error/error_test.exs b/test/scion_tests/error/error_test.exs new file mode 100644 index 0000000..a333b1d --- /dev/null +++ b/test/scion_tests/error/error_test.exs @@ -0,0 +1,92 @@ +defmodule SCIONTest.Error.ErrorTest do + use SC.Case + @tag :scion + @tag spec: "error" + test "error" do + xml = """ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + """ + + test_scxml(xml, "", ["s1"], [{%{"name" => "e1"}, ["pass"]}]) + end +end diff --git a/test/scion_tests/foreach/test1_test.exs b/test/scion_tests/foreach/test1_test.exs new file mode 100644 index 0000000..383b338 --- /dev/null +++ b/test/scion_tests/foreach/test1_test.exs @@ -0,0 +1,61 @@ +defmodule SCIONTest.Foreach.Test1Test do + use SC.Case + @tag :scion + @tag spec: "foreach" + test "test1" do + xml = """ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + """ + + test_scxml(xml, "", ["a"], [{%{"name" => "t"}, ["c"]}]) + end +end diff --git a/test/scion_tests/hierarchy+documentOrder/test0_test.exs b/test/scion_tests/hierarchy+documentOrder/test0_test.exs new file mode 100644 index 0000000..bf69731 --- /dev/null +++ b/test/scion_tests/hierarchy+documentOrder/test0_test.exs @@ -0,0 +1,50 @@ +defmodule :"Elixir.Test.StateChart.Scion.Hierarchy+documentOrder.Test0" do + use SC.Case + @tag :scion + @tag spec: "hierarchy+document_order" + test "test0" do + xml = """ + + + + + + + + + + + + + + + + + + + + + + + """ + + test_scxml(xml, "", ["a1"], [{%{"name" => "t"}, ["a2"]}]) + end +end diff --git a/test/scion_tests/hierarchy+documentOrder/test1_test.exs b/test/scion_tests/hierarchy+documentOrder/test1_test.exs new file mode 100644 index 0000000..efb778d --- /dev/null +++ b/test/scion_tests/hierarchy+documentOrder/test1_test.exs @@ -0,0 +1,50 @@ +defmodule :"Elixir.Test.StateChart.Scion.Hierarchy+documentOrder.Test1" do + use SC.Case + @tag :scion + @tag spec: "hierarchy+document_order" + test "test1" do + xml = """ + + + + + + + + + + + + + + + + + + + + + + + """ + + test_scxml(xml, "", ["a1"], [{%{"name" => "t"}, ["b"]}]) + end +end diff --git a/test/scion_tests/hierarchy/hier0_test.exs b/test/scion_tests/hierarchy/hier0_test.exs new file mode 100644 index 0000000..b829363 --- /dev/null +++ b/test/scion_tests/hierarchy/hier0_test.exs @@ -0,0 +1,43 @@ +defmodule SCIONTest.Hierarchy.Hier0Test do + use SC.Case + @tag :scion + @tag spec: "hierarchy" + test "hier0" do + xml = """ + + + + + + + + + + + + + + + + """ + + test_scxml(xml, "", ["a1"], [{%{"name" => "t"}, ["a2"]}]) + end +end diff --git a/test/scion_tests/hierarchy/hier1_test.exs b/test/scion_tests/hierarchy/hier1_test.exs new file mode 100644 index 0000000..8ded8a3 --- /dev/null +++ b/test/scion_tests/hierarchy/hier1_test.exs @@ -0,0 +1,47 @@ +defmodule SCIONTest.Hierarchy.Hier1Test do + use SC.Case + @tag :scion + @tag spec: "hierarchy" + test "hier1" do + xml = """ + + + + + + + + + + + + + + + + + + + + """ + + test_scxml(xml, "", ["a1"], [{%{"name" => "t"}, ["a2"]}]) + end +end diff --git a/test/scion_tests/hierarchy/hier2_test.exs b/test/scion_tests/hierarchy/hier2_test.exs new file mode 100644 index 0000000..2721ecf --- /dev/null +++ b/test/scion_tests/hierarchy/hier2_test.exs @@ -0,0 +1,47 @@ +defmodule SCIONTest.Hierarchy.Hier2Test do + use SC.Case + @tag :scion + @tag spec: "hierarchy" + test "hier2" do + xml = """ + + + + + + + + + + + + + + + + + + + + """ + + test_scxml(xml, "", ["a1"], [{%{"name" => "t"}, ["b"]}]) + end +end diff --git a/test/scion_tests/history/history0_test.exs b/test/scion_tests/history/history0_test.exs new file mode 100644 index 0000000..84b6e3c --- /dev/null +++ b/test/scion_tests/history/history0_test.exs @@ -0,0 +1,60 @@ +defmodule SCIONTest.History.History0Test do + use SC.Case + @tag :scion + @tag spec: "history" + test "history0" do + xml = """ + + + + + + + + + + + + + + + + + + + + + + + + + + + """ + + test_scxml(xml, "", ["a"], [ + {%{"name" => "t1"}, ["b2"]}, + {%{"name" => "t2"}, ["b3"]}, + {%{"name" => "t3"}, ["a"]}, + {%{"name" => "t1"}, ["b3"]} + ]) + end +end diff --git a/test/scion_tests/history/history1_test.exs b/test/scion_tests/history/history1_test.exs new file mode 100644 index 0000000..9895c4f --- /dev/null +++ b/test/scion_tests/history/history1_test.exs @@ -0,0 +1,64 @@ +defmodule SCIONTest.History.History1Test do + use SC.Case + @tag :scion + @tag spec: "history" + test "history1" do + xml = """ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + """ + + test_scxml(xml, "", ["a"], [ + {%{"name" => "t1"}, ["b1.2"]}, + {%{"name" => "t2"}, ["b1.3"]}, + {%{"name" => "t3"}, ["a"]}, + {%{"name" => "t1"}, ["b1.3"]} + ]) + end +end diff --git a/test/scion_tests/history/history2_test.exs b/test/scion_tests/history/history2_test.exs new file mode 100644 index 0000000..27946fa --- /dev/null +++ b/test/scion_tests/history/history2_test.exs @@ -0,0 +1,64 @@ +defmodule SCIONTest.History.History2Test do + use SC.Case + @tag :scion + @tag spec: "history" + test "history2" do + xml = """ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + """ + + test_scxml(xml, "", ["a"], [ + {%{"name" => "t1"}, ["b1.2"]}, + {%{"name" => "t2"}, ["b1.3"]}, + {%{"name" => "t3"}, ["a"]}, + {%{"name" => "t1"}, ["b1.1"]} + ]) + end +end diff --git a/test/scion_tests/history/history3_test.exs b/test/scion_tests/history/history3_test.exs new file mode 100644 index 0000000..d048ec4 --- /dev/null +++ b/test/scion_tests/history/history3_test.exs @@ -0,0 +1,68 @@ +defmodule SCIONTest.History.History3Test do + use SC.Case + @tag :scion + @tag spec: "history" + test "history3" do + xml = """ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + """ + + test_scxml(xml, "", ["a"], [ + {%{"name" => "t1"}, ["b1", "c1"]}, + {%{"name" => "t2"}, ["b2", "c2"]}, + {%{"name" => "t3"}, ["a"]}, + {%{"name" => "t4"}, ["b2", "c2"]} + ]) + end +end diff --git a/test/scion_tests/history/history4_test.exs b/test/scion_tests/history/history4_test.exs new file mode 100644 index 0000000..46623d9 --- /dev/null +++ b/test/scion_tests/history/history4_test.exs @@ -0,0 +1,114 @@ +defmodule SCIONTest.History.History4Test do + use SC.Case + @tag :scion + @tag spec: "history" + test "history4" do + xml = """ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + """ + + test_scxml(xml, "", ["a"], [ + {%{"name" => "t1"}, ["b1.1", "c1.1"]}, + {%{"name" => "t2"}, ["b1.2", "c1.2"]}, + {%{"name" => "t3"}, ["b2.1", "c2.1"]}, + {%{"name" => "t4"}, ["b2.2", "c2.2"]}, + {%{"name" => "t5"}, ["a"]}, + {%{"name" => "t6"}, ["b2.2", "c2.1"]}, + {%{"name" => "t7"}, ["b2.2", "c2.2"]}, + {%{"name" => "t8"}, ["a"]}, + {%{"name" => "t9"}, ["b2.2", "c2.2"]} + ]) + end +end diff --git a/test/scion_tests/history/history4b_test.exs b/test/scion_tests/history/history4b_test.exs new file mode 100644 index 0000000..a7be720 --- /dev/null +++ b/test/scion_tests/history/history4b_test.exs @@ -0,0 +1,114 @@ +defmodule SCIONTest.History.History4bTest do + use SC.Case + @tag :scion + @tag spec: "history" + test "history4b" do + xml = """ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + """ + + test_scxml(xml, "", ["a"], [ + {%{"name" => "t1"}, ["b1.1", "c1.1"]}, + {%{"name" => "t2"}, ["b1.2", "c1.2"]}, + {%{"name" => "t3"}, ["b2.1", "c2.1"]}, + {%{"name" => "t4"}, ["b2.2", "c2.2"]}, + {%{"name" => "t5"}, ["a"]}, + {%{"name" => "t6"}, ["b2.2", "c2.1"]}, + {%{"name" => "t7"}, ["b2.2", "c2.2"]}, + {%{"name" => "t8"}, ["a"]}, + {%{"name" => "t9"}, ["b2.2", "c2.2"]} + ]) + end +end diff --git a/test/scion_tests/history/history5_test.exs b/test/scion_tests/history/history5_test.exs new file mode 100644 index 0000000..b0b1c7c --- /dev/null +++ b/test/scion_tests/history/history5_test.exs @@ -0,0 +1,87 @@ +defmodule SCIONTest.History.History5Test do + use SC.Case + @tag :scion + @tag spec: "history" + test "history5" do + xml = """ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + """ + + test_scxml(xml, "", ["i1", "j", "h", "g", "f1", "k"], [ + {%{"name" => "t1"}, ["i2", "j", "h", "g", "f2", "k"]}, + {%{"name" => "t2"}, ["l"]}, + {%{"name" => "t3"}, ["i2", "j", "h", "g", "f2", "k"]} + ]) + end +end diff --git a/test/scion_tests/history/history6_test.exs b/test/scion_tests/history/history6_test.exs new file mode 100644 index 0000000..7189ef8 --- /dev/null +++ b/test/scion_tests/history/history6_test.exs @@ -0,0 +1,91 @@ +defmodule SCIONTest.History.History6Test do + use SC.Case + @tag :scion + @tag spec: "history" + test "history6" do + xml = """ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + """ + + test_scxml(xml, "", ["a"], [ + {%{"name" => "t1"}, ["b2"]}, + {%{"name" => "t2"}, ["b3"]}, + {%{"name" => "t3"}, ["a"]}, + {%{"name" => "t1"}, ["b3"]}, + {%{"name" => "t4"}, ["success"]} + ]) + end +end diff --git a/test/scion_tests/if-else/test0_test.exs b/test/scion_tests/if-else/test0_test.exs new file mode 100644 index 0000000..0792ec6 --- /dev/null +++ b/test/scion_tests/if-else/test0_test.exs @@ -0,0 +1,117 @@ +defmodule SCIONTest.IfElse.Test0Test do + use SC.Case + @tag :scion + @tag spec: "if_else" + test "test0" do + xml = """ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + """ + + test_scxml(xml, "", ["a"], [{%{"name" => "t"}, ["c"]}]) + end +end diff --git a/test/scion_tests/in/TestInPredicate_test.exs b/test/scion_tests/in/TestInPredicate_test.exs new file mode 100644 index 0000000..8325eaf --- /dev/null +++ b/test/scion_tests/in/TestInPredicate_test.exs @@ -0,0 +1,129 @@ +defmodule SCIONTest.In.TestInPredicateTest do + use SC.Case + @tag :scion + @tag spec: "in" + test "TestInPredicate" do + xml = """ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + """ + + test_scxml(xml, "", ["a1", "a2"], [ + {%{"name" => "t1"}, ["b1", "a2"]}, + {%{"name" => "t2"}, ["c1", "a2"]}, + {%{"name" => "t3"}, ["d1", "a2"]}, + {%{"name" => "t4"}, ["e1", "a2"]}, + {%{"name" => "t5"}, ["f1", "a2"]}, + {%{"name" => "t6"}, ["g1", "b2"]}, + {%{"name" => "t7"}, ["h1", "d2"]}, + {%{"name" => "t8"}, ["i1", "d2"]}, + {%{"name" => "t9"}, ["j1", "e2"]}, + {%{"name" => "t10"}, ["k1", "e2"]} + ]) + end +end diff --git a/test/scion_tests/internal-transitions/test0.scxml.bak b/test/scion_tests/internal-transitions/test0.scxml.bak new file mode 100644 index 0000000..f9a620d --- /dev/null +++ b/test/scion_tests/internal-transitions/test0.scxml.bak @@ -0,0 +1,56 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/test/scion_tests/internal-transitions/test0_test.exs b/test/scion_tests/internal-transitions/test0_test.exs new file mode 100644 index 0000000..a148ad3 --- /dev/null +++ b/test/scion_tests/internal-transitions/test0_test.exs @@ -0,0 +1,67 @@ +defmodule SCIONTest.InternalTransitions.Test0Test do + use SC.Case + @tag :scion + @tag spec: "internal_transitions" + test "test0" do + xml = """ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + """ + + test_scxml(xml, "", ["a1"], [ + {%{"name" => "t1"}, ["a2"]}, + {%{"name" => "t2"}, ["b"]}, + {%{"name" => "t3"}, ["c"]} + ]) + end +end diff --git a/test/scion_tests/internal-transitions/test1_test.exs b/test/scion_tests/internal-transitions/test1_test.exs new file mode 100644 index 0000000..ef6054a --- /dev/null +++ b/test/scion_tests/internal-transitions/test1_test.exs @@ -0,0 +1,103 @@ +defmodule SCIONTest.InternalTransitions.Test1Test do + use SC.Case + @tag :scion + @tag spec: "internal_transitions" + test "test1" do + xml = """ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + """ + + test_scxml(xml, "", ["a1", "b1"], [ + {%{"name" => "t1"}, ["a2", "b1"]}, + {%{"name" => "t2"}, ["c"]}, + {%{"name" => "t3"}, ["d"]} + ]) + end +end diff --git a/test/scion_tests/misc/deep-initial_test.exs b/test/scion_tests/misc/deep-initial_test.exs new file mode 100644 index 0000000..f7c6430 --- /dev/null +++ b/test/scion_tests/misc/deep-initial_test.exs @@ -0,0 +1,29 @@ +defmodule :"Elixir.Test.StateChart.Scion.Misc.Deep-initial" do + use SC.Case + @tag :scion + @tag spec: "misc" + test "deep-initial" do + xml = """ + + + + + + + + + + + + + + + + + + """ + + test_scxml(xml, "", ["s2"], []) + end +end diff --git a/test/scion_tests/more-parallel/test0_test.exs b/test/scion_tests/more-parallel/test0_test.exs new file mode 100644 index 0000000..c927b9a --- /dev/null +++ b/test/scion_tests/more-parallel/test0_test.exs @@ -0,0 +1,41 @@ +defmodule SCIONTest.MoreParallel.Test0Test do + use SC.Case + @tag :scion + @tag spec: "more_parallel" + test "test0" do + xml = """ + + + + + + + + + + + + + + """ + + test_scxml(xml, "", ["a", "b"], [{%{"name" => "t"}, ["a", "b"]}]) + end +end diff --git a/test/scion_tests/more-parallel/test10_test.exs b/test/scion_tests/more-parallel/test10_test.exs new file mode 100644 index 0000000..788b33c --- /dev/null +++ b/test/scion_tests/more-parallel/test10_test.exs @@ -0,0 +1,75 @@ +defmodule SCIONTest.MoreParallel.Test10Test do + use SC.Case + @tag :scion + @tag spec: "more_parallel" + test "test10" do + xml = """ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + """ + + test_scxml(xml, "", ["a", "b"], [ + {%{"name" => "t1"}, ["a", "b"]}, + {%{"name" => "t2"}, ["a", "b"]}, + {%{"name" => "t3"}, ["a", "b"]} + ]) + end +end diff --git a/test/scion_tests/more-parallel/test10b_test.exs b/test/scion_tests/more-parallel/test10b_test.exs new file mode 100644 index 0000000..b93d07b --- /dev/null +++ b/test/scion_tests/more-parallel/test10b_test.exs @@ -0,0 +1,75 @@ +defmodule SCIONTest.MoreParallel.Test10bTest do + use SC.Case + @tag :scion + @tag spec: "more_parallel" + test "test10b" do + xml = """ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + """ + + test_scxml(xml, "", ["a", "b"], [ + {%{"name" => "t1"}, ["a", "b"]}, + {%{"name" => "t2"}, ["c"]}, + {%{"name" => "t3"}, ["d"]} + ]) + end +end diff --git a/test/scion_tests/more-parallel/test1_test.exs b/test/scion_tests/more-parallel/test1_test.exs new file mode 100644 index 0000000..81aa587 --- /dev/null +++ b/test/scion_tests/more-parallel/test1_test.exs @@ -0,0 +1,52 @@ +defmodule SCIONTest.MoreParallel.Test1Test do + use SC.Case + @tag :scion + @tag spec: "more_parallel" + test "test1" do + xml = """ + + + + + + + + + + + + + + + + + + + + + + + + + """ + + test_scxml(xml, "", ["a1", "b1"], [{%{"name" => "t"}, ["a1", "b1"]}]) + end +end diff --git a/test/scion_tests/more-parallel/test2_test.exs b/test/scion_tests/more-parallel/test2_test.exs new file mode 100644 index 0000000..6fd7ac4 --- /dev/null +++ b/test/scion_tests/more-parallel/test2_test.exs @@ -0,0 +1,54 @@ +defmodule SCIONTest.MoreParallel.Test2Test do + use SC.Case + @tag :scion + @tag spec: "more_parallel" + test "test2" do + xml = """ + + + + + + + + + + + + + + + + + + + + + + + + + + + """ + + test_scxml(xml, "", ["a1", "b1"], [{%{"name" => "t"}, ["a1", "b1"]}]) + end +end diff --git a/test/scion_tests/more-parallel/test2b_test.exs b/test/scion_tests/more-parallel/test2b_test.exs new file mode 100644 index 0000000..f85cdce --- /dev/null +++ b/test/scion_tests/more-parallel/test2b_test.exs @@ -0,0 +1,54 @@ +defmodule SCIONTest.MoreParallel.Test2bTest do + use SC.Case + @tag :scion + @tag spec: "more_parallel" + test "test2b" do + xml = """ + + + + + + + + + + + + + + + + + + + + + + + + + + + """ + + test_scxml(xml, "", ["a1", "b1"], [{%{"name" => "t"}, ["a1", "b2"]}]) + end +end diff --git a/test/scion_tests/more-parallel/test3_test.exs b/test/scion_tests/more-parallel/test3_test.exs new file mode 100644 index 0000000..9f5d82d --- /dev/null +++ b/test/scion_tests/more-parallel/test3_test.exs @@ -0,0 +1,54 @@ +defmodule SCIONTest.MoreParallel.Test3Test do + use SC.Case + @tag :scion + @tag spec: "more_parallel" + test "test3" do + xml = """ + + + + + + + + + + + + + + + + + + + + + + + + + + + """ + + test_scxml(xml, "", ["a1", "b1"], [{%{"name" => "t"}, ["a2", "b1"]}]) + end +end diff --git a/test/scion_tests/more-parallel/test3b_test.exs b/test/scion_tests/more-parallel/test3b_test.exs new file mode 100644 index 0000000..d2ebb0e --- /dev/null +++ b/test/scion_tests/more-parallel/test3b_test.exs @@ -0,0 +1,54 @@ +defmodule SCIONTest.MoreParallel.Test3bTest do + use SC.Case + @tag :scion + @tag spec: "more_parallel" + test "test3b" do + xml = """ + + + + + + + + + + + + + + + + + + + + + + + + + + + """ + + test_scxml(xml, "", ["a1", "b1"], [{%{"name" => "t"}, ["a1", "b2"]}]) + end +end diff --git a/test/scion_tests/more-parallel/test4_test.exs b/test/scion_tests/more-parallel/test4_test.exs new file mode 100644 index 0000000..fbb9418 --- /dev/null +++ b/test/scion_tests/more-parallel/test4_test.exs @@ -0,0 +1,54 @@ +defmodule SCIONTest.MoreParallel.Test4Test do + use SC.Case + @tag :scion + @tag spec: "more_parallel" + test "test4" do + xml = """ + + + + + + + + + + + + + + + + + + + + + + + + + + + """ + + test_scxml(xml, "", ["a1", "b1"], [{%{"name" => "t"}, ["a1", "b1"]}]) + end +end diff --git a/test/scion_tests/more-parallel/test5_test.exs b/test/scion_tests/more-parallel/test5_test.exs new file mode 100644 index 0000000..226abd8 --- /dev/null +++ b/test/scion_tests/more-parallel/test5_test.exs @@ -0,0 +1,54 @@ +defmodule SCIONTest.MoreParallel.Test5Test do + use SC.Case + @tag :scion + @tag spec: "more_parallel" + test "test5" do + xml = """ + + + + + + + + + + + + + + + + + + + + + + + + + + + """ + + test_scxml(xml, "", ["a1", "b1"], [{%{"name" => "t"}, ["a2", "b1"]}]) + end +end diff --git a/test/scion_tests/more-parallel/test6_test.exs b/test/scion_tests/more-parallel/test6_test.exs new file mode 100644 index 0000000..791f196 --- /dev/null +++ b/test/scion_tests/more-parallel/test6_test.exs @@ -0,0 +1,66 @@ +defmodule SCIONTest.MoreParallel.Test6Test do + use SC.Case + @tag :scion + @tag spec: "more_parallel" + test "test6" do + xml = """ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + """ + + test_scxml(xml, "", ["a11", "b11"], [{%{"name" => "t"}, ["a22", "b11"]}]) + end +end diff --git a/test/scion_tests/more-parallel/test6b_test.exs b/test/scion_tests/more-parallel/test6b_test.exs new file mode 100644 index 0000000..f52547d --- /dev/null +++ b/test/scion_tests/more-parallel/test6b_test.exs @@ -0,0 +1,66 @@ +defmodule SCIONTest.MoreParallel.Test6bTest do + use SC.Case + @tag :scion + @tag spec: "more_parallel" + test "test6b" do + xml = """ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + """ + + test_scxml(xml, "", ["a11", "b11"], [{%{"name" => "t"}, ["a11", "b12"]}]) + end +end diff --git a/test/scion_tests/more-parallel/test7_test.exs b/test/scion_tests/more-parallel/test7_test.exs new file mode 100644 index 0000000..2ec6a14 --- /dev/null +++ b/test/scion_tests/more-parallel/test7_test.exs @@ -0,0 +1,66 @@ +defmodule SCIONTest.MoreParallel.Test7Test do + use SC.Case + @tag :scion + @tag spec: "more_parallel" + test "test7" do + xml = """ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + """ + + test_scxml(xml, "", ["a11", "b11"], [{%{"name" => "t"}, ["a22", "b11"]}]) + end +end diff --git a/test/scion_tests/more-parallel/test8_test.exs b/test/scion_tests/more-parallel/test8_test.exs new file mode 100644 index 0000000..ba77604 --- /dev/null +++ b/test/scion_tests/more-parallel/test8_test.exs @@ -0,0 +1,63 @@ +defmodule SCIONTest.MoreParallel.Test8Test do + use SC.Case + @tag :scion + @tag spec: "more_parallel" + test "test8" do + xml = """ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + """ + + test_scxml(xml, "", ["x"], [{%{"name" => "t"}, ["a22", "b11"]}]) + end +end diff --git a/test/scion_tests/more-parallel/test9_test.exs b/test/scion_tests/more-parallel/test9_test.exs new file mode 100644 index 0000000..e8877b9 --- /dev/null +++ b/test/scion_tests/more-parallel/test9_test.exs @@ -0,0 +1,63 @@ +defmodule SCIONTest.MoreParallel.Test9Test do + use SC.Case + @tag :scion + @tag spec: "more_parallel" + test "test9" do + xml = """ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + """ + + test_scxml(xml, "", ["x"], [{%{"name" => "t"}, ["a22", "b22"]}]) + end +end diff --git a/test/scion_tests/multiple-events-per-transition/test1_test.exs b/test/scion_tests/multiple-events-per-transition/test1_test.exs new file mode 100644 index 0000000..6ed26d8 --- /dev/null +++ b/test/scion_tests/multiple-events-per-transition/test1_test.exs @@ -0,0 +1,51 @@ +defmodule SCIONTest.MultipleEventsPerTransition.Test1Test do + use SC.Case + @tag :scion + @tag spec: "multiple_events_per_transition" + test "test1" do + xml = """ + + + + + + + + + + + + + + + + + + + + """ + + test_scxml(xml, "", ["a"], [ + {%{"name" => "foo"}, ["b"]}, + {%{"name" => "bar"}, ["c"]}, + {%{"name" => "bat"}, ["d"]} + ]) + end +end diff --git a/test/scion_tests/parallel+interrupt/test0_test.exs b/test/scion_tests/parallel+interrupt/test0_test.exs new file mode 100644 index 0000000..d2f4076 --- /dev/null +++ b/test/scion_tests/parallel+interrupt/test0_test.exs @@ -0,0 +1,52 @@ +defmodule :"Elixir.Test.StateChart.Scion.Parallel+interrupt.Test0" do + use SC.Case + @tag :scion + @tag spec: "parallel+interrupt" + test "test0" do + xml = """ + + + + + + + + + + + + + + + + + + + + + """ + + test_scxml(xml, "", ["c", "d"], [{%{"name" => "t"}, ["a1"]}]) + end +end diff --git a/test/scion_tests/parallel+interrupt/test10_test.exs b/test/scion_tests/parallel+interrupt/test10_test.exs new file mode 100644 index 0000000..02be6a3 --- /dev/null +++ b/test/scion_tests/parallel+interrupt/test10_test.exs @@ -0,0 +1,60 @@ +defmodule :"Elixir.Test.StateChart.Scion.Parallel+interrupt.Test10" do + use SC.Case + @tag :scion + @tag spec: "parallel+interrupt" + test "test10" do + xml = """ + + + + + + + + + + + + + + + + + + + + + + + + + + + + """ + + test_scxml(xml, "", ["b1", "b2"], [{%{"name" => "t"}, ["c1", "c2"]}]) + end +end diff --git a/test/scion_tests/parallel+interrupt/test11_test.exs b/test/scion_tests/parallel+interrupt/test11_test.exs new file mode 100644 index 0000000..ee0d0f8 --- /dev/null +++ b/test/scion_tests/parallel+interrupt/test11_test.exs @@ -0,0 +1,48 @@ +defmodule :"Elixir.Test.StateChart.Scion.Parallel+interrupt.Test11" do + use SC.Case + @tag :scion + @tag spec: "parallel+interrupt" + test "test11" do + xml = """ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + """ + + test_scxml(xml, "", ["b1", "b2"], [{%{"name" => "t"}, ["d"]}]) + end +end diff --git a/test/scion_tests/parallel+interrupt/test12_test.exs b/test/scion_tests/parallel+interrupt/test12_test.exs new file mode 100644 index 0000000..2fe3cce --- /dev/null +++ b/test/scion_tests/parallel+interrupt/test12_test.exs @@ -0,0 +1,62 @@ +defmodule :"Elixir.Test.StateChart.Scion.Parallel+interrupt.Test12" do + use SC.Case + @tag :scion + @tag spec: "parallel+interrupt" + test "test12" do + xml = """ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + """ + + test_scxml(xml, "", ["b1", "b2"], [{%{"name" => "t"}, ["c1", "c2"]}]) + end +end diff --git a/test/scion_tests/parallel+interrupt/test13_test.exs b/test/scion_tests/parallel+interrupt/test13_test.exs new file mode 100644 index 0000000..61118a1 --- /dev/null +++ b/test/scion_tests/parallel+interrupt/test13_test.exs @@ -0,0 +1,64 @@ +defmodule :"Elixir.Test.StateChart.Scion.Parallel+interrupt.Test13" do + use SC.Case + @tag :scion + @tag spec: "parallel+interrupt" + test "test13" do + xml = """ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + """ + + test_scxml(xml, "", ["b1", "b2"], [{%{"name" => "t"}, ["c1", "c2"]}]) + end +end diff --git a/test/scion_tests/parallel+interrupt/test14_test.exs b/test/scion_tests/parallel+interrupt/test14_test.exs new file mode 100644 index 0000000..594befd --- /dev/null +++ b/test/scion_tests/parallel+interrupt/test14_test.exs @@ -0,0 +1,77 @@ +defmodule :"Elixir.Test.StateChart.Scion.Parallel+interrupt.Test14" do + use SC.Case + @tag :scion + @tag spec: "parallel+interrupt" + test "test14" do + xml = """ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + """ + + test_scxml(xml, "", ["i1", "j", "h", "g", "f1", "k"], [{%{"name" => "t"}, ["l"]}]) + end +end diff --git a/test/scion_tests/parallel+interrupt/test15_test.exs b/test/scion_tests/parallel+interrupt/test15_test.exs new file mode 100644 index 0000000..d38e065 --- /dev/null +++ b/test/scion_tests/parallel+interrupt/test15_test.exs @@ -0,0 +1,78 @@ +defmodule :"Elixir.Test.StateChart.Scion.Parallel+interrupt.Test15" do + use SC.Case + @tag :scion + @tag spec: "parallel+interrupt" + test "test15" do + xml = """ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + """ + + test_scxml(xml, "", ["i1", "j", "h", "g", "f1", "k"], [ + {%{"name" => "t"}, ["i2", "j", "h", "g", "f1", "k"]} + ]) + end +end diff --git a/test/scion_tests/parallel+interrupt/test16_test.exs b/test/scion_tests/parallel+interrupt/test16_test.exs new file mode 100644 index 0000000..cc2e586 --- /dev/null +++ b/test/scion_tests/parallel+interrupt/test16_test.exs @@ -0,0 +1,55 @@ +defmodule :"Elixir.Test.StateChart.Scion.Parallel+interrupt.Test16" do + use SC.Case + @tag :scion + @tag spec: "parallel+interrupt" + test "test16" do + xml = """ + + + + + + + + + + + + + + + + + + + + + + + """ + + test_scxml(xml, "", ["c", "d"], [{%{"name" => "t"}, ["a1"]}]) + end +end diff --git a/test/scion_tests/parallel+interrupt/test17_test.exs b/test/scion_tests/parallel+interrupt/test17_test.exs new file mode 100644 index 0000000..01208c9 --- /dev/null +++ b/test/scion_tests/parallel+interrupt/test17_test.exs @@ -0,0 +1,55 @@ +defmodule :"Elixir.Test.StateChart.Scion.Parallel+interrupt.Test17" do + use SC.Case + @tag :scion + @tag spec: "parallel+interrupt" + test "test17" do + xml = """ + + + + + + + + + + + + + + + + + + + + + + + """ + + test_scxml(xml, "", ["c", "d"], [{%{"name" => "t"}, ["a2"]}]) + end +end diff --git a/test/scion_tests/parallel+interrupt/test18_test.exs b/test/scion_tests/parallel+interrupt/test18_test.exs new file mode 100644 index 0000000..40729e1 --- /dev/null +++ b/test/scion_tests/parallel+interrupt/test18_test.exs @@ -0,0 +1,48 @@ +defmodule :"Elixir.Test.StateChart.Scion.Parallel+interrupt.Test18" do + use SC.Case + @tag :scion + @tag spec: "parallel+interrupt" + test "test18" do + xml = """ + + + + + + + + + + + + + + + + + + + + """ + + test_scxml(xml, "", ["c", "d"], [{%{"name" => "t"}, ["a2"]}]) + end +end diff --git a/test/scion_tests/parallel+interrupt/test19_test.exs b/test/scion_tests/parallel+interrupt/test19_test.exs new file mode 100644 index 0000000..57630c1 --- /dev/null +++ b/test/scion_tests/parallel+interrupt/test19_test.exs @@ -0,0 +1,57 @@ +defmodule :"Elixir.Test.StateChart.Scion.Parallel+interrupt.Test19" do + use SC.Case + @tag :scion + @tag spec: "parallel+interrupt" + test "test19" do + xml = """ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + """ + + test_scxml(xml, "", ["c1", "d1"], [{%{"name" => "t"}, ["c2", "d2"]}]) + end +end diff --git a/test/scion_tests/parallel+interrupt/test1_test.exs b/test/scion_tests/parallel+interrupt/test1_test.exs new file mode 100644 index 0000000..a342c33 --- /dev/null +++ b/test/scion_tests/parallel+interrupt/test1_test.exs @@ -0,0 +1,56 @@ +defmodule :"Elixir.Test.StateChart.Scion.Parallel+interrupt.Test1" do + use SC.Case + @tag :scion + @tag spec: "parallel+interrupt" + test "test1" do + xml = """ + + + + + + + + + + + + + + + + + + + + + + + + + """ + + test_scxml(xml, "", ["c1", "d1"], [{%{"name" => "t"}, ["c2", "d1"]}]) + end +end diff --git a/test/scion_tests/parallel+interrupt/test20_test.exs b/test/scion_tests/parallel+interrupt/test20_test.exs new file mode 100644 index 0000000..1f2a84a --- /dev/null +++ b/test/scion_tests/parallel+interrupt/test20_test.exs @@ -0,0 +1,57 @@ +defmodule :"Elixir.Test.StateChart.Scion.Parallel+interrupt.Test20" do + use SC.Case + @tag :scion + @tag spec: "parallel+interrupt" + test "test20" do + xml = """ + + + + + + + + + + + + + + + + + + + + + + + + + + + """ + + test_scxml(xml, "", ["c1", "d"], [{%{"name" => "t"}, ["c2", "d"]}]) + end +end diff --git a/test/scion_tests/parallel+interrupt/test21_test.exs b/test/scion_tests/parallel+interrupt/test21_test.exs new file mode 100644 index 0000000..2e4989c --- /dev/null +++ b/test/scion_tests/parallel+interrupt/test21_test.exs @@ -0,0 +1,58 @@ +defmodule :"Elixir.Test.StateChart.Scion.Parallel+interrupt.Test21" do + use SC.Case + @tag :scion + @tag spec: "parallel+interrupt" + test "test21" do + xml = """ + + + + + + + + + + + + + + + + + + + + + + + + + + + + """ + + test_scxml(xml, "", ["c", "d1"], [{%{"name" => "t"}, ["a1"]}]) + end +end diff --git a/test/scion_tests/parallel+interrupt/test21b_test.exs b/test/scion_tests/parallel+interrupt/test21b_test.exs new file mode 100644 index 0000000..07c546b --- /dev/null +++ b/test/scion_tests/parallel+interrupt/test21b_test.exs @@ -0,0 +1,59 @@ +defmodule :"Elixir.Test.StateChart.Scion.Parallel+interrupt.Test21b" do + use SC.Case + @tag :scion + @tag spec: "parallel+interrupt" + test "test21b" do + xml = """ + + + + + + + + + + + + + + + + + + + + + + + + + + + + """ + + test_scxml(xml, "", ["c", "d1"], [{%{"name" => "t"}, ["a1"]}]) + end +end diff --git a/test/scion_tests/parallel+interrupt/test21c_test.exs b/test/scion_tests/parallel+interrupt/test21c_test.exs new file mode 100644 index 0000000..f293f12 --- /dev/null +++ b/test/scion_tests/parallel+interrupt/test21c_test.exs @@ -0,0 +1,60 @@ +defmodule :"Elixir.Test.StateChart.Scion.Parallel+interrupt.Test21c" do + use SC.Case + @tag :scion + @tag spec: "parallel+interrupt" + test "test21c" do + xml = """ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + """ + + test_scxml(xml, "", ["c", "d1"], [{%{"name" => "t"}, ["c", "d2"]}]) + end +end diff --git a/test/scion_tests/parallel+interrupt/test22_test.exs b/test/scion_tests/parallel+interrupt/test22_test.exs new file mode 100644 index 0000000..c77b4d9 --- /dev/null +++ b/test/scion_tests/parallel+interrupt/test22_test.exs @@ -0,0 +1,59 @@ +defmodule :"Elixir.Test.StateChart.Scion.Parallel+interrupt.Test22" do + use SC.Case + @tag :scion + @tag spec: "parallel+interrupt" + test "test22" do + xml = """ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + """ + + test_scxml(xml, "", ["c1", "d1"], [{%{"name" => "t"}, ["c2", "d2"]}]) + end +end diff --git a/test/scion_tests/parallel+interrupt/test23_test.exs b/test/scion_tests/parallel+interrupt/test23_test.exs new file mode 100644 index 0000000..e408b18 --- /dev/null +++ b/test/scion_tests/parallel+interrupt/test23_test.exs @@ -0,0 +1,48 @@ +defmodule :"Elixir.Test.StateChart.Scion.Parallel+interrupt.Test23" do + use SC.Case + @tag :scion + @tag spec: "parallel+interrupt" + test "test23" do + xml = """ + + + + + + + + + + + + + + + + + + + + """ + + test_scxml(xml, "", ["c", "d"], [{%{"name" => "t"}, ["a2"]}]) + end +end diff --git a/test/scion_tests/parallel+interrupt/test24_test.exs b/test/scion_tests/parallel+interrupt/test24_test.exs new file mode 100644 index 0000000..f8dd6ba --- /dev/null +++ b/test/scion_tests/parallel+interrupt/test24_test.exs @@ -0,0 +1,57 @@ +defmodule :"Elixir.Test.StateChart.Scion.Parallel+interrupt.Test24" do + use SC.Case + @tag :scion + @tag spec: "parallel+interrupt" + test "test24" do + xml = """ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + """ + + test_scxml(xml, "", ["c1", "d1"], [{%{"name" => "t"}, ["c2", "d2"]}]) + end +end diff --git a/test/scion_tests/parallel+interrupt/test25_test.exs b/test/scion_tests/parallel+interrupt/test25_test.exs new file mode 100644 index 0000000..fd0e0f0 --- /dev/null +++ b/test/scion_tests/parallel+interrupt/test25_test.exs @@ -0,0 +1,57 @@ +defmodule :"Elixir.Test.StateChart.Scion.Parallel+interrupt.Test25" do + use SC.Case + @tag :scion + @tag spec: "parallel+interrupt" + test "test25" do + xml = """ + + + + + + + + + + + + + + + + + + + + + + + + + + + """ + + test_scxml(xml, "", ["c1", "d"], [{%{"name" => "t"}, ["c2", "d"]}]) + end +end diff --git a/test/scion_tests/parallel+interrupt/test27_test.exs b/test/scion_tests/parallel+interrupt/test27_test.exs new file mode 100644 index 0000000..349d07c --- /dev/null +++ b/test/scion_tests/parallel+interrupt/test27_test.exs @@ -0,0 +1,61 @@ +defmodule :"Elixir.Test.StateChart.Scion.Parallel+interrupt.Test27" do + use SC.Case + @tag :scion + @tag spec: "parallel+interrupt" + test "test27" do + xml = """ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + """ + + test_scxml(xml, "", ["c1", "d1"], [{%{"name" => "t"}, ["c2", "d2"]}]) + end +end diff --git a/test/scion_tests/parallel+interrupt/test28_test.exs b/test/scion_tests/parallel+interrupt/test28_test.exs new file mode 100644 index 0000000..8a5ad66 --- /dev/null +++ b/test/scion_tests/parallel+interrupt/test28_test.exs @@ -0,0 +1,55 @@ +defmodule :"Elixir.Test.StateChart.Scion.Parallel+interrupt.Test28" do + use SC.Case + @tag :scion + @tag spec: "parallel+interrupt" + test "test28" do + xml = """ + + + + + + + + + + + + + + + + + + + + + + + + + """ + + test_scxml(xml, "", ["c", "d"], [{%{"name" => "t"}, ["a2"]}]) + end +end diff --git a/test/scion_tests/parallel+interrupt/test29_test.exs b/test/scion_tests/parallel+interrupt/test29_test.exs new file mode 100644 index 0000000..89ebf7a --- /dev/null +++ b/test/scion_tests/parallel+interrupt/test29_test.exs @@ -0,0 +1,55 @@ +defmodule :"Elixir.Test.StateChart.Scion.Parallel+interrupt.Test29" do + use SC.Case + @tag :scion + @tag spec: "parallel+interrupt" + test "test29" do + xml = """ + + + + + + + + + + + + + + + + + + + + + + + + + """ + + test_scxml(xml, "", ["c", "d"], [{%{"name" => "t"}, ["a1"]}]) + end +end diff --git a/test/scion_tests/parallel+interrupt/test2_test.exs b/test/scion_tests/parallel+interrupt/test2_test.exs new file mode 100644 index 0000000..a20a822 --- /dev/null +++ b/test/scion_tests/parallel+interrupt/test2_test.exs @@ -0,0 +1,60 @@ +defmodule :"Elixir.Test.StateChart.Scion.Parallel+interrupt.Test2" do + use SC.Case + @tag :scion + @tag spec: "parallel+interrupt" + test "test2" do + xml = """ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + """ + + test_scxml(xml, "", ["c1", "d1"], [{%{"name" => "t"}, ["a1"]}]) + end +end diff --git a/test/scion_tests/parallel+interrupt/test30_test.exs b/test/scion_tests/parallel+interrupt/test30_test.exs new file mode 100644 index 0000000..15fd010 --- /dev/null +++ b/test/scion_tests/parallel+interrupt/test30_test.exs @@ -0,0 +1,62 @@ +defmodule :"Elixir.Test.StateChart.Scion.Parallel+interrupt.Test30" do + use SC.Case + @tag :scion + @tag spec: "parallel+interrupt" + test "test30" do + xml = """ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + """ + + test_scxml(xml, "", ["c1", "d"], [{%{"name" => "t"}, ["c2", "d"]}]) + end +end diff --git a/test/scion_tests/parallel+interrupt/test31_test.exs b/test/scion_tests/parallel+interrupt/test31_test.exs new file mode 100644 index 0000000..508b37c --- /dev/null +++ b/test/scion_tests/parallel+interrupt/test31_test.exs @@ -0,0 +1,65 @@ +defmodule :"Elixir.Test.StateChart.Scion.Parallel+interrupt.Test31" do + use SC.Case + @tag :scion + @tag spec: "parallel+interrupt" + test "test31" do + xml = """ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + """ + + test_scxml(xml, "", ["c1", "d1"], [{%{"name" => "t"}, ["a1"]}]) + end +end diff --git a/test/scion_tests/parallel+interrupt/test3_test.exs b/test/scion_tests/parallel+interrupt/test3_test.exs new file mode 100644 index 0000000..ca3918e --- /dev/null +++ b/test/scion_tests/parallel+interrupt/test3_test.exs @@ -0,0 +1,50 @@ +defmodule :"Elixir.Test.StateChart.Scion.Parallel+interrupt.Test3" do + use SC.Case + @tag :scion + @tag spec: "parallel+interrupt" + test "test3" do + xml = """ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + """ + + test_scxml(xml, "", ["e", "f", "d"], [{%{"name" => "t"}, ["a1"]}]) + end +end diff --git a/test/scion_tests/parallel+interrupt/test4_test.exs b/test/scion_tests/parallel+interrupt/test4_test.exs new file mode 100644 index 0000000..3cb548d --- /dev/null +++ b/test/scion_tests/parallel+interrupt/test4_test.exs @@ -0,0 +1,69 @@ +defmodule :"Elixir.Test.StateChart.Scion.Parallel+interrupt.Test4" do + use SC.Case + @tag :scion + @tag spec: "parallel+interrupt" + test "test4" do + xml = """ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + """ + + test_scxml(xml, "", ["e", "f", "g"], [{%{"name" => "t"}, ["a1"]}]) + end +end diff --git a/test/scion_tests/parallel+interrupt/test5_test.exs b/test/scion_tests/parallel+interrupt/test5_test.exs new file mode 100644 index 0000000..5cb848e --- /dev/null +++ b/test/scion_tests/parallel+interrupt/test5_test.exs @@ -0,0 +1,67 @@ +defmodule :"Elixir.Test.StateChart.Scion.Parallel+interrupt.Test5" do + use SC.Case + @tag :scion + @tag spec: "parallel+interrupt" + test "test5" do + xml = """ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + """ + + test_scxml(xml, "", ["e", "f", "g"], [{%{"name" => "t"}, ["e", "f", "h"]}]) + end +end diff --git a/test/scion_tests/parallel+interrupt/test6_test.exs b/test/scion_tests/parallel+interrupt/test6_test.exs new file mode 100644 index 0000000..9617dec --- /dev/null +++ b/test/scion_tests/parallel+interrupt/test6_test.exs @@ -0,0 +1,71 @@ +defmodule :"Elixir.Test.StateChart.Scion.Parallel+interrupt.Test6" do + use SC.Case + @tag :scion + @tag spec: "parallel+interrupt" + test "test6" do + xml = """ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + """ + + test_scxml(xml, "", ["g", "e1", "f1"], [{%{"name" => "t"}, ["h", "e2", "f2"]}]) + end +end diff --git a/test/scion_tests/parallel+interrupt/test7_test.exs b/test/scion_tests/parallel+interrupt/test7_test.exs new file mode 100644 index 0000000..988face --- /dev/null +++ b/test/scion_tests/parallel+interrupt/test7_test.exs @@ -0,0 +1,72 @@ +defmodule :"Elixir.Test.StateChart.Scion.Parallel+interrupt.Test7" do + use SC.Case + @tag :scion + @tag spec: "parallel+interrupt" + test "test7" do + xml = """ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + """ + + test_scxml(xml, "", ["c", "e1", "f1"], [{%{"name" => "t"}, ["a1"]}]) + end +end diff --git a/test/scion_tests/parallel+interrupt/test7b_test.exs b/test/scion_tests/parallel+interrupt/test7b_test.exs new file mode 100644 index 0000000..436b785 --- /dev/null +++ b/test/scion_tests/parallel+interrupt/test7b_test.exs @@ -0,0 +1,72 @@ +defmodule :"Elixir.Test.StateChart.Scion.Parallel+interrupt.Test7b" do + use SC.Case + @tag :scion + @tag spec: "parallel+interrupt" + test "test7b" do + xml = """ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + """ + + test_scxml(xml, "", ["c", "e1", "f1"], [{%{"name" => "t"}, ["c", "e2", "f2"]}]) + end +end diff --git a/test/scion_tests/parallel+interrupt/test8_test.exs b/test/scion_tests/parallel+interrupt/test8_test.exs new file mode 100644 index 0000000..2b7965c --- /dev/null +++ b/test/scion_tests/parallel+interrupt/test8_test.exs @@ -0,0 +1,59 @@ +defmodule :"Elixir.Test.StateChart.Scion.Parallel+interrupt.Test8" do + use SC.Case + @tag :scion + @tag spec: "parallel+interrupt" + test "test8" do + xml = """ + + + + + + + + + + + + + + + + + + + + + + + + + + + """ + + test_scxml(xml, "", ["b1", "b2"], [{%{"name" => "t"}, ["c1", "c2"]}]) + end +end diff --git a/test/scion_tests/parallel+interrupt/test9_test.exs b/test/scion_tests/parallel+interrupt/test9_test.exs new file mode 100644 index 0000000..9854042 --- /dev/null +++ b/test/scion_tests/parallel+interrupt/test9_test.exs @@ -0,0 +1,58 @@ +defmodule :"Elixir.Test.StateChart.Scion.Parallel+interrupt.Test9" do + use SC.Case + @tag :scion + @tag spec: "parallel+interrupt" + test "test9" do + xml = """ + + + + + + + + + + + + + + + + + + + + + + + + + + """ + + test_scxml(xml, "", ["b1", "b2"], [{%{"name" => "t"}, ["c1", "c2"]}]) + end +end diff --git a/test/scion_tests/parallel/test0_test.exs b/test/scion_tests/parallel/test0_test.exs new file mode 100644 index 0000000..ebe519c --- /dev/null +++ b/test/scion_tests/parallel/test0_test.exs @@ -0,0 +1,40 @@ +defmodule SCIONTest.Parallel.Test0Test do + use SC.Case + @tag :scion + @tag spec: "parallel" + test "test0" do + xml = """ + + + + + + + + + + + + + """ + + test_scxml(xml, "", ["a", "b"], []) + end +end diff --git a/test/scion_tests/parallel/test1_test.exs b/test/scion_tests/parallel/test1_test.exs new file mode 100644 index 0000000..7837ad7 --- /dev/null +++ b/test/scion_tests/parallel/test1_test.exs @@ -0,0 +1,60 @@ +defmodule SCIONTest.Parallel.Test1Test do + use SC.Case + @tag :scion + @tag spec: "parallel" + test "test1" do + xml = """ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + """ + + test_scxml(xml, "", ["a1", "b1"], [{%{"name" => "t"}, ["a2", "b2"]}]) + end +end diff --git a/test/scion_tests/parallel/test2_test.exs b/test/scion_tests/parallel/test2_test.exs new file mode 100644 index 0000000..b91d894 --- /dev/null +++ b/test/scion_tests/parallel/test2_test.exs @@ -0,0 +1,73 @@ +defmodule SCIONTest.Parallel.Test2Test do + use SC.Case + @tag :scion + @tag spec: "parallel" + test "test2" do + xml = """ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + """ + + test_scxml(xml, "", ["s3", "s4", "s7", "s8"], [{%{"name" => "t"}, ["s5", "s6", "s9", "s10"]}]) + end +end diff --git a/test/scion_tests/parallel/test3_test.exs b/test/scion_tests/parallel/test3_test.exs new file mode 100644 index 0000000..662a6b0 --- /dev/null +++ b/test/scion_tests/parallel/test3_test.exs @@ -0,0 +1,88 @@ +defmodule SCIONTest.Parallel.Test3Test do + use SC.Case + @tag :scion + @tag spec: "parallel" + test "test3" do + xml = """ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + """ + + test_scxml(xml, "", ["s3.1", "s4", "s7", "s8"], [ + {%{"name" => "t"}, ["s3.2", "s4", "s9", "s10"]} + ]) + end +end diff --git a/test/scion_tests/script-src/script-0-0.js b/test/scion_tests/script-src/script-0-0.js new file mode 100644 index 0000000..062f555 --- /dev/null +++ b/test/scion_tests/script-src/script-0-0.js @@ -0,0 +1 @@ +x = 100; diff --git a/test/scion_tests/script-src/script-1-0.js b/test/scion_tests/script-src/script-1-0.js new file mode 100644 index 0000000..226697f --- /dev/null +++ b/test/scion_tests/script-src/script-1-0.js @@ -0,0 +1 @@ +i = 0; diff --git a/test/scion_tests/script-src/script-1-1.js b/test/scion_tests/script-src/script-1-1.js new file mode 100644 index 0000000..8dca7b1 --- /dev/null +++ b/test/scion_tests/script-src/script-1-1.js @@ -0,0 +1 @@ +i = i + 1; diff --git a/test/scion_tests/script-src/script-2-0.js b/test/scion_tests/script-src/script-2-0.js new file mode 100644 index 0000000..226697f --- /dev/null +++ b/test/scion_tests/script-src/script-2-0.js @@ -0,0 +1 @@ +i = 0; diff --git a/test/scion_tests/script-src/script-2-1.js b/test/scion_tests/script-src/script-2-1.js new file mode 100644 index 0000000..8dca7b1 --- /dev/null +++ b/test/scion_tests/script-src/script-2-1.js @@ -0,0 +1 @@ +i = i + 1; diff --git a/test/scion_tests/script-src/script-2-2.js b/test/scion_tests/script-src/script-2-2.js new file mode 100644 index 0000000..8dca7b1 --- /dev/null +++ b/test/scion_tests/script-src/script-2-2.js @@ -0,0 +1 @@ +i = i + 1; diff --git a/test/scion_tests/script-src/script-2-3.js b/test/scion_tests/script-src/script-2-3.js new file mode 100644 index 0000000..795c1f2 --- /dev/null +++ b/test/scion_tests/script-src/script-2-3.js @@ -0,0 +1 @@ +i = i * 2; diff --git a/test/scion_tests/script-src/script-3-0.js b/test/scion_tests/script-src/script-3-0.js new file mode 100644 index 0000000..de469c4 --- /dev/null +++ b/test/scion_tests/script-src/script-3-0.js @@ -0,0 +1,3 @@ +function foo(){ + x = 100; +} diff --git a/test/scion_tests/script-src/test0_test.exs b/test/scion_tests/script-src/test0_test.exs new file mode 100644 index 0000000..200ac72 --- /dev/null +++ b/test/scion_tests/script-src/test0_test.exs @@ -0,0 +1,53 @@ +defmodule SCIONTest.ScriptSrc.Test0Test do + use SC.Case + @tag :scion + @tag spec: "script_src" + test "test0" do + xml = """ + + + + + + + + + + + + + + + + + + + + + + + + + + """ + + test_scxml(xml, "", ["a"], [{%{"name" => "t"}, ["b"]}]) + end +end diff --git a/test/scion_tests/script/test0_test.exs b/test/scion_tests/script/test0_test.exs new file mode 100644 index 0000000..fc063e4 --- /dev/null +++ b/test/scion_tests/script/test0_test.exs @@ -0,0 +1,55 @@ +defmodule SCIONTest.Script.Test0Test do + use SC.Case + @tag :scion + @tag spec: "script" + test "test0" do + xml = """ + + + + + + + + + + + + + + + + + + + + + + + + + + """ + + test_scxml(xml, "", ["a"], [{%{"name" => "t"}, ["b"]}]) + end +end diff --git a/test/scion_tests/script/test1_test.exs b/test/scion_tests/script/test1_test.exs new file mode 100644 index 0000000..d74bb09 --- /dev/null +++ b/test/scion_tests/script/test1_test.exs @@ -0,0 +1,56 @@ +defmodule SCIONTest.Script.Test1Test do + use SC.Case + @tag :scion + @tag spec: "script" + test "test1" do + xml = """ + + + + + + + + + + + + + + + + + + + + + + + + + """ + + test_scxml(xml, "", ["a"], [{%{"name" => "t"}, ["c"]}]) + end +end diff --git a/test/scion_tests/script/test2_test.exs b/test/scion_tests/script/test2_test.exs new file mode 100644 index 0000000..437eb00 --- /dev/null +++ b/test/scion_tests/script/test2_test.exs @@ -0,0 +1,80 @@ +defmodule SCIONTest.Script.Test2Test do + use SC.Case + @tag :scion + @tag spec: "script" + test "test2" do + xml = """ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + """ + + test_scxml(xml, "", ["a"], [{%{"name" => "t"}, ["e"]}]) + end +end diff --git a/test/scion_tests/scxml-prefix-event-name-matching/star0_test.exs b/test/scion_tests/scxml-prefix-event-name-matching/star0_test.exs new file mode 100644 index 0000000..cd51e90 --- /dev/null +++ b/test/scion_tests/scxml-prefix-event-name-matching/star0_test.exs @@ -0,0 +1,44 @@ +defmodule SCIONTest.ScxmlPrefixEventNameMatching.Star0Test do + use SC.Case + @tag :scion + @tag spec: "scxml_prefix_event_name_matching" + test "star0" do + xml = """ + + + + + + + + + + + + + + + + + """ + + test_scxml(xml, "", ["a"], [{%{"name" => "foo"}, ["b"]}]) + end +end diff --git a/test/scion_tests/scxml-prefix-event-name-matching/test0_test.exs b/test/scion_tests/scxml-prefix-event-name-matching/test0_test.exs new file mode 100644 index 0000000..3260767 --- /dev/null +++ b/test/scion_tests/scxml-prefix-event-name-matching/test0_test.exs @@ -0,0 +1,68 @@ +defmodule SCIONTest.ScxmlPrefixEventNameMatching.Test0Test do + use SC.Case + @tag :scion + @tag spec: "scxml_prefix_event_name_matching" + test "test0" do + xml = """ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + """ + + test_scxml(xml, "", ["a"], [ + {%{"name" => "foo"}, ["b"]}, + {%{"name" => "foo.bar"}, ["c"]}, + {%{"name" => "foo.bar.bat"}, ["d"]}, + {%{"name" => "foo.bar.bat"}, ["e"]}, + {%{"name" => "foo"}, ["e"]}, + {%{"name" => "foo.bar.bat"}, ["f"]}, + {%{"name" => "foobar"}, ["f"]}, + {%{"name" => "foo.bar.bat.bif"}, ["g"]} + ]) + end +end diff --git a/test/scion_tests/scxml-prefix-event-name-matching/test1_test.exs b/test/scion_tests/scxml-prefix-event-name-matching/test1_test.exs new file mode 100644 index 0000000..9b9c19e --- /dev/null +++ b/test/scion_tests/scxml-prefix-event-name-matching/test1_test.exs @@ -0,0 +1,73 @@ +defmodule SCIONTest.ScxmlPrefixEventNameMatching.Test1Test do + use SC.Case + @tag :scion + @tag spec: "scxml_prefix_event_name_matching" + test "test1" do + xml = """ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + """ + + test_scxml(xml, "", ["a"], [ + {%{"name" => "foo"}, ["b"]}, + {%{"name" => "foo.bar"}, ["c"]}, + {%{"name" => "foo.bar.bat"}, ["d"]}, + {%{"name" => "foo.bar.bat"}, ["e"]}, + {%{"name" => "foo"}, ["e"]}, + {%{"name" => "foo.bar.bat"}, ["f"]}, + {%{"name" => "foobar"}, ["f"]}, + {%{"name" => "foo.bar.bat.bif"}, ["g"]} + ]) + end +end diff --git a/test/scion_tests/send-data/send1_test.exs b/test/scion_tests/send-data/send1_test.exs new file mode 100644 index 0000000..1847127 --- /dev/null +++ b/test/scion_tests/send-data/send1_test.exs @@ -0,0 +1,91 @@ +defmodule SCIONTest.SendData.Send1Test do + use SC.Case + @tag :scion + @tag spec: "send_data" + test "send1" do + xml = """ + + + + + + + + + + + + + + + + + + + + + + + + More content. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + """ + + test_scxml(xml, "", ["a"], [{%{"name" => "t"}, ["b"]}, {%{"name" => "t2"}, ["e"]}]) + end +end diff --git a/test/scion_tests/send-idlocation/test0_test.exs b/test/scion_tests/send-idlocation/test0_test.exs new file mode 100644 index 0000000..c9aa27a --- /dev/null +++ b/test/scion_tests/send-idlocation/test0_test.exs @@ -0,0 +1,55 @@ +defmodule SCIONTest.SendIdlocation.Test0Test do + use SC.Case + @tag :scion + @tag spec: "send_idlocation" + test "test0" do + xml = """ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + """ + + test_scxml(xml, "", ["s0"], [{%{"name" => "t1"}, ["s1"]}, {%{"name" => "t2"}, ["pass"]}]) + end +end diff --git a/test/scion_tests/send-internal/test0_test.exs b/test/scion_tests/send-internal/test0_test.exs new file mode 100644 index 0000000..f83180c --- /dev/null +++ b/test/scion_tests/send-internal/test0_test.exs @@ -0,0 +1,77 @@ +defmodule SCIONTest.SendInternal.Test0Test do + use SC.Case + @tag :scion + @tag spec: "send_internal" + test "test0" do + xml = """ + + + + + + + + + + + + + + + + + + + + + + + + More content. + + + + + + + + + + + + + + + + + + + + + """ + + test_scxml(xml, "", ["a"], [{%{"name" => "t"}, ["d"]}]) + end +end diff --git a/test/scion_tests/targetless-transition/test0_test.exs b/test/scion_tests/targetless-transition/test0_test.exs new file mode 100644 index 0000000..d744a0d --- /dev/null +++ b/test/scion_tests/targetless-transition/test0_test.exs @@ -0,0 +1,50 @@ +defmodule SCIONTest.TargetlessTransition.Test0Test do + use SC.Case + @tag :scion + @tag spec: "targetless_transition" + test "test0" do + xml = """ + + + + + + + + + + + + + + + + + + + + + + + """ + + test_scxml(xml, "", ["a"], [{%{"name" => "t"}, ["done"]}]) + end +end diff --git a/test/scion_tests/targetless-transition/test1_test.exs b/test/scion_tests/targetless-transition/test1_test.exs new file mode 100644 index 0000000..a92d2b1 --- /dev/null +++ b/test/scion_tests/targetless-transition/test1_test.exs @@ -0,0 +1,53 @@ +defmodule SCIONTest.TargetlessTransition.Test1Test do + use SC.Case + @tag :scion + @tag spec: "targetless_transition" + test "test1" do + xml = """ + + + + + + + + + + + + + + + + + + + + + + + + + + """ + + test_scxml(xml, "", ["a"], [{%{"name" => "foo"}, ["a"]}, {%{"name" => "bar"}, ["done"]}]) + end +end diff --git a/test/scion_tests/targetless-transition/test2_test.exs b/test/scion_tests/targetless-transition/test2_test.exs new file mode 100644 index 0000000..b108589 --- /dev/null +++ b/test/scion_tests/targetless-transition/test2_test.exs @@ -0,0 +1,56 @@ +defmodule SCIONTest.TargetlessTransition.Test2Test do + use SC.Case + @tag :scion + @tag spec: "targetless_transition" + test "test2" do + xml = """ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + """ + + test_scxml(xml, "", ["a"], [{%{"name" => "foo"}, ["a"]}, {%{"name" => "bar"}, ["done"]}]) + end +end diff --git a/test/scion_tests/targetless-transition/test3_test.exs b/test/scion_tests/targetless-transition/test3_test.exs new file mode 100644 index 0000000..a006f61 --- /dev/null +++ b/test/scion_tests/targetless-transition/test3_test.exs @@ -0,0 +1,84 @@ +defmodule SCIONTest.TargetlessTransition.Test3Test do + use SC.Case + @tag :scion + @tag spec: "targetless_transition" + test "test3" do + xml = """ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + """ + + test_scxml(xml, "", ["a1", "b1", "c"], [ + {%{"name" => "foo"}, ["a2", "b2", "c"]}, + {%{"name" => "bar"}, ["done"]} + ]) + end +end diff --git a/test/scxml_tests/mandatory/EvaluationofExecutableContent/test158_test.exs b/test/scxml_tests/mandatory/EvaluationofExecutableContent/test158_test.exs new file mode 100644 index 0000000..433c0c1 --- /dev/null +++ b/test/scxml_tests/mandatory/EvaluationofExecutableContent/test158_test.exs @@ -0,0 +1,42 @@ +defmodule Test.StateChart.W3.EvaluationofExecutableContent.Test158 do + use SC.Case + @tag :scxml_w3 + @tag conformance: "mandatory", spec: "EvaluationofExecutableContent" + test "test158" do + xml = """ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + """ + + description = + "The SCXML processor MUST execute the elements of a block of executable contentin document order." + + test_scxml(xml, description, ["pass"], []) + end +end diff --git a/test/scxml_tests/mandatory/EvaluationofExecutableContent/test159_test.exs b/test/scxml_tests/mandatory/EvaluationofExecutableContent/test159_test.exs new file mode 100644 index 0000000..a171185 --- /dev/null +++ b/test/scxml_tests/mandatory/EvaluationofExecutableContent/test159_test.exs @@ -0,0 +1,38 @@ +defmodule Test.StateChart.W3.EvaluationofExecutableContent.Test159 do + use SC.Case + @tag :scxml_w3 + @tag conformance: "mandatory", spec: "EvaluationofExecutableContent" + test "test159" do + xml = """ + + + + + + + + + + + + + + + + + + + + + + + + + """ + + description = + "If the processing of an element of executable content causes an error to be raised, the processor MUST NOT process the remaining elements of the block." + + test_scxml(xml, description, ["pass"], []) + end +end diff --git a/test/scxml_tests/mandatory/SelectingTransitions/test403a_test.exs b/test/scxml_tests/mandatory/SelectingTransitions/test403a_test.exs new file mode 100644 index 0000000..1307953 --- /dev/null +++ b/test/scxml_tests/mandatory/SelectingTransitions/test403a_test.exs @@ -0,0 +1,49 @@ +defmodule Test.StateChart.W3.SelectingTransitions.Test403a do + use SC.Case + @tag :scxml_w3 + @tag conformance: "mandatory", spec: "SelectingTransitions" + test "test403a" do + xml = """ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + """ + + description = + "To execute a microstep, the SCXML Processor MUST execute the transitions in the corresponding optimal enabled transition set, where the optimal transition set enabled by event E in state configuration C is the largest set of transitions such that a) each transition in the set is optimally enabled by E in an atomic state in C b) no transition conflicts with another transition in the set c) there is no optimally enabled transition outside the set that has a higher priority than some member of the set." + + test_scxml(xml, description, ["pass"], []) + end +end diff --git a/test/scxml_tests/mandatory/SelectingTransitions/test403b_test.exs b/test/scxml_tests/mandatory/SelectingTransitions/test403b_test.exs new file mode 100644 index 0000000..9f1be09 --- /dev/null +++ b/test/scxml_tests/mandatory/SelectingTransitions/test403b_test.exs @@ -0,0 +1,49 @@ +defmodule Test.StateChart.W3.SelectingTransitions.Test403b do + use SC.Case + @tag :scxml_w3 + @tag conformance: "mandatory", spec: "SelectingTransitions" + test "test403b" do + xml = """ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + """ + + description = + "To execute a microstep, the SCXML Processor MUST execute the transitions in the corresponding optimal enabled transition set, where the optimal transition set enabled by event E in state configuration C is the largest set of transitions such that a) each transition in the set is optimally enabled by E in an atomic state in C b) no transition conflicts with another transition in the set c) there is no optimally enabled transition outside the set that has a higher priority than some member of the set." + + test_scxml(xml, description, ["pass"], []) + end +end diff --git a/test/scxml_tests/mandatory/SelectingTransitions/test403c_test.exs b/test/scxml_tests/mandatory/SelectingTransitions/test403c_test.exs new file mode 100644 index 0000000..eb5ee45 --- /dev/null +++ b/test/scxml_tests/mandatory/SelectingTransitions/test403c_test.exs @@ -0,0 +1,64 @@ +defmodule Test.StateChart.W3.SelectingTransitions.Test403c do + use SC.Case + @tag :scxml_w3 + @tag conformance: "mandatory", spec: "SelectingTransitions" + test "test403c" do + xml = """ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + """ + + description = + "To execute a microstep, the SCXML Processor MUST execute the transitions in the corresponding optimal enabled transition set, where the optimal transition set enabled by event E in state configuration C is the largest set of transitions such that a) each transition in the set is optimally enabled by E in an atomic state in C b) no transition conflicts with another transition in the set c) there is no optimally enabled transition outside the set that has a higher priority than some member of the set." + + test_scxml(xml, description, ["pass"], []) + end +end diff --git a/test/scxml_tests/mandatory/SelectingTransitions/test404_test.exs b/test/scxml_tests/mandatory/SelectingTransitions/test404_test.exs new file mode 100644 index 0000000..7ae6520 --- /dev/null +++ b/test/scxml_tests/mandatory/SelectingTransitions/test404_test.exs @@ -0,0 +1,63 @@ +defmodule Test.StateChart.W3.SelectingTransitions.Test404 do + use SC.Case + @tag :scxml_w3 + @tag conformance: "mandatory", spec: "SelectingTransitions" + test "test404" do + xml = """ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + """ + + description = + "To execute a set of transitions, the SCXML Processor MUST first exit all the states in the transitions' exit set in exit order." + + test_scxml(xml, description, ["pass"], []) + end +end diff --git a/test/scxml_tests/mandatory/SelectingTransitions/test405_test.exs b/test/scxml_tests/mandatory/SelectingTransitions/test405_test.exs new file mode 100644 index 0000000..eb6bd04 --- /dev/null +++ b/test/scxml_tests/mandatory/SelectingTransitions/test405_test.exs @@ -0,0 +1,70 @@ +defmodule Test.StateChart.W3.SelectingTransitions.Test405 do + use SC.Case + @tag :scxml_w3 + @tag conformance: "mandatory", spec: "SelectingTransitions" + test "test405" do + xml = """ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + """ + + description = + "[the SCXML Processor executing a set of transitions] MUST then [after the onexits] execute the executable content contained in the transitions in document order." + + test_scxml(xml, description, ["pass"], []) + end +end diff --git a/test/scxml_tests/mandatory/SelectingTransitions/test406_test.exs b/test/scxml_tests/mandatory/SelectingTransitions/test406_test.exs new file mode 100644 index 0000000..78ea034 --- /dev/null +++ b/test/scxml_tests/mandatory/SelectingTransitions/test406_test.exs @@ -0,0 +1,66 @@ +defmodule Test.StateChart.W3.SelectingTransitions.Test406 do + use SC.Case + @tag :scxml_w3 + @tag conformance: "mandatory", spec: "SelectingTransitions" + test "test406" do + xml = """ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + """ + + description = + "[the SCXML Processor executing a set of transitions] MUST then [after the exits and the transitions] enter the states in the transitions' entry set in entry order." + + test_scxml(xml, description, ["pass"], []) + end +end diff --git a/test/scxml_tests/mandatory/SelectingTransitions/test407_test.exs b/test/scxml_tests/mandatory/SelectingTransitions/test407_test.exs new file mode 100644 index 0000000..43f7467 --- /dev/null +++ b/test/scxml_tests/mandatory/SelectingTransitions/test407_test.exs @@ -0,0 +1,40 @@ +defmodule Test.StateChart.W3.SelectingTransitions.Test407 do + use SC.Case + @tag :scxml_w3 + @tag conformance: "mandatory", spec: "SelectingTransitions" + test "test407" do + xml = """ + + + + + + + + + + + + + + + + + + + + + + + + + + + """ + + description = + "To exit a state, the SCXML Processor MUST execute the executable content in the state's onexit handler." + + test_scxml(xml, description, ["pass"], []) + end +end diff --git a/test/scxml_tests/mandatory/SelectingTransitions/test409_test.exs b/test/scxml_tests/mandatory/SelectingTransitions/test409_test.exs new file mode 100644 index 0000000..a22f846 --- /dev/null +++ b/test/scxml_tests/mandatory/SelectingTransitions/test409_test.exs @@ -0,0 +1,45 @@ +defmodule Test.StateChart.W3.SelectingTransitions.Test409 do + use SC.Case + @tag :scxml_w3 + @tag conformance: "mandatory", spec: "SelectingTransitions" + test "test409" do + xml = """ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + """ + + description = + "Finally [after the onexits and canceling the invocations], the Processor MUST remove the state from the active state's list." + + test_scxml(xml, description, ["pass"], []) + end +end diff --git a/test/scxml_tests/mandatory/SelectingTransitions/test411_test.exs b/test/scxml_tests/mandatory/SelectingTransitions/test411_test.exs new file mode 100644 index 0000000..b5d9c61 --- /dev/null +++ b/test/scxml_tests/mandatory/SelectingTransitions/test411_test.exs @@ -0,0 +1,45 @@ +defmodule Test.StateChart.W3.SelectingTransitions.Test411 do + use SC.Case + @tag :scxml_w3 + @tag conformance: "mandatory", spec: "SelectingTransitions" + test "test411" do + xml = """ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + """ + + description = + "To enter a state, the SCXML Processor MUST add the state to the active state's list. Then it MUST execute the executable content in the state's onentry handler." + + test_scxml(xml, description, ["pass"], []) + end +end diff --git a/test/scxml_tests/mandatory/SelectingTransitions/test412_test.exs b/test/scxml_tests/mandatory/SelectingTransitions/test412_test.exs new file mode 100644 index 0000000..f1763bb --- /dev/null +++ b/test/scxml_tests/mandatory/SelectingTransitions/test412_test.exs @@ -0,0 +1,63 @@ +defmodule Test.StateChart.W3.SelectingTransitions.Test412 do + use SC.Case + @tag :scxml_w3 + @tag conformance: "mandatory", spec: "SelectingTransitions" + test "test412" do + xml = """ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + """ + + description = + "If the state is a default entry state and has an initial child, the SCXML Processor MUST then [after doing the active state add and the onentry handlers] execute the executable content in the initial child's transition." + + test_scxml(xml, description, ["pass"], []) + end +end diff --git a/test/scxml_tests/mandatory/SelectingTransitions/test413_test.exs b/test/scxml_tests/mandatory/SelectingTransitions/test413_test.exs new file mode 100644 index 0000000..501e99a --- /dev/null +++ b/test/scxml_tests/mandatory/SelectingTransitions/test413_test.exs @@ -0,0 +1,51 @@ +defmodule Test.StateChart.W3.SelectingTransitions.Test413 do + use SC.Case + @tag :scxml_w3 + @tag conformance: "mandatory", spec: "SelectingTransitions" + test "test413" do + xml = """ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + """ + + description = + "At startup, the SCXML Processor MUST place the state machine in the configuration specified by the 'initial' attribute of the scxml element." + + test_scxml(xml, description, ["pass"], []) + end +end diff --git a/test/scxml_tests/mandatory/SelectingTransitions/test416_test.exs b/test/scxml_tests/mandatory/SelectingTransitions/test416_test.exs new file mode 100644 index 0000000..d0a382b --- /dev/null +++ b/test/scxml_tests/mandatory/SelectingTransitions/test416_test.exs @@ -0,0 +1,40 @@ +defmodule Test.StateChart.W3.SelectingTransitions.Test416 do + use SC.Case + @tag :scxml_w3 + @tag conformance: "mandatory", spec: "SelectingTransitions" + test "test416" do + xml = """ + + + + + + + + + + + + + + + + + + + + + + + + + + + """ + + description = + "If it [the SCXML processor] has entered a final state that is a child of a compound state [during the last microstep], it MUST generate the event done.state.id, where id is the id of the compound state." + + test_scxml(xml, description, ["pass"], []) + end +end diff --git a/test/scxml_tests/mandatory/SelectingTransitions/test417_test.exs b/test/scxml_tests/mandatory/SelectingTransitions/test417_test.exs new file mode 100644 index 0000000..57fbc2c --- /dev/null +++ b/test/scxml_tests/mandatory/SelectingTransitions/test417_test.exs @@ -0,0 +1,48 @@ +defmodule Test.StateChart.W3.SelectingTransitions.Test417 do + use SC.Case + @tag :scxml_w3 + @tag conformance: "mandatory", spec: "SelectingTransitions" + test "test417" do + xml = """ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + """ + + description = + "If the compound state [which has the final element that we entered this microstep] is itself the child of a parallel element, and all the parallel element's other children are in final states, the Processor MUST generate the event done.state.id, where id is the id of the parallel element." + + test_scxml(xml, description, ["pass"], []) + end +end diff --git a/test/scxml_tests/mandatory/SelectingTransitions/test419_test.exs b/test/scxml_tests/mandatory/SelectingTransitions/test419_test.exs new file mode 100644 index 0000000..6464018 --- /dev/null +++ b/test/scxml_tests/mandatory/SelectingTransitions/test419_test.exs @@ -0,0 +1,35 @@ +defmodule Test.StateChart.W3.SelectingTransitions.Test419 do + use SC.Case + @tag :scxml_w3 + @tag conformance: "mandatory", spec: "SelectingTransitions" + test "test419" do + xml = """ + + + + + + + + + + + + + + + + + + + + + + """ + + description = + "After checking the state configuration, the Processor MUST select the optimal transition set enabled by NULL in the current configuration. If the [optimal transition] set [enabled by NULL in the current configuration] is not empty, it [the SCXML Processor] MUST execute it [the set] as a microstep." + + test_scxml(xml, description, ["pass"], []) + end +end diff --git a/test/scxml_tests/mandatory/SelectingTransitions/test421_test.exs b/test/scxml_tests/mandatory/SelectingTransitions/test421_test.exs new file mode 100644 index 0000000..10e4ad5 --- /dev/null +++ b/test/scxml_tests/mandatory/SelectingTransitions/test421_test.exs @@ -0,0 +1,43 @@ +defmodule Test.StateChart.W3.SelectingTransitions.Test421 do + use SC.Case + @tag :scxml_w3 + @tag conformance: "mandatory", spec: "SelectingTransitions" + test "test421" do + xml = """ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + """ + + description = + "If the set (of eventless transitions) is empty, the Processor MUST remove events from the internal event queue until the queue is empty or it finds an event that enables a non-empty optimal transition set in the current configuration. If it finds such a set [a non-empty optimal transition set], the processor MUST then execute it as a microstep." + + test_scxml(xml, description, ["pass"], []) + end +end diff --git a/test/scxml_tests/mandatory/SelectingTransitions/test422_test.exs b/test/scxml_tests/mandatory/SelectingTransitions/test422_test.exs new file mode 100644 index 0000000..b7f7d6f --- /dev/null +++ b/test/scxml_tests/mandatory/SelectingTransitions/test422_test.exs @@ -0,0 +1,86 @@ +defmodule Test.StateChart.W3.SelectingTransitions.Test422 do + use SC.Case + @tag :scxml_w3 + @tag conformance: "mandatory", spec: "SelectingTransitions" + test "test422" do + xml = """ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + """ + + description = + "After completing a macrostep, the SCXML Processor MUST execute in document order the invoke handlers in all states that have been entered (and not exited) since the completion of the last macrostep." + + test_scxml(xml, description, ["pass"], []) + end +end diff --git a/test/scxml_tests/mandatory/SelectingTransitions/test423_test.exs b/test/scxml_tests/mandatory/SelectingTransitions/test423_test.exs new file mode 100644 index 0000000..28e2057 --- /dev/null +++ b/test/scxml_tests/mandatory/SelectingTransitions/test423_test.exs @@ -0,0 +1,40 @@ +defmodule Test.StateChart.W3.SelectingTransitions.Test423 do + use SC.Case + @tag :scxml_w3 + @tag conformance: "mandatory", spec: "SelectingTransitions" + test "test423" do + xml = """ + + + + + + + + + + + + + + + + + + + + + + + + + + + """ + + description = + "Then [after invoking the new invoke handlers since the last macrostep] the Processor MUST remove events from the external event queue, waiting till events appear if necessary, until it finds one that enables a non-empty optimal transition set in the current configuration. The Processor MUST then execute that set [the enabled non-empty optimal transition set in the current configuration triggered by an external event] as a microstep." + + test_scxml(xml, description, ["pass"], []) + end +end diff --git a/test/scxml_tests/mandatory/SelectingTransitions/test503_test.exs b/test/scxml_tests/mandatory/SelectingTransitions/test503_test.exs new file mode 100644 index 0000000..8dbb992 --- /dev/null +++ b/test/scxml_tests/mandatory/SelectingTransitions/test503_test.exs @@ -0,0 +1,51 @@ +defmodule Test.StateChart.W3.SelectingTransitions.Test503 do + use SC.Case + @tag :scxml_w3 + @tag conformance: "mandatory", spec: "SelectingTransitions" + test "test503" do + xml = """ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + """ + + description = "If the transition does not contain a 'target', its exit set is empty." + + test_scxml(xml, description, ["pass"], []) + end +end diff --git a/test/scxml_tests/mandatory/SelectingTransitions/test504_test.exs b/test/scxml_tests/mandatory/SelectingTransitions/test504_test.exs new file mode 100644 index 0000000..2462c04 --- /dev/null +++ b/test/scxml_tests/mandatory/SelectingTransitions/test504_test.exs @@ -0,0 +1,84 @@ +defmodule Test.StateChart.W3.SelectingTransitions.Test504 do + use SC.Case + @tag :scxml_w3 + @tag conformance: "mandatory", spec: "SelectingTransitions" + test "test504" do + xml = """ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + """ + + description = + "if [a transition's] 'type' is \"external\", its exit set consists of all active states that are proper descendents of the Least Common Compound Ancestor (LCCA) of the source and target states. \n " + + test_scxml(xml, description, ["pass"], []) + end +end diff --git a/test/scxml_tests/mandatory/SelectingTransitions/test505_test.exs b/test/scxml_tests/mandatory/SelectingTransitions/test505_test.exs new file mode 100644 index 0000000..a3543c2 --- /dev/null +++ b/test/scxml_tests/mandatory/SelectingTransitions/test505_test.exs @@ -0,0 +1,60 @@ +defmodule Test.StateChart.W3.SelectingTransitions.Test505 do + use SC.Case + @tag :scxml_w3 + @tag conformance: "mandatory", spec: "SelectingTransitions" + test "test505" do + xml = """ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + """ + + description = + "Otherwise, if the transition has 'type' \"internal\", its source state is a compound state and all its target states are proper descendents of its source state, the target set consists of all active states that are proper descendents of its source state.\n " + + test_scxml(xml, description, ["pass"], []) + end +end diff --git a/test/scxml_tests/mandatory/SelectingTransitions/test506_test.exs b/test/scxml_tests/mandatory/SelectingTransitions/test506_test.exs new file mode 100644 index 0000000..4ae373c --- /dev/null +++ b/test/scxml_tests/mandatory/SelectingTransitions/test506_test.exs @@ -0,0 +1,63 @@ +defmodule Test.StateChart.W3.SelectingTransitions.Test506 do + use SC.Case + @tag :scxml_w3 + @tag conformance: "mandatory", spec: "SelectingTransitions" + test "test506" do + xml = """ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + """ + + description = + "If a transition has 'type' of \"internal\", but its source state is not a compound state or its target states are not all proper descendents of its source state, its exit set is defined as if it had 'type' of \"external\".\n " + + test_scxml(xml, description, ["pass"], []) + end +end diff --git a/test/scxml_tests/mandatory/SelectingTransitions/test533_test.exs b/test/scxml_tests/mandatory/SelectingTransitions/test533_test.exs new file mode 100644 index 0000000..ecbfb85 --- /dev/null +++ b/test/scxml_tests/mandatory/SelectingTransitions/test533_test.exs @@ -0,0 +1,73 @@ +defmodule Test.StateChart.W3.SelectingTransitions.Test533 do + use SC.Case + @tag :scxml_w3 + @tag conformance: "mandatory", spec: "SelectingTransitions" + test "test533" do + xml = """ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + """ + + description = + "If a transition has 'type' of \"internal\", but its source state is not a compound state, its exit set is defined as if it had 'type' of \"external\".\n " + + test_scxml(xml, description, ["pass"], []) + end +end diff --git a/test/scxml_tests/mandatory/data/test276_test.exs b/test/scxml_tests/mandatory/data/test276_test.exs new file mode 100644 index 0000000..14df2cb --- /dev/null +++ b/test/scxml_tests/mandatory/data/test276_test.exs @@ -0,0 +1,34 @@ +defmodule Test.StateChart.W3.Data.Test276 do + use SC.Case + @tag :scxml_w3 + @tag conformance: "mandatory", spec: "data" + test "test276" do + xml = """ + + + + + + + + + + + + + + + + + + + + + """ + + description = + "The SCXML Processor MUST allow the environment to provide values for top-level data elements at instantiation time. (Top-level data elements are those that are children of the datamodel element that is a child of scxml). Specifically, the Processor MUST use the values provided at instantiation time instead of those contained in these data elements." + + test_scxml(xml, description, ["pass"], []) + end +end diff --git a/test/scxml_tests/mandatory/data/test276sub1_test.exs b/test/scxml_tests/mandatory/data/test276sub1_test.exs new file mode 100644 index 0000000..b067c2f --- /dev/null +++ b/test/scxml_tests/mandatory/data/test276sub1_test.exs @@ -0,0 +1,29 @@ +defmodule Test.StateChart.W3.Data.Test276sub1 do + use SC.Case + @tag :scxml_w3 + @tag conformance: "mandatory", spec: "data" + test "test276sub1" do + xml = """ + + + + + + + + + + + + + + + + """ + + description = + "The SCXML Processor MUST allow the environment to provide values for top-level data elements at instantiation time. (Top-level data elements are those that are children of the datamodel element that is a child of scxml). Specifically, the Processor MUST use the values provided at instantiation time instead of those contained in these data elements." + + test_scxml(xml, description, ["pass"], []) + end +end diff --git a/test/scxml_tests/mandatory/data/test277_test.exs b/test/scxml_tests/mandatory/data/test277_test.exs new file mode 100644 index 0000000..4cfecf7 --- /dev/null +++ b/test/scxml_tests/mandatory/data/test277_test.exs @@ -0,0 +1,44 @@ +defmodule Test.StateChart.W3.Data.Test277 do + use SC.Case + @tag :scxml_w3 + @tag conformance: "mandatory", spec: "data" + test "test277" do + xml = """ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + """ + + description = + "If the value specified for a data element (by 'src', children, or the environment) is not a legal data value, the SCXML Processor MUST raise place error.execution in the internal event queue and MUST create an empty data element in the data model with the specified id." + + test_scxml(xml, description, ["pass"], []) + end +end diff --git a/test/scxml_tests/mandatory/data/test279_test.exs b/test/scxml_tests/mandatory/data/test279_test.exs new file mode 100644 index 0000000..bcbba42 --- /dev/null +++ b/test/scxml_tests/mandatory/data/test279_test.exs @@ -0,0 +1,37 @@ +defmodule Test.StateChart.W3.Data.Test279 do + use SC.Case + @tag :scxml_w3 + @tag conformance: "mandatory", spec: "data" + test "test279" do + xml = """ + + + + + + + + + + + + + + + + + + + + + + + + """ + + description = + "When 'binding' attribute on the scxml element is assigned the value \"early\" (the default), the SCXML Processor MUST create all data elements and assign their initial values at document initialization time.\n " + + test_scxml(xml, description, ["pass"], []) + end +end diff --git a/test/scxml_tests/mandatory/data/test280_test.exs b/test/scxml_tests/mandatory/data/test280_test.exs new file mode 100644 index 0000000..52026e3 --- /dev/null +++ b/test/scxml_tests/mandatory/data/test280_test.exs @@ -0,0 +1,45 @@ +defmodule Test.StateChart.W3.Data.Test280 do + use SC.Case + @tag :scxml_w3 + @tag conformance: "mandatory", spec: "data" + test "test280" do + xml = """ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + """ + + description = + "When 'binding' attribute on the scxml element is assigned the value \"late\", the SCXML Processor MUST create the data elements at document initialization time, but MUST assign the specified initial value to a given data element only when the state that contains it is entered for the first time, before any onentry markup.\n " + + test_scxml(xml, description, ["pass"], []) + end +end diff --git a/test/scxml_tests/mandatory/data/test550_test.exs b/test/scxml_tests/mandatory/data/test550_test.exs new file mode 100644 index 0000000..f781c5d --- /dev/null +++ b/test/scxml_tests/mandatory/data/test550_test.exs @@ -0,0 +1,36 @@ +defmodule Test.StateChart.W3.Data.Test550 do + use SC.Case + @tag :scxml_w3 + @tag conformance: "mandatory", spec: "data" + test "test550" do + xml = """ + + + + + + + + + + + + + + + + + + + + + + + """ + + description = + "If the 'expr' attribute is present, the Platform MUST evaluate the corresponding expression at the time specified by the 'binding' attribute of scxml and MUST assign the resulting value as the value of the data element" + + test_scxml(xml, description, ["pass"], []) + end +end diff --git a/test/scxml_tests/mandatory/data/test551_test.exs b/test/scxml_tests/mandatory/data/test551_test.exs new file mode 100644 index 0000000..03f1619 --- /dev/null +++ b/test/scxml_tests/mandatory/data/test551_test.exs @@ -0,0 +1,38 @@ +defmodule Test.StateChart.W3.Data.Test551 do + use SC.Case + @tag :scxml_w3 + @tag conformance: "mandatory", spec: "data" + test "test551" do + xml = """ + + + + + + + + + + [1,2,3] + + + + + + + + + + + + + + + """ + + description = + "f child content is specified, the Platform MUST assign it as the value of the data element at the time specified by the 'binding' attribute of scxml." + + test_scxml(xml, description, ["pass"], []) + end +end diff --git a/test/scxml_tests/mandatory/events/test396_test.exs b/test/scxml_tests/mandatory/events/test396_test.exs new file mode 100644 index 0000000..e71fb9a --- /dev/null +++ b/test/scxml_tests/mandatory/events/test396_test.exs @@ -0,0 +1,34 @@ +defmodule Test.StateChart.W3.Events.Test396 do + use SC.Case + @tag :scxml_w3 + @tag conformance: "mandatory", spec: "events" + test "test396" do + xml = """ + + + + + + + + + + + + + + + + + + + + + """ + + description = + "The SCXML processor MUST use this same name value [the one reflected in the event variable] to match against the 'event' attribute of transitions." + + test_scxml(xml, description, ["pass"], []) + end +end diff --git a/test/scxml_tests/mandatory/events/test399_test.exs b/test/scxml_tests/mandatory/events/test399_test.exs new file mode 100644 index 0000000..1490155 --- /dev/null +++ b/test/scxml_tests/mandatory/events/test399_test.exs @@ -0,0 +1,70 @@ +defmodule Test.StateChart.W3.Events.Test399 do + use SC.Case + @tag :scxml_w3 + @tag conformance: "mandatory", spec: "events" + test "test399" do + xml = """ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + """ + + description = + "[Definition: A transition matches an event if at least one of its event descriptors matches the event's name. ] [Definition: An event descriptor matches an event name if its string of tokens is an exact match or a prefix of the set of tokens in the event's name. In all cases, the token matching is case sensitive. ]" + + test_scxml(xml, description, ["pass"], []) + end +end diff --git a/test/scxml_tests/mandatory/events/test401_test.exs b/test/scxml_tests/mandatory/events/test401_test.exs new file mode 100644 index 0000000..940cacd --- /dev/null +++ b/test/scxml_tests/mandatory/events/test401_test.exs @@ -0,0 +1,34 @@ +defmodule Test.StateChart.W3.Events.Test401 do + use SC.Case + @tag :scxml_w3 + @tag conformance: "mandatory", spec: "events" + test "test401" do + xml = """ + + + + + + + + + + + + + + + + + + + + + + """ + + description = "The processor MUST place these [error] events in the internal event queue." + + test_scxml(xml, description, ["pass"], []) + end +end diff --git a/test/scxml_tests/mandatory/events/test402_test.exs b/test/scxml_tests/mandatory/events/test402_test.exs new file mode 100644 index 0000000..85361b7 --- /dev/null +++ b/test/scxml_tests/mandatory/events/test402_test.exs @@ -0,0 +1,50 @@ +defmodule Test.StateChart.W3.Events.Test402 do + use SC.Case + @tag :scxml_w3 + @tag conformance: "mandatory", spec: "events" + test "test402" do + xml = """ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + """ + + description = "The processor MUST process them [error events] like any other event." + + test_scxml(xml, description, ["pass"], []) + end +end diff --git a/test/scxml_tests/mandatory/final/test372_test.exs b/test/scxml_tests/mandatory/final/test372_test.exs new file mode 100644 index 0000000..92c4985 --- /dev/null +++ b/test/scxml_tests/mandatory/final/test372_test.exs @@ -0,0 +1,45 @@ +defmodule Test.StateChart.W3.Final.Test372 do + use SC.Case + @tag :scxml_w3 + @tag conformance: "mandatory", spec: "final" + test "test372" do + xml = """ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + """ + + description = + "When the state machine enters the final child of a state element, the SCXML processor MUST generate the event done.state.id after completion of the onentry elements, where id is the id of the parent state." + + test_scxml(xml, description, ["pass"], []) + end +end diff --git a/test/scxml_tests/mandatory/final/test570_test.exs b/test/scxml_tests/mandatory/final/test570_test.exs new file mode 100644 index 0000000..9a53822 --- /dev/null +++ b/test/scxml_tests/mandatory/final/test570_test.exs @@ -0,0 +1,58 @@ +defmodule Test.StateChart.W3.Final.Test570 do + use SC.Case + @tag :scxml_w3 + @tag conformance: "mandatory", spec: "final" + test "test570" do + xml = """ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + """ + + description = + "Immediately after generating done.state.id upon entering a final child of state, if the parent state is a child of a parallel element, and all of the parallel's other children are also in final states, the Processor MUST generate the event done.state.id where id is the id of the parallel element." + + test_scxml(xml, description, ["pass"], []) + end +end diff --git a/test/scxml_tests/mandatory/foreach/test150_test.exs b/test/scxml_tests/mandatory/foreach/test150_test.exs new file mode 100644 index 0000000..e59c0bd --- /dev/null +++ b/test/scxml_tests/mandatory/foreach/test150_test.exs @@ -0,0 +1,54 @@ +defmodule Test.StateChart.W3.Foreach.Test150 do + use SC.Case + @tag :scxml_w3 + @tag conformance: "mandatory", spec: "foreach" + test "test150" do + xml = """ + + + + + + + [1,2,3] + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + """ + + description = + "In the foreach element, the SCXML processor MUST declare a new variable if the one specified by 'item' is not already defined." + + test_scxml(xml, description, ["pass"], []) + end +end diff --git a/test/scxml_tests/mandatory/foreach/test151_test.exs b/test/scxml_tests/mandatory/foreach/test151_test.exs new file mode 100644 index 0000000..0639ad1 --- /dev/null +++ b/test/scxml_tests/mandatory/foreach/test151_test.exs @@ -0,0 +1,54 @@ +defmodule Test.StateChart.W3.Foreach.Test151 do + use SC.Case + @tag :scxml_w3 + @tag conformance: "mandatory", spec: "foreach" + test "test151" do + xml = """ + + + + + + + [1,2,3] + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + """ + + description = + "In the foreach element, if 'index' is present, the SCXML processor MUST declare a new variable if the one specified by 'index' is not already defined." + + test_scxml(xml, description, ["pass"], []) + end +end diff --git a/test/scxml_tests/mandatory/foreach/test152_test.exs b/test/scxml_tests/mandatory/foreach/test152_test.exs new file mode 100644 index 0000000..bc78ee2 --- /dev/null +++ b/test/scxml_tests/mandatory/foreach/test152_test.exs @@ -0,0 +1,60 @@ +defmodule Test.StateChart.W3.Foreach.Test152 do + use SC.Case + @tag :scxml_w3 + @tag conformance: "mandatory", spec: "foreach" + test "test152" do + xml = """ + + + + + + + + + [1,2,3] + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + """ + + description = + "In the foreach element, if 'array' does not evaluate to a legal iterable collection, or if 'item' does not specify a legal variable name, the SCXML processor MUST terminate execution of the foreach element and the block that contains it, and place the error error.execution on the internal event queue." + + test_scxml(xml, description, ["pass"], []) + end +end diff --git a/test/scxml_tests/mandatory/foreach/test153_test.exs b/test/scxml_tests/mandatory/foreach/test153_test.exs new file mode 100644 index 0000000..12aabf9 --- /dev/null +++ b/test/scxml_tests/mandatory/foreach/test153_test.exs @@ -0,0 +1,48 @@ +defmodule Test.StateChart.W3.Foreach.Test153 do + use SC.Case + @tag :scxml_w3 + @tag conformance: "mandatory", spec: "foreach" + test "test153" do + xml = """ + + + + + + + [1,2,3] + + + + + + + + + + + + + + + + + + + + + + + + + + + + """ + + description = + "When evaluating foreach, the SCXML processor MUST start with the first item in the collection and proceed to the last item in the iteration order that is defined for the collection. For each item in the collection in turn, the processor MUST assign it to the item variable." + + test_scxml(xml, description, ["pass"], []) + end +end diff --git a/test/scxml_tests/mandatory/foreach/test155_test.exs b/test/scxml_tests/mandatory/foreach/test155_test.exs new file mode 100644 index 0000000..ac11816 --- /dev/null +++ b/test/scxml_tests/mandatory/foreach/test155_test.exs @@ -0,0 +1,43 @@ +defmodule Test.StateChart.W3.Foreach.Test155 do + use SC.Case + @tag :scxml_w3 + @tag conformance: "mandatory", spec: "foreach" + test "test155" do + xml = """ + + + + + + + [1,2,3] + + + + + + + + + + + + + + + + + + + + + + + """ + + description = + "when evaluating foreach, for each item, after making the assignment, the SCXML processor MUST evaluate its child executable content. It MUST then proceed to the next item in iteration order." + + test_scxml(xml, description, ["pass"], []) + end +end diff --git a/test/scxml_tests/mandatory/foreach/test156_test.exs b/test/scxml_tests/mandatory/foreach/test156_test.exs new file mode 100644 index 0000000..2a77fb8 --- /dev/null +++ b/test/scxml_tests/mandatory/foreach/test156_test.exs @@ -0,0 +1,44 @@ +defmodule Test.StateChart.W3.Foreach.Test156 do + use SC.Case + @tag :scxml_w3 + @tag conformance: "mandatory", spec: "foreach" + test "test156" do + xml = """ + + + + + + + [1,2,3] + + + + + + + + + + + + + + + + + + + + + + + + """ + + description = + "If the evaluation of any child element of foreach causes an error, the processor MUST cease execution of the foreach element and the block that contains it." + + test_scxml(xml, description, ["pass"], []) + end +end diff --git a/test/scxml_tests/mandatory/foreach/test525_test.exs b/test/scxml_tests/mandatory/foreach/test525_test.exs new file mode 100644 index 0000000..df37bd1 --- /dev/null +++ b/test/scxml_tests/mandatory/foreach/test525_test.exs @@ -0,0 +1,43 @@ +defmodule Test.StateChart.W3.Foreach.Test525 do + use SC.Case + @tag :scxml_w3 + @tag conformance: "mandatory", spec: "foreach" + test "test525" do + xml = """ + + + + + [1,2,3] + + + + + + + + + + + + + + + + + + + + + + + + + """ + + description = + "The SCXML processor MUST act as if it has made a shallow copy of the collection produced by the evaluation of 'array'. Specifically, modifications to the collection during the execution of foreach MUST NOT affect the iteration behavior." + + test_scxml(xml, description, ["pass"], []) + end +end diff --git a/test/scxml_tests/mandatory/history/test387_test.exs b/test/scxml_tests/mandatory/history/test387_test.exs new file mode 100644 index 0000000..d4a6f50 --- /dev/null +++ b/test/scxml_tests/mandatory/history/test387_test.exs @@ -0,0 +1,104 @@ +defmodule Test.StateChart.W3.History.Test387 do + use SC.Case + @tag :scxml_w3 + @tag conformance: "mandatory", spec: "history" + test "test387" do + xml = """ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + """ + + description = + "Before the parent state has been visited for the first time, if a transition is executed that takes the history state as its target, the SCXML processor MUST behave as if the transition had taken the default stored state configuration as its target." + + test_scxml(xml, description, ["pass"], []) + end +end diff --git a/test/scxml_tests/mandatory/history/test388_test.exs b/test/scxml_tests/mandatory/history/test388_test.exs new file mode 100644 index 0000000..e5fcb18 --- /dev/null +++ b/test/scxml_tests/mandatory/history/test388_test.exs @@ -0,0 +1,79 @@ +defmodule Test.StateChart.W3.History.Test388 do + use SC.Case + @tag :scxml_w3 + @tag conformance: "mandatory", spec: "history" + test "test388" do + xml = """ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + """ + + description = + "After the parent state has been visited for the first time, if a transition is executed that takes the history state as its target, the SCXML processor MUST behave as if the transition had taken the stored state configuration as its target." + + test_scxml(xml, description, ["pass"], []) + end +end diff --git a/test/scxml_tests/mandatory/history/test579_test.exs b/test/scxml_tests/mandatory/history/test579_test.exs new file mode 100644 index 0000000..d75f227 --- /dev/null +++ b/test/scxml_tests/mandatory/history/test579_test.exs @@ -0,0 +1,74 @@ +defmodule Test.StateChart.W3.History.Test579 do + use SC.Case + @tag :scxml_w3 + @tag conformance: "mandatory", spec: "history" + test "test579" do + xml = """ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + """ + + description = + "Before the parent state has been visited for the first time, if a transition is executed that takes the history state as its target, the SCXML processor MUST execute any executable content in the transition after the parent state's onentry content and any content in a possible initial transition." + + test_scxml(xml, description, ["pass"], []) + end +end diff --git a/test/scxml_tests/mandatory/history/test580_test.exs b/test/scxml_tests/mandatory/history/test580_test.exs new file mode 100644 index 0000000..e754776 --- /dev/null +++ b/test/scxml_tests/mandatory/history/test580_test.exs @@ -0,0 +1,61 @@ +defmodule Test.StateChart.W3.History.Test580 do + use SC.Case + @tag :scxml_w3 + @tag conformance: "mandatory", spec: "history" + test "test580" do + xml = """ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + """ + + description = + "It follows from the semantics of history states that they never end up in the state configuration" + + test_scxml(xml, description, ["pass"], []) + end +end diff --git a/test/scxml_tests/mandatory/if/test147_test.exs b/test/scxml_tests/mandatory/if/test147_test.exs new file mode 100644 index 0000000..be9bb61 --- /dev/null +++ b/test/scxml_tests/mandatory/if/test147_test.exs @@ -0,0 +1,47 @@ +defmodule Test.StateChart.W3.If.Test147 do + use SC.Case + @tag :scxml_w3 + @tag conformance: "mandatory", spec: "if" + test "test147" do + xml = """ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + """ + + description = + "When the if element is executed, the SCXML processor MUST execute the first partition in document order that is defined by a tag whose 'cond' attribute evaluates to true, if there is one." + + test_scxml(xml, description, ["pass"], []) + end +end diff --git a/test/scxml_tests/mandatory/if/test148_test.exs b/test/scxml_tests/mandatory/if/test148_test.exs new file mode 100644 index 0000000..91822b8 --- /dev/null +++ b/test/scxml_tests/mandatory/if/test148_test.exs @@ -0,0 +1,47 @@ +defmodule Test.StateChart.W3.If.Test148 do + use SC.Case + @tag :scxml_w3 + @tag conformance: "mandatory", spec: "if" + test "test148" do + xml = """ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + """ + + description = + "When the if element is executed, if no 'cond'attribute evaluates to true, the SCXML Processor must execute the partition defined by the else tag, if there is one." + + test_scxml(xml, description, ["pass"], []) + end +end diff --git a/test/scxml_tests/mandatory/if/test149_test.exs b/test/scxml_tests/mandatory/if/test149_test.exs new file mode 100644 index 0000000..675e8eb --- /dev/null +++ b/test/scxml_tests/mandatory/if/test149_test.exs @@ -0,0 +1,44 @@ +defmodule Test.StateChart.W3.If.Test149 do + use SC.Case + @tag :scxml_w3 + @tag conformance: "mandatory", spec: "if" + test "test149" do + xml = """ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + """ + + description = + "When it executes an if element, if no 'cond' attribute evaluates to true and there is no else element, the SCXML processor must not evaluate any executable content within the element." + + test_scxml(xml, description, ["pass"], []) + end +end diff --git a/test/scxml_tests/mandatory/onentry/test375_test.exs b/test/scxml_tests/mandatory/onentry/test375_test.exs new file mode 100644 index 0000000..3e09a3f --- /dev/null +++ b/test/scxml_tests/mandatory/onentry/test375_test.exs @@ -0,0 +1,41 @@ +defmodule Test.StateChart.W3.Onentry.Test375 do + use SC.Case + @tag :scxml_w3 + @tag conformance: "mandatory", spec: "onentry" + test "test375" do + xml = """ + + + + + + + + + + + + + + + + + + + + + + + + + + + + """ + + description = + "The SCXML processor MUST execute the onentry handlers of a state in document order when the state is entered." + + test_scxml(xml, description, ["pass"], []) + end +end diff --git a/test/scxml_tests/mandatory/onentry/test376_test.exs b/test/scxml_tests/mandatory/onentry/test376_test.exs new file mode 100644 index 0000000..81a00b4 --- /dev/null +++ b/test/scxml_tests/mandatory/onentry/test376_test.exs @@ -0,0 +1,40 @@ +defmodule Test.StateChart.W3.Onentry.Test376 do + use SC.Case + @tag :scxml_w3 + @tag conformance: "mandatory", spec: "onentry" + test "test376" do + xml = """ + + + + + + + + + + + + + + + + + + + + + + + + + + + """ + + description = + "The SCXML processor MUST treat each [onentry] handler as a separate block of executable content." + + test_scxml(xml, description, ["pass"], []) + end +end diff --git a/test/scxml_tests/mandatory/onexit/test377_test.exs b/test/scxml_tests/mandatory/onexit/test377_test.exs new file mode 100644 index 0000000..715df09 --- /dev/null +++ b/test/scxml_tests/mandatory/onexit/test377_test.exs @@ -0,0 +1,44 @@ +defmodule Test.StateChart.W3.Onexit.Test377 do + use SC.Case + @tag :scxml_w3 + @tag conformance: "mandatory", spec: "onexit" + test "test377" do + xml = """ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + """ + + description = + "The SCXML processor MUST execute the onexit handlers of a state in document order when the state is exited." + + test_scxml(xml, description, ["pass"], []) + end +end diff --git a/test/scxml_tests/mandatory/onexit/test378_test.exs b/test/scxml_tests/mandatory/onexit/test378_test.exs new file mode 100644 index 0000000..dcbc570 --- /dev/null +++ b/test/scxml_tests/mandatory/onexit/test378_test.exs @@ -0,0 +1,43 @@ +defmodule Test.StateChart.W3.Onexit.Test378 do + use SC.Case + @tag :scxml_w3 + @tag conformance: "mandatory", spec: "onexit" + test "test378" do + xml = """ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + """ + + description = + "The SCXML processor MUST treat each [onexit] handler as a separate block of executable content." + + test_scxml(xml, description, ["pass"], []) + end +end diff --git a/test/scxml_tests/mandatory/raise/test144_test.exs b/test/scxml_tests/mandatory/raise/test144_test.exs new file mode 100644 index 0000000..29506e9 --- /dev/null +++ b/test/scxml_tests/mandatory/raise/test144_test.exs @@ -0,0 +1,39 @@ +defmodule Test.StateChart.W3.Raise.Test144 do + use SC.Case + @tag :scxml_w3 + @tag conformance: "mandatory", spec: "raise" + test "test144" do + xml = """ + + + + + + + + + + + + + + + + + + + + + + + + + + """ + + description = + "The SCXML processor MUST place the event that is generated by the raise element at the rear of the session's internal event queue." + + test_scxml(xml, description, ["pass"], []) + end +end diff --git a/test/scxml_tests/mandatory/scxml/test355_test.exs b/test/scxml_tests/mandatory/scxml/test355_test.exs new file mode 100644 index 0000000..7db1f86 --- /dev/null +++ b/test/scxml_tests/mandatory/scxml/test355_test.exs @@ -0,0 +1,33 @@ +defmodule Test.StateChart.W3.Scxml.Test355 do + use SC.Case + @tag :scxml_w3 + @tag conformance: "mandatory", spec: "scxml" + test "test355" do + xml = """ + + + + + + + + + + + + + + + + + + + + """ + + description = + "At system initialization time, if the 'initial' attribute is not present, the Processor MUST enter the first state in document order." + + test_scxml(xml, description, ["pass"], []) + end +end diff --git a/test/scxml_tests/mandatory/scxml/test576_test.exs b/test/scxml_tests/mandatory/scxml/test576_test.exs new file mode 100644 index 0000000..5adde1a --- /dev/null +++ b/test/scxml_tests/mandatory/scxml/test576_test.exs @@ -0,0 +1,55 @@ +defmodule Test.StateChart.W3.Scxml.Test576 do + use SC.Case + @tag :scxml_w3 + @tag conformance: "mandatory", spec: "scxml" + test "test576" do + xml = """ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + """ + + description = + "At system initialization time, the SCXML Processor MUST enter the states specified by the 'initial' attribute, if it is present." + + test_scxml(xml, description, ["pass"], []) + end +end diff --git a/test/scxml_tests/mandatory/state/test364_test.exs b/test/scxml_tests/mandatory/state/test364_test.exs new file mode 100644 index 0000000..ef9b134 --- /dev/null +++ b/test/scxml_tests/mandatory/state/test364_test.exs @@ -0,0 +1,90 @@ +defmodule Test.StateChart.W3.State.Test364 do + use SC.Case + @tag :scxml_w3 + @tag conformance: "mandatory", spec: "state" + test "test364" do + xml = """ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + """ + + description = + "Definition: The default initial state(s) of a compound state are those specified by the 'initial' attribute or initial element, if either is present. Otherwise it is the state's first child state in document order. If a compound state is entered either as an initial state or as the target of a transition (i.e. and no descendent of it is specified), then the SCXML Processor MUST enter the default initial state(s) after it enters the parent state." + + test_scxml(xml, description, ["pass"], []) + end +end diff --git a/test/support/sc_case.ex b/test/support/sc_case.ex new file mode 100644 index 0000000..3e2e003 --- /dev/null +++ b/test/support/sc_case.ex @@ -0,0 +1,54 @@ +defmodule SC.Case do + # alias StateChart.{Configuration,Event} + use ExUnit.CaseTemplate, async: true + + using do + quote do + import unquote(__MODULE__) + end + end + + def test_scxml(_xml, _description, _conf, _events) do + IO.puts("TODO: need to implement") + # datamodels = %{ + # "ecmascript" => StateChart.DataModel.ECMA, + # "elixir" => StateChart.DataModel.Elixir, + # "null" => StateChart.DataModel.Null + # } + # + # opts = %{datamodels: datamodels} + # + # doc = StateChart.SCXML.parse(xml, opts) + # context = %{} + # + # StateChart.interpret(doc, context) + # # TODO + # |> loop(conf, events) + end + + # defp loop({:await, int, context}, conf, [{event, next} | events]) do + # assert_configuration(int, conf) + # StateChart.handle_event(int, event, context) + # |> loop(next, events) + # end + # defp loop({:await, int, _context}, conf, []) do + # assert_configuration(int, conf) + # assert false, "End of events and not done" + # end + # defp loop({:done, int, _context}, conf, []) do + # assert_configuration(int, conf) + # :ok + # end + # defp loop({:done, int, _context}, conf, events) do + # assert_configuration(int, conf) + # expected = [] + # actual = Enum.map(events, fn({event, _}) -> Event.new(event) end) + # assert expected == actual + # end + # + # defp assert_configuration(int, expected) do + # expected = MapSet.new(expected) + # actual = Configuration.active_states(int) + # assert expected == actual + # end +end From 64c52e02b86697afc0759132f89405cdc23c2143 Mon Sep 17 00:00:00 2001 From: JohnnyT Date: Fri, 15 Aug 2025 20:42:27 -0600 Subject: [PATCH 03/18] Add Claude --- .gitignore | 3 ++ CLAUDE.md | 118 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 121 insertions(+) create mode 100644 CLAUDE.md diff --git a/.gitignore b/.gitignore index 5efb632..f091fca 100644 --- a/.gitignore +++ b/.gitignore @@ -21,3 +21,6 @@ sc-*.tar # Temporary files, for example, from tests. /tmp/ + +# Keep granted permissions local to the person +.claude diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..4c6f80c --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,118 @@ +# CLAUDE.md + +This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. + +## Commands + +**Testing:** +- `mix test` - Run all tests +- `mix test test/sc/parser/scxml_test.exs` - Run specific SCXML parser tests + +**Development:** +- `mix deps.get` - Install dependencies +- `mix compile` - Compile the project +- `mix docs` - Generate documentation +- `mix credo` - Run static code analysis +- `mix test --cover` - Run tests with coverage using ExCoveralls +- `mix format` - Format code according to Elixir standards +- `mix format --check-formatted` - Check if code is properly formatted + +## Architecture + +This is an Elixir implementation of SCXML (State Chart XML) state machines with a focus on W3C compliance. + +The State Chart reference XML is here: https://www.w3.org/TR/scxml/ + +This project uses Elixir Structs for the data structures, and MapSets for sets. + +Also use this initial Elixir implementation as reference: https://github.com/camshaft/ex_statechart + +## Core Components + +### Data Structures +- **`SC.Document`** - Root SCXML document structure with attributes like `name`, `initial`, `datamodel`, `version`, `xmlns`, plus collections of `states` and `datamodel_elements` +- **`SC.State`** - Individual state with `id`, optional `initial` state, nested `states` list, and `transitions` list +- **`SC.Transition`** - State transitions with optional `event`, `target`, and `cond` attributes +- **`SC.DataElement`** - Datamodel elements with required `id` and optional `expr` and `src` attributes + +### Parsers +- **`SC.Parser.SCXML`** - Main SCXML parser using SweetXml library + - Parses XML strings into `SC.Document` structs + - Handles namespace declarations (custom xmlns extraction) + - Supports nested states and hierarchical structures + - Converts empty XML attributes to `nil` for cleaner data representation + - Returns `{:ok, document}` or `{:error, reason}` tuples + +### Test Infrastructure +- **`SC.Case`** - Test case template module for SCXML testing + - Provides `test_scxml/4` function for testing state machine behavior + - Used by both SCION and W3C test suites + +## Dependencies + +- **`sweet_xml`** (~> 0.7) - XML parsing library built on `:xmerl` with Elixir-friendly API + +## Tests + +This project includes comprehensive test coverage: + +### SCION Test Suite (`test/scion_tests/`) +- 127+ test files from the SCION project +- Module naming: `SCIONTest.Category.TestNameTest` (e.g., `SCIONTest.ActionSend.Send1Test`) +- Uses `SC.Case` for test infrastructure +- Tests cover basic state machines, transitions, parallel states, history, etc. + +### W3C SCXML Test Suite (`test/scxml_tests/`) +- 59+ test files from W3C SCXML conformance tests +- Module naming: `Test.StateChart.W3.Category.TestName` (e.g., `Test.StateChart.W3.Events.Test396`) +- Uses `SC.Case` for test infrastructure +- Organized by SCXML specification sections (mandatory tests) + +### Parser Tests (`test/sc/parser/scxml_test.exs`) +- Unit tests for `SC.Parser.SCXML` +- Tests parsing of simple documents, transitions, datamodels, nested states +- Validates error handling for invalid XML +- Ensures proper attribute handling (nil for empty values) + +## Code Style + +- All generated files have no trailing whitespace +- Code is formatted using `mix format` +- Type specs are provided for all public structs +- Comprehensive documentation with `@moduledoc` and `@doc` + +## XML Format + +Test files use triple-quote multiline strings for XML content: + +```elixir +xml = """ + + + + +""" +``` + +XML content within triple quotes uses 4-space base indentation. + +## Implementation Status + +✅ **Completed:** +- Core data structures (Document, State, Transition, DataElement) +- Basic SCXML parser with SweetXml +- Comprehensive test suite integration (SCION + W3C) +- Test infrastructure with SC.Case module +- XML parsing with namespace support +- Error handling for malformed XML + +🚧 **Future Extensions:** +- More executable content elements (``, ``, ``, ``) +- Parallel states (``) +- Final states (``) +- History states (``) +- Additional transition attributes (`type`) +- Script elements and datamodel evaluation +- State machine interpreter/runtime engine + +The implementation follows the W3C SCXML specification closely and includes comprehensive test coverage from both W3C and SCION test suites. From 1398022289d2517f319ef6338677195d266708f9 Mon Sep 17 00:00:00 2001 From: JohnnyT Date: Fri, 15 Aug 2025 20:43:08 -0600 Subject: [PATCH 04/18] Adds initial SCXML parser using SweetXml --- lib/sc/data_element.ex | 17 +++++ lib/sc/document.ex | 25 ++++++ lib/sc/parser/scxml.ex | 79 +++++++++++++++++++ lib/sc/state.ex | 19 +++++ lib/sc/transition.ex | 17 +++++ mix.exs | 3 +- mix.lock | 3 + test/sc/parser/scxml_test.exs | 139 ++++++++++++++++++++++++++++++++++ 8 files changed, 300 insertions(+), 2 deletions(-) create mode 100644 lib/sc/data_element.ex create mode 100644 lib/sc/document.ex create mode 100644 lib/sc/parser/scxml.ex create mode 100644 lib/sc/state.ex create mode 100644 lib/sc/transition.ex create mode 100644 mix.lock create mode 100644 test/sc/parser/scxml_test.exs diff --git a/lib/sc/data_element.ex b/lib/sc/data_element.ex new file mode 100644 index 0000000..9be8ef7 --- /dev/null +++ b/lib/sc/data_element.ex @@ -0,0 +1,17 @@ +defmodule SC.DataElement do + @moduledoc """ + Represents a data element in an SCXML datamodel. + """ + + defstruct [ + :id, + :expr, + :src + ] + + @type t :: %__MODULE__{ + id: String.t(), + expr: String.t() | nil, + src: String.t() | nil + } +end diff --git a/lib/sc/document.ex b/lib/sc/document.ex new file mode 100644 index 0000000..e6a5116 --- /dev/null +++ b/lib/sc/document.ex @@ -0,0 +1,25 @@ +defmodule SC.Document do + @moduledoc """ + Represents a parsed SCXML document. + """ + + defstruct [ + :name, + :initial, + :datamodel, + :version, + :xmlns, + states: [], + datamodel_elements: [] + ] + + @type t :: %__MODULE__{ + name: String.t() | nil, + initial: String.t() | nil, + datamodel: String.t() | nil, + version: String.t() | nil, + xmlns: String.t() | nil, + states: [SC.State.t()], + datamodel_elements: [SC.DataElement.t()] + } +end diff --git a/lib/sc/parser/scxml.ex b/lib/sc/parser/scxml.ex new file mode 100644 index 0000000..f1934f1 --- /dev/null +++ b/lib/sc/parser/scxml.ex @@ -0,0 +1,79 @@ +defmodule SC.Parser.SCXML do + @moduledoc """ + Parser for SCXML documents using SweetXml. + """ + + import SweetXml + + @doc """ + Parse an SCXML string into an SC.Document struct. + """ + @spec parse(String.t()) :: {:ok, SC.Document.t()} | {:error, term()} + def parse(xml_string) do + try do + document = + xml_string + |> xpath(~x"//scxml"e) + |> parse_scxml() + + {:ok, document} + rescue + error -> {:error, error} + catch + :exit, reason -> {:error, reason} + end + end + + defp parse_scxml(scxml_element) do + %SC.Document{ + name: scxml_element |> xpath(~x"./@name"s) |> empty_to_nil(), + initial: scxml_element |> xpath(~x"./@initial"s) |> empty_to_nil(), + datamodel: scxml_element |> xpath(~x"./@datamodel"s) |> empty_to_nil(), + version: scxml_element |> xpath(~x"./@version"s) |> empty_to_nil(), + xmlns: extract_xmlns(scxml_element), + states: scxml_element |> xpath(~x"./state"el) |> Enum.map(&parse_state/1), + datamodel_elements: + scxml_element |> xpath(~x"./datamodel/data"el) |> Enum.map(&parse_data_element/1) + } + end + + defp parse_state(state_element) do + %SC.State{ + id: state_element |> xpath(~x"./@id"s), + initial: state_element |> xpath(~x"./@initial"s) |> empty_to_nil(), + states: state_element |> xpath(~x"./state"el) |> Enum.map(&parse_state/1), + transitions: state_element |> xpath(~x"./transition"el) |> Enum.map(&parse_transition/1) + } + end + + defp parse_transition(transition_element) do + %SC.Transition{ + event: transition_element |> xpath(~x"./@event"s) |> empty_to_nil(), + target: transition_element |> xpath(~x"./@target"s) |> empty_to_nil(), + cond: transition_element |> xpath(~x"./@cond"s) |> empty_to_nil() + } + end + + defp parse_data_element(data_element) do + %SC.DataElement{ + id: data_element |> xpath(~x"./@id"s), + expr: data_element |> xpath(~x"./@expr"s) |> empty_to_nil(), + src: data_element |> xpath(~x"./@src"s) |> empty_to_nil() + } + end + + # Extract xmlns from raw XML element since SweetXml doesn't handle it well + defp extract_xmlns({:xmlElement, _, _, _, _, _, _, attributes, _, _, _, _}) do + case Enum.find(attributes, fn + {:xmlAttribute, :xmlns, _, _, _, _, _, _, _value, _} -> true + _ -> false + end) do + {:xmlAttribute, :xmlns, _, _, _, _, _, _, value, _} -> to_string(value) + nil -> nil + end + end + + # Helper to convert empty strings to nil + defp empty_to_nil(""), do: nil + defp empty_to_nil(value), do: value +end diff --git a/lib/sc/state.ex b/lib/sc/state.ex new file mode 100644 index 0000000..6dceb39 --- /dev/null +++ b/lib/sc/state.ex @@ -0,0 +1,19 @@ +defmodule SC.State do + @moduledoc """ + Represents a state in an SCXML document. + """ + + defstruct [ + :id, + :initial, + states: [], + transitions: [] + ] + + @type t :: %__MODULE__{ + id: String.t(), + initial: String.t() | nil, + states: [SC.State.t()], + transitions: [SC.Transition.t()] + } +end diff --git a/lib/sc/transition.ex b/lib/sc/transition.ex new file mode 100644 index 0000000..11e205b --- /dev/null +++ b/lib/sc/transition.ex @@ -0,0 +1,17 @@ +defmodule SC.Transition do + @moduledoc """ + Represents a transition in an SCXML state. + """ + + defstruct [ + :event, + :target, + :cond + ] + + @type t :: %__MODULE__{ + event: String.t() | nil, + target: String.t() | nil, + cond: String.t() | nil + } +end diff --git a/mix.exs b/mix.exs index 0b3e0a8..89c400f 100644 --- a/mix.exs +++ b/mix.exs @@ -25,8 +25,7 @@ defmodule SC.MixProject do # Run "mix help deps" to learn about dependencies. defp deps do [ - # {:dep_from_hexpm, "~> 0.3.0"}, - # {:dep_from_git, git: "https://github.com/elixir-lang/my_dep.git", tag: "0.1.0"} + {:sweet_xml, "~> 0.7"} ] end end diff --git a/mix.lock b/mix.lock new file mode 100644 index 0000000..2eef226 --- /dev/null +++ b/mix.lock @@ -0,0 +1,3 @@ +%{ + "sweet_xml": {:hex, :sweet_xml, "0.7.5", "803a563113981aaac202a1dbd39771562d0ad31004ddbfc9b5090bdcd5605277", [:mix], [], "hexpm", "193b28a9b12891cae351d81a0cead165ffe67df1b73fe5866d10629f4faefb12"}, +} diff --git a/test/sc/parser/scxml_test.exs b/test/sc/parser/scxml_test.exs new file mode 100644 index 0000000..8748fb1 --- /dev/null +++ b/test/sc/parser/scxml_test.exs @@ -0,0 +1,139 @@ +defmodule SC.Parser.SCXMLTest do + use ExUnit.Case, async: true + + alias SC.Parser.SCXML + alias SC.Document + + describe "parse/1" do + test "parses simple SCXML document" do + xml = """ + + + + + """ + + assert {:ok, %Document{} = doc} = SCXML.parse(xml) + assert doc.xmlns == "http://www.w3.org/2005/07/scxml" + assert doc.version == "1.0" + assert doc.initial == "a" + assert length(doc.states) == 1 + + state = hd(doc.states) + assert state.id == "a" + assert state.initial == nil + assert state.states == [] + assert state.transitions == [] + end + + test "parses SCXML with transition" do + xml = """ + + + + + + + + """ + + assert {:ok, %Document{} = doc} = SCXML.parse(xml) + assert length(doc.states) == 2 + + [state_a, state_b] = doc.states + assert state_a.id == "a" + assert state_b.id == "b" + + assert length(state_a.transitions) == 1 + transition = hd(state_a.transitions) + assert transition.event == "go" + assert transition.target == "b" + assert transition.cond == nil + end + + test "parses SCXML with datamodel" do + xml = """ + + + + + + + + + """ + + assert {:ok, %Document{} = doc} = SCXML.parse(xml) + assert doc.datamodel == "elixir" + assert length(doc.datamodel_elements) == 2 + + [counter, name] = doc.datamodel_elements + assert counter.id == "counter" + assert counter.expr == "0" + assert counter.src == nil + + assert name.id == "name" + assert name.expr == nil + end + + test "parses nested states" do + xml = """ + + + + + + + + + + """ + + assert {:ok, %Document{} = doc} = SCXML.parse(xml) + assert length(doc.states) == 1 + + parent = hd(doc.states) + assert parent.id == "parent" + assert parent.initial == "child1" + assert length(parent.states) == 2 + + [child1, child2] = parent.states + assert child1.id == "child1" + assert child2.id == "child2" + + assert length(child1.transitions) == 1 + transition = hd(child1.transitions) + assert transition.event == "next" + assert transition.target == "child2" + end + + test "handles empty attributes as nil" do + xml = """ + + + + + + + + """ + + assert {:ok, %Document{} = doc} = SCXML.parse(xml) + assert doc.initial == nil + + state = hd(doc.states) + assert state.initial == nil + + transition = hd(state.transitions) + assert transition.event == nil + assert transition.cond == nil + assert transition.target == "end" + end + + test "returns error for invalid XML" do + xml = "" + + assert {:error, _reason} = SCXML.parse(xml) + end + end +end From e7dabfee22207ee3503a986def96d0b0bb4b62e6 Mon Sep 17 00:00:00 2001 From: JohnnyT Date: Sat, 16 Aug 2025 09:39:52 -0600 Subject: [PATCH 05/18] Switches to Saxy; removes whitespace --- CLAUDE.md | 36 +- lib/sc/data_element.ex | 13 +- lib/sc/document.ex | 15 +- lib/sc/parser/scxml.ex | 81 +---- lib/sc/parser/scxml_handler.ex | 321 ++++++++++++++++++ lib/sc/state.ex | 11 +- lib/sc/transition.ex | 13 +- mix.exs | 2 +- mix.lock | 1 + test/sc/location_test.exs | 119 +++++++ test/scion_tests/actionSend/send1_test.exs | 2 +- test/scion_tests/actionSend/send2_test.exs | 2 +- test/scion_tests/actionSend/send3_test.exs | 2 +- test/scion_tests/actionSend/send4_test.exs | 4 +- test/scion_tests/actionSend/send4b_test.exs | 2 +- test/scion_tests/actionSend/send7_test.exs | 4 +- test/scion_tests/actionSend/send7b_test.exs | 2 +- test/scion_tests/actionSend/send8_test.exs | 4 +- test/scion_tests/actionSend/send8b_test.exs | 2 +- test/scion_tests/actionSend/send9_test.exs | 2 +- .../assign-current-small-step/test0_test.exs | 2 +- .../assign-current-small-step/test1_test.exs | 2 +- .../assign-current-small-step/test2_test.exs | 2 +- .../assign-current-small-step/test3_test.exs | 4 +- .../assign-current-small-step/test4_test.exs | 2 +- .../assign/assign_obj_literal_test.exs | 2 +- .../scion_tests/atom3-basic-tests/m0_test.exs | 2 +- .../scion_tests/atom3-basic-tests/m1_test.exs | 2 +- .../scion_tests/atom3-basic-tests/m2_test.exs | 2 +- .../scion_tests/atom3-basic-tests/m3_test.exs | 2 +- test/scion_tests/basic/basic0_test.exs | 2 +- test/scion_tests/basic/basic1_test.exs | 2 +- test/scion_tests/basic/basic2_test.exs | 2 +- .../TestConditionalTransition_test.exs | 8 +- test/scion_tests/cond-js/test0_test.exs | 2 +- test/scion_tests/cond-js/test1_test.exs | 2 +- test/scion_tests/cond-js/test2_test.exs | 2 +- .../default-initial-state/initial1_test.exs | 2 +- .../default-initial-state/initial2_test.exs | 2 +- test/scion_tests/delayedSend/send1_test.exs | 2 +- test/scion_tests/delayedSend/send2_test.exs | 2 +- test/scion_tests/delayedSend/send3_test.exs | 2 +- .../documentOrder/documentOrder0_test.exs | 2 +- test/scion_tests/foreach/test1_test.exs | 2 +- .../hierarchy+documentOrder/test0_test.exs | 2 +- .../hierarchy+documentOrder/test1_test.exs | 2 +- test/scion_tests/hierarchy/hier0_test.exs | 2 +- test/scion_tests/hierarchy/hier1_test.exs | 2 +- test/scion_tests/hierarchy/hier2_test.exs | 2 +- test/scion_tests/history/history0_test.exs | 2 +- test/scion_tests/history/history1_test.exs | 2 +- test/scion_tests/history/history2_test.exs | 2 +- test/scion_tests/history/history3_test.exs | 2 +- test/scion_tests/history/history4_test.exs | 2 +- test/scion_tests/history/history4b_test.exs | 2 +- test/scion_tests/history/history5_test.exs | 4 +- test/scion_tests/history/history6_test.exs | 2 +- test/scion_tests/if-else/test0_test.exs | 2 +- test/scion_tests/in/TestInPredicate_test.exs | 6 +- .../internal-transitions/test0_test.exs | 2 +- .../internal-transitions/test1_test.exs | 4 +- test/scion_tests/more-parallel/test0_test.exs | 2 +- .../scion_tests/more-parallel/test10_test.exs | 2 +- .../more-parallel/test10b_test.exs | 2 +- test/scion_tests/more-parallel/test1_test.exs | 2 +- test/scion_tests/more-parallel/test2_test.exs | 2 +- .../scion_tests/more-parallel/test2b_test.exs | 2 +- test/scion_tests/more-parallel/test3_test.exs | 2 +- .../scion_tests/more-parallel/test3b_test.exs | 2 +- test/scion_tests/more-parallel/test4_test.exs | 2 +- test/scion_tests/more-parallel/test5_test.exs | 2 +- test/scion_tests/more-parallel/test6_test.exs | 2 +- .../scion_tests/more-parallel/test6b_test.exs | 2 +- test/scion_tests/more-parallel/test7_test.exs | 2 +- test/scion_tests/more-parallel/test8_test.exs | 2 +- test/scion_tests/more-parallel/test9_test.exs | 2 +- .../test1_test.exs | 2 +- .../parallel+interrupt/test0_test.exs | 6 +- .../parallel+interrupt/test10_test.exs | 4 +- .../parallel+interrupt/test11_test.exs | 4 +- .../parallel+interrupt/test12_test.exs | 4 +- .../parallel+interrupt/test13_test.exs | 4 +- .../parallel+interrupt/test14_test.exs | 4 +- .../parallel+interrupt/test15_test.exs | 4 +- .../parallel+interrupt/test16_test.exs | 6 +- .../parallel+interrupt/test17_test.exs | 6 +- .../parallel+interrupt/test1_test.exs | 4 +- .../parallel+interrupt/test20_test.exs | 4 +- .../parallel+interrupt/test21_test.exs | 4 +- .../parallel+interrupt/test21b_test.exs | 4 +- .../parallel+interrupt/test21c_test.exs | 4 +- .../parallel+interrupt/test22_test.exs | 4 +- .../parallel+interrupt/test25_test.exs | 4 +- .../parallel+interrupt/test27_test.exs | 4 +- .../parallel+interrupt/test28_test.exs | 2 +- .../parallel+interrupt/test29_test.exs | 2 +- .../parallel+interrupt/test2_test.exs | 4 +- .../parallel+interrupt/test30_test.exs | 4 +- .../parallel+interrupt/test31_test.exs | 4 +- .../parallel+interrupt/test3_test.exs | 6 +- .../parallel+interrupt/test4_test.exs | 6 +- .../parallel+interrupt/test5_test.exs | 6 +- .../parallel+interrupt/test6_test.exs | 6 +- .../parallel+interrupt/test7_test.exs | 10 +- .../parallel+interrupt/test7b_test.exs | 10 +- .../parallel+interrupt/test8_test.exs | 4 +- .../parallel+interrupt/test9_test.exs | 4 +- test/scion_tests/parallel/test0_test.exs | 2 +- test/scion_tests/parallel/test1_test.exs | 2 +- test/scion_tests/parallel/test2_test.exs | 2 +- test/scion_tests/parallel/test3_test.exs | 2 +- test/scion_tests/script-src/test0_test.exs | 2 +- test/scion_tests/script-src/test1_test.exs | 2 +- test/scion_tests/script-src/test2_test.exs | 2 +- test/scion_tests/script-src/test3_test.exs | 2 +- test/scion_tests/script/test0_test.exs | 2 +- test/scion_tests/script/test1_test.exs | 2 +- test/scion_tests/script/test2_test.exs | 2 +- .../star0_test.exs | 2 +- .../test0_test.exs | 2 +- .../test1_test.exs | 2 +- test/scion_tests/send-internal/test0_test.exs | 14 +- .../targetless-transition/test0_test.exs | 4 +- .../targetless-transition/test1_test.exs | 4 +- .../targetless-transition/test2_test.exs | 4 +- .../targetless-transition/test3_test.exs | 4 +- test/test_helper.exs | 2 +- 127 files changed, 709 insertions(+), 261 deletions(-) create mode 100644 lib/sc/parser/scxml_handler.ex create mode 100644 test/sc/location_test.exs diff --git a/CLAUDE.md b/CLAUDE.md index 4c6f80c..55732ab 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -6,6 +6,7 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co **Testing:** - `mix test` - Run all tests +- `mix test test/sc/location_test.exs` - Run location tracking tests - `mix test test/sc/parser/scxml_test.exs` - Run specific SCXML parser tests **Development:** @@ -36,21 +37,34 @@ Also use this initial Elixir implementation as reference: https://github.com/cam - **`SC.DataElement`** - Datamodel elements with required `id` and optional `expr` and `src` attributes ### Parsers -- **`SC.Parser.SCXML`** - Main SCXML parser using SweetXml library - - Parses XML strings into `SC.Document` structs - - Handles namespace declarations (custom xmlns extraction) +- **`SC.Parser.SCXML`** - Main SCXML parser using Saxy SAX parser for accurate location tracking + - Parses XML strings into `SC.Document` structs with precise source location information + - Event-driven SAX parsing for better memory efficiency and location tracking + - Handles namespace declarations and XML attributes correctly - Supports nested states and hierarchical structures - Converts empty XML attributes to `nil` for cleaner data representation - Returns `{:ok, document}` or `{:error, reason}` tuples +- **`SC.Parser.SCXMLHandler`** - SAX event handler for SCXML parsing + - Implements `Saxy.Handler` behavior for processing XML events + - Tracks element occurrences and position information during parsing + - Manages element stack for proper hierarchical document construction ### Test Infrastructure - **`SC.Case`** - Test case template module for SCXML testing - Provides `test_scxml/4` function for testing state machine behavior - Used by both SCION and W3C test suites +### Location Tracking +All parsed SCXML elements include precise source location information for validation error reporting: + +- **Element locations**: Each parsed element (`SC.Document`, `SC.State`, `SC.Transition`, `SC.DataElement`) includes a `source_location` field with line/column information +- **Attribute locations**: Individual attributes have dedicated location fields (e.g., `name_location`, `id_location`, `event_location`) for precise error reporting +- **Multiline support**: Accurately tracks locations for both single-line and multiline XML element definitions +- **SAX-based tracking**: Uses Saxy's event-driven parsing to maintain position information throughout the parsing process + ## Dependencies -- **`sweet_xml`** (~> 0.7) - XML parsing library built on `:xmerl` with Elixir-friendly API +- **`saxy`** (~> 1.6) - Fast, memory-efficient SAX XML parser with position tracking support ## Tests @@ -74,6 +88,12 @@ This project includes comprehensive test coverage: - Validates error handling for invalid XML - Ensures proper attribute handling (nil for empty values) +### Location Tracking Tests (`test/sc/location_test.exs`) +- Tests for precise source location tracking in SCXML documents +- Validates line number accuracy for elements and attributes +- Tests both single-line and multiline XML element definitions +- Ensures proper location tracking for nested elements and datamodel elements + ## Code Style - All generated files have no trailing whitespace @@ -99,12 +119,14 @@ XML content within triple quotes uses 4-space base indentation. ## Implementation Status ✅ **Completed:** -- Core data structures (Document, State, Transition, DataElement) -- Basic SCXML parser with SweetXml +- Core data structures (Document, State, Transition, DataElement) with location tracking +- SCXML parser using Saxy SAX parser for accurate position tracking - Comprehensive test suite integration (SCION + W3C) - Test infrastructure with SC.Case module -- XML parsing with namespace support +- XML parsing with namespace support and precise source location tracking - Error handling for malformed XML +- Location tracking for elements and attributes (line numbers for validation errors) +- Support for both single-line and multiline XML element definitions 🚧 **Future Extensions:** - More executable content elements (``, ``, ``, ``) diff --git a/lib/sc/data_element.ex b/lib/sc/data_element.ex index 9be8ef7..1f26d8c 100644 --- a/lib/sc/data_element.ex +++ b/lib/sc/data_element.ex @@ -6,12 +6,21 @@ defmodule SC.DataElement do defstruct [ :id, :expr, - :src + :src, + # Location information for validation + source_location: nil, + id_location: nil, + expr_location: nil, + src_location: nil ] @type t :: %__MODULE__{ id: String.t(), expr: String.t() | nil, - src: String.t() | nil + src: String.t() | nil, + source_location: map() | nil, + id_location: map() | nil, + expr_location: map() | nil, + src_location: map() | nil } end diff --git a/lib/sc/document.ex b/lib/sc/document.ex index e6a5116..ab6bff5 100644 --- a/lib/sc/document.ex +++ b/lib/sc/document.ex @@ -10,7 +10,13 @@ defmodule SC.Document do :version, :xmlns, states: [], - datamodel_elements: [] + datamodel_elements: [], + # Location information for validation + source_location: nil, + name_location: nil, + initial_location: nil, + datamodel_location: nil, + version_location: nil ] @type t :: %__MODULE__{ @@ -20,6 +26,11 @@ defmodule SC.Document do version: String.t() | nil, xmlns: String.t() | nil, states: [SC.State.t()], - datamodel_elements: [SC.DataElement.t()] + datamodel_elements: [SC.DataElement.t()], + source_location: map() | nil, + name_location: map() | nil, + initial_location: map() | nil, + datamodel_location: map() | nil, + version_location: map() | nil } end diff --git a/lib/sc/parser/scxml.ex b/lib/sc/parser/scxml.ex index f1934f1..d04790c 100644 --- a/lib/sc/parser/scxml.ex +++ b/lib/sc/parser/scxml.ex @@ -1,79 +1,28 @@ defmodule SC.Parser.SCXML do @moduledoc """ - Parser for SCXML documents using SweetXml. + Parser for SCXML documents using Saxy SAX parser with accurate location tracking. """ - import SweetXml + alias SC.Parser.SCXMLHandler @doc """ - Parse an SCXML string into an SC.Document struct. + Parse an SCXML string into an SC.Document struct using Saxy parser. """ @spec parse(String.t()) :: {:ok, SC.Document.t()} | {:error, term()} def parse(xml_string) do - try do - document = - xml_string - |> xpath(~x"//scxml"e) - |> parse_scxml() - - {:ok, document} - rescue - error -> {:error, error} - catch - :exit, reason -> {:error, reason} - end - end - - defp parse_scxml(scxml_element) do - %SC.Document{ - name: scxml_element |> xpath(~x"./@name"s) |> empty_to_nil(), - initial: scxml_element |> xpath(~x"./@initial"s) |> empty_to_nil(), - datamodel: scxml_element |> xpath(~x"./@datamodel"s) |> empty_to_nil(), - version: scxml_element |> xpath(~x"./@version"s) |> empty_to_nil(), - xmlns: extract_xmlns(scxml_element), - states: scxml_element |> xpath(~x"./state"el) |> Enum.map(&parse_state/1), - datamodel_elements: - scxml_element |> xpath(~x"./datamodel/data"el) |> Enum.map(&parse_data_element/1) + initial_state = %SCXMLHandler{ + stack: [], + result: nil, + current_element: nil, + line: 1, + column: 1, + xml_string: xml_string, + element_counts: %{} } - end - - defp parse_state(state_element) do - %SC.State{ - id: state_element |> xpath(~x"./@id"s), - initial: state_element |> xpath(~x"./@initial"s) |> empty_to_nil(), - states: state_element |> xpath(~x"./state"el) |> Enum.map(&parse_state/1), - transitions: state_element |> xpath(~x"./transition"el) |> Enum.map(&parse_transition/1) - } - end - defp parse_transition(transition_element) do - %SC.Transition{ - event: transition_element |> xpath(~x"./@event"s) |> empty_to_nil(), - target: transition_element |> xpath(~x"./@target"s) |> empty_to_nil(), - cond: transition_element |> xpath(~x"./@cond"s) |> empty_to_nil() - } - end - - defp parse_data_element(data_element) do - %SC.DataElement{ - id: data_element |> xpath(~x"./@id"s), - expr: data_element |> xpath(~x"./@expr"s) |> empty_to_nil(), - src: data_element |> xpath(~x"./@src"s) |> empty_to_nil() - } - end - - # Extract xmlns from raw XML element since SweetXml doesn't handle it well - defp extract_xmlns({:xmlElement, _, _, _, _, _, _, attributes, _, _, _, _}) do - case Enum.find(attributes, fn - {:xmlAttribute, :xmlns, _, _, _, _, _, _, _value, _} -> true - _ -> false - end) do - {:xmlAttribute, :xmlns, _, _, _, _, _, _, value, _} -> to_string(value) - nil -> nil + case Saxy.parse_string(xml_string, SCXMLHandler, initial_state) do + {:ok, result} -> {:ok, result} + {:error, error} -> {:error, error} end end - - # Helper to convert empty strings to nil - defp empty_to_nil(""), do: nil - defp empty_to_nil(value), do: value -end +end \ No newline at end of file diff --git a/lib/sc/parser/scxml_handler.ex b/lib/sc/parser/scxml_handler.ex new file mode 100644 index 0000000..ae1e5b0 --- /dev/null +++ b/lib/sc/parser/scxml_handler.ex @@ -0,0 +1,321 @@ +defmodule SC.Parser.SCXMLHandler do + @moduledoc """ + SAX event handler for parsing SCXML documents with accurate location tracking. + """ + + @behaviour Saxy.Handler + + defstruct [ + :stack, # Stack of parent elements for hierarchy tracking + :result, # Final SC.Document result + :current_element, # Current element being processed + :line, # Current line number + :column, # Current column number + :xml_string, # Original XML string for position tracking + :element_counts # Map tracking how many of each element type have been processed + ] + + @impl Saxy.Handler + def handle_event(:start_document, _prolog, state) do + {:ok, state} + end + + @impl Saxy.Handler + def handle_event(:end_document, _data, state) do + {:ok, state.result} + end + + @impl Saxy.Handler + def handle_event(:start_element, {name, attributes}, state) do + # Update element counts first + updated_counts = Map.update(state.element_counts, name, 1, &(&1 + 1)) + state = %{state | element_counts: updated_counts} + + location = get_location_info(state, name) + + case name do + "scxml" -> + handle_scxml_start(attributes, location, state) + "state" -> + handle_state_start(attributes, location, state) + "transition" -> + handle_transition_start(attributes, location, state) + "datamodel" -> + handle_datamodel_start(attributes, location, state) + "data" -> + handle_data_start(attributes, location, state) + _ -> + # Skip unknown elements but track them in stack + {:ok, %{state | stack: [{name, nil} | state.stack]}} + end + end + + @impl Saxy.Handler + def handle_event(:end_element, name, state) do + case name do + "scxml" -> + {:ok, state} + "state" -> + handle_state_end(state) + "transition" -> + handle_transition_end(state) + "datamodel" -> + handle_datamodel_end(state) + "data" -> + handle_data_end(state) + _ -> + # Pop unknown element from stack + {:ok, %{state | stack: tl(state.stack)}} + end + end + + @impl Saxy.Handler + def handle_event(:characters, _chars, state) do + # Ignore text content for now since SCXML elements don't have mixed content + {:ok, state} + end + + # Private helper functions + + defp get_location_info(state, element_name) do + # For now, calculate position based on element name and stack context + # This is a simplified approach that approximates location based on parsing order + calculate_element_position(state.xml_string, element_name, state.stack, state.element_counts) + end + + # Calculate approximate element position based on XML content and parsing context + defp calculate_element_position(xml_string, element_name, _stack, element_counts) do + occurrence = Map.get(element_counts, element_name, 1) + case find_element_position(xml_string, element_name, occurrence) do + {line, column} -> %{line: line, column: column} + _ -> %{line: 1, column: 1} + end + end + + # Find the position of an element by searching the XML string + # This implementation tracks occurrences to handle multiple elements with the same name + defp find_element_position(xml_string, element_name, occurrence) when is_binary(xml_string) and is_binary(element_name) do + lines = String.split(xml_string, "\n", parts: :infinity) + find_element_occurrence(lines, element_name, occurrence, 1) + end + + defp find_element_position(_xml_string, _element_name, _occurrence), do: {1, 1} + + defp find_element_occurrence([], _element_name, _occurrence, _line_num), do: {1, 1} + + defp find_element_occurrence([line | rest], element_name, target_occurrence, line_num) do + # Look for the element as a complete tag, not just substring + # Match , /, or end of line + element_pattern = "<#{element_name}([ />]|$)" + if Regex.match?(~r/#{element_pattern}/, line) do + if target_occurrence <= 1 do + column = case String.split(line, "<#{element_name}", parts: 2) do + [prefix | _] -> String.length(prefix) + 1 + _ -> 1 + end + {line_num, column} + else + find_element_occurrence(rest, element_name, target_occurrence - 1, line_num + 1) + end + else + find_element_occurrence(rest, element_name, target_occurrence, line_num + 1) + end + end + + # Calculate the location of a specific attribute within the XML + defp calculate_attribute_location(xml_string, attr_name, element_location) do + lines = String.split(xml_string, "\n") + find_attribute_location(lines, attr_name, element_location.line, element_location.line) + end + + defp find_attribute_location(lines, attr_name, start_line, current_line) when current_line <= length(lines) do + line = Enum.at(lines, current_line - 1) + if line && String.contains?(line, "#{attr_name}=") do + # Found the attribute - return this line number + %{line: current_line, column: nil} + else + # Check next line (for multiline elements) + find_attribute_location(lines, attr_name, start_line, current_line + 1) + end + end + + defp find_attribute_location(_lines, _attr_name, _start_line, _current_line) do + # Fallback to element location if attribute not found + %{line: nil, column: nil} + end + + defp handle_scxml_start(attributes, location, state) do + attrs_map = attributes_to_map(attributes) + + # Calculate attribute-specific locations + name_location = calculate_attribute_location(state.xml_string, "name", location) + initial_location = calculate_attribute_location(state.xml_string, "initial", location) + datamodel_location = calculate_attribute_location(state.xml_string, "datamodel", location) + version_location = calculate_attribute_location(state.xml_string, "version", location) + + document = %SC.Document{ + name: get_attr_value(attrs_map, "name"), + initial: get_attr_value(attrs_map, "initial"), + datamodel: get_attr_value(attrs_map, "datamodel"), + version: get_attr_value(attrs_map, "version"), + xmlns: get_attr_value(attrs_map, "xmlns"), + states: [], + datamodel_elements: [], + # Location information + source_location: location, + name_location: name_location, + initial_location: initial_location, + datamodel_location: datamodel_location, + version_location: version_location + } + + {:ok, %{state | + result: document, + current_element: {:scxml, document}, + stack: [{"scxml", document} | state.stack] + }} + end + + defp handle_state_start(attributes, location, state) do + attrs_map = attributes_to_map(attributes) + + # Calculate attribute-specific locations + id_location = calculate_attribute_location(state.xml_string, "id", location) + initial_location = calculate_attribute_location(state.xml_string, "initial", location) + + state_element = %SC.State{ + id: get_attr_value(attrs_map, "id"), + initial: get_attr_value(attrs_map, "initial"), + states: [], + transitions: [], + # Location information + source_location: location, + id_location: id_location, + initial_location: initial_location + } + + {:ok, %{state | + current_element: {:state, state_element}, + stack: [{"state", state_element} | state.stack] + }} + end + + defp handle_transition_start(attributes, location, state) do + attrs_map = attributes_to_map(attributes) + + # Calculate attribute-specific locations + event_location = calculate_attribute_location(state.xml_string, "event", location) + target_location = calculate_attribute_location(state.xml_string, "target", location) + cond_location = calculate_attribute_location(state.xml_string, "cond", location) + + transition = %SC.Transition{ + event: get_attr_value(attrs_map, "event"), + target: get_attr_value(attrs_map, "target"), + cond: get_attr_value(attrs_map, "cond"), + # Location information + source_location: location, + event_location: event_location, + target_location: target_location, + cond_location: cond_location + } + + {:ok, %{state | + current_element: {:transition, transition}, + stack: [{"transition", transition} | state.stack] + }} + end + + defp handle_datamodel_start(_attributes, _location, state) do + {:ok, %{state | stack: [{"datamodel", nil} | state.stack]}} + end + + defp handle_data_start(attributes, location, state) do + attrs_map = attributes_to_map(attributes) + + # Calculate attribute-specific locations + id_location = calculate_attribute_location(state.xml_string, "id", location) + expr_location = calculate_attribute_location(state.xml_string, "expr", location) + src_location = calculate_attribute_location(state.xml_string, "src", location) + + data_element = %SC.DataElement{ + id: get_attr_value(attrs_map, "id"), + expr: get_attr_value(attrs_map, "expr"), + src: get_attr_value(attrs_map, "src"), + # Location information + source_location: location, + id_location: id_location, + expr_location: expr_location, + src_location: src_location + } + + {:ok, %{state | + current_element: {:data, data_element}, + stack: [{"data", data_element} | state.stack] + }} + end + + defp handle_state_end(state) do + {_name, state_element} = hd(state.stack) + parent_stack = tl(state.stack) + + case parent_stack do + [{"scxml", document} | _rest] -> + updated_document = %{document | states: document.states ++ [state_element]} + updated_state = %{state | + result: updated_document, + stack: [{"scxml", updated_document} | tl(parent_stack)] + } + {:ok, updated_state} + [{"state", parent_state} | rest] -> + updated_parent = %{parent_state | states: parent_state.states ++ [state_element]} + {:ok, %{state | stack: [{"state", updated_parent} | rest]}} + _ -> + {:ok, %{state | stack: parent_stack}} + end + end + + defp handle_transition_end(state) do + {_name, transition} = hd(state.stack) + parent_stack = tl(state.stack) + + case parent_stack do + [{"state", parent_state} | rest] -> + updated_parent = %{parent_state | transitions: parent_state.transitions ++ [transition]} + {:ok, %{state | stack: [{"state", updated_parent} | rest]}} + _ -> + {:ok, %{state | stack: parent_stack}} + end + end + + defp handle_datamodel_end(state) do + {:ok, %{state | stack: tl(state.stack)}} + end + + defp handle_data_end(state) do + {_name, data_element} = hd(state.stack) + parent_stack = tl(state.stack) + + case parent_stack do + [{"datamodel", _} | [{"scxml", document} | rest]] -> + updated_document = %{document | datamodel_elements: document.datamodel_elements ++ [data_element]} + updated_state = %{state | + result: updated_document, + stack: [{"datamodel", nil}, {"scxml", updated_document} | rest] + } + {:ok, updated_state} + _ -> + {:ok, %{state | stack: parent_stack}} + end + end + + defp attributes_to_map(attributes) do + Enum.into(attributes, %{}) + end + + defp get_attr_value(attrs_map, name) do + case Map.get(attrs_map, name) do + "" -> nil + value -> value + end + end +end \ No newline at end of file diff --git a/lib/sc/state.ex b/lib/sc/state.ex index 6dceb39..89db56a 100644 --- a/lib/sc/state.ex +++ b/lib/sc/state.ex @@ -7,13 +7,20 @@ defmodule SC.State do :id, :initial, states: [], - transitions: [] + transitions: [], + # Location information for validation + source_location: nil, + id_location: nil, + initial_location: nil ] @type t :: %__MODULE__{ id: String.t(), initial: String.t() | nil, states: [SC.State.t()], - transitions: [SC.Transition.t()] + transitions: [SC.Transition.t()], + source_location: map() | nil, + id_location: map() | nil, + initial_location: map() | nil } end diff --git a/lib/sc/transition.ex b/lib/sc/transition.ex index 11e205b..aa052ce 100644 --- a/lib/sc/transition.ex +++ b/lib/sc/transition.ex @@ -6,12 +6,21 @@ defmodule SC.Transition do defstruct [ :event, :target, - :cond + :cond, + # Location information for validation + source_location: nil, + event_location: nil, + target_location: nil, + cond_location: nil ] @type t :: %__MODULE__{ event: String.t() | nil, target: String.t() | nil, - cond: String.t() | nil + cond: String.t() | nil, + source_location: map() | nil, + event_location: map() | nil, + target_location: map() | nil, + cond_location: map() | nil } end diff --git a/mix.exs b/mix.exs index 89c400f..744adac 100644 --- a/mix.exs +++ b/mix.exs @@ -25,7 +25,7 @@ defmodule SC.MixProject do # Run "mix help deps" to learn about dependencies. defp deps do [ - {:sweet_xml, "~> 0.7"} + {:saxy, "~> 1.6"} ] end end diff --git a/mix.lock b/mix.lock index 2eef226..9574027 100644 --- a/mix.lock +++ b/mix.lock @@ -1,3 +1,4 @@ %{ + "saxy": {:hex, :saxy, "1.6.0", "02cb4e9bd045f25ac0c70fae8164754878327ee393c338a090288210b02317ee", [:mix], [], "hexpm", "ef42eb4ac983ca77d650fbdb68368b26570f6cc5895f0faa04d34a6f384abad3"}, "sweet_xml": {:hex, :sweet_xml, "0.7.5", "803a563113981aaac202a1dbd39771562d0ad31004ddbfc9b5090bdcd5605277", [:mix], [], "hexpm", "193b28a9b12891cae351d81a0cead165ffe67df1b73fe5866d10629f4faefb12"}, } diff --git a/test/sc/location_test.exs b/test/sc/location_test.exs new file mode 100644 index 0000000..6fa5e66 --- /dev/null +++ b/test/sc/location_test.exs @@ -0,0 +1,119 @@ +defmodule SC.LocationTest do + use ExUnit.Case, async: true + + alias SC.Parser.SCXML + + describe "location tracking" do + test "tracks source locations for elements and attributes" do + # Creating XML with proper line structure + xml = """ + + + + + + + + """ + + assert {:ok, doc} = SCXML.parse(xml) + + # Document should have location info - absolute line numbers + # is on line 2 + assert doc.source_location.line == 2 + # initial attribute on same line as scxml + assert doc.initial_location.line == 2 + # version attribute on same line as scxml + assert doc.version_location.line == 2 + + # States should have location info + [state_a, state_b] = doc.states + # is on line 3 + assert state_a.source_location.line == 3 + # id attribute on same line as state + assert state_a.id_location.line == 3 + # is on line 6 + assert state_b.source_location.line == 6 + + # Transitions should have location info + [transition] = state_a.transitions + # is on line 4 + assert transition.source_location.line == 4 + # event attribute on same line as transition + assert transition.event_location.line == 4 + # target attribute on same line as transition + assert transition.target_location.line == 4 + end + + test "tracks source locations for multiline attributes" do + # Creating XML with proper line structure + xml = """ + + + + + + + + + """ + + assert {:ok, doc} = SCXML.parse(xml) + + # Document should have location info - absolute line numbers + + assert doc.source_location.line == 2 + assert doc.version_location.line == 4 + assert doc.initial_location.line == 5 + + [state_a, state_b] = doc.states + + assert state_a.source_location.line == 7 + # id attribute on next line + assert state_a.id_location.line == 8 + + assert state_b.source_location.line == 13 + + # Transitions should have location info + [transition] = state_a.transitions + assert transition.source_location.line == 9 + assert transition.event_location.line == 10 + assert transition.target_location.line == 11 + end + + test "tracks datamodel element locations" do + xml = """ + + + + + + + + + """ + + assert {:ok, doc} = SCXML.parse(xml) + + # Datamodel elements should have location info - absolute line numbers + [counter, name] = doc.datamodel_elements + # is on line 4 + assert counter.source_location.line == 4 + # id attribute on same line as data element + assert counter.id_location.line == 4 + # expr attribute on same line as data element + assert counter.expr_location.line == 4 + + # is on line 5 + assert name.source_location.line == 5 + # id attribute on same line as data element + assert name.id_location.line == 5 + end + end +end diff --git a/test/scion_tests/actionSend/send1_test.exs b/test/scion_tests/actionSend/send1_test.exs index 1ce4b2c..d4b54f4 100644 --- a/test/scion_tests/actionSend/send1_test.exs +++ b/test/scion_tests/actionSend/send1_test.exs @@ -20,7 +20,7 @@ defmodule SCIONTest.ActionSend.Send1Test do See the License for the specific language governing permissions and limitations under the License. --> - - - - - = 3 semantics (SCXML Appendix D semantics): The state machine will enter state 'b1', then transition to target 'b3' will be selected over transition to target 'b2', because transition to target 'b3' is an eventless transition. In the Algorithm for SCXML interpretation, transitions without events are selected before transitions with events; and transitions with events will only be selected if no eventless transitions are selected. --> - - - - - - diff --git a/test/scion_tests/assign-current-small-step/test1_test.exs b/test/scion_tests/assign-current-small-step/test1_test.exs index 96d0e3b..28381a9 100644 --- a/test/scion_tests/assign-current-small-step/test1_test.exs +++ b/test/scion_tests/assign-current-small-step/test1_test.exs @@ -23,7 +23,7 @@ defmodule SCIONTest.AssignCurrentSmallStep.Test1Test do - diff --git a/test/scion_tests/assign-current-small-step/test2_test.exs b/test/scion_tests/assign-current-small-step/test2_test.exs index bf4fa28..39cbede 100644 --- a/test/scion_tests/assign-current-small-step/test2_test.exs +++ b/test/scion_tests/assign-current-small-step/test2_test.exs @@ -23,7 +23,7 @@ defmodule SCIONTest.AssignCurrentSmallStep.Test2Test do - diff --git a/test/scion_tests/assign-current-small-step/test3_test.exs b/test/scion_tests/assign-current-small-step/test3_test.exs index c4c337f..e28ed7f 100644 --- a/test/scion_tests/assign-current-small-step/test3_test.exs +++ b/test/scion_tests/assign-current-small-step/test3_test.exs @@ -21,9 +21,9 @@ defmodule SCIONTest.AssignCurrentSmallStep.Test3Test do limitations under the License. --> - diff --git a/test/scion_tests/assign-current-small-step/test4_test.exs b/test/scion_tests/assign-current-small-step/test4_test.exs index cf685d7..7ced1ef 100644 --- a/test/scion_tests/assign-current-small-step/test4_test.exs +++ b/test/scion_tests/assign-current-small-step/test4_test.exs @@ -20,7 +20,7 @@ defmodule SCIONTest.AssignCurrentSmallStep.Test4Test do See the License for the specific language governing permissions and limitations under the License. --> - diff --git a/test/scion_tests/assign/assign_obj_literal_test.exs b/test/scion_tests/assign/assign_obj_literal_test.exs index ee21bd7..0b603fe 100644 --- a/test/scion_tests/assign/assign_obj_literal_test.exs +++ b/test/scion_tests/assign/assign_obj_literal_test.exs @@ -19,7 +19,7 @@ defmodule SCIONTest.Assign.AssignObjLiteralTest do - + diff --git a/test/scion_tests/atom3-basic-tests/m0_test.exs b/test/scion_tests/atom3-basic-tests/m0_test.exs index 5f072da..c1617f9 100644 --- a/test/scion_tests/atom3-basic-tests/m0_test.exs +++ b/test/scion_tests/atom3-basic-tests/m0_test.exs @@ -4,7 +4,7 @@ defmodule SCIONTest.Atom3BasicTests.M0Test do @tag spec: "atom3_basic_tests" test "m0" do xml = """ - diff --git a/test/scion_tests/atom3-basic-tests/m1_test.exs b/test/scion_tests/atom3-basic-tests/m1_test.exs index f55199a..89b9d97 100644 --- a/test/scion_tests/atom3-basic-tests/m1_test.exs +++ b/test/scion_tests/atom3-basic-tests/m1_test.exs @@ -4,7 +4,7 @@ defmodule SCIONTest.Atom3BasicTests.M1Test do @tag spec: "atom3_basic_tests" test "m1" do xml = """ - diff --git a/test/scion_tests/atom3-basic-tests/m2_test.exs b/test/scion_tests/atom3-basic-tests/m2_test.exs index 8428537..66cad05 100644 --- a/test/scion_tests/atom3-basic-tests/m2_test.exs +++ b/test/scion_tests/atom3-basic-tests/m2_test.exs @@ -4,7 +4,7 @@ defmodule SCIONTest.Atom3BasicTests.M2Test do @tag spec: "atom3_basic_tests" test "m2" do xml = """ - diff --git a/test/scion_tests/atom3-basic-tests/m3_test.exs b/test/scion_tests/atom3-basic-tests/m3_test.exs index 05c980d..cc257da 100644 --- a/test/scion_tests/atom3-basic-tests/m3_test.exs +++ b/test/scion_tests/atom3-basic-tests/m3_test.exs @@ -4,7 +4,7 @@ defmodule SCIONTest.Atom3BasicTests.M3Test do @tag spec: "atom3_basic_tests" test "m3" do xml = """ - diff --git a/test/scion_tests/basic/basic0_test.exs b/test/scion_tests/basic/basic0_test.exs index 42917bf..429904e 100644 --- a/test/scion_tests/basic/basic0_test.exs +++ b/test/scion_tests/basic/basic0_test.exs @@ -20,7 +20,7 @@ defmodule SCIONTest.Basic.Basic0Test do See the License for the specific language governing permissions and limitations under the License. --> - - diff --git a/test/scion_tests/basic/basic2_test.exs b/test/scion_tests/basic/basic2_test.exs index 7c56dc9..99ee9c5 100644 --- a/test/scion_tests/basic/basic2_test.exs +++ b/test/scion_tests/basic/basic2_test.exs @@ -20,7 +20,7 @@ defmodule SCIONTest.Basic.Basic2Test do See the License for the specific language governing permissions and limitations under the License. --> - diff --git a/test/scion_tests/cond-js/TestConditionalTransition_test.exs b/test/scion_tests/cond-js/TestConditionalTransition_test.exs index 9ebb159..81cae8b 100644 --- a/test/scion_tests/cond-js/TestConditionalTransition_test.exs +++ b/test/scion_tests/cond-js/TestConditionalTransition_test.exs @@ -21,11 +21,11 @@ defmodule SCIONTest.CondJs.TestConditionalTransitionTest do * See the License for the specific language governing permissions and * limitations under the License. --> - - - diff --git a/test/scion_tests/cond-js/test0_test.exs b/test/scion_tests/cond-js/test0_test.exs index dc3ddbb..65fd3f9 100644 --- a/test/scion_tests/cond-js/test0_test.exs +++ b/test/scion_tests/cond-js/test0_test.exs @@ -20,7 +20,7 @@ defmodule SCIONTest.CondJs.Test0Test do See the License for the specific language governing permissions and limitations under the License. --> - diff --git a/test/scion_tests/cond-js/test1_test.exs b/test/scion_tests/cond-js/test1_test.exs index d2c453d..1c25c4a 100644 --- a/test/scion_tests/cond-js/test1_test.exs +++ b/test/scion_tests/cond-js/test1_test.exs @@ -20,7 +20,7 @@ defmodule SCIONTest.CondJs.Test1Test do See the License for the specific language governing permissions and limitations under the License. --> - diff --git a/test/scion_tests/cond-js/test2_test.exs b/test/scion_tests/cond-js/test2_test.exs index f2b0d91..8a522d9 100644 --- a/test/scion_tests/cond-js/test2_test.exs +++ b/test/scion_tests/cond-js/test2_test.exs @@ -20,7 +20,7 @@ defmodule SCIONTest.CondJs.Test2Test do See the License for the specific language governing permissions and limitations under the License. --> - diff --git a/test/scion_tests/default-initial-state/initial1_test.exs b/test/scion_tests/default-initial-state/initial1_test.exs index ccb09e3..cf56ad4 100644 --- a/test/scion_tests/default-initial-state/initial1_test.exs +++ b/test/scion_tests/default-initial-state/initial1_test.exs @@ -20,7 +20,7 @@ defmodule SCIONTest.DefaultInitialState.Initial1Test do See the License for the specific language governing permissions and limitations under the License. --> - diff --git a/test/scion_tests/default-initial-state/initial2_test.exs b/test/scion_tests/default-initial-state/initial2_test.exs index 1fc1ddb..9fc5fd7 100644 --- a/test/scion_tests/default-initial-state/initial2_test.exs +++ b/test/scion_tests/default-initial-state/initial2_test.exs @@ -20,7 +20,7 @@ defmodule SCIONTest.DefaultInitialState.Initial2Test do See the License for the specific language governing permissions and limitations under the License. --> - - diff --git a/test/scion_tests/delayedSend/send2_test.exs b/test/scion_tests/delayedSend/send2_test.exs index 7044c85..9c7bf12 100644 --- a/test/scion_tests/delayedSend/send2_test.exs +++ b/test/scion_tests/delayedSend/send2_test.exs @@ -20,7 +20,7 @@ defmodule SCIONTest.DelayedSend.Send2Test do See the License for the specific language governing permissions and limitations under the License. --> - diff --git a/test/scion_tests/delayedSend/send3_test.exs b/test/scion_tests/delayedSend/send3_test.exs index 31753a0..3218410 100644 --- a/test/scion_tests/delayedSend/send3_test.exs +++ b/test/scion_tests/delayedSend/send3_test.exs @@ -20,7 +20,7 @@ defmodule SCIONTest.DelayedSend.Send3Test do See the License for the specific language governing permissions and limitations under the License. --> - diff --git a/test/scion_tests/documentOrder/documentOrder0_test.exs b/test/scion_tests/documentOrder/documentOrder0_test.exs index d40deef..f785f02 100644 --- a/test/scion_tests/documentOrder/documentOrder0_test.exs +++ b/test/scion_tests/documentOrder/documentOrder0_test.exs @@ -20,7 +20,7 @@ defmodule SCIONTest.DocumentOrder.DocumentOrder0Test do See the License for the specific language governing permissions and limitations under the License. --> - diff --git a/test/scion_tests/foreach/test1_test.exs b/test/scion_tests/foreach/test1_test.exs index 383b338..912fb7f 100644 --- a/test/scion_tests/foreach/test1_test.exs +++ b/test/scion_tests/foreach/test1_test.exs @@ -23,7 +23,7 @@ defmodule SCIONTest.Foreach.Test1Test do - diff --git a/test/scion_tests/hierarchy+documentOrder/test0_test.exs b/test/scion_tests/hierarchy+documentOrder/test0_test.exs index bf69731..27f28c1 100644 --- a/test/scion_tests/hierarchy+documentOrder/test0_test.exs +++ b/test/scion_tests/hierarchy+documentOrder/test0_test.exs @@ -20,7 +20,7 @@ defmodule :"Elixir.Test.StateChart.Scion.Hierarchy+documentOrder.Test0" do See the License for the specific language governing permissions and limitations under the License. --> - diff --git a/test/scion_tests/hierarchy+documentOrder/test1_test.exs b/test/scion_tests/hierarchy+documentOrder/test1_test.exs index efb778d..971f571 100644 --- a/test/scion_tests/hierarchy+documentOrder/test1_test.exs +++ b/test/scion_tests/hierarchy+documentOrder/test1_test.exs @@ -20,7 +20,7 @@ defmodule :"Elixir.Test.StateChart.Scion.Hierarchy+documentOrder.Test1" do See the License for the specific language governing permissions and limitations under the License. --> - diff --git a/test/scion_tests/hierarchy/hier0_test.exs b/test/scion_tests/hierarchy/hier0_test.exs index b829363..0cc4463 100644 --- a/test/scion_tests/hierarchy/hier0_test.exs +++ b/test/scion_tests/hierarchy/hier0_test.exs @@ -20,7 +20,7 @@ defmodule SCIONTest.Hierarchy.Hier0Test do See the License for the specific language governing permissions and limitations under the License. --> - diff --git a/test/scion_tests/hierarchy/hier1_test.exs b/test/scion_tests/hierarchy/hier1_test.exs index 8ded8a3..253a2d0 100644 --- a/test/scion_tests/hierarchy/hier1_test.exs +++ b/test/scion_tests/hierarchy/hier1_test.exs @@ -20,7 +20,7 @@ defmodule SCIONTest.Hierarchy.Hier1Test do See the License for the specific language governing permissions and limitations under the License. --> - diff --git a/test/scion_tests/hierarchy/hier2_test.exs b/test/scion_tests/hierarchy/hier2_test.exs index 2721ecf..1947246 100644 --- a/test/scion_tests/hierarchy/hier2_test.exs +++ b/test/scion_tests/hierarchy/hier2_test.exs @@ -20,7 +20,7 @@ defmodule SCIONTest.Hierarchy.Hier2Test do See the License for the specific language governing permissions and limitations under the License. --> - diff --git a/test/scion_tests/history/history0_test.exs b/test/scion_tests/history/history0_test.exs index 84b6e3c..47fa96e 100644 --- a/test/scion_tests/history/history0_test.exs +++ b/test/scion_tests/history/history0_test.exs @@ -20,7 +20,7 @@ defmodule SCIONTest.History.History0Test do See the License for the specific language governing permissions and limitations under the License. --> - - - - - - - + --> - - diff --git a/test/scion_tests/in/TestInPredicate_test.exs b/test/scion_tests/in/TestInPredicate_test.exs index 8325eaf..53dfde1 100644 --- a/test/scion_tests/in/TestInPredicate_test.exs +++ b/test/scion_tests/in/TestInPredicate_test.exs @@ -21,10 +21,10 @@ defmodule SCIONTest.In.TestInPredicateTest do * See the License for the specific language governing permissions and * limitations under the License. --> - - - diff --git a/test/scion_tests/internal-transitions/test1_test.exs b/test/scion_tests/internal-transitions/test1_test.exs index ef6054a..a479a4b 100644 --- a/test/scion_tests/internal-transitions/test1_test.exs +++ b/test/scion_tests/internal-transitions/test1_test.exs @@ -20,7 +20,7 @@ defmodule SCIONTest.InternalTransitions.Test1Test do See the License for the specific language governing permissions and limitations under the License. --> - @@ -85,7 +85,7 @@ defmodule SCIONTest.InternalTransitions.Test1Test do - + diff --git a/test/scion_tests/more-parallel/test0_test.exs b/test/scion_tests/more-parallel/test0_test.exs index c927b9a..ea25063 100644 --- a/test/scion_tests/more-parallel/test0_test.exs +++ b/test/scion_tests/more-parallel/test0_test.exs @@ -20,7 +20,7 @@ defmodule SCIONTest.MoreParallel.Test0Test do See the License for the specific language governing permissions and limitations under the License. --> - diff --git a/test/scion_tests/more-parallel/test10_test.exs b/test/scion_tests/more-parallel/test10_test.exs index 788b33c..a4b9d54 100644 --- a/test/scion_tests/more-parallel/test10_test.exs +++ b/test/scion_tests/more-parallel/test10_test.exs @@ -20,7 +20,7 @@ defmodule SCIONTest.MoreParallel.Test10Test do See the License for the specific language governing permissions and limitations under the License. --> - diff --git a/test/scion_tests/more-parallel/test10b_test.exs b/test/scion_tests/more-parallel/test10b_test.exs index b93d07b..2dd9f31 100644 --- a/test/scion_tests/more-parallel/test10b_test.exs +++ b/test/scion_tests/more-parallel/test10b_test.exs @@ -20,7 +20,7 @@ defmodule SCIONTest.MoreParallel.Test10bTest do See the License for the specific language governing permissions and limitations under the License. --> - diff --git a/test/scion_tests/more-parallel/test1_test.exs b/test/scion_tests/more-parallel/test1_test.exs index 81aa587..2f9d2ff 100644 --- a/test/scion_tests/more-parallel/test1_test.exs +++ b/test/scion_tests/more-parallel/test1_test.exs @@ -20,7 +20,7 @@ defmodule SCIONTest.MoreParallel.Test1Test do See the License for the specific language governing permissions and limitations under the License. --> - diff --git a/test/scion_tests/more-parallel/test2_test.exs b/test/scion_tests/more-parallel/test2_test.exs index 6fd7ac4..84a3c2f 100644 --- a/test/scion_tests/more-parallel/test2_test.exs +++ b/test/scion_tests/more-parallel/test2_test.exs @@ -20,7 +20,7 @@ defmodule SCIONTest.MoreParallel.Test2Test do See the License for the specific language governing permissions and limitations under the License. --> - diff --git a/test/scion_tests/more-parallel/test2b_test.exs b/test/scion_tests/more-parallel/test2b_test.exs index f85cdce..79373a0 100644 --- a/test/scion_tests/more-parallel/test2b_test.exs +++ b/test/scion_tests/more-parallel/test2b_test.exs @@ -20,7 +20,7 @@ defmodule SCIONTest.MoreParallel.Test2bTest do See the License for the specific language governing permissions and limitations under the License. --> - diff --git a/test/scion_tests/more-parallel/test3_test.exs b/test/scion_tests/more-parallel/test3_test.exs index 9f5d82d..10e79ac 100644 --- a/test/scion_tests/more-parallel/test3_test.exs +++ b/test/scion_tests/more-parallel/test3_test.exs @@ -20,7 +20,7 @@ defmodule SCIONTest.MoreParallel.Test3Test do See the License for the specific language governing permissions and limitations under the License. --> - diff --git a/test/scion_tests/more-parallel/test3b_test.exs b/test/scion_tests/more-parallel/test3b_test.exs index d2ebb0e..e87fbc1 100644 --- a/test/scion_tests/more-parallel/test3b_test.exs +++ b/test/scion_tests/more-parallel/test3b_test.exs @@ -20,7 +20,7 @@ defmodule SCIONTest.MoreParallel.Test3bTest do See the License for the specific language governing permissions and limitations under the License. --> - diff --git a/test/scion_tests/more-parallel/test4_test.exs b/test/scion_tests/more-parallel/test4_test.exs index fbb9418..486c9f4 100644 --- a/test/scion_tests/more-parallel/test4_test.exs +++ b/test/scion_tests/more-parallel/test4_test.exs @@ -20,7 +20,7 @@ defmodule SCIONTest.MoreParallel.Test4Test do See the License for the specific language governing permissions and limitations under the License. --> - diff --git a/test/scion_tests/more-parallel/test5_test.exs b/test/scion_tests/more-parallel/test5_test.exs index 226abd8..1532218 100644 --- a/test/scion_tests/more-parallel/test5_test.exs +++ b/test/scion_tests/more-parallel/test5_test.exs @@ -20,7 +20,7 @@ defmodule SCIONTest.MoreParallel.Test5Test do See the License for the specific language governing permissions and limitations under the License. --> - diff --git a/test/scion_tests/more-parallel/test6_test.exs b/test/scion_tests/more-parallel/test6_test.exs index 791f196..97597be 100644 --- a/test/scion_tests/more-parallel/test6_test.exs +++ b/test/scion_tests/more-parallel/test6_test.exs @@ -20,7 +20,7 @@ defmodule SCIONTest.MoreParallel.Test6Test do See the License for the specific language governing permissions and limitations under the License. --> - diff --git a/test/scion_tests/more-parallel/test6b_test.exs b/test/scion_tests/more-parallel/test6b_test.exs index f52547d..6a8bb51 100644 --- a/test/scion_tests/more-parallel/test6b_test.exs +++ b/test/scion_tests/more-parallel/test6b_test.exs @@ -20,7 +20,7 @@ defmodule SCIONTest.MoreParallel.Test6bTest do See the License for the specific language governing permissions and limitations under the License. --> - diff --git a/test/scion_tests/more-parallel/test7_test.exs b/test/scion_tests/more-parallel/test7_test.exs index 2ec6a14..ff4acf5 100644 --- a/test/scion_tests/more-parallel/test7_test.exs +++ b/test/scion_tests/more-parallel/test7_test.exs @@ -20,7 +20,7 @@ defmodule SCIONTest.MoreParallel.Test7Test do See the License for the specific language governing permissions and limitations under the License. --> - diff --git a/test/scion_tests/more-parallel/test8_test.exs b/test/scion_tests/more-parallel/test8_test.exs index ba77604..2119420 100644 --- a/test/scion_tests/more-parallel/test8_test.exs +++ b/test/scion_tests/more-parallel/test8_test.exs @@ -20,7 +20,7 @@ defmodule SCIONTest.MoreParallel.Test8Test do See the License for the specific language governing permissions and limitations under the License. --> - diff --git a/test/scion_tests/more-parallel/test9_test.exs b/test/scion_tests/more-parallel/test9_test.exs index e8877b9..7e40b9e 100644 --- a/test/scion_tests/more-parallel/test9_test.exs +++ b/test/scion_tests/more-parallel/test9_test.exs @@ -20,7 +20,7 @@ defmodule SCIONTest.MoreParallel.Test9Test do See the License for the specific language governing permissions and limitations under the License. --> - diff --git a/test/scion_tests/multiple-events-per-transition/test1_test.exs b/test/scion_tests/multiple-events-per-transition/test1_test.exs index 6ed26d8..e8940d9 100644 --- a/test/scion_tests/multiple-events-per-transition/test1_test.exs +++ b/test/scion_tests/multiple-events-per-transition/test1_test.exs @@ -20,7 +20,7 @@ defmodule SCIONTest.MultipleEventsPerTransition.Test1Test do See the License for the specific language governing permissions and limitations under the License. --> - diff --git a/test/scion_tests/parallel+interrupt/test0_test.exs b/test/scion_tests/parallel+interrupt/test0_test.exs index d2f4076..08f912f 100644 --- a/test/scion_tests/parallel+interrupt/test0_test.exs +++ b/test/scion_tests/parallel+interrupt/test0_test.exs @@ -20,10 +20,10 @@ defmodule :"Elixir.Test.StateChart.Scion.Parallel+interrupt.Test0" do See the License for the specific language governing permissions and limitations under the License. --> - + --> - + --> - + --> - + --> - + --> - + --> - + --> - + --> - + --> - + --> - - - - - - - - - - + --> - - - + --> - + - + - + --> - + --> - + --> - + --> - + --> - diff --git a/test/scion_tests/parallel/test1_test.exs b/test/scion_tests/parallel/test1_test.exs index 7837ad7..c5f7c40 100644 --- a/test/scion_tests/parallel/test1_test.exs +++ b/test/scion_tests/parallel/test1_test.exs @@ -20,7 +20,7 @@ defmodule SCIONTest.Parallel.Test1Test do See the License for the specific language governing permissions and limitations under the License. --> - diff --git a/test/scion_tests/parallel/test2_test.exs b/test/scion_tests/parallel/test2_test.exs index b91d894..55c2612 100644 --- a/test/scion_tests/parallel/test2_test.exs +++ b/test/scion_tests/parallel/test2_test.exs @@ -20,7 +20,7 @@ defmodule SCIONTest.Parallel.Test2Test do See the License for the specific language governing permissions and limitations under the License. --> - diff --git a/test/scion_tests/parallel/test3_test.exs b/test/scion_tests/parallel/test3_test.exs index 662a6b0..3523b6e 100644 --- a/test/scion_tests/parallel/test3_test.exs +++ b/test/scion_tests/parallel/test3_test.exs @@ -20,7 +20,7 @@ defmodule SCIONTest.Parallel.Test3Test do See the License for the specific language governing permissions and limitations under the License. --> - diff --git a/test/scion_tests/script-src/test0_test.exs b/test/scion_tests/script-src/test0_test.exs index 200ac72..8c89159 100644 --- a/test/scion_tests/script-src/test0_test.exs +++ b/test/scion_tests/script-src/test0_test.exs @@ -20,7 +20,7 @@ defmodule SCIONTest.ScriptSrc.Test0Test do See the License for the specific language governing permissions and limitations under the License. --> - diff --git a/test/scion_tests/script-src/test1_test.exs b/test/scion_tests/script-src/test1_test.exs index e336c48..d0c825f 100644 --- a/test/scion_tests/script-src/test1_test.exs +++ b/test/scion_tests/script-src/test1_test.exs @@ -20,7 +20,7 @@ defmodule SCIONTest.ScriptSrc.Test1Test do See the License for the specific language governing permissions and limitations under the License. --> - diff --git a/test/scion_tests/script-src/test2_test.exs b/test/scion_tests/script-src/test2_test.exs index 7c1c9a2..190b2bb 100644 --- a/test/scion_tests/script-src/test2_test.exs +++ b/test/scion_tests/script-src/test2_test.exs @@ -20,7 +20,7 @@ defmodule SCIONTest.ScriptSrc.Test2Test do See the License for the specific language governing permissions and limitations under the License. --> - diff --git a/test/scion_tests/script-src/test3_test.exs b/test/scion_tests/script-src/test3_test.exs index 92bd173..dac9e16 100644 --- a/test/scion_tests/script-src/test3_test.exs +++ b/test/scion_tests/script-src/test3_test.exs @@ -20,7 +20,7 @@ defmodule SCIONTest.ScriptSrc.Test3Test do See the License for the specific language governing permissions and limitations under the License. --> - diff --git a/test/scion_tests/script/test0_test.exs b/test/scion_tests/script/test0_test.exs index fc063e4..8c8dd49 100644 --- a/test/scion_tests/script/test0_test.exs +++ b/test/scion_tests/script/test0_test.exs @@ -20,7 +20,7 @@ defmodule SCIONTest.Script.Test0Test do See the License for the specific language governing permissions and limitations under the License. --> - diff --git a/test/scion_tests/script/test1_test.exs b/test/scion_tests/script/test1_test.exs index d74bb09..1d08e66 100644 --- a/test/scion_tests/script/test1_test.exs +++ b/test/scion_tests/script/test1_test.exs @@ -20,7 +20,7 @@ defmodule SCIONTest.Script.Test1Test do See the License for the specific language governing permissions and limitations under the License. --> - diff --git a/test/scion_tests/script/test2_test.exs b/test/scion_tests/script/test2_test.exs index 437eb00..f560ac9 100644 --- a/test/scion_tests/script/test2_test.exs +++ b/test/scion_tests/script/test2_test.exs @@ -20,7 +20,7 @@ defmodule SCIONTest.Script.Test2Test do See the License for the specific language governing permissions and limitations under the License. --> - diff --git a/test/scion_tests/scxml-prefix-event-name-matching/star0_test.exs b/test/scion_tests/scxml-prefix-event-name-matching/star0_test.exs index cd51e90..5880840 100644 --- a/test/scion_tests/scxml-prefix-event-name-matching/star0_test.exs +++ b/test/scion_tests/scxml-prefix-event-name-matching/star0_test.exs @@ -20,7 +20,7 @@ defmodule SCIONTest.ScxmlPrefixEventNameMatching.Star0Test do See the License for the specific language governing permissions and limitations under the License. --> - diff --git a/test/scion_tests/scxml-prefix-event-name-matching/test0_test.exs b/test/scion_tests/scxml-prefix-event-name-matching/test0_test.exs index 3260767..faf4143 100644 --- a/test/scion_tests/scxml-prefix-event-name-matching/test0_test.exs +++ b/test/scion_tests/scxml-prefix-event-name-matching/test0_test.exs @@ -20,7 +20,7 @@ defmodule SCIONTest.ScxmlPrefixEventNameMatching.Test0Test do See the License for the specific language governing permissions and limitations under the License. --> - diff --git a/test/scion_tests/scxml-prefix-event-name-matching/test1_test.exs b/test/scion_tests/scxml-prefix-event-name-matching/test1_test.exs index 9b9c19e..cdeadf3 100644 --- a/test/scion_tests/scxml-prefix-event-name-matching/test1_test.exs +++ b/test/scion_tests/scxml-prefix-event-name-matching/test1_test.exs @@ -20,7 +20,7 @@ defmodule SCIONTest.ScxmlPrefixEventNameMatching.Test1Test do See the License for the specific language governing permissions and limitations under the License. --> - diff --git a/test/scion_tests/send-internal/test0_test.exs b/test/scion_tests/send-internal/test0_test.exs index f83180c..bf7d1be 100644 --- a/test/scion_tests/send-internal/test0_test.exs +++ b/test/scion_tests/send-internal/test0_test.exs @@ -20,7 +20,7 @@ defmodule SCIONTest.SendInternal.Test0Test do See the License for the specific language governing permissions and limitations under the License. --> - @@ -35,15 +35,15 @@ defmodule SCIONTest.SendInternal.Test0Test do - + - @@ -58,7 +58,7 @@ defmodule SCIONTest.SendInternal.Test0Test do - @@ -68,7 +68,7 @@ defmodule SCIONTest.SendInternal.Test0Test do - + """ diff --git a/test/scion_tests/targetless-transition/test0_test.exs b/test/scion_tests/targetless-transition/test0_test.exs index d744a0d..900ed2f 100644 --- a/test/scion_tests/targetless-transition/test0_test.exs +++ b/test/scion_tests/targetless-transition/test0_test.exs @@ -20,7 +20,7 @@ defmodule SCIONTest.TargetlessTransition.Test0Test do See the License for the specific language governing permissions and limitations under the License. --> - @@ -30,7 +30,7 @@ defmodule SCIONTest.TargetlessTransition.Test0Test do - + diff --git a/test/scion_tests/targetless-transition/test1_test.exs b/test/scion_tests/targetless-transition/test1_test.exs index a92d2b1..be067f0 100644 --- a/test/scion_tests/targetless-transition/test1_test.exs +++ b/test/scion_tests/targetless-transition/test1_test.exs @@ -20,7 +20,7 @@ defmodule SCIONTest.TargetlessTransition.Test1Test do See the License for the specific language governing permissions and limitations under the License. --> - @@ -30,7 +30,7 @@ defmodule SCIONTest.TargetlessTransition.Test1Test do - + diff --git a/test/scion_tests/targetless-transition/test2_test.exs b/test/scion_tests/targetless-transition/test2_test.exs index b108589..f0ae285 100644 --- a/test/scion_tests/targetless-transition/test2_test.exs +++ b/test/scion_tests/targetless-transition/test2_test.exs @@ -20,7 +20,7 @@ defmodule SCIONTest.TargetlessTransition.Test2Test do See the License for the specific language governing permissions and limitations under the License. --> - @@ -30,7 +30,7 @@ defmodule SCIONTest.TargetlessTransition.Test2Test do - + diff --git a/test/scion_tests/targetless-transition/test3_test.exs b/test/scion_tests/targetless-transition/test3_test.exs index a006f61..0929db2 100644 --- a/test/scion_tests/targetless-transition/test3_test.exs +++ b/test/scion_tests/targetless-transition/test3_test.exs @@ -20,7 +20,7 @@ defmodule SCIONTest.TargetlessTransition.Test3Test do See the License for the specific language governing permissions and limitations under the License. --> - @@ -63,7 +63,7 @@ defmodule SCIONTest.TargetlessTransition.Test3Test do - + diff --git a/test/test_helper.exs b/test/test_helper.exs index 869559e..743cd46 100644 --- a/test/test_helper.exs +++ b/test/test_helper.exs @@ -1 +1 @@ -ExUnit.start() +ExUnit.start(exclude: [:scion, :scxml_w3]) From 929e8d81f148a23bbbdcb8087e189d5119831adb Mon Sep 17 00:00:00 2001 From: JohnnyT Date: Sat, 16 Aug 2025 10:34:19 -0600 Subject: [PATCH 06/18] Adds Credo --- .credo.exs | 225 +++++++++++++++++++++++++++++++++ CLAUDE.md | 10 +- lib/sc.ex | 1 + lib/sc/parser/scxml.ex | 2 +- lib/sc/parser/scxml_handler.ex | 170 ++++++++++++++++--------- mix.exs | 2 + mix.lock | 4 + test/sc/parser/scxml_test.exs | 2 +- test/support/sc_case.ex | 46 ++----- 9 files changed, 362 insertions(+), 100 deletions(-) create mode 100644 .credo.exs diff --git a/.credo.exs b/.credo.exs new file mode 100644 index 0000000..7a70b1a --- /dev/null +++ b/.credo.exs @@ -0,0 +1,225 @@ +# This file contains the configuration for Credo and you are probably reading +# this after creating it with `mix credo.gen.config`. +# +# If you find anything wrong or unclear in this file, please report an +# issue on GitHub: https://github.com/rrrene/credo/issues +# +%{ + # + # You can have as many configs as you like in the `configs:` field. + configs: [ + %{ + # + # Run any config using `mix credo -C `. If no config name is given + # "default" is used. + # + name: "default", + # + # These are the files included in the analysis: + files: %{ + # + # You can give explicit globs or simply directories. + # In the latter case `**/*.{ex,exs}` will be used. + # + included: [ + "lib/", + "src/", + "test/", + "web/", + "apps/*/lib/", + "apps/*/src/", + "apps/*/test/", + "apps/*/web/" + ], + excluded: [~r"/_build/", ~r"/deps/", ~r"/node_modules/"] + }, + # + # Load and configure plugins here: + # + plugins: [], + # + # If you create your own checks, you must specify the source files for + # them here, so they can be loaded by Credo before running the analysis. + # + requires: [], + # + # If you want to enforce a style guide and need a more traditional linting + # experience, you can change `strict` to `true` below: + # + strict: false, + # + # To modify the timeout for parsing files, change this value: + # + parse_timeout: 5000, + # + # If you want to use uncolored output by default, you can change `color` + # to `false` below: + # + color: true, + # + # You can customize the parameters of any check by adding a second element + # to the tuple. + # + # To disable a check put `false` as second element: + # + # {Credo.Check.Design.DuplicatedCode, false} + # + checks: %{ + enabled: [ + # + ## Consistency Checks + # + {Credo.Check.Consistency.ExceptionNames, []}, + {Credo.Check.Consistency.LineEndings, []}, + {Credo.Check.Consistency.ParameterPatternMatching, []}, + {Credo.Check.Consistency.SpaceAroundOperators, []}, + {Credo.Check.Consistency.SpaceInParentheses, []}, + {Credo.Check.Consistency.TabsOrSpaces, []}, + + # + ## Design Checks + # + # You can customize the priority of any check + # Priority values are: `low, normal, high, higher` + # + {Credo.Check.Design.AliasUsage, + [priority: :low, if_nested_deeper_than: 2, if_called_more_often_than: 0]}, + {Credo.Check.Design.TagFIXME, []}, + # You can also customize the exit_status of each check. + # If you don't want TODO comments to cause `mix credo` to fail, just + # set this value to 0 (zero). + # + {Credo.Check.Design.TagTODO, [exit_status: 2]}, + + # + ## Readability Checks + # + {Credo.Check.Readability.AliasOrder, []}, + {Credo.Check.Readability.FunctionNames, []}, + {Credo.Check.Readability.LargeNumbers, []}, + {Credo.Check.Readability.MaxLineLength, [priority: :low, max_length: 120]}, + {Credo.Check.Readability.ModuleAttributeNames, []}, + {Credo.Check.Readability.ModuleDoc, []}, + {Credo.Check.Readability.ModuleNames, []}, + {Credo.Check.Readability.ParenthesesInCondition, []}, + {Credo.Check.Readability.ParenthesesOnZeroArityDefs, []}, + {Credo.Check.Readability.PipeIntoAnonymousFunctions, []}, + {Credo.Check.Readability.PredicateFunctionNames, []}, + {Credo.Check.Readability.PreferImplicitTry, []}, + {Credo.Check.Readability.RedundantBlankLines, []}, + {Credo.Check.Readability.Semicolons, []}, + {Credo.Check.Readability.SpaceAfterCommas, []}, + {Credo.Check.Readability.StringSigils, []}, + {Credo.Check.Readability.TrailingBlankLine, []}, + {Credo.Check.Readability.TrailingWhiteSpace, []}, + {Credo.Check.Readability.UnnecessaryAliasExpansion, []}, + {Credo.Check.Readability.VariableNames, []}, + {Credo.Check.Readability.WithSingleClause, []}, + + # + ## Refactoring Opportunities + # + {Credo.Check.Refactor.Apply, []}, + {Credo.Check.Refactor.CondStatements, []}, + {Credo.Check.Refactor.CyclomaticComplexity, []}, + {Credo.Check.Refactor.FilterCount, []}, + {Credo.Check.Refactor.FilterFilter, []}, + {Credo.Check.Refactor.FunctionArity, []}, + {Credo.Check.Refactor.LongQuoteBlocks, []}, + {Credo.Check.Refactor.MapJoin, []}, + {Credo.Check.Refactor.MatchInCondition, []}, + {Credo.Check.Refactor.NegatedConditionsInUnless, []}, + {Credo.Check.Refactor.NegatedConditionsWithElse, []}, + {Credo.Check.Refactor.Nesting, []}, + {Credo.Check.Refactor.RedundantWithClauseResult, []}, + {Credo.Check.Refactor.RejectReject, []}, + {Credo.Check.Refactor.UnlessWithElse, []}, + {Credo.Check.Refactor.WithClauses, []}, + + # + ## Warnings + # + {Credo.Check.Warning.ApplicationConfigInModuleAttribute, []}, + {Credo.Check.Warning.BoolOperationOnSameValues, []}, + {Credo.Check.Warning.Dbg, []}, + {Credo.Check.Warning.ExpensiveEmptyEnumCheck, []}, + {Credo.Check.Warning.IExPry, []}, + {Credo.Check.Warning.IoInspect, []}, + {Credo.Check.Warning.MissedMetadataKeyInLoggerConfig, []}, + {Credo.Check.Warning.OperationOnSameValues, []}, + {Credo.Check.Warning.OperationWithConstantResult, []}, + {Credo.Check.Warning.RaiseInsideRescue, []}, + {Credo.Check.Warning.SpecWithStruct, []}, + {Credo.Check.Warning.UnsafeExec, []}, + {Credo.Check.Warning.UnusedEnumOperation, []}, + {Credo.Check.Warning.UnusedFileOperation, []}, + {Credo.Check.Warning.UnusedKeywordOperation, []}, + {Credo.Check.Warning.UnusedListOperation, []}, + {Credo.Check.Warning.UnusedPathOperation, []}, + {Credo.Check.Warning.UnusedRegexOperation, []}, + {Credo.Check.Warning.UnusedStringOperation, []}, + {Credo.Check.Warning.UnusedTupleOperation, []}, + {Credo.Check.Warning.WrongTestFileExtension, []}, + + # Enabled controversial and experimental checks + {Credo.Check.Consistency.UnusedVariableNames, []}, + {Credo.Check.Readability.ImplTrue, []}, + {Credo.Check.Readability.Specs, []}, + {Credo.Check.Readability.StrictModuleLayout, []}, + {Credo.Check.Refactor.IoPuts, []}, + {Credo.Check.Warning.MixEnv, []} + ], + disabled: [ + # + # Checks scheduled for next check update (opt-in for now) + {Credo.Check.Refactor.UtcNowTruncate, []}, + + # + # Controversial and experimental checks (opt-in, just move the check to `:enabled` + # and be sure to use `mix credo --strict` to see low priority checks) + # + {Credo.Check.Consistency.MultiAliasImportRequireUse, []}, + # {Credo.Check.Consistency.UnusedVariableNames, []}, + {Credo.Check.Design.DuplicatedCode, []}, + {Credo.Check.Design.SkipTestWithoutComment, []}, + {Credo.Check.Readability.AliasAs, []}, + {Credo.Check.Readability.BlockPipe, []}, + # {Credo.Check.Readability.ImplTrue, []}, + {Credo.Check.Readability.MultiAlias, []}, + {Credo.Check.Readability.NestedFunctionCalls, []}, + {Credo.Check.Readability.OneArityFunctionInPipe, []}, + {Credo.Check.Readability.OnePipePerLine, []}, + {Credo.Check.Readability.SeparateAliasRequire, []}, + {Credo.Check.Readability.SingleFunctionToBlockPipe, []}, + {Credo.Check.Readability.SinglePipe, []}, + # {Credo.Check.Readability.Specs, []}, + # {Credo.Check.Readability.StrictModuleLayout, []}, + {Credo.Check.Readability.WithCustomTaggedTuple, []}, + {Credo.Check.Refactor.ABCSize, []}, + {Credo.Check.Refactor.AppendSingleItem, []}, + {Credo.Check.Refactor.DoubleBooleanNegation, []}, + {Credo.Check.Refactor.FilterReject, []}, + # {Credo.Check.Refactor.IoPuts, []}, + {Credo.Check.Refactor.MapMap, []}, + {Credo.Check.Refactor.ModuleDependencies, []}, + {Credo.Check.Refactor.NegatedIsNil, []}, + {Credo.Check.Refactor.PassAsyncInTestCases, []}, + {Credo.Check.Refactor.PipeChainStart, []}, + {Credo.Check.Refactor.RejectFilter, []}, + {Credo.Check.Refactor.VariableRebinding, []}, + {Credo.Check.Warning.LazyLogging, []}, + {Credo.Check.Warning.LeakyEnvironment, []}, + {Credo.Check.Warning.MapGetUnsafePass, []}, + # {Credo.Check.Warning.MixEnv, []}, + {Credo.Check.Warning.UnsafeToAtom, []} + + # {Credo.Check.Refactor.MapInto, []}, + + # + # Custom checks can be created using `mix credo.gen.check`. + # + ] + } + } + ] +} diff --git a/CLAUDE.md b/CLAUDE.md index 55732ab..776135d 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -13,7 +13,7 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co - `mix deps.get` - Install dependencies - `mix compile` - Compile the project - `mix docs` - Generate documentation -- `mix credo` - Run static code analysis +- `mix credo --strict` - Run static code analysis with strict mode (always run with tests) - `mix test --cover` - Run tests with coverage using ExCoveralls - `mix format` - Format code according to Elixir standards - `mix format --check-formatted` - Check if code is properly formatted @@ -66,6 +66,10 @@ All parsed SCXML elements include precise source location information for valida - **`saxy`** (~> 1.6) - Fast, memory-efficient SAX XML parser with position tracking support +## Development Dependencies + +- **`credo`** (~> 1.7) - Static code analysis tool for code quality and consistency + ## Tests This project includes comprehensive test coverage: @@ -98,8 +102,10 @@ This project includes comprehensive test coverage: - All generated files have no trailing whitespace - Code is formatted using `mix format` -- Type specs are provided for all public structs +- Static code analysis with `mix credo --strict` - all issues resolved +- Type specs (`@spec`) are provided for all public functions - Comprehensive documentation with `@moduledoc` and `@doc` +- Consistent naming for unused variables (meaningful names with `_` prefix) ## XML Format diff --git a/lib/sc.ex b/lib/sc.ex index cf6c077..ed66be8 100644 --- a/lib/sc.ex +++ b/lib/sc.ex @@ -12,6 +12,7 @@ defmodule SC do :world """ + @spec hello() :: :world def hello do :world end diff --git a/lib/sc/parser/scxml.ex b/lib/sc/parser/scxml.ex index d04790c..d453454 100644 --- a/lib/sc/parser/scxml.ex +++ b/lib/sc/parser/scxml.ex @@ -25,4 +25,4 @@ defmodule SC.Parser.SCXML do {:error, error} -> {:error, error} end end -end \ No newline at end of file +end diff --git a/lib/sc/parser/scxml_handler.ex b/lib/sc/parser/scxml_handler.ex index ae1e5b0..45889d0 100644 --- a/lib/sc/parser/scxml_handler.ex +++ b/lib/sc/parser/scxml_handler.ex @@ -6,13 +6,20 @@ defmodule SC.Parser.SCXMLHandler do @behaviour Saxy.Handler defstruct [ - :stack, # Stack of parent elements for hierarchy tracking - :result, # Final SC.Document result - :current_element, # Current element being processed - :line, # Current line number - :column, # Current column number - :xml_string, # Original XML string for position tracking - :element_counts # Map tracking how many of each element type have been processed + # Stack of parent elements for hierarchy tracking + :stack, + # Final SC.Document result + :result, + # Current element being processed + :current_element, + # Current line number + :line, + # Current column number + :column, + # Original XML string for position tracking + :xml_string, + # Map tracking how many of each element type have been processed + :element_counts ] @impl Saxy.Handler @@ -36,15 +43,20 @@ defmodule SC.Parser.SCXMLHandler do case name do "scxml" -> handle_scxml_start(attributes, location, state) + "state" -> handle_state_start(attributes, location, state) + "transition" -> handle_transition_start(attributes, location, state) + "datamodel" -> handle_datamodel_start(attributes, location, state) + "data" -> handle_data_start(attributes, location, state) - _ -> + + _unknown_element_name -> # Skip unknown elements but track them in stack {:ok, %{state | stack: [{name, nil} | state.stack]}} end @@ -55,22 +67,27 @@ defmodule SC.Parser.SCXMLHandler do case name do "scxml" -> {:ok, state} + "state" -> handle_state_end(state) + "transition" -> handle_transition_end(state) + "datamodel" -> handle_datamodel_end(state) + "data" -> handle_data_end(state) - _ -> + + _unknown_element -> # Pop unknown element from stack {:ok, %{state | stack: tl(state.stack)}} end end @impl Saxy.Handler - def handle_event(:characters, _chars, state) do + def handle_event(:characters, _character_data, state) do # Ignore text content for now since SCXML elements don't have mixed content {:ok, state} end @@ -84,41 +101,49 @@ defmodule SC.Parser.SCXMLHandler do end # Calculate approximate element position based on XML content and parsing context - defp calculate_element_position(xml_string, element_name, _stack, element_counts) do + defp calculate_element_position(xml_string, element_name, _element_stack, element_counts) do occurrence = Map.get(element_counts, element_name, 1) + case find_element_position(xml_string, element_name, occurrence) do {line, column} -> %{line: line, column: column} - _ -> %{line: 1, column: 1} + _fallback -> %{line: 1, column: 1} end end # Find the position of an element by searching the XML string # This implementation tracks occurrences to handle multiple elements with the same name - defp find_element_position(xml_string, element_name, occurrence) when is_binary(xml_string) and is_binary(element_name) do + defp find_element_position(xml_string, element_name, occurrence) + when is_binary(xml_string) and is_binary(element_name) do lines = String.split(xml_string, "\n", parts: :infinity) find_element_occurrence(lines, element_name, occurrence, 1) end - defp find_element_position(_xml_string, _element_name, _occurrence), do: {1, 1} + defp find_element_position(_xml_string, _element_name, _occurrence_count), do: {1, 1} - defp find_element_occurrence([], _element_name, _occurrence, _line_num), do: {1, 1} + defp find_element_occurrence([], _element_name, _target_occurrence, _current_line), do: {1, 1} defp find_element_occurrence([line | rest], element_name, target_occurrence, line_num) do # Look for the element as a complete tag, not just substring # Match , /, or end of line element_pattern = "<#{element_name}([ />]|$)" - if Regex.match?(~r/#{element_pattern}/, line) do - if target_occurrence <= 1 do - column = case String.split(line, "<#{element_name}", parts: 2) do - [prefix | _] -> String.length(prefix) + 1 - _ -> 1 - end - {line_num, column} - else + + cond do + not Regex.match?(~r/#{element_pattern}/, line) -> + find_element_occurrence(rest, element_name, target_occurrence, line_num + 1) + + target_occurrence > 1 -> find_element_occurrence(rest, element_name, target_occurrence - 1, line_num + 1) - end - else - find_element_occurrence(rest, element_name, target_occurrence, line_num + 1) + + true -> + column = calculate_column_position(line, element_name) + {line_num, column} + end + end + + defp calculate_column_position(line, element_name) do + case String.split(line, "<#{element_name}", parts: 2) do + [prefix | _remaining_parts] -> String.length(prefix) + 1 + _no_match -> 1 end end @@ -128,8 +153,10 @@ defmodule SC.Parser.SCXMLHandler do find_attribute_location(lines, attr_name, element_location.line, element_location.line) end - defp find_attribute_location(lines, attr_name, start_line, current_line) when current_line <= length(lines) do + defp find_attribute_location(lines, attr_name, start_line, current_line) + when current_line <= length(lines) do line = Enum.at(lines, current_line - 1) + if line && String.contains?(line, "#{attr_name}=") do # Found the attribute - return this line number %{line: current_line, column: nil} @@ -139,7 +166,7 @@ defmodule SC.Parser.SCXMLHandler do end end - defp find_attribute_location(_lines, _attr_name, _start_line, _current_line) do + defp find_attribute_location(_xml_lines, _attribute_name, _element_start_line, _search_line) do # Fallback to element location if attribute not found %{line: nil, column: nil} end @@ -169,11 +196,13 @@ defmodule SC.Parser.SCXMLHandler do version_location: version_location } - {:ok, %{state | - result: document, - current_element: {:scxml, document}, - stack: [{"scxml", document} | state.stack] - }} + {:ok, + %{ + state + | result: document, + current_element: {:scxml, document}, + stack: [{"scxml", document} | state.stack] + }} end defp handle_state_start(attributes, location, state) do @@ -194,10 +223,12 @@ defmodule SC.Parser.SCXMLHandler do initial_location: initial_location } - {:ok, %{state | - current_element: {:state, state_element}, - stack: [{"state", state_element} | state.stack] - }} + {:ok, + %{ + state + | current_element: {:state, state_element}, + stack: [{"state", state_element} | state.stack] + }} end defp handle_transition_start(attributes, location, state) do @@ -219,10 +250,12 @@ defmodule SC.Parser.SCXMLHandler do cond_location: cond_location } - {:ok, %{state | - current_element: {:transition, transition}, - stack: [{"transition", transition} | state.stack] - }} + {:ok, + %{ + state + | current_element: {:transition, transition}, + stack: [{"transition", transition} | state.stack] + }} end defp handle_datamodel_start(_attributes, _location, state) do @@ -248,41 +281,49 @@ defmodule SC.Parser.SCXMLHandler do src_location: src_location } - {:ok, %{state | - current_element: {:data, data_element}, - stack: [{"data", data_element} | state.stack] - }} + {:ok, + %{ + state + | current_element: {:data, data_element}, + stack: [{"data", data_element} | state.stack] + }} end defp handle_state_end(state) do - {_name, state_element} = hd(state.stack) + {_element_name, state_element} = hd(state.stack) parent_stack = tl(state.stack) case parent_stack do - [{"scxml", document} | _rest] -> + [{"scxml", document} | _remaining_stack] -> updated_document = %{document | states: document.states ++ [state_element]} - updated_state = %{state | - result: updated_document, - stack: [{"scxml", updated_document} | tl(parent_stack)] + + updated_state = %{ + state + | result: updated_document, + stack: [{"scxml", updated_document} | tl(parent_stack)] } + {:ok, updated_state} + [{"state", parent_state} | rest] -> updated_parent = %{parent_state | states: parent_state.states ++ [state_element]} {:ok, %{state | stack: [{"state", updated_parent} | rest]}} - _ -> + + _other_parent -> {:ok, %{state | stack: parent_stack}} end end defp handle_transition_end(state) do - {_name, transition} = hd(state.stack) + {_element_name, transition} = hd(state.stack) parent_stack = tl(state.stack) case parent_stack do [{"state", parent_state} | rest] -> updated_parent = %{parent_state | transitions: parent_state.transitions ++ [transition]} {:ok, %{state | stack: [{"state", updated_parent} | rest]}} - _ -> + + _other_parent -> {:ok, %{state | stack: parent_stack}} end end @@ -292,18 +333,25 @@ defmodule SC.Parser.SCXMLHandler do end defp handle_data_end(state) do - {_name, data_element} = hd(state.stack) + {_element_name, data_element} = hd(state.stack) parent_stack = tl(state.stack) case parent_stack do - [{"datamodel", _} | [{"scxml", document} | rest]] -> - updated_document = %{document | datamodel_elements: document.datamodel_elements ++ [data_element]} - updated_state = %{state | - result: updated_document, - stack: [{"datamodel", nil}, {"scxml", updated_document} | rest] + [{"datamodel", _datamodel_placeholder} | [{"scxml", document} | rest]] -> + updated_document = %{ + document + | datamodel_elements: document.datamodel_elements ++ [data_element] } + + updated_state = %{ + state + | result: updated_document, + stack: [{"datamodel", nil}, {"scxml", updated_document} | rest] + } + {:ok, updated_state} - _ -> + + _other_parent -> {:ok, %{state | stack: parent_stack}} end end @@ -318,4 +366,4 @@ defmodule SC.Parser.SCXMLHandler do value -> value end end -end \ No newline at end of file +end diff --git a/mix.exs b/mix.exs index 744adac..e1ce1e9 100644 --- a/mix.exs +++ b/mix.exs @@ -25,6 +25,8 @@ defmodule SC.MixProject do # Run "mix help deps" to learn about dependencies. defp deps do [ + # Development, Test, Local + {:credo, "~> 1.7", only: [:dev, :test], runtime: false}, {:saxy, "~> 1.6"} ] end diff --git a/mix.lock b/mix.lock index 9574027..a2a3e5c 100644 --- a/mix.lock +++ b/mix.lock @@ -1,4 +1,8 @@ %{ + "bunt": {:hex, :bunt, "1.0.0", "081c2c665f086849e6d57900292b3a161727ab40431219529f13c4ddcf3e7a44", [:mix], [], "hexpm", "dc5f86aa08a5f6fa6b8096f0735c4e76d54ae5c9fa2c143e5a1fc7c1cd9bb6b5"}, + "credo": {:hex, :credo, "1.7.12", "9e3c20463de4b5f3f23721527fcaf16722ec815e70ff6c60b86412c695d426c1", [:mix], [{:bunt, "~> 0.2.1 or ~> 1.0", [hex: :bunt, repo: "hexpm", optional: false]}, {:file_system, "~> 0.2 or ~> 1.0", [hex: :file_system, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "8493d45c656c5427d9c729235b99d498bd133421f3e0a683e5c1b561471291e5"}, + "file_system": {:hex, :file_system, "1.1.0", "08d232062284546c6c34426997dd7ef6ec9f8bbd090eb91780283c9016840e8f", [:mix], [], "hexpm", "bfcf81244f416871f2a2e15c1b515287faa5db9c6bcf290222206d120b3d43f6"}, + "jason": {:hex, :jason, "1.4.4", "b9226785a9aa77b6857ca22832cffa5d5011a667207eb2a0ad56adb5db443b8a", [:mix], [{:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "c5eb0cab91f094599f94d55bc63409236a8ec69a21a67814529e8d5f6cc90b3b"}, "saxy": {:hex, :saxy, "1.6.0", "02cb4e9bd045f25ac0c70fae8164754878327ee393c338a090288210b02317ee", [:mix], [], "hexpm", "ef42eb4ac983ca77d650fbdb68368b26570f6cc5895f0faa04d34a6f384abad3"}, "sweet_xml": {:hex, :sweet_xml, "0.7.5", "803a563113981aaac202a1dbd39771562d0ad31004ddbfc9b5090bdcd5605277", [:mix], [], "hexpm", "193b28a9b12891cae351d81a0cead165ffe67df1b73fe5866d10629f4faefb12"}, } diff --git a/test/sc/parser/scxml_test.exs b/test/sc/parser/scxml_test.exs index 8748fb1..ccc14c0 100644 --- a/test/sc/parser/scxml_test.exs +++ b/test/sc/parser/scxml_test.exs @@ -1,8 +1,8 @@ defmodule SC.Parser.SCXMLTest do use ExUnit.Case, async: true - alias SC.Parser.SCXML alias SC.Document + alias SC.Parser.SCXML describe "parse/1" do test "parses simple SCXML document" do diff --git a/test/support/sc_case.ex b/test/support/sc_case.ex index 3e2e003..d4bc658 100644 --- a/test/support/sc_case.ex +++ b/test/support/sc_case.ex @@ -1,4 +1,12 @@ defmodule SC.Case do + @moduledoc """ + Test case template for SCXML state machine testing. + + Provides utilities for testing state machine behavior against both + SCION and W3C test suites. This module will eventually implement + full state machine interpretation and validation. + """ + # alias StateChart.{Configuration,Event} use ExUnit.CaseTemplate, async: true @@ -8,44 +16,12 @@ defmodule SC.Case do end end + @spec test_scxml(String.t(), String.t(), list(), list()) :: :ok def test_scxml(_xml, _description, _conf, _events) do - IO.puts("TODO: need to implement") - # datamodels = %{ - # "ecmascript" => StateChart.DataModel.ECMA, - # "elixir" => StateChart.DataModel.Elixir, - # "null" => StateChart.DataModel.Null - # } - # - # opts = %{datamodels: datamodels} - # - # doc = StateChart.SCXML.parse(xml, opts) - # context = %{} - # - # StateChart.interpret(doc, context) - # # TODO - # |> loop(conf, events) + # Implementation pending - will interpret SCXML and validate state transitions + :ok end - # defp loop({:await, int, context}, conf, [{event, next} | events]) do - # assert_configuration(int, conf) - # StateChart.handle_event(int, event, context) - # |> loop(next, events) - # end - # defp loop({:await, int, _context}, conf, []) do - # assert_configuration(int, conf) - # assert false, "End of events and not done" - # end - # defp loop({:done, int, _context}, conf, []) do - # assert_configuration(int, conf) - # :ok - # end - # defp loop({:done, int, _context}, conf, events) do - # assert_configuration(int, conf) - # expected = [] - # actual = Enum.map(events, fn({event, _}) -> Event.new(event) end) - # assert expected == actual - # end - # # defp assert_configuration(int, expected) do # expected = MapSet.new(expected) # actual = Configuration.active_states(int) From 204466bc9127429db6fdcbd3c1d54f47e41225b0 Mon Sep 17 00:00:00 2001 From: JohnnyT Date: Sat, 16 Aug 2025 11:51:03 -0600 Subject: [PATCH 07/18] Adds excoveralls and ensures 90% coverage --- CLAUDE.md | 5 +- mix.exs | 35 ++++++---- mix.lock | 1 + test/sc/parser/scxml_test.exs | 123 ++++++++++++++++++++++++++++++++++ 4 files changed, 149 insertions(+), 15 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index 776135d..53821fa 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -5,7 +5,9 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co ## Commands **Testing:** -- `mix test` - Run all tests +- `mix coveralls` - Run all tests with coverage reporting (ensure at least 90% coverage) +- `mix coveralls.detail` - Run tests with detailed coverage report showing uncovered lines +- `mix test` - Run all tests without coverage - `mix test test/sc/location_test.exs` - Run location tracking tests - `mix test test/sc/parser/scxml_test.exs` - Run specific SCXML parser tests @@ -14,7 +16,6 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co - `mix compile` - Compile the project - `mix docs` - Generate documentation - `mix credo --strict` - Run static code analysis with strict mode (always run with tests) -- `mix test --cover` - Run tests with coverage using ExCoveralls - `mix format` - Format code according to Elixir standards - `mix format --check-formatted` - Check if code is properly formatted diff --git a/mix.exs b/mix.exs index e1ce1e9..6771ad1 100644 --- a/mix.exs +++ b/mix.exs @@ -1,18 +1,36 @@ defmodule SC.MixProject do use Mix.Project + + @app :sc + @version "0.1.0" + @deps [ + # Development, Test, Local + {:credo, "~> 1.7", only: [:dev, :test], runtime: false}, + {:excoveralls, "~> 0.18", only: :test}, + + # Runtime + {:saxy, "~> 1.6"} + ] def project do [ - app: :sc, - version: "0.1.0", + app: @app, + version: @version, elixir: "~> 1.18", elixirc_paths: elixirc_paths(Mix.env()), start_permanent: Mix.env() == :prod, - deps: deps() + deps: @deps, + test_coverage: [tool: ExCoveralls], + preferred_cli_env: [ + coveralls: :test, + "coveralls.detail": :test, + "coveralls.post": :test, + "coveralls.html": :test, + "coveralls.cobertura": :test + ] ] end - # Run "mix help compile.app" to learn about applications. def application do [ extra_applications: [:logger] @@ -21,13 +39,4 @@ defmodule SC.MixProject do defp elixirc_paths(:test), do: ["test/support", "lib"] defp elixirc_paths(_), do: ["lib"] - - # Run "mix help deps" to learn about dependencies. - defp deps do - [ - # Development, Test, Local - {:credo, "~> 1.7", only: [:dev, :test], runtime: false}, - {:saxy, "~> 1.6"} - ] - end end diff --git a/mix.lock b/mix.lock index a2a3e5c..7529712 100644 --- a/mix.lock +++ b/mix.lock @@ -1,6 +1,7 @@ %{ "bunt": {:hex, :bunt, "1.0.0", "081c2c665f086849e6d57900292b3a161727ab40431219529f13c4ddcf3e7a44", [:mix], [], "hexpm", "dc5f86aa08a5f6fa6b8096f0735c4e76d54ae5c9fa2c143e5a1fc7c1cd9bb6b5"}, "credo": {:hex, :credo, "1.7.12", "9e3c20463de4b5f3f23721527fcaf16722ec815e70ff6c60b86412c695d426c1", [:mix], [{:bunt, "~> 0.2.1 or ~> 1.0", [hex: :bunt, repo: "hexpm", optional: false]}, {:file_system, "~> 0.2 or ~> 1.0", [hex: :file_system, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "8493d45c656c5427d9c729235b99d498bd133421f3e0a683e5c1b561471291e5"}, + "excoveralls": {:hex, :excoveralls, "0.18.5", "e229d0a65982613332ec30f07940038fe451a2e5b29bce2a5022165f0c9b157e", [:mix], [{:castore, "~> 1.0", [hex: :castore, repo: "hexpm", optional: true]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "523fe8a15603f86d64852aab2abe8ddbd78e68579c8525ae765facc5eae01562"}, "file_system": {:hex, :file_system, "1.1.0", "08d232062284546c6c34426997dd7ef6ec9f8bbd090eb91780283c9016840e8f", [:mix], [], "hexpm", "bfcf81244f416871f2a2e15c1b515287faa5db9c6bcf290222206d120b3d43f6"}, "jason": {:hex, :jason, "1.4.4", "b9226785a9aa77b6857ca22832cffa5d5011a667207eb2a0ad56adb5db443b8a", [:mix], [{:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "c5eb0cab91f094599f94d55bc63409236a8ec69a21a67814529e8d5f6cc90b3b"}, "saxy": {:hex, :saxy, "1.6.0", "02cb4e9bd045f25ac0c70fae8164754878327ee393c338a090288210b02317ee", [:mix], [], "hexpm", "ef42eb4ac983ca77d650fbdb68368b26570f6cc5895f0faa04d34a6f384abad3"}, diff --git a/test/sc/parser/scxml_test.exs b/test/sc/parser/scxml_test.exs index ccc14c0..4597ff9 100644 --- a/test/sc/parser/scxml_test.exs +++ b/test/sc/parser/scxml_test.exs @@ -135,5 +135,128 @@ defmodule SC.Parser.SCXMLTest do assert {:error, _reason} = SCXML.parse(xml) end + + test "handles unknown elements by skipping them" do + xml = """ + + + + + + + + """ + + assert {:ok, %Document{} = doc} = SCXML.parse(xml) + assert length(doc.states) == 1 + state = hd(doc.states) + assert state.id == "a" + end + + test "handles transitions with unknown parent elements" do + xml = """ + + + + + + + + """ + + assert {:ok, %Document{}} = SCXML.parse(xml) + end + + test "handles states with unknown parent elements" do + xml = """ + + + + + + + + """ + + assert {:ok, %Document{} = doc} = SCXML.parse(xml) + assert length(doc.states) == 1 + state = hd(doc.states) + assert state.id == "normal" + end + + test "handles data elements with unknown parent" do + xml = """ + + + + + + + + """ + + assert {:ok, %Document{}} = SCXML.parse(xml) + end + + test "handles empty attribute values" do + xml = """ + + + + + + + + + + """ + + assert {:ok, %Document{} = doc} = SCXML.parse(xml) + assert doc.name == nil + + state = hd(doc.states) + assert state.initial == nil + + transition = hd(state.transitions) + assert transition.event == nil + assert transition.target == nil + assert transition.cond == nil + + data = hd(doc.datamodel_elements) + assert data.expr == nil + assert data.src == nil + end + end + + describe "edge cases and error handling" do + test "handles malformed XML gracefully" do + xml = " + + + + """ + + assert {:ok, %Document{}} = SCXML.parse(xml) + end + + test "handles non-string inputs to position tracking" do + # This indirectly tests the guard clauses in find_element_position + xml = """ + + + + + """ + + assert {:ok, %Document{}} = SCXML.parse(xml) + end end end From 74b4b72290f33f016dbab618b7ffc9a6e37c6110 Mon Sep 17 00:00:00 2001 From: JohnnyT Date: Sat, 16 Aug 2025 12:32:54 -0600 Subject: [PATCH 08/18] Refactors SCXML parser and adds document_order --- CLAUDE.md | 10 +- lib/sc/data_element.ex | 3 + lib/sc/document.ex | 3 + lib/sc/parser/scxml.ex | 6 +- lib/sc/parser/scxml/element_builder.ex | 140 +++++++++ lib/sc/parser/scxml/handler.ex | 165 +++++++++++ lib/sc/parser/scxml/location_tracker.ex | 104 +++++++ lib/sc/parser/scxml/state_stack.ex | 107 +++++++ lib/sc/parser/scxml_handler.ex | 369 ------------------------ lib/sc/state.ex | 3 + lib/sc/transition.ex | 3 + mix.exs | 2 +- test/sc/parser/scxml_test.exs | 37 +++ 13 files changed, 577 insertions(+), 375 deletions(-) create mode 100644 lib/sc/parser/scxml/element_builder.ex create mode 100644 lib/sc/parser/scxml/handler.ex create mode 100644 lib/sc/parser/scxml/location_tracker.ex create mode 100644 lib/sc/parser/scxml/state_stack.ex delete mode 100644 lib/sc/parser/scxml_handler.ex diff --git a/CLAUDE.md b/CLAUDE.md index 53821fa..494484d 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -4,6 +4,12 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co ## Commands +**Code Verification Workflow:** +When verifying code changes, always follow this sequence: +1. `mix format` - Auto-fix formatting issues (trailing whitespace, final newlines, etc.) +2. `mix coveralls` - Ensure functionality and maintain at least 90% test coverage +3. `mix credo --strict` - Run static code analysis only after tests pass + **Testing:** - `mix coveralls` - Run all tests with coverage reporting (ensure at least 90% coverage) - `mix coveralls.detail` - Run tests with detailed coverage report showing uncovered lines @@ -15,9 +21,9 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co - `mix deps.get` - Install dependencies - `mix compile` - Compile the project - `mix docs` - Generate documentation -- `mix credo --strict` - Run static code analysis with strict mode (always run with tests) -- `mix format` - Format code according to Elixir standards +- `mix format` - Format code according to Elixir standards (run first for code verification) - `mix format --check-formatted` - Check if code is properly formatted +- `mix credo --strict` - Run static code analysis with strict mode (run last after tests pass) ## Architecture diff --git a/lib/sc/data_element.ex b/lib/sc/data_element.ex index 1f26d8c..5903873 100644 --- a/lib/sc/data_element.ex +++ b/lib/sc/data_element.ex @@ -7,6 +7,8 @@ defmodule SC.DataElement do :id, :expr, :src, + # Document order for deterministic processing + document_order: nil, # Location information for validation source_location: nil, id_location: nil, @@ -18,6 +20,7 @@ defmodule SC.DataElement do id: String.t(), expr: String.t() | nil, src: String.t() | nil, + document_order: integer() | nil, source_location: map() | nil, id_location: map() | nil, expr_location: map() | nil, diff --git a/lib/sc/document.ex b/lib/sc/document.ex index ab6bff5..a57df5b 100644 --- a/lib/sc/document.ex +++ b/lib/sc/document.ex @@ -11,6 +11,8 @@ defmodule SC.Document do :xmlns, states: [], datamodel_elements: [], + # Document order for deterministic processing + document_order: nil, # Location information for validation source_location: nil, name_location: nil, @@ -27,6 +29,7 @@ defmodule SC.Document do xmlns: String.t() | nil, states: [SC.State.t()], datamodel_elements: [SC.DataElement.t()], + document_order: integer() | nil, source_location: map() | nil, name_location: map() | nil, initial_location: map() | nil, diff --git a/lib/sc/parser/scxml.ex b/lib/sc/parser/scxml.ex index d453454..0a9a071 100644 --- a/lib/sc/parser/scxml.ex +++ b/lib/sc/parser/scxml.ex @@ -3,14 +3,14 @@ defmodule SC.Parser.SCXML do Parser for SCXML documents using Saxy SAX parser with accurate location tracking. """ - alias SC.Parser.SCXMLHandler + alias SC.Parser.SCXML.Handler @doc """ Parse an SCXML string into an SC.Document struct using Saxy parser. """ @spec parse(String.t()) :: {:ok, SC.Document.t()} | {:error, term()} def parse(xml_string) do - initial_state = %SCXMLHandler{ + initial_state = %Handler{ stack: [], result: nil, current_element: nil, @@ -20,7 +20,7 @@ defmodule SC.Parser.SCXML do element_counts: %{} } - case Saxy.parse_string(xml_string, SCXMLHandler, initial_state) do + case Saxy.parse_string(xml_string, Handler, initial_state) do {:ok, result} -> {:ok, result} {:error, error} -> {:error, error} end diff --git a/lib/sc/parser/scxml/element_builder.ex b/lib/sc/parser/scxml/element_builder.ex new file mode 100644 index 0000000..699cbb3 --- /dev/null +++ b/lib/sc/parser/scxml/element_builder.ex @@ -0,0 +1,140 @@ +defmodule SC.Parser.SCXML.ElementBuilder do + @moduledoc """ + Builds SCXML elements from XML attributes and location information. + + This module handles the creation of SC.Document, SC.State, SC.Transition, + and SC.DataElement structs with proper attribute parsing and location tracking. + """ + + alias SC.Parser.SCXML.LocationTracker + + @doc """ + Build an SC.Document from SCXML attributes and location info. + """ + @spec build_document(list(), map(), String.t(), map()) :: SC.Document.t() + def build_document(attributes, location, xml_string, element_counts) do + attrs_map = attributes_to_map(attributes) + document_order = LocationTracker.document_order(element_counts) + + # Calculate attribute-specific locations + name_location = LocationTracker.attribute_location(xml_string, "name", location) + + initial_location = + LocationTracker.attribute_location(xml_string, "initial", location) + + datamodel_location = + LocationTracker.attribute_location(xml_string, "datamodel", location) + + version_location = + LocationTracker.attribute_location(xml_string, "version", location) + + %SC.Document{ + name: get_attr_value(attrs_map, "name"), + initial: get_attr_value(attrs_map, "initial"), + datamodel: get_attr_value(attrs_map, "datamodel"), + version: get_attr_value(attrs_map, "version"), + xmlns: get_attr_value(attrs_map, "xmlns"), + states: [], + datamodel_elements: [], + document_order: document_order, + # Location information + source_location: location, + name_location: name_location, + initial_location: initial_location, + datamodel_location: datamodel_location, + version_location: version_location + } + end + + @doc """ + Build an SC.State from XML attributes and location info. + """ + @spec build_state(list(), map(), String.t(), map()) :: SC.State.t() + def build_state(attributes, location, xml_string, element_counts) do + attrs_map = attributes_to_map(attributes) + document_order = LocationTracker.document_order(element_counts) + + # Calculate attribute-specific locations + id_location = LocationTracker.attribute_location(xml_string, "id", location) + + initial_location = + LocationTracker.attribute_location(xml_string, "initial", location) + + %SC.State{ + id: get_attr_value(attrs_map, "id"), + initial: get_attr_value(attrs_map, "initial"), + states: [], + transitions: [], + document_order: document_order, + # Location information + source_location: location, + id_location: id_location, + initial_location: initial_location + } + end + + @doc """ + Build an SC.Transition from XML attributes and location info. + """ + @spec build_transition(list(), map(), String.t(), map()) :: SC.Transition.t() + def build_transition(attributes, location, xml_string, element_counts) do + attrs_map = attributes_to_map(attributes) + document_order = LocationTracker.document_order(element_counts) + + # Calculate attribute-specific locations + event_location = LocationTracker.attribute_location(xml_string, "event", location) + target_location = LocationTracker.attribute_location(xml_string, "target", location) + cond_location = LocationTracker.attribute_location(xml_string, "cond", location) + + %SC.Transition{ + event: get_attr_value(attrs_map, "event"), + target: get_attr_value(attrs_map, "target"), + cond: get_attr_value(attrs_map, "cond"), + document_order: document_order, + # Location information + source_location: location, + event_location: event_location, + target_location: target_location, + cond_location: cond_location + } + end + + @doc """ + Build an SC.DataElement from XML attributes and location info. + """ + @spec build_data_element(list(), map(), String.t(), map()) :: SC.DataElement.t() + def build_data_element(attributes, location, xml_string, element_counts) do + attrs_map = attributes_to_map(attributes) + document_order = LocationTracker.document_order(element_counts) + + # Calculate attribute-specific locations + id_location = LocationTracker.attribute_location(xml_string, "id", location) + expr_location = LocationTracker.attribute_location(xml_string, "expr", location) + src_location = LocationTracker.attribute_location(xml_string, "src", location) + + %SC.DataElement{ + id: get_attr_value(attrs_map, "id"), + expr: get_attr_value(attrs_map, "expr"), + src: get_attr_value(attrs_map, "src"), + document_order: document_order, + # Location information + source_location: location, + id_location: id_location, + expr_location: expr_location, + src_location: src_location + } + end + + # Private utility functions + + defp attributes_to_map(attributes) do + Enum.into(attributes, %{}) + end + + defp get_attr_value(attrs_map, name) do + case Map.get(attrs_map, name) do + "" -> nil + value -> value + end + end +end diff --git a/lib/sc/parser/scxml/handler.ex b/lib/sc/parser/scxml/handler.ex new file mode 100644 index 0000000..84bad0a --- /dev/null +++ b/lib/sc/parser/scxml/handler.ex @@ -0,0 +1,165 @@ +defmodule SC.Parser.SCXML.Handler do + @moduledoc """ + SAX event handler for parsing SCXML documents with accurate location tracking. + + This module coordinates the parsing process by delegating specific tasks to + specialized modules for location tracking, element building, and stack management. + """ + + @behaviour Saxy.Handler + + alias SC.Parser.SCXML.{ElementBuilder, LocationTracker, StateStack} + + defstruct [ + # Stack of parent elements for hierarchy tracking + :stack, + # Final SC.Document result + :result, + # Current element being processed + :current_element, + # Current line number + :line, + # Current column number + :column, + # Original XML string for position tracking + :xml_string, + # Map tracking how many of each element type have been processed + :element_counts + ] + + @impl Saxy.Handler + def handle_event(:start_document, _prolog, state) do + {:ok, state} + end + + @impl Saxy.Handler + def handle_event(:end_document, _data, state) do + {:ok, state.result} + end + + @impl Saxy.Handler + def handle_event(:start_element, {name, attributes}, state) do + # Update element counts first + updated_counts = Map.update(state.element_counts, name, 1, &(&1 + 1)) + state = %{state | element_counts: updated_counts} + + location = + LocationTracker.get_location_info(state.xml_string, name, state.stack, state.element_counts) + + case name do + "scxml" -> + handle_scxml_start(attributes, location, state) + + "state" -> + handle_state_start(attributes, location, state) + + "transition" -> + handle_transition_start(attributes, location, state) + + "datamodel" -> + handle_datamodel_start(state) + + "data" -> + handle_data_start(attributes, location, state) + + _unknown_element_name -> + # Skip unknown elements but track them in stack + {:ok, StateStack.push_element(state, name, nil)} + end + end + + @impl Saxy.Handler + def handle_event(:end_element, name, state) do + case name do + "scxml" -> + {:ok, state} + + "state" -> + StateStack.handle_state_end(state) + + "transition" -> + StateStack.handle_transition_end(state) + + "datamodel" -> + StateStack.handle_datamodel_end(state) + + "data" -> + StateStack.handle_data_end(state) + + _unknown_element -> + # Pop unknown element from stack + {:ok, StateStack.pop_element(state)} + end + end + + @impl Saxy.Handler + def handle_event(:characters, _character_data, state) do + # Ignore text content for now since SCXML elements don't have mixed content + {:ok, state} + end + + # Private element start handlers + + defp handle_scxml_start(attributes, location, state) do + document = + ElementBuilder.build_document(attributes, location, state.xml_string, state.element_counts) + + updated_state = %{ + state + | result: document, + current_element: {:scxml, document} + } + + {:ok, StateStack.push_element(updated_state, "scxml", document)} + end + + defp handle_state_start(attributes, location, state) do + state_element = + ElementBuilder.build_state(attributes, location, state.xml_string, state.element_counts) + + updated_state = %{ + state + | current_element: {:state, state_element} + } + + {:ok, StateStack.push_element(updated_state, "state", state_element)} + end + + defp handle_transition_start(attributes, location, state) do + transition = + ElementBuilder.build_transition( + attributes, + location, + state.xml_string, + state.element_counts + ) + + updated_state = %{ + state + | current_element: {:transition, transition} + } + + {:ok, StateStack.push_element(updated_state, "transition", transition)} + end + + defp handle_datamodel_start(state) do + {:ok, StateStack.push_element(state, "datamodel", nil)} + end + + defp handle_data_start(attributes, location, state) do + data_element = + ElementBuilder.build_data_element( + attributes, + location, + state.xml_string, + state.element_counts + ) + + updated_state = %{ + state + | current_element: {:data, data_element} + } + + {:ok, StateStack.push_element(updated_state, "data", data_element)} + end +end diff --git a/lib/sc/parser/scxml/location_tracker.ex b/lib/sc/parser/scxml/location_tracker.ex new file mode 100644 index 0000000..297f340 --- /dev/null +++ b/lib/sc/parser/scxml/location_tracker.ex @@ -0,0 +1,104 @@ +defmodule SC.Parser.SCXML.LocationTracker do + @moduledoc """ + Handles location tracking for SCXML parsing using XML string analysis. + + This module provides functionality to accurately track line and column + positions of XML elements and attributes during SAX parsing. + """ + + @doc """ + Calculate the location of an element based on the XML string and element counts. + """ + @spec get_location_info(String.t(), String.t(), map(), map()) :: map() + def get_location_info(xml_string, element_name, _element_stack, element_counts) do + element_position(xml_string, element_name, element_counts) + end + + @doc """ + Get the document order for an element based on element counts. + This represents the sequential order in which elements appear in the document. + """ + @spec document_order(map()) :: integer() + def document_order(element_counts) do + # Sum all element counts to get the current position in document order + element_counts + |> Map.values() + |> Enum.sum() + end + + # Private helper functions + + # Calculate approximate element position based on XML content and parsing context + defp element_position(xml_string, element_name, element_counts) do + occurrence = Map.get(element_counts, element_name, 1) + + case find_element_position(xml_string, element_name, occurrence) do + {line, column} -> %{line: line, column: column} + _fallback -> %{line: 1, column: 1} + end + end + + # Find the position of an element by searching the XML string + # This implementation tracks occurrences to handle multiple elements with the same name + defp find_element_position(xml_string, element_name, occurrence) + when is_binary(xml_string) and is_binary(element_name) do + lines = String.split(xml_string, "\n", parts: :infinity) + find_element_occurrence(lines, element_name, occurrence, 1) + end + + defp find_element_position(_xml_string, _element_name, _occurrence_count), do: {1, 1} + + defp find_element_occurrence([], _element_name, _target_occurrence, _current_line), do: {1, 1} + + defp find_element_occurrence([line | rest], element_name, target_occurrence, line_num) do + # Look for the element as a complete tag, not just substring + # Match , /, or end of line + element_pattern = "<#{element_name}([ />]|$)" + + cond do + not Regex.match?(~r/#{element_pattern}/, line) -> + find_element_occurrence(rest, element_name, target_occurrence, line_num + 1) + + target_occurrence > 1 -> + find_element_occurrence(rest, element_name, target_occurrence - 1, line_num + 1) + + true -> + column = column_position(line, element_name) + {line_num, column} + end + end + + defp column_position(line, element_name) do + case String.split(line, "<#{element_name}", parts: 2) do + [prefix | _remaining_parts] -> String.length(prefix) + 1 + _no_match -> 1 + end + end + + @doc """ + Get the location of a specific attribute within the XML. + """ + @spec attribute_location(String.t(), String.t(), map()) :: map() + def attribute_location(xml_string, attr_name, element_location) do + lines = String.split(xml_string, "\n") + find_attribute_location(lines, attr_name, element_location.line, element_location.line) + end + + defp find_attribute_location(lines, attr_name, start_line, current_line) + when current_line <= length(lines) do + line = Enum.at(lines, current_line - 1) + + if line && String.contains?(line, "#{attr_name}=") do + # Found the attribute - return this line number + %{line: current_line, column: nil} + else + # Check next line (for multiline elements) + find_attribute_location(lines, attr_name, start_line, current_line + 1) + end + end + + defp find_attribute_location(_xml_lines, _attribute_name, _element_start_line, _search_line) do + # Fallback to element location if attribute not found + %{line: nil, column: nil} + end +end diff --git a/lib/sc/parser/scxml/state_stack.ex b/lib/sc/parser/scxml/state_stack.ex new file mode 100644 index 0000000..f35cd84 --- /dev/null +++ b/lib/sc/parser/scxml/state_stack.ex @@ -0,0 +1,107 @@ +defmodule SC.Parser.SCXML.StateStack do + @moduledoc """ + Manages the parsing state stack for hierarchical SCXML document construction. + + This module handles adding and removing elements from the parsing stack, + and updating parent elements when child elements are completed. + """ + + @doc """ + Handle the end of a state element by adding it to its parent. + """ + @spec handle_state_end(map()) :: {:ok, map()} + def handle_state_end(state) do + {_element_name, state_element} = hd(state.stack) + parent_stack = tl(state.stack) + + case parent_stack do + [{"scxml", document} | _remaining_stack] -> + updated_document = %{document | states: document.states ++ [state_element]} + + updated_state = %{ + state + | result: updated_document, + stack: [{"scxml", updated_document} | tl(parent_stack)] + } + + {:ok, updated_state} + + [{"state", parent_state} | rest] -> + updated_parent = %{parent_state | states: parent_state.states ++ [state_element]} + {:ok, %{state | stack: [{"state", updated_parent} | rest]}} + + _other_parent -> + {:ok, %{state | stack: parent_stack}} + end + end + + @doc """ + Handle the end of a transition element by adding it to its parent state. + """ + @spec handle_transition_end(map()) :: {:ok, map()} + def handle_transition_end(state) do + {_element_name, transition} = hd(state.stack) + parent_stack = tl(state.stack) + + case parent_stack do + [{"state", parent_state} | rest] -> + updated_parent = %{parent_state | transitions: parent_state.transitions ++ [transition]} + {:ok, %{state | stack: [{"state", updated_parent} | rest]}} + + _other_parent -> + {:ok, %{state | stack: parent_stack}} + end + end + + @doc """ + Handle the end of a datamodel element by simply popping it from the stack. + """ + @spec handle_datamodel_end(map()) :: {:ok, map()} + def handle_datamodel_end(state) do + {:ok, %{state | stack: tl(state.stack)}} + end + + @doc """ + Handle the end of a data element by adding it to the document's datamodel. + """ + @spec handle_data_end(map()) :: {:ok, map()} + def handle_data_end(state) do + {_element_name, data_element} = hd(state.stack) + parent_stack = tl(state.stack) + + case parent_stack do + [{"datamodel", _datamodel_placeholder} | [{"scxml", document} | rest]] -> + updated_document = %{ + document + | datamodel_elements: document.datamodel_elements ++ [data_element] + } + + updated_state = %{ + state + | result: updated_document, + stack: [{"datamodel", nil}, {"scxml", updated_document} | rest] + } + + {:ok, updated_state} + + _other_parent -> + {:ok, %{state | stack: parent_stack}} + end + end + + @doc """ + Push an element onto the parsing stack. + """ + @spec push_element(map(), String.t(), any()) :: map() + def push_element(state, element_name, element_data) do + %{state | stack: [{element_name, element_data} | state.stack]} + end + + @doc """ + Pop an element from the parsing stack. + """ + @spec pop_element(map()) :: map() + def pop_element(state) do + %{state | stack: tl(state.stack)} + end +end diff --git a/lib/sc/parser/scxml_handler.ex b/lib/sc/parser/scxml_handler.ex deleted file mode 100644 index 45889d0..0000000 --- a/lib/sc/parser/scxml_handler.ex +++ /dev/null @@ -1,369 +0,0 @@ -defmodule SC.Parser.SCXMLHandler do - @moduledoc """ - SAX event handler for parsing SCXML documents with accurate location tracking. - """ - - @behaviour Saxy.Handler - - defstruct [ - # Stack of parent elements for hierarchy tracking - :stack, - # Final SC.Document result - :result, - # Current element being processed - :current_element, - # Current line number - :line, - # Current column number - :column, - # Original XML string for position tracking - :xml_string, - # Map tracking how many of each element type have been processed - :element_counts - ] - - @impl Saxy.Handler - def handle_event(:start_document, _prolog, state) do - {:ok, state} - end - - @impl Saxy.Handler - def handle_event(:end_document, _data, state) do - {:ok, state.result} - end - - @impl Saxy.Handler - def handle_event(:start_element, {name, attributes}, state) do - # Update element counts first - updated_counts = Map.update(state.element_counts, name, 1, &(&1 + 1)) - state = %{state | element_counts: updated_counts} - - location = get_location_info(state, name) - - case name do - "scxml" -> - handle_scxml_start(attributes, location, state) - - "state" -> - handle_state_start(attributes, location, state) - - "transition" -> - handle_transition_start(attributes, location, state) - - "datamodel" -> - handle_datamodel_start(attributes, location, state) - - "data" -> - handle_data_start(attributes, location, state) - - _unknown_element_name -> - # Skip unknown elements but track them in stack - {:ok, %{state | stack: [{name, nil} | state.stack]}} - end - end - - @impl Saxy.Handler - def handle_event(:end_element, name, state) do - case name do - "scxml" -> - {:ok, state} - - "state" -> - handle_state_end(state) - - "transition" -> - handle_transition_end(state) - - "datamodel" -> - handle_datamodel_end(state) - - "data" -> - handle_data_end(state) - - _unknown_element -> - # Pop unknown element from stack - {:ok, %{state | stack: tl(state.stack)}} - end - end - - @impl Saxy.Handler - def handle_event(:characters, _character_data, state) do - # Ignore text content for now since SCXML elements don't have mixed content - {:ok, state} - end - - # Private helper functions - - defp get_location_info(state, element_name) do - # For now, calculate position based on element name and stack context - # This is a simplified approach that approximates location based on parsing order - calculate_element_position(state.xml_string, element_name, state.stack, state.element_counts) - end - - # Calculate approximate element position based on XML content and parsing context - defp calculate_element_position(xml_string, element_name, _element_stack, element_counts) do - occurrence = Map.get(element_counts, element_name, 1) - - case find_element_position(xml_string, element_name, occurrence) do - {line, column} -> %{line: line, column: column} - _fallback -> %{line: 1, column: 1} - end - end - - # Find the position of an element by searching the XML string - # This implementation tracks occurrences to handle multiple elements with the same name - defp find_element_position(xml_string, element_name, occurrence) - when is_binary(xml_string) and is_binary(element_name) do - lines = String.split(xml_string, "\n", parts: :infinity) - find_element_occurrence(lines, element_name, occurrence, 1) - end - - defp find_element_position(_xml_string, _element_name, _occurrence_count), do: {1, 1} - - defp find_element_occurrence([], _element_name, _target_occurrence, _current_line), do: {1, 1} - - defp find_element_occurrence([line | rest], element_name, target_occurrence, line_num) do - # Look for the element as a complete tag, not just substring - # Match , /, or end of line - element_pattern = "<#{element_name}([ />]|$)" - - cond do - not Regex.match?(~r/#{element_pattern}/, line) -> - find_element_occurrence(rest, element_name, target_occurrence, line_num + 1) - - target_occurrence > 1 -> - find_element_occurrence(rest, element_name, target_occurrence - 1, line_num + 1) - - true -> - column = calculate_column_position(line, element_name) - {line_num, column} - end - end - - defp calculate_column_position(line, element_name) do - case String.split(line, "<#{element_name}", parts: 2) do - [prefix | _remaining_parts] -> String.length(prefix) + 1 - _no_match -> 1 - end - end - - # Calculate the location of a specific attribute within the XML - defp calculate_attribute_location(xml_string, attr_name, element_location) do - lines = String.split(xml_string, "\n") - find_attribute_location(lines, attr_name, element_location.line, element_location.line) - end - - defp find_attribute_location(lines, attr_name, start_line, current_line) - when current_line <= length(lines) do - line = Enum.at(lines, current_line - 1) - - if line && String.contains?(line, "#{attr_name}=") do - # Found the attribute - return this line number - %{line: current_line, column: nil} - else - # Check next line (for multiline elements) - find_attribute_location(lines, attr_name, start_line, current_line + 1) - end - end - - defp find_attribute_location(_xml_lines, _attribute_name, _element_start_line, _search_line) do - # Fallback to element location if attribute not found - %{line: nil, column: nil} - end - - defp handle_scxml_start(attributes, location, state) do - attrs_map = attributes_to_map(attributes) - - # Calculate attribute-specific locations - name_location = calculate_attribute_location(state.xml_string, "name", location) - initial_location = calculate_attribute_location(state.xml_string, "initial", location) - datamodel_location = calculate_attribute_location(state.xml_string, "datamodel", location) - version_location = calculate_attribute_location(state.xml_string, "version", location) - - document = %SC.Document{ - name: get_attr_value(attrs_map, "name"), - initial: get_attr_value(attrs_map, "initial"), - datamodel: get_attr_value(attrs_map, "datamodel"), - version: get_attr_value(attrs_map, "version"), - xmlns: get_attr_value(attrs_map, "xmlns"), - states: [], - datamodel_elements: [], - # Location information - source_location: location, - name_location: name_location, - initial_location: initial_location, - datamodel_location: datamodel_location, - version_location: version_location - } - - {:ok, - %{ - state - | result: document, - current_element: {:scxml, document}, - stack: [{"scxml", document} | state.stack] - }} - end - - defp handle_state_start(attributes, location, state) do - attrs_map = attributes_to_map(attributes) - - # Calculate attribute-specific locations - id_location = calculate_attribute_location(state.xml_string, "id", location) - initial_location = calculate_attribute_location(state.xml_string, "initial", location) - - state_element = %SC.State{ - id: get_attr_value(attrs_map, "id"), - initial: get_attr_value(attrs_map, "initial"), - states: [], - transitions: [], - # Location information - source_location: location, - id_location: id_location, - initial_location: initial_location - } - - {:ok, - %{ - state - | current_element: {:state, state_element}, - stack: [{"state", state_element} | state.stack] - }} - end - - defp handle_transition_start(attributes, location, state) do - attrs_map = attributes_to_map(attributes) - - # Calculate attribute-specific locations - event_location = calculate_attribute_location(state.xml_string, "event", location) - target_location = calculate_attribute_location(state.xml_string, "target", location) - cond_location = calculate_attribute_location(state.xml_string, "cond", location) - - transition = %SC.Transition{ - event: get_attr_value(attrs_map, "event"), - target: get_attr_value(attrs_map, "target"), - cond: get_attr_value(attrs_map, "cond"), - # Location information - source_location: location, - event_location: event_location, - target_location: target_location, - cond_location: cond_location - } - - {:ok, - %{ - state - | current_element: {:transition, transition}, - stack: [{"transition", transition} | state.stack] - }} - end - - defp handle_datamodel_start(_attributes, _location, state) do - {:ok, %{state | stack: [{"datamodel", nil} | state.stack]}} - end - - defp handle_data_start(attributes, location, state) do - attrs_map = attributes_to_map(attributes) - - # Calculate attribute-specific locations - id_location = calculate_attribute_location(state.xml_string, "id", location) - expr_location = calculate_attribute_location(state.xml_string, "expr", location) - src_location = calculate_attribute_location(state.xml_string, "src", location) - - data_element = %SC.DataElement{ - id: get_attr_value(attrs_map, "id"), - expr: get_attr_value(attrs_map, "expr"), - src: get_attr_value(attrs_map, "src"), - # Location information - source_location: location, - id_location: id_location, - expr_location: expr_location, - src_location: src_location - } - - {:ok, - %{ - state - | current_element: {:data, data_element}, - stack: [{"data", data_element} | state.stack] - }} - end - - defp handle_state_end(state) do - {_element_name, state_element} = hd(state.stack) - parent_stack = tl(state.stack) - - case parent_stack do - [{"scxml", document} | _remaining_stack] -> - updated_document = %{document | states: document.states ++ [state_element]} - - updated_state = %{ - state - | result: updated_document, - stack: [{"scxml", updated_document} | tl(parent_stack)] - } - - {:ok, updated_state} - - [{"state", parent_state} | rest] -> - updated_parent = %{parent_state | states: parent_state.states ++ [state_element]} - {:ok, %{state | stack: [{"state", updated_parent} | rest]}} - - _other_parent -> - {:ok, %{state | stack: parent_stack}} - end - end - - defp handle_transition_end(state) do - {_element_name, transition} = hd(state.stack) - parent_stack = tl(state.stack) - - case parent_stack do - [{"state", parent_state} | rest] -> - updated_parent = %{parent_state | transitions: parent_state.transitions ++ [transition]} - {:ok, %{state | stack: [{"state", updated_parent} | rest]}} - - _other_parent -> - {:ok, %{state | stack: parent_stack}} - end - end - - defp handle_datamodel_end(state) do - {:ok, %{state | stack: tl(state.stack)}} - end - - defp handle_data_end(state) do - {_element_name, data_element} = hd(state.stack) - parent_stack = tl(state.stack) - - case parent_stack do - [{"datamodel", _datamodel_placeholder} | [{"scxml", document} | rest]] -> - updated_document = %{ - document - | datamodel_elements: document.datamodel_elements ++ [data_element] - } - - updated_state = %{ - state - | result: updated_document, - stack: [{"datamodel", nil}, {"scxml", updated_document} | rest] - } - - {:ok, updated_state} - - _other_parent -> - {:ok, %{state | stack: parent_stack}} - end - end - - defp attributes_to_map(attributes) do - Enum.into(attributes, %{}) - end - - defp get_attr_value(attrs_map, name) do - case Map.get(attrs_map, name) do - "" -> nil - value -> value - end - end -end diff --git a/lib/sc/state.ex b/lib/sc/state.ex index 89db56a..79d2912 100644 --- a/lib/sc/state.ex +++ b/lib/sc/state.ex @@ -8,6 +8,8 @@ defmodule SC.State do :initial, states: [], transitions: [], + # Document order for deterministic processing + document_order: nil, # Location information for validation source_location: nil, id_location: nil, @@ -19,6 +21,7 @@ defmodule SC.State do initial: String.t() | nil, states: [SC.State.t()], transitions: [SC.Transition.t()], + document_order: integer() | nil, source_location: map() | nil, id_location: map() | nil, initial_location: map() | nil diff --git a/lib/sc/transition.ex b/lib/sc/transition.ex index aa052ce..9df0626 100644 --- a/lib/sc/transition.ex +++ b/lib/sc/transition.ex @@ -7,6 +7,8 @@ defmodule SC.Transition do :event, :target, :cond, + # Document order for deterministic processing + document_order: nil, # Location information for validation source_location: nil, event_location: nil, @@ -18,6 +20,7 @@ defmodule SC.Transition do event: String.t() | nil, target: String.t() | nil, cond: String.t() | nil, + document_order: integer() | nil, source_location: map() | nil, event_location: map() | nil, target_location: map() | nil, diff --git a/mix.exs b/mix.exs index 6771ad1..7e52054 100644 --- a/mix.exs +++ b/mix.exs @@ -1,6 +1,6 @@ defmodule SC.MixProject do use Mix.Project - + @app :sc @version "0.1.0" @deps [ diff --git a/test/sc/parser/scxml_test.exs b/test/sc/parser/scxml_test.exs index 4597ff9..a65cc1a 100644 --- a/test/sc/parser/scxml_test.exs +++ b/test/sc/parser/scxml_test.exs @@ -17,11 +17,13 @@ defmodule SC.Parser.SCXMLTest do assert doc.xmlns == "http://www.w3.org/2005/07/scxml" assert doc.version == "1.0" assert doc.initial == "a" + assert doc.document_order == 1 assert length(doc.states) == 1 state = hd(doc.states) assert state.id == "a" assert state.initial == nil + assert state.document_order == 2 assert state.states == [] assert state.transitions == [] end @@ -258,5 +260,40 @@ defmodule SC.Parser.SCXMLTest do assert {:ok, %Document{}} = SCXML.parse(xml) end + + test "assigns document_order based on element counts" do + xml = """ + + + + + + + + + + + + """ + + assert {:ok, %Document{} = doc} = SCXML.parse(xml) + + # Document (scxml) should have document_order of 1 + assert doc.document_order == 1 + + # Data elements should have document_order of 3 and 4 + [data1, data2] = doc.datamodel_elements + assert data1.document_order == 3 + assert data2.document_order == 4 + + # States should have document_order of 5 and 7 + [state_a, state_b] = doc.states + assert state_a.document_order == 5 + assert state_b.document_order == 7 + + # Transition should have document_order of 6 + transition = hd(state_a.transitions) + assert transition.document_order == 6 + end end end From 8a690b1aac3b3a998b2082724076fa906ac5e525 Mon Sep 17 00:00:00 2001 From: JohnnyT Date: Sat, 16 Aug 2025 14:08:30 -0600 Subject: [PATCH 09/18] Adds basic interpreter --- CLAUDE.md | 71 ++++++-- lib/sc/configuration.ex | 90 ++++++++++ lib/sc/document/validator.ex | 265 ++++++++++++++++++++++++++++ lib/sc/event.ex | 59 +++++++ lib/sc/interpreter.ex | 142 +++++++++++++++ lib/sc/state_chart.ex | 95 ++++++++++ test/sc/document/validator_test.exs | 177 +++++++++++++++++++ test/sc/interpreter_test.exs | 185 +++++++++++++++++++ test/support/sc_case.ex | 58 ++++-- 9 files changed, 1120 insertions(+), 22 deletions(-) create mode 100644 lib/sc/configuration.ex create mode 100644 lib/sc/document/validator.ex create mode 100644 lib/sc/event.ex create mode 100644 lib/sc/interpreter.ex create mode 100644 lib/sc/state_chart.ex create mode 100644 test/sc/document/validator_test.exs create mode 100644 test/sc/interpreter_test.exs diff --git a/CLAUDE.md b/CLAUDE.md index 494484d..b1689f9 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -51,14 +51,40 @@ Also use this initial Elixir implementation as reference: https://github.com/cam - Supports nested states and hierarchical structures - Converts empty XML attributes to `nil` for cleaner data representation - Returns `{:ok, document}` or `{:error, reason}` tuples -- **`SC.Parser.SCXMLHandler`** - SAX event handler for SCXML parsing +- **`SC.Parser.SCXML.Handler`** - SAX event handler for SCXML parsing - Implements `Saxy.Handler` behavior for processing XML events - Tracks element occurrences and position information during parsing - Manages element stack for proper hierarchical document construction +- **`SC.Parser.SCXML.ElementBuilder`** - Builds SCXML elements from SAX events +- **`SC.Parser.SCXML.LocationTracker`** - Tracks precise source locations for elements and attributes +- **`SC.Parser.SCXML.StateStack`** - Manages parsing state stack for hierarchical document construction + +### Interpreter and Runtime +- **`SC.Interpreter`** - Core SCXML interpreter with synchronous API + - Initializes state charts from validated documents + - Processes events and manages state transitions + - Returns active state configurations + - Provides `{:ok, result}` or `{:error, reason}` responses +- **`SC.StateChart`** - Runtime container for SCXML state machines + - Combines document, configuration, and event queues + - Maintains internal and external event queues per SCXML specification +- **`SC.Configuration`** - Active state configuration management + - Stores only leaf states for efficient memory usage + - Computes ancestor states dynamically from document hierarchy + - Uses MapSets for fast state membership testing +- **`SC.Event`** - Event representation with internal/external origins + - Supports event data and origin tracking + - Used for state machine event processing +- **`SC.Document.Validator`** - Document validation and consistency checking + - Validates structural correctness and semantic consistency + - Includes finalize callback for whole-document validations + - Catches issues like invalid references, unreachable states, malformed hierarchies ### Test Infrastructure - **`SC.Case`** - Test case template module for SCXML testing - Provides `test_scxml/4` function for testing state machine behavior + - Uses SC.Interpreter for document initialization and event processing + - Supports initial configuration verification and event sequence testing - Used by both SCION and W3C test suites ### Location Tracking @@ -129,25 +155,48 @@ xml = """ XML content within triple quotes uses 4-space base indentation. +## SCION Test Results + +**Current Status:** 107/225 tests passing (47.6% pass rate) + +**Working Features:** +- ✅ Basic state transitions (basic1, basic2 tests pass) +- ✅ Simple hierarchical states +- ✅ Event-driven state changes +- ✅ Initial state configuration +- ✅ Document validation and error reporting + +**Main Failure Categories:** +- **Document parsing failures**: Complex SCXML with parallel states, history states, executable content +- **Validation too strict**: Rejecting valid but complex SCXML documents +- **Missing SCXML features**: Parallel states, conditional transitions, targetless transitions, internal transitions +- **Missing executable content**: `