2 require Config; import Config;
3 if ($Config{'extensions'} !~ /\bXS\/Typemap\b/) {
4 print "1..0 # Skip: XS::Typemap was not built\n";
9 use Test::More tests => 148;
17 # Some inheritance trees to check ISA relationships
19 package intObjPtr::SubClass;
20 use parent '-norequire', qw/ intObjPtr /;
25 package intRefIvPtr::SubClass;
26 use parent '-norequire', qw/ intRefIvPtr /;
30 # T_SV - standard perl scalar value
32 my $sv = "Testing T_SV";
35 # T_SVREF - reference to Scalar
39 is( T_SVREF($svref), $svref );
40 is( ${ T_SVREF($svref) }, $$svref );
42 # Now test that a non reference is rejected
44 eval { T_SVREF( "fail - not ref" ) };
47 note("T_SVREF_REFCOUNT_FIXED");
48 is( T_SVREF_REFCOUNT_FIXED($svref), $svref );
49 is( ${ T_SVREF_REFCOUNT_FIXED($svref) }, $$svref );
50 eval { T_SVREF_REFCOUNT_FIXED( "fail - not ref" ) };
54 # T_AVREF - reference to a perl Array
57 is( T_AVREF(\@array), \@array);
58 # Now test that a non array ref is rejected
59 eval { T_AVREF( \$sv ) };
62 # T_AVREF_REFCOUNT_FIXED - reference to a perl Array, refcount fixed
63 note("T_AVREF_REFCOUNT_FIXED");
64 is( T_AVREF_REFCOUNT_FIXED(\@array), \@array);
65 # Now test that a non array ref is rejected
66 eval { T_AVREF_REFCOUNT_FIXED( \$sv ) };
70 # T_HVREF - reference to a perl Hash
73 is( T_HVREF(\%hash), \%hash);
74 # Now test that a non hash ref is rejected
75 eval { T_HVREF( \@array ) };
79 # T_HVREF_REFCOUNT_FIXED - reference to a perl Hash, refcount fixed
80 note("T_HVREF_REFCOUNT_FIXED");
81 is( T_HVREF_REFCOUNT_FIXED(\%hash), \%hash);
82 # Now test that a non hash ref is rejected
83 eval { T_HVREF_REFCOUNT_FIXED( \@array ) };
87 # T_CVREF - reference to perl subroutine
90 is( T_CVREF($sub), $sub );
91 # Now test that a non code ref is rejected
92 eval { T_CVREF( \@array ) };
95 is( T_CVREF_REFCOUNT_FIXED($sub), $sub );
96 # Now test that a non code ref is rejected
97 eval { T_CVREF_REFCOUNT_FIXED( \@array ) };
101 # T_SYSRET - system return values
103 # first check success
106 is( T_SYSRET_fail, undef);
108 # T_UV - unsigned integer
110 is( T_UV(5), 5 ); # pass
111 isnt( T_UV(-4), -4); # fail
113 # T_U_INT - unsigned integer with (unsigned int) cast
115 is( T_U_INT(5), 5 ); # pass
116 isnt( T_U_INT(-4), -4); # fail
118 # T_IV - signed integer
119 # T_INT - signed integer with cast
120 # T_LONG - signed integer with cast to IV
121 # T_SHORT - signed short
122 for my $t (['T_IV', \&T_IV],
124 ['T_LONG', \&T_LONG],
125 ['T_SHORT', \&T_SHORT])
128 is( $t->[1]->(5), 5);
129 is( $t->[1]->(-4), -4);
130 is( $t->[1]->(4.1), int(4.1));
131 is( $t->[1]->("52"), "52");
132 isnt( $t->[1]->(4.5), 4.5); # failure
135 if ($Config{shortsize} == 2) {
136 isnt( T_SHORT(32801), 32801 );
139 pass(); # e.g. Crays have shortsize 4 (T3X) or 8 (CXX and SVX)
143 ok( T_ENUM(), 'T_ENUM' ); # just hope for a true value
151 ok( ! T_BOOL(undef) );
154 # these attempt to modify a read-only value
155 ok( !eval { T_BOOL_2(52); 1 } );
156 ok( !eval { T_BOOL_2(0); 1 } );
157 ok( !eval { T_BOOL_2(''); 1 } );
158 ok( !eval { T_BOOL_2(undef); 1 } );
164 T_BOOL_OUT($out, $in);
165 ok($out, "T_BOOL_OUT, true in");
168 T_BOOL_OUT($out, $in);
169 ok(!$out, "T_BOOL_OUT, false in");
174 is( T_U_SHORT(32000), 32000);
175 if ($Config{shortsize} == 2) {
176 isnt( T_U_SHORT(65536), 65536); # probably dont want to test edge cases
178 ok(1); # e.g. Crays have shortsize 4 (T3X) or 8 (CXX and SVX)
183 is( T_U_LONG(65536), 65536);
184 isnt( T_U_LONG(-1), -1);
188 is( T_CHAR("a"), "a");
189 is( T_CHAR("-"), "-");
190 is( T_CHAR(chr(128)),chr(128));
191 isnt( T_CHAR(chr(256)), chr(256));
195 is( T_U_CHAR(127), 127);
196 is( T_U_CHAR(128), 128);
197 isnt( T_U_CHAR(-1), -1);
198 isnt( T_U_CHAR(300), 300);
202 is( sprintf("%6.3f",T_FLOAT(52.345)), sprintf("%6.3f",52.345), "T_FLOAT");
205 is( T_NV(52.345), 52.345, "T_NV" );
208 is( sprintf("%6.3f",T_DOUBLE(52.345)), sprintf("%6.3f",52.345), "T_DOUBLE" );
212 is( T_PV("a string"), "a string");
214 ok !defined T_PV_null, 'RETVAL = NULL returns undef for char*';
217 local $SIG{__WARN__} = sub { ++$uninit if shift =~ /uninit/ };
219 is $uninit, 1, 'uninit warning from NULL returned from char* func';
224 my $ptr = T_PTR_OUT($t);
225 is( T_PTR_IN( $ptr ), $t, "T_PTR" );
230 $ptr = T_PTRREF_OUT( $t );
231 is( ref($ptr), "SCALAR");
232 is( T_PTRREF_IN( $ptr ), $t );
234 # test that a non-scalar ref is rejected
235 eval { T_PTRREF_IN( $t ); };
241 $ptr = T_PTROBJ_OUT( $t );
242 is( ref($ptr), "intObjPtr");
243 is( $ptr->T_PTROBJ_IN, $t );
245 # check that normal scalar refs fail
246 eval {intObjPtr::T_PTROBJ_IN( \$t );};
249 # check that inheritance works
250 bless $ptr, "intObjPtr::SubClass";
251 is( ref($ptr), "intObjPtr::SubClass");
252 is( $ptr->T_PTROBJ_IN, $t );
257 note("T_REF_IV_PTR");
259 $ptr = T_REF_IV_PTR_OUT( $t );
260 is( ref($ptr), "intRefIvPtr");
261 is( $ptr->T_REF_IV_PTR_IN(), $t);
263 # inheritance should not work
264 bless $ptr, "intRefIvPtr::SubClass";
265 eval { $ptr->T_REF_IV_PTR_IN };
277 my $p = T_OPAQUEPTR_IN( $t );
278 is( T_OPAQUEPTR_OUT($p), $t);
280 # T_OPAQUEPTR with a struct
281 note("T_OPAQUEPTR with a struct");
283 $p = T_OPAQUEPTR_IN_struct(@test);
284 my @result = T_OPAQUEPTR_OUT_struct($p);
285 is(scalar(@result),scalar(@test));
287 is($result[$_], $test[$_]);
293 $p = T_OPAQUE_IN( $t );
294 is(T_OPAQUEPTR_OUT_short( $p ), $t); # Test using T_OPAQUEPTR
295 is(T_OPAQUE_OUT( $p ), $t ); # Test using T_OPQAQUE
298 note("T_OPAQUE: A packed array");
301 my $packed = T_OPAQUE_array(@opq);
302 my @uopq = unpack("i*",$packed);
303 is(scalar(@uopq), scalar(@opq));
305 is( $uopq[$_], $opq[$_]);
310 my $struct = T_PACKED_out(-4, 3, 2.1);
311 ok(ref($struct) eq 'HASH');
312 is_approx($struct->{a}, -4);
313 is_approx($struct->{b}, 3);
314 is_approx($struct->{c}, 2.1);
315 my @rv = T_PACKED_in($struct);
317 is_approx($rv[0], -4);
318 is_approx($rv[1], 3);
319 is_approx($rv[2], 2.1);
323 note("T_PACKED_ARRAY");
330 push @out, {a => $d[$_*3], b => $d[$_*3+1], c => $d[$_*3+2]} for (0..2);
331 my $structs = T_PACKEDARRAY_out(@d);
332 ok(ref($structs) eq 'ARRAY');
333 is(scalar(@$structs), 3);
334 foreach my $i (0..2) {
335 my $s = $structs->[$i];
337 is_approx($s->{a}, $d[$i*3+0]);
338 is_approx($s->{b}, $d[$i*3+1]);
339 is_approx($s->{c}, $d[$i*3+2]);
341 my @rv = T_PACKEDARRAY_in($structs);
342 is(scalar(@rv), scalar(@d));
343 foreach my $i (0..$#d) {
344 is_approx($rv[$i], $d[$i]);
353 my @inarr = (1,2,3,4,5,6,7,8,9,10);
354 my @outarr = T_ARRAY( 5, @inarr );
355 is_deeply(\@outarr, \@inarr, "T_ARRAY");
360 # open a file in XS for write
361 my $testfile= "stdio.tmp";
362 my $fh = T_STDIO_open( $testfile );
365 # write to it using perl
368 my @lines = ("NormalSTDIO\n", "PerlIO\n");
370 # print to it using FILE* through XS
371 is( T_STDIO_print($fh, $lines[0]), length($lines[0]));
373 # print to it using normal perl
374 ok(print $fh "$lines[1]");
376 # close it using XS if using perlio, using Perl otherwise
377 ok( $Config{useperlio} ? T_STDIO_close( $fh ) : close( $fh ) );
379 # open from perl, and check contents
380 open($fh, "< $testfile");
388 ok(unlink($testfile));
392 skip("Skip Test not relevant since file was not opened correctly",0);
401 open my $fh, "+<", \$buf or die $!;
404 my $fh2 = T_INOUT($fh);
406 is(readline($fh2), $str);
407 ok(print $fh2 "foo\n");
413 my $buf = "Hello!\n";
415 open my $fh, "<", \$buf or die $!;
417 is(readline($fh2), $buf);
418 local $SIG{__WARN__} = sub {die};
419 ok(not(eval {print $fh2 "foo\n"; 1}));
427 open my $fh, "+<", \$buf or die $!;
430 my $fh2 = T_OUT($fh);
432 is(readline($fh2), $str);
433 ok(eval {print $fh2 "foo\n"; 1});
437 my ($l, $r, $n) = @_;
438 if (not defined $l or not defined $r) {
439 fail(defined($n) ? $n : ());
442 ok($l < $r+1e-6 && $r < $l+1e-6, defined($n) ? $n : ())
443 or note("$l and $r seem to be different given a fuzz of 1e-6");