xref: /openbsd-src/gnu/usr.bin/perl/t/op/threads-dirh.t (revision 56d68f1e19ff848c889ecfa71d3a06340ff64892)
1898184e3Ssthen#!perl
2898184e3Ssthen
3898184e3Ssthen# Test interaction of threads and directory handles.
4898184e3Ssthen
5898184e3SsthenBEGIN {
6898184e3Ssthen     chdir 't' if -d 't';
7898184e3Ssthen     @INC = '../lib';
8898184e3Ssthen     require './test.pl';
9898184e3Ssthen     $| = 1;
10898184e3Ssthen
11898184e3Ssthen     require Config;
12898184e3Ssthen     skip_all_without_config('useithreads');
13898184e3Ssthen     skip_all_if_miniperl("no dynamic loading on miniperl, no threads");
14*56d68f1eSafresh1     skip_all("runs out of memory on some EBCDIC") if $ENV{PERL_SKIP_BIG_MEM_TESTS};
15898184e3Ssthen
16898184e3Ssthen     plan(6);
17898184e3Ssthen}
18898184e3Ssthen
19898184e3Ssthenuse strict;
20898184e3Ssthenuse warnings;
21898184e3Ssthenuse threads;
22898184e3Ssthenuse threads::shared;
23898184e3Ssthenuse File::Path;
24898184e3Ssthenuse File::Spec::Functions qw 'updir catdir';
25898184e3Ssthenuse Cwd 'getcwd';
26898184e3Ssthen
27898184e3Ssthen# Basic sanity check: make sure this does not crash
28898184e3Ssthenfresh_perl_is <<'# this is no comment', 'ok', {}, 'crash when duping dirh';
29898184e3Ssthen   use threads;
30898184e3Ssthen   opendir dir, 'op';
31898184e3Ssthen   async{}->join for 1..2;
32898184e3Ssthen   print "ok";
33898184e3Ssthen# this is no comment
34898184e3Ssthen
35898184e3Ssthenmy $dir;
36898184e3SsthenSKIP: {
376fb12b70Safresh1 skip "telldir or seekdir not defined on this platform", 5
386fb12b70Safresh1    if !$Config::Config{d_telldir} || !$Config::Config{d_seekdir};
39898184e3Ssthen my $skip = sub {
40898184e3Ssthen   chdir($dir);
41898184e3Ssthen   chdir updir;
42898184e3Ssthen   skip $_[0], 5
43898184e3Ssthen };
44898184e3Ssthen
45898184e3Ssthen if(!$Config::Config{d_fchdir} && $^O ne "MSWin32") {
46898184e3Ssthen  $::TODO = 'dir handle cloning currently requires fchdir on non-Windows platforms';
47898184e3Ssthen }
48898184e3Ssthen
49898184e3Ssthen my @w :shared; # warnings accumulator
50898184e3Ssthen local $SIG{__WARN__} = sub { push @w, $_[0] };
51898184e3Ssthen
52898184e3Ssthen $dir = catdir getcwd(), "thrext$$" . int rand() * 100000;
53898184e3Ssthen
54b8851fccSafresh1 rmtree($dir) if -d $dir;
55898184e3Ssthen mkdir($dir);
56898184e3Ssthen
57898184e3Ssthen # Create a dir structure like this:
58898184e3Ssthen #   $dir
59898184e3Ssthen #     |
60898184e3Ssthen #     `- toberead
61898184e3Ssthen #            |
62898184e3Ssthen #            +---- thrit
63898184e3Ssthen #            |
64898184e3Ssthen #            +---- rile
65898184e3Ssthen #            |
66898184e3Ssthen #            `---- zor
67898184e3Ssthen
68898184e3Ssthen chdir($dir);
69898184e3Ssthen mkdir 'toberead';
70898184e3Ssthen chdir 'toberead';
71898184e3Ssthen {open my $fh, ">thrit" or &$skip("Cannot create file thrit")}
72898184e3Ssthen {open my $fh, ">rile" or &$skip("Cannot create file rile")}
73898184e3Ssthen {open my $fh, ">zor" or &$skip("Cannot create file zor")}
74898184e3Ssthen chdir updir;
75898184e3Ssthen
76898184e3Ssthen # Then test that dir iterators are cloned correctly.
77898184e3Ssthen
78898184e3Ssthen opendir my $toberead, 'toberead';
79898184e3Ssthen my $start_pos = telldir $toberead;
80898184e3Ssthen my @first_2 = (scalar readdir $toberead, scalar readdir $toberead);
81898184e3Ssthen my @from_thread = @{; async { [readdir $toberead ] } ->join };
82898184e3Ssthen my @from_main = readdir $toberead;
83898184e3Ssthen is join('-', sort @from_thread), join('-', sort @from_main),
84898184e3Ssthen     'dir iterator is copied from one thread to another';
85898184e3Ssthen like
86898184e3Ssthen   join('-', "", sort(@first_2, @from_thread), ""),
87898184e3Ssthen   qr/(?<!-rile)-rile-thrit-zor-(?!zor-)/i,
88898184e3Ssthen  'cloned iterator iterates exactly once over everything not already seen';
89898184e3Ssthen
90898184e3Ssthen seekdir $toberead, $start_pos;
91898184e3Ssthen readdir $toberead for 1 .. @first_2+@from_thread;
92898184e3Ssthen {
93898184e3Ssthen  local $::TODO; # This always passes when dir handles are not cloned.
94898184e3Ssthen  is
95898184e3Ssthen    async { readdir $toberead // 'undef' } ->join, 'undef',
96898184e3Ssthen   'cloned dir iterator that points to the end of the directory'
97898184e3Ssthen  ;
98898184e3Ssthen }
99898184e3Ssthen
100898184e3Ssthen # Make sure the cloning code can handle file names longer than 255 chars
101898184e3Ssthen SKIP: {
102898184e3Ssthen  chdir 'toberead';
103898184e3Ssthen  open my $fh,
104898184e3Ssthen    ">floccipaucinihilopilification-"
105898184e3Ssthen   . "pneumonoultramicroscopicsilicovolcanoconiosis-"
106898184e3Ssthen   . "lopadotemachoselachogaleokranioleipsanodrimypotrimmatosilphiokarabo"
107898184e3Ssthen   . "melitokatakechymenokichlepikossyphophattoperisteralektryonoptokephal"
108898184e3Ssthen   . "liokinklopeleiolagoiosiraiobaphetraganopterygon"
109898184e3Ssthen    or
110898184e3Ssthen     chdir updir,
111898184e3Ssthen     skip("OS does not support long file names (and I mean *long*)", 1);
112898184e3Ssthen  chdir updir;
113898184e3Ssthen  opendir my $dirh, "toberead";
114898184e3Ssthen  my $test_name
115898184e3Ssthen    = "dir iterators can be cloned when the next fn > 255 chars";
116898184e3Ssthen  while() {
117898184e3Ssthen   my $pos = telldir $dirh;
118898184e3Ssthen   my $fn = readdir($dirh);
119898184e3Ssthen   if(!defined $fn) { fail($test_name); last SKIP; }
120898184e3Ssthen   if($fn =~ 'lagoio') {
121898184e3Ssthen    seekdir $dirh, $pos;
122898184e3Ssthen    last;
123898184e3Ssthen   }
124898184e3Ssthen  }
125898184e3Ssthen  is length async { scalar readdir $dirh } ->join, 258, $test_name;
126898184e3Ssthen }
127898184e3Ssthen
128898184e3Ssthen is scalar @w, 0, 'no warnings during all that' or diag @w;
129898184e3Ssthen chdir updir;
130898184e3Ssthen}
131898184e3Ssthenrmtree($dir);
132