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
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 6b26fde19cd7f72d505d12b67a37e9eb7c76aba2
4
- data.tar.gz: 425182f63a8d718786e63dc9f21439c764f9332a
3
+ metadata.gz: ebe37d86fc7f4beca92d9a2774ea9261f65bd3fa
4
+ data.tar.gz: 81b1927dd5809ded4855b31283a53222160160e4
5
5
  SHA512:
6
- metadata.gz: a15fbddc4618acafd6cfe069195656f11ac0ec58ac3d22b36341fa90b0c5a690d15e3ad5c687a0a1c3af134e82093428a93a07737d19f09fcd7241dca437c1a6
7
- data.tar.gz: 6f84daa5917019dbf27dc523e693d7eee093329de27826777b85c9ce173a09268751e396cbba04d55984e3bdc48c7363b66c12492b3a74428da06ea75facc5f9
6
+ metadata.gz: a2d4e8b5fb36b758459a10309ca14fef2007894f73b26301c6eb6c50ed72f7d61a829a7a5fe1606f86e46b0a40488df6950d2a1582bbb96ebd9f5036a9dc839f
7
+ data.tar.gz: ecd21de07c4f79acd1b7dd4f16240dd02adfb8ba96b0f570e937b48cff376e7925450069898ae9389e88589f15814e8fab2109656538d347b2f83765d10374b6
data/Gemfile CHANGED
@@ -1,20 +1,2 @@
1
- source "http://rubygems.org"
2
-
3
- # base
4
- # indentation added to prevent these dependencies when building the gem
5
- gem "rake"
6
- gem "test-unit"
7
- gem "i18n"
8
-
9
- # lexer/parser
10
- gem "rexical"
11
- gem "racc"
12
-
13
- # used all over the place
14
- gem "active_support"
15
-
16
- # terminal color output
17
- gem "colorize"
18
-
19
- # extraction tools
20
- gem "ruby_parser"
1
+ source 'https://rubygems.org'
2
+ gemspec
data/README.md CHANGED
@@ -1,17 +1,15 @@
1
- ADSL - Abstract Data Store Language Parser and Translator
1
+ ADSL - Abstract Data Store Library
2
2
  =========================================================
3
3
 
4
- This tool an Abstract Data Store Language (ADSL) specification verification tool.
4
+ ADSL is a gem for formal verification of Ruby on Rails models. Simply include it in your Gemfile, write a few
5
+ invariants (rules) about ActiveRecord data that you wish to verify (for example, that at any given moment, every
6
+ Address has a User) and run `rake verify`!
5
7
 
6
- ADSL is a language for specifying Abstract Data Stores using a syntax familiar to anyone that has experience
7
- with ORM tools such as Hibernate and ActiveRecord. A specification contains the model classes, actions executed
8
- using a RESTful interface, and a set of invariants to be verified.
8
+ Besides the verification algorithm, this tool includes a DSL for specifying invariants. The syntax should feel
9
+ natural to any Rails user. Look at /examples.
9
10
 
10
- This tool verifies a specification by translating it into a first order logic theorem verifiable by [Spass] [1],
11
- a theorem prover. It provides detailed information on the actions and invariants verified in human-readable or
12
- CSV format.
13
-
14
- This tool is distributed as a Ruby gem and is uploaded to [RubyGems.org] [2]. Install it and give it a try!
11
+ This tool is distributed as a Ruby gem and is uploaded to [RubyGems.org] [2]. It requires Spass[1] to run. Install
12
+ it and give it a try!
15
13
 
16
14
 
17
15
  Installation
@@ -20,24 +18,19 @@ Installation
20
18
  This gem is tested on 32 and 64 bit Linux. OS-X compatibility not tested, give it a try
21
19
  and tell us if it works! Windows is not supported at this moment.
22
20
 
23
- - Ruby 1.8.7 or later required. We suggest using the [Ruby Version Manager](https://rvm.io/rvm/install/) to manage this installation.
21
+ - Ruby 1.9.3 or later required, along with Rails 3.2. We suggest using the [Ruby Version Manager](https://rvm.io/rvm/install/) to manage this installation.
24
22
  - [Download and install Spass](http://www.spass-prover.org/download/index.html) and make sure its executable (`bin/SPASS`) on your $PATH
25
23
  - Install the ADSL gem by running `gem install adsl`.
26
-
27
24
  If you receive an error while generating documentation for 'activesupport' run `gem install rdoc adsl` instead.
28
- - Test the installation by verifying [the example specification](https://raw.github.com/Bocete/adsl/master/example/running-example.adsl)
29
-
25
+
30
26
  Usage
31
27
  -----
32
28
 
33
- adsl-verify <specification-file>
34
-
35
- For options and other modes of operation, run
36
-
37
- adsl-verify --help
38
-
39
- You can download sample ADSL specifications
29
+ rake verify <options>
30
+
31
+ Or, to just observe the extracted model,
40
32
 
33
+ rake adsl_translate
41
34
 
42
35
  Development
43
36
  -----------
@@ -9,7 +9,7 @@ options.language = 'spass'
9
9
  options.halt_on_error = false
10
10
  options.check_satisfiability = true
11
11
  options.timeout = 30
12
- options.csv_output = false
12
+ options.output = 'terminal'
13
13
  options.actions = nil
14
14
  options.invariants = nil
15
15
 
@@ -36,10 +36,10 @@ OptionParser.new do |opts|
36
36
  options.check_satisfiability = check
37
37
  end
38
38
 
39
- opts.on("-s", "--stats-csv",
40
- "Output the results of the verification with stats in CSV form.",
41
- " Default: #{options.csv_output}") do
42
- options.csv_output = true
39
+ opts.on("-o", "--output-format FORMAT",
40
+ "Sets the output format. Options: terminal, csv, or silent",
41
+ " Default: #{options.output}") do |format|
42
+ options.output = format
43
43
  end
44
44
 
45
45
  opts.on("-t", "--timeout TIMEOUT", Integer,
@@ -87,14 +87,14 @@ $LOAD_PATH.unshift GEM_LIB_PATH unless $LOAD_PATH.include? GEM_LIB_PATH
87
87
 
88
88
  case options.language
89
89
  when 'spass'
90
- require 'spass/bin'
91
- include Spass::Bin
90
+ require 'adsl/spass/bin'
91
+ include ADSL::Spass::Bin
92
92
  begin
93
93
  verify(input,
94
94
  :halt_on_error => options.halt_on_error,
95
95
  :check_satisfiability => options.check_satisfiability,
96
96
  :timeout => options.timeout,
97
- :csv_output => options.csv_output,
97
+ :output => options.output,
98
98
  :actions => options.actions,
99
99
  :invariants => options.invariants)
100
100
  rescue Exception => e
@@ -0,0 +1,3 @@
1
+ module ADSL
2
+ require 'adsl/railtie' if defined?(Rails)
3
+ end
@@ -0,0 +1,3 @@
1
+ module ADSL
2
+ require 'adsl/realtie' if refined?(Rails)
3
+ end
@@ -0,0 +1,339 @@
1
+ require 'adsl/util/general'
2
+
3
+ module ADSL
4
+ module DS
5
+ class DSNode
6
+ def list_entity_classes_written_to
7
+ recursively_gather :entity_class_writes
8
+ end
9
+
10
+ def list_entity_classes_read
11
+ recursively_gather :entity_class_reads
12
+ end
13
+
14
+ def replace(what, with)
15
+ to_inspect = [self]
16
+ inspected = Set.new
17
+ replaced = false
18
+ while not to_inspect.empty?
19
+ elem = to_inspect.pop
20
+ if elem.kind_of? Array
21
+ elem.length.times do |i|
22
+ if elem[i] == what
23
+ elem[i] = with
24
+ replaced = true
25
+ else
26
+ to_inspect << elem[i] unless inspected.include? elem[i]
27
+ end
28
+ inspected << elem[i]
29
+ end
30
+ elsif elem.class.methods.include? 'container_for_fields' or elem.class.methods.include? :container_for_fields
31
+ elem.class.container_for_fields.each do |field_name|
32
+ field_val = elem.send field_name
33
+ if field_val == what
34
+ elem.send "#{field_name}=", with
35
+ replaced = true
36
+ elsif field_val.kind_of?(Array) or field_val.class.methods.include?('container_for_fields')
37
+ to_inspect << field_val unless inspected.include? field_val
38
+ end
39
+ inspected << field_val
40
+ end
41
+ end
42
+ end
43
+ replaced
44
+ end
45
+ end
46
+
47
+ class DSSpec < DSNode
48
+ container_for :classes, :actions, :invariants
49
+ end
50
+
51
+ class DSClass < DSNode
52
+ container_for :name, :parent, :relations, :inverse_relations do
53
+ @relations = [] if @relations.nil?
54
+ @inverse_relations = [] if @inverse_relations.nil?
55
+ end
56
+
57
+ def to_s
58
+ @name
59
+ end
60
+
61
+ def superclass_of?(other_class)
62
+ until other_class.nil?
63
+ return true if other_class == self
64
+ other_class = other_class.parent
65
+ end
66
+ return false
67
+ end
68
+
69
+ def self.common_supertype(classes)
70
+ types = classes.uniq
71
+ types.delete nil
72
+ while types.length > 1
73
+ type1 = types.pop
74
+ type2 = types.pop
75
+ if type1.superclass_of? type2
76
+ types << type2
77
+ elsif type2.superclass_of? type1
78
+ types << type1
79
+ else
80
+ raise ADSLError, "Object sets are not of compatible types: #{classes.map { |c| c.name }.join(", ")}"
81
+ end
82
+ end
83
+ types.first
84
+ end
85
+ end
86
+
87
+ class DSRelation < DSNode
88
+ container_for :cardinality, :from_class, :to_class, :name, :inverse_of
89
+
90
+ def to_s
91
+ "#{from_class.name}.#{name}"
92
+ end
93
+ end
94
+
95
+ class DSAction < DSNode
96
+ container_for :name, :args, :cardinalities, :block
97
+
98
+ def statements
99
+ @block.statements
100
+ end
101
+ end
102
+
103
+ class DSBlock < DSNode
104
+ container_for :statements
105
+ end
106
+
107
+ class DSAssignment < DSNode
108
+ container_for :var, :objset
109
+ end
110
+
111
+ class DSCreateObj < DSNode
112
+ container_for :klass
113
+
114
+ def entity_class_writes
115
+ Set[@klass]
116
+ end
117
+ end
118
+
119
+ class DSCreateObjset < DSNode
120
+ container_for :createobj
121
+
122
+ def type
123
+ @createobj.klass
124
+ end
125
+ end
126
+
127
+ class DSCreateTup < DSNode
128
+ container_for :objset1, :relation, :objset2
129
+ end
130
+
131
+ class DSDeleteObj < DSNode
132
+ container_for :objset
133
+
134
+ def entity_class_writes
135
+ Set[@objset.type]
136
+ end
137
+ end
138
+
139
+ class DSDeleteTup < DSNode
140
+ container_for :objset1, :relation, :objset2
141
+ end
142
+
143
+ class DSEither < DSNode
144
+ container_for :blocks, :lambdas
145
+ end
146
+
147
+ class DSEitherLambdaObjset < DSNode
148
+ container_for :either, :vars
149
+ end
150
+
151
+ class DSForEachCommon < DSNode
152
+ container_for :objset, :block
153
+ end
154
+
155
+ class DSForEach < DSForEachCommon
156
+ end
157
+
158
+ class DSFlatForEach < DSForEachCommon
159
+ end
160
+
161
+ class DSForEachIteratorObjset < DSNode
162
+ container_for :for_each
163
+
164
+ def typecheck_and_resolve(context)
165
+ self
166
+ end
167
+
168
+ def type
169
+ @for_each.objset.type
170
+ end
171
+ end
172
+
173
+ class DSForEachPreLambdaObjset < DSNode
174
+ container_for :for_each, :before_var, :inside_var
175
+ end
176
+
177
+ class DSForEachPostLambdaObjset < DSNode
178
+ container_for :for_each, :before_var, :inside_var
179
+ end
180
+
181
+ class DSVariable < DSNode
182
+ container_for :name, :type
183
+ end
184
+
185
+ class DSAllOf < DSNode
186
+ container_for :klass
187
+
188
+ def type
189
+ @klass
190
+ end
191
+
192
+ def entity_class_reads
193
+ @klass
194
+ end
195
+ end
196
+
197
+ class DSSubset < DSNode
198
+ container_for :objset
199
+
200
+ def type
201
+ @objset.type
202
+ end
203
+ end
204
+
205
+ class DSUnion < DSNode
206
+ container_for :objsets
207
+
208
+ def type
209
+ DSClass.common_supertype objsets.reject{ |o| o.type.nil? }.map{ |o| o.type }
210
+ end
211
+ end
212
+
213
+ class DSOneOfObjset < DSNode
214
+ container_for :objsets
215
+
216
+ def type
217
+ DSClass.common_supertype objsets.reject{ |o| o.type.nil? }.map{ |o| o.type }
218
+ end
219
+ end
220
+
221
+ class DSOneOf < DSNode
222
+ container_for :objset
223
+ def type
224
+ @objset.type
225
+ end
226
+ end
227
+
228
+ class DSDereference < DSNode
229
+ container_for :objset, :relation
230
+
231
+ def type
232
+ @relation.to_class
233
+ end
234
+ end
235
+
236
+ class DSEmptyObjset < DSNode
237
+ container_for
238
+
239
+ def type
240
+ nil
241
+ end
242
+ end
243
+
244
+ class DSInvariant < DSNode
245
+ container_for :name, :formula
246
+ end
247
+
248
+ class DSBoolean < DSNode
249
+ container_for :bool_value
250
+
251
+ TRUE = DSBoolean.new :bool_value => true
252
+ FALSE = DSBoolean.new :bool_value => false
253
+
254
+ def type
255
+ :formula
256
+ end
257
+ end
258
+
259
+ class DSForAll < DSNode
260
+ container_for :vars, :objsets, :subformula
261
+
262
+ def type
263
+ :formula
264
+ end
265
+ end
266
+
267
+ class DSExists < DSNode
268
+ container_for :vars, :objsets, :subformula
269
+
270
+ def type
271
+ :formula
272
+ end
273
+ end
274
+
275
+ class DSIn < DSNode
276
+ container_for :objset1, :objset2
277
+
278
+ def type
279
+ :formula
280
+ end
281
+ end
282
+
283
+ class DSEmpty < DSNode
284
+ container_for :objset
285
+
286
+ def type
287
+ :formula
288
+ end
289
+ end
290
+
291
+ class DSNot < DSNode
292
+ container_for :subformula
293
+
294
+ def type
295
+ :formula
296
+ end
297
+ end
298
+
299
+ class DSAnd < DSNode
300
+ container_for :subformulae
301
+
302
+ def type
303
+ :formula
304
+ end
305
+ end
306
+
307
+ class DSOr < DSNode
308
+ container_for :subformulae
309
+
310
+ def type
311
+ :formula
312
+ end
313
+ end
314
+
315
+ class DSImplies < DSNode
316
+ container_for :subformula1, :subformula2
317
+
318
+ def type
319
+ :formula
320
+ end
321
+ end
322
+
323
+ class DSEquiv < DSNode
324
+ container_for :subformulae
325
+
326
+ def type
327
+ :formula
328
+ end
329
+ end
330
+
331
+ class DSEqual < DSNode
332
+ container_for :objsets
333
+
334
+ def type
335
+ :formula
336
+ end
337
+ end
338
+ end
339
+ end