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}
This commit is contained in:
parent
0a5792e907
commit
8434aeb3a7
@ -359,9 +359,10 @@ if (rtc_include_tests) {
|
||||
}
|
||||
|
||||
if (is_ios) {
|
||||
rtc_source_set("fileutils_objc") {
|
||||
rtc_source_set("fileutils_ios_objc") {
|
||||
visibility = [ ":fileutils" ]
|
||||
sources = [
|
||||
"testsupport/iosfileutils.h",
|
||||
"testsupport/iosfileutils.mm",
|
||||
]
|
||||
deps = [
|
||||
@ -373,6 +374,19 @@ if (is_ios) {
|
||||
}
|
||||
}
|
||||
|
||||
if (is_mac) {
|
||||
rtc_source_set("fileutils_mac_objc") {
|
||||
visibility = [ ":fileutils" ]
|
||||
sources = [
|
||||
"testsupport/macfileutils.h",
|
||||
"testsupport/macfileutils.mm",
|
||||
]
|
||||
deps = [
|
||||
"../rtc_base:checks",
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
rtc_source_set("fileutils") {
|
||||
testonly = true
|
||||
visibility = [ "*" ]
|
||||
@ -388,7 +402,10 @@ rtc_source_set("fileutils") {
|
||||
"//third_party/abseil-cpp/absl/types:optional",
|
||||
]
|
||||
if (is_ios) {
|
||||
deps += [ ":fileutils_objc" ]
|
||||
deps += [ ":fileutils_ios_objc" ]
|
||||
}
|
||||
if (is_mac) {
|
||||
deps += [ ":fileutils_mac_objc" ]
|
||||
}
|
||||
if (is_win) {
|
||||
deps += [ "../rtc_base:rtc_base" ]
|
||||
|
||||
@ -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 @@ bool relative_dir_path_set = false;
|
||||
|
||||
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 @@ void SetExecutablePath(const std::string& path) {
|
||||
#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 @@ bool DirExists(const std::string& directory_name) {
|
||||
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) {
|
||||
|
||||
@ -25,11 +25,14 @@ namespace test {
|
||||
// to find the project root.
|
||||
extern const char* kCannotFindProjectRootDir;
|
||||
|
||||
// Creates and 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 top-level of the project, i.e. a subfolder to
|
||||
// the path returned by ProjectRootPath(). The exception is Android where we use
|
||||
// /sdcard/ instead.
|
||||
// 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.
|
||||
@ -100,6 +103,9 @@ bool FileExists(const std::string& file_name);
|
||||
// Checks if a directory exists.
|
||||
bool DirExists(const std::string& directory_name);
|
||||
|
||||
// Strips the rightmost path segment from a path.
|
||||
std::string DirName(const std::string& path);
|
||||
|
||||
// File size of the supplied file in bytes. Will return 0 if the file is
|
||||
// empty or if the file does not exist/is readable.
|
||||
size_t GetFileSize(const std::string& filename);
|
||||
@ -110,6 +116,7 @@ size_t GetFileSize(const std::string& filename);
|
||||
// the argv[0] being sent into the main function to make it possible for
|
||||
// fileutils.h to find the correct project paths even when the working directory
|
||||
// is outside the project tree (which happens in some cases).
|
||||
// TODO(bugs.webrtc.org/9792): Deprecated - going away soon.
|
||||
void SetExecutablePath(const std::string& path_to_executable);
|
||||
|
||||
} // namespace test
|
||||
|
||||
@ -19,6 +19,7 @@
|
||||
|
||||
#include "absl/types/optional.h"
|
||||
#include "rtc_base/checks.h"
|
||||
#include "test/gmock.h"
|
||||
#include "test/gtest.h"
|
||||
|
||||
#ifdef WIN32
|
||||
@ -28,14 +29,19 @@ static const char* kPathDelimiter = "\\";
|
||||
static const char* kPathDelimiter = "/";
|
||||
#endif
|
||||
|
||||
static const char kTestName[] = "fileutils_unittest";
|
||||
static const char kExtension[] = "tmp";
|
||||
using ::testing::EndsWith;
|
||||
|
||||
namespace webrtc {
|
||||
namespace test {
|
||||
|
||||
namespace {
|
||||
|
||||
std::string Path(const std::string& path) {
|
||||
std::string result = path;
|
||||
std::replace(result.begin(), result.end(), '/', *kPathDelimiter);
|
||||
return result;
|
||||
}
|
||||
|
||||
// Remove files and directories in a directory non-recursively and writes the
|
||||
// number of deleted items in |num_deleted_entries|.
|
||||
void CleanDir(const std::string& dir, size_t* num_deleted_entries) {
|
||||
@ -86,34 +92,34 @@ class FileUtilsTest : public testing::Test {
|
||||
|
||||
std::string FileUtilsTest::original_working_dir_ = "";
|
||||
|
||||
// Tests that the project output dir path is returned for the default working
|
||||
// directory that is automatically set when the test executable is launched.
|
||||
// The test is not fully testing the implementation, since we cannot be sure
|
||||
// of where the executable was launched from.
|
||||
#if defined(WEBRTC_ANDROID) || defined(WEBRTC_IOS)
|
||||
#define MAYBE_OutputPathFromUnchangedWorkingDir \
|
||||
DISABLED_OutputPathFromUnchangedWorkingDir
|
||||
// The location will vary depending on where the webrtc checkout is on the
|
||||
// system, but it should end as described above and be an absolute path.
|
||||
std::string ExpectedRootDirByPlatform() {
|
||||
#if defined(WEBRTC_ANDROID)
|
||||
return Path("chromium_tests_root/");
|
||||
#elif defined(WEBRTC_IOS)
|
||||
return Path("tmp/");
|
||||
#else
|
||||
#define MAYBE_OutputPathFromUnchangedWorkingDir \
|
||||
OutputPathFromUnchangedWorkingDir
|
||||
return Path("out/");
|
||||
#endif
|
||||
TEST_F(FileUtilsTest, MAYBE_OutputPathFromUnchangedWorkingDir) {
|
||||
std::string path = webrtc::test::OutputPath();
|
||||
std::string expected_end = "out";
|
||||
expected_end = kPathDelimiter + expected_end + kPathDelimiter;
|
||||
ASSERT_EQ(path.length() - expected_end.length(), path.find(expected_end));
|
||||
}
|
||||
|
||||
TEST_F(FileUtilsTest, OutputPathFromUnchangedWorkingDir) {
|
||||
std::string expected_end = ExpectedRootDirByPlatform();
|
||||
std::string result = webrtc::test::OutputPath();
|
||||
|
||||
ASSERT_THAT(result, EndsWith(expected_end));
|
||||
}
|
||||
|
||||
// Tests with current working directory set to a directory higher up in the
|
||||
// directory tree than the project root dir.
|
||||
#if defined(WEBRTC_ANDROID) || defined(WIN32) || defined(WEBRTC_IOS)
|
||||
#define MAYBE_OutputPathFromRootWorkingDir DISABLED_OutputPathFromRootWorkingDir
|
||||
#else
|
||||
#define MAYBE_OutputPathFromRootWorkingDir OutputPathFromRootWorkingDir
|
||||
#endif
|
||||
TEST_F(FileUtilsTest, MAYBE_OutputPathFromRootWorkingDir) {
|
||||
TEST_F(FileUtilsTest, OutputPathFromRootWorkingDir) {
|
||||
ASSERT_EQ(0, chdir(kPathDelimiter));
|
||||
ASSERT_EQ("./", webrtc::test::OutputPath());
|
||||
|
||||
std::string expected_end = ExpectedRootDirByPlatform();
|
||||
std::string result = webrtc::test::OutputPath();
|
||||
|
||||
ASSERT_THAT(result, EndsWith(expected_end));
|
||||
}
|
||||
|
||||
TEST_F(FileUtilsTest, TempFilename) {
|
||||
@ -152,30 +158,37 @@ TEST_F(FileUtilsTest, MAYBE_CreateDir) {
|
||||
}
|
||||
|
||||
TEST_F(FileUtilsTest, WorkingDirReturnsValue) {
|
||||
// Hard to cover all platforms. Just test that it returns something without
|
||||
// crashing:
|
||||
// This will obviously be different depending on where the webrtc checkout is,
|
||||
// so just check something is returned.
|
||||
std::string working_dir = webrtc::test::WorkingDir();
|
||||
ASSERT_GT(working_dir.length(), 0u);
|
||||
}
|
||||
|
||||
// Due to multiple platforms, it is hard to make a complete test for
|
||||
// ResourcePath. Manual testing has been performed by removing files and
|
||||
// verified the result confirms with the specified documentation for the
|
||||
// function.
|
||||
TEST_F(FileUtilsTest, ResourcePathReturnsValue) {
|
||||
std::string resource = webrtc::test::ResourcePath(kTestName, kExtension);
|
||||
ASSERT_GT(resource.find(kTestName), 0u);
|
||||
ASSERT_GT(resource.find(kExtension), 0u);
|
||||
TEST_F(FileUtilsTest, ResourcePathReturnsCorrectPath) {
|
||||
std::string result = webrtc::test::ResourcePath(
|
||||
Path("video_coding/frame-ethernet-ii"), "pcap");
|
||||
#if defined(WEBRTC_IOS)
|
||||
// iOS bundles resources straight into the bundle root.
|
||||
std::string expected_end = Path("/frame-ethernet-ii.pcap");
|
||||
#else
|
||||
// Other platforms: it's a separate dir.
|
||||
std::string expected_end =
|
||||
Path("resources/video_coding/frame-ethernet-ii.pcap");
|
||||
#endif
|
||||
|
||||
ASSERT_THAT(result, EndsWith(expected_end));
|
||||
ASSERT_TRUE(FileExists(result)) << "Expected " << result << " to exist; did "
|
||||
<< "ResourcePath return an incorrect path?";
|
||||
}
|
||||
|
||||
TEST_F(FileUtilsTest, ResourcePathFromRootWorkingDir) {
|
||||
ASSERT_EQ(0, chdir(kPathDelimiter));
|
||||
std::string resource = webrtc::test::ResourcePath(kTestName, kExtension);
|
||||
std::string resource = webrtc::test::ResourcePath("whatever", "ext");
|
||||
#if !defined(WEBRTC_IOS)
|
||||
ASSERT_NE(resource.find("resources"), std::string::npos);
|
||||
#endif
|
||||
ASSERT_GT(resource.find(kTestName), 0u);
|
||||
ASSERT_GT(resource.find(kExtension), 0u);
|
||||
ASSERT_GT(resource.find("whatever"), 0u);
|
||||
ASSERT_GT(resource.find("ext"), 0u);
|
||||
}
|
||||
|
||||
TEST_F(FileUtilsTest, GetFileSizeExistingFile) {
|
||||
@ -220,7 +233,7 @@ TEST_F(FileUtilsTest, WriteReadDeleteFilesAndDirs) {
|
||||
|
||||
// Create an empty temporary directory for this test.
|
||||
const std::string temp_directory =
|
||||
OutputPath() + "TempFileUtilsTestReadDirectory" + kPathDelimiter;
|
||||
OutputPath() + Path("TempFileUtilsTestReadDirectory/");
|
||||
CreateDir(temp_directory);
|
||||
EXPECT_NO_FATAL_FAILURE(CleanDir(temp_directory, &num_deleted_entries));
|
||||
EXPECT_TRUE(DirExists(temp_directory));
|
||||
@ -231,7 +244,7 @@ TEST_F(FileUtilsTest, WriteReadDeleteFilesAndDirs) {
|
||||
EXPECT_TRUE(FileExists(temp_filename));
|
||||
|
||||
// Add an empty directory.
|
||||
const std::string temp_subdir = temp_directory + "subdir" + kPathDelimiter;
|
||||
const std::string temp_subdir = temp_directory + Path("subdir/");
|
||||
EXPECT_TRUE(CreateDir(temp_subdir));
|
||||
EXPECT_TRUE(DirExists(temp_subdir));
|
||||
|
||||
@ -246,5 +259,21 @@ TEST_F(FileUtilsTest, WriteReadDeleteFilesAndDirs) {
|
||||
EXPECT_FALSE(DirExists(temp_directory));
|
||||
}
|
||||
|
||||
TEST_F(FileUtilsTest, DirNameStripsFilename) {
|
||||
EXPECT_EQ(Path("/some/path"), DirName(Path("/some/path/file.txt")));
|
||||
}
|
||||
|
||||
TEST_F(FileUtilsTest, DirNameKeepsStrippingRightmostPathComponent) {
|
||||
EXPECT_EQ(Path("/some"), DirName(DirName(Path("/some/path/file.txt"))));
|
||||
}
|
||||
|
||||
TEST_F(FileUtilsTest, DirNameDoesntCareIfAPathEndsInPathSeparator) {
|
||||
EXPECT_EQ(Path("/some"), DirName(Path("/some/path/")));
|
||||
}
|
||||
|
||||
TEST_F(FileUtilsTest, DirNameStopsAtRoot) {
|
||||
EXPECT_EQ(Path("/"), DirName(Path("/")));
|
||||
}
|
||||
|
||||
} // namespace test
|
||||
} // namespace webrtc
|
||||
|
||||
26
test/testsupport/iosfileutils.h
Normal file
26
test/testsupport/iosfileutils.h
Normal file
@ -0,0 +1,26 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef TEST_TESTSUPPORT_IOSFILEUTILS_H_
|
||||
#define TEST_TESTSUPPORT_IOSFILEUTILS_H_
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace webrtc {
|
||||
namespace test {
|
||||
|
||||
std::string IOSOutputPath();
|
||||
std::string IOSRootPath();
|
||||
std::string IOSResourcePath(std::string name, std::string extension);
|
||||
|
||||
} // namespace test
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // TEST_TESTSUPPORT_IOSFILEUTILS_H_
|
||||
24
test/testsupport/macfileutils.h
Normal file
24
test/testsupport/macfileutils.h
Normal file
@ -0,0 +1,24 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef TEST_TESTSUPPORT_MACFILEUTILS_H_
|
||||
#define TEST_TESTSUPPORT_MACFILEUTILS_H_
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace webrtc {
|
||||
namespace test {
|
||||
|
||||
void GetNSExecutablePath(std::string* path);
|
||||
|
||||
} // namespace test
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // TEST_TESTSUPPORT_MACFILEUTILS_H_
|
||||
43
test/testsupport/macfileutils.mm
Normal file
43
test/testsupport/macfileutils.mm
Normal file
@ -0,0 +1,43 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#include <dlfcn.h>
|
||||
#include <mach-o/dyld.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "rtc_base/checks.h"
|
||||
|
||||
namespace webrtc {
|
||||
namespace test {
|
||||
|
||||
void GetNSExecutablePath(std::string* path) {
|
||||
RTC_DCHECK(path);
|
||||
// Executable path can have relative references ("..") depending on
|
||||
// how the app was launched.
|
||||
uint32_t executable_length = 0;
|
||||
_NSGetExecutablePath(NULL, &executable_length);
|
||||
RTC_DCHECK_GT(executable_length, 1u);
|
||||
char executable_path[PATH_MAX + 1];
|
||||
int rv = _NSGetExecutablePath(executable_path, &executable_length);
|
||||
RTC_DCHECK_EQ(rv, 0);
|
||||
|
||||
char full_path[PATH_MAX];
|
||||
if (realpath(executable_path, full_path) == nullptr) {
|
||||
*path = "";
|
||||
return;
|
||||
}
|
||||
|
||||
*path = full_path;
|
||||
}
|
||||
|
||||
} // namespace test
|
||||
} // namespace webrtc
|
||||
Loading…
x
Reference in New Issue
Block a user