adsl 0.0.3 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (91) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +2 -20
  3. data/README.md +14 -21
  4. data/bin/adsl-verify +8 -8
  5. data/lib/adsl.rb +3 -0
  6. data/lib/adsl/adsl.rb +3 -0
  7. data/lib/adsl/ds/data_store_spec.rb +339 -0
  8. data/lib/adsl/extract/instrumenter.rb +206 -0
  9. data/lib/adsl/extract/meta.rb +33 -0
  10. data/lib/adsl/extract/rails/action_block_builder.rb +233 -0
  11. data/lib/adsl/extract/rails/action_instrumenter.rb +400 -0
  12. data/lib/adsl/extract/rails/action_runner.rb +57 -0
  13. data/lib/adsl/extract/rails/active_record_metaclass_generator.rb +555 -0
  14. data/lib/adsl/extract/rails/callback_chain_simulator.rb +135 -0
  15. data/lib/adsl/extract/rails/invariant_extractor.rb +48 -0
  16. data/lib/adsl/extract/rails/invariant_instrumenter.rb +70 -0
  17. data/lib/adsl/extract/rails/other_meta.rb +57 -0
  18. data/lib/adsl/extract/rails/rails_extractor.rb +211 -0
  19. data/lib/adsl/extract/rails/rails_instrumentation_test_case.rb +34 -0
  20. data/lib/adsl/extract/rails/rails_special_gem_instrumentation.rb +120 -0
  21. data/lib/adsl/extract/rails/rails_test_helper.rb +140 -0
  22. data/lib/adsl/extract/sexp_utils.rb +54 -0
  23. data/lib/adsl/fol/first_order_logic.rb +261 -0
  24. data/lib/adsl/parser/adsl_parser.racc +159 -0
  25. data/lib/{parser → adsl/parser}/adsl_parser.rex +4 -4
  26. data/lib/{parser → adsl/parser}/adsl_parser.rex.rb +6 -6
  27. data/lib/adsl/parser/adsl_parser.tab.rb +1031 -0
  28. data/lib/adsl/parser/ast_nodes.rb +1410 -0
  29. data/lib/adsl/railtie.rb +67 -0
  30. data/lib/adsl/spass/bin.rb +230 -0
  31. data/lib/{spass → adsl/spass}/ruby_extensions.rb +0 -0
  32. data/lib/adsl/spass/spass_ds_extensions.rb +931 -0
  33. data/lib/adsl/spass/spass_translator.rb +393 -0
  34. data/lib/adsl/spass/util.rb +13 -0
  35. data/lib/adsl/util/csv_hash_formatter.rb +94 -0
  36. data/lib/adsl/util/general.rb +228 -0
  37. data/lib/adsl/util/test_helper.rb +71 -0
  38. data/lib/adsl/verification/formula_generators.rb +231 -0
  39. data/lib/adsl/verification/instrumentation_filter.rb +50 -0
  40. data/lib/adsl/verification/invariant.rb +19 -0
  41. data/lib/adsl/verification/rails_verification.rb +33 -0
  42. data/lib/adsl/verification/utils.rb +20 -0
  43. data/lib/adsl/verification/verification_case.rb +13 -0
  44. data/test/integration/rails/rails_branch_verification_test.rb +112 -0
  45. data/test/integration/rails/rails_verification_test.rb +253 -0
  46. data/test/integration/spass/basic_translation_test.rb +563 -0
  47. data/test/integration/spass/control_flow_translation_test.rb +421 -0
  48. data/test/unit/adsl/ds/data_store_spec_test.rb +54 -0
  49. data/test/unit/adsl/extract/instrumenter_test.rb +103 -0
  50. data/test/unit/adsl/extract/meta_test.rb +142 -0
  51. data/test/unit/adsl/extract/rails/action_block_builder_test.rb +178 -0
  52. data/test/unit/adsl/extract/rails/action_instrumenter_test.rb +68 -0
  53. data/test/unit/adsl/extract/rails/active_record_metaclass_generator_test.rb +336 -0
  54. data/test/unit/adsl/extract/rails/callback_chain_simulator_test.rb +76 -0
  55. data/test/unit/adsl/extract/rails/invariant_extractor_test.rb +92 -0
  56. data/test/unit/adsl/extract/rails/rails_extractor_test.rb +1380 -0
  57. data/test/unit/adsl/extract/rails/rails_test_helper_test.rb +25 -0
  58. data/test/unit/adsl/extract/sexp_utils_test.rb +100 -0
  59. data/test/unit/adsl/fol/first_order_logic_test.rb +227 -0
  60. data/test/unit/adsl/parser/action_parser_test.rb +1040 -0
  61. data/test/unit/adsl/parser/ast_nodes_test.rb +359 -0
  62. data/test/unit/adsl/parser/class_parser_test.rb +288 -0
  63. data/test/unit/adsl/parser/general_parser_test.rb +67 -0
  64. data/test/unit/adsl/parser/invariant_parser_test.rb +432 -0
  65. data/test/unit/adsl/parser/parser_util_test.rb +126 -0
  66. data/test/unit/adsl/spass/bin_test.rb +65 -0
  67. data/test/unit/adsl/spass/ruby_extensions_test.rb +39 -0
  68. data/test/unit/adsl/spass/spass_ds_extensions_test.rb +7 -0
  69. data/test/unit/adsl/spass/spass_translator_test.rb +342 -0
  70. data/test/unit/adsl/util/csv_hash_formatter_test.rb +68 -0
  71. data/test/unit/adsl/util/general_test.rb +303 -0
  72. data/test/unit/adsl/util/test_helper_test.rb +120 -0
  73. data/test/unit/adsl/verification/formula_generators_test.rb +200 -0
  74. data/test/unit/adsl/verification/instrumentation_filter_test.rb +39 -0
  75. data/test/unit/adsl/verification/utils_test.rb +39 -0
  76. data/test/unit/adsl/verification/verification_case_test.rb +8 -0
  77. metadata +229 -29
  78. data/lib/ds/data_store_spec.rb +0 -292
  79. data/lib/fol/first_order_logic.rb +0 -260
  80. data/lib/parser/adsl_ast.rb +0 -779
  81. data/lib/parser/adsl_parser.racc +0 -151
  82. data/lib/parser/adsl_parser.tab.rb +0 -976
  83. data/lib/parser/dsdl_parser.rex.rb +0 -196
  84. data/lib/parser/dsdl_parser.tab.rb +0 -976
  85. data/lib/spass/bin.rb +0 -164
  86. data/lib/spass/spass_ds_extensions.rb +0 -870
  87. data/lib/spass/spass_translator.rb +0 -388
  88. data/lib/spass/util.rb +0 -11
  89. data/lib/util/csv_hash_formatter.rb +0 -47
  90. data/lib/util/test_helper.rb +0 -33
  91. data/lib/util/util.rb +0 -114
@@ -0,0 +1,25 @@
1
+ require 'test/unit'
2
+ require 'active_record'
3
+ require 'ruby_parser'
4
+ require 'ruby2ruby'
5
+ require 'adsl/util/test_helper'
6
+ require 'adsl/extract/rails/rails_test_helper'
7
+ require 'adsl/extract/rails/rails_instrumentation_test_case'
8
+
9
+ class ADSL::Extract::Rails::RailsTestHelperTest < ADSL::Extract::Rails::RailsInstrumentationTestCase
10
+ def test__ar_classes_exist_and_work
11
+ assert self.class.const_defined? :Asd
12
+ assert self.class.const_defined? :Kme
13
+ assert self.class.const_defined? :Mod
14
+ assert Mod.const_defined? :Blah
15
+
16
+ a = Asd.new
17
+ a.blahs.build
18
+ a.save!
19
+
20
+ assert_equal 1, Asd.all.length
21
+ a_from_db = Asd.all.first
22
+ assert_equal 1, a_from_db.blahs.length
23
+ assert_equal a_from_db, Mod::Blah.all.first.asd
24
+ end
25
+ end
@@ -0,0 +1,100 @@
1
+ require 'test/unit'
2
+ require 'pp'
3
+ require 'adsl/extract/sexp_utils'
4
+ require 'adsl/util/test_helper'
5
+
6
+ class ADSL::Extract::SexpUtilsTest < Test::Unit::TestCase
7
+ def test_block_replace__no_match
8
+ sexp = s(:array, s(:lit, 1), s(:lit, 2))
9
+
10
+ replacement = sexp.block_replace(:call) do |a|
11
+ "#{a}2".to_sym
12
+ end
13
+ assert_equal s(:array, s(:lit, 1), s(:lit, 2)), replacement
14
+ end
15
+
16
+ def test_block_replace__plain
17
+ sexp = s(:array, s(:lit, 1), s(:lit, 2), s(:lit, 0))
18
+
19
+ replacement = sexp.block_replace(:array) do |a|
20
+ Sexp.from_array [:array] + a.sexp_body.map{ |e| [:lit, e[1] * 2] }
21
+ end
22
+
23
+ assert_equal s(:array, s(:lit, 2), s(:lit, 4), s(:lit, 0)), replacement
24
+ end
25
+
26
+ def test_block_replace__nested
27
+ sexp = s(:array, s(:lit, 1), s(:lit, 2), s(:array, s(:lit, 3)))
28
+
29
+ replacement = sexp.block_replace(:array) do |a|
30
+ Sexp.from_array [:array] + a.sexp_body.map{ |e| e.sexp_type == :lit ? [:lit, e[1] * 2] : e }
31
+ end
32
+
33
+ assert_equal s(:array, s(:lit, 2), s(:lit, 4), s(:array, s(:lit, 6))), replacement
34
+ end
35
+
36
+ def test_block_replace__deep
37
+ sexp = s(:blah, s(:array, s(:lit, 1), s(:lit, 2)))
38
+
39
+ replacement = sexp.block_replace(:lit) do |a|
40
+ s(:lit, a[1]*2)
41
+ end
42
+
43
+ assert_equal s(:blah, s(:array, s(:lit, 2), s(:lit, 4))), replacement
44
+ end
45
+
46
+ def test_block_replace__unless_in
47
+ sexp = s(:blah, s(:array, s(:lit, 1), s(:blah, s(:lit, 1))), s(:lit, 1))
48
+
49
+ replacement = sexp.block_replace(:lit, :unless_in => :array) do |sexp|
50
+ s(:lit, sexp[1]*2)
51
+ end
52
+
53
+ assert_equal s(:blah, s(:array, s(:lit, 1), s(:blah, s(:lit, 1))), s(:lit, 2)), replacement
54
+
55
+
56
+ sexp = s(:blah, s(:array, s(:lit, 1), s(:blah, s(:lit, 1))), s(:lit, 1))
57
+
58
+ replacement = sexp.block_replace(:lit, :unless_in => [:array]) do |sexp|
59
+ s(:lit, sexp[1]*2)
60
+ end
61
+
62
+ assert_equal s(:blah, s(:array, s(:lit, 1), s(:blah, s(:lit, 1))), s(:lit, 2)), replacement
63
+ end
64
+
65
+ def test_find_shallowest__plain
66
+ assert_equal [], s(s(:self)).find_shallowest(:lit)
67
+ assert_equal [s(:lit, 1), s(:lit, 2)], s(s(:lit, 1), s(:self), s(:lit, 2), s(:self)).find_shallowest(:lit)
68
+ end
69
+
70
+ def test_find_shallowest__goes_through_depth
71
+ assert_equal [s(:lit, 1), s(:lit, 2)], s(s(s(:lit, 1), s(:self), s(:lit, 2), s(:self))).find_shallowest(:lit)
72
+ assert_equal [s(:lit, 1), s(:lit, 2)], s(s(:lit, 1), s(s(:self), s(:lit, 2), s(:self))).find_shallowest(:lit)
73
+ end
74
+
75
+ def test_find_shallowest__only_the_shallowest
76
+ assert_equal [s(:lit, s(:lit, 2))], s(s(:lit, s(:lit, 2)), s(:self)).find_shallowest(:lit)
77
+ end
78
+
79
+ def test_may_return_or_raise__simple
80
+ assert_false s(:block, s(:if, s(:true), s(:block), s(:block))).may_return_or_raise?
81
+ assert s(:block, s(:if, s(:true), s(:block), s(:block, s(:return, s(:nil))))).may_return_or_raise?
82
+
83
+ assert_false s(:block, s(:if, s(:true), s(:block), s(:block))).may_return_or_raise?
84
+ assert s(:block, s(:if, s(:true), s(:block), s(:block, s(:call, nil, :raise)))).may_return_or_raise?
85
+ end
86
+
87
+ def test_may_return_or_raise__deep
88
+ sexp = s(:if,
89
+ s(:lasgn, :user, s(:call, s(:const, :User), :authenticate, s(:call, nil, :http_user), s(:call, nil, :http_pass))),
90
+ s(:block,
91
+ s(:attrasgn, s(:call, nil, :session), :[]=, s(:str, "user_id"), s(:call, s(:lvar, :user), :id)),
92
+ s(:call, nil, :set_current_user, s(:lvar, :user)),
93
+ s(:return, s(:true))
94
+ ),
95
+ nil
96
+ )
97
+ assert sexp.may_return_or_raise?
98
+ end
99
+
100
+ end
@@ -0,0 +1,227 @@
1
+ require 'adsl/fol/first_order_logic'
2
+ require 'test/unit'
3
+ require 'pp'
4
+
5
+ class ADSL::FOL::FirstOrderLogicTest < Test::Unit::TestCase
6
+ def teardown
7
+ if Object.constants.include?(:Foo)
8
+ Object.send(:remove_const, :Foo)
9
+ end
10
+ end
11
+
12
+ def test_fol_class_integration
13
+ eval <<-ruby
14
+ class Foo
15
+ include ADSL::FOL
16
+ end
17
+ ruby
18
+ foo = Foo.new
19
+ assert foo.methods.include?("_and") || foo.methods.include?(:_and)
20
+
21
+ eval <<-ruby
22
+ class Foo
23
+ def asd
24
+ _and(:a, :b)
25
+ end
26
+ end
27
+ ruby
28
+ assert_equal "and(a, b)", Foo.new.asd.resolve_spass
29
+ end
30
+
31
+ def test_literals
32
+ assert_equal "true", true.resolve_spass
33
+ assert_equal "false", false.resolve_spass
34
+ assert_equal "symbol_here", :symbol_here.resolve_spass
35
+ assert_equal "sometext", "sometext".resolve_spass
36
+ end
37
+
38
+ def test_split_by_zero_level_comma
39
+ assert_equal [""], "".split_by_zero_level_comma
40
+ assert_equal ["asd"], "asd".split_by_zero_level_comma
41
+ assert_equal ["asd", "kme"], "asd,kme".split_by_zero_level_comma
42
+ assert_equal ["asd", ""], "asd,".split_by_zero_level_comma
43
+ assert_equal ["", ""], ",".split_by_zero_level_comma
44
+ assert_equal ["(asd, asd)"], "(asd, asd)".split_by_zero_level_comma
45
+ assert_equal ["(a,a,a,()((()())))", ""], "(a,a,a,()((()()))),".split_by_zero_level_comma
46
+ assert_raise do
47
+ ")(".split_by_zero_level_comma
48
+ end
49
+ end
50
+
51
+ def test_not
52
+ assert_raise ArgumentError do
53
+ ADSL::FOL::Not.new
54
+ end
55
+ assert_equal "not(a)", ADSL::FOL::Not.new(:a).resolve_spass
56
+ assert_equal "and(not(a), not(b))".gsub(/\s+/, ''), \
57
+ ADSL::FOL::Not.new(:a, :b).resolve_spass.gsub(/\s+/, '')
58
+ assert_equal "true", ADSL::FOL::Not.new(false).resolve_spass
59
+ assert_equal "false", ADSL::FOL::Not.new(true).resolve_spass
60
+ assert_equal "false", ADSL::FOL::Not.new(true, false).resolve_spass
61
+ assert_equal "a", ADSL::FOL::Not.new(ADSL::FOL::Not.new(:a)).resolve_spass
62
+ assert_equal "and(a, not(b))", ADSL::FOL::Not.new(ADSL::FOL::Not.new(:a), ADSL::FOL::Not.new(ADSL::FOL::Not.new(:b))).resolve_spass
63
+ end
64
+
65
+ def test_and
66
+ assert_equal "true", ADSL::FOL::And.new.resolve_spass
67
+
68
+ assert_equal "a", ADSL::FOL::And.new("a").resolve_spass
69
+ assert_equal "and(a, b)", ADSL::FOL::And.new("a", "b").resolve_spass
70
+
71
+ assert_equal "a", ADSL::FOL::And.new(true, 'a').resolve_spass
72
+ assert_equal "and(a, b)", ADSL::FOL::And.new(true, "a", "b").resolve_spass
73
+ assert_equal "false", ADSL::FOL::And.new(true, false).resolve_spass
74
+ assert_equal "true", ADSL::FOL::And.new(true).resolve_spass
75
+
76
+ assert_equal "and(a, b, c)", ADSL::FOL::And.new(ADSL::FOL::And.new(:a, :b), :c).resolve_spass
77
+ end
78
+
79
+ def test_or
80
+ assert_equal "false", ADSL::FOL::Or.new.resolve_spass
81
+
82
+ assert_equal "a", ADSL::FOL::Or.new("a").resolve_spass
83
+ assert_equal "or(a, b)", ADSL::FOL::Or.new("a", "b").resolve_spass
84
+
85
+ assert_equal "a", ADSL::FOL::Or.new(false, 'a').resolve_spass
86
+ assert_equal "or(a, b)", ADSL::FOL::Or.new(false, "a", "b").resolve_spass
87
+ assert_equal "true", ADSL::FOL::Or.new(true, false).resolve_spass
88
+ assert_equal "false", ADSL::FOL::Or.new(false).resolve_spass
89
+
90
+ assert_equal "or(a, b, c)", ADSL::FOL::Or.new(ADSL::FOL::Or.new(:a, :b), :c).resolve_spass
91
+ end
92
+
93
+ def test_forall
94
+ assert_raise ArgumentError do
95
+ ADSL::FOL::ForAll.new
96
+ end
97
+
98
+ assert_equal "a", ADSL::FOL::ForAll.new(:a).resolve_spass
99
+ assert_equal "true", ADSL::FOL::ForAll.new(:a, :b, true).resolve_spass
100
+ assert_equal "false", ADSL::FOL::ForAll.new(:a, :b, false).resolve_spass
101
+ assert_equal "forall([a], blah(a))".gsub(/\s+/, ''), \
102
+ ADSL::FOL::ForAll.new(:a, "blah(a)").resolve_spass.gsub(/\s+/, '')
103
+ assert_equal "forall([a, b], blah(a))".gsub(/\s+/, ''), \
104
+ ADSL::FOL::ForAll.new(:a, :b, "blah(a)").resolve_spass.gsub(/\s+/, '')
105
+ end
106
+
107
+ def test_exists
108
+ assert_raise ArgumentError do
109
+ ADSL::FOL::Exists.new
110
+ end
111
+
112
+ assert_equal "a", ADSL::FOL::Exists.new(:a).resolve_spass
113
+ assert_equal "true", ADSL::FOL::ForAll.new(:a, :b, true).resolve_spass
114
+ assert_equal "false", ADSL::FOL::ForAll.new(:a, :b, false).resolve_spass
115
+ assert_equal "exists([a], true(a))".gsub(/\s+/, ''), \
116
+ ADSL::FOL::Exists.new(:a, "true(a)").resolve_spass.gsub(/\s+/, '')
117
+ assert_equal "exists([a, b], true(a))".gsub(/\s+/, ''), \
118
+ ADSL::FOL::Exists.new(:a, :b, "true(a)").resolve_spass.gsub(/\s+/, '')
119
+ end
120
+
121
+ def test_equiv
122
+ assert_raise ArgumentError do
123
+ ADSL::FOL::Equiv.new
124
+ end
125
+ assert_raise ArgumentError do
126
+ ADSL::FOL::Equiv.new :a
127
+ end
128
+
129
+ assert_equal 'a', ADSL::FOL::Equiv.new(true, :a).resolve_spass
130
+ assert_equal 'and(a, b)', ADSL::FOL::Equiv.new(:a, true, :b).resolve_spass
131
+ assert_equal 'and(not(a), not(b))', ADSL::FOL::Equiv.new(:a, false, :b).resolve_spass
132
+ assert_equal 'false', ADSL::FOL::Equiv.new(:a, false, :b, true).resolve_spass
133
+ assert_equal "equiv(a, b)".gsub(/\s+/, ''), \
134
+ ADSL::FOL::Equiv.new(:a, :b).resolve_spass.gsub(/\s+/, '')
135
+ assert_equal "and(equiv(a, b), equiv(b, c))".gsub(/\s+/, ''), \
136
+ ADSL::FOL::Equiv.new(:a, :b, :c).resolve_spass.gsub(/\s+/, '')
137
+ end
138
+
139
+ def test_implies
140
+ assert_raise ArgumentError do
141
+ ADSL::FOL::Implies.new
142
+ end
143
+ assert_raise ArgumentError do
144
+ ADSL::FOL::Implies.new :a
145
+ end
146
+ assert_raise ArgumentError do
147
+ ADSL::FOL::Implies.new :a, :b, :c
148
+ end
149
+
150
+ assert_equal "implies(a, b)".gsub(/\s+/, ''), \
151
+ ADSL::FOL::Implies.new(:a, :b).resolve_spass.gsub(/\s+/, '')
152
+ assert_equal "a".gsub(/\s+/, ''), \
153
+ ADSL::FOL::Implies.new(true, :a).resolve_spass.gsub(/\s+/, '')
154
+ assert_equal "true".gsub(/\s+/, ''), \
155
+ ADSL::FOL::Implies.new(:a, true).resolve_spass.gsub(/\s+/, '')
156
+ assert_equal "true".gsub(/\s+/, ''), \
157
+ ADSL::FOL::Implies.new(false, :a).resolve_spass.gsub(/\s+/, '')
158
+ assert_equal "not(a)".gsub(/\s+/, ''), \
159
+ ADSL::FOL::Implies.new(:a, false).resolve_spass.gsub(/\s+/, '')
160
+
161
+ assert_equal 'true', ADSL::FOL::Implies.new(true, true).resolve_spass
162
+ assert_equal 'false', ADSL::FOL::Implies.new(true, false).resolve_spass
163
+ assert_equal 'true', ADSL::FOL::Implies.new(false, true).resolve_spass
164
+ assert_equal 'true', ADSL::FOL::Implies.new(false, false).resolve_spass
165
+ end
166
+
167
+ def test_equal
168
+ assert_raise ArgumentError do
169
+ ADSL::FOL::Equal.new
170
+ end
171
+ assert_raise ArgumentError do
172
+ ADSL::FOL::Equal.new :a
173
+ end
174
+
175
+ assert_equal "equal(a, b)".gsub(/\s+/, ''), \
176
+ ADSL::FOL::Equal.new(:a, :b).resolve_spass.gsub(/\s+/, '')
177
+ assert_equal "and(equal(a, b), equal(b, c))".gsub(/\s+/, ''), \
178
+ ADSL::FOL::Equal.new(:a, :b, :c).resolve_spass.gsub(/\s+/, '')
179
+ end
180
+
181
+ def test_one_of
182
+ assert_equal 'false', ADSL::FOL::OneOf.new.resolve_spass
183
+ assert_equal "a".gsub(/\s+/, ''), \
184
+ ADSL::FOL::OneOf.new(:a).resolve_spass.gsub(/\s+/, '')
185
+ assert_equal "equiv(not(a), b)".gsub(/\s+/, ''), \
186
+ ADSL::FOL::OneOf.new(:a, :b).resolve_spass.gsub(/\s+/, '')
187
+ assert_equal "and(or(a, b, c), implies(a, and(not(b), not(c))), implies(b, and(not(a), not(c))), implies(c, and(not(a), not(b))))".gsub(/\s+/, ''), \
188
+ ADSL::FOL::OneOf.new(:a, :b, :c).resolve_spass.gsub(/\s+/, '')
189
+ end
190
+
191
+ def test_if_then_else
192
+ assert_equal "and(implies(a, b), implies(not(a), c))".gsub(/\s+/, ''), \
193
+ ADSL::FOL::IfThenElse.new(:a, :b, :c).resolve_spass.gsub(/\s+/, '')
194
+ end
195
+
196
+ def test_if_then_else_eq
197
+ assert_equal "and(equiv(a, b), equiv(not(a), c))".gsub(/\s+/, ''), \
198
+ ADSL::FOL::IfThenElseEq.new(:a, :b, :c).resolve_spass.gsub(/\s+/, '')
199
+ end
200
+
201
+ def test_pairwise_equal__explicit_lists
202
+ assert_raise ArgumentError do
203
+ ADSL::FOL::PairwiseEqual.new [], [:a]
204
+ end
205
+ assert_raise ArgumentError do
206
+ ADSL::FOL::PairwiseEqual.new [:b, :c], [:a]
207
+ end
208
+
209
+ assert_equal "true", ADSL::FOL::PairwiseEqual.new([], []).resolve_spass
210
+ assert_equal "equal(a1, b1)", ADSL::FOL::PairwiseEqual.new([:a1], [:b1]).resolve_spass
211
+ assert_equal "and(equal(a1, b1), equal(a2, b2))", ADSL::FOL::PairwiseEqual.new([:a1, :a2], [:b1, :b2]).resolve_spass
212
+ end
213
+
214
+ def test_pairwise_equal__implicit_lists
215
+ assert_raise ArgumentError do
216
+ ADSL::FOL::PairwiseEqual.new :a
217
+ end
218
+ assert_raise ArgumentError do
219
+ ADSL::FOL::PairwiseEqual.new :b, [[:c]], :a
220
+ end
221
+
222
+ assert_equal "true", ADSL::FOL::PairwiseEqual.new().resolve_spass
223
+ assert_equal "equal(a1, b1)", ADSL::FOL::PairwiseEqual.new(:a1, :b1).resolve_spass
224
+ assert_equal "and(equal(a1, b1), equal(a2, b2))", ADSL::FOL::PairwiseEqual.new(:a1, :a2, :b1, [:b2]).resolve_spass
225
+ end
226
+ end
227
+
@@ -0,0 +1,1040 @@
1
+ require 'adsl/parser/adsl_parser.tab'
2
+ require 'adsl/ds/data_store_spec'
3
+ require 'test/unit'
4
+ require 'pp'
5
+
6
+ module ADSL::Parser
7
+ class ActionParserTest < Test::Unit::TestCase
8
+ include ADSL::DS
9
+
10
+ def test_action__empty
11
+ parser = ADSLParser.new
12
+ spec = nil
13
+ assert_nothing_raised ADSLError do
14
+ spec = parser.parse ""
15
+ end
16
+ assert_equal([], spec.actions)
17
+ end
18
+
19
+ def test_action__no_stmts
20
+ parser = ADSLParser.new
21
+ spec = nil
22
+ assert_nothing_raised ADSLError do
23
+ spec = parser.parse <<-adsl
24
+ action do_something() {
25
+ }
26
+ adsl
27
+ end
28
+ assert_equal 1, spec.actions.length
29
+ assert_equal 0, spec.actions.first.block.statements.length
30
+ assert_equal "do_something", spec.actions.first.name
31
+ end
32
+
33
+ def test_action__vars_are_stored
34
+ parser = ADSLParser.new
35
+ spec = nil
36
+ assert_nothing_raised ADSLError do
37
+ spec = parser.parse <<-adsl
38
+ class Class {}
39
+ action do_something() {
40
+ var = allof(Class)
41
+ var = var
42
+ }
43
+ adsl
44
+ end
45
+ assert_equal 1, spec.actions.length
46
+ assert_equal 2, spec.actions.first.block.statements.length
47
+ var1 = spec.actions.first.statements.first.var
48
+ assert_equal var1, spec.actions.first.statements.last.objset
49
+ var2 = spec.actions.first.statements.last.var
50
+ assert var1 != var2
51
+ end
52
+
53
+ def test_action__context_difference
54
+ context1 = ASTTypecheckResolveContext.new
55
+ context1.push_frame
56
+
57
+ a1 = DSVariable.new :name => 'a'
58
+ a2 = DSVariable.new :name => 'a'
59
+ b = DSVariable.new :name => 'b'
60
+ b2 = DSVariable.new :name => 'b'
61
+
62
+ context1.define_var a1, true
63
+ context1.define_var b, true
64
+
65
+ context2 = context1.dup
66
+
67
+ context2.redefine_var a2, false
68
+
69
+ assert_equal({"a" => [a1, a2]}, ASTTypecheckResolveContext.context_vars_that_differ(context1, context2))
70
+
71
+ context3 = context2.dup
72
+ assert_equal({"a" => [a1, a2, a2]}, ASTTypecheckResolveContext.context_vars_that_differ(context1, context2, context3))
73
+
74
+ context3.redefine_var b2, false
75
+ assert_equal({"a" => [a1, a2, a2], "b" => [b, b, b2]}, ASTTypecheckResolveContext.context_vars_that_differ(context1, context2, context3))
76
+ end
77
+
78
+ def test_action__all_stmts_no_subblocks
79
+ parser = ADSLParser.new
80
+ spec = nil
81
+ assert_nothing_raised ADSLError do
82
+ spec = parser.parse <<-adsl
83
+ class Class { 0+ Class relation }
84
+ action do_something() {
85
+ var = create(Class)
86
+ create(Class)
87
+ delete var
88
+ var.relation += var
89
+ var.relation -= var
90
+ }
91
+ adsl
92
+ end
93
+ assert_equal 1, spec.actions.length
94
+ assert_equal 'do_something', spec.actions.first.name
95
+ statements = spec.actions.first.block.statements
96
+ assert_equal 6, statements.length
97
+ relation = spec.classes.first.relations.first
98
+
99
+ assert_equal spec.classes.first, statements[0].klass
100
+
101
+ var = statements[1].var
102
+ assert !var.nil?
103
+ assert_equal 'var', var.name
104
+
105
+ assert_equal spec.classes.first, statements[2].klass
106
+
107
+ assert_equal var, statements[3].objset
108
+
109
+ assert_equal var, statements[4].objset1
110
+ assert_equal var, statements[4].objset2
111
+ assert_equal relation, statements[4].relation
112
+
113
+ assert_equal var, statements[5].objset1
114
+ assert_equal var, statements[5].objset2
115
+ assert_equal relation, statements[5].relation
116
+ end
117
+
118
+ def test_action__multiple_creates_in_single_stmt
119
+ parser = ADSLParser.new
120
+ spec = nil
121
+ assert_nothing_raised ADSLError do
122
+ spec = parser.parse <<-adsl
123
+ class Class { 0+ Class relation}
124
+ action do_something() {
125
+ create(Class).relation += create(Class)
126
+ }
127
+ adsl
128
+ end
129
+ statements = spec.actions.first.block.statements
130
+ assert_equal 3, statements.length
131
+ assert_equal spec.classes.first, statements[0].klass
132
+ assert_equal spec.classes.first, statements[1].klass
133
+ end
134
+
135
+ def test_action__args_typecheck
136
+ parser = ADSLParser.new
137
+ spec = nil
138
+ assert_nothing_raised ADSLError do
139
+ spec = parser.parse <<-adsl
140
+ class Class {}
141
+ action do_something(0+ Class var1) {
142
+ var2 = var1
143
+ }
144
+ adsl
145
+ end
146
+
147
+ klass = spec.classes.first
148
+ var1 = spec.actions.first.args.first
149
+ var2 = spec.actions.first.statements.first.var
150
+
151
+ assert_equal klass, var1.type
152
+ assert_equal klass, var2.type
153
+ end
154
+
155
+ def test_action__args_multiple
156
+ parser = ADSLParser.new
157
+ spec = nil
158
+ assert_nothing_raised ADSLError do
159
+ spec = parser.parse <<-adsl
160
+ class Class1 {}
161
+ class Class2 {}
162
+ class Class3 {}
163
+ action do_something(0..1 Class1 var1, 1 Class2 var2, 1+ Class3 var3) {
164
+ }
165
+ adsl
166
+ end
167
+ assert_equal ['var1', 'var2', 'var3'], spec.actions.first.args.map{ |v| v.name }
168
+ assert_equal spec.classes, spec.actions.first.args.map{ |v| v.type }
169
+ assert_equal [[0, 1], [1, 1], [1, 1.0/0.0]], spec.actions.first.cardinalities
170
+ end
171
+
172
+ def test_action__createtup_deletetup_typecheck
173
+ ['+=', '-='].each do |operator|
174
+ parser = ADSLParser.new
175
+ spec = nil
176
+ assert_nothing_raised ADSLError do
177
+ spec = parser.parse <<-adsl
178
+ class Class { 1 Class rel }
179
+ action blah() {
180
+ allof(Class).rel #{operator} allof(Class)
181
+ }
182
+ adsl
183
+ end
184
+ stmt = spec.actions.first.block.statements.first
185
+ assert_equal spec.classes.first, stmt.objset1.klass
186
+ assert_equal spec.classes.first, stmt.objset2.klass
187
+ assert_equal spec.classes.first.relations.first, stmt.relation
188
+
189
+ assert_raise ADSLError do
190
+ parser.parse <<-adsl
191
+ class Class1 { 1 Class1 rel }
192
+ class Class2 {}
193
+ action blah() {
194
+ allof(Class2).rel #{operator} allof(Class1)
195
+ }
196
+ adsl
197
+ end
198
+
199
+ assert_raise ADSLError do
200
+ parser.parse <<-adsl
201
+ class Class1 { 1 Class1 rel }
202
+ class Class2 {}
203
+ action blah() {
204
+ allof(Class1).rel #{operator} allof(Class2)
205
+ }
206
+ adsl
207
+ end
208
+ end
209
+ end
210
+
211
+ def test_action__superclass_createtup_deletetup_typecheck
212
+ parser = ADSLParser.new
213
+ ['+=', '-='].each do |operator|
214
+ spec = nil
215
+ assert_nothing_raised ADSLError do
216
+ spec = parser.parse <<-adsl
217
+ class Super { 1 Super rel }
218
+ class Sub extends Super {}
219
+ action blah() {
220
+ allof(Super).rel #{operator} allof(Sub)
221
+ }
222
+ adsl
223
+ end
224
+ stmt = spec.actions.first.block.statements.first
225
+ assert_equal spec.classes[0], stmt.objset1.klass
226
+ assert_equal spec.classes[1], stmt.objset2.klass
227
+ assert_equal spec.classes[0].relations.first, stmt.relation
228
+
229
+ assert_nothing_raised ADSLError do
230
+ spec = parser.parse <<-adsl
231
+ class Super { 1 Super rel }
232
+ class Sub extends Super {}
233
+ action blah() {
234
+ allof(Sub).rel #{operator} allof(Sub)
235
+ }
236
+ adsl
237
+ end
238
+ stmt = spec.actions.first.block.statements.first
239
+ assert_equal spec.classes[1], stmt.objset1.klass
240
+ assert_equal spec.classes[1], stmt.objset2.klass
241
+ assert_equal spec.classes[0].relations.first, stmt.relation
242
+
243
+ assert_nothing_raised ADSLError do
244
+ spec = parser.parse <<-adsl
245
+ class Super {}
246
+ class Sub extends Super { 1 Super rel }
247
+ action blah() {
248
+ allof(Sub).rel #{operator} allof(Sub)
249
+ }
250
+ adsl
251
+ end
252
+ stmt = spec.actions.first.block.statements.first
253
+ assert_equal spec.classes[1], stmt.objset1.klass
254
+ assert_equal spec.classes[1], stmt.objset2.klass
255
+ assert_equal spec.classes[1].relations.first, stmt.relation
256
+
257
+ assert_raise ADSLError do
258
+ parser.parse <<-adsl
259
+ class Super {}
260
+ class Sub extends Super { 1 Sub rel }
261
+ action blah() {
262
+ allof(Super).rel #{operator} allof(Super)
263
+ }
264
+ adsl
265
+ end
266
+
267
+ assert_raise ADSLError do
268
+ parser.parse <<-adsl
269
+ class Super {}
270
+ class Sub extends Super { 1 Sub rel }
271
+ action blah() {
272
+ allof(Sub).rel #{operator} allof(Super)
273
+ }
274
+ adsl
275
+ end
276
+ end
277
+ end
278
+
279
+ def test_action__superclass_settup_typecheck
280
+ parser = ADSLParser.new
281
+
282
+ spec = nil
283
+ assert_nothing_raised ADSLError do
284
+ spec = parser.parse <<-adsl
285
+ class Super { 1 Super rel }
286
+ class Sub extends Super {}
287
+ action blah() {
288
+ allof(Super).rel = allof(Sub)
289
+ }
290
+ adsl
291
+ end
292
+ stmt1 = spec.actions.first.block.statements.first
293
+ stmt2 = spec.actions.first.block.statements.last
294
+ assert_equal spec.classes[0], stmt1.objset1.klass
295
+ assert_equal spec.classes[0], stmt1.objset2.klass
296
+ assert_equal spec.classes[0].relations.first, stmt1.relation
297
+ assert_equal spec.classes[0], stmt2.objset1.klass
298
+ assert_equal spec.classes[1], stmt2.objset2.klass
299
+ assert_equal spec.classes[0].relations.first, stmt2.relation
300
+
301
+ assert_nothing_raised ADSLError do
302
+ spec = parser.parse <<-adsl
303
+ class Super { 1 Super rel }
304
+ class Sub extends Super {}
305
+ action blah() {
306
+ allof(Sub).rel = allof(Sub)
307
+ }
308
+ adsl
309
+ end
310
+ stmt1 = spec.actions.first.block.statements.first
311
+ stmt2 = spec.actions.first.block.statements.last
312
+ assert_equal spec.classes[1], stmt1.objset1.klass
313
+ assert_equal spec.classes[0], stmt1.objset2.klass
314
+ assert_equal spec.classes[0].relations.first, stmt1.relation
315
+ assert_equal spec.classes[1], stmt2.objset1.klass
316
+ assert_equal spec.classes[1], stmt2.objset2.klass
317
+ assert_equal spec.classes[0].relations.first, stmt2.relation
318
+
319
+ assert_nothing_raised ADSLError do
320
+ spec = parser.parse <<-adsl
321
+ class Super {}
322
+ class Sub extends Super { 1 Super rel }
323
+ action blah() {
324
+ allof(Sub).rel = allof(Sub)
325
+ }
326
+ adsl
327
+ end
328
+ stmt1 = spec.actions.first.block.statements.first
329
+ stmt2 = spec.actions.first.block.statements.last
330
+ assert_equal spec.classes[1], stmt1.objset1.klass
331
+ assert_equal spec.classes[0], stmt1.objset2.klass
332
+ assert_equal spec.classes[1].relations.first, stmt1.relation
333
+ assert_equal spec.classes[1], stmt2.objset1.klass
334
+ assert_equal spec.classes[1], stmt2.objset2.klass
335
+ assert_equal spec.classes[1].relations.first, stmt2.relation
336
+
337
+ assert_raise ADSLError do
338
+ parser.parse <<-adsl
339
+ class Super {}
340
+ class Sub extends Super { 1 Sub rel }
341
+ action blah() {
342
+ allof(Super).rel = allof(Super)
343
+ }
344
+ adsl
345
+ end
346
+
347
+ assert_raise ADSLError do
348
+ parser.parse <<-adsl
349
+ class Super {}
350
+ class Sub extends Super { 1 Sub rel }
351
+ action blah() {
352
+ allof(Sub).rel = allof(Super)
353
+ }
354
+ adsl
355
+ end
356
+ end
357
+
358
+ def test_action__args_cardinality
359
+ parser = ADSLParser.new
360
+ assert_nothing_raised ADSLError do
361
+ spec = parser.parse <<-adsl
362
+ class Class {}
363
+ action do_something(0..1 Class var1) {
364
+ }
365
+ adsl
366
+ spec = parser.parse <<-adsl
367
+ class Class {}
368
+ action do_something(1 Class var1) {
369
+ }
370
+ adsl
371
+ spec = parser.parse <<-adsl
372
+ class Class {}
373
+ action do_something(1..1 Class var1) {
374
+ }
375
+ adsl
376
+ spec = parser.parse <<-adsl
377
+ class Class {}
378
+ action do_something(0+ Class var1) {
379
+ }
380
+ adsl
381
+ spec = parser.parse <<-adsl
382
+ class Class {}
383
+ action do_something(1+ Class var1) {
384
+ }
385
+ adsl
386
+ end
387
+ assert_raise do
388
+ parser.parse <<-adsl
389
+ class Class{}
390
+ action do_something(1..0)
391
+ adsl
392
+ end
393
+ assert_raise do
394
+ parser.parse <<-adsl
395
+ class Class{}
396
+ action do_something(0)
397
+ adsl
398
+ end
399
+ assert_raise do
400
+ parser.parse <<-adsl
401
+ class Class{}
402
+ action do_something(0..0)
403
+ adsl
404
+ end
405
+ end
406
+
407
+ def test_action__ssa_by_default
408
+ parser = ADSLParser.new
409
+ spec = nil
410
+ assert_nothing_raised ADSLError do
411
+ spec = parser.parse <<-adsl
412
+ class Class {}
413
+ action do_something(0+ Class var1, 0+ Class var2) {
414
+ var2 = var1
415
+ }
416
+ adsl
417
+ end
418
+
419
+ arg1 = spec.actions.first.args.first
420
+ arg2 = spec.actions.first.args.last
421
+ redefined = spec.actions.first.statements.first.var
422
+
423
+ assert arg1 != arg2
424
+ assert arg2 != redefined
425
+ end
426
+
427
+ def test_action__allof_typecheck
428
+ parser = ADSLParser.new
429
+ spec = nil
430
+ assert_nothing_raised ADSLError do
431
+ spec = parser.parse <<-adsl
432
+ class Class { 0+ Class relation }
433
+ action do_something() {
434
+ var = allof(Class)
435
+ var.relation -= var
436
+ }
437
+ adsl
438
+ end
439
+
440
+ assert_equal 1, spec.actions.length
441
+ klass = spec.classes.first
442
+ relation = spec.classes.first.relations.first
443
+
444
+ assert_equal relation, spec.actions.first.block.statements.last.relation
445
+
446
+ assert_raise ADSLError do
447
+ parser.parse <<-adsl
448
+ class Class { 0+ Class relation }
449
+ class Class2 {}
450
+ action do_something() {
451
+ var1 = allof(Class)
452
+ var2 = allof(Class2)
453
+ var1.relation -= var2
454
+ }
455
+ adsl
456
+ end
457
+ end
458
+
459
+ def test_action__subset_typecheck
460
+ parser = ADSLParser.new
461
+ spec = nil
462
+ assert_nothing_raised ADSLError do
463
+ spec = parser.parse <<-adsl
464
+ class Class { 0+ Class relation }
465
+ action do_something() {
466
+ var = subset(allof(Class))
467
+ var.relation -= var
468
+ }
469
+ adsl
470
+ end
471
+
472
+ assert_equal 1, spec.actions.length
473
+ klass = spec.classes.first
474
+ relation = spec.classes.first.relations.first
475
+
476
+ assert_equal relation, spec.actions.first.block.statements.last.relation
477
+
478
+ assert_raise ADSLError do
479
+ parser.parse <<-adsl
480
+ class Class { 0+ Class relation }
481
+ class Class2 {}
482
+ action do_something() {
483
+ var1 = allof(Class)
484
+ var2 = subset(allof(Class2))
485
+ var1.relation -= var2
486
+ }
487
+ adsl
488
+ end
489
+ end
490
+
491
+ def test_action__oneof_typecheck
492
+ parser = ADSLParser.new
493
+ spec = nil
494
+ assert_nothing_raised ADSLError do
495
+ spec = parser.parse <<-adsl
496
+ class Class { 0+ Class relation }
497
+ action do_something() {
498
+ var = oneof(allof(Class))
499
+ var.relation -= var
500
+ }
501
+ adsl
502
+ end
503
+
504
+ assert_equal 1, spec.actions.length
505
+ klass = spec.classes.first
506
+ relation = spec.classes.first.relations.first
507
+
508
+ assert_equal relation, spec.actions.first.block.statements.last.relation
509
+
510
+ assert_raise ADSLError do
511
+ parser.parse <<-adsl
512
+ class Class { 0+ Class relation }
513
+ class Class2 {}
514
+ action do_something() {
515
+ var1 = allof(Class)
516
+ var2 = oneof(allof(Class2))
517
+ var1.relation -= var2
518
+ }
519
+ adsl
520
+ end
521
+ end
522
+
523
+ def test_action__deref_typecheck
524
+ parser = ADSLParser.new
525
+ spec = nil
526
+ assert_nothing_raised ADSLError do
527
+ spec = parser.parse <<-adsl
528
+ class Class1 { 0+ Class2 relation }
529
+ class Class2 { 0+ Class2 other_relation }
530
+ action do_something() {
531
+ allof(Class1).relation.other_relation -= allof(Class2)
532
+ }
533
+ adsl
534
+ end
535
+
536
+ assert_equal 1, spec.actions.length
537
+ klass2 = spec.classes.last
538
+ relation = klass2.relations.first
539
+
540
+ stmt = spec.actions.first.block.statements.last
541
+ assert_equal klass2, stmt.objset1.type
542
+ assert_equal relation, stmt.relation
543
+
544
+ assert_raise ADSLError do
545
+ parser.parse <<-adsl
546
+ class Class1 { 0+ Class2 relation }
547
+ class Class2 { 0+ Class2 other_relation }
548
+ action do_something() {
549
+ allof(Class1).relation.relation -= allof(Class2)
550
+ }
551
+ adsl
552
+ end
553
+ end
554
+
555
+ def test_action__deref_superclass_typecheck
556
+ parser = ADSLParser.new
557
+ spec = nil
558
+
559
+ assert_nothing_raised ADSLError do
560
+ spec = parser.parse <<-adsl
561
+ class Class1 { 0+ Class2 relation }
562
+ class Class2 extends Class1 { 0+ Class2 other_relation }
563
+ action do_something() {
564
+ allof(Class1).relation.other_relation -= allof(Class2)
565
+ }
566
+ adsl
567
+ end
568
+ klass2 = spec.classes.last
569
+ relation = klass2.relations.first
570
+ stmt = spec.actions.first.block.statements.last
571
+ assert_equal klass2, stmt.objset1.type
572
+ assert_equal relation, stmt.relation
573
+
574
+ assert_nothing_raised ADSLError do
575
+ spec = parser.parse <<-adsl
576
+ class Class1 { 0+ Class2 relation }
577
+ class Class2 extends Class1 { 0+ Class2 other_relation }
578
+ action do_something() {
579
+ allof(Class2).relation.other_relation -= allof(Class2)
580
+ }
581
+ adsl
582
+ end
583
+ klass2 = spec.classes.last
584
+ relation = klass2.relations.first
585
+ stmt = spec.actions.first.block.statements.last
586
+ assert_equal klass2, stmt.objset1.type
587
+ assert_equal relation, stmt.relation
588
+ end
589
+
590
+ def test_action__subblocks
591
+ parser = ADSLParser.new
592
+ spec = parser.parse <<-adsl
593
+ class Class { 0+ Class relation }
594
+ action do_something() {
595
+ var = allof(Class)
596
+ foreach subvar: var {
597
+ var.relation -= subvar
598
+ }
599
+ either {
600
+ delete var
601
+ } or {
602
+ create(Class)
603
+ }
604
+ foreach subvar: var {}
605
+ }
606
+ adsl
607
+
608
+ assert_equal 1, spec.actions.length
609
+ stmts = spec.actions.first.block.statements
610
+ var = stmts[0].var
611
+ klass = spec.classes.first
612
+
613
+ assert_equal var, stmts[1].objset
614
+
615
+ assert_equal var, stmts[2].blocks[0].statements.first.objset
616
+
617
+ assert_equal klass, stmts[2].blocks[1].statements.first.klass
618
+ end
619
+
620
+ def test_action__subblocks_dont_undefine_variables
621
+ parser = ADSLParser.new
622
+ assert_nothing_raised ADSLError do
623
+ parser.parse <<-adsl
624
+ class Class {}
625
+ action do_something() {
626
+ var = allof(Class)
627
+ either {
628
+ var = allof(Class)
629
+ } or {
630
+ }
631
+ var = var
632
+ }
633
+ adsl
634
+ end
635
+ end
636
+
637
+ def test_action__types_are_static
638
+ parser = ADSLParser.new
639
+ assert_raise ADSLError do
640
+ parser.parse <<-adsl
641
+ class Class {}
642
+ class Class2 {}
643
+ action do_something() {
644
+ var = allof(Class)
645
+ var = allof(Class2)
646
+ }
647
+ adsl
648
+ end
649
+ end
650
+
651
+ def test_action__either_variable_number_of_blocks
652
+ parser = ADSLParser.new
653
+ assert_raise do
654
+ parser.parse <<-adsl
655
+ class Class {}
656
+ action do_something() {
657
+ either {}
658
+ }
659
+ adsl
660
+ end
661
+ spec = parser.parse <<-adsl
662
+ class Class {}
663
+ action do_something() {
664
+ either {
665
+ } or {
666
+ create(Class)
667
+ }
668
+ }
669
+ adsl
670
+ either = spec.actions.first.block.statements.first
671
+ assert_equal 2, either.blocks.length
672
+ assert_equal 0, either.blocks[0].statements.length
673
+ assert_equal 1, either.blocks[1].statements.length
674
+
675
+ spec = parser.parse <<-adsl
676
+ class Class {}
677
+ action do_something() {
678
+ either {
679
+ } or {
680
+ create(Class)
681
+ } or {
682
+ create(Class)
683
+ create(Class)
684
+ }
685
+ }
686
+ adsl
687
+ either = spec.actions.first.block.statements.first
688
+ assert_equal 3, either.blocks.length
689
+ assert_equal 0, either.blocks[0].statements.length
690
+ assert_equal 1, either.blocks[1].statements.length
691
+ assert_equal 2, either.blocks[2].statements.length
692
+ end
693
+
694
+ def test_action__unmatching_types_in_either
695
+ parser = ADSLParser.new
696
+ assert_raise ADSLError do
697
+ parser.parse <<-adsl
698
+ class Class {}
699
+ class Class2 {}
700
+ action do_something() {
701
+ var = allof(Class)
702
+ either {
703
+ var = allof(Class)
704
+ } or {
705
+ var = allof(Class2)
706
+ }
707
+ }
708
+ adsl
709
+ end
710
+ end
711
+
712
+ def test_action__unmatching_types_in_either_but_inside
713
+ parser = ADSLParser.new
714
+ assert_nothing_raised ADSLError do
715
+ parser.parse <<-adsl
716
+ class Class {}
717
+ class Class2 {}
718
+ action do_something() {
719
+ either {
720
+ var = allof(Class2)
721
+ } or {
722
+ var = allof(Class)
723
+ }
724
+ }
725
+ adsl
726
+ end
727
+ end
728
+
729
+ def test_action__foreach_iterator_var_typecheck
730
+ parser = ADSLParser.new
731
+ assert_nothing_raised ADSLError do
732
+ parser.parse <<-adsl
733
+ class Class { 0+ Class relation }
734
+ action do_something() {
735
+ foreach var: allof(Class) {
736
+ var.relation -= allof(Class)
737
+ }
738
+ }
739
+ adsl
740
+ end
741
+ assert_raise ADSLError do
742
+ parser.parse <<-adsl
743
+ class Class {}
744
+ class Class2 { 0+ Class2 relation }
745
+ action do_something() {
746
+ foreach var: allof(Class) {
747
+ var.relation -= allof(Class)
748
+ }
749
+ }
750
+ adsl
751
+ end
752
+ end
753
+
754
+ def test_action__foreach_does_not_redefine_var
755
+ parser = ADSLParser.new
756
+ assert_nothing_raised ADSLError do
757
+ spec = parser.parse <<-adsl
758
+ class Class { 0+ Class relation }
759
+ action do_something(0+ Class var) {
760
+ foreach var: var {
761
+ }
762
+ }
763
+ adsl
764
+ end
765
+ end
766
+
767
+ def test_action__flat_for_each_is_by_default
768
+ parser = ADSLParser.new
769
+ spec = parser.parse <<-adsl
770
+ class Class { 0+ Class relation }
771
+ action do_something() {
772
+ foreach o: allof(Class) {
773
+ }
774
+ }
775
+ adsl
776
+ assert spec.actions.first.statements.map{ |c| c.class }.include? DSFlatForEach
777
+ end
778
+
779
+ def test_action__either_lambda_works
780
+ parser = ADSLParser.new
781
+ spec = nil
782
+ assert_nothing_raised ADSLError do
783
+ spec = parser.parse <<-adsl
784
+ class Class { 0+ Class relation }
785
+ action do_something() {
786
+ var = allof(Class)
787
+ either {
788
+ var = subset(var)
789
+ } or {
790
+ var = subset(var)
791
+ }
792
+ var = var
793
+ }
794
+ adsl
795
+ end
796
+
797
+ action = spec.actions.first
798
+ orig_def = action.statements[0].var
799
+ inside_def1 = action.statements[1].blocks[0].statements.first.var
800
+ inside_def2 = action.statements[1].blocks[1].statements.first.var
801
+ after_def = action.statements[2].objset
802
+
803
+ assert orig_def != inside_def1
804
+ assert orig_def != inside_def2
805
+ assert inside_def1 != after_def
806
+ assert inside_def2 != after_def
807
+ assert inside_def1 != inside_def2
808
+ assert orig_def != after_def
809
+ assert_equal after_def.vars[0], inside_def1
810
+ assert_equal after_def.vars[1], inside_def2
811
+ end
812
+
813
+ def test_action__foreach_pre_lambda
814
+ get_pre_lambdas = lambda do |for_each|
815
+ for_each.block.statements.select do |stat|
816
+ stat.kind_of?(DSAssignment) and stat.objset.kind_of?(DSForEachPreLambdaObjset)
817
+ end
818
+ end
819
+
820
+ parser = ADSLParser.new
821
+ spec = parser.parse <<-adsl
822
+ class Class {}
823
+ action do_something() {
824
+ foreach var: allof(Class) {}
825
+ }
826
+ adsl
827
+ assert_equal 0, get_pre_lambdas.call(spec.actions.first.block.statements[0]).length
828
+
829
+ spec = parser.parse <<-adsl
830
+ class Class {}
831
+ action do_something() {
832
+ foreach var: allof(Class) {
833
+ var = allof(Class)
834
+ }
835
+ }
836
+ adsl
837
+ assert_equal 0, get_pre_lambdas.call(spec.actions.first.block.statements[0]).length
838
+
839
+ spec = parser.parse <<-adsl
840
+ class Class {}
841
+ action do_something() {
842
+ var = allof(Class)
843
+ foreach a: allof(Class) {
844
+ var = subset(var)
845
+ var = subset(var)
846
+ }
847
+ }
848
+ adsl
849
+ pre_lambdas = get_pre_lambdas.call(spec.actions.first.block.statements[1])
850
+ assert_equal 1, pre_lambdas.length
851
+ assert_equal spec.actions.first.block.statements[0].var, pre_lambdas.first.objset.before_var
852
+ assert_equal spec.actions.first.block.statements[1], pre_lambdas.first.objset.for_each
853
+ assert_equal spec.actions.first.block.statements[1].block.statements.last.var, pre_lambdas.first.objset.inside_var
854
+
855
+ spec = parser.parse <<-adsl
856
+ class Class {}
857
+ action do_something() {
858
+ var = allof(Class)
859
+ foreach var: allof(Class) {
860
+ var = allof(Class)
861
+ }
862
+ }
863
+ adsl
864
+ assert_equal 0, get_pre_lambdas.call(spec.actions.first.block.statements[1]).length
865
+ end
866
+
867
+ def test_action__empty_set__typecheck
868
+ parser = ADSLParser.new
869
+
870
+ assert_nothing_raised ADSLError do
871
+ parser.parse <<-adsl
872
+ class Class {
873
+ 1 Class klass
874
+ }
875
+ class Class2 {
876
+ 1 Class2 klass2
877
+ }
878
+ action do_something() {
879
+ allof(Class).klass += empty
880
+ allof(Class2).klass2 += empty
881
+ }
882
+ adsl
883
+ end
884
+
885
+ assert_raise ADSLError do
886
+ parser.parse <<-adsl
887
+ action do_something() {
888
+ empty.some_relation += empty
889
+ }
890
+ adsl
891
+ end
892
+
893
+ assert_nothing_raised ADSLError do
894
+ parser.parse <<-adsl
895
+ class Class {
896
+ 1 Class klass
897
+ }
898
+ action do_something() {
899
+ foreach c: empty {
900
+ allof(Class).klass += c
901
+ }
902
+ }
903
+ adsl
904
+ end
905
+
906
+ assert_raise ADSLError do
907
+ parser.parse <<-adsl
908
+ class Class {
909
+ 1 Class klass
910
+ }
911
+ action do_something() {
912
+ foreach c: empty {
913
+ c.klass += allof(Class)
914
+ }
915
+ }
916
+ adsl
917
+ end
918
+ end
919
+
920
+ def test_action__empty_set_and_var_types
921
+ parser = ADSLParser.new
922
+
923
+ assert_nothing_raised ADSLError do
924
+ parser.parse <<-adsl
925
+ class Class {
926
+ 1 Class klass
927
+ }
928
+ action do_something() {
929
+ a = empty
930
+ a = allof(Class)
931
+ a.klass += a
932
+ }
933
+ adsl
934
+ end
935
+ assert_nothing_raised ADSLError do
936
+ parser.parse <<-adsl
937
+ class Class {
938
+ 1 Class klass
939
+ }
940
+ action do_something() {
941
+ a = empty
942
+ a = allof(Class)
943
+ a.klass += a
944
+ }
945
+ adsl
946
+ end
947
+ assert_nothing_raised ADSLError do
948
+ parser.parse <<-adsl
949
+ class Class {
950
+ 1 Class klass
951
+ }
952
+ action do_something() {
953
+ a = allof(Class)
954
+ a = empty
955
+ a.klass += a
956
+ }
957
+ adsl
958
+ end
959
+ assert_nothing_raised ADSLError do
960
+ parser.parse <<-adsl
961
+ class Class {
962
+ 1 Class klass
963
+ }
964
+ action do_something() {
965
+ a = allof(Class)
966
+ a = empty
967
+ b = a
968
+ b.klass += a
969
+ }
970
+ adsl
971
+ end
972
+ end
973
+
974
+ def test_action__entity_class_writes
975
+ parser = ADSLParser.new
976
+ spec = nil
977
+ assert_nothing_raised ADSLError do
978
+ spec = parser.parse <<-adsl
979
+ class Class {}
980
+ class Class2 {}
981
+ action do_something() {
982
+ create(Class)
983
+ }
984
+ adsl
985
+ end
986
+ assert_equal Set[spec.classes.first], spec.actions.first.block.list_entity_classes_written_to
987
+
988
+ assert_nothing_raised ADSLError do
989
+ spec = parser.parse <<-adsl
990
+ class Class {}
991
+ class Class2 {}
992
+ action do_something() {
993
+ create(Class)
994
+ either {
995
+ foreach a: allof(Class) {
996
+ delete allof(Class2)
997
+ }
998
+ } or {}
999
+ }
1000
+ adsl
1001
+ end
1002
+ assert_equal Set[*spec.classes], spec.actions.first.block.list_entity_classes_written_to
1003
+ assert_equal Set[spec.classes.first], spec.actions.first.block.statements.first.list_entity_classes_written_to
1004
+ assert_equal Set[spec.classes.second], spec.actions.first.block.statements.last.list_entity_classes_written_to
1005
+ end
1006
+
1007
+ def test_action__entity_class_reads
1008
+ parser = ADSLParser.new
1009
+ spec = nil
1010
+ assert_nothing_raised ADSLError do
1011
+ spec = parser.parse <<-adsl
1012
+ class Class {}
1013
+ class Class2 {}
1014
+ action do_something() {
1015
+ delete allof(Class)
1016
+ }
1017
+ adsl
1018
+ end
1019
+ assert_equal Set[spec.classes.first], spec.actions.first.block.list_entity_classes_read
1020
+
1021
+ assert_nothing_raised ADSLError do
1022
+ spec = parser.parse <<-adsl
1023
+ class Class {}
1024
+ class Class2 {}
1025
+ action do_something() {
1026
+ create(Class)
1027
+ either {
1028
+ foreach a: allof(Class) {
1029
+ delete allof(Class2)
1030
+ }
1031
+ } or {}
1032
+ }
1033
+ adsl
1034
+ end
1035
+ assert_equal Set[*spec.classes], spec.actions.first.block.list_entity_classes_read
1036
+ assert_equal Set[], spec.actions.first.block.statements.first.list_entity_classes_read
1037
+ assert_equal Set[*spec.classes], spec.actions.first.block.statements.last.list_entity_classes_read
1038
+ end
1039
+ end
1040
+ end