1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135
|
// Copyright 2013 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "base/test/test_file_util.h"
#include <vector>
#include "base/files/file_enumerator.h"
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/logging.h"
#include "base/test/test_timeouts.h"
#include "base/threading/platform_thread.h"
#include "base/threading/thread_restrictions.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace base {
namespace {
constexpr FilePath::CharType kDirPrefix[] =
FILE_PATH_LITERAL("test_scoped_temp_dir");
// Deletes all registered file paths upon test completion. There can only be
// one instance at a time.
class PathDeleterOnTestEnd : public testing::EmptyTestEventListener {
public:
PathDeleterOnTestEnd() {
DCHECK(!instance_);
instance_ = this;
}
~PathDeleterOnTestEnd() override {
DCHECK_EQ(instance_, this);
instance_ = nullptr;
}
PathDeleterOnTestEnd(const PathDeleterOnTestEnd&) = delete;
PathDeleterOnTestEnd& operator=(const PathDeleterOnTestEnd&) = delete;
static PathDeleterOnTestEnd* GetInstance() { return instance_; }
void DeletePathRecursivelyUponTestEnd(const FilePath& path) {
file_paths_to_delete_.push_back(path);
}
// EmptyTestEventListener overrides.
void OnTestEnd(const testing::TestInfo& test_info) override {
if (file_paths_to_delete_.empty()) {
// Nothing to delete since the last test ended.
return;
}
ScopedAllowBlockingForTesting allow_blocking;
for (const FilePath& file_path : file_paths_to_delete_) {
if (!DieFileDie(file_path, /*recurse=*/true)) {
base::FileEnumerator enumerator(
file_path, true,
base::FileEnumerator::FILES | FileEnumerator::DIRECTORIES);
for (base::FilePath failed_to_delete = enumerator.Next();
!failed_to_delete.empty(); failed_to_delete = enumerator.Next()) {
LOG(WARNING) << "failed to delete " << failed_to_delete;
}
ADD_FAILURE() << "Failed to delete temporary directory for testing: "
<< file_path;
}
}
file_paths_to_delete_.clear();
}
private:
static PathDeleterOnTestEnd* instance_;
std::vector<FilePath> file_paths_to_delete_;
};
// static
PathDeleterOnTestEnd* PathDeleterOnTestEnd::instance_ = nullptr;
FilePath RegisterPathDeleter(const FilePath& path) {
if (!PathDeleterOnTestEnd::GetInstance()) {
// Append() transfers ownership of the listener. This means
// PathDeleterOnTestEnd::GetInstance() will return non-null until all tests
// are run and the test suite destroyed.
testing::UnitTest::GetInstance()->listeners().Append(
new PathDeleterOnTestEnd());
DCHECK(PathDeleterOnTestEnd::GetInstance());
}
PathDeleterOnTestEnd::GetInstance()->DeletePathRecursivelyUponTestEnd(path);
return path;
}
} // namespace
bool EvictFileFromSystemCacheWithRetry(const FilePath& path) {
const int kCycles = 10;
const TimeDelta kDelay = TestTimeouts::action_timeout() / kCycles;
for (int i = 0; i < kCycles; i++) {
if (EvictFileFromSystemCache(path)) {
return true;
}
PlatformThread::Sleep(kDelay);
}
return false;
}
FilePath GetTempDirForTesting() {
FilePath path;
CHECK(GetTempDir(&path));
return path;
}
FilePath CreateUniqueTempDirectoryScopedToTest() {
ScopedAllowBlockingForTesting allow_blocking;
FilePath path;
if (!CreateNewTempDirectory(kDirPrefix, &path)) {
ADD_FAILURE() << "Failed to create unique temporary directory for testing.";
return FilePath();
}
return RegisterPathDeleter(path);
}
FilePath CreateUniqueTempDirectoryScopedToTestInDir(const base::FilePath& dir) {
ScopedAllowBlockingForTesting allow_blocking;
FilePath path;
if (!CreateTemporaryDirInDir(dir, kDirPrefix, &path)) {
ADD_FAILURE() << "Failed to create unique temporary directory for testing.";
return FilePath();
}
return RegisterPathDeleter(path);
}
} // namespace base
|