From 3f4d613ed7556d8420e7edebe1530c75193be5d0 Mon Sep 17 00:00:00 2001 From: David Robillard Date: Sun, 4 Oct 2015 19:22:43 +0000 Subject: Improve test coverage git-svn-id: http://svn.drobilla.net/sord/trunk@335 3d64ff67-21c5-427c-a301-fe4f08042e5a --- src/sord.c | 28 +++++++++++++-------------- src/sord_internal.h | 6 ++++++ src/sord_test.c | 56 +++++++++++++++++++++++++++++++++++++++++++++++------ src/syntax.c | 22 ++++++++++----------- src/zix/hash.h | 2 +- 5 files changed, 81 insertions(+), 33 deletions(-) diff --git a/src/sord.c b/src/sord.c index ff89505..c6b2b38 100644 --- a/src/sord.c +++ b/src/sord.c @@ -83,11 +83,13 @@ typedef enum { GPOS, ///< Graph, Predicate, Object, Subject } SordOrder; +#ifdef SORD_DEBUG_SEARCH /** String name of each ordering (array indexed by SordOrder) */ static const char* const order_names[NUM_ORDERS] = { "spo", "sop", "ops", "osp", "pso", "pos", "gspo", "gsop", "gops", "gosp", "gpso", "gpos" }; +#endif /** Quads of indices for each order, from most to least significant @@ -321,19 +323,19 @@ sord_iter_forward(SordIter* iter) return zix_btree_iter_is_end(iter->cur); } - SordNode** key = (SordNode**)zix_btree_get(iter->cur); + SordNode** key = (SordNode**)zix_btree_get(iter->cur); const SordQuad initial = { key[0], key[1], key[2], key[3] }; - while (true) { - zix_btree_iter_increment(iter->cur); - if (zix_btree_iter_is_end(iter->cur)) - return true; - + zix_btree_iter_increment(iter->cur); + while (!zix_btree_iter_is_end(iter->cur)) { key = (SordNode**)zix_btree_get(iter->cur); for (int i = 0; i < 3; ++i) if (key[i] != initial[i]) return false; + + zix_btree_iter_increment(iter->cur); } - assert(false); + + return true; } /** @@ -612,7 +614,7 @@ sord_best_index(SordModel* sord, switch (sig) { PAT_CASE(0x011, FILTER_RANGE, OSP, PSO, 1); PAT_CASE(0x101, FILTER_RANGE, SPO, OPS, 1); - PAT_CASE(0x110, FILTER_RANGE, SOP, POS, 1); + // SPO is always present, so 0x110 is never reached here default: break; } @@ -900,16 +902,14 @@ SordNodeType sord_node_get_type(const SordNode* node) { switch (node->node.type) { - case SERD_BLANK: - return SORD_BLANK; - case SERD_LITERAL: - return SORD_LITERAL; case SERD_URI: return SORD_URI; + case SERD_BLANK: + return SORD_BLANK; default: - fprintf(stderr, "error: invalid node type\n"); - return (SordNodeType)0; + return SORD_LITERAL; } + SORD_UNREACHABLE(); } const uint8_t* diff --git a/src/sord_internal.h b/src/sord_internal.h index 5a7236d..71c2f6d 100644 --- a/src/sord_internal.h +++ b/src/sord_internal.h @@ -22,6 +22,12 @@ #include "sord/sord.h" +#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5) +# define SORD_UNREACHABLE() __builtin_unreachable() +#else +# define SORD_UNREACHABLE() assert(false) +#endif + /** Resource node metadata */ typedef struct { size_t refs_as_obj; ///< References as a quad object diff --git a/src/sord_test.c b/src/sord_test.c index fc37f06..438a393 100644 --- a/src/sord_test.c +++ b/src/sord_test.c @@ -22,7 +22,6 @@ #include "sord/sord.h" static const int DIGITS = 3; -static const int MAX_NUM = 999; static const unsigned n_objects_per = 2; static int n_expected_errors = 0; @@ -89,7 +88,7 @@ generate(SordWorld* world, // Add some literals // (98 4 "hello") and (98 4 "hello"^^<5>) - SordQuad tup = { 0, 0, 0, 0}; + SordQuad tup = { 0, 0, 0, 0 }; tup[0] = uri(world, 98); tup[1] = uri(world, 4); tup[2] = sord_new_literal(world, 0, USTR("hello"), NULL); @@ -381,17 +380,20 @@ main(int argc, char** argv) SordWorld* world = sord_world_new(); - sord_world_set_error_sink(world, unexpected_error, NULL); // Attempt to create invalid URI + fprintf(stderr, "expected "); SordNode* bad_uri = sord_new_uri(world, USTR("noscheme")); if (bad_uri) { return test_fail("Successfully created invalid URI \"noscheme\"\n"); } sord_node_free(world, bad_uri); + sord_world_set_error_sink(world, expected_error, NULL); + // Attempt to create invalid CURIE - SerdEnv* env = serd_env_new(NULL); + SerdNode base = serd_node_from_string(SERD_URI, USTR("http://example.org/")); + SerdEnv* env = serd_env_new(&base); SerdNode sbadns = serd_node_from_string(SERD_CURIE, USTR("badns:")); SordNode* badns = sord_node_from_serd_node(world, env, &sbadns, NULL, NULL); if (badns) { @@ -414,10 +416,12 @@ main(int argc, char** argv) sord_world_set_error_sink(world, expected_error, NULL); sord_node_free(world, garbage); sord_world_set_error_sink(world, unexpected_error, NULL); - if (n_expected_errors != 1) { + if (n_expected_errors != 2) { return test_fail("Successfully freed node twice\n"); } + sord_world_set_error_sink(world, unexpected_error, NULL); + // Check node flags are set properly SordNode* with_newline = sord_new_literal(world, NULL, USTR("a\nb"), NULL); if (!(sord_node_get_flags(with_newline) & SERD_HAS_NEWLINE)) { @@ -664,10 +668,50 @@ main(int argc, char** argv) } sord_iter_free(iter); + // Load file into two separate graphs sord_free(sord); + sord = sord_new(world, SORD_SPO, true); + env = serd_env_new(&base); + SordNode* graph1 = sord_new_uri(world, USTR("http://example.org/graph1")); + SordNode* graph2 = sord_new_uri(world, USTR("http://example.org/graph2")); + SerdReader* reader = sord_new_reader(sord, env, SERD_TURTLE, graph1); + if ((st = serd_reader_read_string(reader, USTR("

.")))) { + fprintf(stderr, "Failed to read string (%s)\n", serd_strerror(st)); + goto fail; + } + serd_reader_free(reader); + reader = sord_new_reader(sord, env, SERD_TURTLE, graph2); + if ((st = serd_reader_read_string(reader, USTR("

.")))) { + fprintf(stderr, "Failed to re-read string (%s)\n", serd_strerror(st)); + goto fail; + } - sord_world_free(world); + // Ensure we only see triple once + size_t n_triples = 0; + for (iter = sord_begin(sord); !sord_iter_end(iter); sord_iter_next(iter)) { + fprintf(stderr, "%s %s %s %s\n", + sord_node_get_string(sord_iter_get_node(iter, SORD_SUBJECT)), + sord_node_get_string(sord_iter_get_node(iter, SORD_PREDICATE)), + sord_node_get_string(sord_iter_get_node(iter, SORD_OBJECT)), + sord_node_get_string(sord_iter_get_node(iter, SORD_GRAPH))); + + ++n_triples; + } + if (n_triples != 1) { + fprintf(stderr, "Found duplicate triple\n"); + goto fail; + } + + // Test SPO iteration on an SOP indexed store + sord_free(sord); + sord = sord_new(world, SORD_SOP, false); + generate(world, sord, 1, graph42); + for (iter = sord_begin(sord); !sord_iter_end(iter); sord_iter_next(iter)) { + ++n_triples; + } + sord_free(sord); + sord_world_free(world); return EXIT_SUCCESS; fail: diff --git a/src/syntax.c b/src/syntax.c index 9c7fa74..f17312f 100644 --- a/src/syntax.c +++ b/src/syntax.c @@ -112,7 +112,7 @@ sord_new_reader(SordModel* model, return reader; } -static void +static SerdStatus write_statement(SordModel* sord, SerdWriter* writer, SordQuad tup, @@ -140,7 +140,7 @@ write_statement(SordModel* sord, // TODO: Subject abbreviation if (sord_node_is_inline_object(s) && !(flags & SERD_ANON_CONT)) { - return; + return SERD_SUCCESS; } SerdStatus st = SERD_SUCCESS; @@ -156,10 +156,10 @@ write_statement(SordModel* sord, if (!st && sub_iter) { flags |= SERD_ANON_CONT; - for (; !sord_iter_end(sub_iter); sord_iter_next(sub_iter)) { + for (; !st && !sord_iter_end(sub_iter); sord_iter_next(sub_iter)) { SordQuad sub_tup; sord_iter_get(sub_iter, sub_tup); - write_statement(sord, writer, sub_tup, flags); + st = write_statement(sord, writer, sub_tup, flags); } sord_iter_free(sub_iter); serd_writer_end_anon(writer, so); @@ -169,11 +169,7 @@ write_statement(SordModel* sord, writer, flags, NULL, ss, sp, so, sd, &language); } - if (st) { - fprintf(stderr, "Failed to write statement (%s)\n", - serd_strerror(st)); - return; - } + return st; } bool @@ -195,11 +191,13 @@ sord_write_iter(SordIter* iter, } SordModel* model = (SordModel*)sord_iter_get_model(iter); - for (; !sord_iter_end(iter); sord_iter_next(iter)) { + SerdStatus st = SERD_SUCCESS; + for (; !st && !sord_iter_end(iter); sord_iter_next(iter)) { SordQuad tup; sord_iter_get(iter, tup); - write_statement(model, writer, tup, 0); + st = write_statement(model, writer, tup, 0); } sord_iter_free(iter); - return true; + + return !st; } diff --git a/src/zix/hash.h b/src/zix/hash.h index e6f4028..e95b773 100644 --- a/src/zix/hash.h +++ b/src/zix/hash.h @@ -81,7 +81,7 @@ zix_hash_size(const ZixHash* hash); If no matching value is found, ZIX_STATUS_SUCCESS will be returned, and @p inserted will be pointed to the copy of `value` made in the new hash node. - + If a matching value already exists, ZIX_STATUS_EXISTS will be returned, and `inserted` will be pointed to the existing value. -- cgit v1.2.1