The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.
#!/usr/bin/perl

package Log::Dispatch::Config::TestLog;

use strict;
use warnings;

our $VERSION = "0.02";

use Sub::Override;
use Test::Builder;
use Log::Dispatch::Config;
use Path::Class;

use base qw(Log::Dispatch::Configurator);

sub new {
    my ( $class, %args ) = @_;

    bless {
		%args,
        global => {
            dispatchers => [qw(file)],
			%{ $args{global} || {} }
        },
        file => {
            class     => 'Log::Dispatch::File',
            min_level => 'debug',
			%{ $args{file} || {} }
        },
    }, $class;
}

sub get_attrs {
    my ( $self, $name ) = @_;
    $self->{$name};
}

sub get_attrs_global { shift->get_attrs("global") }

sub needs_reload { return }

sub caller_file_to_log_file {
	my ( $self, $file, %args ) = @_;

	my $log_dir = dir( $ENV{TEST_LOG_DIR} || $args{log_dir} || $file->parent );

	unless ( -d $log_dir ) {
		$log_dir->mkpath
			or die "Couldn't create test log directory $log_dir";
	}

	unless ( -w $log_dir ) {
		die "Log directory $log_dir is not writable";
	}

	return $log_dir->file( $file->basename . ".log" )->stringify;
}

my @overrides;

sub import {
    my ( $self, %args ) = @_;

	require Test::Builder;

	my $file = file($0)->absolute;

    Log::Dispatch::Config->configure(
        $self->new(
			%args,
            file => {
				mode     => "write",
				filename => $self->caller_file_to_log_file( $file, %args ),
				format   => "[%d] [%p] %m\n",
				%{ $args{file} || {} }
			},
        ),
    );

	my $logger = Log::Dispatch::Config->instance;

	$logger->info("Starting test $0, pid = $$");

	my $tap_level = exists($args{tap_log_level})
		? $args{tap_log_level}
		: "info";

	if ( defined( $tap_level ) ) {
		
		unless ( @overrides ) {
			foreach my $print ( qw(_diag _print_to_fh) ) {
				no strict 'refs';
				my $fq = "Test::Builder::$print";
				my $orig = \&$fq;

				push @overrides, Sub::Override->new( $fq, sub {
					my ( $builder, @output ) = @_;
					shift @output if $print eq '_print_to_fh'; # first arg is output handle
					chomp( my $out = "@output" );
					$logger->$tap_level("TAP: $out") if length $out;
					goto $orig;
				});
			}
		}
	}
}

END {
    Log::Dispatch::Config->__instance && Log::Dispatch::Config->instance->info("Finishing test $0");
}

__PACKAGE__

__END__

=pod

=head1 NAME

Log::Dispatch::Config::TestLog - Set up Log::Dispatch::Config for a test run

=head1 SYNOPSIS

	use Log::Dispatch::Config::TestLog;

=head1 DESCRIPTION

This module will load L<Log::Dispatch::Config> and set things up so that:

=over 4

=item *

By default there is a single dispatcher, C<file>, a L<Log::Dispatch::File>
instance, whose output is the name of the test appended with C<log>.

If the environment variable C<TEST_LOG_DIR> is set or the C<log_dir> parameter
is given to C<import>, then log files will be created in that directory
instead.

=item *

All TAP output is logged with the C<info> level by default. If the C<tap_level>
parameter is given to C<import> then that level will be used instead. C<undef>
can be passed to disable TAP output.

Note that this only works for L<Test::Builder> based tests.

=back

=head1 TODO

=over 4

=item Better test logging

Make the test logging use different levels for certain things (fails increase
the level, for instance), and consider scrubbing multi line output since we
provide a one line format by default.

=back

=head1 VERSION CONTROL

L<http://github.com/nothingmuch/log-dispatch-config-testlog>

=head1 AUTHOR

Yuval Kogman E<lt>nothingmuch@woobling.orgE<gt>

=head1 COPYRIGHT

	Copyright (c) 2008, 2010 Yuval Kogman. All rights reserved
	This program is free software; you can redistribute
	it and/or modify it under the same terms as Perl itself.

=cut