blob: 899bf31f9070ac5c5a9166655ca3a164c461e110 [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
kjellander@webrtc.org7de47bc2014-04-16 08:04:26 +000013#include <assert.h>
henrike@webrtc.orgf2aafe42014-04-29 17:54:17 +000014
15#ifdef WIN32
kjellander@webrtc.org7951e812011-10-13 12:24:41 +000016#include <direct.h>
kjellander@webrtc.org7de47bc2014-04-16 08:04:26 +000017#include <tchar.h>
18#include <windows.h>
kjellander@webrtc.orgde499662013-08-29 11:26:41 +000019#include <algorithm>
kjellander@webrtc.org7de47bc2014-04-16 08:04:26 +000020
ehmaldonado00f2ee02016-11-18 07:06:41 -080021#include "Shlwapi.h"
ehmaldonado37535bf2016-12-05 06:42:45 -080022#include "WinDef.h"
ehmaldonado00f2ee02016-11-18 07:06:41 -080023
nisse07b83882017-03-14 01:32:50 -070024#include "webrtc/base/win32.h"
kjellander@webrtc.org7951e812011-10-13 12:24:41 +000025#define GET_CURRENT_DIR _getcwd
kjellander@webrtc.org7951e812011-10-13 12:24:41 +000026#else
27#include <unistd.h>
kjellander@webrtc.org7de47bc2014-04-16 08:04:26 +000028
kjellander@webrtc.org7951e812011-10-13 12:24:41 +000029#define GET_CURRENT_DIR getcwd
kjellander@webrtc.org4d8cd9d2011-11-09 11:24:14 +000030#endif
31
32#include <sys/stat.h> // To check for directory existence.
33#ifndef S_ISDIR // Not defined in stat.h on Windows.
34#define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR)
kjellander@webrtc.org7951e812011-10-13 12:24:41 +000035#endif
36
pbos@webrtc.org12dc1a32013-08-05 16:22:53 +000037#include <stdio.h>
kjellander@webrtc.org7de47bc2014-04-16 08:04:26 +000038#include <stdlib.h>
pbos@webrtc.org12dc1a32013-08-05 16:22:53 +000039#include <string.h>
kjellander@webrtc.org7951e812011-10-13 12:24:41 +000040
kwibergbfefb032016-05-01 14:53:46 -070041#include <memory>
42
pbos@webrtc.org34741c82013-05-27 08:02:22 +000043#include "webrtc/typedefs.h" // For architecture defines
kjellander@webrtc.org4ed4f242011-12-05 16:31:12 +000044
kjellander@webrtc.org7951e812011-10-13 12:24:41 +000045namespace webrtc {
46namespace test {
47
henrika1d34fe92015-06-16 10:04:20 +020048#if defined(WEBRTC_IOS)
49// Defined in iosfileutils.mm. No header file to discourage use elsewhere.
kjellander02060002016-02-16 22:06:12 -080050std::string IOSOutputPath();
Kári Tristan Helgason470c0882016-10-03 13:13:29 +020051std::string IOSRootPath();
henrika1d34fe92015-06-16 10:04:20 +020052std::string IOSResourcePath(std::string name, std::string extension);
53#endif
54
henrike@webrtc.org34773d92013-07-08 14:55:23 +000055namespace {
56
kjellander@webrtc.org4d8cd9d2011-11-09 11:24:14 +000057#ifdef WIN32
henrike@webrtc.org34773d92013-07-08 14:55:23 +000058const char* kPathDelimiter = "\\";
kjellander@webrtc.org4d8cd9d2011-11-09 11:24:14 +000059#else
henrike@webrtc.org34773d92013-07-08 14:55:23 +000060const char* kPathDelimiter = "/";
kjellander@webrtc.org4d8cd9d2011-11-09 11:24:14 +000061#endif
leozwang@webrtc.org363efef2012-10-16 04:31:20 +000062
63#ifdef WEBRTC_ANDROID
kjellander68208892016-06-16 23:29:30 -070064const char* kRootDirName = "/sdcard/chromium_tests_root/";
leozwang@webrtc.org363efef2012-10-16 04:31:20 +000065#else
kjellander02060002016-02-16 22:06:12 -080066#if !defined(WEBRTC_IOS)
henrike@webrtc.org34773d92013-07-08 14:55:23 +000067const char* kOutputDirName = "out";
kjellander@webrtc.org72fd3392014-11-05 06:28:50 +000068#endif
kjellander02060002016-02-16 22:06:12 -080069const char* kFallbackPath = "./";
70#endif // !defined(WEBRTC_ANDROID)
71
henrika1d34fe92015-06-16 10:04:20 +020072#if !defined(WEBRTC_IOS)
kjellander@webrtc.org72fd3392014-11-05 06:28:50 +000073const char* kResourcesDirName = "resources";
henrika1d34fe92015-06-16 10:04:20 +020074#endif
kjellander@webrtc.org72fd3392014-11-05 06:28:50 +000075
pbos@webrtc.orgdb7d82f2013-07-05 08:49:09 +000076char relative_dir_path[FILENAME_MAX];
77bool relative_dir_path_set = false;
henrike@webrtc.org34773d92013-07-08 14:55:23 +000078
79} // namespace
80
81const char* kCannotFindProjectRootDir = "ERROR_CANNOT_FIND_PROJECT_ROOT_DIR";
82
kjellander@webrtc.org193600b2012-10-17 04:39:44 +000083void SetExecutablePath(const std::string& path) {
84 std::string working_dir = WorkingDir();
85 std::string temp_path = path;
86
87 // Handle absolute paths; convert them to relative paths to the working dir.
88 if (path.find(working_dir) != std::string::npos) {
89 temp_path = path.substr(working_dir.length() + 1);
90 }
kjellander@webrtc.orgde499662013-08-29 11:26:41 +000091 // On Windows, when tests are run under memory tools like DrMemory and TSan,
92 // slashes occur in the path as directory separators. Make sure we replace
93 // such cases with backslashes in order for the paths to be correct.
94#ifdef WIN32
95 std::replace(temp_path.begin(), temp_path.end(), '/', '\\');
96#endif
97
kjellander@webrtc.org193600b2012-10-17 04:39:44 +000098 // Trim away the executable name; only store the relative dir path.
99 temp_path = temp_path.substr(0, temp_path.find_last_of(kPathDelimiter));
kjellander@webrtc.org83b767b2012-10-15 18:14:12 +0000100 strncpy(relative_dir_path, temp_path.c_str(), FILENAME_MAX);
101 relative_dir_path_set = true;
102}
103
ehmaldonado88df0bc2017-02-10 09:27:14 -0800104bool FileExists(const std::string& file_name) {
kjellander@webrtc.org83b767b2012-10-15 18:14:12 +0000105 struct stat file_info = {0};
106 return stat(file_name.c_str(), &file_info) == 0;
107}
108
alessiobe49fede2017-03-15 06:04:59 -0700109bool DirExists(const std::string& directory_name) {
110 struct stat directory_info = {0};
111 return stat(directory_name.c_str(), &directory_info) == 0 && S_ISDIR(
112 directory_info.st_mode);
113}
114
leozwang@webrtc.org363efef2012-10-16 04:31:20 +0000115#ifdef WEBRTC_ANDROID
116
117std::string ProjectRootPath() {
kjellander@webrtc.org72fd3392014-11-05 06:28:50 +0000118 return kRootDirName;
leozwang@webrtc.org363efef2012-10-16 04:31:20 +0000119}
120
121std::string OutputPath() {
kjellander@webrtc.org72fd3392014-11-05 06:28:50 +0000122 return kRootDirName;
leozwang@webrtc.org363efef2012-10-16 04:31:20 +0000123}
124
125std::string WorkingDir() {
kjellander@webrtc.org72fd3392014-11-05 06:28:50 +0000126 return kRootDirName;
leozwang@webrtc.org363efef2012-10-16 04:31:20 +0000127}
128
129#else // WEBRTC_ANDROID
130
andrew@webrtc.org0db7dc62011-11-13 01:34:05 +0000131std::string ProjectRootPath() {
Kári Tristan Helgason470c0882016-10-03 13:13:29 +0200132#if defined(WEBRTC_IOS)
133 return IOSRootPath();
134#else
kjellander@webrtc.org83b767b2012-10-15 18:14:12 +0000135 std::string path = WorkingDir();
136 if (path == kFallbackPath) {
kjellander@webrtc.org7951e812011-10-13 12:24:41 +0000137 return kCannotFindProjectRootDir;
138 }
ehmaldonado00f2ee02016-11-18 07:06:41 -0800139 if (relative_dir_path_set) {
kjellander@webrtc.org83b767b2012-10-15 18:14:12 +0000140 path = path + kPathDelimiter + relative_dir_path;
141 }
ehmaldonado00f2ee02016-11-18 07:06:41 -0800142 path = path + kPathDelimiter + ".." + kPathDelimiter + "..";
143 char canonical_path[FILENAME_MAX];
144#ifdef WIN32
ehmaldonado37535bf2016-12-05 06:42:45 -0800145 BOOL succeeded = PathCanonicalizeA(canonical_path, path.c_str());
ehmaldonado00f2ee02016-11-18 07:06:41 -0800146#else
147 bool succeeded = realpath(path.c_str(), canonical_path) != NULL;
148#endif
149 if (succeeded) {
150 path = std::string(canonical_path) + kPathDelimiter;
151 return path;
152 } else {
153 fprintf(stderr, "Cannot find project root directory!\n");
154 return kCannotFindProjectRootDir;
kjellander@webrtc.org7951e812011-10-13 12:24:41 +0000155 }
Kári Tristan Helgason470c0882016-10-03 13:13:29 +0200156#endif
kjellander@webrtc.org7951e812011-10-13 12:24:41 +0000157}
158
andrew@webrtc.org0db7dc62011-11-13 01:34:05 +0000159std::string OutputPath() {
kjellander02060002016-02-16 22:06:12 -0800160#if defined(WEBRTC_IOS)
161 return IOSOutputPath();
162#else
kjellander@webrtc.org72fd3392014-11-05 06:28:50 +0000163 std::string path = ProjectRootPath();
164 if (path == kCannotFindProjectRootDir) {
165 return kFallbackPath;
166 }
167 path += kOutputDirName;
168 if (!CreateDir(path)) {
169 return kFallbackPath;
170 }
171 return path + kPathDelimiter;
kjellander02060002016-02-16 22:06:12 -0800172#endif
kjellander@webrtc.org4d8cd9d2011-11-09 11:24:14 +0000173}
kjellander@webrtc.org4ed4f242011-12-05 16:31:12 +0000174
175std::string WorkingDir() {
176 char path_buffer[FILENAME_MAX];
177 if (!GET_CURRENT_DIR(path_buffer, sizeof(path_buffer))) {
178 fprintf(stderr, "Cannot get current directory!\n");
179 return kFallbackPath;
kjellander@webrtc.org5b97b122011-12-08 07:42:18 +0000180 } else {
kjellander@webrtc.org4ed4f242011-12-05 16:31:12 +0000181 return std::string(path_buffer);
182 }
183}
184
leozwang@webrtc.org363efef2012-10-16 04:31:20 +0000185#endif // !WEBRTC_ANDROID
186
kjellander@webrtc.org7de47bc2014-04-16 08:04:26 +0000187// Generate a temporary filename in a safe way.
188// Largely copied from talk/base/{unixfilesystem,win32filesystem}.cc.
189std::string TempFilename(const std::string &dir, const std::string &prefix) {
190#ifdef WIN32
191 wchar_t filename[MAX_PATH];
nisse07b83882017-03-14 01:32:50 -0700192 if (::GetTempFileName(rtc::ToUtf16(dir).c_str(),
193 rtc::ToUtf16(prefix).c_str(), 0, filename) != 0)
194 return rtc::ToUtf8(filename);
kjellander@webrtc.org7de47bc2014-04-16 08:04:26 +0000195 assert(false);
196 return "";
197#else
198 int len = dir.size() + prefix.size() + 2 + 6;
kwibergbfefb032016-05-01 14:53:46 -0700199 std::unique_ptr<char[]> tempname(new char[len]);
kjellander@webrtc.org7de47bc2014-04-16 08:04:26 +0000200
201 snprintf(tempname.get(), len, "%s/%sXXXXXX", dir.c_str(),
202 prefix.c_str());
203 int fd = ::mkstemp(tempname.get());
204 if (fd == -1) {
205 assert(false);
206 return "";
207 } else {
208 ::close(fd);
209 }
210 std::string ret(tempname.get());
211 return ret;
212#endif
213}
214
ehmaldonado88df0bc2017-02-10 09:27:14 -0800215bool CreateDir(const std::string& directory_name) {
kjellander@webrtc.org4ed4f242011-12-05 16:31:12 +0000216 struct stat path_info = {0};
217 // Check if the path exists already:
218 if (stat(directory_name.c_str(), &path_info) == 0) {
219 if (!S_ISDIR(path_info.st_mode)) {
220 fprintf(stderr, "Path %s exists but is not a directory! Remove this "
221 "file and re-run to create the directory.\n",
222 directory_name.c_str());
223 return false;
224 }
225 } else {
226#ifdef WIN32
227 return _mkdir(directory_name.c_str()) == 0;
228#else
229 return mkdir(directory_name.c_str(), S_IRWXU | S_IRWXG | S_IRWXO) == 0;
230#endif
231 }
232 return true;
233}
234
ehmaldonado88df0bc2017-02-10 09:27:14 -0800235std::string ResourcePath(const std::string& name,
236 const std::string& extension) {
henrika1d34fe92015-06-16 10:04:20 +0200237#if defined(WEBRTC_IOS)
238 return IOSResourcePath(name, extension);
239#else
kjellander@webrtc.org4ed4f242011-12-05 16:31:12 +0000240 std::string platform = "win";
241#ifdef WEBRTC_LINUX
242 platform = "linux";
243#endif // WEBRTC_LINUX
244#ifdef WEBRTC_MAC
245 platform = "mac";
246#endif // WEBRTC_MAC
ivoc72c08ed2016-01-20 07:26:24 -0800247#ifdef WEBRTC_ANDROID
248 platform = "android";
249#endif // WEBRTC_ANDROID
kjellander@webrtc.org4ed4f242011-12-05 16:31:12 +0000250
251#ifdef WEBRTC_ARCH_64_BITS
252 std::string architecture = "64";
253#else
254 std::string architecture = "32";
255#endif // WEBRTC_ARCH_64_BITS
256
kjellander@webrtc.org5b97b122011-12-08 07:42:18 +0000257 std::string resources_path = ProjectRootPath() + kResourcesDirName +
258 kPathDelimiter;
kjellander@webrtc.org4ed4f242011-12-05 16:31:12 +0000259 std::string resource_file = resources_path + name + "_" + platform + "_" +
260 architecture + "." + extension;
kjellander@webrtc.org80b26612011-12-07 18:50:17 +0000261 if (FileExists(resource_file)) {
kjellander@webrtc.org4ed4f242011-12-05 16:31:12 +0000262 return resource_file;
263 }
264 // Try without architecture.
265 resource_file = resources_path + name + "_" + platform + "." + extension;
266 if (FileExists(resource_file)) {
267 return resource_file;
268 }
269 // Try without platform.
270 resource_file = resources_path + name + "_" + architecture + "." + extension;
271 if (FileExists(resource_file)) {
272 return resource_file;
273 }
leozwang@webrtc.org363efef2012-10-16 04:31:20 +0000274
kjellander@webrtc.org4ed4f242011-12-05 16:31:12 +0000275 // Fall back on name without architecture or platform.
276 return resources_path + name + "." + extension;
henrika1d34fe92015-06-16 10:04:20 +0200277#endif // defined (WEBRTC_IOS)
kjellander@webrtc.org4ed4f242011-12-05 16:31:12 +0000278}
279
ehmaldonado88df0bc2017-02-10 09:27:14 -0800280size_t GetFileSize(const std::string& filename) {
kjellander@webrtc.org5b97b122011-12-08 07:42:18 +0000281 FILE* f = fopen(filename.c_str(), "rb");
282 size_t size = 0;
283 if (f != NULL) {
284 if (fseek(f, 0, SEEK_END) == 0) {
285 size = ftell(f);
286 }
287 fclose(f);
288 }
289 return size;
290}
291
kjellander@webrtc.org7951e812011-10-13 12:24:41 +0000292} // namespace test
kjellander@webrtc.org4d8cd9d2011-11-09 11:24:14 +0000293} // namespace webrtc