Skip to content

Improved baseline/current/diff error checking. #397

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Mar 28, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
136 changes: 67 additions & 69 deletions bin/genhtml
Original file line number Diff line number Diff line change
Expand Up @@ -3479,7 +3479,7 @@ sub new
{
my $class = shift;
my $self = [{}, # linemap
{}, # filemap
{}, # filemap: new_filename->old_filename
{}, # baseline: filename -> baseline lineno -> text
undef, # diff filename
[{}, {}], # def location
Expand All @@ -3497,10 +3497,11 @@ sub load
my ($self, $path, $info, $buildDirs) = @_;
$self->_read_udiff($path);

# find list of soft links in [buildDirs] which may point to files in $info
# we need to keep all the aliases as there may be files in baseline
# which are not in current
if (@$buildDirs) {
# find list of soft links in [buildDirs] which point to files in $info
my @stack = @$buildDirs;
my %alias;
while (@stack) {
my $dir = pop(@stack);
die("unexpected non-directory '$dir'") unless -d $dir;
Expand All @@ -3515,7 +3516,10 @@ sub load
push(@stack, $path);
} elsif (-l $path) {
my $l = Cwd::realpath($path);
$alias{$path} = $l if (-f $l);
next if (!-e $l || TraceFile::skipCurrentFile($l));
# may need to turn $l into relative path??
$self->[ALIASES]->{$path} = $l if (-f $l);
#lcovutil::info("add alias '$path' -> '$l'\n");
# really, this should be a file...
die("unexpected soft link $path to directory")
unless -f $l;
Expand All @@ -3524,17 +3528,6 @@ sub load
}
closedir($dh);
}
# now look through list of filenames in the current .info file, and see
# if any match the soft links found above
foreach my $f ($info->files()) {
my $path = $f;
$path = File::Spec->catfile($main::cwd, $f)
unless File::Spec->file_name_is_absolute($f);
if (exists($alias{$path})) {
#lcovutil::info("found alias $alias{$path} of $f\n");
$self->[ALIASES]->{$path} = $alias{$path};
}
}
}
return $self;
}
Expand Down Expand Up @@ -3772,20 +3765,23 @@ sub check_path_consistency
# That is: files whose version differs should appear in the diff data
$self->check_version_match($baseline, $current);

my %diffMap;
my %diffBaseMap;
my %diffMap; # current_filename -> where_used
my %diffBaseMap; # current_directory -> []
# for every 'current' filename in the udiff file
foreach my $f ($self->files()) {
$diffMap{$f} = 0;
$diffMap{$f} = 0; # this file not used in baseline or current (yet)
my $b = File::Basename::basename($f);
$diffBaseMap{$b} = [[], {}]
unless exists($diffBaseMap{$b});
push(@{$diffBaseMap{$b}->[0]}, $f);
}
# foreach unchanged file in udiff data
foreach my $f (keys %{$self->[UNCHANGED]}) {
# unchanged in baseline and current
$diffMap{$f} = 3;
}
my %missed;
# for each file in 'current' info:
foreach my $curr ($current->files()) {
my $b = File::Basename::basename($curr);
if ($self->containsFile($curr)) {
Expand All @@ -3796,10 +3792,12 @@ sub check_path_consistency
$diffBaseMap{$b}->[1]->{$alias} = 0
unless exists($diffBaseMap{$b}->[1]->{$alias});
++$diffBaseMap{$b}->[1]->{$alias};
} else {
} elsif (!exists($self->[UNCHANGED]->{$self->findName($curr)})) {
$missed{$curr} = 1; # in current but not in diff
#lcovutil::info("missed curr: $curr\n");
}
}
# for each file in 'baseline' info:
foreach my $base ($baseline->files()) {
my $b = File::Basename::basename($base);
if ($self->containsFile($base)) {
Expand All @@ -3810,8 +3808,9 @@ sub check_path_consistency
$diffBaseMap{$b}->[1]->{$alias} = 0
unless exists($diffBaseMap{$b}->[1]->{$alias});
++$diffBaseMap{$b}->[1]->{$alias};
} else {
} elsif (!exists($self->[UNCHANGED]->{$self->findName($base)})) {
# in baseline but not in diff
#lcovutil::info("missed base: $base\n");
if (exists($missed{$base})) {
$missed{$base} |= 2;
} else {
Expand All @@ -3822,45 +3821,46 @@ sub check_path_consistency
my $ok = 1;
foreach my $f (sort keys(%missed)) {
my $b = File::Basename::basename($f);
if (exists($diffBaseMap{$b})) {
# this basename is in the diff file and didn't match any other
# trace filename entry (i.e., same filename in more than one
# source code directory) - then warn about possible pathname issue
my ($diffFiles, $sourceFiles) = @{$diffBaseMap{$b}};
# find the files which appear in the 'diff' list which have the
# same basename and were not matched - those might be candidates
my @unused;
for my $d (@$diffFiles) {
# my $location = $self->[DIFF_FILENAME] . ':' . $self->[LOCATION]->[NEW]->{$d};
push(@unused, $d)
unless exists($sourceFiles->{$d});
}
if (scalar(@unused)) {
my $type;

# my $baseData = $baseline->data($f);
# my $baseLocation = join(":", ${$baseData->location()});
# my $currData = $current->data($f);
# my $currLocation = join(":", ${$currData->location()});

if (2 == $missed{$f}) {
$type = "baseline";
} elsif (1 == $missed{$f}) {
$type = "current";
} else {
$type = "both baseline and current";
}
my $single = 1 == scalar(@unused);
# @todo could print line numbers in baseline, current .info files and
# in diff file ..
if (lcovutil::warn_once($lcovutil::ERROR_MISMATCH, $f)) {
my $suffix =
$main::elide_path_mismatch ? ' (elided)' :
lcovutil::explain_once(
'elide-path-mismatch',
' Perhaps see "--elide-path-mismatch", "--substitute" and "--build-directory" options in \'man '
. $lcovutil::tool_name . '\'');
lcovutil::ignorable_warning(
next unless exists($diffBaseMap{$b});

# this basename is in the diff file and didn't match any other
# trace filename entry (i.e., same filename in more than one
# source code directory) - then warn about possible pathname issue
my ($diffFiles, $sourceFiles) = @{$diffBaseMap{$b}};
# find the files which appear in the 'diff' list which have the
# same basename and were not matched - those might be candidates
my @unused;
for my $d (@$diffFiles) {
# my $location = $self->[DIFF_FILENAME] . ':' . $self->[LOCATION]->[NEW]->{$d};
push(@unused, $d)
unless exists($sourceFiles->{$d});
}
next unless @unused;

# my $baseData = $baseline->data($f);
# my $baseLocation = join(":", ${$baseData->location()});
# my $currData = $current->data($f);
# my $currLocation = join(":", ${$currData->location()});

my $type;
if (2 == $missed{$f}) {
$type = "baseline";
} elsif (1 == $missed{$f}) {
$type = "current";
} else {
$type = "both baseline and current";
}
my $single = 1 == scalar(@unused);
# @todo could print line numbers in baseline, current .info files and
# in diff file ..
if (lcovutil::warn_once($lcovutil::ERROR_MISMATCH, $f)) {
my $suffix =
$main::elide_path_mismatch ? ' (elided)' :
lcovutil::explain_once(
'elide-path-mismatch',
' Perhaps see "--elide-path-mismatch", "--substitute" and "--build-directory" options in \'man '
. $lcovutil::tool_name . '\'');
lcovutil::ignorable_warning(
$lcovutil::ERROR_MISMATCH,
"source file '$f' (in $type .info file" .
($missed{$f} == 3 ? "s" : "") .
Expand All @@ -3874,16 +3874,14 @@ sub check_path_consistency
($single ? " " : "\n\t") .
'Possible pathname mismatch?' .
$suffix);
}
if ($main::elide_path_mismatch &&
$missed{$f} == 3 &&
$single) {
$self->[FILEMAP]->{$f} = $f;
$self->[LINEMAP]->{$f} = $self->[LINEMAP]->{$unused[0]};
} else {
$ok = 0;
}
}
}
if ($main::elide_path_mismatch &&
$missed{$f} == 3 &&
$single) {
$self->[FILEMAP]->{$f} = $f;
$self->[LINEMAP]->{$f} = $self->[LINEMAP]->{$unused[0]};
} else {
$ok = 0;
}
}
return $ok;
Expand Down
24 changes: 14 additions & 10 deletions scripts/gitdiff
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

use Getopt::Long;
use strict;
use Cwd /realpath/;

my $verbose = 0;

Expand Down Expand Up @@ -39,18 +40,20 @@ my @include_patterns;
my $suppress_unchanged;
my $prefix = '';
my $ignore_whitespace;
my $repo = '.'; # cwd

if (!GetOptions("exclude=s" => \@exclude_patterns,
"include=s" => \@include_patterns,
'no-unchanged' => \$suppress_unchanged,
'prefix=s' => \$prefix,
'b|blank' => \$ignore_whitespace,
'repo=s' => \$repo,
'verbose+' => \$verbose) ||
(2 != scalar(@ARGV) &&
3 != scalar(@ARGV))
) {
print(STDERR
"usage: [(--exclude|include) regexp[,regexp]] [-b] [dir] base_changelist current_changelist\n'exclude' wins if both exclude and include would match.\n"
"usage: [(--exclude|include) regexp[,regexp]] [--repo repo] [-b] [dir] base_changelist current_changelist\n'exclude' wins if both exclude and include would match.\n"
);
exit(1);
}
Expand All @@ -71,15 +74,16 @@ if ($verbose) {
}

$prefix .= '/' if $prefix;
my $cmd;
if (3 == scalar(@ARGV)) {
my $dir = shift @ARGV;
push(@include_patterns, "$dir");
}
my $base_sha = shift @ARGV;
my $current_sha = shift @ARGV;

$cmd = "git diff $ignore_whitespace $base_sha $current_sha";
$repo = Cwd::realpath($repo);

my $cmd = "cd $repo ; git diff $ignore_whitespace $base_sha $current_sha";

open(HANDLE, "-|", $cmd) or
die("failed to exec git diff: $!");
Expand All @@ -104,8 +108,10 @@ while (<HANDLE>) {
$includeCurrentFile =
(include_me($fileA, \@include_patterns, \@exclude_patterns) ||
include_me($fileB, \@include_patterns, \@exclude_patterns));
$allFiles{$fileB} = $fileA
if ($includeCurrentFile);
if ($includeCurrentFile) {
$allFiles{$fileB} = $fileA;
$line =~ s/($fileA|$fileB)/$1/g;
}
}

printf("%s\n", $line)
Expand All @@ -119,19 +125,17 @@ if (0 != $?) {

exit 0 if defined($suppress_unchanged);

my $p = `git rev-parse --show-prefix`;
chomp $p;

# now find the list of files in the current SHA - we can process that
# to find the list of all current files which were unchanged since the
# baseline SHA
die("failed to exec git ls-tree")
unless (open(HANDLE, "-|", "git ls-tree -r --name-only $current_sha"));
unless (
open(HANDLE, "-|", "cd $repo ; git ls-tree -r --name-only $current_sha"));

while (<HANDLE>) {
chomp($_);
s/\r//g;
my $filename = $p . $_;
my $filename = $repo . '/' . $_;
my $path = $prefix . $filename;
if (!exists($allFiles{$path}) &&
include_me($path, \@include_patterns, \@exclude_patterns)) {
Expand Down