diff options
Diffstat (limited to 'test')
109 files changed, 1808 insertions, 1040 deletions
diff --git a/test/.clang-tidy b/test/.clang-tidy index 75f5312d..80737308 100644 --- a/test/.clang-tidy +++ b/test/.clang-tidy @@ -7,9 +7,14 @@ Checks: > -bugprone-assert-side-effect, -bugprone-easily-swappable-parameters, -cert-err33-c, - -clang-analyzer-nullability.NullableDereferenced, + -clang-analyzer-optin.core.EnumCastOutOfRange, -clang-analyzer-security.insecureAPI.DeprecatedOrUnsafeBufferHandling, -concurrency-mt-unsafe, -hicpp-signed-bitwise, - -readability-function-cognitive-complexity, + -readability-redundant-casting, +CheckOptions: + - key: readability-function-cognitive-complexity.IgnoreMacros + value: 'true' + - key: readability-function-cognitive-complexity.Threshold + value: '6' InheritParentConfig: true 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 + +<http://example.org/thing> a <http://example.org/Thing> . 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 + +<http://example.org/thing> a <http://example.org/Thing> . 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/bad-lang-start-delete.nt b/test/extra/bad/bad-lang-start-delete.nt new file mode 100644 index 00000000..122625e0 --- /dev/null +++ b/test/extra/bad/bad-lang-start-delete.nt @@ -0,0 +1 @@ +<http://example.org/s> <http://example.org/p> "hello"@bad . diff --git a/test/extra/bad/bad-lang-start-space.nt b/test/extra/bad/bad-lang-start-space.nt new file mode 100644 index 00000000..ff5c12ab --- /dev/null +++ b/test/extra/bad/bad-lang-start-space.nt @@ -0,0 +1 @@ +<http://example.org/s> <http://example.org/p> "hello"@ bad . diff --git a/test/extra/bad/bad-lang-start-tab.nt b/test/extra/bad/bad-lang-start-tab.nt new file mode 100644 index 00000000..ad005c6d --- /dev/null +++ b/test/extra/bad/bad-lang-start-tab.nt @@ -0,0 +1 @@ +<http://example.org/s> <http://example.org/p> "hello"@ bad . diff --git a/test/extra/bad/bad-lang-start-wide.nt b/test/extra/bad/bad-lang-start-wide.nt new file mode 100644 index 00000000..04ca4899 --- /dev/null +++ b/test/extra/bad/bad-lang-start-wide.nt @@ -0,0 +1 @@ +<http://example.org/s> <http://example.org/p> "hello"@βad . diff --git a/test/extra/bad/bad-lang.ttl b/test/extra/bad/bad-lang.ttl index 01e04328..b51df89c 100644 --- a/test/extra/bad/bad-lang.ttl +++ b/test/extra/bad/bad-lang.ttl @@ -1 +1 @@ -<> <http://example.org/pred> "hello"@\bad .
\ No newline at end of file +<> <http://example.org/pred> "hello"@b\ad . diff --git a/test/extra/bad/bad-predicate-in-blank.ttl b/test/extra/bad/bad-predicate-in-blank.ttl new file mode 100644 index 00000000..e4200f15 --- /dev/null +++ b/test/extra/bad/bad-predicate-in-blank.ttl @@ -0,0 +1 @@ +<a> <b> [ ERRORHERE <c> ] diff --git a/test/extra/bad/bad-prefix-dot.ttl b/test/extra/bad/bad-prefix-dot.ttl new file mode 100644 index 00000000..7b02211f --- /dev/null +++ b/test/extra/bad/bad-prefix-dot.ttl @@ -0,0 +1 @@ +@prefix dotted.: <http://example.org/> . diff --git a/test/extra/bad/bad-uri-scheme-start-apostrophe.nt b/test/extra/bad/bad-uri-scheme-start-apostrophe.nt new file mode 100644 index 00000000..265b46d1 --- /dev/null +++ b/test/extra/bad/bad-uri-scheme-start-apostrophe.nt @@ -0,0 +1 @@ +<http://example.org/s> <http://example.org/p> <'http://example.org/o> . diff --git a/test/extra/bad/bad-uri-scheme-start-delete.nt b/test/extra/bad/bad-uri-scheme-start-delete.nt new file mode 100644 index 00000000..70b4962a --- /dev/null +++ b/test/extra/bad/bad-uri-scheme-start-delete.nt @@ -0,0 +1 @@ +<http://example.org/s> <http://example.org/p> <http://example.org/o> . diff --git a/test/extra/bad/bad-uri-scheme-start-space.nt b/test/extra/bad/bad-uri-scheme-start-space.nt new file mode 100644 index 00000000..d396d6dd --- /dev/null +++ b/test/extra/bad/bad-uri-scheme-start-space.nt @@ -0,0 +1 @@ +<http://example.org/s> <http://example.org/p> < http://example.org/o> . diff --git a/test/extra/bad/bad-uri-scheme-start-tab.nt b/test/extra/bad/bad-uri-scheme-start-tab.nt new file mode 100644 index 00000000..458a5743 --- /dev/null +++ b/test/extra/bad/bad-uri-scheme-start-tab.nt @@ -0,0 +1 @@ +<http://example.org/s> <http://example.org/p> < http://example.org/o> . diff --git a/test/extra/bad/bad-uri-scheme-start-wide.nt b/test/extra/bad/bad-uri-scheme-start-wide.nt new file mode 100644 index 00000000..7ddfff60 --- /dev/null +++ b/test/extra/bad/bad-uri-scheme-start-wide.nt @@ -0,0 +1 @@ +<http://example.org/s> <http://example.org/p> <σhttp://example.org/o> . diff --git a/test/extra/bad/bad-uri-scheme-start.nt b/test/extra/bad/bad-uri-scheme-start.nt deleted file mode 100644 index cd3fd70f..00000000 --- a/test/extra/bad/bad-uri-scheme-start.nt +++ /dev/null @@ -1 +0,0 @@ -<2http://example.org/s> <http://example.org/p> <http://example.org/o> . diff --git a/test/extra/bad/manifest.ttl b/test/extra/bad/manifest.ttl index 6b6df540..acadde28 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> @@ -25,24 +28,6 @@ <#bad-dot-after-subject> <#bad-dot-in-collection> <#bad-empty-blank-predicate> - <#bad-nt-eof-after-blank> - <#bad-nt-eof-after-lang> - <#bad-nt-eof-after-lang-hyphen> - <#bad-nt-eof-after-lang-subtag> - <#bad-nt-eof-after-object> - <#bad-nt-eof-after-predicate> - <#bad-nt-eof-after-string> - <#bad-nt-eof-after-string-escape> - <#bad-nt-eof-after-subject> - <#bad-nt-eof-after-underscore> - <#bad-nt-eof-before-blank> - <#bad-nt-eof-before-iri> - <#bad-nt-eof-before-lang> - <#bad-nt-eof-before-string> - <#bad-nt-eof-before-string-escape> - <#bad-nt-eof-in-iri-path> - <#bad-nt-eof-in-iri-scheme> - <#bad-nt-eof-in-string> <#bad-nt-syntax-blank-u00F7.nt> <#bad-nt-syntax-blank-u037E.nt> <#bad-nt-syntax-blank-u200B.nt> @@ -62,24 +47,6 @@ <#bad-nt-syntax-uri-grave> <#bad-nt-syntax-uri-less-than> <#bad-nt-syntax-uri-opening-brace> - <#bad-eof-after-quotes> - <#bad-eof-at-string-start> - <#bad-eof-in-blank> - <#bad-eof-in-escape> - <#bad-eof-in-lang-suffix> - <#bad-eof-in-lang> - <#bad-eof-in-list> - <#bad-eof-in-long-string> - <#bad-eof-in-object-list> - <#bad-eof-in-object-list2> - <#bad-eof-in-predicate-list> - <#bad-eof-in-string> - <#bad-eof-in-text-character> - <#bad-eof-in-triple-quote> - <#bad-eof-in-uri> - <#bad-eof-in-uri-character> - <#bad-eof-in-uri-scheme> - <#bad-eof-in-utf8-character> <#bad-equivalence> <#bad-escape> <#bad-ext-namedblank-op> @@ -96,6 +63,10 @@ <#bad-is-of-keywords> <#bad-keywords> <#bad-lang> + <#bad-lang-start-delete> + <#bad-lang-start-space> + <#bad-lang-start-tab> + <#bad-lang-start-wide> <#bad-list> <#bad-list-close-object> <#bad-list2> @@ -113,8 +84,10 @@ <#bad-object2> <#bad-paths> <#bad-pn-escape> - <#bad-prefix-missing-colon> + <#bad-predicate-in-blank> <#bad-prefix> + <#bad-prefix-dot> + <#bad-prefix-missing-colon> <#bad-quote-in-uri> <#bad-semicolon-after-subject> <#bad-string> @@ -124,7 +97,10 @@ <#bad-true-subject> <#bad-uri-escape> <#bad-uri-scheme> - <#bad-uri-scheme-start> + <#bad-uri-scheme-start-delete> + <#bad-uri-scheme-start-space> + <#bad-uri-scheme-start-tab> + <#bad-uri-scheme-start-wide> <#bad-uri-truncated> <#bad-verb> ) . @@ -164,10 +140,25 @@ mf:action <bad-blank-syntax.ttl> ; mf:name "bad-blank-syntax" . -<#bad-bom> +<#bad-bom-1> + a rdft:TestTurtleNegativeSyntax ; + mf:action <bad-bom-1.ttl> ; + mf:name "bad-bom-1" . + +<#bad-bom-2> a rdft:TestTurtleNegativeSyntax ; - mf:action <bad-bom.ttl> ; - mf:name "bad-bom" . + mf:action <bad-bom-2.ttl> ; + mf:name "bad-bom-2" . + +<#bad-bom-only-1> + a rdft:TestTurtleNegativeSyntax ; + mf:action <bad-bom-only-1.ttl> ; + mf:name "bad-bom-only-1" . + +<#bad-bom-only-2> + a rdft:TestTurtleNegativeSyntax ; + mf:action <bad-bom-only-2.ttl> ; + mf:name "bad-bom-only-2" . <#bad-char-in-local> a rdft:TestTurtleNegativeSyntax ; @@ -224,96 +215,6 @@ mf:action <bad-empty-blank-predicate.ttl> ; mf:name "bad-empty-blank-predicate" . -<#bad-nt-eof-after-blank> - a rdft:TestNTriplesNegativeSyntax ; - mf:action <bad-nt-eof-after-blank.nt> ; - mf:name "bad-nt-eof-after-blank" . - -<#bad-nt-eof-after-lang> - a rdft:TestNTriplesNegativeSyntax ; - mf:action <bad-nt-eof-after-lang.nt> ; - mf:name "bad-nt-eof-after-lang" . - -<#bad-nt-eof-after-lang-hyphen> - a rdft:TestNTriplesNegativeSyntax ; - mf:action <bad-nt-eof-after-lang-hyphen.nt> ; - mf:name "bad-nt-eof-after-lang-hyphen" . - -<#bad-nt-eof-after-lang-subtag> - a rdft:TestNTriplesNegativeSyntax ; - mf:action <bad-nt-eof-after-lang-subtag.nt> ; - mf:name "bad-nt-eof-after-lang-subtag" . - -<#bad-nt-eof-after-object> - a rdft:TestNTriplesNegativeSyntax ; - mf:action <bad-nt-eof-after-object.nt> ; - mf:name "bad-nt-eof-after-object" . - -<#bad-nt-eof-after-predicate> - a rdft:TestNTriplesNegativeSyntax ; - mf:action <bad-nt-eof-after-predicate.nt> ; - mf:name "bad-nt-eof-after-predicate" . - -<#bad-nt-eof-after-string> - a rdft:TestNTriplesNegativeSyntax ; - mf:action <bad-nt-eof-after-string.nt> ; - mf:name "bad-nt-eof-after-string" . - -<#bad-nt-eof-after-string-escape> - a rdft:TestNTriplesNegativeSyntax ; - mf:action <bad-nt-eof-after-string-escape.nt> ; - mf:name "bad-nt-eof-after-string-escape" . - -<#bad-nt-eof-after-subject> - a rdft:TestNTriplesNegativeSyntax ; - mf:action <bad-nt-eof-after-subject.nt> ; - mf:name "bad-nt-eof-after-subject" . - -<#bad-nt-eof-after-underscore> - a rdft:TestNTriplesNegativeSyntax ; - mf:action <bad-nt-eof-after-underscore.nt> ; - mf:name "bad-nt-eof-after-underscore" . - -<#bad-nt-eof-before-blank> - a rdft:TestNTriplesNegativeSyntax ; - mf:action <bad-nt-eof-before-blank.nt> ; - mf:name "bad-nt-eof-before-blank" . - -<#bad-nt-eof-before-iri> - a rdft:TestNTriplesNegativeSyntax ; - mf:action <bad-nt-eof-before-iri.nt> ; - mf:name "bad-nt-eof-before-iri" . - -<#bad-nt-eof-before-lang> - a rdft:TestNTriplesNegativeSyntax ; - mf:action <bad-nt-eof-before-lang.nt> ; - mf:name "bad-nt-eof-before-lang" . - -<#bad-nt-eof-before-string> - a rdft:TestNTriplesNegativeSyntax ; - mf:action <bad-nt-eof-before-string.nt> ; - mf:name "bad-nt-eof-before-string" . - -<#bad-nt-eof-before-string-escape> - a rdft:TestNTriplesNegativeSyntax ; - mf:action <bad-nt-eof-before-string-escape.nt> ; - mf:name "bad-nt-eof-before-string-escape" . - -<#bad-nt-eof-in-iri-path> - a rdft:TestNTriplesNegativeSyntax ; - mf:action <bad-nt-eof-in-iri-path.nt> ; - mf:name "bad-nt-eof-in-iri-path" . - -<#bad-nt-eof-in-iri-scheme> - a rdft:TestNTriplesNegativeSyntax ; - mf:action <bad-nt-eof-in-iri-scheme.nt> ; - mf:name "bad-nt-eof-in-iri-scheme" . - -<#bad-nt-eof-in-string> - a rdft:TestNTriplesNegativeSyntax ; - mf:action <bad-nt-eof-in-string.nt> ; - mf:name "bad-nt-eof-in-string" . - <#bad-nt-syntax-blank-u00F7> a rdft:TestNTriplesNegativeSyntax ; mf:action <bad-nt-syntax-blank-u00F7.nt> ; @@ -409,96 +310,6 @@ mf:action <bad-nt-syntax-uri-opening-brace.nt> ; mf:name "bad-nt-syntax-uri-opening-brace" . -<#bad-eof-after-quotes> - a rdft:TestTurtleNegativeSyntax ; - mf:action <bad-eof-after-quotes.ttl> ; - mf:name "bad-eof-after-quotes" . - -<#bad-eof-at-string-start> - a rdft:TestTurtleNegativeSyntax ; - mf:action <bad-eof-at-string-start.ttl> ; - mf:name "bad-eof-at-string-start" . - -<#bad-eof-in-blank> - a rdft:TestTurtleNegativeSyntax ; - mf:action <bad-eof-in-blank.ttl> ; - mf:name "bad-eof-in-blank" . - -<#bad-eof-in-escape> - a rdft:TestTurtleNegativeSyntax ; - mf:action <bad-eof-in-escape.ttl> ; - mf:name "bad-eof-in-escape" . - -<#bad-eof-in-lang> - a rdft:TestTurtleNegativeSyntax ; - mf:action <bad-eof-in-lang.ttl> ; - mf:name "bad-eof-in-lang" . - -<#bad-eof-in-lang-suffix> - a rdft:TestTurtleNegativeSyntax ; - mf:action <bad-eof-in-lang-suffix.ttl> ; - mf:name "bad-eof-in-lang-suffix" . - -<#bad-eof-in-list> - a rdft:TestTurtleNegativeSyntax ; - mf:action <bad-eof-in-list.ttl> ; - mf:name "bad-eof-in-list" . - -<#bad-eof-in-long-string> - a rdft:TestTurtleNegativeSyntax ; - mf:action <bad-eof-in-long-string.ttl> ; - mf:name "bad-eof-in-long-string" . - -<#bad-eof-in-object-list> - a rdft:TestTurtleNegativeSyntax ; - mf:action <bad-eof-in-object-list.ttl> ; - mf:name "bad-eof-in-object-list" . - -<#bad-eof-in-object-list2> - a rdft:TestTurtleNegativeSyntax ; - mf:action <bad-eof-in-object-list2.ttl> ; - mf:name "bad-eof-in-object-list2" . - -<#bad-eof-in-predicate-list> - a rdft:TestTurtleNegativeSyntax ; - mf:action <bad-eof-in-predicate-list.ttl> ; - mf:name "bad-eof-in-predicate-list" . - -<#bad-eof-in-string> - a rdft:TestTurtleNegativeSyntax ; - mf:action <bad-eof-in-string.ttl> ; - mf:name "bad-eof-in-string" . - -<#bad-eof-in-text-character> - a rdft:TestTurtleNegativeSyntax ; - mf:action <bad-eof-in-text-character.ttl> ; - mf:name "bad-eof-in-text-character" . - -<#bad-eof-in-triple-quote> - a rdft:TestTurtleNegativeSyntax ; - mf:action <bad-eof-in-triple-quote.ttl> ; - mf:name "bad-eof-in-triple-quote" . - -<#bad-eof-in-uri> - a rdft:TestTurtleNegativeSyntax ; - mf:action <bad-eof-in-uri.ttl> ; - mf:name "bad-eof-in-uri" . - -<#bad-eof-in-uri-character> - a rdft:TestTurtleNegativeSyntax ; - mf:action <bad-eof-in-uri-character.ttl> ; - mf:name "bad-eof-in-uri-character" . - -<#bad-eof-in-uri-scheme> - a rdft:TestNTriplesNegativeSyntax ; - mf:action <bad-eof-in-uri-scheme.nt> ; - mf:name "bad-eof-in-uri-scheme" . - -<#bad-eof-in-utf8-character> - a rdft:TestTurtleNegativeSyntax ; - mf:action <bad-eof-in-utf8-character.ttl> ; - mf:name "bad-eof-in-utf8-character" . - <#bad-equivalence> a rdft:TestTurtleNegativeSyntax ; mf:action <bad-equivalence.ttl> ; @@ -579,6 +390,26 @@ mf:action <bad-lang.ttl> ; mf:name "bad-lang" . +<#bad-lang-start-delete> + a rdft:TestTurtleNegativeSyntax ; + mf:action <bad-lang-start-delete.nt> ; + mf:name "bad-lang-start-delete" . + +<#bad-lang-start-space> + a rdft:TestTurtleNegativeSyntax ; + mf:action <bad-lang-start-space.nt> ; + mf:name "bad-lang-start-space" . + +<#bad-lang-start-tab> + a rdft:TestTurtleNegativeSyntax ; + mf:action <bad-lang-start-tab.nt> ; + mf:name "bad-lang-start-tab" . + +<#bad-lang-start-wide> + a rdft:TestTurtleNegativeSyntax ; + mf:action <bad-lang-start-wide.nt> ; + mf:name "bad-lang-start-wide" . + <#bad-list> a rdft:TestTurtleNegativeSyntax ; mf:action <bad-list.ttl> ; @@ -664,11 +495,21 @@ mf:action <bad-pn-escape.ttl> ; mf:name "bad-pn-escape" . +<#bad-predicate-in-blank> + a rdft:TestTurtleNegativeSyntax ; + mf:action <bad-predicate-in-blank.ttl> ; + mf:name "bad-predicate-in-blank" . + <#bad-prefix> a rdft:TestTurtleNegativeSyntax ; mf:action <bad-prefix.ttl> ; mf:name "bad-prefix" . +<#bad-prefix-dot> + a rdft:TestTurtleNegativeSyntax ; + mf:action <bad-prefix-dot.ttl> ; + mf:name "bad-prefix-dot" . + <#bad-prefix-missing-colon> a rdft:TestTurtleNegativeSyntax ; mf:action <bad-prefix-missing-colon.ttl> ; @@ -719,10 +560,30 @@ mf:action <bad-uri-scheme.nt> ; mf:name "bad-uri-scheme" . -<#bad-uri-scheme-start> +<#bad-uri-scheme-start-apostrophe> + a rdft:TestNTriplesNegativeSyntax ; + mf:action <bad-uri-scheme-start-apostrophe.nt> ; + mf:name "bad-uri-scheme-start-apostrophe" . + +<#bad-uri-scheme-start-delete> + a rdft:TestNTriplesNegativeSyntax ; + mf:action <bad-uri-scheme-start-delete.nt> ; + mf:name "bad-uri-scheme-start-delete" . + +<#bad-uri-scheme-start-space> + a rdft:TestNTriplesNegativeSyntax ; + mf:action <bad-uri-scheme-start-space.nt> ; + mf:name "bad-uri-scheme-start-space" . + +<#bad-uri-scheme-start-tab> + a rdft:TestNTriplesNegativeSyntax ; + mf:action <bad-uri-scheme-start-tab.nt> ; + mf:name "bad-uri-scheme-start-tab" . + +<#bad-uri-scheme-start-wide> a rdft:TestNTriplesNegativeSyntax ; - mf:action <bad-uri-scheme-start.nt> ; - mf:name "bad-uri-scheme-start" . + mf:action <bad-uri-scheme-start-wide.nt> ; + mf:name "bad-uri-scheme-start-wide" . <#bad-uri-truncated> a rdft:TestNTriplesNegativeSyntax ; diff --git a/test/extra/eof/README.md b/test/extra/eof/README.md new file mode 100644 index 00000000..1e461f79 --- /dev/null +++ b/test/extra/eof/README.md @@ -0,0 +1,5 @@ +EOF Test Suite +============== + +This simple suite tests that inputs truncated in various places are handled +correctly. diff --git a/test/extra/bad/bad-nt-eof-after-blank.nt b/test/extra/eof/bad-nt-eof-after-blank.nt index bc66ca37..bc66ca37 100644 --- a/test/extra/bad/bad-nt-eof-after-blank.nt +++ b/test/extra/eof/bad-nt-eof-after-blank.nt diff --git a/test/extra/bad/bad-nt-eof-after-lang-hyphen.nt b/test/extra/eof/bad-nt-eof-after-lang-hyphen.nt index 9e885d80..9e885d80 100644 --- a/test/extra/bad/bad-nt-eof-after-lang-hyphen.nt +++ b/test/extra/eof/bad-nt-eof-after-lang-hyphen.nt diff --git a/test/extra/bad/bad-nt-eof-after-lang-subtag.nt b/test/extra/eof/bad-nt-eof-after-lang-subtag.nt index f8158aec..f8158aec 100644 --- a/test/extra/bad/bad-nt-eof-after-lang-subtag.nt +++ b/test/extra/eof/bad-nt-eof-after-lang-subtag.nt diff --git a/test/extra/bad/bad-nt-eof-after-lang.nt b/test/extra/eof/bad-nt-eof-after-lang.nt index 7ab04b06..7ab04b06 100644 --- a/test/extra/bad/bad-nt-eof-after-lang.nt +++ b/test/extra/eof/bad-nt-eof-after-lang.nt diff --git a/test/extra/bad/bad-nt-eof-after-object.nt b/test/extra/eof/bad-nt-eof-after-object.nt index e796f2b0..e796f2b0 100644 --- a/test/extra/bad/bad-nt-eof-after-object.nt +++ b/test/extra/eof/bad-nt-eof-after-object.nt diff --git a/test/extra/bad/bad-nt-eof-after-predicate.nt b/test/extra/eof/bad-nt-eof-after-predicate.nt index ea47bfbe..ea47bfbe 100644 --- a/test/extra/bad/bad-nt-eof-after-predicate.nt +++ b/test/extra/eof/bad-nt-eof-after-predicate.nt diff --git a/test/extra/bad/bad-nt-eof-after-string-escape.nt b/test/extra/eof/bad-nt-eof-after-string-escape.nt index 869907e8..869907e8 100644 --- a/test/extra/bad/bad-nt-eof-after-string-escape.nt +++ b/test/extra/eof/bad-nt-eof-after-string-escape.nt diff --git a/test/extra/bad/bad-nt-eof-after-string.nt b/test/extra/eof/bad-nt-eof-after-string.nt index 32dda36d..32dda36d 100644 --- a/test/extra/bad/bad-nt-eof-after-string.nt +++ b/test/extra/eof/bad-nt-eof-after-string.nt diff --git a/test/extra/bad/bad-nt-eof-after-subject.nt b/test/extra/eof/bad-nt-eof-after-subject.nt index 21fa07f4..21fa07f4 100644 --- a/test/extra/bad/bad-nt-eof-after-subject.nt +++ b/test/extra/eof/bad-nt-eof-after-subject.nt diff --git a/test/extra/bad/bad-nt-eof-after-underscore.nt b/test/extra/eof/bad-nt-eof-after-underscore.nt index 4b05f2ac..4b05f2ac 100644 --- a/test/extra/bad/bad-nt-eof-after-underscore.nt +++ b/test/extra/eof/bad-nt-eof-after-underscore.nt diff --git a/test/extra/bad/bad-nt-eof-before-blank.nt b/test/extra/eof/bad-nt-eof-before-blank.nt index 99f70844..99f70844 100644 --- a/test/extra/bad/bad-nt-eof-before-blank.nt +++ b/test/extra/eof/bad-nt-eof-before-blank.nt diff --git a/test/extra/bad/bad-nt-eof-before-iri.nt b/test/extra/eof/bad-nt-eof-before-iri.nt index c5fa7845..c5fa7845 100644 --- a/test/extra/bad/bad-nt-eof-before-iri.nt +++ b/test/extra/eof/bad-nt-eof-before-iri.nt diff --git a/test/extra/bad/bad-nt-eof-before-lang.nt b/test/extra/eof/bad-nt-eof-before-lang.nt index f1a9d0df..f1a9d0df 100644 --- a/test/extra/bad/bad-nt-eof-before-lang.nt +++ b/test/extra/eof/bad-nt-eof-before-lang.nt diff --git a/test/extra/bad/bad-nt-eof-before-string-escape.nt b/test/extra/eof/bad-nt-eof-before-string-escape.nt index 30443488..30443488 100644 --- a/test/extra/bad/bad-nt-eof-before-string-escape.nt +++ b/test/extra/eof/bad-nt-eof-before-string-escape.nt diff --git a/test/extra/bad/bad-nt-eof-before-string.nt b/test/extra/eof/bad-nt-eof-before-string.nt index 6a2a7543..6a2a7543 100644 --- a/test/extra/bad/bad-nt-eof-before-string.nt +++ b/test/extra/eof/bad-nt-eof-before-string.nt diff --git a/test/extra/bad/bad-nt-eof-in-iri-path.nt b/test/extra/eof/bad-nt-eof-in-iri-path.nt index e8555e2b..e8555e2b 100644 --- a/test/extra/bad/bad-nt-eof-in-iri-path.nt +++ b/test/extra/eof/bad-nt-eof-in-iri-path.nt diff --git a/test/extra/bad/bad-nt-eof-in-iri-scheme.nt b/test/extra/eof/bad-nt-eof-in-iri-scheme.nt index 2c071547..2c071547 100644 --- a/test/extra/bad/bad-nt-eof-in-iri-scheme.nt +++ b/test/extra/eof/bad-nt-eof-in-iri-scheme.nt diff --git a/test/extra/bad/bad-nt-eof-in-string.nt b/test/extra/eof/bad-nt-eof-in-string.nt index 98944654..98944654 100644 --- a/test/extra/bad/bad-nt-eof-in-string.nt +++ b/test/extra/eof/bad-nt-eof-in-string.nt diff --git a/test/extra/bad/bad-eof-after-quotes.ttl b/test/extra/eof/bad-ttl-eof-after-quotes.ttl index 40e429cb..40e429cb 100644 --- a/test/extra/bad/bad-eof-after-quotes.ttl +++ b/test/extra/eof/bad-ttl-eof-after-quotes.ttl diff --git a/test/extra/bad/bad-eof-at-string-start.ttl b/test/extra/eof/bad-ttl-eof-at-string-start.ttl index 93d20bcc..93d20bcc 100644 --- a/test/extra/bad/bad-eof-at-string-start.ttl +++ b/test/extra/eof/bad-ttl-eof-at-string-start.ttl diff --git a/test/extra/bad/bad-eof-in-blank.ttl b/test/extra/eof/bad-ttl-eof-in-blank.ttl index 8cf4ee84..8cf4ee84 100644 --- a/test/extra/bad/bad-eof-in-blank.ttl +++ b/test/extra/eof/bad-ttl-eof-in-blank.ttl diff --git a/test/extra/bad/bad-eof-in-escape.ttl b/test/extra/eof/bad-ttl-eof-in-escape.ttl index 24b4eec6..24b4eec6 100644 --- a/test/extra/bad/bad-eof-in-escape.ttl +++ b/test/extra/eof/bad-ttl-eof-in-escape.ttl diff --git a/test/extra/bad/bad-eof-in-lang-suffix.ttl b/test/extra/eof/bad-ttl-eof-in-lang-suffix.ttl index f46a7763..f46a7763 100644 --- a/test/extra/bad/bad-eof-in-lang-suffix.ttl +++ b/test/extra/eof/bad-ttl-eof-in-lang-suffix.ttl diff --git a/test/extra/bad/bad-eof-in-lang.ttl b/test/extra/eof/bad-ttl-eof-in-lang.ttl index bfdffd02..bfdffd02 100644 --- a/test/extra/bad/bad-eof-in-lang.ttl +++ b/test/extra/eof/bad-ttl-eof-in-lang.ttl diff --git a/test/extra/bad/bad-eof-in-list.ttl b/test/extra/eof/bad-ttl-eof-in-list.ttl index 13eeb88d..13eeb88d 100644 --- a/test/extra/bad/bad-eof-in-list.ttl +++ b/test/extra/eof/bad-ttl-eof-in-list.ttl diff --git a/test/extra/bad/bad-eof-in-long-string.ttl b/test/extra/eof/bad-ttl-eof-in-long-string.ttl index 2ef179a8..2ef179a8 100644 --- a/test/extra/bad/bad-eof-in-long-string.ttl +++ b/test/extra/eof/bad-ttl-eof-in-long-string.ttl diff --git a/test/extra/bad/bad-eof-in-object-list.ttl b/test/extra/eof/bad-ttl-eof-in-object-list.ttl index 9bbcd17a..9bbcd17a 100644 --- a/test/extra/bad/bad-eof-in-object-list.ttl +++ b/test/extra/eof/bad-ttl-eof-in-object-list.ttl diff --git a/test/extra/bad/bad-eof-in-object-list2.ttl b/test/extra/eof/bad-ttl-eof-in-object-list2.ttl index 9186fb9f..9186fb9f 100644 --- a/test/extra/bad/bad-eof-in-object-list2.ttl +++ b/test/extra/eof/bad-ttl-eof-in-object-list2.ttl diff --git a/test/extra/bad/bad-eof-in-predicate-list.ttl b/test/extra/eof/bad-ttl-eof-in-predicate-list.ttl index eab5b05b..eab5b05b 100644 --- a/test/extra/bad/bad-eof-in-predicate-list.ttl +++ b/test/extra/eof/bad-ttl-eof-in-predicate-list.ttl diff --git a/test/extra/bad/bad-eof-in-string.ttl b/test/extra/eof/bad-ttl-eof-in-string.ttl index bb6e817f..bb6e817f 100644 --- a/test/extra/bad/bad-eof-in-string.ttl +++ b/test/extra/eof/bad-ttl-eof-in-string.ttl diff --git a/test/extra/bad/bad-eof-in-text-character.ttl b/test/extra/eof/bad-ttl-eof-in-text-character.ttl index a614803a..a614803a 100644 --- a/test/extra/bad/bad-eof-in-text-character.ttl +++ b/test/extra/eof/bad-ttl-eof-in-text-character.ttl diff --git a/test/extra/bad/bad-eof-in-triple-quote.ttl b/test/extra/eof/bad-ttl-eof-in-triple-quote.ttl index fb935441..fb935441 100644 --- a/test/extra/bad/bad-eof-in-triple-quote.ttl +++ b/test/extra/eof/bad-ttl-eof-in-triple-quote.ttl diff --git a/test/extra/bad/bad-eof-in-uri-character.ttl b/test/extra/eof/bad-ttl-eof-in-uri-character.ttl index eda70770..eda70770 100644 --- a/test/extra/bad/bad-eof-in-uri-character.ttl +++ b/test/extra/eof/bad-ttl-eof-in-uri-character.ttl diff --git a/test/extra/bad/bad-eof-in-uri-scheme.nt b/test/extra/eof/bad-ttl-eof-in-uri-scheme.ttl index de892dcf..de892dcf 100644 --- a/test/extra/bad/bad-eof-in-uri-scheme.nt +++ b/test/extra/eof/bad-ttl-eof-in-uri-scheme.ttl diff --git a/test/extra/bad/bad-eof-in-uri.ttl b/test/extra/eof/bad-ttl-eof-in-uri.ttl index 07b6e6ab..07b6e6ab 100644 --- a/test/extra/bad/bad-eof-in-uri.ttl +++ b/test/extra/eof/bad-ttl-eof-in-uri.ttl diff --git a/test/extra/bad/bad-eof-in-utf8-character.ttl b/test/extra/eof/bad-ttl-eof-in-utf8-character.ttl index 16784e88..16784e88 100644 --- a/test/extra/bad/bad-eof-in-utf8-character.ttl +++ b/test/extra/eof/bad-ttl-eof-in-utf8-character.ttl diff --git a/test/extra/eof/manifest.ttl b/test/extra/eof/manifest.ttl new file mode 100644 index 00000000..465333f7 --- /dev/null +++ b/test/extra/eof/manifest.ttl @@ -0,0 +1,225 @@ +@prefix mf: <http://www.w3.org/2001/sw/DataAccess/tests/test-manifest#> . +@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> . +@prefix rdft: <http://www.w3.org/ns/rdftest#> . + +<> + a mf:Manifest ; + rdfs:comment "Serd EOF (truncated input) test suite" ; + mf:entries ( + <#bad-nt-eof-after-blank> + <#bad-nt-eof-after-lang> + <#bad-nt-eof-after-lang-hyphen> + <#bad-nt-eof-after-lang-subtag> + <#bad-nt-eof-after-object> + <#bad-nt-eof-after-predicate> + <#bad-nt-eof-after-string> + <#bad-nt-eof-after-string-escape> + <#bad-nt-eof-after-subject> + <#bad-nt-eof-after-underscore> + <#bad-nt-eof-before-blank> + <#bad-nt-eof-before-iri> + <#bad-nt-eof-before-lang> + <#bad-nt-eof-before-string> + <#bad-nt-eof-before-string-escape> + <#bad-nt-eof-in-iri-path> + <#bad-nt-eof-in-iri-scheme> + <#bad-nt-eof-in-string> + <#bad-ttl-eof-after-quotes> + <#bad-ttl-eof-at-string-start> + <#bad-ttl-eof-in-blank> + <#bad-ttl-eof-in-escape> + <#bad-ttl-eof-in-lang> + <#bad-ttl-eof-in-lang-suffix> + <#bad-ttl-eof-in-list> + <#bad-ttl-eof-in-long-string> + <#bad-ttl-eof-in-object-list> + <#bad-ttl-eof-in-object-list2> + <#bad-ttl-eof-in-predicate-list> + <#bad-ttl-eof-in-string> + <#bad-ttl-eof-in-text-character> + <#bad-ttl-eof-in-triple-quote> + <#bad-ttl-eof-in-uri> + <#bad-ttl-eof-in-uri-character> + <#bad-ttl-eof-in-uri-scheme> + <#bad-ttl-eof-in-utf8-character> + ) . + +<#bad-nt-eof-after-blank> + a rdft:TestNTriplesNegativeSyntax ; + mf:action <bad-nt-eof-after-blank.nt> ; + mf:name "bad-nt-eof-after-blank" . + +<#bad-nt-eof-after-lang> + a rdft:TestNTriplesNegativeSyntax ; + mf:action <bad-nt-eof-after-lang.nt> ; + mf:name "bad-nt-eof-after-lang" . + +<#bad-nt-eof-after-lang-hyphen> + a rdft:TestNTriplesNegativeSyntax ; + mf:action <bad-nt-eof-after-lang-hyphen.nt> ; + mf:name "bad-nt-eof-after-lang-hyphen" . + +<#bad-nt-eof-after-lang-subtag> + a rdft:TestNTriplesNegativeSyntax ; + mf:action <bad-nt-eof-after-lang-subtag.nt> ; + mf:name "bad-nt-eof-after-lang-subtag" . + +<#bad-nt-eof-after-object> + a rdft:TestNTriplesNegativeSyntax ; + mf:action <bad-nt-eof-after-object.nt> ; + mf:name "bad-nt-eof-after-object" . + +<#bad-nt-eof-after-predicate> + a rdft:TestNTriplesNegativeSyntax ; + mf:action <bad-nt-eof-after-predicate.nt> ; + mf:name "bad-nt-eof-after-predicate" . + +<#bad-nt-eof-after-string> + a rdft:TestNTriplesNegativeSyntax ; + mf:action <bad-nt-eof-after-string.nt> ; + mf:name "bad-nt-eof-after-string" . + +<#bad-nt-eof-after-string-escape> + a rdft:TestNTriplesNegativeSyntax ; + mf:action <bad-nt-eof-after-string-escape.nt> ; + mf:name "bad-nt-eof-after-string-escape" . + +<#bad-nt-eof-after-subject> + a rdft:TestNTriplesNegativeSyntax ; + mf:action <bad-nt-eof-after-subject.nt> ; + mf:name "bad-nt-eof-after-subject" . + +<#bad-nt-eof-after-underscore> + a rdft:TestNTriplesNegativeSyntax ; + mf:action <bad-nt-eof-after-underscore.nt> ; + mf:name "bad-nt-eof-after-underscore" . + +<#bad-nt-eof-before-blank> + a rdft:TestNTriplesNegativeSyntax ; + mf:action <bad-nt-eof-before-blank.nt> ; + mf:name "bad-nt-eof-before-blank" . + +<#bad-nt-eof-before-iri> + a rdft:TestNTriplesNegativeSyntax ; + mf:action <bad-nt-eof-before-iri.nt> ; + mf:name "bad-nt-eof-before-iri" . + +<#bad-nt-eof-before-lang> + a rdft:TestNTriplesNegativeSyntax ; + mf:action <bad-nt-eof-before-lang.nt> ; + mf:name "bad-nt-eof-before-lang" . + +<#bad-nt-eof-before-string> + a rdft:TestNTriplesNegativeSyntax ; + mf:action <bad-nt-eof-before-string.nt> ; + mf:name "bad-nt-eof-before-string" . + +<#bad-nt-eof-before-string-escape> + a rdft:TestNTriplesNegativeSyntax ; + mf:action <bad-nt-eof-before-string-escape.nt> ; + mf:name "bad-nt-eof-before-string-escape" . + +<#bad-nt-eof-in-iri-path> + a rdft:TestNTriplesNegativeSyntax ; + mf:action <bad-nt-eof-in-iri-path.nt> ; + mf:name "bad-nt-eof-in-iri-path" . + +<#bad-nt-eof-in-iri-scheme> + a rdft:TestNTriplesNegativeSyntax ; + mf:action <bad-nt-eof-in-iri-scheme.nt> ; + mf:name "bad-nt-eof-in-iri-scheme" . + +<#bad-nt-eof-in-string> + a rdft:TestNTriplesNegativeSyntax ; + mf:action <bad-nt-eof-in-string.nt> ; + mf:name "bad-nt-eof-in-string" . + +<#bad-ttl-eof-after-quotes> + a rdft:TestTurtleNegativeSyntax ; + mf:action <bad-ttl-eof-after-quotes.ttl> ; + mf:name "bad-ttl-eof-after-quotes" . + +<#bad-ttl-eof-at-string-start> + a rdft:TestTurtleNegativeSyntax ; + mf:action <bad-ttl-eof-at-string-start.ttl> ; + mf:name "bad-ttl-eof-at-string-start" . + +<#bad-ttl-eof-in-blank> + a rdft:TestTurtleNegativeSyntax ; + mf:action <bad-ttl-eof-in-blank.ttl> ; + mf:name "bad-ttl-eof-in-blank" . + +<#bad-ttl-eof-in-escape> + a rdft:TestTurtleNegativeSyntax ; + mf:action <bad-ttl-eof-in-escape.ttl> ; + mf:name "bad-ttl-eof-in-escape" . + +<#bad-ttl-eof-in-lang> + a rdft:TestTurtleNegativeSyntax ; + mf:action <bad-ttl-eof-in-lang.ttl> ; + mf:name "bad-ttl-eof-in-lang" . + +<#bad-ttl-eof-in-lang-suffix> + a rdft:TestTurtleNegativeSyntax ; + mf:action <bad-ttl-eof-in-lang-suffix.ttl> ; + mf:name "bad-ttl-eof-in-lang-suffix" . + +<#bad-ttl-eof-in-list> + a rdft:TestTurtleNegativeSyntax ; + mf:action <bad-ttl-eof-in-list.ttl> ; + mf:name "bad-ttl-eof-in-list" . + +<#bad-ttl-eof-in-long-string> + a rdft:TestTurtleNegativeSyntax ; + mf:action <bad-ttl-eof-in-long-string.ttl> ; + mf:name "bad-ttl-eof-in-long-string" . + +<#bad-ttl-eof-in-object-list> + a rdft:TestTurtleNegativeSyntax ; + mf:action <bad-ttl-eof-in-object-list.ttl> ; + mf:name "bad-ttl-eof-in-object-list" . + +<#bad-ttl-eof-in-object-list2> + a rdft:TestTurtleNegativeSyntax ; + mf:action <bad-ttl-eof-in-object-list2.ttl> ; + mf:name "bad-ttl-eof-in-object-list2" . + +<#bad-ttl-eof-in-predicate-list> + a rdft:TestTurtleNegativeSyntax ; + mf:action <bad-ttl-eof-in-predicate-list.ttl> ; + mf:name "bad-ttl-eof-in-predicate-list" . + +<#bad-ttl-eof-in-string> + a rdft:TestTurtleNegativeSyntax ; + mf:action <bad-ttl-eof-in-string.ttl> ; + mf:name "bad-ttl-eof-in-string" . + +<#bad-ttl-eof-in-text-character> + a rdft:TestTurtleNegativeSyntax ; + mf:action <bad-ttl-eof-in-text-character.ttl> ; + mf:name "bad-ttl-eof-in-text-character" . + +<#bad-ttl-eof-in-triple-quote> + a rdft:TestTurtleNegativeSyntax ; + mf:action <bad-ttl-eof-in-triple-quote.ttl> ; + mf:name "bad-ttl-eof-in-triple-quote" . + +<#bad-ttl-eof-in-uri> + a rdft:TestTurtleNegativeSyntax ; + mf:action <bad-ttl-eof-in-uri.ttl> ; + mf:name "bad-ttl-eof-in-uri" . + +<#bad-ttl-eof-in-uri-character> + a rdft:TestTurtleNegativeSyntax ; + mf:action <bad-ttl-eof-in-uri-character.ttl> ; + mf:name "bad-ttl-eof-in-uri-character" . + +<#bad-ttl-eof-in-uri-scheme> + a rdft:TestTurtleNegativeSyntax ; + mf:action <bad-ttl-eof-in-uri-scheme.ttl> ; + mf:name "bad-ttl-eof-in-uri-scheme" . + +<#bad-ttl-eof-in-utf8-character> + a rdft:TestTurtleNegativeSyntax ; + mf:action <bad-ttl-eof-in-utf8-character.ttl> ; + mf:name "bad-ttl-eof-in-utf8-character" . diff --git a/test/extra/good/manifest.ttl b/test/extra/good/manifest.ttl index befe9451..659f8fd1 100644 --- a/test/extra/good/manifest.ttl +++ b/test/extra/good/manifest.ttl @@ -16,24 +16,32 @@ <#test-blank-node-statement> <#test-blankdot> <#test-bom> + <#test-boolish-prefix> <#test-changing-base> <#test-comment-whitespace> <#test-cr> <#test-digit-start-pname> + <#test-decimal-ends-with-dot> <#test-double> + <#test-double-ends-with-dot> <#test-empty-path-base> <#test-eof-at-page-end> <#test-ext-namedblank-iri> <#test-ext-namedblank-prefix> + <#test-false-ends-with-dot> <#test-id> + <#test-integer-ends-with-dot> <#test-list-in-blank> <#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> <#test-nq-syntax-all-rules> <#test-nq-syntax-dot-end> - <#test-nq-syntax-eof-after-blank-dot> + <#test-nt-syntax-all-rules> <#test-nq-syntax-eol-cr> <#test-nq-syntax-eol-crlf> <#test-nq-syntax-eol-lf> @@ -46,13 +54,15 @@ <#test-nt-syntax-eol-crlf> <#test-nt-syntax-eol-lf> <#test-nt-syntax-eol-lfcr> - <#test-out-of-range-unicode> <#test-prefix> <#test-quote-escapes> <#test-rel> <#test-semi-dot> <#test-several-eaten-dots> <#test-string-escapes> + <#test-trig-syntax-all-rules> + <#test-true-ends-with-dot> + <#test-ttl-syntax-all-rules> <#test-uri> ) . @@ -116,6 +126,18 @@ mf:name "test-bom" ; mf:result <test-bom.nt> . +<#test-bom-only> + a rdft:TestTurtleEval ; + mf:action <test-bom-only.ttl> ; + mf:name "test-bom-only" ; + mf:result <test-bom-only.nt> . + +<#test-boolish-prefix> + a rdft:TestTurtleEval ; + mf:action <test-boolish-prefix.ttl> ; + mf:name "test-boolish-prefix" ; + mf:result <test-boolish-prefix.nt> . + <#test-changing-base> a rdft:TestTurtleEval ; mf:action <test-changing-base.ttl> ; @@ -140,12 +162,24 @@ mf:name "test-digit-start-pname" ; mf:result <test-digit-start-pname.nt> . +<#test-decimal-ends-with-dot> + a rdft:TestTurtleEval ; + mf:action <test-decimal-ends-with-dot.ttl> ; + mf:name "test-decimal-ends-with-dot" ; + mf:result <test-decimal-ends-with-dot.nt> . + <#test-double> a rdft:TestTurtleEval ; mf:action <test-double.ttl> ; mf:name "test-double" ; mf:result <test-double.nt> . +<#test-double-ends-with-dot> + a rdft:TestTurtleEval ; + mf:action <test-double-ends-with-dot.ttl> ; + mf:name "test-double-ends-with-dot" ; + mf:result <test-double-ends-with-dot.nt> . + <#test-empty-path-base> a rdft:TestTurtleEval ; mf:action <test-empty-path-base.ttl> ; @@ -170,12 +204,24 @@ mf:name "test-ext-namedblank-prefix" ; mf:result <test-ext-namedblank-prefix.nt> . +<#test-false-ends-with-dot> + a rdft:TestTurtleEval ; + mf:action <test-false-ends-with-dot.ttl> ; + mf:name "test-false-ends-with-dot" ; + mf:result <test-false-ends-with-dot.nt> . + <#test-id> a rdft:TestTurtleEval ; mf:action <test-id.ttl> ; mf:name "test-id" ; mf:result <test-id.nt> . +<#test-integer-ends-with-dot> + a rdft:TestTurtleEval ; + mf:action <test-integer-ends-with-dot.ttl> ; + mf:name "test-integer-ends-with-dot" ; + mf:result <test-integer-ends-with-dot.nt> . + <#test-list-in-blank> a rdft:TestTurtleEval ; mf:action <test-list-in-blank.ttl> ; @@ -188,6 +234,24 @@ mf:name "test-list-subject" ; mf:result <test-list-subject.nt> . +<#test-local-name-ends-with-dot> + a rdft:TestTurtleEval ; + mf:action <test-local-name-ends-with-dot.ttl> ; + mf:name "test-local-name-ends-with-dot" ; + mf:result <test-local-name-ends-with-dot.nt> . + +<#test-local-name-escapes> + a rdft:TestTurtleEval ; + mf:action <test-local-name-escapes.ttl> ; + mf:name "test-local-name-escapes" ; + mf:result <test-local-name-escapes.nt> . + +<#test-local-name-percent> + a rdft:TestTurtleEval ; + mf:action <test-local-name-percent.ttl> ; + mf:name "test-local-name-percent" ; + mf:result <test-local-name-percent.nt> . + <#test-long-utf8> a rdft:TestTurtleEval ; mf:action <test-long-utf8.ttl> ; @@ -206,11 +270,6 @@ mf:name "test-non-curie-uri" ; mf:result <test-non-curie-uri.nt> . -<#test-nq-syntax-eof-after-blank-dot> - a rdft:TestNTriplesPositiveSyntax ; - mf:action <test-nq-syntax-eof-after-blank-dot.nq> ; - mf:name "test-nq-syntax-eof-after-blank-dot" . - <#test-nq-syntax-all-rules> a rdft:TestNQuadsPositiveSyntax ; mf:action <test-nq-syntax-all-rules.nq> ; @@ -221,6 +280,11 @@ mf:action <test-nq-syntax-dot-end.nq> ; mf:name "test-nq-syntax-dot-end" . +<#test-nq-syntax-eof-after-blank-dot> + a rdft:TestNTriplesPositiveSyntax ; + mf:action <test-nq-syntax-eof-after-blank-dot.nq> ; + mf:name "test-nq-syntax-eof-after-blank-dot" . + <#test-nq-syntax-eol-cr> a rdft:TestNTriplesPositiveSyntax ; mf:action <test-nq-syntax-eol-cr.nq> ; @@ -281,12 +345,6 @@ mf:action <test-nt-syntax-eol-lfcr.nt> ; mf:name "test-nt-syntax-eol-lfcr" . -<#test-out-of-range-unicode> - a rdft:TestTurtleEval ; - mf:action <test-out-of-range-unicode.ttl> ; - mf:name "test-out-of-range-unicode" ; - mf:result <test-out-of-range-unicode.nt> . - <#test-prefix> a rdft:TestTurtleEval ; mf:action <test-prefix.ttl> ; @@ -323,6 +381,22 @@ mf:name "test-string-escapes" ; mf:result <test-string-escapes.nt> . +<#test-trig-syntax-all-rules> + a rdft:TestTrigPositiveSyntax ; + mf:action <test-trig-syntax-all-rules.trig> ; + mf:name "test-trig-syntax-all-rules" . + +<#test-true-ends-with-dot> + a rdft:TestTurtleEval ; + mf:action <test-true-ends-with-dot.ttl> ; + mf:name "test-true-ends-with-dot" ; + mf:result <test-true-ends-with-dot.nt> . + +<#test-ttl-syntax-all-rules> + a rdft:TestTurtlePositiveSyntax ; + mf:action <test-ttl-syntax-all-rules.ttl> ; + mf:name "test-ttl-syntax-all-rules" . + <#test-uri> a rdft:TestTurtleEval ; mf:action <test-uri.ttl> ; diff --git a/test/extra/good/test-bom-only.nt b/test/extra/good/test-bom-only.nt new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/test/extra/good/test-bom-only.nt diff --git a/test/extra/good/test-bom-only.ttl b/test/extra/good/test-bom-only.ttl new file mode 100644 index 00000000..5f282702 --- /dev/null +++ b/test/extra/good/test-bom-only.ttl @@ -0,0 +1 @@ +
\ No newline at end of file diff --git a/test/extra/good/test-boolish-prefix.nt b/test/extra/good/test-boolish-prefix.nt new file mode 100644 index 00000000..d49eeab2 --- /dev/null +++ b/test/extra/good/test-boolish-prefix.nt @@ -0,0 +1,2 @@ +<http://example.org/s> <http://example.org/p> <http://example.org/falseish#o> . +<http://example.org/s> <http://example.org/p> <http://example.org/trueish#o> . diff --git a/test/extra/good/test-boolish-prefix.ttl b/test/extra/good/test-boolish-prefix.ttl new file mode 100644 index 00000000..81ffdf11 --- /dev/null +++ b/test/extra/good/test-boolish-prefix.ttl @@ -0,0 +1,5 @@ +@prefix false.ish: <http://example.org/falseish#> . +@prefix true.ish: <http://example.org/trueish#> . + +<http://example.org/s> <http://example.org/p> false.ish:o . +<http://example.org/s> <http://example.org/p> true.ish:o . diff --git a/test/extra/good/test-decimal-ends-with-dot.nt b/test/extra/good/test-decimal-ends-with-dot.nt new file mode 100644 index 00000000..be0802bc --- /dev/null +++ b/test/extra/good/test-decimal-ends-with-dot.nt @@ -0,0 +1 @@ +<http://example.org/eg#s> <http://example.org/eg#p> "12.3"^^<http://www.w3.org/2001/XMLSchema#decimal> . diff --git a/test/extra/good/test-decimal-ends-with-dot.ttl b/test/extra/good/test-decimal-ends-with-dot.ttl new file mode 100644 index 00000000..a63970d3 --- /dev/null +++ b/test/extra/good/test-decimal-ends-with-dot.ttl @@ -0,0 +1,4 @@ +@prefix eg: <http://example.org/eg#> . + +eg:s + eg:p 12.3. diff --git a/test/extra/good/test-double-ends-with-dot.nt b/test/extra/good/test-double-ends-with-dot.nt new file mode 100644 index 00000000..20e4395e --- /dev/null +++ b/test/extra/good/test-double-ends-with-dot.nt @@ -0,0 +1 @@ +<http://example.org/eg#s> <http://example.org/eg#p> "12.3e4"^^<http://www.w3.org/2001/XMLSchema#double> . diff --git a/test/extra/good/test-double-ends-with-dot.ttl b/test/extra/good/test-double-ends-with-dot.ttl new file mode 100644 index 00000000..4bd17a0b --- /dev/null +++ b/test/extra/good/test-double-ends-with-dot.ttl @@ -0,0 +1,4 @@ +@prefix eg: <http://example.org/eg#> . + +eg:s + eg:p 12.3e4. diff --git a/test/extra/good/test-false-ends-with-dot.nt b/test/extra/good/test-false-ends-with-dot.nt new file mode 100644 index 00000000..3b811813 --- /dev/null +++ b/test/extra/good/test-false-ends-with-dot.nt @@ -0,0 +1 @@ +<http://example.org/eg#s> <http://example.org/eg#p> "false"^^<http://www.w3.org/2001/XMLSchema#boolean> . diff --git a/test/extra/good/test-false-ends-with-dot.ttl b/test/extra/good/test-false-ends-with-dot.ttl new file mode 100644 index 00000000..14e2aa90 --- /dev/null +++ b/test/extra/good/test-false-ends-with-dot.ttl @@ -0,0 +1,4 @@ +@prefix eg: <http://example.org/eg#> . + +eg:s + eg:p false. diff --git a/test/extra/good/test-integer-ends-with-dot.nt b/test/extra/good/test-integer-ends-with-dot.nt new file mode 100644 index 00000000..7d6ff362 --- /dev/null +++ b/test/extra/good/test-integer-ends-with-dot.nt @@ -0,0 +1 @@ +<http://example.org/eg#s> <http://example.org/eg#p> "12"^^<http://www.w3.org/2001/XMLSchema#integer> . diff --git a/test/extra/good/test-integer-ends-with-dot.ttl b/test/extra/good/test-integer-ends-with-dot.ttl new file mode 100644 index 00000000..350ea41d --- /dev/null +++ b/test/extra/good/test-integer-ends-with-dot.ttl @@ -0,0 +1,4 @@ +@prefix eg: <http://example.org/eg#> . + +eg:s + eg:p 12. diff --git a/test/extra/good/test-local-name-ends-with-dot.nt b/test/extra/good/test-local-name-ends-with-dot.nt new file mode 100644 index 00000000..3285348a --- /dev/null +++ b/test/extra/good/test-local-name-ends-with-dot.nt @@ -0,0 +1 @@ +<http://example.org/eg#s> <http://example.org/eg#p> <http://example.org/eg#foo.> . diff --git a/test/extra/good/test-local-name-escapes.nt b/test/extra/good/test-local-name-escapes.nt new file mode 100644 index 00000000..a6362d7a --- /dev/null +++ b/test/extra/good/test-local-name-escapes.nt @@ -0,0 +1,17 @@ +<http://example.org/s> <http://example.org/p> <http://example.org/o'> . +<http://example.org/s> <http://example.org/p> <http://example.org/o!> . +<http://example.org/s> <http://example.org/p> <http://example.org/o#> . +<http://example.org/s> <http://example.org/p> <http://example.org/o$> . +<http://example.org/s> <http://example.org/p> <http://example.org/o%> . +<http://example.org/s> <http://example.org/p> <http://example.org/o&> . +<http://example.org/s> <http://example.org/p> <http://example.org/o(> . +<http://example.org/s> <http://example.org/p> <http://example.org/o)> . +<http://example.org/s> <http://example.org/p> <http://example.org/o*> . +<http://example.org/s> <http://example.org/p> <http://example.org/o+> . +<http://example.org/s> <http://example.org/p> <http://example.org/o,> . +<http://example.org/s> <http://example.org/p> <http://example.org/o/> . +<http://example.org/s> <http://example.org/p> <http://example.org/o;> . +<http://example.org/s> <http://example.org/p> <http://example.org/o=> . +<http://example.org/s> <http://example.org/p> <http://example.org/o?> . +<http://example.org/s> <http://example.org/p> <http://example.org/o@> . +<http://example.org/s> <http://example.org/p> <http://example.org/o~> . diff --git a/test/extra/good/test-local-name-escapes.ttl b/test/extra/good/test-local-name-escapes.ttl new file mode 100644 index 00000000..8c5fce37 --- /dev/null +++ b/test/extra/good/test-local-name-escapes.ttl @@ -0,0 +1,19 @@ +@prefix eg: <http://example.org/> . + +eg:s eg:p eg:o\' . +eg:s eg:p eg:o\! . +eg:s eg:p eg:o\# . +eg:s eg:p eg:o\$ . +eg:s eg:p eg:o\% . +eg:s eg:p eg:o\& . +eg:s eg:p eg:o\( . +eg:s eg:p eg:o\) . +eg:s eg:p eg:o\* . +eg:s eg:p eg:o\+ . +eg:s eg:p eg:o\, . +eg:s eg:p eg:o\/ . +eg:s eg:p eg:o\; . +eg:s eg:p eg:o\= . +eg:s eg:p eg:o\? . +eg:s eg:p eg:o\@ . +eg:s eg:p eg:o\~ . 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 @@ +<http://example.org/s> <http://example.org/p> <http://example.org/o%3E> . +<http://example.org/s> <http://example.org/p> <http://example.org/o%3f> . 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: <http://example.org/> . + +eg:s eg:p eg:o%3E . +eg:s eg:p eg:o%3f . diff --git a/test/extra/good/test-nq-syntax-all-rules.nq b/test/extra/good/test-nq-syntax-all-rules.nq index a8b80b9a..f9bffe20 100644 --- a/test/extra/good/test-nq-syntax-all-rules.nq +++ b/test/extra/good/test-nq-syntax-all-rules.nq @@ -2,6 +2,6 @@ _:e.u.s <http://example.org/p> _:o. _:e.u.s <http://example.org/p> "o"@en-gb _:g. _:s <http://example.org/p> "ob\t\b\n\r\f\\\"\'\u0025\U00015678ject" <http://example.org/g> . -_:s <http://example.org/p> "Â€ß¿à €à¿¿á€€ì¿¿í€€íŸ¿î€€ï¿½ð€€ð¿¿½ñ€€€ó¿¿½ô€€€ô¿½" <http://example.org/g> . +_:Σ <http://example.org/p> "Â€ß¿à €à¿¿á€€ì¿¿í€€íŸ¿î€€ï¿½ð€€ð¿¿½ñ€€€ó¿¿½ô€€€ô¿½" <http://example.org/g> . _:s <http://example.org/p> "o"^^<http://example.org/T> <http://example.org/g> . _:s <http://example.org/p> "o"@en _:g . diff --git a/test/extra/good/test-nt-syntax-all-rules.nt b/test/extra/good/test-nt-syntax-all-rules.nt index ed84f410..c626a702 100644 --- a/test/extra/good/test-nt-syntax-all-rules.nt +++ b/test/extra/good/test-nt-syntax-all-rules.nt @@ -4,4 +4,4 @@ _:s <http://example.org/p> "Â€ß¿à €à¿¿á€€ì¿¿í€€íŸ¿î€€ï¿½ð€€ð¿¿½ñ€€€ó¿¿½ô€€€ô¿½ _:s <http://example.org/p> "o"^^<http://example.org/T> . _:s <http://example.org/p> "o"@en . _:e.u.s <http://example.org/p> "o"@en-gb . -_:e.u.s <http://example.org/p> _:o. +_:e.u.s <http://example.org/p> _:Ω. diff --git a/test/extra/good/test-trig-syntax-all-rules.trig b/test/extra/good/test-trig-syntax-all-rules.trig index 97557b86..c824ffae 100644 --- a/test/extra/good/test-trig-syntax-all-rules.trig +++ b/test/extra/good/test-trig-syntax-all-rules.trig @@ -7,13 +7,13 @@ ""string""\t\b\n\r\f\'\u0025\U00015678""" . eg:s eg:p "Â€ß¿à €à¿¿á€€ì¿¿í€€íŸ¿î€€ï¿½ð€€ð¿¿½ñ€€€ó¿¿½ô€€€ô¿½" . eg:sub%25ject eg:pr\~d "o"^^eg:T . -eg:sub%25ject eg:pr\~d "o"@en . +eg:s\@bject eg:pr\~d "o"@en . _:e.u.s eg:p "o"@en-gb . _:e.u.s eg:p _:o. _:e.u.s eg:p‿râ€d 2. _:e.u.s eg:preÌ€d 3 . _:e.u.s eg:pͯ 4.5. -eg:s eg:p 0 , .1 , 2.3 , 4E5, 6e07 . +eg:Σ eg:p 0 , .1 , 2.3 , 4E5, 6e07 . eg:s eg:p .7e8 , .9E0 , 1.e2 , 3.E4 . eg:s eg:p .2E3 , .4e5 , 6.7E8 , 9. [ ] eg:p 0.e1, 2.E3. diff --git a/test/extra/good/test-true-ends-with-dot.nt b/test/extra/good/test-true-ends-with-dot.nt new file mode 100644 index 00000000..9938065b --- /dev/null +++ b/test/extra/good/test-true-ends-with-dot.nt @@ -0,0 +1 @@ +<http://example.org/eg#s> <http://example.org/eg#p> "true"^^<http://www.w3.org/2001/XMLSchema#boolean> . diff --git a/test/extra/good/test-true-ends-with-dot.ttl b/test/extra/good/test-true-ends-with-dot.ttl new file mode 100644 index 00000000..ebd3b6e1 --- /dev/null +++ b/test/extra/good/test-true-ends-with-dot.ttl @@ -0,0 +1,4 @@ +@prefix eg: <http://example.org/eg#> . + +eg:s + eg:p true. diff --git a/test/extra/good/test-ttl-syntax-all-rules.ttl b/test/extra/good/test-ttl-syntax-all-rules.ttl index ead2e8a8..dd4fa315 100644 --- a/test/extra/good/test-ttl-syntax-all-rules.ttl +++ b/test/extra/good/test-ttl-syntax-all-rules.ttl @@ -6,13 +6,13 @@ ""string""\t\b\n\r\f\'\u0025\U00015678""" . eg:s eg:p "Â€ß¿à €à¿¿á€€ì¿¿í€€íŸ¿î€€ï¿½ð€€ð¿¿½ñ€€€ó¿¿½ô€€€ô¿½" . eg:sub%25ject eg:pr\~d "o"^^eg:T . -eg:sub%25ject eg:pr\~d "o"@en . +eg:s\@bject eg:pr\~d "o"@en . _:e.u.s eg:p "o"@en-gb . _:e.u.s eg:p _:o. _:e.u.s eg:p‿râ€d 2. _:e.u.s eg:preÌ€d 3 . _:e.u.s eg:pͯ 4.5. -eg:s eg:p 0 , .1 , 2.3 , 4E5, 6e07 . +eg:Σ eg:p 0 , .1 , 2.3 , 4E5, 6e07 . eg:s eg:p .7e8 , .9E0 , 1.e2 , 3.E4 . eg:s eg:p .2E3 , .4e5 , 6.7E8 , 9. [ ] eg:p 0.e1, 2.E3. @@ -20,7 +20,7 @@ eg:s eg:p .2E3 , .4e5 , 6.7E8 , 9. eg:s eg:p [] . [ eg:p1 eg:o1 ; - eg:p2 _:o2 ; + eg:p2 _:β2 ; eg:p3 "o3" ; ] a eg:S . diff --git a/test/extra/lax/manifest.ttl b/test/extra/lax/manifest.ttl index b9890e14..f79e1984 100644 --- a/test/extra/lax/manifest.ttl +++ b/test/extra/lax/manifest.ttl @@ -8,14 +8,18 @@ mf:entries ( <#test-bad-string-nq> <#test-bad-string-nt> + <#test-bad-string-trig> <#test-bad-string-ttl> <#test-bad-uri-nq> <#test-bad-uri-nt> <#test-bad-uri-ttl> + <#test-bad-uri-trig> <#test-bad-utf8-nq> <#test-bad-utf8-nt> <#test-bad-utf8-ttl> + <#test-bad-utf8-trig> <#test-lone-list> + <#test-out-of-range-unicode> ) . <#test-bad-string-nq> @@ -36,6 +40,12 @@ mf:name "test-bad-string-ttl" ; mf:result <test-bad-string-out.nt> . +<#test-bad-string-trig> + a rdft:TestTrigNegativeSyntax ; + mf:action <test-bad-string.trig> ; + mf:name "test-bad-string-trig" ; + mf:result <test-bad-string-out.nt> . + <#test-bad-uri-nq> a rdft:TestNQuadsNegativeSyntax ; mf:action <test-bad-uri.nq> ; @@ -54,6 +64,12 @@ mf:name "test-bad-uri-ttl" ; mf:result <test-bad-uri-out.nt> . +<#test-bad-uri-trig> + a rdft:TestTurtleNegativeSyntax ; + mf:action <test-bad-uri.trig> ; + mf:name "test-bad-uri-trig" ; + mf:result <test-bad-uri-nq-out.nq> . + <#test-bad-utf8-nq> a rdft:TestNQuadsNegativeSyntax ; mf:action <test-bad-utf8.nq> ; @@ -72,8 +88,20 @@ mf:name "test-bad-utf8-ttl" ; mf:result <test-bad-utf8-ttl-out.nt> . +<#test-bad-utf8-trig> + a rdft:TestTurtleNegativeSyntax ; + mf:action <test-bad-utf8.trig> ; + mf:name "test-bad-utf8-trig" ; + mf:result <test-bad-utf8-ttl-out.nt> . + <#test-lone-list> a rdft:TestTurtleNegativeSyntax ; mf:action <test-lone-list.ttl> ; mf:name "test-lone-list" ; mf:result <test-lone-list.nt> . + +<#test-out-of-range-unicode> + a rdft:TestTurtleNegativeSyntax ; + mf:action <test-out-of-range-unicode.ttl> ; + mf:name "test-out-of-range-unicode" ; + mf:result <test-out-of-range-unicode.nt> . diff --git a/test/extra/lax/test-bad-string.trig b/test/extra/lax/test-bad-string.trig new file mode 100644 index 00000000..72eb9621 --- /dev/null +++ b/test/extra/lax/test-bad-string.trig @@ -0,0 +1,3 @@ +<http://example.org/s1> <http://example.org/p1> "Truncated line +<http://example.org/s1> <http://example.org/p1> "Bad escape \? " . +<http://example.org/s1> <http://example.org/p2> "Good" . diff --git a/test/extra/lax/test-bad-uri.trig b/test/extra/lax/test-bad-uri.trig new file mode 100644 index 00000000..ba852fef --- /dev/null +++ b/test/extra/lax/test-bad-uri.trig @@ -0,0 +1,8 @@ +<http://example.org/ÿÿbadg1> { + <http://example.org/s> <http://example.org/p> <http://example.org/goodo1> +} + +<http://example.org/s> + <http://example.org/p> <http://example.org/ bado1> ; + <http://example.org/p> <http://example.org/ÿÿbado2> ; + <http://example.org/p> <http://example.org/goodo2> . diff --git a/test/extra/lax/test-bad-utf8.trig b/test/extra/lax/test-bad-utf8.trig new file mode 100644 index 00000000..0e177366 --- /dev/null +++ b/test/extra/lax/test-bad-utf8.trig @@ -0,0 +1,6 @@ +<http://example.org/s> <http://example.org/p> "Impossible bytes: þ ÿ" . +<http://example.org/s> <http://example.org/p> "2 continuation bytes: €¿" . +<http://example.org/s> <http://example.org/p> "Missing continuation: À" . +<http://example.org/s> <http://example.org/p> """Impossible bytes: þ ÿ""" . +<http://example.org/s> <http://example.org/p> """2 continuation bytes: €¿""" . +<http://example.org/s> <http://example.org/p> """Missing continuation: À""" . diff --git a/test/extra/good/test-out-of-range-unicode.nt b/test/extra/lax/test-out-of-range-unicode.nt index 5def9e31..5def9e31 100644 --- a/test/extra/good/test-out-of-range-unicode.nt +++ b/test/extra/lax/test-out-of-range-unicode.nt diff --git a/test/extra/good/test-out-of-range-unicode.ttl b/test/extra/lax/test-out-of-range-unicode.ttl index 7e64785a..7e64785a 100644 --- a/test/extra/good/test-out-of-range-unicode.ttl +++ b/test/extra/lax/test-out-of-range-unicode.ttl 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/extra/pretty/manifest.ttl b/test/extra/pretty/manifest.ttl index 6422c9e0..26ed63be 100644 --- a/test/extra/pretty/manifest.ttl +++ b/test/extra/pretty/manifest.ttl @@ -35,6 +35,7 @@ <#nested-list-object> <#nested-list-object-with-empty-lists> <#relative-uris> + <#repeated-directives> <#short-string-escapes> <#uri-escapes> <#nested-list-subject> @@ -214,6 +215,12 @@ mf:name "relative-uris" ; mf:result <relative-uris.ttl> . +<#repeated-directives> + a rdft:TestTurtleEval ; + mf:action <repeated-directives.ttl> ; + mf:name "repeated-directives" ; + mf:result <repeated-directives.ttl> . + <#short-string-escapes> a rdft:TestTurtleEval ; mf:action <short-string-escapes.ttl> ; diff --git a/test/extra/pretty/named-graph.trig b/test/extra/pretty/named-graph.trig index 5cd12f3b..29f1d970 100644 --- a/test/extra/pretty/named-graph.trig +++ b/test/extra/pretty/named-graph.trig @@ -1,8 +1,18 @@ @prefix eg: <http://example.org/> . -eg:g { - eg:s - eg:p [ +eg:g1 { + eg:s1 + eg:p1 [ a eg:Object ] . } + +eg:g2 { + eg:s2 + eg:p2 [ + a eg:Object + ] . +} + +eg:s3 + eg:p3 eg:o3 . diff --git a/test/extra/pretty/repeated-directives.ttl b/test/extra/pretty/repeated-directives.ttl new file mode 100644 index 00000000..c7875c31 --- /dev/null +++ b/test/extra/pretty/repeated-directives.ttl @@ -0,0 +1,17 @@ +@base <http://example.org/base> . +@base <http://example.org/base> . +@base <base> . +@prefix eg: <http://example.org/eg#> . +@prefix eg: <http://example.org/eg#> . +@prefix eg: <eg#> . + +eg:s + eg:p eg:o , + eg:o . + +@prefix eg: <eg#> . +@prefix eg: <http://example.org/eg#> . +@prefix eg: <http://example.org/eg#> . +@base <base> . +@base <http://example.org/base> . +@base <http://example.org/base> . diff --git a/test/headers/.clang-tidy b/test/headers/.clang-tidy index eaf6ac95..06ede334 100644 --- a/test/headers/.clang-tidy +++ b/test/headers/.clang-tidy @@ -1,4 +1,4 @@ -# Copyright 2020-2022 David Robillard <d@drobilla.net> +# Copyright 2020-2024 David Robillard <d@drobilla.net> # SPDX-License-Identifier: 0BSD OR ISC Checks: > @@ -6,6 +6,9 @@ Checks: > -altera-*, -llvmlibc-*, -readability-identifier-length, +CheckOptions: + - key: readability-function-cognitive-complexity.Threshold + value: '0' WarningsAsErrors: '*' HeaderFilterRegex: '.*' FormatStyle: file diff --git a/test/headers/meson.build b/test/headers/meson.build index 6cb14f6e..b9125d2b 100644 --- a/test/headers/meson.build +++ b/test/headers/meson.build @@ -38,6 +38,7 @@ test( files('test_headers.c'), c_args: header_c_suppressions, dependencies: serd_dep, + implicit_include_directories: false, ), suite: 'unit', ) diff --git a/test/headers/test_headers.c b/test/headers/test_headers.c index c855c103..2f923c7e 100644 --- a/test/headers/test_headers.c +++ b/test/headers/test_headers.c @@ -1,10 +1,9 @@ // Copyright 2022 David Robillard <d@drobilla.net> // SPDX-License-Identifier: ISC -#include "serd/serd.h" // IWYU pragma: keep +#include <serd/serd.h> // IWYU pragma: keep -SERD_CONST_FUNC -int +SERD_CONST_FUNC int main(void) { return 0; diff --git a/test/lint/meson.build b/test/lint/meson.build new file mode 100644 index 00000000..cca43342 --- /dev/null +++ b/test/lint/meson.build @@ -0,0 +1,133 @@ +# Copyright 2020-2023 David Robillard <d@drobilla.net> +# SPDX-License-Identifier: 0BSD OR ISC + +plot_script_paths = [ + '../../scripts/serd_bench.py', +] + +simple_script_paths = [ + '../../scripts/check_formatting.py', + '../serd_test_util/__init__.py', + '../run_suite.py', + '../test_quiet.py', + '../test_stdin.py', + '../test_write_error.py', +] + +ttl_metadata_file_paths = [ + '../../serd.ttl', + '../extra/abbreviate/manifest.ttl', + '../extra/bad/manifest.ttl', + '../extra/big/manifest.ttl', + '../extra/full/manifest.ttl', + '../extra/good/manifest.ttl', + '../extra/lax/manifest.ttl', + '../extra/perfect/manifest.ttl', + '../extra/prefix/manifest.ttl', + '../extra/pretty/manifest.ttl', + '../extra/qualify/manifest.ttl', + '../extra/root/manifest.ttl', +] + +plot_scripts = files(plot_script_paths) +simple_scripts = files(simple_script_paths) +python_script_paths = simple_script_paths + plot_script_paths +python_scripts = plot_scripts + simple_scripts + +all_sources = sources + unit_test_sources + files('../../src/serdi.c') + +# Check licensing metadata +reuse = find_program('reuse', required: false) +if reuse.found() + test( + 'REUSE', + reuse, + args: ['--root', serd_src_root, 'lint'], + suite: 'data', + ) +endif + +# Check code formatting +clang_format = find_program('clang-format', required: false) +if clang_format.found() + test( + 'format', + clang_format, + args: ['--Werror', '--dry-run'] + c_headers + all_sources, + suite: 'code', + ) +endif + +# Check script formatting +black = find_program('black', required: false) +if black.found() + black_opts = ['--check', '-q', '-l', '79'] + foreach script_path : python_script_paths + script = files(script_path) + name = 'black_' + script_path.substring(3).underscorify() + test(name, black, args: black_opts + [script], suite: 'scripts') + endforeach +endif + +# Check scripts for errors with flake8 +flake8 = find_program('flake8', required: false) +if flake8.found() + test('flake8', flake8, args: python_scripts, suite: 'scripts') +endif + +# Check scripts for errors with pylint +pylint = find_program('pylint', required: false) +if pylint.found() + pymod = import('python') + plot_py = pymod.find_installation( + 'python3', + modules: ['matplotlib'], + required: false, + ) + + pylint_args = ['--disable', 'bad-option-value'] + simple_scripts + if plot_py.found() + pylint_args += plot_scripts + endif + + test('pylint', pylint, args: pylint_args, suite: 'scripts') +endif + +# Check Turtle formatting with serdi +if is_variable('serdi') + foreach ttl_file_path : ttl_metadata_file_paths + test( + ttl_file_path.substring(3).underscorify(), + check_formatting_py, + args: [files(ttl_file_path), serdi, '-o', 'turtle'], + suite: 'data', + ) + endforeach +endif + +if not meson.is_subproject() + # Check release metadata + autoship = find_program('autoship', required: false) + if autoship.found() + test('autoship', autoship, args: ['test', serd_src_root], suite: 'data') + endif + + # Check code with cppcheck + cppcheck = find_program('cppcheck', required: false) + if cppcheck.found() + compdb_path = join_paths(serd_build_root, 'compile_commands.json') + suppress_path = join_paths(serd_src_root, '.suppress.cppcheck') + test( + 'cppcheck', + cppcheck, + args: [ + '--enable=warning,style,performance,portability', + '--error-exitcode=1', + '--project=' + compdb_path, + '--suppressions-list=' + suppress_path, + '-q', + ], + suite: 'code', + ) + endif +endif diff --git a/test/meson.build b/test/meson.build index f6f56c2b..223e279d 100644 --- a/test/meson.build +++ b/test/meson.build @@ -4,110 +4,6 @@ run_suite = find_program('run_suite.py') wrapper = meson.get_external_property('exe_wrapper', '') -######################## -# Scripts and Metadata # -######################## - -plot_script_paths = [ - '../scripts/serd_bench.py', -] - -simple_script_paths = [ - '../scripts/check_formatting.py', - 'serd_test_util/__init__.py', - 'run_suite.py', - 'test_quiet.py', - 'test_stdin.py', - 'test_write_error.py', -] - -ttl_metadata_file_paths = [ - '../serd.ttl', - 'extra/abbreviate/manifest.ttl', - 'extra/bad/manifest.ttl', - 'extra/big/manifest.ttl', - 'extra/full/manifest.ttl', - 'extra/good/manifest.ttl', - 'extra/lax/manifest.ttl', - 'extra/perfect/manifest.ttl', - 'extra/prefix/manifest.ttl', - 'extra/pretty/manifest.ttl', - 'extra/qualify/manifest.ttl', - 'extra/root/manifest.ttl', -] - -plot_scripts = files(plot_script_paths) -simple_scripts = files(simple_script_paths) -python_script_paths = simple_script_paths + plot_script_paths -python_scripts = plot_scripts + simple_scripts - -if get_option('lint') - # Check release metadata - if not meson.is_subproject() - autoship = find_program('autoship', required: false) - if autoship.found() - test('autoship', autoship, args: ['test', serd_src_root], suite: 'data') - endif - endif - - # Check licensing metadata - reuse = find_program('reuse', required: false) - if reuse.found() - test( - 'REUSE', - reuse, - args: ['--root', serd_src_root, 'lint'], - suite: 'data', - ) - endif - - # Check script formatting - black = find_program('black', required: false) - if black.found() - black_opts = ['--check', '-q', '-l', '79'] - foreach script_path : python_script_paths - script = files(script_path) - name = script_path.underscorify() - test(name, black, args: black_opts + [script], suite: 'scripts') - endforeach - endif - - # Check scripts for errors with flake8 - flake8 = find_program('flake8', required: false) - if flake8.found() - test('flake8', flake8, args: python_scripts, suite: 'scripts') - endif - - # Check scripts for errors with pylint - pylint = find_program('pylint', required: false) - if pylint.found() - pymod = import('python') - plot_py = pymod.find_installation( - 'python3', - modules: ['matplotlib'], - required: false, - ) - - pylint_scripts = simple_scripts - if plot_py.found() - pylint_scripts += plot_scripts - endif - - pylint_args = ['--disable', 'bad-option-value'] - test('pylint', pylint, args: pylint_args + pylint_scripts, suite: 'scripts') - endif - - # Check Turtle formatting with serdi - foreach ttl_file_path : ttl_metadata_file_paths - test( - ttl_file_path.underscorify(), - check_formatting_py, - args: [files(ttl_file_path), serdi, '-o', 'turtle'], - suite: 'data', - ) - endforeach -endif - ################### # Header Warnings # ################### @@ -118,24 +14,30 @@ subdir('headers') # Unit Tests # ############## -unit_tests = [ +unit_test_names = [ 'env', 'free_null', 'node', + 'reader', 'reader_writer', 'string', 'uri', 'writer', ] -foreach unit : unit_tests +unit_test_sources = files('headers/test_headers.c') + +foreach name : unit_test_names + source = files('test_@0@.c'.format(name)) + unit_test_sources += source test( - unit, + name, executable( - 'test_@0@'.format(unit), - files('test_@0@.c'.format(unit)), + 'test_@0@'.format(name), + source, c_args: c_suppressions, dependencies: serd_dep, + implicit_include_directories: false, ), suite: 'unit', ) @@ -154,14 +56,20 @@ simple_command_tests = { 'serdi': { 'bad': [ ['-c'], + ['-cx'], ['-fi'], ['-i', 'turtle'], - ['-i', 'unknown'], + ['-i', 'turt'], ['-i'], - ['-o', 'unknown'], + ['-ix'], + ['-o', '~unknown'], + ['-o', 'ntripleses'], ['-o'], + ['-ox'], ['-p'], + ['-px'], ['-r'], + ['-rx'], ['-z'], ], 'good': [ @@ -178,6 +86,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 +123,7 @@ if is_variable('serdi') 'string': ['-s', '<foo> a <Bar> .'], 'no_such_file': ['no_such_file'], 'remote': ['ftp://example.org/unsupported.ttl'], + 'text': [text_input_file], } foreach name, args : bad_input_tests @@ -303,6 +213,17 @@ test_suites = { '--', '-b', ], + 'eof': [ + files('extra/eof/manifest.ttl'), + ns_serdtest + 'eof/', + ], + 'eof_lax': [ + '--ignore', + files('extra/eof/manifest.ttl'), + ns_serdtest + 'eof/', + '--', + '-l' + ], 'fast': [ files('extra/good/manifest.ttl'), ns_serdtest + 'good/', @@ -384,3 +305,11 @@ if is_variable('serdi') ) endforeach endif + +######## +# Lint # +######## + +if get_option('lint') + subdir('lint') +endif diff --git a/test/run_suite.py b/test/run_suite.py index 2e93502f..84c74dd1 100755 --- a/test/run_suite.py +++ b/test/run_suite.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 -# Copyright 2022-2023 David Robillard <d@drobilla.net> +# Copyright 2022-2025 David Robillard <d@drobilla.net> # SPDX-License-Identifier: ISC """Run a "simple" one-pass RDF-based test suite for serd.""" @@ -43,7 +43,7 @@ def run_eval_test(base_uri, command, in_path, good_path, out_path): syntax = util.syntax_from_path(out_path) command = command + ["-o", syntax, in_path, base_uri] - with subprocess.Popen(command, stdout=PIPE, encoding="utf-8") as proc: + with subprocess.Popen(command, encoding="utf-8", stdout=PIPE) as proc: out = list(proc.stdout) with open(good_path, "r", encoding="utf-8") as good: @@ -58,19 +58,25 @@ def run_positive_test(base_uri, command, in_path): return True -def run_negative_test(base_uri, command, in_path): +def run_negative_test(base_uri, command, in_path, ignore): """Run a negative syntax test and return whether the error was detected.""" if not os.path.exists(in_path): raise RuntimeError("Input file missing: " + in_path) command = command + [in_path, base_uri] - proc = subprocess.run(command, check=False, stderr=PIPE, stdout=DEVNULL) + proc = subprocess.run( + command, check=False, encoding="utf-8", stderr=PIPE, stdout=DEVNULL + ) - if proc.returncode == 0: + if not ignore and proc.returncode == 0: util.error("Unexpected successful return: " + in_path) return False + if proc.returncode < 0: + util.error("Command seems to have crashed: " + in_path) + return False + if len(proc.stderr) == 0: util.error("Command failed with no error output: " + in_path) return False @@ -86,7 +92,7 @@ def run_entry(args, entry, command, out_dir, suite_dir): negative = "Negative" in entry[NS_RDF + "type"][0] if negative and not args.lax: - return run_negative_test(base, command, in_path) + return run_negative_test(base, command, in_path, args.ignore) if NS_MF + "result" not in entry: return run_positive_test(base, command, in_path) @@ -151,6 +157,7 @@ def main(): ) parser.add_argument("--asserter", help="asserter URI for test report") + parser.add_argument("--ignore", action="store_true", help="ignore status") parser.add_argument("--lax", action="store_true", help="tolerate errors") parser.add_argument("--report", help="path to write result report to") parser.add_argument("--reverse", action="store_true", help="reverse test") diff --git a/test/serd_test_util/__init__.py b/test/serd_test_util/__init__.py index 8027462b..c38100b5 100644 --- a/test/serd_test_util/__init__.py +++ b/test/serd_test_util/__init__.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 -# Copyright 2022-2023 David Robillard <d@drobilla.net> +# Copyright 2022-2025 David Robillard <d@drobilla.net> # SPDX-License-Identifier: ISC """Utilities for data-driven tests.""" @@ -8,10 +8,12 @@ # pylint: disable=consider-using-f-string # pylint: disable=invalid-name +import argparse import datetime import difflib import os import re +import shlex import subprocess import sys import urllib.parse @@ -51,6 +53,33 @@ def error(message): sys.stderr.write("\n") +def wrapper_args(description, with_input=False): + """Return the command line arguments for a wrapped test.""" + + parser = argparse.ArgumentParser(description) + parser.add_argument("--serdi", default="./serdi", help="serdi executable") + parser.add_argument("--wrapper", default="", help="executable wrapper") + if with_input: + parser.add_argument("input", help="input file") + + return parser.parse_args(sys.argv[1:]) + + +def command_output(wrapper, command, stdin=None): + """Run a command and check that stdout matches the expected output.""" + + proc = subprocess.run( + shlex.split(wrapper) + command, + capture_output=True, + check=True, + encoding="utf-8", + input=stdin, + ) + + assert wrapper or not proc.stderr + return proc.stdout + + def print_result_summary(results): """Print test result summary to stdout or stderr as appropriate.""" @@ -128,12 +157,14 @@ def load_rdf(filename, base_uri, command_prefix): cmd = command_prefix + [filename, base_uri] proc = subprocess.run( - cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, check=True + cmd, + encoding="utf-8", + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + check=True, ) for line in proc.stdout.splitlines(): - matches = re.match( - r"<([^ ]*)> <([^ ]*)> <([^ ]*)> \.", line.decode("utf-8") - ) + matches = re.match(r"<([^ ]*)> <([^ ]*)> <([^ ]*)> \.", line) if matches: s, p, o = (matches.group(1), matches.group(2), matches.group(3)) if s not in model: diff --git a/test/test_env.c b/test/test_env.c index 1de075f3..bd55e47e 100644 --- a/test/test_env.c +++ b/test/test_env.c @@ -3,16 +3,19 @@ #undef NDEBUG -#include "serd/serd.h" +#include <serd/serd.h> #include <assert.h> #include <stdint.h> #include <string.h> +#define NS_EG "http://example.org/" #define USTR(s) ((const uint8_t*)(s)) static SerdStatus -count_prefixes(void* handle, const SerdNode* name, const SerdNode* uri) +count_prefixes(void* const handle, + const SerdNode* const name, + const SerdNode* const uri) { (void)name; (void)uri; @@ -24,12 +27,11 @@ count_prefixes(void* handle, const SerdNode* name, const SerdNode* uri) static void test_env(void) { - SerdNode u = serd_node_from_string(SERD_URI, USTR("http://example.org/foo")); - SerdNode b = serd_node_from_string(SERD_CURIE, USTR("invalid")); - SerdNode c = serd_node_from_string(SERD_CURIE, USTR("eg.2:b")); + SerdNode u = serd_node_from_string(SERD_URI, USTR(NS_EG "foo")); + SerdNode b = serd_node_from_string(SERD_CURIE, USTR("invalid")); + SerdNode c = serd_node_from_string(SERD_CURIE, USTR("eg.2:b")); SerdEnv* env = serd_env_new(NULL); - serd_env_set_prefix_from_strings( - env, USTR("eg.2"), USTR("http://example.org/")); + serd_env_set_prefix_from_strings(env, USTR("eg.2"), USTR(NS_EG "")); assert(!serd_env_set_base_uri(env, NULL)); assert(serd_env_set_base_uri(env, &SERD_NODE_NULL)); @@ -39,7 +41,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)); @@ -48,7 +51,7 @@ test_env(void) assert(serd_node_equals(&xnode, &SERD_NODE_NULL)); SerdNode xu = serd_env_expand_node(env, &u); - assert(!strcmp((const char*)xu.buf, "http://example.org/foo")); + assert(!strcmp((const char*)xu.buf, NS_EG "foo")); serd_node_free(&xu); SerdNode badpre = serd_node_from_string(SERD_CURIE, USTR("hm:what")); @@ -56,7 +59,7 @@ test_env(void) assert(serd_node_equals(&xbadpre, &SERD_NODE_NULL)); SerdNode xc = serd_env_expand_node(env, &c); - assert(!strcmp((const char*)xc.buf, "http://example.org/b")); + assert(!strcmp((const char*)xc.buf, NS_EG "b")); serd_node_free(&xc); assert(serd_env_set_prefix(env, &SERD_NODE_NULL, &SERD_NODE_NULL)); @@ -71,8 +74,7 @@ test_env(void) assert(serd_node_equals(&xblank, &SERD_NODE_NULL)); int n_prefixes = 0; - serd_env_set_prefix_from_strings( - env, USTR("eg.2"), USTR("http://example.org/")); + serd_env_set_prefix_from_strings(env, USTR("eg.2"), USTR(NS_EG)); serd_env_foreach(env, count_prefixes, &n_prefixes); assert(n_prefixes == 1); diff --git a/test/test_free_null.c b/test/test_free_null.c index 96153c8d..2bc0b10c 100644 --- a/test/test_free_null.c +++ b/test/test_free_null.c @@ -3,7 +3,7 @@ #undef NDEBUG -#include "serd/serd.h" +#include <serd/serd.h> #include <stddef.h> diff --git a/test/test_node.c b/test/test_node.c index f08363cb..c2fccf08 100644 --- a/test/test_node.c +++ b/test/test_node.c @@ -3,7 +3,7 @@ #undef NDEBUG -#include "serd/serd.h" +#include <serd/serd.h> #include <assert.h> #include <float.h> @@ -24,7 +24,7 @@ #endif static void -test_strtod(double dbl, double max_delta) +check_strtod(const double dbl, const double max_delta) { char buf[1024]; snprintf(buf, sizeof(buf), "%f", dbl); @@ -42,15 +42,21 @@ 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); const double delta = fabs(num - expt_test_nums[i]); assert(delta <= DBL_EPSILON); - test_strtod(expt_test_nums[i], DBL_EPSILON); + check_strtod(expt_test_nums[i], DBL_EPSILON); } } @@ -65,8 +71,8 @@ test_double_to_node(void) -16.00001, 5.000000005, 0.0000000001, - NAN, - INFINITY}; + (double)NAN, + (double)INFINITY}; const char* dbl_test_strs[] = {"0.0", "9.0", @@ -117,6 +123,7 @@ test_blob_to_node(void) { for (size_t size = 1; size < 256; ++size) { uint8_t* const data = (uint8_t*)malloc(size); + assert(data); for (size_t i = 0; i < size; ++i) { data[i] = (uint8_t)((size + i) % 256); } @@ -144,6 +151,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) { const uint8_t replacement_char_str[] = {0xEF, 0xBF, 0xBD, 0}; @@ -176,6 +235,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 +248,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,10 +281,10 @@ 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(); - - printf("Success\n"); + test_uri_node_from_node(); return 0; } diff --git a/test/test_quiet.py b/test/test_quiet.py index 42d05785..ff53e26e 100755 --- a/test/test_quiet.py +++ b/test/test_quiet.py @@ -1,25 +1,23 @@ #!/usr/bin/env python3 -# Copyright 2022 David Robillard <d@drobilla.net> +# Copyright 2022-2025 David Robillard <d@drobilla.net> # SPDX-License-Identifier: ISC -"""Test serdi quiet option.""" +"""Test quiet command-line option.""" -import argparse -import sys import shlex import subprocess -parser = argparse.ArgumentParser(description=__doc__) +import serd_test_util as util -parser.add_argument("--serdi", default="./serdi", help="path to serdi") -parser.add_argument("--wrapper", default="", help="executable wrapper") -parser.add_argument("input", help="invalid input file") - -args = parser.parse_args(sys.argv[1:]) +args = util.wrapper_args(__doc__, True) command = shlex.split(args.wrapper) + [args.serdi, "-q", args.input] proc = subprocess.run( - command, check=False, stdout=subprocess.PIPE, stderr=subprocess.PIPE + command, + encoding="utf-8", + check=False, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, ) assert proc.returncode != 0 diff --git a/test/test_reader.c b/test/test_reader.c new file mode 100644 index 00000000..6c38e447 --- /dev/null +++ b/test/test_reader.c @@ -0,0 +1,429 @@ +// Copyright 2011-2024 David Robillard <d@drobilla.net> +// SPDX-License-Identifier: ISC + +#undef NDEBUG + +#include <serd/serd.h> + +#ifdef _WIN32 +# include <windows.h> +#endif + +#include <assert.h> +#include <stdbool.h> +#include <stdint.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#define USTR(s) ((const uint8_t*)(s)) + +typedef struct { + int n_base; + int n_prefix; + int n_statement; + int n_end; +} ReaderTest; + +static SerdStatus +base_sink(void* const handle, const SerdNode* const uri) +{ + (void)uri; + + ReaderTest* const rt = (ReaderTest*)handle; + ++rt->n_base; + return SERD_SUCCESS; +} + +static SerdStatus +prefix_sink(void* const handle, + const SerdNode* const name, + const SerdNode* const uri) +{ + (void)name; + (void)uri; + + ReaderTest* const rt = (ReaderTest*)handle; + ++rt->n_prefix; + return SERD_SUCCESS; +} + +static SerdStatus +statement_sink(void* const handle, + SerdStatementFlags flags, + const SerdNode* const graph, + const SerdNode* const subject, + const SerdNode* const predicate, + const SerdNode* const object, + const SerdNode* const object_datatype, + const SerdNode* const object_lang) +{ + (void)flags; + (void)graph; + (void)subject; + (void)predicate; + (void)object; + (void)object_datatype; + (void)object_lang; + + ReaderTest* const rt = (ReaderTest*)handle; + ++rt->n_statement; + return SERD_SUCCESS; +} + +static SerdStatus +end_sink(void* const handle, const SerdNode* const node) +{ + (void)node; + + ReaderTest* const rt = (ReaderTest*)handle; + ++rt->n_end; + return SERD_SUCCESS; +} + +static void +test_read_string(void) +{ + ReaderTest rt = {0, 0, 0, 0}; + SerdReader* const reader = serd_reader_new( + SERD_TURTLE, &rt, NULL, base_sink, prefix_sink, statement_sink, end_sink); + + assert(reader); + assert(serd_reader_get_handle(reader) == &rt); + + // Test reading a string that ends exactly at the end of input (no newline) + const SerdStatus st = serd_reader_read_string( + reader, + USTR("<http://example.org/s> <http://example.org/p> " + "<http://example.org/o> .")); + + assert(!st); + assert(rt.n_base == 0); + assert(rt.n_prefix == 0); + assert(rt.n_statement == 1); + assert(rt.n_end == 0); + + serd_reader_free(reader); +} + +/// Reads a null byte after a statement, then succeeds again (like a socket) +static size_t +eof_test_read(void* const buf, + const size_t size, + const size_t nmemb, + void* const stream) +{ + assert(size == 1); + assert(nmemb == 1); + (void)size; + + static const char* const string = "_:s1 <http://example.org/p> _:o1 .\n" + "_:s2 <http://example.org/p> _:o2 .\n"; + + size_t* const count = (size_t*)stream; + + // Normal reading for the first statement + if (*count < 35) { + *(char*)buf = string[*count]; + ++*count; + return nmemb; + } + + // EOF for the first read at the start of the second statement + if (*count == 35) { + assert(string[*count] == '_'); + ++*count; + return 0; + } + + if (*count >= strlen(string)) { + return 0; + } + + // Normal reading after the EOF, adjusting for the skipped index 35 + *(char*)buf = string[*count - 1]; + ++*count; + return nmemb; +} + +static int +eof_test_error(void* const stream) +{ + (void)stream; + return 0; +} + +/// A read of a file stream hits EOF then fails to read chunks immediately +static void +test_read_eof_file(const char* const path) +{ + 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); + + ReaderTest rt = {0, 0, 0, 0}; + SerdReader* const reader = serd_reader_new( + SERD_TURTLE, &rt, NULL, base_sink, prefix_sink, statement_sink, end_sink); + + fseek(f, 0L, SEEK_SET); + serd_reader_start_stream(reader, f, (const uint8_t*)"test", true); + assert(serd_reader_read_chunk(reader) == SERD_SUCCESS); + assert(serd_reader_read_chunk(reader) == SERD_FAILURE); + assert(serd_reader_read_chunk(reader) == SERD_FAILURE); + serd_reader_end_stream(reader); + + fseek(f, 0L, SEEK_SET); + serd_reader_start_stream(reader, f, (const uint8_t*)"test", false); + assert(serd_reader_read_chunk(reader) == SERD_SUCCESS); + assert(serd_reader_read_chunk(reader) == SERD_FAILURE); + assert(serd_reader_read_chunk(reader) == SERD_FAILURE); + serd_reader_end_stream(reader); + + serd_reader_free(reader); + assert(!fclose(f)); +} + +// A byte-wise reader hits EOF once then continues (like a socket) +static void +test_read_eof_by_byte(void) +{ + ReaderTest rt = {0, 0, 0, 0}; + SerdReader* const reader = serd_reader_new( + SERD_TURTLE, &rt, NULL, base_sink, prefix_sink, statement_sink, end_sink); + + size_t n_reads = 0U; + serd_reader_start_source_stream(reader, + eof_test_read, + eof_test_error, + &n_reads, + (const uint8_t*)"test", + 1U); + + assert(serd_reader_read_chunk(reader) == SERD_SUCCESS); + assert(serd_reader_read_chunk(reader) == SERD_FAILURE); + assert(serd_reader_read_chunk(reader) == SERD_SUCCESS); + assert(serd_reader_read_chunk(reader) == SERD_FAILURE); + + serd_reader_end_stream(reader); + serd_reader_free(reader); +} + +static void +test_read_nquads_chunks(const char* const path) +{ + static const char null = 0; + + FILE* const f = fopen(path, "w+b"); + assert(f); + + // Write two statements, a null separator, then another statement + + fprintf(f, + "<http://example.org/s> <http://example.org/p1> " + "<http://example.org/o1> .\n"); + + fprintf(f, + "<http://example.org/s> <http://example.org/p2> " + "<http://example.org/o2> .\n"); + + fwrite(&null, sizeof(null), 1, f); + + fprintf(f, + "<http://example.org/s> <http://example.org/p3> " + "<http://example.org/o3> ."); + + fseek(f, 0, SEEK_SET); + + ReaderTest rt = {0, 0, 0, 0}; + SerdReader* const reader = serd_reader_new( + SERD_NQUADS, &rt, NULL, base_sink, prefix_sink, statement_sink, end_sink); + + assert(reader); + assert(serd_reader_get_handle(reader) == &rt); + assert(f); + + SerdStatus st = serd_reader_start_source_stream( + reader, (SerdSource)fread, (SerdStreamErrorFunc)ferror, f, NULL, 32U); + + assert(st == SERD_SUCCESS); + + // Read first statement + st = serd_reader_read_chunk(reader); + assert(st == SERD_SUCCESS); + assert(rt.n_base == 0); + assert(rt.n_prefix == 0); + assert(rt.n_statement == 1); + assert(rt.n_end == 0); + + // Read second statement + st = serd_reader_read_chunk(reader); + assert(st == SERD_SUCCESS); + assert(rt.n_base == 0); + assert(rt.n_prefix == 0); + assert(rt.n_statement == 2); + assert(rt.n_end == 0); + + // Read terminator + st = serd_reader_read_chunk(reader); + assert(st == SERD_FAILURE); + assert(rt.n_base == 0); + assert(rt.n_prefix == 0); + assert(rt.n_statement == 2); + assert(rt.n_end == 0); + + // Read last statement + st = serd_reader_read_chunk(reader); + assert(st == SERD_SUCCESS); + assert(rt.n_base == 0); + assert(rt.n_prefix == 0); + assert(rt.n_statement == 3); + assert(rt.n_end == 0); + + // EOF + st = serd_reader_read_chunk(reader); + assert(st == SERD_FAILURE); + assert(rt.n_base == 0); + assert(rt.n_prefix == 0); + assert(rt.n_statement == 3); + assert(rt.n_end == 0); + + assert(serd_reader_read_chunk(reader) == SERD_FAILURE); + serd_reader_end_stream(reader); + serd_reader_free(reader); + + assert(!fclose(f)); + assert(!remove(path)); +} + +static void +test_read_turtle_chunks(const char* const path) +{ + static const char null = 0; + + FILE* const f = fopen(path, "w+b"); + assert(f); + + // Write two statements separated by null characters + fprintf(f, "@base <http://example.org/base/> .\n"); + fprintf(f, "@prefix eg: <http://example.org/> .\n"); + fprintf(f, "eg:s eg:p1 eg:o1 ;\n"); + fprintf(f, " eg:p2 eg:o2 .\n"); + fwrite(&null, sizeof(null), 1, f); + fprintf(f, "eg:s eg:p [ eg:sp eg:so ] ."); + fseek(f, 0, SEEK_SET); + + ReaderTest rt = {0, 0, 0, 0}; + SerdReader* const reader = serd_reader_new( + SERD_TURTLE, &rt, NULL, base_sink, prefix_sink, statement_sink, end_sink); + + assert(reader); + assert(serd_reader_get_handle(reader) == &rt); + assert(f); + + SerdStatus st = serd_reader_start_source_stream( + reader, (SerdSource)fread, (SerdStreamErrorFunc)ferror, f, NULL, 32U); + assert(st == SERD_SUCCESS); + + // Read base + st = serd_reader_read_chunk(reader); + assert(st == SERD_SUCCESS); + assert(rt.n_base == 1); + assert(rt.n_prefix == 0); + assert(rt.n_statement == 0); + assert(rt.n_end == 0); + + // Read prefix + st = serd_reader_read_chunk(reader); + assert(st == SERD_SUCCESS); + assert(rt.n_base == 1); + assert(rt.n_prefix == 1); + assert(rt.n_statement == 0); + assert(rt.n_end == 0); + + // Read first two statements + st = serd_reader_read_chunk(reader); + assert(st == SERD_SUCCESS); + assert(rt.n_base == 1); + assert(rt.n_prefix == 1); + assert(rt.n_statement == 2); + assert(rt.n_end == 0); + + // Read terminator + st = serd_reader_read_chunk(reader); + assert(st == SERD_FAILURE); + assert(rt.n_base == 1); + assert(rt.n_prefix == 1); + assert(rt.n_statement == 2); + assert(rt.n_end == 0); + + // Read statements after null terminator + st = serd_reader_read_chunk(reader); + assert(st == SERD_SUCCESS); + assert(rt.n_base == 1); + assert(rt.n_prefix == 1); + assert(rt.n_statement == 4); + assert(rt.n_end == 1); + + // Read terminator + st = serd_reader_read_chunk(reader); + assert(st == SERD_FAILURE); + assert(rt.n_base == 1); + assert(rt.n_prefix == 1); + assert(rt.n_statement == 4); + assert(rt.n_end == 1); + + // EOF + st = serd_reader_read_chunk(reader); + assert(st == SERD_FAILURE); + assert(rt.n_base == 1); + assert(rt.n_prefix == 1); + assert(rt.n_statement == 4); + assert(rt.n_end == 1); + + assert(serd_reader_read_chunk(reader) == SERD_FAILURE); + serd_reader_end_stream(reader); + serd_reader_free(reader); + assert(!fclose(f)); + assert(!remove(path)); +} + +int +main(void) +{ +#ifdef _WIN32 + char tmp[MAX_PATH] = {0}; + const size_t tmp_len = (size_t)GetTempPath(sizeof(tmp), tmp); +#else + const char* const env_tmp = getenv("TMPDIR"); + const char* const tmp = env_tmp ? env_tmp : "/tmp"; + const size_t tmp_len = strlen(tmp); +#endif + + const char* const ttl_name = "serd_test_reader.ttl"; + const char* const nq_name = "serd_test_reader.nq"; + const size_t ttl_name_len = strlen(ttl_name); + const size_t nq_name_len = strlen(nq_name); + const size_t path_len = tmp_len + 1 + ttl_name_len; + char* const path = (char*)calloc(path_len + 1, 1); + assert(path); + + memcpy(path, tmp, tmp_len + 1); + path[tmp_len] = '/'; + + memcpy(path + tmp_len + 1, nq_name, nq_name_len + 1); + test_read_nquads_chunks(path); + + memcpy(path + tmp_len + 1, ttl_name, ttl_name_len + 1); + test_read_turtle_chunks(path); + + test_read_string(); + test_read_eof_file(path); + test_read_eof_by_byte(); + assert(!remove(path)); + + free(path); + return 0; +} diff --git a/test/test_reader_writer.c b/test/test_reader_writer.c index cd7ca408..78123110 100644 --- a/test/test_reader_writer.c +++ b/test/test_reader_writer.c @@ -1,9 +1,9 @@ -// Copyright 2011-2023 David Robillard <d@drobilla.net> +// Copyright 2011-2025 David Robillard <d@drobilla.net> // SPDX-License-Identifier: ISC #undef NDEBUG -#include "serd/serd.h" +#include <serd/serd.h> #ifdef _WIN32 # include <windows.h> @@ -11,7 +11,6 @@ #include <assert.h> #include <errno.h> -#include <stdbool.h> #include <stdint.h> #include <stdio.h> #include <stdlib.h> @@ -25,10 +24,7 @@ typedef struct { } ErrorContext; typedef struct { - int n_base; - int n_prefix; int n_statement; - int n_end; const SerdNode* graph; } ReaderTest; @@ -41,6 +37,8 @@ static const char* const doc_string = " \"lang\"@en ;\n" " eg:p <http://example.com/o> .\n" "}\n" + "@prefix other: <http://example.org/other> .\n" + "@base <http://drobilla.net/> .\n" "eg:s\n" " <http://example.org/p> [\n" " eg:p 3.0 ,\n" @@ -56,35 +54,14 @@ static const char* const doc_string = "( eg:o ) eg:t eg:u .\n"; static SerdStatus -test_base_sink(void* handle, const SerdNode* uri) -{ - (void)uri; - - ReaderTest* rt = (ReaderTest*)handle; - ++rt->n_base; - return SERD_SUCCESS; -} - -static SerdStatus -test_prefix_sink(void* handle, const SerdNode* name, const SerdNode* uri) -{ - (void)name; - (void)uri; - - ReaderTest* rt = (ReaderTest*)handle; - ++rt->n_prefix; - return SERD_SUCCESS; -} - -static SerdStatus -test_statement_sink(void* handle, - SerdStatementFlags flags, - const SerdNode* graph, - const SerdNode* subject, - const SerdNode* predicate, - const SerdNode* object, - const SerdNode* object_datatype, - const SerdNode* object_lang) +test_statement_sink(void* const handle, + const SerdStatementFlags flags, + const SerdNode* const graph, + const SerdNode* const subject, + const SerdNode* const predicate, + const SerdNode* const object, + const SerdNode* const object_datatype, + const SerdNode* const object_lang) { (void)flags; (void)subject; @@ -99,274 +76,6 @@ test_statement_sink(void* handle, return SERD_SUCCESS; } -static SerdStatus -test_end_sink(void* handle, const SerdNode* node) -{ - (void)node; - - ReaderTest* rt = (ReaderTest*)handle; - ++rt->n_end; - return SERD_SUCCESS; -} - -/// Reads a null byte after a statement, then succeeds again (like a socket) -static size_t -eof_test_read(void* buf, size_t size, size_t nmemb, void* stream) -{ - assert(size == 1); - assert(nmemb == 1); - (void)size; - - static const char* const string = "_:s1 <http://example.org/p> _:o1 .\n" - "_:s2 <http://example.org/p> _:o2 .\n"; - - size_t* const count = (size_t*)stream; - - // Normal reading for the first statement - if (*count < 35) { - *(char*)buf = string[*count]; - ++*count; - return nmemb; - } - - // EOF for the first read at the start of the second statement - if (*count == 35) { - assert(string[*count] == '_'); - ++*count; - return 0; - } - - if (*count >= strlen(string)) { - return 0; - } - - // Normal reading after the EOF, adjusting for the skipped index 35 - *(char*)buf = string[*count - 1]; - ++*count; - return nmemb; -} - -static int -eof_test_error(void* stream) -{ - (void)stream; - return 0; -} - -static void -test_read_nquads_chunks(const char* const path) -{ - static const char null = 0; - - FILE* const f = fopen(path, "w+b"); - - // Write two statements, a null separator, then another statement - - fprintf(f, - "<http://example.org/s> <http://example.org/p1> " - "<http://example.org/o1> .\n"); - - fprintf(f, - "<http://example.org/s> <http://example.org/p2> " - "<http://example.org/o2> .\n"); - - fwrite(&null, sizeof(null), 1, f); - - fprintf(f, - "<http://example.org/s> <http://example.org/p3> " - "<http://example.org/o3> .\n"); - - fseek(f, 0, SEEK_SET); - - ReaderTest* const rt = (ReaderTest*)calloc(1, sizeof(ReaderTest)); - SerdReader* const reader = serd_reader_new(SERD_NQUADS, - rt, - free, - test_base_sink, - test_prefix_sink, - test_statement_sink, - test_end_sink); - - assert(reader); - assert(serd_reader_get_handle(reader) == rt); - assert(f); - - SerdStatus st = serd_reader_start_stream(reader, f, NULL, false); - assert(st == SERD_SUCCESS); - - // Read first statement - st = serd_reader_read_chunk(reader); - assert(st == SERD_SUCCESS); - assert(rt->n_base == 0); - assert(rt->n_prefix == 0); - assert(rt->n_statement == 1); - assert(rt->n_end == 0); - - // Read second statement - st = serd_reader_read_chunk(reader); - assert(st == SERD_SUCCESS); - assert(rt->n_base == 0); - assert(rt->n_prefix == 0); - assert(rt->n_statement == 2); - assert(rt->n_end == 0); - - // Read terminator - st = serd_reader_read_chunk(reader); - assert(st == SERD_FAILURE); - assert(rt->n_base == 0); - assert(rt->n_prefix == 0); - assert(rt->n_statement == 2); - assert(rt->n_end == 0); - - // Read last statement - st = serd_reader_read_chunk(reader); - assert(st == SERD_SUCCESS); - assert(rt->n_base == 0); - assert(rt->n_prefix == 0); - assert(rt->n_statement == 3); - assert(rt->n_end == 0); - - // EOF - st = serd_reader_read_chunk(reader); - assert(st == SERD_FAILURE); - assert(rt->n_base == 0); - assert(rt->n_prefix == 0); - assert(rt->n_statement == 3); - assert(rt->n_end == 0); - - assert(serd_reader_read_chunk(reader) == SERD_FAILURE); - - serd_reader_free(reader); - fclose(f); - remove(path); -} - -static void -test_read_turtle_chunks(const char* const path) -{ - static const char null = 0; - - FILE* const f = fopen(path, "w+b"); - - // Write two statements separated by null characters - fprintf(f, "@base <http://example.org/base/> .\n"); - fprintf(f, "@prefix eg: <http://example.org/> .\n"); - fprintf(f, "eg:s eg:p1 eg:o1 ;\n"); - fprintf(f, " eg:p2 eg:o2 .\n"); - fwrite(&null, sizeof(null), 1, f); - fprintf(f, "eg:s eg:p [ eg:sp eg:so ] .\n"); - fwrite(&null, sizeof(null), 1, f); - fseek(f, 0, SEEK_SET); - - ReaderTest* const rt = (ReaderTest*)calloc(1, sizeof(ReaderTest)); - SerdReader* const reader = serd_reader_new(SERD_TURTLE, - rt, - free, - test_base_sink, - test_prefix_sink, - test_statement_sink, - test_end_sink); - - assert(reader); - assert(serd_reader_get_handle(reader) == rt); - assert(f); - - SerdStatus st = serd_reader_start_stream(reader, f, NULL, false); - assert(st == SERD_SUCCESS); - - // Read base - st = serd_reader_read_chunk(reader); - assert(st == SERD_SUCCESS); - assert(rt->n_base == 1); - assert(rt->n_prefix == 0); - assert(rt->n_statement == 0); - assert(rt->n_end == 0); - - // Read prefix - st = serd_reader_read_chunk(reader); - assert(st == SERD_SUCCESS); - assert(rt->n_base == 1); - assert(rt->n_prefix == 1); - assert(rt->n_statement == 0); - assert(rt->n_end == 0); - - // Read first two statements - st = serd_reader_read_chunk(reader); - assert(st == SERD_SUCCESS); - assert(rt->n_base == 1); - assert(rt->n_prefix == 1); - assert(rt->n_statement == 2); - assert(rt->n_end == 0); - - // Read terminator - st = serd_reader_read_chunk(reader); - assert(st == SERD_FAILURE); - assert(rt->n_base == 1); - assert(rt->n_prefix == 1); - assert(rt->n_statement == 2); - assert(rt->n_end == 0); - - // Read statements after null terminator - st = serd_reader_read_chunk(reader); - assert(st == SERD_SUCCESS); - assert(rt->n_base == 1); - assert(rt->n_prefix == 1); - assert(rt->n_statement == 4); - assert(rt->n_end == 1); - - // Read terminator - st = serd_reader_read_chunk(reader); - assert(st == SERD_FAILURE); - assert(rt->n_base == 1); - assert(rt->n_prefix == 1); - assert(rt->n_statement == 4); - assert(rt->n_end == 1); - - // EOF - st = serd_reader_read_chunk(reader); - assert(st == SERD_FAILURE); - assert(rt->n_base == 1); - assert(rt->n_prefix == 1); - assert(rt->n_statement == 4); - assert(rt->n_end == 1); - - assert(serd_reader_read_chunk(reader) == SERD_FAILURE); - - serd_reader_free(reader); - fclose(f); - remove(path); -} - -static void -test_read_string(void) -{ - ReaderTest* rt = (ReaderTest*)calloc(1, sizeof(ReaderTest)); - SerdReader* reader = serd_reader_new(SERD_TURTLE, - rt, - free, - test_base_sink, - test_prefix_sink, - test_statement_sink, - test_end_sink); - - assert(reader); - assert(serd_reader_get_handle(reader) == rt); - - // Test reading a string that ends exactly at the end of input (no newline) - const SerdStatus st = serd_reader_read_string( - reader, - USTR("<http://example.org/s> <http://example.org/p> " - "<http://example.org/o> .")); - - assert(!st); - assert(rt->n_base == 0); - assert(rt->n_prefix == 0); - assert(rt->n_statement == 1); - assert(rt->n_end == 0); - - serd_reader_free(reader); -} - static size_t faulty_sink(const void* const buf, const size_t len, void* const stream) { @@ -394,42 +103,58 @@ quiet_error_sink(void* const handle, const SerdError* const e) } static void -test_write_errors(void) +check_write_error_offset(const SerdSyntax syntax, + const size_t offset, + const SerdStatus expected_status) { - ErrorContext ctx = {0U, 0U}; + ErrorContext ctx = {0U, offset}; const SerdStyle style = (SerdStyle)(SERD_STYLE_STRICT | SERD_STYLE_CURIED); + SerdEnv* const env = serd_env_new(NULL); + assert(env); + + SerdWriter* const writer = + serd_writer_new(syntax, style, env, NULL, faulty_sink, &ctx); + assert(writer); + + SerdReader* const reader = + serd_reader_new(SERD_TRIG, + writer, + NULL, + (SerdBaseSink)serd_writer_set_base_uri, + (SerdPrefixSink)serd_writer_set_prefix, + (SerdStatementSink)serd_writer_write_statement, + (SerdEndSink)serd_writer_end_anon); + assert(reader); + + serd_writer_set_error_sink(writer, quiet_error_sink, NULL); + serd_reader_set_error_sink(reader, quiet_error_sink, NULL); + + const SerdStatus rst = serd_reader_read_string(reader, USTR(doc_string)); + const SerdStatus wst = serd_writer_finish(writer); + + serd_reader_free(reader); + serd_writer_free(writer); + serd_env_free(env); + + const SerdStatus st = rst ? rst : wst; + assert(st == expected_status); +} - const size_t max_offsets[] = {0, 386, 1911, 2003, 386}; +static void +test_write_errors(void) +{ + // Syntax-keyed array of output document sizes + static const size_t max_offsets[] = {0, 452, 1911, 2003, 466}; - // Test errors at different offsets to hit different code paths for (unsigned s = 1; s <= (unsigned)SERD_TRIG; ++s) { const SerdSyntax syntax = (SerdSyntax)s; + + // Check successfully writing with enough space + check_write_error_offset(syntax, max_offsets[s], SERD_SUCCESS); + + // Check write error at every offset in the output for (size_t o = 0; o < max_offsets[s]; ++o) { - ctx.n_written = 0; - ctx.error_offset = o; - - SerdEnv* const env = serd_env_new(NULL); - SerdWriter* const writer = - serd_writer_new(syntax, style, env, NULL, faulty_sink, &ctx); - - SerdReader* const reader = - serd_reader_new(SERD_TRIG, - writer, - NULL, - (SerdBaseSink)serd_writer_set_base_uri, - (SerdPrefixSink)serd_writer_set_prefix, - (SerdStatementSink)serd_writer_write_statement, - (SerdEndSink)serd_writer_end_anon); - - serd_reader_set_error_sink(reader, quiet_error_sink, NULL); - serd_writer_set_error_sink(writer, quiet_error_sink, NULL); - - const SerdStatus st = serd_reader_read_string(reader, USTR(doc_string)); - assert(st == SERD_ERR_BAD_WRITE); - - serd_reader_free(reader); - serd_writer_free(writer); - serd_env_free(env); + check_write_error_offset(syntax, o, SERD_ERR_BAD_WRITE); } } } @@ -437,10 +162,12 @@ test_write_errors(void) static void test_writer(const char* const path) { - FILE* fd = fopen(path, "wb"); - SerdEnv* env = serd_env_new(NULL); + FILE* const fd = fopen(path, "wb"); assert(fd); + SerdEnv* const env = serd_env_new(NULL); + assert(env); + SerdWriter* writer = serd_writer_new(SERD_TURTLE, (SerdStyle)0, env, NULL, serd_file_sink, fd); assert(writer); @@ -455,16 +182,21 @@ test_writer(const char* const path) assert(serd_writer_end_anon(writer, NULL)); assert(serd_writer_get_env(writer) == env); - uint8_t buf[] = {0x80, 0, 0, 0, 0}; - SerdNode s = serd_node_from_string(SERD_URI, USTR("")); - SerdNode p = serd_node_from_string(SERD_URI, USTR("http://example.org/pred")); - SerdNode o = serd_node_from_string(SERD_LITERAL, buf); + const uint8_t buf[] = {0x80, 0, 0, 0, 0}; - // Write 3 invalid statements (should write nothing) + const SerdNode s = serd_node_from_string(SERD_URI, USTR("")); + const SerdNode p = + serd_node_from_string(SERD_URI, USTR("http://example.org/pred")); + const SerdNode o = serd_node_from_string(SERD_LITERAL, buf); + const SerdNode t = serd_node_from_string(SERD_URI, USTR("urn:Type")); + const SerdNode l = serd_node_from_string(SERD_LITERAL, USTR("en")); + + // Attempt to write invalid statements (should write nothing) const SerdNode* junk[][5] = {{&s, &p, &SERD_NODE_NULL, NULL, NULL}, {&s, &SERD_NODE_NULL, &o, NULL, NULL}, {&SERD_NODE_NULL, &p, &o, NULL, NULL}, {&s, &o, &o, NULL, NULL}, + {&s, &o, &o, &t, &l}, {&o, &p, &o, NULL, NULL}, {&s, &p, &SERD_NODE_NULL, NULL, NULL}}; for (size_t i = 0; i < sizeof(junk) / (sizeof(SerdNode*) * 5); ++i) { @@ -478,13 +210,12 @@ test_writer(const char* const path) junk[i][4])); } - const SerdNode t = serd_node_from_string(SERD_URI, USTR("urn:Type")); - const SerdNode l = serd_node_from_string(SERD_LITERAL, USTR("en")); + // Write some valid statements const SerdNode* good[][5] = {{&s, &p, &o, NULL, NULL}, + {&s, &p, &lit, NULL, NULL}, {&s, &p, &o, &SERD_NODE_NULL, &SERD_NODE_NULL}, {&s, &p, &o, &t, NULL}, {&s, &p, &o, NULL, &l}, - {&s, &p, &o, &t, &l}, {&s, &p, &o, &t, &SERD_NODE_NULL}, {&s, &p, &o, &SERD_NODE_NULL, &l}, {&s, &p, &o, NULL, &SERD_NODE_NULL}, @@ -510,61 +241,19 @@ test_writer(const char* const path) assert(!serd_writer_write_statement( writer, 0, NULL, &s, &p, &bad_uri, NULL, NULL)); - // Write 1 valid statement - o = serd_node_from_string(SERD_LITERAL, USTR("hello")); - assert(!serd_writer_write_statement(writer, 0, NULL, &s, &p, &o, NULL, NULL)); - serd_writer_free(writer); - - // Test chunk sink - SerdChunk chunk = {NULL, 0}; - writer = serd_writer_new( - SERD_TURTLE, (SerdStyle)0, env, NULL, serd_chunk_sink, &chunk); - - o = serd_node_from_string(SERD_URI, USTR("http://example.org/base")); - assert(!serd_writer_set_base_uri(writer, &o)); - - serd_writer_free(writer); - uint8_t* out = serd_chunk_sink_finish(&chunk); - - assert(!strcmp((const char*)out, "@base <http://example.org/base> .\n")); - serd_free(out); - - // Test writing empty node - SerdNode nothing = serd_node_from_string(SERD_NOTHING, USTR("")); - - chunk.buf = NULL; - chunk.len = 0; - writer = serd_writer_new( - SERD_TURTLE, (SerdStyle)0, env, NULL, serd_chunk_sink, &chunk); - - assert(!serd_writer_write_statement( - writer, 0, NULL, &s, &p, ¬hing, NULL, NULL)); - - assert( - !strncmp((const char*)chunk.buf, "<>\n\t<http://example.org/pred> ", 30)); - - serd_writer_free(writer); - out = serd_chunk_sink_finish(&chunk); - - assert(!strcmp((const char*)out, "<>\n\t<http://example.org/pred> .\n")); - serd_free(out); - serd_env_free(env); - fclose(fd); + assert(!fclose(fd)); } static void -test_reader(const char* path) +test_reader(const char* const path) { - ReaderTest* rt = (ReaderTest*)calloc(1, sizeof(ReaderTest)); - SerdReader* reader = serd_reader_new(SERD_TURTLE, - rt, - free, - test_base_sink, - test_prefix_sink, - test_statement_sink, - test_end_sink); + ReaderTest* const rt = (ReaderTest*)calloc(1, sizeof(ReaderTest)); + assert(rt); + + SerdReader* reader = serd_reader_new( + SERD_TURTLE, rt, free, NULL, NULL, test_statement_sink, NULL); assert(reader); assert(serd_reader_get_handle(reader) == rt); @@ -590,44 +279,12 @@ test_reader(const char* path) const SerdStatus st = serd_reader_read_file(reader, USTR(path)); assert(!st); - assert(rt->n_base == 0); - assert(rt->n_prefix == 0); - assert(rt->n_statement == 13); - assert(rt->n_end == 0); + assert(rt->n_statement == 12); assert(rt->graph && rt->graph->buf && !strcmp((const char*)rt->graph->buf, "http://example.org/")); assert(serd_reader_read_string(reader, USTR("This isn't Turtle at all."))); - // A read of a big page hits EOF then fails to read chunks immediately - { - FILE* const in = fopen(path, "rb"); - serd_reader_start_stream(reader, in, (const uint8_t*)"test", true); - - assert(serd_reader_read_chunk(reader) == SERD_SUCCESS); - assert(serd_reader_read_chunk(reader) == SERD_FAILURE); - assert(serd_reader_read_chunk(reader) == SERD_FAILURE); - - serd_reader_end_stream(reader); - fclose(in); - } - - // A byte-wise reader that hits EOF once then continues (like a socket) - { - size_t n_reads = 0; - serd_reader_start_source_stream(reader, - (SerdSource)eof_test_read, - (SerdStreamErrorFunc)eof_test_error, - &n_reads, - NULL, - 1); - - assert(serd_reader_read_chunk(reader) == SERD_SUCCESS); - assert(serd_reader_read_chunk(reader) == SERD_FAILURE); - assert(serd_reader_read_chunk(reader) == SERD_SUCCESS); - assert(serd_reader_read_chunk(reader) == SERD_FAILURE); - } - serd_reader_free(reader); } @@ -644,22 +301,15 @@ main(void) #endif const char* const ttl_name = "serd_test_reader_writer.ttl"; - const char* const nq_name = "serd_test_reader_writer.nq"; const size_t ttl_name_len = strlen(ttl_name); - const size_t nq_name_len = strlen(nq_name); const size_t path_len = tmp_len + 1 + ttl_name_len; char* const path = (char*)calloc(path_len + 1, 1); + assert(path); memcpy(path, tmp, tmp_len + 1); path[tmp_len] = '/'; - - memcpy(path + tmp_len + 1, nq_name, nq_name_len + 1); - test_read_nquads_chunks(path); - memcpy(path + tmp_len + 1, ttl_name, ttl_name_len + 1); - test_read_turtle_chunks(path); - test_read_string(); test_write_errors(); test_writer(path); @@ -668,6 +318,5 @@ main(void) assert(!remove(path)); free(path); - printf("Success\n"); return 0; } diff --git a/test/test_stdin.py b/test/test_stdin.py index f976ca52..fb01f4ee 100755 --- a/test/test_stdin.py +++ b/test/test_stdin.py @@ -7,37 +7,14 @@ # pylint: disable=consider-using-f-string -import argparse -import sys -import shlex -import subprocess -import tempfile +import serd_test_util as util -parser = argparse.ArgumentParser(description=__doc__) +args = util.wrapper_args(__doc__) +command = [args.serdi, "-i", "ntriples", "-", "http://example.org"] -parser.add_argument("--serdi", default="./serdi", help="path to serdi") -parser.add_argument("--wrapper", default="", help="executable wrapper") +DOC = "<{0}s> <{0}p> <{0}o> .".format("http://example.org/") -args = parser.parse_args(sys.argv[1:]) -command = shlex.split(args.wrapper) + [args.serdi, "-"] +lines = util.command_output(args.wrapper, command, DOC).splitlines(True) -DOCUMENT = "<{0}s> <{0}p> <{0}o> .".format("http://example.org/") - -with tempfile.TemporaryFile() as out: - proc = subprocess.run( - command, - check=False, - encoding="utf-8", - input=DOCUMENT, - stdout=out, - stderr=subprocess.PIPE, - ) - - assert proc.returncode == 0 - assert args.wrapper or len(proc.stderr) == 0 - - out.seek(0) - lines = out.readlines() - - assert len(lines) == 1 - assert lines[0].decode("utf-8").strip() == DOCUMENT +assert len(lines) == 1 +assert lines[0].strip() == DOC diff --git a/test/test_string.c b/test/test_string.c index 6767e5ae..86b5d19e 100644 --- a/test/test_string.c +++ b/test/test_string.c @@ -3,27 +3,38 @@ #undef NDEBUG -#include "serd/serd.h" +#include <serd/serd.h> #include <assert.h> #include <stdint.h> -#include <stdio.h> #include <string.h> 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 @@ -45,7 +56,5 @@ main(void) { test_strlen(); test_strerror(); - - printf("Success\n"); return 0; } diff --git a/test/test_uri.c b/test/test_uri.c index cc81b40e..96fde600 100644 --- a/test/test_uri.c +++ b/test/test_uri.c @@ -3,12 +3,11 @@ #undef NDEBUG -#include "serd/serd.h" +#include <serd/serd.h> #include <assert.h> #include <stdbool.h> #include <stdint.h> -#include <stdio.h> #include <string.h> #define USTR(s) ((const uint8_t*)(s)) @@ -16,6 +15,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"))); @@ -35,11 +36,11 @@ test_uri_string_has_scheme(void) } static void -test_file_uri(const char* const hostname, - const char* const path, - const bool escape, - const char* const expected_uri, - const char* expected_path) +check_file_uri(const char* const hostname, + const char* const path, + const bool escape, + const char* const expected_uri, + const char* expected_path) { if (!expected_path) { expected_path = path; @@ -51,6 +52,7 @@ test_file_uri(const char* const hostname, uint8_t* out_path = serd_file_uri_parse((const uint8_t*)node.buf, &out_hostname); + assert(out_path); assert(!strcmp((const char*)node.buf, expected_uri)); assert((hostname && out_hostname) || (!hostname && !out_hostname)); assert(!hostname || !strcmp(hostname, (const char*)out_hostname)); @@ -67,38 +69,27 @@ test_file_uri(const char* const hostname, #endif static void -test_uri_to_path(void) +check_uri_to_path(const char* const uri, const char* const expected_path) { - assert(!strcmp( - (const char*)serd_uri_to_path((const uint8_t*)"file:///home/user/foo.ttl"), - "/home/user/foo.ttl")); - - assert(!strcmp((const char*)serd_uri_to_path( - (const uint8_t*)"file://localhost/home/user/foo.ttl"), - "/home/user/foo.ttl")); - - assert(!serd_uri_to_path((const uint8_t*)"file:illegal/file/uri")); - - assert(!strcmp( - (const char*)serd_uri_to_path((const uint8_t*)"file:///c:/awful/system"), - "c:/awful/system")); - - assert(!strcmp( - (const char*)serd_uri_to_path((const uint8_t*)"file:///c:awful/system"), - "/c:awful/system")); - - assert(!strcmp((const char*)serd_uri_to_path((const uint8_t*)"file:///0/1"), - "/0/1")); - - assert( - !strcmp((const char*)serd_uri_to_path((const uint8_t*)"C:\\Windows\\Sucks"), - "C:\\Windows\\Sucks")); - - assert( - !strcmp((const char*)serd_uri_to_path((const uint8_t*)"C|/Windows/Sucks"), - "C|/Windows/Sucks")); + const uint8_t* const path = serd_uri_to_path((const uint8_t*)uri); + assert(path); + assert(!strcmp((const char*)path, expected_path)); +} +static void +test_uri_to_path(void) +{ + assert(!serd_uri_to_path((const uint8_t*)"file:invalid/file/uri")); assert(!serd_uri_to_path((const uint8_t*)"http://example.org/path")); + + check_uri_to_path("file:///home/user/foo.ttl", "/home/user/foo.ttl"); + check_uri_to_path("file://localhost/home/user/foo.ttl", "/home/user/foo.ttl"); + check_uri_to_path("file:///c:/awful/system", "c:/awful/system"); + check_uri_to_path("file:///c:awful/system", "/c:awful/system"); + check_uri_to_path("file:///0/1", "/0/1"); + check_uri_to_path("C:\\Windows\\Sucks", "C:\\Windows\\Sucks"); + check_uri_to_path("C|/Windows/Sucks", "C|/Windows/Sucks"); + check_uri_to_path("rel", "rel"); } #if defined(__GNUC__) @@ -108,69 +99,81 @@ test_uri_to_path(void) static void test_uri_parsing(void) { - test_file_uri(NULL, "C:/My 100%", true, "file:///C:/My%20100%%", NULL); - test_file_uri(NULL, "/foo/bar", true, "file:///foo/bar", NULL); - test_file_uri("bhost", "/foo/bar", true, "file://bhost/foo/bar", NULL); - test_file_uri(NULL, "a/relative path", false, "a/relative path", NULL); - test_file_uri( + check_file_uri(NULL, "C:/My 100%", true, "file:///C:/My%20100%%", NULL); + check_file_uri(NULL, "/foo/bar", true, "file:///foo/bar", NULL); + check_file_uri("bhost", "/foo/bar", true, "file://bhost/foo/bar", NULL); + check_file_uri(NULL, "a/relative path", false, "a/relative path", NULL); + check_file_uri( NULL, "a/relative <path>", true, "a/relative%20%3Cpath%3E", NULL); #ifdef _WIN32 - test_file_uri( + check_file_uri( NULL, "C:\\My 100%", true, "file:///C:/My%20100%%", "C:/My 100%"); - test_file_uri(NULL, - "\\drive\\relative", - true, - "file:///drive/relative", - "/drive/relative"); - - test_file_uri(NULL, - "C:\\Program Files\\Serd", - true, - "file:///C:/Program%20Files/Serd", - "C:/Program Files/Serd"); - - test_file_uri("ahost", - "C:\\Pointless Space", - true, - "file://ahost/C:/Pointless%20Space", - "C:/Pointless Space"); + check_file_uri(NULL, + "\\drive\\relative", + true, + "file:///drive/relative", + "/drive/relative"); + + check_file_uri(NULL, + "C:\\Program Files\\Serd", + true, + "file:///C:/Program%20Files/Serd", + "C:/Program Files/Serd"); + + check_file_uri("ahost", + "C:\\Pointless Space", + true, + "file://ahost/C:/Pointless%20Space", + "C:/Pointless Space"); #else /* What happens with Windows paths on other platforms is a bit weird, but more or less unavoidable. It doesn't work to interpret backslashes as path separators on any other platform. */ - test_file_uri("ahost", - "C:\\Pointless Space", - true, - "file://ahost/C:%5CPointless%20Space", - "/C:\\Pointless Space"); - - test_file_uri(NULL, - "\\drive\\relative", - true, - "%5Cdrive%5Crelative", - "\\drive\\relative"); - - test_file_uri(NULL, - "C:\\Program Files\\Serd", - true, - "file:///C:%5CProgram%20Files%5CSerd", - "/C:\\Program Files\\Serd"); - - test_file_uri("ahost", - "C:\\Pointless Space", - true, - "file://ahost/C:%5CPointless%20Space", - "/C:\\Pointless Space"); + check_file_uri("ahost", + "C:\\Pointless Space", + true, + "file://ahost/C:%5CPointless%20Space", + "/C:\\Pointless Space"); + + check_file_uri(NULL, + "\\drive\\relative", + true, + "%5Cdrive%5Crelative", + "\\drive\\relative"); + + check_file_uri(NULL, + "C:\\Program Files\\Serd", + true, + "file:///C:%5CProgram%20Files%5CSerd", + "/C:\\Program Files\\Serd"); + + check_file_uri("ahost", + "C:\\Pointless Space", + true, + "file://ahost/C:%5CPointless%20Space", + "/C:\\Pointless Space"); #endif + // Test tolerance of NULL hostname parameter + uint8_t* const hosted = serd_file_uri_parse(USTR("file://host/path"), NULL); + assert(hosted); + 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(junk1); + assert(!strcmp((const char*)junk1, "/foo/bar")); + serd_free(junk1); + + uint8_t* const junk2 = serd_file_uri_parse(USTR("file:///foo/%X0bar"), NULL); + assert(junk2); + assert(!strcmp((const char*)junk2, "/foo/bar")); + serd_free(junk2); } static void @@ -194,8 +197,8 @@ test_uri_from_string(void) serd_node_free(&base); } -static inline bool -chunk_equals(const SerdChunk* a, const SerdChunk* b) +static bool +chunk_equals(const SerdChunk* const a, const SerdChunk* const b) { return (!a->len && !b->len && !a->buf && !b->buf) || (a->len && b->len && a->buf && b->buf && @@ -343,6 +346,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 @@ -353,7 +372,5 @@ main(void) test_uri_parsing(); test_uri_from_string(); test_relative_uri(); - - printf("Success\n"); return 0; } diff --git a/test/test_write_error.py b/test/test_write_error.py index 35fde232..93b0249a 100755 --- a/test/test_write_error.py +++ b/test/test_write_error.py @@ -1,33 +1,32 @@ #!/usr/bin/env python3 -# Copyright 2022-2023 David Robillard <d@drobilla.net> +# Copyright 2022-2025 David Robillard <d@drobilla.net> # SPDX-License-Identifier: ISC """Test errors writing to a file.""" -import argparse import sys import shlex import subprocess import os -parser = argparse.ArgumentParser(description=__doc__) +import serd_test_util as util -parser.add_argument("--serdi", default="./serdi", help="path to serdi") -parser.add_argument("--wrapper", default="", help="executable wrapper") -parser.add_argument("input", help="valid input file") - -args = parser.parse_args(sys.argv[1:]) +args = util.wrapper_args(__doc__, True) command = shlex.split(args.wrapper) + [args.serdi, args.input] if os.path.exists("/dev/full"): with open("/dev/full", "w", encoding="utf-8") as out: proc = subprocess.run( - command, check=False, stdout=out, stderr=subprocess.PIPE + command, + encoding="utf-8", + check=False, + stdout=out, + stderr=subprocess.PIPE, ) assert proc.returncode != 0 - assert "error" in proc.stderr.decode("utf-8") + assert "error" in proc.stderr else: sys.stderr.write("warning: /dev/full not present, skipping test") diff --git a/test/test_writer.c b/test/test_writer.c index b02aba7e..51f5d9ed 100644 --- a/test/test_writer.c +++ b/test/test_writer.c @@ -1,15 +1,17 @@ -// Copyright 2011-2023 David Robillard <d@drobilla.net> +// Copyright 2011-2025 David Robillard <d@drobilla.net> // SPDX-License-Identifier: ISC #undef NDEBUG -#include "serd/serd.h" +#include <serd/serd.h> #include <assert.h> #include <stdint.h> #include <stdio.h> #include <string.h> +#define NS_EG "http://example.org/" + #define USTR(s) ((const uint8_t*)(s)) static void @@ -19,27 +21,27 @@ test_write_long_literal(void) SerdChunk chunk = {NULL, 0}; SerdWriter* writer = serd_writer_new( SERD_TURTLE, (SerdStyle)0, env, NULL, serd_chunk_sink, &chunk); - assert(writer); - SerdNode s = serd_node_from_string(SERD_URI, USTR("http://example.org/s")); - SerdNode p = serd_node_from_string(SERD_URI, USTR("http://example.org/p")); + SerdNode s = serd_node_from_string(SERD_URI, USTR(NS_EG "s")); + SerdNode p = serd_node_from_string(SERD_URI, USTR(NS_EG "p")); SerdNode o = serd_node_from_string(SERD_LITERAL, USTR("hello \"\"\"world\"\"\"!")); assert(!serd_writer_write_statement(writer, 0, NULL, &s, &p, &o, NULL, NULL)); - - serd_writer_free(writer); - serd_env_free(env); - - uint8_t* out = serd_chunk_sink_finish(&chunk); + assert(!serd_writer_finish(writer)); static const char* const expected = "<http://example.org/s>\n" "\t<http://example.org/p> \"\"\"hello \"\"\\\"world\"\"\\\"!\"\"\" .\n"; + uint8_t* const out = serd_chunk_sink_finish(&chunk); + assert(out); assert(!strcmp((char*)out, expected)); serd_free(out); + + serd_writer_free(writer); + serd_env_free(env); } static void @@ -49,19 +51,18 @@ test_write_nested_anon(void) SerdChunk chunk = {NULL, 0}; SerdWriter* writer = serd_writer_new( SERD_TURTLE, (SerdStyle)0, env, NULL, serd_chunk_sink, &chunk); - assert(writer); - SerdNode s0 = serd_node_from_string(SERD_URI, USTR("http://example.org/s0")); - SerdNode p0 = serd_node_from_string(SERD_URI, USTR("http://example.org/p0")); + SerdNode s0 = serd_node_from_string(SERD_URI, USTR(NS_EG "s0")); + SerdNode p0 = serd_node_from_string(SERD_URI, USTR(NS_EG "p0")); SerdNode b0 = serd_node_from_string(SERD_BLANK, USTR("b0")); - SerdNode p1 = serd_node_from_string(SERD_URI, USTR("http://example.org/p1")); + SerdNode p1 = serd_node_from_string(SERD_URI, USTR(NS_EG "p1")); SerdNode b1 = serd_node_from_string(SERD_BLANK, USTR("b1")); - SerdNode p2 = serd_node_from_string(SERD_URI, USTR("http://example.org/p2")); - SerdNode o2 = serd_node_from_string(SERD_URI, USTR("http://example.org/o2")); - SerdNode p3 = serd_node_from_string(SERD_URI, USTR("http://example.org/p3")); - SerdNode p4 = serd_node_from_string(SERD_URI, USTR("http://example.org/p4")); - SerdNode o4 = serd_node_from_string(SERD_URI, USTR("http://example.org/o4")); + SerdNode p2 = serd_node_from_string(SERD_URI, USTR(NS_EG "p2")); + SerdNode o2 = serd_node_from_string(SERD_URI, USTR(NS_EG "o2")); + SerdNode p3 = serd_node_from_string(SERD_URI, USTR(NS_EG "p3")); + SerdNode p4 = serd_node_from_string(SERD_URI, USTR(NS_EG "p4")); + SerdNode o4 = serd_node_from_string(SERD_URI, USTR(NS_EG "o4")); SerdNode nil = serd_node_from_string( SERD_URI, USTR("http://www.w3.org/1999/02/22-rdf-syntax-ns#nil")); @@ -94,11 +95,7 @@ test_write_nested_anon(void) writer, SERD_ANON_CONT, NULL, &b0, &p4, &o4, NULL, NULL)); assert(!serd_writer_end_anon(writer, &b0)); - - serd_writer_free(writer); - serd_env_free(env); - - uint8_t* const out = serd_chunk_sink_finish(&chunk); + assert(!serd_writer_finish(writer)); static const char* const expected = "<http://example.org/s0>\n" @@ -110,9 +107,13 @@ test_write_nested_anon(void) "\t\t<http://example.org/p4> <http://example.org/o4>\n" "\t] .\n"; - fprintf(stderr, "%s\n", out); + uint8_t* const out = serd_chunk_sink_finish(&chunk); + assert(out); assert(!strcmp((char*)out, expected)); serd_free(out); + + serd_writer_free(writer); + serd_env_free(env); } static size_t @@ -131,10 +132,13 @@ test_writer_cleanup(void) SerdEnv* env = serd_env_new(NULL); SerdWriter* writer = serd_writer_new(SERD_TURTLE, (SerdStyle)0U, env, NULL, null_sink, NULL); + assert(writer); - SerdNode s = serd_node_from_string(SERD_URI, USTR("http://example.org/s")); - SerdNode p = serd_node_from_string(SERD_URI, USTR("http://example.org/p")); - SerdNode o = serd_node_from_string(SERD_BLANK, USTR("http://example.org/o")); + SerdNode s = serd_node_from_string(SERD_URI, USTR(NS_EG "s")); + SerdNode p = serd_node_from_string(SERD_URI, USTR(NS_EG "p")); + + char o_buf[12] = {'b', '0', '\0'}; + SerdNode o = serd_node_from_string(SERD_BLANK, USTR(o_buf)); st = serd_writer_write_statement( writer, SERD_ANON_O_BEGIN, NULL, &s, &p, &o, NULL, NULL); @@ -142,23 +146,33 @@ test_writer_cleanup(void) assert(!st); // Write the start of several nested anonymous objects - for (unsigned i = 0U; !st && i < 8U; ++i) { - char buf[12] = {0}; - snprintf(buf, sizeof(buf), "b%u", i); + for (unsigned i = 1U; !st && i < 9U; ++i) { + char next_o_buf[12] = {'\0'}; + snprintf(next_o_buf, sizeof(next_o_buf), "b%u", i); + + SerdNode next_o = serd_node_from_string(SERD_BLANK, USTR(next_o_buf)); - SerdNode next_o = serd_node_from_string(SERD_BLANK, USTR(buf)); + st = serd_writer_write_statement(writer, + SERD_ANON_O_BEGIN | SERD_ANON_CONT, + NULL, + &o, + &p, + &next_o, + NULL, + NULL); - st = serd_writer_write_statement( - writer, SERD_ANON_O_BEGIN, NULL, &o, &p, &next_o, NULL, NULL); + assert(!st); - o = next_o; + memcpy(o_buf, next_o_buf, sizeof(o_buf)); } // Finish writing without terminating nodes - assert(!(st = serd_writer_finish(writer))); + st = serd_writer_finish(writer); + assert(!st); // Set the base to an empty URI - assert(!(st = serd_writer_set_base_uri(writer, NULL))); + st = serd_writer_set_base_uri(writer, NULL); + assert(!st); // Free (which could leak if the writer doesn't clean up the stack properly) serd_writer_free(writer); @@ -166,22 +180,49 @@ test_writer_cleanup(void) } static void -test_strict_write(void) +test_write_bad_anon_stack(void) { - const char* const path = "serd_strict_write_test.ttl"; - FILE* const fd = fopen(path, "wb"); - assert(fd); + SerdStatus st = SERD_SUCCESS; + SerdEnv* env = serd_env_new(NULL); + SerdWriter* writer = + serd_writer_new(SERD_TURTLE, (SerdStyle)0U, env, NULL, null_sink, NULL); + assert(writer); + + SerdNode s = serd_node_from_string(SERD_URI, USTR(NS_EG "s")); + SerdNode p = serd_node_from_string(SERD_URI, USTR(NS_EG "p")); + SerdNode b0 = serd_node_from_string(SERD_BLANK, USTR("b0")); + SerdNode b1 = serd_node_from_string(SERD_BLANK, USTR("b1")); + SerdNode b2 = serd_node_from_string(SERD_BLANK, USTR("b2")); + + st = serd_writer_write_statement( + writer, SERD_ANON_O_BEGIN, NULL, &s, &p, &b0, NULL, NULL); + assert(!st); + + // (missing call to end the anonymous node here) + + st = serd_writer_write_statement( + writer, SERD_ANON_O_BEGIN, NULL, &b1, &p, &b2, NULL, NULL); + assert(st == SERD_ERR_BAD_ARG); + + st = serd_writer_finish(writer); + assert(!st); + serd_writer_free(writer); + serd_env_free(env); +} + +static void +test_strict_write(void) +{ SerdEnv* const env = serd_env_new(NULL); SerdWriter* const writer = serd_writer_new( - SERD_TURTLE, (SerdStyle)SERD_STYLE_STRICT, env, NULL, null_sink, fd); - + SERD_TURTLE, (SerdStyle)SERD_STYLE_STRICT, env, NULL, null_sink, NULL); assert(writer); const uint8_t bad_str[] = {0xFF, 0x90, 'h', 'i', 0}; - SerdNode s = serd_node_from_string(SERD_URI, USTR("http://example.org/s")); - SerdNode p = serd_node_from_string(SERD_URI, USTR("http://example.org/p")); + SerdNode s = serd_node_from_string(SERD_URI, USTR(NS_EG "s")); + SerdNode p = serd_node_from_string(SERD_URI, USTR(NS_EG "p")); SerdNode bad_lit = serd_node_from_string(SERD_LITERAL, bad_str); SerdNode bad_uri = serd_node_from_string(SERD_URI, bad_str); @@ -194,8 +235,6 @@ test_strict_write(void) serd_writer_free(writer); serd_env_free(env); - fclose(fd); - remove(path); } // Produce a write error without setting errno @@ -211,19 +250,129 @@ error_sink(const void* const buf, const size_t len, void* const stream) static void test_write_error(void) { - SerdEnv* const env = serd_env_new(NULL); - SerdWriter* writer = NULL; - SerdStatus st = SERD_SUCCESS; + SerdEnv* const env = serd_env_new(NULL); - SerdNode u = serd_node_from_string(SERD_URI, USTR("http://example.com/u")); - - writer = + SerdWriter* const writer = serd_writer_new(SERD_TURTLE, (SerdStyle)0, env, NULL, error_sink, NULL); assert(writer); - st = serd_writer_write_statement(writer, 0U, NULL, &u, &u, &u, NULL, NULL); + + SerdNode u = serd_node_from_string(SERD_URI, USTR("http://example.com/u")); + + const SerdStatus st = + serd_writer_write_statement(writer, 0U, NULL, &u, &u, &u, NULL, NULL); assert(st == SERD_ERR_BAD_WRITE); + + serd_writer_free(writer); + serd_env_free(env); +} + +static void +test_chunk_sink(void) +{ + SerdEnv* const env = serd_env_new(NULL); + assert(env); + + SerdChunk chunk = {NULL, 0}; + SerdWriter* const writer = serd_writer_new( + SERD_TURTLE, (SerdStyle)0, env, NULL, serd_chunk_sink, &chunk); + assert(writer); + + const SerdNode base = + serd_node_from_string(SERD_URI, USTR("http://example.org/base")); + assert(!serd_writer_set_base_uri(writer, &base)); + assert(!serd_writer_finish(writer)); + + uint8_t* const out = serd_chunk_sink_finish(&chunk); + assert(out); + assert(!strcmp((const char*)out, "@base <http://example.org/base> .\n")); + serd_free(out); + + serd_writer_free(writer); + serd_env_free(env); +} + +static void +test_write_nothing_node(void) +{ + SerdEnv* const env = serd_env_new(NULL); + assert(env); + + SerdChunk chunk = {NULL, 0}; + SerdWriter* const writer = serd_writer_new( + SERD_TURTLE, (SerdStyle)0, env, NULL, serd_chunk_sink, &chunk); + assert(writer); + + SerdNode s = serd_node_from_string(SERD_URI, USTR("")); + SerdNode p = serd_node_from_string(SERD_URI, USTR("http://example.org/pred")); + SerdNode o = serd_node_from_string(SERD_NOTHING, USTR("")); + assert(serd_writer_write_statement(writer, 0, NULL, &s, &p, &o, NULL, NULL) == + SERD_ERR_BAD_ARG); + + assert(!chunk.buf); serd_writer_free(writer); + serd_env_free(env); +} + +static void +test_write_bad_statement(void) +{ + SerdEnv* const env = serd_env_new(NULL); + assert(env); + + SerdChunk chunk = {NULL, 0}; + SerdWriter* const writer = serd_writer_new( + SERD_TURTLE, (SerdStyle)0, env, NULL, serd_chunk_sink, &chunk); + assert(writer); + SerdNode s = serd_node_from_string(SERD_URI, USTR("http://example.org/s")); + SerdNode p = serd_node_from_string(SERD_URI, USTR("http://example.org/p")); + SerdNode o = serd_node_from_string(SERD_URI, USTR("http://example.org/o")); + SerdNode l = serd_node_from_string(SERD_LITERAL, USTR("lang")); + + assert(serd_writer_write_statement( + writer, + (SerdStatementFlags)(SERD_ANON_S_BEGIN | SERD_LIST_S_BEGIN), + NULL, + &s, + &p, + &o, + NULL, + NULL) == SERD_ERR_BAD_ARG); + + assert(serd_writer_write_statement( + writer, + (SerdStatementFlags)(SERD_EMPTY_S | SERD_LIST_S_BEGIN), + NULL, + &s, + &p, + &o, + NULL, + NULL) == SERD_ERR_BAD_ARG); + + assert(serd_writer_write_statement( + writer, + (SerdStatementFlags)(SERD_ANON_O_BEGIN | SERD_LIST_O_BEGIN), + NULL, + &s, + &p, + &o, + NULL, + NULL) == SERD_ERR_BAD_ARG); + + assert(serd_writer_write_statement( + writer, + (SerdStatementFlags)(SERD_EMPTY_O | SERD_LIST_O_BEGIN), + NULL, + &s, + &p, + &o, + NULL, + NULL) == SERD_ERR_BAD_ARG); + + assert(serd_writer_write_statement(writer, 0U, NULL, &s, &p, &o, &o, &l) == + SERD_ERR_BAD_ARG); + + serd_writer_free(writer); serd_env_free(env); } @@ -233,8 +382,14 @@ main(void) test_write_long_literal(); test_write_nested_anon(); test_writer_cleanup(); + test_write_bad_anon_stack(); test_strict_write(); test_write_error(); + test_chunk_sink(); + test_write_nothing_node(); + test_write_bad_statement(); return 0; } + +#undef NS_EG |