aboutsummaryrefslogtreecommitdiffstats
path: root/test/test_reader.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_reader.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_reader.c')
-rw-r--r--test/test_reader.c144
1 files changed, 111 insertions, 33 deletions
diff --git a/test/test_reader.c b/test/test_reader.c
index f1ec1d35..a0eaee5c 100644
--- a/test/test_reader.c
+++ b/test/test_reader.c
@@ -3,6 +3,8 @@
#undef NDEBUG
+#include "failing_allocator.h"
+
#include "serd/caret.h"
#include "serd/env.h"
#include "serd/event.h"
@@ -60,6 +62,81 @@ test_sink(void* handle, const SerdEvent* event)
return SERD_SUCCESS;
}
+static void
+test_new_failed_alloc(void)
+{
+ SerdFailingAllocator allocator = serd_failing_allocator();
+
+ SerdWorld* const world = serd_world_new(&allocator.base);
+ SerdEnv* const env = serd_env_new(&allocator.base, serd_empty_string());
+ size_t ignored = 0U;
+ SerdSink* const sink =
+ serd_sink_new(&allocator.base, &ignored, test_sink, NULL);
+
+ // Successfully allocate a reader to count the number of allocations
+ const size_t n_world_allocs = allocator.n_allocations;
+ SerdReader* reader = serd_reader_new(world, SERD_TURTLE, 0U, env, sink);
+ assert(reader);
+
+ // 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_reader_new(world, SERD_TURTLE, 0U, env, sink));
+ }
+
+ serd_reader_free(reader);
+ serd_env_free(env);
+ serd_sink_free(sink);
+ serd_world_free(world);
+}
+
+static void
+test_start_failed_alloc(const char* const path)
+{
+ SerdFailingAllocator allocator = serd_failing_allocator();
+
+ FILE* const f = fopen(path, "w+b");
+ assert(f);
+
+ fprintf(f, "_:s <http://example.org/p> _:o .\n");
+ fflush(f);
+ fseek(f, 0L, SEEK_SET);
+
+ SerdWorld* world = serd_world_new(&allocator.base);
+ SerdEnv* env = serd_env_new(&allocator.base, serd_empty_string());
+ size_t ignored = 0U;
+ SerdSink* sink = serd_sink_new(&allocator.base, &ignored, test_sink, NULL);
+ SerdReader* reader = serd_reader_new(world, SERD_TURTLE, 0U, env, sink);
+ assert(reader);
+
+ SerdInputStream in =
+ serd_open_input_stream((SerdReadFunc)fread, (SerdErrorFunc)ferror, NULL, f);
+
+ // Successfully start a new read to count the number of allocations
+ const size_t n_setup_allocs = allocator.n_allocations;
+ assert(serd_reader_start(reader, &in, NULL, 4096) == SERD_SUCCESS);
+
+ // Test that each allocation failing is handled gracefully
+ const size_t n_new_allocs = allocator.n_allocations - n_setup_allocs;
+ assert(!serd_reader_finish(reader));
+ for (size_t i = 0; i < n_new_allocs; ++i) {
+ allocator.n_remaining = i;
+
+ in = serd_open_input_stream(
+ (SerdReadFunc)fread, (SerdErrorFunc)ferror, NULL, f);
+
+ SerdStatus st = serd_reader_start(reader, &in, NULL, 4096);
+ assert(st == SERD_BAD_ALLOC);
+ }
+
+ serd_reader_free(reader);
+ serd_env_free(env);
+ serd_sink_free(sink);
+ serd_world_free(world);
+ fclose(f);
+}
+
ZIX_PURE_FUNC static size_t
prepare_test_read(void* buf, size_t size, size_t nmemb, void* stream)
{
@@ -84,7 +161,7 @@ prepare_test_error(void* stream)
static void
test_prepare_error(const char* const path)
{
- SerdWorld* const world = serd_world_new();
+ SerdWorld* const world = serd_world_new(NULL);
ReaderTest rt = {0, 0, 0, 0};
FILE* const f = fopen(path, "w+b");
@@ -94,12 +171,11 @@ test_prepare_error(const char* const path)
fflush(f);
fseek(f, 0L, SEEK_SET);
- SerdSink* const sink = serd_sink_new(&rt, test_sink, NULL);
+ SerdSink* const sink = serd_sink_new(NULL, &rt, test_sink, NULL);
assert(sink);
- SerdEnv* const env = serd_env_new(serd_empty_string());
+ SerdEnv* const env = serd_env_new(NULL, serd_empty_string());
SerdReader* const reader = serd_reader_new(world, SERD_TURTLE, 0, env, sink);
-
assert(reader);
SerdInputStream in =
@@ -124,14 +200,13 @@ test_prepare_error(const char* const path)
static void
test_read_string(void)
{
- SerdWorld* world = serd_world_new();
+ SerdWorld* world = serd_world_new(NULL);
ReaderTest rt = {0, 0, 0, 0};
- SerdSink* sink = serd_sink_new(&rt, test_sink, NULL);
+ SerdSink* sink = serd_sink_new(NULL, &rt, test_sink, NULL);
assert(sink);
- SerdEnv* const env = serd_env_new(serd_empty_string());
+ SerdEnv* const env = serd_env_new(NULL, serd_empty_string());
SerdReader* const reader = serd_reader_new(world, SERD_TURTLE, 0U, env, sink);
-
assert(reader);
static const char* const string1 =
@@ -228,11 +303,12 @@ test_read_eof_by_page(const char* const path)
fflush(f);
fseek(f, 0L, SEEK_SET);
- SerdWorld* world = serd_world_new();
- ReaderTest ignored = {0, 0, 0, 0};
- SerdSink* sink = serd_sink_new(&ignored, test_sink, NULL);
- SerdEnv* env = serd_env_new(serd_empty_string());
- SerdReader* reader = serd_reader_new(world, SERD_TURTLE, 0U, env, sink);
+ SerdWorld* const world = serd_world_new(NULL);
+ ReaderTest rt = {0, 0, 0, 0};
+ SerdSink* const sink = serd_sink_new(NULL, &rt, test_sink, NULL);
+ SerdEnv* const env = serd_env_new(NULL, serd_empty_string());
+ SerdReader* reader = serd_reader_new(world, SERD_TURTLE, 0U, env, sink);
+
SerdInputStream in =
serd_open_input_stream((SerdReadFunc)fread, (SerdErrorFunc)ferror, NULL, f);
@@ -255,11 +331,11 @@ test_read_eof_by_page(const char* const path)
static void
test_read_eof_by_byte(void)
{
- SerdWorld* world = serd_world_new();
- ReaderTest ignored = {0, 0, 0, 0};
- SerdSink* sink = serd_sink_new(&ignored, test_sink, NULL);
- SerdEnv* env = serd_env_new(serd_empty_string());
- SerdReader* reader = serd_reader_new(world, SERD_TURTLE, 0U, env, sink);
+ SerdWorld* const world = serd_world_new(NULL);
+ ReaderTest rt = {0, 0, 0, 0};
+ SerdSink* const sink = serd_sink_new(NULL, &rt, test_sink, NULL);
+ SerdEnv* const env = serd_env_new(NULL, serd_empty_string());
+ SerdReader* reader = serd_reader_new(world, SERD_TURTLE, 0U, env, sink);
size_t n_reads = 0U;
SerdInputStream in = serd_open_input_stream(
@@ -305,12 +381,12 @@ test_read_nquads_chunks(const char* const path)
fseek(f, 0, SEEK_SET);
- SerdWorld* const world = serd_world_new();
+ SerdWorld* const world = serd_world_new(NULL);
ReaderTest rt = {0, 0, 0, 0};
- SerdSink* const sink = serd_sink_new(&rt, test_sink, NULL);
+ SerdSink* const sink = serd_sink_new(NULL, &rt, test_sink, NULL);
assert(sink);
- SerdEnv* const env = serd_env_new(serd_empty_string());
+ SerdEnv* const env = serd_env_new(NULL, serd_empty_string());
assert(env);
SerdReader* const reader = serd_reader_new(world, SERD_TURTLE, 0U, env, sink);
@@ -391,12 +467,12 @@ 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 = {0, 0, 0, 0};
- SerdSink* sink = serd_sink_new(&rt, test_sink, NULL);
+ SerdWorld* const world = serd_world_new(NULL);
+ ReaderTest rt = {0, 0, 0, 0};
+ SerdSink* const sink = serd_sink_new(NULL, &rt, test_sink, NULL);
assert(sink);
- SerdEnv* const env = serd_env_new(serd_empty_string());
+ SerdEnv* const env = serd_env_new(NULL, serd_empty_string());
assert(env);
SerdReader* const reader = serd_reader_new(world, SERD_TURTLE, 0U, env, sink);
@@ -479,13 +555,13 @@ test_read_turtle_chunks(const char* const path)
static void
test_read_empty(const char* const path)
{
- SerdWorld* const world = serd_world_new();
+ SerdWorld* const world = serd_world_new(NULL);
ReaderTest rt = {0, 0, 0, 0};
- SerdSink* const sink = serd_sink_new(&rt, test_sink, NULL);
+ SerdSink* const sink = serd_sink_new(NULL, &rt, test_sink, NULL);
assert(sink);
- SerdEnv* const env = serd_env_new(serd_empty_string());
+ SerdEnv* const env = serd_env_new(NULL, serd_empty_string());
assert(env);
SerdReader* const reader =
@@ -536,10 +612,10 @@ check_cursor(void* handle, const SerdEvent* event)
static void
test_error_cursor(void)
{
- SerdWorld* world = serd_world_new();
+ SerdWorld* const world = serd_world_new(NULL);
bool called = false;
- SerdSink* sink = serd_sink_new(&called, check_cursor, NULL);
- SerdEnv* const env = serd_env_new(serd_empty_string());
+ SerdSink* const sink = serd_sink_new(NULL, &called, check_cursor, NULL);
+ SerdEnv* const env = serd_env_new(NULL, serd_empty_string());
SerdReader* const reader = serd_reader_new(world, SERD_TURTLE, 0U, env, sink);
assert(sink);
assert(reader);
@@ -548,7 +624,7 @@ test_error_cursor(void)
"<http://example.org/s> <http://example.org/p> "
"<http://example.org/o> .";
- SerdNode* const string_name = serd_new_string(serd_string("string"));
+ SerdNode* const string_name = serd_new_string(NULL, serd_string("string"));
const char* position = string;
SerdInputStream in = serd_open_input_string(&position);
@@ -559,7 +635,7 @@ test_error_cursor(void)
assert(called);
assert(!serd_close_input(&in));
- serd_node_free(string_name);
+ serd_node_free(NULL, string_name);
serd_reader_free(reader);
serd_env_free(env);
serd_sink_free(sink);
@@ -575,6 +651,8 @@ main(void)
char* const ttl_path = zix_path_join(NULL, dir, "serd_test_reader.ttl");
char* const nq_path = zix_path_join(NULL, dir, "serd_test_reader.nq");
+ test_new_failed_alloc();
+ test_start_failed_alloc(ttl_path);
test_read_nquads_chunks(nq_path);
test_read_turtle_chunks(ttl_path);
test_prepare_error(ttl_path);