judges 0.0.30 → 0.0.32

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2966161948e1ac2ed8c36b5f0e515183a9f8ea02d6ddabf396e7bd5db98ca787
4
- data.tar.gz: 227712553b74473211e835d5c1df9afbf03e00d8942639d137fea6d98d40a236
3
+ metadata.gz: cf26642d3989b5d0097e54b224bd8c8b431f5e488f04a6c6cc778f9a914e0ad6
4
+ data.tar.gz: 79974f0a047a19f499e8b9b69566ded6b9b78d3bf6f470bfc67e9aead9988dc9
5
5
  SHA512:
6
- metadata.gz: 120d2cec10fbca12aa6a9107ea348236dd44e999a8499dbef93952cb2fb313ea11bb67c658d0ebb6b6ee4f002383d2f8177d75d06bd8cb01d547032222e6b9aa
7
- data.tar.gz: 3cf907ef01704e0e11ffa8313226420536436571ab11ea9a25cf4d8c7cbc98e334cbb7e193ea5994910c36c20dcf29d0ae1d1fee040cefca9c7b5d2c0ec91a33
6
+ metadata.gz: f7af589ce71752db5991f3838ea4e6b0e13969f3caab954f21d991d692d75b592c5f3bbe5d42e26cdc9a5d2c68a8ed3fcbe87401c34b1d6daa92c380f6fc7688
7
+ data.tar.gz: 25a4cc8aa470fb2f457c9f00b1581d5e4c05ab07d8580da124fd59d92c768796b4548948cb03abfc88256936b3ad8a2ae2fa4dd0edd66a7f1ae69a8530176fcf
@@ -0,0 +1,57 @@
1
+ # Copyright (c) 2024 Yegor Bugayenko
2
+ #
3
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ # of this software and associated documentation files (the 'Software'), to deal
5
+ # in the Software without restriction, including without limitation the rights
6
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ # copies of the Software, and to permit persons to whom the Software is
8
+ # furnished to do so, subject to the following conditions:
9
+ #
10
+ # The above copyright notice and this permission notice shall be included in all
11
+ # copies or substantial portions of the Software.
12
+ #
13
+ # THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19
+ # SOFTWARE.
20
+ ---
21
+ name: license
22
+ 'on':
23
+ push:
24
+ branches:
25
+ - master
26
+ pull_request:
27
+ branches:
28
+ - master
29
+ jobs:
30
+ license:
31
+ runs-on: ubuntu-22.04
32
+ steps:
33
+ - uses: actions/checkout@v4
34
+ - shell: bash
35
+ run: |
36
+ header="Copyright (c) $(date +%Y) Yegor Bugayenko"
37
+ failed="false"
38
+ while IFS= read -r file; do
39
+ if ! grep -q "${header}" "${file}"; then
40
+ failed="true"
41
+ echo "⚠️ Copyright header is not found in: ${file}"
42
+ else
43
+ echo "File looks good: ${file}"
44
+ fi
45
+ done < <(find . -type f \( \
46
+ -name "Dockerfile" -o \
47
+ -name "LICENSE.txt" -o \
48
+ -name "Makefile" -o \
49
+ -name "Rakefile" -o \
50
+ -name "*.sh" -o \
51
+ -name "*.rb" -o \
52
+ -name "*.fe" -o \
53
+ -name "*.yml" \
54
+ \) -print)
55
+ if [ "${failed}" = "true" ]; then
56
+ exit 1
57
+ fi
data/Gemfile CHANGED
@@ -24,10 +24,10 @@ source 'https://rubygems.org'
24
24
  gemspec
25
25
 
26
26
  gem 'cucumber', '9.2.0', require: false
27
- gem 'minitest', '5.23.0', require: false
27
+ gem 'minitest', '5.23.1', require: false
28
28
  gem 'rake', '13.2.1', require: false
29
29
  gem 'rspec-rails', '6.1.2', require: false
30
- gem 'rubocop', '1.63.5', require: false
30
+ gem 'rubocop', '1.64.0', require: false
31
31
  gem 'rubocop-performance', '1.21.0', require: false
32
32
  gem 'rubocop-rspec', '2.29.2', require: false
33
33
  gem 'simplecov', '0.22.0', require: false
data/Gemfile.lock CHANGED
@@ -3,7 +3,7 @@ PATH
3
3
  specs:
4
4
  judges (0.0.0)
5
5
  backtrace (~> 0.3)
6
- factbase (~> 0.0.29)
6
+ factbase (~> 0.0.30)
7
7
  gli (~> 2.21)
8
8
  loog (~> 0.2)
9
9
  nokogiri (~> 1.10)
@@ -74,7 +74,7 @@ GEM
74
74
  docile (1.4.0)
75
75
  drb (2.2.1)
76
76
  erubi (1.12.0)
77
- factbase (0.0.29)
77
+ factbase (0.0.30)
78
78
  json (~> 2.7)
79
79
  loog (~> 0.2)
80
80
  nokogiri (~> 1.10)
@@ -95,7 +95,7 @@ GEM
95
95
  nokogiri (>= 1.12.0)
96
96
  loog (0.5.1)
97
97
  mini_mime (1.1.5)
98
- minitest (5.23.0)
98
+ minitest (5.23.1)
99
99
  multi_test (1.1.0)
100
100
  mutex_m (0.2.0)
101
101
  nokogiri (1.16.5-arm64-darwin)
@@ -112,7 +112,7 @@ GEM
112
112
  racc
113
113
  psych (5.1.2)
114
114
  stringio
115
- racc (1.7.3)
115
+ racc (1.8.0)
116
116
  rack (3.0.11)
117
117
  rack-session (2.0.0)
118
118
  rack (>= 3.0.0)
@@ -138,7 +138,7 @@ GEM
138
138
  zeitwerk (~> 2.6)
139
139
  rainbow (3.1.1)
140
140
  rake (13.2.1)
141
- rdoc (6.6.3.1)
141
+ rdoc (6.7.0)
142
142
  psych (>= 4.0.0)
143
143
  regexp_parser (2.9.2)
144
144
  reline (0.5.7)
@@ -162,7 +162,7 @@ GEM
162
162
  rspec-mocks (~> 3.13)
163
163
  rspec-support (~> 3.13)
164
164
  rspec-support (3.13.1)
165
- rubocop (1.63.5)
165
+ rubocop (1.64.0)
166
166
  json (~> 2.3)
167
167
  language_server-protocol (>= 3.17.0)
168
168
  parallel (~> 1.10)
@@ -221,10 +221,10 @@ PLATFORMS
221
221
  DEPENDENCIES
222
222
  cucumber (= 9.2.0)
223
223
  judges!
224
- minitest (= 5.23.0)
224
+ minitest (= 5.23.1)
225
225
  rake (= 13.2.1)
226
226
  rspec-rails (= 6.1.2)
227
- rubocop (= 1.63.5)
227
+ rubocop (= 1.64.0)
228
228
  rubocop-performance (= 1.21.0)
229
229
  rubocop-rspec (= 2.29.2)
230
230
  simplecov (= 0.22.0)
data/bin/judges CHANGED
@@ -32,7 +32,7 @@ Encoding.default_internal = Encoding::UTF_8
32
32
  class App
33
33
  extend GLI::App
34
34
 
35
- ver = '0.0.30'
35
+ ver = '0.0.32'
36
36
 
37
37
  loog = Loog::REGULAR
38
38
 
@@ -13,5 +13,5 @@ Feature: Import
13
13
  z: 3.14
14
14
  """
15
15
  Then I run bin/judges with "--verbose import simple.yaml simple.fb"
16
- Then Stdout contains "Import finished"
16
+ Then Stdout contains "Import of 2 facts finished"
17
17
  And Exit code is zero
@@ -49,7 +49,7 @@ When(%r{^I run bin/judges with "([^"]*)"$}) do |arg|
49
49
  home = File.join(File.dirname(__FILE__), '../..')
50
50
  cmd = "ruby -I#{home}/lib #{home}/bin/judges #{arg}"
51
51
  cmd = "GLI_DEBUG=true #{cmd}" unless Gem.win_platform?
52
- @stdout = `#{cmd}`
52
+ @stdout = `#{cmd} 2>&1`
53
53
  @exitstatus = $CHILD_STATUS.exitstatus
54
54
  end
55
55
 
@@ -8,7 +8,7 @@ Feature: Test
8
8
  And Exit code is zero
9
9
 
10
10
  Scenario: Simple test of just one pack
11
- Given I run bin/judges with "test --pack reward_for_good_bug ./fixtures"
11
+ Given I run bin/judges with "test --pack guess ./fixtures"
12
12
  Then Stdout contains "judge(s) tested successfully"
13
13
  And Exit code is zero
14
14
 
@@ -30,3 +30,23 @@ Feature: Update
30
30
  Then Stdout contains "1 judge(s) processed"
31
31
  Then Stdout contains "Update finished: 1 cycles"
32
32
  And Exit code is zero
33
+
34
+ Scenario: The update fails when a bug in a judge
35
+ Given I make a temp directory
36
+ Then I have a "mypacks/mypack/broken.rb" file with content:
37
+ """
38
+ a < 1
39
+ """
40
+ Then I run bin/judges with "update mypacks simple.fb"
41
+ Then Stdout contains "Failed to update correctly"
42
+ And Exit code is not zero
43
+
44
+ Scenario: The update fails when a broken Ruby syntax in a judge
45
+ Given I make a temp directory
46
+ Then I have a "mypacks/mypack/broken.rb" file with content:
47
+ """
48
+ invalid$ruby$syntax$here
49
+ """
50
+ Then I run bin/judges with "update mypacks simple.fb"
51
+ Then Stdout contains "Failed to update correctly"
52
+ And Exit code is not zero
@@ -0,0 +1,28 @@
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
+ $loog.info("Trying to guess a number (judge=#{$judge})...")
24
+ $fb.txn do |fbt|
25
+ n = fbt.insert
26
+ n.number = Random.rand(100)
27
+ n.time = Time.now
28
+ end
@@ -18,17 +18,8 @@
18
18
  # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19
19
  # SOFTWARE.
20
20
  ---
21
- input:
22
- -
23
- kind: bug was accepted
24
- reporter: yegor256
25
- time: 2024-01-01T03:15:45
26
- seen:
27
- - one
28
- - two
29
- - three
21
+ input: []
30
22
  expected:
31
- - /fb[count(f)=2]
32
- - /fb/f[kind='nominate for good bug']
33
- - /fb/f[payee='yegor256']
34
- - /fb/f[amount='15']
23
+ - /fb[count(f)=1]
24
+ - /fb/f/number
25
+ - /fb/f/time
@@ -0,0 +1,24 @@
1
+ # Copyright (c) 2024 Yegor Bugayenko
2
+ #
3
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ # of this software and associated documentation files (the 'Software'), to deal
5
+ # in the Software without restriction, including without limitation the rights
6
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ # copies of the Software, and to permit persons to whom the Software is
8
+ # furnished to do so, subject to the following conditions:
9
+ #
10
+ # The above copyright notice and this permission notice shall be included in all
11
+ # copies or substantial portions of the Software.
12
+ #
13
+ # THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19
+ # SOFTWARE.
20
+ ---
21
+ skip: true
22
+ input: []
23
+ expected:
24
+ - /should-never-reach-this-point
@@ -20,12 +20,8 @@
20
20
  ---
21
21
  input:
22
22
  -
23
- kind: bug was accepted
24
- reporter: yegor256
23
+ number: 42
25
24
  time: 2024-01-01T03:15:45
26
- seen:
27
- - one
28
- - reward_for_good_bug
29
- - two
30
25
  expected:
31
- - /fb[count(f)=1]
26
+ - /fb[count(f)=2]
27
+ - /fb/f/guess
@@ -20,13 +20,7 @@
20
20
  # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
21
  # SOFTWARE.
22
22
 
23
- $loog.info("Trying to reward a good reported bug (judge=#{$judge})...")
24
-
25
- once($fb).query("(eq kind 'bug was accepted')").each do |f|
26
- $loog.info('Good candidate found!')
23
+ once($fb).query("(and (exists number) (lt time #{Time.now.utc.iso8601}))").each do |f|
27
24
  n = $fb.insert
28
- n.kind = 'nominate for good bug'
29
- n.payee = f.reporter
30
- n.amount = 15
31
- n.message = 'thanks for reporting a bug; you get +15 points for this'
25
+ n.guess = f.number
32
26
  end
data/judges.gemspec CHANGED
@@ -26,7 +26,7 @@ Gem::Specification.new do |s|
26
26
  s.required_rubygems_version = Gem::Requirement.new('>= 0') if s.respond_to? :required_rubygems_version=
27
27
  s.required_ruby_version = '>=3.2'
28
28
  s.name = 'judges'
29
- s.version = '0.0.30'
29
+ s.version = '0.0.32'
30
30
  s.license = 'MIT'
31
31
  s.summary = 'Command-Line Tool for a Factbase'
32
32
  s.description = '
@@ -42,7 +42,7 @@ Gem::Specification.new do |s|
42
42
  s.rdoc_options = ['--charset=UTF-8']
43
43
  s.extra_rdoc_files = ['README.md', 'LICENSE.txt']
44
44
  s.add_runtime_dependency 'backtrace', '~> 0.3'
45
- s.add_runtime_dependency 'factbase', '~>0.0.29'
45
+ s.add_runtime_dependency 'factbase', '~>0.0.30'
46
46
  s.add_runtime_dependency 'gli', '~>2.21'
47
47
  s.add_runtime_dependency 'loog', '~>0.2'
48
48
  s.add_runtime_dependency 'nokogiri', '~> 1.10'
@@ -20,13 +20,10 @@
20
20
  # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
21
  # SOFTWARE.
22
22
 
23
- require 'backtrace'
24
23
  require 'factbase/looged'
25
24
  require_relative '../../judges'
26
- require_relative '../../judges/to_rel'
27
- require_relative '../../judges/packs'
28
- require_relative '../../judges/options'
29
25
  require_relative '../../judges/impex'
26
+ require_relative '../../judges/elapsed'
30
27
 
31
28
  # Eval.
32
29
  # Author:: Yegor Bugayenko (yegor256@gmail.com)
@@ -40,12 +37,15 @@ class Judges::Eval
40
37
  def run(_opts, args)
41
38
  raise 'Exactly two arguments required' unless args.size == 2
42
39
  impex = Judges::Impex.new(@loog, args[0])
43
- $fb = impex.import(strict: false)
44
- $fb = Factbase::Looged.new($fb, @loog)
45
- expr = args[1]
46
- # rubocop:disable Security/Eval
47
- eval(expr)
48
- # rubocop:enable Security/Eval
49
- impex.export($fb)
40
+ elapsed(@loog) do
41
+ $fb = impex.import(strict: false)
42
+ $fb = Factbase::Looged.new($fb, @loog)
43
+ expr = args[1]
44
+ # rubocop:disable Security/Eval
45
+ eval(expr)
46
+ # rubocop:enable Security/Eval
47
+ impex.export($fb)
48
+ throw :'Evaluated successfully'
49
+ end
50
50
  end
51
51
  end
@@ -25,6 +25,7 @@ require 'factbase/looged'
25
25
  require_relative '../../judges'
26
26
  require_relative '../../judges/impex'
27
27
  require_relative '../../judges/to_rel'
28
+ require_relative '../../judges/elapsed'
28
29
 
29
30
  # Import.
30
31
  # Author:: Yegor Bugayenko (yegor256@gmail.com)
@@ -38,19 +39,20 @@ class Judges::Import
38
39
  def run(_opts, args)
39
40
  raise 'Exactly two arguments required' unless args.size == 2
40
41
  raise "File not found #{args[0].to_rel}" unless File.exist?(args[0])
41
- start = Time.now
42
- yaml = YAML.load_file(args[0], permitted_classes: [Time])
43
- @loog.info("YAML loaded from #{args[0].to_rel} (#{yaml.size} facts)")
44
- impex = Judges::Impex.new(@loog, args[1])
45
- fb = impex.import(strict: false)
46
- fb = Factbase::Looged.new(fb, @loog)
47
- yaml.each do |i|
48
- f = fb.insert
49
- i.each do |p, v|
50
- f.send("#{p}=", v)
42
+ elapsed(@loog) do
43
+ yaml = YAML.load_file(args[0], permitted_classes: [Time])
44
+ @loog.info("YAML loaded from #{args[0].to_rel} (#{yaml.size} facts)")
45
+ impex = Judges::Impex.new(@loog, args[1])
46
+ fb = impex.import(strict: false)
47
+ fb = Factbase::Looged.new(fb, @loog)
48
+ yaml.each do |i|
49
+ f = fb.insert
50
+ i.each do |p, v|
51
+ f.send("#{p}=", v)
52
+ end
51
53
  end
54
+ impex.export(fb)
55
+ throw :"Import of #{yaml.size} facts finished"
52
56
  end
53
- impex.export(fb)
54
- @loog.info("Import finished in #{format('%.02f', Time.now - start)}s")
55
57
  end
56
58
  end
@@ -22,6 +22,7 @@
22
22
 
23
23
  require_relative '../../judges'
24
24
  require_relative '../../judges/impex'
25
+ require_relative '../../judges/elapsed'
25
26
 
26
27
  # Join.
27
28
  # Author:: Yegor Bugayenko (yegor256@gmail.com)
@@ -36,9 +37,11 @@ class Judges::Join
36
37
  raise 'Exactly two arguments required' unless args.size == 2
37
38
  master = Judges::Impex.new(@loog, args[0])
38
39
  slave = Judges::Impex.new(@loog, args[1])
39
- fb = master.import
40
- slave.import_to(fb)
41
- master.export(fb)
42
- @loog.info('Two factbases joined')
40
+ elapsed(@loog) do
41
+ fb = master.import
42
+ slave.import_to(fb)
43
+ master.export(fb)
44
+ throw :'Two factbases joined'
45
+ end
43
46
  end
44
47
  end
@@ -24,6 +24,7 @@ require 'fileutils'
24
24
  require 'factbase'
25
25
  require_relative '../../judges'
26
26
  require_relative '../../judges/impex'
27
+ require_relative '../../judges/elapsed'
27
28
 
28
29
  # Update.
29
30
  # Author:: Yegor Bugayenko (yegor256@gmail.com)
@@ -53,20 +54,21 @@ class Judges::Print
53
54
  end
54
55
  @loog.debug("The factbase #{f.to_rel} is younger than the target #{o.to_rel}, need to print")
55
56
  end
56
- start = Time.now
57
- output =
58
- case opts[:format].downcase
59
- when 'yaml'
60
- require 'factbase/to_yaml'
61
- Factbase::ToYAML.new(fb).yaml
62
- when 'json'
63
- require 'factbase/to_json'
64
- Factbase::ToJSON.new(fb).json
65
- when 'xml'
66
- require 'factbase/to_xml'
67
- Factbase::ToXML.new(fb).xml
68
- end
69
- File.binwrite(o, output)
70
- @loog.info("Factbase printed to #{o.to_rel} (#{File.size(o)} bytes) in #{format('%.02f', Time.now - start)}s")
57
+ elapsed(@loog) do
58
+ output =
59
+ case opts[:format].downcase
60
+ when 'yaml'
61
+ require 'factbase/to_yaml'
62
+ Factbase::ToYAML.new(fb).yaml
63
+ when 'json'
64
+ require 'factbase/to_json'
65
+ Factbase::ToJSON.new(fb).json
66
+ when 'xml'
67
+ require 'factbase/to_xml'
68
+ Factbase::ToXML.new(fb).xml
69
+ end
70
+ File.binwrite(o, output)
71
+ throw :"Factbase printed to #{o.to_rel} (#{File.size(o)} bytes)"
72
+ end
71
73
  end
72
74
  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/elapsed'
32
33
 
33
34
  # Test.
34
35
  # Author:: Yegor Bugayenko (yegor256@gmail.com)
@@ -45,34 +46,32 @@ class Judges::Test
45
46
  @loog.info("Testing judges in #{dir.to_rel}...")
46
47
  errors = []
47
48
  done = 0
48
- global = {}
49
- start = Time.now
50
- Judges::Packs.new(dir, opts['lib'], @loog).each_with_index do |p, i|
51
- local = {}
52
- next unless include?(opts, p.name)
53
- @loog.info("\n👉 Testing #{p.script} (##{i}) in #{p.dir.to_rel}...")
54
- p.tests.each do |f|
55
- yaml = YAML.load_file(f, permitted_classes: [Time])
56
- @loog.info("Testing #{f.to_rel}:")
57
- begin
58
- test_one(p, global, local, yaml)
59
- rescue StandardError => e
60
- @loog.warn(Backtrace.new(e))
61
- errors << f
49
+ elapsed(@loog) do
50
+ Judges::Packs.new(dir, opts['lib'], @loog).each_with_index do |p, i|
51
+ next unless include?(opts, p.name)
52
+ @loog.info("\n👉 Testing #{p.script} (##{i}) in #{p.dir.to_rel}...")
53
+ p.tests.each do |f|
54
+ yaml = YAML.load_file(f, permitted_classes: [Time])
55
+ if yaml['skip']
56
+ @loog.info("Skippped #{f.to_rel}")
57
+ next
58
+ end
59
+ @loog.info("Testing #{f.to_rel}:")
60
+ begin
61
+ test_one(p, yaml)
62
+ rescue StandardError => e
63
+ @loog.warn(Backtrace.new(e))
64
+ errors << f
65
+ end
62
66
  end
67
+ done += 1
63
68
  end
64
- done += 1
65
- end
66
- lapse = "in #{format('%.02f', Time.now - start)}s"
67
- if done.zero?
68
- raise 'No judges tested :(' unless opts['quiet']
69
- @loog.warn("\n👍 No judges tested #{lapse}")
70
- elsif errors.empty?
71
- @loog.info("\n👍 All #{done} judge(s) tested successfully #{lapse}")
72
- else
73
- @loog.info("\n❌ #{done} judge(s) tested, #{errors.size} of them failed #{lapse}")
74
- raise "#{errors.size} tests failed" unless opts['quiet']
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"
75
72
  end
73
+ raise "#{errors.size} tests failed" unless opts['quiet'] || errors.empty?
74
+ raise 'No judges tested :(' unless opts['quiet'] || !done.zero?
76
75
  end
77
76
 
78
77
  private
@@ -83,7 +82,7 @@ class Judges::Test
83
82
  packs.include?(name)
84
83
  end
85
84
 
86
- def test_one(pack, global, local, yaml)
85
+ def test_one(pack, yaml)
87
86
  fb = Factbase.new
88
87
  yaml['input'].each do |i|
89
88
  f = fb.insert
@@ -97,7 +96,7 @@ class Judges::Test
97
96
  end
98
97
  end
99
98
  end
100
- pack.run(Factbase::Looged.new(fb, @loog), global, local, Judges::Options.new(yaml['options']))
99
+ pack.run(Factbase::Looged.new(fb, @loog), {}, {}, Judges::Options.new(yaml['options']))
101
100
  xml = Nokogiri::XML.parse(Factbase::ToXML.new(fb).xml)
102
101
  yaml['expected'].each do |xp|
103
102
  raise "#{pack.script} doesn't match '#{xp}':\n#{xml}" if xml.xpath(xp).empty?
@@ -23,6 +23,7 @@
23
23
  require 'time'
24
24
  require_relative '../../judges'
25
25
  require_relative '../../judges/impex'
26
+ require_relative '../../judges/elapsed'
26
27
 
27
28
  # Trim.
28
29
  # Author:: Yegor Bugayenko (yegor256@gmail.com)
@@ -46,14 +47,11 @@ class Judges::Trim
46
47
  else
47
48
  raise 'Specify either --days or --query' unless opts['days'].nil?
48
49
  end
49
- start = Time.now
50
- deleted = fb.query(query).delete!
51
- lapse = "in #{format('%.02f', Time.now - start)}s"
52
- if deleted.zero?
53
- @loog.info("No facts deleted #{lapse}")
54
- else
55
- @loog.info("🗑 #{deleted} fact(s) deleted #{lapse}")
50
+ elapsed(@loog) do
51
+ deleted = fb.query(query).delete!
52
+ throw :'No facts deleted' if deleted.zero?
56
53
  impex.export(fb)
54
+ throw :"🗑 #{deleted} fact(s) deleted"
57
55
  end
58
56
  end
59
57
  end
@@ -27,6 +27,7 @@ require_relative '../../judges/to_rel'
27
27
  require_relative '../../judges/packs'
28
28
  require_relative '../../judges/options'
29
29
  require_relative '../../judges/impex'
30
+ require_relative '../../judges/elapsed'
30
31
 
31
32
  # Update.
32
33
  # Author:: Yegor Bugayenko (yegor256@gmail.com)
@@ -48,23 +49,27 @@ class Judges::Update
48
49
  @loog.debug("The following options provided:\n\t#{options.to_s.gsub("\n", "\n\t")}")
49
50
  packs = Judges::Packs.new(dir, opts['lib'], @loog)
50
51
  c = 0
51
- start = Time.now
52
- loop do
53
- c += 1
54
- diff = cycle(opts, packs, fb, options)
55
- impex.export(fb)
56
- break if diff.zero?
57
- if !opts['max-cycles'].nil? && c >= opts['max-cycles']
58
- @loog.info('Too many cycles already, as set by --max-cycles, breaking')
59
- break
52
+ elapsed(@loog) do
53
+ loop do
54
+ c += 1
55
+ if c > 1
56
+ @loog.info("\n\nStarting cycle ##{c}#{opts['max-cycles'] ? " (out of #{opts['max-cycles']})" : ''}...")
57
+ end
58
+ diff = cycle(opts, packs, fb, options)
59
+ impex.export(fb)
60
+ break if diff.zero?
61
+ if !opts['max-cycles'].nil? && c >= opts['max-cycles']
62
+ @loog.info('Too many cycles already, as set by --max-cycles, breaking')
63
+ break
64
+ end
65
+ @loog.info(
66
+ "By #{diff} facts the factbase " \
67
+ "#{diff.positive? ? 'increased' : 'decreased'} " \
68
+ "its size at the cycle ##{c}"
69
+ )
60
70
  end
61
- @loog.info(
62
- "By #{diff} facts the factbase " \
63
- "#{diff.positive? ? 'increased' : 'decreased'} " \
64
- "its size at the cycle ##{c}"
65
- )
71
+ throw :"Update finished: #{c} cycles"
66
72
  end
67
- @loog.info("Update finished: #{c} cycles in #{format('%.02f', Time.now - start)}s")
68
73
  end
69
74
 
70
75
  private
@@ -73,25 +78,27 @@ class Judges::Update
73
78
  errors = []
74
79
  diff = 0
75
80
  global = {}
76
- done = packs.each_with_index do |p, i|
77
- local = {}
78
- @loog.info("👉 Running #{p.name} (##{i}) at #{p.dir.to_rel}...")
79
- before = fb.size
80
- begin
81
- p.run(fb, global, local, options)
82
- rescue StandardError => e
83
- @loog.warn(Backtrace.new(e))
84
- errors << p.script
81
+ elapsed(@loog) do
82
+ done = packs.each_with_index do |p, i|
83
+ local = {}
84
+ @loog.info("👉 Running #{p.name} (##{i}) at #{p.dir.to_rel}...")
85
+ before = fb.size
86
+ begin
87
+ p.run(fb, global, local, options)
88
+ rescue StandardError, SyntaxError => e
89
+ @loog.warn(Backtrace.new(e))
90
+ errors << p.script
91
+ end
92
+ after = fb.size
93
+ @loog.info("👍 The judge #{p.dir.to_rel} added #{after - before} facts") if after > before
94
+ diff += after - before
85
95
  end
86
- after = fb.size
87
- @loog.info("👍 Pack #{p.dir.to_rel} added #{after - before} facts") if after > before
88
- diff += after - before
96
+ throw :"👍 #{done} judge(s) processed" if errors.empty?
97
+ throw :" #{done} judge(s) processed with #{errors.size} errors"
89
98
  end
90
- if errors.empty?
91
- @loog.info("👍 #{done} judge(s) processed")
92
- else
93
- @loog.info("❌ #{done} judge(s) processed with #{errors.size} errors")
99
+ unless errors.empty?
94
100
  raise "Failed to update correctly (#{errors.size} errors)" unless opts['quiet']
101
+ @loog.info('Not failing because of the --quiet flag provided')
95
102
  end
96
103
  diff
97
104
  end
@@ -0,0 +1,32 @@
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
+ def elapsed(loog)
24
+ start = Time.now
25
+ begin
26
+ yield
27
+ rescue UncaughtThrowError => e
28
+ tag = e.tag
29
+ throw e unless tag.is_a?(Symbol)
30
+ loog.info("#{tag} in #{format('%.02f', Time.now - start)}s")
31
+ end
32
+ end
data/lib/judges/pack.rb CHANGED
@@ -22,6 +22,7 @@
22
22
 
23
23
  require_relative '../judges'
24
24
  require_relative '../judges/to_rel'
25
+ require_relative '../judges/elapsed'
25
26
  require_relative '../judges/fb/once'
26
27
  require_relative '../judges/fb/if_absent'
27
28
 
@@ -55,8 +56,9 @@ class Judges::Pack
55
56
  end
56
57
  s = File.join(@dir, script)
57
58
  raise "Can't load '#{s}'" unless File.exist?(s)
58
- begin
59
+ elapsed(@loog) do
59
60
  load(s, true)
61
+ throw :"#{name} finished"
60
62
  ensure
61
63
  $fb = $judge = $options = $loog = nil
62
64
  end
@@ -62,9 +62,19 @@ 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
+ File.write(File.join(d, '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 }, [d, file])
68
68
  end
69
69
  end
70
+
71
+ def test_update_with_error_no_quiet
72
+ assert_raises do
73
+ Dir.mktmpdir do |d|
74
+ File.write(File.join(d, 'foo.rb'), 'a < 1')
75
+ file = File.join(d, 'base.fb')
76
+ Judges::Update.new(Loog::NULL).run({ 'quiet' => false }, [d, file])
77
+ end
78
+ end
79
+ end
70
80
  end
data/test/test_pack.rb CHANGED
@@ -107,4 +107,28 @@ class TestPack < Minitest::Test
107
107
  assert_equal(42, fb.query('()').each.to_a.first.bar)
108
108
  end
109
109
  end
110
+
111
+ def test_with_broken_ruby_syntax
112
+ assert_raises do
113
+ Dir.mktmpdir do |d|
114
+ dir = File.join(d, 'packs')
115
+ FileUtils.mkdir_p(dir)
116
+ File.write(File.join(dir, 'x.rb'), 'this$is$broken$syntax')
117
+ pack = Judges::Pack.new(dir, lib, Loog::NULL)
118
+ pack.run(Factbase.new, {}, {}, {})
119
+ end
120
+ end
121
+ end
122
+
123
+ def test_with_runtime_ruby_error
124
+ assert_raises do
125
+ Dir.mktmpdir do |d|
126
+ dir = File.join(d, 'packs')
127
+ FileUtils.mkdir_p(dir)
128
+ File.write(File.join(dir, 'x.rb'), 'a < 1')
129
+ pack = Judges::Pack.new(dir, lib, Loog::NULL)
130
+ pack.run(Factbase.new, {}, {}, {})
131
+ end
132
+ end
133
+ end
110
134
  end
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.0.30
4
+ version: 0.0.32
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-05-21 00:00:00.000000000 Z
11
+ date: 2024-05-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: backtrace
@@ -30,14 +30,14 @@ dependencies:
30
30
  requirements:
31
31
  - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: 0.0.29
33
+ version: 0.0.30
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
- version: 0.0.29
40
+ version: 0.0.30
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: gli
43
43
  requirement: !ruby/object:Gem::Requirement
@@ -96,6 +96,7 @@ files:
96
96
  - ".gitattributes"
97
97
  - ".github/workflows/actionlint.yml"
98
98
  - ".github/workflows/codecov.yml"
99
+ - ".github/workflows/license.yml"
99
100
  - ".github/workflows/markdown-lint.yml"
100
101
  - ".github/workflows/pdd.yml"
101
102
  - ".github/workflows/rake.yml"
@@ -123,10 +124,11 @@ files:
123
124
  - features/test.feature
124
125
  - features/trim.feature
125
126
  - features/update.feature
126
- - fixtures/reward_for_good_bug/README.md
127
- - fixtures/reward_for_good_bug/no-reward.yml
128
- - fixtures/reward_for_good_bug/reward_it.rb
129
- - fixtures/reward_for_good_bug/simple-reward.yml
127
+ - fixtures/guess/guess.rb
128
+ - fixtures/guess/guess_made.yml
129
+ - fixtures/guess/skipped.yml
130
+ - fixtures/try/tried.yml
131
+ - fixtures/try/try.rb
130
132
  - judges.gemspec
131
133
  - lib/judges.rb
132
134
  - lib/judges/commands/eval.rb
@@ -137,6 +139,7 @@ files:
137
139
  - lib/judges/commands/test.rb
138
140
  - lib/judges/commands/trim.rb
139
141
  - lib/judges/commands/update.rb
142
+ - lib/judges/elapsed.rb
140
143
  - lib/judges/fb/if_absent.rb
141
144
  - lib/judges/fb/once.rb
142
145
  - lib/judges/impex.rb
@@ -1,8 +0,0 @@
1
- # Why bugs reports are rewarded?
2
-
3
- Every bug reported and accepted deserves a reward, which
4
- are given to the reporter of the bug. A bug is considered as
5
- "accepted" only if it has the `bug`, `enhancement`, or `question` label
6
- attached to it. Such a reward encourages programmers to report
7
- more bugs, thus revealing problems that will be fixed before they
8
- are shipped to a customer.