#include "pch.h"

#include <Cache.h>

#include "CppUnitTest.h"

using namespace Microsoft::VisualStudio::CppUnitTestFramework;

namespace FrameworkTests
{
    TEST_CLASS (CacheTests)
    {
    public:
        TEST_METHOD (EmtptyTest)
        {
            Framework::Cache<int, int> cache(
                100,
                [](int i) { return i; },
                Framework::CacheCleanupStrategy::RANDOM);
            Assert::IsTrue(cache.getCurrentSize() == 0,
                L"getCurrentSize() on empty cache should be 0");
            Assert::IsTrue(
                cache.getMaxSize() == 100, L"getMaxSize() on empty cache");
        }

        TEST_METHOD (PutTest)
        {
            Framework::Cache<int, int> cache(
                2,
                [](int i) { return i; },
                Framework::CacheCleanupStrategy::RANDOM);
            cache.put(0, 100);
            cache.put(1, 10);
            cache.put(2, 1000);
            Assert::IsTrue(cache.getCurrentSize() == 2,
                L"unexpected count of elements in cache");
            Assert::IsTrue(cache.has(0) ? cache.get(0) == 100 : 1,
                L"invalid value at key 0 in cache after adding elements");
            Assert::IsTrue(cache.has(1) ? cache.get(1) == 10 : 1,
                L"invalid value at key 1 in cache after adding elements");
            Assert::IsTrue(cache.get(2) == 1000,
                L"invalid value at key 2 in cache after adding elements");
            int count = 0;
            for (Framework::MapEntry<int, int> i : cache)
            {
                if (i.getKey() == 0)
                    Assert::IsTrue(i.getValue() == 100,
                        L"invalid value at key 0 in cache after adding "
                        L"elements");
                else if (i.getKey() == 1)
                    Assert::IsTrue(i.getValue() == 10,
                        L"invalid value at key 1 in cache after adding "
                        L"elements");
                else if (i.getKey() == 2)
                    Assert::IsTrue(i.getValue() == 1000,
                        L"invalid value at key 2 in cache after adding "
                        L"elements");
                else
                    Assert::Fail(L"invalid key in cache after adding elements");
                count++;
            }
            Assert::IsTrue(
                count == 2, L"unexpected count of elements in cache");
        }

        TEST_METHOD (OldestTest)
        {
            Framework::Cache<int, int> cache(
                2,
                [](int i) { return i; },
                Framework::CacheCleanupStrategy::OLDEST);
            cache.put(0, 100);
            Sleep(1000);
            cache.put(1, 10);
            Sleep(1000);
            cache.put(2, 1000);
            Assert::IsTrue(cache.getCurrentSize() == 2,
                L"unexpected count of elements in cache");
            Assert::IsFalse(cache.has(0),
                L"invalid value at key 0 in cache after adding elements");
            Assert::IsTrue(cache.has(1) && cache.get(1) == 10,
                L"invalid value at key 1 in cache after adding elements");
            Assert::IsTrue(cache.get(2) == 1000,
                L"invalid value at key 2 in cache after adding elements");
            int count = 0;
            for (Framework::MapEntry<int, int> i : cache)
            {
                if (i.getKey() == 1)
                    Assert::IsTrue(i.getValue() == 10,
                        L"invalid value at key 1 in cache after adding "
                        L"elements");
                else if (i.getKey() == 2)
                    Assert::IsTrue(i.getValue() == 1000,
                        L"invalid value at key 2 in cache after adding "
                        L"elements");
                else
                    Assert::Fail(L"invalid key in cache after adding elements");
                count++;
            }
            Assert::IsTrue(
                count == 2, L"unexpected count of elements in cache");
        }

        TEST_METHOD (LongestNotUsedTest)
        {
            Framework::Cache<int, int> cache(
                2,
                [](int i) { return i; },
                Framework::CacheCleanupStrategy::LONGEST_NOT_USED);
            cache.put(0, 100);
            Sleep(1000);
            cache.put(1, 10);
            Sleep(1000);
            cache.get(0);
            cache.put(2, 1000);
            Assert::IsTrue(cache.getCurrentSize() == 2,
                L"unexpected count of elements in cache");
            Assert::IsTrue(cache.has(0) && cache.get(0) == 100,
                L"invalid value at key 0 in cache after adding elements");
            Assert::IsFalse(cache.has(1),
                L"invalid value at key 1 in cache after adding elements");
            Assert::IsTrue(cache.get(2) == 1000,
                L"invalid value at key 2 in cache after adding elements");
            int count = 0;
            for (Framework::MapEntry<int, int> i : cache)
            {
                if (i.getKey() == 0)
                    Assert::IsTrue(i.getValue() == 100,
                        L"invalid value at key 0 in cache after adding "
                        L"elements");
                else if (i.getKey() == 2)
                    Assert::IsTrue(i.getValue() == 1000,
                        L"invalid value at key 2 in cache after adding "
                        L"elements");
                else
                    Assert::Fail(L"invalid key in cache after adding elements");
                count++;
            }
            Assert::IsTrue(
                count == 2, L"unexpected count of elements in cache");
        }
    };
} // namespace FrameworkTests