diff --git a/webrtc/test/testsupport/fileutils.cc b/webrtc/test/testsupport/fileutils.cc index 02ef06580b..a96b1eaf02 100644 --- a/webrtc/test/testsupport/fileutils.cc +++ b/webrtc/test/testsupport/fileutils.cc @@ -24,6 +24,7 @@ #include "webrtc/base/win32.h" #define GET_CURRENT_DIR _getcwd #else +#include #include #define GET_CURRENT_DIR getcwd @@ -39,7 +40,9 @@ #include #include +#include +#include "webrtc/base/checks.h" #include "webrtc/typedefs.h" // For architecture defines namespace webrtc { @@ -126,7 +129,7 @@ std::string WorkingDir() { return kRootDirName; } -#else // WEBRTC_ANDROID +#else // WEBRTC_ANDROID std::string ProjectRootPath() { #if defined(WEBRTC_IOS) @@ -212,6 +215,57 @@ std::string TempFilename(const std::string &dir, const std::string &prefix) { #endif } +rtc::Optional> ReadDirectory(std::string path) { + if (path.length() == 0) + return rtc::Optional>(); + +#if defined(WEBRTC_WIN) + // Append separator character if needed. + if (path.back() != '\\') + path += '\\'; + + // Init. + WIN32_FIND_DATA data; + HANDLE handle = ::FindFirstFile(rtc::ToUtf16(path + '*').c_str(), &data); + if (handle == INVALID_HANDLE_VALUE) + return rtc::Optional>(); + + // Populate output. + std::vector found_entries; + do { + const std::string name = rtc::ToUtf8(data.cFileName); + if (name != "." && name != "..") + found_entries.emplace_back(path + name); + } while (::FindNextFile(handle, &data) == TRUE); + + // Release resources. + if (handle != INVALID_HANDLE_VALUE) + ::FindClose(handle); +#else + // Append separator character if needed. + if (path.back() != '/') + path += '/'; + + // Init. + DIR* dir = ::opendir(path.c_str()); + if (dir == nullptr) + return rtc::Optional>(); + + // Populate output. + std::vector found_entries; + while (dirent* dirent = readdir(dir)) { + const std::string& name = dirent->d_name; + if (name != "." && name != "..") + found_entries.emplace_back(path + name); + } + + // Release resources. + closedir(dir); +#endif + + return rtc::Optional>(std::move(found_entries)); +} + bool CreateDir(const std::string& directory_name) { struct stat path_info = {0}; // Check if the path exists already: diff --git a/webrtc/test/testsupport/fileutils.h b/webrtc/test/testsupport/fileutils.h index 2135681380..434287d6d9 100644 --- a/webrtc/test/testsupport/fileutils.h +++ b/webrtc/test/testsupport/fileutils.h @@ -14,6 +14,9 @@ #define WEBRTC_TEST_TESTSUPPORT_FILEUTILS_H_ #include +#include + +#include "webrtc/base/optional.h" namespace webrtc { namespace test { @@ -66,6 +69,12 @@ std::string ResourcePath(const std::string& name, // directory. std::string WorkingDir(); +// Reads the content of a directory and, in case of success, returns a vector +// of strings with one element for each found file or directory. Each element is +// a path created by prepending |dir| to the file/directory name. "." and ".." +// are never added in the returned vector. +rtc::Optional> ReadDirectory(std::string path); + // Creates a directory if it not already exists. // Returns true if successful. Will print an error message to stderr and return // false if a file with the same name already exists. diff --git a/webrtc/test/testsupport/fileutils_unittest.cc b/webrtc/test/testsupport/fileutils_unittest.cc index 132436f004..560300f640 100644 --- a/webrtc/test/testsupport/fileutils_unittest.cc +++ b/webrtc/test/testsupport/fileutils_unittest.cc @@ -12,9 +12,14 @@ #include +#include +#include #include #include +#include "webrtc/base/checks.h" +#include "webrtc/base/optional.h" +#include "webrtc/base/pathutils.h" #include "webrtc/test/gtest.h" #ifdef WIN32 @@ -24,11 +29,41 @@ static const char* kPathDelimiter = "\\"; static const char* kPathDelimiter = "/"; #endif -static const std::string kResourcesDir = "resources"; -static const std::string kTestName = "fileutils_unittest"; -static const std::string kExtension = "tmp"; +static const char kTestName[] = "fileutils_unittest"; +static const char kExtension[] = "tmp"; namespace webrtc { +namespace test { + +namespace { + +// Remove files and directories in a directory non-recursively and writes the +// number of deleted items in |num_deleted_entries|. +void CleanDir(const std::string& dir, size_t* num_deleted_entries) { + RTC_DCHECK(num_deleted_entries); + *num_deleted_entries = 0; + rtc::Optional> dir_content = ReadDirectory(dir); + EXPECT_TRUE(dir_content); + for (const auto& entry : *dir_content) { + if (DirExists(entry)) { + EXPECT_TRUE(RemoveDir(entry)); + (*num_deleted_entries)++; + } else if (FileExists(entry)) { + EXPECT_TRUE(RemoveFile(entry)); + (*num_deleted_entries)++; + } else { + FAIL(); + } + } +} + +void WriteStringInFile(const std::string& what, const std::string& file_path) { + std::ofstream out(file_path); + out << what; + out.close(); +} + +} // namespace // Test fixture to restore the working directory between each test, since some // of them change it with chdir during execution (not restored by the @@ -170,4 +205,36 @@ TEST_F(FileUtilsTest, DirExists) { remove(temp_filename.c_str()); } +TEST_F(FileUtilsTest, WriteReadDeleteFilesAndDirs) { + size_t num_deleted_entries; + + // Create an empty temporary directory for this test. + const std::string temp_directory = + OutputPath() + "TempFileUtilsTestReadDirectory" + kPathDelimiter; + CreateDir(temp_directory); + EXPECT_NO_FATAL_FAILURE(CleanDir(temp_directory, &num_deleted_entries)); + EXPECT_TRUE(DirExists(temp_directory)); + + // Add a file. + const std::string temp_filename = temp_directory + "TempFilenameTest"; + WriteStringInFile("test\n", temp_filename); + EXPECT_TRUE(FileExists(temp_filename)); + + // Add an empty directory. + const std::string temp_subdir = temp_directory + "subdir" + kPathDelimiter; + EXPECT_TRUE(CreateDir(temp_subdir)); + EXPECT_TRUE(DirExists(temp_subdir)); + + // Checks. + rtc::Optional> dir_content = + ReadDirectory(temp_directory); + EXPECT_TRUE(dir_content); + EXPECT_EQ(2u, dir_content->size()); + EXPECT_NO_FATAL_FAILURE(CleanDir(temp_directory, &num_deleted_entries)); + EXPECT_EQ(2u, num_deleted_entries); + EXPECT_TRUE(RemoveDir(temp_directory)); + EXPECT_FALSE(DirExists(temp_directory)); +} + +} // namespace test } // namespace webrtc