package tests::DlfCategoriserTest;

use strict;

use base qw/ Lire::Test::TestCase tests::TestStoreFixture /;

use Lire::DlfCategoriser;
use Lire::DlfAnalyserProcess;
use Lire::PluginManager;
use Time::Local;
use Class::Inner;

sub new {
    my $self = shift()->SUPER::new( @_ );

    $self->init();

    $self->{'config'} = { 'name' => 'value' };
    $self->{'20040311_121201'} = timelocal( 1, 12, 12, 11, 2, 2004 );

    return $self;
}

sub set_up {
    my $self = $_[0];
    $self->SUPER::set_up();

    $self->set_up_test_schema();
    $self->set_up_test_store();
    $self->set_up_plugin_mgr();
    push@{$self->{'cfg'}{'lr_schemas_path'}},
      "$self->{'testdir'}/../../schemas";

    return;
}

sub tear_down {
    my $self = $_[0];
    $self->SUPER::tear_down();

    $self->tear_down_test_store();

    return;
}

sub test_analyse {
    my $self = $_[0];

    my $categoriser =
      new Class::Inner( 'parent' => 'Lire::DlfCategoriser',
                        'methods' =>
                        {
                         'new' => sub { bless [], shift },
                         'name' => sub { 'extended' },
                         'src_schema' => sub { 'test' },
                         'dst_schema' => sub { 'test-extended' },
                         'initialise' => sub { push @{$_[0]}, [ 'initialise',
                                                                @_ ] },
                         'categorise' => sub { push @{$_[0]}, [ 'categorise',
                                                                @_ ] },
                         'finalise' => sub { push @{$_[0]}, [ 'finalise', @_]},
                        } );
    my $process = $self->create_mock_process( $categoriser );

    my $stream = $self->{'store'}->open_dlf_stream( 'test', 'w' );
    $stream->clean();
    $stream->write_dlf( { 'time_start' => $self->{'20040311_121201'} -86400,
                          'dlf_source' => 'a_source' } );
    $stream->write_dlf( { 'time_start' => $self->{'20040311_121201'} - 3600,
                          'dlf_source' => 'my_source' } );
    $stream->write_dlf( { 'time_start' => $self->{'20040311_121201'},
                          'dlf_source' => 'my_source' } );
    $stream->write_dlf( { 'time_start' => $self->{'20040311_121201'} +3600,
                          'dlf_source' => 'my_source' } );
    $stream->write_dlf( { 'time_start' => $self->{'20040311_121201'} +86400,
                          'dlf_source' => 'another_source' } );
    $stream->close();

    $process->run_analysis_job( $self->{'20040311_121201'} );

    $self->assert_num_equals( 5, scalar @$categoriser );
    $self->assert_str_equals( 'initialise', $categoriser->[0][0] );
    $self->assert_str_equals( 'categorise', $categoriser->[1][0] );
    $self->assert_num_equals( $self->{'20040311_121201'} -3600,
                              $categoriser->[1][2]{'time_start'} );
    $self->assert_num_equals( $self->{'20040311_121201'},
                              $categoriser->[2][2]{'time_start'} );
    $self->assert_num_equals( $self->{'20040311_121201'} +3600,
                              $categoriser->[3][2]{'time_start'} );
    $self->assert_str_equals( 'finalise', $categoriser->[4][0] );

    $self->assert_null( $process->{'errors'} );
    $self->assert_num_equals( 3, scalar @{$process->{'dlf'}} );
    $self->assert_num_equals( $self->{'20040311_121201'} -3600,
                              $process->{'dlf'}[0]{'time_start'} );
    $self->assert_num_equals( $self->{'20040311_121201'},
                              $process->{'dlf'}[1]{'time_start'} );
    $self->assert_num_equals( $self->{'20040311_121201'} +3600,
                              $process->{'dlf'}[2]{'time_start'} );
}

sub test_analyse_derived {
    my $self = $_[0];

    my $categoriser =
      new Class::Inner( 'parent' => 'Lire::DlfCategoriser',
                        'methods' =>
                        {
                         'new' => sub { bless [], shift },
                         'name' => sub { 'derived' },
                         'src_schema' => sub { 'test' },
                         'dst_schema' => sub { 'test-derived' },
                        } );
    my $process = $self->create_mock_process( $categoriser );
    $self->assert_dies( qr/'derived' analyser doesn't declare to write to an ExtendedSchema: 'test-derived'/,
                        sub { $categoriser->analyse( $process, {} ) } );
}

sub test_analyse_failing_initialise {
    my $self = $_[0];

    my $categoriser =
      new Class::Inner( 'parent' => 'Lire::DlfCategoriser',
                        'methods' =>
                        {
                         'new' => sub { bless [], shift },
                         'name' => sub { 'failing_initialise' },
                         'src_schema' => sub { 'test' },
                         'dst_schema' => sub { 'test-extended' },
                         'initialise' => sub { die "Failed\n" },
                        } );
    my $process = $self->create_mock_process( $categoriser );
    my $stream = $self->{'store'}->open_dlf_stream( 'test', 'w' );
    $stream->clean();
    $stream->write_dlf( { 'time_start' => $self->{'20040311_121201'}} );
    $stream->close();

    $process->run_analysis_job( $self->{'20040311_121201'} );
    $self->assert_null( $process->{'dlf'} );
    $self->assert_deep_equals( [ "Error during initialise: Failed\n" ],
                               $process->{'errors'} );
}

sub test_analyse_failing_categorise {
    my $self = $_[0];

    my $categoriser =
      new Class::Inner( 'parent' => 'Lire::DlfCategoriser',
                        'methods' =>
                        {
                         'new' => sub { bless [], shift },
                         'name' => sub { 'failing_categorise' },
                         'src_schema' => sub { 'test' },
                         'dst_schema' => sub { 'test-extended' },
                         'initialise' => sub {},
                         'categorise' => sub { die "Failed\n" },
                        } );
    my $process = $self->create_mock_process( $categoriser );
    my $stream = $self->{'store'}->open_dlf_stream( 'test', 'w' );
    $stream->clean();
    $stream->write_dlf( { 'time_start' => $self->{'20040311_121201'} - 3600,
                          'dlf_source' => 'my_source' } );
    $stream->write_dlf( { 'time_start' => $self->{'20040311_121201'} ,
                          'dlf_source' => 'my_source' } );
    $stream->close();

    $process->run_analysis_job( $self->{'20040311_121201'} );
    $self->assert_deep_equals( [ "Failed\n", "Failed\n", ],
                               $process->{'errors'} );
    $self->assert_null( $process->{'dlf'} );
}

sub create_mock_process {
    my ($self, $categoriser) = @_;

    Lire::PluginManager->register_plugin( $categoriser );
    return
      new Class::Inner( 'parent' => 'Lire::DlfAnalyserProcess',
                        'args' => [ $self->{'store'}, $categoriser->name(),
                                    $self->{'config'}, 'my_source' ],
                        'methods' =>
                        {
                         'error' => sub { $_[0]{'errors'} ||= [];
                                          push @{$_[0]{'errors'}}, $_[1] },
                         'write_dlf' => sub { $_[0]{'dlf'} ||= [];
                                              push @{$_[0]{'dlf'}}, $_[1] }
                        } );
}

1;


syntax highlighted by Code2HTML, v. 0.9.1