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
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
|
BEGIN {
if( $ENV{PERL_CORE} ) {
chdir '../lib/Archive/Extract' if -d '../lib/Archive/Extract';
unshift @INC, '../../..', '../../../..';
}
}
BEGIN { chdir 't' if -d 't' };
BEGIN { mkdir 'out' unless -d 'out' };
use strict;
use lib qw[../lib];
use constant IS_WIN32 => $^O eq 'MSWin32' ? 1 : 0;
use constant IS_CYGWIN => $^O eq 'cygwin' ? 1 : 0;
use constant IS_VMS => $^O eq 'VMS' ? 1 : 0;
use Cwd qw[cwd];
use Test::More qw[no_plan];
use File::Spec;
use File::Spec::Unix;
use File::Path;
use Data::Dumper;
use File::Basename qw[basename];
use Module::Load::Conditional qw[check_install];
### uninitialized value in File::Spec warnings come from A::Zip:
# t/01_Archive-Extract....ok 135/0Use of uninitialized value in concatenation (.) or string at /opt/lib/perl5/5.8.3/File/Spec/Unix.pm line 313.
# File::Spec::Unix::catpath('File::Spec','','','undef') called at /opt/lib/perl5/site_perl/5.8.3/Archive/Zip.pm line 473
# Archive::Zip::_asLocalName('') called at /opt/lib/perl5/site_perl/5.8.3/Archive/Zip.pm line 652
# Archive::Zip::Archive::extractMember('Archive::Zip::Archive=HASH(0x9679c8)','Archive::Zip::ZipFileMember=HASH(0x9678fc)') called at ../lib/Archive/Extract.pm line 753
# Archive::Extract::_unzip_az('Archive::Extract=HASH(0x966eac)') called at ../lib/Archive/Extract.pm line 674
# Archive::Extract::_unzip('Archive::Extract=HASH(0x966eac)') called at ../lib/Archive/Extract.pm line 275
# Archive::Extract::extract('Archive::Extract=HASH(0x966eac)','to','/Users/kane/sources/p4/other/archive-extract/t/out') called at t/01_Archive-Extract.t line 180
#BEGIN { $SIG{__WARN__} = sub { require Carp; Carp::cluck(@_) } };
if ((IS_WIN32 or IS_CYGWIN) && ! $ENV{PERL_CORE}) {
diag( "Older versions of Archive::Zip may cause File::Spec warnings" );
diag( "See bug #19713 in rt.cpan.org. It is safe to ignore them" );
}
my $Debug = $ARGV[0] ? 1 : 0;
my $Me = basename( $0 );
my $Class = 'Archive::Extract';
my $Self = File::Spec->rel2abs(
IS_WIN32 ? &Win32::GetShortPathName( cwd() ) : cwd()
);
my $SrcDir = File::Spec->catdir( $Self,'src' );
my $OutDir = File::Spec->catdir( $Self,'out' );
use_ok($Class);
### set verbose if debug is on ###
### stupid stupid silly stupid warnings silly! ###
$Archive::Extract::VERBOSE = $Archive::Extract::VERBOSE = $Debug;
$Archive::Extract::WARN = $Archive::Extract::WARN = $Debug ? 1 : 0;
my $tmpl = {
### plain files
'x.bz2' => { programs => [qw[bunzip2]],
modules => [qw[IO::Uncompress::Bunzip2]],
method => 'is_bz2',
outfile => 'a',
},
'x.tgz' => { programs => [qw[gzip tar]],
modules => [qw[Archive::Tar IO::Zlib]],
method => 'is_tgz',
outfile => 'a',
},
'x.tar.gz' => { programs => [qw[gzip tar]],
modules => [qw[Archive::Tar IO::Zlib]],
method => 'is_tgz',
outfile => 'a',
},
'x.tar' => { programs => [qw[tar]],
modules => [qw[Archive::Tar]],
method => 'is_tar',
outfile => 'a',
},
'x.gz' => { programs => [qw[gzip]],
modules => [qw[Compress::Zlib]],
method => 'is_gz',
outfile => 'a',
},
'x.Z' => { programs => [qw[uncompress]],
modules => [qw[Compress::Zlib]],
method => 'is_Z',
outfile => 'a',
},
'x.zip' => { programs => [qw[unzip]],
modules => [qw[Archive::Zip]],
method => 'is_zip',
outfile => 'a',
},
'x.jar' => { programs => [qw[unzip]],
modules => [qw[Archive::Zip]],
method => 'is_zip',
outfile => 'a',
},
'x.par' => { programs => [qw[unzip]],
modules => [qw[Archive::Zip]],
method => 'is_zip',
outfile => 'a',
},
### with a directory
'y.tbz' => { programs => [qw[bunzip2 tar]],
modules => [qw[Archive::Tar
IO::Uncompress::Bunzip2]],
method => 'is_tbz',
outfile => 'z',
outdir => 'y',
},
'y.tar.bz2' => { programs => [qw[bunzip2 tar]],
modules => [qw[Archive::Tar
IO::Uncompress::Bunzip2]],
method => 'is_tbz',
outfile => 'z',
outdir => 'y'
},
'y.tgz' => { programs => [qw[gzip tar]],
modules => [qw[Archive::Tar IO::Zlib]],
method => 'is_tgz',
outfile => 'z',
outdir => 'y'
},
'y.tar.gz' => { programs => [qw[gzip tar]],
modules => [qw[Archive::Tar IO::Zlib]],
method => 'is_tgz',
outfile => 'z',
outdir => 'y'
},
'y.tar' => { programs => [qw[tar]],
modules => [qw[Archive::Tar]],
method => 'is_tar',
outfile => 'z',
outdir => 'y'
},
'y.zip' => { programs => [qw[unzip]],
modules => [qw[Archive::Zip]],
method => 'is_zip',
outfile => 'z',
outdir => 'y'
},
'y.par' => { programs => [qw[unzip]],
modules => [qw[Archive::Zip]],
method => 'is_zip',
outfile => 'z',
outdir => 'y'
},
'y.jar' => { programs => [qw[unzip]],
modules => [qw[Archive::Zip]],
method => 'is_zip',
outfile => 'z',
outdir => 'y'
},
### with non-same top dir
'double_dir.zip' => {
programs => [qw[unzip]],
modules => [qw[Archive::Zip]],
method => 'is_zip',
outfile => 'w',
outdir => 'x'
},
};
### show us the tools IPC::Cmd will use to run binary programs
if( $Debug ) {
diag( "IPC::Run enabled: $IPC::Cmd::USE_IPC_RUN " );
diag( "IPC::Run available: " . IPC::Cmd->can_use_ipc_run );
diag( "IPC::Run vesion: $IPC::Run::VERSION" );
diag( "IPC::Open3 enabled: $IPC::Cmd::USE_IPC_OPEN3 " );
diag( "IPC::Open3 available: " . IPC::Cmd->can_use_ipc_open3 );
diag( "IPC::Open3 vesion: $IPC::Open3::VERSION" );
}
### test all type specifications to new()
### this tests bug #24578: Wrong check for `type' argument
{ my $meth = 'types';
can_ok( $Class, $meth );
my @types = $Class->$meth;
ok( scalar(@types), " Got a list of types" );
for my $type ( @types ) {
my $obj = $Class->new( archive => $Me, type => $type );
ok( $obj, " Object created based on '$type'" );
ok( !$obj->error, " No error logged" );
}
}
### XXX whitebox test
### test __get_extract_dir
SKIP: { my $meth = '__get_extract_dir';
### get the right separator -- File::Spec does clean ups for
### paths, so we need to join ourselves.
my $sep = [ split '', File::Spec->catfile( 'a', 'b' ) ]->[1];
### bug #23999: Attempt to generate Makefile.PL gone awry
### showed that dirs in the style of './dir/' were reported
### to be unpacked in '.' rather than in 'dir'. here we test
### for this.
for my $prefix ( '', '.' ) {
skip "Prepending ./ to a valid path doesn't give you another valid path on VMS", 2
if IS_VMS && length($prefix);
my $dir = basename( $SrcDir );
### build a list like [dir, dir/file] and [./dir ./dir/file]
### where the dir and file actually exist, which is important
### for the method call
my @files = map { length $prefix
? join $sep, $prefix, $_
: $_
} $dir, File::Spec->catfile( $dir, [keys %$tmpl]->[0] );
my $res = $Class->$meth( \@files );
$res = &Win32::GetShortPathName( $res ) if IS_WIN32;
ok( $res, "Found extraction dir '$res'" );
is( $res, $SrcDir, " Is expected dir '$SrcDir'" );
}
}
for my $switch (0,1) {
local $Archive::Extract::PREFER_BIN = $switch;
diag("Running extract with PREFER_BIN = $Archive::Extract::PREFER_BIN")
if $Debug;
for my $archive (keys %$tmpl) {
diag("Extracting $archive") if $Debug;
### check first if we can do the proper
my $ae = Archive::Extract->new(
archive => File::Spec->catfile($SrcDir,$archive) );
isa_ok( $ae, $Class );
my $method = $tmpl->{$archive}->{method};
ok( $ae->$method(), "Archive type recognized properly" );
### 10 tests from here on down ###
SKIP: {
my $file = $tmpl->{$archive}->{outfile};
my $dir = $tmpl->{$archive}->{outdir}; # can be undef
my $rel_path = File::Spec->catfile( grep { defined } $dir, $file );
my $abs_path = File::Spec->catfile( $OutDir, $rel_path );
my $abs_dir = File::Spec->catdir(
grep { defined } $OutDir, $dir );
my $nix_path = File::Spec::Unix->catfile(
grep { defined } $dir, $file );
### check if we can run this test ###
my $pgm_fail; my $mod_fail;
for my $pgm ( @{$tmpl->{$archive}->{programs}} ) {
### no binary extract method
$pgm_fail++, next unless $pgm;
### we dont have the program
$pgm_fail++ unless $Archive::Extract::PROGRAMS->{$pgm} &&
$Archive::Extract::PROGRAMS->{$pgm};
}
for my $mod ( @{$tmpl->{$archive}->{modules}} ) {
### no module extract method
$mod_fail++, next unless $mod;
### we dont have the module
$mod_fail++ unless check_install( module => $mod );
}
### where to extract to -- try both dir and file for gz files
### XXX test me!
#my @outs = $ae->is_gz ? ($abs_path, $OutDir) : ($OutDir);
my @outs = $ae->is_gz || $ae->is_bz2 || $ae->is_Z
? ($abs_path)
: ($OutDir);
skip "No binaries or modules to extract ".$archive,
(10 * scalar @outs) if $mod_fail && $pgm_fail;
### we dont warnings spewed about missing modules, that might
### be a problem...
local $IPC::Cmd::WARN = 0;
local $IPC::Cmd::WARN = 0;
for my $use_buffer ( IPC::Cmd->can_capture_buffer , 0 ) {
### test buffers ###
my $turn_off = !$use_buffer && !$pgm_fail &&
$Archive::Extract::PREFER_BIN;
### whitebox test ###
### stupid warnings ###
local $IPC::Cmd::USE_IPC_RUN = 0 if $turn_off;
local $IPC::Cmd::USE_IPC_RUN = 0 if $turn_off;
local $IPC::Cmd::USE_IPC_OPEN3 = 0 if $turn_off;
local $IPC::Cmd::USE_IPC_OPEN3 = 0 if $turn_off;
### try extracting ###
for my $to ( @outs ) {
diag("Extracting to: $to") if $Debug;
diag("Buffers enabled: ".!$turn_off) if $Debug;
my $rv = $ae->extract( to => $to );
ok( $rv, "extract() for '$archive' reports success");
diag("Extractor was: " . $ae->_extractor) if $Debug;
SKIP: {
my $re = qr/^No buffer captured/;
my $err = $ae->error || '';
### skip buffer tests if we dont have buffers or
### explicitly turned them off
skip "No buffers available", 7,
if ( $turn_off || !IPC::Cmd->can_capture_buffer)
&& $err =~ $re;
### if we /should/ have buffers, there should be
### no errors complaining we dont have them...
unlike( $err, $re,
"No errors capturing buffers" );
### might be 1 or 2, depending wether we extracted
### a dir too
my $file_cnt = grep { defined } $file, $dir;
is( scalar @{ $ae->files || []}, $file_cnt,
"Found correct number of output files" );
is( $ae->files->[-1], $nix_path,
"Found correct output file '$nix_path'" );
ok( -e $abs_path,
"Output file '$abs_path' exists" );
ok( $ae->extract_path,
"Extract dir found" );
ok( -d $ae->extract_path,
"Extract dir exists" );
is( $ae->extract_path, $abs_dir,
"Extract dir is expected '$abs_dir'" );
}
SKIP: {
skip "Unlink tests are unreliable on Win32", 3 if IS_WIN32;
1 while unlink $abs_path;
ok( !(-e $abs_path), "Output file successfully removed" );
SKIP: {
skip "No extract path captured, can't remove paths", 2
unless $ae->extract_path;
### if something went wrong with determining the out
### path, don't go deleting stuff.. might be Really Bad
my $out_re = quotemeta( $OutDir );
if( $ae->extract_path !~ /^$out_re/ ) {
ok( 0, "Extractpath WRONG (".$ae->extract_path.")");
skip( "Unsafe operation -- skip cleanup!!!" ), 1;
}
eval { rmtree( $ae->extract_path ) };
ok( !$@, " rmtree gave no error" );
ok( !(-d $ae->extract_path ),
" Extract dir succesfully removed" );
}
}
}
}
} }
}
|