#include "volksdata/graph.h" #include "test.h" #include "assets/triples.h" #define N_LUT 13 static int _graph_new (VOLK_StoreType type) { VOLK_Graph *gr; VOLK_Store *store = NULL; if (type == VOLK_STORE_HTABLE) { gr = VOLK_graph_new (NULL, NULL); } else { store = VOLK_store_new (type, NULL, 0, true); gr = VOLK_graph_new (store, NULL); } ASSERT (gr != NULL, "Error creating graph!"); EXPECT_PASS (VOLK_graph_set_uri (gr, "urn:gr:1")); EXPECT_STR_EQ (VOLK_graph_uri (gr)->data, "urn:gr:1"); ASSERT ( strcmp (VOLK_graph_uri (gr)->data, "urn:gr:1") == 0, "Graph URI mismatch!"); EXPECT_INT_EQ (VOLK_graph_size (gr), 0); // Check that setup function is idempotent with clear == false. const VOLK_StoreInt *sif = VOLK_store_int (type); if (sif->setup_fn) EXPECT_INT_EQ ( sif->setup_fn (NULL, false), VOLK_NOACTION); VOLK_graph_free (gr); VOLK_store_free (store); return 0; } /// Test creating a graph with a namespaced URI. static int _graph_ns_uri (VOLK_StoreType type) { const VOLK_StoreInt *sif = VOLK_store_int (type); const char *nsdata[][2] = { {"ns1", "urn:ns1#"}, {"ns2", "urn:ns2#"}, {"ns3", "urn:ns3#"}, {NULL} }; VOLK_Store *store = NULL; if (sif->features & VOLK_STORE_PERM) store = VOLK_store_new (type, NULL, 0, true); log_info("Testing NSM for graph store type: %d", type); for (int i = 0; nsdata[i][0]; i++) EXPECT_PASS (VOLK_nsmap_add (nsdata[i][0], nsdata[i][1])); VOLK_Graph *gr; gr = VOLK_graph_new_ns (store, NULL); ASSERT (gr == NULL, "NS graph URI cannot be NULL!"); gr = VOLK_graph_new_ns (store, "ns1:gr1"); ASSERT (gr != NULL, "Error creating graph!"); VOLK_Term *comp = VOLK_iriref_new ("urn:ns1#gr1"); ASSERT ( VOLK_term_equals (VOLK_graph_uri (gr), comp), "Namespaced graph URI is incorrect!" ); VOLK_term_free (comp); VOLK_graph_free (gr); VOLK_store_free (store); return 0; } static int _graph_add (VOLK_StoreType type) { VOLK_Triple **trp = create_triples(); VOLK_Graph *gr; VOLK_Store *store; if (type == VOLK_STORE_HTABLE) store = NULL; else store = VOLK_store_new (type, NULL, 0, true); gr = VOLK_graph_new (store, NULL); ASSERT (gr != NULL, "Error creating graph!"); size_t ct; VOLK_graph_add (gr, trp, &ct); EXPECT_INT_EQ (ct, 8); EXPECT_INT_EQ (VOLK_graph_size (gr), 8); for (int i = 0; i < sizeof (trp); i++) { log_info ("checking triple #%d.", i); ASSERT (VOLK_graph_contains (gr, trp[i]), "Triple not in graph!"); } VOLK_Triple *missing_trp = VOLK_triple_new ( trp[1]->s, trp[6]->p, trp[4]->o); ASSERT (! VOLK_graph_contains (gr, missing_trp), "Triple in graph!"); free (missing_trp); free_triples (trp); // gr copied data. // Check size again after freeing triples. EXPECT_INT_EQ (VOLK_graph_size (gr), 8); VOLK_Graph *gr2 = VOLK_graph_new (NULL, NULL); // Test equality against empty graph. ASSERT (!VOLK_graph_equals (gr, gr2), "Graphs should not be equal!"); ASSERT (!VOLK_graph_equals (gr2, gr), "Graphs should not be equal!"); VOLK_graph_free (gr); VOLK_graph_free (gr2); VOLK_store_free (store); return 0; } static int _graph_get (VOLK_StoreType type) { const VOLK_StoreInt *sif = VOLK_store_int (type); // Skip if the store doesn't support contexts. if (!(sif->features & VOLK_STORE_CTX)) return 0; VOLK_Triple **trp = create_triples(); VOLK_Store *store; if (type == VOLK_STORE_HTABLE) store = NULL; else store = VOLK_store_new (type, NULL, 0, true); VOLK_Graph *gr1 = VOLK_graph_new (store, NULL), *gr2 = VOLK_graph_new (store, NULL); ASSERT (gr1 != NULL, "Error creating graph!"); ASSERT (gr2 != NULL, "Error creating graph!"); // Add 2 groups of triples to different graphs. void *it1 = VOLK_graph_add_init (gr1); for (size_t i = 0; i < 5; i++) { VOLK_graph_add_iter(it1, trp[i]); } VOLK_graph_add_done (it1); void *it2 = VOLK_graph_add_init (gr2); for (size_t i = 5; i < NUM_TRP; i++) { VOLK_graph_add_iter(it2, trp[i]); } VOLK_graph_add_done (it2); free_triples (trp); EXPECT_INT_EQ (VOLK_graph_size (gr1), 5); EXPECT_INT_EQ (VOLK_graph_size (gr2), 3); size_t ct3, ct4; VOLK_Graph *gr3 = VOLK_graph_get (store, VOLK_graph_uri (gr1), &ct3), *gr4 = VOLK_graph_get (store, VOLK_graph_uri (gr2), &ct4); EXPECT_INT_EQ (VOLK_graph_size (gr3), VOLK_graph_size (gr1)); EXPECT_INT_EQ (VOLK_graph_size (gr3), ct3); EXPECT_INT_EQ (VOLK_graph_size (gr4), VOLK_graph_size (gr2)); EXPECT_INT_EQ (VOLK_graph_size (gr4), ct4); ASSERT (!VOLK_graph_equals (gr1, gr2), "Graphs 1 and 2 are equal!"); ASSERT (!VOLK_graph_equals (gr3, gr4), "Graphs 3 and 4 are equal!"); ASSERT (VOLK_graph_equals (gr1, gr3), "Graphs 1 and 3 are not equal!"); ASSERT (VOLK_graph_equals (gr2, gr4), "Graphs 2 and 4 are not equal!"); VOLK_graph_free (gr1); VOLK_graph_free (gr2); VOLK_graph_free (gr3); VOLK_graph_free (gr4); VOLK_store_free (store); return 0; } static int _graph_link_map (VOLK_StoreType type) { VOLK_Triple **trp = create_triples(); VOLK_Store *store; if (type == VOLK_STORE_HTABLE) store = NULL; else store = VOLK_store_new (type, NULL, 0, true); VOLK_Graph *gr = VOLK_graph_new (store, NULL); size_t ct; VOLK_graph_add (gr, trp, &ct); VOLK_LinkMap *lmap; VOLK_LinkMapIterator *lmit ; //VOLK_Term *k = NULL; VOLK_TermSet *ts = NULL; // Term set being iterated in link map loop. VOLK_Term *k_res[9] = {NULL}; // Collected keys. VOLK_Term *ts_res[9] = {NULL}; // Collected terms in term set in loop. size_t i = 0, j = 0; /* VOLK_Term *po[6][4] = { {trp[0]->p, trp[0]->o, NULL}, {trp[3]->p, trp[3]->o, NULL}, {trp[4]->p, trp[4]->o, trp[7]->o, NULL}, {trp[5]->p, trp[5]->o, NULL}, {NULL} }; */ // terms connected to subject, urn:s:0 lmap = VOLK_graph_connections (gr, trp[0]->s, VOLK_LINK_OUTBOUND); lmit = VOLK_link_map_iter_new (lmap); while (VOLK_link_map_next (lmit, k_res + i, &ts) == VOLK_OK) { while (VOLK_term_set_next (ts, &j, ts_res + j) == VOLK_OK); /* // TODO test exact terms. This requires a cross-check. ASSERT ( VOLK_term_equals (k_res[i], po[i][0]), "Wrong term in link map!"); for (size_t k = 1; po[i][k]; k++) ASSERT ( VOLK_term_equals (ts_res[k - 1], po[i][k]), "Wrong term in term set!"); */ i++; } VOLK_link_map_iter_free (lmit); VOLK_link_map_free (lmap); EXPECT_INT_EQ (i, 4); i = 0; j = 0; memset (k_res, 0, sizeof (k_res)); memset (ts_res, 0, sizeof (ts_res)); /* VOLK_Term *so[3][3] = { {trp[1]->s, trp[1]->o, NULL}, {trp[3]->s, trp[3]->o, NULL}, }; */ // terms connected to predicate, urn:p:1 lmap = VOLK_graph_connections (gr, trp[1]->p, VOLK_LINK_EDGE); lmit = VOLK_link_map_iter_new (lmap); while (VOLK_link_map_next (lmit, k_res + i, &ts) == VOLK_OK) { while (VOLK_term_set_next (ts, &j, ts_res + j) == VOLK_OK); /* ASSERT ( VOLK_term_equals (k_res[i], so[i][0]), "Wrong term in link map!"); for (size_t k = 1; so[i][k]; k++) ASSERT ( VOLK_term_equals (ts_res[k - 1], so[i][k]), "Wrong term in term set!"); */ i++; } VOLK_link_map_iter_free (lmit); VOLK_link_map_free (lmap); EXPECT_INT_EQ (i, 2); i = 0; j = 0; memset (k_res, 0, sizeof (k_res)); memset (ts_res, 0, sizeof (ts_res)); /* VOLK_Term *sp[1][3] = { {trp[6]->s, trp[6]->p, NULL}, }; */ // terms connected to object, "String 1"@es-ES lmap = VOLK_graph_connections (gr, trp[6]->o, VOLK_LINK_INBOUND); lmit = VOLK_link_map_iter_new (lmap); while (VOLK_link_map_next (lmit, k_res + i, &ts) == VOLK_OK) { while (VOLK_term_set_next (ts, &j, ts_res + j) == VOLK_OK); /* ASSERT ( VOLK_term_equals (k_res[i], sp[i][0]), "Wrong term in link map!"); for (size_t k = 1; sp[i][k]; k++) ASSERT ( VOLK_term_equals (ts_res[k - 1], sp[i][k]), "Wrong term in term set!"); */ i++; } VOLK_link_map_iter_free (lmit); VOLK_link_map_free (lmap); EXPECT_INT_EQ (i, 1); free_triples (trp); VOLK_graph_free (gr); VOLK_store_free (store); return 0; } static int _graph_bool_ops (VOLK_StoreType type) { const VOLK_StoreInt *sif = VOLK_store_int (type); // Skip if the store doesn't support contexts. if (!(sif->features & VOLK_STORE_CTX)) return 0; VOLK_Triple **trp = create_triples(); VOLK_Store *store; if (type == VOLK_STORE_HTABLE) store = NULL; else store = VOLK_store_new (type, NULL, 0, true); VOLK_Graph *gr1 = VOLK_graph_new (store, NULL), *gr2 = VOLK_graph_new (store, NULL), *gr_dest; // Add 2 groups of triples to different graphs. void *it; it = VOLK_graph_add_init (gr1); for (size_t i = 0; i < 4; i++) { VOLK_graph_add_iter(it, trp[i]); } VOLK_graph_add_done (it); // Skip duplicate triples, we already tested those. // trp[3] is in both graphs. it = VOLK_graph_add_init (gr2); for (size_t i = 3; i < 8; i++) { VOLK_graph_add_iter(it, trp[i]); } VOLK_graph_add_done (it); // Test union. gr_dest = VOLK_graph_new (store, NULL); EXPECT_PASS (VOLK_graph_bool_op (VOLK_BOOL_UNION, gr1, gr2, gr_dest)); for (size_t i = 0; i < 8; i++) ASSERT (VOLK_graph_contains (gr_dest, trp[i]), "Union test failed!"); VOLK_graph_free (gr_dest); // Test subtraction. gr_dest = VOLK_graph_new (store, NULL); EXPECT_PASS (VOLK_graph_bool_op ( VOLK_BOOL_SUBTRACTION, gr1, gr2, gr_dest)); for (size_t i = 0; i < 3; i++) ASSERT (VOLK_graph_contains ( gr_dest, trp[i]), "Subtraction test is missing triples!"); for (size_t i = 3; i < 8; i++) ASSERT (!VOLK_graph_contains ( gr_dest, trp[i]), "Subtraction test has excess triples!"); VOLK_graph_free (gr_dest); gr_dest = VOLK_graph_new (store, NULL); EXPECT_PASS (VOLK_graph_bool_op ( VOLK_BOOL_SUBTRACTION, gr2, gr1, gr_dest)); for (size_t i = 0; i < 4; i++) ASSERT (!VOLK_graph_contains ( gr_dest, trp[i]), "Subtraction test is missing triples!"); for (size_t i = 4; i < 8; i++) ASSERT (VOLK_graph_contains ( gr_dest, trp[i]), "Subtraction test has excess triples!"); VOLK_graph_free (gr_dest); // Test intersection. gr_dest = VOLK_graph_new (store, NULL); EXPECT_PASS (VOLK_graph_bool_op ( VOLK_BOOL_INTERSECTION, gr1, gr2, gr_dest)); for (size_t i = 0; i < 3; i++) ASSERT (!VOLK_graph_contains ( gr_dest, trp[i]), "Intersection is missing triples!"); ASSERT (VOLK_graph_contains ( gr_dest, trp[3]), "Intersection test failed!"); for (size_t i = 4; i < 8; i++) ASSERT (!VOLK_graph_contains ( gr_dest, trp[i]), "Intersection test has excess triples!"); VOLK_graph_free (gr_dest); // Test XOR. gr_dest = VOLK_graph_new (store, NULL); EXPECT_PASS (VOLK_graph_bool_op (VOLK_BOOL_XOR, gr1, gr2, gr_dest)); for (size_t i = 0; i < 3; i++) ASSERT (VOLK_graph_contains ( gr_dest, trp[i]), "XOR test is missing triples!"); ASSERT (!VOLK_graph_contains ( gr_dest, trp[3]), "XOR test has excess triples!"); for (size_t i = 4; i < 8; i++) ASSERT (VOLK_graph_contains ( gr_dest, trp[i]), "XOR test is missing triples!"); VOLK_graph_free (gr_dest); // Test union with result graph as one of the sources. EXPECT_PASS (VOLK_graph_bool_op (VOLK_BOOL_UNION, gr1, gr2, gr1)); for (size_t i = 0; i < 8; i++) ASSERT (VOLK_graph_contains (gr1, trp[i]), "Self-union test failed!"); VOLK_graph_free (gr1); VOLK_graph_free (gr2); free_triples (trp); VOLK_store_free (store); return 0; } static int _graph_lookup (VOLK_StoreType type) { VOLK_Triple **trp = create_triples(); // Lookup triples. VOLK_Term *lu_trp[N_LUT][3] = { {NULL, NULL, NULL}, // 8 matches {trp[0]->s, NULL, NULL}, // 5 matches {NULL, trp[2]->p, NULL}, // 3 matches {NULL, NULL, trp[5]->o}, // 2 matches {trp[0]->s, trp[0]->p, NULL}, // 1 match {NULL, trp[0]->p, trp[0]->o}, // 1 match {trp[0]->s, trp[2]->p, trp[5]->o}, // 1 match {trp[0]->p, NULL, NULL}, // 0 matches {NULL, trp[2]->s, NULL}, // 0 matches {NULL, NULL, trp[5]->p}, // 0 matches {trp[2]->s, trp[6]->p, NULL}, // 0 matches {NULL, trp[1]->p, trp[5]->o}, // 0 matches {trp[2]->s, trp[2]->p, trp[5]->o}, // 0 matches }; // Lookup result counts. size_t lu_ct[N_LUT] = { 8, 5, 3, 2, 1, 1, 1, 0, 0, 0, 0, 0, 0 }; /* TODO // Index of lookup matches from trp. size_t lu_match[N_LUT][8] = { {0, 1, 2, 3, 4, 5, 6, 7}, {0, 3, 4, 5, 7}, {2, 4, 7}, {5, 7}, {0}, {0}, {7}, {}, {}, {}, {}, {}, {}, }; // Index of lookup non-matches from trp. size_t lu_no_match[N_LUT][8] = { {}, {1, 2, 6}, {0, 1, 3, 5, 6}, {0, 1, 2, 3, 4, 6}, {1, 2, 3, 4, 5, 6, 7}, {1, 2, 3, 4, 5, 6, 7}, {0, 1, 2, 3, 4, 5, 6}, {0, 1, 2, 3, 4, 5, 6, 7}, {0, 1, 2, 3, 4, 5, 6, 7}, {0, 1, 2, 3, 4, 5, 6, 7}, {0, 1, 2, 3, 4, 5, 6, 7}, {0, 1, 2, 3, 4, 5, 6, 7}, {0, 1, 2, 3, 4, 5, 6, 7}, }; */ VOLK_Graph *gr; VOLK_Store *store = NULL; if (type == VOLK_STORE_HTABLE) { gr = VOLK_graph_new (NULL, NULL); } else { store = VOLK_store_new (type, NULL, 0, true); gr = VOLK_graph_new (store, NULL); } size_t ct; VOLK_graph_add (gr, trp, &ct); EXPECT_INT_EQ (ct, 8); EXPECT_INT_EQ (VOLK_graph_size (gr), 8); for (int i = 0; i < N_LUT; i++) { log_info ("Checking triple #%d on %d.", i, type); VOLK_GraphIterator *it = VOLK_graph_lookup ( gr, lu_trp[i][0], lu_trp[i][1], lu_trp[i][2], &ct); EXPECT_INT_EQ (ct, lu_ct[i]); // Verify that iteration count matches stat count. VOLK_Triple *spo = NULL; ct = 0; while (VOLK_graph_iter_next (it, &spo) != VOLK_END) { ct++; // TODO do something useful with the triple. VOLK_triple_free (spo); spo = NULL; } VOLK_triple_free (spo); EXPECT_INT_EQ (ct, lu_ct[i]); /* TODO for (int j = 0; j < 8; j++) { for (int k = 0; VOLK_graph_iter_next(it) != VOLK_END; k++) { ASSERT ( VOLK_graph_contains (trp[lu_match[j]]), "Triple not found!"); ASSERT ( !(VOLK_graph_contains (trp[lu_no_match[j]])), "Unexpected triple found!"); } } */ VOLK_graph_iter_free (it); }; #if 0 // Enable to test print functionality and exit early. VOLK_graph_print (gr); return 1; #endif free_triples (trp); VOLK_graph_free (gr); VOLK_store_free (store); return 0; } static int _graph_remove (VOLK_StoreType type) { VOLK_Triple **trp = create_triples(); VOLK_Graph *gr; VOLK_Store *store = NULL; if (type == VOLK_STORE_HTABLE) { gr = VOLK_graph_new (NULL, NULL); } else { store = VOLK_store_new (type, NULL, 0, true); gr = VOLK_graph_new (store, NULL); } size_t ct; VOLK_graph_add (gr, trp, &ct); EXPECT_INT_EQ (ct, 8); EXPECT_INT_EQ (VOLK_graph_size (gr), 8); // Triples 0, 3, 4, 5, 7 will be removed. VOLK_graph_remove (gr, trp[0]->s, NULL, NULL, &ct); EXPECT_INT_EQ (ct, 5); EXPECT_INT_EQ (VOLK_graph_size (gr), 3); ASSERT (!VOLK_graph_contains (gr, trp[0]), "Unexpected triple found!"); ASSERT (VOLK_graph_contains (gr, trp[1]), "Triple not in graph!"); ASSERT (VOLK_graph_contains (gr, trp[2]), "Triple not in graph!"); ASSERT (!VOLK_graph_contains (gr, trp[3]), "Unexpected triple found!"); ASSERT (!VOLK_graph_contains (gr, trp[4]), "Unexpected triple found!"); ASSERT (!VOLK_graph_contains (gr, trp[5]), "Unexpected triple found!"); ASSERT (VOLK_graph_contains (gr, trp[6]), "Triple not in graph!"); ASSERT (!VOLK_graph_contains (gr, trp[7]), "Unexpected triple found!"); free_triples (trp); // gr copied data. VOLK_graph_free (gr); VOLK_store_free (store); // TODO Test complete removal of triples from index when they are not // in another context. return 0; } static int _graph_txn (VOLK_StoreType type) { const VOLK_StoreInt *sif = VOLK_store_int (type); if (!(sif->features & VOLK_STORE_TXN)) return 0; VOLK_Triple **trp = create_triples(); VOLK_Graph *gr; VOLK_Store *store = type == VOLK_STORE_HTABLE ? NULL : VOLK_store_new (type, NULL, 0, true); gr = VOLK_graph_new (store, NULL); void *txn; size_t ct; EXPECT_PASS (VOLK_store_begin (store, 0, &txn)); EXPECT_PASS (VOLK_graph_add_txn (txn, gr, trp, &ct)); VOLK_store_abort (store, txn); // NOTE that ct reports the count before the txn was aborted. This is // intentional. EXPECT_INT_EQ (ct, 8); EXPECT_INT_EQ (VOLK_graph_size (gr), 0); EXPECT_PASS (VOLK_store_begin (store, 0, &txn)); EXPECT_PASS (VOLK_graph_add_txn (txn, gr, trp, &ct)); VOLK_store_commit (store, txn); EXPECT_INT_EQ (ct, 8); EXPECT_INT_EQ (VOLK_graph_size (gr), 8); VOLK_graph_free (gr); VOLK_store_free (store); free_triples (trp); // gr copied data. return 0; } static int _graph_relative (VOLK_StoreType type) { VOLK_Term *s = VOLK_iriref_new ("http://onto.knowledgetx.com/gr1/s1"), *s2 = VOLK_iriref_new ("http://onto.knowledgetx.com/gr2/s1"), *p = VOLK_iriref_new ("http://onto.knowledgetx.com/vocab/p1"), *o = VOLK_iriref_new ("http://onto.knowledgetx.com/gr1/o1"), *o2 = VOLK_iriref_new ("http://onto.knowledgetx.com/gr2/o1"), *c = VOLK_iriref_new ("http://onto.knowledgetx.com/gr1/"), *rel_s = VOLK_iriref_new_rel (c, s), *rel_o = VOLK_iriref_new_rel (c, o); VOLK_Triple *spo[2] = { VOLK_triple_new (s, p, o), NULL }; VOLK_Triple *rel_spo = VOLK_triple_new (rel_s, p, rel_o); VOLK_Store *store = type == VOLK_STORE_HTABLE ? NULL : VOLK_store_new (type, NULL, 0, true); VOLK_Graph *gr = VOLK_graph_new (store, c->data); size_t ct; VOLK_graph_add (gr, spo, &ct); // Both absolute and relative IRIs should be found. ASSERT (VOLK_graph_contains (gr, rel_spo), "Relative triple not found!"); ASSERT (VOLK_graph_contains (gr, spo[0]), "Absolute triple not found!"); // Change graph URI and verify that relative URIs are still found, and // that absolute URIs change with it. spo[0]->s = s2; VOLK_term_free (s); spo[0]->o = o2; VOLK_term_free (o); VOLK_graph_set_uri (gr, "http://onto.knowledgetx.com/gr2/"); VOLK_term_free (c); ASSERT (VOLK_graph_contains (gr, rel_spo), "Relative triple not found!"); ASSERT (VOLK_graph_contains (gr, spo[0]), "Absolute triple not found!"); VOLK_triple_free (spo[0]); VOLK_term_free (rel_s); VOLK_term_free (rel_o); free (rel_spo); VOLK_graph_free (gr); VOLK_store_free (store); return 0; } static int _graph_list (VOLK_StoreType type) { const VOLK_StoreInt *sif = VOLK_store_int (type); if (!(sif->features & VOLK_STORE_CTX)) return 0; VOLK_Store *store = VOLK_store_new (type, NULL, 0, true); VOLK_Graph *gg[3] = { VOLK_graph_new (store, "urn:gr:1"), VOLK_graph_new (store, "urn:gr:2"), VOLK_graph_new (store, "urn:gr:3"), }; VOLK_Triple **trp = create_triples(); VOLK_graph_add (gg[0], trp, NULL); // Add some triples to the 1st graph. VOLK_graph_add (gg[1], trp + 4, NULL); // Same with the 2nd graph. free_triples (trp); VOLK_TermSet *ts = VOLK_graph_list (store); ASSERT (ts != NULL, "Error creating context list!"); EXPECT_INT_EQ (hashmap_count (ts), 2); // Check if first 2 graphs (with triples) are in the context set. VOLK_Hash key; key = VOLK_term_hash (VOLK_graph_uri (gg[0])); ASSERT (VOLK_term_set_get (ts, key) != NULL, "Context #1 not found!"); key = VOLK_term_hash (VOLK_graph_uri (gg[1])); ASSERT (VOLK_term_set_get (ts, key) != NULL, "Context #2 not found!"); key = VOLK_term_hash (VOLK_graph_uri (gg[2])); ASSERT ( VOLK_term_set_get (ts, key) == NULL, "Empty context shoud not be here!"); for (size_t i = 0; i < 3; i++) VOLK_graph_free (gg[i]); VOLK_term_set_free (ts); VOLK_store_free (store); return 0; } static int test_environment() { // The env should already be initialized and re-initializing it is idempotent. EXPECT_INT_EQ (VOLK_IS_INIT, true); ASSERT (VOLK_init() > 0, "Error initializing environment!"); EXPECT_INT_EQ (VOLK_IS_INIT, true); // Tearing down is idempotent too. VOLK_done(); EXPECT_INT_EQ (VOLK_IS_INIT, false); VOLK_done(); EXPECT_INT_EQ (VOLK_IS_INIT, false); ASSERT (VOLK_init() >= 0, "Environment not initialized!"); EXPECT_INT_EQ (VOLK_IS_INIT, true); ASSERT (VOLK_init() >= 0, "Environment not initialized!"); EXPECT_INT_EQ (VOLK_IS_INIT, true); return 0; } static int test_graph_new() { #define ENTRY(a, b) \ if (_graph_new (VOLK_STORE_##a) != 0) return -1; BACKEND_TBL #undef ENTRY return 0; } static int test_graph_ns_uri() { #define ENTRY(a, b) \ if (_graph_ns_uri (VOLK_STORE_##a) != 0) return -1; BACKEND_TBL #undef ENTRY return 0; } static int test_graph_add() { #define ENTRY(a, b) \ if (_graph_add (VOLK_STORE_##a) != 0) return -1; BACKEND_TBL #undef ENTRY return 0; } static int test_graph_get() { #define ENTRY(a, b) \ if (_graph_get (VOLK_STORE_##a) != 0) return -1; BACKEND_TBL #undef ENTRY return 0; } static int test_graph_link_map() { #define ENTRY(a, b) \ if (_graph_link_map (VOLK_STORE_##a) != 0) return -1; BACKEND_TBL #undef ENTRY return 0; } static int test_graph_bool_ops() { #define ENTRY(a, b) \ if (_graph_bool_ops (VOLK_STORE_##a) != 0) return -1; BACKEND_TBL #undef ENTRY return 0; } static int test_graph_lookup() { #define ENTRY(a, b) \ if (_graph_lookup (VOLK_STORE_##a) != 0) return -1; BACKEND_TBL #undef ENTRY return 0; } static int test_graph_remove() { #define ENTRY(a, b) \ if (_graph_remove (VOLK_STORE_##a) != 0) return -1; BACKEND_TBL #undef ENTRY return 0; } static int test_graph_txn() { /* * Test transactions only if the backend supports them. */ #define ENTRY(a, b) \ if (_graph_txn (VOLK_STORE_##a) != 0) return -1; BACKEND_TBL #undef ENTRY return 0; } static int test_graph_relative() { /* * Test relative URIs in graphs. */ #define ENTRY(a, b) \ if (_graph_relative (VOLK_STORE_##a) != 0) return -1; BACKEND_TBL #undef ENTRY return 0; } static int test_graph_list() { /* * Test relative URIs in graphs. */ #define ENTRY(a, b) \ if (_graph_list (VOLK_STORE_##a) != 0) return -1; BACKEND_TBL #undef ENTRY return 0; } static int test_graph_copy() { VOLK_Triple **trp = create_triples(); VOLK_Graph *gr1 = VOLK_graph_new (NULL, NULL); ASSERT (gr1 != NULL, "Error creating graph!"); VOLK_graph_add (gr1, trp, NULL); // Copy to graph with same store type. VOLK_Graph *gr2 = VOLK_graph_new (NULL, NULL); EXPECT_PASS (VOLK_graph_copy_contents (gr1, gr2, NULL, NULL, NULL)); EXPECT_INT_EQ (VOLK_graph_size (gr1), VOLK_graph_size (gr2)); for (int i = 0; i < sizeof (trp); i++) { log_info ("checking triple #%d.", i); ASSERT ( VOLK_graph_contains (gr2, trp[i]), "Triple not in copied graph!"); } // Copy to graph with a different store type. VOLK_Graph *gr3 = VOLK_graph_new (NULL, NULL); EXPECT_PASS (VOLK_graph_copy_contents (gr1, gr3, NULL, NULL, NULL)); EXPECT_INT_EQ (VOLK_graph_size (gr1), VOLK_graph_size (gr2)); for (int i = 0; i < sizeof (trp); i++) { log_info ("checking triple #%d.", i); ASSERT ( VOLK_graph_contains (gr3, trp[i]), "Triple not in copied graph!"); } VOLK_graph_free (gr3); VOLK_graph_free (gr2); VOLK_graph_free (gr1); free_triples (trp); return 0; } int graph_tests() { RUN (test_environment); RUN (test_graph_new); RUN (test_graph_ns_uri); RUN (test_graph_add); RUN (test_graph_get); RUN (test_graph_link_map); RUN (test_graph_bool_ops); RUN (test_graph_lookup); RUN (test_graph_remove); RUN (test_graph_copy); RUN (test_graph_txn); RUN (test_graph_relative); RUN (test_graph_list); return 0; }