json-fuzz-generator 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (48) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +22 -0
  3. data/.rspec +2 -0
  4. data/.travis.yml +6 -0
  5. data/Gemfile +4 -0
  6. data/LICENSE.txt +22 -0
  7. data/README.md +100 -0
  8. data/Rakefile +7 -0
  9. data/json-fuzz-generator.gemspec +28 -0
  10. data/lib/json-fuzz-generator.rb +5 -0
  11. data/lib/json/fuzz/generator.rb +160 -0
  12. data/lib/json/fuzz/generator/keyword.rb +9 -0
  13. data/lib/json/fuzz/generator/keyword/additional_properties.rb +61 -0
  14. data/lib/json/fuzz/generator/keyword/all_of.rb +46 -0
  15. data/lib/json/fuzz/generator/keyword/any_of.rb +43 -0
  16. data/lib/json/fuzz/generator/keyword/dependencies.rb +49 -0
  17. data/lib/json/fuzz/generator/keyword/enum.rb +33 -0
  18. data/lib/json/fuzz/generator/keyword/format.rb +93 -0
  19. data/lib/json/fuzz/generator/keyword/items.rb +68 -0
  20. data/lib/json/fuzz/generator/keyword/max_items.rb +44 -0
  21. data/lib/json/fuzz/generator/keyword/max_length.rb +29 -0
  22. data/lib/json/fuzz/generator/keyword/max_properties.rb +44 -0
  23. data/lib/json/fuzz/generator/keyword/maximum.rb +46 -0
  24. data/lib/json/fuzz/generator/keyword/min_items.rb +44 -0
  25. data/lib/json/fuzz/generator/keyword/min_length.rb +29 -0
  26. data/lib/json/fuzz/generator/keyword/min_properties.rb +39 -0
  27. data/lib/json/fuzz/generator/keyword/minimum.rb +45 -0
  28. data/lib/json/fuzz/generator/keyword/multiple_of.rb +29 -0
  29. data/lib/json/fuzz/generator/keyword/not.rb +28 -0
  30. data/lib/json/fuzz/generator/keyword/one_of.rb +45 -0
  31. data/lib/json/fuzz/generator/keyword/pattern.rb +19 -0
  32. data/lib/json/fuzz/generator/keyword/properties.rb +40 -0
  33. data/lib/json/fuzz/generator/keyword/required.rb +41 -0
  34. data/lib/json/fuzz/generator/keyword/unique_items.rb +33 -0
  35. data/lib/json/fuzz/generator/primitive_type.rb +40 -0
  36. data/lib/json/fuzz/generator/primitive_type/array.rb +53 -0
  37. data/lib/json/fuzz/generator/primitive_type/boolean.rb +32 -0
  38. data/lib/json/fuzz/generator/primitive_type/integer.rb +56 -0
  39. data/lib/json/fuzz/generator/primitive_type/null.rb +33 -0
  40. data/lib/json/fuzz/generator/primitive_type/number.rb +52 -0
  41. data/lib/json/fuzz/generator/primitive_type/object.rb +57 -0
  42. data/lib/json/fuzz/generator/primitive_type/string.rb +53 -0
  43. data/lib/json/fuzz/generator/version.rb +7 -0
  44. data/spec/json-fuzz-generator_spec.rb +559 -0
  45. data/spec/schemas/basic_schema.json +17 -0
  46. data/spec/schemas/primitive_types.json +35 -0
  47. data/spec/spec_helper.rb +25 -0
  48. 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,7 @@
1
+ module JSON
2
+ module Fuzz
3
+ module Generator
4
+ VERSION = "0.0.1"
5
+ end
6
+ end
7
+ end
@@ -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