aboutsummaryrefslogtreecommitdiffstats
path: root/test
diff options
context:
space:
mode:
authorDavid Robillard <d@drobilla.net>2023-03-24 20:59:54 -0400
committerDavid Robillard <d@drobilla.net>2023-12-02 18:49:07 -0500
commit65cbb4a13f615658282677fcf04685bae63e893c (patch)
treeb9c66e757cf28ce96906d3426300811645753173 /test
parentc661dbe50d7f634ec5b2863260f41f098fc9c882 (diff)
downloadserd-65cbb4a13f615658282677fcf04685bae63e893c.tar.gz
serd-65cbb4a13f615658282677fcf04685bae63e893c.tar.bz2
serd-65cbb4a13f615658282677fcf04685bae63e893c.zip
Support writing all escapes in Turtle and TriG prefixed names
Diffstat (limited to 'test')
-rw-r--r--test/extra/qualify/qualify-in.ttl3
-rw-r--r--test/extra/qualify/qualify-out.ttl7
-rw-r--r--test/test_writer.c74
3 files changed, 82 insertions, 2 deletions
diff --git a/test/extra/qualify/qualify-in.ttl b/test/extra/qualify/qualify-in.ttl
index 04afc07f..b30e1721 100644
--- a/test/extra/qualify/qualify-in.ttl
+++ b/test/extra/qualify/qualify-in.ttl
@@ -6,5 +6,8 @@
<http://example.org/a-subject>
<http://example.org/a-predicate> <http://example.org/a-object> .
+<http://example.org/special-!#$%&'()*+,-./;=?@_~-chars>
+ <http://example.org/p> <http://example.org/o> .
+
<http://www.w3.org/1999/02/22-rdf-syntax-ns#nil>
<http://www.w3.org/2000/01/rdf-schema#label> "nil" .
diff --git a/test/extra/qualify/qualify-out.ttl b/test/extra/qualify/qualify-out.ttl
index f4dd15d4..79148017 100644
--- a/test/extra/qualify/qualify-out.ttl
+++ b/test/extra/qualify/qualify-out.ttl
@@ -3,8 +3,11 @@
eg:s
eg:p eg:o .
-<http://example.org/a-subject>
- <http://example.org/a-predicate> <http://example.org/a-object> .
+eg:a-subject
+ eg:a-predicate eg:a-object .
+
+eg:special-\!\#\$\%\&\'\(\)\*\+\,-.\/\;\=\?\@_\~-chars
+ eg:p eg:o .
()
<http://www.w3.org/2000/01/rdf-schema#label> "nil" .
diff --git a/test/test_writer.c b/test/test_writer.c
index 6066b6e3..a4d92c5b 100644
--- a/test/test_writer.c
+++ b/test/test_writer.c
@@ -19,6 +19,7 @@
#include <assert.h>
#include <stdint.h>
#include <stdio.h>
+#include <stdlib.h>
#include <string.h>
static void
@@ -325,6 +326,78 @@ test_write_empty_syntax(void)
serd_world_free(world);
}
+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};
+
+ SerdWriter* writer =
+ serd_writer_new(world, SERD_TURTLE, 0U, env, serd_buffer_sink, &buffer);
+
+ assert(writer);
+
+ static const char* const prefix = "http://example.org/";
+ const size_t prefix_len = strlen(prefix);
+
+ 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"));
+
+ 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));
+ assert(!serd_sink_write(serd_writer_sink(writer), 0, s, p, node, NULL));
+ serd_node_free(node);
+
+ free(uri);
+ serd_node_free(p);
+ serd_node_free(s);
+ serd_writer_free(writer);
+ serd_env_free(env);
+
+ char* out = serd_buffer_sink_finish(&buffer);
+ assert(!strcmp((char*)out, expected));
+ serd_free(out);
+
+ serd_world_free(world);
+}
+
+static void
+test_write_pname_escapes(void)
+{
+ // Check that '.' is escaped only at the start and end
+ check_pname_escape(".xyz", "eg:s\n\teg:p eg:\\.xyz .\n");
+ check_pname_escape("w.yz", "eg:s\n\teg:p eg:w.yz .\n");
+ check_pname_escape("wx.z", "eg:s\n\teg:p eg:wx.z .\n");
+ check_pname_escape("wxy.", "eg:s\n\teg:p eg:wxy\\. .\n");
+
+ // Check that ':' is not escaped anywhere
+ check_pname_escape(":xyz", "eg:s\n\teg:p eg::xyz .\n");
+ check_pname_escape("w:yz", "eg:s\n\teg:p eg:w:yz .\n");
+ check_pname_escape("wx:z", "eg:s\n\teg:p eg:wx:z .\n");
+ check_pname_escape("wxy:", "eg:s\n\teg:p eg:wxy: .\n");
+
+ // Check that special characters like '~' are escaped everywhere
+ check_pname_escape("~xyz", "eg:s\n\teg:p eg:\\~xyz .\n");
+ check_pname_escape("w~yz", "eg:s\n\teg:p eg:w\\~yz .\n");
+ check_pname_escape("wx~z", "eg:s\n\teg:p eg:wx\\~z .\n");
+ check_pname_escape("wxy~", "eg:s\n\teg:p eg:wxy\\~ .\n");
+
+ // Check that out of range multi-byte characters are escaped everywhere
+ static const char first_escape[] = {(char)0xC3U, (char)0xB7U, 'y', 'z', 0};
+ static const char mid_escape[] = {'w', (char)0xC3U, (char)0xB7U, 'z', 0};
+ static const char last_escape[] = {'w', 'x', (char)0xC3U, (char)0xB7U, 0};
+
+ check_pname_escape((const char*)first_escape, "eg:s\n\teg:p eg:%C3%B7yz .\n");
+ check_pname_escape((const char*)mid_escape, "eg:s\n\teg:p eg:w%C3%B7z .\n");
+ check_pname_escape((const char*)last_escape, "eg:s\n\teg:p eg:wx%C3%B7 .\n");
+}
+
int
main(void)
{
@@ -336,6 +409,7 @@ main(void)
test_write_error();
test_writer_stack_overflow();
test_write_empty_syntax();
+ test_write_pname_escapes();
return 0;
}