package ExceptionChecker; use strict; use warnings; use Test::Unit::Error; use Test::Unit::Failure; use Error qw(:try); sub check_failures { my $self = shift; $self->check_exceptions('Test::Unit::Failure', @_); } sub check_errors { my $self = shift; $self->check_exceptions('Test::Unit::Error', @_); } sub check_exceptions { my $self = shift; my ($exception_class, @tests) = @_; my ($asserter, $file, $line) = caller($Error::Depth + 1); # EVIL hack! Assumes check_exceptions # always called via check_{failures,errors}. # My brain hurts too much right now to think # of a better way. while (@tests) { my $expected = shift @tests; my $test_components = shift @tests; my ($test_code_line, $test) = @$test_components; my $exception; try { $self->$test(); } catch $exception_class with { $exception = shift; } catch Error::Simple with { $exception = shift; } otherwise { $exception = 0; }; try { $self->check_exception($exception_class, $expected, $exception); $self->check_file_and_line($exception, $file, $test_code_line); } catch Test::Unit::Failure with { my $failure = shift; $failure->throw_new( -package => $asserter, -file => $file, -line => $line, -object => $self ); } } } sub check_exception { my $self = shift; my ($exception_class, $expected, $exception) = @_; Test::Unit::Failure->throw( -text => "Didn't get $exception_class `$expected'", -object => $self, ) unless $exception; my $got = $exception->text(); Test::Unit::Failure->throw( -text => "Expected $exception_class `$expected', got `$got'", -object => $self, ) unless UNIVERSAL::isa($expected, 'Regexp') ? $got =~ /$expected/ : $got eq $expected; } sub check_file_and_line { my $self = shift; my ($exception, $expected_file, $test_code_line) = @_; if ($exception->file() ne $expected_file) { throw Test::Unit::Failure( -text => "failure's file() should have returned $expected_file" . " (line $test_code_line), not " . $exception->file(), -object => $self, ); } if ($exception->line() != $test_code_line) { throw Test::Unit::Failure( -text => "failure's line() should have returned " . "$test_code_line, not " . $exception->line(), -object => $self, ); } } 1;