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,563 @@
1
+ require 'adsl/util/test_helper'
2
+ require 'test/unit'
3
+
4
+ class BasicTranslationTest < Test::Unit::TestCase
5
+ include ADSL::FOL
6
+
7
+ def test_blank_data_store
8
+ adsl_assert :correct, <<-ADSL
9
+ action blah() {}
10
+ ADSL
11
+ end
12
+
13
+ def test_not_creation__nothing_exists
14
+ adsl_assert :correct, <<-ADSL
15
+ class Class {}
16
+ action blah() {}
17
+ invariant not exists(Class o)
18
+ ADSL
19
+ end
20
+
21
+ def test_not_creation__something_exists
22
+ adsl_assert :correct, <<-ADSL
23
+ class Class {}
24
+ action blah() {}
25
+ invariant exists(Class o)
26
+ ADSL
27
+ end
28
+
29
+ def test_creating_objects__something_exists
30
+ adsl_assert :correct, <<-ADSL
31
+ class Class {}
32
+ action blah() {
33
+ create(Class)
34
+ }
35
+ invariant exists(Class o)
36
+ ADSL
37
+ end
38
+
39
+ def test_creating_objects__nothing_exists
40
+ adsl_assert :incorrect, <<-ADSL
41
+ class Class {}
42
+ action blah() {
43
+ create(Class)
44
+ }
45
+ invariant not exists(Class o)
46
+ ADSL
47
+ end
48
+
49
+ def test_creating_objects__of_exact_class
50
+ adsl_assert :correct, <<-ADSL
51
+ class Parent {}
52
+ class Child extends Parent {}
53
+ action blah() {
54
+ create(Parent)
55
+ }
56
+ invariant not exists(Child o)
57
+ ADSL
58
+ end
59
+
60
+ def test_classtypes
61
+ conjecture = ForAll.new(:o, Not.new(And.new('of_Class1_type(o)', 'of_Class2_type(o)')))
62
+ adsl_assert :correct, <<-ADSL, :conjecture => conjecture
63
+ class Class1 {}
64
+ class Class2 {}
65
+ action blah() {}
66
+ ADSL
67
+ end
68
+
69
+ def test_classtypes_polymorphism__no_contradictions
70
+ conjecture = Or.new(
71
+ Not.new(Exists.new(:o, 'of_Parent_type(o)')),
72
+ Not.new(Exists.new(:o, 'of_Child1_type(o)')),
73
+ Not.new(Exists.new(:o, 'of_Child2_type(o)')),
74
+ Not.new(Exists.new(:o, 'of_SubChild_type(o)')),
75
+ Not.new(Exists.new(:o, 'of_Parent2_type(o)'))
76
+ )
77
+ adsl_assert :incorrect, <<-ADSL, :conjecture => conjecture
78
+ class Parent {}
79
+ class Child1 extends Parent {}
80
+ class Child2 extends Parent {}
81
+ class SubChild extends Child1 {}
82
+ class Parent2 {}
83
+ action blah() {}
84
+ ADSL
85
+ end
86
+
87
+ def test_classtypes_polymorphism
88
+ type_spec = <<-ADSL
89
+ class Parent {}
90
+ class Child1 extends Parent {}
91
+ class Child2 extends Parent {}
92
+ class SubChild extends Child1 {}
93
+ class Parent2 {}
94
+ action blah() {}
95
+ ADSL
96
+
97
+ conjecture = ForAll.new(:o, Implies.new('of_Child1_type(o)', 'of_Parent_type(o)'))
98
+ adsl_assert :correct, type_spec, :conjecture => conjecture
99
+
100
+ conjecture = ForAll.new(:o, Implies.new(Not.new('of_Child1_type(o)'), 'of_Parent_type(o)'))
101
+ adsl_assert :incorrect, type_spec, :conjecture => conjecture
102
+
103
+ conjecture = ForAll.new(:o, Implies.new(Not.new('of_Parent_type(o)'), And.new(
104
+ Not.new('of_Child1_type(o)'),
105
+ Not.new('of_Child2_type(o)')
106
+ )))
107
+ adsl_assert :correct, type_spec, :conjecture => conjecture
108
+
109
+ conjecture = ForAll.new(:o, Not.new(And.new('of_Child1_type(o)', 'of_Parent2_type(o)')))
110
+ adsl_assert :correct, type_spec, :conjecture => conjecture
111
+
112
+ conjecture = ForAll.new(:o, Implies.new('of_SubChild_type(o)', 'of_Child1_type(o)'))
113
+ adsl_assert :correct, type_spec, :conjecture => conjecture
114
+ end
115
+
116
+ def test_multiple_invariants
117
+ adsl_assert :correct, <<-ADSL
118
+ class Class {}
119
+ action blah() {
120
+ create(Class)
121
+ }
122
+ invariant true
123
+ invariant true
124
+ invariant exists(Class o)
125
+ ADSL
126
+ adsl_assert :incorrect, <<-ADSL
127
+ class Class {}
128
+ action blah() {
129
+ create(Class)
130
+ }
131
+ invariant true
132
+ invariant not exists(Class o)
133
+ invariant true
134
+ ADSL
135
+ end
136
+
137
+ def test_variables__any_cardinality
138
+ adsl_assert :incorrect, <<-ADSL
139
+ class Class {}
140
+ action blah(0+ Class var) {
141
+ delete var
142
+ }
143
+ invariant exists(Class o)
144
+ ADSL
145
+ adsl_assert :correct, <<-ADSL
146
+ class Class {}
147
+ action blah(0+ Class var) {
148
+ delete var
149
+ }
150
+ invariant not exists(Class o)
151
+ ADSL
152
+ end
153
+
154
+ def test_variables__cardinality_constraint
155
+ adsl_assert :correct, <<-ADSL
156
+ class Class {}
157
+ action blah(0..1 Class var) {
158
+ create(Class)
159
+ delete var
160
+ }
161
+ invariant exists(Class o)
162
+ ADSL
163
+ adsl_assert :correct, <<-ADSL
164
+ class Class {}
165
+ action blah(1 Class var) {
166
+ create(Class)
167
+ delete var
168
+ }
169
+ invariant exists(Class o)
170
+ invariant forall(Class o1, Class o2: o1 == o2)
171
+ ADSL
172
+ end
173
+
174
+ def test_no_creation_objects__forall_does_not_imply_exists
175
+ adsl_assert :correct, <<-ADSL
176
+ class Class {}
177
+ action blah() {}
178
+ invariant forall(Class o1, Class o2: o1 == o2)
179
+ invariant not exists(Class o)
180
+ ADSL
181
+ end
182
+
183
+ def test_creation__add_objects_to_max_one_object
184
+ adsl_assert :incorrect, <<-ADSL
185
+ class Class {}
186
+ action blah() {
187
+ create(Class)
188
+ }
189
+ invariant forall(Class o1, Class o2: o1 == o2)
190
+ ADSL
191
+ end
192
+
193
+ def test_creation__add_two_objects_adds_two_objects
194
+ adsl_assert :incorrect, <<-ADSL
195
+ class Class { 0+ Class relation }
196
+ action blah() {
197
+ create(Class).relation += create(Class)
198
+ delete oneof(allof(Class))
199
+ }
200
+ invariant forall(Class o1, Class o2: o1 == o2)
201
+ ADSL
202
+ adsl_assert :correct, <<-ADSL
203
+ class Class { 0+ Class relation }
204
+ action blah() {
205
+ create(Class).relation += create(Class)
206
+ delete oneof(allof(Class))
207
+ delete oneof(allof(Class))
208
+ }
209
+ invariant forall(Class o1, Class o2: o1 == o2)
210
+ ADSL
211
+ end
212
+
213
+ def test_creation__class_specific
214
+ adsl_assert :correct, <<-ADSL
215
+ class Class {}
216
+ class Class2 {}
217
+ action blah() {
218
+ create(Class2)
219
+ }
220
+ invariant forall(Class o1, Class o2: o1 == o2)
221
+ ADSL
222
+ end
223
+
224
+ def test_deletion__empty_data_store
225
+ adsl_assert :correct, <<-ADSL
226
+ class Class {}
227
+ action blah() {
228
+ delete allof(Class)
229
+ }
230
+ invariant not exists(Class c)
231
+ ADSL
232
+ adsl_assert :incorrect, <<-ADSL
233
+ class Class {}
234
+ action blah() {
235
+ delete allof(Class)
236
+ }
237
+ invariant exists(Class c)
238
+ ADSL
239
+ end
240
+
241
+ def test_deletion__create_delete_data_store
242
+ adsl_assert :correct, <<-ADSL
243
+ class Class {}
244
+ action blah() {
245
+ create(Class)
246
+ delete allof(Class)
247
+ }
248
+ invariant not exists(Class c)
249
+ ADSL
250
+ adsl_assert :incorrect, <<-ADSL
251
+ class Class {}
252
+ action blah() {
253
+ create(Class)
254
+ delete allof(Class)
255
+ }
256
+ invariant exists(Class c)
257
+ ADSL
258
+ adsl_assert :incorrect, <<-ADSL
259
+ class Class {}
260
+ action blah() {
261
+ delete allof(Class)
262
+ create(Class)
263
+ }
264
+ invariant not exists(Class c)
265
+ ADSL
266
+ adsl_assert :correct, <<-ADSL
267
+ class Class {}
268
+ action blah() {
269
+ delete allof(Class)
270
+ create(Class)
271
+ }
272
+ invariant exists(Class c)
273
+ ADSL
274
+ end
275
+
276
+ def test_subset__invariant
277
+ adsl_assert :correct, <<-ADSL
278
+ class Class {}
279
+ action blah() {}
280
+ invariant subset(allof(Class)) in allof(Class)
281
+ ADSL
282
+ adsl_assert :incorrect, <<-ADSL
283
+ class Class {}
284
+ action blah() {}
285
+ invariant subset(allof(Class)) in subset(allof(Class))
286
+ ADSL
287
+ end
288
+
289
+ def test_variable__basic
290
+ adsl_assert :incorrect, <<-ADSL
291
+ class Class {}
292
+ action blah() {
293
+ a = allof(Class)
294
+ delete a
295
+ }
296
+ invariant exists(Class c)
297
+ ADSL
298
+ adsl_assert :correct, <<-ADSL
299
+ class Class {}
300
+ action blah() {
301
+ a = allof(Class)
302
+ delete a
303
+ }
304
+ invariant not exists(Class c)
305
+ ADSL
306
+ adsl_assert :incorrect, <<-ADSL
307
+ class Class {}
308
+ action blah() {
309
+ a = subset(allof(Class))
310
+ delete a
311
+ }
312
+ invariant exists(Class c)
313
+ ADSL
314
+ end
315
+
316
+ def test_create__assignment
317
+ adsl_assert :correct, <<-ADSL
318
+ class Class {}
319
+ action blah() {
320
+ a = create(Class)
321
+ delete a
322
+ }
323
+ invariant not exists(Class c)
324
+ ADSL
325
+ adsl_assert :incorrect, <<-ADSL
326
+ class Class {}
327
+ action blah() {
328
+ a = create(Class)
329
+ b = create(Class)
330
+ delete a
331
+ }
332
+ invariant not exists(Class c)
333
+ ADSL
334
+ end
335
+
336
+ def test_oneof__is_one_object
337
+ adsl_assert :correct, <<-ADSL
338
+ class Class {}
339
+ action blah() {
340
+ create(Class)
341
+ delete oneof(allof(Class))
342
+ }
343
+ invariant exists(Class c)
344
+ ADSL
345
+ end
346
+
347
+ def test_is_empty
348
+ adsl_assert :correct, <<-ADSL
349
+ class Class {}
350
+ action blah() {
351
+ delete allof(Class)
352
+ }
353
+ invariant empty(allof(Class))
354
+ ADSL
355
+ adsl_assert :correct, <<-ADSL
356
+ class Class {}
357
+ action blah() {}
358
+ invariant empty(allof(Class))
359
+ ADSL
360
+ adsl_assert :incorrect, <<-ADSL
361
+ class Class {}
362
+ action blah() {
363
+ create(Class)
364
+ }
365
+ invariant empty(allof(Class))
366
+ ADSL
367
+ end
368
+
369
+ def test_deref
370
+ adsl_assert :correct, <<-ADSL
371
+ class Class { 0+ Class2 rel }
372
+ class Class2 {}
373
+ action blah() {
374
+ delete allof(Class).rel
375
+ }
376
+ invariant forall(Class o: empty(o.rel))
377
+ ADSL
378
+ adsl_assert :incorrect, <<-ADSL
379
+ class Class { 0+ Class2 rel }
380
+ class Class2 {}
381
+ action blah() {
382
+ delete allof(Class).rel
383
+ }
384
+ invariant not forall(Class o: empty(o.rel))
385
+ ADSL
386
+ end
387
+
388
+ def test_deref_polymorphic
389
+ adsl_assert :incorrect, <<-ADSL
390
+ class Parent { 0+ Parent rel }
391
+ class Child extends Parent {}
392
+ action blah() {
393
+ delete allof(Parent).rel
394
+ }
395
+ invariant exists(Child o: not empty(o.rel))
396
+ ADSL
397
+ adsl_assert :incorrect, <<-ADSL
398
+ class Parent { 0+ Parent rel }
399
+ class Child extends Parent {}
400
+ action blah() {
401
+ delete allof(Child).rel
402
+ }
403
+ invariant exists(Child o: not empty(o.rel))
404
+ ADSL
405
+ adsl_assert :correct, <<-ADSL
406
+ class Parent { 0+ Parent rel }
407
+ class Child extends Parent {}
408
+ action blah() {
409
+ delete allof(Child).rel
410
+ }
411
+ invariant exists(Parent o: not empty(o.rel)) and not exists(Child o: not empty(o.rel))
412
+ ADSL
413
+ end
414
+
415
+ def test__create_ref
416
+ adsl_assert :correct, <<-ADSL
417
+ class Class{ 0+ Class rel }
418
+ action blah() {
419
+ v1 = oneof (allof(Class))
420
+ v2 = oneof (allof(Class))
421
+ v1.rel += v2
422
+ }
423
+ invariant exists(Class o: not empty(o.rel))
424
+ ADSL
425
+ adsl_assert :incorrect, <<-ADSL
426
+ class Class{ 0+ Class rel }
427
+ action blah() {
428
+ v1 = oneof (allof(Class))
429
+ v2 = oneof (allof(Class))
430
+ v1.rel += v2
431
+ }
432
+ invariant forall(Class o: empty(o.rel))
433
+ ADSL
434
+ end
435
+
436
+ def test__create_ref_clique
437
+ adsl_assert :correct, <<-adsl
438
+ class Class{ 0+ Class rel }
439
+ action blah() {
440
+ allof(Class).rel += allof(Class)
441
+ }
442
+ invariant forall(Class v: v.rel == allof(Class))
443
+ adsl
444
+
445
+ conjecture = <<-SPASS
446
+ forall( [o1, o2], implies(
447
+ and(exists_finally(o1), exists_finally(o2), is_object(o1), is_object(o2)),
448
+ exists( [r], and(left_link_Class_rel(r, o1), right_link_Class_rel(r, o2)))
449
+ ))
450
+ SPASS
451
+ adsl_assert(:correct, <<-adsl, :conjecture => conjecture)
452
+ class Class{ 0+ Class rel }
453
+ action blah() {
454
+ allof(Class).rel += allof(Class)
455
+ }
456
+ invariant forall(Class v: v.rel == allof(Class))
457
+ adsl
458
+
459
+ adsl_assert :incorrect, <<-ADSL
460
+ class Class{ 0+ Class rel }
461
+ action blah() {
462
+ allof(Class).rel += allof(Class)
463
+ }
464
+ invariant !forall(Class v: v.rel == allof(Class))
465
+ ADSL
466
+ end
467
+
468
+ def test__no_refs_on_new_object
469
+ adsl_assert :correct, <<-ADSL
470
+ class Class { 0+ Class rel }
471
+ action blah() {
472
+ create(Class)
473
+ }
474
+ invariant exists(Class o: empty(o.rel))
475
+ ADSL
476
+ adsl_assert :incorrect, <<-ADSL
477
+ class Class { 0+ Class rel }
478
+ action blah() {
479
+ create(Class)
480
+ }
481
+ invariant forall(Class o: not empty(o.rel))
482
+ ADSL
483
+ end
484
+
485
+ def test__delete_removes_all_refs
486
+ adsl_assert :correct, <<-ADSL
487
+ class Class { 0+ Class rel }
488
+ action blah() {
489
+ delete allof(Class)
490
+ a = create(Class)
491
+ b = create(Class)
492
+ a.rel += b
493
+ delete a
494
+ }
495
+ invariant forall(Class a: empty(a.rel))
496
+ ADSL
497
+ adsl_assert :incorrect, <<-ADSL
498
+ class Class { 0+ Class rel }
499
+ action blah() {
500
+ delete allof(Class)
501
+ a = create(Class)
502
+ b = create(Class)
503
+ a.rel += b
504
+ delete a
505
+ }
506
+ invariant !forall(Class a: empty(a.rel))
507
+ ADSL
508
+ end
509
+
510
+ def test__delete_ref
511
+ adsl_assert :correct, <<-ADSL
512
+ class Class { 0+ Class rel }
513
+ action blah() {
514
+ allof(Class).rel -= allof(Class)
515
+ }
516
+ invariant forall(Class a: empty(a.rel))
517
+ ADSL
518
+ adsl_assert :incorrect, <<-ADSL
519
+ class Class { 0+ Class rel }
520
+ action blah() {
521
+ allof(Class).rel -= allof(Class)
522
+ }
523
+ invariant exists(Class a: not empty(a.rel))
524
+ ADSL
525
+ end
526
+
527
+ def test_ref_cardinality__at_least_one
528
+ conjecture = <<-SPASS
529
+ forall( [o], implies(of_Class_type(o), exists([r], left_link_Class_rel(r, o))))
530
+ SPASS
531
+ adsl_assert :correct, <<-ADSL, :conjecture => conjecture
532
+ class Class { 1+ Class rel }
533
+ action blah() {}
534
+ ADSL
535
+ adsl_assert :incorrect, <<-ADSL, :conjecture => "not(#{conjecture})"
536
+ class Class { 1+ Class rel }
537
+ action blah() {}
538
+ ADSL
539
+ end
540
+
541
+ def test_ref_cardinality__at_most_one
542
+ conjecture = <<-SPASS
543
+ exists( [o, r1, r2], and(of_Class_type(o), left_link_Class_rel(r1, o), left_link_Class_rel(r2, o), not(equal(r1, r2))))
544
+ SPASS
545
+ adsl_assert :correct, <<-ADSL, :conjecture => "not(#{conjecture})"
546
+ class Class { 0..1 Class rel }
547
+ action blah() {}
548
+ ADSL
549
+ adsl_assert :incorrect, <<-ADSL, :conjecture => conjecture
550
+ class Class { 0..1 Class rel }
551
+ action blah() {}
552
+ ADSL
553
+ end
554
+
555
+ def test__inverse_relations
556
+ adsl_assert :correct, <<-ADSL
557
+ class Class1 { 1 Class2 rel }
558
+ class Class2 { 1 Class1 rel inverseof rel }
559
+ action blah() {}
560
+ invariant forall(Class1 a: a == a.rel.rel)
561
+ ADSL
562
+ end
563
+ end