package tests::functional::LrProcessMailTest;

use strict;

use base qw/Lire::Test::FunctionalTestCase tests::functional::TestSchemaFixture/;
use Lire::Config::Build qw/ac_path ac_info/;
use Lire::ReportParser::ReportBuilder;
use Lire::Utils qw/tempdir file_content/;
use File::Basename qw/dirname/;
use Cwd 'realpath';
use Carp;
{
    # See LrMailTest.pm for rationale
    use utf8;
    use MIME::Parser;
}

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

    $self->tests::functional::TestSchemaFixture::init();

    $self->{'lr_processmail_path'} = ac_path( 'libexecdir', 'PACKAGE' ) . "/lr_processmail";
    $self->{'testsdir'} = realpath(dirname( __FILE__ ) . "/..");
    $self->{'report_cfg'} = "$self->{'testsdir'}/data/test.cfg";
    $self->{'parser'} = new MIME::Parser();
    my $tmpdir = tempdir( "MIME::Parser_XXXXXX", 'CLEANUP' => 1 );
    $self->{'parser'}->output_under( $tmpdir );

    return $self;
}

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

    $self->set_up_test_schemas();
    $self->set_up_test_specs();
    $self->set_up_TestDlfConverter();
    $self->set_up_test_analysers();

    return;
}

sub tear_down {
    my $self = $_[0];
    $self->SUPER::tear_down();
    $self->tests::functional::TestSchemaFixture::tear_down();
    return;
}

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

    my $result = $self->lire_run( "$self->{'lr_processmail_path'} test_newapi < $self->{'testsdir'}/data/test-compressed-anon.msg" );
    $self->annotate( $result->stderr() );
    $self->assert_equals( 0, $result->status() );
    $self->assert( !$result->stdout, "stdout should be empty" );
    $self->assert_does_not_match( qr/ (crit|err|warning) /, $result->stderr(),
                                  "There were warnings or error messages." );

    my $msg = $result->sent_mail();
    $self->assert_equals( 1, scalar @$msg );
    $self->assert_deep_equals( [ "flacoste+anon\@logreport.org" ],
                               $msg->[0]{'recipients'} );

    my $entity = $self->{'parser'}->parse_data( $msg->[0]{'message'} );
    my $head = $entity->head();
    $self->assert_equals( "[LogReport] test_newapi report (was: Test log file (compressed))\n",
                          $head->get( 'Subject' ) );
    $self->assert_equals( 'multipart/mixed', $head->mime_type() );

    # 2 parts: report, signature and disclaimer
    $self->assert_equals( 2, scalar $entity->parts() );

    my $report = $entity->parts( 0 );
    $self->assert_equals( "text/xml", $report->mime_type() );
    $self->check_xml_report( "$self->{'testsdir'}/data/test-sqlite.xml",
                             $report->bodyhandle()->as_string() );

    # Check that the explanation is there
    my $sig_disc = $entity->parts( 1 );
    $self->assert_equals( "text/plain", $sig_disc->mime_type() );
    $self->assert_matches( qr/LogReport/, 
                           $sig_disc->bodyhandle()->as_string() );
    $self->assert_matches( qr/raw Lire report/,
                           $sig_disc->bodyhandle()->as_string() );

}

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

    # Turn archiving on
    my $cfg = $self->create_test_cfg_file( "archive" );
    $cfg->global->get( 'lr_archive' )->set( 1 );

    my $result = $self->lire_run( "$self->{'lr_processmail_path'} test_newapi < $self->{'testsdir'}/data/test-regular.msg" );
    $self->annotate( $result->stderr() );
    $self->assert_equals( 0, $result->status() );
    $self->assert( !$result->stdout, "stdout should be empty" );
    $self->assert_does_not_match( qr/ (crit|err|warning) /, $result->stderr,
                                  "There were warnings or error messages." );

    my $msg = $result->sent_mail;
    $self->assert_equals( 1, scalar @$msg );
    $self->assert_deep_equals( [ "flacoste\@logreport.org" ],
                               $msg->[0]{'recipients'} );

    my $entity = $self->{'parser'}->parse_data( $msg->[0]{'message'} );
    my $head = $entity->head();
    $self->assert_equals( "[LogReport] test_newapi report (was: Test DLF file (uncrompressed))\n",
                          $head->get( 'Subject' ) );
    $self->assert_equals( 'text/plain', $head->mime_type );

    # Check that the signature was included
    $self->assert_matches( qr/LogReport/, $entity->bodyhandle()->as_string() );

    # Check archiving
    my $archivedir = ac_info( 'LR_ARCHIVEDIR' ) . "/email/raw/test/test_newapi/flacoste\@logreport.org";
    my ($id) = $result->stderr =~ /(lr_tag-[^ ]+)/;
    my $archivefile = $archivedir . "/$id.msg.gz";
    $self->assert( -d $archivedir, "$archivedir wasn't created" );
    $self->assert( -s $archivefile,
                   "Message wasn't archived in $archivefile" );
}

sub check_xml_report {
    my ($self, $expected_report, $report_data ) = @_;

    my $parser = new Lire::ReportParser::ReportBuilder;
    my $report_e = $parser->parsefile( $expected_report );
    my $report_t = $parser->parse( $report_data  );

    # The difference in these fields are normal
    $report_t->date( $report_e->date() );
    $report_t->generator( $report_e->generator() );
    delete $report_e->{'_id_cache'};

    $self->assert_deep_equals( $report_e, $report_t );
}

1;


syntax highlighted by Code2HTML, v. 0.9.1