1 // Copyright 2017 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 "net/disk_cache/backend_cleanup_tracker.h"
6
7 #include "base/files/scoped_temp_dir.h"
8 #include "base/functional/bind.h"
9 #include "base/functional/callback.h"
10 #include "base/memory/ref_counted.h"
11 #include "net/test/test_with_task_environment.h"
12 #include "testing/gmock/include/gmock/gmock.h"
13 #include "testing/gtest/include/gtest/gtest.h"
14
15 namespace disk_cache {
16 namespace {
17
18 using testing::UnorderedElementsAre;
19 using testing::IsEmpty;
20
21 class BackendCleanupTrackerTest : public net::TestWithTaskEnvironment {
22 protected:
23 BackendCleanupTrackerTest() = default;
24
SetUp()25 void SetUp() override {
26 testing::Test::SetUp();
27
28 ASSERT_TRUE(tmp_dir_.CreateUniqueTempDir());
29 // Create two unique paths.
30 path1_ = tmp_dir_.GetPath().Append(FILE_PATH_LITERAL("a"));
31 path2_ = tmp_dir_.GetPath().Append(FILE_PATH_LITERAL("b"));
32 }
33
RecordCall(int val)34 void RecordCall(int val) { called_.push_back(val); }
35
RecordCallClosure(int val)36 base::OnceClosure RecordCallClosure(int val) {
37 return base::BindOnce(&BackendCleanupTrackerTest::RecordCall,
38 base::Unretained(this), val);
39 }
40
41 base::ScopedTempDir tmp_dir_;
42 base::FilePath path1_;
43 base::FilePath path2_;
44 std::vector<int> called_;
45 };
46
TEST_F(BackendCleanupTrackerTest,DistinctPath)47 TEST_F(BackendCleanupTrackerTest, DistinctPath) {
48 scoped_refptr<BackendCleanupTracker> t1 =
49 BackendCleanupTracker::TryCreate(path1_, RecordCallClosure(1));
50 scoped_refptr<BackendCleanupTracker> t2 =
51 BackendCleanupTracker::TryCreate(path2_, RecordCallClosure(2));
52 // Both should be created immediately (since the paths are distinct), none of
53 // the callbacks should be invoked.
54 ASSERT_TRUE(t1 != nullptr);
55 ASSERT_TRUE(t2 != nullptr);
56 RunUntilIdle();
57 EXPECT_TRUE(called_.empty());
58
59 t1->AddPostCleanupCallback(RecordCallClosure(3));
60 t2->AddPostCleanupCallback(RecordCallClosure(4));
61 t2->AddPostCleanupCallback(RecordCallClosure(5));
62
63 // Just adding callbacks doesn't run them, nor just an event loop.
64 EXPECT_TRUE(called_.empty());
65 RunUntilIdle();
66 EXPECT_TRUE(called_.empty());
67
68 t1 = nullptr;
69 // Callbacks are not invoked immediately.
70 EXPECT_TRUE(called_.empty());
71
72 // ... but via the event loop.
73 RunUntilIdle();
74 EXPECT_THAT(called_, UnorderedElementsAre(3));
75
76 // Now cleanup t2.
77 t2 = nullptr;
78 EXPECT_THAT(called_, UnorderedElementsAre(3));
79 RunUntilIdle();
80 EXPECT_THAT(called_, UnorderedElementsAre(3, 4, 5));
81 }
82
TEST_F(BackendCleanupTrackerTest,SamePath)83 TEST_F(BackendCleanupTrackerTest, SamePath) {
84 scoped_refptr<BackendCleanupTracker> t1 =
85 BackendCleanupTracker::TryCreate(path1_, RecordCallClosure(1));
86 scoped_refptr<BackendCleanupTracker> t2 =
87 BackendCleanupTracker::TryCreate(path1_, RecordCallClosure(2));
88 // Since path is the same, only first call succeeds. No callback yet,
89 // since t1 controls the path.
90 ASSERT_TRUE(t1 != nullptr);
91 EXPECT_TRUE(t2 == nullptr);
92 RunUntilIdle();
93 EXPECT_TRUE(called_.empty());
94
95 t1->AddPostCleanupCallback(RecordCallClosure(3));
96 t1->AddPostCleanupCallback(RecordCallClosure(4));
97
98 // Create an alias denoting work in progress.
99 scoped_refptr<BackendCleanupTracker> alias = t1;
100 t1 = nullptr;
101
102 EXPECT_TRUE(called_.empty());
103 RunUntilIdle();
104 EXPECT_TRUE(called_.empty());
105
106 alias = nullptr;
107 EXPECT_TRUE(called_.empty());
108 RunUntilIdle();
109 // Both the callback passed to the TryCreate that failed and ones passed to
110 // AddPostCleanupCallback are called.
111 EXPECT_THAT(called_, UnorderedElementsAre(2, 3, 4));
112 }
113
114 } // namespace
115 } // namespace disk_cache
116