diff --git a/src/RA_Integration.vcxproj b/src/RA_Integration.vcxproj index 611699a5..c1ae0ea0 100644 --- a/src/RA_Integration.vcxproj +++ b/src/RA_Integration.vcxproj @@ -84,7 +84,6 @@ - Create @@ -217,7 +216,6 @@ - diff --git a/src/RA_Integration.vcxproj.filters b/src/RA_Integration.vcxproj.filters index 55261723..9c83a149 100644 --- a/src/RA_Integration.vcxproj.filters +++ b/src/RA_Integration.vcxproj.filters @@ -339,9 +339,6 @@ UI\ViewModels - - Data\Models - UI\Win32 @@ -836,9 +833,6 @@ UI\ViewModels - - Data\Models - UI\Win32 diff --git a/src/data/context/GameContext.hh b/src/data/context/GameContext.hh index 3d97f608..7511d0e3 100644 --- a/src/data/context/GameContext.hh +++ b/src/data/context/GameContext.hh @@ -2,6 +2,10 @@ #define RA_DATA_GAMECONTEXT_HH #pragma once +#include "context/IGameContext.hh" + +#include "services/ServiceLocator.hh" + #include "GameAssets.hh" #include @@ -15,10 +19,13 @@ namespace ra { namespace data { namespace context { -class GameContext +class GameContext : public ra::context::IGameContext { public: - GSL_SUPPRESS_F6 GameContext() = default; + GSL_SUPPRESS_F6 GameContext() + : m_IGameContextOverride(this) + { + } virtual ~GameContext() noexcept = default; GameContext(const GameContext&) noexcept = delete; GameContext& operator=(const GameContext&) noexcept = delete; @@ -47,11 +54,6 @@ public: /// bool IsGameLoading() const noexcept { return m_nLoadCount != 0; } - /// - /// Gets the unique identifier of the currently loaded game. - /// - unsigned int GameId() const noexcept { return m_nGameId; } - /// /// Gets the unique identifier of the currently loaded subset game. /// @@ -135,27 +137,6 @@ public: GameAssets& Assets() noexcept { return m_vAssets; } const GameAssets& Assets() const noexcept { return m_vAssets; } - class NotifyTarget - { - public: - NotifyTarget() noexcept = default; - virtual ~NotifyTarget() noexcept = default; - NotifyTarget(const NotifyTarget&) noexcept = delete; - NotifyTarget& operator=(const NotifyTarget&) noexcept = delete; - NotifyTarget(NotifyTarget&&) noexcept = default; - NotifyTarget& operator=(NotifyTarget&&) noexcept = default; - - virtual void OnBeforeActiveGameChanged() noexcept(false) {} - virtual void OnActiveGameChanged() noexcept(false) {} - virtual void OnBeginGameLoad() noexcept(false) {} - virtual void OnEndGameLoad() noexcept(false) {} - virtual void OnMemoryNoteChanged(ra::data::ByteAddress, const std::wstring&) noexcept(false) {} - virtual void OnMemoryNoteMoved(ra::data::ByteAddress, ra::data::ByteAddress, const std::wstring&) noexcept(false) {} - }; - - void AddNotifyTarget(NotifyTarget& pTarget) noexcept { m_vNotifyTargets.Add(pTarget); } - void RemoveNotifyTarget(NotifyTarget& pTarget) noexcept { m_vNotifyTargets.Remove(pTarget); } - void DoFrame(); enum SubsetType @@ -194,6 +175,17 @@ public: void InitializeSubsets(const rc_api_fetch_game_sets_response_t* game_data_response); uint32_t GetGameId(uint32_t nSubsetId) const noexcept; + ra::data::models::MemoryNotesModel& MemoryNotes() override + { + auto* pNotes = m_vAssets.FindMemoryNotes(); + return pNotes ? *pNotes : m_oDefaultNotes; + } + const ra::data::models::MemoryNotesModel& MemoryNotes() const override + { + auto* pNotes = m_vAssets.FindMemoryNotes(); + return pNotes ? *pNotes : m_oDefaultNotes; + } + private: void FinishLoadGame(int nResult, const char* sErrorMessage, bool bWasPaused); void MigrateSubsetUserFiles(); @@ -210,7 +202,6 @@ protected: void BeginLoad(); void EndLoad(); - unsigned int m_nGameId = 0; unsigned int m_nActiveGameId = 0; std::wstring m_sGameTitle; std::string m_sGameHash; @@ -219,14 +210,16 @@ protected: std::vector m_vSubsets; private: - NotifyTargetSet m_vNotifyTargets; - GameAssets m_vAssets; std::atomic m_nLoadCount = 0; int m_nMasteryPopupId = 0; std::mutex m_mLoadMutex; + + // use the mock helper to register as both GameContext and IGameContext + ra::services::ServiceLocator::ServiceOverride m_IGameContextOverride; + ra::data::models::MemoryNotesModel m_oDefaultNotes; }; } // namespace context diff --git a/src/devkit/RADevKit.vcxproj b/src/devkit/RADevKit.vcxproj index b9d19001..30cb6ecc 100644 --- a/src/devkit/RADevKit.vcxproj +++ b/src/devkit/RADevKit.vcxproj @@ -73,6 +73,7 @@ + @@ -82,6 +83,7 @@ + @@ -102,6 +104,7 @@ + diff --git a/src/devkit/RADevKit.vcxproj.filters b/src/devkit/RADevKit.vcxproj.filters index c6039c82..330a3926 100644 --- a/src/devkit/RADevKit.vcxproj.filters +++ b/src/devkit/RADevKit.vcxproj.filters @@ -179,6 +179,8 @@ + + @@ -248,5 +250,6 @@ data\models + \ No newline at end of file diff --git a/src/devkit/context/IGameContext.hh b/src/devkit/context/IGameContext.hh new file mode 100644 index 00000000..21d5464e --- /dev/null +++ b/src/devkit/context/IGameContext.hh @@ -0,0 +1,67 @@ +#ifndef RA_CONTEXT_IGAMECONTEXT_HH +#define RA_CONTEXT_IGAMECONTEXT_HH +#pragma once + +#include "data/Memory.hh" +#include "data/NotifyTargetSet.hh" + +#include + +namespace ra { + +namespace data { +namespace models { + class MemoryNotesModel; +} // namespace models +} // namespace data + +namespace context { + +class IGameContext +{ +public: + IGameContext() noexcept = default; + virtual ~IGameContext() noexcept = default; + IGameContext(const IGameContext&) noexcept = delete; + IGameContext& operator=(const IGameContext&) noexcept = delete; + IGameContext(IGameContext&&) noexcept = delete; + IGameContext& operator=(IGameContext&&) noexcept = delete; + + /// + /// Gets the unique identifier of the currently loaded game. + /// + unsigned int GameId() const noexcept { return m_nGameId; } + + class NotifyTarget + { + public: + NotifyTarget() noexcept = default; + virtual ~NotifyTarget() noexcept = default; + NotifyTarget(const NotifyTarget&) noexcept = delete; + NotifyTarget& operator=(const NotifyTarget&) noexcept = delete; + NotifyTarget(NotifyTarget&&) noexcept = default; + NotifyTarget& operator=(NotifyTarget&&) noexcept = default; + + virtual void OnBeforeActiveGameChanged() noexcept(false) {} + virtual void OnActiveGameChanged() noexcept(false) {} + virtual void OnBeginGameLoad() noexcept(false) {} + virtual void OnEndGameLoad() noexcept(false) {} + virtual void OnMemoryNoteChanged(ra::data::ByteAddress, const std::wstring&) noexcept(false) {} + virtual void OnMemoryNoteMoved(ra::data::ByteAddress, ra::data::ByteAddress, const std::wstring&) noexcept(false) {} + }; + + void AddNotifyTarget(NotifyTarget& pTarget) noexcept { m_vNotifyTargets.Add(pTarget); } + void RemoveNotifyTarget(NotifyTarget& pTarget) noexcept { m_vNotifyTargets.Remove(pTarget); } + + virtual ra::data::models::MemoryNotesModel& MemoryNotes() noexcept(false) = 0; + virtual const ra::data::models::MemoryNotesModel& MemoryNotes() const noexcept(false) = 0; + +protected: + unsigned int m_nGameId = 0; + ra::data::NotifyTargetSet m_vNotifyTargets; +}; + +} // namespace context +} // namespace ra + +#endif // !RA_CONTEXT_IGAMECONTEXT_HH diff --git a/src/data/models/TriggerValidation.cpp b/src/devkit/data/models/TriggerValidation.cpp similarity index 94% rename from src/data/models/TriggerValidation.cpp rename to src/devkit/data/models/TriggerValidation.cpp index 69724f47..786caabe 100644 --- a/src/data/models/TriggerValidation.cpp +++ b/src/devkit/data/models/TriggerValidation.cpp @@ -1,13 +1,15 @@ #include "TriggerValidation.hh" #include "context/IConsoleContext.hh" +#include "context/IEmulatorMemoryContext.hh" +#include "context/IGameContext.hh" + +#include "data/models/MemoryNotesModel.hh" #include "services/ServiceLocator.hh" #include "util/Strings.hh" -#include "data/context/GameContext.hh" - #include #include @@ -115,7 +117,7 @@ static bool ValidateMemoryNotesOperand(const rc_operand_t& pOperand, const ra::d if (nStartAddress != nAddress) { sError.append(L" at "); - sError.append(ra::util::String::Widen(pMemoryContext.FormatAddress(nStartAddress).substr(2))); + sError.append(pMemoryContext.FormatAddress(nStartAddress).substr(2)); } return false; @@ -166,14 +168,12 @@ static bool ValidateMemoryNotesCondSet(const rc_condset_t* pCondSet, const ra::d static bool ValidateMemoryNotes(const rc_trigger_t* pTrigger, std::wstring& sError) { - if (!ra::services::ServiceLocator::Exists()) + if (!ra::services::ServiceLocator::Exists()) return true; - const auto* pNotes = ra::services::ServiceLocator::Get().Assets().FindMemoryNotes(); - if (!pNotes) - return true; + const auto& pNotes = ra::services::ServiceLocator::Get().MemoryNotes(); - if (!ValidateMemoryNotesCondSet(pTrigger->requirement, *pNotes, sError)) + if (!ValidateMemoryNotesCondSet(pTrigger->requirement, pNotes, sError)) { if (pTrigger->alternative) sError = L"Core " + sError; @@ -185,7 +185,7 @@ static bool ValidateMemoryNotes(const rc_trigger_t* pTrigger, std::wstring& sErr for (; pCondSet; pCondSet = pCondSet->next) { nIndex++; - if (!ValidateMemoryNotesCondSet(pCondSet, *pNotes, sError)) + if (!ValidateMemoryNotesCondSet(pCondSet, pNotes, sError)) { sError = ra::util::String::Printf(L"Alt%u %s", nIndex, sError); return false; diff --git a/src/data/models/TriggerValidation.hh b/src/devkit/data/models/TriggerValidation.hh similarity index 70% rename from src/data/models/TriggerValidation.hh rename to src/devkit/data/models/TriggerValidation.hh index ba8a0c35..12d9a548 100644 --- a/src/data/models/TriggerValidation.hh +++ b/src/devkit/data/models/TriggerValidation.hh @@ -1,5 +1,5 @@ -#ifndef RA_DATA_TRIGGER_VALIDATION_H -#define RA_DATA_TRIGGER_VALIDATION_H +#ifndef RA_DATA_MODELS_TRIGGERVALIDATION_H +#define RA_DATA_MODELS_TRIGGERVALIDATION_H #pragma once #include "data\models\AssetModelBase.hh" @@ -18,4 +18,4 @@ public: } // namespace data } // namespace ra -#endif RA_DATA_TRIGGER_VALIDATION_H +#endif RA_DATA_MODELS_TRIGGERVALIDATION_H diff --git a/tests/RA_Integration.Tests.vcxproj b/tests/RA_Integration.Tests.vcxproj index 64cc0a99..2e1257a8 100644 --- a/tests/RA_Integration.Tests.vcxproj +++ b/tests/RA_Integration.Tests.vcxproj @@ -85,7 +85,6 @@ - Create @@ -159,7 +158,6 @@ - diff --git a/tests/RA_Integration.Tests.vcxproj.filters b/tests/RA_Integration.Tests.vcxproj.filters index 74656eab..1aedc3ed 100644 --- a/tests/RA_Integration.Tests.vcxproj.filters +++ b/tests/RA_Integration.Tests.vcxproj.filters @@ -351,12 +351,6 @@ Tests\UI\ViewModels - - Code - - - Tests\Data\Models - Code diff --git a/tests/data/context/GameAssets_Tests.cpp b/tests/data/context/GameAssets_Tests.cpp index 52f48ce9..1fab5989 100644 --- a/tests/data/context/GameAssets_Tests.cpp +++ b/tests/data/context/GameAssets_Tests.cpp @@ -6,6 +6,7 @@ #include "data\models\LocalBadgesModel.hh" #include "tests\RA_UnitTestHelpers.h" +#include "tests\devkit\context\mocks\MockEmulatorMemoryContext.hh" #include "tests\devkit\context\mocks\MockRcClient.hh" #include "tests\devkit\services\mocks\MockLocalStorage.hh" #include "tests\devkit\testutil\AssetAsserts.hh" @@ -30,6 +31,7 @@ TEST_CLASS(GameAssets_Tests) class GameAssetsHarness : public GameAssets { public: + ra::context::mocks::MockEmulatorMemoryContext mockEmulatorMemoryContext; ra::context::mocks::MockRcClient mockRcClient; ra::data::context::mocks::MockGameContext mockGameContext; ra::services::mocks::MockAchievementRuntime mockRuntime; diff --git a/tests/data/models/AchievementModel_Tests.cpp b/tests/data/models/AchievementModel_Tests.cpp index 7bc32167..19d3779a 100644 --- a/tests/data/models/AchievementModel_Tests.cpp +++ b/tests/data/models/AchievementModel_Tests.cpp @@ -8,7 +8,9 @@ #include "tests\RA_UnitTestHelpers.h" #include "tests\data\DataAsserts.hh" +#include "tests\devkit\context\mocks\MockEmulatorMemoryContext.hh" #include "tests\devkit\context\mocks\MockRcClient.hh" +#include "tests\devkit\context\mocks\MockUserContext.hh" #include "tests\devkit\services\mocks\MockClock.hh" #include "tests\devkit\testutil\AssetAsserts.hh" #include "tests\mocks\MockAchievementRuntime.hh" @@ -34,7 +36,9 @@ TEST_CLASS(AchievementModel_Tests) GSL_SUPPRESS_F6 mockRuntime.MockGame(); } + ra::context::mocks::MockEmulatorMemoryContext mockEmulatorMemoryContext; ra::context::mocks::MockRcClient mockRcClient; + ra::context::mocks::MockUserContext mockUserContext; ra::data::context::mocks::MockGameContext mockGameContext; ra::services::impl::StringTextWriter textWriter; ra::services::mocks::MockAchievementRuntime mockRuntime; @@ -127,6 +131,7 @@ TEST_CLASS(AchievementModel_Tests) { AchievementModelHarness achievement; achievement.mockGameContext.SetGameId(22); + achievement.mockGameContext.SetNote(0x1234, L"Note"); achievement.AddLocalBadgesModel(); achievement.SetBadge(L"12345.png"); achievement.CreateServerCheckpoint(); @@ -204,8 +209,12 @@ TEST_CLASS(AchievementModel_Tests) achievement.CreateLocalCheckpoint(); std::string sTrigger; - for (int i = 0; i < 65535/12 - 1; i++) + for (int i = 0; i < 65535 / 12 - 1; i++) + { + achievement.mockGameContext.SetNote(i, L"a"); sTrigger.append(ra::util::String::Printf("0xH00%04X=0_", i)); + } + achievement.mockGameContext.SetNote(0xfff0, L"[32-bit] a"); sTrigger.append("0xX00FFF0=12345"); Assert::AreEqual({65535U}, sTrigger.length()); achievement.SetTrigger(sTrigger); @@ -222,7 +231,6 @@ TEST_CLASS(AchievementModel_Tests) TEST_METHOD(TestDeactivateHidesIndicator) { - AchievementModelHarness achievement; achievement.mockGameContext.SetGameId(22); achievement.SetID(53U); diff --git a/tests/data/models/LeaderboardModel_Tests.cpp b/tests/data/models/LeaderboardModel_Tests.cpp index e27d229f..7aecf4d0 100644 --- a/tests/data/models/LeaderboardModel_Tests.cpp +++ b/tests/data/models/LeaderboardModel_Tests.cpp @@ -6,7 +6,9 @@ #include "tests\RA_UnitTestHelpers.h" +#include "tests\devkit\context\mocks\MockEmulatorMemoryContext.hh" #include "tests\devkit\context\mocks\MockRcClient.hh" +#include "tests\devkit\context\mocks\MockUserContext.hh" #include "tests\devkit\testutil\AssetAsserts.hh" #include "tests\devkit\testutil\ValueAsserts.hh" #include "tests\mocks\MockAchievementRuntime.hh" @@ -27,7 +29,9 @@ TEST_CLASS(LeaderboardModel_Tests) class LeaderboardModelHarness : public LeaderboardModel { public: + ra::context::mocks::MockEmulatorMemoryContext mockEmulatorMemoryContext; ra::context::mocks::MockRcClient mockRcClient; + ra::context::mocks::MockUserContext mockUserContext; ra::data::context::mocks::MockGameContext mockGameContext; ra::services::impl::StringTextWriter textWriter; ra::services::mocks::MockAchievementRuntime mockRuntime; @@ -205,6 +209,8 @@ TEST_CLASS(LeaderboardModel_Tests) TEST_METHOD(TestValidateMissingField) { LeaderboardModelHarness leaderboard; + leaderboard.mockGameContext.SetNote(0x1234, L"a"); + leaderboard.mockGameContext.SetNote(0x2345, L"a"); leaderboard.SetID(1U); leaderboard.SetName(L"Title"); leaderboard.SetDescription(L"Desc"); @@ -236,6 +242,7 @@ TEST_CLASS(LeaderboardModel_Tests) TEST_METHOD(TestValidateInvalidField) { LeaderboardModelHarness leaderboard; + leaderboard.mockGameContext.SetNote(0x1234, L"a"); leaderboard.SetID(1U); leaderboard.SetName(L"Title"); leaderboard.SetDescription(L"Desc"); diff --git a/tests/devkit/RADevKit.Tests.vcxproj b/tests/devkit/RADevKit.Tests.vcxproj index 8a043a86..ade41895 100644 --- a/tests/devkit/RADevKit.Tests.vcxproj +++ b/tests/devkit/RADevKit.Tests.vcxproj @@ -72,9 +72,11 @@ + + diff --git a/tests/devkit/RADevKit.Tests.vcxproj.filters b/tests/devkit/RADevKit.Tests.vcxproj.filters index 0085c27a..4c697283 100644 --- a/tests/devkit/RADevKit.Tests.vcxproj.filters +++ b/tests/devkit/RADevKit.Tests.vcxproj.filters @@ -62,6 +62,7 @@ data\models + @@ -151,5 +152,6 @@ testutil + \ No newline at end of file diff --git a/tests/devkit/context/mocks/MockGameContext.hh b/tests/devkit/context/mocks/MockGameContext.hh new file mode 100644 index 00000000..48e359f1 --- /dev/null +++ b/tests/devkit/context/mocks/MockGameContext.hh @@ -0,0 +1,98 @@ +#ifndef RA_CONTEXT_MOCK_GAMECONTEXT_HH +#define RA_CONTEXT_MOCK_GAMECONTEXT_HH +#pragma once + +#include "context/IGameContext.hh" + +#include "data/models/MemoryNotesModel.hh" + +#include "services/ServiceLocator.hh" + +namespace ra { +namespace context { +namespace mocks { + +class MockGameContext : public IGameContext +{ +public: + GSL_SUPPRESS_F6 MockGameContext() noexcept + : m_Override(this) + { + } + + void SetId(unsigned int nId) noexcept { m_nGameId = nId; } + + ra::data::models::MemoryNotesModel& MemoryNotes() noexcept override { return m_oMemoryNotes; } + const ra::data::models::MemoryNotesModel& MemoryNotes() const noexcept override { return m_oMemoryNotes; } + + bool SetNote(ra::data::ByteAddress nAddress, const std::wstring& sNote) + { + if (m_oMemoryNotes.NoteCount() == 0) + { + m_oMemoryNotes.Initialize( + [this](ra::data::ByteAddress nAddress, const std::wstring& sNote) { + // a note with pointer notation is expected to keep track of where each + // pointed-at note exists. this normally occurs in DoFrame, but for + // the unit tests, force the update immediately after the note is updated + GSL_SUPPRESS_TYPE3 + auto* pNote = const_cast(m_oMemoryNotes.FindMemoryNoteModel(nAddress, false)); + if (pNote && pNote->IsPointer()) + { + const auto& pMemoryContext = ra::services::ServiceLocator::Get(); + pNote->UpdateRawPointerValue(nAddress, pMemoryContext, nullptr); + } + + OnMemoryNoteChanged(nAddress, sNote); + }, + [this](ra::data::ByteAddress nOldAddress, ra::data::ByteAddress nNewAddress, const std::wstring& sNote) { + OnMemoryNoteMoved(nOldAddress, nNewAddress, sNote); + }); + } + + m_oMemoryNotes.SetServerNote(nAddress, sNote); + return true; + } + +private: + void OnMemoryNoteChanged(ra::data::ByteAddress nAddress, const std::wstring& sNewNote) + { + if (m_vNotifyTargets.LockIfNotEmpty()) + { + for (auto& target : m_vNotifyTargets.Targets()) + target.OnMemoryNoteChanged(nAddress, sNewNote); + + m_vNotifyTargets.Unlock(); + } + } + + void OnMemoryNoteMoved(ra::data::ByteAddress nOldAddress, ra::data::ByteAddress nNewAddress, const std::wstring& sNote) + { + if (m_vNotifyTargets.LockIfNotEmpty()) + { + for (auto& target : m_vNotifyTargets.Targets()) + target.OnMemoryNoteMoved(nOldAddress, nNewAddress, sNote); + + m_vNotifyTargets.Unlock(); + } + } + + class MockMemoryNotesModel : public ra::data::models::MemoryNotesModel + { + public: + void Initialize(MemoryNoteChangedFunction fMemoryNoteChanged, MemoryNoteMovedFunction fMemoryNoteMoved) + { + m_fMemoryNoteChanged = fMemoryNoteChanged; + m_fMemoryNoteMoved = fMemoryNoteMoved; + } + }; + + MockMemoryNotesModel m_oMemoryNotes; + + ra::services::ServiceLocator::ServiceOverride m_Override; +}; + +} // namespace mocks +} // namespace context +} // namespace ra + +#endif // !RA_CONTEXT_MOCK_CONSOLECONTEXT_HH diff --git a/tests/data/models/TriggerValidation_Tests.cpp b/tests/devkit/data/models/TriggerValidation_Tests.cpp similarity index 96% rename from tests/data/models/TriggerValidation_Tests.cpp rename to tests/devkit/data/models/TriggerValidation_Tests.cpp index 77982925..b8465425 100644 --- a/tests/data/models/TriggerValidation_Tests.cpp +++ b/tests/devkit/data/models/TriggerValidation_Tests.cpp @@ -1,13 +1,12 @@ -#include "CppUnitTest.h" -#include "data\models\TriggerValidation.hh" +#include "data/models/TriggerValidation.hh" -#include "tests\devkit\context\mocks\MockConsoleContext.hh" -#include "tests\devkit\context\mocks\MockEmulatorMemoryContext.hh" -#include "tests\devkit\context\mocks\MockUserContext.hh" -#include "tests\mocks\MockGameContext.hh" +#include "tests/devkit/context/mocks/MockConsoleContext.hh" +#include "tests/devkit/context/mocks/MockEmulatorMemoryContext.hh" +#include "tests/devkit/context/mocks/MockGameContext.hh" +#include "tests/devkit/context/mocks/MockUserContext.hh" +#include "tests/devkit/testutil/AssetAsserts.hh" -using namespace Microsoft::VisualStudio::CppUnitTestFramework; namespace ra { namespace data { @@ -195,7 +194,7 @@ TEST_CLASS(TriggerValidation_Tests) TEST_METHOD(TestMemoryNoteSizeComparisons) { ra::context::mocks::MockUserContext mockUserContext; - ra::data::context::mocks::MockGameContext mockGameContext; + ra::context::mocks::MockGameContext mockGameContext; ra::context::mocks::MockEmulatorMemoryContext mockEmulatorMemoryContext; mockGameContext.SetNote(0x0008, L"[8-bit] Byte address"); mockGameContext.SetNote(0x0010, L"[16-bit] Word address"); diff --git a/tests/ui/viewmodels/AssetEditorViewModel_Tests.cpp b/tests/ui/viewmodels/AssetEditorViewModel_Tests.cpp index 68378974..ff0d4fc2 100644 --- a/tests/ui/viewmodels/AssetEditorViewModel_Tests.cpp +++ b/tests/ui/viewmodels/AssetEditorViewModel_Tests.cpp @@ -13,6 +13,7 @@ #include "tests\devkit\context\mocks\MockEmulatorMemoryContext.hh" #include "tests\devkit\context\mocks\MockRcClient.hh" +#include "tests\devkit\context\mocks\MockUserContext.hh" #include "tests\devkit\services\mocks\MockClock.hh" #include "tests\devkit\services\mocks\MockFileSystem.hh" #include "tests\devkit\services\mocks\MockThreadPool.hh" @@ -71,6 +72,7 @@ TEST_CLASS(AssetEditorViewModel_Tests) ra::context::mocks::MockEmulatorMemoryContext mockEmulatorMemoryContext; ra::context::mocks::MockRcClient mockRcClient; + ra::context::mocks::MockUserContext mockUserContext; ra::services::mocks::MockAchievementRuntime mockRuntime; ra::services::mocks::MockClock mockClock; ra::services::mocks::MockConfiguration mockConfiguration; @@ -526,6 +528,7 @@ TEST_CLASS(AssetEditorViewModel_Tests) TEST_METHOD(TestLoadAchievementValidationError) { AssetEditorViewModelHarness editor; + editor.mockGameContext.SetNote(0x1234, L"a"); AchievementModel achievement; achievement.SetName(L"Test Achievement"); achievement.SetID(1234U); @@ -534,7 +537,7 @@ TEST_CLASS(AssetEditorViewModel_Tests) achievement.SetCategory(AssetCategory::Unofficial); achievement.SetPoints(10); achievement.SetBadge(L"58329"); - achievement.SetTrigger("M:0x1234=10"); + achievement.SetTrigger("M:0xH1234=10"); achievement.CreateServerCheckpoint(); achievement.CreateLocalCheckpoint(); @@ -565,6 +568,7 @@ TEST_CLASS(AssetEditorViewModel_Tests) TEST_METHOD(TestLoadAchievementValidationErrorCancel) { AssetEditorViewModelHarness editor; + editor.mockGameContext.SetNote(0x1234, L"a"); AchievementModel achievement; achievement.SetName(L"Test Achievement"); achievement.SetID(1234U); @@ -573,7 +577,7 @@ TEST_CLASS(AssetEditorViewModel_Tests) achievement.SetCategory(AssetCategory::Unofficial); achievement.SetPoints(10); achievement.SetBadge(L"58329"); - achievement.SetTrigger("M:0x1234=10"); + achievement.SetTrigger("M:0xH1234=10"); achievement.CreateServerCheckpoint(); achievement.CreateLocalCheckpoint(); @@ -606,6 +610,7 @@ TEST_CLASS(AssetEditorViewModel_Tests) TEST_METHOD(TestLoadAchievementValidationErrorDeleted) { AssetEditorViewModelHarness editor; + editor.mockGameContext.SetNote(0x1234, L"a"); AchievementModel achievement; achievement.SetName(L"Test Achievement"); achievement.SetID(1234U); @@ -614,7 +619,7 @@ TEST_CLASS(AssetEditorViewModel_Tests) achievement.SetCategory(AssetCategory::Unofficial); achievement.SetPoints(10); achievement.SetBadge(L"58329"); - achievement.SetTrigger("M:0x1234=10"); + achievement.SetTrigger("M:0xH1234=10"); achievement.CreateServerCheckpoint(); achievement.CreateLocalCheckpoint(); @@ -640,6 +645,7 @@ TEST_CLASS(AssetEditorViewModel_Tests) TEST_METHOD(TestLoadAchievementForcedValidationError) { AssetEditorViewModelHarness editor; + editor.mockGameContext.SetNote(0x1234, L"a"); AchievementModel achievement; achievement.SetName(L"Test Achievement"); achievement.SetID(1234U); @@ -648,7 +654,7 @@ TEST_CLASS(AssetEditorViewModel_Tests) achievement.SetCategory(AssetCategory::Unofficial); achievement.SetPoints(10); achievement.SetBadge(L"58329"); - achievement.SetTrigger("M:0x1234=10"); + achievement.SetTrigger("M:0xH1234=10"); achievement.CreateServerCheckpoint(); achievement.CreateLocalCheckpoint(); @@ -672,6 +678,8 @@ TEST_CLASS(AssetEditorViewModel_Tests) TEST_METHOD(TestLoadLeaderboard) { AssetEditorViewModelHarness editor; + editor.mockGameContext.SetNote(0x1234, L"a"); + editor.mockGameContext.SetNote(0x2345, L"a"); LeaderboardModel leaderboard; leaderboard.SetName(L"Test Leaderboard"); leaderboard.SetID(1234U); diff --git a/tests/ui/viewmodels/AssetListViewModel_Tests.cpp b/tests/ui/viewmodels/AssetListViewModel_Tests.cpp index ff5622d8..e4a45f1e 100644 --- a/tests/ui/viewmodels/AssetListViewModel_Tests.cpp +++ b/tests/ui/viewmodels/AssetListViewModel_Tests.cpp @@ -2606,11 +2606,12 @@ TEST_CLASS(AssetListViewModel_Tests) TEST_METHOD(TestSaveSelectedValidationWarning) { AssetListViewModelHarness vmAssetList; + vmAssetList.mockGameContext.SetNote(0x1234, L"[16-bit] a"); vmAssetList.MockGameId(22U); - vmAssetList.AddAchievement(AssetCategory::Core, 5, L"Test1", L"Desc1", L"12345", "0xH1234=1"); + vmAssetList.AddAchievement(AssetCategory::Core, 5, L"Test1", L"Desc1", L"12345", "0x1234=1"); vmAssetList.AddAchievement(AssetCategory::Core, 7, L"Test2", L"Desc2", L"11111", "0xH1111=1"); - auto* pItem = dynamic_cast(vmAssetList.mockGameContext.Assets().GetItemAt(0)); + auto* pItem = vmAssetList.mockGameContext.Assets().FindAchievement(2); Expects(pItem != nullptr); pItem->SetName(L"Test1b"); pItem->SetTrigger("A:0x1234"); @@ -2624,7 +2625,7 @@ TEST_CLASS(AssetListViewModel_Tests) // invalid item can still be saved const auto& sText = vmAssetList.GetUserFile(L"22"); - AssertContains(sText, "1:\"A:0x1234\":Test1b:Desc1:::::5:::::12345"); + AssertContains(sText, "2:\"A:0x1234\":Test1b:Desc1:::::5:::::12345"); Assert::AreEqual(std::wstring(L"Condition 1: AddSource condition type expects another condition to follow"), pItem->GetValidationError()); @@ -2633,7 +2634,7 @@ TEST_CLASS(AssetListViewModel_Tests) // invalid item can still be saved const auto& sText2 = vmAssetList.GetUserFile(L"22"); - AssertContains(sText2, "1:\"A:0x1234\":Test1c:Desc1:::::5:::::12345"); + AssertContains(sText2, "2:\"A:0x1234\":Test1c:Desc1:::::5:::::12345"); } TEST_METHOD(TestSaveSelectedPublishCoreModified)