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,40 @@
|
|
1
|
+
module JSON
|
2
|
+
module Fuzz
|
3
|
+
module Generator
|
4
|
+
class PrimitiveType
|
5
|
+
Dir[File.join(File.dirname(__FILE__), "primitive_type/*.rb")].each {|file| require file }
|
6
|
+
|
7
|
+
class << self
|
8
|
+
def type_to_class_map
|
9
|
+
{
|
10
|
+
"array" => JSON::Fuzz::Generator::PrimitiveType::Array,
|
11
|
+
"boolean" => JSON::Fuzz::Generator::PrimitiveType::Boolean,
|
12
|
+
"integer" => JSON::Fuzz::Generator::PrimitiveType::Integer,
|
13
|
+
"null" => JSON::Fuzz::Generator::PrimitiveType::Null,
|
14
|
+
"number" => JSON::Fuzz::Generator::PrimitiveType::Number,
|
15
|
+
"object" => JSON::Fuzz::Generator::PrimitiveType::Object,
|
16
|
+
"string" => JSON::Fuzz::Generator::PrimitiveType::String,
|
17
|
+
}
|
18
|
+
end
|
19
|
+
|
20
|
+
def invalid_params_by_type(attributes)
|
21
|
+
type = attributes["type"]
|
22
|
+
raise "No type given: #{attributes}" unless type
|
23
|
+
|
24
|
+
valid_types = [type].flatten
|
25
|
+
valid_types.push("integer") if valid_types.include?("number")
|
26
|
+
|
27
|
+
invalid_params = []
|
28
|
+
|
29
|
+
type_to_class_map.each do |key, klass|
|
30
|
+
invalid_params.push(klass.valid_param(attributes)) unless valid_types.include?(key)
|
31
|
+
end
|
32
|
+
|
33
|
+
invalid_params
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
@@ -0,0 +1,53 @@
|
|
1
|
+
module JSON
|
2
|
+
module Fuzz
|
3
|
+
module Generator
|
4
|
+
class PrimitiveType
|
5
|
+
class Array
|
6
|
+
class << self
|
7
|
+
def invalid_params(attributes)
|
8
|
+
generated_params = []
|
9
|
+
|
10
|
+
if type = attributes["type"]
|
11
|
+
JSON::Fuzz::Generator::PrimitiveType.invalid_params_by_type(attributes).each do |invalid_param|
|
12
|
+
generated_params.push(invalid_param)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
attributes.each do |keyword, attribute|
|
17
|
+
if klass = keyword_to_class_map[keyword]
|
18
|
+
klass.invalid_params(attributes).each do |invalid_param|
|
19
|
+
generated_params << invalid_param
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
generated_params
|
25
|
+
end
|
26
|
+
|
27
|
+
def valid_param(attributes = {})
|
28
|
+
valid_params = []
|
29
|
+
|
30
|
+
attributes.each do |keyword, attribute|
|
31
|
+
if klass = keyword_to_class_map[keyword]
|
32
|
+
valid_params << klass.valid_param(attributes)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
valid_params.empty? ? ["sample", "array"] : valid_params.sample
|
37
|
+
end
|
38
|
+
|
39
|
+
def keyword_to_class_map
|
40
|
+
{
|
41
|
+
"minItems" => JSON::Fuzz::Generator::Keyword::MinItems,
|
42
|
+
"maxItems" => JSON::Fuzz::Generator::Keyword::MaxItems,
|
43
|
+
"uniqueItems" => JSON::Fuzz::Generator::Keyword::UniqueItems,
|
44
|
+
"items" => JSON::Fuzz::Generator::Keyword::Items,
|
45
|
+
}
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module JSON
|
2
|
+
module Fuzz
|
3
|
+
module Generator
|
4
|
+
class PrimitiveType
|
5
|
+
class Boolean
|
6
|
+
class << self
|
7
|
+
def invalid_params(attributes)
|
8
|
+
generated_params = []
|
9
|
+
|
10
|
+
if type = attributes["type"]
|
11
|
+
valid_types = [type].flatten
|
12
|
+
generated_params = ["true", "false", "1", "0"] unless valid_types.include?("string")
|
13
|
+
JSON::Fuzz::Generator::PrimitiveType.invalid_params_by_type(attributes).each do |invalid_param|
|
14
|
+
generated_params.push(invalid_param)
|
15
|
+
end
|
16
|
+
else
|
17
|
+
generated_params = ["true", "false", "1", "0"]
|
18
|
+
end
|
19
|
+
|
20
|
+
generated_params
|
21
|
+
end
|
22
|
+
|
23
|
+
def valid_param(attributes = {})
|
24
|
+
[true, false].sample
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
@@ -0,0 +1,56 @@
|
|
1
|
+
module JSON
|
2
|
+
module Fuzz
|
3
|
+
module Generator
|
4
|
+
class PrimitiveType
|
5
|
+
class Integer
|
6
|
+
class << self
|
7
|
+
def invalid_params(attributes)
|
8
|
+
generated_params = []
|
9
|
+
if type = attributes["type"]
|
10
|
+
valid_types = [type].flatten
|
11
|
+
["a", "1"].each {|val| generated_params << val} unless valid_types.include?("string")
|
12
|
+
generated_params << 0.1 unless valid_types.include?("number")
|
13
|
+
JSON::Fuzz::Generator::PrimitiveType.invalid_params_by_type(attributes).each do |invalid_param|
|
14
|
+
generated_params << invalid_param
|
15
|
+
end
|
16
|
+
else
|
17
|
+
#generated_params = ["a", "1"]
|
18
|
+
end
|
19
|
+
|
20
|
+
attributes.each do |keyword, attribute|
|
21
|
+
if klass = keyword_to_class_map[keyword]
|
22
|
+
klass.invalid_params(attributes).each do |invalid_param|
|
23
|
+
generated_params << invalid_param
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
generated_params
|
29
|
+
end
|
30
|
+
|
31
|
+
def valid_param(attributes = {})
|
32
|
+
valid_params = []
|
33
|
+
|
34
|
+
attributes.each do |keyword, attribute|
|
35
|
+
if klass = keyword_to_class_map[keyword]
|
36
|
+
valid_params << klass.valid_param(attributes)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
valid_params.empty? ? rand(100) : valid_params.sample
|
41
|
+
end
|
42
|
+
|
43
|
+
def keyword_to_class_map
|
44
|
+
{
|
45
|
+
"minimum" => JSON::Fuzz::Generator::Keyword::Minimum,
|
46
|
+
"maximum" => JSON::Fuzz::Generator::Keyword::Maximum,
|
47
|
+
"multipleOf" => JSON::Fuzz::Generator::Keyword::MultipleOf,
|
48
|
+
}
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module JSON
|
2
|
+
module Fuzz
|
3
|
+
module Generator
|
4
|
+
class PrimitiveType
|
5
|
+
class Null
|
6
|
+
class << self
|
7
|
+
def invalid_params(attributes)
|
8
|
+
generated_params = []
|
9
|
+
if type = attributes["type"]
|
10
|
+
valid_types = [type].flatten
|
11
|
+
generated_params = ["nil", "0", "null", ""] unless valid_types.include?("string")
|
12
|
+
generated_params.push(false) unless valid_types.include?("boolean")
|
13
|
+
|
14
|
+
JSON::Fuzz::Generator::PrimitiveType.invalid_params_by_type(attributes).each do |invalid_param|
|
15
|
+
generated_params.push(invalid_param)
|
16
|
+
end
|
17
|
+
else
|
18
|
+
generated_params = ["nil", "0", "null", false, ""]
|
19
|
+
end
|
20
|
+
|
21
|
+
generated_params
|
22
|
+
end
|
23
|
+
|
24
|
+
def valid_param(attributes = {})
|
25
|
+
nil
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
@@ -0,0 +1,52 @@
|
|
1
|
+
module JSON
|
2
|
+
module Fuzz
|
3
|
+
module Generator
|
4
|
+
class PrimitiveType
|
5
|
+
class Number
|
6
|
+
class << self
|
7
|
+
def invalid_params(attributes)
|
8
|
+
generated_params = []
|
9
|
+
if type = attributes["type"]
|
10
|
+
valid_types = [type].flatten
|
11
|
+
generated_params = ["0.1", "10", "hoge"] unless valid_types.include?("string")
|
12
|
+
JSON::Fuzz::Generator::PrimitiveType.invalid_params_by_type(attributes).each do |invalid_param|
|
13
|
+
generated_params << invalid_param
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
attributes.each do |keyword, attribute|
|
18
|
+
if klass = keyword_to_class_map[keyword]
|
19
|
+
klass.invalid_params(attributes).each do |invalid_param|
|
20
|
+
generated_params << invalid_param
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
generated_params
|
26
|
+
end
|
27
|
+
|
28
|
+
def valid_param(attributes = {})
|
29
|
+
valid_params = []
|
30
|
+
|
31
|
+
attributes.each do |keyword, attribute|
|
32
|
+
if klass = keyword_to_class_map[keyword]
|
33
|
+
valid_params << klass.valid_param(attributes).to_f
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
valid_params.empty? ? rand : valid_params.sample
|
38
|
+
end
|
39
|
+
|
40
|
+
def keyword_to_class_map
|
41
|
+
{
|
42
|
+
"minimum" => JSON::Fuzz::Generator::Keyword::Minimum,
|
43
|
+
"maximum" => JSON::Fuzz::Generator::Keyword::Maximum,
|
44
|
+
"multipleOf" => JSON::Fuzz::Generator::Keyword::MultipleOf,
|
45
|
+
}
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
module JSON
|
2
|
+
module Fuzz
|
3
|
+
module Generator
|
4
|
+
class PrimitiveType
|
5
|
+
class Object
|
6
|
+
class << self
|
7
|
+
def invalid_params(attributes)
|
8
|
+
generated_params = []
|
9
|
+
|
10
|
+
if type = attributes["type"]
|
11
|
+
valid_types = [type].flatten
|
12
|
+
JSON::Fuzz::Generator::PrimitiveType.invalid_params_by_type(attributes).each do |invalid_param|
|
13
|
+
generated_params.push(invalid_param)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
attributes.each do |keyword, attribute|
|
18
|
+
if klass = keyword_to_class_map[keyword]
|
19
|
+
klass.invalid_params(attributes).each do |invalid_param|
|
20
|
+
generated_params << invalid_param
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
generated_params
|
26
|
+
end
|
27
|
+
|
28
|
+
def valid_param(attributes = {})
|
29
|
+
generated_params = {}
|
30
|
+
|
31
|
+
attributes.each do |keyword, attribute|
|
32
|
+
if klass = keyword_to_class_map[keyword]
|
33
|
+
generated_params.merge!(klass.valid_param(attributes))
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
generated_params
|
38
|
+
end
|
39
|
+
|
40
|
+
def keyword_to_class_map
|
41
|
+
{
|
42
|
+
"members" => JSON::Fuzz::Generator::Keyword::Properties,
|
43
|
+
"properties" => JSON::Fuzz::Generator::Keyword::Properties,
|
44
|
+
"required" => JSON::Fuzz::Generator::Keyword::Required,
|
45
|
+
"minProperties" => JSON::Fuzz::Generator::Keyword::MinProperties,
|
46
|
+
"maxProperties" => JSON::Fuzz::Generator::Keyword::MaxProperties,
|
47
|
+
"additionalProperties" => JSON::Fuzz::Generator::Keyword::AdditionalProperties,
|
48
|
+
"dependencies" => JSON::Fuzz::Generator::Keyword::Dependencies,
|
49
|
+
}
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
@@ -0,0 +1,53 @@
|
|
1
|
+
module JSON
|
2
|
+
module Fuzz
|
3
|
+
module Generator
|
4
|
+
class PrimitiveType
|
5
|
+
class String
|
6
|
+
class << self
|
7
|
+
def invalid_params(attributes)
|
8
|
+
generated_params = []
|
9
|
+
if type = attributes["type"]
|
10
|
+
valid_types = [type].flatten
|
11
|
+
JSON::Fuzz::Generator::PrimitiveType.invalid_params_by_type(attributes).each do |invalid_param|
|
12
|
+
generated_params.push(invalid_param)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
attributes.each do |keyword, attribute|
|
17
|
+
if klass = keyword_to_class_map[keyword]
|
18
|
+
klass.invalid_params(attributes).each do |invalid_param|
|
19
|
+
generated_params << invalid_param
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
generated_params.empty? ? [1] : generated_params
|
25
|
+
end
|
26
|
+
|
27
|
+
def valid_param(attributes = {})
|
28
|
+
generated_params = []
|
29
|
+
|
30
|
+
attributes.each do |keyword, attribute|
|
31
|
+
if klass = keyword_to_class_map[keyword]
|
32
|
+
generated_params << klass.valid_param(attributes)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
generated_params.empty? ? "hoge" : generated_params.sample
|
37
|
+
end
|
38
|
+
|
39
|
+
def keyword_to_class_map
|
40
|
+
{
|
41
|
+
"pattern" => JSON::Fuzz::Generator::Keyword::Pattern,
|
42
|
+
"minLength" => JSON::Fuzz::Generator::Keyword::MinLength,
|
43
|
+
"maxLength" => JSON::Fuzz::Generator::Keyword::MaxLength,
|
44
|
+
"format" => JSON::Fuzz::Generator::Keyword::Format,
|
45
|
+
}
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
@@ -0,0 +1,559 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe JSON::Fuzz do
|
4
|
+
shared_examples_for JSON::Fuzz::Generator do
|
5
|
+
context "#default_param" do
|
6
|
+
it "can generate valid parameter" do
|
7
|
+
valid_parameter = JSON::Fuzz::Generator.default_param(schema)
|
8
|
+
expect(valid_parameter).to be_matching_schema(schema)
|
9
|
+
#expect(JSON::Validator.validate(schema, valid_parameter)).to eq(true)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
context "#generate" do
|
14
|
+
it "can generate invalid parameter" do
|
15
|
+
invalid_parameters = JSON::Fuzz::Generator.generate(schema)
|
16
|
+
invalid_parameters.each do |invalid_param|
|
17
|
+
expect(invalid_param).to be_not_matching_schema(schema)
|
18
|
+
#expect(JSON::Validator.validate(schema, invalid_param)).to eq(false)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
context "types" do
|
25
|
+
%w(integer number string object array null any).each do |type|
|
26
|
+
context "when #{type}" do
|
27
|
+
it_behaves_like JSON::Fuzz::Generator do
|
28
|
+
let(:schema) {{
|
29
|
+
"$schema" => "http://json-schema.org/draft-04/schema#",
|
30
|
+
"type" => type
|
31
|
+
}}
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
context "when union type" do
|
37
|
+
context "given integer and string" do
|
38
|
+
it_behaves_like JSON::Fuzz::Generator do
|
39
|
+
let(:schema) {{
|
40
|
+
"$schema" => "http://json-schema.org/draft-04/schema#",
|
41
|
+
"type" => ["integer", "string"],
|
42
|
+
}}
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
context "given string and null" do
|
47
|
+
it_behaves_like JSON::Fuzz::Generator do
|
48
|
+
let(:schema) {{
|
49
|
+
"$schema" => "http://json-schema.org/draft-04/schema#",
|
50
|
+
"type" => ["string", "null"],
|
51
|
+
}}
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
context "given integer and object" do
|
56
|
+
it_behaves_like JSON::Fuzz::Generator do
|
57
|
+
let(:schema) {{
|
58
|
+
"$schema" => "http://json-schema.org/draft-04/schema#",
|
59
|
+
"type" => ["integer", "object"],
|
60
|
+
}}
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
context "required" do
|
67
|
+
it_behaves_like JSON::Fuzz::Generator do
|
68
|
+
let(:schema) {{
|
69
|
+
"$schema" => "http://json-schema.org/draft-04/schema#",
|
70
|
+
"required" => ["a"],
|
71
|
+
"properties" => {
|
72
|
+
"a" => {},
|
73
|
+
},
|
74
|
+
}}
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
context "minimum" do
|
79
|
+
context "without exclusiveMinimum" do
|
80
|
+
it_behaves_like JSON::Fuzz::Generator do
|
81
|
+
let(:schema) {{
|
82
|
+
"$schema" => "http://json-schema.org/draft-04/schema#",
|
83
|
+
"properties" => {
|
84
|
+
"a" => {"minimum" => 100},
|
85
|
+
},
|
86
|
+
}}
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
context "with exclusiveMinimum" do
|
91
|
+
it_behaves_like JSON::Fuzz::Generator do
|
92
|
+
let(:schema) {{
|
93
|
+
"$schema" => "http://json-schema.org/draft-04/schema#",
|
94
|
+
"properties" => {
|
95
|
+
"a" => {
|
96
|
+
"minimum" => 100,
|
97
|
+
"exclusiveMinimum" => true,
|
98
|
+
},
|
99
|
+
},
|
100
|
+
}}
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
context "maximum" do
|
106
|
+
context "without exclusiveMaximum" do
|
107
|
+
it_behaves_like JSON::Fuzz::Generator do
|
108
|
+
let(:schema) {{
|
109
|
+
"$schema" => "http://json-schema.org/draft-04/schema#",
|
110
|
+
"properties" => {
|
111
|
+
"a" => {"maximum" => 3},
|
112
|
+
},
|
113
|
+
}}
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
context "with exclusiveMaximum" do
|
118
|
+
it_behaves_like JSON::Fuzz::Generator do
|
119
|
+
let(:schema) {{
|
120
|
+
"$schema" => "http://json-schema.org/draft-04/schema#",
|
121
|
+
"properties" => {
|
122
|
+
"a" => {
|
123
|
+
"maximum" => 3,
|
124
|
+
"exclusiveMaximum" => true,
|
125
|
+
},
|
126
|
+
},
|
127
|
+
}}
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
context "minItems" do
|
133
|
+
it_behaves_like JSON::Fuzz::Generator do
|
134
|
+
let(:schema) {{
|
135
|
+
"$schema" => "http://json-schema.org/draft-04/schema#",
|
136
|
+
"properties" => {
|
137
|
+
"a" => {"minItems" => 5},
|
138
|
+
},
|
139
|
+
}}
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
context "maxItems" do
|
144
|
+
it_behaves_like JSON::Fuzz::Generator do
|
145
|
+
let(:schema) {{
|
146
|
+
"$schema" => "http://json-schema.org/draft-04/schema#",
|
147
|
+
"properties" => {
|
148
|
+
"a" => {"maxItems" => 3},
|
149
|
+
},
|
150
|
+
}}
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
context "minProperties" do
|
155
|
+
it_behaves_like JSON::Fuzz::Generator do
|
156
|
+
let(:schema) {{
|
157
|
+
"$schema" => "http://json-schema.org/draft-04/schema#",
|
158
|
+
"minProperties" => 2,
|
159
|
+
"properties" => {},
|
160
|
+
}}
|
161
|
+
end
|
162
|
+
end
|
163
|
+
|
164
|
+
context "maxProperties" do
|
165
|
+
it_behaves_like JSON::Fuzz::Generator do
|
166
|
+
let(:schema) {{
|
167
|
+
"$schema" => "http://json-schema.org/draft-04/schema#",
|
168
|
+
"maxProperties" => 2,
|
169
|
+
"properties" => {},
|
170
|
+
}}
|
171
|
+
end
|
172
|
+
end
|
173
|
+
|
174
|
+
xcontext "strict option" do
|
175
|
+
shared_examples_for JSON::Fuzz::Generator do
|
176
|
+
let(:generator) { JSON::Fuzz::Generator.new }
|
177
|
+
|
178
|
+
context "#default_param" do
|
179
|
+
it "can generate valid parameter" do
|
180
|
+
valid_parameter = generator.default_param(schema, :strict => true)
|
181
|
+
expect(JSON::Validator.validate(schema, valid_parameter, :strict => true)).to eq(true)
|
182
|
+
end
|
183
|
+
end
|
184
|
+
|
185
|
+
context "#generate" do
|
186
|
+
it "can generate invalid parameter" do
|
187
|
+
invalid_parameters = generator.generate(schema, :strict => true)
|
188
|
+
invalid_parameters.each do |invalid_param|
|
189
|
+
expect(JSON::Validator.validate(schema, invalid_param, :strict => true)).to eq(false)
|
190
|
+
end
|
191
|
+
end
|
192
|
+
end
|
193
|
+
end
|
194
|
+
|
195
|
+
context "without anly props" do
|
196
|
+
it_behaves_like JSON::Fuzz::Generator do
|
197
|
+
let(:schema) {{
|
198
|
+
"$schema" => "http://json-schema.org/draft-04/schema#",
|
199
|
+
"properties" => {
|
200
|
+
"a" => {"type" => "string"},
|
201
|
+
"b" => {"type" => "string"},
|
202
|
+
},
|
203
|
+
}}
|
204
|
+
end
|
205
|
+
end
|
206
|
+
|
207
|
+
context "with additionalProperties" do
|
208
|
+
it_behaves_like JSON::Fuzz::Generator do
|
209
|
+
let(:schema) {{
|
210
|
+
"$schema" => "http://json-schema.org/draft-04/schema#",
|
211
|
+
"additionalProperties" => {"type" => "integer"},
|
212
|
+
"properties" => {
|
213
|
+
"a" => {"type" => "string"},
|
214
|
+
"b" => {"type" => "string"}
|
215
|
+
},
|
216
|
+
}}
|
217
|
+
end
|
218
|
+
end
|
219
|
+
|
220
|
+
xcontext "with patternProperties" do
|
221
|
+
it_behaves_like JSON::Fuzz::Generator do
|
222
|
+
let(:schema) {{
|
223
|
+
"$schema" => "http://json-schema.org/draft-04/schema#",
|
224
|
+
"patternProperties" => {"\\d+ taco" => {"type" => "integer"}},
|
225
|
+
"properties" => {
|
226
|
+
"a" => {"type" => "string"},
|
227
|
+
"b" => {"type" => "string"},
|
228
|
+
},
|
229
|
+
}}
|
230
|
+
end
|
231
|
+
end
|
232
|
+
end
|
233
|
+
|
234
|
+
context "uniqueItems" do
|
235
|
+
it_behaves_like JSON::Fuzz::Generator do
|
236
|
+
let(:schema) {{
|
237
|
+
"$schema" => "http://json-schema.org/draft-04/schema#",
|
238
|
+
"properties" => {
|
239
|
+
"a" => {"uniqueItems" => true},
|
240
|
+
},
|
241
|
+
}}
|
242
|
+
end
|
243
|
+
end
|
244
|
+
|
245
|
+
xcontext "pattern" do
|
246
|
+
it_behaves_like JSON::Fuzz::Generator do
|
247
|
+
let(:schema) {{
|
248
|
+
"$schema" => "http://json-schema.org/draft-04/schema#",
|
249
|
+
"properties" => {
|
250
|
+
"a" => {"pattern" => "\\d+ takoyaki"},
|
251
|
+
},
|
252
|
+
}}
|
253
|
+
end
|
254
|
+
end
|
255
|
+
|
256
|
+
context "minLength" do
|
257
|
+
it_behaves_like JSON::Fuzz::Generator do
|
258
|
+
let(:schema) {{
|
259
|
+
"$schema" => "http://json-schema.org/draft-04/schema#",
|
260
|
+
"properties" => {
|
261
|
+
"a" => {"minLength" => 1},
|
262
|
+
},
|
263
|
+
}}
|
264
|
+
end
|
265
|
+
end
|
266
|
+
|
267
|
+
context "maxLength" do
|
268
|
+
it_behaves_like JSON::Fuzz::Generator do
|
269
|
+
let(:schema) {{
|
270
|
+
"$schema" => "http://json-schema.org/draft-04/schema#",
|
271
|
+
"properties" => {
|
272
|
+
"a" => {"maxLength" => 1},
|
273
|
+
},
|
274
|
+
}}
|
275
|
+
end
|
276
|
+
end
|
277
|
+
|
278
|
+
context "enum" do
|
279
|
+
it_behaves_like JSON::Fuzz::Generator do
|
280
|
+
let(:schema) {{
|
281
|
+
"$schema" => "http://json-schema.org/draft-04/schema#",
|
282
|
+
"properties" => {
|
283
|
+
"a" => {"enum" => ["hoge", 22, [0, 3], {"foo" => "bar"}]},
|
284
|
+
},
|
285
|
+
}}
|
286
|
+
end
|
287
|
+
end
|
288
|
+
|
289
|
+
context "multipleOf" do
|
290
|
+
it_behaves_like JSON::Fuzz::Generator do
|
291
|
+
let(:schema) {{
|
292
|
+
"$schema" => "http://json-schema.org/draft-04/schema#",
|
293
|
+
"properties" => {
|
294
|
+
"a" => {"multipleOf" => 1.3},
|
295
|
+
},
|
296
|
+
}}
|
297
|
+
end
|
298
|
+
end
|
299
|
+
|
300
|
+
xcontext "patternProperties" do
|
301
|
+
it_behaves_like JSON::Fuzz::Generator do
|
302
|
+
let(:schema) {{
|
303
|
+
"$schema" => "http://json-schema.org/draft-04/schema#",
|
304
|
+
"patternProperties" => {
|
305
|
+
"\\d+ takoyaki" => {"type" => "integer"},
|
306
|
+
},
|
307
|
+
}}
|
308
|
+
end
|
309
|
+
end
|
310
|
+
|
311
|
+
context "additionalProperties" do
|
312
|
+
context "given no properties" do
|
313
|
+
it_behaves_like JSON::Fuzz::Generator do
|
314
|
+
let(:schema) {{
|
315
|
+
"$schema" => "http://json-schema.org/draft-04/schema#",
|
316
|
+
"properties" => {
|
317
|
+
"a" => {"type" => "integer"},
|
318
|
+
},
|
319
|
+
"additionalProperties" => false,
|
320
|
+
}}
|
321
|
+
end
|
322
|
+
end
|
323
|
+
|
324
|
+
context "given property of type" do
|
325
|
+
it_behaves_like JSON::Fuzz::Generator do
|
326
|
+
let(:schema) {{
|
327
|
+
"$schema" => "http://json-schema.org/draft-04/schema#",
|
328
|
+
"properties" => {
|
329
|
+
"a" => {"type" => "integer"},
|
330
|
+
},
|
331
|
+
"additionalProperties" => {"type" => "string"},
|
332
|
+
}}
|
333
|
+
end
|
334
|
+
end
|
335
|
+
|
336
|
+
xcontext "with patternProperties" do
|
337
|
+
it_behaves_like JSON::Fuzz::Generator do
|
338
|
+
let(:schema) {{
|
339
|
+
"$schema" => "http://json-schema.org/draft-04/schema#",
|
340
|
+
"patternProperties" => {
|
341
|
+
"\\d+ takoyaki" => {"type" => "integer"},
|
342
|
+
},
|
343
|
+
"additionalProperties" => false,
|
344
|
+
}}
|
345
|
+
end
|
346
|
+
end
|
347
|
+
end
|
348
|
+
|
349
|
+
context "items" do
|
350
|
+
context "given single property" do
|
351
|
+
it_behaves_like JSON::Fuzz::Generator do
|
352
|
+
let(:schema) {{
|
353
|
+
"$schema" => "http://json-schema.org/draft-04/schema#",
|
354
|
+
"items" => {"type" => "integer"},
|
355
|
+
}}
|
356
|
+
end
|
357
|
+
end
|
358
|
+
|
359
|
+
context "given multiple properties" do
|
360
|
+
it_behaves_like JSON::Fuzz::Generator do
|
361
|
+
let(:schema) {{
|
362
|
+
"$schema" => "http://json-schema.org/draft-04/schema#",
|
363
|
+
"items" => [
|
364
|
+
{"type" => "integer"},
|
365
|
+
{"type" => "string"},
|
366
|
+
],
|
367
|
+
}}
|
368
|
+
end
|
369
|
+
end
|
370
|
+
|
371
|
+
context "with additionalItems" do
|
372
|
+
context "given false" do
|
373
|
+
it_behaves_like JSON::Fuzz::Generator do
|
374
|
+
let(:schema) {{
|
375
|
+
"$schema" => "http://json-schema.org/draft-04/schema#",
|
376
|
+
"items" => [
|
377
|
+
{"type" => "integer"},
|
378
|
+
{"type" => "string"},
|
379
|
+
],
|
380
|
+
"additionalItems" => false,
|
381
|
+
}}
|
382
|
+
end
|
383
|
+
end
|
384
|
+
|
385
|
+
context "given property" do
|
386
|
+
it_behaves_like JSON::Fuzz::Generator do
|
387
|
+
let(:schema) {{
|
388
|
+
"$schema" => "http://json-schema.org/draft-04/schema#",
|
389
|
+
"items" => [
|
390
|
+
{"type" => "integer"},
|
391
|
+
{"type" => "string"},
|
392
|
+
],
|
393
|
+
"additionalItems" => {"type" => "integer"},
|
394
|
+
}}
|
395
|
+
end
|
396
|
+
end
|
397
|
+
end
|
398
|
+
end
|
399
|
+
|
400
|
+
xcontext "self reference" do
|
401
|
+
it_behaves_like JSON::Fuzz::Generator do
|
402
|
+
let(:schema) {{
|
403
|
+
"$schema" => "http://json-schema.org/draft-04/schema#",
|
404
|
+
"type" => "object",
|
405
|
+
"properties" => {
|
406
|
+
"a" => {"type" => "integer"},
|
407
|
+
"b" => {"$ref" => "#"},
|
408
|
+
},
|
409
|
+
}}
|
410
|
+
end
|
411
|
+
end
|
412
|
+
|
413
|
+
%w[ip-address ipv6 time date date-time uri].each do |format|
|
414
|
+
context "format #{format}" do
|
415
|
+
it_behaves_like JSON::Fuzz::Generator do
|
416
|
+
let(:schema) {{
|
417
|
+
"$schema" => "http://json-schema.org/draft-04/schema#",
|
418
|
+
"type" => "object",
|
419
|
+
"properties" => {
|
420
|
+
"a" => {
|
421
|
+
"type" => "string",
|
422
|
+
"format" => format,
|
423
|
+
},
|
424
|
+
},
|
425
|
+
}}
|
426
|
+
end
|
427
|
+
end
|
428
|
+
end
|
429
|
+
|
430
|
+
context "format with union types" do
|
431
|
+
it_behaves_like JSON::Fuzz::Generator do
|
432
|
+
let(:schema) {{
|
433
|
+
"$schema" => "http://json-schema.org/draft-04/schema#",
|
434
|
+
"type" => "object",
|
435
|
+
"properties" => {
|
436
|
+
"a" => {
|
437
|
+
"type" => ["string", "null"],
|
438
|
+
"format" => "ip-address",
|
439
|
+
},
|
440
|
+
},
|
441
|
+
}}
|
442
|
+
end
|
443
|
+
end
|
444
|
+
|
445
|
+
context "dependencies" do
|
446
|
+
context "given single property" do
|
447
|
+
it_behaves_like JSON::Fuzz::Generator do
|
448
|
+
let(:schema) {{
|
449
|
+
"$schema" => "http://json-schema.org/draft-04/schema#",
|
450
|
+
"type" => "object",
|
451
|
+
"properties" => {
|
452
|
+
"a" => {"type" => "integer"},
|
453
|
+
"b" => {"type" => "integer"},
|
454
|
+
},
|
455
|
+
"dependencies" => {"a" => ["b"]},
|
456
|
+
}}
|
457
|
+
end
|
458
|
+
end
|
459
|
+
|
460
|
+
context "given multiple properties" do
|
461
|
+
it_behaves_like JSON::Fuzz::Generator do
|
462
|
+
let(:schema) {{
|
463
|
+
"$schema" => "http://json-schema.org/draft-04/schema#",
|
464
|
+
"type" => "object",
|
465
|
+
"properties" => {
|
466
|
+
"a" => {"type" => "integer"},
|
467
|
+
"b" => {"type" => "integer"},
|
468
|
+
},
|
469
|
+
"dependencies" => {"a" => ["b", "c"]},
|
470
|
+
}}
|
471
|
+
end
|
472
|
+
end
|
473
|
+
end
|
474
|
+
|
475
|
+
context "default" do
|
476
|
+
it_behaves_like JSON::Fuzz::Generator do
|
477
|
+
let(:schema) {{
|
478
|
+
"$schema" => "http://json-schema.org/draft-04/schema#",
|
479
|
+
"type" => "object",
|
480
|
+
"properties" => {
|
481
|
+
"a" => {"type" => "integer", "default" => 22},
|
482
|
+
"b" => {"type" => "integer"},
|
483
|
+
},
|
484
|
+
}}
|
485
|
+
end
|
486
|
+
|
487
|
+
context "with readonly" do
|
488
|
+
it_behaves_like JSON::Fuzz::Generator do
|
489
|
+
let(:schema) {{
|
490
|
+
"$schema" => "http://json-schema.org/draft-04/schema#",
|
491
|
+
"type" => "object",
|
492
|
+
"properties" => {
|
493
|
+
"a" => {"type" => "integer", "default" => 22, "readonly" => true},
|
494
|
+
"b" => {"type" => "integer"},
|
495
|
+
},
|
496
|
+
}}
|
497
|
+
end
|
498
|
+
end
|
499
|
+
end
|
500
|
+
|
501
|
+
%w[allOf anyOf oneOf].each do |keyword|
|
502
|
+
context keyword do
|
503
|
+
it_behaves_like JSON::Fuzz::Generator do
|
504
|
+
let(:schema) {{
|
505
|
+
"$schema" => "http://json-schema.org/draft-04/schema#",
|
506
|
+
keyword => [
|
507
|
+
{
|
508
|
+
"properties" => {"a" => {"type" => "string"}},
|
509
|
+
"required" => ["a"],
|
510
|
+
},
|
511
|
+
{
|
512
|
+
"properties" => {"b" => {"type" => "integer"}},
|
513
|
+
},
|
514
|
+
]
|
515
|
+
}}
|
516
|
+
end
|
517
|
+
end
|
518
|
+
end
|
519
|
+
|
520
|
+
context "not" do
|
521
|
+
it_behaves_like JSON::Fuzz::Generator do
|
522
|
+
let(:schema) {{
|
523
|
+
"$schema" => "http://json-schema.org/draft-04/schema#",
|
524
|
+
"properties" => {
|
525
|
+
"a" => {"not" => {"type" => ["string", "boolean"]}},
|
526
|
+
},
|
527
|
+
}}
|
528
|
+
end
|
529
|
+
|
530
|
+
context "with sub schema" do
|
531
|
+
it_behaves_like JSON::Fuzz::Generator do
|
532
|
+
let(:schema) {{
|
533
|
+
"$schema" => "http://json-schema.org/draft-04/schema#",
|
534
|
+
"properties" => {"a" => {"not" => {"anyOf" => [
|
535
|
+
{"type" => ["string", "boolean"]},
|
536
|
+
{"type" => "object", "properties" => {"b" => {"type" => "boolean"}}},
|
537
|
+
]}}},
|
538
|
+
}}
|
539
|
+
end
|
540
|
+
end
|
541
|
+
end
|
542
|
+
|
543
|
+
xcontext "definitions" do
|
544
|
+
it_behaves_like JSON::Fuzz::Generator do
|
545
|
+
let(:schema) {{
|
546
|
+
"$schema" => "http://json-schema.org/draft-04/schema#",
|
547
|
+
"type" => "array",
|
548
|
+
"items" => {"$ref" => "#/definitions/positiveInteger"},
|
549
|
+
"definitions" => {
|
550
|
+
"positiveInteger" => {
|
551
|
+
"type" => "integer",
|
552
|
+
"minimum" => 0,
|
553
|
+
"exclusiveMinimum" => true,
|
554
|
+
},
|
555
|
+
},
|
556
|
+
}}
|
557
|
+
end
|
558
|
+
end
|
559
|
+
end
|