From d91517c79990f9f10c404fb1866fdf2982c609ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Mon, 5 Oct 2020 13:19:21 +0200 Subject: [PATCH] Text: expand AbstractFontConverterTest like all other converter tests. And clean up the noise from there. This is some very old code, so the coverage was rather poor, including two uncaught bugs causing test failures. Fixing that in the next commit. --- src/Magnum/Text/AbstractFontConverter.cpp | 2 +- .../Text/Test/AbstractFontConverterTest.cpp | 561 ++++++++++++++---- 2 files changed, 459 insertions(+), 104 deletions(-) diff --git a/src/Magnum/Text/AbstractFontConverter.cpp b/src/Magnum/Text/AbstractFontConverter.cpp index ff7bc364c..72a02d4d6 100644 --- a/src/Magnum/Text/AbstractFontConverter.cpp +++ b/src/Magnum/Text/AbstractFontConverter.cpp @@ -239,7 +239,7 @@ Containers::Pointer AbstractFontConverter::doImportGlyphCach /* Open file */ if(!Utility::Directory::exists(filename)) { - Error() << "Trade::AbstractFontConverter::importGlyphCacheFromFile(): cannot open file" << filename; + Error() << "Text::AbstractFontConverter::importGlyphCacheFromFile(): cannot open file" << filename; return nullptr; } diff --git a/src/Magnum/Text/Test/AbstractFontConverterTest.cpp b/src/Magnum/Text/Test/AbstractFontConverterTest.cpp index 2aca0a3e4..d78fa781a 100644 --- a/src/Magnum/Text/Test/AbstractFontConverterTest.cpp +++ b/src/Magnum/Text/Test/AbstractFontConverterTest.cpp @@ -45,15 +45,29 @@ struct AbstractFontConverterTest: TestSuite::Tester { void convertGlyphs(); void exportFontToSingleData(); + void exportFontToData(); + void exportFontToDataThroughSingleData(); + void exportFontToDataThroughSingleDataFailed(); void exportFontToFile(); - void exportFontToFileFailed(); + void exportFontToFileThroughData(); + void exportFontToFileThroughDataFailed(); + void exportFontToFileThroughDataNotWritable(); void exportGlyphCacheToSingleData(); + void exportGlyphCacheToData(); + void exportGlyphCacheToDataThroughSingleData(); + void exportGlyphCacheToDataThroughSingleDataFailed(); void exportGlyphCacheToFile(); - void exportGlyphCacheToFileFailed(); + void exportGlyphCacheToFileThroughData(); + void exportGlyphCacheToFileThroughDataFailed(); + void exportGlyphCacheToFileThroughDataNotWritable(); void importGlyphCacheFromSingleData(); + void importGlyphCacheFromData(); + void importGlyphCacheFromDataAsSingleData(); void importGlyphCacheFromFile(); + void importGlyphCacheFromFileAsSingleData(); + void importGlyphCacheFromFileAsSingleDataNotFound(); void debugFeature(); void debugFeatures(); @@ -63,15 +77,29 @@ AbstractFontConverterTest::AbstractFontConverterTest() { addTests({&AbstractFontConverterTest::convertGlyphs, &AbstractFontConverterTest::exportFontToSingleData, + &AbstractFontConverterTest::exportFontToData, + &AbstractFontConverterTest::exportFontToDataThroughSingleData, + &AbstractFontConverterTest::exportFontToDataThroughSingleDataFailed, &AbstractFontConverterTest::exportFontToFile, - &AbstractFontConverterTest::exportFontToFileFailed, + &AbstractFontConverterTest::exportFontToFileThroughData, + &AbstractFontConverterTest::exportFontToFileThroughDataFailed, + &AbstractFontConverterTest::exportFontToFileThroughDataNotWritable, &AbstractFontConverterTest::exportGlyphCacheToSingleData, + &AbstractFontConverterTest::exportGlyphCacheToData, + &AbstractFontConverterTest::exportGlyphCacheToDataThroughSingleData, + &AbstractFontConverterTest::exportGlyphCacheToDataThroughSingleDataFailed, &AbstractFontConverterTest::exportGlyphCacheToFile, - &AbstractFontConverterTest::exportGlyphCacheToFileFailed, + &AbstractFontConverterTest::exportGlyphCacheToFileThroughData, + &AbstractFontConverterTest::exportGlyphCacheToFileThroughDataFailed, + &AbstractFontConverterTest::exportGlyphCacheToFileThroughDataNotWritable, &AbstractFontConverterTest::importGlyphCacheFromSingleData, + &AbstractFontConverterTest::importGlyphCacheFromData, + &AbstractFontConverterTest::importGlyphCacheFromDataAsSingleData, &AbstractFontConverterTest::importGlyphCacheFromFile, + &AbstractFontConverterTest::importGlyphCacheFromFileAsSingleData, + &AbstractFontConverterTest::importGlyphCacheFromFileAsSingleDataNotFound, &AbstractFontConverterTest::debugFeature, &AbstractFontConverterTest::debugFeatures}); @@ -100,99 +128,263 @@ struct DummyGlyphCache: AbstractGlyphCache { } dummyGlyphCache{{}}; void AbstractFontConverterTest::convertGlyphs() { - class GlyphExporter: public AbstractFontConverter { - public: - /* GCC 4.8 apparently can't handle {} here */ - GlyphExporter(std::u32string& characters): _characters(characters) {} + std::u32string characters; + struct GlyphConverter: AbstractFontConverter { + /* GCC 4.8 apparently can't handle {} here */ + GlyphConverter(std::u32string& characters): _characters(characters) {} - private: - FontConverterFeatures doFeatures() const override { return FontConverterFeature::ConvertData|FontConverterFeature::ExportFont; } + FontConverterFeatures doFeatures() const override { + return FontConverterFeature::ConvertData|FontConverterFeature::ExportFont; + } - Containers::Array doExportFontToSingleData(AbstractFont&, AbstractGlyphCache&, const std::u32string& characters) const override { - _characters = characters; - return nullptr; - } + Containers::Array doExportFontToSingleData(AbstractFont&, AbstractGlyphCache&, const std::u32string& characters) const override { + _characters = characters; + return nullptr; + } - std::u32string& _characters; - }; + private: std::u32string& _characters; + } converter{characters}; - std::u32string characters; - GlyphExporter exporter(characters); - exporter.exportFontToSingleData(dummyFont, dummyGlyphCache, "abC01a0 "); + converter.exportFontToSingleData(dummyFont, dummyGlyphCache, "abC01a0 "); CORRADE_COMPARE(characters, U" 01Cab"); } void AbstractFontConverterTest::exportFontToSingleData() { - class SingleDataExporter: public Text::AbstractFontConverter { - private: - FontConverterFeatures doFeatures() const override { return FontConverterFeature::ConvertData|FontConverterFeature::ExportFont; } + struct: AbstractFontConverter { + FontConverterFeatures doFeatures() const override { + return FontConverterFeature::ConvertData|FontConverterFeature::ExportFont; + } + + Containers::Array doExportFontToSingleData(AbstractFont&, AbstractGlyphCache&, const std::u32string& characters) const override { + return Containers::array({'\xee', char(characters.size())}); + } + } converter; + + Containers::Array out = converter.exportFontToSingleData(dummyFont, dummyGlyphCache, "euhh"); + CORRADE_COMPARE_AS(out, Containers::arrayView({'\xee', '\x03'}), + TestSuite::Compare::Container); +} + +void AbstractFontConverterTest::exportFontToData() { + struct: AbstractFontConverter { + FontConverterFeatures doFeatures() const override { + return FontConverterFeature::ConvertData|FontConverterFeature::ExportFont; + } + + std::vector>> doExportFontToData(AbstractFont&, AbstractGlyphCache&, const std::string& filename, const std::u32string& characters) const override { + /* Wow what a shit API */ + std::vector>> out; + out.emplace_back(filename, Containers::array({char(characters.size())})); + out.emplace_back(filename + ".dat", Containers::array({'\xee'})); + return out; + } + } converter; - Containers::Array doExportFontToSingleData(AbstractFont&, AbstractGlyphCache&, const std::u32string&) const override { - Containers::Array data(1); - data[0] = '\xee'; - return data; - } - }; + auto ret = converter.exportFontToData(dummyFont, dummyGlyphCache, "font.out", "eH"); + CORRADE_COMPARE(ret.size(), 2); + + CORRADE_COMPARE(ret[0].first, "font.out"); + CORRADE_COMPARE_AS(ret[0].second, Containers::arrayView({'\x02'}), + TestSuite::Compare::Container); + + CORRADE_COMPARE(ret[1].first, "font.out.dat"); + CORRADE_COMPARE_AS(ret[1].second, Containers::arrayView({'\xee'}), + TestSuite::Compare::Container); +} + +void AbstractFontConverterTest::exportFontToDataThroughSingleData() { + struct: AbstractFontConverter { + FontConverterFeatures doFeatures() const override { + return FontConverterFeature::ConvertData|FontConverterFeature::ExportFont; + } + + Containers::Array doExportFontToSingleData(AbstractFont&, AbstractGlyphCache&, const std::u32string& characters) const override { + return Containers::array({'\xee', char(characters.size())}); + } + } converter; /* doExportFontToData() should call doExportFontToSingleData() */ - SingleDataExporter exporter; - auto ret = exporter.exportFontToData(dummyFont, dummyGlyphCache, "font.out", {}); + auto ret = converter.exportFontToData(dummyFont, dummyGlyphCache, "font.out", "ehh"); CORRADE_COMPARE(ret.size(), 1); CORRADE_COMPARE(ret[0].first, "font.out"); - CORRADE_COMPARE(ret[0].second.size(), 1); - CORRADE_COMPARE(ret[0].second[0], '\xee'); + CORRADE_COMPARE_AS(ret[0].second, Containers::arrayView({'\xee', '\x02'}), + TestSuite::Compare::Container); +} + +void AbstractFontConverterTest::exportFontToDataThroughSingleDataFailed() { + struct: AbstractFontConverter { + FontConverterFeatures doFeatures() const override { + return FontConverterFeature::ConvertData|FontConverterFeature::ExportFont; + } + + Containers::Array doExportFontToSingleData(AbstractFont&, AbstractGlyphCache&, const std::u32string&) const override { + return {}; + } + } converter; + + auto ret = converter.exportFontToData(dummyFont, dummyGlyphCache, "font.out", "ehh"); + CORRADE_VERIFY(ret.empty()); } void AbstractFontConverterTest::exportFontToFile() { - class DataExporter: public Text::AbstractFontConverter { - private: - FontConverterFeatures doFeatures() const override { return FontConverterFeature::ConvertData|FontConverterFeature::ExportFont|FontConverterFeature::MultiFile; } - - std::vector>> doExportFontToData(AbstractFont&, AbstractGlyphCache&, const std::string& filename, const std::u32string&) const override { - /* Why the hell GCC 4.9 fails to do proper move so I need to - work around that this ugly way?! */ - std::vector>> ret; - ret.emplace_back(filename, Containers::Array{Containers::InPlaceInit, {'\xf0'}}); - ret.emplace_back(filename + ".data", Containers::Array{Containers::InPlaceInit, {'\xfe', '\xed'}}); - return ret; - } - }; - - /* Remove previous files */ - Utility::Directory::rm(Utility::Directory::join(TEXT_TEST_OUTPUT_DIR, "font.out")); - Utility::Directory::rm(Utility::Directory::join(TEXT_TEST_OUTPUT_DIR, "font.out.data")); + struct: AbstractFontConverter { + FontConverterFeatures doFeatures() const override { + return FontConverterFeature::ConvertData|FontConverterFeature::ExportFont|FontConverterFeature::MultiFile; + } + + bool doExportFontToFile(AbstractFont&, AbstractGlyphCache&, const std::string& filename, const std::u32string& characters) const override { + return + Utility::Directory::write(filename, Containers::arrayView({'\xf0'})) && + Utility::Directory::write(filename + ".dat", Containers::arrayView({'\xfe', char(characters.size())})); + } + } converter; + + const std::string filename = Utility::Directory::join(TEXT_TEST_OUTPUT_DIR, "font.out"); + const std::string filename2 = Utility::Directory::join(TEXT_TEST_OUTPUT_DIR, "font.out.dat"); + + /* Remove previous files, if any */ + Utility::Directory::rm(filename); + Utility::Directory::rm(filename2); + CORRADE_VERIFY(!Utility::Directory::exists(filename)); + CORRADE_VERIFY(!Utility::Directory::exists(filename2)); + + CORRADE_VERIFY(converter.exportFontToFile(dummyFont, dummyGlyphCache, filename, "eh")); + CORRADE_COMPARE_AS(filename, "\xf0", + TestSuite::Compare::FileToString); + CORRADE_COMPARE_AS(filename2, + "\xfe\x02", TestSuite::Compare::FileToString); +} + +void AbstractFontConverterTest::exportFontToFileThroughData() { + struct: AbstractFontConverter { + FontConverterFeatures doFeatures() const override { + return FontConverterFeature::ConvertData|FontConverterFeature::ExportFont|FontConverterFeature::MultiFile; + } + + std::vector>> doExportFontToData(AbstractFont&, AbstractGlyphCache&, const std::string& filename, const std::u32string& characters) const override { + std::vector>> ret; + ret.emplace_back(filename, Containers::array({'\xf0'})); + ret.emplace_back(filename + ".dat", Containers::array({'\xfe', char(characters.size())})); + return ret; + } + } converter; + + const std::string filename = Utility::Directory::join(TEXT_TEST_OUTPUT_DIR, "font.out"); + const std::string filename2 = Utility::Directory::join(TEXT_TEST_OUTPUT_DIR, "font.out.dat"); + + /* Remove previous files, if any */ + Utility::Directory::rm(filename); + Utility::Directory::rm(filename2); + CORRADE_VERIFY(!Utility::Directory::exists(filename)); + CORRADE_VERIFY(!Utility::Directory::exists(filename2)); /* doExportToFile() should call doExportToData() */ - DataExporter exporter; - bool exported = exporter.exportFontToFile(dummyFont, dummyGlyphCache, Utility::Directory::join(TEXT_TEST_OUTPUT_DIR, "font.out"), {}); - CORRADE_VERIFY(exported); - CORRADE_COMPARE_AS(Utility::Directory::join(TEXT_TEST_OUTPUT_DIR, "font.out"), - "\xf0", TestSuite::Compare::FileToString); - CORRADE_COMPARE_AS(Utility::Directory::join(TEXT_TEST_OUTPUT_DIR, "font.out.data"), - "\xfe\xed", TestSuite::Compare::FileToString); + CORRADE_VERIFY(converter.exportFontToFile(dummyFont, dummyGlyphCache, filename, "awoo")); + CORRADE_COMPARE_AS(filename, "\xf0", + TestSuite::Compare::FileToString); + CORRADE_COMPARE_AS(filename2, "\xfe\x03", + TestSuite::Compare::FileToString); } -void AbstractFontConverterTest::exportFontToFileFailed() { +void AbstractFontConverterTest::exportFontToFileThroughDataFailed() { struct: AbstractFontConverter { - FontConverterFeatures doFeatures() const override { return FontConverterFeature::ConvertData|FontConverterFeature::ExportFont|FontConverterFeature::MultiFile; } + FontConverterFeatures doFeatures() const override { + return FontConverterFeature::ConvertData|FontConverterFeature::ExportFont|FontConverterFeature::MultiFile; + } std::vector>> doExportFontToData(AbstractFont&, AbstractGlyphCache&, const std::string&, const std::u32string&) const override { return {}; } - } exporter; + } converter; + + const std::string filename = Utility::Directory::join(TEXT_TEST_OUTPUT_DIR, "font.out"); + + /* Remove previous file, if any */ + Utility::Directory::rm(filename); + CORRADE_VERIFY(!Utility::Directory::exists(filename)); + + /* Function should fail, no file should get written and no error output + should be printed (the base implementation assumes the plugin does it) */ + std::ostringstream out; + Error redirectError{&out}; + CORRADE_VERIFY(!converter.exportFontToFile(dummyFont, dummyGlyphCache, filename, {})); + CORRADE_VERIFY(!Utility::Directory::exists(filename)); + CORRADE_COMPARE(out.str(), ""); +} - CORRADE_VERIFY(!exporter.exportFontToFile(dummyFont, dummyGlyphCache, "nonexistent.dat", {})); +void AbstractFontConverterTest::exportFontToFileThroughDataNotWritable() { + struct: AbstractFontConverter { + FontConverterFeatures doFeatures() const override { + return FontConverterFeature::ConvertData|FontConverterFeature::ExportFont|FontConverterFeature::MultiFile; + } + + std::vector>> doExportFontToData(AbstractFont&, AbstractGlyphCache&, const std::string& filename, const std::u32string&) const override { + std::vector>> ret; + ret.emplace_back(filename, Containers::array({'\xf0'})); + return ret; + } + } converter; + + std::ostringstream out; + Error redirectError{&out}; + CORRADE_VERIFY(!converter.exportFontToFile(dummyFont, dummyGlyphCache, "/some/path/that/does/not/exist", {})); + CORRADE_COMPARE(out.str(), + "Utility::Directory::write(): can't open /some/path/that/does/not/exist\n" + "Text::AbstractFontConverter::exportFontToFile(): cannot write to file /some/path/that/does/not/exist\n"); } void AbstractFontConverterTest::exportGlyphCacheToSingleData() { - struct: Text::AbstractFontConverter { + struct: AbstractFontConverter { FontConverterFeatures doFeatures() const override { return FontConverterFeature::ConvertData|FontConverterFeature::ExportGlyphCache; } Containers::Array doExportGlyphCacheToSingleData(AbstractGlyphCache&) const override { - return Containers::Array{Containers::InPlaceInit, {'\xee'}}; + return Containers::array({'\xee'}); } - } exporter; + } converter; + + Containers::Array out = converter.exportGlyphCacheToSingleData(dummyGlyphCache); + CORRADE_COMPARE_AS(out, + (Containers::Array{Containers::InPlaceInit, {'\xee'}}), + TestSuite::Compare::Container); +} + +void AbstractFontConverterTest::exportGlyphCacheToData() { + struct: AbstractFontConverter { + FontConverterFeatures doFeatures() const override { + return FontConverterFeature::ConvertData|FontConverterFeature::ExportGlyphCache; + } + + std::vector>> doExportGlyphCacheToData(AbstractGlyphCache&, const std::string& filename) const override { + std::vector>> ret; + ret.emplace_back(filename, Containers::array({'\xf0'})); + ret.emplace_back(filename + ".dat", Containers::array({'\xfe', '\xed'})); + return ret; + } + } converter; + + auto ret = converter.exportGlyphCacheToData(dummyGlyphCache, "cache.out"); + CORRADE_COMPARE(ret.size(), 2); + + CORRADE_COMPARE(ret[0].first, "cache.out"); + CORRADE_COMPARE_AS(ret[0].second, Containers::arrayView({'\xf0'}), + TestSuite::Compare::Container); + + CORRADE_COMPARE(ret[1].first, "cache.out.dat"); + CORRADE_COMPARE_AS(ret[1].second, Containers::arrayView({'\xfe', '\xed'}), + TestSuite::Compare::Container); +} + +void AbstractFontConverterTest::exportGlyphCacheToDataThroughSingleData() { + struct: AbstractFontConverter { + FontConverterFeatures doFeatures() const override { + return FontConverterFeature::ConvertData|FontConverterFeature::ExportGlyphCache; + } + + Containers::Array doExportGlyphCacheToSingleData(AbstractGlyphCache&) const override { + return Containers::array({'\xee'}); + } + } converter; /* doExportGlyphCacheToData() should call doExportGlyphCacheToSingleData() */ - auto ret = exporter.exportGlyphCacheToData(dummyGlyphCache, "font.out"); + auto ret = converter.exportGlyphCacheToData(dummyGlyphCache, "font.out"); CORRADE_COMPARE(ret.size(), 1); CORRADE_COMPARE(ret[0].first, "font.out"); CORRADE_COMPARE_AS(ret[0].second, @@ -200,72 +392,235 @@ void AbstractFontConverterTest::exportGlyphCacheToSingleData() { TestSuite::Compare::Container); } +void AbstractFontConverterTest::exportGlyphCacheToDataThroughSingleDataFailed() { + struct: AbstractFontConverter { + FontConverterFeatures doFeatures() const override { + return FontConverterFeature::ConvertData|FontConverterFeature::ExportGlyphCache; + } + + Containers::Array doExportGlyphCacheToSingleData(AbstractGlyphCache&) const override { + return {}; + } + } converter; + + auto ret = converter.exportGlyphCacheToData(dummyGlyphCache, "font.out"); + CORRADE_VERIFY(ret.empty()); +} + void AbstractFontConverterTest::exportGlyphCacheToFile() { - class DataExporter: public Text::AbstractFontConverter { - private: - FontConverterFeatures doFeatures() const override { return FontConverterFeature::ConvertData|FontConverterFeature::ExportGlyphCache|FontConverterFeature::MultiFile; } - - std::vector>> doExportGlyphCacheToData(AbstractGlyphCache&, const std::string& filename) const override { - /* Why the hell GCC 4.9 fails to do proper move so I need to - work around that this ugly way?! */ - std::vector>> ret; - ret.emplace_back(filename, Containers::Array{Containers::InPlaceInit, {'\xf0'}}); - ret.emplace_back(filename + ".data", Containers::Array{Containers::InPlaceInit, {'\xfe', '\xed'}}); - return ret; - } - }; - - /* Remove previous files */ - Utility::Directory::rm(Utility::Directory::join(TEXT_TEST_OUTPUT_DIR, "glyphcache.out")); - Utility::Directory::rm(Utility::Directory::join(TEXT_TEST_OUTPUT_DIR, "glyphcache.out.data")); + struct: AbstractFontConverter { + FontConverterFeatures doFeatures() const override { + return FontConverterFeature::ConvertData|FontConverterFeature::ExportGlyphCache|FontConverterFeature::MultiFile; + } + + bool doExportGlyphCacheToFile(AbstractGlyphCache&, const std::string& filename) const override { + return + Utility::Directory::write(filename, Containers::arrayView({'\xf0'})) && + Utility::Directory::write(filename + ".dat", Containers::arrayView({'\xfe', '\xed'})); + } + } converter; + + const std::string filename = Utility::Directory::join(TEXT_TEST_OUTPUT_DIR, "cache.out"); + const std::string filename2 = Utility::Directory::join(TEXT_TEST_OUTPUT_DIR, "cache.out.dat"); + + /* Remove previous files, if any */ + Utility::Directory::rm(filename); + Utility::Directory::rm(filename2); + CORRADE_VERIFY(!Utility::Directory::exists(filename)); + CORRADE_VERIFY(!Utility::Directory::exists(filename2)); + + CORRADE_VERIFY(converter.exportGlyphCacheToFile(dummyGlyphCache, filename)); + CORRADE_COMPARE_AS(filename, "\xf0", + TestSuite::Compare::FileToString); + CORRADE_COMPARE_AS(filename2, + "\xfe\xed", TestSuite::Compare::FileToString); +} + +void AbstractFontConverterTest::exportGlyphCacheToFileThroughData() { + struct: AbstractFontConverter { + FontConverterFeatures doFeatures() const override { + return FontConverterFeature::ConvertData|FontConverterFeature::ExportGlyphCache|FontConverterFeature::MultiFile; + } + + std::vector>> doExportGlyphCacheToData(AbstractGlyphCache&, const std::string& filename) const override { + std::vector>> ret; + ret.emplace_back(filename, Containers::Array{Containers::InPlaceInit, {'\xf0'}}); + ret.emplace_back(filename + ".dat", Containers::Array{Containers::InPlaceInit, {'\xfe', '\xed'}}); + return ret; + } + } converter; + + const std::string filename = Utility::Directory::join(TEXT_TEST_OUTPUT_DIR, "cache.out"); + const std::string filename2 = Utility::Directory::join(TEXT_TEST_OUTPUT_DIR, "cache.out.dat"); + + /* Remove previous files, if any */ + Utility::Directory::rm(filename); + Utility::Directory::rm(filename2); + CORRADE_VERIFY(!Utility::Directory::exists(filename)); + CORRADE_VERIFY(!Utility::Directory::exists(filename2)); /* doExportGlyphCacheToFile() should call doExportGlyphCacheToData() */ - DataExporter exporter; - bool exported = exporter.exportGlyphCacheToFile(dummyGlyphCache, Utility::Directory::join(TEXT_TEST_OUTPUT_DIR, "glyphcache.out")); - CORRADE_VERIFY(exported); - CORRADE_COMPARE_AS(Utility::Directory::join(TEXT_TEST_OUTPUT_DIR, "glyphcache.out"), - "\xf0", TestSuite::Compare::FileToString); - CORRADE_COMPARE_AS(Utility::Directory::join(TEXT_TEST_OUTPUT_DIR, "glyphcache.out.data"), - "\xfe\xed", TestSuite::Compare::FileToString); + CORRADE_VERIFY(converter.exportGlyphCacheToFile(dummyGlyphCache, filename)); + CORRADE_COMPARE_AS(filename, "\xf0", + TestSuite::Compare::FileToString); + CORRADE_COMPARE_AS(filename2, + "\xfe\xed", TestSuite::Compare::FileToString); } -void AbstractFontConverterTest::exportGlyphCacheToFileFailed() { - struct: Text::AbstractFontConverter { +void AbstractFontConverterTest::exportGlyphCacheToFileThroughDataFailed() { + struct: AbstractFontConverter { FontConverterFeatures doFeatures() const override { return FontConverterFeature::ConvertData|FontConverterFeature::ExportGlyphCache|FontConverterFeature::MultiFile; } std::vector>> doExportGlyphCacheToData(AbstractGlyphCache&, const std::string&) const override { return {}; } - } exporter; + } converter; - /* doExportGlyphCacheToFile() should call doExportGlyphCacheToData() */ - CORRADE_VERIFY(!exporter.exportGlyphCacheToFile(dummyGlyphCache, "nonexistent.dat")); + const std::string filename = Utility::Directory::join(TEXT_TEST_OUTPUT_DIR, "cache.out"); + + /* Remove previous file, if any */ + Utility::Directory::rm(filename); + CORRADE_VERIFY(!Utility::Directory::exists(filename)); + + /* Function should fail, no file should get written and no error output + should be printed (the base implementation assumes the plugin does it) */ + std::ostringstream out; + Error redirectError{&out}; + CORRADE_VERIFY(!converter.exportGlyphCacheToFile(dummyGlyphCache, filename)); + CORRADE_VERIFY(!Utility::Directory::exists(filename)); + CORRADE_COMPARE(out.str(), ""); } -class SingleGlyphCacheDataImporter: public Text::AbstractFontConverter { - private: - FontConverterFeatures doFeatures() const override { return FontConverterFeature::ConvertData|FontConverterFeature::ImportGlyphCache; } +void AbstractFontConverterTest::exportGlyphCacheToFileThroughDataNotWritable() { + struct: AbstractFontConverter { + FontConverterFeatures doFeatures() const override { return FontConverterFeature::ConvertData|FontConverterFeature::ExportGlyphCache|FontConverterFeature::MultiFile; } + + std::vector>> doExportGlyphCacheToData(AbstractGlyphCache&, const std::string& filename) const override { + std::vector>> ret; + ret.emplace_back(filename, Containers::array({'\xf0'})); + return ret; + } + } converter; + + std::ostringstream out; + Error redirectError{&out}; + CORRADE_VERIFY(!converter.exportGlyphCacheToFile(dummyGlyphCache, "/some/path/that/does/not/exist")); + CORRADE_COMPARE(out.str(), + "Utility::Directory::write(): can't open /some/path/that/does/not/exist\n" + "Text::AbstractFontConverter::exportGlyphCacheToFile(): cannot write to file /some/path/that/does/not/exist\n"); +} + +void AbstractFontConverterTest::importGlyphCacheFromSingleData() { + struct: AbstractFontConverter { + FontConverterFeatures doFeatures() const override { + return FontConverterFeature::ConvertData|FontConverterFeature::ImportGlyphCache; + } Containers::Pointer doImportGlyphCacheFromSingleData(const Containers::ArrayView data) const override { if(data.size() == 1 && data[0] == '\xa5') return Containers::pointer(new DummyGlyphCache{{123, 345}}); return nullptr; } -}; + } converter; + + const char data[] = {'\xa5'}; + Containers::Pointer cache = converter.importGlyphCacheFromSingleData(data); + CORRADE_VERIFY(cache); + CORRADE_COMPARE(cache->textureSize(), (Vector2i{123, 345})); +} + +void AbstractFontConverterTest::importGlyphCacheFromData() { + struct: AbstractFontConverter { + FontConverterFeatures doFeatures() const override { + return FontConverterFeature::ConvertData|FontConverterFeature::ImportGlyphCache; + } + + Containers::Pointer doImportGlyphCacheFromData(const std::vector>>& data) const override { + if(data.size() == 2 && data[1].second.size() == 1 && data[1].second[0] == '\xa5') + return Containers::pointer(new DummyGlyphCache{{123, 345}}); + return nullptr; + } + } converter; + + const char data[] = {'\xa5'}; + Containers::Pointer cache = converter.importGlyphCacheFromData({{}, {{}, data}}); + CORRADE_VERIFY(cache); + CORRADE_COMPARE(cache->textureSize(), (Vector2i{123, 345})); +} + +void AbstractFontConverterTest::importGlyphCacheFromDataAsSingleData() { + struct: AbstractFontConverter { + FontConverterFeatures doFeatures() const override { + return FontConverterFeature::ConvertData|FontConverterFeature::ImportGlyphCache; + } + + Containers::Pointer doImportGlyphCacheFromSingleData(const Containers::ArrayView data) const override { + if(data.size() == 1 && data[0] == '\xa5') + return Containers::pointer(new DummyGlyphCache{{123, 345}}); + return nullptr; + } + } converter; -void AbstractFontConverterTest::importGlyphCacheFromSingleData() { - /* doImportFromData() should call doImportFromSingleData() */ - SingleGlyphCacheDataImporter importer; const char data[] = {'\xa5'}; - Containers::Pointer cache = importer.importGlyphCacheFromData({{{}, data}}); + Containers::Pointer cache = converter.importGlyphCacheFromData({{{}, data}}); + CORRADE_VERIFY(cache); CORRADE_COMPARE(cache->textureSize(), (Vector2i{123, 345})); } void AbstractFontConverterTest::importGlyphCacheFromFile() { + struct: AbstractFontConverter { + FontConverterFeatures doFeatures() const override { + return FontConverterFeature::ImportGlyphCache; + } + + Containers::Pointer doImportGlyphCacheFromFile(const std::string& filename) const override { + Containers::Array data = Utility::Directory::read(filename); + if(data.size() == 1 && data[0] == '\xa5') + return Containers::pointer(new DummyGlyphCache{{123, 345}}); + return nullptr; + } + } converter; + + Containers::Pointer cache = converter.importGlyphCacheFromFile(Utility::Directory::join(TEXT_TEST_DIR, "data.bin")); + CORRADE_VERIFY(cache); + CORRADE_COMPARE(cache->textureSize(), (Vector2i{123, 345})); +} + +void AbstractFontConverterTest::importGlyphCacheFromFileAsSingleData() { + struct: AbstractFontConverter { + FontConverterFeatures doFeatures() const override { + return FontConverterFeature::ConvertData|FontConverterFeature::ImportGlyphCache; + } + + Containers::Pointer doImportGlyphCacheFromSingleData(const Containers::ArrayView data) const override { + if(data.size() == 1 && data[0] == '\xa5') + return Containers::pointer(new DummyGlyphCache{{123, 345}}); + return nullptr; + } + } converter; + /* doImportFromFile() should call doImportFromSingleData() */ - SingleGlyphCacheDataImporter importer; - Containers::Pointer cache = importer.importGlyphCacheFromFile(Utility::Directory::join(TEXT_TEST_DIR, "data.bin")); + Containers::Pointer cache = converter.importGlyphCacheFromFile(Utility::Directory::join(TEXT_TEST_DIR, "data.bin")); + CORRADE_VERIFY(cache); CORRADE_COMPARE(cache->textureSize(), (Vector2i{123, 345})); } +void AbstractFontConverterTest::importGlyphCacheFromFileAsSingleDataNotFound() { + struct: AbstractFontConverter { + FontConverterFeatures doFeatures() const override { + return FontConverterFeature::ConvertData|FontConverterFeature::ImportGlyphCache; + } + + Containers::Pointer doImportGlyphCacheFromSingleData(const Containers::ArrayView) const override { + CORRADE_VERIFY(!"this shouldn't get reached"); + return {}; + } + } converter; + + std::ostringstream out; + Error redirectError{&out}; + CORRADE_VERIFY(!converter.importGlyphCacheFromFile("nonexistent.bin")); + CORRADE_COMPARE(out.str(), "Text::AbstractFontConverter::importGlyphCacheFromFile(): cannot open file nonexistent.bin\n"); +} + void AbstractFontConverterTest::debugFeature() { std::ostringstream out;