commit d44340316ab167a310e07beb8fb5d368ada4d5dd
parent 2fe1a9f35bcc05cb61faea27c61364574be2acc2
Author: kyle <kyle@getaddrinfo.net>
Date: Thu, 10 Mar 2016 22:43:41 -0700
add runtime support for multiple source files
- the runtime now sends back data for all of the translation units in the
application
- send the total number of translation units as the first part of the response
- then parse that many translation unit records
Diffstat:
4 files changed, 129 insertions(+), 12 deletions(-)
diff --git a/SCV/Viewer.pm b/SCV/Viewer.pm
@@ -33,18 +33,28 @@ sub request_data {
$client->syswrite("\x00", 1);
+ # First thing sent back is total number of translation units in the
+ # instrumentation chain
my $buf = read_all($client, 8);
- my $file_name_sz = unpack("Q", $buf);
+ my $num_tus = unpack("Q", $buf);
- my $file_name = read_all($client, $file_name_sz);
+ my %tu_data;
+ for (1..$num_tus) {
+ my $buf = read_all($client, 8);
+ my $file_name_sz = unpack("Q", $buf);
- $buf = read_all($client, 8);
- my $num_lines = unpack("Q", $buf);
+ my $file_name = read_all($client, $file_name_sz);
- $buf = read_all($client, 8 * $num_lines);
- my @data = unpack("Q$num_lines", $buf);
+ $buf = read_all($client, 8);
+ my $num_lines = unpack("Q", $buf);
- return ({ file_name => $file_name, data => \@data });
+ $buf = read_all($client, 8 * $num_lines);
+ my @data = unpack("Q$num_lines", $buf);
+
+ $tu_data{$file_name} = \@data ;
+ }
+
+ return \%tu_data;
}
sub read_all {
diff --git a/runtime/runtime.c b/runtime/runtime.c
@@ -54,9 +54,17 @@ void
walk_nodes(int fd)
{
size_t file_name_sz;
+ uint64_t num_tus;
- /* Copy node0, don't use it directly */
struct scv_node walk = node0;
+
+ /* Find how many translation units there are in this application */
+ for (num_tus = 0; walk.size != 0; num_tus++)
+ walk = *walk.next;
+ xwrite(fd, &num_tus, sizeof(num_tus));
+
+ /* Reset walk back to the start */
+ walk = node0;
while (walk.size != 0) {
file_name_sz = strnlen(walk.file_name, PATH_MAX);
diff --git a/t/runtime_sanity.t b/t/runtime_sanity.t
@@ -1,7 +1,7 @@
use strict;
use SCV::Project;
use SCV::Viewer;
-use Test::More tests => 37;
+use Test::More tests => 38;
use Test::Differences;
use Time::HiRes qw( usleep );
@@ -57,11 +57,14 @@ $viewer->accept();
usleep(100 * 1000);
my $data = $viewer->request_data();
-like ($data->{file_name}, qr/tmp\/.*source_0\.c/, "runtime filename check");
-my @lines = @{ $data->{data} };
+my ($file_name, @others) = keys %$data;
+like ($file_name, qr/tmp\/.*source_0\.c/, "runtime filename check");
+is( @others, 0, "runtime check for a single tu" );
-# Check the line counts are something reasonable
+my @lines = @{ $data->{$file_name} };
is (scalar(@lines), 33, "runtime lines count");
+
+# Do a pretty thorough coverage check
is ( $lines[$_], 0, "line $_ check" ) for (0..8);
cmp_ok ( $lines[$_], ">", 0, "line $_ check" ) for (9..12);
is ( $lines[13], 0, "line 13 check" );
diff --git a/t/runtime_sanity_multisource.t b/t/runtime_sanity_multisource.t
@@ -0,0 +1,96 @@
+use strict;
+use Data::Dumper;
+use SCV::Project;
+use SCV::Viewer;
+use Test::More tests => 47;
+use Test::Differences;
+
+my $viewer = SCV::Viewer->new();
+my $project = SCV::Project->new();
+unified_diff;
+
+$project->add_src(<<EOF
+#include <err.h>
+#include <limits.h>
+#include <stdlib.h> /* strtonum */
+
+long long factorial(long long);
+void print_output(long long);
+
+int
+main(int argc, char *argv[])
+{
+ long long n;
+ const char *errstr = NULL;
+
+ if (argc != 2)
+ errx(1, "argc != 2");
+
+ n = strtonum(argv[1], LONG_MIN, LONG_MAX, &errstr);
+ if (errstr)
+ err(1, "%s", errstr);
+
+ print_output(factorial(n));
+ return 0;
+}
+EOF
+);
+
+$project->add_src(<<EOF
+long long
+factorial(long long n)
+{
+ if (n == 0)
+ return 1;
+
+ return n * factorial(n - 1);
+}
+EOF
+);
+
+$project->add_src(<<EOF
+#include <stdio.h>
+
+void
+print_output(long long n)
+{
+ fprintf(stderr, "%lli", n);
+ return;
+}
+EOF
+);
+
+$project->compile();
+$project->run(17);
+
+$viewer->accept();
+my $data = $viewer->request_data();
+
+like ($_, qr/tmp\/.*source_.*\.c/, "runtime filename check") for (keys %$data);
+my ($src_filename_0, $src_filename_1, $src_filename_2) = sort keys %$data;
+
+my @lines = @{ $data->{$src_filename_0} };
+is ( $lines[$_], 0, "src 0 line $_ check" ) for (0..13);
+is ( $lines[14], 1, "src 0 line 14 check" );
+is ( $lines[$_], 0, "src 0 line $_ check" ) for (15..16);
+is ( $lines[$_], 1, "src 0 line $_ check" ) for (17..18);
+is ( $lines[$_], 0, "src 0 line $_ check" ) for (19..20);
+is ( $lines[21], 2, "src 0 line 21 check" );
+is ( $lines[$_], 0, "src 0 line $_ check" ) for (22..23);
+
+my @lines = @{ $data->{$src_filename_1} };
+is ( $lines[$_], 0, "src 1 line $_ check" ) for (0..3);
+is ( $lines[4], 18, "src 1 line 4 check" );
+is ( $lines[5], 1, "src 1 line 5 check" );
+is ( $lines[6], 0, "src 1 line 6 check" );
+is ( $lines[7], 34, "src 1 line 7 check" );
+is ( $lines[8], 0, "src 1 line 8 check" );
+
+my @lines = @{ $data->{$src_filename_2} };
+is ( $lines[$_], 0, "src 2 line $_ check" ) for (0..5);
+is ( $lines[6], 1, "src 2 line 6 check" );
+is ( $lines[$_], 0, "src 2 line $_ check" ) for (7..8);
+
+my ($ret, $err) = $project->wait();
+is( $ret, 0, "instrumented program check return code" );
+is( $err, "355687428096000", "instrumented program check stderr" );