mirror of
https://github.com/catchorg/Catch2.git
synced 2024-11-26 07:16:10 +01:00
Fixed Xml encoding
- don't encode apostrophes - only encode quotes in attributes - encode control characters (as in PR #465)
This commit is contained in:
parent
6de135c63a
commit
d6e59cd56f
@ -14,9 +14,65 @@
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <iomanip>
|
||||
|
||||
namespace Catch {
|
||||
|
||||
class XmlEncode {
|
||||
public:
|
||||
enum ForWhat { ForTextNodes, ForAttributes };
|
||||
|
||||
XmlEncode( std::string const& str, ForWhat forWhat = ForTextNodes )
|
||||
: m_str( str ),
|
||||
m_forWhat( forWhat )
|
||||
{}
|
||||
|
||||
void encodeTo( std::ostream& os ) const {
|
||||
|
||||
// Apostrophe escaping not necessary if we always use " to write attributes
|
||||
// (see: http://www.w3.org/TR/xml/#syntax)
|
||||
|
||||
for( std::size_t i = 0; i < m_str.size(); ++ i ) {
|
||||
char c = m_str[i];
|
||||
switch( c ) {
|
||||
case '<': os << "<"; break;
|
||||
case '&': os << "&"; break;
|
||||
|
||||
case '>':
|
||||
// See: http://www.w3.org/TR/xml/#syntax
|
||||
if( i > 2 && m_str[i-1] == ']' && m_str[i-2] == ']' )
|
||||
os << ">";
|
||||
else
|
||||
os << c;
|
||||
break;
|
||||
|
||||
case '\"':
|
||||
if( m_forWhat == ForAttributes )
|
||||
os << """;
|
||||
else
|
||||
os << c;
|
||||
break;
|
||||
|
||||
default:
|
||||
// Escape control chars - based on contribution by @espenalb in PR #465
|
||||
if ( ( c < '\x09' ) || ( c > '\x0D' && c < '\x20') || c=='\x7F' )
|
||||
os << "&#x" << std::uppercase << std::hex << static_cast<int>( c );
|
||||
else
|
||||
os << c;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
friend std::ostream& operator << ( std::ostream& os, XmlEncode const& xmlEncode ) {
|
||||
xmlEncode.encodeTo( os );
|
||||
return os;
|
||||
}
|
||||
|
||||
private:
|
||||
std::string m_str;
|
||||
ForWhat m_forWhat;
|
||||
};
|
||||
|
||||
class XmlWriter {
|
||||
public:
|
||||
|
||||
@ -99,11 +155,8 @@ namespace Catch {
|
||||
}
|
||||
|
||||
XmlWriter& writeAttribute( std::string const& name, std::string const& attribute ) {
|
||||
if( !name.empty() && !attribute.empty() ) {
|
||||
stream() << " " << name << "=\"";
|
||||
writeEncodedText( attribute );
|
||||
stream() << "\"";
|
||||
}
|
||||
if( !name.empty() && !attribute.empty() )
|
||||
stream() << " " << name << "=\"" << XmlEncode( attribute, XmlEncode::ForAttributes ) << "\"";
|
||||
return *this;
|
||||
}
|
||||
|
||||
@ -114,9 +167,9 @@ namespace Catch {
|
||||
|
||||
template<typename T>
|
||||
XmlWriter& writeAttribute( std::string const& name, T const& attribute ) {
|
||||
if( !name.empty() )
|
||||
stream() << " " << name << "=\"" << attribute << "\"";
|
||||
return *this;
|
||||
std::ostringstream oss;
|
||||
oss << attribute;
|
||||
return writeAttribute( name, oss.str() );
|
||||
}
|
||||
|
||||
XmlWriter& writeText( std::string const& text, bool indent = true ) {
|
||||
@ -125,7 +178,7 @@ namespace Catch {
|
||||
ensureTagClosed();
|
||||
if( tagWasOpen && indent )
|
||||
stream() << m_indent;
|
||||
writeEncodedText( text );
|
||||
stream() << XmlEncode( text );
|
||||
m_needsNewline = true;
|
||||
}
|
||||
return *this;
|
||||
@ -170,30 +223,6 @@ namespace Catch {
|
||||
}
|
||||
}
|
||||
|
||||
void writeEncodedText( std::string const& text ) {
|
||||
static const char* charsToEncode = "<&\"";
|
||||
std::string mtext = text;
|
||||
std::string::size_type pos = mtext.find_first_of( charsToEncode );
|
||||
while( pos != std::string::npos ) {
|
||||
stream() << mtext.substr( 0, pos );
|
||||
|
||||
switch( mtext[pos] ) {
|
||||
case '<':
|
||||
stream() << "<";
|
||||
break;
|
||||
case '&':
|
||||
stream() << "&";
|
||||
break;
|
||||
case '\"':
|
||||
stream() << """;
|
||||
break;
|
||||
}
|
||||
mtext = mtext.substr( pos+1 );
|
||||
pos = mtext.find_first_of( charsToEncode );
|
||||
}
|
||||
stream() << mtext;
|
||||
}
|
||||
|
||||
bool m_tagIsOpen;
|
||||
bool m_needsNewline;
|
||||
std::vector<std::string> m_tags;
|
||||
|
@ -797,6 +797,6 @@ with expansion:
|
||||
"first" == "second"
|
||||
|
||||
===============================================================================
|
||||
test cases: 157 | 117 passed | 39 failed | 1 failed as expected
|
||||
assertions: 773 | 680 passed | 80 failed | 13 failed as expected
|
||||
test cases: 158 | 118 passed | 39 failed | 1 failed as expected
|
||||
assertions: 783 | 690 passed | 80 failed | 13 failed as expected
|
||||
|
||||
|
@ -3762,6 +3762,128 @@ PASSED:
|
||||
with expansion:
|
||||
""wide load"" == ""wide load""
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
XmlEncode
|
||||
normal string
|
||||
-------------------------------------------------------------------------------
|
||||
MiscTests.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
MiscTests.cpp:<line number>:
|
||||
PASSED:
|
||||
REQUIRE( encode( "normal string" ) == "normal string" )
|
||||
with expansion:
|
||||
"normal string" == "normal string"
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
XmlEncode
|
||||
empty string
|
||||
-------------------------------------------------------------------------------
|
||||
MiscTests.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
MiscTests.cpp:<line number>:
|
||||
PASSED:
|
||||
REQUIRE( encode( "" ) == "" )
|
||||
with expansion:
|
||||
"" == ""
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
XmlEncode
|
||||
string with ampersand
|
||||
-------------------------------------------------------------------------------
|
||||
MiscTests.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
MiscTests.cpp:<line number>:
|
||||
PASSED:
|
||||
REQUIRE( encode( "smith & jones" ) == "smith & jones" )
|
||||
with expansion:
|
||||
"smith & jones" == "smith & jones"
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
XmlEncode
|
||||
string with less-than
|
||||
-------------------------------------------------------------------------------
|
||||
MiscTests.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
MiscTests.cpp:<line number>:
|
||||
PASSED:
|
||||
REQUIRE( encode( "smith < jones" ) == "smith < jones" )
|
||||
with expansion:
|
||||
"smith < jones" == "smith < jones"
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
XmlEncode
|
||||
string with greater-than
|
||||
-------------------------------------------------------------------------------
|
||||
MiscTests.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
MiscTests.cpp:<line number>:
|
||||
PASSED:
|
||||
REQUIRE( encode( "smith > jones" ) == "smith > jones" )
|
||||
with expansion:
|
||||
"smith > jones" == "smith > jones"
|
||||
|
||||
MiscTests.cpp:<line number>:
|
||||
PASSED:
|
||||
REQUIRE( encode( "smith ]]> jones" ) == "smith ]]> jones" )
|
||||
with expansion:
|
||||
"smith ]]> jones"
|
||||
==
|
||||
"smith ]]> jones"
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
XmlEncode
|
||||
string with quotes
|
||||
-------------------------------------------------------------------------------
|
||||
MiscTests.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
MiscTests.cpp:<line number>:
|
||||
PASSED:
|
||||
REQUIRE( encode( stringWithQuotes ) == stringWithQuotes )
|
||||
with expansion:
|
||||
"don't "quote" me on that"
|
||||
==
|
||||
"don't "quote" me on that"
|
||||
|
||||
MiscTests.cpp:<line number>:
|
||||
PASSED:
|
||||
REQUIRE( encode( stringWithQuotes, Catch::XmlEncode::ForAttributes ) == "don't "quote" me on that" )
|
||||
with expansion:
|
||||
"don't "quote" me on that"
|
||||
==
|
||||
"don't "quote" me on that"
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
XmlEncode
|
||||
string with control char (1)
|
||||
-------------------------------------------------------------------------------
|
||||
MiscTests.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
MiscTests.cpp:<line number>:
|
||||
PASSED:
|
||||
REQUIRE( encode( "[\x01]" ) == "[]" )
|
||||
with expansion:
|
||||
"[]" == "[]"
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
XmlEncode
|
||||
string with control char (x7F)
|
||||
-------------------------------------------------------------------------------
|
||||
MiscTests.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
MiscTests.cpp:<line number>:
|
||||
PASSED:
|
||||
REQUIRE( encode( "[\x7F]" ) == "[]" )
|
||||
with expansion:
|
||||
"[]" == "[]"
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
Process can be configured on command line
|
||||
default - no arguments
|
||||
@ -8004,6 +8126,6 @@ with expansion:
|
||||
true
|
||||
|
||||
===============================================================================
|
||||
test cases: 157 | 101 passed | 55 failed | 1 failed as expected
|
||||
assertions: 793 | 680 passed | 100 failed | 13 failed as expected
|
||||
test cases: 158 | 102 passed | 55 failed | 1 failed as expected
|
||||
assertions: 803 | 690 passed | 100 failed | 13 failed as expected
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
<testsuites>
|
||||
<testsuite name="all tests" errors="12" failures="88" tests="793" hostname="tbd" time="{duration}" timestamp="tbd">
|
||||
<testsuite name="all tests" errors="12" failures="88" tests="803" hostname="tbd" time="{duration}" timestamp="tbd">
|
||||
<testcase classname="global" name="toString(enum)" time="{duration}"/>
|
||||
<testcase classname="global" name="toString(enum w/operator<<)" time="{duration}"/>
|
||||
<testcase classname="global" name="toString(enum class)" time="{duration}"/>
|
||||
@ -463,6 +463,14 @@ MiscTests.cpp:<line number>
|
||||
<testcase classname="global" name="toString on const wchar_t pointer returns the string contents" time="{duration}"/>
|
||||
<testcase classname="global" name="toString on wchar_t const pointer returns the string contents" time="{duration}"/>
|
||||
<testcase classname="global" name="toString on wchar_t returns the string contents" time="{duration}"/>
|
||||
<testcase classname="XmlEncode" name="normal string" time="{duration}"/>
|
||||
<testcase classname="XmlEncode" name="empty string" time="{duration}"/>
|
||||
<testcase classname="XmlEncode" name="string with ampersand" 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 quotes" time="{duration}"/>
|
||||
<testcase classname="XmlEncode" name="string with control char (1)" time="{duration}"/>
|
||||
<testcase classname="XmlEncode" name="string with control char (x7F)" time="{duration}"/>
|
||||
<testcase classname="Process can be configured on command line" name="default - no arguments" time="{duration}"/>
|
||||
<testcase classname="Process can be configured on command line" name="test lists/1 test" time="{duration}"/>
|
||||
<testcase classname="Process can be configured on command line" name="test lists/Specify one test case exclusion using exclude:" time="{duration}"/>
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -7,6 +7,7 @@
|
||||
*/
|
||||
|
||||
#include "catch.hpp"
|
||||
#include "catch_xmlwriter.hpp"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
@ -381,6 +382,42 @@ TEST_CASE( "toString on wchar_t returns the string contents", "[toString]" ) {
|
||||
CHECK( result == "\"wide load\"" );
|
||||
}
|
||||
|
||||
inline std::string encode( std::string const& str, Catch::XmlEncode::ForWhat forWhat = Catch::XmlEncode::ForTextNodes ) {
|
||||
std::ostringstream oss;
|
||||
oss << Catch::XmlEncode( str, forWhat );
|
||||
return oss.str();
|
||||
}
|
||||
|
||||
TEST_CASE( "XmlEncode" ) {
|
||||
SECTION( "normal string" ) {
|
||||
REQUIRE( encode( "normal string" ) == "normal string" );
|
||||
}
|
||||
SECTION( "empty string" ) {
|
||||
REQUIRE( encode( "" ) == "" );
|
||||
}
|
||||
SECTION( "string with ampersand" ) {
|
||||
REQUIRE( encode( "smith & jones" ) == "smith & jones" );
|
||||
}
|
||||
SECTION( "string with less-than" ) {
|
||||
REQUIRE( encode( "smith < jones" ) == "smith < jones" );
|
||||
}
|
||||
SECTION( "string with greater-than" ) {
|
||||
REQUIRE( encode( "smith > jones" ) == "smith > jones" );
|
||||
REQUIRE( encode( "smith ]]> jones" ) == "smith ]]> jones" );
|
||||
}
|
||||
SECTION( "string with quotes" ) {
|
||||
std::string stringWithQuotes = "don't \"quote\" me on that";
|
||||
REQUIRE( encode( stringWithQuotes ) == stringWithQuotes );
|
||||
REQUIRE( encode( stringWithQuotes, Catch::XmlEncode::ForAttributes ) == "don't "quote" me on that" );
|
||||
}
|
||||
SECTION( "string with control char (1)" ) {
|
||||
REQUIRE( encode( "[\x01]" ) == "[]" );
|
||||
}
|
||||
SECTION( "string with control char (x7F)" ) {
|
||||
REQUIRE( encode( "[\x7F]" ) == "[]" );
|
||||
}
|
||||
}
|
||||
|
||||
//TEST_CASE( "Divide by Zero signal handler", "[.][sig]" ) {
|
||||
// int i = 0;
|
||||
// int x = 10/i; // This should cause the signal to fire
|
||||
|
Loading…
Reference in New Issue
Block a user