factbase 0.4.0 → 0.5.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.0pdd.yml +1 -1
- data/.github/workflows/actionlint.yml +1 -1
- data/.github/workflows/benchmark.yml +64 -0
- data/.github/workflows/codecov.yml +4 -2
- data/.github/workflows/copyrights.yml +2 -2
- data/.github/workflows/markdown-lint.yml +1 -1
- data/.github/workflows/pdd.yml +1 -1
- data/.github/workflows/rake.yml +2 -2
- data/.github/workflows/xcop.yml +1 -1
- data/.github/workflows/yamllint.yml +1 -1
- data/.gitignore +1 -1
- data/.rubocop.yml +6 -1
- data/.rultor.yml +2 -2
- data/.simplecov +1 -1
- data/.yamllint.yml +9 -4
- data/Gemfile +9 -7
- data/Gemfile.lock +98 -78
- data/LICENSE.txt +1 -1
- data/README.md +33 -0
- data/Rakefile +6 -1
- data/benchmarks/simple.rb +96 -0
- data/factbase.gemspec +1 -1
- data/lib/factbase/accum.rb +2 -2
- data/lib/factbase/fact.rb +6 -4
- data/lib/factbase/flatten.rb +2 -2
- data/lib/factbase/inv.rb +2 -2
- data/lib/factbase/looged.rb +6 -5
- data/lib/factbase/pre.rb +2 -2
- data/lib/factbase/query.rb +16 -8
- data/lib/factbase/query_once.rb +71 -0
- data/lib/factbase/rules.rb +3 -3
- data/lib/factbase/syntax.rb +21 -11
- data/lib/factbase/tee.rb +2 -2
- data/lib/factbase/term.rb +33 -5
- data/lib/factbase/term_once.rb +84 -0
- data/lib/factbase/terms/aggregates.rb +4 -4
- data/lib/factbase/terms/aliases.rb +5 -5
- data/lib/factbase/terms/casting.rb +2 -2
- data/lib/factbase/terms/debug.rb +2 -2
- data/lib/factbase/terms/defn.rb +2 -2
- data/lib/factbase/terms/logical.rb +3 -3
- data/lib/factbase/terms/math.rb +2 -2
- data/lib/factbase/terms/meta.rb +2 -2
- data/lib/factbase/terms/ordering.rb +2 -2
- data/lib/factbase/terms/strings.rb +2 -2
- data/lib/factbase/terms/system.rb +2 -2
- data/lib/factbase/to_json.rb +2 -2
- data/lib/factbase/to_xml.rb +2 -2
- data/lib/factbase/to_yaml.rb +2 -2
- data/lib/factbase.rb +16 -6
- data/test/factbase/terms/test_aggregates.rb +6 -6
- data/test/factbase/terms/test_aliases.rb +6 -6
- data/test/factbase/terms/test_casting.rb +6 -6
- data/test/factbase/terms/test_debug.rb +53 -0
- data/test/factbase/terms/test_defn.rb +15 -15
- data/test/factbase/terms/test_logical.rb +15 -13
- data/test/factbase/terms/test_math.rb +42 -42
- data/test/factbase/terms/test_meta.rb +87 -0
- data/test/factbase/terms/test_ordering.rb +45 -0
- data/test/factbase/terms/test_strings.rb +8 -8
- data/test/factbase/terms/test_system.rb +6 -6
- data/test/factbase/test_accum.rb +9 -9
- data/test/factbase/test_fact.rb +22 -22
- data/test/factbase/test_flatten.rb +6 -6
- data/test/factbase/test_inv.rb +3 -3
- data/test/factbase/test_looged.rb +13 -13
- data/test/factbase/test_pre.rb +2 -2
- data/test/factbase/test_query.rb +17 -17
- data/test/factbase/test_rules.rb +8 -8
- data/test/factbase/test_syntax.rb +30 -9
- data/test/factbase/test_tee.rb +11 -11
- data/test/factbase/test_term.rb +18 -18
- data/test/factbase/test_to_json.rb +4 -4
- data/test/factbase/test_to_xml.rb +12 -14
- data/test/factbase/test_to_yaml.rb +3 -3
- data/test/test__helper.rb +2 -2
- data/test/test_factbase.rb +200 -18
- metadata +12 -5
data/test/factbase/test_fact.rb
CHANGED
@@ -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,12 +26,12 @@ require_relative '../../lib/factbase/fact'
|
|
26
26
|
|
27
27
|
# Fact 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 TestFact < Minitest::Test
|
32
32
|
def test_injects_data_correctly
|
33
33
|
map = {}
|
34
|
-
f = Factbase::Fact.new(Mutex.new, map)
|
34
|
+
f = Factbase::Fact.new(Factbase.new, Mutex.new, map)
|
35
35
|
f.foo = 1
|
36
36
|
f.bar = 2
|
37
37
|
f.bar = 3
|
@@ -42,7 +42,7 @@ class TestFact < Minitest::Test
|
|
42
42
|
|
43
43
|
def test_simple_resetting
|
44
44
|
map = {}
|
45
|
-
f = Factbase::Fact.new(Mutex.new, map)
|
45
|
+
f = Factbase::Fact.new(Factbase.new, Mutex.new, map)
|
46
46
|
f.foo = 42
|
47
47
|
assert_equal(42, f.foo, f.to_s)
|
48
48
|
f.foo = 256
|
@@ -52,7 +52,7 @@ class TestFact < Minitest::Test
|
|
52
52
|
|
53
53
|
def test_keeps_values_unique
|
54
54
|
map = {}
|
55
|
-
f = Factbase::Fact.new(Mutex.new, map)
|
55
|
+
f = Factbase::Fact.new(Factbase.new, Mutex.new, map)
|
56
56
|
f.foo = 42
|
57
57
|
f.foo = 'Hello'
|
58
58
|
assert_equal(2, map['foo'].size)
|
@@ -61,50 +61,50 @@ class TestFact < Minitest::Test
|
|
61
61
|
end
|
62
62
|
|
63
63
|
def test_fails_when_empty
|
64
|
-
f = Factbase::Fact.new(Mutex.new, {})
|
65
|
-
assert_raises do
|
64
|
+
f = Factbase::Fact.new(Factbase.new, Mutex.new, {})
|
65
|
+
assert_raises(StandardError) do
|
66
66
|
f.something
|
67
67
|
end
|
68
68
|
end
|
69
69
|
|
70
70
|
def test_fails_when_setting_nil
|
71
|
-
f = Factbase::Fact.new(Mutex.new, {})
|
72
|
-
assert_raises do
|
71
|
+
f = Factbase::Fact.new(Factbase.new, Mutex.new, {})
|
72
|
+
assert_raises(StandardError) do
|
73
73
|
f.foo = nil
|
74
74
|
end
|
75
75
|
end
|
76
76
|
|
77
77
|
def test_fails_when_setting_empty
|
78
|
-
f = Factbase::Fact.new(Mutex.new, {})
|
79
|
-
assert_raises do
|
78
|
+
f = Factbase::Fact.new(Factbase.new, Mutex.new, {})
|
79
|
+
assert_raises(StandardError) do
|
80
80
|
f.foo = ''
|
81
81
|
end
|
82
82
|
end
|
83
83
|
|
84
84
|
def test_fails_when_not_found
|
85
|
-
f = Factbase::Fact.new(Mutex.new, {})
|
85
|
+
f = Factbase::Fact.new(Factbase.new, Mutex.new, {})
|
86
86
|
f.first = 42
|
87
|
-
assert_raises do
|
87
|
+
assert_raises(StandardError) do
|
88
88
|
f.second
|
89
89
|
end
|
90
90
|
end
|
91
91
|
|
92
92
|
def test_set_by_name
|
93
|
-
f = Factbase::Fact.new(Mutex.new, {})
|
94
|
-
f.send(
|
93
|
+
f = Factbase::Fact.new(Factbase.new, Mutex.new, {})
|
94
|
+
f.send(:_foo_bar=, 42)
|
95
95
|
assert_equal(42, f._foo_bar, f.to_s)
|
96
96
|
end
|
97
97
|
|
98
98
|
def test_set_twice_same_value
|
99
99
|
map = {}
|
100
|
-
f = Factbase::Fact.new(Mutex.new, map)
|
100
|
+
f = Factbase::Fact.new(Factbase.new, Mutex.new, map)
|
101
101
|
f.foo = 42
|
102
102
|
f.foo = 42
|
103
103
|
assert_equal([42], map['foo'])
|
104
104
|
end
|
105
105
|
|
106
106
|
def test_time_in_utc
|
107
|
-
f = Factbase::Fact.new(Mutex.new, {})
|
107
|
+
f = Factbase::Fact.new(Factbase.new, Mutex.new, {})
|
108
108
|
t = Time.now
|
109
109
|
f.foo = t
|
110
110
|
assert_equal(t.utc, f.foo)
|
@@ -112,14 +112,14 @@ class TestFact < Minitest::Test
|
|
112
112
|
end
|
113
113
|
|
114
114
|
def test_some_names_are_prohibited
|
115
|
-
f = Factbase::Fact.new(Mutex.new, {})
|
116
|
-
assert_raises { f.to_s = 42 }
|
117
|
-
assert_raises { f.class = 42 }
|
115
|
+
f = Factbase::Fact.new(Factbase.new, Mutex.new, {})
|
116
|
+
assert_raises(StandardError) { f.to_s = 42 }
|
117
|
+
assert_raises(StandardError) { f.class = 42 }
|
118
118
|
end
|
119
119
|
|
120
120
|
def test_get_all_properties
|
121
|
-
f = Factbase::Fact.new(Mutex.new, {})
|
121
|
+
f = Factbase::Fact.new(Factbase.new, Mutex.new, {})
|
122
122
|
f.foo = 42
|
123
|
-
|
123
|
+
assert_includes(f.all_properties, 'foo')
|
124
124
|
end
|
125
125
|
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,20 +26,20 @@ require_relative '../../lib/factbase/flatten'
|
|
26
26
|
|
27
27
|
# 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 TestFlatten < Minitest::Test
|
32
32
|
def test_mapping
|
33
33
|
maps = [{ 'b' => [42], 'i' => 1 }, { 'a' => 33, 'i' => 0 }, { 'c' => %w[hey you], 'i' => 2 }]
|
34
34
|
to = Factbase::Flatten.new(maps, 'i').it
|
35
|
-
|
36
|
-
|
37
|
-
|
35
|
+
assert_equal(33, to[0]['a'])
|
36
|
+
assert_equal(42, to[1]['b'])
|
37
|
+
assert_equal(2, to[2]['c'].size)
|
38
38
|
end
|
39
39
|
|
40
40
|
def test_without_sorter
|
41
41
|
maps = [{ 'b' => [42], 'i' => [44] }, { 'a' => 33 }]
|
42
42
|
to = Factbase::Flatten.new(maps, 'i').it
|
43
|
-
|
43
|
+
assert_equal(33, to[0]['a'])
|
44
44
|
end
|
45
45
|
end
|
data/test/factbase/test_inv.rb
CHANGED
@@ -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
|
@@ -28,7 +28,7 @@ require_relative '../../lib/factbase/pre'
|
|
28
28
|
|
29
29
|
# Test.
|
30
30
|
# Author:: Yegor Bugayenko (yegor256@gmail.com)
|
31
|
-
# Copyright:: Copyright (c) 2024 Yegor Bugayenko
|
31
|
+
# Copyright:: Copyright (c) 2024-2025 Yegor Bugayenko
|
32
32
|
# License:: MIT
|
33
33
|
class TestInv < Minitest::Test
|
34
34
|
def test_simple_checking
|
@@ -38,7 +38,7 @@ class TestInv < Minitest::Test
|
|
38
38
|
end
|
39
39
|
f = fb.insert
|
40
40
|
f.a = 42
|
41
|
-
assert_raises do
|
41
|
+
assert_raises(StandardError) do
|
42
42
|
f.b = 'here we should crash'
|
43
43
|
end
|
44
44
|
f.c = 256
|
@@ -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,7 +27,7 @@ require_relative '../../lib/factbase/looged'
|
|
27
27
|
|
28
28
|
# 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 TestLooged < Minitest::Test
|
33
33
|
def test_simple_setting
|
@@ -36,7 +36,7 @@ class TestLooged < Minitest::Test
|
|
36
36
|
fb.insert.bar = 3
|
37
37
|
found = 0
|
38
38
|
fb.query('(exists bar)').each do |f|
|
39
|
-
|
39
|
+
assert_predicate(f.bar, :positive?)
|
40
40
|
f.foo = 42
|
41
41
|
assert_equal(42, f.foo)
|
42
42
|
found += 1
|
@@ -62,32 +62,32 @@ class TestLooged < Minitest::Test
|
|
62
62
|
end
|
63
63
|
)
|
64
64
|
assert_equal(1, fb.size)
|
65
|
-
|
65
|
+
assert_includes(log.to_s, 'modified', log)
|
66
66
|
end
|
67
67
|
|
68
68
|
def test_with_txn_rollback
|
69
69
|
log = Loog::Buffer.new
|
70
70
|
fb = Factbase::Looged.new(Factbase.new, log)
|
71
|
-
|
71
|
+
refute(fb.txn { raise Factbase::Rollback })
|
72
72
|
assert_equal(0, fb.size)
|
73
|
-
|
74
|
-
|
73
|
+
assert_includes(log.to_s, 'rolled back', log)
|
74
|
+
refute_includes(log.to_s, 'didn\'t touch', log)
|
75
75
|
end
|
76
76
|
|
77
77
|
def test_with_modifying_txn
|
78
78
|
log = Loog::Buffer.new
|
79
79
|
fb = Factbase::Looged.new(Factbase.new, log)
|
80
80
|
fb.insert.foo = 1
|
81
|
-
|
82
|
-
assert(fb.txn { |fbt| fbt.query('(always)').each.to_a[0].foo = 42 }
|
83
|
-
|
81
|
+
refute(fb.txn { |fbt| fbt.query('(always)').each.to_a }, log)
|
82
|
+
assert(fb.txn { |fbt| fbt.query('(always)').each.to_a[0].foo = 42 })
|
83
|
+
assert_includes(log.to_s, 'modified', log)
|
84
84
|
end
|
85
85
|
|
86
86
|
def test_with_empty_txn
|
87
87
|
log = Loog::Buffer.new
|
88
88
|
fb = Factbase::Looged.new(Factbase.new, log)
|
89
|
-
|
90
|
-
|
89
|
+
refute(fb.txn { |fbt| fbt.query('(always)').each.to_a })
|
90
|
+
assert_includes(log.to_s, 'didn\'t touch', log)
|
91
91
|
end
|
92
92
|
|
93
93
|
def test_returns_int
|
@@ -140,7 +140,7 @@ class TestLooged < Minitest::Test
|
|
140
140
|
'Found 1 fact(s) by \'(exists bar)\'',
|
141
141
|
'Deleted 3 fact(s) out of 4 by \'(not (exists bar))\''
|
142
142
|
].each do |s|
|
143
|
-
|
143
|
+
assert_includes(log.to_s, s, "#{log}\n")
|
144
144
|
end
|
145
145
|
end
|
146
146
|
end
|
data/test/factbase/test_pre.rb
CHANGED
@@ -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,7 +26,7 @@ require_relative '../../lib/factbase/pre'
|
|
26
26
|
|
27
27
|
# 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 TestPre < Minitest::Test
|
32
32
|
def test_simple_setting
|
data/test/factbase/test_query.rb
CHANGED
@@ -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,13 +27,13 @@ require_relative '../../lib/factbase/query'
|
|
27
27
|
|
28
28
|
# Query 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 TestQuery < Minitest::Test
|
33
33
|
def test_simple_parsing
|
34
34
|
maps = []
|
35
35
|
maps << { 'foo' => [42] }
|
36
|
-
q = Factbase::Query.new(maps, Mutex.new, '(eq foo 42)')
|
36
|
+
q = Factbase::Query.new(Factbase.new, maps, Mutex.new, '(eq foo 42)')
|
37
37
|
assert_equal(
|
38
38
|
1,
|
39
39
|
q.each do |f|
|
@@ -88,7 +88,7 @@ class TestQuery < Minitest::Test
|
|
88
88
|
"(or (eq num +66) (lt time #{(Time.now - 200).utc.iso8601}))" => 1,
|
89
89
|
'(eq 3 (agg (eq num $num) (count)))' => 1
|
90
90
|
}.each do |q, r|
|
91
|
-
assert_equal(r, Factbase::Query.new(maps, Mutex.new, q).each.to_a.size, q)
|
91
|
+
assert_equal(r, Factbase::Query.new(Factbase.new, maps, Mutex.new, q).each.to_a.size, q)
|
92
92
|
end
|
93
93
|
end
|
94
94
|
|
@@ -96,7 +96,7 @@ class TestQuery < Minitest::Test
|
|
96
96
|
maps = []
|
97
97
|
now = Time.now.utc
|
98
98
|
maps << { 'foo' => [now] }
|
99
|
-
q = Factbase::Query.new(maps, Mutex.new, "(eq foo #{now.iso8601})")
|
99
|
+
q = Factbase::Query.new(Factbase.new, maps, Mutex.new, "(eq foo #{now.iso8601})")
|
100
100
|
assert_equal(1, q.each.to_a.size)
|
101
101
|
end
|
102
102
|
|
@@ -105,7 +105,7 @@ class TestQuery < Minitest::Test
|
|
105
105
|
maps << { 'foo' => [42] }
|
106
106
|
maps << { 'bar' => [4, 5] }
|
107
107
|
maps << { 'bar' => [5] }
|
108
|
-
q = Factbase::Query.new(maps, Mutex.new, '(eq bar 5)')
|
108
|
+
q = Factbase::Query.new(Factbase.new, maps, Mutex.new, '(eq bar 5)')
|
109
109
|
assert_equal(2, q.delete!)
|
110
110
|
assert_equal(1, maps.size)
|
111
111
|
end
|
@@ -121,7 +121,7 @@ class TestQuery < Minitest::Test
|
|
121
121
|
'(agg (eq bar $v) (count))' => 1,
|
122
122
|
'(agg (eq z 40) (count))' => 0
|
123
123
|
}.each do |q, expected|
|
124
|
-
result = Factbase::Query.new(maps, Mutex.new, q).one(v: 4)
|
124
|
+
result = Factbase::Query.new(Factbase.new, maps, Mutex.new, q).one(v: 4)
|
125
125
|
if expected.nil?
|
126
126
|
assert_nil(result, "#{q} -> nil")
|
127
127
|
else
|
@@ -135,7 +135,7 @@ class TestQuery < Minitest::Test
|
|
135
135
|
maps << { 'foo' => [42] }
|
136
136
|
maps << { 'bar' => [4, 5] }
|
137
137
|
maps << { 'bar' => [5] }
|
138
|
-
q = Factbase::Query.new(maps, Mutex.new, '(never)')
|
138
|
+
q = Factbase::Query.new(Factbase.new, maps, Mutex.new, '(never)')
|
139
139
|
assert_equal(0, q.delete!)
|
140
140
|
assert_equal(3, maps.size)
|
141
141
|
end
|
@@ -143,20 +143,20 @@ class TestQuery < Minitest::Test
|
|
143
143
|
def test_to_array
|
144
144
|
maps = []
|
145
145
|
maps << { 'foo' => [42] }
|
146
|
-
assert_equal(1, Factbase::Query.new(maps, Mutex.new, '(eq foo 42)').each.to_a.size)
|
146
|
+
assert_equal(1, Factbase::Query.new(Factbase.new, maps, Mutex.new, '(eq foo 42)').each.to_a.size)
|
147
147
|
end
|
148
148
|
|
149
149
|
def test_returns_int
|
150
150
|
maps = []
|
151
151
|
maps << { 'foo' => [1] }
|
152
|
-
q = Factbase::Query.new(maps, Mutex.new, '(eq foo 1)')
|
152
|
+
q = Factbase::Query.new(Factbase.new, maps, Mutex.new, '(eq foo 1)')
|
153
153
|
assert_equal(1, q.each(&:to_s))
|
154
154
|
end
|
155
155
|
|
156
156
|
def test_with_aliases
|
157
157
|
maps = []
|
158
158
|
maps << { 'foo' => [42] }
|
159
|
-
assert_equal(45, Factbase::Query.new(maps, Mutex.new, '(as bar (plus foo 3))').each.to_a[0].bar)
|
159
|
+
assert_equal(45, Factbase::Query.new(Factbase.new, maps, Mutex.new, '(as bar (plus foo 3))').each.to_a[0].bar)
|
160
160
|
assert_equal(1, maps[0].size)
|
161
161
|
end
|
162
162
|
|
@@ -165,24 +165,24 @@ class TestQuery < Minitest::Test
|
|
165
165
|
maps << { 'foo' => [42] }
|
166
166
|
maps << { 'foo' => [17] }
|
167
167
|
found = 0
|
168
|
-
Factbase::Query.new(maps, Mutex.new, '(eq foo $bar)').each(bar: [42]) do
|
168
|
+
Factbase::Query.new(Factbase.new, maps, Mutex.new, '(eq foo $bar)').each(bar: [42]) do
|
169
169
|
found += 1
|
170
170
|
end
|
171
171
|
assert_equal(1, found)
|
172
|
-
assert_equal(1, Factbase::Query.new(maps, Mutex.new, '(eq foo $bar)').each(bar: 42).to_a.size)
|
173
|
-
assert_equal(0, Factbase::Query.new(maps, Mutex.new, '(eq foo $bar)').each(bar: 555).to_a.size)
|
172
|
+
assert_equal(1, Factbase::Query.new(Factbase.new, maps, Mutex.new, '(eq foo $bar)').each(bar: 42).to_a.size)
|
173
|
+
assert_equal(0, Factbase::Query.new(Factbase.new, maps, Mutex.new, '(eq foo $bar)').each(bar: 555).to_a.size)
|
174
174
|
end
|
175
175
|
|
176
176
|
def test_with_nil_alias
|
177
177
|
maps = []
|
178
178
|
maps << { 'foo' => [42] }
|
179
|
-
|
179
|
+
assert_nil(Factbase::Query.new(Factbase.new, maps, Mutex.new, '(as bar (plus xxx 3))').each.to_a[0]['bar'])
|
180
180
|
end
|
181
181
|
|
182
182
|
def test_get_all_properties
|
183
183
|
maps = []
|
184
184
|
maps << { 'foo' => [42] }
|
185
|
-
f = Factbase::Query.new(maps, Mutex.new, '(always)').each.to_a[0]
|
186
|
-
|
185
|
+
f = Factbase::Query.new(Factbase.new, maps, Mutex.new, '(always)').each.to_a[0]
|
186
|
+
assert_includes(f.all_properties, 'foo')
|
187
187
|
end
|
188
188
|
end
|
data/test/factbase/test_rules.rb
CHANGED
@@ -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,7 +27,7 @@ require_relative '../../lib/factbase/pre'
|
|
27
27
|
|
28
28
|
# 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 TestRules < Minitest::Test
|
33
33
|
def test_simple_checking
|
@@ -38,8 +38,8 @@ class TestRules < Minitest::Test
|
|
38
38
|
f1 = fb.insert
|
39
39
|
f1.second = 2
|
40
40
|
f1.first = 1
|
41
|
-
|
42
|
-
|
41
|
+
f2 = fb.insert
|
42
|
+
assert_raises(StandardError) do
|
43
43
|
f2.first = 1
|
44
44
|
end
|
45
45
|
end
|
@@ -60,7 +60,7 @@ class TestRules < Minitest::Test
|
|
60
60
|
f = fb.insert
|
61
61
|
f.foo = 42
|
62
62
|
s = f.to_s
|
63
|
-
|
63
|
+
assert_predicate(s.length, :positive?, s)
|
64
64
|
assert_equal('[ foo: [42] ]', s)
|
65
65
|
end
|
66
66
|
|
@@ -74,7 +74,7 @@ class TestRules < Minitest::Test
|
|
74
74
|
def test_check_only_when_txn_is_closed
|
75
75
|
fb = Factbase::Rules.new(Factbase.new, '(when (exists a) (exists b))')
|
76
76
|
ok = false
|
77
|
-
assert_raises do
|
77
|
+
assert_raises(StandardError) do
|
78
78
|
fb.txn do |fbt|
|
79
79
|
f = fbt.insert
|
80
80
|
f.a = 1
|
@@ -87,7 +87,7 @@ class TestRules < Minitest::Test
|
|
87
87
|
|
88
88
|
def test_rollback_on_violation
|
89
89
|
fb = Factbase::Rules.new(Factbase.new, '(when (exists a) (exists b))')
|
90
|
-
assert_raises do
|
90
|
+
assert_raises(StandardError) do
|
91
91
|
fb.txn do |fbt|
|
92
92
|
f = fbt.insert
|
93
93
|
f.a = 1
|
@@ -104,7 +104,7 @@ class TestRules < Minitest::Test
|
|
104
104
|
f.hello = 42
|
105
105
|
end
|
106
106
|
ok = false
|
107
|
-
assert_raises do
|
107
|
+
assert_raises(StandardError) do
|
108
108
|
fb.txn do |fbt|
|
109
109
|
f = fbt.insert
|
110
110
|
f.a = 1
|
@@ -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,7 +25,7 @@ require_relative '../../lib/factbase/syntax'
|
|
25
25
|
|
26
26
|
# Syntax 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 TestSyntax < Minitest::Test
|
31
31
|
def test_parses_string_right
|
@@ -35,7 +35,27 @@ class TestSyntax < Minitest::Test
|
|
35
35
|
"(foo 'one two three ')",
|
36
36
|
"(foo 'one two three ' 'tail tail')"
|
37
37
|
].each do |q|
|
38
|
-
assert_equal(q, Factbase::Syntax.new(q).to_term.to_s, q)
|
38
|
+
assert_equal(q, Factbase::Syntax.new(Factbase.new, q).to_term.to_s, q)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def test_makes_abstract_terms
|
43
|
+
{
|
44
|
+
'(foo $bar)' => true,
|
45
|
+
'(foo (bar (a (b c (f $bar)))))' => true,
|
46
|
+
'(foo (bar (a (b c (f bar)))))' => false
|
47
|
+
}.each do |q, a|
|
48
|
+
assert_equal(a, Factbase::Syntax.new(Factbase.new, q).to_term.abstract?)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def test_makes_static_terms
|
53
|
+
{
|
54
|
+
'(foo bar)' => false,
|
55
|
+
'(foo "bar")' => true,
|
56
|
+
'(agg (always) (max id))' => true
|
57
|
+
}.each do |q, a|
|
58
|
+
assert_equal(a, Factbase::Syntax.new(Factbase.new, q).to_term.static?)
|
39
59
|
end
|
40
60
|
end
|
41
61
|
|
@@ -50,7 +70,7 @@ class TestSyntax < Minitest::Test
|
|
50
70
|
"(foo 'Hello,\n\nworld!\r\t\n')\n",
|
51
71
|
"(or ( a 4) (b 5) (always) (and (always) (c 5) \t\t(r 7 w8s w8is 'Foo')))"
|
52
72
|
].each do |q|
|
53
|
-
|
73
|
+
refute_nil(Factbase::Syntax.new(Factbase.new, q).to_term)
|
54
74
|
end
|
55
75
|
end
|
56
76
|
|
@@ -70,7 +90,7 @@ class TestSyntax < Minitest::Test
|
|
70
90
|
'(eq t 3.0e+21)',
|
71
91
|
"(foo (x (f (t (y 42 'Hey you'))) (never) (r 3)) y z)"
|
72
92
|
].each do |q|
|
73
|
-
assert_equal(q, Factbase::Syntax.new(q).to_term.to_s, q)
|
93
|
+
assert_equal(q, Factbase::Syntax.new(Factbase.new, q).to_term.to_s, q)
|
74
94
|
end
|
75
95
|
end
|
76
96
|
|
@@ -85,7 +105,7 @@ class TestSyntax < Minitest::Test
|
|
85
105
|
'(or (eq bar 888) (eq z 1))' => true,
|
86
106
|
"(or (gt bar 100) (eq foo 'Hello, world!'))" => true
|
87
107
|
}.each do |k, v|
|
88
|
-
assert_equal(v, Factbase::Syntax.new(k).to_term.evaluate(m, []), k)
|
108
|
+
assert_equal(v, Factbase::Syntax.new(Factbase.new, k).to_term.evaluate(m, []), k)
|
89
109
|
end
|
90
110
|
end
|
91
111
|
|
@@ -94,6 +114,7 @@ class TestSyntax < Minitest::Test
|
|
94
114
|
'',
|
95
115
|
'()',
|
96
116
|
'(foo',
|
117
|
+
'(foo $)',
|
97
118
|
'(foo 1) (bar 2)',
|
98
119
|
'some text',
|
99
120
|
'"hello, world!',
|
@@ -109,9 +130,9 @@ class TestSyntax < Minitest::Test
|
|
109
130
|
'"'
|
110
131
|
].each do |q|
|
111
132
|
msg = assert_raises(q) do
|
112
|
-
Factbase::Syntax.new(q).to_term
|
133
|
+
Factbase::Syntax.new(Factbase.new, q).to_term
|
113
134
|
end.message
|
114
|
-
|
135
|
+
assert_includes(msg, q, msg)
|
115
136
|
end
|
116
137
|
end
|
117
138
|
|
@@ -121,7 +142,7 @@ class TestSyntax < Minitest::Test
|
|
121
142
|
'(and (foo) (foo))' => '(foo)',
|
122
143
|
'(and (foo) (or (and (eq a 1))) (eq a 1) (foo))' => '(and (foo) (eq a 1))'
|
123
144
|
}.each do |s, t|
|
124
|
-
assert_equal(t, Factbase::Syntax.new(s).to_term.to_s)
|
145
|
+
assert_equal(t, Factbase::Syntax.new(Factbase.new, s).to_term.to_s)
|
125
146
|
end
|
126
147
|
end
|
127
148
|
end
|
data/test/factbase/test_tee.rb
CHANGED
@@ -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,13 +27,13 @@ require_relative '../../lib/factbase/fact'
|
|
27
27
|
|
28
28
|
# Tee 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 TestTee < Minitest::Test
|
33
33
|
def test_two_facts
|
34
|
-
prim = Factbase::Fact.new(Mutex.new, {})
|
34
|
+
prim = Factbase::Fact.new(Factbase.new, Mutex.new, {})
|
35
35
|
prim.foo = 42
|
36
|
-
upper = Factbase::Fact.new(Mutex.new, {})
|
36
|
+
upper = Factbase::Fact.new(Factbase.new, Mutex.new, {})
|
37
37
|
upper.bar = 13
|
38
38
|
t = Factbase::Tee.new(prim, upper)
|
39
39
|
assert_equal(42, t.foo)
|
@@ -41,18 +41,18 @@ class TestTee < Minitest::Test
|
|
41
41
|
end
|
42
42
|
|
43
43
|
def test_all_properties
|
44
|
-
prim = Factbase::Fact.new(Mutex.new, {})
|
44
|
+
prim = Factbase::Fact.new(Factbase.new, Mutex.new, {})
|
45
45
|
prim.foo = 42
|
46
|
-
upper = Factbase::Fact.new(Mutex.new, {})
|
46
|
+
upper = Factbase::Fact.new(Factbase.new, Mutex.new, {})
|
47
47
|
upper.bar = 13
|
48
48
|
t = Factbase::Tee.new(prim, upper)
|
49
|
-
|
50
|
-
|
49
|
+
assert_includes(t.all_properties, 'foo')
|
50
|
+
assert_includes(t.all_properties, 'bar')
|
51
51
|
end
|
52
52
|
|
53
53
|
def test_recursively
|
54
54
|
map = {}
|
55
|
-
prim = Factbase::Fact.new(Mutex.new, map)
|
55
|
+
prim = Factbase::Fact.new(Factbase.new, Mutex.new, map)
|
56
56
|
prim.foo = 42
|
57
57
|
t = Factbase::Tee.new(nil, { 'bar' => 7 })
|
58
58
|
assert_equal(7, t['$bar'])
|
@@ -61,9 +61,9 @@ class TestTee < Minitest::Test
|
|
61
61
|
end
|
62
62
|
|
63
63
|
def test_prints_to_string
|
64
|
-
prim = Factbase::Fact.new(Mutex.new, {})
|
64
|
+
prim = Factbase::Fact.new(Factbase.new, Mutex.new, {})
|
65
65
|
prim.foo = 42
|
66
|
-
upper = Factbase::Fact.new(Mutex.new, {})
|
66
|
+
upper = Factbase::Fact.new(Factbase.new, Mutex.new, {})
|
67
67
|
upper.bar = 13
|
68
68
|
t = Factbase::Tee.new(prim, upper)
|
69
69
|
assert_equal('[ foo: [42] ]', t.to_s)
|