#include #include #include "ContentOpfParser.h" #include "Epub/BookMetadataCache.h" namespace { void parse(ContentOpfParser& parser, const std::string& xml) { ASSERT_TRUE(parser.setup()); EXPECT_EQ(parser.write(reinterpret_cast(xml.data()), xml.size()), xml.size()); } } // namespace TEST(ContentOpfParserMetadata, EntityCallbackDoesNotSplitOneAuthor) { const std::string xml = R"(Émile Zola)"; ContentOpfParser parser("", "", xml.size(), nullptr); parse(parser, xml); EXPECT_EQ(parser.author, "Émile Zola"); } TEST(ContentOpfParserMetadata, ClampsOversizedMetadataTextInsteadOfGrowingUnbounded) { const std::string hugeTitle(64 * 1024, 'A'); const std::string xml = "" + hugeTitle + " tail"; ContentOpfParser parser("", "", xml.size(), nullptr); parse(parser, xml); EXPECT_EQ(parser.title.size(), 512u); EXPECT_EQ(parser.title[0], 'A'); } TEST(ContentOpfParserMetadata, SeparatesCreatorElementsAndCollapsesXmlWhitespace) { const std::string xml = R"( The Left Hand of Darkness Ursula K. Le Guin Octavia E. Butler )"; ContentOpfParser parser("", "", xml.size(), nullptr); parse(parser, xml); EXPECT_EQ(parser.title, "The Left Hand of Darkness"); EXPECT_EQ(parser.author, "Ursula K. Le Guin, Octavia E. Butler"); } TEST(ContentOpfParserMetadata, StopsBeforeManifestWithoutOpeningTemporaryStorage) { const std::string xml = R"( A Wizard of Earthsea Ursula K. Le Guin en )"; Storage = {}; ContentOpfParser parser("/missing-cache", "OPS/", xml.size(), nullptr, true); ASSERT_TRUE(parser.setup()); EXPECT_LT(parser.write(reinterpret_cast(xml.data()), xml.size()), xml.size()); EXPECT_EQ(parser.title, "A Wizard of Earthsea"); EXPECT_EQ(parser.author, "Ursula K. Le Guin"); EXPECT_EQ(parser.language, "en"); EXPECT_EQ(Storage.writeOpens, 0); EXPECT_EQ(Storage.readOpens, 0); } TEST(ContentOpfParserMetadata, NeverEntersManifestWhenMetadataElementIsMissing) { const std::string xml = R"()"; Storage = {}; ContentOpfParser parser("/missing-cache", "OPS/", xml.size(), nullptr, true); ASSERT_TRUE(parser.setup()); EXPECT_LT(parser.write(reinterpret_cast(xml.data()), xml.size()), xml.size()); EXPECT_EQ(Storage.writeOpens, 0); EXPECT_EQ(Storage.readOpens, 0); } TEST(ContentOpfParserCover, ResolvesEpub2CoverWithoutReadingCacheStorage) { const std::string xml = R"( )"; const std::string cachePath = "/missing-cache"; const std::string basePath = "OPS/"; Storage = {}; { ContentOpfParser parser(cachePath, basePath, xml.size(), nullptr); parse(parser, xml); EXPECT_EQ(parser.coverItemHref, "OPS/cover.jpg"); EXPECT_EQ(parser.guideCoverPageHref, "OPS/cover.xhtml"); } EXPECT_EQ(Storage.writeOpens, 0); EXPECT_EQ(Storage.readOpens, 0); } TEST(ContentOpfParserCover, ResolvesEpub3CoverWithoutReadingCacheStorage) { const std::string xml = R"( )"; const std::string cachePath = "/missing-cache"; const std::string basePath = "OPS/"; Storage = {}; { ContentOpfParser parser(cachePath, basePath, xml.size(), nullptr); parse(parser, xml); EXPECT_EQ(parser.coverItemHref, "OPS/cover.png"); } EXPECT_EQ(Storage.writeOpens, 0); EXPECT_EQ(Storage.readOpens, 0); } TEST(ContentOpfParserCover, ReadingParserStillOpensManifestCache) { const std::string xml = R"( )"; const std::string cachePath = "/reading-cache"; const std::string basePath = "OPS/"; BookMetadataCache cache; Storage = {}; { ContentOpfParser parser(cachePath, basePath, xml.size(), &cache); parse(parser, xml); EXPECT_EQ(parser.coverItemHref, "OPS/cover.png"); } EXPECT_EQ(Storage.writeOpens, 1); EXPECT_EQ(Storage.readOpens, 1); }