forgery 0.4.3 → 0.8.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 (56) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +6 -0
  3. data/.travis.yml +12 -0
  4. data/Gemfile +9 -0
  5. data/Gemfile.lock +35 -0
  6. data/LICENSE +1 -1
  7. data/README.markdown +196 -60
  8. data/Rakefile +10 -54
  9. data/forgery.gemspec +23 -0
  10. data/lib/forgery.rb +0 -1
  11. data/lib/forgery/dictionaries/bics +7 -0
  12. data/lib/forgery/dictionaries/company_names +0 -1
  13. data/lib/forgery/dictionaries/currency_descriptions +2 -2
  14. data/lib/forgery/dictionaries/ibans +61 -0
  15. data/lib/forgery/dictionaries/job_titles +1 -1
  16. data/lib/forgery/dictionaries/zones +1 -2
  17. data/lib/forgery/extend.rb +0 -2
  18. data/lib/forgery/extensions/range.rb +1 -1
  19. data/lib/forgery/file_reader.rb +2 -1
  20. data/lib/forgery/forgery/bank_account.rb +25 -0
  21. data/lib/forgery/forgery/basic.rb +1 -1
  22. data/lib/forgery/forgery/credit_card.rb +71 -0
  23. data/lib/forgery/forgery/geo.rb +54 -0
  24. data/lib/forgery/forgery/internet.rb +7 -0
  25. data/lib/forgery/forgery/lorem_ipsum.rb +4 -4
  26. data/lib/forgery/forgery/russian_tax.rb +57 -0
  27. data/lib/forgery/forgery_railtie.rb +0 -29
  28. data/lib/forgery/formats/phone +1 -1
  29. data/lib/forgery/version.rb +3 -1
  30. data/spec/data/dictionaries/code_names +6 -0
  31. data/spec/data/dictionaries/female_first_names +1 -0
  32. data/spec/data/documents/mock_web_page.html +17 -0
  33. data/spec/data/documents/mock_xml_doc.xml +5 -0
  34. data/spec/dictionaries_spec.rb +35 -0
  35. data/spec/extensions/array_spec.rb +25 -0
  36. data/spec/extensions/range_spec.rb +33 -0
  37. data/spec/extensions/string_spec.rb +29 -0
  38. data/spec/file_reader_spec.rb +32 -0
  39. data/spec/forgery/address_spec.rb +84 -0
  40. data/spec/forgery/bank_account_spec.rb +16 -0
  41. data/spec/forgery/basic_spec.rb +179 -0
  42. data/spec/forgery/credit_card_spec.rb +68 -0
  43. data/spec/forgery/currency_spec.rb +15 -0
  44. data/spec/forgery/date_spec.rb +134 -0
  45. data/spec/forgery/internet_spec.rb +62 -0
  46. data/spec/forgery/lorem_ipsum_spec.rb +132 -0
  47. data/spec/forgery/monetary_spec.rb +14 -0
  48. data/spec/forgery/name_spec.rb +11 -0
  49. data/spec/forgery/personal_spec.rb +15 -0
  50. data/spec/forgery/russian_tax_spec.rb +81 -0
  51. data/spec/forgery/time_spec.rb +7 -0
  52. data/spec/forgery_spec.rb +63 -0
  53. data/spec/formats_spec.rb +35 -0
  54. data/spec/spec_helper.rb +39 -0
  55. metadata +89 -38
  56. data/lib/forgery/file_writer.rb +0 -54
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ $LOAD_PATH.push File.expand_path('lib', __dir__)
4
+ require 'forgery/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = 'forgery'
8
+ spec.version = Forgery::VERSION
9
+ spec.authors = ['Nathan Sutton', 'Brandon Arbini', 'Kamil Kieliszczyk']
10
+ spec.email = ['nate@zencoder.com', 'b@arbini.dev', 'kamil@kieliszczyk.net']
11
+ spec.homepage = 'http://github.com/sevenwire/forgery'
12
+ spec.summary = 'Easy and customizable generation of forged data.'
13
+ spec.description = 'Easy and customizable generation of forged data. Can be used as a gem or a rails plugin. Includes rails generators for creating your own forgeries.'
14
+
15
+ spec.platform = Gem::Platform::RUBY
16
+ spec.required_rubygems_version = '>= 1.3.6'
17
+
18
+ spec.files = `git ls-files`.split($INPUT_RECORD_SEPARATOR)
19
+ spec.test_files = `git ls-files spec`.split($INPUT_RECORD_SEPARATOR)
20
+ spec.require_paths = %w[lib]
21
+
22
+ spec.add_development_dependency 'bundler', '~> 2.1.4'
23
+ end
@@ -5,7 +5,6 @@ current_path = File.expand_path(File.dirname(__FILE__)) + '/'
5
5
 
6
6
  # Loading forgery helpers.
7
7
  require 'forgery/file_reader'
8
- require 'forgery/file_writer'
9
8
  require 'forgery/dictionaries'
10
9
  require 'forgery/formats'
11
10
 
@@ -0,0 +1,7 @@
1
+ AARBDE5W100
2
+ GENODEF1PA1
3
+ GENODE61HD1
4
+ BPAAIT2B001
5
+ BPAAIT2B009
6
+ VBRSDE33345
7
+ VBRSDE33347
@@ -204,7 +204,6 @@ Quire
204
204
  Camimbo
205
205
  Aibox
206
206
  Meevee
207
- Brainfire
208
207
  Gabcube
209
208
  Browsetype
210
209
  Shuffletag
@@ -73,7 +73,7 @@ Palladium Ounces
73
73
  Peru Nuevos Soles
74
74
  Philippines Pesos
75
75
  Platinum Ounces
76
- Poland Zlotych
76
+ Polish Zloty
77
77
  Portugal Escudos
78
78
  Qatar Riyals
79
79
  Romania New Lei
@@ -103,4 +103,4 @@ United States Dollars
103
103
  Venezuela Bolivares
104
104
  Venezuela Bolivares Fuertes
105
105
  Vietnam Dong
106
- Zambia Kwacha
106
+ Zambia Kwacha
@@ -0,0 +1,61 @@
1
+ AD1200012030200359100100
2
+ AE070331234567890123456
3
+ AL47212110090000000235698741
4
+ AT611904300234573201
5
+ AZ21NABZ00000000137010001944
6
+ BA391290079401028494
7
+ BE68539007547034
8
+ BG80BNBG96611020345678
9
+ BH67BMAG00001299123456
10
+ CH9300762011623852957
11
+ CY17002001280000001200527600
12
+ CZ6508000000192000145399
13
+ DE89370400440532013000
14
+ DK5000400440116243
15
+ DO28BAGR00000001212453611324
16
+ EE382200221020145685
17
+ ES9121000418450200051332
18
+ FI2112345600000785
19
+ FO7630004440960235
20
+ FR1420041010050500013M02606
21
+ GB29NWBK60161331926819
22
+ GE29NB0000000101904917
23
+ GI75NWBK000000007099453
24
+ GL4330003330229543
25
+ GR1601101250000000012300695
26
+ HR1210010051863000160
27
+ HU42117730161111101800000000
28
+ IE29AIBK93115212345678
29
+ IL620108000000099999999
30
+ IS140159260076545510730339
31
+ IT60X0542811101000000123456
32
+ JO94CBJO0010000000000131000302
33
+ KW81CBKU0000000000001234560101
34
+ KZ86125KZT5004100100
35
+ LB62099900000001001901229114
36
+ LI21088100002324013AA
37
+ LT121000011101001000
38
+ LU280019400644750000
39
+ LV80BANK0000435195001
40
+ MC1112739000700011111000h79
41
+ MD24AG000225100013104168
42
+ ME25505000012345678951
43
+ MK07300000000042425
44
+ MR1300020001010000123456753
45
+ MT84MALT011000012345MTLCAST001S
46
+ MU17BOMM0101101030300200000MUR
47
+ NL91ABNA0417164300
48
+ NO9386011117947
49
+ PL27114020040000300201355387
50
+ PK36SCBL0000001123456702
51
+ PT50000201231234567890154
52
+ QA58DOHB00001234567890ABCDEFG
53
+ RO49AAAA1B31007593840000
54
+ RS35260005601001611379
55
+ SA0380000000608010167519
56
+ SE3550000000054910000003
57
+ SI56191000000123438
58
+ SK3112000000198742637541
59
+ SM86U0322509800000000270100
60
+ TN5914207207100707129648
61
+ TR330006100519786457841326
@@ -24,7 +24,7 @@ Community Outreach Specialist
24
24
  Compensation Analyst
25
25
  Computer Systems Analyst #{N}
26
26
  Cost Accountant
27
- Data Coordiator
27
+ Data Coordinator
28
28
  Database Administrator #{N}
29
29
  Dental Hygienist
30
30
  Design Engineer
@@ -66,7 +66,7 @@ Harare
66
66
  Helsinki
67
67
  Istanbul
68
68
  Jerusalem
69
- Kyev
69
+ Kyiv
70
70
  Minsk
71
71
  Pretoria
72
72
  Riga
@@ -114,7 +114,6 @@ Kuala Lumpur
114
114
  Perth
115
115
  Singapore
116
116
  Taipei
117
- Ulaan Bataar
118
117
  Urumqi
119
118
  Osaka
120
119
  Sapporo
@@ -3,8 +3,6 @@ class Forgery
3
3
  case object
4
4
  when Array
5
5
  Forgery::Extensions::Array.new(object)
6
- when Hash
7
- Forgery::Extensions::Hash.new(object)
8
6
  when Range
9
7
  Forgery::Extensions::Range.new(object.first, object.last, object.exclude_end?)
10
8
  when String
@@ -9,7 +9,7 @@ class Forgery
9
9
  def random
10
10
  Integer(first) && Integer(last)
11
11
  raise ArgumentError if first > last
12
- Kernel.rand(last - first + (exclude_end? ? 0 : 1)) + first
12
+ Random.rand self
13
13
  rescue ArgumentError
14
14
  Forgery::Extend(to_a).random
15
15
  end
@@ -29,8 +29,9 @@ class Forgery
29
29
  def self.find_file(name, folder)
30
30
  Forgery.load_paths.reverse.each do |path|
31
31
  file = "#{path}/#{folder}/#{name}"
32
- return file if File.exists?(file)
32
+ return file if File.exist?(file)
33
33
  end
34
+ raise ArgumentError.new("File '#{name}' wasn't found in '#{folder}' folder. Searched paths: \n#{Forgery.load_paths.join('\n')}")
34
35
  end
35
36
  end
36
37
  end
@@ -0,0 +1,25 @@
1
+ # Generates random bank account information
2
+ class Forgery::BankAccount < Forgery
3
+
4
+ # Gets a random iban out of the 'ibans' dictionary.
5
+ #
6
+ # Forgery(:bank_account).iban
7
+ # # => "BE68539007547034"
8
+ #
9
+ # Forgery(:bank_account).iban
10
+ # # => "FI2112345600000785"
11
+ def self.iban
12
+ dictionaries[:ibans].random.unextend
13
+ end
14
+
15
+ # Gets a random bic out of the 'bics' dictionary.
16
+ #
17
+ # Forgery(:bank_account).bic
18
+ # # => "AARBDE5W100"
19
+ #
20
+ # Forgery(:bank_account).bic
21
+ # # => "GENODEF1PA1"
22
+ def self.bic
23
+ dictionaries[:bics].random.unextend
24
+ end
25
+ end
@@ -50,7 +50,7 @@ class Forgery::Basic < Forgery
50
50
  #
51
51
  # Forgery(:basic).encrypt('your-password', Time.utc(2009))
52
52
  # # => "4b157c2fbf430b962842d21926eaa887c3a12f81"
53
- def self.encrypt(password="password", salt=::Time.now.to_s)
53
+ def self.encrypt(password="password", salt=rand)
54
54
  Digest::SHA1.hexdigest("--#{salt}--#{password}--")
55
55
  end
56
56
 
@@ -0,0 +1,71 @@
1
+ # Generates random credit card numbers.
2
+ class Forgery::CreditCard < Forgery
3
+
4
+ CARDS = Forgery::Extend([
5
+ {:type => 'Visa', :length => 16, :prefixes => %w"4539 4556 4916 4532 4929 40240071 4485 4716 4"},
6
+ {:type => 'MasterCard', :length => 16, :prefixes => %w"51 52 53 54 55"},
7
+ {:type => 'American Express', :length => 15, :prefixes => %w"34 37"},
8
+ {:type => 'Discover', :length => 16, :prefixes => ["6011"]}
9
+ ])
10
+
11
+ # Gets a random credit card type
12
+ #
13
+ # Forgery(:credit_card).type
14
+ # # => "Visa"
15
+ def self.type
16
+ CARDS.random[:type]
17
+ end
18
+
19
+ # Gets a random credit card number
20
+ #
21
+ # Forgery(:credit_card).number
22
+ # # => "4539750423451972"
23
+ #
24
+ # Forgery(:credit_card).number(:type => 'Visa', :length => 13)
25
+ # # => "4556180133982"
26
+ #
27
+ # Supported Options
28
+ # [:type]
29
+ # The credit card type. Defaults to a random selection.
30
+ # [:length]
31
+ # The length of the credit card number. Defaults to the length for the selected card type.
32
+ # [:prefixes]
33
+ # The allowed prefixes for the card number. Defaults to prefixes for the selected card type.
34
+ def self.number(options={})
35
+ # find a card by type specified, or select a card randomly
36
+ card = if options[:type]
37
+ CARDS.find { |ccard| ccard[:type] == options[:type] }.clone
38
+ else
39
+ CARDS.random.clone
40
+ end
41
+ # merge the remaining options
42
+ card.merge!(options)
43
+ # start the number with a prefix for this card
44
+ number = Forgery::Extend(card[:prefixes]).random
45
+ # fill in the rest of the number with random digits, leave one space for the check digit
46
+ number << Forgery::Extend("#" * (card[:length] - number.length - 1)).to_numbers
47
+ # add the check digit
48
+ number += check_digit(number)
49
+ end
50
+
51
+ private
52
+
53
+ def self.check_digit(number)
54
+ # for explanation, please see: http://www.darkcoding.net/credit-card/luhn-formula/
55
+ sum = 0
56
+ digits = number.reverse.chars.to_a.collect { |digit| digit.to_i }
57
+ digits.each_with_index do |digit, index|
58
+ if index.even?
59
+ sum += if digit * 2 > 9
60
+ digit * 2 - 9
61
+ else
62
+ digit * 2
63
+ end
64
+ else
65
+ sum += digit
66
+ end
67
+ end
68
+ (((sum / 10 + 1) * 10 - sum) % 10).to_s
69
+ end
70
+
71
+ end
@@ -0,0 +1,54 @@
1
+ # Generates random geographic information.
2
+ class Forgery::Geo < Forgery
3
+
4
+ # Return a latitude in the range -90.0 to +90.0 as a float.
5
+ def self.latitude
6
+ rand * 180.0 - 90.0
7
+ end
8
+
9
+ # Return a latitude's degrees component in the range -180 to +180 as an integer.
10
+ def self.latitude_degrees
11
+ rand(360)-180
12
+ end
13
+
14
+ # Return a latitude's minutes component in the range 0 to 60 as an integer.
15
+ def self.latitude_minutes
16
+ rand(60)
17
+ end
18
+
19
+ # Return a latitude's seconds component in the range 0 to 60 as an integer.
20
+ def self.latitude_seconds
21
+ rand(60)
22
+ end
23
+
24
+ # Return a latitude's direction component, either "N" (north) or "S" (south)
25
+ def self.latitude_direction
26
+ ['N','S'].sample
27
+ end
28
+
29
+ # Return a longitude in the range -180.0 to +180.0 as a float.
30
+ def self.longitude
31
+ rand * 360.0 - 180.0
32
+ end
33
+
34
+ # Return a longitude's degrees component in the range -180 to +180 as an integer.
35
+ def self.longitude_degrees
36
+ rand(360)-180
37
+ end
38
+
39
+ # Return a longitude's minutes component in the range 0 to 60 as an integer.
40
+ def self.longitude_minutes
41
+ rand(60)
42
+ end
43
+
44
+ # Return a longitude's seconds component in the range 0 to 60 as an integer.
45
+ def self.longitude_seconds
46
+ rand(60)
47
+ end
48
+
49
+ # Return a longitude's direction component, either "E" (east) or "W" (west)
50
+ def self.longitude_direction
51
+ ["E","W"].sample
52
+ end
53
+
54
+ end
@@ -1,3 +1,5 @@
1
+ require 'ipaddr'
2
+
1
3
  class Forgery::Internet < Forgery
2
4
 
3
5
  def self.user_name
@@ -28,4 +30,9 @@ class Forgery::Internet < Forgery
28
30
  (1..4).map{rand(256)}.join('.')
29
31
  end
30
32
 
33
+ # credit for this method from http://stackoverflow.com/a/2811349/793330
34
+ def self.ip_v6
35
+ IPAddr.new(rand(2**128),Socket::AF_INET6).to_s
36
+ end
37
+
31
38
  end
@@ -28,7 +28,7 @@ class Forgery::LoremIpsum < Forgery
28
28
  end
29
29
 
30
30
  def self.characters(quantity=10, options={})
31
- options.merge!(:random_limit => lorem_ipsum_characters.length-quantity) if quantity.is_a?(Fixnum)
31
+ options.merge!(:random_limit => lorem_ipsum_characters.length-quantity) if quantity.is_a?(Integer)
32
32
 
33
33
  lorem_ipsum_characters[range_from_quantity(quantity, options)]
34
34
  end
@@ -38,7 +38,7 @@ class Forgery::LoremIpsum < Forgery
38
38
  end
39
39
 
40
40
  def self.words(quantity=10, options={})
41
- options.merge!(:random_limit => lorem_ipsum_words.length-quantity) if quantity.is_a?(Fixnum)
41
+ options.merge!(:random_limit => lorem_ipsum_words.length-quantity) if quantity.is_a?(Integer)
42
42
 
43
43
  lorem_ipsum_words[range_from_quantity(quantity, options)].join(" ")
44
44
  end
@@ -48,7 +48,7 @@ class Forgery::LoremIpsum < Forgery
48
48
  end
49
49
 
50
50
  def self.sentences(quantity=2, options={})
51
- options.merge!(:random_limit => (dictionaries[:lorem_ipsum].length-quantity)) if quantity.is_a?(Fixnum)
51
+ options.merge!(:random_limit => (dictionaries[:lorem_ipsum].length-quantity)) if quantity.is_a?(Integer)
52
52
 
53
53
  dictionaries[:lorem_ipsum][range_from_quantity(quantity, options)].join(" ")
54
54
  end
@@ -65,7 +65,7 @@ class Forgery::LoremIpsum < Forgery
65
65
  :html => false,
66
66
  :sentences => 3}
67
67
  options = default_options.merge(options)
68
- options.merge!(:random_limit => (dictionaries[:lorem_ipsum].length/options[:sentences])-quantity) if quantity.is_a?(Fixnum)
68
+ options.merge!(:random_limit => (dictionaries[:lorem_ipsum].length/options[:sentences])-quantity) if quantity.is_a?(Integer)
69
69
 
70
70
  if options[:html]
71
71
  options[:wrap] = { :start => "<p>",
@@ -0,0 +1,57 @@
1
+ # Generates various special numbers for Russian taxation system
2
+ # They have numbers for identification, for banks, for companies and entrepreneurs
3
+ class Forgery::RussianTax < Forgery
4
+
5
+ TYPES = Forgery::Extend([:person, :legal])
6
+
7
+ #bank identification
8
+ def self.bik
9
+ "04#{5.times.map { rand(9) + 1 }.join}#{rand(50) + 50}"
10
+ end
11
+
12
+ #bank account format pretty simple
13
+ def self.account_number
14
+ 20.times.map { rand(9) + 1 }.join
15
+ end
16
+
17
+ #taxation id
18
+ def self.inn(options = {})
19
+ type = TYPES.include?(options[:type]) ? options[:type] : TYPES.random
20
+ send [type, :inn].join('_')
21
+ end
22
+
23
+ #government registration id
24
+ def self.ogrn(options = {})
25
+ type = TYPES.include?(options[:type]) ? options[:type] : TYPES.random
26
+ send [type, :ogrn].join('_')
27
+ end
28
+
29
+ private
30
+ def self.person_inn
31
+ mask = [[7, 2, 4, 10, 3, 5, 9, 4, 6, 8], [3, 7, 2, 4, 10, 3, 5, 9, 4, 6, 8]]
32
+ inn = 12.times.map { rand(9) + 1 }.join
33
+ inn[10] = ((0..(inn.length-3)).inject(0) {|crc, i| crc + inn[i].to_i*mask[0][i].to_i} % 11 % 10).to_s
34
+ inn[11] = ((0..(inn.length-2)).inject(0) {|crc, i| crc + inn[i].to_i*mask[1][i].to_i} % 11 % 10).to_s
35
+ inn
36
+ end
37
+
38
+ def self.legal_inn
39
+ mask = [2, 4, 10, 3, 5, 9, 4, 6, 8]
40
+ inn = 10.times.map { rand(9) + 1 }.join
41
+ inn[9] = ((0..(inn.length-2)).inject(0) {|crc, i| crc + inn[i].to_i*mask[i].to_i} % 11 % 10).to_s
42
+ inn
43
+ end
44
+
45
+ def self.person_ogrn
46
+ ogrn = 14.times.map { rand(9) + 1 }.join
47
+ ogrn += (ogrn.to_i%13%10).to_s
48
+ ogrn
49
+ end
50
+
51
+ def self.legal_ogrn
52
+ ogrn = 12.times.map { rand(9) + 1 }.join
53
+ ogrn += (ogrn.to_i%11%10).to_s
54
+ ogrn
55
+ end
56
+
57
+ end