1 // Copyright 2011 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/disk_cache_test_util.h"
6
7 #include "base/check_op.h"
8 #include "base/files/file.h"
9 #include "base/files/file_path.h"
10 #include "base/run_loop.h"
11 #include "base/task/single_thread_task_runner.h"
12 #include "net/base/net_errors.h"
13 #include "net/disk_cache/backend_cleanup_tracker.h"
14 #include "net/disk_cache/blockfile/backend_impl.h"
15 #include "net/disk_cache/blockfile/file.h"
16 #include "net/disk_cache/cache_util.h"
17
18 using base::Time;
19
GenerateKey(bool same_length)20 std::string GenerateKey(bool same_length) {
21 char key[200];
22 CacheTestFillBuffer(base::as_writable_byte_span(key), same_length);
23
24 key[199] = '\0';
25 return std::string(key);
26 }
27
CacheTestFillBuffer(base::span<uint8_t> buffer,bool no_nulls)28 void CacheTestFillBuffer(base::span<uint8_t> buffer, bool no_nulls) {
29 static bool called = false;
30 if (!called) {
31 called = true;
32 int seed = static_cast<int>(Time::Now().ToInternalValue());
33 srand(seed);
34 }
35
36 for (size_t i = 0; i < buffer.size(); i++) {
37 buffer[i] = static_cast<char>(rand());
38 if (!buffer[i] && no_nulls)
39 buffer[i] = 'g';
40 }
41 if (buffer.size() && !buffer[0]) {
42 buffer[0] = 'g';
43 }
44 }
45
CacheTestCreateAndFillBuffer(size_t len,bool no_nulls)46 scoped_refptr<net::IOBufferWithSize> CacheTestCreateAndFillBuffer(
47 size_t len,
48 bool no_nulls) {
49 auto buffer = base::MakeRefCounted<net::IOBufferWithSize>(len);
50 CacheTestFillBuffer(buffer->span(), no_nulls);
51 return buffer;
52 }
53
CreateCacheTestFile(const base::FilePath & name)54 bool CreateCacheTestFile(const base::FilePath& name) {
55 int flags = base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_READ |
56 base::File::FLAG_WRITE;
57
58 base::File file(name, flags);
59 if (!file.IsValid())
60 return false;
61
62 file.SetLength(4 * 1024 * 1024);
63 return true;
64 }
65
DeleteCache(const base::FilePath & path)66 bool DeleteCache(const base::FilePath& path) {
67 disk_cache::DeleteCache(path, false);
68 return true;
69 }
70
CheckCacheIntegrity(const base::FilePath & path,bool new_eviction,int max_size,uint32_t mask)71 bool CheckCacheIntegrity(const base::FilePath& path,
72 bool new_eviction,
73 int max_size,
74 uint32_t mask) {
75 auto cache = std::make_unique<disk_cache::BackendImpl>(
76 path, mask, /* cleanup_tracker = */ nullptr,
77 base::SingleThreadTaskRunner::GetCurrentDefault(), net::DISK_CACHE,
78 nullptr);
79 if (max_size)
80 cache->SetMaxSize(max_size);
81 if (!cache.get())
82 return false;
83 if (new_eviction)
84 cache->SetNewEviction();
85 cache->SetFlags(disk_cache::kNoRandom);
86 if (cache->SyncInit() != net::OK)
87 return false;
88 return cache->SelfCheck() >= 0;
89 }
90
91 // -----------------------------------------------------------------------
92 TestBackendResultCompletionCallback::TestBackendResultCompletionCallback() =
93 default;
94
95 TestBackendResultCompletionCallback::~TestBackendResultCompletionCallback() =
96 default;
97
98 disk_cache::BackendResultCallback
callback()99 TestBackendResultCompletionCallback::callback() {
100 return base::BindOnce(&TestBackendResultCompletionCallback::SetResult,
101 base::Unretained(this));
102 }
103
104 TestEntryResultCompletionCallback::TestEntryResultCompletionCallback() =
105 default;
106
107 TestEntryResultCompletionCallback::~TestEntryResultCompletionCallback() =
108 default;
109
110 disk_cache::Backend::EntryResultCallback
callback()111 TestEntryResultCompletionCallback::callback() {
112 return base::BindOnce(&TestEntryResultCompletionCallback::SetResult,
113 base::Unretained(this));
114 }
115
116 TestRangeResultCompletionCallback::TestRangeResultCompletionCallback() =
117 default;
118
119 TestRangeResultCompletionCallback::~TestRangeResultCompletionCallback() =
120 default;
121
callback()122 disk_cache::RangeResultCallback TestRangeResultCompletionCallback::callback() {
123 return base::BindOnce(&TestRangeResultCompletionCallback::HelpSetResult,
124 base::Unretained(this));
125 }
126
HelpSetResult(const disk_cache::RangeResult & result)127 void TestRangeResultCompletionCallback::HelpSetResult(
128 const disk_cache::RangeResult& result) {
129 SetResult(result);
130 }
131
132 // -----------------------------------------------------------------------
133
134 MessageLoopHelper::MessageLoopHelper() = default;
135
136 MessageLoopHelper::~MessageLoopHelper() = default;
137
WaitUntilCacheIoFinished(int num_callbacks)138 bool MessageLoopHelper::WaitUntilCacheIoFinished(int num_callbacks) {
139 if (num_callbacks == callbacks_called_)
140 return true;
141
142 ExpectCallbacks(num_callbacks);
143 // Create a recurrent timer of 50 ms.
144 base::RepeatingTimer timer;
145 timer.Start(FROM_HERE, base::Milliseconds(50), this,
146 &MessageLoopHelper::TimerExpired);
147 run_loop_ = std::make_unique<base::RunLoop>();
148 run_loop_->Run();
149 run_loop_.reset();
150
151 return completed_;
152 }
153
154 // Quits the message loop when all callbacks are called or we've been waiting
155 // too long for them (2 secs without a callback).
TimerExpired()156 void MessageLoopHelper::TimerExpired() {
157 CHECK_LE(callbacks_called_, num_callbacks_);
158 if (callbacks_called_ == num_callbacks_) {
159 completed_ = true;
160 run_loop_->Quit();
161 } else {
162 // Not finished yet. See if we have to abort.
163 if (last_ == callbacks_called_)
164 num_iterations_++;
165 else
166 last_ = callbacks_called_;
167 if (40 == num_iterations_)
168 run_loop_->Quit();
169 }
170 }
171
172 // -----------------------------------------------------------------------
173
CallbackTest(MessageLoopHelper * helper,bool reuse)174 CallbackTest::CallbackTest(MessageLoopHelper* helper,
175 bool reuse)
176 : helper_(helper),
177 reuse_(reuse ? 0 : 1) {
178 }
179
180 CallbackTest::~CallbackTest() = default;
181
182 // On the actual callback, increase the number of tests received and check for
183 // errors (an unexpected test received)
Run(int result)184 void CallbackTest::Run(int result) {
185 last_result_ = result;
186
187 if (reuse_) {
188 DCHECK_EQ(1, reuse_);
189 if (2 == reuse_)
190 helper_->set_callback_reused_error(true);
191 reuse_++;
192 }
193
194 helper_->CallbackWasCalled();
195 }
196
RunWithEntry(disk_cache::EntryResult result)197 void CallbackTest::RunWithEntry(disk_cache::EntryResult result) {
198 last_entry_result_ = std::move(result);
199 Run(last_entry_result_.net_error());
200 }
201