test_graph.c 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822
  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, "urn:gr:1"));
  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) store = NULL;
  41. else store = LSUP_store_new (type, NULL, 0);
  42. gr = LSUP_graph_new (store, NULL, NULL);
  43. ASSERT (gr != NULL, "Error creating graph!");
  44. size_t ct;
  45. LSUP_graph_add (gr, trp, &ct);
  46. EXPECT_INT_EQ (ct, 8);
  47. EXPECT_INT_EQ (LSUP_graph_size (gr), 8);
  48. for (int i = 0; i < sizeof (trp); i++) {
  49. log_info ("checking triple #%d.", i);
  50. ASSERT (LSUP_graph_contains (gr, trp[i]), "Triple not in graph!");
  51. }
  52. LSUP_Triple *missing_trp = LSUP_triple_new (
  53. trp[1]->s, trp[6]->p, trp[4]->o);
  54. ASSERT (! LSUP_graph_contains (gr, missing_trp), "Triple in graph!");
  55. free (missing_trp);
  56. free_triples (trp); // gr copied data.
  57. // Check size again after freeing triples.
  58. EXPECT_INT_EQ (LSUP_graph_size (gr), 8);
  59. LSUP_Graph *gr2 = LSUP_graph_new (NULL, NULL, NULL);
  60. // Test equality against empty graph.
  61. ASSERT (!LSUP_graph_equals (gr, gr2), "Graphs should not be equal!");
  62. ASSERT (!LSUP_graph_equals (gr2, gr), "Graphs should not be equal!");
  63. LSUP_graph_free (gr);
  64. LSUP_graph_free (gr2);
  65. if (type != LSUP_STORE_HTABLE) LSUP_store_free (store);
  66. return 0;
  67. }
  68. static int
  69. _graph_get (LSUP_StoreType type)
  70. {
  71. const LSUP_StoreInt *sif = LSUP_store_int (type);
  72. // Skip if the store doesn't support contexts.
  73. if (!(sif->features & LSUP_STORE_CTX)) return 0;
  74. if (sif->setup_fn) sif->setup_fn (NULL, true);
  75. LSUP_Triple **trp = create_triples();
  76. LSUP_Store *store = LSUP_store_new (type, NULL, 0);
  77. LSUP_Graph
  78. *gr1 = LSUP_graph_new (store, NULL, NULL),
  79. *gr2 = LSUP_graph_new (store, NULL, NULL);
  80. ASSERT (gr1 != NULL, "Error creating graph!");
  81. ASSERT (gr2 != NULL, "Error creating graph!");
  82. // Add 2 groups of triples to different graphs.
  83. void *it1 = LSUP_graph_add_init (gr1);
  84. for (size_t i = 0; i < 5; i++) {
  85. LSUP_graph_add_iter(it1, trp[i]);
  86. }
  87. LSUP_graph_add_done (it1);
  88. void *it2 = LSUP_graph_add_init (gr2);
  89. for (size_t i = 5; i < NUM_TRP; i++) {
  90. LSUP_graph_add_iter(it2, trp[i]);
  91. }
  92. LSUP_graph_add_done (it2);
  93. free_triples (trp);
  94. EXPECT_INT_EQ (LSUP_graph_size (gr1), 5);
  95. EXPECT_INT_EQ (LSUP_graph_size (gr2), 3);
  96. size_t ct3, ct4;
  97. LSUP_Graph
  98. *gr3 = LSUP_graph_get (store, LSUP_graph_uri (gr1), &ct3),
  99. *gr4 = LSUP_graph_get (store, LSUP_graph_uri (gr2), &ct4);
  100. EXPECT_INT_EQ (LSUP_graph_size (gr3), LSUP_graph_size (gr1));
  101. EXPECT_INT_EQ (LSUP_graph_size (gr4), LSUP_graph_size (gr2));
  102. ASSERT (!LSUP_graph_equals (gr1, gr2), "Graphs 1 and 2 are equal!");
  103. ASSERT (!LSUP_graph_equals (gr3, gr4), "Graphs 3 and 4 are equal!");
  104. ASSERT (LSUP_graph_equals (gr1, gr3), "Graphs 1 and 3 are not equal!");
  105. ASSERT (LSUP_graph_equals (gr2, gr4), "Graphs 2 and 4 are not equal!");
  106. LSUP_graph_free (gr1);
  107. LSUP_graph_free (gr2);
  108. LSUP_graph_free (gr3);
  109. LSUP_graph_free (gr4);
  110. if (type != LSUP_STORE_HTABLE) LSUP_store_free (store);
  111. return 0;
  112. }
  113. static int
  114. _graph_link_map (LSUP_StoreType type)
  115. {
  116. const LSUP_StoreInt *sif = LSUP_store_int (type);
  117. if (sif->setup_fn) sif->setup_fn (NULL, true);
  118. LSUP_Triple **trp = create_triples();
  119. LSUP_Store *store = LSUP_store_new (type, NULL, 0);
  120. LSUP_Graph *gr = LSUP_graph_new (store, NULL, NULL);
  121. size_t ct;
  122. LSUP_graph_add (gr, trp, &ct);
  123. LSUP_LinkMap *lmap;
  124. LSUP_LinkMapIterator *lmit ;
  125. //LSUP_Term *k = NULL;
  126. LSUP_TermSet *ts = NULL; // Term set being iterated in link map loop.
  127. LSUP_Term *k_res[9] = {NULL}; // Collected keys.
  128. LSUP_Term *ts_res[9] = {NULL}; // Collected terms in term set in loop.
  129. size_t i = 0, j = 0;
  130. LSUP_Term *po[6][4] = {
  131. {trp[0]->p, trp[0]->o, NULL},
  132. {trp[3]->p, trp[3]->o, NULL},
  133. {trp[4]->p, trp[4]->o, trp[7]->o, NULL},
  134. {trp[5]->p, trp[5]->o, NULL},
  135. {NULL}
  136. };
  137. // terms connected to subject, urn:s:0
  138. lmap = LSUP_graph_connections (gr, trp[0]->s, LSUP_LINK_OUTBOUND);
  139. lmit = LSUP_link_map_iter_new (lmap);
  140. while (LSUP_link_map_next (lmit, k_res + i, &ts) == LSUP_OK) {
  141. while (LSUP_term_set_next (ts, &j, ts_res + j) == LSUP_OK);
  142. /*
  143. // TODO test exact terms. This requires a cross-check.
  144. ASSERT (
  145. LSUP_term_equals (k_res[i], po[i][0]),
  146. "Wrong term in link map!");
  147. for (size_t k = 1; po[i][k]; k++)
  148. ASSERT (
  149. LSUP_term_equals (ts_res[k - 1], po[i][k]),
  150. "Wrong term in term set!");
  151. */
  152. i++;
  153. }
  154. LSUP_link_map_iter_free (lmit);
  155. LSUP_link_map_free (lmap);
  156. EXPECT_INT_EQ (i, 4);
  157. i = 0; j = 0;
  158. memset (k_res, 0, sizeof (k_res));
  159. memset (ts_res, 0, sizeof (ts_res));
  160. LSUP_Term *so[3][3] = {
  161. {trp[1]->s, trp[1]->o, NULL},
  162. {trp[3]->s, trp[3]->o, NULL},
  163. };
  164. // terms connected to predicate, urn:p:1
  165. lmap = LSUP_graph_connections (gr, trp[1]->p, LSUP_LINK_EDGE);
  166. lmit = LSUP_link_map_iter_new (lmap);
  167. while (LSUP_link_map_next (lmit, k_res + i, &ts) == LSUP_OK) {
  168. while (LSUP_term_set_next (ts, &j, ts_res + j) == LSUP_OK);
  169. /*
  170. ASSERT (
  171. LSUP_term_equals (k_res[i], so[i][0]),
  172. "Wrong term in link map!");
  173. for (size_t k = 1; so[i][k]; k++)
  174. ASSERT (
  175. LSUP_term_equals (ts_res[k - 1], so[i][k]),
  176. "Wrong term in term set!");
  177. */
  178. i++;
  179. }
  180. LSUP_link_map_iter_free (lmit);
  181. LSUP_link_map_free (lmap);
  182. EXPECT_INT_EQ (i, 2);
  183. i = 0; j = 0;
  184. memset (k_res, 0, sizeof (k_res));
  185. memset (ts_res, 0, sizeof (ts_res));
  186. LSUP_Term *sp[1][3] = {
  187. {trp[6]->s, trp[6]->p, NULL},
  188. };
  189. // terms connected to object, "String 1"@es-ES
  190. lmap = LSUP_graph_connections (gr, trp[6]->o, LSUP_LINK_INBOUND);
  191. lmit = LSUP_link_map_iter_new (lmap);
  192. while (LSUP_link_map_next (lmit, k_res + i, &ts) == LSUP_OK) {
  193. while (LSUP_term_set_next (ts, &j, ts_res + j) == LSUP_OK);
  194. /*
  195. ASSERT (
  196. LSUP_term_equals (k_res[i], sp[i][0]),
  197. "Wrong term in link map!");
  198. for (size_t k = 1; sp[i][k]; k++)
  199. ASSERT (
  200. LSUP_term_equals (ts_res[k - 1], sp[i][k]),
  201. "Wrong term in term set!");
  202. */
  203. i++;
  204. }
  205. LSUP_link_map_iter_free (lmit);
  206. LSUP_link_map_free (lmap);
  207. EXPECT_INT_EQ (i, 1);
  208. free_triples (trp);
  209. LSUP_graph_free (gr);
  210. if (type != LSUP_STORE_HTABLE) LSUP_store_free (store);
  211. return 0;
  212. }
  213. static int
  214. _graph_bool_ops (LSUP_StoreType type)
  215. {
  216. const LSUP_StoreInt *sif = LSUP_store_int (type);
  217. // Skip if the store doesn't support contexts.
  218. if (!(sif->features & LSUP_STORE_CTX)) return 0;
  219. if (sif->setup_fn) sif->setup_fn (NULL, true);
  220. LSUP_Triple **trp = create_triples();
  221. LSUP_Store *store = LSUP_store_new (type, NULL, 0);
  222. LSUP_Graph
  223. *gr1 = LSUP_graph_new (store, NULL, NULL),
  224. *gr2 = LSUP_graph_new (store, NULL, NULL),
  225. *gr_dest;
  226. // Add 2 groups of triples to different graphs.
  227. void *it;
  228. it = LSUP_graph_add_init (gr1);
  229. for (size_t i = 0; i < 4; i++) {
  230. LSUP_graph_add_iter(it, trp[i]);
  231. }
  232. LSUP_graph_add_done (it);
  233. // Skip duplicate triples, we already tested those.
  234. // trp[3] is in both graphs.
  235. it = LSUP_graph_add_init (gr2);
  236. for (size_t i = 3; i < 8; i++) {
  237. LSUP_graph_add_iter(it, trp[i]);
  238. }
  239. LSUP_graph_add_done (it);
  240. // Test union.
  241. gr_dest = LSUP_graph_new (store, NULL, NULL);
  242. EXPECT_PASS (LSUP_graph_bool_op (LSUP_BOOL_UNION, gr1, gr2, gr_dest));
  243. for (size_t i = 0; i < 8; i++)
  244. ASSERT (LSUP_graph_contains (gr_dest, trp[i]), "Union test failed!");
  245. LSUP_graph_free (gr_dest);
  246. // Test subtraction.
  247. gr_dest = LSUP_graph_new (store, NULL, NULL);
  248. EXPECT_PASS (LSUP_graph_bool_op (
  249. LSUP_BOOL_SUBTRACTION, gr1, gr2, gr_dest));
  250. for (size_t i = 0; i < 3; i++)
  251. ASSERT (LSUP_graph_contains (
  252. gr_dest, trp[i]), "Subtraction test is missing triples!");
  253. for (size_t i = 3; i < 8; i++)
  254. ASSERT (!LSUP_graph_contains (
  255. gr_dest, trp[i]), "Subtraction test has excess triples!");
  256. LSUP_graph_free (gr_dest);
  257. gr_dest = LSUP_graph_new (store, NULL, NULL);
  258. EXPECT_PASS (LSUP_graph_bool_op (
  259. LSUP_BOOL_SUBTRACTION, gr2, gr1, gr_dest));
  260. for (size_t i = 0; i < 4; i++)
  261. ASSERT (!LSUP_graph_contains (
  262. gr_dest, trp[i]), "Subtraction test is missing triples!");
  263. for (size_t i = 4; i < 8; i++)
  264. ASSERT (LSUP_graph_contains (
  265. gr_dest, trp[i]), "Subtraction test has excess triples!");
  266. LSUP_graph_free (gr_dest);
  267. // Test intersection.
  268. gr_dest = LSUP_graph_new (store, NULL, NULL);
  269. EXPECT_PASS (LSUP_graph_bool_op (
  270. LSUP_BOOL_INTERSECTION, gr1, gr2, gr_dest));
  271. for (size_t i = 0; i < 3; i++)
  272. ASSERT (!LSUP_graph_contains (
  273. gr_dest, trp[i]), "Intersection is missing triples!");
  274. ASSERT (LSUP_graph_contains (
  275. gr_dest, trp[3]), "Intersection test failed!");
  276. for (size_t i = 4; i < 8; i++)
  277. ASSERT (!LSUP_graph_contains (
  278. gr_dest, trp[i]), "Intersection test has excess triples!");
  279. LSUP_graph_free (gr_dest);
  280. // Test XOR.
  281. gr_dest = LSUP_graph_new (store, NULL, NULL);
  282. EXPECT_PASS (LSUP_graph_bool_op (LSUP_BOOL_XOR, gr1, gr2, gr_dest));
  283. for (size_t i = 0; i < 3; i++)
  284. ASSERT (LSUP_graph_contains (
  285. gr_dest, trp[i]), "XOR test is missing triples!");
  286. ASSERT (!LSUP_graph_contains (
  287. gr_dest, trp[3]), "XOR test has excess triples!");
  288. for (size_t i = 4; i < 8; i++)
  289. ASSERT (LSUP_graph_contains (
  290. gr_dest, trp[i]), "XOR test is missing triples!");
  291. LSUP_graph_free (gr_dest);
  292. // Test union with result graph as one of the sources.
  293. EXPECT_PASS (LSUP_graph_bool_op (LSUP_BOOL_UNION, gr1, gr2, gr1));
  294. for (size_t i = 0; i < 8; i++)
  295. ASSERT (LSUP_graph_contains (gr1, trp[i]), "Self-union test failed!");
  296. LSUP_graph_free (gr1);
  297. LSUP_graph_free (gr2);
  298. free_triples (trp);
  299. if (type != LSUP_STORE_HTABLE) LSUP_store_free (store);
  300. return 0;
  301. }
  302. static int
  303. _graph_lookup (LSUP_StoreType type)
  304. {
  305. const LSUP_StoreInt *sif = LSUP_store_int (type);
  306. LSUP_Triple **trp = create_triples();
  307. // Lookup triples.
  308. LSUP_Term *lu_trp[N_LUT][3] = {
  309. {NULL, NULL, NULL}, // 8 matches
  310. {trp[0]->s, NULL, NULL}, // 5 matches
  311. {NULL, trp[2]->p, NULL}, // 3 matches
  312. {NULL, NULL, trp[5]->o}, // 2 matches
  313. {trp[0]->s, trp[0]->p, NULL}, // 1 match
  314. {NULL, trp[0]->p, trp[0]->o}, // 1 match
  315. {trp[0]->s, trp[2]->p, trp[5]->o}, // 1 match
  316. {trp[0]->p, NULL, NULL}, // 0 matches
  317. {NULL, trp[2]->s, NULL}, // 0 matches
  318. {NULL, NULL, trp[5]->p}, // 0 matches
  319. {trp[2]->s, trp[6]->p, NULL}, // 0 matches
  320. {NULL, trp[1]->p, trp[5]->o}, // 0 matches
  321. {trp[2]->s, trp[2]->p, trp[5]->o}, // 0 matches
  322. };
  323. // Lookup result counts.
  324. size_t lu_ct[N_LUT] = {
  325. 8,
  326. 5, 3, 2,
  327. 1, 1, 1,
  328. 0, 0, 0,
  329. 0, 0, 0
  330. };
  331. /* TODO
  332. // Index of lookup matches from trp.
  333. size_t lu_match[N_LUT][8] = {
  334. {0, 1, 2, 3, 4, 5, 6, 7},
  335. {0, 3, 4, 5, 7}, {2, 4, 7}, {5, 7},
  336. {0}, {0}, {7},
  337. {}, {}, {},
  338. {}, {}, {},
  339. };
  340. // Index of lookup non-matches from trp.
  341. size_t lu_no_match[N_LUT][8] = {
  342. {},
  343. {1, 2, 6}, {0, 1, 3, 5, 6}, {0, 1, 2, 3, 4, 6},
  344. {1, 2, 3, 4, 5, 6, 7}, {1, 2, 3, 4, 5, 6, 7}, {0, 1, 2, 3, 4, 5, 6},
  345. {0, 1, 2, 3, 4, 5, 6, 7}, {0, 1, 2, 3, 4, 5, 6, 7}, {0, 1, 2, 3, 4, 5, 6, 7},
  346. {0, 1, 2, 3, 4, 5, 6, 7}, {0, 1, 2, 3, 4, 5, 6, 7}, {0, 1, 2, 3, 4, 5, 6, 7},
  347. };
  348. */
  349. if (sif->setup_fn) sif->setup_fn (NULL, true);
  350. LSUP_Graph *gr;
  351. LSUP_Store *store;
  352. if (type == LSUP_STORE_HTABLE) {
  353. gr = LSUP_graph_new (NULL, NULL, NULL);
  354. } else {
  355. store = LSUP_store_new (type, NULL, 0);
  356. gr = LSUP_graph_new (store, NULL, NULL);
  357. }
  358. size_t ct;
  359. LSUP_graph_add (gr, trp, &ct);
  360. EXPECT_INT_EQ (ct, 8);
  361. EXPECT_INT_EQ (LSUP_graph_size (gr), 8);
  362. for (int i = 0; i < N_LUT; i++) {
  363. log_info ("Checking triple #%d on %d.", i, type);
  364. LSUP_GraphIterator *it = LSUP_graph_lookup (
  365. gr, lu_trp[i][0], lu_trp[i][1], lu_trp[i][2], &ct);
  366. EXPECT_INT_EQ (ct, lu_ct[i]);
  367. // Verify that iteration count matches stat count.
  368. LSUP_Triple *spo = NULL;
  369. ct = 0;
  370. while (LSUP_graph_iter_next (it, &spo) != LSUP_END) {
  371. ct++;
  372. // TODO do something useful with the triple.
  373. LSUP_triple_free (spo);
  374. spo = NULL;
  375. }
  376. LSUP_triple_free (spo);
  377. EXPECT_INT_EQ (ct, lu_ct[i]);
  378. /* TODO
  379. for (int j = 0; j < 8; j++) {
  380. for (int k = 0; LSUP_graph_iter_next(it) != LSUP_END; k++) {
  381. ASSERT (
  382. LSUP_graph_contains (trp[lu_match[j]]),
  383. "Triple not found!");
  384. ASSERT (
  385. !(LSUP_graph_contains (trp[lu_no_match[j]])),
  386. "Unexpected triple found!");
  387. }
  388. }
  389. */
  390. LSUP_graph_iter_free (it);
  391. };
  392. #if 0
  393. // Enable to test print functionality and exit early.
  394. LSUP_graph_print (gr);
  395. return 1;
  396. #endif
  397. free_triples (trp);
  398. LSUP_graph_free (gr);
  399. if (type != LSUP_STORE_HTABLE) LSUP_store_free (store);
  400. return 0;
  401. }
  402. static int
  403. _graph_remove (LSUP_StoreType type)
  404. {
  405. const LSUP_StoreInt *sif = LSUP_store_int (type);
  406. if (sif->setup_fn) sif->setup_fn (NULL, true);
  407. LSUP_Triple **trp = create_triples();
  408. LSUP_Graph *gr;
  409. LSUP_Store *store;
  410. if (type == LSUP_STORE_HTABLE) {
  411. gr = LSUP_graph_new (NULL, NULL, NULL);
  412. } else {
  413. store = LSUP_store_new (type, NULL, 0);
  414. gr = LSUP_graph_new (store, NULL, NULL);
  415. }
  416. size_t ct;
  417. LSUP_graph_add (gr, trp, &ct);
  418. EXPECT_INT_EQ (ct, 8);
  419. EXPECT_INT_EQ (LSUP_graph_size (gr), 8);
  420. // Triples 0, 3, 4, 5, 7 will be removed.
  421. LSUP_graph_remove (gr, trp[0]->s, NULL, NULL, &ct);
  422. EXPECT_INT_EQ (ct, 5);
  423. EXPECT_INT_EQ (LSUP_graph_size (gr), 3);
  424. ASSERT (!LSUP_graph_contains (gr, trp[0]), "Unexpected triple found!");
  425. ASSERT (LSUP_graph_contains (gr, trp[1]), "Triple not in graph!");
  426. ASSERT (LSUP_graph_contains (gr, trp[2]), "Triple not in graph!");
  427. ASSERT (!LSUP_graph_contains (gr, trp[3]), "Unexpected triple found!");
  428. ASSERT (!LSUP_graph_contains (gr, trp[4]), "Unexpected triple found!");
  429. ASSERT (!LSUP_graph_contains (gr, trp[5]), "Unexpected triple found!");
  430. ASSERT (LSUP_graph_contains (gr, trp[6]), "Triple not in graph!");
  431. ASSERT (!LSUP_graph_contains (gr, trp[7]), "Unexpected triple found!");
  432. free_triples (trp); // gr copied data.
  433. LSUP_graph_free (gr);
  434. if (type != LSUP_STORE_HTABLE) LSUP_store_free (store);
  435. // TODO Test complete removal of triples from index when they are not
  436. // in another context.
  437. return 0;
  438. }
  439. static int
  440. _graph_txn (LSUP_StoreType type)
  441. {
  442. const LSUP_StoreInt *sif = LSUP_store_int (type);
  443. if (!(sif->features & LSUP_STORE_TXN)) return 0;
  444. if (sif->setup_fn) sif->setup_fn (NULL, true);
  445. LSUP_Triple **trp = create_triples();
  446. LSUP_Graph *gr;
  447. LSUP_Store *store =
  448. type == LSUP_STORE_HTABLE ? NULL
  449. : LSUP_store_new (type, NULL, 0);
  450. gr = LSUP_graph_new (store, NULL, NULL);
  451. void *txn;
  452. size_t ct;
  453. EXPECT_PASS (LSUP_store_begin (store, 0, &txn));
  454. EXPECT_PASS (LSUP_graph_add_txn (txn, gr, trp, &ct));
  455. LSUP_store_abort (store, txn);
  456. // NOTE that ct reports the count before the txn was aborted. This is
  457. // intentional.
  458. EXPECT_INT_EQ (ct, 8);
  459. EXPECT_INT_EQ (LSUP_graph_size (gr), 0);
  460. EXPECT_PASS (LSUP_store_begin (store, 0, &txn));
  461. EXPECT_PASS (LSUP_graph_add_txn (txn, gr, trp, &ct));
  462. LSUP_store_commit (store, txn);
  463. EXPECT_INT_EQ (ct, 8);
  464. EXPECT_INT_EQ (LSUP_graph_size (gr), 8);
  465. LSUP_graph_free (gr);
  466. if (type != LSUP_STORE_HTABLE) LSUP_store_free (store);
  467. free_triples (trp); // gr copied data.
  468. return 0;
  469. }
  470. static int
  471. _graph_relative (LSUP_StoreType type)
  472. {
  473. const LSUP_StoreInt *sif = LSUP_store_int (type);
  474. if (sif->setup_fn) sif->setup_fn (NULL, true);
  475. LSUP_Term
  476. *s = LSUP_iriref_new ("http://onto.knowledgetx.com/gr1/s1", NULL),
  477. *s2 = LSUP_iriref_new ("http://onto.knowledgetx.com/gr2/s1", NULL),
  478. *p = LSUP_iriref_new ("http://onto.knowledgetx.com/vocab/p1", NULL),
  479. *o = LSUP_iriref_new ("http://onto.knowledgetx.com/gr1/o1", NULL),
  480. *o2 = LSUP_iriref_new ("http://onto.knowledgetx.com/gr2/o1", NULL),
  481. *c = LSUP_iriref_new ("http://onto.knowledgetx.com/gr1/", NULL),
  482. *rel_s = LSUP_iriref_relative (c, s),
  483. *rel_o = LSUP_iriref_relative (c, o);
  484. LSUP_Triple *spo[2] = {
  485. LSUP_triple_new (s, p, o),
  486. NULL
  487. };
  488. LSUP_Triple *rel_spo = LSUP_triple_new (rel_s, p, rel_o);
  489. LSUP_Store *store =
  490. type == LSUP_STORE_HTABLE ? NULL
  491. : LSUP_store_new (type, NULL, 0);
  492. LSUP_Graph *gr = LSUP_graph_new (store, c->data, NULL);
  493. size_t ct;
  494. LSUP_graph_add (gr, spo, &ct);
  495. // Both absolute and relative IRIs should be found.
  496. ASSERT (LSUP_graph_contains (gr, rel_spo), "Relative triple not found!");
  497. ASSERT (LSUP_graph_contains (gr, spo[0]), "Absolute triple not found!");
  498. // Change graph URI and verify that relative URIs are still found, and
  499. // that absolute URIs change with it.
  500. spo[0]->s = s2;
  501. LSUP_term_free (s);
  502. spo[0]->o = o2;
  503. LSUP_term_free (o);
  504. LSUP_graph_set_uri (gr, "http://onto.knowledgetx.com/gr2/");
  505. LSUP_term_free (c);
  506. ASSERT (LSUP_graph_contains (gr, rel_spo), "Relative triple not found!");
  507. ASSERT (LSUP_graph_contains (gr, spo[0]), "Absolute triple not found!");
  508. LSUP_triple_free (spo[0]);
  509. LSUP_term_free (rel_s);
  510. LSUP_term_free (rel_o);
  511. free (rel_spo);
  512. LSUP_graph_free (gr);
  513. if (type != LSUP_STORE_HTABLE) LSUP_store_free (store);
  514. return 0;
  515. }
  516. static int
  517. test_environment()
  518. {
  519. // The env should already be initialized and re-initializing it is idempotent.
  520. EXPECT_INT_EQ (LSUP_IS_INIT, true);
  521. ASSERT (LSUP_init() > 0, "Error initializing environment!");
  522. EXPECT_INT_EQ (LSUP_IS_INIT, true);
  523. // Tearing down is idempotent too.
  524. LSUP_done();
  525. EXPECT_INT_EQ (LSUP_IS_INIT, false);
  526. LSUP_done();
  527. EXPECT_INT_EQ (LSUP_IS_INIT, false);
  528. ASSERT (LSUP_init() >= 0, "Environment not initialized!");
  529. EXPECT_INT_EQ (LSUP_IS_INIT, true);
  530. ASSERT (LSUP_init() >= 0, "Environment not initialized!");
  531. EXPECT_INT_EQ (LSUP_IS_INIT, true);
  532. return 0;
  533. }
  534. static int test_graph_new() {
  535. #define ENTRY(a, b) \
  536. if (_graph_new (LSUP_STORE_##a) != 0) return -1;
  537. BACKEND_TBL
  538. #undef ENTRY
  539. return 0;
  540. }
  541. static int test_graph_add() {
  542. #define ENTRY(a, b) \
  543. if (_graph_add (LSUP_STORE_##a) != 0) return -1;
  544. BACKEND_TBL
  545. #undef ENTRY
  546. return 0;
  547. }
  548. static int test_graph_get() {
  549. #define ENTRY(a, b) \
  550. if (_graph_get (LSUP_STORE_##a) != 0) return -1;
  551. BACKEND_TBL
  552. #undef ENTRY
  553. return 0;
  554. }
  555. static int test_graph_link_map() {
  556. #define ENTRY(a, b) \
  557. if (_graph_link_map (LSUP_STORE_##a) != 0) return -1;
  558. BACKEND_TBL
  559. #undef ENTRY
  560. return 0;
  561. }
  562. static int test_graph_bool_ops() {
  563. #define ENTRY(a, b) \
  564. if (_graph_bool_ops (LSUP_STORE_##a) != 0) return -1;
  565. BACKEND_TBL
  566. #undef ENTRY
  567. return 0;
  568. }
  569. static int test_graph_lookup() {
  570. #define ENTRY(a, b) \
  571. if (_graph_lookup (LSUP_STORE_##a) != 0) return -1;
  572. BACKEND_TBL
  573. #undef ENTRY
  574. return 0;
  575. }
  576. static int test_graph_remove() {
  577. #define ENTRY(a, b) \
  578. if (_graph_remove (LSUP_STORE_##a) != 0) return -1;
  579. BACKEND_TBL
  580. #undef ENTRY
  581. return 0;
  582. }
  583. static int test_graph_txn()
  584. {
  585. /*
  586. * Test transactions only if the backend supports them.
  587. */
  588. #define ENTRY(a, b) \
  589. if (_graph_txn (LSUP_STORE_##a) != 0) return -1;
  590. BACKEND_TBL
  591. #undef ENTRY
  592. return 0;
  593. }
  594. static int test_graph_relative()
  595. {
  596. /*
  597. * Test relative URIs in graphs.
  598. */
  599. #define ENTRY(a, b) \
  600. if (_graph_relative (LSUP_STORE_##a) != 0) return -1;
  601. BACKEND_TBL
  602. #undef ENTRY
  603. return 0;
  604. }
  605. static int test_graph_copy()
  606. {
  607. LSUP_Triple **trp = create_triples();
  608. LSUP_Graph *gr1 = LSUP_graph_new (NULL, NULL, NULL);
  609. ASSERT (gr1 != NULL, "Error creating graph!");
  610. LSUP_graph_add (gr1, trp, NULL);
  611. // Copy to graph with same store type.
  612. LSUP_Graph *gr2 = LSUP_graph_new (NULL, NULL, NULL);
  613. EXPECT_PASS (LSUP_graph_copy_contents (gr1, gr2, NULL, NULL, NULL));
  614. EXPECT_INT_EQ (LSUP_graph_size (gr1), LSUP_graph_size (gr2));
  615. for (int i = 0; i < sizeof (trp); i++) {
  616. log_info ("checking triple #%d.", i);
  617. ASSERT (
  618. LSUP_graph_contains (gr2, trp[i]),
  619. "Triple not in copied graph!");
  620. }
  621. // Copy to graph with a different store type.
  622. LSUP_Graph *gr3 = LSUP_graph_new (NULL, NULL, NULL);
  623. EXPECT_PASS (LSUP_graph_copy_contents (gr1, gr3, NULL, NULL, NULL));
  624. EXPECT_INT_EQ (LSUP_graph_size (gr1), LSUP_graph_size (gr2));
  625. for (int i = 0; i < sizeof (trp); i++) {
  626. log_info ("checking triple #%d.", i);
  627. ASSERT (
  628. LSUP_graph_contains (gr3, trp[i]),
  629. "Triple not in copied graph!");
  630. }
  631. LSUP_graph_free (gr3);
  632. LSUP_graph_free (gr2);
  633. LSUP_graph_free (gr1);
  634. free_triples (trp);
  635. return 0;
  636. }
  637. int graph_tests()
  638. {
  639. RUN (test_environment);
  640. RUN (test_graph_new);
  641. RUN (test_graph_add);
  642. RUN (test_graph_get);
  643. RUN (test_graph_link_map);
  644. RUN (test_graph_bool_ops);
  645. RUN (test_graph_lookup);
  646. RUN (test_graph_remove);
  647. RUN (test_graph_copy);
  648. RUN (test_graph_txn);
  649. RUN (test_graph_relative);
  650. return 0;
  651. }