rgot 1.1.0 → 1.2.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: edabddcdf99d28070fbe94f391d49d7c034cb1b6d467629c76fc671f7d27956b
4
- data.tar.gz: 642606670788ef496178d91b9450f6c08bb97e8e4f9e14442e0868ddf0c2acbd
3
+ metadata.gz: 368b98f9969eee4d2608df53e668eaaed9f06320ecd5b26096ff05c0f81dc16e
4
+ data.tar.gz: b045a87ffcb3f18338ce0286e2f22b71921b5bab011e4049c203164b9ab7a077
5
5
  SHA512:
6
- metadata.gz: eb8824c1730be5395ffb22b3c075239b612a987db000367c804201394305b080834bb246c7c198da556e26090ae7a8424830b6253f7c10fd0183662ff6d490d0
7
- data.tar.gz: 4064bdb31930c1cc0a072ab6c7113f93f66ce8cd3bafd4208824c36a5c591685a0e82f7e09758ff32a4d342eefee64efeb92910e8b45c75a48175571f84e03f7
6
+ metadata.gz: 7a3d443886aa26702be0720d8bdf8abf38dd938e3707d595ac1bf21b1edd0f3cb52f64f29e4ca11996357d8671bfaaa4edc94500560510b67c393244202a2db3
7
+ data.tar.gz: 13d8fcdf048c4c82da186f96dc7bfef3eb78a35fb5df04a2f6f17badda63100587df8cd175dc0618d823d613526b9e60aeec8e18cc09075c8bf3c8c218d58841
@@ -14,13 +14,12 @@ jobs:
14
14
  strategy:
15
15
  matrix:
16
16
  ruby:
17
- - '2.6.10'
18
- - '2.7.6'
19
- - '3.0.4'
20
- - '3.1.2'
17
+ - '2.7.7'
18
+ - '3.0.5'
19
+ - '3.1.3'
21
20
 
22
21
  steps:
23
- - uses: actions/checkout@v2
22
+ - uses: actions/checkout@v3
24
23
  - name: Set up Ruby
25
24
  uses: ruby/setup-ruby@v1
26
25
  with:
data/.gitignore CHANGED
@@ -1,3 +1,2 @@
1
- Gemfile.lock
2
1
  pkg
3
2
  tmp
data/Gemfile.lock ADDED
@@ -0,0 +1,20 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ rgot (1.2.0)
5
+
6
+ GEM
7
+ remote: https://rubygems.org/
8
+ specs:
9
+ rake (13.0.6)
10
+
11
+ PLATFORMS
12
+ ruby
13
+
14
+ DEPENDENCIES
15
+ bundler
16
+ rake
17
+ rgot!
18
+
19
+ BUNDLED WITH
20
+ 2.3.26
data/README.md CHANGED
@@ -341,7 +341,7 @@ And this is default virtual main code.
341
341
  ```ruby
342
342
  module TestSomeCode
343
343
  def test_main(m)
344
- exit m.run
344
+ m.run
345
345
  end
346
346
  end
347
347
  ```
@@ -362,7 +362,7 @@ module TestSomeCode
362
362
  the_before_running_some_code
363
363
  code = m.run
364
364
  the_after_running_some_code
365
- exit code
365
+ code
366
366
  end
367
367
  end
368
368
  ```
data/Rakefile CHANGED
@@ -5,6 +5,8 @@ task :test do |t|
5
5
  targets = [
6
6
  "test/rgot_common_test.rb",
7
7
  "test/rgot_test.rb",
8
+ "test/rgot_benchmark_test.rb",
9
+ "test/rgot_example_test.rb",
8
10
  ]
9
11
  ruby "bin/rgot -v #{targets.join(' ')}"
10
12
  end
data/bin/rgot CHANGED
@@ -1,4 +1,4 @@
1
1
  #! /usr/bin/env ruby
2
2
  require 'rgot/cli'
3
3
 
4
- Rgot::Cli.new(ARGV).run
4
+ exit Rgot::Cli.new(ARGV).run
data/lib/rgot/b.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Rgot
2
4
  class B < Common
3
5
  Options = Struct.new(
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Rgot
2
4
  class BenchmarkResult
3
5
  def initialize(n:, t:)
data/lib/rgot/cli.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'optparse'
2
4
 
3
5
  require_relative '../rgot'
@@ -11,7 +13,7 @@ module Rgot
11
13
  def run
12
14
  opts = Rgot::M::Options.new
13
15
  parse_option(opts)
14
- process_start(opts)
16
+ main_process(opts)
15
17
  end
16
18
 
17
19
  private
@@ -74,81 +76,82 @@ module Rgot
74
76
  end
75
77
  end
76
78
 
77
- def process_start(opts)
79
+ def main_process(opts)
78
80
  code = 0
79
- testing_files.map do |testing_file|
80
- begin
81
- pid = fork do
82
- require testing_file
83
-
84
- modules = Object.constants.select { |c|
85
- next if c == :FileTest
86
- /.*Test\z/ =~ c
87
- }.map { |c|
88
- Object.const_get(c)
89
- }
90
-
91
- modules.each do |test_module|
92
- tests = []
93
- benchmarks = []
94
- examples = []
95
- main = nil
96
- methods = test_module.instance_methods
97
- methods.grep(/\Atest_/).each do |m|
98
- if m == :test_main && main.nil?
99
- main = Rgot::InternalTest.new(test_module, m)
100
- else
101
- tests << Rgot::InternalTest.new(test_module, m)
102
- end
103
- end
104
-
105
- methods.grep(/\Abenchmark_/).each do |m|
106
- benchmarks << Rgot::InternalBenchmark.new(test_module, m)
107
- end
108
-
109
- methods.grep(/\Aexample_?/).each do |m|
110
- examples << Rgot::InternalExample.new(test_module, m)
111
- end
112
-
113
- duration = Rgot.now
114
- at_exit do
115
- template = "%s\t%s\t%.3fs"
116
-
117
- case $!
118
- when SystemExit
119
- if $!.success?
120
- # exit 0
121
- puts sprintf(template, "ok ", test_module, Rgot.now - duration)
122
- else
123
- # exit 1
124
- puts "exit status #{$!.status}"
125
- puts sprintf(template, "FAIL", test_module, Rgot.now - duration)
126
- end
127
- when NilClass
128
- # not raise, not exit
129
- else
130
- # any exception
131
- puts sprintf(template, "FAIL", test_module, Rgot.now - duration)
132
- end
133
- end
134
- m = Rgot::M.new(tests: tests, benchmarks: benchmarks, examples: examples, opts: opts)
135
- if main
136
- main.module.extend main.module
137
- main.module.instance_method(main.name).bind(main.module).call(m)
138
- else
139
- exit m.run
140
- end
141
- end
142
- end
143
- ensure
144
- _, status = Process.waitpid2(pid)
145
- unless status.success?
146
- code = 1
147
- end
81
+
82
+ testing_files.each do |testing_file|
83
+ result = child_process(opts, testing_file)
84
+ unless result == 0
85
+ code = 1
148
86
  end
149
87
  end
150
88
 
151
- exit code
89
+ code
90
+ end
91
+
92
+ def child_process(opts, testing_file)
93
+ node = RubyVM::AbstractSyntaxTree.parse_file(testing_file).children[2]
94
+ test_module_name = find_toplevel_name(node)
95
+
96
+ load testing_file
97
+
98
+ test_module = Object.const_get(test_module_name)
99
+ tests = []
100
+ benchmarks = []
101
+ examples = []
102
+ main = nil
103
+ methods = test_module.public_instance_methods
104
+ methods.grep(/\Atest_/).each do |m|
105
+ if m == :test_main && main.nil?
106
+ main = Rgot::InternalTest.new(test_module, m)
107
+ else
108
+ tests << Rgot::InternalTest.new(test_module, m)
109
+ end
110
+ end
111
+
112
+ methods.grep(/\Abenchmark_/).each do |m|
113
+ benchmarks << Rgot::InternalBenchmark.new(test_module, m)
114
+ end
115
+
116
+ methods.grep(/\Aexample_?/).each do |m|
117
+ examples << Rgot::InternalExample.new(test_module, m)
118
+ end
119
+
120
+ m = Rgot::M.new(test_module: test_module, tests: tests, benchmarks: benchmarks, examples: examples, opts: opts)
121
+ if main
122
+ main.module.extend main.module
123
+ main.module.instance_method(:test_main).bind(main.module).call(m)
124
+ else
125
+ m.run
126
+ end
127
+ end
128
+
129
+ private
130
+
131
+ def find_toplevel_name(node)
132
+ case node.type
133
+ when :MODULE
134
+ find_toplevel_name(node.children.first)
135
+ when :CONST, :COLON3
136
+ node.children.first
137
+ when :COLON2
138
+ case node.children
139
+ in [nil, sym]
140
+ # module Foo
141
+ sym
142
+ in [namespace, sym]
143
+ # module Foo::Bar
144
+ find_toplevel_name(namespace)
145
+ end
146
+ when :BLOCK
147
+ module_node = node.children.find { |c| c.type == :MODULE }
148
+ unless module_node
149
+ raise "no module found"
150
+ end
151
+ find_toplevel_name(module_node)
152
+ else
153
+ raise node.type.to_s
154
+ end
152
155
  end
153
156
  end
154
157
  end
data/lib/rgot/common.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'thread'
2
4
  require 'pathname'
3
5
 
@@ -6,7 +8,7 @@ module Rgot
6
8
  attr_accessor :output
7
9
 
8
10
  def initialize
9
- @output = ""
11
+ @output = "".dup
10
12
  @failed = false
11
13
  @skipped = false
12
14
  @finished = false
@@ -100,7 +102,8 @@ module Rgot
100
102
  path = c.sub(/:.*/, '')
101
103
  line = c.match(/:(\d+?):/)[1]
102
104
  relative_path = Pathname.new(path).relative_path_from(Pathname.new(Dir.pwd)).to_s
103
- "\t#{relative_path}:#{line}: #{str}\n"
105
+ # Every line is indented at least 4 spaces.
106
+ " #{relative_path}:#{line}: #{str}\n"
104
107
  end
105
108
 
106
109
  def internal_log(msg)
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'ripper'
2
4
 
3
5
  module Rgot
@@ -8,7 +10,7 @@ module Rgot
8
10
  @examples = []
9
11
  @in_def = false
10
12
  @has_output = false
11
- @output = ""
13
+ @output = "".dup
12
14
  end
13
15
 
14
16
  def on_def(method, args, body)
data/lib/rgot/m.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'stringio'
2
4
  require 'etc'
3
5
  require 'timeout'
@@ -12,43 +14,74 @@ module Rgot
12
14
  :thread,
13
15
  ); end
14
16
 
15
- def initialize(tests:, benchmarks:, examples:, opts: Options.new)
16
- cpu = opts.cpu || (Etc.respond_to?(:nprocessors) ? Etc.nprocessors : '1').to_s
17
- @cpu_list = cpu.split(',').map { |i|
18
- j = i.to_i
19
- raise Rgot::OptionError, "invalid value #{i.inspect} for --cpu" unless 0 < j
20
- j
21
- }
22
- @thread_list = (opts.thread || "1").split(',').map { |i|
23
- j = i.to_i
24
- raise Rgot::OptionError, "invalid value #{i.inspect} for --thread" unless 0 < j
25
- j
26
- }
17
+ def initialize(tests:, benchmarks:, examples:, test_module: nil, opts: Options.new)
18
+ unless test_module
19
+ raise "Require `test_module` keyword" if Gem::Version.new("2.0") <= Gem::Version.new(Rgot::VERSION)
20
+ warn "`Rgot::M#initialize` will require the `test_module` keyword in the next major version."
21
+ end
22
+
27
23
  @tests = tests
28
24
  @benchmarks = benchmarks
29
25
  @examples = examples
26
+ @test_module = test_module
30
27
  @opts = opts
28
+ @cpu_list = nil
29
+ @thread_list = nil
31
30
  end
32
31
 
33
32
  def run
33
+ duration = Rgot.now
34
34
  test_ok = false
35
35
  example_ok = false
36
36
 
37
+ if @tests.empty? && @benchmarks.empty? && @examples.empty?
38
+ warn "rgot: warning: no tests to run"
39
+ end
40
+
41
+ begin
42
+ parse_option
43
+ rescue Rgot::OptionError
44
+ puts sprintf("%s\t%s\t%.3fs", "FAIL", @test_module, Rgot.now - duration)
45
+ raise
46
+ end
47
+
37
48
  Timeout.timeout(@opts.timeout.to_f) do
38
49
  test_ok = run_tests
39
50
  example_ok = run_examples
40
51
  end
52
+
41
53
  if !test_ok || !example_ok
42
54
  puts "FAIL"
43
- return 1
55
+ puts "exit status 1"
56
+ puts sprintf("%s\t%s\t%.3fs", "FAIL", @test_module, Rgot.now - duration)
57
+
58
+ 1
59
+ else
60
+ puts "PASS"
61
+ run_benchmarks
62
+ puts sprintf("%s\t%s\t%.3fs", "ok ", @test_module, Rgot.now - duration)
63
+
64
+ 0
44
65
  end
45
- puts "PASS"
46
- run_benchmarks
47
- 0
48
66
  end
49
67
 
50
68
  private
51
69
 
70
+ def parse_option
71
+ cpu = @opts.cpu || (Etc.respond_to?(:nprocessors) ? Etc.nprocessors : '1').to_s
72
+ @cpu_list = cpu.split(',').map { |i|
73
+ j = i.to_i
74
+ raise Rgot::OptionError, "invalid value #{i.inspect} for --cpu" unless 0 < j
75
+ j
76
+ }
77
+
78
+ @thread_list = (@opts.thread || "1").split(',').map { |i|
79
+ j = i.to_i
80
+ raise Rgot::OptionError, "invalid value #{i.inspect} for --thread" unless 0 < j
81
+ j
82
+ }
83
+ end
84
+
52
85
  def run_tests
53
86
  ok = true
54
87
  @tests.each do |test|
@@ -57,7 +90,6 @@ module Rgot
57
90
  puts "=== RUN #{test.name}"
58
91
  end
59
92
  t.run
60
- t.report
61
93
  if t.failed?
62
94
  ok = false
63
95
  end
data/lib/rgot/pb.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Rgot
2
4
  class PB
3
5
  attr_accessor :bn
data/lib/rgot/t.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Rgot
2
4
  class T < Common
3
5
  def initialize(test_module, name)
@@ -10,6 +12,7 @@ module Rgot
10
12
  def run
11
13
  catch(:skip) { call }
12
14
  finish!
15
+ report
13
16
  rescue => e
14
17
  fail!
15
18
  report
@@ -17,15 +20,16 @@ module Rgot
17
20
  end
18
21
 
19
22
  def report
23
+ puts @output if Rgot.verbose? && !@output.empty?
20
24
  duration = Rgot.now - @start
21
- template = "--- %s: %s (%.2fs)\n%s"
25
+ template = "--- \e[%sm%s\e[m: %s (%.2fs)\n"
22
26
  if failed?
23
- printf template, "FAIL", @name, duration, @output
27
+ printf template, [41, 1].join(';'), "FAIL", @name, duration
24
28
  elsif Rgot.verbose?
25
29
  if skipped?
26
- printf template, "SKIP", @name, duration, @output
30
+ printf template, [44, 1].join(';'), "SKIP", @name, duration
27
31
  else
28
- printf template, "PASS", @name, duration, @output
32
+ printf template, [42, 1].join(';'), "PASS", @name, duration
29
33
  end
30
34
  end
31
35
  end
data/lib/rgot/version.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Rgot
2
- VERSION = "1.1.0"
4
+ VERSION = "1.2.0"
3
5
  end
data/lib/rgot.rb CHANGED
@@ -1,12 +1,14 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Rgot
2
- require 'rgot/version'
3
- require 'rgot/common'
4
- require 'rgot/m'
5
- require 'rgot/t'
6
- require 'rgot/b'
7
- require 'rgot/pb'
8
- require 'rgot/benchmark_result'
9
- require 'rgot/example_parser'
4
+ autoload :VERSION, 'rgot/version'
5
+ autoload :Common, 'rgot/common'
6
+ autoload :M, 'rgot/m'
7
+ autoload :T, 'rgot/t'
8
+ autoload :B, 'rgot/b'
9
+ autoload :PB, 'rgot/pb'
10
+ autoload :BenchmarkResult, 'rgot/benchmark_result'
11
+ autoload :ExampleParser, 'rgot/example_parser'
10
12
 
11
13
  OptionError = Class.new(StandardError)
12
14
  InternalTest = Struct.new(:module, :name)
data/rgot.gemspec CHANGED
@@ -14,7 +14,7 @@ Gem::Specification.new do |spec|
14
14
  spec.homepage = "https://github.com/ksss/rgot"
15
15
  spec.license = "MIT"
16
16
 
17
- spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
17
+ spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|go)/}) }
18
18
  spec.bindir = "bin"
19
19
  spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
20
20
  spec.require_paths = ["lib"]
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rgot
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.0
4
+ version: 1.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - ksss
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-04-25 00:00:00.000000000 Z
11
+ date: 2022-12-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -49,6 +49,7 @@ files:
49
49
  - ".github/workflows/main.yml"
50
50
  - ".gitignore"
51
51
  - Gemfile
52
+ - Gemfile.lock
52
53
  - LICENSE.txt
53
54
  - README.md
54
55
  - Rakefile
@@ -83,7 +84,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
83
84
  - !ruby/object:Gem::Version
84
85
  version: '0'
85
86
  requirements: []
86
- rubygems_version: 3.4.0.dev
87
+ rubygems_version: 3.3.26
87
88
  signing_key:
88
89
  specification_version: 4
89
90
  summary: Ruby + Golang Testing = Rgot