|
| 1 | +#!/usr/bin/env perl |
| 2 | + |
| 3 | +use strict; |
| 4 | + |
| 5 | +# HOW TO USE THIS TEST |
| 6 | +# |
| 7 | +# By default, this test runs over all directories in t/data/importer/. To run |
| 8 | +# the test only for specific directories, pass the directory names to this |
| 9 | +# script or assign them to the environment variable SERGE_IMPORTER_TESTS as a |
| 10 | +# comma-separated list. The following two examples are equivalent: |
| 11 | +# |
| 12 | +# perl t/importer.t parse_json parse_strings |
| 13 | +# SERGE_IMPORTER_TESTS=parse_json,parse_strings prove t/importer.t |
| 14 | + |
| 15 | +BEGIN { |
| 16 | + use Cwd qw(abs_path); |
| 17 | + use File::Basename; |
| 18 | + use File::Spec::Functions qw(catfile); |
| 19 | + map { unshift(@INC, catfile(dirname(abs_path(__FILE__)), $_)) } qw(lib ../lib); |
| 20 | +} |
| 21 | + |
| 22 | +use Data::Dumper; |
| 23 | +use File::Copy::Recursive qw/dircopy/; |
| 24 | +use File::Find qw(find); |
| 25 | +use File::Path; |
| 26 | +use File::Spec::Functions qw(catfile); |
| 27 | +use Getopt::Long; |
| 28 | +use Test::Config; |
| 29 | +use Test::Diff; |
| 30 | +use Test::More; |
| 31 | +use Test::DB::Dumper; |
| 32 | +use Serge::Importer; |
| 33 | +use Serge::Engine::Job; |
| 34 | + |
| 35 | +$| = 1; # disable output buffering |
| 36 | + |
| 37 | +# to get the same results between tests, |
| 38 | +# we override the `file_mtime` function to return a constant value; |
| 39 | +# Serge::Importer automatically imports this function from Serge::Util |
| 40 | +# (this is why it actually appears in Serge::Importer namespace) |
| 41 | +sub Serge::Importer::file_mtime { |
| 42 | + return 12345678; |
| 43 | +} |
| 44 | + |
| 45 | +my $this_dir = dirname(abs_path(__FILE__)); |
| 46 | +my $tests_dir = catfile($this_dir, 'data', 'importer'); |
| 47 | + |
| 48 | +my @importer_confs; |
| 49 | + |
| 50 | +my ($init_references); |
| 51 | + |
| 52 | +GetOptions("init" => \$init_references); |
| 53 | + |
| 54 | +my @importer_dirs = @ARGV; |
| 55 | +if (my $env_dirs = $ENV{SERGE_IMPORTER_TESTS}) { |
| 56 | + push @importer_dirs, split(/,/, $env_dirs); |
| 57 | +} |
| 58 | + |
| 59 | +unless (@importer_dirs) { |
| 60 | + find(sub { |
| 61 | + push @importer_confs, $File::Find::name if(-f $_ && /\.serge$/ && $_ ne 'common.serge'); |
| 62 | + }, $tests_dir); |
| 63 | +} else { |
| 64 | + for my $dir (@importer_dirs) { |
| 65 | + find(sub { |
| 66 | + push @importer_confs, $File::Find::name if(-f $_ && /\.serge$/ && $_ ne 'common.serge'); |
| 67 | + }, catfile($tests_dir, $dir)); |
| 68 | + } |
| 69 | +} |
| 70 | + |
| 71 | +sub delete_directory { |
| 72 | + my ($path, $ignore_errors) = @_; |
| 73 | + |
| 74 | + my $err; |
| 75 | + |
| 76 | + if (-e $path) { |
| 77 | + rmtree($path, { error => \$err }); |
| 78 | + if (@$err && !$ignore_errors) { |
| 79 | + my $err_text = ''; |
| 80 | + |
| 81 | + map { |
| 82 | + foreach my $key (keys %$_) { |
| 83 | + $err_text .= $key.': '.$_->{$key}."\n"; |
| 84 | + } |
| 85 | + } @$err; |
| 86 | + |
| 87 | + BAIL_OUT("Directory '".$path."' couldn't be removed\n$err_text"); |
| 88 | + } |
| 89 | + } |
| 90 | +} |
| 91 | + |
| 92 | +for my $config_file (@importer_confs) { |
| 93 | + |
| 94 | + subtest "Test config: $config_file" => sub { |
| 95 | + my $cfg = Test::Config->new($config_file); |
| 96 | + |
| 97 | + SKIP: { |
| 98 | + my $ok = ok(defined $cfg, 'Config file read'); |
| 99 | + skip "<$config_file>", $init_references ? 2 : 4 if !$ok; |
| 100 | + |
| 101 | + my $err; |
| 102 | + |
| 103 | + delete_directory($cfg->output_path); |
| 104 | + if ($init_references) { |
| 105 | + delete_directory($cfg->reference_output_path); |
| 106 | + } |
| 107 | + |
| 108 | + my $engine = Serge::Importer->new(); |
| 109 | + $engine->{optimizations} = undef; # force generate all the files |
| 110 | + $cfg->chdir; |
| 111 | + |
| 112 | + foreach my $job_data (@{$cfg->{data}->{jobs}}) { |
| 113 | + my $job; |
| 114 | + |
| 115 | + eval { |
| 116 | + $job = Serge::Engine::Job->new($job_data, $engine, $cfg->{base_dir}); |
| 117 | + $engine->process_job($job); |
| 118 | + }; |
| 119 | + |
| 120 | + if ($@) { |
| 121 | + my $error = $@; |
| 122 | + # cleanup error message to avoid having file paths that will differ across installations |
| 123 | + $error =~ s/\s+$//sg; |
| 124 | + $error =~ s/ at .*? line \d+\.$//s; |
| 125 | + $error =~ s/ \(\@INC contains: .*\)$//s; |
| 126 | + $error =~ s/\@INC.+$/\@INC/s; |
| 127 | + |
| 128 | + print "Job '$job_data->{id}' will be skipped: $error\n"; |
| 129 | + |
| 130 | + eval { mkpath($cfg->errors_path) }; |
| 131 | + die "Couldn't create $cfg->errors_path: $@" if $@; |
| 132 | + my $filename = catfile($cfg->errors_path, $job_data->{id}.'.txt'); |
| 133 | + open(OUT, ">$filename"); |
| 134 | + binmode(OUT, ':unix :utf8'); |
| 135 | + print OUT $error; |
| 136 | + close(OUT); |
| 137 | + } |
| 138 | + } |
| 139 | + |
| 140 | + #ok(!$@, 'Processing all jobs in config file') or BAIL_OUT('Engine failed to run some of the jobs'); |
| 141 | + |
| 142 | + if ($cfg->can_dump_db) { |
| 143 | + my $dumper = Test::DB::Dumper->new($engine); |
| 144 | + $dumper->dump_l10n_tables($Test::DB::Dumper::TYPE_NEAT, $cfg->db_path); |
| 145 | + } else { |
| 146 | + print "Skipped dumping the database, as this is not applicable for this test\n"; |
| 147 | + } |
| 148 | + |
| 149 | + $engine->cleanup; |
| 150 | + |
| 151 | + if ($init_references) { |
| 152 | + ok(dircopy($cfg->output_path, $cfg->reference_output_path), "Initialized ".$cfg->reference_output_path); |
| 153 | + } else { |
| 154 | + $ok &= dir_diff($cfg->errors_path, $cfg->reference_errors_path, { base_dir => $cfg->{base_dir} } ); |
| 155 | + $ok &= dir_diff($cfg->db_path, $cfg->reference_db_path, { base_dir => $cfg->{base_dir} } ); |
| 156 | + $ok &= dir_diff($cfg->ts_path, $cfg->reference_ts_path, { base_dir => $cfg->{base_dir} } ); |
| 157 | + $ok &= dir_diff($cfg->data_path, $cfg->reference_data_path, { base_dir => $cfg->{base_dir} } ) if $cfg->output_lang_files; |
| 158 | + } |
| 159 | + |
| 160 | + # Under Windows, deleting just created files may fail with 'Permission denied' |
| 161 | + # for an unknown reason, and only closing the process will release the file handles. |
| 162 | + # Since we will be removing test output at the beginning of each test anyway, |
| 163 | + # don't bail out this time if some files failed to be removed |
| 164 | + delete_directory($cfg->output_path, 1) if $ok; |
| 165 | + } |
| 166 | + } |
| 167 | +} |
| 168 | + |
| 169 | + |
| 170 | +done_testing(); |
0 commit comments