common/xmlformatter: turn on underscored by default, add unittest

Signed-off-by: liuchang0812 <liuchang0812@gmail.com>
This commit is contained in:
liuchang0812 2017-01-13 13:49:41 +08:00
parent 5b97cce360
commit a7efe6277a
4 changed files with 212 additions and 35 deletions

View File

@ -34,10 +34,6 @@
#include <boost/format.hpp>
static char tolower_underscore(const char b) {
return ' ' == b ? '_' : std::tolower(b);
}
// -----------------------
namespace ceph {
@ -326,9 +322,10 @@ void JSONFormatter::write_raw_data(const char *data)
const char *XMLFormatter::XML_1_DTD =
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>";
XMLFormatter::XMLFormatter(bool pretty, bool lowercased_underscored)
XMLFormatter::XMLFormatter(bool pretty, bool lowercased, bool underscored)
: m_pretty(pretty),
m_lowercased_underscored(lowercased_underscored)
m_lowercased(lowercased),
m_underscored(underscored)
{
reset();
}
@ -410,10 +407,8 @@ void XMLFormatter::close_section()
finish_pending_string();
std::string section = m_sections.back();
if (m_lowercased_underscored) {
std::transform(section.begin(), section.end(), section.begin(),
tolower_underscore);
}
std::transform(section.begin(), section.end(), section.begin(),
[this](char c) { return this->to_lower_underscore(c); });
m_sections.pop_back();
print_spaces();
m_ss << "</" << section << ">";
@ -424,9 +419,9 @@ void XMLFormatter::close_section()
void XMLFormatter::dump_unsigned(const char *name, uint64_t u)
{
std::string e(name);
if (m_lowercased_underscored) {
std::transform(e.begin(), e.end(), e.begin(), tolower_underscore);
}
std::transform(e.begin(), e.end(), e.begin(),
[this](char c) { return this->to_lower_underscore(c); });
print_spaces();
m_ss << "<" << e << ">" << u << "</" << e << ">";
if (m_pretty)
@ -436,9 +431,9 @@ void XMLFormatter::dump_unsigned(const char *name, uint64_t u)
void XMLFormatter::dump_int(const char *name, int64_t u)
{
std::string e(name);
if (m_lowercased_underscored) {
std::transform(e.begin(), e.end(), e.begin(), tolower_underscore);
}
std::transform(e.begin(), e.end(), e.begin(),
[this](char c) { return this->to_lower_underscore(c); });
print_spaces();
m_ss << "<" << e << ">" << u << "</" << e << ">";
if (m_pretty)
@ -448,9 +443,9 @@ void XMLFormatter::dump_int(const char *name, int64_t u)
void XMLFormatter::dump_float(const char *name, double d)
{
std::string e(name);
if (m_lowercased_underscored) {
std::transform(e.begin(), e.end(), e.begin(), tolower_underscore);
}
std::transform(e.begin(), e.end(), e.begin(),
[this](char c) { return this->to_lower_underscore(c); });
print_spaces();
m_ss << "<" << e << ">" << d << "</" << e << ">";
if (m_pretty)
@ -460,9 +455,9 @@ void XMLFormatter::dump_float(const char *name, double d)
void XMLFormatter::dump_string(const char *name, const std::string& s)
{
std::string e(name);
if (m_lowercased_underscored) {
std::transform(e.begin(), e.end(), e.begin(), tolower_underscore);
}
std::transform(e.begin(), e.end(), e.begin(),
[this](char c) { return this->to_lower_underscore(c); });
print_spaces();
m_ss << "<" << e << ">" << escape_xml_str(s.c_str()) << "</" << e << ">";
if (m_pretty)
@ -472,9 +467,9 @@ void XMLFormatter::dump_string(const char *name, const std::string& s)
void XMLFormatter::dump_string_with_attrs(const char *name, const std::string& s, const FormatterAttrs& attrs)
{
std::string e(name);
if (m_lowercased_underscored) {
std::transform(e.begin(), e.end(), e.begin(), tolower_underscore);
}
std::transform(e.begin(), e.end(), e.begin(),
[this](char c) { return this->to_lower_underscore(c); });
std::string attrs_str;
get_attrs_str(&attrs, attrs_str);
print_spaces();
@ -495,11 +490,10 @@ void XMLFormatter::dump_format_va(const char* name, const char *ns, bool quoted,
{
char buf[LARGE_SIZE];
vsnprintf(buf, LARGE_SIZE, fmt, ap);
std::string e(name);
if (m_lowercased_underscored) {
std::transform(e.begin(), e.end(), e.begin(), tolower_underscore);
}
std::transform(e.begin(), e.end(), e.begin(),
[this](char c) { return this->to_lower_underscore(c); });
print_spaces();
if (ns) {
m_ss << "<" << e << " xmlns=\"" << ns << "\">" << buf << "</" << e << ">";
@ -544,9 +538,8 @@ void XMLFormatter::open_section_in_ns(const char *name, const char *ns, const Fo
}
std::string e(name);
if (m_lowercased_underscored) {
std::transform(e.begin(), e.end(), e.begin(), tolower_underscore);
}
std::transform(e.begin(), e.end(), e.begin(),
[this](char c) { return this->to_lower_underscore(c); });
if (ns) {
m_ss << "<" << e << attrs_str << " xmlns=\"" << ns << "\">";
@ -588,6 +581,16 @@ std::string XMLFormatter::escape_xml_str(const char *str)
return std::string(&escaped[0]);
}
char XMLFormatter::to_lower_underscore(char c) const
{
if (m_underscored && c == ' ') {
return '_';
} else if (m_lowercased) {
return std::tolower(c);
}
return c;
}
TableFormatter::TableFormatter(bool keyval) : m_keyval(keyval)
{
reset();

View File

@ -136,7 +136,7 @@ namespace ceph {
class XMLFormatter : public Formatter {
public:
static const char *XML_1_DTD;
XMLFormatter(bool pretty = false, bool lowercased_underscored = false);
XMLFormatter(bool pretty = false, bool lowercased = false, bool underscored = true);
virtual void set_status(int status, const char* status_name) {}
virtual void output_header();
@ -163,17 +163,20 @@ namespace ceph {
void open_array_section_with_attrs(const char *name, const FormatterAttrs& attrs);
void open_object_section_with_attrs(const char *name, const FormatterAttrs& attrs);
void dump_string_with_attrs(const char *name, const std::string& s, const FormatterAttrs& attrs);
protected:
void open_section_in_ns(const char *name, const char *ns, const FormatterAttrs *attrs);
void finish_pending_string();
void print_spaces();
static std::string escape_xml_str(const char *str);
void get_attrs_str(const FormatterAttrs *attrs, std::string& attrs_str);
char to_lower_underscore(char c) const;
std::stringstream m_ss, m_pending_string;
std::deque<std::string> m_sections;
bool m_pretty;
bool m_lowercased_underscored;
const bool m_pretty;
const bool m_lowercased;
const bool m_underscored;
std::string m_pending_string_name;
bool m_header_done;
};

View File

@ -152,6 +152,12 @@ add_executable(unittest_tableformatter
add_ceph_unittest(unittest_tableformatter ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/unittest_tableformatter)
target_link_libraries(unittest_tableformatter global)
add_executable(unittest_xmlformatter
test_xmlformatter.cc
)
add_ceph_unittest(unittest_xmlformatter ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/unittest_xmlformatter)
target_link_libraries(unittest_xmlformatter ceph-common)
# unittest_bit_vector
add_executable(unittest_bit_vector
test_bit_vector.cc

View File

@ -0,0 +1,165 @@
#include "gtest/gtest.h"
#include "common/Formatter.h"
#include <sstream>
#include <string>
using namespace ceph;
TEST(xmlformatter, oneline)
{
std::stringstream sout;
XMLFormatter formatter;
formatter.dump_int("integer", 10);
formatter.dump_float("float", 10.0);
formatter.dump_string("string", "string");
formatter.flush(sout);
std::string cmp = "<integer>10</integer><float>10</float><string>string</string>";
EXPECT_EQ(cmp, sout.str());
}
TEST(xmlformatter, multiline)
{
std::stringstream sout;
XMLFormatter formatter;
formatter.dump_int("integer", 10);
formatter.dump_float("float", 10.0);
formatter.dump_string("string", "string");
formatter.dump_int("integer", 20);
formatter.dump_float("float", 20.0);
formatter.dump_string("string", "string");
std::string cmp = ""
"<integer>10</integer><float>10</float><string>string</string>"
"<integer>20</integer><float>20</float><string>string</string>";
formatter.flush(sout);
EXPECT_EQ(cmp, sout.str());
}
TEST(xmlformatter, multiflush)
{
std::stringstream sout1;
std::stringstream sout2;
XMLFormatter formatter;
formatter.dump_int("integer", 10);
formatter.dump_float("float", 10.0);
formatter.dump_string("string", "string");
formatter.flush(sout1);
std::string cmp = ""
"<integer>10</integer>"
"<float>10</float>"
"<string>string</string>";
EXPECT_EQ(cmp, sout1.str());
formatter.dump_int("integer", 20);
formatter.dump_float("float", 20.0);
formatter.dump_string("string", "string");
formatter.flush(sout2);
cmp = ""
"<integer>20</integer>"
"<float>20</float>"
"<string>string</string>";
EXPECT_EQ(cmp, sout2.str());
}
TEST(xmlformatter, pretty)
{
std::stringstream sout;
XMLFormatter formatter(
true, // pretty
false, // lowercased
false); // underscored
formatter.open_object_section("xml");
formatter.dump_int("Integer", 10);
formatter.dump_float("Float", 10.0);
formatter.dump_string("String", "String");
formatter.close_section();
formatter.flush(sout);
std::string cmp = ""
"<xml>\n"
" <Integer>10</Integer>\n"
" <Float>10</Float>\n"
" <String>String</String>\n"
"</xml>\n\n";
EXPECT_EQ(cmp, sout.str());
}
TEST(xmlformatter, lowercased)
{
std::stringstream sout;
XMLFormatter formatter(
false, // pretty
true, // lowercased
false); // underscored
formatter.dump_int("Integer", 10);
formatter.dump_float("Float", 10.0);
formatter.dump_string("String", "String");
formatter.flush(sout);
std::string cmp = ""
"<integer>10</integer>"
"<float>10</float>"
"<string>String</string>";
EXPECT_EQ(cmp, sout.str());
}
TEST(xmlformatter, underscored)
{
std::stringstream sout;
XMLFormatter formatter(
false, // pretty
false, // lowercased
true); // underscored
formatter.dump_int("Integer Item", 10);
formatter.dump_float("Float Item", 10.0);
formatter.dump_string("String Item", "String");
formatter.flush(sout);
std::string cmp = ""
"<Integer_Item>10</Integer_Item>"
"<Float_Item>10</Float_Item>"
"<String_Item>String</String_Item>";
EXPECT_EQ(cmp, sout.str());
}
TEST(xmlformatter, lowercased_underscored)
{
std::stringstream sout;
XMLFormatter formatter(
false, // pretty
true, // lowercased
true); // underscored
formatter.dump_int("Integer Item", 10);
formatter.dump_float("Float Item", 10.0);
formatter.dump_string("String Item", "String");
formatter.flush(sout);
std::string cmp = ""
"<integer_item>10</integer_item>"
"<float_item>10</float_item>"
"<string_item>String</string_item>";
EXPECT_EQ(cmp, sout.str());
}
TEST(xmlformatter, pretty_lowercased_underscored)
{
std::stringstream sout;
XMLFormatter formatter(
true, // pretty
true, // lowercased
true); // underscored
formatter.dump_int("Integer Item", 10);
formatter.dump_float("Float Item", 10.0);
formatter.dump_string("String Item", "String");
formatter.flush(sout);
std::string cmp = ""
"<integer_item>10</integer_item>\n"
"<float_item>10</float_item>\n"
"<string_item>String</string_item>\n\n";
EXPECT_EQ(cmp, sout.str());
}