/src/test-gsktable.c

https://github.com/davebenson/gsk · C · 263 lines · 239 code · 22 blank · 2 comment · 31 complexity · 3fc80a04a1f5cb08907f04358bc896f5 MD5 · raw file

  1. /* TODO: test reader api */
  2. #include <stdio.h>
  3. #include <string.h>
  4. #include <unistd.h>
  5. #include <errno.h>
  6. #include <sys/stat.h>
  7. #include <sys/types.h>
  8. #include "gskinit.h"
  9. #include "gsktable.h"
  10. #include "gsktable-file.h"
  11. static void gen_kv_0 (guint index,
  12. GByteArray *key,
  13. GByteArray *value)
  14. {
  15. guint32 index_be32 = GUINT32_TO_BE (index);
  16. guint32 suffix_len = index % 33;
  17. char suffix_char = G_CSET_a_2_z[index % 26];
  18. char value_buf[64];
  19. g_byte_array_set_size (key, 4 + suffix_len);
  20. memcpy (key->data, &index_be32, 4);
  21. memset (key->data + 4, suffix_char, suffix_len);
  22. g_snprintf (value_buf, sizeof (value_buf), "%u-%x", index,index);
  23. g_byte_array_set_size (value, strlen (value_buf));
  24. memcpy (value->data, value_buf, value->len);
  25. }
  26. typedef void (*GenKeyValue) (guint index,
  27. GByteArray *key_out,
  28. GByteArray *value_out);
  29. static void
  30. inject_entries (GskTableFile *file,
  31. GenKeyValue gen_kv,
  32. guint start,
  33. guint end)
  34. {
  35. guint i;
  36. GByteArray *key = g_byte_array_new ();
  37. GByteArray *value = g_byte_array_new ();
  38. for (i = start; i < end; i++)
  39. {
  40. GError *error = NULL;
  41. gen_kv (i, key, value);
  42. switch (gsk_table_file_feed_entry (file, key->len, key->data, value->len, value->data, &error))
  43. {
  44. case GSK_TABLE_FEED_ENTRY_WANT_MORE:
  45. case GSK_TABLE_FEED_ENTRY_SUCCESS:
  46. break;
  47. default:
  48. g_error ("gsk_table_file_feed_entry: %s", error->message);
  49. }
  50. }
  51. g_byte_array_free (key, TRUE);
  52. g_byte_array_free (value, TRUE);
  53. }
  54. static void
  55. inject_entries_til_success (GskTableFile *file,
  56. GenKeyValue gen_kv,
  57. guint start,
  58. guint *end_out)
  59. {
  60. guint i = start;
  61. GByteArray *key = g_byte_array_new ();
  62. GByteArray *value = g_byte_array_new ();
  63. while (TRUE)
  64. {
  65. GError *error = NULL;
  66. gen_kv (i++, key, value);
  67. switch (gsk_table_file_feed_entry (file, key->len, key->data, value->len, value->data, &error))
  68. {
  69. case GSK_TABLE_FEED_ENTRY_SUCCESS:
  70. *end_out = i;
  71. g_byte_array_free (key, TRUE);
  72. g_byte_array_free (value, TRUE);
  73. return;
  74. case GSK_TABLE_FEED_ENTRY_WANT_MORE:
  75. break;
  76. default:
  77. g_error ("gsk_table_file_feed_entry: %s", error->message);
  78. }
  79. }
  80. }
  81. static gint
  82. compare_by_memcmp (guint test_key_len,
  83. const guint8 *test_key,
  84. gpointer compare_data)
  85. {
  86. GByteArray *array = compare_data;
  87. if (test_key_len > array->len)
  88. {
  89. int rv = memcmp (test_key, array->data, array->len);
  90. return rv ? rv : 1;
  91. }
  92. else if (test_key_len < array->len)
  93. {
  94. int rv = memcmp (test_key, array->data, test_key_len);
  95. return rv ? rv : -1;
  96. }
  97. else
  98. return memcmp (test_key, array->data, test_key_len);
  99. }
  100. static void
  101. query_entries (GskTableFile *file,
  102. GenKeyValue gen_kv,
  103. guint start,
  104. guint end,
  105. guint step)
  106. {
  107. GByteArray *key = g_byte_array_new ();
  108. GByteArray *value = g_byte_array_new ();
  109. guint i;
  110. GskTableFileQuery query = GSK_TABLE_FILE_QUERY_INIT;
  111. GError *error = NULL;
  112. query.compare = compare_by_memcmp;
  113. query.compare_data = key;
  114. for (i = start; i < end; i += step)
  115. {
  116. gen_kv (i, key, value);
  117. if (!gsk_table_file_query (file, &query, &error))
  118. g_error ("gsk_table_file_query: %s", error->message);
  119. }
  120. g_byte_array_free (key, TRUE);
  121. g_byte_array_free (value, TRUE);
  122. gsk_table_file_query_clear (&query);
  123. }
  124. static void
  125. finish_file (GskTableFile *file)
  126. {
  127. gboolean ready;
  128. GError *error = NULL;
  129. if (!gsk_table_file_done_feeding (file, &ready, &error))
  130. g_error ("gsk_table_file_done_feeding: %s", error->message);
  131. while (!ready)
  132. if (!gsk_table_file_build_file (file, &ready, &error))
  133. g_error ("gsk_table_file_build_file: %s", error->message);
  134. }
  135. static void
  136. run_test (GskTableFileFactory *factory,
  137. const char *dir,
  138. guint64 id)
  139. {
  140. GskTableFile *file;
  141. GskTableFileHints hints = GSK_TABLE_FILE_HINTS_DEFAULTS;
  142. GError *error = NULL;
  143. guint end;
  144. /* --- small test --- */
  145. file = gsk_table_file_factory_create_file (factory, dir, id, &hints, &error);
  146. if (file == NULL)
  147. g_error ("gsk_table_file_factory_create_file: %s", error->message);
  148. inject_entries (file, gen_kv_0, 0, 20);
  149. inject_entries_til_success (file, gen_kv_0, 20, &end);
  150. query_entries (file, gen_kv_0, 0, end, 1);
  151. {
  152. guint state_len;
  153. guint8 *state_data;
  154. if (!gsk_table_file_get_build_state (file, &state_len, &state_data, &error))
  155. g_error ("gsk_table_file_get_build_state: %s", error->message);
  156. if (!gsk_table_file_destroy (file, dir, FALSE, &error))
  157. g_error ("gsk_table_file_destroy: %s", error->message);
  158. file = gsk_table_file_factory_open_building_file (factory, dir, id, state_len, state_data, &error);
  159. if (file == NULL)
  160. g_error ("gsk_table_file_factory_open_building_file: %s", error->message);
  161. g_free (state_data);
  162. }
  163. query_entries (file, gen_kv_0, 0, end, 1);
  164. inject_entries (file, gen_kv_0, end, end + 20);
  165. end += 20;
  166. inject_entries_til_success (file, gen_kv_0, end, &end);
  167. query_entries (file, gen_kv_0, 0, end, 1);
  168. inject_entries (file, gen_kv_0, end, end + 1);
  169. end += 1;
  170. finish_file (file);
  171. query_entries (file, gen_kv_0, 0, end, 1);
  172. if (!gsk_table_file_destroy (file, dir, FALSE, &error))
  173. g_error ("gsk_table_file_destroy: %s", error->message);
  174. file = gsk_table_file_factory_open_file (factory, dir, id, &error);
  175. if (file == NULL)
  176. g_error ("gsk_table_file_factory_open_building_file: %s", error->message);
  177. query_entries (file, gen_kv_0, 0, end, 1);
  178. if (!gsk_table_file_destroy (file, dir, TRUE, &error))
  179. g_error ("gsk_table_file_destroy: %s", error->message);
  180. }
  181. static void
  182. run_test_big (GskTableFileFactory *factory,
  183. const char *dir,
  184. guint64 id)
  185. {
  186. GskTableFile *file;
  187. GskTableFileHints hints = GSK_TABLE_FILE_HINTS_DEFAULTS;
  188. GError *error = NULL;
  189. guint end;
  190. file = gsk_table_file_factory_create_file (factory, dir, id, &hints, &error);
  191. if (file == NULL)
  192. g_error ("gsk_table_file_factory_create_file: %s", error->message);
  193. inject_entries (file, gen_kv_0, 0, 1000*1000);
  194. inject_entries_til_success (file, gen_kv_0, 1000*1000, &end);
  195. query_entries (file, gen_kv_0, 0, end, 101);
  196. inject_entries (file, gen_kv_0, end, 4*1000*1000);
  197. inject_entries_til_success (file, gen_kv_0, 4*1000*1000, &end);
  198. query_entries (file, gen_kv_0, 0, end, 503);
  199. {
  200. guint state_len;
  201. guint8 *state_data;
  202. if (!gsk_table_file_get_build_state (file, &state_len, &state_data, &error))
  203. g_error ("gsk_table_file_get_build_state: %s", error->message);
  204. if (!gsk_table_file_destroy (file, dir, FALSE, &error))
  205. g_error ("gsk_table_file_destroy: %s", error->message);
  206. file = gsk_table_file_factory_open_building_file (factory, dir, id, state_len, state_data, &error);
  207. if (file == NULL)
  208. g_error ("gsk_table_file_factory_open_building_file: %s", error->message);
  209. g_free (state_data);
  210. }
  211. query_entries (file, gen_kv_0, 0, end, 503);
  212. inject_entries (file, gen_kv_0, end, end+51);
  213. finish_file (file);
  214. query_entries (file, gen_kv_0, 0, end, end+51);
  215. end += 51;
  216. query_entries (file, gen_kv_0, 0, end, 503);
  217. if (!gsk_table_file_destroy (file, dir, TRUE, &error))
  218. g_error ("gsk_table_file_destroy: %s", error->message);
  219. }
  220. int
  221. main(int argc,
  222. char **argv)
  223. {
  224. GskTableFileFactory *factory;
  225. char *dir;
  226. gsk_init_without_threads (&argc, &argv);
  227. dir = g_strdup_printf ("test-table-dir-%08x", (guint32) g_random_int ());
  228. if (mkdir (dir, 0755) < 0)
  229. g_error ("error making test dir %s: %s", dir, g_strerror (errno));
  230. factory = gsk_table_file_factory_new_flat ();
  231. g_printerr ("running small test... ");
  232. run_test (factory, dir, 1000);
  233. g_printerr ("done.\n");
  234. g_printerr ("running big test... ");
  235. run_test_big (factory, dir, 1001);
  236. g_printerr ("done.\n");
  237. if (rmdir (dir) < 0)
  238. g_error ("rmdir(%s) failed: %s", dir, g_strerror (errno));
  239. g_free (dir);
  240. return 0;
  241. }