keep refactoring serialization code, updating tests

This commit is contained in:
Thomas Fussell 2015-10-29 23:16:31 -04:00
parent 75ec0f8eee
commit 84e9dd099e
8 changed files with 212 additions and 113 deletions

View File

@ -53,14 +53,14 @@ public:
xml_document write_properties_app() const;
xml_document write_properties_core() const;
private:
using string_pair = std::pair<std::string, std::string>;
std::vector<string_pair> read_sheets(zip_file &archive);
std::vector<string_pair> detect_worksheets(zip_file &archive);
std::vector<string_pair> read_sheets();
std::vector<string_pair> detect_worksheets();
bool write_named_ranges(xml_node &named_ranges_node);
private:
workbook &wb_;
};

View File

@ -147,7 +147,7 @@ std::string workbook_serializer::determine_document_type(const manifest &manifes
/// workbook has a list of titles and relIds but no paths
/// workbook_rels has a list of relIds and paths but no titles
/// </summary>
std::vector<std::pair<std::string, std::string>> workbook_serializer::detect_worksheets(zip_file &archive)
std::vector<string_pair> workbook_serializer::detect_worksheets()
{
static const std::string ValidWorksheet = "application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml";
@ -164,7 +164,7 @@ std::vector<std::pair<std::string, std::string>> workbook_serializer::detect_wor
auto &workbook_relationships = wb_.get_relationships();
std::vector<std::pair<std::string, std::string>> result;
for(const auto &ws : read_sheets(archive))
for(const auto &ws : read_sheets())
{
auto rel = *std::find_if(workbook_relationships.begin(), workbook_relationships.end(), [&](const relationship &r) { return r.get_id() == ws.first; });
auto target = rel.get_target_uri();

View File

@ -1,7 +1,10 @@
#pragma once
#include <sstream>
#include <pugixml.hpp>
#include <xlnt/s11n/xml_document.hpp>
#include <xlnt/s11n/xml_node.hpp>
#include <xlnt/s11n/xml_serializer.hpp>
#include "path_helper.hpp"
@ -28,39 +31,46 @@ public:
operator bool() const { return difference == difference_type::equivalent; }
};
static comparison_result compare_xml(const std::string &expected, const xlnt::xml_document &observed)
{
std::ifstream f(expected);
std::ostringstream s;
f >> s.rdbuf();
auto expected_xml = xlnt::xml_serializer::deserialize(s.str());
return compare_xml(expected_xml.root(), observed.root());
}
static comparison_result compare_xml(const std::string &left_contents, const std::string &right_contents)
{
pugi::xml_document left_doc;
left_doc.load(left_contents.c_str());
pugi::xml_document right_doc;
right_doc.load(right_contents.c_str());
auto left_doc = xlnt::xml_serializer::deserialize(left_contents);
auto right_doc = xlnt::xml_serializer::deserialize(right_contents);
return compare_xml(left_doc.root(), right_doc.root());
}
static comparison_result compare_xml(const pugi::xml_node &left, const pugi::xml_node &right)
static comparison_result compare_xml(const xlnt::xml_node &left, const xlnt::xml_node &right)
{
std::string left_temp = left.name();
std::string right_temp = right.name();
std::string left_temp = left.get_name();
std::string right_temp = right.get_name();
if(left_temp != right_temp)
{
return {difference_type::names_differ, left_temp, right_temp};
}
for(auto left_attribute : left.attributes())
for(auto &left_attribute : left.get_attributes())
{
left_temp = left_attribute.name();
auto right_attribute = right.attribute(left_attribute.name());
left_temp = left_attribute.second;
if(right_attribute == nullptr)
if(!right.has_attribute(left_attribute.first))
{
return {difference_type::missing_attribute, left_temp, "((empty))"};
}
left_temp = left_attribute.value();
right_temp = right_attribute.value();
left_temp = left_attribute.second;
right_temp = right.get_attribute(left_attribute.first);
if(left_temp != right_temp)
{
@ -68,34 +78,35 @@ public:
}
}
if(left.text() != nullptr)
if(left.has_text())
{
left_temp = left.text().as_string();
left_temp = left.get_text();
if(right.text() == nullptr)
if(!right.has_text())
{
return {difference_type::missing_text, left_temp, "((empty))"};
}
right_temp = right.text().as_string();
right_temp = right.get_text();
if(left_temp != right_temp)
{
return {difference_type::text_values_differ, left_temp, right_temp};
}
}
else if(right.text() != nullptr)
else if(right.has_text())
{
right_temp = right.text().as_string();
right_temp = right.get_text();
return {difference_type::text_values_differ, "((empty))", right_temp};
}
auto right_child_iter = right.children().begin();
for(auto left_child : left.children())
{
left_temp = left_child.name();
auto right_child_iter = right.get_children().begin();
if(right_child_iter == right.children().end())
for(auto left_child : left.get_children())
{
left_temp = left_child.get_name();
if(right_child_iter == right.get_children().end())
{
return {difference_type::child_order_differs, left_temp, "((end))"};
}
@ -103,11 +114,6 @@ public:
auto right_child = *right_child_iter;
right_child_iter++;
if(left_child.type() == pugi::xml_node_type::node_cdata || left_child.type() == pugi::xml_node_type::node_pcdata)
{
continue; // ignore text children, these have already been compared
}
auto child_comparison_result = compare_xml(left_child, right_child);
if(!child_comparison_result)
@ -116,38 +122,12 @@ public:
}
}
if(right_child_iter != right.children().end())
if(right_child_iter != right.get_children().end())
{
right_temp = right_child_iter->name();
right_temp = right_child_iter->get_name();
return {difference_type::child_order_differs, "((end))", right_temp};
}
return {difference_type::equivalent, "", ""};
}
static bool EqualsFileContent(const std::string &reference_file, const std::string &observed_content)
{
std::string expected_content;
if(PathHelper::FileExists(reference_file))
{
std::fstream file;
file.open(reference_file);
std::stringstream ss;
ss << file.rdbuf();
expected_content = ss.str();
}
else
{
throw std::runtime_error("file not found");
}
pugi::xml_document doc_observed;
doc_observed.load(observed_content.c_str());
pugi::xml_document doc_expected;
doc_expected.load(expected_content.c_str());
return compare_xml(doc_expected, doc_observed);
}
};

View File

@ -4,6 +4,7 @@
#include <cxxtest/TestSuite.h>
#include <xlnt/s11n/workbook_serializer.hpp>
#include <xlnt/s11n/xml_document.hpp>
#include "helpers/path_helper.hpp"
#include "helpers/helper.hpp"
@ -17,7 +18,9 @@ public:
auto content = archive.read("docProps/core.xml");
xlnt::workbook wb;
xlnt::workbook_serializer serializer(wb);
auto prop = serializer.read_properties_core(content);
xlnt::xml_document xml;
serializer.read_properties_core(xml);
auto &prop = wb.get_properties();
TS_ASSERT_EQUALS(prop.creator, "*.*");
TS_ASSERT_EQUALS(prop.last_modified_by, "Charlie Clark");
TS_ASSERT_EQUALS(prop.created, xlnt::datetime(2010, 4, 9, 20, 43, 12));
@ -32,7 +35,11 @@ public:
const std::vector<std::string> expected_titles = {"Sheet1 - Text", "Sheet2 - Numbers", "Sheet3 - Formulas", "Sheet4 - Dates"};
std::size_t i = 0;
for(auto sheet : xlnt::read_sheets(archive))
xlnt::workbook wb;
xlnt::workbook_serializer serializer(wb);
for(auto sheet : serializer.read_sheets())
{
TS_ASSERT_EQUALS(sheet.second, expected_titles.at(i++));
}
@ -42,7 +49,11 @@ public:
{
xlnt::zip_file archive(PathHelper::GetDataDirectory() + "/genuine/empty_libre.xlsx");
auto content = archive.read("docProps/core.xml");
auto prop = xlnt::read_properties_core(content);
xlnt::workbook wb;
xlnt::workbook_serializer serializer(wb);
xlnt::xml_document xml;
serializer.read_properties_core(xml);
auto &prop = wb.get_properties();
TS_ASSERT_EQUALS(prop.excel_base_date, xlnt::calendar::windows_1900);
}
@ -54,7 +65,11 @@ public:
const std::vector<std::string> expected_titles = {"Sheet1 - Text", "Sheet2 - Numbers", "Sheet3 - Formulas", "Sheet4 - Dates"};
std::size_t i = 0;
for(auto sheet : xlnt::read_sheets(archive))
xlnt::workbook wb;
xlnt::workbook_serializer serializer(wb);
for(auto sheet : serializer.read_sheets())
{
TS_ASSERT_EQUALS(sheet.second, expected_titles.at(i++));
}
@ -62,13 +77,15 @@ public:
void test_write_properties_core()
{
xlnt::document_properties prop;
xlnt::workbook wb;
xlnt::document_properties &prop = wb.get_properties();
prop.creator = "TEST_USER";
prop.last_modified_by = "SOMEBODY";
prop.created = xlnt::datetime(2010, 4, 1, 20, 30, 00);
prop.modified = xlnt::datetime(2010, 4, 5, 14, 5, 30);
auto content = xlnt::write_properties_core(prop);
TS_ASSERT(Helper::EqualsFileContent(PathHelper::GetDataDirectory() + "/writer/expected/core.xml", content));
xlnt::workbook_serializer serializer(wb);
xlnt::xml_document xml = serializer.write_properties_core();
TS_ASSERT(Helper::compare_xml(PathHelper::GetDataDirectory() + "/writer/expected/core.xml", xml));
}
void test_write_properties_app()
@ -76,7 +93,8 @@ public:
xlnt::workbook wb;
wb.create_sheet();
wb.create_sheet();
auto content = xlnt::write_properties_app(wb);
TS_ASSERT(Helper::EqualsFileContent(PathHelper::GetDataDirectory() + "/writer/expected/app.xml", content));
xlnt::workbook_serializer serializer(wb);
xlnt::xml_document xml = serializer.write_properties_app();
TS_ASSERT(Helper::compare_xml(PathHelper::GetDataDirectory() + "/writer/expected/app.xml", xml));
}
};

View File

@ -5,6 +5,12 @@
#include <cxxtest/TestSuite.h>
#include <xlnt/s11n/excel_serializer.hpp>
#include <xlnt/s11n/manifest_serializer.hpp>
#include <xlnt/s11n/workbook_serializer.hpp>
#include <xlnt/s11n/xml_serializer.hpp>
#include <xlnt/workbook/manifest.hpp>
#include "helpers/path_helper.hpp"
class test_read : public CxxTest::TestSuite
@ -13,8 +19,11 @@ public:
xlnt::workbook standard_workbook()
{
xlnt::workbook wb;
auto path = PathHelper::GetDataDirectory("/genuine/empty.xlsx");
return xlnt::excel_reader::load_workbook(path);
wb.load(path);
return wb;
}
void test_read_standard_workbook()
@ -26,14 +35,20 @@ public:
{
auto path = PathHelper::GetDataDirectory("/genuine/empty.xlsx");
std::ifstream fo(path, std::ios::binary);
auto wb = xlnt::excel_reader::load_workbook(path);
TS_ASSERT_DIFFERS(standard_workbook(), nullptr);
xlnt::workbook wb;
xlnt::excel_serializer serializer(wb);
serializer.load_stream_workbook(fo);
TS_ASSERT_DIFFERS(wb, nullptr);
}
void test_read_worksheet()
{
auto wb = standard_workbook();
auto sheet2 = wb.get_sheet_by_name("Sheet2 - Numbers");
TS_ASSERT_DIFFERS(sheet2, nullptr);
TS_ASSERT_EQUALS("This is cell G5", sheet2.get_cell("G5").get_value<std::string>());
TS_ASSERT_EQUALS(18, sheet2.get_cell("D18").get_value<int>());
@ -44,32 +59,55 @@ public:
void test_read_nostring_workbook()
{
auto path = PathHelper::GetDataDirectory("/genuine/empty-no-string.xlsx");
auto wb = xlnt::excel_reader::load_workbook(path);
TS_ASSERT_DIFFERS(standard_workbook(), nullptr);
xlnt::workbook wb;
xlnt::excel_serializer serializer(wb);
serializer.load_workbook(path);
TS_ASSERT_DIFFERS(wb, nullptr);
}
void test_read_empty_file()
{
auto path = PathHelper::GetDataDirectory("/reader/null_file.xlsx");
TS_ASSERT_THROWS(xlnt::excel_reader::load_workbook(path), xlnt::invalid_file_exception);
xlnt::workbook wb;
xlnt::excel_serializer serializer(wb);
TS_ASSERT_THROWS(serializer.load_workbook(path), xlnt::invalid_file_exception);
}
void test_read_empty_archive()
{
auto path = PathHelper::GetDataDirectory("/reader/null_archive.xlsx");
TS_ASSERT_THROWS(xlnt::excel_reader::load_workbook(path), xlnt::invalid_file_exception);
xlnt::workbook wb;
xlnt::excel_serializer serializer(wb);
TS_ASSERT_THROWS(serializer.load_workbook(path), xlnt::invalid_file_exception);
}
void test_read_workbook_with_no_properties()
{
auto path = PathHelper::GetDataDirectory("/genuine/empty_with_no_properties.xlsx");
xlnt::excel_reader::load_workbook(path);
xlnt::workbook wb;
xlnt::excel_serializer serializer(wb);
serializer.load_workbook(path);
}
xlnt::workbook workbook_with_styles()
{
auto path = PathHelper::GetDataDirectory("/genuine/empty-with-styles.xlsx");
return xlnt::excel_reader::load_workbook(path);
xlnt::workbook wb;
xlnt::excel_serializer serializer(wb);
serializer.load_workbook(path);
return wb;
}
void test_read_workbook_with_styles_general()
@ -120,13 +158,25 @@ public:
xlnt::workbook date_mac_1904()
{
auto path = PathHelper::GetDataDirectory("/reader/date_1904.xlsx");
return xlnt::excel_reader::load_workbook(path);
xlnt::workbook wb;
xlnt::excel_serializer serializer(wb);
serializer.load_workbook(path);
return wb;
}
xlnt::workbook date_std_1900()
{
auto path = PathHelper::GetDataDirectory("/reader/date_1900.xlsx");
return xlnt::excel_reader::load_workbook(path);
xlnt::workbook wb;
xlnt::excel_serializer serializer(wb);
serializer.load_workbook(path);
return wb;
}
void test_read_win_base_date()
@ -169,20 +219,25 @@ public:
void test_repair_central_directory()
{
std::string data_a = "foobarbaz" + xlnt::excel_reader::CentralDirectorySignature();
std::string data_a = "foobarbaz" + xlnt::excel_serializer::central_directory_signature();
std::string data_b = "bazbarfoo12345678901234567890";
auto f = xlnt::excel_reader::repair_central_directory(data_a + data_b);
auto f = xlnt::excel_serializer::repair_central_directory(data_a + data_b);
TS_ASSERT_EQUALS(f, data_a + data_b.substr(0, 18));
f = xlnt::excel_reader::repair_central_directory(data_b);
f = xlnt::excel_serializer::repair_central_directory(data_b);
TS_ASSERT_EQUALS(f, data_b);
}
void test_read_no_theme()
{
auto path = PathHelper::GetDataDirectory("/genuine/libreoffice_nrt.xlsx");
auto wb = xlnt::excel_reader::load_workbook(path);
xlnt::workbook wb;
xlnt::excel_serializer serializer(wb);
serializer.load_workbook(path);
TS_ASSERT_DIFFERS(wb, nullptr);
}
@ -246,7 +301,13 @@ public:
void test_data_only()
{
auto path = PathHelper::GetDataDirectory("/reader/formulae.xlsx");
auto wb = xlnt::excel_reader::load_workbook(path, false, true);
xlnt::workbook wb;
xlnt::excel_serializer serializer(wb);
serializer.load_workbook(path, false, true);
auto ws = wb.get_active_sheet();
TS_ASSERT(ws.get_formula_attributes().empty());
@ -364,18 +425,27 @@ public:
};
auto path = PathHelper::GetDataDirectory("/reader/contains_chartsheets.xlsx");
xlnt::zip_file f(path);
auto result = xlnt::read_content_types(f);
if(result.size() != expected.size())
{
TS_ASSERT_EQUALS(result.size(), expected.size());
return;
}
xlnt::workbook wb;
xlnt::manifest_serializer serializer(wb.get_manifest());
xlnt::zip_file archive;
archive.load(path);
serializer.read_manifest(xlnt::xml_serializer::deserialize(archive.read("[Content Types].xml")));
auto &result = wb.get_manifest().get_override_types();
if(result.size() != expected.size())
{
TS_ASSERT_EQUALS(result.size(), expected.size());
return;
}
for(std::size_t i = 0; i < expected.size(); i++)
{
TS_ASSERT_EQUALS(result[i], expected[i]);
TS_ASSERT_EQUALS(result[i].get_part_name(), expected[i].first);
TS_ASSERT_EQUALS(result[i].get_content_type(), expected[i].second);
}
}
@ -383,8 +453,11 @@ public:
{
{
auto path = PathHelper::GetDataDirectory("/reader/bug137.xlsx");
xlnt::zip_file f(path);
auto sheets = xlnt::read_sheets(f);
xlnt::workbook wb;
xlnt::workbook_serializer serializer(wb);
auto sheets = serializer.read_sheets();
std::vector<std::pair<std::string, std::string>> expected =
{{"rId1", "Chart1"}, {"rId2", "Sheet1"}};
TS_ASSERT_EQUALS(sheets, expected);
@ -392,8 +465,11 @@ public:
{
auto path = PathHelper::GetDataDirectory("/reader/bug304.xlsx");
xlnt::zip_file f(path);
auto sheets = xlnt::read_sheets(f);
xlnt::workbook wb;
xlnt::workbook_serializer serializer(wb);
auto sheets = serializer.read_sheets();
std::vector<std::pair<std::string, std::string>> expected =
{{"rId1", "Sheet1"}, {"rId2", "Sheet2"}, {"rId3", "Sheet3"}};
TS_ASSERT_EQUALS(sheets, expected);
@ -410,7 +486,12 @@ public:
{
std::tie(guess, dtype) = expected;
auto path = PathHelper::GetDataDirectory("/genuine/guess_types.xlsx");
auto wb = xlnt::excel_reader::load_workbook(path, guess);
xlnt::workbook wb;
xlnt::excel_serializer serializer(wb);
serializer.load_workbook(path, guess);
auto ws = wb.get_active_sheet();
TS_ASSERT(ws.get_cell("D2").get_data_type() == dtype);
}
@ -419,7 +500,12 @@ public:
void test_read_autofilter()
{
auto path = PathHelper::GetDataDirectory("/reader/bug275.xlsx");
auto wb = xlnt::excel_reader::load_workbook(path);
xlnt::workbook wb;
xlnt::excel_serializer serializer(wb);
serializer.load_workbook(path);
auto ws = wb.get_active_sheet();
TS_ASSERT_EQUALS(ws.get_auto_filter().to_string(), "A1:B6");
}
@ -427,18 +513,30 @@ public:
void test_bad_formats_xlsb()
{
auto path = PathHelper::GetDataDirectory("/genuine/a.xlsb");
TS_ASSERT_THROWS(xlnt::excel_reader::load_workbook(path), xlnt::invalid_file_exception);
xlnt::workbook wb;
xlnt::excel_serializer serializer(wb);
TS_ASSERT_THROWS(serializer.load_workbook(path), xlnt::invalid_file_exception);
}
void test_bad_formats_xls()
{
auto path = PathHelper::GetDataDirectory("/genuine/a.xls");
TS_ASSERT_THROWS(xlnt::excel_reader::load_workbook(path), xlnt::invalid_file_exception);
xlnt::workbook wb;
xlnt::excel_serializer serializer(wb);
TS_ASSERT_THROWS(serializer.load_workbook(path), xlnt::invalid_file_exception);
}
void test_bad_formats_no()
{
auto path = PathHelper::GetDataDirectory("/genuine/a.no-format");
TS_ASSERT_THROWS(xlnt::excel_reader::load_workbook(path), xlnt::invalid_file_exception);
xlnt::workbook wb;
xlnt::excel_serializer serializer(wb);
TS_ASSERT_THROWS(serializer.load_workbook(path), xlnt::invalid_file_exception);
}
};

View File

@ -3,7 +3,7 @@
#include <iostream>
#include <cxxtest/TestSuite.h>
#include <xlnt/xlnt.hpp>
#include <xlnt/s11n/style_serializer.hpp>
class test_style_writer : public CxxTest::TestSuite
{
@ -12,7 +12,7 @@ public:
{
xlnt::workbook wb;
wb.add_number_format(xlnt::number_format("YYYY"));
xlnt::style_writer writer(wb);
xlnt::style_serializer writer(wb);
auto xml = writer.write_number_formats();
std::string expected =
"<styleSheet xmlns=\"http://schemas.openxmlformats.org/spreadsheetml/2006/main\">"

View File

@ -3,7 +3,8 @@
#include <iostream>
#include <cxxtest/TestSuite.h>
#include <xlnt/writer/workbook_writer.hpp>
#include <xlnt/s11n/theme_serializer.hpp>
#include <xlnt/workbook/workbook.hpp>
#include "helpers/path_helper.hpp"
#include "helpers/helper.hpp"
@ -13,7 +14,9 @@ class test_theme : public CxxTest::TestSuite
public:
void test_write_theme()
{
auto content = xlnt::write_theme();
TS_ASSERT(Helper::EqualsFileContent(PathHelper::GetDataDirectory() + "/writer/expected/theme1.xml", content));
xlnt::theme_serializer serializer;
xlnt::workbook wb;
auto content = serializer.write_theme(wb.get_loaded_theme());
TS_ASSERT(Helper::compare_xml(PathHelper::GetDataDirectory() + "/writer/expected/theme1.xml", content));
}
};

View File

@ -3,7 +3,7 @@
#include <iostream>
#include <cxxtest/TestSuite.h>
#include <xlnt/writer/worksheet_writer.hpp>
#include <xlnt/worksheet/worksheet.hpp>
class test_worksheet : public CxxTest::TestSuite
{