From 8f726be415207c38d8256d56ae53dbcdcff8b8d8 Mon Sep 17 00:00:00 2001 From: Artem Titov Date: Tue, 23 Oct 2018 15:50:10 +0200 Subject: [PATCH] Add ability to override detection of resource location and source root MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bug: webrtc:9792 Change-Id: I944d2e1c1b4b4154a90eba6fbe9c417aad17498d Reviewed-on: https://webrtc-review.googlesource.com/c/107401 Commit-Queue: Artem Titov Reviewed-by: Patrik Höglund Reviewed-by: Mirko Bonadei Cr-Commit-Position: refs/heads/master@{#25319} --- test/BUILD.gn | 46 +++++++- test/testsupport/fileutils.cc | 82 +------------- test/testsupport/fileutils_override.cc | 151 +++++++++++++++++++++++++ test/testsupport/fileutils_override.h | 57 ++++++++++ 4 files changed, 256 insertions(+), 80 deletions(-) create mode 100644 test/testsupport/fileutils_override.cc create mode 100644 test/testsupport/fileutils_override.h diff --git a/test/BUILD.gn b/test/BUILD.gn index 4d294cdff5..dc6dc7996d 100644 --- a/test/BUILD.gn +++ b/test/BUILD.gn @@ -377,7 +377,10 @@ if (rtc_include_tests) { if (is_ios) { rtc_source_set("fileutils_ios_objc") { - visibility = [ ":fileutils" ] + visibility = [ + ":fileutils", + ":fileutils_override_impl", + ] sources = [ "testsupport/iosfileutils.h", "testsupport/iosfileutils.mm", @@ -393,7 +396,10 @@ if (is_ios) { if (is_mac) { rtc_source_set("fileutils_mac_objc") { - visibility = [ ":fileutils" ] + visibility = [ + ":fileutils", + ":fileutils_override_impl", + ] sources = [ "testsupport/macfileutils.h", "testsupport/macfileutils.mm", @@ -412,6 +418,42 @@ rtc_source_set("fileutils") { "testsupport/fileutils.h", ] deps = [ + ":fileutils_override_api", + ":fileutils_override_impl", + "..:webrtc_common", + "../rtc_base:checks", + "../rtc_base:rtc_base_approved", + "../rtc_base/system:arch", + "//third_party/abseil-cpp/absl/types:optional", + ] + if (is_ios) { + deps += [ ":fileutils_ios_objc" ] + } + if (is_mac) { + deps += [ ":fileutils_mac_objc" ] + } + if (is_win) { + deps += [ "../rtc_base:rtc_base" ] + } +} + +# We separate header into own target to make it possible for downstream +# projects to override implementation. +rtc_source_set("fileutils_override_api") { + testonly = true + sources = [ + "testsupport/fileutils_override.h", + ] +} + +rtc_source_set("fileutils_override_impl") { + testonly = true + visibility = [ ":fileutils" ] + sources = [ + "testsupport/fileutils_override.cc", + ] + deps = [ + ":fileutils_override_api", "..:webrtc_common", "../rtc_base:checks", "../rtc_base:rtc_base_approved", diff --git a/test/testsupport/fileutils.cc b/test/testsupport/fileutils.cc index ba1e793510..0eac8d5e0f 100644 --- a/test/testsupport/fileutils.cc +++ b/test/testsupport/fileutils.cc @@ -59,6 +59,7 @@ #include "rtc_base/arraysize.h" #include "rtc_base/checks.h" #include "rtc_base/stringutils.h" +#include "test/testsupport/fileutils_override.h" namespace webrtc { namespace test { @@ -71,20 +72,8 @@ const char* kPathDelimiter = "\\"; const char* kPathDelimiter = "/"; #endif -#if defined(WEBRTC_ANDROID) -// This is a special case in Chrome infrastructure. See -// base/test/test_support_android.cc. -const char* kAndroidChromiumTestsRoot = "/sdcard/chromium_tests_root/"; -#endif - -#if !defined(WEBRTC_IOS) -const char* kResourcesDirName = "resources"; -#endif - } // namespace -const char* kCannotFindProjectRootDir = "ERROR_CANNOT_FIND_PROJECT_ROOT_DIR"; - std::string DirName(const std::string& path) { if (path.empty()) return ""; @@ -109,69 +98,12 @@ bool DirExists(const std::string& directory_name) { S_ISDIR(directory_info.st_mode); } -// Finds the WebRTC src dir. -// The returned path always ends with a path separator. -std::string ProjectRootPath() { -#if defined(WEBRTC_ANDROID) - return kAndroidChromiumTestsRoot; -#elif defined WEBRTC_IOS - return IOSRootPath(); -#elif defined(WEBRTC_MAC) - std::string path; - GetNSExecutablePath(&path); - std::string exe_dir = DirName(path); - // On Mac, tests execute in out/Whatever, so src is two levels up except if - // the test is bundled (which our tests are not), in which case it's 5 levels. - return DirName(DirName(exe_dir)) + kPathDelimiter; -#elif defined(WEBRTC_POSIX) - char buf[PATH_MAX]; - ssize_t count = ::readlink("/proc/self/exe", buf, arraysize(buf)); - if (count <= 0) { - RTC_NOTREACHED() << "Unable to resolve /proc/self/exe."; - return kCannotFindProjectRootDir; - } - // On POSIX, tests execute in out/Whatever, so src is two levels up. - std::string exe_dir = DirName(std::string(buf, count)); - return DirName(DirName(exe_dir)) + kPathDelimiter; -#elif defined(WEBRTC_WIN) - wchar_t buf[MAX_PATH]; - buf[0] = 0; - if (GetModuleFileName(NULL, buf, MAX_PATH) == 0) - return kCannotFindProjectRootDir; - - std::string exe_path = rtc::ToUtf8(std::wstring(buf)); - std::string exe_dir = DirName(exe_path); - return DirName(DirName(exe_dir)) + kPathDelimiter; -#endif -} - std::string OutputPath() { -#if defined(WEBRTC_IOS) - return IOSOutputPath(); -#elif defined(WEBRTC_ANDROID) - return kAndroidChromiumTestsRoot; -#else - std::string path = ProjectRootPath(); - RTC_DCHECK_NE(path, kCannotFindProjectRootDir); - path += "out"; - if (!CreateDir(path)) { - return "./"; - } - return path + kPathDelimiter; -#endif + return webrtc::test::internal::OutputPath(); } std::string WorkingDir() { -#if defined(WEBRTC_ANDROID) - return kAndroidChromiumTestsRoot; -#endif - char path_buffer[FILENAME_MAX]; - if (!GET_CURRENT_DIR(path_buffer, sizeof(path_buffer))) { - fprintf(stderr, "Cannot get current directory!\n"); - return "./"; - } else { - return std::string(path_buffer); - } + return webrtc::test::internal::WorkingDir(); } // Generate a temporary filename in a safe way. @@ -298,13 +230,7 @@ bool RemoveFile(const std::string& file_name) { std::string ResourcePath(const std::string& name, const std::string& extension) { -#if defined(WEBRTC_IOS) - return IOSResourcePath(name, extension); -#else - std::string resources_path = - ProjectRootPath() + kResourcesDirName + kPathDelimiter; - return resources_path + name + "." + extension; -#endif + return webrtc::test::internal::ResourcePath(name, extension); } std::string JoinFilename(const std::string& dir, const std::string& name) { diff --git a/test/testsupport/fileutils_override.cc b/test/testsupport/fileutils_override.cc new file mode 100644 index 0000000000..f29ddb8804 --- /dev/null +++ b/test/testsupport/fileutils_override.cc @@ -0,0 +1,151 @@ +/* + * Copyright (c) 2018 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#include "test/testsupport/fileutils_override.h" + +#if defined(WEBRTC_WIN) +#include +#include +#include +#include +#include +#include + +#include "Shlwapi.h" +#include "WinDef.h" + +#include "rtc_base/win32.h" +#define GET_CURRENT_DIR _getcwd +#else +#include +#include +#define GET_CURRENT_DIR getcwd +#endif + +#if defined(WEBRTC_IOS) +#include "test/testsupport/iosfileutils.h" +#endif + +#if defined(WEBRTC_MAC) +#include "test/testsupport/macfileutils.h" +#endif + +#include "rtc_base/arraysize.h" +#include "rtc_base/checks.h" +#include "rtc_base/stringutils.h" + +namespace webrtc { +namespace test { + +std::string DirName(const std::string& path); +bool CreateDir(const std::string& directory_name); + +namespace internal { + +namespace { +#if defined(WEBRTC_WIN) +const char* kPathDelimiter = "\\"; +#elif !defined(WEBRTC_IOS) +const char* kPathDelimiter = "/"; +#endif + +#if defined(WEBRTC_ANDROID) +// This is a special case in Chrome infrastructure. See +// base/test/test_support_android.cc. +const char* kAndroidChromiumTestsRoot = "/sdcard/chromium_tests_root/"; +#endif + +#if !defined(WEBRTC_IOS) +const char* kResourcesDirName = "resources"; +#endif + +} // namespace + +const char* kCannotFindProjectRootDir = "ERROR_CANNOT_FIND_PROJECT_ROOT_DIR"; + +// Finds the WebRTC src dir. +// The returned path always ends with a path separator. +std::string ProjectRootPath() { +#if defined(WEBRTC_ANDROID) + return kAndroidChromiumTestsRoot; +#elif defined WEBRTC_IOS + return IOSRootPath(); +#elif defined(WEBRTC_MAC) + std::string path; + GetNSExecutablePath(&path); + std::string exe_dir = DirName(path); + // On Mac, tests execute in out/Whatever, so src is two levels up except if + // the test is bundled (which our tests are not), in which case it's 5 levels. + return DirName(DirName(exe_dir)) + kPathDelimiter; +#elif defined(WEBRTC_POSIX) + char buf[PATH_MAX]; + ssize_t count = ::readlink("/proc/self/exe", buf, arraysize(buf)); + if (count <= 0) { + RTC_NOTREACHED() << "Unable to resolve /proc/self/exe."; + return kCannotFindProjectRootDir; + } + // On POSIX, tests execute in out/Whatever, so src is two levels up. + std::string exe_dir = DirName(std::string(buf, count)); + return DirName(DirName(exe_dir)) + kPathDelimiter; +#elif defined(WEBRTC_WIN) + wchar_t buf[MAX_PATH]; + buf[0] = 0; + if (GetModuleFileName(NULL, buf, MAX_PATH) == 0) + return kCannotFindProjectRootDir; + + std::string exe_path = rtc::ToUtf8(std::wstring(buf)); + std::string exe_dir = DirName(exe_path); + return DirName(DirName(exe_dir)) + kPathDelimiter; +#endif +} + +std::string OutputPath() { +#if defined(WEBRTC_IOS) + return IOSOutputPath(); +#elif defined(WEBRTC_ANDROID) + return kAndroidChromiumTestsRoot; +#else + std::string path = ProjectRootPath(); + RTC_DCHECK_NE(path, kCannotFindProjectRootDir); + path += "out"; + if (!CreateDir(path)) { + return "./"; + } + return path + kPathDelimiter; +#endif +} + +std::string WorkingDir() { +#if defined(WEBRTC_ANDROID) + return kAndroidChromiumTestsRoot; +#endif + char path_buffer[FILENAME_MAX]; + if (!GET_CURRENT_DIR(path_buffer, sizeof(path_buffer))) { + fprintf(stderr, "Cannot get current directory!\n"); + return "./"; + } else { + return std::string(path_buffer); + } +} + +std::string ResourcePath(const std::string& name, + const std::string& extension) { +#if defined(WEBRTC_IOS) + return IOSResourcePath(name, extension); +#else + std::string resources_path = + ProjectRootPath() + kResourcesDirName + kPathDelimiter; + return resources_path + name + "." + extension; +#endif +} + +} // namespace internal +} // namespace test +} // namespace webrtc diff --git a/test/testsupport/fileutils_override.h b/test/testsupport/fileutils_override.h new file mode 100644 index 0000000000..141c768607 --- /dev/null +++ b/test/testsupport/fileutils_override.h @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2018 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#include +#include + +#ifndef TEST_TESTSUPPORT_FILEUTILS_OVERRIDE_H_ +#define TEST_TESTSUPPORT_FILEUTILS_OVERRIDE_H_ + +namespace webrtc { +namespace test { +namespace internal { + +// Returns the absolute path to the output directory where log files and other +// test artifacts should be put. The output directory is generally a directory +// named "out" at the project root. This root is assumed to be two levels above +// where the test binary is located; this is because tests execute in a dir +// out/Whatever relative to the project root. This convention is also followed +// in Chromium. +// +// The exception is Android where we use /sdcard/ instead. +// +// If symbolic links occur in the path they will be resolved and the actual +// directory will be returned. +// +// Returns the path WITH a trailing path delimiter. If the project root is not +// found, the current working directory ("./") is returned as a fallback. +std::string OutputPath(); + +// Gets the current working directory for the executing program. +// Returns "./" if for some reason it is not possible to find the working +// directory. +std::string WorkingDir(); + +// Returns a path to a resource file in [project-root]/resources/ dir. +// Returns an absolute path +// +// Arguments: +// name - Name of the resource file. If a plain filename (no directory path) +// is supplied, the file is assumed to be located in resources/ +// If a directory path is prepended to the filename, a subdirectory +// hierarchy reflecting that path is assumed to be present. +// extension - File extension, without the dot, i.e. "bmp" or "yuv". +std::string ResourcePath(const std::string& name, const std::string& extension); + +} // namespace internal +} // namespace test +} // namespace webrtc + +#endif // TEST_TESTSUPPORT_FILEUTILS_OVERRIDE_H_