//======================================================================
//-----------------------------------------------------------------------
/**
 * @file        matcher.cpp
 * @brief       matcher test sample
 *
 * @author      t.shirayanagi
 * @par         copyright
 * Copyright (C) 2014-2016, Takazumi Shirayanagi\n
 * This software is released under the new BSD License,
 * see LICENSE
*/
//-----------------------------------------------------------------------
//======================================================================
#include "../include/iutest.hpp"

#if IUTEST_HAS_MATCHERS
#include <map>

using namespace ::iutest::matchers;

namespace {
    struct X { int a, b; X(int _a, int _b) : a(_a), b(_b) {} int GetA() const { return a; } };
    int X2(int v) { return v * 2; }
    float f0 = 0.0f;
    double d0 = 0.0;
}

IUTEST(Matcher, Gernal)
{
    IUTEST_EXPECT_THAT(1, Eq(1));
    IUTEST_EXPECT_THAT(0, Ne(1));
    IUTEST_EXPECT_THAT(0, Le(1));
    IUTEST_EXPECT_THAT(0, Lt(1));
    IUTEST_EXPECT_THAT(1, Ge(0));
    IUTEST_EXPECT_THAT(0, Ge(0));
    IUTEST_EXPECT_THAT(1, Gt(0));
}

IUTEST(Matcher, Null)
{
    int* p1 = NULL;
    int** p2 = &p1;
    IUTEST_EXPECT_THAT(p1, IsNull());
    IUTEST_EXPECT_THAT(p2, NotNull());
    IUTEST_EXPECT_THAT(p2, Pointee(IsNull()));
}

IUTEST(Matcher, FloatingPoint)
{
    IUTEST_EXPECT_THAT(f0, FloatEq(0.0f));
    IUTEST_EXPECT_THAT(d0, DoubleEq(0.0));
    IUTEST_EXPECT_THAT(f0, NanSensitiveFloatEq(0.0f));
    IUTEST_EXPECT_THAT(0.0f / f0, NanSensitiveFloatEq(0.0f / f0));
    IUTEST_EXPECT_THAT(d0, NanSensitiveDoubleEq(0.0));
    IUTEST_EXPECT_THAT(0.0 / d0, NanSensitiveDoubleEq(0.0 / d0));
}

IUTEST(Matcher, String)
{
    IUTEST_EXPECT_THAT("hoge", StrEq("hoge"));
    IUTEST_EXPECT_THAT("hoga", StrNe("hoge"));
    IUTEST_EXPECT_THAT("hoge", StrCaseEq("Hoge"));
    IUTEST_EXPECT_THAT("hoga", StrCaseNe("hoge"));

    IUTEST_EXPECT_THAT("hoge", StartsWith("ho"));
    IUTEST_EXPECT_THAT("hoge", HasSubstr("og"));
    IUTEST_EXPECT_THAT("hoge", EndsWith("ge"));
}

IUTEST(Matcher, Container)
{
    int a[2][3] ={ { 1, 2, 3 }, { 4, 5, 6 } };
    int b[3] ={ 1, 2, 3 };
    IUTEST_EXPECT_THAT(b, Contains(Gt(2)));
    IUTEST_EXPECT_THAT(b, Each(Le(10)));
    IUTEST_EXPECT_THAT(a, Each(Each(Le(10))));
}

IUTEST(Matcher, Member)
{
    X x(0, 1);
    std::map<int, X> m;
    for( int i=0; i < 10; ++i )
    {
        m.insert(::std::pair<int, X>(i, X(i, 100)));
    }
    IUTEST_EXPECT_THAT(m, Each(Key(Le(10))));
    IUTEST_EXPECT_THAT(m, Each(Pair(Le(10), Field(&X::b, Ge(0)))));
    IUTEST_EXPECT_THAT(x, Property(&X::GetA, 0));
    IUTEST_EXPECT_THAT(&x, Property(&X::GetA, 0));
}

IUTEST(Matcher, Function)
{
    IUTEST_EXPECT_THAT(1, ResultOf(X2, 2));
}

IUTEST(Matcher, Not)
{
    IUTEST_EXPECT_THAT(1, Not(2));
}

IUTEST(Matcher, Wildcard)
{
    IUTEST_EXPECT_THAT(42, _);
    IUTEST_EXPECT_THAT(42, A<int>());
}

IUTEST(Matcher, ElementsAreArray)
{
    int a[3] ={ 0, 1, 3 };
    int b[3] ={ 0, 1, 3 };
    IUTEST_EXPECT_THAT(a, ElementsAreArray(b));
}

#if IUTEST_HAS_MATCHER_ELEMENTSARE

IUTEST(Matcher, ElementsAre)
{
    int a[3] ={ 0, -1, 3 };
    IUTEST_EXPECT_THAT(a, ElementsAre(Ge(0), _, Gt(0)));
}

#endif

#if IUTEST_HAS_MATCHER_ALLOF_AND_ANYOF

IUTEST(Matcher, AllOf)
{
    int a[3] ={ 0, 1, 3 };
    IUTEST_EXPECT_THAT("hoge", AllOf(StartsWith("ho"), EndsWith("ge")));
    IUTEST_EXPECT_THAT(a, Each(AllOf(Ge(0), Le(10))));
}

IUTEST(Matcher, AnyOf)
{
    int a[3] ={ 0, -1, 10 };
    IUTEST_EXPECT_THAT("hoge", AnyOf(StartsWith("Ho"), EndsWith("ge")));
    IUTEST_EXPECT_THAT(a, Each(AnyOf(Le(0), Ge(10))));
}

#endif

#endif
