test_graph.c 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920
  1. #include "volksdata/graph.h"
  2. #include "test.h"
  3. #include "assets/triples.h"
  4. #define N_LUT 13
  5. static int
  6. _graph_new (VOLK_StoreType type)
  7. {
  8. VOLK_Graph *gr;
  9. VOLK_Store *store = NULL;
  10. if (type == VOLK_STORE_HTABLE) {
  11. gr = VOLK_graph_new (NULL, NULL);
  12. } else {
  13. store = VOLK_store_new (type, NULL, 0, true);
  14. gr = VOLK_graph_new (store, NULL);
  15. }
  16. ASSERT (gr != NULL, "Error creating graph!");
  17. EXPECT_PASS (VOLK_graph_set_uri (gr, "urn:gr:1"));
  18. EXPECT_STR_EQ (VOLK_graph_uri (gr)->data, "urn:gr:1");
  19. ASSERT (
  20. strcmp (VOLK_graph_uri (gr)->data, "urn:gr:1") == 0,
  21. "Graph URI mismatch!");
  22. EXPECT_INT_EQ (VOLK_graph_size (gr), 0);
  23. // Check that setup function is idempotent with clear == false.
  24. const VOLK_StoreInt *sif = VOLK_store_int (type);
  25. if (sif->setup_fn) EXPECT_INT_EQ (
  26. sif->setup_fn (NULL, false), VOLK_NOACTION);
  27. VOLK_graph_free (gr);
  28. VOLK_store_free (store);
  29. return 0;
  30. }
  31. /// Test creating a graph with a namespaced URI.
  32. static int
  33. _graph_ns_uri (VOLK_StoreType type)
  34. {
  35. const VOLK_StoreInt *sif = VOLK_store_int (type);
  36. const char *nsdata[][2] = {
  37. {"ns1", "urn:ns1#"},
  38. {"ns2", "urn:ns2#"},
  39. {"ns3", "urn:ns3#"},
  40. {NULL}
  41. };
  42. VOLK_Store *store = NULL;
  43. if (sif->features & VOLK_STORE_PERM)
  44. store = VOLK_store_new (type, NULL, 0, true);
  45. log_info("Testing NSM for graph store type: %d", type);
  46. for (int i = 0; nsdata[i][0]; i++)
  47. EXPECT_PASS (VOLK_nsmap_add (nsdata[i][0], nsdata[i][1]));
  48. VOLK_Graph *gr;
  49. gr = VOLK_graph_new_ns (store, NULL);
  50. ASSERT (gr == NULL, "NS graph URI cannot be NULL!");
  51. gr = VOLK_graph_new_ns (store, "ns1:gr1");
  52. ASSERT (gr != NULL, "Error creating graph!");
  53. VOLK_Term *comp = VOLK_iriref_new ("urn:ns1#gr1");
  54. ASSERT (
  55. VOLK_term_equals (VOLK_graph_uri (gr), comp),
  56. "Namespaced graph URI is incorrect!" );
  57. VOLK_term_free (comp);
  58. VOLK_graph_free (gr);
  59. VOLK_store_free (store);
  60. return 0;
  61. }
  62. static int
  63. _graph_add (VOLK_StoreType type)
  64. {
  65. VOLK_Triple **trp = create_triples();
  66. VOLK_Graph *gr;
  67. VOLK_Store *store;
  68. if (type == VOLK_STORE_HTABLE) store = NULL;
  69. else store = VOLK_store_new (type, NULL, 0, true);
  70. gr = VOLK_graph_new (store, NULL);
  71. ASSERT (gr != NULL, "Error creating graph!");
  72. size_t ct;
  73. VOLK_graph_add (gr, trp, &ct);
  74. EXPECT_INT_EQ (ct, 8);
  75. EXPECT_INT_EQ (VOLK_graph_size (gr), 8);
  76. for (unsigned int i = 0; i < sizeof (trp); i++) {
  77. log_info ("checking triple #%d.", i);
  78. ASSERT (VOLK_graph_contains (gr, trp[i]), "Triple not in graph!");
  79. }
  80. VOLK_Triple *missing_trp = VOLK_triple_new (
  81. trp[1]->s, trp[6]->p, trp[4]->o);
  82. ASSERT (! VOLK_graph_contains (gr, missing_trp), "Triple in graph!");
  83. free (missing_trp);
  84. free_triples (trp); // gr copied data.
  85. // Check size again after freeing triples.
  86. EXPECT_INT_EQ (VOLK_graph_size (gr), 8);
  87. VOLK_Graph *gr2 = VOLK_graph_new (NULL, NULL);
  88. // Test equality against empty graph.
  89. ASSERT (!VOLK_graph_equals (gr, gr2), "Graphs should not be equal!");
  90. ASSERT (!VOLK_graph_equals (gr2, gr), "Graphs should not be equal!");
  91. VOLK_graph_free (gr);
  92. VOLK_graph_free (gr2);
  93. VOLK_store_free (store);
  94. return 0;
  95. }
  96. static int
  97. _graph_get (VOLK_StoreType type)
  98. {
  99. const VOLK_StoreInt *sif = VOLK_store_int (type);
  100. // Skip if the store doesn't support contexts.
  101. if (!(sif->features & VOLK_STORE_CTX)) return 0;
  102. VOLK_Triple **trp = create_triples();
  103. VOLK_Store *store;
  104. if (type == VOLK_STORE_HTABLE) store = NULL;
  105. else store = VOLK_store_new (type, NULL, 0, true);
  106. VOLK_Graph
  107. *gr1 = VOLK_graph_new (store, NULL),
  108. *gr2 = VOLK_graph_new (store, NULL);
  109. ASSERT (gr1 != NULL, "Error creating graph!");
  110. ASSERT (gr2 != NULL, "Error creating graph!");
  111. // Add 2 groups of triples to different graphs.
  112. void *it1 = VOLK_graph_add_init (gr1);
  113. for (size_t i = 0; i < 5; i++) {
  114. VOLK_graph_add_iter(it1, trp[i]);
  115. }
  116. VOLK_graph_add_done (it1);
  117. void *it2 = VOLK_graph_add_init (gr2);
  118. for (size_t i = 5; i < NUM_TRP; i++) {
  119. VOLK_graph_add_iter(it2, trp[i]);
  120. }
  121. VOLK_graph_add_done (it2);
  122. free_triples (trp);
  123. EXPECT_INT_EQ (VOLK_graph_size (gr1), 5);
  124. EXPECT_INT_EQ (VOLK_graph_size (gr2), 3);
  125. size_t ct3, ct4;
  126. VOLK_Graph
  127. *gr3 = VOLK_graph_get (store, VOLK_graph_uri (gr1), &ct3),
  128. *gr4 = VOLK_graph_get (store, VOLK_graph_uri (gr2), &ct4);
  129. EXPECT_INT_EQ (VOLK_graph_size (gr3), VOLK_graph_size (gr1));
  130. EXPECT_INT_EQ (VOLK_graph_size (gr3), ct3);
  131. EXPECT_INT_EQ (VOLK_graph_size (gr4), VOLK_graph_size (gr2));
  132. EXPECT_INT_EQ (VOLK_graph_size (gr4), ct4);
  133. ASSERT (!VOLK_graph_equals (gr1, gr2), "Graphs 1 and 2 are equal!");
  134. ASSERT (!VOLK_graph_equals (gr3, gr4), "Graphs 3 and 4 are equal!");
  135. ASSERT (VOLK_graph_equals (gr1, gr3), "Graphs 1 and 3 are not equal!");
  136. ASSERT (VOLK_graph_equals (gr2, gr4), "Graphs 2 and 4 are not equal!");
  137. VOLK_graph_free (gr1);
  138. VOLK_graph_free (gr2);
  139. VOLK_graph_free (gr3);
  140. VOLK_graph_free (gr4);
  141. VOLK_store_free (store);
  142. return 0;
  143. }
  144. static int
  145. _graph_link_map (VOLK_StoreType type)
  146. {
  147. VOLK_Triple **trp = create_triples();
  148. VOLK_Store *store;
  149. if (type == VOLK_STORE_HTABLE) store = NULL;
  150. else store = VOLK_store_new (type, NULL, 0, true);
  151. VOLK_Graph *gr = VOLK_graph_new (store, NULL);
  152. size_t ct;
  153. VOLK_graph_add (gr, trp, &ct);
  154. VOLK_LinkMap *lmap;
  155. VOLK_LinkMapIterator *lmit ;
  156. //VOLK_Term *k = NULL;
  157. VOLK_TermSet *ts = NULL; // Term set being iterated in link map loop.
  158. VOLK_Term *k_res[9] = {NULL}; // Collected keys.
  159. VOLK_Term *ts_res[9] = {NULL}; // Collected terms in term set in loop.
  160. size_t i = 0, j = 0;
  161. /*
  162. VOLK_Term *po[6][4] = {
  163. {trp[0]->p, trp[0]->o, NULL},
  164. {trp[3]->p, trp[3]->o, NULL},
  165. {trp[4]->p, trp[4]->o, trp[7]->o, NULL},
  166. {trp[5]->p, trp[5]->o, NULL},
  167. {NULL}
  168. };
  169. */
  170. // terms connected to subject, urn:s:0
  171. lmap = VOLK_graph_connections (gr, trp[0]->s, VOLK_LINK_OUTBOUND);
  172. lmit = VOLK_link_map_iter_new (lmap);
  173. while (VOLK_link_map_next (lmit, k_res + i, &ts) == VOLK_OK) {
  174. while (VOLK_term_set_next (ts, &j, ts_res + j) == VOLK_OK);
  175. /*
  176. // TODO test exact terms. This requires a cross-check.
  177. ASSERT (
  178. VOLK_term_equals (k_res[i], po[i][0]),
  179. "Wrong term in link map!");
  180. for (size_t k = 1; po[i][k]; k++)
  181. ASSERT (
  182. VOLK_term_equals (ts_res[k - 1], po[i][k]),
  183. "Wrong term in term set!");
  184. */
  185. i++;
  186. }
  187. VOLK_link_map_iter_free (lmit);
  188. VOLK_link_map_free (lmap);
  189. EXPECT_INT_EQ (i, 4);
  190. i = 0; j = 0;
  191. memset (k_res, 0, sizeof (k_res));
  192. memset (ts_res, 0, sizeof (ts_res));
  193. /*
  194. VOLK_Term *so[3][3] = {
  195. {trp[1]->s, trp[1]->o, NULL},
  196. {trp[3]->s, trp[3]->o, NULL},
  197. };
  198. */
  199. // terms connected to predicate, urn:p:1
  200. lmap = VOLK_graph_connections (gr, trp[1]->p, VOLK_LINK_EDGE);
  201. lmit = VOLK_link_map_iter_new (lmap);
  202. while (VOLK_link_map_next (lmit, k_res + i, &ts) == VOLK_OK) {
  203. while (VOLK_term_set_next (ts, &j, ts_res + j) == VOLK_OK);
  204. /*
  205. ASSERT (
  206. VOLK_term_equals (k_res[i], so[i][0]),
  207. "Wrong term in link map!");
  208. for (size_t k = 1; so[i][k]; k++)
  209. ASSERT (
  210. VOLK_term_equals (ts_res[k - 1], so[i][k]),
  211. "Wrong term in term set!");
  212. */
  213. i++;
  214. }
  215. VOLK_link_map_iter_free (lmit);
  216. VOLK_link_map_free (lmap);
  217. EXPECT_INT_EQ (i, 2);
  218. i = 0; j = 0;
  219. memset (k_res, 0, sizeof (k_res));
  220. memset (ts_res, 0, sizeof (ts_res));
  221. /*
  222. VOLK_Term *sp[1][3] = {
  223. {trp[6]->s, trp[6]->p, NULL},
  224. };
  225. */
  226. // terms connected to object, "String 1"@es-ES
  227. lmap = VOLK_graph_connections (gr, trp[6]->o, VOLK_LINK_INBOUND);
  228. lmit = VOLK_link_map_iter_new (lmap);
  229. while (VOLK_link_map_next (lmit, k_res + i, &ts) == VOLK_OK) {
  230. while (VOLK_term_set_next (ts, &j, ts_res + j) == VOLK_OK);
  231. /*
  232. ASSERT (
  233. VOLK_term_equals (k_res[i], sp[i][0]),
  234. "Wrong term in link map!");
  235. for (size_t k = 1; sp[i][k]; k++)
  236. ASSERT (
  237. VOLK_term_equals (ts_res[k - 1], sp[i][k]),
  238. "Wrong term in term set!");
  239. */
  240. i++;
  241. }
  242. VOLK_link_map_iter_free (lmit);
  243. VOLK_link_map_free (lmap);
  244. EXPECT_INT_EQ (i, 1);
  245. free_triples (trp);
  246. VOLK_graph_free (gr);
  247. VOLK_store_free (store);
  248. return 0;
  249. }
  250. static int
  251. _graph_bool_ops (VOLK_StoreType type)
  252. {
  253. const VOLK_StoreInt *sif = VOLK_store_int (type);
  254. // Skip if the store doesn't support contexts.
  255. if (!(sif->features & VOLK_STORE_CTX)) return 0;
  256. VOLK_Triple **trp = create_triples();
  257. VOLK_Store *store;
  258. if (type == VOLK_STORE_HTABLE) store = NULL;
  259. else store = VOLK_store_new (type, NULL, 0, true);
  260. VOLK_Graph
  261. *gr1 = VOLK_graph_new (store, NULL),
  262. *gr2 = VOLK_graph_new (store, NULL),
  263. *gr_dest;
  264. // Add 2 groups of triples to different graphs.
  265. void *it;
  266. it = VOLK_graph_add_init (gr1);
  267. for (size_t i = 0; i < 4; i++) {
  268. VOLK_graph_add_iter(it, trp[i]);
  269. }
  270. VOLK_graph_add_done (it);
  271. // Skip duplicate triples, we already tested those.
  272. // trp[3] is in both graphs.
  273. it = VOLK_graph_add_init (gr2);
  274. for (size_t i = 3; i < 8; i++) {
  275. VOLK_graph_add_iter(it, trp[i]);
  276. }
  277. VOLK_graph_add_done (it);
  278. // Test union.
  279. gr_dest = VOLK_graph_new (store, NULL);
  280. EXPECT_PASS (VOLK_graph_bool_op (VOLK_BOOL_UNION, gr1, gr2, gr_dest));
  281. for (size_t i = 0; i < 8; i++)
  282. ASSERT (VOLK_graph_contains (gr_dest, trp[i]), "Union test failed!");
  283. VOLK_graph_free (gr_dest);
  284. // Test subtraction.
  285. gr_dest = VOLK_graph_new (store, NULL);
  286. EXPECT_PASS (VOLK_graph_bool_op (
  287. VOLK_BOOL_SUBTRACTION, gr1, gr2, gr_dest));
  288. for (size_t i = 0; i < 3; i++)
  289. ASSERT (VOLK_graph_contains (
  290. gr_dest, trp[i]), "Subtraction test is missing triples!");
  291. for (size_t i = 3; i < 8; i++)
  292. ASSERT (!VOLK_graph_contains (
  293. gr_dest, trp[i]), "Subtraction test has excess triples!");
  294. VOLK_graph_free (gr_dest);
  295. gr_dest = VOLK_graph_new (store, NULL);
  296. EXPECT_PASS (VOLK_graph_bool_op (
  297. VOLK_BOOL_SUBTRACTION, gr2, gr1, gr_dest));
  298. for (size_t i = 0; i < 4; i++)
  299. ASSERT (!VOLK_graph_contains (
  300. gr_dest, trp[i]), "Subtraction test is missing triples!");
  301. for (size_t i = 4; i < 8; i++)
  302. ASSERT (VOLK_graph_contains (
  303. gr_dest, trp[i]), "Subtraction test has excess triples!");
  304. VOLK_graph_free (gr_dest);
  305. // Test intersection.
  306. gr_dest = VOLK_graph_new (store, NULL);
  307. EXPECT_PASS (VOLK_graph_bool_op (
  308. VOLK_BOOL_INTERSECTION, gr1, gr2, gr_dest));
  309. for (size_t i = 0; i < 3; i++)
  310. ASSERT (!VOLK_graph_contains (
  311. gr_dest, trp[i]), "Intersection is missing triples!");
  312. ASSERT (VOLK_graph_contains (
  313. gr_dest, trp[3]), "Intersection test failed!");
  314. for (size_t i = 4; i < 8; i++)
  315. ASSERT (!VOLK_graph_contains (
  316. gr_dest, trp[i]), "Intersection test has excess triples!");
  317. VOLK_graph_free (gr_dest);
  318. // Test XOR.
  319. gr_dest = VOLK_graph_new (store, NULL);
  320. EXPECT_PASS (VOLK_graph_bool_op (VOLK_BOOL_XOR, gr1, gr2, gr_dest));
  321. for (size_t i = 0; i < 3; i++)
  322. ASSERT (VOLK_graph_contains (
  323. gr_dest, trp[i]), "XOR test is missing triples!");
  324. ASSERT (!VOLK_graph_contains (
  325. gr_dest, trp[3]), "XOR test has excess triples!");
  326. for (size_t i = 4; i < 8; i++)
  327. ASSERT (VOLK_graph_contains (
  328. gr_dest, trp[i]), "XOR test is missing triples!");
  329. VOLK_graph_free (gr_dest);
  330. // Test union with result graph as one of the sources.
  331. EXPECT_PASS (VOLK_graph_bool_op (VOLK_BOOL_UNION, gr1, gr2, gr1));
  332. for (size_t i = 0; i < 8; i++)
  333. ASSERT (VOLK_graph_contains (gr1, trp[i]), "Self-union test failed!");
  334. VOLK_graph_free (gr1);
  335. VOLK_graph_free (gr2);
  336. free_triples (trp);
  337. VOLK_store_free (store);
  338. return 0;
  339. }
  340. static int
  341. _graph_lookup (VOLK_StoreType type)
  342. {
  343. VOLK_Triple **trp = create_triples();
  344. // Lookup triples.
  345. VOLK_Term *lu_trp[N_LUT][3] = {
  346. {NULL, NULL, NULL}, // 8 matches
  347. {trp[0]->s, NULL, NULL}, // 5 matches
  348. {NULL, trp[2]->p, NULL}, // 3 matches
  349. {NULL, NULL, trp[5]->o}, // 2 matches
  350. {trp[0]->s, trp[0]->p, NULL}, // 1 match
  351. {NULL, trp[0]->p, trp[0]->o}, // 1 match
  352. {trp[0]->s, trp[2]->p, trp[5]->o}, // 1 match
  353. {trp[0]->p, NULL, NULL}, // 0 matches
  354. {NULL, trp[2]->s, NULL}, // 0 matches
  355. {NULL, NULL, trp[5]->p}, // 0 matches
  356. {trp[2]->s, trp[6]->p, NULL}, // 0 matches
  357. {NULL, trp[1]->p, trp[5]->o}, // 0 matches
  358. {trp[2]->s, trp[2]->p, trp[5]->o}, // 0 matches
  359. };
  360. // Lookup result counts.
  361. size_t lu_ct[N_LUT] = {
  362. 8,
  363. 5, 3, 2,
  364. 1, 1, 1,
  365. 0, 0, 0,
  366. 0, 0, 0
  367. };
  368. /* TODO
  369. // Index of lookup matches from trp.
  370. size_t lu_match[N_LUT][8] = {
  371. {0, 1, 2, 3, 4, 5, 6, 7},
  372. {0, 3, 4, 5, 7}, {2, 4, 7}, {5, 7},
  373. {0}, {0}, {7},
  374. {}, {}, {},
  375. {}, {}, {},
  376. };
  377. // Index of lookup non-matches from trp.
  378. size_t lu_no_match[N_LUT][8] = {
  379. {},
  380. {1, 2, 6}, {0, 1, 3, 5, 6}, {0, 1, 2, 3, 4, 6},
  381. {1, 2, 3, 4, 5, 6, 7}, {1, 2, 3, 4, 5, 6, 7}, {0, 1, 2, 3, 4, 5, 6},
  382. {0, 1, 2, 3, 4, 5, 6, 7}, {0, 1, 2, 3, 4, 5, 6, 7}, {0, 1, 2, 3, 4, 5, 6, 7},
  383. {0, 1, 2, 3, 4, 5, 6, 7}, {0, 1, 2, 3, 4, 5, 6, 7}, {0, 1, 2, 3, 4, 5, 6, 7},
  384. };
  385. */
  386. VOLK_Graph *gr;
  387. VOLK_Store *store = NULL;
  388. if (type == VOLK_STORE_HTABLE) {
  389. gr = VOLK_graph_new (NULL, NULL);
  390. } else {
  391. store = VOLK_store_new (type, NULL, 0, true);
  392. gr = VOLK_graph_new (store, NULL);
  393. }
  394. size_t ct;
  395. VOLK_graph_add (gr, trp, &ct);
  396. EXPECT_INT_EQ (ct, 8);
  397. EXPECT_INT_EQ (VOLK_graph_size (gr), 8);
  398. for (int i = 0; i < N_LUT; i++) {
  399. log_info ("Checking triple #%d on %d.", i, type);
  400. VOLK_GraphIterator *it = VOLK_graph_lookup (
  401. gr, lu_trp[i][0], lu_trp[i][1], lu_trp[i][2], &ct);
  402. EXPECT_INT_EQ (ct, lu_ct[i]);
  403. // Verify that iteration count matches stat count.
  404. VOLK_Triple *spo = NULL;
  405. ct = 0;
  406. while (VOLK_graph_iter_next (it, &spo) != VOLK_END) {
  407. ct++;
  408. // TODO do something useful with the triple.
  409. VOLK_triple_free (spo);
  410. spo = NULL;
  411. }
  412. VOLK_triple_free (spo);
  413. EXPECT_INT_EQ (ct, lu_ct[i]);
  414. /* TODO
  415. for (int j = 0; j < 8; j++) {
  416. for (int k = 0; VOLK_graph_iter_next(it) != VOLK_END; k++) {
  417. ASSERT (
  418. VOLK_graph_contains (trp[lu_match[j]]),
  419. "Triple not found!");
  420. ASSERT (
  421. !(VOLK_graph_contains (trp[lu_no_match[j]])),
  422. "Unexpected triple found!");
  423. }
  424. }
  425. */
  426. VOLK_graph_iter_free (it);
  427. };
  428. #if 0
  429. // Enable to test print functionality and exit early.
  430. VOLK_graph_print (gr);
  431. return 1;
  432. #endif
  433. free_triples (trp);
  434. VOLK_graph_free (gr);
  435. VOLK_store_free (store);
  436. return 0;
  437. }
  438. static int
  439. _graph_remove (VOLK_StoreType type)
  440. {
  441. VOLK_Triple **trp = create_triples();
  442. VOLK_Graph *gr;
  443. VOLK_Store *store = NULL;
  444. if (type == VOLK_STORE_HTABLE) {
  445. gr = VOLK_graph_new (NULL, NULL);
  446. } else {
  447. store = VOLK_store_new (type, NULL, 0, true);
  448. gr = VOLK_graph_new (store, NULL);
  449. }
  450. size_t ct;
  451. VOLK_graph_add (gr, trp, &ct);
  452. EXPECT_INT_EQ (ct, 8);
  453. EXPECT_INT_EQ (VOLK_graph_size (gr), 8);
  454. // Triples 0, 3, 4, 5, 7 will be removed.
  455. VOLK_graph_remove (gr, trp[0]->s, NULL, NULL, &ct);
  456. EXPECT_INT_EQ (ct, 5);
  457. EXPECT_INT_EQ (VOLK_graph_size (gr), 3);
  458. ASSERT (!VOLK_graph_contains (gr, trp[0]), "Unexpected triple found!");
  459. ASSERT (VOLK_graph_contains (gr, trp[1]), "Triple not in graph!");
  460. ASSERT (VOLK_graph_contains (gr, trp[2]), "Triple not in graph!");
  461. ASSERT (!VOLK_graph_contains (gr, trp[3]), "Unexpected triple found!");
  462. ASSERT (!VOLK_graph_contains (gr, trp[4]), "Unexpected triple found!");
  463. ASSERT (!VOLK_graph_contains (gr, trp[5]), "Unexpected triple found!");
  464. ASSERT (VOLK_graph_contains (gr, trp[6]), "Triple not in graph!");
  465. ASSERT (!VOLK_graph_contains (gr, trp[7]), "Unexpected triple found!");
  466. free_triples (trp); // gr copied data.
  467. VOLK_graph_free (gr);
  468. VOLK_store_free (store);
  469. // TODO Test complete removal of triples from index when they are not
  470. // in another context.
  471. return 0;
  472. }
  473. static int
  474. _graph_txn (VOLK_StoreType type)
  475. {
  476. const VOLK_StoreInt *sif = VOLK_store_int (type);
  477. if (!(sif->features & VOLK_STORE_TXN)) return 0;
  478. VOLK_Triple **trp = create_triples();
  479. VOLK_Graph *gr;
  480. VOLK_Store *store =
  481. type == VOLK_STORE_HTABLE ? NULL
  482. : VOLK_store_new (type, NULL, 0, true);
  483. gr = VOLK_graph_new (store, NULL);
  484. void *txn;
  485. size_t ct;
  486. EXPECT_PASS (VOLK_store_begin (store, 0, &txn));
  487. EXPECT_PASS (VOLK_graph_add_txn (txn, gr, trp, &ct));
  488. VOLK_store_abort (store, txn);
  489. // NOTE that ct reports the count before the txn was aborted. This is
  490. // intentional.
  491. EXPECT_INT_EQ (ct, 8);
  492. EXPECT_INT_EQ (VOLK_graph_size (gr), 0);
  493. EXPECT_PASS (VOLK_store_begin (store, 0, &txn));
  494. EXPECT_PASS (VOLK_graph_add_txn (txn, gr, trp, &ct));
  495. VOLK_store_commit (store, txn);
  496. EXPECT_INT_EQ (ct, 8);
  497. EXPECT_INT_EQ (VOLK_graph_size (gr), 8);
  498. VOLK_graph_free (gr);
  499. VOLK_store_free (store);
  500. free_triples (trp); // gr copied data.
  501. return 0;
  502. }
  503. static int
  504. _graph_relative (VOLK_StoreType type)
  505. {
  506. VOLK_Term
  507. *s = VOLK_iriref_new ("http://onto.knowledgetx.com/gr1/s1"),
  508. *s2 = VOLK_iriref_new ("http://onto.knowledgetx.com/gr2/s1"),
  509. *p = VOLK_iriref_new ("http://onto.knowledgetx.com/vocab/p1"),
  510. *o = VOLK_iriref_new ("http://onto.knowledgetx.com/gr1/o1"),
  511. *o2 = VOLK_iriref_new ("http://onto.knowledgetx.com/gr2/o1"),
  512. *c = VOLK_iriref_new ("http://onto.knowledgetx.com/gr1/"),
  513. *rel_s = VOLK_iriref_new_rel (c, s),
  514. *rel_o = VOLK_iriref_new_rel (c, o);
  515. VOLK_Triple *spo[2] = {
  516. VOLK_triple_new (s, p, o),
  517. NULL
  518. };
  519. VOLK_Triple *rel_spo = VOLK_triple_new (rel_s, p, rel_o);
  520. VOLK_Store *store =
  521. type == VOLK_STORE_HTABLE ? NULL
  522. : VOLK_store_new (type, NULL, 0, true);
  523. VOLK_Graph *gr = VOLK_graph_new (store, c->data);
  524. size_t ct;
  525. VOLK_graph_add (gr, spo, &ct);
  526. // Both absolute and relative IRIs should be found.
  527. ASSERT (VOLK_graph_contains (gr, rel_spo), "Relative triple not found!");
  528. ASSERT (VOLK_graph_contains (gr, spo[0]), "Absolute triple not found!");
  529. // Change graph URI and verify that relative URIs are still found, and
  530. // that absolute URIs change with it.
  531. spo[0]->s = s2;
  532. VOLK_term_free (s);
  533. spo[0]->o = o2;
  534. VOLK_term_free (o);
  535. VOLK_graph_set_uri (gr, "http://onto.knowledgetx.com/gr2/");
  536. VOLK_term_free (c);
  537. ASSERT (VOLK_graph_contains (gr, rel_spo), "Relative triple not found!");
  538. ASSERT (VOLK_graph_contains (gr, spo[0]), "Absolute triple not found!");
  539. VOLK_triple_free (spo[0]);
  540. VOLK_term_free (rel_s);
  541. VOLK_term_free (rel_o);
  542. free (rel_spo);
  543. VOLK_graph_free (gr);
  544. VOLK_store_free (store);
  545. return 0;
  546. }
  547. static int
  548. _graph_list (VOLK_StoreType type)
  549. {
  550. const VOLK_StoreInt *sif = VOLK_store_int (type);
  551. if (!(sif->features & VOLK_STORE_CTX)) return 0;
  552. VOLK_Store *store = VOLK_store_new (type, NULL, 0, true);
  553. VOLK_Graph *gg[3] = {
  554. VOLK_graph_new (store, "urn:gr:1"),
  555. VOLK_graph_new (store, "urn:gr:2"),
  556. VOLK_graph_new (store, "urn:gr:3"),
  557. };
  558. VOLK_Triple **trp = create_triples();
  559. VOLK_graph_add (gg[0], trp, NULL); // Add some triples to the 1st graph.
  560. VOLK_graph_add (gg[1], trp + 4, NULL); // Same with the 2nd graph.
  561. free_triples (trp);
  562. VOLK_TermSet *ts = VOLK_graph_list (store);
  563. ASSERT (ts != NULL, "Error creating context list!");
  564. EXPECT_INT_EQ (hashmap_count (ts), 2);
  565. // Check if first 2 graphs (with triples) are in the context set.
  566. VOLK_Hash key;
  567. key = VOLK_term_hash (VOLK_graph_uri (gg[0]));
  568. ASSERT (VOLK_term_set_get (ts, key) != NULL, "Context #1 not found!");
  569. key = VOLK_term_hash (VOLK_graph_uri (gg[1]));
  570. ASSERT (VOLK_term_set_get (ts, key) != NULL, "Context #2 not found!");
  571. key = VOLK_term_hash (VOLK_graph_uri (gg[2]));
  572. ASSERT (
  573. VOLK_term_set_get (ts, key) == NULL,
  574. "Empty context shoud not be here!");
  575. for (size_t i = 0; i < 3; i++) VOLK_graph_free (gg[i]);
  576. VOLK_term_set_free (ts);
  577. VOLK_store_free (store);
  578. return 0;
  579. }
  580. static int
  581. test_environment()
  582. {
  583. // The env should already be initialized and re-initializing it is idempotent.
  584. EXPECT_INT_EQ (VOLK_IS_INIT, true);
  585. ASSERT (VOLK_init() > 0, "Error initializing environment!");
  586. EXPECT_INT_EQ (VOLK_IS_INIT, true);
  587. // Tearing down is idempotent too.
  588. VOLK_done();
  589. EXPECT_INT_EQ (VOLK_IS_INIT, false);
  590. VOLK_done();
  591. EXPECT_INT_EQ (VOLK_IS_INIT, false);
  592. ASSERT (VOLK_init() >= 0, "Environment not initialized!");
  593. EXPECT_INT_EQ (VOLK_IS_INIT, true);
  594. ASSERT (VOLK_init() >= 0, "Environment not initialized!");
  595. EXPECT_INT_EQ (VOLK_IS_INIT, true);
  596. return 0;
  597. }
  598. static int test_graph_new() {
  599. #define ENTRY(a, b) \
  600. if (_graph_new (VOLK_STORE_##a) != 0) return -1;
  601. BACKEND_TBL
  602. #undef ENTRY
  603. return 0;
  604. }
  605. static int test_graph_ns_uri() {
  606. #define ENTRY(a, b) \
  607. if (_graph_ns_uri (VOLK_STORE_##a) != 0) return -1;
  608. BACKEND_TBL
  609. #undef ENTRY
  610. return 0;
  611. }
  612. static int test_graph_add() {
  613. #define ENTRY(a, b) \
  614. if (_graph_add (VOLK_STORE_##a) != 0) return -1;
  615. BACKEND_TBL
  616. #undef ENTRY
  617. return 0;
  618. }
  619. static int test_graph_get() {
  620. #define ENTRY(a, b) \
  621. if (_graph_get (VOLK_STORE_##a) != 0) return -1;
  622. BACKEND_TBL
  623. #undef ENTRY
  624. return 0;
  625. }
  626. static int test_graph_link_map() {
  627. #define ENTRY(a, b) \
  628. if (_graph_link_map (VOLK_STORE_##a) != 0) return -1;
  629. BACKEND_TBL
  630. #undef ENTRY
  631. return 0;
  632. }
  633. static int test_graph_bool_ops() {
  634. #define ENTRY(a, b) \
  635. if (_graph_bool_ops (VOLK_STORE_##a) != 0) return -1;
  636. BACKEND_TBL
  637. #undef ENTRY
  638. return 0;
  639. }
  640. static int test_graph_lookup() {
  641. #define ENTRY(a, b) \
  642. if (_graph_lookup (VOLK_STORE_##a) != 0) return -1;
  643. BACKEND_TBL
  644. #undef ENTRY
  645. return 0;
  646. }
  647. static int test_graph_remove() {
  648. #define ENTRY(a, b) \
  649. if (_graph_remove (VOLK_STORE_##a) != 0) return -1;
  650. BACKEND_TBL
  651. #undef ENTRY
  652. return 0;
  653. }
  654. static int test_graph_txn()
  655. {
  656. /*
  657. * Test transactions only if the backend supports them.
  658. */
  659. #define ENTRY(a, b) \
  660. if (_graph_txn (VOLK_STORE_##a) != 0) return -1;
  661. BACKEND_TBL
  662. #undef ENTRY
  663. return 0;
  664. }
  665. static int test_graph_relative()
  666. {
  667. /*
  668. * Test relative URIs in graphs.
  669. */
  670. #define ENTRY(a, b) \
  671. if (_graph_relative (VOLK_STORE_##a) != 0) return -1;
  672. BACKEND_TBL
  673. #undef ENTRY
  674. return 0;
  675. }
  676. static int test_graph_list()
  677. {
  678. /*
  679. * Test relative URIs in graphs.
  680. */
  681. #define ENTRY(a, b) \
  682. if (_graph_list (VOLK_STORE_##a) != 0) return -1;
  683. BACKEND_TBL
  684. #undef ENTRY
  685. return 0;
  686. }
  687. static int test_graph_copy()
  688. {
  689. VOLK_Triple **trp = create_triples();
  690. VOLK_Graph *gr1 = VOLK_graph_new (NULL, NULL);
  691. ASSERT (gr1 != NULL, "Error creating graph!");
  692. VOLK_graph_add (gr1, trp, NULL);
  693. // Copy to graph with same store type.
  694. VOLK_Graph *gr2 = VOLK_graph_new (NULL, NULL);
  695. EXPECT_PASS (VOLK_graph_copy_contents (gr1, gr2, NULL, NULL, NULL));
  696. EXPECT_INT_EQ (VOLK_graph_size (gr1), VOLK_graph_size (gr2));
  697. for (unsigned int i = 0; i < sizeof (trp); i++) {
  698. log_info ("checking triple #%d.", i);
  699. ASSERT (
  700. VOLK_graph_contains (gr2, trp[i]),
  701. "Triple not in copied graph!");
  702. }
  703. // Copy to graph with a different store type.
  704. VOLK_Graph *gr3 = VOLK_graph_new (NULL, NULL);
  705. EXPECT_PASS (VOLK_graph_copy_contents (gr1, gr3, NULL, NULL, NULL));
  706. EXPECT_INT_EQ (VOLK_graph_size (gr1), VOLK_graph_size (gr2));
  707. for (unsigned int i = 0; i < sizeof (trp); i++) {
  708. log_info ("checking triple #%d.", i);
  709. ASSERT (
  710. VOLK_graph_contains (gr3, trp[i]),
  711. "Triple not in copied graph!");
  712. }
  713. VOLK_graph_free (gr3);
  714. VOLK_graph_free (gr2);
  715. VOLK_graph_free (gr1);
  716. free_triples (trp);
  717. return 0;
  718. }
  719. int graph_tests()
  720. {
  721. RUN (test_environment);
  722. RUN (test_graph_new);
  723. RUN (test_graph_ns_uri);
  724. RUN (test_graph_add);
  725. RUN (test_graph_get);
  726. RUN (test_graph_link_map);
  727. RUN (test_graph_bool_ops);
  728. RUN (test_graph_lookup);
  729. RUN (test_graph_remove);
  730. RUN (test_graph_copy);
  731. RUN (test_graph_txn);
  732. RUN (test_graph_relative);
  733. RUN (test_graph_list);
  734. return 0;
  735. }