If you've used CPPUnit before, you are probably aware of its assertion_traits
class that is templatized to handle arbitrary types. This is what allows it to print the "actual" and "expected" values for non-string types when test cases fail. I have used this with success several times, but for one specific type it isn't working for me. Here is a partial declaration for my class, its parent's class, and some non-member operators (the whole thing is huge, plus my company won't let me post it):
class _declspec(dllexport) HWDBDateTime
{
public:
HWDBDateTime();
HWDBDateTime(const HWDBDateTime& other);
HWDBDateTime& operator=(const HWDBDateTime& other);
RWCString asString() const;
RWCString asString(const char *format, const boost::local_time::time_zone_ptr pZone = STimeZone::GetServerTimeZone()) const;
};
bool _declspec(dllexport) operator==(const HWDBDateTime& dt1, const HWDBDateTime& dt2);
bool _declspec(dllexport) operator!=(const HWDBDateTime& dt1, const HWDBDateTime& dt2);
bool _declspec(dllexport) operator< (const HWDBDateTime& dt1, const HWDBDateTime& dt2);
bool _declspec(dllexport) operator<=(const HWDBDateTime& dt1, const HWDBDateTime& dt2);
bool _declspec(dllexport) operator> (const HWDBDateTime& dt1, const HWDBDateTime& dt2);
bool _declspec(dllexport) operator>=(const HWDBDateTime& dt1, const HWDBDateTime& dt2);
class _declspec(dllexport) STimeStamp : public HWDBDateTime
{
public:
STimeStamp();
STimeStamp(const STimeStamp& other);
STimeStamp(const HWDBDateTime& other);
explicit STimeStamp(double d);
STimeStamp& operator=(double d);
operator double() const;
};
And here is my attempt at specializing the CPPUnit assertions class:
template <>
struct CppUnit::assertion_traits<STimeStamp>
{
static bool equal( STimeStamp x, STimeStamp y )
{
return x == y;
}
static std::string toString( STimeStamp x )
{
return (const char *)x.asString();
}
};
I've tried it passing by value, as seen above, also passing const references, I've tried casting the values inside the functions to HWDBDateTime
(since that's where the operators and asString()
methods are defined), nothing seems to help. I've put it at the top of my test suite's CPP file, and I've put it into a master header file that contains project-wide assertion_traits specializations, such as one for RWCString that works flawlessly. Somehow, whenever a test case fails, it insists on printing out my time as a floating-point value (presumably a double; a specialization for double is built in to CPPUnit) -- this is why I made sure to include my to/from double conversion operators in the minimized code above.
Is there something inherently wrong with what I'm doing? Does the specialization need to be present at a certain point in the compilation process, and maybe I just haven't found that point? Would this mythical point be per-translation-unit or per-project? I'm using VS2008.