diff --git a/source/graphics/MaterialManager.cpp b/source/graphics/MaterialManager.cpp index 362f5f0d7c..19e40852f9 100644 --- a/source/graphics/MaterialManager.cpp +++ b/source/graphics/MaterialManager.cpp @@ -1,4 +1,4 @@ -/* Copyright (C) 2022 Wildfire Games. +/* Copyright (C) 2024 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -37,8 +37,11 @@ CMaterialManager::CMaterialManager() CFG_GET_VAL("materialmgr.quality", qualityLevel); qualityLevel = Clamp(qualityLevel, 0.0f, 10.0f); - if (VfsDirectoryExists(L"art/materials/") && !CXeromyces::AddValidator(g_VFS, "material", "art/materials/material.rng")) + if (VfsDirectoryExists(L"art/materials/") && + !g_Xeromyces.AddValidator(g_VFS, "material", "art/materials/material.rng")) + { LOGERROR("CMaterialManager: failed to load grammar file 'art/materials/material.rng'"); + } } CMaterial CMaterialManager::LoadMaterial(const VfsPath& pathname) diff --git a/source/graphics/MiniMapTexture.cpp b/source/graphics/MiniMapTexture.cpp index 13a138df5f..f729d6e949 100644 --- a/source/graphics/MiniMapTexture.cpp +++ b/source/graphics/MiniMapTexture.cpp @@ -197,7 +197,7 @@ CMiniMapTexture::CMiniMapTexture(Renderer::Backend::IDevice* device, CSimulation m_InstanceVertexArray(Renderer::Backend::IBuffer::Type::VERTEX, Renderer::Backend::IBuffer::Usage::TRANSFER_DST) { // Register Relax NG validator. - CXeromyces::AddValidator(g_VFS, "pathfinder", "simulation/data/pathfinder.rng"); + g_Xeromyces.AddValidator(g_VFS, "pathfinder", "simulation/data/pathfinder.rng"); m_ShallowPassageHeight = GetShallowPassageHeight(); diff --git a/source/graphics/ObjectManager.cpp b/source/graphics/ObjectManager.cpp index cb32804040..51c12dbe14 100644 --- a/source/graphics/ObjectManager.cpp +++ b/source/graphics/ObjectManager.cpp @@ -1,4 +1,4 @@ -/* Copyright (C) 2021 Wildfire Games. +/* Copyright (C) 2024 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -54,7 +54,7 @@ CObjectManager::CObjectManager(CMeshManager& meshManager, CSkeletonAnimManager& m_QualityHook = std::make_unique(g_ConfigDB.RegisterHookAndCall("max_actor_quality", [this]() { ActorQualityChanged(); })); m_VariantDiversityHook = std::make_unique(g_ConfigDB.RegisterHookAndCall("variant_diversity", [this]() { VariantDiversityChanged(); })); - if (!CXeromyces::AddValidator(g_VFS, "actor", "art/actors/actor.rng")) + if (!g_Xeromyces.AddValidator(g_VFS, "actor", "art/actors/actor.rng")) LOGERROR("CObjectManager: failed to load actor grammar file 'art/actors/actor.rng'"); } diff --git a/source/graphics/ShaderManager.cpp b/source/graphics/ShaderManager.cpp index ba72f7814f..c763004223 100644 --- a/source/graphics/ShaderManager.cpp +++ b/source/graphics/ShaderManager.cpp @@ -52,7 +52,7 @@ CShaderManager::CShaderManager(Renderer::Backend::IDevice* device) { TIMER_ACCRUE(tc_ShaderValidation); - if (!CXeromyces::AddValidator(g_VFS, "shader", "shaders/program.rng")) + if (!g_Xeromyces.AddValidator(g_VFS, "shader", "shaders/program.rng")) LOGERROR("CShaderManager: failed to load grammar shaders/program.rng"); } #endif diff --git a/source/graphics/TerrainTextureManager.cpp b/source/graphics/TerrainTextureManager.cpp index f7fcfff6c8..b7b1e46dbf 100644 --- a/source/graphics/TerrainTextureManager.cpp +++ b/source/graphics/TerrainTextureManager.cpp @@ -1,4 +1,4 @@ -/* Copyright (C) 2023 Wildfire Games. +/* Copyright (C) 2024 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -40,9 +40,9 @@ CTerrainTextureManager::CTerrainTextureManager(Renderer::Backend::IDevice* devic { if (!VfsDirectoryExists(L"art/terrains/")) return; - if (!CXeromyces::AddValidator(g_VFS, "terrain", "art/terrains/terrain.rng")) + if (!g_Xeromyces.AddValidator(g_VFS, "terrain", "art/terrains/terrain.rng")) LOGERROR("CTerrainTextureManager: failed to load grammar file 'art/terrains/terrain.rng'"); - if (!CXeromyces::AddValidator(g_VFS, "terrain_texture", "art/terrains/terrain_texture.rng")) + if (!g_Xeromyces.AddValidator(g_VFS, "terrain_texture", "art/terrains/terrain_texture.rng")) LOGERROR("CTerrainTextureManager: failed to load grammar file 'art/terrains/terrain_texture.rng'"); } diff --git a/source/graphics/tests/test_MapGenerator.h b/source/graphics/tests/test_MapGenerator.h index 2e13886336..bf29f1e006 100644 --- a/source/graphics/tests/test_MapGenerator.h +++ b/source/graphics/tests/test_MapGenerator.h @@ -31,17 +31,16 @@ public: g_VFS = CreateVfs(); g_VFS->Mount(L"", DataDir() / "mods" / "mod" / "", VFS_MOUNT_MUST_EXIST); g_VFS->Mount(L"", DataDir() / "mods" / "public" / "", VFS_MOUNT_MUST_EXIST, 1); // ignore directory-not-found errors - CXeromyces::Startup(); } void tearDown() { - CXeromyces::Terminate(); g_VFS.reset(); } void test_mapgen_scripts() { + CXeromycesEngine xeromycesEngine; if (!VfsDirectoryExists(L"maps/random/tests/")) { debug_printf("Skipping map generator tests (can't find binaries/data/mods/public/maps/random/tests/)\n"); diff --git a/source/graphics/tests/test_Model.h b/source/graphics/tests/test_Model.h index 9afed15b73..c6ae1846bc 100644 --- a/source/graphics/tests/test_Model.h +++ b/source/graphics/tests/test_Model.h @@ -42,6 +42,7 @@ #include "scriptinterface/ScriptInterface.h" #include "simulation2/Simulation2.h" +#include #include #include @@ -100,6 +101,7 @@ constexpr std::string_view TEST_ACTOR_WITH_SHADOWS_XML{R"( m_XeromycesEngine; OsPath m_ModPath; OsPath m_CachePath; std::unique_ptr m_Viewer; @@ -112,7 +114,7 @@ public: CConfigDB::Initialise(); CConfigDB::Instance()->SetValueString(CFG_SYSTEM, "rendererbackend", "dummy"); - CXeromyces::Startup(); + m_XeromycesEngine.emplace(); TestLogger logger; @@ -152,7 +154,7 @@ public: m_Viewer.reset(); g_VideoMode.Shutdown(); - CXeromyces::Terminate(); + m_XeromycesEngine.reset(); CConfigDB::Shutdown(); g_VFS.reset(); diff --git a/source/graphics/tests/test_TextureManager.h b/source/graphics/tests/test_TextureManager.h index c4461bd9b2..64d6dd6c3c 100644 --- a/source/graphics/tests/test_TextureManager.h +++ b/source/graphics/tests/test_TextureManager.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2022 Wildfire Games. +/* Copyright (C) 2024 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -25,10 +25,13 @@ #include "ps/XML/Xeromyces.h" #include "renderer/backend/dummy/Device.h" +#include + class TestTextureManager : public CxxTest::TestSuite { PIVFS m_VFS; std::unique_ptr m_Device; + std::optional m_XeromycesEngine; public: @@ -42,14 +45,14 @@ public: TS_ASSERT_OK(m_VFS->Mount(L"", DataDir() / "mods" / "_test.tex" / "", VFS_MOUNT_MUST_EXIST)); TS_ASSERT_OK(m_VFS->Mount(L"cache/", DataDir() / "_testcache" / "", 0, VFS_MAX_PRIORITY)); - CXeromyces::Startup(); + m_XeromycesEngine.emplace(); m_Device = std::make_unique(); } void tearDown() { - CXeromyces::Terminate(); + m_XeromycesEngine.reset(); m_VFS.reset(); DeleteDirectory(DataDir()/"_testcache"); diff --git a/source/gui/GUIManager.cpp b/source/gui/GUIManager.cpp index 497d02f3d2..8399b4b328 100644 --- a/source/gui/GUIManager.cpp +++ b/source/gui/GUIManager.cpp @@ -76,9 +76,9 @@ CGUIManager::CGUIManager(ScriptContext& scriptContext, ScriptInterface& scriptIn m_ScriptInterface.SetCallbackData(this); m_ScriptInterface.LoadGlobalScripts(); - if (!CXeromyces::AddValidator(g_VFS, "gui_page", "gui/gui_page.rng")) + if (!g_Xeromyces.AddValidator(g_VFS, "gui_page", "gui/gui_page.rng")) LOGERROR("CGUIManager: failed to load GUI page grammar file 'gui/gui_page.rng'"); - if (!CXeromyces::AddValidator(g_VFS, "gui", "gui/gui.rng")) + if (!g_Xeromyces.AddValidator(g_VFS, "gui", "gui/gui.rng")) LOGERROR("CGUIManager: failed to load GUI XML grammar file 'gui/gui.rng'"); RegisterFileReloadFunc(ReloadChangedFileCB, this); diff --git a/source/gui/tests/test_CGUIText.h b/source/gui/tests/test_CGUIText.h index 464934bb4b..dd779c61ad 100644 --- a/source/gui/tests/test_CGUIText.h +++ b/source/gui/tests/test_CGUIText.h @@ -32,9 +32,11 @@ #include #include +#include class TestCGUIText : public CxxTest::TestSuite { + std::optional m_XeromycesEngine; CProfileViewer* m_Viewer = nullptr; CRenderer* m_Renderer = nullptr; @@ -45,7 +47,7 @@ public: TS_ASSERT_OK(g_VFS->Mount(L"", DataDir() / "mods" / "_test.minimal" / "", VFS_MOUNT_MUST_EXIST)); TS_ASSERT_OK(g_VFS->Mount(L"cache", DataDir() / "_testcache" / "", 0, VFS_MAX_PRIORITY)); - CXeromyces::Startup(); + m_XeromycesEngine.emplace(); // The renderer spews messages. TestLogger logger; @@ -66,7 +68,7 @@ public: delete m_Viewer; g_VideoMode.Shutdown(); CConfigDB::Shutdown(); - CXeromyces::Terminate(); + m_XeromycesEngine.reset(); g_VFS.reset(); DeleteDirectory(DataDir() / "_testcache"); } diff --git a/source/gui/tests/test_GUISetting.h b/source/gui/tests/test_GUISetting.h index e597d6fe6c..b1f1355640 100644 --- a/source/gui/tests/test_GUISetting.h +++ b/source/gui/tests/test_GUISetting.h @@ -33,10 +33,12 @@ #include "scriptinterface/ScriptInterface.h" #include +#include #include class TestGUISetting : public CxxTest::TestSuite { + std::optional m_XeromycesEngine; std::unique_ptr m_Viewer; std::unique_ptr m_Renderer; @@ -55,7 +57,7 @@ public: TS_ASSERT_OK(g_VFS->Mount(L"", DataDir() / "mods" / "_test.minimal" / "", VFS_MOUNT_MUST_EXIST)); TS_ASSERT_OK(g_VFS->Mount(L"cache", DataDir() / "_testcache" / "", 0, VFS_MAX_PRIORITY)); - CXeromyces::Startup(); + m_XeromycesEngine.emplace(); // The renderer spews messages. TestLogger logger; @@ -76,7 +78,7 @@ public: m_Viewer.reset(); g_VideoMode.Shutdown(); CConfigDB::Shutdown(); - CXeromyces::Terminate(); + m_XeromycesEngine.reset(); g_VFS.reset(); DeleteDirectory(DataDir() / "_testcache"); } diff --git a/source/gui/tests/test_GuiManager.h b/source/gui/tests/test_GuiManager.h index 9a51c3c577..17e9823ebb 100644 --- a/source/gui/tests/test_GuiManager.h +++ b/source/gui/tests/test_GuiManager.h @@ -38,6 +38,7 @@ class TestGuiManager : public CxxTest::TestSuite { std::unique_ptr configDB; + std::optional xeromycesEngine; std::optional scriptInterface; public: @@ -49,7 +50,7 @@ public: configDB = std::make_unique(); - CXeromyces::Startup(); + xeromycesEngine.emplace(); scriptInterface.emplace("Engine", "GUIManager", *g_ScriptContext); g_GUI = new CGUIManager{*g_ScriptContext, *scriptInterface}; @@ -59,7 +60,7 @@ public: { delete g_GUI; scriptInterface.reset(); - CXeromyces::Terminate(); + xeromycesEngine.reset(); configDB.reset(); g_VFS.reset(); DeleteDirectory(DataDir()/"_testcache"); diff --git a/source/main.cpp b/source/main.cpp index 39ae9084e8..4885198c10 100644 --- a/source/main.cpp +++ b/source/main.cpp @@ -573,16 +573,13 @@ static void RunGameOrAtlas(const PS::span argv) // We need to initialize SpiderMonkey and libxml2 in the main thread before // any thread uses them. So initialize them here before we might run Atlas. ScriptEngine scriptEngine; - CXeromyces::Startup(); + CXeromycesEngine xeromycesEngine; // Initialise the global task manager at this point (JS & Profiler2 are set up). Threading::TaskManager::Initialise(); if (ATLAS_RunIfOnCmdLine(args, false)) - { - CXeromyces::Terminate(); return; - } if (isNonVisualReplay) { @@ -603,8 +600,6 @@ static void RunGameOrAtlas(const PS::span argv) } g_VFS.reset(); - - CXeromyces::Terminate(); return; } @@ -629,8 +624,6 @@ static void RunGameOrAtlas(const PS::span argv) builder.AddBaseMod(paths.RData()/"mods"/mods[i]); builder.Build(zip, args.Has("archivebuild-compress")); - - CXeromyces::Terminate(); return; } @@ -728,7 +721,6 @@ static void RunGameOrAtlas(const PS::span argv) #endif Threading::TaskManager::Instance().ClearQueue(); - CXeromyces::Terminate(); } #if OS_ANDROID diff --git a/source/network/tests/test_Net.h b/source/network/tests/test_Net.h index 7155a4e738..9b126f06eb 100644 --- a/source/network/tests/test_Net.h +++ b/source/network/tests/test_Net.h @@ -34,15 +34,19 @@ #include "simulation2/Simulation2.h" #include "simulation2/system/TurnManager.h" +#include + class TestNetComms : public CxxTest::TestSuite { + std::optional xeromycesEngine; + public: void setUp() { g_VFS = CreateVfs(); TS_ASSERT_OK(g_VFS->Mount(L"", DataDir() / "mods" / "public" / "", VFS_MOUNT_MUST_EXIST)); TS_ASSERT_OK(g_VFS->Mount(L"cache", DataDir() / "_testcache" / "", 0, VFS_MAX_PRIORITY)); - CXeromyces::Startup(); + xeromycesEngine.emplace(); enet_initialize(); } @@ -51,7 +55,7 @@ public: { enet_deinitialize(); - CXeromyces::Terminate(); + xeromycesEngine.reset(); g_VFS.reset(); DeleteDirectory(DataDir()/"_testcache"); } diff --git a/source/ps/GameSetup/GameSetup.cpp b/source/ps/GameSetup/GameSetup.cpp index cd83ccb41c..9ce21011a1 100644 --- a/source/ps/GameSetup/GameSetup.cpp +++ b/source/ps/GameSetup/GameSetup.cpp @@ -662,7 +662,7 @@ void InitGraphics(const CmdLineArgs& args, int flags, const std::vector& i // TODO: Is this the best place for this? if (VfsDirectoryExists(L"maps/")) - CXeromyces::AddValidator(g_VFS, "map", "maps/scenario.rng"); + g_Xeromyces.AddValidator(g_VFS, "map", "maps/scenario.rng"); try { diff --git a/source/ps/XML/Xeromyces.cpp b/source/ps/XML/Xeromyces.cpp index 3e83859d6f..41d89d8b03 100644 --- a/source/ps/XML/Xeromyces.cpp +++ b/source/ps/XML/Xeromyces.cpp @@ -1,4 +1,4 @@ -/* Copyright (C) 2023 Wildfire Games. +/* Copyright (C) 2024 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -37,7 +37,6 @@ static std::mutex g_ValidatorCacheLock; static std::map g_ValidatorCache; -static bool g_XeromycesStarted = false; static void errorHandler(void* UNUSED(userData), std::conditional_t= 21200, const xmlError, xmlError>* error) @@ -54,20 +53,16 @@ static void errorHandler(void* UNUSED(userData), // so the caching is less transparent than it should be } -void CXeromyces::Startup() +CXeromycesEngine::CXeromycesEngine() { - ENSURE(!g_XeromycesStarted); xmlInitParser(); xmlSetStructuredErrorFunc(NULL, &errorHandler); std::lock_guard lock(g_ValidatorCacheLock); g_ValidatorCache.insert(std::make_pair(std::string(), RelaxNGValidator())); - g_XeromycesStarted = true; } -void CXeromyces::Terminate() +CXeromycesEngine::~CXeromycesEngine() { - ENSURE(g_XeromycesStarted); - g_XeromycesStarted = false; ClearSchemaCache(); std::lock_guard lock(g_ValidatorCacheLock); g_ValidatorCache.clear(); @@ -75,10 +70,8 @@ void CXeromyces::Terminate() xmlCleanupParser(); } -bool CXeromyces::AddValidator(const PIVFS& vfs, const std::string& name, const VfsPath& grammarPath) +bool CXeromycesEngine::AddValidator(const PIVFS& vfs, const std::string& name, const VfsPath& grammarPath) { - ENSURE(g_XeromycesStarted); - RelaxNGValidator validator; if (!validator.LoadGrammarFile(vfs, grammarPath)) { @@ -95,7 +88,7 @@ bool CXeromyces::AddValidator(const PIVFS& vfs, const std::string& name, const V return true; } -bool CXeromyces::ValidateEncoded(const std::string& name, const std::string& filename, const std::string& document) +bool CXeromycesEngine::ValidateEncoded(const std::string& name, const std::string& filename, const std::string& document) { std::lock_guard lock(g_ValidatorCacheLock); return GetValidator(name).ValidateEncoded(filename, document); @@ -104,7 +97,7 @@ bool CXeromyces::ValidateEncoded(const std::string& name, const std::string& fil /** * NOTE: Callers MUST acquire the g_ValidatorCacheLock before calling this. */ -RelaxNGValidator& CXeromyces::GetValidator(const std::string& name) +RelaxNGValidator& CXeromycesEngine::GetValidator(const std::string& name) { if (g_ValidatorCache.find(name) == g_ValidatorCache.end()) return g_ValidatorCache.find("")->second; @@ -113,14 +106,12 @@ RelaxNGValidator& CXeromyces::GetValidator(const std::string& name) PSRETURN CXeromyces::Load(const PIVFS& vfs, const VfsPath& filename, const std::string& validatorName /* = "" */) { - ENSURE(g_XeromycesStarted); - CCacheLoader cacheLoader(vfs, L".xmb"); MD5 validatorGrammarHash; { std::lock_guard lock(g_ValidatorCacheLock); - validatorGrammarHash = GetValidator(validatorName).GetGrammarHash(); + validatorGrammarHash = g_Xeromyces.GetValidator(validatorName).GetGrammarHash(); } VfsPath xmbPath; Status ret = cacheLoader.TryLoadingCached(filename, validatorGrammarHash, XMBStorage::XMBVersion, xmbPath); @@ -181,7 +172,7 @@ PSRETURN CXeromyces::ConvertFile(const PIVFS& vfs, const VfsPath& filename, cons { std::lock_guard lock(g_ValidatorCacheLock); - RelaxNGValidator& validator = GetValidator(validatorName); + RelaxNGValidator& validator = g_Xeromyces.GetValidator(validatorName); if (validator.CanValidate() && !validator.ValidateEncoded(doc)) { LOGERROR("CXeromyces: failed to validate XML file %s", filename.string8()); @@ -205,8 +196,6 @@ PSRETURN CXeromyces::ConvertFile(const PIVFS& vfs, const VfsPath& filename, cons PSRETURN CXeromyces::LoadString(const char* xml, const std::string& validatorName /* = "" */) { - ENSURE(g_XeromycesStarted); - xmlDocPtr doc = xmlReadMemory(xml, (int)strlen(xml), "(no file)", NULL, XML_PARSE_NONET|XML_PARSE_NOCDATA); if (!doc) { @@ -216,7 +205,7 @@ PSRETURN CXeromyces::LoadString(const char* xml, const std::string& validatorNam { std::lock_guard lock(g_ValidatorCacheLock); - RelaxNGValidator& validator = GetValidator(validatorName); + RelaxNGValidator& validator = g_Xeromyces.GetValidator(validatorName); if (validator.CanValidate() && !validator.ValidateEncoded(doc)) { LOGERROR("CXeromyces: failed to validate XML string"); diff --git a/source/ps/XML/Xeromyces.h b/source/ps/XML/Xeromyces.h index 75b9bb0d40..de6d2ca1b7 100644 --- a/source/ps/XML/Xeromyces.h +++ b/source/ps/XML/Xeromyces.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2021 Wildfire Games. +/* Copyright (C) 2024 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -30,6 +30,7 @@ ERROR_TYPE(Xeromyces, XMLOpenFailed); ERROR_TYPE(Xeromyces, XMLParseError); ERROR_TYPE(Xeromyces, XMLValidationFailed); +#include "ps/Singleton.h" #include "ps/XMB/XMBData.h" #include "ps/XMB/XMBStorage.h" @@ -59,29 +60,30 @@ public: */ bool GenerateCachedXMB(const PIVFS& vfs, const VfsPath& sourcePath, VfsPath& archiveCachePath, const std::string& validatorName = ""); - /** - * Call once when initialising the program, to load libxml2. - * This should be run in the main thread, before any thread uses libxml2. - */ - static void Startup(); - - /** - * Call once when shutting down the program, to unload libxml2. - */ - static void Terminate(); - - static bool AddValidator(const PIVFS& vfs, const std::string& name, const VfsPath& grammarPath); - - static bool ValidateEncoded(const std::string& name, const std::string& filename, const std::string& document); - private: - static RelaxNGValidator& GetValidator(const std::string& name); - PSRETURN ConvertFile(const PIVFS& vfs, const VfsPath& filename, const VfsPath& xmbPath, const std::string& validatorName); XMBStorage m_Data; }; +class CXeromycesEngine : public Singleton +{ + friend CXeromyces; +public: + /** + * This should be run in the main thread, before any thread uses libxml2. + */ + CXeromycesEngine(); + ~CXeromycesEngine(); + + bool AddValidator(const PIVFS& vfs, const std::string& name, const VfsPath& grammarPath); + bool ValidateEncoded(const std::string& name, const std::string& filename, const std::string& document); + +private: + RelaxNGValidator& GetValidator(const std::string& name); +}; + +#define g_Xeromyces CXeromycesEngine::GetSingleton() #define _XERO_MAKE_UID2__(p,l) p ## l #define _XERO_MAKE_UID1__(p,l) _XERO_MAKE_UID2__(p,l) diff --git a/source/ps/XML/tests/test_RelaxNG.h b/source/ps/XML/tests/test_RelaxNG.h index 6fa3ba0263..bbd3caf8a8 100644 --- a/source/ps/XML/tests/test_RelaxNG.h +++ b/source/ps/XML/tests/test_RelaxNG.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2021 Wildfire Games. +/* Copyright (C) 2024 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -21,17 +21,20 @@ #include "ps/XML/Xeromyces.h" #include "ps/XML/RelaxNG.h" +#include + class TestRelaxNG : public CxxTest::TestSuite { + std::optional xeromycesEngine; public: void setUp() { - CXeromyces::Startup(); + xeromycesEngine.emplace(); } void tearDown() { - CXeromyces::Terminate(); + xeromycesEngine.reset(); } void test_basic() diff --git a/source/ps/XML/tests/test_Xeromyces.h b/source/ps/XML/tests/test_Xeromyces.h index 80e112e451..600da1c518 100644 --- a/source/ps/XML/tests/test_Xeromyces.h +++ b/source/ps/XML/tests/test_Xeromyces.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2009 Wildfire Games. +/* Copyright (C) 2024 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -24,21 +24,12 @@ class TestXeromyces : public CxxTest::TestSuite { public: - void setUp() - { - CXeromyces::Startup(); - } - - void tearDown() - { - CXeromyces::Terminate(); - } - // TODO: Should test the reading/parsing/writing code, // and parse error handling void test_LoadString() { + CXeromycesEngine xeromycesEngine; CXeromyces xero; TS_ASSERT_EQUALS(xero.LoadString("bar"), PSRETURN_OK); TS_ASSERT_STR_EQUALS(xero.GetElementString(xero.GetRoot().GetNodeName()), "test"); @@ -46,6 +37,7 @@ public: void test_LoadString_invalid() { + CXeromycesEngine xeromycesEngine; TestLogger logger; CXeromyces xero; TS_ASSERT_EQUALS(xero.LoadString(""), PSRETURN_Xeromyces_XMLParseError); diff --git a/source/renderer/backend/gl/ShaderProgram.cpp b/source/renderer/backend/gl/ShaderProgram.cpp index 67806d70b2..6c5471672f 100644 --- a/source/renderer/backend/gl/ShaderProgram.cpp +++ b/source/renderer/backend/gl/ShaderProgram.cpp @@ -1208,8 +1208,7 @@ std::unique_ptr CShaderProgram::Create(CDevice* device, const CS XMLWriter_File shaderFile; shaderFile.SetPrettyPrint(false); shaderFile.XMB(XeroFile); - bool ok = CXeromyces::ValidateEncoded("shader", name, shaderFile.GetOutput()); - if (!ok) + if (!g_Xeromyces.ValidateEncoded("shader", name, shaderFile.GetOutput())) return nullptr; } #endif diff --git a/source/simulation2/components/CCmpPathfinder.cpp b/source/simulation2/components/CCmpPathfinder.cpp index 5260a7395d..3c7eab6b46 100644 --- a/source/simulation2/components/CCmpPathfinder.cpp +++ b/source/simulation2/components/CCmpPathfinder.cpp @@ -70,7 +70,7 @@ void CCmpPathfinder::Init(const CParamNode& UNUSED(paramNode)) m_Futures.resize(workerThreads); // Register Relax NG validator - CXeromyces::AddValidator(g_VFS, "pathfinder", "simulation/data/pathfinder.rng"); + g_Xeromyces.AddValidator(g_VFS, "pathfinder", "simulation/data/pathfinder.rng"); // Since this is used as a system component (not loaded from an entity template), // we can't use the real paramNode (it won't get handled properly when deserializing), diff --git a/source/simulation2/components/CCmpTerritoryManager.cpp b/source/simulation2/components/CCmpTerritoryManager.cpp index d6ecea31f7..25927702ff 100644 --- a/source/simulation2/components/CCmpTerritoryManager.cpp +++ b/source/simulation2/components/CCmpTerritoryManager.cpp @@ -136,7 +136,7 @@ public: m_TerritoryTotalPassableCellCount = 0; // Register Relax NG validator - CXeromyces::AddValidator(g_VFS, "territorymanager", "simulation/data/territorymanager.rng"); + g_Xeromyces.AddValidator(g_VFS, "territorymanager", "simulation/data/territorymanager.rng"); CParamNode externalParamNode; CParamNode::LoadXML(externalParamNode, L"simulation/data/territorymanager.xml", "territorymanager"); diff --git a/source/simulation2/components/tests/test_CinemaManager.h b/source/simulation2/components/tests/test_CinemaManager.h index 14b4e1a3be..7f65a77bc3 100644 --- a/source/simulation2/components/tests/test_CinemaManager.h +++ b/source/simulation2/components/tests/test_CinemaManager.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2023 Wildfire Games. +/* Copyright (C) 2024 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -22,18 +22,9 @@ class TestCmpCinemaManager : public CxxTest::TestSuite { public: - void setUp() - { - CXeromyces::Startup(); - } - - void tearDown() - { - CXeromyces::Terminate(); - } - void test_basic() { + CXeromycesEngine xeromycesEngine; ComponentTestHelper test(*g_ScriptContext); ICmpCinemaManager* cmp = test.Add(CID_CinemaManager, "", SYSTEM_ENTITY); diff --git a/source/simulation2/components/tests/test_CommandQueue.h b/source/simulation2/components/tests/test_CommandQueue.h index 851d3e6aa7..45538f34bc 100644 --- a/source/simulation2/components/tests/test_CommandQueue.h +++ b/source/simulation2/components/tests/test_CommandQueue.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2023 Wildfire Games. +/* Copyright (C) 2024 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -22,18 +22,9 @@ class TestCmpCommandQueue : public CxxTest::TestSuite { public: - void setUp() - { - CXeromyces::Startup(); - } - - void tearDown() - { - CXeromyces::Terminate(); - } - void test_basic() { + CXeromycesEngine xeromycesEngine; ComponentTestHelper test(*g_ScriptContext); ScriptRequest rq(test.GetScriptInterface()); diff --git a/source/simulation2/components/tests/test_ObstructionManager.h b/source/simulation2/components/tests/test_ObstructionManager.h index e2acdcf2d5..694881e586 100644 --- a/source/simulation2/components/tests/test_ObstructionManager.h +++ b/source/simulation2/components/tests/test_ObstructionManager.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2023 Wildfire Games. +/* Copyright (C) 2024 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -20,6 +20,8 @@ #include "simulation2/components/ICmpObstructionManager.h" #include "simulation2/components/ICmpObstruction.h" +#include + class MockObstruction : public ICmpObstruction { public: @@ -59,6 +61,8 @@ class TestCmpObstructionManager : public CxxTest::TestSuite typedef ICmpObstructionManager::tag_t tag_t; typedef ICmpObstructionManager::ObstructionSquare ObstructionSquare; + std::optional xeromycesEngine; + // some variables for setting up a scene with 3 shapes entity_id_t ent1, ent2, ent3; // entity IDs entity_angle_t ent1a; // angles @@ -75,7 +79,7 @@ class TestCmpObstructionManager : public CxxTest::TestSuite public: void setUp() { - CXeromyces::Startup(); + xeromycesEngine.emplace(); CxxTest::setAbortTestOnFail(true); // set up a simple scene with some predefined obstruction shapes @@ -126,7 +130,7 @@ public: delete testHelper; cmp = NULL; // not our responsibility to deallocate - CXeromyces::Terminate(); + xeromycesEngine.reset(); } /** diff --git a/source/simulation2/components/tests/test_Pathfinder.h b/source/simulation2/components/tests/test_Pathfinder.h index 97449af2da..0b5db605dc 100644 --- a/source/simulation2/components/tests/test_Pathfinder.h +++ b/source/simulation2/components/tests/test_Pathfinder.h @@ -32,10 +32,12 @@ #include "simulation2/Simulation2.h" #include +#include #include class TestCmpPathfinder : public CxxTest::TestSuite { + std::optional xeromycesEngine; public: void setUp() { @@ -44,12 +46,12 @@ public: g_VFS->Mount(L"", DataDir() / "mods" / "public" / "", VFS_MOUNT_MUST_EXIST, 1); // ignore directory-not-found errors TS_ASSERT_OK(g_VFS->Mount(L"cache", DataDir() / "_testcache" / "", 0, VFS_MAX_PRIORITY)); - CXeromyces::Startup(); + xeromycesEngine.emplace(); } void tearDown() { - CXeromyces::Terminate(); + xeromycesEngine.reset(); g_VFS.reset(); DeleteDirectory(DataDir()/"_testcache"); } diff --git a/source/simulation2/components/tests/test_Position.h b/source/simulation2/components/tests/test_Position.h index fef2280439..1e46745233 100644 --- a/source/simulation2/components/tests/test_Position.h +++ b/source/simulation2/components/tests/test_Position.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2023 Wildfire Games. +/* Copyright (C) 2024 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -48,16 +48,6 @@ public: class TestCmpPosition : public CxxTest::TestSuite { public: - void setUp() - { - CXeromyces::Startup(); - } - - void tearDown() - { - CXeromyces::Terminate(); - } - static CFixedVector3D fixedvec(int x, int y, int z) { return CFixedVector3D(fixed::FromInt(x), fixed::FromInt(y), fixed::FromInt(z)); @@ -65,6 +55,7 @@ public: void test_basic() { + CXeromycesEngine xeromycesEngine; ComponentTestHelper test(*g_ScriptContext); MockTerrain terrain; @@ -137,6 +128,7 @@ public: void test_water() { + CXeromycesEngine xeromycesEngine; ComponentTestHelper test(*g_ScriptContext); MockTerrain terrain; @@ -210,6 +202,7 @@ public: void test_serialize() { + CXeromycesEngine xeromycesEngine; ComponentTestHelper test(*g_ScriptContext); MockTerrain terrain; diff --git a/source/simulation2/components/tests/test_RangeManager.h b/source/simulation2/components/tests/test_RangeManager.h index 2e47bce865..075e656d0e 100644 --- a/source/simulation2/components/tests/test_RangeManager.h +++ b/source/simulation2/components/tests/test_RangeManager.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2023 Wildfire Games. +/* Copyright (C) 2024 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -25,6 +25,8 @@ #include #include +#include + class MockVisionRgm : public ICmpVision { public: @@ -114,15 +116,16 @@ private: class TestCmpRangeManager : public CxxTest::TestSuite { + std::optional xeromycesEngine; public: void setUp() { - CXeromyces::Startup(); + xeromycesEngine.emplace(); } void tearDown() { - CXeromyces::Terminate(); + xeromycesEngine.reset(); } // TODO It would be nice to call Verify() with the shore revealing system diff --git a/source/simulation2/components/tests/test_TerritoryManager.h b/source/simulation2/components/tests/test_TerritoryManager.h index 430e26cea3..a99c21f116 100644 --- a/source/simulation2/components/tests/test_TerritoryManager.h +++ b/source/simulation2/components/tests/test_TerritoryManager.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2023 Wildfire Games. +/* Copyright (C) 2024 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -27,6 +27,8 @@ #include "simulation2/components/ICmpTerritoryInfluence.h" #include "simulation2/components/ICmpOwnership.h" +#include + class MockPathfinderTerrMan : public ICmpPathfinder { public: @@ -140,6 +142,7 @@ public: class TestCmpTerritoryManager : public CxxTest::TestSuite { + std::optional xeromycesEngine; public: void setUp() { @@ -147,12 +150,12 @@ public: g_VFS = CreateVfs(); TS_ASSERT_OK(g_VFS->Mount(L"", DataDir() / "mods" / "_test.sim" / "", VFS_MOUNT_MUST_EXIST)); TS_ASSERT_OK(g_VFS->Mount(L"cache", DataDir() / "_testcache" / "", 0, VFS_MAX_PRIORITY)); - CXeromyces::Startup(); + xeromycesEngine.emplace(); } void tearDown() { - CXeromyces::Terminate(); + xeromycesEngine.reset(); g_VFS.reset(); DeleteDirectory(DataDir()/"_testcache"); } diff --git a/source/simulation2/components/tests/test_scripts.h b/source/simulation2/components/tests/test_scripts.h index feadfef079..2a0a523a3e 100644 --- a/source/simulation2/components/tests/test_scripts.h +++ b/source/simulation2/components/tests/test_scripts.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2023 Wildfire Games. +/* Copyright (C) 2024 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -32,12 +32,10 @@ public: g_VFS = CreateVfs(); g_VFS->Mount(L"", DataDir() / "mods" / "mod" / "", VFS_MOUNT_MUST_EXIST); g_VFS->Mount(L"", DataDir() / "mods" / "public" / "", VFS_MOUNT_MUST_EXIST, 1); // ignore directory-not-found errors - CXeromyces::Startup(); } void tearDown() { - CXeromyces::Terminate(); g_VFS.reset(); } @@ -79,6 +77,7 @@ public: void test_global_scripts() { + CXeromycesEngine xeromycesEngine; if (!VfsDirectoryExists(L"globalscripts/tests/")) { debug_printf("Skipping globalscripts tests (can't find binaries/data/mods/public/globalscripts/tests/)\n"); @@ -102,6 +101,7 @@ public: void test_scripts() { + CXeromycesEngine xeromycesEngine; if (!VfsFileExists(L"simulation/components/tests/setup.js")) { debug_printf("Skipping component scripts tests (can't find binaries/data/mods/public/simulation/components/tests/setup.js)\n"); diff --git a/source/simulation2/tests/test_CmpTemplateManager.h b/source/simulation2/tests/test_CmpTemplateManager.h index 6ec8820d6b..471c46326e 100644 --- a/source/simulation2/tests/test_CmpTemplateManager.h +++ b/source/simulation2/tests/test_CmpTemplateManager.h @@ -33,20 +33,23 @@ #include "scriptinterface/JSON.h" #include "scriptinterface/ScriptRequest.h" +#include + class TestCmpTemplateManager : public CxxTest::TestSuite { + std::optional xeromycesEngine; public: void setUp() { g_VFS = CreateVfs(); TS_ASSERT_OK(g_VFS->Mount(L"", DataDir() / "mods" / "_test.sim" / "", VFS_MOUNT_MUST_EXIST)); TS_ASSERT_OK(g_VFS->Mount(L"cache", DataDir() / "_testcache" / "", 0, VFS_MAX_PRIORITY)); - CXeromyces::Startup(); + xeromycesEngine.emplace(); } void tearDown() { - CXeromyces::Terminate(); + xeromycesEngine.reset(); g_VFS.reset(); DeleteDirectory(DataDir()/"_testcache"); } @@ -226,12 +229,10 @@ public: TS_ASSERT_OK(g_VFS->Mount(L"", DataDir() / "mods" / "mod" / "", VFS_MOUNT_MUST_EXIST)); TS_ASSERT_OK(g_VFS->Mount(L"", DataDir() / "mods" / "public" / "", VFS_MOUNT_MUST_EXIST)); TS_ASSERT_OK(g_VFS->Mount(L"cache", DataDir()/"_testcache" / "", 0, VFS_MAX_PRIORITY)); - CXeromyces::Startup(); } void tearDown() { - CXeromyces::Terminate(); g_VFS.reset(); DeleteDirectory(DataDir()/"_testcache"); } @@ -239,6 +240,7 @@ public: // This just attempts loading every public entity, to check there's no validation errors void DISABLED_test_load_all() // disabled since it's a bit slow and noisy { + CXeromycesEngine xeromycesEngine; CTerrain dummy; CSimulation2 sim{nullptr, *g_ScriptContext, &dummy}; sim.LoadDefaultScripts(); diff --git a/source/simulation2/tests/test_ComponentManager.h b/source/simulation2/tests/test_ComponentManager.h index 08564884d8..f1b77e8a11 100644 --- a/source/simulation2/tests/test_ComponentManager.h +++ b/source/simulation2/tests/test_ComponentManager.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2023 Wildfire Games. +/* Copyright (C) 2024 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -30,6 +30,8 @@ #include "ps/Filesystem.h" #include "ps/XML/Xeromyces.h" +#include + #define TS_ASSERT_STREAM(stream, len, buffer) \ TS_ASSERT_EQUALS(stream.str().length(), (size_t)len); \ TS_ASSERT_SAME_DATA(stream.str().data(), buffer, len) @@ -40,18 +42,19 @@ class TestComponentManager : public CxxTest::TestSuite { + std::optional xeromycesEngine; public: void setUp() { g_VFS = CreateVfs(); TS_ASSERT_OK(g_VFS->Mount(L"", DataDir() / "mods" / "_test.sim" / "", VFS_MOUNT_MUST_EXIST)); TS_ASSERT_OK(g_VFS->Mount(L"cache", DataDir() / "_testcache" / "", 0, VFS_MAX_PRIORITY)); - CXeromyces::Startup(); + xeromycesEngine.emplace(); } void tearDown() { - CXeromyces::Terminate(); + xeromycesEngine.reset(); g_VFS.reset(); DeleteDirectory(DataDir()/"_testcache"); } diff --git a/source/simulation2/tests/test_ParamNode.h b/source/simulation2/tests/test_ParamNode.h index e9dd7564f2..84c1c4ef07 100644 --- a/source/simulation2/tests/test_ParamNode.h +++ b/source/simulation2/tests/test_ParamNode.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2022 Wildfire Games. +/* Copyright (C) 2024 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -22,17 +22,20 @@ #include "ps/CLogger.h" #include "ps/XML/Xeromyces.h" +#include + class TestParamNode : public CxxTest::TestSuite { + std::optional xeromycesEngine; public: void setUp() { - CXeromyces::Startup(); + xeromycesEngine.emplace(); } void tearDown() { - CXeromyces::Terminate(); + xeromycesEngine.reset(); } void test_basic() diff --git a/source/simulation2/tests/test_Serializer.h b/source/simulation2/tests/test_Serializer.h index da91ea67ef..e049d5bfb9 100644 --- a/source/simulation2/tests/test_Serializer.h +++ b/source/simulation2/tests/test_Serializer.h @@ -879,7 +879,7 @@ public: void DISABLED_test_hash() { - CXeromyces::Startup(); + CXeromycesEngine xeromycesEngine; g_VFS = CreateVfs(); TS_ASSERT_OK(g_VFS->Mount(L"", DataDir() / "mods" / "public" / "", VFS_MOUNT_MUST_EXIST)); @@ -935,7 +935,6 @@ public: // Shut down the world g_VFS.reset(); DeleteDirectory(DataDir()/"_testcache"); - CXeromyces::Terminate(); } }; diff --git a/source/simulation2/tests/test_Simulation2.h b/source/simulation2/tests/test_Simulation2.h index eab75eaa3d..470f42a910 100644 --- a/source/simulation2/tests/test_Simulation2.h +++ b/source/simulation2/tests/test_Simulation2.h @@ -45,18 +45,17 @@ public: g_VFS = CreateVfs(); TS_ASSERT_OK(g_VFS->Mount(L"", DataDir() / "mods" / "_test.sim" / "", VFS_MOUNT_MUST_EXIST)); TS_ASSERT_OK(g_VFS->Mount(L"cache", DataDir() / "_testcache" / "", 0, VFS_MAX_PRIORITY)); - CXeromyces::Startup(); } void tearDown() { - CXeromyces::Terminate(); g_VFS.reset(); DeleteDirectory(DataDir()/"_testcache"); } void test_AddEntity() { + CXeromycesEngine xeromycesEngine; CSimulation2 sim{nullptr, *g_ScriptContext, &m_Terrain}; TS_ASSERT(sim.LoadScripts(L"simulation/components/addentity/")); @@ -77,6 +76,7 @@ public: void test_DestroyEntity() { + CXeromycesEngine xeromycesEngine; CSimulation2 sim{nullptr, *g_ScriptContext, &m_Terrain}; TS_ASSERT(sim.LoadScripts(L"simulation/components/addentity/")); @@ -133,6 +133,7 @@ public: void test_hotload_scripts() { + CXeromycesEngine xeromycesEngine; CSimulation2 sim{nullptr, *g_ScriptContext, &m_Terrain}; TS_ASSERT_OK(CreateDirectories(DataDir()/"mods"/"_test.sim"/"simulation"/"components"/"hotload"/"", 0700)); diff --git a/source/soundmanager/SoundManager.cpp b/source/soundmanager/SoundManager.cpp index 57000f7e74..1822a9e89d 100644 --- a/source/soundmanager/SoundManager.cpp +++ b/source/soundmanager/SoundManager.cpp @@ -261,7 +261,7 @@ CSoundManager::CSoundManager(ALCdevice* device) m_PlayListItems = new PlayList; } - if (!CXeromyces::AddValidator(g_VFS, "sound_group", "audio/sound_group.rng")) + if (!g_Xeromyces.AddValidator(g_VFS, "sound_group", "audio/sound_group.rng")) LOGERROR("CSoundManager: failed to load grammar file 'audio/sound_group.rng'"); RegisterFileReloadFunc(ReloadChangedFileCB, this);