class Rgot::F
def fuzz_foo(f)
f.add(5, "hello") f.fuzz do |t, i, s| ... end
Constants
- SUPPORTED_TYPES
Attributes
@dynamic name
Public Class Methods
Source
# File lib/rgot/f.rb, line 102 def initialize(fuzz_target:, opts:) super() @opts = opts @fuzz_target = fuzz_target @fuzz_block = nil @module = fuzz_target.module @name = fuzz_target.name @corpus = [] end
Calls superclass method
Rgot::Common::new
Public Instance Methods
Source
# File lib/rgot/f.rb, line 160 def add(*args) args.each do |arg| unless SUPPORTED_TYPES.key?(arg.class) raise "unsupported type to Add #{arg.class}" end end entry = CorpusEntry.new( values: args.dup, is_seed: true, path: "seed##{@corpus.length}" ) @corpus.push(entry) end
Source
# File lib/rgot/f.rb, line 174 def fuzz(&block) unless block raise LocalJumpError, "must set block" end unless 2 <= block.arity raise "fuzz target must receive at least two arguments" end t = T.new(@fuzz_target.module, @fuzz_target.name) @corpus.each do |entry| unless entry.values.length == (block.arity - 1) raise "wrong number of values in corpus entry: #{entry.values.length}, want #{block.arity - 1}" end block.call(t, *entry.values.dup) fail! if t.failed? end @fuzz_block = block nil end
Source
# File lib/rgot/f.rb, line 197 def fuzz? return false unless @opts.fuzz return false unless Regexp.new(@opts.fuzz.to_s).match?(@fuzz_target.name) true end
Source
# File lib/rgot/f.rb, line 203 def report puts @output if Rgot.verbose? && !@output.empty? duration = Rgot.now - @start template = "--- \e[%sm%s\e[m: %s (%.2fs)\n" if failed? printf template, [41, 1].join(';'), "FAIL", @name, duration elsif Rgot.verbose? if skipped? printf template, [44, 1].join(';'), "SKIP", @name, duration else printf template, [42, 1].join(';'), "PASS", @name, duration end end end
Source
# File lib/rgot/f.rb, line 113 def run catch(:skip) { call } finish! rescue => e fail! raise e end
TODO: DRY with T
Source
# File lib/rgot/f.rb, line 126 def run_fuzzing return unless fuzz? raise("must call after #fuzz") unless @fuzz_block coordinator = Coordinator.new( warmup_input_count: @corpus.length ) coordinator.start_logger t = T.new(@fuzz_target.module, @fuzz_target.name) begin Timeout.timeout(@opts.fuzztime.to_f) do loop do @corpus.each do |entry| values = entry.mutate_values @fuzz_block.call(t, *values) if 0 < coordinator.diff_coverage coordinator.interesting_count += 1 end coordinator.count += 1 fail! if t.failed? end end end rescue Timeout::Error, Interrupt coordinator.log_stats end report end
Source
# File lib/rgot/f.rb, line 121 def run_testing run report if !fuzz? || failed? end
Private Instance Methods
Source
# File lib/rgot/f.rb, line 220 def call test_method = @module.instance_method(@name).bind(@module) if test_method.arity == 0 path, line = test_method.source_location warn "#{path}:#{line} `#{test_method.name}' is not running. It's a testing method name, But not have argument" else test_method.call(self) end end