File Coverage

blib/lib/Test/Deep/Type.pm
Criterion Covered Total %
statement 57 57 100.0
branch 15 16 93.7
condition 5 5 100.0
subroutine 20 20 100.0
pod 1 6 16.6
total 98 104 94.2


line stmt bran cond sub pod time code
1 2     2   66635 use strict;
  2         6  
  2         77  
2 2     2   11 use warnings;
  2         5  
  2         108  
3             package Test::Deep::Type;
4             # git description: v0.005-1-ga0de865
5             $Test::Deep::Type::VERSION = '0.006';
6             # ABSTRACT: A Test::Deep plugin for validating type constraints
7             # KEYWORDS: testing tests plugin types
8             # vim: set ts=8 sw=4 tw=78 et :
9              
10 2     2   1804 use parent 'Test::Deep::Cmp';
  2         669  
  2         13  
11 2     2   3720 use Scalar::Util qw(blessed reftype);
  2         5  
  2         101  
12 2     2   1685 use Safe::Isa;
  2         891  
  2         261  
13 2     2   828 use Try::Tiny;
  2         1497  
  2         163  
14 2     2   1614 use namespace::clean;
  2         34195  
  2         16  
15 2     2   504 use Exporter 'import';
  2         4  
  2         1268  
16              
17             our @EXPORT = qw(is_type);
18              
19             sub is_type($)
20             {
21 9     9 1 19797 my $type = shift;
22 9         59 return __PACKAGE__->new($type);
23             }
24              
25             sub init
26             {
27 9     9 0 70 my ($self, $type) = @_;
28 9         176 $self->{type} = $type;
29             }
30              
31             sub descend
32             {
33 9     9 0 43315 my ($self, $got) = @_;
34 9         35 return $self->_is_type($self->{type}, $got);
35             }
36              
37             sub diag_message
38             {
39 5     5 0 1304 my ($self, $where) = @_;
40 5         19 my $name = $self->_type_name($self->{type});
41 5 100       1797 return "Validating $where as a"
42             . (defined $name ? ' ' . $name : 'n unknown')
43             . ' type';
44             }
45              
46             # we do not define a diagnostics sub, so we get the one produced by deep_diag
47             # showing exactly what part of the data structure failed. This calls renderGot
48             # and renderVal:
49              
50             sub renderGot
51             {
52 5     5 0 33 my $self = shift;
53 5 100       25 return defined $self->{error_message} ? $self->{error_message} : 'failed';
54             }
55              
56             sub renderExp
57             {
58 5     5 0 23 my $self = shift;
59 5         12 return 'no error';
60             }
61              
62             sub _is_type
63             {
64 9     9   17 my ($self, $type, $got) = @_;
65              
66 9 100       31 if ($type->$_can('validate'))
67             {
68 4         115 $self->{error_message} = $type->validate($got);
69 4         39 return !defined($self->{error_message});
70             }
71              
72             # last ditch effort - use the type as a coderef
73 5 100       49 if (__isa_coderef($type))
74             {
75             return try {
76 4     4   103 $type->($got)
77             } catch {
78 1     1   18 chomp($self->{error_message} = $_);
79 1         4 undef;
80 4         29 };
81             }
82              
83             # for now, stringy types are not supported. If a known Moose type, use
84             # Moose::Util::TypeConstraints::find_type_constraint('typename').
85              
86 1         60 $self->{error_message} = "Can't figure out how to use '$type' as a type";
87 1         4 return;
88             }
89              
90             sub _type_name
91             {
92 5     5   9 my ($self, $type) = @_;
93              
94             # use $type->name if we can
95 5     5   35 my $name = try { $type->name };
  5         145  
96 5 50       66 return $name if $name;
97              
98             # ...or stringify, if possible
99 5 100       27 return "$type" if overload::Method($type, '""');
100              
101             # ...or its package name, if it has one
102 4         1995 my $class = blessed($type);
103 4 100       16 return $class if defined $class;
104              
105             # plain old subref perhaps?
106 2         3 return;
107             }
108              
109             sub __isa_coderef
110             {
111 5 100 100 5   57 ref $_[0] eq 'CODE'
      100        
112             or (reftype($_[0]) || '') eq 'CODE'
113             or overload::Method($_[0], '&{}')
114             }
115              
116             1;
117              
118             __END__