diff --git a/tests-clar/clar.c b/tests-clar/clar.c index 10bea8724..fed87c30d 100644 --- a/tests-clar/clar.c +++ b/tests-clar/clar.c @@ -331,21 +331,14 @@ clar_test(int argc, char **argv) return _clar.total_errors; } -void -clar__assert( - int condition, +void clar__fail( const char *file, int line, const char *error_msg, const char *description, int should_abort) { - struct clar_error *error; - - if (condition) - return; - - error = calloc(1, sizeof(struct clar_error)); + struct clar_error *error = calloc(1, sizeof(struct clar_error)); if (_clar.errors == NULL) _clar.errors = error; @@ -380,6 +373,20 @@ clar__assert( } } +void clar__assert( + int condition, + const char *file, + int line, + const char *error_msg, + const char *description, + int should_abort) +{ + if (condition) + return; + + clar__fail(file, line, error_msg, description, should_abort); +} + void clar__assert_equal_s( const char *s1, const char *s2, @@ -392,8 +399,8 @@ void clar__assert_equal_s( if (!match) { char buf[4096]; - snprint_eq(buf, 4096, "'%s' != '%s'", s1, s2); - clar__assert(0, file, line, err, buf, should_abort); + snprint_eq(buf, sizeof(buf), "'%s' != '%s'", s1, s2); + clar__fail(file, line, err, buf, should_abort); } } @@ -407,8 +414,8 @@ void clar__assert_equal_i( { if (i1 != i2) { char buf[128]; - snprint_eq(buf, 128, "%d != %d", i1, i2); - clar__assert(0, file, line, err, buf, should_abort); + snprint_eq(buf, sizeof(buf), "%d != %d", i1, i2); + clar__fail(file, line, err, buf, should_abort); } } diff --git a/tests-clar/clar.h b/tests-clar/clar.h index 2ba6416b3..d92318bd4 100644 --- a/tests-clar/clar.h +++ b/tests-clar/clar.h @@ -51,17 +51,29 @@ void cl_fixture_cleanup(const char *fixture_name); /** * Forced failure/warning */ -#define cl_fail(desc) clar__assert(0, __FILE__, __LINE__, "Test failed.", desc, 1) -#define cl_warning(desc) clar__assert(0, __FILE__, __LINE__, "Warning during test execution:", desc, 0) +#define cl_fail(desc) clar__fail(__FILE__, __LINE__, "Test failed.", desc, 1) +#define cl_warning(desc) clar__fail(__FILE__, __LINE__, "Warning during test execution:", desc, 0) /** * Typed assertion macros */ #define cl_assert_equal_s(s1,s2) clar__assert_equal_s((s1),(s2),__FILE__,__LINE__,"String mismatch: " #s1 " != " #s2, 1) +#define cl_assert_equal_s_(s1,s2,note) clar__assert_equal_s((s1),(s2),__FILE__,__LINE__,"String mismatch: " #s1 " != " #s2 " (" #note ")", 1) + #define cl_assert_equal_i(i1,i2) clar__assert_equal_i((i1),(i2),__FILE__,__LINE__,#i1 " != " #i2, 1) +#define cl_assert_equal_i_(i1,i2,note) clar__assert_equal_i((i1),(i2),__FILE__,__LINE__,#i1 " != " #i2 " (" #note ")", 1) + #define cl_assert_equal_b(b1,b2) clar__assert_equal_i(!!(b1),!!(b2),__FILE__,__LINE__,#b1 " != " #b2, 1) + #define cl_assert_equal_p(p1,p2) cl_assert((p1) == (p2)) +void clar__fail( + const char *file, + int line, + const char *error, + const char *description, + int should_abort); + void clar__assert( int condition, const char *file, diff --git a/tests-clar/generate.py b/tests-clar/generate.py index c2739224d..d4fe8f2a3 100644 --- a/tests-clar/generate.py +++ b/tests-clar/generate.py @@ -60,7 +60,10 @@ class Module(object): def __init__(self, name): self.name = name + + self.mtime = 0 self.enabled = True + self.modified = False def clean_name(self): return self.name.replace("_", "::") @@ -102,17 +105,41 @@ class Module(object): return self.callbacks != [] - def load(self, path): + def refresh(self, path): + self.modified = False + try: + st = os.stat(path) + + # Not modified + if st.st_mtime == self.mtime: + return True + + self.modified = True + self.mtime = st.st_mtime + with open(path) as fp: - return self.parse(fp.read()) + raw_content = fp.read() + except IOError: return False + return self.parse(raw_content) + class TestSuite(object): + def __init__(self, path): self.path = path + def should_generate(self, path): + if not os.path.isfile(path): + return True + + if any(module.modified for module in self.modules.values()): + return True + + return False + def find_modules(self): modules = [] for root, _, files in os.walk(self.path): @@ -129,15 +156,33 @@ class TestSuite(object): return modules + def load_cache(self): + path = os.path.join(self.path, '.clarcache') + cache = {} + + try: + fp = open(path, 'rb') + cache = pickle.load(fp) + fp.close() + except (IOError, ValueError): + pass + + return cache + + def save_cache(self): + path = os.path.join(self.path, '.clarcache') + with open(path, 'wb') as cache: + pickle.dump(self.modules, cache) + def load(self, force = False): module_data = self.find_modules() - self.modules = {} + self.modules = {} if force else self.load_cache() for path, name in module_data: if name not in self.modules: self.modules[name] = Module(name) - if not self.modules[name].load(path): + if not self.modules[name].refresh(path): del self.modules[name] def disable(self, excluded): @@ -157,6 +202,9 @@ class TestSuite(object): def write(self): output = os.path.join(self.path, 'clar.suite') + if not self.should_generate(output): + return False + with open(output, 'w') as data: for module in self.modules.values(): t = Module.DeclarationTemplate(module) @@ -175,19 +223,22 @@ class TestSuite(object): data.write("static const size_t _clar_suite_count = %d;\n" % self.suite_count()) data.write("static const size_t _clar_callback_count = %d;\n" % self.callback_count()) + suite.save_cache() + return True + if __name__ == '__main__': from optparse import OptionParser parser = OptionParser() + parser.add_option('-f', '--force', dest='force', default=False) parser.add_option('-x', '--exclude', dest='excluded', action='append', default=[]) options, args = parser.parse_args() for path in args or ['.']: suite = TestSuite(path) - suite.load() + suite.load(options.force) suite.disable(options.excluded) - suite.write() - - print("Written `clar.suite` (%d suites)" % len(suite.modules)) + if suite.write(): + print("Written `clar.suite` (%d tests in %d suites)" % (suite.callback_count(), suite.suite_count()))