human-ql 1.0.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 +7 -0
- data/History.rdoc +2 -0
- data/Manifest.txt +17 -0
- data/README.rdoc +59 -0
- data/Rakefile +14 -0
- data/lib/human-ql.rb +17 -0
- data/lib/human-ql/base.rb +21 -0
- data/lib/human-ql/postgresql_custom_parser.rb +67 -0
- data/lib/human-ql/postgresql_generator.rb +83 -0
- data/lib/human-ql/query_generator.rb +163 -0
- data/lib/human-ql/query_parser.rb +498 -0
- data/lib/human-ql/tree_normalizer.rb +226 -0
- data/test/setup.rb +24 -0
- data/test/test_postgresql_fuzz.rb +90 -0
- data/test/test_postgresql_generator.rb +171 -0
- data/test/test_query_generator.rb +87 -0
- data/test/test_query_parser.rb +306 -0
- data/test/test_tree_normalizer.rb +153 -0
- metadata +143 -0
@@ -0,0 +1,87 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
#--
|
4
|
+
# Copyright (c) 2016 David Kellum
|
5
|
+
#
|
6
|
+
# Licensed under the Apache License, Version 2.0 (the "License"); you
|
7
|
+
# may not use this file except in compliance with the License. You may
|
8
|
+
# obtain a copy of the License at
|
9
|
+
#
|
10
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
11
|
+
#
|
12
|
+
# Unless required by applicable law or agreed to in writing, software
|
13
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
14
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
15
|
+
# implied. See the License for the specific language governing
|
16
|
+
# permissions and limitations under the License.
|
17
|
+
#++
|
18
|
+
|
19
|
+
require_relative 'setup.rb'
|
20
|
+
require 'human-ql/query_generator'
|
21
|
+
|
22
|
+
class TestQueryGenerator < Minitest::Test
|
23
|
+
|
24
|
+
TC = HumanQL::QueryParser.new
|
25
|
+
QG = HumanQL::QueryGenerator.new( parser: TC )
|
26
|
+
|
27
|
+
A = 'a'
|
28
|
+
B = 'b'
|
29
|
+
C = 'c'
|
30
|
+
D = 'd'
|
31
|
+
E = 'e'
|
32
|
+
FOO = 'FOO'
|
33
|
+
|
34
|
+
def assert_gen( expected, ast )
|
35
|
+
out = QG.generate( ast )
|
36
|
+
assert_equal( expected, out, ast )
|
37
|
+
end
|
38
|
+
|
39
|
+
def test_empty
|
40
|
+
assert_gen( nil, nil )
|
41
|
+
end
|
42
|
+
|
43
|
+
def test_simple
|
44
|
+
assert_gen( 'a', A )
|
45
|
+
end
|
46
|
+
|
47
|
+
def test_default
|
48
|
+
assert_gen( 'a b', [:and, A, B] )
|
49
|
+
end
|
50
|
+
|
51
|
+
def test_or
|
52
|
+
assert_gen( 'a or b', [:or, A, B] )
|
53
|
+
end
|
54
|
+
|
55
|
+
def test_not
|
56
|
+
assert_gen( '-a', [:not, A] )
|
57
|
+
end
|
58
|
+
|
59
|
+
def test_not_or
|
60
|
+
assert_gen( '-(a or b)', [:not, [:or, A, B]] )
|
61
|
+
end
|
62
|
+
|
63
|
+
def test_not_and
|
64
|
+
assert_gen( '-(a b)', [:not, [:and, A, B]] )
|
65
|
+
end
|
66
|
+
|
67
|
+
def test_scope
|
68
|
+
assert_gen( 'FOO:a', [FOO, A] )
|
69
|
+
assert_gen( 'FOO:(a or b)', [FOO, [:or, A, B]] )
|
70
|
+
end
|
71
|
+
|
72
|
+
def test_complex_1
|
73
|
+
assert_gen( 'a or b c or d',
|
74
|
+
[:and, [:or, A, B], [:or, C, D]] )
|
75
|
+
end
|
76
|
+
|
77
|
+
def test_complex_2
|
78
|
+
assert_gen( '"a b" -(c or d)',
|
79
|
+
[:and, [:phrase, A, B], [:not, [:or, C, D]]] )
|
80
|
+
end
|
81
|
+
|
82
|
+
def test_complex_3
|
83
|
+
assert_gen( '-(a b) or (c d) or e',
|
84
|
+
[:or, [:not, [:and, A, B]], [:and, C, D], E] )
|
85
|
+
end
|
86
|
+
|
87
|
+
end
|
@@ -0,0 +1,306 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
#--
|
4
|
+
# Copyright (c) 2016 David Kellum
|
5
|
+
#
|
6
|
+
# Licensed under the Apache License, Version 2.0 (the "License"); you
|
7
|
+
# may not use this file except in compliance with the License. You may
|
8
|
+
# obtain a copy of the License at
|
9
|
+
#
|
10
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
11
|
+
#
|
12
|
+
# Unless required by applicable law or agreed to in writing, software
|
13
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
14
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
15
|
+
# implied. See the License for the specific language governing
|
16
|
+
# permissions and limitations under the License.
|
17
|
+
#++
|
18
|
+
|
19
|
+
require_relative 'setup.rb'
|
20
|
+
|
21
|
+
require 'human-ql/query_parser'
|
22
|
+
require 'human-ql/tree_normalizer'
|
23
|
+
|
24
|
+
class TestingQueryParser < HumanQL::QueryParser
|
25
|
+
def initialize
|
26
|
+
super( scopes: [ 'FOO', ignorecase: true ],
|
27
|
+
verbose: ARGV.include?( '--verbose' ) )
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
class TestQueryParser < Minitest::Test
|
32
|
+
TC = TestingQueryParser.new
|
33
|
+
DN = HumanQL::TreeNormalizer.new( not_scope: true )
|
34
|
+
|
35
|
+
def test_norm_prefix
|
36
|
+
assert_equal( '-', TC.norm_prefix( '-' ) )
|
37
|
+
assert_equal( '- ', TC.norm_prefix( '- ' ) )
|
38
|
+
assert_equal( 'a-b', TC.norm_prefix( 'a-b' ) )
|
39
|
+
assert_equal( '- a', TC.norm_prefix( '-a' ) )
|
40
|
+
assert_equal( '- ab', TC.norm_prefix( '-ab' ) )
|
41
|
+
assert_equal( 'a - b', TC.norm_prefix( 'a -b' ) )
|
42
|
+
assert_equal( 'a - bc', TC.norm_prefix( 'a -bc' ) )
|
43
|
+
end
|
44
|
+
|
45
|
+
def test_norm_quote
|
46
|
+
assert_equal( ' " ', TC.norm_infix( '"' ) )
|
47
|
+
assert_equal( ' " ', TC.norm_infix( '" ' ) )
|
48
|
+
assert_equal( 'a " b', TC.norm_infix( 'a"b' ) )
|
49
|
+
assert_equal( ' " a', TC.norm_infix( '"a' ) )
|
50
|
+
assert_equal( ' " ab " ', TC.norm_infix( '"ab"' ) )
|
51
|
+
assert_equal( 'a " b " ', TC.norm_infix( 'a "b"' ) )
|
52
|
+
assert_equal( 'a " bc " ', TC.norm_infix( 'a "bc"' ) )
|
53
|
+
end
|
54
|
+
|
55
|
+
def test_norm_parens_split
|
56
|
+
assert_equal( ' ( ', TC.norm_infix( '(' ) )
|
57
|
+
assert_equal( ' ( ', TC.norm_infix( '( ' ) )
|
58
|
+
assert_equal( ' ( a ) ', TC.norm_infix( '(a)' ) )
|
59
|
+
assert_equal( ' ( ab ) ', TC.norm_infix( '(ab)' ) )
|
60
|
+
assert_equal( 'a ( b ) ', TC.norm_infix( 'a (b)' ) )
|
61
|
+
assert_equal( 'a ( bc ) ', TC.norm_infix( 'a (bc)' ) )
|
62
|
+
assert_equal( 'a ( b ) ', TC.norm_infix( 'a(b)' ) )
|
63
|
+
end
|
64
|
+
|
65
|
+
def test_norm_space
|
66
|
+
assert_equal( 'foo', TC.norm_space( 'foo' ) )
|
67
|
+
assert_equal( 'foo', TC.norm_space( ' foo' ) )
|
68
|
+
assert_equal( 'foo', TC.norm_space( ' foo ' ) )
|
69
|
+
assert_equal( 'foo bar', TC.norm_space( " foo\t bar\r " ) )
|
70
|
+
end
|
71
|
+
|
72
|
+
def test_norm_scope
|
73
|
+
assert_equal( 'FOO: ', TC.norm_scope( 'FOO:' ) )
|
74
|
+
assert_equal( ' ', TC.norm_scope( ':' ) )
|
75
|
+
assert_equal( ' ', TC.norm_scope( ' :' ) )
|
76
|
+
assert_equal( ' after', TC.norm_scope( ':after' ) )
|
77
|
+
assert_equal( ' after', TC.norm_scope( ' :after' ) )
|
78
|
+
|
79
|
+
assert_equal( 'FOO: bar', TC.norm_scope( 'FOO:bar' ) )
|
80
|
+
assert_equal( 'FOO: bar', TC.norm_scope( 'FOO: bar' ) )
|
81
|
+
assert_equal( 'FOO: bar', TC.norm_scope( 'FOO : bar' ) )
|
82
|
+
|
83
|
+
assert_equal( ' FOO: bar', TC.norm_scope( ' FOO:bar' ) )
|
84
|
+
assert_equal( 'a FOO: bar', TC.norm_scope( 'a FOO:bar' ) )
|
85
|
+
end
|
86
|
+
|
87
|
+
def test_norm_scope_undefined
|
88
|
+
assert_equal( 'other bar', TC.norm_scope( 'other : bar' ) )
|
89
|
+
assert_equal( 'other bar', TC.norm_scope( 'other: bar' ) )
|
90
|
+
assert_equal( 'other bar', TC.norm_scope( 'other:bar' ) )
|
91
|
+
|
92
|
+
assert_equal( ' other bar', TC.norm_scope( ' other: bar' ) )
|
93
|
+
assert_equal( 'a other bar', TC.norm_scope( 'a other: bar' ) )
|
94
|
+
end
|
95
|
+
|
96
|
+
def test_normalize
|
97
|
+
assert_equal( nil, TC.normalize( nil ) )
|
98
|
+
assert_equal( nil, TC.normalize( '' ) )
|
99
|
+
assert_equal( nil, TC.normalize( ' ' ) )
|
100
|
+
assert_equal( 'a ( bc | d )', TC.normalize( 'a (bc|d)' ) )
|
101
|
+
assert_equal( '- ( a | b )', TC.normalize( '-(a|b)' ) )
|
102
|
+
end
|
103
|
+
|
104
|
+
A = 'a'
|
105
|
+
B = 'b'
|
106
|
+
C = 'c'
|
107
|
+
D = 'd'
|
108
|
+
E = 'e'
|
109
|
+
FOO = 'FOO'
|
110
|
+
|
111
|
+
def assert_parse( expected_tree, input )
|
112
|
+
out = TC.parse( input )
|
113
|
+
out = DN.normalize( out )
|
114
|
+
assert_equal( expected_tree, out, input )
|
115
|
+
end
|
116
|
+
|
117
|
+
def test_parse_basic_1
|
118
|
+
assert_parse( 'a', 'a' )
|
119
|
+
end
|
120
|
+
|
121
|
+
def test_parse_basic_2
|
122
|
+
assert_parse( [ :and, A, B ], 'a b' )
|
123
|
+
end
|
124
|
+
|
125
|
+
def test_parse_scope_basic
|
126
|
+
assert_parse( [ FOO, A ], 'FOO:a' )
|
127
|
+
assert_parse( [ FOO, A ], 'FOO: a' )
|
128
|
+
assert_parse( [ FOO, A ], 'FOO : a' )
|
129
|
+
assert_parse( [ :and, [ FOO, A ], [ FOO, B ] ], 'FOO : a FOO:b' )
|
130
|
+
assert_parse( [ :or, [ FOO, A ], [ FOO, B ] ], 'FOO : a | FOO:b' )
|
131
|
+
end
|
132
|
+
|
133
|
+
def test_parse_scope_complex
|
134
|
+
assert_parse( [ FOO, [ :phrase, A, B ] ], 'FOO:"a b"' )
|
135
|
+
assert_parse( [ FOO, [ :and, A, B ] ], 'FOO:(a b)' )
|
136
|
+
assert_parse( [ FOO, [ :or, A, B ] ], 'FOO:(a|b)' )
|
137
|
+
end
|
138
|
+
|
139
|
+
def test_parse_scope_not
|
140
|
+
assert_parse( [ FOO, [ :not, A ] ], 'FOO:-a' )
|
141
|
+
end
|
142
|
+
|
143
|
+
def test_parse_not_scope_paren
|
144
|
+
assert_parse( [ :not, [ FOO, A ] ], '-(FOO:a)' )
|
145
|
+
end
|
146
|
+
|
147
|
+
def test_parse_not_scope
|
148
|
+
assert_parse( [ FOO, A ], '- FOO:a' )
|
149
|
+
assert_parse( [ :and, [ :not, FOO ], A ], '-FOO:a' )
|
150
|
+
end
|
151
|
+
|
152
|
+
def test_parse_phrase
|
153
|
+
assert_parse( [ :phrase, A, B ], '"a b"' )
|
154
|
+
end
|
155
|
+
|
156
|
+
def test_parse_empty
|
157
|
+
assert_parse( nil, '' )
|
158
|
+
end
|
159
|
+
|
160
|
+
def test_parse_empty_phrase
|
161
|
+
assert_parse( nil, '"' )
|
162
|
+
assert_parse( nil, '""' )
|
163
|
+
end
|
164
|
+
|
165
|
+
def test_parse_not
|
166
|
+
assert_parse( [ :not, A ], '-a' )
|
167
|
+
end
|
168
|
+
|
169
|
+
def test_parse_not_noop
|
170
|
+
assert_parse( nil, '-' )
|
171
|
+
end
|
172
|
+
|
173
|
+
def test_parse_or
|
174
|
+
assert_parse( [ :or, A, B ], 'a|b' )
|
175
|
+
end
|
176
|
+
|
177
|
+
def test_parse_or_noop_0
|
178
|
+
assert_parse( nil, '|' )
|
179
|
+
assert_parse( nil, '||' )
|
180
|
+
assert_parse( nil, '|&' )
|
181
|
+
assert_parse( nil, '&|' )
|
182
|
+
assert_parse( nil, '-|' )
|
183
|
+
assert_parse( nil, '|-' )
|
184
|
+
end
|
185
|
+
|
186
|
+
def test_noop_trailing_not
|
187
|
+
assert_parse( A, 'a -' )
|
188
|
+
end
|
189
|
+
|
190
|
+
def test_noop_trailing_or
|
191
|
+
assert_parse( [:and, A, B], 'a b |' )
|
192
|
+
end
|
193
|
+
|
194
|
+
def test_noop_leading_or
|
195
|
+
assert_parse( [:and, A, B], '| a b' )
|
196
|
+
end
|
197
|
+
|
198
|
+
def test_parse_or_noop_1
|
199
|
+
assert_parse( A, '|a' )
|
200
|
+
end
|
201
|
+
|
202
|
+
def test_parse_or_noop_2
|
203
|
+
assert_parse( A, 'a|' )
|
204
|
+
end
|
205
|
+
|
206
|
+
def test_parse_and_noop_1
|
207
|
+
assert_parse( A, '&a' )
|
208
|
+
end
|
209
|
+
|
210
|
+
def test_parse_and_noop_2
|
211
|
+
assert_parse( A, 'a&' )
|
212
|
+
end
|
213
|
+
|
214
|
+
def test_parse_not_phrase
|
215
|
+
assert_parse( [ :not, [ :phrase, A, B ] ], '-"a b"' )
|
216
|
+
end
|
217
|
+
|
218
|
+
def test_parse_parens_empty
|
219
|
+
assert_parse( nil, '()' )
|
220
|
+
end
|
221
|
+
|
222
|
+
def test_parse_adj_parens
|
223
|
+
assert_parse( [:and, A, B], '(a)b' )
|
224
|
+
assert_parse( [:and, [:not, 'a-' ], B], '-(a-)b' )
|
225
|
+
assert_parse( [:and, [:not, A], B], '-(a)b' )
|
226
|
+
end
|
227
|
+
|
228
|
+
def test_parse_parens_0
|
229
|
+
assert_parse( A, '(a)' )
|
230
|
+
end
|
231
|
+
|
232
|
+
def test_parse_parens_1
|
233
|
+
assert_parse( [ :and, A, B ], '(a b)' )
|
234
|
+
end
|
235
|
+
|
236
|
+
def test_parse_parens_2
|
237
|
+
assert_parse( [ :and, [ :or, A, B ], C ], '(a|b) c' )
|
238
|
+
end
|
239
|
+
|
240
|
+
def test_parse_parens_3
|
241
|
+
assert_parse( [ :and, C, [ :or, A, B ] ], 'c (a|b)' )
|
242
|
+
end
|
243
|
+
|
244
|
+
def test_parse_parens_4
|
245
|
+
assert_parse( [ :and, D, [ :or, A, B, C ] ], 'd (a|b|c)' )
|
246
|
+
end
|
247
|
+
|
248
|
+
def test_parse_parens_5
|
249
|
+
assert_parse( [ :and, [ :or, A, B ], [ :or, C, D ] ], '(a|b) (c|d)' )
|
250
|
+
assert_parse( [ :and, [ :or, A, B ], [ :or, C, D ] ], '((a|b) (c|d))' )
|
251
|
+
end
|
252
|
+
|
253
|
+
def test_parse_parens_6
|
254
|
+
assert_parse( [ :or, [ :and, A, B ], [ :and, C, D ] ], '((a&b) | (c&d))' )
|
255
|
+
assert_parse( [ :or, [ :and, A, B ], [ :not, [ :and, C, D ] ] ],
|
256
|
+
'((a&b) | -(c&d))' )
|
257
|
+
assert_parse( [ :or, [ :not, [ :and, A, B ] ], [ :and, C, D ], E ],
|
258
|
+
'(-(a&b) | (c&d) | e )' )
|
259
|
+
end
|
260
|
+
|
261
|
+
def test_parens_and_quotes
|
262
|
+
assert_parse( [:phrase, 'a' ], '"(a)"' )
|
263
|
+
assert_parse( [ :or, [ :and, A, B ], [ :and, C, D ] ], '((a&b) |"(c&d))' )
|
264
|
+
assert_parse( [ :or, [ :and, A, B ], [ :and, C, D ] ], '((a&b) |(c&d)")' )
|
265
|
+
assert_parse( [ :and, [ :or, [ :and, A, B ], C ], D ], '((a&b) |(c&"d))' )
|
266
|
+
assert_parse( [ :or, [ :and, A, B ], [ :and, [:phrase, C], D ] ],
|
267
|
+
'((a&b) |("c))"&d))' )
|
268
|
+
end
|
269
|
+
|
270
|
+
def test_parse_precedence_1
|
271
|
+
assert_parse( [ :and, [ :or, A, B ], C ], 'a | b c' )
|
272
|
+
end
|
273
|
+
|
274
|
+
def test_parse_precedence_2
|
275
|
+
assert_parse( [ :and, A, [ :or, B, C ] ], 'a b | c' )
|
276
|
+
end
|
277
|
+
|
278
|
+
def test_parse_precedence_3
|
279
|
+
assert_parse( [ :and, [ :or, A, [ :not, B ] ], C ], 'a | - b c' )
|
280
|
+
end
|
281
|
+
|
282
|
+
def test_parse_precedence_4_explicit
|
283
|
+
assert_parse( [ :and, [ :or, [ :not, A ], B ], C ], '-a | b & c' )
|
284
|
+
end
|
285
|
+
|
286
|
+
def test_parse_precedence_4_implied
|
287
|
+
assert_parse( [ :and, [ :or, [ :not, A ], B ], C ], '-a | b c' )
|
288
|
+
end
|
289
|
+
|
290
|
+
def test_parse_precedence_5_explicit
|
291
|
+
assert_parse( [ :and, [ :or, A, B ], [ :not, C ] ], 'a | b AND -c' )
|
292
|
+
end
|
293
|
+
|
294
|
+
def test_parse_precedence_5_implied
|
295
|
+
assert_parse( [ :and, [ :or, A, B ], [ :not, C ] ], 'a | b -c' )
|
296
|
+
end
|
297
|
+
|
298
|
+
def test_parse_precedence_6
|
299
|
+
assert_parse( [ :and, [ :or, A, B ], [ :not, C ], D ], 'a | b -c d' )
|
300
|
+
end
|
301
|
+
|
302
|
+
def test_parse_empty_not
|
303
|
+
assert_parse( A, 'a -""' )
|
304
|
+
end
|
305
|
+
|
306
|
+
end
|
@@ -0,0 +1,153 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
#--
|
4
|
+
# Copyright (c) 2016 David Kellum
|
5
|
+
#
|
6
|
+
# Licensed under the Apache License, Version 2.0 (the "License"); you
|
7
|
+
# may not use this file except in compliance with the License. You may
|
8
|
+
# obtain a copy of the License at
|
9
|
+
#
|
10
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
11
|
+
#
|
12
|
+
# Unless required by applicable law or agreed to in writing, software
|
13
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
14
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
15
|
+
# implied. See the License for the specific language governing
|
16
|
+
# permissions and limitations under the License.
|
17
|
+
#++
|
18
|
+
|
19
|
+
require_relative 'setup.rb'
|
20
|
+
|
21
|
+
require 'human-ql/tree_normalizer'
|
22
|
+
|
23
|
+
class TestTreeNormalizer < Minitest::Test
|
24
|
+
DN = HumanQL::TreeNormalizer.new
|
25
|
+
UN = HumanQL::TreeNormalizer.new( unconstrained_not: false )
|
26
|
+
LN = HumanQL::TreeNormalizer.new( unconstrained_not: false,
|
27
|
+
scope_at_top_only: true,
|
28
|
+
scope_and_only: true )
|
29
|
+
|
30
|
+
A = 'a'
|
31
|
+
B = 'b'
|
32
|
+
C = 'c'
|
33
|
+
D = 'd'
|
34
|
+
E = 'e'
|
35
|
+
|
36
|
+
S1 = 'S1'
|
37
|
+
S2 = 'S2'
|
38
|
+
|
39
|
+
def assert_norm( normalizer, expected, input )
|
40
|
+
output = normalizer.normalize( input )
|
41
|
+
assert_equal( expected, output, input )
|
42
|
+
end
|
43
|
+
|
44
|
+
def assert_norm_identity( normalizer, id )
|
45
|
+
assert_norm( normalizer, id, id )
|
46
|
+
end
|
47
|
+
|
48
|
+
def test_basic_norm_0
|
49
|
+
assert_norm( DN, nil, nil )
|
50
|
+
assert_norm( DN, nil, [ :and ] )
|
51
|
+
end
|
52
|
+
|
53
|
+
def test_basic_norm_1
|
54
|
+
assert_norm( DN, A, A )
|
55
|
+
end
|
56
|
+
|
57
|
+
def test_basic_norm_2
|
58
|
+
assert_norm( DN, A, [ :or, [ :and ], A ] )
|
59
|
+
end
|
60
|
+
|
61
|
+
def test_basic_norm_3
|
62
|
+
assert_norm( DN, [ :and, A, B ], [ :and, [ :and, A, B ] ] )
|
63
|
+
end
|
64
|
+
|
65
|
+
def test_not
|
66
|
+
assert_norm( DN, [ :not, A ], [ :not, A ] )
|
67
|
+
assert_norm( DN, [ :not, A ], [ :not, A, B ] )
|
68
|
+
end
|
69
|
+
|
70
|
+
def test_nested_not
|
71
|
+
assert_norm( DN, nil, [ :not, [ :not, A ] ] )
|
72
|
+
assert_norm( DN, [ :not, B], [ :not, [ :and, [ :not, A ], B ] ])
|
73
|
+
end
|
74
|
+
|
75
|
+
def test_scope
|
76
|
+
assert_norm( DN, [ S1, A ], [ S1, A ] )
|
77
|
+
assert_norm( DN, [ S1, A ], [ S1, A, B ] )
|
78
|
+
end
|
79
|
+
|
80
|
+
def test_nested_scope
|
81
|
+
assert_norm( DN, [ S2, A ], [ S2, [ :and, A, [ S1, B ] ] ] )
|
82
|
+
assert_norm( DN, [ S2, [ :or, A, C ] ], [ S2, [ :or, A, [ S1, B ], C ] ] )
|
83
|
+
end
|
84
|
+
|
85
|
+
def test_nested_same_scope
|
86
|
+
assert_norm( DN, [ S2, [ :and, A, B ] ],
|
87
|
+
[ S2, [ :and, A, [ S2, B ] ] ] )
|
88
|
+
end
|
89
|
+
|
90
|
+
def test_scope_not
|
91
|
+
assert_norm_identity( DN, [ S1, [ :not, A ] ] )
|
92
|
+
end
|
93
|
+
|
94
|
+
def test_not_scope
|
95
|
+
# Should be inverted
|
96
|
+
assert_norm( DN, [ S1, [ :not, A ] ],
|
97
|
+
[ :not, [ S1, A ] ] )
|
98
|
+
assert_norm( DN, [ S1, [ :not, A ] ],
|
99
|
+
[ :not, [ :and, [ S1, A ] ] ] )
|
100
|
+
assert_norm( DN, [ :and, [ S1, [ :not, A ] ], B ],
|
101
|
+
[ :and, [ :not, [ S1, A ] ], B ] )
|
102
|
+
end
|
103
|
+
|
104
|
+
def test_not_scope_limited
|
105
|
+
assert_norm( LN, [ :and, A, [ S1, [ :not, B ] ] ],
|
106
|
+
[ :and, A, [ :not, [ S1, B ] ] ] )
|
107
|
+
assert_norm( LN, [ :and, A, [ S1, [ :not, B ] ] ],
|
108
|
+
[ :and, A, [ :not, [:and, [ S1, B ] ] ] ] )
|
109
|
+
end
|
110
|
+
|
111
|
+
def test_not_scope_indirect
|
112
|
+
assert_norm( DN, [ :not, B ],
|
113
|
+
[ :not, [ :or, [ S1, A ], B ] ] )
|
114
|
+
end
|
115
|
+
|
116
|
+
def test_unconstrained_scope_not
|
117
|
+
assert_norm( UN, nil, [ S1, [ :not, A ] ] )
|
118
|
+
end
|
119
|
+
|
120
|
+
def test_unconstrained_not_scope
|
121
|
+
assert_norm( UN, nil, [ :not, [ S1, A ] ] )
|
122
|
+
end
|
123
|
+
|
124
|
+
def test_unconstrained_not
|
125
|
+
assert_norm( UN, nil, [ :not, A ] )
|
126
|
+
assert_norm( UN, B, [ :or, [ :not, A ], B ] )
|
127
|
+
end
|
128
|
+
|
129
|
+
def test_unconstrained_not_complex
|
130
|
+
assert_norm( UN, nil, [ :and, [ :not, A ], [ :not, A ] ] )
|
131
|
+
assert_norm( UN, B, [ :and, [ :not, A ], [ :or, [ :not, A ], B ] ] )
|
132
|
+
end
|
133
|
+
|
134
|
+
def test_constrained_not
|
135
|
+
assert_norm_identity( UN, [ :and, [ :not, A ], B ] )
|
136
|
+
assert_norm_identity( UN, [ :and, [ :not, A ], [ :phrase, B, C ] ] )
|
137
|
+
assert_norm_identity( UN, [ :and, A, [ :or, [ :not, B ], [ :not, C ] ] ] )
|
138
|
+
assert_norm_identity( UN, [ :and, [ :or, A, D ],
|
139
|
+
[ :or, [ :not, B ], [ :not, C ] ] ] )
|
140
|
+
assert_norm_identity( UN, [ :and, [ :not, A ],
|
141
|
+
[ :or, [ :and, [ :not, B ], C ], D ] ] )
|
142
|
+
end
|
143
|
+
|
144
|
+
def test_limited_scope
|
145
|
+
assert_norm_identity( LN, [ S1, A ] )
|
146
|
+
assert_norm_identity( LN, [ :and, [ S1, A ], B ] )
|
147
|
+
assert_norm_identity( LN, [ :and, A, [ S1, B ] ] )
|
148
|
+
assert_norm( LN, B, [ :or, [ S1, A ], B ] )
|
149
|
+
assert_norm( LN, [ :and, B, C ],
|
150
|
+
[ :and, [ :or, [ S1, A ], B ], C ] )
|
151
|
+
end
|
152
|
+
|
153
|
+
end
|