1#!perl
2
3# This test file contains 57 tests.
4# You need to number them manually. Don't forget to update this line for the
5# next kind hacker.
6
7END {print "not ok 1\n" unless $loaded;}
8use v5.6.0;
9use Attribute::Handlers;
10$loaded = 1;
11
12CHECK { $main::phase++ }
13
14######################### End of black magic.
15
16# Insert your test code below (better if it prints "ok 13"
17# (correspondingly "not ok 13") depending on the success of chunk 13
18# of the test code):
19
20sub ok { $::count++; push @::results, [$_[1], $_[0]?"":"not ", defined($_[2])?$_[2]:""]; }
21
22END { print "1..$::count\n";
23      print map "$_->[1]ok $_->[0] $_->[2]\n",
24		sort {$a->[0]<=>$b->[0]}
25			grep $_->[0], @::results }
26
27package Test;
28use warnings;
29no warnings 'redefine';
30
31sub UNIVERSAL::Lastly :ATTR(INIT) { ::ok $_[4][0] && $main::phase, $_[4][1] }
32
33sub UNIVERSAL::Okay :ATTR(BEGIN) {
34::ok $_[4][0] && (!$main::phase || !ref $_[1] && $_[1] eq 'LEXICAL'), $_[4][1];
35}
36
37sub Dokay :ATTR(SCALAR) { ::ok @{$_[4]} }
38sub Dokay :ATTR(HASH)   { ::ok @{$_[4]} }
39sub Dokay :ATTR(ARRAY)  { ::ok @{$_[4]} }
40sub Dokay :ATTR(CODE)   { ::ok @{$_[4]} }
41
42sub Vokay :ATTR(VAR)    { ::ok @{$_[4]} }
43
44sub Aokay :ATTR(ANY)    { ::ok @{$_[4]} }
45
46package main;
47use warnings;
48
49my $x1 :Lastly(1,41);
50my @x1 :Lastly(1=>42);
51my %x1 :Lastly(1,43);
52sub x1 :Lastly(1,44) {}
53
54my Test $x2 :Dokay(1,5);
55
56if ($] < 5.011) {
57 ::ok(1, $_, '# skip : invalid before 5.11') for 55 .. 57;
58} else {
59 my $c = $::count;
60 eval '
61  my Test @x2 :Dokay(1,55);
62  my Test %x2 :Dokay(1,56);
63 ';
64 $c = $c + 2 - $::count;
65 while ($c > 0) {
66  ::ok(0, 57 - $c);
67  --$c;
68 }
69 ::ok(!$@, 57);
70}
71
72package Test;
73my $x3 :Dokay(1,6);
74my Test $x4 :Dokay(1,7);
75sub x3 :Dokay(1,8) {}
76
77my $y1 :Okay(1,9);
78my @y1 :Okay(1,10);
79my %y1 :Okay(1,11);
80sub y1 :Okay(1,12) {}
81
82my $y2 :Vokay(1,13);
83my @y2 :Vokay(1,14);
84my %y2 :Vokay(1,15);
85# BEGIN {eval 'sub y2 :Vokay(0,16) {}; 1' or
86::ok(1,16);
87# }
88
89my $z :Aokay(1,17);
90my @z :Aokay(1,18);
91my %z :Aokay(1,19);
92sub z :Aokay(1,20) {};
93
94package DerTest;
95use parent qw(Test);
96use warnings;
97
98my $x5 :Dokay(1,21);
99my Test $x6 :Dokay(1,22);
100sub x5 :Dokay(1,23);
101
102my $y3 :Okay(1,24);
103my @y3 :Okay(1,25);
104my %y3 :Okay(1,26);
105sub y3 :Okay(1,27) {}
106
107package Unrelated;
108
109my $x11 :Okay(1,1);
110my @x11 :Okay(1=>2);
111my %x11 :Okay(1,3);
112sub x11 :Okay(1,4) {}
113
114BEGIN { eval 'my $x7 :Dokay(0,28)' or ::ok(1,28); }
115my Test $x8 :Dokay(1,29);
116eval 'sub x7 :Dokay(0,30) {}' or ::ok(1,30);
117
118
119package Tie::Loud;
120
121sub TIESCALAR { ::ok(1,31); bless {}, $_[0] }
122sub FETCH { ::ok(1,32); return 1 }
123sub STORE { ::ok(1,33); return 1 }
124
125package Tie::Noisy;
126
127sub TIEARRAY { ::ok(1,$_[1]); bless {}, $_[0] }
128sub FETCH { ::ok(1,35); return 1 }
129sub STORE { ::ok(1,36); return 1 }
130sub FETCHSIZE { 100 }
131
132package Tie::Row::dy;
133
134sub TIEHASH { ::ok(1,$_[1]); bless {}, $_[0] }
135sub FETCH { ::ok(1,38); return 1 }
136sub STORE { ::ok(1,39); return 1 }
137
138package main;
139
140eval 'sub x7 :ATTR(SCALAR) :ATTR(CODE) {}' and ::ok(0,40) or ::ok(1,40);
141
142use Attribute::Handlers autotie => {      Other::Loud => Tie::Loud,
143				                Noisy => Tie::Noisy,
144				     UNIVERSAL::Rowdy => Tie::Row::dy,
145                                   };
146
147my Other $loud : Loud;
148$loud++;
149
150my @noisy : Noisy(34);
151$noisy[0]++;
152
153my %rowdy : Rowdy(37,'this arg should be ignored');
154$rowdy{key}++;
155
156
157# check that applying attributes to lexicals doesn't unduly worry
158# their refcounts
159my $out = "begin\n";
160my $applied;
161sub UNIVERSAL::Dummy :ATTR { ++$applied };
162sub Dummy::DESTROY { $out .= "bye\n" }
163
164{ my $dummy;          $dummy = bless {}, 'Dummy'; }
165ok( $out eq "begin\nbye\n", 45 );
166
167{ my $dummy : Dummy;  $dummy = bless {}, 'Dummy'; }
168if($] < 5.008) {
169ok( 1, 46, " # skip lexicals are not runtime prior to 5.8");
170} else {
171ok( $out eq "begin\nbye\nbye\n", 46);
172}
173# are lexical attributes reapplied correctly?
174sub dummy { my $dummy : Dummy; }
175$applied = 0;
176dummy(); dummy();
177if($] < 5.008) {
178ok(1, 47, " # skip does not work with perl prior to 5.8");
179} else {
180ok( $applied == 2, 47 );
181}
182# 45-47 again, but for our variables
183$out = "begin\n";
184{ our $dummy;          $dummy = bless {}, 'Dummy'; }
185ok( $out eq "begin\n", 48 );
186{ no warnings; our $dummy : Dummy;  $dummy = bless {}, 'Dummy'; }
187ok( $out eq "begin\nbye\n", 49 );
188undef $::dummy;
189ok( $out eq "begin\nbye\nbye\n", 50 );
190
191# are lexical attributes reapplied correctly?
192sub dummy_our { no warnings; our $banjo : Dummy; }
193$applied = 0;
194dummy_our(); dummy_our();
195ok( $applied == 0, 51 );
196
197sub UNIVERSAL::Stooge :ATTR(END) {};
198eval {
199	local $SIG{__WARN__} = sub { die @_ };
200	my $groucho : Stooge;
201};
202my $match = $@ =~ /^Won't be able to apply END handler/; 
203if($] < 5.008) {
204ok(1,52 ,"# Skip, no difference between lexical handlers and normal handlers prior to 5.8");
205} else {
206ok( $match, 52 );
207}
208
209
210# The next two check for the phase invariance that Marcel spotted.
211# Subject: Attribute::Handlers phase variance
212# Message-Id: <54EDDB80-FD75-11D6-A18D-00039379E28A@noug.at>
213
214my ($code_applied, $scalar_applied);
215sub Scotty :ATTR(CODE,BEGIN)   { $code_applied = $_[5] }
216{
217no warnings 'redefine';
218sub Scotty :ATTR(SCALAR,CHECK) { $scalar_applied = $_[5] }
219}
220
221sub warp_coil :Scotty {}
222my $photon_torpedo :Scotty;
223
224ok( $code_applied   eq 'BEGIN', 53, "# phase variance" );
225ok( $scalar_applied eq 'CHECK', 54 );
226