diff --git a/README b/README index f51361b0..dc133dfd 100644 --- a/README +++ b/README @@ -371,7 +371,7 @@ LCOV features and capabilities fall into 7 major categories: --baseline-title, --baseline-date, --current-date, --flat, --hierarchical, --show-owners, --show-noncode, --show-navigation, --show-proportion, - --suppress-aliases + --suppress-aliases --simplify-script d) Data manipulation @@ -421,8 +421,10 @@ LCOV features and capabilities fall into 7 major categories: the changes caused by a particular commit or range of commits, or to review changes in a particular release. Sample script: select.pm - vi) keep track of environment and other settings - to aid + vi) keep track of environment and other settings - to aid infrastructure debugging in more complicated use cases. + vii) compress the 'function detail' table to improve readability + by shortening long C++ template and function names. The callback may be any desired script or executable - but there may be performance advantages if it is written as a Perl module. @@ -436,6 +438,7 @@ LCOV features and capabilities fall into 7 major categories: Related options: --annotate-script, --criteria-script, --version-script --resolve-script, --select-script, --context-script + --simplify-script f) Performance diff --git a/bin/genhtml b/bin/genhtml index 93cc8c51..ea0d5de0 100755 --- a/bin/genhtml +++ b/bin/genhtml @@ -291,6 +291,8 @@ sub write_overview(*$$$$); # External prototype (defined in genpng) sub gen_png($$$$$@); +sub simplify_function_name($); + package SummaryInfo; our @selectCallbackScript; @@ -5471,7 +5473,7 @@ sub _computeAge if ($then > $now) { if (lcovutil::warn_once($lcovutil::ERROR_INCONSISTENT_DATA, $path)) { # issue annotation warning at most once per file - # also attempt to clarify where the date comes from + # also attempt to clarify where the date comes from my $data = exists($ENV{SOURCE_DATE_EPOCH}) ? ( @@ -6853,10 +6855,14 @@ our @rate_png = ("ruby.png", "amber.png", "emerald.png"); our $rc_desc_html = 0; # lcovrc: genhtml_desc_html our $deprecated_highlight; # ignored former option -our $cwd = cwd(); # Current working directory +# simplify/shorten names in 'function detail table' +our @simplifyFunctionScript; # the arg list +our $simplifyFunctionCallback; # the actual callback + +our $cwd = cwd(); # Current working directory # for debugging -our $verboseScopeRegexp; # dump categorization processing if match +our $verboseScopeRegexp; # dump categorization processing if match # # Code entry point @@ -6869,7 +6875,8 @@ STDERR->autoflush; STDOUT->autoflush; my @datebins; -my (@rc_date_bins, @rc_annotate_script, @rc_select_script, @rc_date_labels); +my (@rc_date_bins, @rc_annotate_script, @rc_select_script, @rc_date_labels, + @rc_simplifyFunctionScript); my %genhtml_rc_opts = ( "genhtml_css_file" => \$css_filename, @@ -6925,6 +6932,7 @@ my %genhtml_rc_opts = ( 'genhtml_annotate_script' => \@rc_annotate_script, 'genhtml_annotate_tooltip' => \$SourceFile::annotateTooltip, "select_script" => \@rc_select_script, + "simplify_function" => \@rc_simplifyFunctionScript, 'num_context_lines' => \$InInterestingRegion::num_context_lines, 'genhtml_date_bins' => \@rc_date_bins, 'genhtml_date_labels' => \@rc_date_labels, @@ -6938,60 +6946,62 @@ my $save; my $serialize; my $validateHTML = exists($ENV{LCOV_VALIDATE}); -my %genhtml_options = ("output-directory|o=s" => \$output_directory, - "header-title=s" => \$header_title, - "footer=s" => \$footer, - "title|t=s" => \$test_title, - "description-file|d=s" => \$desc_filename, - "keep-descriptions|k" => \$keep_descriptions, - "css-file|c=s" => \$css_filename, - "baseline-file|b=s" => \@base_filenames, - "baseline-title=s" => \$baseline_title, - "baseline-date=s" => \$baseline_date, - "current-date=s" => \$current_date, - "diff-file=s" => \$diff_filename, - "annotate-script=s" => \@SourceFile::annotateScript, - "select-script=s" => \@selectCallbackScript, - "new-file-as-baseline" => \$treatNewFileAsBaseline, - 'elide-path-mismatch' => \$elide_path_mismatch, - 'synthesize-missing' => \$synthesizeMissingFile, - # if 'show-owners' is set: generate the owner table - # if it is passed a value: show all the owners, - # regardless of whether they have uncovered code or not - 'show-owners:s' => \$show_ownerBins, - 'show-noncode' => \$show_nonCodeOwners, - 'show-zero-columns' => \$show_zeroTlaColumns, - 'simplified-colors' => \$show_simplifiedColors, - "date-bins=s" => \@datebins, - 'date-labels=s' => \@SummaryInfo::ageGroupHeader, - "prefix|p=s" => \@opt_dir_prefix, - "num-spaces=i" => \$tab_size, - "no-prefix" => \$no_prefix, - "no-sourceview" => \$no_sourceview, - 'no-html' => \$no_html, - "show-details|s" => \$show_details, - "frames|f" => \$frames, - "highlight" => \$deprecated_highlight, - "legend" => \$legend, - 'save' => \$save, - 'serialize=s' => \$serialize, - 'scheduler+' => \$debugScheduler, - "html-prolog=s" => \$html_prolog_file, - "html-epilog=s" => \$html_epilog_file, - "html-extension=s" => \$html_ext, - "html-gzip" => \$html_gzip, - "hierarchical" => \$hierarchical, - "flat" => \$flat, - "sort-tables" => \$sort_tables, - "no-sort" => \$no_sort, - "precision=i" => \$lcovutil::default_precision, - "missed" => \$opt_missed, - "dark-mode" => \$dark_mode, - "show-navigation" => \$show_tla, - "show-proportion" => \$show_functionProportions, - "merge-aliases" => \$merge_function_aliases, - "suppress-aliases" => \$suppress_function_aliases, - 'validate' => \$validateHTML,); +my %genhtml_options = ( + "output-directory|o=s" => \$output_directory, + "header-title=s" => \$header_title, + "footer=s" => \$footer, + "title|t=s" => \$test_title, + "description-file|d=s" => \$desc_filename, + "keep-descriptions|k" => \$keep_descriptions, + "css-file|c=s" => \$css_filename, + "baseline-file|b=s" => \@base_filenames, + "baseline-title=s" => \$baseline_title, + "baseline-date=s" => \$baseline_date, + "current-date=s" => \$current_date, + "diff-file=s" => \$diff_filename, + "annotate-script=s" => \@SourceFile::annotateScript, + "select-script=s" => \@SummaryInfo::selectCallbackScript, + "simplify-script=s" => \@simplifyFunctionScript, + "new-file-as-baseline" => \$treatNewFileAsBaseline, + 'elide-path-mismatch' => \$elide_path_mismatch, + 'synthesize-missing' => \$synthesizeMissingFile, + # if 'show-owners' is set: generate the owner table + # if it is passed a value: show all the owners, + # regardless of whether they have uncovered code or not + 'show-owners:s' => \$show_ownerBins, + 'show-noncode' => \$show_nonCodeOwners, + 'show-zero-columns' => \$show_zeroTlaColumns, + 'simplified-colors' => \$show_simplifiedColors, + "date-bins=s" => \@datebins, + 'date-labels=s' => \@SummaryInfo::ageGroupHeader, + "prefix|p=s" => \@opt_dir_prefix, + "num-spaces=i" => \$tab_size, + "no-prefix" => \$no_prefix, + "no-sourceview" => \$no_sourceview, + 'no-html' => \$no_html, + "show-details|s" => \$show_details, + "frames|f" => \$frames, + "highlight" => \$deprecated_highlight, + "legend" => \$legend, + 'save' => \$save, + 'serialize=s' => \$serialize, + 'scheduler+' => \$debugScheduler, + "html-prolog=s" => \$html_prolog_file, + "html-epilog=s" => \$html_epilog_file, + "html-extension=s" => \$html_ext, + "html-gzip" => \$html_gzip, + "hierarchical" => \$hierarchical, + "flat" => \$flat, + "sort-tables" => \$sort_tables, + "no-sort" => \$no_sort, + "precision=i" => \$lcovutil::default_precision, + "missed" => \$opt_missed, + "dark-mode" => \$dark_mode, + "show-navigation" => \$show_tla, + "show-proportion" => \$show_functionProportions, + "merge-aliases" => \$merge_function_aliases, + "suppress-aliases" => \$suppress_function_aliases, + 'validate' => \$validateHTML,); # remove ambiguous entry from common table - # (genhtml has '--sort-inputs' and '--sort-tables') @@ -7041,18 +7051,28 @@ $frames = undef unless (defined($frames) && $frames); foreach my $rc ([\@datebins, \@rc_date_bins], [\@SummaryInfo::ageGroupHeader, \@rc_date_labels], [\@SourceFile::annotateScript, \@rc_annotate_script], - [\@selectCallbackScript, \@rc_select_script] + [\@SummaryInfo::selectCallbackScript, \@rc_select_script], + [\@simplifyFunctionScript, \@rc_simplifyFunctionScript], ) { @{$rc->[0]} = @{$rc->[1]} unless (@{$rc->[0]}); } foreach my $cb ([\$SourceFile::annotateCallback, \@SourceFile::annotateScript], - [\$selectCallback, \@selectCallbackScript]) { + [\$SummaryInfo::selectCallback, + \@SummaryInfo::selectCallbackScript + ], + [\$simplifyFunctionCallback, \@simplifyFunctionScript], +) { lcovutil::configure_callback($cb->[0], @{$cb->[1]}) if scalar(@{$cb->[1]}); } +# we won't apply simplifications if we don't generate the table +# (we still check that the callback is valid - even though we don't use it) +$simplifyFunctionCallback = undef + if $no_sourceview; + if (defined($lcovutil::stop_on_error) && !$lcovutil::stop_on_error) { # in the spirit of "don't stop" - don't worry about missing files. @@ -8384,7 +8404,7 @@ sub read_testfile($) local *TEST_HANDLE; open(TEST_HANDLE, "<", $file) or - die("cannot open $file]: $!\n"); + die("cannot open description file '$file': $!\n"); while () { chomp($_); @@ -13322,7 +13342,7 @@ sub write_source($$$$$$$$) my $cbdata = PrintCallback->new($srcfile, $fileCovInfo); my ($region, $empty); - if ($selectCallback) { + if ($SummaryInfo::selectCallback) { $region = InInterestingRegion->new($srcfile, $fileCovInfo->lineMap()); $empty = ''; if ($srcfile->isProjectFile()) { @@ -13583,7 +13603,7 @@ END_OF_HTML next if grep(/^$tla$/, ('DUB', 'DCB')); # don't display deleted functions my $startline = $funcEntry->line() - $func_offset; - my $name = $func; + my $name = simplify_function_name($func); my $countstyle; # Escape special characters @@ -13701,7 +13721,7 @@ END_OF_HTML } # Escape special characters - $alias = escape_html($alias); + $alias = escape_html(simplify_function_name($alias)); write_html(*HTML_HANDLE, < @@ -13878,3 +13898,24 @@ sub parse_dir_prefix(@) } } } + +# +# simplify_function_name($name) +# +# apply @function_simplify_patterns to $name and return +# goal is to shorten really long demangled names/template expansions +# +sub simplify_function_name($) +{ + my $name = shift; + if ($simplifyFunctionCallback) { + + eval { $name = $simplifyFunctionCallback->simplify($name); }; + if ($@) { + my $context = MessageContext::context(); + lcovutil::ignorable_error($lcovutil::ERROR_CALLBACK, + "simplify($name) failed$context: $@"); + } + } + return $name; +} diff --git a/bin/llvm2lcov b/bin/llvm2lcov index 99377ae9..7bcd9211 100755 --- a/bin/llvm2lcov +++ b/bin/llvm2lcov @@ -239,7 +239,8 @@ sub parse } if ($mcdc && $json_version < version->parse("3.0.1")) { my $mcdcData = $fileInfo->testcase_mcdc($testname); - my @mcdcBranches; # array (start line, start column, expression) + my @mcdcBranches + ; # array (start line, start column, expression) foreach my $branch (@$branches) { die("unexpected branch data") unless scalar(@$branch) == 9; @@ -273,8 +274,8 @@ sub parse if (($brLine > $line || ($brLine == $line && $brCol >= $startCol)) && - ($brLine < $endLine || - ($brLine == $endLine && $brCol <= $endCol)) + ( $brLine < $endLine || + ($brLine == $endLine && $brCol <= $endCol)) ) { push(@brExprs, [$brLine, $brCol, $brExpr]); } @@ -344,8 +345,10 @@ sub parse $functionMap->add_count($name, $count); } - my @mcdcBranches; # array (fileId, start line, start column, expression) - my %expanded_mcdcBranches; # hash of branch's fileId -> branch's start line + my @mcdcBranches + ; # array (fileId, start line, start column, expression) + my %expanded_mcdcBranches + ; # hash of branch's fileId -> branch's start line if ($branchData) { my $funcBranchData = BranchData->new(); @@ -451,15 +454,17 @@ sub parse if (($brLine > $line || ($brLine == $line && $brCol >= $col)) && - ($brLine < $endLine || - ($brLine == $endLine && $brCol <= $endCol)) + ( $brLine < $endLine || + ($brLine == $endLine && + $brCol <= $endCol)) ) { push(@brExprs, [$brLine, $brCol, $brExpr]); } } - @brExprs = sort {$a->[0] <=> $b->[0] || - $a->[1] <=> $b->[1] - } @brExprs; + @brExprs = sort { + $a->[0] <=> $b->[0] || + $a->[1] <=> $b->[1] + } @brExprs; $expr = $srcReader->getExpr($line, $col, $endLine, $endCol) diff --git a/lib/lcovutil.pm b/lib/lcovutil.pm index 16bf6a0a..68baa166 100644 --- a/lib/lcovutil.pm +++ b/lib/lcovutil.pm @@ -1656,6 +1656,30 @@ sub transform_pattern($) return qr($pattern); } +sub verify_regexp_patterns +{ + my ($flag, $list, $checkInsensitive) = @_; + PAT: foreach my $pat (@$list) { + my $text = 'abc'; + my $str = eval "\$text =~ $pat ;"; + die("Invalid regexp \"$flag $pat\":\n$@") + if $@; + + if ($checkInsensitive) { + for (my $i = length($pat) - 1; $i >= 0; --$i) { + my $char = substr($pat, $i, 1); + next PAT + if ($char eq 'i'); + last # didn't see the 'i' character + if ($char =~ /[\/#!@%]/); + } + lcovutil::ignorable_warning($lcovutil::ERROR_USAGE, + "$flag pattern '$pat' does not seem to be case insensitive - but you asked for case insensitive matching" + ); + } + } +} + sub munge_file_patterns { # Need perlreg expressions instead of shell pattern @@ -1683,30 +1707,12 @@ sub munge_file_patterns if $@; } # sadly, substitutions aren't regexps and can't be precompiled - foreach my $p (['substitute', \@file_subst_patterns]) { - my ($flag, $list) = @$p; - next unless @$list; - PAT: foreach my $pat (@$list) { - my $text = 'abc'; - my $str = eval { '$test =~ ' . $pat . ';' }; - die("Invalid regexp \"$flag $pat\":\n$@") - if $@; - - if ($lcovutil::case_insensitive) { - for (my $i = length($pat) - 1; $i >= 0; --$i) { - my $char = substr($pat, $i, 1); - next PAT - if ($char eq 'i'); - last # didn't see the 'i' character - if ($char =~ /[\/#!@%]/); - } - lcovutil::ignorable_warning($lcovutil::ERROR_USAGE, - "--$flag pattern '$pat' does not seem to be case insensitive - but you asked for case insensitive matching" - ); - } - } + if (@file_subst_patterns) { + verify_regexp_patterns('--substitute', \@file_subst_patterns, + \$lcovutil::case_insensitive); + # keep track of number of times this was applied - @$list = map({ [$_, 0]; } @$list); + @file_subst_patterns = map({ [$_, 0]; } @file_subst_patterns); } # and check for valid region patterns @@ -1745,7 +1751,7 @@ sub warn_file_patterns ['exclude', \@exclude_file_patterns], ['substitute', \@file_subst_patterns], ['omit-lines', \@omit_line_patterns], - ['exclude-functions', \@exclude_function_patterns] + ['exclude-functions', \@exclude_function_patterns], ) { my ($type, $patterns) = @$p; foreach my $pat (@$patterns) { @@ -2068,7 +2074,7 @@ sub initial_state \@lcovutil::include_file_patterns, \@lcovutil::file_subst_patterns, \@lcovutil::omit_line_patterns, - \@lcovutil::exclude_function_patterns + \@lcovutil::exclude_function_patterns, ) { foreach my $p (@$patType) { $p->[-1] = 0; @@ -2111,7 +2117,7 @@ sub compute_update \@lcovutil::include_file_patterns, \@lcovutil::file_subst_patterns, \@lcovutil::omit_line_patterns, - \@lcovutil::exclude_function_patterns + \@lcovutil::exclude_function_patterns, ) { my @count; foreach my $p (@$patType) { @@ -2171,7 +2177,7 @@ sub update_state \@lcovutil::include_file_patterns, \@lcovutil::file_subst_patterns, \@lcovutil::omit_line_patterns, - \@lcovutil::exclude_function_patterns + \@lcovutil::exclude_function_patterns, ) { my $count = shift; die("unexpected pattern count") unless $#$count == $#$patType; @@ -3339,6 +3345,22 @@ sub select return $self->call(@params); } +sub simplify +{ + my ($self, $func) = @_; + + my $name; + my $pipe = $self->pipe('simplify', $func); + die("broken 'simplify' callback") + unless ($pipe && + ($name = $pipe->next())); + + chomp($name); + $name =~ s/\r//; + lcovutil::info(1, " simplify: $name\n"); + return $name; +} + package JsonSupport; our $rc_json_module = 'auto'; diff --git a/man/genhtml.1 b/man/genhtml.1 index d0bd1582..42a8cff6 100644 --- a/man/genhtml.1 +++ b/man/genhtml.1 @@ -146,6 +146,9 @@ genhtml \- Generate HTML view from LCOV coverage data files .RB [ \-\-select\-script .IR script ] .br +.RB [ \-\-simplify\-script +.IR script ] +.br .RB [ \-\-checksum ] .br .RB [ \-\-fail\-under\-branches @@ -432,6 +435,8 @@ following options: .br .B \-\-select\-script .br +.B \-\-simplify\-script +.br .B \-\-version\-script .br .RE @@ -604,6 +609,23 @@ is the correct path to the indicated source file or if the source file is not found by the callback. .PP +.IP simplify\-script +$new_func_name = $callback_obj->simplify($orig_func_name) +.br +.br + +where +.I $new_func_name +is the function name which will appear in the function detail table and +.I $orig_func_name +is the (possibly demangled) function name found in the coverage DB. + +.br +Note that the modified name is only used in the "function detail" table +and does not modify information in the coveage DB. + +.PP + .RE .IP 2. 3 @@ -1818,6 +1840,28 @@ config file option. See man for details. .RE +.B \-\-simplify\-script +.I callback +.br +.RS +Use +.I callback +to shorten/simplify long demangled C++ function and template names to make the function detail table more compact and readable - for example, to +remove nested namespace names. + +Note that the simplifications affect only the display and not the actual names +stored in the coverage DB. In particular, the DB name (not the simplified name) +is the one used to match +.I \-\-erase\-function +patterns. + +This option is equivalent to the +.B simplify_script +config file option. See man +.B lcovrc(5) +for details +.RE + .BI "\-\-checksum " .RS Specify whether to compare stored tracefile checksum to checksum computed from the source code. @@ -2127,9 +2171,8 @@ Note that this option requires that you use a compiler version which is new enou .BI derive_function_end_line discussion in man .B lcovrc(5). - - .RE + .B \-\-substitute .I regexp_pattern .br @@ -3541,6 +3584,22 @@ feature can instead be realized by .RE .RE +Sample +.I \-\-simplify\-script +callback Perl module: +.RS + +.I \*[scriptdir]/simplify.pm +.RS +Sample script written as Perl module for use with +.B \-\-simplify\-script +that implements regular expression substitutions for function name simplification. +.br +.RE + +.RE +.RE + Sample .I \-\-version\-script callback Perl modules and scripts: diff --git a/man/lcovrc.5 b/man/lcovrc.5 index 68039979..dfdcac5d 100644 --- a/man/lcovrc.5 +++ b/man/lcovrc.5 @@ -3154,6 +3154,21 @@ This option is used by genhtml, lcov, and geninfo. .PP +.BR simplify_script " =" +.IR path_to_executable | parameter +.IP + +This option is equivalent to the genhtml +.I \-\-simplify\-script + option. +This option can be used multiple times in the lcovrc file to specify both a simplify script and additional options which are passed to the script. + +See man +.B genhtml(1) +for details. + +.PP + .BR substitute " =" .IR regexp .IP @@ -3162,7 +3177,8 @@ This option is equivalent to the \-\-substitute option to geninfo, lcov, and gen See the lcov man page for details.; This option can be used multiple times in the lcovrc file to specify multiple substitution patterns. -The patterns specified in the lcovrc file are appended to the list specified on the command line. +If patterns are specified on both the command line and in the lcovrc file, then +the command line patterns are used and the lcovrc patterns are dropped. .br This option is used by genhtml, lcov, and geninfo. diff --git a/scripts/simplify.pm b/scripts/simplify.pm new file mode 100644 index 00000000..3108cea5 --- /dev/null +++ b/scripts/simplify.pm @@ -0,0 +1,114 @@ +#!/usr/bin/end perl + +# Copyright (c) MediaTek USA Inc., 2025 +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or (at +# your option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, see +# . +# +# +# simplify.pm [--file pattern_file] [--re regexp] [--separator sep_char] +# +# This is a sample 'genhtml --simplify-script' callback - used to decide +# whether shorten the (possibly demangled) function names displayed in the +# 'function detail' tables. +# Note that the simplified names are ONLY used in the table - the +# coverage DB is not affected - so, for example '--erase-function' +# regexps must match the actual (possibly demangled) name of the function. +# +# --file: is the name of a file containing Perl regexpe, one per line +# +# --re: is a perl regexp or 'sep_char' separated list of regexps. +# +# --separator: is the character used to separate the list of regexpe. +# (',' is probably a poor choice as perl regexps often contain +# comma. + +package simplify; + +use strict; +use Getopt::Long qw(GetOptionsFromArray); +use File::Basename qw(dirname basename); +use lcovutil; + +our @ISA = qw(Exporter); +our @EXPORT_OK = qw(new); + +sub new +{ + my $class = shift; + my $script = shift; + my (@patterns, $file, $sep); + my @args = @_; + my $exe = basename($script ? $script : $0); + my $standalone = $script eq $0; + my $help; + if (!GetOptionsFromArray(\@_, + ("file:s" => \$file, + 'separator:s' => \$sep, + 're:s' => \@patterns, + 'help' => \$help)) || + $help || + (!$standalone && 0 != scalar(@_)) || + 0 == scalar(@args) || # expect at least one pattern + (@patterns && $file) || !(@patterns || $file) + ) { + print(STDERR <) { + chomp; + next if /^#/ || !$_; # skip comment and blank + push(@patterns, $_); + } + close(HANDLE) or die("unable to close pattern file handle: $!\n"); + } elsif (defined($sep)) { + @patterns = split($sep, join($sep, @patterns)); + } + + # verify that the patterns are valid... + lcovutil::verify_regexp_patterns($script, \@patterns); + + return bless \@patterns, $class; +} + +sub simplify +{ + my ($self, $name) = @_; + + foreach my $p (@$self) { + # sadly, no support for pre-compiled patterns + eval "\$name =~ $p ;"; # apply pattern that user provided... + # $@ should never match: we already checked pattern validity during + # initialization - above. Still: belt and braces. + die("invalid 'simplify' regexp '$p->[0]': $@") + if ($@); + } + return $name; +} + +1; diff --git a/tests/gendiffcov/errs/genError.pm b/tests/gendiffcov/errs/genError.pm index c776df42..fa176691 100644 --- a/tests/gendiffcov/errs/genError.pm +++ b/tests/gendiffcov/errs/genError.pm @@ -47,4 +47,9 @@ sub check_criteria die("die in check_criteria"); } +sub simplify +{ + die("die in simplify"); +} + 1; diff --git a/tests/gendiffcov/errs/msgtest.sh b/tests/gendiffcov/errs/msgtest.sh index 5fa1630e..a0a294dc 100755 --- a/tests/gendiffcov/errs/msgtest.sh +++ b/tests/gendiffcov/errs/msgtest.sh @@ -22,6 +22,7 @@ CRITERIA_SCRIPT=$SCRIPT_DIR/criteria.pm GITBLAME_SCRIPT=$SCRIPT_DIR/gitblame.pm GITVERSION_SCRIPT=$SCRIPT_DIR/gitversion.pm P4VERSION_SCRIPT=$SCRIPT_DIR/P4version.pm +SIMPLIFY_SCRIPT=$SCRIPT_DIR/simplify.pm if [ 1 == "$USE_GIT" ] ; then # this is git @@ -544,10 +545,65 @@ if [ 0 != $? ] ; then fi fi +# invalid regexp +for flag in --substitute ; do + echo genhtml $DIFFCOV_OPTS -o foo initial.info $flag 's#aBc#AbC' --ignore source --rc max_message_count=1 + $COVER $GENHTML_TOOL $DIFFCOV_OPTS -o foo initial.info $flag 's#aBc#AbC' --ignore source --rc max_message_count=1 2>&1 | tee invalid_regexp.log + if [ 0 == ${PIPESTATUS[0]} ] ; then + echo "ERROR: genhtml invalid $flag" + if [ 0 == $KEEP_GOING ] ; then + exit 1 + fi + fi + grep "Invalid regexp \"$flag " invalid_regexp.log + if [ 0 != $? ] ; then + echo "ERROR: missing regexp message for $flag" + if [ 0 == $KEEP_GOING ] ; then + exit 1 + fi + fi +done + +echo genhtml $DIFFCOV_OPTS -o foo initial.info --simplify $SIMPLIFY_SCRIPT,--re, 's#aBc#AbC' --ignore source --rc max_message_count=1 +$COVER $GENHTML_TOOL $DIFFCOV_OPTS -o foo initial.info --simplify $SIMPLIFY_SCRIPT,--re, 's#aBc#AbC' --ignore source --rc max_message_count=1 2>&1 | tee script_err.log +if [ 0 == ${PIPESTATUS[0]} ] ; then + echo "ERROR: genhtml invalid $flag" + if [ 0 == $KEEP_GOING ] ; then + exit 1 + fi +fi +for str in 'Invalid regexp' 'unable to create callback from module ' ; do + grep "$str" script_err.log + if [ 0 != $? ] ; then + echo "ERROR: missing err message for '$str'" + if [ 0 == $KEEP_GOING ] ; then + exit 1 + fi + fi +done + +# script errors +for args in '' ',--file,a,--re,s/a/b/' ',--file,a' ; do + echo genhtml $DIFFCOV_OPTS -o foo initial.info --simplify ${SIMPLIFY_SCRIPT}${args} --ignore source --rc max_message_count=1 + $COVER $GENHTML_TOOL $DIFFCOV_OPTS -o foo initial.info --simplify ${SIMPLIFY_SCRIPT}${args} --ignore source --rc max_message_count=1 2>&1 | tee invalid_callback.log + if [ 0 == ${PIPESTATUS[0]} ] ; then + echo "ERROR: genhtml invalid '$args'" + if [ 0 == $KEEP_GOING ] ; then + exit 1 + fi + fi + grep "unable to create callback from module " invalid_callback.log + if [ 0 != $? ] ; then + echo "ERROR: missing regexp message for '$args'" + if [ 0 == $KEEP_GOING ] ; then + exit 1 + fi + fi +done # callback error testing # die() in 'extract' callback: -echo lcov $LCOV_OPTS --summary version.info --filter line--version-script ./genError.pm +echo lcov $LCOV_OPTS --summary version.info --filter line --version-script ./genError.pm $COVER $LCOV_TOOL $LCOV_OPTS --summary version.info --filter line --version-script ./genError.pm 2>&1 | tee extract_err.log if [ 0 == ${PIPESTATUS[0]} ] ; then echo "ERROR: lcov extract passed by accident" @@ -599,7 +655,7 @@ if [ 0 != $? ] ; then fi fi -for callback in select annotate criteria ; do +for callback in select annotate criteria simplify ; do echo genhtml $DIFCOV_OPTS initial.info -o $callback --${callback}-script ./genError.pm $COVER $GENHTML_TOOL $DIFFCOV_OPTS initial.info -o $callback --${callback}-script ./genError.pm 2>&1 | tee ${callback}_err.log diff --git a/tests/lcov/demangle/demangle.sh b/tests/lcov/demangle/demangle.sh index 7bb26c63..cba6f045 100755 --- a/tests/lcov/demangle/demangle.sh +++ b/tests/lcov/demangle/demangle.sh @@ -5,7 +5,7 @@ source ../../common.tst LCOV_OPTS="--branch-coverage --no-external $PARALLEL $PROFILE" -rm -rf *.gcda *.gcno a.out *.info* *.txt* *.json dumper* testRC *.gcov *.gcov.* *.log +rm -rf *.gcda *.gcno a.out *.info* *.txt* *.json dumper* testRC *.gcov *.gcov.* *.log simplify clean_cover @@ -24,6 +24,7 @@ if [ 'x' == "x$GENHTML_TOOL" ] ; then GENINFO_TOOL=${LCOV_HOME}/bin/geninfo fi +SIMPLIFY_SCRIPT=${SCRIPT_DIR}/simplify.pm ${CXX} -std=c++1y --coverage demangle.cpp ./a.out 1 @@ -57,6 +58,35 @@ for k in FNA ; do fi done +# see if we can "simplify" the function names.. +for callback in './simplify.pl' "${SIMPLIFY_SCRIPT},--sep,;,--re,s/Animal::Animal/subst1/;s/Cat::Cat/subst2/;s/subst2/subst3/" "${SIMPLIFY_SCRIPT},--file,simplify.cmd" ; do + + $COVER $GENHTML_TOOL --branch $PARLLEL $PROFILE -o simplify demangle.info --flat --simplify $callback + if [ $? != 0 ] ; then + echo "genhtml --simplify '$callback' failed" + exit 1 + fi + grep subst1 simplify/demangle/demangle.cpp.func.html + if [ $? != 0 ] ; then + echo "didn't find subst1 pattern after $callback" + exit 1 + fi + grep Animal::Animal simplify/demangle/demangle.cpp.func.html + if [ $? == 0 ] ; then + echo "found pattern that was supposed to be substituted after $callback" + exit 1 + fi + grep subst3 simplify/demangle/demangle.cpp.func.html + if [ $? != 0 ] ; then + echo "didn't find subst3 pattern after $callback" + exit 1 + fi + grep subst2 simplify/demangle/demangle.cpp.func.html + if [ $? == 0 ] ; then + echo "iteratative substitute failed after $callback " + exit 1 + fi +done $COVER $LCOV_TOOL $LCOV_OPTS --capture --filter branch --directory . -o vanilla.info diff --git a/tests/lcov/demangle/simplify.cmd b/tests/lcov/demangle/simplify.cmd new file mode 100644 index 00000000..8a628285 --- /dev/null +++ b/tests/lcov/demangle/simplify.cmd @@ -0,0 +1,6 @@ +# test the 'simplify.pm --file ...' option + +s/Animal::Animal/subst1/ +s/Cat::Cat/subst2/ +s/subst2/subst3/ + diff --git a/tests/lcov/demangle/simplify.pl b/tests/lcov/demangle/simplify.pl new file mode 100755 index 00000000..992dcde8 --- /dev/null +++ b/tests/lcov/demangle/simplify.pl @@ -0,0 +1,11 @@ +#!/usr/bin/env perl +use strict; + +my $name = shift; +$name =~ s/Animal::Animal/subst1/; +$name =~ s/Cat::Cat/subst2/; +$name =~ s/subst2/subst3/; + +print $name; +exit 0; + diff --git a/tests/lcov/errs/errs.sh b/tests/lcov/errs/errs.sh index 5d1c2fbd..16e0831a 100755 --- a/tests/lcov/errs/errs.sh +++ b/tests/lcov/errs/errs.sh @@ -156,7 +156,7 @@ for f in exceptionBranch ; do fi fi - echo lcov $LCOV_OPTS -a ${f}1.info -a ${f}2.info --ignroe mismatch -o ${f}2.log + echo lcov $LCOV_OPTS -a ${f}1.info -a ${f}2.info --ignore mismatch -o ${f}2.log $COVER $LCOV_TOOL $LCOV_OPTS -a ${f}1.info -a ${f}2.info --ignore mismatch -o $f.log if [ 0 != ${PIPESTATUS[0]} ] ; then