#include "content/test/layout_browsertest.h"
#include <sstream>
#include "base/command_line.h"
#include "base/file_path.h"
#include "base/file_util.h"
#include "base/path_service.h"
#include "base/rand_util.h"
#include "base/run_loop.h"
#include "base/scoped_temp_dir.h"
#include "base/stringprintf.h"
#include "base/string_util.h"
#include "base/utf_string_conversions.h"
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/public/common/content_paths.h"
#include "content/public/test/browser_test_utils.h"
#include "content/shell/shell.h"
#include "content/shell/shell_switches.h"
#include "content/shell/webkit_test_runner_host.h"
#include "content/test/content_browser_test_utils.h"
#include "content/test/layout_test_http_server.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 {
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);
}
}
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) {
}
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) {
}
InProcessBrowserLayoutTest::~InProcessBrowserLayoutTest() {
if (test_http_server_.get())
CHECK(test_http_server_->Stop());
}
void InProcessBrowserLayoutTest::SetUpInProcessBrowserTestFixture() {
FilePath src_dir;
ASSERT_TRUE(PathService::Get(content::DIR_LAYOUT_TESTS, &src_dir));
FilePath absolute_parent_dir = src_dir.Append(test_parent_dir_);
ASSERT_TRUE(file_util::DirectoryExists(absolute_parent_dir));
layout_test_dir_ = absolute_parent_dir.Append(test_case_dir_);
ASSERT_TRUE(file_util::DirectoryExists(layout_test_dir_));
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_);
rebase_result_chromium_dir_ = src_dir.AppendASCII("platform").
AppendASCII("chromium").
Append(test_parent_dir_).
Append(test_case_dir_);
#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) {
if (port_ == -1)
port_ = base::RandInt(1024, 65535);
test_http_server_.reset(new LayoutTestHttpServer(
absolute_parent_dir, port_));
ASSERT_TRUE(test_http_server_->Start());
}
}
void InProcessBrowserLayoutTest::SetUpCommandLine(CommandLine* command_line) {
command_line->AppendSwitch(switches::kDumpRenderTree);
}
void InProcessBrowserLayoutTest::SetUpOnMainThread() {
test_controller_.reset(new content::WebKitTestController);
}
void InProcessBrowserLayoutTest::RunLayoutTest(
const std::string& test_case_file_name) {
GURL url = net::FilePathToFileURL(
layout_test_dir_.AppendASCII(test_case_file_name));
RunLayoutTestInternal(test_case_file_name, url);
}
void InProcessBrowserLayoutTest::RunHttpLayoutTest(
const std::string& test_case_file_name) {
DCHECK(test_http_server_.get());
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) {
std::stringstream result;
scoped_ptr<content::WebKitTestResultPrinter> printer(
new content::WebKitTestResultPrinter(&result, NULL));
printer->set_capture_text_only(true);
test_controller_->set_printer(printer.release());
LOG(INFO) << "Navigating to URL " << url << " and blocking.";
ASSERT_TRUE(test_controller_->PrepareForLayoutTest(url, false, ""));
base::RunLoop run_loop;
run_loop.Run();
LOG(INFO) << "Navigation completed.";
ASSERT_TRUE(test_controller_->ResetAfterLayoutTest());
std::string actual_text = result.str();;
std::string expected_text;
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(layout_test_dir_,
test_case_file_name,
&expected_text);
}
ASSERT_TRUE(!expected_text.empty());
CommandLine* command_line = CommandLine::ForCurrentProcess();
if (command_line->HasSwitch(switches::kOutputLayoutTestDifferences)) {
EXPECT_EQ(expected_text, actual_text) <<
SaveResults(expected_text, actual_text);
} else {
EXPECT_EQ(expected_text, actual_text);
}
}
std::string InProcessBrowserLayoutTest::SaveResults(const std::string& expected,
const std::string& actual) {
FilePath cwd;
EXPECT_TRUE(file_util::CreateNewTempDirectory(FILE_PATH_LITERAL(""), &cwd));
FilePath expected_filename = cwd.Append(FILE_PATH_LITERAL("expected.txt"));
FilePath actual_filename = cwd.Append(FILE_PATH_LITERAL("actual.txt"));
EXPECT_NE(-1, file_util::WriteFile(expected_filename,
expected.c_str(),
expected.size()));
EXPECT_NE(-1, file_util::WriteFile(actual_filename,
actual.c_str(),
actual.size()));
return StringPrintf("Wrote %"PRFilePath" %"PRFilePath,
expected_filename.value().c_str(),
actual_filename.value().c_str());
}