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