//======================================================================
//-----------------------------------------------------------------------
/**
 * @file        combine_tests.cpp
 * @brief       Combine 対応テスト
 *
 * @author      t.shirayanagi
 * @par         copyright
 * Copyright (C) 2012-2016, Takazumi Shirayanagi\n
 * This software is released under the new BSD License,
 * see LICENSE
*/
//-----------------------------------------------------------------------
//======================================================================

//======================================================================
// include
#include "iutest.hpp"

#if IUTEST_HAS_PARAM_TEST && IUTEST_HAS_COMBINE

static const int tble[] = {0, 1};

class CombineTest : public ::iutest::TestWithParam< ::iutest::tuples::tuple<bool, int, int> >
{
public:
    typedef ::iutest::tuples::tuple<bool, int, int> Tuple;
    static const int TABLE_SIZE = sizeof(tble)/sizeof(tble[0]);

    static int index;
    static Tuple list[2*2*TABLE_SIZE];

public:
    static void SetUpTestCase(void) { index = 0; }
};

int CombineTest::index = 0;
CombineTest::Tuple CombineTest::list[2*2*CombineTest::TABLE_SIZE] = {
    CombineTest::Tuple(false, 1, 0)
    , CombineTest::Tuple(false, 1, 1)
    , CombineTest::Tuple(false, 10, 0)
    , CombineTest::Tuple(false, 10, 1)
    , CombineTest::Tuple(true, 1, 0)
    , CombineTest::Tuple(true, 1, 1)
    , CombineTest::Tuple(true, 10, 0)
    , CombineTest::Tuple(true, 10, 1)
};

IUTEST_P(CombineTest, Num)
{
    IUTEST_EXPECT_EQ( (2*2*TABLE_SIZE) * 2, ::iutest::UnitTest::GetInstance()->current_test_case()->total_test_count() );
}

IUTEST_P(CombineTest, Param)
{
    IUTEST_EXPECT_EQ( list[index++], GetParam() );
}

IUTEST_INSTANTIATE_TEST_CASE_P(A, CombineTest
    , ::iutest::Combine(::iutest::Bool(), ::iutest::Values(1, 10), ::iutest::ValuesIn(tble)));
#if IUTEST_HAS_CONCAT
IUTEST_INSTANTIATE_TEST_CASE_P(B, CombineTest
    , ::iutest::Concat(
        ::iutest::Combine(::iutest::Values(false), ::iutest::Values(1, 10), ::iutest::ValuesIn(tble))
        , ::iutest::Combine(::iutest::Values(true), ::iutest::Values(1, 10), ::iutest::ValuesIn(tble))
    )
    );
IUTEST_INSTANTIATE_TEST_CASE_P(C, CombineTest
    , ::iutest::Combine(::iutest::Values(false), ::iutest::Values(1, 10), ::iutest::ValuesIn(tble))
        + ::iutest::Combine(::iutest::Values(true), ::iutest::Values(1, 10), ::iutest::ValuesIn(tble))
    );
#endif


class CombineInTest : public ::iutest::TestWithParam< ::iutest::tuples::tuple< ::iutest::tuples::tuple<bool, int>, int > >
{
};

IUTEST_P(CombineInTest, A)
{
}

IUTEST_INSTANTIATE_TEST_CASE_P(A, CombineInTest
    , ::iutest::Combine( ::iutest::Combine(::iutest::Bool(), ::iutest::Values(1, 10)), ::iutest::ValuesIn(tble)) );
IUTEST_INSTANTIATE_TEST_CASE_P(B, CombineInTest
    , ::iutest::Combine( ::iutest::Values( ::iutest::tuples::tuple<bool, int>(false, 1), ::iutest::tuples::tuple<bool, int>(true, 10) )
        , ::iutest::ValuesIn(tble)) );


#if IUTEST_HAS_VARIADIC_COMBINE

namespace variadic_combine_test
{

typedef ::iutest::tuples::tuple<int, int, int, int, int, int, int, int, int, int> VariadicCombineTestTuple;

static const int TUPLE_SIZE = ::iutest::tuples::tuple_size< VariadicCombineTestTuple >::value;
static const int test_table[] = { 0, 1 };
static const int TABLE_SIZE = sizeof(test_table)/sizeof(test_table[0]);

class VariadicCombineTest : public ::iutest::TestWithParam< VariadicCombineTestTuple >
{
    static int power(int n, int c) { return c == 0 ? 1 : power(n, c-1) * n; }
public:
    static int num;
    static int count;

    static VariadicCombineTestTuple count_to_tuple(int c)
    {
        return ::iutest::tuples::make_tuple(
            (c>>(TUPLE_SIZE-1))&1
            , (c>>(TUPLE_SIZE-2))&1
            , (c>>(TUPLE_SIZE-3))&1
            , (c>>(TUPLE_SIZE-4))&1
            , (c>>(TUPLE_SIZE-5))&1
            , (c>>(TUPLE_SIZE-6))&1
            , (c>>(TUPLE_SIZE-7))&1
            , (c>>(TUPLE_SIZE-8))&1
            , (c>>(TUPLE_SIZE-9))&1
            , (c>>(TUPLE_SIZE-10))&1
        );
    }
};
int VariadicCombineTest::num = power(TABLE_SIZE, TUPLE_SIZE);
int VariadicCombineTest::count = 0;

IUTEST_P(VariadicCombineTest, Num)
{
    IUTEST_EXPECT_EQ( num, ::iutest::UnitTest::GetInstance()->current_test_case()->total_test_count() );
    IUTEST_EXPECT_EQ( count_to_tuple(count++), GetParam() );
}

IUTEST_INSTANTIATE_TEST_CASE_P(A, VariadicCombineTest
    , ::iutest::Combine(::iutest::ValuesIn(test_table)
        , ::iutest::ValuesIn(test_table)
        , ::iutest::ValuesIn(test_table)
        , ::iutest::ValuesIn(test_table)
        , ::iutest::ValuesIn(test_table)
        , ::iutest::ValuesIn(test_table)
        , ::iutest::ValuesIn(test_table)
        , ::iutest::ValuesIn(test_table)
        , ::iutest::ValuesIn(test_table)
        , ::iutest::ValuesIn(test_table)
    ));

}   // end of namespace variadic_combine_test

#endif

#endif

