string_pattern 2.1.4 → 2.2.3
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 +4 -4
- data/README.md +2 -0
- data/lib/string/pattern/add_to_ruby.rb +74 -65
- data/lib/string/pattern/analyze.rb +195 -0
- data/lib/string/pattern/generate.rb +579 -0
- data/lib/string/pattern/validate.rb +220 -0
- data/lib/string_pattern.rb +14 -987
- metadata +12 -10
@@ -0,0 +1,579 @@
|
|
1
|
+
class StringPattern
|
2
|
+
###############################################
|
3
|
+
# Generate a random string based on the pattern supplied
|
4
|
+
# (if SP_ADD_TO_RUBY==true, by default is true) To simplify its use it is part of the String, Array, Symbol and Kernel Ruby so can be easily used also like this:
|
5
|
+
# "10-15:Ln/x/".generate #generate method on String class (alias: gen)
|
6
|
+
# ['(', :'3:N', ')', :'6-8:N'].generate #generate method on Array class (alias: gen)
|
7
|
+
# generate("10-15:Ln/x/") #generate Ruby Kernel method
|
8
|
+
# generate(['(', :'3:N', ')', :'6-8:N']) #generate Ruby Kernel method
|
9
|
+
# "(,3:N,) ,3:N,-,2:N,-,2:N".split(",").generate #>(937) #generate method on Array class (alias: gen)
|
10
|
+
# %w{( 3:N ) 1:_ 3:N - 2:N - 2:N}.gen #generate method on Array class, using alias gen method
|
11
|
+
# Input:
|
12
|
+
# pattern: array or string of different patterns. A pattern is a string with this info:
|
13
|
+
# "length:symbol_type" or "min_length-max_length:symbol_type"
|
14
|
+
# In case an array supplied, the positions using a string pattern should be supplied as symbols if StringPattern.optimistic==false
|
15
|
+
#
|
16
|
+
# These are the possible string patterns you will be able to supply:
|
17
|
+
# If at the beginning we supply the character ! the resulting string won't fulfill the pattern. This character need to be the first character of the pattern.
|
18
|
+
# min_length -- minimum length of the string
|
19
|
+
# max_length (optional) -- maximum length of the string. If not provided the result will be with the min_length provided
|
20
|
+
# symbol_type -- the type of the string we want.
|
21
|
+
# you can use a combination of any ot these:
|
22
|
+
# x for alpha in lowercase
|
23
|
+
# X for alpha in capital letters
|
24
|
+
# L for all kind of alpha in capital and lower letters
|
25
|
+
# T for the national characters defined on StringPattern.national_chars
|
26
|
+
# n for number
|
27
|
+
# $ for special characters (includes space)
|
28
|
+
# _ for space
|
29
|
+
# * all characters
|
30
|
+
# [characters] the characters we want. If we want to add also the ] character you have to write: ]]. If we want to add also the % character you have to write: %%
|
31
|
+
# %characters% the characters we don't want on the resulting string. %% to exclude the character %
|
32
|
+
# /symbols or characters/ If we want these characters to be included on the resulting string. If we want to add also the / character you have to write: //
|
33
|
+
# We can supply 0 to allow empty strings, this character need to be at the beginning
|
34
|
+
# If you want to include the character " use \"
|
35
|
+
# If you want to include the character \ use \\
|
36
|
+
# If you want to include the character [ use \[
|
37
|
+
# Other uses:
|
38
|
+
# @ for email
|
39
|
+
# W for English words, capital and lower
|
40
|
+
# w for English words only lower and words separated by underscore
|
41
|
+
# P for Spanish words, capital and lower
|
42
|
+
# p for Spanish words only lower and words separated by underscore
|
43
|
+
# Examples:
|
44
|
+
# [:"6:X", :"3-8:_N"]
|
45
|
+
# # it will return a string starting with 6 capital letters and then a string containing numbers and space from 3 to 8 characters, for example: "LDJKKD34 555"
|
46
|
+
# [:"6-15:L_N", "fixed text", :"3:N"]
|
47
|
+
# # it will return a string of 6-15 characters containing Letters-spaces-numbers, then the text: 'fixed text' and at the end a string of 3 characters containing numbers, for example: ["L_N",6,15],"fixed text",["N",3] "3 Am399 afixed text882"
|
48
|
+
# "10-20:LN[=#]"
|
49
|
+
# # it will return a string of 10-20 characters containing Letters and/or numbers and/or the characters = and #, for example: eiyweQFWeL#do4Vl
|
50
|
+
# "30:TN_[#=]/x/"
|
51
|
+
# # it will return a string of 30 characters containing national characters defined on StringPattern.national_chars and/or numbers and/or spaces and/or the characters # = and it is necessary the resultant string includes lower alpha chars. For example: HaEdQTzJ3=OtXMh1mAPqv7NCy=upLy
|
52
|
+
# "10:N[%0%]"
|
53
|
+
# # 10 characters length containing numbers and excluding the character 0, for example: 3523497757
|
54
|
+
# "10:N[%0%/AB/]"
|
55
|
+
# # 10 characters length containing numbers and excluding the character 0 and necessary to contain the characters A B, for example: 3AA4AA57BB
|
56
|
+
# "!10:N[%0%/AB/]"
|
57
|
+
# # it will generate a string that doesn't fulfill the pattern supplied, examples:
|
58
|
+
# # a6oMQ4JK9g
|
59
|
+
# # /Y<N6Aa[ae
|
60
|
+
# # 3444439A34B32
|
61
|
+
# "10:N[%0%/AB/]", errors: [:length]
|
62
|
+
# # it will generate a string following the pattern and with the errors supplied, in this case, length, example: AB44
|
63
|
+
# Output:
|
64
|
+
# the generated string
|
65
|
+
###############################################
|
66
|
+
def StringPattern.generate(pattern, expected_errors: [], **synonyms)
|
67
|
+
tries = 0
|
68
|
+
begin
|
69
|
+
good_result = true
|
70
|
+
tries += 1
|
71
|
+
string = ""
|
72
|
+
|
73
|
+
expected_errors = synonyms[:errors] if synonyms.keys.include?(:errors)
|
74
|
+
|
75
|
+
if expected_errors.kind_of?(Symbol)
|
76
|
+
expected_errors = [expected_errors]
|
77
|
+
end
|
78
|
+
|
79
|
+
if pattern.kind_of?(Array)
|
80
|
+
pattern.each { |pat|
|
81
|
+
if pat.kind_of?(Array) # for the case it is one of the values
|
82
|
+
pat = pat.sample
|
83
|
+
end
|
84
|
+
|
85
|
+
if pat.kind_of?(Symbol)
|
86
|
+
if pat.to_s.scan(/^!?\d+-?\d*:.+/).size > 0
|
87
|
+
string << StringPattern.generate(pat.to_s, expected_errors: expected_errors)
|
88
|
+
else
|
89
|
+
string << pat.to_s
|
90
|
+
end
|
91
|
+
elsif pat.kind_of?(String)
|
92
|
+
if @optimistic and pat.to_s.scan(/^!?\d+-?\d*:.+/).size > 0
|
93
|
+
string << StringPattern.generate(pat.to_s, expected_errors: expected_errors)
|
94
|
+
else
|
95
|
+
string << pat
|
96
|
+
end
|
97
|
+
else
|
98
|
+
puts "StringPattern.generate: it seems you supplied wrong array of patterns: #{pattern.inspect}, expected_errors: #{expected_errors.inspect}"
|
99
|
+
return ""
|
100
|
+
end
|
101
|
+
}
|
102
|
+
return string
|
103
|
+
elsif pattern.kind_of?(String) or pattern.kind_of?(Symbol)
|
104
|
+
patt = StringPattern.analyze(pattern).clone
|
105
|
+
return "" unless patt.kind_of?(Struct)
|
106
|
+
|
107
|
+
min_length = patt.min_length.clone
|
108
|
+
max_length = patt.max_length.clone
|
109
|
+
symbol_type = patt.symbol_type.clone
|
110
|
+
|
111
|
+
required_data = patt.required_data.clone
|
112
|
+
excluded_data = patt.excluded_data.clone
|
113
|
+
string_set = patt.string_set.clone
|
114
|
+
all_characters_set = patt.all_characters_set.clone
|
115
|
+
|
116
|
+
required_chars = Array.new
|
117
|
+
unless required_data.size == 0
|
118
|
+
required_data.each { |rd|
|
119
|
+
required_chars << rd if rd.size == 1
|
120
|
+
}
|
121
|
+
unless excluded_data.size == 0
|
122
|
+
if (required_chars.flatten & excluded_data.flatten).size > 0
|
123
|
+
puts "pattern argument not valid on StringPattern.generate, a character cannot be required and excluded at the same time: #{pattern.inspect}, expected_errors: #{expected_errors.inspect}"
|
124
|
+
return ""
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
string_set_not_allowed = Array.new
|
130
|
+
elsif pattern.kind_of?(Regexp)
|
131
|
+
return generate(pattern.to_sp, expected_errors: expected_errors)
|
132
|
+
else
|
133
|
+
puts "pattern argument not valid on StringPattern.generate: #{pattern.inspect}, expected_errors: #{expected_errors.inspect}"
|
134
|
+
return pattern.to_s
|
135
|
+
end
|
136
|
+
|
137
|
+
allow_empty = false
|
138
|
+
deny_pattern = false
|
139
|
+
if symbol_type[0..0] == "!"
|
140
|
+
deny_pattern = true
|
141
|
+
possible_errors = [:length, :value, :string_set_not_allowed]
|
142
|
+
(rand(possible_errors.size) + 1).times {
|
143
|
+
expected_errors << possible_errors.sample
|
144
|
+
}
|
145
|
+
expected_errors.uniq!
|
146
|
+
if symbol_type[1..1] == "0"
|
147
|
+
allow_empty = true
|
148
|
+
end
|
149
|
+
elsif symbol_type[0..0] == "0"
|
150
|
+
allow_empty = true
|
151
|
+
end
|
152
|
+
|
153
|
+
if expected_errors.include?(:min_length) or expected_errors.include?(:length) or
|
154
|
+
expected_errors.include?(:max_length)
|
155
|
+
allow_empty = !allow_empty
|
156
|
+
elsif expected_errors.include?(:value) or
|
157
|
+
expected_errors.include?(:excluded_data) or
|
158
|
+
expected_errors.include?(:required_data) or
|
159
|
+
expected_errors.include?(:string_set_not_allowed) and allow_empty
|
160
|
+
allow_empty = false
|
161
|
+
end
|
162
|
+
|
163
|
+
length = min_length
|
164
|
+
symbol_type_orig = symbol_type
|
165
|
+
|
166
|
+
expected_errors_left = expected_errors.dup
|
167
|
+
|
168
|
+
symbol_type = symbol_type_orig
|
169
|
+
|
170
|
+
unless deny_pattern
|
171
|
+
if required_data.size == 0 and expected_errors_left.include?(:required_data)
|
172
|
+
puts "required data not supplied on pattern so it won't be possible to generate a wrong string. StringPattern.generate: #{pattern.inspect}, expected_errors: #{expected_errors.inspect}"
|
173
|
+
return ""
|
174
|
+
end
|
175
|
+
|
176
|
+
if excluded_data.size == 0 and expected_errors_left.include?(:excluded_data)
|
177
|
+
puts "excluded data not supplied on pattern so it won't be possible to generate a wrong string. StringPattern.generate: #{pattern.inspect}, expected_errors: #{expected_errors.inspect}"
|
178
|
+
return ""
|
179
|
+
end
|
180
|
+
|
181
|
+
if expected_errors_left.include?(:string_set_not_allowed)
|
182
|
+
string_set_not_allowed = all_characters_set - string_set
|
183
|
+
|
184
|
+
if string_set_not_allowed.size == 0
|
185
|
+
puts "all characters are allowed so it won't be possible to generate a wrong string. StringPattern.generate: #{pattern.inspect}, expected_errors: #{expected_errors.inspect}"
|
186
|
+
return ""
|
187
|
+
end
|
188
|
+
end
|
189
|
+
end
|
190
|
+
|
191
|
+
if expected_errors_left.include?(:min_length) or
|
192
|
+
expected_errors_left.include?(:max_length) or
|
193
|
+
expected_errors_left.include?(:length)
|
194
|
+
if expected_errors_left.include?(:min_length) or
|
195
|
+
(min_length > 0 and expected_errors_left.include?(:length) and rand(2) == 0)
|
196
|
+
if min_length > 0
|
197
|
+
if allow_empty
|
198
|
+
length = rand(min_length).to_i
|
199
|
+
else
|
200
|
+
length = rand(min_length - 1).to_i + 1
|
201
|
+
end
|
202
|
+
if required_data.size > length and required_data.size < min_length
|
203
|
+
length = required_data.size
|
204
|
+
end
|
205
|
+
expected_errors_left.delete(:length)
|
206
|
+
expected_errors_left.delete(:min_length)
|
207
|
+
else
|
208
|
+
puts "min_length is 0 so it won't be possible to generate a wrong string smaller than 0 characters. StringPattern.generate: #{pattern.inspect}, expected_errors: #{expected_errors.inspect}"
|
209
|
+
return ""
|
210
|
+
end
|
211
|
+
elsif expected_errors_left.include?(:max_length) or expected_errors_left.include?(:length)
|
212
|
+
length = max_length + 1 + rand(max_length).to_i
|
213
|
+
expected_errors_left.delete(:length)
|
214
|
+
expected_errors_left.delete(:max_length)
|
215
|
+
end
|
216
|
+
else
|
217
|
+
if allow_empty and rand(7) == 1
|
218
|
+
length = 0
|
219
|
+
else
|
220
|
+
if max_length == min_length
|
221
|
+
length = min_length
|
222
|
+
else
|
223
|
+
length = min_length + rand(max_length - min_length + 1)
|
224
|
+
end
|
225
|
+
end
|
226
|
+
end
|
227
|
+
|
228
|
+
if deny_pattern
|
229
|
+
if required_data.size == 0 and expected_errors_left.include?(:required_data)
|
230
|
+
expected_errors_left.delete(:required_data)
|
231
|
+
end
|
232
|
+
|
233
|
+
if excluded_data.size == 0 and expected_errors_left.include?(:excluded_data)
|
234
|
+
expected_errors_left.delete(:excluded_data)
|
235
|
+
end
|
236
|
+
|
237
|
+
if expected_errors_left.include?(:string_set_not_allowed)
|
238
|
+
string_set_not_allowed = all_characters_set - string_set
|
239
|
+
if string_set_not_allowed.size == 0
|
240
|
+
expected_errors_left.delete(:string_set_not_allowed)
|
241
|
+
end
|
242
|
+
end
|
243
|
+
|
244
|
+
if symbol_type == "!@" and expected_errors_left.size == 0 and !expected_errors.include?(:length) and
|
245
|
+
(expected_errors.include?(:required_data) or expected_errors.include?(:excluded_data))
|
246
|
+
expected_errors_left.push(:value)
|
247
|
+
end
|
248
|
+
end
|
249
|
+
|
250
|
+
string = ""
|
251
|
+
if symbol_type != "@" and symbol_type != "!@" and length != 0 and string_set.size != 0
|
252
|
+
if string_set.size != 0
|
253
|
+
1.upto(length) { |i|
|
254
|
+
string << string_set.sample.to_s
|
255
|
+
}
|
256
|
+
end
|
257
|
+
if required_data.size > 0
|
258
|
+
positions_to_set = (0..(string.size - 1)).to_a
|
259
|
+
required_data.each { |rd|
|
260
|
+
if (string.chars & rd).size > 0
|
261
|
+
rd_to_set = (string.chars & rd).sample
|
262
|
+
else
|
263
|
+
rd_to_set = rd.sample
|
264
|
+
end
|
265
|
+
if ((0...string.length).find_all { |i| string[i, 1] == rd_to_set }).size == 0
|
266
|
+
if positions_to_set.size == 0
|
267
|
+
puts "pattern not valid on StringPattern.generate, not possible to generate a valid string: #{pattern.inspect}, expected_errors: #{expected_errors.inspect}"
|
268
|
+
return ""
|
269
|
+
else
|
270
|
+
k = positions_to_set.sample
|
271
|
+
string[k] = rd_to_set
|
272
|
+
positions_to_set.delete(k)
|
273
|
+
end
|
274
|
+
else
|
275
|
+
k = ((0...string.length).find_all { |i| string[i, 1] == rd_to_set }).sample
|
276
|
+
positions_to_set.delete(k)
|
277
|
+
end
|
278
|
+
}
|
279
|
+
end
|
280
|
+
excluded_data.each { |ed|
|
281
|
+
if (string.chars & ed).size > 0
|
282
|
+
(string.chars & ed).each { |s|
|
283
|
+
string.gsub!(s, string_set.sample)
|
284
|
+
}
|
285
|
+
end
|
286
|
+
}
|
287
|
+
|
288
|
+
if expected_errors_left.include?(:value)
|
289
|
+
string_set_not_allowed = all_characters_set - string_set if string_set_not_allowed.size == 0
|
290
|
+
|
291
|
+
if string_set_not_allowed.size == 0
|
292
|
+
puts "Not possible to generate a non valid string on StringPattern.generate: #{pattern.inspect}, expected_errors: #{expected_errors.inspect}"
|
293
|
+
return ""
|
294
|
+
end
|
295
|
+
(rand(string.size) + 1).times {
|
296
|
+
string[rand(string.size)] = (all_characters_set - string_set).sample
|
297
|
+
}
|
298
|
+
expected_errors_left.delete(:value)
|
299
|
+
end
|
300
|
+
|
301
|
+
if expected_errors_left.include?(:required_data) and required_data.size > 0
|
302
|
+
(rand(required_data.size) + 1).times {
|
303
|
+
chars_to_remove = required_data.sample
|
304
|
+
chars_to_remove.each { |char_to_remove|
|
305
|
+
string.gsub!(char_to_remove, (string_set - chars_to_remove).sample)
|
306
|
+
}
|
307
|
+
}
|
308
|
+
expected_errors_left.delete(:required_data)
|
309
|
+
end
|
310
|
+
|
311
|
+
if expected_errors_left.include?(:excluded_data) and excluded_data.size > 0
|
312
|
+
(rand(string.size) + 1).times {
|
313
|
+
string[rand(string.size)] = excluded_data.sample.sample
|
314
|
+
}
|
315
|
+
expected_errors_left.delete(:excluded_data)
|
316
|
+
end
|
317
|
+
|
318
|
+
if expected_errors_left.include?(:string_set_not_allowed)
|
319
|
+
string_set_not_allowed = all_characters_set - string_set if string_set_not_allowed.size == 0
|
320
|
+
if string_set_not_allowed.size > 0
|
321
|
+
(rand(string.size) + 1).times {
|
322
|
+
string[rand(string.size)] = string_set_not_allowed.sample
|
323
|
+
}
|
324
|
+
expected_errors_left.delete(:string_set_not_allowed)
|
325
|
+
end
|
326
|
+
end
|
327
|
+
elsif (symbol_type == "W" or symbol_type == "P" or symbol_type == "w" or symbol_type == "p") and length > 0
|
328
|
+
words = []
|
329
|
+
words_short = []
|
330
|
+
if symbol_type == "W"
|
331
|
+
if @words_camel.empty?
|
332
|
+
require "pathname"
|
333
|
+
require "json"
|
334
|
+
filename = File.join Pathname(File.dirname(__FILE__)), "../../../data", "english/nouns.json"
|
335
|
+
nouns = JSON.parse(File.read(filename))
|
336
|
+
filename = File.join Pathname(File.dirname(__FILE__)), "../../../data", "english/adjs.json"
|
337
|
+
adjs = JSON.parse(File.read(filename))
|
338
|
+
nouns = nouns.map(&:to_camel_case)
|
339
|
+
adjs = adjs.map(&:to_camel_case)
|
340
|
+
@words_camel = adjs + nouns
|
341
|
+
@words_camel_short = @words_camel.sample(2000)
|
342
|
+
end
|
343
|
+
words = @words_camel
|
344
|
+
words_short = @words_camel_short
|
345
|
+
elsif symbol_type == "w"
|
346
|
+
if @words.empty?
|
347
|
+
require "pathname"
|
348
|
+
require "json"
|
349
|
+
filename = File.join Pathname(File.dirname(__FILE__)), "../../../data", "english/nouns.json"
|
350
|
+
nouns = JSON.parse(File.read(filename))
|
351
|
+
filename = File.join Pathname(File.dirname(__FILE__)), "../../../data", "english/adjs.json"
|
352
|
+
adjs = JSON.parse(File.read(filename))
|
353
|
+
@words = adjs + nouns
|
354
|
+
@words_short = @words.sample(2000)
|
355
|
+
end
|
356
|
+
words = @words
|
357
|
+
words_short = @words_short
|
358
|
+
elsif symbol_type == "P"
|
359
|
+
if @palabras_camel.empty?
|
360
|
+
require "pathname"
|
361
|
+
require "json"
|
362
|
+
filename = File.join Pathname(File.dirname(__FILE__)), "../../../data", "spanish/palabras#{rand(12)}.json"
|
363
|
+
palabras = JSON.parse(File.read(filename))
|
364
|
+
palabras = palabras.map(&:to_camel_case)
|
365
|
+
@palabras_camel = palabras
|
366
|
+
@palabras_camel_short = @palabras_camel.sample(2000)
|
367
|
+
end
|
368
|
+
words = @palabras_camel
|
369
|
+
words_short = @palabras_camel_short
|
370
|
+
elsif symbol_type == "p"
|
371
|
+
if @palabras.empty?
|
372
|
+
require "pathname"
|
373
|
+
require "json"
|
374
|
+
filename = File.join Pathname(File.dirname(__FILE__)), "../../../data", "spanish/palabras#{rand(12)}.json"
|
375
|
+
palabras = JSON.parse(File.read(filename))
|
376
|
+
@palabras = palabras
|
377
|
+
@palabras_short = @palabras.sample(2000)
|
378
|
+
end
|
379
|
+
words = @palabras
|
380
|
+
words_short = @palabras_short
|
381
|
+
end
|
382
|
+
|
383
|
+
wordr = ""
|
384
|
+
wordr_array = []
|
385
|
+
tries = 0
|
386
|
+
while wordr.length < min_length
|
387
|
+
tries += 1
|
388
|
+
length = max_length - wordr.length
|
389
|
+
if tries > 1000
|
390
|
+
wordr += "A" * length
|
391
|
+
break
|
392
|
+
end
|
393
|
+
if symbol_type == "w" or symbol_type == "p"
|
394
|
+
length = length - 1 if wordr_array.size > 0
|
395
|
+
res = (words_short.select { |word| word.length <= length && word.length != length - 1 && word.length != length - 2 && word.length != length - 3 }).sample.to_s
|
396
|
+
unless res.to_s == ""
|
397
|
+
wordr_array << res
|
398
|
+
wordr = wordr_array.join(@word_separator)
|
399
|
+
end
|
400
|
+
else
|
401
|
+
wordr += (words_short.select { |word| word.length <= length && word.length != length - 1 && word.length != length - 2 && word.length != length - 3 }).sample.to_s
|
402
|
+
end
|
403
|
+
if (tries % 100) == 0
|
404
|
+
words_short = words.sample(2000)
|
405
|
+
end
|
406
|
+
end
|
407
|
+
good_result = true
|
408
|
+
string = wordr
|
409
|
+
elsif (symbol_type == "@" or symbol_type == "!@") and length > 0
|
410
|
+
if min_length > 6 and length < 6
|
411
|
+
length = 6
|
412
|
+
end
|
413
|
+
if deny_pattern and
|
414
|
+
(expected_errors.include?(:required_data) or expected_errors.include?(:excluded_data) or
|
415
|
+
expected_errors.include?(:string_set_not_allowed))
|
416
|
+
expected_errors_left.push(:value)
|
417
|
+
expected_errors.push(:value)
|
418
|
+
expected_errors.uniq!
|
419
|
+
expected_errors_left.uniq!
|
420
|
+
end
|
421
|
+
|
422
|
+
expected_errors_left_orig = expected_errors_left.dup
|
423
|
+
tries = 0
|
424
|
+
|
425
|
+
begin
|
426
|
+
expected_errors_left = expected_errors_left_orig.dup
|
427
|
+
tries += 1
|
428
|
+
string = ""
|
429
|
+
alpha_set = ALPHA_SET_LOWER.clone + ALPHA_SET_CAPITAL.clone
|
430
|
+
string_set = alpha_set + NUMBER_SET.clone + ["."] + ["_"] + ["-"]
|
431
|
+
string_set_not_allowed = all_characters_set - string_set
|
432
|
+
|
433
|
+
extension = "."
|
434
|
+
at_sign = "@"
|
435
|
+
|
436
|
+
if expected_errors_left.include?(:value)
|
437
|
+
if rand(2) == 1
|
438
|
+
extension = (all_characters_set - ["."]).sample.dup
|
439
|
+
expected_errors_left.delete(:value)
|
440
|
+
expected_errors_left.delete(:required_data)
|
441
|
+
end
|
442
|
+
|
443
|
+
if rand(2) == 1
|
444
|
+
1.upto(rand(7)) { |i|
|
445
|
+
extension << alpha_set.sample.downcase
|
446
|
+
}
|
447
|
+
|
448
|
+
(rand(extension.size) + 1).times {
|
449
|
+
extension[rand(extension.size)] = (string_set - alpha_set - ["."]).sample
|
450
|
+
}
|
451
|
+
|
452
|
+
expected_errors_left.delete(:value)
|
453
|
+
else
|
454
|
+
1.upto(rand(3) + 2) { |i|
|
455
|
+
extension << alpha_set.sample.downcase
|
456
|
+
}
|
457
|
+
end
|
458
|
+
|
459
|
+
if rand(2) == 1
|
460
|
+
at_sign = (string_set - ["@"]).sample.dup
|
461
|
+
expected_errors_left.delete(:value)
|
462
|
+
expected_errors_left.delete(:required_data)
|
463
|
+
end
|
464
|
+
else
|
465
|
+
if length > 6
|
466
|
+
1.upto(rand(3) + 2) { |i|
|
467
|
+
extension << alpha_set.sample.downcase
|
468
|
+
}
|
469
|
+
else
|
470
|
+
1.upto(2) { |i|
|
471
|
+
extension << alpha_set.sample.downcase
|
472
|
+
}
|
473
|
+
end
|
474
|
+
end
|
475
|
+
length_e = length - extension.size - 1
|
476
|
+
length1 = rand(length_e - 1) + 1
|
477
|
+
length2 = length_e - length1
|
478
|
+
1.upto(length1) { |i| string << string_set.sample }
|
479
|
+
|
480
|
+
string << at_sign
|
481
|
+
|
482
|
+
domain = ""
|
483
|
+
domain_set = alpha_set + NUMBER_SET.clone + ["."] + ["-"]
|
484
|
+
1.upto(length2) { |i|
|
485
|
+
domain << domain_set.sample.downcase
|
486
|
+
}
|
487
|
+
|
488
|
+
if expected_errors.include?(:value) and rand(2) == 1 and domain.size > 0
|
489
|
+
(rand(domain.size) + 1).times {
|
490
|
+
domain[rand(domain.size)] = (all_characters_set - domain_set).sample
|
491
|
+
}
|
492
|
+
expected_errors_left.delete(:value)
|
493
|
+
end
|
494
|
+
|
495
|
+
string << domain << extension
|
496
|
+
|
497
|
+
if expected_errors_left.include?(:value) or expected_errors_left.include?(:string_set_not_allowed)
|
498
|
+
(rand(string.size) + 1).times {
|
499
|
+
string[rand(string.size)] = string_set_not_allowed.sample
|
500
|
+
}
|
501
|
+
expected_errors_left.delete(:value)
|
502
|
+
expected_errors_left.delete(:string_set_not_allowed)
|
503
|
+
end
|
504
|
+
|
505
|
+
error_regular_expression = false
|
506
|
+
|
507
|
+
if deny_pattern and expected_errors.include?(:length)
|
508
|
+
good_result = true #it is already with wrong length
|
509
|
+
else
|
510
|
+
# I'm doing this because many times the regular expression checking hangs with these characters
|
511
|
+
wrong = %w(.. __ -- ._ _. .- -. _- -_ @. @_ @- .@ _@ -@ @@)
|
512
|
+
if !(Regexp.union(*wrong) === string) #don't include any or the wrong strings
|
513
|
+
if string.index("@").to_i > 0 and
|
514
|
+
string[0..(string.index("@") - 1)].scan(/([a-z0-9]+([\+\._\-][a-z0-9]|)*)/i).join == string[0..(string.index("@") - 1)] and
|
515
|
+
string[(string.index("@") + 1)..-1].scan(/([0-9a-z]+([\.-][a-z0-9]|)*)/i).join == string[string[(string.index("@") + 1)..-1]]
|
516
|
+
error_regular_expression = false
|
517
|
+
else
|
518
|
+
error_regular_expression = true
|
519
|
+
end
|
520
|
+
else
|
521
|
+
error_regular_expression = true
|
522
|
+
end
|
523
|
+
|
524
|
+
if expected_errors.size == 0
|
525
|
+
if error_regular_expression
|
526
|
+
good_result = false
|
527
|
+
else
|
528
|
+
good_result = true
|
529
|
+
end
|
530
|
+
elsif expected_errors_left.size == 0 and
|
531
|
+
(expected_errors - [:length, :min_length, :max_length]).size == 0
|
532
|
+
good_result = true
|
533
|
+
elsif expected_errors != [:length]
|
534
|
+
if !error_regular_expression
|
535
|
+
good_result = false
|
536
|
+
elsif expected_errors.include?(:value)
|
537
|
+
good_result = true
|
538
|
+
end
|
539
|
+
end
|
540
|
+
end
|
541
|
+
end until good_result or tries > 100
|
542
|
+
unless good_result
|
543
|
+
puts "Not possible to generate an email on StringPattern.generate: #{pattern.inspect}, expected_errors: #{expected_errors.inspect}"
|
544
|
+
return ""
|
545
|
+
end
|
546
|
+
end
|
547
|
+
if @dont_repeat
|
548
|
+
if @cache_values[pattern.to_s].nil?
|
549
|
+
@cache_values[pattern.to_s] = Array.new()
|
550
|
+
@cache_values[pattern.to_s].push(string)
|
551
|
+
good_result = true
|
552
|
+
elsif @cache_values[pattern.to_s].include?(string)
|
553
|
+
good_result = false
|
554
|
+
else
|
555
|
+
@cache_values[pattern.to_s].push(string)
|
556
|
+
good_result = true
|
557
|
+
end
|
558
|
+
end
|
559
|
+
if pattern.kind_of?(Symbol) and patt.unique
|
560
|
+
if @cache_values[pattern.__id__].nil?
|
561
|
+
@cache_values[pattern.__id__] = Array.new()
|
562
|
+
@cache_values[pattern.__id__].push(string)
|
563
|
+
good_result = true
|
564
|
+
elsif @cache_values[pattern.__id__].include?(string)
|
565
|
+
good_result = false
|
566
|
+
else
|
567
|
+
@cache_values[pattern.__id__].push(string)
|
568
|
+
good_result = true
|
569
|
+
end
|
570
|
+
end
|
571
|
+
end until good_result or tries > 10000
|
572
|
+
unless good_result
|
573
|
+
puts "Not possible to generate the string on StringPattern.generate: #{pattern.inspect}, expected_errors: #{expected_errors.inspect}"
|
574
|
+
puts "Take in consideration if you are using StringPattern.dont_repeat=true that you don't try to generate more strings that are possible to be generated"
|
575
|
+
return ""
|
576
|
+
end
|
577
|
+
return string
|
578
|
+
end
|
579
|
+
end
|