Revert "XmlWriter reverts to XML 1.0."

This reverts commit a189387f49.
This commit is contained in:
Phil Nash 2017-02-06 16:21:01 +00:00
parent 23eb4cc580
commit 88b760276d
6 changed files with 52 additions and 121 deletions

View File

@ -22,12 +22,10 @@ namespace Catch {
class XmlEncode { class XmlEncode {
public: public:
enum ForWhat { ForTextNodes, ForAttributes }; enum ForWhat { ForTextNodes, ForAttributes };
enum XmlVersion { _1_0, _1_1 };
XmlEncode( XmlVersion xmlVersion, std::string const& str, ForWhat forWhat = ForTextNodes ) XmlEncode( std::string const& str, ForWhat forWhat = ForTextNodes )
: m_str( str ), : m_str( str ),
m_forWhat( forWhat ), m_forWhat( forWhat )
m_xmlVersion( xmlVersion )
{} {}
void encodeTo( std::ostream& os ) const { void encodeTo( std::ostream& os ) const {
@ -59,15 +57,8 @@ namespace Catch {
default: default:
// Escape control chars - based on contribution by @espenalb in PR #465 and // Escape control chars - based on contribution by @espenalb in PR #465 and
// by @mrpi PR #588 // by @mrpi PR #588
if ( ( c >= 0 && c < '\x09' ) || ( c > '\x0D' && c < '\x20') || c=='\x7F' ) { if ( ( c >= 0 && c < '\x09' ) || ( c > '\x0D' && c < '\x20') || c=='\x7F' )
if( m_xmlVersion == _1_0 ) os << "&#x" << std::uppercase << std::hex << std::setfill('0') << std::setw(2) << static_cast<int>( c ) << ';';
// see http://stackoverflow.com/questions/404107/why-are-control-characters-illegal-in-xml-1-0
os << "\\x" << std::uppercase << std::hex << std::setfill('0') << std::setw(2)
<< static_cast<int>( c );
else
os << "&#x" << std::uppercase << std::hex << std::setfill('0') << std::setw(2)
<< static_cast<int>( c ) << ';';
}
else else
os << c; os << c;
} }
@ -82,7 +73,6 @@ namespace Catch {
private: private:
std::string m_str; std::string m_str;
ForWhat m_forWhat; ForWhat m_forWhat;
XmlVersion m_xmlVersion;
}; };
class XmlWriter { class XmlWriter {
@ -122,19 +112,20 @@ namespace Catch {
XmlWriter() XmlWriter()
: m_tagIsOpen( false ), : m_tagIsOpen( false ),
m_needsNewline( false ), m_needsNewline( false ),
m_os( Catch::cout() ), m_os( &Catch::cout() )
m_xmlVersion( XmlEncode::_1_0 )
{ {
writeDeclaration(); // We encode control characters, which requires
// XML 1.1
// see http://stackoverflow.com/questions/404107/why-are-control-characters-illegal-in-xml-1-0
*m_os << "<?xml version=\"1.1\" encoding=\"UTF-8\"?>\n";
} }
XmlWriter( std::ostream& os ) XmlWriter( std::ostream& os )
: m_tagIsOpen( false ), : m_tagIsOpen( false ),
m_needsNewline( false ), m_needsNewline( false ),
m_os( os ), m_os( &os )
m_xmlVersion( XmlEncode::_1_0 )
{ {
writeDeclaration(); *m_os << "<?xml version=\"1.1\" encoding=\"UTF-8\"?>\n";
} }
~XmlWriter() { ~XmlWriter() {
@ -145,7 +136,7 @@ namespace Catch {
XmlWriter& startElement( std::string const& name ) { XmlWriter& startElement( std::string const& name ) {
ensureTagClosed(); ensureTagClosed();
newlineIfNecessary(); newlineIfNecessary();
m_os << m_indent << '<' << name; stream() << m_indent << '<' << name;
m_tags.push_back( name ); m_tags.push_back( name );
m_indent += " "; m_indent += " ";
m_tagIsOpen = true; m_tagIsOpen = true;
@ -162,11 +153,11 @@ namespace Catch {
newlineIfNecessary(); newlineIfNecessary();
m_indent = m_indent.substr( 0, m_indent.size()-2 ); m_indent = m_indent.substr( 0, m_indent.size()-2 );
if( m_tagIsOpen ) { if( m_tagIsOpen ) {
m_os << "/>\n"; stream() << "/>\n";
m_tagIsOpen = false; m_tagIsOpen = false;
} }
else { else {
m_os << m_indent << "</" << m_tags.back() << ">\n"; stream() << m_indent << "</" << m_tags.back() << ">\n";
} }
m_tags.pop_back(); m_tags.pop_back();
return *this; return *this;
@ -174,12 +165,12 @@ namespace Catch {
XmlWriter& writeAttribute( std::string const& name, std::string const& attribute ) { XmlWriter& writeAttribute( std::string const& name, std::string const& attribute ) {
if( !name.empty() && !attribute.empty() ) if( !name.empty() && !attribute.empty() )
m_os << ' ' << name << "=\"" << XmlEncode( m_xmlVersion, attribute, XmlEncode::ForAttributes ) << '"'; stream() << ' ' << name << "=\"" << XmlEncode( attribute, XmlEncode::ForAttributes ) << '"';
return *this; return *this;
} }
XmlWriter& writeAttribute( std::string const& name, bool attribute ) { XmlWriter& writeAttribute( std::string const& name, bool attribute ) {
m_os << ' ' << name << "=\"" << ( attribute ? "true" : "false" ) << '"'; stream() << ' ' << name << "=\"" << ( attribute ? "true" : "false" ) << '"';
return *this; return *this;
} }
@ -195,8 +186,8 @@ namespace Catch {
bool tagWasOpen = m_tagIsOpen; bool tagWasOpen = m_tagIsOpen;
ensureTagClosed(); ensureTagClosed();
if( tagWasOpen && indent ) if( tagWasOpen && indent )
m_os << m_indent; stream() << m_indent;
m_os << XmlEncode( m_xmlVersion, text ); stream() << XmlEncode( text );
m_needsNewline = true; m_needsNewline = true;
} }
return *this; return *this;
@ -204,42 +195,39 @@ namespace Catch {
XmlWriter& writeComment( std::string const& text ) { XmlWriter& writeComment( std::string const& text ) {
ensureTagClosed(); ensureTagClosed();
m_os << m_indent << "<!--" << text << "-->"; stream() << m_indent << "<!--" << text << "-->";
m_needsNewline = true; m_needsNewline = true;
return *this; return *this;
} }
XmlWriter& writeBlankLine() { XmlWriter& writeBlankLine() {
ensureTagClosed(); ensureTagClosed();
m_os << '\n'; stream() << '\n';
return *this; return *this;
} }
void setStream( std::ostream& os ) {
m_os = &os;
}
private: private:
XmlWriter( XmlWriter const& ); XmlWriter( XmlWriter const& );
void operator=( XmlWriter const& ); void operator=( XmlWriter const& );
void writeDeclaration() { std::ostream& stream() {
switch( m_xmlVersion ) { return *m_os;
case XmlEncode::_1_0:
m_os << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
break;
case XmlEncode::_1_1:
m_os << "<?xml version=\"1.1\" encoding=\"UTF-8\"?>\n";
break;
}
} }
void ensureTagClosed() { void ensureTagClosed() {
if( m_tagIsOpen ) { if( m_tagIsOpen ) {
m_os << ">\n"; stream() << ">\n";
m_tagIsOpen = false; m_tagIsOpen = false;
} }
} }
void newlineIfNecessary() { void newlineIfNecessary() {
if( m_needsNewline ) { if( m_needsNewline ) {
m_os << '\n'; stream() << '\n';
m_needsNewline = false; m_needsNewline = false;
} }
} }
@ -248,8 +236,7 @@ namespace Catch {
bool m_needsNewline; bool m_needsNewline;
std::vector<std::string> m_tags; std::vector<std::string> m_tags;
std::string m_indent; std::string m_indent;
std::ostream& m_os; std::ostream* m_os;
XmlEncode::XmlVersion m_xmlVersion;
}; };
} }

View File

@ -830,5 +830,5 @@ with expansion:
=============================================================================== ===============================================================================
test cases: 157 | 113 passed | 42 failed | 2 failed as expected test cases: 157 | 113 passed | 42 failed | 2 failed as expected
assertions: 915 | 819 passed | 78 failed | 18 failed as expected assertions: 913 | 817 passed | 78 failed | 18 failed as expected

View File

@ -7982,53 +7982,27 @@ with expansion:
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
XmlEncode XmlEncode
string with control char (1) (XML 1.0) string with control char (1)
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
MiscTests.cpp:<line number> MiscTests.cpp:<line number>
............................................................................... ...............................................................................
MiscTests.cpp:<line number>: MiscTests.cpp:<line number>:
PASSED: PASSED:
REQUIRE( encode( "[\x01]" ) == "[\\x01]" ) REQUIRE( encode( "[\x01]" ) == "[&#x01;]" )
with expansion:
"[\x01]" == "[\x01]"
-------------------------------------------------------------------------------
XmlEncode
string with control char (1) (XMl 1.1)
-------------------------------------------------------------------------------
MiscTests.cpp:<line number>
...............................................................................
MiscTests.cpp:<line number>:
PASSED:
REQUIRE( encode( "[\x01]", Catch::XmlEncode::ForTextNodes, Catch::XmlEncode::_1_1 ) == "[&#x01;]" )
with expansion: with expansion:
"[&#x01;]" == "[&#x01;]" "[&#x01;]" == "[&#x01;]"
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
XmlEncode XmlEncode
string with control char (x7F) (XML 1.0) string with control char (x7F)
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
MiscTests.cpp:<line number> MiscTests.cpp:<line number>
............................................................................... ...............................................................................
MiscTests.cpp:<line number>: MiscTests.cpp:<line number>:
PASSED: PASSED:
REQUIRE( encode( "[\x7F]" ) == "[\\x7F]" ) REQUIRE( encode( "[\x7F]" ) == "[&#x7F;]" )
with expansion:
"[\x7F]" == "[\x7F]"
-------------------------------------------------------------------------------
XmlEncode
string with control char (x7F) (XML 1.1)
-------------------------------------------------------------------------------
MiscTests.cpp:<line number>
...............................................................................
MiscTests.cpp:<line number>:
PASSED:
REQUIRE( encode( "[\x7F]", Catch::XmlEncode::ForTextNodes, Catch::XmlEncode::_1_1 ) == "[&#x7F;]" )
with expansion: with expansion:
"[&#x7F;]" == "[&#x7F;]" "[&#x7F;]" == "[&#x7F;]"
@ -9052,5 +9026,5 @@ PASSED:
=============================================================================== ===============================================================================
test cases: 157 | 112 passed | 43 failed | 2 failed as expected test cases: 157 | 112 passed | 43 failed | 2 failed as expected
assertions: 917 | 819 passed | 80 failed | 18 failed as expected assertions: 915 | 817 passed | 80 failed | 18 failed as expected

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.1" encoding="UTF-8"?>
<testsuites> <testsuites>
<testsuite name="<exe-name>" errors="13" failures="68" tests="918" hostname="tbd" time="{duration}" timestamp="{iso8601-timestamp}"> <testsuite name="<exe-name>" errors="13" failures="68" tests="916" hostname="tbd" time="{duration}" timestamp="{iso8601-timestamp}">
<testcase classname="global" name="# A test name that starts with a #" time="{duration}"/> <testcase classname="global" name="# A test name that starts with a #" time="{duration}"/>
<testcase classname="global" name="'Not' checks that should fail" time="{duration}"> <testcase classname="global" name="'Not' checks that should fail" time="{duration}">
<failure message="false != false" type="CHECK"> <failure message="false != false" type="CHECK">
@ -538,10 +538,8 @@ ExceptionTests.cpp:<line number>
<testcase classname="XmlEncode" name="string with less-than" time="{duration}"/> <testcase classname="XmlEncode" name="string with less-than" time="{duration}"/>
<testcase classname="XmlEncode" name="string with greater-than" time="{duration}"/> <testcase classname="XmlEncode" name="string with greater-than" time="{duration}"/>
<testcase classname="XmlEncode" name="string with quotes" time="{duration}"/> <testcase classname="XmlEncode" name="string with quotes" time="{duration}"/>
<testcase classname="XmlEncode" name="string with control char (1) (XML 1.0)" time="{duration}"/> <testcase classname="XmlEncode" name="string with control char (1)" time="{duration}"/>
<testcase classname="XmlEncode" name="string with control char (1) (XMl 1.1)" time="{duration}"/> <testcase classname="XmlEncode" name="string with control char (x7F)" time="{duration}"/>
<testcase classname="XmlEncode" name="string with control char (x7F) (XML 1.0)" time="{duration}"/>
<testcase classname="XmlEncode" name="string with control char (x7F) (XML 1.1)" time="{duration}"/>
<testcase classname="global" name="atomic if" time="{duration}"/> <testcase classname="global" name="atomic if" time="{duration}"/>
<testcase classname="global" name="boolean member" time="{duration}"/> <testcase classname="global" name="boolean member" time="{duration}"/>
<testcase classname="global" name="checkedElse" time="{duration}"/> <testcase classname="global" name="checkedElse" time="{duration}"/>

View File

@ -1,4 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.1" encoding="UTF-8"?>
<Catch name="<exe-name>"> <Catch name="<exe-name>">
<Group name="<exe-name>"> <Group name="<exe-name>">
<TestCase name="# A test name that starts with a #"> <TestCase name="# A test name that starts with a #">
@ -8462,21 +8462,10 @@ there"
</Expression> </Expression>
<OverallResults successes="2" failures="0" expectedFailures="0"/> <OverallResults successes="2" failures="0" expectedFailures="0"/>
</Section> </Section>
<Section name="string with control char (1) (XML 1.0)"> <Section name="string with control char (1)">
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/MiscTests.cpp" > <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/MiscTests.cpp" >
<Original> <Original>
encode( "[\x01]" ) == "[\\x01]" encode( "[\x01]" ) == "[&amp;#x01;]"
</Original>
<Expanded>
"[\x01]" == "[\x01]"
</Expanded>
</Expression>
<OverallResults successes="1" failures="0" expectedFailures="0"/>
</Section>
<Section name="string with control char (1) (XMl 1.1)">
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/MiscTests.cpp" >
<Original>
encode( "[\x01]", Catch::XmlEncode::ForTextNodes, Catch::XmlEncode::_1_1 ) == "[&amp;#x01;]"
</Original> </Original>
<Expanded> <Expanded>
"[&amp;#x01;]" == "[&amp;#x01;]" "[&amp;#x01;]" == "[&amp;#x01;]"
@ -8484,21 +8473,10 @@ there"
</Expression> </Expression>
<OverallResults successes="1" failures="0" expectedFailures="0"/> <OverallResults successes="1" failures="0" expectedFailures="0"/>
</Section> </Section>
<Section name="string with control char (x7F) (XML 1.0)"> <Section name="string with control char (x7F)">
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/MiscTests.cpp" > <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/MiscTests.cpp" >
<Original> <Original>
encode( "[\x7F]" ) == "[\\x7F]" encode( "[\x7F]" ) == "[&amp;#x7F;]"
</Original>
<Expanded>
"[\x7F]" == "[\x7F]"
</Expanded>
</Expression>
<OverallResults successes="1" failures="0" expectedFailures="0"/>
</Section>
<Section name="string with control char (x7F) (XML 1.1)">
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/MiscTests.cpp" >
<Original>
encode( "[\x7F]", Catch::XmlEncode::ForTextNodes, Catch::XmlEncode::_1_1 ) == "[&amp;#x7F;]"
</Original> </Original>
<Expanded> <Expanded>
"[&amp;#x7F;]" == "[&amp;#x7F;]" "[&amp;#x7F;]" == "[&amp;#x7F;]"
@ -9542,7 +9520,7 @@ there"
</Section> </Section>
<OverallResult success="true"/> <OverallResult success="true"/>
</TestCase> </TestCase>
<OverallResults successes="819" failures="81" expectedFailures="18"/> <OverallResults successes="817" failures="81" expectedFailures="18"/>
</Group> </Group>
<OverallResults successes="819" failures="80" expectedFailures="18"/> <OverallResults successes="817" failures="80" expectedFailures="18"/>
</Catch> </Catch>

View File

@ -429,9 +429,9 @@ TEST_CASE( "toString on wchar_t returns the string contents", "[toString]" ) {
CHECK( result == "\"wide load\"" ); CHECK( result == "\"wide load\"" );
} }
inline std::string encode( std::string const& str, Catch::XmlEncode::ForWhat forWhat = Catch::XmlEncode::ForTextNodes, Catch::XmlEncode::XmlVersion version = Catch::XmlEncode::_1_0 ) { inline std::string encode( std::string const& str, Catch::XmlEncode::ForWhat forWhat = Catch::XmlEncode::ForTextNodes ) {
std::ostringstream oss; std::ostringstream oss;
oss << Catch::XmlEncode( version, str, forWhat ); oss << Catch::XmlEncode( str, forWhat );
return oss.str(); return oss.str();
} }
@ -457,17 +457,11 @@ TEST_CASE( "XmlEncode" ) {
REQUIRE( encode( stringWithQuotes ) == stringWithQuotes ); REQUIRE( encode( stringWithQuotes ) == stringWithQuotes );
REQUIRE( encode( stringWithQuotes, Catch::XmlEncode::ForAttributes ) == "don't &quot;quote&quot; me on that" ); REQUIRE( encode( stringWithQuotes, Catch::XmlEncode::ForAttributes ) == "don't &quot;quote&quot; me on that" );
} }
SECTION( "string with control char (1) (XML 1.0)" ) { SECTION( "string with control char (1)" ) {
REQUIRE( encode( "[\x01]" ) == "[\\x01]" ); REQUIRE( encode( "[\x01]" ) == "[&#x01;]" );
} }
SECTION( "string with control char (1) (XMl 1.1)" ) { SECTION( "string with control char (x7F)" ) {
REQUIRE( encode( "[\x01]", Catch::XmlEncode::ForTextNodes, Catch::XmlEncode::_1_1 ) == "[&#x01;]" ); REQUIRE( encode( "[\x7F]" ) == "[&#x7F;]" );
}
SECTION( "string with control char (x7F) (XML 1.0)" ) {
REQUIRE( encode( "[\x7F]" ) == "[\\x7F]" );
}
SECTION( "string with control char (x7F) (XML 1.1)" ) {
REQUIRE( encode( "[\x7F]", Catch::XmlEncode::ForTextNodes, Catch::XmlEncode::_1_1 ) == "[&#x7F;]" );
} }
} }