adsl 0.0.3 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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