predicate 2.7.1 → 2.9.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 (68) hide show
  1. checksums.yaml +5 -5
  2. data/README.md +17 -0
  3. data/lib/predicate/asserter.rb +12 -0
  4. data/lib/predicate/nodes/and.rb +22 -4
  5. data/lib/predicate/nodes/empty.rb +6 -0
  6. data/lib/predicate/nodes/eq.rb +10 -0
  7. data/lib/predicate/nodes/expr.rb +8 -0
  8. data/lib/predicate/nodes/gt.rb +6 -0
  9. data/lib/predicate/nodes/gte.rb +6 -0
  10. data/lib/predicate/nodes/in.rb +12 -0
  11. data/lib/predicate/nodes/lt.rb +6 -0
  12. data/lib/predicate/nodes/lte.rb +6 -0
  13. data/lib/predicate/nodes/neq.rb +17 -0
  14. data/lib/predicate/nodes/tautology.rb +4 -0
  15. data/lib/predicate/version.rb +2 -2
  16. data/lib/predicate.rb +21 -2
  17. data/spec/factory/shared/a_comparison_factory_method.rb +12 -4
  18. data/spec/factory/shared/a_predicate_ast_node.rb +11 -5
  19. data/spec/factory/test_${op_name}.rb.jeny +3 -1
  20. data/spec/factory/test_and.rb +6 -2
  21. data/spec/factory/test_comp.rb +27 -9
  22. data/spec/factory/test_contradiction.rb +3 -1
  23. data/spec/factory/test_empty.rb +3 -1
  24. data/spec/factory/test_factor_predicate.rb +21 -7
  25. data/spec/factory/test_from_hash.rb +21 -7
  26. data/spec/factory/test_has_size.rb +3 -1
  27. data/spec/factory/test_identifier.rb +6 -2
  28. data/spec/factory/test_literal.rb +6 -2
  29. data/spec/factory/test_match.rb +12 -4
  30. data/spec/factory/test_native.rb +6 -2
  31. data/spec/factory/test_not.rb +6 -2
  32. data/spec/factory/test_or.rb +6 -2
  33. data/spec/factory/test_qualified_identifier.rb +6 -2
  34. data/spec/factory/test_set_ops.rb +6 -2
  35. data/spec/factory/test_tautology.rb +3 -1
  36. data/spec/factory/test_var.rb +12 -4
  37. data/spec/grammar/test_match.rb +19 -19
  38. data/spec/grammar/test_sexpr.rb +49 -17
  39. data/spec/nodes/and/test_and_split.rb +30 -10
  40. data/spec/nodes/dyadic_comp/test_and_split.rb +18 -8
  41. data/spec/nodes/eq/test_and.rb +12 -4
  42. data/spec/nodes/identifier/test_and_split.rb +6 -2
  43. data/spec/nodes/identifier/test_free_variables.rb +3 -1
  44. data/spec/nodes/identifier/test_name.rb +3 -1
  45. data/spec/nodes/in/test_and.rb +18 -6
  46. data/spec/nodes/nadic_bool/test_free_variables.rb +3 -1
  47. data/spec/nodes/or/test_and_split.rb +6 -2
  48. data/spec/nodes/qualified_identifier/test_and_split.rb +6 -2
  49. data/spec/nodes/qualified_identifier/test_free_variables.rb +3 -1
  50. data/spec/nodes/qualified_identifier/test_name.rb +3 -1
  51. data/spec/nodes/qualified_identifier/test_qualifier.rb +3 -1
  52. data/spec/predicate/test_and_split.rb +48 -16
  53. data/spec/predicate/test_assert!.rb +277 -0
  54. data/spec/predicate/test_attr_split.rb +36 -12
  55. data/spec/predicate/test_bool_and.rb +7 -3
  56. data/spec/predicate/test_bool_not.rb +30 -10
  57. data/spec/predicate/test_bool_or.rb +7 -3
  58. data/spec/predicate/test_coerce.rb +19 -17
  59. data/spec/predicate/test_constants.rb +78 -26
  60. data/spec/predicate/test_free_variables.rb +3 -1
  61. data/spec/predicate/test_hash_and_equal.rb +7 -3
  62. data/spec/predicate/test_qualify.rb +8 -6
  63. data/spec/predicate/test_rename.rb +21 -11
  64. data/spec/sequel/test_to_sequel.rb +0 -1
  65. data/spec/shared/a_predicate.rb +8 -8
  66. data/spec/spec_helper.rb +1 -0
  67. data/spec/test_readme.rb +1 -1
  68. metadata +24 -9
@@ -11,37 +11,49 @@ class Predicate
11
11
  context 'with an eq on same variable' do
12
12
  let(:right){ Factory.eq(:x, 2) }
13
13
 
14
- it{ should be(right) }
14
+ it {
15
+ expect(subject).to be(right)
16
+ }
15
17
  end
16
18
 
17
19
  context 'with an eq on same variable yielding a contradiction' do
18
20
  let(:right){ Factory.eq(:x, 3) }
19
21
 
20
- it{ should eql(Factory.contradiction) }
22
+ it {
23
+ expect(subject).to eql(Factory.contradiction)
24
+ }
21
25
  end
22
26
 
23
27
  context 'with an in on same variable' do
24
28
  let(:right){ Factory.in(:x, [2, 4, 5]) }
25
29
 
26
- it{ should eql(Factory.in(:x, [2, 4])) }
30
+ it {
31
+ expect(subject).to eql(Factory.in(:x, [2, 4]))
32
+ }
27
33
  end
28
34
 
29
35
  context 'with an in on same variable, leading to a singleton' do
30
36
  let(:right){ Factory.in(:x, [2]) }
31
37
 
32
- it{ should eql(Factory.eq(:x, 2)) }
38
+ it {
39
+ expect(subject).to eql(Factory.eq(:x, 2))
40
+ }
33
41
  end
34
42
 
35
43
  context 'with an eq on same variable, leading to a singleton' do
36
44
  let(:right){ Factory.in(:x, [2, 5]) }
37
45
 
38
- it{ should eql(Factory.eq(:x, 2)) }
46
+ it {
47
+ expect(subject).to eql(Factory.eq(:x, 2))
48
+ }
39
49
  end
40
50
 
41
51
  context 'with an in on same variable, leading to a empty set' do
42
52
  let(:right){ Factory.in(:x, [5]) }
43
53
 
44
- it{ should eql(Factory.contradiction) }
54
+ it {
55
+ expect(subject).to eql(Factory.contradiction)
56
+ }
45
57
  end
46
58
 
47
59
  end
@@ -7,7 +7,9 @@ class Predicate
7
7
  context "on a complex attribute comparison" do
8
8
  let(:expr){ Factory.comp(:neq, :x => :y, :z => 2) }
9
9
 
10
- it{ should eq([:x, :y, :z]) }
10
+ it {
11
+ expect(subject).to eq([:x, :y, :z])
12
+ }
11
13
  end
12
14
 
13
15
  end
@@ -12,13 +12,17 @@ class Predicate
12
12
  context 'when fully covered' do
13
13
  let(:list){ [:x, :y] }
14
14
 
15
- it{ should eq([predicate, tautology]) }
15
+ it {
16
+ expect(subject).to eq([predicate, tautology])
17
+ }
16
18
  end
17
19
 
18
20
  context 'when fully disjoint' do
19
21
  let(:list){ [:z] }
20
22
 
21
- it{ should eq([tautology, predicate]) }
23
+ it {
24
+ expect(subject).to eq([tautology, predicate])
25
+ }
22
26
  end
23
27
 
24
28
  end
@@ -10,13 +10,17 @@ class Predicate
10
10
  context 'when included' do
11
11
  let(:list){ [:"t.id", :name] }
12
12
 
13
- it{ should eq([predicate, tautology]) }
13
+ it {
14
+ expect(subject).to eq([predicate, tautology])
15
+ }
14
16
  end
15
17
 
16
18
  context 'when not include' do
17
19
  let(:list){ [:name] }
18
20
 
19
- it{ should eq([tautology, predicate]) }
21
+ it {
22
+ expect(subject).to eq([tautology, predicate])
23
+ }
20
24
  end
21
25
 
22
26
  end
@@ -6,7 +6,9 @@ class Predicate
6
6
 
7
7
  subject{ expr.free_variables }
8
8
 
9
- it{ should eq([:"t.id"]) }
9
+ it {
10
+ expect(subject).to eq([:"t.id"])
11
+ }
10
12
 
11
13
  end
12
14
  end
@@ -6,7 +6,9 @@ class Predicate
6
6
 
7
7
  subject{ expr.name }
8
8
 
9
- it{ should eq(:id) }
9
+ it {
10
+ expect(subject).to eq(:id)
11
+ }
10
12
 
11
13
  end
12
14
  end
@@ -6,7 +6,9 @@ class Predicate
6
6
 
7
7
  subject{ expr.qualifier }
8
8
 
9
- it{ should eq(:t) }
9
+ it {
10
+ expect(subject).to eq(:t)
11
+ }
10
12
 
11
13
  end
12
14
  end
@@ -8,97 +8,129 @@ class Predicate
8
8
  context "on tautology" do
9
9
  let(:pred){ p.tautology }
10
10
 
11
- it{ should eq([p.tautology, p.tautology]) }
11
+ it {
12
+ expect(subject).to eq([p.tautology, p.tautology])
13
+ }
12
14
  end
13
15
 
14
16
  context "on contradiction" do
15
17
  let(:pred){ p.contradiction }
16
18
 
17
- it{ should eq([p.tautology, pred]) }
19
+ it {
20
+ expect(subject).to eq([p.tautology, pred])
21
+ }
18
22
  end
19
23
 
20
24
  context "on identifier (included)" do
21
25
  let(:pred){ p.identifier(:x) }
22
26
 
23
- it{ should eq([ pred, p.tautology ]) }
27
+ it {
28
+ expect(subject).to eq([ pred, p.tautology ])
29
+ }
24
30
  end
25
31
 
26
32
  context "on identifier (excluded)" do
27
33
  let(:pred){ p.identifier(:y) }
28
34
 
29
- it{ should eq([ p.tautology, pred ]) }
35
+ it {
36
+ expect(subject).to eq([ p.tautology, pred ])
37
+ }
30
38
  end
31
39
 
32
40
  context "on not (included)" do
33
41
  let(:pred){ p.not(:x) }
34
42
 
35
- it{ should eq([ pred, p.tautology ]) }
43
+ it {
44
+ expect(subject).to eq([ pred, p.tautology ])
45
+ }
36
46
  end
37
47
 
38
48
  context "on not (excluded)" do
39
49
  let(:pred){ p.not(:y) }
40
50
 
41
- it{ should eq([ p.tautology, pred ]) }
51
+ it {
52
+ expect(subject).to eq([ p.tautology, pred ])
53
+ }
42
54
  end
43
55
 
44
56
  context "on eq (included)" do
45
57
  let(:pred){ p.eq(:x, 2) }
46
58
 
47
- it{ should eq([ pred, p.tautology ]) }
59
+ it {
60
+ expect(subject).to eq([ pred, p.tautology ])
61
+ }
48
62
  end
49
63
 
50
64
  context "on eq (excluded)" do
51
65
  let(:pred){ p.eq(:y, 2) }
52
66
 
53
- it{ should eq([ p.tautology, pred ]) }
67
+ it {
68
+ expect(subject).to eq([ p.tautology, pred ])
69
+ }
54
70
  end
55
71
 
56
72
  context "on eq with placeholder" do
57
73
  let(:pred){ p.eq(:x, p.placeholder) }
58
74
 
59
- it{ should eq([ pred, p.tautology ]) }
75
+ it {
76
+ expect(subject).to eq([ pred, p.tautology ])
77
+ }
60
78
  end
61
79
 
62
80
  context "on in with placeholder" do
63
81
  let(:pred){ p.in(:x, p.placeholder) }
64
82
 
65
- it{ should eq([ pred, p.tautology ]) }
83
+ it {
84
+ expect(subject).to eq([ pred, p.tautology ])
85
+ }
66
86
  end
67
87
 
68
88
  context "on match (included)" do
69
89
  let(:pred){ p.match(:x, "London") }
70
90
 
71
- it{ should eq([ pred, p.tautology ]) }
91
+ it {
92
+ expect(subject).to eq([ pred, p.tautology ])
93
+ }
72
94
  end
73
95
 
74
96
  context "on match (excluded)" do
75
97
  let(:pred){ p.match(:y, "London") }
76
98
 
77
- it{ should eq([ p.tautology, pred ]) }
99
+ it {
100
+ expect(subject).to eq([ p.tautology, pred ])
101
+ }
78
102
  end
79
103
 
80
104
  context "on match (included on right)" do
81
105
  let(:pred){ p.match(:y, :x) }
82
106
 
83
- it{ should eq([ pred, p.tautology ]) }
107
+ it {
108
+ expect(subject).to eq([ pred, p.tautology ])
109
+ }
84
110
  end
85
111
 
86
112
  context "on intersect" do
87
113
  let(:pred){ p.intersect(:x, [1, 2]) }
88
114
 
89
- it{ should eq([ pred, p.tautology ]) }
115
+ it {
116
+ expect(subject).to eq([ pred, p.tautology ])
117
+ }
90
118
  end
91
119
 
92
120
  context "on subset" do
93
121
  let(:pred){ p.subset(:x, [1, 2]) }
94
122
 
95
- it{ should eq([ pred, p.tautology ]) }
123
+ it {
124
+ expect(subject).to eq([ pred, p.tautology ])
125
+ }
96
126
  end
97
127
 
98
128
  context "on superset" do
99
129
  let(:pred){ p.superset(:x, [1, 2]) }
100
130
 
101
- it{ should eq([ pred, p.tautology ]) }
131
+ it {
132
+ expect(subject).to eq([ pred, p.tautology ])
133
+ }
102
134
  end
103
135
 
104
136
  end
@@ -0,0 +1,277 @@
1
+ require 'spec_helper'
2
+ class Predicate
3
+ describe Predicate, "assert!" do
4
+
5
+ describe "eq" do
6
+ let(:predicate) {
7
+ Predicate.eq(:x, 2)
8
+ }
9
+
10
+ subject{
11
+ predicate.assert!(input)
12
+ }
13
+
14
+ context "when ok" do
15
+ let(:input){
16
+ { x: 2 }
17
+ }
18
+ it 'works and returns 2' do
19
+ expect(subject).to eql(2)
20
+ end
21
+ end
22
+
23
+ context "when ko" do
24
+ let(:input){
25
+ { x: 3 }
26
+ }
27
+ it 'works and throws' do
28
+ expect{
29
+ subject
30
+ }.to raise_error(Minitest::Assertion, /Expected: 3\s+Actual: 2/)
31
+ end
32
+ end
33
+ end
34
+
35
+ describe "gt" do
36
+ let(:predicate) {
37
+ Predicate.gt(:x, 2)
38
+ }
39
+
40
+ subject{
41
+ predicate.assert!(input)
42
+ }
43
+
44
+ context "when ok" do
45
+ let(:input){
46
+ { x: 3 }
47
+ }
48
+ it 'works and returns 3' do
49
+ expect(subject).to eql(3)
50
+ end
51
+ end
52
+
53
+ context "when ko" do
54
+ let(:input){
55
+ { x: 2 }
56
+ }
57
+ it 'works and throws' do
58
+ expect{
59
+ subject
60
+ }.to raise_error(Minitest::Assertion, /Expected 2 to be > 2/)
61
+ end
62
+ end
63
+ end
64
+
65
+ describe "gte" do
66
+ let(:predicate) {
67
+ Predicate.gte(:x, 2)
68
+ }
69
+
70
+ subject{
71
+ predicate.assert!(input)
72
+ }
73
+
74
+ context "when ok" do
75
+ let(:input){
76
+ { x: 2 }
77
+ }
78
+ it 'works and returns 2' do
79
+ expect(subject).to eql(2)
80
+ end
81
+ end
82
+
83
+ context "when ko" do
84
+ let(:input){
85
+ { x: 1 }
86
+ }
87
+ it 'works and throws' do
88
+ expect{
89
+ subject
90
+ }.to raise_error(Minitest::Assertion, /Expected 1 to be >= 2/)
91
+ end
92
+ end
93
+ end
94
+
95
+ describe "lt" do
96
+ let(:predicate) {
97
+ Predicate.lt(:x, 2)
98
+ }
99
+
100
+ subject{
101
+ predicate.assert!(input)
102
+ }
103
+
104
+ context "when ok" do
105
+ let(:input){
106
+ { x: 1 }
107
+ }
108
+ it 'works and returns 1' do
109
+ expect(subject).to eql(1)
110
+ end
111
+ end
112
+
113
+ context "when ko" do
114
+ let(:input){
115
+ { x: 2 }
116
+ }
117
+ it 'works and throws' do
118
+ expect{
119
+ subject
120
+ }.to raise_error(Minitest::Assertion, /Expected 2 to be < 2/)
121
+ end
122
+ end
123
+ end
124
+
125
+ describe "lte" do
126
+ let(:predicate) {
127
+ Predicate.lte(:x, 2)
128
+ }
129
+
130
+ subject{
131
+ predicate.assert!(input)
132
+ }
133
+
134
+ context "when ok" do
135
+ let(:input){
136
+ { x: 2 }
137
+ }
138
+ it 'works and returns 2' do
139
+ expect(subject).to eql(2)
140
+ end
141
+ end
142
+
143
+ context "when ko" do
144
+ let(:input){
145
+ { x: 3 }
146
+ }
147
+ it 'works and throws' do
148
+ expect{
149
+ subject
150
+ }.to raise_error(Minitest::Assertion, /Expected 3 to be <= 2/)
151
+ end
152
+ end
153
+ end
154
+
155
+ describe "neq" do
156
+ let(:predicate) {
157
+ Predicate.neq(:x, 2)
158
+ }
159
+
160
+ subject{
161
+ predicate.assert!(input)
162
+ }
163
+
164
+ context "when ok" do
165
+ let(:input){
166
+ { x: 3 }
167
+ }
168
+ it 'works and returns 3' do
169
+ expect(subject).to eql(3)
170
+ end
171
+ end
172
+
173
+ context "when ko" do
174
+ let(:input){
175
+ { x: 2 }
176
+ }
177
+ it 'works and throws' do
178
+ expect{
179
+ subject
180
+ }.to raise_error(Minitest::Assertion, /Expected 2 to not be equal to 2./)
181
+ end
182
+ end
183
+ end
184
+
185
+ describe "and" do
186
+ let(:predicate) {
187
+ Predicate.eq(:x, 2) & Predicate.eq(:y, 2)
188
+ }
189
+
190
+ subject{
191
+ predicate.assert!(input)
192
+ }
193
+
194
+ context "when ok" do
195
+ let(:input){
196
+ { x: 2, y: 2 }
197
+ }
198
+ it 'works and returns true' do
199
+ expect(subject).to eql(true)
200
+ end
201
+ end
202
+
203
+ context "when ko" do
204
+ let(:input){
205
+ { x: 2, y: 3 }
206
+ }
207
+ it 'works and throws' do
208
+ expect{
209
+ subject
210
+ }.to raise_error(Minitest::Assertion, /Expected: 3\n Actual: 2/)
211
+ end
212
+ end
213
+ end
214
+
215
+ describe "empty" do
216
+ let(:predicate) {
217
+ Predicate.empty(:x)
218
+ }
219
+
220
+ subject{
221
+ predicate.assert!(input)
222
+ }
223
+
224
+ context "when ok" do
225
+ let(:input){
226
+ { x: [] }
227
+ }
228
+ it 'works and returns true' do
229
+ expect(subject).to eql([])
230
+ end
231
+ end
232
+
233
+ context "when ko" do
234
+ let(:input){
235
+ { x: [2] }
236
+ }
237
+ it 'works and throws' do
238
+ expect{
239
+ subject
240
+ }.to raise_error(Minitest::Assertion, /Expected \[2\] to be empty/)
241
+ end
242
+ end
243
+ end
244
+
245
+ describe "in" do
246
+ let(:predicate) {
247
+ Predicate.in(:x, [2, 3, 4])
248
+ }
249
+
250
+ subject{
251
+ predicate.assert!(input)
252
+ }
253
+
254
+ context "when ok" do
255
+ let(:input){
256
+ { x: 3 }
257
+ }
258
+ it 'works and returns 3' do
259
+ expect(subject).to eql(3)
260
+ end
261
+ end
262
+
263
+ context "when ko" do
264
+ let(:input){
265
+ { x: 8 }
266
+ }
267
+ it 'works and throws' do
268
+ expect{
269
+ subject
270
+ }.to raise_error(Minitest::Assertion, /Expected \[2, 3, 4\] to include 8/)
271
+ end
272
+ end
273
+ end
274
+
275
+ end
276
+ end
277
+
@@ -8,73 +8,97 @@ class Predicate
8
8
  context "on tautology" do
9
9
  let(:pred){ p.tautology }
10
10
 
11
- it{ should eq({}) }
11
+ it {
12
+ expect(subject).to eq({})
13
+ }
12
14
  end
13
15
 
14
16
  context "on contradiction" do
15
17
  let(:pred){ p.contradiction }
16
18
 
17
- it{ should eq({ nil => pred }) }
19
+ it {
20
+ expect(subject).to eq({ nil => pred })
21
+ }
18
22
  end
19
23
 
20
24
  context "on identifier" do
21
25
  let(:pred){ p.identifier(:x) }
22
26
 
23
- it{ should eq({ x: pred }) }
27
+ it {
28
+ expect(subject).to eq({ x: pred })
29
+ }
24
30
  end
25
31
 
26
32
  context "on not" do
27
33
  let(:pred){ p.not(:x) }
28
34
 
29
- it{ should eq({ x: pred }) }
35
+ it {
36
+ expect(subject).to eq({ x: pred })
37
+ }
30
38
  end
31
39
 
32
40
  context "on eq" do
33
41
  let(:pred){ p.eq(:x, 2) }
34
42
 
35
- it{ should eq({ x: pred }) }
43
+ it {
44
+ expect(subject).to eq({ x: pred })
45
+ }
36
46
  end
37
47
 
38
48
  context "on eq with placeholder" do
39
49
  let(:pred){ p.eq(:x, p.placeholder) }
40
50
 
41
- it{ should eq({ x: pred }) }
51
+ it {
52
+ expect(subject).to eq({ x: pred })
53
+ }
42
54
  end
43
55
 
44
56
  context "on in" do
45
57
  let(:pred){ p.in(:x, [2]) }
46
58
 
47
- it{ should eq({ x: pred }) }
59
+ it {
60
+ expect(subject).to eq({ x: pred })
61
+ }
48
62
  end
49
63
 
50
64
  context "on intersect" do
51
65
  let(:pred){ p.intersect(:x, [2]) }
52
66
 
53
- it{ should eq({ x: pred }) }
67
+ it {
68
+ expect(subject).to eq({ x: pred })
69
+ }
54
70
  end
55
71
 
56
72
  context "on subset" do
57
73
  let(:pred){ p.subset(:x, [2]) }
58
74
 
59
- it{ should eq({ x: pred }) }
75
+ it {
76
+ expect(subject).to eq({ x: pred })
77
+ }
60
78
  end
61
79
 
62
80
  context "on superset" do
63
81
  let(:pred){ p.superset(:x, [2]) }
64
82
 
65
- it{ should eq({ x: pred }) }
83
+ it {
84
+ expect(subject).to eq({ x: pred })
85
+ }
66
86
  end
67
87
 
68
88
  context "on match" do
69
89
  let(:pred){ p.match(:x, "London") }
70
90
 
71
- it{ should eq({ x: pred }) }
91
+ it {
92
+ expect(subject).to eq({ x: pred })
93
+ }
72
94
  end
73
95
 
74
96
  context "on match with two identifiers" do
75
97
  let(:pred){ p.match(:x, :y) }
76
98
 
77
- it{ should eq({ nil => pred }) }
99
+ it {
100
+ expect(subject).to eq({ nil => pred })
101
+ }
78
102
  end
79
103
 
80
104
  end
@@ -7,19 +7,23 @@ class Predicate
7
7
  subject{ left & right }
8
8
 
9
9
  before do
10
- subject.should be_a(Predicate)
10
+ expect(subject).to be_a(Predicate)
11
11
  end
12
12
 
13
13
  context 'with itself' do
14
14
  let(:right){ left }
15
15
 
16
- it{ should be(left) }
16
+ it {
17
+ expect(subject).to be(left)
18
+ }
17
19
  end
18
20
 
19
21
  context 'with the same expression' do
20
22
  let(:right){ Predicate.coerce(x: 2) }
21
23
 
22
- it{ should be(left) }
24
+ it {
25
+ expect(subject).to be(left)
26
+ }
23
27
  end
24
28
 
25
29
  context 'with tautology' do