test coverage update

Add myself to RELICENSING file
    Use locking when writing tcov file
    Fixed sometimes last line of function not shown
    Merge tcc_tcov_add_file and tcc_add_tcov
    Allow absolute file names
    Count case labels with no code better
This commit is contained in:
herman ten brugge 2021-01-27 13:27:10 +01:00
parent 65773a5300
commit 1c255baad5
6 changed files with 63 additions and 28 deletions

View File

@ -35,6 +35,7 @@
Frédéric Féret YES x86 64/16 bit asm Frédéric Féret YES x86 64/16 bit asm
grischka YES tccpe.c grischka YES tccpe.c
Henry Kroll YES Henry Kroll YES
Herman ten Brugge YES
Joe Soroka YES Joe Soroka YES
Kirill Smelkov YES Kirill Smelkov YES
mingodad YES mingodad YES

View File

@ -1,6 +1,14 @@
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <stdlib.h> #include <stdlib.h>
#include <fcntl.h>
#ifndef _WIN32
#include <unistd.h>
#include <errno.h>
#else
#include <windows.h>
#include <io.h>
#endif
/* section layout (all little endian): /* section layout (all little endian):
32bit offset to executable/so file name 32bit offset to executable/so file name
@ -38,6 +46,32 @@ typedef struct tcov_file {
struct tcov_file *next; struct tcov_file *next;
} tcov_file; } tcov_file;
static FILE *open_tcov_file (char *cov_filename)
{
int fd;
#ifndef _WIN32
struct flock lock;
lock.l_type = F_WRLCK;
lock.l_whence = SEEK_SET;
lock.l_start = 0;
lock.l_len = 0; /* Until EOF. */
lock.l_pid = getpid ();
#endif
fd = open (cov_filename, O_RDWR | O_CREAT, 0666);
if (fd < 0)
return NULL;
#ifndef _WIN32
while (fcntl (fd, F_SETLKW, &lock) && errno == EINTR)
continue;
#else
LockFile((HANDLE)_get_osfhandle(fd), 0, 0, 1, 0);
#endif
return fdopen (fd, "r+");
}
static unsigned long long get_value(unsigned char *p, int size) static unsigned long long get_value(unsigned char *p, int size)
{ {
unsigned long long value = 0; unsigned long long value = 0;
@ -176,11 +210,10 @@ static tcov_file *sort_test_coverage (unsigned char *p)
} }
/* merge with previous tcov file */ /* merge with previous tcov file */
static void merge_test_coverage (tcov_file *file, char *cov_filename, static void merge_test_coverage (tcov_file *file, FILE *fp,
unsigned int *pruns) unsigned int *pruns)
{ {
unsigned int runs; unsigned int runs;
FILE *fp = fopen (cov_filename, "r");
char *p; char *p;
char str[10000]; char str[10000];
@ -228,7 +261,6 @@ static void merge_test_coverage (tcov_file *file, char *cov_filename,
} }
file = file->next; file = file->next;
} }
fclose (fp);
} }
/* store tcov data in file */ /* store tcov data in file */
@ -247,13 +279,14 @@ void __store_test_coverage (unsigned char * p)
tcov_file *nfile; tcov_file *nfile;
tcov_function *func; tcov_function *func;
file = sort_test_coverage (p); fp = open_tcov_file (cov_filename);
merge_test_coverage (file, cov_filename, &runs);
fp = fopen (cov_filename, "w");
if (fp == NULL) { if (fp == NULL) {
fprintf (stderr, "Cannot create coverage file: %s\n", cov_filename); fprintf (stderr, "Cannot create coverage file: %s\n", cov_filename);
return; return;
} }
file = sort_test_coverage (p);
merge_test_coverage (file, fp, &runs);
fseek (fp, 0, SEEK_SET);
fprintf (fp, " -: 0:Runs:%u\n", runs); fprintf (fp, " -: 0:Runs:%u\n", runs);
files = 0; files = 0;
funcs = 0; funcs = 0;
@ -346,12 +379,11 @@ void __store_test_coverage (unsigned char * p)
lline = nlline; lline = nlline;
j++; j++;
} }
else { else
if (same_line)
lline++;
break; break;
}
} }
if (same_line)
lline++;
while (curline < fline) while (curline < fline)
if (fgets(str, sizeof(str), src)) if (fgets(str, sizeof(str), src))

1
tcc.h
View File

@ -1467,7 +1467,6 @@ ST_FUNC void tcc_debug_end(TCCState *s1);
ST_FUNC void tcc_debug_bincl(TCCState *s1); ST_FUNC void tcc_debug_bincl(TCCState *s1);
ST_FUNC void tcc_debug_eincl(TCCState *s1); ST_FUNC void tcc_debug_eincl(TCCState *s1);
ST_FUNC void tcc_debug_putfile(TCCState *s1, const char *filename); ST_FUNC void tcc_debug_putfile(TCCState *s1, const char *filename);
ST_FUNC void tcc_add_tcov(TCCState *s1);
ST_FUNC void tccgen_init(TCCState *s1); ST_FUNC void tccgen_init(TCCState *s1);
ST_FUNC int tccgen_compile(TCCState *s1); ST_FUNC int tccgen_compile(TCCState *s1);

View File

@ -1438,9 +1438,13 @@ static void tcc_tcov_add_file(TCCState *s1, const char *filename)
section_ptr_add(tcov_section, 1); section_ptr_add(tcov_section, 1);
write32le (tcov_section->data, tcov_section->data_offset); write32le (tcov_section->data, tcov_section->data_offset);
getcwd (wd, sizeof(wd));
cstr_new (&cstr); cstr_new (&cstr);
cstr_printf (&cstr, "%s/%s.tcov", wd, filename); if (filename[0] == '/')
cstr_printf (&cstr, "%s.tcov", filename);
else {
getcwd (wd, sizeof(wd));
cstr_printf (&cstr, "%s/%s.tcov", wd, filename);
}
ptr = section_ptr_add(tcov_section, cstr.size + 1); ptr = section_ptr_add(tcov_section, cstr.size + 1);
strncpy((char *)ptr, cstr.data, cstr.size); strncpy((char *)ptr, cstr.data, cstr.size);
unlink((char *)ptr); unlink((char *)ptr);
@ -1448,11 +1452,6 @@ static void tcc_tcov_add_file(TCCState *s1, const char *filename)
normalize_slashes((char *)ptr); normalize_slashes((char *)ptr);
#endif #endif
cstr_free (&cstr); cstr_free (&cstr);
}
ST_FUNC void tcc_add_tcov(TCCState *s1)
{
CString cstr;
cstr_new(&cstr); cstr_new(&cstr);
cstr_printf(&cstr, cstr_printf(&cstr,
@ -1512,8 +1511,6 @@ ST_FUNC void tcc_add_runtime(TCCState *s1)
tcc_add_btstub(s1); tcc_add_btstub(s1);
} }
#endif #endif
if (s1->test_coverage)
tcc_add_tcov(s1);
if (strlen(TCC_LIBTCC1) > 0) if (strlen(TCC_LIBTCC1) > 0)
tcc_add_support(s1, TCC_LIBTCC1); tcc_add_support(s1, TCC_LIBTCC1);
#if TARGETOS_OpenBSD || TARGETOS_FreeBSD || TARGETOS_NetBSD #if TARGETOS_OpenBSD || TARGETOS_FreeBSD || TARGETOS_NetBSD

View File

@ -208,7 +208,6 @@ static struct debug_info {
static struct { static struct {
unsigned long offset; unsigned long offset;
unsigned long last_offset;
unsigned long last_file_name; unsigned long last_file_name;
unsigned long last_func_name; unsigned long last_func_name;
int ind; int ind;
@ -822,6 +821,7 @@ static void tcc_tcov_block_begin(void)
{ {
SValue sv; SValue sv;
void *ptr; void *ptr;
unsigned long last_offset = tcov_data.offset;
tcc_tcov_block_end (0); tcc_tcov_block_end (0);
if (tcc_state->test_coverage == 0 || nocode_wanted) if (tcc_state->test_coverage == 0 || nocode_wanted)
@ -837,11 +837,17 @@ static void tcc_tcov_block_begin(void)
section_ptr_add(tcov_section, 1); section_ptr_add(tcov_section, 1);
if (tcov_data.last_file_name) if (tcov_data.last_file_name)
section_ptr_add(tcov_section, 1); section_ptr_add(tcov_section, 1);
getcwd (wd, sizeof(wd));
tcov_data.last_file_name = tcov_section->data_offset + strlen(wd) + 1;
tcov_data.last_func_name = 0; tcov_data.last_func_name = 0;
cstr_new (&cstr); cstr_new (&cstr);
cstr_printf (&cstr, "%s/%s", wd, file->true_filename); if (file->true_filename[0] == '/') {
tcov_data.last_file_name = tcov_section->data_offset;
cstr_printf (&cstr, "%s", file->true_filename);
}
else {
getcwd (wd, sizeof(wd));
tcov_data.last_file_name = tcov_section->data_offset + strlen(wd) + 1;
cstr_printf (&cstr, "%s/%s", wd, file->true_filename);
}
ptr = section_ptr_add(tcov_section, cstr.size + 1); ptr = section_ptr_add(tcov_section, cstr.size + 1);
strncpy((char *)ptr, cstr.data, cstr.size); strncpy((char *)ptr, cstr.data, cstr.size);
#ifdef _WIN32 #ifdef _WIN32
@ -865,7 +871,7 @@ static void tcc_tcov_block_begin(void)
write64le (ptr, file->line_num); write64le (ptr, file->line_num);
} }
if (ind == tcov_data.ind && tcov_data.line == file->line_num) if (ind == tcov_data.ind && tcov_data.line == file->line_num)
tcov_data.offset = tcov_data.last_offset; tcov_data.offset = last_offset;
else { else {
Sym label = {0}; Sym label = {0};
label.type.t = VT_LLONG | VT_STATIC; label.type.t = VT_LLONG | VT_STATIC;
@ -903,7 +909,6 @@ static void tcc_tcov_block_end(int line)
unsigned long long nline = line ? line : file->line_num; unsigned long long nline = line ? line : file->line_num;
write64le (ptr, (read64le (ptr) & 0xfffffffffull) | (nline << 36)); write64le (ptr, (read64le (ptr) & 0xfffffffffull) | (nline << 36));
tcov_data.last_offset = tcov_data.offset;
tcov_data.offset = 0; tcov_data.offset = 0;
} }
} }
@ -5744,6 +5749,7 @@ static inline int is_memory_model(const SValue *sv)
* Ideally we should check whether the model matches 1:1. * Ideally we should check whether the model matches 1:1.
* If it is possible, we should check by the name of the value. * If it is possible, we should check by the name of the value.
*/ */
int t = 0; // XXX: HACK
return (((t & VT_BTYPE) == VT_INT) && (sv->c.i < 6)); return (((t & VT_BTYPE) == VT_INT) && (sv->c.i < 6));
} }
@ -7576,6 +7582,7 @@ again:
|| (cur_switch->sv.type.t & VT_UNSIGNED && (uint64_t)cr->v2 < (uint64_t)cr->v1)) || (cur_switch->sv.type.t & VT_UNSIGNED && (uint64_t)cr->v2 < (uint64_t)cr->v1))
tcc_warning("empty case range"); tcc_warning("empty case range");
} }
tcov_data.ind = 0;
cr->sym = gind(); cr->sym = gind();
dynarray_add(&cur_switch->p, &cur_switch->n, cr); dynarray_add(&cur_switch->p, &cur_switch->n, cr);
skip(':'); skip(':');
@ -7587,6 +7594,7 @@ again:
expect("switch"); expect("switch");
if (cur_switch->def_sym) if (cur_switch->def_sym)
tcc_error("too many 'default'"); tcc_error("too many 'default'");
tcov_data.ind = 0;
cur_switch->def_sym = gind(); cur_switch->def_sym = gind();
skip(':'); skip(':');
is_expr = 0; is_expr = 0;

View File

@ -1915,8 +1915,6 @@ static void pe_add_runtime(TCCState *s1, struct pe_info *pe)
tcc_add_btstub(s1); tcc_add_btstub(s1);
} }
#endif #endif
if (s1->test_coverage)
tcc_add_tcov(s1);
/* grab the startup code from libtcc1.a */ /* grab the startup code from libtcc1.a */
#ifdef TCC_IS_NATIVE #ifdef TCC_IS_NATIVE