Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ project(gridtools-verification CXX C)

include(ExternalProject)

set(GRIDTOOLS_VERIFICATION_VERSION_STRING "0.3")
set(GRIDTOOLS_VERIFICATION_VERSION_STRING "0.4")
set(SERIALBOX_VERSION_REQUIRED "2.2.1")

#----------------- CMake options
Expand Down
16 changes: 16 additions & 0 deletions src/common.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,3 +36,19 @@
#pragma once

#include <boost/core/noncopyable.hpp>

#if __cplusplus >= 201402L // since c++14
#define GV_DEPRECATED(func) [[deprecated]] func
#define GV_DEPRECATED_REASON(func, msg) [[deprecated(#msg)]] func
#else
#ifdef __GNUC__
#define GV_DEPRECATED(func) __attribute__((deprecated)) func
#define GV_DEPRECATED_REASON(func, msg) GV_DEPRECATED(func)
#elif defined(_MSC_VER)
#define GV_DEPRECATED(func) __declspec(deprecated) func
#define GV_DEPRECATED_REASON(func, msg) GV_DEPRECATED(func)
#else
#define GV_DEPRECATED(func) func
#define GV_DEPRECATED_REASON(func, msg) GV_DEPRECATED(func)
#endif
#endif
120 changes: 111 additions & 9 deletions src/verification/field_collection.h
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,19 @@ namespace gt_verification {
};
}

// TODO a clean solution for the iterator would iterate over something like this.
// class verification_savepoint {
// public:
// void load_input(...)
// {
// }
// verification_result verify(..)
// {
// }
// private:
// ...
// };

/**
* @brief A collection of serialized fields
*
Expand All @@ -84,8 +97,40 @@ namespace gt_verification {
template < typename T >
class field_collection {
public:
field_collection(verification_specification verificationSpecification)
: verificationSpecification_(verificationSpecification){};
field_collection(verification_specification verificationSpecification) : reporter_(verificationSpecification){};

field_collection(const field_collection &) = delete;
field_collection &operator=(const field_collection &) = delete;
field_collection(field_collection &&) = default;
field_collection &operator=(field_collection &&) = default;

struct collection_iterator {
size_t pos_;
// TODO this is a bit hacky, but I think good enough for now,
// the clean solution would be to iterate over a list of s
field_collection< T > &collection_;

collection_iterator(size_t pos, field_collection< T > &collection) : pos_(pos), collection_(collection) {}

field_collection< T > &operator*() {
collection_.active_iteration_ = pos_; // TODO
return collection_;
};

collection_iterator &operator++() {
pos_++;
return *this;
}

collection_iterator operator++(int) {
collection_iterator tmp(*this);
operator++();
return tmp;
}

bool operator==(const collection_iterator &other) const { return pos_ == other.pos_; }
bool operator!=(const collection_iterator &other) const { return !operator==(other); }
};

/**
* @brief Attach a reference serializer to the collection.
Expand Down Expand Up @@ -141,11 +186,21 @@ namespace gt_verification {
* @param field The field that has to be filled with data from disk
*/
template < typename FieldType >
void register_input_field(const std::string &fieldname, FieldType &field, bool also_previous = false) noexcept {
GV_DEPRECATED_REASON(void register_input_field(
const std::string &fieldname, FieldType &field, bool also_previous = false) noexcept,
"Use the c++11 iterator with iterator.load_input(...).") {
inputFields_.push_back(
internal::input_field< T >{fieldname, type_erased_field_view< T >(field), also_previous});
}

template < typename FieldType >
void load_input(const std::string &fieldname, FieldType &field) {
serialization serialization(referenceSerializer_);
auto inputSavepoint = iterations_[active_iteration_].input;
type_erased_field_view< T > f(field);
serialization.load(fieldname, f, inputSavepoint);
}

/**
* @brief Register an output field for verification
*
Expand All @@ -157,27 +212,56 @@ namespace gt_verification {
* @param metric The metric which is used to check the field
*/
template < typename FieldType >
void register_output_and_reference_field(
const std::string &fieldname, FieldType &field, boundary_extent boundary = boundary_extent()) noexcept {
GV_DEPRECATED_REASON(
void register_output_and_reference_field(
const std::string &fieldname, FieldType &field, boundary_extent boundary = boundary_extent()) noexcept,
"Use the c++11 iterator with iterator.verify_output(...).") {
boundaries_.push_back(boundary);
outputFields_.push_back(std::make_pair(fieldname, type_erased_field_view< T >(field)));

// Construct new field holding the reference data
referenceFields_.push_back(std::make_pair(fieldname, type_erased_field< T >(field)));
}

/**
* @brief verify an output field
*
* This is a new interface where you don't register the output field but call the verify with the field.
*/
template < typename FieldType >
verification_result add_output(const std::string &fieldname,
FieldType &field,
const error_metric_interface< T > &error_metric,
boundary_extent boundary = boundary_extent()) noexcept {

auto refSavepoint = iterations_[active_iteration_].output;

type_erased_field< T > reference_field(field);

serialization serialization(referenceSerializer_);
serialization.load(fieldname, reference_field.to_view(), refSavepoint);

verifications_.emplace_back(type_erased_field_view< T >(field), reference_field.to_view(), boundary);
result_.merge(verifications_.back().verify(error_metric));

return result_;
}

/**
* @brief Loads input values and reference values from disk into the input- and reference fields
*
* After this the computations and verification can take place.
*/
void load_iteration(int iteration) {
GV_DEPRECATED_REASON(void load_iteration(int iteration),
"Use the c++11 iterator with iterator.load_input(...) and iterator.verify_output(...).") {
if (iteration >= (int)iterations_.size())
error::fatal(boost::format("invalid access of iteration '%i' (there are only %i iterations)") %
iteration % iterations_.size());

serialization serialization(referenceSerializer_);

active_iteration_ = iteration;

auto inputSavepoint = iterations_[iteration].input;
auto refSavepoint = iterations_[iteration].output;

Expand Down Expand Up @@ -226,10 +310,9 @@ namespace gt_verification {
* @brief Report failures depending on values set in VerificationReporter
*/
void report_failures() const noexcept {
verification_reporter verificationReporter(verificationSpecification_);
for (const auto &verification : verifications_)
if (!verification) {
verificationReporter.report(verification);
reporter_.report(verification);
}
}

Expand All @@ -248,6 +331,24 @@ namespace gt_verification {
*/
const std::vector< internal::savepoint_pair > &iterations() const noexcept { return iterations_; }

collection_iterator begin() { return collection_iterator(0, *this); }
collection_iterator end() { return collection_iterator(iterations_.size(), *this); }

/**
* @brief reports errors and resets the error state
*/
verification_result verify_collection() {
if (!result_.passed())
report_failures();

verification_result tmp = result_;
verifications_.clear();
result_.clear();
return tmp;
}

int active_iteration_;

private:
std::string name_;
std::shared_ptr< ser::serializer > referenceSerializer_;
Expand All @@ -260,7 +361,8 @@ namespace gt_verification {
std::vector< std::pair< std::string, type_erased_field< T > > > referenceFields_;
std::vector< boundary_extent > boundaries_;

verification_specification verificationSpecification_;
verification_reporter reporter_;
std::vector< verification< T > > verifications_;
verification_result result_;
};
}
7 changes: 4 additions & 3 deletions src/verification/unittest_environment.h
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ namespace gt_verification {
skipped_.push_back(spname);
}

return collection;
return std::move(collection);
}

void skip_test(std::string spname = "");
Expand Down Expand Up @@ -127,8 +127,9 @@ namespace gt_verification {
* otherwise
*/
template < typename T >
testing::AssertionResult verify_collection(
field_collection< T > &fieldCollection, const error_metric_interface< T > &errorMetric) {
GV_DEPRECATED_REASON(testing::AssertionResult verify_collection(field_collection< T > &fieldCollection,
const error_metric_interface< T > &errorMetric),
"Consider calling verify_collection on the collection instead.") {
verification_result result = fieldCollection.verify(errorMetric);
if (!result.passed())
fieldCollection.report_failures();
Expand Down
4 changes: 2 additions & 2 deletions src/verification/verification_reporter.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ namespace gt_verification {
*
* @ingroup DycoreUnittestVerificationLibrary
*/
class verification_reporter : private boost::noncopyable {
class verification_reporter {
protected:
template < typename T >
void list_failures(const verification< T > &verif) const noexcept {
Expand Down Expand Up @@ -176,7 +176,7 @@ namespace gt_verification {
}

public:
verification_reporter(const verification_specification verifSpec) : verifSpec_(verifSpec){};
verification_reporter(const verification_specification &verifSpec) : verifSpec_(verifSpec){};

/**
* @brief Report failures to console
Expand Down
6 changes: 5 additions & 1 deletion src/verification/verification_result.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,6 @@ namespace gt_verification {
*/
class verification_result {
public:
verification_result() : passed_(true), msg_("") {}
verification_result(const verification_result &) = default;
verification_result(verification_result &&) = default;
verification_result &operator=(const verification_result &) = default;
Expand Down Expand Up @@ -77,6 +76,11 @@ namespace gt_verification {
msg_ += " " + result.msg() + "\n";
}

void clear() noexcept {
passed_ = true;
msg_ = "\n";
}

/**
* @brief Check if any test failed
*/
Expand Down