diff --git a/tests/construct_tests.c b/tests/construct_tests.c index 446df7a..cae357a 100644 --- a/tests/construct_tests.c +++ b/tests/construct_tests.c @@ -6,6 +6,30 @@ #include "construct.h" #include "testing.h" +static bool +accepts_from_state(const fsa_t *nfa, int state_id, const char *input) +{ + const fsa_state_t *state = &nfa->states[state_id]; + if ('\0' == *input) + return state->final; + + for (int i = 0; i < state->count; ++i) { + if (EPSILON == state->rules[i].input + && accepts_from_state(nfa, state->rules[i].next, input)) + return true; + if (*input == state->rules[i].input + && accepts_from_state(nfa, state->rules[i].next, input + 1)) + return true; + } + + return false; +} + +static bool accepts(const fsa_t *nfa, const char *input) +{ + return accepts_from_state(nfa, nfa->initial, input); +} + static void test_empty_expression(void) { regex_term_t *terms = malloc(1 * sizeof(regex_term_t)); @@ -20,9 +44,7 @@ static void test_empty_expression(void) fsa_t fsa; construct(®ex, &fsa); - ASSERT_EQ(1, fsa.count); - ASSERT_TRUE(fsa.states[fsa.initial].final); - ASSERT_EQ(0, fsa.states[fsa.initial].count); + ASSERT_TRUE(accepts(&fsa, "")); regex_free(®ex); fsa_free(&fsa); @@ -43,14 +65,8 @@ static void test_literal_expression(void) fsa_t fsa; construct(®ex, &fsa); - const fsa_state_t *initial = &fsa.states[fsa.initial]; - ASSERT_EQ(2, fsa.count); - ASSERT_EQ(1, initial->count); - ASSERT_EQ('a', initial->rules[0].input); - - const int next = initial->rules[0].next; - ASSERT_TRUE(fsa.states[next].final); - ASSERT_EQ(0, fsa.states[next].count); + ASSERT_TRUE(accepts(&fsa, "a")); + ASSERT_FALSE(accepts(&fsa, "b")); regex_free(®ex); fsa_free(&fsa); @@ -73,30 +89,10 @@ static void test_sequence(void) fsa_t fsa; construct(®ex, &fsa); - int next = fsa.initial; - const fsa_state_t *state; - - state = &fsa.states[next]; - ASSERT_FALSE(state->final); - ASSERT_EQ(1, state->count); - ASSERT_EQ('a', state->rules[0].input); - next = state->rules[0].next; - - state = &fsa.states[next]; - ASSERT_FALSE(state->final); - ASSERT_EQ(1, state->count); - ASSERT_EQ('b', state->rules[0].input); - next = state->rules[0].next; - - state = &fsa.states[next]; - ASSERT_FALSE(state->final); - ASSERT_EQ(1, state->count); - ASSERT_EQ('c', state->rules[0].input); - next = state->rules[0].next; - - state = &fsa.states[next]; - ASSERT_TRUE(state->final); - ASSERT_EQ(0, state->count); + ASSERT_TRUE(accepts(&fsa, "abc")); + ASSERT_FALSE(accepts(&fsa, "a")); + ASSERT_FALSE(accepts(&fsa, "ab")); + ASSERT_FALSE(accepts(&fsa, "d")); regex_free(®ex); fsa_free(&fsa); @@ -120,13 +116,10 @@ static void test_union(void) fsa_t fsa; construct(®ex, &fsa); - const fsa_state_t *initial = &fsa.states[fsa.initial]; - ASSERT_EQ(3, initial->count); - for (int i = 0; i < 3; ++i) { - ASSERT_EQ(literals[i], initial->rules[i].input); - const int next = initial->rules[i].next; - ASSERT_TRUE(fsa.states[next].final); - } + ASSERT_TRUE(accepts(&fsa, "a")); + ASSERT_TRUE(accepts(&fsa, "b")); + ASSERT_TRUE(accepts(&fsa, "c")); + ASSERT_FALSE(accepts(&fsa, "d")); regex_free(®ex); fsa_free(&fsa); @@ -146,11 +139,10 @@ static void test_star(void) fsa_t fsa; construct(®ex, &fsa); - const fsa_state_t *initial = &fsa.states[fsa.initial]; - ASSERT_TRUE(initial->final); - ASSERT_EQ(1, initial->count); - ASSERT_EQ('a', initial->rules[0].input); - ASSERT_EQ(fsa.initial, initial->rules[0].next); + ASSERT_TRUE(accepts(&fsa, "")); + ASSERT_TRUE(accepts(&fsa, "a")); + ASSERT_TRUE(accepts(&fsa, "aaaaaa")); + ASSERT_FALSE(accepts(&fsa, "b")); regex_free(®ex); fsa_free(&fsa); @@ -179,14 +171,8 @@ static void test_subexpression(void) fsa_t fsa; construct(®ex, &fsa); - const fsa_state_t *initial = &fsa.states[fsa.initial]; - ASSERT_EQ(2, fsa.count); - ASSERT_EQ(1, initial->count); - ASSERT_EQ('a', initial->rules[0].input); - - const int next = initial->rules[0].next; - ASSERT_TRUE(fsa.states[next].final); - ASSERT_EQ(0, fsa.states[next].count); + ASSERT_TRUE(accepts(&fsa, "a")); + ASSERT_FALSE(accepts(&fsa, "b")); regex_free(®ex); fsa_free(&fsa);