From 6f362db2fbfe1b02929673aa9b0529b4328fb195 Mon Sep 17 00:00:00 2001 From: David Robillard Date: Mon, 1 Mar 2021 19:38:01 -0500 Subject: Add SerdSink interface and hide implementations --- test/test_sink.c | 159 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 159 insertions(+) create mode 100644 test/test_sink.c (limited to 'test/test_sink.c') diff --git a/test/test_sink.c b/test/test_sink.c new file mode 100644 index 00000000..982fc1c9 --- /dev/null +++ b/test/test_sink.c @@ -0,0 +1,159 @@ +/* + Copyright 2019-2020 David Robillard + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ + +#undef NDEBUG + +#include "serd/serd.h" + +#include +#include +#include +#include + +#define NS_EG "http://example.org/" + +typedef struct { + const SerdNode* last_base; + const SerdNode* last_name; + const SerdNode* last_namespace; + const SerdNode* last_end; + const SerdNode* last_subject; + const SerdNode* last_predicate; + const SerdNode* last_object; + const SerdNode* last_graph; + SerdStatus return_status; +} State; + +static SerdStatus +on_base(void* handle, const SerdNode* uri) +{ + State* state = (State*)handle; + + state->last_base = uri; + return state->return_status; +} + +static SerdStatus +on_prefix(void* handle, const SerdNode* name, const SerdNode* uri) +{ + State* state = (State*)handle; + + state->last_name = name; + state->last_namespace = uri; + return state->return_status; +} + +static SerdStatus +on_statement(void* handle, + SerdStatementFlags flags, + const SerdNode* const graph, + const SerdNode* const subject, + const SerdNode* const predicate, + const SerdNode* const object) +{ + (void)flags; + + State* state = (State*)handle; + + state->last_subject = subject; + state->last_predicate = predicate; + state->last_object = object; + state->last_graph = graph; + + return state->return_status; +} + +static SerdStatus +on_end(void* handle, const SerdNode* node) +{ + State* state = (State*)handle; + + state->last_end = node; + return state->return_status; +} + +static void +test_callbacks(void) +{ + SerdNode* const base = serd_new_uri(SERD_STRING(NS_EG)); + SerdNode* const name = serd_new_string(SERD_STRING("eg")); + SerdNode* const uri = serd_new_uri(SERD_STRING(NS_EG "uri")); + SerdNode* const blank = serd_new_blank(SERD_STRING("b1")); + SerdEnv* env = serd_env_new(serd_node_string_view(base)); + State state = {0, 0, 0, 0, 0, 0, 0, 0, SERD_SUCCESS}; + + // Call functions on a sink with no functions set + + SerdSink* null_sink = serd_sink_new(&state, NULL); + assert(!serd_sink_write_base(null_sink, base)); + assert(!serd_sink_write_prefix(null_sink, name, uri)); + assert(!serd_sink_write(null_sink, 0, base, uri, blank, NULL)); + assert(!serd_sink_write_end(null_sink, blank)); + serd_sink_free(null_sink); + + // Try again with a sink that has the event handler set + + SerdSink* sink = serd_sink_new(&state, NULL); + serd_sink_set_base_func(sink, on_base); + serd_sink_set_prefix_func(sink, on_prefix); + serd_sink_set_statement_func(sink, on_statement); + serd_sink_set_end_func(sink, on_end); + + assert(!serd_sink_write_base(sink, base)); + assert(serd_node_equals(state.last_base, base)); + + assert(!serd_sink_write_prefix(sink, name, uri)); + assert(serd_node_equals(state.last_name, name)); + assert(serd_node_equals(state.last_namespace, uri)); + + assert(!serd_sink_write(sink, 0, base, uri, blank, NULL)); + assert(serd_node_equals(state.last_subject, base)); + assert(serd_node_equals(state.last_predicate, uri)); + assert(serd_node_equals(state.last_object, blank)); + assert(!state.last_graph); + + assert(!serd_sink_write_end(sink, blank)); + assert(serd_node_equals(state.last_end, blank)); + + serd_sink_free(sink); + serd_env_free(env); + serd_node_free(blank); + serd_node_free(uri); + serd_node_free(name); + serd_node_free(base); +} + +static void +test_free(void) +{ + // Free of null should (as always) not crash + serd_sink_free(NULL); + + // Set up a sink with dynamically allocated data and a free function + uintptr_t* data = (uintptr_t*)calloc(1, sizeof(uintptr_t)); + SerdSink* sink = serd_sink_new(data, free); + + // Free the sink, which should free the data (rely on valgrind or sanitizers) + serd_sink_free(sink); +} + +int +main(void) +{ + test_callbacks(); + test_free(); + return 0; +} -- cgit v1.2.1