Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions examples/valgrind-error.c
Original file line number Diff line number Diff line change
Expand Up @@ -61,3 +61,11 @@ SCU_TEST(memory_leak, "Memory leak")
b[1] = 17;
SCU_ASSERT(b[1] == 17);
}

SCU_TEST(another_memory_leak, "Another memory leak")
{
char *b = malloc(15);

b[1] = 17;
SCU_ASSERT(b[1] == 17);
}
4 changes: 4 additions & 0 deletions libscu-c/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ CFLAGS+=$(SCU_VALGRIND_CFLAGS)
endif
endif

ifneq ($(SCU_VALGRIND_LEAK_LEVEL),)
CFLAGS+=-DSCU_VALGRIND_LEAK_LEVEL=$(SCU_VALGRIND_LEAK_LEVEL)
endif

.PHONY: clean

libscu-c.a: src/scu.o
Expand Down
45 changes: 42 additions & 3 deletions libscu-c/src/scu.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@

#ifdef SCU_HAVE_VALGRIND
#include <valgrind/valgrind.h>
#include <valgrind/memcheck.h>
#ifndef SCU_VALGRIND_LEAK_LEVEL
#define SCU_VALGRIND_LEAK_LEVEL 1
#endif
#else
#define VALGRIND_COUNT_ERRORS 0
#define VALGRIND_PRINTF(format, ...)
Expand Down Expand Up @@ -202,7 +206,7 @@ static void
_scu_output_test_end(int idx, bool success, size_t asserts,
double mono_time, double cpu_time,
size_t num_failures, _scu_failure *failures,
size_t valgrind_errors)
size_t valgrind_errors, size_t valgrind_leaks)
{
json_object_start(_scu_cmd_fd);
json_object_key(_scu_cmd_fd, "event");
Expand All @@ -228,6 +232,11 @@ _scu_output_test_end(int idx, bool success, size_t asserts,
json_object_key(_scu_cmd_fd, "valgrind_errors");
json_integer(_scu_cmd_fd, valgrind_errors);
}
if (valgrind_leaks) {
json_separator(_scu_cmd_fd);
json_object_key(_scu_cmd_fd, "valgrind_leaks");
json_integer(_scu_cmd_fd, valgrind_leaks);
}
json_object_end(_scu_cmd_fd);
_scu_flush_json();
}
Expand Down Expand Up @@ -266,6 +275,30 @@ _scu_redirect_output(char *filename, size_t len)
setvbuf(stderr, NULL, _IONBF, 0);
}

static unsigned _scu_valgrind_leaks (void)
{
unsigned total_leaks = 0;

#ifdef SCU_HAVE_VALGRIND
unsigned leaked, dubious, reachable, suppressed;

VALGRIND_DO_QUICK_LEAK_CHECK;
VALGRIND_COUNT_LEAKS(leaked, dubious, reachable, suppressed);

/* Not errorous leaks */
(void) reachable;
(void) suppressed;

if (SCU_VALGRIND_LEAK_LEVEL >= 1)
total_leaks += leaked;

if (SCU_VALGRIND_LEAK_LEVEL >= 2)
total_leaks += dubious;
#endif

return total_leaks;
}

/* Module actions */

static void
Expand Down Expand Up @@ -338,6 +371,7 @@ _scu_run_test(int idx)
struct timespec start_mono_time, end_mono_time, start_cpu_time, end_cpu_time;

unsigned valgrind_errors_before = VALGRIND_COUNT_ERRORS;
unsigned valgrind_leaks_before = _scu_valgrind_leaks();

_scu_before_each();

Expand All @@ -361,13 +395,18 @@ _scu_run_test(int idx)
_scu_after_each();

unsigned valgrind_errors_after = VALGRIND_COUNT_ERRORS;
unsigned valgrind_leaks_after = _scu_valgrind_leaks();

unsigned valgrind_error_count = valgrind_errors_after - valgrind_errors_before;
unsigned valgrind_leak_count = valgrind_leaks_after - valgrind_leaks_before;

success = success && !valgrind_error_count && !valgrind_leak_count;

_scu_output_test_end(idx, success && !valgrind_error_count, asserts,
_scu_output_test_end(idx, success, asserts,
_scu_get_time_diff(start_mono_time, end_mono_time),
_scu_get_time_diff(start_cpu_time, end_cpu_time),
num_failures, _failures, valgrind_error_count);
num_failures, _failures, valgrind_error_count,
valgrind_leak_count);
}

static void
Expand Down
13 changes: 13 additions & 0 deletions testrunner
Original file line number Diff line number Diff line change
Expand Up @@ -390,6 +390,9 @@ class TestEmitter(Observer):
if event.get('valgrind_errors', 0):
print(" ! {colors.RED}{vgerrs} valgrind error(s){colors.DEFAULT} reported!"
.format(vgerrs=event['valgrind_errors'], colors=Colors))
if event.get('valgrind_leaks', 0):
print(" ! {colors.RED}{vgerrs}B leaked memory{colors.DEFAULT} reported!"
.format(vgerrs=event['valgrind_leaks'], colors=Colors))
elif event_type in ('testcase_error', 'module_crash'):
print('')
print(" ! " + event['message'])
Expand All @@ -414,6 +417,8 @@ class SummaryEmitter(Observer):
self.has_reported_failing_test = {}
self.tests_with_valgrind_errors_counter = 0
self.valgrind_errors_counter = 0
self.tests_with_valgrind_leaks_counter = 0
self.valgrind_leaks_counter = 0
self.show_valgrind_stats = False

def handle_module_start(self, module, event):
Expand All @@ -431,6 +436,9 @@ class SummaryEmitter(Observer):
if event.get('valgrind_errors', 0):
self.tests_with_valgrind_errors_counter += 1
self.valgrind_errors_counter += event['valgrind_errors']
if event.get('valgrind_leaks', 0):
self.tests_with_valgrind_leaks_counter += 1
self.valgrind_leaks_counter += event['valgrind_leaks']

def handle_testcase_error(self, module, event):
self.test_counter += 1
Expand All @@ -449,6 +457,7 @@ class SummaryEmitter(Observer):
def is_failure(self):
return any((self.module_fail_counter > 0,
self.valgrind_errors_counter > 0,
self.valgrind_leaks_counter > 0,
self.module_init_fail_counter > 0))

def print_summary(self):
Expand Down Expand Up @@ -482,11 +491,15 @@ class SummaryEmitter(Observer):
" | Valgrind | |\n"
" +--------------------+------------+\n"
" | Errors: | {:10} |\n"
" | Leaks(B): | {:10} |\n"
" | Tests with errors: | {:10} |\n"
" | Tests with leaks: [ {:10} |\n"
" +--------------------+------------+\n"
).format(
self.valgrind_errors_counter,
self.valgrind_leaks_counter,
self.tests_with_valgrind_errors_counter,
self.tests_with_valgrind_leaks_counter,
))


Expand Down