From c821e6f53be7f676f63e1696cf0183e7fe01886b Mon Sep 17 00:00:00 2001 From: Deukhoofd Date: Mon, 23 Aug 2021 21:44:59 +0200 Subject: [PATCH] Initial work on also doing battle stuff in tests. --- src/BuildData | 2 +- src/Globals.cpp | 3 ++ src/Globals.hpp | 10 ++++ src/Tester/AngelScript/BattleBuilder.hpp | 52 +++++++++++++++++++ .../{ => AngelScript}/TestFunctions.hpp | 38 +++++++------- ...ertionFailed.hpp => RequirementFailed.hpp} | 14 ++--- src/Tester/Test.hpp | 1 + src/Tester/TestEnvironment.hpp | 24 ++++++++- src/main.cpp | 11 ++-- 9 files changed, 123 insertions(+), 32 deletions(-) create mode 100644 src/Globals.cpp create mode 100644 src/Globals.hpp create mode 100644 src/Tester/AngelScript/BattleBuilder.hpp rename src/Tester/{ => AngelScript}/TestFunctions.hpp (61%) rename src/Tester/{AssertionFailed.hpp => RequirementFailed.hpp} (71%) diff --git a/src/BuildData b/src/BuildData index 069eadf..9b27ad7 160000 --- a/src/BuildData +++ b/src/BuildData @@ -1 +1 @@ -Subproject commit 069eadf7c9f94ca4b8616dca8eb7562c9ecf26e0 +Subproject commit 9b27ad72f18d4924d0851a523b64fbff0c779620 diff --git a/src/Globals.cpp b/src/Globals.cpp new file mode 100644 index 0000000..2d53311 --- /dev/null +++ b/src/Globals.cpp @@ -0,0 +1,3 @@ +#include "Globals.hpp" + +ArbUt::OptionalUniquePtr Globals::Library = nullptr; \ No newline at end of file diff --git a/src/Globals.hpp b/src/Globals.hpp new file mode 100644 index 0000000..4cf70f2 --- /dev/null +++ b/src/Globals.hpp @@ -0,0 +1,10 @@ +#ifndef POKEMONSCRIPTTESTER_GLOBALS_HPP +#define POKEMONSCRIPTTESTER_GLOBALS_HPP +#include + +class Globals { +public: + static ArbUt::OptionalUniquePtr Library; +}; + +#endif // POKEMONSCRIPTTESTER_GLOBALS_HPP diff --git a/src/Tester/AngelScript/BattleBuilder.hpp b/src/Tester/AngelScript/BattleBuilder.hpp new file mode 100644 index 0000000..c4a4737 --- /dev/null +++ b/src/Tester/AngelScript/BattleBuilder.hpp @@ -0,0 +1,52 @@ +#ifndef POKEMONSCRIPTTESTER_BATTLEBUILDER_HPP +#define POKEMONSCRIPTTESTER_BATTLEBUILDER_HPP + +#include +#include +#include +#include "../TestEnvironment.hpp" + +class BattleBuilder { + static PkmnLib::Battling::Battle* CreateSimpleBattle(u32 seed, const ArbUt::StringView& species1, + const ArbUt::StringView& species2, u8 level) { + auto* ctx = asGetActiveContext(); + TestEnvironment* env = static_cast(ctx->GetUserData()); + auto lib = Globals::Library.GetValue(); + + auto mon1 = PkmnLib::Battling::CreatePokemon(lib, species1, level).Build(); + auto p1 = new CreatureLib::Battling::CreatureParty(1); + p1->SwapInto(0, mon1); + + auto mon2 = PkmnLib::Battling::CreatePokemon(lib, species2, level).Build(); + auto p2 = new CreatureLib::Battling::CreatureParty(1); + p1->SwapInto(0, mon2); + + auto battle = new PkmnLib::Battling::Battle( + lib, + {new CreatureLib::Battling::BattleParty(p1, {CreatureLib::Battling::CreatureIndex(0, 0)}), + new CreatureLib::Battling::BattleParty(p2, {CreatureLib::Battling::CreatureIndex(1, 0)})}, + true, // can flee + 2, // 2 sides + 1, // 1 mon per side + seed // with seed + ); + battle->SwitchCreature(0, 0, mon1); + battle->SwitchCreature(1, 0, mon2); + + env->AddGarbage(battle); + env->AddGarbage(p1); + env->AddGarbage(p2); + + return battle; + } + +public: + static void Register(AngelScriptResolver* scriptResolver) { + auto engine = scriptResolver->GetBuilder().GetEngine(); + Ensure(engine->RegisterGlobalFunction("Battle@ CreateSimpleBattle(uint seed, const constString&in species1, " + "const constString&in species2, uint8 level)", + asFUNCTION(CreateSimpleBattle), asCALL_CDECL) >= 0); + } +}; + +#endif // POKEMONSCRIPTTESTER_BATTLEBUILDER_HPP diff --git a/src/Tester/TestFunctions.hpp b/src/Tester/AngelScript/TestFunctions.hpp similarity index 61% rename from src/Tester/TestFunctions.hpp rename to src/Tester/AngelScript/TestFunctions.hpp index ed827d2..5179cb8 100644 --- a/src/Tester/TestFunctions.hpp +++ b/src/Tester/AngelScript/TestFunctions.hpp @@ -2,32 +2,32 @@ #define POKEMONSCRIPTTESTER_TESTFUNCTIONS_HPP #include -#include "AssertionFailed.hpp" -#include "TestEnvironment.hpp" +#include "../RequirementFailed.hpp" +#include "../TestEnvironment.hpp" class TestFunctions { private: - struct AssertionData { + struct RequirementData { std::string FileName; size_t Line; }; - static AssertionData GetAssertionData() { + static RequirementData GetRequirementData() { auto* ctx = asGetActiveContext(); TestEnvironment* env = static_cast(ctx->GetUserData()); env->AssertionCount += 1; auto filename = ctx->GetFunction()->GetScriptSectionName(); auto line = ctx->GetLineNumber(); - return AssertionData{ + return RequirementData{ .FileName = filename, .Line = (size_t)line, }; } - static bool Assert(bool value) { + static bool Require(bool value) { if (!value) { - auto data = GetAssertionData(); - throw AssertionFailed(data.FileName, data.Line); + auto data = GetRequirementData(); + throw RequirementFailed(data.FileName, data.Line); } return true; } @@ -40,25 +40,25 @@ private: eqMsg = ss.str(); \ } - static bool AssertEqualsI32(i32 expected, i32 actual) { + static bool RequireEqualsI32(i32 expected, i32 actual) { if (expected != actual) { - auto data = GetAssertionData(); + auto data = GetRequirementData(); GetEqualityMessage(expected, actual); - throw AssertionFailed(data.FileName, data.Line, eqMsg); + throw RequirementFailed(data.FileName, data.Line, eqMsg); } return true; } - static bool AssertEqualsString(const std::string& expected, const std::string& actual) { + static bool RequireEqualsString(const std::string& expected, const std::string& actual) { if (expected != actual) { - auto data = GetAssertionData(); + auto data = GetRequirementData(); std::string eqMsg; { std::ostringstream ss; ss << "Expected: '" << expected << "', but was: '" << actual << "'"; eqMsg = ss.str(); } - throw AssertionFailed(data.FileName, data.Line, eqMsg); + throw RequirementFailed(data.FileName, data.Line, eqMsg); } return true; } @@ -66,11 +66,11 @@ private: public: static void Register(AngelScriptResolver* scriptResolver) { auto engine = scriptResolver->GetBuilder().GetEngine(); - Ensure(engine->RegisterGlobalFunction("bool Assert(bool expression)", asFUNCTION(Assert), asCALL_CDECL) >= 0); - Ensure(engine->RegisterGlobalFunction("bool AssertEquals(int expected, int actual)", - asFUNCTION(AssertEqualsI32), asCALL_CDECL) >= 0); - Ensure(engine->RegisterGlobalFunction("bool AssertEquals(const string &in expected, const string &in actual)", - asFUNCTION(AssertEqualsString), asCALL_CDECL) >= 0); + Ensure(engine->RegisterGlobalFunction("bool Require(bool expression)", asFUNCTION(Require), asCALL_CDECL) >= 0); + Ensure(engine->RegisterGlobalFunction("bool RequireEquals(int expected, int actual)", + asFUNCTION(RequireEqualsI32), asCALL_CDECL) >= 0); + Ensure(engine->RegisterGlobalFunction("bool RequireEquals(const string &in expected, const string &in actual)", + asFUNCTION(RequireEqualsString), asCALL_CDECL) >= 0); } }; diff --git a/src/Tester/AssertionFailed.hpp b/src/Tester/RequirementFailed.hpp similarity index 71% rename from src/Tester/AssertionFailed.hpp rename to src/Tester/RequirementFailed.hpp index 3be4613..0b91e31 100644 --- a/src/Tester/AssertionFailed.hpp +++ b/src/Tester/RequirementFailed.hpp @@ -1,9 +1,9 @@ -#ifndef POKEMONSCRIPTTESTER_ASSERTIONFAILED_HPP -#define POKEMONSCRIPTTESTER_ASSERTIONFAILED_HPP +#ifndef POKEMONSCRIPTTESTER_REQUIREMENTFAILED_HPP +#define POKEMONSCRIPTTESTER_REQUIREMENTFAILED_HPP #include #include -class AssertionFailed : public std::exception { +class RequirementFailed : public std::exception { static inline std::string& ltrim(std::string& s, const char* t = " \t\n\r\f\v") { s.erase(0, s.find_first_not_of(t)); return s; @@ -26,10 +26,10 @@ class AssertionFailed : public std::exception { char* _msg; public: - AssertionFailed(const std::string& path, size_t line, const std::string& message = "") { + RequirementFailed(const std::string& path, size_t line, const std::string& message = "") { auto l = GetLine(path, line); std::stringstream ss; - ss << "Assertion failed at: " << path << ":" << line << std::endl; + ss << "Requirement failed at: " << path << ":" << line << std::endl; ss << l; if (message.length() > 0) { ss << std::endl << message; @@ -40,9 +40,9 @@ public: _msg[str.length()] = 0; } - ~AssertionFailed() { delete[] _msg; } + ~RequirementFailed() { delete[] _msg; } const char* what() const _GLIBCXX_TXN_SAFE_DYN _GLIBCXX_NOTHROW override { return _msg; } }; -#endif // POKEMONSCRIPTTESTER_ASSERTIONFAILED_HPP +#endif // POKEMONSCRIPTTESTER_REQUIREMENTFAILED_HPP diff --git a/src/Tester/Test.hpp b/src/Tester/Test.hpp index 3edd8ff..6c47ea6 100644 --- a/src/Tester/Test.hpp +++ b/src/Tester/Test.hpp @@ -15,6 +15,7 @@ public: ctx->Prepare(_function); ctx->SetUserData(_env.get()); auto e = ctx->Execute(); + _env->CollectGarbage(); if (e == asEXECUTION_EXCEPTION) { _errorMessage = ctx->GetExceptionString(); _result = TestResult::Failed; diff --git a/src/Tester/TestEnvironment.hpp b/src/Tester/TestEnvironment.hpp index 6eb6e18..395dd80 100644 --- a/src/Tester/TestEnvironment.hpp +++ b/src/Tester/TestEnvironment.hpp @@ -1,8 +1,30 @@ #ifndef POKEMONSCRIPTTESTER_TESTENVIRONMENT_HPP #define POKEMONSCRIPTTESTER_TESTENVIRONMENT_HPP -struct TestEnvironment{ +struct TestEnvironment { size_t AssertionCount = 0; + + template void AddGarbage(T* data) { _garbage.Append(GarbageObject(data)); } + + void CollectGarbage() { + for (auto& o : _garbage) { + o.Destructor(o.Ptr); + } + _garbage.Clear(); + } + +private: + struct GarbageObject { + void* Ptr; + std::function Destructor; + + template GarbageObject(T* ptr) { + Ptr = ptr; + Destructor = [](void* v) { delete static_cast(v); }; + } + }; + + ArbUt::List _garbage; }; #endif // POKEMONSCRIPTTESTER_TESTENVIRONMENT_HPP diff --git a/src/main.cpp b/src/main.cpp index db3d605..5799290 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -3,7 +3,9 @@ #include #include "../extern/args.hpp" #include "BuildData/BuildLibrary.hpp" -#include "Tester/TestFunctions.hpp" +#include "Globals.hpp" +#include "Tester/AngelScript/BattleBuilder.hpp" +#include "Tester/AngelScript/TestFunctions.hpp" #include "Tester/TestRunner.hpp" int main(int argc, char** argv) { @@ -41,13 +43,14 @@ int main(int argc, char** argv) { auto* scriptResolver = dynamic_cast(resolver); scriptResolver->DefineWord("TEST"); TestFunctions::Register(scriptResolver); + BattleBuilder::Register(scriptResolver); }; - auto battleLib = ArbUt::OptionalScopedPtr(BuildLibrary::Build("", initialize)); - if (!battleLib.HasValue()) { + Globals::Library = BuildLibrary::Build("", initialize); + if (!Globals::Library.HasValue()) { return 1; } - auto* scriptResolver = dynamic_cast(battleLib.GetValue()->GetScriptResolver().get()); + auto* scriptResolver = dynamic_cast(Globals::Library.GetValue()->GetScriptResolver().get()); auto testRunner = TestRunner(scriptResolver); auto* engine = scriptResolver->GetBuilder().GetEngine(); return testRunner.RunAll(engine);