diff options
| author | tanaka takashi <isazaka@gmail.com> | 2026-06-29 02:36:40 +0900 |
|---|---|---|
| committer | tanaka takashi <isazaka@gmail.com> | 2026-06-29 02:36:40 +0900 |
| commit | 4c6a831aa2a57e2bcc20aa3fc2f1b7172f5be285 (patch) | |
| tree | 074021381abf57cad434430f25027115b681b8a9 /tests/storage_test.c | |
| parent | 8d38b06f11c713e547d70468340242f23322152c (diff) | |
feat: 会話メモリのプロトタイプを実装
- 6種類のMCPツールと入力検証を追加
- バイナリログ、スナップショット、復旧、圧縮処理を実装
- Unicode n-gram検索とドメインモデルを追加
- 単体テストと統合テストを追加
- アーキテクチャと実装状況を文書化
- Cコードの記述スタイルを統一
Diffstat (limited to 'tests/storage_test.c')
| -rw-r--r-- | tests/storage_test.c | 97 |
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; +} |
