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/macros.h" | |
9 #include "base/md5.h" | |
8 #include "base/strings/string_util.h" | 10 #include "base/strings/string_util.h" |
11 #include "base/strings/stringprintf.h" | |
9 #include "testing/gtest/include/gtest/gtest.h" | 12 #include "testing/gtest/include/gtest/gtest.h" |
10 | 13 |
11 namespace ash { | 14 namespace ash { |
12 | 15 |
13 namespace { | 16 namespace { |
14 | 17 |
18 // The number of non-Search-based accelerators as of 2017-04-06. | |
19 constexpr int kNonSearchAcceleratorsNum = 92; | |
20 // The hash of non-Search-based accelerators as of 2017-04-06. | |
21 // See HashAcceleratorData(). | |
22 constexpr char kNonSearchAcceleratorsHash[] = | |
23 "6c6695ca5f4d7298504e4d1e8a148902"; | |
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 " | |
39 "action=%d", | |
Daniel Erat
2017/04/06 19:33:33
just using the integer value here like this is fin
| |
40 accelerator.trigger_on_press ? "true" : "false", accelerator.keycode, | |
41 (accelerator.modifiers & ui::EF_SHIFT_DOWN) ? "true" : "false", | |
42 (accelerator.modifiers & ui::EF_CONTROL_DOWN) ? "true" : "false", | |
43 (accelerator.modifiers & ui::EF_ALT_DOWN) ? "true" : "false", | |
44 (accelerator.modifiers & ui::EF_COMMAND_DOWN) ? "true" : "false", | |
45 accelerator.action); | |
46 } | |
47 | |
48 std::string HashAcceleratorData( | |
49 const std::vector<AcceleratorData> accelerators) { | |
50 base::MD5Context context; | |
51 base::MD5Init(&context); | |
52 for (const AcceleratorData& accelerator : accelerators) | |
53 base::MD5Update(&context, AcceleratorDataToString(accelerator)); | |
54 | |
55 base::MD5Digest digest; | |
56 base::MD5Final(&digest, &context); | |
57 return MD5DigestToBase16(digest); | |
58 } | |
59 | |
26 } // namespace | 60 } // namespace |
27 | 61 |
28 TEST(AcceleratorTableTest, CheckDuplicatedAccelerators) { | 62 TEST(AcceleratorTableTest, CheckDuplicatedAccelerators) { |
29 std::set<AcceleratorData, Cmp> accelerators; | 63 std::set<AcceleratorData, Cmp> accelerators; |
30 for (size_t i = 0; i < kAcceleratorDataLength; ++i) { | 64 for (size_t i = 0; i < kAcceleratorDataLength; ++i) { |
31 const AcceleratorData& entry = kAcceleratorData[i]; | 65 const AcceleratorData& entry = kAcceleratorData[i]; |
32 EXPECT_TRUE(accelerators.insert(entry).second) | 66 EXPECT_TRUE(accelerators.insert(entry).second) |
33 << "Duplicated accelerator: " << entry.trigger_on_press << ", " | 67 << "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 } | 68 } |
38 } | 69 } |
39 | 70 |
40 TEST(AcceleratorTableTest, CheckDuplicatedReservedActions) { | 71 TEST(AcceleratorTableTest, CheckDuplicatedReservedActions) { |
41 std::set<AcceleratorAction> actions; | 72 std::set<AcceleratorAction> actions; |
42 for (size_t i = 0; i < kReservedActionsLength; ++i) { | 73 for (size_t i = 0; i < kReservedActionsLength; ++i) { |
43 EXPECT_TRUE(actions.insert(kReservedActions[i]).second) | 74 EXPECT_TRUE(actions.insert(kReservedActions[i]).second) |
44 << "Duplicated action: " << kReservedActions[i]; | 75 << "Duplicated action: " << kReservedActions[i]; |
45 } | 76 } |
46 } | 77 } |
(...skipping 26 matching lines...) Expand all Loading... | |
73 << "Duplicated action: " << kRepeatableActions[i] << " at index: " << i; | 104 << "Duplicated action: " << kRepeatableActions[i] << " at index: " << i; |
74 } | 105 } |
75 } | 106 } |
76 | 107 |
77 TEST(AcceleratorTableTest, CheckDeprecatedAccelerators) { | 108 TEST(AcceleratorTableTest, CheckDeprecatedAccelerators) { |
78 std::set<AcceleratorData, Cmp> deprecated_actions; | 109 std::set<AcceleratorData, Cmp> deprecated_actions; |
79 for (size_t i = 0; i < kDeprecatedAcceleratorsLength; ++i) { | 110 for (size_t i = 0; i < kDeprecatedAcceleratorsLength; ++i) { |
80 // A deprecated action can never appear twice in the list. | 111 // A deprecated action can never appear twice in the list. |
81 const AcceleratorData& entry = kDeprecatedAccelerators[i]; | 112 const AcceleratorData& entry = kDeprecatedAccelerators[i]; |
82 EXPECT_TRUE(deprecated_actions.insert(entry).second) | 113 EXPECT_TRUE(deprecated_actions.insert(entry).second) |
83 << "Duplicate deprecated accelerator: " << entry.trigger_on_press | 114 << "Duplicate deprecated accelerator: " |
84 << ", " << entry.keycode << ", " | 115 << AcceleratorDataToString(entry); |
85 << (entry.modifiers & ui::EF_SHIFT_DOWN) << ", " | |
86 << (entry.modifiers & ui::EF_CONTROL_DOWN) << ", " | |
87 << (entry.modifiers & ui::EF_ALT_DOWN); | |
88 } | 116 } |
89 | 117 |
90 std::set<AcceleratorAction> actions; | 118 std::set<AcceleratorAction> actions; |
91 for (size_t i = 0; i < kDeprecatedAcceleratorsDataLength; ++i) { | 119 for (size_t i = 0; i < kDeprecatedAcceleratorsDataLength; ++i) { |
92 // There must never be any duplicated actions. | 120 // There must never be any duplicated actions. |
93 const DeprecatedAcceleratorData& data = kDeprecatedAcceleratorsData[i]; | 121 const DeprecatedAcceleratorData& data = kDeprecatedAcceleratorsData[i]; |
94 EXPECT_TRUE(actions.insert(data.action).second) << "Deprecated action: " | 122 EXPECT_TRUE(actions.insert(data.action).second) << "Deprecated action: " |
95 << data.action; | 123 << data.action; |
96 | 124 |
97 // The UMA histogram name must be of the format "Ash.Accelerators.*" | 125 // The UMA histogram name must be of the format "Ash.Accelerators.*" |
98 std::string uma_histogram(data.uma_histogram_name); | 126 std::string uma_histogram(data.uma_histogram_name); |
99 EXPECT_TRUE(base::StartsWith(uma_histogram, "Ash.Accelerators.", | 127 EXPECT_TRUE(base::StartsWith(uma_histogram, "Ash.Accelerators.", |
100 base::CompareCase::SENSITIVE)); | 128 base::CompareCase::SENSITIVE)); |
101 } | 129 } |
102 } | 130 } |
103 | 131 |
132 // All new accelerators should be Search-based and approved by UX. | |
133 TEST(AcceleratorTableTest, CheckSearchBasedAccelerators) { | |
134 std::vector<AcceleratorData> non_search_accelerators; | |
135 for (size_t i = 0; i < kAcceleratorDataLength; ++i) { | |
136 const AcceleratorData& entry = kAcceleratorData[i]; | |
137 if (entry.modifiers & ui::EF_COMMAND_DOWN) | |
138 continue; | |
139 non_search_accelerators.emplace_back(entry); | |
140 } | |
141 | |
142 const int accelerators_number = non_search_accelerators.size(); | |
143 EXPECT_LE(accelerators_number, kNonSearchAcceleratorsNum) | |
144 << "All new accelerators should be Search-based and approved by UX."; | |
145 | |
146 std::stable_sort(non_search_accelerators.begin(), | |
147 non_search_accelerators.end(), Cmp()); | |
148 const std::string non_search_accelerators_hash = | |
149 HashAcceleratorData(non_search_accelerators); | |
150 | |
151 EXPECT_EQ(non_search_accelerators_hash, kNonSearchAcceleratorsHash) | |
152 << "New accelerators must use the Search key. Please talk to the UX " | |
153 "team.\n" | |
154 "If you are removing a non-Search-based accelerator, please update " | |
155 "the date along with the following values\n" | |
156 << "kNonSearchAcceleratorsNum=" << accelerators_number << " and " | |
157 << "kNonSearchAcceleratorsHash=\"" << non_search_accelerators_hash | |
158 << "\""; | |
159 } | |
160 | |
104 } // namespace ash | 161 } // namespace ash |
OLD | NEW |