summaryrefslogtreecommitdiff
path: root/tests-clar/clar
diff options
context:
space:
mode:
Diffstat (limited to 'tests-clar/clar')
-rwxr-xr-xtests-clar/clar311
-rw-r--r--tests-clar/clar/fixtures.h38
-rw-r--r--tests-clar/clar/fs.h325
-rw-r--r--tests-clar/clar/print.h60
-rw-r--r--tests-clar/clar/sandbox.h127
5 files changed, 550 insertions, 311 deletions
diff --git a/tests-clar/clar b/tests-clar/clar
deleted file mode 100755
index 873dc3b0c..000000000
--- a/tests-clar/clar
+++ /dev/null
@@ -1,311 +0,0 @@
-#!/usr/bin/env python
-
-from __future__ import with_statement
-from string import Template
-import re, fnmatch, os
-
-VERSION = "0.10.0"
-
-TEST_FUNC_REGEX = r"^(void\s+(test_%s__(\w+))\(\s*void\s*\))\s*\{"
-
-EVENT_CB_REGEX = re.compile(
- r"^(void\s+clar_on_(\w+)\(\s*void\s*\))\s*\{",
- re.MULTILINE)
-
-SKIP_COMMENTS_REGEX = re.compile(
- r'//.*?$|/\*.*?\*/|\'(?:\\.|[^\\\'])*\'|"(?:\\.|[^\\"])*"',
- re.DOTALL | re.MULTILINE)
-
-CLAR_HEADER = """
-/*
- * Clar v%s
- *
- * This is an autogenerated file. Do not modify.
- * To add new unit tests or suites, regenerate the whole
- * file with `./clar`
- */
-""" % VERSION
-
-CLAR_EVENTS = [
- 'init',
- 'shutdown',
- 'test',
- 'suite'
-]
-
-def main():
- from optparse import OptionParser
-
- parser = OptionParser()
-
- parser.add_option('-c', '--clar-path', dest='clar_path')
- parser.add_option('-v', '--report-to', dest='print_mode', default='default')
-
- options, args = parser.parse_args()
-
- for folder in args or ['.']:
- builder = ClarTestBuilder(folder,
- clar_path = options.clar_path,
- print_mode = options.print_mode)
-
- builder.render()
-
-
-class ClarTestBuilder:
- def __init__(self, path, clar_path = None, print_mode = 'default'):
- self.declarations = []
- self.suite_names = []
- self.callback_data = {}
- self.suite_data = {}
- self.event_callbacks = []
-
- self.clar_path = os.path.abspath(clar_path) if clar_path else None
-
- self.path = os.path.abspath(path)
- self.modules = [
- "clar_sandbox.c",
- "clar_fixtures.c",
- "clar_fs.c"
- ]
-
- self.modules.append("clar_print_%s.c" % print_mode)
-
- print("Loading test suites...")
-
- for root, dirs, files in os.walk(self.path):
- module_root = root[len(self.path):]
- module_root = [c for c in module_root.split(os.sep) if c]
-
- tests_in_module = fnmatch.filter(files, "*.c")
-
- for test_file in tests_in_module:
- full_path = os.path.join(root, test_file)
- test_name = "_".join(module_root + [test_file[:-2]])
-
- with open(full_path) as f:
- self._process_test_file(test_name, f.read())
-
- if not self.suite_data:
- raise RuntimeError(
- 'No tests found under "%s"' % path)
-
- def render(self):
- main_file = os.path.join(self.path, 'clar_main.c')
- with open(main_file, "w") as out:
- out.write(self._render_main())
-
- header_file = os.path.join(self.path, 'clar.h')
- with open(header_file, "w") as out:
- out.write(self._render_header())
-
- print ('Written Clar suite to "%s"' % self.path)
-
- #####################################################
- # Internal methods
- #####################################################
-
- def _render_cb(self, cb):
- return '{"%s", &%s}' % (cb['short_name'], cb['symbol'])
-
- def _render_suite(self, suite, index):
- template = Template(
-r"""
- {
- ${suite_index},
- "${clean_name}",
- ${initialize},
- ${cleanup},
- ${cb_ptr}, ${cb_count}
- }
-""")
-
- callbacks = {}
- for cb in ['initialize', 'cleanup']:
- callbacks[cb] = (self._render_cb(suite[cb])
- if suite[cb] else "{NULL, NULL}")
-
- return template.substitute(
- suite_index = index,
- clean_name = suite['name'].replace("_", "::"),
- initialize = callbacks['initialize'],
- cleanup = callbacks['cleanup'],
- cb_ptr = "_clar_cb_%s" % suite['name'],
- cb_count = suite['cb_count']
- ).strip()
-
- def _render_callbacks(self, suite_name, callbacks):
- template = Template(
-r"""
-static const struct clar_func _clar_cb_${suite_name}[] = {
- ${callbacks}
-};
-""")
- callbacks = [
- self._render_cb(cb)
- for cb in callbacks
- if cb['short_name'] not in ('initialize', 'cleanup')
- ]
-
- return template.substitute(
- suite_name = suite_name,
- callbacks = ",\n\t".join(callbacks)
- ).strip()
-
- def _render_event_overrides(self):
- overrides = []
- for event in CLAR_EVENTS:
- if event in self.event_callbacks:
- continue
-
- overrides.append(
- "#define clar_on_%s() /* nop */" % event
- )
-
- return '\n'.join(overrides)
-
- def _render_header(self):
- template = Template(self._load_file('clar.h'))
-
- declarations = "\n".join(
- "extern %s;" % decl
- for decl in sorted(self.declarations)
- )
-
- return template.substitute(
- extern_declarations = declarations,
- )
-
- def _render_main(self):
- template = Template(self._load_file('clar.c'))
- suite_names = sorted(self.suite_names)
-
- suite_data = [
- self._render_suite(self.suite_data[s], i)
- for i, s in enumerate(suite_names)
- ]
-
- callbacks = [
- self._render_callbacks(s, self.callback_data[s])
- for s in suite_names
- ]
-
- callback_count = sum(
- len(cbs) for cbs in self.callback_data.values()
- )
-
- return template.substitute(
- clar_modules = self._get_modules(),
- clar_callbacks = "\n".join(callbacks),
- clar_suites = ",\n\t".join(suite_data),
- clar_suite_count = len(suite_data),
- clar_callback_count = callback_count,
- clar_event_overrides = self._render_event_overrides(),
- )
-
- def _load_file(self, filename):
- if self.clar_path:
- filename = os.path.join(self.clar_path, filename)
- with open(filename) as cfile:
- return cfile.read()
-
- else:
- import zlib, base64, sys
- content = CLAR_FILES[filename]
-
- if sys.version_info >= (3, 0):
- content = bytearray(content, 'utf_8')
- content = base64.b64decode(content)
- content = zlib.decompress(content)
- return str(content, 'utf-8')
- else:
- content = base64.b64decode(content)
- return zlib.decompress(content)
-
- def _get_modules(self):
- return "\n".join(self._load_file(f) for f in self.modules)
-
- def _skip_comments(self, text):
- def _replacer(match):
- s = match.group(0)
- return "" if s.startswith('/') else s
-
- return re.sub(SKIP_COMMENTS_REGEX, _replacer, text)
-
- def _process_test_file(self, suite_name, contents):
- contents = self._skip_comments(contents)
-
- self._process_events(contents)
- self._process_declarations(suite_name, contents)
-
- def _process_events(self, contents):
- for (decl, event) in EVENT_CB_REGEX.findall(contents):
- if event not in CLAR_EVENTS:
- continue
-
- self.declarations.append(decl)
- self.event_callbacks.append(event)
-
- def _process_declarations(self, suite_name, contents):
- callbacks = []
- initialize = cleanup = None
-
- regex_string = TEST_FUNC_REGEX % suite_name
- regex = re.compile(regex_string, re.MULTILINE)
-
- for (declaration, symbol, short_name) in regex.findall(contents):
- data = {
- "short_name" : short_name,
- "declaration" : declaration,
- "symbol" : symbol
- }
-
- if short_name == 'initialize':
- initialize = data
- elif short_name == 'cleanup':
- cleanup = data
- else:
- callbacks.append(data)
-
- if not callbacks:
- return
-
- tests_in_suite = len(callbacks)
-
- suite = {
- "name" : suite_name,
- "initialize" : initialize,
- "cleanup" : cleanup,
- "cb_count" : tests_in_suite
- }
-
- if initialize:
- self.declarations.append(initialize['declaration'])
-
- if cleanup:
- self.declarations.append(cleanup['declaration'])
-
- self.declarations += [
- callback['declaration']
- for callback in callbacks
- ]
-
- callbacks.sort(key=lambda x: x['short_name'])
- self.callback_data[suite_name] = callbacks
- self.suite_data[suite_name] = suite
- self.suite_names.append(suite_name)
-
- print(" %s (%d tests)" % (suite_name, tests_in_suite))
-
-
-
-CLAR_FILES = {
-"clar.c" : r"""eJytGWtv20byM/krNs4lpmxasZTD4c5OXAS55mC0dYA8kAKJQazIlbUORcpcMrHb6r93ZvbB5UN2D2g+xOa8dmZ2nuvHskjzJhPsBVdKVPV0dRY+djAl6uv1pgers1wuBjBZ9kGVLK66sDWvVwNGXhFV+OyAVeKmkZXI2LKsmOJFtihvQQg7eOaz3Kln9d1GqJ4kAKuakwEAXmZiyZJP5xfP5+HjwFF9l0VWftesLdTo3gLUSuQ538geOAPlUnNCAAfIQrDkl1fnF8nr1yxJ0kykuYdCdaIN2BzDrxOWdL9buvVXEGwQ6zITQNqCPLp05YAs8T5aCp6mQqmuqCHM17DKmk0EP0g994FGyGVBPkx+Ob/436fn8yQBYLCp+NWas7Rcr0VRRxAJMdsjdz2f76FkT3SRbu6iuozZsirXMavLRMnfQCWDShQhDdhSJR/efbx4/erDj76wT8nbn9jx3IO8T87f//f8XXQ7YVF0y56yBCBvADJhj16y444mxQZCsU7ETbRolrH6LV6u65jHC7RZ45agi8G58x0ViBK5EqMS7a9LJCoyuQwDjE10HFjZpLW+dfb+w6sPyYfT8LGR1Anb71xiUDHIAPx1I7NoPqGgb+maQkKu6HjsRZ53nSN69fXpqUM6t2m0l+a8mq72whDpZMq+lRLSUSXVOkrLQtUQhLxiB4kqmyoVk9M+XVrCnY9QxswHZgIS4NQd4qPCpbytm0okGLAdSQuuemIsacHXQosjE9GGRFQVFJHfw8BnqOHc0xC8WjP8NSma9UJUp10i1cha9GBLmQvDmIOnxxnpyGStrhBu7UwruallWYB6wVC/g0Lcgkbb1heGpqc4T2v5TSRG/xGMUVqrSB/6BGXNLWueO5DngrRsitpCKrEpq9qQJWWR3+1Q28keweVcGRHITIERHeRlCuenueBFs5lEBD2AO9P4Lhqu/i4veYbs0H4SyExWV3y9KdH31iAHSETBF7kA8i2URVCkFwnLpkj7/sSIOXXKbaDkkUoTexUtN/kS2fFQ6B7i9nRU1OBEWcha8hxK2xjWmOpkDQgoVsnDICHpXhbqCMXiDRRMzaHT/mCaYtXwM9LDoj5R99pj1kaLAQwSgZJL9RLdE6tWTQ0ttXhYNAJ0ihBgt0giInmQZlalXUG4W0xZoDpRP//JIK2NVwM0YMkhz7P7RJJF0biXfJspUu4TxBeQaR1BUDhiNp1OJ/3bNZPQjtttCoO3EWwoUBef3aJR9o/fBGJ5ni94+pWV38CVEooVHvCP37WPkSRxmC3xvWrq8koUouI1TGnoPpbxmrPFHR3lsVvZyNip8sPcStrf1edL9hKSjcE/I0jDt50SqTPC49MRBaw+kwZuT0fZrH59zi7cJNrrshLaWkxNrOaqdxUhMXfKp/Z3aCsHHDEbr5f0I7atIAw0+KVWdOoq7fcVxCaLNBZmnIuPP/88wcIUICPQE+boTIsJgmFCHR7GzOZMECwrISLD4/WpHo4+rUZGNFxp4CvndG0rP9P6QakKR9zUFNTJovuLX7wb3dbWe4hss7FXoGuPqp263TYZao+VRjc0XJMNO42+S5C6ZJFekaI+6YS9xDGU7gfJWo2PzqDduAsEdNDD4dEARi3ct+fzUXWOrTrmIvx26p81gh5jsR14YsUa+EB3H671Nkq6RnB4iFBa7tZQTRgv7hiddQSes22QrUW9KjPKqjEdXTiNIa2yjsj3xHCimdjc6GYrOpmG807mmB6Ct6Tvg+o8fvbtJGA0DCx25gKPLnuyOyf83jIsk7rRUDTflzXgBSI8OusNENI65tGDnuk2OyNOdzjzYdubyxlN6kWAP5e2OplhacRNJoZx848kfUHNfOHbYqYfdngodV51DjK244/P8nJqDgq6BeepQcfsqTPEVRIHs4WD0m5LrwnsGLezWkDmVbyS+R3LpNLJN9oI8DZlcZWPXecDFW5w27uc9dcdPXSRJQh7DiKt/qJztm59HNjfKH7VnZJ4dUXG6K002vuIFCfsiWKfS+o76vJL8aXYixlSnraEbzX2BHA+mLEj9euvX+ov9bumYBi9rF4JbT3TIx2DUEIrGdANmG8YQ+a3yKgzgfyiQArsxyuoJrzQiWt4xS2Mz0ezHem74ZUSCaiuaG6FX9LYWI6mf2vngE6Qz3SQI7kX185jDb6xABlKgKiltoAZbFGfjy+xGO8f7VNp8VxPHMeXupOo77JOVx7b7NIcBBs121f7J/QVmIkbDkQjJhCUdZk7LnbI5hAG9jNms2MaDjoaYdcz2iK9PiawJeia6AN9xtFMf5EzrnXGX4MzBmMdeuaaDNRngV4pdNxWkc4Aea1z3++/7ZlGgSBYVIJ/NR/b0P6H0pHwBT4gBbs8aggjbdQEGc5eDtW2Z49M/Xvv/TB9krGshNm7KGFGuZWqnlIeAFYf5oWeVbTXMp52PACMRk1nJU4P5rZv9k/a9jXsAWZMdbwhPXrxJq9PdoYYKbX18gJs1WlBNWV3QvS3U5BEkTc2osddpL9ZAmZvLwy8YcXbeiZ0mzrcR27iDW18rC7tezOVEaqU4F/YdKYm//1b2HrDIinujkY7oePP2lbaFgbtAzK+O6N0K7g/2betOxh0xtE8kZMHw0NedkzobfHh+GSz2/OG2nteMjfhJgMruoW2KyuqUom6qQo2FESltq2xif4LRaQLKTSXTGJriIcvdXH7UhfveKLrwb0FyDCrVdnkWUJhQsG6a3NzUWcVwivQNvnbHEZzmUazmPbQchkN5E16YWF7fX96dzNA5/jBBjac+h1OL4m+hJH9zeEMi5keBhPFaYfCPKc4Qv/ZytLZUWUY/S0NXiOQmHdXA/SeXgFnHgMNzt2sVV0/xGrneNfr+2W4/eIApf8M0l2Jx6Yw3GxGwl8vPNSo/BBym+CjXWucaRgjVYq6AJQqOETbdsJ4b3ViFZdK6KnlNhWk91QXrk7/oE6Ql8XV2NIaM1vfTOIxP/EScdOAlSrqPZfPermk5v9vSu5KOQSuOc4uMJKomU0F9scfTM3bSvmDRSoYOE7cgKAw1+ZmEHDLD8nz5qxFs/z8z+P//OsSvdP7UxFDRMz29p+ofRq04Cd0ZiPYrRe2MB3HFK+xthJvKmYkpmPYQ/6VpsDJmXGL/Pv8iQ8RM7REznsumM3/PeoBgIMDYEQBpicZGA9qIfffY3yiRO3eIcxjfP9vBLF+6zwoN/ym8Tei/gtB+6R+/yOBFkTNxTz6rcusyemNE93m/qK75rIYTC809lyiGvhIaXpXO+x0mvw2/BMhekzB""",
-"clar_print_default.c" : r"""eJyFU8Fu2zAMPdtfwQUwIgVuenew9tZTsMuwU1sYqiW3AhzJkOhswNB/n0Q5rRws6Ukmxff4RD6XHgXqDo5WS+gG4drRaYOtNhpZ+ABUHtvOTgZriLGfNKpTorPGI3RvwsEmXRhxUJ6Xf8uCRUr+Cd+VBVH3bLW3QioJlUxsvoHKP5lVDbEjX3TIWTOGnygcKhlAIftelhde4d8mlPa3+folMaGcsy4lLr0gpTLkRy4D78pPoU8maSxIlVOjddhSrWdXpVMN6TbT4TRpj27qMJVRAWzoILmnlhAGy+FB6GFyqqG5Bgqeq6p801QeWOU5PIagks/weIPhiOVlURDrzR09NIvjLGK4Mhak8p3TI2q7gPR6yBGDNmF90+FFuTOeObvQBScjzHVpqAf/SlW6BzZfZM3h23f48Wu/54H+Ek9Wzpfbue4fa6JSlts8SQ9+TJ7JXpISfZi7kuf+iYDdMkOYzNJVF/QmNNzD+mENDay36y/00YbY///D3ObaSPWHVN1uwFg7wuZ2aWeqOLN4kn2tv3gJhl70D9uqYbvdUrOjaAcdroR7HXcU+vjnshjXkBZbHPt5Bh5lWBjla4LwhFFGsjl8L/8BsUiTTQ==""",
-"clar_print_tap.c" : r"""eJyNVE1vnDAQPcOvmGWFBAiQot6yaqr2HFU9tLdKyAGzscLayDbbVlX+e8cDJPbuJtsTzPObmTcfdmwss6KFoxIdtAPTzaiFtI2Qwmb4A5Yb27RqkrYEZ5tJWL4CrZLGQvvINBTzgWQHbvL4bxxlLmT+6r5bIY94gq08ktBnyffP3+DItRFKws2HnzLJd/FzHL8h2TxOtlO/5HXZDuBaKz0D/yM3xDznXRxHoodsEwSMXmrYwsiM4R2wYYC0I2GZybGY0hOJhUV8MDxw7JkY0BGd2EHJ/am3l7BEvyiMtoa5qeu0O8/2dhspLPVQTod1xMbqqbUzjQhQ0MdrHbJdL9a8AFVVzSPzMJy5YXsOt5Ca1yKqu7mWg9mHdMNx/ML+uaVenEWj0QCcRSM8pLri4QLV4SGzx6ZfYjo8ZA5CrszOZzq8wXY8cJ2v67Ecddy0WozWbfTmI3z9cX/vLwuARzgV4B3lYafrur52OZSk1fEvLO2Du4bzhZhNUj0D8/rRhNdUqXFLWC3CUPiyop8gkcqCekqwGQl+3Jkf8MXEdHFE8kmc5qPSy86Z7EoFNNbs8pvj33IhO/470L2FoihQNWTbtMudQY313X3X92WwB5QcyMC9Ld0QKOeRNYPAI6b3445MjIQOzi5hWfF+UWbwxZrwRUq+YCMBfzdAO348JVAKFyKfY3LZZYv5HP8D5Mbj9w==""",
-"clar_sandbox.c" : r"""eJydVWtP4kAU/dz+iism0gpKfWQ3G9YPm+gasioEMJgomdR2KhPplMwM7KLxv++dTqEP0DVrTKjcO+eec+6cKpWvWADBxBdAgqkvyMxXk/tT79uXcdu2pSkzrmwmycKfspCoeJY2OUHCpTJH9/UXrv1qW4PhjyEZglR42mIROBrC0eUm7Enlws4ZeK5tWYKqueDgrfp2BqQzOO/08cChVCROQupW+7Jnxw8CKmWGOiLdXy6cadi2/VbiHDFe5JsyfZxHERVNkOyFEgVTyp8M9V0W8ZBGQEadm5Nj28pwjMqse4EGBcmcKziD03alx+BTvkCjhLwfYw8aYtWG1z3UVWuCfko/Lszn7eCi3+t3f3auLmo2WG8oEaxsEtN6o0SAwxDHawOD7/n4NjQazE3hK7Ox+YkqfHDWRNgYjbGMyfilNlWfUozPqZ6SVjbXq1vNCJQpeDBbOivvsNRcOaehC0uyrDcbf22rtQ+dCNSE6m4mEh5TtC1MqOR19NNfgs+XasL4UxOUWIJKYC4ptHA+7Lfsd0jVdL2W8arSMsUSswIxJLVLp5Ia6EuqhjSe9TSocz7q9s9dc6wJBq5y+XYpD1lkdA0nTIJcSkXjtaApe6YooKRFiw/mQqTCmaCBSrD4gbjDd5UdfiRr9efBUTEAi4SFkEZ6zqXPw8fkj6O/S2OqCRTy7o11gOoPXj1XjVcDI1FMRDBBFcgSaRYMiSQRcQGsmkL0k01DklEwStc8CrdXF4jy2TRNTi3F09bcpT81nbZ1ZFcvjXLAcw4m3klUpOVigIpvHu2WbSEYTkO/8aEsoqr+FXD1PBExLu2FpnT1onvdQecOMKm/fRGCnPpyQmW65EKUrY0oaxF5iKv7YNk+HtJ9WFalBPVWfR219SIqGFrZARyN9RsX+82gcr3RyMH0PVpdu7wLGpppM1/ONmdxDDZllgF6xjgNHUKuOzeXo5NjQtyMXPyMkZmVjqLMm9urq4296P74Wd+34la9r5638S9EH8BkF0enKytPJfKf92ML7v8QWb1i8NQn5a5XmOe6HKEU4fMhhr29banbngCNYpJdJLrVixK9v7GvgW8=""",
-"clar_fixtures.c" : r"""eJyFUV1LwzAUfW5+xZU9rLUVJ4ggZQ9DFAUfZEwQSglZmrBAl5Qkk6n43236tWbKfMvNOfecc+81llhBgSppLNAN0XCOuNjbnWa4InYTjpE1MSzxuD1Vki2L0BcKTKfn0EYgu57d3uRpjYhPhi1opSwumUwRCvo3zMFYXT9C5xA5stWSVh9hI5FAa+wUFG//osgJCA5tmQ1SF3CVw9kcppfTCAWBj8ZxDg3UN4/zZ7MaHBrHSBw7vpcJ4mGS5Ijtai9qnannNqk1q7myXU+KvhGaCF4wDnfPiyV+eHpbvS7v8cti9YjGq6Yl7lzCkxfo1L0j/lJOwOtrUrwrUcDBBRsii7Xan3bjBlNVL2WUzuMkgGlJdLuIP21oyYjcVf/a6G3ozXTQPRqmsZkwWQiOfgAVGffP""",
-"clar_fs.c" : r"""eJylVdtu20YQfSa/YkAD8TKWY8dJX6L0wXDEVqgsBhINN7UFhiGX1qIkl9hd+dLG/57ZCynJUWEkfZE0s7NnZufMGe2xsqAlpJfj6ZsT399DgzUUojhKo8npb3Mg+ud8PBlNE/hq/NP4LJ5G49n5aTKOp71zNJvFs4vx06DzPz6MZ6HvS5UplkO+zAS89EtWUd7KtM3UkuS8kcqdGE/o/+t71tYm/ArTi8lk6HuS/UNTBRVtbtRyAGzo+x4rgaQ2zMaFvucJqlaicdd8z15AHKkE/rbxIQI6+DqrKp4TF3YAJ2GH/AxwTeu8fTBRA0jtl0Xp0K+sucAsx9suzPPauX2v5AIIMxYweO9AhnBwwELAbvTFXLGFrmf/aF+X4/Uu2L++3scEjwjmitRnQ/+x7/0tZ0XXecIaBTUv6AC22i/5SuRPnQWVynAy/z3CSYg/zpPZxVkCJQLp4m2YvYqVbJHrEHU7bJgG+y7IZNBQf1HBz2nNxQN5oeEHoDnnJdlOHYa2aa18dRetmlxziI8ZOl8bCV5ruk3u3ptw9OlUnaeMquxGorOfd/OcKs2kpEKlBFuMibHUuKUCm8gbW1aoOTge4HFwyZqC30l4EgdlhmYR+J4tVVBK1q0wpnv0U4JkKmqygxTDQEdfFKcfRpNRMsKx6zgzM7oLL+c4oz9A80aSs/jjp40U6bpmA46t0vgVzZpVS7TLApg3lOwe55A6ivMqE04hwcsgtCB7tJK0KxdH0pdLWlUpXylii3IVZuLm9mphsPXg6gsrqeXECtwH+Kl7jF96sLj4m6z1i773cGw1VLYCb5dEqoIKodnzgvmDVLQGtLl4B5/t7c+Q40ZwFL66bgLNmUfvmSKHr0Onsg5eT4LFp/c0vyWm1uPFwBTdBd9lTGGwvjCAF7b+Ad4b9mq9HP05TubJaXIxJ/b8f3DZU2lNU9Ivi+G2VNcL1dopLh3dt17IuC0LpHVDwuvA9TLtT21LrHm1EXlo9ly/s/4rwC5C1z00g6MvrDnK22DovCYoOJz1jpPFpsaN6412udkJndTNwdtF/zdiFF6vpMJxlNKIfD12hjQj7MiwD4qD7jkovbfcSEvtlVlTfOH3uxX+rKg3NL3B0dvFrh6I+rselNtN6F68oxk/+2araVBLuv3SZ6RvZL5q3BVi9r52bTgeUfZNwUr/G9kaoSs=""",
-"clar.h" : r"""eJy9VU1P4zAQPZNfYZo9JJUFlCMLSAi1AqlCKyjavVmO4xBrEyfYztLVav874yRtmq922QOX1pnxzHvOe+O4IpIhjxAht8ubR7KaP63IHSGOC0EheS/uuEKypAg5utQmTERwEl87zq9MhIglVBFCtebKeM6RkAaxTIbCiExi5wjWGiIxVWgaiYTjaksCKJ0sVypTnVjINVMir3vZQh1nRRISGmTK+F8HOBD+WtCEaG+3Dx5/gKa9ADQe6ys8WzBUNNRl04ZobghLOJVF7pUxb1o/+tXz1MeoWmQ5fS14Q4FEulVq27oisvKVIi3uf6yeH+fk283qztnlYEvF2hSKe20VyhiRNG2h1GFNZRhk64+UbNjtKXE5WCJynNPp1EFTdFO+UlAVpZSpTKM3YWLE13kimDCotAJKudb0hcP+060xATUttCE5iEI8KFAYWZP4bR+WGR9dX6EzDGZe3C/nhNjV8v6hXE0WhWQlAUaTBEUUrBleoAlym54YzfwesN15GPhyFHe+zjkzPERRi4DJSg4HGNROPAh/PH5uwFfwXi2w0EhmBhlV8CHcjVa3MWc//0MnZus+Sagzv4/8yUoNUfgEoc78A0Mls38cp5rS0IQ9PC+Xw6PQKdp9572i+ujbirabq+3jpjt0jsZuDULfgj1SjVe6ZXvPUm7pVgyeZJEpZk0E3eA+PH2jSgr50mVfEhjwyZg7Vhxu2moYTibDl0WN9JGu36sSFBbK/hkLwtecFdZVF5MBz61+53A42nFe93SdL7OeYX3eprTNQdLHHqTxluGW4OTJlLxSoVNqWFwOg57BL8yRXZ6PXJjbT/cMi2Fg4UESgMUgsCsaELEfJPCCGQ7GQI6PIe1j+zcMFDRAwX6g3MtnOD/fmSQPIj66ukIehHcksiqm3MRZCPpZWtRKVYn05Q9fG64k2c38dTbf63eIKlZw"""
-}
-if __name__ == '__main__':
- main()
diff --git a/tests-clar/clar/fixtures.h b/tests-clar/clar/fixtures.h
new file mode 100644
index 000000000..264cd7f4f
--- /dev/null
+++ b/tests-clar/clar/fixtures.h
@@ -0,0 +1,38 @@
+static const char *
+fixture_path(const char *base, const char *fixture_name)
+{
+ static char _path[4096];
+ size_t root_len;
+
+ root_len = strlen(base);
+ strncpy(_path, base, sizeof(_path));
+
+ if (_path[root_len - 1] != '/')
+ _path[root_len++] = '/';
+
+ if (fixture_name[0] == '/')
+ fixture_name++;
+
+ strncpy(_path + root_len,
+ fixture_name,
+ sizeof(_path) - root_len);
+
+ return _path;
+}
+
+#ifdef CLAR_FIXTURE_PATH
+const char *cl_fixture(const char *fixture_name)
+{
+ return fixture_path(CLAR_FIXTURE_PATH, fixture_name);
+}
+
+void cl_fixture_sandbox(const char *fixture_name)
+{
+ fs_copy(cl_fixture(fixture_name), _clar_path);
+}
+
+void cl_fixture_cleanup(const char *fixture_name)
+{
+ fs_rm(fixture_path(_clar_path, fixture_name));
+}
+#endif
diff --git a/tests-clar/clar/fs.h b/tests-clar/clar/fs.h
new file mode 100644
index 000000000..b7a1ff9d2
--- /dev/null
+++ b/tests-clar/clar/fs.h
@@ -0,0 +1,325 @@
+#ifdef _WIN32
+
+#define RM_RETRY_COUNT 5
+#define RM_RETRY_DELAY 10
+
+#ifdef __MINGW32__
+
+/* These security-enhanced functions are not available
+ * in MinGW, so just use the vanilla ones */
+#define wcscpy_s(a, b, c) wcscpy((a), (c))
+#define wcscat_s(a, b, c) wcscat((a), (c))
+
+#endif /* __MINGW32__ */
+
+static int
+fs__dotordotdot(WCHAR *_tocheck)
+{
+ return _tocheck[0] == '.' &&
+ (_tocheck[1] == '\0' ||
+ (_tocheck[1] == '.' && _tocheck[2] == '\0'));
+}
+
+static int
+fs_rmdir_rmdir(WCHAR *_wpath)
+{
+ unsigned retries = 1;
+
+ while (!RemoveDirectoryW(_wpath)) {
+ /* Only retry when we have retries remaining, and the
+ * error was ERROR_DIR_NOT_EMPTY. */
+ if (retries++ > RM_RETRY_COUNT ||
+ ERROR_DIR_NOT_EMPTY != GetLastError())
+ return -1;
+
+ /* Give whatever has a handle to a child item some time
+ * to release it before trying again */
+ Sleep(RM_RETRY_DELAY * retries * retries);
+ }
+
+ return 0;
+}
+
+static void
+fs_rmdir_helper(WCHAR *_wsource)
+{
+ WCHAR buffer[MAX_PATH];
+ HANDLE find_handle;
+ WIN32_FIND_DATAW find_data;
+ size_t buffer_prefix_len;
+
+ /* Set up the buffer and capture the length */
+ wcscpy_s(buffer, MAX_PATH, _wsource);
+ wcscat_s(buffer, MAX_PATH, L"\\");
+ buffer_prefix_len = wcslen(buffer);
+
+ /* FindFirstFile needs a wildcard to match multiple items */
+ wcscat_s(buffer, MAX_PATH, L"*");
+ find_handle = FindFirstFileW(buffer, &find_data);
+ cl_assert(INVALID_HANDLE_VALUE != find_handle);
+
+ do {
+ /* FindFirstFile/FindNextFile gives back . and ..
+ * entries at the beginning */
+ if (fs__dotordotdot(find_data.cFileName))
+ continue;
+
+ wcscpy_s(buffer + buffer_prefix_len, MAX_PATH - buffer_prefix_len, find_data.cFileName);
+
+ if (FILE_ATTRIBUTE_DIRECTORY & find_data.dwFileAttributes)
+ fs_rmdir_helper(buffer);
+ else {
+ /* If set, the +R bit must be cleared before deleting */
+ if (FILE_ATTRIBUTE_READONLY & find_data.dwFileAttributes)
+ cl_assert(SetFileAttributesW(buffer, find_data.dwFileAttributes & ~FILE_ATTRIBUTE_READONLY));
+
+ cl_assert(DeleteFileW(buffer));
+ }
+ }
+ while (FindNextFileW(find_handle, &find_data));
+
+ /* Ensure that we successfully completed the enumeration */
+ cl_assert(ERROR_NO_MORE_FILES == GetLastError());
+
+ /* Close the find handle */
+ FindClose(find_handle);
+
+ /* Now that the directory is empty, remove it */
+ cl_assert(0 == fs_rmdir_rmdir(_wsource));
+}
+
+static int
+fs_rm_wait(WCHAR *_wpath)
+{
+ unsigned retries = 1;
+ DWORD last_error;
+
+ do {
+ if (INVALID_FILE_ATTRIBUTES == GetFileAttributesW(_wpath))
+ last_error = GetLastError();
+ else
+ last_error = ERROR_SUCCESS;
+
+ /* Is the item gone? */
+ if (ERROR_FILE_NOT_FOUND == last_error ||
+ ERROR_PATH_NOT_FOUND == last_error)
+ return 0;
+
+ Sleep(RM_RETRY_DELAY * retries * retries);
+ }
+ while (retries++ <= RM_RETRY_COUNT);
+
+ return -1;
+}
+
+static void
+fs_rm(const char *_source)
+{
+ WCHAR wsource[MAX_PATH];
+ DWORD attrs;
+
+ /* The input path is UTF-8. Convert it to wide characters
+ * for use with the Windows API */
+ cl_assert(MultiByteToWideChar(CP_UTF8,
+ MB_ERR_INVALID_CHARS,
+ _source,
+ -1, /* Indicates NULL termination */
+ wsource,
+ MAX_PATH));
+
+ /* Does the item exist? If not, we have no work to do */
+ attrs = GetFileAttributesW(wsource);
+
+ if (INVALID_FILE_ATTRIBUTES == attrs)
+ return;
+
+ if (FILE_ATTRIBUTE_DIRECTORY & attrs)
+ fs_rmdir_helper(wsource);
+ else {
+ /* The item is a file. Strip the +R bit */
+ if (FILE_ATTRIBUTE_READONLY & attrs)
+ cl_assert(SetFileAttributesW(wsource, attrs & ~FILE_ATTRIBUTE_READONLY));
+
+ cl_assert(DeleteFileW(wsource));
+ }
+
+ /* Wait for the DeleteFile or RemoveDirectory call to complete */
+ cl_assert(0 == fs_rm_wait(wsource));
+}
+
+static void
+fs_copydir_helper(WCHAR *_wsource, WCHAR *_wdest)
+{
+ WCHAR buf_source[MAX_PATH], buf_dest[MAX_PATH];
+ HANDLE find_handle;
+ WIN32_FIND_DATAW find_data;
+ size_t buf_source_prefix_len, buf_dest_prefix_len;
+
+ wcscpy_s(buf_source, MAX_PATH, _wsource);
+ wcscat_s(buf_source, MAX_PATH, L"\\");
+ buf_source_prefix_len = wcslen(buf_source);
+
+ wcscpy_s(buf_dest, MAX_PATH, _wdest);
+ wcscat_s(buf_dest, MAX_PATH, L"\\");
+ buf_dest_prefix_len = wcslen(buf_dest);
+
+ /* Get an enumerator for the items in the source. */
+ wcscat_s(buf_source, MAX_PATH, L"*");
+ find_handle = FindFirstFileW(buf_source, &find_data);
+ cl_assert(INVALID_HANDLE_VALUE != find_handle);
+
+ /* Create the target directory. */
+ cl_assert(CreateDirectoryW(_wdest, NULL));
+
+ do {
+ /* FindFirstFile/FindNextFile gives back . and ..
+ * entries at the beginning */
+ if (fs__dotordotdot(find_data.cFileName))
+ continue;
+
+ wcscpy_s(buf_source + buf_source_prefix_len, MAX_PATH - buf_source_prefix_len, find_data.cFileName);
+ wcscpy_s(buf_dest + buf_dest_prefix_len, MAX_PATH - buf_dest_prefix_len, find_data.cFileName);
+
+ if (FILE_ATTRIBUTE_DIRECTORY & find_data.dwFileAttributes)
+ fs_copydir_helper(buf_source, buf_dest);
+ else
+ cl_assert(CopyFileW(buf_source, buf_dest, TRUE));
+ }
+ while (FindNextFileW(find_handle, &find_data));
+
+ /* Ensure that we successfully completed the enumeration */
+ cl_assert(ERROR_NO_MORE_FILES == GetLastError());
+
+ /* Close the find handle */
+ FindClose(find_handle);
+}
+
+static void
+fs_copy(const char *_source, const char *_dest)
+{
+ WCHAR wsource[MAX_PATH], wdest[MAX_PATH];
+ DWORD source_attrs, dest_attrs;
+ HANDLE find_handle;
+ WIN32_FIND_DATAW find_data;
+
+ /* The input paths are UTF-8. Convert them to wide characters
+ * for use with the Windows API. */
+ cl_assert(MultiByteToWideChar(CP_UTF8,
+ MB_ERR_INVALID_CHARS,
+ _source,
+ -1,
+ wsource,
+ MAX_PATH));
+
+ cl_assert(MultiByteToWideChar(CP_UTF8,
+ MB_ERR_INVALID_CHARS,
+ _dest,
+ -1,
+ wdest,
+ MAX_PATH));
+
+ /* Check the source for existence */
+ source_attrs = GetFileAttributesW(wsource);
+ cl_assert(INVALID_FILE_ATTRIBUTES != source_attrs);
+
+ /* Check the target for existence */
+ dest_attrs = GetFileAttributesW(wdest);
+
+ if (INVALID_FILE_ATTRIBUTES != dest_attrs) {
+ /* Target exists; append last path part of source to target.
+ * Use FindFirstFile to parse the path */
+ find_handle = FindFirstFileW(wsource, &find_data);
+ cl_assert(INVALID_HANDLE_VALUE != find_handle);
+ wcscat_s(wdest, MAX_PATH, L"\\");
+ wcscat_s(wdest, MAX_PATH, find_data.cFileName);
+ FindClose(find_handle);
+
+ /* Check the new target for existence */
+ cl_assert(INVALID_FILE_ATTRIBUTES == GetFileAttributesW(wdest));
+ }
+
+ if (FILE_ATTRIBUTE_DIRECTORY & source_attrs)
+ fs_copydir_helper(wsource, wdest);
+ else
+ cl_assert(CopyFileW(wsource, wdest, TRUE));
+}
+
+void
+cl_fs_cleanup(void)
+{
+ fs_rm(fixture_path(_clar_path, "*"));
+}
+
+#else
+static int
+shell_out(char * const argv[])
+{
+ int status;
+ pid_t pid;
+
+ pid = fork();
+
+ if (pid < 0) {
+ fprintf(stderr,
+ "System error: `fork()` call failed.\n");
+ exit(-1);
+ }
+
+ if (pid == 0) {
+ execv(argv[0], argv);
+ }
+
+ waitpid(pid, &status, 0);
+ return WEXITSTATUS(status);
+}
+
+static void
+fs_copy(const char *_source, const char *dest)
+{
+ char *argv[5];
+ char *source;
+ size_t source_len;
+
+ source = strdup(_source);
+ source_len = strlen(source);
+
+ if (source[source_len - 1] == '/')
+ source[source_len - 1] = 0;
+
+ argv[0] = "/bin/cp";
+ argv[1] = "-R";
+ argv[2] = source;
+ argv[3] = (char *)dest;
+ argv[4] = NULL;
+
+ cl_must_pass_(
+ shell_out(argv),
+ "Failed to copy test fixtures to sandbox"
+ );
+
+ free(source);
+}
+
+static void
+fs_rm(const char *source)
+{
+ char *argv[4];
+
+ argv[0] = "/bin/rm";
+ argv[1] = "-Rf";
+ argv[2] = (char *)source;
+ argv[3] = NULL;
+
+ cl_must_pass_(
+ shell_out(argv),
+ "Failed to cleanup the sandbox"
+ );
+}
+
+void
+cl_fs_cleanup(void)
+{
+ clar_unsandbox();
+ clar_sandbox();
+}
+#endif
diff --git a/tests-clar/clar/print.h b/tests-clar/clar/print.h
new file mode 100644
index 000000000..368016f2f
--- /dev/null
+++ b/tests-clar/clar/print.h
@@ -0,0 +1,60 @@
+
+static void clar_print_init(int test_count, int suite_count, const char *suite_names)
+{
+ (void)test_count;
+ printf("Loaded %d suites: %s\n", (int)suite_count, suite_names);
+ printf("Started\n");
+}
+
+static void clar_print_shutdown(int test_count, int suite_count, int error_count)
+{
+ (void)test_count;
+ (void)suite_count;
+ (void)error_count;
+
+ printf("\n\n");
+ clar_report_errors();
+}
+
+static void clar_print_error(int num, const struct clar_error *error)
+{
+ printf(" %d) Failure:\n", num);
+
+ printf("%s::%s [%s:%d]\n",
+ error->suite,
+ error->test,
+ error->file,
+ error->line_number);
+
+ printf(" %s\n", error->error_msg);
+
+ if (error->description != NULL)
+ printf(" %s\n", error->description);
+
+ printf("\n");
+ fflush(stdout);
+}
+
+static void clar_print_ontest(const char *test_name, int test_number, int failed)
+{
+ (void)test_name;
+ (void)test_number;
+ printf("%c", failed ? 'F' : '.');
+ fflush(stdout);
+}
+
+static void clar_print_onsuite(const char *suite_name, int suite_index)
+{
+ if (_clar.report_suite_names)
+ printf("\n%s", suite_name);
+
+ (void)suite_index;
+}
+
+static void clar_print_onabort(const char *msg, ...)
+{
+ va_list argp;
+ va_start(argp, msg);
+ vfprintf(stderr, msg, argp);
+ va_end(argp);
+}
diff --git a/tests-clar/clar/sandbox.h b/tests-clar/clar/sandbox.h
new file mode 100644
index 000000000..bed3011fe
--- /dev/null
+++ b/tests-clar/clar/sandbox.h
@@ -0,0 +1,127 @@
+static char _clar_path[4096];
+
+static int
+is_valid_tmp_path(const char *path)
+{
+ STAT_T st;
+
+ if (stat(path, &st) != 0)
+ return 0;
+
+ if (!S_ISDIR(st.st_mode))
+ return 0;
+
+ return (access(path, W_OK) == 0);
+}
+
+static int
+find_tmp_path(char *buffer, size_t length)
+{
+#ifndef _WIN32
+ static const size_t var_count = 4;
+ static const char *env_vars[] = {
+ "TMPDIR", "TMP", "TEMP", "USERPROFILE"
+ };
+
+ size_t i;
+
+ for (i = 0; i < var_count; ++i) {
+ const char *env = getenv(env_vars[i]);
+ if (!env)
+ continue;
+
+ if (is_valid_tmp_path(env)) {
+ strncpy(buffer, env, length);
+ return 0;
+ }
+ }
+
+ /* If the environment doesn't say anything, try to use /tmp */
+ if (is_valid_tmp_path("/tmp")) {
+ strncpy(buffer, "/tmp", length);
+ return 0;
+ }
+
+#else
+ if (GetTempPath((DWORD)length, buffer))
+ return 0;
+#endif
+
+ /* This system doesn't like us, try to use the current directory */
+ if (is_valid_tmp_path(".")) {
+ strncpy(buffer, ".", length);
+ return 0;
+ }
+
+ return -1;
+}
+
+static void clar_unsandbox(void)
+{
+ if (_clar_path[0] == '\0')
+ return;
+
+#ifdef _WIN32
+ chdir("..");
+#endif
+
+ fs_rm(_clar_path);
+}
+
+static int build_sandbox_path(void)
+{
+ const char path_tail[] = "clar_tmp_XXXXXX";
+ size_t len;
+
+ if (find_tmp_path(_clar_path, sizeof(_clar_path)) < 0)
+ return -1;
+
+ len = strlen(_clar_path);
+
+#ifdef _WIN32
+ { /* normalize path to POSIX forward slashes */
+ size_t i;
+ for (i = 0; i < len; ++i) {
+ if (_clar_path[i] == '\\')
+ _clar_path[i] = '/';
+ }
+ }
+#endif
+
+ if (_clar_path[len - 1] != '/') {
+ _clar_path[len++] = '/';
+ }
+
+ strncpy(_clar_path + len, path_tail, sizeof(_clar_path) - len);
+
+#if defined(__MINGW32__)
+ if (_mktemp(_clar_path) == NULL)
+ return -1;
+
+ if (mkdir(_clar_path, 0700) != 0)
+ return -1;
+#elif defined(_WIN32)
+ if (_mktemp_s(_clar_path, sizeof(_clar_path)) != 0)
+ return -1;
+
+ if (mkdir(_clar_path, 0700) != 0)
+ return -1;
+#else
+ if (mkdtemp(_clar_path) == NULL)
+ return -1;
+#endif
+
+ return 0;
+}
+
+static int clar_sandbox(void)
+{
+ if (_clar_path[0] == '\0' && build_sandbox_path() < 0)
+ return -1;
+
+ if (chdir(_clar_path) != 0)
+ return -1;
+
+ return 0;
+}
+