Skip to content
This repository
Fetching contributors…

Octocat-spinner-32-eaf2f5

Cannot retrieve contributors at this time

file 189 lines (168 sloc) 8.474 kb
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 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188
#!/usr/bin/perl

use strict;
use warnings;
use lib 't/lib';
use GenErrorRegex; # error-generating subs imported below

use Test::More;
use Test::Exception;


# This test file is all about making sure that errors are reported at the right places. That is,
# when you make a compile-time mistake, we should report the error at the place where you declare
# the method, and when you make a run-time mistake, we should report it at the place where you
# _call_ the method, not in the method itself, or (even worse) somewhere deep inside
# Method::Signatures.
#
# The errors we're concerned about are:
#
# *) The error thrown when you fail to pass a required argument.
# *) The error thrown when you pass a named argument that was not declared.
# *) The error thrown when you try to pass a type that is unrecognized.
# *) The error thrown when you try to pass an argument of the wrong type.
#
# This is mildly tricky, since trapping the error to check it means the error could end up reported
# as being in "eval 27" or somesuch. So we're going to use a few different layers of files that
# include each other to work around that for the run-time errors. For the compile-time errors,
# we'll just call require instead of use.
#
# Ready? Here we go.

my %compile_time_errors =
(
    BadParameter => {
                                error_gen => 'bad_param_error',
                                error_args => [
                                                    '&$bar',
                                                ],
                                test_name => 'illegal param spec reports correctly',
                            },
    TrailingGarbage => {
                                error_gen => 'unexpected_after_error',
                                error_args => [
                                                    '&',
                                                ],
                                test_name => 'trailing code after param reports correctly',
                            },
    NamedAfterOptPos => {
                                error_gen => 'named_after_optpos_error',
                                error_args => [
                                                    '$baz',
                                                    '$bar',
                                                ],
                                test_name => 'named param following optional positional reports correctly',
                            },
    PosAfterNamed => {
                                error_gen => 'pos_after_named_error',
                                error_args => [
                                                    '$baz',
                                                    '$bar',
                                                ],
                                test_name => 'positional param following named reports correctly',
                            },
    MispositionedSlurpy => {
                                error_gen => 'mispositioned_slurpy_error',
                                error_args => [
                                                    '@bar',
                                                ],
                                test_name => 'mispositioned slurpy param reports correctly',
                            },
    MultipleSlurpy => {
                                error_gen => 'multiple_slurpy_error',
                                error_args => [
                                                ],
                                test_name => 'multiple slurpy params reports correctly',
                            },
    NamedSlurpy => {
                                error_gen => 'named_slurpy_error',
                                error_args => [
                                                    '@bar',
                                                ],
                                test_name => 'named slurpy param reports correctly',
                            },
);

my %run_time_errors =
(
    MissingRequired => {
                                method => 'bar',
                                error_gen => 'required_error',
                                error_args => [
                                                    'InnerMissingRequired',
                                                    '$bar',
                                                    'foo',
                                                ],
                                test_name => 'missing required param reports correctly',
                            },
    NoSuchNamed => {
                                method => 'bar',
                                error_gen => 'named_param_error',
                                error_args => [
                                                    'InnerNoSuchNamed',
                                                    'bmoogle',
                                                    'foo',
                                                ],
                                test_name => 'no such named param reports correctly',
                            },
    UnknownType => {
                                method => 'bar',
                                error_gen => 'badtype_error',
                                error_args => [
                                                    'InnerUnknownType',
                                                    'Foo::Bmoogle',
                                                    'perhaps you forgot to load it?',
                                                    'foo',
                                                ],
                                test_name => 'unrecognized type reports correctly',
                            },
    BadType => {
                                method => 'bar',
                                error_gen => 'badval_error',
                                error_args => [
                                                    'InnerBadType',
                                                    'bar',
                                                    'Int',
                                                    'thing',
                                                    'foo',
                                                ],
                                test_name => 'incorrect type reports correctly',
                            },
);

# this is *much* easier (and less error-prone) than having to update the import list manually up top
GenErrorRegex->import( map { $_->{error_gen} } values %compile_time_errors, values %run_time_errors );


while (my ($testclass, $test) = each %compile_time_errors)
{
    (my $testmod = "$testclass.pm") =~ s{::}{/}g;
    no strict 'refs';

    throws_ok { require $testmod }
            $test->{error_gen}->(@{$test->{error_args}}, FILE => "t/lib/$testmod", LINE => 1133),
            $test->{test_name};
}

while (my ($testclass, $test) = each %run_time_errors)
{
    (my $testmod = "$testclass.pm") =~ s{::}{/}g;
    no strict 'refs';

    lives_ok { require $testmod } "$testclass loads correctly";
    throws_ok { &{ $testclass . '::' . $test->{method} }->() }
            $test->{error_gen}->(@{$test->{error_args}}, FILE => "t/lib/$testmod", LINE => 1133),
            $test->{test_name};
}


# modifiers bad type value checks (handled a bit differently than those above)
SKIP:
{
    eval { require MooseX::Declare } or skip "MooseX::Declare required for this test", 1;

    # different modifiers will throw different types in their errors
    my %bad_types =
    (
        before => 'Int',
        around => 'Int',
        after => 'Num',
        override => 'Int',
        augment => 'Num',
    );

    lives_ok { require ModifierBadType } 'incorrect type loads correctly';

    foreach ( qw< before around after override augment > )
    {
        my $test_meth = "test_$_";
        my $error_args = [ 'Foo::Bar', num => $bad_types{$_} => 'thing', $test_meth, ];

        throws_ok{ ModifierBadType::bar($test_meth) }
                badval_error(@$error_args, FILE => 't/lib/ModifierBadType.pm', LINE => 1133),
                "incorrect type for $_ modifier reports correctly";
    }
}


done_testing;
Something went wrong with that request. Please try again.