aboutsummaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
authorPřemysl Janouch <p.janouch@gmail.com>2015-02-28 19:53:23 +0100
committerPřemysl Janouch <p.janouch@gmail.com>2015-02-28 19:53:23 +0100
commit087645848baec5e59e4296817850bd5dd240cbb2 (patch)
treef5b3d507c4a65a95a26a52a17136fdf94811b785 /tests
downloadliberty-087645848baec5e59e4296817850bd5dd240cbb2.tar.gz
liberty-087645848baec5e59e4296817850bd5dd240cbb2.tar.xz
liberty-087645848baec5e59e4296817850bd5dd240cbb2.zip
Initial commit
Diffstat (limited to 'tests')
-rw-r--r--tests/liberty.c345
1 files changed, 345 insertions, 0 deletions
diff --git a/tests/liberty.c b/tests/liberty.c
new file mode 100644
index 0000000..8956ed0
--- /dev/null
+++ b/tests/liberty.c
@@ -0,0 +1,345 @@
+/*
+ * tests/liberty.c
+ *
+ * Copyright (c) 2015, Přemysl Janouch <p.janouch@gmail.com>
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ */
+
+#define PROGRAM_NAME "test"
+#define PROGRAM_VERSION "0"
+
+#include "../liberty.c"
+
+// --- Memory ------------------------------------------------------------------
+
+#define KILO 1024
+#define MEGA 1048576
+
+static void
+test_memory (void)
+{
+ void *m = xmalloc (MEGA);
+ memset (m, 0, MEGA);
+
+ void *n = xcalloc (KILO, KILO);
+ soft_assert (!memcmp (n, m, MEGA));
+
+ m = xrealloc (m, 1024);
+ n = xreallocarray (n, KILO, 1);
+ soft_assert (!memcmp (n, m, KILO));
+
+ free (m);
+ free (n);
+
+ char *s = xstrdup ("test");
+ char *t = xstrndup ("testing", 4);
+ soft_assert (!strcmp (s, t));
+
+ free (s);
+ free (t);
+}
+
+// --- Linked lists ------------------------------------------------------------
+
+struct my_link
+{
+ LIST_HEADER (struct my_link)
+ int n;
+};
+
+static struct my_link *
+make_link (int value)
+{
+ struct my_link *link = xcalloc (1, sizeof *link);
+ link->n = value;
+ return link;
+}
+
+static void
+check_linked_list (struct my_link *list, struct my_link **a, int n)
+{
+ // The linked list must contain items from the array, in that order
+ struct my_link *iter = list;
+ for (int i = 0; i < n; i++)
+ {
+ if (!a[i])
+ continue;
+
+ hard_assert (iter != NULL);
+ soft_assert (iter->n == i);
+ iter = iter->next;
+ }
+
+ // And nothing more
+ soft_assert (iter == NULL);
+}
+
+static void
+test_list (void)
+{
+ struct my_link *list = NULL;
+ struct my_link *a[10];
+
+ // Prepare a linked list
+ for (int i = N_ELEMENTS (a); i--; )
+ {
+ a[i] = make_link (i);
+ LIST_PREPEND (list, a[i]);
+ }
+
+ // Remove a few entries
+ LIST_UNLINK (list, a[0]); a[0] = NULL;
+ LIST_UNLINK (list, a[3]); a[3] = NULL;
+ LIST_UNLINK (list, a[4]); a[4] = NULL;
+ LIST_UNLINK (list, a[6]); a[6] = NULL;
+
+ // Prepend one more item
+ a[0] = make_link (0);
+ LIST_PREPEND (list, a[0]);
+
+ // Check the contents
+ check_linked_list (list, a, N_ELEMENTS (a));
+
+ // Destroy the linked list
+ LIST_FOR_EACH (struct my_link, iter, list)
+ free (iter);
+}
+
+static void
+test_list_with_tail (void)
+{
+ struct my_link *list = NULL;
+ struct my_link *tail = NULL;
+ struct my_link *a[10];
+
+ // Prepare a linked list
+ for (int i = 0; i < (int) N_ELEMENTS (a); i++)
+ {
+ a[i] = make_link (i);
+ LIST_APPEND_WITH_TAIL (list, tail, a[i]);
+ }
+
+ // Remove a few entries
+ LIST_UNLINK_WITH_TAIL (list, tail, a[0]); a[0] = NULL;
+ LIST_UNLINK_WITH_TAIL (list, tail, a[3]); a[3] = NULL;
+ LIST_UNLINK_WITH_TAIL (list, tail, a[4]); a[4] = NULL;
+ LIST_UNLINK_WITH_TAIL (list, tail, a[6]); a[6] = NULL;
+ LIST_UNLINK_WITH_TAIL (list, tail, a[9]); a[9] = NULL;
+
+ // Append one more item
+ a[9] = make_link (9);
+ LIST_APPEND_WITH_TAIL (list, tail, a[9]);
+
+ // Check the contents
+ check_linked_list (list, a, N_ELEMENTS (a));
+
+ // Destroy the linked list
+ LIST_FOR_EACH (struct my_link, iter, list)
+ free (iter);
+}
+
+// --- Strings -----------------------------------------------------------------
+
+static void
+test_str_vector (void)
+{
+ struct str_vector v;
+ str_vector_init (&v);
+
+ str_vector_add_owned (&v, xstrdup ("xkcd"));
+ str_vector_reset (&v);
+
+ const char *a[] =
+ { "123", "456", "a", "bc", "def", "ghij", "klmno", "pqrstu" };
+
+ // Add the first two items via another vector
+ struct str_vector w;
+ str_vector_init (&w);
+ str_vector_add_args (&w, a[0], a[1], NULL);
+ str_vector_add_vector (&v, w.vector);
+ str_vector_free (&w);
+
+ // Add an item and delete it right after
+ str_vector_add (&v, "test");
+ str_vector_remove (&v, v.len - 1);
+
+ // Add the rest of the list properly
+ for (int i = 2; i < (int) N_ELEMENTS (a); i++)
+ str_vector_add (&v, a[i]);
+
+ // Check the contents
+ soft_assert (v.len == N_ELEMENTS (a));
+ for (int i = 0; i < (int) N_ELEMENTS (a); i++)
+ soft_assert (!strcmp (v.vector[i], a[i]));
+ soft_assert (v.vector[v.len] == NULL);
+
+ str_vector_free (&v);
+}
+
+static void
+test_str (void)
+{
+ uint8_t x[] = { 0x12, 0x34, 0x56, 0x78, 0x11, 0x22, 0x33, 0x44 };
+
+ struct str s;
+ str_init (&s);
+ str_ensure_space (&s, MEGA);
+ str_append_data (&s, x, sizeof x);
+ str_remove_slice (&s, 4, 4);
+ soft_assert (s.len == 4);
+
+ struct str t;
+ str_init (&t);
+ str_append_str (&t, &s);
+ str_append (&t, "abc");
+ str_append_c (&t, 'd');
+ str_append_printf (&t, "efg");
+
+ char *y = str_steal (&t);
+ soft_assert (!strcmp (y, "\x12\x34\x56\x78" "abcdefg"));
+ free (y);
+
+ str_reset (&s);
+ str_free (&s);
+}
+
+// --- Errors ------------------------------------------------------------------
+
+static void
+test_error (void)
+{
+ const char *m = "something fucked up";
+
+ struct error *e = NULL;
+ error_set (&e, "%s", m);
+
+ struct error *f = NULL;
+ error_propagate (&f, e);
+
+ soft_assert (f != NULL);
+ soft_assert (!strcmp (f->message, m));
+ error_free (f);
+}
+
+// --- Hash map ----------------------------------------------------------------
+
+static int
+tolower_ascii (int c)
+{
+ return c >= 'A' && c <= 'Z' ? c + ('a' - 'A') : c;
+}
+
+static size_t
+tolower_strxfrm (char *dest, const char *src, size_t n)
+{
+ size_t len = strlen (src);
+ while (n-- && (*dest++ = tolower_ascii (*src++)))
+ ;
+ return len;
+}
+
+static void
+free_counter (void *data)
+{
+ int *counter = data;
+ if (!--*counter)
+ free (data);
+}
+
+static int *
+make_counter (void)
+{
+ int *counter = xmalloc (sizeof *counter);
+ *counter = 1;
+ return counter;
+}
+
+static int *
+ref_counter (int *counter)
+{
+ (*counter)++;
+ return counter;
+}
+
+static void
+test_str_map (void)
+{
+ // Put two reference counted objects in the map under case-insensitive keys
+ struct str_map m;
+ str_map_init (&m);
+ m.key_xfrm = tolower_strxfrm;
+ m.free = free_counter;
+
+ int *a = make_counter ();
+ int *b = make_counter ();
+
+ str_map_set (&m, "abc", ref_counter (a));
+ soft_assert (str_map_find (&m, "ABC") == a);
+ soft_assert (!str_map_find (&m, "DEFghi"));
+
+ str_map_set (&m, "defghi", ref_counter (b));
+ soft_assert (str_map_find (&m, "ABC") == a);
+ soft_assert (str_map_find (&m, "DEFghi") == b);
+
+ // Check that we can iterate over both of them
+ struct str_map_iter iter;
+ str_map_iter_init (&iter, &m);
+
+ bool met_a = false;
+ bool met_b = false;
+ void *iter_data;
+ while ((iter_data = str_map_iter_next (&iter)))
+ {
+ if (iter_data == a) { soft_assert (!met_a); met_a = true; }
+ if (iter_data == b) { soft_assert (!met_b); met_b = true; }
+ soft_assert (met_a || met_b);
+ }
+ soft_assert (met_a && met_b);
+
+ // Remove one of the keys
+ str_map_set (&m, "abc", NULL);
+ soft_assert (!str_map_find (&m, "ABC"));
+ soft_assert (str_map_find (&m, "DEFghi") == b);
+
+ str_map_free (&m);
+
+ // Check that the objects have been destroyed exactly once
+ soft_assert (*a == 1);
+ soft_assert (*b == 1);
+ free_counter (a);
+ free_counter (b);
+}
+
+// --- Main --------------------------------------------------------------------
+
+int
+main (int argc, char *argv[])
+{
+ struct test test;
+ test_init (&test, argc, argv);
+
+ test_add_simple (&test, "/memory", NULL, test_memory);
+ test_add_simple (&test, "/list", NULL, test_list);
+ test_add_simple (&test, "/list-with-tail", NULL, test_list_with_tail);
+ test_add_simple (&test, "/str-vector", NULL, test_str_vector);
+ test_add_simple (&test, "/str", NULL, test_str);
+ test_add_simple (&test, "/error", NULL, test_error);
+ test_add_simple (&test, "/str-map", NULL, test_str_map);
+
+ // TODO: write tests for the rest of the library
+
+ return test_run (&test);
+}