line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Test::Mimic; |
2
|
|
|
|
|
|
|
|
3
|
1
|
|
|
1
|
|
38835
|
use strict; |
|
1
|
|
|
|
|
3
|
|
|
1
|
|
|
|
|
42
|
|
4
|
1
|
|
|
1
|
|
5
|
use warnings; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
37
|
|
5
|
|
|
|
|
|
|
|
6
|
1
|
|
|
|
|
120
|
use Test::Mimic::Library qw< |
7
|
|
|
|
|
|
|
load_records |
8
|
|
|
|
|
|
|
init_records |
9
|
|
|
|
|
|
|
load_preferences |
10
|
|
|
|
|
|
|
ARBITRARY |
11
|
1
|
|
|
1
|
|
1155
|
>; |
|
1
|
|
|
|
|
48439
|
|
12
|
1
|
|
|
1
|
|
1141
|
use Test::Mimic::Generator; |
|
1
|
|
|
|
|
7007
|
|
|
1
|
|
|
|
|
559
|
|
13
|
|
|
|
|
|
|
|
14
|
|
|
|
|
|
|
our $VERSION = 0.009_007; |
15
|
|
|
|
|
|
|
|
16
|
|
|
|
|
|
|
# Preloaded methods go here. |
17
|
|
|
|
|
|
|
|
18
|
|
|
|
|
|
|
# Private to the Test::Mimic suite. |
19
|
|
|
|
|
|
|
{ |
20
|
|
|
|
|
|
|
my @pristine_INC; |
21
|
|
|
|
|
|
|
|
22
|
|
|
|
|
|
|
# Returns @INC to its state prior to when require_from was called. |
23
|
|
|
|
|
|
|
# Generated packages must call this before using any external modules. |
24
|
|
|
|
|
|
|
sub prepare_for_use { |
25
|
2
|
100
|
|
2
|
0
|
8
|
if (@pristine_INC) { |
26
|
1
|
|
|
|
|
4
|
@INC = @pristine_INC; |
27
|
1
|
|
|
|
|
17
|
@pristine_INC = (); |
28
|
|
|
|
|
|
|
} |
29
|
|
|
|
|
|
|
} |
30
|
|
|
|
|
|
|
|
31
|
|
|
|
|
|
|
# Accepts a package to require and a directory name to load it from. |
32
|
|
|
|
|
|
|
# This will modify @INC while it is running, but return restore it |
33
|
|
|
|
|
|
|
# prior to exiting. |
34
|
|
|
|
|
|
|
sub require_from { |
35
|
1
|
|
|
1
|
0
|
2
|
my ( $package, $dir ) = @_; |
36
|
|
|
|
|
|
|
|
37
|
1
|
|
|
|
|
6
|
@pristine_INC = @INC; |
38
|
1
|
|
|
|
|
3
|
@INC = ($dir); |
39
|
|
|
|
|
|
|
|
40
|
|
|
|
|
|
|
# Load the package |
41
|
1
|
|
|
|
|
56
|
my $success = eval( "require $package; 1" ); |
42
|
|
|
|
|
|
|
|
43
|
|
|
|
|
|
|
# Undo the @INC change |
44
|
1
|
|
|
|
|
5
|
prepare_for_use(); |
45
|
|
|
|
|
|
|
|
46
|
1
|
|
|
|
|
4
|
return $success; |
47
|
|
|
|
|
|
|
} |
48
|
|
|
|
|
|
|
} |
49
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
my $save_to; # The directory to read/write recorded behavior. |
51
|
|
|
|
|
|
|
my $recording_required; # Will be set to true iff a package was requrested that has not yet been recorded. |
52
|
|
|
|
|
|
|
|
53
|
|
|
|
|
|
|
# See the POD below. |
54
|
|
|
|
|
|
|
sub import { |
55
|
1
|
|
|
1
|
|
17
|
my ( $class, $user_preferences ) = @_; |
56
|
|
|
|
|
|
|
|
57
|
1
|
50
|
|
|
|
5
|
if ( ! defined($user_preferences) ) { |
58
|
0
|
|
|
|
|
0
|
die 'No preference hash reference passed to import in Test::Mimic.'; |
59
|
|
|
|
|
|
|
} |
60
|
|
|
|
|
|
|
|
61
|
1
|
|
|
|
|
1
|
my %preferences = %{$user_preferences}; |
|
1
|
|
|
|
|
6
|
|
62
|
|
|
|
|
|
|
|
63
|
1
|
50
|
|
|
|
5
|
if ( ! defined( $preferences{'packages'} ) ) { |
64
|
0
|
|
|
|
|
0
|
die 'No packages selected to mimic.'; |
65
|
|
|
|
|
|
|
} |
66
|
|
|
|
|
|
|
|
67
|
1
|
|
|
|
|
1
|
$preferences{'test_mimic'} = ARBITRARY; |
68
|
1
|
|
50
|
|
|
9
|
$save_to = $preferences{'save'} ||= '.test_mimic_data'; |
69
|
|
|
|
|
|
|
|
70
|
|
|
|
|
|
|
# Setup the library to behave per user preferences. |
71
|
1
|
|
|
|
|
4
|
my $history = $save_to . '/history_for_playback.rec'; |
72
|
1
|
50
|
|
|
|
25
|
if ( -e $history ) { # This won't be true if we haven't recorded at all before. |
73
|
1
|
|
|
|
|
5
|
load_records($history); |
74
|
|
|
|
|
|
|
} |
75
|
|
|
|
|
|
|
else { |
76
|
0
|
|
|
|
|
0
|
init_records(); |
77
|
|
|
|
|
|
|
} |
78
|
1
|
|
|
|
|
1460
|
load_preferences(\%preferences); |
79
|
|
|
|
|
|
|
|
80
|
|
|
|
|
|
|
# Attempt to load mimicked versions of each package. Note those that have not been recorded. |
81
|
1
|
|
|
|
|
18
|
my $lib_dir = $save_to . '/lib'; |
82
|
1
|
|
|
|
|
1
|
my $playback_stage = 0; |
83
|
1
|
|
|
|
|
2
|
my @to_record; |
84
|
1
|
|
|
|
|
2
|
for my $package_to_mimic ( keys %{ $preferences{'packages'} } ) { |
|
1
|
|
|
|
|
4
|
|
85
|
1
|
50
|
|
|
|
5
|
if ( ! require_from( $package_to_mimic, $lib_dir ) ) { |
86
|
0
|
|
|
|
|
0
|
push( @to_record, $package_to_mimic ); |
87
|
|
|
|
|
|
|
} |
88
|
|
|
|
|
|
|
else { |
89
|
1
|
|
|
|
|
131
|
$playback_stage = 1; |
90
|
|
|
|
|
|
|
} |
91
|
|
|
|
|
|
|
} |
92
|
|
|
|
|
|
|
|
93
|
|
|
|
|
|
|
# Prevent playback/recording conflicts. |
94
|
1
|
50
|
33
|
|
|
12
|
if ( $playback_stage && @to_record > 0 ) { |
95
|
0
|
|
|
|
|
0
|
die "The playback stage and the recording stage can not coincide. Either delete the current" . |
96
|
|
|
|
|
|
|
"recordings or stop mimicking the following package(s): @to_record"; |
97
|
|
|
|
|
|
|
} |
98
|
|
|
|
|
|
|
|
99
|
|
|
|
|
|
|
# Record the missing packages. |
100
|
1
|
50
|
|
|
|
30
|
if ( @to_record != 0 ) { |
101
|
0
|
|
|
|
|
|
$recording_required = 1; |
102
|
0
|
|
|
|
|
|
require Test::Mimic::Recorder; |
103
|
0
|
|
|
|
|
|
my %recorder_prefs = %preferences; |
104
|
|
|
|
|
|
|
|
105
|
|
|
|
|
|
|
#Only include those packages that need recording. |
106
|
0
|
|
|
|
|
|
$recorder_prefs{'packages'} = {}; |
107
|
0
|
|
|
|
|
|
for my $package (@to_record) { |
108
|
0
|
|
|
|
|
|
$recorder_prefs{'packages'}->{$package} = $preferences{'packages'}->{$package}; |
109
|
|
|
|
|
|
|
} |
110
|
0
|
|
|
|
|
|
Test::Mimic::Recorder->import(\%recorder_prefs); |
111
|
|
|
|
|
|
|
} |
112
|
|
|
|
|
|
|
} |
113
|
|
|
|
|
|
|
|
114
|
|
|
|
|
|
|
# Handles the code generation after the recording is complete. |
115
|
|
|
|
|
|
|
# NOTE: This relies on the LIFO structure of END block execution. |
116
|
|
|
|
|
|
|
END { |
117
|
1
|
50
|
|
1
|
|
586
|
if ($recording_required) { |
118
|
0
|
|
|
|
|
0
|
my $generator = Test::Mimic::Generator->new(); |
119
|
0
|
|
|
|
|
0
|
$generator->load($save_to); |
120
|
0
|
|
|
|
|
0
|
$generator->write($save_to); |
121
|
|
|
|
|
|
|
} |
122
|
|
|
|
|
|
|
} |
123
|
|
|
|
|
|
|
|
124
|
|
|
|
|
|
|
1; |
125
|
|
|
|
|
|
|
__END__ |