diff options
Diffstat (limited to 'vespalib/src/apps/make_fixture_macros/make_fixture_macros.cpp')
-rw-r--r-- | vespalib/src/apps/make_fixture_macros/make_fixture_macros.cpp | 153 |
1 files changed, 153 insertions, 0 deletions
diff --git a/vespalib/src/apps/make_fixture_macros/make_fixture_macros.cpp b/vespalib/src/apps/make_fixture_macros/make_fixture_macros.cpp new file mode 100644 index 00000000000..52ff7faca1f --- /dev/null +++ b/vespalib/src/apps/make_fixture_macros/make_fixture_macros.cpp @@ -0,0 +1,153 @@ +// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. + +#include <stdio.h> +#include <stdlib.h> +#include <algorithm> + +void out(const char *str) { fprintf(stdout, "%s", str); } +void out_n(const char *str, int n) { fprintf(stdout, str, n); } +void out_nn(const char *str, int n) { fprintf(stdout, str, n, n); } +void out_nnn(const char *str, int n) { fprintf(stdout, str, n, n, n); } +void out_if(const char *str, bool cond) { if (cond) { out(str); } } +void out_opt(bool cond, const char *str1, const char *str2) { + if (cond) { + out(str1); + } else { + out(str2); + } +} +void out_list(const char *pre, const char *str, const char *sep, const char *post, int n, int x) { + out_if(pre, n > 0); + for (int i = 0; i < n; ++i) { + out_if(sep, i > 0); + switch (x) { + case 0: out(str); break; + case 1: out_n(str, i + 1); break; + case 2: out_nn(str, i + 1); break; + default: abort(); + } + } + out_if(post, n > 0); +} +void out_fff(int n) { + out_list("_", "F", "", "", n, 0); +} +void out_list_n(const char *pre, const char *str, const char *post, int n) { + out_list(pre, str, ", ", post, n, 1); +} +void out_list_nn(const char *pre, const char *str, const char *post, int n) { + out_list(pre, str, ", ", post, n, 2); +} + +void make_wrapper(int n) { + out_list_n(" template <", "typename F%d", "> \\\n", n); + out(" struct Test : vespalib::TestFixtureWrapper { \\\n"); + out_if(" F1 &f; \\\n", n == 1); + out_list("", " F%d &f%d; \\\n", "", "", n, 2); + out_list_nn(" Test(", "F%d &f%d_in", ") : ", n); + out_if("f(f1_in), ", n == 1); + out_list_nn("", "f%d(f%d_in)", " {} \\\n", n); + out(" virtual void test_entry_point(); \\\n"); + out(" }; \\\n"); +} + +void make_perform(int n) { + out(" Test"); + out_list_n("<", "F%d", ">", n); + out(" test"); + out_list_n("(", "f%d", ")", n); + out("; \\\n"); + out(" return runTest(test, threads); \\\n"); +} + +void make_dispatch(int n) { + for (int i = n; i > 0; --i) { + out_list_n(" template <", "typename F%d", "> \\\n", i); + out_n(" bool dispatch%d(", i); + out_list_nn("", "F%d &f%d", ", ", i - 1); + out_nn("F%d *_f%d_ptr_) { \\\n", i); + out_nnn(" std::unique_ptr<F%d> _f%d_ap_(_f%d_ptr_); \\\n", i); + out_nnn(" F%d &f%d = *_f%d_ap_; \\\n", i); + out_if(" size_t num_threads(threads); (void) num_threads; \\\n", i < n); + if (i < n) { + out_n(" return dispatch%d(", i + 1); + out_list_n("", "f%d", ", ", i); + out_n("new fixture%d); \\\n", i + 1); + } else { + make_perform(n); + } + out(" } \\\n"); + } +} + +void make_macro_impl(int n) { + fprintf(stdout, "// common test macro implementation for %d test fixtures BEGIN\n\n", n); + out("#define TEST"); + out_fff(n); + out("_IMPL(name, ignore, threads"); + out_list_n(", ", "fixture%d", "", n); + out(") \\\n"); + out("namespace { \\\n"); + out("struct TEST_CAT(TestKitHook, __LINE__) : vespalib::TestHook { \\\n"); + out(" TEST_CAT(TestKitHook, __LINE__)() : vespalib::TestHook(__FILE__, name, ignore) {} \\\n"); + make_wrapper(n); + make_dispatch(n); + out(" virtual bool run() { \\\n"); + out(" TEST_STATE(name); \\\n"); + out_if(" size_t num_threads(threads); (void) num_threads; \\\n", n > 0); + if (n > 0) { + out(" return dispatch1(new fixture1); \\\n"); + } else { + make_perform(0); + } + out(" } \\\n"); + out("}; \\\n"); + out("TEST_CAT(TestKitHook, __LINE__) TEST_CAT(testKitHook, __LINE__); \\\n"); + out("} /* end of unnamed namespace */ \\\n"); + out_list_n("template <", "typename F%d", "> \\\n", n); + out("void TEST_CAT(TestKitHook, __LINE__)::Test"); + out_list_n("<", "F%d", ">", n); + out("::test_entry_point()\n"); + fprintf(stdout, "\n// common test macro implementation for %d test fixtures END\n\n", n); +} + +void make_macro_wire(int n) { + fprintf(stdout, "// test macro variants for %d test fixtures BEGIN\n\n", n); + for (int ignore = 0; ignore < 2; ++ignore) { + for (int mt = 0; mt < 2; ++mt) { + out("#define "); + out_if("IGNORE_", ignore); + out("TEST"); + out_if("_MT", mt); + out_fff(n); + out("(name"); + out_if(", threads", mt); + out_list_n(", ", "fixture%d", "", n); + out(") TEST"); + out_fff(n); + out("_IMPL(name"); + out_opt(ignore, ", true", ", false"); + out_opt(mt, ", threads", ", 1"); + out_list_n(", ", "fixture%d", "", n); + out(")\n"); + } + } + fprintf(stdout, "\n// test macro variants for %d test fixtures END\n\n", n); +} + +int main(int argc, char **argv) { + if (argc != 2) { + fprintf(stderr, "usage: %s <N>\n", argv[0]); + fprintf(stderr, " produce macros for up to N (minimum 3) test fixtures\n"); + return 1; + } + int n = std::max(3, atoi(argv[1])); + fprintf(stdout, "// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.\n"); + fprintf(stdout, "// macros for up to %d test fixtures, generated by " + "vespalib/testkit/make_fixture_macros\n\n", n); + for (int i = 0; i <= n; ++i) { + make_macro_impl(i); + make_macro_wire(i); + } + return 0; +} |