Skip to content

Commit b8d574d

Browse files
committed
t/class/accessor.t - add additional :reader and :writer tests
The :reader tests are not really needed at present, as `pp_leavesub` makes the necessary copies, but exploring some fast accessor ideas which bypass that logic has shown the usefulness of having these tests present. The :writer tests verify that user errors are handled as expected.
1 parent 201ee5d commit b8d574d

File tree

1 file changed

+35
-0
lines changed

1 file changed

+35
-0
lines changed

t/class/accessor.t

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,10 @@ no warnings 'experimental::class';
1919
field @a :reader = qw( the array );
2020

2121
# Present-but-empty parens counts as default
22+
2223
field %h :reader() = qw( the hash );
24+
25+
field $empty :reader;
2326
}
2427

2528
my $o = Testcase1->new;
@@ -35,12 +38,26 @@ no warnings 'experimental::class';
3538
'Reader accessor fails with argument');
3639
like($@, qr/^Too many arguments for subroutine \'Testcase1::s\' \(got 2; expected 1\) at /,
3740
'Failure from argument to accessor');
41+
42+
# Reading an undefined value has predictable behaviour
43+
$o->empty;
44+
pass("void :reader on an uninitialized field doesn't crash");
45+
ok(!defined scalar $o->empty, 'scalar :reader on uninitialized field is undef');
46+
my ($empty) = $o->empty;
47+
ok(!defined $empty, 'list :reader on uninitialized field is undef');
48+
49+
# :reader returns value copies, not the internal SVs
50+
map { $_ = 99 } $o->s, $o->a, $o->h;
51+
is($o->s, "the scalar", ':reader does not expose internal SVs');
52+
ok(eq_array([$o->a], [qw( the array )]), ':reader does not expose internal AVs');
53+
ok(eq_hash({$o->h}, {qw( the hash )}), ':reader does not expose internal HVs');
3854
}
3955

4056
# writer accessors on scalars
4157
{
4258
class Testcase2 {
4359
field $s :reader :writer = "initial";
60+
field $xno :param :reader = "Eh-ehhh";
4461
}
4562

4663
my $o = Testcase2->new;
@@ -57,6 +74,12 @@ no warnings 'experimental::class';
5774
'Writer accessor fails with 2 arguments');
5875
like($@, qr/^Too many arguments for subroutine \'Testcase2::set_s\' \(got 3; expected 2\) at /,
5976
'Failure from argument to accessor');
77+
78+
# Should not be able to write without the :writer attribute
79+
ok(!eval { $o->set_xno(77) },
80+
'Cannot write without :writer attribute');
81+
like($@, qr/^Can\'t locate object method \"set_xno\" via package \"Testcase2\"/,
82+
'Failure from writing without :writer');
6083
}
6184

6285
# Alternative names
@@ -76,4 +99,16 @@ no warnings 'experimental::class';
7699
'Failure from lack of original name accessor');
77100
}
78101

102+
# writer accessors on AVs or HVs
103+
{
104+
ok(!eval "class Testcase4 { field \@a :writer; }",
105+
'Cannot assign a :writer to an array field');
106+
like($@, qr/^Cannot apply a :writer attribute to a non-scalar field/,
107+
'Failure from assigning :writer to an array field');
108+
ok(!eval "class Testcase5 { field \%h :writer; }",
109+
'Cannot assign a :writer to an hash field');
110+
like($@, qr/^Cannot apply a :writer attribute to a non-scalar field/,
111+
'Failure from assigning :writer to an hash field');
112+
}
113+
79114
done_testing;

0 commit comments

Comments
 (0)