diff --git a/.clang-format b/.clang-format index 186eef0b02dc..059a3080d8f2 100644 --- a/.clang-format +++ b/.clang-format @@ -20,6 +20,7 @@ AlwaysBreakTemplateDeclarations: Yes BinPackArguments: false BinPackParameters: false BraceWrapping: + AfterCaseLabel: true AfterClass: true AfterControlStatement: true AfterEnum: true @@ -28,7 +29,7 @@ BraceWrapping: AfterObjCDeclaration: true AfterStruct: true AfterUnion: true - AfterExternBlock: false + AfterExternBlock: true BeforeCatch: true BeforeElse: true IndentBraces: false @@ -90,4 +91,4 @@ SpacesInParentheses: false SpacesInSquareBrackets: false Standard: Cpp11 TabWidth: 4 -UseTab: Never \ No newline at end of file +UseTab: Never diff --git a/src/modules/fancyzones/lib/FancyZones.cpp b/src/modules/fancyzones/lib/FancyZones.cpp index 1c8443fdb5f3..282c693284c3 100644 --- a/src/modules/fancyzones/lib/FancyZones.cpp +++ b/src/modules/fancyzones/lib/FancyZones.cpp @@ -47,28 +47,42 @@ struct FancyZones : public winrt::implementsGetSettings().zoneHightlightColor; @@ -78,7 +92,8 @@ struct FancyZones : public winrt::implementsGetSettings().zoneHighlightOpacity; } @@ -176,7 +192,8 @@ UINT FancyZones::WM_PRIV_VDINIT = RegisterWindowMessage(L"{469818a8-00fa-4069-b8 UINT FancyZones::WM_PRIV_EDITOR = RegisterWindowMessage(L"{87543824-7080-4e91-9d9c-0404642fc7b6}"); // IFancyZones -IFACEMETHODIMP_(void) FancyZones::Run() noexcept +IFACEMETHODIMP_(void) +FancyZones::Run() noexcept { std::unique_lock writeLock(m_lock); @@ -212,7 +229,8 @@ IFACEMETHODIMP_(void) FancyZones::Run() noexcept } // IFancyZones -IFACEMETHODIMP_(void) FancyZones::Destroy() noexcept +IFACEMETHODIMP_(void) +FancyZones::Destroy() noexcept { std::unique_lock writeLock(m_lock); m_zoneWindowMap.clear(); @@ -234,7 +252,8 @@ IFACEMETHODIMP_(void) FancyZones::Destroy() noexcept } // IFancyZonesCallback -IFACEMETHODIMP_(void) FancyZones::MoveSizeStart(HWND window, HMONITOR monitor, POINT const& ptScreen) noexcept +IFACEMETHODIMP_(void) +FancyZones::MoveSizeStart(HWND window, HMONITOR monitor, POINT const& ptScreen) noexcept { if (IsInterestingWindow(window)) { @@ -244,14 +263,16 @@ IFACEMETHODIMP_(void) FancyZones::MoveSizeStart(HWND window, HMONITOR monitor, P } // IFancyZonesCallback -IFACEMETHODIMP_(void) FancyZones::MoveSizeUpdate(HMONITOR monitor, POINT const& ptScreen) noexcept +IFACEMETHODIMP_(void) +FancyZones::MoveSizeUpdate(HMONITOR monitor, POINT const& ptScreen) noexcept { std::unique_lock writeLock(m_lock); MoveSizeUpdateInternal(monitor, ptScreen, writeLock); } // IFancyZonesCallback -IFACEMETHODIMP_(void) FancyZones::MoveSizeEnd(HWND window, POINT const& ptScreen) noexcept +IFACEMETHODIMP_(void) +FancyZones::MoveSizeEnd(HWND window, POINT const& ptScreen) noexcept { if (window == m_windowMoveSize || IsInterestingWindow(window)) { @@ -261,7 +282,8 @@ IFACEMETHODIMP_(void) FancyZones::MoveSizeEnd(HWND window, POINT const& ptScreen } // IFancyZonesCallback -IFACEMETHODIMP_(void) FancyZones::VirtualDesktopChanged() noexcept +IFACEMETHODIMP_(void) +FancyZones::VirtualDesktopChanged() noexcept { // VirtualDesktopChanged is called from another thread but results in new windows being created. // Jump over to the UI thread to handle it. @@ -270,13 +292,15 @@ IFACEMETHODIMP_(void) FancyZones::VirtualDesktopChanged() noexcept } // IFancyZonesCallback -IFACEMETHODIMP_(void) FancyZones::VirtualDesktopInitialize() noexcept +IFACEMETHODIMP_(void) +FancyZones::VirtualDesktopInitialize() noexcept { PostMessage(m_window, WM_PRIV_VDINIT, 0, 0); } // IFancyZonesCallback -IFACEMETHODIMP_(void) FancyZones::WindowCreated(HWND window) noexcept +IFACEMETHODIMP_(void) +FancyZones::WindowCreated(HWND window) noexcept { if (m_settings->GetSettings().appLastZone_moveWindows && IsInterestingWindow(window)) { @@ -308,7 +332,8 @@ IFACEMETHODIMP_(void) FancyZones::WindowCreated(HWND window) noexcept } // IFancyZonesCallback -IFACEMETHODIMP_(bool) FancyZones::OnKeyDown(PKBDLLHOOKSTRUCT info) noexcept +IFACEMETHODIMP_(bool) +FancyZones::OnKeyDown(PKBDLLHOOKSTRUCT info) noexcept { // Return true to swallow the keyboard event bool const shift = GetAsyncKeyState(VK_SHIFT) & 0x8000; @@ -430,9 +455,13 @@ void FancyZones::ToggleEditor() noexcept std::to_wstring(width) + L"_" + std::to_wstring(height); - const auto& deviceInfo = fancyZonesData.GetDeviceInfoMap().at(zoneWindow->UniqueId()); + const auto deviceInfo = fancyZonesData.FindDeviceInfo(zoneWindow->UniqueId()); + if (!deviceInfo.has_value()) + { + return; + } - JSONHelpers::DeviceInfoJSON deviceInfoJson{ zoneWindow->UniqueId(), deviceInfo }; + JSONHelpers::DeviceInfoJSON deviceInfoJson{ zoneWindow->UniqueId(), *deviceInfo }; fancyZonesData.SerializeDeviceInfoToTmpFile(deviceInfoJson, ZoneWindowUtils::GetActiveZoneSetTmpPath()); const std::wstring params = @@ -484,7 +513,8 @@ void FancyZones::SettingsChanged() noexcept } // IZoneWindowHost -IFACEMETHODIMP_(void) FancyZones::MoveWindowsOnActiveZoneSetChange() noexcept +IFACEMETHODIMP_(void) +FancyZones::MoveWindowsOnActiveZoneSetChange() noexcept { if (m_settings->GetSettings().zoneSetChange_moveWindows) { @@ -566,7 +596,7 @@ void FancyZones::OnDisplayChange(DisplayChangeType changeType) noexcept GUID currentVirtualDesktopId{}; if (SUCCEEDED(RegistryHelpers::GetCurrentVirtualDesktop(¤tVirtualDesktopId))) { - std::unique_lock writeLock(m_lock); + std::unique_lock writeLock(m_lock); m_currentVirtualDesktopId = currentVirtualDesktopId; } else diff --git a/src/modules/fancyzones/lib/JsonHelpers.cpp b/src/modules/fancyzones/lib/JsonHelpers.cpp index 790befc6128b..ca9516243921 100644 --- a/src/modules/fancyzones/lib/JsonHelpers.cpp +++ b/src/modules/fancyzones/lib/JsonHelpers.cpp @@ -135,13 +135,10 @@ namespace JSONHelpers jsonFilePath = result + L"\\" + std::wstring(FANCY_ZONES_DATA_FILE); } - const std::wstring& FancyZonesData::GetPersistFancyZonesJSONPath() const - { - return jsonFilePath; - } - json::JsonObject FancyZonesData::GetPersistFancyZonesJSON() { + std::scoped_lock lock{ dataLock }; + std::wstring save_file_path = GetPersistFancyZonesJSONPath(); auto result = json::from_file(save_file_path); @@ -155,12 +152,27 @@ namespace JSONHelpers } } + std::optional FancyZonesData::FindDeviceInfo(const std::wstring& zoneWindowId) const + { + std::scoped_lock lock{ dataLock }; + auto it = deviceInfoMap.find(zoneWindowId); + return it != end(deviceInfoMap) ? std::optional{ it->second } : std::nullopt; + } + + std::optional FancyZonesData::FindCustomZoneSet(const std::wstring& guuid) const + { + std::scoped_lock lock{ dataLock }; + auto it = customZoneSetsMap.find(guuid); + return it != end(customZoneSetsMap) ? std::optional{ it->second } : std::nullopt; + } + void FancyZonesData::AddDevice(const std::wstring& deviceId) { + std::scoped_lock lock{ dataLock }; if (!deviceInfoMap.contains(deviceId)) { // Creates default entry in map when ZoneWindow is created - deviceInfoMap[deviceId] = DeviceInfoData{ ZoneSetData{ L"null", ZoneSetLayoutType::Blank } }; + deviceInfoMap[deviceId] = DeviceInfoData{ ZoneSetData{ L"null", ZoneSetLayoutType::Blank } }; MigrateDeviceInfoFromRegistry(deviceId); } @@ -168,6 +180,7 @@ namespace JSONHelpers void FancyZonesData::CloneDeviceInfo(const std::wstring& source, const std::wstring& destination) { + std::scoped_lock lock{ dataLock }; // Clone information from source device if destination device is uninitialized (Blank). auto& destInfo = deviceInfoMap[destination]; if (destInfo.activeZoneSet.type == ZoneSetLayoutType::Blank) @@ -178,6 +191,7 @@ namespace JSONHelpers int FancyZonesData::GetAppLastZoneIndex(HWND window, const std::wstring_view& deviceId, const std::wstring_view& zoneSetId) const { + std::scoped_lock lock{ dataLock }; auto processPath = get_process_path(window); if (!processPath.empty()) { @@ -188,7 +202,7 @@ namespace JSONHelpers if (data.zoneSetUuid == zoneSetId && data.deviceId == deviceId) { return history->second.zoneIndex; - } + } } } @@ -197,6 +211,7 @@ namespace JSONHelpers bool FancyZonesData::RemoveAppLastZone(HWND window, const std::wstring_view& deviceId, const std::wstring_view& zoneSetId) { + std::scoped_lock lock{ dataLock }; auto processPath = get_process_path(window); if (!processPath.empty()) { @@ -218,6 +233,7 @@ namespace JSONHelpers bool FancyZonesData::SetAppLastZone(HWND window, const std::wstring& deviceId, const std::wstring& zoneSetId, int zoneIndex) { + std::scoped_lock lock{ dataLock }; auto processPath = get_process_path(window); if (processPath.empty()) { @@ -231,6 +247,7 @@ namespace JSONHelpers void FancyZonesData::SetActiveZoneSet(const std::wstring& deviceId, const ZoneSetData& data) { + std::scoped_lock lock{ dataLock }; auto it = deviceInfoMap.find(deviceId); if (it != deviceInfoMap.end()) { @@ -240,12 +257,14 @@ namespace JSONHelpers void FancyZonesData::SerializeDeviceInfoToTmpFile(const DeviceInfoJSON& deviceInfo, std::wstring_view tmpFilePath) const { + std::scoped_lock lock{ dataLock }; json::JsonObject deviceInfoJson = DeviceInfoJSON::ToJson(deviceInfo); json::to_file(tmpFilePath, deviceInfoJson); } void FancyZonesData::ParseDeviceInfoFromTmpFile(std::wstring_view tmpFilePath) { + std::scoped_lock lock{ dataLock }; if (std::filesystem::exists(tmpFilePath)) { if (auto zoneSetJson = json::from_file(tmpFilePath); zoneSetJson.has_value()) @@ -266,6 +285,7 @@ namespace JSONHelpers bool FancyZonesData::ParseCustomZoneSetFromTmpFile(std::wstring_view tmpFilePath) { + std::scoped_lock lock{ dataLock }; bool res = true; if (std::filesystem::exists(tmpFilePath)) { @@ -291,6 +311,7 @@ namespace JSONHelpers bool FancyZonesData::ParseDeletedCustomZoneSetsFromTmpFile(std::wstring_view tmpFilePath) { + std::scoped_lock lock{ dataLock }; bool res = true; if (std::filesystem::exists(tmpFilePath)) { @@ -317,6 +338,7 @@ namespace JSONHelpers bool FancyZonesData::ParseAppZoneHistory(const json::JsonObject& fancyZonesDataJSON) { + std::scoped_lock lock{ dataLock }; try { auto appLastZones = fancyZonesDataJSON.GetNamedArray(L"app-zone-history"); @@ -344,6 +366,7 @@ namespace JSONHelpers json::JsonArray FancyZonesData::SerializeAppZoneHistory() const { + std::scoped_lock lock{ dataLock }; json::JsonArray appHistoryArray; for (const auto& [appPath, appZoneHistoryData] : appZoneHistoryMap) @@ -356,6 +379,7 @@ namespace JSONHelpers bool FancyZonesData::ParseDeviceInfos(const json::JsonObject& fancyZonesDataJSON) { + std::scoped_lock lock{ dataLock }; try { auto devices = fancyZonesDataJSON.GetNamedArray(L"devices"); @@ -382,11 +406,13 @@ namespace JSONHelpers json::JsonArray FancyZonesData::SerializeDeviceInfos() const { + std::scoped_lock lock{ dataLock }; json::JsonArray DeviceInfosJSON{}; for (const auto& [deviceID, deviceData] : deviceInfoMap) { - if (deviceData.activeZoneSet.type != ZoneSetLayoutType::Blank) { + if (deviceData.activeZoneSet.type != ZoneSetLayoutType::Blank) + { DeviceInfosJSON.Append(DeviceInfoJSON::DeviceInfoJSON::ToJson(DeviceInfoJSON{ deviceID, deviceData })); } } @@ -396,6 +422,7 @@ namespace JSONHelpers bool FancyZonesData::ParseCustomZoneSets(const json::JsonObject& fancyZonesDataJSON) { + std::scoped_lock lock{ dataLock }; try { auto customZoneSets = fancyZonesDataJSON.GetNamedArray(L"custom-zone-sets"); @@ -418,6 +445,7 @@ namespace JSONHelpers json::JsonArray FancyZonesData::SerializeCustomZoneSets() const { + std::scoped_lock lock{ dataLock }; json::JsonArray customZoneSetsJSON{}; for (const auto& [zoneSetId, zoneSetData] : customZoneSetsMap) @@ -430,6 +458,7 @@ namespace JSONHelpers void FancyZonesData::CustomZoneSetsToJsonFile(std::wstring_view filePath) const { + std::scoped_lock lock{ dataLock }; const auto& customZoneSetsJson = SerializeCustomZoneSets(); json::JsonObject root{}; root.SetNamedValue(L"custom-zone-sets", customZoneSetsJson); @@ -438,6 +467,7 @@ namespace JSONHelpers void FancyZonesData::LoadFancyZonesData() { + std::scoped_lock lock{ dataLock }; std::wstring jsonFilePath = GetPersistFancyZonesJSONPath(); if (!std::filesystem::exists(jsonFilePath)) @@ -461,6 +491,7 @@ namespace JSONHelpers void FancyZonesData::SaveFancyZonesData() const { + std::scoped_lock lock{ dataLock }; json::JsonObject root{}; root.SetNamedValue(L"app-zone-history", SerializeAppZoneHistory()); @@ -474,6 +505,7 @@ namespace JSONHelpers { std::wregex ex(L"^[0-9]{3,4}_[0-9]{3,4}$"); + std::scoped_lock lock{ dataLock }; wchar_t key[256]; StringCchPrintf(key, ARRAYSIZE(key), L"%s", RegistryHelpers::REG_SETTINGS); HKEY hkey; @@ -521,6 +553,7 @@ namespace JSONHelpers void FancyZonesData::MigrateDeviceInfoFromRegistry(const std::wstring& deviceId) { + std::scoped_lock lock{ dataLock }; wchar_t key[256]; StringCchPrintf(key, ARRAYSIZE(key), L"%s\\%s", RegistryHelpers::REG_SETTINGS, deviceId.c_str()); @@ -546,6 +579,7 @@ namespace JSONHelpers void FancyZonesData::MigrateCustomZoneSetsFromRegistry() { + std::scoped_lock lock{ dataLock }; wchar_t key[256]; StringCchPrintf(key, ARRAYSIZE(key), L"%s\\%s", RegistryHelpers::REG_SETTINGS, L"Layouts"); HKEY hkey; @@ -574,8 +608,7 @@ namespace JSONHelpers } switch (zoneSetData.type) { - case CustomLayoutType::Grid: - { + case CustomLayoutType::Grid: { int j = 5; GridLayoutInfo zoneSetInfo(GridLayoutInfo::Minimal{ .rows = data[j++], .columns = data[j++] }); @@ -599,8 +632,7 @@ namespace JSONHelpers zoneSetData.info = zoneSetInfo; break; } - case CustomLayoutType::Canvas: - { + case CustomLayoutType::Canvas: { CanvasLayoutInfo info; int j = 5; @@ -880,8 +912,7 @@ namespace JSONHelpers result.SetNamedValue(L"name", json::value(customZoneSet.data.name)); switch (customZoneSet.data.type) { - case CustomLayoutType::Canvas: - { + case CustomLayoutType::Canvas: { result.SetNamedValue(L"type", json::value(L"canvas")); CanvasLayoutInfo info = std::get(customZoneSet.data.info); @@ -889,8 +920,7 @@ namespace JSONHelpers break; } - case CustomLayoutType::Grid: - { + case CustomLayoutType::Grid: { result.SetNamedValue(L"type", json::value(L"grid")); GridLayoutInfo gridInfo = std::get(customZoneSet.data.info); diff --git a/src/modules/fancyzones/lib/JsonHelpers.h b/src/modules/fancyzones/lib/JsonHelpers.h index 5ec6b461fbde..19feda4aebc6 100644 --- a/src/modules/fancyzones/lib/JsonHelpers.h +++ b/src/modules/fancyzones/lib/JsonHelpers.h @@ -2,6 +2,7 @@ #include #include +#include #include #include @@ -159,12 +160,28 @@ namespace JSONHelpers class FancyZonesData { + mutable std::recursive_mutex dataLock; + public: FancyZonesData(); - const std::wstring& GetPersistFancyZonesJSONPath() const; + inline const std::wstring& GetPersistFancyZonesJSONPath() const + { + return jsonFilePath; + } json::JsonObject GetPersistFancyZonesJSON(); + std::optional FindDeviceInfo(const std::wstring& zoneWindowId) const; + + std::optional FindCustomZoneSet(const std::wstring& guuid) const; + + inline const std::wstring GetActiveDeviceId() const + { + std::scoped_lock lock{ dataLock }; + return activeDeviceId; + } + +#if defined(UNIT_TESTS) inline const std::unordered_map& GetDeviceInfoMap() const { return deviceInfoMap; @@ -180,13 +197,19 @@ namespace JSONHelpers return appZoneHistoryMap; } - inline const std::wstring GetActiveDeviceId() const + inline void clear_data() { - return activeDeviceId; + appliedZoneSetsMap.clear(); + appZoneHistoryMap.clear(); + deviceInfoMap.clear(); + customZoneSetsMap.clear(); + activeDeviceId.clear(); } +#endif - void SetActiveDeviceId(const std::wstring& deviceId) + inline void SetActiveDeviceId(const std::wstring& deviceId) { + std::scoped_lock lock{ dataLock }; activeDeviceId = deviceId; } diff --git a/src/modules/fancyzones/lib/ZoneSet.cpp b/src/modules/fancyzones/lib/ZoneSet.cpp index cce49c61e36b..9faf0bdfca38 100644 --- a/src/modules/fancyzones/lib/ZoneSet.cpp +++ b/src/modules/fancyzones/lib/ZoneSet.cpp @@ -497,13 +497,15 @@ bool ZoneSet::CalculateCustomLayout(Rect workArea, int spacing) noexcept if (SUCCEEDED_LOG(StringFromCLSID(m_config.Id, &guuidStr))) { const std::wstring guuid = guuidStr.get(); - const auto& customZoneSets = JSONHelpers::FancyZonesDataInstance().GetCustomZoneSetsMap(); - if (!customZoneSets.contains(guuid)) + + const auto zoneSetSearchResult = JSONHelpers::FancyZonesDataInstance().FindCustomZoneSet(guuid); + + if (!zoneSetSearchResult.has_value()) { return false; } - const auto& zoneSet = customZoneSets.at(guuid); + const auto& zoneSet = *zoneSetSearchResult; if (zoneSet.type == JSONHelpers::CustomLayoutType::Canvas && std::holds_alternative(zoneSet.info)) { const auto& zoneSetInfo = std::get(zoneSet.info); diff --git a/src/modules/fancyzones/lib/ZoneWindow.cpp b/src/modules/fancyzones/lib/ZoneWindow.cpp index a70ffc5dfa1f..ca72839ac7b0 100644 --- a/src/modules/fancyzones/lib/ZoneWindow.cpp +++ b/src/modules/fancyzones/lib/ZoneWindow.cpp @@ -280,14 +280,22 @@ struct ZoneWindow : public winrt::implements IFACEMETHODIMP MoveSizeUpdate(POINT const& ptScreen, bool dragEnabled) noexcept; IFACEMETHODIMP MoveSizeEnd(HWND window, POINT const& ptScreen) noexcept; IFACEMETHODIMP MoveSizeCancel() noexcept; - IFACEMETHODIMP_(bool) IsDragEnabled() noexcept { return m_dragEnabled; } - IFACEMETHODIMP_(void) MoveWindowIntoZoneByIndex(HWND window, int index) noexcept; - IFACEMETHODIMP_(void) MoveWindowIntoZoneByDirection(HWND window, DWORD vkCode) noexcept; - IFACEMETHODIMP_(void) CycleActiveZoneSet(DWORD vkCode) noexcept; - IFACEMETHODIMP_(std::wstring) UniqueId() noexcept { return { m_uniqueId }; } - IFACEMETHODIMP_(std::wstring) WorkAreaKey() noexcept { return { m_workArea }; } - IFACEMETHODIMP_(void) SaveWindowProcessToZoneIndex(HWND window) noexcept; - IFACEMETHODIMP_(IZoneSet*) ActiveZoneSet() noexcept { return m_activeZoneSet.get(); } + IFACEMETHODIMP_(bool) + IsDragEnabled() noexcept { return m_dragEnabled; } + IFACEMETHODIMP_(void) + MoveWindowIntoZoneByIndex(HWND window, int index) noexcept; + IFACEMETHODIMP_(void) + MoveWindowIntoZoneByDirection(HWND window, DWORD vkCode) noexcept; + IFACEMETHODIMP_(void) + CycleActiveZoneSet(DWORD vkCode) noexcept; + IFACEMETHODIMP_(std::wstring) + UniqueId() noexcept { return { m_uniqueId }; } + IFACEMETHODIMP_(std::wstring) + WorkAreaKey() noexcept { return { m_workArea }; } + IFACEMETHODIMP_(void) + SaveWindowProcessToZoneIndex(HWND window) noexcept; + IFACEMETHODIMP_(IZoneSet*) + ActiveZoneSet() noexcept { return m_activeZoneSet.get(); } protected: static LRESULT CALLBACK s_WndProc(HWND window, UINT message, WPARAM wparam, LPARAM lparam) noexcept; @@ -559,15 +567,21 @@ void ZoneWindow::InitializeZoneSets(MONITORINFO const& mi) noexcept void ZoneWindow::CalculateZoneSet() noexcept { const auto& fancyZonesData = JSONHelpers::FancyZonesDataInstance(); - const auto& deviceInfoMap = fancyZonesData.GetDeviceInfoMap(); + const auto deviceInfoData = fancyZonesData.FindDeviceInfo(m_uniqueId); const auto& activeDeviceId = fancyZonesData.GetActiveDeviceId(); - const auto& activeZoneSet = deviceInfoMap.at(m_uniqueId).activeZoneSet; if (!activeDeviceId.empty() && activeDeviceId != m_uniqueId) { return; } + if (!deviceInfoData.has_value()) + { + return; + } + + const auto& activeZoneSet = deviceInfoData->activeZoneSet; + if (activeZoneSet.uuid.empty() || activeZoneSet.type == JSONHelpers::ZoneSetLayoutType::Blank) { return; @@ -585,9 +599,9 @@ void ZoneWindow::CalculateZoneSet() noexcept monitorInfo.cbSize = sizeof(monitorInfo); if (GetMonitorInfoW(m_monitor, &monitorInfo)) { - bool showSpacing = deviceInfoMap.at(m_uniqueId).showSpacing; - int spacing = showSpacing ? deviceInfoMap.at(m_uniqueId).spacing : 0; - int zoneCount = deviceInfoMap.at(m_uniqueId).zoneCount; + bool showSpacing = deviceInfoData->showSpacing; + int spacing = showSpacing ? deviceInfoData->spacing : 0; + int zoneCount = deviceInfoData->zoneCount; zoneSet->CalculateZones(monitorInfo, zoneCount, spacing); UpdateActiveZoneSet(zoneSet.get()); } diff --git a/src/modules/fancyzones/tests/UnitTests/FancyZones.Spec.cpp b/src/modules/fancyzones/tests/UnitTests/FancyZones.Spec.cpp index 07e2e78ef36e..8345437be753 100644 --- a/src/modules/fancyzones/tests/UnitTests/FancyZones.Spec.cpp +++ b/src/modules/fancyzones/tests/UnitTests/FancyZones.Spec.cpp @@ -290,7 +290,7 @@ namespace FancyZonesUnitTests m_fzCallback = fancyZones.as(); Assert::IsTrue(m_fzCallback != nullptr); - m_fancyZonesData = JSONHelpers::FancyZonesData(); + m_fancyZonesData.clear_data(); } TEST_METHOD_CLEANUP(Cleanup) diff --git a/src/modules/fancyzones/tests/UnitTests/JsonHelpers.Tests.cpp b/src/modules/fancyzones/tests/UnitTests/JsonHelpers.Tests.cpp index ce161a2c586d..ce76b56b4798 100644 --- a/src/modules/fancyzones/tests/UnitTests/JsonHelpers.Tests.cpp +++ b/src/modules/fancyzones/tests/UnitTests/JsonHelpers.Tests.cpp @@ -51,8 +51,7 @@ namespace FancyZonesUnitTests } } - TEST_CLASS(ZoneSetLayoutTypeUnitTest) - { + TEST_CLASS(ZoneSetLayoutTypeUnitTest){ TEST_METHOD(ZoneSetLayoutTypeToString){ std::map expectedMap = { std::make_pair(-2, L"TypeToString_ERROR"), @@ -66,1594 +65,1593 @@ 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); - } - } - - 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::TypeToString(static_cast(expected.first)); + Assert::AreEqual(expected.second, actual); + } +} - for (const auto& expected : expectedMap) - { - auto actual = JSONHelpers::TypeFromString(expected.second); - Assert::AreEqual(static_cast(expected.first), static_cast(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(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::TypeFromString(expected.second); + Assert::AreEqual(static_cast(expected.first), static_cast(actual)); + } +} - for (const auto& expected : expectedMap) - { - auto actual = JSONHelpers::TypeFromLayoutId(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), }; - TEST_CLASS(CanvasLayoutInfoUnitTests) + for (const auto& expected : expectedMap) { - 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 = JSONHelpers::TypeFromLayoutId(expected.second); + Assert::AreEqual(static_cast(expected.first), static_cast(actual)); + } +} +} +; - auto actual = CanvasLayoutInfo::ToJson(info); - compareJsonObjects(m_json, actual); - } +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(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(ToJson) + { + CanvasLayoutInfo info; + info.referenceWidth = 123; + info.referenceHeight = 321; + info.zones = { CanvasLayoutInfo::Rect{ 11, 22, 33, 44 }, CanvasLayoutInfo::Rect{ 55, 66, 77, 88 } }; - 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 actual = CanvasLayoutInfo::ToJson(info); + compareJsonObjects(m_json, actual); + } - auto iter = json.First(); - while (iter.HasCurrent()) - { - json::JsonObject modifiedJson = json::JsonObject::Parse(json.Stringify()); - modifiedJson.Remove(iter.Current().Key()); + 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(modifiedJson); - Assert::IsFalse(actual.has_value()); + auto actual = CanvasLayoutInfo::FromJson(m_json); + Assert::IsTrue(actual.has_value()); - iter.MoveNext(); - } + 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_CLASS(GridLayoutInfoUnitTests) + TEST_METHOD(FromJsonMissingKeys) { - 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; + CanvasLayoutInfo info{ 123, 321, { CanvasLayoutInfo::Rect{ 11, 22, 33, 44 }, CanvasLayoutInfo::Rect{ 55, 66, 77, 88 } } }; + const auto json = CanvasLayoutInfo::ToJson(info); - void compareSizes(int expectedRows, int expectedColumns, const GridLayoutInfo& actual) + auto iter = json.First(); + while (iter.HasCurrent()) { - 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()); + json::JsonObject modifiedJson = json::JsonObject::Parse(json.Stringify()); + modifiedJson.Remove(iter.Current().Key()); - for (int i = 0; i < expectedRows; i++) - { - Assert::AreEqual((size_t)expectedColumns, actual.cellChildMap()[i].size()); - } - } + auto actual = CanvasLayoutInfo::FromJson(modifiedJson); + Assert::IsFalse(actual.has_value()); - 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]); - } + iter.MoveNext(); } + } +}; - void compareGridInfos(const GridLayoutInfo& expected, const GridLayoutInfo& actual) - { - compareSizes(expected.rows(), expected.columns(), actual); +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; - 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]); - } - } + 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()); - TEST_METHOD_INITIALIZE(Init) + for (int i = 0; i < expectedRows; i++) { - 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); + Assert::AreEqual((size_t)expectedColumns, actual.cellChildMap()[i].size()); } + } - TEST_METHOD_CLEANUP(Cleanup) + void compareVectors(const std::vector& expected, const std::vector& actual) + { + Assert::AreEqual(expected.size(), actual.size()); + for (int i = 0; i < expected.size(); i++) { - m_rowsArray.Clear(); - m_cells.Clear(); - m_columnsArray.Clear(); - m_gridJson.Clear(); - m_info = GridLayoutInfo(GridLayoutInfo::Minimal{ .rows = 3, .columns = 4 }); + Assert::AreEqual(expected[i], actual[i]); } + } - public: - TEST_METHOD(CreationZero) - { - const int expectedRows = 0, expectedColumns = 0; - GridLayoutInfo info(GridLayoutInfo::Minimal{ .rows = expectedRows, .columns = expectedColumns }); - compareSizes(expectedRows, expectedColumns, info); - } + void compareGridInfos(const GridLayoutInfo& expected, const GridLayoutInfo& actual) + { + compareSizes(expected.rows(), expected.columns(), actual); - TEST_METHOD(Creation) + compareVectors(expected.rowsPercents(), actual.rowsPercents()); + compareVectors(expected.columnsPercents(), actual.columnsPercents()); + for (int i = 0; i < expected.cellChildMap().size(); i++) { - 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]); - } + compareVectors(expected.cellChildMap()[i], actual.cellChildMap()[i]); } + } - TEST_METHOD(CreationFull) + TEST_METHOD_INITIALIZE(Init) + { + m_info = GridLayoutInfo(GridLayoutInfo::Minimal{ .rows = 3, .columns = 4 }); + for (int i = 0; i < m_info.rows(); i++) { - 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]); - } + int row = rand() % 100; + m_rowsArray.Append(json::JsonValue::CreateNumberValue(row)); + m_info.rowsPercents()[i] = row; } - TEST_METHOD(CreationFullVectorsSmaller) + for (int i = 0; i < m_info.columns(); i++) { - 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]); - } + int column = rand() % 100; + m_columnsArray.Append(json::JsonValue::CreateNumberValue(column)); + m_info.columnsPercents()[i] = column; } - TEST_METHOD(CreationFullVectorsBigger) + for (int i = 0; i < m_info.rows(); i++) { - 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++) + json::JsonArray cellsArray; + for (int j = 0; j < m_info.columns(); j++) { - compareVectors(expectedCells[i], info.cellChildMap()[i]); + int cell = rand() % 100; + m_info.cellChildMap()[i][j] = cell; + cellsArray.Append(json::JsonValue::CreateNumberValue(cell)); } + m_cells.Append(cellsArray); } - TEST_METHOD(ToJson) - { - json::JsonObject expected = json::JsonObject(m_gridJson); - GridLayoutInfo info = m_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); + } - auto actual = GridLayoutInfo::ToJson(info); - compareJsonObjects(expected, actual); - } + 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(FromJson) - { - json::JsonObject json = json::JsonObject(m_gridJson); - GridLayoutInfo expected = m_info; +public: + TEST_METHOD(CreationZero) + { + const int expectedRows = 0, expectedColumns = 0; + GridLayoutInfo info(GridLayoutInfo::Minimal{ .rows = expectedRows, .columns = expectedColumns }); + compareSizes(expectedRows, expectedColumns, info); + } - auto actual = GridLayoutInfo::FromJson(json); - Assert::IsTrue(actual.has_value()); - compareGridInfos(expected, *actual); - } + TEST_METHOD(Creation) + { + const int expectedRows = 3, expectedColumns = 4; + const std::vector expectedRowsPercents = { 0, 0, 0 }; + const std::vector expectedColumnsPercents = { 0, 0, 0, 0 }; - TEST_METHOD(FromJsonEmptyArray) + 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++) { - json::JsonObject json = json::JsonObject::Parse(L"{\"rows\": 0, \"columns\": 0}"); - GridLayoutInfo expected(GridLayoutInfo::Minimal{ 0, 0 }); + compareVectors({ 0, 0, 0, 0 }, info.cellChildMap()[i]); + } + } - json.SetNamedValue(L"rows-percentage", json::JsonArray()); - json.SetNamedValue(L"columns-percentage", json::JsonArray()); - json.SetNamedValue(L"cell-child-map", json::JsonArray()); + 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 }; - auto actual = GridLayoutInfo::FromJson(json); - Assert::IsTrue(actual.has_value()); - compareGridInfos(expected, *actual); - } + GridLayoutInfo info(GridLayoutInfo::Full{ + .rows = expectedRows, + .columns = expectedColumns, + .rowsPercents = expectedRowsPercents, + .columnsPercents = expectedColumnsPercents, + .cellChildMap = expectedCells }); + compareSizes(expectedRows, expectedColumns, info); - TEST_METHOD(FromJsonSmallerArray) + compareVectors(expectedRowsPercents, info.rowsPercents()); + compareVectors(expectedColumnsPercents, info.columnsPercents()); + for (int i = 0; i < info.cellChildMap().size(); i++) { - 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()); + compareVectors(expectedCells[i], info.cellChildMap()[i]); } + } - TEST_METHOD(FromJsonBiggerArray) - { - GridLayoutInfo expected = m_info; + 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 } }; - //extra - for (int i = 0; i < 5; i++) - { - expected.rowsPercents().push_back(rand() % 100); - expected.columnsPercents().push_back(rand() % 100); - expected.cellChildMap().push_back({}); + GridLayoutInfo info(GridLayoutInfo::Full{ + .rows = expectedRows, + .columns = expectedColumns, + .rowsPercents = { 1, 2 }, + .columnsPercents = { 4, 3 }, + .cellChildMap = { {}, { 1 }, { 1, 2 } } }); + compareSizes(expectedRows, expectedColumns, info); - for (int j = 0; j < 5; j++) - { - expected.cellChildMap()[i].push_back(rand() % 100); - } - } + compareVectors(expectedRowsPercents, info.rowsPercents()); + compareVectors(expectedColumnsPercents, info.columnsPercents()); + for (int i = 0; i < info.cellChildMap().size(); i++) + { + compareVectors(expectedCells[i], info.cellChildMap()[i]); + } + } - auto json = GridLayoutInfo::ToJson(expected); + 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 }; - auto actual = GridLayoutInfo::FromJson(json); - Assert::IsFalse(actual.has_value()); - } + 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); - TEST_METHOD(FromJsonMissingKeys) + compareVectors(expectedRowsPercents, info.rowsPercents()); + compareVectors(expectedColumnsPercents, info.columnsPercents()); + for (int i = 0; i < info.cellChildMap().size(); i++) { - 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()); + compareVectors(expectedCells[i], info.cellChildMap()[i]); + } + } - auto actual = GridLayoutInfo::FromJson(modifiedJson); - Assert::IsFalse(actual.has_value()); + TEST_METHOD(ToJson) + { + json::JsonObject expected = json::JsonObject(m_gridJson); + GridLayoutInfo info = m_info; - iter.MoveNext(); - } - } - }; + auto actual = GridLayoutInfo::ToJson(info); + compareJsonObjects(expected, actual); + } - TEST_CLASS(CustomZoneSetUnitTests) + TEST_METHOD(FromJson) { - TEST_METHOD(ToJsonGrid) - { - CustomZoneSetJSON zoneSet{ L"uuid", CustomZoneSetData{ L"name", CustomLayoutType::Grid, GridLayoutInfo(GridLayoutInfo::Minimal{}) } }; + json::JsonObject json = json::JsonObject(m_gridJson); + GridLayoutInfo expected = m_info; - 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 = GridLayoutInfo::FromJson(json); + Assert::IsTrue(actual.has_value()); + compareGridInfos(expected, *actual); + } - auto actual = CustomZoneSetJSON::ToJson(zoneSet); - compareJsonObjects(expected, actual); - } + TEST_METHOD(FromJsonEmptyArray) + { + json::JsonObject json = json::JsonObject::Parse(L"{\"rows\": 0, \"columns\": 0}"); + GridLayoutInfo expected(GridLayoutInfo::Minimal{ 0, 0 }); - TEST_METHOD(ToJsonCanvas) - { - CustomZoneSetJSON zoneSet{ L"uuid", CustomZoneSetData{ L"name", CustomLayoutType::Canvas, CanvasLayoutInfo{} } }; + json.SetNamedValue(L"rows-percentage", json::JsonArray()); + json.SetNamedValue(L"columns-percentage", json::JsonArray()); + json.SetNamedValue(L"cell-child-map", json::JsonArray()); - 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 = GridLayoutInfo::FromJson(json); + Assert::IsTrue(actual.has_value()); + compareGridInfos(expected, *actual); + } - auto actual = CustomZoneSetJSON::ToJson(zoneSet); - compareJsonObjects(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; - TEST_METHOD(FromJsonGrid) + //extra + for (int i = 0; i < 5; i++) { - 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 } }; + expected.rowsPercents().push_back(rand() % 100); + expected.columnsPercents().push_back(rand() % 100); + expected.cellChildMap().push_back({}); - json::JsonObject json = json::JsonObject::Parse(L"{\"uuid\": \"uuid\", \"name\": \"name\", \"type\": \"grid\"}"); - json.SetNamedValue(L"info", GridLayoutInfo::ToJson(std::get(expected.data.info))); + for (int j = 0; j < 5; j++) + { + expected.cellChildMap()[i].push_back(rand() % 100); + } + } - auto actual = CustomZoneSetJSON::FromJson(json); - Assert::IsTrue(actual.has_value()); + auto json = GridLayoutInfo::ToJson(expected); - 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 actual = GridLayoutInfo::FromJson(json); + Assert::IsFalse(actual.has_value()); + } - 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(FromJsonMissingKeys) + { + GridLayoutInfo info = m_info; + const auto json = json::JsonObject(m_gridJson); - TEST_METHOD(FromJsonCanvas) + auto iter = json.First(); + while (iter.HasCurrent()) { - CustomZoneSetJSON expected{ L"uuid", CustomZoneSetData{ L"name", CustomLayoutType::Canvas, CanvasLayoutInfo{ 2, 1 } } }; + json::JsonObject modifiedJson = json::JsonObject::Parse(json.Stringify()); + modifiedJson.Remove(iter.Current().Key()); - 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 = GridLayoutInfo::FromJson(modifiedJson); + Assert::IsFalse(actual.has_value()); - auto actual = CustomZoneSetJSON::FromJson(json); - Assert::IsTrue(actual.has_value()); + iter.MoveNext(); + } + } +}; - 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); +TEST_CLASS(CustomZoneSetUnitTests){ + TEST_METHOD(ToJsonGrid){ + CustomZoneSetJSON zoneSet{ L"uuid", CustomZoneSetData{ L"name", CustomLayoutType::Grid, GridLayoutInfo(GridLayoutInfo::Minimal{}) } }; - 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); - } +json::JsonObject expected = json::JsonObject::Parse(L"{\"uuid\": \"uuid\", \"name\": \"name\", \"type\": \"grid\"}"); +expected.SetNamedValue(L"info", GridLayoutInfo::ToJson(std::get(zoneSet.data.info))); - TEST_METHOD(FromJsonMissingKeys) - { - CustomZoneSetJSON zoneSet{ L"uuid", CustomZoneSetData{ L"name", CustomLayoutType::Canvas, CanvasLayoutInfo{ 2, 1 } } }; - const auto json = CustomZoneSetJSON::ToJson(zoneSet); +auto actual = CustomZoneSetJSON::ToJson(zoneSet); +compareJsonObjects(expected, actual); +} - auto iter = json.First(); - while (iter.HasCurrent()) - { - json::JsonObject modifiedJson = json::JsonObject::Parse(json.Stringify()); - modifiedJson.Remove(iter.Current().Key()); +TEST_METHOD(ToJsonCanvas) +{ + CustomZoneSetJSON zoneSet{ L"uuid", CustomZoneSetData{ L"name", CustomLayoutType::Canvas, CanvasLayoutInfo{} } }; - auto actual = CustomZoneSetJSON::FromJson(modifiedJson); - Assert::IsFalse(actual.has_value()); + json::JsonObject expected = json::JsonObject::Parse(L"{\"uuid\": \"uuid\", \"name\": \"name\", \"type\": \"canvas\"}"); + expected.SetNamedValue(L"info", CanvasLayoutInfo::ToJson(std::get(zoneSet.data.info))); - iter.MoveNext(); - } - } - }; + auto actual = CustomZoneSetJSON::ToJson(zoneSet); + compareJsonObjects(expected, actual); +} - 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(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 } }; - TEST_METHOD(FromJsonGeneral) - { - ZoneSetData expected{ L"uuid", ZoneSetLayoutType::Columns }; + json::JsonObject json = json::JsonObject::Parse(L"{\"uuid\": \"uuid\", \"name\": \"name\", \"type\": \"grid\"}"); + json.SetNamedValue(L"info", GridLayoutInfo::ToJson(std::get(expected.data.info))); - json::JsonObject json = json::JsonObject::Parse(L"{\"uuid\": \"uuid\", \"type\": \"columns\"}"); - auto actual = ZoneSetData::FromJson(json); - Assert::IsTrue(actual.has_value()); + auto actual = CustomZoneSetJSON::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); - } + 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); - TEST_METHOD(FromJsonTypeInvalid) - { - ZoneSetData expected{ L"uuid", ZoneSetLayoutType::Blank }; + 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()); +} - json::JsonObject json = json::JsonObject::Parse(L"{\"uuid\": \"uuid\", \"type\": \"invalid_type\"}"); - auto actual = ZoneSetData::FromJson(json); - Assert::IsTrue(actual.has_value()); +TEST_METHOD(FromJsonCanvas) +{ + CustomZoneSetJSON expected{ L"uuid", CustomZoneSetData{ L"name", CustomLayoutType::Canvas, CanvasLayoutInfo{ 2, 1 } } }; - Assert::AreEqual(expected.uuid.c_str(), actual->uuid.c_str()); - Assert::AreEqual((int)expected.type, (int)actual->type); - } + json::JsonObject json = json::JsonObject::Parse(L"{\"uuid\": \"uuid\", \"name\": \"name\", \"type\": \"canvas\"}"); + json.SetNamedValue(L"info", CanvasLayoutInfo::ToJson(std::get(expected.data.info))); - TEST_METHOD(FromJsonMissingKeys) - { - ZoneSetData data{ L"uuid", ZoneSetLayoutType::Columns }; - const auto json = ZoneSetData::ToJson(data); + auto actual = CustomZoneSetJSON::FromJson(json); + Assert::IsTrue(actual.has_value()); - auto iter = json.First(); - while (iter.HasCurrent()) - { - json::JsonObject modifiedJson = json::JsonObject::Parse(json.Stringify()); - modifiedJson.Remove(iter.Current().Key()); + 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 actual = ZoneSetData::FromJson(modifiedJson); - Assert::IsFalse(actual.has_value()); + 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); +} - iter.MoveNext(); - } - } - }; +TEST_METHOD(FromJsonMissingKeys) +{ + CustomZoneSetJSON zoneSet{ L"uuid", CustomZoneSetData{ L"name", CustomLayoutType::Canvas, CanvasLayoutInfo{ 2, 1 } } }; + const auto json = CustomZoneSetJSON::ToJson(zoneSet); - TEST_CLASS(AppZoneHistoryUnitTests) + auto iter = json.First(); + while (iter.HasCurrent()) { - 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}"); + json::JsonObject modifiedJson = json::JsonObject::Parse(json.Stringify()); + modifiedJson.Remove(iter.Current().Key()); - auto actual = AppZoneHistoryJSON::ToJson(appZoneHistory); - compareJsonObjects(expected, actual); - } + auto actual = CustomZoneSetJSON::FromJson(modifiedJson); + Assert::IsFalse(actual.has_value()); - 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}"); + 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 }; - auto actual = AppZoneHistoryJSON::FromJson(json); - Assert::IsTrue(actual.has_value()); + json::JsonObject json = json::JsonObject::Parse(L"{\"uuid\": \"uuid\", \"type\": \"columns\"}"); + auto actual = ZoneSetData::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()); - } + Assert::AreEqual(expected.uuid.c_str(), actual->uuid.c_str()); + Assert::AreEqual((int)expected.type, (int)actual->type); +} - TEST_METHOD(FromJsonMissingKeys) - { - AppZoneHistoryJSON appZoneHistory{ L"appPath", AppZoneHistoryData{ .zoneSetUuid = L"zoneset-uuid", .deviceId = L"device-id", .zoneIndex = 54321 } }; - const auto json = AppZoneHistoryJSON::ToJson(appZoneHistory); +TEST_METHOD(FromJsonTypeInvalid) +{ + ZoneSetData expected{ L"uuid", ZoneSetLayoutType::Blank }; - auto iter = json.First(); - while (iter.HasCurrent()) - { - json::JsonObject modifiedJson = json::JsonObject::Parse(json.Stringify()); - modifiedJson.Remove(iter.Current().Key()); + json::JsonObject json = json::JsonObject::Parse(L"{\"uuid\": \"uuid\", \"type\": \"invalid_type\"}"); + auto actual = ZoneSetData::FromJson(json); + Assert::IsTrue(actual.has_value()); - auto actual = AppZoneHistoryJSON::FromJson(modifiedJson); - Assert::IsFalse(actual.has_value()); + Assert::AreEqual(expected.uuid.c_str(), actual->uuid.c_str()); + Assert::AreEqual((int)expected.type, (int)actual->type); +} - iter.MoveNext(); - } - } - }; +TEST_METHOD(FromJsonMissingKeys) +{ + ZoneSetData data{ L"uuid", ZoneSetLayoutType::Columns }; + const auto json = ZoneSetData::ToJson(data); - TEST_CLASS(DeviceInfoUnitTests) + auto iter = json.First(); + while (iter.HasCurrent()) { - 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}"); + json::JsonObject modifiedJson = json::JsonObject::Parse(json.Stringify()); + modifiedJson.Remove(iter.Current().Key()); - public: - TEST_METHOD(ToJson) - { - DeviceInfoJSON deviceInfo = m_defaultDeviceInfo; - json::JsonObject expected = m_defaultJson; + auto actual = ZoneSetData::FromJson(modifiedJson); + Assert::IsFalse(actual.has_value()); - auto actual = DeviceInfoJSON::ToJson(deviceInfo); - compareJsonObjects(expected, actual); - } - - TEST_METHOD(FromJson) - { - DeviceInfoJSON expected = m_defaultDeviceInfo; - expected.data.spacing = true; + iter.MoveNext(); + } +} +} +; - json::JsonObject json = DeviceInfoJSON::ToJson(expected); - auto actual = DeviceInfoJSON::FromJson(json); - Assert::IsTrue(actual.has_value()); +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}"); - 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"); - } +auto actual = AppZoneHistoryJSON::ToJson(appZoneHistory); +compareJsonObjects(expected, actual); +} - TEST_METHOD(FromJsonSpacingTrue) - { - DeviceInfoJSON expected = m_defaultDeviceInfo; - expected.data.spacing = true; +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}"); - json::JsonObject json = DeviceInfoJSON::ToJson(expected); - auto actual = DeviceInfoJSON::FromJson(json); - Assert::IsTrue(actual.has_value()); + auto actual = AppZoneHistoryJSON::FromJson(json); + Assert::IsTrue(actual.has_value()); - Assert::AreEqual(expected.data.spacing, actual->data.spacing); - } + 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(FromJsonSpacingFalse) - { - DeviceInfoJSON expected = m_defaultDeviceInfo; - expected.data.activeZoneSet.type = ZoneSetLayoutType::Custom; +TEST_METHOD(FromJsonMissingKeys) +{ + AppZoneHistoryJSON appZoneHistory{ L"appPath", AppZoneHistoryData{ .zoneSetUuid = L"zoneset-uuid", .deviceId = L"device-id", .zoneIndex = 54321 } }; + const auto json = AppZoneHistoryJSON::ToJson(appZoneHistory); - json::JsonObject json = DeviceInfoJSON::ToJson(expected); - auto actual = DeviceInfoJSON::FromJson(json); - Assert::IsTrue(actual.has_value()); + auto iter = json.First(); + while (iter.HasCurrent()) + { + json::JsonObject modifiedJson = json::JsonObject::Parse(json.Stringify()); + modifiedJson.Remove(iter.Current().Key()); - Assert::AreEqual(expected.data.spacing, actual->data.spacing); - } + auto actual = AppZoneHistoryJSON::FromJson(modifiedJson); + Assert::IsFalse(actual.has_value()); - TEST_METHOD(FromJsonZoneGeneral) - { - DeviceInfoJSON expected = m_defaultDeviceInfo; - expected.data.activeZoneSet.type = ZoneSetLayoutType::PriorityGrid; + iter.MoveNext(); + } +} +} +; - json::JsonObject json = DeviceInfoJSON::ToJson(expected); - auto actual = DeviceInfoJSON::FromJson(json); - Assert::IsTrue(actual.has_value()); +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}"); - Assert::AreEqual((int)expected.data.activeZoneSet.type, (int)actual->data.activeZoneSet.type, L"zone set type"); - } +public: + TEST_METHOD(ToJson) + { + DeviceInfoJSON deviceInfo = m_defaultDeviceInfo; + json::JsonObject expected = m_defaultJson; - 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 actual = DeviceInfoJSON::ToJson(deviceInfo); + compareJsonObjects(expected, actual); + } - auto iter = json.First(); - while (iter.HasCurrent()) - { - json::JsonObject modifiedJson = json::JsonObject::Parse(json.Stringify()); - modifiedJson.Remove(iter.Current().Key()); + TEST_METHOD(FromJson) + { + DeviceInfoJSON expected = m_defaultDeviceInfo; + expected.data.spacing = true; - auto actual = DeviceInfoJSON::FromJson(modifiedJson); - Assert::IsFalse(actual.has_value()); + json::JsonObject json = DeviceInfoJSON::ToJson(expected); + auto actual = DeviceInfoJSON::FromJson(json); + Assert::IsTrue(actual.has_value()); - iter.MoveNext(); - } - } - }; + 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_CLASS(FancyZonesDataUnitTests) + TEST_METHOD(FromJsonSpacingTrue) { - 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); + DeviceInfoJSON expected = m_defaultDeviceInfo; + expected.data.spacing = true; - HINSTANCE m_hInst{}; - FancyZonesData& m_fzData = FancyZonesDataInstance(); + json::JsonObject json = DeviceInfoJSON::ToJson(expected); + auto actual = DeviceInfoJSON::FromJson(json); + Assert::IsTrue(actual.has_value()); - 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)); - } - } + Assert::AreEqual(expected.data.spacing, actual->data.spacing); + } - TEST_METHOD_INITIALIZE(Init) - { - m_hInst = (HINSTANCE)GetModuleHandleW(nullptr); - m_fzData = FancyZonesData(); - } + TEST_METHOD(FromJsonSpacingFalse) + { + DeviceInfoJSON expected = m_defaultDeviceInfo; + expected.data.activeZoneSet.type = ZoneSetLayoutType::Custom; - public: - TEST_METHOD(FancyZonesDataPath) - { - FancyZonesData data; - Assert::IsFalse(data.GetPersistFancyZonesJSONPath().empty()); - } + json::JsonObject json = DeviceInfoJSON::ToJson(expected); + auto actual = DeviceInfoJSON::FromJson(json); + Assert::IsTrue(actual.has_value()); - TEST_METHOD(FancyZonesDataJsonEmpty) - { - FancyZonesData data; - const auto jsonPath = data.GetPersistFancyZonesJSONPath(); - auto savedJson = json::from_file(jsonPath); + Assert::AreEqual(expected.data.spacing, actual->data.spacing); + } - if (std::filesystem::exists(jsonPath)) - { - std::filesystem::remove(jsonPath); - } + TEST_METHOD(FromJsonZoneGeneral) + { + DeviceInfoJSON expected = m_defaultDeviceInfo; + expected.data.activeZoneSet.type = ZoneSetLayoutType::PriorityGrid; - json::JsonObject expected; - auto actual = data.GetPersistFancyZonesJSON(); + json::JsonObject json = DeviceInfoJSON::ToJson(expected); + auto actual = DeviceInfoJSON::FromJson(json); + Assert::IsTrue(actual.has_value()); - Assert::AreEqual(expected.Stringify().c_str(), actual.Stringify().c_str()); + Assert::AreEqual((int)expected.data.activeZoneSet.type, (int)actual->data.activeZoneSet.type, L"zone set type"); + } - if (savedJson) - { - json::to_file(jsonPath, *savedJson); - } - } + TEST_METHOD(FromJsonMissingKeys) + { + DeviceInfoJSON deviceInfo{ L"default_device_id", DeviceInfoData{ ZoneSetData{ L"uuid", ZoneSetLayoutType::Custom }, true, 16, 3 } }; + const auto json = DeviceInfoJSON::ToJson(deviceInfo); - TEST_METHOD(FancyZonesDataJson) + auto iter = json.First(); + while (iter.HasCurrent()) { - FancyZonesData data; - const auto jsonPath = data.GetPersistFancyZonesJSONPath(); - auto savedJson = json::from_file(jsonPath); + json::JsonObject modifiedJson = json::JsonObject::Parse(json.Stringify()); + modifiedJson.Remove(iter.Current().Key()); - if (std::filesystem::exists(jsonPath)) - { - std::filesystem::remove(jsonPath); - } + auto actual = DeviceInfoJSON::FromJson(modifiedJson); + Assert::IsFalse(actual.has_value()); - json::JsonObject expected = json::JsonObject::Parse(L"{\"fancy-zones\":{\"custom-zonesets \":[{\"uuid\":\"uuid1\",\"name\":\"Custom1\",\"type\":\"custom\" }] } }"); - json::to_file(jsonPath, expected); + iter.MoveNext(); + } + } +}; - auto actual = data.GetPersistFancyZonesJSON(); - Assert::AreEqual(expected.Stringify().c_str(), actual.Stringify().c_str()); +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); - if (savedJson) - { - json::to_file(jsonPath, *savedJson); - } - else - { - std::filesystem::remove(jsonPath); - } - } + HINSTANCE m_hInst{}; + FancyZonesData& m_fzData = FancyZonesDataInstance(); - TEST_METHOD(FancyZonesDataDeviceInfoMap) + 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++) { - FancyZonesData data; - const auto actual = data.GetDeviceInfoMap(); - Assert::IsTrue(actual.empty()); + compareJsonObjects(expected.GetObjectAt(i), actual.GetObjectAt(i)); } + } - TEST_METHOD(FancyZonesDataDeviceInfoMapParseEmpty) - { - FancyZonesData data; + TEST_METHOD_INITIALIZE(Init) + { + m_hInst = (HINSTANCE)GetModuleHandleW(nullptr); + m_fzData.clear_data(); + } - json::JsonObject json; - data.ParseDeviceInfos(json); +public: + TEST_METHOD(FancyZonesDataPath) + { + FancyZonesData data; + Assert::IsFalse(data.GetPersistFancyZonesJSONPath().empty()); + } - const auto actual = data.GetDeviceInfoMap(); - Assert::IsTrue(actual.empty()); - } + TEST_METHOD(FancyZonesDataJsonEmpty) + { + FancyZonesData data; + const auto jsonPath = data.GetPersistFancyZonesJSONPath(); + auto savedJson = json::from_file(jsonPath); - TEST_METHOD(FancyZonesDataDeviceInfoMapParseValidEmpty) + if (std::filesystem::exists(jsonPath)) { - FancyZonesData data; + std::filesystem::remove(jsonPath); + } - json::JsonObject expected; - json::JsonArray zoneSets; - expected.SetNamedValue(L"devices", zoneSets); + json::JsonObject expected; + auto actual = data.GetPersistFancyZonesJSON(); - data.ParseDeviceInfos(expected); + Assert::AreEqual(expected.Stringify().c_str(), actual.Stringify().c_str()); - const auto actual = data.GetDeviceInfoMap(); - Assert::IsTrue(actual.empty()); + if (savedJson) + { + json::to_file(jsonPath, *savedJson); } + } + + TEST_METHOD(FancyZonesDataJson) + { + FancyZonesData data; + const auto jsonPath = data.GetPersistFancyZonesJSONPath(); + auto savedJson = json::from_file(jsonPath); - TEST_METHOD(FancyZonesDataDeviceInfoMapParseInvalid) + if (std::filesystem::exists(jsonPath)) { - json::JsonArray devices; - devices.Append(json::JsonObject::Parse(m_defaultCustomDeviceStr)); - devices.Append(json::JsonObject::Parse(L"{\"device-id\": \"device_id\"}")); + std::filesystem::remove(jsonPath); + } - json::JsonObject expected; - expected.SetNamedValue(L"devices", devices); + json::JsonObject expected = json::JsonObject::Parse(L"{\"fancy-zones\":{\"custom-zonesets \":[{\"uuid\":\"uuid1\",\"name\":\"Custom1\",\"type\":\"custom\" }] } }"); + json::to_file(jsonPath, expected); - FancyZonesData data; - auto actual = data.ParseDeviceInfos(expected); + auto actual = data.GetPersistFancyZonesJSON(); + Assert::AreEqual(expected.Stringify().c_str(), actual.Stringify().c_str()); - Assert::IsFalse(actual); + if (savedJson) + { + json::to_file(jsonPath, *savedJson); } - - TEST_METHOD(FancyZonesDataDeviceInfoMapParseSingle) + else { - 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()); + std::filesystem::remove(jsonPath); } + } - 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))); + TEST_METHOD(FancyZonesDataDeviceInfoMap) + { + FancyZonesData data; + const auto actual = data.GetDeviceInfoMap(); + Assert::IsTrue(actual.empty()); + } - Logger::WriteMessage(obj.Stringify().c_str()); - Logger::WriteMessage("\n"); + TEST_METHOD(FancyZonesDataDeviceInfoMapParseEmpty) + { + FancyZonesData data; - devices.Append(obj); - } + json::JsonObject json; + data.ParseDeviceInfos(json); - json::JsonObject expected; - expected.SetNamedValue(L"devices", devices); - Logger::WriteMessage(expected.Stringify().c_str()); - Logger::WriteMessage("\n"); + const auto actual = data.GetDeviceInfoMap(); + Assert::IsTrue(actual.empty()); + } - FancyZonesData data; - data.ParseDeviceInfos(expected); + TEST_METHOD(FancyZonesDataDeviceInfoMapParseValidEmpty) + { + FancyZonesData data; - const auto actualMap = data.GetDeviceInfoMap(); - Assert::AreEqual((size_t)10, actualMap.size()); - } + json::JsonObject expected; + json::JsonArray zoneSets; + expected.SetNamedValue(L"devices", zoneSets); - TEST_METHOD(FancyZonesDataSerialize) - { - json::JsonArray expectedDevices; - expectedDevices.Append(m_defaultCustomDeviceObj); - json::JsonObject expected; - expected.SetNamedValue(L"devices", expectedDevices); + data.ParseDeviceInfos(expected); - FancyZonesData data; - data.ParseDeviceInfos(expected); + const auto actual = data.GetDeviceInfoMap(); + Assert::IsTrue(actual.empty()); + } - auto actual = data.SerializeDeviceInfos(); - compareJsonArrays(expectedDevices, actual); - } + TEST_METHOD(FancyZonesDataDeviceInfoMapParseInvalid) + { + json::JsonArray devices; + devices.Append(json::JsonObject::Parse(m_defaultCustomDeviceStr)); + devices.Append(json::JsonObject::Parse(L"{\"device-id\": \"device_id\"}")); - TEST_METHOD(DeviceInfoSaveTemp) - { - FancyZonesData data; - DeviceInfoJSON deviceInfo{ L"default_device_id", DeviceInfoData{ ZoneSetData{ L"uuid", ZoneSetLayoutType::Custom }, true, 16, 3 } }; + json::JsonObject expected; + expected.SetNamedValue(L"devices", devices); - const std::wstring path = data.GetPersistFancyZonesJSONPath() + L".test_tmp"; - data.SerializeDeviceInfoToTmpFile(deviceInfo, path); + FancyZonesData data; + auto actual = data.ParseDeviceInfos(expected); - bool actualFileExists = std::filesystem::exists(path); - Assert::IsTrue(actualFileExists); + Assert::IsFalse(actual); + } - auto expectedData = DeviceInfoJSON::ToJson(deviceInfo); - auto actualSavedData = json::from_file(path); - std::filesystem::remove(path); //clean up before compare asserts + TEST_METHOD(FancyZonesDataDeviceInfoMapParseSingle) + { + json::JsonArray devices; + devices.Append(m_defaultCustomDeviceValue); + json::JsonObject expected; + expected.SetNamedValue(L"devices", devices); - Assert::IsTrue(actualSavedData.has_value()); - compareJsonObjects(expectedData, *actualSavedData); - } + FancyZonesData data; + data.ParseDeviceInfos(expected); - TEST_METHOD(DeviceInfoReadTemp) + 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++) { - 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); + json::JsonObject obj = json::JsonObject::Parse(m_defaultCustomDeviceStr); + obj.SetNamedValue(L"device-id", json::JsonValue::CreateStringValue(std::to_wstring(i))); - data.ParseDeviceInfoFromTmpFile(path); + Logger::WriteMessage(obj.Stringify().c_str()); + Logger::WriteMessage("\n"); - bool actualFileExists = std::filesystem::exists(path); - if (actualFileExists) - { - std::filesystem::remove(path); //clean up before compare asserts - } - Assert::IsFalse(actualFileExists); + devices.Append(obj); + } - auto devices = data.GetDeviceInfoMap(); - Assert::AreEqual((size_t)1, devices.size()); + json::JsonObject expected; + expected.SetNamedValue(L"devices", devices); + Logger::WriteMessage(expected.Stringify().c_str()); + Logger::WriteMessage("\n"); - 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()); - } + FancyZonesData data; + data.ParseDeviceInfos(expected); - TEST_METHOD(DeviceInfoReadTempUnexsisted) - { - FancyZonesData data; - const std::wstring path = data.GetPersistFancyZonesJSONPath() + L".test_tmp"; - data.ParseDeviceInfoFromTmpFile(path); + const auto actualMap = data.GetDeviceInfoMap(); + Assert::AreEqual((size_t)10, actualMap.size()); + } - auto devices = data.GetDeviceInfoMap(); - Assert::AreEqual((size_t)0, devices.size()); - } + TEST_METHOD(FancyZonesDataSerialize) + { + json::JsonArray expectedDevices; + expectedDevices.Append(m_defaultCustomDeviceObj); + json::JsonObject expected; + expected.SetNamedValue(L"devices", expectedDevices); - 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); - } + FancyZonesData data; + data.ParseDeviceInfos(expected); - 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 } })); + auto actual = data.SerializeDeviceInfos(); + compareJsonArrays(expectedDevices, actual); + } - json.SetNamedValue(L"app-zone-history", json::JsonValue::Parse(zoneHistoryArray.Stringify())); + TEST_METHOD(DeviceInfoSaveTemp) + { + FancyZonesData data; + DeviceInfoJSON deviceInfo{ L"default_device_id", DeviceInfoData{ ZoneSetData{ L"uuid", ZoneSetLayoutType::Custom }, true, 16, 3 } }; - FancyZonesData data; - data.ParseAppZoneHistory(json); + const std::wstring path = data.GetPersistFancyZonesJSONPath() + L".test_tmp"; + data.SerializeDeviceInfoToTmpFile(deviceInfo, path); - auto actualMap = data.GetAppZoneHistoryMap(); - Assert::AreEqual((size_t)zoneHistoryArray.Size(), actualMap.size()); + bool actualFileExists = std::filesystem::exists(path); + Assert::IsTrue(actualFileExists); - const auto actualProcessHistoryMap = data.GetAppZoneHistoryMap(); - Assert::AreEqual((size_t)zoneHistoryArray.Size(), actualProcessHistoryMap.size()); + auto expectedData = DeviceInfoJSON::ToJson(deviceInfo); + auto actualSavedData = json::from_file(path); + std::filesystem::remove(path); //clean up before compare asserts - auto iter = zoneHistoryArray.First(); - while (iter.HasCurrent()) - { - auto expected = AppZoneHistoryJSON::FromJson(json::JsonObject::Parse(iter.Current().Stringify())); + Assert::IsTrue(actualSavedData.has_value()); + compareJsonObjects(expectedData, *actualSavedData); + } - 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); + 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); - iter.MoveNext(); - } - } + data.ParseDeviceInfoFromTmpFile(path); - TEST_METHOD(AppZoneHistoryParseManyZonesForSingleApp) + bool actualFileExists = std::filesystem::exists(path); + if (actualFileExists) { - 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); + std::filesystem::remove(path); //clean up before compare asserts } + Assert::IsFalse(actualFileExists); - TEST_METHOD(AppZoneHistoryParseEmpty) - { - FancyZonesData data; - data.ParseAppZoneHistory(json::JsonObject()); + auto devices = data.GetDeviceInfoMap(); + Assert::AreEqual((size_t)1, devices.size()); - auto actual = data.GetAppZoneHistoryMap(); - Assert::IsTrue(actual.empty()); - } + 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(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())); + TEST_METHOD(DeviceInfoReadTempUnexsisted) + { + FancyZonesData data; + const std::wstring path = data.GetPersistFancyZonesJSONPath() + L".test_tmp"; + data.ParseDeviceInfoFromTmpFile(path); - FancyZonesData data; - bool actual = data.ParseAppZoneHistory(json); + auto devices = data.GetDeviceInfoMap(); + Assert::AreEqual((size_t)0, devices.size()); + } - Assert::IsFalse(actual); - } + 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(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())); + 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 } })); - FancyZonesData data; - data.ParseAppZoneHistory(json); + json.SetNamedValue(L"app-zone-history", json::JsonValue::Parse(zoneHistoryArray.Stringify())); - auto actual = data.SerializeAppZoneHistory(); - compareJsonArrays(expected, actual); - } + FancyZonesData data; + data.ParseAppZoneHistory(json); - 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); - } + 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()); - TEST_METHOD(AppZoneHistorySerializeEmpty) + auto iter = zoneHistoryArray.First(); + while (iter.HasCurrent()) { - json::JsonArray expected; - json::JsonObject json; - json.SetNamedValue(L"app-zone-history", json::JsonValue::Parse(expected.Stringify())); + auto expected = AppZoneHistoryJSON::FromJson(json::JsonObject::Parse(iter.Current().Stringify())); - FancyZonesData data; - data.ParseAppZoneHistory(json); + 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); - auto actual = data.SerializeAppZoneHistory(); - compareJsonArrays(expected, actual); + iter.MoveNext(); } + } - 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(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(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"); + TEST_METHOD(AppZoneHistoryParseEmpty) + { + FancyZonesData data; + data.ParseAppZoneHistory(json::JsonObject()); - 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"); - } + auto actual = data.GetAppZoneHistoryMap(); + Assert::IsTrue(actual.empty()); + } - iter.MoveNext(); - } - } + 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())); - TEST_METHOD(CustomZoneSetsParseEmpty) - { - FancyZonesData data; - data.ParseCustomZoneSets(json::JsonObject()); + FancyZonesData data; + bool actual = data.ParseAppZoneHistory(json); - auto actual = data.GetCustomZoneSetsMap(); - Assert::IsTrue(actual.empty()); - } + Assert::IsFalse(actual); + } - 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())); + 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; - auto actual = data.ParseCustomZoneSets(json); + FancyZonesData data; + data.ParseAppZoneHistory(json); - Assert::IsFalse(actual); - } + auto actual = data.SerializeAppZoneHistory(); + compareJsonArrays(expected, 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(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(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(AppZoneHistorySerializeEmpty) + { + json::JsonArray expected; + json::JsonObject json; + json.SetNamedValue(L"app-zone-history", json::JsonValue::Parse(expected.Stringify())); - TEST_METHOD(CustomZoneSetsSerializeEmpty) - { - json::JsonArray expected; - json::JsonObject json; - json.SetNamedValue(L"custom-zone-sets", json::JsonValue::Parse(expected.Stringify())); + FancyZonesData data; + data.ParseAppZoneHistory(json); - FancyZonesData data; - data.ParseCustomZoneSets(json); + auto actual = data.SerializeAppZoneHistory(); + compareJsonArrays(expected, actual); + } - auto actual = data.SerializeCustomZoneSets(); - 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(CustomZoneSetsReadTemp) + 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()) { - //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); + 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"); - m_fzData.ParseDeviceInfoFromTmpFile(deviceInfoPath); - std::filesystem::remove(deviceInfoPath); + 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"); } - - 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) + else { - std::filesystem::remove(path); //clean up before compare asserts + 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"); } - 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()); + + iter.MoveNext(); } + } - TEST_METHOD(CustomZoneSetsReadTempUnexsisted) - { - const std::wstring path = m_fzData.GetPersistFancyZonesJSONPath() + L".test_tmp"; - const std::wstring deviceId = L"default_device_id"; + TEST_METHOD(CustomZoneSetsParseEmpty) + { + FancyZonesData data; + data.ParseCustomZoneSets(json::JsonObject()); - m_fzData.ParseCustomZoneSetFromTmpFile(path); - auto devices = m_fzData.GetDeviceInfoMap(); - Assert::AreEqual((size_t)0, devices.size()); - } + auto actual = data.GetCustomZoneSetsMap(); + Assert::IsTrue(actual.empty()); + } - 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 - }; + 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())); - data.SetActiveZoneSet(uniqueId, expectedZoneSetData); + FancyZonesData data; + auto actual = data.ParseCustomZoneSets(json); - 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); - } + Assert::IsFalse(actual); + } - 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 - }; + 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); + } - data.SetActiveZoneSet(uniqueId, expectedZoneSetData); + 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); + } - 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(CustomZoneSetsSerializeEmpty) + { + json::JsonArray expected; + json::JsonObject json; + json.SetNamedValue(L"custom-zone-sets", json::JsonValue::Parse(expected.Stringify())); - 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 - }; + FancyZonesData data; + data.ParseCustomZoneSets(json); - data.SetActiveZoneSet(uniqueId, zoneSetData); + auto actual = data.SerializeCustomZoneSets(); + compareJsonArrays(expected, actual); + } - 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(CustomZoneSetsReadTemp) + { + //prepare device data + const std::wstring deviceId = L"default_device_id"; - TEST_METHOD(LoadFancyZonesDataFromJson) { - FancyZonesData data; - const auto jsonPath = data.GetPersistFancyZonesJSONPath(); - auto savedJson = json::from_file(jsonPath); + 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); - if (std::filesystem::exists(jsonPath)) - { - std::filesystem::remove(jsonPath); - } + m_fzData.ParseDeviceInfoFromTmpFile(deviceInfoPath); + std::filesystem::remove(deviceInfoPath); + } - 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); - } + 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 } }; - Assert::IsFalse(data.GetCustomZoneSetsMap().empty()); - Assert::IsFalse(data.GetCustomZoneSetsMap().empty()); - Assert::IsFalse(data.GetCustomZoneSetsMap().empty()); - } + FancyZonesData data; + const std::wstring path = data.GetPersistFancyZonesJSONPath() + L".test_tmp"; + json::to_file(path, CustomZoneSetJSON::ToJson(expected)); + m_fzData.ParseCustomZoneSetFromTmpFile(path); - TEST_METHOD(LoadFancyZonesDataFromRegistry) + bool actualFileExists = std::filesystem::exists(path); + if (actualFileExists) { - FancyZonesData data; - const auto jsonPath = data.GetPersistFancyZonesJSONPath(); - auto savedJson = json::from_file(jsonPath); + std::filesystem::remove(path); //clean up before compare asserts + } + Assert::IsFalse(actualFileExists); - if (std::filesystem::exists(jsonPath)) - { - std::filesystem::remove(jsonPath); - } + auto devices = m_fzData.GetCustomZoneSetsMap(); + Assert::AreEqual((size_t)1, devices.size()); - data.LoadFancyZonesData(); - bool actual = std::filesystem::exists(jsonPath); - if (savedJson) - { - json::to_file(jsonPath, *savedJson); - } - else - { - std::filesystem::remove(jsonPath); - } + 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()); + } - Assert::IsTrue(actual); - } + TEST_METHOD(CustomZoneSetsReadTempUnexsisted) + { + const std::wstring path = m_fzData.GetPersistFancyZonesJSONPath() + L".test_tmp"; + const std::wstring deviceId = L"default_device_id"; - TEST_METHOD(SaveFancyZonesData) - { - FancyZonesData data; - const auto jsonPath = data.GetPersistFancyZonesJSONPath(); - auto savedJson = json::from_file(jsonPath); + m_fzData.ParseCustomZoneSetFromTmpFile(path); + auto devices = m_fzData.GetDeviceInfoMap(); + Assert::AreEqual((size_t)0, devices.size()); + } - if (std::filesystem::exists(jsonPath)) - { - std::filesystem::remove(jsonPath); - } + TEST_METHOD(SetActiveZoneSet) + { + FancyZonesData data; + const std::wstring uniqueId = L"default_device_id"; - data.SaveFancyZonesData(); - bool actual = std::filesystem::exists(jsonPath); + json::JsonArray devices; + devices.Append(m_defaultCustomDeviceValue); + json::JsonObject json; + json.SetNamedValue(L"devices", devices); + data.ParseDeviceInfos(json); - if (savedJson) - { - json::to_file(jsonPath, *savedJson); - } - else - { - std::filesystem::remove(jsonPath); - } + JSONHelpers::ZoneSetData expectedZoneSetData{ + .uuid = L"uuid", + .type = ZoneSetLayoutType::Focus + }; - Assert::IsTrue(actual); - } + data.SetActiveZoneSet(uniqueId, expectedZoneSetData); - 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; + 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); + } - Assert::AreEqual(-1, data.GetAppLastZoneIndex(window, deviceId, zoneSetId)); + 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); + } - const int expectedZoneIndex = 10; - Assert::IsTrue(data.SetAppLastZone(window, deviceId, zoneSetId, expectedZoneIndex)); - Assert::AreEqual(expectedZoneIndex, data.GetAppLastZoneIndex(window, deviceId, zoneSetId)); - } + 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(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(LoadFancyZonesDataFromJson) + { + FancyZonesData data; + const auto jsonPath = data.GetPersistFancyZonesJSONPath(); + auto savedJson = json::from_file(jsonPath); - TEST_METHOD(AppLastZoneIndexNegative) + if (std::filesystem::exists(jsonPath)) { - 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)); + std::filesystem::remove(jsonPath); } - 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)); - } + 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); - TEST_METHOD(AppLastZoneIndexOverride) + json::to_file(jsonPath, fancyZones); + + data.LoadFancyZonesData(); + if (savedJson) { - 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)); + json::to_file(jsonPath, *savedJson); } - - TEST_METHOD(AppLastZoneInvalidWindow) + else { - 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)); + std::filesystem::remove(jsonPath); } - TEST_METHOD(AppLastZoneNullWindow) - { - const std::wstring zoneSetId = L"zoneset-uuid"; - const auto window = nullptr; - FancyZonesData data; + Assert::IsFalse(data.GetCustomZoneSetsMap().empty()); + Assert::IsFalse(data.GetCustomZoneSetsMap().empty()); + Assert::IsFalse(data.GetCustomZoneSetsMap().empty()); + } - const int expectedZoneIndex = 1; - Assert::IsFalse(data.SetAppLastZone(window, L"device-id", zoneSetId, expectedZoneIndex)); - } + TEST_METHOD(LoadFancyZonesDataFromRegistry) + { + FancyZonesData data; + const auto jsonPath = data.GetPersistFancyZonesJSONPath(); + auto savedJson = json::from_file(jsonPath); - TEST_METHOD(AppLastdeviceIdTest) + if (std::filesystem::exists(jsonPath)) { - 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)); + std::filesystem::remove(jsonPath); } - TEST_METHOD(AppLastZoneSetIdTest) + data.LoadFancyZonesData(); + bool actual = std::filesystem::exists(jsonPath); + if (savedJson) { - 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)); + json::to_file(jsonPath, *savedJson); } - - TEST_METHOD(AppLastZoneRemoveWindow) + else { - 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)); + std::filesystem::remove(jsonPath); } - 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::IsTrue(actual); + } - Assert::IsFalse(data.RemoveAppLastZone(window, deviceId, zoneSetId)); - Assert::AreEqual(-1, data.GetAppLastZoneIndex(window, deviceId, zoneSetId)); - } + TEST_METHOD(SaveFancyZonesData) + { + FancyZonesData data; + const auto jsonPath = data.GetPersistFancyZonesJSONPath(); + auto savedJson = json::from_file(jsonPath); - TEST_METHOD(AppLastZoneRemoveUnknownZoneSetId) + if (std::filesystem::exists(jsonPath)) { - 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)); + std::filesystem::remove(jsonPath); } - TEST_METHOD(AppLastZoneRemoveUnknownWindowId) + data.SaveFancyZonesData(); + bool actual = std::filesystem::exists(jsonPath); + + if (savedJson) { - 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)); + json::to_file(jsonPath, *savedJson); } - - TEST_METHOD(AppLastZoneRemoveNullWindow) + else { - 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)); + 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/UnitTests.vcxproj b/src/modules/fancyzones/tests/UnitTests/UnitTests.vcxproj index c42116b8f02b..705320f3523c 100644 --- a/src/modules/fancyzones/tests/UnitTests/UnitTests.vcxproj +++ b/src/modules/fancyzones/tests/UnitTests/UnitTests.vcxproj @@ -60,7 +60,7 @@ Disabled true ..\..\..\..\common\Telemetry;..\..\..\..\;..\..\..\..\..\deps\cpprestsdk\include;..\..\;$(VCInstallDir)UnitTest\include;%(AdditionalIncludeDirectories) - _DEBUG;%(PreprocessorDefinitions) + UNIT_TESTS;_DEBUG;%(PreprocessorDefinitions) true pch.h stdcpplatest @@ -81,7 +81,7 @@ true true ..\..\..\..\common\Telemetry;..\..\..\..\;..\..\..\..\..\deps\cpprestsdk\include;..\..\;$(VCInstallDir)UnitTest\include;%(AdditionalIncludeDirectories) - NDEBUG;%(PreprocessorDefinitions) + UNIT_TESTS;NDEBUG;%(PreprocessorDefinitions) true pch.h stdcpplatest diff --git a/src/modules/fancyzones/tests/UnitTests/ZoneWindow.Spec.cpp b/src/modules/fancyzones/tests/UnitTests/ZoneWindow.Spec.cpp index 8a5418bedeea..2f230b354fb6 100644 --- a/src/modules/fancyzones/tests/UnitTests/ZoneWindow.Spec.cpp +++ b/src/modules/fancyzones/tests/UnitTests/ZoneWindow.Spec.cpp @@ -68,7 +68,7 @@ namespace FancyZonesUnitTests GUID guid; Assert::AreEqual(S_OK, CoCreateGuid(&guid)); - return GuidString(guid); + return GuidString(guid); } TEST_METHOD_INITIALIZE(Init) @@ -89,7 +89,7 @@ namespace FancyZonesUnitTests Assert::IsFalse(std::filesystem::exists(ZoneWindowUtils::GetAppliedZoneSetTmpPath())); Assert::IsFalse(std::filesystem::exists(ZoneWindowUtils::GetCustomZoneSetsTmpPath())); - m_fancyZonesData = JSONHelpers::FancyZonesData(); + m_fancyZonesData.clear_data(); } TEST_METHOD_CLEANUP(Cleanup) @@ -622,7 +622,7 @@ namespace FancyZonesUnitTests const auto processPath = get_process_path(window); const auto deviceId = m_zoneWindow->UniqueId(); const auto zoneSetId = m_zoneWindow->ActiveZoneSet()->Id(); - + //fill app zone history map Assert::IsTrue(m_fancyZonesData.SetAppLastZone(window, deviceId, GuidString(zoneSetId), 0)); Assert::AreEqual((size_t)1, m_fancyZonesData.GetAppZoneHistoryMap().size());