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