/ src / modules / keyboardmanager / KeyboardManagerEditorTest / LoadingAndSavingRemappingTests.cpp
LoadingAndSavingRemappingTests.cpp
  1  #include "pch.h"
  2  
  3  // Suppressing 26466 - Don't use static_cast downcasts - in CppUnitTest.h
  4  #pragma warning(push)
  5  #pragma warning(disable : 26466)
  6  #include "CppUnitTest.h"
  7  #pragma warning(pop)
  8  
  9  #include <keyboardmanager/common/MappingConfiguration.h>
 10  #include <keyboardmanager/KeyboardManagerEditorLibrary/LoadingAndSavingRemappingHelper.h>
 11  #include <common/interop/shared_constants.h>
 12  #include <keyboardmanager/KeyboardManagerEditorLibrary/ShortcutErrorType.h>
 13  
 14  using namespace Microsoft::VisualStudio::CppUnitTestFramework;
 15  
 16  namespace RemappingUITests
 17  {
 18      // Tests for methods in the LoadingAndSavingRemappingHelper namespace
 19      TEST_CLASS (LoadingAndSavingRemappingTests)
 20      {
 21          std::wstring testApp1 = L"testprocess1.exe";
 22          std::wstring testApp2 = L"testprocess2.exe";
 23  
 24      public:
 25          TEST_METHOD_INITIALIZE(InitializeTestEnv)
 26          {
 27          }
 28  
 29          // Test if the CheckIfRemappingsAreValid method is successful when no remaps are passed
 30          TEST_METHOD (CheckIfRemappingsAreValid_ShouldReturnNoError_OnPassingNoRemaps)
 31          {
 32              RemapBuffer remapBuffer;
 33  
 34              // Assert that remapping set is valid
 35              bool isSuccess = (LoadingAndSavingRemappingHelper::CheckIfRemappingsAreValid(remapBuffer) == ShortcutErrorType::NoError);
 36              Assert::AreEqual(true, isSuccess);
 37          }
 38  
 39          // Test if the CheckIfRemappingsAreValid method is successful when valid key to key remaps are passed
 40          TEST_METHOD (CheckIfRemappingsAreValid_ShouldReturnNoError_OnPassingValidKeyToKeyRemaps)
 41          {
 42              RemapBuffer remapBuffer;
 43  
 44              // Remap A to B and B to C
 45              remapBuffer.push_back(RemapBufferRow{ RemapBufferItem({ (DWORD)0x41, (DWORD)0x42 }), std::wstring() });
 46              remapBuffer.push_back(RemapBufferRow{ RemapBufferItem({ (DWORD)0x42, (DWORD)0x43 }), std::wstring() });
 47  
 48              // Assert that remapping set is valid
 49              bool isSuccess = (LoadingAndSavingRemappingHelper::CheckIfRemappingsAreValid(remapBuffer) == ShortcutErrorType::NoError);
 50              Assert::AreEqual(true, isSuccess);
 51          }
 52  
 53          // Test if the CheckIfRemappingsAreValid method is successful when valid key to shortcut remaps are passed
 54          TEST_METHOD (CheckIfRemappingsAreValid_ShouldReturnNoError_OnPassingValidKeyToShortcutRemaps)
 55          {
 56              RemapBuffer remapBuffer;
 57  
 58              // Remap A to Ctrl+V and B to Alt+Tab
 59              Shortcut s1;
 60              s1.SetKey(VK_CONTROL);
 61              s1.SetKey(0x56);
 62              Shortcut s2;
 63              s2.SetKey(VK_MENU);
 64              s2.SetKey(VK_TAB);
 65              remapBuffer.push_back(RemapBufferRow{ RemapBufferItem({ (DWORD)0x41, s1 }), std::wstring() });
 66              remapBuffer.push_back(RemapBufferRow{ RemapBufferItem({ (DWORD)0x42, s2 }), std::wstring() });
 67  
 68              // Assert that remapping set is valid
 69              bool isSuccess = (LoadingAndSavingRemappingHelper::CheckIfRemappingsAreValid(remapBuffer) == ShortcutErrorType::NoError);
 70              Assert::AreEqual(true, isSuccess);
 71          }
 72  
 73          // Test if the CheckIfRemappingsAreValid method is successful when valid shortcut to key remaps are passed
 74          TEST_METHOD (CheckIfRemappingsAreValid_ShouldReturnNoError_OnPassingValidShortcutToKeyRemaps)
 75          {
 76              RemapBuffer remapBuffer;
 77  
 78              // Remap Ctrl+V to A and Alt+Tab to B
 79              Shortcut s1;
 80              s1.SetKey(VK_CONTROL);
 81              s1.SetKey(0x56);
 82              Shortcut s2;
 83              s2.SetKey(VK_MENU);
 84              s2.SetKey(VK_TAB);
 85              remapBuffer.push_back(RemapBufferRow{ RemapBufferItem({ s1, (DWORD)0x41 }), std::wstring() });
 86              remapBuffer.push_back(RemapBufferRow{ RemapBufferItem({ s2, (DWORD)0x42 }), std::wstring() });
 87  
 88              // Assert that remapping set is valid
 89              bool isSuccess = (LoadingAndSavingRemappingHelper::CheckIfRemappingsAreValid(remapBuffer) == ShortcutErrorType::NoError);
 90              Assert::AreEqual(true, isSuccess);
 91          }
 92  
 93          // Test if the CheckIfRemappingsAreValid method is successful when valid shortcut to shortcut remaps are passed
 94          TEST_METHOD (CheckIfRemappingsAreValid_ShouldReturnNoError_OnPassingValidShortcutToShortcutRemaps)
 95          {
 96              RemapBuffer remapBuffer;
 97  
 98              // Remap Ctrl+V to Ctrl+D and Alt+Tab to Win+A
 99              Shortcut src1;
100              src1.SetKey(VK_CONTROL);
101              src1.SetKey(0x56);
102              Shortcut dest1;
103              dest1.SetKey(VK_CONTROL);
104              dest1.SetKey(0x44);
105              Shortcut src2;
106              src2.SetKey(VK_MENU);
107              src2.SetKey(VK_TAB);
108              Shortcut dest2;
109              dest2.SetKey(CommonSharedConstants::VK_WIN_BOTH);
110              dest2.SetKey(0x41);
111              remapBuffer.push_back(RemapBufferRow{ RemapBufferItem({ src1, dest1 }), std::wstring() });
112              remapBuffer.push_back(RemapBufferRow{ RemapBufferItem({ src2, dest2 }), std::wstring() });
113  
114              // Assert that remapping set is valid
115              bool isSuccess = (LoadingAndSavingRemappingHelper::CheckIfRemappingsAreValid(remapBuffer) == ShortcutErrorType::NoError);
116              Assert::AreEqual(true, isSuccess);
117          }
118  
119          // Test if the CheckIfRemappingsAreValid method is successful when valid remaps are passed
120          TEST_METHOD (CheckIfRemappingsAreValid_ShouldReturnNoError_OnPassingValidRemapsOfAllTypes)
121          {
122              RemapBuffer remapBuffer;
123  
124              // Remap Ctrl+V to Ctrl+D, Alt+Tab to A, A to B and B to Win+A
125              Shortcut src1;
126              src1.SetKey(VK_CONTROL);
127              src1.SetKey(0x56);
128              Shortcut dest1;
129              dest1.SetKey(VK_CONTROL);
130              dest1.SetKey(0x44);
131              Shortcut src2;
132              src2.SetKey(VK_MENU);
133              src2.SetKey(VK_TAB);
134              Shortcut dest2;
135              dest2.SetKey(CommonSharedConstants::VK_WIN_BOTH);
136              dest2.SetKey(0x41);
137              remapBuffer.push_back(RemapBufferRow{ RemapBufferItem({ src1, dest1 }), std::wstring() });
138              remapBuffer.push_back(RemapBufferRow{ RemapBufferItem({ src2, (DWORD)0x41 }), std::wstring() });
139              remapBuffer.push_back(RemapBufferRow{ RemapBufferItem({ (DWORD)0x41, (DWORD)0x42 }), std::wstring() });
140              remapBuffer.push_back(RemapBufferRow{ RemapBufferItem({ (DWORD)0x42, dest2 }), std::wstring() });
141  
142              // Assert that remapping set is valid
143              bool isSuccess = (LoadingAndSavingRemappingHelper::CheckIfRemappingsAreValid(remapBuffer) == ShortcutErrorType::NoError);
144              Assert::AreEqual(true, isSuccess);
145          }
146  
147          // Test if the CheckIfRemappingsAreValid method is unsuccessful when remaps with null keys are passed
148          TEST_METHOD (CheckIfRemappingsAreValid_ShouldReturnRemapUnsuccessful_OnPassingRemapsWithNullKeys)
149          {
150              RemapBuffer remapBuffer;
151  
152              // Remap A to NULL
153              remapBuffer.push_back(RemapBufferRow{ RemapBufferItem({ (DWORD)0x41, (DWORD)0 }), std::wstring() });
154  
155              // Assert that remapping set is invalid
156              bool isSuccess = (LoadingAndSavingRemappingHelper::CheckIfRemappingsAreValid(remapBuffer) == ShortcutErrorType::RemapUnsuccessful);
157              Assert::AreEqual(true, isSuccess);
158          }
159  
160          // Test if the CheckIfRemappingsAreValid method is unsuccessful when remaps with invalid shortcuts are passed
161          TEST_METHOD (CheckIfRemappingsAreValid_ShouldReturnRemapUnsuccessful_OnPassingRemapsWithInvalidShortcut)
162          {
163              RemapBuffer remapBuffer;
164  
165              // Remap A to incomplete shortcut (Ctrl)
166              Shortcut src1;
167              src1.SetKey(VK_CONTROL);
168              remapBuffer.push_back(RemapBufferRow{ RemapBufferItem({ (DWORD)0x41, src1 }), std::wstring() });
169  
170              // Assert that remapping set is invalid
171              bool isSuccess = (LoadingAndSavingRemappingHelper::CheckIfRemappingsAreValid(remapBuffer) == ShortcutErrorType::RemapUnsuccessful);
172              Assert::AreEqual(true, isSuccess);
173          }
174  
175          // Test if the CheckIfRemappingsAreValid method is unsuccessful when remaps with the same key remapped twice are passed
176          TEST_METHOD (CheckIfRemappingsAreValid_ShouldReturnRemapUnsuccessful_OnPassingRemapsWithSameKeyRemappedTwice)
177          {
178              RemapBuffer remapBuffer;
179  
180              // Remap A to B and A to Ctrl+C
181              Shortcut src1;
182              src1.SetKey(VK_CONTROL);
183              src1.SetKey(0x43);
184              remapBuffer.push_back(RemapBufferRow{ RemapBufferItem({ (DWORD)0x41, (DWORD)0x42 }), std::wstring() });
185              remapBuffer.push_back(RemapBufferRow{ RemapBufferItem({ (DWORD)0x41, src1 }), std::wstring() });
186  
187              // Assert that remapping set is invalid
188              bool isSuccess = (LoadingAndSavingRemappingHelper::CheckIfRemappingsAreValid(remapBuffer) == ShortcutErrorType::RemapUnsuccessful);
189              Assert::AreEqual(true, isSuccess);
190          }
191  
192          // Test if the CheckIfRemappingsAreValid method is unsuccessful when remaps with the same shortcut remapped twice are passed
193          TEST_METHOD (CheckIfRemappingsAreValid_ShouldReturnRemapUnsuccessful_OnPassingRemapsWithSameShortcutRemappedTwice)
194          {
195              RemapBuffer remapBuffer;
196  
197              // Remap Ctrl+A to B and Ctrl+A to Ctrl+V
198              Shortcut src1;
199              src1.SetKey(VK_CONTROL);
200              src1.SetKey(0x41);
201              Shortcut dest1;
202              dest1.SetKey(VK_CONTROL);
203              dest1.SetKey(0x56);
204              remapBuffer.push_back(RemapBufferRow{ RemapBufferItem({ src1, (DWORD)0x42 }), std::wstring() });
205              remapBuffer.push_back(RemapBufferRow{ RemapBufferItem({ src1, dest1 }), std::wstring() });
206  
207              // Assert that remapping set is invalid
208              bool isSuccess = (LoadingAndSavingRemappingHelper::CheckIfRemappingsAreValid(remapBuffer) == ShortcutErrorType::RemapUnsuccessful);
209              Assert::AreEqual(true, isSuccess);
210          }
211  
212          // Test if the CheckIfRemappingsAreValid method is unsuccessful when app specific remaps with the same shortcut remapped twice for the same target app are passed
213          TEST_METHOD (CheckIfRemappingsAreValid_ShouldReturnRemapUnsuccessful_OnPassingAppSpecificRemapsWithSameShortcutRemappedTwiceForTheSameTargetApp)
214          {
215              RemapBuffer remapBuffer;
216  
217              // Remap Ctrl+A to B and Ctrl+A to Ctrl+V for testApp1
218              Shortcut src1;
219              src1.SetKey(VK_CONTROL);
220              src1.SetKey(0x41);
221              Shortcut dest1;
222              dest1.SetKey(VK_CONTROL);
223              dest1.SetKey(0x56);
224              remapBuffer.push_back(RemapBufferRow{ RemapBufferItem({ src1, (DWORD)0x42 }), testApp1 });
225              remapBuffer.push_back(RemapBufferRow{ RemapBufferItem({ src1, dest1 }), testApp1 });
226  
227              // Assert that remapping set is invalid
228              bool isSuccess = (LoadingAndSavingRemappingHelper::CheckIfRemappingsAreValid(remapBuffer) == ShortcutErrorType::RemapUnsuccessful);
229              Assert::AreEqual(true, isSuccess);
230          }
231  
232          // Test if the CheckIfRemappingsAreValid method is successful when app specific remaps with the same shortcut remapped twice for different target apps are passed
233          TEST_METHOD (CheckIfRemappingsAreValid_ShouldReturnNoError_OnPassingAppSpecificRemapsWithSameShortcutRemappedTwiceForDifferentTargetApps)
234          {
235              RemapBuffer remapBuffer;
236  
237              // Remap Ctrl+A to B for testApp1 and Ctrl+A to Ctrl+V for testApp2
238              Shortcut src1;
239              src1.SetKey(VK_CONTROL);
240              src1.SetKey(0x41);
241              Shortcut dest1;
242              dest1.SetKey(VK_CONTROL);
243              dest1.SetKey(0x56);
244              remapBuffer.push_back(RemapBufferRow{ RemapBufferItem({ src1, (DWORD)0x42 }), testApp1 });
245              remapBuffer.push_back(RemapBufferRow{ RemapBufferItem({ src1, dest1 }), testApp2 });
246  
247              // Assert that remapping set is valid
248              bool isSuccess = (LoadingAndSavingRemappingHelper::CheckIfRemappingsAreValid(remapBuffer) == ShortcutErrorType::NoError);
249              Assert::AreEqual(true, isSuccess);
250          }
251  
252          // Test if the GetOrphanedKeys method return an empty vector on passing no remaps
253          TEST_METHOD (GetOrphanedKeys_ShouldReturnEmptyVector_OnPassingNoRemaps)
254          {
255              RemapBuffer remapBuffer;
256  
257              // Assert that there are no orphaned keys
258              Assert::AreEqual(true, LoadingAndSavingRemappingHelper::GetOrphanedKeys(remapBuffer).empty());
259          }
260  
261          // Test if the GetOrphanedKeys method return one orphaned on passing one key remap
262          TEST_METHOD (GetOrphanedKeys_ShouldReturnOneOrphanedKey_OnPassingOneKeyRemap)
263          {
264              RemapBuffer remapBuffer;
265  
266              // Remap A to B
267              remapBuffer.push_back(RemapBufferRow{ RemapBufferItem({ (DWORD)0x41, (DWORD)0x42 }), std::wstring() });
268  
269              // Assert that only A is orphaned
270              Assert::AreEqual((size_t)1, LoadingAndSavingRemappingHelper::GetOrphanedKeys(remapBuffer).size());
271              Assert::AreEqual((DWORD)0x41, LoadingAndSavingRemappingHelper::GetOrphanedKeys(remapBuffer)[0]);
272          }
273  
274          // Test if the GetOrphanedKeys method return an empty vector on passing swapped key remaps
275          TEST_METHOD (GetOrphanedKeys_ShouldReturnEmptyVector_OnPassingSwappedKeyRemap)
276          {
277              RemapBuffer remapBuffer;
278  
279              // Remap A to B and B to A
280              remapBuffer.push_back(RemapBufferRow{ RemapBufferItem({ (DWORD)0x41, (DWORD)0x42 }), std::wstring() });
281              remapBuffer.push_back(RemapBufferRow{ RemapBufferItem({ (DWORD)0x42, (DWORD)0x41 }), std::wstring() });
282  
283              // Assert that there are no orphaned keys
284              Assert::AreEqual(true, LoadingAndSavingRemappingHelper::GetOrphanedKeys(remapBuffer).empty());
285          }
286  
287          // Test if the GetOrphanedKeys method return one orphaned on passing two key remaps where one key is mapped to a remapped key
288          TEST_METHOD (GetOrphanedKeys_ShouldReturnOneOrphanedKey_OnPassingTwoKeyRemapsWhereOneKeyIsMappedToARemappedKey)
289          {
290              RemapBuffer remapBuffer;
291  
292              // Remap A to Ctrl+B and C to A
293              Shortcut dest1;
294              dest1.SetKey(VK_CONTROL);
295              dest1.SetKey(0x42);
296              remapBuffer.push_back(RemapBufferRow{ RemapBufferItem({ (DWORD)0x41, dest1 }), std::wstring() });
297              remapBuffer.push_back(RemapBufferRow{ RemapBufferItem({ (DWORD)0x43, (DWORD)0x41 }), std::wstring() });
298  
299              // Assert that only C is orphaned
300              Assert::AreEqual((size_t)1, LoadingAndSavingRemappingHelper::GetOrphanedKeys(remapBuffer).size());
301              Assert::AreEqual((DWORD)0x43, LoadingAndSavingRemappingHelper::GetOrphanedKeys(remapBuffer)[0]);
302          }
303  
304          // Test if the PreProcessRemapTable method combines all the modifier pairs when the left and right modifiers are remapped to the same target
305          TEST_METHOD (PreProcessRemapTable_ShouldCombineAllPairs_OnPassingLeftAndRightModifiersRemappedToTheSameTarget)
306          {
307              SingleKeyRemapTable remapTable;
308  
309              // Remap LCtrl and RCtrl to A, LAlt and RAlt to B, LShift and RShift to C, LWin and RWin to D
310              remapTable[VK_LCONTROL] = (DWORD)0x41;
311              remapTable[VK_RCONTROL] = (DWORD)0x41;
312              remapTable[VK_LMENU] = (DWORD)0x42;
313              remapTable[VK_RMENU] = (DWORD)0x42;
314              remapTable[VK_LSHIFT] = (DWORD)0x43;
315              remapTable[VK_RSHIFT] = (DWORD)0x43;
316              remapTable[VK_LWIN] = (DWORD)0x44;
317              remapTable[VK_RWIN] = (DWORD)0x44;
318  
319              // Pre process table
320              LoadingAndSavingRemappingHelper::PreProcessRemapTable(remapTable);
321  
322              // Expected Ctrl remapped to A, Alt to B, Shift to C, Win to D
323              SingleKeyRemapTable expectedTable;
324              expectedTable[VK_CONTROL] = (DWORD)0x41;
325              expectedTable[VK_MENU] = (DWORD)0x42;
326              expectedTable[VK_SHIFT] = (DWORD)0x43;
327              expectedTable[CommonSharedConstants::VK_WIN_BOTH] = (DWORD)0x44;
328  
329              bool areTablesEqual = (expectedTable == remapTable);
330              Assert::AreEqual(true, areTablesEqual);
331          }
332  
333          // Test if the PreProcessRemapTable method does not combines any of the modifier pairs when the left and right modifiers are remapped to different targets
334          TEST_METHOD (PreProcessRemapTable_ShouldNotCombineAnyPairs_OnPassingLeftAndRightModifiersRemappedToTheDifferentTargets)
335          {
336              SingleKeyRemapTable remapTable;
337  
338              // Remap left modifiers to A and right modifiers to B
339              remapTable[VK_LCONTROL] = (DWORD)0x41;
340              remapTable[VK_RCONTROL] = (DWORD)0x42;
341              remapTable[VK_LMENU] = (DWORD)0x41;
342              remapTable[VK_RMENU] = (DWORD)0x42;
343              remapTable[VK_LSHIFT] = (DWORD)0x41;
344              remapTable[VK_RSHIFT] = (DWORD)0x42;
345              remapTable[VK_LWIN] = (DWORD)0x41;
346              remapTable[VK_RWIN] = (DWORD)0x42;
347  
348              // Pre process table
349              LoadingAndSavingRemappingHelper::PreProcessRemapTable(remapTable);
350  
351              // Expected unchanged table
352              SingleKeyRemapTable expectedTable;
353              expectedTable[VK_LCONTROL] = (DWORD)0x41;
354              expectedTable[VK_RCONTROL] = (DWORD)0x42;
355              expectedTable[VK_LMENU] = (DWORD)0x41;
356              expectedTable[VK_RMENU] = (DWORD)0x42;
357              expectedTable[VK_LSHIFT] = (DWORD)0x41;
358              expectedTable[VK_RSHIFT] = (DWORD)0x42;
359              expectedTable[VK_LWIN] = (DWORD)0x41;
360              expectedTable[VK_RWIN] = (DWORD)0x42;
361  
362              bool areTablesEqual = (expectedTable == remapTable);
363              Assert::AreEqual(true, areTablesEqual);
364          }
365  
366          // Test if the ApplySingleKeyRemappings method resets the keyboard manager state's single key remappings on passing an empty buffer
367          TEST_METHOD (ApplySingleKeyRemappings_ShouldResetSingleKeyRemappings_OnPassingEmptyBuffer)
368          {
369              MappingConfiguration testShortcuts;
370              RemapBuffer remapBuffer;
371  
372              // Remap A to B
373              testShortcuts.AddSingleKeyRemap(0x41, (DWORD)0x42);
374  
375              // Apply the single key remaps from the buffer to the keyboard manager state variable
376              LoadingAndSavingRemappingHelper::ApplySingleKeyRemappings(testShortcuts, remapBuffer, false);
377  
378              // Assert that single key remapping in the kbm state variable is empty
379              Assert::AreEqual((size_t)0, testShortcuts.singleKeyReMap.size());
380          }
381  
382          // Test if the ApplySingleKeyRemappings method copies only the valid remappings to the keyboard manager state variable when some of the remappings are invalid
383          TEST_METHOD (ApplySingleKeyRemappings_ShouldCopyOnlyValidRemappings_OnPassingBufferWithSomeInvalidRemappings)
384          {
385              MappingConfiguration testShortcuts;
386              RemapBuffer remapBuffer;
387  
388              // Add A->B, B->Ctrl+V, C to incomplete shortcut and D to incomplete key remappings to the buffer
389              Shortcut s1;
390              s1.SetKey(VK_CONTROL);
391              s1.SetKey(0x56);
392              Shortcut s2;
393              s2.SetKey(VK_LMENU);
394              remapBuffer.push_back(RemapBufferRow{ RemapBufferItem({ (DWORD)0x41, (DWORD)0x42 }), std::wstring() });
395              remapBuffer.push_back(RemapBufferRow{ RemapBufferItem({ (DWORD)0x42, s1 }), std::wstring() });
396              remapBuffer.push_back(RemapBufferRow{ RemapBufferItem({ (DWORD)0x43, (DWORD)0 }), std::wstring() });
397              remapBuffer.push_back(RemapBufferRow{ RemapBufferItem({ (DWORD)0x44, s2 }), std::wstring() });
398  
399              // Apply the single key remaps from the buffer to the keyboard manager state variable
400              LoadingAndSavingRemappingHelper::ApplySingleKeyRemappings(testShortcuts, remapBuffer, false);
401  
402              // Expected A remapped to B, B remapped to Ctrl+V
403              SingleKeyRemapTable expectedTable;
404              expectedTable[0x41] = (DWORD)0x42;
405              expectedTable[0x42] = s1;
406  
407              bool areTablesEqual = (expectedTable == testShortcuts.singleKeyReMap);
408              Assert::AreEqual(true, areTablesEqual);
409          }
410  
411          // Test if the ApplySingleKeyRemappings method splits common modifiers to their left and right version when copying to the keyboard manager state variable if remappings from common modifiers are passed
412          TEST_METHOD (ApplySingleKeyRemappings_ShouldSplitRemappingsFromCommonModifiers_OnPassingBufferWithSomeMappingsFromCommonModifiers)
413          {
414              MappingConfiguration testShortcuts;
415              RemapBuffer remapBuffer;
416  
417              // Add Ctrl->A, Alt->B, Shift->C and Win->D remappings to the buffer
418              remapBuffer.push_back(RemapBufferRow{ RemapBufferItem({ (DWORD)VK_CONTROL, (DWORD)0x41 }), std::wstring() });
419              remapBuffer.push_back(RemapBufferRow{ RemapBufferItem({ (DWORD)VK_MENU, (DWORD)0x42 }), std::wstring() });
420              remapBuffer.push_back(RemapBufferRow{ RemapBufferItem({ (DWORD)VK_SHIFT, (DWORD)0x43 }), std::wstring() });
421              remapBuffer.push_back(RemapBufferRow{ RemapBufferItem({ (DWORD)CommonSharedConstants::VK_WIN_BOTH, (DWORD)0x44 }), std::wstring() });
422  
423              // Apply the single key remaps from the buffer to the keyboard manager state variable
424              LoadingAndSavingRemappingHelper::ApplySingleKeyRemappings(testShortcuts, remapBuffer, false);
425  
426              // Expected LCtrl/RCtrl remapped to A, LAlt/RAlt to B, LShift/RShift to C, LWin/RWin to D
427              SingleKeyRemapTable expectedTable;
428              expectedTable[VK_LCONTROL] = (DWORD)0x41;
429              expectedTable[VK_RCONTROL] = (DWORD)0x41;
430              expectedTable[VK_LMENU] = (DWORD)0x42;
431              expectedTable[VK_RMENU] = (DWORD)0x42;
432              expectedTable[VK_LSHIFT] = (DWORD)0x43;
433              expectedTable[VK_RSHIFT] = (DWORD)0x43;
434              expectedTable[VK_LWIN] = (DWORD)0x44;
435              expectedTable[VK_RWIN] = (DWORD)0x44;
436  
437              bool areTablesEqual = (expectedTable == testShortcuts.singleKeyReMap);
438              Assert::AreEqual(true, areTablesEqual);
439          }
440  
441          // Test if the ApplyShortcutRemappings method resets the keyboard manager state's os level and app specific shortcut remappings on passing an empty buffer
442          TEST_METHOD (ApplyShortcutRemappings_ShouldResetShortcutRemappings_OnPassingEmptyBuffer)
443          {
444              MappingConfiguration testShortcuts;
445              RemapBuffer remapBuffer;
446  
447              // Remap Ctrl+A to Ctrl+B for all apps and Ctrl+C to Alt+V for testApp1
448              Shortcut src1;
449              src1.SetKey(VK_CONTROL);
450              src1.SetKey(0x41);
451              Shortcut dest1;
452              dest1.SetKey(VK_CONTROL);
453              dest1.SetKey(0x42);
454              Shortcut src2;
455              src2.SetKey(VK_CONTROL);
456              src2.SetKey(0x43);
457              Shortcut dest2;
458              dest2.SetKey(VK_MENU);
459              dest2.SetKey(0x56);
460              testShortcuts.AddOSLevelShortcut(src1, dest1);
461              testShortcuts.AddAppSpecificShortcut(testApp1, src1, dest1);
462  
463              // Apply the shortcut remaps from the buffer to the keyboard manager state variable
464              LoadingAndSavingRemappingHelper::ApplyShortcutRemappings(testShortcuts, remapBuffer, false);
465  
466              // Assert that shortcut remappings in the kbm state variable is empty
467              Assert::AreEqual((size_t)0, testShortcuts.osLevelShortcutReMap.size());
468              Assert::AreEqual((size_t)0, testShortcuts.appSpecificShortcutReMap.size());
469          }
470  
471          // Test if the ApplyShortcutRemappings method copies only the valid remappings to the keyboard manager state variable when some of the remappings are invalid
472          TEST_METHOD (ApplyShortcutRemappings_ShouldCopyOnlyValidRemappings_OnPassingBufferWithSomeInvalidRemappings)
473          {
474              MappingConfiguration testShortcuts;
475              RemapBuffer remapBuffer;
476  
477              // Add Ctrl+A->Ctrl+B, Ctrl+C->Alt+V, Ctrl+F->incomplete shortcut and Ctrl+G->incomplete key os level remappings to buffer
478              // Add Ctrl+F->Alt+V, Ctrl+G->Ctrl+B, Ctrl+A->incomplete shortcut and  Ctrl+C->incomplete key app specific remappings to buffer
479              Shortcut src1;
480              src1.SetKey(VK_CONTROL);
481              src1.SetKey(0x41);
482              Shortcut dest1;
483              dest1.SetKey(VK_CONTROL);
484              dest1.SetKey(0x42);
485              Shortcut src2;
486              src2.SetKey(VK_CONTROL);
487              src2.SetKey(0x43);
488              Shortcut dest2;
489              dest2.SetKey(VK_MENU);
490              dest2.SetKey(0x56);
491              Shortcut src3;
492              src3.SetKey(VK_CONTROL);
493              src3.SetKey(0x46);
494              Shortcut src4;
495              src4.SetKey(VK_CONTROL);
496              src4.SetKey(0x47);
497              Shortcut dest4;
498              dest4.SetKey(VK_CONTROL);
499              remapBuffer.push_back(RemapBufferRow{ RemapBufferItem({ src1, dest1 }), std::wstring() });
500              remapBuffer.push_back(RemapBufferRow{ RemapBufferItem({ src2, dest2 }), std::wstring() });
501              remapBuffer.push_back(RemapBufferRow{ RemapBufferItem({ src3, (DWORD)0 }), std::wstring() });
502              remapBuffer.push_back(RemapBufferRow{ RemapBufferItem({ src4, dest4 }), std::wstring() });
503              remapBuffer.push_back(RemapBufferRow{ RemapBufferItem({ src3, dest2 }), testApp1 });
504              remapBuffer.push_back(RemapBufferRow{ RemapBufferItem({ src4, dest1 }), testApp1 });
505              remapBuffer.push_back(RemapBufferRow{ RemapBufferItem({ src1, (DWORD)0 }), testApp1 });
506              remapBuffer.push_back(RemapBufferRow{ RemapBufferItem({ src2, dest4 }), testApp1 });
507  
508              // Apply the shortcut remaps from the buffer to the keyboard manager state variable
509              LoadingAndSavingRemappingHelper::ApplyShortcutRemappings(testShortcuts, remapBuffer, false);
510  
511              // Ctrl+A->Ctrl+B and Ctrl+C->Alt+V
512              ShortcutRemapTable expectedOSLevelTable;
513              expectedOSLevelTable[src1] = RemapShortcut(dest1);
514              expectedOSLevelTable[src2] = RemapShortcut(dest2);
515  
516              // Ctrl+F->Alt+V and Ctrl+G->Ctrl+B for testApp1
517              AppSpecificShortcutRemapTable expectedAppSpecificLevelTable;
518              expectedAppSpecificLevelTable[testApp1][src3] = RemapShortcut(dest2);
519              expectedAppSpecificLevelTable[testApp1][src4] = RemapShortcut(dest1);
520  
521              bool areOSLevelTablesEqual = (expectedOSLevelTable == testShortcuts.osLevelShortcutReMap);
522              bool areAppSpecificTablesEqual = (expectedAppSpecificLevelTable == testShortcuts.appSpecificShortcutReMap);
523              Assert::AreEqual(true, areOSLevelTablesEqual);
524              Assert::AreEqual(true, areAppSpecificTablesEqual);
525          }
526      };
527  }