blob: 9d04ab0238ae97c4eb64f684642afd728a905e8b [file] [log] [blame]
kjellander@webrtc.org7951e812011-10-13 12:24:41 +00001/*
andrew@webrtc.org7a281a52012-06-27 03:22:37 +00002 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
kjellander@webrtc.org7951e812011-10-13 12:24:41 +00003 *
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
pbos@webrtc.org34741c82013-05-27 08:02:22 +000011#include "webrtc/test/testsupport/fileutils.h"
kjellander@webrtc.org7951e812011-10-13 12:24:41 +000012
13#ifdef WIN32
kjellander@webrtc.org7de47bc2014-04-16 08:04:26 +000014#include <assert.h>
kjellander@webrtc.org7951e812011-10-13 12:24:41 +000015#include <direct.h>
kjellander@webrtc.org7de47bc2014-04-16 08:04:26 +000016#include <tchar.h>
17#include <windows.h>
kjellander@webrtc.orgde499662013-08-29 11:26:41 +000018#include <algorithm>
kjellander@webrtc.org7de47bc2014-04-16 08:04:26 +000019
20#include "webrtc/system_wrappers/interface/utf_util_win.h"
kjellander@webrtc.org7951e812011-10-13 12:24:41 +000021#define GET_CURRENT_DIR _getcwd
kjellander@webrtc.org7951e812011-10-13 12:24:41 +000022#else
23#include <unistd.h>
kjellander@webrtc.org7de47bc2014-04-16 08:04:26 +000024
25#include "webrtc/system_wrappers/interface/scoped_ptr.h"
kjellander@webrtc.org7951e812011-10-13 12:24:41 +000026#define GET_CURRENT_DIR getcwd
kjellander@webrtc.org4d8cd9d2011-11-09 11:24:14 +000027#endif
28
29#include <sys/stat.h> // To check for directory existence.
30#ifndef S_ISDIR // Not defined in stat.h on Windows.
31#define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR)
kjellander@webrtc.org7951e812011-10-13 12:24:41 +000032#endif
33
pbos@webrtc.org12dc1a32013-08-05 16:22:53 +000034#include <stdio.h>
kjellander@webrtc.org7de47bc2014-04-16 08:04:26 +000035#include <stdlib.h>
pbos@webrtc.org12dc1a32013-08-05 16:22:53 +000036#include <string.h>
kjellander@webrtc.org7951e812011-10-13 12:24:41 +000037
pbos@webrtc.org34741c82013-05-27 08:02:22 +000038#include "webrtc/typedefs.h" // For architecture defines
kjellander@webrtc.org4ed4f242011-12-05 16:31:12 +000039
kjellander@webrtc.org7951e812011-10-13 12:24:41 +000040namespace webrtc {
41namespace test {
42
henrike@webrtc.org34773d92013-07-08 14:55:23 +000043namespace {
44
kjellander@webrtc.org4d8cd9d2011-11-09 11:24:14 +000045#ifdef WIN32
henrike@webrtc.org34773d92013-07-08 14:55:23 +000046const char* kPathDelimiter = "\\";
kjellander@webrtc.org4d8cd9d2011-11-09 11:24:14 +000047#else
henrike@webrtc.org34773d92013-07-08 14:55:23 +000048const char* kPathDelimiter = "/";
kjellander@webrtc.org4d8cd9d2011-11-09 11:24:14 +000049#endif
leozwang@webrtc.org363efef2012-10-16 04:31:20 +000050
51#ifdef WEBRTC_ANDROID
henrike@webrtc.org34773d92013-07-08 14:55:23 +000052const char* kResourcesDirName = "resources";
leozwang@webrtc.org363efef2012-10-16 04:31:20 +000053#else
andrew@webrtc.org1e10bb32011-10-31 20:22:02 +000054// The file we're looking for to identify the project root dir.
henrike@webrtc.org34773d92013-07-08 14:55:23 +000055const char* kProjectRootFileName = "DEPS";
56const char* kResourcesDirName = "resources";
leozwang@webrtc.orgfb594422012-06-29 18:28:12 +000057#endif
henrike@webrtc.orgcaf2fcc2013-07-05 04:15:38 +000058
henrike@webrtc.org34773d92013-07-08 14:55:23 +000059const char* kFallbackPath = "./";
60const char* kOutputDirName = "out";
pbos@webrtc.orgdb7d82f2013-07-05 08:49:09 +000061char relative_dir_path[FILENAME_MAX];
62bool relative_dir_path_set = false;
henrike@webrtc.org34773d92013-07-08 14:55:23 +000063
64} // namespace
65
66const char* kCannotFindProjectRootDir = "ERROR_CANNOT_FIND_PROJECT_ROOT_DIR";
67
68std::string OutputPathAndroid();
pbos@webrtc.orgfc496d92013-07-09 15:24:16 +000069std::string ProjectRootPathAndroid();
kjellander@webrtc.org83b767b2012-10-15 18:14:12 +000070
kjellander@webrtc.org193600b2012-10-17 04:39:44 +000071void SetExecutablePath(const std::string& path) {
72 std::string working_dir = WorkingDir();
73 std::string temp_path = path;
74
75 // Handle absolute paths; convert them to relative paths to the working dir.
76 if (path.find(working_dir) != std::string::npos) {
77 temp_path = path.substr(working_dir.length() + 1);
78 }
kjellander@webrtc.orgde499662013-08-29 11:26:41 +000079 // On Windows, when tests are run under memory tools like DrMemory and TSan,
80 // slashes occur in the path as directory separators. Make sure we replace
81 // such cases with backslashes in order for the paths to be correct.
82#ifdef WIN32
83 std::replace(temp_path.begin(), temp_path.end(), '/', '\\');
84#endif
85
kjellander@webrtc.org193600b2012-10-17 04:39:44 +000086 // Trim away the executable name; only store the relative dir path.
87 temp_path = temp_path.substr(0, temp_path.find_last_of(kPathDelimiter));
kjellander@webrtc.org83b767b2012-10-15 18:14:12 +000088 strncpy(relative_dir_path, temp_path.c_str(), FILENAME_MAX);
89 relative_dir_path_set = true;
90}
91
92bool FileExists(std::string& file_name) {
93 struct stat file_info = {0};
94 return stat(file_name.c_str(), &file_info) == 0;
95}
96
henrike@webrtc.org34773d92013-07-08 14:55:23 +000097std::string OutputPathImpl() {
98 std::string path = ProjectRootPath();
99 if (path == kCannotFindProjectRootDir) {
100 return kFallbackPath;
101 }
102 path += kOutputDirName;
kjellander@webrtc.org7de47bc2014-04-16 08:04:26 +0000103 if (!CreateDir(path)) {
henrike@webrtc.org34773d92013-07-08 14:55:23 +0000104 return kFallbackPath;
105 }
106 return path + kPathDelimiter;
107}
108
leozwang@webrtc.org363efef2012-10-16 04:31:20 +0000109#ifdef WEBRTC_ANDROID
110
111std::string ProjectRootPath() {
pbos@webrtc.orgfc496d92013-07-09 15:24:16 +0000112 return ProjectRootPathAndroid();
leozwang@webrtc.org363efef2012-10-16 04:31:20 +0000113}
114
115std::string OutputPath() {
henrike@webrtc.org34773d92013-07-08 14:55:23 +0000116 return OutputPathAndroid();
leozwang@webrtc.org363efef2012-10-16 04:31:20 +0000117}
118
119std::string WorkingDir() {
henrike@webrtc.org34773d92013-07-08 14:55:23 +0000120 return ProjectRootPath();
leozwang@webrtc.org363efef2012-10-16 04:31:20 +0000121}
122
123#else // WEBRTC_ANDROID
124
andrew@webrtc.org0db7dc62011-11-13 01:34:05 +0000125std::string ProjectRootPath() {
kjellander@webrtc.org83b767b2012-10-15 18:14:12 +0000126 std::string path = WorkingDir();
127 if (path == kFallbackPath) {
kjellander@webrtc.org7951e812011-10-13 12:24:41 +0000128 return kCannotFindProjectRootDir;
129 }
kjellander@webrtc.org83b767b2012-10-15 18:14:12 +0000130 if (relative_dir_path_set) {
131 path = path + kPathDelimiter + relative_dir_path;
132 }
kjellander@webrtc.org7951e812011-10-13 12:24:41 +0000133 // Check for our file that verifies the root dir.
kjellander@webrtc.org193600b2012-10-17 04:39:44 +0000134 size_t path_delimiter_index = path.find_last_of(kPathDelimiter);
135 while (path_delimiter_index != std::string::npos) {
kjellander@webrtc.org83b767b2012-10-15 18:14:12 +0000136 std::string root_filename = path + kPathDelimiter + kProjectRootFileName;
137 if (FileExists(root_filename)) {
138 return path + kPathDelimiter;
kjellander@webrtc.org7951e812011-10-13 12:24:41 +0000139 }
kjellander@webrtc.org7951e812011-10-13 12:24:41 +0000140 // Move up one directory in the directory tree.
kjellander@webrtc.org83b767b2012-10-15 18:14:12 +0000141 path = path.substr(0, path_delimiter_index);
142 path_delimiter_index = path.find_last_of(kPathDelimiter);
kjellander@webrtc.org7951e812011-10-13 12:24:41 +0000143 }
kjellander@webrtc.org7951e812011-10-13 12:24:41 +0000144 // Reached the root directory.
145 fprintf(stderr, "Cannot find project root directory!\n");
146 return kCannotFindProjectRootDir;
147}
148
andrew@webrtc.org0db7dc62011-11-13 01:34:05 +0000149std::string OutputPath() {
henrike@webrtc.org34773d92013-07-08 14:55:23 +0000150 return OutputPathImpl();
kjellander@webrtc.org4d8cd9d2011-11-09 11:24:14 +0000151}
kjellander@webrtc.org4ed4f242011-12-05 16:31:12 +0000152
153std::string WorkingDir() {
154 char path_buffer[FILENAME_MAX];
155 if (!GET_CURRENT_DIR(path_buffer, sizeof(path_buffer))) {
156 fprintf(stderr, "Cannot get current directory!\n");
157 return kFallbackPath;
kjellander@webrtc.org5b97b122011-12-08 07:42:18 +0000158 } else {
kjellander@webrtc.org4ed4f242011-12-05 16:31:12 +0000159 return std::string(path_buffer);
160 }
161}
162
leozwang@webrtc.org363efef2012-10-16 04:31:20 +0000163#endif // !WEBRTC_ANDROID
164
kjellander@webrtc.org7de47bc2014-04-16 08:04:26 +0000165// Generate a temporary filename in a safe way.
166// Largely copied from talk/base/{unixfilesystem,win32filesystem}.cc.
167std::string TempFilename(const std::string &dir, const std::string &prefix) {
168#ifdef WIN32
169 wchar_t filename[MAX_PATH];
170 if (::GetTempFileName(ToUtf16(dir).c_str(),
171 ToUtf16(prefix).c_str(), 0, filename) != 0)
172 return ToUtf8(filename);
173 assert(false);
174 return "";
175#else
176 int len = dir.size() + prefix.size() + 2 + 6;
177 scoped_ptr<char[]> tempname(new char[len]);
178
179 snprintf(tempname.get(), len, "%s/%sXXXXXX", dir.c_str(),
180 prefix.c_str());
181 int fd = ::mkstemp(tempname.get());
182 if (fd == -1) {
183 assert(false);
184 return "";
185 } else {
186 ::close(fd);
187 }
188 std::string ret(tempname.get());
189 return ret;
190#endif
191}
192
193bool CreateDir(std::string directory_name) {
kjellander@webrtc.org4ed4f242011-12-05 16:31:12 +0000194 struct stat path_info = {0};
195 // Check if the path exists already:
196 if (stat(directory_name.c_str(), &path_info) == 0) {
197 if (!S_ISDIR(path_info.st_mode)) {
198 fprintf(stderr, "Path %s exists but is not a directory! Remove this "
199 "file and re-run to create the directory.\n",
200 directory_name.c_str());
201 return false;
202 }
203 } else {
204#ifdef WIN32
205 return _mkdir(directory_name.c_str()) == 0;
206#else
207 return mkdir(directory_name.c_str(), S_IRWXU | S_IRWXG | S_IRWXO) == 0;
208#endif
209 }
210 return true;
211}
212
kjellander@webrtc.org4ed4f242011-12-05 16:31:12 +0000213std::string ResourcePath(std::string name, std::string extension) {
214 std::string platform = "win";
215#ifdef WEBRTC_LINUX
216 platform = "linux";
217#endif // WEBRTC_LINUX
218#ifdef WEBRTC_MAC
219 platform = "mac";
220#endif // WEBRTC_MAC
221
222#ifdef WEBRTC_ARCH_64_BITS
223 std::string architecture = "64";
224#else
225 std::string architecture = "32";
226#endif // WEBRTC_ARCH_64_BITS
227
kjellander@webrtc.org5b97b122011-12-08 07:42:18 +0000228 std::string resources_path = ProjectRootPath() + kResourcesDirName +
229 kPathDelimiter;
kjellander@webrtc.org4ed4f242011-12-05 16:31:12 +0000230 std::string resource_file = resources_path + name + "_" + platform + "_" +
231 architecture + "." + extension;
kjellander@webrtc.org80b26612011-12-07 18:50:17 +0000232 if (FileExists(resource_file)) {
kjellander@webrtc.org4ed4f242011-12-05 16:31:12 +0000233 return resource_file;
234 }
235 // Try without architecture.
236 resource_file = resources_path + name + "_" + platform + "." + extension;
237 if (FileExists(resource_file)) {
238 return resource_file;
239 }
240 // Try without platform.
241 resource_file = resources_path + name + "_" + architecture + "." + extension;
242 if (FileExists(resource_file)) {
243 return resource_file;
244 }
leozwang@webrtc.org363efef2012-10-16 04:31:20 +0000245
kjellander@webrtc.org4ed4f242011-12-05 16:31:12 +0000246 // Fall back on name without architecture or platform.
247 return resources_path + name + "." + extension;
248}
249
kjellander@webrtc.org5b97b122011-12-08 07:42:18 +0000250size_t GetFileSize(std::string filename) {
251 FILE* f = fopen(filename.c_str(), "rb");
252 size_t size = 0;
253 if (f != NULL) {
254 if (fseek(f, 0, SEEK_END) == 0) {
255 size = ftell(f);
256 }
257 fclose(f);
258 }
259 return size;
260}
261
kjellander@webrtc.org7951e812011-10-13 12:24:41 +0000262} // namespace test
kjellander@webrtc.org4d8cd9d2011-11-09 11:24:14 +0000263} // namespace webrtc