| 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 <string> | 5 #include <string> |
| 6 #include <vector> | 6 #include <vector> |
| 7 | 7 |
| 8 #include "base/logging.h" | 8 #include "base/logging.h" |
| 9 #include "base/path_service.h" | 9 #include "base/path_service.h" |
| 10 #include "base/string_util.h" | 10 #include "base/string_util.h" |
| (...skipping 17 matching lines...) Expand all Loading... |
| 28 using content::RenderViewHostImpl; | 28 using content::RenderViewHostImpl; |
| 29 using content::RenderWidgetHostImpl; | 29 using content::RenderWidgetHostImpl; |
| 30 using content::RenderWidgetHost; | 30 using content::RenderWidgetHost; |
| 31 using content::RenderWidgetHostViewPort; | 31 using content::RenderWidgetHostViewPort; |
| 32 using content::Referrer; | 32 using content::Referrer; |
| 33 | 33 |
| 34 namespace { | 34 namespace { |
| 35 // Required to enter html content into a url. | 35 // Required to enter html content into a url. |
| 36 static const std::string kUrlPreamble = "data:text/html,\n<!doctype html>"; | 36 static const std::string kUrlPreamble = "data:text/html,\n<!doctype html>"; |
| 37 static const char kCommentToken = '#'; | 37 static const char kCommentToken = '#'; |
| 38 static const char* kMarkSkipFile = "#<skip"; |
| 39 static const char* kMarkEndOfFile = "<-- End-of-file -->"; |
| 40 static const char* kSignalDiff = "*"; |
| 38 } // namespace | 41 } // namespace |
| 39 | 42 |
| 40 // This test takes a snapshot of the platform BrowserAccessibility tree and | 43 // This test takes a snapshot of the platform BrowserAccessibility tree and |
| 41 // tests it against an expected baseline. | 44 // tests it against an expected baseline. |
| 42 // | 45 // |
| 43 // The flow of the test is as outlined below. | 46 // The flow of the test is as outlined below. |
| 44 // 1. Load an html file from chrome/test/data/accessibility. | 47 // 1. Load an html file from chrome/test/data/accessibility. |
| 45 // 2. Read the expectation. | 48 // 2. Read the expectation. |
| 46 // 3. Browse to the page and serialize the platform specific tree into a human | 49 // 3. Browse to the page and serialize the platform specific tree into a human |
| 47 // readable string. | 50 // readable string. |
| 48 // 4. Perform a comparison between actual and expected and fail if they do not | 51 // 4. Perform a comparison between actual and expected and fail if they do not |
| 49 // exactly match. | 52 // exactly match. |
| 50 class DumpAccessibilityTreeTest : public InProcessBrowserTest { | 53 class DumpAccessibilityTreeTest : public InProcessBrowserTest { |
| 51 public: | 54 public: |
| 52 // Utility helper that does a comment aware equality check. | 55 // Utility helper that does a comment aware equality check. |
| 53 bool EqualsWithComments(std::string& expected, std::string& actual) { | 56 // Returns array of lines from expected file which are different. |
| 54 std::vector<std::string> actual_lines, expected_lines; | 57 std::vector<int> DiffLines(std::vector<std::string>& expected_lines, |
| 55 int actual_lines_count = Tokenize(actual, "\n", &actual_lines); | 58 std::vector<std::string>& actual_lines) { |
| 56 int expected_lines_count = Tokenize(expected, "\n", &expected_lines); | 59 int actual_lines_count = actual_lines.size(); |
| 57 int i = actual_lines_count - 1, j = expected_lines_count - 1; | 60 int expected_lines_count = expected_lines.size(); |
| 58 while (i >= 0 && j >= 0) { | 61 std::vector<int> diff_lines; |
| 59 if (expected_lines[j].size() > 0 && | 62 int i = 0, j = 0; |
| 63 while (i < actual_lines_count && j < expected_lines_count) { |
| 64 if (expected_lines[j].size() == 0 || |
| 60 expected_lines[j][0] == kCommentToken) { | 65 expected_lines[j][0] == kCommentToken) { |
| 61 --j; | 66 // Skip comment lines and blank lines in expected output. |
| 67 ++j; |
| 62 continue; | 68 continue; |
| 63 } | 69 } |
| 64 | 70 |
| 65 if (actual_lines[i] != expected_lines[j]) | 71 if (actual_lines[i] != expected_lines[j]) |
| 66 return false; | 72 diff_lines.push_back(j); |
| 67 --i; | 73 ++i; |
| 68 --j; | 74 ++j; |
| 69 } | 75 } |
| 70 | 76 |
| 71 // Actual file has been fully checked. | 77 // Actual file has been fully checked. |
| 72 return i < 0; | 78 return diff_lines; |
| 73 } | 79 } |
| 74 | 80 |
| 75 DumpAccessibilityTreeHelper helper_; | 81 DumpAccessibilityTreeHelper helper_; |
| 76 }; | 82 }; |
| 77 | 83 |
| 78 IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, | 84 IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, |
| 79 PlatformTreeDifferenceTest) { | 85 PlatformTreeDifferenceTest) { |
| 80 RenderWidgetHostViewPort* host_view = static_cast<RenderWidgetHostViewPort*>( | 86 RenderWidgetHostViewPort* host_view = static_cast<RenderWidgetHostViewPort*>( |
| 81 browser()->GetSelectedWebContents()->GetRenderWidgetHostView()); | 87 browser()->GetSelectedWebContents()->GetRenderWidgetHostView()); |
| 82 RenderWidgetHost* host = host_view->GetRenderWidgetHost(); | 88 RenderWidgetHost* host = host_view->GetRenderWidgetHost(); |
| (...skipping 16 matching lines...) Expand all Loading... |
| 99 // Grab all HTML files. | 105 // Grab all HTML files. |
| 100 file_util::FileEnumerator file_enumerator(test_path, | 106 file_util::FileEnumerator file_enumerator(test_path, |
| 101 false, | 107 false, |
| 102 file_util::FileEnumerator::FILES, | 108 file_util::FileEnumerator::FILES, |
| 103 FILE_PATH_LITERAL("*.html")); | 109 FILE_PATH_LITERAL("*.html")); |
| 104 | 110 |
| 105 // TODO(dtseng): Make each of these a gtest with script. | 111 // TODO(dtseng): Make each of these a gtest with script. |
| 106 FilePath html_file(file_enumerator.Next()); | 112 FilePath html_file(file_enumerator.Next()); |
| 107 ASSERT_FALSE(html_file.empty()); | 113 ASSERT_FALSE(html_file.empty()); |
| 108 do { | 114 do { |
| 109 printf("Testing %s\n", html_file.BaseName().MaybeAsASCII().c_str()); | |
| 110 | |
| 111 std::string html_contents; | 115 std::string html_contents; |
| 112 file_util::ReadFileToString(html_file, &html_contents); | 116 file_util::ReadFileToString(html_file, &html_contents); |
| 113 | 117 |
| 114 // Read the expected file. | 118 // Read the expected file. |
| 115 std::string expected_contents_raw; | 119 std::string expected_contents_raw; |
| 116 FilePath expected_file = | 120 FilePath expected_file = |
| 117 FilePath(html_file.RemoveExtension().value() + | 121 FilePath(html_file.RemoveExtension().value() + |
| 118 helper_.GetExpectedFileSuffix()); | 122 helper_.GetExpectedFileSuffix()); |
| 119 file_util::ReadFileToString( | 123 file_util::ReadFileToString( |
| 120 expected_file, | 124 expected_file, |
| 121 &expected_contents_raw); | 125 &expected_contents_raw); |
| 122 | 126 |
| 123 // Tolerate Windows-style line endings (\r\n) in the expected file: | 127 // 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. | 128 // normalize by deleting all \r from the file (if any) to leave only \n. |
| 125 std::string expected_contents; | 129 std::string expected_contents; |
| 126 RemoveChars(expected_contents_raw, "\r", &expected_contents); | 130 RemoveChars(expected_contents_raw, "\r", &expected_contents); |
| 127 | 131 |
| 132 if (!expected_contents.compare(0, strlen(kMarkSkipFile), kMarkSkipFile)) { |
| 133 printf("Skipping %s\n", html_file.BaseName().MaybeAsASCII().c_str()); |
| 134 continue; |
| 135 } |
| 136 |
| 137 printf("Testing %s\n", html_file.BaseName().MaybeAsASCII().c_str()); |
| 138 |
| 128 // Load the page. | 139 // Load the page. |
| 129 ui_test_utils::WindowedNotificationObserver tree_updated_observer( | 140 ui_test_utils::WindowedNotificationObserver tree_updated_observer( |
| 130 content::NOTIFICATION_RENDER_VIEW_HOST_ACCESSIBILITY_TREE_UPDATED, | 141 content::NOTIFICATION_RENDER_VIEW_HOST_ACCESSIBILITY_TREE_UPDATED, |
| 131 content::NotificationService::AllSources()); | 142 content::NotificationService::AllSources()); |
| 132 string16 html_contents16; | 143 string16 html_contents16; |
| 133 html_contents16 = UTF8ToUTF16(html_contents); | 144 html_contents16 = UTF8ToUTF16(html_contents); |
| 134 GURL url(UTF8ToUTF16(kUrlPreamble) + html_contents16); | 145 GURL url(UTF8ToUTF16(kUrlPreamble) + html_contents16); |
| 135 browser()->OpenURL(OpenURLParams( | 146 browser()->OpenURL(OpenURLParams( |
| 136 url, Referrer(), CURRENT_TAB, content::PAGE_TRANSITION_TYPED, false)); | 147 url, Referrer(), CURRENT_TAB, content::PAGE_TRANSITION_TYPED, false)); |
| 137 | 148 |
| 138 // Wait for the tree. | 149 // Wait for the tree. |
| 139 tree_updated_observer.Wait(); | 150 tree_updated_observer.Wait(); |
| 140 | 151 |
| 141 // Perform a diff (or write the initial baseline). | 152 // Perform a diff (or write the initial baseline). |
| 142 string16 actual_contents_utf16; | 153 string16 actual_contents_utf16; |
| 143 helper_.DumpAccessibilityTree( | 154 helper_.DumpAccessibilityTree( |
| 144 host_view->GetBrowserAccessibilityManager()->GetRoot(), | 155 host_view->GetBrowserAccessibilityManager()->GetRoot(), |
| 145 &actual_contents_utf16); | 156 &actual_contents_utf16); |
| 146 std::string actual_contents = UTF16ToUTF8(actual_contents_utf16); | 157 std::string actual_contents = UTF16ToUTF8(actual_contents_utf16); |
| 147 EXPECT_TRUE(EqualsWithComments(expected_contents, actual_contents)); | 158 std::vector<std::string> actual_lines, expected_lines; |
| 148 if (expected_contents != actual_contents) { | 159 Tokenize(actual_contents, "\n", &actual_lines); |
| 149 printf("*** EXPECTED: ***\n%s\n", expected_contents.c_str()); | 160 Tokenize(expected_contents, "\n", &expected_lines); |
| 150 printf("*** ACTUAL: ***\n%s\n", actual_contents.c_str()); | 161 // Marking the end of the file with a line of text ensures that |
| 162 // file length differences are found. |
| 163 expected_lines.push_back(kMarkEndOfFile); |
| 164 actual_lines.push_back(kMarkEndOfFile); |
| 165 |
| 166 std::vector<int> diff_lines = DiffLines(expected_lines, actual_lines); |
| 167 bool is_different = diff_lines.size() > 0; |
| 168 EXPECT_FALSE(is_different); |
| 169 if (is_different) { |
| 170 // Mark the expected lines which did not match actual output with a *. |
| 171 printf("* Line Expected\n"); |
| 172 printf("- ---- --------\n"); |
| 173 for (int line = 0, diff_index = 0; |
| 174 line < static_cast<int>(expected_lines.size()); |
| 175 ++line) { |
| 176 bool is_diff = false; |
| 177 if (diff_index < static_cast<int>(diff_lines.size()) && |
| 178 diff_lines[diff_index] == line) { |
| 179 is_diff = true; |
| 180 ++ diff_index; |
| 181 } |
| 182 printf("%1s %4d %s\n", is_diff? kSignalDiff : "", line + 1, |
| 183 expected_lines[line].c_str()); |
| 184 } |
| 185 printf("\n"); |
| 151 } | 186 } |
| 152 | 187 |
| 153 if (!file_util::PathExists(expected_file)) { | 188 if (!file_util::PathExists(expected_file)) { |
| 154 FilePath actual_file = | 189 FilePath actual_file = |
| 155 FilePath(html_file.RemoveExtension().value() + | 190 FilePath(html_file.RemoveExtension().value() + |
| 156 helper_.GetActualFileSuffix()); | 191 helper_.GetActualFileSuffix()); |
| 157 | 192 |
| 158 EXPECT_TRUE(file_util::WriteFile( | 193 EXPECT_TRUE(file_util::WriteFile( |
| 159 actual_file, actual_contents.c_str(), actual_contents.size())); | 194 actual_file, actual_contents.c_str(), actual_contents.size())); |
| 160 | 195 |
| 161 ADD_FAILURE() << "No expectation found. Create it by doing:\n" | 196 ADD_FAILURE() << "No expectation found. Create it by doing:\n" |
| 162 << "mv " << actual_file.LossyDisplayName() << " " | 197 << "mv " << actual_file.LossyDisplayName() << " " |
| 163 << expected_file.LossyDisplayName(); | 198 << expected_file.LossyDisplayName(); |
| 164 } | 199 } |
| 165 } while (!(html_file = file_enumerator.Next()).empty()); | 200 } while (!(html_file = file_enumerator.Next()).empty()); |
| 166 } | 201 } |
| 167 | 202 |
| OLD | NEW |