forked from 0ad/0ad
Introduce CLogger::ScopedReplacement and FileLogger
Comments By: @sera, @vladislavbelov, @Stan Differential Revision: https://code.wildfiregames.com/D5167 This was SVN commit r27953.
This commit is contained in:
parent
63a4799f56
commit
949be94aab
@ -643,6 +643,14 @@ static void RunGameOrAtlas(const PS::span<const char* const> argv)
|
||||
{
|
||||
g_Shutdown = ShutdownType::None;
|
||||
|
||||
// Do this as soon as possible, because it chdirs and will mess up the error reporting if
|
||||
// anything crashes before the working directory is set.
|
||||
InitVfs(args);
|
||||
|
||||
// This must come after VFS init, which sets the current directory (required for finding our
|
||||
// output log files).
|
||||
FileLogger logger;
|
||||
|
||||
if (!Init(args, flags))
|
||||
{
|
||||
flags &= ~INIT_MODS;
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 2022 Wildfire Games.
|
||||
/* Copyright (C) 2023 Wildfire Games.
|
||||
* This file is part of 0 A.D.
|
||||
*
|
||||
* 0 A.D. is free software: you can redistribute it and/or modify
|
||||
@ -34,6 +34,7 @@
|
||||
#include <ctime>
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <utility>
|
||||
|
||||
#include <boost/algorithm/string/replace.hpp>
|
||||
|
||||
@ -310,31 +311,30 @@ void CLogger::CleanupRenderQueue()
|
||||
m_RenderMessages.erase(m_RenderMessages.begin(), m_RenderMessages.end() - RENDER_LIMIT);
|
||||
}
|
||||
|
||||
TestLogger::TestLogger()
|
||||
{
|
||||
m_OldLogger = g_Logger;
|
||||
g_Logger = new CLogger(&m_Stream, &blackHoleStream, false, false);
|
||||
}
|
||||
CLogger::ScopedReplacement::ScopedReplacement() :
|
||||
m_OldLogger{std::exchange(g_Logger, &m_ThisLogger)}
|
||||
{}
|
||||
|
||||
TestLogger::~TestLogger()
|
||||
CLogger::ScopedReplacement::ScopedReplacement(std::ostream* mainLog, std::ostream* interestingLog,
|
||||
const bool takeOwnership, const bool useDebugPrintf) :
|
||||
m_ThisLogger{mainLog, interestingLog, takeOwnership, useDebugPrintf},
|
||||
m_OldLogger{std::exchange(g_Logger, &m_ThisLogger)}
|
||||
{}
|
||||
|
||||
CLogger::ScopedReplacement::~ScopedReplacement()
|
||||
{
|
||||
delete g_Logger;
|
||||
g_Logger = m_OldLogger;
|
||||
}
|
||||
|
||||
TestLogger::TestLogger() :
|
||||
m_ScopedReplacement{&m_Stream, &blackHoleStream, false, false}
|
||||
{}
|
||||
|
||||
std::string TestLogger::GetOutput()
|
||||
{
|
||||
return m_Stream.str();
|
||||
}
|
||||
|
||||
TestStdoutLogger::TestStdoutLogger()
|
||||
{
|
||||
m_OldLogger = g_Logger;
|
||||
g_Logger = new CLogger(&std::cout, &blackHoleStream, false, false);
|
||||
}
|
||||
|
||||
TestStdoutLogger::~TestStdoutLogger()
|
||||
{
|
||||
delete g_Logger;
|
||||
g_Logger = m_OldLogger;
|
||||
}
|
||||
TestStdoutLogger::TestStdoutLogger() :
|
||||
m_ScopedReplacement{&std::cout, &blackHoleStream, false, false}
|
||||
{}
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 2022 Wildfire Games.
|
||||
/* Copyright (C) 2023 Wildfire Games.
|
||||
* This file is part of 0 A.D.
|
||||
*
|
||||
* 0 A.D. is free software: you can redistribute it and/or modify
|
||||
@ -47,6 +47,8 @@ class CLogger
|
||||
{
|
||||
NONCOPYABLE(CLogger);
|
||||
public:
|
||||
class ScopedReplacement;
|
||||
|
||||
enum ELogMethod
|
||||
{
|
||||
Normal,
|
||||
@ -109,19 +111,48 @@ private:
|
||||
};
|
||||
|
||||
/**
|
||||
* Helper class for unit tests - captures all log output while it is in scope,
|
||||
* and returns it as a single string.
|
||||
* Replaces `g_Logger` for as long as it's in scope.
|
||||
*/
|
||||
class CLogger::ScopedReplacement
|
||||
{
|
||||
public:
|
||||
ScopedReplacement();
|
||||
ScopedReplacement(std::ostream* mainLog, std::ostream* interestingLog, const bool takeOwnership,
|
||||
const bool useDebugPrintf);
|
||||
|
||||
ScopedReplacement(const ScopedReplacement&) = delete;
|
||||
ScopedReplacement& operator=(const ScopedReplacement&) = delete;
|
||||
ScopedReplacement(ScopedReplacement&&) = delete;
|
||||
ScopedReplacement& operator=(ScopedReplacement&&) = delete;
|
||||
~ScopedReplacement();
|
||||
|
||||
private:
|
||||
CLogger m_ThisLogger;
|
||||
CLogger* m_OldLogger;
|
||||
};
|
||||
|
||||
/**
|
||||
* This is used in the engine to log the messages to the logfiles.
|
||||
*/
|
||||
class FileLogger
|
||||
{
|
||||
private:
|
||||
CLogger::ScopedReplacement m_ScopedReplacement;
|
||||
};
|
||||
|
||||
/**
|
||||
* Helper class for unit tests - captures all log output, and returns it as a
|
||||
* single string.
|
||||
*/
|
||||
class TestLogger
|
||||
{
|
||||
NONCOPYABLE(TestLogger);
|
||||
public:
|
||||
TestLogger();
|
||||
~TestLogger();
|
||||
|
||||
std::string GetOutput();
|
||||
private:
|
||||
CLogger* m_OldLogger;
|
||||
std::stringstream m_Stream;
|
||||
CLogger::ScopedReplacement m_ScopedReplacement;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -129,12 +160,10 @@ private:
|
||||
*/
|
||||
class TestStdoutLogger
|
||||
{
|
||||
NONCOPYABLE(TestStdoutLogger);
|
||||
public:
|
||||
TestStdoutLogger();
|
||||
~TestStdoutLogger();
|
||||
private:
|
||||
CLogger* m_OldLogger;
|
||||
CLogger::ScopedReplacement m_ScopedReplacement;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -155,12 +155,10 @@ void MountMods(const Paths& paths, const std::vector<CStr>& mods)
|
||||
g_VFS->Mount(L"", modUserPath / "user" / "", userFlags, InDevelopmentCopy() ? 0 : priority + 1);
|
||||
}
|
||||
|
||||
static void InitVfs(const CmdLineArgs& args, int flags)
|
||||
void InitVfs(const CmdLineArgs& args)
|
||||
{
|
||||
TIMER(L"InitVfs");
|
||||
|
||||
const bool setup_error = (flags & INIT_HAVE_DISPLAY_ERROR) == 0;
|
||||
|
||||
const Paths paths(args);
|
||||
|
||||
OsPath logs(paths.Logs());
|
||||
@ -172,8 +170,7 @@ static void InitVfs(const CmdLineArgs& args, int flags)
|
||||
AppHooks hooks = {0};
|
||||
hooks.bundle_logs = psBundleLogs;
|
||||
hooks.get_log_dir = psLogDir;
|
||||
if (setup_error)
|
||||
hooks.display_error = psDisplayError;
|
||||
hooks.display_error = psDisplayError;
|
||||
app_hooks_update(&hooks);
|
||||
|
||||
g_VFS = CreateVfs();
|
||||
@ -407,7 +404,6 @@ from_config:
|
||||
CNetHost::Deinitialize();
|
||||
|
||||
// should be last, since the above use them
|
||||
SAFE_DELETE(g_Logger);
|
||||
delete &g_Profiler;
|
||||
delete &g_ProfileViewer;
|
||||
|
||||
@ -523,15 +519,6 @@ bool AutostartVisualReplay(const std::string& replayFile);
|
||||
|
||||
bool Init(const CmdLineArgs& args, int flags)
|
||||
{
|
||||
// Do this as soon as possible, because it chdirs
|
||||
// and will mess up the error reporting if anything
|
||||
// crashes before the working directory is set.
|
||||
InitVfs(args, flags);
|
||||
|
||||
// This must come after VFS init, which sets the current directory
|
||||
// (required for finding our output log files).
|
||||
g_Logger = new CLogger;
|
||||
|
||||
new CProfileViewer;
|
||||
new CProfileManager; // before any script code
|
||||
|
||||
|
@ -44,10 +44,6 @@ enum InitFlags
|
||||
// needed by map editor because it uses its own GUI.
|
||||
INIT_NO_GUI = 2,
|
||||
|
||||
// avoid setting display_error app hook
|
||||
// needed by map editor because it has its own wx error display
|
||||
INIT_HAVE_DISPLAY_ERROR = 4,
|
||||
|
||||
// initialize the mod folders from command line parameters
|
||||
INIT_MODS = 8,
|
||||
|
||||
@ -72,6 +68,8 @@ extern const std::vector<CStr>& GetMods(const CmdLineArgs& args, int flags);
|
||||
*/
|
||||
extern void MountMods(const Paths& paths, const std::vector<CStr>& mods);
|
||||
|
||||
void InitVfs(const CmdLineArgs& args);
|
||||
|
||||
/**
|
||||
* Returns true if successful, false if Init is aborted early (for instance if
|
||||
* mods changed, or if we are using -dumpSchema).
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 2022 Wildfire Games.
|
||||
/* Copyright (C) 2023 Wildfire Games.
|
||||
* This file is part of 0 A.D.
|
||||
*
|
||||
* 0 A.D. is free software: you can redistribute it and/or modify
|
||||
@ -43,6 +43,8 @@
|
||||
#include "renderer/Renderer.h"
|
||||
#include "renderer/SceneRenderer.h"
|
||||
|
||||
#include <optional>
|
||||
|
||||
#if OS_WIN
|
||||
// We don't include wutil header directly to prevent including Windows headers.
|
||||
extern void wutil_SetAppWindow(void* hwnd);
|
||||
@ -50,7 +52,8 @@ extern void wutil_SetAppWindow(void* hwnd);
|
||||
|
||||
namespace AtlasMessage
|
||||
{
|
||||
|
||||
namespace
|
||||
{
|
||||
InputProcessor g_Input;
|
||||
|
||||
// This keeps track of the last in-game user input.
|
||||
@ -60,12 +63,19 @@ double last_user_activity;
|
||||
// see comment in GameLoop.cpp about ah_display_error before using INIT_HAVE_DISPLAY_ERROR
|
||||
const int g_InitFlags = INIT_HAVE_VMODE | INIT_NO_GUI;
|
||||
|
||||
// This isn't used directly. When it's emplaced and when it's reset it does mutate `g_Logger`.
|
||||
std::optional<FileLogger> g_FileLogger;
|
||||
}
|
||||
|
||||
MESSAGEHANDLER(Init)
|
||||
{
|
||||
UNUSED2(msg);
|
||||
|
||||
g_Quickstart = true;
|
||||
|
||||
InitVfs(g_AtlasGameLoop->args);
|
||||
g_FileLogger.emplace();
|
||||
|
||||
// Mount mods if there are any specified as command line parameters
|
||||
if (!Init(g_AtlasGameLoop->args, g_InitFlags | INIT_MODS| INIT_MODS_PUBLIC))
|
||||
{
|
||||
@ -138,6 +148,7 @@ MESSAGEHANDLER(Shutdown)
|
||||
|
||||
int flags = 0;
|
||||
Shutdown(flags);
|
||||
g_FileLogger.reset();
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user