BuffTests migrated. Release Build 13440.
Some checks failed
Emscripten Build / Build_and_Deploy_Web_Build (push) Failing after 4m26s
Emscripten Build / UnitTesting (push) Failing after 1m49s

This commit is contained in:
AMay 2026-04-30 14:38:29 -05:00
parent a2e8c7740a
commit 6f03946d4d
7 changed files with 320 additions and 5 deletions

View File

@ -269,8 +269,7 @@
<Command>powershell.exe -ExecutionPolicy Bypass -NoProfile -NonInteractive -File update_version.ps1 "./version.h"</Command>
</PreBuildEvent>
<PostBuildEvent>
<Command>
</Command>
<Command>powershell.exe -ExecutionPolicy Bypass -NoProfile -NonInteractive -File ../unit-testing-prebuild.ps1</Command>
</PostBuildEvent>
<Lib>
<AdditionalDependencies>discord_game_sdk.dll.lib;freetype.lib;steam_api64.lib;$(CoreLibraryDependencies);%(AdditionalDependencies);</AdditionalDependencies>
@ -422,6 +421,7 @@
</SubType>
</ClInclude>
<ClInclude Include="FriendlyType.h" />
<ClInclude Include="GameHelper.h" />
<ClInclude Include="HurtDamageInfo.h">
<SubType>
</SubType>
@ -849,6 +849,7 @@
<SubType>
</SubType>
</ClCompile>
<ClCompile Include="BuffTests.cpp" />
<ClCompile Include="Bullet.cpp">
<SubType>
</SubType>

View File

@ -112,6 +112,9 @@
<Filter Include="Source Files\Unit Tests">
<UniqueIdentifier>{38efdf17-2483-4a53-8598-e8cebb722137}</UniqueIdentifier>
</Filter>
<Filter Include="Header Files\Unit Testing">
<UniqueIdentifier>{64d4cc9f-7c64-4939-9483-ddd2e3ad4bba}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ClInclude Include="olcPixelGameEngine.h">
@ -738,6 +741,9 @@
<ClInclude Include="catch.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="GameHelper.h">
<Filter>Header Files\Unit Testing</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="Player.cpp">
@ -1394,6 +1400,9 @@
<ClCompile Include="GeometryTests.cpp">
<Filter>Source Files\Unit Tests</Filter>
</ClCompile>
<ClCompile Include="BuffTests.cpp">
<Filter>Source Files\Unit Tests</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<None Include="cpp.hint" />

View File

@ -0,0 +1,187 @@
#pragma region License
/*
License (OLC-3)
~~~~~~~~~~~~~~~
Copyright 2026 Amy Sigona <sigonasr2@gmail.com>
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions or derivations of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions or derivative works in binary form must reproduce the above
copyright notice. This list of conditions and the following disclaimer must be
reproduced in the documentation and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors may
be used to endorse or promote products derived from this software without specific
prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
SUCH DAMAGE.
Portions of this software are copyright © 2024 The FreeType
Project (www.freetype.org). Please see LICENSE_FT.txt for more information.
All rights reserved.
*/
#pragma endregion
#include "AdventuresInLestoria.h"
#include "config.h"
#include "ItemDrop.h"
#include "Tutorial.h"
#include "DamageNumber.h"
#include "GameHelper.h"
#include"catch.h"
using namespace olc::utils;
INCLUDE_INITIALIZEGAMECONFIGURATIONS
INCLUDE_game
INCLUDE_GFX
INCLUDE_DAMAGENUMBER_LIST
class BuffTests{
public:
inline BuffTests(){
SetupTestMonster();
SetupMockMap();
}
inline ~BuffTests(){
testGame->EndGame();
testGame->OnUserUpdate(0.f);
testGame.reset();
}
std::unique_ptr<AiL>testGame;
#pragma region Setup Functions
void SetupTestMonster(){
InitializeGameConfigurations();
testGame.reset(new AiL(true));
ItemAttribute::Initialize();
ItemInfo::InitializeItems();
testGame->InitializeGraphics();
testGame->InitializeClasses();
sig::Animation::InitializeAnimations();
testGame->InitializeDefaultKeybinds();
testGame->InitializePlayer();
sig::Animation::SetupPlayerAnimations();
Menu::InitializeMenus();
Tutorial::Initialize();
Stats::InitializeDamageReductionTable();
Monster::InitializeStrategies();
GameState::Initialize();
GameState::STATE=GameState::states.at(States::State::GAME_RUN);
testGame->ResetLevelStates();
#pragma region Setup a fake test map
game->MAP_DATA.Unlock();
game->MAP_DATA["CAMPAIGN_1_1"];
Game::_SetCurrentLevel("CAMPAIGN_1_1");
ItemDrop::ClearDrops();
#pragma endregion
MonsterData testMonsterData{"TestName","Test Monster",30,10,5,{MonsterDropData{"Health Potion",100.f,1,1}},200.f};
MONSTER_DATA["TestName"]=testMonsterData;
Menu::themes.SetInitialized();
GFX.SetInitialized();
DAMAGENUMBER_LIST.clear();
game->MAP_DATA.SetInitialized();
}
void SetupMockMap(){
game->MAP_DATA.at("CAMPAIGN_1_1")=Map{};
ItemDrop::ClearDrops();
}
#pragma endregion
};
TEST(BuffTests,"AddBuffMonsterCallbackExpireFunctionTest") {
Monster&m{game->SpawnMonster({},MONSTER_DATA.at("TestName"))};
Game::Update(0.f);
REQUIRE(size_t(0)==m.GetBuffs(BuffType::AFFECTED_BY_LIGHTNING_BOLT).size());
m.AddBuff(BuffType::AFFECTED_BY_LIGHTNING_BOLT,3.f,1,[](std::weak_ptr<Monster>attachedTarget,Buff&b){attachedTarget.lock()->Hurt(5,attachedTarget.lock()->OnUpperLevel(),attachedTarget.lock()->GetZ());});
REQUIRE(size_t(1)==m.GetBuffs(BuffType::AFFECTED_BY_LIGHTNING_BOLT).size());
Game::Update(0.f);
Game::Update(3.f);
REQUIRE(25==m.GetHealth());
}
TEST(BuffTests,"AddBuffPlayerCallbackExpireFunctionTest"){
REQUIRE(size_t(0)==game->GetPlayer()->GetBuffs(BuffType::AFFECTED_BY_LIGHTNING_BOLT).size());
game->GetPlayer()->AddBuff(BuffType::AFFECTED_BY_LIGHTNING_BOLT,3.f,1,[](Player*attachedTarget,Buff&b){attachedTarget->Hurt(5,attachedTarget->OnUpperLevel(),attachedTarget->GetZ());});
Game::Update(0.f);
REQUIRE(size_t(1)==game->GetPlayer()->GetBuffs(BuffType::AFFECTED_BY_LIGHTNING_BOLT).size());
Game::Update(0.f);
Game::Update(3.f);
REQUIRE(95==game->GetPlayer()->GetHealth());
}
TEST(BuffTests,"MonsterHasBuffFunctionTest"){
Monster&m{game->SpawnMonster({},MONSTER_DATA.at("TestName"))};
Game::Update(0.f);
REQUIRE(!m.HasBuff(BuffType::SPEEDBOOST));
m.AddBuff(BuffType::ADRENALINE_RUSH,1.f,1.f);
REQUIRE(!m.HasBuff(BuffType::SPEEDBOOST));
m.AddBuff(BuffType::SPEEDBOOST,1.f,1.f);
REQUIRE(m.HasBuff(BuffType::SPEEDBOOST));
m.AddBuff(BuffType::SPEEDBOOST,2.f,1.f);
REQUIRE(m.HasBuff(BuffType::SPEEDBOOST));
Game::Update(0.f);
Game::Update(1.f);
REQUIRE(m.HasBuff(BuffType::SPEEDBOOST));
Game::Update(1.f);
REQUIRE(!m.HasBuff(BuffType::SPEEDBOOST));
m.AddBuff(BuffType::SPEEDBOOST,1.f,1.f);
m.RemoveBuff(BuffType::SPEEDBOOST);
REQUIRE(!m.HasBuff(BuffType::SPEEDBOOST));
}
TEST(BuffTests,"PlayerHasBuffFunctionTest"){
REQUIRE(!game->GetPlayer()->HasBuff(BuffType::SPEEDBOOST));
Game::AddBuffToPlayer(BuffType::ADRENALINE_RUSH,1.f,1.f);
REQUIRE(!game->GetPlayer()->HasBuff(BuffType::SPEEDBOOST));
Game::AddBuffToPlayer(BuffType::SPEEDBOOST,1.f,1.f);
REQUIRE(game->GetPlayer()->HasBuff(BuffType::SPEEDBOOST));
Game::AddBuffToPlayer(BuffType::SPEEDBOOST,2.f,1.f);
REQUIRE(game->GetPlayer()->HasBuff(BuffType::SPEEDBOOST));
Game::Update(0.f);
Game::Update(1.f);
REQUIRE(game->GetPlayer()->HasBuff(BuffType::SPEEDBOOST));
Game::Update(1.f);
REQUIRE(!game->GetPlayer()->HasBuff(BuffType::SPEEDBOOST));
Game::AddBuffToPlayer(BuffType::SPEEDBOOST,1.f,1.f);
game->GetPlayer()->RemoveBuff(BuffType::SPEEDBOOST);
REQUIRE(!game->GetPlayer()->HasBuff(BuffType::SPEEDBOOST));
}
TEST(BuffTests,"PlayerDoesNotImmediatelyReceiveBuffTest"){
REQUIRE(!game->GetPlayer()->HasBuff(BuffType::SPEEDBOOST));
game->GetPlayer()->AddBuff(BuffType::SPEEDBOOST,1.f,1.f);
REQUIRE(!game->GetPlayer()->HasBuff(BuffType::SPEEDBOOST));
Game::Update(0.f);
REQUIRE(game->GetPlayer()->HasBuff(BuffType::SPEEDBOOST));
}
TEST(BuffTests,"MonsterGetBuffFunctionTest"){
Monster&m{game->SpawnMonster({},MONSTER_DATA.at("TestName"))};
Game::Update(0.f);
REQUIRE(!bool(m.GetBuff(BuffType::ADRENALINE_RUSH)));
m.AddBuff(BuffType::ADRENALINE_RUSH,1.f,1.f);
m.AddBuff(BuffType::SPEEDBOOST,1.f,1.f);
m.AddBuff(BuffType::SPEEDBOOST,2.f,1.f);
Game::Update(0.f);
REQUIRE(bool(m.GetBuff(BuffType::ADRENALINE_RUSH)));
REQUIRE(bool(m.GetBuff(BuffType::SPEEDBOOST)));
REQUIRE(1.f==(*m.GetBuff(BuffType::SPEEDBOOST)).lifetime);
Game::Update(1.f);
REQUIRE(1.f==(*m.GetBuff(BuffType::SPEEDBOOST)).lifetime);
Game::Update(1.f);
REQUIRE(!bool(m.GetBuff(BuffType::SPEEDBOOST)));
}

View File

@ -0,0 +1,118 @@
#pragma region License
/*
License (OLC-3)
~~~~~~~~~~~~~~~
Copyright 2026 Amy Sigona <sigonasr2@gmail.com>
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions or derivations of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions or derivative works in binary form must reproduce the above
copyright notice. This list of conditions and the following disclaimer must be
reproduced in the documentation and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors may
be used to endorse or promote products derived from this software without specific
prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
SUCH DAMAGE.
Portions of this software are copyright © 2024 The FreeType
Project (www.freetype.org). Please see LICENSE_FT.txt for more information.
All rights reserved.
*/
#pragma endregion
#pragma once
#include "CppUnitTest.h"
#include "AdventuresInLestoria.h"
INCLUDE_game
using namespace Microsoft::VisualStudio::CppUnitTestFramework;
namespace Game{
enum class CastWaitProperty{
WAIT_FOR_CAST_TIME,
NO_WAIT,
};
inline void Update(const float fElapsedTime){
game->SetElapsedTime(fElapsedTime);
game->OnUserUpdate(fElapsedTime);
}
inline void CastAbilityAtLocation(Ability&ability,const vf2d&worldLoc,const CastWaitProperty castWaitTime=CastWaitProperty::WAIT_FOR_CAST_TIME){ //NOTE: screenLoc is the actual screen coordinates, NOT the world coordinates! You are defining the mouse position essentially.
game->GetPlayer()->SetTestScreenAimingLocation(worldLoc);
game->GetPlayer()->PrepareCast(ability);
game->GetPlayer()->CastSpell(ability);
Game::Update(ability.precastInfo.castTime);
}
inline void ChangeClass(Player*&player_in,const Class&cl){
game->ResetPlayerAndChangeClass(cl);
player_in=game->GetPlayer();
}
inline std::weak_ptr<Item>GiveAndEquipEnchantedRing(const std::string_view enchantName,const EquipSlot slot=EquipSlot::RING1){
std::weak_ptr<Item>nullRing{Inventory::AddItem("Null Ring"s)};
Inventory::EquipItem(nullRing,slot);
nullRing.lock()->_EnchantItem(enchantName);
return nullRing;
}
//Adds the buff directly to the player instead of the buffs added list. (By calling an update tick.)
inline void AddBuffToPlayer(BuffType type,float duration,float intensity){
game->GetPlayer()->AddBuff(type,duration,intensity);
Update(0.f);
}
//NOTE: If adding a % increase stat, please use the percentage version! 100% = 1!!
inline void AddBuffToPlayer(BuffType type,float duration,float intensity,std::set<ItemAttribute>attr){
game->GetPlayer()->AddBuff(type,duration,intensity,attr);
Update(0.f);
}
//NOTE: If adding a % increase stat, please use the percentage version! 100% = 1!!
inline void AddBuffToPlayer(BuffType type,float duration,float intensity,std::set<std::string>attr){
game->GetPlayer()->AddBuff(type,duration,intensity,attr);
Update(0.f);
}
inline void ResetPlayerAndChangeClass(Class cl,Player*&pl,AiL*const game){
game->ResetPlayerAndChangeClass(cl);
pl=game->GetPlayer(); //The player pointer has been reassigned...
}
inline void LoadLevelWithTMX(const std::string&mapKeyname,AiL*const game){
game->InitializeLevel("map_path"_S+DATA["Levels"][mapKeyname]["Map File"].GetString(),mapKeyname);
game->SetupLevel(game->MAP_DATA[mapKeyname]);
_SetCurrentLevel(mapKeyname);
}
inline void LoadFakeLevel(const std::string&mapKeyname,AiL*const game){
game->MAP_DATA.at(mapKeyname).name=mapKeyname;
game->SetupLevel(game->MAP_DATA[mapKeyname]);
_SetCurrentLevel(mapKeyname);
}
//NOTE: This will modify the currentLevel variable without triggering anything else in-game, this will normally mess up the state in the game. Ideally this is only used when initializing a test level.
inline void _SetCurrentLevel(const MapName map){
game->ResetLevelStates();
game->currentLevel=map;
}
}
namespace Test
{
template<class T>
inline static void InRange(T initialVal,std::pair<T,T>range,std::wstring_view assertMessage){
Assert::IsTrue(initialVal>=range.first&&initialVal<=range.second,std::format(L"Expected: {}~{} Actual: {} - {}",range.first,range.second,initialVal,assertMessage).c_str());
}
}

View File

@ -39,7 +39,7 @@ All rights reserved.
#define VERSION_MAJOR 1
#define VERSION_MINOR 3
#define VERSION_PATCH 0
#define VERSION_BUILD 13425
#define VERSION_BUILD 13440
#define stringify(a) stringify_(a)
#define stringify_(a) #a

View File

@ -247,12 +247,12 @@ const std::string util::toLower(const std::string oldStr){
const std::string util::GetCaseInsensitiveFilename(const std::string&filename){
if(std::filesystem::exists(filename))return filename;
if(!std::filesystem::path{filename}.has_parent_path())ERR("WARNING! Invalid path {} for filename {}! THIS SHOULD NOT BE HAPPENING!");
if(!std::filesystem::path{filename}.has_parent_path())ERR(std::format("WARNING! Invalid path {} for filename {}! THIS SHOULD NOT BE HAPPENING!",std::filesystem::path{filename}.string(),filename));
for(auto&path:std::filesystem::recursive_directory_iterator(std::filesystem::path{filename}.parent_path())){
if(path.is_regular_file()&&util::toLower(path.path().filename().string())==util::toLower(std::filesystem::path{filename}.filename().string())){
return path.path().string();
}
}
ERR("WARNING! Could not find or match case for filename {}! THIS SHOULD NOT BE HAPPENING!");
ERR(std::format("WARNING! Could not find or match case for filename {}! THIS SHOULD NOT BE HAPPENING!",filename));
std::unreachable();
}