diff options
author | David Robillard <d@drobilla.net> | 2023-09-10 15:06:42 -0400 |
---|---|---|
committer | David Robillard <d@drobilla.net> | 2023-12-02 18:49:08 -0500 |
commit | 248a874d7425749d29cf900a1c3783c624ea8d8c (patch) | |
tree | aed59f5a484a815cd254506866e98a947858904d /test/test_writer.c | |
parent | 0bd10132c6707353dba80bd89cf0102ee7ca4e34 (diff) | |
download | serd-248a874d7425749d29cf900a1c3783c624ea8d8c.tar.gz serd-248a874d7425749d29cf900a1c3783c624ea8d8c.tar.bz2 serd-248a874d7425749d29cf900a1c3783c624ea8d8c.zip |
Add support for custom allocators
This makes it explicit in the API where memory is allocated, and allows the
user to provide a custom allocator to avoid the use of the default system
allocator for whatever reason.
Diffstat (limited to 'test/test_writer.c')
-rw-r--r-- | test/test_writer.c | 269 |
1 files changed, 182 insertions, 87 deletions
diff --git a/test/test_writer.c b/test/test_writer.c index 47350031..39bcd34a 100644 --- a/test/test_writer.c +++ b/test/test_writer.c @@ -3,6 +3,8 @@ #undef NDEBUG +#include "failing_allocator.h" + #include "serd/buffer.h" #include "serd/env.h" #include "serd/event.h" @@ -26,23 +28,112 @@ static void test_writer_new(void) { - SerdWorld* world = serd_world_new(); - SerdEnv* env = serd_env_new(serd_empty_string()); - SerdBuffer buffer = {NULL, 0}; + SerdWorld* world = serd_world_new(NULL); + SerdEnv* env = serd_env_new(NULL, serd_empty_string()); + SerdBuffer buffer = {NULL, NULL, 0}; SerdOutputStream output = serd_open_output_buffer(&buffer); assert(!serd_writer_new(world, SERD_TURTLE, 0U, env, &output, 0U)); + serd_env_free(env); serd_world_free(world); +} + +static void +test_new_failed_alloc(void) +{ + SerdFailingAllocator allocator = serd_failing_allocator(); + + SerdWorld* const world = serd_world_new(&allocator.base); + SerdEnv* env = serd_env_new(&allocator.base, serd_empty_string()); + SerdBuffer buffer = {&allocator.base, NULL, 0}; + SerdOutputStream output = serd_open_output_buffer(&buffer); + const size_t n_world_allocs = allocator.n_allocations; + + // Successfully allocate a writer to count the number of allocations + SerdWriter* const writer = + serd_writer_new(world, SERD_TURTLE, 0U, env, &output, 1U); + + assert(writer); + + // Test that each allocation failing is handled gracefully + const size_t n_new_allocs = allocator.n_allocations - n_world_allocs; + for (size_t i = 0; i < n_new_allocs; ++i) { + allocator.n_remaining = i; + assert(!serd_writer_new(world, SERD_TURTLE, 0U, env, &output, 1U)); + } + + serd_writer_free(writer); serd_env_free(env); + serd_world_free(world); +} + +static void +test_write_failed_alloc(void) +{ + SerdFailingAllocator allocator = serd_failing_allocator(); + + SerdWorld* world = serd_world_new(&allocator.base); + SerdEnv* env = serd_env_new(NULL, serd_empty_string()); + SerdBuffer buffer = {&allocator.base, NULL, 0}; + SerdOutputStream output = serd_open_output_buffer(&buffer); + + SerdNode* s = serd_new_uri(NULL, serd_string("http://example.org/s")); + SerdNode* p1 = serd_new_uri(NULL, serd_string("http://example.org/p")); + + SerdNode* p2 = serd_new_uri( + NULL, serd_string("http://example.org/dramatically/longer/predicate")); + + SerdNode* o = serd_new_token(NULL, SERD_BLANK, serd_string("o")); + + const size_t n_setup_allocs = allocator.n_allocations; + + // Successfully write a statement to count the number of allocations + SerdWriter* writer = + serd_writer_new(world, SERD_TURTLE, 0U, env, &output, 1U); + const SerdSink* sink = serd_writer_sink(writer); + assert(writer); + assert(sink); + assert(!serd_sink_write(sink, 0U, s, p1, o, NULL)); + assert(!serd_sink_write(sink, 0U, s, p2, o, NULL)); + const size_t n_new_allocs = allocator.n_allocations - n_setup_allocs; + + serd_writer_free(writer); + + // Test that each allocation failing is handled gracefully + for (size_t i = 0; i < n_new_allocs; ++i) { + allocator.n_remaining = i; + + if ((writer = serd_writer_new(world, SERD_TURTLE, 0U, env, &output, 1U))) { + sink = serd_writer_sink(writer); + + const SerdStatus st1 = serd_sink_write(sink, 0U, s, p1, o, NULL); + const SerdStatus st2 = serd_sink_write(sink, 0U, s, p2, o, NULL); + + assert(st1 == SERD_BAD_ALLOC || st1 == SERD_BAD_WRITE || + st2 == SERD_BAD_ALLOC || st2 == SERD_BAD_WRITE); + + serd_writer_free(writer); + } + } + + serd_close_output(&output); + serd_env_free(env); + serd_buffer_close(&buffer); + serd_free(NULL, buffer.buf); + serd_node_free(NULL, o); + serd_node_free(NULL, p2); + serd_node_free(NULL, p1); + serd_node_free(NULL, s); + serd_world_free(world); } static void test_write_bad_event(void) { - SerdWorld* world = serd_world_new(); - SerdEnv* env = serd_env_new(serd_empty_string()); - SerdBuffer buffer = {NULL, 0}; + SerdWorld* world = serd_world_new(NULL); + SerdEnv* env = serd_env_new(NULL, serd_empty_string()); + SerdBuffer buffer = {NULL, NULL, 0}; SerdOutputStream output = serd_open_output_buffer(&buffer); SerdWriter* writer = @@ -58,7 +149,7 @@ test_write_bad_event(void) char* const out = (char*)buffer.buf; assert(out); assert(!strcmp(out, "")); - serd_free(out); + serd_free(NULL, buffer.buf); serd_writer_free(writer); serd_env_free(env); @@ -68,26 +159,28 @@ test_write_bad_event(void) static void test_write_long_literal(void) { - SerdWorld* world = serd_world_new(); - SerdEnv* env = serd_env_new(serd_empty_string()); - SerdBuffer buffer = {NULL, 0}; + SerdWorld* world = serd_world_new(NULL); + SerdEnv* env = serd_env_new(NULL, serd_empty_string()); + SerdBuffer buffer = {NULL, NULL, 0}; SerdOutputStream output = serd_open_output_buffer(&buffer); SerdWriter* writer = serd_writer_new(world, SERD_TURTLE, 0U, env, &output, 1U); assert(writer); - SerdNode* s = serd_new_uri(serd_string("http://example.org/s")); - SerdNode* p = serd_new_uri(serd_string("http://example.org/p")); - SerdNode* o = serd_new_literal( - serd_string("hello \"\"\"world\"\"\"!"), SERD_IS_LONG, serd_empty_string()); + SerdNode* s = serd_new_uri(NULL, serd_string("http://example.org/s")); + SerdNode* p = serd_new_uri(NULL, serd_string("http://example.org/p")); + SerdNode* o = serd_new_literal(NULL, + serd_string("hello \"\"\"world\"\"\"!"), + SERD_IS_LONG, + serd_empty_string()); assert(serd_node_flags(o) & SERD_IS_LONG); assert(!serd_sink_write(serd_writer_sink(writer), 0, s, p, o, NULL)); - serd_node_free(o); - serd_node_free(p); - serd_node_free(s); + serd_node_free(NULL, o); + serd_node_free(NULL, p); + serd_node_free(NULL, s); serd_writer_free(writer); serd_close_output(&output); serd_env_free(env); @@ -100,7 +193,7 @@ test_write_long_literal(void) "\t<http://example.org/p> \"\"\"hello \"\"\\\"world\"\"\\\"!\"\"\" .\n"; assert(!strcmp(out, expected)); - serd_free(out); + serd_free(NULL, buffer.buf); serd_world_free(world); } @@ -121,8 +214,8 @@ static void test_writer_cleanup(void) { SerdStatus st = SERD_SUCCESS; - SerdWorld* world = serd_world_new(); - SerdEnv* env = serd_env_new(serd_empty_string()); + SerdWorld* world = serd_world_new(NULL); + SerdEnv* env = serd_env_new(NULL, serd_empty_string()); SerdOutputStream output = serd_open_output_stream(null_sink, NULL, NULL, NULL); @@ -131,9 +224,9 @@ test_writer_cleanup(void) const SerdSink* sink = serd_writer_sink(writer); - SerdNode* s = serd_new_uri(serd_string("http://example.org/s")); - SerdNode* p = serd_new_uri(serd_string("http://example.org/p")); - SerdNode* o = serd_new_blank(serd_string("start")); + SerdNode* s = serd_new_uri(NULL, serd_string("http://example.org/s")); + SerdNode* p = serd_new_uri(NULL, serd_string("http://example.org/p")); + SerdNode* o = serd_new_blank(NULL, serd_string("start")); st = serd_sink_write(sink, SERD_ANON_O, s, p, o, NULL); assert(!st); @@ -143,11 +236,11 @@ test_writer_cleanup(void) char buf[12] = {0}; snprintf(buf, sizeof(buf), "b%u", i); - SerdNode* next_o = serd_new_blank(serd_string(buf)); + SerdNode* next_o = serd_new_blank(NULL, serd_string(buf)); st = serd_sink_write(sink, SERD_ANON_O, o, p, next_o, NULL); - serd_node_free(o); + serd_node_free(NULL, o); o = next_o; } @@ -155,14 +248,14 @@ test_writer_cleanup(void) assert(!(st = serd_writer_finish(writer))); // Set the base to an empty URI - SerdNode* empty_uri = serd_new_uri(serd_string("")); + SerdNode* empty_uri = serd_new_uri(NULL, serd_string("")); assert(!(st = serd_sink_write_base(sink, empty_uri))); - serd_node_free(empty_uri); + serd_node_free(NULL, empty_uri); // Free (which could leak if the writer doesn't clean up the stack properly) - serd_node_free(o); - serd_node_free(p); - serd_node_free(s); + serd_node_free(NULL, o); + serd_node_free(NULL, p); + serd_node_free(NULL, s); serd_writer_free(writer); serd_env_free(env); serd_world_free(world); @@ -175,8 +268,8 @@ test_strict_write(void) FILE* const fd = fopen(path, "wb"); assert(fd); - SerdWorld* world = serd_world_new(); - SerdEnv* const env = serd_env_new(serd_empty_string()); + SerdWorld* world = serd_world_new(NULL); + SerdEnv* const env = serd_env_new(NULL, serd_empty_string()); SerdOutputStream out = serd_open_output_stream(null_sink, NULL, NULL, fd); SerdWriter* const writer = serd_writer_new(world, SERD_TURTLE, 0U, env, &out, 1U); @@ -187,19 +280,19 @@ test_strict_write(void) const uint8_t bad_str[] = {0xFF, 0x90, 'h', 'i', 0}; - SerdNode* s = serd_new_uri(serd_string("http://example.org/s")); - SerdNode* p = serd_new_uri(serd_string("http://example.org/p")); + SerdNode* s = serd_new_uri(NULL, serd_string("http://example.org/s")); + SerdNode* p = serd_new_uri(NULL, serd_string("http://example.org/p")); - SerdNode* bad_lit = serd_new_string(serd_string((const char*)bad_str)); - SerdNode* bad_uri = serd_new_uri(serd_string((const char*)bad_str)); + SerdNode* bad_lit = serd_new_string(NULL, serd_string((const char*)bad_str)); + SerdNode* bad_uri = serd_new_uri(NULL, serd_string((const char*)bad_str)); assert(serd_sink_write(sink, 0, s, p, bad_lit, NULL) == SERD_BAD_TEXT); assert(serd_sink_write(sink, 0, s, p, bad_uri, NULL) == SERD_BAD_TEXT); - serd_node_free(bad_uri); - serd_node_free(bad_lit); - serd_node_free(p); - serd_node_free(s); + serd_node_free(NULL, bad_uri); + serd_node_free(NULL, bad_lit); + serd_node_free(NULL, p); + serd_node_free(NULL, s); serd_writer_free(writer); serd_env_free(env); serd_world_free(world); @@ -224,15 +317,14 @@ error_sink(const void* const buf, static void test_write_error(void) { - SerdWorld* const world = serd_world_new(); - SerdEnv* const env = serd_env_new(serd_empty_string()); + SerdWorld* const world = serd_world_new(NULL); + SerdEnv* const env = serd_env_new(NULL, serd_empty_string()); SerdOutputStream out = serd_open_output_stream(error_sink, NULL, NULL, NULL); - SerdWriter* writer = NULL; - SerdStatus st = SERD_SUCCESS; + SerdStatus st = SERD_SUCCESS; - SerdNode* u = serd_new_uri(serd_string("http://example.com/u")); + SerdNode* u = serd_new_uri(NULL, serd_string("http://example.com/u")); - writer = + SerdWriter* const writer = serd_writer_new(world, SERD_TURTLE, (SerdWriterFlags)0, env, &out, 1U); assert(writer); @@ -242,7 +334,7 @@ test_write_error(void) assert(st == SERD_BAD_WRITE); serd_writer_free(writer); - serd_node_free(u); + serd_node_free(NULL, u); serd_env_free(env); serd_world_free(world); } @@ -250,8 +342,8 @@ test_write_error(void) static void test_writer_stack_overflow(void) { - SerdWorld* world = serd_world_new(); - SerdEnv* env = serd_env_new(serd_empty_string()); + SerdWorld* world = serd_world_new(NULL); + SerdEnv* env = serd_env_new(NULL, serd_empty_string()); SerdOutputStream output = serd_open_output_stream(null_sink, NULL, NULL, NULL); @@ -261,10 +353,10 @@ test_writer_stack_overflow(void) const SerdSink* sink = serd_writer_sink(writer); - SerdNode* const s = serd_new_uri(serd_string("http://example.org/s")); - SerdNode* const p = serd_new_uri(serd_string("http://example.org/p")); + SerdNode* const s = serd_new_uri(NULL, serd_string("http://example.org/s")); + SerdNode* const p = serd_new_uri(NULL, serd_string("http://example.org/p")); - SerdNode* o = serd_new_blank(serd_string("blank")); + SerdNode* o = serd_new_blank(NULL, serd_string("blank")); SerdStatus st = serd_sink_write(sink, SERD_ANON_O, s, p, o, NULL); assert(!st); @@ -273,11 +365,11 @@ test_writer_stack_overflow(void) char buf[1024]; snprintf(buf, sizeof(buf), "b%u", i); - SerdNode* next_o = serd_new_blank(serd_string(buf)); + SerdNode* next_o = serd_new_blank(NULL, serd_string(buf)); st = serd_sink_write(sink, SERD_ANON_O, o, p, next_o, NULL); - serd_node_free(o); + serd_node_free(NULL, o); o = next_o; if (st) { @@ -288,9 +380,9 @@ test_writer_stack_overflow(void) assert(st == SERD_BAD_STACK); - serd_node_free(o); - serd_node_free(p); - serd_node_free(s); + serd_node_free(NULL, o); + serd_node_free(NULL, p); + serd_node_free(NULL, s); serd_writer_free(writer); serd_close_output(&output); serd_env_free(env); @@ -300,14 +392,14 @@ test_writer_stack_overflow(void) static void test_write_empty_syntax(void) { - SerdWorld* world = serd_world_new(); - SerdEnv* env = serd_env_new(serd_empty_string()); + SerdWorld* world = serd_world_new(NULL); + SerdEnv* env = serd_env_new(NULL, serd_empty_string()); - SerdNode* s = serd_new_uri(serd_string("http://example.org/s")); - SerdNode* p = serd_new_uri(serd_string("http://example.org/p")); - SerdNode* o = serd_new_uri(serd_string("http://example.org/o")); + SerdNode* s = serd_new_uri(NULL, serd_string("http://example.org/s")); + SerdNode* p = serd_new_uri(NULL, serd_string("http://example.org/p")); + SerdNode* o = serd_new_uri(NULL, serd_string("http://example.org/o")); - SerdBuffer buffer = {NULL, 0}; + SerdBuffer buffer = {NULL, NULL, 0}; SerdOutputStream output = serd_open_output_buffer(&buffer); SerdWriter* writer = @@ -321,12 +413,12 @@ test_write_empty_syntax(void) char* const out = (char*)buffer.buf; assert(out); assert(strlen(out) == 0); - serd_free(out); + serd_free(NULL, buffer.buf); serd_writer_free(writer); - serd_node_free(o); - serd_node_free(p); - serd_node_free(s); + serd_node_free(NULL, o); + serd_node_free(NULL, p); + serd_node_free(NULL, s); serd_close_output(&output); serd_env_free(env); serd_world_free(world); @@ -335,9 +427,9 @@ test_write_empty_syntax(void) static void check_pname_escape(const char* const lname, const char* const expected) { - SerdWorld* world = serd_world_new(); - SerdEnv* env = serd_env_new(serd_empty_string()); - SerdBuffer buffer = {NULL, 0}; + SerdWorld* world = serd_world_new(NULL); + SerdEnv* env = serd_env_new(NULL, serd_empty_string()); + SerdBuffer buffer = {NULL, NULL, 0}; SerdOutputStream output = serd_open_output_buffer(&buffer); SerdWriter* writer = @@ -349,20 +441,20 @@ check_pname_escape(const char* const lname, const char* const expected) serd_env_set_prefix(env, serd_string("eg"), serd_string(prefix)); - SerdNode* s = serd_new_uri(serd_string("http://example.org/s")); - SerdNode* p = serd_new_uri(serd_string("http://example.org/p")); + SerdNode* s = serd_new_uri(NULL, serd_string("http://example.org/s")); + SerdNode* p = serd_new_uri(NULL, serd_string("http://example.org/p")); char* const uri = (char*)calloc(1, prefix_len + strlen(lname) + 1); memcpy(uri, prefix, prefix_len + 1); memcpy(uri + prefix_len, lname, strlen(lname) + 1); - SerdNode* node = serd_new_uri(serd_string(uri)); + SerdNode* node = serd_new_uri(NULL, serd_string(uri)); assert(!serd_sink_write(serd_writer_sink(writer), 0, s, p, node, NULL)); - serd_node_free(node); + serd_node_free(NULL, node); free(uri); - serd_node_free(p); - serd_node_free(s); + serd_node_free(NULL, p); + serd_node_free(NULL, s); serd_writer_free(writer); serd_close_output(&output); serd_env_free(env); @@ -370,7 +462,7 @@ check_pname_escape(const char* const lname, const char* const expected) char* const out = (char*)buffer.buf; assert(!strcmp(out, expected)); - serd_free(out); + serd_free(NULL, buffer.buf); serd_world_free(world); } @@ -409,12 +501,13 @@ test_write_pname_escapes(void) static void test_write_bad_uri(void) { - SerdWorld* world = serd_world_new(); - SerdEnv* env = serd_env_new(serd_empty_string()); - SerdNode* s = serd_new_uri(serd_string("http://example.org/s")); - SerdNode* p = serd_new_uri(serd_string("http://example.org/p")); - SerdNode* rel = serd_new_uri(serd_string("rel")); - SerdBuffer buffer = {NULL, 0}; + SerdWorld* world = serd_world_new(NULL); + SerdEnv* env = serd_env_new(NULL, serd_empty_string()); + SerdNode* s = serd_new_uri(NULL, serd_string("http://example.org/s")); + SerdNode* p = serd_new_uri(NULL, serd_string("http://example.org/p")); + SerdNode* rel = serd_new_uri(NULL, serd_string("rel")); + + SerdBuffer buffer = {NULL, NULL, 0}; SerdOutputStream output = serd_open_output_buffer(&buffer); SerdWriter* writer = serd_writer_new(world, SERD_NTRIPLES, 0U, env, &output, 1U); @@ -429,10 +522,10 @@ test_write_bad_uri(void) serd_writer_free(writer); serd_close_output(&output); - serd_free(buffer.buf); - serd_node_free(rel); - serd_node_free(p); - serd_node_free(s); + serd_free(NULL, buffer.buf); + serd_node_free(NULL, rel); + serd_node_free(NULL, p); + serd_node_free(NULL, s); serd_env_free(env); serd_world_free(world); } @@ -441,6 +534,8 @@ int main(void) { test_writer_new(); + test_new_failed_alloc(); + test_write_failed_alloc(); test_write_bad_event(); test_write_long_literal(); test_writer_cleanup(); |