- add sources.
[platform/framework/web/crosswalk.git] / src / content / browser / accessibility / dump_accessibility_tree_browsertest.cc
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
3 // found in the LICENSE file.
4
5 #include <set>
6 #include <string>
7 #include <vector>
8
9 #include "base/file_util.h"
10 #include "base/logging.h"
11 #include "base/path_service.h"
12 #include "base/strings/string16.h"
13 #include "base/strings/string_split.h"
14 #include "base/strings/string_util.h"
15 #include "base/strings/utf_string_conversions.h"
16 #include "content/browser/accessibility/accessibility_tree_formatter.h"
17 #include "content/browser/accessibility/browser_accessibility.h"
18 #include "content/browser/accessibility/browser_accessibility_manager.h"
19 #include "content/browser/renderer_host/render_view_host_impl.h"
20 #include "content/port/browser/render_widget_host_view_port.h"
21 #include "content/public/browser/web_contents.h"
22 #include "content/public/common/content_paths.h"
23 #include "content/public/common/url_constants.h"
24 #include "content/shell/browser/shell.h"
25 #include "content/test/accessibility_browser_test_utils.h"
26 #include "content/test/content_browser_test.h"
27 #include "content/test/content_browser_test_utils.h"
28 #include "testing/gtest/include/gtest/gtest.h"
29
30 // TODO(dmazzoni): Disabled accessibility tests on Win64. crbug.com/179717
31 #if defined(OS_WIN) && defined(ARCH_CPU_X86_64)
32 #define MAYBE(x) DISABLED_##x
33 #else
34 #define MAYBE(x) x
35 #endif
36
37 namespace content {
38
39 namespace {
40
41 const char kCommentToken = '#';
42 const char kMarkSkipFile[] = "#<skip";
43 const char kMarkEndOfFile[] = "<-- End-of-file -->";
44 const char kSignalDiff[] = "*";
45
46 }  // namespace
47
48 typedef AccessibilityTreeFormatter::Filter Filter;
49
50 // This test takes a snapshot of the platform BrowserAccessibility tree and
51 // tests it against an expected baseline.
52 //
53 // The flow of the test is as outlined below.
54 // 1. Load an html file from chrome/test/data/accessibility.
55 // 2. Read the expectation.
56 // 3. Browse to the page and serialize the platform specific tree into a human
57 //    readable string.
58 // 4. Perform a comparison between actual and expected and fail if they do not
59 //    exactly match.
60 class DumpAccessibilityTreeTest : public ContentBrowserTest {
61  public:
62   // Utility helper that does a comment aware equality check.
63   // Returns array of lines from expected file which are different.
64   std::vector<int> DiffLines(const std::vector<std::string>& expected_lines,
65                              const std::vector<std::string>& actual_lines) {
66     int actual_lines_count = actual_lines.size();
67     int expected_lines_count = expected_lines.size();
68     std::vector<int> diff_lines;
69     int i = 0, j = 0;
70     while (i < actual_lines_count && j < expected_lines_count) {
71       if (expected_lines[j].size() == 0 ||
72           expected_lines[j][0] == kCommentToken) {
73         // Skip comment lines and blank lines in expected output.
74         ++j;
75         continue;
76       }
77
78       if (actual_lines[i] != expected_lines[j])
79         diff_lines.push_back(j);
80       ++i;
81       ++j;
82     }
83
84     // Actual file has been fully checked.
85     return diff_lines;
86   }
87
88   void AddDefaultFilters(std::vector<Filter>* filters) {
89     filters->push_back(Filter(ASCIIToUTF16("FOCUSABLE"), Filter::ALLOW));
90     filters->push_back(Filter(ASCIIToUTF16("READONLY"), Filter::ALLOW));
91     filters->push_back(Filter(ASCIIToUTF16("*=''"), Filter::DENY));
92   }
93
94   void ParseFilters(const std::string& test_html,
95                     std::vector<Filter>* filters) {
96     std::vector<std::string> lines;
97     base::SplitString(test_html, '\n', &lines);
98     for (std::vector<std::string>::const_iterator iter = lines.begin();
99          iter != lines.end();
100          ++iter) {
101       const std::string& line = *iter;
102       const std::string& allow_empty_str =
103           AccessibilityTreeFormatter::GetAllowEmptyString();
104       const std::string& allow_str =
105           AccessibilityTreeFormatter::GetAllowString();
106       const std::string& deny_str =
107           AccessibilityTreeFormatter::GetDenyString();
108       if (StartsWithASCII(line, allow_empty_str, true)) {
109         filters->push_back(
110           Filter(UTF8ToUTF16(line.substr(allow_empty_str.size())),
111                  Filter::ALLOW_EMPTY));
112       } else if (StartsWithASCII(line, allow_str, true)) {
113         filters->push_back(Filter(UTF8ToUTF16(line.substr(allow_str.size())),
114                                   Filter::ALLOW));
115       } else if (StartsWithASCII(line, deny_str, true)) {
116         filters->push_back(Filter(UTF8ToUTF16(line.substr(deny_str.size())),
117                                   Filter::DENY));
118       }
119     }
120   }
121
122   void RunTest(const base::FilePath::CharType* file_path);
123 };
124
125 void DumpAccessibilityTreeTest::RunTest(
126     const base::FilePath::CharType* file_path) {
127   NavigateToURL(shell(), GURL(kAboutBlankURL));
128
129   // Setup test paths.
130   base::FilePath dir_test_data;
131   ASSERT_TRUE(PathService::Get(DIR_TEST_DATA, &dir_test_data));
132   base::FilePath test_path(
133       dir_test_data.Append(FILE_PATH_LITERAL("accessibility")));
134   ASSERT_TRUE(base::PathExists(test_path))
135       << test_path.LossyDisplayName();
136
137   base::FilePath html_file = test_path.Append(base::FilePath(file_path));
138   // Output the test path to help anyone who encounters a failure and needs
139   // to know where to look.
140   printf("Testing: %s\n", html_file.MaybeAsASCII().c_str());
141
142   std::string html_contents;
143   base::ReadFileToString(html_file, &html_contents);
144
145   // Read the expected file.
146   std::string expected_contents_raw;
147   base::FilePath expected_file =
148     base::FilePath(html_file.RemoveExtension().value() +
149                    AccessibilityTreeFormatter::GetExpectedFileSuffix());
150   base::ReadFileToString(expected_file, &expected_contents_raw);
151
152   // Tolerate Windows-style line endings (\r\n) in the expected file:
153   // normalize by deleting all \r from the file (if any) to leave only \n.
154   std::string expected_contents;
155   RemoveChars(expected_contents_raw, "\r", &expected_contents);
156
157   if (!expected_contents.compare(0, strlen(kMarkSkipFile), kMarkSkipFile)) {
158     printf("Skipping this test on this platform.\n");
159     return;
160   }
161
162   // Load the page.
163   string16 html_contents16;
164   html_contents16 = UTF8ToUTF16(html_contents);
165   GURL url = GetTestUrl("accessibility",
166                         html_file.BaseName().MaybeAsASCII().c_str());
167   AccessibilityNotificationWaiter waiter(
168       shell(), AccessibilityModeComplete,
169       WebKit::WebAXEventLoadComplete);
170   NavigateToURL(shell(), url);
171   waiter.WaitForNotification();
172
173   RenderWidgetHostViewPort* host_view = RenderWidgetHostViewPort::FromRWHV(
174       shell()->web_contents()->GetRenderWidgetHostView());
175   AccessibilityTreeFormatter formatter(
176       host_view->GetBrowserAccessibilityManager()->GetRoot());
177
178   // Parse filters in the test file.
179   std::vector<Filter> filters;
180   AddDefaultFilters(&filters);
181   ParseFilters(html_contents, &filters);
182   formatter.SetFilters(filters);
183
184   // Perform a diff (or write the initial baseline).
185   string16 actual_contents_utf16;
186   formatter.FormatAccessibilityTree(&actual_contents_utf16);
187   std::string actual_contents = UTF16ToUTF8(actual_contents_utf16);
188   std::vector<std::string> actual_lines, expected_lines;
189   Tokenize(actual_contents, "\n", &actual_lines);
190   Tokenize(expected_contents, "\n", &expected_lines);
191   // Marking the end of the file with a line of text ensures that
192   // file length differences are found.
193   expected_lines.push_back(kMarkEndOfFile);
194   actual_lines.push_back(kMarkEndOfFile);
195
196   std::vector<int> diff_lines = DiffLines(expected_lines, actual_lines);
197   bool is_different = diff_lines.size() > 0;
198   EXPECT_FALSE(is_different);
199   if (is_different) {
200     // Mark the expected lines which did not match actual output with a *.
201     printf("* Line Expected\n");
202     printf("- ---- --------\n");
203     for (int line = 0, diff_index = 0;
204          line < static_cast<int>(expected_lines.size());
205          ++line) {
206       bool is_diff = false;
207       if (diff_index < static_cast<int>(diff_lines.size()) &&
208           diff_lines[diff_index] == line) {
209         is_diff = true;
210         ++diff_index;
211       }
212       printf("%1s %4d %s\n", is_diff? kSignalDiff : "", line + 1,
213              expected_lines[line].c_str());
214     }
215     printf("\nActual\n");
216     printf("------\n");
217     printf("%s\n", actual_contents.c_str());
218   }
219
220   if (!base::PathExists(expected_file)) {
221     base::FilePath actual_file =
222         base::FilePath(html_file.RemoveExtension().value() +
223                        AccessibilityTreeFormatter::GetActualFileSuffix());
224
225     EXPECT_TRUE(file_util::WriteFile(
226         actual_file, actual_contents.c_str(), actual_contents.size()));
227
228     ADD_FAILURE() << "No expectation found. Create it by doing:\n"
229                   << "mv " << actual_file.LossyDisplayName() << " "
230                   << expected_file.LossyDisplayName();
231   }
232 }
233
234 IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityA) {
235   RunTest(FILE_PATH_LITERAL("a.html"));
236 }
237
238 IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityAddress) {
239   RunTest(FILE_PATH_LITERAL("address.html"));
240 }
241
242 IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityAName) {
243   RunTest(FILE_PATH_LITERAL("a-name.html"));
244 }
245
246 IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityAOnclick) {
247   RunTest(FILE_PATH_LITERAL("a-onclick.html"));
248 }
249
250 IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest,
251                        AccessibilityAriaApplication) {
252   RunTest(FILE_PATH_LITERAL("aria-application.html"));
253 }
254
255 IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest,
256                        AccessibilityAriaAutocomplete) {
257   RunTest(FILE_PATH_LITERAL("aria-autocomplete.html"));
258 }
259
260 IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityAriaCombobox) {
261   RunTest(FILE_PATH_LITERAL("aria-combobox.html"));
262 }
263
264 IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityAriaInvalid) {
265   RunTest(FILE_PATH_LITERAL("aria-invalid.html"));
266 }
267
268 IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityAriaLevel) {
269   RunTest(FILE_PATH_LITERAL("aria-level.html"));
270 }
271
272 IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityAriaMenu) {
273   RunTest(FILE_PATH_LITERAL("aria-menu.html"));
274 }
275
276 IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest,
277                        AccessibilityAriaMenuitemradio) {
278   RunTest(FILE_PATH_LITERAL("aria-menuitemradio.html"));
279 }
280
281 IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest,
282                        AccessibilityAriaPressed) {
283   RunTest(FILE_PATH_LITERAL("aria-pressed.html"));
284 }
285
286 IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest,
287                        AccessibilityAriaProgressbar) {
288   RunTest(FILE_PATH_LITERAL("aria-progressbar.html"));
289 }
290
291 IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest,
292                        AccessibilityAriaToolbar) {
293   RunTest(FILE_PATH_LITERAL("toolbar.html"));
294 }
295
296 IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest,
297                        AccessibilityAriaValueMin) {
298   RunTest(FILE_PATH_LITERAL("aria-valuemin.html"));
299 }
300
301 IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest,
302                        AccessibilityAriaValueMax) {
303   RunTest(FILE_PATH_LITERAL("aria-valuemax.html"));
304 }
305
306 IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityArticle) {
307   RunTest(FILE_PATH_LITERAL("article.html"));
308 }
309
310 IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityAWithImg) {
311   RunTest(FILE_PATH_LITERAL("a-with-img.html"));
312 }
313
314 IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityBdo) {
315   RunTest(FILE_PATH_LITERAL("bdo.html"));
316 }
317
318 IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityBR) {
319   RunTest(FILE_PATH_LITERAL("br.html"));
320 }
321
322 IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityButtonNameCalc) {
323   RunTest(FILE_PATH_LITERAL("button-name-calc.html"));
324 }
325
326 IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityCanvas) {
327   RunTest(FILE_PATH_LITERAL("canvas.html"));
328 }
329
330 IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest,
331                        AccessibilityCheckboxNameCalc) {
332   RunTest(FILE_PATH_LITERAL("checkbox-name-calc.html"));
333 }
334
335 IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityDiv) {
336   RunTest(FILE_PATH_LITERAL("div.html"));
337 }
338
339 IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityDl) {
340   RunTest(FILE_PATH_LITERAL("dl.html"));
341 }
342
343 IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest,
344                        AccessibilityContenteditableDescendants) {
345   RunTest(FILE_PATH_LITERAL("contenteditable-descendants.html"));
346 }
347
348 IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityEm) {
349   RunTest(FILE_PATH_LITERAL("em.html"));
350 }
351
352 IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityFooter) {
353   RunTest(FILE_PATH_LITERAL("footer.html"));
354 }
355
356 IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityForm) {
357   RunTest(FILE_PATH_LITERAL("form.html"));
358 }
359
360 IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityHeading) {
361   RunTest(FILE_PATH_LITERAL("heading.html"));
362 }
363
364 IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityHR) {
365   RunTest(FILE_PATH_LITERAL("hr.html"));
366 }
367
368 // crbug.com/179717 and crbug.com/224659
369 IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest,
370                        DISABLED_AccessibilityIframeCoordinates) {
371   RunTest(FILE_PATH_LITERAL("iframe-coordinates.html"));
372 }
373
374 IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityInputButton) {
375   RunTest(FILE_PATH_LITERAL("input-button.html"));
376 }
377
378 IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest,
379                        AccessibilityInputButtonInMenu) {
380   RunTest(FILE_PATH_LITERAL("input-button-in-menu.html"));
381 }
382
383 IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityInputColor) {
384   RunTest(FILE_PATH_LITERAL("input-color.html"));
385 }
386
387 IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest,
388                        AccessibilityInputImageButtonInMenu) {
389   RunTest(FILE_PATH_LITERAL("input-image-button-in-menu.html"));
390 }
391
392 IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityInputRange) {
393   RunTest(FILE_PATH_LITERAL("input-range.html"));
394 }
395
396 IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest,
397                        AccessibilityInputTextNameCalc) {
398   RunTest(FILE_PATH_LITERAL("input-text-name-calc.html"));
399 }
400
401 IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityLabel) {
402   RunTest(FILE_PATH_LITERAL("label.html"));
403 }
404
405 IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityListMarkers) {
406   RunTest(FILE_PATH_LITERAL("list-markers.html"));
407 }
408
409 IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityP) {
410   RunTest(FILE_PATH_LITERAL("p.html"));
411 }
412
413 IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilitySelect) {
414   RunTest(FILE_PATH_LITERAL("select.html"));
415 }
416
417 IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilitySpan) {
418   RunTest(FILE_PATH_LITERAL("span.html"));
419 }
420
421 IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilitySpinButton) {
422   RunTest(FILE_PATH_LITERAL("spinbutton.html"));
423 }
424
425 // TODO(dmazzoni): Rebaseline this test after Blink rolls past r155083.
426 // See http://crbug.com/265619
427 IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, DISABLED_AccessibilitySvg) {
428   RunTest(FILE_PATH_LITERAL("svg.html"));
429 }
430
431 IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityTab) {
432   RunTest(FILE_PATH_LITERAL("tab.html"));
433 }
434
435 IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityTableSimple) {
436   RunTest(FILE_PATH_LITERAL("table-simple.html"));
437 }
438
439 IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityTableSpans) {
440   RunTest(FILE_PATH_LITERAL("table-spans.html"));
441 }
442
443 IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest,
444                        AccessibilityToggleButton) {
445   RunTest(FILE_PATH_LITERAL("togglebutton.html"));
446 }
447
448 IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityUl) {
449   RunTest(FILE_PATH_LITERAL("ul.html"));
450 }
451
452 IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityWbr) {
453   RunTest(FILE_PATH_LITERAL("wbr.html"));
454 }
455
456 }  // namespace content