summaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
Diffstat (limited to 'tests')
-rw-r--r--tests/array.c256
-rw-r--r--tests/array.h8
-rw-r--r--tests/array_typed.c261
-rw-r--r--tests/array_typed.h8
-rw-r--r--tests/main.c23
-rw-r--r--tests/ring_buffer.c198
-rw-r--r--tests/ring_buffer.h8
-rw-r--r--tests/str.c191
-rw-r--r--tests/str.h8
9 files changed, 961 insertions, 0 deletions
diff --git a/tests/array.c b/tests/array.c
new file mode 100644
index 0000000..ad03c3c
--- /dev/null
+++ b/tests/array.c
@@ -0,0 +1,256 @@
+#include <al/test.h>
+#include <al/array.h>
+
+#include "array.h"
+
+struct test_t {
+ u32 i;
+};
+
+static bool array_test_init(void)
+{
+ AL_TEST_START("array_init");
+
+ array(u32) arr;
+ al_array_init(arr);
+
+ AL_TEST_EQ((void *)arr.data, NULL, ptr);
+ AL_TEST_EQ(arr.alloc, 0, u32);
+ AL_TEST_EQ(arr.size, 0, u32);
+
+ al_array_free(arr);
+
+ AL_TEST_END();
+}
+
+static bool array_test_reserve(void)
+{
+ AL_TEST_START("array_reserve");
+
+ array(u32) arr;
+ al_array_init(arr);
+
+ al_array_reserve(arr, 64);
+
+ AL_TEST_NEQ((void *)arr.data, NULL, ptr);
+ AL_TEST_EQ(arr.alloc, 128, u32);
+
+ al_array_reserve(arr, 128);
+
+ AL_TEST_NEQ((void *)arr.data, NULL, ptr);
+ AL_TEST_EQ(arr.alloc, 256, u32);
+
+ al_array_free(arr);
+
+ AL_TEST_END();
+}
+
+static bool array_test_at(void)
+{
+ AL_TEST_START("array_at");
+
+ array(u32) arr;
+ al_array_init(arr);
+
+ u32 x = 5;
+ al_array_push(arr, x);
+
+ AL_TEST_EQ(al_array_at(arr, 0), 5, u32);
+
+ al_array_free(arr);
+
+ AL_TEST_END();
+}
+
+static bool array_test_last(void)
+{
+ AL_TEST_START("array_last");
+
+ array(u32) arr;
+ al_array_init(arr);
+
+ u32 x = 1, y = 2, z = 3;
+
+ al_array_push(arr, x);
+ al_array_push(arr, y);
+ al_array_push(arr, z);
+
+ AL_TEST_EQ(al_array_last(arr), 3, u32);
+
+ al_array_free(arr);
+
+ AL_TEST_END();
+}
+
+static bool array_test_push(void)
+{
+ AL_TEST_START("array_push");
+
+ array(u32) arr;
+ al_array_init(arr);
+
+ u32 x = 4, y = 5;
+
+ al_array_push(arr, x);
+ al_array_push(arr, y);
+
+ AL_TEST_EQ(arr.size, 2, u32);
+ AL_TEST_EQ(al_array_at(arr, 0), x, u32);
+ AL_TEST_EQ(al_array_at(arr, 1), y, u32);
+
+ al_array_free(arr);
+
+ AL_TEST_END();
+}
+
+static bool array_test_pop(void)
+{
+ AL_TEST_START("array_pop");
+
+ array(u32) arr;
+ al_array_init(arr);
+
+ u32 x = 4, y = 5;
+
+ al_array_push(arr, x);
+ al_array_push(arr, y);
+
+ u32 rx, ry;
+
+ ry = al_array_pop(arr);
+
+ AL_TEST_EQ(arr.size, 1, u32);
+
+ rx = al_array_pop(arr);
+
+ AL_TEST_EQ(arr.size, 0, u32);
+ AL_TEST_EQ(rx, x, u32);
+ AL_TEST_EQ(ry, y, u32);
+
+ al_array_free(arr);
+
+ AL_TEST_END();
+}
+
+static bool array_test_remove_at(void)
+{
+ AL_TEST_START("array_remove_at");
+
+ array(u32) arr;
+ al_array_init(arr);
+ al_array_reserve(arr, 12);
+
+ u32 array_before[] = { 1, 2, 3, 4, 5, 6 };
+ u32 array_after[] = { 2, 3, 4 };
+
+ for (u32 i = 0; i < sizeof(array_before) / sizeof(u32); i++) {
+ al_array_push(arr, array_before[i]);
+ }
+
+ al_array_remove_at(arr, 0);
+ al_array_remove_at(arr, 3);
+ al_array_remove_at(arr, 3);
+
+ AL_TEST_EQ(arr.size, (u32)(sizeof(array_after) / sizeof(u32)), u32);
+
+ for (u32 i = 0; i < sizeof(array_after) / sizeof(u32); i++) {
+ AL_TEST_EQ(al_array_at(arr, i), array_after[i], u32);
+ }
+
+ al_array_free(arr);
+
+ AL_TEST_END();
+}
+
+static bool array_test_pop_at(void)
+{
+ AL_TEST_START("array_pop_at");
+
+ array(u32) arr;
+ al_array_init(arr);
+
+ u32 array_before[] = { 1, 2, 3, 4, 5, 6 };
+ u32 array_after[] = { 2, 3, 4 };
+
+ for (u32 i = 0; i < sizeof(array_before) / sizeof(u32); i++) {
+ al_array_push(arr, array_before[i]);
+ }
+
+ u32 x, y, z;
+
+ al_array_pop_at(arr, 0, x);
+ al_array_pop_at(arr, 3, y);
+ al_array_pop_at(arr, 3, z);
+
+ AL_TEST_EQ(x, array_before[0], u32);
+ AL_TEST_EQ(y, array_before[4], u32);
+ AL_TEST_EQ(z, array_before[5], u32);
+
+ AL_TEST_EQ(arr.size, (u32)(sizeof(array_after) / sizeof(u32)), u32);
+
+ for (u32 i = 0; i < sizeof(array_after) / sizeof(u32); i++) {
+ AL_TEST_EQ(al_array_at(arr, i), array_after[i], u32);
+ }
+
+ al_array_free(arr);
+
+ AL_TEST_END();
+}
+
+static bool array_test_insert(void)
+{
+ AL_TEST_START("array_insert");
+
+ array(struct test_t) arr;
+ al_array_init(arr);
+
+ struct test_t x = {
+ .i = 5
+ };
+
+ struct test_t y = {
+ .i = 5
+ };
+
+ struct test_t z = {
+ .i = 5
+ };
+
+ al_array_insert(arr, x, 1);
+ al_array_insert(arr, y, 0);
+ al_array_insert(arr, z, 1);
+
+ AL_TEST_EQ(al_array_at(arr, 3).i, x.i, u32);
+ AL_TEST_EQ(al_array_at(arr, 0).i, y.i, u32);
+ AL_TEST_EQ(al_array_at(arr, 1).i, z.i, u32);
+
+ AL_TEST_EQ(arr.size, 4, u32);
+
+ al_array_remove_at(arr, 3);
+
+ AL_TEST_EQ(arr.size, 3, u32);
+
+ AL_TEST_EQ(al_array_at(arr, 0).i, y.i, u32);
+ AL_TEST_EQ(al_array_at(arr, 1).i, z.i, u32);
+
+ al_array_free(arr);
+
+ AL_TEST_END();
+}
+
+bool array_tests_run(void)
+{
+ AL_TEST_START_GROUP("array");
+
+ AL_TEST_RUN(array_test_init);
+ AL_TEST_RUN(array_test_reserve);
+ AL_TEST_RUN(array_test_at);
+ AL_TEST_RUN(array_test_last);
+ AL_TEST_RUN(array_test_push);
+ AL_TEST_RUN(array_test_pop);
+ AL_TEST_RUN(array_test_remove_at);
+ AL_TEST_RUN(array_test_pop_at);
+ AL_TEST_RUN(array_test_insert);
+
+ AL_TEST_END_GROUP();
+}
diff --git a/tests/array.h b/tests/array.h
new file mode 100644
index 0000000..881f936
--- /dev/null
+++ b/tests/array.h
@@ -0,0 +1,8 @@
+#ifndef _AL_ARRAY_TESTS_H
+#define _AL_ARRAY_TESTS_H
+
+#include <al/types.h>
+
+bool array_tests_run(void);
+
+#endif // _AL_ARRAY_TESTS_H
diff --git a/tests/array_typed.c b/tests/array_typed.c
new file mode 100644
index 0000000..21620e5
--- /dev/null
+++ b/tests/array_typed.c
@@ -0,0 +1,261 @@
+#include <al/test.h>
+#include <al/array_typed.h>
+
+#include "array_typed.h"
+
+struct test_t {
+ u32 i;
+};
+
+AL_ARRAY_INLINE_STORAGE_DEFINE(u32, u32, 64)
+AL_ARRAY_DEFINE(u32, u32)
+AL_ARRAY_INLINE_STORAGE_DEFINE(test_t, struct test_t, 16)
+
+static bool array_test_init(void)
+{
+ AL_TEST_START("array_init");
+
+ array(u32, 64) arr;
+ al_array_init(u32, 64)(&arr);
+
+ AL_TEST_EQ((void *)arr.data, NULL, ptr);
+ AL_TEST_EQ(arr.alloc, 64, u32);
+ AL_TEST_EQ(arr.size, 0, u32);
+ AL_TEST_EQ(sizeof(arr.inline_data), 64 * sizeof(u32), size_t);
+
+ al_array_free(u32, 64)(&arr);
+
+ AL_TEST_END();
+}
+
+static bool array_test_reserve(void)
+{
+ AL_TEST_START("array_reserve");
+
+ array(u32, 64) arr;
+ al_array_init(u32, 64)(&arr);
+
+ al_array_reserve(u32, 64)(&arr, 64);
+
+ AL_TEST_EQ((void *)arr.data, NULL, ptr);
+ AL_TEST_EQ(arr.alloc, 64, u32);
+
+ al_array_reserve(u32, 64)(&arr, 128);
+
+ AL_TEST_NEQ((void *)arr.data, NULL, ptr);
+ AL_TEST_EQ(arr.alloc, 256, u32);
+
+ al_array_free(u32, 64)(&arr);
+
+ AL_TEST_END();
+}
+
+static bool array_test_at(void)
+{
+ AL_TEST_START("array_at");
+
+ array(u32, 64) arr;
+ al_array_init(u32, 64)(&arr);
+
+ u32 x = 5;
+ al_array_push(u32, 64)(&arr, &x);
+
+ AL_TEST_EQ(*al_array_at(u32, 64)(&arr, 0), 5, u32);
+
+ al_array_free(u32, 64)(&arr);
+
+ AL_TEST_END();
+}
+
+static bool array_test_last(void)
+{
+ AL_TEST_START("array_last");
+
+ array(u32, 64) arr;
+ al_array_init(u32, 64)(&arr);
+
+ u32 x = 1, y = 2, z = 3;
+
+ al_array_push(u32, 64)(&arr, &x);
+ al_array_push(u32, 64)(&arr, &y);
+ al_array_push(u32, 64)(&arr, &z);
+
+ AL_TEST_EQ(*al_array_last(u32, 64)(&arr), 3, u32);
+
+ al_array_free(u32, 64)(&arr);
+
+ AL_TEST_END();
+}
+
+static bool array_test_push(void)
+{
+ AL_TEST_START("array_push");
+
+ array(u32, 64) arr;
+ al_array_init(u32, 64)(&arr);
+
+ u32 x = 4, y = 5;
+
+ al_array_push(u32, 64)(&arr, &x);
+ al_array_push(u32, 64)(&arr, &y);
+
+ AL_TEST_EQ(arr.size, 2, u32);
+ AL_TEST_EQ(*al_array_at(u32, 64)(&arr, 0), x, u32);
+ AL_TEST_EQ(*al_array_at(u32, 64)(&arr, 1), y, u32);
+
+ al_array_free(u32, 64)(&arr);
+
+ AL_TEST_END();
+}
+
+static bool array_test_pop(void)
+{
+ AL_TEST_START("array_pop");
+
+ array(u32, 64) arr;
+ al_array_init(u32, 64)(&arr);
+
+ u32 x = 4, y = 5;
+
+ al_array_push(u32, 64)(&arr, &x);
+ al_array_push(u32, 64)(&arr, &y);
+
+ u32 rx, ry;
+
+ al_array_pop(u32, 64)(&arr, &ry);
+
+ AL_TEST_EQ(arr.size, 1, u32);
+
+ al_array_pop(u32, 64)(&arr, &rx);
+
+ AL_TEST_EQ(arr.size, 0, u32);
+ AL_TEST_EQ(rx, x, u32);
+ AL_TEST_EQ(ry, y, u32);
+
+ al_array_free(u32, 64)(&arr);
+
+ AL_TEST_END();
+}
+
+static bool array_test_remove_at(void)
+{
+ AL_TEST_START("array_remove_at");
+
+ array(u32) arr;
+ al_array_init(u32)(&arr);
+ al_array_reserve(u32)(&arr, 12);
+
+ u32 array_before[] = { 1, 2, 3, 4, 5, 6 };
+ u32 array_after[] = { 2, 3, 4 };
+
+ for (u32 i = 0; i < sizeof(array_before) / sizeof(u32); i++) {
+ al_array_push(u32)(&arr, &array_before[i]);
+ }
+
+ al_array_remove_at(u32)(&arr, 0);
+ al_array_remove_at(u32)(&arr, 3);
+ al_array_remove_at(u32)(&arr, 3);
+
+ AL_TEST_EQ(arr.size, (u32)(sizeof(array_after) / sizeof(u32)), u32);
+
+ for (u32 i = 0; i < sizeof(array_after) / sizeof(u32); i++) {
+ AL_TEST_EQ(*al_array_at(u32)(&arr, i), array_after[i], u32);
+ }
+
+ al_array_free(u32)(&arr);
+
+ AL_TEST_END();
+}
+
+static bool array_test_pop_at(void)
+{
+ AL_TEST_START("array_pop_at");
+
+ array(u32, 64) arr;
+ al_array_init(u32, 64)(&arr);
+
+ u32 array_before[] = { 1, 2, 3, 4, 5, 6 };
+ u32 array_after[] = { 2, 3, 4 };
+
+ for (u32 i = 0; i < sizeof(array_before) / sizeof(u32); i++) {
+ al_array_push(u32, 64)(&arr, &array_before[i]);
+ }
+
+ u32 x, y, z;
+
+ al_array_pop_at(u32, 64)(&arr, 0, &x);
+ al_array_pop_at(u32, 64)(&arr, 3, &y);
+ al_array_pop_at(u32, 64)(&arr, 3, &z);
+
+ AL_TEST_EQ(x, array_before[0], u32);
+ AL_TEST_EQ(y, array_before[4], u32);
+ AL_TEST_EQ(z, array_before[5], u32);
+
+ AL_TEST_EQ(arr.size, (u32)(sizeof(array_after) / sizeof(u32)), u32);
+
+ for (u32 i = 0; i < sizeof(array_after) / sizeof(u32); i++) {
+ AL_TEST_EQ(*al_array_at(u32, 64)(&arr, i), array_after[i], u32);
+ }
+
+ al_array_free(u32, 64)(&arr);
+
+ AL_TEST_END();
+}
+
+static bool array_test_insert(void)
+{
+ AL_TEST_START("array_insert");
+
+ array(test_t, 16) arr;
+ al_array_init(test_t, 16)(&arr);
+
+ struct test_t x = {
+ .i = 5
+ };
+
+ struct test_t y = {
+ .i = 5
+ };
+
+ struct test_t z = {
+ .i = 5
+ };
+
+ al_array_insert(test_t, 16)(&arr, &x, 1);
+ al_array_insert(test_t, 16)(&arr, &y, 0);
+ al_array_insert(test_t, 16)(&arr, &z, 1);
+
+ AL_TEST_EQ(al_array_at(test_t, 16)(&arr, 3)->i, x.i, u32);
+ AL_TEST_EQ(al_array_at(test_t, 16)(&arr, 0)->i, y.i, u32);
+ AL_TEST_EQ(al_array_at(test_t, 16)(&arr, 1)->i, z.i, u32);
+
+ AL_TEST_EQ(arr.size, 4, u32);
+
+ al_array_remove_at(test_t, 16)(&arr, 3);
+
+ AL_TEST_EQ(arr.size, 3, u32);
+
+ AL_TEST_EQ(al_array_at(test_t, 16)(&arr, 0)->i, y.i, u32);
+ AL_TEST_EQ(al_array_at(test_t, 16)(&arr, 1)->i, z.i, u32);
+
+ al_array_free(test_t, 16)(&arr);
+
+ AL_TEST_END();
+}
+
+bool array_typed_tests_run(void)
+{
+ AL_TEST_START_GROUP("array_typed");
+
+ AL_TEST_RUN(array_test_init);
+ AL_TEST_RUN(array_test_reserve);
+ AL_TEST_RUN(array_test_at);
+ AL_TEST_RUN(array_test_last);
+ AL_TEST_RUN(array_test_push);
+ AL_TEST_RUN(array_test_pop);
+ AL_TEST_RUN(array_test_remove_at);
+ AL_TEST_RUN(array_test_pop_at);
+ AL_TEST_RUN(array_test_insert);
+
+ AL_TEST_END_GROUP();
+}
diff --git a/tests/array_typed.h b/tests/array_typed.h
new file mode 100644
index 0000000..644cce6
--- /dev/null
+++ b/tests/array_typed.h
@@ -0,0 +1,8 @@
+#ifndef _AL_ARRAY_TYPED_TESTS_H
+#define _AL_ARRAY_TYPED_TESTS_H
+
+#include <al/types.h>
+
+bool array_typed_tests_run(void);
+
+#endif // _AL_ARRAY_TYPED_TESTS_H
diff --git a/tests/main.c b/tests/main.c
new file mode 100644
index 0000000..622e969
--- /dev/null
+++ b/tests/main.c
@@ -0,0 +1,23 @@
+#include <al/lib.h>
+
+#include "array.h"
+#ifdef HAVE_GNU_EXTENSIONS
+#include "array_typed.h"
+#endif
+#include "str.h"
+#include "ring_buffer.h"
+
+s32 main(void)
+{
+ if (!array_tests_run()) goto fail;
+#ifdef HAVE_GNU_EXTENSIONS
+ if (!array_typed_tests_run()) goto fail;
+#endif
+ if (!str_tests_run()) goto fail;
+ if (!ring_buffer_tests_run()) goto fail;
+
+ return EXIT_SUCCESS;
+
+fail:
+ return EXIT_FAILURE;
+}
diff --git a/tests/ring_buffer.c b/tests/ring_buffer.c
new file mode 100644
index 0000000..3ed7d4d
--- /dev/null
+++ b/tests/ring_buffer.c
@@ -0,0 +1,198 @@
+#include <al/test.h>
+#include <al/ring_buffer.h>
+
+#define TEST_BUFFER_SIZE 32
+
+static u8 buffer[TEST_BUFFER_SIZE];
+static u8 buffer_ret[TEST_BUFFER_SIZE];
+static u8 buffer_half[TEST_BUFFER_SIZE / 2] = {0};
+static u8 buffer_over[TEST_BUFFER_SIZE + 16] = {0};
+
+static bool ring_buffer_test_init(void)
+{
+ AL_TEST_START("ring_buffer_init");
+
+ struct al_ring_buffer buf;
+ al_ring_buffer_init(&buf, buffer, TEST_BUFFER_SIZE);
+
+ AL_TEST_EQ(buf.start, buffer, ptr);
+ AL_TEST_EQ(buf.end, buffer + TEST_BUFFER_SIZE, ptr);
+ AL_TEST_EQ(al_atomic_ptr_load(&buf.read, AL_ATOMIC_RELAXED), buffer, ptr);
+ AL_TEST_EQ(al_atomic_ptr_load(&buf.write, AL_ATOMIC_RELAXED), buffer, ptr);
+
+ AL_TEST_END();
+}
+
+static bool ring_buffer_test_space(void)
+{
+ AL_TEST_START("ring_buffer_space");
+
+ struct al_ring_buffer buf;
+ al_ring_buffer_init(&buf, buffer, TEST_BUFFER_SIZE);
+
+ AL_TEST_EQ(al_ring_buffer_space(&buf), TEST_BUFFER_SIZE - 1, size_t);
+
+ AL_TEST_END();
+}
+
+static bool ring_buffer_test_occupied(void)
+{
+ AL_TEST_START("ring_buffer_occupied");
+
+ struct al_ring_buffer buf;
+ al_ring_buffer_init(&buf, buffer, TEST_BUFFER_SIZE);
+
+ AL_TEST_EQ(al_ring_buffer_occupied(&buf), 0, size_t);
+
+ AL_TEST_END();
+}
+
+static bool ring_buffer_test_read_and_write_chunk(void)
+{
+ AL_TEST_START("ring_buffer_read_and_write_chunk");
+
+ struct al_ring_buffer buf;
+ al_ring_buffer_init(&buf, buffer, TEST_BUFFER_SIZE);
+
+ char *data = "TestTEST";
+ size_t data_size = al_strlen(data) + 1;
+
+ size_t size;
+ u8 *ptr = al_ring_buffer_write_chunk(&buf, &size);
+
+ AL_TEST_EQ(size, TEST_BUFFER_SIZE - 1, size_t);
+
+ al_memcpy(ptr, data, data_size);
+ al_ring_buffer_append(&buf, ptr, data_size);
+
+ AL_TEST_EQ(al_ring_buffer_occupied(&buf), data_size, size_t);
+ AL_TEST_EQ(al_ring_buffer_space(&buf), (TEST_BUFFER_SIZE - 1) - data_size, size_t);
+
+ ptr = al_ring_buffer_read_chunk(&buf, &size);
+ AL_TEST_EQ(size, data_size, size_t);
+ AL_TEST_TRUE((strcmp((char *)ptr, data) == 0));
+ al_ring_buffer_consume(&buf, ptr, size);
+
+ AL_TEST_EQ(al_ring_buffer_occupied(&buf), 0, size_t);
+ AL_TEST_EQ(al_ring_buffer_space(&buf), TEST_BUFFER_SIZE - 1, size_t);
+
+ AL_TEST_END();
+}
+
+static bool ring_buffer_test_read_and_write(void)
+{
+ AL_TEST_START("ring_buffer_read_and_write");
+
+ struct al_ring_buffer buf;
+ al_ring_buffer_init(&buf, buffer, TEST_BUFFER_SIZE);
+
+ char *data = "TestTEST";
+ size_t data_size = al_strlen(data) + 1;
+
+ al_ring_buffer_write(&buf, (u8 *)data, data_size);
+
+ AL_TEST_EQ(al_ring_buffer_occupied(&buf), data_size, size_t);
+ AL_TEST_EQ(al_ring_buffer_space(&buf), (TEST_BUFFER_SIZE - 1) - data_size, size_t);
+
+ al_ring_buffer_read(&buf, (u8 *)buffer_ret, data_size);
+ AL_TEST_TRUE((strcmp((char *)buffer_ret, data) == 0));
+
+ AL_TEST_EQ(al_ring_buffer_occupied(&buf), 0, size_t);
+ AL_TEST_EQ(al_ring_buffer_space(&buf), TEST_BUFFER_SIZE - 1, size_t);
+
+ al_memset(buffer_half, 'd', sizeof(buffer_half));
+
+ AL_TEST_EQ(al_ring_buffer_write(&buf, buffer_half, sizeof(buffer_half)), sizeof(buffer_half), size_t);
+ AL_TEST_EQ(al_ring_buffer_occupied(&buf), sizeof(buffer_half), size_t);
+ AL_TEST_EQ(al_ring_buffer_space(&buf), (TEST_BUFFER_SIZE - 1) - sizeof(buffer_half), size_t);
+
+ AL_TEST_EQ(al_ring_buffer_read(&buf, (u8 *)buffer_ret, data_size), data_size, size_t);
+ AL_TEST_TRUE(al_memcmp(buffer_ret, "ddddddddd", data_size) == 0);
+
+ AL_TEST_EQ(al_ring_buffer_write(&buf, buffer_half, sizeof(buffer_half)), sizeof(buffer_half), size_t);
+ AL_TEST_EQ(al_ring_buffer_occupied(&buf), TEST_BUFFER_SIZE - data_size, size_t);
+ AL_TEST_LT(al_atomic_ptr_load(&buf.write, AL_ATOMIC_RELAXED), al_atomic_ptr_load(&buf.read, AL_ATOMIC_RELAXED), ptr);
+
+ size_t space = al_ring_buffer_space(&buf);
+ AL_TEST_EQ(space, data_size - 1, size_t);
+ AL_TEST_EQ(al_ring_buffer_write(&buf, buffer_over, sizeof(buffer_over)), space, size_t);
+
+ AL_TEST_EQ(al_ring_buffer_read(&buf, buffer_ret, sizeof(buffer_over)), TEST_BUFFER_SIZE - 1, size_t);
+
+ AL_TEST_END();
+}
+
+static bool ring_buffer_test_peek(void)
+{
+ AL_TEST_START("ring_buffer_peek");
+
+ struct al_ring_buffer buf;
+ al_ring_buffer_init(&buf, buffer, TEST_BUFFER_SIZE);
+
+ char *data = "abcabcabcabcabcabcabcabcabcabca";
+ size_t data_size = al_strlen(data);
+ AL_TEST_EQ(data_size, TEST_BUFFER_SIZE - 1, size_t);
+
+ al_ring_buffer_write(&buf, (u8 *)data, data_size);
+
+ al_ring_buffer_peek(&buf, buffer_ret, 0, data_size);
+ AL_TEST_TRUE(al_memcmp(buffer_ret, data, data_size) == 0);
+
+ al_ring_buffer_peek(&buf, buffer_ret, 3, data_size);
+ AL_TEST_TRUE(al_memcmp(buffer_ret, data + 3, data_size - 3) == 0);
+
+ al_ring_buffer_read(&buf, buffer_ret, 3);
+ AL_TEST_TRUE(al_memcmp(buffer_ret, data, 3) == 0);
+ al_ring_buffer_write(&buf, (u8 *)data, data_size);
+
+ al_ring_buffer_peek(&buf, buffer_ret, 3, data_size);
+ AL_TEST_TRUE(al_memcmp(buffer_ret, data + 6, data_size - 6) == 0);
+
+ al_ring_buffer_peek(&buf, buffer_ret, 0, data_size);
+ AL_TEST_TRUE(al_memcmp(buffer_ret, "abcabcabcabcabcabcabcabcabcaabc", data_size) == 0);
+
+ al_ring_buffer_read(&buf, buffer_ret, (TEST_BUFFER_SIZE - 1) - 4);
+
+ al_ring_buffer_peek(&buf, buffer_ret, 0, data_size);
+ AL_TEST_TRUE(al_memcmp(buffer_ret, "aab", 3) == 0);
+
+ AL_TEST_EQ(al_ring_buffer_peek(&buf, buffer_ret, 10, data_size), 0, size_t);
+ AL_TEST_EQ(al_ring_buffer_peek(&buf, buffer_ret, 3, data_size), 1, size_t);
+ AL_TEST_EQ(al_ring_buffer_peek(&buf, buffer_ret, 4, data_size), 0, size_t);
+
+ al_ring_buffer_peek(&buf, buffer_ret, 1, data_size);
+ AL_TEST_TRUE(al_memcmp(buffer_ret, "abc", 3) == 0);
+
+ AL_TEST_EQ(al_ring_buffer_peek(&buf, buffer_ret, 2, data_size), 2, size_t);
+ AL_TEST_TRUE(al_memcmp(buffer_ret, "bc", 2) == 0);
+
+ al_ring_buffer_read(&buf, buffer_ret, 1);
+
+ AL_TEST_EQ(al_ring_buffer_peek(&buf, buffer_ret, 0, data_size), 3, size_t);
+ AL_TEST_TRUE(al_memcmp(buffer_ret, "abc", 3) == 0);
+
+ AL_TEST_EQ(al_ring_buffer_peek(&buf, buffer_ret, 3, data_size), 0, size_t);
+ AL_TEST_EQ(al_ring_buffer_peek(&buf, buffer_ret, 4, data_size), 0, size_t);
+
+ AL_TEST_EQ(al_ring_buffer_read(&buf, buffer_ret, 4), 3, size_t);
+
+ AL_TEST_EQ(al_ring_buffer_peek(&buf, buffer_ret, 0, data_size), 0, size_t);
+ AL_TEST_EQ(al_ring_buffer_peek(&buf, buffer_ret, 1, data_size), 0, size_t);
+ AL_TEST_EQ(al_ring_buffer_peek(&buf, buffer_ret, 2, data_size), 0, size_t);
+
+ AL_TEST_END();
+}
+
+bool ring_buffer_tests_run(void)
+{
+ AL_TEST_START_GROUP("ring_buffer");
+
+ AL_TEST_RUN(ring_buffer_test_init);
+ AL_TEST_RUN(ring_buffer_test_space);
+ AL_TEST_RUN(ring_buffer_test_occupied);
+ AL_TEST_RUN(ring_buffer_test_read_and_write_chunk);
+ AL_TEST_RUN(ring_buffer_test_read_and_write);
+ AL_TEST_RUN(ring_buffer_test_peek);
+
+ AL_TEST_END_GROUP();
+}
diff --git a/tests/ring_buffer.h b/tests/ring_buffer.h
new file mode 100644
index 0000000..920c32d
--- /dev/null
+++ b/tests/ring_buffer.h
@@ -0,0 +1,8 @@
+#ifndef _AL_RING_BUFFER_TESTS_H
+#define _AL_RING_BUFFER_TESTS_H
+
+#include <al/types.h>
+
+bool ring_buffer_tests_run(void);
+
+#endif // _AL_RING_BUFFER_TESTS_H
diff --git a/tests/str.c b/tests/str.c
new file mode 100644
index 0000000..0dcd896
--- /dev/null
+++ b/tests/str.c
@@ -0,0 +1,191 @@
+#include <al/test.h>
+#include <al/str.h>
+
+static bool str_test_cmp(void)
+{
+ AL_TEST_START("str_cmp");
+
+ str *s0 = al_str_c("testtestasdf");
+ str *s1 = al_str_c("testtestasdf");
+ str *s2 = al_str_c("testtedfdfstasdf");
+ str *s3 = al_str_c("dtesttedfdfstasdf");
+
+ AL_TEST_TRUE(al_str_eq(s0, s1));
+ AL_TEST_FALSE(al_str_eq(s0, s2));
+ AL_TEST_FALSE(al_str_eq(s0, s3));
+ AL_TEST_FALSE(al_str_eq(s2, s3));
+
+ AL_TEST_EQ(al_str_cmp(s0, al_str_c("test"), 0, 4), 0, u32);
+ AL_TEST_EQ(al_str_cmp(s0, al_str_c("tt"), 3, 2), 0, u32);
+ AL_TEST_GT(al_str_cmp(s0, al_str_c("r"), 6, 1), 0, u32);
+ AL_TEST_EQ(al_str_cmp(s0, al_str_c("ee"), 15, 2), -1, u32);
+
+ str *s4 = al_str_c("page");
+ str *s5 = al_str_c("page.json");
+
+ AL_TEST_FALSE(al_str_eq(s5, s4));
+ AL_TEST_FALSE(al_str_eq(s4, s5));
+
+ AL_TEST_END();
+}
+
+static bool str_test_cat(void)
+{
+ AL_TEST_START("str_cat");
+
+ str *result = al_str_c("testtestasdf");
+
+ str s0;
+ al_str_from(&s0, "");
+
+ AL_TEST_EQ(s0.len, 0, u32);
+
+ al_str_cat(&s0, al_str_c("testtestasdf"));
+
+ AL_TEST_TRUE(al_str_eq(result, &s0));
+
+ al_str_free(&s0);
+
+ AL_TEST_END();
+}
+
+static bool str_test_insert(void)
+{
+ AL_TEST_START("str_insert");
+
+ str *insert_result = al_str_c("testtest[insert]asdf");
+ str *prepend_result = al_str_c("[prepend]testtestasdf");
+
+ str insert_str;
+ str prepend_str;
+
+ al_str_from(&insert_str, "testtestasdf");
+ al_str_from(&prepend_str, "testtestasdf");
+
+ al_str_insert(&insert_str, al_str_c("[insert]"), 8);
+ al_str_prepend(&prepend_str, al_str_c("[prepend]"));
+
+ AL_TEST_TRUE(al_str_eq(insert_result, &insert_str));
+ AL_TEST_TRUE(al_str_eq(prepend_result, &prepend_str));
+
+ al_str_free(&insert_str);
+ al_str_free(&prepend_str);
+
+ AL_TEST_END();
+}
+
+static bool str_test_find_rfind(void)
+{
+ AL_TEST_START("str_find_rfind");
+
+ str *s0 = al_str_c("testtes\\ta\\sdf");
+
+ AL_TEST_EQ(al_str_find(s0, '\\'), 7, s32);
+ AL_TEST_EQ(al_str_rfind(s0, '\\'), 10, s32);
+
+ AL_TEST_EQ(al_str_find_str(s0, al_str_c("tes\\")), 4, s32);
+
+ AL_TEST_END();
+}
+
+static bool str_test_substr(void)
+{
+ AL_TEST_START("str_substr");
+
+ str *result0 = al_str_c("[cutout0]");
+ str *result1 = al_str_c("[cutout1]");
+
+ str s;
+ al_str_from(&s, "dfkdljfd[cutout0]dfd[cutout1]fd");
+
+ s32 start = al_str_find(&s, '[');
+ s32 end = al_str_find(&s, ']') + 1;
+
+ str *cutout0 = al_str_substr(&s, start, end);
+ str *sub = al_str_substr(&s, end, s.len);
+
+ start = al_str_find(sub, '[');
+ end = al_str_find(sub, ']') + 1;
+
+ str *cutout1 = al_str_substr(sub, start, end);
+
+ AL_TEST_TRUE(al_str_eq(result0, cutout0));
+ AL_TEST_TRUE(al_str_eq(result1, cutout1));
+
+ al_str_free(&s);
+
+ AL_TEST_END();
+}
+
+static bool str_test_get_line(void)
+{
+ AL_TEST_START("str_get_line");
+
+ str *lines = al_str_c("test\nasdf\ntest2\na\n");
+ str *lines_array[] = { al_str_c("test"), al_str_c("asdf"), al_str_c("test2"), al_str_c("a") };
+
+ u32 count = 0;
+
+ for (str line = { 0 }; al_str_get_line(lines, &line); ) {
+ AL_TEST_TRUE(al_str_eq(&line, lines_array[count++]));
+ }
+
+ AL_TEST_END();
+}
+
+static bool str_test_to_long(void)
+{
+ AL_TEST_START("str_to_long");
+
+ str *s0 = al_str_c("10353");
+ str *s1 = al_str_c("-3563");
+ str *s2 = al_str_c("-2147483647"); // 1 away
+ // This fails on MSVC for some reason.
+ str *s2_1 = al_str_c("-2147483648"); // min
+ str *s2_2 = al_str_c("-2147483649"); // underflow
+ str *s3 = al_str_c("0xfff");
+ str *s4 = al_str_c("0b01010");
+ str *s5 = al_str_c("01010");
+ str *s6 = al_str_c("99999999999999999999");
+ str *s7 = al_str_c(" -99999999999999999999");
+ str *s8 = al_str_c("---99999999999999999999");
+ str *s9 = al_str_c("'p[afd'dfdfs[f");
+ str *s10 = al_str_c("\n\t 01010");
+ str *s11 = al_str_c("-9223372036854775809");
+ str *s12 = al_str_c("6519749124957310923");
+ str *s13 = al_str_c("-3519311901742109472");
+
+ AL_TEST_EQ(al_str_to_long(s0, 10), 10353L, s64);
+ AL_TEST_EQ(al_str_to_long(s1, 10), -3563L, s64);
+ AL_TEST_EQ(al_str_to_long(s2, 10), -2147483647L, s64);
+ AL_TEST_EQ(al_str_to_long(s2_1, 10), -2147483648L, s64);
+ AL_TEST_EQ(al_str_to_long(s2_2, 10), -2147483649L, s64);
+ AL_TEST_EQ(al_str_to_long(s3, 16), 0xfff, s64);
+ AL_TEST_EQ(al_str_to_long(s4, 2), 0b01010, s64);
+ AL_TEST_EQ(al_str_to_long(s5, 2), 0b01010, s64);
+ AL_TEST_EQ(al_str_to_long(s6, 10), INT64_MAX, s64);
+ AL_TEST_EQ(al_str_to_long(s7, 10), INT64_MIN, s64);
+ AL_TEST_EQ(al_str_to_long(s8, 10), INT64_MIN, s64);
+ AL_TEST_EQ(al_str_to_long(s9, 10), INT64_MAX, s64);
+ AL_TEST_EQ(al_str_to_long(s10, 2), 0b01010, s64);
+ AL_TEST_EQ(al_str_to_long(s11, 10), INT64_MIN, s64);
+ AL_TEST_EQ(al_str_to_long(s12, 10), 6519749124957310923L, s64);
+ AL_TEST_EQ(al_str_to_long(s13, 10), -3519311901742109472, s64);
+
+ AL_TEST_END();
+}
+
+bool str_tests_run(void)
+{
+ AL_TEST_START_GROUP("str");
+
+ AL_TEST_RUN(str_test_cmp);
+ AL_TEST_RUN(str_test_cat);
+ AL_TEST_RUN(str_test_insert);
+ AL_TEST_RUN(str_test_find_rfind);
+ AL_TEST_RUN(str_test_substr);
+ AL_TEST_RUN(str_test_get_line);
+ AL_TEST_RUN(str_test_to_long);
+
+ AL_TEST_END_GROUP();
+}
diff --git a/tests/str.h b/tests/str.h
new file mode 100644
index 0000000..64eb0fa
--- /dev/null
+++ b/tests/str.h
@@ -0,0 +1,8 @@
+#ifndef _AL_STR_TESTS_H
+#define _AL_STR_TESTS_H
+
+#include <al/types.h>
+
+bool str_tests_run(void);
+
+#endif // _AL_STR_TESTS_H