factbase 0.4.0 → 0.5.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 (79) hide show
  1. checksums.yaml +4 -4
  2. data/.0pdd.yml +1 -1
  3. data/.github/workflows/actionlint.yml +1 -1
  4. data/.github/workflows/benchmark.yml +64 -0
  5. data/.github/workflows/codecov.yml +4 -2
  6. data/.github/workflows/copyrights.yml +2 -2
  7. data/.github/workflows/markdown-lint.yml +1 -1
  8. data/.github/workflows/pdd.yml +1 -1
  9. data/.github/workflows/rake.yml +2 -2
  10. data/.github/workflows/xcop.yml +1 -1
  11. data/.github/workflows/yamllint.yml +1 -1
  12. data/.gitignore +1 -1
  13. data/.rubocop.yml +6 -1
  14. data/.rultor.yml +2 -2
  15. data/.simplecov +1 -1
  16. data/.yamllint.yml +9 -4
  17. data/Gemfile +9 -7
  18. data/Gemfile.lock +98 -78
  19. data/LICENSE.txt +1 -1
  20. data/README.md +33 -0
  21. data/Rakefile +6 -1
  22. data/benchmarks/simple.rb +96 -0
  23. data/factbase.gemspec +1 -1
  24. data/lib/factbase/accum.rb +2 -2
  25. data/lib/factbase/fact.rb +6 -4
  26. data/lib/factbase/flatten.rb +2 -2
  27. data/lib/factbase/inv.rb +2 -2
  28. data/lib/factbase/looged.rb +6 -5
  29. data/lib/factbase/pre.rb +2 -2
  30. data/lib/factbase/query.rb +16 -8
  31. data/lib/factbase/query_once.rb +71 -0
  32. data/lib/factbase/rules.rb +3 -3
  33. data/lib/factbase/syntax.rb +21 -11
  34. data/lib/factbase/tee.rb +2 -2
  35. data/lib/factbase/term.rb +33 -5
  36. data/lib/factbase/term_once.rb +84 -0
  37. data/lib/factbase/terms/aggregates.rb +4 -4
  38. data/lib/factbase/terms/aliases.rb +5 -5
  39. data/lib/factbase/terms/casting.rb +2 -2
  40. data/lib/factbase/terms/debug.rb +2 -2
  41. data/lib/factbase/terms/defn.rb +2 -2
  42. data/lib/factbase/terms/logical.rb +3 -3
  43. data/lib/factbase/terms/math.rb +2 -2
  44. data/lib/factbase/terms/meta.rb +2 -2
  45. data/lib/factbase/terms/ordering.rb +2 -2
  46. data/lib/factbase/terms/strings.rb +2 -2
  47. data/lib/factbase/terms/system.rb +2 -2
  48. data/lib/factbase/to_json.rb +2 -2
  49. data/lib/factbase/to_xml.rb +2 -2
  50. data/lib/factbase/to_yaml.rb +2 -2
  51. data/lib/factbase.rb +16 -6
  52. data/test/factbase/terms/test_aggregates.rb +6 -6
  53. data/test/factbase/terms/test_aliases.rb +6 -6
  54. data/test/factbase/terms/test_casting.rb +6 -6
  55. data/test/factbase/terms/test_debug.rb +53 -0
  56. data/test/factbase/terms/test_defn.rb +15 -15
  57. data/test/factbase/terms/test_logical.rb +15 -13
  58. data/test/factbase/terms/test_math.rb +42 -42
  59. data/test/factbase/terms/test_meta.rb +87 -0
  60. data/test/factbase/terms/test_ordering.rb +45 -0
  61. data/test/factbase/terms/test_strings.rb +8 -8
  62. data/test/factbase/terms/test_system.rb +6 -6
  63. data/test/factbase/test_accum.rb +9 -9
  64. data/test/factbase/test_fact.rb +22 -22
  65. data/test/factbase/test_flatten.rb +6 -6
  66. data/test/factbase/test_inv.rb +3 -3
  67. data/test/factbase/test_looged.rb +13 -13
  68. data/test/factbase/test_pre.rb +2 -2
  69. data/test/factbase/test_query.rb +17 -17
  70. data/test/factbase/test_rules.rb +8 -8
  71. data/test/factbase/test_syntax.rb +30 -9
  72. data/test/factbase/test_tee.rb +11 -11
  73. data/test/factbase/test_term.rb +18 -18
  74. data/test/factbase/test_to_json.rb +4 -4
  75. data/test/factbase/test_to_xml.rb +12 -14
  76. data/test/factbase/test_to_yaml.rb +3 -3
  77. data/test/test__helper.rb +2 -2
  78. data/test/test_factbase.rb +200 -18
  79. metadata +12 -5
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # Copyright (c) 2024 Yegor Bugayenko
3
+ # Copyright (c) 2024-2025 Yegor Bugayenko
4
4
  #
5
5
  # Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  # of this software and associated documentation files (the 'Software'), to deal
@@ -25,41 +25,41 @@ require_relative '../../../lib/factbase/term'
25
25
 
26
26
  # Defn test.
27
27
  # Author:: Yegor Bugayenko (yegor256@gmail.com)
28
- # Copyright:: Copyright (c) 2024 Yegor Bugayenko
28
+ # Copyright:: Copyright (c) 2024-2025 Yegor Bugayenko
29
29
  # License:: MIT
30
30
  class TestDefn < Minitest::Test
31
31
  def test_defn_simple
32
- t = Factbase::Term.new(:defn, [:foo, 'self.to_s'])
33
- assert_equal(true, t.evaluate(fact('foo' => 4), []))
34
- t1 = Factbase::Term.new(:foo, ['hello, world!'])
32
+ t = Factbase::Term.new(Factbase.new, :defn, [:foo, 'self.to_s'])
33
+ assert(t.evaluate(fact('foo' => 4), []))
34
+ t1 = Factbase::Term.new(Factbase.new, :foo, ['hello, world!'])
35
35
  assert_equal('(foo \'hello, world!\')', t1.evaluate(fact, []))
36
36
  end
37
37
 
38
38
  def test_defn_again_by_mistake
39
- t = Factbase::Term.new(:defn, [:and, 'self.to_s'])
40
- assert_raises do
39
+ t = Factbase::Term.new(Factbase.new, :defn, [:and, 'self.to_s'])
40
+ assert_raises(StandardError) do
41
41
  t.evaluate(fact, [])
42
42
  end
43
43
  end
44
44
 
45
45
  def test_defn_bad_name_by_mistake
46
- t = Factbase::Term.new(:defn, [:to_s, 'self.to_s'])
47
- assert_raises do
46
+ t = Factbase::Term.new(Factbase.new, :defn, [:to_s, 'self.to_s'])
47
+ assert_raises(StandardError) do
48
48
  t.evaluate(fact, [])
49
49
  end
50
50
  end
51
51
 
52
52
  def test_defn_bad_name_spelling_by_mistake
53
- t = Factbase::Term.new(:defn, [:'some-key', 'self.to_s'])
54
- assert_raises do
53
+ t = Factbase::Term.new(Factbase.new, :defn, [:'some-key', 'self.to_s'])
54
+ assert_raises(StandardError) do
55
55
  t.evaluate(fact, [])
56
56
  end
57
57
  end
58
58
 
59
59
  def test_undef_simple
60
- t = Factbase::Term.new(:defn, [:hello, 'self.to_s'])
61
- assert_equal(true, t.evaluate(fact, []))
62
- t = Factbase::Term.new(:undef, [:hello])
63
- assert_equal(true, t.evaluate(fact, []))
60
+ t = Factbase::Term.new(Factbase.new, :defn, [:hello, 'self.to_s'])
61
+ assert(t.evaluate(fact, []))
62
+ t = Factbase::Term.new(Factbase.new, :undef, [:hello])
63
+ assert(t.evaluate(fact, []))
64
64
  end
65
65
  end
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # Copyright (c) 2024 Yegor Bugayenko
3
+ # Copyright (c) 2024-2025 Yegor Bugayenko
4
4
  #
5
5
  # Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  # of this software and associated documentation files (the 'Software'), to deal
@@ -25,48 +25,50 @@ require_relative '../../../lib/factbase/term'
25
25
 
26
26
  # Logical test.
27
27
  # Author:: Yegor Bugayenko (yegor256@gmail.com)
28
- # Copyright:: Copyright (c) 2024 Yegor Bugayenko
28
+ # Copyright:: Copyright (c) 2024-2025 Yegor Bugayenko
29
29
  # License:: MIT
30
30
  class TestLogical < Minitest::Test
31
31
  def test_not_matching
32
- t = Factbase::Term.new(:not, [Factbase::Term.new(:always, [])])
33
- assert(!t.evaluate(fact('foo' => [100]), []))
32
+ t = Factbase::Term.new(Factbase.new, :not, [Factbase::Term.new(Factbase.new, :always, [])])
33
+ refute(t.evaluate(fact('foo' => [100]), []))
34
34
  end
35
35
 
36
36
  def test_not_eq_matching
37
- t = Factbase::Term.new(:not, [Factbase::Term.new(:eq, [:foo, 100])])
37
+ t = Factbase::Term.new(Factbase.new, :not, [Factbase::Term.new(Factbase.new, :eq, [:foo, 100])])
38
38
  assert(t.evaluate(fact('foo' => [42, 12, -90]), []))
39
- assert(!t.evaluate(fact('foo' => 100), []))
39
+ refute(t.evaluate(fact('foo' => 100), []))
40
40
  end
41
41
 
42
42
  def test_either
43
- t = Factbase::Term.new(:either, [Factbase::Term.new(:at, [5, :foo]), 42])
43
+ t = Factbase::Term.new(Factbase.new, :either, [Factbase::Term.new(Factbase.new, :at, [5, :foo]), 42])
44
44
  assert_equal([42], t.evaluate(fact('foo' => 4), []))
45
45
  end
46
46
 
47
47
  def test_or_matching
48
48
  t = Factbase::Term.new(
49
+ Factbase.new,
49
50
  :or,
50
51
  [
51
- Factbase::Term.new(:eq, [:foo, 4]),
52
- Factbase::Term.new(:eq, [:bar, 5])
52
+ Factbase::Term.new(Factbase.new, :eq, [:foo, 4]),
53
+ Factbase::Term.new(Factbase.new, :eq, [:bar, 5])
53
54
  ]
54
55
  )
55
56
  assert(t.evaluate(fact('foo' => [4]), []))
56
57
  assert(t.evaluate(fact('bar' => [5]), []))
57
- assert(!t.evaluate(fact('bar' => [42]), []))
58
+ refute(t.evaluate(fact('bar' => [42]), []))
58
59
  end
59
60
 
60
61
  def test_when_matching
61
62
  t = Factbase::Term.new(
63
+ Factbase.new,
62
64
  :when,
63
65
  [
64
- Factbase::Term.new(:eq, [:foo, 4]),
65
- Factbase::Term.new(:eq, [:bar, 5])
66
+ Factbase::Term.new(Factbase.new, :eq, [:foo, 4]),
67
+ Factbase::Term.new(Factbase.new, :eq, [:bar, 5])
66
68
  ]
67
69
  )
68
70
  assert(t.evaluate(fact('foo' => 4, 'bar' => 5), []))
69
- assert(!t.evaluate(fact('foo' => 4), []))
71
+ refute(t.evaluate(fact('foo' => 4), []))
70
72
  assert(t.evaluate(fact('foo' => 5, 'bar' => 5), []))
71
73
  end
72
74
  end
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # Copyright (c) 2024 Yegor Bugayenko
3
+ # Copyright (c) 2024-2025 Yegor Bugayenko
4
4
  #
5
5
  # Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  # of this software and associated documentation files (the 'Software'), to deal
@@ -26,113 +26,113 @@ require_relative '../../../lib/factbase/term'
26
26
 
27
27
  # Math test.
28
28
  # Author:: Yegor Bugayenko (yegor256@gmail.com)
29
- # Copyright:: Copyright (c) 2024 Yegor Bugayenko
29
+ # Copyright:: Copyright (c) 2024-2025 Yegor Bugayenko
30
30
  # License:: MIT
31
31
  class TestMath < Minitest::Test
32
32
  def test_simple
33
- t = Factbase::Term.new(:eq, [:foo, 42])
33
+ t = Factbase::Term.new(Factbase.new, :eq, [:foo, 42])
34
34
  assert(t.evaluate(fact('foo' => [42]), []))
35
- assert(!t.evaluate(fact('foo' => 'Hello!'), []))
36
- assert(!t.evaluate(fact('bar' => ['Hello!']), []))
35
+ refute(t.evaluate(fact('foo' => 'Hello!'), []))
36
+ refute(t.evaluate(fact('bar' => ['Hello!']), []))
37
37
  end
38
38
 
39
39
  def test_zero
40
- t = Factbase::Term.new(:zero, [:foo])
40
+ t = Factbase::Term.new(Factbase.new, :zero, [:foo])
41
41
  assert(t.evaluate(fact('foo' => [0]), []))
42
42
  assert(t.evaluate(fact('foo' => [10, 5, 6, -8, 'hey', 0, 9, 'fdsf']), []))
43
- assert(!t.evaluate(fact('foo' => [100]), []))
44
- assert(!t.evaluate(fact('foo' => []), []))
45
- assert(!t.evaluate(fact('bar' => []), []))
43
+ refute(t.evaluate(fact('foo' => [100]), []))
44
+ refute(t.evaluate(fact('foo' => []), []))
45
+ refute(t.evaluate(fact('bar' => []), []))
46
46
  end
47
47
 
48
48
  def test_eq
49
- t = Factbase::Term.new(:eq, [:foo, 42])
49
+ t = Factbase::Term.new(Factbase.new, :eq, [:foo, 42])
50
50
  assert(t.evaluate(fact('foo' => 42), []))
51
51
  assert(t.evaluate(fact('foo' => [10, 5, 6, -8, 'hey', 42, 9, 'fdsf']), []))
52
- assert(!t.evaluate(fact('foo' => [100]), []))
53
- assert(!t.evaluate(fact('foo' => []), []))
54
- assert(!t.evaluate(fact('bar' => []), []))
52
+ refute(t.evaluate(fact('foo' => [100]), []))
53
+ refute(t.evaluate(fact('foo' => []), []))
54
+ refute(t.evaluate(fact('bar' => []), []))
55
55
  end
56
56
 
57
57
  def test_eq_time
58
58
  now = Time.now
59
- t = Factbase::Term.new(:eq, [:foo, Time.parse(now.iso8601)])
59
+ t = Factbase::Term.new(Factbase.new, :eq, [:foo, Time.parse(now.iso8601)])
60
60
  assert(t.evaluate(fact('foo' => now), []))
61
61
  assert(t.evaluate(fact('foo' => [now, Time.now]), []))
62
62
  end
63
63
 
64
64
  def test_lt
65
- t = Factbase::Term.new(:lt, [:foo, 42])
65
+ t = Factbase::Term.new(Factbase.new, :lt, [:foo, 42])
66
66
  assert(t.evaluate(fact('foo' => [10]), []))
67
- assert(!t.evaluate(fact('foo' => [100]), []))
68
- assert(!t.evaluate(fact('foo' => 100), []))
69
- assert(!t.evaluate(fact('bar' => 100), []))
67
+ refute(t.evaluate(fact('foo' => [100]), []))
68
+ refute(t.evaluate(fact('foo' => 100), []))
69
+ refute(t.evaluate(fact('bar' => 100), []))
70
70
  end
71
71
 
72
72
  def test_gte
73
- t = Factbase::Term.new(:gte, [:foo, 42])
73
+ t = Factbase::Term.new(Factbase.new, :gte, [:foo, 42])
74
74
  assert(t.evaluate(fact('foo' => 100), []))
75
75
  assert(t.evaluate(fact('foo' => 42), []))
76
- assert(!t.evaluate(fact('foo' => 41), []))
76
+ refute(t.evaluate(fact('foo' => 41), []))
77
77
  end
78
78
 
79
79
  def test_lte
80
- t = Factbase::Term.new(:lte, [:foo, 42])
80
+ t = Factbase::Term.new(Factbase.new, :lte, [:foo, 42])
81
81
  assert(t.evaluate(fact('foo' => 41), []))
82
82
  assert(t.evaluate(fact('foo' => 42), []))
83
- assert(!t.evaluate(fact('foo' => 100), []))
83
+ refute(t.evaluate(fact('foo' => 100), []))
84
84
  end
85
85
 
86
86
  def test_gt
87
- t = Factbase::Term.new(:gt, [:foo, 42])
87
+ t = Factbase::Term.new(Factbase.new, :gt, [:foo, 42])
88
88
  assert(t.evaluate(fact('foo' => [100]), []))
89
89
  assert(t.evaluate(fact('foo' => 100), []))
90
- assert(!t.evaluate(fact('foo' => [10]), []))
91
- assert(!t.evaluate(fact('foo' => 10), []))
92
- assert(!t.evaluate(fact('bar' => 10), []))
90
+ refute(t.evaluate(fact('foo' => [10]), []))
91
+ refute(t.evaluate(fact('foo' => 10), []))
92
+ refute(t.evaluate(fact('bar' => 10), []))
93
93
  end
94
94
 
95
95
  def test_lt_time
96
- t = Factbase::Term.new(:lt, [:foo, Time.now])
96
+ t = Factbase::Term.new(Factbase.new, :lt, [:foo, Time.now])
97
97
  assert(t.evaluate(fact('foo' => [Time.now - 100]), []))
98
- assert(!t.evaluate(fact('foo' => [Time.now + 100]), []))
99
- assert(!t.evaluate(fact('bar' => [100]), []))
98
+ refute(t.evaluate(fact('foo' => [Time.now + 100]), []))
99
+ refute(t.evaluate(fact('bar' => [100]), []))
100
100
  end
101
101
 
102
102
  def test_gt_time
103
- t = Factbase::Term.new(:gt, [:foo, Time.now])
103
+ t = Factbase::Term.new(Factbase.new, :gt, [:foo, Time.now])
104
104
  assert(t.evaluate(fact('foo' => [Time.now + 100]), []))
105
- assert(!t.evaluate(fact('foo' => [Time.now - 100]), []))
106
- assert(!t.evaluate(fact('bar' => [100]), []))
105
+ refute(t.evaluate(fact('foo' => [Time.now - 100]), []))
106
+ refute(t.evaluate(fact('bar' => [100]), []))
107
107
  end
108
108
 
109
109
  def test_plus
110
- t = Factbase::Term.new(:plus, [:foo, 42])
110
+ t = Factbase::Term.new(Factbase.new, :plus, [:foo, 42])
111
111
  assert_equal(46, t.evaluate(fact('foo' => 4), []))
112
- assert(t.evaluate(fact, []).nil?)
112
+ assert_nil(t.evaluate(fact, []))
113
113
  end
114
114
 
115
115
  def test_plus_time
116
- t = Factbase::Term.new(:plus, [:foo, '12 days'])
116
+ t = Factbase::Term.new(Factbase.new, :plus, [:foo, '12 days'])
117
117
  assert_equal(Time.parse('2024-01-13'), t.evaluate(fact('foo' => Time.parse('2024-01-01')), []))
118
- assert(t.evaluate(fact, []).nil?)
118
+ assert_nil(t.evaluate(fact, []))
119
119
  end
120
120
 
121
121
  def test_minus
122
- t = Factbase::Term.new(:minus, [:foo, 42])
122
+ t = Factbase::Term.new(Factbase.new, :minus, [:foo, 42])
123
123
  assert_equal(58, t.evaluate(fact('foo' => 100), []))
124
- assert(t.evaluate(fact, []).nil?)
124
+ assert_nil(t.evaluate(fact, []))
125
125
  end
126
126
 
127
127
  def test_minus_time
128
- t = Factbase::Term.new(:minus, [:foo, '4 hours'])
128
+ t = Factbase::Term.new(Factbase.new, :minus, [:foo, '4 hours'])
129
129
  assert_equal(Time.parse('2024-01-01T06:04'), t.evaluate(fact('foo' => Time.parse('2024-01-01T10:04')), []))
130
- assert(t.evaluate(fact, []).nil?)
130
+ assert_nil(t.evaluate(fact, []))
131
131
  end
132
132
 
133
133
  def test_minus_time_singular
134
- t = Factbase::Term.new(:minus, [:foo, '1 hour'])
134
+ t = Factbase::Term.new(Factbase.new, :minus, [:foo, '1 hour'])
135
135
  assert_equal(Time.parse('2024-01-01T09:04'), t.evaluate(fact('foo' => Time.parse('2024-01-01T10:04')), []))
136
- assert(t.evaluate(fact, []).nil?)
136
+ assert_nil(t.evaluate(fact, []))
137
137
  end
138
138
  end
@@ -0,0 +1,87 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright (c) 2024-2025 Yegor Bugayenko
4
+ #
5
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ # of this software and associated documentation files (the 'Software'), to deal
7
+ # in the Software without restriction, including without limitation the rights
8
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ # copies of the Software, and to permit persons to whom the Software is
10
+ # furnished to do so, subject to the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be included in all
13
+ # copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFINGEMENT. IN NO EVENT SHALL THE
18
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ # SOFTWARE.
22
+
23
+ require 'minitest/autorun'
24
+ require_relative '../../../lib/factbase/term'
25
+
26
+ # Meta test.
27
+ # Author:: Yegor Bugayenko (yegor256@gmail.com)
28
+ # Copyright:: Copyright (c) 2024-2025 Yegor Bugayenko
29
+ # License:: MIT
30
+ class TestMeta < Minitest::Test
31
+ def test_exists
32
+ t = Factbase::Term.new(Factbase.new, :exists, [:foo])
33
+ assert(t.evaluate(fact('foo' => 41), []))
34
+ refute(t.evaluate(fact('bar' => 41), []))
35
+ end
36
+
37
+ def test_absent
38
+ t = Factbase::Term.new(Factbase.new, :absent, [:foo])
39
+ refute(t.evaluate(fact('foo' => 41), []))
40
+ assert(t.evaluate(fact('bar' => 41), []))
41
+ end
42
+
43
+ def test_size
44
+ t = Factbase::Term.new(Factbase.new, :size, [:foo])
45
+ assert_equal(1, t.evaluate(fact('foo' => 41), []))
46
+ assert_equal(0, t.evaluate(fact('foo' => nil), []))
47
+ assert_equal(4, t.evaluate(fact('foo' => [1, 2, 3, 4]), []))
48
+ assert_equal(0, t.evaluate(fact('foo' => []), []))
49
+ assert_equal(1, t.evaluate(fact('foo' => ''), []))
50
+ end
51
+
52
+ def test_type
53
+ t = Factbase::Term.new(Factbase.new, :type, [:foo])
54
+ assert_equal('nil', t.evaluate(fact('foo' => nil), []))
55
+ assert_equal('Integer', t.evaluate(fact('foo' => [1]), []))
56
+ assert_equal('Array', t.evaluate(fact('foo' => [1, 2]), []))
57
+ assert_equal('String', t.evaluate(fact('foo' => 'bar'), []))
58
+ assert_equal('Float', t.evaluate(fact('foo' => 2.1), []))
59
+ assert_equal('Time', t.evaluate(fact('foo' => Time.now), []))
60
+ end
61
+
62
+ def test_nil
63
+ t = Factbase::Term.new(Factbase.new, :nil, [:foo])
64
+ assert(t.evaluate(fact('foo' => nil), []))
65
+ refute(t.evaluate(fact('foo' => true), []))
66
+ refute(t.evaluate(fact('foo' => 'bar'), []))
67
+ end
68
+
69
+ def test_many
70
+ t = Factbase::Term.new(Factbase.new, :many, [:foo])
71
+ refute(t.evaluate(fact('foo' => nil), []))
72
+ refute(t.evaluate(fact('foo' => 1), []))
73
+ refute(t.evaluate(fact('foo' => '1234'), []))
74
+ assert(t.evaluate(fact('foo' => [1, 3, 5]), []))
75
+ refute(t.evaluate(fact('foo' => []), []))
76
+ end
77
+
78
+ def test_one
79
+ t = Factbase::Term.new(Factbase.new, :one, [:foo])
80
+ assert(t.evaluate(fact('foo' => 1), []))
81
+ assert(t.evaluate(fact('foo' => '1234'), []))
82
+ assert(t.evaluate(fact('foo' => [1]), []))
83
+ refute(t.evaluate(fact('foo' => nil), []))
84
+ refute(t.evaluate(fact('foo' => [1, 3, 5]), []))
85
+ refute(t.evaluate(fact('foo' => []), []))
86
+ end
87
+ end
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright (c) 2024-2025 Yegor Bugayenko
4
+ #
5
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ # of this software and associated documentation files (the 'Software'), to deal
7
+ # in the Software without restriction, including without limitation the rights
8
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ # copies of the Software, and to permit persons to whom the Software is
10
+ # furnished to do so, subject to the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be included in all
13
+ # copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFINGEMENT. IN NO EVENT SHALL THE
18
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ # SOFTWARE.
22
+
23
+ require 'minitest/autorun'
24
+ require_relative '../../../lib/factbase/term'
25
+
26
+ # Ordering test.
27
+ # Author:: Yegor Bugayenko (yegor256@gmail.com)
28
+ # Copyright:: Copyright (c) 2024-2025 Yegor Bugayenko
29
+ # License:: MIT
30
+ class TestOrdering < Minitest::Test
31
+ def test_prev
32
+ t = Factbase::Term.new(Factbase.new, :prev, [:foo])
33
+ assert_nil(t.evaluate(fact('foo' => 41), []))
34
+ assert_equal([41], t.evaluate(fact('foo' => 5), []))
35
+ assert_equal([5], t.evaluate(fact('foo' => 6), []))
36
+ end
37
+
38
+ def test_unique
39
+ t = Factbase::Term.new(Factbase.new, :unique, [:foo])
40
+ refute(t.evaluate(fact, []))
41
+ assert(t.evaluate(fact('foo' => 41), []))
42
+ refute(t.evaluate(fact('foo' => 41), []))
43
+ assert(t.evaluate(fact('foo' => 1), []))
44
+ end
45
+ end
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # Copyright (c) 2024 Yegor Bugayenko
3
+ # Copyright (c) 2024-2025 Yegor Bugayenko
4
4
  #
5
5
  # Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  # of this software and associated documentation files (the 'Software'), to deal
@@ -25,29 +25,29 @@ require_relative '../../../lib/factbase/term'
25
25
 
26
26
  # Strings test.
27
27
  # Author:: Yegor Bugayenko (yegor256@gmail.com)
28
- # Copyright:: Copyright (c) 2024 Yegor Bugayenko
28
+ # Copyright:: Copyright (c) 2024-2025 Yegor Bugayenko
29
29
  # License:: MIT
30
30
  class TestStrings < Minitest::Test
31
31
  def test_regexp_matching
32
- t = Factbase::Term.new(:matches, [:foo, '[a-z]+'])
32
+ t = Factbase::Term.new(Factbase.new, :matches, [:foo, '[a-z]+'])
33
33
  assert(t.evaluate(fact('foo' => 'hello'), []))
34
34
  assert(t.evaluate(fact('foo' => 'hello 42'), []))
35
- assert(!t.evaluate(fact('foo' => 42), []))
35
+ refute(t.evaluate(fact('foo' => 42), []))
36
36
  end
37
37
 
38
38
  def test_concat
39
- t = Factbase::Term.new(:concat, [42, 'hi', 3.14, :hey, Time.now])
39
+ t = Factbase::Term.new(Factbase.new, :concat, [42, 'hi', 3.14, :hey, Time.now])
40
40
  s = t.evaluate(fact, [])
41
- assert(s.start_with?('42hi3.14'), s)
41
+ assert(s.start_with?('42hi3.14'))
42
42
  end
43
43
 
44
44
  def test_concat_empty
45
- t = Factbase::Term.new(:concat, [])
45
+ t = Factbase::Term.new(Factbase.new, :concat, [])
46
46
  assert_equal('', t.evaluate(fact, []))
47
47
  end
48
48
 
49
49
  def test_sprintf
50
- t = Factbase::Term.new(:sprintf, ['hi, %s!', 'Jeff'])
50
+ t = Factbase::Term.new(Factbase.new, :sprintf, ['hi, %s!', 'Jeff'])
51
51
  assert_equal('hi, Jeff!', t.evaluate(fact, []))
52
52
  end
53
53
  end
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # Copyright (c) 2024 Yegor Bugayenko
3
+ # Copyright (c) 2024-2025 Yegor Bugayenko
4
4
  #
5
5
  # Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  # of this software and associated documentation files (the 'Software'), to deal
@@ -26,24 +26,24 @@ require_relative '../../../lib/factbase/term'
26
26
 
27
27
  # System test.
28
28
  # Author:: Yegor Bugayenko (yegor256@gmail.com)
29
- # Copyright:: Copyright (c) 2024 Yegor Bugayenko
29
+ # Copyright:: Copyright (c) 2024-2025 Yegor Bugayenko
30
30
  # License:: MIT
31
31
  class TestSystem < Minitest::Test
32
32
  def test_env
33
33
  ENV.store('FOO', 'bar')
34
- t = Factbase::Term.new(:env, ['FOO', ''])
34
+ t = Factbase::Term.new(Factbase.new, :env, ['FOO', ''])
35
35
  assert_equal('bar', t.evaluate(fact, []))
36
36
  end
37
37
 
38
38
  def test_default
39
39
  ENV.delete('FOO')
40
- t = Factbase::Term.new(:env, ['FOO', 'мой друг'])
40
+ t = Factbase::Term.new(Factbase.new, :env, ['FOO', 'мой друг'])
41
41
  assert_equal('мой друг', t.evaluate(fact, []))
42
42
  end
43
43
 
44
44
  def test_when_default_is_absent
45
45
  ENV.delete('FOO')
46
- t = Factbase::Term.new(:env, ['FOO'])
47
- assert_raises { t.evaluate(fact, []) }
46
+ t = Factbase::Term.new(Factbase.new, :env, ['FOO'])
47
+ assert_raises(StandardError) { t.evaluate(fact, []) }
48
48
  end
49
49
  end
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # Copyright (c) 2024 Yegor Bugayenko
3
+ # Copyright (c) 2024-2025 Yegor Bugayenko
4
4
  #
5
5
  # Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  # of this software and associated documentation files (the 'Software'), to deal
@@ -27,23 +27,23 @@ require_relative '../../lib/factbase/fact'
27
27
 
28
28
  # Accum test.
29
29
  # Author:: Yegor Bugayenko (yegor256@gmail.com)
30
- # Copyright:: Copyright (c) 2024 Yegor Bugayenko
30
+ # Copyright:: Copyright (c) 2024-2025 Yegor Bugayenko
31
31
  # License:: MIT
32
32
  class TestAccum < Minitest::Test
33
33
  def test_holds_props
34
34
  map = {}
35
- f = Factbase::Fact.new(Mutex.new, map)
35
+ f = Factbase::Fact.new(Factbase.new, Mutex.new, map)
36
36
  props = {}
37
37
  a = Factbase::Accum.new(f, props, false)
38
38
  a.foo = 42
39
- assert_raises { f.foo }
39
+ assert_raises(StandardError) { f.foo }
40
40
  assert_equal(42, a.foo)
41
41
  assert_equal([42], props['foo'])
42
42
  end
43
43
 
44
44
  def test_passes_props
45
45
  map = {}
46
- f = Factbase::Fact.new(Mutex.new, map)
46
+ f = Factbase::Fact.new(Factbase.new, Mutex.new, map)
47
47
  props = {}
48
48
  a = Factbase::Accum.new(f, props, true)
49
49
  a.foo = 42
@@ -54,7 +54,7 @@ class TestAccum < Minitest::Test
54
54
 
55
55
  def test_appends_props
56
56
  map = {}
57
- f = Factbase::Fact.new(Mutex.new, map)
57
+ f = Factbase::Fact.new(Factbase.new, Mutex.new, map)
58
58
  f.foo = 42
59
59
  props = {}
60
60
  a = Factbase::Accum.new(f, props, false)
@@ -63,14 +63,14 @@ class TestAccum < Minitest::Test
63
63
  end
64
64
 
65
65
  def test_empties
66
- f = Factbase::Fact.new(Mutex.new, {})
66
+ f = Factbase::Fact.new(Factbase.new, Mutex.new, {})
67
67
  a = Factbase::Accum.new(f, {}, false)
68
- assert(a['foo'].nil?)
68
+ assert_nil(a['foo'])
69
69
  end
70
70
 
71
71
  def test_prints_to_string
72
72
  map = {}
73
- f = Factbase::Fact.new(Mutex.new, map)
73
+ f = Factbase::Fact.new(Factbase.new, Mutex.new, map)
74
74
  props = {}
75
75
  a = Factbase::Accum.new(f, props, true)
76
76
  a.foo = 42