Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 25 additions & 0 deletions t/class/accessor.t
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,10 @@ no warnings 'experimental::class';
field @a :reader = qw( the array );

# Present-but-empty parens counts as default

field %h :reader() = qw( the hash );

field $empty :reader;
}

my $o = Testcase1->new;
Expand All @@ -35,12 +38,26 @@ no warnings 'experimental::class';
'Reader accessor fails with argument');
like($@, qr/^Too many arguments for subroutine \'Testcase1::s\' \(got 2; expected 1\) at /,
'Failure from argument to accessor');

# Reading an undefined value has predictable behaviour
$o->empty;
pass("void :reader on an uninitialized field doesn't crash");
ok(!defined scalar $o->empty, 'scalar :reader on uninitialized field is undef');
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This and the similar test below should use:

is(scalar $o->empty, undef, 'scalar :reader on uninitialized field is undef');

since that will report what the define value is, if it turns out to be defined.

my ($empty) = $o->empty;
ok(!defined $empty, 'list :reader on uninitialized field is undef');

# :reader returns value copies, not the internal SVs
map { $_ = 99 } $o->s, $o->a, $o->h;
is($o->s, "the scalar", ':reader does not expose internal SVs');
ok(eq_array([$o->a], [qw( the array )]), ':reader does not expose internal AVs');
ok(eq_hash({$o->h}, {qw( the hash )}), ':reader does not expose internal HVs');
}

# writer accessors on scalars
{
class Testcase2 {
field $s :reader :writer = "initial";
field $xno :param :reader = "Eh-ehhh";
}

my $o = Testcase2->new;
Expand All @@ -57,6 +74,12 @@ no warnings 'experimental::class';
'Writer accessor fails with 2 arguments');
like($@, qr/^Too many arguments for subroutine \'Testcase2::set_s\' \(got 3; expected 2\) at /,
'Failure from argument to accessor');

# Should not be able to write without the :writer attribute
ok(!eval { $o->set_xno(77) },
'Cannot write without :writer attribute');
like($@, qr/^Can\'t locate object method \"set_xno\" via package \"Testcase2\"/,
'Failure from writing without :writer');
}

# Alternative names
Expand All @@ -76,4 +99,6 @@ no warnings 'experimental::class';
'Failure from lack of original name accessor');
}

# Note: see t/lib/croak/class for testing :writer accessors on AVs or HVs

done_testing;
12 changes: 11 additions & 1 deletion t/lib/croak/class
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,7 @@ class XXX {
EXPECT
"set-abc-def" is not a valid name for a generated method at - line 6.
########
# Writer on non-scalar field
# Writer on array field
use v5.36;
use feature 'class';
no warnings 'experimental::class';
Expand All @@ -185,6 +185,16 @@ class XXX {
EXPECT
Cannot apply a :writer attribute to a non-scalar field at - line 6.
########
# Writer on hash field
use v5.36;
use feature 'class';
no warnings 'experimental::class';
class XXX {
field %things :writer;
}
EXPECT
Cannot apply a :writer attribute to a non-scalar field at - line 6.
########
use v5.36;
use feature 'class';
no warnings 'experimental::class';
Expand Down