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,67 @@
1
+ require 'adsl/parser/adsl_parser.tab'
2
+ require 'test/unit'
3
+ require 'pp'
4
+
5
+ module ADSL::Parser
6
+ class GeneralParserTest < Test::Unit::TestCase
7
+ include ADSL::Parser
8
+
9
+ def test_comments_single_line
10
+ parser = ADSLParser.new
11
+
12
+ ['#', '//'].each do |commentchar|
13
+ spec = parser.parse <<-ADSL
14
+ class Class1 {}
15
+ #{commentchar} class Class1 {}
16
+ class Class2
17
+ #{commentchar} class Class3
18
+ {} #{commentchar}#{commentchar} class Class4 {}
19
+ #{commentchar}#{commentchar}
20
+ #{commentchar}
21
+ ADSL
22
+ assert_equal ['Class1', 'Class2'], spec.classes.map{ |c| c.name }
23
+
24
+ spec = parser.parse <<-ADSL
25
+ #{commentchar} class Class1 {}
26
+ ADSL
27
+ assert spec.classes.empty?
28
+ end
29
+ end
30
+
31
+ def test_comments_multi_line
32
+ parser = ADSLParser.new
33
+
34
+ spec = parser.parse <<-ADSL
35
+ class Class1 {}
36
+ /* class Class2 {} */
37
+ ADSL
38
+ assert_equal ['Class1'], spec.classes.map{ |c| c.name }
39
+
40
+ spec = parser.parse <<-ADSL
41
+ class Class1 /*
42
+ */ {} /*
43
+ */ class Class2 {}
44
+ ADSL
45
+ assert_equal ['Class1', 'Class2'], spec.classes.map{ |c| c.name }
46
+ end
47
+
48
+ def test_different_comment_types_dont_interfere
49
+ parser = ADSLParser.new
50
+
51
+ spec = parser.parse <<-ADSL
52
+ class Class1 {}
53
+ /* // */
54
+ class Class2 {}
55
+ /* # */
56
+ ADSL
57
+ assert_equal ['Class1', 'Class2'], spec.classes.map{ |c| c.name }
58
+
59
+ spec = parser.parse <<-ADSL
60
+ // /*
61
+ class Class1 {}
62
+ # */
63
+ ADSL
64
+ assert_equal ['Class1'], spec.classes.map{ |c| c.name }
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,432 @@
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 InvariantParserTest < Test::Unit::TestCase
8
+ include ADSL::Parser
9
+ include ADSL::DS
10
+
11
+ def test_invariant__constants
12
+ parser = ADSLParser.new
13
+
14
+ [true, false].each do |bool|
15
+ spec = nil
16
+ assert_nothing_raised ADSLError do
17
+ spec = parser.parse "invariant #{bool.to_s}"
18
+ end
19
+ assert_equal([], spec.actions)
20
+ assert_equal([], spec.classes)
21
+ assert_equal 1, spec.invariants.length
22
+ assert_equal bool, spec.invariants.first.formula.bool_value
23
+ end
24
+ end
25
+
26
+ def test_invariant__names
27
+ parser = ADSLParser.new
28
+ spec = nil
29
+ assert_nothing_raised ADSLError do
30
+ spec = parser.parse "invariant some_name: true"
31
+ end
32
+ assert_equal "some_name", spec.invariants.first.name
33
+
34
+ assert_nothing_raised ADSLError do
35
+ spec = parser.parse <<-ADSL
36
+ invariant some_name: true
37
+ invariant true
38
+ ADSL
39
+ end
40
+
41
+ assert_raise ADSLError do
42
+ spec = parser.parse <<-ADSL
43
+ invariant some_name: true
44
+ invariant some_name: true
45
+ ADSL
46
+ end
47
+
48
+ assert_nothing_raised ADSLError do
49
+ spec = parser.parse <<-ADSL
50
+ invariant true
51
+ invariant true
52
+ ADSL
53
+ end
54
+ assert_equal "unnamed_line_1", spec.invariants.first.name
55
+ assert_equal "unnamed_line_2", spec.invariants.last.name
56
+ end
57
+
58
+ def test_invariant__forall_and_exists_one_param
59
+ parser = ADSLParser.new
60
+
61
+ operators = {
62
+ "forall" => DSForAll,
63
+ "exists" => DSExists
64
+ }
65
+
66
+ operators.each do |word, type|
67
+ spec = nil
68
+ assert_nothing_raised ADSLError do
69
+ spec = parser.parse <<-ADSL
70
+ class Class {}
71
+ invariant #{word}(Class a: true)
72
+ ADSL
73
+ end
74
+ invariant = spec.invariants.first
75
+ assert_equal type, invariant.formula.class
76
+ assert_equal 1, invariant.formula.vars.length
77
+ assert_equal spec.classes.first, invariant.formula.vars.first.type
78
+ assert_equal 'a', invariant.formula.vars.first.name
79
+ assert_equal true, invariant.formula.subformula.bool_value
80
+ end
81
+ end
82
+
83
+ def test_invariant__forall_and_exists_mulitple_params
84
+ parser = ADSLParser.new
85
+
86
+ operators = {
87
+ "forall" => DSForAll,
88
+ "exists" => DSExists
89
+ }
90
+
91
+ operators.each do |word, type|
92
+ spec = nil
93
+ assert_nothing_raised ADSLError do
94
+ spec = parser.parse <<-ADSL
95
+ class Class {}
96
+ invariant #{word}(Class a, Class b: true)
97
+ ADSL
98
+ end
99
+ invariant = spec.invariants.first
100
+ assert_equal type, invariant.formula.class
101
+ assert_equal 2, invariant.formula.vars.length
102
+ assert_equal [spec.classes.first, spec.classes.first], invariant.formula.vars.map{ |v| v.type }
103
+ assert_equal ['a', 'b'], invariant.formula.vars.map{ |v| v.name }
104
+ assert_equal true, invariant.formula.subformula.bool_value
105
+ end
106
+ end
107
+
108
+ def test_invariant__forall_and_exists_typecheck
109
+ parser = ADSLParser.new
110
+
111
+ ['forall', 'exists'].each do |formula|
112
+ assert_raise do
113
+ parser.parse <<-ADSL
114
+ invariant #{formula}(true)
115
+ ADSL
116
+ end
117
+ assert_raise ADSLError do
118
+ parser.parse <<-ADSL
119
+ invariant #{formula}(Class a, Class b: true)
120
+ ADSL
121
+ end
122
+ assert_raise ADSLError do
123
+ parser.parse <<-ADSL
124
+ class Class {}
125
+ invariant #{formula}(Class a, Class a: true)
126
+ ADSL
127
+ end
128
+ assert_raise ADSLError do
129
+ parser.parse <<-ADSL
130
+ class Class {}
131
+ invariant #{formula}(Class a: #{formula}(Class a: true))
132
+ ADSL
133
+ end
134
+ end
135
+ end
136
+
137
+ def test_invariant__forall_and_exists_can_use_objsets
138
+ parser = ADSLParser.new
139
+ ['forall', 'exists'].each do |formula|
140
+ spec = parser.parse <<-ADSL
141
+ class Class { 0+ Class relation }
142
+ invariant #{formula}(a in allof(Class): true)
143
+ ADSL
144
+ invariant = spec.invariants.first
145
+ assert_equal 'a', invariant.formula.vars.first.name
146
+ assert_equal DSAllOf, invariant.formula.objsets.first.class
147
+
148
+ spec = parser.parse <<-ADSL
149
+ class Class { 0+ Class relation }
150
+ invariant #{formula}(a in allof(Class).relation: true)
151
+ ADSL
152
+ invariant = spec.invariants.first
153
+ assert_equal 'a', invariant.formula.vars.first.name
154
+ assert_equal DSDereference, invariant.formula.objsets.first.class
155
+
156
+ spec = parser.parse <<-ADSL
157
+ class Class { 0+ Class relation }
158
+ invariant #{formula}(Class a: #{formula}(b in a: true))
159
+ ADSL
160
+ end
161
+ end
162
+
163
+ def test_invariant__exists_can_go_without_subformula_while_forall_cannot
164
+ parser = ADSLParser.new
165
+ assert_nothing_raised ADSLError do
166
+ spec = parser.parse <<-ADSL
167
+ class Class {}
168
+ invariant exists(Class a)
169
+ ADSL
170
+ end
171
+ assert_raise do
172
+ spec = parser.parse <<-ADSL
173
+ class Class {}
174
+ invariant forall(Class a)
175
+ ADSL
176
+ end
177
+ end
178
+
179
+ def test_invariant__parenthesis
180
+ parser = ADSLParser.new
181
+ spec = parser.parse <<-ADSL
182
+ invariant (true)
183
+ ADSL
184
+ invariant = spec.invariants.first
185
+ assert_equal true, invariant.formula.bool_value
186
+ end
187
+
188
+ def test_invariant__not
189
+ parser = ADSLParser.new
190
+ ['not', '!'].each do |word|
191
+ spec = parser.parse <<-ADSL
192
+ invariant not false
193
+ ADSL
194
+ invariant = spec.invariants.first
195
+ assert_equal DSNot, invariant.formula.class
196
+ assert_equal false, invariant.formula.subformula.bool_value
197
+ end
198
+ end
199
+
200
+ def test_invariant__and_or
201
+ parser = ADSLParser.new
202
+ operators = {
203
+ "and" => DSAnd,
204
+ "or" => DSOr
205
+ }
206
+ operators.each do |word, type|
207
+ spec = parser.parse <<-ADSL
208
+ invariant true #{word} false
209
+ ADSL
210
+ invariant = spec.invariants.first
211
+ assert_equal type, invariant.formula.class
212
+ assert_equal [true, false], invariant.formula.subformulae.map{ |a| a.bool_value}
213
+
214
+ spec = parser.parse <<-ADSL
215
+ invariant true #{word} false #{word} true
216
+ ADSL
217
+ invariant = spec.invariants.first
218
+ assert_equal type, invariant.formula.class
219
+ assert_equal [true, false, true], invariant.formula.subformulae.map{ |a| a.bool_value}
220
+ end
221
+ end
222
+
223
+ def test_invariant__operator_precedence_and_associativity
224
+ parser = ADSLParser.new
225
+ operators = {
226
+ "and" => DSAnd,
227
+ "or" => DSOr
228
+ }
229
+ operators.each do |word, type|
230
+ spec = parser.parse <<-ADSL
231
+ invariant not true #{word} false
232
+ ADSL
233
+ invariant = spec.invariants.first
234
+ assert_equal type, invariant.formula.class
235
+ assert_equal DSNot, invariant.formula.subformulae.first.class
236
+ assert_equal false, invariant.formula.subformulae.second.bool_value
237
+ end
238
+ operators.each do |word, type|
239
+ spec = parser.parse <<-ADSL
240
+ invariant not (true #{word} false)
241
+ ADSL
242
+ invariant = spec.invariants.first
243
+ assert_equal DSNot, invariant.formula.class
244
+ assert_equal type, invariant.formula.subformula.class
245
+ end
246
+ spec = parser.parse <<-ADSL
247
+ invariant true and !false or true
248
+ ADSL
249
+ invariant = spec.invariants.first
250
+ assert_equal DSOr, invariant.formula.class
251
+ assert_equal true, invariant.formula.subformulae.second.bool_value
252
+ assert_equal DSAnd, invariant.formula.subformulae.first.class
253
+ assert_equal true, invariant.formula.subformulae.first.subformulae.first.bool_value
254
+ assert_equal DSNot, invariant.formula.subformulae.first.subformulae.second.class
255
+ end
256
+
257
+ def test_invariant__equal
258
+ parser = ADSLParser.new
259
+ spec = parser.parse <<-ADSL
260
+ class Class {}
261
+ invariant exists(Class o1, Class o2: o1 == o2)
262
+ ADSL
263
+ f = spec.invariants.first.formula.subformula
264
+ assert_equal DSEqual, f.class
265
+ assert_equal ['o1', 'o2'], f.objsets.map { |v| v.name }
266
+
267
+ spec = parser.parse <<-ADSL
268
+ class Class {}
269
+ invariant exists(Class o1, Class o2: equal(o1, o2))
270
+ ADSL
271
+ f = spec.invariants.first.formula.subformula
272
+ assert_equal DSEqual, f.class
273
+ assert_equal ['o1', 'o2'], f.objsets.map { |v| v.name }
274
+
275
+ spec = parser.parse <<-ADSL
276
+ class Class {}
277
+ invariant exists(Class o1, Class o2: equal(o1, o2, o1, o1))
278
+ ADSL
279
+ f = spec.invariants.first.formula.subformula
280
+ assert_equal DSEqual, f.class
281
+ assert_equal ['o1', 'o2', 'o1', 'o1'], f.objsets.map { |v| v.name }
282
+
283
+ assert_nothing_raised ADSLError do
284
+ parser.parse <<-ADSL
285
+ class Class {}
286
+ class Child extends Class {}
287
+ invariant allof(Class) == allof(Child)
288
+ ADSL
289
+ end
290
+ assert_raise ADSLError do
291
+ parser.parse <<-ADSL
292
+ class Class1 {}
293
+ class Class2 {}
294
+ invariant allof(Class1) == allof(Child2)
295
+ ADSL
296
+ end
297
+ assert_raise ADSLError do
298
+ parser.parse <<-ADSL
299
+ class Parent {}
300
+ class Class1 extends Parent {}
301
+ class Class2 extends Parent {}
302
+ invariant equal(allof(Parent), allof(Class1), allof(Child2))
303
+ ADSL
304
+ end
305
+ end
306
+
307
+ def test_invariant__not_equal
308
+ parser = ADSLParser.new
309
+ spec = parser.parse <<-ADSL
310
+ class Class {}
311
+ invariant exists(Class o1, Class o2: o1 != o2)
312
+ ADSL
313
+ f = spec.invariants.first.formula.subformula
314
+ assert_equal DSNot, f.class
315
+ assert_equal DSEqual, f.subformula.class
316
+ assert_equal ['o1', 'o2'], f.subformula.objsets.map { |v| v.name }
317
+ end
318
+
319
+ def test_invariant__equiv
320
+ parser = ADSLParser.new
321
+ spec = parser.parse <<-ADSL
322
+ class Class {}
323
+ invariant true <=> false
324
+ ADSL
325
+ invariant = spec.invariants.first
326
+ assert_equal DSEquiv, invariant.formula.class
327
+ assert_equal [true, false], invariant.formula.subformulae.map{ |f| f.bool_value }
328
+
329
+ spec = parser.parse <<-ADSL
330
+ class Class {}
331
+ invariant equiv(true, false)
332
+ ADSL
333
+ invariant = spec.invariants.first
334
+ assert_equal DSEquiv, invariant.formula.class
335
+ assert_equal [true, false], invariant.formula.subformulae.map{ |f| f.bool_value }
336
+
337
+ spec = parser.parse <<-ADSL
338
+ class Class {}
339
+ invariant equiv(true, false, true, true)
340
+ ADSL
341
+ invariant = spec.invariants.first
342
+ assert_equal DSEquiv, invariant.formula.class
343
+ assert_equal [true, false, true, true], invariant.formula.subformulae.map{ |f| f.bool_value }
344
+ end
345
+
346
+ def test_invariant__implies
347
+ parser = ADSLParser.new
348
+ spec = parser.parse <<-ADSL
349
+ class Class {}
350
+ invariant true => false
351
+ ADSL
352
+ invariant = spec.invariants.first
353
+ assert_equal DSImplies, invariant.formula.class
354
+ assert_equal true, invariant.formula.subformula1.bool_value
355
+ assert_equal false, invariant.formula.subformula2.bool_value
356
+
357
+ spec = parser.parse <<-ADSL
358
+ class Class {}
359
+ invariant false <= true
360
+ ADSL
361
+ invariant = spec.invariants.first
362
+ assert_equal DSImplies, invariant.formula.class
363
+ assert_equal true, invariant.formula.subformula1.bool_value
364
+ assert_equal false, invariant.formula.subformula2.bool_value
365
+
366
+ spec = parser.parse <<-ADSL
367
+ class Class {}
368
+ invariant implies(true, false)
369
+ ADSL
370
+ invariant = spec.invariants.first
371
+ assert_equal DSImplies, invariant.formula.class
372
+ assert_equal true, invariant.formula.subformula1.bool_value
373
+ assert_equal false, invariant.formula.subformula2.bool_value
374
+ end
375
+
376
+ def test_invariant__empty
377
+ parser = ADSLParser.new
378
+ spec = parser.parse <<-ADSL
379
+ class Class {}
380
+ invariant empty(allof(Class))
381
+ ADSL
382
+ invariant = spec.invariants.first
383
+ assert_equal DSEmpty, invariant.formula.class
384
+ assert_equal DSAllOf, invariant.formula.objset.class
385
+ end
386
+
387
+ def test_invariant__in
388
+ parser = ADSLParser.new
389
+ spec = parser.parse <<-ADSL
390
+ class Class {}
391
+ invariant allof(Class) in allof(Class)
392
+ ADSL
393
+ invariant = spec.invariants.first
394
+ assert_equal DSIn, invariant.formula.class
395
+ assert_equal DSAllOf, invariant.formula.objset1.class
396
+ assert_equal DSAllOf, invariant.formula.objset2.class
397
+
398
+ assert_raise ADSLError do
399
+ parser.parse <<-ADSL
400
+ class Class1 {}
401
+ class Class2 {}
402
+ invariant allof(Class1) in allof(Class2)
403
+ ADSL
404
+ end
405
+ assert_raise ADSLError do
406
+ parser.parse <<-ADSL
407
+ class Super {}
408
+ class Sub extends Super {}
409
+ invariant allof(Super) in allof(Sub)
410
+ ADSL
411
+ end
412
+ assert_nothing_raised ADSLError do
413
+ parser.parse <<-ADSL
414
+ class Super {}
415
+ class Sub extends Super {}
416
+ invariant allof(Sub) in allof(Super)
417
+ ADSL
418
+ end
419
+ end
420
+
421
+ def test_invariant__variable_scope
422
+ parser = ADSLParser.new
423
+ spec = parser.parse <<-ADSL
424
+ class Class {}
425
+ invariant exists(Class o)
426
+ invariant exists(Class o)
427
+ invariant exists(Class o)
428
+ invariant exists(Class o)
429
+ ADSL
430
+ end
431
+ end
432
+ end