File Coverage

blib/lib/Aion/Meta/RequiresFeature.pm
Criterion Covered Total %
statement 35 47 74.4
branch 14 40 35.0
condition 1 15 6.6
subroutine 9 9 100.0
pod 3 3 100.0
total 62 114 54.3


line stmt bran cond sub pod time code
1             package Aion::Meta::RequiresFeature;
2              
3 5     5   558 use common::sense;
  5         8  
  5         25  
4              
5 5     5   304 use Aion::Meta::Util qw//;
  5         8  
  5         77  
6 5     5   14 use List::Util qw/pairmap/;
  5         8  
  5         321  
7 5     5   21 use Scalar::Util qw/looks_like_number reftype blessed refaddr/;
  5         6  
  5         4490  
8              
9             Aion::Meta::Util::create_getters(qw/pkg name opt has/);
10              
11             # Конструктор
12             sub new {
13 2     2 1 9 my ($cls, $pkg, $name, @has) = @_;
14 2   33     25 bless {pkg => $pkg, name => $name, opt => {@has}, has => \@has}, ref $cls || $cls;
15             }
16              
17             # Строковое представление фичи
18             sub stringify {
19 2     2 1 8 my ($self) = @_;
20 4     4   4 my $has = join ', ', pairmap { "$a => ${\
21 4         14 Aion::Meta::Util::val_to_str($b)
22 2         8 }" } @{$self->{has}};
  2         12  
23 2         23 return "req $self->{name} => ($has) of $self->{pkg}";
24             }
25              
26             # Сравнивает с фичей, но только значения которые есть в этой
27             sub compare {
28 3     3 1 11 my ($self, $feature) = @_;
29              
30 3 100       12 die "Requires ${\$self->stringify}" unless UNIVERSAL::isa($feature, 'Aion::Meta::Feature');
  1         3  
31              
32 2         3 for my $key (keys %{$self->{opt}}) {
  2         10  
33 4         8 my $value = $self->{opt}{$key};
34 4         7 my $feature_value = $feature->{opt}{$key};
35            
36 4 50       9 die "Feature mismatch ($key => ${\
37 0         0 Aion::Meta::Util::val_to_str($value)
38             } != ${\
39 0         0 Aion::Meta::Util::val_to_str($feature_value)
40 0         0 }) with ${\$self->stringify}"
41             unless _deep_equal($value, $feature_value);
42             }
43             }
44              
45             # Сравнивает два значения
46             sub _deep_equal {
47 4     4   7 my ($value, $other_value) = @_;
48              
49 4 100       42 if (blessed $value) {
    50          
    50          
    50          
    50          
    50          
50 2 50       5 return "" unless blessed $other_value;
51              
52 2 50       8 if (overload::Method($value, '==')) {
    0          
53 2 50       189 return "" unless $value == $other_value;
54             }
55             elsif (overload::Method($value, 'eq')) {
56 0 0       0 return "" unless $value eq $other_value;
57             }
58             else {
59 0 0       0 return "" unless refaddr $value == refaddr $other_value;
60             }
61             }
62             elsif (looks_like_number($value)) {
63 0 0 0     0 return "" unless looks_like_number($other_value) && $value == $other_value;
64             }
65             elsif (reftype $value eq 'ARRAY') {
66 0         0 for(my $i = 0; $i <= $#$value; $i++) {
67 0 0       0 return "" unless _deep_equal($value->[$i], $other_value->[$i]);
68             }
69             }
70             elsif (reftype $value eq 'HASH') {
71 0         0 for my $k (keys %$value) {
72 0 0 0     0 return "" unless exists $other_value->{$k} && _deep_equal($value->{$k}, $other_value->{$k});
73             }
74             }
75             elsif (reftype $value eq 'SCALAR') {
76 0 0 0     0 return "" unless reftype $other_value eq 'SCALAR' && _deep_equal($$value, $$other_value);
77             }
78             elsif (reftype $value eq 'CODE') {
79 0 0 0     0 return "" unless reftype $other_value eq 'CODE' && refaddr $value == refaddr $other_value;
80             }
81             else {
82 2 50       6 return "" if $value ne $other_value;
83             }
84              
85 4         12 return 1;
86             }
87              
88             1;
89              
90             __END__