From ac6bd3a677d483df4af36b50974d83edbf11885d Mon Sep 17 00:00:00 2001 From: Anthony Pesch Date: Sat, 17 Dec 2016 01:31:50 -0800 Subject: [PATCH] added TEST macro reenabled test_list_* fixed bug when adding an uninitialized list_node --- CMakeLists.txt | 3 +- src/core/list.c | 30 ++-- test/retest.c | 13 ++ test/retest.h | 26 +++ test/test_dead_code_elimination_pass.c | 5 +- test/test_intrusive_list.cc | 218 ------------------------ test/test_list.c | 144 ++++++++++++++++ test/test_list.cc | 163 ------------------ test/test_load_store_elimination_pass.c | 5 +- 9 files changed, 200 insertions(+), 407 deletions(-) create mode 100644 test/retest.h delete mode 100644 test/test_intrusive_list.cc create mode 100644 test/test_list.c delete mode 100644 test/test_list.cc diff --git a/CMakeLists.txt b/CMakeLists.txt index 08599ca3..ef13ce91 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -408,10 +408,9 @@ if(BUILD_TESTS) ## build test binary set(RETEST_SOURCES test/test_dead_code_elimination_pass.c + test/test_list.c test/test_load_store_elimination_pass.c #test/test_interval_tree.cc - #test/test_intrusive_list.cc - #test/test_list.cc #test/test_minmax_heap.cc #test/test_sh4.cc #${asm_inc} diff --git a/src/core/list.c b/src/core/list.c index 0b5c4a08..6364ffc2 100644 --- a/src/core/list.c +++ b/src/core/list.c @@ -10,30 +10,24 @@ void list_add(struct list *list, struct list_node *n) { void list_add_after(struct list *list, struct list_node *after, struct list_node *n) { - if (!after) { - if (list->head) { - n->next = list->head; - n->next->prev = n; - } - - list->head = n; - } else { - struct list_node *next = after->next; + struct list_node *before = NULL; + if (after) { + before = after->next; n->prev = after; n->prev->next = n; - - if (next) { - n->next = next; - n->next->prev = n; - } else { - n->next = NULL; - } + } else { + before = list->head; + list->head = n; + list->head->prev = NULL; } - /* no need to check list->tail == NULL, in that case after would be NULL */ - if (list->tail == after) { + if (before) { + n->next = before; + n->next->prev = n; + } else { list->tail = n; + list->tail->next = NULL; } } diff --git a/test/retest.c b/test/retest.c index dff68db9..a33513a0 100644 --- a/test/retest.c +++ b/test/retest.c @@ -1,5 +1,18 @@ #include +#include "retest.h" + +static struct list tests; + +void test_register(struct test *test) { + list_add(&tests, &test->it); +} int main() { + list_for_each_entry(test, &tests, struct test, it) { + LOG_INFO("[%s]", test->name); + test->run(); + LOG_INFO(ANSI_COLOR_GREEN "OK" ANSI_COLOR_RESET); + } + return EXIT_SUCCESS; } diff --git a/test/retest.h b/test/retest.h new file mode 100644 index 00000000..4655768c --- /dev/null +++ b/test/retest.h @@ -0,0 +1,26 @@ +#ifndef RETEST_H +#define RETEST_H + +#include "core/assert.h" +#include "core/constructor.h" +#include "core/list.h" + +typedef void (*test_callback_t)(); + +struct test { + const char *name; + test_callback_t run; + struct list_node it; +}; + +#define TEST(name) \ + static void name(); \ + CONSTRUCTOR(TEST_REGISTER_##name) { \ + static struct test test = {#name, &name, {0}}; \ + test_register(&test); \ + } \ + void name() + +void test_register(struct test *test); + +#endif diff --git a/test/test_dead_code_elimination_pass.c b/test/test_dead_code_elimination_pass.c index ef20cb0d..d9f42724 100644 --- a/test/test_dead_code_elimination_pass.c +++ b/test/test_dead_code_elimination_pass.c @@ -1,12 +1,11 @@ -#include "core/assert.h" -#include "core/constructor.h" #include "jit/ir/ir.h" #include "jit/ir/passes/dead_code_elimination_pass.h" +#include "retest.h" static uint8_t ir_buffer[1024 * 1024]; static char scratch_buffer[1024 * 1024]; -CONSTRUCTOR(test_dead_code_elimination_pass) { +TEST(test_dead_code_elimination_pass) { static const char input_str[] = "i32 %0 = load_context i32 0xbc\n" "i32 %1 = load_slow i32 %0\n" diff --git a/test/test_intrusive_list.cc b/test/test_intrusive_list.cc deleted file mode 100644 index ed7578c6..00000000 --- a/test/test_intrusive_list.cc +++ /dev/null @@ -1,218 +0,0 @@ -#include - -extern "C" { -#include "core/arena.h" -#include "core/intrusive_list.h" -} - -using namespace re; - -struct Person : public IntrusiveListNode { - Person(const char *name) : name(name) {} - - const char *name; -}; - -struct PersonComparator { - bool operator()(const Person *a, const Person *b) const { - // sort is descending order - return strcmp(b->name, a->name) < 0; - } -}; - -class IntrusiveTestEmptySet : public ::testing::Test { - public: - IntrusiveTestEmptySet() : arena(1024) {} - - Arena arena; - IntrusiveList people; -}; - -class IntrusiveTestABCSet : public ::testing::Test { - public: - IntrusiveTestABCSet() : arena(1024) { - aaa = new (arena.Alloc()) Person("aaa"); - people.Append(aaa); - - bbb = new (arena.Alloc()) Person("bbb"); - people.Append(bbb); - - ccc = new (arena.Alloc()) Person("ccc"); - people.Append(ccc); - } - - Arena arena; - IntrusiveList people; - Person *aaa, *bbb, *ccc; -}; - -// add tests -TEST_F(IntrusiveTestEmptySet, AddSingle) { - Person *aaa = new (arena.Alloc()) Person("aaa"); - people.Append(aaa); - - ASSERT_EQ(aaa, people.head()); - ASSERT_EQ(aaa, *people.begin()); - - ASSERT_EQ(aaa, people.tail()); - ASSERT_EQ(aaa, *(--people.end())); -} - -TEST_F(IntrusiveTestEmptySet, Prepend) { - Person *aaa = new (arena.Alloc()) Person("aaa"); - people.Prepend(aaa); - - ASSERT_EQ(aaa, people.head()); - ASSERT_EQ(NULL, people.head()->prev()); - ASSERT_EQ(NULL, people.head()->next()); - ASSERT_EQ(aaa, *people.begin()); - - Person *bbb = new (arena.Alloc()) Person("bbb"); - people.Prepend(bbb); - - ASSERT_EQ(aaa, people.head()->next()); - - ASSERT_EQ(aaa, people.tail()); - ASSERT_EQ(bbb, people.tail()->prev()); - ASSERT_EQ(NULL, people.tail()->next()); - ASSERT_EQ(aaa, *(--people.end())); -} - -TEST_F(IntrusiveTestEmptySet, Append) { - Person *aaa = new (arena.Alloc()) Person("aaa"); - people.Append(aaa); - - ASSERT_EQ(aaa, people.head()); - ASSERT_EQ(NULL, people.head()->prev()); - ASSERT_EQ(NULL, people.head()->next()); - ASSERT_EQ(aaa, *people.begin()); - - Person *bbb = new (arena.Alloc()) Person("bbb"); - people.Append(bbb); - - ASSERT_EQ(bbb, people.head()->next()); - - ASSERT_EQ(bbb, people.tail()); - ASSERT_EQ(aaa, people.tail()->prev()); - ASSERT_EQ(NULL, people.tail()->next()); - ASSERT_EQ(bbb, *(--people.end())); -} - -// remove tests -TEST_F(IntrusiveTestABCSet, RemoveHead) { - people.Remove(aaa); - - ASSERT_EQ(bbb, people.head()); - ASSERT_EQ(NULL, people.head()->prev()); - ASSERT_EQ(ccc, people.head()->next()); - ASSERT_EQ(bbb, *people.begin()); - - ASSERT_EQ(ccc, people.tail()); - ASSERT_EQ(bbb, people.tail()->prev()); - ASSERT_EQ(NULL, people.tail()->next()); - ASSERT_EQ(ccc, *(--people.end())); -} - -TEST_F(IntrusiveTestABCSet, RemoveMiddle) { - people.Remove(bbb); - - ASSERT_EQ(aaa, people.head()); - ASSERT_EQ(NULL, people.head()->prev()); - ASSERT_EQ(ccc, people.head()->next()); - ASSERT_EQ(aaa, *people.begin()); - - ASSERT_EQ(ccc, people.tail()); - ASSERT_EQ(aaa, people.tail()->prev()); - ASSERT_EQ(NULL, people.tail()->next()); - ASSERT_EQ(ccc, *(--people.end())); -} - -TEST_F(IntrusiveTestABCSet, RemoveTail) { - people.Remove(ccc); - - ASSERT_EQ(aaa, people.head()); - ASSERT_EQ(NULL, people.head()->prev()); - ASSERT_EQ(bbb, people.head()->next()); - ASSERT_EQ(aaa, *people.begin()); - - ASSERT_EQ(bbb, people.tail()); - ASSERT_EQ(aaa, people.tail()->prev()); - ASSERT_EQ(NULL, people.tail()->next()); - ASSERT_EQ(bbb, *(--people.end())); -} - -TEST_F(IntrusiveTestABCSet, Clear) { - people.Clear(); - - ASSERT_EQ(NULL, people.head()); - ASSERT_EQ(NULL, people.tail()); -} - -// iterator tests -TEST_F(IntrusiveTestEmptySet, EmptyIterate) { - ASSERT_EQ(people.begin(), people.end()); -} - -TEST_F(IntrusiveTestABCSet, ForwardIterator) { - auto it = people.begin(); - ASSERT_EQ(aaa, *it); - ASSERT_EQ(bbb, *(++it)); - ASSERT_EQ(ccc, *(++it)); - ASSERT_EQ(people.end(), ++it); -} - -TEST_F(IntrusiveTestABCSet, ForwardIteratorReverse) { - auto it = people.end(); - ASSERT_EQ(ccc, *(--it)); - ASSERT_EQ(bbb, *(--it)); - ASSERT_EQ(aaa, *(--it)); - ASSERT_EQ(people.begin(), it); -} - -TEST_F(IntrusiveTestABCSet, ReverseIterator) { - auto it = people.rbegin(); - ASSERT_EQ(ccc, *it); - ASSERT_EQ(bbb, *(++it)); - ASSERT_EQ(aaa, *(++it)); - ASSERT_EQ(people.rend(), ++it); -} - -TEST_F(IntrusiveTestABCSet, ReverseIteratorReverse) { - auto it = people.rend(); - ASSERT_EQ(aaa, *(--it)); - ASSERT_EQ(bbb, *(--it)); - ASSERT_EQ(ccc, *(--it)); - ASSERT_EQ(people.rbegin(), it); -} - -TEST_F(IntrusiveTestABCSet, ValidOnInsert) { - auto it = people.begin(); - ASSERT_EQ(aaa, *it); - - Person *zzz = new (arena.Alloc()) Person("zzz"); - people.Prepend(zzz); - ASSERT_EQ(aaa, *it); -} - -TEST_F(IntrusiveTestABCSet, ValidOnRemove) { - auto it = ++people.begin(); - ASSERT_EQ(bbb, *it); - - people.Remove(aaa); - ASSERT_EQ(bbb, *it); -} - -// sort tests -TEST_F(IntrusiveTestEmptySet, EmptySort) { - people.Sort(PersonComparator()); - ASSERT_EQ(NULL, people.head()); - ASSERT_EQ(NULL, people.tail()); -} - -TEST_F(IntrusiveTestABCSet, Sort) { - people.Sort(PersonComparator()); - auto it = people.begin(); - ASSERT_STREQ("ccc", (it++)->name); - ASSERT_STREQ("bbb", (it++)->name); - ASSERT_STREQ("aaa", (it++)->name); -} diff --git a/test/test_list.c b/test/test_list.c new file mode 100644 index 00000000..0b8b658f --- /dev/null +++ b/test/test_list.c @@ -0,0 +1,144 @@ +#include "core/list.h" +#include "retest.h" + +struct person { + const char *name; + struct list_node it; +}; + +static struct person aaa = {"aaa", {0}}; +static struct person bbb = {"bbb", {0}}; +static struct person ccc = {"ccc", {0}}; + +static void init_people(struct list *people) { + list_add(people, &aaa.it); + list_add(people, &bbb.it); + list_add(people, &ccc.it); +} + +static void validate_people(struct list *people, struct person **expected, + int num_expected) { + /* validate iterating forward */ + { + int n = 0; + + list_for_each_entry(person, people, struct person, it) { + struct person *expected_person = expected[n]; + CHECK_STREQ(person->name, expected_person->name); + n++; + } + + CHECK_EQ(n, num_expected); + } + + /* validate iterating in reverse */ + { + int n = 0; + + list_for_each_entry_reverse(person, people, struct person, it) { + struct person *expected_person = expected[num_expected - n - 1]; + CHECK_STREQ(person->name, expected_person->name); + n++; + } + + CHECK_EQ(n, num_expected); + } +} + +/* add tests */ +TEST(test_intrusive_list_append) { + struct list people = {0}; + list_add(&people, &aaa.it); + list_add(&people, &bbb.it); + list_add(&people, &ccc.it); + + struct person *expected[] = {&aaa, &bbb, &ccc}; + int num_expected = array_size(expected); + validate_people(&people, expected, num_expected); +} + +TEST(test_intrusive_list_prepend) { + struct list people = {0}; + list_add_after(&people, NULL, &aaa.it); + list_add_after(&people, NULL, &bbb.it); + list_add_after(&people, NULL, &ccc.it); + + struct person *expected[] = {&ccc, &bbb, &aaa}; + int num_expected = array_size(expected); + validate_people(&people, expected, num_expected); +} + +/* remove tests */ +TEST(test_intrusive_list_remove_head) { + struct list people = {0}; + init_people(&people); + + list_remove(&people, &aaa.it); + + struct person *expected[] = {&bbb, &ccc}; + int num_expected = array_size(expected); + validate_people(&people, expected, num_expected); +} + +TEST(test_intrusive_list_remove_middle) { + struct list people = {0}; + init_people(&people); + + list_remove(&people, &bbb.it); + + struct person *expected[] = {&aaa, &ccc}; + int num_expected = array_size(expected); + validate_people(&people, expected, num_expected); +} + +TEST(test_intrusive_list_remove_tail) { + struct list people = {0}; + init_people(&people); + + list_remove(&people, &ccc.it); + + struct person *expected[] = {&aaa, &bbb}; + int num_expected = array_size(expected); + validate_people(&people, expected, num_expected); +} + +TEST(test_intrusive_list_remove_clear) { + struct list people = {0}; + init_people(&people); + + CHECK(!list_empty(&people)); + + list_for_each(&people, it) { + list_remove(&people, it); + } + + CHECK(list_empty(&people)); +} + +/* sort tests */ +int person_sort(const struct list_node *list_lhs, + const struct list_node *list_rhs) { + const struct person *lhs = list_entry(list_lhs, const struct person, it); + const struct person *rhs = list_entry(list_rhs, const struct person, it); + /* sort in descending order */ + return strcmp(rhs->name, lhs->name); +} + +TEST(test_intrusive_list_empty_sort) { + struct list people = {0}; + + list_sort(&people, &person_sort); + + CHECK(list_empty(&people)); +} + +TEST(test_intrusive_list_sort) { + struct list people = {0}; + init_people(&people); + + list_sort(&people, &person_sort); + + struct person *expected[] = {&ccc, &bbb, &aaa}; + int num_expected = array_size(expected); + validate_people(&people, expected, num_expected); +} diff --git a/test/test_list.cc b/test/test_list.cc deleted file mode 100644 index 353dc348..00000000 --- a/test/test_list.cc +++ /dev/null @@ -1,163 +0,0 @@ -#include - -extern "C" { -#include "core/list.h" -} - -typedef struct { - struct list_node it; - const char *name; -} person_t; - -// struct PersonComparator { -// bool operator()(const Person *a, const Person *b) const { -// // sort is descending order -// return strcmp(b->name, a->name) < 0; -// } -// }; - -class IntrusiveTestEmptySet : public ::testing::Test { - public: - IntrusiveTestEmptySet() {} - - struct list people_list = {}; -}; - -class IntrusiveTestABCSet : public ::testing::Test { - public: - IntrusiveTestABCSet() { - list_add(&people_list, &aaa.it); - list_add(&people_list, &bbb.it); - list_add(&people_list, &ccc.it); - } - - struct list people_list = {}; - person_t aaa = {{}, "aaa"}; - person_t bbb = {{}, "bbb"}; - person_t ccc = {{}, "ccc"}; -}; - -static void validate_people(struct list *people_list, - person_t **expected_people, - int num_expected_people) { - int n = 0; - - list_for_each_entry(person, people_list, person_t, it) { - person_t *expected_person = expected_people[n]; - ASSERT_STREQ(person->name, expected_person->name); - n++; - } - - ASSERT_EQ(n, num_expected_people); -} - -static void validate_people_reverse(struct list *people_list, - person_t **expected_people, - int num_expected_people) { - int n = 0; - - list_for_each_entry_reverse(person, people_list, person_t, it) { - person_t *expected_person = expected_people[num_expected_people - n - 1]; - ASSERT_STREQ(person->name, expected_person->name); - n++; - } - - ASSERT_EQ(n, num_expected_people); -} - -// add tests -TEST_F(IntrusiveTestEmptySet, Append) { - person_t aaa = {{}, "aaa"}; - person_t bbb = {{}, "bbb"}; - person_t ccc = {{}, "ccc"}; - - person_t *people[] = {&aaa, &bbb, &ccc}; - int num_people = array_size(people); - - for (int i = 0; i < num_people; i++) { - person_t *expected_person = people[i]; - list_add(&people_list, &expected_person->it); - } - - person_t *expected_people[] = {&aaa, &bbb, &ccc}; - int num_expected_people = array_size(expected_people); - - validate_people(&people_list, expected_people, num_expected_people); - validate_people_reverse(&people_list, expected_people, num_expected_people); -} - -TEST_F(IntrusiveTestEmptySet, Prepend) { - person_t aaa = {{}, "aaa"}; - person_t bbb = {{}, "bbb"}; - person_t ccc = {{}, "ccc"}; - - person_t *people[] = {&aaa, &bbb, &ccc}; - int num_people = array_size(people); - - for (int i = 0; i < num_people; i++) { - person_t *expected_person = people[i]; - list_add_after(&people_list, NULL, &expected_person->it); - } - - person_t *expected_people[] = {&ccc, &bbb, &aaa}; - int num_expected_people = array_size(expected_people); - - validate_people(&people_list, expected_people, num_expected_people); - validate_people_reverse(&people_list, expected_people, num_expected_people); -} - -// remove tests -TEST_F(IntrusiveTestABCSet, RemoveHead) { - list_remove(&people_list, &aaa.it); - - person_t *expected_people[] = {&bbb, &ccc}; - int num_expected_people = array_size(expected_people); - - validate_people(&people_list, expected_people, num_expected_people); - validate_people_reverse(&people_list, expected_people, num_expected_people); -} - -TEST_F(IntrusiveTestABCSet, RemoveMiddle) { - list_remove(&people_list, &bbb.it); - - person_t *expected_people[] = {&aaa, &ccc}; - int num_expected_people = array_size(expected_people); - - validate_people(&people_list, expected_people, num_expected_people); - validate_people_reverse(&people_list, expected_people, num_expected_people); -} - -TEST_F(IntrusiveTestABCSet, RemoveTail) { - list_remove(&people_list, &ccc.it); - - person_t *expected_people[] = {&aaa, &bbb}; - int num_expected_people = array_size(expected_people); - - validate_people(&people_list, expected_people, num_expected_people); - validate_people_reverse(&people_list, expected_people, num_expected_people); -} - -TEST_F(IntrusiveTestABCSet, Clear) { - ASSERT_FALSE(list_empty(&people_list)); - - list_for_each(&people_list, it) { - list_remove(&people_list, it); - } - - ASSERT_TRUE(list_empty(&people_list)); -} - -// // sort tests -// TEST_F(IntrusiveTestEmptySet, EmptySort) { -// people.Sort(PersonComparator()); -// ASSERT_EQ(NULL, people.head()); -// ASSERT_EQ(NULL, people.tail()); -// } - -// TEST_F(IntrusiveTestABCSet, Sort) { -// people.Sort(PersonComparator()); -// auto it = people.begin(); -// ASSERT_STREQ("ccc", (it++)->name); -// ASSERT_STREQ("bbb", (it++)->name); -// ASSERT_STREQ("aaa", (it++)->name); -// } diff --git a/test/test_load_store_elimination_pass.c b/test/test_load_store_elimination_pass.c index d35a29a0..1ec763dc 100644 --- a/test/test_load_store_elimination_pass.c +++ b/test/test_load_store_elimination_pass.c @@ -1,12 +1,11 @@ -#include "core/assert.h" -#include "core/constructor.h" #include "jit/ir/ir.h" #include "jit/ir/passes/load_store_elimination_pass.h" +#include "retest.h" static uint8_t ir_buffer[1024 * 1024]; static char scratch_buffer[1024 * 1024]; -CONSTRUCTOR(test_load_store_elimination_pass_test) { +TEST(test_load_store_elimination_pass_test) { static const char input_str[] = "store_context i32 0x104, i32 0x0\n" "store_context i32 0x100, i32 0x0\n"