OLD | NEW |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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 #include "chrome/browser/ui/webui/web_ui_browsertest.h" | 4 #include "chrome/browser/ui/webui/web_ui_browsertest.h" |
5 | 5 |
6 #include <string> | 6 #include <string> |
7 #include <vector> | 7 #include <vector> |
8 | 8 |
| 9 #include "base/file_util.h" |
| 10 #include "base/lazy_instance.h" |
9 #include "base/path_service.h" | 11 #include "base/path_service.h" |
10 #include "base/utf_string_conversions.h" | 12 #include "base/utf_string_conversions.h" |
11 #include "base/values.h" | 13 #include "base/values.h" |
12 #include "chrome/browser/ui/browser.h" | 14 #include "chrome/browser/ui/browser.h" |
13 #include "chrome/common/chrome_paths.h" | 15 #include "chrome/common/chrome_paths.h" |
14 #include "chrome/common/url_constants.h" | 16 #include "chrome/common/url_constants.h" |
| 17 #include "chrome/test/out_of_proc_test_runner.h" |
15 #include "chrome/test/ui_test_utils.h" | 18 #include "chrome/test/ui_test_utils.h" |
16 #include "content/browser/tab_contents/tab_contents.h" | 19 #include "content/browser/tab_contents/tab_contents.h" |
17 #include "content/browser/webui/web_ui.h" | 20 #include "content/browser/webui/web_ui.h" |
18 #include "ui/base/resource/resource_bundle.h" | 21 #include "ui/base/resource/resource_bundle.h" |
| 22 #include "v8/include/v8.h" |
19 | 23 |
20 static const FilePath::CharType* kWebUILibraryJS = | 24 namespace { |
21 FILE_PATH_LITERAL("test_api.js"); | 25 const FilePath::StringType kWebUILibraryJS = FILE_PATH_LITERAL("test_api.js"); |
22 static const FilePath::CharType* kWebUITestFolder = FILE_PATH_LITERAL("webui"); | 26 const FilePath::StringType kWebUITestFolder = FILE_PATH_LITERAL("webui"); |
23 static std::vector<std::string> error_messages_; | 27 const FilePath::StringType kSrcBaseName = FILE_PATH_LITERAL("src"); |
| 28 const FilePath::StringType kBuildBaseName = FILE_PATH_LITERAL("build"); |
| 29 |
| 30 base::LazyInstance<std::vector<std::string> > error_messages_( |
| 31 base::LINKER_INITIALIZED); |
| 32 |
| 33 // This method is called before the system is initialized, and we can't use |
| 34 // PathService. In order to support both automated builds and engineers on |
| 35 // multiple platforms, we look down for a src dir if we are within a build |
| 36 // directory and up for src if we are not. |
| 37 FilePath GetTestDataDirectory() { |
| 38 FilePath test_data_directory; |
| 39 EXPECT_TRUE(file_util::GetCurrentDirectory(&test_data_directory)); |
| 40 DLOG(INFO) << "test_data_directory = " << test_data_directory.value(); |
| 41 if (test_data_directory.BaseName().value() == kBuildBaseName) { |
| 42 FilePath src_subdir = test_data_directory.Append(kSrcBaseName); |
| 43 if (file_util::PathExists(test_data_directory.Append(kSrcBaseName))) |
| 44 test_data_directory = src_subdir; |
| 45 } |
| 46 while (test_data_directory.BaseName().value() != kSrcBaseName) { |
| 47 FilePath dir_name = test_data_directory.DirName(); |
| 48 if (test_data_directory == dir_name) |
| 49 break; |
| 50 test_data_directory = dir_name; |
| 51 } |
| 52 EXPECT_EQ(kSrcBaseName, test_data_directory.BaseName().value()); |
| 53 test_data_directory = test_data_directory.Append(FILE_PATH_LITERAL("chrome")); |
| 54 test_data_directory = test_data_directory.Append(FILE_PATH_LITERAL("test")); |
| 55 test_data_directory = test_data_directory.Append(FILE_PATH_LITERAL("data")); |
| 56 return test_data_directory.Append(kWebUITestFolder); |
| 57 } |
24 | 58 |
25 // Intercepts all log messages. | 59 // Intercepts all log messages. |
26 bool LogHandler(int severity, | 60 bool LogHandler(int severity, |
27 const char* file, | 61 const char* file, |
28 int line, | 62 int line, |
29 size_t message_start, | 63 size_t message_start, |
30 const std::string& str) { | 64 const std::string& str) { |
31 if (severity == logging::LOG_ERROR) { | 65 if (severity == logging::LOG_ERROR) { |
32 error_messages_.push_back(str); | 66 error_messages_.Get().push_back(str); |
33 return true; | 67 return true; |
34 } else { | 68 } else { |
35 // For debugging messages while developing tests. | 69 // For debugging messages while developing tests. |
36 return false; | 70 return false; |
37 } | 71 } |
38 } | 72 } |
39 | 73 |
| 74 // Read the specified |library| into |content|, prepending |test_data_directory| |
| 75 // when |library| is relative. |
| 76 void ReadLibraryToString(const FilePath& test_data_directory, |
| 77 const FilePath& library, |
| 78 std::string* content) { |
| 79 ASSERT_TRUE(content); |
| 80 if (library.IsAbsolute()) |
| 81 ASSERT_TRUE(file_util::ReadFileToString(library, content)); |
| 82 else |
| 83 ASSERT_TRUE(file_util::ReadFileToString(test_data_directory.Append(library), |
| 84 content)); |
| 85 } |
| 86 |
| 87 // Gets functions defined in |library_path| starting with "test". Results are |
| 88 // stored in |testFuncs|, which may not be NULL. |
| 89 bool GetTestFuncs(const FilePath& library_path, |
| 90 std::vector<std::string>* testFuncs) { |
| 91 DCHECK(testFuncs); |
| 92 |
| 93 // For export of test_api functions. |
| 94 std::string content = "var window = {};"; |
| 95 ReadLibraryToString(GetTestDataDirectory(), library_path, &content); |
| 96 content.append("this;"); |
| 97 |
| 98 // Run the script, dispose the context, and check the results. |
| 99 v8::HandleScope handle_scope; |
| 100 v8::Persistent<v8::Context> context = v8::Context::New(); |
| 101 v8::Context::Scope context_scope(context); |
| 102 v8::Handle<v8::String> source = v8::String::New(content.data(), |
| 103 content.size()); |
| 104 v8::Handle<v8::Script> script = v8::Script::Compile(source); |
| 105 v8::TryCatch trycatch; |
| 106 v8::Handle<v8::Value> result = script->Run(); |
| 107 context.Dispose(); |
| 108 if (result.IsEmpty()) { |
| 109 v8::Handle<v8::Value> exception = trycatch.Exception(); |
| 110 v8::String::AsciiValue exception_str(exception); |
| 111 NOTREACHED() << "Exception: " << *exception_str; |
| 112 return false; |
| 113 } |
| 114 |
| 115 // Examine the resulting object for properties which are functions, and push |
| 116 // them into |testFuncs|. |
| 117 v8::Local<v8::Object> result_obj = result->ToObject(); |
| 118 v8::Local<v8::Array> property_names = result_obj->GetPropertyNames(); |
| 119 for (uint32_t index = 0; index < property_names->Length(); ++index) { |
| 120 v8::Local<v8::String> property_name( |
| 121 property_names->Get(index).As<v8::String>()); |
| 122 if (!result_obj->HasOwnProperty(property_name)) |
| 123 continue; |
| 124 v8::Local<v8::Value> value = result_obj->Get(property_name); |
| 125 if (value.IsEmpty() || !value->IsFunction()) |
| 126 continue; |
| 127 v8::String::AsciiValue property_name_ascii(property_name); |
| 128 testFuncs->push_back(std::string(*property_name_ascii, |
| 129 property_name_ascii.length())); |
| 130 } |
| 131 return true; |
| 132 } |
| 133 |
| 134 // Since v8 cannot get an isolation thread at linker initialization time on |
| 135 // non-linux systems, we defer the registry until runtime. |
| 136 class WebUITestCallback : public ::test::RegisterTestCallback { |
| 137 public: |
| 138 WebUITestCallback( |
| 139 const ::FilePath& library_path, |
| 140 const char* test_case_name, const char* name, |
| 141 const char* type_param, |
| 142 const char* value_param, |
| 143 ::testing::internal::TypeId fixture_class_id, |
| 144 ::testing::internal::SetUpTestCaseFunc set_up_tc, |
| 145 ::testing::internal::TearDownTestCaseFunc tear_down_tc, |
| 146 ::testing::internal::TestMetaFactoryBase<std::string>* meta_factory) |
| 147 : library_path_(library_path), |
| 148 test_case_name_(test_case_name), |
| 149 name_(name), |
| 150 type_param_(type_param), |
| 151 value_param_(value_param), |
| 152 fixture_class_id_(fixture_class_id), |
| 153 set_up_tc_(set_up_tc), |
| 154 tear_down_tc_(tear_down_tc), |
| 155 meta_factory_(meta_factory) {} |
| 156 |
| 157 private: |
| 158 virtual void RegisterTest() const { |
| 159 std::vector<std::string> testFuncs; |
| 160 EXPECT_TRUE(GetTestFuncs(library_path_, &testFuncs)); |
| 161 for (std::vector<std::string>::const_iterator it = testFuncs.begin(); |
| 162 it != testFuncs.end(); ++it) { |
| 163 std::string test_name = *it + "/" + name_; |
| 164 ::testing::internal::MakeAndRegisterTestInfo( |
| 165 test_case_name_.c_str(), test_name.c_str(), |
| 166 type_param_.c_str(), |
| 167 value_param_.c_str(), |
| 168 fixture_class_id_, |
| 169 set_up_tc_, |
| 170 tear_down_tc_, |
| 171 meta_factory_->CreateTestFactory(*it)); |
| 172 } |
| 173 } |
| 174 |
| 175 ::FilePath library_path_; |
| 176 std::string test_case_name_; |
| 177 std::string name_; |
| 178 std::string type_param_; |
| 179 std::string value_param_; |
| 180 ::testing::internal::TypeId fixture_class_id_; |
| 181 ::testing::internal::SetUpTestCaseFunc set_up_tc_; |
| 182 ::testing::internal::TearDownTestCaseFunc tear_down_tc_; |
| 183 ::testing::internal::TestMetaFactoryBase<std::string>* meta_factory_; |
| 184 |
| 185 DISALLOW_COPY_AND_ASSIGN(WebUITestCallback); |
| 186 }; |
| 187 |
| 188 } // namespace |
| 189 |
40 WebUIBrowserTest::~WebUIBrowserTest() {} | 190 WebUIBrowserTest::~WebUIBrowserTest() {} |
41 | 191 |
42 bool WebUIBrowserTest::RunJavascriptFunction(const std::string& function_name) { | 192 bool WebUIBrowserTest::RunJavascriptFunction(const std::string& function_name) { |
43 return RunJavascriptFunction(function_name, ConstValueVector()); | 193 return RunJavascriptFunction(function_name, ConstValueVector()); |
44 } | 194 } |
45 | 195 |
46 bool WebUIBrowserTest::RunJavascriptFunction(const std::string& function_name, | 196 bool WebUIBrowserTest::RunJavascriptFunction(const std::string& function_name, |
47 const Value& arg) { | 197 const Value& arg) { |
48 ConstValueVector args; | 198 ConstValueVector args; |
49 args.push_back(&arg); | 199 args.push_back(&arg); |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
88 bool WebUIBrowserTest::RunJavascriptTest( | 238 bool WebUIBrowserTest::RunJavascriptTest( |
89 const std::string& test_name, | 239 const std::string& test_name, |
90 const ConstValueVector& test_arguments) { | 240 const ConstValueVector& test_arguments) { |
91 return RunJavascriptUsingHandler(test_name, test_arguments, true); | 241 return RunJavascriptUsingHandler(test_name, test_arguments, true); |
92 } | 242 } |
93 | 243 |
94 WebUIBrowserTest::WebUIBrowserTest() | 244 WebUIBrowserTest::WebUIBrowserTest() |
95 : test_handler_(new WebUITestHandler()) {} | 245 : test_handler_(new WebUITestHandler()) {} |
96 | 246 |
97 void WebUIBrowserTest::SetUpInProcessBrowserTestFixture() { | 247 void WebUIBrowserTest::SetUpInProcessBrowserTestFixture() { |
98 ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &test_data_directory_)); | 248 test_data_directory_ = GetTestDataDirectory(); |
99 test_data_directory_ = test_data_directory_.Append(kWebUITestFolder); | |
100 | 249 |
101 // TODO(dtseng): should this be part of every BrowserTest or just WebUI test. | 250 // TODO(dtseng): should this be part of every BrowserTest or just WebUI test. |
102 FilePath resources_pack_path; | 251 FilePath resources_pack_path; |
103 PathService::Get(chrome::FILE_RESOURCES_PACK, &resources_pack_path); | 252 PathService::Get(chrome::FILE_RESOURCES_PACK, &resources_pack_path); |
104 ResourceBundle::AddDataPackToSharedInstance(resources_pack_path); | 253 ResourceBundle::AddDataPackToSharedInstance(resources_pack_path); |
105 | 254 |
106 AddLibrary(FilePath(kWebUILibraryJS)); | 255 AddLibrary(FilePath(kWebUILibraryJS)); |
107 } | 256 } |
108 | 257 |
109 WebUIMessageHandler* WebUIBrowserTest::GetMockMessageHandler() { | 258 WebUIMessageHandler* WebUIBrowserTest::GetMockMessageHandler() { |
110 return NULL; | 259 return NULL; |
111 } | 260 } |
112 | 261 |
113 void WebUIBrowserTest::BuildJavascriptLibraries(std::string* content) { | 262 int WebUIBrowserTest::AddJSToRegistry( |
| 263 const FilePath& library_path, |
| 264 const char* test_case_name, const char* name, |
| 265 const char* type_param, |
| 266 const char* value_param, |
| 267 ::testing::internal::TypeId fixture_class_id, |
| 268 ::testing::internal::SetUpTestCaseFunc set_up_tc, |
| 269 ::testing::internal::TearDownTestCaseFunc tear_down_tc, |
| 270 ::testing::internal::TestMetaFactoryBase<std::string>* meta_factory) { |
| 271 test::AddRegisterTestCallback(new WebUITestCallback( |
| 272 library_path, test_case_name, name, type_param, value_param, |
| 273 fixture_class_id, set_up_tc, tear_down_tc, meta_factory)); |
| 274 |
| 275 return 0; |
| 276 } |
| 277 |
| 278 |
| 279 void WebUIBrowserTest::BuildJavascriptLibraries(std::string* content) const { |
114 ASSERT_TRUE(content != NULL); | 280 ASSERT_TRUE(content != NULL); |
115 std::string library_content, src_content; | 281 std::string library_content; |
116 | 282 |
117 std::vector<FilePath>::iterator user_libraries_iterator; | 283 std::vector<FilePath>::const_iterator user_libraries_iterator; |
118 for (user_libraries_iterator = user_libraries.begin(); | 284 for (user_libraries_iterator = user_libraries_.begin(); |
119 user_libraries_iterator != user_libraries.end(); | 285 user_libraries_iterator != user_libraries_.end(); |
120 ++user_libraries_iterator) { | 286 ++user_libraries_iterator) { |
121 if (user_libraries_iterator->IsAbsolute()) { | 287 ReadLibraryToString(test_data_directory_, *user_libraries_iterator, |
122 ASSERT_TRUE(file_util::ReadFileToString(*user_libraries_iterator, | 288 &library_content); |
123 &library_content)); | |
124 } else { | |
125 ASSERT_TRUE(file_util::ReadFileToString( | |
126 test_data_directory_.Append(*user_libraries_iterator), | |
127 &library_content)); | |
128 } | |
129 content->append(library_content); | 289 content->append(library_content); |
130 content->append(";\n"); | 290 content->append(";\n"); |
131 } | 291 } |
132 } | 292 } |
133 | 293 |
134 string16 WebUIBrowserTest::BuildRunTestJSCall( | 294 string16 WebUIBrowserTest::BuildRunTestJSCall( |
135 const std::string& function_name, | 295 const std::string& function_name, |
136 const WebUIBrowserTest::ConstValueVector& test_func_args) { | 296 const WebUIBrowserTest::ConstValueVector& test_func_args) { |
137 WebUIBrowserTest::ConstValueVector arguments; | 297 WebUIBrowserTest::ConstValueVector arguments; |
138 StringValue function_name_arg(function_name); | 298 StringValue function_name_arg(function_name); |
(...skipping 24 matching lines...) Expand all Loading... |
163 called_function = WebUI::GetJavascriptCall(function_name, | 323 called_function = WebUI::GetJavascriptCall(function_name, |
164 function_arguments); | 324 function_arguments); |
165 } | 325 } |
166 content.append(UTF16ToUTF8(called_function)); | 326 content.append(UTF16ToUTF8(called_function)); |
167 } | 327 } |
168 SetupHandlers(); | 328 SetupHandlers(); |
169 logging::SetLogMessageHandler(&LogHandler); | 329 logging::SetLogMessageHandler(&LogHandler); |
170 bool result = test_handler_->RunJavascript(content, is_test); | 330 bool result = test_handler_->RunJavascript(content, is_test); |
171 logging::SetLogMessageHandler(NULL); | 331 logging::SetLogMessageHandler(NULL); |
172 | 332 |
173 if (error_messages_.size() > 0) { | 333 if (error_messages_.Get().size() > 0) { |
174 LOG(ERROR) << "Encountered javascript console error(s)"; | 334 LOG(ERROR) << "Encountered javascript console error(s)"; |
175 result = false; | 335 result = false; |
176 error_messages_.clear(); | 336 error_messages_.Get().clear(); |
177 } | 337 } |
178 return result; | 338 return result; |
179 } | 339 } |
180 | 340 |
181 void WebUIBrowserTest::SetupHandlers() { | 341 void WebUIBrowserTest::SetupHandlers() { |
182 WebUI* web_ui_instance = | 342 WebUI* web_ui_instance = |
183 browser()->GetSelectedTabContents()->web_ui(); | 343 browser()->GetSelectedTabContents()->web_ui(); |
184 ASSERT_TRUE(web_ui_instance != NULL); | 344 ASSERT_TRUE(web_ui_instance != NULL); |
185 web_ui_instance->register_callback_overwrites(true); | 345 web_ui_instance->register_callback_overwrites(true); |
186 test_handler_->Attach(web_ui_instance); | 346 test_handler_->Attach(web_ui_instance); |
187 | 347 |
188 if (GetMockMessageHandler()) | 348 if (GetMockMessageHandler()) |
189 GetMockMessageHandler()->Attach(web_ui_instance); | 349 GetMockMessageHandler()->Attach(web_ui_instance); |
190 } | 350 } |
191 | 351 |
192 void WebUIBrowserTest::AddLibrary(const FilePath& library_path) { | 352 void WebUIBrowserTest::AddLibrary(const FilePath& library_path) { |
193 user_libraries.push_back(library_path); | 353 user_libraries_.push_back(library_path); |
194 } | 354 } |
195 | 355 |
196 IN_PROC_BROWSER_TEST_F(WebUIBrowserTest, TestSamplePass) { | 356 IN_PROC_BROWSER_TEST_F(WebUIBrowserTest, TestSamplePass) { |
197 AddLibrary(FilePath(FILE_PATH_LITERAL("sample_downloads.js"))); | 357 AddLibrary(FilePath(FILE_PATH_LITERAL("sample_passing.js"))); |
198 | 358 |
199 // Navigate to UI. | 359 // Navigate to UI. |
200 // TODO(dtseng): make accessor for subclasses to return? | 360 // TODO(dtseng): make accessor for subclasses to return? |
201 ui_test_utils::NavigateToURL(browser(), GURL(chrome::kChromeUIDownloadsURL)); | 361 ui_test_utils::NavigateToURL(browser(), GURL(chrome::kChromeUIDownloadsURL)); |
202 | 362 |
203 ASSERT_TRUE(RunJavascriptTest("testAssertFalse")); | 363 ASSERT_TRUE(RunJavascriptTest("testAssertFalse")); |
204 ASSERT_TRUE(RunJavascriptTest("testInitialFocus")); | 364 ASSERT_TRUE(RunJavascriptTest("testInitialFocus")); |
| 365 } |
| 366 |
| 367 IN_PROC_BROWSER_TEST_F(WebUIBrowserTest, TestSampleFail) { |
| 368 AddLibrary(FilePath(FILE_PATH_LITERAL("sample_failing.js"))); |
| 369 |
| 370 // Navigate to UI. |
| 371 // TODO(dtseng): make accessor for subclasses to return? |
| 372 ui_test_utils::NavigateToURL(browser(), GURL(chrome::kChromeUIDownloadsURL)); |
| 373 |
205 ASSERT_FALSE(RunJavascriptTest("testConsoleError")); | 374 ASSERT_FALSE(RunJavascriptTest("testConsoleError")); |
206 } | 375 } |
| 376 |
| 377 WEB_UI_BROWSER_TEST_JS(WebUIBrowserTest, TestJSPass, |
| 378 FILE_PATH_LITERAL("sample_passing.js")) { |
| 379 ui_test_utils::NavigateToURL(browser(), GURL(chrome::kChromeUIDownloadsURL)); |
| 380 } |
| 381 |
| 382 WEB_UI_BROWSER_TEST_JS_FALSE(WebUIBrowserTest, TestJSFail, |
| 383 FILE_PATH_LITERAL("sample_failing.js")) { |
| 384 ui_test_utils::NavigateToURL(browser(), GURL(chrome::kChromeUIDownloadsURL)); |
| 385 } |
OLD | NEW |