judges 0.0.32 → 0.0.34

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: cf26642d3989b5d0097e54b224bd8c8b431f5e488f04a6c6cc778f9a914e0ad6
4
- data.tar.gz: 79974f0a047a19f499e8b9b69566ded6b9b78d3bf6f470bfc67e9aead9988dc9
3
+ metadata.gz: 7d6543b9b405aa797aa98883b8294c15e61215db07121c7c0e4616081f9457de
4
+ data.tar.gz: 86c543a69bf748262f0f1072f151f8e1f3de9f8d015192699d811d809452328c
5
5
  SHA512:
6
- metadata.gz: f7af589ce71752db5991f3838ea4e6b0e13969f3caab954f21d991d692d75b592c5f3bbe5d42e26cdc9a5d2c68a8ed3fcbe87401c34b1d6daa92c380f6fc7688
7
- data.tar.gz: 25a4cc8aa470fb2f457c9f00b1581d5e4c05ab07d8580da124fd59d92c768796b4548948cb03abfc88256936b3ad8a2ae2fa4dd0edd66a7f1ae69a8530176fcf
6
+ metadata.gz: a487dade2d9e24c24298aab0132fdf653688a2133904c2cad712692762759e9fe8c3e9076e99d09b67a73b8a2580445600ffb2766db0a6d4ef01052de2163392
7
+ data.tar.gz: 76111d01a21353718aadde66a0af44d5b341bce928c670704298118ffa8cd0d147e5d50ce21329d7a1adb69e0241243a6a2c3af273d0f6e126bb49fff9618c82
data/.rultor.yml CHANGED
@@ -33,8 +33,8 @@ release:
33
33
  rm -rf *.gem
34
34
  sed -i "s/0\.0\.0/${tag}/g" judges.gemspec
35
35
  git add judges.gemspec
36
- sed -i "s/0\.0\.0/${tag}/g" bin/judges
37
- git add bin/judges
36
+ sed -i "s/0\.0\.0/${tag}/g" lib/judges.rb
37
+ git add lib/judges.rb
38
38
  git commit -m "version set to ${tag}"
39
39
  gem build judges.gemspec
40
40
  chmod 0600 ../rubygems.yml
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.30)
6
+ factbase (~> 0.0.38)
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.30)
77
+ factbase (0.0.38)
78
78
  json (~> 2.7)
79
79
  loog (~> 0.2)
80
80
  nokogiri (~> 1.10)
@@ -210,7 +210,7 @@ GEM
210
210
  webrick (1.8.1)
211
211
  yaml (0.3.0)
212
212
  yard (0.9.36)
213
- zeitwerk (2.6.14)
213
+ zeitwerk (2.6.15)
214
214
 
215
215
  PLATFORMS
216
216
  arm64-darwin-22
data/bin/judges CHANGED
@@ -32,13 +32,12 @@ Encoding.default_internal = Encoding::UTF_8
32
32
  class App
33
33
  extend GLI::App
34
34
 
35
- ver = '0.0.32'
36
-
37
35
  loog = Loog::REGULAR
38
36
 
39
37
  program_desc('Automated executor of judges for a factbase')
40
38
 
41
- version(ver)
39
+ require_relative '../lib/judges'
40
+ version(Judges::VERSION)
42
41
 
43
42
  synopsis_format(:full)
44
43
 
@@ -51,7 +50,7 @@ class App
51
50
  if global[:verbose]
52
51
  loog = Loog::VERBOSE
53
52
  end
54
- loog.debug("judges #{ver}")
53
+ loog.debug("judges #{Judges::VERSION}")
55
54
  true
56
55
  end
57
56
 
@@ -98,9 +97,7 @@ class App
98
97
  desc 'Remove the facts that are too old'
99
98
  command :trim do |c|
100
99
  c.desc 'Only the facts that match the expression are deleted'
101
- c.flag([:query])
102
- c.desc 'Remove facts that are older than X days'
103
- c.flag([:days], type: Integer)
100
+ c.flag([:query], default_value: '(never)')
104
101
  c.action do |global, options, args|
105
102
  require_relative '../lib/judges/commands/trim'
106
103
  Judges::Trim.new(loog).run(options, args)
@@ -114,7 +111,7 @@ class App
114
111
  c.desc 'Generate output name of the file automatically'
115
112
  c.switch([:auto], default_value: false)
116
113
  c.desc 'Only the facts that match the expression are printed'
117
- c.flag([:query], default_value: '()')
114
+ c.flag([:query], default_value: '(always)')
118
115
  c.desc 'Print even if target file already exists and is older than the factbase'
119
116
  c.switch([:force], default_value: false)
120
117
  c.action do |global, options, args|
@@ -133,6 +130,12 @@ class App
133
130
 
134
131
  desc 'Run automated tests for all judges'
135
132
  command :test do |c|
133
+ c.desc 'Options to pass to every judge (may be overwritten by YAML)'
134
+ c.flag([:o, :option], multiple: true, arg_name: '<key=value>')
135
+ c.desc 'Categories of tests to disable'
136
+ c.flag([:disable], multiple: true)
137
+ c.desc 'Categories of tests to enable'
138
+ c.flag([:enable], multiple: true)
136
139
  c.desc 'Name of the test pack to run'
137
140
  c.flag([:pack], multiple: true)
138
141
  c.desc 'The location of a Ruby library (directory with .rb files to include)'
@@ -4,12 +4,12 @@ Feature: Test
4
4
  Scenario: Simple test of a few judges
5
5
  Given I run bin/judges with "test ./fixtures"
6
6
  Then Stdout contains "👉 Testing"
7
- Then Stdout contains "judge(s) tested successfully"
7
+ Then Stdout contains "All 2 judge(s) and 2 tests passed"
8
8
  And Exit code is zero
9
9
 
10
10
  Scenario: Simple test of just one pack
11
11
  Given I run bin/judges with "test --pack guess ./fixtures"
12
- Then Stdout contains "judge(s) tested successfully"
12
+ Then Stdout contains "All 1 judge(s) and 1 tests passed"
13
13
  And Exit code is zero
14
14
 
15
15
  Scenario: Simple test of no packs
@@ -28,5 +28,36 @@ Feature: Test
28
28
  $foo = 42
29
29
  """
30
30
  Then I run bin/judges with "test --lib mylib mypacks"
31
- Then Stdout contains "All 1 judge(s) tested successfully"
31
+ Then Stdout contains "All 1 judge(s) and 0 tests passed"
32
32
  And Exit code is zero
33
+
34
+ Scenario: Enable only one category
35
+ Given I make a temp directory
36
+ Then I have a "mypacks/good/good.rb" file with content:
37
+ """
38
+ n = $fb.insert
39
+ """
40
+ Then I have a "mypacks/good/good.yml" file with content:
41
+ """
42
+ ---
43
+ category: good
44
+ input: []
45
+ """
46
+ Then I have a "mypacks/bad/bad.rb" file with content:
47
+ """
48
+ broken$ruby$syntax
49
+ """
50
+ Then I have a "mypacks/bad/bad.yml" file with content:
51
+ """
52
+ ---
53
+ category: bad
54
+ """
55
+ Then I run bin/judges with "test --enable good mypacks"
56
+ Then Stdout contains "All 2 judge(s) and 1 tests passed"
57
+ And Exit code is zero
58
+ Then I run bin/judges with "test --disable bad mypacks"
59
+ Then Stdout contains "All 2 judge(s) and 1 tests passed"
60
+ And Exit code is zero
61
+ Then I run bin/judges with "test --enable bad mypacks"
62
+ Then Stdout contains "Testing mypacks/bad/bad.yml"
63
+ And Exit code is not zero
@@ -1,17 +1,16 @@
1
1
  Feature: Trim
2
2
  I want to trim a factbase
3
3
 
4
- Scenario: Simple trimming of a factbase
4
+ Scenario: Simple trimming of a factbase, with a query
5
5
  Given I make a temp directory
6
- Then I run bin/judges with "--verbose eval simple.fb '$fb.insert.time = Time.now - 100 * 60 * 60 * 24'"
7
- Then I run bin/judges with "--verbose update . simple.fb"
8
- Given I run bin/judges with "trim --days 5 simple.fb"
6
+ Then I run bin/judges with "--verbose eval simple.fb '$fb.insert.foo = 42'"
7
+ Given I run bin/judges with "trim --query '(eq foo 42)' simple.fb"
9
8
  Then Stdout contains "1 fact(s) deleted"
10
9
  And Exit code is zero
11
10
 
12
- Scenario: Simple trimming of a factbase, with a query
11
+ Scenario: Delete nothing by default
13
12
  Given I make a temp directory
14
13
  Then I run bin/judges with "--verbose eval simple.fb '$fb.insert.foo = 42'"
15
- Given I run bin/judges with "trim --query '(eq foo 42)' simple.fb"
16
- Then Stdout contains "1 fact(s) deleted"
14
+ Given I run bin/judges with "trim simple.fb"
15
+ Then Stdout contains "No facts deleted"
17
16
  And Exit code is zero
data/fixtures/try/try.rb CHANGED
@@ -20,7 +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
- once($fb).query("(and (exists number) (lt time #{Time.now.utc.iso8601}))").each do |f|
23
+ each_once($fb, "(and (exists number) (lt time #{Time.now.utc.iso8601}))") do |f|
24
24
  n = $fb.insert
25
25
  n.guess = f.number
26
26
  end
data/judges.gemspec CHANGED
@@ -26,14 +26,15 @@ 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.32'
29
+ s.version = '0.0.34'
30
30
  s.license = 'MIT'
31
31
  s.summary = 'Command-Line Tool for a Factbase'
32
- s.description = '
33
- Runs a collection of \"judges\" against a \"factbase,\" modifying it and updating.
34
- Also, helps printing a factbase, merge with another one, inspect, and so on.
35
- Also, helps run automated tests for a set of judges.
36
- '
32
+ s.description =
33
+ 'A command-line tool that runs a collection of \"judges\" ' \
34
+ 'against a \"factbase,\" modifying ' \
35
+ 'it and updating. Also, helps printing a factbase, merge with ' \
36
+ 'another one, inspect, and so on. Also, helps run automated tests ' \
37
+ 'for a set of judges.'
37
38
  s.authors = ['Yegor Bugayenko']
38
39
  s.email = 'yegor256@gmail.com'
39
40
  s.homepage = 'http://github.com/yegor256/judges'
@@ -42,7 +43,7 @@ Gem::Specification.new do |s|
42
43
  s.rdoc_options = ['--charset=UTF-8']
43
44
  s.extra_rdoc_files = ['README.md', 'LICENSE.txt']
44
45
  s.add_runtime_dependency 'backtrace', '~> 0.3'
45
- s.add_runtime_dependency 'factbase', '~>0.0.30'
46
+ s.add_runtime_dependency 'factbase', '~>0.0.38'
46
47
  s.add_runtime_dependency 'gli', '~>2.21'
47
48
  s.add_runtime_dependency 'loog', '~>0.2'
48
49
  s.add_runtime_dependency 'nokogiri', '~> 1.10'
@@ -0,0 +1,51 @@
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_relative '../judges'
24
+
25
+ # Categories of tests.
26
+ # Author:: Yegor Bugayenko (yegor256@gmail.com)
27
+ # Copyright:: Copyright (c) 2024 Yegor Bugayenko
28
+ # License:: MIT
29
+ class Judges::Categories
30
+ # Ctor.
31
+ # @param [Array<String>] enable List of categories to enable
32
+ # @param [Array<String>] disable List of categories to enable
33
+ def initialize(enable, disable)
34
+ @enable = enable.is_a?(Array) ? enable : []
35
+ @disable = disable.is_a?(Array) ? disable : []
36
+ end
37
+
38
+ # This test is good to go, with this list of categories?
39
+ # @param [Array<String>] cats List of them
40
+ # @return [Boolean] True if yes
41
+ def ok?(cats)
42
+ cats = [] if cats.nil?
43
+ cats = [cats] unless cats.is_a?(Array)
44
+ cats.each do |c|
45
+ return false if @disable.any? { |d| d == c }
46
+ return true if @enable.any? { |d| d == c }
47
+ end
48
+ return true if @enable.empty?
49
+ false
50
+ end
51
+ 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
@@ -38,17 +38,8 @@ class Judges::Trim
38
38
  raise 'Exactly one argument required' unless args.size == 1
39
39
  impex = Judges::Impex.new(@loog, args[0])
40
40
  fb = impex.import
41
- query = opts['query']
42
- if query.nil?
43
- days = opts['days']
44
- day = Time.now - (days * 60 * 60 * 24)
45
- query = "(lt time #{day.utc.iso8601})"
46
- @loog.info("Deleting facts that are older than #{days} days")
47
- else
48
- raise 'Specify either --days or --query' unless opts['days'].nil?
49
- end
50
41
  elapsed(@loog) do
51
- deleted = fb.query(query).delete!
42
+ deleted = fb.query(opts['query']).delete!
52
43
  throw :'No facts deleted' if deleted.zero?
53
44
  impex.export(fb)
54
45
  throw :"🗑 #{deleted} fact(s) deleted"
@@ -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.34'
29
+ end
@@ -39,7 +39,7 @@ class TestTrim < Minitest::Test
39
39
  before.insert.time = Time.now + 1
40
40
  before.insert.time = Time.now - (100 * 24 * 60 * 60)
41
41
  File.binwrite(file, before.export)
42
- Judges::Trim.new(Loog::NULL).run({ 'days' => 10 }, [file])
42
+ Judges::Trim.new(Loog::NULL).run({ 'query' => "(lt time #{Time.now.utc.iso8601})" }, [file])
43
43
  after = Factbase.new
44
44
  after.import(File.binread(file))
45
45
  assert_equal(1, after.size)
@@ -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('()').each { |f| f.foo = 42 }
38
- assert(fb.query('()').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
@@ -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
data/test/test_pack.rb CHANGED
@@ -57,7 +57,7 @@ class TestPack < Minitest::Test
57
57
 
58
58
  def test_with_supplemenary_functions
59
59
  Dir.mktmpdir do |d|
60
- File.write(File.join(d, 'x.rb'), 'once($fb).insert')
60
+ File.write(File.join(d, 'x.rb'), 'each_once($fb, "(always)").to_a')
61
61
  pack = Judges::Pack.new(d, nil, Loog::NULL)
62
62
  pack.run(Factbase.new, {}, {}, {})
63
63
  end
@@ -97,14 +97,14 @@ class TestPack < Minitest::Test
97
97
  Dir.mktmpdir do |d|
98
98
  dir = File.join(d, 'packs')
99
99
  FileUtils.mkdir_p(dir)
100
- File.write(File.join(dir, 'x.rb'), 'once($fb).insert.bar = $foo')
100
+ File.write(File.join(dir, 'x.rb'), '$fb.insert.bar = $foo; each_once($fb, "(always)").to_a')
101
101
  lib = File.join(d, 'lib')
102
102
  FileUtils.mkdir_p(lib)
103
103
  File.write(File.join(lib, 'y.rb'), '$foo = 42')
104
104
  pack = Judges::Pack.new(dir, lib, Loog::NULL)
105
105
  fb = Factbase.new
106
106
  pack.run(fb, {}, {}, {})
107
- assert_equal(42, fb.query('()').each.to_a.first.bar)
107
+ assert_equal(42, fb.query('(always)').each.to_a.first.bar)
108
108
  end
109
109
  end
110
110
 
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.32
4
+ version: 0.0.34
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-24 00:00:00.000000000 Z
11
+ date: 2024-05-27 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.30
33
+ version: 0.0.38
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.30
40
+ version: 0.0.38
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: gli
43
43
  requirement: !ruby/object:Gem::Requirement
@@ -80,10 +80,9 @@ dependencies:
80
80
  - - "~>"
81
81
  - !ruby/object:Gem::Version
82
82
  version: '1.10'
83
- description: "\n Runs a collection of \\\"judges\\\" against a \\\"factbase,\\\"
84
- modifying it and updating.\n Also, helps printing a factbase, merge with another
85
- one, inspect, and so on.\n Also, helps run automated tests for a set of judges.\n
86
- \ "
83
+ description: A command-line tool that runs a collection of \"judges\" against a \"factbase,\"
84
+ modifying it and updating. Also, helps printing a factbase, merge with another one,
85
+ inspect, and so on. Also, helps run automated tests for a set of judges.
87
86
  email: yegor256@gmail.com
88
87
  executables:
89
88
  - judges
@@ -131,6 +130,7 @@ files:
131
130
  - fixtures/try/try.rb
132
131
  - judges.gemspec
133
132
  - lib/judges.rb
133
+ - lib/judges/categories.rb
134
134
  - lib/judges/commands/eval.rb
135
135
  - lib/judges/commands/import.rb
136
136
  - lib/judges/commands/inspect.rb
@@ -159,6 +159,7 @@ files:
159
159
  - test/fb/test_if_absent.rb
160
160
  - test/fb/test_once.rb
161
161
  - test/test__helper.rb
162
+ - test/test_categories.rb
162
163
  - test/test_impex.rb
163
164
  - test/test_judges.rb
164
165
  - test/test_options.rb