Browse Source

ShaderTools,Text,Trade: thoroughly test operation failures.

So far, even though code coverage says it's all fine, things like data
conversion failures were not tested at all, or only by checking the
return value, but without verifying that the implementation got actually
called, and without checking that no superfluous message was printed by
accident.

The AbstractFontConverter interface is tested for failures as well even
though most of it is scheduled for rework (STL removal, etc.), as
otherwise it'd be likely that I forget to test the failure cases when
simply porting the old test code to the new APIs. On the other hand, the
Audio importer interface is not touched as it's scheduled for merging
into Trade.
pull/482/merge
Vladimír Vondruš 2 weeks ago
parent
commit
66388912b7
  1. 125
      src/Magnum/ShaderTools/Test/AbstractConverterTest.cpp
  2. 343
      src/Magnum/Text/Test/AbstractFontConverterTest.cpp
  3. 329
      src/Magnum/Text/Test/AbstractFontTest.cpp
  4. 792
      src/Magnum/Trade/Test/AbstractImageConverterTest.cpp
  5. 398
      src/Magnum/Trade/Test/AbstractImporterTest.cpp
  6. 331
      src/Magnum/Trade/Test/AbstractSceneConverterTest.cpp

125
src/Magnum/ShaderTools/Test/AbstractConverterTest.cpp

@ -80,6 +80,7 @@ struct AbstractConverterTest: TestSuite::Tester {
void validateFileFailed();
void validateFileAsData();
void validateFileAsDataNotFound();
void validateFileAsDataFailed();
void validateFileNotSupported();
void validateFileNotImplemented();
void validateFilePreprocessOnly();
@ -109,6 +110,7 @@ struct AbstractConverterTest: TestSuite::Tester {
void convertFileToDataFailed();
void convertFileToDataAsData();
void convertFileToDataAsDataNotFound();
void convertFileToDataAsDataFailed();
void convertFileToDataNotSupported();
void convertFileToDataNotImplemented();
void convertFileToDataCustomDeleter();
@ -143,6 +145,7 @@ struct AbstractConverterTest: TestSuite::Tester {
void linkFilesToDataFailed();
void linkFilesToDataAsData();
void linkFilesToDataAsDataNotFound();
void linkFilesToDataAsDataFailed();
void linkFilesToDataNotSupported();
void linkFilesToDataNotImplemented();
void linkFilesToDataPreprocessOnly();
@ -232,6 +235,7 @@ AbstractConverterTest::AbstractConverterTest() {
&AbstractConverterTest::validateFileFailed,
&AbstractConverterTest::validateFileAsData,
&AbstractConverterTest::validateFileAsDataNotFound,
&AbstractConverterTest::validateFileAsDataFailed,
&AbstractConverterTest::validateFileNotSupported,
&AbstractConverterTest::validateFileNotImplemented,
&AbstractConverterTest::validateFilePreprocessOnly,
@ -261,6 +265,7 @@ AbstractConverterTest::AbstractConverterTest() {
&AbstractConverterTest::convertFileToDataFailed,
&AbstractConverterTest::convertFileToDataAsData,
&AbstractConverterTest::convertFileToDataAsDataNotFound,
&AbstractConverterTest::convertFileToDataAsDataFailed,
&AbstractConverterTest::convertFileToDataNotSupported,
&AbstractConverterTest::convertFileToDataNotImplemented,
&AbstractConverterTest::convertFileToDataCustomDeleter,
@ -295,6 +300,7 @@ AbstractConverterTest::AbstractConverterTest() {
&AbstractConverterTest::linkFilesToDataFailed,
&AbstractConverterTest::linkFilesToDataAsData,
&AbstractConverterTest::linkFilesToDataAsDataNotFound,
&AbstractConverterTest::linkFilesToDataAsDataFailed,
&AbstractConverterTest::linkFilesToDataNotSupported,
&AbstractConverterTest::linkFilesToDataNotImplemented,
&AbstractConverterTest::linkFilesToDataPreprocessOnly,
@ -705,14 +711,18 @@ void AbstractConverterTest::validateDataFailed() {
void doSetOutputFormat(Format, Containers::StringView) override {}
Containers::Pair<bool, Containers::String> doValidateData(Stage, Containers::ArrayView<const char>) override {
called = true;
return {};
}
bool called = false;
} converter;
/* The implementation is expected to print an error message on its own */
Containers::String out;
Error redirectError{&out};
CORRADE_VERIFY(!converter.validateData(Stage::MeshTask, nullptr).first());
CORRADE_VERIFY(converter.called);
CORRADE_COMPARE(out, "");
}
@ -818,14 +828,18 @@ void AbstractConverterTest::validateFileFailed() {
void doSetOutputFormat(Format, Containers::StringView) override {}
Containers::Pair<bool, Containers::String> doValidateFile(Stage, Containers::StringView) override {
called = true;
return {};
}
bool called = false;
} converter;
/* The implementation is expected to print an error message on its own */
Containers::String out;
Error redirectError{&out};
CORRADE_VERIFY(!converter.validateFile(Stage::MeshTask, {}).first());
CORRADE_VERIFY(converter.called);
CORRADE_COMPARE(out, "");
}
@ -872,6 +886,30 @@ void AbstractConverterTest::validateFileAsDataNotFound() {
TestSuite::Compare::StringHasSuffix);
}
void AbstractConverterTest::validateFileAsDataFailed() {
struct: AbstractConverter {
ConverterFeatures doFeatures() const override {
return ConverterFeature::ValidateData;
}
void doSetInputFormat(Format, Containers::StringView) override {}
void doSetOutputFormat(Format, Containers::StringView) override {}
Containers::Pair<bool, Containers::String> doValidateData(Stage, Containers::ArrayView<const char>) override {
called = true;
return {};
}
bool called = false;
} converter;
/* The implementation is expected to print an error message on its own */
Containers::String out;
Error redirectError{&out};
CORRADE_COMPARE(converter.validateFile({}, Utility::Path::join(SHADERTOOLS_TEST_DIR, "file.dat")), (Containers::Pair<bool, Containers::String>{}));
CORRADE_VERIFY(converter.called);
CORRADE_COMPARE(out, "");
}
void AbstractConverterTest::validateFileNotSupported() {
CORRADE_SKIP_IF_NO_ASSERT();
@ -974,14 +1012,18 @@ void AbstractConverterTest::convertDataToDataFailed() {
void doSetOutputFormat(Format, Containers::StringView) override {}
Containers::Optional<Containers::Array<char>> doConvertDataToData(Stage, Containers::ArrayView<const char>) override {
called = true;
return {};
}
bool called = false;
} converter;
/* The implementation is expected to print an error message on its own */
Containers::String out;
Error redirectError{&out};
CORRADE_VERIFY(!converter.convertDataToData({}, nullptr));
CORRADE_VERIFY(converter.called);
CORRADE_COMPARE(out, "");
}
@ -1074,8 +1116,11 @@ void AbstractConverterTest::convertDataToFileThroughDataFailed() {
void doSetOutputFormat(Format, Containers::StringView) override {}
Containers::Optional<Containers::Array<char>> doConvertDataToData(Stage, Containers::ArrayView<const char>) override {
called = true;
return {};
}
bool called = false;
} converter;
/* Remove previous file, if any */
@ -1089,6 +1134,7 @@ void AbstractConverterTest::convertDataToFileThroughDataFailed() {
Error redirectError{&out};
CORRADE_VERIFY(!converter.convertDataToFile({}, {}, filename));
CORRADE_VERIFY(!Utility::Path::exists(filename));
CORRADE_VERIFY(converter.called);
CORRADE_COMPARE(out, "");
}
@ -1183,14 +1229,18 @@ void AbstractConverterTest::convertFileToFileFailed() {
void doSetOutputFormat(Format, Containers::StringView) override {}
bool doConvertFileToFile(Stage, Containers::StringView, Containers::StringView) override {
called = true;
return {};
}
bool called = false;
} converter;
/* The implementation is expected to print an error message on its own */
Containers::String out;
Error redirectError{&out};
CORRADE_VERIFY(!converter.convertFileToFile({}, Utility::Path::join(SHADERTOOLS_TEST_DIR, "file.dat"), Utility::Path::join(SHADERTOOLS_TEST_OUTPUT_DIR, "file.dat")));
CORRADE_VERIFY(converter.called);
CORRADE_COMPARE(out, "");
}
@ -1249,8 +1299,11 @@ void AbstractConverterTest::convertFileToFileThroughDataFailed() {
void doSetOutputFormat(Format, Containers::StringView) override {}
Containers::Optional<Containers::Array<char>> doConvertDataToData(Stage, Containers::ArrayView<const char>) override {
called = true;
return {};
}
bool called = false;
} converter;
/* Remove previous file, if any */
@ -1264,6 +1317,7 @@ void AbstractConverterTest::convertFileToFileThroughDataFailed() {
Error redirectError{&out};
CORRADE_VERIFY(!converter.convertFileToFile({}, Utility::Path::join(SHADERTOOLS_TEST_DIR, "file.dat"), filename));
CORRADE_VERIFY(!Utility::Path::exists(filename));
CORRADE_VERIFY(converter.called);
CORRADE_COMPARE(out, "");
}
@ -1354,14 +1408,18 @@ void AbstractConverterTest::convertFileToDataFailed() {
void doSetOutputFormat(Format, Containers::StringView) override {}
Containers::Optional<Containers::Array<char>> doConvertFileToData(Stage, Containers::StringView) override {
called = true;
return {};
}
bool called = false;
} converter;
/* The implementation is expected to print an error message on its own */
Containers::String out;
Error redirectError{&out};
CORRADE_VERIFY(!converter.convertFileToData({}, Utility::Path::join(SHADERTOOLS_TEST_DIR, "file.dat")));
CORRADE_VERIFY(converter.called);
CORRADE_COMPARE(out, "");
}
@ -1407,6 +1465,30 @@ void AbstractConverterTest::convertFileToDataAsDataNotFound() {
TestSuite::Compare::StringHasSuffix);
}
void AbstractConverterTest::convertFileToDataAsDataFailed() {
struct: AbstractConverter {
ConverterFeatures doFeatures() const override {
return ConverterFeature::ConvertData;
}
void doSetInputFormat(Format, Containers::StringView) override {}
void doSetOutputFormat(Format, Containers::StringView) override {}
Containers::Optional<Containers::Array<char>> doConvertDataToData(Stage, Containers::ArrayView<const char>) override {
called = true;
return {};
}
bool called = false;
} converter;
/* The implementation is expected to print an error message on its own */
Containers::String out;
Error redirectError{&out};
CORRADE_VERIFY(!converter.convertFileToData({}, Utility::Path::join(SHADERTOOLS_TEST_DIR, "file.dat")));
CORRADE_VERIFY(converter.called);
CORRADE_COMPARE(out, "");
}
void AbstractConverterTest::convertFileToDataNotSupported() {
CORRADE_SKIP_IF_NO_ASSERT();
@ -1500,8 +1582,11 @@ void AbstractConverterTest::linkDataToDataFailed() {
void doSetOutputFormat(Format, Containers::StringView) override {}
Containers::Optional<Containers::Array<char>> doLinkDataToData(Containers::ArrayView<const Containers::Pair<Stage, Containers::ArrayView<const char>>>) override {
called = true;
return {};
}
bool called = false;
} converter;
/* The implementation is expected to print an error message on its own */
@ -1509,6 +1594,7 @@ void AbstractConverterTest::linkDataToDataFailed() {
Error redirectError{&out};
/* {{}} makes GCC 4.8 warn about zero as null pointer constant */
CORRADE_VERIFY(!converter.linkDataToData({Containers::Pair<Stage, Containers::ArrayView<const void>>{}}));
CORRADE_VERIFY(converter.called);
CORRADE_COMPARE(out, "");
}
@ -1643,8 +1729,11 @@ void AbstractConverterTest::linkDataToFileThroughDataFailed() {
void doSetOutputFormat(Format, Containers::StringView) override {}
Containers::Optional<Containers::Array<char>> doLinkDataToData(Containers::ArrayView<const Containers::Pair<Stage, Containers::ArrayView<const char>>>) override {
called = true;
return {};
}
bool called = false;
} converter;
/* Remove previous file, if any */
@ -1659,6 +1748,7 @@ void AbstractConverterTest::linkDataToFileThroughDataFailed() {
/* {{}} makes GCC 4.8 warn about zero as null pointer constant */
CORRADE_VERIFY(!converter.linkDataToFile({Containers::Pair<Stage, Containers::ArrayView<const void>>{}}, filename));
CORRADE_VERIFY(!Utility::Path::exists(filename));
CORRADE_VERIFY(converter.called);
CORRADE_COMPARE(out, "");
}
@ -1877,8 +1967,11 @@ void AbstractConverterTest::linkFilesToFileThroughDataFailed() {
void doSetOutputFormat(Format, Containers::StringView) override {}
Containers::Optional<Containers::Array<char>> doLinkDataToData(Containers::ArrayView<const Containers::Pair<Stage, Containers::ArrayView<const char>>>) override {
called = true;
return {};
}
bool called = false;
} converter;
/* Remove previous file, if any */
@ -1894,6 +1987,7 @@ void AbstractConverterTest::linkFilesToFileThroughDataFailed() {
{{}, Utility::Path::join(SHADERTOOLS_TEST_DIR, "file.dat")}
}, filename));
CORRADE_VERIFY(!Utility::Path::exists(filename));
CORRADE_VERIFY(converter.called);
CORRADE_COMPARE(out, "");
}
@ -2031,8 +2125,11 @@ void AbstractConverterTest::linkFilesToDataFailed() {
void doSetOutputFormat(Format, Containers::StringView) override {}
Containers::Optional<Containers::Array<char>> doLinkFilesToData(Containers::ArrayView<const Containers::Pair<Stage, Containers::StringView>>) override {
called = true;
return {};
}
bool called = false;
} converter;
/* The implementation is expected to print an error message on its own */
@ -2041,6 +2138,7 @@ void AbstractConverterTest::linkFilesToDataFailed() {
CORRADE_VERIFY(!converter.linkFilesToData({
{Stage::Vertex, Utility::Path::join(SHADERTOOLS_TEST_DIR, "another.dat")}
}));
CORRADE_VERIFY(converter.called);
CORRADE_COMPARE(out, "");
}
@ -2099,6 +2197,33 @@ void AbstractConverterTest::linkFilesToDataAsDataNotFound() {
TestSuite::Compare::StringHasSuffix);
}
void AbstractConverterTest::linkFilesToDataAsDataFailed() {
struct: AbstractConverter {
ConverterFeatures doFeatures() const override {
return ConverterFeature::LinkData;
}
void doSetInputFormat(Format, Containers::StringView) override {}
void doSetOutputFormat(Format, Containers::StringView) override {}
Containers::Optional<Containers::Array<char>> doLinkDataToData(Containers::ArrayView<const Containers::Pair<Stage, Containers::ArrayView<const char>>>) override {
called = true;
return {};
}
bool called = false;
} converter;
/* The implementation is expected to print an error message on its own */
Containers::String out;
Error redirectError{&out};
/* {{}} makes GCC 4.8 warn about zero as null pointer constant */
CORRADE_VERIFY(!converter.linkFilesToData({
{Stage::Fragment, Utility::Path::join(SHADERTOOLS_TEST_DIR, "file.dat")}
}));
CORRADE_VERIFY(converter.called);
CORRADE_COMPARE(out, "");
}
void AbstractConverterTest::linkFilesToDataNotSupported() {
CORRADE_SKIP_IF_NO_ASSERT();

343
src/Magnum/Text/Test/AbstractFontConverterTest.cpp

@ -53,46 +53,57 @@ struct AbstractFontConverterTest: TestSuite::Tester {
void thingNotSupported();
void exportFontToSingleData();
void exportFontToSingleDataFailed();
void exportFontToSingleDataNotImplemented();
void exportFontToSingleDataCustomDeleter();
void exportFontToSingleDataNotSingleFile();
void exportFontToData();
void exportFontToDataFailed();
void exportFontToDataNotImplemented();
void exportFontToDataCustomDeleter();
void exportFontToDataThroughSingleData();
void exportFontToDataThroughSingleDataFailed();
void exportFontToFile();
void exportFontToFileFailed();
void exportFontToFileNotImplemented();
void exportFontToFileThroughData();
void exportFontToFileThroughDataFailed();
void exportFontToFileThroughDataNotWritable();
void exportGlyphCacheToSingleData();
void exportGlyphCacheToSingleDataFailed();
void exportGlyphCacheToSingleDataNotImplemented();
void exportGlyphCacheToSingleDataCustomDeleter();
void exportGlyphCacheToSingleDataNotSingleFile();
void exportGlyphCacheToData();
void exportGlyphCacheToDataFailed();
void exportGlyphCacheToDataNotImplemented();
void exportGlyphCacheToDataCustomDeleter();
void exportGlyphCacheToDataThroughSingleData();
void exportGlyphCacheToDataThroughSingleDataFailed();
void exportGlyphCacheToFile();
void exportGlyphCacheToFileFailed();
void exportGlyphCacheToFileNotImplemented();
void exportGlyphCacheToFileThroughData();
void exportGlyphCacheToFileThroughDataFailed();
void exportGlyphCacheToFileThroughDataNotWritable();
void importGlyphCacheFromSingleData();
void importGlyphCacheFromSingleDataFailed();
void importGlyphCacheFromSingleDataNotImplemented();
void importGlyphCacheFromSingleDataNotSingleFile();
void importGlyphCacheFromData();
void importGlyphCacheFromDataFailed();
void importGlyphCacheFromDataNoData();
void importGlyphCacheFromDataNotImplemented();
void importGlyphCacheFromDataAsSingleData();
void importGlyphCacheFromDataAsSingleDataFailed();
void importGlyphCacheFromFile();
void importGlyphCacheFromFileFailed();
void importGlyphCacheFromFileNotImplemented();
void importGlyphCacheFromFileAsSingleData();
void importGlyphCacheFromFileAsSingleDataNotFound();
void importGlyphCacheFromFileAsSingleDataFailed();
void debugFeature();
void debugFeaturePacked();
@ -106,46 +117,57 @@ AbstractFontConverterTest::AbstractFontConverterTest() {
&AbstractFontConverterTest::thingNotSupported,
&AbstractFontConverterTest::exportFontToSingleData,
&AbstractFontConverterTest::exportFontToSingleDataFailed,
&AbstractFontConverterTest::exportFontToSingleDataNotImplemented,
&AbstractFontConverterTest::exportFontToSingleDataCustomDeleter,
&AbstractFontConverterTest::exportFontToSingleDataNotSingleFile,
&AbstractFontConverterTest::exportFontToData,
&AbstractFontConverterTest::exportFontToDataFailed,
&AbstractFontConverterTest::exportFontToDataNotImplemented,
&AbstractFontConverterTest::exportFontToDataCustomDeleter,
&AbstractFontConverterTest::exportFontToDataThroughSingleData,
&AbstractFontConverterTest::exportFontToDataThroughSingleDataFailed,
&AbstractFontConverterTest::exportFontToFile,
&AbstractFontConverterTest::exportFontToFileFailed,
&AbstractFontConverterTest::exportFontToFileNotImplemented,
&AbstractFontConverterTest::exportFontToFileThroughData,
&AbstractFontConverterTest::exportFontToFileThroughDataFailed,
&AbstractFontConverterTest::exportFontToFileThroughDataNotWritable,
&AbstractFontConverterTest::exportGlyphCacheToSingleData,
&AbstractFontConverterTest::exportGlyphCacheToSingleDataFailed,
&AbstractFontConverterTest::exportGlyphCacheToSingleDataNotImplemented,
&AbstractFontConverterTest::exportGlyphCacheToSingleDataCustomDeleter,
&AbstractFontConverterTest::exportGlyphCacheToSingleDataNotSingleFile,
&AbstractFontConverterTest::exportGlyphCacheToData,
&AbstractFontConverterTest::exportGlyphCacheToDataFailed,
&AbstractFontConverterTest::exportGlyphCacheToDataNotImplemented,
&AbstractFontConverterTest::exportGlyphCacheToDataCustomDeleter,
&AbstractFontConverterTest::exportGlyphCacheToDataThroughSingleData,
&AbstractFontConverterTest::exportGlyphCacheToDataThroughSingleDataFailed,
&AbstractFontConverterTest::exportGlyphCacheToFile,
&AbstractFontConverterTest::exportGlyphCacheToFileFailed,
&AbstractFontConverterTest::exportGlyphCacheToFileNotImplemented,
&AbstractFontConverterTest::exportGlyphCacheToFileThroughData,
&AbstractFontConverterTest::exportGlyphCacheToFileThroughDataFailed,
&AbstractFontConverterTest::exportGlyphCacheToFileThroughDataNotWritable,
&AbstractFontConverterTest::importGlyphCacheFromSingleData,
&AbstractFontConverterTest::importGlyphCacheFromSingleDataFailed,
&AbstractFontConverterTest::importGlyphCacheFromSingleDataNotImplemented,
&AbstractFontConverterTest::importGlyphCacheFromSingleDataNotSingleFile,
&AbstractFontConverterTest::importGlyphCacheFromData,
&AbstractFontConverterTest::importGlyphCacheFromDataFailed,
&AbstractFontConverterTest::importGlyphCacheFromDataNoData,
&AbstractFontConverterTest::importGlyphCacheFromDataNotImplemented,
&AbstractFontConverterTest::importGlyphCacheFromDataAsSingleData,
&AbstractFontConverterTest::importGlyphCacheFromDataAsSingleDataFailed,
&AbstractFontConverterTest::importGlyphCacheFromFile,
&AbstractFontConverterTest::importGlyphCacheFromFileFailed,
&AbstractFontConverterTest::importGlyphCacheFromFileNotImplemented,
&AbstractFontConverterTest::importGlyphCacheFromFileAsSingleData,
&AbstractFontConverterTest::importGlyphCacheFromFileAsSingleDataNotFound,
&AbstractFontConverterTest::importGlyphCacheFromFileAsSingleDataFailed,
&AbstractFontConverterTest::debugFeature,
&AbstractFontConverterTest::debugFeaturePacked,
@ -243,6 +265,30 @@ void AbstractFontConverterTest::exportFontToSingleData() {
TestSuite::Compare::Container);
}
void AbstractFontConverterTest::exportFontToSingleDataFailed() {
struct: AbstractFontConverter {
FontConverterFeatures doFeatures() const override {
return FontConverterFeature::ConvertData|FontConverterFeature::ExportFont;
}
Containers::Array<char> doExportFontToSingleData(AbstractFont&, AbstractGlyphCache&, const std::u32string&) const override {
called = true;
return {};
}
/** @todo drop the mutable once the APIs are reworked and no longer
const (ugh) */
mutable bool called = false;
} converter;
/* The implementation is expected to print an error message on its own */
Containers::String out;
Error redirectError{&out};
CORRADE_VERIFY(!converter.exportFontToSingleData(dummyFont, dummyGlyphCache, "euhh"));
CORRADE_VERIFY(converter.called);
CORRADE_COMPARE(out, "");
}
void AbstractFontConverterTest::exportFontToSingleDataNotImplemented() {
CORRADE_SKIP_IF_NO_ASSERT();
@ -319,6 +365,30 @@ void AbstractFontConverterTest::exportFontToData() {
TestSuite::Compare::Container);
}
void AbstractFontConverterTest::exportFontToDataFailed() {
struct: AbstractFontConverter {
FontConverterFeatures doFeatures() const override {
return FontConverterFeature::ConvertData|FontConverterFeature::ExportFont;
}
std::vector<std::pair<std::string, Containers::Array<char>>> doExportFontToData(AbstractFont&, AbstractGlyphCache&, const std::string&, const std::u32string&) const override {
called = true;
return {};
}
/** @todo drop the mutable once the APIs are reworked and no longer
const (ugh) */
mutable bool called = false;
} converter;
/* The implementation is expected to print an error message on its own */
Containers::String out;
Error redirectError{&out};
CORRADE_VERIFY(converter.exportFontToData(dummyFont, dummyGlyphCache, "", "").empty());
CORRADE_VERIFY(converter.called);
CORRADE_COMPARE(out, "");
}
void AbstractFontConverterTest::exportFontToDataNotImplemented() {
CORRADE_SKIP_IF_NO_ASSERT();
@ -384,12 +454,21 @@ void AbstractFontConverterTest::exportFontToDataThroughSingleDataFailed() {
}
Containers::Array<char> doExportFontToSingleData(AbstractFont&, AbstractGlyphCache&, const std::u32string&) const override {
called = true;
return {};
}
/** @todo drop the mutable once the APIs are reworked and no longer
const (ugh) */
mutable bool called = false;
} converter;
auto ret = converter.exportFontToData(dummyFont, dummyGlyphCache, "font.out", "ehh");
CORRADE_VERIFY(ret.empty());
/* The implementation is expected to print an error message on its own */
Containers::String out;
Error redirectError{&out};
CORRADE_VERIFY(converter.exportFontToData(dummyFont, dummyGlyphCache, "", "").empty());
CORRADE_VERIFY(converter.called);
CORRADE_COMPARE(out, "");
}
void AbstractFontConverterTest::exportFontToFile() {
@ -423,6 +502,30 @@ void AbstractFontConverterTest::exportFontToFile() {
"\xfe\x02", TestSuite::Compare::FileToString);
}
void AbstractFontConverterTest::exportFontToFileFailed() {
struct: AbstractFontConverter {
FontConverterFeatures doFeatures() const override {
return FontConverterFeature::ConvertData|FontConverterFeature::ExportFont|FontConverterFeature::MultiFile;
}
bool doExportFontToFile(AbstractFont&, AbstractGlyphCache&, const std::string&, const std::u32string&) const override {
called = true;
return false;
}
/** @todo drop the mutable once the APIs are reworked and no longer
const (ugh) */
mutable bool called = false;
} converter;
/* The implementation is expected to print an error message on its own */
Containers::String out;
Error redirectError{&out};
CORRADE_VERIFY(!converter.exportFontToFile(dummyFont, dummyGlyphCache, "", ""));
CORRADE_VERIFY(converter.called);
CORRADE_COMPARE(out, "");
}
void AbstractFontConverterTest::exportFontToFileNotImplemented() {
CORRADE_SKIP_IF_NO_ASSERT();
@ -475,7 +578,14 @@ void AbstractFontConverterTest::exportFontToFileThroughDataFailed() {
return FontConverterFeature::ConvertData|FontConverterFeature::ExportFont|FontConverterFeature::MultiFile;
}
std::vector<std::pair<std::string, Containers::Array<char>>> doExportFontToData(AbstractFont&, AbstractGlyphCache&, const std::string&, const std::u32string&) const override { return {}; }
std::vector<std::pair<std::string, Containers::Array<char>>> doExportFontToData(AbstractFont&, AbstractGlyphCache&, const std::string&, const std::u32string&) const override {
called = true;
return {};
}
/** @todo drop the mutable once the APIs are reworked and no longer
const (ugh) */
mutable bool called = false;
} converter;
Containers::String filename = Utility::Path::join(TEXT_TEST_OUTPUT_DIR, "font.out");
@ -485,11 +595,13 @@ void AbstractFontConverterTest::exportFontToFileThroughDataFailed() {
CORRADE_VERIFY(Utility::Path::remove(filename));
/* Function should fail, no file should get written and no error output
should be printed (the base implementation assumes the plugin does it) */
should be printed (the base implementation assumes the plugin does
it) */
Containers::String out;
Error redirectError{&out};
CORRADE_VERIFY(!converter.exportFontToFile(dummyFont, dummyGlyphCache, filename, {}));
CORRADE_VERIFY(!Utility::Path::exists(filename));
CORRADE_VERIFY(converter.called);
CORRADE_COMPARE(out, "");
}
@ -529,6 +641,31 @@ void AbstractFontConverterTest::exportGlyphCacheToSingleData() {
TestSuite::Compare::Container);
}
void AbstractFontConverterTest::exportGlyphCacheToSingleDataFailed() {
struct: AbstractFontConverter {
FontConverterFeatures doFeatures() const override {
return FontConverterFeature::ConvertData|
FontConverterFeature::ExportGlyphCache;
}
Containers::Array<char> doExportGlyphCacheToSingleData(AbstractGlyphCache&) const override {
called = true;
return {};
}
/** @todo drop the mutable once the APIs are reworked and no longer
const (ugh) */
mutable bool called = false;
} converter;
/* The implementation is expected to print an error message on its own */
Containers::String out;
Error redirectError{&out};
CORRADE_VERIFY(!converter.exportGlyphCacheToSingleData(dummyGlyphCache));
CORRADE_VERIFY(converter.called);
CORRADE_COMPARE(out, "");
}
void AbstractFontConverterTest::exportGlyphCacheToSingleDataNotImplemented() {
CORRADE_SKIP_IF_NO_ASSERT();
@ -604,6 +741,31 @@ void AbstractFontConverterTest::exportGlyphCacheToData() {
TestSuite::Compare::Container);
}
void AbstractFontConverterTest::exportGlyphCacheToDataFailed() {
struct: AbstractFontConverter {
FontConverterFeatures doFeatures() const override {
return FontConverterFeature::ConvertData|
FontConverterFeature::ExportGlyphCache;
}
Containers::Array<char> doExportGlyphCacheToSingleData(AbstractGlyphCache&) const override {
called = true;
return {};
}
/** @todo drop the mutable once the APIs are reworked and no longer
const (ugh) */
mutable bool called = false;
} converter;
/* The implementation is expected to print an error message on its own */
Containers::String out;
Error redirectError{&out};
CORRADE_VERIFY(converter.exportGlyphCacheToData(dummyGlyphCache, "").empty());
CORRADE_VERIFY(converter.called);
CORRADE_COMPARE(out, "");
}
void AbstractFontConverterTest::exportGlyphCacheToDataNotImplemented() {
CORRADE_SKIP_IF_NO_ASSERT();
@ -670,12 +832,21 @@ void AbstractFontConverterTest::exportGlyphCacheToDataThroughSingleDataFailed()
}
Containers::Array<char> doExportGlyphCacheToSingleData(AbstractGlyphCache&) const override {
called = true;
return {};
}
/** @todo drop the mutable once the APIs are reworked and no longer
const (ugh) */
mutable bool called = false;
} converter;
auto ret = converter.exportGlyphCacheToData(dummyGlyphCache, "font.out");
CORRADE_VERIFY(ret.empty());
/* The implementation is expected to print an error message on its own */
Containers::String out;
Error redirectError{&out};
CORRADE_VERIFY(converter.exportGlyphCacheToData(dummyGlyphCache, "").empty());
CORRADE_VERIFY(converter.called);
CORRADE_COMPARE(out, "");
}
void AbstractFontConverterTest::exportGlyphCacheToFile() {
@ -709,6 +880,32 @@ void AbstractFontConverterTest::exportGlyphCacheToFile() {
"\xfe\xed", TestSuite::Compare::FileToString);
}
void AbstractFontConverterTest::exportGlyphCacheToFileFailed() {
struct: AbstractFontConverter {
FontConverterFeatures doFeatures() const override {
return FontConverterFeature::ConvertData|
FontConverterFeature::ExportGlyphCache|
FontConverterFeature::MultiFile;
}
bool doExportGlyphCacheToFile(AbstractGlyphCache&, const std::string&) const override {
called = true;
return {};
}
/** @todo drop the mutable once the APIs are reworked and no longer
const (ugh) */
mutable bool called = false;
} converter;
/* The implementation is expected to print an error message on its own */
Containers::String out;
Error redirectError{&out};
CORRADE_VERIFY(!converter.exportGlyphCacheToFile(dummyGlyphCache, ""));
CORRADE_VERIFY(converter.called);
CORRADE_COMPARE(out, "");
}
void AbstractFontConverterTest::exportGlyphCacheToFileNotImplemented() {
CORRADE_SKIP_IF_NO_ASSERT();
@ -759,7 +956,14 @@ void AbstractFontConverterTest::exportGlyphCacheToFileThroughDataFailed() {
struct: AbstractFontConverter {
FontConverterFeatures doFeatures() const override { return FontConverterFeature::ConvertData|FontConverterFeature::ExportGlyphCache|FontConverterFeature::MultiFile; }
std::vector<std::pair<std::string, Containers::Array<char>>> doExportGlyphCacheToData(AbstractGlyphCache&, const std::string&) const override { return {}; }
std::vector<std::pair<std::string, Containers::Array<char>>> doExportGlyphCacheToData(AbstractGlyphCache&, const std::string&) const override {
called = true;
return {};
}
/** @todo drop the mutable once the APIs are reworked and no longer
const (ugh) */
mutable bool called = false;
} converter;
/* Remove previous file, if any */
@ -773,6 +977,7 @@ void AbstractFontConverterTest::exportGlyphCacheToFileThroughDataFailed() {
Error redirectError{&out};
CORRADE_VERIFY(!converter.exportGlyphCacheToFile(dummyGlyphCache, filename));
CORRADE_VERIFY(!Utility::Path::exists(filename));
CORRADE_VERIFY(converter.called);
CORRADE_COMPARE(out, "");
}
@ -814,6 +1019,31 @@ void AbstractFontConverterTest::importGlyphCacheFromSingleData() {
CORRADE_COMPARE(cache->size(), (Vector3i{123, 345, 1}));
}
void AbstractFontConverterTest::importGlyphCacheFromSingleDataFailed() {
struct: AbstractFontConverter {
FontConverterFeatures doFeatures() const override {
return FontConverterFeature::ConvertData|
FontConverterFeature::ImportGlyphCache;
}
Containers::Pointer<AbstractGlyphCache> doImportGlyphCacheFromSingleData(Containers::ArrayView<const char>) const override {
called = true;
return {};
}
/** @todo drop the mutable once the APIs are reworked and no longer
const (ugh) */
mutable bool called = false;
} converter;
/* The implementation is expected to print an error message on its own */
Containers::String out;
Error redirectError{&out};
CORRADE_VERIFY(!converter.importGlyphCacheFromSingleData(nullptr));
CORRADE_VERIFY(converter.called);
CORRADE_COMPARE(out, "");
}
void AbstractFontConverterTest::importGlyphCacheFromSingleDataNotImplemented() {
CORRADE_SKIP_IF_NO_ASSERT();
@ -863,6 +1093,31 @@ void AbstractFontConverterTest::importGlyphCacheFromData() {
CORRADE_COMPARE(cache->size(), (Vector3i{123, 345, 1}));
}
void AbstractFontConverterTest::importGlyphCacheFromDataFailed() {
struct: AbstractFontConverter {
FontConverterFeatures doFeatures() const override {
return FontConverterFeature::ConvertData|
FontConverterFeature::ImportGlyphCache;
}
Containers::Pointer<AbstractGlyphCache> doImportGlyphCacheFromData(const std::vector<std::pair<std::string, Containers::ArrayView<const char>>>&) const override {
called = true;
return {};
}
/** @todo drop the mutable once the APIs are reworked and no longer
const (ugh) */
mutable bool called = false;
} converter;
/* The implementation is expected to print an error message on its own */
Containers::String out;
Error redirectError{&out};
CORRADE_VERIFY(!converter.importGlyphCacheFromData({{}, {{}, nullptr}}));
CORRADE_VERIFY(converter.called);
CORRADE_COMPARE(out, "");
}
void AbstractFontConverterTest::importGlyphCacheFromDataNoData() {
CORRADE_SKIP_IF_NO_ASSERT();
@ -914,6 +1169,31 @@ void AbstractFontConverterTest::importGlyphCacheFromDataAsSingleData() {
CORRADE_COMPARE(cache->size(), (Vector3i{123, 345, 1}));
}
void AbstractFontConverterTest::importGlyphCacheFromDataAsSingleDataFailed() {
struct: AbstractFontConverter {
FontConverterFeatures doFeatures() const override {
return FontConverterFeature::ConvertData|
FontConverterFeature::ImportGlyphCache;
}
Containers::Pointer<AbstractGlyphCache> doImportGlyphCacheFromSingleData(const Containers::ArrayView<const char>) const override {
called = true;
return {};
}
/** @todo drop the mutable once the APIs are reworked and no longer
const (ugh) */
mutable bool called = false;
} converter;
/* The implementation is expected to print an error message on its own */
Containers::String out;
Error redirectError{&out};
CORRADE_VERIFY(!converter.importGlyphCacheFromData({{{}, nullptr}}));
CORRADE_VERIFY(converter.called);
CORRADE_COMPARE(out, "");
}
void AbstractFontConverterTest::importGlyphCacheFromFile() {
struct: AbstractFontConverter {
FontConverterFeatures doFeatures() const override {
@ -935,6 +1215,30 @@ void AbstractFontConverterTest::importGlyphCacheFromFile() {
CORRADE_COMPARE(cache->size(), (Vector3i{123, 345, 1}));
}
void AbstractFontConverterTest::importGlyphCacheFromFileFailed() {
struct: AbstractFontConverter {
FontConverterFeatures doFeatures() const override {
return FontConverterFeature::ImportGlyphCache;
}
Containers::Pointer<AbstractGlyphCache> doImportGlyphCacheFromFile(const std::string&) const override {
called = true;
return {};
}
/** @todo drop the mutable once the APIs are reworked and no longer
const (ugh) */
mutable bool called = false;
} converter;
/* The implementation is expected to print an error message on its own */
Containers::String out;
Error redirectError{&out};
CORRADE_VERIFY(!converter.importGlyphCacheFromFile(Utility::Path::join(TEXT_TEST_DIR, "data.bin")));
CORRADE_VERIFY(converter.called);
CORRADE_COMPARE(out, "");
}
void AbstractFontConverterTest::importGlyphCacheFromFileNotImplemented() {
CORRADE_SKIP_IF_NO_ASSERT();
@ -990,6 +1294,31 @@ void AbstractFontConverterTest::importGlyphCacheFromFileAsSingleDataNotFound() {
TestSuite::Compare::StringHasSuffix);
}
void AbstractFontConverterTest::importGlyphCacheFromFileAsSingleDataFailed() {
struct: AbstractFontConverter {
FontConverterFeatures doFeatures() const override {
return FontConverterFeature::ConvertData|
FontConverterFeature::ImportGlyphCache;
}
Containers::Pointer<AbstractGlyphCache> doImportGlyphCacheFromSingleData(const Containers::ArrayView<const char>) const override {
called = true;
return {};
}
/** @todo drop the mutable once the APIs are reworked and no longer
const (ugh) */
mutable bool called = false;
} converter;
/* The implementation is expected to print an error message on its own */
Containers::String out;
Error redirectError{&out};
CORRADE_VERIFY(!converter.importGlyphCacheFromFile(Utility::Path::join(TEXT_TEST_DIR, "data.bin")));
CORRADE_VERIFY(converter.called);
CORRADE_COMPARE(out, "");
}
void AbstractFontConverterTest::debugFeature() {
Containers::String out;

329
src/Magnum/Text/Test/AbstractFontTest.cpp

@ -58,9 +58,12 @@ struct AbstractFontTest: TestSuite::Tester {
void construct();
void openData();
void openDataFailed();
void openFile();
void openFileFailed();
void openFileAsData();
void openFileAsDataNotFound();
void openFileAsDataFailed();
void openFileNotImplemented();
void openDataNotSupported();
@ -74,9 +77,12 @@ struct AbstractFontTest: TestSuite::Tester {
void setFileCallbackNotImplemented();
void setFileCallbackNotSupported();
void setFileCallbackOpenFileDirectly();
void setFileCallbackOpenFileDirectlyFailed();
void setFileCallbackOpenFileThroughBaseImplementation();
void setFileCallbackOpenFileThroughBaseImplementationNotFound();
void setFileCallbackOpenFileThroughBaseImplementationFailed();
void setFileCallbackOpenFileAsData();
void setFileCallbackOpenFileAsDataNotFound();
void setFileCallbackOpenFileAsDataFailed();
void properties();
@ -133,9 +139,12 @@ AbstractFontTest::AbstractFontTest() {
addTests({&AbstractFontTest::construct,
&AbstractFontTest::openData,
&AbstractFontTest::openDataFailed,
&AbstractFontTest::openFile,
&AbstractFontTest::openFileFailed,
&AbstractFontTest::openFileAsData,
&AbstractFontTest::openFileAsDataNotFound,
&AbstractFontTest::openFileAsDataFailed,
&AbstractFontTest::openFileNotImplemented,
&AbstractFontTest::openDataNotSupported,
@ -149,9 +158,12 @@ AbstractFontTest::AbstractFontTest() {
&AbstractFontTest::setFileCallbackNotImplemented,
&AbstractFontTest::setFileCallbackNotSupported,
&AbstractFontTest::setFileCallbackOpenFileDirectly,
&AbstractFontTest::setFileCallbackOpenFileDirectlyFailed,
&AbstractFontTest::setFileCallbackOpenFileThroughBaseImplementation,
&AbstractFontTest::setFileCallbackOpenFileThroughBaseImplementationNotFound,
&AbstractFontTest::setFileCallbackOpenFileThroughBaseImplementationFailed,
&AbstractFontTest::setFileCallbackOpenFileAsData,
&AbstractFontTest::setFileCallbackOpenFileAsDataNotFound,
&AbstractFontTest::setFileCallbackOpenFileAsDataFailed,
&AbstractFontTest::properties,
@ -229,7 +241,10 @@ void AbstractFontTest::openData() {
struct: AbstractFont {
FontFeatures doFeatures() const override { return FontFeature::OpenData; }
bool doIsOpened() const override { return _opened; }
void doClose() override {}
void doClose() override {
CORRADE_VERIFY(_opened);
_opened = false;
}
Properties doOpenData(Containers::ArrayView<const char> data, Float size) override {
CORRADE_COMPARE_AS(data,
@ -257,13 +272,47 @@ void AbstractFontTest::openData() {
CORRADE_COMPARE(font.descent(), 2.0f);
CORRADE_COMPARE(font.lineHeight(), 3.0f);
CORRADE_COMPARE(font.glyphCount(), 15);
font.close();
CORRADE_VERIFY(!font.isOpened());
}
void AbstractFontTest::openDataFailed() {
struct: AbstractFont {
FontFeatures doFeatures() const override { return FontFeature::OpenData; }
bool doIsOpened() const override { return false; }
void doClose() override {}
Properties doOpenData(Containers::ArrayView<const char>, Float) override {
called = true;
return {};
}
void doGlyphIdsInto(const Containers::StridedArrayView1D<const char32_t>&, const Containers::StridedArrayView1D<UnsignedInt>&) override {}
Vector2 doGlyphSize(UnsignedInt) override { return {}; }
Vector2 doGlyphAdvance(UnsignedInt) override { return {}; }
Containers::Pointer<AbstractShaper> doCreateShaper() override { return {}; }
bool called = false;
} font;
/* The implementation is expected to print an error message on its own */
Containers::String out;
Error redirectError{&out};
CORRADE_VERIFY(!font.openData(nullptr, 1.0f));
CORRADE_VERIFY(!font.isOpened());
CORRADE_VERIFY(font.called);
CORRADE_COMPARE(out, "");
}
void AbstractFontTest::openFile() {
struct: AbstractFont {
FontFeatures doFeatures() const override { return {}; }
bool doIsOpened() const override { return _opened; }
void doClose() override {}
void doClose() override {
CORRADE_VERIFY(_opened);
_opened = false;
}
Properties doOpenFile(Containers::StringView filename, Float size) override {
CORRADE_COMPARE(filename, "hello.ttf");
@ -288,13 +337,47 @@ void AbstractFontTest::openFile() {
CORRADE_COMPARE(font.descent(), 2.0f);
CORRADE_COMPARE(font.lineHeight(), 3.0f);
CORRADE_COMPARE(font.glyphCount(), 15);
font.close();
CORRADE_VERIFY(!font.isOpened());
}
void AbstractFontTest::openFileFailed() {
struct: AbstractFont {
FontFeatures doFeatures() const override { return FontFeature::OpenData; }
bool doIsOpened() const override { return false; }
void doClose() override {}
Properties doOpenFile(Containers::StringView, Float) override {
called = true;
return {};
}
void doGlyphIdsInto(const Containers::StridedArrayView1D<const char32_t>&, const Containers::StridedArrayView1D<UnsignedInt>&) override {}
Vector2 doGlyphSize(UnsignedInt) override { return {}; }
Vector2 doGlyphAdvance(UnsignedInt) override { return {}; }
Containers::Pointer<AbstractShaper> doCreateShaper() override { return {}; }
bool called = false;
} font;
/* The implementation is expected to print an error message on its own */
Containers::String out;
Error redirectError{&out};
CORRADE_VERIFY(!font.openFile("hello.ttf", 1.0f));
CORRADE_VERIFY(!font.isOpened());
CORRADE_VERIFY(font.called);
CORRADE_COMPARE(out, "");
}
void AbstractFontTest::openFileAsData() {
struct: AbstractFont {
FontFeatures doFeatures() const override { return FontFeature::OpenData; }
bool doIsOpened() const override { return _opened; }
void doClose() override {}
void doClose() override {
CORRADE_VERIFY(_opened);
_opened = false;
}
Properties doOpenData(Containers::ArrayView<const char> data, Float size) override {
CORRADE_COMPARE_AS(data,
@ -322,6 +405,9 @@ void AbstractFontTest::openFileAsData() {
CORRADE_COMPARE(font.descent(), 2.0f);
CORRADE_COMPARE(font.lineHeight(), 3.0f);
CORRADE_COMPARE(font.glyphCount(), 15);
font.close();
CORRADE_VERIFY(!font.isOpened());
}
void AbstractFontTest::openFileAsDataNotFound() {
@ -330,6 +416,11 @@ void AbstractFontTest::openFileAsDataNotFound() {
bool doIsOpened() const override { return false; }
void doClose() override {}
Properties doOpenData(Containers::ArrayView<const char>, Float) override {
CORRADE_FAIL("This should not be called");
return {};
}
void doGlyphIdsInto(const Containers::StridedArrayView1D<const char32_t>&, const Containers::StridedArrayView1D<UnsignedInt>&) override {}
Vector2 doGlyphSize(UnsignedInt) override { return {}; }
Vector2 doGlyphAdvance(UnsignedInt) override { return {}; }
@ -339,12 +430,41 @@ void AbstractFontTest::openFileAsDataNotFound() {
Containers::String out;
Error redirectError{&out};
CORRADE_VERIFY(!font.openFile("nonexistent.foo", 12.0f));
CORRADE_VERIFY(!font.isOpened());
/* There's an error message from Path::read() before */
CORRADE_COMPARE_AS(out,
"\nText::AbstractFont::openFile(): cannot open file nonexistent.foo\n",
TestSuite::Compare::StringHasSuffix);
}
void AbstractFontTest::openFileAsDataFailed() {
struct: AbstractFont {
FontFeatures doFeatures() const override { return FontFeature::OpenData; }
bool doIsOpened() const override { return false; }
void doClose() override {}
Properties doOpenData(Containers::ArrayView<const char>, Float) override {
called = true;
return {};
}
void doGlyphIdsInto(const Containers::StridedArrayView1D<const char32_t>&, const Containers::StridedArrayView1D<UnsignedInt>&) override {}
Vector2 doGlyphSize(UnsignedInt) override { return {}; }
Vector2 doGlyphAdvance(UnsignedInt) override { return {}; }
Containers::Pointer<AbstractShaper> doCreateShaper() override { return {}; }
bool called = false;
} font;
/* The implementation is expected to print an error message on its own */
Containers::String out;
Error redirectError{&out};
CORRADE_VERIFY(!font.openData(nullptr, 1.0f));
CORRADE_VERIFY(!font.isOpened());
CORRADE_VERIFY(font.called);
CORRADE_COMPARE(out, "");
}
void AbstractFontTest::openFileNotImplemented() {
CORRADE_SKIP_IF_NO_ASSERT();
@ -624,6 +744,7 @@ void AbstractFontTest::setFileCallbackOpenFileDirectly() {
}, &dummy);
CORRADE_VERIFY(font.openFile("file.dat", 42.0f));
CORRADE_VERIFY(font.isOpened());
CORRADE_COMPARE(font.size(), 42.0f);
CORRADE_COMPARE(font.ascent(), 1.0f);
CORRADE_COMPARE(font.descent(), 2.0f);
@ -631,6 +752,44 @@ void AbstractFontTest::setFileCallbackOpenFileDirectly() {
CORRADE_COMPARE(font.glyphCount(), 15);
}
void AbstractFontTest::setFileCallbackOpenFileDirectlyFailed() {
struct: AbstractFont {
FontFeatures doFeatures() const override { return FontFeature::FileCallback|FontFeature::OpenData; }
bool doIsOpened() const override { return false; }
void doClose() override {}
Properties doOpenFile(Containers::StringView, Float) override {
called = true;
return {};
}
Properties doOpenData(Containers::ArrayView<const char>, Float) override {
CORRADE_FAIL("This should not be called");
return {};
}
void doGlyphIdsInto(const Containers::StridedArrayView1D<const char32_t>&, const Containers::StridedArrayView1D<UnsignedInt>&) override {}
Vector2 doGlyphSize(UnsignedInt) override { return {}; }
Vector2 doGlyphAdvance(UnsignedInt) override { return {}; }
Containers::Pointer<AbstractShaper> doCreateShaper() override { return {}; }
bool called = false;
} font;
font.setFileCallback([](const std::string&, InputFileCallbackPolicy, void*) -> Containers::Optional<Containers::ArrayView<const char>> {
CORRADE_FAIL("This shouldn't be called");
return {};
});
/* The implementation is expected to print an error message on its own */
Containers::String out;
Error redirectError{&out};
CORRADE_VERIFY(!font.openFile("file.dat", 42.0f));
CORRADE_VERIFY(!font.isOpened());
CORRADE_VERIFY(font.called);
CORRADE_COMPARE(out, "");
}
void AbstractFontTest::setFileCallbackOpenFileThroughBaseImplementation() {
struct: AbstractFont {
FontFeatures doFeatures() const override { return FontFeature::FileCallback|FontFeature::OpenData; }
@ -641,7 +800,7 @@ void AbstractFontTest::setFileCallbackOpenFileThroughBaseImplementation() {
CORRADE_COMPARE(filename, "file.dat");
CORRADE_VERIFY(fileCallback());
CORRADE_VERIFY(fileCallbackUserData());
openFileCalled = true;
called = true;
return AbstractFont::doOpenFile(filename, size);
}
@ -658,7 +817,7 @@ void AbstractFontTest::setFileCallbackOpenFileThroughBaseImplementation() {
Vector2 doGlyphAdvance(UnsignedInt) override { return {}; }
Containers::Pointer<AbstractShaper> doCreateShaper() override { return {}; }
bool openFileCalled = false;
bool called = false;
private:
bool _opened = false;
@ -687,7 +846,8 @@ void AbstractFontTest::setFileCallbackOpenFileThroughBaseImplementation() {
}, state);
CORRADE_VERIFY(font.openFile("file.dat", 42.0f));
CORRADE_VERIFY(font.openFileCalled);
CORRADE_VERIFY(font.isOpened());
CORRADE_VERIFY(font.called);
CORRADE_VERIFY(state.loaded);
CORRADE_VERIFY(state.closed);
CORRADE_COMPARE(font.size(), 42.0f);
@ -697,6 +857,48 @@ void AbstractFontTest::setFileCallbackOpenFileThroughBaseImplementation() {
CORRADE_COMPARE(font.glyphCount(), 15);
}
void AbstractFontTest::setFileCallbackOpenFileThroughBaseImplementationNotFound() {
struct: AbstractFont {
FontFeatures doFeatures() const override { return FontFeature::FileCallback|FontFeature::OpenData; }
bool doIsOpened() const override { return false; }
void doClose() override {}
Properties doOpenFile(Containers::StringView filename, Float size) override {
called = true;
return AbstractFont::doOpenFile(filename, size);
}
Properties doOpenData(Containers::ArrayView<const char>, Float) override {
CORRADE_FAIL("This should not be called");
return {};
}
void doGlyphIdsInto(const Containers::StridedArrayView1D<const char32_t>&, const Containers::StridedArrayView1D<UnsignedInt>&) override {}
Vector2 doGlyphSize(UnsignedInt) override { return {}; }
Vector2 doGlyphAdvance(UnsignedInt) override { return {}; }
Containers::Pointer<AbstractShaper> doCreateShaper() override { return {}; }
bool called = false;
} font;
bool fileCallbackCalled = false;
font.setFileCallback([](const std::string&, InputFileCallbackPolicy policy, bool& fileCallbackCalled) -> Containers::Optional<Containers::ArrayView<const char>> {
/* The callback should be only called to open the file, not to close it
afterwards */
CORRADE_COMPARE(policy, InputFileCallbackPolicy::LoadTemporary);
fileCallbackCalled = true;
return {};
}, fileCallbackCalled);
Containers::String out;
Error redirectError{&out};
CORRADE_VERIFY(!font.openFile("file.dat", 42.0f));
CORRADE_VERIFY(!font.isOpened());
CORRADE_VERIFY(font.called);
CORRADE_VERIFY(fileCallbackCalled);
CORRADE_COMPARE(out, "Text::AbstractFont::openFile(): cannot open file file.dat\n");
}
void AbstractFontTest::setFileCallbackOpenFileThroughBaseImplementationFailed() {
struct: AbstractFont {
FontFeatures doFeatures() const override { return FontFeature::FileCallback|FontFeature::OpenData; }
@ -708,24 +910,49 @@ void AbstractFontTest::setFileCallbackOpenFileThroughBaseImplementationFailed()
return AbstractFont::doOpenFile(filename, size);
}
Properties doOpenData(Containers::ArrayView<const char>, Float) override {
openDataCalled = true;
return {};
}
void doGlyphIdsInto(const Containers::StridedArrayView1D<const char32_t>&, const Containers::StridedArrayView1D<UnsignedInt>&) override {}
Vector2 doGlyphSize(UnsignedInt) override { return {}; }
Vector2 doGlyphAdvance(UnsignedInt) override { return {}; }
Containers::Pointer<AbstractShaper> doCreateShaper() override { return {}; }
bool openFileCalled = false;
bool openDataCalled = false;
} font;
font.setFileCallback([](const std::string&, InputFileCallbackPolicy, void*) -> Containers::Optional<Containers::ArrayView<const char>> {
struct State {
bool loaded = false;
bool closed = false;
} state;
font.setFileCallback([](const std::string&, InputFileCallbackPolicy policy, State& state) -> Containers::Optional<Containers::ArrayView<const char>> {
if(policy == InputFileCallbackPolicy::LoadTemporary) {
state.loaded = true;
return Containers::ArrayView<const char>{};
}
if(policy == InputFileCallbackPolicy::Close) {
state.closed = true;
return {};
});
}
CORRADE_FAIL("Unexpected policy" << policy);
return {};
}, state);
/* The implementation is expected to print an error message on its own */
Containers::String out;
Error redirectError{&out};
CORRADE_VERIFY(!font.openFile("file.dat", 42.0f));
CORRADE_VERIFY(!font.isOpened());
CORRADE_VERIFY(font.openFileCalled);
CORRADE_COMPARE(out, "Text::AbstractFont::openFile(): cannot open file file.dat\n");
CORRADE_VERIFY(font.openDataCalled);
CORRADE_VERIFY(state.loaded);
CORRADE_VERIFY(state.closed);
CORRADE_COMPARE(out, "");
}
void AbstractFontTest::setFileCallbackOpenFileAsData() {
@ -735,7 +962,7 @@ void AbstractFontTest::setFileCallbackOpenFileAsData() {
void doClose() override { _opened = false; }
Properties doOpenFile(Containers::StringView, Float) override {
openFileCalled = true;
CORRADE_FAIL("This should not be called");
return {};
}
@ -752,8 +979,8 @@ void AbstractFontTest::setFileCallbackOpenFileAsData() {
Vector2 doGlyphAdvance(UnsignedInt) override { return {}; }
Containers::Pointer<AbstractShaper> doCreateShaper() override { return {}; }
private:
bool _opened = false;
bool openFileCalled = false;
} font;
struct State {
@ -761,7 +988,6 @@ void AbstractFontTest::setFileCallbackOpenFileAsData() {
bool loaded = false;
bool closed = false;
} state;
font.setFileCallback([](const std::string& filename, InputFileCallbackPolicy policy, State& state) -> Containers::Optional<Containers::ArrayView<const char>> {
CORRADE_COMPARE(Containers::StringView{filename}, "file.dat");
@ -780,7 +1006,7 @@ void AbstractFontTest::setFileCallbackOpenFileAsData() {
}, state);
CORRADE_VERIFY(font.openFile("file.dat", 13.0f));
CORRADE_VERIFY(!font.openFileCalled);
CORRADE_VERIFY(font.isOpened());
CORRADE_VERIFY(state.loaded);
CORRADE_VERIFY(state.closed);
CORRADE_COMPARE(font.size(), 13.0f);
@ -790,7 +1016,7 @@ void AbstractFontTest::setFileCallbackOpenFileAsData() {
CORRADE_COMPARE(font.glyphCount(), 15);
}
void AbstractFontTest::setFileCallbackOpenFileAsDataFailed() {
void AbstractFontTest::setFileCallbackOpenFileAsDataNotFound() {
struct: AbstractFont {
FontFeatures doFeatures() const override { return FontFeature::OpenData; }
bool doIsOpened() const override { return false; }
@ -801,22 +1027,88 @@ void AbstractFontTest::setFileCallbackOpenFileAsDataFailed() {
return {};
}
Properties doOpenData(Containers::ArrayView<const char>, Float) override {
CORRADE_FAIL("This should not be called");
return {};
}
void doGlyphIdsInto(const Containers::StridedArrayView1D<const char32_t>&, const Containers::StridedArrayView1D<UnsignedInt>&) override {}
Vector2 doGlyphSize(UnsignedInt) override { return {}; }
Vector2 doGlyphAdvance(UnsignedInt) override { return {}; }
Containers::Pointer<AbstractShaper> doCreateShaper() override { return {}; }
} font;
font.setFileCallback([](const std::string&, InputFileCallbackPolicy, void*) {
return Containers::Optional<Containers::ArrayView<const char>>{};
});
bool fileCallbackCalled = false;
font.setFileCallback([](const std::string&, InputFileCallbackPolicy policy, bool& fileCallbackCalled) -> Containers::Optional<Containers::ArrayView<const char>> {
/* The callback should be only called to open the file, not to close it
afterwards */
CORRADE_COMPARE(policy, InputFileCallbackPolicy::LoadTemporary);
fileCallbackCalled = true;
return {};
}, fileCallbackCalled);
Containers::String out;
Error redirectError{&out};
CORRADE_VERIFY(!font.openFile("file.dat", 132.0f));
CORRADE_VERIFY(!font.isOpened());
CORRADE_VERIFY(fileCallbackCalled);
CORRADE_COMPARE(out, "Text::AbstractFont::openFile(): cannot open file file.dat\n");
}
void AbstractFontTest::setFileCallbackOpenFileAsDataFailed() {
struct: AbstractFont {
FontFeatures doFeatures() const override { return FontFeature::OpenData; }
bool doIsOpened() const override { return false; }
void doClose() override {}
Properties doOpenFile(Containers::StringView, Float) override {
CORRADE_FAIL("This should not be called");
return {};
}
Properties doOpenData(Containers::ArrayView<const char>, Float) override {
called = true;
return {};
}
void doGlyphIdsInto(const Containers::StridedArrayView1D<const char32_t>&, const Containers::StridedArrayView1D<UnsignedInt>&) override {}
Vector2 doGlyphSize(UnsignedInt) override { return {}; }
Vector2 doGlyphAdvance(UnsignedInt) override { return {}; }
Containers::Pointer<AbstractShaper> doCreateShaper() override { return {}; }
bool called = false;
} font;
struct State {
bool loaded = false;
bool closed = false;
} state;
font.setFileCallback([](const std::string&, InputFileCallbackPolicy policy, State& state) -> Containers::Optional<Containers::ArrayView<const char>> {
if(policy == InputFileCallbackPolicy::LoadTemporary) {
state.loaded = true;
return Containers::ArrayView<const char>{};
}
if(policy == InputFileCallbackPolicy::Close) {
state.closed = true;
return {};
}
CORRADE_FAIL("Unexpected policy" << policy);
return {};
}, state);
/* The implementation is expected to print an error message on its own */
Containers::String out;
Error redirectError{&out};
CORRADE_VERIFY(!font.openFile("file.dat", 132.0f));
CORRADE_VERIFY(!font.isOpened());
CORRADE_VERIFY(font.called);
CORRADE_VERIFY(state.loaded);
CORRADE_VERIFY(state.closed);
CORRADE_COMPARE(out, "");
}
void AbstractFontTest::properties() {
struct: AbstractFont {
FontFeatures doFeatures() const override { return FontFeature::OpenData; }
@ -837,6 +1129,7 @@ void AbstractFontTest::properties() {
} font;
CORRADE_VERIFY(font.openData(nullptr, 13.0f));
CORRADE_VERIFY(font.isOpened());
CORRADE_COMPARE(font.size(), 13.0f);
CORRADE_COMPARE(font.ascent(), 1.0f);
CORRADE_COMPARE(font.descent(), 2.0f);

792
src/Magnum/Trade/Test/AbstractImageConverterTest.cpp

File diff suppressed because it is too large Load Diff

398
src/Magnum/Trade/Test/AbstractImporterTest.cpp

@ -28,6 +28,7 @@
#include <Corrade/Containers/ArrayView.h>
#include <Corrade/Containers/Optional.h>
#include <Corrade/Containers/String.h>
#include <Corrade/Containers/StringStl.h> /** @todo remove once file callbacks are std::string-free */
#include <Corrade/TestSuite/Tester.h>
#include <Corrade/TestSuite/Compare/Container.h>
#include <Corrade/TestSuite/Compare/Numeric.h>
@ -83,6 +84,7 @@ struct AbstractImporterTest: TestSuite::Tester {
void openDataFailed();
#ifdef MAGNUM_BUILD_DEPRECATED
void openDataDeprecatedFallback();
void openDataDeprecatedFallbackFailed();
#endif
void openMemory();
void openMemoryFailed();
@ -90,6 +92,7 @@ struct AbstractImporterTest: TestSuite::Tester {
void openFileFailed();
void openFileAsData();
void openFileAsDataNotFound();
void openFileAsDataFailed();
void openState();
void openStateFailed();
@ -107,9 +110,12 @@ struct AbstractImporterTest: TestSuite::Tester {
void setFileCallbackNotImplemented();
void setFileCallbackNotSupported();
void setFileCallbackOpenFileDirectly();
void setFileCallbackOpenFileDirectlyFailed();
void setFileCallbackOpenFileThroughBaseImplementation();
void setFileCallbackOpenFileThroughBaseImplementationNotFound();
void setFileCallbackOpenFileThroughBaseImplementationFailed();
void setFileCallbackOpenFileAsData();
void setFileCallbackOpenFileAsDataNotFound();
void setFileCallbackOpenFileAsDataFailed();
void thingCountNotImplemented();
@ -407,6 +413,7 @@ AbstractImporterTest::AbstractImporterTest() {
&AbstractImporterTest::openDataFailed,
#ifdef MAGNUM_BUILD_DEPRECATED
&AbstractImporterTest::openDataDeprecatedFallback,
&AbstractImporterTest::openDataDeprecatedFallbackFailed,
#endif
&AbstractImporterTest::openMemory,
&AbstractImporterTest::openMemoryFailed,
@ -414,6 +421,7 @@ AbstractImporterTest::AbstractImporterTest() {
&AbstractImporterTest::openFileFailed,
&AbstractImporterTest::openFileAsData,
&AbstractImporterTest::openFileAsDataNotFound,
&AbstractImporterTest::openFileAsDataFailed,
&AbstractImporterTest::openState,
&AbstractImporterTest::openStateFailed,
@ -431,9 +439,12 @@ AbstractImporterTest::AbstractImporterTest() {
&AbstractImporterTest::setFileCallbackNotImplemented,
&AbstractImporterTest::setFileCallbackNotSupported,
&AbstractImporterTest::setFileCallbackOpenFileDirectly,
&AbstractImporterTest::setFileCallbackOpenFileDirectlyFailed,
&AbstractImporterTest::setFileCallbackOpenFileThroughBaseImplementation,
&AbstractImporterTest::setFileCallbackOpenFileThroughBaseImplementationNotFound,
&AbstractImporterTest::setFileCallbackOpenFileThroughBaseImplementationFailed,
&AbstractImporterTest::setFileCallbackOpenFileAsData,
&AbstractImporterTest::setFileCallbackOpenFileAsDataNotFound,
&AbstractImporterTest::setFileCallbackOpenFileAsDataFailed,
&AbstractImporterTest::thingCountNotImplemented,
@ -812,7 +823,10 @@ void AbstractImporterTest::openData() {
struct: AbstractImporter {
ImporterFeatures doFeatures() const override { return ImporterFeature::OpenData; }
bool doIsOpened() const override { return _opened; }
void doClose() override { _opened = false; }
void doClose() override {
CORRADE_VERIFY(_opened);
_opened = false;
}
void doOpenData(Containers::Array<char>&& data, DataFlags dataFlags) override {
CORRADE_COMPARE_AS(data,
@ -844,13 +858,19 @@ void AbstractImporterTest::openDataFailed() {
bool doIsOpened() const override { return false; }
void doClose() override {}
void doOpenData(Containers::Array<char>&&, DataFlags) override {}
void doOpenData(Containers::Array<char>&&, DataFlags) override {
called = true;
}
bool called = false;
} importer;
/* The implementation is expected to print an error message on its own */
Containers::String out;
Error redirectError{&out};
CORRADE_VERIFY(!importer.openData(nullptr));
CORRADE_VERIFY(!importer.isOpened());
CORRADE_VERIFY(importer.called);
CORRADE_COMPARE(out, "");
}
@ -859,7 +879,10 @@ void AbstractImporterTest::openDataDeprecatedFallback() {
struct: AbstractImporter {
ImporterFeatures doFeatures() const override { return ImporterFeature::OpenData; }
bool doIsOpened() const override { return _opened; }
void doClose() override { _opened = false; }
void doClose() override {
CORRADE_VERIFY(_opened);
_opened = false;
}
void doOpenData(Containers::ArrayView<const char> data) override {
CORRADE_COMPARE_AS(data,
@ -879,13 +902,40 @@ void AbstractImporterTest::openDataDeprecatedFallback() {
importer.close();
CORRADE_VERIFY(!importer.isOpened());
}
void AbstractImporterTest::openDataDeprecatedFallbackFailed() {
struct: AbstractImporter {
ImporterFeatures doFeatures() const override {
return ImporterFeature::OpenData;
}
bool doIsOpened() const override { return false; }
void doClose() override {}
void doOpenData(Containers::ArrayView<const char>) override {
called = true;
}
bool called = false;
} importer;
/* The implementation is expected to print an error message on its own */
Containers::String out;
Error redirectError{&out};
CORRADE_VERIFY(!importer.openData(nullptr));
CORRADE_VERIFY(!importer.isOpened());
CORRADE_VERIFY(importer.called);
CORRADE_COMPARE(out, "");
}
#endif
void AbstractImporterTest::openMemory() {
struct: AbstractImporter {
ImporterFeatures doFeatures() const override { return ImporterFeature::OpenData; }
bool doIsOpened() const override { return _opened; }
void doClose() override { _opened = false; }
void doClose() override {
CORRADE_VERIFY(_opened);
_opened = false;
}
void doOpenData(Containers::Array<char>&& data, DataFlags dataFlags) override {
CORRADE_COMPARE_AS(data,
@ -917,13 +967,19 @@ void AbstractImporterTest::openMemoryFailed() {
bool doIsOpened() const override { return false; }
void doClose() override {}
void doOpenData(Containers::Array<char>&&, DataFlags) override {}
void doOpenData(Containers::Array<char>&&, DataFlags) override {
called = true;
}
bool called = false;
} importer;
/* The implementation is expected to print an error message on its own */
Containers::String out;
Error redirectError{&out};
CORRADE_VERIFY(!importer.openMemory(nullptr));
CORRADE_VERIFY(!importer.isOpened());
CORRADE_VERIFY(importer.called);
CORRADE_COMPARE(out, "");
}
@ -931,7 +987,10 @@ void AbstractImporterTest::openFile() {
struct: AbstractImporter {
ImporterFeatures doFeatures() const override { return {}; }
bool doIsOpened() const override { return _opened; }
void doClose() override { _opened = false; }
void doClose() override {
CORRADE_VERIFY(_opened);
_opened = false;
}
void doOpenFile(Containers::StringView filename) override {
CORRADE_COMPARE(filename, "yello.foo");
@ -955,13 +1014,19 @@ void AbstractImporterTest::openFileFailed() {
bool doIsOpened() const override { return false; }
void doClose() override {}
void doOpenFile(Containers::StringView) override {}
void doOpenFile(Containers::StringView) override {
called = true;
}
bool called = false;
} importer;
/* The implementation is expected to print an error message on its own */
Containers::String out;
Error redirectError{&out};
CORRADE_VERIFY(!importer.openFile({}));
CORRADE_VERIFY(!importer.isOpened());
CORRADE_VERIFY(importer.called);
CORRADE_COMPARE(out, "");
}
@ -969,7 +1034,10 @@ void AbstractImporterTest::openFileAsData() {
struct: AbstractImporter {
ImporterFeatures doFeatures() const override { return ImporterFeature::OpenData; }
bool doIsOpened() const override { return _opened; }
void doClose() override { _opened = false; }
void doClose() override {
CORRADE_VERIFY(_opened);
_opened = false;
}
void doOpenData(Containers::Array<char>&& data, DataFlags dataFlags) override {
CORRADE_COMPARE_AS(data,
@ -996,11 +1064,11 @@ void AbstractImporterTest::openFileAsData() {
void AbstractImporterTest::openFileAsDataNotFound() {
struct Importer: AbstractImporter {
ImporterFeatures doFeatures() const override { return ImporterFeature::OpenData; }
bool doIsOpened() const override { return _opened; }
void doClose() override { _opened = false; }
bool doIsOpened() const override { return false; }
void doClose() override {}
void doOpenData(Containers::Array<char>&&, DataFlags) override {
_opened = true;
CORRADE_FAIL("This should not be called");
}
bool _opened = false;
@ -1008,7 +1076,6 @@ void AbstractImporterTest::openFileAsDataNotFound() {
Containers::String out;
Error redirectError{&out};
CORRADE_VERIFY(!importer.openFile("nonexistent.bin"));
CORRADE_VERIFY(!importer.isOpened());
/* There's an error message from Path::read() before */
@ -1017,13 +1084,40 @@ void AbstractImporterTest::openFileAsDataNotFound() {
TestSuite::Compare::StringHasSuffix);
}
void AbstractImporterTest::openFileAsDataFailed() {
struct: AbstractImporter {
ImporterFeatures doFeatures() const override {
return ImporterFeature::OpenData;
}
bool doIsOpened() const override { return false; }
void doClose() override {}
void doOpenData(Containers::Array<char>&&, DataFlags) override {
called = true;
}
bool called = false;
} importer;
/* The implementation is expected to print an error message on its own */
Containers::String out;
Error redirectError{&out};
CORRADE_VERIFY(!importer.openFile(Utility::Path::join(TRADE_TEST_DIR, "file.bin")));
CORRADE_VERIFY(!importer.isOpened());
CORRADE_VERIFY(importer.called);
CORRADE_COMPARE(out, "");
}
void AbstractImporterTest::openState() {
struct: AbstractImporter {
ImporterFeatures doFeatures() const override {
return ImporterFeature::OpenState;
}
bool doIsOpened() const override { return _opened; }
void doClose() override { _opened = false; }
void doClose() override {
CORRADE_VERIFY(_opened);
_opened = false;
}
void doOpenState(const void* state, Containers::StringView filePath) override {
CORRADE_COMPARE(state, reinterpret_cast<const void*>(std::size_t{0xbadcafe}));
@ -1050,13 +1144,19 @@ void AbstractImporterTest::openStateFailed() {
bool doIsOpened() const override { return false; }
void doClose() override {}
void doOpenState(const void*, Containers::StringView) override {}
void doOpenState(const void*, Containers::StringView) override {
called = true;
}
bool called = false;
} importer;
/* The implementation is expected to print an error message on its own */
Containers::String out;
Error redirectError{&out};
CORRADE_VERIFY(!importer.openState({}));
CORRADE_VERIFY(!importer.isOpened());
CORRADE_VERIFY(importer.called);
CORRADE_COMPARE(out, "");
}
@ -1300,23 +1400,55 @@ void AbstractImporterTest::setFileCallbackOpenFileDirectly() {
}
void doOpenData(Containers::Array<char>&&, DataFlags) override {
/* Shouldn't be called because FileCallback is supported */
openDataCalledNotSureWhy = true;
CORRADE_FAIL("This should not be called");
}
private:
bool _opened = false;
bool openDataCalledNotSureWhy = false;
} importer;
bool calledNotSureWhy = false;
importer.setFileCallback([](const std::string&, InputFileCallbackPolicy, bool& calledNotSureWhy) -> Containers::Optional<Containers::ArrayView<const char>> {
calledNotSureWhy = true;
/* The callback shouldn't be called from the class itself, it's the
doOpenFile() implementation responsibility to call it. In this case the
implementation only verifies that it's set, along with the user data. */
int dummy;
importer.setFileCallback([](const std::string&, InputFileCallbackPolicy, void*) -> Containers::Optional<Containers::ArrayView<const char>> {
CORRADE_FAIL("This shouldn't be called");
return {};
}, calledNotSureWhy);
}, &dummy);
CORRADE_VERIFY(importer.openFile("file.dat"));
CORRADE_VERIFY(!calledNotSureWhy);
CORRADE_VERIFY(!importer.openDataCalledNotSureWhy);
CORRADE_VERIFY(importer.isOpened());
}
void AbstractImporterTest::setFileCallbackOpenFileDirectlyFailed() {
struct: AbstractImporter {
ImporterFeatures doFeatures() const override { return ImporterFeature::FileCallback|ImporterFeature::OpenData; }
bool doIsOpened() const override { return false; }
void doClose() override {}
void doOpenFile(Containers::StringView) override {
called = true;
}
void doOpenData(Containers::Array<char>&&, DataFlags) override {
CORRADE_FAIL("This should not be called");
}
bool called = false;
} importer;
importer.setFileCallback([](const std::string&, InputFileCallbackPolicy, void*) -> Containers::Optional<Containers::ArrayView<const char>> {
CORRADE_FAIL("This shouldn't be called");
return {};
});
/* The implementation is expected to print an error message on its own */
Containers::String out;
Error redirectError{&out};
CORRADE_VERIFY(!importer.openFile("file.dat"));
CORRADE_VERIFY(!importer.isOpened());
CORRADE_VERIFY(importer.called);
CORRADE_COMPARE(out, "");
}
void AbstractImporterTest::setFileCallbackOpenFileThroughBaseImplementation() {
@ -1329,7 +1461,7 @@ void AbstractImporterTest::setFileCallbackOpenFileThroughBaseImplementation() {
CORRADE_COMPARE(filename, "file.dat");
CORRADE_VERIFY(fileCallback());
CORRADE_VERIFY(fileCallbackUserData());
openFileCalled = true;
called = true;
AbstractImporter::doOpenFile(filename);
}
@ -1341,37 +1473,74 @@ void AbstractImporterTest::setFileCallbackOpenFileThroughBaseImplementation() {
_opened = true;
}
bool called = false;
private:
bool _opened = false;
bool openFileCalled = false;
} importer;
struct State {
const char data = '\xb0';
bool loaded = false;
bool closed = false;
bool calledNotSureWhy = false;
} state;
importer.setFileCallback([](const std::string& filename, InputFileCallbackPolicy policy, State& state) -> Containers::Optional<Containers::ArrayView<const char>> {
if(filename == "file.dat" && policy == InputFileCallbackPolicy::LoadTemporary) {
CORRADE_COMPARE(Containers::StringView{filename}, "file.dat");
if(policy == InputFileCallbackPolicy::LoadTemporary) {
state.loaded = true;
return Containers::arrayView(&state.data, 1);
}
if(filename == "file.dat" && policy == InputFileCallbackPolicy::Close) {
if(policy == InputFileCallbackPolicy::Close) {
state.closed = true;
return {};
}
state.calledNotSureWhy = true;
CORRADE_FAIL("Unexpected policy" << policy);
return {};
}, state);
CORRADE_VERIFY(importer.openFile("file.dat"));
CORRADE_VERIFY(importer.openFileCalled);
CORRADE_VERIFY(importer.called);
CORRADE_VERIFY(state.loaded);
CORRADE_VERIFY(state.closed);
CORRADE_VERIFY(!state.calledNotSureWhy);
}
void AbstractImporterTest::setFileCallbackOpenFileThroughBaseImplementationNotFound() {
struct: AbstractImporter {
ImporterFeatures doFeatures() const override { return ImporterFeature::FileCallback|ImporterFeature::OpenData; }
bool doIsOpened() const override { return false; }
void doClose() override {}
void doOpenFile(Containers::StringView filename) override {
called = true;
AbstractImporter::doOpenFile(filename);
}
void doOpenData(Containers::Array<char>&&, DataFlags) override {
CORRADE_FAIL("This should not be called");
}
bool called = false;
} importer;
bool fileCallbackCalled = false;
importer.setFileCallback([](const std::string&, InputFileCallbackPolicy policy, bool& fileCallbackCalled) -> Containers::Optional<Containers::ArrayView<const char>> {
/* The callback should be only called to open the file, not to close it
afterwards */
CORRADE_COMPARE(policy, InputFileCallbackPolicy::LoadTemporary);
fileCallbackCalled = true;
return {};
}, fileCallbackCalled);
Containers::String out;
Error redirectError{&out};
CORRADE_VERIFY(!importer.openFile("file.dat"));
CORRADE_VERIFY(!importer.isOpened());
CORRADE_VERIFY(importer.called);
CORRADE_VERIFY(fileCallbackCalled);
CORRADE_COMPARE(out, "Trade::AbstractImporter::openFile(): cannot open file file.dat\n");
}
void AbstractImporterTest::setFileCallbackOpenFileThroughBaseImplementationFailed() {
@ -1385,19 +1554,43 @@ void AbstractImporterTest::setFileCallbackOpenFileThroughBaseImplementationFaile
AbstractImporter::doOpenFile(filename);
}
void doOpenData(Containers::Array<char>&&, DataFlags) override {
openDataCalled = true;
}
bool openFileCalled = false;
bool openDataCalled = false;
} importer;
importer.setFileCallback([](const std::string&, InputFileCallbackPolicy, void*) -> Containers::Optional<Containers::ArrayView<const char>> {
struct State {
bool loaded = false;
bool closed = false;
} state;
importer.setFileCallback([](const std::string&, InputFileCallbackPolicy policy, State& state) -> Containers::Optional<Containers::ArrayView<const char>> {
if(policy == InputFileCallbackPolicy::LoadTemporary) {
state.loaded = true;
return Containers::ArrayView<const char>{};
}
if(policy == InputFileCallbackPolicy::Close) {
state.closed = true;
return {};
});
}
CORRADE_FAIL("Unexpected policy" << policy);
return {};
}, state);
/* The implementation is expected to print an error message on its own */
Containers::String out;
Error redirectError{&out};
CORRADE_VERIFY(!importer.openFile("file.dat"));
CORRADE_VERIFY(!importer.isOpened());
CORRADE_VERIFY(importer.openFileCalled);
CORRADE_COMPARE(out, "Trade::AbstractImporter::openFile(): cannot open file file.dat\n");
CORRADE_VERIFY(importer.openDataCalled);
CORRADE_VERIFY(state.loaded);
CORRADE_VERIFY(state.closed);
CORRADE_COMPARE(out, "");
}
void AbstractImporterTest::setFileCallbackOpenFileAsData() {
@ -1407,7 +1600,7 @@ void AbstractImporterTest::setFileCallbackOpenFileAsData() {
void doClose() override { _opened = false; }
void doOpenFile(Containers::StringView) override {
openFileCalled = true;
CORRADE_FAIL("This should not be called");
}
void doOpenData(Containers::Array<char>&& data, DataFlags dataFlags) override {
@ -1418,64 +1611,117 @@ void AbstractImporterTest::setFileCallbackOpenFileAsData() {
_opened = true;
}
private:
bool _opened = false;
bool openFileCalled = false;
} importer;
struct State {
const char data = '\xb0';
bool loaded = false;
bool closed = false;
bool calledNotSureWhy = false;
} state;
importer.setFileCallback([](const std::string& filename, InputFileCallbackPolicy policy, State& state) -> Containers::Optional<Containers::ArrayView<const char>> {
if(filename == "file.dat" && policy == InputFileCallbackPolicy::LoadTemporary) {
CORRADE_COMPARE(Containers::StringView{filename}, "file.dat");
if(policy == InputFileCallbackPolicy::LoadTemporary) {
state.loaded = true;
return Containers::arrayView(&state.data, 1);
}
if(filename == "file.dat" && policy == InputFileCallbackPolicy::Close) {
if(policy == InputFileCallbackPolicy::Close) {
state.closed = true;
return {};
}
state.calledNotSureWhy = true;
CORRADE_FAIL("Unexpected policy" << policy);
return {};
}, state);
CORRADE_VERIFY(importer.openFile("file.dat"));
CORRADE_VERIFY(!importer.openFileCalled);
CORRADE_VERIFY(state.loaded);
CORRADE_VERIFY(state.closed);
CORRADE_VERIFY(!state.calledNotSureWhy);
}
void AbstractImporterTest::setFileCallbackOpenFileAsDataFailed() {
void AbstractImporterTest::setFileCallbackOpenFileAsDataNotFound() {
struct: AbstractImporter {
ImporterFeatures doFeatures() const override { return ImporterFeature::OpenData; }
bool doIsOpened() const override { return false; }
void doClose() override {}
void doOpenFile(Containers::StringView) override {
openFileCalled = true;
CORRADE_FAIL("This should not be called");
}
bool openFileCalled = false;
void doOpenData(Containers::Array<char>&&, DataFlags) override {
CORRADE_FAIL("This should not be called");
}
} importer;
importer.setFileCallback([](const std::string&, InputFileCallbackPolicy, void*) {
return Containers::Optional<Containers::ArrayView<const char>>{};
});
bool fileCallbackCalled = false;
importer.setFileCallback([](const std::string&, InputFileCallbackPolicy policy, bool& fileCallbackCalled) -> Containers::Optional<Containers::ArrayView<const char>> {
/* The callback should be only called to open the file, not to close it
afterwards */
CORRADE_COMPARE(policy, InputFileCallbackPolicy::LoadTemporary);
fileCallbackCalled = true;
return {};
}, fileCallbackCalled);
Containers::String out;
Error redirectError{&out};
CORRADE_VERIFY(!importer.openFile("file.dat"));
CORRADE_VERIFY(!importer.openFileCalled);
CORRADE_VERIFY(!importer.isOpened());
CORRADE_VERIFY(fileCallbackCalled);
CORRADE_COMPARE(out, "Trade::AbstractImporter::openFile(): cannot open file file.dat\n");
}
void AbstractImporterTest::setFileCallbackOpenFileAsDataFailed() {
struct: AbstractImporter {
ImporterFeatures doFeatures() const override { return ImporterFeature::OpenData; }
bool doIsOpened() const override { return false; }
void doClose() override {}
void doOpenFile(Containers::StringView) override {
CORRADE_FAIL("This should not be called");
}
void doOpenData(Containers::Array<char>&&, DataFlags) override {
called = true;
}
bool called = false;
} importer;
struct State {
bool loaded = false;
bool closed = false;
} state;
importer.setFileCallback([](const std::string&, InputFileCallbackPolicy policy, State& state) -> Containers::Optional<Containers::ArrayView<const char>> {
if(policy == InputFileCallbackPolicy::LoadTemporary) {
state.loaded = true;
return Containers::ArrayView<const char>{};
}
if(policy == InputFileCallbackPolicy::Close) {
state.closed = true;
return {};
}
CORRADE_FAIL("Unexpected policy" << policy);
return {};
}, state);
/* The implementation is expected to print an error message on its own */
Containers::String out;
Error redirectError{&out};
CORRADE_VERIFY(!importer.openFile("file.dat"));
CORRADE_VERIFY(!importer.isOpened());
CORRADE_VERIFY(importer.called);
CORRADE_VERIFY(state.loaded);
CORRADE_VERIFY(state.closed);
CORRADE_COMPARE(out, "");
}
void AbstractImporterTest::thingCountNotImplemented() {
struct: AbstractImporter {
ImporterFeatures doFeatures() const override { return {}; }
@ -1908,14 +2154,18 @@ void AbstractImporterTest::sceneFailed() {
UnsignedInt doSceneCount() const override { return 1; }
Containers::Optional<SceneData> doScene(UnsignedInt) override {
called = true;
return {};
}
bool called = false;
} importer;
/* The implementation is expected to print an error message on its own */
Containers::String out;
Error redirectError{&out};
CORRADE_VERIFY(!importer.scene(0));
CORRADE_VERIFY(importer.called);
CORRADE_COMPARE(out, "");
}
@ -3881,14 +4131,18 @@ void AbstractImporterTest::animationFailed() {
UnsignedInt doAnimationCount() const override { return 1; }
Containers::Optional<AnimationData> doAnimation(UnsignedInt) override {
called = true;
return {};
}
bool called = false;
} importer;
/* The implementation is expected to print an error message on its own */
Containers::String out;
Error redirectError{&out};
CORRADE_VERIFY(!importer.animation(0));
CORRADE_VERIFY(importer.called);
CORRADE_COMPARE(out, "");
}
@ -4204,14 +4458,18 @@ void AbstractImporterTest::lightFailed() {
UnsignedInt doLightCount() const override { return 1; }
Containers::Optional<LightData> doLight(UnsignedInt) override {
called = true;
return {};
}
bool called = false;
} importer;
/* The implementation is expected to print an error message on its own */
Containers::String out;
Error redirectError{&out};
CORRADE_VERIFY(!importer.light(0));
CORRADE_VERIFY(importer.called);
CORRADE_COMPARE(out, "");
}
@ -4363,14 +4621,18 @@ void AbstractImporterTest::cameraFailed() {
UnsignedInt doCameraCount() const override { return 1; }
Containers::Optional<CameraData> doCamera(UnsignedInt) override {
called = true;
return {};
}
bool called = false;
} importer;
/* The implementation is expected to print an error message on its own */
Containers::String out;
Error redirectError{&out};
CORRADE_VERIFY(!importer.camera(0));
CORRADE_VERIFY(importer.called);
CORRADE_COMPARE(out, "");
}
@ -5054,14 +5316,18 @@ void AbstractImporterTest::skin2DFailed() {
UnsignedInt doSkin2DCount() const override { return 1; }
Containers::Optional<SkinData2D> doSkin2D(UnsignedInt) override {
called = true;
return {};
}
bool called = false;
} importer;
/* The implementation is expected to print an error message on its own */
Containers::String out;
Error redirectError{&out};
CORRADE_VERIFY(!importer.skin2D(0));
CORRADE_VERIFY(importer.called);
CORRADE_COMPARE(out, "");
}
@ -5293,14 +5559,18 @@ void AbstractImporterTest::skin3DFailed() {
UnsignedInt doSkin3DCount() const override { return 1; }
Containers::Optional<SkinData3D> doSkin3D(UnsignedInt) override {
called = true;
return {};
}
bool called = false;
} importer;
/* The implementation is expected to print an error message on its own */
Containers::String out;
Error redirectError{&out};
CORRADE_VERIFY(!importer.skin3D(0));
CORRADE_VERIFY(importer.called);
CORRADE_COMPARE(out, "");
}
@ -5537,14 +5807,18 @@ void AbstractImporterTest::meshFailed() {
UnsignedInt doMeshCount() const override { return 1; }
Containers::Optional<MeshData> doMesh(UnsignedInt, UnsignedInt) override {
called = true;
return {};
}
bool called = false;
} importer;
/* The implementation is expected to print an error message on its own */
Containers::String out;
Error redirectError{&out};
CORRADE_VERIFY(!importer.mesh(0));
CORRADE_VERIFY(importer.called);
CORRADE_COMPARE(out, "");
}
@ -6429,14 +6703,18 @@ void AbstractImporterTest::materialFailed() {
UnsignedInt doMaterialCount() const override { return 1; }
Containers::Optional<MaterialData> doMaterial(UnsignedInt) override {
called = true;
return {};
}
bool called = false;
} importer;
/* The implementation is expected to print an error message on its own */
Containers::String out;
Error redirectError{&out};
CORRADE_VERIFY(!importer.material(0));
CORRADE_VERIFY(importer.called);
CORRADE_COMPARE(out, "");
}
@ -6709,14 +6987,18 @@ void AbstractImporterTest::textureFailed() {
UnsignedInt doTextureCount() const override { return 1; }
Containers::Optional<TextureData> doTexture(UnsignedInt) override {
called = true;
return {};
}
bool called = false;
} importer;
/* The implementation is expected to print an error message on its own */
Containers::String out;
Error redirectError{&out};
CORRADE_VERIFY(!importer.texture(0));
CORRADE_VERIFY(importer.called);
CORRADE_COMPARE(out, "");
}
@ -6873,14 +7155,18 @@ void AbstractImporterTest::image1DFailed() {
UnsignedInt doImage1DCount() const override { return 1; }
Containers::Optional<ImageData1D> doImage1D(UnsignedInt, UnsignedInt) override {
called = true;
return {};
}
bool called = false;
} importer;
/* The implementation is expected to print an error message on its own */
Containers::String out;
Error redirectError{&out};
CORRADE_VERIFY(!importer.image1D(0));
CORRADE_VERIFY(importer.called);
CORRADE_COMPARE(out, "");
}
@ -7177,14 +7463,18 @@ void AbstractImporterTest::image2DFailed() {
UnsignedInt doImage2DCount() const override { return 1; }
Containers::Optional<ImageData2D> doImage2D(UnsignedInt, UnsignedInt) override {
called = true;
return {};
}
bool called = false;
} importer;
/* The implementation is expected to print an error message on its own */
Containers::String out;
Error redirectError{&out};
CORRADE_VERIFY(!importer.image2D(0));
CORRADE_VERIFY(importer.called);
CORRADE_COMPARE(out, "");
}
@ -7481,14 +7771,18 @@ void AbstractImporterTest::image3DFailed() {
UnsignedInt doImage3DCount() const override { return 1; }
Containers::Optional<ImageData3D> doImage3D(UnsignedInt, UnsignedInt) override {
called = true;
return {};
}
bool called = false;
} importer;
/* The implementation is expected to print an error message on its own */
Containers::String out;
Error redirectError{&out};
CORRADE_VERIFY(!importer.image3D(0));
CORRADE_VERIFY(importer.called);
CORRADE_COMPARE(out, "");
}

331
src/Magnum/Trade/Test/AbstractSceneConverterTest.cpp

@ -208,6 +208,7 @@ struct AbstractSceneConverterTest: TestSuite::Tester {
void addMeshLevelsNotImplemented();
void addMeshThroughLevels();
void addMeshThroughLevelsFailed();
void setMeshAttributeName();
void setMeshAttributeNameNotImplemented();
@ -284,6 +285,9 @@ struct AbstractSceneConverterTest: TestSuite::Tester {
void addImage1DThroughLevels();
void addImage2DThroughLevels();
void addImage3DThroughLevels();
void addImage1DThroughLevelsFailed();
void addImage2DThroughLevelsFailed();
void addImage3DThroughLevelsFailed();
void addImporterContents();
void addImporterContentsCustomSceneFields();
@ -771,7 +775,8 @@ AbstractSceneConverterTest::AbstractSceneConverterTest() {
&AbstractSceneConverterTest::addMeshLevelsNoLevels,
&AbstractSceneConverterTest::addMeshLevelsNotImplemented,
&AbstractSceneConverterTest::addMeshThroughLevels});
&AbstractSceneConverterTest::addMeshThroughLevels,
&AbstractSceneConverterTest::addMeshThroughLevelsFailed});
addInstancedTests({&AbstractSceneConverterTest::setMeshAttributeName},
Containers::arraySize(SetMeshAttributeData));
@ -839,7 +844,10 @@ AbstractSceneConverterTest::AbstractSceneConverterTest() {
&AbstractSceneConverterTest::addImage1DThroughLevels,
&AbstractSceneConverterTest::addImage2DThroughLevels,
&AbstractSceneConverterTest::addImage3DThroughLevels});
&AbstractSceneConverterTest::addImage3DThroughLevels,
&AbstractSceneConverterTest::addImage1DThroughLevelsFailed,
&AbstractSceneConverterTest::addImage2DThroughLevelsFailed,
&AbstractSceneConverterTest::addImage3DThroughLevelsFailed});
addInstancedTests({&AbstractSceneConverterTest::addImporterContents},
Containers::arraySize(AddImporterContentsData));
@ -1245,14 +1253,18 @@ void AbstractSceneConverterTest::convertMeshFailed() {
}
Containers::Optional<MeshData> doConvert(const MeshData&) override {
called = true;
return {};
}
bool called = false;
} converter;
/* The implementation is expected to print an error message on its own */
Containers::String out;
Error redirectError{&out};
CORRADE_VERIFY(!converter.convert(MeshData{MeshPrimitive::Triangles, 0}));
CORRADE_VERIFY(converter.called);
CORRADE_COMPARE(out, "");
}
@ -1408,8 +1420,11 @@ void AbstractSceneConverterTest::convertMeshInPlaceFailed() {
}
bool doConvertInPlace(MeshData&) override {
called = true;
return {};
}
bool called = false;
} converter;
MeshData mesh{MeshPrimitive::Triangles, 0};
@ -1418,6 +1433,7 @@ void AbstractSceneConverterTest::convertMeshInPlaceFailed() {
Containers::String out;
Error redirectError{&out};
CORRADE_VERIFY(!converter.convertInPlace(mesh));
CORRADE_VERIFY(converter.called);
CORRADE_COMPARE(out, "");
}
@ -1457,14 +1473,18 @@ void AbstractSceneConverterTest::convertMeshToDataFailed() {
}
Containers::Optional<Containers::Array<char>> doConvertToData(const MeshData&) override {
called = true;
return {};
}
bool called = false;
} converter;
/* The implementation is expected to print an error message on its own */
Containers::String out;
Error redirectError{&out};
CORRADE_VERIFY(!converter.convertToData(MeshData{MeshPrimitive::Triangles, 0}));
CORRADE_VERIFY(converter.called);
CORRADE_COMPARE(out, "");
}
@ -1515,6 +1535,7 @@ void AbstractSceneConverterTest::convertMeshToDataThroughBatchAddFailed() {
bool doBeginData() override { return true; }
bool doAdd(UnsignedInt, const MeshData&, Containers::StringView) override {
called = true;
return false;
}
@ -1522,6 +1543,8 @@ void AbstractSceneConverterTest::convertMeshToDataThroughBatchAddFailed() {
CORRADE_FAIL("doEndData() shouldn't be called");
return {};
}
bool called = false;
} converter;
/* The implementation is expected to print an error message on its own */
@ -1529,6 +1552,7 @@ void AbstractSceneConverterTest::convertMeshToDataThroughBatchAddFailed() {
Error redirectError{&out};
CORRADE_VERIFY(!converter.convertToData(MeshData{MeshPrimitive::Triangles, 6}));
CORRADE_VERIFY(!converter.isConverting());
CORRADE_VERIFY(converter.called);
CORRADE_COMPARE(out, "");
}
@ -1546,8 +1570,11 @@ void AbstractSceneConverterTest::convertMeshToDataThroughBatchEndFailed() {
}
Containers::Optional<Containers::Array<char>> doEndData() override {
called = true;
return {};
}
bool called = false;
} converter;
/* The implementation is expected to print an error message on its own */
@ -1555,6 +1582,7 @@ void AbstractSceneConverterTest::convertMeshToDataThroughBatchEndFailed() {
Error redirectError{&out};
CORRADE_VERIFY(!converter.convertToData(MeshData{MeshPrimitive::Triangles, 6}));
CORRADE_VERIFY(!converter.isConverting());
CORRADE_VERIFY(converter.called);
CORRADE_COMPARE(out, "");
}
@ -1654,14 +1682,18 @@ void AbstractSceneConverterTest::convertMeshToFileFailed() {
}
bool doConvertToFile(const MeshData&, Containers::StringView) override {
called = true;
return false;
}
bool called = false;
} converter;
/* The implementation is expected to print an error message on its own */
Containers::String out;
Error redirectError{&out};
CORRADE_VERIFY(!converter.convertToFile(MeshData{MeshPrimitive::Triangles, 0}, Utility::Path::join(TRADE_TEST_OUTPUT_DIR, "mesh.out")));
CORRADE_VERIFY(!converter.convertToFile(MeshData{MeshPrimitive::Triangles, 0}, ""));
CORRADE_VERIFY(converter.called);
CORRADE_COMPARE(out, "");
}
@ -1690,8 +1722,11 @@ void AbstractSceneConverterTest::convertMeshToFileThroughDataFailed() {
SceneConverterFeatures doFeatures() const override { return SceneConverterFeature::ConvertMeshToData; }
Containers::Optional<Containers::Array<char>> doConvertToData(const MeshData&) override {
called = true;
return {};
}
bool called = false;
} converter;
/* Remove previous file, if any */
@ -1705,6 +1740,7 @@ void AbstractSceneConverterTest::convertMeshToFileThroughDataFailed() {
Error redirectError{&out};
CORRADE_VERIFY(!converter.convertToFile(MeshData{MeshPrimitive::Triangles, 0xef}, filename));
CORRADE_VERIFY(!Utility::Path::exists(filename));
CORRADE_VERIFY(converter.called);
CORRADE_COMPARE(out, "");
}
@ -1780,6 +1816,7 @@ void AbstractSceneConverterTest::convertMeshToFileThroughBatchAddFailed() {
bool doBeginFile(Containers::StringView) override { return true; }
bool doAdd(UnsignedInt, const MeshData&, Containers::StringView) override {
called = true;
return false;
}
@ -1787,6 +1824,8 @@ void AbstractSceneConverterTest::convertMeshToFileThroughBatchAddFailed() {
CORRADE_FAIL("doEndFile() shouldn't be called");
return {};
}
bool called = false;
} converter;
/* The implementation is expected to print an error message on its own */
@ -1794,6 +1833,7 @@ void AbstractSceneConverterTest::convertMeshToFileThroughBatchAddFailed() {
Error redirectError{&out};
CORRADE_VERIFY(!converter.convertToFile(MeshData{MeshPrimitive::Triangles, 0xfc}, Utility::Path::join(TRADE_TEST_OUTPUT_DIR, "mesh.out")));
CORRADE_VERIFY(!converter.isConverting());
CORRADE_VERIFY(converter.called);
CORRADE_COMPARE(out, "");
}
@ -1811,8 +1851,11 @@ void AbstractSceneConverterTest::convertMeshToFileThroughBatchEndFailed() {
}
bool doEndFile(Containers::StringView) override {
called = true;
return {};
}
bool called = false;
} converter;
/* The implementation is expected to print an error message on its own */
@ -1820,6 +1863,7 @@ void AbstractSceneConverterTest::convertMeshToFileThroughBatchEndFailed() {
Error redirectError{&out};
CORRADE_VERIFY(!converter.convertToFile(MeshData{MeshPrimitive::Triangles, 0xfc}, Utility::Path::join(TRADE_TEST_OUTPUT_DIR, "mesh.out")));
CORRADE_VERIFY(!converter.isConverting());
CORRADE_VERIFY(converter.called);
CORRADE_COMPARE(out, "");
}
@ -1887,13 +1931,19 @@ void AbstractSceneConverterTest::beginFailed() {
return SceneConverterFeature::ConvertMultiple;
}
bool doBegin() override { return false; }
bool doBegin() override {
called = true;
return false;
}
bool called = false;
} converter;
/* The implementation is expected to print an error message on its own */
Containers::String out;
Error redirectError{&out};
CORRADE_VERIFY(!converter.begin());
CORRADE_VERIFY(converter.called);
CORRADE_COMPARE(out, "");
CORRADE_VERIFY(!converter.isConverting());
@ -1908,8 +1958,11 @@ void AbstractSceneConverterTest::endFailed() {
bool doBegin() override { return true; }
Containers::Pointer<AbstractImporter> doEnd() override {
called = true;
return nullptr;
}
bool called = false;
} converter;
CORRADE_VERIFY(converter.begin());
@ -1918,6 +1971,7 @@ void AbstractSceneConverterTest::endFailed() {
Containers::String out;
Error redirectError{&out};
CORRADE_VERIFY(!converter.end());
CORRADE_VERIFY(converter.called);
CORRADE_COMPARE(out, "");
CORRADE_VERIFY(!converter.isConverting());
@ -2001,13 +2055,19 @@ void AbstractSceneConverterTest::beginDataFailed() {
return SceneConverterFeature::ConvertMultipleToData;
}
bool doBeginData() override { return false; }
bool doBeginData() override {
called = true;
return false;
}
bool called = false;
} converter;
/* The implementation is expected to print an error message on its own */
Containers::String out;
Error redirectError{&out};
CORRADE_VERIFY(!converter.beginData());
CORRADE_VERIFY(converter.called);
CORRADE_COMPARE(out, "");
CORRADE_VERIFY(!converter.isConverting());
@ -2022,8 +2082,11 @@ void AbstractSceneConverterTest::endDataFailed() {
bool doBeginData() override { return true; }
Containers::Optional<Containers::Array<char>> doEndData() override {
called = true;
return {};
}
bool called = false;
} converter;
CORRADE_VERIFY(converter.beginData());
@ -2032,6 +2095,7 @@ void AbstractSceneConverterTest::endDataFailed() {
Containers::String out;
Error redirectError{&out};
CORRADE_VERIFY(!converter.endData());
CORRADE_VERIFY(converter.called);
CORRADE_COMPARE(out, "");
CORRADE_VERIFY(!converter.isConverting());
@ -2143,13 +2207,19 @@ void AbstractSceneConverterTest::beginFileFailed() {
return SceneConverterFeature::ConvertMultipleToFile;
}
bool doBeginFile(Containers::StringView) override { return false; }
bool doBeginFile(Containers::StringView) override {
called = true;
return false;
}
bool called = false;
} converter;
/* The implementation is expected to print an error message on its own */
Containers::String out;
Error redirectError{&out};
CORRADE_VERIFY(!converter.beginFile("file.gltf"));
CORRADE_VERIFY(converter.called);
CORRADE_COMPARE(out, "");
CORRADE_VERIFY(!converter.isConverting());
@ -2163,7 +2233,12 @@ void AbstractSceneConverterTest::endFileFailed() {
bool doBeginFile(Containers::StringView) override { return true; }
bool doEndFile(Containers::StringView) override { return false; }
bool doEndFile(Containers::StringView) override {
called = true;
return false;
}
bool called = false;
} converter;
CORRADE_VERIFY(converter.beginFile("file.gltf"));
@ -2172,6 +2247,7 @@ void AbstractSceneConverterTest::endFileFailed() {
Containers::String out;
Error redirectError{&out};
CORRADE_VERIFY(!converter.endFile());
CORRADE_VERIFY(converter.called);
CORRADE_COMPARE(out, "");
CORRADE_VERIFY(!converter.isConverting());
@ -2212,8 +2288,11 @@ void AbstractSceneConverterTest::beginEndFileThroughDataFailed() {
bool doBeginData() override { return true; }
Containers::Optional<Containers::Array<char>> doEndData() override {
called = true;
return {};
}
bool called = false;
} converter;
/* Remove previous file, if any */
@ -2230,6 +2309,7 @@ void AbstractSceneConverterTest::beginEndFileThroughDataFailed() {
CORRADE_VERIFY(!converter.endFile());
CORRADE_VERIFY(!converter.isConverting());
CORRADE_VERIFY(!Utility::Path::exists(filename));
CORRADE_VERIFY(converter.called);
CORRADE_COMPARE(out, "");
}
@ -2800,8 +2880,11 @@ void AbstractSceneConverterTest::addSceneFailed() {
bool doBegin() override { return true; }
bool doAdd(UnsignedInt, const SceneData&, Containers::StringView) override {
called = true;
return false;
}
bool called = false;
} converter;
CORRADE_VERIFY(converter.begin());
@ -2812,6 +2895,7 @@ void AbstractSceneConverterTest::addSceneFailed() {
Containers::String out;
Error redirectError{&out};
CORRADE_VERIFY(!converter.add(SceneData{SceneMappingType::UnsignedInt, 0, nullptr, nullptr}));
CORRADE_VERIFY(converter.called);
CORRADE_COMPARE(out, "");
}
@ -3066,8 +3150,11 @@ void AbstractSceneConverterTest::addAnimationFailed() {
bool doBegin() override { return true; }
bool doAdd(UnsignedInt, const AnimationData&, Containers::StringView) override {
called = true;
return false;
}
bool called = false;
} converter;
CORRADE_VERIFY(converter.begin());
@ -3078,6 +3165,7 @@ void AbstractSceneConverterTest::addAnimationFailed() {
Containers::String out;
Error redirectError{&out};
CORRADE_VERIFY(!converter.add(AnimationData{nullptr, nullptr}));
CORRADE_VERIFY(converter.called);
CORRADE_COMPARE(out, "");
}
@ -3210,8 +3298,11 @@ void AbstractSceneConverterTest::addLightFailed() {
bool doBegin() override { return true; }
bool doAdd(UnsignedInt, const LightData&, Containers::StringView) override {
called = true;
return false;
}
bool called = false;
} converter;
CORRADE_VERIFY(converter.begin());
@ -3222,6 +3313,7 @@ void AbstractSceneConverterTest::addLightFailed() {
Containers::String out;
Error redirectError{&out};
CORRADE_VERIFY(!converter.add(LightData{LightType::Point, {}, 0.0f}));
CORRADE_VERIFY(converter.called);
CORRADE_COMPARE(out, "");
}
@ -3293,8 +3385,11 @@ void AbstractSceneConverterTest::addCameraFailed() {
bool doBegin() override { return true; }
bool doAdd(UnsignedInt, const CameraData&, Containers::StringView) override {
called = true;
return false;
}
bool called = false;
} converter;
CORRADE_VERIFY(converter.begin());
@ -3305,6 +3400,7 @@ void AbstractSceneConverterTest::addCameraFailed() {
Containers::String out;
Error redirectError{&out};
CORRADE_VERIFY(!converter.add(CameraData{CameraType::Orthographic3D, {}, 0.0f, 1.0f}));
CORRADE_VERIFY(converter.called);
CORRADE_COMPARE(out, "");
}
@ -3376,8 +3472,11 @@ void AbstractSceneConverterTest::addSkin2DFailed() {
bool doBegin() override { return true; }
bool doAdd(UnsignedInt, const SkinData2D&, Containers::StringView) override {
called = true;
return false;
}
bool called = false;
} converter;
CORRADE_VERIFY(converter.begin());
@ -3388,6 +3487,7 @@ void AbstractSceneConverterTest::addSkin2DFailed() {
Containers::String out;
Error redirectError{&out};
CORRADE_VERIFY(!converter.add(SkinData2D{nullptr, nullptr}));
CORRADE_VERIFY(converter.called);
CORRADE_COMPARE(out, "");
}
@ -3459,8 +3559,11 @@ void AbstractSceneConverterTest::addSkin3DFailed() {
bool doBegin() override { return true; }
bool doAdd(UnsignedInt, const SkinData3D&, Containers::StringView) override {
called = true;
return false;
}
bool called = false;
} converter;
CORRADE_VERIFY(converter.begin());
@ -3471,6 +3574,7 @@ void AbstractSceneConverterTest::addSkin3DFailed() {
Containers::String out;
Error redirectError{&out};
CORRADE_VERIFY(!converter.add(SkinData3D{nullptr, nullptr}));
CORRADE_VERIFY(converter.called);
CORRADE_COMPARE(out, "");
}
@ -3542,8 +3646,11 @@ void AbstractSceneConverterTest::addMeshFailed() {
bool doBegin() override { return true; }
bool doAdd(UnsignedInt, const MeshData&, Containers::StringView) override {
called = true;
return false;
}
bool called = false;
} converter;
CORRADE_VERIFY(converter.begin());
@ -3554,6 +3661,7 @@ void AbstractSceneConverterTest::addMeshFailed() {
Containers::String out;
Error redirectError{&out};
CORRADE_VERIFY(!converter.add(MeshData{MeshPrimitive::Triangles, 0}));
CORRADE_VERIFY(converter.called);
CORRADE_COMPARE(out, "");
}
@ -3630,13 +3738,17 @@ void AbstractSceneConverterTest::addMeshThroughConvertMeshFailed() {
}
Containers::Optional<MeshData> doConvert(const MeshData&) override {
called = true;
return {};
}
bool called = false;
} converter;
CORRADE_VERIFY(converter.begin());
CORRADE_VERIFY(!converter.add(MeshData{MeshPrimitive::Lines, 6}));
CORRADE_VERIFY(converter.called);
/* It shouldn't abort the whole process */
CORRADE_VERIFY(converter.isConverting());
CORRADE_COMPARE(converter.meshCount(), 0);
@ -3749,13 +3861,17 @@ void AbstractSceneConverterTest::addMeshThroughConvertMeshToDataFailed() {
}
Containers::Optional<Containers::Array<char>> doConvertToData(const MeshData&) override {
called = true;
return {};
}
bool called = false;
} converter;
CORRADE_VERIFY(converter.beginData());
CORRADE_VERIFY(!converter.add(MeshData{MeshPrimitive::Lines, 6}));
CORRADE_VERIFY(converter.called);
/* It shouldn't abort the whole process */
CORRADE_VERIFY(converter.isConverting());
CORRADE_COMPARE(converter.meshCount(), 0);
@ -3935,8 +4051,11 @@ void AbstractSceneConverterTest::addMeshThroughConvertMeshToFileFailed() {
}
bool doConvertToFile(const MeshData&, Containers::StringView) override {
called = true;
return false;
}
bool called = false;
} converter;
/* Remove previous file, if any */
@ -3948,6 +4067,7 @@ void AbstractSceneConverterTest::addMeshThroughConvertMeshToFileFailed() {
CORRADE_VERIFY(!Utility::Path::exists(filename));
CORRADE_VERIFY(!converter.add(MeshData{MeshPrimitive::Lines, 6}));
CORRADE_VERIFY(converter.called);
/* It shouldn't abort the whole process */
CORRADE_VERIFY(converter.isConverting());
CORRADE_COMPARE(converter.meshCount(), 0);
@ -4104,8 +4224,11 @@ void AbstractSceneConverterTest::addMeshLevelsFailed() {
bool doBegin() override { return true; }
bool doAdd(UnsignedInt, const Containers::Iterable<const MeshData>&, Containers::StringView) override {
called = true;
return false;
}
bool called = false;
} converter;
CORRADE_VERIFY(converter.begin());
@ -4119,6 +4242,7 @@ void AbstractSceneConverterTest::addMeshLevelsFailed() {
MeshData{MeshPrimitive::Triangles, 0},
MeshData{MeshPrimitive::Triangles, 0}
}));
CORRADE_VERIFY(converter.called);
CORRADE_COMPARE(out, "");
}
@ -4200,6 +4324,41 @@ void AbstractSceneConverterTest::addMeshThroughLevels() {
CORRADE_COMPARE(converter.meshCount(), 1);
}
void AbstractSceneConverterTest::addMeshThroughLevelsFailed() {
struct: AbstractSceneConverter {
SceneConverterFeatures doFeatures() const override {
return SceneConverterFeature::ConvertMultiple|
SceneConverterFeature::AddMeshes|
SceneConverterFeature::MeshLevels;
}
bool doBegin() override { return true; }
bool doAdd(UnsignedInt, const Containers::Iterable<const MeshData>&, Containers::StringView) override {
called = true;
return false;
}
bool called = false;
} converter;
CORRADE_VERIFY(converter.begin());
CORRADE_COMPARE(converter.meshCount(), 0);
/* The implementation is expected to print an error message on its own */
{
Containers::String out;
Error redirectError{&out};
CORRADE_VERIFY(!converter.add(MeshData{MeshPrimitive::Triangles, 0}));
CORRADE_VERIFY(converter.called);
CORRADE_COMPARE(out, "");
}
/* It shouldn't abort the whole process */
CORRADE_VERIFY(converter.isConverting());
CORRADE_COMPARE(converter.meshCount(), 0);
}
void AbstractSceneConverterTest::setMeshAttributeName() {
auto&& data = SetMeshAttributeData[testCaseInstanceId()];
setTestCaseDescription(data.name);
@ -4312,8 +4471,11 @@ void AbstractSceneConverterTest::addMaterialFailed() {
bool doBegin() override { return true; }
bool doAdd(UnsignedInt, const MaterialData&, Containers::StringView) override {
called = true;
return false;
}
bool called = false;
} converter;
CORRADE_VERIFY(converter.begin());
@ -4324,6 +4486,7 @@ void AbstractSceneConverterTest::addMaterialFailed() {
Containers::String out;
Error redirectError{&out};
CORRADE_VERIFY(!converter.add(MaterialData{{}, nullptr}));
CORRADE_VERIFY(converter.called);
CORRADE_COMPARE(out, "");
}
@ -4395,8 +4558,11 @@ void AbstractSceneConverterTest::addTextureFailed() {
bool doBegin() override { return true; }
bool doAdd(UnsignedInt, const TextureData&, Containers::StringView) override {
called = true;
return false;
}
bool called = false;
} converter;
CORRADE_VERIFY(converter.begin());
@ -4407,6 +4573,7 @@ void AbstractSceneConverterTest::addTextureFailed() {
Containers::String out;
Error redirectError{&out};
CORRADE_VERIFY(!converter.add(TextureData{{}, {}, {}, {}, {}, 0}));
CORRADE_VERIFY(converter.called);
CORRADE_COMPARE(out, "");
}
@ -4553,8 +4720,11 @@ void AbstractSceneConverterTest::addImage1DFailed() {
bool doBegin() override { return true; }
bool doAdd(UnsignedInt, const ImageData1D&, Containers::StringView) override {
++called;
return false;
}
Int called = 0;
} converter;
const char imageData[16]{};
@ -4571,6 +4741,7 @@ void AbstractSceneConverterTest::addImage1DFailed() {
CORRADE_VERIFY(!converter.add(ImageData1D{PixelFormat::RGBA8Unorm, 1, DataFlags{}, imageData}));
CORRADE_VERIFY(!converter.add(ImageView1D{PixelFormat::RGBA8Unorm, 1, imageData}));
CORRADE_VERIFY(!converter.add(CompressedImageView1D{CompressedPixelFormat::Astc4x4RGBAUnorm, 1, imageData}));
CORRADE_COMPARE(converter.called, 3);
CORRADE_COMPARE(out, "");
}
@ -4741,8 +4912,11 @@ void AbstractSceneConverterTest::addImage2DFailed() {
bool doBegin() override { return true; }
bool doAdd(UnsignedInt, const ImageData2D&, Containers::StringView) override {
++called;
return false;
}
Int called = 0;
} converter;
const char imageData[16]{};
@ -4759,6 +4933,7 @@ void AbstractSceneConverterTest::addImage2DFailed() {
CORRADE_VERIFY(!converter.add(ImageData2D{PixelFormat::RGBA8Unorm, {1, 1}, DataFlags{}, imageData}));
CORRADE_VERIFY(!converter.add(ImageView2D{PixelFormat::RGBA8Unorm, {1, 1}, imageData}));
CORRADE_VERIFY(!converter.add(CompressedImageView2D{CompressedPixelFormat::Astc4x4RGBAUnorm, {1, 1}, imageData}));
CORRADE_COMPARE(converter.called, 3);
CORRADE_COMPARE(out, "");
}
@ -4951,8 +5126,11 @@ void AbstractSceneConverterTest::addImage3DFailed() {
bool doBegin() override { return true; }
bool doAdd(UnsignedInt, const ImageData3D&, Containers::StringView) override {
++called;
return false;
}
Int called = 0;
} converter;
const char imageData[16]{};
@ -4969,6 +5147,7 @@ void AbstractSceneConverterTest::addImage3DFailed() {
CORRADE_VERIFY(!converter.add(ImageData3D{PixelFormat::RGBA8Unorm, {1, 1, 1}, DataFlags{}, imageData}));
CORRADE_VERIFY(!converter.add(ImageView3D{PixelFormat::RGBA8Unorm, {1, 1, 1}, imageData}));
CORRADE_VERIFY(!converter.add(CompressedImageView3D{CompressedPixelFormat::Astc4x4RGBAUnorm, {1, 1, 1}, imageData}));
CORRADE_COMPARE(converter.called, 3);
CORRADE_COMPARE(out, "");
}
@ -5155,8 +5334,11 @@ void AbstractSceneConverterTest::addImageLevels1DFailed() {
bool doBegin() override { return true; }
bool doAdd(UnsignedInt, const Containers::Iterable<const ImageData1D>&, Containers::StringView) override {
++called;
return false;
}
Int called = 0;
} converter;
const char imageData[16]{};
@ -5182,6 +5364,7 @@ void AbstractSceneConverterTest::addImageLevels1DFailed() {
CompressedImageView1D{CompressedPixelFormat::Astc4x4RGBAUnorm, 1, imageData},
CompressedImageView1D{CompressedPixelFormat::Astc4x4RGBAUnorm, 1, imageData},
}));
CORRADE_COMPARE(converter.called, 3);
CORRADE_COMPARE(out, "");
}
@ -5373,8 +5556,11 @@ void AbstractSceneConverterTest::addImageLevels2DFailed() {
bool doBegin() override { return true; }
bool doAdd(UnsignedInt, const Containers::Iterable<const ImageData2D>&, Containers::StringView) override {
++called;
return false;
}
Int called = 0;
} converter;
const char imageData[16]{};
@ -5400,6 +5586,7 @@ void AbstractSceneConverterTest::addImageLevels2DFailed() {
CompressedImageView2D{CompressedPixelFormat::Astc4x4RGBAUnorm, {1, 1}, imageData},
CompressedImageView2D{CompressedPixelFormat::Astc4x4RGBAUnorm, {1, 1}, imageData}
}));
CORRADE_COMPARE(converter.called, 3);
CORRADE_COMPARE(out, "");
}
@ -5780,8 +5967,11 @@ void AbstractSceneConverterTest::addImageLevels3DFailed() {
bool doBegin() override { return true; }
bool doAdd(UnsignedInt, const Containers::Iterable<const ImageData3D>&, Containers::StringView) override {
++called;
return false;
}
Int called = 0;
} converter;
const char imageData[16]{};
@ -5807,6 +5997,7 @@ void AbstractSceneConverterTest::addImageLevels3DFailed() {
CompressedImageView3D{CompressedPixelFormat::Astc4x4RGBAUnorm, {1, 1, 1}, imageData},
CompressedImageView3D{CompressedPixelFormat::Astc4x4RGBAUnorm, {1, 1, 1}, imageData}
}));
CORRADE_COMPARE(converter.called, 3);
CORRADE_COMPARE(out, "");
}
@ -5952,6 +6143,132 @@ void AbstractSceneConverterTest::addImage3DThroughLevels() {
CORRADE_COMPARE(converter.image3DCount(), 1);
}
void AbstractSceneConverterTest::addImage1DThroughLevelsFailed() {
struct: AbstractSceneConverter {
SceneConverterFeatures doFeatures() const override {
return SceneConverterFeature::ConvertMultiple|
SceneConverterFeature::AddImages1D|
SceneConverterFeature::AddCompressedImages1D|
SceneConverterFeature::ImageLevels;
}
bool doBegin() override { return true; }
bool doAdd(UnsignedInt, const Containers::Iterable<const ImageData1D>&, Containers::StringView) override {
++called;
return false;
}
Int called = 0;
} converter;
const char imageData[16]{};
CORRADE_VERIFY(converter.begin());
CORRADE_COMPARE(converter.image1DCount(), 0);
/* The implementation is expected to print an error message on its own */
{
Containers::String out;
Error redirectError{&out};
/* Testing all three variants to "fake" coverage for the name-less
overloads as well */
CORRADE_VERIFY(!converter.add(ImageData1D{PixelFormat::RGBA8Unorm, 1, DataFlags{}, imageData}));
CORRADE_VERIFY(!converter.add(ImageView1D{PixelFormat::RGBA8Unorm, 1, imageData}));
CORRADE_VERIFY(!converter.add(CompressedImageView1D{CompressedPixelFormat::Astc4x4RGBAUnorm, 1, imageData}));
CORRADE_COMPARE(converter.called, 3);
CORRADE_COMPARE(out, "");
}
/* It shouldn't abort the whole process */
CORRADE_VERIFY(converter.isConverting());
CORRADE_COMPARE(converter.image1DCount(), 0);
}
void AbstractSceneConverterTest::addImage2DThroughLevelsFailed() {
struct: AbstractSceneConverter {
SceneConverterFeatures doFeatures() const override {
return SceneConverterFeature::ConvertMultiple|
SceneConverterFeature::AddImages2D|
SceneConverterFeature::AddCompressedImages2D|
SceneConverterFeature::ImageLevels;
}
bool doBegin() override { return true; }
bool doAdd(UnsignedInt, const Containers::Iterable<const ImageData2D>&, Containers::StringView) override {
++called;
return false;
}
Int called = 0;
} converter;
const char imageData[16]{};
CORRADE_VERIFY(converter.begin());
CORRADE_COMPARE(converter.image2DCount(), 0);
/* The implementation is expected to print an error message on its own */
{
Containers::String out;
Error redirectError{&out};
/* Testing all three variants to "fake" coverage for the name-less
overloads as well */
CORRADE_VERIFY(!converter.add(ImageData2D{PixelFormat::RGBA8Unorm, {1, 1}, DataFlags{}, imageData}));
CORRADE_VERIFY(!converter.add(ImageView2D{PixelFormat::RGBA8Unorm, {1, 1}, imageData}));
CORRADE_VERIFY(!converter.add(CompressedImageView2D{CompressedPixelFormat::Astc4x4RGBAUnorm, {1, 1}, imageData}));
CORRADE_COMPARE(converter.called, 3);
CORRADE_COMPARE(out, "");
}
/* It shouldn't abort the whole process */
CORRADE_VERIFY(converter.isConverting());
CORRADE_COMPARE(converter.image2DCount(), 0);
}
void AbstractSceneConverterTest::addImage3DThroughLevelsFailed() {
struct: AbstractSceneConverter {
SceneConverterFeatures doFeatures() const override {
return SceneConverterFeature::ConvertMultiple|
SceneConverterFeature::AddImages3D|
SceneConverterFeature::AddCompressedImages3D|
SceneConverterFeature::ImageLevels;
}
bool doBegin() override { return true; }
bool doAdd(UnsignedInt, const Containers::Iterable<const ImageData3D>&, Containers::StringView) override {
++called;
return false;
}
Int called = 0;
} converter;
const char imageData[16]{};
CORRADE_VERIFY(converter.begin());
CORRADE_COMPARE(converter.image3DCount(), 0);
/* The implementation is expected to print an error message on its own */
{
Containers::String out;
Error redirectError{&out};
/* Testing all three variants to "fake" coverage for the name-less
overloads as well */
CORRADE_VERIFY(!converter.add(ImageData3D{PixelFormat::RGBA8Unorm, {1, 1, 1}, DataFlags{}, imageData}));
CORRADE_VERIFY(!converter.add(ImageView3D{PixelFormat::RGBA8Unorm, {1, 1, 1}, imageData}));
CORRADE_VERIFY(!converter.add(CompressedImageView3D{CompressedPixelFormat::Astc4x4RGBAUnorm, {1, 1, 1}, imageData}));
CORRADE_COMPARE(converter.called, 3);
CORRADE_COMPARE(out, "");
}
/* It shouldn't abort the whole process */
CORRADE_VERIFY(converter.isConverting());
CORRADE_COMPARE(converter.image3DCount(), 0);
}
void AbstractSceneConverterTest::addImporterContents() {
auto&& data = AddImporterContentsData[testCaseInstanceId()];
setTestCaseDescription(data.name);

Loading…
Cancel
Save