]> granicus.if.org Git - re2c/commitdiff
Added test for operations on character classes (addition and subtraction).
authorUlya Trofimovich <skvadrik@gmail.com>
Tue, 23 Jun 2015 20:44:13 +0000 (21:44 +0100)
committerUlya Trofimovich <skvadrik@gmail.com>
Tue, 23 Jun 2015 20:44:13 +0000 (21:44 +0100)
Test is built into a separate binary. Both test building and running
is triggered by `make check`.

re2c/Makefile.am
re2c/src/test/range/test-impl.h [new file with mode: 0644]
re2c/src/test/range/test.cc [new file with mode: 0644]
re2c/src/test/range/test.h [new file with mode: 0644]
re2c/src/util/range.h
re2c/src/util/static_assert.h [new file with mode: 0644]

index ff7e7030fc76f504be8887f2e5be04c6d8f4a7c4..bca40f8c4269d5bb3994479094604f2a019d4dbe 100644 (file)
@@ -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 (file)
index 0000000..61478f9
--- /dev/null
@@ -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 <uint8_t BITS>
+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 <uint8_t BITS>
+re2c::Range * add (uint32_t n1, uint32_t n2)
+{
+       return range<BITS> (n1 | n2);
+}
+
+template <uint8_t BITS>
+re2c::Range * sub (uint32_t n1, uint32_t n2)
+{
+       return range<BITS> (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 (file)
index 0000000..a602f79
--- /dev/null
@@ -0,0 +1,94 @@
+#include <stdio.h>
+
+#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<BITS> (i);
+                       re2c::Range * r2 = range<BITS> (j);
+                       ok |= diff (r1, r2, add<BITS> (i, j), re2c::Range::add (r1, r2), "U");
+                       ok |= diff (r1, r2, sub<BITS> (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 (file)
index 0000000..fb54635
--- /dev/null
@@ -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 <uint8_t BITS> re2c::Range * range (uint32_t n);
+template <uint8_t BITS> re2c::Range * add (uint32_t n1, uint32_t n2);
+template <uint8_t BITS> re2c::Range * sub (uint32_t n1, uint32_t n2);
+
+} // namespace re2c_test
+
+#endif // _RE2C_TEST_RANGE_TEST_
index 68d5d28c526147d9ff6f71bb47abdca3c7fc464c..90523833595d4901bfe0be3219369b2cc1ce2cc7 100644 (file)
@@ -4,6 +4,7 @@
 #include <assert.h>
 #include <stddef.h> // 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 <uint8_t> 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 (file)
index 0000000..c2a1327
--- /dev/null
@@ -0,0 +1,14 @@
+#ifndef _RE2C_UTIL_STATIC_ASSERT_
+#define _RE2C_UTIL_STATIC_ASSERT_
+
+namespace re2c {
+
+template<bool> struct static_assert_t;
+template<> struct static_assert_t<true> {};
+
+} // namespace re2c
+
+#define RE2C_STATIC_ASSERT(e) \
+    { re2c::static_assert_t<e> _; (void) _; }
+
+#endif // _RE2C_UTIL_STATIC_ASSERT_