utx : Unit Test driver for cpp using "Reflection".

Download utx.zip

Synopsis:

utx.h
utxcom.h
App.cpp
App.h
FileFind.cpp
FileFind.h
FileList.cpp
FileList.h
ImageFile.cpp
ImageFile.h
ImageFileWrapper.cpp
ImageFileWrapper.h
Library.cpp
Library.h
MemoryMappedImageFile.cpp
MemoryMappedImageFile.h
NTHandles.h
Statistics.cpp
Statistics.h
ut.rc
utx.cpp
utxCommon.h
testansi.cpp
testcom.cpp
testunicode.cpp
testunicodebase.cpp
testutx.cpp


utx.h

Synopsis
#pragma once
//---------------------------------------
//Minimum sample program:
//   #include "ut.h"
//
//   UTDLLMAIN()
//
//   TEST(1)
//   {
//      utxBoolAssert(true);
//      utxassert(1, 0);
//   }
//---------------------------------------

//#define _WIN32_WINNT 0x0501
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <string>
#include <sstream>
#include <algorithm>
#ifndef T
#include <tchar.h>
#endif
using std::transform;
#ifdef UNICODE
using std::wstring;
#define tstring std::wstring
#else
using std::string;
#define tstring std::string
#endif

//----
#ifdef _DEBUG
#include <crtdbg.h>
#ifdef CRTMEMDEBUG
#define UTDEBUGNEW new(_NORMAL_BLOCK,__FILE__,__LINE__)
#define new UTDEBUGNEW
#endif

#define UTX_ATTACH(stopValue) \
  static _CrtMemState before; \
  _CrtMemCheckpoint(&before); \
  _CrtSetBreakAlloc(stopValue)

#define UTX_DETACH() \
  _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG); \
  _CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDOUT); \
  _CrtMemState after; \
  _CrtMemState diff; \
  _CrtMemCheckpoint(&after); \
  _CrtMemDifference(&diff, &before, &after); \
  if (diff.lCounts[1]) \
  { \
  _RPT1(_CRT_WARN, "-----Memory Leaks in %s\n", __FILE__); \
  _CrtMemDumpAllObjectsSince(&diff); \
  _RPT1(_CRT_WARN, "-----end of Memory Leaks in %s\n", __FILE__); \
  } \
           else \
           _RPT1(_CRT_WARN, "----- No Memory Leaks in %s\n", __FILE__);
#else
#define UTX_ATTACH(stopvalue)
#define UTX_DETACH()
#endif

#define UTXDLLMAIN() BOOL APIENTRY DllMain( HANDLE, DWORD, LPVOID) {return TRUE; }

#define UTXDLLMAIN_CHECKLEAKS(stopValue) \
  BOOL APIENTRY DllMain( HANDLE , DWORD  ul_reason_for_call, LPVOID ) \
  { switch (ul_reason_for_call) \
  {   case DLL_PROCESS_ATTACH:  UTX_ATTACH(stopValue); break; \
                  case DLL_THREAD_ATTACH: break; \
                  case DLL_THREAD_DETACH: break; \
                  case DLL_PROCESS_DETACH:  UTX_DETACH(); break; \
  }  return TRUE; }

//helper functions
#ifdef UNICODE
inline std::string _utxToNarrowString(const wstring& s)
  {
  std::string narrowstr;
  narrowstr.resize(s.size() + 1);
  transform(s.begin(), s.end(), narrowstr.begin(), wctob);
  return narrowstr;
  }
#else
#define _utxToNarrowString(s) (s)
#endif

//----
#define TEST(t) __declspec(dllexport)  void __stdcall  test##t(void)
typedef void (*__UTXFUNCTIONPTR) (bool, const char*, const char*, const char*, const long);
#ifdef UNICODE
#define _UTXFUNCNAME ((LPCWSTR) L"UTXASSERTFUNC")
#else
#define _UTXFUNCNAME ((LPCSTR) "UTXASSERTFUNC")
#endif
inline __UTXFUNCTIONPTR _utxGetFunction()
  {
  HANDLE mMapFile = CreateFileMapping(
                 INVALID_HANDLE_VALUE,    // use paging file
                 NULL,                    // default security 
                 PAGE_READWRITE,          // read/write access
                 0,                       // max. object size 
                 sizeof(__UTXFUNCTIONPTR),                // buffer size  
                 _UTXFUNCNAME);   // name of mapping object
   LPTSTR mBuf = (LPTSTR) MapViewOfFile(mMapFile,   // handle to map object
                        FILE_MAP_ALL_ACCESS, // read/write permission
                        0,                   
                        0,                   
                        sizeof(__UTXFUNCTIONPTR));           
   __UTXFUNCTIONPTR fp;
    memcpy((void*)&fp, (void*) mBuf, sizeof(__UTXFUNCTIONPTR));
    UnmapViewOfFile(mBuf);
    CloseHandle(mMapFile);
    return fp;
  }

//for testing utx only. DO NOT USE!
#ifdef DEFINEUTXTEST
#ifdef DEFINENEXTASSERTFAILS
bool _gutxAssertNextAssertFails = false;
#else
extern bool _gutxAssertNextAssertFails;
#endif
inline void _utxAssertNextAssertFails()
  {
  _gutxAssertNextAssertFails = true;
  }
inline bool _utxCheckMissingFailure(__UTXFUNCTIONPTR fp, bool c, const tstring& cAsString, const char* fname, const long lineno, const tstring& msg)
  {
  if (!_gutxAssertNextAssertFails) return false;
  _gutxAssertNextAssertFails = false;
  if (!c) return true;
  
  fp(false, 
     _utxToNarrowString(_T("Expected a failure: ") + cAsString).c_str(), 
     _utxToNarrowString(msg).c_str(), 
     fname, lineno);
  return true;
  }
#else
inline bool _utxCheckMissingFailure(__UTXFUNCTIONPTR /*fp*/, bool /*c*/, const string& /*cAsString*/, const char* /*fname*/, const long /*lineno*/, const string& /*msg*/)
  {
  return false;
  }
#endif

//base level calls
inline void _utxAssertBase(bool c, const tstring& cAsString, const char* fname, const long lineno, const tstring& msg)
  {
  __UTXFUNCTIONPTR fp = _utxGetFunction();
  if (_utxCheckMissingFailure(fp, c, cAsString, fname, lineno, msg)) return;
  fp(c, _utxToNarrowString(cAsString).c_str(), _utxToNarrowString(msg).c_str(), fname, lineno);
  }
//inline void _utxAssertBase(bool c, const wstring& cAsString, char* fname, const long lineno, const wstring& msg)
//  {
//  _utxAssertBase(c, _utxToNarrowString(cAsString), fname, lineno, _utxToNarrowString(msg));
//  }
//inline void _utxAssertBase(bool c, const string& cAsString, char* fname, const long lineno, const wstring& msg)
//  {
//  _utxAssertBase(c, cAsString, fname, lineno, _utxToNarrowString(msg));
//  }

//pointer check
inline bool _utxCheckNulls(const void *actual, const void* expected, const char* fname, const long lineno)
  {
  if (actual == 0 && expected == 0) return false; //do not continue
  if (actual != 0 && expected != 0) return true; //ok to continue
  _utxAssertBase(false, tstring(_T("actual=")) + (actual == 0 ? _T("null") : _T("non-null")) + tstring(_T(" expected=")) + (expected == 0 ? _T("null") : _T("non-null")), fname, lineno, tstring());
  return false;
  }
inline bool _utxCheckNullsNot(const void *actual, const void* expected, const char* fname, const long lineno)
  {
  if (actual == 0 && expected != 0) return false; //do not continue
  if (actual != 0 && expected == 0) return false; //do not continue
  if (actual != 0 && expected != 0) return true; //ok to continue
  _utxAssertBase(false, tstring(_T("actual=")) + (actual == 0 ? _T("null") : _T("non-null")) + tstring(_T(" expected=")) + (expected == 0 ? _T("null") : _T("non-null")), fname, lineno, tstring());
  return false;
  }

//output string formatting routines
#define DefineFormatMsgFunc(type, format) \
  inline tstring _utxFormatMsg(const tstring& t, type p1, type p2) \
  { TCHAR desc[100]; \
  _stprintf(desc, _T(format), p1, t.c_str(), p2); \
  return tstring(desc); }

#pragma warning (disable:4996)
DefineFormatMsgFunc(const void*,   "actual=0x%p expected%s0x%p")
DefineFormatMsgFunc(int,           "actual=%d expected%s%d")
DefineFormatMsgFunc(unsigned int,  "actual=%u expected%s%u")
DefineFormatMsgFunc(long,          "actual=%ld expected%s%ld")
DefineFormatMsgFunc(unsigned long, "actual=%lu expected%s%lu")
//DefineFormatMsgFunc(__int64,       "actual=%I64d expected%s%I64d")
DefineFormatMsgFunc(long long,     "actual=%lld expected%s%lld")
//#pragma warning (disable:4996)

inline tstring _utxFormatMsg(const tstring& type, double n1, double n2, double epsilon)
  {
  TCHAR desc[100];
  _stprintf(desc, _T("actual=%f expected%s%f (epsilon=%f)"), n1, type.c_str(), n2, epsilon);
  return tstring(desc);
  }
inline tstring _utxFormatMsg(const tstring& type, const tstring& actual, const tstring& expected)
  {
  return _T("actual='") + actual + _T("' expected") + type + _T("'") + expected + _T("'");
  }
inline tstring _utxFormatMsg(const tstring& type, bool actual, bool expected)
  {
  tstring t(_T("true"));
  tstring f(_T("false"));
  return _T("actual='") + (actual ? t : f) + _T("' expected") + type + _T("'") + (expected ? t : f) + _T("'");
  }
inline tstring _utxFormatContainsMsg(const tstring& type, const tstring& actual, const tstring& expected)
  {
  return _T("'") + actual + _T("' ") + type + _T(" contain '") + expected + _T("'");
  }
//inline string _utxFormatContainsMsg(const string& type, const wstring& actual, const wstring& expected)
//  {
//  return _utxFormatContainsMsg(type, _utxToNarrowString(actual), _utxToNarrowString(expected));
//  }
//inline string _utxFormatMsg(const string& type, const wstring& actual, const wstring& expected)
//  {
//  return _utxFormatMsg(type, _utxToNarrowString(actual), _utxToNarrowString(expected));
//  }
inline tstring _utxFormatMsg(const tstring& type, const TCHAR* actual, const TCHAR* expected)
  {
  return _utxFormatMsg(type, tstring(actual), tstring(expected));
  }
//inline string _utxFormatMsg(const string& type, const wchar_t* actual, const wchar_t* expected)
//  {
//  return _utxFormatMsg(type, wstring(actual), wstring(expected));
//  }

//helper macros
#define DefineCharArrayWithMsg(type, casttype, msgtype) \
  inline void _utxAssert2(type actual, type expected, const char* fname, const long lineno, const msgtype& msg) \
  { if (!_utxCheckNulls(actual, expected, fname, lineno)) return; \
  _utxAssert2(casttype(actual), casttype(expected), fname, lineno, msg); }

#define DefineCharArrayNoMsg(type, msgtype) \
  inline void _utxAssert(type actual, type expected, const char* fname, const long lineno) \
  {  _utxAssert2(actual, expected, fname, lineno, msgtype()); }

#define DefineCharArrayWithMsgNot(type, casttype, msgtype) \
  inline void _utxAssertNot2(type actual, type expected, const char* fname, const long lineno, const msgtype& msg) \
  { if (!_utxCheckNullsNot(actual, expected, fname, lineno)) return; \
  _utxAssertBase(casttype(actual) != casttype(expected), _utxFormatMsg(_T(" !="), actual, expected), fname, lineno, msg); }

#define DefineCharArrayNoMsgNot(type, msgtype) \
  inline void _utxAssertNot(type actual, type expected, const char* fname, const long lineno) \
  { _utxAssertNot2(actual, expected, fname, lineno, msgtype()); }

#define DefineFuncWithMsg(type, msgtype) \
  inline void _utxAssert2(type actual, type expected, const char* fname, const long lineno, const msgtype& msg) \
  { _utxAssertBase(actual == expected, _utxFormatMsg(_T("="), actual, expected), fname, lineno, msg); }

#define DefineFuncNoMsg(type, msgtype) \
  inline void _utxAssert(type actual, type expected, const char* fname, const long lineno) \
  { _utxAssert2(actual, expected, fname, lineno, msgtype()); }

#define DefineFuncWithMsgNot(type, msgtype) \
  inline void _utxAssertNot2(type actual, type expected, const char* fname, const long lineno, const msgtype& msg) \
  { _utxAssertBase(actual != expected, _utxFormatMsg(_T(" !="), actual, expected), fname, lineno, msg); }

#define DefineFuncNoMsgNot(type, msgtype) \
  inline void _utxAssertNot(type actual, type expected, const char* fname, const long lineno) \
  { _utxAssertNot2(actual, expected, fname, lineno, msgtype()); }

#define DefineSubStringFuncWithMsg(type, msgtype) \
  inline void _utxAssertStringContains2(type actual, type expected, const char* fname, const long lineno, const msgtype& msg) \
  { _utxAssertBase((actual).find(expected) != tstring::npos, _utxFormatContainsMsg(_T("does not"), actual, expected), fname, lineno, msg); }

#define DefineSubStringFuncNoMsg(type, msgtype) \
  inline void _utxAssertStringContains(type actual, type expected, const char* fname, const long lineno) \
  { _utxAssertStringContains2(actual, expected, fname, lineno, msgtype()); }

#define DefineSubStringFuncWithMsgNot(type, msgtype) \
  inline void _utxAssertStringContainsNot2(type actual, type expected, const char* fname, const long lineno, const msgtype& msg) \
  { _utxAssertBase((actual).find(expected) == tstring::npos, _utxFormatContainsMsg(_T("should not"), actual, expected), fname, lineno, msg);  }

#define DefineSubStringFuncNoMsgNot(type, msgtype) \
  inline void _utxAssertStringContainsNot(type actual, type expected, const char* fname, const long lineno) \
  { _utxAssertStringContainsNot2(actual, expected, fname, lineno, msgtype()); }

//bool
inline void _utxAssert2(bool actual, const tstring& cAsString, const char* fname, const long lineno, const tstring& msg)
  {
  tstring m = (msg.empty() ? _T("") : msg + _T(": ")) + _utxFormatMsg(_T("="), false, true);
  _utxAssertBase(actual, cAsString, fname, lineno, m);
  }
//inline void _utxAssert2(bool actual, const string& cAsString, char* fname, const long lineno, const wstring& msg)
//  {
//  _utxAssertBase(actual, cAsString, fname, lineno, msg);
//  }
inline void _utxAssert(bool actual, const tstring& cAsString, const char* fname, const long lineno)
  {
  _utxAssert2(actual, cAsString, fname, lineno, tstring());
  }
inline void _utxAssertNot2(bool actual, const tstring& cAsString, const char* fname, const long lineno, const tstring& msg)
  {
  tstring m = (msg.empty() ? _T("") : msg + _T(": ")) + _utxFormatMsg(_T(" !="), true, true);
  _utxAssertBase(!actual, cAsString, fname, lineno, m);
  }
//inline void _utxAssertNot2(bool actual, const string& cAsString, char* fname, const long lineno, const wstring& msg)
//  {
//  _utxAssertNot2(actual, cAsString, fname, lineno, _utxToNarrowString(msg));
//  }
inline void _utxAssertNot(bool actual, const tstring& cAsString, const char* fname, const long lineno)
  {
  _utxAssertNot2(actual, cAsString, fname, lineno, tstring());
  }

//void*
inline void _utxAssert2(const void* actual, const char* fname, const long lineno, const tstring& msg)
  {
  _utxAssertBase(actual == 0, _utxFormatMsg(_T("="), actual, 0), fname, lineno, msg);
  }
inline void _utxAssert(const void* actual, const char* fname, const long lineno)
  {
  _utxAssert2(actual, fname, lineno, tstring());
  }
inline void _utxAssertNot2(const void* actual, const char* fname, const long lineno, const tstring& msg)
  {
  _utxAssertBase(actual != 0, _utxFormatMsg(_T(" !="), actual, 0), fname, lineno, msg);
  }
inline void _utxAssertNot(const void* actual, const char* fname, const long lineno)
  {
  _utxAssertNot2(actual, fname, lineno, tstring());
  }

//-- all string types go here -----

//string
DefineFuncWithMsg(const tstring&, tstring)
DefineFuncNoMsg(const tstring&,   tstring)
DefineFuncWithMsgNot(const tstring&, tstring)
DefineFuncNoMsgNot(const tstring&, tstring)

////wstring
//DefineFuncWithMsg(const wstring&, string)
//DefineFuncWithMsg(const wstring&, wstring)
//DefineFuncNoMsg(const wstring&, string)
//DefineFuncWithMsgNot(const wstring&, wstring)
//DefineFuncWithMsgNot(const wstring&,  string)
//DefineFuncNoMsgNot(const wstring&, wstring)

//substring
DefineSubStringFuncWithMsg(const tstring&, tstring)
DefineSubStringFuncNoMsg(const tstring&, tstring)
DefineSubStringFuncWithMsgNot(const tstring&, tstring)
DefineSubStringFuncNoMsgNot(const tstring&, tstring)

////wsubstring
//DefineSubStringFuncWithMsg(const wstring&, wstring)
//DefineSubStringFuncNoMsg(const wstring&, wstring)
//DefineSubStringFuncWithMsgNot(const wstring&, wstring)
//DefineSubStringFuncNoMsgNot(const wstring&, wstring)

//string + char*
inline void _utxAssert2(const tstring& actual, const TCHAR* expected, const char* fname, const long lineno, const tstring& msg)
  {
  _utxAssertBase(actual == tstring(expected), _utxFormatMsg(_T("="), actual, expected), fname, lineno, msg);
  }
inline void _utxAssert(const tstring& actual, const TCHAR* expected, const char* fname, const long lineno)
  {
  _utxAssert2(actual, tstring(expected), fname, lineno, tstring());
  }
inline void _utxAssertNot2(const tstring& actual, const TCHAR* expected, const char* fname, const long lineno, const tstring& msg)
  {
  _utxAssertBase(actual != tstring(expected), _utxFormatMsg(_T(" !="), actual, expected), fname, lineno, msg);
  }
inline void _utxAssertNot(const tstring& actual, const TCHAR* expected, const char* fname, const long lineno)
  {
  _utxAssertNot2(actual, expected, fname, lineno, tstring());
  }

//-- all char* types go here -----
//char*
DefineCharArrayWithMsg(const TCHAR*, tstring, tstring)
DefineCharArrayNoMsg(const TCHAR*, tstring)
DefineCharArrayWithMsgNot(const TCHAR*, tstring, tstring)
DefineCharArrayNoMsgNot(const TCHAR*, tstring)

////wchar_t
//DefineCharArrayWithMsg(const wchar_t*, wstring, string)
//DefineCharArrayWithMsg(const wchar_t*, wstring, wstring)
//DefineCharArrayNoMsg(const wchar_t*, string)
//DefineCharArrayWithMsgNot(const wchar_t*, wstring, wstring)
//DefineCharArrayNoMsgNot(const wchar_t*, wstring)

//-- all real types go here -----

//double
//inline void _utxAssert2(double actual, double expected, double epsilon, char* fname, const long lineno, const wstring& msg)
//  {
//  _utxAssertBase((actual > expected - epsilon && actual < expected + epsilon),  _utxFormatMsg("=", actual, expected, epsilon), fname, lineno, msg);
//  }
inline void _utxAssert2(double actual, double expected, double epsilon, const char* fname, const long lineno, const tstring& msg)
  {
  _utxAssertBase((actual > expected - epsilon && actual < expected + epsilon),  _utxFormatMsg(_T("="), actual, expected, epsilon), fname, lineno, msg);
  }
inline void _utxAssert(double actual, double expected, double epsilon, const char* fname, const long lineno)
  {
  _utxAssert2(actual, expected, epsilon, fname, lineno, tstring());
  }
//inline void _utxAssertNot2(double actual, double expected, double epsilon, char* fname, const long lineno, const wstring& msg)
//  {
//  _utxAssertBase((actual <= expected - epsilon || actual >= expected + epsilon), _utxFormatMsg(" !=", actual, expected, epsilon), fname, lineno, msg);
//  }
inline void _utxAssertNot2(double actual, double expected, double epsilon, const char* fname, const long lineno, const tstring& msg)
  {
  _utxAssertBase((actual <= expected - epsilon || actual >= expected + epsilon), _utxFormatMsg(_T(" !="), actual, expected, epsilon), fname, lineno, msg);
  }
inline void _utxAssertNot(double actual, double expected, double epsilon, const char* fname, const long lineno)
  {
  _utxAssertNot2(actual, expected, epsilon, fname, lineno, tstring());
  }

//-- all integral types go here -----

//long
//DefineFuncWithMsg   (long,  wstring)
DefineFuncWithMsg   (long,  tstring)
DefineFuncNoMsg     (long,  tstring)
//DefineFuncWithMsgNot(long,  wstring)
DefineFuncWithMsgNot(long,  tstring)
DefineFuncNoMsgNot  (long,  tstring)

//unsigned long
//DefineFuncWithMsg   (unsigned long, wstring)
DefineFuncWithMsg   (unsigned long, tstring)
DefineFuncNoMsg     (unsigned long, tstring)
//DefineFuncWithMsgNot(unsigned long, wstring)
DefineFuncWithMsgNot(unsigned long, tstring)
DefineFuncNoMsgNot  (unsigned long, tstring)

//int
//DefineFuncWithMsg   (int,  wstring)
DefineFuncWithMsg   (int,  tstring)
DefineFuncNoMsg     (int,  tstring)
//DefineFuncWithMsgNot(int,  wstring)
DefineFuncWithMsgNot(int,  tstring)
DefineFuncNoMsgNot  (int,  tstring)

//unsigned int
//DefineFuncWithMsg   (unsigned int, wstring)
DefineFuncWithMsg   (unsigned int, tstring)
DefineFuncNoMsg     (unsigned int, tstring)
//DefineFuncWithMsgNot(unsigned int, wstring)
DefineFuncWithMsgNot(unsigned int, tstring)
DefineFuncNoMsgNot  (unsigned int, tstring)

//__int64
//DefineFuncWithMsg   (__int64,  wstring)
//DefineFuncWithMsg   (__int64,  string)
//DefineFuncNoMsg     (__int64,  string)
//DefineFuncWithMsgNot(__int64,  wstring)
//DefineFuncWithMsgNot(__int64,  string)
//DefineFuncNoMsgNot  (__int64,  string)

//DefineFuncWithMsg   (__int64,  wstring)
DefineFuncWithMsg   (long long,  tstring)
DefineFuncNoMsg     (long long,  tstring)
//DefineFuncWithMsgNot(__int64,  wstring)
DefineFuncWithMsgNot(long long,  tstring)
DefineFuncNoMsgNot  (long long,  tstring)

//gather the file and lineno info
#define utxBoolAssert(c)          _utxAssert((c), tstring(_T(#c)), __FILE__,__LINE__)
#define utxBoolAssert2(c, msg)    _utxAssert2((c), tstring(_T(#c)), __FILE__,__LINE__, tstring(msg))
#define utxBoolAssertNot(c)       _utxAssertNot((c), tstring(_T(#c)), __FILE__,__LINE__)
#define utxBoolAssertNot2(c, msg) _utxAssertNot2((c), tstring(_T(#c)), __FILE__,__LINE__, tstring(msg))

#define utxAssertPtrIsNull(p)          _utxAssert((p), __FILE__,__LINE__)
#define utxAssertPtrIsNull2(p, msg)    _utxAssert2((p), __FILE__,__LINE__, tstring(msg))
#define utxAssertPtrIsNotNull(p)       _utxAssertNot((p), __FILE__,__LINE__)
#define utxAssertPtrIsNotNull2(p, msg)  _utxAssertNot2((p), __FILE__,__LINE__, tstring(msg))

#define utxDoubleAssert(actual, expected, epsilon)          _utxAssert((actual), (expected), (epsilon),__FILE__, __LINE__)
#define utxDoubleAssert2(actual, expected, epsilon, msg)    _utxAssert2((actual), (expected), (epsilon), __FILE__, __LINE__, tstring(msg))
#define utxDoubleAssertNot(actual, expected, epsilon)       _utxAssertNot((actual), (expected), (epsilon),__FILE__, __LINE__)
#define utxDoubleAssertNot2(actual, expected, epsilon, msg) _utxAssertNot2((actual), (expected), (epsilon), __FILE__, __LINE__, tstring(msg))

#define utxassert(actual, expected)          _utxAssert((actual), (expected), __FILE__, __LINE__)
#define utxassert2(actual, expected, msg)    _utxAssert2((actual), (expected), __FILE__,__LINE__, tstring(msg))
#define utxassertnot(actual, expected)       _utxAssertNot((actual), (expected), __FILE__, __LINE__)
#define utxassertnot2(actual, expected, msg) _utxAssertNot2((actual), (expected), __FILE__, __LINE__, tstring(msg))

#define utxAssertStringContains(actual, expected)       _utxAssertStringContains((actual), (expected), __FILE__, __LINE__)
#define utxAssertStringContains2(actual, expected, msg) _utxAssertStringContains2((actual), (expected),  __FILE__, __LINE__, tstring(msg))
#define utxAssertStringContainsNot(actual, expected)       _utxAssertStringContainsNot((actual), (expected), __FILE__, __LINE__)
#define utxAssertStringContainsNot2(actual, expected, msg) _utxAssertStringContainsNot2((actual), (expected),  __FILE__, __LINE__, tstring(msg))


utxcom.h

Synopsis
#pragma once

#include <comdef.h>
inline bool _utxCheckNulls(const _bstr_t& actual, const _bstr_t& expected, char* fname, const long lineno)
  {
  return _utxCheckNulls((char*)actual, (char*)expected, fname, lineno);
  }
inline bool _utxCheckNullsNot(const _bstr_t& actual, const _bstr_t& expected, char* fname, const long lineno)
  {
  return _utxCheckNullsNot((char*) actual, (char*) expected, fname, lineno);
  }

inline string _utxFormatMsg(const string& type, const _bstr_t& actual, const _bstr_t& expected)
  {
  return _utxFormatMsg(type, (wchar_t*) actual, (wchar_t*) expected);
  }

//bstr_t
inline void _utxAssert2(const _bstr_t& actual, const _bstr_t& expected, char* fname, const long lineno, const char* msg)
  {
  if (!_utxCheckNulls(actual, expected, fname, lineno)) return;
  _utxAssertBase(actual == expected, "actual='" + string((char*) actual) + "' expected='" + string((char*) expected) + "'", fname, lineno, msg);
  }
inline void _utxAssert(const _bstr_t& actual, const _bstr_t& expected, char* fname, const long lineno)
  {
  _utxAssert2(actual, expected, fname, lineno, "");
  }
inline void _utxAssertNot2(const _bstr_t& actual, const _bstr_t& expected, char* fname, const long lineno, const string& msg)
  {
  if (!_utxCheckNullsNot(actual, expected, fname, lineno)) return;
  _utxAssertBase(actual != expected, "actual='" + string((char*) actual) + "' expected='" + string((char*) expected) + "'", fname, lineno, msg);
  }
inline void _utxAssertNot(const _bstr_t& actual, const _bstr_t& expected, char* fname, const long lineno)
  {
  _utxAssertNot2(actual, expected, fname, lineno, "");
  }

//BSTR
inline void _utxAssert2(const BSTR actual, const BSTR expected, char* fname, const long lineno, const char* msg)
  {
  _utxAssert2(_bstr_t(actual), _bstr_t(expected), fname, lineno, msg);
  }
inline void _utxAssert(const BSTR actual, const BSTR expected, char* fname, const long lineno)
  {
  _utxAssert2(actual, expected, fname, lineno, "");
  }
inline void _utxAssertNot2(const BSTR actual, const BSTR expected, char* fname, const long lineno, const string& msg)
  {
  _utxAssertNot2(_bstr_t(actual), _bstr_t(expected), fname, lineno, msg);
  }
inline void _utxAssertNot(const BSTR actual, const BSTR expected, char* fname, const long lineno)
  {
  _utxAssertNot2(actual, expected, fname, lineno, "");
  }

//BSTR & _bstr_t mix
inline void _utxAssert2(const _bstr_t& actual, const BSTR expected, char* fname, const long lineno, const char* msg)
  {
  _utxAssert2(actual, _bstr_t(expected), fname, lineno, msg);
  }
inline void _utxAssert(const _bstr_t& actual, const BSTR expected, char* fname, const long lineno)
  {
  _utxAssert2(actual, expected, fname, lineno, "");
  }
inline void _utxAssertNot2(const _bstr_t& actual, const BSTR expected, char* fname, const long lineno, const string& msg)
  {
  _utxAssertNot2(actual, _bstr_t(expected), fname, lineno, msg);
  }
inline void _utxAssertNot(const _bstr_t& actual, const BSTR expected, char* fname, const long lineno)
  {
  _utxAssertNot2(actual, expected, fname, lineno, "");
  }

//----------------------------------

#ifdef USECOMSPY
#include "\projects\src\jcomheap\jcomheap.h"
#pragma comment(lib, "c:\\projects\\debug\\jcomheap\\jcomheap.lib")
#define STARTCOMSPY(breaknum) \
  jComHeap*  _comheap = new jComHeap(); \
  _comheap->Init(); \
  _comheap->BreakOnAllocNumber(breaknum)

#define ENDCOMSPY() \
  _comheap->Report(__FILE__, __LINE__); \
  delete _comheap; \
  _comheap = 0

#define UTXCOMDLLMAIN_CHECKLEAKS(stopValue) \
  BOOL APIENTRY DllMain( HANDLE , DWORD  ul_reason_for_call, LPVOID ) \
  {  static jComHeap*  _comheap = new jComHeap(); \
  switch (ul_reason_for_call) \
  {   case DLL_PROCESS_ATTACH:  \
          _RPT1(_CRT_WARN, "----- Attach Here! %s\n", __FILE__); \
          _comheap->Init(); \
          _comheap->BreakOnAllocNumber(stopValue); \
          break; \
        case DLL_THREAD_ATTACH: break; \
        case DLL_THREAD_DETACH: break; \
        case DLL_PROCESS_DETACH:  \
  _RPT1(_CRT_WARN, "----- Detach START Here! %s\n", __FILE__); \
  CoFreeUnusedLibraries(); \
  _comheap->Report(__FILE__, __LINE__); \
  delete _comheap; \
  _comheap = 0; \
  _RPT1(_CRT_WARN, "----- Detach DONE Here! %s\n", __FILE__); \
  break; \
  }  return TRUE; }
#else
#define STARTCOMSPY(breaknum)
#define ENDCOMSPY()
#define UTXCOMDLLMAIN_CHECKLEAKS(stopValue)
#endif


#define STARTCOM() \
  HRESULT hr; \
  hr = CoInitialize(0); \
  {

#define CREATECOM(clazz, vrbl, coclass) \
  clazz vrbl; \
  hr = vrbl##.CreateInstance(__uuidof(coclass)); \
  utxassert(hr, S_OK)

#define ENDCOM() \
  } \
  CoUninitialize()

#define UTXCOMDLLMAIN() BOOL APIENTRY DllMain( HANDLE, DWORD, LPVOID) {return TRUE; }

App.cpp

Synopsis
#include <string>
#include <iostream>
#include <algorithm>
using namespace std;

#include "utxCommon.h"
#include "utx.h"
#include "App.h"
#include "ImageFile.h"

//-----------------------------------------------------
//all lowercase!
string cUTFilePrefix = "";
string cUTFileSuffix = "_utest.dll";
string cUTMethodPrefix = "test";
string cUTMethodSuffix = "";

//-----------------------------------------------------
char HelpText[] = 
"usage: utx [switches] [dir or file]\n"
"\n"
"switches:\n"
" -h display this help screen\n"
" -? display this help screen\n"
" -v display version and exit\n"
"\n"
" -test:<pattern>\n"
" -file:<pattern>\n"
"     defaults:\n"
"         -file:*_utest\n"
"         -test:test*\n"
"     where <pattern> is a series of characters\n"
"     there can be zero or one asterisk '*' in it\n"
"     can be empty before or after the asterisk or both\n"
"     don't use file extension (.dll, .class) etc.\n"
"     examples:\n"
"         -file:ut_*     all dll's and classes starting with 'ut_'\n"
"         -file:ut_abc   the files 'ut_abc.dll', 'ut_abc.class' etc.\n"
"         -test:case*    all functions with signatures like 'void casexxx()'\n"
"\n"
" if no file name or directory given, defaults to '.'\n";

//-----------------------------------------------------
template<typename _Ty> 
inline bool startswith(const _Ty& _F, const _Ty& _PFX)
  {
  typename _Ty::const_iterator it = _PFX.begin();
  typename _Ty::const_iterator it2 = _F.begin();
  for ( ; it != _PFX.end() && it2 != _F.end(); ++it, ++it2)
    {
	if (*it != *it2)
      return false;
    }

  return  it == _PFX.end(); 
  }

template<typename _Ty> 
inline bool endswith(const _Ty& _F, const _Ty& _SFX)
  {
  typename _Ty::const_reverse_iterator it = _SFX.rbegin();
  typename _Ty::const_reverse_iterator it2 = _F.rbegin();
  for ( ; it != _SFX.rend() && it2 != _F.rend(); ++it, ++it2)
    {
	if (*it != *it2)
	  return false;
    }

  return  it == _SFX.rend(); 
  }


//-----------------------------------------------------
static bool isMatch(const string& f)
  {
  return startswith(f, cUTFilePrefix) && endswith(f, cUTFileSuffix);
  }

//-----------------------------------------------------
class App::AssertFunction
  {
  public:
  //----------
  void Set(__UTXFUNCTIONPTR fp)
    {
    mMapFile = CreateFileMapping(
                 INVALID_HANDLE_VALUE,    // use paging file
                 NULL,                    // default security 
                 PAGE_READWRITE,          // read/write access
                 0,                       // max. object size 
                 BUF_SIZE,                // buffer size  
                 "UTXASSERTFUNC");                 // name of mapping object

    checkInternalError(mMapFile == 0 || mMapFile == INVALID_HANDLE_VALUE, "Can't crate file mapping");
    mBuf = (LPTSTR) MapViewOfFile(mMapFile,   // handle to map object
                        FILE_MAP_ALL_ACCESS, // read/write permission
                        0,                   
                        0,                   
                        BUF_SIZE);           
    checkInternalError(mBuf == 0, "Can't map view of file");

    memcpy((void*)mBuf, (void*) &fp, BUF_SIZE);
    }
    
  //----------
  void Close()
    {
    if (mMapFile != INVALID_HANDLE_VALUE)
      {
      UnmapViewOfFile(mBuf);
      mBuf = 0;
      CloseHandle(mMapFile);
      mMapFile = INVALID_HANDLE_VALUE;
      }
    }

  private:
    //-----------------------------------------------------
    void checkInternalError(bool condition, const char* s)
      {
      if (condition)
        {
        char buf[512];
        sprintf(buf, "Internal error: %s: gle=%lX", s, ::GetLastError());
        throw string(buf);
        }
      }

  private:
    enum { BUF_SIZE = sizeof(__UTXFUNCTIONPTR) };
    HANDLE mMapFile;
    LPTSTR mBuf;
  } ;
    
//-----------------------------------------------------
App::App()
: mFunc(* new App::AssertFunction), m_files(isMatch)
  {
  }

//-----------------------------------------------------
App::~App()
  {
  delete &mFunc;
  }

//-----------------------------------------------------
void App::Init(int argc, char** argv)
  {
    
  initDebugRoutines();

  try 
    {
    processCommandLine(argc, argv);

    setAssertFunction();
    //todo: how does g++ handle system exceptions?
    //_set_se_translator(translate_exceptions);

    m_files.get(m_argpath);
    } 
  catch (const string& s)
    {
    cout << s << endl << endl;
    cout << HelpText;
    throw 1;
    }
  catch (const char* s)
    {
    cout << s << endl << endl;
    cout << HelpText;
    throw 1;
    }
  catch(int n)
    {
    throw n;
    }
  }

//-----------------------------------------------------
void App::Run()
  {
  stats.numfiles = m_files.size();
  for(FileList::iterator it = m_files.begin(); it != m_files.end(); ++it)
    {
    ImageFile img;
    img.Run(*it);
    }
  }

//-----------------------------------------------------
void App::utxAssertImpl(bool cond, const char* condstr, const char* msg, const char* fn, const long line)
  {
  stats.numasserts++;
  if (cond) return;

  if (strcmp(msg, "") == 0)
    cout << fn << "(" << line << "): FAILED: " << condstr << endl;
  else
    cout << fn << "(" << line << "): FAILED: " << msg << ": " << condstr << endl;
  stats.numerrors++;
  }

//-----------------------------------------------------
void App::setAssertFunction()
  {
  __UTXFUNCTIONPTR fp = utxAssertImpl;
  mFunc.Set(fp);
  }
 
void App::closeAssertFunction()
  {
  mFunc.Close();
  }

//-----------------------------------------------------
void App::translate_exceptions(unsigned int u, EXCEPTION_POINTERS* pExp)
  {
  SE_Exception se;
  se.ex = u;
  throw se;
  }

//-----------------------------------------------------
bool App::isSwitch(char* arg)
  {
  return arg[0] == '-' || arg[0] == '/';
  }

//-----------------------------------------------------
void App::processCommandLine(int argc, char** argv)
  {
  for (int i=1; i < argc; i++ )
    {
    strlwr(argv[i]);

    if (isSwitch(argv[i]) )
      handleSwitch(&argv[i][1]);
    else if (m_argpath != "")
      throw "already have a filename or directory to scan";
    else
      m_argpath = argv[i];
    }

  if (m_argpath == "")
    m_argpath = ".";
  }

//-----------------------------------------------------
void App::handleSwitch(char* s)
  {
  string arg = s;
  if (arg == "h" || arg == "?")
    throw "";
  
  if (arg == "v")
    {
    cout << "utx V0.9" << endl;
    throw 2;
    }
  
  if (strncmp(s, "test:", 5) == 0)
    {
    handlePattern(&s[5], cUTMethodPrefix, cUTMethodSuffix);
    }
  
  else if (strncmp(s, "file:", 5) == 0)
    {
    handlePattern(&s[5], cUTFilePrefix, cUTFileSuffix);
    cUTFileSuffix += ".dll";
    }
  else
    {
    char buf[200];
    sprintf(buf, "unknown switch: %s", s);
    throw buf;
    }
}

//-----------------------------------------------------
void App::handlePattern(const string& pattern, string& prefix, string& suffix)
  {
  int starcount = count(pattern.begin(), pattern.end(), '*');

  if (starcount > 1)
    throw "Only zero or one asterisk allowed!";

  string::size_type idx = pattern.find('*');
  prefix = pattern.substr(0, idx);
  suffix = idx == string::npos ? "" : pattern.substr(idx+1);
  }

//-----------------------------------------------------
void App::initDebugRoutines()
  {
//  _CrtSetDbgFlag(_CrtSetDbgFlag(_CRTDBG_REPORT_FLAG) | _CRTDBG_LEAK_CHECK_DF);
//  _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG);
//  _CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDOUT);
  }


App.h

Synopsis
//-----------------------------------------------------
#pragma once

#include <string>
using std::string;
#include "FileList.h"

class App
  {
  public:
    App();
    ~App();
    void Init(int argc, char** argv);
    void Run();
    
  private:
    static void utxAssertImpl(bool cond, const char* msg, const char* condstr, const char* fn, const long line);
    void setAssertFunction();
    void closeAssertFunction();
    static void translate_exceptions(unsigned int u, EXCEPTION_POINTERS* pExp);
    void processCommandLine(int argc, char** argv);
    void initDebugRoutines();
    bool isSwitch(char* arg);
    void handleSwitch(char* s);
    void handlePattern(const string& pattern, string& prefix, string& suffix);
    
  private:
    class AssertFunction;
    AssertFunction& mFunc;
    FileList m_files;
    string m_argpath;
  } ;


FileFind.cpp

Synopsis
#include <string>
#include <algorithm>
using namespace std;

#include "utxCommon.h"
#include "FileFind.h"
#include "NTHandles.h"

static string toDosPath(const string& path)
  {
  struct LocalFunc
    {
    static bool isForwardSlash(char c) { return c == '/'; }
    } ;
  string s = path;
  replace_if(s.begin(), s.end(), LocalFunc::isForwardSlash, '\\');
  return s;
  }
    
//-----------------------------------------------------
class FileFind::Private
  {
  public:
    Private(const string& dir)
      {
      mRootdir = toDosPath(dir);
      filefindData.first = mRootdir + "\\*.*";
      filefindData.second = &fdata;
      resetFilename();
      }
    
    bool findFirst()
      {
      resetFilename();
      return hFileFind.create(filefindData);
      }
    
    bool findnext()
      {
      resetFilename();
      return hFileFind.next(filefindData);
      }

    const string filename()
      {
      if (mFilename == "")
         setFilename(strlwr(fdata.cFileName));
  
      return mFilename;
      }

    const string fullpath()
      {
      if (mFullpath == "")
        mFullpath = string(mRootdir + "\\" + filename());
      
      return mFullpath;
      }

    bool isDir()
      {
      return (fdata.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0;
      }
   
  private:
    void resetFilename()
      {
      setFilename("");
      }

    void setFilename(const char* fn)
      {
      mFilename = string(fn);
      mFullpath = "";
      }

  private:
    string mRootdir;
    string mFilename;
    string mFullpath;

    WIN32_FIND_DATA fdata;
    FileFindPair filefindData;
    NtFileFindHandle hFileFind;
  } ;

//-----------------------------------------------------
FileFind::FileFind(const string& dir)
: mimpl (* new FileFind::Private(dir))
  {
  }

//-----------------------------------------------------
FileFind::~FileFind()
  {
  delete &mimpl;
  }

//-----------------------------------------------------
bool FileFind::getFirst()
  {
  if (!mimpl.findFirst())
    return false;
  
  for(;;)
    {
    if (!isDotDir())
      return true;
    
    if (!getNext())
      return false;
    }
  }

//-----------------------------------------------------
bool FileFind::getNext()
  {
  return mimpl.findnext();
  }

//-----------------------------------------------------
bool FileFind::isDotDir()
  {
  return fileName() == string(".") || fileName() == string("..");
  }

//-----------------------------------------------------
bool FileFind::isDir()
  {
  return mimpl.isDir();
  }

//-----------------------------------------------------
const string FileFind::fullPath()
  {
  return mimpl.fullpath();
  }

//-----------------------------------------------------
const string FileFind::fileName()
  {
  return mimpl.filename();
  }


FileFind.h

Synopsis
#pragma once
#include <string>

class FileFind 
  {
  public:
    FileFind(const std::string& dir);
    ~FileFind();
    bool getFirst();
    bool getNext();
    bool isDotDir();
    bool isDir();
    const std::string fullPath();
    const std::string fileName();
  
  private:
    class Private;
    Private& mimpl;
  };

FileList.cpp

Synopsis
#include <string>
using namespace std;

#define WIN32_LEAN_AND_MEAN
#define NOMINMAX 1
#include <windows.h>

#include "utxCommon.h"
#include "FileList.h"
#include "FileFind.h"

//-----------------------------------------------------
FileList::FileList(isMatchFunc p)
: matchfunc(p)
  {
  }

//-----------------------------------------------------
void FileList::get(const std::string& path)
  {
  m_argpath = path;

  if (! isArgAFile())
    argIsDirectory();
  
  if (empty())
    throw "No files were found to scan";
  }

//-----------------------------------------------------
void FileList::argIsDirectory()
  {
  Paths dirs;
  
  dirs.push(m_argpath);
  while(!dirs.empty())
    {
    string dir = dirs.top();
    dirs.pop();

    searchDir(dir, dirs);
    }
  }

//-----------------------------------------------------
void FileList::searchDir(const string& dir, Paths& dirs)
  {
  FileFind ff(dir);
 
  for (bool rc = ff.getFirst(); rc; rc = ff.getNext())
    {
    if (ff.isDir())
      dirs.push(ff.fullPath());

    else if (matchfunc(ff.fileName()))
      push_back(ff.fullPath());
    }
  }

//-----------------------------------------------------
bool FileList::isArgAFile()
  {
  DWORD fattr = GetFileAttributes(m_argpath.c_str());
  if (fattr == 0xFFFFFFFF)
    {
    char buf[200];
    sprintf(buf, "Could not find the file or directory '%s'", m_argpath.c_str());
    throw buf;
    }
  
  if ((fattr & FILE_ATTRIBUTE_DIRECTORY) == 0)
    {
    push_back(m_argpath);
    return true;
    }

  return false;
  }

FileList.h

Synopsis
#pragma once

#include <algorithm>
#include <string>
#include <list>
#include <stack>

typedef bool (* isMatchFunc) (const std::string& f);

class FileList : public std::list<std::string>
  {
  public:
    FileList(isMatchFunc p);
    void get(const std::string& path);

  private:
    FileList();
    typedef std::stack<std::string> Paths;
    void searchDir(const std::string& dir, Paths& dirs);
    bool isArgAFile();
    void argIsDirectory();

  private:
    isMatchFunc matchfunc;
    std::string m_argpath;
  } ;

ImageFile.cpp

Synopsis
#include <string>
#include <iostream>
using namespace std;

#include "utxCommon.h"
#include "Library.h"
#include "ImageFile.h"
#include "ImageFileWrapper.h"

//------------------------------------------------------
class ImageFile::Private
  {
  public:
    bool Load(const std::string& fn);
    void invokeUnitTests();

  private:
    bool isOkUnitTest(char* p);
    ostream& operator << (ostream& os);
    void AssertFailed(const char* s);
    void ThrewException(const unsigned int ex);
    void ThrewUnknownException();
    
  private:    
    string FQFileName;
    ImageFileWrapper ifw;
    
    char undecoratedName[512];
  } ;

//------------------------------------------------------
ImageFile::ImageFile() 
: m_impl(* new Private())
  {
  }

//------------------------------------------------------
ImageFile::~ImageFile() 
  {
  delete &m_impl;
  }

//------------------------------------------------------
void ImageFile::Run(const string& fn)
  {
  if (m_impl.Load(fn))
    m_impl.invokeUnitTests();
  }

//------------------------------------------------------
ostream& ImageFile::Private::operator << (ostream& os)
  {
  os << FQFileName << ": " << undecoratedName << " : ";
  return os;
  }

//------------------------------------------------------
void ImageFile::Private::AssertFailed(const char* s)
  {
  operator << (cout);
  cout << "utxassert failed '" << s << "'" << endl;
  }

//------------------------------------------------------
void ImageFile::Private::ThrewException(const unsigned int ex) 
  {
  operator << (cout);
  cout << "threw an exception: 0x" << hex << ex << dec << endl;
  }

//------------------------------------------------------
void ImageFile::Private::ThrewUnknownException()
  {
  operator << (cout);
  cout << "threw an unknown exception" << endl;
  }

//------------------------------------------------------
bool ImageFile::Private::Load(const string& fn)
  {
  FQFileName = fn;
  ifw.Load(FQFileName);
  if (!ifw.isValid())
    return false;

  return ifw.loadExportTable();
  }

//-----------------------------------------------------
void ImageFile::Private::invokeUnitTests()
  {
  Library lib(FQFileName);
  
  for(ifw.reset(); !ifw.done(); ifw.next())
    {
    if (!isOkUnitTest(ifw.getDecoratedName()))
      continue;
    
    try 
      {
      stats.numtestcases++;
  
      lib.invokeFunctionAt(ifw.getOrdinal());
      }
    catch(char* s)
      {
      AssertFailed(s);
      stats.numerrors++;
      }
    catch(unsigned int ex)
      {
      ThrewException(ex);
      stats.numexcps++;
      }
    catch(int ex)
      {
      ThrewException(ex);
      stats.numexcps++;
      }
    catch(SE_Exception& se)
      {
      ThrewException(se.ex);
      stats.numexcps++;
      }
    catch(...)
      {
      ThrewUnknownException();
      stats.numexcps++;
      }
    }
  }


//-------------------------
int toint(const char* s)
  {
  int n;
  for(n = 0; *s; ++s)
    {
    n = n * 10 + *s - '0';
    }
  return n;
  }

////-------------------------
////must have a signature like:
////   void  __stdcall  f(void)   => _Z5testfv@0
////  using namespace nmsp { void  __stdcall  f(void) } => _ZN4nmsp5testfEv@0
//bool ImageFile::Private::isOkUnitTest(char *p)
//  {
//  unsigned int i = 0;
//  unsigned int j = 0;
//  
////  if (p[i] != '_')
////    return false; //invalid or unknown decorated name
//  //++i;
//  //if (p[i] != 'Z')
//  //  return false; //invalid or unknown decorated name
//  if (p[i] != '?')
//    return false; //invalid or unknown decorated name
//
//  
//  char nlen[256];
//  char nsname[256];
//  ++i;
//  if (p[i] == 'N') //it's a namespace
//    {
//    ++i;
//    for (j = 0; isdigit(p[i]); ++i, ++j)
//      {
//      nlen[j] = p[i];
//      }
//    nlen[j] = 0;
//    int n = toint(nlen);
//    for (j = 0; n > 0; --n, ++i)
//      {
//      nsname[j] = p[i];
//      }
//    nsname[j] = 0;
//    }
//
//  //we're at the name
//  for (j = 0; isdigit(p[i]); ++i, ++j)
//    {
//    nlen[j] = p[i];
//    }
//  nlen[j] = 0;
//  int n = toint(nlen);
//  for (j = 0; j < sizeof(undecoratedName) && n > 0; --n, ++i, ++j)
//    {
//    undecoratedName[j] = p[i];
//    }
//  undecoratedName[j] = 0;
//  
//  if (j >= sizeof(undecoratedName))
//    return false; //func name > buf size... possible invalid or unknown decorated name
//  
//  if (strncmp(undecoratedName, cUTMethodPrefix.c_str(), cUTMethodPrefix.length()) != 0)
//    return false;
//
//  cout << "here: " << (char*) &p[i] << " : " << undecoratedName << "\n";
//  
////  if (p[i] == 0)
////    return false; //invalid or unknown decorated name
////  
////  ++i;
////  if (p[i] != 'Y')
////    return false;  //invalid or unknown function type; if p[i] == 'Q' then it's a class
////  
////  ++i;
////  if (p[i] != 'G')
////    return false; //not __stdcall calling convention
////  
////  ++i;
////  if (p[i] != 'X')
////    return false; //not a void return call
////  
////  ++i;
////  if (p[i] != 'X')
////    return false; //not a void parameter list
////
//  return true;
//  }
  
  bool ImageFile::Private::isOkUnitTest(char *p)
  {
  unsigned int i = 0;
  unsigned int j = 0;
  
  if (p[0] != '?')
    return false; //invalid or unknown decorated name
  
  for(j = 0, ++i; j < sizeof(undecoratedName) && p[i] && p[i] != '@'; ++i, ++j)
    {
    undecoratedName[j] = p[i];
    }
  if (j >= sizeof(undecoratedName))
    return false; //func name > buf size... possible invalid or unknown decorated name
  
  if (strncmp(undecoratedName, cUTMethodPrefix.c_str(), cUTMethodPrefix.length()) != 0)
    return false;
  
  if (p[i] == 0)
    return false; //invalid or unknown decorated name
  
  undecoratedName[j] = 0;
  ++i; //skip @
  
  //it can be a class name or a namespace here...
  //if (p[i] && p[i] != '@')
  //  {
  //  return false; //it's a class method
  //  }
  char nsname[256];
  nsname[0] = 0;
  if (p[i] && p[i] != '@')
    {
    //it's a class or a namespace...

    for(j = 0, ++i; j < sizeof(nsname) && p[i] && p[i] != '@'; ++i, ++j)
      {
      nsname[j] = p[i];
      }

    nsname[j] = 0;
    i++; //skip '@'

    //return false; //it's a class method
    }

  ++i;
  if (p[i] != 'Y')
    return false;  //invalid or unknown function type; if p[i] == 'Q' then it's a class
  
  ++i;
  if (p[i] != 'G')
    return false; //not __stdcall calling convention
  
  ++i;
  if (p[i] != 'X')
    return false; //not a void return call
  
  ++i;
  if (p[i] != 'X')
    return false; //not a void parameter list

  //++i;
  //if (p[i] != 'Z')
  //  return false; //last char is a 'Z'

  return true;
  }
  

ImageFile.h

Synopsis
#pragma once
#include <string>

//-----------------------------------------------------
class SE_Exception
  {
  public:
    unsigned int ex;
  } ;

//------------------------------------------------------
class ImageFile
  {
  public:
    ImageFile();
    ~ImageFile(); 
    void Run(const std::string& fn);
    
  private:
    class Private;
    Private& m_impl;
  } ;

ImageFileWrapper.cpp

Synopsis
#include <iostream>
using std::cout;
using std::endl;

#define WIN32_LEAN_AND_MEAN
#define NOMINMAX 1
#include <windows.h>

#include "utxCommon.h"
#include "ImageFileWrapper.h"
#include "MemoryMappedImageFile.h"

//-----------------------------------------------------
class SectionHeader
  {
  public:
    //-----------------------------------------------------
    SectionHeader& operator = (PIMAGE_SECTION_HEADER h)
      {
      header = h;
      return *this;
      }
    
    //-----------------------------------------------------
    bool isNull()
      {
      return header == 0;
      }
    
    //-----------------------------------------------------
    DWORD getOffset(DWORD base)
      {
      return base - getDelta();
      }
    
    //-----------------------------------------------------
    DWORD getDelta()
      {
      return (DWORD) (header->VirtualAddress - header->PointerToRawData);
      }
    
    //-----------------------------------------------------
    PIMAGE_EXPORT_DIRECTORY getExportDir(DWORD base)
      {
      return  MakePtr(PIMAGE_EXPORT_DIRECTORY, base, header->PointerToRawData);
      }
    
    //-----------------------------------------------------
    PIMAGE_EXPORT_DIRECTORY getExportDir(DWORD base, DWORD tableVA)
      {
      return (PIMAGE_EXPORT_DIRECTORY) (base + tableVA - getDelta());
      }
    
  private:
    PIMAGE_SECTION_HEADER header;
  } ;


//-----------------------------------------------------
class DosHeaderPtr
  {
  public:
    //-----------------------------------------------------
    DosHeaderPtr()
      : header(0)
      {
      }
    
    //-----------------------------------------------------
    PIMAGE_NT_HEADERS getNtHeader()
      {
      return  MakePtr( PIMAGE_NT_HEADERS, header,	header->e_lfanew );
      }
    
    //-----------------------------------------------------
    operator DWORD()
      {
      return (DWORD) header;
      }
    
    //-----------------------------------------------------
    DosHeaderPtr& operator = (PIMAGE_DOS_HEADER h)
      {
      header = h;
      return *this;
      }
    
    //-----------------------------------------------------
    bool isValidImage()
      {
      return !isNull() && isDosSignature();
      }
    
  private:
    //-----------------------------------------------------
    bool isNull()
      {
      return header == 0;
      }
    
    //-----------------------------------------------------
    bool isDosSignature()
      {
      return header->e_magic == IMAGE_DOS_SIGNATURE;
      }
    
  private:
    PIMAGE_DOS_HEADER header;
  } ;

//-----------------------------------------------------
class NtHeaderPtr
  {
  public:
    //-----------------------------------------------------
    NtHeaderPtr() : header(0)
      {
      }
    
    //-----------------------------------------------------
    NtHeaderPtr& operator =(DosHeaderPtr& p)
      {
      header = p.getNtHeader();
      return *this;
      }
    
    //-----------------------------------------------------
    bool findExportTable(DWORD base, PIMAGE_EXPORT_DIRECTORY& exportDir, DWORD& offset)
      {
      SectionHeader sHeader;
      sHeader = getSectionHeader(".edata");
      if (!sHeader.isNull())
        {
        exportDir = sHeader.getExportDir(base);
        offset = sHeader.getOffset(base);
        return true;
        }
      
      DWORD tableVA = getExportTableVA();
      if (tableVA == 0)
        return false;
      
      sHeader = getSectionHeader();
      exportDir = sHeader.getExportDir(base, tableVA);
      offset = sHeader.getOffset(base);
      return true;
      }
    
    //-----------------------------------------------------
    bool isValidSignature()
      {
      return !IsBadReadPtr(header, sizeof(IMAGE_NT_HEADERS)) && isNtSignature();
      }
    
    //-----------------------------------------------------
    bool isValidExecutable()
      {
      return isCharacteristic(IMAGE_FILE_EXECUTABLE_IMAGE);
      };
    
    //-----------------------------------------------------
    bool isValidDll()
      {
      return isCharacteristic(IMAGE_FILE_DLL);
      }
    
  private:
    //-----------------------------------------------------
    bool isCharacteristic(WORD ch)
      {
      PIMAGE_FILE_HEADER pImageFileHeader = (PIMAGE_FILE_HEADER)&header->FileHeader;
      return (pImageFileHeader->Characteristics & ch) != 0;
      };
    
    //-----------------------------------------------------
    DWORD getExportTableVA()
      {
      PIMAGE_OPTIONAL_HEADER optionalHeader = (PIMAGE_OPTIONAL_HEADER)&header->OptionalHeader;
      return optionalHeader->DataDirectory[0].VirtualAddress;
      }
    
    //-----------------------------------------------------
    PIMAGE_SECTION_HEADER getSectionHeader()
      {
      return getEnclosingSectionHeader(getExportTableVA());
      }
      
    //-----------------------------------------------------
    static int icmp(const char* s1, const char* s2, int len)
      {
      for (int i = 0; i < len; ++i, ++s1, ++s2)
        {
        if (*s1 == 0 && *s2 == 0) return 0;
        if (*s1 == 0) return -1;
        if (*s2 == 0) return 1;
        if (*s1 == *s2) continue;
        if (*s1 < *s2) return -1;
        return 1;
        }
      return 0;
      }
    //-----------------------------------------------------
    PIMAGE_SECTION_HEADER getSectionHeader(PSTR name)
      {
      PIMAGE_SECTION_HEADER section = (PIMAGE_SECTION_HEADER)(header+1);
      for (unsigned int i = 0; i < header->FileHeader.NumberOfSections; i++, section++ )
        {
        if ( icmp((const char*) section->Name, name, IMAGE_SIZEOF_SHORT_NAME) == 0 )
          return section;
        }
      return 0;
      }
    
    //-----------------------------------------------------
    PIMAGE_SECTION_HEADER getEnclosingSectionHeader(DWORD rva)
      {
      PIMAGE_SECTION_HEADER section = IMAGE_FIRST_SECTION(header);
      for (unsigned i=0; i < header->FileHeader.NumberOfSections; i++, section++ )
        {
        // Is the RVA within this section?
        if ( (rva >= section->VirtualAddress) &&
          (rva < (section->VirtualAddress + section->Misc.VirtualSize)))
          return section;
        }
      return 0;
      }
    
    //-----------------------------------------------------
    bool isNtSignature()
      {
      return  header->Signature == IMAGE_NT_SIGNATURE ;
      }
    
  private:
    PIMAGE_NT_HEADERS header;
  } ;
  
  
  //-----------------------------------------------------
  class ExportTable
    {
    public:
      //-----------------------------------------------------
      ExportTable()
        : pDirectory(0), offset(0), functions(0), ordinals(0), name(0)
        {
        }
      
      //-----------------------------------------------------
      bool done()
        {
        return current >= pDirectory->NumberOfNames;
        }
      
      //-----------------------------------------------------
      void reset()
        {
        current = 0;
        }
      
      //-----------------------------------------------------
      void next()
        {
        current++;
        name++;			// Bump each pointer to the next array element
        ordinals++;
        functions++;
        }
      
      //-----------------------------------------------------
      DWORD getOrdinal()
        {
        return *ordinals + pDirectory->Base;
        }
      
      //-----------------------------------------------------
      char * getDecoratedName()
        {
        return *name + offset;
        }
      
      //-----------------------------------------------------
      bool Load(NtHeaderPtr& ntHeader, DosHeaderPtr& dosHeader)
        {
        if (! ntHeader.findExportTable(dosHeader, pDirectory, offset))
          return false;
     
        functions = (PDWORD)((DWORD)pDirectory->AddressOfFunctions + offset);
        ordinals = (PWORD)((DWORD)pDirectory->AddressOfNameOrdinals + offset);
        name = (PSTR*)((DWORD)pDirectory->AddressOfNames + offset);
        return true;
        }
      
    private:
      PIMAGE_EXPORT_DIRECTORY pDirectory;
      DWORD offset;
      
      PDWORD functions;
      PWORD ordinals;
      PSTR* name;
      DWORD current;
    } ;
  
  
  //-----------------------------------------------------
  class ImageFileWrapper::Private
    {
    public:
      ExportTable exportTable;
      MemoryMappedImageFile mmifile;
      
      //-----------------------------------------------------
      bool loadExportTable()
        {
        return exportTable.Load(pNtHeader, pDosHeader);
        }
      
      //-----------------------------------------------------
      void setHeaders()
        {
        pDosHeader = mmifile.getHeader();
        pNtHeader = pDosHeader;
        }
      
      //-----------------------------------------------------
      bool isValid()
        {
        if (!pDosHeader.isValidImage())
          {
          cout << "Unrecognized file format, expecting a DLL" << endl;
          return false;
          }
        
        if (!pNtHeader.isValidSignature())
          {
          cout << "Unhandled EXE type, or invalid .EXE" << endl;
          return false;
          }
        
        if (!pNtHeader.isValidExecutable())
          {
          cout << "File is not an executable image!" << endl;
          return false;
          }
        
        if (!pNtHeader.isValidDll())
          {
          cout << "File is not a DLL!" << endl;
          return false;
          }
        
        return true;
        }
      
    private:
      DosHeaderPtr pDosHeader;
      NtHeaderPtr  pNtHeader;
      
    } ;
  
  //-----------------------------------------------------
  ImageFileWrapper::ImageFileWrapper()
    : pimpl(* new Private)
    {
    }
  
  //-----------------------------------------------------
  ImageFileWrapper::~ImageFileWrapper()
    {
    delete &pimpl;
    }
  
  //-----------------------------------------------------
  bool ImageFileWrapper::loadExportTable()
    {
    return pimpl.loadExportTable();
    }
  
  //-----------------------------------------------------
  void ImageFileWrapper::Load(const string& fn)
    {
    if (!pimpl.mmifile.Load(fn))
      return;
    
    cout << "Loading file " << fn << "..." << endl;;
    pimpl.setHeaders();
    }
  
  //-----------------------------------------------------
  bool ImageFileWrapper::isValid()
    {
    return pimpl.isValid();
    }
  
  //-----------------------------------------------------
  void ImageFileWrapper::reset()
    {
    pimpl.exportTable.reset();
    }
  
  //-----------------------------------------------------
  bool ImageFileWrapper::done()
    {
    return pimpl.exportTable.done();
    }
  
  //-----------------------------------------------------
  void ImageFileWrapper::next()
    {
    pimpl.exportTable.next();
    }
  
  //-----------------------------------------------------
  char* ImageFileWrapper::getDecoratedName() 
    {
    return pimpl.exportTable.getDecoratedName();
    }
  
  //-----------------------------------------------------
  DWORD ImageFileWrapper::getOrdinal()
    {
    return pimpl.exportTable.getOrdinal();
    }
  

ImageFileWrapper.h

Synopsis
#pragma once

#include <string>
using std::string;

//------------------------------------------------------
class ImageFileWrapper
  {
  public:
    ImageFileWrapper();
    ~ImageFileWrapper();
    bool loadExportTable();
    void Load(const string& fn);
    bool isValid();
    
    void reset();
    bool done();
    void next();
    char * getDecoratedName();
    DWORD getOrdinal();
    
  private:
    class Private;
    Private& pimpl;
  } ;

Library.cpp

Synopsis
#include <string>
#include <iostream>
using namespace std;

#include "utxCommon.h"
#include "Library.h"

//-----------------------------------------------------
Library::Library(const string& fn)
: m_fileName(fn)
  {
  }

//-----------------------------------------------------
Library::~Library()
  {
  }

//-----------------------------------------------------
void Library::invokeFunctionAt(DWORD ordinal)
  {
  typedef void (*VVFUNCP)();

  VVFUNCP fp = (VVFUNCP) getAddress(ordinal);
  if (fp)
    fp();
  }

//-----------------------------------------------------
FARPROC Library::getAddress(DWORD ordinal)
  {
  if (!m_handle.create(m_fileName))
    {
    cout << "here " << m_fileName << " : " << ordinal << " : " << ::GetLastError() << "\n";
    return 0;
    }
  
  return ::GetProcAddress(m_handle, (LPCSTR) (0x0000FFFF & ordinal));
  }

Library.h

Synopsis
#pragma once
#include <string>

#include "NtHandles.h"
//-----------------------------------------------------
class Library
  {
  public:
    Library(const std::string& fn);
    ~Library();
    void invokeFunctionAt(DWORD ordinal);

  private:
    Library();
    FARPROC getAddress(DWORD ordinal);
    
  private:
    NtLibraryHandle m_handle;
    std::string m_fileName;
  } ;


MemoryMappedImageFile.cpp

Synopsis
#include <string>
#include <iostream>
using namespace std;

#define WIN32_LEAN_AND_MEAN
#define NOMINMAX 1
#include <windows.h>

#include "utxCommon.h"
#include "MemoryMappedImageFile.h"
#include "NtHandles.h"

//-----------------------------------------------------
class MemoryMappedImageFile::Private
  {
  public:
    NtFileHandle hFile;
    NtFileMappingHandle hFileMapping;
    NtMappedFileViewHandle hFileView;
  } ;

//-----------------------------------------------------
MemoryMappedImageFile::MemoryMappedImageFile()
: m_impl(* new Private())
  {
  }

//-----------------------------------------------------
MemoryMappedImageFile::~MemoryMappedImageFile()
  {
  delete &m_impl;
  }

//------------------------------------------------------
bool MemoryMappedImageFile::Load(const string& fn)
  {
  if (!m_impl.hFile.create(fn.c_str()))
    {
    cout << "Couldn't open file with CreateFile(), gle=" << GetLastError() << " : " << fn.c_str() << endl;
    return false;
    }
  
  if (!m_impl.hFileMapping.create(m_impl.hFile))
    {
    cout << "Couldn't open file mapping with CreateFileMapping()" << endl;
    return false;
    }
  
  if (!m_impl.hFileView.create(m_impl.hFileMapping))
    {
    cout << "Couldn't map view of file with MapViewOfFile()" << endl;
    return false;
    }
  
  return true;
  }

//-----------------------------------------------------
PIMAGE_DOS_HEADER MemoryMappedImageFile::getHeader()
  {
  return (PIMAGE_DOS_HEADER) (LPVOID) m_impl.hFileView;
  }

MemoryMappedImageFile.h

Synopsis
#pragma once
#include <string>
using std::string;

//-----------------------------------------------------
class MemoryMappedImageFile
  {
  public:
    MemoryMappedImageFile();
    ~MemoryMappedImageFile();
    bool Load(const std::string& fn);
    PIMAGE_DOS_HEADER getHeader();
    
  private:
    class Private;
    Private& m_impl;
  } ;

NTHandles.h

Synopsis
#pragma once

#include <windows.h>

//-----------------------------------------------------
template <typename tTrait>
class NtHandleImpl
  {
  protected:
    typename tTrait::HandleType h;
    bool isInvalid() { return h == tTrait::BadValue(); }

  public:	
    NtHandleImpl()
      : h(tTrait::BadValue())
      {
      }

    ~NtHandleImpl()
      {
      if (isInvalid())
        return;

      tTrait::Cleanup(h);
      h = tTrait::BadValue();
      }

    bool create(typename tTrait::CreateParmType p)
      {
      if (isInvalid())
        h = tTrait::create(p);
      return !isInvalid();
      }

    operator typename tTrait::HandleType()
      {
      return h;
      }
  } ;

//------------------------------------------------------
//-- Used for Nt Files in general
class NtFileHandleTrait
  {
  public:
    typedef HANDLE HandleType;
    typedef string CreateParmType;

    static HandleType BadValue()      { return INVALID_HANDLE_VALUE; }
    static void Cleanup(HandleType h) { CloseHandle(h); }
    static HandleType create(CreateParmType& fn)
      {
      return  ::CreateFile(fn.c_str(), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
      }
  } ;
typedef NtHandleImpl<NtFileHandleTrait>  NtFileHandle;
 
//------------------------------------------------------
//-- Used for Nt Memory Mapped Files
class NtFileMappingHandleTrait
  {
  public:
    typedef HANDLE HandleType;
    typedef HANDLE CreateParmType;

    static HandleType BadValue()      { return 0; }
    static void Cleanup(HandleType h) { CloseHandle(h); }
    static HandleType create(CreateParmType& hfile)
      {
      return  ::CreateFileMapping(hfile, NULL, PAGE_READONLY, 0, 0, NULL);
      }
  } ;
typedef NtHandleImpl<NtFileMappingHandleTrait> NtFileMappingHandle;

//------------------------------------------------------
//-- Used for Nt Memory Mapped Files
class NtMappedFileViewHandleTrait
  {
  public:
    typedef LPVOID HandleType;
    typedef HANDLE CreateParmType;

    static HandleType BadValue()      { return 0; }
    static void Cleanup(HandleType h) { UnmapViewOfFile(h); }
    static HandleType create(CreateParmType& hfilemap)
      {
      return  ::MapViewOfFile(hfilemap, FILE_MAP_READ, 0, 0, 0);
      }
  } ;
typedef NtHandleImpl<NtMappedFileViewHandleTrait> NtMappedFileViewHandle;

//------------------------------------------------------
//-- Used for Nt FileFind operations
typedef pair<string, WIN32_FIND_DATA*> FileFindPair;
class NtFileFindHandleTrait
  {
  public:
    typedef HANDLE HandleType;
    typedef FileFindPair CreateParmType;

    static HandleType BadValue()      { return INVALID_HANDLE_VALUE; }
    static void Cleanup(HandleType h) { FindClose(h); }
    static HandleType create(CreateParmType& cpt)
      {
      return ::FindFirstFile(cpt.first.c_str(), cpt.second);
      }
  } ;

class NtFileFindHandle : public NtHandleImpl<NtFileFindHandleTrait>
  {
  public:	
    bool next(NtFileFindHandleTrait::CreateParmType& cpt)
      {
      return ::FindNextFile(h, cpt.second) == TRUE;
      }
  } ;

//------------------------------------------------------
//-- Used for Nt DLL Libraries
class NtLibraryHandleTrait
  {
  public:
    typedef HMODULE HandleType;
    typedef string CreateParmType;

    static HandleType BadValue()      { return 0; }
    static void Cleanup(HandleType h) { ::FreeLibrary(h); }
    static HandleType create(CreateParmType& fn)
      {
      return ::LoadLibrary(fn.c_str());
      }
  } ;
typedef NtHandleImpl<NtLibraryHandleTrait>  NtLibraryHandle;

Statistics.cpp

Synopsis
#include "utxCommon.h"
#include <iostream>
using namespace std;

//--------------------------------------------
Statistics::Statistics()
{
  numfiles = 0;
  numtestcases = 0;
  numasserts = 0;
  numerrors = 0;
  numexcps = 0;
}

//--------------------------------------------
void Statistics::dump()
{
  cout << endl
    << "Number of unit tests    : " << numfiles << endl
    << "Number of test methods  : " << numtestcases << endl
    << "Number of assert calls  : " << numasserts << endl
    << "Number of errors        : " << numerrors << endl
    << "Number of exceptions    : " << numexcps << endl;
  if (numerrors != 0 || numexcps != 0)
    cout << "************* FAILED *** FAILED *** FAILED *************" << endl;
}

Statistics.h

Synopsis
#pragma once

class Statistics
{
public:
  int numfiles;
  int numtestcases;
  int numasserts;
  int numerrors;
  int numexcps;
  
  Statistics();
  void dump();
} ;

ut.rc

Synopsis
 UTXASSERTFUNC RCDATA
 BEGIN
 "XXXX"
 END
 

utx.cpp

Synopsis
#define WIN32_LEAN_AND_MEAN
#define NOMINMAX 1
#include <windows.h>

#include "utxCommon.h"
#include "App.h"

Statistics stats;

//-----------------------------------------------------
int main(int argc, char *argv[])
  {
  int rc = 0;
  try 
    {
    App theApp;
    theApp.Init(argc, argv);
    theApp.Run();
    stats.dump();
    rc = stats.numerrors + stats.numexcps;
    } 
  catch (int badrc)
    {
    rc = badrc;
    }

  return rc;
  }

utxCommon.h

Synopsis
#pragma once

#include "Statistics.h"

#define MakePtr( cast, ptr, addValue ) ((cast)( (DWORD)(ptr) + (DWORD)(addValue) ))
extern Statistics stats;

#include <string>
using std::string;
extern string cUTFilePrefix;
extern string cUTFileSuffix;
extern string cUTMethodPrefix;
extern string cUTMethodSuffix;


testansi.cpp

Synopsis
#define DEFINEUTXTEST
#include "\projects\include\utx.h"

//once with ansi
namespace ns_ansi
  {
  #include "testunicodebase.cpp"
  }

__declspec(dllexport) class xxbob2
  {
  public:
    TEST(unicode_normal_notsubstring_vrbl)
      {
      utxBoolAssert(false);
      }
  } ;

testcom.cpp

Synopsis
//#define DEFINEUTXTEST
//#include "\projects\include\utx.h"
//#include "\projects\include\utxcom.h"
//
////BSTR
//TEST(normal_bstr_vrbl)
//  {
//  BSTR v1 = SysAllocString(L"abc");
//  BSTR v2 = SysAllocString(L"abc");
//  BSTR v3 = SysAllocString(L"abcx");
//  utxassert(v1, v2);
//  utxassert2(v1, v2, "with a message");
//
//  _utxAssertNextAssertFails();
//  utxassert(v1, v3);
//  _utxAssertNextAssertFails();
//  utxassert2(v1, v3, "with a message");
//
//  SysFreeString(v1);
//  SysFreeString(v2);
//  SysFreeString(v3);
//  }
//
//TEST(normal_notbstr_vrbl)
//{
//  BSTR v1 = SysAllocString(L"abc");
//  BSTR v2 = SysAllocString(L"abcx");
//  BSTR v3 = SysAllocString(L"abc");
//
//  utxassertnot(v1, v2);
//  utxassertnot2(v1, v2, "with a message");
//
//  _utxAssertNextAssertFails();
//  utxassertnot(v1, v3);
//  _utxAssertNextAssertFails();
//  utxassertnot2(v1, v3, "with a message");
//  SysFreeString(v1);
//  SysFreeString(v2);
//  SysFreeString(v3);
//  }
//
//TEST(normal_bstr_t_vrbl)
//  {
//  _bstr_t v1 = "abc";
//  _bstr_t v2 = "abc";
//  _bstr_t v3 = "abcx";
//  utxassert(v1, v2);
//  utxassert2(v1, v2, "with a message");
//
//  _utxAssertNextAssertFails();
//  utxassert(v1, v3);
//  _utxAssertNextAssertFails();
//  utxassert2(v1, v3, "with a message");
//  }
//

testunicode.cpp

Synopsis
#define DEFINEUTXTEST
#define UNICODE 1
#define _UNICODE 1
#include "\projects\include\utx.h"

//once with unicode
namespace ns_unicode
  {
  #include "testunicodebase.cpp"
  }

class xxbob
  {
  public:
    TEST(unicode_normal_notsubstring_vrbl)
      {
      utxBoolAssert(false);
      }
  } ;

testunicodebase.cpp

Synopsis
//NO #PRAGMA ONCE!

//bool ------------------------------------------------------------------
TEST(bool_literal)
  {
  utxBoolAssert(true || true);
  utxBoolAssert2(true || false, _T("with a message"));

  _utxAssertNextAssertFails();
  utxBoolAssert(false || false);
  _utxAssertNextAssertFails();
  utxBoolAssert2(false && true, _T("with a message"));
  }
TEST(notbool_literal)
  {
  utxBoolAssertNot(false && true);
  utxBoolAssertNot2(false && false, _T("with a message"));

  _utxAssertNextAssertFails();
  utxBoolAssertNot(true || true);
  _utxAssertNextAssertFails();
  utxBoolAssertNot2(true || false, _T("with a message"));
  }

TEST(bool_vrbl)
  {
  bool v1 = true;
  bool v2 = false;
  utxBoolAssert(v1);
  utxBoolAssert2(v1, _T("with a message"));

  _utxAssertNextAssertFails();
  utxBoolAssert(v2);
  _utxAssertNextAssertFails();
  utxBoolAssert2(v2, _T("with a message"));
  _utxAssertNextAssertFails();
  utxBoolAssert2(v1 && v2, _T("with a message"));
  }

TEST(notbool_vrbl)
  {
  bool v1 = false;
  bool v2 = true;
  utxBoolAssertNot(v1);
  utxBoolAssertNot2(v1, _T("with a message"));

  _utxAssertNextAssertFails();
  utxBoolAssertNot(v2);
  _utxAssertNextAssertFails();
  utxBoolAssertNot2(v2, _T("with a message"));
  _utxAssertNextAssertFails();
  utxBoolAssertNot2(v1 || v2, _T("with a message"));
  }

//TCHAR* ------------------------------------------------------------------
TEST(charstar_literal)
  {
  utxassert(_T("abc"), _T("abc"));
  utxassert2(_T("abc"), _T("abc"), _T("with a message"));
  //utxassert2(_T("abc"), _T("abc"), "with a message");

  _utxAssertNextAssertFails();
  utxassert(_T("abc"), _T("abcx"));
  _utxAssertNextAssertFails();
  utxassert2(_T("abc"), _T("abcx"), _T("with a message"));
  }

TEST(notcharstar_literal)
  {
  utxassertnot(_T("abc"), _T("abcx"));
  utxassertnot2(_T("abc"), _T("abcx"), _T("with a message"));

  _utxAssertNextAssertFails();
  utxassertnot(_T("abc"), _T("abc"));
  _utxAssertNextAssertFails();
  utxassertnot2(_T("abc"), _T("abc"), _T("with a message"));
  }

TEST(charstar_vrbl)
  {
  TCHAR* v1 = _T("abc");
  TCHAR* v2 = _T("abc");
  TCHAR* v3 = _T("abcx");
  utxassert(v1, v2);
  utxassert2(v1, v2, _T("with a message"));

  _utxAssertNextAssertFails();
  utxassert(v1, v3);
  _utxAssertNextAssertFails();
  utxassert2(v1, v3, _T("with a message"));
  }

TEST(notcharstar_vrbl)
  {
  TCHAR* v1 = _T("abc");
  TCHAR* v2 = _T("abcx");
  TCHAR* v3 = _T("abc");
  utxassertnot(v1, v2);
  utxassertnot2(v1, v2, _T("with a message"));

  _utxAssertNextAssertFails();
  utxassertnot(v1, v3);
  _utxAssertNextAssertFails();
  utxassertnot2(v1, v3, _T("with a message"));
  }

//tchar[]  ------------------------------------------------------------------
TEST(charbuf_vrbl)
  {
  TCHAR v1[] = _T("abc");
  TCHAR v2[] = _T("abc");
  TCHAR v3[] = _T("abcx");
  utxassert(v1, v2);
  utxassert2(v1, v2, _T("with a message"));

  _utxAssertNextAssertFails();
  utxassert(v1, v3);
  _utxAssertNextAssertFails();
  utxassert2(v1, v3, _T("with a message"));
  }

TEST(notcharbuf_vrbl)
  {
  TCHAR v1[] = _T("abc");
  TCHAR v2[] = _T("abcx");
  TCHAR v3[] = _T("abc");
  utxassertnot(v1, v2);
  utxassertnot2(v1, v2, _T("with a message"));

  _utxAssertNextAssertFails();
  utxassertnot(v1, v3);
  _utxAssertNextAssertFails();
  utxassertnot2(v1, v3, _T("with a message"));
  }

//substring  ------------------------------------------------------------------
TEST(substring_literal)
  {
  utxAssertStringContains(_T("abcd"), _T("bc"));
  utxAssertStringContains2(_T("abcd"), _T("bc"), _T("with a message"));

  utxAssertStringContains(_T("abcd"), _T("a"));
  utxAssertStringContains(_T("abcd"), _T("d"));
  utxAssertStringContains(_T("abcd"), _T("")); //every string contains the empty string
  utxAssertStringContains(_T("abcd"), _T("abcd")); //every string contains itself

  _utxAssertNextAssertFails();
  utxAssertStringContains(_T("abcd"), _T("x"));
  _utxAssertNextAssertFails();
  utxAssertStringContains2(_T("abcd"), _T("x"), _T("with a message"));
  _utxAssertNextAssertFails();
  utxAssertStringContains(_T("abcd"), _T("xabcdx"));
  }

TEST(notsubstring_literal)
  {
  utxAssertStringContainsNot(_T("abcd"), _T("bx"));
  utxAssertStringContainsNot2(_T("abcd"), _T("bx"), _T("with a message"));

  utxAssertStringContainsNot(_T("abcd"), _T("x"));
  utxAssertStringContainsNot(_T("abcd"), _T("x"));

  _utxAssertNextAssertFails();
  utxAssertStringContainsNot(_T("abcd"), _T("bc"));
  _utxAssertNextAssertFails();
  utxAssertStringContainsNot2(_T("abcd"), _T("bc"), _T("with a message"));
  _utxAssertNextAssertFails();
  utxAssertStringContainsNot(_T("abcd"), _T(""));
  _utxAssertNextAssertFails();
  utxAssertStringContainsNot(_T("abcd"), _T("abcd"));
  }

TEST(substring_vrbl)
  {
  tstring v1 = _T("abcd");
  tstring v2 = _T("bc");
  utxAssertStringContains(v1, v2);
  utxAssertStringContains2(v1, v2, _T("with a message"));

  tstring v3 = _T("a");
  tstring v4 = _T("d");
  utxAssertStringContains(v1, v3);
  utxAssertStringContains(v1, v4);
  tstring v5 = _T("");
  utxAssertStringContains(v1, v5); //every string contains the empty string
  tstring v6;
  utxAssertStringContains(v1, v6); //every string contains the empty string
  tstring v7 = v1;
  utxAssertStringContains(v1, v7); //every string contains itself

  tstring v8 = _T("x");
  _utxAssertNextAssertFails();
  utxAssertStringContains(v1, v8);
  _utxAssertNextAssertFails();
  utxAssertStringContains2(v1, v8, _T("with a message"));
  _utxAssertNextAssertFails();
  tstring v9 = _T("xabcdx");
  utxAssertStringContains(v1, v9);
  }

TEST(notsubstring_vrbl)
  {
  tstring v1 = _T("abcd");
  tstring v2 = _T("bx");
  utxAssertStringContainsNot(v1, v2);
  utxAssertStringContainsNot2(v1, v2, _T("with a message"));

  tstring v3 = _T("x");
  utxAssertStringContainsNot(v1, v3);

  tstring v9 = _T("xabcdx");
  utxAssertStringContainsNot(v1, v9);

  tstring v8 = _T("b");
  _utxAssertNextAssertFails();
  utxAssertStringContainsNot(v1, v8);
  _utxAssertNextAssertFails();
  utxAssertStringContainsNot2(v1, v8, _T("with a message"));

  _utxAssertNextAssertFails();
  tstring v5 = _T("");
  utxAssertStringContainsNot(v1, v5); //every string contains the empty string

  _utxAssertNextAssertFails();
  tstring v6;
  utxAssertStringContainsNot(v1, v6); //every string contains the empty string

  _utxAssertNextAssertFails();
  tstring v7 = v1;
  utxAssertStringContainsNot(v1, v7); //every string contains itself
  }

//tstring  ------------------------------------------------------------------
TEST(tstring_literal)
  {
  utxassert(tstring(_T("abc")), tstring(_T("abc")));
  utxassert2(tstring(_T("abc")), tstring(_T("abc")), _T("with a message"));

  _utxAssertNextAssertFails();
  utxassert(tstring(_T("abc")), tstring(_T("abcx")));
  _utxAssertNextAssertFails();
  utxassert2(tstring(_T("abc")), tstring(_T("abcx")), _T("with a message"));
  }

TEST(nottstring_literal)
  {
  utxassertnot(tstring(_T("abc")), tstring(_T("abcx")));
  utxassertnot2(tstring(_T("abc")), tstring(_T("abcx")), _T("with a message"));

  _utxAssertNextAssertFails();
  utxassertnot(tstring(_T("abc")), tstring(_T("abc")));
  _utxAssertNextAssertFails();
  utxassertnot2(tstring(_T("abc")), tstring(_T("abc")), _T("with a message"));
  }

TEST(tstring_vrbl)
  {
  tstring v1 = _T("abc");
  tstring v2 = _T("abc");
  tstring v3 = _T("abcx");
  utxassert(v1, v2);
  utxassert2(v1, v2, _T("with a message"));

  _utxAssertNextAssertFails();
  utxassert(v1, v3);
  _utxAssertNextAssertFails();
  utxassert2(v1, v3, _T("with a message"));
  }

TEST(nottstring_vrbl)
  {
  tstring v1 = _T("abc");
  tstring v2 = _T("abcx");
  tstring v3 = _T("abc");
  utxassertnot(v1, v2);
  utxassertnot2(v1, v2, _T("with a message"));

  _utxAssertNextAssertFails();
  utxassertnot(v1, v3);
  _utxAssertNextAssertFails();
  utxassertnot2(v1, v3, _T("with a message"));
  }

//integral types  ------------------------------------------------------------------
#define TEST1_INTEGRALTYPE(name, type, val1, val2) \
  TEST(name##_literal) \
     { \
     utxassert((type) val1, (type) val1); \
     utxassert2((type) val1, (type) val1, _T("with a message")); \
     _utxAssertNextAssertFails(); \
     utxassert((type) val1, (type) val2); \
     _utxAssertNextAssertFails(); \
     utxassert2((type) val1, (type) val2, _T("with a message")); \
     }

#define TEST2_INTEGRALTYPE(name, type, val1, val2) \
  TEST(name##_literal_not) \
      { \
      utxassertnot((type) val1, (type) val2); \
      utxassertnot2((type) val1, (type) val2, _T("with a message")); \
      _utxAssertNextAssertFails(); \
      utxassertnot((type) val1, (type) val1); \
      _utxAssertNextAssertFails(); \
      utxassertnot2((type) val1, (type) val1, _T("with a message")); \
      }
#define TEST3_INTEGRALTYPE(name, type, val1, val2) \
  TEST(name##_vrbl) \
      { \
      type v1 = (type) val1; \
      type v2 = (type) val1; \
      type v3 = (type) val2; \
      utxassert(v1, v2); \
      utxassert2(v1, v2, _T("with a message")); \
      _utxAssertNextAssertFails(); \
      utxassert(v1, v3); \
      _utxAssertNextAssertFails(); \
      utxassert2(v1, v3, _T("with a message")); \
      }
#define TEST4_INTEGRALTYPE(name, type, val1, val2) \
  TEST(name##_vrbl_not) \
      { \
      type v1 = (type) val1; \
      type v2 = (type) val2; \
      type v3 = (type) val1; \
      utxassertnot(v1, v2); \
      utxassertnot2(v1, v2, _T("with a message")); \
      _utxAssertNextAssertFails(); \
      utxassertnot(v1, v3); \
      _utxAssertNextAssertFails(); \
      utxassertnot2(v1, v3, _T("with a message")); \
      }

//long ------------------------------------------------------------------
TEST1_INTEGRALTYPE(slong, long, 0x7FFFFFF, 0x7FFFFFE);
TEST2_INTEGRALTYPE(slong, long, -1, -2);
TEST3_INTEGRALTYPE(slong, long, 0xFFFFFFFF, 0xFFFFFFFE);
TEST4_INTEGRALTYPE(slong, long, 0xFFFFFFFF, 0xFFFFFFFE);

//unsigned long ------------------------------------------------------------------
TEST1_INTEGRALTYPE(ulong, unsigned long, 0x7FFFFFF, 0x7FFFFFE);
TEST2_INTEGRALTYPE(ulong, unsigned long, 0xFFFFFFF, 0xFFFFFFE);
TEST3_INTEGRALTYPE(ulong, unsigned long, -1, -2);
TEST4_INTEGRALTYPE(ulong, unsigned long, 23, 24);

//int ------------------------------------------------------------------
TEST1_INTEGRALTYPE(sint, int, 0x7FFFFFF, 0x7FFFFFE);
TEST2_INTEGRALTYPE(sint, int, -1, -2);
TEST3_INTEGRALTYPE(sint, int, 0xFFFFFFFF, 0xFFFFFFFE);
TEST4_INTEGRALTYPE(sint, int, 0xFFFFFFFF, 0xFFFFFFFE);

//unsigned int ------------------------------------------------------------------
TEST1_INTEGRALTYPE(uint, unsigned int, 0x7FFFFFF, 0x7FFFFFE);
TEST2_INTEGRALTYPE(uint, unsigned int, 0xFFFFFFF, 0xFFFFFFE);
TEST3_INTEGRALTYPE(uint, unsigned int, -1, -2);
TEST4_INTEGRALTYPE(uint, unsigned int, 23, 24);

//short ------------------------------------------------------------------
TEST1_INTEGRALTYPE(sshort, short, 0x7FFF, 0x7FFE);
TEST2_INTEGRALTYPE(sshort, short, -1, -2);
TEST3_INTEGRALTYPE(sshort, short, 0x7FFF, 0x7FFE);
TEST4_INTEGRALTYPE(sshort, short, 0x7FFF, 0x7FFE);

//unsigned short ------------------------------------------------------------------
TEST1_INTEGRALTYPE(ushort, unsigned short, 0x7FFF, 0x7FFE);
TEST2_INTEGRALTYPE(ushort, unsigned short, 0xFFFF, 0xFFFE);
TEST3_INTEGRALTYPE(ushort, unsigned short, -1, -2);
TEST4_INTEGRALTYPE(ushort, unsigned short, 23, 24);

////__int64 ------------------------------------------------------------------
//TEST1_INTEGRALTYPE(i64, __int64, 0x7FFFFFFFFFFFFFF, 0x7FFFFFFFFFFFFFE);
TEST2_INTEGRALTYPE(i64, __int64, 0xFFFFFFF, 0xFFFFFFE);
TEST3_INTEGRALTYPE(i64, __int64, -1, -2);
TEST4_INTEGRALTYPE(i64, __int64, 23, 24);

////long long ------------------------------------------------------------------
//TEST1_INTEGRALTYPE(i64, long long int, 0x7FFFFFFFFFFFFFF, 0x7FFFFFFFFFFFFFE);
//TEST2_INTEGRALTYPE(i64, long long, 0xFFFFFFF, 0xFFFFFFE);
//TEST3_INTEGRALTYPE(i64, long long, -1, -2);
//TEST4_INTEGRALTYPE(i64, long long, 23, 24);

//double  ------------------------------------------------------------------
TEST(double_literal)
  {
  utxDoubleAssert(23.0, 23.0, 0.001);
  utxDoubleAssert2(23.0, 23.0, 0.001, _T("with a message"));

  _utxAssertNextAssertFails();
  utxDoubleAssert(23.0, 24.0, 0.001);
  _utxAssertNextAssertFails();
  utxDoubleAssert2(23.0, 24.0, 0.001, _T("with a message"));

  utxDoubleAssert(23.0009, 23.0, 0.001);
  _utxAssertNextAssertFails();
  utxDoubleAssert(23.0009, 23.0, 0.0001);
  }

TEST(notdouble_literal)
  {
  utxDoubleAssertNot(23.0, 24.0, 0.001);
  utxDoubleAssertNot2(23.0, 24.0, 0.001, _T("with a message"));

  _utxAssertNextAssertFails();
  utxDoubleAssertNot(23.0, 23.0, 0.001);
  _utxAssertNextAssertFails();
  utxDoubleAssertNot2(23.0, 23.0, 0.001, _T("with a message"));

  utxDoubleAssertNot(23.0009, 23.0, 0.0001);
  _utxAssertNextAssertFails();
  utxDoubleAssertNot(23.0009, 23.0, 0.001);
  }

TEST(double_vrbl)
  {
  double v1 = 23.0;
  double v2 = 23.0;
  double v3 = 24.0;
  double v4 = 23.0009;

  utxDoubleAssert(v1, v2, 0.001);
  utxDoubleAssert2(v1, v2, 0.001, _T("with a message"));

  _utxAssertNextAssertFails();
  utxDoubleAssert(v1, v3, 0.001);
  _utxAssertNextAssertFails();
  utxDoubleAssert2(v1, v3, 0.001, _T("with a message"));

  utxDoubleAssert(v4, v1, 0.001);
  _utxAssertNextAssertFails();
  utxDoubleAssert(v4, v1, 0.0001);
  }

TEST(notdouble_vrbl)
  {
  double v1 = 23.0;
  double v2 = 24.0;
  double v3 = 23.0;
  double v4 = 23.0009;

  utxDoubleAssertNot(v1, v2, 0.001);
  utxDoubleAssertNot2(v1, v2, 0.001, _T("with a message"));

  _utxAssertNextAssertFails();
  utxDoubleAssertNot(v1, v3, 0.001);
  _utxAssertNextAssertFails();
  utxDoubleAssertNot2(v1, v3, 0.001, _T("with a message"));

  utxDoubleAssertNot(v4, v1, 0.0001);
  _utxAssertNextAssertFails();
  utxDoubleAssertNot(v4, v1, 0.001);
  }

testutx.cpp

Synopsis
#define DEFINEUTXTEST
#define DEFINENEXTASSERTFAILS
#define CRTMEMDEBUG 
#include "d:/projects/include/utx.h"

#if defined(UNICODE) || defined(_UNICODE)
#error "Turn off UNICODE!"
#endif

UTXDLLMAIN_CHECKLEAKS(-1);

TEST(crt_leaks)
  {
  int* x = new int;
  x = 0;
  //you will see a report on standard output
  }

//void*
TEST(ptr)
  {
  void* p = 0;
  utxAssertPtrIsNull(p);
  utxAssertPtrIsNull2(p, "a message");

  p = (void*) 1;
  _utxAssertNextAssertFails();
  utxAssertPtrIsNull(p);
  _utxAssertNextAssertFails();
  utxAssertPtrIsNull2(p, "a message");
  }

TEST(ptr_not)
  {
  void* p = (void*) 1;
  utxAssertPtrIsNotNull(p);
  utxAssertPtrIsNotNull2(p, "a message");

  p = 0;
  _utxAssertNextAssertFails();
  utxAssertPtrIsNotNull(p);
  _utxAssertNextAssertFails();
  utxAssertPtrIsNotNull2(p, "a message");
  }






Contact me about content on this page using john_web-at-arrizza-dot-com
For Web Master or site problems contact: webadmin-at-arrizza-dot-com
Copyright John Arrizza (c) 2001,2002,2003,2004,2005,2006,2007