diff --git a/NEWS b/NEWS index e69ac155..7eebca04 100644 --- a/NEWS +++ b/NEWS @@ -1,6 +1,9 @@ In Development: # Mentioning Check 0.10.0 for now, to fix distcheck target until next release +* Emit only valid XML characters in XML logging (assumes ASCII encoding). + Bug #103 + * Add LGPL header to files where it was missing; update FSF address in LGPL headers Bug #110 diff --git a/src/check_print.c b/src/check_print.c index d56e1707..35f13b64 100644 --- a/src/check_print.c +++ b/src/check_print.c @@ -95,34 +95,53 @@ static void srunner_fprint_results(FILE * file, SRunner * sr, void fprint_xml_esc(FILE * file, const char *str) { + /* The valid XML characters are as follows: + * #x9 | #xA | #xD | [#x20-#xD7FF] | [#xE000-#xFFFD] | [#x10000-#x10FFFF] + * Characters that are outside of ASCII must be encoded. Further, the + * following special characters: + * " ' < > & + * must be encoded. We assume that the incoming string may be a multibyte + * character. + */ + for(; *str != '\0'; str++) { + char next = *str; - switch (*str) + /* handle special characters that must be escaped */ + if(next == '"' || next == '\'' || next == '<' || next == '>' || next == '&') { - - /* handle special characters that must be escaped */ - case '"': - fputs(""", file); - break; - case '\'': - fputs("'", file); - break; - case '<': - fputs("<", file); - break; - case '>': - fputs(">", file); - break; - case '&': - fputs("&", file); - break; - - /* regular characters, print as is */ - default: - fputc(*str, file); - break; + switch (next) + { + case '"': + fputs(""", file); + break; + case '\'': + fputs("'", file); + break; + case '<': + fputs("<", file); + break; + case '>': + fputs(">", file); + break; + case '&': + fputs("&", file); + break; + } + } + /* printable ASCII */ + else if(next >= ' ' && next <= '~') + { + fputc(next, file); + } + /* Non-printable character */ + else if(next == 0x9 || next == 0xA || next == 0xD || + next >= 0x20) + { + fprintf(file, "&#x%X;", next); } + /* If it did not get printed, it is not a valid XML character*/ } } diff --git a/tests/ex_output.c b/tests/ex_output.c index 6d0aad27..9e4e7467 100644 --- a/tests/ex_output.c +++ b/tests/ex_output.c @@ -75,7 +75,7 @@ END_TEST START_TEST(test_xml_esc_fail_msg) { - ck_abort_msg("fail \" ' < > & message"); + ck_abort_msg("fail \" ' < > & \x9 \xA" "X""\x08"" message"); /* backspace char \x08 deletes the X */ } END_TEST @@ -120,8 +120,8 @@ static Suite *make_xml_esc_suite(void) Suite *s; TCase *tc; - s = suite_create("XML escape \" ' < > & tests"); - tc = tcase_create("description \" ' < > &"); + s = suite_create("XML escape \" ' < > & \x9 \xA" "X""\x08"" tests"); /* backspace char \x08 deletes the X */ + tc = tcase_create("description \" ' < > & \x9 \xA" "X""\x08"" end"); /* backspace char \x08 deletes the X */ suite_add_tcase(s, tc); tcase_add_test(tc, test_xml_esc_fail_msg); diff --git a/tests/test_output_strings b/tests/test_output_strings index b23da03f..ccb3861f 100644 --- a/tests/test_output_strings +++ b/tests/test_output_strings @@ -2,12 +2,17 @@ . ./test_vars +# Set the 'internal field separator' character to +# something besides whitespace so that the string +# comparisons will work +IFS="~" + ################## # stdout output ################## -suite_output="Running suite(s): S1 +suite_output=`printf "Running suite(s): S1 S2 - XML escape \" ' < > & tests" + XML escape \" ' < > & \x9 \x0AX\x08 tests"` exp_silent="" @@ -20,25 +25,25 @@ exp_minimal="$suite_output $exp_minimal_result" if [ $HAVE_FORK -eq 1 ]; then -exp_normal_result="37%: Checks: 8, Failures: 4, Errors: 1 +exp_normal_result=`printf "37%%: Checks: 8, Failures: 4, Errors: 1 ${SRCDIR}ex_output.c:37:F:Core:test_fail:0: Failure ${SRCDIR}ex_output.c:46:E:Core:test_exit:0: (after this point) Early exit with return value 1 ${SRCDIR}ex_output.c:72:F:Core:test_loop:0: Iteration 0 failed ${SRCDIR}ex_output.c:72:F:Core:test_loop:2: Iteration 2 failed -${SRCDIR}ex_output.c:78:F:description \" ' < > &:test_xml_esc_fail_msg:0: fail \" ' < > & message" +${SRCDIR}ex_output.c:78:F:description \" ' < > & \x9 \x0AX\x08 end:test_xml_esc_fail_msg:0: fail \" ' < > & \x9 \x0AX\x08 message"` else -exp_normal_result="42%: Checks: 7, Failures: 4, Errors: 0 +exp_normal_result=`printf "42%%: Checks: 7, Failures: 4, Errors: 0 ${SRCDIR}ex_output.c:37:F:Core:test_fail:0: Failure ${SRCDIR}ex_output.c:72:F:Core:test_loop:0: Iteration 0 failed ${SRCDIR}ex_output.c:72:F:Core:test_loop:2: Iteration 2 failed -${SRCDIR}ex_output.c:78:F:description \" ' < > &:test_xml_esc_fail_msg:0: fail \" ' < > & message" +${SRCDIR}ex_output.c:78:F:description \" ' < > &\x9 \xA end:test_xml_esc_fail_msg:0: fail \" ' < > & \x9 \x0AX\x08 message"` fi exp_normal="$suite_output $exp_normal_result" if [ $HAVE_FORK -eq 1 ]; then -exp_verbose_result="37%: Checks: 8, Failures: 4, Errors: 1 +exp_verbose_result=`printf "37%%: Checks: 8, Failures: 4, Errors: 1 ${SRCDIR}ex_output.c:31:P:Core:test_pass:0: Passed ${SRCDIR}ex_output.c:37:F:Core:test_fail:0: Failure ${SRCDIR}ex_output.c:46:E:Core:test_exit:0: (after this point) Early exit with return value 1 @@ -46,22 +51,22 @@ ${SRCDIR}ex_output.c:66:P:Core:test_pass2:0: Passed ${SRCDIR}ex_output.c:72:F:Core:test_loop:0: Iteration 0 failed ${SRCDIR}ex_output.c:72:P:Core:test_loop:1: Passed ${SRCDIR}ex_output.c:72:F:Core:test_loop:2: Iteration 2 failed -${SRCDIR}ex_output.c:78:F:description \" ' < > &:test_xml_esc_fail_msg:0: fail \" ' < > & message" +${SRCDIR}ex_output.c:78:F:description \" ' < > & \x9 \x0AX\x08 end:test_xml_esc_fail_msg:0: fail \" ' < > & \x9 \x0AX\x08 message"` else -exp_verbose_result="42%: Checks: 7, Failures: 4, Errors: 0 +exp_verbose_result=`printf "42%%: Checks: 7, Failures: 4, Errors: 0 ${SRCDIR}ex_output.c:31:P:Core:test_pass:0: Passed ${SRCDIR}ex_output.c:37:F:Core:test_fail:0: Failure ${SRCDIR}ex_output.c:66:P:Core:test_pass2:0: Passed ${SRCDIR}ex_output.c:72:F:Core:test_loop:0: Iteration 0 failed ${SRCDIR}ex_output.c:72:P:Core:test_loop:1: Passed ${SRCDIR}ex_output.c:72:F:Core:test_loop:2: Iteration 2 failed -${SRCDIR}ex_output.c:78:F:description \" ' < > &:test_xml_esc_fail_msg:0: fail \" ' < > & message" +${SRCDIR}ex_output.c:78:F:description \" ' < > & \x9 \x0AX\x08 end:test_xml_esc_fail_msg:0: fail \" ' < > & \x9 \x0AX\x08 message"` fi exp_verbose="$suite_output $exp_verbose_result" if [ $HAVE_FORK -eq 1 ]; then -exp_subunit="test: Core:test_pass +exp_subunit=`printf "test: Core:test_pass success: Core:test_pass test: Core:test_fail failure: Core:test_fail [ @@ -83,12 +88,12 @@ test: Core:test_loop failure: Core:test_loop [ ${SRCDIR}ex_output.c:72: Iteration 2 failed ] -test: description \" ' < > &:test_xml_esc_fail_msg -failure: description \" ' < > &:test_xml_esc_fail_msg [ -${SRCDIR}ex_output.c:78: fail \" ' < > & message -]" +test: description \" ' < > & \x9 \x0AX\x08 end:test_xml_esc_fail_msg +failure: description \" ' < > & \x9 \x0AX\x08 end:test_xml_esc_fail_msg [ +${SRCDIR}ex_output.c:78: fail \" ' < > & \x9 \x0AX\x08 message +]"` else -exp_subunit="test: Core:test_pass +exp_subunit=`printf "test: Core:test_pass success: Core:test_pass test: Core:test_fail failure: Core:test_fail [ @@ -106,17 +111,17 @@ test: Core:test_loop failure: Core:test_loop [ ${SRCDIR}ex_output.c:72: Iteration 2 failed ] -test: description \" ' < > &:test_xml_esc_fail_msg -failure: description \" ' < > &:test_xml_esc_fail_msg [ -${SRCDIR}ex_output.c:78: fail \" ' < > & message -]" +test: description \" ' < > & \x9 \x0AX\x08 end:test_xml_esc_fail_msg +failure: description \" ' < > & \x9 \x0AX\x08 end:test_xml_esc_fail_msg [ +${SRCDIR}ex_output.c:78: fail \" ' < > & \x9 \x0AX\x08 message +]"` fi ################## # log output ################## if [ $HAVE_FORK -eq 1 ]; then -expected_log_log="Running suite S1 +expected_log_log=`printf "Running suite S1 ${SRCDIR}ex_output.c:31:P:Core:test_pass:0: Passed ${SRCDIR}ex_output.c:37:F:Core:test_fail:0: Failure ${SRCDIR}ex_output.c:46:E:Core:test_exit:0: (after this point) Early exit with return value 1 @@ -125,12 +130,12 @@ ${SRCDIR}ex_output.c:66:P:Core:test_pass2:0: Passed ${SRCDIR}ex_output.c:72:F:Core:test_loop:0: Iteration 0 failed ${SRCDIR}ex_output.c:72:P:Core:test_loop:1: Passed ${SRCDIR}ex_output.c:72:F:Core:test_loop:2: Iteration 2 failed -Running suite XML escape \" ' < > & tests -${SRCDIR}ex_output.c:78:F:description \" ' < > &:test_xml_esc_fail_msg:0: fail \" ' < > & message +Running suite XML escape \" ' < > & \x9 \x0AX\x08 tests +${SRCDIR}ex_output.c:78:F:description \" ' < > & \x9 \x0AX\x08 end:test_xml_esc_fail_msg:0: fail \" ' < > & \x9 \x0AX\x08 message Results for all suites run: -37%: Checks: 8, Failures: 4, Errors: 1" +37%%: Checks: 8, Failures: 4, Errors: 1"` else -expected_log_log="Running suite S1 +expected_log_log=`printf "Running suite S1 ${SRCDIR}ex_output.c:31:P:Core:test_pass:0: Passed ${SRCDIR}ex_output.c:37:F:Core:test_fail:0: Failure Running suite S2 @@ -138,10 +143,10 @@ ${SRCDIR}ex_output.c:66:P:Core:test_pass2:0: Passed ${SRCDIR}ex_output.c:72:F:Core:test_loop:0: Iteration 0 failed ${SRCDIR}ex_output.c:72:P:Core:test_loop:1: Passed ${SRCDIR}ex_output.c:72:F:Core:test_loop:2: Iteration 2 failed -Running suite XML escape \" ' < > & tests -${SRCDIR}ex_output.c:78:F:description \" ' < > &:test_xml_esc_fail_msg:0: fail \" ' < > & message +Running suite XML escape \" ' < > & \x9 \x0AX\x08 tests +${SRCDIR}ex_output.c:78:F:description \" ' < > & \x9 \x0AX\x08 end:test_xml_esc_fail_msg:0: fail \" ' < > & \x9 \x0AX\x08 message Results for all suites run: -42%: Checks: 7, Failures: 4, Errors: 0" +42%%: Checks: 7, Failures: 4, Errors: 0"` fi ################## @@ -207,19 +212,19 @@ expected_xml=" - XML escape " ' < > & tests + XML escape " ' < > & X tests ex_output.c:78 test_xml_esc_fail_msg 0 - description " ' < > & - fail " ' < > & message + description " ' < > & X end + fail " ' < > & X message " expected_duration_count=9 else -expected_xml=" +expected_xml=" @@ -271,13 +276,13 @@ expected_xml=" - XML escape " ' < > & tests + XML escape " ' < > & X tests ex_output.c:78 test_xml_esc_fail_msg 0 - description " ' < > & - fail " ' < > & message + description " ' < > & X end + fail " ' < > & X message " @@ -288,16 +293,16 @@ fi # tap output ################## if [ $HAVE_FORK -eq 1 ]; then -expected_normal_tap="ok 1 - ${SRCDIR}ex_output.c:Core:test_pass: Passed +expected_normal_tap=`printf "ok 1 - ${SRCDIR}ex_output.c:Core:test_pass: Passed not ok 2 - ${SRCDIR}ex_output.c:Core:test_fail: Failure not ok 3 - ${SRCDIR}ex_output.c:Core:test_exit: Early exit with return value 1 ok 4 - ${SRCDIR}ex_output.c:Core:test_pass2: Passed not ok 5 - ${SRCDIR}ex_output.c:Core:test_loop: Iteration 0 failed ok 6 - ${SRCDIR}ex_output.c:Core:test_loop: Passed not ok 7 - ${SRCDIR}ex_output.c:Core:test_loop: Iteration 2 failed -not ok 8 - ${SRCDIR}ex_output.c:description \" ' < > &:test_xml_esc_fail_msg: fail \" ' < > & message -1..8" -expected_aborted_tap="ok 1 - ${SRCDIR}ex_output.c:Core:test_pass: Passed +not ok 8 - ${SRCDIR}ex_output.c:description \" ' < > & \x9 \x0AX\x08 end:test_xml_esc_fail_msg: fail \" ' < > & \x9 \x0AX\x08 message +1..8"` +expected_aborted_tap=`printf "ok 1 - ${SRCDIR}ex_output.c:Core:test_pass: Passed not ok 2 - ${SRCDIR}ex_output.c:Core:test_fail: Failure not ok 3 - ${SRCDIR}ex_output.c:Core:test_exit: Early exit with return value 1 not ok 4 - ${SRCDIR}ex_output.c:Core:test_abort: Early exit with return value 1 @@ -305,17 +310,17 @@ ok 5 - ${SRCDIR}ex_output.c:Core:test_pass2: Passed not ok 6 - ${SRCDIR}ex_output.c:Core:test_loop: Iteration 0 failed ok 7 - ${SRCDIR}ex_output.c:Core:test_loop: Passed not ok 8 - ${SRCDIR}ex_output.c:Core:test_loop: Iteration 2 failed -not ok 9 - ${SRCDIR}ex_output.c:description \" ' < > &:test_xml_esc_fail_msg: fail \" ' < > & message -1..9" +not ok 9 - ${SRCDIR}ex_output.c:description \" ' < > & \x9 \x0AX\x08 end:test_xml_esc_fail_msg: fail \" ' < > & \x9 \x0AX\x08 message +1..9"` else -expected_normal_tap="ok 1 - ${SRCDIR}ex_output.c:Core:test_pass: Passed +expected_normal_tap=`printf "ok 1 - ${SRCDIR}ex_output.c:Core:test_pass: Passed not ok 2 - ${SRCDIR}ex_output.c:Core:test_fail: Failure ok 3 - ${SRCDIR}ex_output.c:Core:test_pass2: Passed not ok 4 - ${SRCDIR}ex_output.c:Core:test_loop: Iteration 0 failed ok 5 - ${SRCDIR}ex_output.c:Core:test_loop: Passed not ok 6 - ${SRCDIR}ex_output.c:Core:test_loop: Iteration 2 failed -not ok 7 - ${SRCDIR}ex_output.c:description \" ' < > &:test_xml_esc_fail_msg: fail \" ' < > & message -1..7" +not ok 7 - ${SRCDIR}ex_output.c:description \" ' < > & \x9 \x0AX\x08 end:test_xml_esc_fail_msg: fail \" ' < > & \x9 \x0AX\x08 message +1..7"` # When fork() is unavailable, one of the tests # will invoke exit() which will terminate the # unit testing program. In that case, the tap diff --git a/tests/test_xml_output.sh b/tests/test_xml_output.sh index 7497f376..11bb77ad 100755 --- a/tests/test_xml_output.sh +++ b/tests/test_xml_output.sh @@ -25,12 +25,18 @@ if [ x"${expected_duration_count}" != x"${actual_duration_count}" ]; then exit 1; fi -for duration in `grep "\" ${OUTPUT_FILE} | cut -d ">" -f 2 | cut -d "<" -f 1`; do -int_duration=`echo $duration | cut -d "." -f 1` -if [ "${int_duration}" -ne "-1" ] && [ "${int_duration}" -gt "${CK_DEFAULT_TIMEOUT}" ]; then - echo "Problem with duration ${duration}; is not valid. Should be -1 or in [0, ${CK_DEFAULT_TIMEOUT}]" - exit 1 -fi +num_durations=`grep "\" ${OUTPUT_FILE} | wc -l` + +i=1 +while [ ${i} -le ${num_durations} ]; do + duration=`grep "\" ${OUTPUT_FILE} | head -n ${i} | tail -n 1 | cut -d ">" -f 2 | cut -d "<" -f 1` + int_duration=`echo $duration | cut -d "." -f 1` + if [ "${int_duration}" -ne "-1" ] && [ "${int_duration}" -gt "${CK_DEFAULT_TIMEOUT}" ]; then + echo "Problem with duration ${duration}; is not valid. Should be -1 or in [0, ${CK_DEFAULT_TIMEOUT}]" + exit 1 + fi + + i=$((i+1)) done