From 51cc405d288a078543523efd380ce3c7d11ac501 Mon Sep 17 00:00:00 2001 From: David Robillard Date: Mon, 24 Jun 2024 15:12:05 -0400 Subject: Improve test suite coverage --- test/extra/bad/bad-bom-1.ttl | 3 + test/extra/bad/bad-bom-2.ttl | 3 + test/extra/bad/bad-bom-only-1.ttl | 1 + test/extra/bad/bad-bom-only-2.ttl | 1 + test/extra/bad/manifest.ttl | 26 +++++++-- test/extra/good/manifest.ttl | 7 +++ test/extra/good/test-local-name-percent.nt | 2 + test/extra/good/test-local-name-percent.ttl | 4 ++ test/extra/pretty/datatypes.ttl | 2 + test/meson.build | 7 +++ test/test_env.c | 3 +- test/test_node.c | 90 ++++++++++++++++++++++++++++- test/test_reader_writer.c | 4 +- test/test_string.c | 30 +++++++--- test/test_uri.c | 35 ++++++++++- 15 files changed, 198 insertions(+), 20 deletions(-) create mode 100644 test/extra/bad/bad-bom-1.ttl create mode 100644 test/extra/bad/bad-bom-2.ttl create mode 100644 test/extra/bad/bad-bom-only-1.ttl create mode 100644 test/extra/bad/bad-bom-only-2.ttl create mode 100644 test/extra/good/test-local-name-percent.nt create mode 100644 test/extra/good/test-local-name-percent.ttl (limited to 'test') diff --git a/test/extra/bad/bad-bom-1.ttl b/test/extra/bad/bad-bom-1.ttl new file mode 100644 index 00000000..7d7681d4 --- /dev/null +++ b/test/extra/bad/bad-bom-1.ttl @@ -0,0 +1,3 @@ +ï# This file starts with the first byte of the UTF-8 Byte Order Mark + + a . diff --git a/test/extra/bad/bad-bom-2.ttl b/test/extra/bad/bad-bom-2.ttl new file mode 100644 index 00000000..9ce3f093 --- /dev/null +++ b/test/extra/bad/bad-bom-2.ttl @@ -0,0 +1,3 @@ +ï»# This file starts with the first two bytes of the UTF-8 Byte Order Mark + + a . diff --git a/test/extra/bad/bad-bom-only-1.ttl b/test/extra/bad/bad-bom-only-1.ttl new file mode 100644 index 00000000..a4a063a1 --- /dev/null +++ b/test/extra/bad/bad-bom-only-1.ttl @@ -0,0 +1 @@ +ï \ No newline at end of file diff --git a/test/extra/bad/bad-bom-only-2.ttl b/test/extra/bad/bad-bom-only-2.ttl new file mode 100644 index 00000000..022c50f1 --- /dev/null +++ b/test/extra/bad/bad-bom-only-2.ttl @@ -0,0 +1 @@ +ï» \ No newline at end of file diff --git a/test/extra/bad/manifest.ttl b/test/extra/bad/manifest.ttl index 7e35e5ff..64dbf05f 100644 --- a/test/extra/bad/manifest.ttl +++ b/test/extra/bad/manifest.ttl @@ -13,7 +13,10 @@ <#bad-blank-node-label> <#bad-blank-predicate> <#bad-blank-syntax> - <#bad-bom> + <#bad-bom-1> + <#bad-bom-2> + <#bad-bom-only-1> + <#bad-bom-only-2> <#bad-char-in-local> <#bad-char-in-prefix> <#bad-char-in-uri> @@ -165,10 +168,25 @@ mf:action ; mf:name "bad-blank-syntax" . -<#bad-bom> +<#bad-bom-1> a rdft:TestTurtleNegativeSyntax ; - mf:action ; - mf:name "bad-bom" . + mf:action ; + mf:name "bad-bom-1" . + +<#bad-bom-2> + a rdft:TestTurtleNegativeSyntax ; + mf:action ; + mf:name "bad-bom-2" . + +<#bad-bom-only-1> + a rdft:TestTurtleNegativeSyntax ; + mf:action ; + mf:name "bad-bom-only-1" . + +<#bad-bom-only-2> + a rdft:TestTurtleNegativeSyntax ; + mf:action ; + mf:name "bad-bom-only-2" . <#bad-char-in-local> a rdft:TestTurtleNegativeSyntax ; diff --git a/test/extra/good/manifest.ttl b/test/extra/good/manifest.ttl index 5e7458ec..350d7d9c 100644 --- a/test/extra/good/manifest.ttl +++ b/test/extra/good/manifest.ttl @@ -30,6 +30,7 @@ <#test-list-subject> <#test-local-name-ends-with-dot> <#test-local-name-escapes> + <#test-local-name-percent> <#test-long-utf8> <#test-no-spaces> <#test-non-curie-uri> @@ -203,6 +204,12 @@ mf:name "test-local-name-escapes" ; mf:result . +<#test-local-name-percent> + a rdft:TestTurtleEval ; + mf:action ; + mf:name "test-local-name-percent" ; + mf:result . + <#test-long-utf8> a rdft:TestTurtleEval ; mf:action ; diff --git a/test/extra/good/test-local-name-percent.nt b/test/extra/good/test-local-name-percent.nt new file mode 100644 index 00000000..e6330547 --- /dev/null +++ b/test/extra/good/test-local-name-percent.nt @@ -0,0 +1,2 @@ + . + . diff --git a/test/extra/good/test-local-name-percent.ttl b/test/extra/good/test-local-name-percent.ttl new file mode 100644 index 00000000..32fb63d5 --- /dev/null +++ b/test/extra/good/test-local-name-percent.ttl @@ -0,0 +1,4 @@ +@prefix eg: . + +eg:s eg:p eg:o%3E . +eg:s eg:p eg:o%3f . diff --git a/test/extra/pretty/datatypes.ttl b/test/extra/pretty/datatypes.ttl index 721dfe4d..8f8b13f2 100644 --- a/test/extra/pretty/datatypes.ttl +++ b/test/extra/pretty/datatypes.ttl @@ -9,6 +9,8 @@ eg:s 1 , 2.3 , "4."^^xsd:decimal , + "5"^^xsd:decimal , + "6.7E8"^^xsd:float , false , true , "x"^^eg:datatype , diff --git a/test/meson.build b/test/meson.build index fe476491..ab012908 100644 --- a/test/meson.build +++ b/test/meson.build @@ -153,15 +153,20 @@ simple_command_tests = { 'serdi': { 'bad': [ ['-c'], + ['-cx'], ['-fi'], ['-i', 'turtle'], ['-i', 'turt'], ['-i'], + ['-ix'], ['-o', '~unknown'], ['-o', 'ntripleses'], ['-o'], + ['-ox'], ['-p'], + ['-px'], ['-r'], + ['-rx'], ['-z'], ], 'good': [ @@ -178,6 +183,7 @@ if is_variable('serdi') script_args = common_script_args + ['--serdi', serdi] serd_ttl = files('../serd.ttl')[0] bad_input_file = files('extra/bad/bad-base.ttl') + text_input_file = files('extra/bad/README.md') test('serd_ttl', serdi, args: [serd_ttl], suite: 'data') @@ -214,6 +220,7 @@ if is_variable('serdi') 'string': ['-s', ' a .'], 'no_such_file': ['no_such_file'], 'remote': ['ftp://example.org/unsupported.ttl'], + 'text': [text_input_file], } foreach name, args : bad_input_tests diff --git a/test/test_env.c b/test/test_env.c index 1de075f3..9547042f 100644 --- a/test/test_env.c +++ b/test/test_env.c @@ -39,7 +39,8 @@ test_env(void) SerdChunk suffix; assert(!serd_env_qualify(NULL, &u, &u, &suffix)); assert(serd_env_expand(NULL, &c, &prefix, &suffix)); - assert(serd_env_expand(env, &b, &prefix, &suffix)); + assert(serd_env_expand(env, &b, &prefix, &suffix) == SERD_ERR_BAD_ARG); + assert(serd_env_expand(env, &u, &prefix, &suffix) == SERD_ERR_BAD_ARG); SerdNode nxnode = serd_env_expand_node(NULL, &c); assert(serd_node_equals(&nxnode, &SERD_NODE_NULL)); diff --git a/test/test_node.c b/test/test_node.c index f08363cb..af14171b 100644 --- a/test/test_node.c +++ b/test/test_node.c @@ -42,8 +42,14 @@ test_string_to_double(void) const double expt_test_nums[] = { 2.0E18, -5e19, +8e20, 2e+22, -5e-5, 8e0, 9e-0, 2e+0}; - const char* expt_test_strs[] = { - "02e18", "-5e019", "+8e20", "2E+22", "-5E-5", "8E0", "9e-0", " 2e+0"}; + const char* expt_test_strs[] = {"02e18", + "-5e019", + " +8e20", + "\f2E+22", + "\n-5E-5", + "\r8E0", + "\t9e-0", + "\v2e+0"}; for (size_t i = 0; i < sizeof(expt_test_nums) / sizeof(double); ++i) { const double num = serd_strtod(expt_test_strs[i], NULL); @@ -143,6 +149,58 @@ test_blob_to_node(void) } } +static void +test_base64_decode(void) +{ + static const char* const decoded = "test"; + static const size_t decoded_len = 4U; + + // Test decoding clean base64 + { + static const char* const encoded = "dGVzdA=="; + static const size_t encoded_len = 8U; + + size_t size = 0U; + void* const data = + serd_base64_decode((const uint8_t*)encoded, encoded_len, &size); + + assert(data); + assert(size == decoded_len); + assert(!strncmp((const char*)data, decoded, decoded_len)); + serd_free(data); + } + + // Test decoding equivalent dirty base64 with ignored junk characters + { + static const char* const encoded = "d-G#V!z*d(A$%=="; + static const size_t encoded_len = 13U; + + size_t size = 0U; + void* const data = + serd_base64_decode((const uint8_t*)encoded, encoded_len, &size); + + assert(data); + assert(size == decoded_len); + assert(!strncmp((const char*)data, decoded, decoded_len)); + serd_free(data); + } + + // Test decoding effectively nothing + { + static const char* const encoded = "@#$%"; + static const size_t encoded_len = 4U; + + size_t size = 0U; + void* const data = + serd_base64_decode((const uint8_t*)encoded, encoded_len, &size); + + assert(data); + assert(!size); + // Contents of data are undefined + serd_free(data); + } +} + static void test_node_equals(void) { @@ -176,6 +234,8 @@ test_node_from_string(void) static void test_node_from_substring(void) { + static const uint8_t utf8_str[] = {'l', 0xC3, 0xB6, 'n', 'g', 0}; + SerdNode empty = serd_node_from_substring(SERD_LITERAL, NULL, 32); assert(!empty.buf && !empty.n_bytes && !empty.n_chars && !empty.flags && !empty.type); @@ -187,6 +247,30 @@ test_node_from_substring(void) a_b = serd_node_from_substring(SERD_LITERAL, USTR("a\"bc"), 10); assert(a_b.n_bytes == 4 && a_b.n_chars == 4 && a_b.flags == SERD_HAS_QUOTE && !strncmp((const char*)a_b.buf, "a\"bc", 4)); + + SerdNode utf8 = serd_node_from_substring(SERD_LITERAL, utf8_str, 5); + assert(utf8.n_bytes == 5 && utf8.n_chars == 4 && !utf8.flags && + !strncmp((const char*)utf8.buf, (const char*)utf8_str, 6)); +} + +static void +test_uri_node_from_node(void) +{ + const SerdNode string = serd_node_from_string(SERD_LITERAL, USTR("s")); + SerdNode string_node = serd_node_new_uri_from_node(&string, NULL, NULL); + assert(!string_node.n_bytes); + serd_node_free(&string_node); + + const SerdNode nouri = {NULL, 0U, 0U, 0U, SERD_URI}; + SerdNode nouri_node = serd_node_new_uri_from_node(&nouri, NULL, NULL); + assert(!nouri_node.n_bytes); + serd_node_free(&nouri_node); + + const SerdNode uri = + serd_node_from_string(SERD_URI, USTR("http://example.org/p")); + SerdNode uri_node = serd_node_new_uri_from_node(&uri, NULL, NULL); + assert(uri_node.n_bytes == 20U); + serd_node_free(&uri_node); } int @@ -196,9 +280,11 @@ main(void) test_double_to_node(); test_integer_to_node(); test_blob_to_node(); + test_base64_decode(); test_node_equals(); test_node_from_string(); test_node_from_substring(); + test_uri_node_from_node(); printf("Success\n"); return 0; diff --git a/test/test_reader_writer.c b/test/test_reader_writer.c index cd7ca408..374ec4e1 100644 --- a/test/test_reader_writer.c +++ b/test/test_reader_writer.c @@ -41,6 +41,8 @@ static const char* const doc_string = " \"lang\"@en ;\n" " eg:p .\n" "}\n" + "@prefix other: .\n" + "@base .\n" "eg:s\n" " [\n" " eg:p 3.0 ,\n" @@ -399,7 +401,7 @@ test_write_errors(void) ErrorContext ctx = {0U, 0U}; const SerdStyle style = (SerdStyle)(SERD_STYLE_STRICT | SERD_STYLE_CURIED); - const size_t max_offsets[] = {0, 386, 1911, 2003, 386}; + const size_t max_offsets[] = {0, 462, 1911, 2003, 462}; // Test errors at different offsets to hit different code paths for (unsigned s = 1; s <= (unsigned)SERD_TRIG; ++s) { diff --git a/test/test_string.c b/test/test_string.c index 6767e5ae..23835ca9 100644 --- a/test/test_string.c +++ b/test/test_string.c @@ -10,20 +10,32 @@ #include #include +static void +check_strlen(const char* const str, + const size_t expected_n_bytes, + const size_t expected_n_chars, + const SerdNodeFlags expected_flags) +{ + size_t n_bytes = 0U; + SerdNodeFlags flags = 0U; + const size_t n_chars = serd_strlen((const uint8_t*)str, &n_bytes, &flags); + + assert(n_bytes == expected_n_bytes); + assert(n_chars == expected_n_chars); + assert(flags == expected_flags); +} + static void test_strlen(void) { - const uint8_t str[] = {'"', '5', 0xE2, 0x82, 0xAC, '"', '\n', 0}; + static const uint8_t utf8[] = {'"', '5', 0xE2, 0x82, 0xAC, '"', '\n', 0}; - size_t n_bytes = 0; - SerdNodeFlags flags = 0; - size_t len = serd_strlen(str, &n_bytes, &flags); - assert(len == 5 && n_bytes == 7 && - flags == (SERD_HAS_QUOTE | SERD_HAS_NEWLINE)); - len = serd_strlen(str, NULL, &flags); - assert(len == 5); + check_strlen("\"quotes\"", 8U, 8U, SERD_HAS_QUOTE); + check_strlen("newline\n", 8U, 8U, SERD_HAS_NEWLINE); + check_strlen("\rreturn", 7U, 7U, SERD_HAS_NEWLINE); + check_strlen((const char*)utf8, 7U, 5U, SERD_HAS_QUOTE | SERD_HAS_NEWLINE); - assert(serd_strlen(str, &n_bytes, NULL) == 5); + assert(serd_strlen((const uint8_t*)"nulls", NULL, NULL) == 5U); } static void diff --git a/test/test_uri.c b/test/test_uri.c index cc81b40e..fc5eab71 100644 --- a/test/test_uri.c +++ b/test/test_uri.c @@ -16,6 +16,8 @@ static void test_uri_string_has_scheme(void) { + assert(!serd_uri_string_has_scheme(NULL)); + assert(!serd_uri_string_has_scheme(USTR("relative"))); assert(!serd_uri_string_has_scheme(USTR("http"))); assert(!serd_uri_string_has_scheme(USTR("5nostartdigit"))); @@ -99,6 +101,8 @@ test_uri_to_path(void) "C|/Windows/Sucks")); assert(!serd_uri_to_path((const uint8_t*)"http://example.org/path")); + + assert(!strcmp((const char*)serd_uri_to_path((const uint8_t*)"rel"), "rel")); } #if defined(__GNUC__) @@ -166,11 +170,20 @@ test_uri_parsing(void) "/C:\\Pointless Space"); #endif + // Test tolerance of NULL hostname parameter + uint8_t* const hosted = serd_file_uri_parse(USTR("file://host/path"), NULL); + assert(!strcmp((const char*)hosted, "/path")); + serd_free(hosted); + // Test tolerance of parsing junk URI escapes - uint8_t* out_path = serd_file_uri_parse(USTR("file:///foo/%0Xbar"), NULL); - assert(!strcmp((const char*)out_path, "/foo/bar")); - serd_free(out_path); + uint8_t* const junk1 = serd_file_uri_parse(USTR("file:///foo/%0Xbar"), NULL); + assert(!strcmp((const char*)junk1, "/foo/bar")); + serd_free(junk1); + + uint8_t* const junk2 = serd_file_uri_parse(USTR("file:///foo/%X0bar"), NULL); + assert(!strcmp((const char*)junk2, "/foo/bar")); + serd_free(junk2); } static void @@ -343,6 +356,22 @@ test_relative_uri(void) "http://example.org/a/b/c", "http://example.org/a/b", "http://example.org/a"); + + // Tolerance of NULL URI output parameter + { + SerdURI uri = SERD_URI_NULL; + assert(!serd_uri_parse(USTR("http://example.org/path"), &uri)); + + SerdURI base = SERD_URI_NULL; + assert(!serd_uri_parse(USTR("http://example.org/"), &base)); + + SerdNode result_node = serd_node_new_relative_uri(&uri, &base, NULL, NULL); + + assert(result_node.n_bytes == 4U); + assert(!strcmp((const char*)result_node.buf, "path")); + + serd_node_free(&result_node); + } } int -- cgit v1.2.1