factbase 0.14.7 → 0.15.1

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 (90) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile.lock +5 -5
  3. data/README.md +6 -12
  4. data/factbase.gemspec +4 -4
  5. data/lib/factbase/fact.rb +1 -1
  6. data/lib/factbase/fact_as_yaml.rb +10 -1
  7. data/lib/factbase/indexed/indexed_term.rb +6 -1
  8. data/lib/factbase/terms/ordering.rb +17 -8
  9. data/lib/factbase/version.rb +1 -1
  10. metadata +8 -88
  11. data/.0pdd.yml +0 -8
  12. data/.gitattributes +0 -7
  13. data/.github/publish-benchmark.sh +0 -24
  14. data/.github/workflows/actionlint.yml +0 -25
  15. data/.github/workflows/benchmark.yml +0 -36
  16. data/.github/workflows/codecov.yml +0 -27
  17. data/.github/workflows/copyrights.yml +0 -19
  18. data/.github/workflows/markdown-lint.yml +0 -23
  19. data/.github/workflows/pdd.yml +0 -19
  20. data/.github/workflows/rake.yml +0 -28
  21. data/.github/workflows/reuse.yml +0 -19
  22. data/.github/workflows/typos.yml +0 -19
  23. data/.github/workflows/xcop.yml +0 -19
  24. data/.github/workflows/yamllint.yml +0 -19
  25. data/.gitignore +0 -11
  26. data/.pdd +0 -7
  27. data/.rubocop.yml +0 -51
  28. data/.rultor.yml +0 -27
  29. data/benchmark/bench_factbase.rb +0 -61
  30. data/benchmark/bench_large_query.rb +0 -128
  31. data/benchmark/bench_query.rb +0 -57
  32. data/benchmark/bench_taped.rb +0 -33
  33. data/fixtures/stories/agg.yml +0 -17
  34. data/fixtures/stories/always.yml +0 -16
  35. data/fixtures/stories/and.yml +0 -19
  36. data/fixtures/stories/as.yml +0 -16
  37. data/fixtures/stories/count.yml +0 -18
  38. data/fixtures/stories/empty.yml +0 -23
  39. data/fixtures/stories/eq.yml +0 -30
  40. data/fixtures/stories/gt.yml +0 -18
  41. data/fixtures/stories/join.yml +0 -22
  42. data/fixtures/stories/max.yml +0 -14
  43. data/fixtures/stories/min.yml +0 -14
  44. data/fixtures/stories/nth.yml +0 -14
  45. data/fixtures/stories/one.yml +0 -14
  46. data/fixtures/stories/or.yml +0 -18
  47. data/fixtures/stories/sprintf.yml +0 -12
  48. data/fixtures/stories/sum.yml +0 -14
  49. data/fixtures/stories/unique.yml +0 -16
  50. data/renovate.json +0 -6
  51. data/test/factbase/cached/test_cached_factbase.rb +0 -44
  52. data/test/factbase/cached/test_cached_query.rb +0 -100
  53. data/test/factbase/indexed/test_indexed_fact.rb +0 -23
  54. data/test/factbase/indexed/test_indexed_factbase.rb +0 -96
  55. data/test/factbase/indexed/test_indexed_query.rb +0 -208
  56. data/test/factbase/indexed/test_indexed_term.rb +0 -140
  57. data/test/factbase/sync/test_sync_factbase.rb +0 -22
  58. data/test/factbase/sync/test_sync_query.rb +0 -30
  59. data/test/factbase/terms/test_aggregates.rb +0 -63
  60. data/test/factbase/terms/test_aliases.rb +0 -58
  61. data/test/factbase/terms/test_casting.rb +0 -33
  62. data/test/factbase/terms/test_debug.rb +0 -111
  63. data/test/factbase/terms/test_defn.rb +0 -48
  64. data/test/factbase/terms/test_logical.rb +0 -57
  65. data/test/factbase/terms/test_math.rb +0 -122
  66. data/test/factbase/terms/test_meta.rb +0 -70
  67. data/test/factbase/terms/test_ordering.rb +0 -28
  68. data/test/factbase/terms/test_strings.rb +0 -36
  69. data/test/factbase/terms/test_system.rb +0 -31
  70. data/test/factbase/test_accum.rb +0 -74
  71. data/test/factbase/test_churn.rb +0 -41
  72. data/test/factbase/test_fact.rb +0 -108
  73. data/test/factbase/test_fact_as_yaml.rb +0 -77
  74. data/test/factbase/test_flatten.rb +0 -28
  75. data/test/factbase/test_impatient.rb +0 -176
  76. data/test/factbase/test_inv.rb +0 -44
  77. data/test/factbase/test_logged.rb +0 -155
  78. data/test/factbase/test_pre.rb +0 -35
  79. data/test/factbase/test_query.rb +0 -445
  80. data/test/factbase/test_rules.rb +0 -113
  81. data/test/factbase/test_syntax.rb +0 -166
  82. data/test/factbase/test_tallied.rb +0 -81
  83. data/test/factbase/test_taped.rb +0 -72
  84. data/test/factbase/test_tee.rb +0 -85
  85. data/test/factbase/test_term.rb +0 -87
  86. data/test/factbase/test_to_json.rb +0 -35
  87. data/test/factbase/test_to_xml.rb +0 -89
  88. data/test/factbase/test_to_yaml.rb +0 -39
  89. data/test/test__helper.rb +0 -41
  90. data/test/test_factbase.rb +0 -509
@@ -1,155 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- # SPDX-FileCopyrightText: Copyright (c) 2024-2025 Yegor Bugayenko
4
- # SPDX-License-Identifier: MIT
5
-
6
- require_relative '../test__helper'
7
- require 'loog'
8
- require_relative '../../lib/factbase'
9
- require_relative '../../lib/factbase/logged'
10
- require_relative '../../lib/factbase/cached/cached_factbase'
11
-
12
- # Test.
13
- # Author:: Yegor Bugayenko (yegor256@gmail.com)
14
- # Copyright:: Copyright (c) 2024-2025 Yegor Bugayenko
15
- # License:: MIT
16
- class TestLogged < Factbase::Test
17
- def test_simple_setting
18
- fb = Factbase::Logged.new(Factbase.new, Loog::NULL)
19
- fb.insert
20
- fb.insert.bar = 3
21
- found = 0
22
- fb.query('(exists bar)').each do |f|
23
- assert_predicate(f.bar, :positive?)
24
- f.foo = 42
25
- assert_equal(42, f.foo)
26
- found += 1
27
- end
28
- assert_equal(1, found)
29
- assert_equal(2, fb.size)
30
- end
31
-
32
- def test_reading_one
33
- fb = Factbase::Logged.new(Factbase.new, Loog::NULL)
34
- fb.insert
35
- fb.insert.bar = 42
36
- assert_equal(1, fb.query('(agg (exists bar) (count))').one)
37
- assert_equal([42], fb.query('(agg (exists bar) (first bar))').one)
38
- end
39
-
40
- def test_avoid_inner_logging
41
- buf = Loog::Buffer.new
42
- fb = Factbase.new
43
- fb.insert
44
- fb.insert.bar = 42
45
- fb = Factbase::Logged.new(Factbase::CachedFactbase.new(fb), buf)
46
- fb.query('(agg (exists bar) (count))').one
47
- fb.query('(join "foo<=bar" (exists bar))').each.to_a
48
- refute_includes(buf.to_s, '\'(count)\'')
49
- refute_includes(buf.to_s, '\'(exists bar)\'')
50
- end
51
-
52
- def test_with_txn
53
- log = Loog::Buffer.new
54
- fb = Factbase::Logged.new(Factbase.new, log)
55
- assert(
56
- fb.txn do |fbt|
57
- fbt.insert.foo = 42
58
- end
59
- )
60
- assert_equal(1, fb.size)
61
- assert_includes(log.to_s, 'touched', log)
62
- end
63
-
64
- def test_with_slow_txn
65
- log = Loog::Buffer.new
66
- fb = Factbase::Logged.new(Factbase.new, log, time_tolerate: 0.1)
67
- fb.txn { sleep 0.4 }
68
- assert_includes(log.to_s, '(slow!)', log)
69
- end
70
-
71
- def test_with_txn_rollback
72
- log = Loog::Buffer.new
73
- fb = Factbase::Logged.new(Factbase.new, log)
74
- assert_equal(0, fb.txn { raise Factbase::Rollback })
75
- assert_equal(0, fb.size)
76
- assert_includes(log.to_s, 'rolled back', log)
77
- refute_includes(log.to_s, 'didn\'t touch', log)
78
- end
79
-
80
- def test_with_modifying_txn
81
- log = Loog::Buffer.new
82
- fb = Factbase::Logged.new(Factbase.new, log)
83
- fb.insert.foo = 1
84
- assert_equal(0, fb.txn { |fbt| fbt.query('(always)').each.to_a }.to_i, log)
85
- assert_equal(1, fb.txn { |fbt| fbt.query('(always)').each.to_a[0].foo = 42 }.to_i)
86
- assert_includes(log.to_s, 'touched', log)
87
- end
88
-
89
- def test_with_empty_txn
90
- log = Loog::Buffer.new
91
- fb = Factbase::Logged.new(Factbase.new, log)
92
- assert_equal(0, fb.txn { |fbt| fbt.query('(always)').each.to_a }.to_i)
93
- assert_includes(log.to_s, 'touched', log)
94
- end
95
-
96
- def test_returns_int
97
- fb = Factbase.new
98
- fb.insert
99
- fb.insert
100
- assert_equal(2, Factbase::Logged.new(fb, Loog::NULL).query('(always)').each(&:to_s))
101
- end
102
-
103
- def test_returns_int_when_empty
104
- fb = Factbase.new
105
- assert_equal(0, Factbase::Logged.new(fb, Loog::NULL).query('(always)').each(&:to_s))
106
- end
107
-
108
- def test_returns_to_s_correctly
109
- fb = Factbase.new
110
- q = '(always)'
111
- assert_equal(q, fb.query(q).to_s)
112
- end
113
-
114
- def test_logs_when_enumerator
115
- fb = Factbase::Logged.new(Factbase.new, Loog::NULL)
116
- assert_equal(0, fb.query('(always)').each.to_a.size)
117
- fb.insert
118
- assert_equal(1, fb.query('(always)').each.to_a.size)
119
- end
120
-
121
- def test_proper_logging
122
- log = Loog::Buffer.new
123
- fb = Factbase::Logged.new(Factbase.new, log)
124
- fb.insert
125
- fb.insert.bar = 3
126
- fb.insert
127
- fb.insert.str =
128
- "Он поскорей звонит. Вбегает
129
- К нему слуга француз Гильо,
130
- Халат и туфли предлагает
131
- И подает ему белье.
132
- Спешит Онегин одеваться,
133
- Слуге велит приготовляться
134
- С ним вместе ехать и с собой
135
- Взять также ящик боевой.
136
- Готовы санки беговые.
137
- Он сел, на мельницу летит.
138
- Примчались. Он слуге велит
139
- Лепажа стволы роковые
140
- Нести за ним, а лошадям
141
- Отъехать в поле к двум дубкам."
142
- fb.query('(exists bar)').each(&:to_s)
143
- fb.query('(not (exists bar))').delete!
144
- [
145
- 'Inserted new fact #1',
146
- 'Inserted new fact #2',
147
- 'Set \'bar\' to 3 (Integer)',
148
- 'Set \'str\' to "Он поскорей звонит. Вбегает\n ... Отъехать в поле к двум дубкам." (String)',
149
- 'Found 1/4 fact(s) by \'(exists bar)\'',
150
- 'Deleted 3 fact(s) out of 4 by \'(not (exists bar))\''
151
- ].each do |s|
152
- assert_includes(log.to_s, s, "#{log}\n")
153
- end
154
- end
155
- end
@@ -1,35 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- # SPDX-FileCopyrightText: Copyright (c) 2024-2025 Yegor Bugayenko
4
- # SPDX-License-Identifier: MIT
5
-
6
- require_relative '../test__helper'
7
- require 'loog'
8
- require_relative '../../lib/factbase/pre'
9
-
10
- # Test.
11
- # Author:: Yegor Bugayenko (yegor256@gmail.com)
12
- # Copyright:: Copyright (c) 2024-2025 Yegor Bugayenko
13
- # License:: MIT
14
- class TestPre < Factbase::Test
15
- def test_simple_setting
16
- fb = Factbase::Pre.new(Factbase.new) { |f| f.foo = 42 }
17
- f = fb.insert
18
- assert_equal(42, f.foo)
19
- assert_equal(1, fb.query('(always)').each.to_a.size)
20
- end
21
-
22
- def test_in_transaction
23
- fb =
24
- Factbase::Pre.new(Factbase.new) do |f, fbt|
25
- f.total = fbt.size
26
- end
27
- fb.txn do |fbt|
28
- fbt.insert
29
- fbt.insert
30
- end
31
- arr = fb.query('(always)').each.to_a
32
- assert_equal(1, arr[0].total)
33
- assert_equal(2, arr[1].total)
34
- end
35
- end
@@ -1,445 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- # SPDX-FileCopyrightText: Copyright (c) 2024-2025 Yegor Bugayenko
4
- # SPDX-License-Identifier: MIT
5
-
6
- require_relative '../test__helper'
7
- require 'loog'
8
- require 'time'
9
- require_relative '../../lib/factbase'
10
- require_relative '../../lib/factbase/query'
11
- require_relative '../../lib/factbase/logged'
12
- require_relative '../../lib/factbase/pre'
13
- require_relative '../../lib/factbase/impatient'
14
- require_relative '../../lib/factbase/inv'
15
- require_relative '../../lib/factbase/rules'
16
- require_relative '../../lib/factbase/tallied'
17
- require_relative '../../lib/factbase/cached/cached_factbase'
18
- require_relative '../../lib/factbase/indexed/indexed_factbase'
19
- require_relative '../../lib/factbase/sync/sync_factbase'
20
-
21
- # Query test.
22
- # Author:: Yegor Bugayenko (yegor256@gmail.com)
23
- # Copyright:: Copyright (c) 2024-2025 Yegor Bugayenko
24
- # License:: MIT
25
- class TestQuery < Factbase::Test
26
- def test_stories
27
- with_factbases do |badge, fb|
28
- Dir[File.join(__dir__, '../../fixtures/stories/**/*.yml')].each do |fixture|
29
- base = File.basename(fixture)
30
- story = YAML.load_file(fixture)
31
- 2.times do
32
- fb.query('(always)').delete!
33
- story['facts'].each do |y|
34
- f = fb.insert
35
- y.each do |k, vv|
36
- vv = [vv] unless vv.is_a?(Array)
37
- vv.each do |v|
38
- f.send(:"#{k}=", v)
39
- end
40
- end
41
- end
42
- story['queries'].each do |q|
43
- qry = q['query']
44
- if q['size']
45
- size = q['size']
46
- assert_equal(size, fb.query(qry).each.to_a.size, "#{base}: #{qry} at #{badge}")
47
- fb.txn do |fbt|
48
- facts = fbt.query(qry).each.to_a
49
- assert_equal(size, facts.size, "#{base}: #{qry} at #{badge} (in txn)")
50
- facts.each do |fact|
51
- refute_empty(fact.all_properties)
52
- refute_nil(fact.to_s)
53
- end
54
- end
55
- else
56
- ret = q['one']
57
- assert_equal(ret, fb.query(qry).one, "#{base}: #{qry} at #{badge}")
58
- fb.txn do |fbt|
59
- assert_equal(ret, fbt.query(qry).one, "#{base}: #{qry} at #{badge} (in txn)")
60
- end
61
- end
62
- end
63
- end
64
- end
65
- end
66
- end
67
-
68
- def test_simple_parsing
69
- maps = []
70
- maps << { 'foo' => [42] }
71
- q = Factbase::Query.new(maps, '(eq foo 42)', Factbase.new)
72
- assert_equal(
73
- 1,
74
- q.each do |f|
75
- assert_equal(42, f.foo)
76
- end
77
- )
78
- end
79
-
80
- def test_complex_parsing
81
- queries = {
82
- '(eq num 444)' => 0,
83
- '(eq hi 4)' => 1,
84
- '(eq time 0)' => 0,
85
- '(gt num 60)' => 1,
86
- '(gt hi 3)' => 1,
87
- "(and (lt pi 100) \n\n (gt num 1000))" => 0,
88
- '(exists pi)' => 1,
89
- '(eq pi +3.14)' => 1,
90
- '(not (exists hello))' => 3,
91
- '(eq "Integer" (type num))' => 2,
92
- '(eq "Integer" (type hi))' => 1,
93
- '(when (eq num 0) (exists time))' => 2,
94
- '(unique num)' => 2,
95
- '(unique name)' => 2,
96
- '(unique pi)' => 1,
97
- '(many num)' => 1,
98
- '(one num)' => 2,
99
- '(nil (agg (exists hello) (min num)))' => 3,
100
- '(gt num (minus 1 (either (at 0 (prev num)) 0)))' => 3,
101
- '(and (not (many num)) (eq num (plus 21 +21)))' => 1,
102
- '(and (not (many num)) (eq num (minus -100 -142)))' => 1,
103
- '(and (one num) (eq num (times 7 6)))' => 1,
104
- '(and (one pi) (eq pi (div -6.28 -2)))' => 1,
105
- '(gt (size num) 2)' => 1,
106
- '(matches name "^[a-z]+$")' => 1,
107
- '(matches nome "^Walter$")' => 1,
108
- '(lt (size num) 2)' => 2,
109
- '(eq (size _hello) 0)' => 3,
110
- '(eq num pi)' => 0,
111
- '(absent time)' => 2,
112
- '(eq pi (agg (eq num 0) (sum pi)))' => 1,
113
- '(eq num (agg (exists oops) (count)))' => 2,
114
- '(lt num (agg (eq num 0) (max pi)))' => 2,
115
- '(eq time (min time))' => 1,
116
- '(and (absent time) (exists pi))' => 1,
117
- "(and (exists time) (not (\t\texists pi)))" => 1,
118
- '(undef something)' => 3,
119
- "(or (eq num +66) (lt time #{(Time.now - 200).utc.iso8601}))" => 1,
120
- '(eq 3 (agg (eq num $num) (count)))' => 1,
121
- '(and (eq num 42) (not (empty (eq name "Jeff"))))' => 2,
122
- '(and (eq num 42) (empty (eq x $name)))' => 2,
123
- '(and (eq num 42) (not (empty (eq name $name))))' => 2
124
- }
125
- maps = [
126
- { 'num' => [42], 'name' => ['Jeff'] },
127
- { 'num' => [42, 66, 0], 'pi' => [3.14], 'name' => ['peter'] },
128
- { 'num' => [0], 'time' => [Time.now - 100], 'hi' => [4], 'nome' => ['Walter'] }
129
- ]
130
- 3.times do |cycle|
131
- with_factbases(maps) do |badge, fb|
132
- queries.each do |q, r|
133
- assert_equal(r, fb.query(q).each.to_a.size, "#{q} in #{badge} (cycle ##{cycle})")
134
- fb.txn do |fbt|
135
- assert_equal(r, fbt.query(q).each.to_a.size, "#{q} in #{badge} (txn, cycle ##{cycle})")
136
- end
137
- end
138
- end
139
- end
140
- end
141
-
142
- def test_simple_parsing_with_time
143
- maps = []
144
- now = Time.now.utc
145
- maps << { 'foo' => [now] }
146
- q = Factbase::Query.new(maps, "(eq foo #{now.iso8601})", Factbase.new)
147
- assert_equal(1, q.each.to_a.size)
148
- end
149
-
150
- def test_simple_deleting
151
- maps = [
152
- { 'foo' => [42] },
153
- { 'bar' => [4, 5] },
154
- { 'bar' => [5] }
155
- ]
156
- q = Factbase::Query.new(maps, '(eq bar 5)', Factbase.new)
157
- assert_equal(2, q.delete!)
158
- assert_equal(1, maps.size)
159
- end
160
-
161
- def test_reading_one
162
- maps = [
163
- { 'foo' => [42], 'hello' => [4] },
164
- { 'bar' => [4, 5] }
165
- ]
166
- with_factbases(maps) do |badge, fb|
167
- {
168
- '(agg (and (eq foo 42) (eq hello $v)) (min foo))' => 42,
169
- '(agg (or (eq foo 42) (eq bar 4)) (min foo))' => 42,
170
- '(agg (exists foo) (first foo))' => [42],
171
- '(agg (exists z) (first z))' => nil,
172
- '(agg (always) (count))' => 2,
173
- '(agg (eq bar $v) (count))' => 1,
174
- '(agg (eq foo 42) (min foo))' => 42,
175
- '(agg (and (eq foo 42)) (min foo))' => 42,
176
- '(agg (eq z 40) (count))' => 0
177
- }.each do |q, expected|
178
- result = fb.query(q).one(fb, 'v' => 4)
179
- if expected.nil?
180
- assert_nil(result, "#{q} -> nil in #{badge}")
181
- else
182
- assert_equal(expected, result, "#{q} -> #{expected} in #{badge}")
183
- end
184
- end
185
- end
186
- end
187
-
188
- def test_deleting_nothing
189
- maps = [
190
- { 'foo' => [42] },
191
- { 'bar' => [4, 5] },
192
- { 'bar' => [5] }
193
- ]
194
- with_factbases(maps) do |badge, fb|
195
- q = fb.query('(never)')
196
- assert_equal(0, q.delete!, "#{q} in #{badge}")
197
- assert_equal(3, maps.size, "#{q} in #{badge}")
198
- end
199
- end
200
-
201
- def test_finds_with_substitution
202
- maps = [{ 'foo' => [42] }, { 'bar' => [7] }, { 'foo' => [666] }]
203
- with_factbases(maps) do |badge, fb|
204
- assert_equal(0, fb.query('(eq 2 (agg (eq foo $foo) (count)))').each.to_a.size, "with #{badge}")
205
- fb.txn do |fbt|
206
- assert_equal(0, fbt.query('(eq 2 (agg (eq foo $foo) (count)))').each.to_a.size, "with #{badge} (txn)")
207
- end
208
- end
209
- end
210
-
211
- def test_scans_and_inserts
212
- with_factbases do |_, fb|
213
- fb.insert.foo = 42
214
- before = fb.size
215
- more = 0
216
- fb.query('(exists foo)').each do |f|
217
- fb.insert.bar = f.foo
218
- more += 1
219
- end
220
- assert_equal(before + more, fb.size)
221
- end
222
- end
223
-
224
- def test_scans_and_inserts_in_txn
225
- with_factbases do |_, fb|
226
- fb.insert.foo = 42
227
- before = fb.size
228
- more = 0
229
- fb.query('(exists foo)').each do |f|
230
- fb.txn do |fbt|
231
- fbt.insert.bar = f.foo
232
- more += 1
233
- end
234
- end
235
- assert_equal(before + more, fb.size)
236
- end
237
- end
238
-
239
- def test_scans_and_inserts_in_queried_txn
240
- with_factbases do |_, fb|
241
- fb.insert.foo = 42
242
- before = fb.size
243
- more = 0
244
- fb.txn do |fbt|
245
- fbt.query('(exists foo)').each do |f|
246
- fbt.insert.bar = f.foo
247
- more += 1
248
- end
249
- end
250
- assert_equal(before + more, fb.size)
251
- end
252
- end
253
-
254
- def test_scans_and_appends_in_queried_txn
255
- with_factbases do |badge, fb|
256
- fb.insert.foo = 42
257
- fb.txn do |fbt|
258
- fbt.query('(exists foo)').each do |f|
259
- f.bar = 33
260
- end
261
- refute_empty(fbt.query('(exists bar)').each.to_a, "in #{badge}")
262
- end
263
- refute_empty(fb.query('(exists bar)').each.to_a, "in #{badge}")
264
- assert_empty(fb.query('(and (exists foo) (not (exists bar)))').each.to_a, "in #{badge}")
265
- end
266
- end
267
-
268
- def test_turns_query_to_string
269
- with_factbases do |badge, fb|
270
- assert_equal('(always)', fb.query('(always)').to_s, "Fails with #{badge}")
271
- end
272
- end
273
-
274
- def test_to_array
275
- maps = []
276
- maps << { 'foo' => [42] }
277
- assert_equal(1, Factbase::Query.new(maps, '(eq foo 42)', Factbase.new).each.to_a.size)
278
- end
279
-
280
- def test_returns_int
281
- maps = []
282
- maps << { 'foo' => [1] }
283
- q = Factbase::Query.new(maps, '(eq foo 1)', Factbase.new)
284
- assert_equal(1, q.each(&:to_s))
285
- end
286
-
287
- def test_with_aliases
288
- maps = []
289
- maps << { 'foo' => [42] }
290
- assert_equal(45, Factbase::Query.new(maps, '(as bar (plus foo 3))', Factbase.new).each.to_a[0].bar)
291
- assert_equal(1, maps[0].size)
292
- end
293
-
294
- def test_with_params
295
- maps = [
296
- { 'foo' => [42] },
297
- { 'foo' => [17] }
298
- ]
299
- found = 0
300
- Factbase::Query.new(maps, '(eq foo $bar)', Factbase.new).each(Factbase.new, bar: [42]) do
301
- found += 1
302
- end
303
- assert_equal(1, found)
304
- assert_equal(1, Factbase::Query.new(maps, '(eq foo $bar)', Factbase.new).each(Factbase.new, bar: [42]).to_a.size)
305
- assert_equal(0, Factbase::Query.new(maps, '(eq foo $bar)', Factbase.new).each(Factbase.new, bar: [555]).to_a.size)
306
- end
307
-
308
- def test_with_nil_alias
309
- maps = [{ 'foo' => [42] }]
310
- assert_nil(Factbase::Query.new(maps, '(as bar (plus xxx 3))', Factbase.new).each.to_a[0]['bar'])
311
- end
312
-
313
- def test_get_all_properties
314
- maps = [{ 'foo' => [42] }]
315
- f = Factbase::Query.new(maps, '(always)', Factbase.new).each.to_a[0]
316
- assert_includes(f.all_properties, 'foo')
317
- end
318
-
319
- private
320
-
321
- def with_factbases(maps = [], &)
322
- {
323
- 'plain' => Factbase.new(maps),
324
- 'plain+impatient' => Factbase::Impatient.new(Factbase.new(maps)),
325
- 'pre+plain' => Factbase::Pre.new(Factbase.new(maps)) { nil },
326
- 'rules+plain' => Factbase::Rules.new(Factbase.new(maps), '(always)'),
327
- 'inv+plain' => Factbase::Inv.new(Factbase.new(maps)) { nil },
328
- 'sync+plain' => Factbase::SyncFactbase.new(Factbase.new(maps)),
329
- 'tallied+plain' => Factbase::Tallied.new(Factbase.new(maps)),
330
- 'indexed+plain' => Factbase::IndexedFactbase.new(Factbase.new(maps)),
331
- 'indexed+logged+plain' => Factbase::IndexedFactbase.new(
332
- Factbase::Logged.new(
333
- Factbase.new(maps),
334
- Loog::NULL
335
- )
336
- ),
337
- 'cached+plain' => Factbase::CachedFactbase.new(Factbase.new(maps)),
338
- 'cached+logged+plain' => Factbase::CachedFactbase.new(
339
- Factbase::Logged.new(
340
- Factbase.new(maps),
341
- Loog::NULL
342
- )
343
- ),
344
- 'logged+plain' => Factbase::Logged.new(Factbase.new(maps), Loog::NULL),
345
- 'indexed+cached+plain' => Factbase::IndexedFactbase.new(
346
- Factbase::CachedFactbase.new(Factbase.new(maps))
347
- ),
348
- 'indexed+cached+rules+plain' => Factbase::IndexedFactbase.new(
349
- Factbase::CachedFactbase.new(
350
- Factbase::Rules.new(
351
- Factbase.new(maps),
352
- '(always)',
353
- uid: '_id'
354
- )
355
- )
356
- ),
357
- 'cached+indexed+plain' => Factbase::CachedFactbase.new(
358
- Factbase::IndexedFactbase.new(Factbase.new(maps))
359
- ),
360
- 'indexed+indexed+plain' => Factbase::IndexedFactbase.new(
361
- Factbase::IndexedFactbase.new(Factbase.new(maps))
362
- ),
363
- 'cached+cached+cached+plain' => Factbase::CachedFactbase.new(
364
- Factbase::CachedFactbase.new(
365
- Factbase::CachedFactbase.new(
366
- Factbase.new(maps)
367
- )
368
- )
369
- ),
370
- 'tallied+pre+rules+inv+plain' => Factbase::Tallied.new(
371
- Factbase::Pre.new(
372
- Factbase::Rules.new(
373
- Factbase::Inv.new(
374
- Factbase.new(maps)
375
- ) { nil },
376
- '(always)'
377
- )
378
- ) { nil }
379
- ),
380
- 'sync+cached+indexed+plain' => Factbase::SyncFactbase.new(
381
- Factbase::CachedFactbase.new(
382
- Factbase::IndexedFactbase.new(
383
- Factbase.new(maps)
384
- )
385
- )
386
- ),
387
- 'sync+logged+plain' => Factbase::SyncFactbase.new(
388
- Factbase::Logged.new(
389
- Factbase.new(maps),
390
- Loog::NULL
391
- )
392
- ),
393
- 'sync+cached+indexed+logged+plain' => Factbase::SyncFactbase.new(
394
- Factbase::CachedFactbase.new(
395
- Factbase::IndexedFactbase.new(
396
- Factbase::Logged.new(
397
- Factbase.new(maps),
398
- Loog::NULL
399
- )
400
- )
401
- )
402
- ),
403
- 'sync+sync+sync+plain' => Factbase::SyncFactbase.new(
404
- Factbase::SyncFactbase.new(
405
- Factbase::SyncFactbase.new(
406
- Factbase::SyncFactbase.new(
407
- Factbase.new(maps)
408
- )
409
- )
410
- )
411
- ),
412
- 'logged+logged+logged+plain' => Factbase::SyncFactbase.new(
413
- Factbase::Logged.new(
414
- Factbase::Logged.new(
415
- Factbase::Logged.new(
416
- Factbase.new(maps),
417
- Loog::NULL
418
- ),
419
- Loog::NULL
420
- ),
421
- Loog::NULL
422
- )
423
- ),
424
- 'all+plain' => Factbase::Tallied.new(
425
- Factbase::Pre.new(
426
- Factbase::Rules.new(
427
- Factbase::Inv.new(
428
- Factbase::SyncFactbase.new(
429
- Factbase::CachedFactbase.new(
430
- Factbase::IndexedFactbase.new(
431
- Factbase::Logged.new(
432
- Factbase.new(maps),
433
- Loog::NULL
434
- )
435
- )
436
- )
437
- )
438
- ) { nil },
439
- '(always)'
440
- )
441
- ) { nil }
442
- )
443
- }.each(&)
444
- end
445
- end