diff options
author | David Robillard <d@drobilla.net> | 2021-02-20 19:18:28 -0500 |
---|---|---|
committer | David Robillard <d@drobilla.net> | 2023-12-02 18:49:07 -0500 |
commit | d62c7dc45af3256c6cd70d12a11e91b5b872c7db (patch) | |
tree | 63f9f1cc8f8900ad59b5bd8f07b70e6008522d21 /test | |
parent | ab1aa43256fac3e017212abe6f9d845bf74c024c (diff) | |
download | serd-d62c7dc45af3256c6cd70d12a11e91b5b872c7db.tar.gz serd-d62c7dc45af3256c6cd70d12a11e91b5b872c7db.tar.bz2 serd-d62c7dc45af3256c6cd70d12a11e91b5b872c7db.zip |
Replace multiple stream callbacks with SerdEvent
This makes plumbing easier since everything goes through the same "stream" and
only one callback is required to handling everything. It's also more easily
extensible in case more event types need to be added in the future.
Diffstat (limited to 'test')
-rw-r--r-- | test/test_env.c | 18 | ||||
-rw-r--r-- | test/test_overflow.c | 2 | ||||
-rw-r--r-- | test/test_reader_writer.c | 216 | ||||
-rw-r--r-- | test/test_sink.c | 50 | ||||
-rw-r--r-- | test/test_writer.c | 28 |
5 files changed, 170 insertions, 144 deletions
diff --git a/test/test_env.c b/test/test_env.c index 8dbc24a1..31446f69 100644 --- a/test/test_env.c +++ b/test/test_env.c @@ -4,7 +4,9 @@ #undef NDEBUG #include "serd/env.h" +#include "serd/event.h" #include "serd/node.h" +#include "serd/sink.h" #include "serd/status.h" #include "serd/string_view.h" @@ -12,12 +14,12 @@ #include <string.h> static SerdStatus -count_prefixes(void* handle, const SerdNode* name, const SerdNode* uri) +count_prefixes(void* handle, const SerdEvent* event) { - (void)name; - (void)uri; + if (event->type == SERD_PREFIX) { + ++*(int*)handle; + } - ++*(int*)handle; return SERD_SUCCESS; } @@ -73,10 +75,13 @@ test_env(void) assert(!serd_env_expand_node(env, blank)); serd_node_free(blank); - int n_prefixes = 0; + size_t n_prefixes = 0; + SerdSink* const count_prefixes_sink = + serd_sink_new(&n_prefixes, count_prefixes, NULL); + serd_env_set_prefix( env, serd_string("eg.2"), serd_string("http://example.org/")); - serd_env_foreach(env, count_prefixes, &n_prefixes); + serd_env_write_prefixes(env, count_prefixes_sink); assert(n_prefixes == 1); SerdNode* shorter_uri = serd_new_uri(serd_string("urn:foo")); @@ -93,6 +98,7 @@ test_env(void) assert(!serd_env_set_base_uri(env, serd_empty_string())); assert(!serd_env_base_uri(env)); + serd_sink_free(count_prefixes_sink); serd_node_free(shorter_uri); serd_node_free(badpre); serd_node_free(s); diff --git a/test/test_overflow.c b/test/test_overflow.c index f4c5a863..62154958 100644 --- a/test/test_overflow.c +++ b/test/test_overflow.c @@ -17,7 +17,7 @@ test_size(SerdWorld* const world, const SerdSyntax syntax, const size_t stack_size) { - SerdSink* sink = serd_sink_new(NULL, NULL); + SerdSink* sink = serd_sink_new(NULL, NULL, NULL); SerdReader* const reader = serd_reader_new(world, syntax, sink, stack_size); if (!reader) { return SERD_BAD_STACK; diff --git a/test/test_reader_writer.c b/test/test_reader_writer.c index c4f8bb90..abea37b3 100644 --- a/test/test_reader_writer.c +++ b/test/test_reader_writer.c @@ -5,11 +5,11 @@ #include "serd/buffer.h" #include "serd/env.h" +#include "serd/event.h" #include "serd/memory.h" #include "serd/node.h" #include "serd/reader.h" #include "serd/sink.h" -#include "serd/statement.h" #include "serd/status.h" #include "serd/stream.h" #include "serd/string_view.h" @@ -65,46 +65,25 @@ static const char* const doc_string = "( eg:o ) eg:t eg:u .\n"; static SerdStatus -test_base_sink(void* handle, const SerdNode* uri) +test_sink(void* handle, const SerdEvent* event) { - (void)uri; - - ReaderTest* rt = (ReaderTest*)handle; - ++rt->n_base; - return SERD_SUCCESS; -} - -static SerdStatus -test_prefix_sink(void* handle, const SerdNode* name, const SerdNode* uri) -{ - (void)name; - (void)uri; - ReaderTest* rt = (ReaderTest*)handle; - ++rt->n_prefix; - return SERD_SUCCESS; -} - -static SerdStatus -test_statement_sink(void* handle, - const SerdStatementFlags flags, - const SerdStatement* statement) -{ - (void)flags; - (void)statement; - - ReaderTest* rt = (ReaderTest*)handle; - ++rt->n_statement; - return SERD_SUCCESS; -} -static SerdStatus -test_end_sink(void* handle, const SerdNode* node) -{ - (void)node; + switch (event->type) { + case SERD_BASE: + ++rt->n_base; + break; + case SERD_PREFIX: + ++rt->n_prefix; + break; + case SERD_STATEMENT: + ++rt->n_statement; + break; + case SERD_END: + ++rt->n_end; + break; + } - ReaderTest* rt = (ReaderTest*)handle; - ++rt->n_end; return SERD_SUCCESS; } @@ -158,6 +137,7 @@ test_read_nquads_chunks(const char* const path) static const char null = 0; FILE* const f = fopen(path, "w+b"); + assert(f); // Write two statements, a null separator, then another statement @@ -177,18 +157,13 @@ test_read_nquads_chunks(const char* const path) fseek(f, 0, SEEK_SET); - SerdWorld* const world = serd_world_new(); - ReaderTest* const rt = (ReaderTest*)calloc(1, sizeof(ReaderTest)); - SerdSink* const sink = serd_sink_new(rt, NULL); - SerdReader* const reader = serd_reader_new(world, SERD_NQUADS, sink, 4096); + SerdWorld* const world = serd_world_new(); + ReaderTest rt = {0, 0, 0, 0}; + SerdSink* const sink = serd_sink_new(&rt, test_sink, NULL); + assert(sink); + SerdReader* const reader = serd_reader_new(world, SERD_NQUADS, sink, 4096); assert(reader); - assert(sink); - assert(f); - serd_sink_set_base_func(sink, test_base_sink); - serd_sink_set_prefix_func(sink, test_prefix_sink); - serd_sink_set_statement_func(sink, test_statement_sink); - serd_sink_set_end_func(sink, test_end_sink); SerdStatus st = serd_reader_start_stream( reader, (SerdReadFunc)fread, (SerdStreamErrorFunc)ferror, f, NULL, 1); @@ -197,48 +172,47 @@ test_read_nquads_chunks(const char* const path) // Read first statement st = serd_reader_read_chunk(reader); assert(st == SERD_SUCCESS); - assert(rt->n_base == 0); - assert(rt->n_prefix == 0); - assert(rt->n_statement == 1); - assert(rt->n_end == 0); + assert(rt.n_base == 0); + assert(rt.n_prefix == 0); + assert(rt.n_statement == 1); + assert(rt.n_end == 0); // Read second statement st = serd_reader_read_chunk(reader); assert(st == SERD_SUCCESS); - assert(rt->n_base == 0); - assert(rt->n_prefix == 0); - assert(rt->n_statement == 2); - assert(rt->n_end == 0); + assert(rt.n_base == 0); + assert(rt.n_prefix == 0); + assert(rt.n_statement == 2); + assert(rt.n_end == 0); // Read terminator st = serd_reader_read_chunk(reader); assert(st == SERD_FAILURE); - assert(rt->n_base == 0); - assert(rt->n_prefix == 0); - assert(rt->n_statement == 2); - assert(rt->n_end == 0); + assert(rt.n_base == 0); + assert(rt.n_prefix == 0); + assert(rt.n_statement == 2); + assert(rt.n_end == 0); // Read last statement st = serd_reader_read_chunk(reader); assert(st == SERD_SUCCESS); - assert(rt->n_base == 0); - assert(rt->n_prefix == 0); - assert(rt->n_statement == 3); - assert(rt->n_end == 0); + assert(rt.n_base == 0); + assert(rt.n_prefix == 0); + assert(rt.n_statement == 3); + assert(rt.n_end == 0); // EOF st = serd_reader_read_chunk(reader); assert(st == SERD_FAILURE); - assert(rt->n_base == 0); - assert(rt->n_prefix == 0); - assert(rt->n_statement == 3); - assert(rt->n_end == 0); + assert(rt.n_base == 0); + assert(rt.n_prefix == 0); + assert(rt.n_statement == 3); + assert(rt.n_end == 0); assert(serd_reader_read_chunk(reader) == SERD_FAILURE); serd_reader_free(reader); serd_sink_free(sink); - free(rt); serd_world_free(world); fclose(f); remove(path); @@ -250,6 +224,7 @@ test_read_turtle_chunks(const char* const path) static const char null = 0; FILE* const f = fopen(path, "w+b"); + assert(f); // Write two statements separated by null characters fprintf(f, "@base <http://example.org/base/> .\n"); @@ -261,18 +236,13 @@ test_read_turtle_chunks(const char* const path) fwrite(&null, sizeof(null), 1, f); fseek(f, 0, SEEK_SET); - SerdWorld* world = serd_world_new(); - ReaderTest* rt = (ReaderTest*)calloc(1, sizeof(ReaderTest)); - SerdSink* sink = serd_sink_new(rt, NULL); - SerdReader* reader = serd_reader_new(world, SERD_TURTLE, sink, 4096); + SerdWorld* world = serd_world_new(); + ReaderTest rt = {0, 0, 0, 0}; + SerdSink* sink = serd_sink_new(&rt, test_sink, NULL); + assert(sink); + SerdReader* reader = serd_reader_new(world, SERD_TURTLE, sink, 4096); assert(reader); - assert(sink); - assert(f); - serd_sink_set_base_func(sink, test_base_sink); - serd_sink_set_prefix_func(sink, test_prefix_sink); - serd_sink_set_statement_func(sink, test_statement_sink); - serd_sink_set_end_func(sink, test_end_sink); SerdStatus st = serd_reader_start_stream( reader, (SerdReadFunc)fread, (SerdStreamErrorFunc)ferror, f, NULL, 1); @@ -281,64 +251,63 @@ test_read_turtle_chunks(const char* const path) // Read base st = serd_reader_read_chunk(reader); assert(st == SERD_SUCCESS); - assert(rt->n_base == 1); - assert(rt->n_prefix == 0); - assert(rt->n_statement == 0); - assert(rt->n_end == 0); + assert(rt.n_base == 1); + assert(rt.n_prefix == 0); + assert(rt.n_statement == 0); + assert(rt.n_end == 0); // Read prefix st = serd_reader_read_chunk(reader); assert(st == SERD_SUCCESS); - assert(rt->n_base == 1); - assert(rt->n_prefix == 1); - assert(rt->n_statement == 0); - assert(rt->n_end == 0); + assert(rt.n_base == 1); + assert(rt.n_prefix == 1); + assert(rt.n_statement == 0); + assert(rt.n_end == 0); // Read first two statements st = serd_reader_read_chunk(reader); assert(st == SERD_SUCCESS); - assert(rt->n_base == 1); - assert(rt->n_prefix == 1); - assert(rt->n_statement == 2); - assert(rt->n_end == 0); + assert(rt.n_base == 1); + assert(rt.n_prefix == 1); + assert(rt.n_statement == 2); + assert(rt.n_end == 0); // Read terminator st = serd_reader_read_chunk(reader); assert(st == SERD_FAILURE); - assert(rt->n_base == 1); - assert(rt->n_prefix == 1); - assert(rt->n_statement == 2); - assert(rt->n_end == 0); + assert(rt.n_base == 1); + assert(rt.n_prefix == 1); + assert(rt.n_statement == 2); + assert(rt.n_end == 0); // Read statements after null terminator st = serd_reader_read_chunk(reader); assert(st == SERD_SUCCESS); - assert(rt->n_base == 1); - assert(rt->n_prefix == 1); - assert(rt->n_statement == 4); - assert(rt->n_end == 1); + assert(rt.n_base == 1); + assert(rt.n_prefix == 1); + assert(rt.n_statement == 4); + assert(rt.n_end == 1); // Read terminator st = serd_reader_read_chunk(reader); assert(st == SERD_FAILURE); - assert(rt->n_base == 1); - assert(rt->n_prefix == 1); - assert(rt->n_statement == 4); - assert(rt->n_end == 1); + assert(rt.n_base == 1); + assert(rt.n_prefix == 1); + assert(rt.n_statement == 4); + assert(rt.n_end == 1); // EOF st = serd_reader_read_chunk(reader); assert(st == SERD_FAILURE); - assert(rt->n_base == 1); - assert(rt->n_prefix == 1); - assert(rt->n_statement == 4); - assert(rt->n_end == 1); + assert(rt.n_base == 1); + assert(rt.n_prefix == 1); + assert(rt.n_statement == 4); + assert(rt.n_end == 1); assert(serd_reader_read_chunk(reader) == SERD_FAILURE); serd_reader_free(reader); serd_sink_free(sink); - free(rt); serd_world_free(world); fclose(f); remove(path); @@ -347,18 +316,13 @@ test_read_turtle_chunks(const char* const path) static void test_read_string(void) { - SerdWorld* world = serd_world_new(); - ReaderTest* rt = (ReaderTest*)calloc(1, sizeof(ReaderTest)); - SerdSink* sink = serd_sink_new(rt, NULL); - SerdReader* reader = serd_reader_new(world, SERD_TURTLE, sink, 4096); - - assert(reader); + SerdWorld* world = serd_world_new(); + ReaderTest rt = {0, 0, 0, 0}; + SerdSink* sink = serd_sink_new(&rt, test_sink, NULL); assert(sink); - serd_sink_set_base_func(sink, test_base_sink); - serd_sink_set_prefix_func(sink, test_prefix_sink); - serd_sink_set_statement_func(sink, test_statement_sink); - serd_sink_set_end_func(sink, test_end_sink); + SerdReader* reader = serd_reader_new(world, SERD_TURTLE, sink, 4096); + assert(reader); // Test reading a string that ends exactly at the end of input (no newline) assert( @@ -368,15 +332,14 @@ test_read_string(void) NULL)); assert(!serd_reader_read_document(reader)); - assert(rt->n_base == 0); - assert(rt->n_prefix == 0); - assert(rt->n_statement == 1); - assert(rt->n_end == 0); + assert(rt.n_base == 0); + assert(rt.n_prefix == 0); + assert(rt.n_statement == 1); + assert(rt.n_end == 0); assert(!serd_reader_finish(reader)); serd_reader_free(reader); serd_sink_free(sink); - free(rt); serd_world_free(world); } @@ -525,7 +488,7 @@ test_writer(const char* const path) SerdNode* const base = serd_new_uri(serd_string("http://example.org/base")); - serd_writer_set_base_uri(writer, base); + serd_sink_write_base(serd_writer_sink(writer), base); serd_node_free(base); serd_writer_free(writer); @@ -547,14 +510,9 @@ test_reader(const char* path) { SerdWorld* world = serd_world_new(); ReaderTest rt = {0, 0, 0, 0}; - SerdSink* const sink = serd_sink_new(&rt, NULL); + SerdSink* const sink = serd_sink_new(&rt, test_sink, NULL); assert(sink); - serd_sink_set_base_func(sink, test_base_sink); - serd_sink_set_prefix_func(sink, test_prefix_sink); - serd_sink_set_statement_func(sink, test_statement_sink); - serd_sink_set_end_func(sink, test_end_sink); - // Test that too little stack space fails gracefully assert(!serd_reader_new(world, SERD_TURTLE, sink, 32)); diff --git a/test/test_sink.c b/test/test_sink.c index 4b9a2eb2..b0756fcc 100644 --- a/test/test_sink.c +++ b/test/test_sink.c @@ -4,6 +4,7 @@ #undef NDEBUG #include "serd/env.h" +#include "serd/event.h" #include "serd/node.h" #include "serd/sink.h" #include "serd/statement.h" @@ -68,6 +69,24 @@ on_end(void* handle, const SerdNode* node) return state->return_status; } +static SerdStatus +on_event(void* const handle, const SerdEvent* const event) +{ + switch (event->type) { + case SERD_BASE: + return on_base(handle, event->base.uri); + case SERD_PREFIX: + return on_prefix(handle, event->prefix.name, event->prefix.uri); + case SERD_STATEMENT: + return on_statement( + handle, event->statement.flags, event->statement.statement); + case SERD_END: + return on_end(handle, event->end.node); + } + + return SERD_BAD_ARG; +} + static void test_callbacks(void) { @@ -81,23 +100,37 @@ test_callbacks(void) SerdStatement* const statement = serd_statement_new(base, uri, blank, NULL, NULL); + const SerdBaseEvent base_event = {SERD_BASE, uri}; + const SerdPrefixEvent prefix_event = {SERD_PREFIX, name, uri}; + const SerdStatementEvent statement_event = {SERD_STATEMENT, 0U, statement}; + const SerdEndEvent end_event = {SERD_END, blank}; + // Call functions on a sink with no functions set - SerdSink* null_sink = serd_sink_new(&state, NULL); + SerdSink* null_sink = serd_sink_new(&state, NULL, NULL); + assert(!serd_sink_write_base(null_sink, base)); assert(!serd_sink_write_prefix(null_sink, name, uri)); assert(!serd_sink_write_statement(null_sink, 0, statement)); assert(!serd_sink_write(null_sink, 0, base, uri, blank, NULL)); assert(!serd_sink_write_end(null_sink, blank)); + + SerdEvent event = {SERD_BASE}; + + event.base = base_event; + assert(!serd_sink_write_event(null_sink, &event)); + event.prefix = prefix_event; + assert(!serd_sink_write_event(null_sink, &event)); + event.statement = statement_event; + assert(!serd_sink_write_event(null_sink, &event)); + event.end = end_event; + assert(!serd_sink_write_event(null_sink, &event)); + 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); + SerdSink* sink = serd_sink_new(&state, on_event, NULL); assert(!serd_sink_write_base(sink, base)); assert(serd_node_equals(state.last_base, base)); @@ -112,6 +145,9 @@ test_callbacks(void) assert(!serd_sink_write_end(sink, blank)); assert(serd_node_equals(state.last_end, blank)); + const SerdEvent junk = {(SerdEventType)42}; + assert(serd_sink_write_event(sink, &junk) == SERD_BAD_ARG); + serd_sink_free(sink); serd_statement_free(statement); @@ -130,7 +166,7 @@ test_free(void) // 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); + SerdSink* sink = serd_sink_new(data, NULL, free); // Free the sink, which should free the data (rely on valgrind or sanitizers) serd_sink_free(sink); diff --git a/test/test_writer.c b/test/test_writer.c index db68454f..d2f59af0 100644 --- a/test/test_writer.c +++ b/test/test_writer.c @@ -5,6 +5,7 @@ #include "serd/buffer.h" #include "serd/env.h" +#include "serd/event.h" #include "serd/memory.h" #include "serd/node.h" #include "serd/sink.h" @@ -21,6 +22,31 @@ #include <string.h> static void +test_write_bad_event(void) +{ + SerdWorld* world = serd_world_new(); + SerdEnv* env = serd_env_new(serd_empty_string()); + SerdBuffer buffer = {NULL, 0}; + SerdWriter* writer = + serd_writer_new(world, SERD_TURTLE, 0U, env, serd_buffer_sink, &buffer); + + assert(writer); + + const SerdEvent event = {(SerdEventType)42}; + assert(serd_sink_write_event(serd_writer_sink(writer), &event) == + SERD_BAD_ARG); + + char* const out = serd_buffer_sink_finish(&buffer); + + assert(!strcmp(out, "")); + serd_free(out); + + serd_writer_free(writer); + serd_env_free(env); + serd_world_free(world); +} + +static void test_write_bad_prefix(void) { SerdWorld* world = serd_world_new(); @@ -129,7 +155,6 @@ test_writer_cleanup(void) // Finish writing without terminating nodes assert(!(st = serd_writer_finish(writer))); - assert(!(st = serd_writer_set_base_uri(writer, NULL))); // Set the base to an empty URI SerdNode* empty_uri = serd_new_uri(serd_string("")); @@ -225,6 +250,7 @@ test_write_error(void) int main(void) { + test_write_bad_event(); test_write_bad_prefix(); test_write_long_literal(); test_writer_cleanup(); |