#!/usr/bin/perl -w
sub
help {
print
<<EOF;
status_upd -fqd [ 1.32 | path ]
OPTIONS:
-q quiet
-f fail only
-t todo only
-d no unify dumps
-a all, do not skip too old logs
-s sort by test (ignored)
-u update STATUS (ignored)
-h help
EOF
exit
;
}
my
$logs
=
"log.test-*-5.*"
;
my
$dir
=
"."
;
my
$STATUS
=
"./STATUS"
;
chdir
".."
if
! -d
"t"
and -d
"../t"
;
chdir
"../.."
if
! -d
"t"
and -d
"../../t"
;
my
(
$sortbytest
,
$update
,
$quiet
,
$failonly
,
$todoonly
,
$noskip
,
$nodump
,
$help
);
Getopt::Long::Configure (
"bundling"
);
GetOptions (
"sort|s"
=> \
$sortbytest
,
"update|u"
=> \
$update
,
"quiet|q"
=> \
$quiet
,
"fail|f"
=> \
$failonly
,
"todo|pass|t"
=> \
$todoonly
,
"all|a"
=> \
$noskip
,
"dump|d"
=> \
$nodump
,
"help|h"
=> \
$help
);
help
if
$help
;
for
(
@ARGV
) {
-d
"t/reports/$_"
and
$dir
=
"t/reports/$_"
;
-d
"$_"
and
$dir
=
$_
;
}
sub
status {
my
$h
=
shift
;
my
@g
=
@_
;
my
$s
=
""
;
my
%h
=
%$h
;
my
$prefix
=
''
;
my
$oldprefix
=
''
;
my
$skipped
= 0;
while
(
@g
) {
if
(
$g
[0] =~ /^--/) {
$oldprefix
=
$prefix
if
$prefix
;
$prefix
=
''
;
shift
@g
;
next
;
}
my
$file
=
shift
@g
;
my
$failed
=
shift
@g
;
my
$ctime
= 0;
unless
(
$prefix
) {
my
(
$f
) =
$file
=~ m{(
log
.test-.*?)-t/};
(
$prefix
) =
$file
=~ m{
log
.test-(.*?)-t/};
if
(
$prefix
and
$oldprefix
ne
$prefix
) {
$ctime
= -f
$f
?
sprintf
(
"%0.3f"
, -C
$f
) : 0;
print
"\n$prefix: age=$ctime"
unless
$quiet
;
if
(
$ctime
> 1.5 and !
$noskip
) {
$skipped
= 1;
print
" skipped: too old"
unless
$quiet
;
$s
.=
"\n$prefix:\n"
unless
$quiet
;
}
else
{
$s
.=
"\n$prefix:\n"
;
$skipped
= 0;
}
print
"\n"
unless
$quiet
;
}
}
next
unless
$prefix
;
next
unless
$file
;
chomp
$file
;
(
$file
) =
$file
=~ m{
log
.test-.*-(t/[\w\.]+\s?)};
next
unless
$file
;
$file
=~ s{\s*$}{};
$file
=~ s{^\s*}{};
$failed
=~ s{^.+(Failed tests?:?)}{$1}i;
$failed
=~ s{^.+TODO passed:}{TODO passed:};
chomp
$failed
;
$failed
=~ s/(\d)-(\d)/$1..$2/g;
my
$f
=
$failed
;
$f
=~ s{^Failed tests?:?\s*(.+)$}{$1}i;
$f
=~ s{^TODO passed:\s*}{};
$f
=~ s/ //g;
my
$c
=
"$file\t"
if
$failed
;
$c
.=
"\t"
if
length
(
$file
) < 8;
$c
.=
"$failed\n"
;
$h
{
$prefix
}->{
$file
} =
$f
;
next
if
$skipped
;
print
"$c"
unless
$quiet
;
$s
.=
$c
;
}
print
"\n"
unless
$quiet
;
[
$s
, \
%h
];
}
sub
platform_version_split {
local
$_
=
shift
;
my
(
$p
,
$v
,
$f
) = m/^(.+)-(5\.[\d\.]+)([-dnt]+)?$/;
$f
=~ s/^-//
if
$f
;
$v
=~ s/(\d\.\d+)\.\d+/$1/
if
$v
;
return
(
$p
,
$v
,
$f
);
}
sub
h_size($) {
scalar
keys
%{
$_
[0]} }
sub
split_tests($) {
my
$t
=
shift
;
map
{
if
(/(\d+)\.\.(\d+)/) {
($1 .. $2)
}
else
{
$_
}
}
split
/,\s*/,
$t
;
}
sub
in_both ($$) {
my
%h1
=
map
{
$_
=> 1 } @{
$_
[0]};
my
%h2
=
map
{
$_
=> 1 } @{
$_
[1]};
for
(
keys
%h1
) {
my
$e
=
$h1
{
$_
};
undef
$h1
{
$_
}
unless
$h2
{
$e
};
}
sort
keys
%h1
;
}
sub
all_common {
my
$h
=
shift
;
my
$result
=
shift
;
my
(
%tests
);
if
(
@_
== 1) {
delete
$h
->{
$_
[0]}->{
''
};
return
$h
->{
$_
[0]};
}
my
@p
=
sort
{ h_size(
$h
->{
$a
}) <=> h_size(
$h
->{
$b
}) }
@_
;
my
$pivot
=
$p
[0];
my
$pivotset
= Set::Object->new(
keys
%{
$h
->{
$pivot
}});
for
(
$pivotset
->members) {
if
(
my
$k
=
$h
->{
$pivot
}->{
$_
}) {
$tests
{
$_
} = Set::Object->new(split_tests(
$k
));
}
}
for
my
$p
(
@_
) {
my
$c
=
$pivotset
* Set::Object->new(
keys
%{
$h
->{
$p
}});
for
(
$c
->members) {
if
(
$_
and
exists
$tests
{
$_
}) {
$result
->{
$_
} =
$result
->{
$_
} ?
$tests
{
$_
} *
$result
->{
$_
} :
$tests
{
$_
};
$result
->{
$_
} =
$result
->{
$_
} * Set::Object->new( split_tests(
$h
->{
$p
}->{
$_
}) )
if
$result
->{
$_
}->members;
$result
->{
$_
} =
$result
->{
$_
}->members;
}
delete
$result
->{
$_
}
unless
$result
->{
$_
};
}
}
delete
$result
->{
''
};
return
$result
;
}
sub
unify_results {
my
$h
=
shift
;
my
$name
=
shift
;
my
@platforms
=
keys
%$h
;
my
$result
= all_common(
$h
, {},
@platforms
);
if
(
%$result
) {
print
Data::Dumper->Dump([
$result
],[
"common_$name"
]);
for
my
$p
(
@platforms
) {
for
(
keys
%{
$h
->{
$p
}}) {
if
(
$result
->{
$_
} and
$result
->{
$_
} ne
$h
->{
$p
}->{
$_
}) {
my
$both
= Set::Object->new(split_tests
$h
->{
$p
}->{
$_
})
- Set::Object->new(
$result
->{
$_
});
if
(
$both
->members) {
$h
->{
$p
}->{
$_
} =
join
(
","
,
$both
->members);
}
else
{
undef
$h
->{
$p
}->{
$_
};
}
}
}
}
}
my
$h_sav
=
$h
;
my
%versions
;
for
(
@platforms
) {
my
(
$p
,
$v
,
$f
) = platform_version_split(
$_
);
push
@{
$versions
{
$v
}}, (
$_
)
if
$v
;
}
for
my
$v
(
sort
keys
%versions
) {
if
(
$v
!~ /^5\.(7|9|11)$/) {
my
$v1
= all_common(
$h
,
$result
, @{
$versions
{
$v
}});
if
(
%$v1
) {
print
Data::Dumper->Dump([
$v1
],[
"v$v $name"
]);
}
}
}
$h
=
$h_sav
;
my
%feat
;
for
(
@platforms
) {
my
(
$p
,
$v
,
$f
) = platform_version_split(
$_
);
$f
=
""
unless
$f
;
push
@{
$feat
{
$f
}}, (
$_
);
}
for
my
$f
(
sort
keys
%feat
) {
my
$f1
= all_common(
$h
,
$result
, @{
$feat
{
$f
}});
if
(
%$f1
) {
print
Data::Dumper->Dump([
$f1
],[
"feature $f $name"
]);
}
}
}
my
$dlogs
=
$dir
eq
'.'
?
"$logs"
:
"$dir/$logs"
;
my
$cmd
=
'grep -a -i "tests" '
.
$dlogs
.
" | grep -v t/CORE"
;
my
%h
;
my
%h_sav
=
%h
;
if
(
my
@g
= `
$cmd
`) {
for
my
$file
(
@g
) {
my
$prefix
;
if
((
$prefix
) =
$file
=~ m{
log
.test-(.*?):}) {
(
$file
) =
$file
=~ m/(
log
.test-.*?):/;
my
$ctime
= -f
$file
?
sprintf
(
"%0.3f"
, -C
$file
) : 0;
if
(
$ctime
< 1.5 or
$noskip
) {
$h
{
$prefix
}->{
''
} =
''
;
}
}
}
}
else
{
die
"no $logs found\n"
;
}
if
(!
$todoonly
) {
my
$cmd
=
'grep -a -B1 -i "Failed test" '
.
$dlogs
.
" | grep -v t/CORE"
;
print
"$cmd\n"
unless
$quiet
;
if
(
my
@g
= `
$cmd
`) {
my
$failed
= status(\
%h
,
@g
);
print
$failed
->[0]
if
$nodump
and
$quiet
;
my
$failedu
= unify_results(
$failed
->[1],
"fail"
)
unless
$nodump
;
}
}
%h
=
%h_sav
;
if
(!
$failonly
) {
my
$cmd
=
'grep -a -B1 -i "TODO passed" '
.
$dlogs
.
" | grep -v t/CORE"
;
print
"\n$cmd\n"
unless
$quiet
;
if
(
my
@g
= `
$cmd
`) {
my
$todo
= status(\
%h
,
@g
);
print
$todo
->[0]
if
$nodump
and
$quiet
;
my
$todou
= unify_results(
$todo
->[1],
"todo_pass"
)
unless
$nodump
;
}
}
if
(
$update
) {
die
"file not found $STATUS\n"
unless
-e
$STATUS
;
die
"-u update STATUS not yet implemented\n"
;
}