From d390214929f4b280cc66cdbc170694ec9b1fa8c4 Mon Sep 17 00:00:00 2001 From: Mattes D Date: Thu, 11 Jun 2015 22:20:04 +0200 Subject: SelfTests are registered and executed after logging framework init. Fixes #2228. --- src/BoundingBox.cpp | 13 +++-- src/ByteBuffer.cpp | 15 +++--- src/CMakeLists.txt | 2 + src/CompositeChat.cpp | 23 +++++---- src/Generating/PieceGenerator.cpp | 12 +++-- src/OSSupport/NetworkInterfaceEnum.cpp | 13 +++-- src/Root.cpp | 17 +++++-- src/Root.h | 8 +++- src/SelfTests.cpp | 71 ++++++++++++++++++++++++++++ src/SelfTests.h | 51 ++++++++++++++++++++ src/WorldStorage/SchematicFileSerializer.cpp | 6 +++ 11 files changed, 198 insertions(+), 33 deletions(-) create mode 100644 src/SelfTests.cpp create mode 100644 src/SelfTests.h diff --git a/src/BoundingBox.cpp b/src/BoundingBox.cpp index 6b163b01e..64e3c02d2 100644 --- a/src/BoundingBox.cpp +++ b/src/BoundingBox.cpp @@ -5,6 +5,7 @@ #include "Globals.h" #include "BoundingBox.h" #include "Defines.h" +#include "SelfTests.h" @@ -17,6 +18,11 @@ static class SelfTest_BoundingBox { public: SelfTest_BoundingBox(void) + { + cSelfTests::Get().Register(cSelfTests::SelfTestFunction(&Test), "Bounding box intersections"); + } + + static void Test(void) { Vector3d Min(1, 1, 1); Vector3d Max(2, 2, 2); @@ -41,7 +47,7 @@ public: bool res = cBoundingBox::CalcLineIntersection(Min, Max, Line1, Line2, LineCoeff, Face); if (res != Results[i]) { - fprintf(stderr, "LineIntersection({%.02f, %.02f, %.02f}, {%.02f, %.02f, %.02f}) -> %d, %.05f, %d\n", + LOGERROR("LineIntersection({%.02f, %.02f, %.02f}, {%.02f, %.02f, %.02f}) -> %d, %.05f, %d", Line1.x, Line1.y, Line1.z, Line2.x, Line2.y, Line2.z, res ? 1 : 0, LineCoeff, Face @@ -52,7 +58,7 @@ public: { if (LineCoeff != LineCoeffs[i]) { - fprintf(stderr, "LineIntersection({%.02f, %.02f, %.02f}, {%.02f, %.02f, %.02f}) -> %d, %.05f, %d\n", + LOGERROR("LineIntersection({%.02f, %.02f, %.02f}, {%.02f, %.02f, %.02f}) -> %d, %.05f, %d", Line1.x, Line1.y, Line1.z, Line2.x, Line2.y, Line2.z, res ? 1 : 0, LineCoeff, Face @@ -61,9 +67,8 @@ public: } } } // for i - LineDefs[] - fprintf(stderr, "BoundingBox selftest complete.\n"); } -} gTest; +} g_BoundingBoxTest; #endif diff --git a/src/ByteBuffer.cpp b/src/ByteBuffer.cpp index dc757d8f6..f50e3845b 100644 --- a/src/ByteBuffer.cpp +++ b/src/ByteBuffer.cpp @@ -8,6 +8,7 @@ #include "ByteBuffer.h" #include "Endianness.h" #include "OSSupport/IsThread.h" +#include "SelfTests.h" @@ -55,18 +56,18 @@ Unfortunately it is very slow, so it is disabled even for regular DEBUG builds. #ifdef SELF_TEST -/// Self-test of the VarInt-reading and writing code +/** Self-test of the VarInt-reading and writing code */ static class cByteBufferSelfTest { public: cByteBufferSelfTest(void) { - TestRead(); - TestWrite(); - TestWrap(); + cSelfTests::Get().Register(cSelfTests::SelfTestFunction(&TestRead), "ByteBuffer read"); + cSelfTests::Get().Register(cSelfTests::SelfTestFunction(&TestWrite), "ByteBuffer write"); + cSelfTests::Get().Register(cSelfTests::SelfTestFunction(&TestWrap), "ByteBuffer wraparound"); } - void TestRead(void) + static void TestRead(void) { cByteBuffer buf(50); buf.Write("\x05\xac\x02\x00", 4); @@ -78,7 +79,7 @@ public: assert_test(buf.ReadVarInt(v3) && (v3 == 0)); } - void TestWrite(void) + static void TestWrite(void) { cByteBuffer buf(50); buf.WriteVarInt32(5); @@ -90,7 +91,7 @@ public: assert_test(memcmp(All.data(), "\x05\xac\x02\x00", All.size()) == 0); } - void TestWrap(void) + static void TestWrap(void) { cByteBuffer buf(3); for (int i = 0; i < 1000; i++) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 429087ae2..fcafdbe87 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -61,6 +61,7 @@ SET (SRCS RCONServer.cpp Root.cpp Scoreboard.cpp + SelfTests.cpp Server.cpp SetChunkData.cpp SpawnPrepare.cpp @@ -134,6 +135,7 @@ SET (HDRS RCONServer.h Root.h Scoreboard.h + SelfTests.h Server.h SetChunkData.h SettingsRepositoryInterface.h diff --git a/src/CompositeChat.cpp b/src/CompositeChat.cpp index 5d6c028ab..353835039 100644 --- a/src/CompositeChat.cpp +++ b/src/CompositeChat.cpp @@ -6,6 +6,7 @@ #include "Globals.h" #include "CompositeChat.h" #include "ClientHandle.h" +#include "SelfTests.h" @@ -19,16 +20,14 @@ class SelfTest_CompositeChat public: SelfTest_CompositeChat(void) { - fprintf(stderr, "cCompositeChat self test...\n"); - TestParser1(); - TestParser2(); - TestParser3(); - TestParser4(); - TestParser5(); - fprintf(stderr, "cCompositeChat self test finished.\n"); + cSelfTests::Get().Register(cSelfTests::SelfTestFunction(&TestParser1), "CompositeChat parser test 1"); + cSelfTests::Get().Register(cSelfTests::SelfTestFunction(&TestParser2), "CompositeChat parser test 2"); + cSelfTests::Get().Register(cSelfTests::SelfTestFunction(&TestParser3), "CompositeChat parser test 3"); + cSelfTests::Get().Register(cSelfTests::SelfTestFunction(&TestParser4), "CompositeChat parser test 4"); + cSelfTests::Get().Register(cSelfTests::SelfTestFunction(&TestParser5), "CompositeChat parser test 5"); } - void TestParser1(void) + static void TestParser1(void) { cCompositeChat Msg; Msg.ParseText("Testing @2color codes and http://links parser"); @@ -44,7 +43,7 @@ public: assert_test(Parts[3]->m_Style == "@2"); } - void TestParser2(void) + static void TestParser2(void) { cCompositeChat Msg; Msg.ParseText("@3Advanced stuff: @5overriding color codes and http://links.with/@4color-in-them handling"); @@ -60,7 +59,7 @@ public: assert_test(Parts[3]->m_Style == "@5"); } - void TestParser3(void) + static void TestParser3(void) { cCompositeChat Msg; Msg.ParseText("http://links.starting the text"); @@ -72,7 +71,7 @@ public: assert_test(Parts[1]->m_Style == ""); } - void TestParser4(void) + static void TestParser4(void) { cCompositeChat Msg; Msg.ParseText("links finishing the text: http://some.server"); @@ -84,7 +83,7 @@ public: assert_test(Parts[1]->m_Style == ""); } - void TestParser5(void) + static void TestParser5(void) { cCompositeChat Msg; Msg.ParseText("http://only.links"); diff --git a/src/Generating/PieceGenerator.cpp b/src/Generating/PieceGenerator.cpp index 14a9da39d..93e7179e2 100644 --- a/src/Generating/PieceGenerator.cpp +++ b/src/Generating/PieceGenerator.cpp @@ -6,6 +6,7 @@ #include "Globals.h" #include "PieceGenerator.h" +#include "../SelfTests.h" @@ -21,6 +22,11 @@ static class cPieceGeneratorSelfTest : { public: cPieceGeneratorSelfTest(void) + { + cSelfTests::Get().Register(std::bind(&cPieceGeneratorSelfTest::Test, this), "PieceGenerator"); + } + + void Test(void) { // Prepare the internal state: InitializePieces(); @@ -31,14 +37,14 @@ public: Gen.PlacePieces(500, 50, 500, 3, OutPieces); // Print out the pieces: - printf("OutPieces.size() = " SIZE_T_FMT "\n", OutPieces.size()); + LOG("OutPieces.size() = " SIZE_T_FMT, OutPieces.size()); size_t idx = 0; for (cPlacedPieces::const_iterator itr = OutPieces.begin(), end = OutPieces.end(); itr != end; ++itr, ++idx) { const Vector3i & Coords = (*itr)->GetCoords(); cCuboid Hitbox = (*itr)->GetHitBox(); Hitbox.Sort(); - printf(SIZE_T_FMT ": {%d, %d, %d}, rot %d, hitbox {%d, %d, %d} - {%d, %d, %d} (%d * %d * %d)\n", idx, + LOG(SIZE_T_FMT ": {%d, %d, %d}, rot %d, hitbox {%d, %d, %d} - {%d, %d, %d} (%d * %d * %d)", idx, Coords.x, Coords.y, Coords.z, (*itr)->GetNumCCWRotations(), Hitbox.p1.x, Hitbox.p1.y, Hitbox.p1.z, @@ -46,7 +52,7 @@ public: Hitbox.DifX() + 1, Hitbox.DifY() + 1, Hitbox.DifZ() + 1 ); } // itr - OutPieces[] - printf("Done.\n"); + LOG("Done."); // Free the placed pieces properly: Gen.FreePieces(OutPieces); diff --git a/src/OSSupport/NetworkInterfaceEnum.cpp b/src/OSSupport/NetworkInterfaceEnum.cpp index c4af1e93c..d74565e07 100644 --- a/src/OSSupport/NetworkInterfaceEnum.cpp +++ b/src/OSSupport/NetworkInterfaceEnum.cpp @@ -6,6 +6,8 @@ #include "Globals.h" #include "Network.h" #include "event2/util.h" +#include "../SelfTests.h" + #ifdef _WIN32 #include #pragma comment(lib, "IPHLPAPI.lib") @@ -27,13 +29,18 @@ static class cEnumIPAddressTest public: cEnumIPAddressTest(void) { - printf("Enumerating all IP addresses...\n"); + cSelfTests::Get().Register(std::function(&Test), "Network IP enumeration"); + } + + static void Test(void) + { + LOG("Enumerating all IP addresses..."); auto IPs = cNetwork::EnumLocalIPAddresses(); for (auto & ip: IPs) { - printf(" %s\n", ip.c_str()); + LOG(" %s", ip.c_str()); } - printf("Done.\n"); + LOG("Done."); } } g_EnumIPAddressTest; diff --git a/src/Root.cpp b/src/Root.cpp index 8d344ee65..8ad71edf3 100644 --- a/src/Root.cpp +++ b/src/Root.cpp @@ -21,6 +21,7 @@ #include "IniFile.h" #include "SettingsRepositoryInterface.h" #include "OverridesSettingsRepository.h" +#include "SelfTests.h" #ifdef _WIN32 #include @@ -111,11 +112,16 @@ void cRoot::Start(std::unique_ptr overridesRepo) cLogger::GetInstance().AttachListener(consoleLogListener); cLogger::GetInstance().AttachListener(fileLogListener); - LOG("--- Started Log ---\n"); + LOG("--- Started Log ---"); #ifdef BUILD_ID - LOG("MCServer " BUILD_SERIES_NAME " build id: " BUILD_ID); - LOG("from commit id: " BUILD_COMMIT_ID " built at: " BUILD_DATETIME); + LOG("MCServer " BUILD_SERIES_NAME " build id: " BUILD_ID); + LOG("from commit id: " BUILD_COMMIT_ID " built at: " BUILD_DATETIME); + #endif + + // Run the self-tests registered previously via cSelfTests::Register(): + #if SELF_TEST + cSelfTests::ExecuteAll(); #endif cDeadlockDetect dd; @@ -869,3 +875,8 @@ int cRoot::GetFurnaceFuelBurnTime(const cItem & a_Fuel) cFurnaceRecipe * FR = Get()->GetFurnaceRecipe(); return FR->GetBurnTime(a_Fuel); } + + + + + diff --git a/src/Root.h b/src/Root.h index 81551a503..a484db657 100644 --- a/src/Root.h +++ b/src/Root.h @@ -38,7 +38,7 @@ namespace Json -/// The root of the object hierarchy +/** The root of the object hierarchy */ // tolua_begin class cRoot { @@ -217,6 +217,7 @@ private: bool m_bRestart; + void LoadGlobalSettings(); /// Loads the worlds from settings.ini, creates the worldmap @@ -238,3 +239,8 @@ private: static void InputThread(cRoot & a_Params); }; // tolua_export + + + + + diff --git a/src/SelfTests.cpp b/src/SelfTests.cpp new file mode 100644 index 000000000..f03035a76 --- /dev/null +++ b/src/SelfTests.cpp @@ -0,0 +1,71 @@ + +// SelfTests.h + +// Implements the cSelfTests class representing the singleton used for registering self-tests +// This class is only declared if SELF_TEST macro is defined. + +#include "Globals.h" +#include "SelfTests.h" + + + + + +#if SELF_TEST + cSelfTests::cSelfTests(void): + m_AllowRegistering(true) + { + } + + + + + + cSelfTests & cSelfTests::Get(void) + { + static cSelfTests singleton; + return singleton; + } + + + + + + void cSelfTests::Register(cSelfTests::SelfTestFunction a_FnToExecute, const AString & a_TestName) + { + ASSERT(Get().m_AllowRegistering); + Get().m_SelfTests.push_back(std::make_pair(a_FnToExecute, a_TestName)); + } + + + + + + void cSelfTests::ExecuteAll(void) + { + Get().m_AllowRegistering = false; + LOG("--- Performing self-tests ---"); + for (auto & test: Get().m_SelfTests) + { + LOG("Performing self-test: %s", test.second.c_str()); + try + { + test.first(); + } + catch (const std::exception & exc) + { + LOGWARNING("Exception in test %s: %s", test.second.c_str(), exc.what()); + } + catch (...) + { + LOGWARNING("Unknown exception in test %s", test.second.c_str()); + } + } // for test - m_SelfTests[] + LOG("--- Self-tests finished ---"); + } + +#endif // SELF_TEST + + + + diff --git a/src/SelfTests.h b/src/SelfTests.h new file mode 100644 index 000000000..03a3b5faa --- /dev/null +++ b/src/SelfTests.h @@ -0,0 +1,51 @@ + +// SelfTests.h + +// Declares the cSelfTests class representing the singleton used for registering self-tests +// This class is only declared if SELF_TEST macro is defined. + + + + + +#pragma once + + + + + +#ifdef SELF_TEST + /** Singleton containing registered self-tests. + Used to schedule self-tests to run after the logging framework is initialized (#2228). */ + class cSelfTests + { + public: + /** Returns the singleton instance of this class. */ + static cSelfTests & Get(void); + + // typedef void (* SelfTestFunction)(void); + typedef std::function SelfTestFunction; + + /** Registers a self-test to be executed once the logging framework is initialized. */ + static void Register(SelfTestFunction a_FnToExecute, const AString & a_TestName); + + /** Executes all the registered self-tests. */ + static void ExecuteAll(void); + + protected: + typedef std::vector> SelfTestFunctions; + + /** Functions (registered self-tests) to call once the logging framework is initialized. */ + SelfTestFunctions m_SelfTests; + + /** If true, tests may be registered. Set to false once the tests are executed, to detect tests that are registered too late. */ + bool m_AllowRegistering; + + + cSelfTests(void); + }; +#endif // SELF_TEST + + + + diff --git a/src/WorldStorage/SchematicFileSerializer.cpp b/src/WorldStorage/SchematicFileSerializer.cpp index fb881e290..199873968 100644 --- a/src/WorldStorage/SchematicFileSerializer.cpp +++ b/src/WorldStorage/SchematicFileSerializer.cpp @@ -9,6 +9,7 @@ #include "FastNBT.h" #include "SchematicFileSerializer.h" #include "../StringCompression.h" +#include "../SelfTests.h" @@ -20,6 +21,11 @@ static class cSchematicStringSelfTest { public: cSchematicStringSelfTest(void) + { + cSelfTests::Get().Register(cSelfTests::SelfTestFunction(&Test), "Schematic-to-string serialization"); + } + + static void Test(void) { cBlockArea ba; ba.Create(21, 256, 21); -- cgit v1.2.3