mirror of
https://github.com/ceph/ceph
synced 2025-01-03 09:32:43 +00:00
common: Formatter: add TableFormatter class
For more human readable and shell parsable output. Signed-off-by: Andreas Peters <andreas.joachim.peters@cern.ch>
This commit is contained in:
parent
1e444e9103
commit
e797dcf6e9
@ -26,6 +26,11 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <set>
|
||||
#include <boost/format.hpp>
|
||||
|
||||
|
||||
|
||||
// -----------------------
|
||||
namespace ceph {
|
||||
@ -77,6 +82,10 @@ new_formatter(const std::string &type)
|
||||
return new XMLFormatter(false);
|
||||
else if (mytype == "xml-pretty")
|
||||
return new XMLFormatter(true);
|
||||
else if (mytype == "table")
|
||||
return new TableFormatter();
|
||||
else if (mytype == "table-kv")
|
||||
return new TableFormatter(true);
|
||||
else
|
||||
return (Formatter *)NULL;
|
||||
}
|
||||
@ -294,7 +303,7 @@ void JSONFormatter::write_raw_data(const char *data)
|
||||
m_ss << data;
|
||||
}
|
||||
|
||||
const char *XMLFormatter::XML_1_DTD =
|
||||
const char *XMLFormatter::XML_1_DTD =
|
||||
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>";
|
||||
|
||||
XMLFormatter::XMLFormatter(bool pretty)
|
||||
@ -509,4 +518,347 @@ std::string XMLFormatter::escape_xml_str(const char *str)
|
||||
return std::string(&escaped[0]);
|
||||
}
|
||||
|
||||
TableFormatter::TableFormatter(bool keyval) : m_keyval(keyval)
|
||||
{
|
||||
reset();
|
||||
}
|
||||
|
||||
void TableFormatter::flush(std::ostream& os)
|
||||
{
|
||||
finish_pending_string();
|
||||
std::vector<size_t> column_size = m_column_size;
|
||||
std::vector<std::string> column_name = m_column_name;
|
||||
|
||||
std::set<int> need_header_set;
|
||||
|
||||
// auto-sizing columns
|
||||
for (size_t i=0; i< m_vec.size(); i++) {
|
||||
for (size_t j=0; j< m_vec[i].size(); j++) {
|
||||
column_size.resize(m_vec[i].size());
|
||||
column_name.resize(m_vec[i].size());
|
||||
if (i>0) {
|
||||
if (m_vec[i-1][j] != m_vec[i][j]) {
|
||||
// changing row labels require to show the header
|
||||
need_header_set.insert(i);
|
||||
column_name[i] = m_vec[i][j].first;
|
||||
}
|
||||
} else {
|
||||
column_name[i] = m_vec[i][j].first;
|
||||
}
|
||||
|
||||
if (m_vec[i][j].second.length()> column_size[j])
|
||||
column_size[j]=m_vec[i][j].second.length();
|
||||
if (m_vec[i][j].first.length()> column_size[j])
|
||||
column_size[j]=m_vec[i][j].first.length();
|
||||
}
|
||||
}
|
||||
|
||||
bool need_header=false;
|
||||
if ( (column_size.size() == m_column_size.size() ) ) {
|
||||
for (size_t i=0; i<column_size.size(); i++) {
|
||||
if (column_size[i] != m_column_size[i]) {
|
||||
need_header = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
need_header = true;
|
||||
}
|
||||
|
||||
if (need_header) {
|
||||
// first row always needs a header if there wasn't one before
|
||||
need_header_set.insert(0);
|
||||
}
|
||||
|
||||
m_column_size = column_size;
|
||||
for (size_t i=0; i< m_vec.size(); i++) {
|
||||
if (i==0) {
|
||||
if (need_header_set.count(i)) {
|
||||
// print the header
|
||||
if (!m_keyval) {
|
||||
os << "+";
|
||||
for (size_t j=0; j< m_vec[i].size(); j++) {
|
||||
for (size_t v=0; v< m_column_size[j]+3; v++)
|
||||
os << "-";
|
||||
os << "+";
|
||||
}
|
||||
os << "\n";
|
||||
os << "|";
|
||||
|
||||
for (size_t j=0; j< m_vec[i].size(); j++) {
|
||||
os << " ";
|
||||
std::stringstream fs;
|
||||
fs << boost::format ("%%-%is") % (m_column_size[j]+2);
|
||||
os << boost::format (fs.str()) % m_vec[i][j].first;
|
||||
os << "|";
|
||||
}
|
||||
os << "\n";
|
||||
os << "+";
|
||||
for (size_t j=0; j< m_vec[i].size(); j++) {
|
||||
for (size_t v=0; v< m_column_size[j]+3;v++)
|
||||
os << "-";
|
||||
os << "+";
|
||||
}
|
||||
os << "\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
// print body
|
||||
if (!m_keyval)
|
||||
os << "|";
|
||||
for (size_t j=0; j< m_vec[i].size(); j++) {
|
||||
if (!m_keyval)
|
||||
os << " ";
|
||||
std::stringstream fs;
|
||||
|
||||
if (m_keyval) {
|
||||
os << "key::";
|
||||
os << m_vec[i][j].first;
|
||||
os << "=";
|
||||
os << "\"";
|
||||
os << m_vec[i][j].second;
|
||||
os << "\" ";
|
||||
} else {
|
||||
fs << boost::format ("%%-%is") % (m_column_size[j]+2);
|
||||
os << boost::format (fs.str()) % m_vec[i][j].second;
|
||||
os << "|";
|
||||
}
|
||||
}
|
||||
|
||||
os << "\n";
|
||||
if (!m_keyval) {
|
||||
if ( i == (m_vec.size()-1) ) {
|
||||
// print trailer
|
||||
os << "+";
|
||||
for (size_t j=0; j< m_vec[i].size(); j++) {
|
||||
for (size_t v=0; v< m_column_size[j]+3;v++)
|
||||
os << "-";
|
||||
os << "+";
|
||||
}
|
||||
os << "\n";
|
||||
}
|
||||
}
|
||||
m_vec[i].clear();
|
||||
}
|
||||
m_vec.clear();
|
||||
}
|
||||
|
||||
void TableFormatter::reset()
|
||||
{
|
||||
m_ss.clear();
|
||||
m_ss.str("");
|
||||
m_section_cnt.clear();
|
||||
m_column_size.clear();
|
||||
m_section_open = 0;
|
||||
}
|
||||
|
||||
void TableFormatter::open_object_section(const char *name)
|
||||
{
|
||||
open_section_in_ns(name, NULL, NULL);
|
||||
}
|
||||
|
||||
void TableFormatter::open_object_section_with_attrs(const char *name, const FormatterAttrs& attrs)
|
||||
{
|
||||
open_section_in_ns(name, NULL, NULL);
|
||||
}
|
||||
|
||||
void TableFormatter::open_object_section_in_ns(const char *name, const char *ns)
|
||||
{
|
||||
open_section_in_ns(name, NULL, NULL);
|
||||
}
|
||||
|
||||
void TableFormatter::open_array_section(const char *name)
|
||||
{
|
||||
open_section_in_ns(name, NULL, NULL);
|
||||
}
|
||||
|
||||
void TableFormatter::open_array_section_with_attrs(const char *name, const FormatterAttrs& attrs)
|
||||
{
|
||||
open_section_in_ns(name, NULL, NULL);
|
||||
}
|
||||
|
||||
void TableFormatter::open_array_section_in_ns(const char *name, const char *ns)
|
||||
{
|
||||
open_section_in_ns(name, NULL, NULL);
|
||||
}
|
||||
|
||||
void TableFormatter::open_section_in_ns(const char *name, const char *ns, const FormatterAttrs *attrs)
|
||||
{
|
||||
m_section.push_back(name);
|
||||
m_section_open++;
|
||||
}
|
||||
|
||||
void TableFormatter::close_section()
|
||||
{
|
||||
//
|
||||
m_section_open--;
|
||||
if (m_section.size()) {
|
||||
m_section_cnt[m_section.back()]=0;
|
||||
m_section.pop_back();
|
||||
}
|
||||
}
|
||||
|
||||
size_t TableFormatter::m_vec_index(const char *name)
|
||||
{
|
||||
std::string key(name);
|
||||
|
||||
size_t i = m_vec.size();
|
||||
if (i)
|
||||
i--;
|
||||
|
||||
// make sure there are vectors to push back key/val pairs
|
||||
if (!m_vec.size())
|
||||
m_vec.resize(1);
|
||||
|
||||
if (m_vec.size()) {
|
||||
if (m_vec[i].size()) {
|
||||
if (m_vec[i][0].first == key) {
|
||||
// start a new column if a key is repeated
|
||||
m_vec.resize(m_vec.size()+1);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
std::string TableFormatter::get_section_name(const char* name)
|
||||
{
|
||||
std::string t_name=name;
|
||||
for (size_t i=0; i< m_section.size(); i++)
|
||||
{
|
||||
t_name.insert(0,":");
|
||||
t_name.insert(0,m_section[i]);
|
||||
}
|
||||
if (m_section_open) {
|
||||
std::stringstream lss;
|
||||
lss << t_name;
|
||||
lss << "[";
|
||||
lss << m_section_cnt[t_name]++;
|
||||
lss << "]";
|
||||
return lss.str();
|
||||
} else {
|
||||
return t_name;
|
||||
}
|
||||
}
|
||||
|
||||
void TableFormatter::dump_unsigned(const char *name, uint64_t u)
|
||||
{
|
||||
finish_pending_string();
|
||||
size_t i = m_vec_index(name);
|
||||
m_ss << u;
|
||||
m_vec[i].push_back(std::make_pair(get_section_name(name),m_ss.str()));
|
||||
m_ss.clear();
|
||||
m_ss.str("");
|
||||
}
|
||||
|
||||
void TableFormatter::dump_int(const char *name, int64_t u)
|
||||
{
|
||||
finish_pending_string();
|
||||
size_t i = m_vec_index(name);
|
||||
m_ss << u;
|
||||
m_vec[i].push_back(std::make_pair(get_section_name(name),m_ss.str()));
|
||||
m_ss.clear();
|
||||
m_ss.str("");
|
||||
}
|
||||
|
||||
void TableFormatter::dump_float(const char *name, double d)
|
||||
{
|
||||
finish_pending_string();
|
||||
size_t i = m_vec_index(name);
|
||||
m_ss << d;
|
||||
|
||||
m_vec[i].push_back(std::make_pair(get_section_name(name),m_ss.str()));
|
||||
m_ss.clear();
|
||||
m_ss.str("");
|
||||
}
|
||||
|
||||
void TableFormatter::dump_string(const char *name, std::string s)
|
||||
{
|
||||
finish_pending_string();
|
||||
size_t i = m_vec_index(name);
|
||||
m_ss << s;
|
||||
|
||||
m_vec[i].push_back(std::make_pair(get_section_name(name),m_ss.str()));
|
||||
m_ss.clear();
|
||||
m_ss.str("");
|
||||
}
|
||||
|
||||
void TableFormatter::dump_string_with_attrs(const char *name, std::string s, const FormatterAttrs& attrs)
|
||||
{
|
||||
finish_pending_string();
|
||||
size_t i = m_vec_index(name);
|
||||
|
||||
std::string attrs_str;
|
||||
get_attrs_str(&attrs, attrs_str);
|
||||
m_ss << attrs_str << s;
|
||||
|
||||
m_vec[i].push_back(std::make_pair(get_section_name(name),m_ss.str()));
|
||||
m_ss.clear();
|
||||
m_ss.str("");
|
||||
}
|
||||
|
||||
|
||||
void TableFormatter::dump_format_va(const char* name, const char *ns, bool quoted, const char *fmt, va_list ap)
|
||||
{
|
||||
finish_pending_string();
|
||||
char buf[LARGE_SIZE];
|
||||
vsnprintf(buf, LARGE_SIZE, fmt, ap);
|
||||
|
||||
size_t i = m_vec_index(name);
|
||||
if (ns) {
|
||||
m_ss << ns << "." << buf;
|
||||
} else
|
||||
m_ss << buf;
|
||||
|
||||
m_vec[i].push_back(std::make_pair(get_section_name(name),m_ss.str()));
|
||||
m_ss.clear();
|
||||
m_ss.str("");
|
||||
}
|
||||
|
||||
std::ostream& TableFormatter::dump_stream(const char *name)
|
||||
{
|
||||
finish_pending_string();
|
||||
// we don't support this
|
||||
m_pending_name=name;
|
||||
return m_ss;
|
||||
}
|
||||
|
||||
int TableFormatter::get_len() const
|
||||
{
|
||||
// we don't know the size until flush is called
|
||||
return 0;
|
||||
}
|
||||
|
||||
void TableFormatter::write_raw_data(const char *data)
|
||||
{
|
||||
// not supported
|
||||
}
|
||||
|
||||
void TableFormatter::get_attrs_str(const FormatterAttrs *attrs, std::string& attrs_str)
|
||||
{
|
||||
std::stringstream attrs_ss;
|
||||
|
||||
for (std::list<std::pair<std::string, std::string> >::const_iterator iter = attrs->attrs.begin();
|
||||
iter != attrs->attrs.end(); ++iter) {
|
||||
std::pair<std::string, std::string> p = *iter;
|
||||
attrs_ss << " " << p.first << "=" << "\"" << p.second << "\"";
|
||||
}
|
||||
|
||||
attrs_str = attrs_ss.str();
|
||||
}
|
||||
|
||||
void TableFormatter::finish_pending_string()
|
||||
{
|
||||
if (m_pending_name.length()) {
|
||||
std::string ss = m_ss.str();
|
||||
m_ss.clear();
|
||||
m_ss.str("");
|
||||
std::string pending_name=m_pending_name;
|
||||
m_pending_name="";
|
||||
dump_string(pending_name.c_str(),ss);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -6,10 +6,12 @@
|
||||
#include <deque>
|
||||
#include <iostream>
|
||||
#include <list>
|
||||
#include <vector>
|
||||
#include <ostream>
|
||||
#include <sstream>
|
||||
#include <stdarg.h>
|
||||
#include <string>
|
||||
#include <map>
|
||||
|
||||
#include "include/buffer.h"
|
||||
|
||||
@ -95,7 +97,7 @@ class JSONFormatter : public Formatter {
|
||||
bool is_array;
|
||||
json_formatter_stack_entry_d() : size(0), is_array(false) {}
|
||||
};
|
||||
|
||||
|
||||
bool m_pretty;
|
||||
void open_section(const char *name, bool is_array);
|
||||
void print_quoted_string(const char *s);
|
||||
@ -146,5 +148,50 @@ class XMLFormatter : public Formatter {
|
||||
std::string m_pending_string_name;
|
||||
};
|
||||
|
||||
class TableFormatter : public Formatter {
|
||||
public:
|
||||
TableFormatter(bool keyval=false);
|
||||
|
||||
void flush(std::ostream& os);
|
||||
void reset();
|
||||
virtual void open_array_section(const char *name);
|
||||
void open_array_section_in_ns(const char *name, const char *ns);
|
||||
void open_object_section(const char *name);
|
||||
void open_object_section_in_ns(const char *name, const char *ns);
|
||||
|
||||
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 close_section();
|
||||
void dump_unsigned(const char *name, uint64_t u);
|
||||
void dump_int(const char *name, int64_t u);
|
||||
void dump_float(const char *name, double d);
|
||||
void dump_string(const char *name, std::string s);
|
||||
void dump_format_va(const char *name, const char *ns, bool quoted, const char *fmt, va_list ap);
|
||||
void dump_string_with_attrs(const char *name, std::string s, const FormatterAttrs& attrs);
|
||||
std::ostream& dump_stream(const char *name);
|
||||
|
||||
int get_len() const;
|
||||
void write_raw_data(const char *data);
|
||||
void get_attrs_str(const FormatterAttrs *attrs, std::string& attrs_str);
|
||||
|
||||
private:
|
||||
void open_section_in_ns(const char *name, const char *ns, const FormatterAttrs *attrs);
|
||||
std::vector< std::vector<std::pair<std::string,std::string> > > m_vec;
|
||||
std::stringstream m_ss;
|
||||
size_t m_vec_index(const char* name);
|
||||
std::string get_section_name(const char* name);
|
||||
void finish_pending_string();
|
||||
std::string m_pending_name;
|
||||
bool m_keyval;
|
||||
|
||||
int m_section_open;
|
||||
std::vector< std::string > m_section;
|
||||
std::map<std::string,int> m_section_cnt;
|
||||
std::vector<size_t> m_column_size;
|
||||
std::vector< std::string > m_column_name;
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
#endif
|
||||
|
@ -652,6 +652,10 @@ unittest_msgr_LDADD = $(UNITTEST_LDADD) $(CEPH_GLOBAL)
|
||||
unittest_msgr_CXXFLAGS = $(UNITTEST_CXXFLAGS)
|
||||
check_PROGRAMS += unittest_msgr
|
||||
|
||||
unittest_tableformatter_SOURCES = test/common/test_tableformatter.cc
|
||||
unittest_tableformatter_CXXFLAGS = $(UNITTEST_CXXFLAGS)
|
||||
unittest_tableformatter_LDADD = $(UNITTEST_LDADD) $(CEPH_GLOBAL)
|
||||
check_PROGRAMS += unittest_tableformatter
|
||||
|
||||
check_SCRIPTS += test/pybind/test_ceph_argparse.py
|
||||
|
||||
|
236
src/test/common/test_tableformatter.cc
Normal file
236
src/test/common/test_tableformatter.cc
Normal file
@ -0,0 +1,236 @@
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
#include "common/Formatter.h"
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
|
||||
TEST(tableformatter, singleline) {
|
||||
std::stringstream sout;
|
||||
TableFormatter formatter;
|
||||
formatter.dump_int("integer",10);
|
||||
formatter.dump_float("float",10.0);
|
||||
formatter.dump_string("string","string");
|
||||
formatter.flush(sout);
|
||||
|
||||
std::string cmp = ""
|
||||
"+----------+--------+---------+\n"
|
||||
"| integer | float | string |\n"
|
||||
"+----------+--------+---------+\n"
|
||||
"| 10 | 10 | string |\n"
|
||||
"+----------+--------+---------+\n";
|
||||
EXPECT_EQ(cmp,sout.str());
|
||||
}
|
||||
|
||||
TEST(tableformatter, multiline) {
|
||||
std::stringstream sout;
|
||||
TableFormatter 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 = ""
|
||||
"+----------+--------+---------+\n"
|
||||
"| integer | float | string |\n"
|
||||
"+----------+--------+---------+\n"
|
||||
"| 10 | 10 | string |\n"
|
||||
"| 20 | 20 | string |\n"
|
||||
"+----------+--------+---------+\n";
|
||||
|
||||
formatter.flush(sout);
|
||||
EXPECT_EQ(cmp,sout.str());
|
||||
}
|
||||
|
||||
TEST(tableformatter, multiflush) {
|
||||
std::stringstream sout1;
|
||||
std::stringstream sout2;
|
||||
TableFormatter formatter;
|
||||
formatter.dump_int("integer",10);
|
||||
formatter.dump_float("float",10.0);
|
||||
formatter.dump_string("string","string");
|
||||
formatter.flush(sout1);
|
||||
|
||||
std::string cmp = ""
|
||||
"+----------+--------+---------+\n"
|
||||
"| integer | float | string |\n"
|
||||
"+----------+--------+---------+\n"
|
||||
"| 10 | 10 | string |\n"
|
||||
"+----------+--------+---------+\n";
|
||||
|
||||
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 = ""
|
||||
"| 20 | 20 | string |\n"
|
||||
"+----------+--------+---------+\n";
|
||||
|
||||
EXPECT_EQ(cmp,sout2.str());
|
||||
|
||||
}
|
||||
|
||||
TEST(tableformatter, multireset) {
|
||||
std::stringstream sout;
|
||||
TableFormatter formatter;
|
||||
formatter.dump_int("integer",10);
|
||||
formatter.dump_float("float",10.0);
|
||||
formatter.dump_string("string","string");
|
||||
formatter.flush(sout);
|
||||
formatter.reset();
|
||||
formatter.dump_int("integer",20);
|
||||
formatter.dump_float("float",20.0);
|
||||
formatter.dump_string("string","string");
|
||||
formatter.flush(sout);
|
||||
|
||||
std::string cmp = ""
|
||||
"+----------+--------+---------+\n"
|
||||
"| integer | float | string |\n"
|
||||
"+----------+--------+---------+\n"
|
||||
"| 10 | 10 | string |\n"
|
||||
"+----------+--------+---------+\n"
|
||||
"+----------+--------+---------+\n"
|
||||
"| integer | float | string |\n"
|
||||
"+----------+--------+---------+\n"
|
||||
"| 20 | 20 | string |\n"
|
||||
"+----------+--------+---------+\n";
|
||||
|
||||
EXPECT_EQ(cmp,sout.str());
|
||||
}
|
||||
|
||||
TEST(tableformatter, changingheaderlength) {
|
||||
std::stringstream sout;
|
||||
TableFormatter formatter;
|
||||
formatter.dump_int("integer",10);
|
||||
formatter.dump_float("float",10.0);
|
||||
formatter.dump_string("string","string");
|
||||
formatter.flush(sout);
|
||||
formatter.dump_int("integer",20);
|
||||
formatter.dump_float("float",20.0);
|
||||
formatter.dump_string("string","stringstring");
|
||||
formatter.flush(sout);
|
||||
|
||||
std::string cmp = ""
|
||||
"+----------+--------+---------+\n"
|
||||
"| integer | float | string |\n"
|
||||
"+----------+--------+---------+\n"
|
||||
"| 10 | 10 | string |\n"
|
||||
"+----------+--------+---------+\n"
|
||||
"+----------+--------+---------------+\n"
|
||||
"| integer | float | string |\n"
|
||||
"+----------+--------+---------------+\n"
|
||||
"| 20 | 20 | stringstring |\n"
|
||||
"+----------+--------+---------------+\n";
|
||||
|
||||
EXPECT_EQ(cmp,sout.str());
|
||||
}
|
||||
|
||||
TEST(tableformatter, changingheader) {
|
||||
std::stringstream sout;
|
||||
TableFormatter formatter;
|
||||
formatter.dump_int("integer",10);
|
||||
formatter.dump_float("float",10.0);
|
||||
formatter.dump_string("string","string");
|
||||
formatter.flush(sout);
|
||||
formatter.dump_int("longinteger",20);
|
||||
formatter.dump_float("double",20.0);
|
||||
formatter.dump_string("char*","stringstring");
|
||||
formatter.flush(sout);
|
||||
|
||||
std::string cmp = ""
|
||||
"+----------+--------+---------+\n"
|
||||
"| integer | float | string |\n"
|
||||
"+----------+--------+---------+\n"
|
||||
"| 10 | 10 | string |\n"
|
||||
"+----------+--------+---------+\n"
|
||||
"+--------------+---------+---------------+\n"
|
||||
"| longinteger | double | char* |\n"
|
||||
"+--------------+---------+---------------+\n"
|
||||
"| 20 | 20 | stringstring |\n"
|
||||
"+--------------+---------+---------------+\n";
|
||||
|
||||
EXPECT_EQ(cmp,sout.str());
|
||||
}
|
||||
|
||||
TEST(tableformatter, extendingheader) {
|
||||
std::stringstream sout;
|
||||
TableFormatter formatter;
|
||||
formatter.dump_int("integer",10);
|
||||
formatter.dump_float("float",10.0);
|
||||
formatter.dump_string("string","string");
|
||||
formatter.flush(sout);
|
||||
formatter.dump_int("integer",20);
|
||||
formatter.dump_float("float",20.0);
|
||||
formatter.dump_string("string","string");
|
||||
formatter.dump_string("char*","abcde");
|
||||
formatter.flush(sout);
|
||||
|
||||
std::string cmp = ""
|
||||
"+----------+--------+---------+\n"
|
||||
"| integer | float | string |\n"
|
||||
"+----------+--------+---------+\n"
|
||||
"| 10 | 10 | string |\n"
|
||||
"+----------+--------+---------+\n"
|
||||
"+----------+--------+---------+--------+\n"
|
||||
"| integer | float | string | char* |\n"
|
||||
"+----------+--------+---------+--------+\n"
|
||||
"| 20 | 20 | string | abcde |\n"
|
||||
"+----------+--------+---------+--------+\n";
|
||||
|
||||
EXPECT_EQ(cmp,sout.str());
|
||||
}
|
||||
|
||||
TEST(tableformatter, stream) {
|
||||
std::stringstream sout;
|
||||
TableFormatter* formatter = (TableFormatter*) new_formatter("table");
|
||||
formatter->dump_stream("integer") << 10;
|
||||
formatter->dump_stream("float") << 10.0;
|
||||
formatter->dump_stream("string") << "string";
|
||||
formatter->flush(sout);
|
||||
delete formatter;
|
||||
|
||||
std::string cmp = ""
|
||||
"+----------+--------+---------+\n"
|
||||
"| integer | float | string |\n"
|
||||
"+----------+--------+---------+\n"
|
||||
"| 10 | 10 | string |\n"
|
||||
"+----------+--------+---------+\n";
|
||||
|
||||
EXPECT_EQ(cmp,sout.str());
|
||||
}
|
||||
|
||||
TEST(tableformatter, multiline_keyval) {
|
||||
std::stringstream sout;
|
||||
TableFormatter* formatter = (TableFormatter*) new_formatter("table-kv");
|
||||
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");
|
||||
formatter->flush(sout);
|
||||
delete formatter;
|
||||
|
||||
std::string cmp = ""
|
||||
"key::integer=\"10\" key::float=\"10\" key::string=\"string\" \n"
|
||||
"key::integer=\"20\" key::float=\"20\" key::string=\"string\" \n";
|
||||
|
||||
EXPECT_EQ(cmp,sout.str());
|
||||
}
|
||||
|
||||
/*
|
||||
* Local Variables:
|
||||
* compile-command: "cd ../.. ; make -j4 &&
|
||||
* make unittest_tableformatter &&
|
||||
* ./unittest_tableformatter
|
||||
* '
|
||||
* End:
|
||||
*/
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user