// Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "content/test/layout_browsertest.h" #include "base/file_path.h" #include "base/file_util.h" #include "base/path_service.h" #include "base/rand_util.h" #include "base/scoped_temp_dir.h" #include "base/stringprintf.h" #include "base/string_util.h" #include "base/utf_string_conversions.h" #include "chrome/browser/ui/browser.h" #include "chrome/test/base/in_process_browser_test.h" #include "chrome/test/base/layout_test_http_server.h" #include "chrome/test/base/ui_test_utils.h" #include "content/browser/tab_contents/tab_contents.h" #include "content/public/common/content_paths.h" #include "net/base/net_util.h" #if defined(OS_WIN) static const char kPlatformName[] = "chromium-win"; #elif defined(OS_MACOSX) static const char kPlatformName[] = "chromium-mac"; #elif defined(OS_LINUX) static const char kPlatformName[] = "chromium-linux"; #elif defined(OS_OPENBSD) static const char kPlatformName[] = "chromium-openbsd"; #else #error No known OS defined #endif namespace { size_t FindInsertPosition(const std::string& html) { size_t tag_start = html.find("", tag_start); if (tag_end == std::string::npos) return 0; return tag_end + 1; } bool ReadExpectedResult(const FilePath& result_dir_path, const std::string test_case_file_name, std::string* expected_result_value) { FilePath expected_result_path(result_dir_path); expected_result_path = expected_result_path.AppendASCII(test_case_file_name); expected_result_path = expected_result_path.InsertBeforeExtension( FILE_PATH_LITERAL("-expected")); expected_result_path = expected_result_path.ReplaceExtension(FILE_PATH_LITERAL("txt")); return file_util::ReadFileToString( expected_result_path, expected_result_value); } void ScrapeResultFromBrowser(Browser* browser, std::string* actual_text) { DOMElementProxyRef doc = ui_test_utils::GetActiveDOMDocument(browser); DOMElementProxyRef body = doc->FindElement(DOMElementProxy::By::XPath("//body")); ASSERT_TRUE(body.get()); ASSERT_TRUE(body->GetInnerText(actual_text)); } static const std::string preamble = "\n"; } InProcessBrowserLayoutTest::InProcessBrowserLayoutTest( const FilePath& test_parent_dir, const FilePath& test_case_dir) : test_parent_dir_(test_parent_dir), test_case_dir_(test_case_dir), port_(-2) { EnableDOMAutomation(); } InProcessBrowserLayoutTest::InProcessBrowserLayoutTest( const FilePath& test_parent_dir, const FilePath& test_case_dir, int port) : test_parent_dir_(test_parent_dir), test_case_dir_(test_case_dir), port_(port) { EnableDOMAutomation(); } InProcessBrowserLayoutTest::~InProcessBrowserLayoutTest() { if (test_http_server_.get()) CHECK(test_http_server_->Stop()); } void InProcessBrowserLayoutTest::SetUpInProcessBrowserTestFixture() { ASSERT_TRUE(scoped_temp_dir_.CreateUniqueTempDir()); FilePath src_dir; ASSERT_TRUE(PathService::Get(content::DIR_LAYOUT_TESTS, &src_dir)); our_original_layout_test_dir_ = src_dir.Append(test_parent_dir_).Append(test_case_dir_); ASSERT_TRUE(file_util::DirectoryExists(our_original_layout_test_dir_)); our_layout_test_temp_dir_ = scoped_temp_dir_.path() .AppendASCII("LayoutTests").Append(test_parent_dir_); ASSERT_TRUE(file_util::CreateDirectory( our_layout_test_temp_dir_.Append(test_case_dir_))); file_util::CopyDirectory( our_original_layout_test_dir_.AppendASCII("resources"), our_layout_test_temp_dir_.Append(test_case_dir_).AppendASCII("resources"), true /*recursive*/); // Gets the file path to rebased expected result directory for the current // platform. // $LayoutTestRoot/platform/chromium_***/... rebase_result_dir_ = src_dir.AppendASCII("platform"); rebase_result_dir_ = rebase_result_dir_.AppendASCII(kPlatformName); rebase_result_dir_ = rebase_result_dir_.Append(test_parent_dir_); rebase_result_dir_ = rebase_result_dir_.Append(test_case_dir_); // Generic chromium expected results. Not OS-specific. For example, // v8-specific differences go here. // chrome/test/data/layout_tests/LayoutTests/platform/chromium/... rebase_result_chromium_dir_ = src_dir.AppendASCII("platform"). AppendASCII("chromium"). Append(test_parent_dir_). Append(test_case_dir_); // Gets the file path to rebased expected result directory under the // win32 platform. This is used by other non-win32 platform to use the same // rebased expected results. #if !defined(OS_WIN) rebase_result_win_dir_ = src_dir.AppendASCII("platform"). AppendASCII("chromium-win"). Append(test_parent_dir_). Append(test_case_dir_); #endif if (port_ != -2) { // Layout tests expect that the server points at the // LayoutTests\http\tests directory. if (port_ == -1) port_ = base::RandInt(1024, 65535); test_http_server_.reset(new LayoutTestHttpServer( our_layout_test_temp_dir_, port_)); ASSERT_TRUE(test_http_server_->Start()); } } void InProcessBrowserLayoutTest::RunLayoutTest( const std::string& test_case_file_name) { FilePath file_path; WriteModifiedFile(test_case_file_name, &file_path); GURL url = net::FilePathToFileURL(file_path); RunLayoutTestInternal(test_case_file_name, url); } void InProcessBrowserLayoutTest::RunHttpLayoutTest( const std::string& test_case_file_name) { DCHECK(test_http_server_.get()); FilePath file_path; WriteModifiedFile(test_case_file_name, &file_path); GURL url(StringPrintf( "http://127.0.0.1:%d/%s/%s", port_, test_case_dir_.MaybeAsASCII().c_str(), test_case_file_name.c_str())); RunLayoutTestInternal(test_case_file_name, url); } void InProcessBrowserLayoutTest::RunLayoutTestInternal( const std::string& test_case_file_name, const GURL& url) { LOG(INFO) << "Navigating to URL " << url << " and blocking."; const string16 expected_title = ASCIIToUTF16("done"); ui_test_utils::TitleWatcher title_watcher( browser()->GetSelectedWebContents(), expected_title); ui_test_utils::NavigateToURL(browser(), url); LOG(INFO) << "Navigation completed, now waiting for title."; string16 final_title = title_watcher.WaitAndGetTitle(); EXPECT_EQ(expected_title, final_title); std::string actual_text; ScrapeResultFromBrowser(browser(), &actual_text); ReplaceSubstringsAfterOffset(&actual_text, 0, "\r", ""); TrimString(actual_text, "\n", &actual_text); std::string expected_text; // Reads the expected result. First try to read from rebase directory. // If failed, read from original directory. if (!ReadExpectedResult(rebase_result_dir_, test_case_file_name, &expected_text) && !ReadExpectedResult(rebase_result_chromium_dir_, test_case_file_name, &expected_text)) { if (rebase_result_win_dir_.empty() || !ReadExpectedResult(rebase_result_win_dir_, test_case_file_name, &expected_text)) ReadExpectedResult(our_original_layout_test_dir_, test_case_file_name, &expected_text); } ASSERT_TRUE(!expected_text.empty()); ReplaceSubstringsAfterOffset(&expected_text, 0, "\r", ""); TrimString(expected_text, "\n", &expected_text); EXPECT_EQ(expected_text, actual_text); } void InProcessBrowserLayoutTest::AddResourceForLayoutTest( const FilePath& parent_dir, const FilePath& resource_name) { FilePath source; ASSERT_TRUE(PathService::Get(content::DIR_LAYOUT_TESTS, &source)); source = source.Append(parent_dir); source = source.Append(resource_name); ASSERT_TRUE(file_util::PathExists(source)); FilePath dest_parent_dir = scoped_temp_dir_.path(). AppendASCII("LayoutTests").Append(parent_dir); ASSERT_TRUE(file_util::CreateDirectory(dest_parent_dir)); FilePath dest = dest_parent_dir.Append(resource_name); if (file_util::DirectoryExists(source)) { ASSERT_TRUE(file_util::CreateDirectory(dest.DirName())); ASSERT_TRUE(file_util::CopyDirectory(source, dest, true)); } else { ASSERT_TRUE(file_util::CopyFile(source, dest)); } } void InProcessBrowserLayoutTest::WriteModifiedFile( const std::string& test_case_file_name, FilePath* test_path) { FilePath path_to_single_test = our_original_layout_test_dir_.AppendASCII(test_case_file_name); std::string test_html; ASSERT_TRUE(file_util::ReadFileToString(path_to_single_test, &test_html)); size_t insertion_position = FindInsertPosition(test_html); test_html.insert(insertion_position, preamble); *test_path = our_layout_test_temp_dir_.Append(test_case_dir_); *test_path = test_path->AppendASCII(test_case_file_name); ASSERT_TRUE(file_util::WriteFile(*test_path, &test_html.at(0), static_cast(test_html.size()))); }