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,30 +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_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
@@ -1,63 +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_relative '../../../lib/factbase/term'
8
- require_relative '../../../lib/factbase/syntax'
9
-
10
- # Aggregates test.
11
- # Author:: Yegor Bugayenko (yegor256@gmail.com)
12
- # Copyright:: Copyright (c) 2024-2025 Yegor Bugayenko
13
- # License:: MIT
14
- class TestAggregates < Factbase::Test
15
- def test_aggregation
16
- maps = [
17
- { 'x' => [1], 'y' => [0], 'z' => [4] },
18
- { 'x' => [2], 'y' => [42], 'z' => [3] },
19
- { 'x' => [3], 'y' => [42], 'z' => [5] },
20
- { 'x' => [4], 'y' => [42], 'z' => [2] },
21
- { 'x' => [5], 'y' => [42], 'z' => [1] },
22
- { 'x' => [8], 'y' => [0], 'z' => [6] }
23
- ]
24
- {
25
- '(eq x (agg (eq y 42) (min x)))' => '(eq x 2)',
26
- '(eq z (agg (eq y 0) (max z)))' => '(eq x 8)',
27
- '(eq x (agg (and (eq y 42) (gt z 1)) (max x)))' => '(eq x 4)',
28
- '(and (eq x (agg (eq y 42) (min x))) (eq z 3))' => '(eq x 2)',
29
- '(eq x (agg (eq y 0) (nth 0 x)))' => '(eq x 1)',
30
- '(eq x (agg (eq y 0) (first x)))' => '(eq x 1)',
31
- '(agg (eq foo 42) (always))' => '(eq x 1)'
32
- }.each do |q, r|
33
- t = Factbase::Syntax.new(q).to_term
34
- f = maps.find { |m| t.evaluate(fact(m), maps, Factbase.new) }
35
- refute_nil(f, "nothing found by: #{q}")
36
- assert(Factbase::Syntax.new(r).to_term.evaluate(fact(f), [], Factbase.new))
37
- end
38
- end
39
-
40
- def test_empty
41
- maps = [
42
- { 'x' => [1], 'y' => [0], 'z' => [4] },
43
- { 'x' => [8], 'y' => [0] }
44
- ]
45
- {
46
- '(empty (eq y 42))' => true,
47
- '(empty (eq x 1))' => false
48
- }.each do |q, r|
49
- t = Factbase::Syntax.new(q).to_term
50
- assert_equal(r, t.evaluate(Factbase::Fact.new({}), maps, Factbase.new), q)
51
- end
52
- end
53
-
54
- def test_empty_with_params
55
- maps = [
56
- { 'a' => [3], 'b' => [44] },
57
- { 'a' => [4], 'b' => [55] }
58
- ]
59
- t = Factbase::Syntax.new('(empty (eq b $x))').to_term
60
- assert(t.evaluate(Factbase::Fact.new({ 'x' => [42] }), maps, Factbase.new))
61
- refute(t.evaluate(Factbase::Fact.new({ 'x' => [44] }), maps, Factbase.new))
62
- end
63
- end
@@ -1,58 +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 'loog'
7
- require_relative '../../test__helper'
8
- require_relative '../../../lib/factbase/term'
9
- require_relative '../../../lib/factbase/syntax'
10
- require_relative '../../../lib/factbase/accum'
11
-
12
- # Aliases test.
13
- # Author:: Yegor Bugayenko (yegor256@gmail.com)
14
- # Copyright:: Copyright (c) 2024-2025 Yegor Bugayenko
15
- # License:: MIT
16
- class TestAliases < Factbase::Test
17
- def test_aliases
18
- maps = [
19
- { 'x' => [1], 'y' => [0], 't1' => [Time.now], 't2' => [Time.now] },
20
- { 'x' => [2], 'y' => [42], 't' => [Time.now] }
21
- ]
22
- {
23
- '(as foo (plus x 1))' => '(exists foo)',
24
- '(as foo (plus x y))' => '(gt foo 0)',
25
- '(as foo (plus bar 1))' => '(absent foo)',
26
- '(as foo (minus t1 t2))' => '(when (exists foo) (eq "Float" (type foo)))'
27
- }.each do |q, r|
28
- t = Factbase::Syntax.new(q).to_term
29
- maps.each do |m|
30
- f = Factbase::Accum.new(fact(m), {}, false)
31
- next unless t.evaluate(f, maps, Factbase.new)
32
- assert(Factbase::Syntax.new(r).to_term.evaluate(f, [], Factbase.new), "#{q} -> #{f}")
33
- end
34
- end
35
- end
36
-
37
- def test_join
38
- maps = [
39
- { 'x' => 1, 'y' => 0, 'z' => 4 },
40
- { 'x' => [2], 'bar' => [44, 55, 66] }
41
- ]
42
- {
43
- '(join "foo_x<=x" (gt x 1))' => '(exists foo_x)',
44
- '(join "foo <=bar " (exists bar))' => '(and (eq foo 44) (eq foo 55))',
45
- '(join "uuu" (eq x 1))' => '(absent uuu)',
46
- '(join "uuu <= fff" (eq fff 1))' => '(absent uuu)'
47
- }.each do |q, r|
48
- t = Factbase::Syntax.new(q).to_term
49
- maps.each do |m|
50
- f = Factbase::Accum.new(fact(m), {}, false)
51
- require_relative '../../../lib/factbase/logged'
52
- f = Factbase::Logged::Fact.new(f, log: Loog::NULL)
53
- next unless t.evaluate(f, maps, Factbase.new)
54
- assert(Factbase::Syntax.new(r).to_term.evaluate(f, [], Factbase.new), "#{q} -> #{f} doesn't match #{r}")
55
- end
56
- end
57
- end
58
- end
@@ -1,33 +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_relative '../../../lib/factbase/term'
8
-
9
- # Math test.
10
- # Author:: Yegor Bugayenko (yegor256@gmail.com)
11
- # Copyright:: Copyright (c) 2024-2025 Yegor Bugayenko
12
- # License:: MIT
13
- class TestCasting < Factbase::Test
14
- def test_to_str
15
- t = Factbase::Term.new(:to_string, [Time.now])
16
- assert_equal('String', t.evaluate(fact, [], Factbase.new).class.to_s)
17
- end
18
-
19
- def test_to_integer
20
- t = Factbase::Term.new(:to_integer, [[42, 'hello']])
21
- assert_equal('Integer', t.evaluate(fact, [], Factbase.new).class.to_s)
22
- end
23
-
24
- def test_to_float
25
- t = Factbase::Term.new(:to_float, [[3.14, 'hello']])
26
- assert_equal('Float', t.evaluate(fact, [], Factbase.new).class.to_s)
27
- end
28
-
29
- def test_to_time
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
- end
33
- end
@@ -1,111 +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_relative '../../../lib/factbase/term'
8
-
9
- # Debug test.
10
- # Author:: Yegor Bugayenko (yegor256@gmail.com)
11
- # Copyright:: Copyright (c) 2024-2025 Yegor Bugayenko
12
- # License:: MIT
13
- class TestDebug < Factbase::Test
14
- def test_traced
15
- t = Factbase::Term.new(:traced, [Factbase::Term.new(:defn, [:test_debug, 'self.to_s'])])
16
- assert_output("(traced (defn test_debug 'self.to_s')) -> true\n") do
17
- assert(t.evaluate(fact, [], Factbase.new))
18
- end
19
- end
20
-
21
- def test_traced_raises
22
- e = assert_raises(StandardError) { Factbase::Term.new(:traced, ['foo']).evaluate(fact, [], Factbase.new) }
23
- assert_match(/A term is expected, but 'foo' provided/, e.message)
24
- end
25
-
26
- def test_traced_raises_when_too_many_args
27
- e =
28
- assert_raises(StandardError) do
29
- Factbase::Term.new(
30
- :traced,
31
- [Factbase::Term.new(:defn, [:debug, 'self.to_s']), 'something']
32
- ).evaluate(fact, [], Factbase.new)
33
- end
34
- assert_match(/Too many \(\d+\) operands for 'traced' \(\d+ expected\)/, e.message)
35
- end
36
-
37
- def test_assert_with_true_condition
38
- t = Factbase::Term.new(:assert, ['all must be positive', Factbase::Term.new(:gt, [:foo, 0])])
39
- assert(t.evaluate(fact('foo' => 5), [], Factbase.new))
40
- end
41
-
42
- def test_assert_with_false_condition
43
- t = Factbase::Term.new(:assert, ['all must be positive', Factbase::Term.new(:gt, [:foo, 0])])
44
- e =
45
- assert_raises(RuntimeError) do
46
- t.evaluate(fact('foo' => -1), [], Factbase.new)
47
- end
48
- assert_equal("all must be positive at (assert 'all must be positive' (gt foo 0))", e.message)
49
- end
50
-
51
- def test_assert_with_zero_value
52
- t = Factbase::Term.new(:assert, ['value must not be zero', Factbase::Term.new(:gt, [:foo, 0])])
53
- e =
54
- assert_raises(RuntimeError) do
55
- t.evaluate(fact('foo' => 0), [], Factbase.new)
56
- end
57
- assert_equal("value must not be zero at (assert 'value must not be zero' (gt foo 0))", e.message)
58
- end
59
-
60
- def test_assert_with_array_true_condition
61
- t = Factbase::Term.new(:assert, ['at least one positive', Factbase::Term.new(:gt, [:foo, 0])])
62
- assert(t.evaluate(fact('foo' => [1, 2, 3]), [], Factbase.new))
63
- end
64
-
65
- def test_assert_with_array_false_condition
66
- t = Factbase::Term.new(:assert, ['at least one positive', Factbase::Term.new(:gt, [:foo, 0])])
67
- e =
68
- assert_raises(RuntimeError) do
69
- t.evaluate(fact('foo' => [-1, -2, -3]), [], Factbase.new)
70
- end
71
- assert_equal("at least one positive at (assert 'at least one positive' (gt foo 0))", e.message)
72
- end
73
-
74
- def test_assert_with_mixed_array
75
- t = Factbase::Term.new(:assert, ['at least one positive', Factbase::Term.new(:gt, [:foo, 0])])
76
- assert(t.evaluate(fact('foo' => [-1, 0, 3]), [], Factbase.new))
77
- end
78
-
79
- def test_assert_raises_when_message_not_string
80
- e =
81
- assert_raises(StandardError) do
82
- Factbase::Term.new(:assert, [123, Factbase::Term.new(:gt, [:foo, 0])]).evaluate(fact, [], Factbase.new)
83
- end
84
- assert_match(/A string is expected as first argument of 'assert', but '123' provided/, e.message)
85
- end
86
-
87
- def test_assert_raises_when_second_arg_not_term
88
- e =
89
- assert_raises(StandardError) do
90
- Factbase::Term.new(:assert, %w[message not_a_term]).evaluate(fact, [], Factbase.new)
91
- end
92
- assert_match(/A term is expected as second argument of 'assert', but 'not_a_term' provided/, e.message)
93
- end
94
-
95
- def test_assert_raises_when_too_few_args
96
- e =
97
- assert_raises(StandardError) do
98
- Factbase::Term.new(:assert, ['message']).evaluate(fact, [], Factbase.new)
99
- end
100
- assert_match(/Too few \(\d+\) operands for 'assert' \(\d+ expected\)/, e.message)
101
- end
102
-
103
- def test_assert_raises_when_too_many_args
104
- e =
105
- assert_raises(StandardError) do
106
- Factbase::Term.new(:assert, ['message', Factbase::Term.new(:gt, [:foo, 0]), 'extra']).evaluate(fact, [],
107
- Factbase.new)
108
- end
109
- assert_match(/Too many \(\d+\) operands for 'assert' \(\d+ expected\)/, e.message)
110
- end
111
- end
@@ -1,48 +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_relative '../../../lib/factbase/term'
8
-
9
- # Defn test.
10
- # Author:: Yegor Bugayenko (yegor256@gmail.com)
11
- # Copyright:: Copyright (c) 2024-2025 Yegor Bugayenko
12
- # License:: MIT
13
- class TestDefn < Factbase::Test
14
- def test_defn_simple
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
- end
20
-
21
- def test_defn_again_by_mistake
22
- t = Factbase::Term.new(:defn, [:and, 'self.to_s'])
23
- assert_raises(StandardError) do
24
- t.evaluate(fact, [], Factbase.new)
25
- end
26
- end
27
-
28
- def test_defn_bad_name_by_mistake
29
- t = Factbase::Term.new(:defn, [:to_s, 'self.to_s'])
30
- assert_raises(StandardError) do
31
- t.evaluate(fact, [], Factbase.new)
32
- end
33
- end
34
-
35
- def test_defn_bad_name_spelling_by_mistake
36
- t = Factbase::Term.new(:defn, [:'some-key', 'self.to_s'])
37
- assert_raises(StandardError) do
38
- t.evaluate(fact, [], Factbase.new)
39
- end
40
- end
41
-
42
- def test_undef_simple
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
- end
48
- end
@@ -1,57 +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_relative '../../../lib/factbase/accum'
8
- require_relative '../../../lib/factbase/term'
9
- require_relative '../../../lib/factbase/syntax'
10
-
11
- # Logical test.
12
- # Author:: Yegor Bugayenko (yegor256@gmail.com)
13
- # Copyright:: Copyright (c) 2024-2025 Yegor Bugayenko
14
- # License:: MIT
15
- class TestLogical < Factbase::Test
16
- def test_not_matching
17
- t = Factbase::Term.new(:not, [Factbase::Term.new(:always, [])])
18
- refute(t.evaluate(fact('foo' => [100]), [], Factbase.new))
19
- end
20
-
21
- def test_not_eq_matching
22
- t = Factbase::Term.new(:not, [Factbase::Term.new(:eq, [:foo, 100])])
23
- assert(t.evaluate(fact('foo' => [42, 12, -90]), [], Factbase.new))
24
- refute(t.evaluate(fact('foo' => 100), [], Factbase.new))
25
- end
26
-
27
- def test_either
28
- t = Factbase::Term.new(:either, [Factbase::Term.new(:at, [5, :foo]), 42])
29
- assert_equal([42], t.evaluate(fact('foo' => 4), [], Factbase.new))
30
- end
31
-
32
- def test_or_matching
33
- t = Factbase::Term.new(
34
- :or,
35
- [
36
- Factbase::Term.new(:eq, [:foo, 4]),
37
- Factbase::Term.new(:eq, [:bar, 5])
38
- ]
39
- )
40
- assert(t.evaluate(fact('foo' => [4]), [], Factbase.new))
41
- assert(t.evaluate(fact('bar' => [5]), [], Factbase.new))
42
- refute(t.evaluate(fact('bar' => [42]), [], Factbase.new))
43
- end
44
-
45
- def test_when_matching
46
- t = Factbase::Term.new(
47
- :when,
48
- [
49
- Factbase::Term.new(:eq, [:foo, 4]),
50
- Factbase::Term.new(:eq, [:bar, 5])
51
- ]
52
- )
53
- assert(t.evaluate(fact('foo' => 4, 'bar' => 5), [], Factbase.new))
54
- refute(t.evaluate(fact('foo' => 4), [], Factbase.new))
55
- assert(t.evaluate(fact('foo' => 5, 'bar' => 5), [], Factbase.new))
56
- end
57
- end
@@ -1,122 +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_relative '../../../lib/factbase/term'
8
-
9
- # Math test.
10
- # Author:: Yegor Bugayenko (yegor256@gmail.com)
11
- # Copyright:: Copyright (c) 2024-2025 Yegor Bugayenko
12
- # License:: MIT
13
- class TestMath < Factbase::Test
14
- def test_simple
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
- end
20
-
21
- def test_zero
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
- end
29
-
30
- def test_eq
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
- end
38
-
39
- def test_eq_time
40
- 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
- end
45
-
46
- def test_lt
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
- end
53
-
54
- def test_gte
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
- end
60
-
61
- def test_lte
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
- end
67
-
68
- def test_gt
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
- end
76
-
77
- def test_lt_time
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
- end
83
-
84
- def test_gt_time
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
- end
90
-
91
- def test_plus
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
- end
96
-
97
- def test_plus_time
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
- end
102
-
103
- def test_minus
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
- end
108
-
109
- def test_minus_time
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))
114
- end
115
-
116
- def test_minus_time_singular
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))
121
- end
122
- end
@@ -1,70 +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_relative '../../../lib/factbase/term'
8
-
9
- # Meta test.
10
- # Author:: Yegor Bugayenko (yegor256@gmail.com)
11
- # Copyright:: Copyright (c) 2024-2025 Yegor Bugayenko
12
- # License:: MIT
13
- class TestMeta < Factbase::Test
14
- def test_exists
15
- t = Factbase::Term.new(:exists, [:foo])
16
- assert(t.evaluate(fact('foo' => 41), [], Factbase.new))
17
- refute(t.evaluate(fact('bar' => 41), [], Factbase.new))
18
- end
19
-
20
- def test_absent
21
- t = Factbase::Term.new(:absent, [:foo])
22
- refute(t.evaluate(fact('foo' => 41), [], Factbase.new))
23
- assert(t.evaluate(fact('bar' => 41), [], Factbase.new))
24
- end
25
-
26
- def test_size
27
- t = Factbase::Term.new(:size, [:foo])
28
- assert_equal(1, t.evaluate(fact('foo' => 41), [], Factbase.new))
29
- assert_equal(0, t.evaluate(fact('foo' => nil), [], Factbase.new))
30
- assert_equal(4, t.evaluate(fact('foo' => [1, 2, 3, 4]), [], Factbase.new))
31
- assert_equal(0, t.evaluate(fact('foo' => []), [], Factbase.new))
32
- assert_equal(1, t.evaluate(fact('foo' => ''), [], Factbase.new))
33
- end
34
-
35
- def test_type
36
- t = Factbase::Term.new(:type, [:foo])
37
- assert_equal('nil', t.evaluate(fact('foo' => nil), [], Factbase.new))
38
- assert_equal('Integer', t.evaluate(fact('foo' => [1]), [], Factbase.new))
39
- assert_equal('Array', t.evaluate(fact('foo' => [1, 2]), [], Factbase.new))
40
- assert_equal('String', t.evaluate(fact('foo' => 'bar'), [], Factbase.new))
41
- assert_equal('Float', t.evaluate(fact('foo' => 2.1), [], Factbase.new))
42
- assert_equal('Time', t.evaluate(fact('foo' => Time.now), [], Factbase.new))
43
- end
44
-
45
- def test_nil
46
- t = Factbase::Term.new(:nil, [:foo])
47
- assert(t.evaluate(fact('foo' => nil), [], Factbase.new))
48
- refute(t.evaluate(fact('foo' => true), [], Factbase.new))
49
- refute(t.evaluate(fact('foo' => 'bar'), [], Factbase.new))
50
- end
51
-
52
- def test_many
53
- t = Factbase::Term.new(:many, [:foo])
54
- refute(t.evaluate(fact('foo' => nil), [], Factbase.new))
55
- refute(t.evaluate(fact('foo' => 1), [], Factbase.new))
56
- refute(t.evaluate(fact('foo' => '1234'), [], Factbase.new))
57
- assert(t.evaluate(fact('foo' => [1, 3, 5]), [], Factbase.new))
58
- refute(t.evaluate(fact('foo' => []), [], Factbase.new))
59
- end
60
-
61
- def test_one
62
- t = Factbase::Term.new(:one, [:foo])
63
- assert(t.evaluate(fact('foo' => 1), [], Factbase.new))
64
- assert(t.evaluate(fact('foo' => '1234'), [], Factbase.new))
65
- assert(t.evaluate(fact('foo' => [1]), [], Factbase.new))
66
- refute(t.evaluate(fact('foo' => nil), [], Factbase.new))
67
- refute(t.evaluate(fact('foo' => [1, 3, 5]), [], Factbase.new))
68
- refute(t.evaluate(fact('foo' => []), [], Factbase.new))
69
- end
70
- end
@@ -1,28 +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_relative '../../../lib/factbase/term'
8
-
9
- # Ordering test.
10
- # Author:: Yegor Bugayenko (yegor256@gmail.com)
11
- # Copyright:: Copyright (c) 2024-2025 Yegor Bugayenko
12
- # License:: MIT
13
- class TestOrdering < Factbase::Test
14
- def test_prev
15
- t = Factbase::Term.new(:prev, [:foo])
16
- assert_nil(t.evaluate(fact('foo' => 41), [], Factbase.new))
17
- assert_equal([41], t.evaluate(fact('foo' => 5), [], Factbase.new))
18
- assert_equal([5], t.evaluate(fact('foo' => 6), [], Factbase.new))
19
- end
20
-
21
- def test_unique
22
- t = Factbase::Term.new(:unique, [:foo])
23
- refute(t.evaluate(fact, [], Factbase.new))
24
- assert(t.evaluate(fact('foo' => 41), [], Factbase.new))
25
- refute(t.evaluate(fact('foo' => 41), [], Factbase.new))
26
- assert(t.evaluate(fact('foo' => 1), [], Factbase.new))
27
- end
28
- end
@@ -1,36 +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_relative '../../../lib/factbase/term'
8
-
9
- # Strings test.
10
- # Author:: Yegor Bugayenko (yegor256@gmail.com)
11
- # Copyright:: Copyright (c) 2024-2025 Yegor Bugayenko
12
- # License:: MIT
13
- class TestStrings < Factbase::Test
14
- def test_regexp_matching
15
- t = Factbase::Term.new(:matches, [:foo, '[a-z]+'])
16
- assert(t.evaluate(fact('foo' => 'hello'), [], Factbase.new))
17
- assert(t.evaluate(fact('foo' => 'hello 42'), [], Factbase.new))
18
- refute(t.evaluate(fact('foo' => 42), [], Factbase.new))
19
- end
20
-
21
- def test_concat
22
- t = Factbase::Term.new(:concat, [42, 'hi', 3.14, :hey, Time.now])
23
- s = t.evaluate(fact, [], Factbase.new)
24
- assert(s.start_with?('42hi3.14'))
25
- end
26
-
27
- def test_concat_empty
28
- t = Factbase::Term.new(:concat, [])
29
- assert_equal('', t.evaluate(fact, [], Factbase.new))
30
- end
31
-
32
- def test_sprintf
33
- t = Factbase::Term.new(:sprintf, ['hi, %s!', 'Jeff'])
34
- assert_equal('hi, Jeff!', t.evaluate(fact, [], Factbase.new))
35
- end
36
- end