judges 0.0.33 → 0.0.35
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +2 -0
- data/.rultor.yml +2 -2
- data/Gemfile +2 -0
- data/Gemfile.lock +25 -3
- data/bin/judges +45 -4
- data/features/pull.feature +12 -0
- data/features/push.feature +11 -0
- data/features/step_definitions/steps.rb +5 -0
- data/features/test.feature +34 -3
- data/fixtures/try/try.rb +1 -1
- data/judges.gemspec +11 -7
- data/lib/judges/baza.rb +171 -0
- data/lib/judges/categories.rb +51 -0
- data/lib/judges/commands/print.rb +1 -1
- data/lib/judges/commands/pull.rb +70 -0
- data/lib/judges/commands/push.rb +53 -0
- data/lib/judges/commands/test.rb +29 -13
- data/lib/judges/commands/update.rb +5 -2
- data/lib/judges/fb/if_absent.rb +7 -4
- data/lib/judges/fb/once.rb +24 -33
- data/lib/judges/options.rb +11 -1
- data/lib/judges/pack.rb +0 -1
- data/lib/judges.rb +3 -1
- data/test/commands/test_pull.rb +58 -0
- data/test/commands/test_push.rb +77 -0
- data/test/fb/test_if_absent.rb +8 -1
- data/test/fb/test_once.rb +52 -4
- data/test/test_baza.rb +75 -0
- data/test/test_categories.rb +50 -0
- data/test/test_options.rb +8 -0
- data/test/test_pack.rb +2 -2
- metadata +59 -8
@@ -0,0 +1,53 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Copyright (c) 2024 Yegor Bugayenko
|
4
|
+
#
|
5
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
# of this software and associated documentation files (the 'Software'), to deal
|
7
|
+
# in the Software without restriction, including without limitation the rights
|
8
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
# copies of the Software, and to permit persons to whom the Software is
|
10
|
+
# furnished to do so, subject to the following conditions:
|
11
|
+
#
|
12
|
+
# The above copyright notice and this permission notice shall be included in all
|
13
|
+
# copies or substantial portions of the Software.
|
14
|
+
#
|
15
|
+
# THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
+
# SOFTWARE.
|
22
|
+
|
23
|
+
require 'typhoeus'
|
24
|
+
require 'iri'
|
25
|
+
require_relative '../../judges'
|
26
|
+
require_relative '../../judges/impex'
|
27
|
+
require_relative '../../judges/baza'
|
28
|
+
|
29
|
+
# Push.
|
30
|
+
# Author:: Yegor Bugayenko (yegor256@gmail.com)
|
31
|
+
# Copyright:: Copyright (c) 2024 Yegor Bugayenko
|
32
|
+
# License:: MIT
|
33
|
+
class Judges::Push
|
34
|
+
def initialize(loog)
|
35
|
+
@loog = loog
|
36
|
+
end
|
37
|
+
|
38
|
+
def run(opts, args)
|
39
|
+
raise 'Exactly two arguments required' unless args.size == 2
|
40
|
+
name = args[0]
|
41
|
+
fb = Judges::Impex.new(@loog, args[1]).import
|
42
|
+
baza = Judges::Baza.new(
|
43
|
+
opts['host'], opts['port'].to_i, opts['token'],
|
44
|
+
ssl: opts['ssl'],
|
45
|
+
timeout: (opts['timeout'] || 5).to_i,
|
46
|
+
loog: @loog
|
47
|
+
)
|
48
|
+
elapsed(@loog) do
|
49
|
+
id = baza.push(name, fb.export)
|
50
|
+
throw :"Pushed #{fb.size} facts, job ID is #{id}"
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
data/lib/judges/commands/test.rb
CHANGED
@@ -29,6 +29,7 @@ require_relative '../../judges'
|
|
29
29
|
require_relative '../../judges/to_rel'
|
30
30
|
require_relative '../../judges/packs'
|
31
31
|
require_relative '../../judges/options'
|
32
|
+
require_relative '../../judges/categories'
|
32
33
|
require_relative '../../judges/elapsed'
|
33
34
|
|
34
35
|
# Test.
|
@@ -45,7 +46,8 @@ class Judges::Test
|
|
45
46
|
dir = args[0]
|
46
47
|
@loog.info("Testing judges in #{dir.to_rel}...")
|
47
48
|
errors = []
|
48
|
-
|
49
|
+
packs = 0
|
50
|
+
tests = 0
|
49
51
|
elapsed(@loog) do
|
50
52
|
Judges::Packs.new(dir, opts['lib'], @loog).each_with_index do |p, i|
|
51
53
|
next unless include?(opts, p.name)
|
@@ -56,22 +58,32 @@ class Judges::Test
|
|
56
58
|
@loog.info("Skippped #{f.to_rel}")
|
57
59
|
next
|
58
60
|
end
|
59
|
-
|
61
|
+
unless Judges::Categories.new(opts['enable'], opts['disable']).ok?(yaml['category'])
|
62
|
+
@loog.info("Skippped #{f.to_rel} because of its category")
|
63
|
+
next
|
64
|
+
end
|
65
|
+
@loog.info("🛠️ Testing #{f.to_rel}:")
|
60
66
|
begin
|
61
|
-
test_one(p, yaml)
|
67
|
+
test_one(opts, p, yaml)
|
68
|
+
tests += 1
|
62
69
|
rescue StandardError => e
|
63
70
|
@loog.warn(Backtrace.new(e))
|
64
71
|
errors << f
|
65
72
|
end
|
66
73
|
end
|
67
|
-
|
74
|
+
packs += 1
|
68
75
|
end
|
69
|
-
throw :'👍 No judges tested' if
|
70
|
-
throw :"👍 All #{
|
71
|
-
throw :"❌ #{
|
76
|
+
throw :'👍 No judges tested' if packs.zero?
|
77
|
+
throw :"👍 All #{packs} judge(s) and #{tests} tests passed" if errors.empty?
|
78
|
+
throw :"❌ #{packs} judge(s) tested, #{errors.size} of them failed"
|
79
|
+
end
|
80
|
+
unless errors.empty?
|
81
|
+
raise "#{errors.size} tests failed" unless opts['quiet']
|
82
|
+
@loog.debug('Not failing the build with tests failures, due to the --quiet option')
|
72
83
|
end
|
73
|
-
|
74
|
-
raise 'No judges tested :(' unless opts['quiet']
|
84
|
+
return unless packs.zero?
|
85
|
+
raise 'No judges tested :(' unless opts['quiet']
|
86
|
+
@loog.debug('Not failing the build with no judges tested, due to the --quiet option')
|
75
87
|
end
|
76
88
|
|
77
89
|
private
|
@@ -82,9 +94,10 @@ class Judges::Test
|
|
82
94
|
packs.include?(name)
|
83
95
|
end
|
84
96
|
|
85
|
-
def test_one(pack, yaml)
|
97
|
+
def test_one(opts, pack, yaml)
|
86
98
|
fb = Factbase.new
|
87
|
-
yaml['input']
|
99
|
+
inputs = yaml['input']
|
100
|
+
inputs&.each do |i|
|
88
101
|
f = fb.insert
|
89
102
|
i.each do |k, vv|
|
90
103
|
if vv.is_a?(Array)
|
@@ -96,9 +109,12 @@ class Judges::Test
|
|
96
109
|
end
|
97
110
|
end
|
98
111
|
end
|
99
|
-
|
112
|
+
options = Judges::Options.new(opts['option']) + Judges::Options.new(yaml['options'])
|
113
|
+
pack.run(Factbase::Looged.new(fb, @loog), {}, {}, options)
|
114
|
+
xpaths = yaml['expected']
|
115
|
+
return if xpaths.nil?
|
100
116
|
xml = Nokogiri::XML.parse(Factbase::ToXML.new(fb).xml)
|
101
|
-
|
117
|
+
xpaths.each do |xp|
|
102
118
|
raise "#{pack.script} doesn't match '#{xp}':\n#{xml}" if xml.xpath(xp).empty?
|
103
119
|
end
|
104
120
|
end
|
@@ -57,9 +57,12 @@ class Judges::Update
|
|
57
57
|
end
|
58
58
|
diff = cycle(opts, packs, fb, options)
|
59
59
|
impex.export(fb)
|
60
|
-
|
60
|
+
if diff.zero?
|
61
|
+
@loog.info("The update cycle ##{c} has made no changes to the factbase, let's stop")
|
62
|
+
break
|
63
|
+
end
|
61
64
|
if !opts['max-cycles'].nil? && c >= opts['max-cycles']
|
62
|
-
@loog.info(
|
65
|
+
@loog.info("Too many cycles already, as set by --max-cycles=#{opts['max-cycles']}, breaking")
|
63
66
|
break
|
64
67
|
end
|
65
68
|
@loog.info(
|
data/lib/judges/fb/if_absent.rb
CHANGED
@@ -31,9 +31,9 @@ def if_absent(fb)
|
|
31
31
|
q = attrs.map do |k, v|
|
32
32
|
vv = v.to_s
|
33
33
|
if v.is_a?(String)
|
34
|
-
vv = "'#{vv.gsub('"', '
|
34
|
+
vv = "'#{vv.gsub('"', '\\\\"').gsub("'", "\\\\'")}'"
|
35
35
|
elsif v.is_a?(Time)
|
36
|
-
vv = v.iso8601
|
36
|
+
vv = v.utc.iso8601
|
37
37
|
end
|
38
38
|
"(eq #{k} #{vv})"
|
39
39
|
end.join(' ')
|
@@ -55,8 +55,11 @@ class Judges::Accumulator
|
|
55
55
|
|
56
56
|
def method_missing(*args)
|
57
57
|
k = args[0]
|
58
|
-
|
59
|
-
|
58
|
+
if k.end_with?('=')
|
59
|
+
@map[k[0..-2].to_sym] = args[1]
|
60
|
+
else
|
61
|
+
@map[k.to_sym]
|
62
|
+
end
|
60
63
|
end
|
61
64
|
|
62
65
|
# rubocop:disable Style/OptionalBooleanParameter
|
data/lib/judges/fb/once.rb
CHANGED
@@ -21,43 +21,34 @@
|
|
21
21
|
# SOFTWARE.
|
22
22
|
|
23
23
|
require 'judges'
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
# License:: MIT
|
34
|
-
class Judges::Once
|
35
|
-
def initialize(fb, func)
|
36
|
-
@fb = fb
|
37
|
-
@func = func
|
38
|
-
end
|
39
|
-
|
40
|
-
def query(expr)
|
41
|
-
expr = "(and #{expr} (not (eq seen '#{@func}')))"
|
42
|
-
After.new(@fb.query(expr), @func)
|
43
|
-
end
|
44
|
-
|
45
|
-
def insert
|
46
|
-
@fb.insert
|
24
|
+
require 'factbase/tuples'
|
25
|
+
|
26
|
+
# Returns a decorated global factbase, which only touches facts once.
|
27
|
+
def each_once(fb, query, judge: $judge)
|
28
|
+
return to_enum(__method__, fb, query, judge:) unless block_given?
|
29
|
+
q = "(and #{query} (not (eq seen '#{judge}')))"
|
30
|
+
fb.query(q).each do |f|
|
31
|
+
yield f
|
32
|
+
f.seen = judge
|
47
33
|
end
|
34
|
+
end
|
48
35
|
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
36
|
+
# Returns a decorated global factbase, which only touches a tuple once.
|
37
|
+
def each_tuple_once(fb, *queries, judge: $judge)
|
38
|
+
return to_enum(__method__, fb, *queries, judge:) unless block_given?
|
39
|
+
qq = queries.map { |q| "(and #{q} (not (eq seen '#{judge}')))" }
|
40
|
+
Factbase::Tuples.new(fb, qq).each do |fs|
|
41
|
+
yield fs
|
42
|
+
fs.each do |f|
|
43
|
+
f.seen = judge
|
54
44
|
end
|
45
|
+
end
|
46
|
+
end
|
55
47
|
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
end
|
48
|
+
def each_tuple_once_txn(fb, *queries, judge: $judge)
|
49
|
+
fb.txn do |fbt|
|
50
|
+
each_tuple_once(fb, *queries, judge:) do |fs|
|
51
|
+
yield [fbt] + fs
|
61
52
|
end
|
62
53
|
end
|
63
54
|
end
|
data/lib/judges/options.rb
CHANGED
@@ -28,11 +28,21 @@ require_relative '../judges'
|
|
28
28
|
# License:: MIT
|
29
29
|
class Judges::Options
|
30
30
|
# Ctor.
|
31
|
-
# @param
|
31
|
+
# @param [Array<String>] pairs List of pairs, like ["token=af73cd3", "max_speed=1"]
|
32
32
|
def initialize(pairs = nil)
|
33
33
|
@pairs = pairs
|
34
34
|
end
|
35
35
|
|
36
|
+
def +(other)
|
37
|
+
touch # this will trigger method_missing() method, which will create @hash
|
38
|
+
h = @hash.dup
|
39
|
+
other.touch # this will trigger method_missing() method, which will create @hash
|
40
|
+
other.instance_variable_get(:@hash).each do |k, v|
|
41
|
+
h[k] = v
|
42
|
+
end
|
43
|
+
Judges::Options.new(h.map { |k, v| "#{k}=#{v}" })
|
44
|
+
end
|
45
|
+
|
36
46
|
# Convert them all to a string (printable in a log).
|
37
47
|
def to_s
|
38
48
|
touch # this will trigger method_missing() method, which will create @hash
|
data/lib/judges/pack.rb
CHANGED
data/lib/judges.rb
CHANGED
@@ -0,0 +1,58 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Copyright (c) 2024 Yegor Bugayenko
|
4
|
+
#
|
5
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
# of this software and associated documentation files (the 'Software'), to deal
|
7
|
+
# in the Software without restriction, including without limitation the rights
|
8
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
# copies of the Software, and to permit persons to whom the Software is
|
10
|
+
# furnished to do so, subject to the following conditions:
|
11
|
+
#
|
12
|
+
# The above copyright notice and this permission notice shall be included in all
|
13
|
+
# copies or substantial portions of the Software.
|
14
|
+
#
|
15
|
+
# THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
+
# SOFTWARE.
|
22
|
+
|
23
|
+
require 'minitest/autorun'
|
24
|
+
require 'webmock/minitest'
|
25
|
+
require 'loog'
|
26
|
+
require 'factbase'
|
27
|
+
require_relative '../../lib/judges'
|
28
|
+
require_relative '../../lib/judges/commands/pull'
|
29
|
+
|
30
|
+
# Test.
|
31
|
+
# Author:: Yegor Bugayenko (yegor256@gmail.com)
|
32
|
+
# Copyright:: Copyright (c) 2024 Yegor Bugayenko
|
33
|
+
# License:: MIT
|
34
|
+
class TestPull < Minitest::Test
|
35
|
+
def test_pull_simple_factbase
|
36
|
+
WebMock.disable_net_connect!
|
37
|
+
stub_request(:get, 'http://example.org/exists/foo').to_return(body: 'yes')
|
38
|
+
stub_request(:get, 'http://example.org/recent/foo.txt').to_return(body: '42')
|
39
|
+
stub_request(:get, 'http://example.org/finished/42').to_return(body: 'yes')
|
40
|
+
fb = Factbase.new
|
41
|
+
fb.insert.foo = 42
|
42
|
+
stub_request(:get, 'http://example.org/pull/42.fb').to_return(body: fb.export)
|
43
|
+
Dir.mktmpdir do |d|
|
44
|
+
file = File.join(d, 'base.fb')
|
45
|
+
Judges::Pull.new(Loog::NULL).run(
|
46
|
+
{
|
47
|
+
'token' => '000',
|
48
|
+
'host' => 'example.org',
|
49
|
+
'port' => 80,
|
50
|
+
'ssl' => false
|
51
|
+
},
|
52
|
+
['foo', file]
|
53
|
+
)
|
54
|
+
fb = Factbase.new
|
55
|
+
fb.import(File.binread(file))
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,77 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Copyright (c) 2024 Yegor Bugayenko
|
4
|
+
#
|
5
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
# of this software and associated documentation files (the 'Software'), to deal
|
7
|
+
# in the Software without restriction, including without limitation the rights
|
8
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
# copies of the Software, and to permit persons to whom the Software is
|
10
|
+
# furnished to do so, subject to the following conditions:
|
11
|
+
#
|
12
|
+
# The above copyright notice and this permission notice shall be included in all
|
13
|
+
# copies or substantial portions of the Software.
|
14
|
+
#
|
15
|
+
# THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
+
# SOFTWARE.
|
22
|
+
|
23
|
+
require 'minitest/autorun'
|
24
|
+
require 'webmock/minitest'
|
25
|
+
require 'loog'
|
26
|
+
require_relative '../../lib/judges'
|
27
|
+
require_relative '../../lib/judges/commands/push'
|
28
|
+
|
29
|
+
# Test.
|
30
|
+
# Author:: Yegor Bugayenko (yegor256@gmail.com)
|
31
|
+
# Copyright:: Copyright (c) 2024 Yegor Bugayenko
|
32
|
+
# License:: MIT
|
33
|
+
class TestPush < Minitest::Test
|
34
|
+
def test_push_simple_factbase
|
35
|
+
WebMock.disable_net_connect!
|
36
|
+
stub_request(:put, 'https://example.org/push/foo').to_return(
|
37
|
+
status: 200, body: '42'
|
38
|
+
)
|
39
|
+
Dir.mktmpdir do |d|
|
40
|
+
file = File.join(d, 'base.fb')
|
41
|
+
fb = Factbase.new
|
42
|
+
fb.insert.foo_bar = 42
|
43
|
+
File.binwrite(file, fb.export)
|
44
|
+
Judges::Push.new(Loog::NULL).run(
|
45
|
+
{
|
46
|
+
'token' => '000',
|
47
|
+
'host' => 'example.org',
|
48
|
+
'port' => 443,
|
49
|
+
'ssl' => true
|
50
|
+
},
|
51
|
+
['foo', file]
|
52
|
+
)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def test_fails_on_http_error
|
57
|
+
WebMock.disable_net_connect!
|
58
|
+
stub_request(:put, 'http://example.org/push/foo').to_return(status: 500)
|
59
|
+
Dir.mktmpdir do |d|
|
60
|
+
file = File.join(d, 'base.fb')
|
61
|
+
fb = Factbase.new
|
62
|
+
fb.insert.foo_bar = 42
|
63
|
+
File.binwrite(file, fb.export)
|
64
|
+
assert_raises do
|
65
|
+
Judges::Push.new(Loog::NULL).run(
|
66
|
+
{
|
67
|
+
'token' => '000',
|
68
|
+
'host' => 'example.org',
|
69
|
+
'port' => 80,
|
70
|
+
'ssl' => false
|
71
|
+
},
|
72
|
+
['foo', file]
|
73
|
+
)
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
data/test/fb/test_if_absent.rb
CHANGED
@@ -60,6 +60,13 @@ class TestIfAbsent < Minitest::Test
|
|
60
60
|
assert_equal(42, n.foo)
|
61
61
|
end
|
62
62
|
|
63
|
+
def test_injects_and_reads
|
64
|
+
if_absent(Factbase.new) do |f|
|
65
|
+
f.foo = 42
|
66
|
+
assert_equal(42, f.foo)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
63
70
|
def test_complex_ignores
|
64
71
|
fb = Factbase.new
|
65
72
|
f1 = fb.insert
|
@@ -86,7 +93,7 @@ class TestIfAbsent < Minitest::Test
|
|
86
93
|
f1.z = t
|
87
94
|
f1.bar = 3.14
|
88
95
|
n = if_absent(fb) do |f|
|
89
|
-
f.foo = "hello, \\\"dude\\\" \\' \\' ( \n\n ) (!"
|
96
|
+
f.foo = "hello, \\\"dude\\\" \\' \\' ( \n\n ) (! '"
|
90
97
|
f.abc = 42
|
91
98
|
f.z = t + 1
|
92
99
|
f.bar = 3.15
|
data/test/fb/test_once.rb
CHANGED
@@ -21,7 +21,6 @@
|
|
21
21
|
# SOFTWARE.
|
22
22
|
|
23
23
|
require 'minitest/autorun'
|
24
|
-
require 'tmpdir'
|
25
24
|
require 'factbase'
|
26
25
|
require_relative '../../lib/judges'
|
27
26
|
require_relative '../../lib/judges/fb/once'
|
@@ -32,9 +31,58 @@ require_relative '../../lib/judges/fb/once'
|
|
32
31
|
# License:: MIT
|
33
32
|
class TestOnce < Minitest::Test
|
34
33
|
def test_touch_once
|
35
|
-
fb =
|
34
|
+
fb = Factbase.new
|
36
35
|
fb.insert
|
37
|
-
fb
|
38
|
-
assert(fb
|
36
|
+
assert(!each_once(fb, '(always)', judge: 'something').to_a.empty?)
|
37
|
+
assert(each_once(fb, '(always)', judge: 'something').to_a.empty?)
|
38
|
+
end
|
39
|
+
|
40
|
+
def test_seen_property
|
41
|
+
fb = Factbase.new
|
42
|
+
f1 = fb.insert
|
43
|
+
f1.foo = 42
|
44
|
+
assert_equal(1, each_tuple_once(fb, '(eq foo 42)', judge: 'x').to_a.size)
|
45
|
+
assert(each_tuple_once(fb, '(eq foo 42)', judge: 'x').to_a.empty?)
|
46
|
+
end
|
47
|
+
|
48
|
+
def test_seen_all_or_nothing
|
49
|
+
fb = Factbase.new
|
50
|
+
f1 = fb.insert
|
51
|
+
f1.a = 1
|
52
|
+
assert(each_tuple_once(fb, '(exists a)', '(exists b)', judge: 'x').to_a.empty?)
|
53
|
+
f2 = fb.insert
|
54
|
+
f2.b = 1
|
55
|
+
assert(!each_tuple_once(fb, '(exists a)', '(exists b)', judge: 'x').to_a.empty?)
|
56
|
+
assert(each_tuple_once(fb, '(exists a)', '(exists b)', judge: 'x').to_a.empty?)
|
57
|
+
end
|
58
|
+
|
59
|
+
def test_with_txn
|
60
|
+
fb = Factbase.new
|
61
|
+
f1 = fb.insert
|
62
|
+
f1.foo = 42
|
63
|
+
each_tuple_once(fb, '(exists foo)', judge: 'xx') do |fs|
|
64
|
+
fb.txn do |fbt|
|
65
|
+
f = fbt.insert
|
66
|
+
f.bar = 1
|
67
|
+
end
|
68
|
+
fs[0].xyz = 'hey'
|
69
|
+
end
|
70
|
+
assert_equal(1, fb.query('(exists seen)').each.to_a.size)
|
71
|
+
assert_equal(1, fb.query('(exists bar)').each.to_a.size)
|
72
|
+
assert_equal(1, fb.query('(exists xyz)').each.to_a.size)
|
73
|
+
end
|
74
|
+
|
75
|
+
def test_with_chain_txn
|
76
|
+
fb = Factbase.new
|
77
|
+
f1 = fb.insert
|
78
|
+
f1.foo = 42
|
79
|
+
each_tuple_once_txn(fb, '(exists foo)', judge: 'xx') do |fbt, ff|
|
80
|
+
f = fbt.insert
|
81
|
+
f.bar = 1
|
82
|
+
ff.xyz = 'hey'
|
83
|
+
end
|
84
|
+
assert_equal(1, fb.query('(exists seen)').each.to_a.size)
|
85
|
+
assert_equal(1, fb.query('(exists bar)').each.to_a.size)
|
86
|
+
assert_equal(1, fb.query('(exists xyz)').each.to_a.size)
|
39
87
|
end
|
40
88
|
end
|
data/test/test_baza.rb
ADDED
@@ -0,0 +1,75 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Copyright (c) 2024 Yegor Bugayenko
|
4
|
+
#
|
5
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
# of this software and associated documentation files (the 'Software'), to deal
|
7
|
+
# in the Software without restriction, including without limitation the rights
|
8
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
# copies of the Software, and to permit persons to whom the Software is
|
10
|
+
# furnished to do so, subject to the following conditions:
|
11
|
+
#
|
12
|
+
# The above copyright notice and this permission notice shall be included in all
|
13
|
+
# copies or substantial portions of the Software.
|
14
|
+
#
|
15
|
+
# THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
+
# SOFTWARE.
|
22
|
+
|
23
|
+
require 'minitest/autorun'
|
24
|
+
require 'webmock/minitest'
|
25
|
+
require 'loog'
|
26
|
+
require_relative '../lib/judges'
|
27
|
+
require_relative '../lib/judges/baza'
|
28
|
+
|
29
|
+
# Test.
|
30
|
+
# Author:: Yegor Bugayenko (yegor256@gmail.com)
|
31
|
+
# Copyright:: Copyright (c) 2024 Yegor Bugayenko
|
32
|
+
# License:: MIT
|
33
|
+
class TestBaza < Minitest::Test
|
34
|
+
def test_simple_push
|
35
|
+
WebMock.disable_net_connect!
|
36
|
+
stub_request(:put, 'https://example.org/push/simple').to_return(
|
37
|
+
status: 200, body: '42'
|
38
|
+
)
|
39
|
+
assert_equal(
|
40
|
+
42,
|
41
|
+
Judges::Baza.new('example.org', 443, '000').push('simple', 'hello, world!')
|
42
|
+
)
|
43
|
+
end
|
44
|
+
|
45
|
+
def test_simple_recent_check
|
46
|
+
WebMock.disable_net_connect!
|
47
|
+
stub_request(:get, 'https://example.org/recent/simple.txt').to_return(
|
48
|
+
status: 200, body: '42'
|
49
|
+
)
|
50
|
+
assert_equal(
|
51
|
+
42,
|
52
|
+
Judges::Baza.new('example.org', 443, '000').recent('simple')
|
53
|
+
)
|
54
|
+
end
|
55
|
+
|
56
|
+
def test_simple_exists_check
|
57
|
+
WebMock.disable_net_connect!
|
58
|
+
stub_request(:get, 'https://example.org/exists/simple').to_return(
|
59
|
+
status: 200, body: 'yes'
|
60
|
+
)
|
61
|
+
assert(
|
62
|
+
Judges::Baza.new('example.org', 443, '000').name_exists?('simple')
|
63
|
+
)
|
64
|
+
end
|
65
|
+
|
66
|
+
def test_simple_pull
|
67
|
+
WebMock.disable_net_connect!
|
68
|
+
stub_request(:get, 'https://example.org/pull/333.fb').to_return(
|
69
|
+
status: 200, body: 'hello, world!'
|
70
|
+
)
|
71
|
+
assert(
|
72
|
+
Judges::Baza.new('example.org', 443, '000').pull(333).start_with?('hello')
|
73
|
+
)
|
74
|
+
end
|
75
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Copyright (c) 2024 Yegor Bugayenko
|
4
|
+
#
|
5
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
# of this software and associated documentation files (the 'Software'), to deal
|
7
|
+
# in the Software without restriction, including without limitation the rights
|
8
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
# copies of the Software, and to permit persons to whom the Software is
|
10
|
+
# furnished to do so, subject to the following conditions:
|
11
|
+
#
|
12
|
+
# The above copyright notice and this permission notice shall be included in all
|
13
|
+
# copies or substantial portions of the Software.
|
14
|
+
#
|
15
|
+
# THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
+
# SOFTWARE.
|
22
|
+
|
23
|
+
require 'minitest/autorun'
|
24
|
+
require_relative '../lib/judges'
|
25
|
+
require_relative '../lib/judges/categories'
|
26
|
+
|
27
|
+
# Test.
|
28
|
+
# Author:: Yegor Bugayenko (yegor256@gmail.com)
|
29
|
+
# Copyright:: Copyright (c) 2024 Yegor Bugayenko
|
30
|
+
# License:: MIT
|
31
|
+
class TestCategories < Minitest::Test
|
32
|
+
def test_basic
|
33
|
+
cats = Judges::Categories.new(%w[foo bar], ['bad'])
|
34
|
+
assert(cats.ok?(%w[foo other]))
|
35
|
+
assert(cats.ok?(%w[other more bar]))
|
36
|
+
assert(!cats.ok?(%w[bad other]))
|
37
|
+
assert(!cats.ok?(['other']))
|
38
|
+
assert(!cats.ok?('hey'))
|
39
|
+
assert(!cats.ok?(nil))
|
40
|
+
end
|
41
|
+
|
42
|
+
def test_all_enabled
|
43
|
+
cats = Judges::Categories.new([], ['bad'])
|
44
|
+
assert(cats.ok?(nil))
|
45
|
+
assert(cats.ok?('hey'))
|
46
|
+
assert(cats.ok?(%w[foo other]))
|
47
|
+
assert(cats.ok?(%w[other more bar]))
|
48
|
+
assert(!cats.ok?(%w[bad other]))
|
49
|
+
end
|
50
|
+
end
|
data/test/test_options.rb
CHANGED
@@ -75,4 +75,12 @@ class TestOptions < Minitest::Test
|
|
75
75
|
assert(s.include?('foo → "44"'))
|
76
76
|
assert(s.include?('"long********************"'))
|
77
77
|
end
|
78
|
+
|
79
|
+
def test_merge
|
80
|
+
left = Judges::Options.new(['a = 1', 'b = 4'])
|
81
|
+
right = Judges::Options.new(['a = 44', 'c = 3'])
|
82
|
+
opts = left + right
|
83
|
+
assert_equal(44, opts.a)
|
84
|
+
assert_equal(3, opts.c)
|
85
|
+
end
|
78
86
|
end
|