Initial work on also doing battle stuff in tests.
This commit is contained in:
parent
3488339d51
commit
c821e6f53b
|
@ -1 +1 @@
|
||||||
Subproject commit 069eadf7c9f94ca4b8616dca8eb7562c9ecf26e0
|
Subproject commit 9b27ad72f18d4924d0851a523b64fbff0c779620
|
|
@ -0,0 +1,3 @@
|
||||||
|
#include "Globals.hpp"
|
||||||
|
|
||||||
|
ArbUt::OptionalUniquePtr<const PkmnLib::Battling::BattleLibrary> Globals::Library = nullptr;
|
|
@ -0,0 +1,10 @@
|
||||||
|
#ifndef POKEMONSCRIPTTESTER_GLOBALS_HPP
|
||||||
|
#define POKEMONSCRIPTTESTER_GLOBALS_HPP
|
||||||
|
#include <PkmnLib/Battling/Library/BattleLibrary.hpp>
|
||||||
|
|
||||||
|
class Globals {
|
||||||
|
public:
|
||||||
|
static ArbUt::OptionalUniquePtr<const PkmnLib::Battling::BattleLibrary> Library;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // POKEMONSCRIPTTESTER_GLOBALS_HPP
|
|
@ -0,0 +1,52 @@
|
||||||
|
#ifndef POKEMONSCRIPTTESTER_BATTLEBUILDER_HPP
|
||||||
|
#define POKEMONSCRIPTTESTER_BATTLEBUILDER_HPP
|
||||||
|
|
||||||
|
#include <PkmnLib/Battling/Battle/Battle.hpp>
|
||||||
|
#include <PkmnLib/Battling/Pokemon/CreatePokemon.hpp>
|
||||||
|
#include <angelscript.h>
|
||||||
|
#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<TestEnvironment*>(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
|
|
@ -2,32 +2,32 @@
|
||||||
#define POKEMONSCRIPTTESTER_TESTFUNCTIONS_HPP
|
#define POKEMONSCRIPTTESTER_TESTFUNCTIONS_HPP
|
||||||
|
|
||||||
#include <angelscript.h>
|
#include <angelscript.h>
|
||||||
#include "AssertionFailed.hpp"
|
#include "../RequirementFailed.hpp"
|
||||||
#include "TestEnvironment.hpp"
|
#include "../TestEnvironment.hpp"
|
||||||
|
|
||||||
class TestFunctions {
|
class TestFunctions {
|
||||||
private:
|
private:
|
||||||
struct AssertionData {
|
struct RequirementData {
|
||||||
std::string FileName;
|
std::string FileName;
|
||||||
size_t Line;
|
size_t Line;
|
||||||
};
|
};
|
||||||
|
|
||||||
static AssertionData GetAssertionData() {
|
static RequirementData GetRequirementData() {
|
||||||
auto* ctx = asGetActiveContext();
|
auto* ctx = asGetActiveContext();
|
||||||
TestEnvironment* env = static_cast<TestEnvironment*>(ctx->GetUserData());
|
TestEnvironment* env = static_cast<TestEnvironment*>(ctx->GetUserData());
|
||||||
env->AssertionCount += 1;
|
env->AssertionCount += 1;
|
||||||
auto filename = ctx->GetFunction()->GetScriptSectionName();
|
auto filename = ctx->GetFunction()->GetScriptSectionName();
|
||||||
auto line = ctx->GetLineNumber();
|
auto line = ctx->GetLineNumber();
|
||||||
return AssertionData{
|
return RequirementData{
|
||||||
.FileName = filename,
|
.FileName = filename,
|
||||||
.Line = (size_t)line,
|
.Line = (size_t)line,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool Assert(bool value) {
|
static bool Require(bool value) {
|
||||||
if (!value) {
|
if (!value) {
|
||||||
auto data = GetAssertionData();
|
auto data = GetRequirementData();
|
||||||
throw AssertionFailed(data.FileName, data.Line);
|
throw RequirementFailed(data.FileName, data.Line);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -40,25 +40,25 @@ private:
|
||||||
eqMsg = ss.str(); \
|
eqMsg = ss.str(); \
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool AssertEqualsI32(i32 expected, i32 actual) {
|
static bool RequireEqualsI32(i32 expected, i32 actual) {
|
||||||
if (expected != actual) {
|
if (expected != actual) {
|
||||||
auto data = GetAssertionData();
|
auto data = GetRequirementData();
|
||||||
GetEqualityMessage(expected, actual);
|
GetEqualityMessage(expected, actual);
|
||||||
throw AssertionFailed(data.FileName, data.Line, eqMsg);
|
throw RequirementFailed(data.FileName, data.Line, eqMsg);
|
||||||
}
|
}
|
||||||
return true;
|
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) {
|
if (expected != actual) {
|
||||||
auto data = GetAssertionData();
|
auto data = GetRequirementData();
|
||||||
std::string eqMsg;
|
std::string eqMsg;
|
||||||
{
|
{
|
||||||
std::ostringstream ss;
|
std::ostringstream ss;
|
||||||
ss << "Expected: '" << expected << "', but was: '" << actual << "'";
|
ss << "Expected: '" << expected << "', but was: '" << actual << "'";
|
||||||
eqMsg = ss.str();
|
eqMsg = ss.str();
|
||||||
}
|
}
|
||||||
throw AssertionFailed(data.FileName, data.Line, eqMsg);
|
throw RequirementFailed(data.FileName, data.Line, eqMsg);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -66,11 +66,11 @@ private:
|
||||||
public:
|
public:
|
||||||
static void Register(AngelScriptResolver* scriptResolver) {
|
static void Register(AngelScriptResolver* scriptResolver) {
|
||||||
auto engine = scriptResolver->GetBuilder().GetEngine();
|
auto engine = scriptResolver->GetBuilder().GetEngine();
|
||||||
Ensure(engine->RegisterGlobalFunction("bool Assert(bool expression)", asFUNCTION(Assert), asCALL_CDECL) >= 0);
|
Ensure(engine->RegisterGlobalFunction("bool Require(bool expression)", asFUNCTION(Require), asCALL_CDECL) >= 0);
|
||||||
Ensure(engine->RegisterGlobalFunction("bool AssertEquals(int expected, int actual)",
|
Ensure(engine->RegisterGlobalFunction("bool RequireEquals(int expected, int actual)",
|
||||||
asFUNCTION(AssertEqualsI32), asCALL_CDECL) >= 0);
|
asFUNCTION(RequireEqualsI32), asCALL_CDECL) >= 0);
|
||||||
Ensure(engine->RegisterGlobalFunction("bool AssertEquals(const string &in expected, const string &in actual)",
|
Ensure(engine->RegisterGlobalFunction("bool RequireEquals(const string &in expected, const string &in actual)",
|
||||||
asFUNCTION(AssertEqualsString), asCALL_CDECL) >= 0);
|
asFUNCTION(RequireEqualsString), asCALL_CDECL) >= 0);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
#ifndef POKEMONSCRIPTTESTER_ASSERTIONFAILED_HPP
|
#ifndef POKEMONSCRIPTTESTER_REQUIREMENTFAILED_HPP
|
||||||
#define POKEMONSCRIPTTESTER_ASSERTIONFAILED_HPP
|
#define POKEMONSCRIPTTESTER_REQUIREMENTFAILED_HPP
|
||||||
#include <exception>
|
#include <exception>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
|
||||||
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") {
|
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));
|
s.erase(0, s.find_first_not_of(t));
|
||||||
return s;
|
return s;
|
||||||
|
@ -26,10 +26,10 @@ class AssertionFailed : public std::exception {
|
||||||
char* _msg;
|
char* _msg;
|
||||||
|
|
||||||
public:
|
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);
|
auto l = GetLine(path, line);
|
||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
ss << "Assertion failed at: " << path << ":" << line << std::endl;
|
ss << "Requirement failed at: " << path << ":" << line << std::endl;
|
||||||
ss << l;
|
ss << l;
|
||||||
if (message.length() > 0) {
|
if (message.length() > 0) {
|
||||||
ss << std::endl << message;
|
ss << std::endl << message;
|
||||||
|
@ -40,9 +40,9 @@ public:
|
||||||
_msg[str.length()] = 0;
|
_msg[str.length()] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
~AssertionFailed() { delete[] _msg; }
|
~RequirementFailed() { delete[] _msg; }
|
||||||
|
|
||||||
const char* what() const _GLIBCXX_TXN_SAFE_DYN _GLIBCXX_NOTHROW override { return _msg; }
|
const char* what() const _GLIBCXX_TXN_SAFE_DYN _GLIBCXX_NOTHROW override { return _msg; }
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // POKEMONSCRIPTTESTER_ASSERTIONFAILED_HPP
|
#endif // POKEMONSCRIPTTESTER_REQUIREMENTFAILED_HPP
|
|
@ -15,6 +15,7 @@ public:
|
||||||
ctx->Prepare(_function);
|
ctx->Prepare(_function);
|
||||||
ctx->SetUserData(_env.get());
|
ctx->SetUserData(_env.get());
|
||||||
auto e = ctx->Execute();
|
auto e = ctx->Execute();
|
||||||
|
_env->CollectGarbage();
|
||||||
if (e == asEXECUTION_EXCEPTION) {
|
if (e == asEXECUTION_EXCEPTION) {
|
||||||
_errorMessage = ctx->GetExceptionString();
|
_errorMessage = ctx->GetExceptionString();
|
||||||
_result = TestResult::Failed;
|
_result = TestResult::Failed;
|
||||||
|
|
|
@ -3,6 +3,28 @@
|
||||||
|
|
||||||
struct TestEnvironment {
|
struct TestEnvironment {
|
||||||
size_t AssertionCount = 0;
|
size_t AssertionCount = 0;
|
||||||
|
|
||||||
|
template <typename T> 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<void(void* ptr)> Destructor;
|
||||||
|
|
||||||
|
template <typename T> GarbageObject(T* ptr) {
|
||||||
|
Ptr = ptr;
|
||||||
|
Destructor = [](void* v) { delete static_cast<T*>(v); };
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
ArbUt::List<GarbageObject> _garbage;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // POKEMONSCRIPTTESTER_TESTENVIRONMENT_HPP
|
#endif // POKEMONSCRIPTTESTER_TESTENVIRONMENT_HPP
|
||||||
|
|
11
src/main.cpp
11
src/main.cpp
|
@ -3,7 +3,9 @@
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include "../extern/args.hpp"
|
#include "../extern/args.hpp"
|
||||||
#include "BuildData/BuildLibrary.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"
|
#include "Tester/TestRunner.hpp"
|
||||||
|
|
||||||
int main(int argc, char** argv) {
|
int main(int argc, char** argv) {
|
||||||
|
@ -41,13 +43,14 @@ int main(int argc, char** argv) {
|
||||||
auto* scriptResolver = dynamic_cast<AngelScriptResolver*>(resolver);
|
auto* scriptResolver = dynamic_cast<AngelScriptResolver*>(resolver);
|
||||||
scriptResolver->DefineWord("TEST");
|
scriptResolver->DefineWord("TEST");
|
||||||
TestFunctions::Register(scriptResolver);
|
TestFunctions::Register(scriptResolver);
|
||||||
|
BattleBuilder::Register(scriptResolver);
|
||||||
};
|
};
|
||||||
|
|
||||||
auto battleLib = ArbUt::OptionalScopedPtr(BuildLibrary::Build("", initialize));
|
Globals::Library = BuildLibrary::Build("", initialize);
|
||||||
if (!battleLib.HasValue()) {
|
if (!Globals::Library.HasValue()) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
auto* scriptResolver = dynamic_cast<AngelScriptResolver*>(battleLib.GetValue()->GetScriptResolver().get());
|
auto* scriptResolver = dynamic_cast<AngelScriptResolver*>(Globals::Library.GetValue()->GetScriptResolver().get());
|
||||||
auto testRunner = TestRunner(scriptResolver);
|
auto testRunner = TestRunner(scriptResolver);
|
||||||
auto* engine = scriptResolver->GetBuilder().GetEngine();
|
auto* engine = scriptResolver->GetBuilder().GetEngine();
|
||||||
return testRunner.RunAll(engine);
|
return testRunner.RunAll(engine);
|
||||||
|
|
Loading…
Reference in New Issue