judges 0.0.33 → 0.0.35

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
@@ -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
- done = 0
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
- @loog.info("Testing #{f.to_rel}:")
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
- done += 1
74
+ packs += 1
68
75
  end
69
- throw :'👍 No judges tested' if done.zero?
70
- throw :"👍 All #{done} judge(s) tested successfully" if errors.empty?
71
- throw :"❌ #{done} judge(s) tested, #{errors.size} of them failed"
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
- raise "#{errors.size} tests failed" unless opts['quiet'] || errors.empty?
74
- raise 'No judges tested :(' unless opts['quiet'] || !done.zero?
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'].each do |i|
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
- pack.run(Factbase::Looged.new(fb, @loog), {}, {}, Judges::Options.new(yaml['options']))
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
- yaml['expected'].each do |xp|
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
- break if diff.zero?
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('Too many cycles already, as set by --max-cycles, breaking')
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(
@@ -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('"', '\\"').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
- raise "Unexpected interation with the fact: '#{k}'" unless k.end_with?('=')
59
- @map[k[0..-2]] = args[1]
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
@@ -21,43 +21,34 @@
21
21
  # SOFTWARE.
22
22
 
23
23
  require 'judges'
24
-
25
- # Returns a decorated global factbase, which only touches facts once
26
- def once(fb, judge: $judge)
27
- Judges::Once.new(fb, judge)
28
- end
29
-
30
- # Runs only once.
31
- # Author:: Yegor Bugayenko (yegor256@gmail.com)
32
- # Copyright:: Copyright (c) 2024 Yegor Bugayenko
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
- # What happens after a fact is processed.
50
- class After
51
- def initialize(query, func)
52
- @query = query
53
- @func = func
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
- def each
57
- @query.each do |f|
58
- yield f
59
- f.seen = @func
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
@@ -28,11 +28,21 @@ require_relative '../judges'
28
28
  # License:: MIT
29
29
  class Judges::Options
30
30
  # Ctor.
31
- # @param pairs [Array<String>] List of pairs, like ["token=af73cd3", "max_speed=1"]
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
@@ -58,7 +58,6 @@ class Judges::Pack
58
58
  raise "Can't load '#{s}'" unless File.exist?(s)
59
59
  elapsed(@loog) do
60
60
  load(s, true)
61
- throw :"#{name} finished"
62
61
  ensure
63
62
  $fb = $judge = $options = $loog = nil
64
63
  end
data/lib/judges.rb CHANGED
@@ -24,4 +24,6 @@
24
24
  # Author:: Yegor Bugayenko (yegor256@gmail.com)
25
25
  # Copyright:: Copyright (c) 2024 Yegor Bugayenko
26
26
  # License:: MIT
27
- module Judges; end
27
+ module Judges
28
+ VERSION = '0.0.35'
29
+ end
@@ -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
@@ -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 = once(Factbase.new, judge: 'something')
34
+ fb = Factbase.new
36
35
  fb.insert
37
- fb.query('(always)').each { |f| f.foo = 42 }
38
- assert(fb.query('(always)').extend(Enumerable).to_a.empty?)
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