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