/**
 * @file RegistryKeyTest.h
 * @author Bartosz Janiak
 * 
 * @brief
 *
 * Copyright © 2009 NVIDIA Corporation. All rights reserved.
 *
 * NVIDIA Corporation and its licensors retain all intellectual property and proprietary
 * rights in and to this software, related documentation and any modifications thereto. Any
 * use, reproduction, disclosure or distribution of this software and related documentation
 * without express license agreement from NVIDIA Corporation is strictly prohibited.
 */

#pragma once
#include "MockWinApi.h"
#include "cxxtest/TestSuite.h"
#include "TestObjects.h"
#include <Logging.h>
#include <boost/assign/std/set.hpp>

namespace Nvidia {
namespace Logging {
namespace Test {

using namespace boost::assign; // bring 'operator+=()' into scope

class RegistryKeyTest : public CxxTest::TestSuite
{
/*
    [HKEY_LOCAL_MACHINE\Software\NVIDIA Corporation\TestRegistryKey]
    "StringValue"="abcDEF"
    "StringValue2"="foobarFOOBARfoobar"
    "DwordValue"=dword:0F008AF0
    "DwordValue2"=dword:F0F00F0F
    "BinaryValue"=hex:
    "OneByteStringValue"="P"

    [HKEY_LOCAL_MACHINE\Software\NVIDIA Corporation\TestRegistryKey\SubKeyShort]

    [HKEY_LOCAL_MACHINE\Software\NVIDIA Corporation\TestRegistryKey\SubKeyLoooooooooooooooooooooooooooooooooong]

    [HKEY_LOCAL_MACHINE\Software\NVIDIA Corporation\TestRegistryKey\SubKeyShort2]
*/

private:
    RegistryKey* key;

public:
    void setUp()
    {
        key = new RegistryKey(RegistryKey(HKEY_LOCAL_MACHINE).GetSubKey(_T("Software"))
            .GetSubKey(_T("NVIDIA Corporation")).GetSubKey(_T("TestRegistryKey")));
    }

    void tearDown()
    {
        delete key;
    }

    void TestOriginalKey()
    {
        RunAllTests(*key, _T("OriginalKey"));
    }

    void TestKeyCopy()
    {
        RegistryKey key2(*key);
        RunAllTests(key2, _T("Copied key"));
    }

    void TestKeyAssignment()
    {
        RegistryKey key2(HKEY_LOCAL_MACHINE);
        key2 = *key;
        RunAllTests(key2, _T("Assigned key"));
    }

    void RunAllTests(RegistryKey& key, const std::tstring& message)
    {
        GetValueNamesTest(key, message);
        GetSubKeyNamesTest(key, message);
        GetDWORDValueTest(key, message);
        GetStringValueTest(key, message);
        GetSubKeyTest(key, message);
        ErrorsTest(key, message);
    }

    void GetValueNamesTest(RegistryKey& key, const std::tstring& message)
    {
        std::set<std::tstring> expectedResult;
        expectedResult += _T("BinaryValue"), _T("StringValue"), _T("StringValue2"), _T("DwordValue"), _T("DwordValue2"), _T("OneByteStringValue");
        TSM_ASSERT_EQUALS(message, key.GetValueNames(), expectedResult);
    }

    void GetSubKeyNamesTest(RegistryKey& key, const std::tstring& message)
    {
        std::set<std::tstring> expectedResult;
        expectedResult += _T("SubKeyShort"), _T("SubKeyLoooooooooooooooooooooooooooooooooong"), _T("SubKeyShort2");
        TSM_ASSERT_EQUALS(message, key.GetSubKeyNames(), expectedResult);    
    }

    void GetDWORDValueTest(RegistryKey& key, const std::tstring& message)
    {
        TSM_ASSERT_EQUALS(message, key.GetDWORDValue(_T("DwordValue")), 0x0F008AF0);
        TSM_ASSERT_EQUALS(message, key.GetDWORDValue(std::tstring(_T("DwordValue2"))), 0xF0F00F0F);
    }

    void GetStringValueTest(RegistryKey& key, const std::tstring& message)
    {
        TSM_ASSERT_EQUALS(message, key.GetStringValue(_T("StringValue")), std::tstring(_T("abcDEF")));
    }

    void GetSubKeyTest(RegistryKey& key, const std::tstring& message)
    {
        TSM_ASSERT_THROWS_NOTHING(message, key.GetSubKey(_T("SubKeyShort")));
        TSM_ASSERT_THROWS_NOTHING(message, key.GetSubKey(std::tstring(_T("SubKeyShort2"))));
    }

    void ErrorsTest(RegistryKey& key, const std::tstring& message)
    {
        TSM_ASSERT_THROWS(message, key.GetDWORDValue(_T("NoSuchValue")), RegistryException)
        TSM_ASSERT_THROWS(message, key.GetDWORDValue(_T("StringValue")), RegistryException);
        TSM_ASSERT_THROWS(message, key.GetDWORDValue(_T("OneByteStringValue")), RegistryException);

        TSM_ASSERT_THROWS(message, key.GetStringValue(_T("NoSuchValue")), RegistryException);
        TSM_ASSERT_THROWS(message, key.GetStringValue(_T("DwordValue")), RegistryException);

        TSM_ASSERT_THROWS(message, key.GetSubKey(_T("NoSuchKey")), RegistryException);
        TSM_ASSERT_THROWS(message, RegistryKey(HKEY_LOCAL_MACHINE, _T("NoSuchKey")), RegistryException);
    }
};

}
}
}

using namespace Nvidia::Logging::Test;
