//======================================================================
//-----------------------------------------------------------------------
/**
 * @file        iutest_switch_throw_value.hpp
 * @brief       IUTEST_*_THROW_VALUE アサーション切り替え ファイル
 *
 * @author      t.shirayanagi
 * @par         copyright
 * Copyright (C) 2012-2016, Takazumi Shirayanagi\n
 * This software is released under the new BSD License,
 * see LICENSE
*/
//-----------------------------------------------------------------------
//======================================================================
#ifndef INCG_IRIS_IUTEST_SWITCH_THROW_VALUE_HPP_5D6B75EE_F445_4730_8FEA_FB6249BCBD9C_
#define INCG_IRIS_IUTEST_SWITCH_THROW_VALUE_HPP_5D6B75EE_F445_4730_8FEA_FB6249BCBD9C_

#if !defined(IUTEST_USE_GTEST)

//======================================================================
// define

#else // !defined(IUTEST_USE_GTEST)

//======================================================================
// undef
#if defined(INCG_IRIS_IUTEST_HPP_)

#undef IUTEST_ASSERT_THROW_VALUE_EQ
#undef IUTEST_ASSERT_THROW_VALUE_NE
#undef IUTEST_ASSERT_THROW_VALUE_STREQ
#undef IUTEST_ASSERT_THROW_VALUE_STRCASEEQ

#undef IUTEST_EXPECT_THROW_VALUE_EQ
#undef IUTEST_EXPECT_THROW_VALUE_NE
#undef IUTEST_EXPECT_THROW_VALUE_STREQ
#undef IUTEST_EXPECT_THROW_VALUE_STRCASEEQ

#undef IUTEST_INFORM_THROW_VALUE_EQ
#undef IUTEST_INFORM_THROW_VALUE_NE
#undef IUTEST_INFORM_THROW_VALUE_STREQ
#undef IUTEST_INFORM_THROW_VALUE_STRCASEEQ

#undef IUTEST_ASSUME_THROW_VALUE_EQ
#undef IUTEST_ASSUME_THROW_VALUE_NE
#undef IUTEST_ASSUME_THROW_VALUE_STREQ
#undef IUTEST_ASSUME_THROW_VALUE_STRCASEEQ


#undef IUTEST_TEST_THROW_VALUE_
#undef IUTEST_TEST_THROW_VALUE_EQ_
#undef IUTEST_TEST_THROW_VALUE_NE_
#undef IUTEST_TEST_THROW_VALUE_STREQ_
#undef IUTEST_TEST_THROW_VALUE_STRCASEEQ_

#endif

//======================================================================
// define
#ifndef IUTEST_ASSERT_THROW_PRED_FORMAT2
#  define IUTEST_ASSERT_THROW_PRED_FORMAT2(pred_formatter, statement, expected_exception, expected_exception_value)     \
    IUTEST_THROW_PRED_FORMAT2_(pred_formatter, statement, expected_exception, expected_exception_value, IUTEST_ASSERT_FAILURE)
#endif

#ifndef IUTEST_EXPECT_THROW_PRED_FORMAT2
#  define IUTEST_EXPECT_THROW_PRED_FORMAT2(pred_formatter, statement, expected_exception, expected_exception_value)     \
    IUTEST_THROW_PRED_FORMAT2_(pred_formatter, statement, expected_exception, expected_exception_value, IUTEST_EXPECT_FAILURE)
#endif

#ifndef IUTEST_INFORM_THROW_PRED_FORMAT2
#  define IUTEST_INFORM_THROW_PRED_FORMAT2(pred_formatter, statement, expected_exception, expected_exception_value)     \
    IUTEST_THROW_PRED_FORMAT2_(pred_formatter, statement, expected_exception, expected_exception_value, IUTEST_INFORM_FAILURE)
#endif

#ifndef IUTEST_ASSUME_THROW_PRED_FORMAT2
#  define IUTEST_ASSUME_THROW_PRED_FORMAT2(pred_formatter, statement, expected_exception, expected_exception_value)     \
    IUTEST_THROW_PRED_FORMAT2_(pred_formatter, statement, expected_exception, expected_exception_value, IUTEST_INFORM_FAILURE)
#endif

// ASSERT
#define IUTEST_ASSERT_THROW_VALUE_EQ(statement, expected_exception, expected_value)         \
            IUTEST_TEST_THROW_VALUE_EQ_(statement, expected_exception, expected_value, IUTEST_ASSERT_FAILURE)
#define IUTEST_ASSERT_THROW_VALUE_NE(statement, expected_exception, expected_value)         \
            IUTEST_TEST_THROW_VALUE_NE_(statement, expected_exception, expected_value, IUTEST_ASSERT_FAILURE)
#define IUTEST_ASSERT_THROW_VALUE_STREQ(statement, expected_exception, expected_value)      \
            IUTEST_TEST_THROW_VALUE_STREQ_(statement, expected_exception, expected_value, IUTEST_ASSERT_FAILURE)
#define IUTEST_ASSERT_THROW_VALUE_STRCASEEQ(statement, expected_exception, expected_value)  \
            IUTEST_TEST_THROW_VALUE_STRCASEEQ_(statement, expected_exception, expected_value, IUTEST_ASSERT_FAILURE)

// EXPECT
#define IUTEST_EXPECT_THROW_VALUE_EQ(statement, expected_exception, expected_value)         \
            IUTEST_TEST_THROW_VALUE_EQ_(statement, expected_exception, expected_value, IUTEST_EXPECT_FAILURE)
#define IUTEST_EXPECT_THROW_VALUE_NE(statement, expected_exception, expected_value)         \
            IUTEST_TEST_THROW_VALUE_NE_(statement, expected_exception, expected_value, IUTEST_EXPECT_FAILURE)
#define IUTEST_EXPECT_THROW_VALUE_STREQ(statement, expected_exception, expected_value)      \
            IUTEST_TEST_THROW_VALUE_STREQ_(statement, expected_exception, expected_value, IUTEST_EXPECT_FAILURE)
#define IUTEST_EXPECT_THROW_VALUE_STRCASEEQ(statement, expected_exception, expected_value)  \
            IUTEST_TEST_THROW_VALUE_STRCASEEQ_(statement, expected_exception, expected_value, IUTEST_EXPECT_FAILURE)

// INFORM
#define IUTEST_INFORM_THROW_VALUE_EQ(statement, expected_exception, expected_value)         \
            IUTEST_TEST_THROW_VALUE_EQ_(statement, expected_exception, expected_value, IUTEST_INFORM_FAILURE)
#define IUTEST_INFORM_THROW_VALUE_NE(statement, expected_exception, expected_value)         \
            IUTEST_TEST_THROW_VALUE_NE_(statement, expected_exception, expected_value, IUTEST_INFORM_FAILURE)
#define IUTEST_INFORM_THROW_VALUE_STREQ(statement, expected_exception, expected_value)      \
            IUTEST_TEST_THROW_VALUE_STREQ_(statement, expected_exception, expected_value, IUTEST_INFORM_FAILURE)
#define IUTEST_INFORM_THROW_VALUE_STRCASEEQ(statement, expected_exception, expected_value)  \
            IUTEST_TEST_THROW_VALUE_STRCASEEQ_(statement, expected_exception, expected_value, IUTEST_INFORM_FAILURE)

// ASSUME
#define IUTEST_ASSUME_THROW_VALUE_EQ(statement, expected_exception, expected_value)         \
            IUTEST_TEST_THROW_VALUE_EQ_(statement, expected_exception, expected_value, IUTEST_ASSUME_FAILURE)
#define IUTEST_ASSUME_THROW_VALUE_NE(statement, expected_exception, expected_value)         \
            IUTEST_TEST_THROW_VALUE_NE_(statement, expected_exception, expected_value, IUTEST_ASSUME_FAILURE)
#define IUTEST_ASSUME_THROW_VALUE_STREQ(statement, expected_exception, expected_value)      \
            IUTEST_TEST_THROW_VALUE_STREQ_(statement, expected_exception, expected_value, IUTEST_ASSUME_FAILURE)
#define IUTEST_ASSUME_THROW_VALUE_STRCASEEQ(statement, expected_exception, expected_value)  \
            IUTEST_TEST_THROW_VALUE_STRCASEEQ_(statement, expected_exception, expected_value, IUTEST_ASSUME_FAILURE)


#define IUTEST_TEST_THROW_VALUE_(statement, expected_exception, expected_exception_value, on_failure, pred_formatter)   \
    IUTEST_AMBIGUOUS_ELSE_BLOCKER_                                                  \
    if( ::testing::AssertionResult ar = ::testing::AssertionSuccess() ) {           \
        try {                                                                       \
            IUTEST_SUPPRESS_UNREACHABLE_CODE_WARNING((void)(statement));            \
            ar << "\nExpected: " #statement " throws an exception of type "         \
                    #expected_exception ".\n  Actual: it throws nothing.";          \
            goto IUTEST_PP_CAT(iutest_label_throw_value, __LINE__);                 \
        } catch( expected_exception const& e) {                                     \
            if( ::testing::AssertionResult ar2 = pred_formatter("e", #expected_exception_value, e, expected_exception_value) ) {            \
            } else {                                                                \
                ar << "\nExpected: " #statement " throws an exception of value\n" << ar2.message(); \
                goto IUTEST_PP_CAT(iutest_label_throw_value, __LINE__);             \
            }                                                                       \
        } catch( ... ) {                                                            \
            ar << "\nExpected: " #statement " throws an exception of type "         \
                #expected_exception ".\n  Actual: it throws a different type.";     \
            goto IUTEST_PP_CAT(iutest_label_throw_value, __LINE__);                 \
        }                                                                           \
    } else                                                                          \
        IUTEST_PP_CAT(iutest_label_throw_value, __LINE__):                          \
        on_failure(ar.message())

#define IUTEST_TEST_THROW_VALUE_EQ_(statement, expected_exception, expected_exception_value, on_failure)    \
    IUTEST_TEST_THROW_VALUE_(statement, expected_exception, expected_exception_value, on_failure            \
        , ::testing::internal::EqHelper<GTEST_IS_NULL_LITERAL_(expected_exception_value)>::Compare)
#define IUTEST_TEST_THROW_VALUE_NE_(statement, expected_exception, expected_exception_value, on_failure)    \
    IUTEST_TEST_THROW_VALUE_(statement, expected_exception, expected_exception_value, on_failure            \
        , ::testing::internal::NeHelper<GTEST_IS_NULL_LITERAL_(expected_exception_value)>::Compare)
#define IUTEST_TEST_THROW_VALUE_STREQ_(statement, expected_exception, expected_exception_value, on_failure) \
    IUTEST_TEST_THROW_VALUE_(statement, expected_exception, expected_exception_value, on_failure            \
        , ::testing::internal::CmpHelperSTREQ)
#define IUTEST_TEST_THROW_VALUE_STRCASEEQ_(statement, expected_exception, expected_exception_value, on_failure) \
    IUTEST_TEST_THROW_VALUE_(statement, expected_exception, expected_exception_value, on_failure                \
        , ::testing::internal::CmpHelperSTRCASEEQ)

#endif // !defined(IUTEST_USE_GTEST)

// ASSERT
#define ASSERT_THROW_PRED_FORMAT2       IUTEST_ASSERT_THROW_PRED_FORMAT2
#define ASSERT_THROW_VALUE_EQ           IUTEST_ASSERT_THROW_VALUE_EQ
#define ASSERT_THROW_VALUE_NE           IUTEST_ASSERT_THROW_VALUE_NE
#define ASSERT_THROW_VALUE_STREQ        IUTEST_ASSERT_THROW_VALUE_STREQ
#define ASSERT_THROW_VALUE_STRCASEEQ    IUTEST_ASSERT_THROW_VALUE_STRCASEEQ

// EXPECT
#define EXPECT_THROW_PRED_FORMAT2       IUTEST_EXPECT_THROW_PRED_FORMAT2
#define EXPECT_THROW_VALUE_EQ           IUTEST_EXPECT_THROW_VALUE_EQ
#define EXPECT_THROW_VALUE_NE           IUTEST_EXPECT_THROW_VALUE_NE
#define EXPECT_THROW_VALUE_STREQ        IUTEST_EXPECT_THROW_VALUE_STREQ
#define EXPECT_THROW_VALUE_STRCASEEQ    IUTEST_EXPECT_THROW_VALUE_STRCASEEQ

// INFORM
#define INFORM_THROW_PRED_FORMAT2       IUTEST_INFORM_THROW_PRED_FORMAT2
#define INFORM_THROW_VALUE_EQ           IUTEST_INFORM_THROW_VALUE_EQ
#define INFORM_THROW_VALUE_NE           IUTEST_INFORM_THROW_VALUE_NE
#define INFORM_THROW_VALUE_STREQ        IUTEST_INFORM_THROW_VALUE_STREQ
#define INFORM_THROW_VALUE_STRCASEEQ    IUTEST_INFORM_THROW_VALUE_STRCASEEQ

// ASSUME
#define ASSUME_THROW_PRED_FORMAT2       IUTEST_ASSUME_THROW_PRED_FORMAT2
#define ASSUME_THROW_VALUE_EQ           IUTEST_ASSUME_THROW_VALUE_EQ
#define ASSUME_THROW_VALUE_NE           IUTEST_ASSUME_THROW_VALUE_NE
#define ASSUME_THROW_VALUE_STREQ        IUTEST_ASSUME_THROW_VALUE_STREQ
#define ASSUME_THROW_VALUE_STRCASEEQ    IUTEST_ASSUME_THROW_VALUE_STRCASEEQ

#endif // INCG_IRIS_IUTEST_SWITCH_THROW_VALUE_HPP_5D6B75EE_F445_4730_8FEA_FB6249BCBD9C_
