package tests::ReportConfigTest;
use strict;
use base qw/Lire::Test::TestCase tests::TestStoreFixture/;
use Lire::ReportSpec;
use Lire::FilterSpec;
use Lire::ReportSection;
use Lire::ReportConfig;
use Lire::I18N;
use Lire::Utils qw/tempfile tempdir deep_copy/;
use Lire::ReportParser::ReportBuilder;
use Lire::PluginManager;
use Lire::Config::ReportSpec;
use Lire::Config::SpecParser;
use tests::helpers::TestExtendedAnalyzer;
use tests::helpers::TestDerivedAnalyzer;
use Lire::Test::Mock;
use File::Path qw/rmtree/;
use File::Copy qw/copy/;
#our @TESTS = qw//;
sub new {
my $self = shift()->SUPER::new( @_ );
$self->init();
return $self;
}
sub set_up {
my $self = shift->SUPER::set_up();
$self->set_up_test_schema();
$self->set_up_tz( 'EST5' );
$self->{'cfg'}{'lr_scale_numbers'} = 0;
$self->{'cfg'}{'lr_scale_bytes'} = 1;
$self->{'cfg'}{'lr_scale_seconds'} = 1;
$self->{'report_cfg'} = $self->{'testdir'} . "/data/test.cfg";
$self->{'cfg'}{'lr_reports_path'} = [ $self->{'testdir'} . "/reports" ];
$self->{'cfg'}{'lr_filters_path'} = [ $self->{'testdir'} . "/filters" ];
( $self->{'tmp_fh'}, $self->{'tmp_filename'} ) = tempfile();
return $self;
}
sub set_up_plugins {
my $self = $_[0];
$self->set_up_plugin_mgr();
Lire::PluginManager->register_plugin( new tests::helpers::TestExtendedAnalyzer() );
Lire::PluginManager->register_plugin( new tests::helpers::TestDerivedAnalyzer() );
return;
}
sub tear_down {
my $self = shift->SUPER::tear_down();
unlink ($self->{'tmp_filename'});
rmtree( $self->{'tmpdir'} )
if defined $self->{'tmpdir'};
$Lire::Config::TEMPLATES = undef;
return $self;
}
sub add_to_section {
my ( $self, $section, $specs ) = @_;
# Specs: [ [ 'id', { param1 => value, ... } ], ... ]
foreach my $s ( @$specs ) {
my ( $id, $params ) = @$s;
my $spec;
if ( substr( $id, 0, 1) eq '|' ) {
$spec = Lire::FilterSpec->load( 'test', substr( $id, 1 ) );
$section->add_filter( $spec );
} else {
$spec = Lire::ReportSpec->load( 'test', $id );
$self->{'_id_cache'}{$id} ||= 0;
$spec->subreport_id( $id . "." . $self->{'_id_cache'}{$id}++ );
$section->add_report( $spec );
}
for my $param ( keys %$params ) {
$spec->param( $param )->value( $params->{$param} );
}
}
}
sub build_expected_cfg {
my $self = $_[0];
my $cfg = new Lire::ReportConfig();
$cfg->{'_filename'} = $self->{'report_cfg'};
my $all_section = new Lire::ReportSection( "test", "All Files" );
$cfg->add_section( $all_section );
$self->add_to_section( $all_section,
[ [ 'top-files', { 'files_to_show' => 5 } ],
[ 'top-dirs', { 'dirs_to_show' => 5 } ],
[ 'downloads-by-period',
{ 'period' => '15m' } ] ] );
my $jpeg_section = new Lire::ReportSection( "test", "JPEG Files" );
$cfg->add_section( $jpeg_section );
$self->add_to_section( $jpeg_section,
[ [ '|select-file', { 'file_match' => '.*.jpg$' }],
[ 'top-files', { 'files_to_show' => 5, } ],
[ 'top-dirs', { 'dirs_to_show' => 5 } ] ] );
my $sess_section = new Lire::ReportSection( "test", "Sessions" );
$cfg->add_section( $sess_section );
$self->add_to_section( $sess_section,
[[ 'sessions-by-length', {} ],
[ 'sessions-by-user_class', {} ] ] );
my $dl_section = new Lire::ReportSection( "test", "Download Reports" );
$cfg->add_section( $dl_section );
$self->add_to_section( $dl_section,
[ ['avg-file_size-by-timeslot', { 'unit' => '1h' }],
[ 'user_downloads-report', {} ] ] );
return $cfg;
}
sub test_load_from_file {
my $self = $_[0];
my $e_cfg = $self->build_expected_cfg();
my $cfg = Lire::ReportConfig->new_from_file( "test", $self->{'report_cfg'} );
$self->assert_deep_equals( $e_cfg, $cfg );
}
sub test_parse_encoding_line {
my $self = $_[0];
return unless $Lire::I18N::USE_ENCODING;
my $fh = $self->{'tmp_fh'};
print $fh "This is an eacute: \xc3\xa9\n";
close $fh;
open $fh, $self->{'tmp_filename'};
my $cfg = new Lire::ReportConfig( 'test' );
$cfg->{'_fh'} = $fh;
$cfg->{'_curr_section'} = '1';
local $. = 2; # prevents warning
$self->assert_dies( qr/'encoding' directive must be the first directive/,
sub { $cfg->_parse_encoding_line( '=encoding test' ); } );
$cfg->{'_curr_section'} = undef;
$self->assert_dies( qr/invalid 'encoding' directive, at line/,
sub { $cfg->_parse_encoding_line ( '=encoding' ); } );
$self->assert_dies( qr/invalid 'encoding' directive, at line/,
sub { $cfg->_parse_encoding_line( '=encoding wa wa' ); });
$cfg->_parse_encoding_line( '=encoding utf-8' );
$self->assert_equals( $cfg->{'_encoding'}, 'utf-8' );
my $line = <$fh>;
$self->assert_str_equals( "This is an eacute: \x{e9}\n", $line );
$self->assert_dies( qr/only one 'encoding' directive allowed, at line/,
sub { $cfg->_parse_encoding_line ( '=encoding test' ) } );
}
sub test_parse_encoding_line_no_support {
my $self = $_[0];
local $Lire::I18N::USE_ENCODING = 0;
local $. = 2; # prevents warning
my $cfg = new Lire::ReportConfig( 'test' );
$self->assert_dies( qr/'encoding' directive requires perl >= 5.8.0, at line/,
sub { $cfg->_parse_encoding_line ( '=encoding UTF-8' ) });
}
sub test_schemas {
my $self = $_[0];
my $cfg = Lire::ReportConfig->new_from_file("test", $self->{'report_cfg'});
$self->assert_deep_equals( [ sort 'test', 'test-extended', 'test-derived' ],
[ sort @{$cfg->schemas()} ] );
}
sub test_print {
my $self = $_[0];
return unless $Lire::I18N::USE_ENCODING;
my $fh = $self->{'tmp_fh'};
my $cfg = new Lire::ReportConfig( 'test' );
$cfg->{'_encoding'} = 'utf-8';
my $sect = new Lire::ReportSection( 'test', "Eacute: \x{00e9}" );
$cfg->add_section( $sect );
$self->add_to_section( $sect,
[ [ '|select-file', { 'file_match' => '.*.jpg$' }],
[ 'top-files', { 'files_to_show' => 5, } ] ] );
$cfg->print( $fh );
close $fh;
open $fh, $self->{'tmp_filename'};
local $/ = undef;
my $file = <$fh>;
$self->assert_equals( <<EOC, $file );
=encoding utf-8
=section Eacute: \xc3\xa9
|select-file file_match=".*.jpg\$"
top-files files_to_show="5"
EOC
}
sub test_create_report {
my $self = $_[0];
my $section = new Lire::Test::Mock ( 'Lire::ReportSection' );
my $cfg = new Lire::ReportConfig();
$cfg->add_section( $section );
my $now = time();
my $report = $cfg->create_report( $now, $now + 3600 );
$self->assert_isa( 'Lire::Report', $report );
$self->assert_num_equals( $now, $report->timespan_start() );
$self->assert_num_equals( $now +3600 , $report->timespan_end() );
$self->assert_null( $report->title() );
$self->assert_deep_equals( [ $section, $report ], $section->get_invocation( 'create_report_section' ) );
$cfg->title( 'My title' );
$report = $cfg->create_report( $now, $now + 3600 );
$self->assert_str_equals( 'My title', $report->title() );
}
sub test_generate_report {
my $self = $_[0];
$self->set_up_test_store();
$self->set_up_plugins();
my $parser = new Lire::ReportParser::ReportBuilder();
my $report_e = $parser->parsefile( "$self->{'testdir'}/data/test-sqlite.xml" );
my $cfg = new_from_file Lire::ReportConfig( 'test',
$self->{'report_cfg'} );
$cfg->create_analyser_streams( $self->{'store'} );
my $report_t = $cfg->generate_report( $self->{'store'} );
$self->assert_isa( 'Lire::Report', $report_t );
# 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 );
}
sub test_create_analyser_streams {
my $self = $_[0];
$self->set_up_test_store();
$self->set_up_plugins();
$self->assert( $self->{'store'}->has_dlf_stream( 'test' ) );
$self->assert( ! $self->{'store'}->has_dlf_stream( 'test-extended' ) );
$self->assert( ! $self->{'store'}->has_dlf_stream( 'test-derived' ) );
my $cfg = new_from_file Lire::ReportConfig( 'test',
$self->{'report_cfg'} );
$cfg->create_analyser_streams( $self->{'store'} );
$self->assert( $self->{'store'}->has_dlf_stream( 'test-extended' ) );
my $extended = $self->{'store'}->open_dlf_stream( 'test-extended' );
$self->assert_num_equals( 24, $extended->nrecords() );
$self->assert_str_equals( '/pictures',
$extended->read_dlf()->{'dirname'} );
$extended->close();
$self->assert( $self->{'store'}->has_dlf_stream( 'test-derived' ) );
my $derived = $self->{'store'}->open_dlf_stream( 'test-derived', 'r',
'connection_id' );
$self->assert_num_equals( 5, $derived->nrecords() );
$self->assert_str_equals( 'AABBCCDD',
$derived->read_dlf()->{'connection_id'} );
$derived->close();
}
sub test_new_from_config {
my $self = $_[0];
my $cfg_spec = new Lire::Config::ReportSpec( 'name' => 'report' );
my $report_cfg = $cfg_spec->instance();
$report_cfg->get( 'id' )->set( 'My Report' );
$report_cfg->get( 'title' )->set( 'My title' );
my $section1 = $cfg_spec->get( 'sections' )->get( 'section' )->instance();
$section1->get( 'superservice' )->set( 'test' );
$section1->get( 'title' )->set( 'My title' );
$report_cfg->get( 'sections' )->append( $section1 );
my $cfg = $report_cfg->as_value();
$self->assert_isa( 'Lire::ReportConfig', $cfg );
$self->assert_str_equals( 'My title', $cfg->title() );
$self->assert_num_equals( 1, scalar $cfg->sections() );
}
sub _set_up_templates {
my $self = $_[0];
$self->{'tmpdir'} = tempdir( __PACKAGE__ . "_XXXXXX" );
copy( "$self->{'testdir'}/data/test_report_cfg.xml",
"$self->{'tmpdir'}/test_default.xml" );
$self->{'cfg'}{'lr_templates_path'} = [ $self->{'tmpdir'} ];
my $parser = new Lire::Config::SpecParser();
$self->{'templates'} = $parser->parsefile( "$self->{'testdir'}/data/test_report_cfg.xml" );
}
sub test_templates {
my $self = $_[0];
$self->_set_up_templates();
$self->assert_deep_equals( {}, \%Lire::ReportConfig::TEMPLATES );
local $Lire::ReportConfig::TEMPLATES{'test'} = 1;
$self->assert_deep_equals( [ 'test', 'test_default', ],
[ sort @{Lire::ReportConfig->templates()} ] );
$self->assert_deep_equals( { 'test' => 1 },
\%Lire::ReportConfig::TEMPLATES );
$self->assert( !Lire::ReportConfig->has_template( 'test_1' ) ? 1 : 0,
'!has_template( "test_1" )' );
$self->assert( Lire::ReportConfig->has_template( 'test' ) ? 1 : 0,
'has_template( "test" )' );
$self->assert( Lire::ReportConfig->has_template( 'test_default' ) ? 1 : 0,
'has_template( "test_default" )' );
$self->assert_num_equals( 1, Lire::ReportConfig->template( 'test' ) );
my $template = Lire::ReportConfig->template( 'test_default' );
$self->assert_isa( 'Lire::Config::Object', $template );
$self->assert_str_equals( 'test_default', $template->name() );
$self->assert_deep_equals( { 'test_default' => $self->{'templates'}->get( 'test_default' )->instance(),
'test' => 1 },
\%Lire::ReportConfig::TEMPLATES );
$self->assert_str_equals( $template,
Lire::ReportConfig->template( 'test_default' ) );
}
sub test_as_config_value {
my $self = $_[0];
my $cfg = new Lire::ReportConfig();
my $section = new Lire::ReportSection( 'test', 'My section' );
$cfg->add_section( $section );
my $select = Lire::FilterSpec->load( 'test', 'select-file' );
$select->param( 'file_match')->value( 'my_file' );
$section->add_filter( $select );
my $top_dirs = Lire::ReportSpec->load( 'test', 'top-dirs' );
$top_dirs->subreport_id( 'top-dirs.0' );
$top_dirs->param( 'dirs_to_show' )->value( 5 );
$section->add_report( $top_dirs );
my $cfg_value =
new Lire::Config::ReportSpec( 'name' => 'my_report' )->instance();
$cfg_value->get( 'id' )->set( 'my_report' );
my $section_value = $cfg_value->spec()->get( 'sections' )->get( 'section' )->instance();
$section_value->get( 'title' )->set( 'My section' );
$section_value->get( 'superservice' )->set( 'test' );
$cfg_value->get( 'sections' )->append( $section_value );
my $filter_value = $section_value->spec()->get( 'filters' )->get( 'test:select-file' )->instance();
$filter_value->get( 'id' )->set( 'select-file.0' );
$filter_value->get( 'file_match' )->set( 'my_file' );
$section_value->get( 'filters' )->append( $filter_value );
my $report_value = $section_value->spec()->get( 'specs' )->get( 'test:top-dirs' )->instance();
$report_value->get( 'id' )->set( 'top-dirs.0' );
$report_value->get( 'dirs_to_show' )->set( 5 );
$section_value->get( 'specs' )->append( $report_value );
$self->assert_deep_equals( $cfg_value,
$cfg->as_config_value( 'my_report' ) );
}
1;
syntax highlighted by Code2HTML, v. 0.9.1