diff options
Diffstat (limited to 'src/libdisfluid/disfluid-tests.h')
-rw-r--r-- | src/libdisfluid/disfluid-tests.h | 134 |
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); |