Last active
February 2, 2023 15:52
-
-
Save bit-hack/f697f21540035e9f7938872287828415 to your computer and use it in GitHub Desktop.
cover_test
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#pragma once | |
#define ENABLE_COVERAGE 1 | |
#if ENABLE_COVERAGE | |
#define COVER_LOCATION printf("%s:%u ", __FILE__, __LINE__) | |
#define COVER_TOKEN printf(" // COVERED\n") | |
#define COVER_ONCE(TEXT) \ | |
{ \ | |
static uint32_t covered = 0; \ | |
if (!covered) { \ | |
covered = 1; \ | |
COVER_LOCATION; \ | |
COVER_TOKEN; \ | |
} \ | |
} | |
#define COVER_COND(TEXT, EXPR) \ | |
if (EXPR) { \ | |
COVER_LOCATION; \ | |
COVER_TOKEN; \ | |
} | |
#define COVER(TEXT) \ | |
{ \ | |
COVER_LOCATION; \ | |
COVER_TOKEN; \ | |
} | |
#else | |
#define COVER_ONCE(TEXT) | |
#define COVER_COND(TEXT, EXPR) | |
#define COVER(TEXT) | |
#endif // ENABLE_COVERAGE |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/python | |
from __future__ import print_function | |
import re | |
import argparse | |
# match lines such as: | |
# cover.c:45: COVER_ONCE("loop was executed"); | |
RE_COVER_POINT = re.compile('(\w+.c):(\d+):\s*(COVER[_\w]*)\("([^"]+)"') | |
# match lines such as: | |
# cover.c:45 // COVER | |
RE_COVER_HIT = re.compile('(\w+.c):(\d+)\s+\/\/ COVERED') | |
class CoverLocation(object): | |
def __init__(self, file, line): | |
self.file = file | |
self.line = line | |
def __repr__(self): | |
return '{}:{}'.format(self.file, self.line) | |
def __eq__(self, obj): | |
return self.file == obj.file and self.line == obj.line | |
def __hash__(self): | |
return hash((self.file, self.line)) | |
class CoverPoint(object): | |
def __init__(self, line): | |
match = RE_COVER_POINT.match(line) | |
if not match: | |
raise RuntimeError('unable to parse cover point: "{}"'.format(line)) | |
self.file = match.group(1) | |
self.line = int(match.group(2)) | |
self.type = match.group(3) | |
self.text = match.group(4) | |
def location(self): | |
return CoverLocation(self.file, self.line) | |
def __repr__(self): | |
return '{:<16} {}'.format(self.type, self.text) | |
class CoverHit(object): | |
def __init__(self, line): | |
match = RE_COVER_HIT.match(line) | |
if not match: | |
raise RuntimeError('unable to parse hit point: "{}"'.format(line)) | |
self.file = match.group(1) | |
self.line = int(match.group(2)) | |
def location(self): | |
return CoverLocation(self.file, self.line) | |
class CoverDict(object): | |
def __init__(self, filename): | |
self.table = {} | |
self.build(filename) | |
def add_cover_point(self, point): | |
self.table[ point.location() ] = point | |
def build(self, filename): | |
with open(filename, 'r') as fd: | |
for l in fd.readlines(): | |
self.add_cover_point(CoverPoint(l)) | |
def dict(self): | |
return self.table | |
class CoverHitList(object): | |
def __init__(self): | |
self.hits = [] | |
def accumulate(self, filename): | |
with open(filename, 'r') as fd: | |
for l in fd.readlines(): | |
self.add_hit(CoverHit(l)) | |
def add_hit(self, hit): | |
self.hits.append(hit) | |
def list(self): | |
return self.hits | |
def parse_args(): | |
parser = argparse.ArgumentParser( | |
prog='cover.py', | |
description='coverage correlation tool' | |
) | |
parser.add_argument('--coverpoints', required=True) | |
parser.add_argument('hits', nargs='+') | |
return parser.parse_args() | |
def correlate(cover_dict, hit_list): | |
points = {} | |
# fill table with all un-hit cover points | |
for loc, cover_point in cover_dict.dict().items(): | |
points[loc] = (0, cover_point) | |
# increment hit count for every hit we see | |
for hit in hit_list.list(): | |
loc = hit.location() | |
if loc not in points: | |
raise RuntimeError('hit with no matching cover point at {}'.format(loc)) | |
points[loc] = (points[loc][0] + 1, points[loc][1]) | |
# report list of cover points sorted by hit count | |
print('location hits type message') | |
for point in sorted(points.items(), key=lambda p: p[1][0]): | |
location = point[0] | |
cover_tuple = point[1] | |
hit_count = cover_tuple[0] | |
cover_point = cover_tuple[1] | |
print('{:<16} {:<8} {}'.format(str(location), hit_count, cover_point)) | |
# usage: | |
# ./cover.py --coverpoints cover_points.cov cover_hit.cov ... | |
def main(): | |
args = parse_args() | |
cover_dict = CoverDict(args.coverpoints) | |
hit_list = CoverHitList() | |
for hit_file in args.hits: | |
hit_list.accumulate(hit_file) | |
correlate(cover_dict, hit_list) | |
if __name__ == '__main__': | |
main() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
set -e | |
# remove our cover point and hits | |
rm -rf *.cov | |
# recompile our test program | |
rm -rf a.out | |
gcc test.c test_file2.c | |
# extract cover points | |
grep -rn --with-filename COVER --include=*.c | grep -v -E "printf|//|#" > cover_points.cov | |
# run program to generate hit points | |
a.out > cover_hit.cov | |
# generate the coverage report | |
python ./cover.py --coverpoints cover_points.cov cover_hit.cov |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdint.h> | |
#include <stdio.h> | |
#include "cover.h" | |
void test_func(int param); | |
int main(int argc, char **args) { | |
COVER("main was executed"); | |
test_func(0); | |
test_func(123); | |
return 0; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdint.h> | |
#include <stdio.h> | |
#include "cover.h" | |
void test_func(int param) { | |
COVER_COND("test_func param equals 123", param == 123); | |
// COVER("This is not a valid cover point"); | |
int i=0; | |
for (i=0; i<32; ++i) { | |
COVER_ONCE("loop was executed"); | |
if (i & 2) { | |
COVER("this event is happened"); | |
} | |
COVER_COND("super important code!!", i == 33); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment