libdev.a

C Helper library
Log | Files | Refs | README | LICENSE | git clone https://git.ne02ptzero.me/git/libdev.a

commit d063661fc82acb8c5e40e741a6595b09c2aad8c8
parent abd96144ef67a2da672d4081c727d151a43724c2
Author: Ne02ptzero <louis@ne02ptzero.me>
Date:   Tue, 11 Oct 2016 17:51:52 +0200

Add(Units tests):

Add unit tests to the library.
Fix some data issues in singletons.
Update the documentation

Diffstat:
MMakefile | 3+++
MREADME.md | 7+++++--
Mlibdev.h | 4++--
Mlists.c | 7++++++-
Mtests.c | 19++++++++++++++++---
Mtests/main.c | 157+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
6 files changed, 189 insertions(+), 8 deletions(-)

diff --git a/Makefile b/Makefile @@ -12,6 +12,9 @@ all: $(NAME) $(NAME): $(OBJS) $(LIB) $(LFLAGS) $(NAME).a $(OBJS) +test: $(NAME) + cd tests && make + clean: rm -f $(OBJS) diff --git a/README.md b/README.md @@ -138,7 +138,7 @@ unsigned long long | u64_t | 64 | 8 | 0 to 18,446,744,073,709,551,615 ## Singletons #### Definition ```C -t_list *singleton_lists(u8_t list_type, t_list *ptr); +void *singleton_lists(u8_t list_type, void *ptr); ``` #### Example Singletons are a way to avoid global variables. The way it works is quite simple: You set a variable to a function, this function stores it, and you can retrieve the same variable later. Let's see an example: @@ -158,6 +158,8 @@ singleton_lists(T_LISTS, list); list = singleton_lists(T_LISTS, NULL); ``` In order to set / retrieve the list, you need an unique identifier. In this example, an enum is used, but you can actually use what you want. Some notes though: The id used needs to be unique, and in a range of a ```unsigned char```. + +Note: In this example, i use a ```t_list``` pointer, but you can pass any data you want to store. ```void *``` Magic ! ## Print Helpers ### Info #### Definition @@ -250,8 +252,9 @@ In this example, we are testing than ```i``` is equal to 1. In order to do that, > Bad initialization: Test: 'i == 1', File main.c:33 ``` As you see, the second parameter of the macro is the error returned if the test failed. +The error message max length is 250. -You _must_ finish all of your tests with the ```TEST_SUCCESS``` macro, in order to inform the test handler that all went well. +You *must* finish all of your tests with the ```TEST_SUCCESS``` macro, in order to inform the test handler that all went well. ### Register a Test Your test is now declared, but you must register it to the test handler. In libdev.a, all the tests are registered in groups. diff --git a/libdev.h b/libdev.h @@ -73,7 +73,7 @@ typedef struct s_list { typedef struct s_singleton { u_char type; // List type (ENUM) - t_list *ptr; // Actual pointer to the list + void *ptr; // Actual pointer to the list } t_singleton; typedef struct s_test { @@ -99,7 +99,7 @@ size_t list_size(t_list *list); void *list_get(t_list *list, void *ptr, size_t size); // singleton.c -t_list *singleton_lists(u_char list_type, t_list *ptr); +void *singleton_lists(u_char list_type, void *ptr); // print.c void error(char *str, ...); diff --git a/lists.c b/lists.c @@ -76,6 +76,11 @@ t_list *list_insert_before(t_list *org, t_list *ptr, void *member, size_t size) if (!tmp->next) { tmp->next = n_member; n_member->prev = tmp; + } else if (ptr == org) { + n_member->next = org; + n_member->prev = 0x0; + org->prev = n_member; + org = n_member; } else { tmp2 = tmp->prev; n_member->next = tmp; @@ -103,7 +108,7 @@ void *list_get(t_list *list, void *member, size_t size) { if (!list) return 0x0; list_for_each(list, tmp, ptr) { - if (!memcmp(ptr, member, size)) + if (!memcmp(ptr, member, size) && (size == tmp->size)) return ptr; } return 0x0; diff --git a/tests.c b/tests.c @@ -1,5 +1,18 @@ #include <libdev.h> +static void title(char *s) { + u_char len = 80; + int i; + + len -= strlen(s); + for (i = 0; i < len / 2; i++, write(1, "=", 1)); + write(1, " ", 1); + write(1, s, strlen(s)); + write(1, " ", 1); + for (; i < len; i++, write(1, "=", 1)); + write(1, "\n", 1); +} + void register_test(char *group, char *(*fn_test)(void), char *name) { t_list *tests = singleton_lists(TESTS_LIST, 0x0); t_test *ptr; @@ -24,12 +37,12 @@ t_test_results test_group(char *group) { char *s_tmp; res.total = res.success = res.failed = 0; - info("======================= GROUP %s TESTS =======================\n", group); + title(group); list_for_each(tests, tmp, ptr) { if (!strcmp(ptr->group, group)) { res.total++; info("Testing %s ...", ptr->name); - for (tab = strlen(ptr->name); tab < 40; tab++, printf(" ")); + for (tab = strlen(ptr->name); tab < 62; tab++, printf(" ")); if ((s_tmp = ptr->fn_test())) { printf("[ \033[1;31mFAILED\033[0m ]\n"); warning("\033[0;37m%s\033[0m\n", s_tmp); @@ -69,7 +82,7 @@ void test_all(void) { warning("No tests registered, skipping.\n"); else { printf("\n"); - info("============================= RESULTS =============================\n"); + title("RESULTS"); info("\033[1;32mTESTS SUCCESS\033[0m:\t%d\n", success); info("\033[1;31mTESTS FAILED\033[0m:\t\t%d\n", failed); info("\033[1;34mTOTAL COVERAGE\033[0m:\t%d%%\n", (success * 100) / total); diff --git a/tests/main.c b/tests/main.c @@ -1,5 +1,10 @@ #include <libdev.h> +enum { + S_1, + S_2 +}; + TEST(list_add_null) { t_list *ptr = 0x0; void *null = 0x0; @@ -106,8 +111,146 @@ TEST(list_add_after) { return TEST_SUCCESS; } +TEST(list_add_before) { + t_list *ptr = 0x0, *tmp; + char test[] = "Hello !\n"; + char test2[] = "Hello2 !\n"; + char test3[] = "Hello3 !\n"; + char test4[] = "Hello2.5 !\n"; + char test5[] = "Hello4 !\n"; + + list_add(ptr, test, 8); + list_add(ptr, test2, 9); + list_add(ptr, test3, 9); + list_add_before(ptr, ptr->next, test4, 11); + T_ASSERT(!strcmp(ptr->member, "Hello !\n"), "Head is wrong."); + T_ASSERT(!strcmp(ptr->next->member, "Hello2.5 !\n"), "Order is wrong."); + T_ASSERT(!strcmp(ptr->next->next->member, "Hello2 !\n"), "Order is wrong."); + T_ASSERT(!strcmp(ptr->next->next->next->member, "Hello3 !\n"), "Order is wrong."); + list_add_before(ptr, ptr, test5, 9); + tmp = ptr->head; + T_ASSERT(!strcmp(tmp->member, "Hello4 !\n"), "Order is wrong."); + T_ASSERT(!tmp->prev, "Next pointer is wrong."); + return TEST_SUCCESS; +} + +TEST(list_for_each_rev) { + t_list *ptr = 0x0, *tmp; + char test[] = "Hello !\n"; + char test2[] = "Hello2 !\n"; + char test3[] = "Hello3 !\n"; + char *s_tmp; + size_t i = 0; + + list_add(ptr, test, 8); + list_add(ptr, test2, 9); + list_add(ptr, test3, 9); + list_for_each_rev(ptr, tmp, s_tmp) { + switch (i) { + case 0: T_ASSERT(s_tmp, "Hello3 !\n"); break; + case 1: T_ASSERT(s_tmp, "Hello2 !\n"); break; + case 2: T_ASSERT(s_tmp, "Hello !\n"); break; + case 3: T_ASSERT(0, "list_for_each too many iterations."); + } + } + return TEST_SUCCESS; +} +TEST(list_size) { + t_list *ptr = 0x0; + char test[] = "Hello !\n"; + char test2[] = "Hello2 !\n"; + char test3[] = "Hello3 !\n"; + list_add(ptr, test, 8); + list_add(ptr, test2, 9); + list_add(ptr, test3, 9); + T_ASSERT(list_size(ptr) == 3, "Size is wrong."); + return TEST_SUCCESS; +} + +TEST(s8_t) { + s8_t l; + T_ASSERT(sizeof(l) == 1, "Wrong size."); + return TEST_SUCCESS; +} + +TEST(u8_t) { + u8_t l; + T_ASSERT(sizeof(l) == 1, "Wrong size."); + return TEST_SUCCESS; +} + +TEST(s16_t) { + s16_t l; + T_ASSERT(sizeof(l) == 2, "Wrong size."); + return TEST_SUCCESS; +} + +TEST(u16_t) { + u16_t l; + T_ASSERT(sizeof(l) == 2, "Wrong size."); + return TEST_SUCCESS; +} + +TEST(s32_t) { + s32_t l; + T_ASSERT(sizeof(l) == 4, "Wrong size."); + return TEST_SUCCESS; +} + +TEST(u32_t) { + u32_t l; + T_ASSERT(sizeof(l) == 4, "Wrong size."); + return TEST_SUCCESS; +} + +TEST(s64_t) { + s64_t l; + T_ASSERT(sizeof(l) == 8, "Wrong size."); + return TEST_SUCCESS; +} + +TEST(u64_t) { + u64_t l; + T_ASSERT(sizeof(l) == 8, "Wrong size."); + return TEST_SUCCESS; +} + +TEST(singleton_set) { + char *ptr = malloc(10); + char *ptr2 = malloc(10); + + T_ASSERT(ptr && ptr2, "Malloc failed"); + strcpy(ptr, "Test123"); + strcpy(ptr2, "Test1234"); + T_ASSERT(!singleton_lists(S_1, ptr), "Return is not null."); + T_ASSERT(!singleton_lists(S_2, ptr2), "Return is not null."); + return TEST_SUCCESS; +} + +TEST(singleton_get) { + char *ptr, *ptr2; + + ptr = singleton_lists(S_1, 0x0); + ptr2 = singleton_lists(S_2, 0x0); + T_ASSERT(!strcmp(ptr, "Test123"), "Wrong Value."); + T_ASSERT(!strcmp(ptr2, "Test1234"), "Wrong Value."); + free(ptr); free(ptr2); + return TEST_SUCCESS; +} + +TEST(singleton_replace) { + char *ptr = malloc(10); + + T_ASSERT(ptr, "Malloc failed"); + strcpy(ptr, "Test12345"); + singleton_lists(S_1, ptr); + ptr = 0x0; + ptr = singleton_lists(S_1, 0x0); + T_ASSERT(!strcmp(ptr, "Test12345"), "Wrong Value."); + return TEST_SUCCESS; +} int main(void) { reg_test("linked_list", list_add_null); @@ -117,6 +260,20 @@ int main(void) { reg_test("linked_list", list_for_each); reg_test("linked_list", list_tail); reg_test("linked_list", list_add_after); + reg_test("linked_list", list_add_before); + reg_test("linked_list", list_for_each_rev); + reg_test("linked_list", list_size); + reg_test("types", s8_t); + reg_test("types", u8_t); + reg_test("types", s16_t); + reg_test("types", u16_t); + reg_test("types", s32_t); + reg_test("types", u32_t); + reg_test("types", s64_t); + reg_test("types", u64_t); + reg_test("singletons", singleton_set); + reg_test("singletons", singleton_get); + reg_test("singletons", singleton_replace); test_all(); return 0;