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( <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;