1#!perl 2BEGIN { 3 chdir 't' if -d 't'; 4 @INC = "../lib"; 5 require './test.pl'; 6} 7 8use strict; 9use Config qw(%Config); 10use XS::APItest; 11 12# memory usage checked with top 13$ENV{PERL_TEST_MEMORY} >= 60 14 or skip_all("Need ~60GB for this test"); 15$Config{ptrsize} >= 8 16 or skip_all("Need 64-bit pointers for this test"); 17XS::APItest::wide_marks() 18 or skip_all("Not configured for SSize_t marks"); 19 20my @x; 21$x[0x8000_0000] = "Hello"; 22 23my $arg_count; 24 25my @tests = 26 ( 27 [ mark => sub 28 { 29 # unlike the grep example this avoids the mark manipulation done by grep 30 # so it's more of a pure mark type test 31 # it also fails/succeeds a lot faster 32 my $count = () = (x(), z()); 33 is($count, 0x8000_0002, "got expected (large) list size"); 34 }, 35 ], 36 [ xssize => sub 37 { 38 # check XS gets the right numbers in our predefined variables 39 # returned ~ -2G before fix 40 my $count = XS::APItest::xs_items(x(), z()); 41 is($count, 0x8000_0002, "got expected XS list size"); 42 } 43 ], 44 [ listsub => sub 45 { 46 my $last = ( x() )[-1]; 47 is($last, "Hello", "list subscripting"); 48 49 my ($first, $last2, $last1) = ( "first", x(), "Goodbye" )[0, -2, -1]; 50 is($first, "first", "list subscripting in list context (0)"); 51 is($last2, "Hello", "list subscripting in list context (-2)"); 52 is($last1, "Goodbye", "list subscripting in list context (-1)"); 53 } 54 ], 55 [ iterctx => sub 56 { 57 # the iter context had an I32 stack offset 58 my $last = ( x(), iter() )[-1]; 59 is($last, "abc", "check iteration not confused"); 60 } 61 ], 62 [ split => sub 63 { 64 # split had an I32 base offset 65 # this paniced with "Split loop" 66 my $count = () = ( x(), do_split("ABC") ); 67 is($count, 0x8000_0004, "split base index"); 68 # it would be nice to test split returning >2G (or >4G) items, but 69 # I don't have the memory needed 70 } 71 ], 72 [ xsload => sub 73 { 74 # I expect this to crash if buggy 75 my $count = () = (x(), loader()); 76 is($count, 0x8000_0001, "check loading XS with large stack"); 77 } 78 ], 79 [ pp_list => sub 80 { 81 my $l = ( x(), list2() )[-1]; 82 is($l, 2, "pp_list mark handling"); 83 } 84 ], 85 [ 86 chomp_av => sub { 87 # not really stack related, but is 32-bit related 88 local $x[-1] = "Hello\n"; 89 chomp(@x); 90 is($x[-1], "Hello", "chomp on a large array"); 91 } 92 ], 93 [ 94 grepwhile => sub { 95 SKIP: { 96 skip "This test is even slower - define PERL_RUN_SLOW_TESTS to run me", 1 97 unless $ENV{PERL_RUN_SLOW_TESTS}; 98 # grep ..., @x used too much memory 99 my $count = grep 1, ( (undef) x 0x7FFF_FFFF, 1, 1 ); 100 is($count, 0x8000_0001, "grepwhile item count"); 101 } 102 } 103 ], 104 [ 105 repeat => sub { 106 SKIP: 107 { 108 $ENV{PERL_TEST_MEMORY} >= 70 109 or skip "repeat test needs 70GB", 2; 110 # pp_repeat would throw an unable to allocate error 111 my ($lastm1, $middle) = ( ( x() ) x 2 )[-1, @x-1]; 112 is($lastm1, "Hello", "repeat lastm1"); 113 is($middle, "Hello", "repeat middle"); 114 } 115 }, 116 ], 117 [ 118 tiescalar => sub { 119 SKIP: 120 { 121 # this swaps unless you have actually 80GB RAM, since 122 # most of the memory is touched 123 $ENV{PERL_TEST_MEMORY} >= 80 124 or skip "tiescalar second test needs 80GB", 2; 125 my $x; 126 ok(ref( ( x(), tie($x, "ScalarTie", 1..5))[-1]), 127 "tied with deep stack"); 128 is($x, 6, "check arguments received"); 129 untie $x; 130 ok(tie($x, "ScalarTie", x()), "tie scalar with long argument list"); 131 is($x, 1+scalar(@x), "check arguments received"); 132 untie $x; 133 SKIP: 134 { 135 skip "This test is even slower - define PERL_RUN_SLOW_TESTS to run me", 1 136 unless $ENV{PERL_RUN_SLOW_TESTS}; 137 my $o = bless {}, "ScalarTie"; 138 # this was news to me 139 ok(tie($x, $o, x(), 1), "tie scalar via object with long argument list"); 140 is($x, 2+scalar(@x), "check arguments received"); 141 untie $x; 142 } 143 } 144 } 145 ], 146 [ 147 apply => sub { 148 SKIP: 149 { 150 skip "2**31 system calls take a very long time - define PERL_RUN_SLOW_TESTS to run me", 1 151 unless $ENV{PERL_RUN_SLOW_TESTS}; 152 my $mode = (stat $0)[2]; 153 my $tries = 0x8000_0001; 154 my $count = chmod $mode, ( $0 ) x $tries; 155 is($count, $tries, "chmod with 2G files"); 156 } 157 } 158 ], 159 [ 160 join => sub { 161 no warnings 'uninitialized'; 162 my $joined = join "", @x, "!"; 163 is($joined, "Hello!", "join"); 164 }, 165 ], 166 [ 167 class_construct => sub { 168 use experimental 'class'; 169 class Foo { 170 field $x :param; 171 }; 172 my $y = Foo->new((x => 1) x 0x4000_0001); 173 ok($y, "construct class based object with 2G parameters"); 174 }, 175 ], 176 [ 177 eval_sv_count => sub { 178 SKIP: 179 { 180 $ENV{PERL_TEST_MEMORY} >= 70 181 or skip "eval_sv_count test needs 70GB", 2; 182 183 my $count = ( @x, XS::APItest::eval_sv('@x', G_LIST) )[-1]; 184 is($count, scalar @x, "check eval_sv result/mark handling"); 185 } 186 } 187 ], 188 [ 189 call_sv_args => sub { 190 undef $arg_count; 191 my $ret_count = XS::APItest::call_sv(\&arg_count, G_LIST, x()); 192 is($ret_count, 0, "call_sv with 2G args - arg_count() returns nothing"); 193 is($arg_count, scalar @x, "check call_sv argument handling - argument count"); 194 }, 195 ], 196 [ 197 call_sv_mark => sub { 198 my $ret_count = ( x(), XS::APItest::call_sv(\&list, G_LIST) )[-1]; 199 is($ret_count, 2, "call_sv with deep stack - returned value count"); 200 }, 201 ], 202 ); 203 204# these tests are slow, let someone debug them one at a time 205my %enabled = map { $_ => 1 } @ARGV; 206for my $test (@tests) { 207 my ($id, $code) = @$test; 208 if (!@ARGV || $enabled{$id}) { 209 note($id); 210 $code->(); 211 } 212} 213 214done_testing(); 215 216sub x { @x } 217 218sub z { 1 } 219 220sub iter { 221 my $result = ''; 222 my $count = 0; 223 for my $item (qw(a b c)) { 224 $result .= $item; 225 die "iteration bug" if ++$count > 5; 226 } 227 $result; 228} 229 230sub do_split { 231 return split //, $_[0]; 232} 233 234sub loader { 235 require Cwd; 236 (); 237} 238 239sub list2 { 240 scalar list(1); 241} 242 243sub list { 244 # ensure this continues to use a pp_list op 245 # if you change it. 246 return shift() ? (1, 2) : (2, 1); 247} 248 249sub arg_count { 250 $arg_count = @_; 251 (); 252} 253 254package ScalarTie; 255 256sub TIESCALAR { 257 ::note("TIESCALAR $_[0]"); 258 bless { count => scalar @_ }, __PACKAGE__; 259} 260 261sub FETCH { 262 $_[0]{count}; 263} 264