factbase 0.4.0 → 0.5.1

Sign up to get free protection for your applications and to get access to all the features.
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