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,113 +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/rules'
9
- require_relative '../../lib/factbase/pre'
10
-
11
- # Test.
12
- # Author:: Yegor Bugayenko (yegor256@gmail.com)
13
- # Copyright:: Copyright (c) 2024-2025 Yegor Bugayenko
14
- # License:: MIT
15
- class TestRules < Factbase::Test
16
- def test_simple_checking
17
- fb = Factbase::Rules.new(
18
- Factbase.new,
19
- '(when (exists first) (exists second))'
20
- )
21
- f1 = fb.insert
22
- f1.second = 2
23
- f1.first = 1
24
- f2 = fb.insert
25
- assert_raises(StandardError) do
26
- f2.first = 1
27
- end
28
- end
29
-
30
- def test_check_with_id
31
- fb = Factbase::Rules.new(Factbase.new, '(exists foo)', uid: 'id')
32
- fb.txn do |fbt|
33
- f = fbt.insert
34
- f.foo = 42
35
- end
36
- end
37
-
38
- def test_to_string
39
- fb = Factbase::Rules.new(
40
- Factbase.new,
41
- '(when (exists a) (exists b))'
42
- )
43
- f = fb.insert
44
- f.foo = 42
45
- s = f.to_s
46
- assert_predicate(s.length, :positive?, s)
47
- assert_equal('[ foo: [42] ]', s)
48
- end
49
-
50
- def test_query_one
51
- fb = Factbase::Rules.new(Factbase.new, '(always)')
52
- f = fb.insert
53
- f.foo = 42
54
- assert_equal(1, fb.query('(agg (eq foo $v) (count))').one(Factbase.new, v: 42))
55
- end
56
-
57
- def test_check_only_when_txn_is_closed
58
- fb = Factbase::Rules.new(Factbase.new, '(when (exists a) (exists b))')
59
- ok = false
60
- assert_raises(StandardError) do
61
- fb.txn do |fbt|
62
- f = fbt.insert
63
- f.a = 1
64
- f.c = 2
65
- ok = true
66
- end
67
- end
68
- assert(ok)
69
- end
70
-
71
- def test_rollback_on_violation
72
- fb = Factbase::Rules.new(Factbase.new, '(when (exists a) (exists b))')
73
- assert_raises(StandardError) do
74
- fb.txn do |fbt|
75
- f = fbt.insert
76
- f.a = 1
77
- f.c = 2
78
- end
79
- end
80
- assert_equal(0, fb.size)
81
- end
82
-
83
- def test_defends_against_id_duplicates
84
- fb = Factbase::Rules.new(Factbase.new, '(always)', uid: 'id')
85
- assert_raises(StandardError) do
86
- fb.txn do |fbt|
87
- fbt.insert.then do |f|
88
- f.id = 1
89
- f.id = 2
90
- end
91
- end
92
- end
93
- end
94
-
95
- def test_in_combination_with_pre
96
- fb = Factbase::Rules.new(Factbase.new, '(when (exists a) (exists b))')
97
- fb =
98
- Factbase::Pre.new(fb) do |f|
99
- f.hello = 42
100
- end
101
- ok = false
102
- assert_raises(StandardError) do
103
- fb.txn do |fbt|
104
- f = fbt.insert
105
- f.a = 1
106
- f.c = 2
107
- ok = true
108
- end
109
- end
110
- assert(ok)
111
- assert_equal(0, fb.query('(eq hello $v)').each(v: 42).to_a.size)
112
- end
113
- end
@@ -1,166 +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/syntax'
8
-
9
- # Syntax test.
10
- # Author:: Yegor Bugayenko (yegor256@gmail.com)
11
- # Copyright:: Copyright (c) 2024-2025 Yegor Bugayenko
12
- # License:: MIT
13
- class TestSyntax < Factbase::Test
14
- def test_parses_string_right
15
- [
16
- "(foo 'abc')",
17
- "(foo 'one two')",
18
- "(foo 'one two three ')",
19
- "(foo 'one two three ' 'tail tail')"
20
- ].each do |q|
21
- assert_equal(q, Factbase::Syntax.new(q).to_term.to_s, q)
22
- end
23
- end
24
-
25
- def test_makes_abstract_terms
26
- {
27
- '(foo $bar)' => true,
28
- '(foo (bar (a (b c (f $bar)))))' => true,
29
- '(foo (bar (a (b c (f bar)))))' => false
30
- }.each do |q, a|
31
- assert_equal(a, Factbase::Syntax.new(q).to_term.abstract?)
32
- end
33
- end
34
-
35
- def test_makes_static_terms
36
- {
37
- '(foo bar)' => false,
38
- '(foo "bar")' => true,
39
- '(agg (always) (max id))' => true
40
- }.each do |q, a|
41
- assert_equal(a, Factbase::Syntax.new(q).to_term.static?)
42
- end
43
- end
44
-
45
- def test_simple_parsing
46
- [
47
- '(foo)',
48
- '(foo (bar) (zz 77) ) # hey',
49
- "# hello\n\n\n(foo ($bar))",
50
- "(eq foo \n\n 'Hello, world!'\n)\n",
51
- "(eq x 'Hello, \\' \n) \\' ( world!')",
52
- "# this is a comment\n(eq foo # test\n 42)\n\n# another comment\n",
53
- "(foo 'Hello,\n\nworld!\r\t\n')\n",
54
- "(or ( a 4) (b 5) (always) (and (always) (c 5) \t\t(r 7 w8s w8is 'Foo')))"
55
- ].each do |q|
56
- refute_nil(Factbase::Syntax.new(q).to_term)
57
- end
58
- end
59
-
60
- def test_exact_parsing
61
- [
62
- '(foo)',
63
- '(foo 7)',
64
- "(foo 7 'Dude')",
65
- "(r 'Dude\\'s Friend')",
66
- "(r 'I\\'m \\\"good\\\"')",
67
- '(foo x y z)',
68
- "(foo x y z t f 42 'Hi!# you' 33)",
69
- '(foo (x) y z)',
70
- '(eq t 2024-05-25T19:43:48Z)',
71
- '(eq t 2024-05-25T19:43:48Z)',
72
- '(eq t 3.1415926)',
73
- '(eq t 3.0e+21)',
74
- "(foo (x (f (t (y 42 'Hey you'))) (never) (r 3)) y z)"
75
- ].each do |q|
76
- assert_equal(q, Factbase::Syntax.new(q).to_term.to_s, q)
77
- end
78
- end
79
-
80
- def test_simple_matching
81
- m = {
82
- 'foo' => ['Hello, world!'],
83
- 'bar' => [42],
84
- 'z' => [1, 2, 3, 4]
85
- }
86
- {
87
- '(eq z 1)' => true,
88
- '(or (eq bar 888) (eq z 1))' => true,
89
- "(or (gt bar 100) (eq foo 'Hello, world!'))" => true
90
- }.each do |k, v|
91
- assert_equal(v, Factbase::Syntax.new(k).to_term.evaluate(m, [], Factbase.new), k)
92
- end
93
- end
94
-
95
- def test_broken_syntax
96
- [
97
- '',
98
- '()',
99
- '(foo',
100
- '(foo $)',
101
- '(foo 1) (bar 2)',
102
- 'some text',
103
- '"hello, world!',
104
- '(foo 7',
105
- "(foo 7 'Dude'",
106
- '(foo x y z (',
107
- '(bad-term-name 42)',
108
- '(foo x y (z t (f 42 ',
109
- ')foo ) y z)',
110
- '(x "")',
111
- ")y 42 'Hey you)",
112
- ')',
113
- '"'
114
- ].each do |q|
115
- msg = assert_raises(q) do
116
- Factbase::Syntax.new(q).to_term
117
- end.message
118
- assert_includes(msg, q, msg)
119
- end
120
- end
121
-
122
- def test_raises_on_broken_syntax
123
- 100.times do
124
- q = [
125
- '(', ')', '#test', '$foo', '%what',
126
- '"hello"', '42', '+', '?', '!', '\"',
127
- '\'', 'привет'
128
- ].shuffle.join(' . ')
129
- assert_raises(Factbase::Syntax::Broken, q) do
130
- Factbase::Syntax.new(q).to_term
131
- end
132
- end
133
- end
134
-
135
- def test_simplification
136
- {
137
- '(foo)' => '(foo)',
138
- '(and (foo) (foo))' => '(foo)',
139
- '(and (foo) (or (and (eq a 1))) (eq a 1) (foo))' => '(and (foo) (eq a 1))'
140
- }.each do |s, t|
141
- assert_equal(t, Factbase::Syntax.new(s).to_term.to_s)
142
- end
143
- end
144
-
145
- def test_fails_when_term_is_not_a_class
146
- assert_raises(StandardError) { Factbase::Syntax.new('(foo 1)', term: 'hello') }
147
- end
148
-
149
- def test_fails_when_term_is_wrong_class
150
- assert_raises(StandardError) { Factbase::Syntax.new('(bar 1)', term: String).to_term }
151
- end
152
-
153
- def test_fails_when_term_is_incorrectly_defined_class
154
- assert_includes(
155
- assert_raises(StandardError) { Factbase::Syntax.new('(bar 1)', term: FakeTerm).to_term }.message,
156
- 'wrong number of arguments'
157
- )
158
- end
159
-
160
- class FakeTerm < Factbase::Term
161
- def initialize(invalid)
162
- super
163
- @x = invalid
164
- end
165
- end
166
- end
@@ -1,81 +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 'threads'
8
- require_relative '../../lib/factbase'
9
- require_relative '../../lib/factbase/tallied'
10
-
11
- # Test.
12
- # Author:: Yegor Bugayenko (yegor256@gmail.com)
13
- # Copyright:: Copyright (c) 2024-2025 Yegor Bugayenko
14
- # License:: MIT
15
- class TestTallied < Factbase::Test
16
- def test_counts_size
17
- fb = Factbase::Tallied.new(Factbase.new)
18
- assert_equal(0, fb.size)
19
- end
20
-
21
- def test_queries_empty_factbase
22
- fb = Factbase::Tallied.new(Factbase.new)
23
- assert_equal(0, fb.query('(gt foo 1)').each.to_a.size)
24
- end
25
-
26
- def test_counts_simple_changes
27
- fb = Factbase::Tallied.new(Factbase.new)
28
- fb.insert.bar = 3
29
- fb.query('(exists bar)').each do |f|
30
- f.foo = 42
31
- end
32
- assert_equal(1, fb.churn.inserted)
33
- assert_equal(0, fb.churn.deleted)
34
- assert_equal(2, fb.churn.added)
35
- end
36
-
37
- def test_counts_in_one
38
- fb = Factbase::Tallied.new(Factbase.new)
39
- fb.insert.bar = 3
40
- assert_equal(1, fb.query('(agg (eq bar 3) (count))').one)
41
- assert_equal(1, fb.churn.added)
42
- end
43
-
44
- def test_returns_all_props
45
- fb = Factbase::Tallied.new(Factbase.new)
46
- f = fb.insert
47
- f.bar = 3
48
- assert_includes(f.all_properties, 'bar')
49
- end
50
-
51
- def test_counts_in_txn
52
- fb = Factbase::Tallied.new(Factbase.new)
53
- fb.txn do |fbt|
54
- fbt.insert.boom = 3
55
- fbt.query('(exists boom)').each do |f|
56
- f.foo = 88
57
- end
58
- end
59
- assert_equal(1, fb.churn.inserted)
60
- assert_equal(0, fb.churn.deleted)
61
- assert_equal(2, fb.churn.added)
62
- end
63
-
64
- def test_counts_in_txn_in_threads
65
- fb = Factbase::Tallied.new(Factbase.new)
66
- t = 5
67
- Threads.new(t).assert do |i|
68
- fb.txn do |fbt|
69
- fbt.insert.x = i
70
- fbt.query("(eq x #{i})").each do |f|
71
- f.send(:"a#{i}=", i)
72
- end
73
- fbt.query("(lt x #{t + 1})").delete!
74
- end
75
- end
76
- assert_equal(0, fb.size)
77
- assert_equal(t, fb.churn.inserted)
78
- assert_equal(t, fb.churn.deleted)
79
- assert_equal(t * 2, fb.churn.added)
80
- end
81
- end
@@ -1,72 +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/taped'
9
-
10
- # Test.
11
- # Author:: Yegor Bugayenko (yegor256@gmail.com)
12
- # Copyright:: Copyright (c) 2024-2025 Yegor Bugayenko
13
- # License:: MIT
14
- class TestTaped < Factbase::Test
15
- def test_tracks_insertion
16
- t = Factbase::Taped.new([])
17
- t << {}
18
- assert_equal(1, t.inserted.size)
19
- end
20
-
21
- def test_joins_with_empty
22
- t = Factbase::Taped.new([{ foo: 'yes' }])
23
- t &= []
24
- assert_equal(0, t.size)
25
- end
26
-
27
- def test_disjoins_with_empty
28
- t = Factbase::Taped.new([{ bar: 'oops' }])
29
- t |= []
30
- assert_equal(1, t.size)
31
- end
32
-
33
- def test_tracks_deletion
34
- t = Factbase::Taped.new([{ x: 1 }, { x: 2 }])
35
- t.delete_if { |m| m[:x] == 1 }
36
- assert_equal(1, t.deleted.size)
37
- end
38
-
39
- def test_tracks_addition
40
- h = { f: 5 }
41
- t = Factbase::Taped.new([h])
42
- t.each do |m|
43
- m[:bar] = 66
44
- end
45
- assert_equal(1, t.added.size)
46
- assert_equal(h.object_id, t.added.first)
47
- end
48
-
49
- def test_tracks_addition_uniquely
50
- h = { f: 5 }
51
- t = Factbase::Taped.new([h])
52
- t.each do |m|
53
- m[:bar] = 66
54
- m[:foo] = 77
55
- end
56
- assert_equal(1, t.added.size)
57
- end
58
-
59
- def test_tracks_factbase
60
- t = Factbase::Taped.new([])
61
- fb = Factbase.new(t)
62
- fb.insert
63
- fb.query('(always)').each do |f|
64
- f.foo = 42
65
- f.foo = 5
66
- end
67
- fb.query('(always)').delete!
68
- assert_equal(1, t.inserted.size)
69
- assert_equal(1, t.added.size)
70
- assert_equal(1, t.deleted.size)
71
- end
72
- end
@@ -1,85 +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/accum'
9
- require_relative '../../lib/factbase/tee'
10
- require_relative '../../lib/factbase/fact'
11
-
12
- def global_function_for_test_only(foo)
13
- raise foo
14
- end
15
-
16
- # Tee test.
17
- # Author:: Yegor Bugayenko (yegor256@gmail.com)
18
- # Copyright:: Copyright (c) 2024-2025 Yegor Bugayenko
19
- # License:: MIT
20
- class TestTee < Factbase::Test
21
- def test_two_facts
22
- prim = Factbase::Fact.new({})
23
- prim.foo = 42
24
- upper = Factbase::Fact.new({})
25
- upper.bar = 13
26
- t = Factbase::Tee.new(prim, upper)
27
- assert_equal(42, t.foo)
28
- assert_equal([13], t['$bar'])
29
- end
30
-
31
- def test_no_trip_to_prim_if_not_found
32
- prim = Factbase::Fact.new({})
33
- prim.foo = 777
34
- t = Factbase::Tee.new(prim, Factbase::Fact.new({}))
35
- assert_nil(t['$foo'])
36
- end
37
-
38
- def test_fetches_simply
39
- t = Factbase::Accum.new(
40
- Factbase::Tee.new(
41
- Factbase::Fact.new({ 'foo_bar' => [987] }),
42
- Factbase::Fact.new({})
43
- ),
44
- {}, true
45
- )
46
- assert_equal(987, t.foo_bar)
47
- end
48
-
49
- def test_fetches_without_conflict_with_global_name
50
- t = Factbase::Tee.new(
51
- Factbase::Fact.new({ 'global_function_for_test_only' => [2] }),
52
- Factbase::Fact.new({})
53
- )
54
- assert_equal(2, t.global_function_for_test_only)
55
- end
56
-
57
- def test_all_properties
58
- prim = Factbase::Fact.new({})
59
- prim.foo = 42
60
- upper = Factbase::Fact.new({})
61
- upper.bar = 13
62
- t = Factbase::Tee.new(prim, upper)
63
- assert_includes(t.all_properties, 'foo')
64
- assert_includes(t.all_properties, 'bar')
65
- end
66
-
67
- def test_recursively
68
- map = {}
69
- prim = Factbase::Fact.new(map)
70
- prim.foo = 42
71
- t = Factbase::Tee.new(Factbase::Fact.new({}), { 'bar' => [7] })
72
- assert_equal([7], t['$bar'])
73
- t = Factbase::Tee.new(prim, t)
74
- assert_equal([7], t['$bar'])
75
- end
76
-
77
- def test_prints_to_string
78
- prim = Factbase::Fact.new({})
79
- prim.foo = 42
80
- upper = Factbase::Fact.new({})
81
- upper.bar = 13
82
- t = Factbase::Tee.new(prim, upper)
83
- assert_equal('[ foo: [42] ]', t.to_s)
84
- end
85
- end
@@ -1,87 +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/term'
9
-
10
- # Term test.
11
- # Author:: Yegor Bugayenko (yegor256@gmail.com)
12
- # Copyright:: Copyright (c) 2024-2025 Yegor Bugayenko
13
- # License:: MIT
14
- class TestTerm < Factbase::Test
15
- def test_false_matching
16
- t = Factbase::Term.new(:never, [])
17
- refute(t.evaluate(fact('foo' => [100]), [], Factbase.new))
18
- end
19
-
20
- def test_size_matching
21
- t = Factbase::Term.new(:size, [:foo])
22
- assert_equal(3, t.evaluate(fact('foo' => [42, 12, -90]), [], Factbase.new))
23
- assert_equal(0, t.evaluate(fact('bar' => 100), [], Factbase.new))
24
- end
25
-
26
- def test_exists_matching
27
- t = Factbase::Term.new(:exists, [:foo])
28
- assert(t.evaluate(fact('foo' => [42, 12, -90]), [], Factbase.new))
29
- refute(t.evaluate(fact('bar' => 100), [], Factbase.new))
30
- end
31
-
32
- def test_absent_matching
33
- t = Factbase::Term.new(:absent, [:foo])
34
- assert(t.evaluate(fact('z' => [42, 12, -90]), [], Factbase.new))
35
- refute(t.evaluate(fact('foo' => 100), [], Factbase.new))
36
- end
37
-
38
- def test_type_matching
39
- t = Factbase::Term.new(:type, [:foo])
40
- assert_equal('Integer', t.evaluate(fact('foo' => 42), [], Factbase.new))
41
- assert_equal('Integer', t.evaluate(fact('foo' => [42]), [], Factbase.new))
42
- assert_equal('Array', t.evaluate(fact('foo' => [1, 2, 3]), [], Factbase.new))
43
- assert_equal('String', t.evaluate(fact('foo' => 'Hello, world!'), [], Factbase.new))
44
- assert_equal('Float', t.evaluate(fact('foo' => 3.14), [], Factbase.new))
45
- assert_equal('Time', t.evaluate(fact('foo' => Time.now), [], Factbase.new))
46
- assert_equal('Integer', t.evaluate(fact('foo' => 1_000_000_000_000_000), [], Factbase.new))
47
- assert_equal('nil', t.evaluate(fact, [], Factbase.new))
48
- end
49
-
50
- def test_past
51
- t = Factbase::Term.new(:prev, [:foo])
52
- assert_nil(t.evaluate(fact('foo' => 4), [], Factbase.new))
53
- assert_equal([4], t.evaluate(fact('foo' => 5), [], Factbase.new))
54
- end
55
-
56
- def test_at
57
- t = Factbase::Term.new(:at, [1, :foo])
58
- assert_nil(t.evaluate(fact('foo' => 4), [], Factbase.new))
59
- assert_equal(5, t.evaluate(fact('foo' => [4, 5]), [], Factbase.new))
60
- end
61
-
62
- def test_report_missing_term
63
- t = Factbase::Term.new(:something, [])
64
- msg = assert_raises(StandardError) do
65
- t.evaluate(fact, [], Factbase.new)
66
- end.message
67
- assert_includes(msg, 'not defined at (something)', msg)
68
- end
69
-
70
- def test_report_other_error
71
- t = Factbase::Term.new(:at, [])
72
- msg = assert_raises(StandardError) do
73
- t.evaluate(fact, [], Factbase.new)
74
- end.message
75
- assert_includes(msg, 'at (at)', msg)
76
- end
77
-
78
- def test_redresses_itself
79
- t = Factbase::Term.new(:something, [])
80
- require_relative '../../lib/factbase/indexed/indexed_term'
81
- t.redress!(Factbase::IndexedTerm)
82
- require_relative '../../lib/factbase/cached/cached_term'
83
- t.redress!(Factbase::CachedTerm)
84
- assert_kind_of(Factbase::CachedTerm, t)
85
- refute_kind_of(Factbase::CachedTerm, Factbase::Term.new(:something, []))
86
- end
87
- end
@@ -1,35 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- # SPDX-FileCopyrightText: Copyright (c) 2024-2025 Yegor Bugayenko
4
- # SPDX-License-Identifier: MIT
5
-
6
- require_relative '../test__helper'
7
- require 'loog'
8
- require_relative '../../lib/factbase'
9
- require_relative '../../lib/factbase/to_json'
10
-
11
- # Test.
12
- # Author:: Yegor Bugayenko (yegor256@gmail.com)
13
- # Copyright:: Copyright (c) 2024-2025 Yegor Bugayenko
14
- # License:: MIT
15
- class TestToJSON < Factbase::Test
16
- def test_simple_rendering
17
- fb = Factbase.new
18
- f = fb.insert
19
- f.foo = 42
20
- f.foo = 256
21
- to = Factbase::ToJSON.new(fb)
22
- json = JSON.parse(to.json)
23
- assert_equal(256, json[0]['foo'][1])
24
- end
25
-
26
- def test_sort_keys
27
- fb = Factbase.new
28
- f = fb.insert
29
- f.c = 42
30
- f.b = 1
31
- f.a = 256
32
- json = Factbase::ToJSON.new(fb).json
33
- assert_includes(json, '{"a":256,"b":1,"c":42}', json)
34
- end
35
- end