test_graph.c 26 KB

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