"Clean" implementation of binmode(FH)/":raw" identity.
[p5sagit/p5-mst-13.2.git] / ext / Thread / thr5005.t
1 #!./perl
2
3 BEGIN {
4     chdir 't' if -d 't';
5     @INC = '../lib';
6     require Config; import Config;
7     if (! $Config{'use5005threads'}) {
8         print "1..0 # Skip: no use5005threads\n";
9         exit 0;
10     }
11
12     # XXX known trouble with global destruction
13     $ENV{PERL_DESTRUCT_LEVEL} = 0 unless $ENV{PERL_DESTRUCT_LEVEL} > 3;
14 }
15 $| = 1;
16 print "1..74\n";
17 use Thread 'yield';
18 print "ok 1\n";
19
20 sub content
21 {
22  print shift;
23  return shift;
24 }
25
26 # create a thread passing args and immedaietly wait for it.
27 my $t = new Thread \&content,("ok 2\n","ok 3\n", 1..1000);
28 print $t->join;
29
30 # check that lock works ...
31 {lock $foo;
32  $t = new Thread sub { lock $foo; print "ok 5\n" };
33  print "ok 4\n";
34 }
35 $t->join;
36
37 sub dorecurse
38 {
39  my $val = shift;
40  my $ret;
41  print $val;
42  if (@_)
43   {
44    $ret = Thread->new(\&dorecurse, @_);
45    $ret->join;
46   }
47 }
48
49 $t = new Thread \&dorecurse, map { "ok $_\n" } 6..10;
50 $t->join;
51
52 # test that sleep lets other thread run
53 $t = new Thread \&dorecurse,"ok 11\n";
54 sleep 6;
55 print "ok 12\n";
56 $t->join;
57
58 sub islocked : locked {
59  my $val = shift;
60  my $ret;
61  print $val;
62  if (@_)
63   {
64    $ret = Thread->new(\&islocked, shift);
65   }
66  $ret;
67 }
68
69 $t = Thread->new(\&islocked, "ok 13\n", "ok 14\n");
70 $t->join->join;
71
72 {
73     package Loch::Ness;
74     sub new { bless [], shift }
75     sub monster : locked : method {
76         my($s, $m) = @_;
77         print "ok $m\n";
78     }
79     sub gollum { &monster }
80 }
81 Loch::Ness->monster(15);
82 Loch::Ness->new->monster(16);
83 Loch::Ness->gollum(17);
84 Loch::Ness->new->gollum(18);
85
86 my $short = "This is a long string that goes on and on.";
87 my $shorte = " a long string that goes on and on.";
88 my $long  = "This is short.";
89 my $longe  = " short.";
90 my $thr1 = new Thread \&threaded, $short, $shorte, "19";
91 my $thr2 = new Thread \&threaded, $long, $longe, "20";
92 my $thr3 = new Thread \&testsprintf, "21";
93
94 sub testsprintf {
95   my $testno = shift;
96   # this may coredump if thread vars are not properly initialised
97   my $same = sprintf "%.0f", $testno;
98   if ($testno eq $same) {
99     print "ok $testno\n";
100   } else {
101     print "not ok $testno\t# '$testno' ne '$same'\n";
102   }
103 }
104
105 sub threaded {
106   my ($string, $string_end, $testno) = @_;
107
108   # Do the match, saving the output in appropriate variables
109   $string =~ /(.*)(is)(.*)/;
110   # Yield control, allowing the other thread to fill in the match variables
111   yield();
112   # Examine the match variable contents; on broken perls this fails
113   if ($3 eq $string_end) {
114     print "ok $testno\n";
115   }
116   else {
117     warn <<EOT;
118
119 #
120 # This is a KNOWN FAILURE, and one of the reasons why threading
121 # is still an experimental feature.  It is here to stop people
122 # from deploying threads in production. ;-)
123 #
124 EOT
125     print "not ok $testno # other thread filled in match variables\n";
126   }
127 }
128 $thr1->join;
129 $thr2->join;
130 $thr3->join;
131 print "ok 22\n";
132
133 {
134     my $THRf_STATE_MASK = 7;
135     my $THRf_R_JOINABLE = 0;
136     my $THRf_R_JOINED = 1;
137     my $THRf_R_DETACHED = 2;
138     my $THRf_ZOMBIE = 3;
139     my $THRf_DEAD = 4;
140     my $THRf_DID_DIE = 8;
141     sub _test {
142         my($test, $t, $state, $die) = @_;
143         my $flags = $t->flags;
144         if (($flags & $THRf_STATE_MASK) == $state
145                 && !($flags & $THRf_DID_DIE) == !$die) {
146             print "ok $test\n";
147         } else {
148             print <<BAD;
149 not ok $test\t# got flags $flags not @{[ $state + ($die ? $THRf_DID_DIE : 0) ]}
150 BAD
151         }
152     }
153
154     my @t;
155     push @t, (
156         Thread->new(sub { sleep 4; die "thread die\n" }),
157         Thread->new(sub { die "thread die\n" }),
158         Thread->new(sub { sleep 4; 1 }),
159         Thread->new(sub { 1 }),
160     ) for 1, 2;
161     $_->detach for @t[grep $_ & 4, 0..$#t];
162
163     sleep 1;
164     my $test = 23;
165     for (0..7) {
166         my $t = $t[$_];
167         my $flags = ($_ & 1)
168             ? ($_ & 4) ? $THRf_DEAD : $THRf_ZOMBIE
169             : ($_ & 4) ? $THRf_R_DETACHED : $THRf_R_JOINABLE;
170         _test($test++, $t, $flags, (($_ & 3) != 1) ? 0 : $THRf_DID_DIE);
171         printf "%sok %s\n", !$t->done == !($_ & 1) ? "" : "not ", $test++;
172     }
173 #   $test = 39;
174     for (grep $_ & 1, 0..$#t) {
175         next if $_ & 4;         # can't join detached threads
176         $t[$_]->eval;
177         my $die = ($_ & 2) ? "" : "thread die\n";
178         printf "%sok %s\n", $@ eq $die ? "" : "not ", $test++;
179     }
180 #   $test = 41;
181     for (0..7) {
182         my $t = $t[$_];
183         my $flags = ($_ & 1)
184             ? ($_ & 4) ? $THRf_DEAD : $THRf_DEAD
185             : ($_ & 4) ? $THRf_R_DETACHED : $THRf_R_JOINABLE;
186         _test($test++, $t, $flags, (($_ & 3) != 1) ? 0 : $THRf_DID_DIE);
187         printf "%sok %s\n", !$t->done == !($_ & 1) ? "" : "not ", $test++;
188     }
189 #   $test = 57;
190     for (grep !($_ & 1), 0..$#t) {
191         next if $_ & 4;         # can't join detached threads
192         $t[$_]->eval;
193         my $die = ($_ & 2) ? "" : "thread die\n";
194         printf "%sok %s\n", $@ eq $die ? "" : "not ", $test++;
195     }
196     sleep 1;    # make sure even the detached threads are done sleeping
197 #   $test = 59;
198     for (0..7) {
199         my $t = $t[$_];
200         my $flags = ($_ & 1)
201             ? ($_ & 4) ? $THRf_DEAD : $THRf_DEAD
202             : ($_ & 4) ? $THRf_DEAD : $THRf_DEAD;
203         _test($test++, $t, $flags, ($_ & 2) ? 0 : $THRf_DID_DIE);
204         printf "%sok %s\n", $t->done ? "" : "not ", $test++;
205     }
206 #   $test = 75;
207 }