Refactor FlaxTests to run as Editor with all engine services initialized

This commit is contained in:
Wojtek Figat
2022-07-26 23:07:10 +02:00
parent ff1fba403d
commit bbb5b68e91
8 changed files with 94 additions and 26 deletions

View File

@@ -53,6 +53,7 @@ bool Editor::CheckProjectUpgrade()
int32 lastMajor = FLAXENGINE_VERSION_MAJOR;
int32 lastMinor = FLAXENGINE_VERSION_MINOR;
int32 lastBuild = FLAXENGINE_VERSION_BUILD;
if (FileSystem::FileExists(versionFilePath))
{
auto file = FileReadStream::Open(versionFilePath);
if (file)
@@ -77,10 +78,10 @@ bool Editor::CheckProjectUpgrade()
Delete(file);
}
else
{
LOG(Warning, "Missing version cache file");
}
}
else
{
LOG(Warning, "Missing version cache file");
}
// Check if project is in the old, deprecated layout
@@ -365,6 +366,12 @@ int32 Editor::LoadProduct()
Globals::ProductName = TEXT("Flax Editor");
Globals::CompanyName = TEXT("Flax");
#if FLAX_TESTS
// Flax Tests use auto-generated temporary project
CommandLine::Options.Project = Globals::TemporaryFolder / TEXT("Project");
CommandLine::Options.NewProject = true;
#endif
// Gather project directory from the command line
String projectPath = CommandLine::Options.Project.TrimTrailing();
const int32 startIndex = projectPath.StartsWith('\"') || projectPath.StartsWith('\'') ? 1 : 0;

View File

@@ -21,11 +21,13 @@
#include "Engine/Engine/Globals.h"
#include "Engine/Profiler/ProfilerCPU.h"
#include "Engine/Streaming/StreamingSettings.h"
#if FLAX_TESTS
#include "Engine/Platform/FileSystem.h"
#endif
class GameSettingsService : public EngineService
{
public:
GameSettingsService()
: EngineService(TEXT("GameSettings"), -70)
{
@@ -49,7 +51,7 @@ IMPLEMENT_ENGINE_SETTINGS_GETTER(StreamingSettings, Streaming);
#if !USE_EDITOR
#if PLATFORM_WINDOWS
IMPLEMENT_ENGINE_SETTINGS_GETTER(WindowsPlatformSettings, WindowsPlatform);
#elif PLATFORM_UWP
#elif PLATFORM_UWP
IMPLEMENT_ENGINE_SETTINGS_GETTER(UWPPlatformSettings, UWPPlatform);
#elif PLATFORM_LINUX
IMPLEMENT_ENGINE_SETTINGS_GETTER(LinuxPlatformSettings, LinuxPlatform);
@@ -83,6 +85,11 @@ GameSettings* GameSettings::Get()
// It may be missing in editor during dev but must be ready in the build game.
PROFILE_CPU();
const auto assetPath = Globals::ProjectContentFolder / TEXT("GameSettings.json");
#if FLAX_TESTS
// Silence missing GameSettings during test run before Editor creates it (not important)
if (!FileSystem::FileExists(assetPath))
return nullptr;
#endif
GameSettingsAsset = Content::LoadAsync<JsonAsset>(assetPath);
if (GameSettingsAsset == nullptr)
{

View File

@@ -84,6 +84,14 @@ int32 Engine::Main(const Char* cmdLine)
return -1;
}
#if FLAX_TESTS
// Configure engine for test running environment
CommandLine::Options.Headless = true;
CommandLine::Options.Null = true;
CommandLine::Options.Mute = true;
CommandLine::Options.Std = true;
#endif
if (Platform::Init())
{
Platform::Fatal(TEXT("Cannot init platform."));
@@ -102,6 +110,11 @@ int32 Engine::Main(const Char* cmdLine)
StringUtils::PathRemoveRelativeParts(Globals::StartupFolder);
FileSystem::NormalizePath(Globals::BinariesFolder);
FileSystem::GetSpecialFolderPath(SpecialFolder::Temporary, Globals::TemporaryFolder);
if (Globals::TemporaryFolder.IsEmpty())
Platform::Fatal(TEXT("Failed to gather temporary folder directory."));
Globals::TemporaryFolder /= Guid::New().ToString(Guid::FormatType::D);
// Load game info or project info
{
const int32 result = Application::LoadProduct();
@@ -512,12 +525,6 @@ void EngineImpl::InitLog()
void EngineImpl::InitPaths()
{
// Prepare temp folder path
FileSystem::GetSpecialFolderPath(SpecialFolder::Temporary, Globals::TemporaryFolder);
if (Globals::TemporaryFolder.IsEmpty())
Platform::Fatal(TEXT("Failed to gather temporary folder directory."));
Globals::TemporaryFolder /= Guid::New().ToString(Guid::FormatType::D);
// Cache other global paths
FileSystem::GetSpecialFolderPath(SpecialFolder::LocalAppData, Globals::ProductLocalFolder);
if (Globals::ProductLocalFolder.IsEmpty())
@@ -551,7 +558,7 @@ void EngineImpl::InitPaths()
if (!Globals::StartupFolder.IsANSI())
Platform::Fatal(TEXT("Cannot start application in directory which name contains non-ANSI characters."));
#if !PLATFORM_SWITCH
#if !PLATFORM_SWITCH && !FLAX_TESTS
// Setup directories
if (FileSystem::DirectoryExists(Globals::TemporaryFolder))
FileSystem::DeleteDirectory(Globals::TemporaryFolder);

View File

@@ -27,8 +27,17 @@ __declspec(dllexport) int32 AmdPowerXpressRequestHighPerformance = 1;
extern LONG CALLBACK SehExceptionHandler(EXCEPTION_POINTERS* ep);
#if FLAX_TESTS
int main(int argc, char* argv[])
#else
int APIENTRY wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow)
#endif
{
#if FLAX_TESTS
HINSTANCE hInstance = GetModuleHandle(NULL);
LPTSTR lpCmdLine = GetCommandLineW();
#endif
#ifdef USE_VS_MEM_LEAKS_CHECK
// Memory leaks detect inside VS
int flag = _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG);

View File

@@ -2,13 +2,46 @@
#if PLATFORM_WINDOWS || PLATFORM_LINUX || PLATFORM_MAC
#include "Engine/Core/Log.h"
#include "Engine/Engine/Engine.h"
#include "Engine/Engine/EngineService.h"
#include "Engine/Scripting/Scripting.h"
#include "Editor/Scripting/ScriptsBuilder.h"
#define CATCH_CONFIG_RUNNER
#include <ThirdParty/catch2/catch.hpp>
int main(int argc, char* argv[])
class TestsRunnerService : public EngineService
{
int result = Catch::Session().run(argc, argv);
return result;
public:
TestsRunnerService()
: EngineService(TEXT("TestsRunnerService"), 10000)
{
}
void Update() override;
};
TestsRunnerService TestsRunnerServiceInstance;
void TestsRunnerService::Update()
{
// Wait for Editor to be ready for running tests (eg. scripting loaded)
if (!ScriptsBuilder::IsReady() ||
!Scripting::IsEveryAssemblyLoaded() ||
!Scripting::HasGameModulesLoaded())
return;
// Runs tests
Log::Logger::WriteFloor();
LOG(Info, "Running Flax Tests...");
const int result = Catch::Session().run();
if (result == 0)
LOG(Info, "Result: {0}", result);
else
LOG(Error, "Result: {0}", result);
Log::Logger::WriteFloor();
Engine::RequestExit(result);
}
#endif

View File

@@ -2,6 +2,7 @@
using System.Collections.Generic;
using Flax.Build;
using Flax.Build.NativeCpp;
/// <summary>
/// Engine tests module.
@@ -14,6 +15,15 @@ public class Tests : EngineModule
Deploy = false;
}
/// <inheritdoc />
public override void Setup(BuildOptions options)
{
base.Setup(options);
options.PrivateDependencies.Add("Content");
options.PrivateDependencies.Add("Level");
}
/// <inheritdoc />
public override void GetFilesToDeploy(List<string> files)
{

View File

@@ -1,7 +1,6 @@
// Copyright (c) 2012-2022 Wojciech Figat. All rights reserved.
using System;
using System.IO;
using System.Linq;
using Flax.Build;
using Flax.Build.NativeCpp;
@@ -9,7 +8,7 @@ using Flax.Build.NativeCpp;
/// <summary>
/// Target that builds standalone, native tests.
/// </summary>
public class FlaxTestsTarget : EngineTarget
public class FlaxTestsTarget : FlaxEditor
{
/// <inheritdoc />
public override void Init()
@@ -35,8 +34,9 @@ public class FlaxTestsTarget : EngineTarget
{
TargetConfiguration.Development,
};
GlobalDefinitions.Add("FLAX_TESTS");
Win32ResourceFile = null;
Modules.Remove("Main");
Modules.Add("Tests");
}
@@ -45,13 +45,8 @@ public class FlaxTestsTarget : EngineTarget
{
base.SetupTargetEnvironment(options);
// Produce console program
options.LinkEnv.LinkAsConsoleProgram = true;
// Setup output folder for Test binaries
var platformName = options.Platform.Target.ToString();
var architectureName = options.Architecture.ToString();
var configurationName = options.Configuration.ToString();
options.OutputFolder = Path.Combine(options.WorkingDirectory, "Binaries", "Tests", platformName, architectureName, configurationName);
}
/// <inheritdoc />