summaryrefslogtreecommitdiff
path: root/tests/storage_test.c
blob: bac0f0b70f5abe45eb3311966487eb7bedb4c1f9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
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;
}