1BEGIN { chdir 't' if -d 't' };
2
3use strict;
4use lib '../lib';
5
6use Test::More 'no_plan';
7
8use Cwd             qw[cwd];
9use File::Basename  qw[basename];
10use File::Path      qw[rmtree];
11use Data::Dumper;
12
13use_ok('File::Fetch');
14
15### optionally set debugging ###
16$File::Fetch::DEBUG = $File::Fetch::DEBUG   = 1 if $ARGV[0];
17$IPC::Cmd::DEBUG    = $IPC::Cmd::DEBUG      = 1 if $ARGV[0];
18
19$File::Fetch::FORCEIPV4=1;
20
21unless( $ENV{PERL_CORE} ) {
22    warn qq[
23
24####################### NOTE ##############################
25
26Some of these tests assume you are connected to the
27internet. If you are not, or if certain protocols or hosts
28are blocked and/or firewalled, these tests could fail due
29to no fault of the module itself.
30
31###########################################################
32
33];
34
35    sleep 3 unless $File::Fetch::DEBUG;
36}
37
38### show us the tools IPC::Cmd will use to run binary programs
39if( $File::Fetch::DEBUG ) {
40    ### stupid 'used only once' warnings ;(
41    diag( "IPC::Run enabled: " .
42            $IPC::Cmd::USE_IPC_RUN || $IPC::Cmd::USE_IPC_RUN );
43    diag( "IPC::Run available: " . IPC::Cmd->can_use_ipc_run );
44    diag( "IPC::Run vesion: $IPC::Run::VERSION" );
45    diag( "IPC::Open3 enabled: " .
46            $IPC::Cmd::USE_IPC_OPEN3 || $IPC::Cmd::USE_IPC_OPEN3 );
47    diag( "IPC::Open3 available: " . IPC::Cmd->can_use_ipc_open3 );
48    diag( "IPC::Open3 vesion: $IPC::Open3::VERSION" );
49}
50
51### Heuristics
52my %heuristics = map { $_ => 1 } qw(http ftp rsync file git);
53### _parse_uri tests
54### these go on all platforms
55my @map = (
56    {   uri     => 'ftp://cpan.org/pub/mirror/index.txt',
57        scheme  => 'ftp',
58        host    => 'cpan.org',
59        path    => '/pub/mirror/',
60        file    => 'index.txt'
61    },
62    {	uri	    => 'rsync://cpan.pair.com/CPAN/MIRRORING.FROM',
63        scheme	=> 'rsync',
64        host	=> 'cpan.pair.com',
65        path	=> '/CPAN/',
66        file	=> 'MIRRORING.FROM',
67    },
68    {	uri	    => 'git://github.com/Perl-Toolchain-Gang/file-fetch.git',
69        scheme	=> 'git',
70        host	=> 'github.com',
71        path	=> '/Perl-Toolchain-Gang/',
72        file	=> 'file-fetch.git',
73    },
74    {   uri     => 'http://localhost/tmp/index.txt',
75        scheme  => 'http',
76        host    => 'localhost',          # host is empty only on 'file://'
77        path    => '/tmp/',
78        file    => 'index.txt',
79    },
80
81    ### only test host part, the rest is OS dependant
82    {   uri     => 'file://localhost/tmp/index.txt',
83        host    => '',                  # host should be empty on 'file://'
84    },
85);
86
87### these only if we're not on win32/vms
88push @map, (
89    {   uri     => 'file:///usr/local/tmp/foo.txt',
90        scheme  => 'file',
91        host    => '',
92        path    => '/usr/local/tmp/',
93        file    => 'foo.txt',
94    },
95    {   uri     => 'file://hostname/tmp/foo.txt',
96        scheme  => 'file',
97        host    => 'hostname',
98        path    => '/tmp/',
99        file    => 'foo.txt',
100    },
101) if not &File::Fetch::ON_WIN and not &File::Fetch::ON_VMS;
102
103### these only on win32
104push @map, (
105    {   uri     => 'file:////hostname/share/tmp/foo.txt',
106        scheme  => 'file',
107        host    => 'hostname',
108        share   => 'share',
109        path    => '/tmp/',
110        file    => 'foo.txt',
111    },
112    {   uri     => 'file:///D:/tmp/foo.txt',
113        scheme  => 'file',
114        host    => '',
115        vol     => 'D:',
116        path    => '/tmp/',
117        file    => 'foo.txt',
118    },
119    {   uri     => 'file:///D|/tmp/foo.txt',
120        scheme  => 'file',
121        host    => '',
122        vol     => 'D:',
123        path    => '/tmp/',
124        file    => 'foo.txt',
125    },
126) if &File::Fetch::ON_WIN;
127
128
129### sanity tests
130{
131    no warnings;
132    like( $File::Fetch::USER_AGENT, qr/$File::Fetch::VERSION/,
133                                "User agent contains version" );
134    like( $File::Fetch::FROM_EMAIL, qr/@/,
135                                q[Email contains '@'] );
136}
137
138### parse uri tests ###
139for my $entry (@map ) {
140    my $uri = $entry->{'uri'};
141
142    my $href = File::Fetch->_parse_uri( $uri );
143    ok( $href,  "Able to parse uri '$uri'" );
144
145    for my $key ( sort keys %$entry ) {
146        is( $href->{$key}, $entry->{$key},
147                "   '$key' ok ($entry->{$key}) for $uri");
148    }
149}
150
151### File::Fetch->new tests ###
152for my $entry (@map) {
153    my $ff = File::Fetch->new( uri => $entry->{uri} );
154
155    ok( $ff,                    "Object for uri '$entry->{uri}'" );
156    isa_ok( $ff, "File::Fetch", "   Object" );
157
158    for my $acc ( keys %$entry ) {
159        is( $ff->$acc(), $entry->{$acc},
160                                "   Accessor '$acc' ok ($entry->{$acc})" );
161    }
162}
163
164### fetch() tests ###
165
166### file:// tests ###
167{
168    my $prefix = &File::Fetch::ON_UNIX ? 'file://' : 'file:///';
169    my $uri = $prefix . cwd() .'/'. basename($0);
170
171    for (qw[lwp lftp file]) {
172        _fetch_uri( file => $uri, $_ );
173    }
174}
175
176### Heuristics
177{
178  require IO::Socket::INET;
179  my $sock = IO::Socket::INET->new( PeerAddr => 'mirror.bytemark.co.uk', PeerPort => 21, Timeout => 20 )
180     or $heuristics{ftp} = 0;
181}
182
183### ftp:// tests ###
184{   my $uri = 'ftp://mirror.bytemark.co.uk/CPAN/index.html';
185    for (qw[wget curl lftp fetch ncftp]) {
186
187        ### STUPID STUPID warnings ###
188        next if $_ eq 'ncftp' and $File::Fetch::FTP_PASSIVE
189                              and $File::Fetch::FTP_PASSIVE;
190
191        _fetch_uri( ftp => $uri, $_ );
192    }
193}
194
195### Heuristics
196{
197  require IO::Socket::INET;
198  my $sock = IO::Socket::INET->new( PeerAddr => 'httpbin.org', PeerPort => 80, Timeout => 20 )
199     or $heuristics{http} = 0;
200}
201
202### http:// tests ###
203{   for my $uri ( 'http://httpbin.org/html',
204                  'http://httpbin.org/response-headers?q=1',
205                  'http://httpbin.org/response-headers?q=1&y=2',
206                  #'http://www.cpan.org/index.html?q=1&y=2',
207                  #'http://user:passwd@httpbin.org/basic-auth/user/passwd',
208    ) {
209        for (qw[lwp httptiny wget curl lftp fetch lynx httplite iosock]) {
210            _fetch_uri( http => $uri, $_ );
211        }
212    }
213}
214
215### Heuristics
216{
217  require IO::Socket::INET;
218  my $sock = IO::Socket::INET->new( PeerAddr => 'cpan.pair.com', PeerPort => 873, Timeout => 20 )
219     or $heuristics{rsync} = 0;
220}
221
222### rsync:// tests ###
223{   my $uri = 'rsync://cpan.pair.com/CPAN/MIRRORING.FROM';
224
225    for (qw[rsync]) {
226        _fetch_uri( rsync => $uri, $_ );
227    }
228}
229
230### Heuristics
231{
232  require IO::Socket::INET;
233  my $sock = IO::Socket::INET->new( PeerAddr => 'github.com', PeerPort => 9418, Timeout => 20 )
234     or $heuristics{git} = 0;
235}
236
237### git:// tests ###
238{   my $uri = 'https://github.com/Perl-Toolchain-Gang/file-fetch.git';
239
240    for (qw[git]) {
241        local $ENV{GIT_CONFIG_NOSYSTEM} = 1;
242        local $ENV{XDG_CONFIG_HOME};
243        local $ENV{HOME};
244        _fetch_uri( git => $uri, $_ );
245    }
246}
247
248sub _fetch_uri {
249    my $type    = shift;
250    my $uri     = shift;
251    my $method  = shift or return;
252
253    SKIP: {
254        skip "'$method' fetching tests disabled under perl core", 4
255                if $ENV{PERL_CORE};
256
257        skip "'$type' fetching tests disabled due to heuristic failure", 4
258                unless $heuristics{ $type };
259
260        ### stupid warnings ###
261        $File::Fetch::METHODS =
262        $File::Fetch::METHODS = { $type => [$method] };
263
264        ### fetch regularly
265        my $ff  = File::Fetch->new( uri => $uri );
266
267        ok( $ff,                "FF object for $uri (fetch with $method)" );
268
269        for my $to ( 'tmp', do { \my $o } ) { SKIP: {
270
271
272            my $how     = ref $to && $type ne 'git' ? 'slurp' : 'file';
273            my $skip    = ref $to ? 4       : 3;
274
275            ok( 1,              "   Fetching '$uri' in $how mode" );
276
277            my $file = $ff->fetch( to => $to );
278
279            skip "You do not have '$method' installed/available", $skip
280                if $File::Fetch::METHOD_FAIL->{$method} &&
281                   $File::Fetch::METHOD_FAIL->{$method};
282
283            ### if the file wasn't fetched, it may be a network/firewall issue
284            skip "Fetch failed; no network connectivity for '$type'?", $skip
285                unless $file;
286
287            ok( $file,          "   File ($file) fetched with $method ($uri)" );
288
289            ### check we got some contents if we were meant to slurp
290            if( ref $to && $type ne 'git' ) {
291                ok( $$to,       "   Contents slurped" );
292            }
293
294            ok( $file && -s $file,
295                                "   File has size" );
296            is( $file && basename($file), $ff->output_file,
297                                "   File has expected name" );
298
299            rmtree $file;
300        }}
301    }
302}
303
304
305
306
307
308
309
310
311