Chromium Code Reviews| Index: chrome/browser/ui/webui/web_ui_browsertest.cc |
| diff --git a/chrome/browser/ui/webui/web_ui_browsertest.cc b/chrome/browser/ui/webui/web_ui_browsertest.cc |
| index 026c77d7cbf0163419dbee10654620b6b81dac4c..fdd3c2611e6a349841d47b7ec5a461bcfa213a37 100644 |
| --- a/chrome/browser/ui/webui/web_ui_browsertest.cc |
| +++ b/chrome/browser/ui/webui/web_ui_browsertest.cc |
| @@ -6,6 +6,9 @@ |
| #include <string> |
| #include <vector> |
| +#include "base/at_exit.h" |
| +#include "base/lazy_instance.h" |
| +#include "base/memory/singleton.h" |
| #include "base/path_service.h" |
| #include "base/values.h" |
| #include "chrome/browser/ui/browser.h" |
| @@ -15,11 +18,29 @@ |
| #include "content/browser/tab_contents/tab_contents.h" |
| #include "content/browser/webui/web_ui.h" |
| #include "ui/base/resource/resource_bundle.h" |
| +#include "v8/include/v8.h" |
| -static const FilePath::CharType* kWebUILibraryJS = |
| - FILE_PATH_LITERAL("test_api.js"); |
| -static const FilePath::CharType* kWebUITestFolder = FILE_PATH_LITERAL("webui"); |
| -static std::vector<std::string> error_messages_; |
| +namespace { |
| +const FilePath::CharType* kWebUILibraryJS = FILE_PATH_LITERAL("test_api.js"); |
| +const FilePath::CharType* kWebUITestFolder = FILE_PATH_LITERAL("webui"); |
| + |
| +base::LazyInstance<std::vector<std::string> > error_messages_( |
| + base::LINKER_INITIALIZED); |
| + |
| +// GTEST registration happens at linker initialization. When |
| +// |linker_initialized| is true, set up and tear down enough to enable the |
| +// PathService to give us path to the test data directory. |
| +FilePath GetTestDataDirectory(bool linker_initialized) { |
| + scoped_ptr<base::AtExitManager> at_exit_manager; |
| + if (linker_initialized) { |
| + at_exit_manager.reset(new base::AtExitManager()); |
| + chrome::RegisterPathProvider(); |
| + } |
| + |
| + FilePath test_data_directory; |
| + EXPECT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &test_data_directory)); |
| + return test_data_directory.Append(kWebUITestFolder); |
| +} |
| // Intercepts all log messages. |
| bool LogHandler(int severity, |
| @@ -28,7 +49,7 @@ bool LogHandler(int severity, |
| size_t message_start, |
| const std::string& str) { |
| if (severity == logging::LOG_ERROR) { |
| - error_messages_.push_back(str); |
| + error_messages_.Get().push_back(str); |
| return true; |
| } else { |
| // For debugging messages while developing tests. |
| @@ -36,6 +57,67 @@ bool LogHandler(int severity, |
| } |
| } |
| +// Read the specified |library| into |content|, prepending |test_data_directory| |
| +// when |library| is relative. |
| +void ReadLibraryToString(const FilePath& test_data_directory, |
| + const FilePath& library, |
| + std::string* content) { |
| + ASSERT_TRUE(content); |
| + if (library.IsAbsolute()) { |
|
Paweł Hajdan Jr.
2011/05/30 17:17:58
I think this may be error prone. Could you add two
Sheridan Rawlins
2011/05/31 23:15:00
David says we don't need the absolute case. I'll
Sheridan Rawlins
2011/06/08 14:24:45
The BIDI checker uses third party test script. Pu
|
| + ASSERT_TRUE(file_util::ReadFileToString(library, content)); |
| + } else { |
| + ASSERT_TRUE(file_util::ReadFileToString(test_data_directory.Append(library), |
| + content)); |
| + } |
| +} |
| + |
| +// Gets functions defined in |library_path| starting with "test". |testFuncs| |
| +// may not be NULL. |
| +bool GetTestFuncs(const FilePath& library_path, |
| + std::vector<std::string>* testFuncs) { |
| + DCHECK(testFuncs); |
| + |
| + std::string content = "var window = {};"; |
| + ReadLibraryToString(GetTestDataDirectory(true), library_path, &content); |
| + content.append( |
| + "(function () {" |
|
David Tseng
2011/05/30 20:44:49
Is there some way we can ask V8 to give us back th
Sheridan Rawlins
2011/05/31 23:15:00
The only way to get a variable from javascript is
|
| + " var funcs = new Array();" |
| + " for (var func in this) {" |
| + " if (typeof this[func] == 'function')" |
| + " funcs.push(func);" |
| + " }" |
| + " return funcs;" |
| + "})()"); |
| + |
| + v8::HandleScope handle_scope; |
| + v8::Persistent<v8::Context> context = v8::Context::New(); |
| + v8::Context::Scope context_scope(context); |
| + v8::Handle<v8::String> source = v8::String::New(content.data(), |
| + content.size()); |
| + v8::Handle<v8::Script> script = v8::Script::Compile(source); |
| + v8::TryCatch trycatch; |
| + v8::Handle<v8::Array> result = script->Run().As<v8::Array>(); |
| + context.Dispose(); |
| + if (result.IsEmpty()) { |
| + v8::Handle<v8::Value> exception = trycatch.Exception(); |
| + v8::String::AsciiValue exception_str(exception); |
| + NOTREACHED() << "Exception: " << *exception_str; |
|
Paweł Hajdan Jr.
2011/05/30 17:17:58
Why should a JS exception crash the entire test (t
Sheridan Rawlins
2011/05/31 23:15:00
Keep in mind this is a JS exception in examining t
|
| + return false; |
| + } |
| + |
| + for (uint32_t index = 0; index < result->Length(); ++index) { |
| + v8::Local<v8::String> value(result->Get(index).As<v8::String>()); |
| + if (value.IsEmpty()) { |
| + return false; |
| + } |
| + v8::String::AsciiValue ascii(value); |
| + testFuncs->push_back(std::string(*ascii, ascii.length())); |
| + } |
| + return true; |
| +} |
| + |
| +} // namespace |
| + |
| WebUIBrowserTest::~WebUIBrowserTest() {} |
| bool WebUIBrowserTest::RunJavascriptFunction(const std::string& function_name) { |
| @@ -94,8 +176,7 @@ WebUIBrowserTest::WebUIBrowserTest() |
| : test_handler_(new WebUITestHandler()) {} |
| void WebUIBrowserTest::SetUpInProcessBrowserTestFixture() { |
| - ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &test_data_directory_)); |
| - test_data_directory_ = test_data_directory_.Append(kWebUITestFolder); |
| + test_data_directory_ = GetTestDataDirectory(false); |
| // TODO(dtseng): should this be part of every BrowserTest or just WebUI test. |
| FilePath resources_pack_path; |
| @@ -109,22 +190,42 @@ WebUIMessageHandler* WebUIBrowserTest::GetMockMessageHandler() { |
| return NULL; |
| } |
| -void WebUIBrowserTest::BuildJavascriptLibraries(std::string* content) { |
| +int WebUIBrowserTest::AddJSToRegistry( |
| + const FilePath& library_path, |
| + const char* test_case_name, const char* name, |
| + const char* type_param, |
| + const char* value_param, |
| + ::testing::internal::TypeId fixture_class_id, |
| + ::testing::internal::SetUpTestCaseFunc set_up_tc, |
| + ::testing::internal::TearDownTestCaseFunc tear_down_tc, |
| + ::testing::internal::TestMetaFactoryBase<std::string>* meta_factory) { |
| + std::vector<std::string> testFuncs; |
| + EXPECT_TRUE(GetTestFuncs(library_path, &testFuncs)); |
| + for (std::vector<std::string>::const_iterator it = testFuncs.begin(); |
| + it != testFuncs.end(); ++it) { |
| + std::string test_name = *it + "/" + name; |
|
David Tseng
2011/05/30 20:44:49
Should
std::string test_name = *it + "/" + nam
Sheridan Rawlins
2011/05/31 23:15:00
I prefer to have the C++ Testname available (as me
|
| + ::testing::internal::MakeAndRegisterTestInfo( |
| + test_case_name, test_name.c_str(), |
| + type_param, |
| + value_param, |
| + fixture_class_id, |
| + set_up_tc, |
| + tear_down_tc, |
| + meta_factory->CreateTestFactory(*it)); |
| + } |
| + return testFuncs.size(); |
| +} |
| + |
| +void WebUIBrowserTest::BuildJavascriptLibraries(std::string* content) const { |
| ASSERT_TRUE(content != NULL); |
| - std::string library_content, src_content; |
| + std::string library_content; |
| - std::vector<FilePath>::iterator user_libraries_iterator; |
| - for (user_libraries_iterator = user_libraries.begin(); |
| - user_libraries_iterator != user_libraries.end(); |
| + std::vector<FilePath>::const_iterator user_libraries_iterator; |
| + for (user_libraries_iterator = user_libraries_.begin(); |
| + user_libraries_iterator != user_libraries_.end(); |
| ++user_libraries_iterator) { |
| - if (user_libraries_iterator->IsAbsolute()) { |
| - ASSERT_TRUE(file_util::ReadFileToString(*user_libraries_iterator, |
| - &library_content)); |
| - } else { |
| - ASSERT_TRUE(file_util::ReadFileToString( |
| - test_data_directory_.Append(*user_libraries_iterator), |
| - &library_content)); |
| - } |
| + ReadLibraryToString(test_data_directory_, *user_libraries_iterator, |
| + &library_content); |
| content->append(library_content); |
| content->append(";\n"); |
| } |
| @@ -169,10 +270,10 @@ bool WebUIBrowserTest::RunJavascriptUsingHandler( |
| bool result = test_handler_->RunJavascript(content, is_test); |
| logging::SetLogMessageHandler(NULL); |
| - if (error_messages_.size() > 0) { |
| + if (error_messages_.Get().size() > 0) { |
| LOG(ERROR) << "Encountered javascript console error(s)"; |
| result = false; |
| - error_messages_.clear(); |
| + error_messages_.Get().clear(); |
| } |
| return result; |
| } |
| @@ -189,11 +290,11 @@ void WebUIBrowserTest::SetupHandlers() { |
| } |
| void WebUIBrowserTest::AddLibrary(const FilePath& library_path) { |
| - user_libraries.push_back(library_path); |
| + user_libraries_.push_back(library_path); |
| } |
| IN_PROC_BROWSER_TEST_F(WebUIBrowserTest, TestSamplePass) { |
| - AddLibrary(FilePath(FILE_PATH_LITERAL("sample_downloads.js"))); |
| + AddLibrary(FilePath(FILE_PATH_LITERAL("sample_passing.js"))); |
| // Navigate to UI. |
| // TODO(dtseng): make accessor for subclasses to return? |
| @@ -201,5 +302,24 @@ IN_PROC_BROWSER_TEST_F(WebUIBrowserTest, TestSamplePass) { |
| ASSERT_TRUE(RunJavascriptTest("testAssertFalse")); |
| ASSERT_TRUE(RunJavascriptTest("testInitialFocus")); |
| +} |
| + |
| +IN_PROC_BROWSER_TEST_F(WebUIBrowserTest, TestSampleFail) { |
| + AddLibrary(FilePath(FILE_PATH_LITERAL("sample_failing.js"))); |
| + |
| + // Navigate to UI. |
| + // TODO(dtseng): make accessor for subclasses to return? |
| + ui_test_utils::NavigateToURL(browser(), GURL(chrome::kChromeUIDownloadsURL)); |
| + |
| ASSERT_FALSE(RunJavascriptTest("testConsoleError")); |
| } |
| + |
| +WEB_UI_BROWSER_TEST_JS(WebUIBrowserTest, TestJSPass, |
| + FILE_PATH_LITERAL("sample_passing.js")) { |
| + ui_test_utils::NavigateToURL(browser(), GURL(chrome::kChromeUIDownloadsURL)); |
| +} |
| + |
| +WEB_UI_BROWSER_TEST_JS_FALSE(WebUIBrowserTest, TestJSFail, |
| + FILE_PATH_LITERAL("sample_failing.js")) { |
| + ui_test_utils::NavigateToURL(browser(), GURL(chrome::kChromeUIDownloadsURL)); |
| +} |