1 /*
2 * Copyright (c) 2018 The WebRTC project authors. All Rights Reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
11 #include "test/testsupport/file_utils_override.h"
12
13 #include <limits.h>
14 #include <stdio.h>
15
16 #if defined(WEBRTC_WIN)
17 #include <direct.h>
18 #include <tchar.h>
19 #include <windows.h>
20
21 #include <algorithm>
22 #include <codecvt>
23 #include <locale>
24
25 #include "Shlwapi.h"
26 #include "WinDef.h"
27 #include "rtc_base/win32.h"
28
29 #define GET_CURRENT_DIR _getcwd
30 #else
31 #include <unistd.h>
32
33 #define GET_CURRENT_DIR getcwd
34 #endif
35
36 #if defined(WEBRTC_IOS)
37 #include "test/testsupport/ios_file_utils.h"
38 #endif
39
40 #if defined(WEBRTC_MAC)
41 #include "test/testsupport/mac_file_utils.h"
42 #endif
43
44 #include "absl/strings/string_view.h"
45 #include "absl/types/optional.h"
46 #include "rtc_base/arraysize.h"
47 #include "rtc_base/checks.h"
48 #include "rtc_base/string_utils.h"
49 #include "rtc_base/strings/string_builder.h"
50
51 namespace webrtc {
52 namespace test {
53
54 std::string DirName(absl::string_view path);
55 bool CreateDir(absl::string_view directory_name);
56
57 namespace internal {
58
59 namespace {
60 #if defined(WEBRTC_WIN)
61 const absl::string_view kPathDelimiter = "\\";
62 #elif !defined(WEBRTC_IOS)
63 const absl::string_view kPathDelimiter = "/";
64 #endif
65
66 #if defined(WEBRTC_ANDROID)
67 // This is a special case in Chrome infrastructure. See
68 // base/test/test_support_android.cc.
69 const absl::string_view kAndroidChromiumTestsRoot =
70 "/sdcard/chromium_tests_root/";
71 #endif
72 #if defined(WEBRTC_FUCHSIA)
73 const absl::string_view kFuchsiaTestRoot = "/pkg/";
74 const absl::string_view kFuchsiaTempWritableDir = "/tmp/";
75 #endif
76 #if !defined(WEBRTC_IOS)
77 const absl::string_view kResourcesDirName = "resources";
78 #endif
79
80 } // namespace
81
82 // Finds the WebRTC src dir.
83 // The returned path always ends with a path separator.
ProjectRootPath()84 absl::optional<std::string> ProjectRootPath() {
85 #if defined(WEBRTC_ANDROID)
86 return std::string(kAndroidChromiumTestsRoot);
87 #elif defined WEBRTC_IOS
88 return IOSRootPath();
89 #elif defined(WEBRTC_MAC)
90 std::string path;
91 GetNSExecutablePath(&path);
92 std::string exe_dir = DirName(path);
93 // On Mac, tests execute in out/Whatever, so src is two levels up except if
94 // the test is bundled (which our tests are not), in which case it's 5 levels.
95 return DirName(DirName(exe_dir)) + std::string(kPathDelimiter);
96 #elif defined(WEBRTC_POSIX)
97 // Fuchsia uses POSIX defines as well but does not have full POSIX
98 // functionality.
99 #if defined(WEBRTC_FUCHSIA)
100 return std::string(kFuchsiaTestRoot);
101 #else
102 char buf[PATH_MAX];
103 ssize_t count = ::readlink("/proc/self/exe", buf, arraysize(buf));
104 if (count <= 0) {
105 RTC_DCHECK_NOTREACHED() << "Unable to resolve /proc/self/exe.";
106 return absl::nullopt;
107 }
108 // On POSIX, tests execute in out/Whatever, so src is two levels up.
109 std::string exe_dir = DirName(absl::string_view(buf, count));
110 return DirName(DirName(exe_dir)) + std::string(kPathDelimiter);
111 #endif
112 #elif defined(WEBRTC_WIN)
113 wchar_t buf[MAX_PATH];
114 buf[0] = 0;
115 if (GetModuleFileNameW(NULL, buf, MAX_PATH) == 0)
116 return absl::nullopt;
117
118 std::string exe_path = rtc::ToUtf8(std::wstring(buf));
119 std::string exe_dir = DirName(exe_path);
120 return DirName(DirName(exe_dir)) + std::string(kPathDelimiter);
121 #endif
122 }
123
OutputPath()124 std::string OutputPath() {
125 #if defined(WEBRTC_IOS)
126 return IOSOutputPath();
127 #elif defined(WEBRTC_ANDROID)
128 return std::string(kAndroidChromiumTestsRoot);
129 #elif defined(WEBRTC_FUCHSIA)
130 return std::string(kFuchsiaTempWritableDir);
131 #else
132 absl::optional<std::string> path_opt = ProjectRootPath();
133 RTC_DCHECK(path_opt);
134 std::string path = *path_opt + "out";
135 if (!CreateDir(path)) {
136 return "./";
137 }
138 return path + std::string(kPathDelimiter);
139 #endif
140 }
141
WorkingDir()142 std::string WorkingDir() {
143 #if defined(WEBRTC_ANDROID)
144 return std::string(kAndroidChromiumTestsRoot);
145 #else
146 char path_buffer[FILENAME_MAX];
147 if (!GET_CURRENT_DIR(path_buffer, sizeof(path_buffer))) {
148 fprintf(stderr, "Cannot get current directory!\n");
149 return "./";
150 } else {
151 return std::string(path_buffer);
152 }
153 #endif
154 }
155
ResourcePath(absl::string_view name,absl::string_view extension)156 std::string ResourcePath(absl::string_view name, absl::string_view extension) {
157 #if defined(WEBRTC_IOS)
158 return IOSResourcePath(name, extension);
159 #else
160 absl::optional<std::string> path_opt = ProjectRootPath();
161 RTC_DCHECK(path_opt);
162 rtc::StringBuilder os(*path_opt);
163 os << kResourcesDirName << kPathDelimiter << name << "." << extension;
164 return os.Release();
165 #endif
166 }
167
168 } // namespace internal
169 } // namespace test
170 } // namespace webrtc
171