test_graph.c 10 KB

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