package tests::DlfAnalyserProcessTest;

use strict;

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

use Lire::DlfAnalyser;
use Lire::DlfAnalyserProcess;
use Lire::PluginManager;
use Time::Local;
use Lire::Test::Mock;

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

    $self->init();

    $self->{'analyser'} =
      new_proxy Lire::Test::Mock( 'Lire::DlfAnalyser' );
    $self->{'analyser'}->set_result( 'name' => 'analyser',
                                     'src_schema' => 'test',
                                     'dst_schema' => 'test-derived',
                                     'analyse' => '' );
    return $self;
}

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

    $self->set_up_test_schema();
    $self->set_up_test_store();

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

    $self->{'cfg'}{'lr_week_numbering'} = 'U';
    push@{$self->{'cfg'}{'lr_schemas_path'}},
      "$self->{'testdir'}/../../schemas";

    $self->set_up_plugin_mgr();
    Lire::PluginManager->register_plugin( $self->{'analyser'} );

    $self->{'analyser_cfg'} = { 'name' => 'value' };
    $self->{'process'} = new Lire::DlfAnalyserProcess( $self->{'store'},
                                                       'analyser',
                                                       $self->{'analyser_cfg'},
                                                       'my_source' );
    return;
}

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

    $self->SUPER::tear_down();

    return;
}

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

    my $config = $self->{'analyser_cfg'};
    $self->assert_dies( qr/no analyser 'test' was registered/,
                        sub { new Lire::DlfAnalyserProcess( $self->{'store'},
                                                            'test',
                                                            $config ) } );
    my $process = $self->{'process'};
    $self->assert_isa( 'Lire::DlfAnalyserProcess', $process );
    $self->assert_str_equals( $self->{'store'}, $process->{'_store'} );
    $self->assert_str_equals( $self->{'store'}, $process->dlf_store() );
    $self->assert_str_equals( 'analyser', $process->{'_analyser'} );
    $self->assert_str_equals( 'analyser', $process->dlf_analyser() );
    $self->assert_str_equals( $config, $process->{'_analyser_config'} );
    $self->assert_str_equals( $config, $process->dlf_analyser_config() );
    $self->assert_str_equals( 'my_source', $process->{'_dlf_source'} );
    $self->assert_str_equals( 'my_source', $process->dlf_source() );

}

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

    my $process = $self->{'process'};
    $process->_init_process( $self->{'20040311_121201'} );
    $self->assert_num_equals( $self->{'20040311_121201'},
                              $process->{'_time'} );
    $self->assert_num_equals( 0, $process->{'_dlf_count'} );
    $self->assert_num_equals( 0, $process->{'_error_count'} );
    $self->assert_str_equals( $process->{'_job_id'},
                              'analyser-20040311_121201' );

    $self->assert_isa( 'Lire::DlfStream', $process->{'_dlf_stream'} );
    $self->assert_str_equals( 'w', $process->{'_dlf_stream'}->mode() );
    $self->assert_str_equals( 'test-derived',
                              $process->{'_dlf_stream'}->name() );
    $self->assert_isa( 'Lire::DlfStream', $process->{'_log_stream'} );
    $self->assert_str_equals( 'w', $process->{'_log_stream'}->mode() );
    $self->assert_str_equals( 'lire_import_log',
                              $process->{'_log_stream'}->name() );
}

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

    my $process = $self->{'process'};
    my $filter = $process->source_filter();
    $self->assert_isa( 'Lire::FilterExpr::DlfSource', $filter );
    $self->assert_str_equals( 'my_source', $filter->value() );

    $process->{'_dlf_source'} = undef;
    $self->assert_null( undef, $process->source_filter() );
}

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

    my $process = $self->{'process'};
    $process->_init_process( $self->{'20040311_121201'} );

    my @args = ();
    no warnings 'redefine';
    local *Lire::DlfStream::write_dlf = sub { @args = @_ };
    my $dlf = { 'connection_id' => 'test' };
    my $dlf_ids = [ 1 ];
    $process->write_dlf( { %$dlf }, $dlf_ids );
    $dlf->{'dlf_source'} = 'analyser-20040311_121201';
    $self->assert_deep_equals( [ $process->{'_dlf_stream'},
                                 $dlf, $dlf_ids ], \@args );
    $self->assert_num_equals( 1, $process->{'_dlf_count'} );
}

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

    my $process = $self->{'process'};
    $process->_init_process( $self->{'20040311_121201'} );

    my @args = ();
    no warnings 'redefine';
    local *Lire::DlfStream::write_dlf = sub { @args = @_ };
    $process->error( 'My error' );
    $self->assert_str_equals( $process->{'_log_stream'}, $args[0] );
    $self->assert_str_equals( 'analyser', $args[1]{'job_name'} );
    $self->assert_str_equals( 'analyser-20040311_121201', $args[1]{'job_id'} );
    $self->assert_not_null( $args[1]{'time'} );
    $self->assert_str_equals( 'error', $args[1]{'type'} );
    $self->assert_str_equals( 'My error', $args[1]{'msg'} );

    $self->assert_num_equals( 1, $process->{'_error_count'} );

}

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

    my $process = $self->{'process'};
    $process->_init_process( $self->{'20040311_121201'} );
    $process->{'_dlf_count'} = 45;
    $process->{'_error_count'} = 1;

    $process->_save_analysis_stats();
    my $stream = $self->{'store'}->open_dlf_stream( 'lire_import_stats', 'r' );
    my $stats = $stream->read_dlf();
    $stream->close();
    $self->assert_str_equals( $self->{'20040311_121201'},
                              $stats->{'time_start'} );
    $self->assert( ( time() - $self->{'20040311_121201'} )
                   >= $stats->{'elapsed'} );
    $self->assert_str_equals( 'analyser', $stats->{'job_name'} );
    $self->assert_str_equals( "analyser-20040311_121201",
                              $stats->{'job_id'} );
    $self->assert_num_equals( 45, $stats->{'dlf_count'} );
    $self->assert_num_equals( 1, $stats->{'error_count'} );
}

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

    my $process = $self->{'process'};
    $process->run_analysis_job();

    $self->assert_num_equals( 1, $self->{'analyser'}->invocation_count( 'analyse' ) );
    $self->assert_deep_equals( [ $self->{'analyser'}, $self->{'process'},
                                 $self->{'analyser_cfg'} ],
                               $self->{'analyser'}->get_invocation( 'analyse' ) );
    $self->assert_null( $process->{'_log_stream'}, 'was stream closed?' );
    $self->assert_null( $process->{'_dlf_stream'}, 'was stream closed?' );
}

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

    my $failing = new_proxy Lire::Test::Mock( 'Lire::DlfAnalyser' );
    $failing->set_result('name' => 'failing',
                         'src_schema' => 'test',
                         'dst_schema' => 'test-derived',
                         'analyse' => sub { die "Failed\n" } );

    Lire::PluginManager->register_plugin( $failing );
    my $process = new_proxy Lire::Test::Mock( 'Lire::DlfAnalyserProcess',
                                              $self->{'store'},
                                              'failing', {} );
    $process->run_analysis_job();
    $self->assert_num_equals( 1, $process->invocation_count( 'error' ) );
    $self->assert_deep_equals( [ $process, "Failed\n" ],
                               $process->get_invocation( 'error' ) );
}

1;


syntax highlighted by Code2HTML, v. 0.9.1