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 @@
#include <Base/Utils/BaseError.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() << "\"";
return _ds;
......
......@@ -13,7 +13,7 @@
#ifdef DEB_ON
#include <string>
#include "../Config/BaseDefines.hh"
#include <Base/Config/BaseDefines.hh>
namespace Debug {
......
......@@ -32,50 +32,31 @@
#else // DEB_ON
#include "Base/Code/CodeLink.hh"
#include "Base/Utils/OStringStream.hh"
#include <string>
#include <sstream>
#include <vector>
#if (_MSC_VER >= 1900 || __cplusplus > 199711L || defined(__GXX_EXPERIMENTAL_CXX0X__))
#include <array>
#endif
#include "../Config/BaseDefines.hh"
namespace Debug {
typedef unsigned int uint;
const int INVALID_LEVEL = -1;
const char* const ERROR = "ERROR";
const char* const WARNING = "WARNING";
class Stream;
class BASEDLLEXPORT Command
{
public:
enum CommandType
{
END = 0x01,
END_LF = 0x03,
END_ERR = 0x07
};
CommandType com_;
CommandType com() const
{
return com_;
}
Command(CommandType _com) : com_(_com) {}
};
// Class used to maintain Stream's CallStack
// This does not currently contain a pointer to the file streamer used
// but might do in future.
class BASEDLLEXPORT Enter
class Enter
{
public:
const char* flnm_; //!< File name for this DEB_enter
const char* fnct_; //!< Function name for this DEB_enter
int nmbr_; //!< deb_nmbr for this function.
int lvl_; //!< deb_level for this function.
int id_; /*!< Unique identifier for this Enter (used in ANCHORS) */
......@@ -90,19 +71,16 @@ public:
//! pass the output on the level or not?
bool pass(const int _lvl) const { return _lvl <= lvl_; }
Stream& stream(const int _warn = 0, const bool _print = true);
Command end() const { return Command(Command::END); }
Command end_lf() const { return Command(Command::END_LF); }
Command end_err() const { return Command(Command::END_ERR); }
Stream& stream();
};
//! This is a private implementation for Stream
class File;
class BASEDLLEXPORT Stream
class Stream : public Base::IOutputStream
{
public:
enum StreamType
enum Flags
{
APPEND = 0x01,
HTML = 0x02,
......@@ -110,113 +88,46 @@ public:
KEEP_OPEN = 0x08
};
private:
File* dfile_;
public:
File* dfile() const
{
return dfile_;
}
//! Constructor.
Stream(
const char* _file_name = NULL, //!< [in] File name if file based.
const StreamType _type = APPEND //!< [in] bitsfield enum type identifier
) ;
const char* _flnm = nullptr, //!< [in] Filename if file based.
const uint _flags = APPEND //!< [in] bit-field type identifier
);
~Stream();
const char* string_out() const;
Stream& print(const int);
Stream& print(const double);
Stream& print(const char* const, bool fork = true);
Stream& print(const char);
Stream& print(const Command&);
Base::IOutputStream& print(const int);
Base::IOutputStream& print(const size_t);
Base::IOutputStream& print(const double);
Base::IOutputStream& print(const char* const);
Base::IOutputStream& print(const char);
Base::IOutputStream& print(const Base::Command&);
//! Get the currently active Stream
static Stream& get_global(int _warn = 0);
private:
File* dfile_;
private:
// inhibit copy
Stream(const Stream&);
Stream& operator=(const Stream&);
};
BASEDLLEXPORT
Stream& operator<<(Stream& _ds, const int i);
BASEDLLEXPORT
Stream& operator<<(Stream& _ds, const double d);
BASEDLLEXPORT
Stream& operator<<(Stream& _ds, const size_t i);
File* dfile() const { return dfile_; }
BASEDLLEXPORT
Stream& operator<<(Stream& _ds, const unsigned int i);
BASEDLLEXPORT
Stream& operator<<(Stream& _ds, const float d);
BASEDLLEXPORT
Stream& operator<<(Stream& _ds, const char c);
BASEDLLEXPORT
Stream& operator<<(Stream& _ds, const char* const s);
BASEDLLEXPORT
Stream& operator<<(Stream& _ds, const std::string& s);
friend class Enter;
friend class Controller;
};
BASEDLLEXPORT
Stream& operator<<(Stream& _ds, const Command& co);
extern void warning(const std::string& _wrng, const ::Base::CodeLink& _lnk);
extern void error(const std::string& _err, const ::Base::CodeLink& _lnk);
// Stream operator for std::vector<>
template< typename ElementT>
Stream& operator<<(Stream& _ds, const std::vector<ElementT>& _vec)
{
_ds << "[ ";
for (typename std::vector<ElementT>::const_iterator el_it = _vec.begin(); el_it != _vec.end(); ++el_it)
_ds << *el_it << " ";
_ds << "]";
return _ds;
}
#if (_MSC_VER >= 1900 || __cplusplus > 199711L || defined(__GXX_EXPERIMENTAL_CXX0X__))
// Stream operator for std::array<>
template< typename ElementT, size_t _el_nmbr>
Stream& operator<<(Stream& _ds, const std::array<ElementT, _el_nmbr>& _vec)
{
_ds << "[ ";
for (const auto el : _vec)
_ds << el << " ";
_ds << "]";
return _ds;
}
#endif
// Stream operator for fixed size arrays
template <typename ElementT, size_t _el_nmbr>
Stream& operator<<(Stream& _ds, const ElementT(&_arr)[_el_nmbr])
{
_ds << "[ ";
for (unsigned int i = 0; i < _el_nmbr; ++i)
_ds << _arr[i] << " ";
_ds << "]";
return _ds;
}
// Stream std::pair<>
template <typename T0, typename T1>
Stream& operator<<(Stream& _ds, const std::pair<T0, T1>& _pair)
{
_ds << "(" << _pair.first << ", " << _pair.second << ")";
return _ds;
}
}//namespace Debug
#define DEB_module(MODULE)
//TODO: This should use an atomic thread-safe static int(s)
#define DEB_enter_func static int deb_nmbr = 0; \
static int deb_lvl = Debug::INVALID_LEVEL; \
Debug::Enter deb(__FILE__, __FUNCTION__, deb_nmbr, deb_lvl);
::Debug::Enter deb(__FILE__, __FUNCTION__, deb_nmbr, deb_lvl);
#define DEB_only(CC) CC
......@@ -225,40 +136,27 @@ Stream& operator<<(Stream& _ds, const std::pair<T0, T1>& _pair)
#define DEB_out(LL, AA) DEB_out_if(true, LL, AA)
#define DEB_out_if(CC, LL, AA) { if (deb.pass(LL) && (CC)) \
{ deb.stream() << AA << deb.end(); } }
{ deb.stream() << AA << ::Base::Command::END; } }
#define DEB_line(LL, AA) DEB_line_if(true, LL, AA)
#define DEB_line_if(CC, LL, AA) { if (deb.pass(LL) && (CC)) \
{ deb.stream() << AA << deb.end_lf(); } }
{ deb.stream() << AA << ::Base::LF; } }
#define DEB_warning(LL, AA) DEB_warning_if(true, LL, AA)
#define DEB_warning_if(CC, LL, AA) { if (deb.pass(LL) && (CC)) \
{ deb.stream(1) << "WARNING: " << AA << deb.end_lf(); } }
{ ::Base::OStringStream strm; strm << AA; \
::Debug::warning(strm.str, BASE_CODELINK); } }
#define DEB_error(AA) { deb.stream(2) << "ERROR: " << AA << deb.end_err(); }
#define DEB_error(AA) { ::Base::OStringStream strm; strm << AA; \
::Debug::error(strm.str, BASE_CODELINK); }
#define DEB_error_if(CC, AA) { if (CC) DEB_error(AA); }
// Stream does not fulfill ostream. If you want to exploit an existing
// ostream streamer to DEB_out a class as text without exploiting any
// numeric processing or custom Stream streamers then use this macro thus
// DEB_out(1, "my_class is " << DEB_os_str(my_c) )
#if (_MSC_VER >= 1900 || __cplusplus > 199711L || defined(__GXX_EXPERIMENTAL_CXX0X__))
#define DEB_os_str(AA) \
dynamic_cast<std::ostringstream &&>((std::ostringstream() << AA )).str()
#else
template <typename T>
std::string toString(const T& t)
{
std::ostringstream ss;
ss << t;
return ss.str();
}
#define DEB_os_str(AA) \
Debug::toString(AA)
#endif
}//namespace Debug
#endif // DEB_ON
......
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