Commit 6ed6785b authored by Martin Marinov's avatar Martin Marinov

Merge branch 'ReForm-master' into merge-from-ReForm

parents 7de4bcb9 169fdc3a
// (C) Copyright 2016 by Autodesk, Inc.
//
// The information contained herein is confidential, proprietary
// to Autodesk, Inc., and considered a trade secret as defined
// in section 499C of the penal code of the State of California.
// Use of this information by anyone other than authorized
// employees of Autodesk, Inc. is granted only under a written
// non-disclosure agreement, expressly prescribing the scope
// and manner of such use.
#ifndef BASE_CODELINK_HH_INCLUDED
#define BASE_CODELINK_HH_INCLUDED
namespace Base {
class IOutputStream;
//! Convenient wrapper around a preprocessor source code link
struct CodeLink
{
CodeLink(
const char* _fnct,
const char* _file,
const int _line
)
: fnct(_fnct), file(_file), line(_line)
{}
const char* fnct;
const char* file;
int line;
};
IOutputStream& operator<<(IOutputStream& _os, const CodeLink& _lnk);
}//namespace Base
#define BASE_CODELINK ::Base::CodeLink(__FUNCTION__, __FILE__, __LINE__)
#endif//BASE_CODELINK_HH_INCLUDED
// (C) Copyright 2016 by Autodesk, Inc.
//
// The information contained herein is confidential, proprietary
// to Autodesk, Inc., and considered a trade secret as defined
// in section 499C of the penal code of the State of California.
// Use of this information by anyone other than authorized
// employees of Autodesk, Inc. is granted only under a written
// non-disclosure agreement, expressly prescribing the scope
// and manner of such use.
#ifndef BASE_DEBDEFAULT_HH_INCLUDED
#define BASE_DEBDEFAULT_HH_INCLUDED
namespace Debug {
namespace Default {
const char* const LOG_FILENAME = "reform_deb_out.txt";
}//Default
}//Debug
#endif//BASE_DEBDEFAULT_HH_INCLUDED
...@@ -15,9 +15,9 @@ ...@@ -15,9 +15,9 @@
#include <Base/Utils/BaseError.hh> #include <Base/Utils/BaseError.hh>
#include <Base/Debug/DebOut.hh> #include <Base/Debug/DebOut.hh>
namespace Debug { namespace Base {
inline Stream& operator<<(Stream& _ds, const Base::Error& _err) inline IOutputStream& operator<<(IOutputStream& _ds, const Base::Error& _err)
{ {
_ds << "\"" << _err.message() << "\""; _ds << "\"" << _err.message() << "\"";
return _ds; return _ds;
......
...@@ -13,7 +13,7 @@ ...@@ -13,7 +13,7 @@
#ifdef DEB_ON #ifdef DEB_ON
#include <string> #include <string>
#include "../Config/BaseDefines.hh" #include <Base/Config/BaseDefines.hh>
namespace Debug { namespace Debug {
......
This diff is collapsed.
This diff is collapsed.
#ifdef TEST_ON
#include "Checksum.hh"
#include <fstream>
#include <iostream>
namespace Test {
namespace Checksum {
namespace {
Registry& registry_modify()
{
static Registry chksm_reg;
return chksm_reg;
}
}//namespace
const Registry& registry()
{
return registry_modify();
}
///////////////////////////////////////////////////////////////////////////////
// class Checksum implementation
Object::Object(const char* _name)
: name_(_name)
{
auto pos = registry_modify().emplace(name_, this);
if (!pos.second)
{
std::cout << "Duplicate checksum definition: " << _name << std::endl;
throw;
}
}
Difference Object::compare_data(const String& _old, const String& _new) const
{
if (_old == _new)
return Difference::EQUAL;
String diff;
diff.resize((std::max(_old.length(), _new.length())));
for (int i = 0; i < diff.size(); ++i)
{
diff[i] = i < _old.length() && i < _new.length() && _old[i] == _new[i] ?
' ' : '*';
}
return Difference(Difference::UNKNOWN, diff);
}
Difference Object::compare(
const Path& /*_old_path*/,
const Record& _old_rcrd,
const Path& /*_new_path*/,
const Record& _new_rcrd
) const
{
const auto old_rslt_type = _old_rcrd.rslt.type();
const auto new_rslt_type = _new_rcrd.rslt.type();
auto data_diff = compare_data(_old_rcrd.data, _new_rcrd.data);
if (old_rslt_type == new_rslt_type) // same result, so just data compare
return data_diff;
// result types are different, qualify the difference
#define DIFFERENCE(TYPE) data_diff += Difference(Difference::TYPE)
switch (old_rslt_type)
{
case Result::OK :
{
return new_rslt_type == Result::WARNING ?
DIFFERENCE(SUSPICIOUS) : DIFFERENCE(REGRESSED);
}
case Result::WARNING :
{
return new_rslt_type == Result::OK ?
DIFFERENCE(IMPROVED) : DIFFERENCE(REGRESSED);
}
default : // ERROR, CRASH, HANG, etc
{
return new_rslt_type == Result::OK || new_rslt_type == Result::WARNING ?
DIFFERENCE(IMPROVED) : DIFFERENCE(UNKNOWN);
}
}
}
void Object::add(const Result& _rslt, const String& _data)
{
static Base::OutputStreamAdaptT<std::ofstream> test_str(REPORT_FILENAME);
test_str << _rslt << " " << name() << ": " << _data << Base::LF;
}
}//Checksum
}//namespace Test
#endif//TEST_ON
// (C) Copyright 2016 by Autodesk, Inc.
//
// The information contained herein is confidential, proprietary
// to Autodesk, Inc., and considered a trade secret as defined
// in section 499C of the penal code of the State of California.
// Use of this information by anyone other than authorized
// employees of Autodesk, Inc. is granted only under a written
// non-disclosure agreement, expressly prescribing the scope
// and manner of such use.
#ifndef BASE_ICHECKSUM_HH_INCLUDE
#define BASE_ICHECKSUM_HH_INCLUDE
#ifndef TEST_ON
#define TEST_only(CC)
#else
#include <Base/Test/TestResult.hh>
#include <Base/Utils/OStringStream.hh>
#include <map>
#include <sstream>
namespace Test {
namespace Checksum {
//! typedef String, this is used a lot in this namespace
typedef std::string String;
//! The checksum record
struct Record
{
Record() {}
Record(const Result& _rslt, const String _data) : rslt(_rslt), data(_data) {}
Result rslt; //! record result
String data; //!< recorded "data" (as string, can be parsed)
};
//! The difference found by the IChecksum::compare() operation
class Difference
{
public:
enum Type
{
EQUAL,
UNKNOWN,
IMPROVED,
NEGLEGIBLE,
SUSPICIOUS,
REGRESSED
};
static const char* const type_text(const Type _type)
{
static const char dscr[][32] =
{
"EQUAL",
"UNKNOWN",
"IMPROVED",
"NEGLEGIBLE",
"SUSPICIOUS",
"REGRESSED"
};
return dscr[_type];
}
Difference(const Type _type = EQUAL, const String& _dscr = String())
: type_(_type), dscr_(_dscr)
{}
const Type type() const { return type_; }
bool equal() const { return type() == EQUAL; }
bool operator==(const Difference& _othr) const
{
return type_ == _othr.type_ && dscr_ == _othr.dscr_;
}
Difference& operator+=(const Difference& _othr)
{
if (type_ < _othr.type_)
type_ = _othr.type_;
if (dscr_.empty())
dscr_ = _othr.dscr_;
else if (!_othr.dscr_.empty())
dscr_ += "; " + _othr.dscr_;
return *this;
}
Difference& operator+=(const Difference::Type& _type)
{
if (type_ < _type)
type_ = type_;
return *this;
}
const String& description() const
{
return dscr_;
}
const char* const type_text() const { return type_text(type_); }
friend Base::IOutputStream& operator<<(Base::IOutputStream& _os,
Difference& _diff)
{
// TODO: use string description array
return _os << _diff.type_text() << " " << _diff.dscr_;
}
private:
Type type_;
String dscr_;
};
/*!
Base class for test checksums. Whatever check we want to add in the test system,
it must be an instance of a class derived from Checksum. All derived classes
must be instantiated as global variables.
*/
class Object
{
public:
/*!
Performs an automatic registration of the new checksum in a
global list, and verifies that the name is unique.
*/
Object(const char* const _name);
//! Checksum name.
const char* const name() const { return name_; }
//! Add a record the checksum (generic version)
template <typename T>
void record(const Result& _rslt, const T& _data)
{
Base::OStringStream strm;
strm << _data;
add(_rslt, strm.str);
}
//! Add a record of the checksum (public version)
void record(const Result& _rslt, const String& _data) { add(_rslt, _data); }
/*!
Compare two existing records (old and new).
Returns a qualification and a description of the difference.
The default implementation has some intelligence in comparing the record
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;
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
virtual Difference compare_data(const String& _old, const String& _new) const;
private:
const char* const name_;
private:
Object(const Object&);
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_only(CC) CC
#endif//TEST_ON
#endif//BASE_ICHECKSUM_HH_INCLUDE
// (C) Copyright 2016 by Autodesk, Inc.
//
// The information contained herein is confidential, proprietary
// to Autodesk, Inc., and considered a trade secret as defined
// in section 499C of the penal code of the State of California.
// Use of this information by anyone other than authorized
// employees of Autodesk, Inc. is granted only under a written
// non-disclosure agreement, expressly prescribing the scope
// and manner of such use.
#if defined(TEST_ON) && defined(DEB_ON)
#include "ChecksumDebugEvent.hh"
#include "TestResult.hh"
#include "Base/Code/CodeLink.hh"
#include "Base/Debug/DebOut.hh"
#include <algorithm>
namespace Test {
namespace Checksum {
namespace Debug {
// put test checksum tag and separators in the required format
const char* const LINK_MARK = " reported ";
void Event::record(const std::string& _evnt, const Base::CodeLink& _lnk)
{
Base::OStringStream strm;
strm << "#" << nmbr_++ << ": " << _evnt << LINK_MARK << _lnk;
add(name() == ::Debug::ERROR ? Result::ERROR : Result::WARNING,
strm.str);
}
void Event::record_number()
{
Base::OStringStream strm;
strm << "total#: " << nmbr_;
add(
nmbr_ == 0 ? Result::OK :
(name() == ::Debug::ERROR ? Result::ERROR : Result::WARNING),
strm.str);
}
Difference Event::compare_data(const String& _old, const String& _new) const
{
// exclude the code link from the comparison
auto old_tmp = _old;
auto new_tmp = _new;
auto old_link_pos = old_tmp.rfind(LINK_MARK);
auto new_link_pos = new_tmp.rfind(LINK_MARK);
if (old_link_pos != String::npos && new_link_pos != String::npos)
{
old_tmp.resize(old_link_pos);
new_tmp.resize(new_link_pos);
}
return Object::compare_data(old_tmp, new_tmp);
}
Event error(::Debug::ERROR);
Event warning(::Debug::WARNING);
}//namespace Debug
}//Checksum
}//namespace Test
#endif//defined(TEST_ON) && defined(DEB_ON)
// (C) Copyright 2016 by Autodesk, Inc.
//
// The information contained herein is confidential, proprietary
// to Autodesk, Inc., and considered a trade secret as defined
// in section 499C of the penal code of the State of California.
// Use of this information by anyone other than authorized
// employees of Autodesk, Inc. is granted only under a written
// non-disclosure agreement, expressly prescribing the scope
// and manner of such use.
#ifndef BASE_CHECKSUMCOUNT_HH_INCLUDE
#define BASE_CHECKSUMCOUNT_HH_INCLUDE
#include <Base/Debug/DebOut.hh>
#include <Base/Test/Checksum.hh>
#if defined(TEST_ON) && defined(DEB_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 {
struct CodeLink;
}//namespace Base
namespace Test {
namespace Checksum {
namespace Debug {
class Event : public Object
{
public:
Event(const char* _name) : Object(_name), nmbr_(0) {}
virtual void record(const std::string& _evnt, const Base::CodeLink& _lnk);
virtual void record_number();
protected:
//! Implement "smarter" comparison
virtual Difference compare_data(const String& _old, const String& _new) const;
protected:
int nmbr_;
};
extern Event error;
extern Event warning;
}//namespace Debug
}//namespace Checksum
}//namespace Test
#endif//defined(TEST_ON) && defined(DEB_ON)
#endif//BASE_CHECKSUMCOUNT_HH_INCLUDE
// (C) Copyright 2016 by Autodesk, Inc.
//
// The information contained herein is confidential, proprietary
// to Autodesk, Inc., and considered a trade secret as defined
// in section 499C of the penal code of the State of California.
// Use of this information by anyone other than authorized
// employees of Autodesk, Inc. is granted only under a written
// non-disclosure agreement, expressly prescribing the scope
// and manner of such use.
#ifdef TEST_ON
#include "ChecksumFile.hh"
#include "Base/Utils/OStringStream.hh"
#include <boost/functional/hash.hpp>
#include <boost/filesystem.hpp>
#include <fstream>
namespace Test {
namespace Checksum {
void File::record(const char* _flnm)
{
// Reads the file, makes a has number form its data and finally record
// hash_number and filename.
std::ifstream fstr(_flnm);
std::array<char, 1000> buf;
size_t file_hash = 0;
size_t file_size = 0;
while(fstr)
{
fstr.read(buf.data(), buf.size());
auto buf_hash = boost::hash_range(buf.data(), buf.data() + fstr.gcount());
file_size += fstr.gcount();
boost::hash_combine(file_hash, buf_hash);
}
Base::OStringStream strm;
strm << "\"" << _flnm << '\"' << " (Size: " << file_size << ")" <<
"(Hash: " << Base::format_hex(file_hash) << ")";
add(Result::OK, strm.str);
}
}//namespace Checksum
}//namespace Test
#endif//TEST_ON
// (C) Copyright 2016 by Autodesk, Inc.
//
// The information contained herein is confidential, proprietary
// to Autodesk, Inc., and considered a trade secret as defined
// in section 499C of the penal code of the State of California.
// Use of this information by anyone other than authorized
// employees of Autodesk, Inc. is granted only under a written
// non-disclosure agreement, expressly prescribing the scope
// and manner of such use.
#ifndef BASE_CHECKSUMFILE_HH_INCLUDE
#define BASE_CHECKSUMFILE_HH_INCLUDE
#ifdef TEST_ON
#include <Base/Test/Checksum.hh>
namespace Test {
namespace Checksum {
/*!
checksum for output files. It has a method record that add a file hash.
*/
class File : public Object
{
public:
enum TagUsed { TAG_USED };
//! Make sure the constructor caller is aware of the tag requirement
File(const char* _name, TagUsed) : Object(_name) {}
void record(const char* _flnm);
static const char* tag() { return "-file"; }
};
}//namespace Checksum
}//namespace Test
#define TEST_CHECKSUM_FILE(VRBL, NAME) \
Test::Checksum::File VRBL(NAME"-file", Test::Checksum::File::TAG_USED)
#else//TEST_ON
#define TEST_CHECKSUM_FILE(VRBL, NAME)
#endif//TEST_ON
#endif//BASE_CHECKSUMFILE_HH_INCLUDE
// (C) Copyright 2016 by Autodesk, Inc.
//
// The information contained herein is confidential, proprietary
// to Autodesk, Inc., and considered a trade secret as defined
// in section 499C of the penal code of the State of California.
// Use of this information by anyone other than authorized
// employees of Autodesk, Inc. is granted only under a written
// non-disclosure agreement, expressly prescribing the scope
// and manner of such use.
#ifndef BASE_CHECKSUMLOGVALUET_HH_INCLUDE
#define BASE_CHECKSUMLOGVALUET_HH_INCLUDE
#ifdef TEST_ON
#include <Base/Test/Checksum.hh>
#include <sstream>
namespace Test {
namespace Checksum {
/*! Default implementation of a comparison class for ValueT.
*/
template <typename ValueT>
struct DefaultCompareT
{
bool same(const ValueT& _a, const ValueT& _b) const { return _a == _b; }
};
/*! Comparison class for checksums that MUST only be logged.
*/
template <typename ValueT>
struct NoCompareT
{
bool same(const ValueT& _a, const ValueT& _b) const { return true; }
};
/*!
Utility class to compare double with a tolerance. Can be used to redefine the
default compare class in class ValueT.