diff --git a/src/modules/fancyzones/lib/JsonHelpers.cpp b/src/modules/fancyzones/lib/JsonHelpers.cpp index a057ca1cd0..b3a2cc5162 100644 --- a/src/modules/fancyzones/lib/JsonHelpers.cpp +++ b/src/modules/fancyzones/lib/JsonHelpers.cpp @@ -10,6 +10,7 @@ #include #include #include +#include namespace { @@ -46,6 +47,59 @@ namespace namespace JSONHelpers { + bool isValidGuid(const std::wstring& str) + { + GUID id; + return SUCCEEDED_LOG(CLSIDFromString(str.c_str(), &id)); + } + + bool isValidDeviceId(const std::wstring& str) + { + std::wstring temp; + std::vector parts; + std::wstringstream wss(str); + while (std::getline(wss, temp, L'_')) + { + parts.push_back(temp); + } + + if (parts.size() != 4) + { + return false; + } + + /* + Refer to ZoneWindowUtils::GenerateUniqueId parts contain: + 1. monitor id [string] + 2. width of device [int] + 3. height of device [int] + 4. virtual desktop id (GUID) [string] + */ + try + { + //check if resolution contain only digits + for (const auto& c : parts[1]) + { + std::stoi(std::wstring(&c)); + } + for (const auto& c : parts[2]) + { + std::stoi(std::wstring(&c)); + } + } + catch (const std::exception&) + { + return false; + } + + if (!isValidGuid(parts[3]) || parts[0].empty()) + { + return false; + } + + return true; + } + json::JsonArray NumVecToJsonArray(const std::vector& vec) { json::JsonArray arr; @@ -733,10 +787,14 @@ namespace JSONHelpers try { ZoneSetData zoneSetData; - zoneSetData.uuid = zoneSet.GetNamedString(L"uuid"); zoneSetData.type = TypeFromString(std::wstring{ zoneSet.GetNamedString(L"type") }); + if (!isValidGuid(zoneSetData.uuid)) + { + return std::nullopt; + } + return zoneSetData; } catch (const winrt::hresult_error&) @@ -768,6 +826,11 @@ namespace JSONHelpers result.data.deviceId = zoneSet.GetNamedString(L"device-id"); result.data.zoneSetUuid = zoneSet.GetNamedString(L"zoneset-uuid"); + if (!isValidGuid(result.data.zoneSetUuid) || !isValidDeviceId(result.data.deviceId)) + { + return std::nullopt; + } + return result; } catch (const winrt::hresult_error&) @@ -796,6 +859,10 @@ namespace JSONHelpers DeviceInfoJSON result; result.deviceId = device.GetNamedString(L"device-id"); + if (!isValidDeviceId(result.deviceId)) + { + return std::nullopt; + } if (auto zoneSet = ZoneSetData::FromJson(device.GetNamedObject(L"active-zoneset")); zoneSet.has_value()) { @@ -988,6 +1055,11 @@ namespace JSONHelpers CustomZoneSetJSON result; result.uuid = customZoneSet.GetNamedString(L"uuid"); + if (!isValidGuid(result.uuid)) + { + return std::nullopt; + } + result.data.name = customZoneSet.GetNamedString(L"name"); json::JsonObject infoJson = customZoneSet.GetNamedObject(L"info"); diff --git a/src/modules/fancyzones/lib/JsonHelpers.h b/src/modules/fancyzones/lib/JsonHelpers.h index c211bbaac9..04069110be 100644 --- a/src/modules/fancyzones/lib/JsonHelpers.h +++ b/src/modules/fancyzones/lib/JsonHelpers.h @@ -16,6 +16,11 @@ namespace JSONHelpers { constexpr int MAX_ZONE_COUNT = 50; + #if defined(UNIT_TESTS) + bool isValidGuid(const std::wstring& str); + bool isValidDeviceId(const std::wstring& str); + #endif + enum class ZoneSetLayoutType : int { Blank = -1, diff --git a/src/modules/fancyzones/tests/UnitTests/FancyZonesSettings.Spec.cpp b/src/modules/fancyzones/tests/UnitTests/FancyZonesSettings.Spec.cpp index 1479ef15bb..4d2bed306b 100644 --- a/src/modules/fancyzones/tests/UnitTests/FancyZonesSettings.Spec.cpp +++ b/src/modules/fancyzones/tests/UnitTests/FancyZonesSettings.Spec.cpp @@ -1,5 +1,6 @@ #include "pch.h" #include +#include #include #include @@ -46,7 +47,7 @@ namespace FancyZonesUnitTests compareHotkeyObjects(expected.editorHotkey, actual.editorHotkey); } - TEST_CLASS(FancyZonesSettingsCreationUnitTest) + TEST_CLASS (FancyZonesSettingsCreationUnitTest) { HINSTANCE m_hInst; PCWSTR m_moduleName = L"FancyZonesTest"; @@ -56,349 +57,371 @@ namespace FancyZonesUnitTests const Settings m_defaultSettings; TEST_METHOD_INITIALIZE(Init) - { - m_hInst = (HINSTANCE)GetModuleHandleW(nullptr); - m_tmpName = PTSettingsHelper::get_module_save_folder_location(m_moduleName) + L"\\settings.json"; - } + { + m_hInst = (HINSTANCE)GetModuleHandleW(nullptr); + m_tmpName = PTSettingsHelper::get_module_save_folder_location(m_moduleName) + L"\\settings.json"; + } - TEST_METHOD_CLEANUP(Cleanup) - { - std::filesystem::remove(m_tmpName); - } + TEST_METHOD_CLEANUP(Cleanup) + { + std::filesystem::remove(m_tmpName); + std::filesystem::remove(PTSettingsHelper::get_module_save_folder_location(m_moduleName)); + } - TEST_METHOD(CreateWithHinstanceDefault) - { - auto actual = MakeFancyZonesSettings({}, m_moduleName); - Assert::IsTrue(actual != nullptr); + TEST_METHOD (CreateWithHinstanceDefault) + { + auto actual = MakeFancyZonesSettings({}, m_moduleName); + Assert::IsTrue(actual != nullptr); - auto actualSettings = actual->GetSettings(); - compareSettings(m_defaultSettings, *actualSettings); - } + auto actualSettings = actual->GetSettings(); + compareSettings(m_defaultSettings, *actualSettings); + } - TEST_METHOD(CreateWithHinstanceNullptr) - { - auto actual = MakeFancyZonesSettings(nullptr, m_moduleName); - Assert::IsTrue(actual != nullptr); + TEST_METHOD (CreateWithHinstanceNullptr) + { + auto actual = MakeFancyZonesSettings(nullptr, m_moduleName); + Assert::IsTrue(actual != nullptr); - auto actualSettings = actual->GetSettings(); - compareSettings(m_defaultSettings, *actualSettings); - } + auto actualSettings = actual->GetSettings(); + compareSettings(m_defaultSettings, *actualSettings); + } - TEST_METHOD(CreateWithNameEmpty) - { - auto actual = MakeFancyZonesSettings(m_hInst, L""); - Assert::IsTrue(actual != nullptr); + TEST_METHOD (CreateWithNameEmpty) + { + auto actual = MakeFancyZonesSettings(m_hInst, L""); + Assert::IsTrue(actual != nullptr); - auto actualSettings = actual->GetSettings(); - compareSettings(m_defaultSettings, *actualSettings); - } + auto actualSettings = actual->GetSettings(); + compareSettings(m_defaultSettings, *actualSettings); + } - TEST_METHOD(Create) - { - //prepare data - const Settings expected { - .shiftDrag = false, - .displayChange_moveWindows = true, - .virtualDesktopChange_moveWindows = true, - .zoneSetChange_flashZones = true, - .zoneSetChange_moveWindows = true, - .overrideSnapHotkeys = false, - .appLastZone_moveWindows = false, - .use_cursorpos_editor_startupscreen = true, - .showZonesOnAllMonitors = false, - .zoneHightlightColor = L"#00FFD7", - .zoneHighlightOpacity = 45, - .editorHotkey = PowerToysSettings::HotkeyObject::from_settings(false, true, true, false, VK_OEM_3), - .excludedApps = L"app", - .excludedAppsArray = { L"APP" }, - }; + TEST_METHOD (Create) + { + //prepare data + const Settings expected{ + .shiftDrag = false, + .displayChange_moveWindows = true, + .virtualDesktopChange_moveWindows = true, + .zoneSetChange_flashZones = true, + .zoneSetChange_moveWindows = true, + .overrideSnapHotkeys = false, + .appLastZone_moveWindows = false, + .use_cursorpos_editor_startupscreen = true, + .showZonesOnAllMonitors = false, + .zoneHightlightColor = L"#00FFD7", + .zoneHighlightOpacity = 45, + .editorHotkey = PowerToysSettings::HotkeyObject::from_settings(false, true, true, false, VK_OEM_3), + .excludedApps = L"app", + .excludedAppsArray = { L"APP" }, + }; - PowerToysSettings::PowerToyValues values(m_moduleName); - values.add_property(L"fancyzones_shiftDrag", expected.shiftDrag); - values.add_property(L"fancyzones_displayChange_moveWindows", expected.displayChange_moveWindows); - values.add_property(L"fancyzones_virtualDesktopChange_moveWindows", expected.virtualDesktopChange_moveWindows); - values.add_property(L"fancyzones_zoneSetChange_flashZones", expected.zoneSetChange_flashZones); - values.add_property(L"fancyzones_zoneSetChange_moveWindows", expected.zoneSetChange_moveWindows); - values.add_property(L"fancyzones_overrideSnapHotkeys", expected.overrideSnapHotkeys); - values.add_property(L"fancyzones_appLastZone_moveWindows", expected.appLastZone_moveWindows); - values.add_property(L"use_cursorpos_editor_startupscreen", expected.use_cursorpos_editor_startupscreen); - values.add_property(L"fancyzones_show_on_all_monitors", expected.showZonesOnAllMonitors); - values.add_property(L"fancyzones_zoneHighlightColor", expected.zoneHightlightColor); - values.add_property(L"fancyzones_highlight_opacity", expected.zoneHighlightOpacity); - values.add_property(L"fancyzones_editor_hotkey", expected.editorHotkey.get_json()); - values.add_property(L"fancyzones_excluded_apps", expected.excludedApps); + PowerToysSettings::PowerToyValues values(m_moduleName); + values.add_property(L"fancyzones_shiftDrag", expected.shiftDrag); + values.add_property(L"fancyzones_displayChange_moveWindows", expected.displayChange_moveWindows); + values.add_property(L"fancyzones_virtualDesktopChange_moveWindows", expected.virtualDesktopChange_moveWindows); + values.add_property(L"fancyzones_zoneSetChange_flashZones", expected.zoneSetChange_flashZones); + values.add_property(L"fancyzones_zoneSetChange_moveWindows", expected.zoneSetChange_moveWindows); + values.add_property(L"fancyzones_overrideSnapHotkeys", expected.overrideSnapHotkeys); + values.add_property(L"fancyzones_appLastZone_moveWindows", expected.appLastZone_moveWindows); + values.add_property(L"use_cursorpos_editor_startupscreen", expected.use_cursorpos_editor_startupscreen); + values.add_property(L"fancyzones_show_on_all_monitors", expected.showZonesOnAllMonitors); + values.add_property(L"fancyzones_zoneHighlightColor", expected.zoneHightlightColor); + values.add_property(L"fancyzones_highlight_opacity", expected.zoneHighlightOpacity); + values.add_property(L"fancyzones_editor_hotkey", expected.editorHotkey.get_json()); + values.add_property(L"fancyzones_excluded_apps", expected.excludedApps); - values.save_to_settings_file(); + values.save_to_settings_file(); - auto actual = MakeFancyZonesSettings(m_hInst, m_moduleName); - Assert::IsTrue(actual != nullptr); + auto actual = MakeFancyZonesSettings(m_hInst, m_moduleName); + Assert::IsTrue(actual != nullptr); - auto actualSettings = actual->GetSettings(); - compareSettings(expected, *actualSettings); - } + auto actualSettings = actual->GetSettings(); + compareSettings(expected, *actualSettings); + } - TEST_METHOD(CreateWithMultipleApps) - { - //prepare data - const Settings expected { - .shiftDrag = false, - .displayChange_moveWindows = true, - .virtualDesktopChange_moveWindows = true, - .zoneSetChange_flashZones = true, - .zoneSetChange_moveWindows = true, - .overrideSnapHotkeys = false, - .appLastZone_moveWindows = false, - .use_cursorpos_editor_startupscreen = true, - .showZonesOnAllMonitors = false, - .zoneHightlightColor = L"#00FFD7", - .zoneHighlightOpacity = 45, - .editorHotkey = PowerToysSettings::HotkeyObject::from_settings(false, true, true, false, VK_OEM_3), - .excludedApps = L"app\r\napp1\r\napp2\r\nanother app", - .excludedAppsArray = { L"APP", L"APP1", L"APP2", L"ANOTHER APP" }, - }; + TEST_METHOD (CreateWithMultipleApps) + { + //prepare data + const Settings expected{ + .shiftDrag = false, + .displayChange_moveWindows = true, + .virtualDesktopChange_moveWindows = true, + .zoneSetChange_flashZones = true, + .zoneSetChange_moveWindows = true, + .overrideSnapHotkeys = false, + .appLastZone_moveWindows = false, + .use_cursorpos_editor_startupscreen = true, + .showZonesOnAllMonitors = false, + .zoneHightlightColor = L"#00FFD7", + .zoneHighlightOpacity = 45, + .editorHotkey = PowerToysSettings::HotkeyObject::from_settings(false, true, true, false, VK_OEM_3), + .excludedApps = L"app\r\napp1\r\napp2\r\nanother app", + .excludedAppsArray = { L"APP", L"APP1", L"APP2", L"ANOTHER APP" }, + }; - PowerToysSettings::PowerToyValues values(m_moduleName); - values.add_property(L"fancyzones_shiftDrag", expected.shiftDrag); - values.add_property(L"fancyzones_displayChange_moveWindows", expected.displayChange_moveWindows); - values.add_property(L"fancyzones_virtualDesktopChange_moveWindows", expected.virtualDesktopChange_moveWindows); - values.add_property(L"fancyzones_zoneSetChange_flashZones", expected.zoneSetChange_flashZones); - values.add_property(L"fancyzones_zoneSetChange_moveWindows", expected.zoneSetChange_moveWindows); - values.add_property(L"fancyzones_overrideSnapHotkeys", expected.overrideSnapHotkeys); - values.add_property(L"fancyzones_appLastZone_moveWindows", expected.appLastZone_moveWindows); - values.add_property(L"use_cursorpos_editor_startupscreen", expected.use_cursorpos_editor_startupscreen); - values.add_property(L"fancyzones_show_on_all_monitors", expected.showZonesOnAllMonitors); - values.add_property(L"fancyzones_zoneHighlightColor", expected.zoneHightlightColor); - values.add_property(L"fancyzones_highlight_opacity", expected.zoneHighlightOpacity); - values.add_property(L"fancyzones_editor_hotkey", expected.editorHotkey.get_json()); - values.add_property(L"fancyzones_excluded_apps", expected.excludedApps); + PowerToysSettings::PowerToyValues values(m_moduleName); + values.add_property(L"fancyzones_shiftDrag", expected.shiftDrag); + values.add_property(L"fancyzones_displayChange_moveWindows", expected.displayChange_moveWindows); + values.add_property(L"fancyzones_virtualDesktopChange_moveWindows", expected.virtualDesktopChange_moveWindows); + values.add_property(L"fancyzones_zoneSetChange_flashZones", expected.zoneSetChange_flashZones); + values.add_property(L"fancyzones_zoneSetChange_moveWindows", expected.zoneSetChange_moveWindows); + values.add_property(L"fancyzones_overrideSnapHotkeys", expected.overrideSnapHotkeys); + values.add_property(L"fancyzones_appLastZone_moveWindows", expected.appLastZone_moveWindows); + values.add_property(L"use_cursorpos_editor_startupscreen", expected.use_cursorpos_editor_startupscreen); + values.add_property(L"fancyzones_show_on_all_monitors", expected.showZonesOnAllMonitors); + values.add_property(L"fancyzones_zoneHighlightColor", expected.zoneHightlightColor); + values.add_property(L"fancyzones_highlight_opacity", expected.zoneHighlightOpacity); + values.add_property(L"fancyzones_editor_hotkey", expected.editorHotkey.get_json()); + values.add_property(L"fancyzones_excluded_apps", expected.excludedApps); - values.save_to_settings_file(); + values.save_to_settings_file(); - auto actual = MakeFancyZonesSettings(m_hInst, m_moduleName); - Assert::IsTrue(actual != nullptr); + auto actual = MakeFancyZonesSettings(m_hInst, m_moduleName); + Assert::IsTrue(actual != nullptr); - auto actualSettings = actual->GetSettings(); - compareSettings(expected, *actualSettings); - } + auto actualSettings = actual->GetSettings(); + compareSettings(expected, *actualSettings); + } - TEST_METHOD(CreateWithBoolValuesMissed) - { - const Settings expected { - .shiftDrag = m_defaultSettings.shiftDrag, - .displayChange_moveWindows = m_defaultSettings.displayChange_moveWindows, - .virtualDesktopChange_moveWindows = m_defaultSettings.virtualDesktopChange_moveWindows, - .zoneSetChange_flashZones = m_defaultSettings.zoneSetChange_flashZones, - .zoneSetChange_moveWindows = m_defaultSettings.zoneSetChange_moveWindows, - .overrideSnapHotkeys = m_defaultSettings.overrideSnapHotkeys, - .appLastZone_moveWindows = m_defaultSettings.appLastZone_moveWindows, - .use_cursorpos_editor_startupscreen = m_defaultSettings.use_cursorpos_editor_startupscreen, - .showZonesOnAllMonitors = m_defaultSettings.showZonesOnAllMonitors, - .zoneHightlightColor = L"#00FFD7", - .zoneHighlightOpacity = 45, - .editorHotkey = PowerToysSettings::HotkeyObject::from_settings(false, true, true, false, VK_OEM_3), - .excludedApps = L"app", - .excludedAppsArray = { L"APP" }, - }; + TEST_METHOD (CreateWithBoolValuesMissed) + { + const Settings expected{ + .shiftDrag = m_defaultSettings.shiftDrag, + .displayChange_moveWindows = m_defaultSettings.displayChange_moveWindows, + .virtualDesktopChange_moveWindows = m_defaultSettings.virtualDesktopChange_moveWindows, + .zoneSetChange_flashZones = m_defaultSettings.zoneSetChange_flashZones, + .zoneSetChange_moveWindows = m_defaultSettings.zoneSetChange_moveWindows, + .overrideSnapHotkeys = m_defaultSettings.overrideSnapHotkeys, + .appLastZone_moveWindows = m_defaultSettings.appLastZone_moveWindows, + .use_cursorpos_editor_startupscreen = m_defaultSettings.use_cursorpos_editor_startupscreen, + .showZonesOnAllMonitors = m_defaultSettings.showZonesOnAllMonitors, + .zoneHightlightColor = L"#00FFD7", + .zoneHighlightOpacity = 45, + .editorHotkey = PowerToysSettings::HotkeyObject::from_settings(false, true, true, false, VK_OEM_3), + .excludedApps = L"app", + .excludedAppsArray = { L"APP" }, + }; - PowerToysSettings::PowerToyValues values(m_moduleName); - values.add_property(L"fancyzones_zoneHighlightColor", expected.zoneHightlightColor); - values.add_property(L"fancyzones_highlight_opacity", expected.zoneHighlightOpacity); - values.add_property(L"fancyzones_editor_hotkey", expected.editorHotkey.get_json()); - values.add_property(L"fancyzones_excluded_apps", expected.excludedApps); + PowerToysSettings::PowerToyValues values(m_moduleName); + values.add_property(L"fancyzones_zoneHighlightColor", expected.zoneHightlightColor); + values.add_property(L"fancyzones_highlight_opacity", expected.zoneHighlightOpacity); + values.add_property(L"fancyzones_editor_hotkey", expected.editorHotkey.get_json()); + values.add_property(L"fancyzones_excluded_apps", expected.excludedApps); - values.save_to_settings_file(); + values.save_to_settings_file(); - auto actual = MakeFancyZonesSettings(m_hInst, m_moduleName); - Assert::IsTrue(actual != nullptr); + auto actual = MakeFancyZonesSettings(m_hInst, m_moduleName); + Assert::IsTrue(actual != nullptr); - auto actualSettings = actual->GetSettings(); - compareSettings(expected, *actualSettings); - } + auto actualSettings = actual->GetSettings(); + compareSettings(expected, *actualSettings); + } - TEST_METHOD(CreateColorMissed) - { - //prepare data - const Settings expected { - .shiftDrag = false, - .displayChange_moveWindows = true, - .virtualDesktopChange_moveWindows = true, - .zoneSetChange_flashZones = true, - .zoneSetChange_moveWindows = true, - .overrideSnapHotkeys = false, - .appLastZone_moveWindows = false, - .use_cursorpos_editor_startupscreen = true, - .showZonesOnAllMonitors = false, - .zoneHightlightColor = m_defaultSettings.zoneHightlightColor, - .zoneHighlightOpacity = 45, - .editorHotkey = PowerToysSettings::HotkeyObject::from_settings(false, true, true, false, VK_OEM_3), - .excludedApps = L"app", - .excludedAppsArray = { L"APP" }, - }; + TEST_METHOD (CreateColorMissed) + { + //prepare data + const Settings expected{ + .shiftDrag = false, + .displayChange_moveWindows = true, + .virtualDesktopChange_moveWindows = true, + .zoneSetChange_flashZones = true, + .zoneSetChange_moveWindows = true, + .overrideSnapHotkeys = false, + .appLastZone_moveWindows = false, + .use_cursorpos_editor_startupscreen = true, + .showZonesOnAllMonitors = false, + .zoneHightlightColor = m_defaultSettings.zoneHightlightColor, + .zoneHighlightOpacity = 45, + .editorHotkey = PowerToysSettings::HotkeyObject::from_settings(false, true, true, false, VK_OEM_3), + .excludedApps = L"app", + .excludedAppsArray = { L"APP" }, + }; - PowerToysSettings::PowerToyValues values(m_moduleName); - values.add_property(L"fancyzones_shiftDrag", expected.shiftDrag); - values.add_property(L"fancyzones_displayChange_moveWindows", expected.displayChange_moveWindows); - values.add_property(L"fancyzones_virtualDesktopChange_moveWindows", expected.virtualDesktopChange_moveWindows); - values.add_property(L"fancyzones_zoneSetChange_flashZones", expected.zoneSetChange_flashZones); - values.add_property(L"fancyzones_zoneSetChange_moveWindows", expected.zoneSetChange_moveWindows); - values.add_property(L"fancyzones_overrideSnapHotkeys", expected.overrideSnapHotkeys); - values.add_property(L"fancyzones_appLastZone_moveWindows", expected.appLastZone_moveWindows); - values.add_property(L"use_cursorpos_editor_startupscreen", expected.use_cursorpos_editor_startupscreen); - values.add_property(L"fancyzones_show_on_all_monitors", expected.showZonesOnAllMonitors); - values.add_property(L"fancyzones_highlight_opacity", expected.zoneHighlightOpacity); - values.add_property(L"fancyzones_editor_hotkey", expected.editorHotkey.get_json()); - values.add_property(L"fancyzones_excluded_apps", expected.excludedApps); + PowerToysSettings::PowerToyValues values(m_moduleName); + values.add_property(L"fancyzones_shiftDrag", expected.shiftDrag); + values.add_property(L"fancyzones_displayChange_moveWindows", expected.displayChange_moveWindows); + values.add_property(L"fancyzones_virtualDesktopChange_moveWindows", expected.virtualDesktopChange_moveWindows); + values.add_property(L"fancyzones_zoneSetChange_flashZones", expected.zoneSetChange_flashZones); + values.add_property(L"fancyzones_zoneSetChange_moveWindows", expected.zoneSetChange_moveWindows); + values.add_property(L"fancyzones_overrideSnapHotkeys", expected.overrideSnapHotkeys); + values.add_property(L"fancyzones_appLastZone_moveWindows", expected.appLastZone_moveWindows); + values.add_property(L"use_cursorpos_editor_startupscreen", expected.use_cursorpos_editor_startupscreen); + values.add_property(L"fancyzones_show_on_all_monitors", expected.showZonesOnAllMonitors); + values.add_property(L"fancyzones_highlight_opacity", expected.zoneHighlightOpacity); + values.add_property(L"fancyzones_editor_hotkey", expected.editorHotkey.get_json()); + values.add_property(L"fancyzones_excluded_apps", expected.excludedApps); - values.save_to_settings_file(); + values.save_to_settings_file(); - auto actual = MakeFancyZonesSettings(m_hInst, m_moduleName); - Assert::IsTrue(actual != nullptr); + auto actual = MakeFancyZonesSettings(m_hInst, m_moduleName); + Assert::IsTrue(actual != nullptr); - auto actualSettings = actual->GetSettings(); - compareSettings(expected, *actualSettings); - } + auto actualSettings = actual->GetSettings(); + compareSettings(expected, *actualSettings); + } - TEST_METHOD(CreateOpacityMissed) - { - //prepare data - const Settings expected { - .shiftDrag = false, - .displayChange_moveWindows = true, - .virtualDesktopChange_moveWindows = true, - .zoneSetChange_flashZones = true, - .zoneSetChange_moveWindows = true, - .overrideSnapHotkeys = false, - .appLastZone_moveWindows = false, - .use_cursorpos_editor_startupscreen = true, - .showZonesOnAllMonitors = false, - .zoneHightlightColor = L"#00FFD7", - .zoneHighlightOpacity = m_defaultSettings.zoneHighlightOpacity, - .editorHotkey = PowerToysSettings::HotkeyObject::from_settings(false, true, true, false, VK_OEM_3), - .excludedApps = L"app", - .excludedAppsArray = { L"APP" }, - }; + TEST_METHOD (CreateOpacityMissed) + { + //prepare data + const Settings expected{ + .shiftDrag = false, + .displayChange_moveWindows = true, + .virtualDesktopChange_moveWindows = true, + .zoneSetChange_flashZones = true, + .zoneSetChange_moveWindows = true, + .overrideSnapHotkeys = false, + .appLastZone_moveWindows = false, + .use_cursorpos_editor_startupscreen = true, + .showZonesOnAllMonitors = false, + .zoneHightlightColor = L"#00FFD7", + .zoneHighlightOpacity = m_defaultSettings.zoneHighlightOpacity, + .editorHotkey = PowerToysSettings::HotkeyObject::from_settings(false, true, true, false, VK_OEM_3), + .excludedApps = L"app", + .excludedAppsArray = { L"APP" }, + }; - PowerToysSettings::PowerToyValues values(m_moduleName); - values.add_property(L"fancyzones_shiftDrag", expected.shiftDrag); - values.add_property(L"fancyzones_displayChange_moveWindows", expected.displayChange_moveWindows); - values.add_property(L"fancyzones_virtualDesktopChange_moveWindows", expected.virtualDesktopChange_moveWindows); - values.add_property(L"fancyzones_zoneSetChange_flashZones", expected.zoneSetChange_flashZones); - values.add_property(L"fancyzones_zoneSetChange_moveWindows", expected.zoneSetChange_moveWindows); - values.add_property(L"fancyzones_overrideSnapHotkeys", expected.overrideSnapHotkeys); - values.add_property(L"fancyzones_appLastZone_moveWindows", expected.appLastZone_moveWindows); - values.add_property(L"use_cursorpos_editor_startupscreen", expected.use_cursorpos_editor_startupscreen); - values.add_property(L"fancyzones_show_on_all_monitors", expected.showZonesOnAllMonitors); - values.add_property(L"fancyzones_zoneHighlightColor", expected.zoneHightlightColor); - values.add_property(L"fancyzones_editor_hotkey", expected.editorHotkey.get_json()); - values.add_property(L"fancyzones_excluded_apps", expected.excludedApps); + PowerToysSettings::PowerToyValues values(m_moduleName); + values.add_property(L"fancyzones_shiftDrag", expected.shiftDrag); + values.add_property(L"fancyzones_displayChange_moveWindows", expected.displayChange_moveWindows); + values.add_property(L"fancyzones_virtualDesktopChange_moveWindows", expected.virtualDesktopChange_moveWindows); + values.add_property(L"fancyzones_zoneSetChange_flashZones", expected.zoneSetChange_flashZones); + values.add_property(L"fancyzones_zoneSetChange_moveWindows", expected.zoneSetChange_moveWindows); + values.add_property(L"fancyzones_overrideSnapHotkeys", expected.overrideSnapHotkeys); + values.add_property(L"fancyzones_appLastZone_moveWindows", expected.appLastZone_moveWindows); + values.add_property(L"use_cursorpos_editor_startupscreen", expected.use_cursorpos_editor_startupscreen); + values.add_property(L"fancyzones_show_on_all_monitors", expected.showZonesOnAllMonitors); + values.add_property(L"fancyzones_zoneHighlightColor", expected.zoneHightlightColor); + values.add_property(L"fancyzones_editor_hotkey", expected.editorHotkey.get_json()); + values.add_property(L"fancyzones_excluded_apps", expected.excludedApps); - values.save_to_settings_file(); + values.save_to_settings_file(); - auto actual = MakeFancyZonesSettings(m_hInst, m_moduleName); - Assert::IsTrue(actual != nullptr); + auto actual = MakeFancyZonesSettings(m_hInst, m_moduleName); + Assert::IsTrue(actual != nullptr); - auto actualSettings = actual->GetSettings(); - compareSettings(expected, *actualSettings); - } + auto actualSettings = actual->GetSettings(); + compareSettings(expected, *actualSettings); + } - TEST_METHOD(CreateHotkeyMissed) - { - //prepare data - const Settings expected = Settings{ - .shiftDrag = false, - .displayChange_moveWindows = true, - .virtualDesktopChange_moveWindows = true, - .zoneSetChange_flashZones = true, - .zoneSetChange_moveWindows = true, - .overrideSnapHotkeys = false, - .appLastZone_moveWindows = false, - .use_cursorpos_editor_startupscreen = true, - .showZonesOnAllMonitors = false, - .zoneHightlightColor = L"#00FFD7", - .zoneHighlightOpacity = 45, - .editorHotkey = m_defaultSettings.editorHotkey, - .excludedApps = L"app", - .excludedAppsArray = { L"APP" }, - }; + TEST_METHOD (CreateHotkeyMissed) + { + //prepare data + const Settings expected = Settings{ + .shiftDrag = false, + .displayChange_moveWindows = true, + .virtualDesktopChange_moveWindows = true, + .zoneSetChange_flashZones = true, + .zoneSetChange_moveWindows = true, + .overrideSnapHotkeys = false, + .appLastZone_moveWindows = false, + .use_cursorpos_editor_startupscreen = true, + .showZonesOnAllMonitors = false, + .zoneHightlightColor = L"#00FFD7", + .zoneHighlightOpacity = 45, + .editorHotkey = m_defaultSettings.editorHotkey, + .excludedApps = L"app", + .excludedAppsArray = { L"APP" }, + }; - PowerToysSettings::PowerToyValues values(m_moduleName); - values.add_property(L"fancyzones_shiftDrag", expected.shiftDrag); - values.add_property(L"fancyzones_displayChange_moveWindows", expected.displayChange_moveWindows); - values.add_property(L"fancyzones_virtualDesktopChange_moveWindows", expected.virtualDesktopChange_moveWindows); - values.add_property(L"fancyzones_zoneSetChange_flashZones", expected.zoneSetChange_flashZones); - values.add_property(L"fancyzones_zoneSetChange_moveWindows", expected.zoneSetChange_moveWindows); - values.add_property(L"fancyzones_overrideSnapHotkeys", expected.overrideSnapHotkeys); - values.add_property(L"fancyzones_appLastZone_moveWindows", expected.appLastZone_moveWindows); - values.add_property(L"use_cursorpos_editor_startupscreen", expected.use_cursorpos_editor_startupscreen); - values.add_property(L"fancyzones_show_on_all_monitors", expected.showZonesOnAllMonitors); - values.add_property(L"fancyzones_zoneHighlightColor", expected.zoneHightlightColor); - values.add_property(L"fancyzones_highlight_opacity", expected.zoneHighlightOpacity); - values.add_property(L"fancyzones_excluded_apps", expected.excludedApps); + PowerToysSettings::PowerToyValues values(m_moduleName); + values.add_property(L"fancyzones_shiftDrag", expected.shiftDrag); + values.add_property(L"fancyzones_displayChange_moveWindows", expected.displayChange_moveWindows); + values.add_property(L"fancyzones_virtualDesktopChange_moveWindows", expected.virtualDesktopChange_moveWindows); + values.add_property(L"fancyzones_zoneSetChange_flashZones", expected.zoneSetChange_flashZones); + values.add_property(L"fancyzones_zoneSetChange_moveWindows", expected.zoneSetChange_moveWindows); + values.add_property(L"fancyzones_overrideSnapHotkeys", expected.overrideSnapHotkeys); + values.add_property(L"fancyzones_appLastZone_moveWindows", expected.appLastZone_moveWindows); + values.add_property(L"use_cursorpos_editor_startupscreen", expected.use_cursorpos_editor_startupscreen); + values.add_property(L"fancyzones_show_on_all_monitors", expected.showZonesOnAllMonitors); + values.add_property(L"fancyzones_zoneHighlightColor", expected.zoneHightlightColor); + values.add_property(L"fancyzones_highlight_opacity", expected.zoneHighlightOpacity); + values.add_property(L"fancyzones_excluded_apps", expected.excludedApps); - values.save_to_settings_file(); + values.save_to_settings_file(); - auto actual = MakeFancyZonesSettings(m_hInst, m_moduleName); - Assert::IsTrue(actual != nullptr); + auto actual = MakeFancyZonesSettings(m_hInst, m_moduleName); + Assert::IsTrue(actual != nullptr); - auto actualSettings = actual->GetSettings(); - compareSettings(expected, *actualSettings); - } + auto actualSettings = actual->GetSettings(); + compareSettings(expected, *actualSettings); + } - TEST_METHOD(CreateAppsMissed) - { - //prepare data - const Settings expected = Settings{ - .shiftDrag = false, - .displayChange_moveWindows = true, - .virtualDesktopChange_moveWindows = true, - .zoneSetChange_flashZones = true, - .zoneSetChange_moveWindows = true, - .overrideSnapHotkeys = false, - .appLastZone_moveWindows = false, - .use_cursorpos_editor_startupscreen = true, - .showZonesOnAllMonitors = false, - .zoneHightlightColor = L"#00FFD7", - .zoneHighlightOpacity = 45, - .editorHotkey = PowerToysSettings::HotkeyObject::from_settings(false, true, true, false, VK_OEM_3), - .excludedApps = m_defaultSettings.excludedApps, - .excludedAppsArray = m_defaultSettings.excludedAppsArray, - }; + TEST_METHOD (CreateAppsMissed) + { + //prepare data + const Settings expected = Settings{ + .shiftDrag = false, + .displayChange_moveWindows = true, + .virtualDesktopChange_moveWindows = true, + .zoneSetChange_flashZones = true, + .zoneSetChange_moveWindows = true, + .overrideSnapHotkeys = false, + .appLastZone_moveWindows = false, + .use_cursorpos_editor_startupscreen = true, + .showZonesOnAllMonitors = false, + .zoneHightlightColor = L"#00FFD7", + .zoneHighlightOpacity = 45, + .editorHotkey = PowerToysSettings::HotkeyObject::from_settings(false, true, true, false, VK_OEM_3), + .excludedApps = m_defaultSettings.excludedApps, + .excludedAppsArray = m_defaultSettings.excludedAppsArray, + }; - PowerToysSettings::PowerToyValues values(m_moduleName); - values.add_property(L"fancyzones_shiftDrag", expected.shiftDrag); - values.add_property(L"fancyzones_displayChange_moveWindows", expected.displayChange_moveWindows); - values.add_property(L"fancyzones_virtualDesktopChange_moveWindows", expected.virtualDesktopChange_moveWindows); - values.add_property(L"fancyzones_zoneSetChange_flashZones", expected.zoneSetChange_flashZones); - values.add_property(L"fancyzones_zoneSetChange_moveWindows", expected.zoneSetChange_moveWindows); - values.add_property(L"fancyzones_overrideSnapHotkeys", expected.overrideSnapHotkeys); - values.add_property(L"fancyzones_appLastZone_moveWindows", expected.appLastZone_moveWindows); - values.add_property(L"use_cursorpos_editor_startupscreen", expected.use_cursorpos_editor_startupscreen); - values.add_property(L"fancyzones_show_on_all_monitors", expected.showZonesOnAllMonitors); - values.add_property(L"fancyzones_zoneHighlightColor", expected.zoneHightlightColor); - values.add_property(L"fancyzones_highlight_opacity", expected.zoneHighlightOpacity); - values.add_property(L"fancyzones_editor_hotkey", expected.editorHotkey.get_json()); + PowerToysSettings::PowerToyValues values(m_moduleName); + values.add_property(L"fancyzones_shiftDrag", expected.shiftDrag); + values.add_property(L"fancyzones_displayChange_moveWindows", expected.displayChange_moveWindows); + values.add_property(L"fancyzones_virtualDesktopChange_moveWindows", expected.virtualDesktopChange_moveWindows); + values.add_property(L"fancyzones_zoneSetChange_flashZones", expected.zoneSetChange_flashZones); + values.add_property(L"fancyzones_zoneSetChange_moveWindows", expected.zoneSetChange_moveWindows); + values.add_property(L"fancyzones_overrideSnapHotkeys", expected.overrideSnapHotkeys); + values.add_property(L"fancyzones_appLastZone_moveWindows", expected.appLastZone_moveWindows); + values.add_property(L"use_cursorpos_editor_startupscreen", expected.use_cursorpos_editor_startupscreen); + values.add_property(L"fancyzones_show_on_all_monitors", expected.showZonesOnAllMonitors); + values.add_property(L"fancyzones_zoneHighlightColor", expected.zoneHightlightColor); + values.add_property(L"fancyzones_highlight_opacity", expected.zoneHighlightOpacity); + values.add_property(L"fancyzones_editor_hotkey", expected.editorHotkey.get_json()); - values.save_to_settings_file(); + values.save_to_settings_file(); - auto actual = MakeFancyZonesSettings(m_hInst, m_moduleName); - Assert::IsTrue(actual != nullptr); + auto actual = MakeFancyZonesSettings(m_hInst, m_moduleName); + Assert::IsTrue(actual != nullptr); - auto actualSettings = actual->GetSettings(); - compareSettings(expected, *actualSettings); - } + auto actualSettings = actual->GetSettings(); + compareSettings(expected, *actualSettings); + } - TEST_METHOD(CreateWithEmptyJson) - { - json::to_file(m_tmpName, json::JsonObject()); - auto actual = MakeFancyZonesSettings(m_hInst, m_moduleName); - Assert::IsTrue(actual != nullptr); + TEST_METHOD (CreateWithEmptyJson) + { + json::to_file(m_tmpName, json::JsonObject()); + auto actual = MakeFancyZonesSettings(m_hInst, m_moduleName); + Assert::IsTrue(actual != nullptr); - auto actualSettings = actual->GetSettings(); - compareSettings(m_defaultSettings, *actualSettings); - } + auto actualSettings = actual->GetSettings(); + compareSettings(m_defaultSettings, *actualSettings); + } + + TEST_METHOD (CreateWithCorruptedJson) + { + std::wofstream{ m_tmpName.data(), std::ios::binary } << L"{ \"version\": \"1.0\", \"name\": \""; + + auto actual = MakeFancyZonesSettings(m_hInst, m_moduleName); + + Assert::IsTrue(actual != nullptr); + auto actualSettings = actual->GetSettings(); + compareSettings(m_defaultSettings, *actualSettings); + } + + TEST_METHOD (CreateWithCyrillicSymbolsInJson) + { + std::wofstream{ m_tmpName.data(), std::ios::binary } << L"{ \"version\": \"1.0\", \"name\": \"ФансиЗонс\"}"; + auto actual = MakeFancyZonesSettings(m_hInst, m_moduleName); + Assert::IsTrue(actual != nullptr); + + auto actualSettings = actual->GetSettings(); + compareSettings(m_defaultSettings, *actualSettings); + } }; - TEST_CLASS(FancyZonesSettingsCallbackUnitTests) + TEST_CLASS (FancyZonesSettingsCallbackUnitTests) { winrt::com_ptr m_settings = nullptr; PCWSTR m_moduleName = L"FancyZonesTest"; @@ -412,22 +435,32 @@ namespace FancyZonesUnitTests *m_callFlag = false; } - IFACEMETHODIMP_(bool) InMoveSize() noexcept { return false; } - IFACEMETHODIMP_(void) MoveSizeStart(HWND window, HMONITOR monitor, POINT const& ptScreen) noexcept {} - IFACEMETHODIMP_(void) MoveSizeUpdate(HMONITOR monitor, POINT const& ptScreen) noexcept {} - IFACEMETHODIMP_(void) MoveSizeEnd(HWND window, POINT const& ptScreen) noexcept {} - IFACEMETHODIMP_(void) VirtualDesktopChanged() noexcept {} - IFACEMETHODIMP_(void) VirtualDesktopInitialize() noexcept {} - IFACEMETHODIMP_(void) WindowCreated(HWND window) noexcept {} - IFACEMETHODIMP_(bool) OnKeyDown(PKBDLLHOOKSTRUCT info) noexcept { return false; } + IFACEMETHODIMP_(bool) + InMoveSize() noexcept { return false; } + IFACEMETHODIMP_(void) + MoveSizeStart(HWND window, HMONITOR monitor, POINT const& ptScreen) noexcept {} + IFACEMETHODIMP_(void) + MoveSizeUpdate(HMONITOR monitor, POINT const& ptScreen) noexcept {} + IFACEMETHODIMP_(void) + MoveSizeEnd(HWND window, POINT const& ptScreen) noexcept {} + IFACEMETHODIMP_(void) + VirtualDesktopChanged() noexcept {} + IFACEMETHODIMP_(void) + VirtualDesktopInitialize() noexcept {} + IFACEMETHODIMP_(void) + WindowCreated(HWND window) noexcept {} + IFACEMETHODIMP_(bool) + OnKeyDown(PKBDLLHOOKSTRUCT info) noexcept { return false; } - IFACEMETHODIMP_(void) ToggleEditor() noexcept + IFACEMETHODIMP_(void) + ToggleEditor() noexcept { Assert::IsNotNull(m_callFlag); *m_callFlag = true; } - IFACEMETHODIMP_(void) SettingsChanged() noexcept + IFACEMETHODIMP_(void) + SettingsChanged() noexcept { Assert::IsNotNull(m_callFlag); *m_callFlag = true; @@ -438,120 +471,120 @@ namespace FancyZonesUnitTests }; TEST_METHOD_INITIALIZE(Init) - { - HINSTANCE hInst = (HINSTANCE)GetModuleHandleW(nullptr); - const Settings expected{ - .shiftDrag = false, - .displayChange_moveWindows = true, - .virtualDesktopChange_moveWindows = true, - .zoneSetChange_flashZones = true, - .zoneSetChange_moveWindows = true, - .overrideSnapHotkeys = false, - .appLastZone_moveWindows = false, - .use_cursorpos_editor_startupscreen = true, - .showZonesOnAllMonitors = false, - .zoneHightlightColor = L"#00FFD7", - .zoneHighlightOpacity = 45, - .editorHotkey = PowerToysSettings::HotkeyObject::from_settings(false, true, true, false, VK_OEM_3), - .excludedApps = L"app", - .excludedAppsArray = { L"APP" }, - }; + { + HINSTANCE hInst = (HINSTANCE)GetModuleHandleW(nullptr); + const Settings expected{ + .shiftDrag = false, + .displayChange_moveWindows = true, + .virtualDesktopChange_moveWindows = true, + .zoneSetChange_flashZones = true, + .zoneSetChange_moveWindows = true, + .overrideSnapHotkeys = false, + .appLastZone_moveWindows = false, + .use_cursorpos_editor_startupscreen = true, + .showZonesOnAllMonitors = false, + .zoneHightlightColor = L"#00FFD7", + .zoneHighlightOpacity = 45, + .editorHotkey = PowerToysSettings::HotkeyObject::from_settings(false, true, true, false, VK_OEM_3), + .excludedApps = L"app", + .excludedAppsArray = { L"APP" }, + }; - PowerToysSettings::PowerToyValues values(m_moduleName); - values.add_property(L"fancyzones_shiftDrag", expected.shiftDrag); - values.add_property(L"fancyzones_displayChange_moveWindows", expected.displayChange_moveWindows); - values.add_property(L"fancyzones_virtualDesktopChange_moveWindows", expected.virtualDesktopChange_moveWindows); - values.add_property(L"fancyzones_zoneSetChange_flashZones", expected.zoneSetChange_flashZones); - values.add_property(L"fancyzones_zoneSetChange_moveWindows", expected.zoneSetChange_moveWindows); - values.add_property(L"fancyzones_overrideSnapHotkeys", expected.overrideSnapHotkeys); - values.add_property(L"fancyzones_appLastZone_moveWindows", expected.appLastZone_moveWindows); - values.add_property(L"use_cursorpos_editor_startupscreen", expected.use_cursorpos_editor_startupscreen); - values.add_property(L"fancyzones_show_on_all_monitors", expected.showZonesOnAllMonitors); - values.add_property(L"fancyzones_zoneHighlightColor", expected.zoneHightlightColor); - values.add_property(L"fancyzones_highlight_opacity", expected.zoneHighlightOpacity); - values.add_property(L"fancyzones_editor_hotkey", expected.editorHotkey.get_json()); - values.add_property(L"fancyzones_excluded_apps", expected.excludedApps); + PowerToysSettings::PowerToyValues values(m_moduleName); + values.add_property(L"fancyzones_shiftDrag", expected.shiftDrag); + values.add_property(L"fancyzones_displayChange_moveWindows", expected.displayChange_moveWindows); + values.add_property(L"fancyzones_virtualDesktopChange_moveWindows", expected.virtualDesktopChange_moveWindows); + values.add_property(L"fancyzones_zoneSetChange_flashZones", expected.zoneSetChange_flashZones); + values.add_property(L"fancyzones_zoneSetChange_moveWindows", expected.zoneSetChange_moveWindows); + values.add_property(L"fancyzones_overrideSnapHotkeys", expected.overrideSnapHotkeys); + values.add_property(L"fancyzones_appLastZone_moveWindows", expected.appLastZone_moveWindows); + values.add_property(L"use_cursorpos_editor_startupscreen", expected.use_cursorpos_editor_startupscreen); + values.add_property(L"fancyzones_show_on_all_monitors", expected.showZonesOnAllMonitors); + values.add_property(L"fancyzones_zoneHighlightColor", expected.zoneHightlightColor); + values.add_property(L"fancyzones_highlight_opacity", expected.zoneHighlightOpacity); + values.add_property(L"fancyzones_editor_hotkey", expected.editorHotkey.get_json()); + values.add_property(L"fancyzones_excluded_apps", expected.excludedApps); - values.save_to_settings_file(); + values.save_to_settings_file(); - m_settings = MakeFancyZonesSettings(hInst, m_moduleName); - Assert::IsTrue(m_settings != nullptr); - } + m_settings = MakeFancyZonesSettings(hInst, m_moduleName); + Assert::IsTrue(m_settings != nullptr); + } - TEST_METHOD_CLEANUP(Cleanup) - { - const auto settingsFile = PTSettingsHelper::get_module_save_folder_location(m_moduleName) + L"\\settings.json"; - std::filesystem::remove(settingsFile); - } + TEST_METHOD_CLEANUP(Cleanup) + { + const auto settingsFile = PTSettingsHelper::get_module_save_folder_location(m_moduleName) + L"\\settings.json"; + std::filesystem::remove(settingsFile); + } - TEST_METHOD(CallbackSetConfig) - { - bool flag = false; - FZCallback callback(&flag); + TEST_METHOD (CallbackSetConfig) + { + bool flag = false; + FZCallback callback(&flag); - json::JsonObject json{}; - json.SetNamedValue(L"name", json::JsonValue::CreateStringValue(L"name")); + json::JsonObject json{}; + json.SetNamedValue(L"name", json::JsonValue::CreateStringValue(L"name")); - m_settings->SetCallback(&callback); - m_settings->SetConfig(json.Stringify().c_str()); + m_settings->SetCallback(&callback); + m_settings->SetConfig(json.Stringify().c_str()); - Assert::IsTrue(flag); - } + Assert::IsTrue(flag); + } - TEST_METHOD(CallbackCallCustomAction) - { - bool flag = false; - FZCallback callback(&flag); + TEST_METHOD (CallbackCallCustomAction) + { + bool flag = false; + FZCallback callback(&flag); - json::JsonObject action{}; - action.SetNamedValue(L"action_name", json::JsonValue::CreateStringValue(L"ToggledFZEditor")); + json::JsonObject action{}; + action.SetNamedValue(L"action_name", json::JsonValue::CreateStringValue(L"ToggledFZEditor")); - m_settings->SetCallback(&callback); - m_settings->CallCustomAction(action.Stringify().c_str()); + m_settings->SetCallback(&callback); + m_settings->CallCustomAction(action.Stringify().c_str()); - Assert::IsTrue(flag); - } + Assert::IsTrue(flag); + } - TEST_METHOD(CallbackCallCustomActionNotToggle) - { - bool flag = false; - FZCallback callback(&flag); + TEST_METHOD (CallbackCallCustomActionNotToggle) + { + bool flag = false; + FZCallback callback(&flag); - json::JsonObject action{}; - action.SetNamedValue(L"action_name", json::JsonValue::CreateStringValue(L"NOT_ToggledFZEditor")); + json::JsonObject action{}; + action.SetNamedValue(L"action_name", json::JsonValue::CreateStringValue(L"NOT_ToggledFZEditor")); - m_settings->SetCallback(&callback); - m_settings->CallCustomAction(action.Stringify().c_str()); + m_settings->SetCallback(&callback); + m_settings->CallCustomAction(action.Stringify().c_str()); - Assert::IsFalse(flag); - } + Assert::IsFalse(flag); + } - TEST_METHOD(CallbackGetConfig) - { - bool flag = false; - FZCallback callback(&flag); + TEST_METHOD (CallbackGetConfig) + { + bool flag = false; + FZCallback callback(&flag); - m_settings->SetCallback(&callback); + m_settings->SetCallback(&callback); - int bufSize = 0; - m_settings->GetConfig(L"", &bufSize); + int bufSize = 0; + m_settings->GetConfig(L"", &bufSize); - Assert::IsFalse(flag); - } + Assert::IsFalse(flag); + } - TEST_METHOD(CallbackGetSettings) - { - bool flag = false; - FZCallback callback(&flag); + TEST_METHOD (CallbackGetSettings) + { + bool flag = false; + FZCallback callback(&flag); - m_settings->SetCallback(&callback); - m_settings->GetSettings(); + m_settings->SetCallback(&callback); + m_settings->GetSettings(); - Assert::IsFalse(flag); - } + Assert::IsFalse(flag); + } }; - TEST_CLASS(FancyZonesSettingsUnitTests) + TEST_CLASS (FancyZonesSettingsUnitTests) { winrt::com_ptr m_settings = nullptr; PowerToysSettings::Settings* m_ptSettings = nullptr; @@ -588,148 +621,148 @@ namespace FancyZonesUnitTests } TEST_METHOD_INITIALIZE(Init) - { - HINSTANCE hInst = (HINSTANCE)GetModuleHandleW(nullptr); + { + HINSTANCE hInst = (HINSTANCE)GetModuleHandleW(nullptr); - //init m_settings - const Settings expected{ - .shiftDrag = false, - .displayChange_moveWindows = true, - .virtualDesktopChange_moveWindows = true, - .zoneSetChange_flashZones = true, - .zoneSetChange_moveWindows = true, - .overrideSnapHotkeys = false, - .appLastZone_moveWindows = false, - .use_cursorpos_editor_startupscreen = true, - .showZonesOnAllMonitors = false, - .zoneHightlightColor = L"#00FFD7", - .zoneHighlightOpacity = 45, - .editorHotkey = PowerToysSettings::HotkeyObject::from_settings(false, true, true, false, VK_OEM_3), - .excludedApps = L"app", - .excludedAppsArray = { L"APP" }, - }; + //init m_settings + const Settings expected{ + .shiftDrag = false, + .displayChange_moveWindows = true, + .virtualDesktopChange_moveWindows = true, + .zoneSetChange_flashZones = true, + .zoneSetChange_moveWindows = true, + .overrideSnapHotkeys = false, + .appLastZone_moveWindows = false, + .use_cursorpos_editor_startupscreen = true, + .showZonesOnAllMonitors = false, + .zoneHightlightColor = L"#00FFD7", + .zoneHighlightOpacity = 45, + .editorHotkey = PowerToysSettings::HotkeyObject::from_settings(false, true, true, false, VK_OEM_3), + .excludedApps = L"app", + .excludedAppsArray = { L"APP" }, + }; - PowerToysSettings::PowerToyValues values(m_moduleName); - values.add_property(L"fancyzones_shiftDrag", expected.shiftDrag); - values.add_property(L"fancyzones_displayChange_moveWindows", expected.displayChange_moveWindows); - values.add_property(L"fancyzones_virtualDesktopChange_moveWindows", expected.virtualDesktopChange_moveWindows); - values.add_property(L"fancyzones_zoneSetChange_flashZones", expected.zoneSetChange_flashZones); - values.add_property(L"fancyzones_zoneSetChange_moveWindows", expected.zoneSetChange_moveWindows); - values.add_property(L"fancyzones_overrideSnapHotkeys", expected.overrideSnapHotkeys); - values.add_property(L"fancyzones_appLastZone_moveWindows", expected.appLastZone_moveWindows); - values.add_property(L"use_cursorpos_editor_startupscreen", expected.use_cursorpos_editor_startupscreen); - values.add_property(L"fancyzones_show_on_all_monitors", expected.showZonesOnAllMonitors); - values.add_property(L"fancyzones_zoneHighlightColor", expected.zoneHightlightColor); - values.add_property(L"fancyzones_highlight_opacity", expected.zoneHighlightOpacity); - values.add_property(L"fancyzones_editor_hotkey", expected.editorHotkey.get_json()); - values.add_property(L"fancyzones_excluded_apps", expected.excludedApps); + PowerToysSettings::PowerToyValues values(m_moduleName); + values.add_property(L"fancyzones_shiftDrag", expected.shiftDrag); + values.add_property(L"fancyzones_displayChange_moveWindows", expected.displayChange_moveWindows); + values.add_property(L"fancyzones_virtualDesktopChange_moveWindows", expected.virtualDesktopChange_moveWindows); + values.add_property(L"fancyzones_zoneSetChange_flashZones", expected.zoneSetChange_flashZones); + values.add_property(L"fancyzones_zoneSetChange_moveWindows", expected.zoneSetChange_moveWindows); + values.add_property(L"fancyzones_overrideSnapHotkeys", expected.overrideSnapHotkeys); + values.add_property(L"fancyzones_appLastZone_moveWindows", expected.appLastZone_moveWindows); + values.add_property(L"use_cursorpos_editor_startupscreen", expected.use_cursorpos_editor_startupscreen); + values.add_property(L"fancyzones_show_on_all_monitors", expected.showZonesOnAllMonitors); + values.add_property(L"fancyzones_zoneHighlightColor", expected.zoneHightlightColor); + values.add_property(L"fancyzones_highlight_opacity", expected.zoneHighlightOpacity); + values.add_property(L"fancyzones_editor_hotkey", expected.editorHotkey.get_json()); + values.add_property(L"fancyzones_excluded_apps", expected.excludedApps); - values.save_to_settings_file(); + values.save_to_settings_file(); - m_settings = MakeFancyZonesSettings(hInst, m_moduleName); - Assert::IsTrue(m_settings != nullptr); + m_settings = MakeFancyZonesSettings(hInst, m_moduleName); + Assert::IsTrue(m_settings != nullptr); - //init m_ptSettings - m_ptSettings = new PowerToysSettings::Settings(hInst, m_moduleName); - m_ptSettings->set_description(IDS_SETTING_DESCRIPTION); - m_ptSettings->set_icon_key(L"pt-fancy-zones"); - m_ptSettings->set_overview_link(L"https://github.com/microsoft/PowerToys/blob/master/src/modules/fancyzones/README.md"); - m_ptSettings->set_video_link(L"https://youtu.be/rTtGzZYAXgY"); + //init m_ptSettings + m_ptSettings = new PowerToysSettings::Settings(hInst, m_moduleName); + m_ptSettings->set_description(IDS_SETTING_DESCRIPTION); + m_ptSettings->set_icon_key(L"pt-fancy-zones"); + m_ptSettings->set_overview_link(L"https://github.com/microsoft/PowerToys/blob/master/src/modules/fancyzones/README.md"); + m_ptSettings->set_video_link(L"https://youtu.be/rTtGzZYAXgY"); - m_ptSettings->add_custom_action( - L"ToggledFZEditor", // action name. - IDS_SETTING_LAUNCH_EDITOR_LABEL, - IDS_SETTING_LAUNCH_EDITOR_BUTTON, - IDS_SETTING_LAUNCH_EDITOR_DESCRIPTION); - m_ptSettings->add_hotkey(L"fancyzones_editor_hotkey", IDS_SETTING_LAUNCH_EDITOR_HOTKEY_LABEL, expected.editorHotkey); - m_ptSettings->add_bool_toogle(L"fancyzones_shiftDrag", IDS_SETTING_DESCRIPTION_SHIFTDRAG, expected.shiftDrag); - m_ptSettings->add_bool_toogle(L"fancyzones_overrideSnapHotkeys", IDS_SETTING_DESCRIPTION_OVERRIDE_SNAP_HOTKEYS, expected.overrideSnapHotkeys); - m_ptSettings->add_bool_toogle(L"fancyzones_zoneSetChange_flashZones", IDS_SETTING_DESCRIPTION_ZONESETCHANGE_FLASHZONES, expected.zoneSetChange_flashZones); - m_ptSettings->add_bool_toogle(L"fancyzones_displayChange_moveWindows", IDS_SETTING_DESCRIPTION_DISPLAYCHANGE_MOVEWINDOWS, expected.displayChange_moveWindows); - m_ptSettings->add_bool_toogle(L"fancyzones_zoneSetChange_moveWindows", IDS_SETTING_DESCRIPTION_ZONESETCHANGE_MOVEWINDOWS, expected.zoneSetChange_moveWindows); - m_ptSettings->add_bool_toogle(L"fancyzones_virtualDesktopChange_moveWindows", IDS_SETTING_DESCRIPTION_VIRTUALDESKTOPCHANGE_MOVEWINDOWS, expected.virtualDesktopChange_moveWindows); - m_ptSettings->add_bool_toogle(L"fancyzones_appLastZone_moveWindows", IDS_SETTING_DESCRIPTION_APPLASTZONE_MOVEWINDOWS, expected.appLastZone_moveWindows); - m_ptSettings->add_bool_toogle(L"use_cursorpos_editor_startupscreen", IDS_SETTING_DESCRIPTION_USE_CURSORPOS_EDITOR_STARTUPSCREEN, expected.use_cursorpos_editor_startupscreen); - m_ptSettings->add_bool_toogle(L"fancyzones_show_on_all_monitors", IDS_SETTING_DESCRIPTION_SHOW_FANCY_ZONES_ON_ALL_MONITORS, expected.showZonesOnAllMonitors); - m_ptSettings->add_int_spinner(L"fancyzones_highlight_opacity", IDS_SETTINGS_HIGHLIGHT_OPACITY, expected.zoneHighlightOpacity, 0, 100, 1); - m_ptSettings->add_color_picker(L"fancyzones_zoneHighlightColor", IDS_SETTING_DESCRIPTION_ZONEHIGHLIGHTCOLOR, expected.zoneHightlightColor); - m_ptSettings->add_multiline_string(L"fancyzones_excluded_apps", IDS_SETTING_EXCLCUDED_APPS_DESCRIPTION, expected.excludedApps); - } + m_ptSettings->add_custom_action( + L"ToggledFZEditor", // action name. + IDS_SETTING_LAUNCH_EDITOR_LABEL, + IDS_SETTING_LAUNCH_EDITOR_BUTTON, + IDS_SETTING_LAUNCH_EDITOR_DESCRIPTION); + m_ptSettings->add_hotkey(L"fancyzones_editor_hotkey", IDS_SETTING_LAUNCH_EDITOR_HOTKEY_LABEL, expected.editorHotkey); + m_ptSettings->add_bool_toogle(L"fancyzones_shiftDrag", IDS_SETTING_DESCRIPTION_SHIFTDRAG, expected.shiftDrag); + m_ptSettings->add_bool_toogle(L"fancyzones_overrideSnapHotkeys", IDS_SETTING_DESCRIPTION_OVERRIDE_SNAP_HOTKEYS, expected.overrideSnapHotkeys); + m_ptSettings->add_bool_toogle(L"fancyzones_zoneSetChange_flashZones", IDS_SETTING_DESCRIPTION_ZONESETCHANGE_FLASHZONES, expected.zoneSetChange_flashZones); + m_ptSettings->add_bool_toogle(L"fancyzones_displayChange_moveWindows", IDS_SETTING_DESCRIPTION_DISPLAYCHANGE_MOVEWINDOWS, expected.displayChange_moveWindows); + m_ptSettings->add_bool_toogle(L"fancyzones_zoneSetChange_moveWindows", IDS_SETTING_DESCRIPTION_ZONESETCHANGE_MOVEWINDOWS, expected.zoneSetChange_moveWindows); + m_ptSettings->add_bool_toogle(L"fancyzones_virtualDesktopChange_moveWindows", IDS_SETTING_DESCRIPTION_VIRTUALDESKTOPCHANGE_MOVEWINDOWS, expected.virtualDesktopChange_moveWindows); + m_ptSettings->add_bool_toogle(L"fancyzones_appLastZone_moveWindows", IDS_SETTING_DESCRIPTION_APPLASTZONE_MOVEWINDOWS, expected.appLastZone_moveWindows); + m_ptSettings->add_bool_toogle(L"use_cursorpos_editor_startupscreen", IDS_SETTING_DESCRIPTION_USE_CURSORPOS_EDITOR_STARTUPSCREEN, expected.use_cursorpos_editor_startupscreen); + m_ptSettings->add_bool_toogle(L"fancyzones_show_on_all_monitors", IDS_SETTING_DESCRIPTION_SHOW_FANCY_ZONES_ON_ALL_MONITORS, expected.showZonesOnAllMonitors); + m_ptSettings->add_int_spinner(L"fancyzones_highlight_opacity", IDS_SETTINGS_HIGHLIGHT_OPACITY, expected.zoneHighlightOpacity, 0, 100, 1); + m_ptSettings->add_color_picker(L"fancyzones_zoneHighlightColor", IDS_SETTING_DESCRIPTION_ZONEHIGHLIGHTCOLOR, expected.zoneHightlightColor); + m_ptSettings->add_multiline_string(L"fancyzones_excluded_apps", IDS_SETTING_EXCLCUDED_APPS_DESCRIPTION, expected.excludedApps); + } - TEST_METHOD_CLEANUP(Cleanup) - { - const auto settingsFile = PTSettingsHelper::get_module_save_folder_location(m_moduleName) + L"\\settings.json"; - std::filesystem::remove(settingsFile); - } + TEST_METHOD_CLEANUP(Cleanup) + { + const auto settingsFile = PTSettingsHelper::get_module_save_folder_location(m_moduleName) + L"\\settings.json"; + std::filesystem::remove(settingsFile); + } - TEST_METHOD(GetConfig) - { - const int expectedSize = static_cast(m_ptSettings->serialize().size()) + 1; + TEST_METHOD (GetConfig) + { + const int expectedSize = static_cast(m_ptSettings->serialize().size()) + 1; - int actualBufferSize = expectedSize; - PWSTR actualBuffer = new wchar_t[actualBufferSize]; + int actualBufferSize = expectedSize; + PWSTR actualBuffer = new wchar_t[actualBufferSize]; - Assert::IsTrue(m_settings->GetConfig(actualBuffer, &actualBufferSize)); - Assert::AreEqual(expectedSize, actualBufferSize); + Assert::IsTrue(m_settings->GetConfig(actualBuffer, &actualBufferSize)); + Assert::AreEqual(expectedSize, actualBufferSize); - Assert::AreEqual(m_ptSettings->serialize().c_str(), actualBuffer); - } + Assert::AreEqual(m_ptSettings->serialize().c_str(), actualBuffer); + } - TEST_METHOD(GetConfigSmallBuffer) - { - const auto serialized = m_ptSettings->serialize(); - const int size = static_cast(serialized.size()); - const int expectedSize = size + 1; + TEST_METHOD (GetConfigSmallBuffer) + { + const auto serialized = m_ptSettings->serialize(); + const int size = static_cast(serialized.size()); + const int expectedSize = size + 1; - int actualBufferSize = size - 1; - PWSTR actualBuffer = new wchar_t[actualBufferSize]; + int actualBufferSize = size - 1; + PWSTR actualBuffer = new wchar_t[actualBufferSize]; - Assert::IsFalse(m_settings->GetConfig(actualBuffer, &actualBufferSize)); - Assert::AreEqual(expectedSize, actualBufferSize); - Assert::AreNotEqual(serialized.c_str(), actualBuffer); - } + Assert::IsFalse(m_settings->GetConfig(actualBuffer, &actualBufferSize)); + Assert::AreEqual(expectedSize, actualBufferSize); + Assert::AreNotEqual(serialized.c_str(), actualBuffer); + } - TEST_METHOD(GetConfigNullBuffer) - { - const auto serialized = m_ptSettings->serialize(); - const int expectedSize = static_cast(serialized.size()) + 1; + TEST_METHOD (GetConfigNullBuffer) + { + const auto serialized = m_ptSettings->serialize(); + const int expectedSize = static_cast(serialized.size()) + 1; - int actualBufferSize = 0; + int actualBufferSize = 0; - Assert::IsFalse(m_settings->GetConfig(nullptr, &actualBufferSize)); - Assert::AreEqual(expectedSize, actualBufferSize); - } + Assert::IsFalse(m_settings->GetConfig(nullptr, &actualBufferSize)); + Assert::AreEqual(expectedSize, actualBufferSize); + } - TEST_METHOD(SetConfig) - { - //cleanup file before call set config - const auto settingsFile = PTSettingsHelper::get_module_save_folder_location(m_moduleName) + L"\\settings.json"; - std::filesystem::remove(settingsFile); + TEST_METHOD (SetConfig) + { + //cleanup file before call set config + const auto settingsFile = PTSettingsHelper::get_module_save_folder_location(m_moduleName) + L"\\settings.json"; + std::filesystem::remove(settingsFile); - const Settings expected { - .shiftDrag = true, - .displayChange_moveWindows = true, - .virtualDesktopChange_moveWindows = true, - .zoneSetChange_flashZones = false, - .zoneSetChange_moveWindows = true, - .overrideSnapHotkeys = false, - .appLastZone_moveWindows = true, - .use_cursorpos_editor_startupscreen = true, - .showZonesOnAllMonitors = false, - .zoneHightlightColor = L"#00AABB", - .zoneHighlightOpacity = 45, - .editorHotkey = PowerToysSettings::HotkeyObject::from_settings(false, false, false, false, VK_OEM_3), - .excludedApps = L"app\r\napp2", - .excludedAppsArray = { L"APP", L"APP2" }, - }; + const Settings expected{ + .shiftDrag = true, + .displayChange_moveWindows = true, + .virtualDesktopChange_moveWindows = true, + .zoneSetChange_flashZones = false, + .zoneSetChange_moveWindows = true, + .overrideSnapHotkeys = false, + .appLastZone_moveWindows = true, + .use_cursorpos_editor_startupscreen = true, + .showZonesOnAllMonitors = false, + .zoneHightlightColor = L"#00AABB", + .zoneHighlightOpacity = 45, + .editorHotkey = PowerToysSettings::HotkeyObject::from_settings(false, false, false, false, VK_OEM_3), + .excludedApps = L"app\r\napp2", + .excludedAppsArray = { L"APP", L"APP2" }, + }; - auto config = serializedPowerToySettings(expected); - m_settings->SetConfig(config.c_str()); + auto config = serializedPowerToySettings(expected); + m_settings->SetConfig(config.c_str()); - auto actual = m_settings->GetSettings(); - compareSettings(expected, *actual); + auto actual = m_settings->GetSettings(); + compareSettings(expected, *actual); - Assert::IsTrue(std::filesystem::exists(settingsFile)); - } + Assert::IsTrue(std::filesystem::exists(settingsFile)); + } }; } \ No newline at end of file diff --git a/src/modules/fancyzones/tests/UnitTests/JsonHelpers.Tests.cpp b/src/modules/fancyzones/tests/UnitTests/JsonHelpers.Tests.cpp index ce76b56b47..01f1669e34 100644 --- a/src/modules/fancyzones/tests/UnitTests/JsonHelpers.Tests.cpp +++ b/src/modules/fancyzones/tests/UnitTests/JsonHelpers.Tests.cpp @@ -1,5 +1,6 @@ #include "pch.h" #include +#include #include #include "util.h" @@ -51,8 +52,78 @@ namespace FancyZonesUnitTests } } - TEST_CLASS(ZoneSetLayoutTypeUnitTest){ - TEST_METHOD(ZoneSetLayoutTypeToString){ + TEST_CLASS (IdValidationUnitTest) + { + TEST_METHOD (GuidValid) + { + const auto guidStr = Helpers::CreateGuidString(); + Assert::IsTrue(isValidGuid(guidStr)); + } + + TEST_METHOD (GuidInvalidForm) + { + const auto guidStr = L"33A2B101-06E0-437B-A61E-CDBECF502906"; + Assert::IsFalse(isValidGuid(guidStr)); + } + + TEST_METHOD (GuidInvalidSymbols) + { + const auto guidStr = L"{33A2B101-06E0-437B-A61E-CDBECF50290*}"; + Assert::IsFalse(isValidGuid(guidStr)); + } + + TEST_METHOD (GuidInvalid) + { + const auto guidStr = L"guid"; + Assert::IsFalse(isValidGuid(guidStr)); + } + + TEST_METHOD (DeviceId) + { + const auto deviceId = L"AOC2460#4&fe3a015&0&UID65793_1920_1200_{39B25DD2-130D-4B5D-8851-4791D66B1539}"; + Assert::IsTrue(isValidDeviceId(deviceId)); + } + + TEST_METHOD (DeviceIdInvalidFormat) + { + const auto deviceId = L"_1920_1200_{39B25DD2-130D-4B5D-8851-4791D66B1539}"; + Assert::IsFalse(isValidDeviceId(deviceId)); + } + + TEST_METHOD (DeviceIdInvalidFormat2) + { + const auto deviceId = L"AOC2460#4&fe3a015&0&UID65793_19201200_{39B25DD2-130D-4B5D-8851-4791D66B1539}"; + Assert::IsFalse(isValidDeviceId(deviceId)); + } + + TEST_METHOD (DeviceIdInvalidDecimals) + { + const auto deviceId = L"AOC2460#4&fe3a015&0&UID65793_aaaa_1200_{39B25DD2-130D-4B5D-8851-4791D66B1539}"; + Assert::IsFalse(isValidDeviceId(deviceId)); + } + + TEST_METHOD (DeviceIdInvalidDecimals2) + { + const auto deviceId = L"AOC2460#4&fe3a015&0&UID65793_19a0_1200_{39B25DD2-130D-4B5D-8851-4791D66B1539}"; + Assert::IsFalse(isValidDeviceId(deviceId)); + } + + TEST_METHOD (DeviceIdInvalidDecimals3) + { + const auto deviceId = L"AOC2460#4&fe3a015&0&UID65793_1900_120000000000000_{39B25DD2-130D-4B5D-8851-4791D66B1539}"; + Assert::IsFalse(isValidDeviceId(deviceId)); + } + + TEST_METHOD (DeviceIdInvalidGuid) + { + const auto deviceId = L"AOC2460#4&fe3a015&0&UID65793_1920_1200_{39B25DD2-4B5D-8851-4791D66B1539}"; + Assert::IsFalse(isValidDeviceId(deviceId)); + } + }; + TEST_CLASS (ZoneSetLayoutTypeUnitTest) + { + TEST_METHOD (ZoneSetLayoutTypeToString) + { std::map expectedMap = { std::make_pair(-2, L"TypeToString_ERROR"), std::make_pair(-1, L"blank"), @@ -65,1593 +136,1778 @@ namespace FancyZonesUnitTests std::make_pair(6, L"TypeToString_ERROR"), }; - for (const auto& expected : expectedMap) - { - auto actual = JSONHelpers::TypeToString(static_cast(expected.first)); - Assert::AreEqual(expected.second, actual); - } -} + for (const auto& expected : expectedMap) + { + auto actual = JSONHelpers::TypeToString(static_cast(expected.first)); + Assert::AreEqual(expected.second, actual); + } + } -TEST_METHOD(ZoneSetLayoutTypeFromString) -{ - std::map expectedMap = { - std::make_pair(ZoneSetLayoutType::Focus, L"focus"), - std::make_pair(ZoneSetLayoutType::Columns, L"columns"), - std::make_pair(ZoneSetLayoutType::Rows, L"rows"), - std::make_pair(ZoneSetLayoutType::Grid, L"grid"), - std::make_pair(ZoneSetLayoutType::PriorityGrid, L"priority-grid"), - std::make_pair(ZoneSetLayoutType::Custom, L"custom"), + TEST_METHOD (ZoneSetLayoutTypeFromString) + { + std::map expectedMap = { + std::make_pair(ZoneSetLayoutType::Focus, L"focus"), + std::make_pair(ZoneSetLayoutType::Columns, L"columns"), + std::make_pair(ZoneSetLayoutType::Rows, L"rows"), + std::make_pair(ZoneSetLayoutType::Grid, L"grid"), + std::make_pair(ZoneSetLayoutType::PriorityGrid, L"priority-grid"), + std::make_pair(ZoneSetLayoutType::Custom, L"custom"), + }; + + for (const auto& expected : expectedMap) + { + auto actual = JSONHelpers::TypeFromString(expected.second); + Assert::AreEqual(static_cast(expected.first), static_cast(actual)); + } + } + + TEST_METHOD (ZoneSetLayoutTypeFromLayoutId) + { + std::map expectedMap = { + std::make_pair(ZoneSetLayoutType::Focus, 0xFFFF), + std::make_pair(ZoneSetLayoutType::Columns, 0xFFFD), + std::make_pair(ZoneSetLayoutType::Rows, 0xFFFE), + std::make_pair(ZoneSetLayoutType::Grid, 0xFFFC), + std::make_pair(ZoneSetLayoutType::PriorityGrid, 0xFFFB), + std::make_pair(ZoneSetLayoutType::Blank, 0xFFFA), + std::make_pair(ZoneSetLayoutType::Custom, 0), + std::make_pair(ZoneSetLayoutType::Custom, 1), + std::make_pair(ZoneSetLayoutType::Custom, -1), + }; + + for (const auto& expected : expectedMap) + { + auto actual = JSONHelpers::TypeFromLayoutId(expected.second); + Assert::AreEqual(static_cast(expected.first), static_cast(actual)); + } + } }; - for (const auto& expected : expectedMap) + TEST_CLASS (CanvasLayoutInfoUnitTests) { - auto actual = JSONHelpers::TypeFromString(expected.second); - Assert::AreEqual(static_cast(expected.first), static_cast(actual)); - } -} + json::JsonObject m_json = json::JsonObject::Parse(L"{\"ref-width\": 123, \"ref-height\": 321, \"zones\": [{\"X\": 11, \"Y\": 22, \"width\": 33, \"height\": 44}, {\"X\": 55, \"Y\": 66, \"width\": 77, \"height\": 88}]}"); -TEST_METHOD(ZoneSetLayoutTypeFromLayoutId) -{ - std::map expectedMap = { - std::make_pair(ZoneSetLayoutType::Focus, 0xFFFF), - std::make_pair(ZoneSetLayoutType::Columns, 0xFFFD), - std::make_pair(ZoneSetLayoutType::Rows, 0xFFFE), - std::make_pair(ZoneSetLayoutType::Grid, 0xFFFC), - std::make_pair(ZoneSetLayoutType::PriorityGrid, 0xFFFB), - std::make_pair(ZoneSetLayoutType::Blank, 0xFFFA), - std::make_pair(ZoneSetLayoutType::Custom, 0), - std::make_pair(ZoneSetLayoutType::Custom, 1), - std::make_pair(ZoneSetLayoutType::Custom, -1), + TEST_METHOD (ToJson) + { + CanvasLayoutInfo info; + info.referenceWidth = 123; + info.referenceHeight = 321; + info.zones = { CanvasLayoutInfo::Rect{ 11, 22, 33, 44 }, CanvasLayoutInfo::Rect{ 55, 66, 77, 88 } }; + + auto actual = CanvasLayoutInfo::ToJson(info); + compareJsonObjects(m_json, actual); + } + + TEST_METHOD (FromJson) + { + CanvasLayoutInfo expected; + expected.referenceWidth = 123; + expected.referenceHeight = 321; + expected.zones = { CanvasLayoutInfo::Rect{ 11, 22, 33, 44 }, CanvasLayoutInfo::Rect{ 55, 66, 77, 88 } }; + + auto actual = CanvasLayoutInfo::FromJson(m_json); + Assert::IsTrue(actual.has_value()); + + Assert::AreEqual(expected.referenceHeight, actual->referenceHeight); + Assert::AreEqual(expected.referenceWidth, actual->referenceWidth); + Assert::AreEqual(expected.zones.size(), actual->zones.size()); + for (int i = 0; i < expected.zones.size(); i++) + { + Assert::AreEqual(expected.zones[i].x, actual->zones[i].x); + Assert::AreEqual(expected.zones[i].y, actual->zones[i].y); + Assert::AreEqual(expected.zones[i].width, actual->zones[i].width); + Assert::AreEqual(expected.zones[i].height, actual->zones[i].height); + } + } + + TEST_METHOD (FromJsonMissingKeys) + { + CanvasLayoutInfo info{ 123, 321, { CanvasLayoutInfo::Rect{ 11, 22, 33, 44 }, CanvasLayoutInfo::Rect{ 55, 66, 77, 88 } } }; + const auto json = CanvasLayoutInfo::ToJson(info); + + auto iter = json.First(); + while (iter.HasCurrent()) + { + json::JsonObject modifiedJson = json::JsonObject::Parse(json.Stringify()); + modifiedJson.Remove(iter.Current().Key()); + + auto actual = CanvasLayoutInfo::FromJson(modifiedJson); + Assert::IsFalse(actual.has_value()); + + iter.MoveNext(); + } + } + + TEST_METHOD (FromJsonInvalidTypes) + { + json::JsonObject m_json = json::JsonObject::Parse(L"{\"ref-width\": true, \"ref-height\": \"string\", \"zones\": [{\"X\": \"11\", \"Y\": \"22\", \"width\": \".\", \"height\": \"*\"}, {\"X\": null, \"Y\": {}, \"width\": [], \"height\": \"абвгд\"}]}"); + Assert::IsFalse(CanvasLayoutInfo::FromJson(m_json).has_value()); + } }; - for (const auto& expected : expectedMap) + TEST_CLASS (GridLayoutInfoUnitTests) { - auto actual = JSONHelpers::TypeFromLayoutId(expected.second); - Assert::AreEqual(static_cast(expected.first), static_cast(actual)); - } -} -} -; + GridLayoutInfo m_info = GridLayoutInfo(GridLayoutInfo::Minimal{ .rows = 3, .columns = 4 }); + json::JsonObject m_gridJson = json::JsonObject(); + json::JsonArray m_rowsArray, m_columnsArray, m_cells; -TEST_CLASS(CanvasLayoutInfoUnitTests) -{ - json::JsonObject m_json = json::JsonObject::Parse(L"{\"ref-width\": 123, \"ref-height\": 321, \"zones\": [{\"X\": 11, \"Y\": 22, \"width\": 33, \"height\": 44}, {\"X\": 55, \"Y\": 66, \"width\": 77, \"height\": 88}]}"); - - TEST_METHOD(ToJson) - { - CanvasLayoutInfo info; - info.referenceWidth = 123; - info.referenceHeight = 321; - info.zones = { CanvasLayoutInfo::Rect{ 11, 22, 33, 44 }, CanvasLayoutInfo::Rect{ 55, 66, 77, 88 } }; - - auto actual = CanvasLayoutInfo::ToJson(info); - compareJsonObjects(m_json, actual); - } - - TEST_METHOD(FromJson) - { - CanvasLayoutInfo expected; - expected.referenceWidth = 123; - expected.referenceHeight = 321; - expected.zones = { CanvasLayoutInfo::Rect{ 11, 22, 33, 44 }, CanvasLayoutInfo::Rect{ 55, 66, 77, 88 } }; - - auto actual = CanvasLayoutInfo::FromJson(m_json); - Assert::IsTrue(actual.has_value()); - - Assert::AreEqual(expected.referenceHeight, actual->referenceHeight); - Assert::AreEqual(expected.referenceWidth, actual->referenceWidth); - Assert::AreEqual(expected.zones.size(), actual->zones.size()); - for (int i = 0; i < expected.zones.size(); i++) + void compareSizes(int expectedRows, int expectedColumns, const GridLayoutInfo& actual) { - Assert::AreEqual(expected.zones[i].x, actual->zones[i].x); - Assert::AreEqual(expected.zones[i].y, actual->zones[i].y); - Assert::AreEqual(expected.zones[i].width, actual->zones[i].width); - Assert::AreEqual(expected.zones[i].height, actual->zones[i].height); + Assert::AreEqual(expectedRows, actual.rows()); + Assert::AreEqual(expectedColumns, actual.columns()); + Assert::AreEqual((size_t)expectedRows, actual.rowsPercents().size()); + Assert::AreEqual((size_t)expectedColumns, actual.columnsPercents().size()); + Assert::AreEqual((size_t)expectedRows, actual.cellChildMap().size()); + + for (int i = 0; i < expectedRows; i++) + { + Assert::AreEqual((size_t)expectedColumns, actual.cellChildMap()[i].size()); + } } - } - TEST_METHOD(FromJsonMissingKeys) - { - CanvasLayoutInfo info{ 123, 321, { CanvasLayoutInfo::Rect{ 11, 22, 33, 44 }, CanvasLayoutInfo::Rect{ 55, 66, 77, 88 } } }; - const auto json = CanvasLayoutInfo::ToJson(info); - - auto iter = json.First(); - while (iter.HasCurrent()) + void compareVectors(const std::vector& expected, const std::vector& actual) { - json::JsonObject modifiedJson = json::JsonObject::Parse(json.Stringify()); - modifiedJson.Remove(iter.Current().Key()); + Assert::AreEqual(expected.size(), actual.size()); + for (int i = 0; i < expected.size(); i++) + { + Assert::AreEqual(expected[i], actual[i]); + } + } - auto actual = CanvasLayoutInfo::FromJson(modifiedJson); + void compareGridInfos(const GridLayoutInfo& expected, const GridLayoutInfo& actual) + { + compareSizes(expected.rows(), expected.columns(), actual); + + compareVectors(expected.rowsPercents(), actual.rowsPercents()); + compareVectors(expected.columnsPercents(), actual.columnsPercents()); + for (int i = 0; i < expected.cellChildMap().size(); i++) + { + compareVectors(expected.cellChildMap()[i], actual.cellChildMap()[i]); + } + } + + TEST_METHOD_INITIALIZE(Init) + { + m_info = GridLayoutInfo(GridLayoutInfo::Minimal{ .rows = 3, .columns = 4 }); + for (int i = 0; i < m_info.rows(); i++) + { + int row = rand() % 100; + m_rowsArray.Append(json::JsonValue::CreateNumberValue(row)); + m_info.rowsPercents()[i] = row; + } + + for (int i = 0; i < m_info.columns(); i++) + { + int column = rand() % 100; + m_columnsArray.Append(json::JsonValue::CreateNumberValue(column)); + m_info.columnsPercents()[i] = column; + } + + for (int i = 0; i < m_info.rows(); i++) + { + json::JsonArray cellsArray; + for (int j = 0; j < m_info.columns(); j++) + { + int cell = rand() % 100; + m_info.cellChildMap()[i][j] = cell; + cellsArray.Append(json::JsonValue::CreateNumberValue(cell)); + } + m_cells.Append(cellsArray); + } + + m_gridJson = json::JsonObject::Parse(L"{\"rows\": 3, \"columns\": 4}"); + m_gridJson.SetNamedValue(L"rows-percentage", m_rowsArray); + m_gridJson.SetNamedValue(L"columns-percentage", m_columnsArray); + m_gridJson.SetNamedValue(L"cell-child-map", m_cells); + } + + TEST_METHOD_CLEANUP(Cleanup) + { + m_rowsArray.Clear(); + m_cells.Clear(); + m_columnsArray.Clear(); + m_gridJson.Clear(); + m_info = GridLayoutInfo(GridLayoutInfo::Minimal{ .rows = 3, .columns = 4 }); + } + + TEST_METHOD (CreationZero) + { + const int expectedRows = 0, expectedColumns = 0; + GridLayoutInfo info(GridLayoutInfo::Minimal{ .rows = expectedRows, .columns = expectedColumns }); + compareSizes(expectedRows, expectedColumns, info); + } + + TEST_METHOD (Creation) + { + const int expectedRows = 3, expectedColumns = 4; + const std::vector expectedRowsPercents = { 0, 0, 0 }; + const std::vector expectedColumnsPercents = { 0, 0, 0, 0 }; + + GridLayoutInfo info(GridLayoutInfo::Minimal{ .rows = expectedRows, .columns = expectedColumns }); + compareSizes(expectedRows, expectedColumns, info); + + compareVectors(expectedRowsPercents, info.rowsPercents()); + compareVectors(expectedColumnsPercents, info.columnsPercents()); + for (int i = 0; i < info.cellChildMap().size(); i++) + { + compareVectors({ 0, 0, 0, 0 }, info.cellChildMap()[i]); + } + } + + TEST_METHOD (CreationFull) + { + const int expectedRows = 3, expectedColumns = 4; + const std::vector expectedRowsPercents = { 1, 2, 3 }; + const std::vector expectedColumnsPercents = { 4, 3, 2, 1 }; + const std::vector> expectedCells = { expectedColumnsPercents, expectedColumnsPercents, expectedColumnsPercents }; + + GridLayoutInfo info(GridLayoutInfo::Full{ + .rows = expectedRows, + .columns = expectedColumns, + .rowsPercents = expectedRowsPercents, + .columnsPercents = expectedColumnsPercents, + .cellChildMap = expectedCells }); + compareSizes(expectedRows, expectedColumns, info); + + compareVectors(expectedRowsPercents, info.rowsPercents()); + compareVectors(expectedColumnsPercents, info.columnsPercents()); + for (int i = 0; i < info.cellChildMap().size(); i++) + { + compareVectors(expectedCells[i], info.cellChildMap()[i]); + } + } + + TEST_METHOD (CreationFullVectorsSmaller) + { + const int expectedRows = 3, expectedColumns = 4; + const std::vector expectedRowsPercents = { 1, 2, 0 }; + const std::vector expectedColumnsPercents = { 4, 3, 0, 0 }; + const std::vector> expectedCells = { { 0, 0, 0, 0 }, { 1, 0, 0, 0 }, { 1, 2, 0, 0 } }; + + GridLayoutInfo info(GridLayoutInfo::Full{ + .rows = expectedRows, + .columns = expectedColumns, + .rowsPercents = { 1, 2 }, + .columnsPercents = { 4, 3 }, + .cellChildMap = { {}, { 1 }, { 1, 2 } } }); + compareSizes(expectedRows, expectedColumns, info); + + compareVectors(expectedRowsPercents, info.rowsPercents()); + compareVectors(expectedColumnsPercents, info.columnsPercents()); + for (int i = 0; i < info.cellChildMap().size(); i++) + { + compareVectors(expectedCells[i], info.cellChildMap()[i]); + } + } + + TEST_METHOD (CreationFullVectorsBigger) + { + const int expectedRows = 3, expectedColumns = 4; + const std::vector expectedRowsPercents = { 1, 2, 3 }; + const std::vector expectedColumnsPercents = { 4, 3, 2, 1 }; + const std::vector> expectedCells = { expectedColumnsPercents, expectedColumnsPercents, expectedColumnsPercents }; + + GridLayoutInfo info(GridLayoutInfo::Full{ + .rows = expectedRows, + .columns = expectedColumns, + .rowsPercents = { 1, 2, 3, 4, 5 }, + .columnsPercents = { 4, 3, 2, 1, 0, -1 }, + .cellChildMap = { { 4, 3, 2, 1, 0, -1 }, { 4, 3, 2, 1, 0, -1 }, { 4, 3, 2, 1, 0, -1 } } }); + compareSizes(expectedRows, expectedColumns, info); + + compareVectors(expectedRowsPercents, info.rowsPercents()); + compareVectors(expectedColumnsPercents, info.columnsPercents()); + for (int i = 0; i < info.cellChildMap().size(); i++) + { + compareVectors(expectedCells[i], info.cellChildMap()[i]); + } + } + + TEST_METHOD (ToJson) + { + json::JsonObject expected = json::JsonObject(m_gridJson); + GridLayoutInfo info = m_info; + + auto actual = GridLayoutInfo::ToJson(info); + compareJsonObjects(expected, actual); + } + + TEST_METHOD (FromJson) + { + json::JsonObject json = json::JsonObject(m_gridJson); + GridLayoutInfo expected = m_info; + + auto actual = GridLayoutInfo::FromJson(json); + Assert::IsTrue(actual.has_value()); + compareGridInfos(expected, *actual); + } + + TEST_METHOD (FromJsonEmptyArray) + { + json::JsonObject json = json::JsonObject::Parse(L"{\"rows\": 0, \"columns\": 0}"); + GridLayoutInfo expected(GridLayoutInfo::Minimal{ 0, 0 }); + + json.SetNamedValue(L"rows-percentage", json::JsonArray()); + json.SetNamedValue(L"columns-percentage", json::JsonArray()); + json.SetNamedValue(L"cell-child-map", json::JsonArray()); + + auto actual = GridLayoutInfo::FromJson(json); + Assert::IsTrue(actual.has_value()); + compareGridInfos(expected, *actual); + } + + TEST_METHOD (FromJsonSmallerArray) + { + GridLayoutInfo expected = m_info; + expected.rowsPercents().pop_back(); + expected.columnsPercents().pop_back(); + expected.cellChildMap().pop_back(); + expected.cellChildMap()[0].pop_back(); + json::JsonObject json = GridLayoutInfo::ToJson(expected); + + auto actual = GridLayoutInfo::FromJson(json); + Assert::IsFalse(actual.has_value()); + } + + TEST_METHOD (FromJsonBiggerArray) + { + GridLayoutInfo expected = m_info; + + //extra + for (int i = 0; i < 5; i++) + { + expected.rowsPercents().push_back(rand() % 100); + expected.columnsPercents().push_back(rand() % 100); + expected.cellChildMap().push_back({}); + + for (int j = 0; j < 5; j++) + { + expected.cellChildMap()[i].push_back(rand() % 100); + } + } + + auto json = GridLayoutInfo::ToJson(expected); + + auto actual = GridLayoutInfo::FromJson(json); + Assert::IsFalse(actual.has_value()); + } + + TEST_METHOD (FromJsonMissingKeys) + { + GridLayoutInfo info = m_info; + const auto json = json::JsonObject(m_gridJson); + + auto iter = json.First(); + while (iter.HasCurrent()) + { + json::JsonObject modifiedJson = json::JsonObject::Parse(json.Stringify()); + modifiedJson.Remove(iter.Current().Key()); + + auto actual = GridLayoutInfo::FromJson(modifiedJson); + Assert::IsFalse(actual.has_value()); + + iter.MoveNext(); + } + } + + TEST_METHOD (FromJsonInvalidTypes) + { + json::JsonObject gridJson = json::JsonObject::Parse(L"{\"rows\": \"три\", \"columns\": \"четыре\"}"); + Assert::IsFalse(GridLayoutInfo::FromJson(gridJson).has_value()); + } + }; + + TEST_CLASS (CustomZoneSetUnitTests) + { + TEST_METHOD (ToJsonGrid) + { + CustomZoneSetJSON zoneSet{ L"uuid", CustomZoneSetData{ L"name", CustomLayoutType::Grid, GridLayoutInfo(GridLayoutInfo::Minimal{}) } }; + + json::JsonObject expected = json::JsonObject::Parse(L"{\"uuid\": \"uuid\", \"name\": \"name\", \"type\": \"grid\"}"); + expected.SetNamedValue(L"info", GridLayoutInfo::ToJson(std::get(zoneSet.data.info))); + + auto actual = CustomZoneSetJSON::ToJson(zoneSet); + compareJsonObjects(expected, actual); + } + + TEST_METHOD (ToJsonCanvas) + { + CustomZoneSetJSON zoneSet{ L"uuid", CustomZoneSetData{ L"name", CustomLayoutType::Canvas, CanvasLayoutInfo{} } }; + + json::JsonObject expected = json::JsonObject::Parse(L"{\"uuid\": \"uuid\", \"name\": \"name\", \"type\": \"canvas\"}"); + expected.SetNamedValue(L"info", CanvasLayoutInfo::ToJson(std::get(zoneSet.data.info))); + + auto actual = CustomZoneSetJSON::ToJson(zoneSet); + compareJsonObjects(expected, actual); + } + + TEST_METHOD (FromJsonGrid) + { + const auto grid = GridLayoutInfo(GridLayoutInfo::Full{ 1, 3, { 10000 }, { 2500, 5000, 2500 }, { { 0, 1, 2 } } }); + CustomZoneSetJSON expected{ L"{33A2B101-06E0-437B-A61E-CDBECF502906}", CustomZoneSetData{ L"name", CustomLayoutType::Grid, grid } }; + + json::JsonObject json = json::JsonObject::Parse(L"{\"uuid\": \"{33A2B101-06E0-437B-A61E-CDBECF502906}\", \"name\": \"name\", \"type\": \"grid\"}"); + json.SetNamedValue(L"info", GridLayoutInfo::ToJson(std::get(expected.data.info))); + + auto actual = CustomZoneSetJSON::FromJson(json); + Assert::IsTrue(actual.has_value()); + + Assert::AreEqual(expected.uuid.c_str(), actual->uuid.c_str()); + Assert::AreEqual(expected.data.name.c_str(), actual->data.name.c_str()); + Assert::AreEqual((int)expected.data.type, (int)actual->data.type); + + auto expectedGrid = std::get(expected.data.info); + auto actualGrid = std::get(actual->data.info); + Assert::AreEqual(expectedGrid.rows(), actualGrid.rows()); + Assert::AreEqual(expectedGrid.columns(), actualGrid.columns()); + } + + TEST_METHOD (FromJsonCanvas) + { + CustomZoneSetJSON expected{ L"{33A2B101-06E0-437B-A61E-CDBECF502906}", CustomZoneSetData{ L"name", CustomLayoutType::Canvas, CanvasLayoutInfo{ 2, 1 } } }; + + json::JsonObject json = json::JsonObject::Parse(L"{\"uuid\": \"{33A2B101-06E0-437B-A61E-CDBECF502906}\", \"name\": \"name\", \"type\": \"canvas\"}"); + json.SetNamedValue(L"info", CanvasLayoutInfo::ToJson(std::get(expected.data.info))); + + auto actual = CustomZoneSetJSON::FromJson(json); + Assert::IsTrue(actual.has_value()); + + Assert::AreEqual(expected.uuid.c_str(), actual->uuid.c_str()); + Assert::AreEqual(expected.data.name.c_str(), actual->data.name.c_str()); + Assert::AreEqual((int)expected.data.type, (int)actual->data.type); + + auto expectedGrid = std::get(expected.data.info); + auto actualGrid = std::get(actual->data.info); + Assert::AreEqual(expectedGrid.referenceWidth, actualGrid.referenceWidth); + Assert::AreEqual(expectedGrid.referenceHeight, actualGrid.referenceHeight); + } + + TEST_METHOD (FromJsonGridInvalidUuid) + { + const auto grid = GridLayoutInfo(GridLayoutInfo::Full{ 1, 3, { 10000 }, { 2500, 5000, 2500 }, { { 0, 1, 2 } } }); + CustomZoneSetJSON expected{ L"uuid", CustomZoneSetData{ L"name", CustomLayoutType::Grid, grid } }; + + json::JsonObject json = json::JsonObject::Parse(L"{\"uuid\": \"uuid\", \"name\": \"name\", \"type\": \"grid\"}"); + json.SetNamedValue(L"info", GridLayoutInfo::ToJson(std::get(expected.data.info))); + + auto actual = CustomZoneSetJSON::FromJson(json); Assert::IsFalse(actual.has_value()); - - iter.MoveNext(); - } - } -}; - -TEST_CLASS(GridLayoutInfoUnitTests) -{ -private: - GridLayoutInfo m_info = GridLayoutInfo(GridLayoutInfo::Minimal{ .rows = 3, .columns = 4 }); - json::JsonObject m_gridJson = json::JsonObject(); - json::JsonArray m_rowsArray, m_columnsArray, m_cells; - - void compareSizes(int expectedRows, int expectedColumns, const GridLayoutInfo& actual) - { - Assert::AreEqual(expectedRows, actual.rows()); - Assert::AreEqual(expectedColumns, actual.columns()); - Assert::AreEqual((size_t)expectedRows, actual.rowsPercents().size()); - Assert::AreEqual((size_t)expectedColumns, actual.columnsPercents().size()); - Assert::AreEqual((size_t)expectedRows, actual.cellChildMap().size()); - - for (int i = 0; i < expectedRows; i++) - { - Assert::AreEqual((size_t)expectedColumns, actual.cellChildMap()[i].size()); - } - } - - void compareVectors(const std::vector& expected, const std::vector& actual) - { - Assert::AreEqual(expected.size(), actual.size()); - for (int i = 0; i < expected.size(); i++) - { - Assert::AreEqual(expected[i], actual[i]); - } - } - - void compareGridInfos(const GridLayoutInfo& expected, const GridLayoutInfo& actual) - { - compareSizes(expected.rows(), expected.columns(), actual); - - compareVectors(expected.rowsPercents(), actual.rowsPercents()); - compareVectors(expected.columnsPercents(), actual.columnsPercents()); - for (int i = 0; i < expected.cellChildMap().size(); i++) - { - compareVectors(expected.cellChildMap()[i], actual.cellChildMap()[i]); - } - } - - TEST_METHOD_INITIALIZE(Init) - { - m_info = GridLayoutInfo(GridLayoutInfo::Minimal{ .rows = 3, .columns = 4 }); - for (int i = 0; i < m_info.rows(); i++) - { - int row = rand() % 100; - m_rowsArray.Append(json::JsonValue::CreateNumberValue(row)); - m_info.rowsPercents()[i] = row; } - for (int i = 0; i < m_info.columns(); i++) + TEST_METHOD (FromJsonCanvasInvalidUuid) { - int column = rand() % 100; - m_columnsArray.Append(json::JsonValue::CreateNumberValue(column)); - m_info.columnsPercents()[i] = column; - } + CustomZoneSetJSON expected{ L"uuid", CustomZoneSetData{ L"name", CustomLayoutType::Canvas, CanvasLayoutInfo{ 2, 1 } } }; - for (int i = 0; i < m_info.rows(); i++) - { - json::JsonArray cellsArray; - for (int j = 0; j < m_info.columns(); j++) - { - int cell = rand() % 100; - m_info.cellChildMap()[i][j] = cell; - cellsArray.Append(json::JsonValue::CreateNumberValue(cell)); - } - m_cells.Append(cellsArray); - } + json::JsonObject json = json::JsonObject::Parse(L"{\"uuid\": \"uuid\", \"name\": \"name\", \"type\": \"canvas\"}"); + json.SetNamedValue(L"info", CanvasLayoutInfo::ToJson(std::get(expected.data.info))); - m_gridJson = json::JsonObject::Parse(L"{\"rows\": 3, \"columns\": 4}"); - m_gridJson.SetNamedValue(L"rows-percentage", m_rowsArray); - m_gridJson.SetNamedValue(L"columns-percentage", m_columnsArray); - m_gridJson.SetNamedValue(L"cell-child-map", m_cells); - } - - TEST_METHOD_CLEANUP(Cleanup) - { - m_rowsArray.Clear(); - m_cells.Clear(); - m_columnsArray.Clear(); - m_gridJson.Clear(); - m_info = GridLayoutInfo(GridLayoutInfo::Minimal{ .rows = 3, .columns = 4 }); - } - -public: - TEST_METHOD(CreationZero) - { - const int expectedRows = 0, expectedColumns = 0; - GridLayoutInfo info(GridLayoutInfo::Minimal{ .rows = expectedRows, .columns = expectedColumns }); - compareSizes(expectedRows, expectedColumns, info); - } - - TEST_METHOD(Creation) - { - const int expectedRows = 3, expectedColumns = 4; - const std::vector expectedRowsPercents = { 0, 0, 0 }; - const std::vector expectedColumnsPercents = { 0, 0, 0, 0 }; - - GridLayoutInfo info(GridLayoutInfo::Minimal{ .rows = expectedRows, .columns = expectedColumns }); - compareSizes(expectedRows, expectedColumns, info); - - compareVectors(expectedRowsPercents, info.rowsPercents()); - compareVectors(expectedColumnsPercents, info.columnsPercents()); - for (int i = 0; i < info.cellChildMap().size(); i++) - { - compareVectors({ 0, 0, 0, 0 }, info.cellChildMap()[i]); - } - } - - TEST_METHOD(CreationFull) - { - const int expectedRows = 3, expectedColumns = 4; - const std::vector expectedRowsPercents = { 1, 2, 3 }; - const std::vector expectedColumnsPercents = { 4, 3, 2, 1 }; - const std::vector> expectedCells = { expectedColumnsPercents, expectedColumnsPercents, expectedColumnsPercents }; - - GridLayoutInfo info(GridLayoutInfo::Full{ - .rows = expectedRows, - .columns = expectedColumns, - .rowsPercents = expectedRowsPercents, - .columnsPercents = expectedColumnsPercents, - .cellChildMap = expectedCells }); - compareSizes(expectedRows, expectedColumns, info); - - compareVectors(expectedRowsPercents, info.rowsPercents()); - compareVectors(expectedColumnsPercents, info.columnsPercents()); - for (int i = 0; i < info.cellChildMap().size(); i++) - { - compareVectors(expectedCells[i], info.cellChildMap()[i]); - } - } - - TEST_METHOD(CreationFullVectorsSmaller) - { - const int expectedRows = 3, expectedColumns = 4; - const std::vector expectedRowsPercents = { 1, 2, 0 }; - const std::vector expectedColumnsPercents = { 4, 3, 0, 0 }; - const std::vector> expectedCells = { { 0, 0, 0, 0 }, { 1, 0, 0, 0 }, { 1, 2, 0, 0 } }; - - GridLayoutInfo info(GridLayoutInfo::Full{ - .rows = expectedRows, - .columns = expectedColumns, - .rowsPercents = { 1, 2 }, - .columnsPercents = { 4, 3 }, - .cellChildMap = { {}, { 1 }, { 1, 2 } } }); - compareSizes(expectedRows, expectedColumns, info); - - compareVectors(expectedRowsPercents, info.rowsPercents()); - compareVectors(expectedColumnsPercents, info.columnsPercents()); - for (int i = 0; i < info.cellChildMap().size(); i++) - { - compareVectors(expectedCells[i], info.cellChildMap()[i]); - } - } - - TEST_METHOD(CreationFullVectorsBigger) - { - const int expectedRows = 3, expectedColumns = 4; - const std::vector expectedRowsPercents = { 1, 2, 3 }; - const std::vector expectedColumnsPercents = { 4, 3, 2, 1 }; - const std::vector> expectedCells = { expectedColumnsPercents, expectedColumnsPercents, expectedColumnsPercents }; - - GridLayoutInfo info(GridLayoutInfo::Full{ - .rows = expectedRows, - .columns = expectedColumns, - .rowsPercents = { 1, 2, 3, 4, 5 }, - .columnsPercents = { 4, 3, 2, 1, 0, -1 }, - .cellChildMap = { { 4, 3, 2, 1, 0, -1 }, { 4, 3, 2, 1, 0, -1 }, { 4, 3, 2, 1, 0, -1 } } }); - compareSizes(expectedRows, expectedColumns, info); - - compareVectors(expectedRowsPercents, info.rowsPercents()); - compareVectors(expectedColumnsPercents, info.columnsPercents()); - for (int i = 0; i < info.cellChildMap().size(); i++) - { - compareVectors(expectedCells[i], info.cellChildMap()[i]); - } - } - - TEST_METHOD(ToJson) - { - json::JsonObject expected = json::JsonObject(m_gridJson); - GridLayoutInfo info = m_info; - - auto actual = GridLayoutInfo::ToJson(info); - compareJsonObjects(expected, actual); - } - - TEST_METHOD(FromJson) - { - json::JsonObject json = json::JsonObject(m_gridJson); - GridLayoutInfo expected = m_info; - - auto actual = GridLayoutInfo::FromJson(json); - Assert::IsTrue(actual.has_value()); - compareGridInfos(expected, *actual); - } - - TEST_METHOD(FromJsonEmptyArray) - { - json::JsonObject json = json::JsonObject::Parse(L"{\"rows\": 0, \"columns\": 0}"); - GridLayoutInfo expected(GridLayoutInfo::Minimal{ 0, 0 }); - - json.SetNamedValue(L"rows-percentage", json::JsonArray()); - json.SetNamedValue(L"columns-percentage", json::JsonArray()); - json.SetNamedValue(L"cell-child-map", json::JsonArray()); - - auto actual = GridLayoutInfo::FromJson(json); - Assert::IsTrue(actual.has_value()); - compareGridInfos(expected, *actual); - } - - TEST_METHOD(FromJsonSmallerArray) - { - GridLayoutInfo expected = m_info; - expected.rowsPercents().pop_back(); - expected.columnsPercents().pop_back(); - expected.cellChildMap().pop_back(); - expected.cellChildMap()[0].pop_back(); - json::JsonObject json = GridLayoutInfo::ToJson(expected); - - auto actual = GridLayoutInfo::FromJson(json); - Assert::IsFalse(actual.has_value()); - } - - TEST_METHOD(FromJsonBiggerArray) - { - GridLayoutInfo expected = m_info; - - //extra - for (int i = 0; i < 5; i++) - { - expected.rowsPercents().push_back(rand() % 100); - expected.columnsPercents().push_back(rand() % 100); - expected.cellChildMap().push_back({}); - - for (int j = 0; j < 5; j++) - { - expected.cellChildMap()[i].push_back(rand() % 100); - } - } - - auto json = GridLayoutInfo::ToJson(expected); - - auto actual = GridLayoutInfo::FromJson(json); - Assert::IsFalse(actual.has_value()); - } - - TEST_METHOD(FromJsonMissingKeys) - { - GridLayoutInfo info = m_info; - const auto json = json::JsonObject(m_gridJson); - - auto iter = json.First(); - while (iter.HasCurrent()) - { - json::JsonObject modifiedJson = json::JsonObject::Parse(json.Stringify()); - modifiedJson.Remove(iter.Current().Key()); - - auto actual = GridLayoutInfo::FromJson(modifiedJson); + auto actual = CustomZoneSetJSON::FromJson(json); Assert::IsFalse(actual.has_value()); - - iter.MoveNext(); } - } -}; -TEST_CLASS(CustomZoneSetUnitTests){ - TEST_METHOD(ToJsonGrid){ - CustomZoneSetJSON zoneSet{ L"uuid", CustomZoneSetData{ L"name", CustomLayoutType::Grid, GridLayoutInfo(GridLayoutInfo::Minimal{}) } }; - -json::JsonObject expected = json::JsonObject::Parse(L"{\"uuid\": \"uuid\", \"name\": \"name\", \"type\": \"grid\"}"); -expected.SetNamedValue(L"info", GridLayoutInfo::ToJson(std::get(zoneSet.data.info))); - -auto actual = CustomZoneSetJSON::ToJson(zoneSet); -compareJsonObjects(expected, actual); -} - -TEST_METHOD(ToJsonCanvas) -{ - CustomZoneSetJSON zoneSet{ L"uuid", CustomZoneSetData{ L"name", CustomLayoutType::Canvas, CanvasLayoutInfo{} } }; - - json::JsonObject expected = json::JsonObject::Parse(L"{\"uuid\": \"uuid\", \"name\": \"name\", \"type\": \"canvas\"}"); - expected.SetNamedValue(L"info", CanvasLayoutInfo::ToJson(std::get(zoneSet.data.info))); - - auto actual = CustomZoneSetJSON::ToJson(zoneSet); - compareJsonObjects(expected, actual); -} - -TEST_METHOD(FromJsonGrid) -{ - const auto grid = GridLayoutInfo(GridLayoutInfo::Full{ 1, 3, { 10000 }, { 2500, 5000, 2500 }, { { 0, 1, 2 } } }); - CustomZoneSetJSON expected{ L"uuid", CustomZoneSetData{ L"name", CustomLayoutType::Grid, grid } }; - - json::JsonObject json = json::JsonObject::Parse(L"{\"uuid\": \"uuid\", \"name\": \"name\", \"type\": \"grid\"}"); - json.SetNamedValue(L"info", GridLayoutInfo::ToJson(std::get(expected.data.info))); - - auto actual = CustomZoneSetJSON::FromJson(json); - Assert::IsTrue(actual.has_value()); - - Assert::AreEqual(expected.uuid.c_str(), actual->uuid.c_str()); - Assert::AreEqual(expected.data.name.c_str(), actual->data.name.c_str()); - Assert::AreEqual((int)expected.data.type, (int)actual->data.type); - - auto expectedGrid = std::get(expected.data.info); - auto actualGrid = std::get(actual->data.info); - Assert::AreEqual(expectedGrid.rows(), actualGrid.rows()); - Assert::AreEqual(expectedGrid.columns(), actualGrid.columns()); -} - -TEST_METHOD(FromJsonCanvas) -{ - CustomZoneSetJSON expected{ L"uuid", CustomZoneSetData{ L"name", CustomLayoutType::Canvas, CanvasLayoutInfo{ 2, 1 } } }; - - json::JsonObject json = json::JsonObject::Parse(L"{\"uuid\": \"uuid\", \"name\": \"name\", \"type\": \"canvas\"}"); - json.SetNamedValue(L"info", CanvasLayoutInfo::ToJson(std::get(expected.data.info))); - - auto actual = CustomZoneSetJSON::FromJson(json); - Assert::IsTrue(actual.has_value()); - - Assert::AreEqual(expected.uuid.c_str(), actual->uuid.c_str()); - Assert::AreEqual(expected.data.name.c_str(), actual->data.name.c_str()); - Assert::AreEqual((int)expected.data.type, (int)actual->data.type); - - auto expectedGrid = std::get(expected.data.info); - auto actualGrid = std::get(actual->data.info); - Assert::AreEqual(expectedGrid.referenceWidth, actualGrid.referenceWidth); - Assert::AreEqual(expectedGrid.referenceHeight, actualGrid.referenceHeight); -} - -TEST_METHOD(FromJsonMissingKeys) -{ - CustomZoneSetJSON zoneSet{ L"uuid", CustomZoneSetData{ L"name", CustomLayoutType::Canvas, CanvasLayoutInfo{ 2, 1 } } }; - const auto json = CustomZoneSetJSON::ToJson(zoneSet); - - auto iter = json.First(); - while (iter.HasCurrent()) - { - json::JsonObject modifiedJson = json::JsonObject::Parse(json.Stringify()); - modifiedJson.Remove(iter.Current().Key()); - - auto actual = CustomZoneSetJSON::FromJson(modifiedJson); - Assert::IsFalse(actual.has_value()); - - iter.MoveNext(); - } -} -} -; - -TEST_CLASS(ZoneSetDataUnitTest){ - TEST_METHOD(ToJsonGeneral){ - json::JsonObject expected = json::JsonObject::Parse(L"{\"uuid\": \"uuid\", \"type\": \"rows\"}"); -ZoneSetData data{ L"uuid", ZoneSetLayoutType::Rows }; -const auto actual = ZoneSetData::ToJson(data); -compareJsonObjects(expected, actual); -} - -TEST_METHOD(FromJsonGeneral) -{ - ZoneSetData expected{ L"uuid", ZoneSetLayoutType::Columns }; - - json::JsonObject json = json::JsonObject::Parse(L"{\"uuid\": \"uuid\", \"type\": \"columns\"}"); - auto actual = ZoneSetData::FromJson(json); - Assert::IsTrue(actual.has_value()); - - Assert::AreEqual(expected.uuid.c_str(), actual->uuid.c_str()); - Assert::AreEqual((int)expected.type, (int)actual->type); -} - -TEST_METHOD(FromJsonTypeInvalid) -{ - ZoneSetData expected{ L"uuid", ZoneSetLayoutType::Blank }; - - json::JsonObject json = json::JsonObject::Parse(L"{\"uuid\": \"uuid\", \"type\": \"invalid_type\"}"); - auto actual = ZoneSetData::FromJson(json); - Assert::IsTrue(actual.has_value()); - - Assert::AreEqual(expected.uuid.c_str(), actual->uuid.c_str()); - Assert::AreEqual((int)expected.type, (int)actual->type); -} - -TEST_METHOD(FromJsonMissingKeys) -{ - ZoneSetData data{ L"uuid", ZoneSetLayoutType::Columns }; - const auto json = ZoneSetData::ToJson(data); - - auto iter = json.First(); - while (iter.HasCurrent()) - { - json::JsonObject modifiedJson = json::JsonObject::Parse(json.Stringify()); - modifiedJson.Remove(iter.Current().Key()); - - auto actual = ZoneSetData::FromJson(modifiedJson); - Assert::IsFalse(actual.has_value()); - - iter.MoveNext(); - } -} -} -; - -TEST_CLASS(AppZoneHistoryUnitTests){ - TEST_METHOD(ToJson){ - AppZoneHistoryJSON appZoneHistory{ L"appPath", AppZoneHistoryData{ .zoneSetUuid = L"zoneset-uuid", .deviceId = L"device-id", .zoneIndex = 54321 } }; -json::JsonObject expected = json::JsonObject::Parse(L"{\"app-path\": \"appPath\", \"device-id\": \"device-id\", \"zoneset-uuid\": \"zoneset-uuid\", \"zone-index\": 54321}"); - -auto actual = AppZoneHistoryJSON::ToJson(appZoneHistory); -compareJsonObjects(expected, actual); -} - -TEST_METHOD(FromJson) -{ - AppZoneHistoryJSON expected{ L"appPath", AppZoneHistoryData{ .zoneSetUuid = L"zoneset-uuid", .deviceId = L"device-id", .zoneIndex = 54321 } }; - json::JsonObject json = json::JsonObject::Parse(L"{\"app-path\": \"appPath\", \"device-id\": \"device-id\", \"zoneset-uuid\": \"zoneset-uuid\", \"zone-index\": 54321}"); - - auto actual = AppZoneHistoryJSON::FromJson(json); - Assert::IsTrue(actual.has_value()); - - Assert::AreEqual(expected.appPath.c_str(), actual->appPath.c_str()); - Assert::AreEqual(expected.data.zoneIndex, actual->data.zoneIndex); - Assert::AreEqual(expected.data.deviceId.c_str(), actual->data.deviceId.c_str()); - Assert::AreEqual(expected.data.zoneSetUuid.c_str(), actual->data.zoneSetUuid.c_str()); -} - -TEST_METHOD(FromJsonMissingKeys) -{ - AppZoneHistoryJSON appZoneHistory{ L"appPath", AppZoneHistoryData{ .zoneSetUuid = L"zoneset-uuid", .deviceId = L"device-id", .zoneIndex = 54321 } }; - const auto json = AppZoneHistoryJSON::ToJson(appZoneHistory); - - auto iter = json.First(); - while (iter.HasCurrent()) - { - json::JsonObject modifiedJson = json::JsonObject::Parse(json.Stringify()); - modifiedJson.Remove(iter.Current().Key()); - - auto actual = AppZoneHistoryJSON::FromJson(modifiedJson); - Assert::IsFalse(actual.has_value()); - - iter.MoveNext(); - } -} -} -; - -TEST_CLASS(DeviceInfoUnitTests) -{ -private: - DeviceInfoJSON m_defaultDeviceInfo = DeviceInfoJSON{ L"default_device_id", DeviceInfoData{ ZoneSetData{ L"uuid", ZoneSetLayoutType::Custom }, true, 16, 3 } }; - json::JsonObject m_defaultJson = json::JsonObject::Parse(L"{\"device-id\": \"default_device_id\", \"active-zoneset\": {\"type\": \"custom\", \"uuid\": \"uuid\"}, \"editor-show-spacing\": true, \"editor-spacing\": 16, \"editor-zone-count\": 3}"); - -public: - TEST_METHOD(ToJson) - { - DeviceInfoJSON deviceInfo = m_defaultDeviceInfo; - json::JsonObject expected = m_defaultJson; - - auto actual = DeviceInfoJSON::ToJson(deviceInfo); - compareJsonObjects(expected, actual); - } - - TEST_METHOD(FromJson) - { - DeviceInfoJSON expected = m_defaultDeviceInfo; - expected.data.spacing = true; - - json::JsonObject json = DeviceInfoJSON::ToJson(expected); - auto actual = DeviceInfoJSON::FromJson(json); - Assert::IsTrue(actual.has_value()); - - Assert::AreEqual(expected.deviceId.c_str(), actual->deviceId.c_str(), L"device id"); - Assert::AreEqual(expected.data.zoneCount, actual->data.zoneCount, L"zone count"); - Assert::AreEqual((int)expected.data.activeZoneSet.type, (int)actual->data.activeZoneSet.type, L"zone set type"); - Assert::AreEqual(expected.data.activeZoneSet.uuid.c_str(), actual->data.activeZoneSet.uuid.c_str(), L"zone set uuid"); - } - - TEST_METHOD(FromJsonSpacingTrue) - { - DeviceInfoJSON expected = m_defaultDeviceInfo; - expected.data.spacing = true; - - json::JsonObject json = DeviceInfoJSON::ToJson(expected); - auto actual = DeviceInfoJSON::FromJson(json); - Assert::IsTrue(actual.has_value()); - - Assert::AreEqual(expected.data.spacing, actual->data.spacing); - } - - TEST_METHOD(FromJsonSpacingFalse) - { - DeviceInfoJSON expected = m_defaultDeviceInfo; - expected.data.activeZoneSet.type = ZoneSetLayoutType::Custom; - - json::JsonObject json = DeviceInfoJSON::ToJson(expected); - auto actual = DeviceInfoJSON::FromJson(json); - Assert::IsTrue(actual.has_value()); - - Assert::AreEqual(expected.data.spacing, actual->data.spacing); - } - - TEST_METHOD(FromJsonZoneGeneral) - { - DeviceInfoJSON expected = m_defaultDeviceInfo; - expected.data.activeZoneSet.type = ZoneSetLayoutType::PriorityGrid; - - json::JsonObject json = DeviceInfoJSON::ToJson(expected); - auto actual = DeviceInfoJSON::FromJson(json); - Assert::IsTrue(actual.has_value()); - - Assert::AreEqual((int)expected.data.activeZoneSet.type, (int)actual->data.activeZoneSet.type, L"zone set type"); - } - - TEST_METHOD(FromJsonMissingKeys) - { - DeviceInfoJSON deviceInfo{ L"default_device_id", DeviceInfoData{ ZoneSetData{ L"uuid", ZoneSetLayoutType::Custom }, true, 16, 3 } }; - const auto json = DeviceInfoJSON::ToJson(deviceInfo); - - auto iter = json.First(); - while (iter.HasCurrent()) + TEST_METHOD (FromJsonMissingKeys) { - json::JsonObject modifiedJson = json::JsonObject::Parse(json.Stringify()); - modifiedJson.Remove(iter.Current().Key()); + CustomZoneSetJSON zoneSet{ L"uuid", CustomZoneSetData{ L"name", CustomLayoutType::Canvas, CanvasLayoutInfo{ 2, 1 } } }; + const auto json = CustomZoneSetJSON::ToJson(zoneSet); - auto actual = DeviceInfoJSON::FromJson(modifiedJson); + auto iter = json.First(); + while (iter.HasCurrent()) + { + json::JsonObject modifiedJson = json::JsonObject::Parse(json.Stringify()); + modifiedJson.Remove(iter.Current().Key()); + + auto actual = CustomZoneSetJSON::FromJson(modifiedJson); + Assert::IsFalse(actual.has_value()); + + iter.MoveNext(); + } + } + + TEST_METHOD (FromJsonInvalidTypes) + { + json::JsonObject json = json::JsonObject::Parse(L"{\"uuid\": null, \"name\": \"имя\", \"type\": true}"); + Assert::IsFalse(CustomZoneSetJSON::FromJson(json).has_value()); + + json = json::JsonObject::Parse(L"{\"uuid\": \"uuid\", \"name\": \"name\", \"type\": \"unknown type\"}"); + Assert::IsFalse(CustomZoneSetJSON::FromJson(json).has_value()); + } + }; + + TEST_CLASS (ZoneSetDataUnitTest) + { + TEST_METHOD (ToJsonGeneral) + { + json::JsonObject expected = json::JsonObject::Parse(L"{\"uuid\": \"{33A2B101-06E0-437B-A61E-CDBECF502906}\", \"type\": \"rows\"}"); + ZoneSetData data{ L"{33A2B101-06E0-437B-A61E-CDBECF502906}", ZoneSetLayoutType::Rows }; + const auto actual = ZoneSetData::ToJson(data); + compareJsonObjects(expected, actual); + } + + TEST_METHOD (FromJsonGeneral) + { + ZoneSetData expected{ L"{33A2B101-06E0-437B-A61E-CDBECF502906}", ZoneSetLayoutType::Columns }; + + json::JsonObject json = json::JsonObject::Parse(L"{\"uuid\": \"{33A2B101-06E0-437B-A61E-CDBECF502906}\", \"type\": \"columns\"}"); + auto actual = ZoneSetData::FromJson(json); + Assert::IsTrue(actual.has_value()); + + Assert::AreEqual(expected.uuid.c_str(), actual->uuid.c_str()); + Assert::AreEqual((int)expected.type, (int)actual->type); + } + + TEST_METHOD (FromJsonTypeInvalid) + { + ZoneSetData expected{ L"{33A2B101-06E0-437B-A61E-CDBECF502906}", ZoneSetLayoutType::Blank }; + + json::JsonObject json = json::JsonObject::Parse(L"{\"uuid\": \"{33A2B101-06E0-437B-A61E-CDBECF502906}\", \"type\": \"invalid_type\"}"); + auto actual = ZoneSetData::FromJson(json); + Assert::IsTrue(actual.has_value()); + + Assert::AreEqual(expected.uuid.c_str(), actual->uuid.c_str()); + Assert::AreEqual((int)expected.type, (int)actual->type); + } + + TEST_METHOD (FromJsonUuidInvalid) + { + json::JsonObject json = json::JsonObject::Parse(L"{\"uuid\": \"uuid\", \"type\": \"invalid_type\"}"); + auto actual = ZoneSetData::FromJson(json); Assert::IsFalse(actual.has_value()); - - iter.MoveNext(); - } - } -}; - -TEST_CLASS(FancyZonesDataUnitTests) -{ -private: - const std::wstring m_defaultCustomDeviceStr = L"{\"device-id\": \"default_device_id\", \"active-zoneset\": {\"type\": \"custom\", \"uuid\": \"uuid\"}, \"editor-show-spacing\": true, \"editor-spacing\": 16, \"editor-zone-count\": 3}"; - const json::JsonValue m_defaultCustomDeviceValue = json::JsonValue::Parse(m_defaultCustomDeviceStr); - const json::JsonObject m_defaultCustomDeviceObj = json::JsonObject::Parse(m_defaultCustomDeviceStr); - - HINSTANCE m_hInst{}; - FancyZonesData& m_fzData = FancyZonesDataInstance(); - - void compareJsonArrays(const json::JsonArray& expected, const json::JsonArray& actual) - { - Assert::AreEqual(expected.Size(), actual.Size()); - for (uint32_t i = 0; i < expected.Size(); i++) - { - compareJsonObjects(expected.GetObjectAt(i), actual.GetObjectAt(i)); - } - } - - TEST_METHOD_INITIALIZE(Init) - { - m_hInst = (HINSTANCE)GetModuleHandleW(nullptr); - m_fzData.clear_data(); - } - -public: - TEST_METHOD(FancyZonesDataPath) - { - FancyZonesData data; - Assert::IsFalse(data.GetPersistFancyZonesJSONPath().empty()); - } - - TEST_METHOD(FancyZonesDataJsonEmpty) - { - FancyZonesData data; - const auto jsonPath = data.GetPersistFancyZonesJSONPath(); - auto savedJson = json::from_file(jsonPath); - - if (std::filesystem::exists(jsonPath)) - { - std::filesystem::remove(jsonPath); } - json::JsonObject expected; - auto actual = data.GetPersistFancyZonesJSON(); - - Assert::AreEqual(expected.Stringify().c_str(), actual.Stringify().c_str()); - - if (savedJson) + TEST_METHOD (FromJsonMissingKeys) { - json::to_file(jsonPath, *savedJson); - } - } + ZoneSetData data{ L"{33A2B101-06E0-437B-A61E-CDBECF502906}", ZoneSetLayoutType::Columns }; + const auto json = ZoneSetData::ToJson(data); - TEST_METHOD(FancyZonesDataJson) - { - FancyZonesData data; - const auto jsonPath = data.GetPersistFancyZonesJSONPath(); - auto savedJson = json::from_file(jsonPath); - - if (std::filesystem::exists(jsonPath)) - { - std::filesystem::remove(jsonPath); - } - - json::JsonObject expected = json::JsonObject::Parse(L"{\"fancy-zones\":{\"custom-zonesets \":[{\"uuid\":\"uuid1\",\"name\":\"Custom1\",\"type\":\"custom\" }] } }"); - json::to_file(jsonPath, expected); - - auto actual = data.GetPersistFancyZonesJSON(); - Assert::AreEqual(expected.Stringify().c_str(), actual.Stringify().c_str()); - - if (savedJson) - { - json::to_file(jsonPath, *savedJson); - } - else - { - std::filesystem::remove(jsonPath); - } - } - - TEST_METHOD(FancyZonesDataDeviceInfoMap) - { - FancyZonesData data; - const auto actual = data.GetDeviceInfoMap(); - Assert::IsTrue(actual.empty()); - } - - TEST_METHOD(FancyZonesDataDeviceInfoMapParseEmpty) - { - FancyZonesData data; - - json::JsonObject json; - data.ParseDeviceInfos(json); - - const auto actual = data.GetDeviceInfoMap(); - Assert::IsTrue(actual.empty()); - } - - TEST_METHOD(FancyZonesDataDeviceInfoMapParseValidEmpty) - { - FancyZonesData data; - - json::JsonObject expected; - json::JsonArray zoneSets; - expected.SetNamedValue(L"devices", zoneSets); - - data.ParseDeviceInfos(expected); - - const auto actual = data.GetDeviceInfoMap(); - Assert::IsTrue(actual.empty()); - } - - TEST_METHOD(FancyZonesDataDeviceInfoMapParseInvalid) - { - json::JsonArray devices; - devices.Append(json::JsonObject::Parse(m_defaultCustomDeviceStr)); - devices.Append(json::JsonObject::Parse(L"{\"device-id\": \"device_id\"}")); - - json::JsonObject expected; - expected.SetNamedValue(L"devices", devices); - - FancyZonesData data; - auto actual = data.ParseDeviceInfos(expected); - - Assert::IsFalse(actual); - } - - TEST_METHOD(FancyZonesDataDeviceInfoMapParseSingle) - { - json::JsonArray devices; - devices.Append(m_defaultCustomDeviceValue); - json::JsonObject expected; - expected.SetNamedValue(L"devices", devices); - - FancyZonesData data; - data.ParseDeviceInfos(expected); - - const auto actualMap = data.GetDeviceInfoMap(); - Assert::AreEqual((size_t)1, actualMap.size()); - } - - TEST_METHOD(FancyZonesDataDeviceInfoMapParseMany) - { - json::JsonArray devices; - for (int i = 0; i < 10; i++) - { - json::JsonObject obj = json::JsonObject::Parse(m_defaultCustomDeviceStr); - obj.SetNamedValue(L"device-id", json::JsonValue::CreateStringValue(std::to_wstring(i))); - - Logger::WriteMessage(obj.Stringify().c_str()); - Logger::WriteMessage("\n"); - - devices.Append(obj); - } - - json::JsonObject expected; - expected.SetNamedValue(L"devices", devices); - Logger::WriteMessage(expected.Stringify().c_str()); - Logger::WriteMessage("\n"); - - FancyZonesData data; - data.ParseDeviceInfos(expected); - - const auto actualMap = data.GetDeviceInfoMap(); - Assert::AreEqual((size_t)10, actualMap.size()); - } - - TEST_METHOD(FancyZonesDataSerialize) - { - json::JsonArray expectedDevices; - expectedDevices.Append(m_defaultCustomDeviceObj); - json::JsonObject expected; - expected.SetNamedValue(L"devices", expectedDevices); - - FancyZonesData data; - data.ParseDeviceInfos(expected); - - auto actual = data.SerializeDeviceInfos(); - compareJsonArrays(expectedDevices, actual); - } - - TEST_METHOD(DeviceInfoSaveTemp) - { - FancyZonesData data; - DeviceInfoJSON deviceInfo{ L"default_device_id", DeviceInfoData{ ZoneSetData{ L"uuid", ZoneSetLayoutType::Custom }, true, 16, 3 } }; - - const std::wstring path = data.GetPersistFancyZonesJSONPath() + L".test_tmp"; - data.SerializeDeviceInfoToTmpFile(deviceInfo, path); - - bool actualFileExists = std::filesystem::exists(path); - Assert::IsTrue(actualFileExists); - - auto expectedData = DeviceInfoJSON::ToJson(deviceInfo); - auto actualSavedData = json::from_file(path); - std::filesystem::remove(path); //clean up before compare asserts - - Assert::IsTrue(actualSavedData.has_value()); - compareJsonObjects(expectedData, *actualSavedData); - } - - TEST_METHOD(DeviceInfoReadTemp) - { - FancyZonesData data; - const std::wstring zoneUuid = L"default_device_id"; - DeviceInfoJSON expected{ zoneUuid, DeviceInfoData{ ZoneSetData{ L"uuid", ZoneSetLayoutType::Custom }, true, 16, 3 } }; - const std::wstring path = data.GetPersistFancyZonesJSONPath() + L".test_tmp"; - data.SerializeDeviceInfoToTmpFile(expected, path); - - data.ParseDeviceInfoFromTmpFile(path); - - bool actualFileExists = std::filesystem::exists(path); - if (actualFileExists) - { - std::filesystem::remove(path); //clean up before compare asserts - } - Assert::IsFalse(actualFileExists); - - auto devices = data.GetDeviceInfoMap(); - Assert::AreEqual((size_t)1, devices.size()); - - auto actual = devices.find(zoneUuid)->second; - Assert::AreEqual(expected.data.showSpacing, actual.showSpacing); - Assert::AreEqual(expected.data.spacing, actual.spacing); - Assert::AreEqual(expected.data.zoneCount, actual.zoneCount); - Assert::AreEqual((int)expected.data.activeZoneSet.type, (int)actual.activeZoneSet.type); - Assert::AreEqual(expected.data.activeZoneSet.uuid.c_str(), actual.activeZoneSet.uuid.c_str()); - } - - TEST_METHOD(DeviceInfoReadTempUnexsisted) - { - FancyZonesData data; - const std::wstring path = data.GetPersistFancyZonesJSONPath() + L".test_tmp"; - data.ParseDeviceInfoFromTmpFile(path); - - auto devices = data.GetDeviceInfoMap(); - Assert::AreEqual((size_t)0, devices.size()); - } - - TEST_METHOD(AppZoneHistoryParseSingle) - { - const std::wstring expectedAppPath = L"appPath"; - const std::wstring expectedDeviceId = L"device-id"; - const std::wstring expectedZoneSetId = L"zone-set-id"; - const int expectedIndex = 54321; - - json::JsonObject json; - AppZoneHistoryJSON expected{ expectedAppPath, AppZoneHistoryData{ .zoneSetUuid = expectedZoneSetId, .deviceId = expectedDeviceId, .zoneIndex = expectedIndex } }; - json::JsonArray zoneHistoryArray; - zoneHistoryArray.Append(AppZoneHistoryJSON::ToJson(expected)); - json.SetNamedValue(L"app-zone-history", json::JsonValue::Parse(zoneHistoryArray.Stringify())); - - FancyZonesData data; - data.ParseAppZoneHistory(json); - - const auto actualProcessHistoryMap = data.GetAppZoneHistoryMap(); - Assert::AreEqual((size_t)zoneHistoryArray.Size(), actualProcessHistoryMap.size()); - - const auto actualProcessHistory = actualProcessHistoryMap.begin(); - Assert::AreEqual(expectedAppPath.c_str(), actualProcessHistory->first.c_str()); - - const auto actualAppZoneHistory = actualProcessHistory->second; - Assert::AreEqual(expectedZoneSetId.c_str(), actualAppZoneHistory.zoneSetUuid.c_str()); - Assert::AreEqual(expectedDeviceId.c_str(), actualAppZoneHistory.deviceId.c_str()); - Assert::AreEqual(expectedIndex, actualAppZoneHistory.zoneIndex); - } - - TEST_METHOD(AppZoneHistoryParseManyApps) - { - json::JsonObject json; - json::JsonArray zoneHistoryArray; - zoneHistoryArray.Append(AppZoneHistoryJSON::ToJson(AppZoneHistoryJSON{ L"app-path-1", AppZoneHistoryData{ .zoneSetUuid = L"zoneset-uuid-1", .deviceId = L"device-id-1", .zoneIndex = 1 } })); - zoneHistoryArray.Append(AppZoneHistoryJSON::ToJson(AppZoneHistoryJSON{ L"app-path-2", AppZoneHistoryData{ .zoneSetUuid = L"zoneset-uuid-2", .deviceId = L"device-id-2", .zoneIndex = 2 } })); - zoneHistoryArray.Append(AppZoneHistoryJSON::ToJson(AppZoneHistoryJSON{ L"app-path-3", AppZoneHistoryData{ .zoneSetUuid = L"zoneset-uuid-3", .deviceId = L"device-id-3", .zoneIndex = 3 } })); - zoneHistoryArray.Append(AppZoneHistoryJSON::ToJson(AppZoneHistoryJSON{ L"app-path-4", AppZoneHistoryData{ .zoneSetUuid = L"zoneset-uuid-4", .deviceId = L"device-id-4", .zoneIndex = 4 } })); - - json.SetNamedValue(L"app-zone-history", json::JsonValue::Parse(zoneHistoryArray.Stringify())); - - FancyZonesData data; - data.ParseAppZoneHistory(json); - - auto actualMap = data.GetAppZoneHistoryMap(); - Assert::AreEqual((size_t)zoneHistoryArray.Size(), actualMap.size()); - - const auto actualProcessHistoryMap = data.GetAppZoneHistoryMap(); - Assert::AreEqual((size_t)zoneHistoryArray.Size(), actualProcessHistoryMap.size()); - - auto iter = zoneHistoryArray.First(); - while (iter.HasCurrent()) - { - auto expected = AppZoneHistoryJSON::FromJson(json::JsonObject::Parse(iter.Current().Stringify())); - - const auto actual = actualProcessHistoryMap.at(expected->appPath); - Assert::AreEqual(expected->data.deviceId.c_str(), actual.deviceId.c_str()); - Assert::AreEqual(expected->data.zoneSetUuid.c_str(), actual.zoneSetUuid.c_str()); - Assert::AreEqual(expected->data.zoneIndex, actual.zoneIndex); - - iter.MoveNext(); - } - } - - TEST_METHOD(AppZoneHistoryParseManyZonesForSingleApp) - { - json::JsonObject json; - json::JsonArray zoneHistoryArray; - - const auto appPath = L"app-path"; - zoneHistoryArray.Append(AppZoneHistoryJSON::ToJson(AppZoneHistoryJSON{ appPath, AppZoneHistoryData{ .zoneSetUuid = L"zoneset-uuid-1", .deviceId = L"device-id-1", .zoneIndex = 1 } })); - zoneHistoryArray.Append(AppZoneHistoryJSON::ToJson(AppZoneHistoryJSON{ appPath, AppZoneHistoryData{ .zoneSetUuid = L"zoneset-uuid-2", .deviceId = L"device-id-2", .zoneIndex = 2 } })); - zoneHistoryArray.Append(AppZoneHistoryJSON::ToJson(AppZoneHistoryJSON{ appPath, AppZoneHistoryData{ .zoneSetUuid = L"zoneset-uuid-3", .deviceId = L"device-id-3", .zoneIndex = 3 } })); - const auto expected = AppZoneHistoryData{ .zoneSetUuid = L"zoneset-uuid-4", .deviceId = L"device-id-4", .zoneIndex = 4 }; - zoneHistoryArray.Append(AppZoneHistoryJSON::ToJson(AppZoneHistoryJSON{ appPath, expected })); - json.SetNamedValue(L"app-zone-history", json::JsonValue::Parse(zoneHistoryArray.Stringify())); - - FancyZonesData data; - data.ParseAppZoneHistory(json); - - const auto actualProcessHistoryMap = data.GetAppZoneHistoryMap(); - Assert::AreEqual((size_t)1, actualProcessHistoryMap.size()); - - const auto actual = actualProcessHistoryMap.at(appPath); - Assert::AreEqual(expected.deviceId.c_str(), actual.deviceId.c_str()); - Assert::AreEqual(expected.zoneSetUuid.c_str(), actual.zoneSetUuid.c_str()); - Assert::AreEqual(expected.zoneIndex, actual.zoneIndex); - } - - TEST_METHOD(AppZoneHistoryParseEmpty) - { - FancyZonesData data; - data.ParseAppZoneHistory(json::JsonObject()); - - auto actual = data.GetAppZoneHistoryMap(); - Assert::IsTrue(actual.empty()); - } - - TEST_METHOD(AppZoneHistoryParseInvalid) - { - const std::wstring appPath = L"appPath"; - json::JsonObject json; - AppZoneHistoryJSON expected{ appPath, AppZoneHistoryData{ .zoneSetUuid = L"zoneset-uuid", .deviceId = L"device-id", .zoneIndex = 54321 } }; - json.SetNamedValue(L"app-zone-history", json::JsonValue::Parse(AppZoneHistoryJSON::ToJson(expected).Stringify())); - - FancyZonesData data; - bool actual = data.ParseAppZoneHistory(json); - - Assert::IsFalse(actual); - } - - TEST_METHOD(AppZoneHistorySerializeSingle) - { - const std::wstring appPath = L"appPath"; - json::JsonArray expected; - expected.Append(AppZoneHistoryJSON::ToJson(AppZoneHistoryJSON{ appPath, AppZoneHistoryData{ .zoneSetUuid = L"zoneset-uuid", .deviceId = L"device-id", .zoneIndex = 54321 } })); - json::JsonObject json; - json.SetNamedValue(L"app-zone-history", json::JsonValue::Parse(expected.Stringify())); - - FancyZonesData data; - data.ParseAppZoneHistory(json); - - auto actual = data.SerializeAppZoneHistory(); - compareJsonArrays(expected, actual); - } - - TEST_METHOD(AppZoneHistorySerializeMany) - { - json::JsonObject json; - json::JsonArray expected; - expected.Append(AppZoneHistoryJSON::ToJson(AppZoneHistoryJSON{ L"app-path-1", AppZoneHistoryData{ .zoneSetUuid = L"zoneset-uuid", .deviceId = L"device-id", .zoneIndex = 54321 } })); - expected.Append(AppZoneHistoryJSON::ToJson(AppZoneHistoryJSON{ L"app-path-2", AppZoneHistoryData{ .zoneSetUuid = L"zoneset-uuid", .deviceId = L"device-id", .zoneIndex = 54321 } })); - expected.Append(AppZoneHistoryJSON::ToJson(AppZoneHistoryJSON{ L"app-path-3", AppZoneHistoryData{ .zoneSetUuid = L"zoneset-uuid", .deviceId = L"device-id", .zoneIndex = 54321 } })); - expected.Append(AppZoneHistoryJSON::ToJson(AppZoneHistoryJSON{ L"app-path-4", AppZoneHistoryData{ .zoneSetUuid = L"zoneset-uuid", .deviceId = L"device-id", .zoneIndex = 54321 } })); - json.SetNamedValue(L"app-zone-history", json::JsonValue::Parse(expected.Stringify())); - - FancyZonesData data; - data.ParseAppZoneHistory(json); - - auto actual = data.SerializeAppZoneHistory(); - compareJsonArrays(expected, actual); - } - - TEST_METHOD(AppZoneHistorySerializeEmpty) - { - json::JsonArray expected; - json::JsonObject json; - json.SetNamedValue(L"app-zone-history", json::JsonValue::Parse(expected.Stringify())); - - FancyZonesData data; - data.ParseAppZoneHistory(json); - - auto actual = data.SerializeAppZoneHistory(); - compareJsonArrays(expected, actual); - } - - TEST_METHOD(CustomZoneSetsParseSingle) - { - const std::wstring zoneUuid = L"uuid"; - GridLayoutInfo grid(GridLayoutInfo(JSONHelpers::GridLayoutInfo::Full{ - .rows = 1, - .columns = 3, - .rowsPercents = { 10000 }, - .columnsPercents = { 2500, 5000, 2500 }, - .cellChildMap = { { 0, 1, 2 } } })); - - json::JsonObject json; - CustomZoneSetJSON expected{ zoneUuid, CustomZoneSetData{ L"name", CustomLayoutType::Grid, grid } }; - json::JsonArray array; - array.Append(CustomZoneSetJSON::ToJson(expected)); - json.SetNamedValue(L"custom-zone-sets", json::JsonValue::Parse(array.Stringify())); - - FancyZonesData data; - data.ParseCustomZoneSets(json); - - auto actualMap = data.GetCustomZoneSetsMap(); - Assert::AreEqual((size_t)array.Size(), actualMap.size()); - - auto actual = actualMap.find(zoneUuid)->second; - Assert::AreEqual(expected.data.name.c_str(), actual.name.c_str()); - Assert::AreEqual((int)expected.data.type, (int)actual.type); - - auto expectedGrid = std::get(expected.data.info); - auto actualGrid = std::get(actual.info); - Assert::AreEqual(expectedGrid.rows(), actualGrid.rows()); - Assert::AreEqual(expectedGrid.columns(), actualGrid.columns()); - } - - TEST_METHOD(CustomZoneSetsParseMany) - { - json::JsonObject json; - json::JsonArray array; - const GridLayoutInfo grid(GridLayoutInfo(JSONHelpers::GridLayoutInfo::Full{ - .rows = 1, - .columns = 3, - .rowsPercents = { 10000 }, - .columnsPercents = { 2500, 5000, 2500 }, - .cellChildMap = { { 0, 1, 2 } } })); - array.Append(CustomZoneSetJSON::ToJson(CustomZoneSetJSON{ L"zone-uuid-1", CustomZoneSetData{ L"name", CustomLayoutType::Grid, grid } })); - array.Append(CustomZoneSetJSON::ToJson(CustomZoneSetJSON{ L"zone-uuid-2", CustomZoneSetData{ L"name", CustomLayoutType::Canvas, CanvasLayoutInfo{ 1, 2 } } })); - array.Append(CustomZoneSetJSON::ToJson(CustomZoneSetJSON{ L"zone-uuid-3", CustomZoneSetData{ L"name", CustomLayoutType::Grid, grid } })); - array.Append(CustomZoneSetJSON::ToJson(CustomZoneSetJSON{ L"zone-uuid-4", CustomZoneSetData{ L"name", CustomLayoutType::Canvas, CanvasLayoutInfo{ 1, 2 } } })); - json.SetNamedValue(L"custom-zone-sets", json::JsonValue::Parse(array.Stringify())); - - FancyZonesData data; - data.ParseCustomZoneSets(json); - - auto actualMap = data.GetCustomZoneSetsMap(); - Assert::AreEqual((size_t)array.Size(), actualMap.size()); - - auto iter = array.First(); - while (iter.HasCurrent()) - { - auto expected = CustomZoneSetJSON::FromJson(json::JsonObject::Parse(iter.Current().Stringify())); - auto actual = actualMap.find(expected->uuid)->second; - Assert::AreEqual(expected->data.name.c_str(), actual.name.c_str(), L"name"); - Assert::AreEqual((int)expected->data.type, (int)actual.type, L"type"); - - if (expected->data.type == CustomLayoutType::Grid) + auto iter = json.First(); + while (iter.HasCurrent()) { - auto expectedInfo = std::get(expected->data.info); - auto actualInfo = std::get(actual.info); - Assert::AreEqual(expectedInfo.rows(), actualInfo.rows(), L"grid rows"); - Assert::AreEqual(expectedInfo.columns(), actualInfo.columns(), L"grid columns"); + json::JsonObject modifiedJson = json::JsonObject::Parse(json.Stringify()); + modifiedJson.Remove(iter.Current().Key()); + + auto actual = ZoneSetData::FromJson(modifiedJson); + Assert::IsFalse(actual.has_value()); + + iter.MoveNext(); } - else + } + }; + + TEST_CLASS (AppZoneHistoryUnitTests) + { + TEST_METHOD (ToJson) + { + AppZoneHistoryJSON appZoneHistory{ L"appPath", AppZoneHistoryData{ .zoneSetUuid = L"zoneset-uuid", .deviceId = L"device-id", .zoneIndex = 54321 } }; + json::JsonObject expected = json::JsonObject::Parse(L"{\"app-path\": \"appPath\", \"device-id\": \"device-id\", \"zoneset-uuid\": \"zoneset-uuid\", \"zone-index\": 54321}"); + + auto actual = AppZoneHistoryJSON::ToJson(appZoneHistory); + compareJsonObjects(expected, actual); + } + + TEST_METHOD (FromJson) + { + AppZoneHistoryJSON expected{ L"appPath", AppZoneHistoryData{ .zoneSetUuid = L"{33A2B101-06E0-437B-A61E-CDBECF502906}", .deviceId = L"AOC2460#4&fe3a015&0&UID65793_1920_1200_{39B25DD2-130D-4B5D-8851-4791D66B1539}", .zoneIndex = 54321 } }; + json::JsonObject json = json::JsonObject::Parse(L"{\"app-path\": \"appPath\", \"device-id\": \"AOC2460#4&fe3a015&0&UID65793_1920_1200_{39B25DD2-130D-4B5D-8851-4791D66B1539}\", \"zoneset-uuid\": \"{33A2B101-06E0-437B-A61E-CDBECF502906}\", \"zone-index\": 54321}"); + + auto actual = AppZoneHistoryJSON::FromJson(json); + Assert::IsTrue(actual.has_value()); + + Assert::AreEqual(expected.appPath.c_str(), actual->appPath.c_str()); + Assert::AreEqual(expected.data.zoneIndex, actual->data.zoneIndex); + Assert::AreEqual(expected.data.deviceId.c_str(), actual->data.deviceId.c_str()); + Assert::AreEqual(expected.data.zoneSetUuid.c_str(), actual->data.zoneSetUuid.c_str()); + } + + TEST_METHOD (FromJsonInvalidUuid) + { + json::JsonObject json = json::JsonObject::Parse(L"{\"app-path\": \"appPath\", \"device-id\": \"AOC2460#4&fe3a015&0&UID65793_1920_1200_{39B25DD2-130D-4B5D-8851-4791D66B1539}\", \"zoneset-uuid\": \"zoneset-uuid\", \"zone-index\": 54321}"); + auto actual = AppZoneHistoryJSON::FromJson(json); + Assert::IsFalse(actual.has_value()); + } + + TEST_METHOD (FromJsonInvalidDeviceId) + { + json::JsonObject json = json::JsonObject::Parse(L"{\"app-path\": \"appPath\", \"device-id\": \"device-id\", \"zoneset-uuid\": \"{33A2B101-06E0-437B-A61E-CDBECF502906}\", \"zone-index\": 54321}"); + auto actual = AppZoneHistoryJSON::FromJson(json); + Assert::IsFalse(actual.has_value()); + } + + TEST_METHOD (FromJsonMissingKeys) + { + AppZoneHistoryJSON appZoneHistory{ L"appPath", AppZoneHistoryData{ .zoneSetUuid = L"zoneset-uuid", .deviceId = L"AOC2460#4&fe3a015&0&UID65793_1920_1200_{39B25DD2-130D-4B5D-8851-4791D66B1539}", .zoneIndex = 54321 } }; + const auto json = AppZoneHistoryJSON::ToJson(appZoneHistory); + + auto iter = json.First(); + while (iter.HasCurrent()) { - auto expectedInfo = std::get(expected->data.info); - auto actualInfo = std::get(actual.info); - Assert::AreEqual(expectedInfo.referenceWidth, actualInfo.referenceWidth, L"canvas width"); - Assert::AreEqual(expectedInfo.referenceHeight, actualInfo.referenceHeight, L"canvas height"); + json::JsonObject modifiedJson = json::JsonObject::Parse(json.Stringify()); + modifiedJson.Remove(iter.Current().Key()); + + auto actual = AppZoneHistoryJSON::FromJson(modifiedJson); + Assert::IsFalse(actual.has_value()); + + iter.MoveNext(); + } + } + + TEST_METHOD (FromJsonInvalidTypes) + { + json::JsonObject json = json::JsonObject::Parse(L"{\"app-path\": false, \"device-id\": [], \"zoneset-uuid\": {}, \"zone-index\": \"54321\"}"); + Assert::IsFalse(AppZoneHistoryJSON::FromJson(json).has_value()); + } + }; + + TEST_CLASS (DeviceInfoUnitTests) + { + private: + const std::wstring m_defaultDeviceId = L"AOC2460#4&fe3a015&0&UID65793_1920_1200_{39B25DD2-130D-4B5D-8851-4791D66B1539}"; + DeviceInfoJSON m_defaultDeviceInfo = DeviceInfoJSON{ m_defaultDeviceId, DeviceInfoData{ ZoneSetData{ L"{33A2B101-06E0-437B-A61E-CDBECF502906}", ZoneSetLayoutType::Custom }, true, 16, 3 } }; + json::JsonObject m_defaultJson = json::JsonObject::Parse(L"{\"device-id\": \"AOC2460#4&fe3a015&0&UID65793_1920_1200_{39B25DD2-130D-4B5D-8851-4791D66B1539}\", \"active-zoneset\": {\"type\": \"custom\", \"uuid\": \"{33A2B101-06E0-437B-A61E-CDBECF502906}\"}, \"editor-show-spacing\": true, \"editor-spacing\": 16, \"editor-zone-count\": 3}"); + + public: + TEST_METHOD (ToJson) + { + DeviceInfoJSON deviceInfo = m_defaultDeviceInfo; + json::JsonObject expected = m_defaultJson; + + auto actual = DeviceInfoJSON::ToJson(deviceInfo); + compareJsonObjects(expected, actual); + } + + TEST_METHOD (FromJson) + { + DeviceInfoJSON expected = m_defaultDeviceInfo; + expected.data.spacing = true; + + json::JsonObject json = DeviceInfoJSON::ToJson(expected); + auto actual = DeviceInfoJSON::FromJson(json); + Assert::IsTrue(actual.has_value()); + + Assert::AreEqual(expected.deviceId.c_str(), actual->deviceId.c_str(), L"device id"); + Assert::AreEqual(expected.data.zoneCount, actual->data.zoneCount, L"zone count"); + Assert::AreEqual((int)expected.data.activeZoneSet.type, (int)actual->data.activeZoneSet.type, L"zone set type"); + Assert::AreEqual(expected.data.activeZoneSet.uuid.c_str(), actual->data.activeZoneSet.uuid.c_str(), L"zone set uuid"); + } + + TEST_METHOD (FromJsonSpacingTrue) + { + DeviceInfoJSON expected = m_defaultDeviceInfo; + expected.data.spacing = true; + + json::JsonObject json = DeviceInfoJSON::ToJson(expected); + auto actual = DeviceInfoJSON::FromJson(json); + Assert::IsTrue(actual.has_value()); + + Assert::AreEqual(expected.data.spacing, actual->data.spacing); + } + + TEST_METHOD (FromJsonSpacingFalse) + { + DeviceInfoJSON expected = m_defaultDeviceInfo; + expected.data.activeZoneSet.type = ZoneSetLayoutType::Custom; + + json::JsonObject json = DeviceInfoJSON::ToJson(expected); + auto actual = DeviceInfoJSON::FromJson(json); + Assert::IsTrue(actual.has_value()); + + Assert::AreEqual(expected.data.spacing, actual->data.spacing); + } + + TEST_METHOD (FromJsonZoneGeneral) + { + DeviceInfoJSON expected = m_defaultDeviceInfo; + expected.data.activeZoneSet.type = ZoneSetLayoutType::PriorityGrid; + + json::JsonObject json = DeviceInfoJSON::ToJson(expected); + auto actual = DeviceInfoJSON::FromJson(json); + Assert::IsTrue(actual.has_value()); + + Assert::AreEqual((int)expected.data.activeZoneSet.type, (int)actual->data.activeZoneSet.type, L"zone set type"); + } + + TEST_METHOD (FromJsonMissingKeys) + { + DeviceInfoJSON deviceInfo{ m_defaultDeviceId, DeviceInfoData{ ZoneSetData{ L"{33A2B101-06E0-437B-A61E-CDBECF502906}", ZoneSetLayoutType::Custom }, true, 16, 3 } }; + const auto json = DeviceInfoJSON::ToJson(deviceInfo); + + auto iter = json.First(); + while (iter.HasCurrent()) + { + json::JsonObject modifiedJson = json::JsonObject::Parse(json.Stringify()); + modifiedJson.Remove(iter.Current().Key()); + + auto actual = DeviceInfoJSON::FromJson(modifiedJson); + Assert::IsFalse(actual.has_value()); + + iter.MoveNext(); + } + } + + TEST_METHOD (FromJsonInvalidTypes) + { + json::JsonObject json = json::JsonObject::Parse(L"{\"device-id\": true, \"active-zoneset\": {\"type\": null, \"uuid\": \"{33A2B101-06E0-437B-A61E-CDBECF502906}\"}, \"editor-show-spacing\": true, \"editor-spacing\": 16, \"editor-zone-count\": 3}"); + Assert::IsFalse(DeviceInfoJSON::FromJson(json).has_value()); + } + + TEST_METHOD (FromJsonInvalidUuid) + { + json::JsonObject json = json::JsonObject::Parse(L"{\"device-id\": \"AOC2460#4&fe3a015&0&UID65793_1920_1200_{39B25DD2-130D-4B5D-8851-4791D66B1539}\", \"active-zoneset\": {\"type\": \"custom\", \"uuid\": \"uuid\"}, \"editor-show-spacing\": true, \"editor-spacing\": 16, \"editor-zone-count\": 3}"); + Assert::IsFalse(DeviceInfoJSON::FromJson(json).has_value()); + } + + TEST_METHOD (FromJsonInvalidDeviceId) + { + json::JsonObject json = json::JsonObject::Parse(L"{\"device-id\": true, \"active-zoneset\": {\"type\": \"custom\", \"uuid\": \"{33A2B101-06E0-437B-A61E-CDBECF502906}\"}, \"editor-show-spacing\": true, \"editor-spacing\": 16, \"editor-zone-count\": 3}"); + Assert::IsFalse(DeviceInfoJSON::FromJson(json).has_value()); + } + }; + + TEST_CLASS (FancyZonesDataUnitTests) + { + private: + const std::wstring m_defaultDeviceId = L"AOC2460#4&fe3a015&0&UID65793_1920_1200_{39B25DD2-130D-4B5D-8851-4791D66B1539}"; + const std::wstring m_defaultCustomDeviceStr = L"{\"device-id\": \"AOC2460#4&fe3a015&0&UID65793_1920_1200_{39B25DD2-130D-4B5D-8851-4791D66B1539}\", \"active-zoneset\": {\"type\": \"custom\", \"uuid\": \"{33A2B101-06E0-437B-A61E-CDBECF502906}\"}, \"editor-show-spacing\": true, \"editor-spacing\": 16, \"editor-zone-count\": 3}"; + const json::JsonValue m_defaultCustomDeviceValue = json::JsonValue::Parse(m_defaultCustomDeviceStr); + const json::JsonObject m_defaultCustomDeviceObj = json::JsonObject::Parse(m_defaultCustomDeviceStr); + + HINSTANCE m_hInst{}; + FancyZonesData& m_fzData = FancyZonesDataInstance(); + + void compareJsonArrays(const json::JsonArray& expected, const json::JsonArray& actual) + { + Assert::AreEqual(expected.Size(), actual.Size()); + for (uint32_t i = 0; i < expected.Size(); i++) + { + compareJsonObjects(expected.GetObjectAt(i), actual.GetObjectAt(i)); + } + } + + TEST_METHOD_INITIALIZE(Init) + { + m_hInst = (HINSTANCE)GetModuleHandleW(nullptr); + m_fzData.clear_data(); } - iter.MoveNext(); - } - } - - TEST_METHOD(CustomZoneSetsParseEmpty) - { - FancyZonesData data; - data.ParseCustomZoneSets(json::JsonObject()); - - auto actual = data.GetCustomZoneSetsMap(); - Assert::IsTrue(actual.empty()); - } - - TEST_METHOD(CustomZoneSetsParseInvalid) - { - json::JsonObject json; - CustomZoneSetJSON expected{ L"uuid", CustomZoneSetData{ L"name", CustomLayoutType::Grid, GridLayoutInfo(GridLayoutInfo::Minimal{ 1, 2 }) } }; - json.SetNamedValue(L"custom-zone-sets", json::JsonValue::Parse(CustomZoneSetJSON::ToJson(expected).Stringify())); - - FancyZonesData data; - auto actual = data.ParseCustomZoneSets(json); - - Assert::IsFalse(actual); - } - - TEST_METHOD(CustomZoneSetsSerializeSingle) - { - json::JsonArray expected; - const GridLayoutInfo grid(GridLayoutInfo(JSONHelpers::GridLayoutInfo::Full{ - .rows = 1, - .columns = 3, - .rowsPercents = { 10000 }, - .columnsPercents = { 2500, 5000, 2500 }, - .cellChildMap = { { 0, 1, 2 } } })); - expected.Append(CustomZoneSetJSON::ToJson(CustomZoneSetJSON{ L"uuid", CustomZoneSetData{ L"name", CustomLayoutType::Grid, grid } })); - json::JsonObject json; - json.SetNamedValue(L"custom-zone-sets", json::JsonValue::Parse(expected.Stringify())); - - FancyZonesData data; - data.ParseCustomZoneSets(json); - - auto actual = data.SerializeCustomZoneSets(); - compareJsonArrays(expected, actual); - } - - TEST_METHOD(CustomZoneSetsSerializeMany) - { - json::JsonObject json; - json::JsonArray expected; - const GridLayoutInfo grid(GridLayoutInfo(JSONHelpers::GridLayoutInfo::Full{ - .rows = 1, - .columns = 3, - .rowsPercents = { 10000 }, - .columnsPercents = { 2500, 5000, 2500 }, - .cellChildMap = { { 0, 1, 2 } } })); - - expected.Append(CustomZoneSetJSON::ToJson(CustomZoneSetJSON{ L"zone-uuid-1", CustomZoneSetData{ L"name", CustomLayoutType::Grid, grid } })); - expected.Append(CustomZoneSetJSON::ToJson(CustomZoneSetJSON{ L"zone-uuid-2", CustomZoneSetData{ L"name", CustomLayoutType::Canvas, CanvasLayoutInfo{ 1, 2 } } })); - expected.Append(CustomZoneSetJSON::ToJson(CustomZoneSetJSON{ L"zone-uuid-3", CustomZoneSetData{ L"name", CustomLayoutType::Grid, grid } })); - expected.Append(CustomZoneSetJSON::ToJson(CustomZoneSetJSON{ L"zone-uuid-4", CustomZoneSetData{ L"name", CustomLayoutType::Canvas, CanvasLayoutInfo{ 1, 2 } } })); - json.SetNamedValue(L"custom-zone-sets", json::JsonValue::Parse(expected.Stringify())); - - FancyZonesData data; - data.ParseCustomZoneSets(json); - - auto actual = data.SerializeCustomZoneSets(); - compareJsonArrays(expected, actual); - } - - TEST_METHOD(CustomZoneSetsSerializeEmpty) - { - json::JsonArray expected; - json::JsonObject json; - json.SetNamedValue(L"custom-zone-sets", json::JsonValue::Parse(expected.Stringify())); - - FancyZonesData data; - data.ParseCustomZoneSets(json); - - auto actual = data.SerializeCustomZoneSets(); - compareJsonArrays(expected, actual); - } - - TEST_METHOD(CustomZoneSetsReadTemp) - { - //prepare device data - const std::wstring deviceId = L"default_device_id"; - - { - DeviceInfoJSON deviceInfo{ deviceId, DeviceInfoData{ ZoneSetData{ L"uuid", ZoneSetLayoutType::Custom }, true, 16, 3 } }; - const std::wstring deviceInfoPath = m_fzData.GetPersistFancyZonesJSONPath() + L".device_info_tmp"; - m_fzData.SerializeDeviceInfoToTmpFile(deviceInfo, deviceInfoPath); - - m_fzData.ParseDeviceInfoFromTmpFile(deviceInfoPath); - std::filesystem::remove(deviceInfoPath); - } - - const std::wstring uuid = L"uuid"; - const GridLayoutInfo grid(GridLayoutInfo(JSONHelpers::GridLayoutInfo::Full{ - .rows = 1, - .columns = 3, - .rowsPercents = { 10000 }, - .columnsPercents = { 2500, 5000, 2500 }, - .cellChildMap = { { 0, 1, 2 } } })); - CustomZoneSetJSON expected{ uuid, CustomZoneSetData{ L"name", CustomLayoutType::Grid, grid } }; - - FancyZonesData data; - const std::wstring path = data.GetPersistFancyZonesJSONPath() + L".test_tmp"; - json::to_file(path, CustomZoneSetJSON::ToJson(expected)); - m_fzData.ParseCustomZoneSetFromTmpFile(path); - - bool actualFileExists = std::filesystem::exists(path); - if (actualFileExists) - { - std::filesystem::remove(path); //clean up before compare asserts - } - Assert::IsFalse(actualFileExists); - - auto devices = m_fzData.GetCustomZoneSetsMap(); - Assert::AreEqual((size_t)1, devices.size()); - - auto actual = devices.find(uuid)->second; - Assert::AreEqual((int)expected.data.type, (int)actual.type); - Assert::AreEqual(expected.data.name.c_str(), actual.name.c_str()); - auto expectedGrid = std::get(expected.data.info); - auto actualGrid = std::get(actual.info); - Assert::AreEqual(expectedGrid.rows(), actualGrid.rows()); - Assert::AreEqual(expectedGrid.columns(), actualGrid.columns()); - } - - TEST_METHOD(CustomZoneSetsReadTempUnexsisted) - { - const std::wstring path = m_fzData.GetPersistFancyZonesJSONPath() + L".test_tmp"; - const std::wstring deviceId = L"default_device_id"; - - m_fzData.ParseCustomZoneSetFromTmpFile(path); - auto devices = m_fzData.GetDeviceInfoMap(); - Assert::AreEqual((size_t)0, devices.size()); - } - - TEST_METHOD(SetActiveZoneSet) - { - FancyZonesData data; - const std::wstring uniqueId = L"default_device_id"; - - json::JsonArray devices; - devices.Append(m_defaultCustomDeviceValue); - json::JsonObject json; - json.SetNamedValue(L"devices", devices); - data.ParseDeviceInfos(json); - - JSONHelpers::ZoneSetData expectedZoneSetData{ - .uuid = L"uuid", - .type = ZoneSetLayoutType::Focus - }; - - data.SetActiveZoneSet(uniqueId, expectedZoneSetData); - - auto actual = data.GetDeviceInfoMap().find(uniqueId)->second; - Assert::AreEqual(expectedZoneSetData.uuid.c_str(), actual.activeZoneSet.uuid.c_str()); - Assert::IsTrue(expectedZoneSetData.type == actual.activeZoneSet.type); - } - - TEST_METHOD(SetActiveZoneSetUuidEmpty) - { - FancyZonesData data; - const std::wstring expected = L"uuid"; - const std::wstring uniqueId = L"default_device_id"; - - json::JsonArray devices; - devices.Append(m_defaultCustomDeviceValue); - json::JsonObject json; - json.SetNamedValue(L"devices", devices); - data.ParseDeviceInfos(json); - - JSONHelpers::ZoneSetData expectedZoneSetData{ - .uuid = L"", - .type = ZoneSetLayoutType::Focus - }; - - data.SetActiveZoneSet(uniqueId, expectedZoneSetData); - - auto actual = data.GetDeviceInfoMap().find(uniqueId)->second; - Assert::AreEqual(expectedZoneSetData.uuid.c_str(), actual.activeZoneSet.uuid.c_str()); - Assert::IsTrue(expectedZoneSetData.type == actual.activeZoneSet.type); - } - - TEST_METHOD(SetActiveZoneSetUniqueIdInvalid) - { - FancyZonesData data; - const std::wstring expected = L"uuid"; - const std::wstring uniqueId = L"id_not_contained_by_device_info_map"; - - json::JsonArray devices; - devices.Append(m_defaultCustomDeviceValue); - json::JsonObject json; - json.SetNamedValue(L"devices", devices); - bool parseRes = data.ParseDeviceInfos(json); - Assert::IsTrue(parseRes); - - JSONHelpers::ZoneSetData zoneSetData{ - .uuid = L"new_uuid", - .type = ZoneSetLayoutType::Focus - }; - - data.SetActiveZoneSet(uniqueId, zoneSetData); - - const auto& deviceInfoMap = data.GetDeviceInfoMap(); - auto actual = deviceInfoMap.find(L"default_device_id")->second; - Assert::AreEqual(expected.c_str(), actual.activeZoneSet.uuid.c_str()); - Assert::IsTrue(deviceInfoMap.end() == deviceInfoMap.find(uniqueId), L"new device info should not be added"); - } - - TEST_METHOD(LoadFancyZonesDataFromJson) - { - FancyZonesData data; - const auto jsonPath = data.GetPersistFancyZonesJSONPath(); - auto savedJson = json::from_file(jsonPath); - - if (std::filesystem::exists(jsonPath)) - { - std::filesystem::remove(jsonPath); - } - - const GridLayoutInfo grid(GridLayoutInfo(JSONHelpers::GridLayoutInfo::Full{ - .rows = 1, - .columns = 3, - .rowsPercents = { 10000 }, - .columnsPercents = { 2500, 5000, 2500 }, - .cellChildMap = { { 0, 1, 2 } } })); - CustomZoneSetJSON zoneSets{ L"zone-set-uuid", CustomZoneSetData{ L"name", CustomLayoutType::Grid, grid } }; - AppZoneHistoryJSON appZoneHistory{ L"app-path", AppZoneHistoryData{ .zoneSetUuid = L"zoneset-uuid", .deviceId = L"device-id", .zoneIndex = 54321 } }; - DeviceInfoJSON deviceInfo{ L"uuid", DeviceInfoData{ ZoneSetData{ L"uuid", ZoneSetLayoutType::Custom }, true, 16, 3 } }; - json::JsonArray zoneSetsArray, appZonesArray, deviceInfoArray; - zoneSetsArray.Append(CustomZoneSetJSON::ToJson(zoneSets)); - appZonesArray.Append(AppZoneHistoryJSON::ToJson(appZoneHistory)); - deviceInfoArray.Append(DeviceInfoJSON::ToJson(deviceInfo)); - json::JsonObject fancyZones; - fancyZones.SetNamedValue(L"custom-zone-sets", zoneSetsArray); - fancyZones.SetNamedValue(L"app-zone-history", appZonesArray); - fancyZones.SetNamedValue(L"devices", deviceInfoArray); - - json::to_file(jsonPath, fancyZones); - - data.LoadFancyZonesData(); - if (savedJson) - { - json::to_file(jsonPath, *savedJson); - } - else - { - std::filesystem::remove(jsonPath); - } - - Assert::IsFalse(data.GetCustomZoneSetsMap().empty()); - Assert::IsFalse(data.GetCustomZoneSetsMap().empty()); - Assert::IsFalse(data.GetCustomZoneSetsMap().empty()); - } - - TEST_METHOD(LoadFancyZonesDataFromRegistry) - { - FancyZonesData data; - const auto jsonPath = data.GetPersistFancyZonesJSONPath(); - auto savedJson = json::from_file(jsonPath); - - if (std::filesystem::exists(jsonPath)) - { - std::filesystem::remove(jsonPath); - } - - data.LoadFancyZonesData(); - bool actual = std::filesystem::exists(jsonPath); - if (savedJson) - { - json::to_file(jsonPath, *savedJson); - } - else - { - std::filesystem::remove(jsonPath); - } - - Assert::IsTrue(actual); - } - - TEST_METHOD(SaveFancyZonesData) - { - FancyZonesData data; - const auto jsonPath = data.GetPersistFancyZonesJSONPath(); - auto savedJson = json::from_file(jsonPath); - - if (std::filesystem::exists(jsonPath)) - { - std::filesystem::remove(jsonPath); - } - - data.SaveFancyZonesData(); - bool actual = std::filesystem::exists(jsonPath); - - if (savedJson) - { - json::to_file(jsonPath, *savedJson); - } - else - { - std::filesystem::remove(jsonPath); - } - - Assert::IsTrue(actual); - } - - TEST_METHOD(AppLastZoneIndex) - { - const std::wstring deviceId = L"device-id"; - const std::wstring zoneSetId = L"zoneset-uuid"; - const auto window = Mocks::WindowCreate(m_hInst); - FancyZonesData data; - - Assert::AreEqual(-1, data.GetAppLastZoneIndex(window, deviceId, zoneSetId)); - - const int expectedZoneIndex = 10; - Assert::IsTrue(data.SetAppLastZone(window, deviceId, zoneSetId, expectedZoneIndex)); - Assert::AreEqual(expectedZoneIndex, data.GetAppLastZoneIndex(window, deviceId, zoneSetId)); - } - - TEST_METHOD(AppLastZoneIndexZero) - { - const std::wstring zoneSetId = L"zoneset-uuid"; - const std::wstring deviceId = L"device-id"; - const auto window = Mocks::WindowCreate(m_hInst); - FancyZonesData data; - - const int expectedZoneIndex = 0; - Assert::IsTrue(data.SetAppLastZone(window, deviceId, zoneSetId, expectedZoneIndex)); - Assert::AreEqual(expectedZoneIndex, data.GetAppLastZoneIndex(window, deviceId, zoneSetId)); - } - - TEST_METHOD(AppLastZoneIndexNegative) - { - const std::wstring zoneSetId = L"zoneset-uuid"; - const std::wstring deviceId = L"device-id"; - const auto window = Mocks::WindowCreate(m_hInst); - FancyZonesData data; - - const int expectedZoneIndex = -1; - Assert::IsTrue(data.SetAppLastZone(window, deviceId, zoneSetId, expectedZoneIndex)); - Assert::AreEqual(expectedZoneIndex, data.GetAppLastZoneIndex(window, deviceId, zoneSetId)); - } - - TEST_METHOD(AppLastZoneIndexOverflow) - { - const std::wstring zoneSetId = L"zoneset-uuid"; - const std::wstring deviceId = L"device-id"; - const auto window = Mocks::WindowCreate(m_hInst); - FancyZonesData data; - - const long expectedZoneIndex = LONG_MAX; - Assert::IsTrue(data.SetAppLastZone(window, deviceId, zoneSetId, expectedZoneIndex)); - Assert::AreEqual(static_cast(expectedZoneIndex), data.GetAppLastZoneIndex(window, deviceId, zoneSetId)); - } - - TEST_METHOD(AppLastZoneIndexOverride) - { - const std::wstring zoneSetId = L"zoneset-uuid"; - const std::wstring deviceId = L"device-id"; - const auto window = Mocks::WindowCreate(m_hInst); - FancyZonesData data; - - const int expectedZoneIndex = 3; - Assert::IsTrue(data.SetAppLastZone(window, deviceId, zoneSetId, 1)); - Assert::IsTrue(data.SetAppLastZone(window, deviceId, zoneSetId, 2)); - Assert::IsTrue(data.SetAppLastZone(window, deviceId, zoneSetId, expectedZoneIndex)); - Assert::AreEqual(expectedZoneIndex, data.GetAppLastZoneIndex(window, deviceId, zoneSetId)); - } - - TEST_METHOD(AppLastZoneInvalidWindow) - { - const std::wstring zoneSetId = L"zoneset-uuid"; - const std::wstring deviceId = L"device-id"; - const auto window = Mocks::Window(); - FancyZonesData data; - - Assert::AreEqual(-1, data.GetAppLastZoneIndex(window, deviceId, zoneSetId)); - - const int expectedZoneIndex = 1; - Assert::IsFalse(data.SetAppLastZone(window, deviceId, zoneSetId, expectedZoneIndex)); - } - - TEST_METHOD(AppLastZoneNullWindow) - { - const std::wstring zoneSetId = L"zoneset-uuid"; - const auto window = nullptr; - FancyZonesData data; - - const int expectedZoneIndex = 1; - Assert::IsFalse(data.SetAppLastZone(window, L"device-id", zoneSetId, expectedZoneIndex)); - } - - TEST_METHOD(AppLastdeviceIdTest) - { - const std::wstring zoneSetId = L"zoneset-uuid"; - const std::wstring deviceId1 = L"device-id-1"; - const std::wstring deviceId2 = L"device-id-2"; - const auto window = Mocks::WindowCreate(m_hInst); - FancyZonesData data; - - const int expectedZoneIndex = 10; - Assert::IsTrue(data.SetAppLastZone(window, deviceId1, zoneSetId, expectedZoneIndex)); - Assert::AreEqual(expectedZoneIndex, data.GetAppLastZoneIndex(window, deviceId1, zoneSetId)); - Assert::AreEqual(-1, data.GetAppLastZoneIndex(window, deviceId2, zoneSetId)); - } - - TEST_METHOD(AppLastZoneSetIdTest) - { - const std::wstring zoneSetId1 = L"zoneset-uuid-1"; - const std::wstring zoneSetId2 = L"zoneset-uuid-2"; - const std::wstring deviceId = L"device-id"; - const auto window = Mocks::WindowCreate(m_hInst); - FancyZonesData data; - - const int expectedZoneIndex = 10; - Assert::IsTrue(data.SetAppLastZone(window, deviceId, zoneSetId1, expectedZoneIndex)); - Assert::AreEqual(expectedZoneIndex, data.GetAppLastZoneIndex(window, deviceId, zoneSetId1)); - Assert::AreEqual(-1, data.GetAppLastZoneIndex(window, deviceId, zoneSetId2)); - } - - TEST_METHOD(AppLastZoneRemoveWindow) - { - const std::wstring zoneSetId = L"zoneset-uuid"; - const std::wstring deviceId = L"device-id"; - const auto window = Mocks::WindowCreate(m_hInst); - FancyZonesData data; - - Assert::IsTrue(data.SetAppLastZone(window, deviceId, zoneSetId, 1)); - Assert::IsTrue(data.RemoveAppLastZone(window, deviceId, zoneSetId)); - Assert::AreEqual(-1, data.GetAppLastZoneIndex(window, deviceId, zoneSetId)); - } - - TEST_METHOD(AppLastZoneRemoveUnknownWindow) - { - const std::wstring zoneSetId = L"zoneset-uuid"; - const std::wstring deviceId = L"device-id"; - const auto window = Mocks::WindowCreate(m_hInst); - FancyZonesData data; - - Assert::IsFalse(data.RemoveAppLastZone(window, deviceId, zoneSetId)); - Assert::AreEqual(-1, data.GetAppLastZoneIndex(window, deviceId, zoneSetId)); - } - - TEST_METHOD(AppLastZoneRemoveUnknownZoneSetId) - { - const std::wstring zoneSetIdToInsert = L"zoneset-uuid-to-insert"; - const std::wstring zoneSetIdToRemove = L"zoneset-uuid-to-remove"; - const std::wstring deviceId = L"device-id"; - const auto window = Mocks::WindowCreate(m_hInst); - FancyZonesData data; - - Assert::IsTrue(data.SetAppLastZone(window, deviceId, zoneSetIdToInsert, 1)); - Assert::IsFalse(data.RemoveAppLastZone(window, deviceId, zoneSetIdToRemove)); - Assert::AreEqual(1, data.GetAppLastZoneIndex(window, deviceId, zoneSetIdToInsert)); - } - - TEST_METHOD(AppLastZoneRemoveUnknownWindowId) - { - const std::wstring zoneSetId = L"zoneset-uuid"; - const std::wstring deviceIdToInsert = L"device-id-insert"; - const std::wstring deviceIdToRemove = L"device-id-remove"; - const auto window = Mocks::WindowCreate(m_hInst); - FancyZonesData data; - - Assert::IsTrue(data.SetAppLastZone(window, deviceIdToInsert, zoneSetId, 1)); - Assert::IsFalse(data.RemoveAppLastZone(window, deviceIdToRemove, zoneSetId)); - Assert::AreEqual(1, data.GetAppLastZoneIndex(window, deviceIdToInsert, zoneSetId)); - } - - TEST_METHOD(AppLastZoneRemoveNullWindow) - { - const std::wstring zoneSetId = L"zoneset-uuid"; - const std::wstring deviceId = L"device-id"; - const auto window = Mocks::WindowCreate(m_hInst); - FancyZonesData data; - - Assert::IsFalse(data.RemoveAppLastZone(nullptr, deviceId, zoneSetId)); - } -}; + public: + TEST_METHOD (FancyZonesDataPath) + { + FancyZonesData data; + Assert::IsFalse(data.GetPersistFancyZonesJSONPath().empty()); + } + + TEST_METHOD (FancyZonesDataJsonEmpty) + { + FancyZonesData data; + const auto jsonPath = data.GetPersistFancyZonesJSONPath(); + auto savedJson = json::from_file(jsonPath); + + if (std::filesystem::exists(jsonPath)) + { + std::filesystem::remove(jsonPath); + } + + json::JsonObject expected; + auto actual = data.GetPersistFancyZonesJSON(); + + Assert::AreEqual(expected.Stringify().c_str(), actual.Stringify().c_str()); + + if (savedJson) + { + json::to_file(jsonPath, *savedJson); + } + } + + TEST_METHOD (FancyZonesDataJson) + { + FancyZonesData data; + const auto jsonPath = data.GetPersistFancyZonesJSONPath(); + auto savedJson = json::from_file(jsonPath); + + if (std::filesystem::exists(jsonPath)) + { + std::filesystem::remove(jsonPath); + } + + json::JsonObject expected = json::JsonObject::Parse(L"{\"fancy-zones\":{\"custom-zonesets \":[{\"uuid\":\"uuid1\",\"name\":\"Custom1\",\"type\":\"custom\" }] } }"); + json::to_file(jsonPath, expected); + + auto actual = data.GetPersistFancyZonesJSON(); + Assert::AreEqual(expected.Stringify().c_str(), actual.Stringify().c_str()); + + if (savedJson) + { + json::to_file(jsonPath, *savedJson); + } + else + { + std::filesystem::remove(jsonPath); + } + } + + TEST_METHOD (FancyZonesDataDeviceInfoMap) + { + FancyZonesData data; + const auto actual = data.GetDeviceInfoMap(); + Assert::IsTrue(actual.empty()); + } + + TEST_METHOD (FancyZonesDataDeviceInfoMapParseEmpty) + { + FancyZonesData data; + + json::JsonObject json; + data.ParseDeviceInfos(json); + + const auto actual = data.GetDeviceInfoMap(); + Assert::IsTrue(actual.empty()); + } + + TEST_METHOD (FancyZonesDataDeviceInfoMapParseValidEmpty) + { + FancyZonesData data; + + json::JsonObject expected; + json::JsonArray zoneSets; + expected.SetNamedValue(L"devices", zoneSets); + + data.ParseDeviceInfos(expected); + + const auto actual = data.GetDeviceInfoMap(); + Assert::IsTrue(actual.empty()); + } + + TEST_METHOD (FancyZonesDataDeviceInfoMapParseInvalid) + { + json::JsonArray devices; + devices.Append(json::JsonObject::Parse(m_defaultCustomDeviceStr)); + devices.Append(json::JsonObject::Parse(L"{\"device-id\": \"device_id\"}")); + + json::JsonObject expected; + expected.SetNamedValue(L"devices", devices); + + FancyZonesData data; + auto actual = data.ParseDeviceInfos(expected); + + Assert::IsFalse(actual); + } + + TEST_METHOD (FancyZonesDataDeviceInfoMapParseSingle) + { + json::JsonArray devices; + devices.Append(m_defaultCustomDeviceValue); + json::JsonObject expected; + expected.SetNamedValue(L"devices", devices); + + FancyZonesData data; + data.ParseDeviceInfos(expected); + + const auto actualMap = data.GetDeviceInfoMap(); + Assert::AreEqual((size_t)1, actualMap.size()); + } + + TEST_METHOD (FancyZonesDataDeviceInfoMapParseMany) + { + json::JsonArray devices; + for (int i = 0; i < 10; i++) + { + json::JsonObject obj = json::JsonObject::Parse(m_defaultCustomDeviceStr); + obj.SetNamedValue(L"device-id", json::JsonValue::CreateStringValue(std::to_wstring(i) + L"_1920_1200_{39B25DD2-130D-4B5D-8851-4791D66B1539}")); + devices.Append(obj); + } + + json::JsonObject expected; + expected.SetNamedValue(L"devices", devices); + Logger::WriteMessage(expected.Stringify().c_str()); + Logger::WriteMessage("\n"); + + FancyZonesData data; + data.ParseDeviceInfos(expected); + + const auto actualMap = data.GetDeviceInfoMap(); + Assert::AreEqual((size_t)10, actualMap.size()); + } + + TEST_METHOD (FancyZonesDataSerialize) + { + json::JsonArray expectedDevices; + expectedDevices.Append(m_defaultCustomDeviceObj); + json::JsonObject expected; + expected.SetNamedValue(L"devices", expectedDevices); + + FancyZonesData data; + data.ParseDeviceInfos(expected); + + auto actual = data.SerializeDeviceInfos(); + compareJsonArrays(expectedDevices, actual); + } + + TEST_METHOD (DeviceInfoSaveTemp) + { + FancyZonesData data; + DeviceInfoJSON deviceInfo{ L"default_device_id", DeviceInfoData{ ZoneSetData{ L"uuid", ZoneSetLayoutType::Custom }, true, 16, 3 } }; + + const std::wstring path = data.GetPersistFancyZonesJSONPath() + L".test_tmp"; + data.SerializeDeviceInfoToTmpFile(deviceInfo, path); + + bool actualFileExists = std::filesystem::exists(path); + Assert::IsTrue(actualFileExists); + + auto expectedData = DeviceInfoJSON::ToJson(deviceInfo); + auto actualSavedData = json::from_file(path); + std::filesystem::remove(path); //clean up before compare asserts + + Assert::IsTrue(actualSavedData.has_value()); + compareJsonObjects(expectedData, *actualSavedData); + } + + TEST_METHOD (DeviceInfoReadTemp) + { + FancyZonesData data; + const std::wstring deviceId = m_defaultDeviceId; + DeviceInfoJSON expected{ deviceId, DeviceInfoData{ ZoneSetData{ L"{33A2B101-06E0-437B-A61E-CDBECF502906}", ZoneSetLayoutType::Custom }, true, 16, 3 } }; + const std::wstring path = data.GetPersistFancyZonesJSONPath() + L".test_tmp"; + data.SerializeDeviceInfoToTmpFile(expected, path); + + data.ParseDeviceInfoFromTmpFile(path); + + bool actualFileExists = std::filesystem::exists(path); + if (actualFileExists) + { + std::filesystem::remove(path); //clean up before compare asserts + } + Assert::IsFalse(actualFileExists); + + auto devices = data.GetDeviceInfoMap(); + Assert::AreEqual((size_t)1, devices.size()); + + auto actual = devices.find(deviceId)->second; + Assert::AreEqual(expected.data.showSpacing, actual.showSpacing); + Assert::AreEqual(expected.data.spacing, actual.spacing); + Assert::AreEqual(expected.data.zoneCount, actual.zoneCount); + Assert::AreEqual((int)expected.data.activeZoneSet.type, (int)actual.activeZoneSet.type); + Assert::AreEqual(expected.data.activeZoneSet.uuid.c_str(), actual.activeZoneSet.uuid.c_str()); + } + + TEST_METHOD (DeviceInfoReadTempUnexsisted) + { + FancyZonesData data; + const std::wstring path = data.GetPersistFancyZonesJSONPath() + L".test_tmp"; + data.ParseDeviceInfoFromTmpFile(path); + + auto devices = data.GetDeviceInfoMap(); + Assert::AreEqual((size_t)0, devices.size()); + } + + TEST_METHOD (AppZoneHistoryParseSingle) + { + const std::wstring expectedAppPath = L"appPath"; + const std::wstring expectedDeviceId = m_defaultDeviceId; + const std::wstring expectedZoneSetId = L"{33A2B101-06E0-437B-A61E-CDBECF502906}"; + const int expectedIndex = 54321; + + json::JsonObject json; + AppZoneHistoryJSON expected{ expectedAppPath, AppZoneHistoryData{ .zoneSetUuid = expectedZoneSetId, .deviceId = expectedDeviceId, .zoneIndex = expectedIndex } }; + json::JsonArray zoneHistoryArray; + zoneHistoryArray.Append(AppZoneHistoryJSON::ToJson(expected)); + json.SetNamedValue(L"app-zone-history", json::JsonValue::Parse(zoneHistoryArray.Stringify())); + + FancyZonesData data; + data.ParseAppZoneHistory(json); + + const auto actualProcessHistoryMap = data.GetAppZoneHistoryMap(); + Assert::AreEqual((size_t)zoneHistoryArray.Size(), actualProcessHistoryMap.size()); + + const auto actualProcessHistory = actualProcessHistoryMap.begin(); + Assert::AreEqual(expectedAppPath.c_str(), actualProcessHistory->first.c_str()); + + const auto actualAppZoneHistory = actualProcessHistory->second; + Assert::AreEqual(expectedZoneSetId.c_str(), actualAppZoneHistory.zoneSetUuid.c_str()); + Assert::AreEqual(expectedDeviceId.c_str(), actualAppZoneHistory.deviceId.c_str()); + Assert::AreEqual(expectedIndex, actualAppZoneHistory.zoneIndex); + } + + TEST_METHOD (AppZoneHistoryParseManyApps) + { + json::JsonObject json; + json::JsonArray zoneHistoryArray; + zoneHistoryArray.Append(AppZoneHistoryJSON::ToJson(AppZoneHistoryJSON{ L"app-path-1", AppZoneHistoryData{ .zoneSetUuid = L"{33A2B101-06E0-437B-A61E-CDBECF502900}", .deviceId = L"AOC2460#4&fe3a015&0&UID65793_1920_1200_{39B25DD2-130D-4B5D-8851-4791D66B1530}", .zoneIndex = 1 } })); + zoneHistoryArray.Append(AppZoneHistoryJSON::ToJson(AppZoneHistoryJSON{ L"app-path-2", AppZoneHistoryData{ .zoneSetUuid = L"{33A2B101-06E0-437B-A61E-CDBECF502901}", .deviceId = L"AOC2460#4&fe3a015&0&UID65793_1920_1200_{39B25DD2-130D-4B5D-8851-4791D66B1531}", .zoneIndex = 2 } })); + zoneHistoryArray.Append(AppZoneHistoryJSON::ToJson(AppZoneHistoryJSON{ L"app-path-3", AppZoneHistoryData{ .zoneSetUuid = L"{33A2B101-06E0-437B-A61E-CDBECF502902}", .deviceId = L"AOC2460#4&fe3a015&0&UID65793_1920_1200_{39B25DD2-130D-4B5D-8851-4791D66B1532}", .zoneIndex = 3 } })); + zoneHistoryArray.Append(AppZoneHistoryJSON::ToJson(AppZoneHistoryJSON{ L"app-path-4", AppZoneHistoryData{ .zoneSetUuid = L"{33A2B101-06E0-437B-A61E-CDBECF502903}", .deviceId = L"AOC2460#4&fe3a015&0&UID65793_1920_1200_{39B25DD2-130D-4B5D-8851-4791D66B1533}", .zoneIndex = 4 } })); + + json.SetNamedValue(L"app-zone-history", json::JsonValue::Parse(zoneHistoryArray.Stringify())); + + FancyZonesData data; + data.ParseAppZoneHistory(json); + + auto actualMap = data.GetAppZoneHistoryMap(); + Assert::AreEqual((size_t)zoneHistoryArray.Size(), actualMap.size()); + + const auto actualProcessHistoryMap = data.GetAppZoneHistoryMap(); + Assert::AreEqual((size_t)zoneHistoryArray.Size(), actualProcessHistoryMap.size()); + + auto iter = zoneHistoryArray.First(); + while (iter.HasCurrent()) + { + auto expected = AppZoneHistoryJSON::FromJson(json::JsonObject::Parse(iter.Current().Stringify())); + + const auto actual = actualProcessHistoryMap.at(expected->appPath); + Assert::AreEqual(expected->data.deviceId.c_str(), actual.deviceId.c_str()); + Assert::AreEqual(expected->data.zoneSetUuid.c_str(), actual.zoneSetUuid.c_str()); + Assert::AreEqual(expected->data.zoneIndex, actual.zoneIndex); + + iter.MoveNext(); + } + } + + TEST_METHOD (AppZoneHistoryParseManyZonesForSingleApp) + { + json::JsonObject json; + json::JsonArray zoneHistoryArray; + + const auto appPath = L"app-path"; + zoneHistoryArray.Append(AppZoneHistoryJSON::ToJson(AppZoneHistoryJSON{ appPath, AppZoneHistoryData{ .zoneSetUuid = L"{33A2B101-06E0-437B-A61E-CDBECF502900}", .deviceId = L"AOC2460#4&fe3a015&0&UID65793_1920_1200_{39B25DD2-130D-4B5D-8851-4791D66B1530}", .zoneIndex = 1 } })); + zoneHistoryArray.Append(AppZoneHistoryJSON::ToJson(AppZoneHistoryJSON{ appPath, AppZoneHistoryData{ .zoneSetUuid = L"{33A2B101-06E0-437B-A61E-CDBECF502901}", .deviceId = L"AOC2460#4&fe3a015&0&UID65793_1920_1200_{39B25DD2-130D-4B5D-8851-4791D66B1531}", .zoneIndex = 2 } })); + zoneHistoryArray.Append(AppZoneHistoryJSON::ToJson(AppZoneHistoryJSON{ appPath, AppZoneHistoryData{ .zoneSetUuid = L"{33A2B101-06E0-437B-A61E-CDBECF502902}", .deviceId = L"AOC2460#4&fe3a015&0&UID65793_1920_1200_{39B25DD2-130D-4B5D-8851-4791D66B1532}", .zoneIndex = 3 } })); + const auto expected = AppZoneHistoryData{ .zoneSetUuid = L"{33A2B101-06E0-437B-A61E-CDBECF502903}", .deviceId = L"AOC2460#4&fe3a015&0&UID65793_1920_1200_{39B25DD2-130D-4B5D-8851-4791D66B1533}", .zoneIndex = 4 }; + zoneHistoryArray.Append(AppZoneHistoryJSON::ToJson(AppZoneHistoryJSON{ appPath, expected })); + json.SetNamedValue(L"app-zone-history", json::JsonValue::Parse(zoneHistoryArray.Stringify())); + + FancyZonesData data; + data.ParseAppZoneHistory(json); + + const auto actualProcessHistoryMap = data.GetAppZoneHistoryMap(); + Assert::AreEqual((size_t)1, actualProcessHistoryMap.size()); + + const auto actual = actualProcessHistoryMap.at(appPath); + Assert::AreEqual(expected.deviceId.c_str(), actual.deviceId.c_str()); + Assert::AreEqual(expected.zoneSetUuid.c_str(), actual.zoneSetUuid.c_str()); + Assert::AreEqual(expected.zoneIndex, actual.zoneIndex); + } + + TEST_METHOD (AppZoneHistoryParseEmpty) + { + FancyZonesData data; + data.ParseAppZoneHistory(json::JsonObject()); + + auto actual = data.GetAppZoneHistoryMap(); + Assert::IsTrue(actual.empty()); + } + + TEST_METHOD (AppZoneHistoryParseInvalid) + { + const std::wstring appPath = L"appPath"; + json::JsonObject json; + AppZoneHistoryJSON expected{ appPath, AppZoneHistoryData{ .zoneSetUuid = L"{33A2B101-06E0-437B-A61E-CDBECF502906}", .deviceId = L"device-id", .zoneIndex = 54321 } }; + json.SetNamedValue(L"app-zone-history", json::JsonValue::Parse(AppZoneHistoryJSON::ToJson(expected).Stringify())); + + FancyZonesData data; + bool actual = data.ParseAppZoneHistory(json); + + Assert::IsFalse(actual); + } + + TEST_METHOD (AppZoneHistoryParseInvalidUuid) + { + const std::wstring appPath = L"appPath"; + json::JsonObject json; + AppZoneHistoryJSON expected{ appPath, AppZoneHistoryData{ .zoneSetUuid = L"zoneset-uuid", .deviceId = L"device-id", .zoneIndex = 54321 } }; + json.SetNamedValue(L"app-zone-history", json::JsonValue::Parse(AppZoneHistoryJSON::ToJson(expected).Stringify())); + + FancyZonesData data; + bool actual = data.ParseAppZoneHistory(json); + + Assert::IsFalse(actual); + } + + TEST_METHOD (AppZoneHistorySerializeSingle) + { + const std::wstring appPath = L"appPath"; + json::JsonArray expected; + expected.Append(AppZoneHistoryJSON::ToJson(AppZoneHistoryJSON{ appPath, AppZoneHistoryData{ .zoneSetUuid = L"{39B25DD2-130D-4B5D-8851-4791D66B1539}", .deviceId = m_defaultDeviceId, .zoneIndex = 54321 } })); + json::JsonObject json; + json.SetNamedValue(L"app-zone-history", json::JsonValue::Parse(expected.Stringify())); + + FancyZonesData data; + data.ParseAppZoneHistory(json); + + auto actual = data.SerializeAppZoneHistory(); + compareJsonArrays(expected, actual); + } + + TEST_METHOD (AppZoneHistorySerializeMany) + { + json::JsonObject json; + json::JsonArray expected; + expected.Append(AppZoneHistoryJSON::ToJson(AppZoneHistoryJSON{ L"app-path-1", AppZoneHistoryData{ .zoneSetUuid = L"{33A2B101-06E0-437B-A61E-CDBECF502906}", .deviceId = m_defaultDeviceId, .zoneIndex = 54321 } })); + expected.Append(AppZoneHistoryJSON::ToJson(AppZoneHistoryJSON{ L"app-path-2", AppZoneHistoryData{ .zoneSetUuid = L"{33A2B101-06E0-437B-A61E-CDBECF502906}", .deviceId = m_defaultDeviceId, .zoneIndex = 54321 } })); + expected.Append(AppZoneHistoryJSON::ToJson(AppZoneHistoryJSON{ L"app-path-3", AppZoneHistoryData{ .zoneSetUuid = L"{33A2B101-06E0-437B-A61E-CDBECF502906}", .deviceId = m_defaultDeviceId, .zoneIndex = 54321 } })); + expected.Append(AppZoneHistoryJSON::ToJson(AppZoneHistoryJSON{ L"app-path-4", AppZoneHistoryData{ .zoneSetUuid = L"{33A2B101-06E0-437B-A61E-CDBECF502906}", .deviceId = m_defaultDeviceId, .zoneIndex = 54321 } })); + json.SetNamedValue(L"app-zone-history", json::JsonValue::Parse(expected.Stringify())); + + FancyZonesData data; + data.ParseAppZoneHistory(json); + + auto actual = data.SerializeAppZoneHistory(); + compareJsonArrays(expected, actual); + } + + TEST_METHOD (AppZoneHistorySerializeEmpty) + { + json::JsonArray expected; + json::JsonObject json; + json.SetNamedValue(L"app-zone-history", json::JsonValue::Parse(expected.Stringify())); + + FancyZonesData data; + data.ParseAppZoneHistory(json); + + auto actual = data.SerializeAppZoneHistory(); + compareJsonArrays(expected, actual); + } + + TEST_METHOD (CustomZoneSetsParseSingle) + { + const std::wstring zoneUuid = L"{33A2B101-06E0-437B-A61E-CDBECF502906}"; + GridLayoutInfo grid(GridLayoutInfo(JSONHelpers::GridLayoutInfo::Full{ + .rows = 1, + .columns = 3, + .rowsPercents = { 10000 }, + .columnsPercents = { 2500, 5000, 2500 }, + .cellChildMap = { { 0, 1, 2 } } })); + + json::JsonObject json; + CustomZoneSetJSON expected{ zoneUuid, CustomZoneSetData{ L"name", CustomLayoutType::Grid, grid } }; + json::JsonArray array; + array.Append(CustomZoneSetJSON::ToJson(expected)); + json.SetNamedValue(L"custom-zone-sets", json::JsonValue::Parse(array.Stringify())); + + FancyZonesData data; + data.ParseCustomZoneSets(json); + + auto actualMap = data.GetCustomZoneSetsMap(); + Assert::AreEqual((size_t)array.Size(), actualMap.size()); + + auto actual = actualMap.find(zoneUuid)->second; + Assert::AreEqual(expected.data.name.c_str(), actual.name.c_str()); + Assert::AreEqual((int)expected.data.type, (int)actual.type); + + auto expectedGrid = std::get(expected.data.info); + auto actualGrid = std::get(actual.info); + Assert::AreEqual(expectedGrid.rows(), actualGrid.rows()); + Assert::AreEqual(expectedGrid.columns(), actualGrid.columns()); + } + + TEST_METHOD (CustomZoneSetsParseMany) + { + json::JsonObject json; + json::JsonArray array; + const GridLayoutInfo grid(GridLayoutInfo(JSONHelpers::GridLayoutInfo::Full{ + .rows = 1, + .columns = 3, + .rowsPercents = { 10000 }, + .columnsPercents = { 2500, 5000, 2500 }, + .cellChildMap = { { 0, 1, 2 } } })); + array.Append(CustomZoneSetJSON::ToJson(CustomZoneSetJSON{ L"{33A2B101-06E0-437B-A61E-CDBECF502900}", CustomZoneSetData{ L"name", CustomLayoutType::Grid, grid } })); + array.Append(CustomZoneSetJSON::ToJson(CustomZoneSetJSON{ L"{33A2B101-06E0-437B-A61E-CDBECF502901}", CustomZoneSetData{ L"name", CustomLayoutType::Canvas, CanvasLayoutInfo{ 1, 2 } } })); + array.Append(CustomZoneSetJSON::ToJson(CustomZoneSetJSON{ L"{33A2B101-06E0-437B-A61E-CDBECF502902}", CustomZoneSetData{ L"name", CustomLayoutType::Grid, grid } })); + array.Append(CustomZoneSetJSON::ToJson(CustomZoneSetJSON{ L"{33A2B101-06E0-437B-A61E-CDBECF502903}", CustomZoneSetData{ L"name", CustomLayoutType::Canvas, CanvasLayoutInfo{ 1, 2 } } })); + json.SetNamedValue(L"custom-zone-sets", json::JsonValue::Parse(array.Stringify())); + + FancyZonesData data; + data.ParseCustomZoneSets(json); + + auto actualMap = data.GetCustomZoneSetsMap(); + Assert::AreEqual((size_t)array.Size(), actualMap.size()); + + auto iter = array.First(); + while (iter.HasCurrent()) + { + auto expected = CustomZoneSetJSON::FromJson(json::JsonObject::Parse(iter.Current().Stringify())); + auto actual = actualMap.find(expected->uuid)->second; + Assert::AreEqual(expected->data.name.c_str(), actual.name.c_str(), L"name"); + Assert::AreEqual((int)expected->data.type, (int)actual.type, L"type"); + + if (expected->data.type == CustomLayoutType::Grid) + { + auto expectedInfo = std::get(expected->data.info); + auto actualInfo = std::get(actual.info); + Assert::AreEqual(expectedInfo.rows(), actualInfo.rows(), L"grid rows"); + Assert::AreEqual(expectedInfo.columns(), actualInfo.columns(), L"grid columns"); + } + else + { + auto expectedInfo = std::get(expected->data.info); + auto actualInfo = std::get(actual.info); + Assert::AreEqual(expectedInfo.referenceWidth, actualInfo.referenceWidth, L"canvas width"); + Assert::AreEqual(expectedInfo.referenceHeight, actualInfo.referenceHeight, L"canvas height"); + } + + iter.MoveNext(); + } + } + + TEST_METHOD (CustomZoneSetsParseEmpty) + { + FancyZonesData data; + data.ParseCustomZoneSets(json::JsonObject()); + + auto actual = data.GetCustomZoneSetsMap(); + Assert::IsTrue(actual.empty()); + } + + TEST_METHOD (CustomZoneSetsParseInvalid) + { + json::JsonObject json; + CustomZoneSetJSON expected{ L"uuid", CustomZoneSetData{ L"name", CustomLayoutType::Grid, GridLayoutInfo(GridLayoutInfo::Minimal{ 1, 2 }) } }; + json.SetNamedValue(L"custom-zone-sets", json::JsonValue::Parse(CustomZoneSetJSON::ToJson(expected).Stringify())); + + FancyZonesData data; + auto actual = data.ParseCustomZoneSets(json); + + Assert::IsFalse(actual); + } + + TEST_METHOD (CustomZoneSetsSerializeSingle) + { + json::JsonArray expected; + const GridLayoutInfo grid(GridLayoutInfo(JSONHelpers::GridLayoutInfo::Full{ + .rows = 1, + .columns = 3, + .rowsPercents = { 10000 }, + .columnsPercents = { 2500, 5000, 2500 }, + .cellChildMap = { { 0, 1, 2 } } })); + expected.Append(CustomZoneSetJSON::ToJson(CustomZoneSetJSON{ L"{33A2B101-06E0-437B-A61E-CDBECF502906}", CustomZoneSetData{ L"name", CustomLayoutType::Grid, grid } })); + json::JsonObject json; + json.SetNamedValue(L"custom-zone-sets", json::JsonValue::Parse(expected.Stringify())); + + FancyZonesData data; + data.ParseCustomZoneSets(json); + + auto actual = data.SerializeCustomZoneSets(); + compareJsonArrays(expected, actual); + } + + TEST_METHOD (CustomZoneSetsSerializeMany) + { + json::JsonObject json; + json::JsonArray expected; + const GridLayoutInfo grid(GridLayoutInfo(JSONHelpers::GridLayoutInfo::Full{ + .rows = 1, + .columns = 3, + .rowsPercents = { 10000 }, + .columnsPercents = { 2500, 5000, 2500 }, + .cellChildMap = { { 0, 1, 2 } } })); + + expected.Append(CustomZoneSetJSON::ToJson(CustomZoneSetJSON{ L"{33A2B101-06E0-437B-A61E-CDBECF502900}", CustomZoneSetData{ L"name", CustomLayoutType::Grid, grid } })); + expected.Append(CustomZoneSetJSON::ToJson(CustomZoneSetJSON{ L"{33A2B101-06E0-437B-A61E-CDBECF502901}", CustomZoneSetData{ L"name", CustomLayoutType::Canvas, CanvasLayoutInfo{ 1, 2 } } })); + expected.Append(CustomZoneSetJSON::ToJson(CustomZoneSetJSON{ L"{33A2B101-06E0-437B-A61E-CDBECF502902}", CustomZoneSetData{ L"name", CustomLayoutType::Grid, grid } })); + expected.Append(CustomZoneSetJSON::ToJson(CustomZoneSetJSON{ L"{33A2B101-06E0-437B-A61E-CDBECF502903}", CustomZoneSetData{ L"name", CustomLayoutType::Canvas, CanvasLayoutInfo{ 1, 2 } } })); + json.SetNamedValue(L"custom-zone-sets", json::JsonValue::Parse(expected.Stringify())); + + FancyZonesData data; + data.ParseCustomZoneSets(json); + + auto actual = data.SerializeCustomZoneSets(); + compareJsonArrays(expected, actual); + } + + TEST_METHOD (CustomZoneSetsSerializeEmpty) + { + json::JsonArray expected; + json::JsonObject json; + json.SetNamedValue(L"custom-zone-sets", json::JsonValue::Parse(expected.Stringify())); + + FancyZonesData data; + data.ParseCustomZoneSets(json); + + auto actual = data.SerializeCustomZoneSets(); + compareJsonArrays(expected, actual); + } + + TEST_METHOD (CustomZoneSetsReadTemp) + { + //prepare device data + const std::wstring deviceId = L"default_device_id"; + + { + DeviceInfoJSON deviceInfo{ deviceId, DeviceInfoData{ ZoneSetData{ L"{33A2B101-06E0-437B-A61E-CDBECF502906}", ZoneSetLayoutType::Custom }, true, 16, 3 } }; + const std::wstring deviceInfoPath = m_fzData.GetPersistFancyZonesJSONPath() + L".device_info_tmp"; + m_fzData.SerializeDeviceInfoToTmpFile(deviceInfo, deviceInfoPath); + + m_fzData.ParseDeviceInfoFromTmpFile(deviceInfoPath); + std::filesystem::remove(deviceInfoPath); + } + + const std::wstring uuid = L"{33A2B101-06E0-437B-A61E-CDBECF502906}"; + const GridLayoutInfo grid(GridLayoutInfo(JSONHelpers::GridLayoutInfo::Full{ + .rows = 1, + .columns = 3, + .rowsPercents = { 10000 }, + .columnsPercents = { 2500, 5000, 2500 }, + .cellChildMap = { { 0, 1, 2 } } })); + CustomZoneSetJSON expected{ uuid, CustomZoneSetData{ L"name", CustomLayoutType::Grid, grid } }; + + FancyZonesData data; + const std::wstring path = data.GetPersistFancyZonesJSONPath() + L".test_tmp"; + json::to_file(path, CustomZoneSetJSON::ToJson(expected)); + m_fzData.ParseCustomZoneSetFromTmpFile(path); + + bool actualFileExists = std::filesystem::exists(path); + if (actualFileExists) + { + std::filesystem::remove(path); //clean up before compare asserts + } + Assert::IsFalse(actualFileExists); + + auto devices = m_fzData.GetCustomZoneSetsMap(); + Assert::AreEqual((size_t)1, devices.size()); + + auto actual = devices.find(uuid)->second; + Assert::AreEqual((int)expected.data.type, (int)actual.type); + Assert::AreEqual(expected.data.name.c_str(), actual.name.c_str()); + auto expectedGrid = std::get(expected.data.info); + auto actualGrid = std::get(actual.info); + Assert::AreEqual(expectedGrid.rows(), actualGrid.rows()); + Assert::AreEqual(expectedGrid.columns(), actualGrid.columns()); + } + + TEST_METHOD (CustomZoneSetsReadTempUnexsisted) + { + const std::wstring path = m_fzData.GetPersistFancyZonesJSONPath() + L".test_tmp"; + const std::wstring deviceId = L"default_device_id"; + + m_fzData.ParseCustomZoneSetFromTmpFile(path); + auto devices = m_fzData.GetDeviceInfoMap(); + Assert::AreEqual((size_t)0, devices.size()); + } + + TEST_METHOD (SetActiveZoneSet) + { + FancyZonesData data; + const std::wstring uniqueId = m_defaultDeviceId; + + json::JsonArray devices; + devices.Append(m_defaultCustomDeviceValue); + json::JsonObject json; + json.SetNamedValue(L"devices", devices); + data.ParseDeviceInfos(json); + + JSONHelpers::ZoneSetData expectedZoneSetData{ + .uuid = L"{33A2B101-06E0-437B-A61E-CDBECF502906}", + .type = ZoneSetLayoutType::Focus + }; + + data.SetActiveZoneSet(uniqueId, expectedZoneSetData); + + auto actual = data.GetDeviceInfoMap().find(uniqueId)->second; + Assert::AreEqual(expectedZoneSetData.uuid.c_str(), actual.activeZoneSet.uuid.c_str()); + Assert::IsTrue(expectedZoneSetData.type == actual.activeZoneSet.type); + } + + TEST_METHOD (SetActiveZoneSetUuidEmpty) + { + FancyZonesData data; + const std::wstring expected = L"{39B25DD2-130D-4B5D-8851-4791D66B1539}"; + const std::wstring uniqueId = m_defaultDeviceId; + + json::JsonArray devices; + devices.Append(m_defaultCustomDeviceValue); + json::JsonObject json; + json.SetNamedValue(L"devices", devices); + data.ParseDeviceInfos(json); + + JSONHelpers::ZoneSetData expectedZoneSetData{ + .uuid = L"", + .type = ZoneSetLayoutType::Focus + }; + + data.SetActiveZoneSet(uniqueId, expectedZoneSetData); + + auto actual = data.GetDeviceInfoMap().find(uniqueId)->second; + Assert::AreEqual(expectedZoneSetData.uuid.c_str(), actual.activeZoneSet.uuid.c_str()); + Assert::IsTrue(expectedZoneSetData.type == actual.activeZoneSet.type); + } + + TEST_METHOD (SetActiveZoneSetUniqueIdInvalid) + { + FancyZonesData data; + const std::wstring expected = L"{33A2B101-06E0-437B-A61E-CDBECF502906}"; + const std::wstring uniqueId = L"id-not-contained-by-device-info-map_1920_1200_{39B25DD2-130D-4B5D-8851-4791D66B1539}"; + + json::JsonArray devices; + devices.Append(m_defaultCustomDeviceValue); + json::JsonObject json; + json.SetNamedValue(L"devices", devices); + bool parseRes = data.ParseDeviceInfos(json); + Assert::IsTrue(parseRes); + + JSONHelpers::ZoneSetData zoneSetData{ + .uuid = L"new_uuid", + .type = ZoneSetLayoutType::Focus + }; + + data.SetActiveZoneSet(uniqueId, zoneSetData); + + const auto& deviceInfoMap = data.GetDeviceInfoMap(); + auto actual = deviceInfoMap.find(m_defaultDeviceId)->second; + Assert::AreEqual(expected.c_str(), actual.activeZoneSet.uuid.c_str()); + Assert::IsTrue(deviceInfoMap.end() == deviceInfoMap.find(uniqueId), L"new device info should not be added"); + } + + TEST_METHOD (LoadFancyZonesDataFromJson) + { + FancyZonesData data; + const auto jsonPath = data.GetPersistFancyZonesJSONPath(); + auto savedJson = json::from_file(jsonPath); + + if (std::filesystem::exists(jsonPath)) + { + std::filesystem::remove(jsonPath); + } + + const GridLayoutInfo grid(GridLayoutInfo(JSONHelpers::GridLayoutInfo::Full{ + .rows = 1, + .columns = 3, + .rowsPercents = { 10000 }, + .columnsPercents = { 2500, 5000, 2500 }, + .cellChildMap = { { 0, 1, 2 } } })); + CustomZoneSetJSON zoneSets{ L"{33A2B101-06E0-437B-A61E-CDBECF502906}", CustomZoneSetData{ L"name", CustomLayoutType::Grid, grid } }; + AppZoneHistoryJSON appZoneHistory{ L"app-path", AppZoneHistoryData{ .zoneSetUuid = L"{33A2B101-06E0-437B-A61E-CDBECF502906}", .deviceId = L"device-id", .zoneIndex = 54321 } }; + DeviceInfoJSON deviceInfo{ L"{33A2B101-06E0-437B-A61E-CDBECF502906}", DeviceInfoData{ ZoneSetData{ L"uuid", ZoneSetLayoutType::Custom }, true, 16, 3 } }; + json::JsonArray zoneSetsArray, appZonesArray, deviceInfoArray; + zoneSetsArray.Append(CustomZoneSetJSON::ToJson(zoneSets)); + appZonesArray.Append(AppZoneHistoryJSON::ToJson(appZoneHistory)); + deviceInfoArray.Append(DeviceInfoJSON::ToJson(deviceInfo)); + json::JsonObject fancyZones; + fancyZones.SetNamedValue(L"custom-zone-sets", zoneSetsArray); + fancyZones.SetNamedValue(L"app-zone-history", appZonesArray); + fancyZones.SetNamedValue(L"devices", deviceInfoArray); + + json::to_file(jsonPath, fancyZones); + + data.LoadFancyZonesData(); + if (savedJson) + { + json::to_file(jsonPath, *savedJson); + } + else + { + std::filesystem::remove(jsonPath); + } + + Assert::IsFalse(data.GetCustomZoneSetsMap().empty()); + Assert::IsFalse(data.GetCustomZoneSetsMap().empty()); + Assert::IsFalse(data.GetCustomZoneSetsMap().empty()); + } + + TEST_METHOD (LoadFancyZonesDataFromCroppedJson) + { + FancyZonesData data; + const auto jsonPath = data.GetPersistFancyZonesJSONPath(); + auto savedJson = json::from_file(jsonPath); + + if (std::filesystem::exists(jsonPath)) + { + std::filesystem::remove(jsonPath); + } + + std::wofstream{ jsonPath.data(), std::ios::binary } << L"{ \"app-zone-history\": [], \"devices\": [{\"device-id\": \""; + + data.LoadFancyZonesData(); + + if (savedJson) + { + json::to_file(jsonPath, *savedJson); + } + else + { + std::filesystem::remove(jsonPath); + } + + Assert::IsTrue(data.GetCustomZoneSetsMap().empty()); + Assert::IsTrue(data.GetAppZoneHistoryMap().empty()); + Assert::IsTrue(data.GetDeviceInfoMap().empty()); + } + + TEST_METHOD (LoadFancyZonesDataFromJsonWithCyrillicSymbols) + { + FancyZonesData data; + const auto jsonPath = data.GetPersistFancyZonesJSONPath(); + auto savedJson = json::from_file(jsonPath); + + if (std::filesystem::exists(jsonPath)) + { + std::filesystem::remove(jsonPath); + } + + std::wofstream{ jsonPath.data(), std::ios::binary } << L"{ \"app-zone-history\": [], \"devices\": [{\"device-id\": \"кириллица\"}], \"custom-zone-sets\": []}"; + data.LoadFancyZonesData(); + + if (savedJson) + { + json::to_file(jsonPath, *savedJson); + } + else + { + std::filesystem::remove(jsonPath); + } + + Assert::IsTrue(data.GetCustomZoneSetsMap().empty()); + Assert::IsTrue(data.GetAppZoneHistoryMap().empty()); + Assert::IsTrue(data.GetDeviceInfoMap().empty()); + } + + TEST_METHOD (LoadFancyZonesDataFromJsonWithInvalidTypes) + { + FancyZonesData data; + const auto jsonPath = data.GetPersistFancyZonesJSONPath(); + auto savedJson = json::from_file(jsonPath); + + if (std::filesystem::exists(jsonPath)) + { + std::filesystem::remove(jsonPath); + } + + std::wofstream{ jsonPath.data(), std::ios::binary } << L"{ \"app-zone-history\": null, \"devices\": [{\"device-id\":\"AOC2460#4&fe3a015&0&UID65793_1920_1200_{39B25DD2-130D-4B5D-8851-4791D66B1539}\",\"active-zoneset\":{\"uuid\":\"{568EBC3A-C09C-483E-A64D-6F1F2AF4E48D}\",\"type\":\"columns\"},\"editor-show-spacing\":true,\"editor-spacing\":16,\"editor-zone-count\":3}], \"custom-zone-sets\": []}"; + data.LoadFancyZonesData(); + + if (savedJson) + { + json::to_file(jsonPath, *savedJson); + } + else + { + std::filesystem::remove(jsonPath); + } + + Assert::IsTrue(data.GetCustomZoneSetsMap().empty()); + Assert::IsTrue(data.GetAppZoneHistoryMap().empty()); + Assert::IsFalse(data.GetDeviceInfoMap().empty()); + } + + TEST_METHOD (LoadFancyZonesDataFromRegistry) + { + FancyZonesData data; + const auto jsonPath = data.GetPersistFancyZonesJSONPath(); + auto savedJson = json::from_file(jsonPath); + + if (std::filesystem::exists(jsonPath)) + { + std::filesystem::remove(jsonPath); + } + + data.LoadFancyZonesData(); + bool actual = std::filesystem::exists(jsonPath); + if (savedJson) + { + json::to_file(jsonPath, *savedJson); + } + else + { + std::filesystem::remove(jsonPath); + } + + Assert::IsTrue(actual); + } + + TEST_METHOD (SaveFancyZonesData) + { + FancyZonesData data; + const auto jsonPath = data.GetPersistFancyZonesJSONPath(); + auto savedJson = json::from_file(jsonPath); + + if (std::filesystem::exists(jsonPath)) + { + std::filesystem::remove(jsonPath); + } + + data.SaveFancyZonesData(); + bool actual = std::filesystem::exists(jsonPath); + + if (savedJson) + { + json::to_file(jsonPath, *savedJson); + } + else + { + std::filesystem::remove(jsonPath); + } + + Assert::IsTrue(actual); + } + + TEST_METHOD (AppLastZoneIndex) + { + const std::wstring deviceId = L"device-id"; + const std::wstring zoneSetId = L"zoneset-uuid"; + const auto window = Mocks::WindowCreate(m_hInst); + FancyZonesData data; + + Assert::AreEqual(-1, data.GetAppLastZoneIndex(window, deviceId, zoneSetId)); + + const int expectedZoneIndex = 10; + Assert::IsTrue(data.SetAppLastZone(window, deviceId, zoneSetId, expectedZoneIndex)); + Assert::AreEqual(expectedZoneIndex, data.GetAppLastZoneIndex(window, deviceId, zoneSetId)); + } + + TEST_METHOD (AppLastZoneIndexZero) + { + const std::wstring zoneSetId = L"zoneset-uuid"; + const std::wstring deviceId = L"device-id"; + const auto window = Mocks::WindowCreate(m_hInst); + FancyZonesData data; + + const int expectedZoneIndex = 0; + Assert::IsTrue(data.SetAppLastZone(window, deviceId, zoneSetId, expectedZoneIndex)); + Assert::AreEqual(expectedZoneIndex, data.GetAppLastZoneIndex(window, deviceId, zoneSetId)); + } + + TEST_METHOD (AppLastZoneIndexNegative) + { + const std::wstring zoneSetId = L"zoneset-uuid"; + const std::wstring deviceId = L"device-id"; + const auto window = Mocks::WindowCreate(m_hInst); + FancyZonesData data; + + const int expectedZoneIndex = -1; + Assert::IsTrue(data.SetAppLastZone(window, deviceId, zoneSetId, expectedZoneIndex)); + Assert::AreEqual(expectedZoneIndex, data.GetAppLastZoneIndex(window, deviceId, zoneSetId)); + } + + TEST_METHOD (AppLastZoneIndexOverflow) + { + const std::wstring zoneSetId = L"zoneset-uuid"; + const std::wstring deviceId = L"device-id"; + const auto window = Mocks::WindowCreate(m_hInst); + FancyZonesData data; + + const long expectedZoneIndex = LONG_MAX; + Assert::IsTrue(data.SetAppLastZone(window, deviceId, zoneSetId, expectedZoneIndex)); + Assert::AreEqual(static_cast(expectedZoneIndex), data.GetAppLastZoneIndex(window, deviceId, zoneSetId)); + } + + TEST_METHOD (AppLastZoneIndexOverride) + { + const std::wstring zoneSetId = L"zoneset-uuid"; + const std::wstring deviceId = L"device-id"; + const auto window = Mocks::WindowCreate(m_hInst); + FancyZonesData data; + + const int expectedZoneIndex = 3; + Assert::IsTrue(data.SetAppLastZone(window, deviceId, zoneSetId, 1)); + Assert::IsTrue(data.SetAppLastZone(window, deviceId, zoneSetId, 2)); + Assert::IsTrue(data.SetAppLastZone(window, deviceId, zoneSetId, expectedZoneIndex)); + Assert::AreEqual(expectedZoneIndex, data.GetAppLastZoneIndex(window, deviceId, zoneSetId)); + } + + TEST_METHOD (AppLastZoneInvalidWindow) + { + const std::wstring zoneSetId = L"zoneset-uuid"; + const std::wstring deviceId = L"device-id"; + const auto window = Mocks::Window(); + FancyZonesData data; + + Assert::AreEqual(-1, data.GetAppLastZoneIndex(window, deviceId, zoneSetId)); + + const int expectedZoneIndex = 1; + Assert::IsFalse(data.SetAppLastZone(window, deviceId, zoneSetId, expectedZoneIndex)); + } + + TEST_METHOD (AppLastZoneNullWindow) + { + const std::wstring zoneSetId = L"zoneset-uuid"; + const auto window = nullptr; + FancyZonesData data; + + const int expectedZoneIndex = 1; + Assert::IsFalse(data.SetAppLastZone(window, L"device-id", zoneSetId, expectedZoneIndex)); + } + + TEST_METHOD (AppLastdeviceIdTest) + { + const std::wstring zoneSetId = L"zoneset-uuid"; + const std::wstring deviceId1 = L"device-id-1"; + const std::wstring deviceId2 = L"device-id-2"; + const auto window = Mocks::WindowCreate(m_hInst); + FancyZonesData data; + + const int expectedZoneIndex = 10; + Assert::IsTrue(data.SetAppLastZone(window, deviceId1, zoneSetId, expectedZoneIndex)); + Assert::AreEqual(expectedZoneIndex, data.GetAppLastZoneIndex(window, deviceId1, zoneSetId)); + Assert::AreEqual(-1, data.GetAppLastZoneIndex(window, deviceId2, zoneSetId)); + } + + TEST_METHOD (AppLastZoneSetIdTest) + { + const std::wstring zoneSetId1 = L"zoneset-uuid-1"; + const std::wstring zoneSetId2 = L"zoneset-uuid-2"; + const std::wstring deviceId = L"device-id"; + const auto window = Mocks::WindowCreate(m_hInst); + FancyZonesData data; + + const int expectedZoneIndex = 10; + Assert::IsTrue(data.SetAppLastZone(window, deviceId, zoneSetId1, expectedZoneIndex)); + Assert::AreEqual(expectedZoneIndex, data.GetAppLastZoneIndex(window, deviceId, zoneSetId1)); + Assert::AreEqual(-1, data.GetAppLastZoneIndex(window, deviceId, zoneSetId2)); + } + + TEST_METHOD (AppLastZoneRemoveWindow) + { + const std::wstring zoneSetId = L"zoneset-uuid"; + const std::wstring deviceId = L"device-id"; + const auto window = Mocks::WindowCreate(m_hInst); + FancyZonesData data; + + Assert::IsTrue(data.SetAppLastZone(window, deviceId, zoneSetId, 1)); + Assert::IsTrue(data.RemoveAppLastZone(window, deviceId, zoneSetId)); + Assert::AreEqual(-1, data.GetAppLastZoneIndex(window, deviceId, zoneSetId)); + } + + TEST_METHOD (AppLastZoneRemoveUnknownWindow) + { + const std::wstring zoneSetId = L"zoneset-uuid"; + const std::wstring deviceId = L"device-id"; + const auto window = Mocks::WindowCreate(m_hInst); + FancyZonesData data; + + Assert::IsFalse(data.RemoveAppLastZone(window, deviceId, zoneSetId)); + Assert::AreEqual(-1, data.GetAppLastZoneIndex(window, deviceId, zoneSetId)); + } + + TEST_METHOD (AppLastZoneRemoveUnknownZoneSetId) + { + const std::wstring zoneSetIdToInsert = L"zoneset-uuid-to-insert"; + const std::wstring zoneSetIdToRemove = L"zoneset-uuid-to-remove"; + const std::wstring deviceId = L"device-id"; + const auto window = Mocks::WindowCreate(m_hInst); + FancyZonesData data; + + Assert::IsTrue(data.SetAppLastZone(window, deviceId, zoneSetIdToInsert, 1)); + Assert::IsFalse(data.RemoveAppLastZone(window, deviceId, zoneSetIdToRemove)); + Assert::AreEqual(1, data.GetAppLastZoneIndex(window, deviceId, zoneSetIdToInsert)); + } + + TEST_METHOD (AppLastZoneRemoveUnknownWindowId) + { + const std::wstring zoneSetId = L"zoneset-uuid"; + const std::wstring deviceIdToInsert = L"device-id-insert"; + const std::wstring deviceIdToRemove = L"device-id-remove"; + const auto window = Mocks::WindowCreate(m_hInst); + FancyZonesData data; + + Assert::IsTrue(data.SetAppLastZone(window, deviceIdToInsert, zoneSetId, 1)); + Assert::IsFalse(data.RemoveAppLastZone(window, deviceIdToRemove, zoneSetId)); + Assert::AreEqual(1, data.GetAppLastZoneIndex(window, deviceIdToInsert, zoneSetId)); + } + + TEST_METHOD (AppLastZoneRemoveNullWindow) + { + const std::wstring zoneSetId = L"zoneset-uuid"; + const std::wstring deviceId = L"device-id"; + const auto window = Mocks::WindowCreate(m_hInst); + FancyZonesData data; + + Assert::IsFalse(data.RemoveAppLastZone(nullptr, deviceId, zoneSetId)); + } + }; } \ No newline at end of file diff --git a/src/modules/fancyzones/tests/UnitTests/Util.cpp b/src/modules/fancyzones/tests/UnitTests/Util.cpp index b0657288d6..4d302fdb8a 100644 --- a/src/modules/fancyzones/tests/UnitTests/Util.cpp +++ b/src/modules/fancyzones/tests/UnitTests/Util.cpp @@ -146,4 +146,28 @@ namespace Mocks m_conditionVar.notify_one(); } -} \ No newline at end of file +} + +std::wstring Helpers::GuidToString(const GUID& guid) +{ + OLECHAR* guidString; + if (StringFromCLSID(guid, &guidString) == S_OK) + { + std::wstring guidStr{ guidString }; + CoTaskMemFree(guidString); + return guidStr; + } + + return L""; +} + +std::wstring Helpers::CreateGuidString() +{ + GUID guid; + if (CoCreateGuid(&guid) == S_OK) + { + return GuidToString(guid); + } + + return L""; +} diff --git a/src/modules/fancyzones/tests/UnitTests/Util.h b/src/modules/fancyzones/tests/UnitTests/Util.h index b66e51381e..fa55b301e1 100644 --- a/src/modules/fancyzones/tests/UnitTests/Util.h +++ b/src/modules/fancyzones/tests/UnitTests/Util.h @@ -43,3 +43,9 @@ namespace Mocks HWND WindowCreate(HINSTANCE hInst); } + +namespace Helpers +{ + std::wstring GuidToString(const GUID& guid); + std::wstring CreateGuidString(); +} \ No newline at end of file diff --git a/src/modules/fancyzones/tests/UnitTests/ZoneWindow.Spec.cpp b/src/modules/fancyzones/tests/UnitTests/ZoneWindow.Spec.cpp index 0842152e29..9d3eb3b752 100644 --- a/src/modules/fancyzones/tests/UnitTests/ZoneWindow.Spec.cpp +++ b/src/modules/fancyzones/tests/UnitTests/ZoneWindow.Spec.cpp @@ -52,25 +52,6 @@ namespace FancyZonesUnitTests JSONHelpers::FancyZonesData& m_fancyZonesData = JSONHelpers::FancyZonesDataInstance(); - std::wstring GuidString(const GUID& guid) - { - OLECHAR* guidString; - Assert::AreEqual(S_OK, StringFromCLSID(guid, &guidString)); - - std::wstring guidStr{ guidString }; - CoTaskMemFree(guidString); - - return guidStr; - } - - std::wstring CreateGuidString() - { - GUID guid; - Assert::AreEqual(S_OK, CoCreateGuid(&guid)); - - return GuidString(guid); - } - TEST_METHOD_INITIALIZE(Init) { m_hInst = (HINSTANCE)GetModuleHandleW(nullptr); @@ -79,7 +60,7 @@ namespace FancyZonesUnitTests m_monitorInfo.cbSize = sizeof(m_monitorInfo); Assert::AreNotEqual(0, GetMonitorInfoW(m_monitor, &m_monitorInfo)); - m_uniqueId << L"DELA026#5&10a58c63&0&UID16777488_" << m_monitorInfo.rcMonitor.right << "_" << m_monitorInfo.rcMonitor.bottom << "_MyVirtualDesktopId"; + m_uniqueId << L"DELA026#5&10a58c63&0&UID16777488_" << m_monitorInfo.rcMonitor.right << "_" << m_monitorInfo.rcMonitor.bottom << "_{39B25DD2-130D-4B5D-8851-4791D66B1539}"; Assert::IsFalse(ZoneWindowUtils::GetActiveZoneSetTmpPath().empty()); Assert::IsFalse(ZoneWindowUtils::GetAppliedZoneSetTmpPath().empty()); @@ -108,7 +89,7 @@ namespace FancyZonesUnitTests Assert::IsFalse(std::filesystem::exists(activeZoneSetTempPath)); const auto type = JSONHelpers::ZoneSetLayoutType::Columns; - const auto expectedZoneSet = JSONHelpers::ZoneSetData{ CreateGuidString(), type }; + const auto expectedZoneSet = JSONHelpers::ZoneSetData{ Helpers::CreateGuidString(), type }; const auto data = JSONHelpers::DeviceInfoData{ expectedZoneSet, true, 16, 3 }; const auto deviceInfo = JSONHelpers::DeviceInfoJSON{ m_uniqueId.str(), data }; const auto json = JSONHelpers::DeviceInfoJSON::ToJson(deviceInfo); @@ -208,7 +189,7 @@ namespace FancyZonesUnitTests for (int type = static_cast(ZoneSetLayoutType::Focus); type < static_cast(ZoneSetLayoutType::Custom); type++) { - const auto expectedZoneSet = ZoneSetData{ CreateGuidString(), static_cast(type) }; + const auto expectedZoneSet = ZoneSetData{ Helpers::CreateGuidString(), static_cast(type) }; const auto data = DeviceInfoData{ expectedZoneSet, true, 16, 3 }; const auto deviceInfo = DeviceInfoJSON{ m_uniqueId.str(), data }; const auto json = DeviceInfoJSON::ToJson(deviceInfo); @@ -232,7 +213,7 @@ namespace FancyZonesUnitTests const auto activeZoneSetTempPath = ZoneWindowUtils::GetActiveZoneSetTmpPath(); const ZoneSetLayoutType type = ZoneSetLayoutType::Custom; - const auto expectedZoneSet = ZoneSetData{ CreateGuidString(), type }; + const auto expectedZoneSet = ZoneSetData{ Helpers::CreateGuidString(), type }; const auto data = DeviceInfoData{ expectedZoneSet, true, 16, 3 }; const auto deviceInfo = DeviceInfoJSON{ m_uniqueId.str(), data }; const auto json = DeviceInfoJSON::ToJson(deviceInfo); @@ -260,7 +241,7 @@ namespace FancyZonesUnitTests const auto appliedZoneSetTempPath = ZoneWindowUtils::GetAppliedZoneSetTmpPath(); const ZoneSetLayoutType type = ZoneSetLayoutType::Custom; - const auto customSetGuid = CreateGuidString(); + const auto customSetGuid = Helpers::CreateGuidString(); const auto expectedZoneSet = ZoneSetData{ customSetGuid, type }; const auto data = DeviceInfoData{ expectedZoneSet, true, 16, 3 }; const auto deviceInfo = DeviceInfoJSON{ m_uniqueId.str(), data }; @@ -297,7 +278,7 @@ namespace FancyZonesUnitTests const auto deletedZonesTempPath = ZoneWindowUtils::GetCustomZoneSetsTmpPath(); const ZoneSetLayoutType type = ZoneSetLayoutType::Custom; - const auto customSetGuid = CreateGuidString(); + const auto customSetGuid = Helpers::CreateGuidString(); const auto expectedZoneSet = ZoneSetData{ customSetGuid, type }; const auto data = DeviceInfoData{ expectedZoneSet, true, 16, 3 }; const auto deviceInfo = DeviceInfoJSON{ m_uniqueId.str(), data }; @@ -343,7 +324,7 @@ namespace FancyZonesUnitTests const auto deletedZonesTempPath = ZoneWindowUtils::GetCustomZoneSetsTmpPath(); const ZoneSetLayoutType type = ZoneSetLayoutType::Custom; - const auto customSetGuid = CreateGuidString(); + const auto customSetGuid = Helpers::CreateGuidString(); const auto expectedZoneSet = ZoneSetData{ customSetGuid, type }; const auto data = DeviceInfoData{ expectedZoneSet, true, 16, 3 }; const auto deviceInfo = DeviceInfoJSON{ m_uniqueId.str(), data }; @@ -361,7 +342,7 @@ namespace FancyZonesUnitTests //save different zone as deleted json::JsonObject deletedCustomZoneSets = {}; json::JsonArray zonesArray{}; - const auto uuid = CreateGuidString(); + const auto uuid = Helpers::CreateGuidString(); zonesArray.Append(json::JsonValue::CreateStringValue(uuid.substr(1, uuid.size() - 2).c_str())); deletedCustomZoneSets.SetNamedValue(L"deleted-custom-zone-sets", zonesArray); json::to_file(deletedZonesTempPath, deletedCustomZoneSets); @@ -614,7 +595,7 @@ namespace FancyZonesUnitTests const auto zoneSetId = m_zoneWindow->ActiveZoneSet()->Id(); //fill app zone history map - Assert::IsTrue(m_fancyZonesData.SetAppLastZone(window, deviceId, GuidString(zoneSetId), 0)); + Assert::IsTrue(m_fancyZonesData.SetAppLastZone(window, deviceId, Helpers::GuidToString(zoneSetId), 0)); Assert::AreEqual((size_t)1, m_fancyZonesData.GetAppZoneHistoryMap().size()); Assert::AreEqual(0, m_fancyZonesData.GetAppZoneHistoryMap().at(processPath).zoneIndex); @@ -642,7 +623,7 @@ namespace FancyZonesUnitTests m_zoneWindow->ActiveZoneSet()->AddZone(zone); //fill app zone history map - Assert::IsTrue(m_fancyZonesData.SetAppLastZone(window, deviceId, GuidString(zoneSetId), 2)); + Assert::IsTrue(m_fancyZonesData.SetAppLastZone(window, deviceId, Helpers::GuidToString(zoneSetId), 2)); Assert::AreEqual((size_t)1, m_fancyZonesData.GetAppZoneHistoryMap().size()); Assert::AreEqual(2, m_fancyZonesData.GetAppZoneHistoryMap().at(processPath).zoneIndex);