X-Git-Url: https://review.fuel-infra.org/gitweb?a=blobdiff_plain;f=lib%2Fmcollective%2Fvendor%2Fjson%2Ftools%2Ffuzz.rb;fp=lib%2Fmcollective%2Fvendor%2Fjson%2Ftools%2Ffuzz.rb;h=c0fae12c6cb34ca57e30b2487e1aebe520ef14a4;hb=b87d2f4e68281062df1913440ca5753ae63314a9;hp=0000000000000000000000000000000000000000;hpb=ab0ea530b8ac956091f17b104ab2311336cfc250;p=packages%2Fprecise%2Fmcollective.git diff --git a/lib/mcollective/vendor/json/tools/fuzz.rb b/lib/mcollective/vendor/json/tools/fuzz.rb new file mode 100755 index 0000000..c0fae12 --- /dev/null +++ b/lib/mcollective/vendor/json/tools/fuzz.rb @@ -0,0 +1,139 @@ +require 'json' + +require 'iconv' +ISO_8859_1_TO_UTF8 = Iconv.new('utf-8', 'iso-8859-15') +class ::String + def to_utf8 + ISO_8859_1_TO_UTF8.iconv self + end +end + +class Fuzzer + def initialize(n, freqs = {}) + sum = freqs.inject(0.0) { |s, x| s + x.last } + freqs.each_key { |x| freqs[x] /= sum } + s = 0.0 + freqs.each_key do |x| + freqs[x] = s .. (s + t = freqs[x]) + s += t + end + @freqs = freqs + @n = n + @alpha = (0..0xff).to_a + end + + def random_string + s = '' + 30.times { s << @alpha[rand(@alpha.size)] } + s.to_utf8 + end + + def pick + r = rand + found = @freqs.find { |k, f| f.include? rand } + found && found.first + end + + def make_pick + k = pick + case + when k == Hash, k == Array + k.new + when k == true, k == false, k == nil + k + when k == String + random_string + when k == Fixnum + rand(2 ** 30) - 2 ** 29 + when k == Bignum + rand(2 ** 70) - 2 ** 69 + end + end + + def fuzz(current = nil) + if @n > 0 + case current + when nil + @n -= 1 + current = fuzz [ Hash, Array ][rand(2)].new + when Array + while @n > 0 + @n -= 1 + current << case p = make_pick + when Array, Hash + fuzz(p) + else + p + end + end + when Hash + while @n > 0 + @n -= 1 + current[random_string] = case p = make_pick + when Array, Hash + fuzz(p) + else + p + end + end + end + end + current + end +end + +class MyState < JSON.state + WS = " \r\t\n" + + def initialize + super( + :indent => make_spaces, + :space => make_spaces, + :space_before => make_spaces, + :object_nl => make_spaces, + :array_nl => make_spaces, + :max_nesting => false + ) + end + + def make_spaces + s = '' + rand(1).times { s << WS[rand(WS.size)] } + s + end +end + +n = (ARGV.shift || 500).to_i +loop do + fuzzer = Fuzzer.new(n, + Hash => 25, + Array => 25, + String => 10, + Fixnum => 10, + Bignum => 10, + nil => 5, + true => 5, + false => 5 + ) + o1 = fuzzer.fuzz + json = JSON.generate o1, MyState.new + if $DEBUG + puts "-" * 80 + puts json, json.size + else + puts json.size + end + begin + o2 = JSON.parse(json, :max_nesting => false) + rescue JSON::ParserError => e + puts "Caught #{e.class}: #{e.message}\n#{e.backtrace * "\n"}" + puts "o1 = #{o1.inspect}", "json = #{json}", "json_str = #{json.inspect}" + puts "locals = #{local_variables.inspect}" + exit + end + if o1 != o2 + puts "mismatch", "o1 = #{o1.inspect}", "o2 = #{o2.inspect}", + "json = #{json}", "json_str = #{json.inspect}" + puts "locals = #{local_variables.inspect}" + end +end