From a7149be8c026ae5664ca467e4ad441a3eb9b2313 Mon Sep 17 00:00:00 2001 From: Guus der Kinderen Date: Sat, 5 Nov 2022 16:53:26 +0100 Subject: [PATCH 01/11] fixes #1235: Script that validates XEP-0001 conformance This adds a simple bash script that checks if a provided file (filename to be provided as first argument) conforms to XEP-0001. Expected to be executed from the directory that holds all xep XML files. Requires one argument: the file name of the xep to be validated, eg: $ tools/validate-xep0001-conformance.sh xep-0010.xml exit status will be non-zero upon validation failure. requires: bash, xmllint --- tools/validate-xep0001-conformance.sh | 132 ++++++++++++++++++++++++++ 1 file changed, 132 insertions(+) create mode 100755 tools/validate-xep0001-conformance.sh diff --git a/tools/validate-xep0001-conformance.sh b/tools/validate-xep0001-conformance.sh new file mode 100755 index 00000000..e5194141 --- /dev/null +++ b/tools/validate-xep0001-conformance.sh @@ -0,0 +1,132 @@ +#!/bin/bash + +# Checks if provided file (filename to be provided as first argument) conforms to XEP-0001. +# See https://github.com/xsf/xeps/issues/1235 +# +# Expected to be executed from the directory that holds all xep XML files. +# Requires one argument: the file name of the xep to be validated, eg: +# +# $ tools/validate-xep0001-conformance.sh xep-0010.xml +# +# exit status will be non-zero upon validation failure. +# +# requires: bash, xmllint + +set -e + +VALIDATION_RESULT=0 + +# 1. Check DTD conformance against xep.dtd +XEP_DTD="xep.dtd" +if (xmllint --noout --dtdvalid "$XEP_DTD" "$1") +then + echo "[PASS] DTD conformance against xep.dtd" +else + echo "[FAIL] DTD conformance against xep.dtd" + VALIDATION_RESULT=1; +fi + +FILE_NAME="$(basename -- $1)" +HEADER_NUMBER=$(xmllint --xpath '/xep/header/number/text()' --nowarning --dtdvalid "$XEP_DTD" $1) +HEADER_STATUS=$(xmllint --xpath '/xep/header/status/text()' --nowarning --dtdvalid "$XEP_DTD" $1) +HEADER_TYPE=$(xmllint --xpath '/xep/header/type/text()' --nowarning --dtdvalid "$XEP_DTD" $1) +HEADER_APPROVER=$(xmllint --xpath '/xep/header/approver/text()' --nowarning --dtdvalid "$XEP_DTD" $1) + +if (echo "$FILE_NAME" | grep -Eq "^xep-[0-9]{4}.xml$") +then + echo "[INFO] The filename ('$FILE_NAME') matches 'xep-[0-9]{4}.xml'." + # 2. If the filename matches xep-[0-9]{4}.xml, check: + # 2.1 that the number in the filename equals /xep/header/number (XPath) + if [ "$FILE_NAME" = "xep-$HEADER_NUMBER.xml" ] + then + echo "[PASS] The number in the filename ('$FILE_NAME') equals XPATH value /xep/header/number/text() ('$HEADER_NUMBER')." + else + echo "[FAIL] The number in the filename ('$FILE_NAME') does not equals XPATH value /xep/header/number/text() ('$HEADER_NUMBER') (but should)." + VALIDATION_RESULT=1; + fi +else + echo "[INFO] The filename ('$FILE_NAME') does not match 'xep-[0-9]{4}.xml'." + # 3. If the filename does not match xep-[0-9]{4}.xml, check: + # 3.1 That the /xep/header/status/text() (XPath) is ProtoXEP + if [ "$HEADER_STATUS" = "ProtoXEP" ] + then + echo "[PASS] XPATH value /xep/header/status/text() ('$HEADER_STATUS') equals 'ProtoXEP'." + else + echo "[FAIL] XPATH value /xep/header/status/text() ('$HEADER_STATUS') does not equal 'ProtoXEP' (but should)." + VALIDATION_RESULT=1; + fi + + # 3.2 That the /xep/header/number/text() (XPath) is literally XXXX + if [ "$HEADER_NUMBER" = "XXXX" ] + then + echo "[PASS] XPATH value /xep/header/number/text() ('$HEADER_STATUS') equals 'XXXX'." + else + echo "[FAIL] XPATH value /xep/header/nimber/text() ('$HEADER_STATUS') does not equal 'XXXX' (but should)." + VALIDATION_RESULT=1; + fi + + # 3.3 That the name does not start with xep-[0-9] + if (echo "$FILE_NAME" | grep -Eq "^xep-[0-9].*$") + then + echo "[FAIL] The filename ('$FILE_NAME') starts with 'xep-[0-9]' (but should not)." + VALIDATION_RESULT=1; + else + echo "[PASS] The filename ('$FILE_NAME') does not start with 'xep-[0-9]'." + fi +fi + +# 4. Check that /xep/header/status/text() (XPath) is a defined status (see tools/xeplib.py for an enum) +case $HEADER_STATUS in + ProtoXEP | Experimental | Proposed | Draft | Active | Final | Retracted | Obsolete | Deferred | Rejected | Deprecated ) + echo "[PASS] XPATH value /xep/header/status/text() ('$HEADER_STATUS') equals a defined status." + ;; + *) + echo "[FAIL] XPATH value /xep/header/status/text() ('$HEADER_STATUS') does not equals a defined status (but should)." + VALIDATION_RESULT=1; + ;; +esac + +# 5. Check that /xep/header/type/text() (XPath) is defined in XEP-0001 +# If the XEP number is less than 400, also accept some legacy values. To find which, see which you encounter in the XEP numbers below 400 :-). +echo "[INFO] implementation of validation of XPATH value /xep/header/type/text() ('$HEADER_TYPE') is pending!" + +# 6. Check that /xep/header/approver/text() (XPath) is either Board or Council +case $HEADER_APPROVER in + Board | Council ) + echo "[PASS] XPATH value /xep/header/approver/text() ('$HEADER_APPROVER') equals either 'Board' or 'Council'." + ;; + *) + echo "[FAIL] XPATH value /xep/header/approver/text() ('$HEADER_APPROVER') does not equals 'Board' or 'Council' (but should)." + VALIDATION_RESULT=1; + ;; +esac + +# 7. Check that the version numbers in the revision blocks are descending (from top to bottom in the document) +echo "[INFO] implementation of validation version numbers in the revision blocks is pending!" + +# 8. If the approver (see above) is Board, enforce that /xep/header/type is not Standards Track. +if [ "$HEADER_APPROVER" = "Board" ] +then + if [ "$HEADER_TYPE" = "Standards Track" ] + then + echo "[FAIL] XPATH value /xep/header/approver/text() ('$HEADER_APPROVER') is 'Board' but XPATH value /xep/header/type/text() is 'Standards Track' (it should not be)." + VALIDATION_RESULT=1; + else + echo "[PASS] XPATH value /xep/header/approver/text() ('$HEADER_APPROVER') is 'Board' and XPATH value /xep/header/type/text() is not 'Standards Track'." + fi +fi + +# 9. Check that it uses the xep.xsl XML stylesheet. +echo "[INFO] implementation of xep.xsl XML stylesheet usage is pending!" + +# 10. Check that it includes the correct legal notice (either by checking for the entity reference, or by checking the content) +echo "[INFO] implementation of inclusion of correct legal notice is pending!" + +echo "" +if [ $VALIDATION_RESULT = 0 ] +then + echo "No issues found (but not all checks are implemented)."; +else + echo "Issues found!" +fi +exit $VALIDATION_RESULT From d65a5b4c2fa718a4c256d45173f14f90bb04090a Mon Sep 17 00:00:00 2001 From: Guus der Kinderen Date: Sun, 6 Nov 2022 09:29:18 +0100 Subject: [PATCH 02/11] for #1235: Use `set -euo pipefail` instead of `set -e` As per @horazont's feedback: `-u` shouts at you if you use an undefined variable (very useful to catch typos) and `-o pipefail` improves error handling by also failing if any of the commands in a pipe fail. --- tools/validate-xep0001-conformance.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/validate-xep0001-conformance.sh b/tools/validate-xep0001-conformance.sh index e5194141..cf073165 100755 --- a/tools/validate-xep0001-conformance.sh +++ b/tools/validate-xep0001-conformance.sh @@ -12,7 +12,7 @@ # # requires: bash, xmllint -set -e +set -euo pipefail VALIDATION_RESULT=0 From 7389c8a3e9d92a11d6d90d70240e45395c62fbd0 Mon Sep 17 00:00:00 2001 From: Guus der Kinderen Date: Sun, 6 Nov 2022 09:33:59 +0100 Subject: [PATCH 03/11] for #1235: Remove redundant braces in if-expression As per @horazont's feedback: > You do not need () around the command in an if. I think that causes a subshell to spawn, the effects of which I'm not certain about. Further Googling suggests that the exit status of a pipeline is that of the most recently executed foreground pipeline, meaning that the exit code can be used directly in conditional statements. --- tools/validate-xep0001-conformance.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tools/validate-xep0001-conformance.sh b/tools/validate-xep0001-conformance.sh index cf073165..72b71314 100755 --- a/tools/validate-xep0001-conformance.sh +++ b/tools/validate-xep0001-conformance.sh @@ -18,7 +18,7 @@ VALIDATION_RESULT=0 # 1. Check DTD conformance against xep.dtd XEP_DTD="xep.dtd" -if (xmllint --noout --dtdvalid "$XEP_DTD" "$1") +if xmllint --noout --dtdvalid "$XEP_DTD" "$1" then echo "[PASS] DTD conformance against xep.dtd" else @@ -32,7 +32,7 @@ HEADER_STATUS=$(xmllint --xpath '/xep/header/status/text()' --nowarning --dtdval HEADER_TYPE=$(xmllint --xpath '/xep/header/type/text()' --nowarning --dtdvalid "$XEP_DTD" $1) HEADER_APPROVER=$(xmllint --xpath '/xep/header/approver/text()' --nowarning --dtdvalid "$XEP_DTD" $1) -if (echo "$FILE_NAME" | grep -Eq "^xep-[0-9]{4}.xml$") +if echo "$FILE_NAME" | grep -Eq "^xep-[0-9]{4}.xml$" then echo "[INFO] The filename ('$FILE_NAME') matches 'xep-[0-9]{4}.xml'." # 2. If the filename matches xep-[0-9]{4}.xml, check: @@ -66,7 +66,7 @@ else fi # 3.3 That the name does not start with xep-[0-9] - if (echo "$FILE_NAME" | grep -Eq "^xep-[0-9].*$") + if echo "$FILE_NAME" | grep -Eq "^xep-[0-9].*$" then echo "[FAIL] The filename ('$FILE_NAME') starts with 'xep-[0-9]' (but should not)." VALIDATION_RESULT=1; From f1197f143a3124430e4d2ddae1fbde4ca0982c69 Mon Sep 17 00:00:00 2001 From: Guus der Kinderen Date: Sun, 6 Nov 2022 09:40:32 +0100 Subject: [PATCH 04/11] for #1235: Double quote to prevent globbing and word splitting. As per @horazont's feedback: > Whenever you reference a variable ($foobar) and unless you know what you're doing, put it in double quotes. --- tools/validate-xep0001-conformance.sh | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tools/validate-xep0001-conformance.sh b/tools/validate-xep0001-conformance.sh index 72b71314..d938a501 100755 --- a/tools/validate-xep0001-conformance.sh +++ b/tools/validate-xep0001-conformance.sh @@ -26,11 +26,11 @@ else VALIDATION_RESULT=1; fi -FILE_NAME="$(basename -- $1)" -HEADER_NUMBER=$(xmllint --xpath '/xep/header/number/text()' --nowarning --dtdvalid "$XEP_DTD" $1) -HEADER_STATUS=$(xmllint --xpath '/xep/header/status/text()' --nowarning --dtdvalid "$XEP_DTD" $1) -HEADER_TYPE=$(xmllint --xpath '/xep/header/type/text()' --nowarning --dtdvalid "$XEP_DTD" $1) -HEADER_APPROVER=$(xmllint --xpath '/xep/header/approver/text()' --nowarning --dtdvalid "$XEP_DTD" $1) +FILE_NAME=$(basename -- "$1") +HEADER_NUMBER=$(xmllint --xpath '/xep/header/number/text()' --nowarning --dtdvalid "$XEP_DTD" "$1") +HEADER_STATUS=$(xmllint --xpath '/xep/header/status/text()' --nowarning --dtdvalid "$XEP_DTD" "$1") +HEADER_TYPE=$(xmllint --xpath '/xep/header/type/text()' --nowarning --dtdvalid "$XEP_DTD" "$1") +HEADER_APPROVER=$(xmllint --xpath '/xep/header/approver/text()' --nowarning --dtdvalid "$XEP_DTD" "$1") if echo "$FILE_NAME" | grep -Eq "^xep-[0-9]{4}.xml$" then From 3f6f199159002f8466114b2471d65a985a4d0668 Mon Sep 17 00:00:00 2001 From: Guus der Kinderen Date: Sun, 6 Nov 2022 09:45:33 +0100 Subject: [PATCH 05/11] for #1235: variable casing to conform to convention --- tools/validate-xep0001-conformance.sh | 88 +++++++++++++-------------- 1 file changed, 44 insertions(+), 44 deletions(-) diff --git a/tools/validate-xep0001-conformance.sh b/tools/validate-xep0001-conformance.sh index d938a501..9f68f4f8 100755 --- a/tools/validate-xep0001-conformance.sh +++ b/tools/validate-xep0001-conformance.sh @@ -14,90 +14,90 @@ set -euo pipefail -VALIDATION_RESULT=0 +validation_result=0 # 1. Check DTD conformance against xep.dtd -XEP_DTD="xep.dtd" -if xmllint --noout --dtdvalid "$XEP_DTD" "$1" +xep_dtd="xep.dtd" +if xmllint --noout --dtdvalid "$xep_dtd" "$1" then echo "[PASS] DTD conformance against xep.dtd" else echo "[FAIL] DTD conformance against xep.dtd" - VALIDATION_RESULT=1; + validation_result=1; fi -FILE_NAME=$(basename -- "$1") -HEADER_NUMBER=$(xmllint --xpath '/xep/header/number/text()' --nowarning --dtdvalid "$XEP_DTD" "$1") -HEADER_STATUS=$(xmllint --xpath '/xep/header/status/text()' --nowarning --dtdvalid "$XEP_DTD" "$1") -HEADER_TYPE=$(xmllint --xpath '/xep/header/type/text()' --nowarning --dtdvalid "$XEP_DTD" "$1") -HEADER_APPROVER=$(xmllint --xpath '/xep/header/approver/text()' --nowarning --dtdvalid "$XEP_DTD" "$1") +file_name=$(basename -- "$1") +header_number=$(xmllint --xpath '/xep/header/number/text()' --nowarning --dtdvalid "$xep_dtd" "$1") +header_status=$(xmllint --xpath '/xep/header/status/text()' --nowarning --dtdvalid "$xep_dtd" "$1") +header_type=$(xmllint --xpath '/xep/header/type/text()' --nowarning --dtdvalid "$xep_dtd" "$1") +header_approver=$(xmllint --xpath '/xep/header/approver/text()' --nowarning --dtdvalid "$xep_dtd" "$1") -if echo "$FILE_NAME" | grep -Eq "^xep-[0-9]{4}.xml$" +if echo "$file_name" | grep -Eq "^xep-[0-9]{4}.xml$" then - echo "[INFO] The filename ('$FILE_NAME') matches 'xep-[0-9]{4}.xml'." + echo "[INFO] The filename ('$file_name') matches 'xep-[0-9]{4}.xml'." # 2. If the filename matches xep-[0-9]{4}.xml, check: # 2.1 that the number in the filename equals /xep/header/number (XPath) - if [ "$FILE_NAME" = "xep-$HEADER_NUMBER.xml" ] + if [ "$file_name" = "xep-$header_number.xml" ] then - echo "[PASS] The number in the filename ('$FILE_NAME') equals XPATH value /xep/header/number/text() ('$HEADER_NUMBER')." + echo "[PASS] The number in the filename ('$file_name') equals XPATH value /xep/header/number/text() ('$header_number')." else - echo "[FAIL] The number in the filename ('$FILE_NAME') does not equals XPATH value /xep/header/number/text() ('$HEADER_NUMBER') (but should)." - VALIDATION_RESULT=1; + echo "[FAIL] The number in the filename ('$file_name') does not equals XPATH value /xep/header/number/text() ('$header_number') (but should)." + validation_result=1; fi else - echo "[INFO] The filename ('$FILE_NAME') does not match 'xep-[0-9]{4}.xml'." + echo "[INFO] The filename ('$file_name') does not match 'xep-[0-9]{4}.xml'." # 3. If the filename does not match xep-[0-9]{4}.xml, check: # 3.1 That the /xep/header/status/text() (XPath) is ProtoXEP - if [ "$HEADER_STATUS" = "ProtoXEP" ] + if [ "$header_status" = "ProtoXEP" ] then - echo "[PASS] XPATH value /xep/header/status/text() ('$HEADER_STATUS') equals 'ProtoXEP'." + echo "[PASS] XPATH value /xep/header/status/text() ('$header_status') equals 'ProtoXEP'." else - echo "[FAIL] XPATH value /xep/header/status/text() ('$HEADER_STATUS') does not equal 'ProtoXEP' (but should)." - VALIDATION_RESULT=1; + echo "[FAIL] XPATH value /xep/header/status/text() ('$header_status') does not equal 'ProtoXEP' (but should)." + validation_result=1; fi # 3.2 That the /xep/header/number/text() (XPath) is literally XXXX - if [ "$HEADER_NUMBER" = "XXXX" ] + if [ "$header_number" = "XXXX" ] then - echo "[PASS] XPATH value /xep/header/number/text() ('$HEADER_STATUS') equals 'XXXX'." + echo "[PASS] XPATH value /xep/header/number/text() ('$header_status') equals 'XXXX'." else - echo "[FAIL] XPATH value /xep/header/nimber/text() ('$HEADER_STATUS') does not equal 'XXXX' (but should)." - VALIDATION_RESULT=1; + echo "[FAIL] XPATH value /xep/header/nimber/text() ('$header_status') does not equal 'XXXX' (but should)." + validation_result=1; fi # 3.3 That the name does not start with xep-[0-9] - if echo "$FILE_NAME" | grep -Eq "^xep-[0-9].*$" + if echo "$file_name" | grep -Eq "^xep-[0-9].*$" then - echo "[FAIL] The filename ('$FILE_NAME') starts with 'xep-[0-9]' (but should not)." - VALIDATION_RESULT=1; + echo "[FAIL] The filename ('$file_name') starts with 'xep-[0-9]' (but should not)." + validation_result=1; else - echo "[PASS] The filename ('$FILE_NAME') does not start with 'xep-[0-9]'." + echo "[PASS] The filename ('$file_name') does not start with 'xep-[0-9]'." fi fi # 4. Check that /xep/header/status/text() (XPath) is a defined status (see tools/xeplib.py for an enum) -case $HEADER_STATUS in +case $header_status in ProtoXEP | Experimental | Proposed | Draft | Active | Final | Retracted | Obsolete | Deferred | Rejected | Deprecated ) - echo "[PASS] XPATH value /xep/header/status/text() ('$HEADER_STATUS') equals a defined status." + echo "[PASS] XPATH value /xep/header/status/text() ('$header_status') equals a defined status." ;; *) - echo "[FAIL] XPATH value /xep/header/status/text() ('$HEADER_STATUS') does not equals a defined status (but should)." - VALIDATION_RESULT=1; + echo "[FAIL] XPATH value /xep/header/status/text() ('$header_status') does not equals a defined status (but should)." + validation_result=1; ;; esac # 5. Check that /xep/header/type/text() (XPath) is defined in XEP-0001 # If the XEP number is less than 400, also accept some legacy values. To find which, see which you encounter in the XEP numbers below 400 :-). -echo "[INFO] implementation of validation of XPATH value /xep/header/type/text() ('$HEADER_TYPE') is pending!" +echo "[INFO] implementation of validation of XPATH value /xep/header/type/text() ('$header_type') is pending!" # 6. Check that /xep/header/approver/text() (XPath) is either Board or Council -case $HEADER_APPROVER in +case $header_approver in Board | Council ) - echo "[PASS] XPATH value /xep/header/approver/text() ('$HEADER_APPROVER') equals either 'Board' or 'Council'." + echo "[PASS] XPATH value /xep/header/approver/text() ('$header_approver') equals either 'Board' or 'Council'." ;; *) - echo "[FAIL] XPATH value /xep/header/approver/text() ('$HEADER_APPROVER') does not equals 'Board' or 'Council' (but should)." - VALIDATION_RESULT=1; + echo "[FAIL] XPATH value /xep/header/approver/text() ('$header_approver') does not equals 'Board' or 'Council' (but should)." + validation_result=1; ;; esac @@ -105,14 +105,14 @@ esac echo "[INFO] implementation of validation version numbers in the revision blocks is pending!" # 8. If the approver (see above) is Board, enforce that /xep/header/type is not Standards Track. -if [ "$HEADER_APPROVER" = "Board" ] +if [ "$header_approver" = "Board" ] then - if [ "$HEADER_TYPE" = "Standards Track" ] + if [ "$header_type" = "Standards Track" ] then - echo "[FAIL] XPATH value /xep/header/approver/text() ('$HEADER_APPROVER') is 'Board' but XPATH value /xep/header/type/text() is 'Standards Track' (it should not be)." - VALIDATION_RESULT=1; + echo "[FAIL] XPATH value /xep/header/approver/text() ('$header_approver') is 'Board' but XPATH value /xep/header/type/text() is 'Standards Track' (it should not be)." + validation_result=1; else - echo "[PASS] XPATH value /xep/header/approver/text() ('$HEADER_APPROVER') is 'Board' and XPATH value /xep/header/type/text() is not 'Standards Track'." + echo "[PASS] XPATH value /xep/header/approver/text() ('$header_approver') is 'Board' and XPATH value /xep/header/type/text() is not 'Standards Track'." fi fi @@ -123,10 +123,10 @@ echo "[INFO] implementation of xep.xsl XML stylesheet usage is pending!" echo "[INFO] implementation of inclusion of correct legal notice is pending!" echo "" -if [ $VALIDATION_RESULT = 0 ] +if [ $validation_result = 0 ] then echo "No issues found (but not all checks are implemented)."; else echo "Issues found!" fi -exit $VALIDATION_RESULT +exit $validation_result From 269e4d620a65b3e5bcffcb1611f0fde9e3bf029e Mon Sep 17 00:00:00 2001 From: Guus der Kinderen Date: Sun, 6 Nov 2022 10:14:54 +0100 Subject: [PATCH 06/11] for #1235: Add xep.xsl XML stylesheet usage validation --- tools/validate-xep0001-conformance.sh | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/tools/validate-xep0001-conformance.sh b/tools/validate-xep0001-conformance.sh index 9f68f4f8..4fed854d 100755 --- a/tools/validate-xep0001-conformance.sh +++ b/tools/validate-xep0001-conformance.sh @@ -31,6 +31,7 @@ header_number=$(xmllint --xpath '/xep/header/number/text()' --nowarning --dtdval header_status=$(xmllint --xpath '/xep/header/status/text()' --nowarning --dtdvalid "$xep_dtd" "$1") header_type=$(xmllint --xpath '/xep/header/type/text()' --nowarning --dtdvalid "$xep_dtd" "$1") header_approver=$(xmllint --xpath '/xep/header/approver/text()' --nowarning --dtdvalid "$xep_dtd" "$1") +processing_instructions=$(xmllint --xpath '/processing-instruction("xml-stylesheet")' --nowarning --dtdvalid "$xep_dtd" "$1") if echo "$file_name" | grep -Eq "^xep-[0-9]{4}.xml$" then @@ -42,7 +43,7 @@ then echo "[PASS] The number in the filename ('$file_name') equals XPATH value /xep/header/number/text() ('$header_number')." else echo "[FAIL] The number in the filename ('$file_name') does not equals XPATH value /xep/header/number/text() ('$header_number') (but should)." - validation_result=1; + validation_result=1 fi else echo "[INFO] The filename ('$file_name') does not match 'xep-[0-9]{4}.xml'." @@ -53,7 +54,7 @@ else echo "[PASS] XPATH value /xep/header/status/text() ('$header_status') equals 'ProtoXEP'." else echo "[FAIL] XPATH value /xep/header/status/text() ('$header_status') does not equal 'ProtoXEP' (but should)." - validation_result=1; + validation_result=1 fi # 3.2 That the /xep/header/number/text() (XPath) is literally XXXX @@ -62,14 +63,14 @@ else echo "[PASS] XPATH value /xep/header/number/text() ('$header_status') equals 'XXXX'." else echo "[FAIL] XPATH value /xep/header/nimber/text() ('$header_status') does not equal 'XXXX' (but should)." - validation_result=1; + validation_result=1 fi # 3.3 That the name does not start with xep-[0-9] if echo "$file_name" | grep -Eq "^xep-[0-9].*$" then echo "[FAIL] The filename ('$file_name') starts with 'xep-[0-9]' (but should not)." - validation_result=1; + validation_result=1 else echo "[PASS] The filename ('$file_name') does not start with 'xep-[0-9]'." fi @@ -82,7 +83,7 @@ case $header_status in ;; *) echo "[FAIL] XPATH value /xep/header/status/text() ('$header_status') does not equals a defined status (but should)." - validation_result=1; + validation_result=1 ;; esac @@ -97,7 +98,7 @@ case $header_approver in ;; *) echo "[FAIL] XPATH value /xep/header/approver/text() ('$header_approver') does not equals 'Board' or 'Council' (but should)." - validation_result=1; + validation_result=1 ;; esac @@ -110,14 +111,20 @@ then if [ "$header_type" = "Standards Track" ] then echo "[FAIL] XPATH value /xep/header/approver/text() ('$header_approver') is 'Board' but XPATH value /xep/header/type/text() is 'Standards Track' (it should not be)." - validation_result=1; + validation_result=1 else echo "[PASS] XPATH value /xep/header/approver/text() ('$header_approver') is 'Board' and XPATH value /xep/header/type/text() is not 'Standards Track'." fi fi # 9. Check that it uses the xep.xsl XML stylesheet. -echo "[INFO] implementation of xep.xsl XML stylesheet usage is pending!" +if echo "$processing_instructions" | grep -Eq "href=['\"]xep.xsl['\"]" +then + echo "[PASS] xep.xsl XML stylesheet is used." +else + echo "[FAIL] xep.xsl XML stylesheet is not used (but should be)." + validation_result=1 +fi # 10. Check that it includes the correct legal notice (either by checking for the entity reference, or by checking the content) echo "[INFO] implementation of inclusion of correct legal notice is pending!" @@ -125,7 +132,7 @@ echo "[INFO] implementation of inclusion of correct legal notice is pending!" echo "" if [ $validation_result = 0 ] then - echo "No issues found (but not all checks are implemented)."; + echo "No issues found (but not all checks are implemented)." else echo "Issues found!" fi From da76032e2471838b79dc9f85b4847f3c47aa8099 Mon Sep 17 00:00:00 2001 From: Guus der Kinderen Date: Sun, 6 Nov 2022 10:40:02 +0100 Subject: [PATCH 07/11] for #1235: Add revision block version validation. --- tools/validate-xep0001-conformance.sh | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/tools/validate-xep0001-conformance.sh b/tools/validate-xep0001-conformance.sh index 4fed854d..946b3d47 100755 --- a/tools/validate-xep0001-conformance.sh +++ b/tools/validate-xep0001-conformance.sh @@ -10,7 +10,7 @@ # # exit status will be non-zero upon validation failure. # -# requires: bash, xmllint +# requires: bash, xmllint, sort (supporting the '-V' argument) set -euo pipefail @@ -31,6 +31,7 @@ header_number=$(xmllint --xpath '/xep/header/number/text()' --nowarning --dtdval header_status=$(xmllint --xpath '/xep/header/status/text()' --nowarning --dtdvalid "$xep_dtd" "$1") header_type=$(xmllint --xpath '/xep/header/type/text()' --nowarning --dtdvalid "$xep_dtd" "$1") header_approver=$(xmllint --xpath '/xep/header/approver/text()' --nowarning --dtdvalid "$xep_dtd" "$1") +header_revisions=$(xmllint --xpath '/xep/header/revision/version/text()' --nowarning --dtdvalid "$xep_dtd" "$1") processing_instructions=$(xmllint --xpath '/processing-instruction("xml-stylesheet")' --nowarning --dtdvalid "$xep_dtd" "$1") if echo "$file_name" | grep -Eq "^xep-[0-9]{4}.xml$" @@ -103,7 +104,16 @@ case $header_approver in esac # 7. Check that the version numbers in the revision blocks are descending (from top to bottom in the document) -echo "[INFO] implementation of validation version numbers in the revision blocks is pending!" +expected_revision_order=$(echo "$header_revisions" | tr " " "\n" | sort -Vr) +if [ "$expected_revision_order" = "$header_revisions" ] +then + echo "[PASS] Version numbers in the revision blocks are descending." +else + echo "[FAIL] Version numbers in the revision blocks are not ordered (descending from top to bottom in the document) (but should be)." + echo " Order found : $(echo $header_revisions)" # funky $() nesting to remove newlines. + echo " Expected was: $(echo $expected_revision_order)" + validation_result=1 +fi # 8. If the approver (see above) is Board, enforce that /xep/header/type is not Standards Track. if [ "$header_approver" = "Board" ] From 56cef32c91ee00c82599a4f300ee2180613d7f36 Mon Sep 17 00:00:00 2001 From: Guus der Kinderen Date: Sun, 6 Nov 2022 11:11:13 +0100 Subject: [PATCH 08/11] for #1235: Add header type validation. --- tools/validate-xep0001-conformance.sh | 51 +++++++++++++++++++++++++-- 1 file changed, 49 insertions(+), 2 deletions(-) diff --git a/tools/validate-xep0001-conformance.sh b/tools/validate-xep0001-conformance.sh index 946b3d47..02a21054 100755 --- a/tools/validate-xep0001-conformance.sh +++ b/tools/validate-xep0001-conformance.sh @@ -63,7 +63,7 @@ else then echo "[PASS] XPATH value /xep/header/number/text() ('$header_status') equals 'XXXX'." else - echo "[FAIL] XPATH value /xep/header/nimber/text() ('$header_status') does not equal 'XXXX' (but should)." + echo "[FAIL] XPATH value /xep/header/number/text() ('$header_status') does not equal 'XXXX' (but should)." validation_result=1 fi @@ -90,7 +90,54 @@ esac # 5. Check that /xep/header/type/text() (XPath) is defined in XEP-0001 # If the XEP number is less than 400, also accept some legacy values. To find which, see which you encounter in the XEP numbers below 400 :-). -echo "[INFO] implementation of validation of XPATH value /xep/header/type/text() ('$header_type') is pending!" + +# FIXME: lots of duplications here. Find a better solution. +case $file_name in + 'xep-0001.xml' | 'xep-0002.xml' | 'xep-0019.xml' | 'xep-0053.xml' | 'xep-00143.xml' | 'xep-0182.xml' | 'xep-0345.xml' | 'xep-0381.xml' | 'xep-0429.xml' | 'xep-0458.xml' ) + case $header_type in + Historical | Humorous | Informational | Organizational | 'Standards Track' | 'Procedural' ) + echo "[PASS] XPATH value /xep/header/type/text() ('$header_type') equals a defined type." + ;; + *) + echo "[FAIL] XPATH value /xep/header/type/text() ('$header_type') does not equals a defined type (but should)." + validation_result=1 + ;; + esac + ;; + 'xep-0006.xml' | 'xep-0010.xml' | 'xep-0069.xml' | 'xep-0139.xml' ) + case $header_type in + Historical | Humorous | Informational | Organizational | 'Standards Track' | 'SIG Formation' ) + echo "[PASS] XPATH value /xep/header/type/text() ('$header_type') equals a defined type." + ;; + *) + echo "[FAIL] XPATH value /xep/header/type/text() ('$header_type') does not equals a defined type (but should)." + validation_result=1 + ;; + esac + ;; + 'xep-0007.xml' ) + case $header_type in + Historical | Humorous | Informational | Organizational | 'Standards Track' | 'SIG Proposal' ) + echo "[PASS] XPATH value /xep/header/type/text() ('$header_type') equals a defined type." + ;; + *) + echo "[FAIL] XPATH value /xep/header/type/text() ('$header_type') does not equals a defined type (but should)." + validation_result=1 + ;; + esac + ;; + * ) + case $header_type in + Historical | Humorous | Informational | Organizational | 'Standards Track' ) + echo "[PASS] XPATH value /xep/header/type/text() ('$header_type') equals a defined type." + ;; + *) + echo "[FAIL] XPATH value /xep/header/type/text() ('$header_type') does not equals a defined type (but should)." + validation_result=1 + ;; + esac + ;; +esac # 6. Check that /xep/header/approver/text() (XPath) is either Board or Council case $header_approver in From 028fd1a68502c0cc9db85d381882afb3978ac25e Mon Sep 17 00:00:00 2001 From: Guus der Kinderen Date: Sun, 6 Nov 2022 19:20:34 +0100 Subject: [PATCH 09/11] for #1235: Add legal notice validation This adds a check for the usage of the _entity reference_ that is the legal notice. --- tools/validate-xep0001-conformance.sh | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/tools/validate-xep0001-conformance.sh b/tools/validate-xep0001-conformance.sh index 02a21054..a5bdfccd 100755 --- a/tools/validate-xep0001-conformance.sh +++ b/tools/validate-xep0001-conformance.sh @@ -183,13 +183,19 @@ else validation_result=1 fi -# 10. Check that it includes the correct legal notice (either by checking for the entity reference, or by checking the content) -echo "[INFO] implementation of inclusion of correct legal notice is pending!" +# 10. Check that it includes the correct legal notice (by checking for the entity reference) +if grep -q "&LEGALNOTICE;" "$1" +then + echo "[PASS] entity reference for the legal notice has been detected." +else + echo "[FAIL] entity reference for the legal notice has not been detected (but it should have been)." + validation_result=1 +fi echo "" if [ $validation_result = 0 ] then - echo "No issues found (but not all checks are implemented)." + echo "No issues found." else echo "Issues found!" fi From bee4c93cd380b82cc3de6f65f884957b3bdc296e Mon Sep 17 00:00:00 2001 From: Guus der Kinderen Date: Sun, 6 Nov 2022 20:08:15 +0100 Subject: [PATCH 10/11] for #1235: Do not exit script when XPATH yields no result xmllint will return exit code 10 when an XPATH query finds no matches. With the changes in this commit, the script isn't stopped. Instead, it uses an empty value, which is likely to cause the validation checks (further down in the script) to fail. --- tools/validate-xep0001-conformance.sh | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/tools/validate-xep0001-conformance.sh b/tools/validate-xep0001-conformance.sh index a5bdfccd..f1abd268 100755 --- a/tools/validate-xep0001-conformance.sh +++ b/tools/validate-xep0001-conformance.sh @@ -27,12 +27,15 @@ else fi file_name=$(basename -- "$1") -header_number=$(xmllint --xpath '/xep/header/number/text()' --nowarning --dtdvalid "$xep_dtd" "$1") -header_status=$(xmllint --xpath '/xep/header/status/text()' --nowarning --dtdvalid "$xep_dtd" "$1") -header_type=$(xmllint --xpath '/xep/header/type/text()' --nowarning --dtdvalid "$xep_dtd" "$1") -header_approver=$(xmllint --xpath '/xep/header/approver/text()' --nowarning --dtdvalid "$xep_dtd" "$1") -header_revisions=$(xmllint --xpath '/xep/header/revision/version/text()' --nowarning --dtdvalid "$xep_dtd" "$1") -processing_instructions=$(xmllint --xpath '/processing-instruction("xml-stylesheet")' --nowarning --dtdvalid "$xep_dtd" "$1") + +# The test for exit code equalling 10 detects when the XPATH evaluation yields no results. In that case, the execution +# should not fail immediately, but use an empty value instead (which will likely cause a validation failure further down). +header_number=$(xmllint --xpath '/xep/header/number/text()' --nowarning --dtdvalid "$xep_dtd" "$1") || test $?=10 +header_status=$(xmllint --xpath '/xep/header/status/text()' --nowarning --dtdvalid "$xep_dtd" "$1") || test $?=10 +header_type=$(xmllint --xpath '/xep/header/type/text()' --nowarning --dtdvalid "$xep_dtd" "$1") || test $?=10 +header_approver=$(xmllint --xpath '/xep/header/approver/text()' --nowarning --dtdvalid "$xep_dtd" "$1") || test $?=10 +header_revisions=$(xmllint --xpath '/xep/header/revision/version/text()' --nowarning --dtdvalid "$xep_dtd" "$1") || test $?=10 +processing_instructions=$(xmllint --xpath '/processing-instruction("xml-stylesheet")' --nowarning --dtdvalid "$xep_dtd" "$1") || test $?=10 if echo "$file_name" | grep -Eq "^xep-[0-9]{4}.xml$" then From fbc0072c929b514681a94a8d5ab52ed495c53538 Mon Sep 17 00:00:00 2001 From: Guus der Kinderen Date: Sun, 6 Nov 2022 20:31:58 +0100 Subject: [PATCH 11/11] for #1235: fix incorrect exemption for XEP-0143 --- tools/validate-xep0001-conformance.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/validate-xep0001-conformance.sh b/tools/validate-xep0001-conformance.sh index f1abd268..79fcceb6 100755 --- a/tools/validate-xep0001-conformance.sh +++ b/tools/validate-xep0001-conformance.sh @@ -96,7 +96,7 @@ esac # FIXME: lots of duplications here. Find a better solution. case $file_name in - 'xep-0001.xml' | 'xep-0002.xml' | 'xep-0019.xml' | 'xep-0053.xml' | 'xep-00143.xml' | 'xep-0182.xml' | 'xep-0345.xml' | 'xep-0381.xml' | 'xep-0429.xml' | 'xep-0458.xml' ) + 'xep-0001.xml' | 'xep-0002.xml' | 'xep-0019.xml' | 'xep-0053.xml' | 'xep-0143.xml' | 'xep-0182.xml' | 'xep-0345.xml' | 'xep-0381.xml' | 'xep-0429.xml' | 'xep-0458.xml' ) case $header_type in Historical | Humorous | Informational | Organizational | 'Standards Track' | 'Procedural' ) echo "[PASS] XPATH value /xep/header/type/text() ('$header_type') equals a defined type."