PageRenderTime 64ms CodeModel.GetById 33ms app.highlight 25ms RepoModel.GetById 1ms app.codeStats 0ms

/Src/Dependencies/Boost/libs/unordered/test/helpers/exception_test.hpp

http://hadesmem.googlecode.com/
C++ Header | 236 lines | 194 code | 38 blank | 4 comment | 5 complexity | 514963d46c9eaef1009f627f2201b484 MD5 | raw file
  1
  2// Copyright 2006-2009 Daniel James.
  3// Distributed under the Boost Software License, Version 1.0. (See accompanying
  4// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  5
  6#if !defined(BOOST_UNORDERED_EXCEPTION_TEST_HEADER)
  7#define BOOST_UNORDERED_EXCEPTION_TEST_HEADER
  8
  9#include "./test.hpp"
 10
 11#include <boost/preprocessor/seq/for_each_product.hpp>
 12#include <boost/preprocessor/seq/elem.hpp>
 13#include <boost/preprocessor/cat.hpp>
 14
 15#   define UNORDERED_EXCEPTION_TEST_CASE(name, test_func, type)             \
 16        UNORDERED_AUTO_TEST(name)                                           \
 17        {                                                                   \
 18            test_func< type > fixture;                                      \
 19            ::test::lightweight::exception_safety(                          \
 20                fixture, BOOST_STRINGIZE(test_func<type>));                 \
 21        }                                                                   \
 22
 23#    define UNORDERED_EPOINT_IMPL ::test::lightweight::epoint
 24
 25#define UNORDERED_EXCEPTION_TEST_POSTFIX RUN_TESTS()
 26
 27#define RUN_EXCEPTION_TESTS(test_seq, param_seq)                            \
 28    BOOST_PP_SEQ_FOR_EACH_PRODUCT(RUN_EXCEPTION_TESTS_OP,                   \
 29        (test_seq)(param_seq))                                              \
 30    RUN_TESTS()                                                             \
 31
 32#define RUN_EXCEPTION_TESTS_OP(r, product)                                  \
 33    UNORDERED_EXCEPTION_TEST_CASE(                                          \
 34        BOOST_PP_CAT(BOOST_PP_SEQ_ELEM(0, product),                         \
 35            BOOST_PP_CAT(_, BOOST_PP_SEQ_ELEM(1, product))                  \
 36        ),                                                                  \
 37        BOOST_PP_SEQ_ELEM(0, product),                                      \
 38        BOOST_PP_SEQ_ELEM(1, product)                                       \
 39    )                                                                       \
 40
 41#define UNORDERED_SCOPE(scope_name)                                         \
 42    for(::test::scope_guard unordered_test_guard(                           \
 43            BOOST_STRINGIZE(scope_name));                                   \
 44        !unordered_test_guard.dismissed();                                  \
 45        unordered_test_guard.dismiss())                                     \
 46
 47#define UNORDERED_EPOINT(name)                                              \
 48    if(::test::exceptions_enabled) {                                        \
 49        UNORDERED_EPOINT_IMPL(name);                                        \
 50    }                                                                       \
 51
 52#define ENABLE_EXCEPTIONS                                                   \
 53    ::test::exceptions_enable BOOST_PP_CAT(                                 \
 54        ENABLE_EXCEPTIONS_, __LINE__)(true)                                 \
 55
 56#define DISABLE_EXCEPTIONS                                                  \
 57    ::test::exceptions_enable BOOST_PP_CAT(                                 \
 58        ENABLE_EXCEPTIONS_, __LINE__)(false)                                \
 59
 60namespace test {
 61    static char const* scope = "";
 62    bool exceptions_enabled = false;
 63
 64    class scope_guard {
 65        scope_guard& operator=(scope_guard const&);
 66        scope_guard(scope_guard const&);
 67
 68        char const* old_scope_;
 69        char const* scope_;
 70        bool dismissed_;
 71    public:
 72        scope_guard(char const* name)
 73            : old_scope_(scope),
 74            scope_(name),
 75            dismissed_(false)
 76        {
 77            scope = scope_;
 78        }
 79
 80        ~scope_guard() {
 81            if(dismissed_) scope = old_scope_;
 82        }
 83
 84        void dismiss() {
 85            dismissed_ = true;
 86        }
 87
 88        bool dismissed() const {
 89            return dismissed_;
 90        }
 91    };
 92
 93    class exceptions_enable
 94    {
 95        exceptions_enable& operator=(exceptions_enable const&);
 96        exceptions_enable(exceptions_enable const&);
 97
 98        bool old_value_;
 99    public:
100        exceptions_enable(bool enable)
101            : old_value_(exceptions_enabled)
102        {
103            exceptions_enabled = enable;
104        }
105
106        ~exceptions_enable()
107        {
108            exceptions_enabled = old_value_;
109        }
110    };
111
112    struct exception_base {
113        struct data_type {};
114        struct strong_type {
115            template <class T> void store(T const&) {}
116            template <class T> void test(T const&) const {}
117        };
118        data_type init() const { return data_type(); }
119        void check BOOST_PREVENT_MACRO_SUBSTITUTION() const {}
120    };
121
122    template <class T, class P1, class P2, class T2>
123    inline void call_ignore_extra_parameters(
124            void (T::*fn)() const, T2 const& obj,
125            P1&, P2&)
126    {
127        (obj.*fn)();
128    }
129
130    template <class T, class P1, class P2, class T2>
131    inline void call_ignore_extra_parameters(
132            void (T::*fn)(P1&) const, T2 const& obj,
133            P1& p1, P2&)
134    {
135        (obj.*fn)(p1);
136    }
137
138    template <class T, class P1, class P2, class T2>
139    inline void call_ignore_extra_parameters(
140            void (T::*fn)(P1&, P2&) const, T2 const& obj,
141            P1& p1, P2& p2)
142    {
143        (obj.*fn)(p1, p2);
144    }
145
146    template <class T>
147    T const& constant(T const& x) {
148        return x;
149    }
150
151    template <class Test>
152    class test_runner
153    {
154        Test const& test_;
155
156        test_runner(test_runner const&);
157        test_runner& operator=(test_runner const&);
158    public:
159        test_runner(Test const& t) : test_(t) {}
160        void operator()() const {
161            DISABLE_EXCEPTIONS;
162            test::scope = "";
163            BOOST_DEDUCED_TYPENAME Test::data_type x(test_.init());
164            BOOST_DEDUCED_TYPENAME Test::strong_type strong;
165            strong.store(x);
166            try {
167                ENABLE_EXCEPTIONS;
168                call_ignore_extra_parameters<
169                    Test,
170                    BOOST_DEDUCED_TYPENAME Test::data_type,
171                    BOOST_DEDUCED_TYPENAME Test::strong_type
172                >(&Test::run, test_, x, strong);
173            }
174            catch(...) {
175                call_ignore_extra_parameters<
176                    Test,
177                    BOOST_DEDUCED_TYPENAME Test::data_type const,
178                    BOOST_DEDUCED_TYPENAME Test::strong_type const
179                >(&Test::check, test_, constant(x), constant(strong));
180                throw;
181            }
182        }
183    };
184
185    // Quick exception testing based on lightweight test
186
187    namespace lightweight {
188        static int iteration;
189        static int count;
190
191        struct test_exception {
192            char const* name;
193            test_exception(char const* n) : name(n) {}
194        };
195
196        struct test_failure {
197        };
198
199        void epoint(char const* name) {
200            ++count;
201            if(count == iteration) {
202                throw test_exception(name);
203            }
204        }
205
206        template <class Test>
207        void exception_safety(Test const& f, char const* /*name*/) {
208            test_runner<Test> runner(f);
209
210            iteration = 0;
211            bool success = false;
212            do {
213                ++iteration;
214                count = 0;
215
216                try {
217                    runner();
218                    success = true;
219                }
220                catch(test_failure) {
221                    BOOST_ERROR("test_failure caught.");
222                    break;
223                }
224                catch(test_exception) {
225                    continue;
226                }
227                catch(...) {
228                    BOOST_ERROR("Unexpected exception.");
229                    break;
230                }
231            } while(!success);
232        }
233    }
234}
235
236#endif