Added script that automatically generates code for code coverage
This commit is contained in:
1 parent
8e73cde6ae
commit
1dd0f25ff8
16 files changed
+145
-63
No files matched your search
+112
@@ -0,0 +1,112 @@
|
||||
# A script that automatically expands the macros for code coverage
|
||||
|
||||
import os
|
||||
import re
|
||||
import time
|
||||
import subprocess
|
||||
|
||||
# Compiler settings
|
||||
CC = 'gcc'
|
||||
INCLUDE = '-I ./src'
|
||||
# -E Only preprocessor
|
||||
# -P No linemarkers
|
||||
# -C Keep comments, except those inside macros (for UNIQUE_FLAG)
|
||||
FLAGS = '-E -P -C'
|
||||
|
||||
# Used to delimiter where the actual code starts and ends
|
||||
# Used by regex
|
||||
# Needs to be a valid C comment
|
||||
UNIQUE_FLAG = '// C_MACRO_COLLECTIONS_CODE'
|
||||
|
||||
# Temporary file used to expand the macros
|
||||
TMP_FILE = 'main.c'
|
||||
|
||||
# Output directory
|
||||
OUTPUT_DIR = './tests/codecov/src'
|
||||
|
||||
collections = [
|
||||
# type, header, pfx, sname, key, val
|
||||
{'t': 'BIDIMAP', 'h': '"cmc/bidimap.h"', 'pfx': 'bm', 'sname': 'bidimap', 'key': 'size_t', 'val': 'size_t'},
|
||||
{'t': 'DEQUE', 'h': '"cmc/deque.h"', 'pfx': 'd', 'sname': 'deque', 'key': '', 'val': 'size_t'},
|
||||
{'t': 'HASHMAP', 'h': '"cmc/hashmap.h"', 'pfx': 'hm', 'sname': 'hashmap', 'key': 'size_t', 'val': 'size_t'},
|
||||
{'t': 'HASHSET', 'h': '"cmc/hashset.h"', 'pfx': 'hs', 'sname': 'hashset', 'key': '', 'val': 'size_t'},
|
||||
{'t': 'HEAP', 'h': '"cmc/heap.h"', 'pfx': 'h', 'sname': 'heap', 'key': '', 'val': 'size_t'},
|
||||
{'t': 'INTERVALHEAP', 'h': '"cmc/intervalheap.h"', 'pfx': 'ih', 'sname': 'intervalheap', 'key': '', 'val': 'size_t'},
|
||||
{'t': 'LINKEDLIST', 'h': '"cmc/linkedlist.h"', 'pfx': 'll', 'sname': 'linkedlist', 'key': '', 'val': 'size_t'},
|
||||
{'t': 'LIST', 'h': '"cmc/list.h"', 'pfx': 'l', 'sname': 'list', 'key': '', 'val': 'size_t'},
|
||||
{'t': 'MULTIMAP', 'h': '"cmc/multimap.h"', 'pfx': 'mm', 'sname': 'multimap', 'key': 'size_t', 'val': 'size_t'},
|
||||
{'t': 'MULTISET', 'h': '"cmc/multiset.h"', 'pfx': 'ms', 'sname': 'multiset', 'key': '', 'val': 'size_t'},
|
||||
{'t': 'QUEUE', 'h': '"cmc/queue.h"', 'pfx': 'q', 'sname': 'queue', 'key': '', 'val': 'size_t'},
|
||||
{'t': 'SORTEDLIST', 'h': '"cmc/sortedlist.h"', 'pfx': 'sl', 'sname': 'sortedlist', 'key': '', 'val': 'size_t'},
|
||||
{'t': 'STACK', 'h': '"cmc/stack.h"', 'pfx': 's', 'sname': 'stack', 'key': '', 'val': 'size_t'},
|
||||
{'t': 'TREEMAP', 'h': '"cmc/treemap.h"', 'pfx': 'tm', 'sname': 'treemap', 'key': 'size_t', 'val': 'size_t'},
|
||||
{'t': 'TREESET', 'h': '"cmc/treeset.h"', 'pfx': 'ts', 'sname': 'treeset', 'key': '', 'val': 'size_t'}
|
||||
]
|
||||
|
||||
# Create output directory
|
||||
if not os.path.exists(OUTPUT_DIR):
|
||||
os.makedirs(OUTPUT_DIR)
|
||||
|
||||
for data in collections:
|
||||
file = open(TMP_FILE, 'w')
|
||||
|
||||
file.write(
|
||||
f'''
|
||||
#include {data['h']}
|
||||
|
||||
{UNIQUE_FLAG}
|
||||
|
||||
CMC_GENERATE_{data['t']}({data['pfx']}, {data['sname']}, {f'{data["key"]}, {data["val"]}' if data['key'] != '' else data['val']})
|
||||
|
||||
{UNIQUE_FLAG}
|
||||
''')
|
||||
|
||||
file.flush()
|
||||
file.close()
|
||||
|
||||
result = subprocess.run(f'{CC} {FLAGS} {INCLUDE} {TMP_FILE}', stdout=subprocess.PIPE).stdout.decode('utf-8')
|
||||
|
||||
# (?s) makes '.' match anything, even '\n'
|
||||
match = re.search(fr'(?s){UNIQUE_FLAG}(?P<code>.+){UNIQUE_FLAG}', result)
|
||||
|
||||
if match is None:
|
||||
os.remove(TMP_FILE)
|
||||
print('Didn\'t match FLAG. Probably because compilation failed.')
|
||||
exit(1)
|
||||
|
||||
file = open(f'{OUTPUT_DIR}/{data["sname"]}.c', 'w')
|
||||
|
||||
file.write(f'#include {data["h"]}\n{match.group("code")}')
|
||||
|
||||
file.flush()
|
||||
file.close()
|
||||
|
||||
print(f'Generated {data["h"]: >20} -> {OUTPUT_DIR}/{data["sname"]}.c')
|
||||
|
||||
# This seemed to be crashing
|
||||
# subprocess.run(f'clang-format --style=file -i {OUTPUT_DIR}/*.c')
|
||||
|
||||
# So I guess... it will have to be called from a temp Makefile... ugh
|
||||
TMP_MAKE = 'temp_makefile'
|
||||
|
||||
data = '''
|
||||
.PHONY: codecov FORCE
|
||||
|
||||
codecov: FORCE
|
||||
\tclang-format --style=file -i $(OUTPUT_DIR)/*.c
|
||||
|
||||
FORCE:
|
||||
|
||||
'''
|
||||
|
||||
print(f'Creating temporary Makefile as {TMP_MAKE}')
|
||||
|
||||
file = open(TMP_MAKE, 'w')
|
||||
file.write(data)
|
||||
file.flush()
|
||||
file.close()
|
||||
|
||||
subprocess.call(f'make -f {TMP_MAKE} codecov OUTPUT_DIR={OUTPUT_DIR} --always-make')
|
||||
|
||||
os.remove(TMP_FILE)
|
||||
os.remove(TMP_MAKE)
|
||||
@@ -1,6 +1,4 @@
|
||||
#include <cmc/bidimap.h>
|
||||
|
||||
// CMC_GENERATE_BIDIMAP(bm, bidimap, size_t, size_t)
|
||||
#include "cmc/bidimap.h"
|
||||
|
||||
struct bidimap
|
||||
{
|
||||
@@ -120,7 +118,7 @@ struct bidimap *bm_new(size_t capacity, double load,
|
||||
struct cmc_alloc_node *alloc = &cmc_alloc_node_default;
|
||||
if (capacity == 0 || load <= 0 || load >= 1)
|
||||
return ((void *)0);
|
||||
if (capacity >= 0xffffffffffffffff * load)
|
||||
if (capacity >= 0xffffffffffffffffULL * load)
|
||||
return ((void *)0);
|
||||
if (!f_key || !f_val)
|
||||
return ((void *)0);
|
||||
@@ -156,7 +154,7 @@ struct bidimap *bm_new_custom(size_t capacity, double load,
|
||||
{
|
||||
if (capacity == 0 || load <= 0 || load >= 1)
|
||||
return ((void *)0);
|
||||
if (capacity >= 0xffffffffffffffff * load)
|
||||
if (capacity >= 0xffffffffffffffffULL * load)
|
||||
return ((void *)0);
|
||||
if (!f_key || !f_val)
|
||||
return ((void *)0);
|
||||
@@ -483,7 +481,7 @@ _Bool bm_resize(struct bidimap *_map_, size_t capacity)
|
||||
goto success;
|
||||
if (_map_->capacity > capacity / _map_->load)
|
||||
goto success;
|
||||
if (capacity >= 0xffffffffffffffff * _map_->load)
|
||||
if (capacity >= 0xffffffffffffffffULL * _map_->load)
|
||||
{
|
||||
_map_->flag = cmc_flags.ERROR;
|
||||
return 0;
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
#include <cmc/deque.h>
|
||||
|
||||
// CMC_GENERATE_DEQUE(d, deque, size_t)
|
||||
#include "cmc/deque.h"
|
||||
|
||||
struct deque
|
||||
{
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
#include <cmc/hashmap.h>
|
||||
|
||||
// CMC_GENERATE_HASHMAP(hm, hashmap, size_t, size_t)
|
||||
#include "cmc/hashmap.h"
|
||||
|
||||
struct hashmap
|
||||
{
|
||||
@@ -111,7 +109,7 @@ struct hashmap *hm_new(size_t capacity, double load,
|
||||
struct cmc_alloc_node *alloc = &cmc_alloc_node_default;
|
||||
if (capacity == 0 || load <= 0 || load >= 1)
|
||||
return ((void *)0);
|
||||
if (capacity >= 0xffffffffffffffff * load)
|
||||
if (capacity >= 0xffffffffffffffffULL * load)
|
||||
return ((void *)0);
|
||||
if (!f_key || !f_val)
|
||||
return ((void *)0);
|
||||
@@ -145,7 +143,7 @@ struct hashmap *hm_new_custom(size_t capacity, double load,
|
||||
{
|
||||
if (capacity == 0 || load <= 0 || load >= 1)
|
||||
return ((void *)0);
|
||||
if (capacity >= 0xffffffffffffffff * load)
|
||||
if (capacity >= 0xffffffffffffffffULL * load)
|
||||
return ((void *)0);
|
||||
if (!f_key || !f_val)
|
||||
return ((void *)0);
|
||||
@@ -462,7 +460,7 @@ _Bool hm_resize(struct hashmap *_map_, size_t capacity)
|
||||
goto success;
|
||||
if (_map_->capacity > capacity / _map_->load)
|
||||
goto success;
|
||||
if (capacity >= 0xffffffffffffffff * _map_->load)
|
||||
if (capacity >= 0xffffffffffffffffULL * _map_->load)
|
||||
{
|
||||
_map_->flag = cmc_flags.ERROR;
|
||||
return 0;
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
#include <cmc/hashset.h>
|
||||
|
||||
// CMC_GENERATE_HASHSET(hs, hashset, size_t)
|
||||
#include "cmc/hashset.h"
|
||||
|
||||
struct hashset
|
||||
{
|
||||
@@ -101,7 +99,7 @@ struct hashset *hs_new(size_t capacity, double load,
|
||||
struct cmc_alloc_node *alloc = &cmc_alloc_node_default;
|
||||
if (capacity == 0 || load <= 0 || load >= 1)
|
||||
return ((void *)0);
|
||||
if (capacity >= 0xffffffffffffffff * load)
|
||||
if (capacity >= 0xffffffffffffffffULL * load)
|
||||
return ((void *)0);
|
||||
if (!f_val)
|
||||
return ((void *)0);
|
||||
@@ -133,7 +131,7 @@ struct hashset *hs_new_custom(size_t capacity, double load,
|
||||
{
|
||||
if (capacity == 0 || load <= 0 || load >= 1)
|
||||
return ((void *)0);
|
||||
if (capacity >= 0xffffffffffffffff * load)
|
||||
if (capacity >= 0xffffffffffffffffULL * load)
|
||||
return ((void *)0);
|
||||
if (!f_val)
|
||||
return ((void *)0);
|
||||
@@ -367,7 +365,7 @@ _Bool hs_resize(struct hashset *_set_, size_t capacity)
|
||||
goto success;
|
||||
if (_set_->capacity > capacity / _set_->load)
|
||||
goto success;
|
||||
if (capacity >= 0xffffffffffffffff * _set_->load)
|
||||
if (capacity >= 0xffffffffffffffffULL * _set_->load)
|
||||
{
|
||||
_set_->flag = cmc_flags.ERROR;
|
||||
return 0;
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
#include <cmc/heap.h>
|
||||
|
||||
// CMC_GENERATE_HEAP(h, heap, size_t)
|
||||
#include "cmc/heap.h"
|
||||
|
||||
struct heap
|
||||
{
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
#include <cmc/intervalheap.h>
|
||||
|
||||
// CMC_GENERATE_INTERVALHEAP(ih, intervalheap, size_t)
|
||||
#include "cmc/intervalheap.h"
|
||||
|
||||
struct intervalheap
|
||||
{
|
||||
@@ -87,7 +85,7 @@ struct intervalheap *ih_new(size_t capacity,
|
||||
struct intervalheap_ftab_val *f_val)
|
||||
{
|
||||
struct cmc_alloc_node *alloc = &cmc_alloc_node_default;
|
||||
if (capacity == 0 || capacity == 0xffffffffffffffff)
|
||||
if (capacity == 0 || capacity == 0xffffffffffffffffULL)
|
||||
return ((void *)0);
|
||||
if (!f_val)
|
||||
return ((void *)0);
|
||||
@@ -117,7 +115,7 @@ struct intervalheap *ih_new_custom(size_t capacity,
|
||||
struct cmc_alloc_node *alloc,
|
||||
struct cmc_callbacks *callbacks)
|
||||
{
|
||||
if (capacity == 0 || capacity == 0xffffffffffffffff)
|
||||
if (capacity == 0 || capacity == 0xffffffffffffffffULL)
|
||||
return ((void *)0);
|
||||
if (!f_val)
|
||||
return ((void *)0);
|
||||
@@ -414,7 +412,7 @@ _Bool ih_resize(struct intervalheap *_heap_, size_t capacity)
|
||||
_heap_->flag = cmc_flags.INVALID;
|
||||
return 0;
|
||||
}
|
||||
if (capacity == 0xffffffffffffffff)
|
||||
if (capacity == 0xffffffffffffffffULL)
|
||||
{
|
||||
_heap_->flag = cmc_flags.ERROR;
|
||||
return 0;
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
#include <cmc/linkedlist.h>
|
||||
|
||||
// CMC_GENERATE_LINKEDLIST(ll, linkedlist, size_t)
|
||||
#include "cmc/linkedlist.h"
|
||||
|
||||
struct linkedlist
|
||||
{
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
#include <cmc/list.h>
|
||||
|
||||
// CMC_GENERATE_LIST(l, list, size_t)
|
||||
#include "cmc/list.h"
|
||||
|
||||
struct list
|
||||
{
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
#include <cmc/multimap.h>
|
||||
|
||||
// CMC_GENERATE_MULTIMAP(mm, multimap, size_t, size_t)
|
||||
#include "cmc/multimap.h"
|
||||
|
||||
struct multimap
|
||||
{
|
||||
@@ -118,7 +116,7 @@ struct multimap *mm_new(size_t capacity, double load,
|
||||
struct cmc_alloc_node *alloc = &cmc_alloc_node_default;
|
||||
if (capacity == 0 || load <= 0)
|
||||
return ((void *)0);
|
||||
if (capacity >= 0xffffffffffffffff * load)
|
||||
if (capacity >= 0xffffffffffffffffULL * load)
|
||||
return ((void *)0);
|
||||
if (!f_key || !f_val)
|
||||
return ((void *)0);
|
||||
@@ -153,7 +151,7 @@ struct multimap *mm_new_custom(size_t capacity, double load,
|
||||
{
|
||||
if (capacity == 0 || load <= 0)
|
||||
return ((void *)0);
|
||||
if (capacity >= 0xffffffffffffffff * load)
|
||||
if (capacity >= 0xffffffffffffffffULL * load)
|
||||
return ((void *)0);
|
||||
if (!f_key || !f_val)
|
||||
return ((void *)0);
|
||||
@@ -632,7 +630,7 @@ _Bool mm_resize(struct multimap *_map_, size_t capacity)
|
||||
goto success;
|
||||
if (_map_->capacity > capacity / _map_->load)
|
||||
goto success;
|
||||
if (capacity >= 0xffffffffffffffff * _map_->load)
|
||||
if (capacity >= 0xffffffffffffffffULL * _map_->load)
|
||||
{
|
||||
_map_->flag = cmc_flags.ERROR;
|
||||
return 0;
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
#include <cmc/multiset.h>
|
||||
|
||||
// CMC_GENERATE_MULTISET(ms, multiset, size_t)
|
||||
#include "cmc/multiset.h"
|
||||
|
||||
struct multiset
|
||||
{
|
||||
@@ -116,7 +114,7 @@ struct multiset *ms_new(size_t capacity, double load,
|
||||
struct cmc_alloc_node *alloc = &cmc_alloc_node_default;
|
||||
if (capacity == 0 || load <= 0 || load >= 1)
|
||||
return ((void *)0);
|
||||
if (capacity >= 0xffffffffffffffff * load)
|
||||
if (capacity >= 0xffffffffffffffffULL * load)
|
||||
return ((void *)0);
|
||||
if (!f_val)
|
||||
return ((void *)0);
|
||||
@@ -149,7 +147,7 @@ struct multiset *ms_new_custom(size_t capacity, double load,
|
||||
{
|
||||
if (capacity == 0 || load <= 0 || load >= 1)
|
||||
return ((void *)0);
|
||||
if (capacity >= 0xffffffffffffffff * load)
|
||||
if (capacity >= 0xffffffffffffffffULL * load)
|
||||
return ((void *)0);
|
||||
if (!f_val)
|
||||
return ((void *)0);
|
||||
@@ -449,7 +447,7 @@ _Bool ms_resize(struct multiset *_set_, size_t capacity)
|
||||
goto success;
|
||||
if (_set_->capacity > capacity / _set_->load)
|
||||
goto success;
|
||||
if (capacity >= 0xffffffffffffffff * _set_->load)
|
||||
if (capacity >= 0xffffffffffffffffULL * _set_->load)
|
||||
{
|
||||
_set_->flag = cmc_flags.ERROR;
|
||||
return 0;
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
#include <cmc/queue.h>
|
||||
|
||||
// CMC_GENERATE_QUEUE(q, queue, size_t)
|
||||
#include "cmc/queue.h"
|
||||
|
||||
struct queue
|
||||
{
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
#include <cmc/sortedlist.h>
|
||||
|
||||
// CMC_GENERATE_SORTEDLIST(sl, sortedlist, size_t)
|
||||
#include "cmc/sortedlist.h"
|
||||
|
||||
struct sortedlist
|
||||
{
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
#include <cmc/stack.h>
|
||||
|
||||
// CMC_GENERATE_STACK(s, stack, size_t)
|
||||
#include "cmc/stack.h"
|
||||
|
||||
struct stack
|
||||
{
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
#include <cmc/treemap.h>
|
||||
|
||||
// CMC_GENERATE_TREEMAP(tm, treemap, size_t, size_t)
|
||||
#include "cmc/treemap.h"
|
||||
|
||||
struct treemap
|
||||
{
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
#include <cmc/treeset.h>
|
||||
|
||||
// CMC_GENERATE_TREESET(ts, treeset, size_t)
|
||||
#include "cmc/treeset.h"
|
||||
|
||||
struct treeset
|
||||
{
|
||||
|
||||
Reference in new issue
Block a user