test_graph.c 25 KB

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