// iutest_mfc_sample.cpp : コンソール アプリケーションのエントリ ポイントを定義します。
//

#include "stdafx.h"
#include "iutest_mfc_sample.h"
#include "iutest.hpp"
#include <map>

#ifdef _DEBUG
#define new DEBUG_NEW
#endif


// 唯一のアプリケーション オブジェクトです。

CWinApp theApp;

using namespace std;

int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
{
	IUTEST_UNUSED_VAR(envp);
	int nRetCode = 0;

	HMODULE hModule = ::GetModuleHandle(NULL);

	if (hModule != NULL)
	{
		// MFC を初期化して、エラーの場合は結果を印刷します。
		if (!AfxWinInit(hModule, NULL, ::GetCommandLine(), 0))
		{
			// TODO: 必要に応じてエラー コードを変更してください。
			_tprintf(_T("致命的なエラー: MFC の初期化ができませんでした。\n"));
			nRetCode = 1;
		}
		else
		{
			// TODO: アプリケーションの動作を記述するコードをここに挿入してください。
			IUTEST_INIT(&argc, argv);
			nRetCode = IUTEST_RUN_ALL_TESTS();
		}
	}
	else
	{
		// TODO: 必要に応じてエラー コードを変更してください。
		_tprintf(_T("致命的なエラー: GetModuleHandle が失敗しました\n"));
		nRetCode = 1;
	}

	return nRetCode;
}

IUTEST(MFC, String)
{
	CString str = _T("Test");
	IUTEST_ASSERT_EQ(_T("Test"), str);
	IUTEST_ASSERT_STREQ(_T("Test"), str);
	IUTEST_ASSERT_STREQ(str, str);

	IUTEST_ASSERT_STRIN(str, _T("Test"));
}

IUTEST(MFC, Rect)
{
	CRect r = { 0, 0, 100, 100 };
	IUTEST_ASSERT_EQ(r, r);
}

template<typename T>
struct test_value
{
	static T get(int index) { return static_cast<T>(index); }
};
template<typename T>
struct test_value< T* >
{
	static T* get(int) { return NULL; }
};
template<>
struct test_value < CString >
{
	static CString get(int index) { CString s; s.Format(_T("%d"), index); return s; }
};

template<typename T>
class MFCArrayTypedTest : public ::iutest::Test {};
IUTEST_TYPED_TEST_CASE(MFCArrayTypedTest, ::iutest::Types<CArray<int>, CTypedPtrArray<CPtrArray, int*>
	, CByteArray, CWordArray, CDWordArray, CUIntArray, CStringArray, CPtrArray, CObArray>);

IUTEST_TYPED_TEST(MFCArrayTypedTest, EqCollections)
{
	typename iutest::mfc::CContainer<TypeParam>::BASE_TYPE a[10];
	TypeParam ar;
	ar.SetSize(IUTEST_PP_COUNTOF(a));
	for(int i = 0; i < IUTEST_PP_COUNTOF(a); ++i)
	{
		a[i] = test_value<iutest::mfc::CContainer<TypeParam>::BASE_TYPE>::get(i);
		ar[i] = test_value<iutest::mfc::CContainer<TypeParam>::BASE_TYPE>::get(i);
	}
	IUTEST_ASSERT_EQ_COLLECTIONS(
		  ::iutest::mfc::begin(ar)
		, ::iutest::mfc::end(ar)
		, ::std::begin(a)
		, ::std::end(a)
		);
}

template<typename T>
class MFCListTypedTest : public ::iutest::Test {};
IUTEST_TYPED_TEST_CASE(MFCListTypedTest, ::iutest::Types<CList<int>, CTypedPtrList<CPtrList, int*>
	, CStringList, CPtrList, CObList>);

IUTEST_TYPED_TEST(MFCListTypedTest, EqCollections)
{
	typename iutest::mfc::CContainer<TypeParam>::BASE_TYPE a[10];
	TypeParam list;
	for(int i = 0; i < IUTEST_PP_COUNTOF(a); ++i)
	{
		a[i] = test_value<iutest::mfc::CContainer<TypeParam>::BASE_TYPE>::get(i);
		list.AddTail(test_value<iutest::mfc::CContainer<TypeParam>::BASE_TYPE>::get(i));
	}
	IUTEST_ASSERT_EQ_COLLECTIONS(
		  ::iutest::mfc::begin(list)
		, ::iutest::mfc::end(list)
		, ::std::begin(a)
		, ::std::end(a)
		);
}

template<typename T>
class MFCMapTypedTest : public ::iutest::Test {};
IUTEST_TYPED_TEST_CASE(MFCMapTypedTest, ::iutest::Types< CMap<int, int, int, int>
	, CTypedPtrMap<CMapPtrToPtr, int*, int*>, CTypedPtrMap<CMapPtrToWord, int*, WORD>
	, CTypedPtrMap<CMapWordToPtr, WORD, int*>, CTypedPtrMap<CMapStringToPtr, CString, int*>
	, CMapWordToPtr, CMapWordToOb, CMapPtrToPtr, CMapPtrToWord
	, CMapStringToPtr, CMapStringToOb, CMapStringToString >);

IUTEST_TYPED_TEST(MFCMapTypedTest, EqCollections)
{
	TypeParam map;
	for(int i = 0; i < 10; ++i)
	{
		map.SetAt(test_value<iutest::mfc::CContainer<TypeParam>::BASE_KEY>::get(i)
			, test_value<iutest::mfc::CContainer<TypeParam>::BASE_VALUE>::get(i) );
	}
	IUTEST_ASSERT_EQ_COLLECTIONS(
		  ::iutest::mfc::begin(map)
		, ::iutest::mfc::end(map)
		, ::iutest::mfc::begin(map)
		, ::iutest::mfc::end(map)
		);
}


#if IUTEST_HAS_MATCHERS

using namespace ::iutest::matchers;

IUTEST_TYPED_TEST(MFCArrayTypedTest, Matcher)
{
	TypeParam ar;
	ar.SetSize(10);
	for(int i = 0; i < 10; ++i)
	{
		ar[i] = test_value<iutest::mfc::CContainer<TypeParam>::BASE_TYPE>::get(i);
	}
	IUTEST_EXPECT_THAT(::iutest::mfc::make_container(ar), Each(_));
}

IUTEST_TYPED_TEST(MFCListTypedTest, Matcher)
{
	TypeParam list;
	for(int i = 0; i < 10; ++i)
	{
		list.AddTail(test_value<iutest::mfc::CContainer<TypeParam>::BASE_TYPE>::get(i));
	}
	IUTEST_EXPECT_THAT(::iutest::mfc::make_container(list), Each(_));
}

IUTEST_TYPED_TEST(MFCMapTypedTest, Matcher)
{
	TypeParam map;
	for(int i = 0; i < 10; ++i) {
		map.SetAt(test_value<iutest::mfc::CContainer<TypeParam>::BASE_KEY>::get(i)
			, test_value<iutest::mfc::CContainer<TypeParam>::BASE_VALUE>::get(i));
	}
	IUTEST_EXPECT_THAT(::iutest::mfc::make_container(map), Each(Key(_)));
	IUTEST_EXPECT_THAT(::iutest::mfc::make_container(map), Each(Pair(_, _)));
}

#endif

