Add DeprecationVerifier to the list of available verifiers

Add unit tests for DeprecationVerifier
This commit is contained in:
Alexander Bock
2016-09-23 23:24:03 +02:00
parent d8ca2965eb
commit 3dce9f0f21
6 changed files with 295 additions and 17 deletions

View File

@@ -69,11 +69,36 @@ struct TestResult {
/// The Reason that caused this offense
Reason reason;
};
/**
* A warning is some value that that does not exactly adhere to the specification, but
* that also does not violate so badly to warrant an Offense. This, for example, could
* be that a value is marked deprecated and should not be used anymore as the value
* might be removed in a latter version.
*/
struct Warning {
/**
* The reason for the warning
*/
enum class Reason {
Deprecated ///< The value is marked as deprecated and should not used
};
/// The offending key that caused the Warning. In the case of a nested table,
/// this value will be the fully qualified name of the key
std::string offender;
/// The Reason that caused this Warning
Reason reason;
};
/// Is \c true if the TestResult is positive, \c false otherwise
bool success;
/// Contains a list of offenses that were found in the test. Is empty if
/// TestResult::Success is \c true
std::vector<Offense> offenses;
/// Contains a list of warnings that were found in the test
std::vector<Warning> warnings;
};
/**

View File

@@ -665,6 +665,33 @@ struct AnnotationVerifier : public T {
std::string annotation;
};
/**
* This Verifier is a marker that performs the same testing as the \c T parameter, but
* also adds a warning to the test result informing the user of the deprecation.
* Furthermore, the documentation will contain the word <code>(deprecated)</code> in
* addition to the documentation returned by \c
* \tparam T The Verifier that is to be marked deprecated
*/
template <typename T>
struct DeprecatedVerifier : public T {
/**
* Tests the \p dictionary%s \p key using the Verifier \c T and adds a warning to the
* TestResult informing the caller of the deprecation.
* \param dictionary The ghoul::Dictionary whose \p key should be tested
* \param key The key inside the \p dictionary that is to be tested
* \return A TestResult that contains the results of the testing
*/
TestResult operator()(const ghoul::Dictionary& dictionary,
const std::string& key) const override;
/**
* Returns the documentation as reported by \c T and adds the word
* <code>(deprecated)</code> to it.
* \return The deprecated version of \c T%'s documentation
*/
std::string documentation() const override;
};
/**
* This Verifier can reference and apply other Documentation%s that have been registered
* with a DocumentationEngine. The dependency is only resolved when the operator() is
@@ -884,6 +911,18 @@ using StringAnnotationVerifier = AnnotationVerifier<StringVerifier>;
/// <code>ghoul::Dictionary</code>
using TableAnnotationVerifier = AnnotationVerifier<TableVerifier>;
/// A short-hand definition for a DeprecatedVerifier with a type check for \c bool
using BoolDeprecatedVerifier = DeprecatedVerifier<BoolVerifier>;
/// A short-hand definition for a DeprecatedVerifier with a type check for \c int
using IntDeprecatedVerifier = DeprecatedVerifier<IntVerifier>;
/// A short-hand definition for a DeprecatedVerifier with a type check for \c double
using DoubleDeprecatedVerifier = DeprecatedVerifier<DoubleVerifier>;
/// A short-hand definition for a DeprecatedVerifier with a type check for \c string
using StringDeprecatedVerifier = DeprecatedVerifier<StringVerifier>;
/// A short-hand definition for a DeprecatedVerifier with a type check for
/// <code>ghoul::Dictionary</code>
using TableDeprecatedVerifier = DeprecatedVerifier<TableVerifier>;
// Definitions of external templates that are instantiated in the cpp file
// This cuts down the compilation times as almost all of the possible template types do
// not need to be instantiated multiple times
@@ -933,7 +972,30 @@ extern template struct AnnotationVerifier<IntVerifier>;
extern template struct AnnotationVerifier<DoubleVerifier>;
extern template struct AnnotationVerifier<StringVerifier>;
extern template struct AnnotationVerifier<TableVerifier>;
extern template struct AnnotationVerifier<BoolVector2Verifier>;
extern template struct AnnotationVerifier<IntVector2Verifier>;
extern template struct AnnotationVerifier<DoubleVector2Verifier>;
extern template struct AnnotationVerifier<BoolVector3Verifier>;
extern template struct AnnotationVerifier<IntVector3Verifier>;
extern template struct AnnotationVerifier<DoubleVector3Verifier>;
extern template struct AnnotationVerifier<BoolVector4Verifier>;
extern template struct AnnotationVerifier<IntVector4Verifier>;
extern template struct AnnotationVerifier<DoubleVector4Verifier>;
extern template struct DeprecatedVerifier<BoolVerifier>;
extern template struct DeprecatedVerifier<IntVerifier>;
extern template struct DeprecatedVerifier<DoubleVerifier>;
extern template struct DeprecatedVerifier<StringVerifier>;
extern template struct DeprecatedVerifier<TableVerifier>;
extern template struct DeprecatedVerifier<BoolVector2Verifier>;
extern template struct DeprecatedVerifier<IntVector2Verifier>;
extern template struct DeprecatedVerifier<DoubleVector2Verifier>;
extern template struct DeprecatedVerifier<BoolVector3Verifier>;
extern template struct DeprecatedVerifier<IntVector3Verifier>;
extern template struct DeprecatedVerifier<DoubleVector3Verifier>;
extern template struct DeprecatedVerifier<BoolVector4Verifier>;
extern template struct DeprecatedVerifier<IntVector4Verifier>;
extern template struct DeprecatedVerifier<DoubleVector4Verifier>;
} // namespace documentation
} // namespace openspace

View File

@@ -263,7 +263,7 @@ NotInRangeVerifier<T>::NotInRangeVerifier(typename T::Type lower, typename T::Ty
template <typename T>
TestResult NotInRangeVerifier<T>::operator()(const ghoul::Dictionary& dict,
const std::string& key) const {
const std::string& key) const {
TestResult res = T::operator()(dict, key);
if (res.success) {
typename T::Type val = dict.value<typename T::Type>(key);
@@ -299,5 +299,19 @@ std::string AnnotationVerifier<T>::documentation() const {
return annotation;
}
template <typename T>
TestResult DeprecatedVerifier<T>::operator()(const ghoul::Dictionary& dict,
const std::string& key) const
{
TestResult res = T::operator()(dict, key);
res.warnings.push_back(TestResult::Warning{ key, TestResult::Warning::Reason::Deprecated });
return res;
}
template <typename T>
std::string DeprecatedVerifier<T>::documentation() const {
return T::documentation() + " (deprecated)";
}
} // namespace documentation
} // namespace openspace

View File

@@ -31,8 +31,7 @@ namespace {
// Structure used to make offenses unique
struct OffenseCompare {
using Offense = openspace::documentation::TestResult::Offense;
bool operator()(const Offense& lhs, const Offense& rhs) const
{
bool operator()(const Offense& lhs, const Offense& rhs) const {
if (lhs.offender != rhs.offender) {
return lhs.offender < rhs.offender;
}
@@ -41,8 +40,21 @@ namespace {
std::underlying_type_t<Offense::Reason>(rhs.reason);
}
}
};
struct WarningCompare {
using Warning = openspace::documentation::TestResult::Warning;
bool operator()(const Warning& lhs, const Warning& rhs) const {
if (lhs.offender != rhs.offender) {
return lhs.offender < rhs.offender;
}
else {
return std::underlying_type_t<Warning::Reason>(lhs.reason) <
std::underlying_type_t<Warning::Reason>(rhs.reason);
}
}
};
} // namespace
// Unfortunately, the standard library does not contain a no-op for the to_string method
@@ -128,6 +140,11 @@ TestResult testSpecification(const Documentation& d, const ghoul::Dictionary& di
res.offenses.end()
);
}
result.warnings.insert(
result.warnings.end(),
res.warnings.begin(),
res.warnings.end()
);
};
for (const auto& p : d.entries) {
@@ -181,6 +198,13 @@ TestResult testSpecification(const Documentation& d, const ghoul::Dictionary& di
result.offenses = std::vector<TestResult::Offense>(
uniqueOffenders.begin(), uniqueOffenders.end()
);
// Remove duplicate warnings. This should normally not happen, but we want to be sure
std::set<TestResult::Warning, WarningCompare> uniqueWarnings(
result.warnings.begin(), result.warnings.end()
);
result.warnings = std::vector<TestResult::Warning>(
uniqueWarnings.begin(), uniqueWarnings.end()
);
return result;
}

View File

@@ -72,11 +72,36 @@ template struct InRangeVerifier<DoubleVerifier>;
template struct NotInRangeVerifier<IntVerifier>;
template struct NotInRangeVerifier<DoubleVerifier>;
template struct AnnotationVerifier<BoolVerifier>;
template struct AnnotationVerifier<IntVerifier>;
template struct AnnotationVerifier<DoubleVerifier>;
template struct AnnotationVerifier<StringVerifier>;
template struct AnnotationVerifier<TableVerifier>;
template struct AnnotationVerifier<BoolVector2Verifier>;
template struct AnnotationVerifier<IntVector2Verifier>;
template struct AnnotationVerifier<DoubleVector2Verifier>;
template struct AnnotationVerifier<BoolVector3Verifier>;
template struct AnnotationVerifier<IntVector3Verifier>;
template struct AnnotationVerifier<DoubleVector3Verifier>;
template struct AnnotationVerifier<BoolVector4Verifier>;
template struct AnnotationVerifier<IntVector4Verifier>;
template struct AnnotationVerifier<DoubleVector4Verifier>;
template struct DeprecatedVerifier<BoolVerifier>;
template struct DeprecatedVerifier<IntVerifier>;
template struct DeprecatedVerifier<DoubleVerifier>;
template struct DeprecatedVerifier<StringVerifier>;
template struct DeprecatedVerifier<TableVerifier>;
template struct DeprecatedVerifier<BoolVector2Verifier>;
template struct DeprecatedVerifier<IntVector2Verifier>;
template struct DeprecatedVerifier<DoubleVector2Verifier>;
template struct DeprecatedVerifier<BoolVector3Verifier>;
template struct DeprecatedVerifier<IntVector3Verifier>;
template struct DeprecatedVerifier<DoubleVector3Verifier>;
template struct DeprecatedVerifier<BoolVector4Verifier>;
template struct DeprecatedVerifier<IntVector4Verifier>;
template struct DeprecatedVerifier<DoubleVector4Verifier>;
std::string BoolVerifier::type() const {
return "Boolean";
@@ -127,7 +152,8 @@ std::string StringVerifier::type() const {
TableVerifier::TableVerifier(std::vector<DocumentationEntry> d, Exhaustive exhaustive)
: documentations(std::move(d))
, exhaustive(std::move(exhaustive)) {}
, exhaustive(std::move(exhaustive))
{}
TestResult TableVerifier::operator()(const ghoul::Dictionary& dict,
const std::string& key) const {
@@ -135,19 +161,25 @@ TestResult TableVerifier::operator()(const ghoul::Dictionary& dict,
ghoul::Dictionary d = dict.value<ghoul::Dictionary>(key);
TestResult res = testSpecification({ "", documentations, exhaustive }, d);
// Add the 'key' as a prefix to make the new offender a fully qualified identifer
for (TestResult::Offense& s : res.offenses) {
s.offender = key + "." + s.offender;
}
// Add the 'key' as a prefix to make the new warning a fully qualified identifer
for (TestResult::Warning& w : res.warnings) {
w.offender = key + "." + w.offender;
}
return res;
}
else {
if (dict.hasKey(key)) {
return{ false, { { key, TestResult::Offense::Reason::WrongType } } };
return { false, { { key, TestResult::Offense::Reason::WrongType } } };
}
else {
return{ false, { { key, TestResult::Offense::Reason::MissingKey } } };
return { false, { { key, TestResult::Offense::Reason::MissingKey } } };
}
}
}
@@ -182,10 +214,16 @@ TestResult ReferencingVerifier::operator()(const ghoul::Dictionary& dictionary,
ghoul::Dictionary d = dictionary.value<ghoul::Dictionary>(key);
TestResult res = testSpecification(*it, d);
// Add the 'key' as a prefix to make the offender a fully qualified identifer
for (TestResult::Offense& s : res.offenses) {
s.offender = key + "." + s.offender;
}
// Add the 'key' as a prefix to make the warning a fully qualified identifer
for (TestResult::Warning& w : res.warnings) {
w.offender = key + "." + w.offender;
}
return res;
}
}

View File

@@ -2308,6 +2308,73 @@ TEST_F(DocumentationTest, DoubleVector4Verifier) {
EXPECT_EQ(TestResult::Offense::Reason::WrongType, negativeRes.offenses[0].reason);
}
TEST_F(DocumentationTest, DeprecatedVerifier) {
using namespace openspace::documentation;
using namespace std::string_literals;
Documentation doc{ {
{ "bool", new BoolDeprecatedVerifier },
{ "int" , new IntDeprecatedVerifier },
{ "double", new DoubleDeprecatedVerifier },
{ "string" , new StringDeprecatedVerifier },
{ "boolvec2", new DeprecatedVerifier<BoolVector2Verifier> },
{ "intvec2", new DeprecatedVerifier<IntVector2Verifier> },
{ "doublevec2", new DeprecatedVerifier<DoubleVector2Verifier> },
{ "boolvec3", new DeprecatedVerifier<BoolVector3Verifier> },
{ "intvec3", new DeprecatedVerifier<IntVector3Verifier> },
{ "doublevec3", new DeprecatedVerifier<DoubleVector3Verifier> },
{ "boolvec4", new DeprecatedVerifier<BoolVector4Verifier> },
{ "intvec4", new DeprecatedVerifier<IntVector4Verifier> },
{ "doublevec4", new DeprecatedVerifier<DoubleVector4Verifier> }
}};
ghoul::Dictionary positive {
{ "bool", true },
{ "int", 1 },
{ "double", 2.0 },
{ "string" , ""s },
{ "boolvec2", glm::bvec2() },
{ "intvec2", glm::ivec2() },
{ "doublevec2", glm::dvec2() },
{ "boolvec3", glm::bvec3() },
{ "intvec3", glm::ivec3() },
{ "doublevec3", glm::dvec3() },
{ "boolvec4", glm::bvec4() },
{ "intvec4", glm::ivec4() },
{ "doublevec4", glm::dvec4() }
};
TestResult positiveRes = testSpecification(doc, positive);
EXPECT_TRUE(positiveRes.success);
EXPECT_EQ(0, positiveRes.offenses.size());
ASSERT_EQ(13, positiveRes.warnings.size());
EXPECT_EQ("bool", positiveRes.warnings[0].offender);
EXPECT_EQ(TestResult::Warning::Reason::Deprecated, positiveRes.warnings[0].reason);
EXPECT_EQ("int", positiveRes.warnings[1].offender);
EXPECT_EQ(TestResult::Warning::Reason::Deprecated, positiveRes.warnings[1].reason);
EXPECT_EQ("double", positiveRes.warnings[2].offender);
EXPECT_EQ(TestResult::Warning::Reason::Deprecated, positiveRes.warnings[2].reason);
EXPECT_EQ("string", positiveRes.warnings[3].offender);
EXPECT_EQ(TestResult::Warning::Reason::Deprecated, positiveRes.warnings[3].reason);
EXPECT_EQ("boolvec2", positiveRes.warnings[4].offender);
EXPECT_EQ(TestResult::Warning::Reason::Deprecated, positiveRes.warnings[4].reason);
EXPECT_EQ("intvec2", positiveRes.warnings[5].offender);
EXPECT_EQ(TestResult::Warning::Reason::Deprecated, positiveRes.warnings[5].reason);
EXPECT_EQ("doublevec2", positiveRes.warnings[6].offender);
EXPECT_EQ(TestResult::Warning::Reason::Deprecated, positiveRes.warnings[6].reason);
EXPECT_EQ("boolvec3", positiveRes.warnings[7].offender);
EXPECT_EQ(TestResult::Warning::Reason::Deprecated, positiveRes.warnings[7].reason);
EXPECT_EQ("intvec3", positiveRes.warnings[8].offender);
EXPECT_EQ(TestResult::Warning::Reason::Deprecated, positiveRes.warnings[8].reason);
EXPECT_EQ("doublevec3", positiveRes.warnings[9].offender);
EXPECT_EQ(TestResult::Warning::Reason::Deprecated, positiveRes.warnings[9].reason);
EXPECT_EQ("boolvec4", positiveRes.warnings[10].offender);
EXPECT_EQ(TestResult::Warning::Reason::Deprecated, positiveRes.warnings[10].reason);
EXPECT_EQ("intvec4", positiveRes.warnings[11].offender);
EXPECT_EQ(TestResult::Warning::Reason::Deprecated, positiveRes.warnings[11].reason);
EXPECT_EQ("doublevec4", positiveRes.warnings[12].offender);
EXPECT_EQ(TestResult::Warning::Reason::Deprecated, positiveRes.warnings[12].reason);
}
TEST_F(DocumentationTest, VerifierTypePostConditions) {
using namespace openspace::documentation;
using namespace std::string_literals;
@@ -2360,11 +2427,35 @@ TEST_F(DocumentationTest, VerifierTypePostConditions) {
EXPECT_NE("", IntNotInRangeVerifier({ 0, 1 }).type());
EXPECT_NE("", DoubleNotInRangeVerifier({ 0.0, 1.0 }).type());
EXPECT_NE("", BoolAnnotationVerifier("Annotation"s).type());
EXPECT_NE("", IntAnnotationVerifier("Annotation"s).type());
EXPECT_NE("", DoubleAnnotationVerifier("Annotation"s).type());
EXPECT_NE("", StringAnnotationVerifier("Annotation"s).type());
EXPECT_NE("", TableAnnotationVerifier("Annotation"s).type());
EXPECT_NE("", BoolAnnotationVerifier("A"s).type());
EXPECT_NE("", IntAnnotationVerifier("A"s).type());
EXPECT_NE("", DoubleAnnotationVerifier("A"s).type());
EXPECT_NE("", StringAnnotationVerifier("A"s).type());
EXPECT_NE("", TableAnnotationVerifier("A"s).type());
EXPECT_NE("", AnnotationVerifier<BoolVector2Verifier>("A"s).type());
EXPECT_NE("", AnnotationVerifier<IntVector2Verifier>("A"s).type());
EXPECT_NE("", AnnotationVerifier<DoubleVector2Verifier>("A"s).type());
EXPECT_NE("", AnnotationVerifier<BoolVector3Verifier>("A"s).type());
EXPECT_NE("", AnnotationVerifier<IntVector3Verifier>("A"s).type());
EXPECT_NE("", AnnotationVerifier<DoubleVector3Verifier>("A"s).type());
EXPECT_NE("", AnnotationVerifier<BoolVector4Verifier>("A"s).type());
EXPECT_NE("", AnnotationVerifier<IntVector4Verifier>("A"s).type());
EXPECT_NE("", AnnotationVerifier<DoubleVector4Verifier>("A"s).type());
EXPECT_NE("", BoolDeprecatedVerifier().type());
EXPECT_NE("", IntDeprecatedVerifier().type());
EXPECT_NE("", DoubleDeprecatedVerifier().type());
EXPECT_NE("", StringDeprecatedVerifier().type());
EXPECT_NE("", TableDeprecatedVerifier().type());
EXPECT_NE("", DeprecatedVerifier<BoolVector2Verifier>().type());
EXPECT_NE("", DeprecatedVerifier<IntVector2Verifier>().type());
EXPECT_NE("", DeprecatedVerifier<DoubleVector2Verifier>().type());
EXPECT_NE("", DeprecatedVerifier<BoolVector3Verifier>().type());
EXPECT_NE("", DeprecatedVerifier<IntVector3Verifier>().type());
EXPECT_NE("", DeprecatedVerifier<DoubleVector3Verifier>().type());
EXPECT_NE("", DeprecatedVerifier<BoolVector4Verifier>().type());
EXPECT_NE("", DeprecatedVerifier<IntVector4Verifier>().type());
EXPECT_NE("", DeprecatedVerifier<DoubleVector4Verifier>().type());
EXPECT_NE("", ReferencingVerifier("identifier"s).type());
}
@@ -2421,11 +2512,35 @@ TEST_F(DocumentationTest, VerifierDocumentationPostConditions) {
EXPECT_NE("", IntNotInRangeVerifier({ 0, 1 }).documentation());
EXPECT_NE("", DoubleNotInRangeVerifier({ 0.0, 1.0 }).documentation());
EXPECT_NE("", BoolAnnotationVerifier("Annotation"s).documentation());
EXPECT_NE("", IntAnnotationVerifier("Annotation"s).documentation());
EXPECT_NE("", DoubleAnnotationVerifier("Annotation"s).documentation());
EXPECT_NE("", StringAnnotationVerifier("Annotation"s).documentation());
EXPECT_NE("", TableAnnotationVerifier("Annotation"s).documentation());
EXPECT_NE("", BoolAnnotationVerifier("A"s).documentation());
EXPECT_NE("", IntAnnotationVerifier("A"s).documentation());
EXPECT_NE("", DoubleAnnotationVerifier("A"s).documentation());
EXPECT_NE("", StringAnnotationVerifier("A"s).documentation());
EXPECT_NE("", TableAnnotationVerifier("A"s).documentation());
EXPECT_NE("", AnnotationVerifier<BoolVector2Verifier>("A"s).documentation());
EXPECT_NE("", AnnotationVerifier<IntVector2Verifier>("A"s).documentation());
EXPECT_NE("", AnnotationVerifier<DoubleVector2Verifier>("A"s).documentation());
EXPECT_NE("", AnnotationVerifier<BoolVector3Verifier>("A"s).documentation());
EXPECT_NE("", AnnotationVerifier<IntVector3Verifier>("A"s).documentation());
EXPECT_NE("", AnnotationVerifier<DoubleVector3Verifier>("A"s).documentation());
EXPECT_NE("", AnnotationVerifier<BoolVector4Verifier>("A"s).documentation());
EXPECT_NE("", AnnotationVerifier<IntVector4Verifier>("A"s).documentation());
EXPECT_NE("", AnnotationVerifier<DoubleVector4Verifier>("A"s).documentation());
EXPECT_NE("", BoolDeprecatedVerifier().documentation());
EXPECT_NE("", IntDeprecatedVerifier().documentation());
EXPECT_NE("", DoubleDeprecatedVerifier().documentation());
EXPECT_NE("", StringDeprecatedVerifier().documentation());
EXPECT_NE("", TableDeprecatedVerifier().documentation());
EXPECT_NE("", DeprecatedVerifier<BoolVector2Verifier>().documentation());
EXPECT_NE("", DeprecatedVerifier<IntVector2Verifier>().documentation());
EXPECT_NE("", DeprecatedVerifier<DoubleVector2Verifier>().documentation());
EXPECT_NE("", DeprecatedVerifier<BoolVector3Verifier>().documentation());
EXPECT_NE("", DeprecatedVerifier<IntVector3Verifier>().documentation());
EXPECT_NE("", DeprecatedVerifier<DoubleVector3Verifier>().documentation());
EXPECT_NE("", DeprecatedVerifier<BoolVector4Verifier>().documentation());
EXPECT_NE("", DeprecatedVerifier<IntVector4Verifier>().documentation());
EXPECT_NE("", DeprecatedVerifier<DoubleVector4Verifier>().documentation());
EXPECT_NE("", ReferencingVerifier("identifier"s).documentation());