summaryrefslogtreecommitdiff
path: root/tests/storage_test.c
diff options
context:
space:
mode:
Diffstat (limited to 'tests/storage_test.c')
-rw-r--r--tests/storage_test.c97
1 files changed, 97 insertions, 0 deletions
diff --git a/tests/storage_test.c b/tests/storage_test.c
new file mode 100644
index 0000000..bac0f0b
--- /dev/null
+++ b/tests/storage_test.c
@@ -0,0 +1,97 @@
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+
+#include "storage/store.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+static int failures;
+#define CHECK(value) \
+ do \
+ { \
+ if (!(value)) \
+ { \
+ fprintf(stderr, "CHECK failed at line %d: %s\n", __LINE__, #value); \
+ failures++; \
+ } \
+ } \
+ while (0)
+
+int
+wmain(void)
+{
+ wchar_t temporary[MAX_PATH], directory[MAX_PATH], log_path[MAX_PATH];
+ tiny_store_t *store = NULL, *second = NULL;
+ tiny_message_t input, first, second_message;
+ tiny_store_status_t status;
+ HANDLE log;
+ HANDLE blocker;
+ tiny_rebuild_report_t report;
+ LARGE_INTEGER position;
+ unsigned char byte;
+ DWORD count;
+
+ CHECK(GetTempPathW(MAX_PATH, temporary) > 0);
+ CHECK(GetTempFileNameW(temporary, L"tcm", 0, directory) > 0);
+ DeleteFileW(directory);
+ CHECK(CreateDirectoryW(directory, NULL) != 0);
+ status = tiny_store_open(&store, directory);
+ CHECK(status == TINY_STORE_OK);
+ CHECK(tiny_store_open(&second, directory) == TINY_STORE_BUSY);
+
+ tiny_message_init(&input);
+ tiny_message_init(&first);
+ tiny_message_init(&second_message);
+ input.session_id = _strdup("unit");
+ input.content = _strdup("first");
+ input.role = TINY_ROLE_USER;
+ CHECK(tiny_store_write(store, &input, &first) == TINY_STORE_OK);
+ free(input.content);
+ input.content = _strdup("second");
+ CHECK(tiny_store_write(store, &input, &second_message) == TINY_STORE_OK);
+ CHECK(strcmp(first.message_id, second_message.message_id) < 0);
+ tiny_message_free(&input);
+ tiny_message_free(&first);
+ tiny_message_free(&second_message);
+ tiny_store_close(store);
+ store = NULL;
+
+ CHECK(tiny_store_open(&store, directory) == TINY_STORE_OK);
+ CHECK(tiny_store_entry_count(store) == 2);
+ swprintf_s(log_path, MAX_PATH, L"%s\\active.tmp", directory);
+ blocker = CreateFileW(
+ log_path, GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
+ CHECK(blocker != INVALID_HANDLE_VALUE);
+ CHECK(tiny_store_rebuild(store, &report) == TINY_STORE_IO_ERROR);
+ CHECK(tiny_store_entry_count(store) == 2);
+ CloseHandle(blocker);
+ DeleteFileW(log_path);
+ tiny_store_close(store);
+ store = NULL;
+
+ swprintf_s(log_path, MAX_PATH, L"%s\\active.log", directory);
+ log = CreateFileW(
+ log_path, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
+ CHECK(log != INVALID_HANDLE_VALUE);
+ position.QuadPart = -1;
+ CHECK(SetFilePointerEx(log, position, NULL, FILE_END) != 0);
+ CHECK(ReadFile(log, &byte, 1, &count, NULL) != 0 && count == 1);
+ byte ^= 0x5a;
+ position.QuadPart = -1;
+ CHECK(SetFilePointerEx(log, position, NULL, FILE_CURRENT) != 0);
+ CHECK(WriteFile(log, &byte, 1, &count, NULL) != 0 && count == 1);
+ CloseHandle(log);
+ CHECK(tiny_store_open(&store, directory) == TINY_STORE_CORRUPT);
+
+ DeleteFileW(log_path);
+ swprintf_s(log_path, MAX_PATH, L"%s\\active.tmp", directory);
+ DeleteFileW(log_path);
+ swprintf_s(log_path, MAX_PATH, L"%s\\store.lock", directory);
+ DeleteFileW(log_path);
+ swprintf_s(log_path, MAX_PATH, L"%s\\snapshot.bin", directory);
+ DeleteFileW(log_path);
+ RemoveDirectoryW(directory);
+ return failures == 0 ? 0 : 1;
+}