test_graph.c 25 KB

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