commit - dfbe39864b6e5026765fb16732426ea0100f396e
commit + da735c49230ce27cc18449d4d5d7f3bcfecaa7de
blob - 221cf5558f79da78e54a00bb1e33cb3b7b840279
blob + 82a7d72d0085fded034b6622d51eb0a1b5456546
--- .gitignore
+++ .gitignore
test
tcptest
testrunner
+test_*
.idea
netmanual
blob - 2fd17e00ad933ad40ed49fb4cce439bb2a8c93ac
blob + c24d9315fdc198311dd387eec1a0fe4f21aae62c
--- CMakeLists.txt
+++ CMakeLists.txt
endif()
if(${CMAKE_PROJECT_NAME} STREQUAL flint)
- add_executable(tests tests/tests.c)
- target_include_directories(tests PRIVATE include)
+ enable_testing()
if (${CMAKE_SYSTEM_NAME} STREQUAL "Linux")
- target_link_libraries(tests flint pthread bsd)
+ set(FLINT_TEST_LIBS flint pthread bsd)
else()
- target_link_libraries(tests flint pthread)
+ set(FLINT_TEST_LIBS flint pthread)
endif()
+ set(TESTS
+ linkedlist
+ set
+ stack
+ binarytree
+ math
+ vector
+ string
+ crypto
+ parsing
+ memory
+ )
+
+ foreach(t ${TESTS})
+ add_executable(test_${t} tests/test_${t}.c)
+ target_include_directories(test_${t} PRIVATE include)
+ target_link_libraries(test_${t} ${FLINT_TEST_LIBS})
+ add_test(NAME ${t} COMMAND test_${t})
+ endforeach()
+
+ # Network test (slow, uses sleep + sockets)
+ add_executable(test_network tests/test_network.c)
+ target_include_directories(test_network PRIVATE include)
+ target_link_libraries(test_network ${FLINT_TEST_LIBS})
+ add_test(NAME network COMMAND test_network)
+ set_tests_properties(network PROPERTIES LABELS "slow")
+
+ # macOS-only test
+ if (${CMAKE_SYSTEM_NAME} STREQUAL "Darwin")
+ add_executable(test_macos tests/test_macos.c)
+ target_include_directories(test_macos PRIVATE include)
+ target_link_libraries(test_macos ${FLINT_TEST_LIBS})
+ add_test(NAME macos COMMAND test_macos)
+ set_tests_properties(macos PROPERTIES LABELS "slow")
+ endif()
+
add_executable(netmanual tests/netmanual.c)
target_include_directories(netmanual PRIVATE include)
-
- if (${CMAKE_SYSTEM_NAME} STREQUAL "Linux")
- target_link_libraries(netmanual flint pthread bsd)
- else()
- target_link_libraries(netmanual flint pthread)
- endif()
+ target_link_libraries(netmanual ${FLINT_TEST_LIBS})
endif()
blob - 2768f4d06b3602b115b09dcf2cd98a2de2a7f17b
blob + 171a33440699c49f52cca8fb2fd1d322cfe13875
--- README.md
+++ README.md
## Documentation
-Extensive documentation can be found [here](https://burkey.co/Software+Documentation/libflint/libflint). You can also check out `tests/tests.c` to
-see example usage from most of the library's API.
+Extensive documentation can be found [here](https://burkey.co/Software+Documentation/libflint/libflint). You can also check out the per-module test files in `tests/` for example usage.
## Building
target_link_libraries(${TARGET} PRIVATE flint )
```
+## Testing
+
+```sh
+cmake -B build && cmake --build build
+ctest --test-dir build # run all tests
+ctest --test-dir build --parallel # run in parallel
+ctest --test-dir build --label-exclude slow # skip slow tests (network, macos)
+```
+
## Requirements
Building on Linux requires `libbsd`. Building on macOS, OpenBSD, or FreeBSD requires no extra dependencies.
blob - 9bcb2fd8c09c5f4ce210a98b0d1240e559cd0c60
blob + af1bf32c978a6307eeb41f46b079b5affe93f477
--- include/lfmemory.h
+++ include/lfmemory.h
#include "lflinkedlist.h"
-#ifndef DEFAULT_ALIGNMENT
+#ifndef LF_DEFAULT_ALIGNMENT
#define LF_DEFAULT_ALIGNMENT (2*sizeof(void*))
-#endif // DEFAULT_ALIGNMENT
+#endif // LF_DEFAULT_ALIGNMENT
typedef struct {
unsigned char* buf;
blob - /dev/null
blob + 1f3824fd374d29737e21ca07953ec4764eaa03ae (mode 644)
--- /dev/null
+++ include/lftest.h
+#ifndef LFTEST_H
+#define LFTEST_H
+
+#include <stdio.h>
+#include <string.h>
+
+static int lf_tests_total;
+static int lf_tests_failed;
+
+#define ASSERT_TRUE(expr) do { \
+ lf_tests_total++; \
+ if (!(expr)) { \
+ lf_tests_failed++; \
+ fprintf(stderr, " FAIL %s:%d: %s\n", __FILE__, __LINE__, #expr); \
+ } \
+} while(0)
+
+#define ASSERT_FALSE(expr) ASSERT_TRUE(!(expr))
+
+#define ASSERT_EQ(a, b) do { \
+ lf_tests_total++; \
+ if ((a) != (b)) { \
+ lf_tests_failed++; \
+ fprintf(stderr, " FAIL %s:%d: %s != %s\n", __FILE__, __LINE__, #a, #b); \
+ } \
+} while(0)
+
+#define ASSERT_NEQ(a, b) do { \
+ lf_tests_total++; \
+ if ((a) == (b)) { \
+ lf_tests_failed++; \
+ fprintf(stderr, " FAIL %s:%d: %s == %s\n", __FILE__, __LINE__, #a, #b); \
+ } \
+} while(0)
+
+#define ASSERT_LT(a, b) do { \
+ lf_tests_total++; \
+ if (!((a) < (b))) { \
+ lf_tests_failed++; \
+ fprintf(stderr, " FAIL %s:%d: %s >= %s\n", __FILE__, __LINE__, #a, #b); \
+ } \
+} while(0)
+
+#define ASSERT_STR_EQ(a, b) do { \
+ lf_tests_total++; \
+ if (strcmp((a), (b)) != 0) { \
+ lf_tests_failed++; \
+ fprintf(stderr, " FAIL %s:%d: \"%s\" != \"%s\"\n", __FILE__, __LINE__, (a), (b)); \
+ } \
+} while(0)
+
+#define ASSERT_NULL(expr) ASSERT_EQ((void *)(expr), NULL)
+#define ASSERT_NOT_NULL(expr) ASSERT_NEQ((void *)(expr), NULL)
+
+#define TEST_REPORT() do { \
+ printf("%d/%d passed\n", lf_tests_total - lf_tests_failed, lf_tests_total); \
+ return lf_tests_failed ? 1 : 0; \
+} while(0)
+
+#endif /* LFTEST_H */
blob - ba1a8603f7586d7eeb17a88cfc6ff4b521905727 (mode 755)
blob + /dev/null
--- run_tests.sh
+++ /dev/null
-set -e
-
-#./testrunner
-./tcptest &
-tcpout=$(echo "hello" | nc localhost 18632)
-echo "tcpout: $tcpout"
-if [ "$tcpout" != "TEST SEND" ]; then
- echo "Error: \"$tcpout\" != \"TEST SEND\""
- exit 1
-fi
-
-exit 0
blob - a0f755715046807ad86e477d29bea7d3dd73b17b
blob + 037cd2638c2f251bc8df208e644d4732c6b0fe71
--- src/binarytree.c
+++ src/binarytree.c
merge->root->left = left->root;
merge->root->right = right->root;
+ merge->size = 1 + left->size + right->size;
left->root = NULL;
left->size = 0;
blob - 3d47bb055dcc82e60c8aa50c424b65ade9a9e5de
blob + 7dc6dc22e56c5d9d88b4e00d81e93377619c0ffc
--- src/crypto.c
+++ src/crypto.c
break;
}
// Not base64 characters
- if (!isalnum(s[j]) || s[j] == '+' || s[j] == '/') {
+ if (!isalnum(s[j]) && s[j] != '+' && s[j] != '/') {
break;
}
blob - 23d54c9df9d8498a4e6c0e3b3fc2ff863ecb955e
blob + dfb3e5a33f8c3184643b3c716537b25f2949adcc
--- src/input.c
+++ src/input.c
return NULL;
}
fgets(buf, buf_sz, tmp);
+ pclose(tmp);
return buf;
}
\ No newline at end of file
blob - 1eb166ac02c8c4fd1e7e973c8040eb3088d7aa80
blob + 53ec9d9a88a03fb3090e822ddcc9959b4fef0560
--- src/linkedlist.c
+++ src/linkedlist.c
}
int ll_remove_next(List *list, ListNode *node, void **data) {
- if (node->next == NULL) {
+ if (node == NULL || node->next == NULL) {
return -1;
}
return ll_remove(list, node->next, data);
}
int ll_remove_prev(List *list, ListNode *node, void **data) {
- if (node->prev == NULL) {
+ if (node == NULL || node->prev == NULL) {
return -1;
}
return ll_remove(list, node->prev, data);
blob - 14e275b908de1b802c8ebf3e5d73acc95d2f19aa
blob + 5659ee6ca791e2ed0df101b495a7236946c2a812
--- src/math.c
+++ src/math.c
}
int is_power_of_two(int i) {
- return (i & (i - 1)) == 0;
+ return i > 0 && (i & (i - 1)) == 0;
}
blob - 6cfe72d28dc88b08e240782f73007000a8b8da3c
blob + 83289bdda46e17a6c8bf99a1fbcdf72cef59c53c
--- src/memory.c
+++ src/memory.c
}
void arena_free(ArenaAllocator *allocator) {
+ if (allocator == NULL) {
+ return;
+ }
free(allocator->buf);
- free(allocator);
+ allocator->buf = NULL;
+ allocator->buf_sz = 0;
+ allocator->offset_cur = 0;
+ allocator->offset_prev = 0;
}
void arena_clear(ArenaAllocator *allocator) {
allocator->offset_prev = 0;
}
-static uintptr_t align_forward_uintptr(const uintptr_t ptr, const uintptr_t align) {
+static uintptr_t align_forward(const uintptr_t ptr, const uintptr_t align) {
if (!is_power_of_two(align)) {
- // TODO: Error
+ return 0;
}
uintptr_t p = ptr;
const uintptr_t m = p & (align - 1);
return p;
}
-static uintptr_t align_forward_size(const size_t ptr, const size_t align) {
- if (!is_power_of_two(align)) {
- // TODO: Error
- }
- uintptr_t p = ptr;
- const uintptr_t m = p & (align - 1);
-
- if (m != 0) {
- p += align - m;
- }
- return p;
-}
-
static void *arena_malloc_align(ArenaAllocator *allocator, const size_t size, size_t align) {
uintptr_t cur_ptr = (uintptr_t)allocator->buf + allocator->offset_cur;
// Push forward to align, then change to relative offset
- uintptr_t offset = align_forward_uintptr(cur_ptr, align);
+ uintptr_t offset = align_forward(cur_ptr, align);
offset -= (uintptr_t)allocator->buf;
if (offset + size <= allocator->buf_sz) {
static void *arena_resize_align(ArenaAllocator *allocator, void *mem, const size_t old_sz, const size_t new_sz, size_t align) {
unsigned char *old_mem = mem;
if (!is_power_of_two(align)) {
- // TODO: Error handling
+ return NULL;
}
if (old_mem == NULL || old_sz == 0) {
if (allocator->buf <= (unsigned char*)mem && (unsigned char*)mem < allocator->buf + allocator->buf_sz) {
if (allocator->buf + allocator->offset_prev == old_mem) {
+ if (allocator->offset_prev + new_sz > allocator->buf_sz) {
+ return NULL;
+ }
allocator->offset_cur = allocator->offset_prev + new_sz;
if (new_sz > old_sz) {
- // Zero out memory
- memset(&allocator->buf[allocator->offset_cur], 0, new_sz - old_sz);
+ memset(&allocator->buf[allocator->offset_prev + old_sz], 0, new_sz - old_sz);
}
return old_mem;
}
void *new_mem = arena_malloc_align(allocator, new_sz, align);
+ if (new_mem == NULL) {
+ return NULL;
+ }
size_t copy_size = old_sz < new_sz ? old_sz : new_sz;
memmove(new_mem, old_mem, copy_size);
return new_mem;
}
void arena_resize_buf(ArenaAllocator *allocator, const size_t new_sz) {
- allocator->buf = realloc(allocator->buf, sizeof(unsigned char) * new_sz);
+ unsigned char *new_buf = realloc(allocator->buf, sizeof(unsigned char) * new_sz);
+ if (new_buf == NULL) {
+ return;
+ }
+ allocator->buf = new_buf;
+ allocator->buf_sz = new_sz;
}
void *arena_malloc(ArenaAllocator *allocator, const size_t size) {
allocator->buf = malloc(sizeof(unsigned char) * buf_sz);
uintptr_t istart = (uintptr_t)allocator->buf;
- uintptr_t start = align_forward_uintptr(istart, chunk_align);
+ uintptr_t start = align_forward(istart, chunk_align);
allocator->buf_sz = buf_sz - (start - istart);
- allocator->chunk_size = align_forward_size(chunk_sz, chunk_align);
+ allocator->chunk_size = align_forward(chunk_sz, chunk_align);
if (allocator->chunk_size < sizeof(void *) || allocator->buf_sz < allocator->chunk_size) {
- //TODO: Handle error better
+ free(allocator->buf);
+ allocator->buf = NULL;
+ allocator->buf_sz = 0;
return;
}
}
void pool_free(PoolAllocator *allocator, void *ptr) {
- ListNode *node = NULL;
const void *start = allocator->buf;
const void *end = &allocator->buf[allocator->buf_sz];
}
if (!(start <= ptr && ptr < end)) {
- // TODO: Handle error better
return;
}
}
void pool_free_all(PoolAllocator *allocator) {
+ ll_destroy(allocator->free_list);
+ ll_init(allocator->free_list, NULL);
+
size_t chunk_count = allocator->buf_sz / allocator->chunk_size;
for (size_t i = 0; i < chunk_count; ++i) {
ll_ins_next(allocator->free_list, allocator->free_list->head, &allocator->buf[i * allocator->chunk_size]);
void *pool_alloc(PoolAllocator *allocator) {
ListNode *node = allocator->free_list->head;
if (node == NULL) {
- // TODO: Handle error better
return NULL;
}
}
void pool_destroy(PoolAllocator *allocator) {
+ if (allocator == NULL) {
+ return;
+ }
ll_destroy(allocator->free_list);
free(allocator->free_list);
free(allocator->buf);
blob - 29841222c56782549f59bf4c7bff135b55aafe67
blob + b4f2ebfa3ef9b4d8dd0f24d89f8d435b77ab21c0
--- src/network.c
+++ src/network.c
// This is just for macOS and BSDs
#if !defined(__linux__) && !defined(_WIN32)
struct sigaction sa;
- sa.sa_handler = sighandler;
+ sigemptyset(&sa.sa_mask);
+ sa.sa_handler = sighandler;
sa.sa_flags = SA_RESTART;
if (sigaction(SIGCHLD, &sa, NULL) == -1) {
fprintf(stderr, "Failed to set sigaction\n");
break;
}
- if (send(fd, recv_buf, strlen(recv_buf), 0) == -1) {
+ if (send(fd, recv_buf, r, 0) == -1) {
fprintf(stderr, "Failed to send echo. Errno: %d\n", errno);
close(fd);
break;
}
}
+ return NULL;
}
void handler_tcp_echo(Server *s) {
blob - 0857c95fd03a046ef2ae07d90a6aa4cb1618b109
blob + 9e68fc54b2da44997bbd2dcc4d980f68c25aaef4
--- src/set.c
+++ src/set.c
if (node == NULL) {
return -1;
}
- return ll_remove_next(set, node, data);
+ return ll_remove(set, node, data);
}
int set_union(Set *setu, const Set *a, const Set *b) {
}
int set_is_equal(const Set *a, const Set *b) {
- if (a->size == b->size) {
+ if (a->size != b->size) {
return 0;
}
return set_is_subset(a, b);
blob - 4fe56033bd86f75901823d8367d78b305597e022
blob + 2cb1d2572d1af0dac58eb454a6b5905d9111c579
--- src/string.c
+++ src/string.c
return NULL;
}
- char *substr = malloc(sizeof(char) * len + 1);
+ char *substr = malloc(sizeof(char) * (len + 1));
if (substr == NULL) {
return NULL;
}
blob - 83da588467cb044d00a0cbb1bc97c7cdcc691505
blob + 86f65c6f6b4f52c38a382ae4a35ab935d0a45eb9
--- src/vector.c
+++ src/vector.c
}
const void *vec_min(const Vector *vec, int(*cmp)(const void *a, const void *b)) {
+ if (vec_len(vec) == 0) {
+ return NULL;
+ }
void *a = vec->elements[0];
for (size_t i = 1; i < vec_len(vec); ++i) {
if (cmp(a, vec->elements[i]) > 0) {
}
const void *vec_max(const Vector *vec, int(*cmp)(const void *a, const void *b)) {
+ if (vec_len(vec) == 0) {
+ return NULL;
+ }
void *a = vec->elements[0];
for (size_t i = 1; i < vec_len(vec); ++i) {
if (cmp(a, vec->elements[i]) < 0) {
}
int vec_cmp_char(const void *a, const void *b) {
- const char x = *(int*)a;
- const char y = *(int*)b;
+ const char x = *(char*)a;
+ const char y = *(char*)b;
if (x > y) {
return 1;
blob - bf4544915dcf359a7e1d70423f9d57eba614ec03 (mode 644)
blob + /dev/null
--- tests/tests.c
+++ /dev/null
-#include <stdio.h>
-#include <stdlib.h>
-#include <assert.h>
-#include <unistd.h>
-#include <arpa/inet.h>
-#include <sys/socket.h>
-#include <pthread.h>
-
-#include "lflinkedlist.h"
-#include "lfnetwork.h"
-#include "lfset.h"
-#include "lfstack.h"
-#include "lfbinarytree.h"
-#include "lfvector.h"
-#include "lfmath.h"
-#include "lfstring.h"
-#include "lfcrypto.h"
-#include "lfparsing.h"
-#include "lfinput.h"
-#include "lfmemory.h"
-
-#if defined(__APPLE__) || defined(__MACH__)
-#include "lfmacos.h"
-#endif /* defined(__APPLE__) || defined(__MACH__) */
-
-void print_ll(List *list) {
- LL_ITER(list) {
- printf(" %d", *((int *) node->data));
- }
- printf("\n");
-}
-
-void test_ll() {
- printf("\n--- LIST TEST ---\n");
- List *list = malloc(sizeof(List));
- ll_init(list, NULL);
-
- int i = 1;
- int j = 2;
- int k = 4;
-
- ll_ins_next(list, list->head, (void *) &i);
- ll_ins_next(list, list->tail, (void *) &j);
- ll_ins_next(list, list->tail, (void *) &k);
-
- printf("List: ");
- print_ll(list);
-
- void *data;
- ll_remove_next(list, list->head, &data);
-
- printf("List: ");
- print_ll(list);
- assert(*(int*)data == 2);
- printf("Removed: %d\n", *((int *) data));
-
- ll_destroy(list);
- free(list);
-}
-
-int int_match(const void *a, const void *b) {
- return *((int *) a) == *((int *) b);
-}
-
-void test_set() {
- printf("\n--- SET TEST ---\n");
- Set *set = malloc(sizeof(Set));
- set_init(set, int_match, NULL);
-
- int i = 1;
- int j = 2;
- int k = 2;
-
- set_insert(set, &i);
- set_insert(set, &j);
- set_insert(set, &k);
-
- int i2 = 1;
- int j2 = 4;
-
- Set *set2 = malloc(sizeof(Set));
- set_init(set2, int_match, NULL);
-
- set_insert(set2, &i2);
- set_insert(set2, &j2);
-
- printf("Set 1:");
- print_ll(set);
-
- printf("Set 2:");
- print_ll(set2);
- printf("\n");
-
- Set *set_u = malloc(sizeof(Set));
- Set *set_i = malloc(sizeof(Set));
- Set *set_d = malloc(sizeof(Set));
-
- set_union(set_u, set, set2);
- printf("Union:");
- print_ll(set_u);
-
- set_difference(set_d, set, set2);
- printf("Difference:");
- print_ll(set_d);
-
- set_intersection(set_i, set, set2);
- printf("Intersection:");
- print_ll(set_i);
-
- set_destroy(set);
- set_destroy(set2);
- set_destroy(set_u);
- set_destroy(set_i);
- set_destroy(set_d);
- free(set);
- free(set2);
- free(set_u);
- free(set_i);
- free(set_d);
-}
-
-void test_stack() {
- printf("\n--- STACK TEST ---\n");
- Stack *stack = malloc(sizeof(Stack));
- stack_init(stack, NULL);
-
- int a = 1, b = 2;
- stack_push(stack, &a);
- stack_push(stack, &b);
- printf("Stack size: %lu\n", stack->size);
-
- int *p = NULL;
- stack_pop(stack, (void **) &p);
- printf("b = %d\n", *p);
-
- stack_pop(stack, (void **) &p);
- printf("a = %d\n", *p);
- printf("Stack size: %lu\n", stack->size);
-
- stack_destroy(stack);
- free(stack);
- stack = NULL;
-}
-
-void test_bintree() {
- printf("\n--- BINARY TREE TEST ---\n");
- BinTree *tree = malloc(sizeof(BinTree));
- bintree_init(tree, NULL);
-
- int root = 0;
- int l1 = 1;
- int l2 = 2;
- int r1 = 12;
- int r2 = 200;
-
- bintree_ins_left(tree, NULL, &root);
- bintree_ins_left(tree, tree->root, &l1);
- bintree_ins_left(tree, tree->root->left, &l2);
- bintree_ins_right(tree, tree->root->left, &r2);
- bintree_ins_right(tree, tree->root, &r1);
- bintree_ins_right(tree, tree->root->right, &r2);
- bintree_ins_left(tree, tree->root->right, &l1);
-
- bintree_debug_print(tree);
-
- printf("Changing r2\n");
- r2 = 100;
- bintree_debug_print(tree);
-
- bintree_destroy(tree);
- free(tree);
- tree = NULL;
-}
-
-void test_math() {
- printf("\n--- MATH TEST ---\n");
- int i = 1, j = 2;
- assert(max_int(i, j) == j);
- printf("Between %d and %d, %d is larger\n", i, j, max_int(i, j));
- printf("Between %d and %d, %d is smaller\n", i, j, min_int(i, j));
-
- char *s = "10101101";
- printf("Binary: %s\n", s);
- printf("Decimal: %d\n", binstr_to_int(s));
-
- char *s2 = "1010_1101";
- printf("Binary: %s\n", s2);
- printf("Decimal: %d\n", binstr_to_int(s2));
-
- i = 10;
- i = clamp_int(i, 2, 5);
- assert(i == 5);
-
- printf("\nGenerate line from 0,0 to 2,5\n");
- size_t sz = 0;
- Point *line = bresenham(0, 0, 2, 5, &sz);
- for (size_t idx = 0; idx < sz; idx++) {
- printf("%d,%d ", line[idx].x, line[idx].y);
- }
- printf("\n");
- free(line);
-}
-
-void print_vector(Vector *vec) {
- for (size_t i = 0; i < vec->length; ++i) {
- int t = *(int *) vec_at(vec, i);
- printf("%d ", t);
- }
- printf("\n");
-}
-
-void test_vector() {
- printf("\n--- VECTOR TEST ---\n");
- Vector *v = malloc(sizeof(Vector));
- vec_init(v, NULL);
-
- int e0 = 0;
- int e1 = 1;
- int e2 = 2;
- int e3 = 3;
- int e4 = 4;
-
- vec_push(v, &e0);
- assert(v->length == 1);
- int *t = vec_at(v, 0);
- assert(*t == 0);
-
- vec_push(v, &e1);
- vec_push(v, &e2);
- assert(v->length == 3);
-
- // test access outside bounds
- t = (int *) vec_safe_at(v, 3);
- assert(t == NULL);
-
- printf("Before insert: ");
- print_vector(v);
- vec_push(v, &e3);
- vec_insert(v, &e4, 1);
- printf("After insert: ");
- print_vector(v);
-
- t = (int *) vec_at(v, 4);
- assert(*t == e3);
- t = (int *) vec_at(v, 1);
- assert(*t == e4);
-
- const int *min = vec_min(v, vec_cmp_int);
- const int *max = vec_max(v, vec_cmp_int);
- printf("min: %d\n", *min);
- printf("max: %d\n", *max);
- assert(*min == e0);
- assert(*max == e4);
-
- t = (int *) vec_remove(v, 1);
- assert(t != NULL);
- assert(*t == 4);
- printf("After removal: ");
- print_vector(v);
-
- t = (int *) vec_remove(v, 10);
- assert(t == NULL);
-
- printf("\ncap before shrink: %zu\n", vec_cap(v));
- vec_shrink(v);
- assert(vec_len(v) == vec_cap(v));
- printf("cap after shrink: %zu\n", vec_cap(v));
-
- vec_clear(v);
- assert(vec_len(v) == 0);
- printf("\ncap after clear: %zu\n", vec_cap(v));
- printf("len after clear: %zu\n", vec_len(v));
-
- vec_grow_to(v, 10);
- assert(vec_cap(v) == 10);
- assert(vec_len(v) == 0);
-
- vec_destroy(v);
- free(v);
-}
-
-void test_string() {
- printf("\n--- STRING TEST ---\n");
- const char *haystack =
- "Test one two one and also maybe two but not Gabe's least favorite number, which is not one.";
- const char *needles[] = {
- "one",
- "two",
- "Gabe"
- };
-
- size_t sub_sz = 0;
- size_t *subs = NULL;
- find_substrings(haystack, needles[0], &sub_sz, &subs);
-
- assert(sub_sz == 3);
- assert(subs[0] == 5);
- assert(subs[1] == 13);
- assert(subs[2] == 87);
-
- char *s = substr(haystack, subs[0], strlen(needles[0]));
- assert(strcmp(s, needles[0]) == 0);
-
- free(s);
- free(subs);
- subs = NULL;
-
- find_substrings(haystack, needles[1], &sub_sz, &subs);
- assert(sub_sz == 2);
- assert(subs[0] == 9);
-
- free(subs);
- subs = NULL;
-
- find_substrings("test one two", "nope", &sub_sz, &subs);
- assert(sub_sz == 0);
- assert(subs == NULL);
- free(subs);
- subs = NULL;
-
- find_substrings("123", "nopes", &sub_sz, &subs);
- assert(sub_sz == 0);
- assert(subs == NULL);
- free(subs);
- subs = NULL;
-
- printf("Passes all string tests\n");
-}
-
-void test_crypto() {
- printf("\n--- CRYPTO TEST ---\n");
-
- char *in = "BUTT";
- unsigned char *s = b64_encode(in, strlen(in));
- assert(strcmp(s, "QlVUVA==") == 0);
- free(s);
-
- char *in2 = "a longer base64 test, apparently";
- s = b64_encode(in2, strlen(in2));
- assert(strcmp(s, "YSBsb25nZXIgYmFzZTY0IHRlc3QsIGFwcGFyZW50bHk=") == 0);
- free(s);
-
- char *out2 = "YSBsb25nZXIgYmFzZTY0IHRlc3QsIGFwcGFyZW50bHk=";
- size_t s_sz = 0;
- s = (char *) b64_decode(out2, strlen(out2), &s_sz);
- assert(strcmp(s, "a longer base64 test, apparently") == 0);
- assert(strlen(s) == s_sz);
- free(s);
-
- s = hex_decode("DEADBEEF", &s_sz);
- unsigned char h[4] = {
- 0xDE, 0xAD, 0xBE, 0xEF
- };
- for (size_t i = 0; i < 4; ++i) {
- assert(s[i] == h[i]);
- }
- free(s);
-
- // Odd number of characters
- s = hex_decode("f00f5", &s_sz);
- unsigned char h2[4] = {
- 0x0F, 0x00, 0xF5
- };
- for (size_t i = 0; i < 3; ++i) {
- assert(s[i] == h2[i]);
- }
- free(s);
-
- // leading 0x
- s = hex_decode("0xf00f5", &s_sz);
- for (size_t i = 0; i < 3; ++i) {
- assert(s[i] == h2[i]);
- }
- free(s);
-
- s = hex_encode(h, 4);
- assert(strcmp(s, "deadbeef") == 0);
- free(s);
-
- // "Sup?"
- unsigned char hexsup[4] = {
- 0x53, 0x75, 0x70, 0x3F
- };
- s = hex_to_str(hexsup, 4);
- assert(strcmp(s, "Sup?") == 0);
- free(s);
-
- s = repeating_key_xor_s("TEST", "HI");
- char *enc = hex_encode(s, 4);
- assert(strcmp(enc, "1c0c1b1d") == 0);
- free(enc);
- free(s);
-
- unsigned char ua[2] = {0x2, 0xF};
- unsigned char ub[2] = {0x4, 0xE};
- unsigned int hamming = hamming_distance(ua, ub, 2);
- assert(hamming == 3);
-
- hamming = hamming_distance_s("this is a test", "wokka wokka!!!");
- assert(hamming == 37);
-
- printf("Passes all crypto tests\n");
-}
-
-void test_parsing() {
- printf("\n--- PARSING TEST ---\n");
-
- char *nonsense = "8d82jI|dms~<>s2d";
- char *english = "This is an English sentence!";
- assert(simple_english_scoring(english) > simple_english_scoring(nonsense));
-
- printf("Passes all parsing tests\n");
-}
-
-#define NET_MSG "TEST SEND"
-
-void tcp_test_handler(Server *s) {
- struct sockaddr_storage client_addr;
- socklen_t client_addr_sz = sizeof(client_addr);
- int new_fd = accept(s->fd, (struct sockaddr *) &client_addr, &client_addr_sz);
- assert(new_fd != -1);
- assert(send(new_fd, NET_MSG, 10, 0) != -1);
- close(new_fd);
-}
-
-void *tcp_server_thread(void *vargp) {
- Server *server = new_server(SERVERTYPE_TCP, "18632", tcp_test_handler);
- serve(server, DEFAULT_BACKLOG);
- delete_server(server);
-}
-
-void udp_test_handler(Server *s) {
- struct sockaddr_storage client_addr;
- socklen_t client_addr_sz = sizeof(client_addr);
- char recv_buf[128];
-
- int r = (int) recvfrom(s->fd, recv_buf, 128, 0, (struct sockaddr *) &client_addr, &client_addr_sz);
- assert(r > 0);
- assert(strcmp(recv_buf, NET_MSG) == 0);
-}
-
-void *udp_server_thread(void *vargp) {
- Server *server = new_server(SERVERTYPE_UDP, "18633", udp_test_handler);
- serve(server, DEFAULT_BACKLOG);
- delete_server(server);
-}
-
-void test_network() {
- printf("\n--- NETWORK TEST ---\n");
- pthread_t srv_tid;
- pthread_create(&srv_tid, NULL, tcp_server_thread, NULL);
-
- sleep(1);
- const char *s = capture_system("echo hello | nc localhost 18632", 0);
- assert(strcmp(s, NET_MSG) == 0);
- free((char *) s);
-
- pthread_join(srv_tid, NULL);
- printf("Passed TCP test\n");
-
- pthread_create(&srv_tid, NULL, udp_server_thread, NULL);
- sleep(1);
- system("echo hello | nc localhost 18633");
-
- pthread_join(srv_tid, NULL);
- printf("Passed UDP test\n");
-}
-
-#if defined(__APPLE__) || defined(__MACH__)
-void test_macos() {
- printf("\n--- macOS TEST ---\n");
-
- pid_t pid = getpid();
- ProcessData *pd = new_ProcessData();
- for (int i = 0; i < 4; i++) {
- update_process(pid, pd);
- printf("CPU: %.2f\n", pd->percent_cpu);
- sleep(1);
- }
- free(pd);
-}
-#endif
-
-void test_memory() {
- printf("\n--- MEMORY TEST ---\n");
- ArenaAllocator *arena = malloc(sizeof(ArenaAllocator));
- arena_init(arena, 1024);
-
- int *i1 = arena_malloc(arena, sizeof(int));
- int *i2 = arena_malloc(arena, sizeof(int));
-
- *i1 = 1;
- *i2 = 2;
-
- assert(i1 < i2);
- assert(*i1 < *i2);
-
- long *l = arena_resize(arena, i1, sizeof(int), sizeof(long));
- assert(*l == 1);
-
- unsigned char *char_test = arena_resize(arena, i2, sizeof(int), sizeof(unsigned char));
- assert(*char_test == 2);
-
- arena_free(arena);
- arena = NULL;
-
- PoolAllocator *pool = malloc(sizeof(PoolAllocator));
- pool_init(pool, 64, 16, LF_DEFAULT_ALIGNMENT);
- void *a = pool_alloc(pool);
- void *b = pool_alloc(pool);
- void *c = pool_alloc(pool);
- void *d = pool_alloc(pool);
-
- assert(a != NULL);
- assert(b != NULL);
- assert(c != NULL);
- assert(d != NULL);
-
- assert(pool_count_available(pool) == 0);
- pool_free(pool, d);
- d = NULL;
- assert(pool_count_available(pool) == 1);
-
- pool_destroy(pool);
- printf("Passes all memory tests\n");
-}
-
-int main() {
- test_ll();
- test_set();
- test_stack();
- test_bintree();
- test_math();
- test_vector();
- test_string();
- test_crypto();
- test_parsing();
- test_network();
- test_memory();
-
-#if defined(__APPLE__) || defined(__MACH__)
- test_macos();
-#endif
-
- return 0;
-}
blob - /dev/null
blob + fe79293ff6446784eaeff8ae652c0ab90891af70 (mode 644)
--- /dev/null
+++ tests/test_binarytree.c
+#include <stdio.h>
+#include <stdlib.h>
+#include "lftest.h"
+#include "lfbinarytree.h"
+
+int main() {
+ BinTree *tree = malloc(sizeof(BinTree));
+ bintree_init(tree, NULL);
+
+ int root = 0;
+ int l1 = 1;
+ int l2 = 2;
+ int r1 = 12;
+ int r2 = 200;
+
+ bintree_ins_left(tree, NULL, &root);
+ ASSERT_NOT_NULL(tree->root);
+
+ bintree_ins_left(tree, tree->root, &l1);
+ bintree_ins_left(tree, tree->root->left, &l2);
+ bintree_ins_right(tree, tree->root->left, &r2);
+ bintree_ins_right(tree, tree->root, &r1);
+ bintree_ins_right(tree, tree->root->right, &r2);
+ bintree_ins_left(tree, tree->root->right, &l1);
+
+ ASSERT_EQ(*(int *)tree->root->data, 0);
+ ASSERT_EQ(*(int *)tree->root->left->data, 1);
+ ASSERT_EQ(*(int *)tree->root->right->data, 12);
+
+ bintree_destroy(tree);
+ free(tree);
+
+ TEST_REPORT();
+}
blob - /dev/null
blob + 42b3af2038c8a4078c1f6260551b08f1dd30c637 (mode 644)
--- /dev/null
+++ tests/test_crypto.c
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "lftest.h"
+#include "lfcrypto.h"
+
+int main() {
+ char *in = "BUTT";
+ unsigned char *s = b64_encode(in, strlen(in));
+ ASSERT_STR_EQ((char *)s, "QlVUVA==");
+ free(s);
+
+ char *in2 = "a longer base64 test, apparently";
+ s = b64_encode(in2, strlen(in2));
+ ASSERT_STR_EQ((char *)s, "YSBsb25nZXIgYmFzZTY0IHRlc3QsIGFwcGFyZW50bHk=");
+ free(s);
+
+ char *out2 = "YSBsb25nZXIgYmFzZTY0IHRlc3QsIGFwcGFyZW50bHk=";
+ size_t s_sz = 0;
+ s = (unsigned char *) b64_decode(out2, strlen(out2), &s_sz);
+ ASSERT_STR_EQ((char *)s, "a longer base64 test, apparently");
+ ASSERT_EQ(strlen((char *)s), s_sz);
+ free(s);
+
+ s = hex_decode("DEADBEEF", &s_sz);
+ unsigned char h[4] = { 0xDE, 0xAD, 0xBE, 0xEF };
+ for (size_t i = 0; i < 4; ++i) {
+ ASSERT_EQ(s[i], h[i]);
+ }
+ free(s);
+
+ s = hex_decode("f00f5", &s_sz);
+ unsigned char h2[3] = { 0x0F, 0x00, 0xF5 };
+ for (size_t i = 0; i < 3; ++i) {
+ ASSERT_EQ(s[i], h2[i]);
+ }
+ free(s);
+
+ s = hex_decode("0xf00f5", &s_sz);
+ for (size_t i = 0; i < 3; ++i) {
+ ASSERT_EQ(s[i], h2[i]);
+ }
+ free(s);
+
+ char *enc_s = hex_encode(h, 4);
+ ASSERT_STR_EQ(enc_s, "deadbeef");
+ free(enc_s);
+
+ unsigned char hexsup[4] = { 0x53, 0x75, 0x70, 0x3F };
+ enc_s = hex_to_str(hexsup, 4);
+ ASSERT_STR_EQ(enc_s, "Sup?");
+ free(enc_s);
+
+ unsigned char *xor_s = repeating_key_xor_s("TEST", "HI");
+ enc_s = hex_encode(xor_s, 4);
+ ASSERT_STR_EQ(enc_s, "1c0c1b1d");
+ free(enc_s);
+ free(xor_s);
+
+ unsigned char ua[2] = {0x2, 0xF};
+ unsigned char ub[2] = {0x4, 0xE};
+ unsigned int hamming = hamming_distance(ua, ub, 2);
+ ASSERT_EQ(hamming, 3);
+
+ hamming = hamming_distance_s("this is a test", "wokka wokka!!!");
+ ASSERT_EQ(hamming, 37);
+
+ TEST_REPORT();
+}
blob - /dev/null
blob + 02121eab523233f0ce728df2fc6931aba6901619 (mode 644)
--- /dev/null
+++ tests/test_linkedlist.c
+#include <stdio.h>
+#include <stdlib.h>
+#include "lftest.h"
+#include "lflinkedlist.h"
+
+int main() {
+ List *list = malloc(sizeof(List));
+ ll_init(list, NULL);
+
+ int i = 1;
+ int j = 2;
+ int k = 4;
+
+ ll_ins_next(list, list->head, (void *) &i);
+ ll_ins_next(list, list->tail, (void *) &j);
+ ll_ins_next(list, list->tail, (void *) &k);
+
+ ASSERT_EQ(list->size, 3);
+
+ void *data;
+ ll_remove_next(list, list->head, &data);
+ ASSERT_EQ(*(int *)data, 2);
+ ASSERT_EQ(list->size, 2);
+
+ ll_destroy(list);
+ free(list);
+
+ TEST_REPORT();
+}
blob - /dev/null
blob + 48c994ca9950ca8f7a752bc05da4cd93b1d76514 (mode 644)
--- /dev/null
+++ tests/test_macos.c
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include "lftest.h"
+
+#if defined(__APPLE__) || defined(__MACH__)
+#include "lfmacos.h"
+
+int main() {
+ pid_t pid = getpid();
+ ProcessData *pd = new_ProcessData();
+ ASSERT_NOT_NULL(pd);
+
+ for (int i = 0; i < 2; i++) {
+ update_process(pid, pd);
+ sleep(1);
+ }
+ ASSERT_TRUE(pd->percent_cpu >= 0.0);
+
+ free(pd);
+ TEST_REPORT();
+}
+#else
+int main() {
+ printf("Skipped (not macOS)\n");
+ return 0;
+}
+#endif
blob - /dev/null
blob + 780eca704baf4f47eec03ef622bf50095d48d0bb (mode 644)
--- /dev/null
+++ tests/test_math.c
+#include <stdio.h>
+#include <stdlib.h>
+#include "lftest.h"
+#include "lfmath.h"
+
+int main() {
+ int i = 1, j = 2;
+ ASSERT_EQ(max_int(i, j), j);
+ ASSERT_EQ(min_int(i, j), i);
+
+ char *s = "10101101";
+ ASSERT_EQ(binstr_to_int(s), 173);
+
+ char *s2 = "1010_1101";
+ ASSERT_EQ(binstr_to_int(s2), 173);
+
+ i = 10;
+ i = clamp_int(i, 2, 5);
+ ASSERT_EQ(i, 5);
+
+ size_t sz = 0;
+ Point *line = bresenham(0, 0, 2, 5, &sz);
+ ASSERT_TRUE(sz > 0);
+ ASSERT_NOT_NULL(line);
+ free(line);
+
+ TEST_REPORT();
+}
blob - /dev/null
blob + 11d06ce65252457ffd479c6d1f893f96c1b21ca5 (mode 644)
--- /dev/null
+++ tests/test_memory.c
+#include <stdio.h>
+#include <stdlib.h>
+#include "lftest.h"
+#include "lfmemory.h"
+
+int main() {
+ ArenaAllocator *arena = malloc(sizeof(ArenaAllocator));
+ arena_init(arena, 1024);
+
+ int *i1 = arena_malloc(arena, sizeof(int));
+ int *i2 = arena_malloc(arena, sizeof(int));
+
+ *i1 = 1;
+ *i2 = 2;
+
+ ASSERT_LT(i1, i2);
+ ASSERT_LT(*i1, *i2);
+
+ long *l = arena_resize(arena, i1, sizeof(int), sizeof(long));
+ ASSERT_EQ(*l, 1);
+
+ unsigned char *char_test = arena_resize(arena, i2, sizeof(int), sizeof(unsigned char));
+ ASSERT_EQ(*char_test, 2);
+
+ /* Test in-place resize (most recent allocation) */
+ int *last = arena_malloc(arena, sizeof(int));
+ *last = 42;
+ long *last_resized = arena_resize(arena, last, sizeof(int), sizeof(long));
+ ASSERT_EQ((void *)last_resized, (void *)last);
+ ASSERT_EQ(*last_resized, 42);
+
+ /* Test resize returns NULL when arena is full */
+ void *too_big = arena_resize(arena, last_resized, sizeof(long), 2048);
+ ASSERT_NULL(too_big);
+
+ /* Test arena_malloc returns NULL when full */
+ void *full = arena_malloc(arena, 2048);
+ ASSERT_NULL(full);
+
+ /* Test arena_clear resets offsets */
+ arena_clear(arena);
+ int *after_clear = arena_malloc(arena, sizeof(int));
+ ASSERT_NOT_NULL(after_clear);
+
+ /* Test arena_resize_buf */
+ arena_resize_buf(arena, 2048);
+ void *big_alloc = arena_malloc(arena, 1500);
+ ASSERT_NOT_NULL(big_alloc);
+
+ arena_free(arena);
+ free(arena);
+
+ /* Test stack-allocated arena */
+ ArenaAllocator stack_arena;
+ arena_init(&stack_arena, 256);
+ int *si = arena_malloc(&stack_arena, sizeof(int));
+ ASSERT_NOT_NULL(si);
+ *si = 99;
+ ASSERT_EQ(*si, 99);
+ arena_free(&stack_arena);
+
+ PoolAllocator *pool = malloc(sizeof(PoolAllocator));
+ pool_init(pool, 64, 16, LF_DEFAULT_ALIGNMENT);
+ void *a = pool_alloc(pool);
+ void *b = pool_alloc(pool);
+ void *c = pool_alloc(pool);
+ void *d = pool_alloc(pool);
+
+ ASSERT_NOT_NULL(a);
+ ASSERT_NOT_NULL(b);
+ ASSERT_NOT_NULL(c);
+ ASSERT_NOT_NULL(d);
+
+ ASSERT_EQ(pool_count_available(pool), 0);
+ pool_free(pool, d);
+ ASSERT_EQ(pool_count_available(pool), 1);
+
+ /* Test pool_free_all resets properly */
+ pool_free_all(pool);
+ size_t chunk_count = 64 / 16;
+ ASSERT_EQ(pool_count_available(pool), chunk_count);
+
+ /* Allocate again after free_all to verify no corruption */
+ a = pool_alloc(pool);
+ ASSERT_NOT_NULL(a);
+ b = pool_alloc(pool);
+ ASSERT_NOT_NULL(b);
+
+ pool_destroy(pool);
+
+ TEST_REPORT();
+}
blob - /dev/null
blob + 9fa89c42d0b00b733699a8d0ad057431232d3eda (mode 644)
--- /dev/null
+++ tests/test_network.c
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <arpa/inet.h>
+#include <sys/socket.h>
+#include <pthread.h>
+#include "lftest.h"
+#include "lfnetwork.h"
+#include "lfinput.h"
+
+#define NET_MSG "TEST SEND"
+
+static void tcp_test_handler(Server *s) {
+ struct sockaddr_storage client_addr;
+ socklen_t client_addr_sz = sizeof(client_addr);
+ int new_fd = accept(s->fd, (struct sockaddr *) &client_addr, &client_addr_sz);
+ ASSERT_NEQ(new_fd, -1);
+ ASSERT_NEQ((int)send(new_fd, NET_MSG, 10, 0), -1);
+ close(new_fd);
+}
+
+static void *tcp_server_thread(void *vargp) {
+ (void)vargp;
+ Server *server = new_server(SERVERTYPE_TCP, "18632", tcp_test_handler);
+ serve(server, DEFAULT_BACKLOG);
+ delete_server(server);
+ return NULL;
+}
+
+static void udp_test_handler(Server *s) {
+ struct sockaddr_storage client_addr;
+ socklen_t client_addr_sz = sizeof(client_addr);
+ char recv_buf[128];
+
+ int r = (int) recvfrom(s->fd, recv_buf, 128, 0, (struct sockaddr *) &client_addr, &client_addr_sz);
+ ASSERT_TRUE(r > 0);
+ ASSERT_STR_EQ(recv_buf, NET_MSG);
+}
+
+static void *udp_server_thread(void *vargp) {
+ (void)vargp;
+ Server *server = new_server(SERVERTYPE_UDP, "18633", udp_test_handler);
+ serve(server, DEFAULT_BACKLOG);
+ delete_server(server);
+ return NULL;
+}
+
+int main() {
+ pthread_t srv_tid;
+ pthread_create(&srv_tid, NULL, tcp_server_thread, NULL);
+
+ sleep(1);
+ const char *s = capture_system("echo hello | nc localhost 18632", 0);
+ ASSERT_STR_EQ(s, NET_MSG);
+ free((char *) s);
+
+ pthread_join(srv_tid, NULL);
+
+ pthread_create(&srv_tid, NULL, udp_server_thread, NULL);
+ sleep(1);
+ system("echo hello | nc localhost 18633");
+
+ pthread_join(srv_tid, NULL);
+
+ TEST_REPORT();
+}
blob - /dev/null
blob + 57abe442572fbbbc6526d2271a7729463d8b5d61 (mode 644)
--- /dev/null
+++ tests/test_parsing.c
+#include <stdio.h>
+#include "lftest.h"
+#include "lfparsing.h"
+
+int main() {
+ char *nonsense = "8d82jI|dms~<>s2d";
+ char *english = "This is an English sentence!";
+ ASSERT_TRUE(simple_english_scoring(english) > simple_english_scoring(nonsense));
+
+ TEST_REPORT();
+}
blob - /dev/null
blob + 278cc30436e944c2424022d7e15b7ed2b6d3e657 (mode 644)
--- /dev/null
+++ tests/test_set.c
+#include <stdio.h>
+#include <stdlib.h>
+#include "lftest.h"
+#include "lfset.h"
+
+static int int_match(const void *a, const void *b) {
+ return *((int *) a) == *((int *) b);
+}
+
+int main() {
+ Set *set = malloc(sizeof(Set));
+ set_init(set, int_match, NULL);
+
+ int i = 1;
+ int j = 2;
+ int k = 2;
+
+ set_insert(set, &i);
+ set_insert(set, &j);
+ set_insert(set, &k);
+
+ ASSERT_EQ(set->size, 2); /* duplicate should not be inserted */
+
+ int i2 = 1;
+ int j2 = 4;
+
+ Set *set2 = malloc(sizeof(Set));
+ set_init(set2, int_match, NULL);
+ set_insert(set2, &i2);
+ set_insert(set2, &j2);
+
+ Set *set_u = malloc(sizeof(Set));
+ Set *set_i = malloc(sizeof(Set));
+ Set *set_d = malloc(sizeof(Set));
+
+ set_union(set_u, set, set2);
+ set_difference(set_d, set, set2);
+ set_intersection(set_i, set, set2);
+
+ ASSERT_EQ(set_u->size, 3); /* {1, 2, 4} */
+ ASSERT_EQ(set_d->size, 1); /* {2} */
+ ASSERT_EQ(set_i->size, 1); /* {1} */
+
+ set_destroy(set);
+ set_destroy(set2);
+ set_destroy(set_u);
+ set_destroy(set_i);
+ set_destroy(set_d);
+ free(set);
+ free(set2);
+ free(set_u);
+ free(set_i);
+ free(set_d);
+
+ TEST_REPORT();
+}
blob - /dev/null
blob + ae60a2174307462510938d3759e5dd662d312bdf (mode 644)
--- /dev/null
+++ tests/test_stack.c
+#include <stdio.h>
+#include <stdlib.h>
+#include "lftest.h"
+#include "lfstack.h"
+
+int main() {
+ Stack *stack = malloc(sizeof(Stack));
+ stack_init(stack, NULL);
+
+ int a = 1, b = 2;
+ stack_push(stack, &a);
+ stack_push(stack, &b);
+ ASSERT_EQ(stack->size, 2);
+
+ int *p = NULL;
+ stack_pop(stack, (void **) &p);
+ ASSERT_EQ(*p, 2);
+
+ stack_pop(stack, (void **) &p);
+ ASSERT_EQ(*p, 1);
+ ASSERT_EQ(stack->size, 0);
+
+ stack_destroy(stack);
+ free(stack);
+
+ TEST_REPORT();
+}
blob - /dev/null
blob + ba720d22e8bd1104d7cf1fc2952c5df00d8f4b50 (mode 644)
--- /dev/null
+++ tests/test_string.c
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "lftest.h"
+#include "lfstring.h"
+
+int main() {
+ const char *haystack =
+ "Test one two one and also maybe two but not Gabe's least favorite number, which is not one.";
+ const char *needles[] = {
+ "one",
+ "two",
+ "Gabe"
+ };
+
+ size_t sub_sz = 0;
+ size_t *subs = NULL;
+ find_substrings(haystack, needles[0], &sub_sz, &subs);
+
+ ASSERT_EQ(sub_sz, 3);
+ ASSERT_EQ(subs[0], 5);
+ ASSERT_EQ(subs[1], 13);
+ ASSERT_EQ(subs[2], 87);
+
+ char *s = substr(haystack, subs[0], strlen(needles[0]));
+ ASSERT_STR_EQ(s, needles[0]);
+
+ free(s);
+ free(subs);
+ subs = NULL;
+
+ find_substrings(haystack, needles[1], &sub_sz, &subs);
+ ASSERT_EQ(sub_sz, 2);
+ ASSERT_EQ(subs[0], 9);
+
+ free(subs);
+ subs = NULL;
+
+ find_substrings("test one two", "nope", &sub_sz, &subs);
+ ASSERT_EQ(sub_sz, 0);
+ ASSERT_NULL(subs);
+ free(subs);
+ subs = NULL;
+
+ find_substrings("123", "nopes", &sub_sz, &subs);
+ ASSERT_EQ(sub_sz, 0);
+ ASSERT_NULL(subs);
+ free(subs);
+ subs = NULL;
+
+ TEST_REPORT();
+}
blob - /dev/null
blob + efca273644b392b0885d8e9f10840b81d4e34dc7 (mode 644)
--- /dev/null
+++ tests/test_vector.c
+#include <stdio.h>
+#include <stdlib.h>
+#include "lftest.h"
+#include "lfvector.h"
+
+int main() {
+ Vector *v = malloc(sizeof(Vector));
+ vec_init(v, NULL);
+
+ int e0 = 0;
+ int e1 = 1;
+ int e2 = 2;
+ int e3 = 3;
+ int e4 = 4;
+
+ vec_push(v, &e0);
+ ASSERT_EQ(v->length, 1);
+ int *t = vec_at(v, 0);
+ ASSERT_EQ(*t, 0);
+
+ vec_push(v, &e1);
+ vec_push(v, &e2);
+ ASSERT_EQ(v->length, 3);
+
+ t = (int *) vec_safe_at(v, 3);
+ ASSERT_NULL(t);
+
+ vec_push(v, &e3);
+ vec_insert(v, &e4, 1);
+
+ t = (int *) vec_at(v, 4);
+ ASSERT_EQ(*t, e3);
+ t = (int *) vec_at(v, 1);
+ ASSERT_EQ(*t, e4);
+
+ const int *min = vec_min(v, vec_cmp_int);
+ const int *max = vec_max(v, vec_cmp_int);
+ ASSERT_EQ(*min, e0);
+ ASSERT_EQ(*max, e4);
+
+ t = (int *) vec_remove(v, 1);
+ ASSERT_NOT_NULL(t);
+ ASSERT_EQ(*t, 4);
+
+ t = (int *) vec_remove(v, 10);
+ ASSERT_NULL(t);
+
+ vec_shrink(v);
+ ASSERT_EQ(vec_len(v), vec_cap(v));
+
+ vec_clear(v);
+ ASSERT_EQ(vec_len(v), 0);
+
+ vec_grow_to(v, 10);
+ ASSERT_EQ(vec_cap(v), 10);
+ ASSERT_EQ(vec_len(v), 0);
+
+ vec_destroy(v);
+ free(v);
+
+ TEST_REPORT();
+}