Initial commit

This commit is contained in:
alexpete
2021-03-05 11:26:34 -08:00
commit a10351f38d
27091 changed files with 5521199 additions and 0 deletions
@@ -0,0 +1,115 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#include "CrySystem_precompiled.h"
#include <AzTest/AzTest.h>
#include <AzCore/UnitTest/UnitTest.h>
#include <AzCore/UnitTest/TestTypes.h>
#include <AzCore/Memory/AllocatorScope.h>
#include <AzCore/std/string/string.h>
#include <BootProfiler.h>
#if defined(ENABLE_LOADING_PROFILER)
namespace UnitTests
{
using BootProfilerTestAllocatorScope = AZ::AllocatorScope<AZ::LegacyAllocator, CryStringAllocator>;
class BootProfilerTest :
public ::testing::Test,
BootProfilerTestAllocatorScope,
UnitTest::TraceBusRedirector
{
public:
BootProfilerTest()
{
BootProfilerTestAllocatorScope::ActivateAllocators();
UnitTest::TraceBusRedirector::BusConnect();
}
~BootProfilerTest()
{
UnitTest::TraceBusRedirector::BusDisconnect();
BootProfilerTestAllocatorScope::DeactivateAllocators();
}
void SetUp() override
{
}
void TearDown() override
{
}
};
TEST_F(BootProfilerTest, BootProfilerTest_StartStopBlocksInThreads_Success)
{
CBootProfiler testProfiler;
const char scopeName[] = "TestScope";
const char blockArg[] = "TestArg";
const int numAttempts = 1000;
const int numThreads = 10;
auto switchSessionFunc = [&]() {
for (int sessionNum = 0; sessionNum < numAttempts; ++sessionNum)
{
auto sessionName = AZStd::string::format("TestSession%d", sessionNum);
testProfiler.StartSession(sessionName.c_str());
testProfiler.StopSession(sessionName.c_str());
}
};
auto testProfileFunc = [&]() {
for (int blockNum = 0; blockNum < numAttempts; ++blockNum)
{
auto someBlock = testProfiler.StartBlock(scopeName, blockArg);
testProfiler.StopBlock(someBlock);
}
};
AZStd::thread threadArray[numThreads];
AZStd::thread sessionThread = AZStd::thread(switchSessionFunc);
for (int i = 0; i < numThreads; ++i)
{
threadArray[i] = AZStd::thread(testProfileFunc);
}
for (int i = 0; i < numThreads; ++i)
{
threadArray[i].join();
}
sessionThread.join();
}
class FrameTestBootProfiler : public CBootProfiler
{
public:
FrameTestBootProfiler(int frameCount) : CBootProfiler()
{
SetFrameCount(frameCount);
}
};
TEST_F(BootProfilerTest, BootProfilerTest_FrameStartStop_Success)
{
const int numTestFrames = 10;
FrameTestBootProfiler testProfiler(numTestFrames);
for (int i = 0; i < numTestFrames; ++i)
{
testProfiler.StartFrame("TestFrame");
testProfiler.StopFrame();
}
}
} // namespace UnitTests
#endif
@@ -0,0 +1,187 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#include "CrySystem_precompiled.h"
#include <AzTest/AzTest.h>
#include <Log.h>
#include <Mocks/ISystemMock.h>
#include <Mocks/IRemoteConsoleMock.h>
#include <AzCore/IO/SystemFile.h> // for max path decl
#include <AzCore/Math/Random.h>
#include <AzCore/Memory/AllocatorScope.h>
#include <AzCore/UnitTest/UnitTest.h>
#include <AzCore/UnitTest/Mocks/MockFileIOBase.h>
namespace CLogUnitTests
{
using ::testing::NiceMock;
using ::testing::_;
using ::testing::Return;
// for fuzzing test, how much work to do? Not much, as this must be fast.
const int NumTrialsToPerform = 16000;
class CLogUnitTests
: public ::testing::Test
{
public:
using CryPrimitivesAllocatorScope = AZ::AllocatorScope<AZ::LegacyAllocator, CryStringAllocator>;
void SetUp() override
{
m_primitiveAllocators.ActivateAllocators();
m_priorEnv = gEnv;
m_priorFileIO = AZ::IO::FileIOBase::GetInstance();
m_priorDirectFileIO = AZ::IO::FileIOBase::GetDirectInstance();
m_data = AZStd::make_unique<DataMembers>();
m_data->m_stubEnv.pSystem = &m_data->m_system;
gEnv = &m_data->m_stubEnv;
// for FileIO, you must set the instance to null before changing it.
// this is a way to tell the singleton system that you mean to replace a singleton and its
// not a mistake.
AZ::IO::FileIOBase::SetInstance(nullptr);
AZ::IO::FileIOBase::SetInstance(&m_data->m_fileIOMock);
AZ::IO::FileIOBase::SetDirectInstance(nullptr);
AZ::IO::FileIOBase::SetDirectInstance(&m_data->m_fileIOMock);
ON_CALL(m_data->m_system, GetIRemoteConsole())
.WillByDefault(
Return(&m_data->m_remoteConsoleMock));
AZ::IO::MockFileIOBase::InstallDefaultReturns(m_data->m_fileIOMock);
}
void TearDown() override
{
AZ::IO::FileIOBase::SetInstance(nullptr);
AZ::IO::FileIOBase::SetInstance(m_priorFileIO);
AZ::IO::FileIOBase::SetDirectInstance(nullptr);
AZ::IO::FileIOBase::SetDirectInstance(m_priorDirectFileIO);
m_data.reset();
// restore state.
gEnv = m_priorEnv;
m_primitiveAllocators.DeactivateAllocators();
}
struct DataMembers
{
SSystemGlobalEnvironment m_stubEnv;
NiceMock<SystemMock> m_system;
NiceMock<AZ::IO::MockFileIOBase> m_fileIOMock;
NiceMock<IRemoteConsoleMock> m_remoteConsoleMock;
};
AZStd::unique_ptr<DataMembers> m_data;
SSystemGlobalEnvironment* m_priorEnv = nullptr;
ISystem* m_priorSystem = nullptr;
AZ::IO::FileIOBase* m_priorFileIO = nullptr;
AZ::IO::FileIOBase* m_priorDirectFileIO = nullptr;
CryPrimitivesAllocatorScope m_primitiveAllocators;
};
TEST_F(CLogUnitTests, LogAlways_InvalidString_Asserts)
{
AZ_TEST_START_TRACE_SUPPRESSION;
CLog testLog(&m_data->m_system);
testLog.LogAlways(nullptr);
AZ_TEST_STOP_TRACE_SUPPRESSION(1);
}
TEST_F(CLogUnitTests, LogAlways_EmptyString_IgnoresWithoutCrashing)
{
CLog testLog(&m_data->m_system);
testLog.LogAlways("");
}
TEST_F(CLogUnitTests, LogAlways_NormalString_NoFileName_DoesNotCrash)
{
CLog testLog(&m_data->m_system);
testLog.LogAlways("test");
}
TEST_F(CLogUnitTests, LogAlways_SetFileName_Empty_DoesNotCrash)
{
CLog testLog(&m_data->m_system);
testLog.SetFileName("", false);
testLog.LogAlways("test");
}
#if AZ_TRAIT_DISABLE_LOG_ALWAYS_FUZZ_TEST
TEST_F(CLogUnitTests, DISABLED_LogAlways_FuzzTest)
#else
TEST_F(CLogUnitTests, LogAlways_FuzzTest)
#endif // AZ_TRAIT_DISABLE_LOG_ALWAYS_FUZZ_TEST
{
CLog testLog(&m_data->m_system);
AZStd::string randomJunkName;
randomJunkName.resize(128, '\0');
// expect the mock to repeatedly get called. If we fail this expectation
// it means the code is early-outing somewhere and we are not getting coverage.
EXPECT_CALL(m_data->m_fileIOMock, Write(_, _, _, _))
.WillRepeatedly(
Return(AZ::IO::Result(AZ::IO::ResultCode::Success)));
// don't rely on randomness in unit tests, they need to be repeatable.
// the following random generator is not seeded by the time, but by a constant (default 1234).
AZ::SimpleLcgRandom randGen;
for (int trialNumber = 0; trialNumber < NumTrialsToPerform; ++trialNumber)
{
for (int randomChar = 0; randomChar < randomJunkName.size(); ++randomChar)
{
// note that this is intentionally allowing null characters to generate.
// note that this also puts characters AFTER the null, if a null appears in the mddle.
// so that if there are off by one errors they could include cruft afterwards.
if (randomChar > trialNumber % randomJunkName.size())
{
// choose this point for the nulls to begin. It makes sure we test every size of string.
randomJunkName[randomChar] = 0;
}
else
{
randomJunkName[randomChar] = (char)(randGen.GetRandom() % 256); // this will trigger invalid UTF8 decoding too
}
}
testLog.LogAlways("%s", randomJunkName.c_str());
}
}
TEST_F(CLogUnitTests, LogAlways_SetFileName_Correct_DoesNotCrash_WritesToFile)
{
CLog testLog(&m_data->m_system);
testLog.SetFileName("logfile.log", false);
// EXPECT a call to the file system - if we dont get a call here, it means something went wrong.
// it also expects exactly one call to write. One call to log should be one call to write,
// or else performance will suffer.
EXPECT_CALL(m_data->m_fileIOMock, Write(_, _, _, _))
.WillOnce(
Return(AZ::IO::Result(AZ::IO::ResultCode::Success)));
testLog.LogAlways("test");
}
} // end namespace CLogUnitTests
@@ -0,0 +1,282 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#include "CrySystem_precompiled.h"
#include <AzTest/AzTest.h>
#include <XConsole.h>
#include <AzCore/UnitTest/UnitTest.h>
#include <AzCore/Memory/AllocatorScope.h>
#include <AzCore/Debug/TraceMessageBus.h>
#include <AzCore/std/functional.h>
#include <Mocks/ISystemMock.h>
namespace UnitTests
{
class RemoteConsoleMock
: public IRemoteConsole
{
public:
MOCK_METHOD0(RegisterConsoleVariables, void());
MOCK_METHOD0(UnregisterConsoleVariables, void());
MOCK_METHOD0(Start, void());
MOCK_METHOD0(Stop, void());
MOCK_CONST_METHOD0(IsStarted, bool());
MOCK_METHOD1(AddLogMessage, void(const char*));
MOCK_METHOD1(AddLogWarning, void(const char*));
MOCK_METHOD1(AddLogError, void(const char*));
MOCK_METHOD0(Update, void());
MOCK_METHOD2(RegisterListener, void(IRemoteConsoleListener*, const char*));
MOCK_METHOD1(UnregisterListener, void(IRemoteConsoleListener*));
};
struct TestTraceMessageCapture
: public AZ::Debug::TraceMessageBus::Handler
{
using Callback = AZStd::function<void(const char* window, const char* message)>;
Callback m_callback;
TestTraceMessageCapture()
{
AZ::Debug::TraceMessageBus::Handler::BusConnect();
}
~TestTraceMessageCapture()
{
AZ::Debug::TraceMessageBus::Handler::BusDisconnect();
}
bool OnError(const char* window, const char* message) override
{
if (m_callback)
{
m_callback(window, message);
}
return false;
}
bool OnWarning(const char* window, const char* message) override
{
if (m_callback)
{
m_callback(window, message);
}
return false;
}
};
using SystemAllocatorScope = AZ::AllocatorScope<AZ::LegacyAllocator, CryStringAllocator>;
struct CommandRegistrationUnitTests
: public ::testing::Test
, public SystemAllocatorScope
{
CommandRegistrationUnitTests()
{
EXPECT_CALL(m_system, GetIRemoteConsole())
.WillRepeatedly(::testing::Return(&m_remoteConsole));
}
void SetUp() override
{
SystemAllocatorScope::ActivateAllocators();
memset(&m_stubEnv, 0, sizeof(SSystemGlobalEnvironment));
m_stubEnv.pSystem = &m_system;
m_priorEnv = gEnv;
gEnv = &m_stubEnv;
// now it safe to set up the console
m_console = AZStd::make_unique<CXConsole>();
m_stubEnv.pConsole = m_console.get();
EXPECT_CALL(m_system, GetIConsole())
.WillRepeatedly(::testing::Return(m_stubEnv.pConsole));
}
void TearDown() override
{
m_console.reset();
gEnv = m_priorEnv;
SystemAllocatorScope::DeactivateAllocators();
}
::testing::NiceMock<SystemMock> m_system;
::testing::NiceMock<RemoteConsoleMock> m_remoteConsole;
AZStd::unique_ptr<CXConsole> m_console;
SSystemGlobalEnvironment m_stubEnv;
SSystemGlobalEnvironment* m_priorEnv = nullptr;
};
TEST_F(CommandRegistrationUnitTests, RegisterUnregisterTest)
{
using namespace AzFramework;
{
bool result = false;
CommandRegistrationBus::BroadcastResult(result, &CommandRegistrationBus::Events::RegisterCommand, "foo", "", 0, [](const AZStd::vector<AZStd::string_view>&) -> CommandResult
{
return CommandResult::Success;
});
EXPECT_TRUE(result);
}
{
bool result = false;
CommandRegistrationBus::BroadcastResult(result, &CommandRegistrationBus::Events::UnregisterCommand, "foo");
EXPECT_TRUE(result);
}
}
TEST_F(CommandRegistrationUnitTests, RegisterUnregisterNegativeTest)
{
using namespace AzFramework;
// register too many times
{
auto fnFoo = [](const AZStd::vector<AZStd::string_view>&) -> CommandResult
{
return CommandResult::Success;
};
bool result = false;
CommandRegistrationBus::BroadcastResult(result, &CommandRegistrationBus::Events::RegisterCommand, "foo", "", 0, fnFoo);
EXPECT_TRUE(result);
CommandRegistrationBus::BroadcastResult(result, &CommandRegistrationBus::Events::RegisterCommand, "foo", "", 0, fnFoo);
EXPECT_FALSE(result);
}
// unregister too many times
{
bool result = false;
CommandRegistrationBus::BroadcastResult(result, &CommandRegistrationBus::Events::UnregisterCommand, "foo");
EXPECT_TRUE(result);
CommandRegistrationBus::BroadcastResult(result, &CommandRegistrationBus::Events::UnregisterCommand, "foo");
EXPECT_FALSE(result);
}
// a null callback should fail
{
AZ_TEST_START_TRACE_SUPPRESSION;
bool result = false;
CommandRegistrationBus::BroadcastResult(result, &CommandRegistrationBus::Events::RegisterCommand, "shouldfail", "", 0, nullptr);
EXPECT_FALSE(result);
AZ_TEST_STOP_TRACE_SUPPRESSION(1);
}
// a null identifier should fail
{
AZ_TEST_START_TRACE_SUPPRESSION;
bool result = false;
CommandRegistrationBus::BroadcastResult(result, &CommandRegistrationBus::Events::RegisterCommand, "", "", 0, nullptr);
EXPECT_FALSE(result);
AZ_TEST_STOP_TRACE_SUPPRESSION(1);
}
}
TEST_F(CommandRegistrationUnitTests, DoCallback)
{
using namespace AzFramework;
int count = 0;
{
auto fnCommand = [&count](const AZStd::vector<AZStd::string_view>&) -> CommandResult
{
++count;
return CommandResult::Success;
};
bool result = false;
CommandRegistrationBus::BroadcastResult(result, &CommandRegistrationBus::Events::RegisterCommand, "bar", "bar docs", CommandFlags::Development, fnCommand);
EXPECT_TRUE(result);
}
const bool bSilentMode = true;
const bool bDeferExecution = false;
m_console->ExecuteString("bar", bSilentMode, bDeferExecution);
EXPECT_EQ(1, count);
{
bool result = false;
CommandRegistrationBus::BroadcastResult(result, &CommandRegistrationBus::Events::UnregisterCommand, "bar");
EXPECT_TRUE(result);
}
}
TEST_F(CommandRegistrationUnitTests, DoCallbackNegativeTests)
{
using namespace AzFramework;
bool result = false;
CommandRegistrationBus::BroadcastResult(result, &CommandRegistrationBus::Events::RegisterCommand, "bar", "", 0, [](const AZStd::vector<AZStd::string_view>& args)
{
if (args.size() > 1)
{
return CommandResult::ErrorWrongNumberOfArguments;
}
return CommandResult::Error;
});
EXPECT_TRUE(result);
const bool bSilentMode = true;
const bool bDeferExecution = false;
// general error
{
int found = 0;
TestTraceMessageCapture capture;
capture.m_callback = [&found](const char* window, const char* message)
{
if (azstrnicmp(window, "console", AZ_ARRAY_SIZE("console") - 1) == 0)
{
if (azstrnicmp(message, "Command returned a generic error\n", AZ_ARRAY_SIZE("Command returned a generic error\n") - 1) == 0)
{
++found;
}
}
};
m_console->ExecuteString("bar", bSilentMode, bDeferExecution);
EXPECT_EQ(1, found);
}
// too many args
{
int found = 0;
TestTraceMessageCapture capture;
capture.m_callback = [&found](const char* window, const char* message)
{
if (azstrnicmp(window, "console", AZ_ARRAY_SIZE("console") - 1) == 0)
{
if (azstrnicmp(message, "Command does not have the right number of arguments (send = 4)\n", AZ_ARRAY_SIZE("Command does not have the right number of arguments (send = 4)\n") - 1) == 0)
{
++found;
}
}
};
m_console->ExecuteString("bar 1 2 3", bSilentMode, bDeferExecution);
EXPECT_EQ(1, found);
}
// clean up
{
result = false;
CommandRegistrationBus::BroadcastResult(result, &CommandRegistrationBus::Events::UnregisterCommand, "bar");
EXPECT_TRUE(result);
}
}
} // namespace UnitTests
@@ -0,0 +1,481 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#include "CrySystem_precompiled.h"
#include <AzTest/AzTest.h>
#include <AzCore/Memory/AllocatorScope.h>
#include <CryCommon/stl/STLAlignedAlloc.h>
TEST(StringTests, CUT_Strings)
{
bool bOk;
char bf[4];
// cry_strcpy()
bOk = cry_strcpy(0, 0, 0);
EXPECT_TRUE(!bOk);
bOk = cry_strcpy(0, 0, 0, 0);
EXPECT_TRUE(!bOk);
bOk = cry_strcpy(0, 1, 0);
EXPECT_TRUE(!bOk);
bOk = cry_strcpy(0, 1, 0, 1);
EXPECT_TRUE(!bOk);
bOk = cry_strcpy(0, 1, "");
EXPECT_TRUE(!bOk);
bOk = cry_strcpy(0, 1, "", 1);
EXPECT_TRUE(!bOk);
memcpy(bf, "abcd", 4);
bOk = cry_strcpy(bf, 0, "");
EXPECT_TRUE(!bOk && !memcmp(bf, "abcd", 4));
memcpy(bf, "abcd", 4);
bOk = cry_strcpy(bf, 0, "", 1);
EXPECT_TRUE(!bOk && !memcmp(bf, "abcd", 4));
memcpy(bf, "abcd", 4);
bOk = cry_strcpy(bf, 1, 0);
EXPECT_TRUE(!bOk && !memcmp(bf, "\000bcd", 4));
memcpy(bf, "abcd", 4);
bOk = cry_strcpy(bf, 1, 0, 0);
EXPECT_TRUE(!bOk && !memcmp(bf, "\000bcd", 4));
memcpy(bf, "abcd", 4);
bOk = cry_strcpy(bf, 0);
EXPECT_TRUE(!bOk && !memcmp(bf, "\000bcd", 4));
memcpy(bf, "abcd", 4);
bOk = cry_strcpy(bf, 3, "qwerty");
EXPECT_TRUE(!bOk && !memcmp(bf, "qw\000d", 4));
memcpy(bf, "abcd", 4);
bOk = cry_strcpy(bf, 3, "qwerty", 4);
EXPECT_TRUE(!bOk && !memcmp(bf, "qw\000d", 4));
memcpy(bf, "abcd", 4);
bOk = cry_strcpy(bf, 3, "qwerty", 3);
EXPECT_TRUE(!bOk && !memcmp(bf, "qw\000d", 4));
memcpy(bf, "abcd", 4);
bOk = cry_strcpy(bf, 3, "qwerty", 2);
EXPECT_TRUE(bOk && !memcmp(bf, "qw\000d", 4));
memcpy(bf, "abcd", 4);
bOk = cry_strcpy(bf, 3, "qwerty", 1);
EXPECT_TRUE(bOk && !memcmp(bf, "q\000cd", 4));
memcpy(bf, "abcd", 4);
bOk = cry_strcpy(bf, 3, "qwerty", 0);
EXPECT_TRUE(bOk && !memcmp(bf, "\000bcd", 4));
memcpy(bf, "abcd", 4);
bOk = cry_strcpy(bf, "qwerty");
EXPECT_TRUE(!bOk && !memcmp(bf, "qwe\000", 4));
memcpy(bf, "abcd", 4);
bOk = cry_strcpy(bf, "qwerty", 4);
EXPECT_TRUE(!bOk && !memcmp(bf, "qwe\000", 4));
memcpy(bf, "abcd", 4);
bOk = cry_strcpy(bf, "qwerty", 3);
EXPECT_TRUE(bOk && !memcmp(bf, "qwe\000", 4));
memcpy(bf, "abcd", 4);
bOk = cry_strcpy(bf, "qwerty", 2);
EXPECT_TRUE(bOk && !memcmp(bf, "qw\000d", 4));
memcpy(bf, "abcd", 4);
bOk = cry_strcpy(bf, "qwe");
EXPECT_TRUE(bOk && !memcmp(bf, "qwe\000", 4));
memcpy(bf, "abcd", 4);
bOk = cry_strcpy(bf, "qwe", 4);
EXPECT_TRUE(bOk && !memcmp(bf, "qwe\000", 4));
memcpy(bf, "abcd", 4);
bOk = cry_strcpy(bf, "qw", 3);
EXPECT_TRUE(bOk && !memcmp(bf, "qw\000d", 4));
memcpy(bf, "abcd", 4);
bOk = cry_strcpy(bf, sizeof(bf), "q");
EXPECT_TRUE(bOk && !memcmp(bf, "q\000cd", 4));
memcpy(bf, "abcd", 4);
bOk = cry_strcpy(bf, sizeof(bf), "q", 2);
EXPECT_TRUE(bOk && !memcmp(bf, "q\000cd", 4));
// cry_strcat()
bOk = cry_strcat(0, 0, 0);
EXPECT_TRUE(!bOk);
bOk = cry_strcat(0, 0, 0, 0);
EXPECT_TRUE(!bOk);
bOk = cry_strcat(0, 1, 0);
EXPECT_TRUE(!bOk);
bOk = cry_strcat(0, 1, 0, 0);
EXPECT_TRUE(!bOk);
bOk = cry_strcat(0, 1, "");
EXPECT_TRUE(!bOk);
bOk = cry_strcat(0, 1, "", 1);
EXPECT_TRUE(!bOk);
memcpy(bf, "abcd", 4);
bOk = cry_strcat(bf, 0, "xy");
EXPECT_TRUE(!bOk && !memcmp(bf, "abcd", 4));
memcpy(bf, "abcd", 4);
bOk = cry_strcat(bf, 0, "xy", 3);
EXPECT_TRUE(!bOk && !memcmp(bf, "abcd", 4));
memcpy(bf, "abcd", 4);
bOk = cry_strcat(bf, 0, "xy", 0);
EXPECT_TRUE(!bOk && !memcmp(bf, "abcd", 4));
memcpy(bf, "abcd", 4);
bOk = cry_strcat(bf, 1, "xyz");
EXPECT_TRUE(!bOk && !memcmp(bf, "\000bcd", 4));
memcpy(bf, "abcd", 4);
bOk = cry_strcat(bf, 1, "xyz", 4);
EXPECT_TRUE(!bOk && !memcmp(bf, "\000bcd", 4));
memcpy(bf, "abcd", 4);
bOk = cry_strcat(bf, 1, "xyz", 1);
EXPECT_TRUE(!bOk && !memcmp(bf, "\000bcd", 4));
memcpy(bf, "abcd", 4);
bOk = cry_strcat(bf, 1, "xyz", 0);
EXPECT_TRUE(bOk && !memcmp(bf, "\000bcd", 4));
memcpy(bf, "abcd", 4);
bOk = cry_strcat(bf, 1, 0, 0);
EXPECT_TRUE(!bOk && !memcmp(bf, "\000bcd", 4));
memcpy(bf, "a\000cd", 4);
bOk = cry_strcat(bf, 3, "xyz");
EXPECT_TRUE(!bOk && !memcmp(bf, "ax\000d", 4));
memcpy(bf, "a\000cd", 4);
bOk = cry_strcat(bf, 3, "xyz", 4);
EXPECT_TRUE(!bOk && !memcmp(bf, "ax\000d", 4));
memcpy(bf, "a\000cd", 4);
bOk = cry_strcat(bf, 3, "xyz", 2);
EXPECT_TRUE(!bOk && !memcmp(bf, "ax\000d", 4));
memcpy(bf, "a\000cd", 4);
bOk = cry_strcat(bf, 3, "xyz", 1);
EXPECT_TRUE(bOk && !memcmp(bf, "ax\000d", 4));
memcpy(bf, "abcd", 4);
bOk = cry_strcat(bf, "xyz");
EXPECT_TRUE(!bOk && !memcmp(bf, "abc\000", 4));
memcpy(bf, "abcd", 4);
bOk = cry_strcat(bf, "xyz", 4);
EXPECT_TRUE(!bOk && !memcmp(bf, "abc\000", 4));
memcpy(bf, "abcd", 4);
bOk = cry_strcat(bf, "xyz", 1);
EXPECT_TRUE(!bOk && !memcmp(bf, "abc\000", 4));
memcpy(bf, "abcd", 4);
bOk = cry_strcat(bf, "xyz", 0);
EXPECT_TRUE(bOk && !memcmp(bf, "abc\000", 4));
memcpy(bf, "ab\000d", 4);
bOk = cry_strcat(bf, "xyz");
EXPECT_TRUE(!bOk && !memcmp(bf, "abx\000", 4));
memcpy(bf, "ab\000d", 4);
bOk = cry_strcat(bf, "xyz", 4);
EXPECT_TRUE(!bOk && !memcmp(bf, "abx\000", 4));
memcpy(bf, "ab\000d", 4);
bOk = cry_strcat(bf, "xyz", 1);
EXPECT_TRUE(bOk && !memcmp(bf, "abx\000", 4));
memcpy(bf, "ab\000d", 4);
bOk = cry_strcat(bf, "xyz", 0);
EXPECT_TRUE(bOk && !memcmp(bf, "ab\000d", 4));
memcpy(bf, "ab\000d", 4);
bOk = cry_strcat(bf, 0, 0);
EXPECT_TRUE(!bOk && !memcmp(bf, "ab\000d", 4));
memcpy(bf, "ab\000d", 4);
bOk = cry_strcat(bf, 0, 1);
EXPECT_TRUE(!bOk && !memcmp(bf, "ab\000d", 4));
memcpy(bf, "a\000cd", 4);
bOk = cry_strcat(bf, sizeof(bf), "xy");
EXPECT_TRUE(bOk && !memcmp(bf, "axy\000", 4));
memcpy(bf, "a\000cd", 4);
bOk = cry_strcat(bf, sizeof(bf), "xy", 3);
EXPECT_TRUE(bOk && !memcmp(bf, "axy\000", 4));
memcpy(bf, "a\000cd", 4);
bOk = cry_strcat(bf, sizeof(bf), "xy", 1);
EXPECT_TRUE(bOk && !memcmp(bf, "ax\000d", 4));
}
using CryPrimitivesAllocatorScope = AZ::AllocatorScope<AZ::LegacyAllocator, CryStringAllocator>;
class CryPrimitives
: public ::testing::Test
{
public:
void SetUp() override
{
m_memory.ActivateAllocators();
}
void TearDown() override
{
m_memory.DeactivateAllocators();
}
CryPrimitivesAllocatorScope m_memory;
};
TEST_F(CryPrimitives, CUT_CryString)
{
//////////////////////////////////////////////////////////////////////////
// Based on MS documentation of find_last_of
string strTestFindLastOfOverload1("abcd-1234-abcd-1234");
string strTestFindLastOfOverload2("ABCD-1234-ABCD-1234");
string strTestFindLastOfOverload3("456-EFG-456-EFG");
string strTestFindLastOfOverload4("12-ab-12-ab");
const char* cstr2 = "B1";
const char* cstr2b = "D2";
const char* cstr3a = "5E";
string str4a("ba3");
string str4b("a2");
size_t nPosition(string::npos);
nPosition = strTestFindLastOfOverload1.find_last_of('d', 14);
EXPECT_TRUE(nPosition == 13);
nPosition = strTestFindLastOfOverload2.find_last_of(cstr2, 12);
EXPECT_TRUE(nPosition == 11);
nPosition = strTestFindLastOfOverload2.find_last_of(cstr2b);
EXPECT_TRUE(nPosition == 16);
nPosition = strTestFindLastOfOverload3.find_last_of(cstr3a, 8, 2);
EXPECT_TRUE(nPosition == 4);
nPosition = strTestFindLastOfOverload4.find_last_of(str4a, 8);
EXPECT_TRUE(nPosition == 4);
nPosition = strTestFindLastOfOverload4.find_last_of(str4b);
EXPECT_TRUE(nPosition == 9);
//////////////////////////////////////////////////////////////////////////
// Based on MS documentation of find_last_not_of
string strTestFindLastNotOfOverload1("dddd-1dd4-abdd");
string strTestFindLastNotOfOverload2("BBB-1111");
string strTestFindLastNotOfOverload3("444-555-GGG");
string strTestFindLastNotOfOverload4("12-ab-12-ab");
const char* cstr2NF = "B1";
const char* cstr3aNF = "45G";
const char* cstr3bNF = "45G";
string str4aNF("b-a");
string str4bNF("12");
size_t nPosition3A(string::npos);
nPosition = strTestFindLastNotOfOverload1.find_last_not_of('d', 7);
EXPECT_TRUE(nPosition == 5);
nPosition = strTestFindLastNotOfOverload1.find_last_not_of("d");
EXPECT_TRUE(nPosition == 11);
nPosition = strTestFindLastNotOfOverload2.find_last_not_of(cstr2NF, 6);
EXPECT_TRUE(nPosition == 3);
nPosition = strTestFindLastNotOfOverload3.find_last_not_of(cstr3aNF);
EXPECT_TRUE(nPosition == 7);
nPosition = strTestFindLastNotOfOverload3.find_last_not_of(cstr3bNF, 6, 3);//nPosition - 1 );
EXPECT_TRUE(nPosition == 3);
nPosition = strTestFindLastNotOfOverload4.find_last_not_of(str4aNF, 5);
EXPECT_TRUE(nPosition == 1);
nPosition = strTestFindLastNotOfOverload4.find_last_not_of(str4bNF);
EXPECT_TRUE(nPosition == 10);
}
TEST_F(CryPrimitives, CUT_FixedString)
{
CryStackStringT<char, 10> str1;
CryStackStringT<char, 10> str2;
CryStackStringT<char, 4> str3;
CryStackStringT<char, 10> str4;
CryStackStringT<char, 6> str5;
CryStackStringT<wchar_t, 16> wstr1;
CryStackStringT<wchar_t, 255> wstr2;
CryFixedStringT<100> fixedString100;
CryFixedStringT<200> fixedString200;
typedef CryStackStringT<char, 10> T;
T* pStr = new T;
*pStr = "adads";
delete pStr;
str1 = "abcd";
EXPECT_EQ(str1, "abcd");
str2 = "efg";
EXPECT_EQ(str2, "efg");
str2 = str1;
EXPECT_EQ(str2, "abcd");
str1 += "XY";
EXPECT_EQ(str1, "abcdXY");
str2 += "efghijk";
EXPECT_EQ(str2, "abcdefghijk");
str1.replace("bc", "");
EXPECT_EQ(str1, "adXY");
str1.replace("XY", "1234");
EXPECT_EQ(str1, "ad1234");
str1.replace("1234", "1234567890");
EXPECT_EQ(str1, "ad1234567890");
str1.reserve(200);
EXPECT_EQ(str1, "ad1234567890");
EXPECT_TRUE(str1.capacity() == 200);
str1.reserve(0);
EXPECT_EQ(str1, "ad1234567890");
EXPECT_TRUE(str1.capacity() == str1.length());
str1.erase(7); // doesn't change capacity
EXPECT_EQ(str1, "ad12345");
str4.assign("abc");
EXPECT_EQ(str4, "abc");
str4.reserve(9);
EXPECT_TRUE(str4.capacity() >= 9); // capacity is always >= MAX_SIZE-1
str4.reserve(0);
EXPECT_TRUE(str4.capacity() >= 9); // capacity is always >= MAX_SIZE-1
size_t idx = str1.find("123");
EXPECT_TRUE(idx == 2);
idx = str1.find("123", 3);
EXPECT_TRUE(idx == str1.npos);
wstr1 = L"abc";
EXPECT_EQ(wstr1, L"abc");
EXPECT_TRUE(wstr1.compare(L"aBc") > 0);
EXPECT_TRUE(wstr1.compare(L"babc") < 0);
EXPECT_TRUE(wstr1.compareNoCase(L"aBc") == 0);
str1.Format("This is a %s %ls with %d params", "mixed", L"string", 3);
str2.Format("This is a %ls %s with %d params", L"mixed", "string", 3);
EXPECT_EQ(str1, "This is a mixed string with 3 params");
EXPECT_EQ(str1, str2);
wstr1.Format(L"This is a %ls %hs with %d params", L"mixed", "string", 3);
wstr2.Format(L"This is a %hs %ls with %d params", "mixed", L"string", 3);
EXPECT_EQ(wstr1, L"This is a mixed string with 3 params");
str5.FormatFast("%s", "12345");
EXPECT_EQ("1234", str5);
// we expect here that the string gets cut since it doesn't fit into the string buffer
str5.FormatFast("%s", "012345");
EXPECT_EQ("0123", str5);
}
//////////////////////////////////////////////////////////////////////////
// Unit Testing of aligned_vector
//////////////////////////////////////////////////////////////////////////
TEST_F(CryPrimitives, CUT_AlignedVector)
{
stl::aligned_vector<int, 16> vec;
vec.push_back(1);
vec.push_back(2);
vec.push_back(3);
EXPECT_TRUE(vec.size() == 3);
EXPECT_TRUE(((INT_PTR)(&vec[0]) % 16) == 0);
}
TEST_F(CryPrimitives, CUT_DynArray)
{
LegacyDynArray<int> a;
a.push_back(3);
a.insert(&a[0], 1, 1);
a.insert(&a[1], 1, 2);
a.insert(&a[0], 1, 0);
for (int i = 0; i < 4; i++)
{
EXPECT_TRUE(a[i] == i);
}
const int nStrs = 11;
string Strs[nStrs] = { "nought", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten" };
LegacyDynArray<string> s;
for (int i = 0; i < nStrs; i += 2)
{
s.push_back(Strs[i]);
}
for (int i = 1; i < nStrs; i += 2)
{
s.insert(i, Strs[i]);
}
for (int i = 0; i < nStrs; i++)
{
EXPECT_TRUE(s[i] == Strs[i]);
}
LegacyDynArray<string> s2 = s;
s.erase(5, 2);
EXPECT_TRUE(s.size() == nStrs - 2);
s.insert(&s[3], &Strs[5], &Strs[8]);
s2 = s2(3, 4);
EXPECT_TRUE(s2.size() == 4);
}
@@ -0,0 +1,102 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#include "CrySystem_precompiled.h"
#include <AzCore/UnitTest/TestTypes.h>
#include <AzCore/UnitTest/UnitTest.h>
#include <AzTest/AzTest.h>
#include <AzCore/Memory/OSAllocator.h>
#include "CrySizerImpl.h"
namespace UnitTest
{
class CrySizerTest
: public AllocatorsFixture
{
public:
void SetUp() override
{
AZ::AllocatorInstance<AZ::LegacyAllocator>::Create();
AZ::AllocatorInstance<CryStringAllocator>::Create();
m_sizer = new CrySizerImpl();
}
void TearDown() override
{
delete m_sizer;
AZ::AllocatorInstance<CryStringAllocator>::Destroy();
AZ::AllocatorInstance<AZ::LegacyAllocator>::Destroy();
}
protected:
CrySizerImpl* m_sizer;
}; //class StatisticsTest
/**
* The key data structures fed to ICrySizer in CTerrain::GetMemoryUsage(class ICrySizer* pSizer):
* 1. structs and classes.
* 2. PodArray< of structs / classes>
* 3. PodArray< of pointers>
*/
TEST_F(CrySizerTest, CrySizerTest_AddSomeObjectsUsedInCTerrain_GetExpectedSize)
{
struct TmpStruct
{
AZ::u32 a;
AZ::u32 b;
};
TmpStruct tmpStructObj;
//Tracking a simple struct.
m_sizer->AddObjectSize(&tmpStructObj);
//The AddObject method is only available when using the ICrySizer base class.
ICrySizer* sizer = static_cast<ICrySizer*>(m_sizer);
const int numItemsPerArray = 1024;
//PodArray of structs
PodArray<TmpStruct> podArrayOfTmpStruct;
podArrayOfTmpStruct.resize(numItemsPerArray);
sizer->AddObject(podArrayOfTmpStruct);
//PodArray of pointers
PodArray<TmpStruct*> podArrayOfTmpStructPointers;
podArrayOfTmpStructPointers.resize(numItemsPerArray);
sizer->AddObject(podArrayOfTmpStructPointers);
//PodArray of Array2d of pointers.
const int array2dAxisSize = 64;
PodArray<Array2d<TmpStruct*>> podArrayOfArray2d;
podArrayOfArray2d.resize(numItemsPerArray);
for (int i = 0; i < numItemsPerArray; ++i)
{
//Array2d will allocate array2dAxisSize * array2dAxisSize elements.
podArrayOfArray2d[i].Allocate(array2dAxisSize);
}
sizer->AddObject(podArrayOfArray2d);
//Calculate the total expected size
const size_t expectedSizeOfArray2d = sizeof(Array2d<TmpStruct*>)
+ (array2dAxisSize * array2dAxisSize) * sizeof(TmpStruct*);
const size_t expectedTotalSize = sizeof(TmpStruct)
+ numItemsPerArray * sizeof(TmpStruct)
+ numItemsPerArray * sizeof(TmpStruct*)
+ numItemsPerArray * expectedSizeOfArray2d;
EXPECT_EQ( m_sizer->GetTotalSize(), expectedTotalSize);
}
}//namespace UnitTest
@@ -0,0 +1,157 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#include "CrySystem_precompiled.h"
#include <AzTest/AzTest.h>
#include <AzCore/Memory/AllocatorScope.h>
#include "LocalizedStringManager.h"
#include <Mocks/ISystemMock.h>
#include <Mocks/IConsoleMock.h>
#include <Mocks/ICryPakMock.h>
#include <Mocks/ICVarMock.h>
#include <vector>
class SystemEventDispatcherMock
: public ISystemEventDispatcher
{
public:
virtual ~SystemEventDispatcherMock() {}
MOCK_METHOD1(RegisterListener, bool(ISystemEventListener* pListener));
MOCK_METHOD1(RemoveListener, bool(ISystemEventListener* pListener));
MOCK_METHOD3(OnSystemEvent, void(ESystemEvent event, UINT_PTR wparam, UINT_PTR lparam));
MOCK_METHOD0(Update, void());
};
using namespace testing;
using ::testing::NiceMock;
using SystemAllocatorScope = AZ::AllocatorScope<AZ::LegacyAllocator, CryStringAllocator>;
class SystemFixture
: public ::testing::Test
, public SystemAllocatorScope
{
public:
SystemFixture()
{
EXPECT_CALL(m_system, GetISystemEventDispatcher())
.WillRepeatedly(Return(&m_dispatcher));
EXPECT_CALL(m_console, GetCVar(_))
.WillRepeatedly(Return(&m_cvarMock));
EXPECT_CALL(m_cryPak, FindFirst(_, _, _))
.WillRepeatedly(Return(AZ::IO::ArchiveFileIterator{}));
EXPECT_CALL(m_cryPak, GetLocalizationFolder())
.WillRepeatedly(Return("french"));
EXPECT_CALL(m_cvarMock, GetFlags())
.WillRepeatedly(Return(VF_WASINCONFIG));
}
void SetUp() override
{
SystemAllocatorScope::ActivateAllocators();
memset(&m_stubEnv, 0, sizeof(SSystemGlobalEnvironment));
m_stubEnv.pConsole = &m_console;
m_stubEnv.pSystem = &m_system;
m_stubEnv.pCryPak = &m_cryPak;
m_stubEnv.pLog = nullptr;
m_priorEnv = gEnv;
gEnv = &m_stubEnv;
}
void TearDown() override
{
gEnv = m_priorEnv;
SystemAllocatorScope::DeactivateAllocators();
}
NiceMock<SystemMock> m_system;
NiceMock<SystemEventDispatcherMock> m_dispatcher;
NiceMock<ConsoleMock> m_console;
NiceMock<CryPakMock> m_cryPak;
NiceMock<CVarMock> m_cvarMock;
SSystemGlobalEnvironment m_stubEnv;
SSystemGlobalEnvironment* m_priorEnv = nullptr;
};
class UnitTestCLocalizedStringsManager : public CLocalizedStringsManager
{
public:
UnitTestCLocalizedStringsManager(ISystem* pSystem) : CLocalizedStringsManager(pSystem)
{
}
bool LocalizeLabel(const char* sLabel, string& outLocalizedString, bool bEnglish = false) override
{
m_capturedLabels.push_back(sLabel);
return CLocalizedStringsManager::LocalizeLabel(sLabel, outLocalizedString, bEnglish);
}
std::vector<string> m_capturedLabels;
friend class GTEST_TEST_CLASS_NAME_(SystemFixture, LocalizeStringInternal_WhitespaceCharacters_CorrectlyTokenizes);
};
// this test makes sure that whitespace characters such as tab work (not just space) and are considered to be separators.
TEST_F(SystemFixture, LocalizeStringInternal_SpecificWhitespaceCharacters_CorrectlyTokenizes)
{
UnitTestCLocalizedStringsManager manager(&m_system);
manager.SetLanguage("french");
string outString;
manager.LocalizeString_s("@hello\t@world", outString, false);
ASSERT_EQ(manager.m_capturedLabels.size(), 2);
EXPECT_STREQ(manager.m_capturedLabels[0].c_str(), "@hello");
EXPECT_STREQ(manager.m_capturedLabels[1].c_str(), "@world");
manager.m_capturedLabels.clear();
manager.LocalizeString_s("@hello\n@world", outString, false);
ASSERT_EQ(manager.m_capturedLabels.size(), 2);
EXPECT_STREQ(manager.m_capturedLabels[0].c_str(), "@hello");
EXPECT_STREQ(manager.m_capturedLabels[1].c_str(), "@world");
manager.m_capturedLabels.clear();
manager.LocalizeString_s("@hello\r@world", outString, false);
ASSERT_EQ(manager.m_capturedLabels.size(), 2);
EXPECT_STREQ(manager.m_capturedLabels[0].c_str(), "@hello");
EXPECT_STREQ(manager.m_capturedLabels[1].c_str(), "@world");
manager.m_capturedLabels.clear();
manager.LocalizeString_s("@hello @world", outString, false);
ASSERT_EQ(manager.m_capturedLabels.size(), 2);
EXPECT_STREQ(manager.m_capturedLabels[0].c_str(), "@hello");
EXPECT_STREQ(manager.m_capturedLabels[1].c_str(), "@world");
manager.m_capturedLabels.clear();
}
// this test makes sure that multiple whitespace characters in a row don't themselves count as tokens or change the output in undesirable ways.
TEST_F(SystemFixture, LocalizeStringInternal_ManyWhitespaceCharacters_CorrectlyTokenizes)
{
UnitTestCLocalizedStringsManager manager(&m_system);
manager.SetLanguage("french");
string outString;
const char* testString = "@hello\n\r\t \t\r\n@world\n\r\t ";
manager.LocalizeString_ch(testString, outString, false);
ASSERT_EQ(manager.m_capturedLabels.size(), 2);
EXPECT_STREQ(manager.m_capturedLabels[0].c_str(), "@hello");
EXPECT_STREQ(manager.m_capturedLabels[1].c_str(), "@world");
// since there are no localizations available it should not have gobbled up whitespace or altered it.
EXPECT_STREQ(outString, testString);
}
@@ -0,0 +1,61 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#include "CrySystem_precompiled.h"
#include <AzTest/AzTest.h>
#include <AzCore/Memory/OSAllocator.h>
#include <AzCore/Memory/SystemAllocator.h>
#include <LegacyAllocator.h>
#include <System.h>
#include <CryMemoryManager.h>
namespace UnitTests
{
class CSystemUnitTests
: public ::testing::Test
{
public:
void SetUp() override
{
IMemoryManager* cryMemoryManager = nullptr;
CryGetIMemoryManagerInterface((void**)&cryMemoryManager);
AZ_Assert(cryMemoryManager, "Unable to resolve CryMemoryManager");
m_cryMemoryManager = AZ::Environment::CreateVariable<IMemoryManager*>("CryIMemoryManagerInterface", cryMemoryManager);
SSystemInitParams startupParams;
AZ::AllocatorInstance<AZ::LegacyAllocator>::Create();
AZ::AllocatorInstance<CryStringAllocator>::Create();
m_system = new CSystem(startupParams.pSharedEnvironment);
}
void TearDown() override
{
delete m_system;
AZ::AllocatorInstance<CryStringAllocator>::Destroy();
AZ::AllocatorInstance<AZ::LegacyAllocator>::Destroy();
}
CSystem* m_system = nullptr;
AZ::EnvironmentVariable<IMemoryManager*> m_cryMemoryManager;
};
TEST_F(CSystemUnitTests, ApplicationLogInstanceUnitTests)
{
const char dummyString[] = "dummy";
const char testString[] = "test";
EXPECT_EQ(m_system->GetApplicationLogInstance(dummyString), 0);
EXPECT_EQ(m_system->GetApplicationLogInstance(testString), 0);
#if AZ_TRAIT_OS_USE_WINDOWS_MUTEX
EXPECT_EQ(m_system->GetApplicationLogInstance(dummyString), 1);
#endif
}
}
@@ -0,0 +1,43 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#include "CrySystem_precompiled.h"
#include <AzTest/AzTest.h>
#include <AzCore/Memory/OSAllocator.h>
#include <AzCore/Memory/SystemAllocator.h>
#include <AzCore/UnitTest/UnitTest.h>
class CrySystemTestEnvironment
: public AZ::Test::ITestEnvironment
, public ::UnitTest::TraceBusRedirector
{
public:
virtual ~CrySystemTestEnvironment()
{}
protected:
void SetupEnvironment() override
{
AZ::AllocatorInstance<AZ::OSAllocator>::Create();
AZ::AllocatorInstance<AZ::SystemAllocator>::Create();
::UnitTest::TraceBusRedirector::BusConnect();
}
void TeardownEnvironment() override
{
::UnitTest::TraceBusRedirector::BusDisconnect();
AZ::AllocatorInstance<AZ::OSAllocator>::Destroy();
AZ::AllocatorInstance<AZ::SystemAllocator>::Destroy();
}
};
AZ_UNIT_TEST_HOOK(new CrySystemTestEnvironment)
@@ -0,0 +1,89 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#include "CrySystem_precompiled.h"
#include <AzTest/AzTest.h>
#include <AzCore/base.h>
#include <AzCore/IO/SystemFile.h>
#include "MaterialUtils.h"
#include <IConsole.h>
TEST(CrySystemMaterialUtilsTests, MaterialUtilsTestBasics)
{
char tempBuffer[AZ_MAX_PATH_LEN] = { 0 };
// call to ensure that it handles nullptr without crashing
MaterialUtils::UnifyMaterialName(nullptr);
MaterialUtils::UnifyMaterialName(tempBuffer);
EXPECT_TRUE(tempBuffer[0] == 0);
}
TEST(CrySystemMaterialUtilsTests, MaterialUtilsTestExtensions)
{
char tempBuffer[AZ_MAX_PATH_LEN];
azstrcpy(tempBuffer, AZ_MAX_PATH_LEN, "blahblah.mtl");
MaterialUtils::UnifyMaterialName(tempBuffer);
EXPECT_TRUE(strcmp(tempBuffer, "blahblah") == 0);
azstrcpy(tempBuffer, AZ_MAX_PATH_LEN, "blahblah.mat.mat.abc.test.mtl");
MaterialUtils::UnifyMaterialName(tempBuffer);
EXPECT_TRUE(strcmp(tempBuffer, "blahblah.mat.mat.abc.test") == 0);
azstrcpy(tempBuffer, AZ_MAX_PATH_LEN, "test/.mat.mat/blahblah.mat.mat.abc.test.mtl");
MaterialUtils::UnifyMaterialName(tempBuffer);
EXPECT_TRUE(strcmp(tempBuffer, "test/.mat.mat/blahblah.mat.mat.abc.test") == 0);
azstrcpy(tempBuffer, AZ_MAX_PATH_LEN, ".mat.mat.blahblah.mat.mat.abc.test.mtl");
MaterialUtils::UnifyMaterialName(tempBuffer);
EXPECT_TRUE(strcmp(tempBuffer, ".mat.mat.blahblah.mat.mat.abc.test") == 0);
}
TEST(CrySystemMaterialUtilsTests, MaterialUtilsTestPrefixes)
{
char tempBuffer[AZ_MAX_PATH_LEN];
azstrcpy(tempBuffer, AZ_MAX_PATH_LEN, ".\\blahblah.mat");
MaterialUtils::UnifyMaterialName(tempBuffer);
EXPECT_TRUE(strcmp(tempBuffer, "blahblah") == 0);
azstrcpy(tempBuffer, AZ_MAX_PATH_LEN, "./materials/blahblah.mat.mat.abc.test");
MaterialUtils::UnifyMaterialName(tempBuffer);
EXPECT_TRUE(strcmp(tempBuffer, "materials/blahblah.mat.mat.abc") == 0);
azstrcpy(tempBuffer, AZ_MAX_PATH_LEN, ".\\engine\\materials\\blahblah.mat.mat.abc.test");
MaterialUtils::UnifyMaterialName(tempBuffer);
EXPECT_TRUE(strcmp(tempBuffer, "materials/blahblah.mat.mat.abc") == 0);
azstrcpy(tempBuffer, AZ_MAX_PATH_LEN, "engine/materials/blahblah.mat.mat.abc.test");
MaterialUtils::UnifyMaterialName(tempBuffer);
EXPECT_TRUE(strcmp(tempBuffer, "materials/blahblah.mat.mat.abc") == 0);
azstrcpy(tempBuffer, AZ_MAX_PATH_LEN, "materials/blahblah.mat");
MaterialUtils::UnifyMaterialName(tempBuffer);
EXPECT_TRUE(strcmp(tempBuffer, "materials/blahblah") == 0);
}
TEST(CrySystemMaterialUtilsTests, MaterialUtilsTestGameName)
{
char tempBuffer[AZ_MAX_PATH_LEN];
ICVar* pGameNameCVar = nullptr;
if ((gEnv)&&(gEnv->pConsole))
{
pGameNameCVar = gEnv->pConsole->GetCVar("sys_game_folder");
}
azsnprintf(tempBuffer, AZ_MAX_PATH_LEN, ".\\%s\\materials\\blahblah.mat.mat.abc.test", pGameNameCVar ? pGameNameCVar->GetString() : "SamplesProject");
MaterialUtils::UnifyMaterialName(tempBuffer);
EXPECT_TRUE(strcmp(tempBuffer, "materials/blahblah.mat.mat.abc") == 0);
}