summaryrefslogtreecommitdiff
path: root/sax/tst/test_decoder.cc
diff options
context:
space:
mode:
Diffstat (limited to 'sax/tst/test_decoder.cc')
-rw-r--r--sax/tst/test_decoder.cc242
1 files changed, 242 insertions, 0 deletions
diff --git a/sax/tst/test_decoder.cc b/sax/tst/test_decoder.cc
new file mode 100644
index 0000000..86f230b
--- /dev/null
+++ b/sax/tst/test_decoder.cc
@@ -0,0 +1,242 @@
+#include "sax_decoder.hh"
+#include "sax_decoder_factory.hh"
+#include "sax_processor.hh"
+#include "sax_delegate.hh"
+
+#include <memory>
+#include <gtest/gtest.h>
+
+namespace {
+
+class TestDelegate : public modxml::sax::Delegate {
+ public:
+ ~TestDelegate() override = default;
+
+ void empty_element(std::string_view name,
+ modxml::sax::Attributes const&) override {
+ EXPECT_EQ(name, "root");
+ if (name == "root") {
+ EXPECT_FALSE(have_root_);
+ have_root_ = true;
+ }
+ }
+
+ void error(std::string_view message) override {
+ have_error_ = true;
+ FAIL() << message;
+ }
+
+ bool have_root() const { return have_root_; }
+
+ bool have_error() const { return have_error_; }
+
+ private:
+ bool have_root_{false};
+ bool have_error_{false};
+};
+
+bool process_all(modxml::sax::Processor& processor,
+ TestDelegate& delegate,
+ std::span<uint8_t const> data) {
+ std::size_t offset = 0;
+ while (offset < data.size()) {
+ auto consumed = processor.process(data, offset);
+ if (consumed == 0 || delegate.have_error())
+ return false;
+ offset += consumed;
+ }
+ return true;
+}
+
+} // namespace
+
+TEST(sax, decoder_utf8) {
+ auto delegate = std::make_shared<TestDelegate>();
+ auto processor = modxml::sax::Processor::create(delegate);
+ std::string input = R"(<?xml version="1.0" encoding="utf-8"?><root />)";
+ std::cerr << input << std::endl;
+ EXPECT_TRUE(process_all(
+ *processor.get(),
+ *delegate.get(),
+ std::span<uint8_t const>(reinterpret_cast<uint8_t const*>(input.data()),
+ input.size())));
+ EXPECT_TRUE(delegate->have_root());
+}
+
+TEST(sax, decoder_utf8_bom) {
+ auto delegate = std::make_shared<TestDelegate>();
+ auto processor = modxml::sax::Processor::create(delegate);
+ std::string input =
+ "\xef\xbb\xbf" R"(<?xml version="1.0" encoding="utf-8"?><root />)";
+ std::cerr << input << std::endl;
+ EXPECT_TRUE(process_all(
+ *processor.get(),
+ *delegate.get(),
+ std::span<uint8_t const>(reinterpret_cast<uint8_t const*>(input.data()),
+ input.size())));
+ EXPECT_TRUE(delegate->have_root());
+}
+
+TEST(sax, decoder_utf16) {
+ auto delegate = std::make_shared<TestDelegate>();
+ auto processor = modxml::sax::Processor::create(delegate);
+ std::u16string input = uR"(<?xml version="1.0" encoding="utf-16"?><root />)";
+ EXPECT_TRUE(process_all(
+ *processor.get(),
+ *delegate.get(),
+ std::span<uint8_t const>(reinterpret_cast<uint8_t const*>(input.data()),
+ input.size() * sizeof(char16_t))));
+ EXPECT_TRUE(delegate->have_root());
+}
+
+TEST(sax, decoder_utf16be) {
+ auto delegate = std::make_shared<TestDelegate>();
+ auto processor = modxml::sax::Processor::create(delegate);
+ std::u16string str = uR"(<?xml version="1.0" encoding="utf-16"?><root />)";
+ std::vector<uint8_t> input;
+ for (char16_t c : str) {
+ input.push_back(c >> 8);
+ input.push_back(c & 0xff);
+ }
+ EXPECT_TRUE(process_all(
+ *processor.get(),
+ *delegate.get(),
+ std::span<uint8_t const>(input.data(), input.size())));
+ EXPECT_TRUE(delegate->have_root());
+}
+
+TEST(sax, decoder_utf16le) {
+ auto delegate = std::make_shared<TestDelegate>();
+ auto processor = modxml::sax::Processor::create(delegate);
+ std::u16string str = uR"(<?xml version="1.0" encoding="utf-16"?><root />)";
+ std::vector<uint8_t> input;
+ for (char16_t c : str) {
+ input.push_back(c & 0xff);
+ input.push_back(c >> 8);
+ }
+ EXPECT_TRUE(process_all(
+ *processor.get(),
+ *delegate.get(),
+ std::span<uint8_t const>(input.data(), input.size())));
+ EXPECT_TRUE(delegate->have_root());
+}
+
+TEST(sax, decoder_utf16be_bom) {
+ auto delegate = std::make_shared<TestDelegate>();
+ auto processor = modxml::sax::Processor::create(delegate);
+ std::u16string str =
+ u"\ufffe" uR"(<?xml version="1.0" encoding="utf-16"?><root />)";
+ std::vector<uint8_t> input;
+ for (char16_t c : str) {
+ input.push_back(c >> 8);
+ input.push_back(c & 0xff);
+ }
+ EXPECT_TRUE(process_all(
+ *processor.get(),
+ *delegate.get(),
+ std::span<uint8_t const>(input.data(), input.size())));
+ EXPECT_TRUE(delegate->have_root());
+}
+
+TEST(sax, decoder_utf16le_bom) {
+ auto delegate = std::make_shared<TestDelegate>();
+ auto processor = modxml::sax::Processor::create(delegate);
+ std::u16string str =
+ u"\ufffe" uR"(<?xml version="1.0" encoding="utf-16"?><root />)";
+ std::vector<uint8_t> input;
+ for (char16_t c : str) {
+ input.push_back(c & 0xff);
+ input.push_back(c >> 8);
+ }
+ EXPECT_TRUE(process_all(
+ *processor.get(),
+ *delegate.get(),
+ std::span<uint8_t const>(input.data(), input.size())));
+ EXPECT_TRUE(delegate->have_root());
+}
+
+TEST(sax, decoder_utf32) {
+ auto delegate = std::make_shared<TestDelegate>();
+ auto processor = modxml::sax::Processor::create(delegate);
+ std::u32string input = UR"(<?xml version="1.0" encoding="utf-32"?><root />)";
+ EXPECT_TRUE(process_all(
+ *processor.get(),
+ *delegate.get(),
+ std::span<uint8_t const>(reinterpret_cast<uint8_t const*>(input.data()),
+ input.size() * sizeof(char32_t))));
+ EXPECT_TRUE(delegate->have_root());
+}
+
+TEST(sax, decoder_utf32be) {
+ auto delegate = std::make_shared<TestDelegate>();
+ auto processor = modxml::sax::Processor::create(delegate);
+ std::u32string str = UR"(<?xml version="1.0" encoding="utf-32"?><root />)";
+ std::vector<uint8_t> input;
+ for (char32_t c : str) {
+ input.push_back(c >> 24);
+ input.push_back((c >> 16) & 0xff);
+ input.push_back((c >> 8) & 0xff);
+ input.push_back(c & 0xff);
+ }
+ EXPECT_TRUE(process_all(
+ *processor.get(),
+ *delegate.get(),
+ std::span<uint8_t const>(input.data(), input.size())));
+ EXPECT_TRUE(delegate->have_root());
+}
+
+TEST(sax, decoder_utf32le) {
+ auto delegate = std::make_shared<TestDelegate>();
+ auto processor = modxml::sax::Processor::create(delegate);
+ std::u32string str = UR"(<?xml version="1.0" encoding="utf-32"?><root />)";
+ std::vector<uint8_t> input;
+ for (char32_t c : str) {
+ input.push_back(c & 0xff);
+ input.push_back((c >> 8) & 0xff);
+ input.push_back((c >> 16) & 0xff);
+ input.push_back(c >> 24);
+ }
+ EXPECT_TRUE(process_all(
+ *processor.get(),
+ *delegate.get(),
+ std::span<uint8_t const>(input.data(), input.size())));
+ EXPECT_TRUE(delegate->have_root());
+}
+
+TEST(sax, decoder_utf32be_bom) {
+ auto delegate = std::make_shared<TestDelegate>();
+ auto processor = modxml::sax::Processor::create(delegate);
+ std::u32string str =
+ U"\ufffe" UR"(<?xml version="1.0" encoding="utf-32"?><root />)";
+ std::vector<uint8_t> input;
+ for (char32_t c : str) {
+ input.push_back(c >> 24);
+ input.push_back((c >> 16) & 0xff);
+ input.push_back((c >> 8) & 0xff);
+ input.push_back(c & 0xff);
+ }
+ EXPECT_TRUE(process_all(
+ *processor.get(),
+ *delegate.get(),
+ std::span<uint8_t const>(input.data(), input.size())));
+ EXPECT_TRUE(delegate->have_root());
+}
+
+TEST(sax, decoder_utf32le_bom) {
+ auto delegate = std::make_shared<TestDelegate>();
+ auto processor = modxml::sax::Processor::create(delegate);
+ std::u32string str =
+ U"\ufffe" R"(<?xml version="1.0" encoding="utf-32"?><root />)";
+ std::vector<uint8_t> input;
+ for (char32_t c : str) {
+ input.push_back(c & 0xff);
+ input.push_back((c >> 8) & 0xff);
+ input.push_back((c >> 16) & 0xff);
+ input.push_back(c >> 24);
+ }
+ EXPECT_TRUE(process_all(
+ *processor.get(),
+ *delegate.get(),
+ std::span<uint8_t const>(input.data(), input.size())));
+ EXPECT_TRUE(delegate->have_root());
+}