test_graph.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489
  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 (
  56. trp[1]->s, trp[6]->p, trp[4]->o);
  57. ASSERT (! LSUP_graph_contains (gr, missing_trp), "Triple in graph!");
  58. free (missing_trp);
  59. free_triples (trp); // gr copied data.
  60. LSUP_graph_free (gr);
  61. if (type != LSUP_STORE_HTABLE) LSUP_store_free (store);
  62. return 0;
  63. }
  64. static int
  65. _graph_get (LSUP_StoreType type)
  66. {
  67. const LSUP_StoreInt *sif = LSUP_store_int (type);
  68. // Skip if the store doesn't support contexts.
  69. if (!(sif->features & LSUP_STORE_CTX)) return 0;
  70. if (sif->setup_fn) sif->setup_fn (NULL, true);
  71. LSUP_Triple **trp = create_triples();
  72. LSUP_Store *store = LSUP_store_new (type, NULL, 0);
  73. LSUP_Graph
  74. *gr1 = LSUP_graph_new (store, NULL, NULL),
  75. *gr2 = LSUP_graph_new (store, NULL, NULL);
  76. ASSERT (gr1 != NULL, "Error creating graph!");
  77. ASSERT (gr2 != NULL, "Error creating graph!");
  78. // Add 2 groups of triples to different graphs.
  79. void *it1 = LSUP_graph_add_init (gr1);
  80. for (size_t i = 0; i < 5; i++) {
  81. LSUP_graph_add_iter(it1, trp[i]);
  82. }
  83. LSUP_graph_add_done (it1);
  84. void *it2 = LSUP_graph_add_init (gr2);
  85. for (size_t i = 5; i < NUM_TRP; i++) {
  86. LSUP_graph_add_iter(it2, trp[i]);
  87. }
  88. LSUP_graph_add_done (it2);
  89. EXPECT_INT_EQ (LSUP_graph_size (gr1), 5);
  90. EXPECT_INT_EQ (LSUP_graph_size (gr2), 3);
  91. size_t ct3, ct4;
  92. LSUP_Graph
  93. *gr3 = LSUP_graph_get (store, LSUP_graph_uri (gr1), &ct3),
  94. *gr4 = LSUP_graph_get (store, LSUP_graph_uri (gr2), &ct4);
  95. EXPECT_INT_EQ (LSUP_graph_size (gr3), LSUP_graph_size (gr1));
  96. EXPECT_INT_EQ (LSUP_graph_size (gr4), LSUP_graph_size (gr2));
  97. ASSERT (LSUP_graph_equals (gr1, gr3), "Graphs 1 and 3 are not equal!");
  98. ASSERT (LSUP_graph_equals (gr2, gr4), "Graphs 2 and 4 are not equal!");
  99. LSUP_graph_free (gr1);
  100. LSUP_graph_free (gr2);
  101. LSUP_graph_free (gr3);
  102. LSUP_graph_free (gr4);
  103. free_triples (trp);
  104. return 0;
  105. }
  106. static int
  107. _graph_lookup (LSUP_StoreType type)
  108. {
  109. const LSUP_StoreInt *sif = LSUP_store_int (type);
  110. LSUP_Triple **trp = create_triples();
  111. // Lookup triples.
  112. LSUP_Term *lu_trp[N_LUT][3] = {
  113. {NULL, NULL, NULL}, // 8 matches
  114. {trp[0]->s, NULL, NULL}, // 5 matches
  115. {NULL, trp[2]->p, NULL}, // 3 matches
  116. {NULL, NULL, trp[5]->o}, // 2 matches
  117. {trp[0]->s, trp[0]->p, NULL}, // 1 match
  118. {NULL, trp[0]->p, trp[0]->o}, // 1 match
  119. {trp[0]->s, trp[2]->p, trp[5]->o}, // 1 match
  120. {trp[0]->p, NULL, NULL}, // 0 matches
  121. {NULL, trp[2]->s, NULL}, // 0 matches
  122. {NULL, NULL, trp[5]->p}, // 0 matches
  123. {trp[2]->s, trp[6]->p, NULL}, // 0 matches
  124. {NULL, trp[1]->p, trp[5]->o}, // 0 matches
  125. {trp[2]->s, trp[2]->p, trp[5]->o}, // 0 matches
  126. };
  127. // Lookup result counts.
  128. size_t lu_ct[N_LUT] = {
  129. 8,
  130. 5, 3, 2,
  131. 1, 1, 1,
  132. 0, 0, 0,
  133. 0, 0, 0
  134. };
  135. /* TODO
  136. // Index of lookup matches from trp.
  137. size_t lu_match[N_LUT][8] = {
  138. {0, 1, 2, 3, 4, 5, 6, 7},
  139. {0, 3, 4, 5, 7}, {2, 4, 7}, {5, 7},
  140. {0}, {0}, {7},
  141. {}, {}, {},
  142. {}, {}, {},
  143. };
  144. // Index of lookup non-matches from trp.
  145. size_t lu_no_match[N_LUT][8] = {
  146. {},
  147. {1, 2, 6}, {0, 1, 3, 5, 6}, {0, 1, 2, 3, 4, 6},
  148. {1, 2, 3, 4, 5, 6, 7}, {1, 2, 3, 4, 5, 6, 7}, {0, 1, 2, 3, 4, 5, 6},
  149. {0, 1, 2, 3, 4, 5, 6, 7}, {0, 1, 2, 3, 4, 5, 6, 7}, {0, 1, 2, 3, 4, 5, 6, 7},
  150. {0, 1, 2, 3, 4, 5, 6, 7}, {0, 1, 2, 3, 4, 5, 6, 7}, {0, 1, 2, 3, 4, 5, 6, 7},
  151. };
  152. */
  153. if (sif->setup_fn) sif->setup_fn (NULL, true);
  154. LSUP_Graph *gr;
  155. LSUP_Store *store;
  156. if (type == LSUP_STORE_HTABLE) {
  157. gr = LSUP_graph_new (NULL, NULL, NULL);
  158. } else {
  159. store = LSUP_store_new (type, NULL, 0);
  160. gr = LSUP_graph_new (store, NULL, NULL);
  161. }
  162. size_t ct;
  163. LSUP_graph_add (gr, trp, &ct);
  164. EXPECT_INT_EQ (ct, 8);
  165. EXPECT_INT_EQ (LSUP_graph_size (gr), 8);
  166. for (int i = 0; i < N_LUT; i++) {
  167. log_info ("Checking triple #%d on %d.", i, type);
  168. LSUP_GraphIterator *it = LSUP_graph_lookup (
  169. gr, lu_trp[i][0], lu_trp[i][1], lu_trp[i][2], &ct);
  170. EXPECT_INT_EQ (ct, lu_ct[i]);
  171. // Verify that iteration count matches stat count.
  172. LSUP_Triple *spo = NULL;
  173. ct = 0;
  174. while (LSUP_graph_iter_next (it, &spo) != LSUP_END) {
  175. ct++;
  176. // TODO do something useful with the triple.
  177. LSUP_triple_free (spo);
  178. spo = NULL;
  179. }
  180. LSUP_triple_free (spo);
  181. EXPECT_INT_EQ (ct, lu_ct[i]);
  182. /* TODO
  183. for (int j = 0; j < 8; j++) {
  184. for (int k = 0; LSUP_graph_iter_next(it) != LSUP_END; k++) {
  185. ASSERT (
  186. LSUP_graph_contains (trp[lu_match[j]]),
  187. "Triple not found!");
  188. ASSERT (
  189. !(LSUP_graph_contains (trp[lu_no_match[j]])),
  190. "Unexpected triple found!");
  191. }
  192. }
  193. */
  194. LSUP_graph_iter_free (it);
  195. };
  196. free_triples (trp);
  197. LSUP_graph_free (gr);
  198. if (type != LSUP_STORE_HTABLE) LSUP_store_free (store);
  199. return 0;
  200. }
  201. static int
  202. _graph_remove (LSUP_StoreType type)
  203. {
  204. const LSUP_StoreInt *sif = LSUP_store_int (type);
  205. if (sif->setup_fn) sif->setup_fn (NULL, true);
  206. LSUP_Triple **trp = create_triples();
  207. LSUP_Graph *gr;
  208. LSUP_Store *store;
  209. if (type == LSUP_STORE_HTABLE) {
  210. gr = LSUP_graph_new (NULL, NULL, NULL);
  211. } else {
  212. store = LSUP_store_new (type, NULL, 0);
  213. gr = LSUP_graph_new (store, NULL, NULL);
  214. }
  215. size_t ct;
  216. LSUP_graph_add (gr, trp, &ct);
  217. EXPECT_INT_EQ (ct, 8);
  218. EXPECT_INT_EQ (LSUP_graph_size (gr), 8);
  219. // Triples 0, 3, 4, 5, 7 will be removed.
  220. LSUP_graph_remove (gr, trp[0]->s, NULL, NULL, &ct);
  221. EXPECT_INT_EQ (ct, 5);
  222. EXPECT_INT_EQ (LSUP_graph_size (gr), 3);
  223. ASSERT (!LSUP_graph_contains (gr, trp[0]), "Unexpected triple found!");
  224. ASSERT (LSUP_graph_contains (gr, trp[1]), "Triple not in graph!");
  225. ASSERT (LSUP_graph_contains (gr, trp[2]), "Triple not in graph!");
  226. ASSERT (!LSUP_graph_contains (gr, trp[3]), "Unexpected triple found!");
  227. ASSERT (!LSUP_graph_contains (gr, trp[4]), "Unexpected triple found!");
  228. ASSERT (!LSUP_graph_contains (gr, trp[5]), "Unexpected triple found!");
  229. ASSERT (LSUP_graph_contains (gr, trp[6]), "Triple not in graph!");
  230. ASSERT (!LSUP_graph_contains (gr, trp[7]), "Unexpected triple found!");
  231. free_triples (trp); // gr copied data.
  232. LSUP_graph_free (gr);
  233. if (type != LSUP_STORE_HTABLE) LSUP_store_free (store);
  234. // TODO Test complete removal of triples from index when they are not
  235. // in another context.
  236. return 0;
  237. }
  238. static int
  239. _graph_txn (LSUP_StoreType type)
  240. {
  241. const LSUP_StoreInt *sif = LSUP_store_int (type);
  242. if (!(sif->features & LSUP_STORE_TXN)) return 0;
  243. if (sif->setup_fn) sif->setup_fn (NULL, true);
  244. LSUP_Triple **trp = create_triples();
  245. LSUP_Graph *gr;
  246. LSUP_Store *store =
  247. type == LSUP_STORE_HTABLE ? NULL
  248. : LSUP_store_new (type, NULL, 0);
  249. gr = LSUP_graph_new (store, NULL, NULL);
  250. void *txn;
  251. size_t ct;
  252. EXPECT_PASS (LSUP_store_begin (store, 0, &txn));
  253. EXPECT_PASS (LSUP_graph_add_txn (txn, gr, trp, &ct));
  254. LSUP_store_abort (store, txn);
  255. // NOTE that ct reports the count before the txn was aborted. This is
  256. // intentional.
  257. EXPECT_INT_EQ (ct, 8);
  258. EXPECT_INT_EQ (LSUP_graph_size (gr), 0);
  259. EXPECT_PASS (LSUP_store_begin (store, 0, &txn));
  260. EXPECT_PASS (LSUP_graph_add_txn (txn, gr, trp, &ct));
  261. LSUP_store_commit (store, txn);
  262. EXPECT_INT_EQ (ct, 8);
  263. EXPECT_INT_EQ (LSUP_graph_size (gr), 8);
  264. LSUP_graph_free (gr);
  265. if (type != LSUP_STORE_HTABLE) LSUP_store_free (store);
  266. free_triples (trp); // gr copied data.
  267. return 0;
  268. }
  269. static int
  270. test_environment()
  271. {
  272. // The env should already be initialized and re-initializing it is idempotent.
  273. EXPECT_INT_EQ (LSUP_IS_INIT, true);
  274. ASSERT (LSUP_init() > 0, "Error initializing environment!");
  275. EXPECT_INT_EQ (LSUP_IS_INIT, true);
  276. // Tearing down is idempotent too.
  277. LSUP_done();
  278. EXPECT_INT_EQ (LSUP_IS_INIT, false);
  279. LSUP_done();
  280. EXPECT_INT_EQ (LSUP_IS_INIT, false);
  281. ASSERT (LSUP_init() >= 0, "Environment not initialized!");
  282. EXPECT_INT_EQ (LSUP_IS_INIT, true);
  283. ASSERT (LSUP_init() >= 0, "Environment not initialized!");
  284. EXPECT_INT_EQ (LSUP_IS_INIT, true);
  285. return 0;
  286. }
  287. static int test_graph_new() {
  288. #define ENTRY(a, b) \
  289. if (_graph_new (LSUP_STORE_##a) != 0) return -1;
  290. BACKEND_TBL
  291. #undef ENTRY
  292. return 0;
  293. }
  294. static int test_graph_add() {
  295. #define ENTRY(a, b) \
  296. if (_graph_add (LSUP_STORE_##a) != 0) return -1;
  297. BACKEND_TBL
  298. #undef ENTRY
  299. return 0;
  300. }
  301. static int test_graph_get() {
  302. #define ENTRY(a, b) \
  303. if (_graph_get (LSUP_STORE_##a) != 0) return -1;
  304. BACKEND_TBL
  305. #undef ENTRY
  306. return 0;
  307. }
  308. static int test_graph_lookup() {
  309. #define ENTRY(a, b) \
  310. if (_graph_lookup (LSUP_STORE_##a) != 0) return -1;
  311. BACKEND_TBL
  312. #undef ENTRY
  313. return 0;
  314. }
  315. static int test_graph_remove() {
  316. #define ENTRY(a, b) \
  317. if (_graph_remove (LSUP_STORE_##a) != 0) return -1;
  318. BACKEND_TBL
  319. #undef ENTRY
  320. return 0;
  321. }
  322. static int test_graph_txn()
  323. {
  324. /*
  325. * Test transactions only if the backend supports them.
  326. */
  327. #define ENTRY(a, b) \
  328. if (_graph_txn (LSUP_STORE_##a) != 0) return -1;
  329. BACKEND_TBL
  330. #undef ENTRY
  331. return 0;
  332. }
  333. static int test_graph_copy()
  334. {
  335. LSUP_Triple **trp = create_triples();
  336. LSUP_Graph *gr1 = LSUP_graph_new (NULL, NULL, NULL);
  337. ASSERT (gr1 != NULL, "Error creating graph!");
  338. LSUP_graph_add (gr1, trp, NULL);
  339. // Copy to graph with same store type.
  340. LSUP_Graph *gr2 = LSUP_graph_new (NULL, NULL, NULL);
  341. EXPECT_PASS (LSUP_graph_copy_contents (gr1, gr2));
  342. EXPECT_INT_EQ (LSUP_graph_size (gr1), LSUP_graph_size (gr2));
  343. for (int i = 0; i < sizeof (trp); i++) {
  344. log_info ("checking triple #%d.", i);
  345. ASSERT (
  346. LSUP_graph_contains (gr2, trp[i]),
  347. "Triple not in copied graph!");
  348. }
  349. // Copy to graph with a different store type.
  350. LSUP_Graph *gr3 = LSUP_graph_new (NULL, NULL, NULL);
  351. EXPECT_PASS (LSUP_graph_copy_contents (gr1, gr3));
  352. EXPECT_INT_EQ (LSUP_graph_size (gr1), LSUP_graph_size (gr2));
  353. for (int i = 0; i < sizeof (trp); i++) {
  354. log_info ("checking triple #%d.", i);
  355. ASSERT (
  356. LSUP_graph_contains (gr3, trp[i]),
  357. "Triple not in copied graph!");
  358. }
  359. LSUP_graph_free (gr3);
  360. LSUP_graph_free (gr2);
  361. LSUP_graph_free (gr1);
  362. free_triples (trp);
  363. return 0;
  364. }
  365. int graph_tests()
  366. {
  367. RUN (test_environment);
  368. RUN (test_graph_new);
  369. RUN (test_graph_add);
  370. RUN (test_graph_get);
  371. RUN (test_graph_lookup);
  372. RUN (test_graph_remove);
  373. RUN (test_graph_copy);
  374. RUN (test_graph_txn);
  375. return 0;
  376. }