-
Notifications
You must be signed in to change notification settings - Fork 4
/
Sims.pm
142 lines (94 loc) · 3.08 KB
/
Sims.pm
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
package Test::Sims;
use strict;
use warnings;
our $VERSION = "20090628";
=head1 NAME
Test::Sims - Helps build semi-random data for testing
=head1 SYNOPSIS
package My::Sims;
use Test::Sims;
# Creates rand_name() and exported on demand.
make_rand name => [
qw(Mal Zoe Jayne Kaylee Inara River Simon Wash Zoe Book)
];
# Automatically exported
sub sim_character {
my %defaults = (
name => rand_name(),
series => "Firefly",
);
require Character;
return Character->new(
%defaults, @_;
);
}
=head1 DESCRIPTION
This is a module to help building semi-random data for testing and to
create large, nested, interesting data structures.
This module contains no new assertions, but it does tie in with
Test::Builder.
It does two things. It contains functions which make generating
random data easier and it allows you to write repeatable, yet random,
test data.
=head2 Automatic exports
By using Test::Sims your module will inherit from Exporter.
=begin todo
It will automatically export any functions called C<<sim_*>> and will
export anything called C<<rand_*>> on demand. In addition there will
be export tags. C<<:sim>> will export all C<<sim_*>> functions and
C<<:rand>> all C<<rand_*>> functions. C<<:ALL>> exports everything.
=end todo
=head2 make_rand()
my $code = make_rand $name => \@list;
Creates a subroutine called C<<rand_$name>> and exports it on request.
=head2 Controlling randomness
You can control the random seed used by Test::Sims by setting the
C<TEST_SIMS_SEED> environment variable. This is handy to make test runs
repeatable.
=begin todo
Test::Sims will output the seed used at the end of each test run. If
the test failed it will be visible to the user, otherwise it will be a
TAP comment and only visible if the test is run verbosely.
=end todo
=cut
use base qw(Exporter);
our @EXPORT = qw(make_rand);
# Yes, its not a great seed but it doesn't have to be secure.
my $Seed = defined $ENV{TEST_SIMS_SEED} ? $ENV{TEST_SIMS_SEED} : time ^ $$;
# XXX If something else calls srand() we're in trouble
srand($Seed);
sub import {
my $class = shift;
my $caller = caller;
{
no strict 'refs';
unshift @{$caller. "::ISA"}, "Exporter" unless $caller->isa("Exporter");
}
__PACKAGE__->export_to_level(1, $class, @_);
}
sub make_rand {
my $name = shift;
my $items = shift;
my $caller = caller;
my $code = sub {
my %args = @_;
$args{min} = 1 unless defined $args{min};
$args{max} = 1 unless defined $args{max};
my $max = int rand($args{max} - $args{min} + 1) + $args{min};
my @return;
for (1..$max) {
push @return, $items->[rand @$items];
}
return @return;
};
{
no strict 'refs';
my $func = "rand_$name";
*{$caller .'::'. $func} = $code;
push @{$caller . '::EXPORT_OK'}, $func;
my $export_tags = \%{ $caller . '::EXPORT_TAGS' };
push @{$export_tags->{"rand"}}, $func;
}
return $code;
}
1;