From 6dbe52d05d15dbf6044f7b762a3317be02e5cde6 Mon Sep 17 00:00:00 2001 From: Ulya Trofimovich Date: Tue, 23 Jun 2015 21:44:13 +0100 Subject: [PATCH] Added test for operations on character classes (addition and subtraction). Test is built into a separate binary. Both test building and running is triggered by `make check`. --- re2c/Makefile.am | 38 ++++++++----- re2c/src/test/range/test-impl.h | 50 ++++++++++++++++++ re2c/src/test/range/test.cc | 94 +++++++++++++++++++++++++++++++++ re2c/src/test/range/test.h | 16 ++++++ re2c/src/util/range.h | 4 ++ re2c/src/util/static_assert.h | 14 +++++ 6 files changed, 204 insertions(+), 12 deletions(-) create mode 100644 re2c/src/test/range/test-impl.h create mode 100644 re2c/src/test/range/test.cc create mode 100644 re2c/src/test/range/test.h create mode 100644 re2c/src/util/static_assert.h diff --git a/re2c/Makefile.am b/re2c/Makefile.am index ff7e7030..bca40f8c 100644 --- a/re2c/Makefile.am +++ b/re2c/Makefile.am @@ -61,6 +61,7 @@ SRC_HDR = \ src/util/local_increment.h \ src/util/range.h \ src/util/smart_ptr.h \ + src/util/static_assert.h \ src/util/substr.h \ src/util/uniq_vector.h \ src/util/wrap_iterator.h @@ -166,8 +167,6 @@ CLEANFILES = \ $(AUTOGEN) \ $(DOC) -TESTS = run_tests.sh - # rule has side effects: # - autogenerated header in build directory # - bootstrap files in source directory, must manually prepend $(top_srcdir) @@ -202,16 +201,6 @@ bootstrap: all rm $(AUTOGEN_SCANNER) make all -.PHONY: tests -tests: all $(TESTS) - ./$(TESTS) -.PHONY: vtests -vtests: all $(TESTS) - ./$(TESTS) --valgrind -.PHONY: wtests -wtests: all $(TESTS) - ./$(TESTS) --wine -j1 - .PHONY: docs if REBUILD_DOCS docs: $(DOC_MAN) $(DOC_HTML) @@ -235,3 +224,28 @@ $(DOC_HTML): $(BOOTSTRAP_DOC_HTML) endif all-local: docs + +# tests +TST_SUITE = run_tests.sh +.PHONY: tests +tests: all $(TST_SUITE) + ./$(TST_SUITE) +.PHONY: vtests +vtests: all $(TST_SUITE) + ./$(TST_SUITE) --valgrind +.PHONY: wtests +wtests: all $(TST_SUITE) + ./$(TST_SUITE) --wine -j1 + +TST_RANGE = testrange +testrange_SOURCES = \ + src/test/range/test-impl.h \ + src/test/range/test.cc \ + src/test/range/test.h \ + src/util/range.cc\ + src/util/range.h \ + src/util/static_assert.h + +check_PROGRAMS = $(TST_RANGE) + +TESTS = $(TST_SUITE) $(check_PROGRAMS) diff --git a/re2c/src/test/range/test-impl.h b/re2c/src/test/range/test-impl.h new file mode 100644 index 00000000..61478f9f --- /dev/null +++ b/re2c/src/test/range/test-impl.h @@ -0,0 +1,50 @@ +#ifndef _RE2C_TEST_RANGE_TEST_IMPL_ +#define _RE2C_TEST_RANGE_TEST_IMPL_ + +#include "src/test/range/test.h" +#include "src/util/range.h" +#include "src/util/static_assert.h" + +namespace re2c_test { + +static inline bool bit_set (uint32_t n, uint8_t bit) +{ + return n & (1 << bit); +} + +template +re2c::Range * range (uint32_t n) +{ + RE2C_STATIC_ASSERT (BITS <= 31); + + re2c::Range * r = NULL; + re2c::Range ** p = &r; + for (uint32_t i = 0; i < BITS; ++i) + { + for (; i < BITS && !bit_set (n, i); ++i); + if (i == BITS && !bit_set (n, BITS - 1)) + { + break; + } + const uint32_t lb = i; + for (; i < BITS && bit_set (n, i); ++i); + re2c::Range::append (p, lb, i); + } + return r; +} + +template +re2c::Range * add (uint32_t n1, uint32_t n2) +{ + return range (n1 | n2); +} + +template +re2c::Range * sub (uint32_t n1, uint32_t n2) +{ + return range (n1 & ~n2); +} + +} // namespace re2c_test + +#endif // _RE2C_TEST_RANGE_TEST_IMPL_ diff --git a/re2c/src/test/range/test.cc b/re2c/src/test/range/test.cc new file mode 100644 index 00000000..a602f79d --- /dev/null +++ b/re2c/src/test/range/test.cc @@ -0,0 +1,94 @@ +#include + +#include "src/test/range/test.h" +#include "src/test/range/test-impl.h" + +namespace re2c_test { + +static bool equal (const re2c::Range * r1, const re2c::Range * r2) +{ + for (; r1 && r2; r1 = r1->next (), r2 = r2->next ()) + { + if (r1->lower () != r2->lower () + || r1->upper () != r2->upper ()) + { + return false; + } + } + return !r1 && !r2; +} + +static void show (const re2c::Range * r) +{ + if (!r) + { + fprintf (stderr, "[]"); + } + for (; r; r = r->next ()) + { + const uint32_t l = r->lower (); + const uint32_t u = r->upper () - 1; + if (l < u) + { + fprintf (stderr, "[%X-%X]", l, u); + } + else + { + fprintf (stderr, "[%X]", l); + } + } +} + +static int32_t diff + ( const re2c::Range * r1 + , const re2c::Range * r2 + , const re2c::Range * op1 + , const re2c::Range * op2 + , const char * op) +{ + if (equal (op1, op2)) + { + return 0; + } + else + { + fprintf (stderr, "%s error: ", op); + show (r1); + fprintf (stderr, " %s ", op); + show (r2); + fprintf (stderr, " ====> "); + show (op2); + fprintf (stderr, " =/= "); + show (op1); + fprintf (stderr, "\n"); + return 1; + } +} + +static int32_t test () +{ + int32_t ok = 0; + + static const uint32_t BITS = 8; + static const uint32_t N = 1u << BITS; + for (uint32_t i = 0; i <= N; ++i) + { + for (uint32_t j = 0; j <= N; ++j) + { + re2c::Range * r1 = range (i); + re2c::Range * r2 = range (j); + ok |= diff (r1, r2, add (i, j), re2c::Range::add (r1, r2), "U"); + ok |= diff (r1, r2, sub (i, j), re2c::Range::sub (r1, r2), "D"); + re2c::Range::vFreeList.clear (); + } + } + + return ok; +} + +} // namespace re2c_test + +int main () +{ + return re2c_test::test (); +} diff --git a/re2c/src/test/range/test.h b/re2c/src/test/range/test.h new file mode 100644 index 00000000..fb546351 --- /dev/null +++ b/re2c/src/test/range/test.h @@ -0,0 +1,16 @@ +#ifndef _RE2C_TEST_RANGE_TEST_ +#define _RE2C_TEST_RANGE_TEST_ + +#include "src/util/c99_stdint.h" + +namespace re2c { class Range; } + +namespace re2c_test { + +template re2c::Range * range (uint32_t n); +template re2c::Range * add (uint32_t n1, uint32_t n2); +template re2c::Range * sub (uint32_t n1, uint32_t n2); + +} // namespace re2c_test + +#endif // _RE2C_TEST_RANGE_TEST_ diff --git a/re2c/src/util/range.h b/re2c/src/util/range.h index 68d5d28c..90523833 100644 --- a/re2c/src/util/range.h +++ b/re2c/src/util/range.h @@ -4,6 +4,7 @@ #include #include // NULL +#include "src/test/range/test.h" #include "src/util/c99_stdint.h" #include "src/util/forbid_copy.h" #include "src/util/free_list.h" @@ -53,6 +54,9 @@ private: static void append_overlapping (Range * & head, Range * & tail, const Range * r); static void append (Range ** & ptail, uint32_t l, uint32_t u); + // test addition and subtraction + template friend Range * re2c_test::range (uint32_t n); + FORBID_COPY (Range); }; diff --git a/re2c/src/util/static_assert.h b/re2c/src/util/static_assert.h new file mode 100644 index 00000000..c2a1327d --- /dev/null +++ b/re2c/src/util/static_assert.h @@ -0,0 +1,14 @@ +#ifndef _RE2C_UTIL_STATIC_ASSERT_ +#define _RE2C_UTIL_STATIC_ASSERT_ + +namespace re2c { + +template struct static_assert_t; +template<> struct static_assert_t {}; + +} // namespace re2c + +#define RE2C_STATIC_ASSERT(e) \ + { re2c::static_assert_t _; (void) _; } + +#endif // _RE2C_UTIL_STATIC_ASSERT_ -- 2.40.0