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