Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include <set> | 5 #include <set> |
| 6 | 6 |
| 7 #include "ash/common/accelerators/accelerator_table.h" | 7 #include "ash/common/accelerators/accelerator_table.h" |
| 8 #include "base/bit_cast.h" | |
|
afakhry
2017/04/06 17:50:29
You don't need this header, do you?
wutao
2017/04/06 19:06:10
I do not need it, removed.
| |
| 9 #include "base/macros.h" | |
| 10 #include "base/md5.h" | |
| 8 #include "base/strings/string_util.h" | 11 #include "base/strings/string_util.h" |
| 12 #include "base/strings/stringprintf.h" | |
| 9 #include "testing/gtest/include/gtest/gtest.h" | 13 #include "testing/gtest/include/gtest/gtest.h" |
| 10 | 14 |
| 11 namespace ash { | 15 namespace ash { |
| 12 | 16 |
| 13 namespace { | 17 namespace { |
| 14 | 18 |
| 19 // The snapshot of non-Search-based acclerators number. | |
|
Daniel Erat
2017/04/06 18:04:55
nit: s/acclerators/accelerators/, but something li
wutao
2017/04/06 19:06:11
Done.
| |
| 20 const int kNonSearchAcceleratorsNum = 92; | |
|
afakhry
2017/04/06 17:50:29
constexpr
wutao
2017/04/06 19:06:10
Done.
| |
| 21 // The snapshot of non-Search-based acclerators hash. | |
|
Daniel Erat
2017/04/06 18:04:56
also change this to something like:
// The hash o
wutao
2017/04/06 19:06:11
Done.
| |
| 22 const std::string kNonSearchAcceleratorsHash = | |
|
afakhry
2017/04/06 17:50:29
A global string object? Hmm, I haven't seen that b
Daniel Erat
2017/04/06 18:04:56
nope, this isn't allowed (since std::string isn't
wutao
2017/04/06 19:06:10
Acknowledged.
wutao
2017/04/06 19:06:10
Done.
| |
| 23 "a8801bb755aba2d1097a4d870386eab4"; | |
| 24 | |
| 15 struct Cmp { | 25 struct Cmp { |
| 16 bool operator()(const AcceleratorData& lhs, const AcceleratorData& rhs) { | 26 bool operator()(const AcceleratorData& lhs, const AcceleratorData& rhs) { |
| 17 if (lhs.trigger_on_press != rhs.trigger_on_press) | 27 if (lhs.trigger_on_press != rhs.trigger_on_press) |
| 18 return lhs.trigger_on_press < rhs.trigger_on_press; | 28 return lhs.trigger_on_press < rhs.trigger_on_press; |
| 19 if (lhs.keycode != rhs.keycode) | 29 if (lhs.keycode != rhs.keycode) |
| 20 return lhs.keycode < rhs.keycode; | 30 return lhs.keycode < rhs.keycode; |
| 21 return lhs.modifiers < rhs.modifiers; | 31 return lhs.modifiers < rhs.modifiers; |
| 22 // Do not check |action|. | 32 // Do not check |action|. |
| 23 } | 33 } |
| 24 }; | 34 }; |
| 25 | 35 |
| 36 std::string AcceleratorDataToString(const AcceleratorData& accelerator) { | |
| 37 return base::StringPrintf( | |
| 38 "trigger_on_press=%s keycode=%d SHIFT=%s CONTROL=%s ALT=%s SEARCH=%s", | |
|
Daniel Erat
2017/04/06 18:04:55
did you mean to include the action here as well? i
wutao
2017/04/06 19:06:10
Changed to lowercase.
For the action, is the enum
| |
| 39 accelerator.trigger_on_press ? "true" : "false", accelerator.keycode, | |
| 40 (accelerator.modifiers & ui::EF_SHIFT_DOWN) ? "true" : "false", | |
| 41 (accelerator.modifiers & ui::EF_CONTROL_DOWN) ? "true" : "false", | |
| 42 (accelerator.modifiers & ui::EF_ALT_DOWN) ? "true" : "false", | |
| 43 (accelerator.modifiers & ui::EF_COMMAND_DOWN) ? "true" : "false"); | |
| 44 } | |
| 45 | |
| 46 std::string HashAcceleratorData( | |
| 47 const std::vector<AcceleratorData> accelerators) { | |
| 48 base::MD5Digest digest; | |
| 49 base::MD5Sum(reinterpret_cast<const char*>(&accelerators[0]), | |
| 50 sizeof(accelerators[0]) * accelerators.size(), &digest); | |
|
Daniel Erat
2017/04/06 18:04:55
will this have endianness issues?
i'm wondering i
wutao
2017/04/06 19:06:10
Nice! done.
| |
| 51 return MD5DigestToBase16(digest); | |
| 52 } | |
| 53 | |
| 26 } // namespace | 54 } // namespace |
| 27 | 55 |
| 28 TEST(AcceleratorTableTest, CheckDuplicatedAccelerators) { | 56 TEST(AcceleratorTableTest, CheckDuplicatedAccelerators) { |
| 29 std::set<AcceleratorData, Cmp> accelerators; | 57 std::set<AcceleratorData, Cmp> accelerators; |
| 30 for (size_t i = 0; i < kAcceleratorDataLength; ++i) { | 58 for (size_t i = 0; i < kAcceleratorDataLength; ++i) { |
| 31 const AcceleratorData& entry = kAcceleratorData[i]; | 59 const AcceleratorData& entry = kAcceleratorData[i]; |
| 32 EXPECT_TRUE(accelerators.insert(entry).second) | 60 EXPECT_TRUE(accelerators.insert(entry).second) |
| 33 << "Duplicated accelerator: " << entry.trigger_on_press << ", " | 61 << "Duplicated accelerator: " << AcceleratorDataToString(entry); |
| 34 << entry.keycode << ", " << (entry.modifiers & ui::EF_SHIFT_DOWN) | |
| 35 << ", " << (entry.modifiers & ui::EF_CONTROL_DOWN) << ", " | |
| 36 << (entry.modifiers & ui::EF_ALT_DOWN); | |
| 37 } | 62 } |
| 38 } | 63 } |
| 39 | 64 |
| 40 TEST(AcceleratorTableTest, CheckDuplicatedReservedActions) { | 65 TEST(AcceleratorTableTest, CheckDuplicatedReservedActions) { |
| 41 std::set<AcceleratorAction> actions; | 66 std::set<AcceleratorAction> actions; |
| 42 for (size_t i = 0; i < kReservedActionsLength; ++i) { | 67 for (size_t i = 0; i < kReservedActionsLength; ++i) { |
| 43 EXPECT_TRUE(actions.insert(kReservedActions[i]).second) | 68 EXPECT_TRUE(actions.insert(kReservedActions[i]).second) |
| 44 << "Duplicated action: " << kReservedActions[i]; | 69 << "Duplicated action: " << kReservedActions[i]; |
| 45 } | 70 } |
| 46 } | 71 } |
| (...skipping 26 matching lines...) Expand all Loading... | |
| 73 << "Duplicated action: " << kRepeatableActions[i] << " at index: " << i; | 98 << "Duplicated action: " << kRepeatableActions[i] << " at index: " << i; |
| 74 } | 99 } |
| 75 } | 100 } |
| 76 | 101 |
| 77 TEST(AcceleratorTableTest, CheckDeprecatedAccelerators) { | 102 TEST(AcceleratorTableTest, CheckDeprecatedAccelerators) { |
| 78 std::set<AcceleratorData, Cmp> deprecated_actions; | 103 std::set<AcceleratorData, Cmp> deprecated_actions; |
| 79 for (size_t i = 0; i < kDeprecatedAcceleratorsLength; ++i) { | 104 for (size_t i = 0; i < kDeprecatedAcceleratorsLength; ++i) { |
| 80 // A deprecated action can never appear twice in the list. | 105 // A deprecated action can never appear twice in the list. |
| 81 const AcceleratorData& entry = kDeprecatedAccelerators[i]; | 106 const AcceleratorData& entry = kDeprecatedAccelerators[i]; |
| 82 EXPECT_TRUE(deprecated_actions.insert(entry).second) | 107 EXPECT_TRUE(deprecated_actions.insert(entry).second) |
| 83 << "Duplicate deprecated accelerator: " << entry.trigger_on_press | 108 << "Duplicate deprecated accelerator: " |
| 84 << ", " << entry.keycode << ", " | 109 << AcceleratorDataToString(entry); |
| 85 << (entry.modifiers & ui::EF_SHIFT_DOWN) << ", " | |
| 86 << (entry.modifiers & ui::EF_CONTROL_DOWN) << ", " | |
| 87 << (entry.modifiers & ui::EF_ALT_DOWN); | |
| 88 } | 110 } |
| 89 | 111 |
| 90 std::set<AcceleratorAction> actions; | 112 std::set<AcceleratorAction> actions; |
| 91 for (size_t i = 0; i < kDeprecatedAcceleratorsDataLength; ++i) { | 113 for (size_t i = 0; i < kDeprecatedAcceleratorsDataLength; ++i) { |
| 92 // There must never be any duplicated actions. | 114 // There must never be any duplicated actions. |
| 93 const DeprecatedAcceleratorData& data = kDeprecatedAcceleratorsData[i]; | 115 const DeprecatedAcceleratorData& data = kDeprecatedAcceleratorsData[i]; |
| 94 EXPECT_TRUE(actions.insert(data.action).second) << "Deprecated action: " | 116 EXPECT_TRUE(actions.insert(data.action).second) << "Deprecated action: " |
| 95 << data.action; | 117 << data.action; |
| 96 | 118 |
| 97 // The UMA histogram name must be of the format "Ash.Accelerators.*" | 119 // The UMA histogram name must be of the format "Ash.Accelerators.*" |
| 98 std::string uma_histogram(data.uma_histogram_name); | 120 std::string uma_histogram(data.uma_histogram_name); |
| 99 EXPECT_TRUE(base::StartsWith(uma_histogram, "Ash.Accelerators.", | 121 EXPECT_TRUE(base::StartsWith(uma_histogram, "Ash.Accelerators.", |
| 100 base::CompareCase::SENSITIVE)); | 122 base::CompareCase::SENSITIVE)); |
| 101 } | 123 } |
| 102 } | 124 } |
| 103 | 125 |
| 126 // All new accelerators should be Search-based and approved by UX. | |
| 127 TEST(AcceleratorTableTest, CheckSearchBasedAccelerators) { | |
| 128 std::vector<AcceleratorData> non_search_accelerators; | |
| 129 for (size_t i = 0; i < kAcceleratorDataLength; ++i) { | |
| 130 const AcceleratorData& entry = kAcceleratorData[i]; | |
| 131 if (entry.modifiers & ui::EF_COMMAND_DOWN) | |
| 132 continue; | |
| 133 non_search_accelerators.emplace_back(entry); | |
| 134 } | |
| 135 | |
| 136 const size_t accelerators_number = non_search_accelerators.size(); | |
| 137 EXPECT_TRUE(accelerators_number <= kNonSearchAcceleratorsNum) | |
|
Daniel Erat
2017/04/06 18:04:55
use EXPECT_LE instead
wutao
2017/04/06 19:06:11
Done.
| |
| 138 << "All new accelerators should be Search-based and approved by UX."; | |
| 139 | |
| 140 std::stable_sort(non_search_accelerators.begin(), | |
| 141 non_search_accelerators.end(), Cmp()); | |
| 142 const std::string non_search_accelerators_hash = | |
| 143 HashAcceleratorData(non_search_accelerators); | |
| 144 | |
| 145 EXPECT_EQ(non_search_accelerators_hash, kNonSearchAcceleratorsHash) | |
| 146 << "If you are changing accelerator modifier to non-Search-based, please " | |
| 147 "consider using Search-based modifier and get approval from UX.\n" | |
|
Daniel Erat
2017/04/06 18:04:55
i'd word this more strongly, e.g.
New accelerator
| |
| 148 "If you are removing non-Search-based accelerators, please update\n" | |
| 149 << "kNonSearchAcceleratorsNum=" << accelerators_number << " and " | |
| 150 << "kNonSearchAcceleratorsHash=\"" << non_search_accelerators_hash | |
| 151 << "\""; | |
| 152 } | |
| 153 | |
| 104 } // namespace ash | 154 } // namespace ash |
| OLD | NEW |