views:

136

answers:

3

Is there a more elegant way to write the portion of the test script which is O/S dependant?

Please refer to the code below the comment line.

Background: Module Perl::Tags creates a tags file for VIM. On Win32 the directory separator is "\" but on other OS's it is "/". Vim's Perl-support module seems to read the tags file quite happily, so there seems to be no need to modify the module.

#!/usr/bin/perl -w
use strict; use warnings;
use Data::Dumper;

use Test::More tests => 6;
use FindBin qw($Bin);

BEGIN {
  use_ok( 'Perl::Tags' );
}

my $naive_tagger = Perl::Tags::Naive->new( max_level=>1 );
ok (defined $naive_tagger, 'created Perl::Tags' );
isa_ok ($naive_tagger, 'Perl::Tags::Naive' );
isa_ok ($naive_tagger, 'Perl::Tags' );

my $result = 
    $naive_tagger->process(
        files => [ "$Bin/Test.pm" ],
        refresh=> 1
    );
ok ($result, 'processed successfully' ) or diag "RESULT $result";

# Other tests also fail because \Test.pm on Win32 vs /Test.pm on Linux/ OS X
if ( $^O =~ /MSWin32/ ) {
    like ($naive_tagger, qr{Test\t\S+\\Test.pm\t/package Test;/}       , 'package line');
} else {
    like ($naive_tagger, qr{Test\t\S+/Test.pm\t/package Test;/}       , 'package line');
}
+3  A: 

Maybe you can simply always use the Linux style slashes, because:

There are many important issues you must be aware of when writing Perl scripts that must run under NT and UNIX. First of all, there is the issue of pathnames. In DOS, Windows NT, and Windows 95 you specify pathnames with a backslash operator, whereas in UNIX you use the forward slash operator. The Win32 Perl port allows either forward slashes or backslashes. A Perl script using forward slashes in pathnames is more likely to be portable than a script using backslashes. Besides that, Perl scripts will have to use the backslash twice in strings to escape one instance of a backslash from the Perl interpreter. Drive letters do not have to change.

For example, the following pathname can be set using either of the following:

$myFile = "E:/users/default/datafile.txt";

$myFile = "E:\\users\\default\\datafile.txt";

(from Perl 5 Unleashed)


In case that you are sure that you can't always use the Linux style, you can try using the CPAN modules File::Spec or Path::Class. Check the "CPAN Module for mixing Unix/Windows path" discussion on Perlmonks for additional info.

Igor Oks
Thanks. Please refer to comment to Sinan below.
heferav
@Sinan - thanks.
Igor Oks
@Igor: You are welcome. Deleted my comments since they were no longer relevant.
Sinan Ünür
+3  A: 

File::Spec and Path::Class were built to address exactly these kinds of platform specific issues.

Is the following what you are trying to do?

#!/usr/bin/perl
use strict; use warnings;

use Test::More tests => 6;
use FindBin qw($Bin);
use File::Spec::Functions qw(catfile catpath rootdir);

BEGIN {
  use_ok( 'Perl::Tags' );
}

my $naive_tagger = Perl::Tags::Naive->new(max_level => 1);
ok (defined $naive_tagger, 'created Perl::Tags');
isa_ok ($naive_tagger, 'Perl::Tags::Naive');
isa_ok ($naive_tagger, 'Perl::Tags');

my $result = 
    $naive_tagger->process(
        files => [ catfile($Bin, 'Test.pm') ],
        refresh => 1
    );
ok ($result, 'processed successfully' ) or diag "RESULT $result";

my $file = catfile(rootdir, 'Test.pm');
# or $file = catpath('C:', rootdir(), 'Test.pm')
# depending on what you mean.

like($naive_tagger
    qr{Test\t\S+\Q$file\E\t/package Test;/}, 
    'package line',
);
Sinan Ünür
Thanks for pointing out Path::Class. Stringification of file('', 'Test.pm') returns \Test.pm or /Test.pm as required. Unfortunately qr{ } requires \\Test.pm. I will post interim solution below for your comment.
heferav
That is exactly what I am trying to do, except all tests are conducted on Test.pm hence no need to declare **my $file**.
heferav
A: 

Revised following guidance from Sinan Ünür -- there is no need to do OS specific tests if

like ($naive_tagger, qr{Test\t\S\Test.pm\t/package Test;/}       , 'package line');

is replaced with

like ($naive_tagger, qr{Test\t\S+\QTest.pm\E\t/package Test;/}       , 'package line');

\Q (disable) pattern metacharacters till \E

\E disable pattern metacharacters again

heferav
**`qr{Test\t\S+\Q$file\E\t/package Test;/}`** There is no need for all the hoops you are going through.
Sinan Ünür
Brilliant. Works a treat. Thank you very much. Previous attempt deserved a down vote!
heferav
Note, there is no need to mention my name in bold. Also, I think you made some kind of cut'n'paste error in the current version. Take a look at it and see if you are saying what you mean.
Sinan Ünür
Took bold off attribution to Sinan and fixed cut and paste errors
heferav