#!/usr/bin/env python # encoding: utf-8 from __future__ import print_function copyright = ''' // Copyright © 2014 Ben Longbons // // This file is part of The Mana World (Athena server) // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program. If not, see . ''' import glob import itertools import os import subprocess import sys import tempfile import protocol error = False def eprint(s): print('Error:', s, file=sys.stderr) def get_classes_from_file(a): global error d = {} execfile(a, d) for (k, v) in sorted(d.items()): try: name = v.name except AttributeError: if hasattr(v, 'enabled') and hasattr(v, 'tests'): name = 'None::' + k else: continue else: if name.split('::')[-1] != k: eprint('Mismatch: class %s is for %s' % (k, name)) error = True if not v.enabled: eprint('Disabled: %s' % name) continue try: tests = v.tests except AttributeError: eprint('Unimplemented tests for %s' % name) error = True continue extra = getattr(v, 'test_extra', '').rstrip(' ') yield (k, tests, extra) def c_quote(s): s = s.replace('\\', '\\\\') s = s.replace('\n', '\\n') s = s.replace('"', '\\"') return '"' + s + '"' def gen_test(name, expr, expected, w): print('static', file=w) print('void %s()' % name, file=w) print('{', file=w) print(' auto&& value = %s;' % expr, file=w) print(' const char *expected = %s;' % c_quote(expected), file=w) print(' do_breakpoint(value, expected);', file=w) print('}', file=w) def main(args): outdir = args[0] args = args[1:] for g in glob.glob(os.path.join(outdir, '*.[ch]pp')): os.rename(g, g + '.old') for a in args: names = [] basename, ext = os.path.splitext(a) assert ext == '.py' newbase = basename.split('src/')[1].replace('/', '-') out = os.path.join(outdir, newbase + '.cpp') with protocol.OpenWrite(out) as w: print('// %s.cpp - generated by %s from %s' % (newbase, __file__, a), file=w) print(copyright, file=w) print('#include ', file=w) print('// just mention "fwd.hpp" and "../poison.hpp" to make formatter happy', file=w) print('namespace tmwa', file=w) print('{', file=w) print(' void do_nothing_asan_is_funny_global_constructor();', file=w) print(' void do_nothing_asan_is_funny_global_constructor() {}', file=w) print('} // namespace tmwa', file=w) print(file=w) print('template', file=w) print('__attribute__((noinline))', file=w) print('void do_breakpoint(const T& value, const char *expected)', file=w) print('{', file=w) print(' (void)value;', file=w) print(' (void)expected;', file=w) print(' if (!expected) printf("printer test: %p = %s\\n", &value, expected);', file=w) print('}', file=w) print(file=w) print('// Tests from', a, file=w) header = basename + '.hpp' print('#include "%s"' % header, file=w) for (k, tests, extra) in get_classes_from_file(a): print(file=w) print('// Tests for', k, file=w) print(extra, file=w) for (i, (expr, expected)) in enumerate(tests): name = 'testset_%s_subtest_%d' % (k, i) gen_test(name, expr, expected, w) names.append(name) print('int main()', file=w) print('{', file=w) for n in names: print(' %s();' % n, file=w) print('}', file=w) for g in glob.glob(os.path.join(outdir, '*.old')): print('Obsolete: %s' % g) os.remove(g) if error and not os.getenv('TMWA_FORCE_GENERATE'): sys.exit(1) if __name__ == '__main__': main(sys.argv[1:])