⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tut.hpp

📁 VC源码,开源测试工具.有助于VC++的学习与开发
💻 HPP
📖 第 1 页 / 共 2 页
字号:
private:    std::string current_test_name_;};namespace{/** * Tests provided condition. * Throws if false. */void ensure(bool cond){    if (!cond)    {        // TODO: default ctor?        throw failure("");    }}/** * Tests provided condition. * Throws if true. */void ensure_not(bool cond){    ensure(!cond);}/** * Tests provided condition. * Throws if false. */template <typename T>void ensure(const T msg, bool cond){    if (!cond)    {        throw failure(msg);    }}/** * Tests provided condition. * Throws if true. */template <typename T>void ensure_not(const T msg, bool cond){    ensure(msg, !cond);}/** * Tests two objects for being equal. * Throws if false. * * NB: both T and Q must have operator << defined somewhere, or * client code will not compile at all! */template <class T, class Q>void ensure_equals(const char* msg, const Q& actual, const T& expected){    if (expected != actual)    {        std::stringstream ss;        ss << (msg ? msg : "")             << (msg ? ":" : "")             << " expected '"             << expected             << "' actual '"             << actual            << '\'';        throw failure(ss.str().c_str());    }}template <class T, class Q>void ensure_equals(const Q& actual, const T& expected){    ensure_equals<>(0, actual, expected);}/** * Tests two objects for being at most in given distance one from another. * Borders are excluded. * Throws if false. * * NB: T must have operator << defined somewhere, or * client code will not compile at all! Also, T shall have * operators + and -, and be comparable. */template <class T>void ensure_distance(const char* msg, const T& actual, const T& expected,    const T& distance){    if (expected-distance >= actual || expected+distance <= actual)    {        std::stringstream ss;        ss << (msg ? msg : "")             << (msg? ":" : "")             << " expected ("             << expected-distance             << " - "            << expected+distance             << ") actual '"             << actual            << '\'';        throw failure(ss.str().c_str());    }}template <class T>void ensure_distance(const T& actual, const T& expected, const T& distance){    ensure_distance<>(0, actual, expected, distance);}/** * Unconditionally fails with message. */void fail(const char* msg = ""){    throw failure(msg);}} // end of namespace/** * Walks through test tree and stores address of each * test method in group. Instantiation stops at 0. */template <class Test, class Group, int n>struct tests_registerer{    static void reg(Group& group)    {        group.reg(n, &Test::template test<n>);        tests_registerer<Test, Group, n - 1>::reg(group);    }};template <class Test, class Group>struct tests_registerer<Test, Group, 0>{    static void reg(Group&)    {    }};/** * Test group; used to recreate test object instance for * each new test since we have to have reinitialized  * Data base class. */template <class Data, int MaxTestsInGroup = 50>class test_group : public group_base{    const char* name_;    typedef void (test_object<Data>::*testmethod)();    typedef std::map<int, testmethod> tests;    typedef typename tests::iterator tests_iterator;    typedef typename tests::const_iterator tests_const_iterator;    typedef typename tests::const_reverse_iterator    tests_const_reverse_iterator;    typedef typename tests::size_type size_type;    tests tests_;    tests_iterator current_test_;    /**     * Exception-in-destructor-safe smart-pointer class.     */    template <class T>    class safe_holder    {        T* p_;        bool permit_throw_in_dtor;        safe_holder(const safe_holder&);        safe_holder& operator=(const safe_holder&);    public:        safe_holder()             : p_(0),              permit_throw_in_dtor(false)        {        }        ~safe_holder()        {            release();        }        T* operator->() const        {            return p_;        }                T* get() const        {            return p_;        }        /**         * Tell ptr it can throw from destructor. Right way is to         * use std::uncaught_exception(), but some compilers lack         * correct implementation of the function.         */        void permit_throw()        {            permit_throw_in_dtor = true;        }        /**         * Specially treats exceptions in test object destructor;          * if test itself failed, exceptions in destructor         * are ignored; if test was successful and destructor failed,         * warning exception throwed.         */        void release()        {            try            {                if (delete_obj() == false)                {                    throw warning("destructor of test object raised"                        " an SEH exception");                }            }            catch (const std::exception& ex)            {                if (permit_throw_in_dtor)                {                    std::string msg = "destructor of test object raised"                        " exception: ";                    msg += ex.what();                    throw warning(msg);                }            }            catch( ... )            {                if (permit_throw_in_dtor)                {                    throw warning("destructor of test object raised an"                        " exception");                }            }        }        /**         * Re-init holder to get brand new object.         */        void reset()        {            release();            permit_throw_in_dtor = false;            p_ = new T();        }        bool delete_obj()        {#if defined(TUT_USE_SEH)            __try            {#endif                T* p = p_;                p_ = 0;                delete p;#if defined(TUT_USE_SEH)            }            __except(handle_seh_(::GetExceptionCode()))            {                if (permit_throw_in_dtor)                {                    return false;                }            }#endif            return true;        }    };public:    typedef test_object<Data> object;    /**     * Creates and registers test group with specified name.     */    test_group(const char* name)        : name_(name)    {        // register itself        runner.get().register_group(name_,this);        // register all tests        tests_registerer<object, test_group, MaxTestsInGroup>::reg(*this);    }    /**     * This constructor is used in self-test run only.     */    test_group(const char* name, test_runner& another_runner)        : name_(name)    {        // register itself        another_runner.register_group(name_, this);        // register all tests        tests_registerer<test_object<Data>, test_group,             MaxTestsInGroup>::reg(*this);    };    /**     * Registers test method under given number.     */    void reg(int n, testmethod tm)    {        tests_[n] = tm;    }    /**     * Reset test position before first test.     */    void rewind()    {        current_test_ = tests_.begin();    }    /**     * Runs next test.     */    test_result run_next()    {        if (current_test_ == tests_.end())        {            throw no_more_tests();        }        // find next user-specialized test        safe_holder<object> obj;        while (current_test_ != tests_.end())        {            try            {                return run_test_(current_test_++, obj);            }            catch (const no_such_test&)            {                continue;            }        }        throw no_more_tests();    }    /**     * Runs one test by position.     */    test_result run_test(int n)    {        // beyond tests is special case to discover upper limit        if (tests_.rbegin() == tests_.rend())        {            throw beyond_last_test();        }                if (tests_.rbegin()->first < n)        {            throw beyond_last_test();        }        // withing scope; check if given test exists        tests_iterator ti = tests_.find(n);        if (ti == tests_.end())        {            throw no_such_test();        }        safe_holder<object> obj;        return run_test_(ti, obj);    }private:    /**     * VC allows only one exception handling type per function,     * so I have to split the method.     *      * TODO: refactoring needed!     */    test_result run_test_(const tests_iterator& ti, safe_holder<object>& obj)    {        std::string current_test_name;        try        {            if (run_test_seh_(ti->second,obj, current_test_name) == false)            {                throw seh("seh");            }        }        catch (const no_such_test&)        {            throw;        }        catch (const warning& ex)        {            // test ok, but destructor failed            if (obj.get())            {                current_test_name = obj->get_test_name();            }            test_result tr(name_,ti->first, current_test_name,                 test_result::warn, ex);            return tr;        }        catch (const failure& ex)        {            // test failed because of ensure() or similar method            if (obj.get())            {                current_test_name = obj->get_test_name();            }            test_result tr(name_,ti->first, current_test_name,                 test_result::fail, ex);            return tr;        }        catch (const seh& ex)        {            // test failed with sigsegv, divide by zero, etc            if (obj.get())            {                current_test_name = obj->get_test_name();            }            test_result tr(name_, ti->first, current_test_name,                 test_result::term, ex);            return tr;        }        catch (const bad_ctor& ex)        {            // test failed because test ctor failed; stop the whole group            if (obj.get())            {                current_test_name = obj->get_test_name();            }            test_result tr(name_, ti->first, current_test_name,                 test_result::ex_ctor, ex);            return tr;        }        catch (const std::exception& ex)        {            // test failed with std::exception            if (obj.get())            {                current_test_name = obj->get_test_name();            }            test_result tr(name_, ti->first, current_test_name,                 test_result::ex, ex);            return tr;        }        catch (...)        {            // test failed with unknown exception            if (obj.get())            {                current_test_name = obj->get_test_name();            }            test_result tr(name_, ti->first, current_test_name,                 test_result::ex);            return tr;        }        // test passed        test_result tr(name_,ti->first, current_test_name, test_result::ok);        return tr;    }    /**     * Runs one under SEH if platform supports it.     */    bool run_test_seh_(testmethod tm, safe_holder<object>& obj,         std::string& current_test_name)    {#if defined(TUT_USE_SEH)        __try        {#endif        if (obj.get() == 0)        {            reset_holder_(obj);        }                    obj->called_method_was_a_dummy_test_ = false;#if defined(TUT_USE_SEH)            __try            {#endif                (obj.get()->*tm)();#if defined(TUT_USE_SEH)            }            __except(handle_seh_(::GetExceptionCode()))            {                // throw seh("SEH");                current_test_name = obj->get_test_name();                return false;            }#endif        if (obj->called_method_was_a_dummy_test_)        {            // do not call obj.release(); reuse object            throw no_such_test();        }        current_test_name = obj->get_test_name();        obj.permit_throw();        obj.release();#if defined(TUT_USE_SEH)        }        __except(handle_seh_(::GetExceptionCode()))        {            return false;        }#endif        return true;    }    void reset_holder_(safe_holder<object>& obj)    {        try        {            obj.reset();        }        catch (const std::exception& ex)        {            throw bad_ctor(ex.what());        }        catch (...)        {            throw bad_ctor("test constructor has generated an exception;"                " group execution is terminated");        }    }};#if defined(TUT_USE_SEH)/** * Decides should we execute handler or ignore SE. */inline int handle_seh_(DWORD excode){    switch(excode)    {    case EXCEPTION_ACCESS_VIOLATION:    case EXCEPTION_DATATYPE_MISALIGNMENT:    case EXCEPTION_BREAKPOINT:    case EXCEPTION_SINGLE_STEP:    case EXCEPTION_ARRAY_BOUNDS_EXCEEDED:    case EXCEPTION_FLT_DENORMAL_OPERAND:    case EXCEPTION_FLT_DIVIDE_BY_ZERO:    case EXCEPTION_FLT_INEXACT_RESULT:    case EXCEPTION_FLT_INVALID_OPERATION:    case EXCEPTION_FLT_OVERFLOW:    case EXCEPTION_FLT_STACK_CHECK:    case EXCEPTION_FLT_UNDERFLOW:    case EXCEPTION_INT_DIVIDE_BY_ZERO:    case EXCEPTION_INT_OVERFLOW:    case EXCEPTION_PRIV_INSTRUCTION:    case EXCEPTION_IN_PAGE_ERROR:    case EXCEPTION_ILLEGAL_INSTRUCTION:    case EXCEPTION_NONCONTINUABLE_EXCEPTION:    case EXCEPTION_STACK_OVERFLOW:    case EXCEPTION_INVALID_DISPOSITION:    case EXCEPTION_GUARD_PAGE:    case EXCEPTION_INVALID_HANDLE:        return EXCEPTION_EXECUTE_HANDLER;    };    return EXCEPTION_CONTINUE_SEARCH;}#endif}#endif

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -