24 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
24 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
25 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
25 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
26 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
26 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
27 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
27 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
28 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
28 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
29 // |
29 |
30 // Authors: keith.ray@gmail.com (Keith Ray) |
30 #include "gtest/internal/gtest-filepath.h" |
31 |
31 |
|
32 #include <stdlib.h> |
|
33 #include "gtest/internal/gtest-port.h" |
32 #include "gtest/gtest-message.h" |
34 #include "gtest/gtest-message.h" |
33 #include "gtest/internal/gtest-filepath.h" |
|
34 #include "gtest/internal/gtest-port.h" |
|
35 |
|
36 #include <stdlib.h> |
|
37 |
35 |
38 #if GTEST_OS_WINDOWS_MOBILE |
36 #if GTEST_OS_WINDOWS_MOBILE |
39 # include <windows.h> |
37 # include <windows.h> |
40 #elif GTEST_OS_WINDOWS |
38 #elif GTEST_OS_WINDOWS |
41 # include <direct.h> |
39 # include <direct.h> |
46 #else |
44 #else |
47 # include <limits.h> |
45 # include <limits.h> |
48 # include <climits> // Some Linux distributions define PATH_MAX here. |
46 # include <climits> // Some Linux distributions define PATH_MAX here. |
49 #endif // GTEST_OS_WINDOWS_MOBILE |
47 #endif // GTEST_OS_WINDOWS_MOBILE |
50 |
48 |
|
49 #include "gtest/internal/gtest-string.h" |
|
50 |
51 #if GTEST_OS_WINDOWS |
51 #if GTEST_OS_WINDOWS |
52 # define GTEST_PATH_MAX_ _MAX_PATH |
52 # define GTEST_PATH_MAX_ _MAX_PATH |
53 #elif defined(PATH_MAX) |
53 #elif defined(PATH_MAX) |
54 # define GTEST_PATH_MAX_ PATH_MAX |
54 # define GTEST_PATH_MAX_ PATH_MAX |
55 #elif defined(_XOPEN_PATH_MAX) |
55 #elif defined(_XOPEN_PATH_MAX) |
56 # define GTEST_PATH_MAX_ _XOPEN_PATH_MAX |
56 # define GTEST_PATH_MAX_ _XOPEN_PATH_MAX |
57 #else |
57 #else |
58 # define GTEST_PATH_MAX_ _POSIX_PATH_MAX |
58 # define GTEST_PATH_MAX_ _POSIX_PATH_MAX |
59 #endif // GTEST_OS_WINDOWS |
59 #endif // GTEST_OS_WINDOWS |
60 |
|
61 #include "gtest/internal/gtest-string.h" |
|
62 |
60 |
63 namespace testing { |
61 namespace testing { |
64 namespace internal { |
62 namespace internal { |
65 |
63 |
66 #if GTEST_OS_WINDOWS |
64 #if GTEST_OS_WINDOWS |
68 // Windows API also accept '/' as an alternate path separator. Unless otherwise |
66 // Windows API also accept '/' as an alternate path separator. Unless otherwise |
69 // noted, a file path can contain either kind of path separators, or a mixture |
67 // noted, a file path can contain either kind of path separators, or a mixture |
70 // of them. |
68 // of them. |
71 const char kPathSeparator = '\\'; |
69 const char kPathSeparator = '\\'; |
72 const char kAlternatePathSeparator = '/'; |
70 const char kAlternatePathSeparator = '/'; |
73 const char kPathSeparatorString[] = "\\"; |
|
74 const char kAlternatePathSeparatorString[] = "/"; |
71 const char kAlternatePathSeparatorString[] = "/"; |
75 # if GTEST_OS_WINDOWS_MOBILE |
72 # if GTEST_OS_WINDOWS_MOBILE |
76 // Windows CE doesn't have a current directory. You should not use |
73 // Windows CE doesn't have a current directory. You should not use |
77 // the current directory in tests on Windows CE, but this at least |
74 // the current directory in tests on Windows CE, but this at least |
78 // provides a reasonable fallback. |
75 // provides a reasonable fallback. |
82 # else |
79 # else |
83 const char kCurrentDirectoryString[] = ".\\"; |
80 const char kCurrentDirectoryString[] = ".\\"; |
84 # endif // GTEST_OS_WINDOWS_MOBILE |
81 # endif // GTEST_OS_WINDOWS_MOBILE |
85 #else |
82 #else |
86 const char kPathSeparator = '/'; |
83 const char kPathSeparator = '/'; |
87 const char kPathSeparatorString[] = "/"; |
|
88 const char kCurrentDirectoryString[] = "./"; |
84 const char kCurrentDirectoryString[] = "./"; |
89 #endif // GTEST_OS_WINDOWS |
85 #endif // GTEST_OS_WINDOWS |
90 |
86 |
91 // Returns whether the given character is a valid path separator. |
87 // Returns whether the given character is a valid path separator. |
92 static bool IsPathSeparator(char c) { |
88 static bool IsPathSeparator(char c) { |
97 #endif |
93 #endif |
98 } |
94 } |
99 |
95 |
100 // Returns the current working directory, or "" if unsuccessful. |
96 // Returns the current working directory, or "" if unsuccessful. |
101 FilePath FilePath::GetCurrentDir() { |
97 FilePath FilePath::GetCurrentDir() { |
102 #if GTEST_OS_WINDOWS_MOBILE |
98 #if GTEST_OS_WINDOWS_MOBILE || GTEST_OS_WINDOWS_PHONE || GTEST_OS_WINDOWS_RT |
103 // Windows CE doesn't have a current directory, so we just return |
99 // Windows CE doesn't have a current directory, so we just return |
104 // something reasonable. |
100 // something reasonable. |
105 return FilePath(kCurrentDirectoryString); |
101 return FilePath(kCurrentDirectoryString); |
106 #elif GTEST_OS_WINDOWS |
102 #elif GTEST_OS_WINDOWS |
107 char cwd[GTEST_PATH_MAX_ + 1] = { '\0' }; |
103 char cwd[GTEST_PATH_MAX_ + 1] = { '\0' }; |
108 return FilePath(_getcwd(cwd, sizeof(cwd)) == NULL ? "" : cwd); |
104 return FilePath(_getcwd(cwd, sizeof(cwd)) == NULL ? "" : cwd); |
109 #else |
105 #else |
110 char cwd[GTEST_PATH_MAX_ + 1] = { '\0' }; |
106 char cwd[GTEST_PATH_MAX_ + 1] = { '\0' }; |
111 return FilePath(getcwd(cwd, sizeof(cwd)) == NULL ? "" : cwd); |
107 char* result = getcwd(cwd, sizeof(cwd)); |
|
108 # if GTEST_OS_NACL |
|
109 // getcwd will likely fail in NaCl due to the sandbox, so return something |
|
110 // reasonable. The user may have provided a shim implementation for getcwd, |
|
111 // however, so fallback only when failure is detected. |
|
112 return FilePath(result == NULL ? kCurrentDirectoryString : cwd); |
|
113 # endif // GTEST_OS_NACL |
|
114 return FilePath(result == NULL ? "" : cwd); |
112 #endif // GTEST_OS_WINDOWS_MOBILE |
115 #endif // GTEST_OS_WINDOWS_MOBILE |
113 } |
116 } |
114 |
117 |
115 // Returns a copy of the FilePath with the case-insensitive extension removed. |
118 // Returns a copy of the FilePath with the case-insensitive extension removed. |
116 // Example: FilePath("dir/file.exe").RemoveExtension("EXE") returns |
119 // Example: FilePath("dir/file.exe").RemoveExtension("EXE") returns |
123 0, pathname_.length() - dot_extension.length())); |
126 0, pathname_.length() - dot_extension.length())); |
124 } |
127 } |
125 return *this; |
128 return *this; |
126 } |
129 } |
127 |
130 |
128 // Returns a pointer to the last occurence of a valid path separator in |
131 // Returns a pointer to the last occurrence of a valid path separator in |
129 // the FilePath. On Windows, for example, both '/' and '\' are valid path |
132 // the FilePath. On Windows, for example, both '/' and '\' are valid path |
130 // separators. Returns NULL if no path separator was found. |
133 // separators. Returns NULL if no path separator was found. |
131 const char* FilePath::FindLastPathSeparator() const { |
134 const char* FilePath::FindLastPathSeparator() const { |
132 const char* const last_sep = strrchr(c_str(), kPathSeparator); |
135 const char* const last_sep = strrchr(c_str(), kPathSeparator); |
133 #if GTEST_HAS_ALT_PATH_SEP_ |
136 #if GTEST_HAS_ALT_PATH_SEP_ |
245 |
248 |
246 // Returns true if pathname describes a root directory. (Windows has one |
249 // Returns true if pathname describes a root directory. (Windows has one |
247 // root directory per disk drive.) |
250 // root directory per disk drive.) |
248 bool FilePath::IsRootDirectory() const { |
251 bool FilePath::IsRootDirectory() const { |
249 #if GTEST_OS_WINDOWS |
252 #if GTEST_OS_WINDOWS |
250 // TODO(wan@google.com): on Windows a network share like |
253 // FIXME: on Windows a network share like |
251 // \\server\share can be a root directory, although it cannot be the |
254 // \\server\share can be a root directory, although it cannot be the |
252 // current directory. Handle this properly. |
255 // current directory. Handle this properly. |
253 return pathname_.length() == 3 && IsAbsolutePath(); |
256 return pathname_.length() == 3 && IsAbsolutePath(); |
254 #else |
257 #else |
255 return pathname_.length() == 1 && IsPathSeparator(pathname_.c_str()[0]); |
258 return pathname_.length() == 1 && IsPathSeparator(pathname_.c_str()[0]); |
345 } |
348 } |
346 |
349 |
347 // Removes any redundant separators that might be in the pathname. |
350 // Removes any redundant separators that might be in the pathname. |
348 // For example, "bar///foo" becomes "bar/foo". Does not eliminate other |
351 // For example, "bar///foo" becomes "bar/foo". Does not eliminate other |
349 // redundancies that might be in a pathname involving "." or "..". |
352 // redundancies that might be in a pathname involving "." or "..". |
350 // TODO(wan@google.com): handle Windows network shares (e.g. \\server\share). |
353 // FIXME: handle Windows network shares (e.g. \\server\share). |
351 void FilePath::Normalize() { |
354 void FilePath::Normalize() { |
352 if (pathname_.c_str() == NULL) { |
355 if (pathname_.c_str() == NULL) { |
353 pathname_ = ""; |
356 pathname_ = ""; |
354 return; |
357 return; |
355 } |
358 } |