citrun

watch C/C++ source code execute
Log | Files | Refs | LICENSE

commit 74d8861cced9ca583039438354e7e9665f99129d
parent 77c51f8bd803b8cde13f2cee3217a32d5d88c684
Author: Kyle Milz <kyle@0x30.net>
Date:   Sun, 26 Jun 2016 21:14:34 -0600

Test/Viewer: rework to be more sane

- add test ok()'s to functions in this class
- rename some things to match runtime
- add some helpers for test verification and use them

Diffstat:
MTest/Viewer.pm | 86+++++++++++++++++++++++++++++++++++++++++++++++++------------------------------
Mt/runtime_counters_increase.t | 31++++++++++++++-----------------
Mt/runtime_metadata.t | 26++++----------------------
Mt/runtime_reconnect.t | 14+++-----------
Mt/runtime_sanity.t | 43+++++++++++++++++--------------------------
5 files changed, 91 insertions(+), 109 deletions(-)

diff --git a/Test/Viewer.pm b/Test/Viewer.pm @@ -2,7 +2,8 @@ package Test::Viewer; use strict; use IO::Socket::UNIX; -use Test; +use List::MoreUtils qw( each_array ); +use Test::More; my $viewer_socket_name = "citrun-test.socket"; @@ -25,64 +26,64 @@ sub new { sub accept { my ($self) = @_; + # Accept a new connection on the listening viewer socket. my $socket = $self->{viewer_socket}; - $self->{client_socket} = $socket->accept(); -} -sub get_metadata { - my ($self) = @_; - my $client = $self->{client_socket}; + my $client = $socket->accept(); + $self->{client_socket} = $client; - # First thing sent is total number of translation units + # Read the total number of instrumented translation units. my $buf = read_all($client, 8); - my $num_tus = unpack("Q", $buf); + $self->{num_tus} = unpack("Q", $buf); - # Next is the 3 4 byte pid_t's + # Read three 4 byte pid_t's $buf = read_all($client, 12); - my ($pid, $ppid, $pgrp) = unpack("L3", $buf); - - my $runtime_metadata = { - num_tus => $num_tus, - pid => $pid, - ppid => $ppid, - pgrp => $pgrp, - }; - - my @tus_ordered; - my %tus; - for (1..$num_tus) { + ($self->{pid}, $self->{ppid}, $self->{pgrp}) = unpack("L3", $buf); + + # Always sanity check these. + cmp_ok( $self->{pid}, ">", 1, "pid lower bound check" ); + cmp_ok( $self->{pid}, "<", 100000, "pid upper bound check" ); + cmp_ok( $self->{ppid}, ">", 1, "ppid lower bound check" ); + cmp_ok( $self->{ppid}, "<", 100000, "ppid upper bound check" ); + cmp_ok( $self->{pgrp}, ">", 1, "pgrp lower bound check" ); + cmp_ok( $self->{pgrp}, "<", 100000, "pgrp upper bound check" ); + + # Read the static translation unit information. + my @tus; + for (1..$self->{num_tus}) { + # Size of absolute file path. my $buf = read_all($client, 8); my $file_name_sz = unpack("Q", $buf); + # Absolute file path. my $file_name = read_all($client, $file_name_sz); + # Total number of lines in primary source file. $buf = read_all($client, 4); my $num_lines = unpack("L", $buf); + # Number of instrumentation sites in primary source file. $buf = read_all($client, 4); my $inst_sites = unpack("L", $buf); - push @tus_ordered, $file_name; - $tus{$file_name} = { lines => $num_lines, inst_sites => $inst_sites }; + # Keep this in order so it's easy to fetch dynamic data. + push @tus, [ $file_name, $num_lines, $inst_sites ]; } - $runtime_metadata->{tus_ordered} = \@tus_ordered; - $runtime_metadata->{tus} = \%tus; - - return $runtime_metadata; + $self->{tus} = \@tus; } -sub get_execution_data { - my ($self, $tus_ordered, $tus) = @_; - my $client = $self->{client_socket}; +sub get_dynamic_data { + my ($self) = @_; + my $client = $self->{client_socket}; my %data; - for my $file_name (@$tus_ordered) { - my $num_lines = $tus->{$file_name}->{lines}; + for my $tu (@{ $self->{tus} }) { + my $num_lines = $tu->[1]; my $buf = read_all($client, 8 * $num_lines); my @data_tmp = unpack("Q$num_lines", $buf); - $data{$file_name} = \@data_tmp; + $data{$tu->[0]} = \@data_tmp; } # Send an 'ok' response @@ -91,6 +92,25 @@ sub get_execution_data { return \%data; } +sub cmp_static_data { + my ($self, $known_good) = @_; + + # Sort these alphabetically by file name (field 0). + my @sorted_tus = sort { $a->[0] cmp $b->[0] } @{ $self->{tus} }; + + # Walk two lists at the same time + # http://stackoverflow.com/questions/822563/how-can-i-iterate-over-multiple-lists-at-the-same-time-in-perl + my $it = each_array( @$known_good, @sorted_tus ); + while ( my ($x, $y) = $it->() ) { + like( $y->[0], qr/.*$x->[0]/, "$x->[0]: filename check" ); + is ( $y->[1], $x->[1], "$x->[0]: total lines check" ); + + # Check instrumented sites ranges + cmp_ok ( $y->[2], ">", $x->[2] - 5, "$x->[0]: instr sites check lower" ); + cmp_ok ( $y->[2], "<", $x->[2] + 5, "$x->[0]: instr sites check upper" ); + } +} + sub read_all { my ($sock, $bytes_total) = @_; diff --git a/t/runtime_counters_increase.t b/t/runtime_counters_increase.t @@ -1,6 +1,7 @@ use strict; -use Test::More tests => 14; +use Data::Dumper; +use Test::More tests => 25; use Test::Differences; use Test::Project; @@ -40,32 +41,28 @@ main(int argc, char *argv[]) } EOF -# Compile the above inefficient program and have it compute the input 40, which -# takes a few seconds +# Compile above inefficient program and let it run for a few seconds. $project->compile(); $project->run(45); -# Accept the runtime's connection +# Accept the runtime connection and check a few things. $viewer->accept(); -my $runtime_metadata = $viewer->get_metadata(); -my $tus_ordered = $runtime_metadata->{tus_ordered}; -my $tus = $runtime_metadata->{tus}; +is( $viewer->{num_tus}, 1, "num tus check" ); +$viewer->cmp_static_data([ [ "source_0.c", 28, 18 ] ]); -my ($file_name) = keys %$tus; -like ($file_name, qr/.*source_0\.c/, "runtime filename check"); -is( $tus->{$file_name}->{lines}, 28, "runtime lines count" ); +my $data = $viewer->get_dynamic_data(); +ok( keys %$data == 1, "single dynamic data key" ); +my ($exec_lines1) = values %$data; -my $data = $viewer->get_execution_data($tus_ordered, $tus); -my @exec_lines1 = @{ $data->{$file_name} }; - -my $data = $viewer->get_execution_data($tus_ordered, $tus); -my @exec_lines2 = @{ $data->{$file_name} }; +my $data = $viewer->get_dynamic_data(); +ok( keys %$data == 1, "single dynamic data key" ); +my ($exec_lines2) = values %$data; # Only lines 8 - 12 in the source code above are executing for (8..12) { - cmp_ok( $exec_lines1[$_], ">", 0, "line $_ executed nonzero times" ); + cmp_ok( $exec_lines1->[$_], ">", 0, "line $_ executed nonzero times" ); # Make sure the second time we queried the execution counts they were higher - cmp_ok( $exec_lines2[$_], ">=", $exec_lines1[$_], "line $_ after > before" ); + cmp_ok( $exec_lines2->[$_], ">=", $exec_lines1->[$_], "line $_ after > before" ); } $project->kill(); diff --git a/t/runtime_metadata.t b/t/runtime_metadata.t @@ -1,6 +1,6 @@ use strict; -use Test::More tests => 11; +use Test::More tests => 13; use Test::Project; use Test::Viewer; @@ -22,28 +22,10 @@ $project->compile(); $project->run(); $viewer->accept(); +is( $viewer->{num_tus}, 1, "translation unit count" ); -# Request and check metadata first -my $runtime_metadata = $viewer->get_metadata(); - -my $pid = $runtime_metadata->{pid}; -my $ppid = $runtime_metadata->{ppid}; -my $pgrp = $runtime_metadata->{pgrp}; - -cmp_ok( $pid, ">", 1, "pid is positive" ); -cmp_ok( $ppid, ">", 1, "ppid is positive" ); -cmp_ok( $pgrp, ">", 1, "pgrp is positive" ); - -cmp_ok( $pid, "<", 100 * 1000, "pid is a reasonable value" ); -cmp_ok( $ppid, "<", 100 * 1000, "ppid is a reasonable value" ); -cmp_ok( $pgrp, "<", 100 * 1000, "pgrp is a reasonable value" ); - -my $tus = $runtime_metadata->{tus}; -is ( scalar(keys %$tus), 1, "translation unit count" ); - -my ($file_name) = keys %$tus; -like( $file_name, qr/.*source_0.c/, "filename check" ); -is( $tus->{$file_name}->{lines}, 8, "line count check" ); +my @known_good = [ [ "source_0.c", 8, 2 ] ]; +$viewer->cmp_static_data(@known_good); $project->kill(); my ($ret, $err) = $project->wait(); diff --git a/t/runtime_reconnect.t b/t/runtime_reconnect.t @@ -1,6 +1,6 @@ use strict; -use Test::More tests => 5; +use Test::More tests => 13; use Test::Project; use Test::Viewer; @@ -24,16 +24,8 @@ sleep(1); my $viewer = Test::Viewer->new(); $viewer->accept(); - -# Request and check metadata first -my $runtime_metadata = $viewer->get_metadata(); - -my $tus = $runtime_metadata->{tus}; -is ( scalar(keys %$tus), 1, "translation unit count" ); - -my ($file_name) = keys %$tus; -like( $file_name, qr/.*source_0.c/, "filename check" ); -is( $tus->{$file_name}->{lines}, 7, "line count check" ); +is( $viewer->{num_tus}, 1, "num tus check" ); +$viewer->cmp_static_data([ [ "source_0.c", 7, 2 ] ]); $project->kill(); my ($ret, $err) = $project->wait(); diff --git a/t/runtime_sanity.t b/t/runtime_sanity.t @@ -1,7 +1,7 @@ use strict; use Data::Dumper; -use Test::More tests => 50; +use Test::More tests => 58; use Test::Differences; use Test::Project; @@ -61,33 +61,24 @@ $project->compile(); $project->run(45); $viewer->accept(); +is( $viewer->{num_tus}, 3, "translation unit count" ); -# Request and check metadata first -my $runtime_metadata = $viewer->get_metadata(); -my $tus_ordered = $runtime_metadata->{tus_ordered}; -my $tus = $runtime_metadata->{tus}; +# Check static data. +my @known_good = [ + # filename lines inst sites + [ "source_0.c", 20, 9 ], + [ "source_1.c", 11, 7 ], + [ "source_2.c", 9, 6 ], +]; +$viewer->cmp_static_data(@known_good); -my ($fn0, $fn1, $fn2) = sort keys %$tus; -like( $fn0, qr/.*source_0.c/, "runtime filename check 0" ); -is( $tus->{$fn0}->{lines}, 20, "runtime line count check 0" ); -my $sites0 = $tus->{$fn0}->{inst_sites}; -cmp_ok( $sites0, ">=", 6, "site count 0 lower" ); -cmp_ok( $sites0, "<=", 11, "site count 0 upper" ); +# Request and check execution data. +my $data = $viewer->get_dynamic_data(); -like( $fn1, qr/.*source_1.c/, "runtime filename check 1" ); -is( $tus->{$fn1}->{lines}, 11, "runtime line count check 1" ); -is( $tus->{$fn1}->{inst_sites}, 7, "instrumented site count 1" ); +# The nodes can be in any order. +my ($s0, $s1, $s2) = sort keys %$data; -like( $fn2, qr/.*source_2.c/, "runtime filename check 2" ); -is( $tus->{$fn2}->{lines}, 9, "runtime line count check 2" ); -my $sites2 = $tus->{$fn2}->{inst_sites}; -cmp_ok( $sites2, ">=", 5, "site count 2 lower" ); -cmp_ok( $sites2, "<=", 6, "site count 2 upper" ); - -# Request and check execution data -my $data = $viewer->get_execution_data($tus_ordered, $tus); - -my @lines = @{ $data->{$fn0} }; +my @lines = @{ $data->{$s0} }; is( $lines[$_], 0, "src 0 line $_ check" ) for (1..11); is( $lines[12], 1, "src 0 line 14 check" ); is( $lines[$_], 0, "src 0 line $_ check" ) for (13..14); @@ -96,12 +87,12 @@ is( $lines[16], 0, "src 0 line 16 check" ); is( $lines[17], 2, "src 0 line 17 check" ); is( $lines[$_], 0, "src 0 line $_ check" ) for (18..19); -my @lines = @{ $data->{$fn1} }; +my @lines = @{ $data->{$s1} }; is( $lines[$_], 0, "src 1 line $_ check" ) for (0..3); cmp_ok ( $lines[$_], ">", 10, "src 1 line $_ check" ) for (4..7); is( $lines[8], 0, "src 1 line 8 check" ); -my @lines = @{ $data->{$fn2} }; +my @lines = @{ $data->{$s2} }; is( $lines[$_], 0, "src 2 line $_ check" ) for (0..8); $project->kill();