diff options
author | Florian Frank <flori@ping.de> | 2009-08-24 16:20:32 +0200 |
---|---|---|
committer | Florian Frank <flori@ping.de> | 2009-08-24 16:20:32 +0200 |
commit | 10f03df1f6a54edaae86e87e1fd7d9a6a6a319f1 (patch) | |
tree | d7133d6f5ba8bc2f195ee6e070b34331bd4f5d04 /tools | |
download | json-10f03df1f6a54edaae86e87e1fd7d9a6a6a319f1.tar.gz |
initial commit
Diffstat (limited to 'tools')
-rwxr-xr-x | tools/fuzz.rb | 139 | ||||
-rwxr-xr-x | tools/server.rb | 61 |
2 files changed, 200 insertions, 0 deletions
diff --git a/tools/fuzz.rb b/tools/fuzz.rb new file mode 100755 index 0000000..4dacd95 --- /dev/null +++ b/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 diff --git a/tools/server.rb b/tools/server.rb new file mode 100755 index 0000000..084377f --- /dev/null +++ b/tools/server.rb @@ -0,0 +1,61 @@ +#!/usr/bin/env ruby + +require 'webrick' +include WEBrick +$:.unshift 'ext' +$:.unshift 'lib' +require 'json' + +class JSONServlet < HTTPServlet::AbstractServlet + @@count = 1 + + def do_GET(req, res) + obj = { + "TIME" => Time.now.strftime("%FT%T"), + "foo" => "Bär", + "bar" => "© ≠ €!", + 'a' => 2, + 'b' => 3.141, + 'COUNT' => @@count += 1, + 'c' => 'c', + 'd' => [ 1, "b", 3.14 ], + 'e' => { 'foo' => 'bar' }, + 'g' => "松本行弘", + 'h' => 1000.0, + 'i' => 0.001, + 'j' => "\xf0\xa0\x80\x81", + } + res.body = JSON.generate obj + res['Content-Type'] = "application/json" + end +end + +def create_server(err, dir, port) + dir = File.expand_path(dir) + err.puts "Surf to:", "http://#{Socket.gethostname}:#{port}" + + s = HTTPServer.new( + :Port => port, + :DocumentRoot => dir, + :Logger => WEBrick::Log.new(err), + :AccessLog => [ + [ err, WEBrick::AccessLog::COMMON_LOG_FORMAT ], + [ err, WEBrick::AccessLog::REFERER_LOG_FORMAT ], + [ err, WEBrick::AccessLog::AGENT_LOG_FORMAT ] + ] + ) + s.mount("/json", JSONServlet) + s +end + +default_dir = File.expand_path(File.join(File.dirname(__FILE__), '..', 'data')) +dir = ARGV.shift || default_dir +port = (ARGV.shift || 6666).to_i +s = create_server(STDERR, dir, 6666) +t = Thread.new { s.start } +trap(:INT) do + s.shutdown + t.join + exit +end +sleep |