Use Chromium's code for locating the src dir.
This code is much more sophisticated in that it doesn't rely
on argv[0], but rather asks the OS where our executable is.
We can then simply go two steps up since we count on running
in out/Whatever relative to the src dir. This is how Chromium
does it.
The aim here is to get rid of SetExecutablePath, which will
be the next CL.
Bug: webrtc:9792
Change-Id: I7da027b7391e759b1f612de12f27a244fe884c09
Reviewed-on: https://webrtc-review.googlesource.com/c/103121
Reviewed-by: Artem Titov <titovartem@webrtc.org>
Commit-Queue: Patrik Höglund <phoglund@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#25017}
diff --git a/test/testsupport/fileutils.cc b/test/testsupport/fileutils.cc
index 370ee06..cb88472 100644
--- a/test/testsupport/fileutils.cc
+++ b/test/testsupport/fileutils.cc
@@ -12,11 +12,17 @@
#include <assert.h>
-#ifdef WIN32
+#if defined(WEBRTC_POSIX)
+#include <unistd.h>
+#endif
+
+#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"
@@ -42,35 +48,34 @@
#include <memory>
#include <utility>
+#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 {
-#if defined(WEBRTC_IOS)
-// Defined in iosfileutils.mm. No header file to discourage use elsewhere.
-std::string IOSOutputPath();
-std::string IOSRootPath();
-std::string IOSResourcePath(std::string name, std::string extension);
-#endif
-
namespace {
-#ifdef WIN32
+#if defined(WEBRTC_WIN)
const char* kPathDelimiter = "\\";
#else
const char* kPathDelimiter = "/";
#endif
-#ifdef WEBRTC_ANDROID
-const char* kRootDirName = "/sdcard/chromium_tests_root/";
-#else
-#if !defined(WEBRTC_IOS)
-const char* kOutputDirName = "out";
+#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
-const char* kFallbackPath = "./";
-#endif // !defined(WEBRTC_ANDROID)
#if !defined(WEBRTC_IOS)
const char* kResourcesDirName = "resources";
@@ -83,6 +88,19 @@
const char* kCannotFindProjectRootDir = "ERROR_CANNOT_FIND_PROJECT_ROOT_DIR";
+std::string DirName(const std::string& path) {
+ if (path.empty())
+ return "";
+ if (path == kPathDelimiter)
+ return path;
+
+ std::string result = path;
+ if (result.back() == *kPathDelimiter)
+ result.pop_back(); // Remove trailing separator.
+
+ return result.substr(0, result.find_last_of(kPathDelimiter));
+}
+
void SetExecutablePath(const std::string& path) {
std::string working_dir = WorkingDir();
std::string temp_path = path;
@@ -99,7 +117,7 @@
#endif
// Trim away the executable name; only store the relative dir path.
- temp_path = temp_path.substr(0, temp_path.find_last_of(kPathDelimiter));
+ temp_path = DirName(temp_path);
strncpy(relative_dir_path, temp_path.c_str(), FILENAME_MAX);
relative_dir_path_set = true;
}
@@ -115,78 +133,71 @@
S_ISDIR(directory_info.st_mode);
}
-#ifdef WEBRTC_ANDROID
-
+// Finds the WebRTC src dir.
+// The returned path always ends with a path separator.
std::string ProjectRootPath() {
- return kRootDirName;
-}
-
-std::string OutputPath() {
- return kRootDirName;
-}
-
-std::string WorkingDir() {
- return kRootDirName;
-}
-
-#else // WEBRTC_ANDROID
-
-std::string ProjectRootPath() {
-#if defined(WEBRTC_IOS)
+#if defined(WEBRTC_ANDROID)
+ return kAndroidChromiumTestsRoot;
+#elif defined WEBRTC_IOS
return IOSRootPath();
-#else
- std::string path = WorkingDir();
- if (path == kFallbackPath) {
+#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;
}
- if (relative_dir_path_set) {
- path = path + kPathDelimiter + relative_dir_path;
- }
- path = path + kPathDelimiter + ".." + kPathDelimiter + "..";
- char canonical_path[FILENAME_MAX];
-#ifdef WIN32
- BOOL succeeded = PathCanonicalizeA(canonical_path, path.c_str());
-#else
- bool succeeded = realpath(path.c_str(), canonical_path) != NULL;
-#endif
- if (succeeded) {
- path = std::string(canonical_path) + kPathDelimiter;
- return path;
- } else {
- fprintf(stderr, "Cannot find project root directory!\n");
+ // 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();
- if (path == kCannotFindProjectRootDir) {
- return kFallbackPath;
- }
- path += kOutputDirName;
+ RTC_DCHECK_NE(path, kCannotFindProjectRootDir);
+ path += "out";
if (!CreateDir(path)) {
- return kFallbackPath;
+ 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 kFallbackPath;
+ return "./";
} else {
return std::string(path_buffer);
}
}
-#endif // !WEBRTC_ANDROID
-
// Generate a temporary filename in a safe way.
// Largely copied from talk/base/{unixfilesystem,win32filesystem}.cc.
std::string TempFilename(const std::string& dir, const std::string& prefix) {