File: accessors.t

package info (click to toggle)
libclass-accessor-grouped-perl 0.10012-1
  • links: PTS, VCS
  • area: main
  • in suites: jessie, jessie-kfreebsd, stretch
  • size: 356 kB
  • ctags: 187
  • sloc: perl: 2,553; makefile: 2
file content (138 lines) | stat: -rw-r--r-- 4,209 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
use Test::More;
use strict;
use warnings;
no warnings 'once';
use lib 't/lib';
use B qw/svref_2object/;

# we test the pure-perl versions only, but allow overrides
# from the accessor_xs test-umbrella
# Also make sure a rogue envvar will not interfere with
# things
my $use_xs;
BEGIN {
  $Class::Accessor::Grouped::USE_XS = 0
    unless defined $Class::Accessor::Grouped::USE_XS;
  $ENV{CAG_USE_XS} = 1;
  $use_xs = $Class::Accessor::Grouped::USE_XS;
};

require AccessorGroupsSubclass;

my $test_accessors = {
  singlefield => {
    is_simple => 1,
    has_extra => 1,
  },
  runtime_around => {
    # even though this accessor is declared as simple it will *not* be
    # reinstalled due to the runtime 'around'
    forced_class => 'AccessorGroups',
    is_simple => 1,
    has_extra => 1,
  },
  multiple1 => {
  },
  multiple2 => {
  },
  lr1name => {
    custom_field => 'lr1;field',
  },
  lr2name => {
    custom_field => "lr2'field",
  },
  fieldname_torture => {
    is_simple => 1,
    custom_field => join ('', map { chr($_) } (0..255) ),
  },
};

for my $class (qw(
  AccessorGroupsSubclass
  AccessorGroups
  AccessorGroupsParent
)) {
  my $obj = $class->new;

  for my $name (sort keys %$test_accessors) {
    my $alias = "_${name}_accessor";
    my $field = $test_accessors->{$name}{custom_field} || $name;
    my $extra = $test_accessors->{$name}{has_extra};
    my $origin_class = 'AccessorGroupsParent';

    if ( $class eq 'AccessorGroupsParent' ) {
      next if $name eq 'runtime_around';  # implemented in the AG subclass
      $extra = 0;
    }
    elsif ($name eq 'fieldname_torture') {
      $field = reverse $field;
      $origin_class = 'AccessorGroups';
    }

    can_ok($obj, $name, $alias);
    ok(!$obj->can($field), "field for $name is not a method on $class")
      if $field ne $name;

    my $init_shims;

    # initial method name
    for my $meth ($name, $alias) {
      my $cv = svref_2object( $init_shims->{$meth} = $obj->can($meth) );
      is($cv->GV->NAME, $meth, "initial ${class}::$meth accessor is named");
      is(
        $cv->GV->STASH->NAME,
        $test_accessors->{$name}{forced_class} || $origin_class,
        "initial ${class}::$meth origin class correct",
      );
    }

    is($obj->$name, undef, "${class}::$name begins undef");
    is($obj->$alias, undef, "${class}::$alias begins undef");

    # get/set via name
    is($obj->$name('a'), 'a', "${class}::$name setter RV correct");
    is($obj->$name, 'a', "${class}::$name getter correct");
    is($obj->{$field}, $extra ? 'a Extra tackled on' : 'a', "${class}::$name corresponding field correct");

    # alias gets same as name
    is($obj->$alias, 'a', "${class}::$alias getter correct after ${class}::$name setter");

    # get/set via alias
    is($obj->$alias('b'), 'b', "${class}::$alias setter RV correct");
    is($obj->$alias, 'b', "${class}::$alias getter correct");
    is($obj->{$field}, $extra ? 'b Extra tackled on' : 'b', "${class}::$alias corresponding field still correct");

    # alias gets same as name
    is($obj->$name, 'b', "${class}::$name getter correct after ${class}::$alias setter");

    for my $meth ($name, $alias) {
      my $resolved = $obj->can($meth);

      my $cv = svref_2object($resolved);
      is($cv->GV->NAME, $meth, "$meth accessor is named after operations");
      is(
        $cv->GV->STASH->NAME,
        # XS deferred subs install into each caller, not into the original parent
        $test_accessors->{$name}{forced_class} || (
          ($use_xs and $test_accessors->{$name}{is_simple})
            ? (ref $obj)
            : $origin_class
        ),
        "${class}::$meth origin class correct after operations",
      );

      # just simple for now
      if ($use_xs and $test_accessors->{$name}{is_simple} and ! $test_accessors->{$name}{forced_class}) {
        ok ($resolved != $init_shims->{$meth}, "$meth was replaced with a resolved version");
        if ($class eq 'AccessorGroupsParent') {
          ok ($cv->XSUB, "${class}::$meth is an XSUB");
        }
        else {
          ok (!$cv->XSUB, "${class}::$meth is *not* an XSUB (due to get_simple overrides)");
        }
      }
    }
  }
}

done_testing unless $::SUBTESTING;