diff options
author | 2020-03-07 11:19:34 -0800 | |
---|---|---|
committer | 2020-03-07 11:20:45 -0800 | |
commit | 1383dfc4ff1dfe5bfa5b327b4ae19b2af6a2a28e (patch) | |
tree | ef46b4d84362cabf31dd2c098d0fae38fcd0e018 /t | |
parent | Gentoo: alpha is now ~arch-only (diff) | |
parent | Bugzilla/Util: disable BiDi tr safety (diff) | |
download | bugzilla-1383dfc4ff1dfe5bfa5b327b4ae19b2af6a2a28e.tar.gz bugzilla-1383dfc4ff1dfe5bfa5b327b4ae19b2af6a2a28e.tar.bz2 bugzilla-1383dfc4ff1dfe5bfa5b327b4ae19b2af6a2a28e.zip |
Bugzilla 5.0.6! Merge branch 'bugstest'
This update Gentoo production Bugzilla to 5.0.6.
Please note that upstream reformatted all code, so the commit series has
some extra hops to help reflect that change.
Signed-off-by: Robin H. Johnson <robbat2@gentoo.org>
Diffstat (limited to 't')
-rw-r--r-- | t/001compile.t | 118 | ||||
-rw-r--r-- | t/002goodperl.t | 271 | ||||
-rw-r--r-- | t/003safesys.t | 61 | ||||
-rw-r--r-- | t/004template.t | 180 | ||||
-rw-r--r-- | t/005whitespace.t | 66 | ||||
-rw-r--r-- | t/006spellcheck.t | 104 | ||||
-rw-r--r-- | t/007util.t | 68 | ||||
-rw-r--r-- | t/008filter.t | 310 | ||||
-rw-r--r-- | t/009bugwords.t | 84 | ||||
-rw-r--r-- | t/010dependencies.t | 76 | ||||
-rw-r--r-- | t/011pod.t | 154 | ||||
-rw-r--r-- | t/012throwables.t | 280 | ||||
-rw-r--r-- | t/013dbschema.t | 80 | ||||
-rw-r--r-- | t/Support/Files.pm | 40 | ||||
-rw-r--r-- | t/Support/Templates.pm | 91 |
15 files changed, 1050 insertions, 933 deletions
diff --git a/t/001compile.t b/t/001compile.t index 7097ad361..ad29975af 100644 --- a/t/001compile.t +++ b/t/001compile.t @@ -18,78 +18,78 @@ use lib qw(. lib t); use Config; use Support::Files; use Test::More tests => scalar(@Support::Files::testitems) - + scalar(@Support::Files::test_files); + + scalar(@Support::Files::test_files); -BEGIN { - use_ok('Bugzilla::Constants'); - use_ok('Bugzilla::Install::Requirements'); - use_ok('Bugzilla'); +BEGIN { + use_ok('Bugzilla::Constants'); + use_ok('Bugzilla::Install::Requirements'); + use_ok('Bugzilla'); } sub compile_file { - my ($file) = @_; + my ($file) = @_; - # Don't allow CPAN.pm to modify the global @INC, which the version - # shipped with Perl 5.8.8 does. (It gets loaded by - # Bugzilla::Install::CPAN.) - local @INC = @INC; + # Don't allow CPAN.pm to modify the global @INC, which the version + # shipped with Perl 5.8.8 does. (It gets loaded by + # Bugzilla::Install::CPAN.) + local @INC = @INC; - if ($file =~ s/\.pm$//) { - $file =~ s{/}{::}g; - use_ok($file); - return; - } + if ($file =~ s/\.pm$//) { + $file =~ s{/}{::}g; + use_ok($file); + return; + } - open(my $fh, $file); - my $bang = <$fh>; - close $fh; + open(my $fh, $file); + my $bang = <$fh>; + close $fh; - my $T = ""; - if ($bang =~ m/#!\S*perl\s+-.*T/) { - $T = "T"; - } + my $T = ""; + if ($bang =~ m/#!\S*perl\s+-.*T/) { + $T = "T"; + } - my $libs = ''; - if ($ENV{PERL5LIB}) { - $libs = join " ", map { "-I\"$_\"" } split /$Config{path_sep}/, $ENV{PERL5LIB}; - } - my $perl = qq{"$^X"}; - my $output = `$perl $libs -c$T $file 2>&1`; - chomp($output); - my $return_val = $?; - $output =~ s/^\Q$file\E syntax OK$//ms; - diag($output) if $output; - ok(!$return_val, $file) or diag('--ERROR'); + my $libs = ''; + if ($ENV{PERL5LIB}) { + $libs = join " ", map {"-I\"$_\""} split /$Config{path_sep}/, $ENV{PERL5LIB}; + } + my $perl = qq{"$^X"}; + my $output = `$perl $libs -c$T $file 2>&1`; + chomp($output); + my $return_val = $?; + $output =~ s/^\Q$file\E syntax OK$//ms; + diag($output) if $output; + ok(!$return_val, $file) or diag('--ERROR'); } -my @testitems = (@Support::Files::testitems, @Support::Files::test_files); +my @testitems = (@Support::Files::testitems, @Support::Files::test_files); my $file_features = map_files_to_features(); # Test the scripts by compiling them foreach my $file (@testitems) { - # These were already compiled, above. - next if ($file eq 'Bugzilla.pm' - or $file eq 'Bugzilla/Constants.pm' - or $file eq 'Bugzilla/Install/Requirements.pm'); - SKIP: { - if ($file eq 'mod_perl.pl') { - skip 'mod_perl.pl cannot be compiled from the command line', 1; - } - my $feature = $file_features->{$file}; - if ($feature and !Bugzilla->feature($feature)) { - skip "$file: $feature not enabled", 1; - } - - # Check that we have a DBI module to support the DB, if this - # is a database module (but not Schema) - if ($file =~ m{Bugzilla/DB/([^/]+)\.pm$} - and $file ne "Bugzilla/DB/Schema.pm") - { - my $module = lc($1); - my $dbd = DB_MODULE->{$module}->{dbd}->{module}; - eval("use $dbd; 1") or skip "$file: $dbd not installed", 1; - } - - compile_file($file); + + # These were already compiled, above. + next + if ($file eq 'Bugzilla.pm' + or $file eq 'Bugzilla/Constants.pm' + or $file eq 'Bugzilla/Install/Requirements.pm'); +SKIP: { + if ($file eq 'mod_perl.pl') { + skip 'mod_perl.pl cannot be compiled from the command line', 1; + } + my $feature = $file_features->{$file}; + if ($feature and !Bugzilla->feature($feature)) { + skip "$file: $feature not enabled", 1; } -} + + # Check that we have a DBI module to support the DB, if this + # is a database module (but not Schema) + if ($file =~ m{Bugzilla/DB/([^/]+)\.pm$} and $file ne "Bugzilla/DB/Schema.pm") { + my $module = lc($1); + my $dbd = DB_MODULE->{$module}->{dbd}->{module}; + eval("use $dbd; 1") or skip "$file: $dbd not installed", 1; + } + + compile_file($file); + } +} diff --git a/t/002goodperl.t b/t/002goodperl.t index d1858361f..837849282 100644 --- a/t/002goodperl.t +++ b/t/002goodperl.t @@ -18,156 +18,171 @@ use lib 't'; use Support::Files; -use Test::More tests => (scalar(@Support::Files::testitems) - + scalar(@Support::Files::test_files)) * 6; +use Test::More tests => + (scalar(@Support::Files::testitems) + scalar(@Support::Files::test_files)) + * 6; -my @testitems = (@Support::Files::test_files, @Support::Files::testitems); +my @testitems = (@Support::Files::test_files, @Support::Files::testitems); my @require_taint = qw(email_in.pl importxml.pl mod_perl.pl whine.pl); foreach my $file (@testitems) { - $file =~ s/\s.*$//; # nuke everything after the first space (#comment) - next if (!$file); # skip null entries - if (! open (FILE, $file)) { - ok(0,"could not open $file --WARNING"); + $file =~ s/\s.*$//; # nuke everything after the first space (#comment) + next if (!$file); # skip null entries + if (!open(FILE, $file)) { + ok(0, "could not open $file --WARNING"); + } + my $file_line1 = <FILE>; + close(FILE); + + $file =~ m/.*\.(.*)/; + my $ext = $1; + + if ($file_line1 !~ m/^#\!/) { + ok(1, "$file does not have a shebang"); + } + else { + my $flags; + if (!defined $ext || $ext eq "pl") { + + # standalone programs aren't taint checked yet + if (grep { $file eq $_ } @require_taint) { + $flags = 'T'; + } + else { + $flags = ''; + } } - my $file_line1 = <FILE>; - close (FILE); - - $file =~ m/.*\.(.*)/; - my $ext = $1; - - if ($file_line1 !~ m/^#\!/) { - ok(1,"$file does not have a shebang"); - } else { - my $flags; - if (!defined $ext || $ext eq "pl") { - # standalone programs aren't taint checked yet - if (grep { $file eq $_ } @require_taint) { - $flags = 'T'; - } - else { - $flags = ''; - } - } elsif ($ext eq "pm") { - ok(0, "$file is a module, but has a shebang"); - next; - } elsif ($ext eq "cgi") { - # cgi files must be taint checked - $flags = 'T'; - } else { - ok(0, "$file has shebang but unknown extension"); - next; - } - - if ($file_line1 =~ m#^\#\!/usr/bin/perl(?:\s-(\w+))?$#) { - my $file_flags = $1 || ''; - if ($flags eq $file_flags) { - ok(1, "$file uses standard perl location" . ($flags ? " and -$flags flag" : "")); - } - elsif ($flags) { - ok(0, "$file is MISSING -$flags flag --WARNING"); - } - else { - ok(0, "$file has unexpected -$file_flags flag --WARNING"); - } - } else { - ok(0,"$file uses non-standard perl location"); - } + elsif ($ext eq "pm") { + ok(0, "$file is a module, but has a shebang"); + next; } -} + elsif ($ext eq "cgi") { -foreach my $file (@testitems) { - my $found_use_perl = 0; - my $found_use_strict = 0; - my $found_use_warnings = 0; - - $file =~ s/\s.*$//; # nuke everything after the first space (#comment) - next if (!$file); # skip null entries - if (! open (FILE, $file)) { - ok(0,"could not open $file --WARNING"); - next; - } - while (my $file_line = <FILE>) { - $found_use_perl = 1 if $file_line =~ m/^\s*use 5.10.1/; - $found_use_strict = 1 if $file_line =~ m/^\s*use strict/; - $found_use_warnings = 1 if $file_line =~ m/^\s*use warnings/; - last if ($found_use_perl && $found_use_strict && $found_use_warnings); + # cgi files must be taint checked + $flags = 'T'; } - close (FILE); - if ($found_use_perl) { - ok(1,"$file requires Perl 5.10.1"); - } else { - ok(0,"$file DOES NOT require Perl 5.10.1 --WARNING"); + else { + ok(0, "$file has shebang but unknown extension"); + next; } - if ($found_use_strict) { - ok(1,"$file uses strict"); - } else { - ok(0,"$file DOES NOT use strict --WARNING"); + if ($file_line1 =~ m#^\#\!/usr/bin/perl(?:\s-(\w+))?$#) { + my $file_flags = $1 || ''; + if ($flags eq $file_flags) { + ok(1, + "$file uses standard perl location" . ($flags ? " and -$flags flag" : "")); + } + elsif ($flags) { + ok(0, "$file is MISSING -$flags flag --WARNING"); + } + else { + ok(0, "$file has unexpected -$file_flags flag --WARNING"); + } } - - if ($found_use_warnings) { - ok(1,"$file uses warnings"); - } else { - ok(0,"$file DOES NOT use warnings --WARNING"); + else { + ok(0, "$file uses non-standard perl location"); } + } +} + +foreach my $file (@testitems) { + my $found_use_perl = 0; + my $found_use_strict = 0; + my $found_use_warnings = 0; + + $file =~ s/\s.*$//; # nuke everything after the first space (#comment) + next if (!$file); # skip null entries + if (!open(FILE, $file)) { + ok(0, "could not open $file --WARNING"); + next; + } + while (my $file_line = <FILE>) { + $found_use_perl = 1 if $file_line =~ m/^\s*use 5.10.1/; + $found_use_strict = 1 if $file_line =~ m/^\s*use strict/; + $found_use_warnings = 1 if $file_line =~ m/^\s*use warnings/; + last if ($found_use_perl && $found_use_strict && $found_use_warnings); + } + close(FILE); + if ($found_use_perl) { + ok(1, "$file requires Perl 5.10.1"); + } + else { + ok(0, "$file DOES NOT require Perl 5.10.1 --WARNING"); + } + + if ($found_use_strict) { + ok(1, "$file uses strict"); + } + else { + ok(0, "$file DOES NOT use strict --WARNING"); + } + + if ($found_use_warnings) { + ok(1, "$file uses warnings"); + } + else { + ok(0, "$file DOES NOT use warnings --WARNING"); + } } # Check to see that all error messages use tags (for l10n reasons.) foreach my $file (@testitems) { - $file =~ s/\s.*$//; # nuke everything after the first space (#comment) - next if (!$file); # skip null entries - if (! open (FILE, $file)) { - ok(0,"could not open $file --WARNING"); - next; + $file =~ s/\s.*$//; # nuke everything after the first space (#comment) + next if (!$file); # skip null entries + if (!open(FILE, $file)) { + ok(0, "could not open $file --WARNING"); + next; + } + my $lineno = 0; + my $error = 0; + + while (!$error && (my $file_line = <FILE>)) { + $lineno++; + if ($file_line =~ /Throw.*Error\("(.*?)"/) { + if ($1 =~ /\s/) { + ok( + 0, "$file has a Throw*Error call on line $lineno + which doesn't use a tag --ERROR" + ); + $error = 1; + } } - my $lineno = 0; - my $error = 0; - - while (!$error && (my $file_line = <FILE>)) { - $lineno++; - if ($file_line =~ /Throw.*Error\("(.*?)"/) { - if ($1 =~ /\s/) { - ok(0,"$file has a Throw*Error call on line $lineno - which doesn't use a tag --ERROR"); - $error = 1; - } - } - } - - ok(1,"$file uses Throw*Error calls correctly") if !$error; - - close(FILE); + } + + ok(1, "$file uses Throw*Error calls correctly") if !$error; + + close(FILE); } # Forbird the { foo => $cgi->param() } syntax, for security reasons. foreach my $file (@testitems) { - $file =~ s/\s.*$//; # nuke everything after the first space (#comment) - next unless $file; # skip null entries - if (!open(FILE, $file)) { - ok(0, "could not open $file --WARNING"); - next; + $file =~ s/\s.*$//; # nuke everything after the first space (#comment) + next unless $file; # skip null entries + if (!open(FILE, $file)) { + ok(0, "could not open $file --WARNING"); + next; + } + my $lineno = 0; + my @unsafe_args; + + while (my $file_line = <FILE>) { + $lineno++; + $file_line =~ s/^\s*(.+)\s*$/$1/; # Remove leading and trailing whitespaces. + if ($file_line =~ /^[^#]+=> \$cgi\->param/) { + push(@unsafe_args, "$file_line on line $lineno"); } - my $lineno = 0; - my @unsafe_args; - - while (my $file_line = <FILE>) { - $lineno++; - $file_line =~ s/^\s*(.+)\s*$/$1/; # Remove leading and trailing whitespaces. - if ($file_line =~ /^[^#]+=> \$cgi\->param/) { - push(@unsafe_args, "$file_line on line $lineno"); - } - } - - if (@unsafe_args) { - ok(0, "$file incorrectly passes a CGI argument to a hash --ERROR\n" . - join("\n", @unsafe_args)); - } - else { - ok(1, "$file has no vulnerable hash syntax"); - } - - close(FILE); + } + + if (@unsafe_args) { + ok(0, + "$file incorrectly passes a CGI argument to a hash --ERROR\n" + . join("\n", @unsafe_args)); + } + else { + ok(1, "$file has no vulnerable hash syntax"); + } + + close(FILE); } exit 0; diff --git a/t/003safesys.t b/t/003safesys.t index 443f96415..3cc55f835 100644 --- a/t/003safesys.t +++ b/t/003safesys.t @@ -24,39 +24,42 @@ use Test::More tests => scalar(@Support::Files::testitems); # This will handle verbosity for us automatically. my $fh; { - no warnings qw(unopened); # Don't complain about non-existent filehandles - if (-e \*Test::More::TESTOUT) { - $fh = \*Test::More::TESTOUT; - } elsif (-e \*Test::Builder::TESTOUT) { - $fh = \*Test::Builder::TESTOUT; - } else { - $fh = \*STDOUT; - } + no warnings qw(unopened); # Don't complain about non-existent filehandles + if (-e \*Test::More::TESTOUT) { + $fh = \*Test::More::TESTOUT; + } + elsif (-e \*Test::Builder::TESTOUT) { + $fh = \*Test::Builder::TESTOUT; + } + else { + $fh = \*STDOUT; + } } -my @testitems = @Support::Files::testitems; -my $perlapp = "\"$^X\""; +my @testitems = @Support::Files::testitems; +my $perlapp = "\"$^X\""; foreach my $file (@testitems) { - $file =~ s/\s.*$//; # nuke everything after the first space (#comment) - next if (!$file); # skip null entries - - open(my $fh2, '<', $file); - my $bang = <$fh2>; - close $fh2; - - my $T = ""; - if ($bang =~ m/#!\S*perl\s+-.*T/) { - $T = "T"; - } - my $command = "$perlapp -c$T -It -MSupport::Systemexec $file 2>&1"; - my $loginfo=`$command`; - if ($loginfo =~ /arguments for Support::Systemexec::(system|exec)/im) { - ok(0,"$file DOES NOT use proper system or exec calls"); - print $fh $loginfo; - } else { - ok(1,"$file uses proper system and exec calls"); - } + $file =~ s/\s.*$//; # nuke everything after the first space (#comment) + next if (!$file); # skip null entries + + open(my $fh2, '<', $file); + my $bang = <$fh2>; + close $fh2; + + my $T = ""; + if ($bang =~ m/#!\S*perl\s+-.*T/) { + $T = "T"; + } + my $command = "$perlapp -c$T -It -MSupport::Systemexec $file 2>&1"; + my $loginfo = `$command`; + if ($loginfo =~ /arguments for Support::Systemexec::(system|exec)/im) { + ok(0, "$file DOES NOT use proper system or exec calls"); + print $fh $loginfo; + } + else { + ok(1, "$file uses proper system and exec calls"); + } } exit 0; diff --git a/t/004template.t b/t/004template.t index 0a6f0e0aa..938ee8b18 100644 --- a/t/004template.t +++ b/t/004template.t @@ -22,20 +22,22 @@ use CGI qw(-no_debug); use File::Spec; use Template; -use Test::More tests => ( scalar(@referenced_files) + 2 * $num_actual_files ); +use Test::More tests => (scalar(@referenced_files) + 2 * $num_actual_files); # Capture the TESTOUT from Test::More or Test::Builder for printing errors. # This will handle verbosity for us automatically. my $fh; { - no warnings qw(unopened); # Don't complain about non-existent filehandles - if (-e \*Test::More::TESTOUT) { - $fh = \*Test::More::TESTOUT; - } elsif (-e \*Test::Builder::TESTOUT) { - $fh = \*Test::Builder::TESTOUT; - } else { - $fh = \*STDOUT; - } + no warnings qw(unopened); # Don't complain about non-existent filehandles + if (-e \*Test::More::TESTOUT) { + $fh = \*Test::More::TESTOUT; + } + elsif (-e \*Test::Builder::TESTOUT) { + $fh = \*Test::Builder::TESTOUT; + } + else { + $fh = \*STDOUT; + } } # Check to make sure all templates that are referenced in Bugzilla @@ -44,82 +46,106 @@ my $fh; # fall back to English if necessary. foreach my $file (@referenced_files) { - my $found = 0; - foreach my $path (@english_default_include_paths) { - my $pathfile = File::Spec->catfile($path, $file); - if (-e $pathfile) { - $found = 1; - last; - } + my $found = 0; + foreach my $path (@english_default_include_paths) { + my $pathfile = File::Spec->catfile($path, $file); + if (-e $pathfile) { + $found = 1; + last; } + } - ok($found, "$file found"); + ok($found, "$file found"); } foreach my $include_path (@include_paths) { - # Processes all the templates to make sure they have good syntax - my $provider = Template::Provider->new( - { - INCLUDE_PATH => $include_path , - # Need to define filters used in the codebase, they don't - # actually have to function in this test, just be defined. - # See Template.pm for the actual codebase definitions. - - # Initialize templates (f.e. by loading plugins like Hook). - PRE_PROCESS => "global/variables.none.tmpl", - - FILTERS => - { - html_linebreak => sub { return $_; }, - js => sub { return $_ } , - base64 => sub { return $_ } , - inactive => [ sub { return sub { return $_; } }, 1] , - closed => [ sub { return sub { return $_; } }, 1] , - obsolete => [ sub { return sub { return $_; } }, 1] , - url_quote => sub { return $_ } , - css_class_quote => sub { return $_ } , - xml => sub { return $_ } , - quoteUrls => sub { return $_ } , - bug_link => [ sub { return sub { return $_; } }, 1] , - csv => sub { return $_ } , - unitconvert => sub { return $_ }, - time => sub { return $_ } , - wrap_comment => sub { return $_ }, - none => sub { return $_ } , - ics => [ sub { return sub { return $_; } }, 1] , + + # Processes all the templates to make sure they have good syntax + my $provider = Template::Provider->new({ + INCLUDE_PATH => $include_path, + + # Need to define filters used in the codebase, they don't + # actually have to function in this test, just be defined. + # See Template.pm for the actual codebase definitions. + + # Initialize templates (f.e. by loading plugins like Hook). + PRE_PROCESS => "global/variables.none.tmpl", + + FILTERS => { + html_linebreak => sub { return $_; }, + js => sub { return $_ }, + base64 => sub { return $_ }, + inactive => [ + sub { + return sub { return $_; } + }, + 1 + ], + closed => [ + sub { + return sub { return $_; } + }, + 1 + ], + obsolete => [ + sub { + return sub { return $_; } + }, + 1 + ], + url_quote => sub { return $_ }, + css_class_quote => sub { return $_ }, + xml => sub { return $_ }, + quoteUrls => sub { return $_ }, + bug_link => [ + sub { + return sub { return $_; } + }, + 1 + ], + csv => sub { return $_ }, + unitconvert => sub { return $_ }, + time => sub { return $_ }, + wrap_comment => sub { return $_ }, + none => sub { return $_ }, + ics => [ + sub { + return sub { return $_; } }, + 1 + ], + }, + }); + + foreach my $file (@{$actual_files{$include_path}}) { + my $path = File::Spec->catfile($include_path, $file); + + # These are actual files, so there's no need to check for existence. + + my ($data, $err) = $provider->fetch($file); + + if (!$err) { + ok(1, "$path syntax ok"); + } + else { + ok(0, "$path has bad syntax --ERROR"); + print $fh $data . "\n"; + } + + # Make sure no forbidden constructs are present. + local $/; + open(FILE, '<', $path) or die "Can't open $file: $!\n"; + $data = <FILE>; + close(FILE); + + # Forbid single quotes to delimit URLs, see bug 926085. + if ($data =~ /href=\\?'/) { + ok(0, "$path contains blacklisted constructs: href='...'"); } - ); - - foreach my $file (@{$actual_files{$include_path}}) { - my $path = File::Spec->catfile($include_path, $file); - - # These are actual files, so there's no need to check for existence. - - my ($data, $err) = $provider->fetch($file); - - if (!$err) { - ok(1, "$path syntax ok"); - } - else { - ok(0, "$path has bad syntax --ERROR"); - print $fh $data . "\n"; - } - - # Make sure no forbidden constructs are present. - local $/; - open(FILE, '<', $path) or die "Can't open $file: $!\n"; - $data = <FILE>; - close (FILE); - - # Forbid single quotes to delimit URLs, see bug 926085. - if ($data =~ /href=\\?'/) { - ok(0, "$path contains blacklisted constructs: href='...'"); - } - else { - ok(1, "$path contains no blacklisted constructs"); - } + else { + ok(1, "$path contains no blacklisted constructs"); } + } } exit 0; diff --git a/t/005whitespace.t b/t/005whitespace.t index b6de8cee3..ef589e693 100644 --- a/t/005whitespace.t +++ b/t/005whitespace.t @@ -19,49 +19,57 @@ use Support::Files; use Support::Templates; use File::Spec; -use Test::More tests => (scalar(@Support::Files::testitems) - + scalar(@Support::Files::test_files) - + $Support::Templates::num_actual_files) * 3; +use Test::More tests => ( + scalar(@Support::Files::testitems) + + scalar(@Support::Files::test_files) + + $Support::Templates::num_actual_files) + * 3; my @testitems = (@Support::Files::testitems, @Support::Files::test_files); for my $path (@Support::Templates::include_paths) { - push(@testitems, map(File::Spec->catfile($path, $_), - Support::Templates::find_actual_files($path))); + push( + @testitems, + map(File::Spec->catfile($path, $_), + Support::Templates::find_actual_files($path)) + ); } my %results; foreach my $file (@testitems) { - open (FILE, "$file"); - my @contents = <FILE>; - if (grep /\t/, @contents) { - ok(0, "$file contains tabs --WARNING"); - } else { - ok(1, "$file has no tabs"); - } - close (FILE); + open(FILE, "$file"); + my @contents = <FILE>; + if (grep /\t/, @contents) { + ok(0, "$file contains tabs --WARNING"); + } + else { + ok(1, "$file has no tabs"); + } + close(FILE); } foreach my $file (@testitems) { - open (FILE, "$file"); - my @contents = <FILE>; - if (grep /\r/, @contents) { - ok(0, "$file contains non-OS-conformant line endings --WARNING"); - } else { - ok(1, "All line endings of $file are OS conformant"); - } - close (FILE); + open(FILE, "$file"); + my @contents = <FILE>; + if (grep /\r/, @contents) { + ok(0, "$file contains non-OS-conformant line endings --WARNING"); + } + else { + ok(1, "All line endings of $file are OS conformant"); + } + close(FILE); } foreach my $file (@testitems) { - open (FILE, "$file"); - my $first_line = <FILE>; - if ($first_line =~ /\xef\xbb\xbf/) { - ok(0, "$file contains Byte Order Mark --WARNING"); - } else { - ok(1, "$file is free of a Byte Order Mark"); - } - close (FILE); + open(FILE, "$file"); + my $first_line = <FILE>; + if ($first_line =~ /\xef\xbb\xbf/) { + ok(0, "$file contains Byte Order Mark --WARNING"); + } + else { + ok(1, "$file is free of a Byte Order Mark"); + } + close(FILE); } exit 0; diff --git a/t/006spellcheck.t b/t/006spellcheck.t index 24e00242d..ccbd69932 100644 --- a/t/006spellcheck.t +++ b/t/006spellcheck.t @@ -19,72 +19,76 @@ use Support::Files; # -1 because 006spellcheck.t must not be checked. use Test::More tests => scalar(@Support::Files::testitems) - + scalar(@Support::Files::test_files) - 1; + + scalar(@Support::Files::test_files) - 1; # Capture the TESTOUT from Test::More or Test::Builder for printing errors. # This will handle verbosity for us automatically. my $fh; { - no warnings qw(unopened); # Don't complain about non-existent filehandles - if (-e \*Test::More::TESTOUT) { - $fh = \*Test::More::TESTOUT; - } elsif (-e \*Test::Builder::TESTOUT) { - $fh = \*Test::Builder::TESTOUT; - } else { - $fh = \*STDOUT; - } + no warnings qw(unopened); # Don't complain about non-existent filehandles + if (-e \*Test::More::TESTOUT) { + $fh = \*Test::More::TESTOUT; + } + elsif (-e \*Test::Builder::TESTOUT) { + $fh = \*Test::Builder::TESTOUT; + } + else { + $fh = \*STDOUT; + } } my @testitems = (@Support::Files::testitems, @Support::Files::test_files); #add the words to check here: my @evilwords = qw( - anyways - appearence - arbitary - cancelled - critera - databasa - dependan - existance - existant - paramater - refered - repsentation - suported - varsion + anyways + appearence + arbitary + cancelled + critera + databasa + dependan + existance + existant + paramater + refered + repsentation + suported + varsion ); my $evilwordsregexp = join('|', @evilwords); foreach my $file (@testitems) { - $file =~ s/\s.*$//; # nuke everything after the first space (#comment) - next if (!$file); # skip null entries - # Do not try to validate this file as it obviously contains a list - # of wrongly spelled words. - next if ($file eq 't/006spellcheck.t'); - - if (open (FILE, $file)) { # open the file for reading - - my $found_word = ''; - - while (my $file_line = <FILE>) { # and go through the file line by line - if ($file_line =~ /($evilwordsregexp)/i) { # found an evil word - $found_word = $1; - last; - } - } - - close (FILE); - - if ($found_word) { - ok(0,"$file: found SPELLING ERROR $found_word --WARNING"); - } else { - ok(1,"$file does not contain registered spelling errors"); - } - } else { - ok(0,"could not open $file for spellcheck --WARNING"); + $file =~ s/\s.*$//; # nuke everything after the first space (#comment) + next if (!$file); # skip null entries + # Do not try to validate this file as it obviously contains a list + # of wrongly spelled words. + next if ($file eq 't/006spellcheck.t'); + + if (open(FILE, $file)) { # open the file for reading + + my $found_word = ''; + + while (my $file_line = <FILE>) { # and go through the file line by line + if ($file_line =~ /($evilwordsregexp)/i) { # found an evil word + $found_word = $1; + last; + } } -} + + close(FILE); + + if ($found_word) { + ok(0, "$file: found SPELLING ERROR $found_word --WARNING"); + } + else { + ok(1, "$file does not contain registered spelling errors"); + } + } + else { + ok(0, "could not open $file for spellcheck --WARNING"); + } +} exit 0; diff --git a/t/007util.t b/t/007util.t index 66c2df032..94f62dfc1 100644 --- a/t/007util.t +++ b/t/007util.t @@ -18,9 +18,9 @@ use Support::Files; use Test::More tests => 17; use DateTime; -BEGIN { - use_ok('Bugzilla'); - use_ok('Bugzilla::Util'); +BEGIN { + use_ok('Bugzilla'); + use_ok('Bugzilla::Util'); } # We need to override user preferences so we can get an expected value when @@ -29,38 +29,57 @@ Bugzilla->user->{'settings'}->{'timezone'}->{'value'} = "local"; # We need to know the local timezone for the date chosen in our tests. # Below, tests are run against Nov. 24, 2002. -my $tz = Bugzilla->local_timezone->short_name_for_datetime(DateTime->new(year => 2002, month => 11, day => 24)); +my $tz = Bugzilla->local_timezone->short_name_for_datetime( + DateTime->new(year => 2002, month => 11, day => 24)); # we don't test the taint functions since that's going to take some more work. # XXX: test taint functions #html_quote(): -is(html_quote("<lala&@>"),"<lala&@>",'html_quote'); +is(html_quote("<lala&@>"), "<lala&@>", 'html_quote'); #url_quote(): -is(url_quote("<lala&>gaa\"'[]{\\"),"%3Clala%26%3Egaa%22%27%5B%5D%7B%5C",'url_quote'); +is(url_quote("<lala&>gaa\"'[]{\\"), + "%3Clala%26%3Egaa%22%27%5B%5D%7B%5C", 'url_quote'); #trim(): -is(trim(" fg<*\$%>+=~~ "),'fg<*$%>+=~~','trim()'); +is(trim(" fg<*\$%>+=~~ "), 'fg<*$%>+=~~', 'trim()'); #format_time(); -is(format_time("2002.11.24 00:05"), "2002-11-24 00:05 $tz",'format_time("2002.11.24 00:05") is ' . format_time("2002.11.24 00:05")); -is(format_time("2002.11.24 00:05:56"), "2002-11-24 00:05:56 $tz",'format_time("2002.11.24 00:05:56")'); -is(format_time("2002.11.24 00:05:56", "%Y-%m-%d %R"), '2002-11-24 00:05', 'format_time("2002.11.24 00:05:56", "%Y-%m-%d %R") (with no timezone)'); -is(format_time("2002.11.24 00:05:56", "%Y-%m-%d %R %Z"), "2002-11-24 00:05 $tz", 'format_time("2002.11.24 00:05:56", "%Y-%m-%d %R %Z") (with timezone)'); +is( + format_time("2002.11.24 00:05"), + "2002-11-24 00:05 $tz", + 'format_time("2002.11.24 00:05") is ' . format_time("2002.11.24 00:05") +); +is( + format_time("2002.11.24 00:05:56"), + "2002-11-24 00:05:56 $tz", + 'format_time("2002.11.24 00:05:56")' +); +is( + format_time("2002.11.24 00:05:56", "%Y-%m-%d %R"), + '2002-11-24 00:05', + 'format_time("2002.11.24 00:05:56", "%Y-%m-%d %R") (with no timezone)' +); +is( + format_time("2002.11.24 00:05:56", "%Y-%m-%d %R %Z"), + "2002-11-24 00:05 $tz", + 'format_time("2002.11.24 00:05:56", "%Y-%m-%d %R %Z") (with timezone)' +); # email_filter my %email_strings = ( - 'somebody@somewhere.com' => 'somebody', - 'Somebody <somebody@somewhere.com>' => 'Somebody <somebody>', - 'One Person <one@person.com>, Two Person <two@person.com>' - => 'One Person <one>, Two Person <two>', - 'This string contains somebody@somewhere.com and also this@that.com' - => 'This string contains somebody and also this', + 'somebody@somewhere.com' => 'somebody', + 'Somebody <somebody@somewhere.com>' => 'Somebody <somebody>', + 'One Person <one@person.com>, Two Person <two@person.com>' => + 'One Person <one>, Two Person <two>', + 'This string contains somebody@somewhere.com and also this@that.com' => + 'This string contains somebody and also this', ); + foreach my $input (keys %email_strings) { - is(Bugzilla::Util::email_filter($input), $email_strings{$input}, - "email_filter('$input')"); + is(Bugzilla::Util::email_filter($input), + $email_strings{$input}, "email_filter('$input')"); } # validate_email_syntax. We need to override some parameters. @@ -68,14 +87,18 @@ my $params = Bugzilla->params; $params->{emailregexp} = '.*'; $params->{emailsuffix} = ''; my $ascii_email = 'admin@company.com'; + # U+0430 returns the Cyrillic "а", which looks similar to the ASCII "a". my $utf8_email = "\N{U+0430}dmin\@company.com"; -ok(validate_email_syntax($ascii_email), 'correctly formatted ASCII-only email address is valid'); -ok(!validate_email_syntax($utf8_email), 'correctly formatted email address with non-ASCII characters is rejected'); +ok(validate_email_syntax($ascii_email), + 'correctly formatted ASCII-only email address is valid'); +ok(!validate_email_syntax($utf8_email), + 'correctly formatted email address with non-ASCII characters is rejected'); # diff_arrays(): my @old_array = qw(alpha beta alpha gamma gamma beta alpha delta epsilon gamma); my @new_array = qw(alpha alpha beta gamma epsilon delta beta delta); + # The order is not relevant when comparing both arrays for matching items, # i.e. (foo bar) and (bar foo) are the same arrays (same items). # But when returning data, we try to respect the initial order. @@ -83,5 +106,6 @@ my @new_array = qw(alpha alpha beta gamma epsilon delta beta delta); # Removed (in this order): gamma alpha gamma. # Added (in this order): delta my ($removed, $added) = diff_arrays(\@old_array, \@new_array); -is_deeply($removed, [qw(gamma alpha gamma)], 'diff_array(\@old, \@new) (check removal)'); +is_deeply($removed, [qw(gamma alpha gamma)], + 'diff_array(\@old, \@new) (check removal)'); is_deeply($added, [qw(delta)], 'diff_array(\@old, \@new) (check addition)'); diff --git a/t/008filter.t b/t/008filter.t index f0a26d13f..b60a97579 100644 --- a/t/008filter.t +++ b/t/008filter.t @@ -11,7 +11,7 @@ # This test scans all our templates for every directive. Having eliminated # those which cannot possibly cause XSS problems, it then checks the rest -# against the safe list stored in the filterexceptions.pl file. +# against the safe list stored in the filterexceptions.pl file. # Sample exploit code: '>"><script>alert('Oh dear...')</script> @@ -29,192 +29,196 @@ use Cwd; # Undefine the record separator so we can read in whole files at once my $oldrecsep = $/; -my $topdir = cwd; +my $topdir = cwd; $/ = undef; our %safe; foreach my $path (@Support::Templates::include_paths) { - $path =~ s|\\|/|g if ON_WINDOWS; # convert \ to / in path if on windows - $path =~ m|template/([^/]+)/([^/]+)|; - my $lang = $1; - my $flavor = $2; - - chdir $topdir; # absolute path - my @testitems = Support::Templates::find_actual_files($path); - chdir $topdir; # absolute path - - next unless @testitems; - - # Some people require this, others don't. No-one knows why. - chdir $path; # relative path - - # We load a %safe list of acceptable exceptions. - if (-r "filterexceptions.pl") { - do "filterexceptions.pl"; - if (ON_WINDOWS) { - # filterexceptions.pl uses / separated paths, while - # find_actual_files returns \ separated ones on Windows. - # Here, we convert the filter exception hash to use \. - foreach my $file (keys %safe) { - my $orig_file = $file; - $file =~ s|/|\\|g; - if ($file ne $orig_file) { - $safe{$file} = $safe{$orig_file}; - delete $safe{$orig_file}; - } - } + $path =~ s|\\|/|g if ON_WINDOWS; # convert \ to / in path if on windows + $path =~ m|template/([^/]+)/([^/]+)|; + my $lang = $1; + my $flavor = $2; + + chdir $topdir; # absolute path + my @testitems = Support::Templates::find_actual_files($path); + chdir $topdir; # absolute path + + next unless @testitems; + + # Some people require this, others don't. No-one knows why. + chdir $path; # relative path + + # We load a %safe list of acceptable exceptions. + if (-r "filterexceptions.pl") { + do "filterexceptions.pl"; + if (ON_WINDOWS) { + + # filterexceptions.pl uses / separated paths, while + # find_actual_files returns \ separated ones on Windows. + # Here, we convert the filter exception hash to use \. + foreach my $file (keys %safe) { + my $orig_file = $file; + $file =~ s|/|\\|g; + if ($file ne $orig_file) { + $safe{$file} = $safe{$orig_file}; + delete $safe{$orig_file}; } + } } - - # We preprocess the %safe hash of lists into a hash of hashes. This allows - # us to flag which members were not found, and report that as a warning, - # thereby keeping the lists clean. - foreach my $file (keys %safe) { - if (ref $safe{$file} eq 'ARRAY') { - my $list = $safe{$file}; - $safe{$file} = {}; - foreach my $directive (@$list) { - $safe{$file}{$directive} = 0; - } - } + } + + # We preprocess the %safe hash of lists into a hash of hashes. This allows + # us to flag which members were not found, and report that as a warning, + # thereby keeping the lists clean. + foreach my $file (keys %safe) { + if (ref $safe{$file} eq 'ARRAY') { + my $list = $safe{$file}; + $safe{$file} = {}; + foreach my $directive (@$list) { + $safe{$file}{$directive} = 0; + } } + } - foreach my $file (@testitems) { - # There are some files we don't check, because there is no need to - # filter their contents due to their content-type. - if ($file =~ /\.(pm|txt|rst|png)\.tmpl$/) { - ok(1, "($lang/$flavor) $file is filter-safe"); - next; - } + foreach my $file (@testitems) { - # Read the entire file into a string - open (FILE, "<$file") || die "Can't open $file: $!\n"; - my $slurp = <FILE>; - close (FILE); + # There are some files we don't check, because there is no need to + # filter their contents due to their content-type. + if ($file =~ /\.(pm|txt|rst|png)\.tmpl$/) { + ok(1, "($lang/$flavor) $file is filter-safe"); + next; + } - my @unfiltered; + # Read the entire file into a string + open(FILE, "<$file") || die "Can't open $file: $!\n"; + my $slurp = <FILE>; + close(FILE); - # /g means we execute this loop for every match - # /s means we ignore linefeeds in the regexp matches - while ($slurp =~ /\[%(?:-|\+|~|=)?(.*?)(?:-|\+|~|=)?%\]/gs) { - my $directive = $1; + my @unfiltered; - my @lineno = ($` =~ m/\n/gs); - my $lineno = scalar(@lineno) + 1; + # /g means we execute this loop for every match + # /s means we ignore linefeeds in the regexp matches + while ($slurp =~ /\[%(?:-|\+|~|=)?(.*?)(?:-|\+|~|=)?%\]/gs) { + my $directive = $1; - if (!directive_ok($file, $directive)) { + my @lineno = ($` =~ m/\n/gs); + my $lineno = scalar(@lineno) + 1; - # This intentionally makes no effort to eliminate duplicates; to do - # so would merely make it more likely that the user would not - # escape all instances when attempting to correct an error. - push(@unfiltered, "$lineno:$directive"); - } - } + if (!directive_ok($file, $directive)) { - my $fullpath = File::Spec->catfile($path, $file); - - if (@unfiltered) { - my $uflist = join("\n ", @unfiltered); - ok(0, "($lang/$flavor) $fullpath has unfiltered directives:\n $uflist\n--ERROR"); - } - else { - # Find any members of the exclusion list which were not found - my @notfound; - foreach my $directive (keys %{$safe{$file}}) { - push(@notfound, $directive) if ($safe{$file}{$directive} == 0); - } - - if (@notfound) { - my $nflist = join("\n ", @notfound); - ok(0, "($lang/$flavor) $fullpath - filterexceptions.pl has extra members:\n $nflist\n" . - "--WARNING"); - } - else { - # Don't use the full path here - it's too long and unwieldy. - ok(1, "($lang/$flavor) $file is filter-safe"); - } - } + # This intentionally makes no effort to eliminate duplicates; to do + # so would merely make it more likely that the user would not + # escape all instances when attempting to correct an error. + push(@unfiltered, "$lineno:$directive"); + } } + + my $fullpath = File::Spec->catfile($path, $file); + + if (@unfiltered) { + my $uflist = join("\n ", @unfiltered); + ok(0, + "($lang/$flavor) $fullpath has unfiltered directives:\n $uflist\n--ERROR"); + } + else { + # Find any members of the exclusion list which were not found + my @notfound; + foreach my $directive (keys %{$safe{$file}}) { + push(@notfound, $directive) if ($safe{$file}{$directive} == 0); + } + + if (@notfound) { + my $nflist = join("\n ", @notfound); + ok(0, + "($lang/$flavor) $fullpath - filterexceptions.pl has extra members:\n $nflist\n" + . "--WARNING"); + } + else { + # Don't use the full path here - it's too long and unwieldy. + ok(1, "($lang/$flavor) $file is filter-safe"); + } + } + } } sub directive_ok { - my ($file, $directive) = @_; + my ($file, $directive) = @_; - # Comments - return 1 if $directive =~ /^#/; + # Comments + return 1 if $directive =~ /^#/; - # Remove any leading/trailing whitespace. - $directive =~ s/^\s*//; - $directive =~ s/\s*$//; + # Remove any leading/trailing whitespace. + $directive =~ s/^\s*//; + $directive =~ s/\s*$//; - # Empty directives are ok; they are usually line break helpers - return 1 if $directive eq ''; + # Empty directives are ok; they are usually line break helpers + return 1 if $directive eq ''; - # Make sure we're not looking for ./ in the $safe hash - $file =~ s#^\./##; + # Make sure we're not looking for ./ in the $safe hash + $file =~ s#^\./##; - # Exclude those on the nofilter list - if (defined($safe{$file}{$directive})) { - $safe{$file}{$directive}++; - return 1; - }; + # Exclude those on the nofilter list + if (defined($safe{$file}{$directive})) { + $safe{$file}{$directive}++; + return 1; + } - # Directives - return 1 if $directive =~ /^(IF|END|UNLESS|FOREACH|PROCESS|INCLUDE| + # Directives + return 1 if $directive =~ /^(IF|END|UNLESS|FOREACH|PROCESS|INCLUDE| BLOCK|USE|ELSE|NEXT|LAST|DEFAULT| ELSIF|SET|SWITCH|CASE|WHILE|RETURN|STOP| TRY|CATCH|FINAL|THROW|CLEAR|MACRO|FILTER)/x; - # ? : - if ($directive =~ /.+\?(.+):(.+)/) { - return 1 if directive_ok($file, $1) && directive_ok($file, $2); - } + # ? : + if ($directive =~ /.+\?(.+):(.+)/) { + return 1 if directive_ok($file, $1) && directive_ok($file, $2); + } + + # + - * / + return 1 if $directive =~ /[+\-*\/]/; + + # Numbers + return 1 if $directive =~ /^[0-9]+$/; + + # Simple assignments + return 1 if $directive =~ /^[\w\.\$\{\}]+\s+=\s+/; + + # Conditional literals with either sort of quotes + # There must be no $ in the string for it to be a literal + return 1 if $directive =~ /^(["'])[^\$]*[^\\]\1/; + return 1 if $directive =~ /^(["'])\1/; + + # Special values always used for numbers + return 1 if $directive =~ /^[ijkn]$/; + return 1 if $directive =~ /^count$/; + + # Params + return 1 if $directive =~ /^Param\(/; + + # Hooks + return 1 if $directive =~ /^Hook.process\(/; + + # Other functions guaranteed to return OK output + return 1 if $directive =~ /^(time2str|url)\(/; + + # Safe Template Toolkit virtual methods + return 1 if $directive =~ /\.(length$|size$|push\(|unshift\(|delete\()/; + + # Special Template Toolkit loop variable + return 1 if $directive =~ /^loop\.(index|count)$/; + + # Branding terms + return 1 if $directive =~ /^terms\./; - # + - * / - return 1 if $directive =~ /[+\-*\/]/; - - # Numbers - return 1 if $directive =~ /^[0-9]+$/; - - # Simple assignments - return 1 if $directive =~ /^[\w\.\$\{\}]+\s+=\s+/; - - # Conditional literals with either sort of quotes - # There must be no $ in the string for it to be a literal - return 1 if $directive =~ /^(["'])[^\$]*[^\\]\1/; - return 1 if $directive =~ /^(["'])\1/; - - # Special values always used for numbers - return 1 if $directive =~ /^[ijkn]$/; - return 1 if $directive =~ /^count$/; - - # Params - return 1 if $directive =~ /^Param\(/; - - # Hooks - return 1 if $directive =~ /^Hook.process\(/; - - # Other functions guaranteed to return OK output - return 1 if $directive =~ /^(time2str|url)\(/; - - # Safe Template Toolkit virtual methods - return 1 if $directive =~ /\.(length$|size$|push\(|unshift\(|delete\()/; - - # Special Template Toolkit loop variable - return 1 if $directive =~ /^loop\.(index|count)$/; - - # Branding terms - return 1 if $directive =~ /^terms\./; - - # Things which are already filtered - # Note: If a single directive prints two things, and only one is - # filtered, we may not catch that case. - return 1 if $directive =~ /FILTER\ (html|csv|js|base64|css_class_quote|ics| + # Things which are already filtered + # Note: If a single directive prints two things, and only one is + # filtered, we may not catch that case. + return 1 if $directive =~ /FILTER\ (html|csv|js|base64|css_class_quote|ics| quoteUrls|time|uri|xml|lower|html_light| obsolete|inactive|closed|unitconvert| txt|html_linebreak|none)\b/x; - return 0; + return 0; } $/ = $oldrecsep; diff --git a/t/009bugwords.t b/t/009bugwords.t index e36651edb..da432e114 100644 --- a/t/009bugwords.t +++ b/t/009bugwords.t @@ -9,9 +9,9 @@ #Bugzilla Test 9# ####bugwords##### -# Bugzilla has a mechanism for taking various words, including "bug", "bugs", +# Bugzilla has a mechanism for taking various words, including "bug", "bugs", # and "a bug" and automatically replacing them in the templates with the local -# terminology. It does this by using the 'terms' hash, so "bug" becomes +# terminology. It does this by using the 'terms' hash, so "bug" becomes # "[% terms.bug %]". This test makes sure the relevant words aren't used # bare. @@ -27,53 +27,57 @@ use Bugzilla::Util; use File::Spec; -use Test::More tests => ($Support::Templates::num_actual_files); +use Test::More tests => ($Support::Templates::num_actual_files); # Find all the templates my @testitems; for my $path (@Support::Templates::include_paths) { - push(@testitems, map(File::Spec->catfile($path, $_), - Support::Templates::find_actual_files($path))); + push( + @testitems, + map(File::Spec->catfile($path, $_), + Support::Templates::find_actual_files($path)) + ); } foreach my $file (@testitems) { - my @errors; - - # Read the entire file into a string - local $/; - open (FILE, "<$file") || die "Can't open $file: $!\n"; - my $slurp = <FILE>; - close (FILE); - - # /g means we execute this loop for every match - # /s means we ignore linefeeds in the regexp matches - # This extracts everything which is _not_ a directive. - while ($slurp =~ /%\](.*?)(\[%|$)/gs) { - my $text = $1; - - my @lineno = ($` =~ m/\n/gs); - my $lineno = scalar(@lineno) + 1; - - # "a bug", "bug", "bugs" - if (grep /(a?[\s>]bugs?[\s.:;,<])/i, $text) { - # Exclude variable assignment. - unless (grep /bugs =/, $text) { - push(@errors, [$lineno, $text]); - next; - } - } - } - - if (scalar(@errors)) { - ok(0, "$file contains invalid bare words (e.g. 'bug') --WARNING"); - - foreach my $error (@errors) { - print "$error->[0]: $error->[1]\n"; + my @errors; + + # Read the entire file into a string + local $/; + open(FILE, "<$file") || die "Can't open $file: $!\n"; + my $slurp = <FILE>; + close(FILE); + + # /g means we execute this loop for every match + # /s means we ignore linefeeds in the regexp matches + # This extracts everything which is _not_ a directive. + while ($slurp =~ /%\](.*?)(\[%|$)/gs) { + my $text = $1; + + my @lineno = ($` =~ m/\n/gs); + my $lineno = scalar(@lineno) + 1; + + # "a bug", "bug", "bugs" + if (grep /(a?[\s>]bugs?[\s.:;,<])/i, $text) { + + # Exclude variable assignment. + unless (grep /bugs =/, $text) { + push(@errors, [$lineno, $text]); + next; } - } - else { - ok(1, "$file has no invalid barewords"); } + } + + if (scalar(@errors)) { + ok(0, "$file contains invalid bare words (e.g. 'bug') --WARNING"); + + foreach my $error (@errors) { + print "$error->[0]: $error->[1]\n"; + } + } + else { + ok(1, "$file has no invalid barewords"); + } } exit 0; diff --git a/t/010dependencies.t b/t/010dependencies.t index afd29a652..b600766b6 100644 --- a/t/010dependencies.t +++ b/t/010dependencies.t @@ -30,7 +30,8 @@ use constant MODULE_REGEX => qr/ ['"]? ([\w:\.\\]+) /x; -use constant BASE_REGEX => qr/^use (?:base|parent) (?:-norequire, )?qw\(([^\)]+)/; +use constant BASE_REGEX => + qr/^use (?:base|parent) (?:-norequire, )?qw\(([^\)]+)/; # Extract all Perl modules. foreach my $file (@Support::Files::testitems) { @@ -42,46 +43,47 @@ foreach my $file (@Support::Files::testitems) { } foreach my $module (keys %mods) { - my $reading = 1; - my @use; - - open(SOURCE, $mods{$module}); - while (my $line = <SOURCE>) { - last if ($line =~ /^__END__/); - if ($line =~ /^=cut/) { - $reading = 1; - next; - } - next unless $reading; - if ($line =~ /^=(head|over|item|back|pod|begin|end|for)/) { - $reading = 0; - next; - } - if ($line =~ /^package\s+([^;]);/) { - $module = $1; - } - elsif ($line =~ BASE_REGEX or $line =~ MODULE_REGEX) { - my $used_string = $1; - # "use base"/"use parent" can have multiple modules - my @used_array = split(/\s+/, $used_string); - foreach my $used (@used_array) { - next if $used !~ /^Bugzilla/; - $used =~ s#/#::#g; - $used =~ s#\.pm$##; - $used =~ s#\$module#[^:]+#; - $used =~ s#\${[^}]+}#[^:]+#; - $used =~ s#[" ]##g; - push(@use, grep(/^\Q$used\E$/, keys %mods)); - } - } + my $reading = 1; + my @use; + + open(SOURCE, $mods{$module}); + while (my $line = <SOURCE>) { + last if ($line =~ /^__END__/); + if ($line =~ /^=cut/) { + $reading = 1; + next; + } + next unless $reading; + if ($line =~ /^=(head|over|item|back|pod|begin|end|for)/) { + $reading = 0; + next; } - close (SOURCE); + if ($line =~ /^package\s+([^;]);/) { + $module = $1; + } + elsif ($line =~ BASE_REGEX or $line =~ MODULE_REGEX) { + my $used_string = $1; - foreach my $u (@use) { - if (!grep {$_ eq $u} @{$deps{$module}}) { - push(@{$deps{$module}}, $u); + # "use base"/"use parent" can have multiple modules + my @used_array = split(/\s+/, $used_string); + foreach my $used (@used_array) { + next if $used !~ /^Bugzilla/; + $used =~ s#/#::#g; + $used =~ s#\.pm$##; + $used =~ s#\$module#[^:]+#; + $used =~ s#\${[^}]+}#[^:]+#; + $used =~ s#[" ]##g; + push(@use, grep(/^\Q$used\E$/, keys %mods)); } } + } + close(SOURCE); + + foreach my $u (@use) { + if (!grep { $_ eq $u } @{$deps{$module}}) { + push(@{$deps{$module}}, $u); + } + } } sub creates_loop { diff --git a/t/011pod.t b/t/011pod.t index 8a7f374ce..2930ea112 100644 --- a/t/011pod.t +++ b/t/011pod.t @@ -21,111 +21,123 @@ use Pod::Checker; use Pod::Coverage; use Test::More tests => scalar(@Support::Files::testitems) - + scalar(@Support::Files::module_files); + + scalar(@Support::Files::module_files); # These methods do not need to be documented by default. -use constant DEFAULT_WHITELIST => qr/^(?:new|new_from_list|check|run_create_validators)$/; +use constant DEFAULT_WHITELIST => + qr/^(?:new|new_from_list|check|run_create_validators)$/; # These subroutines do not need to be documented, generally because # you shouldn't call them yourself. No need to include subroutines # of the form _foo(); they are already treated as private. use constant SUB_WHITELIST => ( - 'Bugzilla::Flag' => qr/^(?:(force_)?retarget|force_cleanup)$/, - 'Bugzilla::FlagType' => qr/^sqlify_criteria$/, - 'Bugzilla::JobQueue' => qr/(?:^work_once|work_until_done|subprocess_worker)$/, - 'Bugzilla::Search' => qr/^SPECIAL_PARSING$/, - 'Bugzilla::Template' => qr/^field_name$/, - 'Bugzilla::MIME' => qr/^as_string$/, + 'Bugzilla::Flag' => qr/^(?:(force_)?retarget|force_cleanup)$/, + 'Bugzilla::FlagType' => qr/^sqlify_criteria$/, + 'Bugzilla::JobQueue' => qr/(?:^work_once|work_until_done|subprocess_worker)$/, + 'Bugzilla::Search' => qr/^SPECIAL_PARSING$/, + 'Bugzilla::Template' => qr/^field_name$/, + 'Bugzilla::MIME' => qr/^as_string$/, ); # These modules do not need to be documented, generally because they # are subclasses of another module which already has all the relevant # documentation. Partial names are allowed. use constant MODULE_WHITELIST => qw( - Bugzilla::Auth::Login:: - Bugzilla::Auth::Persist:: - Bugzilla::Auth::Verify:: - Bugzilla::BugUrl:: - Bugzilla::Config:: - Bugzilla::Extension:: - Bugzilla::Job:: - Bugzilla::Migrate:: - docs::lib::Pod::Simple:: + Bugzilla::Auth::Login:: + Bugzilla::Auth::Persist:: + Bugzilla::Auth::Verify:: + Bugzilla::BugUrl:: + Bugzilla::Config:: + Bugzilla::Extension:: + Bugzilla::Job:: + Bugzilla::Migrate:: + docs::lib::Pod::Simple:: ); # Capture the TESTOUT from Test::More or Test::Builder for printing errors. # This will handle verbosity for us automatically. my $fh; { - no warnings qw(unopened); # Don't complain about non-existent filehandles - if (-e \*Test::More::TESTOUT) { - $fh = \*Test::More::TESTOUT; - } elsif (-e \*Test::Builder::TESTOUT) { - $fh = \*Test::Builder::TESTOUT; - } else { - $fh = \*STDOUT; - } + no warnings qw(unopened); # Don't complain about non-existent filehandles + if (-e \*Test::More::TESTOUT) { + $fh = \*Test::More::TESTOUT; + } + elsif (-e \*Test::Builder::TESTOUT) { + $fh = \*Test::Builder::TESTOUT; + } + else { + $fh = \*STDOUT; + } } my @testitems = @Support::Files::testitems; foreach my $file (@testitems) { - $file =~ s/\s.*$//; # nuke everything after the first space (#comment) - next if (!$file); # skip null entries - my $error_count = podchecker($file, $fh); - if ($error_count < 0) { - ok(1,"$file does not contain any POD"); - } elsif ($error_count == 0) { - ok(1,"$file has correct POD syntax"); - } else { - ok(0,"$file has incorrect POD syntax --ERROR"); - } + $file =~ s/\s.*$//; # nuke everything after the first space (#comment) + next if (!$file); # skip null entries + my $error_count = podchecker($file, $fh); + if ($error_count < 0) { + ok(1, "$file does not contain any POD"); + } + elsif ($error_count == 0) { + ok(1, "$file has correct POD syntax"); + } + else { + ok(0, "$file has incorrect POD syntax --ERROR"); + } } my %sub_whitelist = SUB_WHITELIST; -my @module_files = sort @Support::Files::module_files; +my @module_files = sort @Support::Files::module_files; foreach my $file (@module_files) { - my $module = $file; - $module =~ s/\.pm$//; - $module =~ s#/#::#g; - $module =~ s/^extensions/Bugzilla::Extension/; - - my @whitelist = (DEFAULT_WHITELIST); - push(@whitelist, $sub_whitelist{$module}) if $sub_whitelist{$module}; - - # XXX Once all methods are correctly documented, nonwhitespace should - # be set to 1. - my $cover = Pod::Coverage->new(package => $module, nonwhitespace => 0, - trustme => \@whitelist); - my $coverage = $cover->coverage; - my $reason = $cover->why_unrated; - - if (defined $coverage) { - if ($coverage == 1) { - ok(1, "$file has POD for all methods"); - } - else { - ok(0, "$file POD coverage is " . sprintf("%u%%", 100 * $coverage) . - ". Undocumented methods: " . join(', ', $cover->uncovered)); - } + my $module = $file; + $module =~ s/\.pm$//; + $module =~ s#/#::#g; + $module =~ s/^extensions/Bugzilla::Extension/; + + my @whitelist = (DEFAULT_WHITELIST); + push(@whitelist, $sub_whitelist{$module}) if $sub_whitelist{$module}; + + # XXX Once all methods are correctly documented, nonwhitespace should + # be set to 1. + my $cover = Pod::Coverage->new( + package => $module, + nonwhitespace => 0, + trustme => \@whitelist + ); + my $coverage = $cover->coverage; + my $reason = $cover->why_unrated; + + if (defined $coverage) { + if ($coverage == 1) { + ok(1, "$file has POD for all methods"); } - # These errors are thrown when the module couldn't be loaded due to - # a missing dependency. - elsif ($reason =~ /^(?:no public symbols defined|requiring '[^']+' failed)$/) { - ok(1, "$file cannot be loaded"); + else { + ok(0, + "$file POD coverage is " + . sprintf("%u%%", 100 * $coverage) + . ". Undocumented methods: " + . join(', ', $cover->uncovered)); } - elsif ($reason eq "couldn't find pod") { - if (grep { $module =~ /^\Q$_\E/ } MODULE_WHITELIST) { - ok(1, "$file does not contain any POD (whitelisted)"); - } - else { - ok(0, "$file POD coverage is 0%"); - } + } + + # These errors are thrown when the module couldn't be loaded due to + # a missing dependency. + elsif ($reason =~ /^(?:no public symbols defined|requiring '[^']+' failed)$/) { + ok(1, "$file cannot be loaded"); + } + elsif ($reason eq "couldn't find pod") { + if (grep { $module =~ /^\Q$_\E/ } MODULE_WHITELIST) { + ok(1, "$file does not contain any POD (whitelisted)"); } else { - ok(0, "$file: $reason"); + ok(0, "$file POD coverage is 0%"); } + } + else { + ok(0, "$file: $reason"); + } } exit 0; diff --git a/t/012throwables.t b/t/012throwables.t index 0ef043fa5..6b092d8c2 100644 --- a/t/012throwables.t +++ b/t/012throwables.t @@ -6,7 +6,6 @@ # defined by the Mozilla Public License, v. 2.0. - ################## #Bugzilla Test 12# ######Errors###### @@ -32,11 +31,11 @@ push @{$Errors{code}{template_error}{used_in}{'Bugzilla/Error.pm'}}, 0; # Define files to test. Each file would have a list of error messages, if any. my %test_templates = (); -my %test_modules = (); +my %test_modules = (); # Find all modules foreach my $module (@Support::Files::testitems) { - $test_modules{$module} = (); + $test_modules{$module} = (); } # Find all error templates @@ -44,20 +43,19 @@ foreach my $module (@Support::Files::testitems) { # hairy. But let us do it only once. foreach my $include_path (@include_paths) { - foreach my $path (@{$actual_files{$include_path}}) { - my $file = File::Spec->catfile($include_path, $path); - $file =~ s/\s.*$//; # nuke everything after the first space - $file =~ s|\\|/|g if ON_WINDOWS; # convert \ to / in path if on windows - $test_templates{$file} = () - if $file =~ m#global/(code|user)-error\.html\.tmpl#; - - # Make sure the extension is not disabled - if ($file =~ m#^(extensions/[^/]+/)#) { - $test_templates{$file} = () - if ! -e "${1}disabled" - && $file =~ m#global/(code|user)-error-errors\.html\.tmpl#; - } + foreach my $path (@{$actual_files{$include_path}}) { + my $file = File::Spec->catfile($include_path, $path); + $file =~ s/\s.*$//; # nuke everything after the first space + $file =~ s|\\|/|g if ON_WINDOWS; # convert \ to / in path if on windows + $test_templates{$file} = () if $file =~ m#global/(code|user)-error\.html\.tmpl#; + + # Make sure the extension is not disabled + if ($file =~ m#^(extensions/[^/]+/)#) { + $test_templates{$file} = () + if !-e "${1}disabled" + && $file =~ m#global/(code|user)-error-errors\.html\.tmpl#; } + } } # Count the tests. The +1 is for checking the WS_ERROR_CODE errors. @@ -69,112 +67,115 @@ plan tests => $tests; # Collect all errors defined in templates foreach my $file (keys %test_templates) { - $file =~ m|template/([^/]+).*/global/([^/]+)-error(?:-errors)?\.html\.tmpl|; - my $lang = $1; - my $errtype = $2; - - if (! open (TMPL, $file)) { - Register(\%test_templates, $file, "could not open file --WARNING"); - next; + $file =~ m|template/([^/]+).*/global/([^/]+)-error(?:-errors)?\.html\.tmpl|; + my $lang = $1; + my $errtype = $2; + + if (!open(TMPL, $file)) { + Register(\%test_templates, $file, "could not open file --WARNING"); + next; + } + + my $lineno = 0; + while (my $line = <TMPL>) { + $lineno++; + if ($line =~ /\[%\s[A-Z]+\s*error\s*==\s*"(.+)"\s*%\]/) { + my $errtag = $1; + if ($errtag =~ /\s/) { + Register(\%test_templates, $file, + "has an error definition \"$errtag\" at line $lineno with " + . "space(s) embedded --ERROR"); + } + else { + push @{$Errors{$errtype}{$errtag}{defined_in}{$lang}{$file}}, $lineno; + } } - - my $lineno=0; - while (my $line = <TMPL>) { - $lineno++; - if ($line =~ /\[%\s[A-Z]+\s*error\s*==\s*"(.+)"\s*%\]/) { - my $errtag = $1; - if ($errtag =~ /\s/) { - Register(\%test_templates, $file, - "has an error definition \"$errtag\" at line $lineno with " - . "space(s) embedded --ERROR"); - } - else { - push @{$Errors{$errtype}{$errtag}{defined_in}{$lang}{$file}}, $lineno; - } - } - } - close(TMPL); + } + close(TMPL); } # Collect all used errors from cgi/pm files foreach my $file (keys %test_modules) { - $file =~ s/\s.*$//; # nuke everything after the first space (#comment) - next if (!$file); # skip null entries - if (! open (TMPL, $file)) { - Register(\%test_modules, $file, "could not open file --WARNING"); - next; + $file =~ s/\s.*$//; # nuke everything after the first space (#comment) + next if (!$file); # skip null entries + if (!open(TMPL, $file)) { + Register(\%test_modules, $file, "could not open file --WARNING"); + next; + } + + my $lineno = 0; + while (my $line = <TMPL>) { + last if $line =~ /^__END__/; # skip the POD (at least in + # Bugzilla/Error.pm) + $lineno++; + if ($line + =~ /^[^#]*\b(Throw(Code|User)Error|(user_)?error\s+=>)\s*\(?\s*["'](.*?)['"]/) + { + my $errtype; + + # If it's a normal ThrowCode/UserError + if ($2) { + $errtype = lc($2); + } + + # If it's an AUTH_ERROR tag + else { + $errtype = $3 ? 'user' : 'code'; + } + my $errtag = $4; + push @{$Errors{$errtype}{$errtag}{used_in}{$file}}, $lineno; } + } - my $lineno = 0; - while (my $line = <TMPL>) { - last if $line =~ /^__END__/; # skip the POD (at least in - # Bugzilla/Error.pm) - $lineno++; - if ($line =~ -/^[^#]*\b(Throw(Code|User)Error|(user_)?error\s+=>)\s*\(?\s*["'](.*?)['"]/) { - my $errtype; - # If it's a normal ThrowCode/UserError - if ($2) { - $errtype = lc($2); - } - # If it's an AUTH_ERROR tag - else { - $errtype = $3 ? 'user' : 'code'; - } - my $errtag = $4; - push @{$Errors{$errtype}{$errtag}{used_in}{$file}}, $lineno; - } - } - - close(TMPL); + close(TMPL); } # Now let us start the checks foreach my $errtype (keys %Errors) { - foreach my $errtag (keys %{$Errors{$errtype}}) { - # Check for undefined tags - if (!defined $Errors{$errtype}{$errtag}{defined_in}) { - UsedIn($errtype, $errtag, "any"); + foreach my $errtag (keys %{$Errors{$errtype}}) { + + # Check for undefined tags + if (!defined $Errors{$errtype}{$errtag}{defined_in}) { + UsedIn($errtype, $errtag, "any"); + } + else { + # Check for all languages!!! + my @langs = (); + foreach my $lang (@languages) { + if (!defined $Errors{$errtype}{$errtag}{defined_in}{$lang}) { + push @langs, $lang; } - else { - # Check for all languages!!! - my @langs = (); - foreach my $lang (@languages) { - if (!defined $Errors{$errtype}{$errtag}{defined_in}{$lang}) { - push @langs, $lang; - } - } - if (scalar @langs) { - UsedIn($errtype, $errtag, join(', ',@langs)); - } - - # Now check for tag usage in all DEFINED languages - foreach my $lang (keys %{$Errors{$errtype}{$errtag}{defined_in}}) { - if (!defined $Errors{$errtype}{$errtag}{used_in}) { - DefinedIn($errtype, $errtag, $lang); - } - } + } + if (scalar @langs) { + UsedIn($errtype, $errtag, join(', ', @langs)); + } + + # Now check for tag usage in all DEFINED languages + foreach my $lang (keys %{$Errors{$errtype}{$errtag}{defined_in}}) { + if (!defined $Errors{$errtype}{$errtag}{used_in}) { + DefinedIn($errtype, $errtag, $lang); } + } } + } } # And make sure that everything defined in WS_ERROR_CODE # is actually a valid error. foreach my $err_name (keys %{WS_ERROR_CODE()}) { - if (!defined $Errors{'code'}{$err_name} - && !defined $Errors{'user'}{$err_name}) - { - Register(\%test_modules, 'WS_ERROR_CODE', - "Error tag '$err_name' is used in WS_ERROR_CODE in" - . " Bugzilla/WebService/Constants.pm" - . " but not defined in any template, and not used in any code."); - } + if (!defined $Errors{'code'}{$err_name} && !defined $Errors{'user'}{$err_name}) + { + Register(\%test_modules, 'WS_ERROR_CODE', + "Error tag '$err_name' is used in WS_ERROR_CODE in" + . " Bugzilla/WebService/Constants.pm" + . " but not defined in any template, and not used in any code."); + } } # Now report modules results foreach my $file (sort keys %test_modules) { - Report($file, @{$test_modules{$file}}); + Report($file, @{$test_modules{$file}}); } # And report WS_ERROR_CODE results @@ -182,56 +183,67 @@ Report('WS_ERROR_CODE', @{$test_modules{'WS_ERROR_CODE'}}); # Now report templates results foreach my $file (sort keys %test_templates) { - Report($file, @{$test_templates{$file}}); + Report($file, @{$test_templates{$file}}); } sub Register { - my ($hash, $file, $message, $warning) = @_; - # If set to 1, $warning will avoid the test to fail. - $warning ||= 0; - push(@{$hash->{$file}}, {'message' => $message, 'warning' => $warning}); + my ($hash, $file, $message, $warning) = @_; + + # If set to 1, $warning will avoid the test to fail. + $warning ||= 0; + push(@{$hash->{$file}}, {'message' => $message, 'warning' => $warning}); } sub Report { - my ($file, @errors) = @_; - if (scalar @errors) { - # Do we only have warnings to report or also real errors? - my @real_errors = grep {$_->{'warning'} == 0} @errors; - # Extract error messages. - @errors = map {$_->{'message'}} @errors; - if (scalar(@real_errors)) { - ok(0, "$file has ". scalar(@errors) ." error(s):\n" . join("\n", @errors)); - } - else { - ok(1, "--WARNING $file has " . scalar(@errors) . - " unused error tag(s):\n" . join("\n", @errors)); - } + my ($file, @errors) = @_; + if (scalar @errors) { + + # Do we only have warnings to report or also real errors? + my @real_errors = grep { $_->{'warning'} == 0 } @errors; + + # Extract error messages. + @errors = map { $_->{'message'} } @errors; + if (scalar(@real_errors)) { + ok(0, "$file has " . scalar(@errors) . " error(s):\n" . join("\n", @errors)); } else { - # This is used for both code and template files, so let's use - # file-independent phrase - ok(1, "$file uses error tags correctly"); + ok(1, + "--WARNING $file has " + . scalar(@errors) + . " unused error tag(s):\n" + . join("\n", @errors)); } + } + else { + # This is used for both code and template files, so let's use + # file-independent phrase + ok(1, "$file uses error tags correctly"); + } } sub UsedIn { - my ($errtype, $errtag, $lang) = @_; - $lang = $lang || "any"; - foreach my $file (keys %{$Errors{$errtype}{$errtag}{used_in}}) { - Register(\%test_modules, $file, - "$errtype error tag '$errtag' is used at line(s) (" - . join (',', @{$Errors{$errtype}{$errtag}{used_in}{$file}}) - . ") but not defined for language(s): $lang"); - } + my ($errtype, $errtag, $lang) = @_; + $lang = $lang || "any"; + foreach my $file (keys %{$Errors{$errtype}{$errtag}{used_in}}) { + Register(\%test_modules, $file, + "$errtype error tag '$errtag' is used at line(s) (" + . join(',', @{$Errors{$errtype}{$errtag}{used_in}{$file}}) + . ") but not defined for language(s): $lang"); + } } + sub DefinedIn { - my ($errtype, $errtag, $lang) = @_; - foreach my $file (keys %{$Errors{$errtype}{$errtag}{defined_in}{$lang}}) { - Register(\%test_templates, $file, - "$errtype error tag '$errtag' is defined at line(s) (" - . join (',', @{$Errors{$errtype}{$errtag}{defined_in}{$lang}{$file}}) - . ") but is not used anywhere", 1); - } + my ($errtype, $errtag, $lang) = @_; + foreach my $file (keys %{$Errors{$errtype}{$errtag}{defined_in}{$lang}}) { + Register( + \%test_templates, + $file, + "$errtype error tag '$errtag' is defined at line(s) (" + . join(',', @{$Errors{$errtype}{$errtag}{defined_in}{$lang}{$file}}) + . ") but is not used anywhere", + 1 + ); + } } exit 0; diff --git a/t/013dbschema.t b/t/013dbschema.t index 217176ff2..062a22992 100644 --- a/t/013dbschema.t +++ b/t/013dbschema.t @@ -23,30 +23,30 @@ use Bugzilla::DB::Schema; # SQL reserved words use constant RESERVED_WORDS => qw( - ABSOLUTE ACTION ACTOR ADD AFTER ALL ALLOCATE ALTER ANY AND ARE AS ASC ASSERTION ASYNC AT - ATTRIBUTES BEFORE BEGIN BETWEEN BIT BIT_LENGTH BOOLEAN BOTH BREADTH BY CALL CASCADE - CASCADED CASE CAST CATALOG CHAR CHARACTER_LENGTH CHAR_LENGTH COLLATE - COLLATION COLUMN COMPLETION CONNECT CONNECTION CONSTRAINT CONSTRAINTS - CONVERT CORRESPONDING CREATE CROSS CURRENT_DATE CURRENT_PATH CURRENT_TIME - CURRENT_TIMESTAMP CURRENT_USER CYCLE DATA DATE DAY DEALLOCATE DECLARE DEFAULT DEFERRABLE - DEFERRED DELETE DEPTH DESC DESCRIBE DESCRIPTOR DESTROY DIAGNOSTICS DICTIONARY - DISCONNECT DISTINCT DO DOMAIN DROP EACH ELEMENT ELSE ELSEIF END END-EXEC EQUALS EXCEPT - EXCEPTION EXECUTE EXTERNAL EXTRACT FACTOR FALSE FIRST FOR FROM FULL GENERAL GET - GLOBAL GRANT GROUP HAVING HOLD HOUR IDENTITY IF IGNORE IMMEDIATE IN INITIALLY INNER INPUT - INSENSITIVE INSERT INSTEAD INTERSECT INTERVAL IS ISOLATION JOIN LAST LEADING LEAVE - LEFT LESS LEVEL LIMIT LIST LOCAL LOOP LOWER MATCH MINUTE MODIFY MONTH NAMES - NATIONAL NATURAL NCHAR NEW NEW_TABLE NEXT NO NONE NOT NULL NULLIF OBJECT - OCTET_LENGTH OFF OID OLD OLD_TABLE ONLY OPERATION OPERATOR OPERATORS OR ORDER OTHERS - OUTER OUTPUT OVERLAPS PAD PARAMETERS PARTIAL PATH PENDANT POSITION POSTFIX - PREFIX PREORDER PREPARE PRESERVE PRIOR PRIVATE PROTECTED READ RECURSIVE REF - REFERENCING RELATIVE REPLACE RESIGNAL RESTRICT RETURN RETURNS REVOKE RIGHT - ROLE ROUTINE ROW ROWS SAVEPOINT SCROLL SEARCH SECOND SELECT SENSITIVE SEQUENCE - SESSION SESSION_USER SIGNAL SIMILAR SIZE SPACE SQLEXCEPTION SQLSTATE - SQLWARNING START STATE STRUCTURE SUBSTRING SYMBOL SYSTEM_USER TABLE TEMPORARY - TERM TEST THEN THERE TIME TIMESTAMP TIMEZONE_HOUR TIMEZONE_MINUTE TRAILING - TRANSACTION TRANSLATE TRANSLATION TRIGGER TRIM TRUE TUPLE UNDER - UNKNOWN UNION UNIQUE UPDATE UPPER USAGE USING VARCHAR VARIABLE VARYING VIEW VIRTUAL VISIBLE - WAIT WHEN WHERE WHILE WITH WITHOUT WRITE YEAR ZONE + ABSOLUTE ACTION ACTOR ADD AFTER ALL ALLOCATE ALTER ANY AND ARE AS ASC ASSERTION ASYNC AT + ATTRIBUTES BEFORE BEGIN BETWEEN BIT BIT_LENGTH BOOLEAN BOTH BREADTH BY CALL CASCADE + CASCADED CASE CAST CATALOG CHAR CHARACTER_LENGTH CHAR_LENGTH COLLATE + COLLATION COLUMN COMPLETION CONNECT CONNECTION CONSTRAINT CONSTRAINTS + CONVERT CORRESPONDING CREATE CROSS CURRENT_DATE CURRENT_PATH CURRENT_TIME + CURRENT_TIMESTAMP CURRENT_USER CYCLE DATA DATE DAY DEALLOCATE DECLARE DEFAULT DEFERRABLE + DEFERRED DELETE DEPTH DESC DESCRIBE DESCRIPTOR DESTROY DIAGNOSTICS DICTIONARY + DISCONNECT DISTINCT DO DOMAIN DROP EACH ELEMENT ELSE ELSEIF END END-EXEC EQUALS EXCEPT + EXCEPTION EXECUTE EXTERNAL EXTRACT FACTOR FALSE FIRST FOR FROM FULL GENERAL GET + GLOBAL GRANT GROUP HAVING HOLD HOUR IDENTITY IF IGNORE IMMEDIATE IN INITIALLY INNER INPUT + INSENSITIVE INSERT INSTEAD INTERSECT INTERVAL IS ISOLATION JOIN LAST LEADING LEAVE + LEFT LESS LEVEL LIMIT LIST LOCAL LOOP LOWER MATCH MINUTE MODIFY MONTH NAMES + NATIONAL NATURAL NCHAR NEW NEW_TABLE NEXT NO NONE NOT NULL NULLIF OBJECT + OCTET_LENGTH OFF OID OLD OLD_TABLE ONLY OPERATION OPERATOR OPERATORS OR ORDER OTHERS + OUTER OUTPUT OVERLAPS PAD PARAMETERS PARTIAL PATH PENDANT POSITION POSTFIX + PREFIX PREORDER PREPARE PRESERVE PRIOR PRIVATE PROTECTED READ RECURSIVE REF + REFERENCING RELATIVE REPLACE RESIGNAL RESTRICT RETURN RETURNS REVOKE RIGHT + ROLE ROUTINE ROW ROWS SAVEPOINT SCROLL SEARCH SECOND SELECT SENSITIVE SEQUENCE + SESSION SESSION_USER SIGNAL SIMILAR SIZE SPACE SQLEXCEPTION SQLSTATE + SQLWARNING START STATE STRUCTURE SUBSTRING SYMBOL SYSTEM_USER TABLE TEMPORARY + TERM TEST THEN THERE TIME TIMESTAMP TIMEZONE_HOUR TIMEZONE_MINUTE TRAILING + TRANSACTION TRANSLATE TRANSLATION TRIGGER TRIM TRUE TUPLE UNDER + UNKNOWN UNION UNIQUE UPDATE UPPER USAGE USING VARCHAR VARIABLE VARYING VIEW VIRTUAL VISIBLE + WAIT WHEN WHERE WHILE WITH WITHOUT WRITE YEAR ZONE ); # Few Exceptions are removed from the above list @@ -57,31 +57,31 @@ our $schema; our @tables; BEGIN { - $schema = Bugzilla::DB::Schema->new("Mysql"); - @tables = $schema->get_table_list(); + $schema = Bugzilla::DB::Schema->new("Mysql"); + @tables = $schema->get_table_list(); } use Test::More tests => scalar(@tables); foreach my $table (@tables) { - my @reserved; + my @reserved; - if (grep { uc($table) eq $_ } RESERVED_WORDS) { - push(@reserved, $table); - } + if (grep { uc($table) eq $_ } RESERVED_WORDS) { + push(@reserved, $table); + } - foreach my $column ($schema->get_table_columns($table)) { - if (grep { uc($column) eq $_ } RESERVED_WORDS) { - push(@reserved, $column); - } + foreach my $column ($schema->get_table_columns($table)) { + if (grep { uc($column) eq $_ } RESERVED_WORDS) { + push(@reserved, $column); } + } - if (scalar @reserved) { - ok(0, "Table $table use reserved words: " . join(", ", @reserved)); - } - else { - ok(1, "Table $table does not use reserved words"); - } + if (scalar @reserved) { + ok(0, "Table $table use reserved words: " . join(", ", @reserved)); + } + else { + ok(1, "Table $table does not use reserved words"); + } } exit 0; diff --git a/t/Support/Files.pm b/t/Support/Files.pm index f3fae58fc..72737ac1f 100644 --- a/t/Support/Files.pm +++ b/t/Support/Files.pm @@ -17,40 +17,40 @@ use File::Find; our @additional_files = (); our @files = glob('*'); -find(sub { push(@files, $File::Find::name) if $_ =~ /\.pm$/;}, qw(Bugzilla docs)); +find(sub { push(@files, $File::Find::name) if $_ =~ /\.pm$/; }, + qw(Bugzilla docs)); push(@files, 'extensions/create.pl', 'docs/makedocs.pl'); -our @extensions = - grep { $_ ne 'extensions/create.pl' && ! -e "$_/disabled" } - glob('extensions/*'); +our @extensions = grep { $_ ne 'extensions/create.pl' && !-e "$_/disabled" } + glob('extensions/*'); foreach my $extension (@extensions) { - find(sub { push(@files, $File::Find::name) if $_ =~ /\.pm$/;}, $extension); + find(sub { push(@files, $File::Find::name) if $_ =~ /\.pm$/; }, $extension); } our @test_files = glob('t/*.t'); sub isTestingFile { - my ($file) = @_; - my $exclude; - - if ($file =~ /\.cgi$|\.pl$|\.pm$/) { - return 1; - } - my $additional; - foreach $additional (@additional_files) { - if ($file eq $additional) { return 1; } - } - return undef; + my ($file) = @_; + my $exclude; + + if ($file =~ /\.cgi$|\.pl$|\.pm$/) { + return 1; + } + my $additional; + foreach $additional (@additional_files) { + if ($file eq $additional) { return 1; } + } + return undef; } our (@testitems, @module_files); foreach my $currentfile (@files) { - if (isTestingFile($currentfile)) { - push(@testitems, $currentfile); - } - push(@module_files, $currentfile) if $currentfile =~ /\.pm$/; + if (isTestingFile($currentfile)) { + push(@testitems, $currentfile); + } + push(@module_files, $currentfile) if $currentfile =~ /\.pm$/; } diff --git a/t/Support/Templates.pm b/t/Support/Templates.pm index d17c7334b..e08686e0f 100644 --- a/t/Support/Templates.pm +++ b/t/Support/Templates.pm @@ -13,9 +13,9 @@ use warnings; use lib 't'; use parent qw(Exporter); -@Support::Templates::EXPORT = - qw(@languages @include_paths @english_default_include_paths - @referenced_files %actual_files $num_actual_files); +@Support::Templates::EXPORT + = qw(@languages @include_paths @english_default_include_paths + @referenced_files %actual_files $num_actual_files); use Bugzilla; use Bugzilla::Constants; @@ -26,15 +26,15 @@ use File::Find; use File::Spec; # English default include paths -our @english_default_include_paths = - (File::Spec->catdir(bz_locations()->{'templatedir'}, 'en', 'default')); +our @english_default_include_paths + = (File::Spec->catdir(bz_locations()->{'templatedir'}, 'en', 'default')); # And the extensions too foreach my $extension (@Support::Files::extensions) { - my $dir = File::Spec->catdir($extension, 'template', 'en', 'default'); - if (-e $dir) { - push @english_default_include_paths, $dir; - } + my $dir = File::Spec->catdir($extension, 'template', 'en', 'default'); + if (-e $dir) { + push @english_default_include_paths, $dir; + } } # Files which are referenced in the cgi files @@ -47,37 +47,39 @@ our %actual_files = (); our $num_actual_files = 0; # Set the template available languages and include paths -our @languages = @{ Bugzilla->languages }; -our @include_paths = @{ template_include_path({ language => Bugzilla->languages }) }; +our @languages = @{Bugzilla->languages}; +our @include_paths + = @{template_include_path({language => Bugzilla->languages})}; our @files; # Local subroutine used with File::Find sub find_templates { - # Prune CVS directories - if (-d $_ && $_ eq 'CVS') { - $File::Find::prune = 1; - return; - } - # Only include files ending in '.tmpl' - if (-f $_ && $_ =~ m/\.tmpl$/i) { - my $filename; - my $local_dir = File::Spec->abs2rel($File::Find::dir, - $File::Find::topdir); + # Prune CVS directories + if (-d $_ && $_ eq 'CVS') { + $File::Find::prune = 1; + return; + } - # File::Spec 3.13 and newer return "." instead of "" if both - # arguments of abs2rel() are identical. - $local_dir = "" if ($local_dir eq "."); + # Only include files ending in '.tmpl' + if (-f $_ && $_ =~ m/\.tmpl$/i) { + my $filename; + my $local_dir = File::Spec->abs2rel($File::Find::dir, $File::Find::topdir); - if ($local_dir) { - $filename = File::Spec->catfile($local_dir, $_); - } else { - $filename = $_; - } + # File::Spec 3.13 and newer return "." instead of "" if both + # arguments of abs2rel() are identical. + $local_dir = "" if ($local_dir eq "."); - push(@files, $filename); + if ($local_dir) { + $filename = File::Spec->catfile($local_dir, $_); } + else { + $filename = $_; + } + + push(@files, $filename); + } } # Scan the given template include path for templates @@ -90,7 +92,7 @@ sub find_actual_files { foreach my $include_path (@include_paths) { - $actual_files{$include_path} = [ find_actual_files($include_path) ]; + $actual_files{$include_path} = [find_actual_files($include_path)]; $num_actual_files += scalar(@{$actual_files{$include_path}}); } @@ -99,20 +101,21 @@ foreach my $include_path (@include_paths) { my %seen; foreach my $file (@Support::Files::testitems) { - open (FILE, $file); - my @lines = <FILE>; - close (FILE); - foreach my $line (@lines) { - if ($line =~ m/template->process\(\"(.+?)\", .+?\)/) { - my $template = $1; - # Ignore templates with $ in the name, since they're - # probably vars, not real files - next if $template =~ m/\$/; - next if $seen{$template}; - push (@referenced_files, $template); - $seen{$template} = 1; - } + open(FILE, $file); + my @lines = <FILE>; + close(FILE); + foreach my $line (@lines) { + if ($line =~ m/template->process\(\"(.+?)\", .+?\)/) { + my $template = $1; + + # Ignore templates with $ in the name, since they're + # probably vars, not real files + next if $template =~ m/\$/; + next if $seen{$template}; + push(@referenced_files, $template); + $seen{$template} = 1; } + } } 1; |