summaryrefslogtreecommitdiff
path: root/lib/ExtUtils/t/MM_OS2.t
blob: c09f68a4473c2b5687d7e4c39c142f289116b40a (plain)
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
#!/usr/bin/perl -w

BEGIN {
    if( $ENV{PERL_CORE} ) {
        chdir 't' if -d 't';
        @INC = '../lib';
    }
    else {
        unshift @INC, 't/lib';
    }
}
chdir 't';

use strict;
use Test::More;
if ($^O =~ /os2/i) {
	plan( tests => 32 );
} else {
	plan( skip_all => "This is not OS/2" );
}

# for dlsyms, overridden in tests
BEGIN {
	package ExtUtils::MM_OS2;
	use subs 'system', 'unlink';
}

# for maybe_command
use File::Spec;

use_ok( 'ExtUtils::MM_OS2' );
ok( grep( 'ExtUtils::MM_OS2',  @MM::ISA), 
	'ExtUtils::MM_OS2 should be parent of MM' );

# dlsyms
my $mm = bless({ 
	SKIPHASH => { 
		dynamic => 1 
	}, 
	NAME => 'foo:bar::',
}, 'ExtUtils::MM_OS2');

is( $mm->dlsyms(), '', 
	'dlsyms() should return nothing with dynamic flag set' );

$mm->{BASEEXT} = 'baseext';
delete $mm->{SKIPHASH};
my $res = $mm->dlsyms();
like( $res, qr/baseext\.def: Makefile/,
	'... without flag, should return make targets' );
like( $res, qr/"DL_FUNCS" => {  }/, 
	'... should provide empty hash refs where necessary' );
like( $res, qr/"DL_VARS" => \[]/, '... and empty array refs too' );

$mm->{FUNCLIST} = 'funclist';
$res = $mm->dlsyms( IMPORTS => 'imports' );
like( $res, qr/"FUNCLIST" => .+funclist/, 
	'... should pick up values from object' );
like( $res, qr/"IMPORTS" => .+imports/, '... and allow parameter options too' );

my $can_write;
{
	local *OUT;
	$can_write = open(OUT, '>tmp_imp');
}

SKIP: {
	skip("Cannot write test files: $!", 7) unless $can_write;

	$mm->{IMPORTS} = { foo => 'bar' };

	local $@;
	eval { $mm->dlsyms() };
	like( $@, qr/Can.t mkdir tmp_imp/, 
		'... should die if directory cannot be made' );

	unlink('tmp_imp') or skip("Cannot remove test file: $!", 9);
	eval { $mm->dlsyms() };
	like( $@, qr/Malformed IMPORT/, 'should die from malformed import symbols');

	$mm->{IMPORTS} = { foo => 'bar.baz' };

	my @sysfail = ( 1, 0, 1 );
	my ($sysargs, $unlinked);

	*ExtUtils::MM_OS2::system = sub {
		$sysargs = shift;
		return shift @sysfail;
	};

	*ExtUtils::MM_OS2::unlink = sub {
		$unlinked++;
	};

	eval { $mm->dlsyms() };

	like( $sysargs, qr/^emximp/, '... should try to call system() though' );
	like( $@, qr/Cannot make import library/, 
		'... should die if emximp syscall fails' );

	# sysfail is 0 now, call emximp call should succeed
	eval { $mm->dlsyms() };
	is( $unlinked, 1, '... should attempt to unlink temp files' );
	like( $@, qr/Cannot extract import/, 
		'... should die if other syscall fails' );
	
	# make both syscalls succeed
	@sysfail = (0, 0);
	local $@;
	eval { $mm->dlsyms() };
	is( $@, '', '... should not die if both syscalls succeed' );
}

# static_lib
{
	my $called = 0;

	# avoid "used only once"
	local *ExtUtils::MM_Unix::static_lib;
	*ExtUtils::MM_Unix::static_lib = sub {
		$called++;
		return "\n\ncalled static_lib\n\nline2\nline3\n\nline4";
	};

	my $args = bless({ IMPORTS => {}, }, 'MM');

	# without IMPORTS as a populated hash, there will be no extra data
	my $ret = ExtUtils::MM_OS2::static_lib( $args );
	is( $called, 1, 'static_lib() should call parent method' );
	like( $ret, qr/^called static_lib/m,
		'... should return parent data unless IMPORTS exists' );

	$args->{IMPORTS} = { foo => 1};
	$ret = ExtUtils::MM_OS2::static_lib( $args );
	is( $called, 2, '... should call parent method if extra imports passed' );
	like( $ret, qr/^called static_lib\n\t\$\(AR\) \$\(AR_STATIC_ARGS\)/m, 
		'... should append make tags to first line from parent method' );
	like( $ret, qr/\$@\n\n\nline2\nline3\n\nline4/m, 
		'... should include remaining data from parent method' );

}

# replace_manpage_separator
my $sep = '//a///b//c/de';
is( ExtUtils::MM_OS2->replace_manpage_separator($sep), '.a.b.c.de',
	'replace_manpage_separator() should turn multiple slashes into periods' );

# maybe_command
{
	local *DIR;
	my ($dir, $noext, $exe, $cmd);
	my $found = 0;

	my ($curdir, $updir) = (File::Spec->curdir, File::Spec->updir);

	# we need:
	#	1) a directory
	#	2) an executable file with no extension
	# 	3) an executable file with the .exe extension
	# 	4) an executable file with the .cmd extension
	# we assume there will be one somewhere in the path
	# in addition, we need them to be unique enough they do not trip
	# an earlier file test in maybe_command().  Portability.

	foreach my $path (split(/:/, $ENV{PATH})) {
		opendir(DIR, $path) or next;
		while (defined(my $file = readdir(DIR))) {
			next if $file eq $curdir or $file eq $updir;
			$file = File::Spec->catfile($path, $file);
			unless (defined $dir) {
				if (-d $file) {
					next if ( -x $file . '.exe' or -x $file . '.cmd' );
					
					$dir = $file;
					$found++;
				}
			}
			if (-x $file) {
				my $ext;
				if ($file =~ s/\.(exe|cmd)\z//) {
					$ext = $1;

					# skip executable files with names too similar
					next if -x $file;
					$file .= '.' . $ext;

				} else {
					unless (defined $noext) {
						$noext = $file;
						$found++;
					}
					next;
				}

				unless (defined $exe) {
					if ($ext eq 'exe') {
						$exe = $file;
						$found++;
						next;
					}
				}
				unless (defined $cmd) {
					if ($ext eq 'cmd') {
						$cmd = $file;
						$found++;
						next;
					}
				}
			}
			last if $found == 4;
		}
		last if $found == 4;
	}

	SKIP: {
		skip('No appropriate directory found', 1) unless defined $dir;
		is( ExtUtils::MM_OS2->maybe_command( $dir ), undef, 
			'maybe_command() should ignore directories' );
	}

	SKIP: {
		skip('No non-exension command found', 1) unless defined $noext;
		is( ExtUtils::MM_OS2->maybe_command( $noext ), $noext,
			'maybe_command() should find executable lacking file extension' );
	}

	SKIP: {
		skip('No .exe command found', 1) unless defined $exe;
		(my $noexe = $exe) =~ s/\.exe\z//;
		is( ExtUtils::MM_OS2->maybe_command( $noexe ), $exe,
			'maybe_command() should find .exe file lacking extension' );
	}

	SKIP: {
		skip('No .cmd command found', 1) unless defined $cmd;
		(my $nocmd = $cmd) =~ s/\.cmd\z//;
		is( ExtUtils::MM_OS2->maybe_command( $nocmd ), $cmd,
			'maybe_command() should find .cmd file lacking extension' );
	}
}

# file_name_is_absolute
ok( ExtUtils::MM_OS2->file_name_is_absolute( 's:/' ), 
	'file_name_is_absolute() should be true for paths with volume and slash' );
ok( ExtUtils::MM_OS2->file_name_is_absolute( '\foo' ), 
	'... and for paths with leading slash but no volume' );
ok( ! ExtUtils::MM_OS2->file_name_is_absolute( 'arduk' ), 
	'... but not for paths with no leading slash or volume' );


$mm->init_linker;

# PERL_ARCHIVE
is( $mm->{PERL_ARCHIVE}, '$(PERL_INC)/libperl$(LIB_EXT)', 'PERL_ARCHIVE' );

# PERL_ARCHIVE_AFTER
{
	my $aout = 0;
	local *OS2::is_aout;
	*OS2::is_aout = \$aout;
	
        $mm->init_linker;
	isnt( $mm->{PERL_ARCHIVE_AFTER}, '',
		'PERL_ARCHIVE_AFTER should be empty without $is_aout set' );
	$aout = 1;
	is( $mm->{PERL_ARCHIVE_AFTER}, 
            '$(PERL_INC)/libperl_override$(LIB_EXT)', 
		'... and has libperl_override if it is set' );
}

# EXPORT_LIST
is( $mm->{EXPORT_LIST}, '$(BASEEXT).def', 
	'EXPORT_LIST should add .def to BASEEXT member' );

END {
	use File::Path;
	rmtree('tmp_imp');
	unlink 'tmpimp.imp';
}