File: class.t

package info (click to toggle)
libuniversal-can-perl 1.20140328-1.1
  • links: PTS, VCS
  • area: main
  • in suites: bullseye
  • size: 148 kB
  • sloc: perl: 326; makefile: 2
file content (135 lines) | stat: -rw-r--r-- 3,049 bytes parent folder | download | duplicates (6)
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
#!perl

use strict;
use warnings;

use lib 't/lib';

use Test::More tests => 16;
use Test::SmallWarn;

# must happen here to register warnings category
BEGIN { use_ok( 'UNIVERSAL::can' ) };

{
	package Logger;

	use Scalar::Util 'blessed';

	use vars '$AUTOLOAD';

	sub new
	{
		my ($class, $object) = @_;
		bless { object => $object, calls => [] }, $class;
	}

	sub object
	{
		my $self = shift;
		return $self->{object} if blessed( $self );
		return $self;
	}

	sub calls
	{
		my $self = shift;
		return $self->{calls};
	}

	sub can
	{
		my ($self, $name)  = @_;
		my $object         = $self->object();
		return $self->SUPER::can( $name ) if $object->isa( __PACKAGE__ );
		my $wrapped_method = $self->object->can( $name );
	}

	sub DESTROY {}

	sub AUTOLOAD
	{
		my $self     = shift;
		my ($method) = $AUTOLOAD =~ /::(\w+)$/;
		return unless my $coderef = $self->object->can( $method );

		push @{ $self->calls() }, $method;
		$self->object->$coderef( @_ );
	}

	package Logged;

	sub new
	{
		my $class = shift;
		bless \$class, $class;
	}

	sub foo
	{
		my $self = shift;
		return 'foo'; }

	package Liar;

	use vars '$AUTOLOAD';

	sub can
	{
		my $self = shift;
		return Logger->can( shift );
	}

	sub DESTROY {}

	sub AUTOLOAD
	{
		my $self     = shift;
		my ($method) = $AUTOLOAD =~ /::(\w+)$/;
		return Logger->$method( @_ );
	}
}

my $logger  = Logger->new( 'Logged' );

my $can_new = $logger->can( 'new' );
my $can_foo = $logger->can( 'foo' );
ok( defined  $can_new, 'can() should return true for defined class methods' );
ok( defined &$can_new, '... returning a code reference' );
is( $can_foo, \&Logged::foo, '... the correct code reference' );

my $uncan_foo;
warning_like { $uncan_foo = UNIVERSAL::can( $logger, 'foo' ) }
	qr/Called UNIVERSAL::can\(\) as a function, not a method at t.class.t/,
	'calling UNIVERSAL::can() as function on invocant should warn';
ok( defined  $uncan_foo, 'UNIVERSAL::can() should return true then too' );
ok( defined &$uncan_foo, '... returning a code reference' );
is( $uncan_foo, \&Logged::foo, '... the correct code reference' );

my $can_calls = Logger->can( 'calls' );
ok(  defined $can_calls,
	'can() should return true for methods called as class methods' );
my $can_falls = Logger->can( 'falls' );
ok( ! defined $can_falls,
	'... and false for nonexistant methods' );

my $uncan_liar;
warning_like { $uncan_liar = UNIVERSAL::can( 'Liar', 'new' ) }
	qr/Called UNIVERSAL::can\(\) as a function, not a method at t.class.t/,
	'calling UNIVERSAL::can() as function on class name invocant should warn';

{
	no warnings;
	warnings_are { $uncan_liar = UNIVERSAL::can( 'Liar', 'new' ) }
		[], '... but only with warnings enabled';
}

{
	no warnings 'UNIVERSAL::can';
	warnings_are { $uncan_liar = UNIVERSAL::can( 'Liar', 'new' ) }
		[], '... and not with warnings diabled for UNIVERSAL::can';
}

ok( defined  $uncan_liar, 'can() should return true for class can() method' );
ok( defined &$uncan_liar, '... returning a code reference' );
is( $uncan_liar, \&Logger::new, '... the correct code reference' );