json-fuzz-generator 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +22 -0
- data/.rspec +2 -0
- data/.travis.yml +6 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +100 -0
- data/Rakefile +7 -0
- data/json-fuzz-generator.gemspec +28 -0
- data/lib/json-fuzz-generator.rb +5 -0
- data/lib/json/fuzz/generator.rb +160 -0
- data/lib/json/fuzz/generator/keyword.rb +9 -0
- data/lib/json/fuzz/generator/keyword/additional_properties.rb +61 -0
- data/lib/json/fuzz/generator/keyword/all_of.rb +46 -0
- data/lib/json/fuzz/generator/keyword/any_of.rb +43 -0
- data/lib/json/fuzz/generator/keyword/dependencies.rb +49 -0
- data/lib/json/fuzz/generator/keyword/enum.rb +33 -0
- data/lib/json/fuzz/generator/keyword/format.rb +93 -0
- data/lib/json/fuzz/generator/keyword/items.rb +68 -0
- data/lib/json/fuzz/generator/keyword/max_items.rb +44 -0
- data/lib/json/fuzz/generator/keyword/max_length.rb +29 -0
- data/lib/json/fuzz/generator/keyword/max_properties.rb +44 -0
- data/lib/json/fuzz/generator/keyword/maximum.rb +46 -0
- data/lib/json/fuzz/generator/keyword/min_items.rb +44 -0
- data/lib/json/fuzz/generator/keyword/min_length.rb +29 -0
- data/lib/json/fuzz/generator/keyword/min_properties.rb +39 -0
- data/lib/json/fuzz/generator/keyword/minimum.rb +45 -0
- data/lib/json/fuzz/generator/keyword/multiple_of.rb +29 -0
- data/lib/json/fuzz/generator/keyword/not.rb +28 -0
- data/lib/json/fuzz/generator/keyword/one_of.rb +45 -0
- data/lib/json/fuzz/generator/keyword/pattern.rb +19 -0
- data/lib/json/fuzz/generator/keyword/properties.rb +40 -0
- data/lib/json/fuzz/generator/keyword/required.rb +41 -0
- data/lib/json/fuzz/generator/keyword/unique_items.rb +33 -0
- data/lib/json/fuzz/generator/primitive_type.rb +40 -0
- data/lib/json/fuzz/generator/primitive_type/array.rb +53 -0
- data/lib/json/fuzz/generator/primitive_type/boolean.rb +32 -0
- data/lib/json/fuzz/generator/primitive_type/integer.rb +56 -0
- data/lib/json/fuzz/generator/primitive_type/null.rb +33 -0
- data/lib/json/fuzz/generator/primitive_type/number.rb +52 -0
- data/lib/json/fuzz/generator/primitive_type/object.rb +57 -0
- data/lib/json/fuzz/generator/primitive_type/string.rb +53 -0
- data/lib/json/fuzz/generator/version.rb +7 -0
- data/spec/json-fuzz-generator_spec.rb +559 -0
- data/spec/schemas/basic_schema.json +17 -0
- data/spec/schemas/primitive_types.json +35 -0
- data/spec/spec_helper.rb +25 -0
- metadata +178 -0
@@ -0,0 +1,46 @@
|
|
1
|
+
module JSON
|
2
|
+
module Fuzz
|
3
|
+
module Generator
|
4
|
+
class Keyword
|
5
|
+
class AllOf
|
6
|
+
class << self
|
7
|
+
def invalid_params(attributes)
|
8
|
+
all_of = attributes["allOf"]
|
9
|
+
raise "No allOf keyword given: #{attributes}" unless all_of
|
10
|
+
|
11
|
+
generated_params = []
|
12
|
+
|
13
|
+
all_of.each do |schema|
|
14
|
+
JSON::Fuzz::Generator.generate(schema).each do |invalid_param|
|
15
|
+
if invalid_param.empty?
|
16
|
+
generated_params << invalid_param
|
17
|
+
else
|
18
|
+
template = valid_param(attributes)
|
19
|
+
template.merge!(invalid_param)
|
20
|
+
generated_params << template
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
generated_params
|
26
|
+
end
|
27
|
+
|
28
|
+
def valid_param(attributes)
|
29
|
+
attributes = Marshal.load(Marshal.dump(attributes))
|
30
|
+
all_of = attributes.delete("allOf")
|
31
|
+
raise "No allOf keyword given: #{attributes}" unless all_of
|
32
|
+
|
33
|
+
generated_param = {}
|
34
|
+
|
35
|
+
all_of.each do |schema|
|
36
|
+
generated_param.merge!(JSON::Fuzz::Generator.default_param(schema))
|
37
|
+
end
|
38
|
+
|
39
|
+
generated_param
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
module JSON
|
2
|
+
module Fuzz
|
3
|
+
module Generator
|
4
|
+
class Keyword
|
5
|
+
class AnyOf
|
6
|
+
class << self
|
7
|
+
def invalid_params(attributes)
|
8
|
+
any_of = attributes["anyOf"]
|
9
|
+
raise "No anyOf keyword given: #{attributes}" unless any_of
|
10
|
+
|
11
|
+
generated_params = []
|
12
|
+
|
13
|
+
any_of.each do |schema|
|
14
|
+
temp_params = JSON::Fuzz::Generator.generate(schema).reject do |param|
|
15
|
+
::JSON::Validator.validate(attributes, param)
|
16
|
+
end
|
17
|
+
temp_params.each {|e| generated_params << e}
|
18
|
+
end
|
19
|
+
|
20
|
+
raise "failed to generate invalid_params for schema: #{attributes}" if generated_params.empty?
|
21
|
+
generated_params.uniq
|
22
|
+
end
|
23
|
+
|
24
|
+
def valid_param(attributes)
|
25
|
+
attributes = Marshal.load(Marshal.dump(attributes))
|
26
|
+
any_of = attributes.delete("anyOf")
|
27
|
+
raise "No anyOf keyword given: #{attributes}" unless any_of
|
28
|
+
|
29
|
+
generated_params = []
|
30
|
+
|
31
|
+
any_of.each do |valid_schema|
|
32
|
+
generated_param = JSON::Fuzz::Generator.default_param(valid_schema)
|
33
|
+
generated_params << generated_param
|
34
|
+
end
|
35
|
+
|
36
|
+
generated_params.sample
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
module JSON
|
2
|
+
module Fuzz
|
3
|
+
module Generator
|
4
|
+
class Keyword
|
5
|
+
class Dependencies
|
6
|
+
class << self
|
7
|
+
def invalid_params(attributes)
|
8
|
+
attributes = Marshal.load(Marshal.dump(attributes))
|
9
|
+
dependencies = attributes.delete("dependencies")
|
10
|
+
raise "No dependencies keyword given: #{attributes}" unless dependencies
|
11
|
+
|
12
|
+
generated_params = []
|
13
|
+
template = JSON::Fuzz::Generator.default_param(attributes)
|
14
|
+
|
15
|
+
dependencies.each do |key, dependency|
|
16
|
+
dependency.each do |required_key|
|
17
|
+
invalid_param = Marshal.load(Marshal.dump(template))
|
18
|
+
invalid_param.delete(required_key)
|
19
|
+
generated_params << invalid_param
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
generated_params
|
24
|
+
end
|
25
|
+
|
26
|
+
def valid_param(attributes)
|
27
|
+
attributes = Marshal.load(Marshal.dump(attributes))
|
28
|
+
dependencies = attributes.delete("dependencies")
|
29
|
+
raise "No dependencies keyword given: #{attributes}" unless dependencies
|
30
|
+
|
31
|
+
generated_params = []
|
32
|
+
|
33
|
+
dependencies.each do |key, dependency|
|
34
|
+
template = JSON::Fuzz::Generator.default_param(attributes)
|
35
|
+
template[key] = "hoge" if template.keys.size == 0
|
36
|
+
dependency.each do |required_key|
|
37
|
+
template.merge!(required_key => template[template.keys.sample]) unless template.key?(required_key)
|
38
|
+
generated_params << template
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
generated_params.sample
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module JSON
|
2
|
+
module Fuzz
|
3
|
+
module Generator
|
4
|
+
class Keyword
|
5
|
+
class Enum
|
6
|
+
class << self
|
7
|
+
def invalid_params(attributes)
|
8
|
+
attributes = Marshal.load(Marshal.dump(attributes))
|
9
|
+
enum = attributes.delete("enum")
|
10
|
+
raise "No enum keyword given: #{attributes}" unless enum
|
11
|
+
|
12
|
+
generated_params = []
|
13
|
+
JSON::Fuzz::Generator::PrimitiveType.type_to_class_map.each do |type, klass|
|
14
|
+
klass.invalid_params(attributes).each do |invalid_param|
|
15
|
+
generated_params << invalid_param unless enum.include?(invalid_param)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
generated_params.empty? ? [nil] : generated_params
|
20
|
+
end
|
21
|
+
|
22
|
+
def valid_param(attributes)
|
23
|
+
enum = attributes["enum"]
|
24
|
+
raise "No enum keyword given: #{attributes}" unless enum
|
25
|
+
|
26
|
+
enum.sample
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,93 @@
|
|
1
|
+
module JSON
|
2
|
+
module Fuzz
|
3
|
+
module Generator
|
4
|
+
class Keyword
|
5
|
+
class Format
|
6
|
+
class << self
|
7
|
+
def invalid_params(attributes)
|
8
|
+
format = attributes["format"]
|
9
|
+
raise "No format keyword given: #{attributes}" unless format
|
10
|
+
|
11
|
+
if invalid_params = format_to_invalid_params(format)
|
12
|
+
return invalid_params
|
13
|
+
else
|
14
|
+
raise "invalid format type: #{attributes}"
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def valid_param(attributes)
|
19
|
+
format = attributes["format"]
|
20
|
+
raise "No format keyword given: #{attributes}" unless format
|
21
|
+
|
22
|
+
if valid_params = format_to_valid_params(format)
|
23
|
+
return valid_params.sample
|
24
|
+
else
|
25
|
+
raise "invalid format type: #{attributes}"
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
def format_to_invalid_params(format)
|
31
|
+
{
|
32
|
+
"ip-address" => [
|
33
|
+
"1.1.1", "1.1.1.300", 5,
|
34
|
+
"1.1.1", "1.1.1.1b", "b1.1.1.1"
|
35
|
+
],
|
36
|
+
"ipv6" => [
|
37
|
+
"1111:2222:8888:99999:aaaa:cccc:eeee:ffff",
|
38
|
+
"1111:2222:8888:9999:aaaa:cccc:eeee:gggg",
|
39
|
+
"1111:2222::9999::cccc:eeee:ffff",
|
40
|
+
"1111:2222:8888:9999:aaaa:cccc:eeee:ffff:bbbb",
|
41
|
+
],
|
42
|
+
"time" => [
|
43
|
+
"12:00", "12:00:60", "12:60:00", "24:00:00",
|
44
|
+
"0:00:00", "-12:00:00", "12:00:00b"
|
45
|
+
],
|
46
|
+
"date" => [
|
47
|
+
"2010-01-32", "n2010-01-01", "2010-1-01",
|
48
|
+
"2010-01-1", "2010-01-01n"
|
49
|
+
],
|
50
|
+
"date-time" => [
|
51
|
+
"2010-01-32T12:00:00Z", "2010-13-01T12:00:00Z",
|
52
|
+
"2010-01-01T24:00:00Z", "2010-01-01T12:60:00Z",
|
53
|
+
"2010-01-01T12:00:60Z", "2010-01-01T12:00:00z",
|
54
|
+
"2010-01-0112:00:00Z",
|
55
|
+
],
|
56
|
+
"uri" => [
|
57
|
+
"::hoge",
|
58
|
+
],
|
59
|
+
"email" => [
|
60
|
+
"@example.com",
|
61
|
+
"hoge",
|
62
|
+
"http://example.com",
|
63
|
+
],
|
64
|
+
}[format]
|
65
|
+
end
|
66
|
+
|
67
|
+
def format_to_valid_params(format)
|
68
|
+
{
|
69
|
+
"ip-address" => ["1.1.1.1"],
|
70
|
+
"ipv6" => [
|
71
|
+
"1111:2222:8888:9999:aaaa:cccc:eeee:ffff",
|
72
|
+
"1111:0:8888:0:0:0:eeee:ffff",
|
73
|
+
"1111:2222:8888::eeee:ffff",
|
74
|
+
],
|
75
|
+
"time" => ["12:00:00"],
|
76
|
+
"date" => ["1992-06-27"],
|
77
|
+
"date-time" => [
|
78
|
+
"2010-01-01T12:00:00Z",
|
79
|
+
"2010-01-01T12:00:00.1Z",
|
80
|
+
"2010-01-01T12:00:00,1Z",
|
81
|
+
"2010-01-01T12:00:00+0000",
|
82
|
+
"2010-01-01T12:00:00+00:00",
|
83
|
+
],
|
84
|
+
"uri" => ["http://gitbuh.com"],
|
85
|
+
"email" => ["hoge@example.com"],
|
86
|
+
}[format]
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
module JSON
|
2
|
+
module Fuzz
|
3
|
+
module Generator
|
4
|
+
class Keyword
|
5
|
+
class Items
|
6
|
+
class << self
|
7
|
+
def invalid_params(attributes)
|
8
|
+
attributes = Marshal.load(Marshal.dump(attributes))
|
9
|
+
items = attributes.delete("items")
|
10
|
+
raise "No items keyword given: #{attributes}" unless items
|
11
|
+
|
12
|
+
generated_params = []
|
13
|
+
|
14
|
+
if items.instance_of?(Hash)
|
15
|
+
invalid_param = []
|
16
|
+
JSON::Fuzz::Generator.generate(items).each do |invalid_item|
|
17
|
+
invalid_param << invalid_item
|
18
|
+
end
|
19
|
+
generated_params << invalid_param
|
20
|
+
else
|
21
|
+
invalid_param = []
|
22
|
+
items.each do |item|
|
23
|
+
JSON::Fuzz::Generator.generate(item).each do |invalid_item|
|
24
|
+
invalid_param << invalid_item
|
25
|
+
end
|
26
|
+
end
|
27
|
+
generated_params << invalid_param
|
28
|
+
end
|
29
|
+
|
30
|
+
if attributes.key?("additionalItems")
|
31
|
+
additional_items = attributes.delete("additionalItems")
|
32
|
+
template = valid_param(attributes.merge("items" => items))
|
33
|
+
|
34
|
+
if additional_items
|
35
|
+
template << JSON::Fuzz::Generator.generate(additional_items).sample
|
36
|
+
generated_params << template
|
37
|
+
else
|
38
|
+
template << template.sample
|
39
|
+
generated_params << template
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
generated_params
|
44
|
+
end
|
45
|
+
|
46
|
+
def valid_param(attributes)
|
47
|
+
attributes = Marshal.load(Marshal.dump(attributes))
|
48
|
+
items = attributes.delete("items")
|
49
|
+
raise "No items keyword given: #{attributes}" unless items
|
50
|
+
|
51
|
+
generated_param = []
|
52
|
+
|
53
|
+
if items.instance_of?(Hash)
|
54
|
+
generated_param = JSON::Fuzz::Generator.default_param(items)
|
55
|
+
else
|
56
|
+
items.each do |item|
|
57
|
+
generated_param << JSON::Fuzz::Generator.default_param(item)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
generated_param
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
module JSON
|
2
|
+
module Fuzz
|
3
|
+
module Generator
|
4
|
+
class Keyword
|
5
|
+
class MaxItems
|
6
|
+
class << self
|
7
|
+
def invalid_params(attributes)
|
8
|
+
attributes = Marshal.load(Marshal.dump(attributes))
|
9
|
+
max_items = attributes.delete("maxItems")
|
10
|
+
raise "No maxItems keyword given: #{attributes}" unless max_items
|
11
|
+
|
12
|
+
generated_params = []
|
13
|
+
invalid_param = []
|
14
|
+
|
15
|
+
(max_items + 1).times do
|
16
|
+
item = JSON::Fuzz::Generator.default_param(attributes)
|
17
|
+
item = "null" if item.nil?
|
18
|
+
invalid_param << item
|
19
|
+
end
|
20
|
+
|
21
|
+
generated_params << invalid_param
|
22
|
+
|
23
|
+
generated_params
|
24
|
+
end
|
25
|
+
|
26
|
+
def valid_param(attributes)
|
27
|
+
attributes = Marshal.load(Marshal.dump(attributes))
|
28
|
+
max_items = attributes.delete("maxItems")
|
29
|
+
raise "No maxItems keyword given: #{attributes}" unless max_items
|
30
|
+
|
31
|
+
generated_param = []
|
32
|
+
|
33
|
+
max_items.times do
|
34
|
+
generated_param << JSON::Fuzz::Generator.default_param(attributes)
|
35
|
+
end
|
36
|
+
|
37
|
+
generated_param
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module JSON
|
2
|
+
module Fuzz
|
3
|
+
module Generator
|
4
|
+
class Keyword
|
5
|
+
class MaxLength
|
6
|
+
class << self
|
7
|
+
def invalid_params(attributes)
|
8
|
+
max_length = attributes["maxLength"]
|
9
|
+
raise "No maxLength keyword given: #{attributes}" unless max_length
|
10
|
+
|
11
|
+
generated_params = []
|
12
|
+
|
13
|
+
generated_params << /\w{1}/.gen * (max_length + 1)
|
14
|
+
|
15
|
+
return generated_params
|
16
|
+
end
|
17
|
+
|
18
|
+
def valid_param(attributes)
|
19
|
+
max_length = attributes["maxLength"]
|
20
|
+
raise "No maxLength keyword given: #{attributes}" unless max_length
|
21
|
+
|
22
|
+
/\w{1}/.gen * max_length
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
module JSON
|
2
|
+
module Fuzz
|
3
|
+
module Generator
|
4
|
+
class Keyword
|
5
|
+
class MaxProperties
|
6
|
+
class << self
|
7
|
+
def invalid_params(attributes)
|
8
|
+
max_properties = attributes["maxProperties"]
|
9
|
+
raise "No maxProperties keyword given: #{attributes}" unless max_properties
|
10
|
+
|
11
|
+
generated_params = []
|
12
|
+
invalid_param = {}
|
13
|
+
|
14
|
+
template = valid_param(attributes)
|
15
|
+
|
16
|
+
while template.size <= max_properties
|
17
|
+
key = /\w+/.gen
|
18
|
+
template[key] = template[template.keys.sample]
|
19
|
+
end
|
20
|
+
|
21
|
+
[template]
|
22
|
+
end
|
23
|
+
|
24
|
+
def valid_param(attributes)
|
25
|
+
attributes = Marshal.load(Marshal.dump(attributes))
|
26
|
+
max_properties = attributes.delete("maxProperties")
|
27
|
+
raise "No maxProperties keyword given: #{attributes}" unless max_properties
|
28
|
+
|
29
|
+
template = JSON::Fuzz::Generator.default_param(attributes)
|
30
|
+
|
31
|
+
while template.size > max_properties
|
32
|
+
requred_keys = attributes["required"] || []
|
33
|
+
key = (template.keys - requred_keys).sample
|
34
|
+
template.delete(template.keys.sample)
|
35
|
+
end
|
36
|
+
|
37
|
+
template
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|