accelerator_table_unittest.cc 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175
  1. // Copyright (c) 2012 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include <set>
  5. #include <tuple>
  6. #include "ash/accelerators/accelerator_table.h"
  7. #include "base/hash/md5.h"
  8. #include "base/strings/string_util.h"
  9. #include "base/strings/stringprintf.h"
  10. #include "testing/gtest/include/gtest/gtest.h"
  11. namespace ash {
  12. namespace {
  13. // The number of non-Search-based accelerators.
  14. constexpr int kNonSearchAcceleratorsNum = 109;
  15. // The hash of non-Search-based accelerators. See HashAcceleratorData().
  16. constexpr char kNonSearchAcceleratorsHash[] =
  17. "2cada710fecfc1ae0fa22ecad7900f16";
  18. struct Cmp {
  19. bool operator()(const AcceleratorData& lhs,
  20. const AcceleratorData& rhs) const {
  21. // Do not check |action|.
  22. return std::tie(lhs.trigger_on_press, lhs.keycode, lhs.modifiers) <
  23. std::tie(rhs.trigger_on_press, rhs.keycode, rhs.modifiers);
  24. }
  25. };
  26. std::string AcceleratorDataToString(const AcceleratorData& accelerator) {
  27. return base::StringPrintf(
  28. "trigger_on_press=%s keycode=%d shift=%s control=%s alt=%s search=%s",
  29. accelerator.trigger_on_press ? "true" : "false", accelerator.keycode,
  30. (accelerator.modifiers & ui::EF_SHIFT_DOWN) ? "true" : "false",
  31. (accelerator.modifiers & ui::EF_CONTROL_DOWN) ? "true" : "false",
  32. (accelerator.modifiers & ui::EF_ALT_DOWN) ? "true" : "false",
  33. (accelerator.modifiers & ui::EF_COMMAND_DOWN) ? "true" : "false");
  34. }
  35. std::string HashAcceleratorData(
  36. const std::vector<AcceleratorData> accelerators) {
  37. base::MD5Context context;
  38. base::MD5Init(&context);
  39. for (const AcceleratorData& accelerator : accelerators)
  40. base::MD5Update(&context, AcceleratorDataToString(accelerator));
  41. base::MD5Digest digest;
  42. base::MD5Final(&digest, &context);
  43. return MD5DigestToBase16(digest);
  44. }
  45. } // namespace
  46. TEST(AcceleratorTableTest, CheckDuplicatedAccelerators) {
  47. std::set<AcceleratorData, Cmp> accelerators;
  48. for (size_t i = 0; i < kAcceleratorDataLength; ++i) {
  49. const AcceleratorData& entry = kAcceleratorData[i];
  50. EXPECT_TRUE(accelerators.insert(entry).second)
  51. << "Duplicated accelerator: " << AcceleratorDataToString(entry);
  52. }
  53. for (size_t i = 0; i < kDisableWithNewMappingAcceleratorDataLength; ++i) {
  54. const AcceleratorData& entry = kDisableWithNewMappingAcceleratorData[i];
  55. EXPECT_TRUE(accelerators.insert(entry).second)
  56. << "Duplicated accelerator: " << AcceleratorDataToString(entry);
  57. }
  58. }
  59. TEST(AcceleratorTableTest, CheckDuplicatedReservedActions) {
  60. std::set<AcceleratorAction> actions;
  61. for (size_t i = 0; i < kReservedActionsLength; ++i) {
  62. EXPECT_TRUE(actions.insert(kReservedActions[i]).second)
  63. << "Duplicated action: " << kReservedActions[i];
  64. }
  65. }
  66. TEST(AcceleratorTableTest, CheckDuplicatedActionsAllowedAtLoginOrLockScreen) {
  67. std::set<AcceleratorAction> actions;
  68. for (size_t i = 0; i < kActionsAllowedAtLoginOrLockScreenLength; ++i) {
  69. EXPECT_TRUE(actions.insert(kActionsAllowedAtLoginOrLockScreen[i]).second)
  70. << "Duplicated action: " << kActionsAllowedAtLoginOrLockScreen[i];
  71. }
  72. for (size_t i = 0; i < kActionsAllowedAtLockScreenLength; ++i) {
  73. EXPECT_TRUE(actions.insert(kActionsAllowedAtLockScreen[i]).second)
  74. << "Duplicated action: " << kActionsAllowedAtLockScreen[i];
  75. }
  76. }
  77. TEST(AcceleratorTableTest, CheckDuplicatedActionsAllowedAtPowerMenu) {
  78. std::set<AcceleratorAction> actions;
  79. for (size_t i = 0; i < kActionsAllowedAtPowerMenuLength; ++i) {
  80. EXPECT_TRUE(actions.insert(kActionsAllowedAtPowerMenu[i]).second)
  81. << "Duplicated action: " << kActionsAllowedAtPowerMenu[i];
  82. }
  83. }
  84. TEST(AcceleratorTableTest, CheckDuplicatedActionsAllowedAtModalWindow) {
  85. std::set<AcceleratorAction> actions;
  86. for (size_t i = 0; i < kActionsAllowedAtModalWindowLength; ++i) {
  87. EXPECT_TRUE(actions.insert(kActionsAllowedAtModalWindow[i]).second)
  88. << "Duplicated action: " << kActionsAllowedAtModalWindow[i]
  89. << " at index: " << i;
  90. }
  91. }
  92. TEST(AcceleratorTableTest, CheckDuplicatedRepeatableActions) {
  93. std::set<AcceleratorAction> actions;
  94. for (size_t i = 0; i < kRepeatableActionsLength; ++i) {
  95. EXPECT_TRUE(actions.insert(kRepeatableActions[i]).second)
  96. << "Duplicated action: " << kRepeatableActions[i] << " at index: " << i;
  97. }
  98. }
  99. TEST(AcceleratorTableTest, CheckDeprecatedAccelerators) {
  100. std::set<AcceleratorData, Cmp> deprecated_actions;
  101. for (size_t i = 0; i < kDeprecatedAcceleratorsLength; ++i) {
  102. // A deprecated action can never appear twice in the list.
  103. const AcceleratorData& entry = kDeprecatedAccelerators[i];
  104. EXPECT_TRUE(deprecated_actions.insert(entry).second)
  105. << "Duplicate deprecated accelerator: "
  106. << AcceleratorDataToString(entry);
  107. }
  108. std::set<AcceleratorAction> actions;
  109. for (size_t i = 0; i < kDeprecatedAcceleratorsDataLength; ++i) {
  110. // There must never be any duplicated actions.
  111. const DeprecatedAcceleratorData& data = kDeprecatedAcceleratorsData[i];
  112. EXPECT_TRUE(actions.insert(data.action).second)
  113. << "Deprecated action: " << data.action;
  114. // The UMA histogram name must be of the format "Ash.Accelerators.*"
  115. std::string uma_histogram(data.uma_histogram_name);
  116. EXPECT_TRUE(base::StartsWith(uma_histogram, "Ash.Accelerators.",
  117. base::CompareCase::SENSITIVE));
  118. }
  119. }
  120. // All new accelerators should be Search-based and approved by UX.
  121. TEST(AcceleratorTableTest, CheckSearchBasedAccelerators) {
  122. std::vector<AcceleratorData> non_search_accelerators;
  123. for (size_t i = 0; i < kAcceleratorDataLength; ++i) {
  124. const AcceleratorData& entry = kAcceleratorData[i];
  125. if (entry.modifiers & ui::EF_COMMAND_DOWN)
  126. continue;
  127. non_search_accelerators.emplace_back(entry);
  128. }
  129. for (size_t i = 0; i < kDisableWithNewMappingAcceleratorDataLength; ++i) {
  130. const AcceleratorData& entry = kDisableWithNewMappingAcceleratorData[i];
  131. if (entry.modifiers & ui::EF_COMMAND_DOWN)
  132. continue;
  133. non_search_accelerators.emplace_back(entry);
  134. }
  135. const int accelerators_number = non_search_accelerators.size();
  136. EXPECT_EQ(accelerators_number, kNonSearchAcceleratorsNum)
  137. << "All new accelerators should be Search-based and approved by UX.";
  138. std::stable_sort(non_search_accelerators.begin(),
  139. non_search_accelerators.end(), Cmp());
  140. const std::string non_search_accelerators_hash =
  141. HashAcceleratorData(non_search_accelerators);
  142. EXPECT_EQ(non_search_accelerators_hash, kNonSearchAcceleratorsHash)
  143. << "New accelerators must use the Search key. Please talk to the UX "
  144. "team.\n"
  145. "If you are removing a non-Search-based accelerator, please update "
  146. "the date along with the following values\n"
  147. << "kNonSearchAcceleratorsNum=" << accelerators_number << " and "
  148. << "kNonSearchAcceleratorsHash=\"" << non_search_accelerators_hash
  149. << "\"";
  150. }
  151. } // namespace ash