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
+328
View File
@@ -0,0 +1,328 @@
/*
* 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 <AzTest/AzTest.h>
#include <AzTest/Platform.h>
#include <AzCore/UnitTest/UnitTest.h>
namespace AZ
{
namespace Test
{
::testing::Environment* sTestEnvironment = nullptr;
//! Add a single test environment to the framework
void addTestEnvironment(ITestEnvironment* env)
{
sTestEnvironment = ::testing::AddGlobalTestEnvironment(env);
}
//! Add a list of test environments to the framework
void addTestEnvironments(std::vector<ITestEnvironment*> envs)
{
//! If nothing is supplied, add the default hook
if (envs.empty())
{
addTestEnvironment(AZ::Test::DefaultTestEnv());
}
else
{
for (auto env : envs)
{
//! Skip over nullptr to allow callers to avoid the default hook
if (env != nullptr)
{
addTestEnvironment(env);
}
}
}
}
std::vector<TestEnvironmentRegistry*> TestEnvironmentRegistry::s_envs;
void AddExcludeFilter(const char* name)
{
std::string currentFilter = ::testing::GTEST_FLAG(filter);
if (currentFilter.compare("*") == 0) // is the current filter already the wildcard '*' ?
{
// in which case, change it from wildcard to be everything except the filter ('-thing')
::testing::GTEST_FLAG(filter) = "-";
}
else
{
// otherwise, there is some sort of filter already. Is it a negation filter?
if (currentFilter.find("-") == std::string::npos)
{
// no, add a negation. Only one negation (minus symbol) can appear and everything
// after that negation is negated.
::testing::GTEST_FLAG(filter).append(":-");
}
else
{
// if there's a negation filter already, we just append to the end, and we dont negate again
::testing::GTEST_FLAG(filter).append(":");
}
}
::testing::GTEST_FLAG(filter).append(name);
}
void AddIncludeFilter(const char* name)
{
std::string currentFilter = ::testing::GTEST_FLAG(filter);
if (currentFilter.compare("*") == 0) // is the current filter already the wildcard '*' only
{
// replace it to filter the name
::testing::GTEST_FLAG(filter) = name;
}
else
{
// prepend to the exisiting filter.
std::stringstream additionalFilter;
additionalFilter << name << ":" << currentFilter;
::testing::GTEST_FLAG(filter) = additionalFilter.str();
}
}
//! Filter out integration tests from the test run
void excludeIntegTests()
{
AddExcludeFilter("INTEG_*");
AddExcludeFilter("Integ_*");
}
void ApplyGlobalParameters(int* argc, char** argv)
{
// this is a hook that can be used to apply any other global non-google parameters
// that we use.
AZ_UNUSED(argc);
AZ_UNUSED(argv);
}
//! Print out parameters that are not used by the framework
void printUnusedParametersWarning(int argc, char** argv)
{
//! argv[0] is the runner executable name, which we expect and need to keep around
if (argc > 1)
{
std::cerr << "WARNING: unrecognized parameters: ";
for (int i = 1; i < argc; i++)
{
std::cerr << argv[i] << ", ";
}
std::cerr << std::endl;
}
}
bool AzUnitTestMain::Run(int argc, char** argv)
{
using namespace AZ::Test;
m_returnCode = 0;
if (ContainsParameter(argc, argv, "--unittest") || ContainsParameter(argc, argv, "--unittests"))
{
// the --unittest parameter makes us run tests built inside this executable
// first, remove the unit test parameter so that it doesn't get passed into google
// test, which would potentially generate warnings since its a non standard param:
int unitTestIndex = GetParameterIndex(argc, argv, "--unittest");
if (unitTestIndex != -1)
{
RemoveParameters(argc, argv, unitTestIndex, unitTestIndex);
}
unitTestIndex = GetParameterIndex(argc, argv, "--unittests");
if (unitTestIndex != -1)
{
RemoveParameters(argc, argv, unitTestIndex, unitTestIndex);
}
int waitForDebbugerIndex = GetParameterIndex(argc, argv, "--wait-for-debugger");
if (waitForDebbugerIndex != -1)
{
RemoveParameters(argc, argv, waitForDebbugerIndex, waitForDebbugerIndex);
AZ::Test::Platform& platform = AZ::Test::GetPlatform();
if (platform.SupportsWaitForDebugger())
{
std::cout << "Waiting for debugger..." << std::endl;
platform.WaitForDebugger();
}
else
{
std::cerr << "Warning - platform does not support --wait-for-debugger feature" << std::endl;
}
}
::testing::InitGoogleMock(&argc, argv);
AZ::Test::excludeIntegTests();
AZ::Test::ApplyGlobalParameters(&argc, argv);
AZ::Test::printUnusedParametersWarning(argc, argv);
AZ::Test::addTestEnvironments(m_envs);
m_returnCode = RUN_ALL_TESTS();
return true;
}
else if (ContainsParameter(argc, argv, "--loadunittests"))
{
// Run tests inside defined lib(s) (as runner would)
Platform& platform = GetPlatform();
platform.Printf("Running tests with arguments: \"");
for (int i = 0; i < argc; i++)
{
platform.Printf("%s", argv[i]);
if (i < argc - 1)
{
platform.Printf(" ");
}
}
platform.Printf("\"\n");
int testFlagIndex = GetParameterIndex(argc, argv, "--loadunittests");
RemoveParameters(argc, argv, testFlagIndex, testFlagIndex);
// Grab the test symbol to call
std::string symbol = GetParameterValue(argc, argv, "--symbol", true);
#if !defined(AZ_MONOLITHIC_BUILD)
if (symbol.empty())
{
platform.Printf("ERROR: Must provide --symbol to run tests inside libs!\n");
return false;
}
#endif // AZ_MONOLITHIC_BUILD
// Get the lib information
if (ContainsParameter(argc, argv, "--libs"))
{
// Multiple libs have been given, so grab them all (as a list)
auto libs = GetParameterList(argc, argv, "--libs", true);
// Since we have multiple libs, check for a path for the XML files (do NOT pass in --gtest_output directly)
std::string outputPath = GetParameterValue(argc, argv, "--output_path", true);
platform.Printf("Outputing XML files to: %s\n", outputPath.c_str());
// Now iterate through each lib, defining the output file each time
for (std::string lib : libs)
{
// Create the full output path for the XML file
std::string libName = platform.GetModuleNameFromPath(lib);
std::stringstream outputFileStream;
outputFileStream << "--gtest_output=xml:" << outputPath << "test_result_" << libName << ".xml";
std::string outputFile = outputFileStream.str();
// Create a new array since GTest removes parameters
int targc = argc + 1;
char** targv = new char*[targc];
CopyParameters(argc, targv, argv);
targv[targc - 1] = const_cast<char*>(outputFile.c_str());
// Run the tests
m_returnCode = RunTestsInLib(platform, lib, symbol, targc, targv);
platform.Printf("Test result from '%s': %d\n", lib.c_str(), m_returnCode);
// Cleanup
delete[] targv;
}
}
else if (ContainsParameter(argc, argv, "--lib"))
{
// Only one lib has been given
std::string lib = GetParameterValue(argc, argv, "--lib", true);
m_returnCode = RunTestsInLib(platform, lib, symbol, argc, argv);
platform.Printf("Test result from '%s': %d\n", lib.c_str(), m_returnCode);
}
else
{
platform.Printf("ERROR: Must specify either --lib or --libs to run tests!\n");
return false;
}
return true;
}
return false;
}
bool AzUnitTestMain::Run(const char* commandLine)
{
int tokenSize;
char** commandTokens = AZ::Test::SplitCommandLine(tokenSize, const_cast<char*>(commandLine));
bool result = Run(tokenSize, commandTokens);
for (int i = 0; i < tokenSize; i++)
{
delete[] commandTokens[i];
}
delete[] commandTokens;
return result;
}
int RunTestsInLib(AZ::Test::Platform& platform, const std::string& lib, const std::string& symbol, int& argc, char** argv)
{
#if defined(AZ_MONOLITHIC_BUILD)
::testing::InitGoogleMock(&argc, argv);
std::string lib_upper(lib);
std::transform(lib_upper.begin(), lib_upper.end(), lib_upper.begin(), ::toupper);
for (auto env : AZ::Test::TestEnvironmentRegistry::s_envs)
{
if (env->m_module_name == lib_upper)
{
AZ::Test::addTestEnvironments(env->m_envs);
::testing::GTEST_FLAG(module) = lib_upper;
platform.Printf("Found library: %s\n", lib_upper.c_str());
}
else
{
platform.Printf("Available library %s does not match %s.\n", env->m_module_name.c_str(), lib_upper.c_str());
}
}
AZ::Test::excludeIntegTests();
AZ::Test::printUnusedParametersWarning(argc, argv);
return RUN_ALL_TESTS();
#else // AZ_MONOLITHIC_BUILD
int result = 0;
std::shared_ptr<AZ::Test::IModuleHandle> module = platform.GetModule(lib);
if (module->IsValid())
{
platform.Printf("OKAY Library loaded: %s\n", lib.c_str());
auto fn = module->GetFunction(symbol);
if (fn->IsValid())
{
platform.Printf("OKAY Symbol found: %s\n", symbol.c_str());
result = (*fn)(argc, argv);
platform.Printf("OKAY %s() return %d\n", symbol.c_str(), result);
}
else
{
platform.Printf("FAILED to find symbol: %s\n", symbol.c_str());
result = SYMBOL_NOT_FOUND;
}
}
else
{
platform.Printf("FAILED to load library: %s\n", lib.c_str());
result = LIB_NOT_FOUND;
}
return result;
#endif // AZ_MONOLITHIC_BUILD
}
ITestEnvironment* DefaultTestEnv()
{
return new UnitTest::TraceBusHook();
}
} // Test
} // AZ
+491
View File
@@ -0,0 +1,491 @@
/*
* 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.
*
*/
#pragma once
#include <AzCore/PlatformDef.h>
#include <AzTest_Traits_Platform.h>
#include <list>
#include <array>
AZ_PUSH_DISABLE_WARNING(4389 4800, "-Wunknown-warning-option"); // 'int' : forcing value to bool 'true' or 'false' (performance warning).
#undef strdup // platform.h in CryCommon changes this define which is required by googletest
#include <gtest/gtest.h>
#include <gmock/gmock.h>
AZ_POP_DISABLE_WARNING;
#if defined(HAVE_BENCHMARK)
#include <benchmark/benchmark.h>
#endif
#include <AzCore/Memory/OSAllocator.h>
#define AZTEST_DLL_PUBLIC AZ_DLL_EXPORT
#define AZTEST_EXPORT extern "C" AZTEST_DLL_PUBLIC
namespace AZ
{
namespace Test
{
//! Forward declarations
class Platform;
/*!
* Implement this interface to define the environment setup and teardown functions.
*/
class ITestEnvironment
: public ::testing::Environment
{
public:
virtual ~ITestEnvironment()
{}
void SetUp() override final
{
SetupEnvironment();
}
void TearDown() override final
{
TeardownEnvironment();
}
protected:
virtual void SetupEnvironment() = 0;
virtual void TeardownEnvironment() = 0;
};
extern ::testing::Environment* sTestEnvironment;
/*!
* Monolithic builds will have all the environments available. Keep a mapping to run the desired envs.
*/
class TestEnvironmentRegistry
{
public:
TestEnvironmentRegistry(std::vector<ITestEnvironment*> a_envs, const std::string& a_module_name, bool a_unit)
: m_module_name(a_module_name)
, m_envs(a_envs)
, m_unit(a_unit)
{
s_envs.push_back(this);
}
const std::string m_module_name;
std::vector<ITestEnvironment*> m_envs;
bool m_unit;
static std::vector<TestEnvironmentRegistry*> s_envs;
private:
TestEnvironmentRegistry& operator=(const TestEnvironmentRegistry& tmp);
};
/*!
* Empty implementation of ITestEnvironment.
*/
class EmptyTestEnvironment final
: public ITestEnvironment
{
public:
virtual ~EmptyTestEnvironment()
{}
protected:
void SetupEnvironment() override
{}
void TeardownEnvironment() override
{}
};
void addTestEnvironment(ITestEnvironment* env);
void addTestEnvironments(std::vector<ITestEnvironment*> envs);
void excludeIntegTests();
//! A hook that can be used to read any other misc parameters and remove them before google sees them.
//! Note that this modifies argc and argv to delete the parameters it consumes.
void ApplyGlobalParameters(int* argc, char** argv);
void printUnusedParametersWarning(int argc, char** argv);
/*!
* Main method for running tests from an executable.
*/
class AzUnitTestMain final
{
public:
AzUnitTestMain(std::vector<AZ::Test::ITestEnvironment*> envs)
: m_returnCode(0)
, m_envs(envs)
{}
bool Run(int argc, char** argv);
bool Run(const char* commandLine);
int ReturnCode() const { return m_returnCode; }
private:
int m_returnCode;
std::vector<ITestEnvironment*> m_envs;
};
//! Run tests in a single library by loading it dynamically and executing the exported symbol,
//! passing main-like parameters (argc, argv) from the (real or artificial) command line.
int RunTestsInLib(Platform& platform, const std::string& lib, const std::string& symbol, int& argc, char** argv);
#if defined(HAVE_BENCHMARK)
static constexpr const char* s_benchmarkEnvironmentName = "BenchmarkEnvironment";
// BenchmarkEnvironment is a base that can be implemented to used to perform global initialization and teardown
// for a module
class BenchmarkEnvironmentBase
{
public:
virtual ~BenchmarkEnvironmentBase() = default;
virtual void SetUpBenchmark()
{
}
virtual void TearDownBenchmark()
{
}
};
class BenchmarkEnvironmentRegistry
{
public:
BenchmarkEnvironmentRegistry() = default;
BenchmarkEnvironmentRegistry(const BenchmarkEnvironmentRegistry&) = delete;
BenchmarkEnvironmentRegistry& operator=(const BenchmarkEnvironmentRegistry&) = delete;
void AddBenchmarkEnvironment(std::unique_ptr<BenchmarkEnvironmentBase> env)
{
m_envs.push_back(std::move(env));
}
std::vector<std::unique_ptr<BenchmarkEnvironmentBase>>& GetBenchmarkEnvironments()
{
return m_envs;
}
private:
std::vector<std::unique_ptr<BenchmarkEnvironmentBase>> m_envs;
};
/*
* Creates a BenchmarkEnvironment using the specified template type and registers it with the BenchmarkEnvironmentRegister
* @param T template argument that must have BenchmarkEnvironmentBase as a base class
* @return returns a reference to the created BenchmarkEnvironment
*/
template<typename T>
T& RegisterBenchmarkEnvironment()
{
static_assert(std::is_base_of<BenchmarkEnvironmentBase, T>::value, "Supplied benchmark environment must be derived from BenchmarkEnvironmentBase");
static AZ::EnvironmentVariable<AZ::Test::BenchmarkEnvironmentRegistry> s_benchmarkRegistry;
if (!s_benchmarkRegistry)
{
s_benchmarkRegistry = AZ::Environment::CreateVariable<AZ::Test::BenchmarkEnvironmentRegistry>(s_benchmarkEnvironmentName);
}
auto benchmarkEnv{ new T };
s_benchmarkRegistry->AddBenchmarkEnvironment(std::unique_ptr<BenchmarkEnvironmentBase>{ benchmarkEnv });
return *benchmarkEnv;
}
template<typename... Ts>
std::array<BenchmarkEnvironmentBase*, sizeof...(Ts)> RegisterBenchmarkEnvironments()
{
constexpr size_t EnvironmentCount{ sizeof...(Ts) };
if constexpr (EnvironmentCount)
{
std::array<BenchmarkEnvironmentBase*, EnvironmentCount> benchmarkEnvs{ { &RegisterBenchmarkEnvironment<Ts>()... } };
return benchmarkEnvs;
}
else
{
std::array<BenchmarkEnvironmentBase*, EnvironmentCount> benchmarkEnvs{};
return benchmarkEnvs;
}
}
#endif
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//! listener class to capture and print test output for embedded platforms
class OutputEventListener : public ::testing::EmptyTestEventListener
{
public:
std::list<std::string> resultList;
void OnTestEnd(const ::testing::TestInfo& test_info)
{
std::string result;
if (test_info.result()->Failed())
{
result = "Fail";
}
else
{
result = "Pass";
}
std::string formattedResult = "[GTEST][" + result + "] " + test_info.test_case_name() + " " + test_info.name() + "\n";
resultList.emplace_back(formattedResult);
}
void OnTestProgramEnd(const ::testing::UnitTest& unit_test)
{
for (std::string testResults : resultList)
{
AZ_Printf("", testResults.c_str());
}
if (unit_test.current_test_info())
{
AZ_Printf("", "[GTEST] %s completed %u tests with u% failed test cases.", unit_test.current_test_info()->name(), unit_test.total_test_count(), unit_test.failed_test_case_count());
}
}
};
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
ITestEnvironment* DefaultTestEnv();
} // Test
} // AZ
#define AZ_UNIT_TEST_HOOK_NAME AzRunUnitTests
#if !defined(AZ_MONOLITHIC_BUILD)
// Environments should be declared dynamically, framework will handle deletion of resources
#define AZ_UNIT_TEST_HOOK_ENV(TEST_ENV) \
AZTEST_EXPORT int AZ_UNIT_TEST_HOOK_NAME(int argc, char** argv) \
{ \
::testing::InitGoogleMock(&argc, argv); \
if (AZ_TRAIT_AZTEST_ATTACH_RESULT_LISTENER) \
{ \
::testing::TestEventListeners& listeners = testing::UnitTest::GetInstance()->listeners(); \
listeners.Append(new AZ::Test::OutputEventListener); \
} \
AZ::Test::excludeIntegTests(); \
AZ::Test::ApplyGlobalParameters(&argc, argv); \
AZ::Test::printUnusedParametersWarning(argc, argv); \
AZ::Test::addTestEnvironments({TEST_ENV}); \
int result = RUN_ALL_TESTS(); \
return result; \
}
#if defined(HAVE_BENCHMARK)
#define AZ_BENCHMARK_HOOK_ENV(TEST_ENV) \
AZTEST_EXPORT int AzRunBenchmarks(int argc, char** argv) \
{ \
AZ::Test::RegisterBenchmarkEnvironments<TEST_ENV>(); \
auto benchmarkEnvRegistry = AZ::Environment::FindVariable<AZ::Test::BenchmarkEnvironmentRegistry>(AZ::Test::s_benchmarkEnvironmentName); \
std::vector<std::unique_ptr<AZ::Test::BenchmarkEnvironmentBase>>* benchmarkEnvs = benchmarkEnvRegistry ? &(benchmarkEnvRegistry->GetBenchmarkEnvironments()) : nullptr; \
if (benchmarkEnvs != nullptr) \
{ \
for (std::unique_ptr<AZ::Test::BenchmarkEnvironmentBase>& benchmarkEnv : *benchmarkEnvs) \
{ \
if (benchmarkEnv) \
{ \
benchmarkEnv->SetUpBenchmark(); \
} \
}\
} \
::benchmark::Initialize(&argc, argv); \
::benchmark::RunSpecifiedBenchmarks(); \
if (benchmarkEnvs != nullptr) \
{ \
for (auto benchmarkEnvIter = benchmarkEnvs->rbegin(); benchmarkEnvIter != benchmarkEnvs->rend(); ++benchmarkEnvIter) \
{ \
std::unique_ptr<AZ::Test::BenchmarkEnvironmentBase>& benchmarkEnv = *benchmarkEnvIter; \
if (benchmarkEnv) \
{ \
benchmarkEnv->TearDownBenchmark(); \
} \
}\
} \
return 0; \
}
#define AZ_BENCHMARK_HOOK() \
AZTEST_EXPORT int AzRunBenchmarks(int argc, char** argv) \
{ \
AZ::Test::RegisterBenchmarkEnvironments<>(); \
auto benchmarkEnvRegistry = AZ::Environment::FindVariable<AZ::Test::BenchmarkEnvironmentRegistry>(AZ::Test::s_benchmarkEnvironmentName); \
std::vector<std::unique_ptr<AZ::Test::BenchmarkEnvironmentBase>>* benchmarkEnvs = benchmarkEnvRegistry ? &(benchmarkEnvRegistry->GetBenchmarkEnvironments()) : nullptr; \
if (benchmarkEnvs != nullptr) \
{ \
for (std::unique_ptr<AZ::Test::BenchmarkEnvironmentBase>& benchmarkEnv : *benchmarkEnvs) \
{ \
if (benchmarkEnv) \
{ \
benchmarkEnv->SetUpBenchmark(); \
} \
}\
} \
::benchmark::Initialize(&argc, argv); \
::benchmark::RunSpecifiedBenchmarks(); \
if (benchmarkEnvs != nullptr) \
{ \
for (auto benchmarkEnvIter = benchmarkEnvs->rbegin(); benchmarkEnvIter != benchmarkEnvs->rend(); ++benchmarkEnvIter) \
{ \
std::unique_ptr<AZ::Test::BenchmarkEnvironmentBase>& benchmarkEnv = *benchmarkEnvIter; \
if (benchmarkEnv) \
{ \
benchmarkEnv->TearDownBenchmark(); \
} \
}\
} \
return 0; \
}
#else // !HAVE_BENCHMARK
#define AZ_BENCHMARK_HOOK_ENV(TEST_ENV) \
int AzRunBenchmarks(int argc, char** argv) \
{ \
std::cerr << "'AzRunBenchmarks' Not supported" << std::endl; \
return 1; \
}
#define AZ_BENCHMARK_HOOK() \
int AzRunBenchmarks(int argc, char** argv) \
{ \
std::cerr << "'AzRunBenchmarks' Not supported" << std::endl; \
return 1; \
}
#endif // HAVE_BENCHMARK
#if defined(AZ_TEST_EXECUTABLE)
#define IMPLEMENT_TEST_EXECUTABLE_MAIN() \
int main(int argc, char** argv) \
{ \
const bool isUnitTestCmd = (argc<2)?true:(strcmp(argv[1], AZ_STRINGIZE(AZ_UNIT_TEST_HOOK_NAME))==0); \
const bool isBenchmarkCmd = (argc<2)?false:(strcmp(argv[1], "AzRunBenchmarks")==0); \
if (isUnitTestCmd) \
{ \
if (argc<2) \
{ \
return AZ_UNIT_TEST_HOOK_NAME(argc, argv); \
} \
else \
{ \
argv[1] = argv[0]; \
return AZ_UNIT_TEST_HOOK_NAME(argc-1, &argv[1]); \
} \
} \
else if (isBenchmarkCmd) \
{ \
argv[1] = argv[0]; \
return AzRunBenchmarks(argc-1, &argv[1]); \
} \
else \
{ \
std::cerr << "Invalid arguments for test" << std::endl; \
return 1; \
} \
}
#else
#define IMPLEMENT_TEST_EXECUTABLE_MAIN()
#endif // defined(AZ_TEST_EXECUTABLE)
#else // monolithic build
#undef GTEST_MODULE_NAME_
#define GTEST_MODULE_NAME_ AZ_MODULE_NAME
#define AZTEST_CONCAT_(a, b) a ## _ ## b
#define AZTEST_CONCAT(a, b) AZTEST_CONCAT_(a, b)
#define AZ_UNIT_TEST_HOOK_REGISTRY_NAME AZTEST_CONCAT(AZ_UNIT_TEST_HOOK_NAME, Registry)
#define AZ_UNIT_TEST_HOOK_ENV(TEST_ENV) \
static AZ::Test::TestEnvironmentRegistry* AZ_UNIT_TEST_HOOK_REGISTRY_NAME =\
new( AZ_OS_MALLOC(sizeof(AZ::Test::TestEnvironmentRegistry), \
alignof(AZ::Test::TestEnvironmentRegistry))) \
AZ::Test::TestEnvironmentRegistry({ TEST_ENV }, AZ_MODULE_NAME, true);
#define AZ_BENCHMARK_HOOK_ENV(TEST_ENV)
#define AZ_BENCHMARK_HOOK()
#endif // AZ_MONOLITHIC_BUILD
// These macros are needed to implement unit test hooks necessary for running AzUnitTests or AzBenchmarks.
//
/* For unit test modules that implement AzUnitTests and AzBenchmarkTests with either a custom environment for AzUnitTests or a custom environment class for AzBenchmarks
the follow use the overloaded 'IMPLEMENT_AZ_UNIT_TEST_HOOKS' macro
AZ_UNIT_TEST_HOOK(UNIT_TEST_ENV, BENCHMARK_ENV_CLASS)
// Implement unit test hooks without a custom AzUnitTest or AzBenchmark environment,
AZ_UNIT_TEST_HOOK(DEFAULT_UNIT_TEST_ENV);
// Implement unit test hooks with a custom AzUnitTest environment
AZ_UNIT_TEST_HOOK(new CustomEnvClass());
// Implement unit test hooks with a custom AzBenchmark environment class only
AZ_UNIT_TEST_HOOK(DEFAULT_UNIT_TEST_ENV, CustomBenchmarkEnvClass);
// Implement unit test hooks with a custom AzUnitTest environment and a custom AzBenchmark environment class
AZ_UNIT_TEST_HOOK(new CustomEnvClass(), CustomBenchmarkEnvClass);
*/
#define DEFAULT_UNIT_TEST_ENV AZ::Test::DefaultTestEnv()
#define AZ_UNIT_TEST_HOOK_1(_1) \
AZ_UNIT_TEST_HOOK_ENV(_1) \
AZ_BENCHMARK_HOOK() \
IMPLEMENT_TEST_EXECUTABLE_MAIN()
#define AZ_UNIT_TEST_HOOK_2(_1, _2) \
AZ_UNIT_TEST_HOOK_ENV(_1) \
AZ_BENCHMARK_HOOK_ENV(_2) \
IMPLEMENT_TEST_EXECUTABLE_MAIN()
#define AZ_UNIT_TEST_HOOK(...) AZ_MACRO_SPECIALIZE(AZ_UNIT_TEST_HOOK_, AZ_VA_NUM_ARGS(__VA_ARGS__), (__VA_ARGS__))
// Declares a visible external symbol which identifies an executable as containing tests
#define DECLARE_AZ_UNIT_TEST_MAIN() AZTEST_EXPORT int ContainsAzUnitTestMain() { return 1; }
// Attempts to invoke the unit test main function if appropriate flags are present,
// otherwise simply continues launch as normal.
#define INVOKE_AZ_UNIT_TEST_MAIN(...) \
do { \
AZ::Test::AzUnitTestMain unitTestMain({__VA_ARGS__}); \
if (unitTestMain.Run(argc, argv)) \
{ \
return unitTestMain.ReturnCode(); \
} \
} while (0); // safe multi-line macro - creates a single statement
// Some implementations use a commandLine rather than argc/argv
#define INVOKE_AZ_UNIT_TEST_MAIN_COMMAND_LINE(...) \
do { \
AZ::Test::AzUnitTestMain unitTestMain({__VA_ARGS__}); \
if (unitTestMain.Run(commandLine)) \
{ \
return unitTestMain.ReturnCode(); \
} \
} while (0); // safe multi-line macro - creates a single statement
// Avoid accidentally being managed by CryMemory, or problems with new/delete when
// AZ allocators are not ready or properly un/initialized.
#define AZ_TEST_CLASS_ALLOCATOR(Class_) \
void* operator new (size_t size) \
{ \
return AZ_OS_MALLOC(size, AZStd::alignment_of<Class_>::value); \
} \
void operator delete(void* ptr) \
{ \
AZ_OS_FREE(ptr); \
}
@@ -0,0 +1,74 @@
/*
* 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 <AzCore/UnitTest/UnitTest.h>
#include <gtest/gtest.h>
#include <stdarg.h>
namespace UnitTest
{
namespace Platform
{
void EnableVirtualConsoleProcessingForStdout();
bool TerminalSupportsColor();
}
static const char* GetAnsiColorCode(GTestColor color)
{
switch (color)
{
case COLOR_RED:
return "1";
case COLOR_GREEN:
return "2";
case COLOR_YELLOW:
return "3";
default:
return nullptr;
};
}
// Returns true if and only if Google Test should use colors in the output.
static bool ShouldUseColor(bool stdout_is_tty)
{
const char* const gtest_color = testing::GTEST_FLAG(color).c_str();
if (azstricmp(gtest_color, "auto") == 0)
{
// On non-Windows platforms, we rely on the TERM variable.
return stdout_is_tty && Platform::TerminalSupportsColor();
}
return azstricmp(gtest_color, "yes") == 0 || azstricmp(gtest_color, "true") == 0 || azstricmp(gtest_color, "t") == 0 || strcmp(gtest_color, "1") == 0;
}
void ColoredPrintf(GTestColor color, const char* fmt, ...)
{
va_list args;
va_start(args, fmt);
static const bool in_color_mode = ShouldUseColor(testing::internal::posix::IsATTY(testing::internal::posix::FileNo(stdout)) != 0);
const bool use_color = in_color_mode && (color != COLOR_DEFAULT);
if (!use_color)
{
vprintf(fmt, args);
va_end(args);
return;
}
Platform::EnableVirtualConsoleProcessingForStdout();
printf("\033[0;3%sm", GetAnsiColorCode(color));
vprintf(fmt, args);
printf("\033[m"); // Resets the terminal to default.
va_end(args);
}
}
@@ -0,0 +1,169 @@
/*
* 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 <AzTest/GemTestEnvironment.h>
#include <AzCore/UnitTest/UnitTest.h>
#include <AzCore/Asset/AssetManagerComponent.h>
#include <AzCore/Jobs/JobManagerComponent.h>
#include <AzCore/IO/Streamer/StreamerComponent.h>
#include <AzCore/Memory/MemoryComponent.h>
namespace AZ
{
namespace Test
{
// Helper function to avoid having duplicate components
template<typename T>
void AddComponentIfNotPresent(AZ::Entity* entity)
{
if (entity->FindComponent<T>() == nullptr)
{
entity->AddComponent(aznew T());
}
}
/// An application designed to be used in a GemTestEnvironment.
/// In order to facilitate testing components which are part of a gem, the GemTestApplication can be used to
/// load only the modules, components etc. which are required to test that gem.
class GemTestApplication
: public AZ::ComponentApplication
{
public:
// ComponentApplication
void SetSettingsRegistrySpecializations(SettingsRegistryInterface::Specializations& specializations) override
{
ComponentApplication::SetSettingsRegistrySpecializations(specializations);
specializations.Append("test");
specializations.Append("gemtest");
}
};
GemTestEnvironment::Parameters::~Parameters()
{
m_componentDescriptors.clear();
m_dynamicModulePaths.clear();
m_requiredComponents.clear();
}
GemTestEnvironment::GemTestEnvironment()
{
m_parameters = new Parameters;
}
void GemTestEnvironment::AddDynamicModulePaths(const AZStd::vector<AZStd::string>& dynamicModulePaths)
{
m_parameters->m_dynamicModulePaths.insert(m_parameters->m_dynamicModulePaths.end(),
dynamicModulePaths.begin(), dynamicModulePaths.end());
}
void GemTestEnvironment::AddComponentDescriptors(const AZStd::vector<AZ::ComponentDescriptor*>& componentDescriptors)
{
m_parameters->m_componentDescriptors.insert(m_parameters->m_componentDescriptors.end(),
componentDescriptors.begin(), componentDescriptors.end());
}
void GemTestEnvironment::AddRequiredComponents(const AZStd::vector<AZ::TypeId>& requiredComponents)
{
m_parameters->m_requiredComponents.insert(m_parameters->m_requiredComponents.end(),
requiredComponents.begin(), requiredComponents.end());
}
AZ::ComponentApplication* GemTestEnvironment::CreateApplicationInstance()
{
return aznew GemTestApplication;
}
void GemTestEnvironment::SetupEnvironment()
{
UnitTest::TraceBusHook::SetupEnvironment();
AZ::AllocatorInstance<AZ::SystemAllocator>::Create();
AddGemsAndComponents();
PreCreateApplication();
// Create the application.
m_application = CreateApplicationInstance();
AZ::ComponentApplication::Descriptor appDesc;
appDesc.m_useExistingAllocator = true;
appDesc.m_enableDrilling = false;
// Set up gems for loading.
for (const AZStd::string& dynamicModulePath : m_parameters->m_dynamicModulePaths)
{
AZ::DynamicModuleDescriptor dynamicModuleDescriptor;
dynamicModuleDescriptor.m_dynamicLibraryPath = dynamicModulePath;
appDesc.m_modules.push_back(dynamicModuleDescriptor);
}
// Create a system entity.
m_systemEntity = m_application->Create(appDesc);
for (AZ::ComponentDescriptor* descriptor : m_parameters->m_componentDescriptors)
{
m_application->RegisterComponentDescriptor(descriptor);
}
PostCreateApplication();
// Some applications (e.g. ToolsApplication) already add some of these components
// So making sure we don't duplicate them on the system entity.
AddComponentIfNotPresent<AZ::MemoryComponent>(m_systemEntity);
AddComponentIfNotPresent<AZ::AssetManagerComponent>(m_systemEntity);
AddComponentIfNotPresent<AZ::JobManagerComponent>(m_systemEntity);
AddComponentIfNotPresent<AZ::StreamerComponent>(m_systemEntity);
m_systemEntity->Init();
m_systemEntity->Activate();
PostSystemEntityActivate();
// Create a separate entity in order to activate this gem's required components. Note that this assumes
// any component dependencies are already satisfied either by the system entity or the entities which were
// created during the module loading above. It therefore does not do a dependency sort or use the full
// entity activation.
m_gemEntity = aznew GemTestEntity();
for (AZ::TypeId typeId : m_parameters->m_requiredComponents)
{
m_gemEntity->CreateComponent(typeId);
}
m_gemEntity->Init();
for (AZ::Component* component : m_gemEntity->GetComponents())
{
m_gemEntity->ActivateComponent(*component);
}
}
void GemTestEnvironment::TeardownEnvironment()
{
const AZ::Entity::ComponentArrayType& components = m_gemEntity->GetComponents();
for (auto itComponent = components.rbegin(); itComponent != components.rend(); ++itComponent)
{
m_gemEntity->DeactivateComponent(**itComponent);
}
delete m_gemEntity;
m_gemEntity = nullptr;
PreDestroyApplication();
m_application->Destroy();
delete m_application;
m_application = nullptr;
PostDestroyApplication();
delete m_parameters;
m_parameters = nullptr;
AZ::AllocatorInstance<AZ::SystemAllocator>::Destroy();
UnitTest::TraceBusHook::TeardownEnvironment();
}
} // namespace Test
} // namespace AZ
@@ -0,0 +1,99 @@
/*
* 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.
*
*/
#pragma once
#include <AzCore/Component/ComponentApplication.h>
#include <AzCore/UnitTest/UnitTest.h>
#include <AzTest/AzTest.h>
namespace AZ
{
namespace Test
{
/// A test environment which is intended to facilitate writing unit tests which require components from a gem.
class GemTestEnvironment
: public UnitTest::TraceBusHook
{
public:
GemTestEnvironment();
/// Adds paths for the dynamic modules which should be loaded.
/// These modules will be loaded prior to the setup of the gem which is the focus of the GemTestEnvironment,
/// so any other gems etc. which that gem depends on should be added here. The gem to be tested should not
/// be added here because it cannot be loaded using the usual module loading process, as that would result
/// in attempting to create the gem's environment a second time.
/// @param dynamicModulePaths Dynamic module paths to be added to the existing collection.
void AddDynamicModulePaths(const AZStd::vector<AZStd::string>& dynamicModulePaths);
/// Adds to the collection of component descriptors which should be registered during the environment setup.
/// Generally this will be the same as the descriptors which are registered in the gem's Module function,
/// or a subset of those if only certain components are required during testing.
/// @param componentDescriptors Component descriptors to be added to the existing collection.
void AddComponentDescriptors(const AZStd::vector<AZ::ComponentDescriptor*>& componentDescriptors);
/// Adds to the sorted list of components which should be activated during the environment setup.
/// Any required components, for example the gem's system component, should be added here. Dependency
/// sorting is not performed, so it is up to the caller to ensure that all dependencies are met and the
/// components are provided in a valid activation order.
/// @param requiredComponents Components to be appended to the existing collection of required components.
void AddRequiredComponents(const AZStd::vector<AZ::TypeId>& requiredComponents);
/// Allows derived environments to set up which gems, components etc the environment should load.
virtual void AddGemsAndComponents() {}
/// Allows derived environments to perform additional steps prior to creating the application.
virtual void PreCreateApplication() {}
/// Allows derived environments to perform additional steps after creating the application.
virtual void PostCreateApplication() {}
/// Allows derived environments to perform additional steps after activating the system entity.
virtual void PostSystemEntityActivate() {}
/// Allows derived environments to override to perform additional steps prior to destroying the application.
virtual void PreDestroyApplication() {}
/// Allows derived environments to override to perform additional steps after destroying the application.
virtual void PostDestroyApplication() {}
/// Allows derived environments to create a desired instance of the application (for example ToolsApplication).
virtual AZ::ComponentApplication* CreateApplicationInstance();
protected:
class Parameters
{
public:
~Parameters();
AZStd::vector<AZ::ComponentDescriptor*> m_componentDescriptors;
AZStd::vector<AZStd::string> m_dynamicModulePaths;
AZStd::vector<AZ::TypeId> m_requiredComponents;
};
class GemTestEntity :
public AZ::Entity
{
friend class GemTestEnvironment;
};
// ITestEnvironment
void SetupEnvironment() override;
void TeardownEnvironment() override;
private:
AZ::ComponentApplication* m_application;
AZ::Entity* m_systemEntity;
GemTestEntity* m_gemEntity;
Parameters* m_parameters;
};
} // namespace Test
} // namespace AZ
+72
View File
@@ -0,0 +1,72 @@
/*
* 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.
*
*/
#pragma once
#include <AzTest/AzTest.h>
#include <memory>
#include <string>
#include "Utils.h"
namespace AZ
{
namespace Test
{
const int INCORRECT_USAGE = 101;
const int LIB_NOT_FOUND = 102;
const int SYMBOL_NOT_FOUND = 103;
const int MAX_PRINT_MSG = 4096;
struct IFunctionHandle;
//! Handle to the a module/shared library
struct IModuleHandle
{
virtual ~IModuleHandle() = default;
//! Is the module handle valid (was it loaded successfully)?
virtual bool IsValid() = 0;
//! Retrieve a function from within the module
virtual std::shared_ptr<IFunctionHandle> GetFunction(const std::string& name) = 0;
};
//! Handle to a function within the module/shared library
struct IFunctionHandle
{
virtual ~IFunctionHandle() = default;
//! Is the function handle valid (was it found inside the module correctly)?
virtual bool IsValid() = 0;
//! call as a "main" function
virtual int operator()(int argc, char** argv) = 0;
//! call as simple function
virtual int operator()() = 0;
};
//! Platform implementation of AzTest scanner
class Platform
{
public:
bool SupportsWaitForDebugger();
void WaitForDebugger();
void SuppressPopupWindows();
std::shared_ptr<IModuleHandle> GetModule(const std::string& lib);
std::string GetModuleNameFromPath(const std::string& path);
void Printf(const char* format, ...);
AZ::EnvironmentInstance GetTestRunnerEnvironment();
};
Platform& GetPlatform();
} // Test
} // AZ
@@ -0,0 +1,47 @@
/*
* 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.
*
*/
#pragma once
#define AZ_TRAIT_AZTEST_ATTACH_RESULT_LISTENER 0
#define AZ_TRAIT_UNIT_TEST_ASSET_MANAGER_TEST_DEFAULT_TIMEOUT_SECS 5
#define AZ_TRAIT_UNIT_TEST_ENTITY_ID_GEN_TEST_COUNT 10000
#define AZ_TRAIT_UNIT_TEST_DILLER_TRIGGER_EVENT_COUNT 100000
#define AZ_TRAIT_UNIT_TEST_NAME_COUNT 1000
#define AZ_TRAIT_TEST_APPEND_ROOT_FOLDER_TO_PATH true
#define AZ_TRAIT_DISABLE_FAILED_ALLOCATOR_LEAK_DETECTION_TESTS true
#define AZ_TRAIT_DISABLE_FAILED_ALLOCATOR_MANAGER_TESTS true
#define AZ_TRAIT_DISABLE_FAILED_ASSET_MANAGER_TESTS true
#define AZ_TRAIT_DISABLE_FAILED_AUDIO_SYSTEM_TESTS true
#define AZ_TRAIT_DISABLE_FAILED_AUDIO_WWISE_TESTS true
#define AZ_TRAIT_DISABLE_FAILED_EMOTION_FX_TESTS true
#define AZ_TRAIT_DISABLE_FAILED_GAMELIFT_CLIENT_SESSION_TEST true
#define AZ_TRAIT_DISABLE_FAILED_GRADIENT_SIGNAL_TESTS true
#define AZ_TRAIT_DISABLE_FAILED_GRIDMATE_TESTS true
#define AZ_TRAIT_DISABLE_FAILED_JOB_BASIC_TESTS true
#define AZ_TRAIT_DISABLE_FAILED_MATH_TESTS true
#define AZ_TRAIT_DISABLE_FAILED_MERGESETTINGSFOLDER_CONFLICTINGSPECIALIZATIONS true
#define AZ_TRAIT_DISABLE_FAILED_MULTIPLAYER_GRIDMATE_TESTS true
#define AZ_TRAIT_DISABLE_FAILED_NETWORKING_TESTS true
#define AZ_TRAIT_DISABLE_FAILED_PHYSICS_TESTS true
#define AZ_TRAIT_DISABLE_FAILED_PROFILER_TEST true
#define AZ_TRAIT_DISABLE_FAILED_SAVE_DATA_TESTS true
#define AZ_TRAIT_DISABLE_FAILED_SERIALIZE_BASIC_TEST true
#define AZ_TRAIT_DISABLE_FAILED_STREAMER_TESTS true
#define AZ_TRAIT_DISABLE_FAILED_SURFACE_DATA_TESTS true
#define AZ_TRAIT_DISABLE_FAILED_SYSTEM_FILE_TESTS true
#define AZ_TRAIT_DISABLE_FAILED_TOUCH_BENDING_TESTS true
#define AZ_TRAIT_DISABLE_FAILED_VEGETATION_TESTS true
#define AZ_TRAIT_DISABLE_LOG_ALWAYS_FUZZ_TEST true
@@ -0,0 +1,14 @@
/*
* 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.
*
*/
#pragma once
#include <AzTest_Traits_Android.h>
@@ -0,0 +1,180 @@
/*
* 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 <dlfcn.h>
#include <iostream>
#include <AzTest/Platform.h>
#include <AzCore/Android/AndroidEnv.h>
#include <unistd.h>
#include <sys/resource.h>
#include <fstream>
//==============================================================================
bool FileExists(const std::string& filename)
{
return std::ifstream(filename).good();
}
//==============================================================================
class ModuleHandle
: public AZ::Test::IModuleHandle
{
public:
explicit ModuleHandle(const std::string& lib)
: m_libHandle(nullptr)
{
std::string libext = lib;
if (!AZ::Test::EndsWith(libext, ".so"))
{
libext += ".so";
}
std::cout << "Calling dlopen " << libext << std::endl;
m_libHandle = dlopen(libext.c_str(), RTLD_LAZY);
const char* err = dlerror();
std::cerr << " error: " << (err ? err : "<none>") << std::endl;
}
ModuleHandle(const ModuleHandle&) = delete;
ModuleHandle& operator=(const ModuleHandle&) = delete;
~ModuleHandle() override
{
if (m_libHandle)
{
dlclose(m_libHandle);
}
}
bool IsValid() override { return m_libHandle != nullptr; }
std::shared_ptr<AZ::Test::IFunctionHandle> GetFunction(const std::string& name) override;
private:
friend class FunctionHandle;
void* m_libHandle;
};
//==============================================================================
class FunctionHandle
: public AZ::Test::IFunctionHandle
{
public:
explicit FunctionHandle(ModuleHandle& module, const std::string& symbol)
: m_fn(nullptr)
{
m_fn = dlsym(module.m_libHandle, symbol.c_str());
}
FunctionHandle(const FunctionHandle&) = delete;
FunctionHandle& operator=(const FunctionHandle&) = delete;
~FunctionHandle() override = default;
int operator()(int argc, char** argv) override
{
using Fn = int(int, char**);
Fn* fn = reinterpret_cast<Fn*>(m_fn);
return (*fn)(argc, argv);
}
int operator()() override
{
using Fn = int();
Fn* fn = reinterpret_cast<Fn*>(m_fn);
return (*fn)();
}
bool IsValid() override { return m_fn != nullptr; }
private:
void* m_fn;
};
//==============================================================================
std::shared_ptr<AZ::Test::IFunctionHandle> ModuleHandle::GetFunction(const std::string& name)
{
return std::make_shared<FunctionHandle>(*this, name);
}
//==============================================================================
namespace AZ
{
namespace Test
{
Platform& GetPlatform()
{
static Platform s_platform;
return s_platform;
}
bool Platform::SupportsWaitForDebugger()
{
return false;
}
std::shared_ptr<IModuleHandle> Platform::GetModule(const std::string& lib)
{
return std::make_shared<ModuleHandle>(lib);
}
void Platform::WaitForDebugger()
{
std::cerr << "Platform does not support waiting for debugger." << std::endl;
}
void Platform::SuppressPopupWindows()
{
}
std::string Platform::GetModuleNameFromPath(const std::string& path)
{
size_t start = path.rfind('/');
if (start == std::string::npos)
{
start = 0;
}
size_t end = path.rfind('.');
return path.substr(start, end);
}
void Platform::Printf(const char* format, ...)
{
// Not currently supported
}
AZ::EnvironmentInstance Platform::GetTestRunnerEnvironment()
{
AZ::EnvironmentInstance inst = nullptr;
void* handle = dlopen("libAzTestRunner.so", RTLD_NOW);
using Fn = AZ::EnvironmentInstance();
Fn* fn = nullptr;
if (handle)
{
fn = reinterpret_cast<Fn*>(dlsym(handle, "GetTestRunnerEnvironment"));
}
if (fn)
{
inst = fn();
}
dlclose(handle);
return inst;
}
} // Test
} // AZ
@@ -0,0 +1,32 @@
/*
* 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 <stdlib.h>
#include <AzTest/Platform.h>
namespace AZ
{
namespace Test
{
ScopedAutoTempDirectory::ScopedAutoTempDirectory()
{
char tempDirectoryTemplate[] = "/sdcard/Android/data/com.lumberyard.tests/files/UnitTest-XXXXXX";
const char* tempDir = mkdtemp(tempDirectoryTemplate);
AZ_Error("AzTest", tempDir, "Unable to create temp directory %s", tempDirectoryTemplate);
memset(m_tempDirectory, '\0', sizeof(m_tempDirectory));
if (tempDir)
{
azstrncpy(m_tempDirectory, AZ::IO::MaxPathLength, tempDirectoryTemplate, strlen(tempDirectoryTemplate) + 1);
}
}
} // Test
} // AZ
@@ -0,0 +1,10 @@
#
# 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.
#
@@ -0,0 +1,18 @@
#
# 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.
#
set(FILES
../Common/UnixLike/AzTest/ColorizedOutput_UnixLike.cpp
ScopedAutoTempDirectory_Android.cpp
Platform_Android.cpp
AzTest_Traits_Platform.h
AzTest_Traits_Android.h
)
@@ -0,0 +1,28 @@
/*
* 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 <AzCore/base.h>
#include <gtest/gtest.h>
namespace UnitTest
{
namespace Platform
{
void EnableVirtualConsoleProcessingForStdout()
{
}
bool TerminalSupportsColor()
{
return false;
}
}
}
@@ -0,0 +1,35 @@
/*
* 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 <stdlib.h>
#include <AzTest/Platform.h>
namespace AZ
{
namespace Test
{
ScopedAutoTempDirectory::ScopedAutoTempDirectory()
{
}
ScopedAutoTempDirectory::~ScopedAutoTempDirectory()
{
}
const char* ScopedAutoTempDirectory::GetDirectory() const
{
AZ_Error("AzTest", false, "ScopedAutoTempDirectory not implemented on this platform.");
return nullptr;
}
} // Test
} // AZ
@@ -0,0 +1,107 @@
/*
* 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 "Platform.h"
#include <iostream>
class ModuleHandle
: public AZ::Test::IModuleHandle
{
public:
explicit ModuleHandle(const std::string&)
{
}
ModuleHandle(const ModuleHandle&) = delete;
ModuleHandle& operator=(const ModuleHandle&) = delete;
~ModuleHandle() override = default;
bool IsValid() override { return false; }
std::shared_ptr<AZ::Test::IFunctionHandle> GetFunction(const std::string& name) override
{
return {};
}
};
class FunctionHandle
: public AZ::Test::IFunctionHandle
{
public:
FunctionHandle(ModuleHandle&, const std::string&)
{
}
FunctionHandle(const FunctionHandle&) = delete;
FunctionHandle& operator=(const FunctionHandle&) = delete;
~FunctionHandle() override = default;
int operator()(int, char**) override
{
return -1;
}
int operator()() override
{
return -1;
}
bool IsValid() override { return false; }
};
namespace AZ
{
namespace Test
{
Platform& GetPlatform()
{
static Platform s_platform;
return s_platform;
}
bool Platform::SupportsWaitForDebugger()
{
return false;
}
std::shared_ptr<IModuleHandle> Platform::GetModule(const std::string& lib)
{
return {};
}
void Platform::WaitForDebugger()
{
std::cerr << "Platform does not support waiting for debugger." << std::endl;
}
void Platform::SuppressPopupWindows()
{
}
std::string Platform::GetModuleNameFromPath(const std::string& path)
{
return {};
}
void Platform::Printf(const char* format, ...)
{
// Not currently supported
}
AZ::EnvironmentInstance Platform::GetTestRunnerEnvironment()
{
// Not currently supported
return nullptr;
}
} // Test
} // AZ
@@ -0,0 +1,44 @@
/*
* 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 <AzCore/base.h>
#include <gtest/gtest.h>
namespace UnitTest
{
namespace Platform
{
void EnableVirtualConsoleProcessingForStdout()
{
// UnixLike tty doesn't need ansi escapes enabled for them
}
bool TerminalSupportsColor()
{
const char* const term = testing::internal::posix::GetEnv("TERM");
const bool term_supports_color = term && (
azstricmp(term, "xterm") == 0 ||
azstricmp(term, "xterm-color") == 0 ||
azstricmp(term, "xterm-256color") == 0 ||
azstricmp(term, "screen") == 0 ||
azstricmp(term, "screen-256color") == 0 ||
azstricmp(term, "tmux") == 0 ||
azstricmp(term, "tmux-256color") == 0 ||
azstricmp(term, "rxvt-unicode") == 0 ||
azstricmp(term, "rxvt-unicode-256color") == 0 ||
azstricmp(term, "linux") == 0 ||
azstricmp(term, "cygwin") == 0
);
return term_supports_color;
}
}
}
@@ -0,0 +1,34 @@
/*
* 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 <stdlib.h>
#include <AzTest/Platform.h>
namespace AZ
{
namespace Test
{
ScopedAutoTempDirectory::ScopedAutoTempDirectory()
{
auto tempDirRoot = ::testing::TempDir();
char tempDirectoryTemplate[AZ::IO::MaxPathLength] = { '\0' };
azsnprintf(tempDirectoryTemplate, AZ::IO::MaxPathLength, "%sUnitTest-XXXXXX", tempDirRoot.c_str());
const char* tempDir = mkdtemp(tempDirectoryTemplate);
AZ_Error("AzTest", tempDir, "Unable to create temp directory %s", tempDirectoryTemplate);
memset(m_tempDirectory, '\0', sizeof(m_tempDirectory));
if (tempDir)
{
azstrncpy(m_tempDirectory, AZ::IO::MaxPathLength, tempDirectoryTemplate, strlen(tempDirectoryTemplate) + 1);
}
}
} // Test
} // AZ
@@ -0,0 +1,35 @@
/*
* 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 <AzCore/PlatformIncl.h>
#include <ConsoleApi.h>
namespace UnitTest
{
namespace Platform
{
void EnableVirtualConsoleProcessingForStdout()
{
const HANDLE stdout_handle = GetStdHandle(STD_OUTPUT_HANDLE);
DWORD currentMode{};
#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
GetConsoleMode(stdout_handle, &currentMode);
SetConsoleMode(stdout_handle, currentMode | ENABLE_VIRTUAL_TERMINAL_PROCESSING);
#endif
}
bool TerminalSupportsColor()
{
return true;
}
}
}
@@ -0,0 +1,35 @@
/*
* 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.
*
*/
#pragma once
#define AZ_TRAIT_AZTEST_ATTACH_RESULT_LISTENER 0
#define AZ_TRAIT_UNIT_TEST_ASSET_MANAGER_TEST_DEFAULT_TIMEOUT_SECS 5
#define AZ_TRAIT_UNIT_TEST_ENTITY_ID_GEN_TEST_COUNT 10000
#define AZ_TRAIT_UNIT_TEST_DILLER_TRIGGER_EVENT_COUNT 100000
#define AZ_TRAIT_UNIT_TEST_NAME_COUNT 1000
#define AZ_TRAIT_DISABLE_ALL_SAVE_DATA_TESTS true
#define AZ_TRAIT_DISABLE_FAILED_ATOM_RPI_TESTS true
#define AZ_TRAIT_DISABLE_FAILED_ZERO_COLOR_CONVERSION_TEST true
#define AZ_TRAIT_DISABLE_FAILED_FRAMEWORK_TESTS true
#define AZ_TRAIT_DISABLE_FAILED_NETWORKING_TESTS true
#define AZ_TRAIT_DISABLE_FAILED_GRADIENT_SIGNAL_TESTS true
#define AZ_TRAIT_DISABLE_FAILED_MULTIPLAYER_GRIDMATE_TESTS true
#define AZ_TRAIT_DISABLE_FAILED_INPUT_TESTS true
#define AZ_TRAIT_DISABLE_FAILED_NATIVE_WINDOWS_TESTS true
#define AZ_TRAIT_DISABLE_FAILED_PROCESS_LAUNCHER_TESTS true
#define AZ_TRAIT_DISABLE_FAILED_EMOTION_FX_TESTS true
#define AZ_TRAIT_DISABLE_FAILED_DLL_TESTS true
#define AZ_TRAIT_DISABLE_FAILED_MODULE_TESTS true
#define AZ_TRAIT_DISABLE_FAILED_EMOTION_FX_EDITOR_TESTS true
@@ -0,0 +1,14 @@
/*
* 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.
*
*/
#pragma once
#include <AzTest_Traits_Linux.h>
@@ -0,0 +1,159 @@
/*
* 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 <dlfcn.h>
#include <iostream>
#include <AzTest/Platform.h>
class ModuleHandle
: public AZ::Test::IModuleHandle
{
public:
explicit ModuleHandle(const std::string& lib)
: m_libHandle(nullptr)
{
std::string libext = lib;
if (!AZ::Test::EndsWith(libext, ".so"))
{
libext += ".so";
}
m_libHandle = dlopen(libext.c_str(), RTLD_NOW);
const char* error = dlerror();
if (error)
{
std::cerr << "Fail to open shared library: " << libext << std::endl
<< "Error from dlopen(): " << error << std::endl;
}
}
ModuleHandle(const ModuleHandle&) = delete;
ModuleHandle& operator=(const ModuleHandle&) = delete;
~ModuleHandle() override
{
if (m_libHandle)
{
dlclose(m_libHandle);
}
}
bool IsValid() override { return m_libHandle != nullptr; }
std::shared_ptr<AZ::Test::IFunctionHandle> GetFunction(const std::string& name) override;
private:
friend class FunctionHandle;
void* m_libHandle;
};
class FunctionHandle
: public AZ::Test::IFunctionHandle
{
public:
explicit FunctionHandle(ModuleHandle& module, const std::string& symbol)
: m_fn(nullptr)
{
m_fn = dlsym(module.m_libHandle, symbol.c_str());
const char* error = dlerror();
if (error)
{
std::cerr << "Fail to open symbols file: " << symbol << std::endl
<< "Error from dlsym(): " << error << std::endl;
}
}
FunctionHandle(const FunctionHandle&) = delete;
FunctionHandle& operator=(const FunctionHandle&) = delete;
~FunctionHandle() override = default;
int operator()(int argc, char** argv) override
{
using Fn = int(int, char**);
Fn* fn = reinterpret_cast<Fn*>(m_fn);
return (*fn)(argc, argv);
}
int operator()() override
{
using Fn = int();
Fn* fn = reinterpret_cast<Fn*>(m_fn);
return (*fn)();
}
bool IsValid() override { return m_fn != nullptr; }
private:
void* m_fn;
};
std::shared_ptr<AZ::Test::IFunctionHandle> ModuleHandle::GetFunction(const std::string& name)
{
return std::make_shared<FunctionHandle>(*this, name);
}
namespace AZ
{
namespace Test
{
Platform& GetPlatform()
{
static Platform s_platform;
return s_platform;
}
bool Platform::SupportsWaitForDebugger()
{
return false;
}
std::shared_ptr<IModuleHandle> Platform::GetModule(const std::string& lib)
{
return std::make_shared<ModuleHandle>(lib);
}
void Platform::WaitForDebugger()
{
std::cerr << "Platform does not support waiting for debugger." << std::endl;
}
void Platform::SuppressPopupWindows()
{
}
std::string Platform::GetModuleNameFromPath(const std::string& path)
{
size_t start = path.rfind('/');
if (start == std::string::npos)
{
start = 0;
}
size_t end = path.rfind('.');
return path.substr(start, end);
}
void Platform::Printf(const char* format, ...)
{
// Not currently supported
}
AZ::EnvironmentInstance Platform::GetTestRunnerEnvironment()
{
// Not currently supported
return nullptr;
}
} // Test
} // AZ
@@ -0,0 +1,16 @@
#
# 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.
#
# Platform specific cmake file for configuring target compiler/link properties
# based on the active platform
# NOTE: functions in cmake are global, therefore adding functions to this file
# is being avoided to prevent overriding functions declared in other targets platfrom
# specific cmake files
@@ -0,0 +1,18 @@
#
# 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.
#
set(FILES
../Common/UnixLike/AzTest/ColorizedOutput_UnixLike.cpp
../Common/UnixLike/AzTest/ScopedAutoTempDirectory_UnixLike.cpp
Platform_Linux.cpp
AzTest_Traits_Platform.h
AzTest_Traits_Linux.h
)
@@ -0,0 +1,23 @@
/*
* 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.
*
*/
#pragma once
#define AZ_TRAIT_AZTEST_ATTACH_RESULT_LISTENER 0
#define AZ_TRAIT_UNIT_TEST_ASSET_MANAGER_TEST_DEFAULT_TIMEOUT_SECS 5
#define AZ_TRAIT_UNIT_TEST_ENTITY_ID_GEN_TEST_COUNT 10000
#define AZ_TRAIT_UNIT_TEST_DILLER_TRIGGER_EVENT_COUNT 100000
#define AZ_TRAIT_UNIT_TEST_NAME_COUNT 1000
#define AZ_TRAIT_DISABLE_ASSET_JOB_PARALLEL_TESTS true
#define AZ_TRAIT_DISABLE_ASSET_MANAGER_FLOOD_TEST true
#define AZ_TRAIT_DISABLE_ASSETCONTAINERDISABLETEST true
@@ -0,0 +1,14 @@
/*
* 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.
*
*/
#pragma once
#include <AzTest_Traits_Mac.h>
@@ -0,0 +1,185 @@
/*
* 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 <dlfcn.h>
#include <iostream>
#include <AzTest/Platform.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/sysctl.h>
class ModuleHandle
: public AZ::Test::IModuleHandle
{
public:
explicit ModuleHandle(const std::string& lib)
: m_libHandle(nullptr)
{
std::string libext = lib;
if (!AZ::Test::EndsWith(libext, ".dylib"))
{
libext += ".dylib";
}
m_libHandle = dlopen(libext.c_str(), RTLD_NOW);
const char* error = dlerror();
if (error)
{
std::cout << "Error from dlopen(): " << error << std::endl;
}
}
ModuleHandle(const ModuleHandle&) = delete;
ModuleHandle& operator=(const ModuleHandle&) = delete;
~ModuleHandle() override
{
if (m_libHandle)
{
dlclose(m_libHandle);
}
}
bool IsValid() override { return m_libHandle != nullptr; }
std::shared_ptr<AZ::Test::IFunctionHandle> GetFunction(const std::string& name) override;
private:
friend class FunctionHandle;
void* m_libHandle;
};
class FunctionHandle
: public AZ::Test::IFunctionHandle
{
public:
explicit FunctionHandle(ModuleHandle& module, const std::string& symbol)
: m_fn(nullptr)
{
m_fn = dlsym(module.m_libHandle, symbol.c_str());
const char* error = dlerror();
if (error)
{
std::cout << "Error from dlsym(): " << error << std::endl;
}
}
FunctionHandle(const FunctionHandle&) = delete;
FunctionHandle& operator=(const FunctionHandle&) = delete;
~FunctionHandle() override = default;
int operator()(int argc, char** argv) override
{
using Fn = int(int, char**);
Fn* fn = reinterpret_cast<Fn*>(m_fn);
return (*fn)(argc, argv);
}
int operator()() override
{
using Fn = int();
Fn* fn = reinterpret_cast<Fn*>(m_fn);
return (*fn)();
}
bool IsValid() override { return m_fn != nullptr; }
private:
void* m_fn;
};
std::shared_ptr<AZ::Test::IFunctionHandle> ModuleHandle::GetFunction(const std::string& name)
{
return std::make_shared<FunctionHandle>(*this, name);
}
namespace AZ
{
namespace Test
{
Platform& GetPlatform()
{
static Platform s_platform;
return s_platform;
}
bool Platform::SupportsWaitForDebugger()
{
return true;
}
std::shared_ptr<IModuleHandle> Platform::GetModule(const std::string& lib)
{
return std::make_shared<ModuleHandle>(lib);
}
void Platform::WaitForDebugger()
{
bool debuggerAttached = false;
// Apple Technical Q&A QA1361
// https://developer.apple.com/library/content/qa/qa1361/_index.html
while (!debuggerAttached)
{
const int managementInformationBaseNameLength = 4;
int managementInformationBaseName[managementInformationBaseNameLength];
struct kinfo_proc kernelInfo;
size_t kernelInfoSize = sizeof(kernelInfo);
// Initialize the flags as they are only set if sysctl succeeds.
kernelInfo.kp_proc.p_flag = 0;
// Initialize managementInformationBaseName, which tells sysctl the info we want,
// in this case we're looking for information about a specific process ID.
managementInformationBaseName[0] = CTL_KERN;
managementInformationBaseName[1] = KERN_PROC;
managementInformationBaseName[2] = KERN_PROC_PID;
managementInformationBaseName[3] = getpid();
sysctl(managementInformationBaseName, managementInformationBaseNameLength, &kernelInfo, &kernelInfoSize, nullptr, 0);
// We're being debugged if the P_TRACED flag is set.
debuggerAttached = ((kernelInfo.kp_proc.p_flag & P_TRACED) != 0);
}
}
void Platform::SuppressPopupWindows()
{
}
std::string Platform::GetModuleNameFromPath(const std::string& path)
{
size_t start = path.rfind('/');
if (start == std::string::npos)
{
start = 0;
}
size_t end = path.rfind('.');
return path.substr(start, end);
}
void Platform::Printf(const char* format, ...)
{
// Not currently supported
}
AZ::EnvironmentInstance Platform::GetTestRunnerEnvironment()
{
// Not currently supported
return nullptr;
}
} // Test
} // AZ
@@ -0,0 +1,16 @@
#
# 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.
#
# Platform specific cmake file for configuring target compiler/link properties
# based on the active platform
# NOTE: functions in cmake are global, therefore adding functions to this file
# is being avoided to prevent overriding functions declared in other targets platfrom
# specific cmake files
@@ -0,0 +1,17 @@
#
# 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.
#
set(FILES
../Common/UnixLike/AzTest/ColorizedOutput_UnixLike.cpp
Platform_Mac.cpp
AzTest_Traits_Platform.h
AzTest_Traits_Mac.h
)
@@ -0,0 +1,14 @@
/*
* 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.
*
*/
#pragma once
#include <AzTest_Traits_Windows.h>
@@ -0,0 +1,20 @@
/*
* 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.
*
*/
#pragma once
#define AZ_TRAIT_AZTEST_ATTACH_RESULT_LISTENER 0
// Unit Test traits ...
#define AZ_TRAIT_UNIT_TEST_ASSET_MANAGER_TEST_DEFAULT_TIMEOUT_SECS 5
#define AZ_TRAIT_UNIT_TEST_ENTITY_ID_GEN_TEST_COUNT 10000
#define AZ_TRAIT_UNIT_TEST_DILLER_TRIGGER_EVENT_COUNT 100000
#define AZ_TRAIT_UNIT_TEST_NAME_COUNT 1000
@@ -0,0 +1,167 @@
/*
* 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 <AzCore/PlatformIncl.h>
#include <string>
#include <iostream>
#include <AzTest/Platform.h>
//-------------------------------------------------------------------------------------------------
class ModuleHandle
: public AZ::Test::IModuleHandle
{
public:
explicit ModuleHandle(const std::string& lib)
: m_libHandle(NULL)
{
std::string libext = lib;
if (!AZ::Test::EndsWith(libext, ".dll"))
{
libext += ".dll";
}
m_libHandle = ::LoadLibraryA(libext.c_str()); // LoadLibrary conflicts with CryEngine code, so use LoadLibraryA
if (m_libHandle == NULL)
{
DWORD dw = ::GetLastError();
std::cerr << "FAILED to load library: " << libext << "; GetLastError() returned " << dw << std::endl;
}
}
ModuleHandle(const ModuleHandle&) = delete;
ModuleHandle& operator=(const ModuleHandle&) = delete;
~ModuleHandle() override
{
if (m_libHandle != NULL)
{
FreeLibrary(m_libHandle);
}
}
bool IsValid() override { return m_libHandle != NULL; }
std::shared_ptr<AZ::Test::IFunctionHandle> GetFunction(const std::string& name) override;
private:
friend class FunctionHandle;
HINSTANCE m_libHandle;
};
//-------------------------------------------------------------------------------------------------
class FunctionHandle
: public AZ::Test::IFunctionHandle
{
public:
explicit FunctionHandle(ModuleHandle& module, std::string symbol)
: m_proc(NULL)
{
m_proc = ::GetProcAddress(module.m_libHandle, symbol.c_str());
}
FunctionHandle(const FunctionHandle&) = delete;
FunctionHandle& operator=(const FunctionHandle&) = delete;
~FunctionHandle() override = default;
int operator()(int argc, char** argv) override
{
using Fn = int(int, char**);
Fn* fn = reinterpret_cast<Fn*>(m_proc);
return (*fn)(argc, argv);
}
int operator()() override
{
using Fn = int();
Fn* fn = reinterpret_cast<Fn*>(m_proc);
return (*fn)();
}
bool IsValid() override { return m_proc != NULL; }
private:
FARPROC m_proc;
};
//-------------------------------------------------------------------------------------------------
std::shared_ptr<AZ::Test::IFunctionHandle> ModuleHandle::GetFunction(const std::string& name)
{
return std::make_shared<FunctionHandle>(*this, name);
}
//-------------------------------------------------------------------------------------------------
namespace AZ
{
namespace Test
{
Platform& GetPlatform()
{
static Platform s_platform;
return s_platform;
}
bool Platform::SupportsWaitForDebugger()
{
return true;
}
std::shared_ptr<IModuleHandle> Platform::GetModule(const std::string& lib)
{
return std::make_shared<ModuleHandle>(lib);
}
void Platform::WaitForDebugger()
{
while (!::IsDebuggerPresent()) {}
}
void Platform::SuppressPopupWindows()
{
// use SetErrorMode to disable popup windows in case a required library cannot be found
DWORD errorMode = ::SetErrorMode(SEM_FAILCRITICALERRORS);
::SetErrorMode(errorMode | SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX | SEM_NOOPENFILEERRORBOX);
}
std::string Platform::GetModuleNameFromPath(const std::string& path)
{
size_t start = path.rfind('\\');
if (start == std::string::npos)
{
start = 0;
}
size_t end = path.rfind('.');
return path.substr(start, end);
}
void Platform::Printf(const char* format, ...)
{
char message[MAX_PRINT_MSG];
va_list mark;
va_start(mark, format);
azvsnprintf(message, MAX_PRINT_MSG, format, mark);
va_end(mark);
OutputDebugString(message);
}
AZ::EnvironmentInstance Platform::GetTestRunnerEnvironment()
{
// Not currently supported
return nullptr;
}
} // Test
} // AZ
@@ -0,0 +1,70 @@
/*
* 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 <stdlib.h>
#include <windows.h>
#include <sysinfoapi.h>
#include <fileapi.h>
#include <AzCore/IO/Path/Path.h>
#include <AzCore/std/functional.h>
#include <AzCore/IO/SystemFile.h>
#include <AzTest/Platform.h>
namespace AZ
{
namespace Test
{
ScopedAutoTempDirectory::ScopedAutoTempDirectory()
{
constexpr const DWORD bufferSize = static_cast<DWORD>(AZ::IO::MaxPathLength);
char tempDir[bufferSize] = {0};
GetTempPathA(bufferSize, tempDir);
char workingTempPathBuffer[bufferSize] = {'\0'};
int maxAttempts = 2000; // Prevent an infinite loop by setting an arbitrary maximum attempts at finding an available temp folder name
while (maxAttempts > 0)
{
// Use the system's tick count to base the folder name
DWORD currentTick = GetTickCount64();
azsnprintf(workingTempPathBuffer, bufferSize, "%sUnitTest-%X", tempDir, aznumeric_cast<unsigned int>(currentTick));
// Check if the requested directory name is available and re-generate if it already exists
bool exists = AZ::IO::SystemFile::Exists(workingTempPathBuffer);
if (exists)
{
Sleep(1);
maxAttempts--;
continue;
}
break;
}
AZ_Error("AzTest", maxAttempts > 0, "Unable to determine a temp directory");
if (maxAttempts > 0)
{
// Create the temp directory and track it for deletion
bool tempDirectoryCreated = AZ::IO::SystemFile::CreateDir(workingTempPathBuffer);
if (tempDirectoryCreated)
{
azstrncpy(m_tempDirectory, AZ::IO::MaxPathLength, workingTempPathBuffer, AZ::IO::MaxPathLength);
}
else
{
AZ_Error("AzTest", false, "Unable to create temp directory %s", workingTempPathBuffer);
}
}
}
} // Test
} // AZ
@@ -0,0 +1,16 @@
#
# 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.
#
# Platform specific cmake file for configuring target compiler/link properties
# based on the active platform
# NOTE: functions in cmake are global, therefore adding functions to this file
# is being avoided to prevent overriding functions declared in other targets platfrom
# specific cmake files
@@ -0,0 +1,18 @@
#
# 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.
#
set(FILES
../Common/WinAPI/AzTest/ColorizedOutput_WinAPI.cpp
Platform_Windows.cpp
ScopedAutoTempDirectory_Windows.cpp
AzTest_Traits_Platform.h
AzTest_Traits_Windows.h
)
@@ -0,0 +1,14 @@
/*
* 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.
*
*/
#pragma once
#include <AzTest_Traits_iOS.h>
@@ -0,0 +1,23 @@
/*
* 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.
*
*/
#pragma once
#define AZ_TRAIT_AZTEST_ATTACH_RESULT_LISTENER 0
#define AZ_TRAIT_UNIT_TEST_ASSET_MANAGER_TEST_DEFAULT_TIMEOUT_SECS 5
#define AZ_TRAIT_UNIT_TEST_ENTITY_ID_GEN_TEST_COUNT 10000
#define AZ_TRAIT_UNIT_TEST_DILLER_TRIGGER_EVENT_COUNT 100000
#define AZ_TRAIT_UNIT_TEST_NAME_COUNT 1000
#define AZ_TRAIT_DISABLE_ASSET_JOB_PARALLEL_TESTS true
#define AZ_TRAIT_DISABLE_ASSET_MANAGER_FLOOD_TEST true
#define AZ_TRAIT_DISABLE_ASSETCONTAINERDISABLETEST true
@@ -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 <dlfcn.h>
#include <iostream>
#include <AzTest/Platform.h>
#include <unistd.h>
#include <sys/resource.h>
#include <fstream>
class ModuleHandle
: public AZ::Test::IModuleHandle
{
public:
explicit ModuleHandle(const std::string& lib)
: m_libHandle(nullptr)
{
std::string libPath = lib + ".framework/" + lib;
std::cout << "Calling dlopen " << libPath << std::endl;
m_libHandle = dlopen(libPath.c_str(), RTLD_NOW);
const char* err = dlerror();
if (err)
{
std::cerr << "error: " << err << std::endl;
}
}
ModuleHandle(const ModuleHandle&) = delete;
ModuleHandle& operator=(const ModuleHandle&) = delete;
~ModuleHandle() override
{
if (m_libHandle)
{
dlclose(m_libHandle);
}
}
bool IsValid() override { return m_libHandle != nullptr; }
std::shared_ptr<AZ::Test::IFunctionHandle> GetFunction(const std::string& name) override;
private:
friend class FunctionHandle;
void* m_libHandle;
};
//==============================================================================
class FunctionHandle
: public AZ::Test::IFunctionHandle
{
public:
FunctionHandle(ModuleHandle& module, const std::string& symbol)
: m_fn(nullptr)
{
m_fn = dlsym(module.m_libHandle, symbol.c_str());
}
FunctionHandle(const FunctionHandle&) = delete;
FunctionHandle& operator=(const FunctionHandle&) = delete;
~FunctionHandle() override = default;
int operator()(int argc, char** argv) override
{
using Fn = int(int, char**);
Fn* fn = reinterpret_cast<Fn*>(m_fn);
return (*fn)(argc, argv);
}
int operator()() override
{
using Fn = int();
Fn* fn = reinterpret_cast<Fn*>(m_fn);
return (*fn)();
}
bool IsValid() override { return m_fn != nullptr; }
private:
void* m_fn;
};
//==============================================================================
std::shared_ptr<AZ::Test::IFunctionHandle> ModuleHandle::GetFunction(const std::string& name)
{
return std::make_shared<FunctionHandle>(*this, name);
}
//==============================================================================
namespace AZ
{
namespace Test
{
Platform& GetPlatform()
{
static Platform s_platform;
return s_platform;
}
bool Platform::SupportsWaitForDebugger()
{
return false;
}
std::shared_ptr<IModuleHandle> Platform::GetModule(const std::string& lib)
{
return std::make_shared<ModuleHandle>(lib);
}
void Platform::WaitForDebugger()
{
std::cerr << "Platform does not support waiting for debugger." << std::endl;
}
void Platform::SuppressPopupWindows()
{
}
std::string Platform::GetModuleNameFromPath(const std::string& path)
{
size_t start = path.rfind('/');
if (start == std::string::npos)
{
start = 0;
}
size_t end = path.size();
return path.substr(start, end);
}
void Platform::Printf([[maybe_unused]] const char* format, ...)
{
// Not currently supported
}
AZ::EnvironmentInstance Platform::GetTestRunnerEnvironment()
{
return nullptr;
}
} // Test
} // AZ
@@ -0,0 +1,10 @@
#
# 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.
#
@@ -0,0 +1,18 @@
#
# 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.
#
set(FILES
../Common/UnixLike/AzTest/ColorizedOutput_UnixLike.cpp
${common_dir}/Unimplemented/AzTest/ScopedAutoTempDirectory_Unimplemented.cpp
Platform_iOS.cpp
AzTest_Traits_Platform.h
AzTest_Traits_iOS.h
)
+239
View File
@@ -0,0 +1,239 @@
/*
* 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 "Utils.h"
#include <algorithm>
#include <cstring>
#include <AzCore/base.h>
#include <AzCore/std/functional.h>
#include <AzCore/IO/Path/Path.h>
#include <AzCore/IO/SystemFile.h>
#include <AzCore/StringFunc/StringFunc.h>
#include <AzCore/Utils/Utils.h>
namespace AZ
{
namespace Test
{
bool ContainsParameter(int argc, char** argv, const std::string& param)
{
int index = GetParameterIndex(argc, argv, param);
return index < 0 ? false : true;
}
void CopyParameters(int argc, char** target, char** source)
{
for (int i = 0; i < argc; i++)
{
const size_t dstSize = std::strlen(source[i]) + 1;
target[i] = new char[dstSize];
azstrcpy(target[i], dstSize, source[i]);
}
}
int GetParameterIndex(int argc, char** argv, const std::string& param)
{
for (int i = 0; i < argc; i++)
{
if (param == argv[i])
{
return i;
}
}
return -1;
}
std::vector<std::string> GetParameterList(int& argc, char** argv, const std::string& param, bool removeOnReturn)
{
std::vector<std::string> parameters;
int paramIndex = GetParameterIndex(argc, argv, param);
if (paramIndex > 0)
{
int index = paramIndex + 1;
while (index < argc && !StartsWith(argv[index], "-"))
{
parameters.push_back(std::string(argv[index]));
index++;
}
}
if (removeOnReturn)
{
RemoveParameters(argc, argv, paramIndex, paramIndex + (int)parameters.size());
}
return parameters;
}
std::string GetParameterValue(int& argc, char** argv, const std::string& param, bool removeOnReturn)
{
std::string value("");
int index = GetParameterIndex(argc, argv, param);
// Make sure we have a valid parameter index and value after the parameter index
if (index > 0 && index < (argc - 1))
{
value = argv[index + 1];
if (removeOnReturn)
{
RemoveParameters(argc, argv, index, index + 1);
}
}
return value;
}
void RemoveParameters(int& argc, char** argv, int startIndex, int endIndex)
{
// protect against invalid order of parameters
if (startIndex > endIndex)
{
return;
}
// constraint to valid range
endIndex = std::min(endIndex, argc - 1);
startIndex = std::max(startIndex, 0);
int numRemoved = 0;
int i = startIndex;
int j = endIndex + 1;
// copy all existing paramters
while (j < argc)
{
argv[i++] = argv[j++];
}
// null out all the remaining parameters and count how many
// were removed simultaneously
while (i < argc)
{
argv[i++] = nullptr;
++numRemoved;
}
argc -= numRemoved;
}
char** SplitCommandLine(int& size, char* const cmdLine)
{
std::vector<char*> tokens;
char* next_token = nullptr;
char* tok = azstrtok(cmdLine, 0, " ", &next_token);
while (tok != NULL)
{
tokens.push_back(tok);
tok = azstrtok(NULL, 0, " ", &next_token);
}
size = (int)tokens.size();
char** token_array = new char*[size];
for (size_t i = 0; i < size; i++)
{
const size_t dstSize = std::strlen(tokens[i]) + 1;
token_array[i] = new char[dstSize];
azstrcpy(token_array[i], dstSize, tokens[i]);
}
return token_array;
}
bool EndsWith(const std::string& s, const std::string& ending)
{
if (ending.length() > s.length())
{
return false;
}
return std::equal(ending.rbegin(), ending.rend(), s.rbegin());
}
bool StartsWith(const std::string& s, const std::string& beginning)
{
if (beginning.length() > s.length())
{
return false;
}
return std::equal(beginning.begin(), beginning.end(), s.begin());
}
AZStd::string GetCurrentExecutablePath()
{
char exeDirectory[AZ_MAX_PATH_LEN];
AZ::Utils::GetExecutableDirectory(exeDirectory, AZ_ARRAY_SIZE(exeDirectory));
AZStd::string executablePath = exeDirectory;
return executablePath;
}
AZStd::string GetEngineRootPath()
{
static const AZStd::string engineFile = AZ_CORRECT_FILESYSTEM_SEPARATOR_STRING "engineroot.txt";
AZStd::string currentPath = GetCurrentExecutablePath();
AZStd::string enginePath = currentPath + engineFile;
if (AZ::IO::SystemFile::Exists(enginePath.c_str()))
{
return currentPath;
}
size_t lastPathSeparator = currentPath.find_last_of(AZ_CORRECT_FILESYSTEM_SEPARATOR);
while (lastPathSeparator != AZStd::string::npos)
{
currentPath.erase(lastPathSeparator);
enginePath = currentPath + engineFile;
if (AZ::IO::SystemFile::Exists(enginePath.c_str()))
{
return currentPath;
}
lastPathSeparator = currentPath.find_last_of(AZ_CORRECT_FILESYSTEM_SEPARATOR);
}
return "";
}
AZStd::string ScopedAutoTempDirectory::Resolve(const char* path) const
{
AZStd::string resolved = AZStd::string::format("%s" AZ_CORRECT_FILESYSTEM_SEPARATOR_STRING "%s", m_tempDirectory, path);
return resolved;
}
const char* ScopedAutoTempDirectory::GetDirectory() const
{
return m_tempDirectory;
}
// Method to delete a folder recursively
static void DeleteFolderRecursive(const AZ::IO::PathView& path)
{
auto callback = [&path](AZStd::string_view filename, bool isFile) -> bool {
if (isFile)
{
auto filePath = AZ::IO::FixedMaxPath(path) / filename;
AZ::IO::SystemFile::Delete(filePath.c_str());
}
else
{
if (filename != "." && filename != "..")
{
auto folderPath = AZ::IO::FixedMaxPath(path) / filename;
DeleteFolderRecursive(folderPath);
}
}
return true;
};
auto searchPath = AZ::IO::FixedMaxPath(path) / "*";
AZ::IO::SystemFile::FindFiles(searchPath.c_str(), callback);
AZ::IO::SystemFile::DeleteDir(AZ::IO::FixedMaxPathString(path.Native()).c_str());
}
ScopedAutoTempDirectory::~ScopedAutoTempDirectory()
{
if (m_tempDirectory[0] != '\0')
{
// Delete the directory and its contents if a temp directory was created
AZ::IO::PathView pathView(m_tempDirectory);
DeleteFolderRecursive(pathView);
}
}
}
}
+77
View File
@@ -0,0 +1,77 @@
/*
* 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.
*
*/
#pragma once
#include <string>
#include <vector>
#include <AzCore/std/string/string.h>
#include <AzCore/IO/Path/Path.h>
#include <AzCore/Outcome/Outcome.h>
namespace AZ
{
namespace Test
{
/*! Command line parameter functions */
//! Check to see if the parameters includes the specified parameter
bool ContainsParameter(int argc, char** argv, const std::string& param);
//! Performs a deep copy of an array of char* parameters into a new array
//! New parameters are dynamically allocated
//! This does not set the size for the output array (assumed to be same as argc)
void CopyParameters(int argc, char** target, char** source);
//! Get index of the specified parameter
int GetParameterIndex(int argc, char** argv, const std::string& param);
//! Get multi-value parameter list based on a flag (and remove from argv if specified)
//! Returns a string vector for ease of use and cleanup
std::vector<std::string> GetParameterList(int& argc, char** argv, const std::string& param, bool removeOnReturn = false);
//! Get value of the specified parameter (and remove from argv if specified)
//! This assumes that the value is the next argument after the specified parameter
std::string GetParameterValue(int& argc, char** argv, const std::string& param, bool removeOnReturn = false);
//! Remove parameters and shift remaining down, startIndex and endIndex are inclusive
void RemoveParameters(int& argc, char** argv, int startIndex, int endIndex);
//! Split a C-string command line into an array of char* parameters (argv/argc)
//! Char* array is dynamically allocated
char** SplitCommandLine(int& size /* out */, char* const cmdLine);
/*! General string functions */
//! Check if a string has a specific ending substring
bool EndsWith(const std::string& s, const std::string& ending);
//! Check if a string has a specific beginning substring
bool StartsWith(const std::string& s, const std::string& beginning);
// Returns the path of the current executable (does not include the binary)
AZStd::string GetCurrentExecutablePath();
// Returns the path to the engine's root by cdup from the current execution path until engine.txt is found
AZStd::string GetEngineRootPath();
//! Provides a scoped object that will create a temporary operating-system specific folder on creation, and delete it and
//! its contents on destruction. This class is only available on host platforms (Windows, Mac, and Linux)
class ScopedAutoTempDirectory
{
public:
ScopedAutoTempDirectory();
~ScopedAutoTempDirectory();
const char* GetDirectory() const;
AZStd::string Resolve(const char* path) const;
private:
char m_tempDirectory[AZ::IO::MaxPathLength] = { '\0' };
};
}
}
@@ -0,0 +1,21 @@
#
# 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.
#
set(FILES
AzTest.h
AzTest.cpp
ColorizedOutput.cpp
Platform.h
Utils.h
Utils.cpp
GemTestEnvironment.cpp
GemTestEnvironment.h
)
+36
View File
@@ -0,0 +1,36 @@
#
# 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.
#
if(PAL_TRAIT_BUILD_TESTS_SUPPORTED)
ly_get_list_relative_pal_filename(pal_dir ${CMAKE_CURRENT_LIST_DIR}/AzTest/Platform/${PAL_PLATFORM_NAME})
ly_add_target(
NAME AzTest STATIC
NAMESPACE AZ
FILES_CMAKE
AzTest/aztest_files.cmake
${pal_dir}/platform_${PAL_PLATFORM_NAME_LOWERCASE}_files.cmake
INCLUDE_DIRECTORIES
PUBLIC
.
${pal_dir}
BUILD_DEPENDENCIES
PUBLIC
3rdParty::googletest::GMock
3rdParty::googletest::GTest
3rdParty::GoogleBenchmark
AZ::AzCore
PLATFORM_INCLUDE_FILES
${pal_dir}/platform_${PAL_PLATFORM_NAME_LOWERCASE}.cmake
)
endif()