#include "pch.h"
#include "CppUnitTest.h"
#include <Cache.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 elements");
				else if (i.getKey() == 1)
					Assert::IsTrue(i.getValue() == 10, L"invalid value at key 1 in cache after adding elements");
				else if (i.getKey() == 2)
					Assert::IsTrue(i.getValue() == 1000, L"invalid value at key 2 in cache after adding 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 elements");
				else if (i.getKey() == 2)
					Assert::IsTrue(i.getValue() == 1000, L"invalid value at key 2 in cache after adding 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 elements");
				else if (i.getKey() == 2)
					Assert::IsTrue(i.getValue() == 1000, L"invalid value at key 2 in cache after adding elements");
				else
					Assert::Fail(L"invalid key in cache after adding elements");
				count++;
			}
			Assert::IsTrue(count == 2, L"unexpected count of elements in cache");
		}
	};
}
