test_graph.c 26 KB

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