1b39c5158Smillert#!/usr/bin/perl
2b39c5158Smillert
3b39c5158SmillertBEGIN {
4b39c5158Smillert    unshift @INC, 't/lib';
5b39c5158Smillert}
6b39c5158Smillertchdir 't';
7b39c5158Smillert
8b39c5158Smillertuse strict;
9*256a93a4Safresh1use warnings;
10b39c5158Smillertuse Test::More;
11b39c5158Smillert
12b39c5158SmillertBEGIN {
13898184e3Ssthen    if ($^O !~ /MSWin32/i) {
14b39c5158Smillert        plan skip_all => 'This is not Win32';
15b39c5158Smillert    }
16b39c5158Smillert}
175759b3d2Safresh1plan 'no_plan'; # BinGOs says there are 63 but I can only see 62
18b39c5158Smillert
19b39c5158Smillertuse Config;
20b39c5158Smillertuse File::Spec;
21b39c5158Smillertuse File::Basename;
22b39c5158Smillertuse ExtUtils::MM;
23b39c5158Smillert
24b39c5158Smillertrequire_ok( 'ExtUtils::MM_Win32' );
25b39c5158Smillert
26b39c5158Smillert# Dummy MM object until we have a real MM init method.
27b39c5158Smillertmy $MM = bless {
28b39c5158Smillert                DIR     => [],
29b39c5158Smillert                NOECHO  => '@',
30b39c5158Smillert                XS      => {},
31b39c5158Smillert                MAKEFILE => 'Makefile',
32b39c5158Smillert                RM_RF   => 'rm -rf',
33b39c5158Smillert                MV      => 'mv',
34b39c5158Smillert                MAKE    => $Config{make}
35b39c5158Smillert               }, 'MM';
36b39c5158Smillert
37b39c5158Smillert
38b39c5158Smillert# replace_manpage_separator() => tr|/|.|s ?
39b39c5158Smillert{
40b39c5158Smillert    my $man = 'a/path/to//something';
41b39c5158Smillert    ( my $replaced = $man ) =~ tr|/|.|s;
42b39c5158Smillert    is( $MM->replace_manpage_separator( $man ),
43b39c5158Smillert        $replaced, 'replace_manpage_separator()' );
44b39c5158Smillert}
45b39c5158Smillert
46b39c5158Smillert# maybe_command()
47b39c5158SmillertSKIP: {
48b39c5158Smillert    skip( '$ENV{COMSPEC} not set', 2 )
49b39c5158Smillert        unless $ENV{COMSPEC} =~ m!((?:[a-z]:)?[^|<>]+)!i;
50b39c5158Smillert    my $comspec = $1;
51b39c5158Smillert    is( $MM->maybe_command( $comspec ),
52b39c5158Smillert        $comspec, 'COMSPEC is a maybe_command()' );
53b39c5158Smillert    ( my $comspec2 = $comspec ) =~ s|\..{3}$||;
54b39c5158Smillert    like( $MM->maybe_command( $comspec2 ),
55b39c5158Smillert          qr/\Q$comspec/i,
56b39c5158Smillert          'maybe_command() without extension' );
57b39c5158Smillert}
58b39c5158Smillert
59b39c5158Smillertmy $had_pathext = exists $ENV{PATHEXT};
60b39c5158Smillert{
61b39c5158Smillert    local $ENV{PATHEXT} = '.exe';
62b39c5158Smillert    ok( ! $MM->maybe_command( 'not_a_command.com' ),
63b39c5158Smillert        'not a maybe_command()' );
64b39c5158Smillert}
65b39c5158Smillert# Bug in Perl.  local $ENV{FOO} won't delete the key afterward.
66b39c5158Smillertdelete $ENV{PATHEXT} unless $had_pathext;
67b39c5158Smillert
68b39c5158Smillert# file_name_is_absolute() [Does not support UNC-paths]
69b39c5158Smillert{
70b39c5158Smillert    ok( $MM->file_name_is_absolute( 'C:/' ),
71b39c5158Smillert        'file_name_is_absolute()' );
72b39c5158Smillert    ok( ! $MM->file_name_is_absolute( 'some/path/' ),
73b39c5158Smillert        'not file_name_is_absolute()' );
74b39c5158Smillert
75b39c5158Smillert}
76b39c5158Smillert
77b39c5158Smillert# find_perl()
78b39c5158Smillert# Should be able to find running perl... $^X is OK on Win32
79b39c5158Smillert{
80b39c5158Smillert    my $my_perl = $1 if $^X  =~ /(.*)/; # are we in -T or -t?
81b39c5158Smillert    my( $perl, $path ) = fileparse( $my_perl );
82b39c5158Smillert    like( $MM->find_perl( $], [ $perl ], [ $path ], 0 ),
83b39c5158Smillert          qr/^\Q$my_perl\E$/i, 'find_perl() finds this perl' );
84b39c5158Smillert}
85b39c5158Smillert
86b39c5158Smillert# catdir() (calls MM_Win32->canonpath)
87b39c5158Smillert{
88b39c5158Smillert    my @path_eg = qw( c: trick dir/now_OK );
89b39c5158Smillert
90b39c5158Smillert    is( $MM->catdir( @path_eg ),
91b39c5158Smillert         'C:\\trick\\dir\\now_OK', 'catdir()' );
92b39c5158Smillert    is( $MM->catdir( @path_eg ),
93b39c5158Smillert        File::Spec->catdir( @path_eg ),
94b39c5158Smillert        'catdir() eq File::Spec->catdir()' );
95b39c5158Smillert
96b39c5158Smillert# catfile() (calls MM_Win32->catdir)
97b39c5158Smillert    push @path_eg, 'file.ext';
98b39c5158Smillert
99b39c5158Smillert    is( $MM->catfile( @path_eg ),
100b39c5158Smillert        'C:\\trick\\dir\\now_OK\\file.ext', 'catfile()' );
101b39c5158Smillert
102b39c5158Smillert    is( $MM->catfile( @path_eg ),
103b39c5158Smillert        File::Spec->catfile( @path_eg ),
104b39c5158Smillert        'catfile() eq File::Spec->catfile()' );
105b39c5158Smillert}
106b39c5158Smillert
107898184e3Ssthen# init_tools(): check if all keys are created and set?
108898184e3Ssthennote "init_tools creates expected keys"; {
109898184e3Ssthen    my $mm_w32 = bless( { BASEEXT => 'Foo', MAKE => $Config{make} }, 'MM' );
110898184e3Ssthen    $mm_w32->init_tools();
111898184e3Ssthen    my @keys = qw( TOUCH CHMOD CP RM_F RM_RF MV NOOP NOECHO ECHO ECHO_N TEST_F DEV_NULL );
112898184e3Ssthen    for my $key ( @keys ) {
113898184e3Ssthen        ok( $mm_w32->{ $key }, "init_tools: $key" );
114898184e3Ssthen    }
115898184e3Ssthen}
116898184e3Ssthen
117898184e3Ssthennote "init_others creates expected keys"; {
118898184e3Ssthen    my $mm_w32 = bless( { BASEEXT => 'Foo', MAKE => $Config{make} }, 'MM' );
119b39c5158Smillert    $mm_w32->init_others();
120898184e3Ssthen    my @keys = qw( LD AR LDLOADLIBS );
121b39c5158Smillert    for my $key ( @keys ) {
122b39c5158Smillert        ok( $mm_w32->{ $key }, "init_others: $key" );
123b39c5158Smillert    }
124b39c5158Smillert}
125b39c5158Smillert
126b39c5158Smillert# constants()
127b39c5158Smillert# XXX this test is probably useless now that we can call individual
128b39c5158Smillert# init_* methods and check the keys in $mm_w32 directly
129b39c5158Smillert{
130b39c5158Smillert    my $mm_w32 = bless {
131b39c5158Smillert        NAME         => 'TestMM_Win32',
132b39c5158Smillert        VERSION      => '1.00',
133b39c5158Smillert        PM           => { 'MM_Win32.pm' => 1 },
134898184e3Ssthen        MAKE         => $Config{make},
135b39c5158Smillert    }, 'MM';
136b39c5158Smillert
137b39c5158Smillert    # XXX Hack until we have a proper init method.
138b39c5158Smillert    # Flesh out some necessary keys in the MM object.
139b39c5158Smillert    @{$mm_w32}{qw(XS MAN1PODS MAN3PODS)} = ({}) x 3;
140b39c5158Smillert    @{$mm_w32}{qw(C O_FILES H)}          = ([]) x 3;
141b39c5158Smillert    @{$mm_w32}{qw(PARENT_NAME)}          = ('') x 3;
142b39c5158Smillert    $mm_w32->{FULLEXT} = 'TestMM_Win32';
143b39c5158Smillert    $mm_w32->{BASEEXT} = 'TestMM_Win32';
144b39c5158Smillert
145b39c5158Smillert    $mm_w32->init_VERSION;
146b39c5158Smillert    $mm_w32->init_linker;
147b39c5158Smillert    $mm_w32->init_INST;
148b39c5158Smillert    $mm_w32->init_xs;
149b39c5158Smillert
150b39c5158Smillert    my $s_PM = join( " \\\n\t", sort keys %{$mm_w32->{PM}} );
151b39c5158Smillert
152b39c5158Smillert    my $constants = $mm_w32->constants;
153b39c5158Smillert
154b39c5158Smillert    foreach my $regex (
155b39c5158Smillert         qr|^NAME       \s* = \s* TestMM_Win32 \s* $|xms,
156b39c5158Smillert         qr|^VERSION    \s* = \s* 1\.00 \s* $|xms,
157b39c5158Smillert         qr|^MAKEMAKER  \s* = \s* \Q$INC{'ExtUtils/MakeMaker.pm'}\E \s* $|xms,
158b39c5158Smillert         qr|^MM_VERSION \s* = \s* \Q$ExtUtils::MakeMaker::VERSION\E \s* $|xms,
159b39c5158Smillert         qr|^TO_INST_PM \s* = \s* \Q$s_PM\E \s* $|xms,
160b39c5158Smillert        )
161b39c5158Smillert    {
162b39c5158Smillert        like( $constants, $regex, 'constants() check' );
163b39c5158Smillert    }
164b39c5158Smillert}
165b39c5158Smillert
166b39c5158Smillert# path()
167b39c5158Smillert{
168b39c5158Smillert    ok( eq_array( [ $MM->path() ], [ File::Spec->path ] ),
169b39c5158Smillert        'path() [preset]' );
170b39c5158Smillert}
171b39c5158Smillert
172b39c5158Smillert# static_lib() should look into that
173b39c5158Smillert# dynamic_bs() should look into that
174b39c5158Smillert# dynamic_lib() should look into that
175b39c5158Smillert
176b39c5158Smillert# init_linker
177b39c5158Smillert{
178b39c5158Smillert    my $libperl = File::Spec->catfile('$(PERL_INC)',
179b39c5158Smillert                                      $Config{libperl} || 'libperl.a');
180b39c5158Smillert    my $export  = '$(BASEEXT).def';
181b39c5158Smillert    my $after   = '';
182b39c5158Smillert    $MM->init_linker;
183b39c5158Smillert
184b39c5158Smillert    is( $MM->{PERL_ARCHIVE},        $libperl,   'PERL_ARCHIVE' );
185b39c5158Smillert    is( $MM->{PERL_ARCHIVE_AFTER},  $after,     'PERL_ARCHIVE_AFTER' );
186b39c5158Smillert    is( $MM->{EXPORT_LIST},         $export,    'EXPORT_LIST' );
187b39c5158Smillert}
188b39c5158Smillert
189b39c5158Smillert# canonpath()
190b39c5158Smillert{
191b39c5158Smillert    my $path = 'c:\\Program Files/SomeApp\\Progje.exe';
192b39c5158Smillert    is( $MM->canonpath( $path ), File::Spec->canonpath( $path ),
193b39c5158Smillert        'canonpath() eq File::Spec->canonpath' );
194b39c5158Smillert}
195b39c5158Smillert
196b39c5158Smillert# perl_script()
197b39c5158Smillertmy $script_ext  = '';
198b39c5158Smillertmy $script_name = 'mm_w32tmp';
199b39c5158SmillertSKIP: {
200b39c5158Smillert    local *SCRIPT;
201b39c5158Smillert    skip( "Can't create temp file: $!", 4 )
202b39c5158Smillert        unless open SCRIPT, "> $script_name";
203b39c5158Smillert    print SCRIPT <<'EOSCRIPT';
204b39c5158Smillert#! perl
205b39c5158Smillert__END__
206b39c5158SmillertEOSCRIPT
207b39c5158Smillert    skip( "Can't write to temp file: $!", 4 )
208b39c5158Smillert        unless close SCRIPT;
209b39c5158Smillert    # now start tests:
210b39c5158Smillert    is( $MM->perl_script( $script_name ),
211b39c5158Smillert        "${script_name}$script_ext", "perl_script ($script_ext)" );
212b39c5158Smillert
213b39c5158Smillert    skip( "Can't rename temp file: $!", 3 )
214b39c5158Smillert        unless rename $script_name, "${script_name}.pl";
215b39c5158Smillert    $script_ext = '.pl';
216b39c5158Smillert    is( $MM->perl_script( $script_name ),
217b39c5158Smillert        "${script_name}$script_ext", "perl_script ($script_ext)" );
218b39c5158Smillert
219b39c5158Smillert    skip( "Can't rename temp file: $!", 2 )
220b39c5158Smillert        unless rename "${script_name}$script_ext", "${script_name}.bat";
221b39c5158Smillert    $script_ext = '.bat';
222b39c5158Smillert    is( $MM->perl_script( $script_name ),
223b39c5158Smillert        "${script_name}$script_ext", "perl_script ($script_ext)" );
224b39c5158Smillert
225b39c5158Smillert    skip( "Can't rename temp file: $!", 1 )
226b39c5158Smillert        unless rename "${script_name}$script_ext", "${script_name}.noscript";
227b39c5158Smillert    $script_ext = '.noscript';
228b39c5158Smillert
229b39c5158Smillert    isnt( $MM->perl_script( $script_name ),
230b39c5158Smillert          "${script_name}$script_ext",
231b39c5158Smillert          "not a perl_script anymore ($script_ext)" );
232b39c5158Smillert    is( $MM->perl_script( $script_name ), undef,
233b39c5158Smillert        "perl_script ($script_ext) returns empty" );
234b39c5158Smillert}
235b39c5158Smillertunlink "${script_name}$script_ext" if -f "${script_name}$script_ext";
236b39c5158Smillert
237b39c5158Smillert# is_make_type()
238b39c5158Smillert{
239b39c5158Smillert    # Check for literal nmake
240b39c5158Smillert    SKIP: {
241b39c5158Smillert        skip("Not using 'nmake'", 2) unless $Config{make} eq 'nmake';
242b39c5158Smillert        ok(   $MM->is_make_type('nmake'), '->is_make_type(nmake) true'  );
243b39c5158Smillert        ok( ! $MM->is_make_type('dmake'), '->is_make_type(dmake) false' );
244b39c5158Smillert    }
245b39c5158Smillert
246b39c5158Smillert    # Check for literal nmake
247b39c5158Smillert    SKIP: {
248b39c5158Smillert        skip("Not using /nmake/", 2) unless $Config{make} =~ /nmake/;
249b39c5158Smillert        ok(   $MM->is_make_type('nmake'), '->is_make_type(nmake) true'  );
250b39c5158Smillert        ok( ! $MM->is_make_type('dmake'), '->is_make_type(dmake) false' );
251b39c5158Smillert    }
252b39c5158Smillert
253b39c5158Smillert    # Check for literal dmake
254b39c5158Smillert    SKIP: {
255b39c5158Smillert        skip("Not using 'dmake'", 2) unless $Config{make} eq 'dmake';
256b39c5158Smillert        ok(   $MM->is_make_type('dmake'), '->is_make_type(dmake) true'  );
257b39c5158Smillert        ok( ! $MM->is_make_type('nmake'), '->is_make_type(nmake) false' );
258b39c5158Smillert    }
259b39c5158Smillert
260b39c5158Smillert    # Check for literal dmake
261b39c5158Smillert    SKIP: {
262b39c5158Smillert        skip("Not using /dmake/", 2) unless $Config{make} =~ /dmake/;
263b39c5158Smillert        ok(   $MM->is_make_type('dmake'), '->is_make_type(dmake) true'  );
264b39c5158Smillert        ok( ! $MM->is_make_type('nmake'), '->is_make_type(nmake) false' );
265b39c5158Smillert    }
266b39c5158Smillert
267b39c5158Smillert}
268b39c5158Smillert
269b39c5158Smillert# xs_o() should look into that
270b39c5158Smillert# top_targets() should look into that
271b39c5158Smillert
272b39c5158Smillert# dist_ci() should look into that
273b39c5158Smillert# dist_core() should look into that
274b39c5158Smillert
275898184e3Ssthen# _identify_compiler_environment()
276898184e3Ssthen{
277898184e3Ssthen    sub _run_cc_id {
278898184e3Ssthen        my ( $config ) = @_;
279898184e3Ssthen
280898184e3Ssthen        $config->{cc} ||= '';
281898184e3Ssthen
282898184e3Ssthen        my @cc_env = ExtUtils::MM_Win32::_identify_compiler_environment( $config );
283898184e3Ssthen
2845759b3d2Safresh1        my %cc_env = ( BORLAND => $cc_env[0], GCC => $cc_env[1], MSVC => $cc_env[2] );
285898184e3Ssthen
286898184e3Ssthen        return \%cc_env;
287898184e3Ssthen    }
288898184e3Ssthen
289898184e3Ssthen    sub _check_cc_id_value {
290898184e3Ssthen        my ( $test ) = @_;
291898184e3Ssthen
292898184e3Ssthen        my $res = _run_cc_id( $test->{config} );
293898184e3Ssthen
294898184e3Ssthen        fail( "unknown key '$test->{key}'" ) if !exists $res->{$test->{key}};
295898184e3Ssthen        my $val = $res->{$test->{key}};
296898184e3Ssthen
297898184e3Ssthen        is( $val, $test->{expect}, $test->{desc} );
298898184e3Ssthen
299898184e3Ssthen        return;
300898184e3Ssthen    }
301898184e3Ssthen
302898184e3Ssthen    my @tests = (
303898184e3Ssthen        {
304898184e3Ssthen            config => {},
305898184e3Ssthen            key => 'GCC', expect => 0,
306898184e3Ssthen            desc => 'empty cc is not recognized as gcc',
307898184e3Ssthen        },
308898184e3Ssthen        {
309898184e3Ssthen            config => { cc => 'gcc' },
310898184e3Ssthen            key => 'GCC', expect => 1,
311898184e3Ssthen            desc => 'plain "gcc" is recognized',
312898184e3Ssthen        },
313898184e3Ssthen        {
314898184e3Ssthen            config => { cc => 'C:/MinGW/bin/gcc.exe' },
315898184e3Ssthen            key => 'GCC', expect => 1,
316898184e3Ssthen            desc => 'fully qualified "gcc" is recognized',
317898184e3Ssthen        },
318898184e3Ssthen        {
319898184e3Ssthen            config => { cc => 'C:/MinGW/bin/gcc-1.exe' },
320898184e3Ssthen            key => 'GCC', expect => 1,
321898184e3Ssthen            desc => 'dash-extended gcc is recognized',
322898184e3Ssthen        },
323898184e3Ssthen        {
324898184e3Ssthen            config => { cc => 'C:/MinGW/bin/gcc_1.exe' },
325898184e3Ssthen            key => 'GCC', expect => 0,
326898184e3Ssthen            desc => 'underscore-extended gcc is not recognized',
327898184e3Ssthen        },
328898184e3Ssthen        {
329898184e3Ssthen            config => {},
330898184e3Ssthen            key => 'BORLAND', expect => 0,
331898184e3Ssthen            desc => 'empty cc is not recognized as borland',
332898184e3Ssthen        },
333898184e3Ssthen        {
334898184e3Ssthen            config => { cc => 'bcc' },
335898184e3Ssthen            key => 'BORLAND', expect => 1,
336898184e3Ssthen            desc => 'plain "bcc" is recognized',
337898184e3Ssthen        },
338898184e3Ssthen        {
339898184e3Ssthen            config => { cc => 'C:/Borland/bin/bcc.exe' },
3405759b3d2Safresh1            key => 'BORLAND', expect => 1,
3415759b3d2Safresh1            desc => 'fully qualified borland cc is recognized',
342898184e3Ssthen        },
343898184e3Ssthen        {
344898184e3Ssthen            config => { cc => 'bcc-1.exe' },
345898184e3Ssthen            key => 'BORLAND', expect => 1,
346898184e3Ssthen            desc => 'dash-extended borland cc is recognized',
347898184e3Ssthen        },
348898184e3Ssthen        {
349898184e3Ssthen            config => { cc => 'bcc_1.exe' },
350898184e3Ssthen            key => 'BORLAND', expect => 1,
351898184e3Ssthen            desc => 'underscore-extended borland cc is recognized',
352898184e3Ssthen        },
353898184e3Ssthen    );
354898184e3Ssthen
355898184e3Ssthen    _check_cc_id_value($_) for @tests;
356898184e3Ssthen}
357898184e3Ssthen
358b39c5158Smillertpackage FakeOut;
359b39c5158Smillert
360b39c5158Smillertsub TIEHANDLE {
361b39c5158Smillert    bless(\(my $scalar), $_[0]);
362b39c5158Smillert}
363b39c5158Smillert
364b39c5158Smillertsub PRINT {
365b39c5158Smillert    my $self = shift;
366b39c5158Smillert    $$self .= shift;
367b39c5158Smillert}
368