// SPDX-License-Identifier: LGPL-2.1-or-later #include "gtest/gtest.h" #ifdef _MSC_VER #pragma warning(disable : 4996) #endif #include "Base/Exception.h" #include "Base/Reader.h" #include #include #include #include namespace fs = boost::filesystem; class ReaderTest: public ::testing::Test { protected: void SetUp() override { xercesc_3_2::XMLPlatformUtils::Initialize(); _tempDir = fs::temp_directory_path(); std::string filename = "unit_test_Reader.xml"; _tempFile = _tempDir / filename; } void TearDown() override { if (fs::exists(_tempFile)) { fs::remove(_tempFile); } } void givenDataAsXMLStream(const std::string& data) { auto stringData = R"()" + data + ""; std::istringstream stream(stringData); std::ofstream fileStream(_tempFile.string()); fileStream.write(stringData.data(), static_cast(stringData.length())); fileStream.close(); std::ifstream inputStream(_tempFile.string()); _reader = std::make_unique(_tempFile.string().c_str(), inputStream); } Base::XMLReader* Reader() { return _reader.get(); } private: std::unique_ptr _reader; fs::path _tempDir; fs::path _tempFile; }; TEST_F(ReaderTest, beginCharStreamNormal) { // Arrange givenDataAsXMLStream("Test ASCII data"); Reader()->readElement("data"); // Act auto& result = Reader()->beginCharStream(); // Assert EXPECT_TRUE(result.good()); } TEST_F(ReaderTest, beginCharStreamOpenClose) { // Arrange givenDataAsXMLStream(""); Reader()->readElement("data"); // Act auto& result = Reader()->beginCharStream(); // Not an error, even though there is no data // Assert EXPECT_TRUE(result.good()); } TEST_F(ReaderTest, beginCharStreamAlreadyBegun) { // Arrange givenDataAsXMLStream("Test ASCII data"); Reader()->readElement("data"); Reader()->beginCharStream(); // Act & Assert EXPECT_THROW(Reader()->beginCharStream(), Base::XMLParseException); // NOLINT } TEST_F(ReaderTest, charStreamGood) { // Arrange givenDataAsXMLStream("Test ASCII data"); Reader()->readElement("data"); Reader()->beginCharStream(); // Act auto& result = Reader()->charStream(); // Assert EXPECT_TRUE(result.good()); } TEST_F(ReaderTest, charStreamBad) { // Arrange givenDataAsXMLStream("Test ASCII data"); Reader()->readElement("data"); // Act & Assert EXPECT_THROW(Reader()->charStream(), Base::XMLParseException); // NOLINT } TEST_F(ReaderTest, endCharStreamGood) { // Arrange givenDataAsXMLStream("Test ASCII data"); Reader()->readElement("data"); Reader()->beginCharStream(); // Act & Assert Reader()->endCharStream(); // Does not throw } TEST_F(ReaderTest, endCharStreamBad) { // Arrange givenDataAsXMLStream("Test ASCII data"); Reader()->readElement("data"); // Do not open the stream... // Act & Assert Reader()->endCharStream(); // Does not throw, even with no open stream } TEST_F(ReaderTest, readDataSmallerThanBuffer) { // Arrange constexpr size_t bufferSize {20}; std::string expectedData {"Test ASCII data"}; givenDataAsXMLStream("" + expectedData + ""); Reader()->readElement("data"); Reader()->beginCharStream(); std::array buffer {}; // Act auto bytesRead = Reader()->read(buffer.data(), bufferSize); // Assert EXPECT_STREQ(expectedData.c_str(), buffer.data()); EXPECT_EQ(expectedData.length(), bytesRead); } TEST_F(ReaderTest, readDataLargerThanBuffer) { // Arrange constexpr size_t bufferSize {5}; std::string expectedData {"Test ASCII data"}; givenDataAsXMLStream("" + expectedData + ""); Reader()->readElement("data"); Reader()->beginCharStream(); std::array buffer {}; // Act auto bytesRead = Reader()->read(buffer.data(), bufferSize); // Assert for (size_t i = 0; i < bufferSize; ++i) { EXPECT_EQ(expectedData[i], buffer.at(i)); } EXPECT_EQ(bufferSize, bytesRead); } TEST_F(ReaderTest, readDataLargerThanBufferSecondRead) { // Arrange constexpr size_t bufferSize {5}; std::string expectedData {"Test ASCII data"}; givenDataAsXMLStream("" + expectedData + ""); Reader()->readElement("data"); Reader()->beginCharStream(); std::array buffer {}; Reader()->read(buffer.data(), bufferSize); // Read the first five bytes // Act auto bytesRead = Reader()->read(buffer.data(), bufferSize); // Second five bytes // Assert for (size_t i = 0; i < bufferSize; ++i) { EXPECT_EQ(expectedData[i + bufferSize], buffer.at(i)); } EXPECT_EQ(bufferSize, bytesRead); } TEST_F(ReaderTest, readDataNotStarted) { // Arrange constexpr size_t bufferSize {20}; std::string expectedData {"Test ASCII data"}; givenDataAsXMLStream("" + expectedData + ""); Reader()->readElement("data"); std::array buffer {}; // Act auto bytesRead = Reader()->read(buffer.data(), bufferSize); // Assert EXPECT_EQ(-1, bytesRead); // Because we didn't call beginCharStream } TEST_F(ReaderTest, readNextStartElement) { auto xmlBody = R"( Node1 Node2 )"; givenDataAsXMLStream(xmlBody); // start of document Reader()->readElement("document"); EXPECT_STREQ(Reader()->localName(), "document"); // next element EXPECT_TRUE(Reader()->readNextElement()); EXPECT_STREQ(Reader()->localName(), "node1"); EXPECT_STREQ(Reader()->getAttribute("attr"), "1"); Reader()->readEndElement("node1"); EXPECT_TRUE(Reader()->isEndOfElement()); // next element EXPECT_TRUE(Reader()->readNextElement()); EXPECT_STREQ(Reader()->localName(), "node2"); EXPECT_STREQ(Reader()->getAttribute("attr"), "2"); Reader()->readEndElement("node2"); EXPECT_TRUE(Reader()->isEndOfElement()); } TEST_F(ReaderTest, readNextStartEndElement) { auto xmlBody = R"( )"; givenDataAsXMLStream(xmlBody); // start of document Reader()->readElement("document"); EXPECT_STREQ(Reader()->localName(), "document"); // next element EXPECT_TRUE(Reader()->readNextElement()); EXPECT_STREQ(Reader()->localName(), "node1"); EXPECT_STREQ(Reader()->getAttribute("attr"), "1"); // next element EXPECT_TRUE(Reader()->readNextElement()); EXPECT_STREQ(Reader()->localName(), "node2"); EXPECT_STREQ(Reader()->getAttribute("attr"), "2"); }