forgery 0.4.3 → 0.8.1

Sign up to get free protection for your applications and to get access to all the features.
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