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.
- checksums.yaml +4 -4
- data/Gemfile +2 -20
- data/README.md +14 -21
- data/bin/adsl-verify +8 -8
- data/lib/adsl.rb +3 -0
- data/lib/adsl/adsl.rb +3 -0
- data/lib/adsl/ds/data_store_spec.rb +339 -0
- data/lib/adsl/extract/instrumenter.rb +206 -0
- data/lib/adsl/extract/meta.rb +33 -0
- data/lib/adsl/extract/rails/action_block_builder.rb +233 -0
- data/lib/adsl/extract/rails/action_instrumenter.rb +400 -0
- data/lib/adsl/extract/rails/action_runner.rb +57 -0
- data/lib/adsl/extract/rails/active_record_metaclass_generator.rb +555 -0
- data/lib/adsl/extract/rails/callback_chain_simulator.rb +135 -0
- data/lib/adsl/extract/rails/invariant_extractor.rb +48 -0
- data/lib/adsl/extract/rails/invariant_instrumenter.rb +70 -0
- data/lib/adsl/extract/rails/other_meta.rb +57 -0
- data/lib/adsl/extract/rails/rails_extractor.rb +211 -0
- data/lib/adsl/extract/rails/rails_instrumentation_test_case.rb +34 -0
- data/lib/adsl/extract/rails/rails_special_gem_instrumentation.rb +120 -0
- data/lib/adsl/extract/rails/rails_test_helper.rb +140 -0
- data/lib/adsl/extract/sexp_utils.rb +54 -0
- data/lib/adsl/fol/first_order_logic.rb +261 -0
- data/lib/adsl/parser/adsl_parser.racc +159 -0
- data/lib/{parser → adsl/parser}/adsl_parser.rex +4 -4
- data/lib/{parser → adsl/parser}/adsl_parser.rex.rb +6 -6
- data/lib/adsl/parser/adsl_parser.tab.rb +1031 -0
- data/lib/adsl/parser/ast_nodes.rb +1410 -0
- data/lib/adsl/railtie.rb +67 -0
- data/lib/adsl/spass/bin.rb +230 -0
- data/lib/{spass → adsl/spass}/ruby_extensions.rb +0 -0
- data/lib/adsl/spass/spass_ds_extensions.rb +931 -0
- data/lib/adsl/spass/spass_translator.rb +393 -0
- data/lib/adsl/spass/util.rb +13 -0
- data/lib/adsl/util/csv_hash_formatter.rb +94 -0
- data/lib/adsl/util/general.rb +228 -0
- data/lib/adsl/util/test_helper.rb +71 -0
- data/lib/adsl/verification/formula_generators.rb +231 -0
- data/lib/adsl/verification/instrumentation_filter.rb +50 -0
- data/lib/adsl/verification/invariant.rb +19 -0
- data/lib/adsl/verification/rails_verification.rb +33 -0
- data/lib/adsl/verification/utils.rb +20 -0
- data/lib/adsl/verification/verification_case.rb +13 -0
- data/test/integration/rails/rails_branch_verification_test.rb +112 -0
- data/test/integration/rails/rails_verification_test.rb +253 -0
- data/test/integration/spass/basic_translation_test.rb +563 -0
- data/test/integration/spass/control_flow_translation_test.rb +421 -0
- data/test/unit/adsl/ds/data_store_spec_test.rb +54 -0
- data/test/unit/adsl/extract/instrumenter_test.rb +103 -0
- data/test/unit/adsl/extract/meta_test.rb +142 -0
- data/test/unit/adsl/extract/rails/action_block_builder_test.rb +178 -0
- data/test/unit/adsl/extract/rails/action_instrumenter_test.rb +68 -0
- data/test/unit/adsl/extract/rails/active_record_metaclass_generator_test.rb +336 -0
- data/test/unit/adsl/extract/rails/callback_chain_simulator_test.rb +76 -0
- data/test/unit/adsl/extract/rails/invariant_extractor_test.rb +92 -0
- data/test/unit/adsl/extract/rails/rails_extractor_test.rb +1380 -0
- data/test/unit/adsl/extract/rails/rails_test_helper_test.rb +25 -0
- data/test/unit/adsl/extract/sexp_utils_test.rb +100 -0
- data/test/unit/adsl/fol/first_order_logic_test.rb +227 -0
- data/test/unit/adsl/parser/action_parser_test.rb +1040 -0
- data/test/unit/adsl/parser/ast_nodes_test.rb +359 -0
- data/test/unit/adsl/parser/class_parser_test.rb +288 -0
- data/test/unit/adsl/parser/general_parser_test.rb +67 -0
- data/test/unit/adsl/parser/invariant_parser_test.rb +432 -0
- data/test/unit/adsl/parser/parser_util_test.rb +126 -0
- data/test/unit/adsl/spass/bin_test.rb +65 -0
- data/test/unit/adsl/spass/ruby_extensions_test.rb +39 -0
- data/test/unit/adsl/spass/spass_ds_extensions_test.rb +7 -0
- data/test/unit/adsl/spass/spass_translator_test.rb +342 -0
- data/test/unit/adsl/util/csv_hash_formatter_test.rb +68 -0
- data/test/unit/adsl/util/general_test.rb +303 -0
- data/test/unit/adsl/util/test_helper_test.rb +120 -0
- data/test/unit/adsl/verification/formula_generators_test.rb +200 -0
- data/test/unit/adsl/verification/instrumentation_filter_test.rb +39 -0
- data/test/unit/adsl/verification/utils_test.rb +39 -0
- data/test/unit/adsl/verification/verification_case_test.rb +8 -0
- metadata +229 -29
- data/lib/ds/data_store_spec.rb +0 -292
- data/lib/fol/first_order_logic.rb +0 -260
- data/lib/parser/adsl_ast.rb +0 -779
- data/lib/parser/adsl_parser.racc +0 -151
- data/lib/parser/adsl_parser.tab.rb +0 -976
- data/lib/parser/dsdl_parser.rex.rb +0 -196
- data/lib/parser/dsdl_parser.tab.rb +0 -976
- data/lib/spass/bin.rb +0 -164
- data/lib/spass/spass_ds_extensions.rb +0 -870
- data/lib/spass/spass_translator.rb +0 -388
- data/lib/spass/util.rb +0 -11
- data/lib/util/csv_hash_formatter.rb +0 -47
- data/lib/util/test_helper.rb +0 -33
- data/lib/util/util.rb +0 -114
|
@@ -0,0 +1,359 @@
|
|
|
1
|
+
require 'test/unit'
|
|
2
|
+
require 'adsl/parser/ast_nodes'
|
|
3
|
+
require 'set'
|
|
4
|
+
|
|
5
|
+
class ADSL::Parser::AstNodesTest < Test::Unit::TestCase
|
|
6
|
+
include ADSL::Parser
|
|
7
|
+
|
|
8
|
+
def test__statements_are_statements
|
|
9
|
+
all_nodes = ADSL::Parser.constants.map{ |c| ADSL::Parser.const_get c }.select{ |c| c < ADSL::Parser::ASTNode }
|
|
10
|
+
statements = [:dummy_stmt, :assignment, :create_tup, :delete_tup, :set_tup, :delete_obj, :block, :for_each, :either, :objset_stmt, :declare_var]
|
|
11
|
+
statements = statements.map{ |c| ADSL::Parser.const_get "AST#{c.to_s.camelize}" }
|
|
12
|
+
difference = Set[*statements] ^ Set[*all_nodes.select{ |c| c.is_statement? }]
|
|
13
|
+
assert difference.empty?
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def test__create_objset_has_transitive_sideeffects
|
|
17
|
+
assert ASTCreateObjset.new.objset_has_side_effects?
|
|
18
|
+
|
|
19
|
+
assert_false ASTSubset.new.objset_has_side_effects?
|
|
20
|
+
assert ASTSubset.new(:objset => ASTCreateObjset.new).objset_has_side_effects?
|
|
21
|
+
|
|
22
|
+
assert_false ASTUnion.new.objset_has_side_effects?
|
|
23
|
+
assert_false ASTUnion.new(:objsets => [
|
|
24
|
+
ASTSubset.new, ASTSubset.new
|
|
25
|
+
]).objset_has_side_effects?
|
|
26
|
+
assert ASTUnion.new(:objsets => [
|
|
27
|
+
ASTSubset.new, ASTSubset.new, ASTCreateObjset.new
|
|
28
|
+
]).objset_has_side_effects?
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def test__block_optimize__merges_nested_blocks
|
|
32
|
+
block = ASTBlock.new(:statements => [
|
|
33
|
+
ASTBlock.new(:statements => [
|
|
34
|
+
ASTAssignment.new(:objset => 1),
|
|
35
|
+
ASTAssignment.new(:objset => 2)
|
|
36
|
+
]),
|
|
37
|
+
ASTAssignment.new(:objset => 3),
|
|
38
|
+
ASTBlock.new(:statements => [
|
|
39
|
+
ASTAssignment.new(:objset => 4),
|
|
40
|
+
ASTBlock.new(:statements => [
|
|
41
|
+
ASTAssignment.new(:objset => 5),
|
|
42
|
+
ASTAssignment.new(:objset => 6)
|
|
43
|
+
]),
|
|
44
|
+
ASTAssignment.new(:objset => 7)
|
|
45
|
+
])
|
|
46
|
+
])
|
|
47
|
+
|
|
48
|
+
block = block.optimize
|
|
49
|
+
|
|
50
|
+
assert_equal 7, block.statements.length
|
|
51
|
+
7.times do |i|
|
|
52
|
+
assert_equal i+1, block.statements[i].objset
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def test__block_optimize__remove_noop_objset_stmts
|
|
57
|
+
block = ASTBlock.new(:statements => [
|
|
58
|
+
ASTAssignment.new(:objset => 1),
|
|
59
|
+
ASTObjsetStmt.new(:objset => ASTEmptyObjset.new),
|
|
60
|
+
ASTAssignment.new(:objset => 2),
|
|
61
|
+
ASTAssignment.new(:objset => 3),
|
|
62
|
+
ASTObjsetStmt.new(:objset => ASTEmptyObjset.new)
|
|
63
|
+
])
|
|
64
|
+
|
|
65
|
+
block = block.optimize
|
|
66
|
+
|
|
67
|
+
assert_equal 3, block.statements.length
|
|
68
|
+
3.times do |i|
|
|
69
|
+
stmt = block.statements[i]
|
|
70
|
+
assert_equal ASTAssignment, stmt.class
|
|
71
|
+
assert_equal i+1, stmt.objset
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def test__block_optimize__removes_dummy_stmts
|
|
76
|
+
block = ASTBlock.new(:statements => [
|
|
77
|
+
ASTAssignment.new(:objset => 1),
|
|
78
|
+
ASTDummyStmt.new(),
|
|
79
|
+
ASTAssignment.new(:objset => 2),
|
|
80
|
+
ASTDummyStmt.new()
|
|
81
|
+
])
|
|
82
|
+
|
|
83
|
+
block = block.optimize
|
|
84
|
+
|
|
85
|
+
assert_equal 2, block.statements.length
|
|
86
|
+
2.times do |i|
|
|
87
|
+
stmt = block.statements[i]
|
|
88
|
+
assert_equal ASTAssignment, stmt.class
|
|
89
|
+
assert_equal i+1, stmt.objset
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
def test__either_optimize__merges_nested_eithers
|
|
94
|
+
either = ASTEither.new(:blocks => [
|
|
95
|
+
ASTBlock.new(:statements => [ASTEither.new(:blocks => [
|
|
96
|
+
ASTBlock.new(:statements => [
|
|
97
|
+
ASTAssignment.new(:objset => 1),
|
|
98
|
+
ASTAssignment.new(:objset => 2)
|
|
99
|
+
]),
|
|
100
|
+
ASTBlock.new(:statements => [
|
|
101
|
+
ASTAssignment.new(:objset => 3),
|
|
102
|
+
ASTAssignment.new(:objset => 4)
|
|
103
|
+
]),
|
|
104
|
+
ASTBlock.new(:statements => [
|
|
105
|
+
ASTEither.new(:blocks => [
|
|
106
|
+
ASTBlock.new(:statements => [
|
|
107
|
+
ASTAssignment.new(:objset => 5)
|
|
108
|
+
])
|
|
109
|
+
])
|
|
110
|
+
])
|
|
111
|
+
])]),
|
|
112
|
+
ASTBlock.new(:statements => [
|
|
113
|
+
ASTAssignment.new(:objset => 6)
|
|
114
|
+
]),
|
|
115
|
+
])
|
|
116
|
+
|
|
117
|
+
either = either.optimize
|
|
118
|
+
|
|
119
|
+
assert_equal 4, either.blocks.length
|
|
120
|
+
assert_equal [1, 2], either.blocks[0].statements.map(&:objset)
|
|
121
|
+
assert_equal [3, 4], either.blocks[1].statements.map(&:objset)
|
|
122
|
+
assert_equal [5], either.blocks[2].statements.map(&:objset)
|
|
123
|
+
assert_equal [6], either.blocks[3].statements.map(&:objset)
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
def test__action_optimize__removes_root_either_empty_options
|
|
127
|
+
action = ASTAction.new(:block => ASTBlock.new(:statements => [
|
|
128
|
+
ASTEither.new(:blocks => [
|
|
129
|
+
ASTBlock.new(:statements => []),
|
|
130
|
+
ASTBlock.new(:statements => [
|
|
131
|
+
ASTEither.new(:blocks => [
|
|
132
|
+
ASTBlock.new(:statements => [ASTDeleteObj.new(:objset => 1)]),
|
|
133
|
+
ASTBlock.new(:statements => [ASTDeleteObj.new(:objset => 2)])
|
|
134
|
+
])
|
|
135
|
+
]),
|
|
136
|
+
ASTBlock.new(:statements => [])
|
|
137
|
+
])
|
|
138
|
+
]))
|
|
139
|
+
|
|
140
|
+
action = action.optimize
|
|
141
|
+
|
|
142
|
+
assert_equal 1, action.block.statements.length
|
|
143
|
+
either = action.block.statements.first
|
|
144
|
+
assert_equal ASTEither, either.class
|
|
145
|
+
|
|
146
|
+
assert_equal 2, either.blocks.length
|
|
147
|
+
2.times do |i|
|
|
148
|
+
assert_equal 1, either.blocks[i].statements.length
|
|
149
|
+
assert_equal i+1, either.blocks[i].statements.first.objset
|
|
150
|
+
end
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
def test__action_optimize__removes_root_either_if_only_one_option
|
|
154
|
+
action = ASTAction.new(:block => ASTBlock.new(:statements => [
|
|
155
|
+
ASTEither.new(:blocks => [
|
|
156
|
+
ASTBlock.new(:statements => []),
|
|
157
|
+
ASTBlock.new(:statements => [
|
|
158
|
+
ASTEither.new(:blocks => [
|
|
159
|
+
ASTBlock.new(:statements => [ASTDeleteObj.new(:objset => ASTDummyObjset.new(:type => 1))]),
|
|
160
|
+
ASTBlock.new(:statements => [])
|
|
161
|
+
])
|
|
162
|
+
]),
|
|
163
|
+
ASTBlock.new(:statements => [])
|
|
164
|
+
])
|
|
165
|
+
]))
|
|
166
|
+
|
|
167
|
+
action = action.optimize
|
|
168
|
+
|
|
169
|
+
assert_equal 1, action.block.statements.length
|
|
170
|
+
assert_equal ASTDeleteObj, action.block.statements.first.class
|
|
171
|
+
end
|
|
172
|
+
|
|
173
|
+
def test__equality
|
|
174
|
+
assert ASTIdent.new(:text => 'asd') == ASTIdent.new(:text => 'asd')
|
|
175
|
+
assert_false ASTIdent.new(:text => 'asd') == ASTIdent.new(:text => :asd)
|
|
176
|
+
assert(
|
|
177
|
+
ASTSubset.new(:objset => ASTAllOf.new(:class_name => 'asd')) ==
|
|
178
|
+
ASTSubset.new(:objset => ASTAllOf.new(:class_name => 'asd'))
|
|
179
|
+
)
|
|
180
|
+
assert_false(
|
|
181
|
+
ASTSubset.new(:objset => ASTAllOf.new(:class_name => 'asd')) ==
|
|
182
|
+
ASTSubset.new(:objset => ASTAllOf.new(:class_name => :asd))
|
|
183
|
+
)
|
|
184
|
+
assert_false ASTSubset.new == nil
|
|
185
|
+
assert ASTAnd.new(:subformulae => [1, 2, 3, nil, ASTIdent.new]) == ASTAnd.new(:subformulae => [1, 2, 3, nil, ASTIdent.new])
|
|
186
|
+
assert_false ASTAnd.new(:subformulae => [1, 2, 3, 4, ASTIdent.new]) == ASTAnd.new(:subformulae => [1, 2, 3, nil, ASTIdent.new])
|
|
187
|
+
assert_false(
|
|
188
|
+
ASTAnd.new(:subformulae => [1, 2, 3, nil, ASTIdent.new(:text => '')]) ==
|
|
189
|
+
ASTAnd.new(:subformulae => [1, 2, 3, nil, ASTIdent.new])
|
|
190
|
+
)
|
|
191
|
+
assert ASTDeleteObj.new == ASTDeleteObj.new
|
|
192
|
+
assert ASTDeleteObj.new.eql?(ASTDeleteObj.new)
|
|
193
|
+
assert ASTDeleteObj.new.hash == ASTDeleteObj.new.hash
|
|
194
|
+
end
|
|
195
|
+
|
|
196
|
+
def test__block_replace__replaces_the_instance
|
|
197
|
+
ast_node = ASTSubset.new(:objset => ASTAllOf.new(:class_name => ASTIdent.new(:text => :text)))
|
|
198
|
+
replaced = ast_node.block_replace do |node|
|
|
199
|
+
next unless node.is_a? ASTIdent
|
|
200
|
+
ASTIdent.new :text => 'new_text'
|
|
201
|
+
end
|
|
202
|
+
assert_equal ASTSubset, replaced.class
|
|
203
|
+
assert_equal ASTAllOf, replaced.objset.class
|
|
204
|
+
assert_equal ASTIdent, replaced.objset.class_name.class
|
|
205
|
+
assert_equal 'new_text', replaced.objset.class_name.text
|
|
206
|
+
end
|
|
207
|
+
|
|
208
|
+
def test__action_optimize__prepends_instance_and_class_variables
|
|
209
|
+
action = ASTAction.new(:block => ASTBlock.new(:statements => [
|
|
210
|
+
ASTEither.new(:blocks => [
|
|
211
|
+
ASTBlock.new(:statements => []),
|
|
212
|
+
ASTBlock.new(:statements => [
|
|
213
|
+
ASTBlock.new(:statements => [
|
|
214
|
+
ASTBlock.new(:statements => [
|
|
215
|
+
ASTAssignment.new(:objset => ASTVariable.new(:var_name => ASTIdent.new(:text => 'kme')))
|
|
216
|
+
]),
|
|
217
|
+
ASTBlock.new(:statements => [
|
|
218
|
+
ASTAssignment.new(:objset => ASTVariable.new(:var_name => ASTIdent.new(:text => 'at__blahblah')))
|
|
219
|
+
]),
|
|
220
|
+
ASTBlock.new(:statements => [])
|
|
221
|
+
])
|
|
222
|
+
]),
|
|
223
|
+
ASTBlock.new(:statements => [])
|
|
224
|
+
]),
|
|
225
|
+
ASTDeleteObj.new
|
|
226
|
+
]))
|
|
227
|
+
|
|
228
|
+
action = action.optimize
|
|
229
|
+
action.prepend_global_variables_by_signatures /^at__.*$/, /^atat__.*$/
|
|
230
|
+
assert_equal 3, action.block.statements.length
|
|
231
|
+
|
|
232
|
+
assert_equal ASTAssignment, action.block.statements[0].class
|
|
233
|
+
assert_equal 'at__blahblah', action.block.statements[0].var_name.text
|
|
234
|
+
assert_equal ASTEmptyObjset, action.block.statements[0].objset.class
|
|
235
|
+
|
|
236
|
+
assert_equal ASTEither, action.block.statements[1].class
|
|
237
|
+
blocks = action.block.statements[1].blocks
|
|
238
|
+
|
|
239
|
+
assert_equal 0, blocks.first.statements.length
|
|
240
|
+
assert_equal 2, blocks.second.statements.length
|
|
241
|
+
assert_equal ASTAssignment, blocks.second.statements[0].class
|
|
242
|
+
assert_equal 'kme', blocks.second.statements[0].objset.var_name.text
|
|
243
|
+
assert_equal ASTAssignment, blocks.second.statements[1].class
|
|
244
|
+
assert_equal 'at__blahblah', blocks.second.statements[1].objset.var_name.text
|
|
245
|
+
|
|
246
|
+
assert_equal ASTDeleteObj, action.block.statements[2].class
|
|
247
|
+
end
|
|
248
|
+
|
|
249
|
+
def test__either_optimize__unique_paths
|
|
250
|
+
either = ASTEither.new(:blocks => [
|
|
251
|
+
ASTBlock.new(:statements => []),
|
|
252
|
+
ASTBlock.new(:statements => []),
|
|
253
|
+
ASTBlock.new(:statements => [ASTDeleteObj.new(:objset => 1)]),
|
|
254
|
+
ASTBlock.new(:statements => [ASTDeleteObj.new(:objset => 1)]),
|
|
255
|
+
ASTBlock.new(:statements => [])
|
|
256
|
+
])
|
|
257
|
+
|
|
258
|
+
either = either.optimize
|
|
259
|
+
|
|
260
|
+
assert_equal 2, either.blocks.length
|
|
261
|
+
|
|
262
|
+
assert_equal 0, either.blocks[0].statements.length
|
|
263
|
+
assert_equal 1, either.blocks[1].statements.length
|
|
264
|
+
assert_equal ASTDeleteObj, either.blocks[1].statements[0].class
|
|
265
|
+
assert_equal 1, either.blocks[1].statements[0].objset
|
|
266
|
+
end
|
|
267
|
+
|
|
268
|
+
def test__block_optimize__removes_last_stmts_without_sideeffects
|
|
269
|
+
action = ASTAction.new(:block => ASTBlock.new(:statements => [
|
|
270
|
+
ASTAssignment.new(:var_name => ASTIdent.new(:text => 'at_asdf'), :objset => ASTEmptyObjset.new),
|
|
271
|
+
ASTEither.new(:blocks => [
|
|
272
|
+
ASTBlock.new(:statements => []),
|
|
273
|
+
ASTBlock.new(:statements => [
|
|
274
|
+
ASTEither.new(:blocks => [
|
|
275
|
+
ASTBlock.new(:statements => [
|
|
276
|
+
ASTAssignment.new(:var_name => ASTIdent.new(:text => 'at_asdf'), :objset => ASTDummyObjset.new)
|
|
277
|
+
]),
|
|
278
|
+
ASTBlock.new(:statements => [
|
|
279
|
+
ASTAssignment.new(:var_name => ASTIdent.new(:text => 'at_asdf'), :objset => ASTDummyObjset.new)
|
|
280
|
+
])
|
|
281
|
+
])
|
|
282
|
+
]),
|
|
283
|
+
ASTBlock.new(:statements => [
|
|
284
|
+
ASTAssignment.new(:var_name => ASTIdent.new(:text => 'at_asdf'), :objset => ASTDummyObjset.new)
|
|
285
|
+
]),
|
|
286
|
+
ASTBlock.new(:statements => [
|
|
287
|
+
ASTAssignment.new(:var_name => ASTIdent.new(:text => 'at_asdf'), :objset => ASTCreateObjset.new)
|
|
288
|
+
])
|
|
289
|
+
])
|
|
290
|
+
]))
|
|
291
|
+
|
|
292
|
+
action = action.optimize
|
|
293
|
+
|
|
294
|
+
stmts = action.block.statements
|
|
295
|
+
assert_equal 1, stmts.length
|
|
296
|
+
assert_equal ASTObjsetStmt, stmts.first.class
|
|
297
|
+
assert_equal ASTCreateObjset, stmts.first.objset.class
|
|
298
|
+
end
|
|
299
|
+
|
|
300
|
+
def test__adsl_ast_size
|
|
301
|
+
ast = ASTBlock.new(:statements => [
|
|
302
|
+
ASTAssignment.new(:var_name => ASTIdent.new(:text => 'asd'), :objset => ASTEmptyObjset.new),
|
|
303
|
+
ASTDummyStmt.new(:type => :blah)
|
|
304
|
+
])
|
|
305
|
+
assert_equal 5, ast.adsl_ast_size
|
|
306
|
+
|
|
307
|
+
ast = ASTBlock.new(:statements => [])
|
|
308
|
+
assert_equal 1, ast.adsl_ast_size
|
|
309
|
+
end
|
|
310
|
+
|
|
311
|
+
def test__spec_adsl_ast_size
|
|
312
|
+
spec = ASTSpec.new(
|
|
313
|
+
:classes => [ASTClass.new],
|
|
314
|
+
:actions => [
|
|
315
|
+
ASTAction.new(:name => ASTIdent.new(:text => 'action1')),
|
|
316
|
+
ASTAction.new(:name => ASTIdent.new(:text => 'action2')),
|
|
317
|
+
ASTAction.new(:name => ASTIdent.new(:text => '')),
|
|
318
|
+
],
|
|
319
|
+
:invariants => [
|
|
320
|
+
ASTInvariant.new(:name => ASTIdent.new(:text => 'inv_name1')),
|
|
321
|
+
ASTInvariant.new(:name => ASTIdent.new(:text => 'inv_name2'))
|
|
322
|
+
]
|
|
323
|
+
)
|
|
324
|
+
|
|
325
|
+
assert_equal 12, spec.adsl_ast_size
|
|
326
|
+
assert_equal 8, spec.adsl_ast_size(:action_name => 'action1')
|
|
327
|
+
assert_equal 8, spec.adsl_ast_size(:action_name => 'action2')
|
|
328
|
+
|
|
329
|
+
assert_equal 10, spec.adsl_ast_size(:invariant_name => 'inv_name1')
|
|
330
|
+
|
|
331
|
+
assert_equal 6, spec.adsl_ast_size(:action_name => '', :invariant_name => 'inv_name2')
|
|
332
|
+
end
|
|
333
|
+
|
|
334
|
+
def test__spec_pre_optimize_size
|
|
335
|
+
spec = ASTSpec.new(
|
|
336
|
+
:classes => [ASTClass.new],
|
|
337
|
+
:actions => [ASTAction.new(
|
|
338
|
+
:name => ASTIdent.new(:text => 'action'),
|
|
339
|
+
:block => ASTBlock.new(:statements => [
|
|
340
|
+
ASTDummyStmt.new(:type => :asd),
|
|
341
|
+
ASTEither.new(:blocks => [
|
|
342
|
+
ASTBlock.new(:statements => []),
|
|
343
|
+
ASTBlock.new(:statements => [
|
|
344
|
+
ASTDeleteObj.new
|
|
345
|
+
]),
|
|
346
|
+
])
|
|
347
|
+
])
|
|
348
|
+
)],
|
|
349
|
+
:invariants => []
|
|
350
|
+
)
|
|
351
|
+
spec.actions.map!(&:optimize)
|
|
352
|
+
|
|
353
|
+
assert_equal 8, spec.actions.first.pre_optimize_adsl_ast_size
|
|
354
|
+
assert_equal 4, spec.actions.first.adsl_ast_size
|
|
355
|
+
|
|
356
|
+
assert_equal 6, spec.adsl_ast_size
|
|
357
|
+
assert_equal 10, spec.adsl_ast_size(:pre_optimize => true)
|
|
358
|
+
end
|
|
359
|
+
end
|
|
@@ -0,0 +1,288 @@
|
|
|
1
|
+
require 'adsl/parser/adsl_parser.tab'
|
|
2
|
+
require 'adsl/parser/ast_nodes'
|
|
3
|
+
require 'test/unit'
|
|
4
|
+
require 'pp'
|
|
5
|
+
require 'set'
|
|
6
|
+
|
|
7
|
+
module ADSL::Parser
|
|
8
|
+
class ClassParserTest < Test::Unit::TestCase
|
|
9
|
+
include ADSL::Parser
|
|
10
|
+
|
|
11
|
+
def test_class__empty
|
|
12
|
+
parser = ADSLParser.new
|
|
13
|
+
spec = parser.parse ""
|
|
14
|
+
assert_equal([], spec.classes)
|
|
15
|
+
assert_equal([], spec.actions)
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def test_class__no_rels_and_order
|
|
19
|
+
parser = ADSLParser.new
|
|
20
|
+
spec = parser.parse <<-adsl
|
|
21
|
+
class Kme {}
|
|
22
|
+
class Zsd {}
|
|
23
|
+
class Asd {}
|
|
24
|
+
adsl
|
|
25
|
+
assert_equal 3, spec.classes.length
|
|
26
|
+
assert_equal ["Kme", "Zsd", "Asd"], spec.classes.map{ |a| a.name }
|
|
27
|
+
spec.classes.each do |klass|
|
|
28
|
+
assert_equal 0, klass.relations.count
|
|
29
|
+
assert_nil klass.parent
|
|
30
|
+
end
|
|
31
|
+
assert_equal 0, spec.actions.count
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def test_class__superclass
|
|
35
|
+
parser = ADSLParser.new
|
|
36
|
+
assert_raise ADSLError do
|
|
37
|
+
parser.parse <<-adsl
|
|
38
|
+
class Class extends Unknown {}
|
|
39
|
+
adsl
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
spec = parser.parse <<-adsl
|
|
43
|
+
class Super {}
|
|
44
|
+
class Sub extends Super {}
|
|
45
|
+
adsl
|
|
46
|
+
assert_equal 2, spec.classes.length
|
|
47
|
+
assert_nil spec.classes[0].parent
|
|
48
|
+
assert_equal spec.classes[0], spec.classes[1].parent
|
|
49
|
+
|
|
50
|
+
spec = parser.parse <<-adsl
|
|
51
|
+
class Sub extends Super {}
|
|
52
|
+
class Super {}
|
|
53
|
+
adsl
|
|
54
|
+
assert_equal 2, spec.classes.length
|
|
55
|
+
assert_nil spec.classes[1].parent
|
|
56
|
+
assert_equal spec.classes[1], spec.classes[0].parent
|
|
57
|
+
|
|
58
|
+
begin
|
|
59
|
+
parser.parse <<-adsl
|
|
60
|
+
class Class extends Class {}
|
|
61
|
+
adsl
|
|
62
|
+
flunk "No error raised"
|
|
63
|
+
rescue ADSLError => e
|
|
64
|
+
assert e.message.include? 'Class -> Class'
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
begin
|
|
68
|
+
parser.parse <<-adsl
|
|
69
|
+
class First extends Class1 {}
|
|
70
|
+
class Class2 extends Class1 {}
|
|
71
|
+
class Class1 extends Class2 {}
|
|
72
|
+
adsl
|
|
73
|
+
flunk "No error raised"
|
|
74
|
+
rescue ADSLError => e
|
|
75
|
+
assert e.message.include? 'Class1 -> Class2'
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
def test_typecheck__rels_valid
|
|
80
|
+
parser = ADSLParser.new
|
|
81
|
+
spec = parser.parse <<-adsl
|
|
82
|
+
class Classname {
|
|
83
|
+
1 Classname other
|
|
84
|
+
1 Classname something_else
|
|
85
|
+
1 Classname third
|
|
86
|
+
}
|
|
87
|
+
adsl
|
|
88
|
+
|
|
89
|
+
klass = spec.classes.select{ |a| a.name == "Classname" }.first
|
|
90
|
+
assert klass
|
|
91
|
+
assert_equal 3, klass.relations.count
|
|
92
|
+
assert_equal 'other', klass.relations[0].name
|
|
93
|
+
assert_equal 'something_else', klass.relations[1].name
|
|
94
|
+
assert_equal 'third', klass.relations[2].name
|
|
95
|
+
klass.relations.each do |rel|
|
|
96
|
+
assert rel.inverse_of.nil?
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
def test_typecheck__inverse_rels_valid
|
|
101
|
+
parser = ADSLParser.new
|
|
102
|
+
spec = parser.parse <<-adsl
|
|
103
|
+
class Classname {
|
|
104
|
+
1 Classname other
|
|
105
|
+
1 Classname something_else inverseof other
|
|
106
|
+
}
|
|
107
|
+
adsl
|
|
108
|
+
|
|
109
|
+
klass = spec.classes.select{ |a| a.name == "Classname" }.first
|
|
110
|
+
assert klass
|
|
111
|
+
assert_equal 2, klass.relations.count
|
|
112
|
+
assert_equal 1, klass.relations.select{ |a| a.inverse_of.nil? }.length
|
|
113
|
+
assert_equal 1, klass.relations.select{ |a| not a.inverse_of.nil? }.length
|
|
114
|
+
other = klass.relations.select{ |a| a.name == 'other'}.first
|
|
115
|
+
something_else = klass.relations.select{ |a| a.name == 'something_else'}.first
|
|
116
|
+
assert_equal other, something_else.inverse_of
|
|
117
|
+
|
|
118
|
+
assert_nothing_raised ADSLError do
|
|
119
|
+
parser.parse <<-adsl
|
|
120
|
+
class Classname {
|
|
121
|
+
1 Classname something_else inverseof other
|
|
122
|
+
1 Classname other
|
|
123
|
+
}
|
|
124
|
+
adsl
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
assert_nothing_raised ADSLError do
|
|
128
|
+
parser.parse <<-adsl
|
|
129
|
+
class Classname1 {
|
|
130
|
+
1 Classname2 something_else inverseof other
|
|
131
|
+
}
|
|
132
|
+
class Classname2 {
|
|
133
|
+
1 Classname1 other
|
|
134
|
+
}
|
|
135
|
+
adsl
|
|
136
|
+
end
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
def test_typecheck__relation_cardinality_valid
|
|
140
|
+
parser = ADSLParser.new
|
|
141
|
+
spec = parser.parse <<-adsl
|
|
142
|
+
class Classname {
|
|
143
|
+
1 Classname other1
|
|
144
|
+
1..1 Classname other2
|
|
145
|
+
0..1 Classname other3
|
|
146
|
+
0+ Classname other4
|
|
147
|
+
1+ Classname other5
|
|
148
|
+
}
|
|
149
|
+
adsl
|
|
150
|
+
|
|
151
|
+
klass = spec.classes.select{ |a| a.name == "Classname" }.first
|
|
152
|
+
assert klass
|
|
153
|
+
assert_equal [1, 1], klass.relations[0].cardinality
|
|
154
|
+
assert_equal [1, 1], klass.relations[1].cardinality
|
|
155
|
+
assert_equal [0, 1], klass.relations[2].cardinality
|
|
156
|
+
assert_equal [0, 1.0/0.0], klass.relations[3].cardinality
|
|
157
|
+
assert_equal [1, 1.0/0.0], klass.relations[4].cardinality
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
def test_typecheck__relation_cardinality_invalid
|
|
161
|
+
parser = ADSLParser.new
|
|
162
|
+
assert_raise ADSLError do
|
|
163
|
+
parser.parse <<-adsl
|
|
164
|
+
class Classname {
|
|
165
|
+
0 Classname other
|
|
166
|
+
}
|
|
167
|
+
adsl
|
|
168
|
+
end
|
|
169
|
+
assert_raise ADSLError do
|
|
170
|
+
parser.parse <<-adsl
|
|
171
|
+
class Classname {
|
|
172
|
+
0..0 Classname other
|
|
173
|
+
}
|
|
174
|
+
adsl
|
|
175
|
+
end
|
|
176
|
+
assert_raise ADSLError do
|
|
177
|
+
parser.parse <<-adsl
|
|
178
|
+
class Classname {
|
|
179
|
+
1..0 Classname other
|
|
180
|
+
}
|
|
181
|
+
adsl
|
|
182
|
+
end
|
|
183
|
+
end
|
|
184
|
+
|
|
185
|
+
def test_typecheck__repeating_classname
|
|
186
|
+
parser = ADSLParser.new
|
|
187
|
+
assert_raise ADSLError do
|
|
188
|
+
parser.parse <<-adsl
|
|
189
|
+
class Classname {}
|
|
190
|
+
class Classname {}
|
|
191
|
+
adsl
|
|
192
|
+
end
|
|
193
|
+
end
|
|
194
|
+
|
|
195
|
+
def test_typecheck__unknown_rel_type
|
|
196
|
+
parser = ADSLParser.new
|
|
197
|
+
assert_raise ADSLError do
|
|
198
|
+
parser.parse <<-adsl
|
|
199
|
+
class Classname {
|
|
200
|
+
1 UnknownClass other
|
|
201
|
+
}
|
|
202
|
+
adsl
|
|
203
|
+
end
|
|
204
|
+
end
|
|
205
|
+
|
|
206
|
+
def test_typecheck__mulitple_rels_under_the_same_name
|
|
207
|
+
parser = ADSLParser.new
|
|
208
|
+
assert_raise ADSLError do
|
|
209
|
+
parser.parse <<-adsl
|
|
210
|
+
class Classname {
|
|
211
|
+
1 Classname other
|
|
212
|
+
1 Classname other
|
|
213
|
+
}
|
|
214
|
+
adsl
|
|
215
|
+
end
|
|
216
|
+
end
|
|
217
|
+
|
|
218
|
+
def test_typecheck__multiple_rels_same_name_different_classes
|
|
219
|
+
parser = ADSLParser.new
|
|
220
|
+
assert_nothing_raised do
|
|
221
|
+
parser.parse <<-adsl
|
|
222
|
+
class Classname {
|
|
223
|
+
1 Classname other
|
|
224
|
+
}
|
|
225
|
+
class Classname2 {
|
|
226
|
+
1 Classname other
|
|
227
|
+
}
|
|
228
|
+
adsl
|
|
229
|
+
end
|
|
230
|
+
end
|
|
231
|
+
|
|
232
|
+
def test_typecheck__multiple_rels_same_name_parent_classes
|
|
233
|
+
parser = ADSLParser.new
|
|
234
|
+
assert_nothing_raised ADSLError do
|
|
235
|
+
parser.parse <<-adsl
|
|
236
|
+
class Parent {
|
|
237
|
+
1 Parent other
|
|
238
|
+
}
|
|
239
|
+
class Child extends Parent {
|
|
240
|
+
1 Parent other2
|
|
241
|
+
}
|
|
242
|
+
adsl
|
|
243
|
+
end
|
|
244
|
+
assert_raise ADSLError do
|
|
245
|
+
parser.parse <<-adsl
|
|
246
|
+
class Parent {
|
|
247
|
+
1 Parent other
|
|
248
|
+
}
|
|
249
|
+
class Child extends Parent {
|
|
250
|
+
1 Parent other
|
|
251
|
+
}
|
|
252
|
+
adsl
|
|
253
|
+
end
|
|
254
|
+
end
|
|
255
|
+
|
|
256
|
+
def test_typecheck__inverse_rel_of_unexisting
|
|
257
|
+
parser = ADSLParser.new
|
|
258
|
+
assert_raise ADSLError do
|
|
259
|
+
parser.parse <<-adsl
|
|
260
|
+
class Classname {
|
|
261
|
+
1 Classname other
|
|
262
|
+
1 Classname other2 inverseof unexisting
|
|
263
|
+
}
|
|
264
|
+
adsl
|
|
265
|
+
end
|
|
266
|
+
end
|
|
267
|
+
|
|
268
|
+
def test_typecheck__inverse_rel_of_an_inverse
|
|
269
|
+
parser = ADSLParser.new
|
|
270
|
+
assert_raise ADSLError do
|
|
271
|
+
parser.parse <<-adsl
|
|
272
|
+
class Classname {
|
|
273
|
+
1 Classname other inverseof other
|
|
274
|
+
}
|
|
275
|
+
adsl
|
|
276
|
+
end
|
|
277
|
+
assert_raise ADSLError do
|
|
278
|
+
parser.parse <<-adsl
|
|
279
|
+
class Classname {
|
|
280
|
+
0+ Classname rel1 inverseof rel2
|
|
281
|
+
0+ Classname rel2 inverseof rel1
|
|
282
|
+
}
|
|
283
|
+
adsl
|
|
284
|
+
end
|
|
285
|
+
end
|
|
286
|
+
|
|
287
|
+
end
|
|
288
|
+
end
|