judges 0.20.0 → 0.22.0

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.
@@ -51,9 +51,14 @@ class Judges::Pull
51
51
  )
52
52
  name = args[0]
53
53
  elapsed(@loog) do
54
+ baza.lock(name, opts['owner'])
54
55
  if baza.name_exists?(name)
55
- baza.lock(name, opts['owner'])
56
- fb.import(baza.pull(wait(name, baza, baza.recent(name), opts['wait'])))
56
+ jid = baza.recent(name)
57
+ unless baza.exit_code(jid).zero?
58
+ @loog.warn("STDOUT of the job ##{jid} (from the server):\n#{baza.stdout(jid)}")
59
+ raise "The job ##{jid} ('#{name}') is broken, maybe you should expire it"
60
+ end
61
+ fb.import(baza.pull(wait(name, baza, jid, opts['wait'])))
57
62
  Judges::Impex.new(@loog, args[1]).export(fb)
58
63
  throw :"Pulled #{fb.size} facts by the name '#{name}'"
59
64
  else
@@ -48,7 +48,8 @@ class Judges::Push
48
48
  ssl: opts['ssl'],
49
49
  timeout: (opts['timeout'] || 30).to_i,
50
50
  loog: @loog,
51
- retries: (opts['retries'] || 3).to_i
51
+ retries: (opts['retries'] || 3).to_i,
52
+ compression: opts.fetch('zip', true)
52
53
  )
53
54
  elapsed(@loog) do
54
55
  baza.lock(name, opts['owner'])
@@ -82,6 +82,12 @@ class Judges::Test
82
82
  test_one(fb, opts, j, n, yaml, assert: false)
83
83
  end
84
84
  test_one(fb, opts, judge, tname, yaml)
85
+ yaml['after']&.each do |rb|
86
+ @loog.info("Running #{rb} assertion script...")
87
+ $fb = fb
88
+ $loog = @loog
89
+ load(File.join(judge.dir, rb), true)
90
+ end
85
91
  tests += 1
86
92
  rescue StandardError => e
87
93
  @loog.warn(Backtrace.new(e))
@@ -64,7 +64,7 @@ class Judges::Update
64
64
  loop do
65
65
  c += 1
66
66
  if c > 1
67
- @loog.info("\n\nStarting cycle ##{c}#{opts['max-cycles'] ? " (out of #{opts['max-cycles']})" : ''}...")
67
+ @loog.info("\nStarting cycle ##{c}#{opts['max-cycles'] ? " (out of #{opts['max-cycles']})" : ''}...")
68
68
  end
69
69
  delta = cycle(opts, judges, fb, options)
70
70
  churn += delta
@@ -103,17 +103,18 @@ class Judges::Update
103
103
  churn = Judges::Churn.new(0, 0)
104
104
  global = {}
105
105
  elapsed(@loog) do
106
- done = judges.each_with_index do |p, i|
107
- @loog.info("\nšŸ‘‰ Running #{p.name} (##{i}) at #{p.dir.to_rel}...")
108
- elapsed(@loog) do
109
- c = one_judge(fb, p, global, options)
110
- churn += c
111
- throw :"šŸ‘ The judge #{p.name} modified #{c} facts out of #{fb.size}"
106
+ done =
107
+ judges.each_with_index do |p, i|
108
+ @loog.info("\nšŸ‘‰ Running #{p.name} (##{i}) at #{p.dir.to_rel}...")
109
+ elapsed(@loog) do
110
+ c = one_judge(fb, p, global, options)
111
+ churn += c
112
+ throw :"šŸ‘ The judge #{p.name} modified #{c} facts out of #{fb.size}"
113
+ end
114
+ rescue StandardError, SyntaxError => e
115
+ @loog.warn(Backtrace.new(e))
116
+ churn << e.message
112
117
  end
113
- rescue StandardError, SyntaxError => e
114
- @loog.warn(Backtrace.new(e))
115
- churn << e.message
116
- end
117
118
  throw :"šŸ‘ #{done} judge(s) processed" if churn.errors.empty?
118
119
  throw :"āŒ #{done} judge(s) processed with #{churn.errors.size} errors"
119
120
  end
data/lib/judges/judge.rb CHANGED
@@ -70,9 +70,10 @@ class Judges::Judge
70
70
 
71
71
  # Get the name of the .rb script in the judge.
72
72
  def script
73
- s = Dir.glob(File.join(@dir, '*.rb')).first
74
- raise "No *.rb scripts in #{@dir.to_rel}" if s.nil?
75
- File.basename(s)
73
+ b = "#{File.basename(@dir)}.rb"
74
+ files = Dir.glob(File.join(@dir, '*.rb')).map { |f| File.basename(f) }
75
+ raise "No #{b} script in #{@dir.to_rel} among #{files}" unless files.include?(b)
76
+ b
76
77
  end
77
78
 
78
79
  # Return all .yml tests files.
data/lib/judges/judges.rb CHANGED
@@ -24,6 +24,20 @@ require_relative '../judges'
24
24
  require_relative 'judge'
25
25
 
26
26
  # Collection of all judges to run.
27
+ #
28
+ # In the directory +dir+ the following structure must be maintained:
29
+ #
30
+ # dir/
31
+ # judge-one/
32
+ # judge-one.rb
33
+ # other files...
34
+ # judge-two/
35
+ # judge-two.rb
36
+ # other files...
37
+ #
38
+ # The name of a directory of a judge must be exactly the same as the
39
+ # name of the +.rb+ script inside the directory.
40
+ #
27
41
  # Author:: Yegor Bugayenko (yegor256@gmail.com)
28
42
  # Copyright:: Copyright (c) 2024 Yegor Bugayenko
29
43
  # License:: MIT
@@ -45,9 +59,12 @@ class Judges::Judges
45
59
  # Iterate over them all.
46
60
  # @yield [Judge]
47
61
  def each
48
- Dir.glob(File.join(@dir, '**/*.rb')).each do |f|
49
- d = File.dirname(File.absolute_path(f))
50
- yield Judges::Judge.new(d, @lib, @loog)
62
+ return to_enum(__method__) unless block_given?
63
+ Dir.glob(File.join(@dir, '*')).each do |d|
64
+ next unless File.directory?(d)
65
+ b = File.basename(d)
66
+ next unless File.exist?(File.join(d, "#{b}.rb"))
67
+ yield Judges::Judge.new(File.absolute_path(d), @lib, @loog)
51
68
  end
52
69
  end
53
70
 
@@ -50,34 +50,35 @@ class Judges::Options
50
50
  def to_s
51
51
  to_h.map do |k, v|
52
52
  v = v.to_s
53
- v = "#{v[0..3]}#{'*' * (v.length - 4)}" if v.length > 8
53
+ v = "#{v[0..3]}#{'*' * (v.length - 8)}#{v[-4..]}" if v.length > 8
54
54
  "#{k} → \"#{v}\""
55
- end.join("\n")
55
+ end.sort.join("\n")
56
56
  end
57
57
 
58
58
  def to_h
59
- @to_h ||= begin
60
- pp = @pairs || []
61
- pp = pp.split(',') if pp.is_a?(String)
62
- if pp.is_a?(Array)
63
- pp = pp
64
- .compact
65
- .map(&:strip)
66
- .reject(&:empty?)
67
- .map { |s| s.split('=', 2) }
68
- .map { |a| a.size == 1 ? [a[0], nil] : a }
69
- .reject { |a| a[0].empty? }
59
+ @to_h ||=
60
+ begin
61
+ pp = @pairs || []
62
+ pp = pp.split(',') if pp.is_a?(String)
63
+ if pp.is_a?(Array)
64
+ pp = pp
65
+ .compact
66
+ .map(&:strip)
67
+ .reject(&:empty?)
68
+ .map { |s| s.split('=', 2) }
69
+ .map { |a| a.size == 1 ? [a[0], nil] : a }
70
+ .reject { |a| a[0].empty? }
71
+ .to_h
72
+ end
73
+ pp
74
+ .reject { |k, _| k.nil? }
75
+ .reject { |k, _| k.is_a?(String) && k.empty? }
70
76
  .to_h
77
+ .transform_values { |v| v.nil? ? 'true' : v }
78
+ .transform_values { |v| v.is_a?(String) ? v.strip : v }
79
+ .transform_values { |v| v.is_a?(String) && v.match?(/^[0-9]+$/) ? v.to_i : v }
80
+ .transform_keys { |k| k.to_s.strip.upcase.to_sym }
71
81
  end
72
- pp
73
- .reject { |k, _| k.nil? }
74
- .reject { |k, _| k.is_a?(String) && k.empty? }
75
- .to_h
76
- .transform_values { |v| v.nil? ? 'true' : v }
77
- .transform_values { |v| v.is_a?(String) ? v.strip : v }
78
- .transform_values { |v| v.is_a?(String) && v.match?(/^[0-9]+$/) ? v.to_i : v }
79
- .transform_keys { |k| k.to_s.strip.upcase.to_sym }
80
- end
81
82
  end
82
83
 
83
84
  # Get option by name.
data/lib/judges.rb CHANGED
@@ -25,5 +25,5 @@
25
25
  # Copyright:: Copyright (c) 2024 Yegor Bugayenko
26
26
  # License:: MIT
27
27
  module Judges
28
- VERSION = '0.20.0'
28
+ VERSION = '0.22.0'
29
29
  end
@@ -36,7 +36,7 @@ class TestImport < Minitest::Test
36
36
  Dir.mktmpdir do |d|
37
37
  file = File.join(d, 'base.fb')
38
38
  yaml = File.join(d, 'input.yml')
39
- File.write(
39
+ save_it(
40
40
  yaml,
41
41
  <<-YAML
42
42
  -
@@ -38,6 +38,7 @@ class TestPull < Minitest::Test
38
38
  stub_request(:get, 'http://example.org/exists/foo').to_return(body: 'yes')
39
39
  stub_request(:get, 'http://example.org/recent/foo.txt').to_return(body: '42')
40
40
  stub_request(:get, 'http://example.org/finished/42').to_return(body: 'yes')
41
+ stub_request(:get, 'http://example.org/exit/42').to_return(body: '0')
41
42
  fb = Factbase.new
42
43
  fb.insert.foo = 42
43
44
  stub_request(:get, 'http://example.org/pull/42.fb').to_return(body: fb.export)
@@ -58,4 +59,32 @@ class TestPull < Minitest::Test
58
59
  fb.import(File.binread(file))
59
60
  end
60
61
  end
62
+
63
+ def test_fail_pull_when_job_is_broken
64
+ WebMock.disable_net_connect!
65
+ stub_request(:get, 'http://example.org/lock/foo?owner=none').to_return(status: 302)
66
+ stub_request(:get, 'http://example.org/exists/foo').to_return(body: 'yes')
67
+ stub_request(:get, 'http://example.org/recent/foo.txt').to_return(body: '42')
68
+ stub_request(:get, 'http://example.org/finished/42').to_return(body: 'yes')
69
+ stub_request(:get, 'http://example.org/exit/42').to_return(body: '1')
70
+ stub_request(:get, 'http://example.org/stdout/42').to_return(body: 'oops, some trouble here')
71
+ Dir.mktmpdir do |d|
72
+ file = File.join(d, 'base.fb')
73
+ e =
74
+ assert_raises do
75
+ Judges::Pull.new(Loog::NULL).run(
76
+ {
77
+ 'token' => '000',
78
+ 'host' => 'example.org',
79
+ 'port' => 80,
80
+ 'ssl' => false,
81
+ 'wait' => 10,
82
+ 'owner' => 'none'
83
+ },
84
+ ['foo', file]
85
+ )
86
+ end
87
+ assert(e.message.include?('expire it'), e)
88
+ end
89
+ end
61
90
  end
@@ -32,9 +32,9 @@ require_relative '../../lib/judges/commands/test'
32
32
  class TestTest < Minitest::Test
33
33
  def test_positive
34
34
  Dir.mktmpdir do |d|
35
- File.write(File.join(d, 'foo.rb'), '$fb.query("(eq foo 42)").each { |f| f.bar = 4 }')
36
- File.write(
37
- File.join(d, 'something.yml'),
35
+ save_it(File.join(d, 'foo/foo.rb'), '$fb.query("(eq foo 42)").each { |f| f.bar = 4 }')
36
+ save_it(
37
+ File.join(d, 'foo/something.yml'),
38
38
  <<-YAML
39
39
  input:
40
40
  -
@@ -51,9 +51,9 @@ class TestTest < Minitest::Test
51
51
 
52
52
  def test_negative
53
53
  Dir.mktmpdir do |d|
54
- File.write(File.join(d, 'foo.rb'), '$fb.query("(eq foo 42)").each { |f| f.bar = 4 }')
55
- File.write(
56
- File.join(d, 'something.yml'),
54
+ save_it(File.join(d, 'foo/foo.rb'), '$fb.query("(eq foo 42)").each { |f| f.bar = 4 }')
55
+ save_it(
56
+ File.join(d, 'foo/something.yml'),
57
57
  <<-YAML
58
58
  input:
59
59
  -
@@ -72,9 +72,9 @@ class TestTest < Minitest::Test
72
72
 
73
73
  def test_with_options
74
74
  Dir.mktmpdir do |d|
75
- File.write(File.join(d, 'foo.rb'), '$fb.insert.foo = $options.bar')
76
- File.write(
77
- File.join(d, 'something.yml'),
75
+ save_it(File.join(d, 'foo/foo.rb'), '$fb.insert.foo = $options.bar')
76
+ save_it(
77
+ File.join(d, 'foo/something.yml'),
78
78
  <<-YAML
79
79
  input: []
80
80
  options:
@@ -90,13 +90,10 @@ class TestTest < Minitest::Test
90
90
 
91
91
  def test_with_before
92
92
  Dir.mktmpdir do |d|
93
- home = File.join(d, 'judges')
94
- FileUtils.mkdir_p(File.join(home, 'first'))
95
- File.write(File.join(d, 'judges/first/the-first.rb'), 'x = $fb.size; $fb.insert.foo = x')
96
- FileUtils.mkdir_p(File.join(home, 'second'))
97
- File.write(File.join(d, 'judges/second/the-second.rb'), '$fb.insert.bar = 55')
98
- File.write(
99
- File.join(d, 'judges/second/something.yml'),
93
+ save_it(File.join(d, 'first/first.rb'), 'x = $fb.size; $fb.insert.foo = x')
94
+ save_it(File.join(d, 'second/second.rb'), '$fb.insert.bar = 55')
95
+ save_it(
96
+ File.join(d, 'second/something.yml'),
100
97
  <<-YAML
101
98
  input:
102
99
  -
@@ -110,15 +107,15 @@ class TestTest < Minitest::Test
110
107
  - /fb/f[bar=55]
111
108
  YAML
112
109
  )
113
- Judges::Test.new(Loog::NULL).run({}, [home])
110
+ Judges::Test.new(Loog::NULL).run({}, [d])
114
111
  end
115
112
  end
116
113
 
117
114
  def test_one_judge_negative
118
115
  Dir.mktmpdir do |d|
119
- File.write(File.join(d, 'foo.rb'), '')
120
- File.write(
121
- File.join(d, 'x.yml'),
116
+ save_it(File.join(d, 'foo/foo.rb'), '')
117
+ save_it(
118
+ File.join(d, 'foo/x.yml'),
122
119
  <<-YAML
123
120
  input: []
124
121
  expected:
@@ -130,4 +127,20 @@ class TestTest < Minitest::Test
130
127
  end
131
128
  end
132
129
  end
130
+
131
+ def test_with_after_assertion
132
+ Dir.mktmpdir do |d|
133
+ save_it(File.join(d, 'foo/foo.rb'), '$fb.insert.foo = 42;')
134
+ save_it(File.join(d, 'foo/assert.rb'), 'raise unless $fb.size == 1')
135
+ save_it(
136
+ File.join(d, 'foo/x.yml'),
137
+ <<-YAML
138
+ input: []
139
+ after:
140
+ - assert.rb
141
+ YAML
142
+ )
143
+ Judges::Test.new(Loog::NULL).run({}, [d])
144
+ end
145
+ end
133
146
  end
@@ -34,7 +34,7 @@ require_relative '../../lib/judges/commands/update'
34
34
  class TestUpdate < Minitest::Test
35
35
  def test_build_factbase_from_scratch
36
36
  Dir.mktmpdir do |d|
37
- File.write(File.join(d, 'foo.rb'), 'return if $fb.size > 2; $fb.insert.zzz = $options.foo_bar + 1')
37
+ save_it(File.join(d, 'foo/foo.rb'), 'return if $fb.size > 2; $fb.insert.zzz = $options.foo_bar + 1')
38
38
  file = File.join(d, 'base.fb')
39
39
  Judges::Update.new(Loog::NULL).run({ 'option' => ['foo_bar=42'] }, [d, file])
40
40
  fb = Factbase.new
@@ -50,7 +50,7 @@ class TestUpdate < Minitest::Test
50
50
  fb = Factbase.new
51
51
  fb.insert.foo_bar = 42
52
52
  File.binwrite(file, fb.export)
53
- File.write(File.join(d, 'foo.rb'), '$fb.insert.tt = 4')
53
+ save_it(File.join(d, 'foo/foo.rb'), '$fb.insert.tt = 4')
54
54
  Judges::Update.new(Loog::NULL).run({ 'max-cycles' => 1 }, [d, file])
55
55
  fb = Factbase.new
56
56
  fb.import(File.binread(file))
@@ -62,7 +62,7 @@ class TestUpdate < Minitest::Test
62
62
 
63
63
  def test_update_with_error
64
64
  Dir.mktmpdir do |d|
65
- File.write(File.join(d, 'foo.rb'), 'this$is$a$broken$Ruby$script')
65
+ save_it(File.join(d, 'foo/foo.rb'), 'this$is$a$broken$Ruby$script')
66
66
  file = File.join(d, 'base.fb')
67
67
  Judges::Update.new(Loog::NULL).run({ 'quiet' => true, 'max-cycles' => 2 }, [d, file])
68
68
  end
@@ -71,7 +71,7 @@ class TestUpdate < Minitest::Test
71
71
  def test_update_with_error_no_quiet
72
72
  assert_raises do
73
73
  Dir.mktmpdir do |d|
74
- File.write(File.join(d, 'foo.rb'), 'a < 1')
74
+ save_it(File.join(d, 'foo/foo.rb'), 'a < 1')
75
75
  file = File.join(d, 'base.fb')
76
76
  Judges::Update.new(Loog::NULL).run({ 'quiet' => false }, [d, file])
77
77
  end
@@ -80,7 +80,7 @@ class TestUpdate < Minitest::Test
80
80
 
81
81
  def test_update_with_error_and_summary
82
82
  Dir.mktmpdir do |d|
83
- File.write(File.join(d, 'foo.rb'), 'this$is$a$broken$Ruby$script')
83
+ save_it(File.join(d, 'foo/foo.rb'), 'this$is$a$broken$Ruby$script')
84
84
  file = File.join(d, 'base.fb')
85
85
  2.times do
86
86
  Judges::Update.new(Loog::NULL).run(
data/test/test__helper.rb CHANGED
@@ -32,3 +32,11 @@ require 'minitest/autorun'
32
32
 
33
33
  require 'minitest/reporters'
34
34
  Minitest::Reporters.use! [Minitest::Reporters::SpecReporter.new]
35
+
36
+ class Minitest::Test
37
+ def save_it(file, content)
38
+ require 'fileutils'
39
+ FileUtils.mkdir_p(File.dirname(file))
40
+ File.binwrite(file, content)
41
+ end
42
+ end
data/test/test_baza.rb CHANGED
@@ -22,8 +22,10 @@
22
22
 
23
23
  require 'minitest/autorun'
24
24
  require 'webmock/minitest'
25
+ require 'webrick'
25
26
  require 'loog'
26
27
  require 'socket'
28
+ require 'stringio'
27
29
  require 'random-port'
28
30
  require_relative '../lib/judges'
29
31
  require_relative '../lib/judges/baza'
@@ -76,53 +78,75 @@ class TestBaza < Minitest::Test
76
78
  end
77
79
 
78
80
  def test_real_http
79
- req = with_http_server(200, 'yes') do |baza|
80
- baza.name_exists?('simple')
81
- end
82
- assert(req.include?("User-Agent: judges #{Judges::VERSION}\r\n"))
81
+ req =
82
+ with_http_server(200, 'yes') do |baza|
83
+ baza.name_exists?('simple')
84
+ end
85
+ assert_equal("judges #{Judges::VERSION}", req['user-agent'])
83
86
  end
84
87
 
85
88
  def test_push_with_meta
86
- req = with_http_server(200, 'yes') do |baza|
87
- baza.push('simple', 'hello, world!', ['boom!', 'хей!'])
88
- end
89
- assert(req.include?("X-Zerocracy-Meta: Ym9vbSE= 0YXQtdC5IQ==\r\n"))
89
+ req =
90
+ with_http_server(200, 'yes') do |baza|
91
+ baza.push('simple', 'hello, world!', ['boom!', 'хей!'])
92
+ end
93
+ assert_equal('Ym9vbSE= 0YXQtdC5IQ==', req['x-zerocracy-meta'])
90
94
  end
91
95
 
92
96
  def test_push_with_big_meta
93
- req = with_http_server(200, 'yes') do |baza|
94
- baza.push(
95
- 'simple',
96
- 'hello, world!',
97
- [
98
- 'pages_url:https://zerocracy.github.io/zerocracy.html',
99
- 'others:https://zerocracy.github.io/zerocracy.html',
100
- 'duration:59595'
101
- ]
102
- )
103
- end
104
- assert(req.join.include?('X-Zerocracy-Meta: '))
97
+ req =
98
+ with_http_server(200, 'yes') do |baza|
99
+ baza.push(
100
+ 'simple',
101
+ 'hello, world!',
102
+ [
103
+ 'pages_url:https://zerocracy.github.io/zerocracy.html',
104
+ 'others:https://zerocracy.github.io/zerocracy.html',
105
+ 'duration:59595'
106
+ ]
107
+ )
108
+ end
109
+ assert(req['x-zerocracy-meta'])
110
+ end
111
+
112
+ def test_push_compressed_content
113
+ req =
114
+ with_http_server(200, 'yes') do |baza|
115
+ baza.push('simple', 'hello, world!', %w[meta1 meta2 meta3])
116
+ end
117
+ assert_equal('application/zip', req.content_type)
118
+ assert_equal('gzip', req['content-encoding'])
119
+ body = Zlib::GzipReader.zcat(StringIO.new(req.body))
120
+ assert_equal('hello, world!', body)
121
+ end
122
+
123
+ def test_push_compression_disabled
124
+ req =
125
+ with_http_server(200, 'yes', compression: false) do |baza|
126
+ baza.push('simple', 'hello, world!', %w[meta1 meta2 meta3])
127
+ end
128
+ assert_equal('application/octet-stream', req.content_type)
129
+ assert_equal('hello, world!', req.body)
105
130
  end
106
131
 
107
132
  private
108
133
 
109
- def with_http_server(code, response)
134
+ def with_http_server(code, response, opts = {})
135
+ opts = { ssl: false, timeout: 1 }.merge(opts)
110
136
  WebMock.enable_net_connect!
111
- req = []
137
+ req = WEBrick::HTTPRequest.new(WEBrick::Config::HTTP)
112
138
  host = '127.0.0.1'
113
139
  RandomPort::Pool::SINGLETON.acquire do |port|
114
140
  server = TCPServer.new(host, port)
115
- t = Thread.new do
116
- socket = server.accept
117
- loop do
118
- line = socket.gets
119
- break if line == "\r\n"
120
- req << line
141
+ t =
142
+ Thread.new do
143
+ socket = server.accept
144
+ req.parse(socket)
145
+ req.body
146
+ socket.puts "HTTP/1.1 #{code} OK\r\nContent-Length: #{response.length}\r\n\r\n#{response}"
147
+ socket.close
121
148
  end
122
- socket.puts "HTTP/1.1 #{code} OK\r\nContent-Length: #{response.length}\r\n\r\n#{response}"
123
- socket.close
124
- end
125
- yield Judges::Baza.new(host, port, '0000', ssl: false, timeout: 1)
149
+ yield Judges::Baza.new(host, port, '0000', **opts)
126
150
  t.join
127
151
  end
128
152
  req
data/test/test_judge.rb CHANGED
@@ -34,7 +34,7 @@ require_relative '../lib/judges/judge'
34
34
  class TestJudge < Minitest::Test
35
35
  def test_basic_run
36
36
  Dir.mktmpdir do |d|
37
- File.write(File.join(d, 'foo.rb'), '$fb.insert')
37
+ save_it(File.join(d, "#{File.basename(d)}.rb"), '$fb.insert')
38
38
  judge = Judges::Judge.new(d, nil, Loog::NULL)
39
39
  fb = Factbase.new
40
40
  judge.run(fb, {}, {}, {})
@@ -44,7 +44,7 @@ class TestJudge < Minitest::Test
44
44
 
45
45
  def test_run_isolated
46
46
  Dir.mktmpdir do |d|
47
- File.write(File.join(d, 'bar.rb'), '$fb.insert')
47
+ save_it(File.join(d, "#{File.basename(d)}.rb"), '$fb.insert')
48
48
  judge = Judges::Judge.new(d, nil, Loog::NULL)
49
49
  fb1 = Factbase.new
50
50
  judge.run(fb1, {}, {}, {})
@@ -57,8 +57,8 @@ class TestJudge < Minitest::Test
57
57
 
58
58
  def test_passes_local_vars_between_tests
59
59
  Dir.mktmpdir do |d|
60
- File.write(
61
- File.join(d, 'x.rb'),
60
+ save_it(
61
+ File.join(d, "#{File.basename(d)}.rb"),
62
62
  '
63
63
  $local[:foo] = 42 if $local[:foo].nil?
64
64
  $local[:foo] = $local[:foo] + 1
@@ -77,8 +77,7 @@ class TestJudge < Minitest::Test
77
77
  Dir.mktmpdir do |d|
78
78
  j = 'this_is_it'
79
79
  dir = File.join(d, j)
80
- FileUtils.mkdir(dir)
81
- File.write(File.join(dir, 'foo.rb'), '$loog.info("judge=" + $judge)')
80
+ save_it(File.join(dir, "#{j}.rb"), '$loog.info("judge=" + $judge)')
82
81
  log = Loog::Buffer.new
83
82
  Judges::Judge.new(dir, nil, log).run(Factbase.new, {}, {}, {})
84
83
  assert(log.to_s.include?("judge=#{j}"))
@@ -89,8 +88,7 @@ class TestJudge < Minitest::Test
89
88
  assert_raises do
90
89
  Dir.mktmpdir do |d|
91
90
  dir = File.join(d, 'judges')
92
- FileUtils.mkdir_p(dir)
93
- File.write(File.join(dir, 'x.rb'), 'this$is$broken$syntax')
91
+ save_it(File.join(dir, "#{File.basename(d)}.rb"), 'this$is$broken$syntax')
94
92
  judge = Judges::Judge.new(dir, lib, Loog::NULL)
95
93
  judge.run(Factbase.new, {}, {}, {})
96
94
  end
@@ -101,8 +99,7 @@ class TestJudge < Minitest::Test
101
99
  assert_raises do
102
100
  Dir.mktmpdir do |d|
103
101
  dir = File.join(d, 'judges')
104
- FileUtils.mkdir_p(dir)
105
- File.write(File.join(dir, 'x.rb'), 'a < 1')
102
+ save_it(File.join(dir, "#{File.basename(d)}.rb"), 'a < 1')
106
103
  judge = Judges::Judge.new(dir, lib, Loog::NULL)
107
104
  judge.run(Factbase.new, {}, {}, {})
108
105
  end
data/test/test_judges.rb CHANGED
@@ -33,8 +33,9 @@ require_relative '../lib/judges/judges'
33
33
  class TestJudges < Minitest::Test
34
34
  def test_basic
35
35
  Dir.mktmpdir do |d|
36
- File.write(File.join(d, 'foo.rb'), 'hey')
37
- File.write(File.join(d, 'something.yml'), "---\nfoo: 42")
36
+ dir = File.join(d, 'foo')
37
+ save_it(File.join(dir, 'foo.rb'), 'hey')
38
+ save_it(File.join(dir, 'something.yml'), "---\nfoo: 42")
38
39
  found = 0
39
40
  Judges::Judges.new(d, nil, Loog::NULL).each do |p|
40
41
  assert_equal('foo.rb', p.script)
@@ -47,11 +48,32 @@ class TestJudges < Minitest::Test
47
48
 
48
49
  def test_get_one
49
50
  Dir.mktmpdir do |d|
50
- f = File.join(d, 'boo/foo.rb')
51
- FileUtils.mkdir_p(File.dirname(f))
52
- File.write(f, 'hey')
51
+ save_it(File.join(d, 'boo/boo.rb'), 'hey')
53
52
  j = Judges::Judges.new(d, nil, Loog::NULL).get('boo')
54
- assert_equal('foo.rb', j.script)
53
+ assert_equal('boo.rb', j.script)
54
+ end
55
+ end
56
+
57
+ def test_list_only_direct_subdirs
58
+ Dir.mktmpdir do |d|
59
+ save_it(File.join(d, 'first/first.rb'), '')
60
+ save_it(File.join(d, 'second/second.rb'), '')
61
+ save_it(File.join(d, 'second/just-file.rb'), '')
62
+ save_it(File.join(d, 'wrong.rb'), '')
63
+ save_it(File.join(d, 'another/wrong/wrong.rb'), '')
64
+ save_it(File.join(d, 'bad/hello.rb'), '')
65
+ list = Judges::Judges.new(d, nil, Loog::NULL).each.to_a
66
+ assert_equal(2, list.size)
67
+ end
68
+ end
69
+
70
+ def test_list_with_empty_dir
71
+ Dir.mktmpdir do |d|
72
+ save_it(File.join(d, 'wrong.rb'), '')
73
+ save_it(File.join(d, 'another/wrong/wrong.rb'), '')
74
+ save_it(File.join(d, 'bad/hello.rb'), '')
75
+ list = Judges::Judges.new(d, nil, Loog::NULL).each.to_a
76
+ assert(list.empty?)
55
77
  end
56
78
  end
57
79
  end
data/test/test_options.rb CHANGED
@@ -81,7 +81,7 @@ class TestOptions < Minitest::Test
81
81
  opts = Judges::Options.new('foo' => 44, 'bar' => 'long-string-maybe-secret')
82
82
  s = opts.to_s
83
83
  assert(s.include?('FOO → "44"'), s)
84
- assert(s.include?('"long********************"'))
84
+ assert(s.include?('"long****************cret"'), s)
85
85
  end
86
86
 
87
87
  def test_merge
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: judges
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.20.0
4
+ version: 0.22.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Yegor Bugayenko
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-07-22 00:00:00.000000000 Z
11
+ date: 2024-08-05 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: backtrace