factbase 0.15.0 → 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 (88) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile.lock +5 -5
  3. data/factbase.gemspec +4 -4
  4. data/lib/factbase/fact.rb +1 -1
  5. data/lib/factbase/fact_as_yaml.rb +10 -1
  6. data/lib/factbase/indexed/indexed_term.rb +6 -1
  7. data/lib/factbase/version.rb +1 -1
  8. metadata +7 -87
  9. data/.0pdd.yml +0 -8
  10. data/.gitattributes +0 -7
  11. data/.github/publish-benchmark.sh +0 -24
  12. data/.github/workflows/actionlint.yml +0 -25
  13. data/.github/workflows/benchmark.yml +0 -36
  14. data/.github/workflows/codecov.yml +0 -27
  15. data/.github/workflows/copyrights.yml +0 -19
  16. data/.github/workflows/markdown-lint.yml +0 -23
  17. data/.github/workflows/pdd.yml +0 -19
  18. data/.github/workflows/rake.yml +0 -28
  19. data/.github/workflows/reuse.yml +0 -19
  20. data/.github/workflows/typos.yml +0 -19
  21. data/.github/workflows/xcop.yml +0 -19
  22. data/.github/workflows/yamllint.yml +0 -19
  23. data/.gitignore +0 -11
  24. data/.pdd +0 -7
  25. data/.rubocop.yml +0 -51
  26. data/.rultor.yml +0 -27
  27. data/benchmark/bench_factbase.rb +0 -61
  28. data/benchmark/bench_large_query.rb +0 -128
  29. data/benchmark/bench_query.rb +0 -57
  30. data/benchmark/bench_taped.rb +0 -33
  31. data/fixtures/stories/agg.yml +0 -17
  32. data/fixtures/stories/always.yml +0 -16
  33. data/fixtures/stories/and.yml +0 -19
  34. data/fixtures/stories/as.yml +0 -16
  35. data/fixtures/stories/count.yml +0 -18
  36. data/fixtures/stories/empty.yml +0 -23
  37. data/fixtures/stories/eq.yml +0 -30
  38. data/fixtures/stories/gt.yml +0 -18
  39. data/fixtures/stories/join.yml +0 -22
  40. data/fixtures/stories/max.yml +0 -14
  41. data/fixtures/stories/min.yml +0 -14
  42. data/fixtures/stories/nth.yml +0 -14
  43. data/fixtures/stories/one.yml +0 -14
  44. data/fixtures/stories/or.yml +0 -18
  45. data/fixtures/stories/sprintf.yml +0 -12
  46. data/fixtures/stories/sum.yml +0 -14
  47. data/fixtures/stories/unique.yml +0 -30
  48. data/renovate.json +0 -6
  49. data/test/factbase/cached/test_cached_factbase.rb +0 -44
  50. data/test/factbase/cached/test_cached_query.rb +0 -100
  51. data/test/factbase/indexed/test_indexed_fact.rb +0 -23
  52. data/test/factbase/indexed/test_indexed_factbase.rb +0 -96
  53. data/test/factbase/indexed/test_indexed_query.rb +0 -208
  54. data/test/factbase/indexed/test_indexed_term.rb +0 -140
  55. data/test/factbase/sync/test_sync_factbase.rb +0 -22
  56. data/test/factbase/sync/test_sync_query.rb +0 -30
  57. data/test/factbase/terms/test_aggregates.rb +0 -63
  58. data/test/factbase/terms/test_aliases.rb +0 -58
  59. data/test/factbase/terms/test_casting.rb +0 -33
  60. data/test/factbase/terms/test_debug.rb +0 -111
  61. data/test/factbase/terms/test_defn.rb +0 -48
  62. data/test/factbase/terms/test_logical.rb +0 -57
  63. data/test/factbase/terms/test_math.rb +0 -122
  64. data/test/factbase/terms/test_meta.rb +0 -70
  65. data/test/factbase/terms/test_ordering.rb +0 -44
  66. data/test/factbase/terms/test_strings.rb +0 -36
  67. data/test/factbase/terms/test_system.rb +0 -31
  68. data/test/factbase/test_accum.rb +0 -74
  69. data/test/factbase/test_churn.rb +0 -41
  70. data/test/factbase/test_fact.rb +0 -108
  71. data/test/factbase/test_fact_as_yaml.rb +0 -77
  72. data/test/factbase/test_flatten.rb +0 -28
  73. data/test/factbase/test_impatient.rb +0 -176
  74. data/test/factbase/test_inv.rb +0 -44
  75. data/test/factbase/test_logged.rb +0 -155
  76. data/test/factbase/test_pre.rb +0 -35
  77. data/test/factbase/test_query.rb +0 -445
  78. data/test/factbase/test_rules.rb +0 -128
  79. data/test/factbase/test_syntax.rb +0 -166
  80. data/test/factbase/test_tallied.rb +0 -81
  81. data/test/factbase/test_taped.rb +0 -72
  82. data/test/factbase/test_tee.rb +0 -85
  83. data/test/factbase/test_term.rb +0 -87
  84. data/test/factbase/test_to_json.rb +0 -35
  85. data/test/factbase/test_to_xml.rb +0 -89
  86. data/test/factbase/test_to_yaml.rb +0 -39
  87. data/test/test__helper.rb +0 -41
  88. data/test/test_factbase.rb +0 -509
@@ -1,74 +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/fact'
10
-
11
- def global_function_for_this_test_only(foo)
12
- raise foo
13
- end
14
-
15
- # Accum test.
16
- # Author:: Yegor Bugayenko (yegor256@gmail.com)
17
- # Copyright:: Copyright (c) 2024-2025 Yegor Bugayenko
18
- # License:: MIT
19
- class TestAccum < Factbase::Test
20
- def test_holds_props
21
- map = {}
22
- f = Factbase::Fact.new(map)
23
- props = {}
24
- a = Factbase::Accum.new(f, props, false)
25
- a.foo = 42
26
- assert_raises(StandardError) { f.foo }
27
- assert_equal(42, a.foo)
28
- assert_equal([42], props['foo'])
29
- end
30
-
31
- def test_fetches_without_conflict_with_global_name
32
- t = Factbase::Accum.new(
33
- Factbase::Fact.new({ 'global_function_for_this_test_only' => [2] }),
34
- {}, true
35
- )
36
- assert_equal(2, t.global_function_for_this_test_only)
37
- end
38
-
39
- def test_passes_props
40
- map = {}
41
- f = Factbase::Fact.new(map)
42
- props = {}
43
- a = Factbase::Accum.new(f, props, true)
44
- a.foo = 42
45
- assert_equal(42, f.foo)
46
- assert_equal(42, a.foo)
47
- assert_equal([42], props['foo'])
48
- end
49
-
50
- def test_appends_props
51
- map = {}
52
- f = Factbase::Fact.new(map)
53
- f.foo = 42
54
- props = {}
55
- a = Factbase::Accum.new(f, props, false)
56
- a.foo = 55
57
- assert_equal(2, a['foo'].size)
58
- end
59
-
60
- def test_empties
61
- f = Factbase::Fact.new({})
62
- a = Factbase::Accum.new(f, {}, false)
63
- assert_nil(a['foo'])
64
- end
65
-
66
- def test_prints_to_string
67
- map = {}
68
- f = Factbase::Fact.new(map)
69
- props = {}
70
- a = Factbase::Accum.new(f, props, true)
71
- a.foo = 42
72
- assert_equal('[ foo: [42] ]', f.to_s)
73
- end
74
- end
@@ -1,41 +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/churn'
10
-
11
- # Test.
12
- # Author:: Yegor Bugayenko (yegor256@gmail.com)
13
- # Copyright:: Copyright (c) 2024-2025 Yegor Bugayenko
14
- # License:: MIT
15
- class TestChurn < Factbase::Test
16
- def test_appends
17
- c = Factbase::Churn.new
18
- c.append(1, 2, 3)
19
- assert_equal('1i/2d/3a', c.to_s)
20
- assert_equal(6, c.to_i)
21
- end
22
-
23
- def test_checks_for_zero
24
- c = Factbase::Churn.new
25
- assert_predicate(c, :zero?)
26
- end
27
-
28
- def test_makes_a_duplicate
29
- c = Factbase::Churn.new
30
- assert_predicate(c.dup, :zero?)
31
- end
32
-
33
- def test_concatenates_with_other
34
- c1 = Factbase::Churn.new
35
- c1.append(1, 6, 3)
36
- c2 = Factbase::Churn.new
37
- c2.append(3, 2, 46)
38
- c3 = c1 + c2
39
- assert_equal('4i/8d/49a', c3.to_s)
40
- end
41
- end
@@ -1,108 +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/fact'
9
-
10
- # Fact test.
11
- # Author:: Yegor Bugayenko (yegor256@gmail.com)
12
- # Copyright:: Copyright (c) 2024-2025 Yegor Bugayenko
13
- # License:: MIT
14
- class TestFact < Factbase::Test
15
- def test_injects_data_correctly
16
- map = {}
17
- f = Factbase::Fact.new(map)
18
- f.foo_bar = 1
19
- f.bar = 2
20
- f.bar = 3
21
- assert_equal(2, map.size)
22
- assert_equal([1], map['foo_bar'])
23
- assert_equal([2, 3], map['bar'])
24
- end
25
-
26
- def test_simple_resetting
27
- map = {}
28
- f = Factbase::Fact.new(map)
29
- f.foo = 42
30
- assert_equal(42, f.foo, f.to_s)
31
- f.foo = 256
32
- assert_equal(42, f.foo, f.to_s)
33
- assert_equal([42, 256], f['foo'], f.to_s)
34
- end
35
-
36
- def test_keeps_values_unique
37
- map = {}
38
- f = Factbase::Fact.new(map)
39
- f.foo = 42
40
- f.foo = 'Hello'
41
- assert_equal(2, map['foo'].size)
42
- f.foo = 42
43
- assert_equal(2, map['foo'].size)
44
- end
45
-
46
- def test_fails_when_empty
47
- f = Factbase::Fact.new({})
48
- assert_raises(StandardError) do
49
- f.something
50
- end
51
- end
52
-
53
- def test_fails_when_setting_nil
54
- f = Factbase::Fact.new({})
55
- assert_raises(StandardError) do
56
- f.foo = nil
57
- end
58
- end
59
-
60
- def test_fails_when_setting_empty
61
- f = Factbase::Fact.new({})
62
- assert_raises(StandardError) do
63
- f.foo = ''
64
- end
65
- end
66
-
67
- def test_fails_when_not_found
68
- f = Factbase::Fact.new({})
69
- f.first = 42
70
- assert_raises(StandardError) do
71
- f.second
72
- end
73
- end
74
-
75
- def test_set_by_name
76
- f = Factbase::Fact.new({})
77
- f.send(:_foo_bar=, 42)
78
- assert_equal(42, f._foo_bar, f.to_s)
79
- end
80
-
81
- def test_set_twice_same_value
82
- map = {}
83
- f = Factbase::Fact.new(map)
84
- f.foo = 42
85
- f.foo = 42
86
- assert_equal([42], map['foo'])
87
- end
88
-
89
- def test_time_in_utc
90
- f = Factbase::Fact.new({})
91
- t = Time.now
92
- f.foo = t
93
- assert_equal(t.utc, f.foo)
94
- assert_equal(t.utc.to_s, f.foo.to_s)
95
- end
96
-
97
- def test_some_names_are_prohibited
98
- f = Factbase::Fact.new({})
99
- assert_raises(StandardError) { f.to_s = 42 }
100
- assert_raises(StandardError) { f.class = 42 }
101
- end
102
-
103
- def test_get_all_properties
104
- f = Factbase::Fact.new({})
105
- f.foo = 42
106
- assert_includes(f.all_properties, 'foo')
107
- end
108
- end
@@ -1,77 +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 'yaml'
7
- require_relative '../../lib/factbase'
8
- require_relative '../../lib/factbase/fact_as_yaml'
9
- require_relative '../test__helper'
10
-
11
- # Test.
12
- # Author:: Yegor Bugayenko (yegor256@gmail.com)
13
- # Copyright:: Copyright (c) 2024-2025 Yegor Bugayenko
14
- # License:: MIT
15
- class TestFactAsYaml < Factbase::Test
16
- def test_prints_exactly
17
- fb = Factbase.new
18
- f = fb.insert
19
- f._id = 1
20
- f.foo = 42
21
- f.foo = 33
22
- f.bar = 'hello, world! how are you?'
23
- assert_equal(
24
- "_id: [1]\n" \
25
- "bar: [\"hello, world! how are you?\"]\n" \
26
- 'foo: [42, 33]',
27
- Factbase::FactAsYaml.new(f).to_s
28
- )
29
- end
30
-
31
- def test_simple_rendering
32
- fb = Factbase.new
33
- f = fb.insert
34
- f._id = 1
35
- f.foo = 42
36
- f.bar = 'hello'
37
- yaml_str = Factbase::FactAsYaml.new(f).to_s
38
- yaml = YAML.load(yaml_str)
39
- assert_equal(1, yaml['_id'][0])
40
- assert_equal('hello', yaml['bar'][0])
41
- assert_equal(42, yaml['foo'][0])
42
- end
43
-
44
- def test_multiple_values
45
- fb = Factbase.new
46
- f = fb.insert
47
- f.foo = 42
48
- f.foo = 256
49
- f.foo = 512
50
- yaml_str = Factbase::FactAsYaml.new(f).to_s
51
- yaml = YAML.load(yaml_str)
52
- assert_equal([42, 256, 512], yaml['foo'])
53
- end
54
-
55
- def test_sorted_keys
56
- fb = Factbase.new
57
- f = fb.insert
58
- f.c = 3
59
- f.a = 1
60
- f.b = 2
61
- yaml_str = Factbase::FactAsYaml.new(f).to_s
62
- assert_operator(yaml_str.index('a:'), :<, yaml_str.index('b:'))
63
- assert_operator(yaml_str.index('b:'), :<, yaml_str.index('c:'))
64
- end
65
-
66
- def test_usage_example_from_issue
67
- fb = Factbase.new
68
- f = fb.insert
69
- f._id = 1
70
- f.name = 'test'
71
- f = fb.query('(eq _id 1)').each.to_a.first
72
- yaml_str = Factbase::FactAsYaml.new(f).to_s
73
- assert(yaml_str)
74
- assert_includes(yaml_str, '_id')
75
- assert_includes(yaml_str, 'name')
76
- end
77
- 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'
8
- require_relative '../../lib/factbase/flatten'
9
-
10
- # Test.
11
- # Author:: Yegor Bugayenko (yegor256@gmail.com)
12
- # Copyright:: Copyright (c) 2024-2025 Yegor Bugayenko
13
- # License:: MIT
14
- class TestFlatten < Factbase::Test
15
- def test_mapping
16
- maps = [{ 'b' => [42], 'i' => 1 }, { 'a' => 33, 'i' => 0 }, { 'c' => %w[hey you], 'i' => 2 }]
17
- to = Factbase::Flatten.new(maps, 'i').it
18
- assert_equal(33, to[0]['a'])
19
- assert_equal(42, to[1]['b'])
20
- assert_equal(2, to[2]['c'].size)
21
- end
22
-
23
- def test_without_sorter
24
- maps = [{ 'b' => [42], 'i' => [44] }, { 'a' => 33 }]
25
- to = Factbase::Flatten.new(maps, 'i').it
26
- assert_equal(33, to[0]['a'])
27
- end
28
- end
@@ -1,176 +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/query'
9
- require_relative '../../lib/factbase/impatient'
10
-
11
- # Test.
12
- # Author:: Yegor Bugayenko (yegor256@gmail.com)
13
- # Copyright:: Copyright (c) 2024-2025 Yegor Bugayenko
14
- # License:: MIT
15
- class TestImpatient < Factbase::Test
16
- class SlowFactbase < Factbase
17
- class SlowQuery < Factbase::Query
18
- def one(fb = @fb, params = {})
19
- sleep 0.2
20
- super
21
- end
22
- end
23
-
24
- def query(term, maps = nil)
25
- maps ||= @maps
26
- term = to_term(term) if term.is_a?(String)
27
- SlowQuery.new(maps, term, self)
28
- end
29
- end
30
-
31
- class SlowDeleteFactbase < Factbase
32
- class SlowQuery < Factbase::Query
33
- def delete!(fb = @fb)
34
- sleep 0.2
35
- super
36
- end
37
- end
38
-
39
- def query(term, maps = nil)
40
- maps ||= @maps
41
- term = to_term(term) if term.is_a?(String)
42
- SlowQuery.new(maps, term, self)
43
- end
44
- end
45
-
46
- class SlowEnoughFactbase < Factbase
47
- class SlowQuery < Factbase::Query
48
- def one(fb = @fb, params = {})
49
- sleep 1.5
50
- super
51
- end
52
- end
53
-
54
- def query(term, maps = nil)
55
- maps ||= @maps
56
- term = to_term(term) if term.is_a?(String)
57
- SlowQuery.new(maps, term, self)
58
- end
59
- end
60
-
61
- def test_simple_query
62
- fb = Factbase::Impatient.new(Factbase.new)
63
- fb.insert
64
- fb.insert.bar = 3
65
- found = 0
66
- fb.query('(exists bar)').each do |f|
67
- assert_predicate(f.bar, :positive?)
68
- f.foo = 42
69
- assert_equal(42, f.foo)
70
- found += 1
71
- end
72
- assert_equal(1, found)
73
- assert_equal(2, fb.size)
74
- end
75
-
76
- def test_query_one
77
- fb = Factbase::Impatient.new(Factbase.new)
78
- fb.insert
79
- fb.insert.bar = 42
80
- assert_equal(1, fb.query('(agg (exists bar) (count))').one)
81
- assert_equal([42], fb.query('(agg (exists bar) (first bar))').one)
82
- end
83
-
84
- def test_query_one_timeout
85
- slow = SlowFactbase.new
86
- 10_000.times do
87
- slow.insert.value = rand(1000)
88
- end
89
- fb = Factbase::Impatient.new(slow, timeout: 0.01)
90
- ex =
91
- assert_raises(StandardError) do
92
- fb.query('(agg (min value))').one
93
- end
94
- assert_includes(ex.message, 'timed out after')
95
- end
96
-
97
- def test_delete_timeout
98
- slow = SlowDeleteFactbase.new
99
- 1000.times do |i|
100
- slow.insert.value = i
101
- end
102
- fb = Factbase::Impatient.new(slow, timeout: 0.01)
103
- ex =
104
- assert_raises(StandardError) do
105
- fb.query('(gt value 500)').delete!
106
- end
107
- assert_includes(ex.message, 'timed out after')
108
- end
109
-
110
- def test_with_txn
111
- fb = Factbase::Impatient.new(Factbase.new)
112
- assert(
113
- fb.txn do |fbt|
114
- fbt.insert.foo = 42
115
- end
116
- )
117
- assert_equal(1, fb.size)
118
- end
119
-
120
- def test_returns_int
121
- fb = Factbase.new
122
- fb.insert
123
- fb.insert
124
- assert_equal(2, Factbase::Impatient.new(fb).query('(always)').each(&:to_s))
125
- end
126
-
127
- def test_returns_int_when_empty
128
- fb = Factbase.new
129
- assert_equal(0, Factbase::Impatient.new(fb).query('(always)').each(&:to_s))
130
- end
131
-
132
- def test_returns_to_s_correctly
133
- fb = Factbase.new
134
- q = '(always)'
135
- assert_equal(q, fb.query(q).to_s)
136
- end
137
-
138
- def test_enumerator_support
139
- fb = Factbase::Impatient.new(Factbase.new)
140
- assert_equal(0, fb.query('(always)').each.to_a.size)
141
- fb.insert
142
- assert_equal(1, fb.query('(always)').each.to_a.size)
143
- end
144
-
145
- def test_query_completes_before_timeout
146
- fb = Factbase::Impatient.new(Factbase.new, timeout: 1)
147
- 100.times do |i|
148
- fb.insert.index = i
149
- end
150
- count = 0
151
- fb.query('(always)').each do |f|
152
- count += 1
153
- assert_equal(count - 1, f.index)
154
- end
155
- assert_equal(100, count)
156
- end
157
-
158
- def test_custom_timeout
159
- slow = SlowEnoughFactbase.new
160
- slow.insert.value = 42
161
- fb = Factbase::Impatient.new(slow, timeout: 2)
162
- start = Time.now
163
- result = fb.query('(agg (eq value 42) (first value))').one
164
- elapsed = Time.now - start
165
- assert_operator(elapsed, :>=, 1.5)
166
- assert_equal([42], result)
167
- end
168
-
169
- def test_nil_factbase_raises
170
- ex =
171
- assert_raises(StandardError) do
172
- Factbase::Impatient.new(nil)
173
- end
174
- assert_equal('The "fb" is nil', ex.message)
175
- end
176
- end
@@ -1,44 +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/inv'
10
- require_relative '../../lib/factbase/pre'
11
-
12
- # Test.
13
- # Author:: Yegor Bugayenko (yegor256@gmail.com)
14
- # Copyright:: Copyright (c) 2024-2025 Yegor Bugayenko
15
- # License:: MIT
16
- class TestInv < Factbase::Test
17
- def test_simple_checking
18
- fb =
19
- Factbase::Inv.new(Factbase.new) do |p, v|
20
- raise 'oops' if v.is_a?(String) && p == 'b'
21
- end
22
- f = fb.insert
23
- f.a = 42
24
- assert_raises(StandardError) do
25
- f.b = 'here we should crash'
26
- end
27
- f.c = 256
28
- assert_equal(42, f.a)
29
- assert_equal(1, fb.query('(always)').each.to_a.size)
30
- end
31
-
32
- def test_pre_and_inv
33
- fb =
34
- Factbase::Inv.new(Factbase.new) do |p, v|
35
- raise 'oops' if v.is_a?(String) && p == 'b'
36
- end
37
- fb =
38
- Factbase::Pre.new(fb) do |f|
39
- f.id = 42
40
- end
41
- f = fb.insert
42
- assert_equal(42, f.id)
43
- end
44
- end
@@ -1,155 +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/logged'
10
- require_relative '../../lib/factbase/cached/cached_factbase'
11
-
12
- # Test.
13
- # Author:: Yegor Bugayenko (yegor256@gmail.com)
14
- # Copyright:: Copyright (c) 2024-2025 Yegor Bugayenko
15
- # License:: MIT
16
- class TestLogged < Factbase::Test
17
- def test_simple_setting
18
- fb = Factbase::Logged.new(Factbase.new, Loog::NULL)
19
- fb.insert
20
- fb.insert.bar = 3
21
- found = 0
22
- fb.query('(exists bar)').each do |f|
23
- assert_predicate(f.bar, :positive?)
24
- f.foo = 42
25
- assert_equal(42, f.foo)
26
- found += 1
27
- end
28
- assert_equal(1, found)
29
- assert_equal(2, fb.size)
30
- end
31
-
32
- def test_reading_one
33
- fb = Factbase::Logged.new(Factbase.new, Loog::NULL)
34
- fb.insert
35
- fb.insert.bar = 42
36
- assert_equal(1, fb.query('(agg (exists bar) (count))').one)
37
- assert_equal([42], fb.query('(agg (exists bar) (first bar))').one)
38
- end
39
-
40
- def test_avoid_inner_logging
41
- buf = Loog::Buffer.new
42
- fb = Factbase.new
43
- fb.insert
44
- fb.insert.bar = 42
45
- fb = Factbase::Logged.new(Factbase::CachedFactbase.new(fb), buf)
46
- fb.query('(agg (exists bar) (count))').one
47
- fb.query('(join "foo<=bar" (exists bar))').each.to_a
48
- refute_includes(buf.to_s, '\'(count)\'')
49
- refute_includes(buf.to_s, '\'(exists bar)\'')
50
- end
51
-
52
- def test_with_txn
53
- log = Loog::Buffer.new
54
- fb = Factbase::Logged.new(Factbase.new, log)
55
- assert(
56
- fb.txn do |fbt|
57
- fbt.insert.foo = 42
58
- end
59
- )
60
- assert_equal(1, fb.size)
61
- assert_includes(log.to_s, 'touched', log)
62
- end
63
-
64
- def test_with_slow_txn
65
- log = Loog::Buffer.new
66
- fb = Factbase::Logged.new(Factbase.new, log, time_tolerate: 0.1)
67
- fb.txn { sleep 0.4 }
68
- assert_includes(log.to_s, '(slow!)', log)
69
- end
70
-
71
- def test_with_txn_rollback
72
- log = Loog::Buffer.new
73
- fb = Factbase::Logged.new(Factbase.new, log)
74
- assert_equal(0, fb.txn { raise Factbase::Rollback })
75
- assert_equal(0, fb.size)
76
- assert_includes(log.to_s, 'rolled back', log)
77
- refute_includes(log.to_s, 'didn\'t touch', log)
78
- end
79
-
80
- def test_with_modifying_txn
81
- log = Loog::Buffer.new
82
- fb = Factbase::Logged.new(Factbase.new, log)
83
- fb.insert.foo = 1
84
- assert_equal(0, fb.txn { |fbt| fbt.query('(always)').each.to_a }.to_i, log)
85
- assert_equal(1, fb.txn { |fbt| fbt.query('(always)').each.to_a[0].foo = 42 }.to_i)
86
- assert_includes(log.to_s, 'touched', log)
87
- end
88
-
89
- def test_with_empty_txn
90
- log = Loog::Buffer.new
91
- fb = Factbase::Logged.new(Factbase.new, log)
92
- assert_equal(0, fb.txn { |fbt| fbt.query('(always)').each.to_a }.to_i)
93
- assert_includes(log.to_s, 'touched', log)
94
- end
95
-
96
- def test_returns_int
97
- fb = Factbase.new
98
- fb.insert
99
- fb.insert
100
- assert_equal(2, Factbase::Logged.new(fb, Loog::NULL).query('(always)').each(&:to_s))
101
- end
102
-
103
- def test_returns_int_when_empty
104
- fb = Factbase.new
105
- assert_equal(0, Factbase::Logged.new(fb, Loog::NULL).query('(always)').each(&:to_s))
106
- end
107
-
108
- def test_returns_to_s_correctly
109
- fb = Factbase.new
110
- q = '(always)'
111
- assert_equal(q, fb.query(q).to_s)
112
- end
113
-
114
- def test_logs_when_enumerator
115
- fb = Factbase::Logged.new(Factbase.new, Loog::NULL)
116
- assert_equal(0, fb.query('(always)').each.to_a.size)
117
- fb.insert
118
- assert_equal(1, fb.query('(always)').each.to_a.size)
119
- end
120
-
121
- def test_proper_logging
122
- log = Loog::Buffer.new
123
- fb = Factbase::Logged.new(Factbase.new, log)
124
- fb.insert
125
- fb.insert.bar = 3
126
- fb.insert
127
- fb.insert.str =
128
- "Он поскорей звонит. Вбегает
129
- К нему слуга француз Гильо,
130
- Халат и туфли предлагает
131
- И подает ему белье.
132
- Спешит Онегин одеваться,
133
- Слуге велит приготовляться
134
- С ним вместе ехать и с собой
135
- Взять также ящик боевой.
136
- Готовы санки беговые.
137
- Он сел, на мельницу летит.
138
- Примчались. Он слуге велит
139
- Лепажа стволы роковые
140
- Нести за ним, а лошадям
141
- Отъехать в поле к двум дубкам."
142
- fb.query('(exists bar)').each(&:to_s)
143
- fb.query('(not (exists bar))').delete!
144
- [
145
- 'Inserted new fact #1',
146
- 'Inserted new fact #2',
147
- 'Set \'bar\' to 3 (Integer)',
148
- 'Set \'str\' to "Он поскорей звонит. Вбегает\n ... Отъехать в поле к двум дубкам." (String)',
149
- 'Found 1/4 fact(s) by \'(exists bar)\'',
150
- 'Deleted 3 fact(s) out of 4 by \'(not (exists bar))\''
151
- ].each do |s|
152
- assert_includes(log.to_s, s, "#{log}\n")
153
- end
154
- end
155
- end