factbase 0.7.5 → 0.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 (81) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +1 -1
  3. data/Gemfile +1 -1
  4. data/Gemfile.lock +3 -3
  5. data/README.md +24 -27
  6. data/REUSE.toml +7 -2
  7. data/Rakefile +8 -1
  8. data/benchmark/bench_factbase.rb +1 -1
  9. data/fixtures/stories/agg.yml +17 -0
  10. data/fixtures/stories/always.yml +16 -0
  11. data/fixtures/stories/as.yml +16 -0
  12. data/fixtures/stories/count.yml +18 -0
  13. data/fixtures/stories/eq.yml +30 -0
  14. data/fixtures/stories/gt.yml +18 -0
  15. data/fixtures/stories/join.yml +19 -0
  16. data/fixtures/stories/max.yml +14 -0
  17. data/fixtures/stories/min.yml +14 -0
  18. data/fixtures/stories/nth.yml +14 -0
  19. data/fixtures/stories/or.yml +18 -0
  20. data/fixtures/stories/sprintf.yml +12 -0
  21. data/fixtures/stories/sum.yml +14 -0
  22. data/lib/factbase/cached/cached_fact.rb +28 -0
  23. data/lib/factbase/cached/cached_factbase.rb +64 -0
  24. data/lib/factbase/cached/cached_query.rb +61 -0
  25. data/lib/factbase/cached/cached_term.rb +25 -0
  26. data/lib/factbase/fact.rb +13 -13
  27. data/lib/factbase/indexed/indexed_fact.rb +28 -0
  28. data/lib/factbase/indexed/indexed_factbase.rb +64 -0
  29. data/lib/factbase/indexed/indexed_query.rb +56 -0
  30. data/lib/factbase/indexed/indexed_term.rb +60 -0
  31. data/lib/factbase/light.rb +7 -6
  32. data/lib/factbase/logged.rb +70 -35
  33. data/lib/factbase/query.rb +29 -34
  34. data/lib/factbase/rules.rb +15 -14
  35. data/lib/factbase/sync/sync_factbase.rb +57 -0
  36. data/lib/factbase/sync/sync_query.rb +61 -0
  37. data/lib/factbase/syntax.rb +16 -26
  38. data/lib/factbase/tallied.rb +10 -9
  39. data/lib/factbase/taped.rb +8 -0
  40. data/lib/factbase/tee.rb +2 -0
  41. data/lib/factbase/term.rb +45 -17
  42. data/lib/factbase/terms/aggregates.rb +17 -15
  43. data/lib/factbase/terms/aliases.rb +4 -4
  44. data/lib/factbase/terms/casting.rb +8 -8
  45. data/lib/factbase/terms/debug.rb +2 -2
  46. data/lib/factbase/terms/defn.rb +3 -3
  47. data/lib/factbase/terms/logical.rb +53 -14
  48. data/lib/factbase/terms/math.rb +26 -26
  49. data/lib/factbase/terms/meta.rb +14 -14
  50. data/lib/factbase/terms/ordering.rb +4 -4
  51. data/lib/factbase/terms/strings.rb +8 -8
  52. data/lib/factbase/terms/system.rb +3 -3
  53. data/lib/factbase.rb +67 -55
  54. data/test/factbase/cached/test_cached_factbase.rb +22 -0
  55. data/test/factbase/cached/test_cached_query.rb +79 -0
  56. data/test/factbase/indexed/test_indexed_query.rb +175 -0
  57. data/test/factbase/sync/test_sync_query.rb +30 -0
  58. data/test/factbase/terms/test_aggregates.rb +5 -5
  59. data/test/factbase/terms/test_aliases.rb +7 -7
  60. data/test/factbase/terms/test_casting.rb +8 -8
  61. data/test/factbase/terms/test_debug.rb +6 -6
  62. data/test/factbase/terms/test_defn.rb +14 -14
  63. data/test/factbase/terms/test_logical.rb +17 -19
  64. data/test/factbase/terms/test_math.rb +63 -61
  65. data/test/factbase/terms/test_meta.rb +36 -36
  66. data/test/factbase/terms/test_ordering.rb +9 -9
  67. data/test/factbase/terms/test_strings.rb +10 -10
  68. data/test/factbase/terms/test_system.rb +6 -6
  69. data/test/factbase/test_accum.rb +5 -5
  70. data/test/factbase/test_fact.rb +12 -12
  71. data/test/factbase/test_logged.rb +7 -0
  72. data/test/factbase/test_query.rb +99 -37
  73. data/test/factbase/test_rules.rb +1 -1
  74. data/test/factbase/test_syntax.rb +24 -11
  75. data/test/factbase/test_tee.rb +8 -8
  76. data/test/factbase/test_term.rb +39 -30
  77. data/test/test__helper.rb +2 -2
  78. data/test/test_factbase.rb +6 -0
  79. metadata +29 -4
  80. data/lib/factbase/query_once.rb +0 -54
  81. data/lib/factbase/term_once.rb +0 -67
@@ -0,0 +1,175 @@
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_relative '../../../lib/factbase'
8
+ require_relative '../../../lib/factbase/cached/cached_factbase'
9
+ require_relative '../../../lib/factbase/indexed/indexed_factbase'
10
+
11
+ # Query test.
12
+ # Author:: Yegor Bugayenko (yegor256@gmail.com)
13
+ # Copyright:: Copyright (c) 2024-2025 Yegor Bugayenko
14
+ # License:: MIT
15
+ class TestIndexedQuery < Factbase::Test
16
+ def test_queries_many_times
17
+ fb = Factbase::IndexedFactbase.new(Factbase.new)
18
+ total = 5
19
+ total.times { fb.insert }
20
+ total.times do
21
+ assert_equal(5, fb.query('(always)').each.to_a.size)
22
+ end
23
+ end
24
+
25
+ def test_finds_by_eq
26
+ fb = Factbase::IndexedFactbase.new(Factbase.new)
27
+ fb.insert.foo = 42
28
+ fb.insert
29
+ 3.times do
30
+ assert_equal(1, fb.query('(eq foo 42)').each.to_a.size)
31
+ end
32
+ end
33
+
34
+ def test_finds_by_eq_with_symbol
35
+ fb = Factbase::IndexedFactbase.new(Factbase.new)
36
+ f = fb.insert
37
+ f.num = 256
38
+ f.num = 42
39
+ fb.insert.num = 42
40
+ fb.insert.num = 55
41
+ fb.insert
42
+ fb.insert
43
+ 3.times do
44
+ assert_equal(1, fb.query('(eq 1 (agg (eq num $num) (count)))').each.to_a.size)
45
+ end
46
+ end
47
+
48
+ def test_finds_by_eq_with_array
49
+ fb = Factbase::IndexedFactbase.new(Factbase.new)
50
+ f = fb.insert
51
+ f.foo = 33
52
+ f.foo = 42
53
+ f.foo = 1
54
+ 3.times do
55
+ assert_equal(1, fb.query('(eq foo 42)').each.to_a.size)
56
+ end
57
+ end
58
+
59
+ def test_finds_by_eq_with_agg
60
+ fb = Factbase::IndexedFactbase.new(Factbase.new)
61
+ fb.insert.foo = 42
62
+ fb.insert.foo = 33
63
+ fb.insert
64
+ 3.times do
65
+ assert_equal(1, fb.query('(eq foo (agg (exists foo) (max foo)))').each.to_a.size)
66
+ end
67
+ end
68
+
69
+ def test_finds_max_value
70
+ fb = Factbase::IndexedFactbase.new(Factbase.new)
71
+ fb.insert.foo = 42
72
+ fb.insert.foo = 33
73
+ fb.insert
74
+ 3.times do
75
+ assert_equal(42, fb.query('(agg (exists foo) (max foo))').one)
76
+ end
77
+ end
78
+
79
+ def test_finds_by_eq_with_formula
80
+ fb = Factbase::IndexedFactbase.new(Factbase.new)
81
+ fb.insert.foo = 42
82
+ fb.insert
83
+ 3.times do
84
+ assert_equal(1, fb.query('(eq foo (plus 40 2))').each.to_a.size)
85
+ end
86
+ end
87
+
88
+ def test_finds_by_eq_in_txn
89
+ fb = Factbase::IndexedFactbase.new(Factbase.new)
90
+ fb.insert.foo = 42
91
+ fb.insert
92
+ 3.times do
93
+ fb.txn { |fbt| assert_equal(1, fbt.query('(eq foo 42)').each.to_a.size) }
94
+ end
95
+ end
96
+
97
+ def test_finds_with_conjunction
98
+ fb = Factbase::IndexedFactbase.new(Factbase.new)
99
+ fb.insert.foo = 42
100
+ fb.insert.bar = 33
101
+ 3.times do
102
+ assert_equal(2, fb.query('(or (exists foo) (exists bar))').each.to_a.size)
103
+ end
104
+ end
105
+
106
+ def test_finds_with_disjunction
107
+ fb = Factbase::IndexedFactbase.new(Factbase.new)
108
+ fb.insert.foo = 42
109
+ fb.insert.bar = 33
110
+ f = fb.insert
111
+ f.foo = 42
112
+ f.bar = 33
113
+ 3.times do
114
+ assert_equal(1, fb.query('(and (exists foo) (exists bar))').each.to_a.size)
115
+ end
116
+ end
117
+
118
+ def test_finds_with_inversion
119
+ fb = Factbase::IndexedFactbase.new(Factbase.new)
120
+ fb.insert.foo = 42
121
+ fb.insert.bar = 33
122
+ 3.times do
123
+ assert_equal(1, fb.query('(not (exists foo))').each.to_a.size)
124
+ end
125
+ end
126
+
127
+ def test_finds_with_disjunction_in_txn
128
+ fb = Factbase::IndexedFactbase.new(Factbase.new)
129
+ fb.insert.foo = 42
130
+ fb.insert.bar = 33
131
+ f = fb.insert
132
+ f.foo = 42
133
+ f.bar = 33
134
+ 3.times do
135
+ fb.txn { |fbt| assert_equal(1, fbt.query('(and (exists foo) (exists bar))').each.to_a.size) }
136
+ end
137
+ end
138
+
139
+ def test_attaches_alias
140
+ fb = Factbase::IndexedFactbase.new(Factbase.new)
141
+ total = 10
142
+ total.times do |i|
143
+ f = fb.insert
144
+ f.foo = rand(0..10)
145
+ f.bar = rand(0..10)
146
+ f.xyz = i
147
+ end
148
+ 3.times do
149
+ assert_equal(total, fb.query('(as boom (agg (eq foo $bar) (min xyz)))').each.to_a.size)
150
+ end
151
+ end
152
+
153
+ def test_joins_too
154
+ fb = Factbase::IndexedFactbase.new(Factbase.new)
155
+ total = 10_000
156
+ total.times do |i|
157
+ f = fb.insert
158
+ f.who = i
159
+ end
160
+ total.times do |i|
161
+ f = fb.insert
162
+ f.friend = i
163
+ end
164
+ 3.times do
165
+ assert_equal(total, fb.query('(and (exists who) (join "f<=friend" (eq friend $who)))').each.to_a.size)
166
+ end
167
+ end
168
+
169
+ def test_deletes_too
170
+ fb = Factbase::IndexedFactbase.new(Factbase.new)
171
+ fb.insert.foo = 1
172
+ fb.query('(eq foo 1)').delete!
173
+ assert_equal(0, fb.query('(always)').each.to_a.size)
174
+ end
175
+ end
@@ -0,0 +1,30 @@
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_relative '../../../lib/factbase'
8
+ require_relative '../../../lib/factbase/sync/sync_factbase'
9
+
10
+ # Query test.
11
+ # Author:: Yegor Bugayenko (yegor256@gmail.com)
12
+ # Copyright:: Copyright (c) 2024-2025 Yegor Bugayenko
13
+ # License:: MIT
14
+ class TestSyncQuery < Factbase::Test
15
+ def test_queries_many_times
16
+ fb = Factbase::SyncFactbase.new(Factbase.new)
17
+ total = 5
18
+ total.times { fb.insert }
19
+ total.times do
20
+ assert_equal(5, fb.query('(always)').each.to_a.size)
21
+ end
22
+ end
23
+
24
+ def test_deletes_too
25
+ fb = Factbase::SyncFactbase.new(Factbase.new)
26
+ fb.insert.foo = 1
27
+ fb.query('(eq foo 1)').delete!
28
+ assert_equal(0, fb.query('(always)').each.to_a.size)
29
+ end
30
+ end
@@ -30,10 +30,10 @@ class TestAggregates < Factbase::Test
30
30
  '(eq x (agg (eq y 0) (first x)))' => '(eq x 1)',
31
31
  '(agg (eq foo 42) (always))' => '(eq x 1)'
32
32
  }.each do |q, r|
33
- t = Factbase::Syntax.new(Factbase.new, q).to_term
34
- f = maps.find { |m| t.evaluate(fact(m), maps) }
33
+ t = Factbase::Syntax.new(q).to_term
34
+ f = maps.find { |m| t.evaluate(fact(m), maps, Factbase.new) }
35
35
  refute_nil(f, "nothing found by: #{q}")
36
- assert(Factbase::Syntax.new(Factbase.new, r).to_term.evaluate(fact(f), []))
36
+ assert(Factbase::Syntax.new(r).to_term.evaluate(fact(f), [], Factbase.new))
37
37
  end
38
38
  end
39
39
 
@@ -46,8 +46,8 @@ class TestAggregates < Factbase::Test
46
46
  '(empty (eq y 42))' => true,
47
47
  '(empty (eq x 1))' => false
48
48
  }.each do |q, r|
49
- t = Factbase::Syntax.new(Factbase.new, q).to_term
50
- assert_equal(r, t.evaluate(nil, maps), q)
49
+ t = Factbase::Syntax.new(q).to_term
50
+ assert_equal(r, t.evaluate(Factbase::Fact.new({}), maps, Factbase.new), q)
51
51
  end
52
52
  end
53
53
  end
@@ -24,11 +24,11 @@ class TestAliases < Factbase::Test
24
24
  '(as foo (plus bar 1))' => '(absent foo)',
25
25
  '(as foo (minus t1 t2))' => '(when (exists foo) (eq "Float" (type foo)))'
26
26
  }.each do |q, r|
27
- t = Factbase::Syntax.new(Factbase.new, q).to_term
27
+ t = Factbase::Syntax.new(q).to_term
28
28
  maps.each do |m|
29
29
  f = Factbase::Accum.new(fact(m), {}, false)
30
- next unless t.evaluate(f, maps)
31
- assert(Factbase::Syntax.new(Factbase.new, r).to_term.evaluate(f, []), "#{q} -> #{f}")
30
+ next unless t.evaluate(f, maps, Factbase.new)
31
+ assert(Factbase::Syntax.new(r).to_term.evaluate(f, [], Factbase.new), "#{q} -> #{f}")
32
32
  end
33
33
  end
34
34
  end
@@ -44,13 +44,13 @@ class TestAliases < Factbase::Test
44
44
  '(join "uuu" (eq x 1))' => '(absent uuu)',
45
45
  '(join "uuu <= fff" (eq fff 1))' => '(absent uuu)'
46
46
  }.each do |q, r|
47
- t = Factbase::Syntax.new(Factbase.new, q).to_term
47
+ t = Factbase::Syntax.new(q).to_term
48
48
  maps.each do |m|
49
49
  f = Factbase::Accum.new(fact(m), {}, false)
50
50
  require_relative '../../../lib/factbase/logged'
51
- f = Factbase::Logged::Fact.new(f, Loog::NULL)
52
- next unless t.evaluate(f, maps)
53
- assert(Factbase::Syntax.new(Factbase.new, r).to_term.evaluate(f, []), "#{q} -> #{f} doesn't match #{r}")
51
+ f = Factbase::Logged::Fact.new(f, log: Loog::NULL)
52
+ next unless t.evaluate(f, maps, Factbase.new)
53
+ assert(Factbase::Syntax.new(r).to_term.evaluate(f, [], Factbase.new), "#{q} -> #{f} doesn't match #{r}")
54
54
  end
55
55
  end
56
56
  end
@@ -12,22 +12,22 @@ require_relative '../../../lib/factbase/term'
12
12
  # License:: MIT
13
13
  class TestCasting < Factbase::Test
14
14
  def test_to_str
15
- t = Factbase::Term.new(Factbase.new, :to_string, [Time.now])
16
- assert_equal('String', t.evaluate(fact, []).class.to_s)
15
+ t = Factbase::Term.new(:to_string, [Time.now])
16
+ assert_equal('String', t.evaluate(fact, [], Factbase.new).class.to_s)
17
17
  end
18
18
 
19
19
  def test_to_integer
20
- t = Factbase::Term.new(Factbase.new, :to_integer, [[42, 'hello']])
21
- assert_equal('Integer', t.evaluate(fact, []).class.to_s)
20
+ t = Factbase::Term.new(:to_integer, [[42, 'hello']])
21
+ assert_equal('Integer', t.evaluate(fact, [], Factbase.new).class.to_s)
22
22
  end
23
23
 
24
24
  def test_to_float
25
- t = Factbase::Term.new(Factbase.new, :to_float, [[3.14, 'hello']])
26
- assert_equal('Float', t.evaluate(fact, []).class.to_s)
25
+ t = Factbase::Term.new(:to_float, [[3.14, 'hello']])
26
+ assert_equal('Float', t.evaluate(fact, [], Factbase.new).class.to_s)
27
27
  end
28
28
 
29
29
  def test_to_time
30
- t = Factbase::Term.new(Factbase.new, :to_time, [%w[2023-01-01 hello]])
31
- assert_equal('Time', t.evaluate(fact, []).class.to_s)
30
+ t = Factbase::Term.new(:to_time, [%w[2023-01-01 hello]])
31
+ assert_equal('Time', t.evaluate(fact, [], Factbase.new).class.to_s)
32
32
  end
33
33
  end
@@ -12,14 +12,14 @@ require_relative '../../../lib/factbase/term'
12
12
  # License:: MIT
13
13
  class TestDebug < Factbase::Test
14
14
  def test_traced
15
- t = Factbase::Term.new(Factbase.new, :traced, [Factbase::Term.new(Factbase.new, :defn, [:test_debug, 'self.to_s'])])
15
+ t = Factbase::Term.new(:traced, [Factbase::Term.new(:defn, [:test_debug, 'self.to_s'])])
16
16
  assert_output("(traced (defn test_debug 'self.to_s')) -> true\n") do
17
- assert(t.evaluate(fact, []))
17
+ assert(t.evaluate(fact, [], Factbase.new))
18
18
  end
19
19
  end
20
20
 
21
21
  def test_traced_raises
22
- e = assert_raises(StandardError) { Factbase::Term.new(Factbase.new, :traced, ['foo']).evaluate(fact, []) }
22
+ e = assert_raises(StandardError) { Factbase::Term.new(:traced, ['foo']).evaluate(fact, [], Factbase.new) }
23
23
  assert_match(/A term expected, but 'foo' provided/, e.message)
24
24
  end
25
25
 
@@ -27,9 +27,9 @@ class TestDebug < Factbase::Test
27
27
  e =
28
28
  assert_raises(StandardError) do
29
29
  Factbase::Term.new(
30
- Factbase.new, :traced,
31
- [Factbase::Term.new(Factbase.new, :defn, [:debug, 'self.to_s']), 'something']
32
- ).evaluate(fact, [])
30
+ :traced,
31
+ [Factbase::Term.new(:defn, [:debug, 'self.to_s']), 'something']
32
+ ).evaluate(fact, [], Factbase.new)
33
33
  end
34
34
  assert_match(/Too many \(\d+\) operands for 'traced' \(\d+ expected\)/, e.message)
35
35
  end
@@ -12,37 +12,37 @@ require_relative '../../../lib/factbase/term'
12
12
  # License:: MIT
13
13
  class TestDefn < Factbase::Test
14
14
  def test_defn_simple
15
- t = Factbase::Term.new(Factbase.new, :defn, [:foo, 'self.to_s'])
16
- assert(t.evaluate(fact('foo' => 4), []))
17
- t1 = Factbase::Term.new(Factbase.new, :foo, ['hello, world!'])
18
- assert_equal('(foo \'hello, world!\')', t1.evaluate(fact, []))
15
+ t = Factbase::Term.new(:defn, [:foo, 'self.to_s'])
16
+ assert(t.evaluate(fact('foo' => 4), [], Factbase.new))
17
+ t1 = Factbase::Term.new(:foo, ['hello, world!'])
18
+ assert_equal('(foo \'hello, world!\')', t1.evaluate(fact, [], Factbase.new))
19
19
  end
20
20
 
21
21
  def test_defn_again_by_mistake
22
- t = Factbase::Term.new(Factbase.new, :defn, [:and, 'self.to_s'])
22
+ t = Factbase::Term.new(:defn, [:and, 'self.to_s'])
23
23
  assert_raises(StandardError) do
24
- t.evaluate(fact, [])
24
+ t.evaluate(fact, [], Factbase.new)
25
25
  end
26
26
  end
27
27
 
28
28
  def test_defn_bad_name_by_mistake
29
- t = Factbase::Term.new(Factbase.new, :defn, [:to_s, 'self.to_s'])
29
+ t = Factbase::Term.new(:defn, [:to_s, 'self.to_s'])
30
30
  assert_raises(StandardError) do
31
- t.evaluate(fact, [])
31
+ t.evaluate(fact, [], Factbase.new)
32
32
  end
33
33
  end
34
34
 
35
35
  def test_defn_bad_name_spelling_by_mistake
36
- t = Factbase::Term.new(Factbase.new, :defn, [:'some-key', 'self.to_s'])
36
+ t = Factbase::Term.new(:defn, [:'some-key', 'self.to_s'])
37
37
  assert_raises(StandardError) do
38
- t.evaluate(fact, [])
38
+ t.evaluate(fact, [], Factbase.new)
39
39
  end
40
40
  end
41
41
 
42
42
  def test_undef_simple
43
- t = Factbase::Term.new(Factbase.new, :defn, [:hello, 'self.to_s'])
44
- assert(t.evaluate(fact, []))
45
- t = Factbase::Term.new(Factbase.new, :undef, [:hello])
46
- assert(t.evaluate(fact, []))
43
+ t = Factbase::Term.new(:defn, [:hello, 'self.to_s'])
44
+ assert(t.evaluate(fact, [], Factbase.new))
45
+ t = Factbase::Term.new(:undef, [:hello])
46
+ assert(t.evaluate(fact, [], Factbase.new))
47
47
  end
48
48
  end
@@ -12,46 +12,44 @@ require_relative '../../../lib/factbase/term'
12
12
  # License:: MIT
13
13
  class TestLogical < Factbase::Test
14
14
  def test_not_matching
15
- t = Factbase::Term.new(Factbase.new, :not, [Factbase::Term.new(Factbase.new, :always, [])])
16
- refute(t.evaluate(fact('foo' => [100]), []))
15
+ t = Factbase::Term.new(:not, [Factbase::Term.new(:always, [])])
16
+ refute(t.evaluate(fact('foo' => [100]), [], Factbase.new))
17
17
  end
18
18
 
19
19
  def test_not_eq_matching
20
- t = Factbase::Term.new(Factbase.new, :not, [Factbase::Term.new(Factbase.new, :eq, [:foo, 100])])
21
- assert(t.evaluate(fact('foo' => [42, 12, -90]), []))
22
- refute(t.evaluate(fact('foo' => 100), []))
20
+ t = Factbase::Term.new(:not, [Factbase::Term.new(:eq, [:foo, 100])])
21
+ assert(t.evaluate(fact('foo' => [42, 12, -90]), [], Factbase.new))
22
+ refute(t.evaluate(fact('foo' => 100), [], Factbase.new))
23
23
  end
24
24
 
25
25
  def test_either
26
- t = Factbase::Term.new(Factbase.new, :either, [Factbase::Term.new(Factbase.new, :at, [5, :foo]), 42])
27
- assert_equal([42], t.evaluate(fact('foo' => 4), []))
26
+ t = Factbase::Term.new(:either, [Factbase::Term.new(:at, [5, :foo]), 42])
27
+ assert_equal([42], t.evaluate(fact('foo' => 4), [], Factbase.new))
28
28
  end
29
29
 
30
30
  def test_or_matching
31
31
  t = Factbase::Term.new(
32
- Factbase.new,
33
32
  :or,
34
33
  [
35
- Factbase::Term.new(Factbase.new, :eq, [:foo, 4]),
36
- Factbase::Term.new(Factbase.new, :eq, [:bar, 5])
34
+ Factbase::Term.new(:eq, [:foo, 4]),
35
+ Factbase::Term.new(:eq, [:bar, 5])
37
36
  ]
38
37
  )
39
- assert(t.evaluate(fact('foo' => [4]), []))
40
- assert(t.evaluate(fact('bar' => [5]), []))
41
- refute(t.evaluate(fact('bar' => [42]), []))
38
+ assert(t.evaluate(fact('foo' => [4]), [], Factbase.new))
39
+ assert(t.evaluate(fact('bar' => [5]), [], Factbase.new))
40
+ refute(t.evaluate(fact('bar' => [42]), [], Factbase.new))
42
41
  end
43
42
 
44
43
  def test_when_matching
45
44
  t = Factbase::Term.new(
46
- Factbase.new,
47
45
  :when,
48
46
  [
49
- Factbase::Term.new(Factbase.new, :eq, [:foo, 4]),
50
- Factbase::Term.new(Factbase.new, :eq, [:bar, 5])
47
+ Factbase::Term.new(:eq, [:foo, 4]),
48
+ Factbase::Term.new(:eq, [:bar, 5])
51
49
  ]
52
50
  )
53
- assert(t.evaluate(fact('foo' => 4, 'bar' => 5), []))
54
- refute(t.evaluate(fact('foo' => 4), []))
55
- assert(t.evaluate(fact('foo' => 5, 'bar' => 5), []))
51
+ assert(t.evaluate(fact('foo' => 4, 'bar' => 5), [], Factbase.new))
52
+ refute(t.evaluate(fact('foo' => 4), [], Factbase.new))
53
+ assert(t.evaluate(fact('foo' => 5, 'bar' => 5), [], Factbase.new))
56
54
  end
57
55
  end
@@ -12,109 +12,111 @@ require_relative '../../../lib/factbase/term'
12
12
  # License:: MIT
13
13
  class TestMath < Factbase::Test
14
14
  def test_simple
15
- t = Factbase::Term.new(Factbase.new, :eq, [:foo, 42])
16
- assert(t.evaluate(fact('foo' => [42]), []))
17
- refute(t.evaluate(fact('foo' => 'Hello!'), []))
18
- refute(t.evaluate(fact('bar' => ['Hello!']), []))
15
+ t = Factbase::Term.new(:eq, [:foo, 42])
16
+ assert(t.evaluate(fact('foo' => [42]), [], Factbase.new))
17
+ refute(t.evaluate(fact('foo' => 'Hello!'), [], Factbase.new))
18
+ refute(t.evaluate(fact('bar' => ['Hello!']), [], Factbase.new))
19
19
  end
20
20
 
21
21
  def test_zero
22
- t = Factbase::Term.new(Factbase.new, :zero, [:foo])
23
- assert(t.evaluate(fact('foo' => [0]), []))
24
- assert(t.evaluate(fact('foo' => [10, 5, 6, -8, 'hey', 0, 9, 'fdsf']), []))
25
- refute(t.evaluate(fact('foo' => [100]), []))
26
- refute(t.evaluate(fact('foo' => []), []))
27
- refute(t.evaluate(fact('bar' => []), []))
22
+ t = Factbase::Term.new(:zero, [:foo])
23
+ assert(t.evaluate(fact('foo' => [0]), [], Factbase.new))
24
+ assert(t.evaluate(fact('foo' => [10, 5, 6, -8, 'hey', 0, 9, 'fdsf']), [], Factbase.new))
25
+ refute(t.evaluate(fact('foo' => [100]), [], Factbase.new))
26
+ refute(t.evaluate(fact('foo' => []), [], Factbase.new))
27
+ refute(t.evaluate(fact('bar' => []), [], Factbase.new))
28
28
  end
29
29
 
30
30
  def test_eq
31
- t = Factbase::Term.new(Factbase.new, :eq, [:foo, 42])
32
- assert(t.evaluate(fact('foo' => 42), []))
33
- assert(t.evaluate(fact('foo' => [10, 5, 6, -8, 'hey', 42, 9, 'fdsf']), []))
34
- refute(t.evaluate(fact('foo' => [100]), []))
35
- refute(t.evaluate(fact('foo' => []), []))
36
- refute(t.evaluate(fact('bar' => []), []))
31
+ t = Factbase::Term.new(:eq, [:foo, 42])
32
+ assert(t.evaluate(fact('foo' => 42), [], Factbase.new))
33
+ assert(t.evaluate(fact('foo' => [10, 5, 6, -8, 'hey', 42, 9, 'fdsf']), [], Factbase.new))
34
+ refute(t.evaluate(fact('foo' => [100]), [], Factbase.new))
35
+ refute(t.evaluate(fact('foo' => []), [], Factbase.new))
36
+ refute(t.evaluate(fact('bar' => []), [], Factbase.new))
37
37
  end
38
38
 
39
39
  def test_eq_time
40
40
  now = Time.now
41
- t = Factbase::Term.new(Factbase.new, :eq, [:foo, Time.parse(now.iso8601)])
42
- assert(t.evaluate(fact('foo' => now), []))
43
- assert(t.evaluate(fact('foo' => [now, Time.now]), []))
41
+ t = Factbase::Term.new(:eq, [:foo, Time.parse(now.iso8601)])
42
+ assert(t.evaluate(fact('foo' => now), [], Factbase.new))
43
+ assert(t.evaluate(fact('foo' => [now, Time.now]), [], Factbase.new))
44
44
  end
45
45
 
46
46
  def test_lt
47
- t = Factbase::Term.new(Factbase.new, :lt, [:foo, 42])
48
- assert(t.evaluate(fact('foo' => [10]), []))
49
- refute(t.evaluate(fact('foo' => [100]), []))
50
- refute(t.evaluate(fact('foo' => 100), []))
51
- refute(t.evaluate(fact('bar' => 100), []))
47
+ t = Factbase::Term.new(:lt, [:foo, 42])
48
+ assert(t.evaluate(fact('foo' => [10]), [], Factbase.new))
49
+ refute(t.evaluate(fact('foo' => [100]), [], Factbase.new))
50
+ refute(t.evaluate(fact('foo' => 100), [], Factbase.new))
51
+ refute(t.evaluate(fact('bar' => 100), [], Factbase.new))
52
52
  end
53
53
 
54
54
  def test_gte
55
- t = Factbase::Term.new(Factbase.new, :gte, [:foo, 42])
56
- assert(t.evaluate(fact('foo' => 100), []))
57
- assert(t.evaluate(fact('foo' => 42), []))
58
- refute(t.evaluate(fact('foo' => 41), []))
55
+ t = Factbase::Term.new(:gte, [:foo, 42])
56
+ assert(t.evaluate(fact('foo' => 100), [], Factbase.new))
57
+ assert(t.evaluate(fact('foo' => 42), [], Factbase.new))
58
+ refute(t.evaluate(fact('foo' => 41), [], Factbase.new))
59
59
  end
60
60
 
61
61
  def test_lte
62
- t = Factbase::Term.new(Factbase.new, :lte, [:foo, 42])
63
- assert(t.evaluate(fact('foo' => 41), []))
64
- assert(t.evaluate(fact('foo' => 42), []))
65
- refute(t.evaluate(fact('foo' => 100), []))
62
+ t = Factbase::Term.new(:lte, [:foo, 42])
63
+ assert(t.evaluate(fact('foo' => 41), [], Factbase.new))
64
+ assert(t.evaluate(fact('foo' => 42), [], Factbase.new))
65
+ refute(t.evaluate(fact('foo' => 100), [], Factbase.new))
66
66
  end
67
67
 
68
68
  def test_gt
69
- t = Factbase::Term.new(Factbase.new, :gt, [:foo, 42])
70
- assert(t.evaluate(fact('foo' => [100]), []))
71
- assert(t.evaluate(fact('foo' => 100), []))
72
- refute(t.evaluate(fact('foo' => [10]), []))
73
- refute(t.evaluate(fact('foo' => 10), []))
74
- refute(t.evaluate(fact('bar' => 10), []))
69
+ t = Factbase::Term.new(:gt, [:foo, 42])
70
+ assert(t.evaluate(fact('foo' => [100]), [], Factbase.new))
71
+ assert(t.evaluate(fact('foo' => 100), [], Factbase.new))
72
+ refute(t.evaluate(fact('foo' => [10]), [], Factbase.new))
73
+ refute(t.evaluate(fact('foo' => 10), [], Factbase.new))
74
+ refute(t.evaluate(fact('bar' => 10), [], Factbase.new))
75
75
  end
76
76
 
77
77
  def test_lt_time
78
- t = Factbase::Term.new(Factbase.new, :lt, [:foo, Time.now])
79
- assert(t.evaluate(fact('foo' => [Time.now - 100]), []))
80
- refute(t.evaluate(fact('foo' => [Time.now + 100]), []))
81
- refute(t.evaluate(fact('bar' => [100]), []))
78
+ t = Factbase::Term.new(:lt, [:foo, Time.now])
79
+ assert(t.evaluate(fact('foo' => [Time.now - 100]), [], Factbase.new))
80
+ refute(t.evaluate(fact('foo' => [Time.now + 100]), [], Factbase.new))
81
+ refute(t.evaluate(fact('bar' => [100]), [], Factbase.new))
82
82
  end
83
83
 
84
84
  def test_gt_time
85
- t = Factbase::Term.new(Factbase.new, :gt, [:foo, Time.now])
86
- assert(t.evaluate(fact('foo' => [Time.now + 100]), []))
87
- refute(t.evaluate(fact('foo' => [Time.now - 100]), []))
88
- refute(t.evaluate(fact('bar' => [100]), []))
85
+ t = Factbase::Term.new(:gt, [:foo, Time.now])
86
+ assert(t.evaluate(fact('foo' => [Time.now + 100]), [], Factbase.new))
87
+ refute(t.evaluate(fact('foo' => [Time.now - 100]), [], Factbase.new))
88
+ refute(t.evaluate(fact('bar' => [100]), [], Factbase.new))
89
89
  end
90
90
 
91
91
  def test_plus
92
- t = Factbase::Term.new(Factbase.new, :plus, [:foo, 42])
93
- assert_equal(46, t.evaluate(fact('foo' => 4), []))
94
- assert_nil(t.evaluate(fact, []))
92
+ t = Factbase::Term.new(:plus, [:foo, 42])
93
+ assert_equal(46, t.evaluate(fact('foo' => 4), [], Factbase.new))
94
+ assert_nil(t.evaluate(fact, [], Factbase.new))
95
95
  end
96
96
 
97
97
  def test_plus_time
98
- t = Factbase::Term.new(Factbase.new, :plus, [:foo, '12 days'])
99
- assert_equal(Time.parse('2024-01-13'), t.evaluate(fact('foo' => Time.parse('2024-01-01')), []))
100
- assert_nil(t.evaluate(fact, []))
98
+ t = Factbase::Term.new(:plus, [:foo, '12 days'])
99
+ assert_equal(Time.parse('2024-01-13'), t.evaluate(fact('foo' => Time.parse('2024-01-01')), [], Factbase.new))
100
+ assert_nil(t.evaluate(fact, [], Factbase.new))
101
101
  end
102
102
 
103
103
  def test_minus
104
- t = Factbase::Term.new(Factbase.new, :minus, [:foo, 42])
105
- assert_equal(58, t.evaluate(fact('foo' => 100), []))
106
- assert_nil(t.evaluate(fact, []))
104
+ t = Factbase::Term.new(:minus, [:foo, 42])
105
+ assert_equal(58, t.evaluate(fact('foo' => 100), [], Factbase.new))
106
+ assert_nil(t.evaluate(fact, [], Factbase.new))
107
107
  end
108
108
 
109
109
  def test_minus_time
110
- t = Factbase::Term.new(Factbase.new, :minus, [:foo, '4 hours'])
111
- assert_equal(Time.parse('2024-01-01T06:04'), t.evaluate(fact('foo' => Time.parse('2024-01-01T10:04')), []))
112
- assert_nil(t.evaluate(fact, []))
110
+ t = Factbase::Term.new(:minus, [:foo, '4 hours'])
111
+ assert_equal(Time.parse('2024-01-01T06:04'),
112
+ t.evaluate(fact('foo' => Time.parse('2024-01-01T10:04')), [], Factbase.new))
113
+ assert_nil(t.evaluate(fact, [], Factbase.new))
113
114
  end
114
115
 
115
116
  def test_minus_time_singular
116
- t = Factbase::Term.new(Factbase.new, :minus, [:foo, '1 hour'])
117
- assert_equal(Time.parse('2024-01-01T09:04'), t.evaluate(fact('foo' => Time.parse('2024-01-01T10:04')), []))
118
- assert_nil(t.evaluate(fact, []))
117
+ t = Factbase::Term.new(:minus, [:foo, '1 hour'])
118
+ assert_equal(Time.parse('2024-01-01T09:04'),
119
+ t.evaluate(fact('foo' => Time.parse('2024-01-01T10:04')), [], Factbase.new))
120
+ assert_nil(t.evaluate(fact, [], Factbase.new))
119
121
  end
120
122
  end