lib/rgot/m.rb in rgot-1.2.0 vs lib/rgot/m.rb in rgot-1.3.0
- old
+ new
@@ -10,33 +10,51 @@
:bench,
:benchtime,
:timeout,
:cpu,
:thread,
+ :fuzz,
+ :fuzztime,
); end
- def initialize(tests:, benchmarks:, examples:, test_module: nil, opts: Options.new)
+ def initialize(tests:, benchmarks:, examples:, fuzz_targets: nil, test_module: nil, opts: Options.new)
+ unless fuzz_targets
+ raise "Require `fuzz_targets` keyword" if Gem::Version.new("2.0") <= Gem::Version.new(Rgot::VERSION)
+ warn "`Rgot::M#initialize` will require the `fuzz_targets` keyword in the next major version."
+ end
unless test_module
raise "Require `test_module` keyword" if Gem::Version.new("2.0") <= Gem::Version.new(Rgot::VERSION)
warn "`Rgot::M#initialize` will require the `test_module` keyword in the next major version."
end
@tests = tests
@benchmarks = benchmarks
@examples = examples
+ @fuzz_targets = fuzz_targets || []
@test_module = test_module
@opts = opts
- @cpu_list = nil
- @thread_list = nil
+
+ @cpu_list = []
+ @thread_list = []
+ @fs = @fuzz_targets.map do |fuzz_target|
+ F.new(
+ fuzz_target: fuzz_target,
+ opts: F::Options.new(
+ fuzz: opts.fuzz,
+ fuzztime: opts.fuzztime,
+ )
+ )
+ end
end
def run
duration = Rgot.now
test_ok = false
+ fuzz_targets_ok = false
example_ok = false
- if @tests.empty? && @benchmarks.empty? && @examples.empty?
+ if @tests.empty? && @benchmarks.empty? && @examples.empty? && @fuzz_targets.empty?
warn "rgot: warning: no tests to run"
end
begin
parse_option
@@ -45,26 +63,33 @@
raise
end
Timeout.timeout(@opts.timeout.to_f) do
test_ok = run_tests
+ fuzz_targets_ok = run_fuzz_tests
example_ok = run_examples
end
- if !test_ok || !example_ok
+ if !test_ok || !example_ok || !fuzz_targets_ok
puts "FAIL"
puts "exit status 1"
puts sprintf("%s\t%s\t%.3fs", "FAIL", @test_module, Rgot.now - duration)
+ return 1
+ end
- 1
- else
- puts "PASS"
- run_benchmarks
- puts sprintf("%s\t%s\t%.3fs", "ok ", @test_module, Rgot.now - duration)
-
- 0
+ if !run_fuzzing()
+ puts "FAIL"
+ puts "exit status 1"
+ puts sprintf("%s\t%s\t%.3fs", "FAIL", @test_module, Rgot.now - duration)
+ return 1
end
+
+ puts "PASS"
+ run_benchmarks
+ puts sprintf("%s\t%s\t%.3fs", "ok ", @test_module, Rgot.now - duration)
+
+ 0
end
private
def parse_option
@@ -88,13 +113,11 @@
t = T.new(test.module, test.name.to_sym)
if Rgot.verbose?
puts "=== RUN #{test.name}"
end
t.run
- if t.failed?
- ok = false
- end
+ ok = ok && !t.failed?
end
ok
end
def run_benchmarks
@@ -128,10 +151,54 @@
end
end
ok
end
+ def run_fuzz_tests
+ ok = true
+ @fs.each do |f|
+ if Rgot.verbose?
+ if f.fuzz?
+ puts "=== FUZZ #{f.name}"
+ else
+ puts "=== RUN #{f.name}"
+ end
+ end
+ f.run_testing
+ ok = ok && !f.failed?
+ end
+ ok
+ end
+
+ def run_fuzzing
+ if @fuzz_targets.empty? || @opts.fuzz.nil?
+ return true
+ end
+
+ fuzzing_fs = @fs.select(&:fuzz?)
+
+ if fuzzing_fs.empty?
+ puts "rgot: warning: no fuzz tests to fuzz"
+ return true
+ end
+
+ if fuzzing_fs.length > 1
+ names = fuzzing_fs.map(&:name)
+ puts "rgot: will not fuzz, --fuzz matches more than one fuzz test: #{names.inspect}"
+ return false
+ end
+
+ ok = true
+
+ fuzzing_fs.each do |f|
+ f.run_fuzzing
+ ok = ok && !f.failed?
+ end
+
+ ok
+ end
+
def run_examples
ok = true
@examples.each do |example|
if Rgot.verbose?
puts "=== RUN #{example.name}"
@@ -141,16 +208,16 @@
example.module.extend(example.module)
method = example.module.instance_method(example.name).bind(example.module)
out, _ = capture do
method.call
end
- file = method.source_location[0]
- r = ExampleParser.new(File.read(file))
- r.parse
- e = r.examples.find { |re| re.name == example.name }
+ file = method.source_location&.[](0) or raise("bug")
+ example_parser = ExampleParser.new(File.read(file))
+ example_parser.parse
+ e = example_parser.examples.find { |er| er.name == example.name } or raise("bug")
duration = Rgot.now - start
- if e && e.output.strip != out.strip
+ if e.output.strip != out.strip
printf("--- FAIL: %s (%.2fs)\n", e.name, duration)
ok = false
puts "got:"
puts out.strip
puts "want:"