1 // Copyright 2019 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 
5 #include "ui/accessibility/ax_enum_util.h"
6 
7 #include <string>
8 #include <vector>
9 
10 #include "testing/gtest/include/gtest/gtest.h"
11 #include "ui/accessibility/ax_enums.mojom.h"
12 #include "ui/accessibility/ax_node_data.h"
13 
14 namespace ui {
15 
16 // Templatized function that tests that for a mojom enum
17 // such as ax::mojom::Role, ax::mojom::Event, etc. we can
18 // call ToString() on the enum to get a string, and then
19 // ParseAXEnum() on the string to get back the original
20 // value. Also tests what happens when we call ToString
21 // or ParseAXEnum on a bogus value.
22 template <typename T>
TestEnumStringConversion(int32_t (step)(int32_t)=[](int32_t val){})23 void TestEnumStringConversion(
24     int32_t(step)(int32_t) = [](int32_t val) { return val + 1; }) {
25   // Check every valid enum value.
26   for (int i = static_cast<int>(T::kMinValue);
27        i <= static_cast<int>(T::kMaxValue); i = step(i)) {
28     T src = static_cast<T>(i);
29     std::string str = ToString(src);
30     auto dst = ParseAXEnum<T>(str.c_str());
31     EXPECT_EQ(src, dst);
32   }
33 
34   // Trying to parse a bogus string should crash.
35   // TODO(http://crbug.com/1129919) - try to re-enable this death test.
36   // EXPECT_DEATH_IF_SUPPORTED(ParseAXEnum<T>("bogus"), "Check failed");
37 
38   // Parse the empty string.
39   EXPECT_EQ(T::kNone, ParseAXEnum<T>(""));
40 
41   // Convert a bogus value to a string.
42   int out_of_range_value = static_cast<int>(T::kMaxValue) + 1;
43   EXPECT_STREQ("", ToString(static_cast<T>(out_of_range_value)));
44 }
45 
46 // Templatized function that tries calling a setter on AXNodeData
47 // such as AddIntAttribute, AddFloatAttribute - with each possible
48 // enum value.
49 //
50 // This variant is for cases where the value type is an object.
51 template <typename T, typename U>
TestAXNodeDataSetter(void (AXNodeData::* Setter)(T,const U &),const U & value)52 void TestAXNodeDataSetter(void (AXNodeData::*Setter)(T, const U&),
53                           const U& value) {
54   AXNodeData node_data;
55   for (int i = static_cast<int>(T::kMinValue) + 1;
56        i <= static_cast<int>(T::kMaxValue); ++i) {
57     T attr = static_cast<T>(i);
58     ((node_data).*(Setter))(attr, value);
59   }
60   EXPECT_TRUE(!node_data.ToString().empty());
61 }
62 
63 // Same as TextAXNodeData, above, but This variant is for
64 // cases where the value type is POD.
65 template <typename T, typename U>
TestAXNodeDataSetter(void (AXNodeData::* Setter)(T,U),U value)66 void TestAXNodeDataSetter(void (AXNodeData::*Setter)(T, U), U value) {
67   AXNodeData node_data;
68   for (int i = static_cast<int>(T::kMinValue) + 1;
69        i <= static_cast<int>(T::kMaxValue); ++i) {
70     T attr = static_cast<T>(i);
71     ((node_data).*(Setter))(attr, value);
72   }
73   EXPECT_TRUE(!node_data.ToString().empty());
74 }
75 
TEST(AXEnumUtilTest,Event)76 TEST(AXEnumUtilTest, Event) {
77   TestEnumStringConversion<ax::mojom::Event>();
78 }
79 
TEST(AXEnumUtilTest,Role)80 TEST(AXEnumUtilTest, Role) {
81   TestEnumStringConversion<ax::mojom::Role>();
82 }
83 
TEST(AXEnumUtilTest,State)84 TEST(AXEnumUtilTest, State) {
85   TestEnumStringConversion<ax::mojom::State>();
86 }
87 
TEST(AXEnumUtilTest,Action)88 TEST(AXEnumUtilTest, Action) {
89   TestEnumStringConversion<ax::mojom::Action>();
90 }
91 
TEST(AXEnumUtilTest,ActionFlags)92 TEST(AXEnumUtilTest, ActionFlags) {
93   TestEnumStringConversion<ax::mojom::ActionFlags>();
94 }
95 
TEST(AXEnumUtilTest,DefaultActionVerb)96 TEST(AXEnumUtilTest, DefaultActionVerb) {
97   TestEnumStringConversion<ax::mojom::DefaultActionVerb>();
98 }
99 
TEST(AXEnumUtilTest,Mutation)100 TEST(AXEnumUtilTest, Mutation) {
101   TestEnumStringConversion<ax::mojom::Mutation>();
102 }
103 
TEST(AXEnumUtilTest,StringAttribute)104 TEST(AXEnumUtilTest, StringAttribute) {
105   TestEnumStringConversion<ax::mojom::StringAttribute>();
106   TestAXNodeDataSetter<ax::mojom::StringAttribute>(
107       &AXNodeData::AddStringAttribute, std::string());
108 }
109 
TEST(AXEnumUtilTest,IntAttribute)110 TEST(AXEnumUtilTest, IntAttribute) {
111   TestEnumStringConversion<ax::mojom::IntAttribute>();
112   TestAXNodeDataSetter<ax::mojom::IntAttribute>(&AXNodeData::AddIntAttribute,
113                                                 0);
114 }
115 
TEST(AXEnumUtilTest,FloatAttribute)116 TEST(AXEnumUtilTest, FloatAttribute) {
117   TestEnumStringConversion<ax::mojom::FloatAttribute>();
118   TestAXNodeDataSetter<ax::mojom::FloatAttribute>(
119       &AXNodeData::AddFloatAttribute, 0.0f);
120 }
121 
TEST(AXEnumUtilTest,BoolAttribute)122 TEST(AXEnumUtilTest, BoolAttribute) {
123   TestEnumStringConversion<ax::mojom::BoolAttribute>();
124   TestAXNodeDataSetter<ax::mojom::BoolAttribute>(&AXNodeData::AddBoolAttribute,
125                                                  false);
126 }
127 
TEST(AXEnumUtilTest,IntListAttribute)128 TEST(AXEnumUtilTest, IntListAttribute) {
129   TestEnumStringConversion<ax::mojom::IntListAttribute>();
130   TestAXNodeDataSetter<ax::mojom::IntListAttribute>(
131       &AXNodeData::AddIntListAttribute, std::vector<int32_t>());
132 }
133 
TEST(AXEnumUtilTest,StringListAttribute)134 TEST(AXEnumUtilTest, StringListAttribute) {
135   TestEnumStringConversion<ax::mojom::StringListAttribute>();
136   TestAXNodeDataSetter<ax::mojom::StringListAttribute>(
137       &AXNodeData::AddStringListAttribute, std::vector<std::string>());
138 }
139 
TEST(AXEnumUtilTest,MarkerType)140 TEST(AXEnumUtilTest, MarkerType) {
141   TestEnumStringConversion<ax::mojom::MarkerType>(
142       [](int32_t val) {
143         return val == 0 ? 1 :
144                         // 8 (Composition) is
145                         // explicitly skipped in
146                         // ax_enums.mojom.
147                    val == 4 ? 16 : val * 2;
148       });
149 }
150 
TEST(AXEnumUtilTest,Text_Decoration_Style)151 TEST(AXEnumUtilTest, Text_Decoration_Style) {
152   TestEnumStringConversion<ax::mojom::TextDecorationStyle>();
153 }
154 
TEST(AXEnumUtilTest,ListStyle)155 TEST(AXEnumUtilTest, ListStyle) {
156   TestEnumStringConversion<ax::mojom::ListStyle>();
157 }
158 
TEST(AXEnumUtilTest,MoveDirection)159 TEST(AXEnumUtilTest, MoveDirection) {
160   TestEnumStringConversion<ax::mojom::MoveDirection>();
161 }
162 
TEST(AXEnumUtilTest,Command)163 TEST(AXEnumUtilTest, Command) {
164   TestEnumStringConversion<ax::mojom::Command>();
165 }
166 
TEST(AXEnumUtilTest,InputEventType)167 TEST(AXEnumUtilTest, InputEventType) {
168   TestEnumStringConversion<ax::mojom::InputEventType>();
169 }
170 
TEST(AXEnumUtilTest,TextBoundary)171 TEST(AXEnumUtilTest, TextBoundary) {
172   TestEnumStringConversion<ax::mojom::TextBoundary>();
173 }
174 
TEST(AXEnumUtilTest,TextAlign)175 TEST(AXEnumUtilTest, TextAlign) {
176   TestEnumStringConversion<ax::mojom::TextAlign>();
177 }
178 
TEST(AXEnumUtilTest,WritingDirection)179 TEST(AXEnumUtilTest, WritingDirection) {
180   TestEnumStringConversion<ax::mojom::WritingDirection>();
181 }
182 
TEST(AXEnumUtilTest,TextPosition)183 TEST(AXEnumUtilTest, TextPosition) {
184   TestEnumStringConversion<ax::mojom::TextPosition>();
185 }
186 
TEST(AXEnumUtilTest,TextStyle)187 TEST(AXEnumUtilTest, TextStyle) {
188   TestEnumStringConversion<ax::mojom::TextStyle>();
189 }
190 
TEST(AXEnumUtilTest,AriaCurrentState)191 TEST(AXEnumUtilTest, AriaCurrentState) {
192   TestEnumStringConversion<ax::mojom::AriaCurrentState>();
193 }
194 
TEST(AXEnumUtilTest,HasPopup)195 TEST(AXEnumUtilTest, HasPopup) {
196   TestEnumStringConversion<ax::mojom::HasPopup>();
197 }
198 
TEST(AXEnumUtilTest,InvalidState)199 TEST(AXEnumUtilTest, InvalidState) {
200   TestEnumStringConversion<ax::mojom::InvalidState>();
201 }
202 
TEST(AXEnumUtilTest,Restriction)203 TEST(AXEnumUtilTest, Restriction) {
204   TestEnumStringConversion<ax::mojom::Restriction>();
205 }
206 
TEST(AXEnumUtilTest,CheckedState)207 TEST(AXEnumUtilTest, CheckedState) {
208   TestEnumStringConversion<ax::mojom::CheckedState>();
209 }
210 
TEST(AXEnumUtilTest,SortDirection)211 TEST(AXEnumUtilTest, SortDirection) {
212   TestEnumStringConversion<ax::mojom::SortDirection>();
213 }
214 
TEST(AXEnumUtilTest,NameFrom)215 TEST(AXEnumUtilTest, NameFrom) {
216   TestEnumStringConversion<ax::mojom::NameFrom>();
217 }
218 
TEST(AXEnumUtilTest,DescriptionFrom)219 TEST(AXEnumUtilTest, DescriptionFrom) {
220   TestEnumStringConversion<ax::mojom::DescriptionFrom>();
221 }
222 
TEST(AXEnumUtilTest,EventFrom)223 TEST(AXEnumUtilTest, EventFrom) {
224   TestEnumStringConversion<ax::mojom::EventFrom>();
225 }
226 
TEST(AXEnumUtilTest,Gesture)227 TEST(AXEnumUtilTest, Gesture) {
228   TestEnumStringConversion<ax::mojom::Gesture>();
229 }
230 
TEST(AXEnumUtilTest,TextAffinity)231 TEST(AXEnumUtilTest, TextAffinity) {
232   TestEnumStringConversion<ax::mojom::TextAffinity>();
233 }
234 
TEST(AXEnumUtilTest,TreeOrder)235 TEST(AXEnumUtilTest, TreeOrder) {
236   TestEnumStringConversion<ax::mojom::TreeOrder>();
237 }
238 
TEST(AXEnumUtilTest,ImageAnnotationStatus)239 TEST(AXEnumUtilTest, ImageAnnotationStatus) {
240   TestEnumStringConversion<ax::mojom::ImageAnnotationStatus>();
241 }
242 
TEST(AXEnumUtilTest,Dropeffect)243 TEST(AXEnumUtilTest, Dropeffect) {
244   TestEnumStringConversion<ax::mojom::Dropeffect>();
245 }
246 
247 }  // namespace ui
248