Commits (22)
......@@ -135,7 +135,7 @@ std::string to_string(const T& _t)
#define DEB_enter_func \
PROGRESS_TICK; \
static int deb_nmbr = 0; \
static int deb_lvl = Debug::INVALID_LEVEL; \
static int deb_lvl = ::Debug::INVALID_LEVEL; \
::Debug::Enter deb(__FILE__, __FUNCTION__, deb_nmbr, deb_lvl);
#define DEB_only(CC) CC
......
......@@ -7,7 +7,7 @@
#include "DebUtils.hh"
#include "DebConfig.hh"
#include "Base/Code/CodeLink.hh"
#include "Base/Test/ChecksumDebugEvent.hh"
#include "Base/Test/TestChecksumDebugEvent.hh"
namespace Debug
{
......
......@@ -42,13 +42,13 @@ private:
} //namespace Debug
#define DEB_time_session(SSSN, LL) PROGRESS_TICK; \
Debug::StopWatchSession __sw_sssn(deb, SSSN, LL);
::Debug::StopWatchSession __sw_sssn(deb, SSSN, LL);
#define DEB_time_session_def(SSSN) PROGRESS_TICK; \
Debug::StopWatchSession __sw_sssn(deb, SSSN, 2);
::Debug::StopWatchSession __sw_sssn(deb, SSSN, 2);
#define DEB_time_func(LL) DEB_enter_func \
Debug::StopWatchSession __sw_func(deb, __FUNCTION__, LL);
::Debug::StopWatchSession __sw_func(deb, __FUNCTION__, LL);
#define DEB_time_func_def DEB_time_func(2)
......
......@@ -63,7 +63,13 @@ void Context::abort()
// https://akrzemi1.wordpress.com/2011/09/21/destructors-that-throw/
// But we rather just wait until the current exception is handled.
if (!abrt_alwd_ || std::uncaught_exception())
if (!abrt_alwd_ ||
#ifdef __APPLE__
std::uncaught_exception()
#else // __APPLE__
std::uncaught_exceptions()
#endif // __APPLE__
)
return;
abrt_stte_ = AST_PROCESSING;
BASE_THROW_ERROR(PROGRESS_ABORTED);
......
......@@ -23,6 +23,7 @@
#include <xlocnum>
#include <xutility>
#include <xatomic.h>
#include <xhash>
#if _MSC_VER >= 1920 // Visual Studio 2019 or later
#include <atomic>
......
// (C) Copyright 2021 by Autodesk, Inc.
#ifndef BASE_LONGESTCOMMONSUBSEQUENCET_HH_INCLUDED
#define BASE_LONGESTCOMMONSUBSEQUENCET_HH_INCLUDED
#include <algorithm>
#include <vector>
#include <limits>
namespace Test {
/*!
The dynamic programming version of the longest common subsequence algorithm,
O(n*m), n = a.size(), m = b.size() execution and storage complexity.
References:
https://en.wikipedia.org/wiki/Longest_common_subsequence_problem
https://rosettacode.org/wiki/Longest_common_subsequence
*/
template <class VectorT>
class LongestCommonSubsequenceT
{
public:
typedef VectorT Vector;
typedef int Index;
enum { INVALID_INDEX = -1 };
typedef std::vector<Index> Subsequence;
struct IndexPair
{
Index i, j;
IndexPair() : i(INVALID_INDEX), j(INVALID_INDEX) {}
IndexPair(const Index _i, const Index _j) : i(_i), j(_j) {}
bool i_valid() const { return i != INVALID_INDEX; }
bool j_valid() const { return j != INVALID_INDEX; }
bool valid() const { return i_valid() || j_valid(); }
bool matched() const { return i_valid() && j_valid(); }
bool boundary() const { return i == 0 || j == 0; }
bool interior() const { return i > 0 && j > 0; }
void move_up() { --i; }
void move_left() { --j; }
void move_up_left() { move_up(), move_left(); }
};
typedef std::vector<IndexPair> IndexPairVector;
public:
//! Constructor from the two vectors, a and b, to compare
LongestCommonSubsequenceT(const Vector& _a, const Vector& _b)
: a_(_a), b_(_b), trc_(_a.size(), _b.size())
{}
const Vector& a() const { return a_; }
const Vector& b() const { return b_; }
Index a_size() const { return (Index)a_.size(); }
Index b_size() const { return (Index)b_.size(); }
/*!
Trace and record the longest common subsequence (LCS) and return its size.
The LCS or the difference wrt to a_ and b_ can be extracted correspondingly
with \ref extract(), \ref removed() and \ref added().
*/
Index trace()
{
auto i = a_size();
auto j = b_size();
if (i == 0 || j == 0) // guard against trivial input
return 0;
std::vector<typename Trace::Type> stck;
stck.reserve(i + j);
do
{
if (i == 0 || j == 0 || trace(i, j).done())
{// boundary case or trace_ij already traced, so pop the stack
const auto trc_type = stck.back();
stck.pop_back();
switch (trc_type)
{
case Trace::APPEND : // popping from an APPEND, go up the tree
++i, ++j;
trace(i, j).set(Trace::APPEND, trace_size(i - 1, j - 1) + 1);
break;
case Trace::MOVE_LEFT : // popping from a MOVE_LEFT branch
++j, --i;
stck.push_back(Trace::MOVE_UP); // now push into the MOVE_UP branch
break;
case Trace::MOVE_UP : // popping from a MOVE_UP branch, close the node
{
++i;
const auto size_left = trace_size(i, j - 1);
const auto size_up = trace_size(i - 1, j);
// different solutions are possible based on whether we use >= or >
if (size_left >= size_up)
trace(i, j).set(Trace::MOVE_LEFT, size_left);
else
trace(i, j).set(Trace::MOVE_UP, size_up);
}
break;
default: break;// should not reach this
}
}
else if (a_[i - 1] == b_[j - 1]) // same element?
{// the result is the LCS(i, j) + a_[i - 1]
--i, --j;
stck.push_back(Trace::APPEND);
}
else
{// different elements, so we branch here, going to the left first
--j;
stck.push_back(Trace::MOVE_LEFT);
}
}
while (!stck.empty());
return trace_size(i, j);
}
//! Extract the LCS indices wrt to either a_ or b_, or both
void extract(Subsequence* const _a_sbsqn, Subsequence* const _b_sbsqn) const
{
backtrace(_a_sbsqn, _b_sbsqn);
}
//! Extract the LCS elements (rather than indices) for convenience.
void extract(Vector& _sbsqn) const
{
Subsequence sbsqn;
extract(&sbsqn, nullptr);
_sbsqn.resize(sbsqn.size());
for (size_t i = 0, n = sbsqn.size(); i < n; ++i)
_sbsqn[i] = a_[sbsqn[i]];
}
//! Extract the difference indices, either from a_ or b_
void difference(Subsequence* const _a_sbsqn, Subsequence* const _b_sbsqn) const
{
Subsequence a_sbsqn, b_sbsqn;
Subsequence* const a_subsqn_ptr = _a_sbsqn == nullptr ? nullptr : &a_sbsqn;
Subsequence* const b_subsqn_ptr = _b_sbsqn == nullptr ? nullptr : &b_sbsqn;
extract(a_subsqn_ptr, b_subsqn_ptr);
difference(a_subsqn_ptr, b_subsqn_ptr, _a_sbsqn, _b_sbsqn);
}
//! Extract the matched/mis-matched indices, from both a_ and b_
void match(IndexPairVector& _mtch) const
{
// extract the LCS indices for both a and b
Subsequence a_sbsqn, b_sbsqn;
backtrace(&a_sbsqn, &b_sbsqn);
// reserve space
_mtch.reserve(a_size() + b_size() - a_sbsqn.size());
Index i0 = 0, j0 = 0;
// extract the mis-matched a_ and b_ indices from (i0, j0) to (_i1, _j1)
auto mismatch = [&i0, &j0, &_mtch](const Index _i1, const Index _j1)
{
// add the mis-matched a_ indices from [i0.._i1)
for (Index i = i0; i < _i1; ++i)
_mtch.push_back(IndexPair(i, INVALID_INDEX));
// add the mis-matched b_ indices from [j0.._j1)
for (Index j = j0; j < _j1; ++j)
_mtch.push_back(IndexPair(INVALID_INDEX, j));
// update i0, j0
i0 = _i1 + 1;
j0 = _j1 + 1;
};
for (size_t k = 0, l = a_sbsqn.size(); k < l; ++k)
{
mismatch(a_sbsqn[k], b_sbsqn[k]); // add mismatched elements
_mtch.push_back(IndexPair(a_sbsqn[k], b_sbsqn[k])); // add the match
}
// add the indices from the last match to the end
mismatch(a_size(), b_size());
}
private:
//! A very simple matrix-storage, enough for what we need here
template <class ElementT>
class MatrixT
{
public:
typedef ElementT Element;
public:
MatrixT(const size_t _row_nmbr, const size_t _col_nmbr)
: row_nmbr_(_row_nmbr), col_nmbr_(_col_nmbr)
, elmns_(row_nmbr_ * col_nmbr_)
{}
Element& operator()(const Index _i, const Index _j)
{
return elmns_[index(_i, _j)];
}
const Element& operator()(const Index _i, const Index _j) const
{
return elmns_[index(_i, _j)];
}
private:
size_t row_nmbr_;
size_t col_nmbr_;
std::vector<Element> elmns_;
private:
size_t index(const Index _row_idx, const Index _col_idx) const
{
return _row_idx * col_nmbr_ + _col_idx;
}
};
//! Add a flag to the subsequence to indicate if it has been computed
class Trace
{
public:
// these types correspond to all algorithm trace options
enum Type { UNKNOWN, APPEND, MOVE_LEFT, MOVE_UP };
public:
Trace() : type_(UNKNOWN) {}
void set(const Type _type, const Index _size)
{
type_ = _type, size_ = _size;
}
bool done() const { return type_ != UNKNOWN; }
Index size() const { return size_; }
bool append() const { return type_ == APPEND; }
//! Return the address of the next trace
IndexPair next(const Index _i, const Index _j) const
{
IndexPair ij(_i, _j);
switch (type_)
{
case APPEND : ij.move_up_left(); break;
case MOVE_LEFT : ij.move_left(); break;
case MOVE_UP : ij.move_up(); break;
default: ;// should not reach this
}
return ij;
}
IndexPair next(const IndexPair& _ij) const { return next(_ij.i, _ij.j); }
private:
Type type_;
Index size_;
};
typedef MatrixT<Trace> TraceMatrix;
private:
const Vector& a_;
const Vector& b_;
TraceMatrix trc_; // O(n*m) subsequence trace storage
private:
const Trace& trace(const Index _i, const Index _j) const
{
return trc_(_i - 1, _j - 1);
}
const Trace& trace(const IndexPair& _ij) const { return trace(_ij.i, _ij.j); }
Trace& trace(const Index _i, const Index _j)
{
return trc_(_i - 1, _j - 1);
}
Trace& trace(const IndexPair& _ij) { return trace(_ij.i, _ij.j); }
Index trace_size(const Index _i, const Index _j) const
{
if (_i == 0 || _j == 0) // these cases are not traced, size is always 0
return 0;
return trace(_i, _j).size();
}
Index trace_size(const IndexPair& _ij) const
{
return trace_size(_ij.i, _ij.j);
}
void backtrace(Subsequence* const _a_sbsqn, Subsequence* const _b_sbsqn) const
{
for (IndexPair ij(a_size(), b_size()); ij.interior(); )
{
const auto& trc = trace(ij); // the ij-trace
if (!trc.done())// trace() has not been called/something has gone wrong?
return; // ... just get out of here, instead of crashing
ij = trc.next(ij); // this decreases the indices appropriately for append
if (trc.append()) // append, so add i and/or j
{
if (_a_sbsqn != nullptr)
_a_sbsqn->push_back(ij.i);
if (_b_sbsqn != nullptr)
_b_sbsqn->push_back(ij.j);
}
}
if (_a_sbsqn != nullptr)
std::reverse(_a_sbsqn->begin(), _a_sbsqn->end());
if (_b_sbsqn != nullptr)
std::reverse(_b_sbsqn->begin(), _b_sbsqn->end());
}
void difference(const Subsequence& _sqnc, const Subsequence& _sbsqn,
Subsequence& _diff) const
{
const auto n = _sqnc.size();
const auto m = _sbsqn.size();
_diff.reserve(n - m);
for (size_t i = 0, j = 0; i < n; ++i)
{
if (j < m && i == _sbsqn[j])
++j; // i is contained in _sbsqn, so not in diff
else
_diff.push_back(i);
}
}
//! Disable copy
LongestCommonSubsequenceT(const LongestCommonSubsequenceT&);
//! Disable assignment
LongestCommonSubsequenceT& operator=(const LongestCommonSubsequenceT&);
};
}// namespace Test
#endif//BASE_LONGESTCOMMONSUBSEQUENCET_HH_INCLUDED
// (C) Copyright 2019 by Autodesk, Inc.
// (C) Copyright 2021 by Autodesk, Inc.
#ifdef TEST_ON
#include "Checksum.hh"
#include "TestChecksum.hh"
#include "Base/Debug/DebCallStack.hh"
#include <fstream>
#include <iostream>
#include <map>
#include <mutex>
namespace Test {
namespace Checksum {
namespace Test
{
namespace Checksum
{
Level run_lvl = L_NONE;
namespace {
namespace
{
/*!
Definition of the checksums registry. It is a map from a string (that is the
checksum name to an Checksum::Object.
*/
typedef std::map<String, Object*> Registry;
Registry& registry_modify()
{
......@@ -28,6 +37,15 @@ const Registry& registry()
return registry_modify();
}
Difference compare_from_registry(
const String& _name, const Record& _old_rcrd, const Record& _new_rcrd)
{
auto reg_it = registry().find(_name);
return reg_it == registry().end()
? Difference(Difference::UNKNOWN, "Checksum not registered")
: reg_it->second->compare(_old_rcrd, _new_rcrd);
}
///////////////////////////////////////////////////////////////////////////////
// class Checksum implementation
......@@ -49,7 +67,7 @@ Difference Object::compare_data(const String& _old, const String& _new) const
String diff;
diff.resize((std::max(_old.length(), _new.length())));
for (int i = 0; i < diff.size(); ++i)
for (size_t i = 0; i < diff.size(); ++i)
{
diff[i] = i < _old.length() && i < _new.length() && _old[i] == _new[i] ?
' ' : '*';
......@@ -58,11 +76,7 @@ Difference Object::compare_data(const String& _old, const String& _new) const
}
Difference Object::compare(
const Path& /*_old_path*/,
const Record& _old_rcrd,
const Path& /*_new_path*/,
const Record& _new_rcrd
) const
const Record& _old_rcrd, const Record& _new_rcrd) const
{
const auto old_rslt_type = _old_rcrd.rslt.type();
const auto new_rslt_type = _new_rcrd.rslt.type();
......@@ -132,6 +146,8 @@ Difference Object::compare(
default: ; // disable warnings
};
break;
case Result::TYPE_NUMBER:
; // make compilers happy
}
return data_diff;
}
......
// (C) Copyright 2020 by Autodesk, Inc.
#ifndef BASE_ICHECKSUM_HH_INCLUDE
#define BASE_ICHECKSUM_HH_INCLUDE
// (C) Copyright 2021 by Autodesk, Inc.
#ifndef BASE_TESTCHECKSUM_HH_INCLUDED
#define BASE_TESTCHECKSUM_HH_INCLUDED
#ifndef TEST_ON
#define TEST(CHKSM, RCRD)
......@@ -11,24 +10,14 @@
#else
#include <Base/Test/TestResult.hh>
#include <Base/Test/TestChecksumLevel.hh>
#include <Base/Utils/OStringStream.hh>
#include <map>
#include <sstream>
namespace Test
{
namespace Checksum
{
//! Enumerate the checksum levels
enum Level
{
L_NONE,
L_STABLE,
L_PRIME,
L_ALL
};
extern Level run_lvl; //<! The checksum run level
extern Level run_lvl; //<! The global checksum run level
const char* const LEVEL_TEXT[4] = {"NONE", "STABLE", "PRIME", "ALL"};
//! typedef String, this is used a lot in this namespace
......@@ -53,17 +42,17 @@ public:
EQUAL, // result is bitwise identical
UNKNOWN, // non-negligible difference, but of unknown quality
IMPROVED, // result is better
NEGLEGIBLE, // result is negligibly different
NEGLIGIBLE, // result is negligibly different
SUSPICIOUS, // result is different, and the new result might be worse
REGRESSED, // result is worse
WORKED, // result works now, but used to fail
FAILED // result fails now, but used to work
};
static const char* const type_text(const Type _type)
static const char* type_text(const Type _type)
{
static const char dscr[][32] = {"EQUAL", "UNKNOWN", "IMPROVED",
"NEGLEGIBLE", "SUSPICIOUS", "REGRESSED", "WORKED", "FAILED"};
"NEGLIGIBLE", "SUSPICIOUS", "REGRESSED", "WORKED", "FAILED"};
return dscr[_type];
}
......@@ -72,7 +61,7 @@ public:
{
}
const Type type() const { return type_; }
Type type() const { return type_; }
bool equal() const { return type() == EQUAL; }
bool operator==(const Difference& _othr) const
......@@ -94,13 +83,13 @@ public:
Difference& operator+=(const Difference::Type& _type)
{
if (type_ < _type)
type_ = type_;
type_ = _type;
return *this;
}
const String& description() const { return dscr_; }
const char* const type_text() const { return type_text(type_); }
const char* type_text() const { return type_text(type_); }
friend Base::IOutputStream& operator<<(
Base::IOutputStream& _os, Difference& _diff)
......@@ -125,7 +114,7 @@ class Object
{
public:
//! Checksum name.
const char* const name() const { return name_; }
const char* name() const { return name_; }
//! Add a record the checksum (generic version)
template <typename T> void record(const Result& _rslt, const T& _data)
......@@ -145,9 +134,7 @@ public:
results, but compares the the data simply as strings (no parsing).
*/
virtual Difference compare(
const Path& _old_path, //!<[in] Path to the left record
const Record& _old_rcrd, //!<[in] "Left" record
const Path& _new_path, //!<[in] Path to the right record
const Record& _new_rcrd //!<[in] "Right" record
) const;
......@@ -164,11 +151,16 @@ protected:
//! Add a record of the checksum (protected version)
void add(const Result& _rslt, const String& _data);
//! Compare the data, the default implementation does a string comparison
/*!
Compare the data, the default implementation does a string comparison.
This is called by \ref compare to compare the data only without taking into
account the type of the result. This can be overridden instead of \ref compare
if the result type is insignificant for the comparison.
*/
virtual Difference compare_data(const String& _old, const String& _new) const;
protected:
const Level lvl_;
const Level lvl_; // the checksum level
private:
const char* const name_;
......@@ -178,34 +170,22 @@ private:
Object* operator=(const Object&);
};
/*!
Definition of the checksums registry. It is a map from a string (that is the
checksum name to an IChecksum.
*/
typedef std::map<String, Object*> Registry;
/*!
Function to get a static map with all the registered checksums.
*/
const Registry& registry();
} // namespace Checksum
} // namespace Test
#define TEST(CHKSM, RCRD) \
#define TEST(CHKSM_OBJ, RCRD_FN) \
{ \
if (Test::Checksum::CHKSM.allow()) \
if (Test::Checksum::CHKSM_OBJ.allow()) \
{ \
Test::Checksum::CHKSM.RCRD; \
Test::Checksum::CHKSM_OBJ.RCRD_FN; \
} \
}
#define TEST_if(CNDT, CHKSM, RCRD) \
#define TEST_if(CNDT, CHKSM_OBJ, RCRD_FN) \
{ \
if (CNDT) \
TEST(CHKSM, RCRD) \
TEST(CHKSM_OBJ, RCRD_FN) \
}
#endif // TEST_ON
#endif // BASE_ICHECKSUM_HH_INCLUDE
#endif // BASE_TESTCHECKSUM_HH_INCLUDED
// (C) Copyright 2021 by Autodesk, Inc.
#ifndef BASE_TESTCHECKSUMCOMPARE_HH_INCLUDED
#define BASE_TESTCHECKSUMCOMPARE_HH_INCLUDED
#ifdef TEST_ON
#include <Base/Test/TestChecksum.hh>
#include <functional>
namespace Test
{
namespace Checksum
{
/*!
Function type to compare two records of the same checksum identified by name.
The compare function should return \ref Difference value to describe the
difference of the old vs the new value.
*/
typedef std::function<Difference(const String& /*!<[in] checksum name */,
const Record& /*!<[in] checksum old value */,
const Record& /*!<[in] checksum new value */)>
Compare;
/*!
Compare function that uses the compare method of registered checksums.
\note Make sure to wrap this appropriately for shared object export when using
in shared binary components in order to use the registry in the shared binary!
*/
Difference compare_from_registry(
const String& _name, const Record& _old_rcrd, const Record& _new_rcrd);
} // namespace Checksum
} // namespace Test
#endif // TEST_ON
#endif // BASE_TESTCHECKSUMCOMPARE_HH_INCLUDED
// (C) Copyright 2021 by Autodesk, Inc.
#ifdef TEST_ON
#include "TestChecksumCompletion.hh"
#include <Base/Test/TestChecksum.hh>
#include <Base/Test/TestChecksumNumberT.hh>
#include <chrono>
#include <fstream>
#ifdef __APPLE__
#include <boost/filesystem.hpp>
#else // __APPLE__
// Include <filesystem> but silence resulting C4995 warnings
INSECURE_INCLUDE_SECTION_BEGIN
#include <filesystem>
INSECURE_INCLUDE_SECTION_END
#endif // __APPLE__
namespace Test
{
namespace Checksum
{
namespace
{
#ifdef __APPLE__
namespace fs = boost::filesystem;
#else // __APPLE__
namespace fs = std::filesystem;
#endif // __APPLE__
const char* const END = "END";
const char* const TIMEOUT = "Timeout";
const char* const UNKNOWN_EXCEPTION = "UnknownException";
const char* const NOT_HANDLED_EXCEPTION = "NotHandledException";
// Should be called only if the test has not terminated correctly (process exit
// has not been logged) and returns one of these 3 results:
// NOT_HANDLED_EXCEPTION (a crash)
// TIMEOUT (test has been terminated by the test system because it was taking
// too much time) UNKNOWN_EXCEPTION (we are not able to find the cause of test
// termination).
const char* find_failure(const Path& _dir)
{
// There has been a crash or a time out. A test timeout has been logged in a
// file called test.log in a parent directory of current test directory.
// Here we go back in the directory structure looking for test.log.
Path search = _dir;
std::ifstream test_log;
while (!search.empty())
{
search = search.parent_path();
if (fs::exists(search / "test.log"))
{
test_log.open((search / "test.log").string());
break;
}
}
if (!test_log.good())
return UNKNOWN_EXCEPTION; // Impossible to find the test termination problem.
// test.log contains a list of failing tests in the following format:
/*
The following tests FAILED:
18 - synthetic/box_open_25.cc (SEGFAULT)
19 - synthetic/box_open_08.cc (Failed)
20 - ReCap/OilPump_prep.off (Timeout)
...
*/
// The following code looks for lines with a ")" at the line end and a "-"
// in the middle, extracts the test name, checks if it is the one we are
// processing and checks if the string inside () is Timeout to decide if it
// is a hang or a crash.
std::string line;
while (std::getline(test_log, line))
{
if (line.empty() || line.back() != ')')
continue;
auto test_name_start = line.find_first_of('-');
if (test_name_start == std::string::npos)
continue;
test_name_start += 2;
auto res_pos = line.find_last_of('(');
if (res_pos == std::string::npos)
continue;
auto test_name_end = res_pos - 1;
auto test_name = line.substr(test_name_start, test_name_end - test_name_start);
Path test_dir(test_name);
// Checks if the last part of the directory name is equal to the test name
// in order to select the line reporting the result of the current test.
auto test_path_it = test_dir.begin();
auto dir_it = _dir.begin();
while (dir_it != _dir.end() && *dir_it != *test_path_it)
++dir_it;
while (dir_it != _dir.end() && test_path_it != test_dir.end() &&
*dir_it == *test_path_it)
{
++dir_it;
++test_path_it;
}
if (dir_it != _dir.end() || test_path_it != test_dir.end())
continue;
// Check if test.log reports a timeout.
if (line.substr(res_pos) == "(Timeout)")
return TIMEOUT;
else
return NOT_HANDLED_EXCEPTION;
}
return UNKNOWN_EXCEPTION;
}
} // namespace
Completion::Completion()
: Object("Completion", L_STABLE),
start_time_(std::chrono::system_clock::now())
{
}
void Completion::record_end()
{
auto end_time = std::chrono::system_clock::now();
std::chrono::duration<double> time_diff_sec = end_time - start_time_;
std::stringstream mess;
mess << "Success: " << END << " Time: " << time_diff_sec.count();
add(Result::OK, mess.str());
}
Result Completion::report_failure(const Path& _dir, std::string& _descr)
{
auto err_descr = find_failure(_dir);
_descr = err_descr;
return err_descr == TIMEOUT ? Result::HANG : Result::CRASH;
}
bool Completion::end(const std::string& _line)
{
return _line.find(Checksum::completion.name()) != std::string::npos &&
_line.find(END) != std::string::npos;
}
// Register the checksum to check test completion.
Completion completion;
} // namespace Checksum
} // namespace Test
#endif // TEST_ON
// (C) Copyright 2021 by Autodesk, Inc.
#ifndef BASE_CHECKSUMCOMPLETION_HH_INCLUDE
#define BASE_CHECKSUMCOMPLETION_HH_INCLUDE
#ifdef TEST_ON
#include <Base/Security/Mandatory.hh>
#include <Base/Test/TestChecksum.hh>
#include <chrono>
#include <string>
namespace Test
{
namespace Checksum
{
// Checks it the test has completed and, if not, detect the problem for compare.
class Completion : public Object
{
public:
Completion();
//! Record the test "end" completion checksum
void record_end();
//! Get if the line contains the end completion checksum record
static bool end(const std::string& _line);
/*!
Obtain the report failure type and description.
Analyzes the report folder for a test that has failed to record the end
completion checksum. This means that the test has either crashed or hung.
*/
static Result report_failure(const Path& _dir, std::string& _descr);
private:
std::chrono::time_point<std::chrono::system_clock> start_time_;
};
// Register the checksum to check test completion.
extern Completion completion;
} // namespace Checksum
} // namespace Test
#endif // TEST_ON
#endif // BASE_CHECKSUMCOMPLETION_HH_INCLUDE
// (C) Copyright 2019 by Autodesk, Inc.
// (C) Copyright 2021 by Autodesk, Inc.
#if defined(TEST_ON)
#include "ChecksumCondition.hh"
#include "TestChecksumCondition.hh"
#include "TestResult.hh"
#include "Base/Code/CodeLink.hh"
......
// (C) Copyright 2019 by Autodesk, Inc.
// (C) Copyright 2021 by Autodesk, Inc.
#ifndef REFORM_CHECKSUMCONDITION_HH_INCLUDED
#define REFORM_CHECKSUMCONDITION_HH_INCLUDED
#ifndef BASE_CHECKSUMCONDITION_HH_INCLUDED
#define BASE_CHECKSUMCONDITION_HH_INCLUDED
#include <Base/Debug/DebOut.hh>
#include <Base/Test/Checksum.hh>
#include <Base/Test/TestChecksum.hh>
#if defined(TEST_ON)
// The functions in this file are used to count the number of errors and warnings
// and makes sense only if both the debug and test macro are on.
// The functions in this file are used to count the number of errors and
// warnings and makes sense only if both the debug and test macro are on.
namespace Base {
namespace Base
{
struct CodeLink;
}//namespace Base
} // namespace Base
namespace Test {
namespace Checksum {
namespace Test
{
namespace Checksum
{
class Condition : public Object
{
public:
Condition() : Object("Condition", L_STABLE), nmbr_(0), fail_nmbr_(0) {}
virtual void record(const char* const _cndt, const Base::CodeLink& _lnk,
const bool _rslt);
virtual void record(
const char* const _cndt, const Base::CodeLink& _lnk, const bool _rslt);
virtual void record_number();
protected:
......@@ -32,15 +35,15 @@ protected:
virtual Difference compare_data(const String& _old, const String& _new) const;
protected:
int nmbr_; //number of all checked conditions
int nmbr_; // number of all checked conditions
int fail_nmbr_; // number of failed checked conditions
};
extern Condition condition;
}//namespace Checksum
}//namespace Test
} // namespace Checksum
} // namespace Test
#endif//defined(TEST_ON)
#endif // defined(TEST_ON)
#endif//REFORM_CHECKSUMCONDITION_HH_INCLUDED
#endif // BASE_CHECKSUMCONDITION_HH_INCLUDED
// (C) Copyright 2019 by Autodesk, Inc.
// (C) Copyright 2021 by Autodesk, Inc.
#if defined(TEST_ON) && defined(DEB_ON)
#include "ChecksumDebugEvent.hh"
#include "TestChecksumDebugEvent.hh"
#include "TestResult.hh"
#include "Base/Code/CodeLink.hh"
#include "Base/Debug/DebOut.hh"
......
// (C) Copyright 2019 by Autodesk, Inc.
// (C) Copyright 2021 by Autodesk, Inc.
#ifndef BASE_CHECKSUMCOUNT_HH_INCLUDE
#define BASE_CHECKSUMCOUNT_HH_INCLUDE
#include <Base/Debug/DebOut.hh>
#include <Base/Test/Checksum.hh>
#include <Base/Test/TestChecksum.hh>
#if defined(TEST_ON) && defined(DEB_ON)
......
// (C) Copyright 2021 by Autodesk, Inc.
#ifdef TEST_ON
#include "TestChecksumExecution.hh"
#include <string>
namespace Test
{
namespace Checksum
{
Execution::Execution() : Object("Execution", L_STABLE) {}
void Execution::record(
const char* const _call, const Result& _rslt, const char* _err_msg)
{
Base::OStringStream mess;
mess << _err_msg << " : " << _call;
add(_rslt, mess.str);
}
// Register the checksum to check test execution.
Execution exec;
} // namespace Checksum
} // namespace Test
#endif // TEST_ON
// (C) Copyright 2021 by Autodesk, Inc.
#ifndef BASE_CHECKSUMEXEC_HH_INCLUDE
#define BASE_CHECKSUMEXEC_HH_INCLUDE
#ifdef TEST_ON
#include <Base/Test/TestChecksum.hh>
namespace Test
{
namespace Checksum
{
// Logs the returned result of a (function) call along with any associated error
// message.
class Execution : public Object
{
public:
Execution();
void record(
const char* const _call, const Result& _rslt, const char* _err_msg);
};
// Register the checksum to check test execution.
extern Execution exec;
} // namespace Checksum
} // namespace Test
#endif // TEST_ON
#endif // BASE_CHECKSUMEXEC_HH_INCLUDE
// (C) Copyright 2019 by Autodesk, Inc.
// (C) Copyright 2021 by Autodesk, Inc.
#ifdef TEST_ON
#include "ChecksumFile.hh"
#include "TestChecksumFile.hh"
#include "Base/Utils/OStringStream.hh"
#include <functional>
......
// (C) Copyright 2019 by Autodesk, Inc.
// (C) Copyright 2021 by Autodesk, Inc.
#ifndef BASE_CHECKSUMFILE_HH_INCLUDE
#define BASE_CHECKSUMFILE_HH_INCLUDE
#ifdef TEST_ON
#include <Base/Test/Checksum.hh>
#include <Base/Test/TestChecksum.hh>
namespace Test {
namespace Checksum {
......
// (C) Copyright 2020 by Autodesk, Inc.
// (C) Copyright 2021 by Autodesk, Inc.
#ifdef TEST_ON
#include "ChecksumIssueNumber.hh"
#include "TestChecksumIssueNumber.hh"
#include "TestResult.hh"
#include <sstream>
......