json-fuzz-generator 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 30a39a73a5cf80278262d3256ebb21cf148cf8f3
|
4
|
+
data.tar.gz: 07a5db01c606abf3f00702cfbfad86f6df46d8fd
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: f1ca3a27181a14ef2297b670f4c9742b0ae82bc46b5f09e67c093331dd01f9b42e2db6f676ff3091f747228c1f7c9b35a1e3fe130c6acb61a2c71e562fb7d4c0
|
7
|
+
data.tar.gz: 967c4a4f35a5a3fcbe26ab9e6ce722f25679d7d27ca01780a669f92ab5fdf58c7204a67445d871ce4a92b697e35f4fd831e2f3006810050e6b1c8519a522bb86
|
data/.gitignore
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
*.gem
|
2
|
+
*.rbc
|
3
|
+
.bundle
|
4
|
+
.config
|
5
|
+
.yardoc
|
6
|
+
Gemfile.lock
|
7
|
+
InstalledFiles
|
8
|
+
_yardoc
|
9
|
+
coverage
|
10
|
+
doc/
|
11
|
+
lib/bundler/man
|
12
|
+
pkg
|
13
|
+
rdoc
|
14
|
+
spec/reports
|
15
|
+
test/tmp
|
16
|
+
test/version_tmp
|
17
|
+
tmp
|
18
|
+
*.bundle
|
19
|
+
*.so
|
20
|
+
*.o
|
21
|
+
*.a
|
22
|
+
mkmf.log
|
data/.rspec
ADDED
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2014 Naoki Shimizu
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,100 @@
|
|
1
|
+
# JSON::Fuzz::Generator
|
2
|
+
|
3
|
+
Fuzzing Parameter Generator from JSON Schema
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Add this line to your application's Gemfile:
|
8
|
+
|
9
|
+
gem 'json-fuzz-generator'
|
10
|
+
|
11
|
+
And then execute:
|
12
|
+
|
13
|
+
$ bundle
|
14
|
+
|
15
|
+
Or install it yourself as:
|
16
|
+
|
17
|
+
$ gem install json-fuzz-generator
|
18
|
+
|
19
|
+
## Usage
|
20
|
+
|
21
|
+
### input JSON Schema
|
22
|
+
|
23
|
+
```json:input_schema.json
|
24
|
+
{
|
25
|
+
"title": "Basic Schema",
|
26
|
+
"type": "object",
|
27
|
+
"properties": {
|
28
|
+
"id" : {
|
29
|
+
"type": "integer",
|
30
|
+
"minimum": 0
|
31
|
+
},
|
32
|
+
"name": {
|
33
|
+
"type": "string"
|
34
|
+
},
|
35
|
+
"birthday": {
|
36
|
+
"type": "string",
|
37
|
+
"format": "date"
|
38
|
+
}
|
39
|
+
}
|
40
|
+
}
|
41
|
+
```
|
42
|
+
### generate valid param
|
43
|
+
|
44
|
+
```ruby
|
45
|
+
require "json-fuzz-generator"
|
46
|
+
|
47
|
+
JSON::Fuzz::Generator.default_param(schema_file)
|
48
|
+
# => {"id"=>0, "name"=>"hoge", "birthday"=>"1992-06-27"}
|
49
|
+
```
|
50
|
+
### generate invalid params
|
51
|
+
|
52
|
+
```ruby
|
53
|
+
require "json-fuzz-generator"
|
54
|
+
|
55
|
+
JSON::Fuzz::Generator.generate(schema_file)
|
56
|
+
# =>
|
57
|
+
#[
|
58
|
+
# ["sample", "array"],
|
59
|
+
# true,
|
60
|
+
# 73,
|
61
|
+
# nil,
|
62
|
+
# 0.34259093948835795,
|
63
|
+
# "hoge",
|
64
|
+
# {"id"=>"a", "name"=>"hoge", "birthday"=>"1992-06-27"},
|
65
|
+
# {"id"=>"1", "name"=>"hoge", "birthday"=>"1992-06-27"},
|
66
|
+
# {"id"=>0.1, "name"=>"hoge", "birthday"=>"1992-06-27"},
|
67
|
+
# {"id"=>["sample", "array"], "name"=>"hoge", "birthday"=>"1992-06-27"},
|
68
|
+
# {"id"=>false, "name"=>"hoge", "birthday"=>"1992-06-27"},
|
69
|
+
# {"id"=>nil, "name"=>"hoge", "birthday"=>"1992-06-27"},
|
70
|
+
# {"id"=>0.0, "name"=>"hoge", "birthday"=>"1992-06-27"},
|
71
|
+
# {"id"=>{}, "name"=>"hoge", "birthday"=>"1992-06-27"},
|
72
|
+
# {"id"=>"hoge", "name"=>"hoge", "birthday"=>"1992-06-27"},
|
73
|
+
# {"id"=>-1, "name"=>"hoge", "birthday"=>"1992-06-27"},
|
74
|
+
# {"id"=>0, "name"=>["sample", "array"], "birthday"=>"1992-06-27"},
|
75
|
+
# {"id"=>0, "name"=>true, "birthday"=>"1992-06-27"},
|
76
|
+
# {"id"=>0, "name"=>97, "birthday"=>"1992-06-27"},
|
77
|
+
# {"id"=>0, "name"=>nil, "birthday"=>"1992-06-27"},
|
78
|
+
# {"id"=>0, "name"=>0.7547537108664406, "birthday"=>"1992-06-27"},
|
79
|
+
# {"id"=>0, "name"=>{}, "birthday"=>"1992-06-27"},
|
80
|
+
# {"id"=>0, "name"=>"hoge", "birthday"=>["sample", "array"]},
|
81
|
+
# {"id"=>0, "name"=>"hoge", "birthday"=>false},
|
82
|
+
# {"id"=>0, "name"=>"hoge", "birthday"=>11},
|
83
|
+
# {"id"=>0, "name"=>"hoge", "birthday"=>nil},
|
84
|
+
# {"id"=>0, "name"=>"hoge", "birthday"=>0.5380909041403419},
|
85
|
+
# {"id"=>0, "name"=>"hoge", "birthday"=>{}},
|
86
|
+
# {"id"=>0, "name"=>"hoge", "birthday"=>"2010-01-32"},
|
87
|
+
# {"id"=>0, "name"=>"hoge", "birthday"=>"n2010-01-01"},
|
88
|
+
# {"id"=>0, "name"=>"hoge", "birthday"=>"2010-1-01"},
|
89
|
+
# {"id"=>0, "name"=>"hoge", "birthday"=>"2010-01-1"},
|
90
|
+
# {"id"=>0, "name"=>"hoge", "birthday"=>"2010-01-01n"},
|
91
|
+
#]
|
92
|
+
```
|
93
|
+
|
94
|
+
## Contributing
|
95
|
+
|
96
|
+
1. Fork it ( https://github.com/deme0607/json-fuzz-generator/fork )
|
97
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
98
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
99
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
100
|
+
5. Create a new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'json/fuzz/generator/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "json-fuzz-generator"
|
8
|
+
spec.version = JSON::Fuzz::Generator::VERSION
|
9
|
+
spec.authors = ["deme0607"]
|
10
|
+
spec.email = ["hcs0035@gmail.com"]
|
11
|
+
spec.summary = %q{Fuzz parameter gemerator from json-schema}
|
12
|
+
spec.description = %q{Fuzz parameter gemerator from json-schema}
|
13
|
+
spec.homepage = "https://github.com/deme0607/json-fuzz-generator"
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files -z`.split("\x0")
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.add_dependency "json-schema"
|
22
|
+
spec.add_dependency "randexp"
|
23
|
+
|
24
|
+
spec.add_development_dependency "bundler", "~> 1.6"
|
25
|
+
spec.add_development_dependency "rake"
|
26
|
+
spec.add_development_dependency "rspec"
|
27
|
+
spec.add_development_dependency "pry-byebug"
|
28
|
+
end
|
@@ -0,0 +1,160 @@
|
|
1
|
+
module JSON
|
2
|
+
module Fuzz
|
3
|
+
module Generator
|
4
|
+
Dir[File.join(File.dirname(__FILE__), "generator/*.rb")].each {|file| require file }
|
5
|
+
|
6
|
+
extend self
|
7
|
+
def generators(type)
|
8
|
+
generator_map = {
|
9
|
+
"array" => JSON::Fuzz::Generator::PrimitiveType::Array,
|
10
|
+
"boolean" => JSON::Fuzz::Generator::PrimitiveType::Boolean,
|
11
|
+
"integer" => JSON::Fuzz::Generator::PrimitiveType::Integer,
|
12
|
+
"null" => JSON::Fuzz::Generator::PrimitiveType::Null,
|
13
|
+
"number" => JSON::Fuzz::Generator::PrimitiveType::Number,
|
14
|
+
"object" => JSON::Fuzz::Generator::PrimitiveType::Object,
|
15
|
+
"string" => JSON::Fuzz::Generator::PrimitiveType::String,
|
16
|
+
}
|
17
|
+
|
18
|
+
if generator_map.key?(type)
|
19
|
+
return generator_map[type]
|
20
|
+
else
|
21
|
+
raise "no generator for #{type}"
|
22
|
+
end
|
23
|
+
j end
|
24
|
+
|
25
|
+
def generate(schema)
|
26
|
+
schema = ::JSON::Validator.parse(open(schema).read) if schema.instance_of?(String)
|
27
|
+
generated_params = []
|
28
|
+
|
29
|
+
if type = schema["type"]
|
30
|
+
if type.instance_of?(Array) # union type
|
31
|
+
all_types.each do |target_type|
|
32
|
+
if type.include?(target_type)
|
33
|
+
generators(target_type).invalid_params(schema).each do |invalid_param|
|
34
|
+
generated_params.push(invalid_param)
|
35
|
+
end
|
36
|
+
else
|
37
|
+
generated_params.push(generators(target_type).valid_param("type" => target_type))
|
38
|
+
end
|
39
|
+
end
|
40
|
+
elsif type == "any"
|
41
|
+
# do nothing
|
42
|
+
else
|
43
|
+
generators(type).invalid_params(schema).each do |invalid_param|
|
44
|
+
generated_params.push(invalid_param)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
elsif (schema.key?("members") || schema.key?("properties"))
|
48
|
+
generators("object").invalid_params(schema).each do |invalid_param|
|
49
|
+
generated_params.push(invalid_param)
|
50
|
+
end
|
51
|
+
elsif schema.empty?
|
52
|
+
# do nothing
|
53
|
+
elsif (schema.key?("minimum") || schema.key?("maximum"))
|
54
|
+
generators("number").invalid_params(schema).each do |invalid_param|
|
55
|
+
generated_params.push(invalid_param)
|
56
|
+
end
|
57
|
+
elsif (schema.key?("minItems") || schema.key?("maxItems"))
|
58
|
+
generators("array").invalid_params(schema).each do |invalid_param|
|
59
|
+
generated_params << invalid_param
|
60
|
+
end
|
61
|
+
elsif (schema.key?("minProperties") || schema.key?("maxProperties"))
|
62
|
+
generators("object").invalid_params(schema).each do |invalid_param|
|
63
|
+
generated_params << invalid_param
|
64
|
+
end
|
65
|
+
elsif schema.key?("uniqueItems")
|
66
|
+
generators("array").invalid_params(schema).each do |invalid_param|
|
67
|
+
generated_params << invalid_param
|
68
|
+
end
|
69
|
+
elsif schema.key?("pattern")
|
70
|
+
generators("string").invalid_params(schema).each do |invalid_param|
|
71
|
+
generated_params << invalid_param
|
72
|
+
end
|
73
|
+
elsif (schema.key?("minLength") || schema.key?("maxLength"))
|
74
|
+
generators("string").invalid_params(schema).each do |invalid_param|
|
75
|
+
generated_params << invalid_param
|
76
|
+
end
|
77
|
+
elsif schema.key?("enum")
|
78
|
+
JSON::Fuzz::Generator::Keyword::Enum.invalid_params(schema).each do |invalid_param|
|
79
|
+
generated_params << invalid_param
|
80
|
+
end
|
81
|
+
elsif schema.key?("multipleOf")
|
82
|
+
generators("number").invalid_params(schema).each do |invalid_param|
|
83
|
+
generated_params << invalid_param
|
84
|
+
end
|
85
|
+
elsif schema.key?("items")
|
86
|
+
generators("array").invalid_params(schema).each do |invalid_param|
|
87
|
+
generated_params << invalid_param
|
88
|
+
end
|
89
|
+
elsif schema.key?("$ref")
|
90
|
+
raise "not impremented yet"
|
91
|
+
elsif (schema.key?("allOf") || schema.key?("anyOf") || schema.key?("oneOf"))
|
92
|
+
generators("object").invalid_params(schema).each do |invalid_param|
|
93
|
+
generated_params << invalid_param
|
94
|
+
end
|
95
|
+
elsif schema.key?("not")
|
96
|
+
JSON::Fuzz::Generator::Keyword::Not.invalid_params(schema).each do |invalid_param|
|
97
|
+
generated_params << invalid_param
|
98
|
+
end
|
99
|
+
else
|
100
|
+
raise "Not impremented generator for schema:#{schema}"
|
101
|
+
end
|
102
|
+
|
103
|
+
generated_params
|
104
|
+
end
|
105
|
+
|
106
|
+
def default_param(schema)
|
107
|
+
schema = ::JSON::Validator.parse(open(schema).read) if schema.instance_of?(String)
|
108
|
+
generated_param = nil;
|
109
|
+
|
110
|
+
if type = schema["type"]
|
111
|
+
type = type.sample if type.instance_of?(Array)
|
112
|
+
type = all_types.sample if type == "any"
|
113
|
+
generated_param = generators(type).valid_param(schema)
|
114
|
+
elsif schema.key?("properties")
|
115
|
+
generated_param = generators("object").valid_param(schema)
|
116
|
+
elsif schema.empty?
|
117
|
+
type, generator = JSON::Fuzz::Generator::PrimitiveType.type_to_class_map.to_a.sample
|
118
|
+
generated_param = generator.valid_param
|
119
|
+
elsif (schema.key?("minimum") || schema.key?("maximum"))
|
120
|
+
generated_param = generators("number").valid_param(schema)
|
121
|
+
elsif (schema.key?("minItems") || schema.key?("maxItems"))
|
122
|
+
generated_param = generators("array").valid_param(schema)
|
123
|
+
elsif (schema.key?("minProperties") || schema.key?("maxProperties"))
|
124
|
+
generated_param = generators("object").valid_param(schema)
|
125
|
+
elsif schema.key?("uniqueItems")
|
126
|
+
generated_param = generators("array").valid_param(schema)
|
127
|
+
elsif schema.key?("pattern")
|
128
|
+
generated_param = generators("string").valid_param(schema)
|
129
|
+
elsif (schema.key?("minLength") || schema.key?("maxLength"))
|
130
|
+
generated_param = generators("string").valid_param(schema)
|
131
|
+
elsif schema.key?("enum")
|
132
|
+
generated_param = JSON::Fuzz::Generator::Keyword::Enum.valid_param(schema)
|
133
|
+
elsif schema.key?("multipleOf")
|
134
|
+
generated_param = generators("number").valid_param(schema)
|
135
|
+
elsif schema.key?("items")
|
136
|
+
generated_param = generators("array").valid_param(schema)
|
137
|
+
elsif schema.key?("$ref")
|
138
|
+
raise "not impremented yet"
|
139
|
+
elsif schema.key?("allOf")
|
140
|
+
generated_param = JSON::Fuzz::Generator::Keyword::AllOf.valid_param(schema)
|
141
|
+
elsif schema.key?("anyOf")
|
142
|
+
generated_param = JSON::Fuzz::Generator::Keyword::AnyOf.valid_param(schema)
|
143
|
+
elsif schema.key?("oneOf")
|
144
|
+
generated_param = JSON::Fuzz::Generator::Keyword::OneOf.valid_param(schema)
|
145
|
+
elsif schema.key?("not")
|
146
|
+
generated_param = JSON::Fuzz::Generator::Keyword::Not.valid_param(schema)
|
147
|
+
else
|
148
|
+
raise "Not impremented generator for schema:#{schema}"
|
149
|
+
end
|
150
|
+
|
151
|
+
generated_param
|
152
|
+
end
|
153
|
+
|
154
|
+
private
|
155
|
+
def all_types
|
156
|
+
%w[array boolean integer null number object string]
|
157
|
+
end
|
158
|
+
end
|
159
|
+
end
|
160
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
module JSON
|
2
|
+
module Fuzz
|
3
|
+
module Generator
|
4
|
+
class Keyword
|
5
|
+
class AdditionalProperties
|
6
|
+
class << self
|
7
|
+
def invalid_params(attributes)
|
8
|
+
attributes = Marshal.load(Marshal.dump(attributes))
|
9
|
+
additional_properties = attributes.delete("additionalProperties")
|
10
|
+
raise "No additionalProperties keyword given: #{attributes}" if additional_properties.nil?
|
11
|
+
|
12
|
+
template = JSON::Fuzz::Generator.default_param(attributes)
|
13
|
+
|
14
|
+
additional_key = nil
|
15
|
+
until (additional_key)
|
16
|
+
key = /\w+/.gen
|
17
|
+
additional_key = key unless template.key?(key)
|
18
|
+
end
|
19
|
+
|
20
|
+
if additional_properties
|
21
|
+
additional_param = JSON::Fuzz::Generator.generate(additional_properties).sample
|
22
|
+
template[additional_key] = additional_param
|
23
|
+
else
|
24
|
+
template[additional_key] = template[template.keys.sample]
|
25
|
+
end
|
26
|
+
|
27
|
+
[template]
|
28
|
+
end
|
29
|
+
|
30
|
+
def valid_param(attributes)
|
31
|
+
attributes = Marshal.load(Marshal.dump(attributes))
|
32
|
+
additional_properties = attributes.delete("additionalProperties")
|
33
|
+
raise "No additionalProperties keyword given: #{attributes}" if additional_properties.nil?
|
34
|
+
|
35
|
+
template = JSON::Fuzz::Generator.default_param(attributes)
|
36
|
+
|
37
|
+
if additional_properties
|
38
|
+
additional_param = nil
|
39
|
+
if additional_properties.instance_of?(Hash)
|
40
|
+
additional_param = JSON::Fuzz::Generator.default_param(additional_properties)
|
41
|
+
else
|
42
|
+
additional_param = template[template.keys.sample]
|
43
|
+
end
|
44
|
+
|
45
|
+
additional_key = nil
|
46
|
+
until (additional_key)
|
47
|
+
key = /\w+/.gen
|
48
|
+
additional_key = key unless template.key?(key)
|
49
|
+
end
|
50
|
+
|
51
|
+
template[additional_key] = additional_param
|
52
|
+
end
|
53
|
+
|
54
|
+
template
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|