Add ability to override detection of resource location and source root
Bug: webrtc:9792
Change-Id: I944d2e1c1b4b4154a90eba6fbe9c417aad17498d
Reviewed-on: https://webrtc-review.googlesource.com/c/107401
Commit-Queue: Artem Titov <titovartem@webrtc.org>
Reviewed-by: Patrik Höglund <phoglund@webrtc.org>
Reviewed-by: Mirko Bonadei <mbonadei@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#25319}
diff --git a/test/BUILD.gn b/test/BUILD.gn
index 4d294cd..dc6dc79 100644
--- a/test/BUILD.gn
+++ b/test/BUILD.gn
@@ -377,7 +377,10 @@
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_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 @@
"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 ba1e793..0eac8d5 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 = "/";
#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 @@
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 @@
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 0000000..f29ddb8
--- /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 <direct.h>
+#include <tchar.h>
+#include <windows.h>
+#include <algorithm>
+#include <codecvt>
+#include <locale>
+
+#include "Shlwapi.h"
+#include "WinDef.h"
+
+#include "rtc_base/win32.h"
+#define GET_CURRENT_DIR _getcwd
+#else
+#include <dirent.h>
+#include <unistd.h>
+#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 0000000..141c768
--- /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 <stdio.h>
+#include <string>
+
+#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_