diff options
-rw-r--r-- | NEWS | 3 | ||||
-rw-r--r-- | src/sord.c | 23 | ||||
-rw-r--r-- | src/sord_test.c | 91 |
3 files changed, 101 insertions, 16 deletions
@@ -10,9 +10,10 @@ sord (0.13.1) unstable; PlainLiteral, and someValuesFrom restrictions. * This release does not break the ABI, but the semantics of iterators has changed: any modification to a model invalidates iterators on that model + * Improve test coverage * Upgrade to waf 1.8.14 - -- David Robillard <d@drobilla.net> Fri, 02 Oct 2015 20:55:15 -0400 + -- David Robillard <d@drobilla.net> Fri, 02 Oct 2015 21:13:32 -0400 sord (0.12.2) stable; @@ -361,8 +361,7 @@ sord_iter_seek_match(SordIter* iter) static inline bool sord_iter_seek_match_range(SordIter* iter) { - if (iter->end) - return true; + assert(!iter->end); do { const SordNode** key = (const SordNode**)zix_btree_get(iter->cur); @@ -584,14 +583,10 @@ sord_best_index(SordModel* sord, *n_prefix = 0; switch (sig) { case 0x000: - if (graph_search) { - *mode = RANGE; - *n_prefix = 1; - return DEFAULT_GRAPH_ORDER; - } else { - *mode = ALL; - return DEFAULT_ORDER; - } + assert(graph_search); + *mode = RANGE; + *n_prefix = 1; + return DEFAULT_GRAPH_ORDER; case 0x111: *mode = SINGLE; return graph_search ? DEFAULT_GRAPH_ORDER : DEFAULT_ORDER; @@ -1165,10 +1160,9 @@ sord_node_free(SordWorld* world, SordNode* node) { if (!node) { return; - } - - assert(node->refs > 0); - if (--node->refs == 0) { + } else if (node->refs == 0) { + error(world, SERD_ERR_BAD_ARG, "attempt to free garbage node\n"); + } else if (--node->refs == 0) { sord_node_free_internal(world, node); } } @@ -1252,6 +1246,7 @@ sord_erase(SordModel* sord, SordIter* iter) { if (sord->n_iters > 1) { error(sord->world, SERD_ERR_BAD_ARG, "erased with many iterators\n"); + return SERD_ERR_BAD_ARG; } SordQuad tup; diff --git a/src/sord_test.c b/src/sord_test.c index f52cc01..fc37f06 100644 --- a/src/sord_test.c +++ b/src/sord_test.c @@ -25,6 +25,8 @@ static const int DIGITS = 3; static const int MAX_NUM = 999; static const unsigned n_objects_per = 2; +static int n_expected_errors = 0; + typedef struct { SordQuad query; int expected_num_results; @@ -353,6 +355,23 @@ test_read(SordWorld* world, SordModel* sord, SordNode* g, return ret; } +static SerdStatus +unexpected_error(void* handle, const SerdError* error) +{ + fprintf(stderr, "unexpected error: "); + vfprintf(stderr, error->fmt, *error->args); + return SERD_SUCCESS; +} + +static SerdStatus +expected_error(void* handle, const SerdError* error) +{ + fprintf(stderr, "expected error: "); + vfprintf(stderr, error->fmt, *error->args); + ++n_expected_errors; + return SERD_SUCCESS; +} + int main(int argc, char** argv) { @@ -362,6 +381,53 @@ main(int argc, char** argv) SordWorld* world = sord_world_new(); + sord_world_set_error_sink(world, unexpected_error, NULL); + + // Attempt to create invalid URI + 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); + + // Attempt to create invalid CURIE + SerdEnv* env = serd_env_new(NULL); + SerdNode sbadns = serd_node_from_string(SERD_CURIE, USTR("badns:")); + SordNode* badns = sord_node_from_serd_node(world, env, &sbadns, NULL, NULL); + if (badns) { + return test_fail("Successfully created CURIE with bad namespace\n"); + } + sord_node_free(world, badns); + serd_env_free(env); + + // Attempt to create NULL node + SordNode* nil_node = sord_node_from_serd_node( + world, NULL, &SERD_NODE_NULL, NULL, NULL); + if (nil_node) { + return test_fail("Successfully created NULL node\n"); + } + sord_node_free(world, nil_node); + + // Attempt to double-free a node + SordNode* garbage = sord_new_uri(world, USTR("urn:garbage")); + sord_node_free(world, garbage); + 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) { + return test_fail("Successfully freed node twice\n"); + } + + // 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)) { + return test_fail("Newline flag not set\n"); + } + SordNode* with_quote = sord_new_literal(world, NULL, USTR("a\"b"), NULL); + if (!(sord_node_get_flags(with_quote) & SERD_HAS_QUOTE)) { + return test_fail("Quote flag not set\n"); + } + // Create with minimal indexing SordModel* sord = sord_new(world, SORD_SPO, false); generate(world, sord, n_quads, NULL); @@ -373,6 +439,7 @@ main(int argc, char** argv) } // Check adding tuples with NULL fields fails + sord_world_set_error_sink(world, expected_error, NULL); const size_t initial_num_quads = sord_num_quads(sord); SordQuad tup = { 0, 0, 0, 0}; if (sord_add(sord, tup)) { @@ -392,6 +459,28 @@ main(int argc, char** argv) sord_num_quads(sord), initial_num_quads); } + // Check adding tuples with an active iterator fails + SordIter* iter = sord_begin(sord); + tup[2] = uri(world, 3); + if (sord_add(sord, tup)) { + return test_fail("Added tuple with active iterator\n"); + } + + // Check removing tuples with several active iterator fails + SordIter* iter2 = sord_begin(sord); + if (!sord_erase(sord, iter)) { + return test_fail("Erased tuple with several active iterators\n"); + } + n_expected_errors = 0; + sord_remove(sord, tup); + if (n_expected_errors != 1) { + return test_fail("Removed tuple with several active iterators\n"); + } + sord_iter_free(iter); + sord_iter_free(iter2); + + sord_world_set_error_sink(world, unexpected_error, NULL); + // Check interning merges equivalent values SordNode* uri_id = sord_new_uri(world, USTR("http://example.org")); SordNode* blank_id = sord_new_blank(world, USTR("testblank")); @@ -538,7 +627,7 @@ main(int argc, char** argv) goto fail; } - SordIter* iter = sord_find(sord, tup); + iter = sord_find(sord, tup); if (!sord_iter_end(iter)) { fprintf(stderr, "Found removed tuple\n"); goto fail; |