aboutsummaryrefslogtreecommitdiffstats
path: root/test/test_writer.c
diff options
context:
space:
mode:
authorDavid Robillard <d@drobilla.net>2023-09-10 15:06:42 -0400
committerDavid Robillard <d@drobilla.net>2023-12-02 18:49:08 -0500
commit248a874d7425749d29cf900a1c3783c624ea8d8c (patch)
treeaed59f5a484a815cd254506866e98a947858904d /test/test_writer.c
parent0bd10132c6707353dba80bd89cf0102ee7ca4e34 (diff)
downloadserd-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.c269
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();