gtest-filepath.cc (googletest-release-1.11.0) | : | gtest-filepath.cc (googletest-release-1.12.0) | ||
---|---|---|---|---|
skipping to change at line 33 | skipping to change at line 33 | |||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | |||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | |||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | |||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | |||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |||
#include "gtest/internal/gtest-filepath.h" | #include "gtest/internal/gtest-filepath.h" | |||
#include <stdlib.h> | #include <stdlib.h> | |||
#include "gtest/internal/gtest-port.h" | ||||
#include "gtest/gtest-message.h" | #include "gtest/gtest-message.h" | |||
#include "gtest/internal/gtest-port.h" | ||||
#if GTEST_OS_WINDOWS_MOBILE | #if GTEST_OS_WINDOWS_MOBILE | |||
# include <windows.h> | #include <windows.h> | |||
#elif GTEST_OS_WINDOWS | #elif GTEST_OS_WINDOWS | |||
# include <direct.h> | #include <direct.h> | |||
# include <io.h> | #include <io.h> | |||
#else | #else | |||
# include <limits.h> | #include <limits.h> | |||
# include <climits> // Some Linux distributions define PATH_MAX here. | ||||
#endif // GTEST_OS_WINDOWS_MOBILE | #include <climits> // Some Linux distributions define PATH_MAX here. | |||
#endif // GTEST_OS_WINDOWS_MOBILE | ||||
#include "gtest/internal/gtest-string.h" | #include "gtest/internal/gtest-string.h" | |||
#if GTEST_OS_WINDOWS | #if GTEST_OS_WINDOWS | |||
# define GTEST_PATH_MAX_ _MAX_PATH | #define GTEST_PATH_MAX_ _MAX_PATH | |||
#elif defined(PATH_MAX) | #elif defined(PATH_MAX) | |||
# define GTEST_PATH_MAX_ PATH_MAX | #define GTEST_PATH_MAX_ PATH_MAX | |||
#elif defined(_XOPEN_PATH_MAX) | #elif defined(_XOPEN_PATH_MAX) | |||
# define GTEST_PATH_MAX_ _XOPEN_PATH_MAX | #define GTEST_PATH_MAX_ _XOPEN_PATH_MAX | |||
#else | #else | |||
# define GTEST_PATH_MAX_ _POSIX_PATH_MAX | #define GTEST_PATH_MAX_ _POSIX_PATH_MAX | |||
#endif // GTEST_OS_WINDOWS | #endif // GTEST_OS_WINDOWS | |||
namespace testing { | namespace testing { | |||
namespace internal { | namespace internal { | |||
#if GTEST_OS_WINDOWS | #if GTEST_OS_WINDOWS | |||
// On Windows, '\\' is the standard path separator, but many tools and the | // On Windows, '\\' is the standard path separator, but many tools and the | |||
// Windows API also accept '/' as an alternate path separator. Unless otherwise | // Windows API also accept '/' as an alternate path separator. Unless otherwise | |||
// noted, a file path can contain either kind of path separators, or a mixture | // noted, a file path can contain either kind of path separators, or a mixture | |||
// of them. | // of them. | |||
const char kPathSeparator = '\\'; | const char kPathSeparator = '\\'; | |||
const char kAlternatePathSeparator = '/'; | const char kAlternatePathSeparator = '/'; | |||
const char kAlternatePathSeparatorString[] = "/"; | const char kAlternatePathSeparatorString[] = "/"; | |||
# if GTEST_OS_WINDOWS_MOBILE | #if GTEST_OS_WINDOWS_MOBILE | |||
// Windows CE doesn't have a current directory. You should not use | // Windows CE doesn't have a current directory. You should not use | |||
// the current directory in tests on Windows CE, but this at least | // the current directory in tests on Windows CE, but this at least | |||
// provides a reasonable fallback. | // provides a reasonable fallback. | |||
const char kCurrentDirectoryString[] = "\\"; | const char kCurrentDirectoryString[] = "\\"; | |||
// Windows CE doesn't define INVALID_FILE_ATTRIBUTES | // Windows CE doesn't define INVALID_FILE_ATTRIBUTES | |||
const DWORD kInvalidFileAttributes = 0xffffffff; | const DWORD kInvalidFileAttributes = 0xffffffff; | |||
# else | #else | |||
const char kCurrentDirectoryString[] = ".\\"; | const char kCurrentDirectoryString[] = ".\\"; | |||
# endif // GTEST_OS_WINDOWS_MOBILE | #endif // GTEST_OS_WINDOWS_MOBILE | |||
#else | #else | |||
const char kPathSeparator = '/'; | const char kPathSeparator = '/'; | |||
const char kCurrentDirectoryString[] = "./"; | const char kCurrentDirectoryString[] = "./"; | |||
#endif // GTEST_OS_WINDOWS | #endif // GTEST_OS_WINDOWS | |||
// Returns whether the given character is a valid path separator. | // Returns whether the given character is a valid path separator. | |||
static bool IsPathSeparator(char c) { | static bool IsPathSeparator(char c) { | |||
#if GTEST_HAS_ALT_PATH_SEP_ | #if GTEST_HAS_ALT_PATH_SEP_ | |||
return (c == kPathSeparator) || (c == kAlternatePathSeparator); | return (c == kPathSeparator) || (c == kAlternatePathSeparator); | |||
#else | #else | |||
skipping to change at line 102 | skipping to change at line 104 | |||
// Returns the current working directory, or "" if unsuccessful. | // Returns the current working directory, or "" if unsuccessful. | |||
FilePath FilePath::GetCurrentDir() { | FilePath FilePath::GetCurrentDir() { | |||
#if GTEST_OS_WINDOWS_MOBILE || GTEST_OS_WINDOWS_PHONE || \ | #if GTEST_OS_WINDOWS_MOBILE || GTEST_OS_WINDOWS_PHONE || \ | |||
GTEST_OS_WINDOWS_RT || GTEST_OS_ESP8266 || GTEST_OS_ESP32 || \ | GTEST_OS_WINDOWS_RT || GTEST_OS_ESP8266 || GTEST_OS_ESP32 || \ | |||
GTEST_OS_XTENSA | GTEST_OS_XTENSA | |||
// These platforms do not have a current directory, so we just return | // These platforms do not have a current directory, so we just return | |||
// something reasonable. | // something reasonable. | |||
return FilePath(kCurrentDirectoryString); | return FilePath(kCurrentDirectoryString); | |||
#elif GTEST_OS_WINDOWS | #elif GTEST_OS_WINDOWS | |||
char cwd[GTEST_PATH_MAX_ + 1] = { '\0' }; | char cwd[GTEST_PATH_MAX_ + 1] = {'\0'}; | |||
return FilePath(_getcwd(cwd, sizeof(cwd)) == nullptr ? "" : cwd); | return FilePath(_getcwd(cwd, sizeof(cwd)) == nullptr ? "" : cwd); | |||
#else | #else | |||
char cwd[GTEST_PATH_MAX_ + 1] = { '\0' }; | char cwd[GTEST_PATH_MAX_ + 1] = {'\0'}; | |||
char* result = getcwd(cwd, sizeof(cwd)); | char* result = getcwd(cwd, sizeof(cwd)); | |||
# if GTEST_OS_NACL | #if GTEST_OS_NACL | |||
// getcwd will likely fail in NaCl due to the sandbox, so return something | // getcwd will likely fail in NaCl due to the sandbox, so return something | |||
// reasonable. The user may have provided a shim implementation for getcwd, | // reasonable. The user may have provided a shim implementation for getcwd, | |||
// however, so fallback only when failure is detected. | // however, so fallback only when failure is detected. | |||
return FilePath(result == nullptr ? kCurrentDirectoryString : cwd); | return FilePath(result == nullptr ? kCurrentDirectoryString : cwd); | |||
# endif // GTEST_OS_NACL | #endif // GTEST_OS_NACL | |||
return FilePath(result == nullptr ? "" : cwd); | return FilePath(result == nullptr ? "" : cwd); | |||
#endif // GTEST_OS_WINDOWS_MOBILE | #endif // GTEST_OS_WINDOWS_MOBILE | |||
} | } | |||
// Returns a copy of the FilePath with the case-insensitive extension removed. | // Returns a copy of the FilePath with the case-insensitive extension removed. | |||
// Example: FilePath("dir/file.exe").RemoveExtension("EXE") returns | // Example: FilePath("dir/file.exe").RemoveExtension("EXE") returns | |||
// FilePath("dir/file"). If a case-insensitive extension is not | // FilePath("dir/file"). If a case-insensitive extension is not | |||
// found, returns a copy of the original FilePath. | // found, returns a copy of the original FilePath. | |||
FilePath FilePath::RemoveExtension(const char* extension) const { | FilePath FilePath::RemoveExtension(const char* extension) const { | |||
const std::string dot_extension = std::string(".") + extension; | const std::string dot_extension = std::string(".") + extension; | |||
if (String::EndsWithCaseInsensitive(pathname_, dot_extension)) { | if (String::EndsWithCaseInsensitive(pathname_, dot_extension)) { | |||
return FilePath(pathname_.substr( | return FilePath( | |||
0, pathname_.length() - dot_extension.length())); | pathname_.substr(0, pathname_.length() - dot_extension.length())); | |||
} | } | |||
return *this; | return *this; | |||
} | } | |||
// Returns a pointer to the last occurrence of a valid path separator in | // Returns a pointer to the last occurrence of a valid path separator in | |||
// the FilePath. On Windows, for example, both '/' and '\' are valid path | // the FilePath. On Windows, for example, both '/' and '\' are valid path | |||
// separators. Returns NULL if no path separator was found. | // separators. Returns NULL if no path separator was found. | |||
const char* FilePath::FindLastPathSeparator() const { | const char* FilePath::FindLastPathSeparator() const { | |||
const char* const last_sep = strrchr(c_str(), kPathSeparator); | const char* const last_sep = strrchr(c_str(), kPathSeparator); | |||
#if GTEST_HAS_ALT_PATH_SEP_ | #if GTEST_HAS_ALT_PATH_SEP_ | |||
skipping to change at line 181 | skipping to change at line 183 | |||
return FilePath(dir); | return FilePath(dir); | |||
} | } | |||
// Helper functions for naming files in a directory for xml output. | // Helper functions for naming files in a directory for xml output. | |||
// Given directory = "dir", base_name = "test", number = 0, | // Given directory = "dir", base_name = "test", number = 0, | |||
// extension = "xml", returns "dir/test.xml". If number is greater | // extension = "xml", returns "dir/test.xml". If number is greater | |||
// than zero (e.g., 12), returns "dir/test_12.xml". | // than zero (e.g., 12), returns "dir/test_12.xml". | |||
// On Windows platform, uses \ as the separator rather than /. | // On Windows platform, uses \ as the separator rather than /. | |||
FilePath FilePath::MakeFileName(const FilePath& directory, | FilePath FilePath::MakeFileName(const FilePath& directory, | |||
const FilePath& base_name, | const FilePath& base_name, int number, | |||
int number, | ||||
const char* extension) { | const char* extension) { | |||
std::string file; | std::string file; | |||
if (number == 0) { | if (number == 0) { | |||
file = base_name.string() + "." + extension; | file = base_name.string() + "." + extension; | |||
} else { | } else { | |||
file = base_name.string() + "_" + StreamableToString(number) | file = | |||
+ "." + extension; | base_name.string() + "_" + StreamableToString(number) + "." + extension; | |||
} | } | |||
return ConcatPaths(directory, FilePath(file)); | return ConcatPaths(directory, FilePath(file)); | |||
} | } | |||
// Given directory = "dir", relative_path = "test.xml", returns "dir/test.xml". | // Given directory = "dir", relative_path = "test.xml", returns "dir/test.xml". | |||
// On Windows, uses \ as the separator rather than /. | // On Windows, uses \ as the separator rather than /. | |||
FilePath FilePath::ConcatPaths(const FilePath& directory, | FilePath FilePath::ConcatPaths(const FilePath& directory, | |||
const FilePath& relative_path) { | const FilePath& relative_path) { | |||
if (directory.IsEmpty()) | if (directory.IsEmpty()) return relative_path; | |||
return relative_path; | ||||
const FilePath dir(directory.RemoveTrailingPathSeparator()); | const FilePath dir(directory.RemoveTrailingPathSeparator()); | |||
return FilePath(dir.string() + kPathSeparator + relative_path.string()); | return FilePath(dir.string() + kPathSeparator + relative_path.string()); | |||
} | } | |||
// Returns true if pathname describes something findable in the file-system, | // Returns true if pathname describes something findable in the file-system, | |||
// either a file, directory, or whatever. | // either a file, directory, or whatever. | |||
bool FilePath::FileOrDirectoryExists() const { | bool FilePath::FileOrDirectoryExists() const { | |||
#if GTEST_OS_WINDOWS_MOBILE | #if GTEST_OS_WINDOWS_MOBILE | |||
LPCWSTR unicode = String::AnsiToUtf16(pathname_.c_str()); | LPCWSTR unicode = String::AnsiToUtf16(pathname_.c_str()); | |||
const DWORD attributes = GetFileAttributes(unicode); | const DWORD attributes = GetFileAttributes(unicode); | |||
delete [] unicode; | delete[] unicode; | |||
return attributes != kInvalidFileAttributes; | return attributes != kInvalidFileAttributes; | |||
#else | #else | |||
posix::StatStruct file_stat{}; | posix::StatStruct file_stat{}; | |||
return posix::Stat(pathname_.c_str(), &file_stat) == 0; | return posix::Stat(pathname_.c_str(), &file_stat) == 0; | |||
#endif // GTEST_OS_WINDOWS_MOBILE | #endif // GTEST_OS_WINDOWS_MOBILE | |||
} | } | |||
// Returns true if pathname describes a directory in the file-system | // Returns true if pathname describes a directory in the file-system | |||
// that exists. | // that exists. | |||
bool FilePath::DirectoryExists() const { | bool FilePath::DirectoryExists() const { | |||
bool result = false; | bool result = false; | |||
#if GTEST_OS_WINDOWS | #if GTEST_OS_WINDOWS | |||
// Don't strip off trailing separator if path is a root directory on | // Don't strip off trailing separator if path is a root directory on | |||
// Windows (like "C:\\"). | // Windows (like "C:\\"). | |||
const FilePath& path(IsRootDirectory() ? *this : | const FilePath& path(IsRootDirectory() ? *this | |||
RemoveTrailingPathSeparator()); | : RemoveTrailingPathSeparator()); | |||
#else | #else | |||
const FilePath& path(*this); | const FilePath& path(*this); | |||
#endif | #endif | |||
#if GTEST_OS_WINDOWS_MOBILE | #if GTEST_OS_WINDOWS_MOBILE | |||
LPCWSTR unicode = String::AnsiToUtf16(path.c_str()); | LPCWSTR unicode = String::AnsiToUtf16(path.c_str()); | |||
const DWORD attributes = GetFileAttributes(unicode); | const DWORD attributes = GetFileAttributes(unicode); | |||
delete [] unicode; | delete[] unicode; | |||
if ((attributes != kInvalidFileAttributes) && | if ((attributes != kInvalidFileAttributes) && | |||
(attributes & FILE_ATTRIBUTE_DIRECTORY)) { | (attributes & FILE_ATTRIBUTE_DIRECTORY)) { | |||
result = true; | result = true; | |||
} | } | |||
#else | #else | |||
posix::StatStruct file_stat{}; | posix::StatStruct file_stat{}; | |||
result = posix::Stat(path.c_str(), &file_stat) == 0 && | result = | |||
posix::IsDir(file_stat); | posix::Stat(path.c_str(), &file_stat) == 0 && posix::IsDir(file_stat); | |||
#endif // GTEST_OS_WINDOWS_MOBILE | #endif // GTEST_OS_WINDOWS_MOBILE | |||
return result; | return result; | |||
} | } | |||
// Returns true if pathname describes a root directory. (Windows has one | // Returns true if pathname describes a root directory. (Windows has one | |||
// root directory per disk drive.) | // root directory per disk drive.) | |||
bool FilePath::IsRootDirectory() const { | bool FilePath::IsRootDirectory() const { | |||
#if GTEST_OS_WINDOWS | #if GTEST_OS_WINDOWS | |||
return pathname_.length() == 3 && IsAbsolutePath(); | return pathname_.length() == 3 && IsAbsolutePath(); | |||
#else | #else | |||
return pathname_.length() == 1 && IsPathSeparator(pathname_.c_str()[0]); | return pathname_.length() == 1 && IsPathSeparator(pathname_.c_str()[0]); | |||
#endif | #endif | |||
} | } | |||
// Returns true if pathname describes an absolute path. | // Returns true if pathname describes an absolute path. | |||
bool FilePath::IsAbsolutePath() const { | bool FilePath::IsAbsolutePath() const { | |||
const char* const name = pathname_.c_str(); | const char* const name = pathname_.c_str(); | |||
#if GTEST_OS_WINDOWS | #if GTEST_OS_WINDOWS | |||
return pathname_.length() >= 3 && | return pathname_.length() >= 3 && | |||
((name[0] >= 'a' && name[0] <= 'z') || | ((name[0] >= 'a' && name[0] <= 'z') || | |||
(name[0] >= 'A' && name[0] <= 'Z')) && | (name[0] >= 'A' && name[0] <= 'Z')) && | |||
name[1] == ':' && | name[1] == ':' && IsPathSeparator(name[2]); | |||
IsPathSeparator(name[2]); | ||||
#else | #else | |||
return IsPathSeparator(name[0]); | return IsPathSeparator(name[0]); | |||
#endif | #endif | |||
} | } | |||
// Returns a pathname for a file that does not currently exist. The pathname | // Returns a pathname for a file that does not currently exist. The pathname | |||
// will be directory/base_name.extension or | // will be directory/base_name.extension or | |||
// directory/base_name_<number>.extension if directory/base_name.extension | // directory/base_name_<number>.extension if directory/base_name.extension | |||
// already exists. The number will be incremented until a pathname is found | // already exists. The number will be incremented until a pathname is found | |||
// that does not already exist. | // that does not already exist. | |||
skipping to change at line 324 | skipping to change at line 323 | |||
// Create the directory so that path exists. Returns true if successful or | // Create the directory so that path exists. Returns true if successful or | |||
// if the directory already exists; returns false if unable to create the | // if the directory already exists; returns false if unable to create the | |||
// directory for any reason, including if the parent directory does not | // directory for any reason, including if the parent directory does not | |||
// exist. Not named "CreateDirectory" because that's a macro on Windows. | // exist. Not named "CreateDirectory" because that's a macro on Windows. | |||
bool FilePath::CreateFolder() const { | bool FilePath::CreateFolder() const { | |||
#if GTEST_OS_WINDOWS_MOBILE | #if GTEST_OS_WINDOWS_MOBILE | |||
FilePath removed_sep(this->RemoveTrailingPathSeparator()); | FilePath removed_sep(this->RemoveTrailingPathSeparator()); | |||
LPCWSTR unicode = String::AnsiToUtf16(removed_sep.c_str()); | LPCWSTR unicode = String::AnsiToUtf16(removed_sep.c_str()); | |||
int result = CreateDirectory(unicode, nullptr) ? 0 : -1; | int result = CreateDirectory(unicode, nullptr) ? 0 : -1; | |||
delete [] unicode; | delete[] unicode; | |||
#elif GTEST_OS_WINDOWS | #elif GTEST_OS_WINDOWS | |||
int result = _mkdir(pathname_.c_str()); | int result = _mkdir(pathname_.c_str()); | |||
#elif GTEST_OS_ESP8266 || GTEST_OS_XTENSA | #elif GTEST_OS_ESP8266 || GTEST_OS_XTENSA | |||
// do nothing | // do nothing | |||
int result = 0; | int result = 0; | |||
#else | #else | |||
int result = mkdir(pathname_.c_str(), 0777); | int result = mkdir(pathname_.c_str(), 0777); | |||
#endif // GTEST_OS_WINDOWS_MOBILE | #endif // GTEST_OS_WINDOWS_MOBILE | |||
if (result == -1) { | if (result == -1) { | |||
return this->DirectoryExists(); // An error is OK if the directory exists. | return this->DirectoryExists(); // An error is OK if the directory exists. | |||
} | } | |||
return true; // No error. | return true; // No error. | |||
} | } | |||
// If input name has a trailing separator character, remove it and return the | // If input name has a trailing separator character, remove it and return the | |||
// name, otherwise return the name string unmodified. | // name, otherwise return the name string unmodified. | |||
// On Windows platform, uses \ as the separator, other platforms use /. | // On Windows platform, uses \ as the separator, other platforms use /. | |||
FilePath FilePath::RemoveTrailingPathSeparator() const { | FilePath FilePath::RemoveTrailingPathSeparator() const { | |||
return IsDirectory() | return IsDirectory() ? FilePath(pathname_.substr(0, pathname_.length() - 1)) | |||
? FilePath(pathname_.substr(0, pathname_.length() - 1)) | : *this; | |||
: *this; | ||||
} | } | |||
// Removes any redundant separators that might be in the pathname. | // Removes any redundant separators that might be in the pathname. | |||
// For example, "bar///foo" becomes "bar/foo". Does not eliminate other | // For example, "bar///foo" becomes "bar/foo". Does not eliminate other | |||
// redundancies that might be in a pathname involving "." or "..". | // redundancies that might be in a pathname involving "." or "..". | |||
void FilePath::Normalize() { | void FilePath::Normalize() { | |||
auto out = pathname_.begin(); | auto out = pathname_.begin(); | |||
for (const char character : pathname_) { | for (const char character : pathname_) { | |||
if (!IsPathSeparator(character)) { | if (!IsPathSeparator(character)) { | |||
End of changes. 27 change blocks. | ||||
40 lines changed or deleted | 38 lines changed or added |