judges 0.0.33 → 0.0.34

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 9cdbff8b28d803f0ce0c0c8e8a934ea9af5b6d65b6396f04f94572bc21bb515e
4
- data.tar.gz: 856504a44bf49b36ee64f3d304d14861965682df9257b6bbdb1284b71330d32d
3
+ metadata.gz: 7d6543b9b405aa797aa98883b8294c15e61215db07121c7c0e4616081f9457de
4
+ data.tar.gz: 86c543a69bf748262f0f1072f151f8e1f3de9f8d015192699d811d809452328c
5
5
  SHA512:
6
- metadata.gz: ddb58a1c8443ed4d61c3f55d155c34f0ba9e164d731167e7069169ac3ee7dbe9734fd7c4bd5a9e90a98787136b43d44966a3662fe3d13014298dcf1e770dd5d4
7
- data.tar.gz: 9c8fe18c4bebae1ceeb56611b71862d5cda792d292e6ba33f6f1e6b0700483ab385281d00e6ca1a5f3e134d644f065706e547cc3d9b56c4e634dd7c46afac0dd
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.32)
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.32)
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.33'
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
 
@@ -131,6 +130,12 @@ class App
131
130
 
132
131
  desc 'Run automated tests for all judges'
133
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)
134
139
  c.desc 'Name of the test pack to run'
135
140
  c.flag([:pack], multiple: true)
136
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
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.33'
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.32'
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
@@ -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
@@ -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
@@ -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,7 +97,7 @@ 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')
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.33
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-25 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.32
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.32
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