Files
RAIntegration/tests/services/AchievementRuntimeExports_Tests.cpp

701 lines
28 KiB
C++

#include "services\AchievementRuntimeExports.hh"
#include "services\AchievementRuntime.hh"
#include "tests\RA_UnitTestHelpers.h"
#include "tests\devkit\context\mocks\MockConsoleContext.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\MockConfiguration.hh"
#include "tests\mocks\MockDesktop.hh"
#include "tests\mocks\MockEmulatorContext.hh"
#include "tests\mocks\MockGameContext.hh"
#include "tests\mocks\MockLoginService.hh"
#include <rcheevos\src\rc_client_external.h>
#include <rcheevos\src\rc_client_internal.h>
#include <rcheevos\include\rc_client_raintegration.h>
#include "context\IRcClient.hh"
#include "Exports.hh"
#include "RA_BuildVer.h"
#include "RA_Resource.h"
// the exported functions are not defined in a header anywhere. the only thing that should normally be
// calling them is rcheevos/rc_client_raintegration, and it binds the function pointers using its own
// definition of the functions.
extern "C" API int CCONV _Rcheevos_GetExternalClient(rc_client_external_t* pClientExternal, int nVersion);
extern "C" API const rc_client_raintegration_menu_t* CCONV _Rcheevos_RAIntegrationGetMenu();
extern "C" API void CCONV _Rcheevos_SetRAIntegrationWriteMemoryFunction(rc_client_t* client, rc_client_raintegration_write_memory_func_t handler);
extern "C" API void CCONV _Rcheevos_SetRAIntegrationEventHandler(rc_client_t* client, rc_client_raintegration_event_handler_t handler);
using namespace Microsoft::VisualStudio::CppUnitTestFramework;
namespace ra {
namespace services {
namespace tests {
constexpr int ResetEventBit = (1 << 24);
class AchievementRuntimeExportsHarness : public AchievementRuntime
{
public:
GSL_SUPPRESS_F6 AchievementRuntimeExportsHarness() : AchievementRuntime(false), m_Override(this)
{
InitializeRcClient();
auto* pClient = ra::services::ServiceLocator::Get<ra::context::IRcClient>().GetClient();
mockLoginService.Login("User", "ApiToken");
pClient->user.display_name = "UserDisplay";
pClient->state.user = RC_CLIENT_USER_STATE_LOGGED_IN;
}
~AchievementRuntimeExportsHarness()
{
ResetExternalRcheevosClient();
}
AchievementRuntimeExportsHarness(const AchievementRuntimeExportsHarness&) noexcept = delete;
AchievementRuntimeExportsHarness& operator=(const AchievementRuntimeExportsHarness&) noexcept = delete;
AchievementRuntimeExportsHarness(AchievementRuntimeExportsHarness&&) noexcept = delete;
AchievementRuntimeExportsHarness& operator=(AchievementRuntimeExportsHarness&&) noexcept = delete;
ra::context::mocks::MockEmulatorMemoryContext mockEmulatorMemoryContext;
ra::context::mocks::MockRcClient mockRcClient;
ra::context::mocks::MockUserContext mockUserContext;
ra::data::context::mocks::MockEmulatorContext mockEmulatorContext;
ra::services::mocks::MockConfiguration mockConfiguration;
ra::services::mocks::MockLoginService mockLoginService;
rc_client_t* GetClient() const
{
return ra::services::ServiceLocator::Get<ra::context::IRcClient>().GetClient();
}
void InitializeEventHandler() noexcept
{
s_pRuntimeHarness = this;
_Rcheevos_SetRAIntegrationEventHandler(&m_pExternalClient, DispatchRAIntegrationEvent);
}
void InitializeClientEventHandler() noexcept
{
s_pRuntimeHarness = this;
rc_client_external_t pClient;
memset(&pClient, 0, sizeof(pClient));
_Rcheevos_GetExternalClient(&pClient, 1);
pClient.set_event_handler(&m_pExternalClient, DispatchEvent);
}
void AssertHardcoreChangedEventSeen() const
{
Assert::IsTrue(m_nEventsSeen & (1 << RC_CLIENT_RAINTEGRATION_EVENT_HARDCORE_CHANGED),
L"HARDCORE event not seen");
}
void AssertPauseEventSeen() const
{
Assert::IsTrue(m_nEventsSeen & (1 << RC_CLIENT_RAINTEGRATION_EVENT_PAUSE),
L"PAUSE event not seen");
}
void AssertMenuChangedEventSeen() const
{
Assert::IsTrue(m_nEventsSeen & (1 << RC_CLIENT_RAINTEGRATION_EVENT_MENU_CHANGED),
L"MENU_CHANGED event not seen");
}
void AssertResetEventSeen() const
{
Assert::IsTrue(m_nEventsSeen & ResetEventBit, L"RESET event not seen");
}
void AssertMenuItemCheckedChangedEventSeen(uint32_t nMenuItemId) const
{
Assert::IsTrue(m_nEventsSeen & (1 << RC_CLIENT_RAINTEGRATION_EVENT_MENUITEM_CHECKED_CHANGED),
L"MENUITEM event not seen");
for (const auto nChangedMenuItemId : m_vMenuItemsChanged)
{
if (nChangedMenuItemId == nMenuItemId)
return;
}
Assert::Fail(ra::util::String::Printf(L"MENUITEM check changed event not seen for %d", nMenuItemId).c_str());
}
void ResetSeenEvents() noexcept
{
m_nEventsSeen = 0;
m_vMenuItemsChanged.clear();
}
void InitializeMemoryFunctions() noexcept
{
s_pRuntimeHarness = this;
rc_client_external_t pClient;
memset(&pClient, 0, sizeof(pClient));
_Rcheevos_GetExternalClient(&pClient, 1);
pClient.set_read_memory(&m_pExternalClient, DispatchReadMemory);
_Rcheevos_SetRAIntegrationWriteMemoryFunction(&m_pExternalClient, DispatchWriteMemory);
}
uint8_t GetMemoryByte(uint32_t nAddress)
{
if (nAddress >= m_vMockMemory.size())
return 0;
return m_vMockMemory.at(nAddress);
}
private:
ra::services::ServiceLocator::ServiceOverride<ra::services::AchievementRuntime> m_Override;
static void DispatchEvent(const rc_client_event_t* event, rc_client_t* client)
{
Assert::AreEqual((void*)&s_pRuntimeHarness->m_pExternalClient, (void*)client);
switch (event->type)
{
case RC_CLIENT_EVENT_RESET:
s_pRuntimeHarness->m_nEventsSeen |= ResetEventBit;
break;
}
}
static void DispatchRAIntegrationEvent(const rc_client_raintegration_event_t* event, rc_client_t* client)
{
Assert::AreEqual((void*)&s_pRuntimeHarness->m_pExternalClient, (void*)client);
switch (event->type)
{
case RC_CLIENT_RAINTEGRATION_EVENT_MENUITEM_CHECKED_CHANGED:
s_pRuntimeHarness->m_vMenuItemsChanged.push_back(event->menu_item->id);
break;
}
s_pRuntimeHarness->m_nEventsSeen |= (1 << event->type);
}
static uint32_t DispatchReadMemory(uint32_t address, uint8_t* buffer, uint32_t num_bytes, rc_client_t* client)
{
Assert::AreEqual((void*)&s_pRuntimeHarness->m_pExternalClient, (void*)client);
auto nBytesAvailable = (s_pRuntimeHarness->m_vMockMemory.size() > address) ?
gsl::narrow_cast<uint32_t>(s_pRuntimeHarness->m_vMockMemory.size() - address) : 0;
if (nBytesAvailable > num_bytes)
nBytesAvailable = num_bytes;
if (nBytesAvailable > 0)
memcpy(buffer, &s_pRuntimeHarness->m_vMockMemory.at(address), nBytesAvailable);
return nBytesAvailable;
}
GSL_SUPPRESS_CON3
static void DispatchWriteMemory(uint32_t address, uint8_t* buffer, uint32_t num_bytes, rc_client_t* client)
{
Assert::AreEqual((void*)&s_pRuntimeHarness->m_pExternalClient, (void*)client);
const auto nNextAddress = gsl::narrow_cast<size_t>(address + num_bytes + 1);
if (s_pRuntimeHarness->m_vMockMemory.size() < nNextAddress)
s_pRuntimeHarness->m_vMockMemory.resize(nNextAddress);
memcpy(&s_pRuntimeHarness->m_vMockMemory.at(address), buffer, num_bytes);
}
static AchievementRuntimeExportsHarness* s_pRuntimeHarness;
rc_client_t m_pExternalClient{};
int m_nEventsSeen = 0;
std::vector<uint32_t> m_vMenuItemsChanged;
std::vector<uint8_t> m_vMockMemory;
};
AchievementRuntimeExportsHarness* AchievementRuntimeExportsHarness::s_pRuntimeHarness = nullptr;
TEST_CLASS(AchievementRuntimeExports_Tests)
{
private:
static void AssertMenuItem(const rc_client_raintegration_menu_t* pMenu, int nIndex, uint32_t nId, const char* label)
{
const auto* pItem = &pMenu->items[nIndex];
Assert::AreEqual(nId, pItem->id);
Assert::AreEqual(std::string(label), std::string(pItem->label));
Assert::AreEqual({1}, pItem->enabled);
Assert::AreEqual({0}, pItem->checked);
};
static void AssertMenuItemChecked(const rc_client_raintegration_menu_t* pMenu, int nIndex, uint32_t nId, const char* label)
{
const auto* pItem = &pMenu->items[nIndex];
Assert::AreEqual(nId, pItem->id);
Assert::AreEqual(std::string(label), std::string(pItem->label));
Assert::AreEqual({1}, pItem->enabled);
Assert::AreEqual({1}, pItem->checked);
};
static void AssertMenuSeparator(const rc_client_raintegration_menu_t* pMenu, int nIndex)
{
const auto* pItem = &pMenu->items[nIndex];
Assert::AreEqual(0U, pItem->id);
Assert::IsNull(pItem->label);
Assert::AreEqual({1}, pItem->enabled);
Assert::AreEqual({0}, pItem->checked);
};
GSL_SUPPRESS_TYPE4
static void AssertV1Exports(const rc_client_external_t& pClient)
{
Assert::IsNotNull((void*)pClient.destroy, L"destory not set");
Assert::IsNotNull((void*)pClient.enable_logging, L"enable_logging not set");
Assert::IsNotNull((void*)pClient.set_event_handler, L"set_event_handler not set");
Assert::IsNotNull((void*)pClient.set_read_memory, L"set_read_memory not set");
Assert::IsNotNull((void*)pClient.set_get_time_millisecs, L"set_get_time_millisecs not set");
Assert::IsNotNull((void*)pClient.set_host, L"set_host not set");
Assert::IsNotNull((void*)pClient.get_user_agent_clause, L"set_host not set");
Assert::IsNotNull((void*)pClient.set_hardcore_enabled, L"set_hardcore_enabled not set");
Assert::IsNotNull((void*)pClient.get_hardcore_enabled, L"get_hardcore_enabled not set");
Assert::IsNotNull((void*)pClient.set_unpromoted_enabled, L"set_unpromoted_enabled not set");
Assert::IsNotNull((void*)pClient.get_unpromoted_enabled, L"get_unpromoted_enabled not set");
Assert::IsNotNull((void*)pClient.set_encore_mode_enabled, L"set_encore_mode_enabled not set");
Assert::IsNotNull((void*)pClient.get_encore_mode_enabled, L"get_encore_mode_enabled not set");
Assert::IsNotNull((void*)pClient.set_spectator_mode_enabled, L"set_spectator_mode_enabled not set");
Assert::IsNotNull((void*)pClient.get_spectator_mode_enabled, L"get_spectator_mode_enabled not set");
Assert::IsNotNull((void*)pClient.abort_async, L"abort_async not set");
Assert::IsNotNull((void*)pClient.begin_login_with_password, L"begin_login_with_password not set");
Assert::IsNotNull((void*)pClient.begin_login_with_token, L"begin_login_with_token not set");
Assert::IsNotNull((void*)pClient.logout, L"logout not set");
Assert::IsNotNull((void*)pClient.get_user_info, L"get_user_info not set");
Assert::IsNotNull((void*)pClient.begin_identify_and_load_game, L"begin_identify_and_load_game not set");
Assert::IsNotNull((void*)pClient.begin_load_game, L"begin_load_game not set");
Assert::IsNotNull((void*)pClient.get_game_info, L"get_game_info not set");
Assert::IsNull((void*)pClient.begin_load_subset, L"begin_load_subset set");
Assert::IsNotNull((void*)pClient.get_subset_info, L"get_subset_info not set");
Assert::IsNotNull((void*)pClient.unload_game, L"unload_game not set");
Assert::IsNotNull((void*)pClient.get_user_game_summary, L"get_user_game_summary not set");
Assert::IsNotNull((void*)pClient.begin_change_media, L"begin_change_media not set");
Assert::IsNotNull((void*)pClient.create_achievement_list, L"create_achievement_list not set");
Assert::IsNotNull((void*)pClient.has_achievements, L"has_achievements not set");
Assert::IsNotNull((void*)pClient.get_achievement_info, L"get_achievement_info not set");
Assert::IsNotNull((void*)pClient.create_leaderboard_list, L"create_leaderboard_list not set");
Assert::IsNotNull((void*)pClient.has_leaderboards, L"has_leaderboards not set");
Assert::IsNotNull((void*)pClient.get_leaderboard_info, L"get_leaderboard_info not set");
Assert::IsNotNull((void*)pClient.begin_fetch_leaderboard_entries, L"begin_fetch_leaderboard_entries not set");
Assert::IsNotNull((void*)pClient.begin_fetch_leaderboard_entries_around_user, L"begin_fetch_leaderboard_entries_around_user not set");
Assert::IsNotNull((void*)pClient.get_rich_presence_message, L"get_rich_presence_message not set");
Assert::IsNotNull((void*)pClient.has_rich_presence, L"has_rich_presence not set");
Assert::IsNotNull((void*)pClient.do_frame, L"do_frame not set");
Assert::IsNotNull((void*)pClient.idle, L"idle not set");
Assert::IsNotNull((void*)pClient.is_processing_required, L"is_processing_required not set");
Assert::IsNotNull((void*)pClient.can_pause, L"can_pause not set");
Assert::IsNotNull((void*)pClient.reset, L"reset not set");
Assert::IsNotNull((void*)pClient.progress_size, L"progress_size not set");
Assert::IsNotNull((void*)pClient.serialize_progress, L"serialize_progress not set");
Assert::IsNotNull((void*)pClient.deserialize_progress, L"deserialize_progress not set");
}
GSL_SUPPRESS_TYPE4
static void AssertV2Exports(const rc_client_external_t & pClient)
{
Assert::IsNotNull((void*)pClient.add_game_hash, L"add_game_hash not set");
Assert::IsNotNull((void*)pClient.load_unknown_game, L"load_unknown_game not set");
}
GSL_SUPPRESS_TYPE4
static void AssertV3Exports(const rc_client_external_t & pClient)
{
Assert::IsNotNull((void*)pClient.get_user_info_v3, L"get_user_info_v3 not set");
Assert::IsNotNull((void*)pClient.get_game_info_v3, L"get_game_info_v3 not set");
Assert::IsNotNull((void*)pClient.get_subset_info_v3, L"get_subset_info_v3 not set");
Assert::IsNotNull((void*)pClient.get_achievement_info_v3, L"get_achievement_info_v3 not set");
Assert::IsNotNull((void*)pClient.create_achievement_list_v3, L"create_achievement_list_v3 not set");
}
GSL_SUPPRESS_TYPE4
static void AssertV4Exports(const rc_client_external_t& pClient)
{
Assert::IsNotNull((void*)pClient.get_user_info_v3, L"get_user_info_v3 not set");
Assert::IsNotNull((void*)pClient.get_game_info_v3, L"get_game_info_v3 not set");
Assert::IsNotNull((void*)pClient.get_subset_info_v3, L"get_subset_info_v3 not set");
Assert::IsNotNull((void*)pClient.get_achievement_info_v3, L"get_achievement_info_v3 not set");
Assert::IsNotNull((void*)pClient.create_achievement_list_v3, L"create_achievement_list_v3 not set");
}
GSL_SUPPRESS_TYPE4
static void AssertV5Exports(const rc_client_external_t& pClient)
{
Assert::IsNotNull((void*)pClient.get_user_game_summary_v5, L"get_user_game_summary_v5 not set");
Assert::IsNotNull((void*)pClient.get_user_subset_summary, L"get_user_subset_summary not set");
}
GSL_SUPPRESS_TYPE4
static void AssertV6Exports(const rc_client_external_t& pClient)
{
Assert::IsNotNull((void*)pClient.create_subset_list, L"create_subset_list not set");
}
GSL_SUPPRESS_TYPE4
static void AssertV7Exports(const rc_client_external_t& pClient)
{
Assert::IsNotNull((void*)pClient.get_next_achievement_info, L"get_next_achievement_info not set");
}
public:
TEST_METHOD(TestGetExternalClientV1)
{
AchievementRuntimeExportsHarness runtime;
rc_client_external_t pClient;
memset(&pClient, 0, sizeof(pClient));
_Rcheevos_GetExternalClient(&pClient, 1);
AssertV1Exports(pClient);
Assert::IsTrue(IsExternalRcheevosClient());
}
TEST_METHOD(TestGetExternalClientV2)
{
AchievementRuntimeExportsHarness runtime;
rc_client_external_t pClient;
memset(&pClient, 0, sizeof(pClient));
_Rcheevos_GetExternalClient(&pClient, 2);
AssertV1Exports(pClient);
AssertV2Exports(pClient);
Assert::IsTrue(IsExternalRcheevosClient());
}
TEST_METHOD(TestGetExternalClientV3)
{
AchievementRuntimeExportsHarness runtime;
rc_client_external_t pClient;
memset(&pClient, 0, sizeof(pClient));
_Rcheevos_GetExternalClient(&pClient, 3);
AssertV1Exports(pClient);
AssertV2Exports(pClient);
AssertV3Exports(pClient);
Assert::IsTrue(IsExternalRcheevosClient());
}
TEST_METHOD(TestGetExternalClientV4)
{
AchievementRuntimeExportsHarness runtime;
rc_client_external_t pClient;
memset(&pClient, 0, sizeof(pClient));
_Rcheevos_GetExternalClient(&pClient, 4);
AssertV1Exports(pClient);
AssertV2Exports(pClient);
AssertV3Exports(pClient);
AssertV4Exports(pClient);
Assert::IsTrue(IsExternalRcheevosClient());
}
TEST_METHOD(TestGetExternalClientV5)
{
AchievementRuntimeExportsHarness runtime;
rc_client_external_t pClient;
memset(&pClient, 0, sizeof(pClient));
_Rcheevos_GetExternalClient(&pClient, 5);
AssertV1Exports(pClient);
AssertV2Exports(pClient);
AssertV3Exports(pClient);
AssertV4Exports(pClient);
AssertV5Exports(pClient);
Assert::IsTrue(IsExternalRcheevosClient());
}
TEST_METHOD(TestGetExternalClientV6)
{
AchievementRuntimeExportsHarness runtime;
rc_client_external_t pClient;
memset(&pClient, 0, sizeof(pClient));
_Rcheevos_GetExternalClient(&pClient, 6);
AssertV1Exports(pClient);
AssertV2Exports(pClient);
AssertV3Exports(pClient);
AssertV4Exports(pClient);
AssertV5Exports(pClient);
AssertV6Exports(pClient);
Assert::IsTrue(IsExternalRcheevosClient());
}
TEST_METHOD(TestGetExternalClientV7)
{
AchievementRuntimeExportsHarness runtime;
rc_client_external_t pClient;
memset(&pClient, 0, sizeof(pClient));
_Rcheevos_GetExternalClient(&pClient, 7);
AssertV1Exports(pClient);
AssertV2Exports(pClient);
AssertV3Exports(pClient);
AssertV4Exports(pClient);
AssertV5Exports(pClient);
AssertV6Exports(pClient);
AssertV7Exports(pClient);
Assert::IsTrue(IsExternalRcheevosClient());
}
TEST_METHOD(TestRAIntegrationGetMenu)
{
AchievementRuntimeExportsHarness runtime;
runtime.mockLoginService.Logout();
runtime.InitializeEventHandler();
const rc_client_raintegration_menu_t* pMenu;
pMenu = _Rcheevos_RAIntegrationGetMenu();
Assert::AreEqual(14U, pMenu->num_items);
int nIndex = 0;
AssertMenuItem(pMenu, nIndex++, IDM_RA_HARDCORE_MODE, "&Hardcore Mode");
AssertMenuItem(pMenu, nIndex++, IDM_RA_NON_HARDCORE_WARNING, "Non-Hardcore &Warning");
AssertMenuItem(pMenu, nIndex++, IDM_RA_ONLY_HARDCORE_UNLOCKS, "Only Hardcore Unloc&ks");
AssertMenuSeparator(pMenu, nIndex++);
AssertMenuItem(pMenu, nIndex++, IDM_RA_FILES_OPENALL, "&Open All");
AssertMenuItem(pMenu, nIndex++, IDM_RA_FILES_ACHIEVEMENTS, "Assets Li&st");
AssertMenuItem(pMenu, nIndex++, IDM_RA_FILES_ACHIEVEMENTEDITOR, "Assets &Editor");
AssertMenuItem(pMenu, nIndex++, IDM_RA_FILES_MEMORYFINDER, "&Memory Inspector");
AssertMenuItem(pMenu, nIndex++, IDM_RA_FILES_MEMORYBOOKMARKS, "Memory &Bookmarks");
AssertMenuItem(pMenu, nIndex++, IDM_RA_FILES_CODENOTES, "Memory &Notes");
AssertMenuItem(pMenu, nIndex++, IDM_RA_PARSERICHPRESENCE, "Rich &Presence Monitor");
AssertMenuSeparator(pMenu, nIndex++);
AssertMenuItem(pMenu, nIndex++, IDM_RA_FILES_POINTERFINDER, "Pointer &Finder");
AssertMenuItem(pMenu, nIndex++, IDM_RA_FILES_POINTERINSPECTOR, "Pointer &Inspector");
runtime.mockLoginService.Login("User", "ApiToken");
pMenu = _Rcheevos_RAIntegrationGetMenu();
Assert::AreEqual(20U, pMenu->num_items);
nIndex = 0;
AssertMenuItem(pMenu, nIndex++, IDM_RA_OPENUSERPAGE, "Open my &User Page");
AssertMenuItem(pMenu, nIndex++, IDM_RA_OPENGAMEPAGE, "Open this &Game's Page");
AssertMenuSeparator(pMenu, nIndex++);
AssertMenuItem(pMenu, nIndex++, IDM_RA_HARDCORE_MODE, "&Hardcore Mode");
AssertMenuItem(pMenu, nIndex++, IDM_RA_NON_HARDCORE_WARNING, "Non-Hardcore &Warning");
AssertMenuItem(pMenu, nIndex++, IDM_RA_ONLY_HARDCORE_UNLOCKS, "Only Hardcore Unloc&ks");
AssertMenuSeparator(pMenu, nIndex++);
AssertMenuItem(pMenu, nIndex++, IDM_RA_FILES_OPENALL, "&Open All");
AssertMenuItem(pMenu, nIndex++, IDM_RA_FILES_ACHIEVEMENTS, "Assets Li&st");
AssertMenuItem(pMenu, nIndex++, IDM_RA_FILES_ACHIEVEMENTEDITOR, "Assets &Editor");
AssertMenuItem(pMenu, nIndex++, IDM_RA_FILES_MEMORYFINDER, "&Memory Inspector");
AssertMenuItem(pMenu, nIndex++, IDM_RA_FILES_MEMORYBOOKMARKS, "Memory &Bookmarks");
AssertMenuItem(pMenu, nIndex++, IDM_RA_FILES_CODENOTES, "Memory &Notes");
AssertMenuItem(pMenu, nIndex++, IDM_RA_PARSERICHPRESENCE, "Rich &Presence Monitor");
AssertMenuSeparator(pMenu, nIndex++);
AssertMenuItem(pMenu, nIndex++, IDM_RA_FILES_POINTERFINDER, "Pointer &Finder");
AssertMenuItem(pMenu, nIndex++, IDM_RA_FILES_POINTERINSPECTOR, "Pointer &Inspector");
AssertMenuSeparator(pMenu, nIndex++);
AssertMenuItem(pMenu, nIndex++, IDM_RA_REPORTBROKENACHIEVEMENTS, "&Report Achievement Problem");
AssertMenuItem(pMenu, nIndex++, IDM_RA_GETROMCHECKSUM, "View Game H&ash");
runtime.mockConfiguration.SetFeatureEnabled(ra::services::Feature::Hardcore, true);
runtime.mockConfiguration.SetFeatureEnabled(ra::services::Feature::NonHardcoreWarning, true);
runtime.mockConfiguration.SetFeatureEnabled(ra::services::Feature::OnlyHardcoreUnlocks, true);
pMenu = _Rcheevos_RAIntegrationGetMenu();
Assert::AreEqual(20U, pMenu->num_items);
nIndex = 0;
AssertMenuItem(pMenu, nIndex++, IDM_RA_OPENUSERPAGE, "Open my &User Page");
AssertMenuItem(pMenu, nIndex++, IDM_RA_OPENGAMEPAGE, "Open this &Game's Page");
AssertMenuSeparator(pMenu, nIndex++);
AssertMenuItemChecked(pMenu, nIndex++, IDM_RA_HARDCORE_MODE, "&Hardcore Mode");
AssertMenuItemChecked(pMenu, nIndex++, IDM_RA_NON_HARDCORE_WARNING, "Non-Hardcore &Warning");
AssertMenuItemChecked(pMenu, nIndex++, IDM_RA_ONLY_HARDCORE_UNLOCKS, "Only Hardcore Unloc&ks");
AssertMenuSeparator(pMenu, nIndex++);
AssertMenuItem(pMenu, nIndex++, IDM_RA_FILES_OPENALL, "&Open All");
AssertMenuItem(pMenu, nIndex++, IDM_RA_FILES_ACHIEVEMENTS, "Assets Li&st");
AssertMenuItem(pMenu, nIndex++, IDM_RA_FILES_ACHIEVEMENTEDITOR, "Assets &Editor");
AssertMenuItem(pMenu, nIndex++, IDM_RA_FILES_MEMORYFINDER, "&Memory Inspector");
AssertMenuItem(pMenu, nIndex++, IDM_RA_FILES_MEMORYBOOKMARKS, "Memory &Bookmarks");
AssertMenuItem(pMenu, nIndex++, IDM_RA_FILES_CODENOTES, "Memory &Notes");
AssertMenuItem(pMenu, nIndex++, IDM_RA_PARSERICHPRESENCE, "Rich &Presence Monitor");
AssertMenuSeparator(pMenu, nIndex++);
AssertMenuItem(pMenu, nIndex++, IDM_RA_FILES_POINTERFINDER, "Pointer &Finder");
AssertMenuItem(pMenu, nIndex++, IDM_RA_FILES_POINTERINSPECTOR, "Pointer &Inspector");
AssertMenuSeparator(pMenu, nIndex++);
AssertMenuItem(pMenu, nIndex++, IDM_RA_REPORTBROKENACHIEVEMENTS, "&Report Achievement Problem");
AssertMenuItem(pMenu, nIndex++, IDM_RA_GETROMCHECKSUM, "View Game H&ash");
}
TEST_METHOD(TestSyncHardcore)
{
AchievementRuntimeExportsHarness runtime;
runtime.InitializeEventHandler();
runtime.GetClient()->state.hardcore = 0;
const rc_client_raintegration_menu_t* pMenu;
pMenu = _Rcheevos_RAIntegrationGetMenu();
AssertMenuItem(pMenu, 3, IDM_RA_HARDCORE_MODE, "&Hardcore Mode");
runtime.mockConfiguration.SetFeatureEnabled(ra::services::Feature::Hardcore, true);
SyncClientExternalRAIntegrationMenuItem(IDM_RA_HARDCORE_MODE);
SyncClientExternalHardcoreState();
runtime.AssertHardcoreChangedEventSeen();
runtime.AssertMenuItemCheckedChangedEventSeen(IDM_RA_HARDCORE_MODE);
}
TEST_METHOD(TestReadWriteMemory)
{
AchievementRuntimeExportsHarness runtime;
ra::context::mocks::MockConsoleContext mockConsole(NES, L"NES");
runtime.InitializeMemoryFunctions();
Assert::AreEqual({0}, runtime.GetMemoryByte(1));
Assert::AreEqual({0}, runtime.mockEmulatorMemoryContext.ReadMemoryByte(1));
runtime.mockEmulatorMemoryContext.WriteMemoryByte(1, 3);
Assert::AreEqual({3}, runtime.GetMemoryByte(1));
Assert::AreEqual({3}, runtime.mockEmulatorMemoryContext.ReadMemoryByte(1));
runtime.mockEmulatorMemoryContext.WriteMemoryByte(2, 7);
Assert::AreEqual({7}, runtime.GetMemoryByte(2));
Assert::AreEqual({7}, runtime.mockEmulatorMemoryContext.ReadMemoryByte(2));
Assert::AreEqual({0x0703}, runtime.mockEmulatorMemoryContext.ReadMemory(1, ra::data::Memory::Size::SixteenBit));
}
TEST_METHOD(TestPauseEvent)
{
AchievementRuntimeExportsHarness runtime;
ra::ui::mocks::MockDesktop mockDesktop; // for InvokeOnUIThread
runtime.InitializeEventHandler();
rc_client_external_t pClient;
memset(&pClient, 0, sizeof(pClient));
_Rcheevos_GetExternalClient(&pClient, 1);
runtime.mockEmulatorContext.Pause();
runtime.AssertPauseEventSeen();
}
TEST_METHOD(TestResetEvent)
{
AchievementRuntimeExportsHarness runtime;
ra::ui::mocks::MockDesktop mockDesktop; // for InvokeOnUIThread
runtime.InitializeClientEventHandler();
rc_client_external_t pClient;
memset(&pClient, 0, sizeof(pClient));
_Rcheevos_GetExternalClient(&pClient, 1);
runtime.mockEmulatorContext.Reset();
runtime.AssertResetEventSeen();
}
TEST_METHOD(TestUserAgentClause)
{
AchievementRuntimeExportsHarness runtime;
rc_client_external_t pClient;
memset(&pClient, 0, sizeof(pClient));
_Rcheevos_GetExternalClient(&pClient, 1);
char buffer[32];
Assert::IsTrue(pClient.get_user_agent_clause(buffer, 8) > 8);
Assert::AreEqual("Integra", buffer);
pClient.get_user_agent_clause(buffer, 32);
char* ptr = strchr(buffer, '-');
if (ptr != nullptr)
*ptr = '\0';
Assert::AreEqual("Integration/" RA_INTEGRATION_VERSION, buffer);
}
TEST_METHOD(TestLoadUnknownGame)
{
AchievementRuntimeExportsHarness runtime;
ra::data::context::mocks::MockGameContext mockGameContext;
ra::context::mocks::MockConsoleContext mockConsoleContext;
rc_client_external_t pClient;
memset(&pClient, 0, sizeof(pClient));
_Rcheevos_GetExternalClient(&pClient, 2);
pClient.load_unknown_game("ABCDEF0123456789");
const auto* pGame = rc_client_get_game_info(runtime.GetClient());
Assert::IsNotNull(pGame);
Ensures(pGame != nullptr);
Assert::AreEqual(0U, pGame->id);
Assert::AreEqual("Unknown Game", pGame->title);
Assert::AreEqual(0U, pGame->console_id);
Assert::AreEqual(std::string("ABCDEF0123456789"), mockGameContext.GameHash());
}
TEST_METHOD(TestLoadUnknownGameWithConsole)
{
AchievementRuntimeExportsHarness runtime;
ra::data::context::mocks::MockGameContext mockGameContext;
ra::context::mocks::MockConsoleContext mockConsoleContext;
rc_client_external_t pClient;
memset(&pClient, 0, sizeof(pClient));
_Rcheevos_GetExternalClient(&pClient, 2);
mockConsoleContext.SetId(ConsoleID::GBC);
pClient.load_unknown_game("ABCDEF0123456789");
const auto* pGame = rc_client_get_game_info(runtime.GetClient());
Assert::IsNotNull(pGame);
Ensures(pGame != nullptr);
Assert::AreEqual(0U, pGame->id);
Assert::AreEqual("Unknown Game", pGame->title);
Assert::AreEqual({ RC_CONSOLE_GAMEBOY_COLOR }, pGame->console_id);
Assert::AreEqual(std::string("ABCDEF0123456789"), mockGameContext.GameHash());
}
};
} // namespace tests
} // namespace services
} // namespace ra