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.
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