diff options
author | David Robillard <d@drobilla.net> | 2021-08-12 22:28:59 -0400 |
---|---|---|
committer | David Robillard <d@drobilla.net> | 2022-01-28 21:57:07 -0500 |
commit | 1409f161793a289819df1f31eccb579b71f45475 (patch) | |
tree | 4076c291a397f0a0a2ea560305ee87c47810df33 | |
parent | 6ffe331cfc8af0735b263ab7af6f84b1b4418102 (diff) | |
download | serd-1409f161793a289819df1f31eccb579b71f45475.tar.gz serd-1409f161793a289819df1f31eccb579b71f45475.tar.bz2 serd-1409f161793a289819df1f31eccb579b71f45475.zip |
Fix pretty-printing nested empty lists and add test suite
The earlier "test" was just hitting the code without actually checking the
output. This new suite is a set of pretty-printed documents which serd must
reproduce from a model exactly to pass. This should make it easy to add cases
in the future, since each case is just a document, as it should look.
28 files changed, 446 insertions, 202 deletions
diff --git a/src/describe.c b/src/describe.c index 9bd9d3ae..718eaf1c 100644 --- a/src/describe.c +++ b/src/describe.c @@ -204,7 +204,7 @@ write_range_statement(const SerdSink* const sink, // First write inline list subject, which this statement will follow if (zix_hash_insert(list_subjects, subject) != ZIX_STATUS_EXISTS) { st = write_list( - sink, model, list_subjects, 2, SERD_LIST_S, subject, graph); + sink, model, list_subjects, 2, flags | SERD_LIST_S, subject, graph); } } } @@ -226,9 +226,12 @@ write_range_statement(const SerdSink* const sink, serd_cursor_free(iter); } else if (object_style == LIST_O) { // Write list object like "( ... )" - flags |= SERD_LIST_O; - if (!(st = serd_sink_write_statement(sink, flags, statement))) { - st = write_list(sink, model, list_subjects, depth + 1, 0, object, graph); + if (!(st = + serd_sink_write_statement(sink, flags | SERD_LIST_O, statement))) { + flags = flags & ~((unsigned)SERD_LIST_S); + + st = + write_list(sink, model, list_subjects, depth + 1, flags, object, graph); } } else { @@ -866,11 +866,11 @@ read_collection(SerdReader* const reader, return SERD_ERR_OVERFLOW; } - if (ctx.subject) { - // subject predicate _:head + if (ctx.subject) { // Reading a collection object *ctx.flags |= (end ? 0 : SERD_LIST_O); TRY(st, emit_statement(reader, ctx, *dest)); - } else { + *ctx.flags &= ~((unsigned)SERD_LIST_O); + } else { // Reading a collection subject *ctx.flags |= (end ? 0 : SERD_LIST_S); } diff --git a/src/writer.c b/src/writer.c index 5f9fdaab..452d3679 100644 --- a/src/writer.c +++ b/src/writer.c @@ -1064,6 +1064,11 @@ write_list_statement(SerdWriter* const writer, SerdStatus st = SERD_SUCCESS; bool is_end = false; + if (serd_node_equals(predicate, writer->world->rdf_first) && + serd_node_equals(object, writer->world->rdf_nil)) { + return esink("()", 2, writer); + } + TRY(st, write_list_obj(writer, flags, predicate, object, &is_end)); if (is_end) { pop_context(writer); diff --git a/test/good/manifest.ttl b/test/good/manifest.ttl index b546b9f7..0198a8c8 100644 --- a/test/good/manifest.ttl +++ b/test/good/manifest.ttl @@ -46,7 +46,6 @@ <#test-non-curie-uri> <#test-num> <#test-prefix> - <#test-pretty> <#test-rel> <#test-semi-dot> <#test-uri-escape> @@ -276,12 +275,6 @@ mf:action <test-prefix.ttl> ; mf:result <test-prefix.nt> . -<#test-pretty> - rdf:type rdft:TestTurtleEval ; - mf:name "test-pretty" ; - mf:action <test-pretty.ttl> ; - mf:result <test-pretty.nt> . - <#test-rel> rdf:type rdft:TestTurtleEval ; mf:name "test-rel" ; diff --git a/test/good/pretty.trig b/test/good/pretty.trig deleted file mode 100644 index 140769ce..00000000 --- a/test/good/pretty.trig +++ /dev/null @@ -1,98 +0,0 @@ -@prefix : <http://example.org/> . -@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> . - -:a - :b :c , - :d , - :e ; - :f :g , - :h . - -( - 1 -) - :isA :List . - -[] - :isA :Blank . - -( - 2 -) - :sameAs ( - 2 - ) . - -[] - :sameAs [] . - -( - 1 - 2 -) - a :List ; - rdf:value 3 . - -( - ( - 3 - ) - ( - 4 - ) -) - a :NestedList ; - :sum 7 . - -[ - a :BlankSubject -] - a rdf:Resource . - -[ - a :BlankSubject -] . - -[] - :blank [ - :nestedEmptyBlank [] ; - :nestedNonEmptyBlanks [ - rdf:value 1 - ] , [ - rdf:value 2 - ] - ] ; - :lists ( - 3 - 4 - ) , ( - 5 - 6 - ) , ( - [ - rdf:value 7 - ] - [ - rdf:value 8 - ] - ) . - -:s - a :Thing ; - :predicate1 :object1 , - [ - a :SubThing ; - :predicate2 :object2 - ] , [ - a :OtherSubThing ; - :p3 :o3 - ] ; - :p4 :o4 . - -eg:graph { - :a - :b :c ; - :d [ - :e :f - ] . -} diff --git a/test/good/test-pretty.nt b/test/good/test-pretty.nt deleted file mode 100644 index 9251563a..00000000 --- a/test/good/test-pretty.nt +++ /dev/null @@ -1,46 +0,0 @@ -<http://www.w3.org/1999/02/22-rdf-syntax-ns#nil> <http://example.org/isA> <http://example.org/List> . -_:b1 <http://example.org/isA> <http://example.org/Blank> . -<http://www.w3.org/1999/02/22-rdf-syntax-ns#nil> <http://example.org/sameAs> <http://www.w3.org/1999/02/22-rdf-syntax-ns#nil> . -_:b2 <http://example.org/sameAs> _:b3 . -_:b4 <http://www.w3.org/1999/02/22-rdf-syntax-ns#first> "apple" . -_:b4 <http://www.w3.org/1999/02/22-rdf-syntax-ns#rest> _:b5 . -_:b5 <http://www.w3.org/1999/02/22-rdf-syntax-ns#first> "banana" . -_:b5 <http://www.w3.org/1999/02/22-rdf-syntax-ns#rest> _:b6 . -_:b6 <http://www.w3.org/1999/02/22-rdf-syntax-ns#first> "pear" . -_:b6 <http://www.w3.org/1999/02/22-rdf-syntax-ns#rest> <http://www.w3.org/1999/02/22-rdf-syntax-ns#nil> . -_:b4 <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://example.org/List> . -_:b7 <http://www.w3.org/1999/02/22-rdf-syntax-ns#first> _:b8 . -_:b8 <http://www.w3.org/1999/02/22-rdf-syntax-ns#first> <http://example.org/a> . -_:b8 <http://www.w3.org/1999/02/22-rdf-syntax-ns#rest> _:b9 . -_:b9 <http://www.w3.org/1999/02/22-rdf-syntax-ns#first> <http://example.org/b> . -_:b9 <http://www.w3.org/1999/02/22-rdf-syntax-ns#rest> <http://www.w3.org/1999/02/22-rdf-syntax-ns#nil> . -_:b7 <http://www.w3.org/1999/02/22-rdf-syntax-ns#rest> _:b10 . -_:b10 <http://www.w3.org/1999/02/22-rdf-syntax-ns#first> _:b11 . -_:b11 <http://www.w3.org/1999/02/22-rdf-syntax-ns#first> <http://example.org/c> . -_:b11 <http://www.w3.org/1999/02/22-rdf-syntax-ns#rest> _:b12 . -_:b12 <http://www.w3.org/1999/02/22-rdf-syntax-ns#first> <http://example.org/d> . -_:b12 <http://www.w3.org/1999/02/22-rdf-syntax-ns#rest> <http://www.w3.org/1999/02/22-rdf-syntax-ns#nil> . -_:b10 <http://www.w3.org/1999/02/22-rdf-syntax-ns#rest> <http://www.w3.org/1999/02/22-rdf-syntax-ns#nil> . -_:b7 <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://example.org/List> . -_:b13 <http://example.org/list> _:b14 . -_:b14 <http://www.w3.org/1999/02/22-rdf-syntax-ns#first> "apple" . -_:b14 <http://www.w3.org/1999/02/22-rdf-syntax-ns#rest> _:b15 . -_:b15 <http://www.w3.org/1999/02/22-rdf-syntax-ns#first> "banana" . -_:b15 <http://www.w3.org/1999/02/22-rdf-syntax-ns#rest> _:b16 . -_:b16 <http://www.w3.org/1999/02/22-rdf-syntax-ns#first> "pear" . -_:b16 <http://www.w3.org/1999/02/22-rdf-syntax-ns#rest> <http://www.w3.org/1999/02/22-rdf-syntax-ns#nil> . -_:b17 <http://example.org/a> <http://example.org/b> . -_:b17 <http://example.org/a> <http://example.org/c> . -_:b17 <http://example.org/a> <http://example.org/d> . -_:b18 <http://example.org/a> _:b19 . -_:b19 <http://example.org/b> <http://example.org/c> . -_:b19 <http://example.org/d> <http://example.org/e> . -_:b18 <http://example.org/a> _:b20 . -_:b20 <http://example.org/f> <http://example.org/g> . -_:b21 <http://example.org/list> _:b22 . -_:b22 <http://www.w3.org/1999/02/22-rdf-syntax-ns#first> _:b23 . -_:b23 <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://example.org/Apple> . -_:b22 <http://www.w3.org/1999/02/22-rdf-syntax-ns#rest> _:b24 . -_:b24 <http://www.w3.org/1999/02/22-rdf-syntax-ns#first> _:b25 . -_:b25 <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://example.org/Banana> . -_:b24 <http://www.w3.org/1999/02/22-rdf-syntax-ns#rest> <http://www.w3.org/1999/02/22-rdf-syntax-ns#nil> . diff --git a/test/good/test-pretty.ttl b/test/good/test-pretty.ttl deleted file mode 100644 index 4eb7204f..00000000 --- a/test/good/test-pretty.ttl +++ /dev/null @@ -1,44 +0,0 @@ -@prefix : <http://example.org/> . - -() :isA :List . - -[] :isA :Blank . - -() :sameAs () . - -[] :sameAs [] . - -( - "apple" - "banana" - "pear" -) a :List . - -( - (:a :b) - (:c :d) -) a :List . - -[] - :list ( - "apple" - "banana" - "pear" - ) . - -[] - :a :b , :c , :d . - -[] - :a [ - :b :c ; - :d :e ; - ] , [ - :f :g - ] . - -[] - :list ( - [ a :Apple ] - [ a :Banana ] - ) .
\ No newline at end of file diff --git a/test/meson.build b/test/meson.build index c0ed56e4..c314e1d4 100644 --- a/test/meson.build +++ b/test/meson.build @@ -2,6 +2,7 @@ autoship = find_program('autoship', required: false) run_filter_suite = find_program('run_filter_suite.py') run_pipe_suite = find_program('run_pipe_suite.py') +run_pretty_suite = find_program('run_pretty_suite.py') run_sort_suite = find_program('run_sort_suite.py') wrapper = meson.get_cross_property('exe_wrapper', '') @@ -404,6 +405,7 @@ if is_variable('serd_pipe') and is_variable('serd_sort') subdir('good') subdir('lax') subdir('pattern') + subdir('pretty') subdir('terse') endif diff --git a/test/pretty/anonymous-in-list-object.ttl b/test/pretty/anonymous-in-list-object.ttl new file mode 100644 index 00000000..a6b202f4 --- /dev/null +++ b/test/pretty/anonymous-in-list-object.ttl @@ -0,0 +1,11 @@ +@prefix eg: <http://example.org/> . + +eg:s + eg:p ( + [ + a eg:Spy + ] + [ + a eg:Ninja + ] + ) . diff --git a/test/pretty/anonymous-object.ttl b/test/pretty/anonymous-object.ttl new file mode 100644 index 00000000..f592fed1 --- /dev/null +++ b/test/pretty/anonymous-object.ttl @@ -0,0 +1,10 @@ +@prefix eg: <http://example.org/> . + +eg:s + eg:p1 [ + eg:p2 eg:o2 ; + eg:p3 eg:o3 + ] , [ + eg:p4 eg:o4 ; + eg:p5 eg:o5 + ] . diff --git a/test/pretty/anonymous-subject-and-object.ttl b/test/pretty/anonymous-subject-and-object.ttl new file mode 100644 index 00000000..8904cca6 --- /dev/null +++ b/test/pretty/anonymous-subject-and-object.ttl @@ -0,0 +1,4 @@ +@prefix eg: <http://example.org/> . + +[] + eg:p [] . diff --git a/test/pretty/anonymous-subject.ttl b/test/pretty/anonymous-subject.ttl new file mode 100644 index 00000000..e0e467e2 --- /dev/null +++ b/test/pretty/anonymous-subject.ttl @@ -0,0 +1,4 @@ +@prefix eg: <http://example.org/> . + +[] + eg:p eg:o . diff --git a/test/pretty/empty-anonymous-object.ttl b/test/pretty/empty-anonymous-object.ttl new file mode 100644 index 00000000..f3b8d7f7 --- /dev/null +++ b/test/pretty/empty-anonymous-object.ttl @@ -0,0 +1,4 @@ +@prefix eg: <http://example.org/> . + +eg:s + eg:p [] . diff --git a/test/pretty/empty-list-object.ttl b/test/pretty/empty-list-object.ttl new file mode 100644 index 00000000..b4045ec0 --- /dev/null +++ b/test/pretty/empty-list-object.ttl @@ -0,0 +1,4 @@ +@prefix eg: <http://example.org/> . + +eg:s + eg:list () . diff --git a/test/pretty/empty-list-subject-and-object.ttl b/test/pretty/empty-list-subject-and-object.ttl new file mode 100644 index 00000000..3b84980e --- /dev/null +++ b/test/pretty/empty-list-subject-and-object.ttl @@ -0,0 +1,4 @@ +@prefix eg: <http://example.org/> . + +() + eg:list () . diff --git a/test/pretty/empty-list-subject.ttl b/test/pretty/empty-list-subject.ttl new file mode 100644 index 00000000..0610eb07 --- /dev/null +++ b/test/pretty/empty-list-subject.ttl @@ -0,0 +1,4 @@ +@prefix eg: <http://example.org/> . + +() + a eg:ExampleList . diff --git a/test/pretty/list-in-object.ttl b/test/pretty/list-in-object.ttl new file mode 100644 index 00000000..ce887157 --- /dev/null +++ b/test/pretty/list-in-object.ttl @@ -0,0 +1,10 @@ +@prefix eg: <http://example.org/> . + +eg:s + eg:p [ + eg:list ( + "apple" + "banana" + "cherry" + ) + ] . diff --git a/test/pretty/list-object.ttl b/test/pretty/list-object.ttl new file mode 100644 index 00000000..735d9df6 --- /dev/null +++ b/test/pretty/list-object.ttl @@ -0,0 +1,8 @@ +@prefix eg: <http://example.org/> . + +eg:s + eg:list ( + "apple" + "banana" + "cherry" + ) . diff --git a/test/pretty/list-subject-with-extras.ttl b/test/pretty/list-subject-with-extras.ttl new file mode 100644 index 00000000..dcfb8753 --- /dev/null +++ b/test/pretty/list-subject-with-extras.ttl @@ -0,0 +1,9 @@ +@prefix eg: <http://example.org/> . + +( + "apple" + "banana" + "cherry" +) + eg:with eg:someProperties ; + a eg:ExampleList . diff --git a/test/pretty/list-subject-with-list-extras.ttl b/test/pretty/list-subject-with-list-extras.ttl new file mode 100644 index 00000000..0a0cd0e0 --- /dev/null +++ b/test/pretty/list-subject-with-list-extras.ttl @@ -0,0 +1,12 @@ +@prefix eg: <http://example.org/> . + +( + "apple" + "banana" + "cherry" +) + eg:list ( + "asparagus" + "beet" + "carrot" + ) . diff --git a/test/pretty/list-subject.ttl b/test/pretty/list-subject.ttl new file mode 100644 index 00000000..eb1c7a2e --- /dev/null +++ b/test/pretty/list-subject.ttl @@ -0,0 +1,8 @@ +@prefix eg: <http://example.org/> . + +( + "apple" + "banana" + "cherry" +) + a eg:ExampleList . diff --git a/test/pretty/manifest.ttl b/test/pretty/manifest.ttl new file mode 100644 index 00000000..faae5857 --- /dev/null +++ b/test/pretty/manifest.ttl @@ -0,0 +1,121 @@ +@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#> . +@prefix serd: <http://drobilla.net/ns/serd#> . + +<> + a mf:Manifest ; + rdfs:comment "Serd pretty-printing test cases" ; + mf:entries ( + <#anonymous-in-list-object> + <#anonymous-object> + <#anonymous-subject-and-object> + <#anonymous-subject> + <#empty-anonymous-object> + <#empty-list-object> + <#empty-list-subject-and-object> + <#empty-list-subject> + <#list-in-object> + <#list-object> + <#list-subject-with-extras> + <#list-subject-with-list-extras> + <#list-subject> + <#many-objects> + <#nested-list-object-with-empty-lists> + <#nested-list-object> + <#nested-list-subject> + ) . + +<#anonymous-in-list-object> + a serd:TestTurtlePrint ; + mf:action <anonymous-in-list-object.ttl> ; + mf:name "anonymous-in-list-object" . + +<#anonymous-object> + a serd:TestTurtlePrint ; + mf:action <anonymous-object.ttl> ; + mf:name "anonymous-object" . + +<#anonymous-subject> + a serd:TestTurtlePrint ; + mf:action <anonymous-subject.ttl> ; + mf:name "anonymous-subject" . + +<#anonymous-subject-and-object> + a serd:TestTurtlePrint ; + mf:action <anonymous-subject-and-object.ttl> ; + mf:name "anonymous-subject-and-object" . + +<#empty-anonymous-object> + a serd:TestTurtlePrint ; + mf:action <empty-anonymous-object.ttl> ; + mf:name "empty-anonymous-object" . + +<#empty-list-object> + a serd:TestTurtlePrint ; + mf:action <empty-list-object.ttl> ; + mf:name "empty-list-object" . + +<#empty-list-subject> + a serd:TestTurtlePrint ; + mf:action <empty-list-subject.ttl> ; + mf:name "empty-list-subject" . + +<#empty-list-subject-and-object> + a serd:TestTurtlePrint ; + mf:action <empty-list-subject-and-object.ttl> ; + mf:name "empty-list-subject-and-object" . + +<#list-in-object> + a serd:TestTurtlePrint ; + mf:action <list-in-object.ttl> ; + mf:name "list-in-object" . + +<#list-object> + a serd:TestTurtlePrint ; + mf:action <list-object.ttl> ; + mf:name "list-object" . + +<#list-subject> + a serd:TestTurtlePrint ; + mf:action <list-subject.ttl> ; + mf:name "list-subject" . + +<#list-subject-with-extras> + a serd:TestTurtlePrint ; + mf:action <list-subject-with-extras.ttl> ; + mf:name "list-subject-with-extras" . + +<#list-subject-with-list-extras> + a serd:TestTurtlePrint ; + mf:action <list-subject-with-list-extras.ttl> ; + mf:name "list-subject-with-list-extras" . + +<#many-objects> + a serd:TestTurtlePrint ; + mf:action <many-objects.ttl> ; + mf:name "many-objects" . + +<#nested-list-object> + a serd:TestTurtlePrint ; + mf:action <nested-list-object.ttl> ; + mf:name "nested-list-object" . + +<#nested-list-object-with-empty-lists> + a serd:TestTurtlePrint ; + mf:action <nested-list-object-with-empty-lists.ttl> ; + mf:name "nested-list-object-with-empty-lists" . + +<#nested-list-subject> + a serd:TestTurtlePrint ; + mf:action <nested-list-subject.ttl> ; + mf:name "nested-list-subject" . + +serd:TestTurtlePrint + a rdfs:Class ; + rdfs:comment "Tests that a Turtle document pretty-prints exactly as written." ; + rdfs:label "Turtle Pretty-Printing" ; + rdfs:subClassOf rdft:Test . + +rdft:Test + rdfs:subClassOf mf:ManifestEntry . diff --git a/test/pretty/many-objects.ttl b/test/pretty/many-objects.ttl new file mode 100644 index 00000000..534741dd --- /dev/null +++ b/test/pretty/many-objects.ttl @@ -0,0 +1,9 @@ +@prefix eg: <http://example.org/> . + +eg:s + eg:p1 "apple" , + "banana" , + "cherry" ; + eg:p2 "asparagus" , + "beet" , + "carrot" . diff --git a/test/pretty/meson.build b/test/pretty/meson.build new file mode 100644 index 00000000..634f1e0e --- /dev/null +++ b/test/pretty/meson.build @@ -0,0 +1,17 @@ +base_uri = 'http://drobilla.net/sw/serd/test/good/' + +args = [files('manifest.ttl')] + +test('pretty', + run_pretty_suite, + args: pipe_test_script_args + ['-o', meson.current_build_dir() / 'pipe'] + args, + env: test_env, + suite: ['suite', 'extra', 'pipe'], + timeout: 240) + +test('pretty', + run_pretty_suite, + args: sort_test_script_args + ['-o', meson.current_build_dir() / 'sort'] + args, + env: test_env, + suite: ['suite', 'extra', 'sort'], + timeout: 240) diff --git a/test/pretty/nested-list-object-with-empty-lists.ttl b/test/pretty/nested-list-object-with-empty-lists.ttl new file mode 100644 index 00000000..4760fd2b --- /dev/null +++ b/test/pretty/nested-list-object-with-empty-lists.ttl @@ -0,0 +1,11 @@ +@prefix eg: <http://example.org/> . + +eg:s + eg:list ( + ( + () + ) + ( + () + ) + ) . diff --git a/test/pretty/nested-list-object.ttl b/test/pretty/nested-list-object.ttl new file mode 100644 index 00000000..c4b1898f --- /dev/null +++ b/test/pretty/nested-list-object.ttl @@ -0,0 +1,13 @@ +@prefix eg: <http://example.org/> . + +eg:s + eg:list ( + ( + eg:l1e1 + eg:l1e2 + ) + ( + eg:l2e1 + eg:l2e2 + ) + ) . diff --git a/test/pretty/nested-list-subject.ttl b/test/pretty/nested-list-subject.ttl new file mode 100644 index 00000000..b32aa133 --- /dev/null +++ b/test/pretty/nested-list-subject.ttl @@ -0,0 +1,13 @@ +@prefix eg: <http://example.org/> . + +( + ( + eg:l1e1 + eg:l1e2 + ) + ( + eg:l2e1 + eg:l2e2 + ) +) + a eg:ExampleList . diff --git a/test/run_pretty_suite.py b/test/run_pretty_suite.py new file mode 100755 index 00000000..a17dd0f8 --- /dev/null +++ b/test/run_pretty_suite.py @@ -0,0 +1,153 @@ +#!/usr/bin/env python3 + +"""Run the RDF-based test suite for serd-filter.""" + +import serd_test_util + +import argparse +import datetime +import difflib +import itertools +import os +import re +import shlex +import subprocess +import sys +import tempfile +import urllib.parse + + +def log_error(message): + """Log an error message to stderr""" + + sys.stderr.write("error: ") + sys.stderr.write(message) + + +def _uri_path(test_dir, uri): + path = urllib.parse.urlparse(uri).path + drive = os.path.splitdrive(path[1:])[0] + path = path if not drive else path[1:] + return os.path.join(test_dir, os.path.basename(path)) + + +def test_suite( + manifest_path, + base_uri, + command_prefix, + out_dir, +): + """Run all tests in the manifest.""" + + mf = "http://www.w3.org/2001/sw/DataAccess/tests/test-manifest#" + suite_dir = os.path.dirname(manifest_path) + + model, instances = serd_test_util.load_rdf( + command_prefix + ["-B", base_uri], manifest_path + ) + + os.makedirs(out_dir, exist_ok=True) + + class Results: + def __init__(self): + self.n_tests = 0 + self.n_failures = 0 + + def run_test(entry, results): + """Run a single test entry from the manifest.""" + + input_uri = model[entry][mf + "action"][0] + input_path = _uri_path(suite_dir, input_uri) + + output_path = os.path.join(out_dir, os.path.basename(input_path)) + + command = command_prefix + [ + "-B", + base_uri, + "-O", + "turtle", + "-o", + output_path, + input_path, + ] + + # Read the flat input and pretty-print output + results.n_tests += 1 + try: + subprocess.run(command, check=True) + + # Check that the output is exactly the same as the expected result + if not serd_test_util.file_equals(input_path, output_path): + results.n_failures += 1 + log_error( + "Output {} differs from {}\n".format( + output_path, input_path + ) + ) + + except Exception as e: + log_error(str(e)) + results.n_failures += 1 + + # Run all test types in the test suite + results = Results() + for klass, instances in instances.items(): + if klass == "http://drobilla.net/ns/serd#TestTurtlePrint": + for entry in instances: + run_test(entry, results) + + # Print result summary + if results.n_failures > 0: + log_error( + "{}/{} tests failed\n".format(results.n_failures, results.n_tests) + ) + else: + sys.stdout.write("All {} tests passed\n".format(results.n_tests)) + + return results.n_failures + + +def main(): + """Run the command line tool.""" + + parser = argparse.ArgumentParser( + usage="%(prog)s [OPTION]... MANIFEST -- [TOOL_OPTION]...", + description=__doc__, + formatter_class=argparse.RawDescriptionHelpFormatter, + ) + + parser.add_argument("--tool", default="tools/serd-sort", help="executable") + parser.add_argument("--wrapper", default="", help="executable wrapper") + + parser.add_argument( + "-o", "--out-dir", default="test/pretty", help="output directory" + ) + + parser.add_argument( + "--base-uri", + default="http://drobilla.net/sw/serd/test/", + help="base URI", + ) + parser.add_argument("manifest", help="test suite manifest.ttl file") + + args = parser.parse_args(sys.argv[1:]) + wrapper_prefix = shlex.split(args.wrapper) + command_prefix = wrapper_prefix + [args.tool] + + return test_suite( + args.manifest, + args.base_uri, + command_prefix, + args.out_dir, + ) + + +if __name__ == "__main__": + try: + sys.exit(main()) + except subprocess.CalledProcessError as e: + if e.stderr is not None: + sys.stderr.write(e.stderr.decode("utf-8")) + + sys.stderr.write("error: %s\n" % e) + sys.exit(e.returncode) |