From 45b1b9e7e7028ceee1c43f4c4d5f6cdf06918e44 Mon Sep 17 00:00:00 2001 From: Alexander Bock Date: Sat, 21 Jan 2023 22:14:09 +0100 Subject: [PATCH] Add tests for FileVerifier, DirectoryVerifier, and DateTimeVerifier (closes #1563) --- include/openspace/documentation/verifier.h | 6 + src/documentation/verifier.cpp | 26 +-- tests/test_documentation.cpp | 209 +++++++++++++++++---- tests/verifier/dummyfile.txt | 0 4 files changed, 183 insertions(+), 58 deletions(-) create mode 100644 tests/verifier/dummyfile.txt diff --git a/include/openspace/documentation/verifier.h b/include/openspace/documentation/verifier.h index c0cdcf57c2..5e90b29ea2 100644 --- a/include/openspace/documentation/verifier.h +++ b/include/openspace/documentation/verifier.h @@ -174,6 +174,8 @@ private: * refers to an existing file on disk. */ struct FileVerifier : public StringVerifier { + FileVerifier(); + TestResult operator()(const ghoul::Dictionary& dict, const std::string& key) const override; @@ -185,6 +187,8 @@ struct FileVerifier : public StringVerifier { * refers to an existing directory on disk. */ struct DirectoryVerifier : public StringVerifier { + DirectoryVerifier(); + TestResult operator()(const ghoul::Dictionary& dict, const std::string& key) const override; @@ -196,6 +200,8 @@ struct DirectoryVerifier : public StringVerifier { * a valid date time */ struct DateTimeVerifier : public StringVerifier { + DateTimeVerifier(); + TestResult operator()(const ghoul::Dictionary& dict, const std::string& key) const override; diff --git a/src/documentation/verifier.cpp b/src/documentation/verifier.cpp index dea3219304..c6c6616449 100644 --- a/src/documentation/verifier.cpp +++ b/src/documentation/verifier.cpp @@ -231,6 +231,8 @@ std::string StringVerifier::type() const { return "String"; } +FileVerifier::FileVerifier() : StringVerifier(true) {} + TestResult FileVerifier::operator()(const ghoul::Dictionary& dict, const std::string& key) const { @@ -255,6 +257,8 @@ std::string FileVerifier::type() const { return "File"; } +DirectoryVerifier::DirectoryVerifier() : StringVerifier(true) {} + TestResult DirectoryVerifier::operator()(const ghoul::Dictionary& dict, const std::string& key) const { @@ -279,6 +283,8 @@ std::string DirectoryVerifier::type() const { return "Directory"; } +DateTimeVerifier::DateTimeVerifier() : StringVerifier(true) {} + TestResult DateTimeVerifier::operator()(const ghoul::Dictionary& dict, const std::string& key) const { @@ -303,26 +309,6 @@ TestResult DateTimeVerifier::operator()(const ghoul::Dictionary& dict, off.explanation = "Not a valid format, should be: YYYY MM DD hh:mm:ss"; res.offenses.push_back(off); } - // then check if valid date - else { - // normalize e.g. 29/02/2013 would become 01/03/2013 - std::tm t_copy(t); - time_t when = mktime(&t_copy); - std::tm* norm = localtime(&when); - - // validate (is the normalized date still the same?): - if (norm->tm_mday != t.tm_mday && - norm->tm_mon != t.tm_mon && - norm->tm_year != t.tm_year) - { - res.success = false; - TestResult::Offense off; - off.offender = key; - off.reason = TestResult::Offense::Reason::Verification; - off.explanation = "Not a valid date"; - res.offenses.push_back(off); - } - } return res; } diff --git a/tests/test_documentation.cpp b/tests/test_documentation.cpp index e73fc664ad..b012fc5603 100644 --- a/tests/test_documentation.cpp +++ b/tests/test_documentation.cpp @@ -27,6 +27,7 @@ #include #include #include +#include #include #include @@ -56,6 +57,21 @@ TEST_CASE("Documentation: Constructor", "[documentation]") { new StringVerifier, Optional::No ); + doc.entries.emplace_back( + "FileVerifier", + new FileVerifier, + Optional::No + ); + doc.entries.emplace_back( + "DirectoryVerifier", + new DirectoryVerifier, + Optional::No + ); + doc.entries.emplace_back( + "DateTimeVerifier", + new DateTimeVerifier, + Optional::No + ); doc.entries.emplace_back( "TableVerifier", new TableVerifier, @@ -263,6 +279,9 @@ TEST_CASE("Documentation: Initializer Constructor", "[documentation]") { {"DoubleVerifier", new DoubleVerifier, Optional::No }, {"IntVerifier", new IntVerifier, Optional::No }, {"StringVerifier", new StringVerifier, Optional::No }, + {"FileVerifier", new FileVerifier, Optional::No }, + {"DirectoryVerifier", new DirectoryVerifier, Optional::No }, + {"DateTimeVerifier", new DateTimeVerifier, Optional::No }, {"TableVerifier", new TableVerifier, Optional::No }, // Operator Verifiers @@ -330,10 +349,9 @@ TEST_CASE("Documentation: BoolVerifier", "[documentation]") { CHECK(positiveRes.success); CHECK(positiveRes.offenses.empty()); - ghoul::Dictionary negative; - negative.setValue("Bool", 0); - - TestResult negativeRes = testSpecification(doc, negative); + ghoul::Dictionary negativeType; + negativeType.setValue("Bool", 0); + TestResult negativeRes = testSpecification(doc, negativeType); CHECK_FALSE(negativeRes.success); REQUIRE(negativeRes.offenses.size() == 1); CHECK(negativeRes.offenses[0].offender == "Bool"); @@ -363,10 +381,9 @@ TEST_CASE("Documentation: DoubleVerifier", "[documentation]") { CHECK(positiveRes.success); CHECK(positiveRes.offenses.empty()); - ghoul::Dictionary negative; - negative.setValue("Double", 0); - - TestResult negativeRes = testSpecification(doc, negative); + ghoul::Dictionary negativeType; + negativeType.setValue("Double", 0); + TestResult negativeRes = testSpecification(doc, negativeType); CHECK_FALSE(negativeRes.success); REQUIRE(negativeRes.offenses.size() == 1); CHECK(negativeRes.offenses[0].offender == "Double"); @@ -400,10 +417,9 @@ TEST_CASE("Documentation: IntVerifier", "[documentation]") { CHECK(positiveRes.success); CHECK(positiveRes.offenses.empty()); - ghoul::Dictionary negative; - negative.setValue("Int", 0.1); - - TestResult negativeRes = testSpecification(doc, negative); + ghoul::Dictionary negativeType; + negativeType.setValue("Int", 0.1); + TestResult negativeRes = testSpecification(doc, negativeType); CHECK_FALSE(negativeRes.success); REQUIRE(negativeRes.offenses.size() == 1); CHECK(negativeRes.offenses[0].offender == "Int"); @@ -432,9 +448,9 @@ TEST_CASE("Documentation: StringVerifier", "[documentation]") { CHECK(positiveRes.success); CHECK(positiveRes.offenses.empty()); - ghoul::Dictionary negative; - negative.setValue("String", 0); - TestResult negativeRes = testSpecification(doc, negative); + ghoul::Dictionary negativeType; + negativeType.setValue("String", 0); + TestResult negativeRes = testSpecification(doc, negativeType); CHECK_FALSE(negativeRes.success); REQUIRE(negativeRes.offenses.size() == 1); CHECK(negativeRes.offenses[0].offender == "String"); @@ -449,6 +465,123 @@ TEST_CASE("Documentation: StringVerifier", "[documentation]") { CHECK(negativeRes.offenses[0].reason == TestResult::Offense::Reason::MissingKey); } +TEST_CASE("Documentation: FileVerifier", "[documentation]") { + using namespace openspace::documentation; + using namespace std::string_literals; + + Documentation doc { + {{ "File", new FileVerifier, Optional::No }} + }; + + ghoul::Dictionary positive; + positive.setValue("File", absPath("${TESTDIR}/verifier/dummyfile.txt").string()); + TestResult positiveRes = testSpecification(doc, positive); + CHECK(positiveRes.success); + CHECK(positiveRes.offenses.empty()); + + ghoul::Dictionary negative404; + negative404.setValue("File", absPath("${TESTDIR}/verifier/404.txt").string()); + TestResult negativeRes = testSpecification(doc, negative404); + CHECK(!negativeRes.success); + REQUIRE(negativeRes.offenses.size() == 1); + CHECK(negativeRes.offenses[0].offender == "File"); + CHECK(negativeRes.offenses[0].reason == TestResult::Offense::Reason::Verification); + + ghoul::Dictionary negativeType; + negativeType.setValue("File", 0); + negativeRes = testSpecification(doc, negativeType); + CHECK_FALSE(negativeRes.success); + REQUIRE(negativeRes.offenses.size() == 1); + CHECK(negativeRes.offenses[0].offender == "File"); + CHECK(negativeRes.offenses[0].reason == TestResult::Offense::Reason::WrongType); + + ghoul::Dictionary negativeExist; + negativeExist.setValue("File2", ""s); + negativeRes = testSpecification(doc, negativeExist); + CHECK_FALSE(negativeRes.success); + REQUIRE(negativeRes.offenses.size() == 1); + CHECK(negativeRes.offenses[0].offender == "File"); + CHECK(negativeRes.offenses[0].reason == TestResult::Offense::Reason::MissingKey); +} + +TEST_CASE("Documentation: DirectoryVerifier", "[documentation]") { + using namespace openspace::documentation; + using namespace std::string_literals; + + Documentation doc{ + {{ "Dir", new DirectoryVerifier, Optional::No }} + }; + + ghoul::Dictionary positive; + positive.setValue("Dir", absPath("${TESTDIR}/verifier").string()); + TestResult positiveRes = testSpecification(doc, positive); + CHECK(positiveRes.success); + CHECK(positiveRes.offenses.empty()); + + ghoul::Dictionary negative404; + negative404.setValue("Dir", absPath("${TESTDIR}/verifier404").string()); + TestResult negativeRes = testSpecification(doc, negative404); + CHECK(!negativeRes.success); + REQUIRE(negativeRes.offenses.size() == 1); + CHECK(negativeRes.offenses[0].offender == "Dir"); + CHECK(negativeRes.offenses[0].reason == TestResult::Offense::Reason::Verification); + + ghoul::Dictionary negativeType; + negativeType.setValue("Dir", 0); + negativeRes = testSpecification(doc, negativeType); + CHECK_FALSE(negativeRes.success); + REQUIRE(negativeRes.offenses.size() == 1); + CHECK(negativeRes.offenses[0].offender == "Dir"); + CHECK(negativeRes.offenses[0].reason == TestResult::Offense::Reason::WrongType); + + ghoul::Dictionary negativeExist; + negativeExist.setValue("Dir2", ""s); + negativeRes = testSpecification(doc, negativeExist); + CHECK_FALSE(negativeRes.success); + REQUIRE(negativeRes.offenses.size() == 1); + CHECK(negativeRes.offenses[0].offender == "Dir"); + CHECK(negativeRes.offenses[0].reason == TestResult::Offense::Reason::MissingKey); +} + +TEST_CASE("Documentation: DateTimeVerifier", "[documentation]") { + using namespace openspace::documentation; + using namespace std::string_literals; + + Documentation doc{ + {{ "DateTime", new DateTimeVerifier, Optional::No }} + }; + + ghoul::Dictionary positive; + positive.setValue("DateTime", "1969 07 20 20:17:00"s); + TestResult positiveRes = testSpecification(doc, positive); + CHECK(positiveRes.success); + CHECK(positiveRes.offenses.empty()); + + ghoul::Dictionary negative404; + negative404.setValue("DateTime", "abc"s); + TestResult negativeRes = testSpecification(doc, negative404); + CHECK(!negativeRes.success); + REQUIRE(negativeRes.offenses.size() == 1); + CHECK(negativeRes.offenses[0].offender == "DateTime"); + CHECK(negativeRes.offenses[0].reason == TestResult::Offense::Reason::Verification); + + ghoul::Dictionary negativeType; + negativeType.setValue("DateTime", 0); + negativeRes = testSpecification(doc, negativeType); + CHECK_FALSE(negativeRes.success); + REQUIRE(negativeRes.offenses.size() == 1); + CHECK(negativeRes.offenses[0].offender == "DateTime"); + CHECK(negativeRes.offenses[0].reason == TestResult::Offense::Reason::WrongType); + + ghoul::Dictionary negativeExist; + negativeExist.setValue("DateTime2", ""s); + negativeRes = testSpecification(doc, negativeExist); + CHECK_FALSE(negativeRes.success); + REQUIRE(negativeRes.offenses.size() == 1); + CHECK(negativeRes.offenses[0].offender == "DateTime"); + CHECK(negativeRes.offenses[0].reason == TestResult::Offense::Reason::MissingKey); +} + TEST_CASE("Documentation: TableVerifierType", "[documentation]") { using namespace openspace::documentation; @@ -462,9 +595,9 @@ TEST_CASE("Documentation: TableVerifierType", "[documentation]") { CHECK(positiveRes.success); CHECK(positiveRes.offenses.empty()); - ghoul::Dictionary negative; - negative.setValue("Table", 0); - TestResult negativeRes = testSpecification(doc, negative); + ghoul::Dictionary negativeType; + negativeType.setValue("Table", 0); + TestResult negativeRes = testSpecification(doc, negativeType); CHECK_FALSE(negativeRes.success); REQUIRE(negativeRes.offenses.size() == 1); CHECK(negativeRes.offenses[0].offender == "Table"); @@ -499,9 +632,9 @@ TEST_CASE("Documentation: StringListVerifierType", "[documentation]") { CHECK(positiveRes.success); CHECK(positiveRes.offenses.empty()); - ghoul::Dictionary negative; - negative.setValue("StringList", 0); - TestResult negativeRes = testSpecification(doc, negative); + ghoul::Dictionary negativeType; + negativeType.setValue("StringList", 0); + TestResult negativeRes = testSpecification(doc, negativeType); CHECK_FALSE(negativeRes.success); REQUIRE(negativeRes.offenses.size() == 1); CHECK(negativeRes.offenses[0].offender == "StringList"); @@ -551,9 +684,9 @@ TEST_CASE("Documentation: IntListVerifierType", "[documentation]") { CHECK(positiveRes.success); CHECK(positiveRes.offenses.empty()); - ghoul::Dictionary negative; - negative.setValue("IntList", 0); - TestResult negativeRes = testSpecification(doc, negative); + ghoul::Dictionary negativeType; + negativeType.setValue("IntList", 0); + TestResult negativeRes = testSpecification(doc, negativeType); CHECK_FALSE(negativeRes.success); REQUIRE(negativeRes.offenses.size() == 1); CHECK(negativeRes.offenses[0].offender == "IntList"); @@ -606,25 +739,25 @@ TEST_CASE("Documentation: MixedVerifiers", "[documentation]") { CHECK(positiveRes.success); CHECK(positiveRes.offenses.empty()); - ghoul::Dictionary negative1; - negative1.setValue("Bool", true); - negative1.setValue("Double", 1); - negative1.setValue("Int", 0); - negative1.setValue("String", ""s); - negative1.setValue("Table", ghoul::Dictionary()); - TestResult negativeRes = testSpecification(doc, negative1); + ghoul::Dictionary negativeType1; + negativeType1.setValue("Bool", true); + negativeType1.setValue("Double", 1); + negativeType1.setValue("Int", 0); + negativeType1.setValue("String", ""s); + negativeType1.setValue("Table", ghoul::Dictionary()); + TestResult negativeRes = testSpecification(doc, negativeType1); CHECK_FALSE(negativeRes.success); REQUIRE(negativeRes.offenses.size() == 1); CHECK(negativeRes.offenses[0].offender == "Double"); CHECK(negativeRes.offenses[0].reason == TestResult::Offense::Reason::WrongType); - ghoul::Dictionary negative2; - negative2.setValue("Bool", true); - negative2.setValue("Double", 0.0); - negative2.setValue("Int", ""s); - negative2.setValue("String", 1); - negative2.setValue("Table", ghoul::Dictionary()); - negativeRes = testSpecification(doc, negative2); + ghoul::Dictionary negativeType2; + negativeType2.setValue("Bool", true); + negativeType2.setValue("Double", 0.0); + negativeType2.setValue("Int", ""s); + negativeType2.setValue("String", 1); + negativeType2.setValue("Table", ghoul::Dictionary()); + negativeRes = testSpecification(doc, negativeType2); CHECK_FALSE(negativeRes.success); REQUIRE(negativeRes.offenses.size() == 2); CHECK(negativeRes.offenses[0].offender == "Int"); diff --git a/tests/verifier/dummyfile.txt b/tests/verifier/dummyfile.txt new file mode 100644 index 0000000000..e69de29bb2