File Coverage

blib/lib/DBIx/Class/Sims/Types.pm
Criterion Covered Total %
statement 6 8 75.0
branch n/a
condition n/a
subroutine 3 3 100.0
pod n/a
total 9 11 81.8


line stmt bran cond sub pod time code
1             # vim: set sw=2 ft=perl:
2             package DBIx::Class::Sims::Types;
3              
4 12     12   6546 use 5.010_001;
  12         39  
5              
6 12     12   2919 use strictures 2;
  12         14436  
  12         420  
7              
8 12     12   5399 use DBIx::Class::Sims;
  0            
  0            
9             DBIx::Class::Sims->set_sim_types({
10             map { $_ => __PACKAGE__->can($_) } qw(
11             email_address ip_address
12             us_firstname us_lastname us_name
13             us_address us_city us_county us_phone us_ssntin us_state us_zipcode
14             )
15             });
16              
17             use String::Random qw( random_regex random_string );
18              
19             {
20             my @tlds = qw(
21             com net org gov mil co.uk co.es
22             );
23              
24             sub email_address {
25             my ($info) = @_;
26              
27             my $size = $info->{size} // 7;
28             if ( $size < 7 ) {
29             return '';
30             }
31              
32             my $tld = $tlds[rand @tlds];
33             while ( $size - length($tld) < 4 ) {
34             $tld = $tlds[rand @tlds];
35             }
36              
37             # Don't always create an address to fill the full amount.
38             if ( $size > 20 && rand() < .5 ) {
39             $size -= int(rand($size-20));
40             }
41              
42             $size -= length($tld) + 1 + 1; # + . for $tld + @
43              
44             # Split size evenly-ish, but with randomness
45             my $acct_size = int($size/2);
46             $size -= $acct_size;
47              
48             my $acct = random_string( "0"x$acct_size, ['a'..'z','A'..'Z','0'..'9'] );
49             if ( $acct_size > 5 && rand() < 0.1 ) {
50             my $n = int(rand($acct_size - 4)) + 2;
51             substr($acct, $n, 1) = '+';
52             }
53              
54             my $domain = random_string( "c"x$size );
55             if ( $size > 5 ) {
56             my $n = int(rand($size - 4)) + 2;
57             substr($domain, $n, 1) = '.';
58             }
59              
60             return "${acct}\@${domain}.${tld}";
61             }
62             }
63              
64             sub ip_address {
65             return join '.', map { int(rand(255)) + 1 } 1 .. 4;
66             }
67              
68             {
69             my @street_names = qw(
70             Main Court House Mill Wood Millwood
71             First Second Third Fourth Fifth Sixth Seventh Eight Ninth
72             Magnolia Acacia Poppy Cherry Rose Daisy Daffodil
73             );
74              
75             my @street_types = qw(
76             Street Drive Place Avenue Boulevard Lane
77             St Dr Pl Av Ave Blvd Ln
78             St. Dr. Pl. Av. Ave. Blvd. Ln.
79             );
80              
81             sub us_address {
82             # Assume a varchar-like column type with enough space.
83              
84             if ( rand() < .7 ) {
85             # We want to change this so that distribution is by number of digits, then
86             # randomly within the numbers.
87             my $number = int(rand(99999));
88              
89             my $street_name = $street_names[rand @street_names];
90             my $street_type = $street_types[rand @street_types];
91              
92             return "$number $street_name $street_type";
93             }
94             else {
95             my $po = rand() < .5 ? 'PO' : 'P.O.';
96             return "$po Box " . int(rand(9999));
97             }
98             }
99             }
100              
101             {
102             my @city_names = qw(
103             Ithaca Jonestown Marysville Ripon Minneapolis Miami Paris London Columbus
104             );
105             push @city_names, (
106             'New York', 'Los Angeles', 'Montego By The Bay',
107             );
108              
109             sub us_city {
110             # Assume a varchar-like column type with enough space.
111             return $city_names[rand @city_names];
112             }
113             }
114              
115             {
116             my @county_names = qw(
117             Adams Madison Washinton Union Clark
118             );
119              
120             sub us_county {
121             # Assume a varchar-like column type with enough space.
122             return $county_names[rand @county_names];
123             }
124             }
125              
126             {
127             my @first_names = qw(
128             Aidan Bill Charles Doug Evan Frank George Hunter Ilya Jeff Kilgore
129             Liam Michael Nathan Oscar Perry Robert Shawn Thomas Urkul Victor Xavier
130              
131             Alexandra Betty Camille Debra Ellen Fatima Georgette Hettie Imay Jaime
132             Kathrine Leticia Margaret Nellie Ophelia Patsy Regina Sybil Tricia Valerie
133             );
134              
135             sub us_firstname {
136             # Assume a varchar-like column type with enough space.
137             return $first_names[rand @first_names],
138             }
139             }
140              
141             {
142             my @last_names = qw(
143             Jones Smith Taylor Kinyon Williams Shaner Perry Raymond Moore O'Malley
144             );
145             # Some last names are two words.
146             push @last_names, (
147             "Von Trapp", "Van Kirk",
148             );
149              
150             sub us_lastname {
151             # Assume a varchar-like column type with enough space.
152             return $last_names[rand @last_names],
153             }
154             }
155              
156             {
157             my @letters = ( 'A' .. 'Z' );
158              
159             my @suffixes = (
160             'Jr', 'Sr', 'II', 'III', 'IV', 'Esq.',
161             );
162              
163             sub us_name {
164             # Assume a varchar-like column type with enough space.
165              
166             my @name = us_firstname(@_);
167              
168             # 10% chance of adding a middle initial
169             if ( rand() < 0.1 ) {
170             push @name, $letters[rand @letters] . '.';
171             }
172              
173             push @name, us_lastname(@_);
174              
175             # 10% chance of adding a suffix
176             if ( rand() < 0.1 ) {
177             push @name, $suffixes[rand @suffixes];
178             }
179              
180             return join ' ', @name;
181             }
182             }
183              
184             sub us_phone {
185             my ($info) = @_;
186              
187             # Assume a varchar-like column type.
188             my $length = $info->{size} // 8;
189             if ( $length < 7 ) {
190             return '';
191             }
192             elsif ( $length == 7 ) {
193             return random_regex('\d{7}');
194             }
195             elsif ( $length < 10 ) {
196             return random_regex('\d{3}-\d{4}');
197             }
198             elsif ( $length < 12 ) {
199             return random_regex('\d{10}');
200             }
201             elsif ( $length == 12 ) {
202             return random_regex('\d{3}-\d{3}-\d{4}');
203             }
204             # random_regex() throws a warning no matter how I try to specify the parens.
205             # It does the right thing, but noisily. So, just concatenate them.
206             elsif ( $length == 13 ) {
207             return '(' . random_regex('\d{3}') . ')' . random_regex('\d{3}-\d{4}');
208             }
209             else { #if ( $length >= 14 ) {
210             return '(' . random_regex('\d{3}') . ') ' . random_regex('\d{3}-\d{4}');
211             }
212             }
213              
214             sub us_ssntin {
215             # Give strong preference to a SSN
216             if ( rand() < .8 ) {
217             return random_regex('\d{3}-\d{2}-\d{4}');
218             }
219             # But still generate employer TINs to mix it up.
220             else {
221             return random_regex('\d{2}-\d{7}');
222             }
223             }
224              
225             {
226             my @states = (
227             [ AL => 'Alabama' ],
228             [ AK => 'Alaska' ],
229             [ AZ => 'Arizona' ],
230             [ AR => 'Arkansas' ],
231             [ CA => 'California' ],
232             [ CO => 'Colorado' ],
233             [ CT => 'Connecticut' ],
234             [ DE => 'Delaware' ],
235             [ FL => 'Florida' ],
236             [ GA => 'Georgia' ],
237             [ HI => 'Hawaii' ],
238             [ ID => 'Idaho' ],
239             [ IL => 'Illinois' ],
240             [ IN => 'Indiana' ],
241             [ IA => 'Iowa' ],
242             [ KS => 'Kansas' ],
243             [ KY => 'Kentucky' ],
244             [ LA => 'Louisiana' ],
245             [ ME => 'Maine' ],
246             [ MD => 'Maryland' ],
247             [ MA => 'Massachusetts' ],
248             [ MI => 'Michigan' ],
249             [ MN => 'Minnesota' ],
250             [ MS => 'Mississippi' ],
251             [ MO => 'Missouri' ],
252             [ MT => 'Montana' ],
253             [ NE => 'Nebraska' ],
254             [ NJ => 'New Jersey' ],
255             [ NH => 'New Hampshire' ],
256             [ NV => 'Nevada' ],
257             [ NM => 'New Mexico' ],
258             [ NY => 'New York' ],
259             [ NC => 'North Carolina' ],
260             [ ND => 'North Dakota' ],
261             [ OH => 'Ohio' ],
262             [ OK => 'Oklahoma' ],
263             [ OR => 'Oregon' ],
264             [ PA => 'Pennsylvania' ],
265             [ RI => 'Rhode Island' ],
266             [ SC => 'South Carolina' ],
267             [ SD => 'South Dakota' ],
268             [ TN => 'Tennessee' ],
269             [ TX => 'Texas' ],
270             [ UT => 'Utah' ],
271             [ VT => 'Vermont' ],
272             [ VA => 'Virginia' ],
273             [ WA => 'Washington' ],
274             [ WV => 'West Virginia' ],
275             [ WI => 'Wisconsin' ],
276             [ WY => 'Wyoming' ],
277             # These are territories, not states, but that's okay.
278             [ AS => 'American Samoa' ],
279             [ DC => 'District Of Columbia' ],
280             [ GU => 'Guam' ],
281             [ MD => 'Midway Islands' ],
282             [ NI => 'Northern Mariana Islands' ],
283             [ PR => 'Puerto Rico' ],
284             [ VI => 'Virgin Islands' ],
285             );
286             sub us_state {
287             my ($info) = @_;
288              
289             # Assume a varchar-like column type.
290             my $length = $info->{size} // 2;
291             if ( $length == 2 ) {
292             return $states[rand @states][0];
293             }
294             return substr($states[rand @states][1], 0, $length);
295             }
296             }
297              
298             sub us_zipcode {
299             my ($info) = @_;
300              
301             my $datatype = $info->{data_type};
302             if ( $datatype eq 'varchar' || $datatype eq 'char' ) {
303             my $length = $info->{size} // 9;
304             if ( $length < 5 ) {
305             return '';
306             }
307             elsif ( $length < 9 ) {
308             return random_regex('\d{5}');
309             }
310             elsif ( $length == 9 ) {
311             return random_regex('\d{9}');
312             }
313             else {
314             return random_regex('\d{5}-\d{4}');
315             }
316             }
317             # Treat it as an int.
318             else {
319             return int(rand(99999));
320             }
321             }
322              
323             1;
324             __END__
325              
326             =head1 NAME
327              
328             DBIx::Class::Sims::Types
329              
330             =head1 PURPOSE
331              
332             These are pre-defined sim types for using with L<DBIx::Class::Sims>.
333              
334             =head2 TYPES
335              
336             The following sim types are pre-defined:
337              
338             =over 4
339              
340             =item * email_address
341              
342             This generates a reasonable-looking email address. The account and server names
343             are randomly generated. The TLD is selected from a list of TLDs, including
344             'co.uk' (so be warned). If the server name is large enough, a '.' will be added
345             to create a 2-level name.
346              
347             There is a small chance that a more complex email address will be used. These
348             email addresses are ones that are more likely to break poorly-written validator
349             checks. Some real-life (completely legal) examples are:
350              
351             =over 4
352              
353             =item * rob.kinyon+lists@gmail.com
354              
355             =back
356              
357             =item * ip_address
358              
359             This generates a reasonable-looking IP address.
360              
361             =item * us_address
362              
363             This generates a reasonable-looking US street address. The address will be one
364             of these forms:
365              
366             =over 4
367              
368             =item * "#### Name Type", so something like "123 Main Street"
369              
370             =item * "PO Box ####", so something like "PO Box 13579"
371              
372             =item * "P.O. Box ####", so something like "P.O. Box 97531"
373              
374             =back
375              
376             =item * us_city
377              
378             This generates a reasonable-looking US city name.
379              
380             =item * us_county
381              
382             This generates a reasonable-looking US county name.
383              
384             =item * us_firstname
385              
386             This generates a reasonable-looking US person first name. It will be randomized
387             as to gender.
388              
389             =item * us_lastname
390              
391             This generates a reasonable-looking US person last name. It may contain one
392             word, two words, or an apostrophized word.
393              
394             =item * us_name
395              
396             This generates a reasonable-looking US person name. The first and last names
397             will be generated from us_firstname and us_lastname, respectively. There is a
398             small chance a suffix will be appended.
399              
400             =item * us_phone
401              
402             This generates a reasonable-looking US phone-number, based on the size of the
403             column being filled. The column is assumed to be a character-type column
404             (varchar, etc). If the size of the column is less than 10, there will be no area
405             code. If there is space, hyphens and parentheses will be added in the right
406             places. If the column is long enough, the value will look like "(###) ###-####"
407              
408             Phone extensions are not supported at this time.
409              
410             =item * us_ssntin
411              
412             This generates a reasonable-looking US Social Security Number (SSN) or Tax
413             Identification Number (TIN). These are government identifiers that are often
414             usable as unique personal IDs. An SSN is a personal ID number and a TIN is a
415             corporate ID number.
416              
417             =item * us_state
418              
419             This generates a random US state or territory (so 57 choices). The column is
420             assumed to be able to take a US state as a value. If the size of the column is 2
421             (the default), then the abbreviation will be returned. Otherwise, the first N
422             characters of the name (where N is the size) will be returned.
423              
424             =item * us_zipcode
425              
426             This generates a reasonable-looking US zipcode. If the column is numeric, it
427             generates a number between 1 and 99999. Otherwise, it generates a legal string
428             of numbers (with a possible dash for a 5+4) that will fit within the column's
429             width.
430              
431             =back
432              
433             The reason why several of the pre-defined sim types have the country prefixed is
434             because different countries do things differently. (Shocker, I know!)
435              
436             =head1 AUTHOR
437              
438             Rob Kinyon <rob.kinyon@gmail.com>
439              
440             =head1 LICENSE
441              
442             Copyright (c) 2013 Rob Kinyon. All Rights Reserved.
443             This is free software, you may use it and distribute it under the same terms
444             as Perl itself.
445              
446             =cut