364 lines
9.3 KiB
C++
Raw Normal View History

/*
* Copyright (c) 2012 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 "webrtc/test/testsupport/fileutils.h"
#include <assert.h>
#ifdef WIN32
#include <direct.h>
#include <tchar.h>
#include <windows.h>
#include <algorithm>
#include "Shlwapi.h"
#include "WinDef.h"
#include "webrtc/rtc_base/win32.h"
#define GET_CURRENT_DIR _getcwd
#else
#include <dirent.h>
#include <unistd.h>
#define GET_CURRENT_DIR getcwd
#endif
#include <sys/stat.h> // To check for directory existence.
#ifndef S_ISDIR // Not defined in stat.h on Windows.
#define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR)
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <memory>
#include <utility>
#include "webrtc/rtc_base/checks.h"
#include "webrtc/typedefs.h" // For architecture defines
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
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";
#endif
const char* kFallbackPath = "./";
#endif // !defined(WEBRTC_ANDROID)
#if !defined(WEBRTC_IOS)
const char* kResourcesDirName = "resources";
#endif
Improving the way fileutil.h finds test resources. Adding the argv[0] path to the working directory to make it possible find the project root even when the test is executed from outside the project dir (like it is on some buildbots). Removed tests that moves into directories since they no longer work with this approach. The new functionality have been verified by manual tests of the following cases, example with a checkout root dir called webrtc/: Working dir: Command line: webrtc trunk/out/Debug/test webrtc/trunk out/Debug/test webrtc/trunk/out Debug/test webrtc/trunk/out ./Debug/test webrtc/trunk/out/Debug ./test webrtc/trunk/out/Debug/subdir ../test webrtc/trunk/out/Debug/subdir ./../test I also made another program with its own main method (only links with 'test_support', not 'test_support_main') and made sure that it was still possible to use as before (i.e. works within the project tree but not above it): #include "testsupport/fileutils.h" int main(int argc, char** argv) { printf("Working dir: %s\n", webrtc::test::WorkingDir().c_str()); printf("Project root: %s\n", webrtc::test::ProjectRootPath().c_str()); printf("Output path: %s\n", webrtc::test::OutputPath().c_str()); } BUG=Existing implementation cannot handle when the working directory is outside the project checkout. TEST=test_support_unittests and manual tests with video_codecs_test_framework_integration_tests + passing all trybots + memcheck tool Review URL: https://webrtc-codereview.appspot.com/858014 git-svn-id: http://webrtc.googlecode.com/svn/trunk@2927 4adac7df-926f-26a2-2b94-8c16560cd09d
2012-10-15 18:14:12 +00:00
char relative_dir_path[FILENAME_MAX];
bool relative_dir_path_set = false;
} // namespace
const char* kCannotFindProjectRootDir = "ERROR_CANNOT_FIND_PROJECT_ROOT_DIR";
void SetExecutablePath(const std::string& path) {
std::string working_dir = WorkingDir();
std::string temp_path = path;
// Handle absolute paths; convert them to relative paths to the working dir.
if (path.find(working_dir) != std::string::npos) {
temp_path = path.substr(working_dir.length() + 1);
}
// On Windows, when tests are run under memory tools like DrMemory and TSan,
// slashes occur in the path as directory separators. Make sure we replace
// such cases with backslashes in order for the paths to be correct.
#ifdef WIN32
std::replace(temp_path.begin(), temp_path.end(), '/', '\\');
#endif
// Trim away the executable name; only store the relative dir path.
temp_path = temp_path.substr(0, temp_path.find_last_of(kPathDelimiter));
Improving the way fileutil.h finds test resources. Adding the argv[0] path to the working directory to make it possible find the project root even when the test is executed from outside the project dir (like it is on some buildbots). Removed tests that moves into directories since they no longer work with this approach. The new functionality have been verified by manual tests of the following cases, example with a checkout root dir called webrtc/: Working dir: Command line: webrtc trunk/out/Debug/test webrtc/trunk out/Debug/test webrtc/trunk/out Debug/test webrtc/trunk/out ./Debug/test webrtc/trunk/out/Debug ./test webrtc/trunk/out/Debug/subdir ../test webrtc/trunk/out/Debug/subdir ./../test I also made another program with its own main method (only links with 'test_support', not 'test_support_main') and made sure that it was still possible to use as before (i.e. works within the project tree but not above it): #include "testsupport/fileutils.h" int main(int argc, char** argv) { printf("Working dir: %s\n", webrtc::test::WorkingDir().c_str()); printf("Project root: %s\n", webrtc::test::ProjectRootPath().c_str()); printf("Output path: %s\n", webrtc::test::OutputPath().c_str()); } BUG=Existing implementation cannot handle when the working directory is outside the project checkout. TEST=test_support_unittests and manual tests with video_codecs_test_framework_integration_tests + passing all trybots + memcheck tool Review URL: https://webrtc-codereview.appspot.com/858014 git-svn-id: http://webrtc.googlecode.com/svn/trunk@2927 4adac7df-926f-26a2-2b94-8c16560cd09d
2012-10-15 18:14:12 +00:00
strncpy(relative_dir_path, temp_path.c_str(), FILENAME_MAX);
relative_dir_path_set = true;
}
bool FileExists(const std::string& file_name) {
Improving the way fileutil.h finds test resources. Adding the argv[0] path to the working directory to make it possible find the project root even when the test is executed from outside the project dir (like it is on some buildbots). Removed tests that moves into directories since they no longer work with this approach. The new functionality have been verified by manual tests of the following cases, example with a checkout root dir called webrtc/: Working dir: Command line: webrtc trunk/out/Debug/test webrtc/trunk out/Debug/test webrtc/trunk/out Debug/test webrtc/trunk/out ./Debug/test webrtc/trunk/out/Debug ./test webrtc/trunk/out/Debug/subdir ../test webrtc/trunk/out/Debug/subdir ./../test I also made another program with its own main method (only links with 'test_support', not 'test_support_main') and made sure that it was still possible to use as before (i.e. works within the project tree but not above it): #include "testsupport/fileutils.h" int main(int argc, char** argv) { printf("Working dir: %s\n", webrtc::test::WorkingDir().c_str()); printf("Project root: %s\n", webrtc::test::ProjectRootPath().c_str()); printf("Output path: %s\n", webrtc::test::OutputPath().c_str()); } BUG=Existing implementation cannot handle when the working directory is outside the project checkout. TEST=test_support_unittests and manual tests with video_codecs_test_framework_integration_tests + passing all trybots + memcheck tool Review URL: https://webrtc-codereview.appspot.com/858014 git-svn-id: http://webrtc.googlecode.com/svn/trunk@2927 4adac7df-926f-26a2-2b94-8c16560cd09d
2012-10-15 18:14:12 +00:00
struct stat file_info = {0};
return stat(file_name.c_str(), &file_info) == 0;
}
bool DirExists(const std::string& directory_name) {
struct stat directory_info = {0};
return stat(directory_name.c_str(), &directory_info) == 0 && S_ISDIR(
directory_info.st_mode);
}
#ifdef WEBRTC_ANDROID
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)
return IOSRootPath();
#else
Improving the way fileutil.h finds test resources. Adding the argv[0] path to the working directory to make it possible find the project root even when the test is executed from outside the project dir (like it is on some buildbots). Removed tests that moves into directories since they no longer work with this approach. The new functionality have been verified by manual tests of the following cases, example with a checkout root dir called webrtc/: Working dir: Command line: webrtc trunk/out/Debug/test webrtc/trunk out/Debug/test webrtc/trunk/out Debug/test webrtc/trunk/out ./Debug/test webrtc/trunk/out/Debug ./test webrtc/trunk/out/Debug/subdir ../test webrtc/trunk/out/Debug/subdir ./../test I also made another program with its own main method (only links with 'test_support', not 'test_support_main') and made sure that it was still possible to use as before (i.e. works within the project tree but not above it): #include "testsupport/fileutils.h" int main(int argc, char** argv) { printf("Working dir: %s\n", webrtc::test::WorkingDir().c_str()); printf("Project root: %s\n", webrtc::test::ProjectRootPath().c_str()); printf("Output path: %s\n", webrtc::test::OutputPath().c_str()); } BUG=Existing implementation cannot handle when the working directory is outside the project checkout. TEST=test_support_unittests and manual tests with video_codecs_test_framework_integration_tests + passing all trybots + memcheck tool Review URL: https://webrtc-codereview.appspot.com/858014 git-svn-id: http://webrtc.googlecode.com/svn/trunk@2927 4adac7df-926f-26a2-2b94-8c16560cd09d
2012-10-15 18:14:12 +00:00
std::string path = WorkingDir();
if (path == kFallbackPath) {
return kCannotFindProjectRootDir;
}
if (relative_dir_path_set) {
Improving the way fileutil.h finds test resources. Adding the argv[0] path to the working directory to make it possible find the project root even when the test is executed from outside the project dir (like it is on some buildbots). Removed tests that moves into directories since they no longer work with this approach. The new functionality have been verified by manual tests of the following cases, example with a checkout root dir called webrtc/: Working dir: Command line: webrtc trunk/out/Debug/test webrtc/trunk out/Debug/test webrtc/trunk/out Debug/test webrtc/trunk/out ./Debug/test webrtc/trunk/out/Debug ./test webrtc/trunk/out/Debug/subdir ../test webrtc/trunk/out/Debug/subdir ./../test I also made another program with its own main method (only links with 'test_support', not 'test_support_main') and made sure that it was still possible to use as before (i.e. works within the project tree but not above it): #include "testsupport/fileutils.h" int main(int argc, char** argv) { printf("Working dir: %s\n", webrtc::test::WorkingDir().c_str()); printf("Project root: %s\n", webrtc::test::ProjectRootPath().c_str()); printf("Output path: %s\n", webrtc::test::OutputPath().c_str()); } BUG=Existing implementation cannot handle when the working directory is outside the project checkout. TEST=test_support_unittests and manual tests with video_codecs_test_framework_integration_tests + passing all trybots + memcheck tool Review URL: https://webrtc-codereview.appspot.com/858014 git-svn-id: http://webrtc.googlecode.com/svn/trunk@2927 4adac7df-926f-26a2-2b94-8c16560cd09d
2012-10-15 18:14:12 +00:00
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");
return kCannotFindProjectRootDir;
}
#endif
}
std::string OutputPath() {
#if defined(WEBRTC_IOS)
return IOSOutputPath();
#else
std::string path = ProjectRootPath();
if (path == kCannotFindProjectRootDir) {
return kFallbackPath;
}
path += kOutputDirName;
if (!CreateDir(path)) {
return kFallbackPath;
}
return path + kPathDelimiter;
#endif
}
std::string WorkingDir() {
char path_buffer[FILENAME_MAX];
if (!GET_CURRENT_DIR(path_buffer, sizeof(path_buffer))) {
fprintf(stderr, "Cannot get current directory!\n");
return kFallbackPath;
} 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) {
#ifdef WIN32
wchar_t filename[MAX_PATH];
if (::GetTempFileName(rtc::ToUtf16(dir).c_str(),
rtc::ToUtf16(prefix).c_str(), 0, filename) != 0)
return rtc::ToUtf8(filename);
assert(false);
return "";
#else
int len = dir.size() + prefix.size() + 2 + 6;
std::unique_ptr<char[]> tempname(new char[len]);
snprintf(tempname.get(), len, "%s/%sXXXXXX", dir.c_str(),
prefix.c_str());
int fd = ::mkstemp(tempname.get());
if (fd == -1) {
assert(false);
return "";
} else {
::close(fd);
}
std::string ret(tempname.get());
return ret;
#endif
}
rtc::Optional<std::vector<std::string>> ReadDirectory(std::string path) {
if (path.length() == 0)
return rtc::Optional<std::vector<std::string>>();
#if defined(WEBRTC_WIN)
// Append separator character if needed.
if (path.back() != '\\')
path += '\\';
// Init.
WIN32_FIND_DATA data;
HANDLE handle = ::FindFirstFile(rtc::ToUtf16(path + '*').c_str(), &data);
if (handle == INVALID_HANDLE_VALUE)
return rtc::Optional<std::vector<std::string>>();
// Populate output.
std::vector<std::string> found_entries;
do {
const std::string name = rtc::ToUtf8(data.cFileName);
if (name != "." && name != "..")
found_entries.emplace_back(path + name);
} while (::FindNextFile(handle, &data) == TRUE);
// Release resources.
if (handle != INVALID_HANDLE_VALUE)
::FindClose(handle);
#else
// Append separator character if needed.
if (path.back() != '/')
path += '/';
// Init.
DIR* dir = ::opendir(path.c_str());
if (dir == nullptr)
return rtc::Optional<std::vector<std::string>>();
// Populate output.
std::vector<std::string> found_entries;
while (dirent* dirent = readdir(dir)) {
const std::string& name = dirent->d_name;
if (name != "." && name != "..")
found_entries.emplace_back(path + name);
}
// Release resources.
closedir(dir);
#endif
return rtc::Optional<std::vector<std::string>>(std::move(found_entries));
}
bool CreateDir(const std::string& directory_name) {
struct stat path_info = {0};
// Check if the path exists already:
if (stat(directory_name.c_str(), &path_info) == 0) {
if (!S_ISDIR(path_info.st_mode)) {
fprintf(stderr, "Path %s exists but is not a directory! Remove this "
"file and re-run to create the directory.\n",
directory_name.c_str());
return false;
}
} else {
#ifdef WIN32
return _mkdir(directory_name.c_str()) == 0;
#else
return mkdir(directory_name.c_str(), S_IRWXU | S_IRWXG | S_IRWXO) == 0;
#endif
}
return true;
}
Reland of reduce dependencies on rtc::FileSystem in FileRotatingStream tests... (patchset #1 id:1 of https://codereview.webrtc.org/2885393002/ ) Reason for revert: Downstream project now fixed. Original issue's description: > Revert of Reduce dependencies on rtc::FileSystem in FileRotatingStream tests, adding helpers in webrtc::test:: (patchset #7 id:120001 of https://codereview.webrtc.org/2872283002/ ) > > Reason for revert: > Fails to compile successfully. > > > Original issue's description: > > Reduce dependencies on rtc::FileSystem in FileRotatingStream tests. > > > > Use webrtc::test::OutputPath instead of Filesystem::GetAppTempFolder. > > Added functions RemoveFile and RemoveDir in the webrtc::test namespace, > > to replace use of Filesystem::DeleteFolderAndContents. > > > > This makes Filesystem::DeleteFolderAndContents unused, to be deleted > > together with related code in a followup cl. > > > > BUG=webrtc:7345 > > > > Review-Url: https://codereview.webrtc.org/2872283002 > > Cr-Commit-Position: refs/heads/master@{#18173} > > Committed: https://chromium.googlesource.com/external/webrtc/+/dd7b5f32b59d9def668b9e9487589a572f20f6e0 > > TBR=pthatcher@webrtc.org,kjellander@webrtc.org,tommi@webrtc.org,nisse@webrtc.org > # Skipping CQ checks because original CL landed less than 1 days ago. > NOPRESUBMIT=true > NOTREECHECKS=true > NOTRY=true > BUG=webrtc:7345 > > Review-Url: https://codereview.webrtc.org/2885393002 > Cr-Commit-Position: refs/heads/master@{#18180} > Committed: https://chromium.googlesource.com/external/webrtc/+/deaa33d2f59783e849ddc01428be807d92431983 TBR=pthatcher@webrtc.org,kjellander@webrtc.org,tommi@webrtc.org,ehmaldonado@webrtc.org # Not skipping CQ checks because original CL landed more than 1 days ago. BUG=webrtc:7345 Review-Url: https://codereview.webrtc.org/2885413002 Cr-Commit-Position: refs/heads/master@{#18193}
2017-05-18 03:55:59 -07:00
bool RemoveDir(const std::string& directory_name) {
#ifdef WIN32
return RemoveDirectoryA(directory_name.c_str()) != FALSE;
#else
return rmdir(directory_name.c_str()) == 0;
#endif
}
bool RemoveFile(const std::string& file_name) {
#ifdef WIN32
return DeleteFileA(file_name.c_str()) != FALSE;
#else
return unlink(file_name.c_str()) == 0;
#endif
}
std::string ResourcePath(const std::string& name,
const std::string& extension) {
#if defined(WEBRTC_IOS)
return IOSResourcePath(name, extension);
#else
std::string platform = "win";
#ifdef WEBRTC_LINUX
platform = "linux";
#endif // WEBRTC_LINUX
#ifdef WEBRTC_MAC
platform = "mac";
#endif // WEBRTC_MAC
#ifdef WEBRTC_ANDROID
platform = "android";
#endif // WEBRTC_ANDROID
#ifdef WEBRTC_ARCH_64_BITS
std::string architecture = "64";
#else
std::string architecture = "32";
#endif // WEBRTC_ARCH_64_BITS
std::string resources_path = ProjectRootPath() + kResourcesDirName +
kPathDelimiter;
std::string resource_file = resources_path + name + "_" + platform + "_" +
architecture + "." + extension;
if (FileExists(resource_file)) {
return resource_file;
}
// Try without architecture.
resource_file = resources_path + name + "_" + platform + "." + extension;
if (FileExists(resource_file)) {
return resource_file;
}
// Try without platform.
resource_file = resources_path + name + "_" + architecture + "." + extension;
if (FileExists(resource_file)) {
return resource_file;
}
// Fall back on name without architecture or platform.
return resources_path + name + "." + extension;
#endif // defined (WEBRTC_IOS)
}
size_t GetFileSize(const std::string& filename) {
FILE* f = fopen(filename.c_str(), "rb");
size_t size = 0;
if (f != NULL) {
if (fseek(f, 0, SEEK_END) == 0) {
size = ftell(f);
}
fclose(f);
}
return size;
}
} // namespace test
} // namespace webrtc