summaryrefslogtreecommitdiff
path: root/src/libdisfluid/disfluid-tests.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/libdisfluid/disfluid-tests.h')
-rw-r--r--src/libdisfluid/disfluid-tests.h134
1 files changed, 134 insertions, 0 deletions
diff --git a/src/libdisfluid/disfluid-tests.h b/src/libdisfluid/disfluid-tests.h
index e77b497..50b5a9f 100644
--- a/src/libdisfluid/disfluid-tests.h
+++ b/src/libdisfluid/disfluid-tests.h
@@ -14,6 +14,7 @@ static inline char *run_tests (size_t *n_tests, size_t *n_errors);
# include "disfluid-cache-entry-key.h"
# include "disfluid-db.h"
# include "string-desc.h"
+# include "disfluid-append-only-file.h"
# define BYTES * 1
@@ -527,6 +528,135 @@ START_TEST (test_db_trie_leaf)
END_TEST
/* *INDENT-ON* */
+/* *INDENT-OFF* */
+START_TEST (test_aof_recover)
+/* *INDENT-ON* */
+
+{
+ /* Here we have a partially updated file. The top was offset 5, but
+ is in the process of being updated to 13. In the mean time, the
+ first offset is garbage. */
+ static const uint8_t partial_update[] = {
+ /* Magic: */
+ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
+ /* Status: */
+ 1, 42, 42, 42, 42, 42, 42, 42,
+ /* Top before: */
+ 42, 42, 42, 42, 42, 42, 42, 42,
+ /* Top after: */
+ 0, 0, 0, 0, 0, 0, 0, 13,
+ /* Data: */
+ 72, 101, 108, 108, 111, 44, 32, 119, 111, 114, 108, 100, 33
+ };
+ char filename[] = "/tmp/test-partial-update-XXXXXX";
+ int file = mkstemp (filename);
+ ck_assert_int_ge (file, 0);
+ size_t n_to_write = sizeof (partial_update);
+ const uint8_t *to_write = partial_update;
+ while (n_to_write > 0)
+ {
+ ssize_t n_written = write (file, to_write, n_to_write);
+ ck_assert_int_gt (n_written, 0);
+ ck_assert_int_le (n_written, n_to_write);
+ n_to_write -= n_written;
+ to_write += n_written;
+ }
+ size_t top = 42;
+ int error = ao_file_read_top (file, &top);
+ ck_assert_int_eq (error, 0);
+ ck_assert_int_eq (top, 13);
+ if (lseek (file, 0, SEEK_SET) == -1)
+ {
+ ck_assert (false);
+ }
+ static const uint8_t after_update_expected[] = {
+ /* Magic: */
+ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
+ /* Status: */
+ 0, 42, 42, 42, 42, 42, 42, 42,
+ /* Top before: */
+ 0, 0, 0, 0, 0, 0, 0, 13,
+ /* Top after: */
+ 0, 0, 0, 0, 0, 0, 0, 13,
+ /* Data: */
+ 72, 101, 108, 108, 111, 44, 32, 119, 111, 114, 108, 100, 33
+ };
+ uint8_t actual_data[sizeof (after_update_expected)] = { 0 };
+ size_t n_to_read = sizeof (after_update_expected);
+ uint8_t *read_ptr = actual_data;
+ while (n_to_read > 0)
+ {
+ ssize_t n_read = read (file, read_ptr, n_to_read);
+ ck_assert_int_gt (n_read, 0);
+ ck_assert_int_le (n_read, n_to_read);
+ n_to_read -= n_read;
+ read_ptr += n_read;
+ }
+ for (size_t i = 0; i < sizeof (after_update_expected); i++)
+ {
+ ck_assert_int_eq (actual_data[i], after_update_expected[i]);
+ }
+ remove (filename);
+ close (file);
+}
+/* *INDENT-OFF* */
+END_TEST
+/* *INDENT-ON* */
+
+/* *INDENT-OFF* */
+START_TEST (test_aof_can_read_locked_file)
+/* *INDENT-ON* */
+
+{
+ /* Here we construct a file with "Hello", and lock it. We should
+ still be able to call ao_file_read_top. */
+ char filename[] = "/tmp/test-lock-read-XXXXXX";
+ int file = mkstemp (filename);
+ ck_assert_int_ge (file, 0);
+ static const char *magic_data = "disfluid test ao";
+ const string_desc_t file_magic = {
+ ._data = (char *) magic_data,
+ ._nbytes = strlen (magic_data)
+ };
+ int error = ao_file_prepare (file, file_magic);
+ ck_assert_int_eq (error, 0);
+ size_t top;
+ error = ao_file_lock_for_writing (file, &top);
+ ck_assert_int_eq (error, 0);
+ ck_assert_int_eq (top, 0);
+ static const char *hello_data = "Hello";
+ const string_desc_t hello = {
+ ._data = (char *) hello_data,
+ ._nbytes = strlen (hello_data)
+ };
+ error = ao_file_push_data (file, hello, &top);
+ ck_assert_int_eq (error, 0);
+ ck_assert_int_eq (top, 5);
+ error = ao_file_commit_transaction (file);
+ ck_assert_int_eq (error, 0);
+ static const char *world_data = ", world!";
+ const string_desc_t world = {
+ ._data = (char *) world_data,
+ ._nbytes = strlen (world_data)
+ };
+ error = ao_file_lock_for_writing (file, &top);
+ ck_assert_int_eq (error, 0);
+ ck_assert_int_eq (top, 5);
+ error = ao_file_push_data (file, world, &top);
+ ck_assert_int_eq (error, 0);
+ ck_assert_int_eq (top, 13);
+ /* file is still locked. */
+ error = ao_file_read_top (file, &top);
+ ck_assert_int_eq (error, 0);
+ ck_assert_int_eq (top, 5);
+ ao_file_abort_transaction (file);
+ remove (filename);
+ close (file);
+}
+/* *INDENT-OFF* */
+END_TEST
+/* *INDENT-ON* */
+
static inline char *
tests_read_whole_file (int file)
{
@@ -581,6 +711,10 @@ run_tests (size_t *n_tests, size_t *n_errors)
tcase_add_test (db, test_db_trie_inner);
tcase_add_test (db, test_db_trie_leaf);
suite_add_tcase (suite, db);
+ TCase *aof = tcase_create (_("append-only file"));
+ tcase_add_test (aof, test_aof_recover);
+ tcase_add_test (aof, test_aof_can_read_locked_file);
+ suite_add_tcase (suite, aof);
SRunner *runner = srunner_create (suite);
char log_file_name[] = "/tmp/disfluid-unit-tests-XXXXXX";
int log_file = mkstemp (log_file_name);