Index: ash/common/accelerators/accelerator_table_unittest.cc |
diff --git a/ash/common/accelerators/accelerator_table_unittest.cc b/ash/common/accelerators/accelerator_table_unittest.cc |
index e469625545a0282e11a622e8ac2eff0d9b5d65da..8a4c32dabc0e567ff5dc22d2cb0fad0f7cf18850 100644 |
--- a/ash/common/accelerators/accelerator_table_unittest.cc |
+++ b/ash/common/accelerators/accelerator_table_unittest.cc |
@@ -5,13 +5,23 @@ |
#include <set> |
#include "ash/common/accelerators/accelerator_table.h" |
+#include "base/macros.h" |
+#include "base/md5.h" |
#include "base/strings/string_util.h" |
+#include "base/strings/stringprintf.h" |
#include "testing/gtest/include/gtest/gtest.h" |
namespace ash { |
namespace { |
+// The number of non-Search-based accelerators as of 2017-04-06. |
+constexpr int kNonSearchAcceleratorsNum = 92; |
+// The hash of non-Search-based accelerators as of 2017-04-06. |
+// See HashAcceleratorData(). |
+constexpr char kNonSearchAcceleratorsHash[] = |
+ "6c6695ca5f4d7298504e4d1e8a148902"; |
+ |
struct Cmp { |
bool operator()(const AcceleratorData& lhs, const AcceleratorData& rhs) { |
if (lhs.trigger_on_press != rhs.trigger_on_press) |
@@ -23,6 +33,30 @@ struct Cmp { |
} |
}; |
+std::string AcceleratorDataToString(const AcceleratorData& accelerator) { |
+ return base::StringPrintf( |
+ "trigger_on_press=%s keycode=%d shift=%s control=%s alt=%s search=%s " |
+ "action=%d", |
Daniel Erat
2017/04/06 19:33:33
just using the integer value here like this is fin
|
+ accelerator.trigger_on_press ? "true" : "false", accelerator.keycode, |
+ (accelerator.modifiers & ui::EF_SHIFT_DOWN) ? "true" : "false", |
+ (accelerator.modifiers & ui::EF_CONTROL_DOWN) ? "true" : "false", |
+ (accelerator.modifiers & ui::EF_ALT_DOWN) ? "true" : "false", |
+ (accelerator.modifiers & ui::EF_COMMAND_DOWN) ? "true" : "false", |
+ accelerator.action); |
+} |
+ |
+std::string HashAcceleratorData( |
+ const std::vector<AcceleratorData> accelerators) { |
+ base::MD5Context context; |
+ base::MD5Init(&context); |
+ for (const AcceleratorData& accelerator : accelerators) |
+ base::MD5Update(&context, AcceleratorDataToString(accelerator)); |
+ |
+ base::MD5Digest digest; |
+ base::MD5Final(&digest, &context); |
+ return MD5DigestToBase16(digest); |
+} |
+ |
} // namespace |
TEST(AcceleratorTableTest, CheckDuplicatedAccelerators) { |
@@ -30,10 +64,7 @@ TEST(AcceleratorTableTest, CheckDuplicatedAccelerators) { |
for (size_t i = 0; i < kAcceleratorDataLength; ++i) { |
const AcceleratorData& entry = kAcceleratorData[i]; |
EXPECT_TRUE(accelerators.insert(entry).second) |
- << "Duplicated accelerator: " << entry.trigger_on_press << ", " |
- << entry.keycode << ", " << (entry.modifiers & ui::EF_SHIFT_DOWN) |
- << ", " << (entry.modifiers & ui::EF_CONTROL_DOWN) << ", " |
- << (entry.modifiers & ui::EF_ALT_DOWN); |
+ << "Duplicated accelerator: " << AcceleratorDataToString(entry); |
} |
} |
@@ -80,11 +111,8 @@ TEST(AcceleratorTableTest, CheckDeprecatedAccelerators) { |
// A deprecated action can never appear twice in the list. |
const AcceleratorData& entry = kDeprecatedAccelerators[i]; |
EXPECT_TRUE(deprecated_actions.insert(entry).second) |
- << "Duplicate deprecated accelerator: " << entry.trigger_on_press |
- << ", " << entry.keycode << ", " |
- << (entry.modifiers & ui::EF_SHIFT_DOWN) << ", " |
- << (entry.modifiers & ui::EF_CONTROL_DOWN) << ", " |
- << (entry.modifiers & ui::EF_ALT_DOWN); |
+ << "Duplicate deprecated accelerator: " |
+ << AcceleratorDataToString(entry); |
} |
std::set<AcceleratorAction> actions; |
@@ -101,4 +129,33 @@ TEST(AcceleratorTableTest, CheckDeprecatedAccelerators) { |
} |
} |
+// All new accelerators should be Search-based and approved by UX. |
+TEST(AcceleratorTableTest, CheckSearchBasedAccelerators) { |
+ std::vector<AcceleratorData> non_search_accelerators; |
+ for (size_t i = 0; i < kAcceleratorDataLength; ++i) { |
+ const AcceleratorData& entry = kAcceleratorData[i]; |
+ if (entry.modifiers & ui::EF_COMMAND_DOWN) |
+ continue; |
+ non_search_accelerators.emplace_back(entry); |
+ } |
+ |
+ const int accelerators_number = non_search_accelerators.size(); |
+ EXPECT_LE(accelerators_number, kNonSearchAcceleratorsNum) |
+ << "All new accelerators should be Search-based and approved by UX."; |
+ |
+ std::stable_sort(non_search_accelerators.begin(), |
+ non_search_accelerators.end(), Cmp()); |
+ const std::string non_search_accelerators_hash = |
+ HashAcceleratorData(non_search_accelerators); |
+ |
+ EXPECT_EQ(non_search_accelerators_hash, kNonSearchAcceleratorsHash) |
+ << "New accelerators must use the Search key. Please talk to the UX " |
+ "team.\n" |
+ "If you are removing a non-Search-based accelerator, please update " |
+ "the date along with the following values\n" |
+ << "kNonSearchAcceleratorsNum=" << accelerators_number << " and " |
+ << "kNonSearchAcceleratorsHash=\"" << non_search_accelerators_hash |
+ << "\""; |
+} |
+ |
} // namespace ash |