aboutsummaryrefslogtreecommitdiffstats
path: root/test
diff options
context:
space:
mode:
authorDavid Robillard <d@drobilla.net>2021-07-22 18:35:31 -0400
committerDavid Robillard <d@drobilla.net>2022-01-14 19:37:51 -0500
commit955be33cead7596506cf86211da6b0e53827ef96 (patch)
tree0dac1a7a31e8c50d1ba7200648d6ce402f97867d /test
parent34852e8faa380f12b11522cfa998df4f260e3856 (diff)
downloadserd-955be33cead7596506cf86211da6b0e53827ef96.tar.gz
serd-955be33cead7596506cf86211da6b0e53827ef96.tar.bz2
serd-955be33cead7596506cf86211da6b0e53827ef96.zip
Avoid dynamic allocation when fetching interned nodes
This is more or less a total rewrite of SerdNodes and the underlying ZixHash to make efficient use of the new node construction API.
Diffstat (limited to 'test')
-rw-r--r--test/test_nodes.c282
1 files changed, 256 insertions, 26 deletions
diff --git a/test/test_nodes.c b/test/test_nodes.c
index 74c99c11..c841acc4 100644
--- a/test/test_nodes.c
+++ b/test/test_nodes.c
@@ -19,9 +19,12 @@
#include "serd/serd.h"
#include <assert.h>
+#include <stdbool.h>
#include <stddef.h>
#include <string.h>
+#define NS_XSD "http://www.w3.org/2001/XMLSchema#"
+
static void
test_intern(void)
{
@@ -45,24 +48,6 @@ test_intern(void)
}
static void
-test_manage(void)
-{
- SerdNodes* nodes = serd_nodes_new();
- SerdNode* node = serd_new_string(SERD_STRING("node"));
-
- assert(!serd_nodes_manage(nodes, NULL));
-
- const SerdNode* managed1 = serd_nodes_manage(nodes, node);
- assert(managed1 == node);
-
- SerdNode* equal = serd_new_string(SERD_STRING("node"));
- const SerdNode* managed2 = serd_nodes_manage(nodes, equal);
- assert(managed2 == node);
-
- serd_nodes_free(nodes);
-}
-
-static void
test_string(void)
{
static const SerdStringView string = SERD_STRING("string");
@@ -81,6 +66,29 @@ test_string(void)
}
static void
+test_invalid_literal(void)
+{
+ SerdNodes* const nodes = serd_nodes_new();
+
+ assert(!serd_nodes_literal(nodes,
+ SERD_STRING("double meta"),
+ SERD_HAS_LANGUAGE | SERD_HAS_DATATYPE,
+ SERD_STRING("What am I?")));
+
+ assert(!serd_nodes_literal(nodes,
+ SERD_STRING("empty language"),
+ SERD_HAS_LANGUAGE,
+ SERD_EMPTY_STRING()));
+
+ assert(!serd_nodes_literal(nodes,
+ SERD_STRING("empty datatype"),
+ SERD_HAS_DATATYPE,
+ SERD_EMPTY_STRING()));
+
+ serd_nodes_free(nodes);
+}
+
+static void
test_plain_literal(void)
{
static const SerdStringView string = SERD_STRING("string");
@@ -102,6 +110,24 @@ test_plain_literal(void)
assert(serd_node_length(node) == string.len);
assert(!strcmp(serd_node_string(node), string.buf));
+ const SerdNode* const alias =
+ serd_nodes_literal(nodes, string, SERD_HAS_LANGUAGE, language);
+
+ assert(alias == node);
+
+ const SerdNode* const other =
+ serd_nodes_literal(nodes, string, SERD_HAS_LANGUAGE, SERD_STRING("de"));
+
+ assert(other != node);
+
+ const SerdNode* const other_language_node = serd_node_language(other);
+ assert(other_language_node);
+ assert(serd_node_type(other_language_node) == SERD_LITERAL);
+ assert(serd_node_length(other_language_node) == 2);
+ assert(!strcmp(serd_node_string(other_language_node), "de"));
+ assert(serd_node_length(other) == string.len);
+ assert(!strcmp(serd_node_string(other), string.buf));
+
serd_nodes_free(nodes);
}
@@ -128,6 +154,152 @@ test_typed_literal(void)
assert(serd_node_length(node) == string.len);
assert(!strcmp(serd_node_string(node), string.buf));
+ const SerdNode* const alias =
+ serd_nodes_literal(nodes, string, SERD_HAS_DATATYPE, datatype);
+
+ assert(alias == node);
+
+ serd_nodes_free(nodes);
+}
+
+static void
+test_boolean(void)
+{
+ SerdNodes* const nodes = serd_nodes_new();
+
+ const SerdNode* const false1 = serd_nodes_boolean(nodes, false);
+ const SerdNode* const false2 = serd_nodes_boolean(nodes, false);
+ const SerdNode* const true1 = serd_nodes_boolean(nodes, true);
+ const SerdNode* const true2 = serd_nodes_boolean(nodes, true);
+
+ assert(false1 == false2);
+ assert(true1 == true2);
+ assert(false1 != true1);
+ assert(!strcmp(serd_node_string(false1), "false"));
+ assert(!strcmp(serd_node_string(true1), "true"));
+ assert(serd_node_length(false1) == strlen(serd_node_string(false1)));
+ assert(serd_node_length(true1) == strlen(serd_node_string(true1)));
+ assert(serd_nodes_size(nodes) == 2);
+
+ const SerdNode* const true_datatype = serd_node_datatype(true1);
+ assert(true_datatype);
+ assert(!strcmp(serd_node_string(true_datatype), NS_XSD "boolean"));
+
+ const SerdNode* const false_datatype = serd_node_datatype(false1);
+ assert(false_datatype);
+ assert(!strcmp(serd_node_string(false_datatype), NS_XSD "boolean"));
+
+ serd_nodes_free(nodes);
+}
+
+static void
+test_decimal(void)
+{
+ SerdNodes* const nodes = serd_nodes_new();
+ const SerdNode* const a = serd_nodes_decimal(nodes, -12.3456789);
+ const SerdNode* const b = serd_nodes_decimal(nodes, -12.3456789);
+
+ assert(a == b);
+ assert(!strcmp(serd_node_string(a), "-12.3456789"));
+ assert(serd_node_length(a) == strlen(serd_node_string(a)));
+ assert(serd_nodes_size(nodes) == 1);
+
+ const SerdNode* const default_datatype = serd_node_datatype(a);
+ assert(default_datatype);
+ assert(!strcmp(serd_node_string(default_datatype), NS_XSD "decimal"));
+
+ serd_nodes_free(nodes);
+}
+
+static void
+test_double(void)
+{
+ SerdNodes* const nodes = serd_nodes_new();
+
+ const SerdNode* const a = serd_nodes_double(nodes, -1.2E3);
+ const SerdNode* const b = serd_nodes_double(nodes, -1.2E3);
+
+ assert(a == b);
+ assert(!strcmp(serd_node_string(a), "-1.2E3"));
+ assert(serd_node_length(a) == strlen(serd_node_string(a)));
+ assert(serd_nodes_size(nodes) == 1);
+
+ serd_nodes_free(nodes);
+}
+
+static void
+test_float(void)
+{
+ SerdNodes* const nodes = serd_nodes_new();
+
+ const SerdNode* const a = serd_nodes_float(nodes, -1.2E3f);
+ const SerdNode* const b = serd_nodes_float(nodes, -1.2E3f);
+
+ assert(a == b);
+ assert(!strcmp(serd_node_string(a), "-1.2E3"));
+ assert(serd_node_length(a) == strlen(serd_node_string(a)));
+ assert(serd_nodes_size(nodes) == 1);
+
+ serd_nodes_free(nodes);
+}
+
+static void
+test_integer(void)
+{
+ SerdNodes* const nodes = serd_nodes_new();
+
+ const SerdNode* const a =
+ serd_nodes_integer(nodes, -1234567890, SERD_EMPTY_STRING());
+
+ const SerdNode* const b =
+ serd_nodes_integer(nodes, -1234567890, SERD_EMPTY_STRING());
+
+ assert(a == b);
+ assert(!strcmp(serd_node_string(a), "-1234567890"));
+ assert(serd_node_length(a) == strlen(serd_node_string(a)));
+ assert(serd_nodes_size(nodes) == 1);
+
+ const SerdNode* const default_datatype = serd_node_datatype(a);
+ assert(default_datatype);
+ assert(!strcmp(serd_node_string(default_datatype), NS_XSD "integer"));
+
+ serd_nodes_free(nodes);
+}
+
+static void
+test_base64(void)
+{
+ static const char data[] = {'f', 'o', 'o', 'b', 'a', 'r'};
+
+ SerdNodes* const nodes = serd_nodes_new();
+
+ const SerdNode* const a =
+ serd_nodes_base64(nodes, &data, sizeof(data), SERD_EMPTY_STRING());
+
+ const SerdNode* const b =
+ serd_nodes_base64(nodes, &data, sizeof(data), SERD_EMPTY_STRING());
+
+ assert(a == b);
+ assert(!strcmp(serd_node_string(a), "Zm9vYmFy"));
+ assert(serd_node_length(a) == strlen(serd_node_string(a)));
+ assert(serd_nodes_size(nodes) == 1);
+
+ const SerdNode* const default_datatype = serd_node_datatype(a);
+ assert(default_datatype);
+ assert(!strcmp(serd_node_string(default_datatype), NS_XSD "base64Binary"));
+
+ const SerdStringView user_datatype =
+ SERD_STRING("http://example.org/UserDatatype");
+
+ const SerdNode* const custom =
+ serd_nodes_base64(nodes, &data, sizeof(data), user_datatype);
+ assert(custom);
+ assert(!strcmp(serd_node_string(custom), "Zm9vYmFy"));
+
+ const SerdNode* const custom_datatype = serd_node_datatype(custom);
+ assert(custom_datatype);
+ assert(!strcmp(serd_node_string(custom_datatype), user_datatype.buf));
+
serd_nodes_free(nodes);
}
@@ -150,6 +322,34 @@ test_uri(void)
}
static void
+test_parsed_uri(void)
+{
+ static const SerdStringView string = SERD_STRING("http://example.org/");
+
+ SerdNodes* const nodes = serd_nodes_new();
+ const SerdURIView uri = serd_parse_uri(string.buf);
+ const SerdNode* const node = serd_nodes_parsed_uri(nodes, uri);
+
+ assert(node);
+ assert(serd_node_type(node) == SERD_URI);
+ assert(!serd_node_flags(node));
+ assert(!serd_node_datatype(node));
+ assert(!serd_node_language(node));
+ assert(serd_node_length(node) == string.len);
+ assert(!strcmp(serd_node_string(node), string.buf));
+
+ const SerdNode* const alias = serd_nodes_parsed_uri(nodes, uri);
+ assert(alias == node);
+
+ const SerdNode* const other =
+ serd_nodes_parsed_uri(nodes, serd_parse_uri("http://example.org/x"));
+
+ assert(other != node);
+
+ serd_nodes_free(nodes);
+}
+
+static void
test_blank(void)
{
static const SerdStringView string = SERD_STRING("b42");
@@ -170,17 +370,40 @@ test_blank(void)
static void
test_deref(void)
{
- SerdNodes* nodes = serd_nodes_new();
- const SerdNode* managed = serd_nodes_string(nodes, SERD_STRING("node"));
+ SerdNodes* nodes = serd_nodes_new();
+ const SerdNode* original = serd_nodes_string(nodes, SERD_STRING("node"));
+ const SerdNode* another = serd_nodes_string(nodes, SERD_STRING("node"));
- serd_nodes_deref(nodes, managed);
+ assert(original == another);
- SerdNode* node = serd_new_string(SERD_STRING("node"));
- const SerdNode* interned = serd_nodes_intern(nodes, node);
+ // Dereference the original and ensure the other reference kept it alive
+ serd_nodes_deref(nodes, original);
+ assert(serd_node_length(another) == 4);
+ assert(!strcmp(serd_node_string(another), "node"));
- assert(interned != node);
+ // Drop the other/final reference (freeing the node)
+ serd_nodes_deref(nodes, another);
- serd_node_free(node);
+ /* Intern some other irrelevant node first to (hopefully) avoid the allocator
+ just giving us back the same piece of memory. */
+
+ const SerdNode* other = serd_nodes_string(nodes, SERD_STRING("XXXX"));
+ assert(!strcmp(serd_node_string(other), "XXXX"));
+
+ // Intern a new equivalent node to the original and check that it's really new
+ const SerdNode* imposter = serd_nodes_string(nodes, SERD_STRING("node"));
+ assert(imposter != original);
+ assert(serd_node_length(imposter) == 4);
+ assert(!strcmp(serd_node_string(imposter), "node"));
+
+ // Check that dereferencing some random unknown node doesn't crash
+ SerdNode* unmanaged = serd_new_string(SERD_STRING("unmanaged"));
+ serd_nodes_deref(nodes, unmanaged);
+ serd_node_free(unmanaged);
+
+ serd_nodes_deref(nodes, NULL);
+ serd_nodes_deref(nodes, imposter);
+ serd_nodes_deref(nodes, other);
serd_nodes_free(nodes);
}
@@ -205,11 +428,18 @@ int
main(void)
{
test_intern();
- test_manage();
test_string();
+ test_invalid_literal();
test_plain_literal();
test_typed_literal();
+ test_boolean();
+ test_decimal();
+ test_double();
+ test_float();
+ test_integer();
+ test_base64();
test_uri();
+ test_parsed_uri();
test_blank();
test_deref();
test_get();