test_graph.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420
  1. #include "test.h"
  2. #include "graph.h"
  3. #include "assets/triples.h"
  4. #define N_LUT 13
  5. static int
  6. _graph_new (LSUP_StoreType type)
  7. {
  8. const LSUP_StoreInt *sif = LSUP_store_int (type);
  9. if (sif->setup_fn) sif->setup_fn (NULL, true);
  10. LSUP_Graph *gr;
  11. LSUP_Store *store;
  12. if (type == LSUP_STORE_HTABLE) {
  13. gr = LSUP_graph_new (NULL, NULL, NULL);
  14. } else {
  15. store = LSUP_store_new (type, NULL, 0);
  16. gr = LSUP_graph_new (store, NULL, NULL);
  17. }
  18. ASSERT (gr != NULL, "Error creating graph!");
  19. EXPECT_PASS (LSUP_graph_set_uri (gr, LSUP_iriref_new ("urn:gr:1", NULL)));
  20. EXPECT_STR_EQ (LSUP_graph_uri (gr)->data, "urn:gr:1");
  21. // Check that setup function is idempotent with clear == false.
  22. if (sif->setup_fn) EXPECT_INT_EQ (
  23. sif->setup_fn (NULL, false), LSUP_NOACTION);
  24. ASSERT (
  25. strcmp (LSUP_graph_uri (gr)->data, "urn:gr:1") == 0,
  26. "Graph URI mismatch!");
  27. EXPECT_INT_EQ (LSUP_graph_size (gr), 0);
  28. LSUP_graph_free (gr);
  29. if (type != LSUP_STORE_HTABLE) LSUP_store_free (store);
  30. return 0;
  31. }
  32. static int
  33. _graph_add (LSUP_StoreType type)
  34. {
  35. const LSUP_StoreInt *sif = LSUP_store_int (type);
  36. if (sif->setup_fn) sif->setup_fn (NULL, true);
  37. LSUP_Triple *trp = create_triples();
  38. LSUP_Graph *gr;
  39. LSUP_Store *store;
  40. if (type == LSUP_STORE_HTABLE) {
  41. gr = LSUP_graph_new (NULL, NULL, NULL);
  42. } else {
  43. store = LSUP_store_new (type, NULL, 0);
  44. gr = LSUP_graph_new (store, NULL, NULL);
  45. }
  46. ASSERT (gr != NULL, "Error creating graph!");
  47. size_t ct;
  48. LSUP_graph_add (gr, trp, &ct);
  49. EXPECT_INT_EQ (ct, 8);
  50. EXPECT_INT_EQ (LSUP_graph_size (gr), 8);
  51. for (int i = 0; i < sizeof (trp); i++) {
  52. log_info ("checking triple #%d.", i);
  53. ASSERT (LSUP_graph_contains (gr, trp + i), "Triple not in graph!");
  54. }
  55. LSUP_Triple *missing_trp = LSUP_triple_new (trp[1].s, trp[6].p, trp[4].o);
  56. ASSERT (! LSUP_graph_contains (gr, missing_trp), "Triple in graph!");
  57. free (missing_trp);
  58. free_triples (trp); // gr copied data.
  59. LSUP_graph_free (gr);
  60. if (type != LSUP_STORE_HTABLE) LSUP_store_free (store);
  61. return 0;
  62. }
  63. static int
  64. _graph_lookup (LSUP_StoreType type)
  65. {
  66. const LSUP_StoreInt *sif = LSUP_store_int (type);
  67. LSUP_Triple *trp = create_triples();
  68. // Lookup triples.
  69. LSUP_Term *lu_trp[N_LUT][3] = {
  70. {NULL, NULL, NULL}, // 8 matches
  71. {trp[0].s, NULL, NULL}, // 5 matches
  72. {NULL, trp[2].p, NULL}, // 3 matches
  73. {NULL, NULL, trp[5].o}, // 2 matches
  74. {trp[0].s, trp[0].p, NULL}, // 1 match
  75. {NULL, trp[0].p, trp[0].o}, // 1 match
  76. {trp[0].s, trp[2].p, trp[5].o}, // 1 match
  77. {trp[0].p, NULL, NULL}, // 0 matches
  78. {NULL, trp[2].s, NULL}, // 0 matches
  79. {NULL, NULL, trp[5].p}, // 0 matches
  80. {trp[2].s, trp[6].p, NULL}, // 0 matches
  81. {NULL, trp[1].p, trp[5].o}, // 0 matches
  82. {trp[2].s, trp[2].p, trp[5].o}, // 0 matches
  83. };
  84. // Lookup result counts.
  85. size_t lu_ct[N_LUT] = {
  86. 8,
  87. 5, 3, 2,
  88. 1, 1, 1,
  89. 0, 0, 0,
  90. 0, 0, 0
  91. };
  92. /* TODO
  93. // Index of lookup matches from trp.
  94. size_t lu_match[N_LUT][8] = {
  95. {0, 1, 2, 3, 4, 5, 6, 7},
  96. {0, 3, 4, 5, 7}, {2, 4, 7}, {5, 7},
  97. {0}, {0}, {7},
  98. {}, {}, {},
  99. {}, {}, {},
  100. };
  101. // Index of lookup non-matches from trp.
  102. size_t lu_no_match[N_LUT][8] = {
  103. {},
  104. {1, 2, 6}, {0, 1, 3, 5, 6}, {0, 1, 2, 3, 4, 6},
  105. {1, 2, 3, 4, 5, 6, 7}, {1, 2, 3, 4, 5, 6, 7}, {0, 1, 2, 3, 4, 5, 6},
  106. {0, 1, 2, 3, 4, 5, 6, 7}, {0, 1, 2, 3, 4, 5, 6, 7}, {0, 1, 2, 3, 4, 5, 6, 7},
  107. {0, 1, 2, 3, 4, 5, 6, 7}, {0, 1, 2, 3, 4, 5, 6, 7}, {0, 1, 2, 3, 4, 5, 6, 7},
  108. };
  109. */
  110. if (sif->setup_fn) sif->setup_fn (NULL, true);
  111. LSUP_Graph *gr;
  112. LSUP_Store *store;
  113. if (type == LSUP_STORE_HTABLE) {
  114. gr = LSUP_graph_new (NULL, NULL, NULL);
  115. } else {
  116. store = LSUP_store_new (type, NULL, 0);
  117. gr = LSUP_graph_new (store, NULL, NULL);
  118. }
  119. size_t ct;
  120. LSUP_graph_add (gr, trp, &ct);
  121. EXPECT_INT_EQ (ct, 8);
  122. EXPECT_INT_EQ (LSUP_graph_size (gr), 8);
  123. for (int i = 0; i < N_LUT; i++) {
  124. log_info ("Checking triple #%d on %d.", i, type);
  125. LSUP_GraphIterator *it = LSUP_graph_lookup (
  126. gr, lu_trp[i][0], lu_trp[i][1], lu_trp[i][2], &ct);
  127. EXPECT_INT_EQ (ct, lu_ct[i]);
  128. // Verify that iteration count matches stat count.
  129. LSUP_Triple *spo = NULL;
  130. ct = 0;
  131. while (LSUP_graph_iter_next (it, &spo) != LSUP_END) {
  132. ct++;
  133. // TODO do something useful with the triple.
  134. LSUP_triple_free (spo);
  135. spo = NULL;
  136. }
  137. LSUP_triple_free (spo);
  138. EXPECT_INT_EQ (ct, lu_ct[i]);
  139. /* TODO
  140. for (int j = 0; j < 8; j++) {
  141. for (int k = 0; LSUP_graph_iter_next(it) != LSUP_END; k++) {
  142. ASSERT (
  143. LSUP_graph_contains (trp[lu_match[j]]),
  144. "Triple not found!");
  145. ASSERT (
  146. !(LSUP_graph_contains (trp[lu_no_match[j]])),
  147. "Unexpected triple found!");
  148. }
  149. }
  150. */
  151. LSUP_graph_iter_free (it);
  152. };
  153. free_triples (trp);
  154. LSUP_graph_free (gr);
  155. if (type != LSUP_STORE_HTABLE) LSUP_store_free (store);
  156. return 0;
  157. }
  158. static int
  159. _graph_remove (LSUP_StoreType type)
  160. {
  161. const LSUP_StoreInt *sif = LSUP_store_int (type);
  162. if (sif->setup_fn) sif->setup_fn (NULL, true);
  163. LSUP_Triple *trp = create_triples();
  164. LSUP_Graph *gr;
  165. LSUP_Store *store;
  166. if (type == LSUP_STORE_HTABLE) {
  167. gr = LSUP_graph_new (NULL, NULL, NULL);
  168. } else {
  169. store = LSUP_store_new (type, NULL, 0);
  170. gr = LSUP_graph_new (store, NULL, NULL);
  171. }
  172. size_t ct;
  173. LSUP_graph_add (gr, trp, &ct);
  174. EXPECT_INT_EQ (ct, 8);
  175. EXPECT_INT_EQ (LSUP_graph_size (gr), 8);
  176. // Triples 0, 3, 4, 5, 7 will be removed.
  177. LSUP_graph_remove (gr, trp[0].s, NULL, NULL, &ct);
  178. EXPECT_INT_EQ (ct, 5);
  179. EXPECT_INT_EQ (LSUP_graph_size (gr), 3);
  180. ASSERT (!LSUP_graph_contains (gr, trp + 0), "Unexpected triple found!");
  181. ASSERT (LSUP_graph_contains (gr, trp + 1), "Triple not in graph!");
  182. ASSERT (LSUP_graph_contains (gr, trp + 2), "Triple not in graph!");
  183. ASSERT (!LSUP_graph_contains (gr, trp + 3), "Unexpected triple found!");
  184. ASSERT (!LSUP_graph_contains (gr, trp + 4), "Unexpected triple found!");
  185. ASSERT (!LSUP_graph_contains (gr, trp + 5), "Unexpected triple found!");
  186. ASSERT (LSUP_graph_contains (gr, trp + 6), "Triple not in graph!");
  187. ASSERT (!LSUP_graph_contains (gr, trp + 7), "Unexpected triple found!");
  188. free_triples (trp); // gr copied data.
  189. LSUP_graph_free (gr);
  190. if (type != LSUP_STORE_HTABLE) LSUP_store_free (store);
  191. // TODO Test complete removal of triples from index when they are not
  192. // in another context.
  193. return 0;
  194. }
  195. static int
  196. _graph_txn (LSUP_StoreType type)
  197. {
  198. const LSUP_StoreInt *sif = LSUP_store_int (type);
  199. if (!(sif->features & LSUP_STORE_TXN)) return 0;
  200. if (sif->setup_fn) sif->setup_fn (NULL, true);
  201. LSUP_Triple *trp = create_triples();
  202. LSUP_Graph *gr;
  203. LSUP_Store *store =
  204. type == LSUP_STORE_HTABLE ? NULL
  205. : LSUP_store_new (type, NULL, 0);
  206. gr = LSUP_graph_new (store, NULL, NULL);
  207. void *txn;
  208. size_t ct;
  209. EXPECT_PASS (LSUP_store_begin (store, 0, &txn));
  210. EXPECT_PASS (LSUP_graph_add_txn (txn, gr, trp, &ct));
  211. LSUP_store_abort (store, txn);
  212. // NOTE that ct reports the count before the txn was aborted. This is
  213. // intentional.
  214. EXPECT_INT_EQ (ct, 8);
  215. EXPECT_INT_EQ (LSUP_graph_size (gr), 0);
  216. EXPECT_PASS (LSUP_store_begin (store, 0, &txn));
  217. EXPECT_PASS (LSUP_graph_add_txn (txn, gr, trp, &ct));
  218. LSUP_store_commit (store, txn);
  219. EXPECT_INT_EQ (ct, 8);
  220. EXPECT_INT_EQ (LSUP_graph_size (gr), 8);
  221. LSUP_graph_free (gr);
  222. if (type != LSUP_STORE_HTABLE) LSUP_store_free (store);
  223. free_triples (trp); // gr copied data.
  224. return 0;
  225. }
  226. static int
  227. test_environment()
  228. {
  229. // The env should already be initialized and re-initializing it is idempotent.
  230. EXPECT_INT_EQ (LSUP_IS_INIT, true);
  231. ASSERT (LSUP_init() > 0, "Error initializing environment!");
  232. EXPECT_INT_EQ (LSUP_IS_INIT, true);
  233. // Tearing down is idempotent too.
  234. LSUP_done();
  235. EXPECT_INT_EQ (LSUP_IS_INIT, false);
  236. LSUP_done();
  237. EXPECT_INT_EQ (LSUP_IS_INIT, false);
  238. ASSERT (LSUP_init() >= 0, "Environment not initialized!");
  239. EXPECT_INT_EQ (LSUP_IS_INIT, true);
  240. ASSERT (LSUP_init() >= 0, "Environment not initialized!");
  241. EXPECT_INT_EQ (LSUP_IS_INIT, true);
  242. return 0;
  243. }
  244. static int test_graph_new() {
  245. #define ENTRY(a, b) \
  246. if (_graph_new (LSUP_STORE_##a) != 0) return -1;
  247. BACKEND_TBL
  248. #undef ENTRY
  249. return 0;
  250. }
  251. static int test_graph_add() {
  252. #define ENTRY(a, b) \
  253. if (_graph_add (LSUP_STORE_##a) != 0) return -1;
  254. BACKEND_TBL
  255. #undef ENTRY
  256. return 0;
  257. }
  258. static int test_graph_lookup() {
  259. #define ENTRY(a, b) \
  260. if (_graph_lookup (LSUP_STORE_##a) != 0) return -1;
  261. BACKEND_TBL
  262. #undef ENTRY
  263. return 0;
  264. }
  265. static int test_graph_remove() {
  266. #define ENTRY(a, b) \
  267. if (_graph_remove (LSUP_STORE_##a) != 0) return -1;
  268. BACKEND_TBL
  269. #undef ENTRY
  270. return 0;
  271. }
  272. static int test_graph_txn()
  273. {
  274. /*
  275. * Test transactions only if the backend supports them.
  276. */
  277. #define ENTRY(a, b) \
  278. if (_graph_txn (LSUP_STORE_##a) != 0) return -1;
  279. BACKEND_TBL
  280. #undef ENTRY
  281. return 0;
  282. }
  283. static int test_graph_copy()
  284. {
  285. LSUP_Triple *trp = create_triples();
  286. LSUP_Graph *gr1 = LSUP_graph_new (NULL, NULL, NULL);
  287. ASSERT (gr1 != NULL, "Error creating graph!");
  288. LSUP_graph_add (gr1, trp, NULL);
  289. // Copy to graph with same store type.
  290. LSUP_Graph *gr2 = LSUP_graph_new (NULL, NULL, NULL);
  291. EXPECT_PASS (LSUP_graph_copy_contents (gr1, gr2));
  292. EXPECT_INT_EQ (LSUP_graph_size (gr1), LSUP_graph_size (gr2));
  293. for (int i = 0; i < sizeof (trp); i++) {
  294. log_info ("checking triple #%d.", i);
  295. ASSERT (
  296. LSUP_graph_contains (gr2, trp + i),
  297. "Triple not in copied graph!");
  298. }
  299. // Copy to graph with a different store type.
  300. LSUP_Graph *gr3 = LSUP_graph_new (NULL, NULL, NULL);
  301. EXPECT_PASS (LSUP_graph_copy_contents (gr1, gr3));
  302. EXPECT_INT_EQ (LSUP_graph_size (gr1), LSUP_graph_size (gr2));
  303. for (int i = 0; i < sizeof (trp); i++) {
  304. log_info ("checking triple #%d.", i);
  305. ASSERT (
  306. LSUP_graph_contains (gr3, trp + i),
  307. "Triple not in copied graph!");
  308. }
  309. LSUP_graph_free (gr3);
  310. LSUP_graph_free (gr2);
  311. LSUP_graph_free (gr1);
  312. free_triples (trp);
  313. return 0;
  314. }
  315. int graph_tests()
  316. {
  317. RUN (test_environment);
  318. RUN (test_graph_new);
  319. RUN (test_graph_add);
  320. RUN (test_graph_lookup);
  321. RUN (test_graph_remove);
  322. RUN (test_graph_copy);
  323. RUN (test_graph_txn);
  324. return 0;
  325. }