Skip to content
This repository has been archived by the owner on Oct 12, 2022. It is now read-only.

Commit

Permalink
fix Issue 14464 - coverage merge doesn't work
Browse files Browse the repository at this point in the history
- fix parsing of existing .lst file
- use append semantics (create or merge with existing .lst file)
- enable merge by default
- some code cleanup (reuse buffers, log10, foreach, min/max)
  • Loading branch information
MartinNowak committed May 17, 2015
1 parent 1d082c1 commit 7a8e9dc
Showing 1 changed file with 73 additions and 80 deletions.
153 changes: 73 additions & 80 deletions src/rt/cover.d
Expand Up @@ -58,7 +58,7 @@ private
Cover[] gdata;
string srcpath;
string dstpath;
bool merge;
bool merge = true;
}
}

Expand Down Expand Up @@ -129,133 +129,126 @@ extern (C) void _d_cover_register( string filename, size_t[] valid, uint[] data
_d_cover_register2(filename, valid, data, 0);
}

private:

// returns 0 if s isn't a number
uint parseNum(const(char)[] s)
{
while (s.length && s[0] == ' ')
s = s[1 .. $];
uint res;
while (s.length && s[0] >= '0' && s[0] <= '9')
{
res = 10 * res + s[0] - '0';
s = s[1 .. $];
}
return res;
}

T min(T)(T a, T b) { return a < b ? a : b; }
T max(T)(T a, T b) { return b < a ? a : b; }

shared static ~this()
{
if (!gdata.length) return;

const NUMLINES = 16384 - 1;
const NUMCHARS = 16384 * 16 - 1;

char[] srcbuf = new char[NUMCHARS];
char[][] srclines = new char[][NUMLINES];
char[] lstbuf = new char[NUMCHARS];
char[][] lstlines = new char[][NUMLINES];
auto buf = new char[NUMCHARS];
auto lines = new char[][NUMLINES];

foreach( Cover c; gdata )
foreach (c; gdata)
{
if( !readFile( appendFN( srcpath, c.filename ), srcbuf ) )
continue;
splitLines( srcbuf, srclines );

if( merge )
if (merge && readFile(appendFN(dstpath, addExt(baseName(c.filename), "lst")), buf))
{
if( !readFile( appendFN(dstpath, addExt( baseName( c.filename ), "lst" )), lstbuf ) )
break;
splitLines( lstbuf, lstlines );
splitLines(buf, lines);

for( size_t i = 0; i < lstlines.length; ++i )
{
if( i >= c.data.length )
break;

int count = 0;

foreach( char c2; lstlines[i] )
{
switch( c2 )
{
case ' ':
continue;
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
count = count * 10 + c2 - '0';
continue;
default:
break;
}
}
c.data[i] += count;
}
foreach (i, line; lines[0 .. min($, c.data.length)])
c.data[i] += parseNum(line);
}

FILE* flst = fopen( appendFN(dstpath, (addExt(baseName( c.filename ), "lst\0" ))).ptr, "wb" );
FILE* flst = fopen(appendFN(dstpath, (addExt(baseName(c.filename), "lst\0"))).ptr, "wb");

if (!flst)
continue;
scope(exit) fclose(flst);

if( !flst )
continue; //throw new Exception( "Error opening file for write: " ~ lstfn );
if (!readFile(appendFN(srcpath, c.filename), buf))
continue;
splitLines(buf, lines);

// Calculate the maximum number of digits in the line with the greatest
// number of calls.
uint maxCallCount = 0;
foreach (i; 0..c.data.length)
{
if ( i < srclines.length )
{
const uint lineCallCount = c.data[i];
if (maxCallCount < lineCallCount)
maxCallCount = lineCallCount;
}
}
uint maxCallCount;
foreach (n; c.data[0 .. min($, lines.length)])
maxCallCount = max(maxCallCount, n);

// Make sure that there are a minimum of seven columns in each file so
// that unless there are a very large number of calls, the columns in
// each files lineup.
uint maxDigits = digits(maxCallCount);
if (maxDigits < 7)
maxDigits = 7;
immutable maxDigits = max(7, digits(maxCallCount));

uint nno;
uint nyes;

foreach (i; 0..c.data.length)
foreach (i, n; c.data[0 .. min($, lines.length)])
{
if( i < srclines.length )
{
uint n = c.data[i];
char[] line = srclines[i];

line = expandTabs( line );
auto line = lines[i];
line = expandTabs( line );

if( n == 0 )
if (n == 0)
{
if (c.valid[i])
{
if( c.valid[i] )
{
nno++;
fprintf( flst, "%0*u|%.*s\n", maxDigits, 0, cast(int)line.length, line.ptr );
}
else
{
fprintf( flst, "%*s|%.*s\n", maxDigits, " ".ptr, cast(int)line.length, line.ptr );
}
++nno;
fprintf(flst, "%0*u|%.*s\n", maxDigits, 0, cast(int)line.length, line.ptr);
}
else
{
nyes++;
fprintf( flst, "%*u|%.*s\n", maxDigits, n, cast(int)line.length, line.ptr );
fprintf(flst, "%*s|%.*s\n", maxDigits, " ".ptr, cast(int)line.length, line.ptr);
}
}
else
{
++nyes;
fprintf(flst, "%*u|%.*s\n", maxDigits, n, cast(int)line.length, line.ptr);
}
}
if( nyes + nno ) // no divide by 0 bugs
if (nyes + nno) // no divide by 0 bugs
{
uint percent = ( nyes * 100 ) / ( nyes + nno );
fprintf( flst, "%.*s is %d%% covered\n", cast(int)c.filename.length, c.filename.ptr, percent );
fprintf(flst, "%.*s is %d%% covered\n", cast(int)c.filename.length, c.filename.ptr, percent);
if (percent < c.minPercent)
{
fclose(flst);
fprintf(stderr, "Error: %.*s is %d%% covered, less than required %d%%\n",
cast(int)c.filename.length, c.filename.ptr, percent, c.minPercent);
exit(EXIT_FAILURE);
}
}
fclose( flst );
}
}

uint digits( uint number )
uint digits(uint number)
{
if (number < 10)
return 1;
import core.stdc.math;
return number ? cast(uint)floor(log10(number)) + 1 : 1;
}

return digits(number / 10) + 1;
unittest
{
static void testDigits(uint num, uint dgts)
{
assert(digits(num) == dgts);
assert(digits(num - 1) == dgts - 1);
assert(digits(num + 1) == dgts);
}
assert(digits(0) == 1);
assert(digits(1) == 1);
testDigits(10, 2);
testDigits(1_000, 4);
testDigits(1_000_000, 7);
testDigits(1_000_000_000, 10);
}

string appendFN( string path, string name )
Expand Down

0 comments on commit 7a8e9dc

Please sign in to comment.