|  | // Copyright 2015 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 "components/test_runner/test_info_extractor.h" | 
|  |  | 
|  | #include <iostream> | 
|  |  | 
|  | #include "base/base_paths.h" | 
|  | #include "base/files/file_util.h" | 
|  | #include "base/path_service.h" | 
|  | #include "base/strings/sys_string_conversions.h" | 
|  | #include "base/strings/utf_string_conversions.h" | 
|  | #include "base/threading/thread_restrictions.h" | 
|  | #include "build/build_config.h" | 
|  | #include "net/base/filename_util.h" | 
|  |  | 
|  | namespace test_runner { | 
|  |  | 
|  | namespace { | 
|  |  | 
|  | #if defined(OS_ANDROID) | 
|  | // On Android, all passed tests will be paths to a local temporary directory. | 
|  | // However, because we can't transfer all test files to the device, translate | 
|  | // those paths to a local, forwarded URL so the host can serve them. | 
|  | bool GetTestUrlForAndroid(std::string& path_or_url, GURL* url) { | 
|  | // Path to search for when translating a layout test path to an URL. | 
|  | const char kAndroidLayoutTestPath[] = | 
|  | "/data/local/tmp/third_party/WebKit/LayoutTests/"; | 
|  | // The base URL from which layout tests are being served on Android. | 
|  | const char kAndroidLayoutTestBase[] = "http://127.0.0.1:8000/all-tests/"; | 
|  |  | 
|  | if (path_or_url.find(kAndroidLayoutTestPath) == std::string::npos) | 
|  | return false; | 
|  |  | 
|  | std::string test_location(kAndroidLayoutTestBase); | 
|  | test_location.append(path_or_url.substr(strlen(kAndroidLayoutTestPath))); | 
|  |  | 
|  | *url = GURL(test_location); | 
|  | return true; | 
|  | } | 
|  | #endif  // defined(OS_ANDROID) | 
|  |  | 
|  | scoped_ptr<TestInfo> GetTestInfoFromLayoutTestName( | 
|  | const std::string& test_name) { | 
|  | // A test name is formated like file:///path/to/test'--pixel-test'pixelhash | 
|  | std::string path_or_url = test_name; | 
|  | std::string pixel_switch; | 
|  | std::string::size_type separator_position = path_or_url.find('\''); | 
|  | if (separator_position != std::string::npos) { | 
|  | pixel_switch = path_or_url.substr(separator_position + 1); | 
|  | path_or_url.erase(separator_position); | 
|  | } | 
|  | separator_position = pixel_switch.find('\''); | 
|  | std::string expected_pixel_hash; | 
|  | if (separator_position != std::string::npos) { | 
|  | expected_pixel_hash = pixel_switch.substr(separator_position + 1); | 
|  | pixel_switch.erase(separator_position); | 
|  | } | 
|  | const bool enable_pixel_dumping = | 
|  | (pixel_switch == "--pixel-test" || pixel_switch == "-p"); | 
|  |  | 
|  | GURL test_url; | 
|  | #if defined(OS_ANDROID) | 
|  | if (GetTestUrlForAndroid(path_or_url, &test_url)) { | 
|  | return make_scoped_ptr(new TestInfo(test_url, enable_pixel_dumping, | 
|  | expected_pixel_hash, base::FilePath())); | 
|  | } | 
|  | #endif | 
|  |  | 
|  | test_url = GURL(path_or_url); | 
|  | if (!(test_url.is_valid() && test_url.has_scheme())) { | 
|  | // We're outside of the message loop here, and this is a test. | 
|  | base::ThreadRestrictions::ScopedAllowIO allow_io; | 
|  | #if defined(OS_WIN) | 
|  | base::FilePath::StringType wide_path_or_url = | 
|  | base::SysNativeMBToWide(path_or_url); | 
|  | base::FilePath local_file(wide_path_or_url); | 
|  | #else | 
|  | base::FilePath local_file(path_or_url); | 
|  | #endif | 
|  | if (!base::PathExists(local_file)) { | 
|  | base::FilePath base_path; | 
|  | PathService::Get(base::DIR_SOURCE_ROOT, &base_path); | 
|  | local_file = base_path.Append(FILE_PATH_LITERAL("third_party")) | 
|  | .Append(FILE_PATH_LITERAL("WebKit")) | 
|  | .Append(FILE_PATH_LITERAL("LayoutTests")) | 
|  | .Append(local_file); | 
|  | } | 
|  | test_url = net::FilePathToFileURL(base::MakeAbsoluteFilePath(local_file)); | 
|  | } | 
|  | base::FilePath local_path; | 
|  | base::FilePath current_working_directory; | 
|  |  | 
|  | // We're outside of the message loop here, and this is a test. | 
|  | base::ThreadRestrictions::ScopedAllowIO allow_io; | 
|  | if (net::FileURLToFilePath(test_url, &local_path)) | 
|  | current_working_directory = local_path.DirName(); | 
|  | else | 
|  | base::GetCurrentDirectory(¤t_working_directory); | 
|  | return make_scoped_ptr(new TestInfo(test_url, enable_pixel_dumping, | 
|  | expected_pixel_hash, | 
|  | current_working_directory)); | 
|  | } | 
|  |  | 
|  | }  // namespace | 
|  |  | 
|  | TestInfo::TestInfo(const GURL& url, | 
|  | bool enable_pixel_dumping, | 
|  | const std::string& expected_pixel_hash, | 
|  | const base::FilePath& current_working_directory) | 
|  | : url(url), | 
|  | enable_pixel_dumping(enable_pixel_dumping), | 
|  | expected_pixel_hash(expected_pixel_hash), | 
|  | current_working_directory(current_working_directory) {} | 
|  | TestInfo::~TestInfo() {} | 
|  |  | 
|  | TestInfoExtractor::TestInfoExtractor( | 
|  | const base::CommandLine::StringVector& cmd_args) | 
|  | : cmdline_args_(cmd_args), cmdline_position_(0) {} | 
|  |  | 
|  | TestInfoExtractor::~TestInfoExtractor() {} | 
|  |  | 
|  | scoped_ptr<TestInfo> TestInfoExtractor::GetNextTest() { | 
|  | if (cmdline_position_ >= cmdline_args_.size()) | 
|  | return nullptr; | 
|  |  | 
|  | std::string test_string; | 
|  | if (cmdline_args_[cmdline_position_] == FILE_PATH_LITERAL("-")) { | 
|  | do { | 
|  | bool success = !!std::getline(std::cin, test_string, '\n'); | 
|  | if (!success) | 
|  | return nullptr; | 
|  | } while (test_string.empty()); | 
|  | } else { | 
|  | #if defined(OS_WIN) | 
|  | test_string = base::WideToUTF8(cmdline_args_[cmdline_position_++]); | 
|  | #else | 
|  | test_string = cmdline_args_[cmdline_position_++]; | 
|  | #endif | 
|  | } | 
|  |  | 
|  | DCHECK(!test_string.empty()); | 
|  | if (test_string == "QUIT") | 
|  | return nullptr; | 
|  | return GetTestInfoFromLayoutTestName(test_string); | 
|  | } | 
|  |  | 
|  | }  // namespace test_runner |