1 // Copyright 2020 The Chromium Authors. All rights reserved.
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 "content/browser/service_worker/service_worker_disk_cache.h"
6
7 #include "base/callback_helpers.h"
8 #include "base/files/file_util.h"
9 #include "base/files/scoped_temp_dir.h"
10 #include "base/test/bind.h"
11 #include "base/test/task_environment.h"
12 #include "net/base/net_errors.h"
13 #include "net/base/test_completion_callback.h"
14 #include "net/disk_cache/disk_cache.h"
15 #include "testing/gtest/include/gtest/gtest.h"
16
17 namespace content {
18
19 class ServiceWorkerDiskCacheTest : public testing::Test {
20 public:
21 ServiceWorkerDiskCacheTest() = default;
22
SetUp()23 void SetUp() override { ASSERT_TRUE(directory_.CreateUniqueTempDir()); }
24
TearDown()25 void TearDown() override { FlushCacheTasks(); }
26
FlushCacheTasks()27 void FlushCacheTasks() {
28 disk_cache::FlushCacheThreadForTesting();
29 task_environment_.RunUntilIdle();
30 }
31
InitializeDiskCache(ServiceWorkerDiskCache * disk_cache)32 void InitializeDiskCache(ServiceWorkerDiskCache* disk_cache) {
33 base::RunLoop loop;
34 disk_cache->InitWithDiskBackend(
35 GetPath(), false,
36 /*post_cleanup_callback=*/base::DoNothing::Once(),
37 base::BindLambdaForTesting([&](int rv) {
38 ASSERT_EQ(rv, net::OK);
39 loop.Quit();
40 }));
41 loop.Run();
42 }
43
GetPath()44 base::FilePath GetPath() { return directory_.GetPath(); }
45
46 private:
47 base::test::TaskEnvironment task_environment_;
48 base::ScopedTempDir directory_;
49 };
50
51 // Tests that callbacks of operations are invoked even when these operations are
52 // called at the same time for the same key.
TEST_F(ServiceWorkerDiskCacheTest,MultipleCallsForSameKey)53 TEST_F(ServiceWorkerDiskCacheTest, MultipleCallsForSameKey) {
54 auto disk_cache = std::make_unique<ServiceWorkerDiskCache>();
55
56 bool create_entry_called = false;
57 bool open_entry_called = false;
58 bool doom_entry_called = false;
59
60 const int64_t kKey = 1;
61 disk_cache->CreateEntry(
62 kKey, base::BindLambdaForTesting(
63 [&](int rv, std::unique_ptr<ServiceWorkerDiskCacheEntry>) {
64 create_entry_called = true;
65 }));
66 disk_cache->OpenEntry(
67 kKey, base::BindLambdaForTesting(
68 [&](int rv, std::unique_ptr<ServiceWorkerDiskCacheEntry>) {
69 open_entry_called = true;
70 }));
71 disk_cache->DoomEntry(kKey, base::BindLambdaForTesting(
72 [&](int rv) { doom_entry_called = true; }));
73
74 InitializeDiskCache(disk_cache.get());
75 FlushCacheTasks();
76
77 EXPECT_TRUE(create_entry_called);
78 EXPECT_TRUE(open_entry_called);
79 EXPECT_TRUE(doom_entry_called);
80 }
81
TEST_F(ServiceWorkerDiskCacheTest,DisablePriorToInitCompletion)82 TEST_F(ServiceWorkerDiskCacheTest, DisablePriorToInitCompletion) {
83 // Create an instance and start it initializing, queue up
84 // one of each kind of "entry" function.
85 auto disk_cache = std::make_unique<ServiceWorkerDiskCache>();
86 EXPECT_FALSE(disk_cache->is_disabled());
87
88 size_t callback_count = 0;
89 auto completion_callback = base::BindLambdaForTesting([&](int rv) {
90 EXPECT_EQ(rv, net::ERR_ABORTED);
91 ++callback_count;
92 });
93 auto entry_callback = base::BindLambdaForTesting(
94 [&](int rv, std::unique_ptr<ServiceWorkerDiskCacheEntry> entry) {
95 EXPECT_EQ(rv, net::ERR_ABORTED);
96 EXPECT_FALSE(entry);
97 ++callback_count;
98 });
99 disk_cache->InitWithDiskBackend(GetPath(), false,
100 /*post_cleanup_callback=*/base::DoNothing(),
101 completion_callback);
102 disk_cache->CreateEntry(1, entry_callback);
103 disk_cache->OpenEntry(2, entry_callback);
104 disk_cache->DoomEntry(3, completion_callback);
105
106 // Pull the plug on all that.
107 EXPECT_FALSE(disk_cache->is_disabled());
108 disk_cache->Disable();
109 EXPECT_TRUE(disk_cache->is_disabled());
110
111 FlushCacheTasks();
112
113 EXPECT_EQ(callback_count, 4u);
114
115 // Ensure the directory can be deleted at this point.
116 EXPECT_TRUE(base::DirectoryExists(GetPath()));
117 EXPECT_FALSE(base::IsDirectoryEmpty(GetPath()));
118 EXPECT_TRUE(base::DeletePathRecursively(GetPath()));
119 EXPECT_FALSE(base::DirectoryExists(GetPath()));
120 }
121
TEST_F(ServiceWorkerDiskCacheTest,DisableAfterInitted)122 TEST_F(ServiceWorkerDiskCacheTest, DisableAfterInitted) {
123 // Create an instance and start it initializing, queue up
124 // one of each kind of "entry" function.
125 auto disk_cache = std::make_unique<ServiceWorkerDiskCache>();
126 EXPECT_FALSE(disk_cache->is_disabled());
127 InitializeDiskCache(disk_cache.get());
128
129 // Pull the plug
130 disk_cache->Disable();
131 FlushCacheTasks();
132
133 // Ensure the directory can be deleted at this point.
134 EXPECT_TRUE(base::DirectoryExists(GetPath()));
135 EXPECT_FALSE(base::IsDirectoryEmpty(GetPath()));
136 EXPECT_TRUE(base::DeletePathRecursively(GetPath()));
137 EXPECT_FALSE(base::DirectoryExists(GetPath()));
138
139 // Methods should fail.
140 size_t callback_count = 0;
141 auto completion_callback = base::BindLambdaForTesting([&](int rv) {
142 EXPECT_EQ(rv, net::ERR_ABORTED);
143 ++callback_count;
144 });
145 auto entry_callback = base::BindLambdaForTesting(
146 [&](int rv, std::unique_ptr<ServiceWorkerDiskCacheEntry> entry) {
147 EXPECT_EQ(rv, net::ERR_ABORTED);
148 EXPECT_FALSE(entry);
149 ++callback_count;
150 });
151 disk_cache->CreateEntry(1, entry_callback);
152 disk_cache->OpenEntry(2, entry_callback);
153 disk_cache->DoomEntry(3, completion_callback);
154 FlushCacheTasks();
155
156 EXPECT_EQ(callback_count, 3u);
157 }
158
TEST_F(ServiceWorkerDiskCacheTest,CleanupCallback)159 TEST_F(ServiceWorkerDiskCacheTest, CleanupCallback) {
160 // Test that things delete fine when we disable the cache and wait for
161 // the cleanup callback.
162
163 net::TestClosure cleanup_done;
164 net::TestCompletionCallback init_done;
165 auto disk_cache = std::make_unique<ServiceWorkerDiskCache>();
166 EXPECT_FALSE(disk_cache->is_disabled());
167 disk_cache->InitWithDiskBackend(GetPath(), false, cleanup_done.closure(),
168 init_done.callback());
169 EXPECT_EQ(net::OK, init_done.WaitForResult());
170
171 disk_cache->Disable();
172 cleanup_done.WaitForResult();
173
174 // Ensure the directory can be deleted at this point.
175 EXPECT_TRUE(base::DirectoryExists(GetPath()));
176 EXPECT_FALSE(base::IsDirectoryEmpty(GetPath()));
177 EXPECT_TRUE(base::DeletePathRecursively(GetPath()));
178 EXPECT_FALSE(base::DirectoryExists(GetPath()));
179 }
180
181 } // namespace content
182