// -*- c++ -*- // The original version of this code (revision 2 of the Subversion // archive) was released subject to the following license: // Copyright (c) 2006, Sun Microsystems, Inc. All rights reserved. // Redistribution and use in source and binary forms, with or // without modification, are permitted provided that the following // conditions are met: // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following // disclaimer in the documentation and/or other materials provided // with the distribution. // * Neither the name of Sun Microsystems or the names of // contributors may be used to endorse or promote products derived // from this software without specific prior written permission. // THIS SOFTWARE IS PROVIDED BY SUN AND ITS LICENSORS ``AS IS'' AND // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, // THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A // PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SUN OR ITS // LICENSORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF // USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED // AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN // ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE // POSSIBILITY OF SUCH DAMAGE. // Subsequent additions and modifications are Copyright (c) 2006 David // Carlton, and may be used subject to the same conditions. #include #include // The implementation of the parts of UnitTest.h that depend on // templates. This file should only be included by UnitTest.h; users // shouldn't use the material in here. namespace UnitTest { namespace Private { extern Radix radix; std::string demangledName(const std::type_info &typeinfo); class BasicAssertionFailure : public AssertionFailure { public: BasicAssertionFailure(const char *filename, int line, const char *function); void printMe(std::ostream &stream, const std::string &testName) const; private: const char *const filename_; const int line_; const char *const function_; }; template class EqualityAssertionFailure : public BasicAssertionFailure { public: EqualityAssertionFailure(const S &expected, const T &actual, const char *filename, int line, const char *function); void printMe(std::ostream &stream, const std::string &testName) const; private: const S expected_; const T actual_; }; template class TestHolderBase : public Test { public: TestHolderBase() : test_(0) {} void setUp() { test_ = construct(); } void run() { test_->run(); } void tearDown() { T *test = test_; test_ = 0; delete test; } std::string name() const { return demangledName(typeid(T)); } protected: virtual T *construct() = 0; const T *test() const { return test_; } private: // NOTE (2005-05-24, carlton): We can't use std::auto_ptr here, // because that can cause destructors to be called twice if ~T // throws an exception and the TestHolder object gets destroyed. T *test_; }; template class TestHolder : public TestHolderBase { public: TestHolder(A a, B b, C c, D d) : a_(a), b_(b), c_(c), d_(d) {} protected: T *construct() { return new T(a_, b_, c_, d_); } private: A a_; B b_; C c_; D d_; }; template class TestHolder : public TestHolderBase { public: TestHolder(A a, B b, C c) : a_(a), b_(b), c_(c) {} protected: T *construct() { return new T(a_, b_, c_); } private: A a_; B b_; C c_; }; template class TestHolder : public TestHolderBase { public: TestHolder(A a, B b) : a_(a), b_(b) {} protected: T *construct() { return new T(a_, b_); } private: A a_; B b_; }; template class TestHolder : public TestHolderBase { public: TestHolder(A a) : a_(a) {} protected: T *construct() { return new T(a_); } private: A a_; }; template class TestHolder : public TestHolderBase { protected: T *construct() { return new T(); } }; template class SuiteHolder : public TestHolder { public: SuiteHolder() : passes_(0), failures_(0) {} void tearDown() { passes_ = test()->passes(); failures_ = test()->failures(); TestHolder::tearDown(); } int passes() const { return passes_; } int failures() const { return failures_; } protected: using TestHolder::test; private: int passes_; int failures_; }; } template void assertEquals(const S &expected, const T &actual, const char *filename, int line, const char *function) { if (expected != actual) throw Private::EqualityAssertionFailure (expected, actual, filename, line, function); } template Private::EqualityAssertionFailure::EqualityAssertionFailure (const S &expected, const T &actual, const char *filename, int line, const char *function) : BasicAssertionFailure(filename, line, function), expected_(expected), actual_(actual) { } template void Private::EqualityAssertionFailure::printMe (std::ostream &stream, const std::string &testName) const { BasicAssertionFailure::printMe(stream, testName); std::ostringstream oss; if (radix == HEX) oss << std::hex << std::showbase; oss << "Expected " << expected_ << ", got " << actual_ << "."; stream << oss.str() << std::endl; } template TestPtr createSuite() { return TestPtr(new Private::SuiteHolder()); } template TestPtr createNonSuite() { return TestPtr(new Private::TestHolder()); } template TestPtr createNonSuite(A a) { return TestPtr(new Private::TestHolder(a)); } template TestPtr createNonSuite(A a, B b) { return TestPtr(new Private::TestHolder(a, b)); } template TestPtr createNonSuite(A a, B b, C c) { return TestPtr(new Private::TestHolder(a, b, c)); } template TestPtr createNonSuite(A a, B b, C c, D d) { return TestPtr(new Private::TestHolder(a, b, c, d)); } }