rgot 1.1.0 → 1.2.0

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: 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