Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(15)

Side by Side Diff: content/browser/accessibility/dump_accessibility_tree_browsertest.cc

Issue 10662003: Allow filters in accessibility tests to specify which attributes to check. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Work around missing webkit strings in content_browsertests for now Created 8 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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 <string> 6 #include <string>
6 #include <vector> 7 #include <vector>
7 8
8 #include "base/logging.h" 9 #include "base/logging.h"
9 #include "base/path_service.h" 10 #include "base/path_service.h"
11 #include "base/string_split.h"
10 #include "base/string_util.h" 12 #include "base/string_util.h"
11 #include "base/string16.h" 13 #include "base/string16.h"
12 #include "base/utf_string_conversions.h" 14 #include "base/utf_string_conversions.h"
13 #include "content/browser/accessibility/browser_accessibility.h" 15 #include "content/browser/accessibility/browser_accessibility.h"
14 #include "content/browser/accessibility/browser_accessibility_manager.h" 16 #include "content/browser/accessibility/browser_accessibility_manager.h"
15 #include "content/browser/accessibility/dump_accessibility_tree_helper.h" 17 #include "content/browser/accessibility/dump_accessibility_tree_helper.h"
16 #include "content/browser/renderer_host/render_view_host_impl.h" 18 #include "content/browser/renderer_host/render_view_host_impl.h"
17 #include "content/port/browser/render_widget_host_view_port.h" 19 #include "content/port/browser/render_widget_host_view_port.h"
18 #include "content/public/browser/notification_service.h" 20 #include "content/public/browser/notification_service.h"
19 #include "content/public/browser/notification_types.h" 21 #include "content/public/browser/notification_types.h"
20 #include "content/public/browser/web_contents.h" 22 #include "content/public/browser/web_contents.h"
21 #include "content/public/common/content_paths.h" 23 #include "content/public/common/content_paths.h"
22 #include "content/public/test/test_utils.h" 24 #include "content/public/test/test_utils.h"
23 #include "content/test/content_browser_test.h" 25 #include "content/test/content_browser_test.h"
24 #include "content/test/content_browser_test_utils.h" 26 #include "content/test/content_browser_test_utils.h"
25 #include "content/shell/shell.h" 27 #include "content/shell/shell.h"
26 #include "testing/gtest/include/gtest/gtest.h" 28 #include "testing/gtest/include/gtest/gtest.h"
27 29
28 namespace { 30 namespace {
29 // Required to enter html content into a url.
30 static const std::string kUrlPreamble = "data:text/html,\n<!doctype html>";
31 static const char kCommentToken = '#'; 31 static const char kCommentToken = '#';
32 static const char* kMarkSkipFile = "#<skip"; 32 static const char* kMarkSkipFile = "#<skip";
33 static const char* kMarkEndOfFile = "<-- End-of-file -->"; 33 static const char* kMarkEndOfFile = "<-- End-of-file -->";
34 static const char* kSignalDiff = "*"; 34 static const char* kSignalDiff = "*";
35 } // namespace 35 } // namespace
36 36
37 namespace content { 37 namespace content {
38 38
39 // This test takes a snapshot of the platform BrowserAccessibility tree and 39 // This test takes a snapshot of the platform BrowserAccessibility tree and
40 // tests it against an expected baseline. 40 // tests it against an expected baseline.
41 // 41 //
42 // The flow of the test is as outlined below. 42 // The flow of the test is as outlined below.
43 // 1. Load an html file from chrome/test/data/accessibility. 43 // 1. Load an html file from chrome/test/data/accessibility.
44 // 2. Read the expectation. 44 // 2. Read the expectation.
45 // 3. Browse to the page and serialize the platform specific tree into a human 45 // 3. Browse to the page and serialize the platform specific tree into a human
46 // readable string. 46 // readable string.
47 // 4. Perform a comparison between actual and expected and fail if they do not 47 // 4. Perform a comparison between actual and expected and fail if they do not
48 // exactly match. 48 // exactly match.
49 class DumpAccessibilityTreeTest : public ContentBrowserTest { 49 class DumpAccessibilityTreeTest : public ContentBrowserTest {
50 public: 50 public:
51 // Utility helper that does a comment aware equality check. 51 // Utility helper that does a comment aware equality check.
52 // Returns array of lines from expected file which are different. 52 // Returns array of lines from expected file which are different.
53 std::vector<int> DiffLines(std::vector<std::string>& expected_lines, 53 std::vector<int> DiffLines(std::vector<std::string>& expected_lines,
54 std::vector<std::string>& actual_lines) { 54 std::vector<std::string>& actual_lines) {
55 int actual_lines_count = actual_lines.size(); 55 int actual_lines_count = actual_lines.size();
56 int expected_lines_count = expected_lines.size(); 56 int expected_lines_count = expected_lines.size();
57 std::vector<int> diff_lines; 57 std::vector<int> diff_lines;
58 int i = 0, j = 0; 58 int i = 0, j = 0;
59 while (i < actual_lines_count && j < expected_lines_count) { 59 while (i < actual_lines_count && j < expected_lines_count) {
60 if (expected_lines[j].size() == 0 || 60 if (expected_lines[j].size() == 0 ||
61 expected_lines[j][0] == kCommentToken) { 61 expected_lines[j][0] == kCommentToken) {
62 // Skip comment lines and blank lines in expected output. 62 // Skip comment lines and blank lines in expected output.
63 ++j; 63 ++j;
64 continue; 64 continue;
65 } 65 }
66 66
67 if (actual_lines[i] != expected_lines[j]) 67 if (actual_lines[i] != expected_lines[j])
68 diff_lines.push_back(j); 68 diff_lines.push_back(j);
69 ++i; 69 ++i;
70 ++j; 70 ++j;
71 } 71 }
72 72
73 // Actual file has been fully checked. 73 // Actual file has been fully checked.
74 return diff_lines; 74 return diff_lines;
75 } 75 }
76 76
77 void AddDefaultFilters(std::set<string16>* allow_filters,
78 std::set<string16>* deny_filters) {
79 allow_filters->insert(ASCIIToUTF16("FOCUSABLE"));
80 allow_filters->insert(ASCIIToUTF16("READONLY"));
81 }
82
83 void ParseFilters(const std::string& test_html,
84 std::set<string16>* allow_filters,
85 std::set<string16>* deny_filters) {
86 std::vector<std::string> lines;
87 base::SplitString(test_html, '\n', &lines);
88 for (std::vector<std::string>::const_iterator iter = lines.begin();
89 iter != lines.end();
90 ++iter) {
91 const std::string& line = *iter;
92 const std::string& allow_str = helper_.GetAllowString();
93 const std::string& deny_str = helper_.GetDenyString();
94 if (StartsWithASCII(line, allow_str, true))
95 allow_filters->insert(UTF8ToUTF16(line.substr(allow_str.size())));
96 else if (StartsWithASCII(line, deny_str, true))
97 deny_filters->insert(UTF8ToUTF16(line.substr(deny_str.size())));
98 }
99 }
100
101 void RunTest(const FilePath::CharType* file_path);
102
77 DumpAccessibilityTreeHelper helper_; 103 DumpAccessibilityTreeHelper helper_;
78 }; 104 };
79 105
80 IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, 106 void DumpAccessibilityTreeTest::RunTest(const FilePath::CharType* file_path) {
81 DISABLED_PlatformTreeDifferenceTest) { 107 NavigateToURL(shell(), GURL("about:blank"));
82 RenderWidgetHostViewPort* host_view = static_cast<RenderWidgetHostViewPort*>( 108 RenderWidgetHostViewPort* host_view = static_cast<RenderWidgetHostViewPort*>(
83 shell()->web_contents()->GetRenderWidgetHostView()); 109 shell()->web_contents()->GetRenderWidgetHostView());
84 RenderWidgetHost* host = host_view->GetRenderWidgetHost(); 110 RenderWidgetHostImpl* host =
85 RenderViewHostImpl* view_host = 111 RenderWidgetHostImpl::From(host_view->GetRenderWidgetHost());
86 static_cast<RenderViewHostImpl*>(RenderWidgetHostImpl::From(host)); 112 RenderViewHostImpl* view_host = static_cast<RenderViewHostImpl*>(host);
87 view_host->set_save_accessibility_tree_for_testing(true); 113 view_host->set_save_accessibility_tree_for_testing(true);
88 view_host->SetAccessibilityMode(AccessibilityModeComplete); 114 view_host->SetAccessibilityMode(AccessibilityModeComplete);
89 115
90 // Setup test paths. 116 // Setup test paths.
91 FilePath dir_test_data; 117 FilePath dir_test_data;
92 EXPECT_TRUE(PathService::Get(DIR_TEST_DATA, &dir_test_data)); 118 EXPECT_TRUE(PathService::Get(DIR_TEST_DATA, &dir_test_data));
93 FilePath test_path(dir_test_data.Append(FILE_PATH_LITERAL("accessibility"))); 119 FilePath test_path(dir_test_data.Append(FILE_PATH_LITERAL("accessibility")));
94 EXPECT_TRUE(file_util::PathExists(test_path)) 120 EXPECT_TRUE(file_util::PathExists(test_path))
95 << test_path.LossyDisplayName(); 121 << test_path.LossyDisplayName();
96 122
123 FilePath html_file = test_path.Append(FilePath(file_path));
97 // Output the test path to help anyone who encounters a failure and needs 124 // Output the test path to help anyone who encounters a failure and needs
98 // to know where to look. 125 // to know where to look.
99 printf("Path to test files: %s\n", test_path.MaybeAsASCII().c_str()); 126 printf("Testing: %s\n", html_file.MaybeAsASCII().c_str());
100 127
101 // Grab all HTML files. 128 std::string html_contents;
102 file_util::FileEnumerator file_enumerator(test_path, 129 file_util::ReadFileToString(html_file, &html_contents);
103 false,
104 file_util::FileEnumerator::FILES,
105 FILE_PATH_LITERAL("*.html"));
106 130
107 // TODO(dtseng): Make each of these a gtest with script. 131 // Parse filters in the test file.
108 FilePath html_file(file_enumerator.Next()); 132 std::set<string16> allow_filters;
109 ASSERT_FALSE(html_file.empty()); 133 std::set<string16> deny_filters;
110 do { 134 AddDefaultFilters(&allow_filters, &deny_filters);
111 std::string html_contents; 135 ParseFilters(html_contents, &allow_filters, &deny_filters);
112 file_util::ReadFileToString(html_file, &html_contents); 136 helper_.SetFilters(allow_filters, deny_filters);
113 137
114 // Read the expected file. 138 // Read the expected file.
115 std::string expected_contents_raw; 139 std::string expected_contents_raw;
116 FilePath expected_file = 140 FilePath expected_file =
117 FilePath(html_file.RemoveExtension().value() + 141 FilePath(html_file.RemoveExtension().value() +
118 helper_.GetExpectedFileSuffix()); 142 helper_.GetExpectedFileSuffix());
119 file_util::ReadFileToString( 143 file_util::ReadFileToString(
120 expected_file, 144 expected_file,
121 &expected_contents_raw); 145 &expected_contents_raw);
122 146
123 // Tolerate Windows-style line endings (\r\n) in the expected file: 147 // Tolerate Windows-style line endings (\r\n) in the expected file:
124 // normalize by deleting all \r from the file (if any) to leave only \n. 148 // normalize by deleting all \r from the file (if any) to leave only \n.
125 std::string expected_contents; 149 std::string expected_contents;
126 RemoveChars(expected_contents_raw, "\r", &expected_contents); 150 RemoveChars(expected_contents_raw, "\r", &expected_contents);
127 151
128 if (!expected_contents.compare(0, strlen(kMarkSkipFile), kMarkSkipFile)) { 152 if (!expected_contents.compare(0, strlen(kMarkSkipFile), kMarkSkipFile)) {
129 printf("Skipping %s\n", html_file.BaseName().MaybeAsASCII().c_str()); 153 printf("Skipping this test on this platform.\n");
130 continue; 154 return;
155 }
156
157 // Load the page.
158 WindowedNotificationObserver tree_updated_observer(
159 NOTIFICATION_RENDER_VIEW_HOST_ACCESSIBILITY_TREE_UPDATED,
160 NotificationService::AllSources());
161 string16 html_contents16;
162 html_contents16 = UTF8ToUTF16(html_contents);
163 GURL url = GetTestUrl("accessibility",
164 html_file.BaseName().MaybeAsASCII().c_str());
165 NavigateToURL(shell(), url);
166
167 // Wait for the tree.
168 tree_updated_observer.Wait();
169
170 // Perform a diff (or write the initial baseline).
171 string16 actual_contents_utf16;
172 helper_.DumpAccessibilityTree(
173 host_view->GetBrowserAccessibilityManager()->GetRoot(),
174 &actual_contents_utf16);
175 std::string actual_contents = UTF16ToUTF8(actual_contents_utf16);
176 std::vector<std::string> actual_lines, expected_lines;
177 Tokenize(actual_contents, "\n", &actual_lines);
178 Tokenize(expected_contents, "\n", &expected_lines);
179 // Marking the end of the file with a line of text ensures that
180 // file length differences are found.
181 expected_lines.push_back(kMarkEndOfFile);
182 actual_lines.push_back(kMarkEndOfFile);
183
184 std::vector<int> diff_lines = DiffLines(expected_lines, actual_lines);
185 bool is_different = diff_lines.size() > 0;
186 EXPECT_FALSE(is_different);
187 if (is_different) {
188 // Mark the expected lines which did not match actual output with a *.
189 printf("* Line Expected\n");
190 printf("- ---- --------\n");
191 for (int line = 0, diff_index = 0;
192 line < static_cast<int>(expected_lines.size());
193 ++line) {
194 bool is_diff = false;
195 if (diff_index < static_cast<int>(diff_lines.size()) &&
196 diff_lines[diff_index] == line) {
197 is_diff = true;
198 ++ diff_index;
199 }
200 printf("%1s %4d %s\n", is_diff? kSignalDiff : "", line + 1,
201 expected_lines[line].c_str());
131 } 202 }
203 printf("\nActual\n");
204 printf("------\n");
205 printf("%s\n", actual_contents.c_str());
206 }
132 207
133 printf("Testing %s\n", html_file.BaseName().MaybeAsASCII().c_str()); 208 if (!file_util::PathExists(expected_file)) {
209 FilePath actual_file =
210 FilePath(html_file.RemoveExtension().value() +
211 helper_.GetActualFileSuffix());
134 212
135 // Load the page. 213 EXPECT_TRUE(file_util::WriteFile(
136 WindowedNotificationObserver tree_updated_observer( 214 actual_file, actual_contents.c_str(), actual_contents.size()));
137 NOTIFICATION_RENDER_VIEW_HOST_ACCESSIBILITY_TREE_UPDATED,
138 NotificationService::AllSources());
139 string16 html_contents16;
140 html_contents16 = UTF8ToUTF16(html_contents);
141 GURL url(UTF8ToUTF16(kUrlPreamble) + html_contents16);
142 NavigateToURL(shell(), url);
143 215
144 // Wait for the tree. 216 ADD_FAILURE() << "No expectation found. Create it by doing:\n"
145 tree_updated_observer.Wait(); 217 << "mv " << actual_file.LossyDisplayName() << " "
218 << expected_file.LossyDisplayName();
219 }
220 }
146 221
147 // Perform a diff (or write the initial baseline). 222 IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityA) {
David Tseng 2012/07/31 17:04:17 nit: Do we really want to add a test per file? Gte
148 string16 actual_contents_utf16; 223 RunTest(FILE_PATH_LITERAL("a.html"));
149 helper_.DumpAccessibilityTree( 224 }
150 host_view->GetBrowserAccessibilityManager()->GetRoot(),
151 &actual_contents_utf16);
152 std::string actual_contents = UTF16ToUTF8(actual_contents_utf16);
153 std::vector<std::string> actual_lines, expected_lines;
154 Tokenize(actual_contents, "\n", &actual_lines);
155 Tokenize(expected_contents, "\n", &expected_lines);
156 // Marking the end of the file with a line of text ensures that
157 // file length differences are found.
158 expected_lines.push_back(kMarkEndOfFile);
159 actual_lines.push_back(kMarkEndOfFile);
160 225
161 std::vector<int> diff_lines = DiffLines(expected_lines, actual_lines); 226 IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityAName) {
162 bool is_different = diff_lines.size() > 0; 227 RunTest(FILE_PATH_LITERAL("a-name.html"));
163 EXPECT_FALSE(is_different); 228 }
164 if (is_different) {
165 // Mark the expected lines which did not match actual output with a *.
166 printf("* Line Expected\n");
167 printf("- ---- --------\n");
168 for (int line = 0, diff_index = 0;
169 line < static_cast<int>(expected_lines.size());
170 ++line) {
171 bool is_diff = false;
172 if (diff_index < static_cast<int>(diff_lines.size()) &&
173 diff_lines[diff_index] == line) {
174 is_diff = true;
175 ++ diff_index;
176 }
177 printf("%1s %4d %s\n", is_diff? kSignalDiff : "", line + 1,
178 expected_lines[line].c_str());
179 }
180 printf("\nActual\n");
181 printf("------\n");
182 printf("%s\n", actual_contents.c_str());
183 }
184 229
185 if (!file_util::PathExists(expected_file)) { 230 IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityAOnclick) {
186 FilePath actual_file = 231 RunTest(FILE_PATH_LITERAL("a-onclick.html"));
187 FilePath(html_file.RemoveExtension().value() + 232 }
188 helper_.GetActualFileSuffix());
189 233
190 EXPECT_TRUE(file_util::WriteFile( 234 IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest,
191 actual_file, actual_contents.c_str(), actual_contents.size())); 235 AccessibilityAriaApplication) {
236 RunTest(FILE_PATH_LITERAL("aria-application.html"));
237 }
192 238
193 ADD_FAILURE() << "No expectation found. Create it by doing:\n" 239 IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityAWithImg) {
194 << "mv " << actual_file.LossyDisplayName() << " " 240 RunTest(FILE_PATH_LITERAL("a-with-img.html"));
195 << expected_file.LossyDisplayName(); 241 }
196 } 242
197 } while (!(html_file = file_enumerator.Next()).empty()); 243 IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest,
244 AccessibilityContenteditableDescendants) {
245 RunTest(FILE_PATH_LITERAL("contenteditable-descendants.html"));
246 }
247
248 IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityFooter) {
249 RunTest(FILE_PATH_LITERAL("footer.html"));
250 }
251
252 IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityListMarkers) {
253 RunTest(FILE_PATH_LITERAL("list-markers.html"));
254 }
255
256 IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityUl) {
257 RunTest(FILE_PATH_LITERAL("ul.html"));
198 } 258 }
199 259
200 } // namespace content 260 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698