#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" );
        }
    };
}