xref: /aosp_15_r20/external/cronet/net/disk_cache/entry_unittest.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1 // Copyright 2012 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 <utility>
6 
7 #include "base/files/file.h"
8 #include "base/files/file_util.h"
9 #include "base/functional/bind.h"
10 #include "base/functional/callback_helpers.h"
11 #include "base/metrics/field_trial.h"
12 #include "base/metrics/field_trial_param_associator.h"
13 #include "base/run_loop.h"
14 #include "base/strings/string_number_conversions.h"
15 #include "base/strings/string_util.h"
16 #include "base/test/metrics/histogram_tester.h"
17 #include "base/test/scoped_feature_list.h"
18 #include "base/threading/platform_thread.h"
19 #include "base/time/time.h"
20 #include "build/build_config.h"
21 #include "net/base/completion_once_callback.h"
22 #include "net/base/io_buffer.h"
23 #include "net/base/net_errors.h"
24 #include "net/base/request_priority.h"
25 #include "net/base/test_completion_callback.h"
26 #include "net/disk_cache/blockfile/backend_impl.h"
27 #include "net/disk_cache/blockfile/entry_impl.h"
28 #include "net/disk_cache/cache_util.h"
29 #include "net/disk_cache/disk_cache_test_base.h"
30 #include "net/disk_cache/disk_cache_test_util.h"
31 #include "net/disk_cache/memory/mem_entry_impl.h"
32 #include "net/disk_cache/simple/simple_backend_impl.h"
33 #include "net/disk_cache/simple/simple_entry_format.h"
34 #include "net/disk_cache/simple/simple_entry_impl.h"
35 #include "net/disk_cache/simple/simple_histogram_enums.h"
36 #include "net/disk_cache/simple/simple_synchronous_entry.h"
37 #include "net/disk_cache/simple/simple_test_util.h"
38 #include "net/disk_cache/simple/simple_util.h"
39 #include "net/test/gtest_util.h"
40 #include "testing/gmock/include/gmock/gmock.h"
41 #include "testing/gtest/include/gtest/gtest.h"
42 
43 using net::test::IsError;
44 using net::test::IsOk;
45 
46 using base::Time;
47 using disk_cache::EntryResult;
48 using disk_cache::EntryResultCallback;
49 using disk_cache::RangeResult;
50 using disk_cache::ScopedEntryPtr;
51 
52 // Tests that can run with different types of caches.
53 class DiskCacheEntryTest : public DiskCacheTestWithCache {
54  public:
55   void InternalSyncIOBackground(disk_cache::Entry* entry);
56   void ExternalSyncIOBackground(disk_cache::Entry* entry);
57 
58  protected:
59   void InternalSyncIO();
60   void InternalAsyncIO();
61   void ExternalSyncIO();
62   void ExternalAsyncIO();
63   void ReleaseBuffer(int stream_index);
64   void StreamAccess();
65   void GetKey();
66   void GetTimes(int stream_index);
67   void GrowData(int stream_index);
68   void TruncateData(int stream_index);
69   void ZeroLengthIO(int stream_index);
70   void Buffering();
71   void SizeAtCreate();
72   void SizeChanges(int stream_index);
73   void ReuseEntry(int size, int stream_index);
74   void InvalidData(int stream_index);
75   void ReadWriteDestroyBuffer(int stream_index);
76   void DoomNormalEntry();
77   void DoomEntryNextToOpenEntry();
78   void DoomedEntry(int stream_index);
79   void BasicSparseIO();
80   void HugeSparseIO();
81   void GetAvailableRangeTest();
82   void CouldBeSparse();
83   void UpdateSparseEntry();
84   void DoomSparseEntry();
85   void PartialSparseEntry();
86   void SparseInvalidArg();
87   void SparseClipEnd(int64_t max_index, bool expected_unsupported);
88   bool SimpleCacheMakeBadChecksumEntry(const std::string& key, int data_size);
89   bool SimpleCacheThirdStreamFileExists(const char* key);
90   void SyncDoomEntry(const char* key);
91   void CreateEntryWithHeaderBodyAndSideData(const std::string& key,
92                                             int data_size);
93   void TruncateFileFromEnd(int file_index,
94                            const std::string& key,
95                            int data_size,
96                            int truncate_size);
97   void UseAfterBackendDestruction();
98   void CloseSparseAfterBackendDestruction();
99   void LastUsedTimePersists();
100   void TruncateBackwards();
101   void ZeroWriteBackwards();
102   void SparseOffset64Bit();
103 };
104 
105 // This part of the test runs on the background thread.
InternalSyncIOBackground(disk_cache::Entry * entry)106 void DiskCacheEntryTest::InternalSyncIOBackground(disk_cache::Entry* entry) {
107   const int kSize1 = 10;
108   auto buffer1 = base::MakeRefCounted<net::IOBufferWithSize>(kSize1);
109   CacheTestFillBuffer(buffer1->data(), kSize1, false);
110   EXPECT_EQ(0, entry->ReadData(0, 0, buffer1.get(), kSize1,
111                                net::CompletionOnceCallback()));
112   base::strlcpy(buffer1->data(), "the data", kSize1);
113   EXPECT_EQ(10, entry->WriteData(0, 0, buffer1.get(), kSize1,
114                                  net::CompletionOnceCallback(), false));
115   memset(buffer1->data(), 0, kSize1);
116   EXPECT_EQ(10, entry->ReadData(0, 0, buffer1.get(), kSize1,
117                                 net::CompletionOnceCallback()));
118   EXPECT_STREQ("the data", buffer1->data());
119 
120   const int kSize2 = 5000;
121   const int kSize3 = 10000;
122   auto buffer2 = base::MakeRefCounted<net::IOBufferWithSize>(kSize2);
123   auto buffer3 = base::MakeRefCounted<net::IOBufferWithSize>(kSize3);
124   memset(buffer3->data(), 0, kSize3);
125   CacheTestFillBuffer(buffer2->data(), kSize2, false);
126   base::strlcpy(buffer2->data(), "The really big data goes here", kSize2);
127   EXPECT_EQ(5000, entry->WriteData(1, 1500, buffer2.get(), kSize2,
128                                    net::CompletionOnceCallback(), false));
129   memset(buffer2->data(), 0, kSize2);
130   EXPECT_EQ(4989, entry->ReadData(1, 1511, buffer2.get(), kSize2,
131                                   net::CompletionOnceCallback()));
132   EXPECT_STREQ("big data goes here", buffer2->data());
133   EXPECT_EQ(5000, entry->ReadData(1, 0, buffer2.get(), kSize2,
134                                   net::CompletionOnceCallback()));
135   EXPECT_EQ(0, memcmp(buffer2->data(), buffer3->data(), 1500));
136   EXPECT_EQ(1500, entry->ReadData(1, 5000, buffer2.get(), kSize2,
137                                   net::CompletionOnceCallback()));
138 
139   EXPECT_EQ(0, entry->ReadData(1, 6500, buffer2.get(), kSize2,
140                                net::CompletionOnceCallback()));
141   EXPECT_EQ(6500, entry->ReadData(1, 0, buffer3.get(), kSize3,
142                                   net::CompletionOnceCallback()));
143   EXPECT_EQ(8192, entry->WriteData(1, 0, buffer3.get(), 8192,
144                                    net::CompletionOnceCallback(), false));
145   EXPECT_EQ(8192, entry->ReadData(1, 0, buffer3.get(), kSize3,
146                                   net::CompletionOnceCallback()));
147   EXPECT_EQ(8192, entry->GetDataSize(1));
148 
149   // We need to delete the memory buffer on this thread.
150   EXPECT_EQ(0, entry->WriteData(0, 0, nullptr, 0, net::CompletionOnceCallback(),
151                                 true));
152   EXPECT_EQ(0, entry->WriteData(1, 0, nullptr, 0, net::CompletionOnceCallback(),
153                                 true));
154 }
155 
156 // We need to support synchronous IO even though it is not a supported operation
157 // from the point of view of the disk cache's public interface, because we use
158 // it internally, not just by a few tests, but as part of the implementation
159 // (see sparse_control.cc, for example).
InternalSyncIO()160 void DiskCacheEntryTest::InternalSyncIO() {
161   disk_cache::Entry* entry = nullptr;
162   ASSERT_THAT(CreateEntry("the first key", &entry), IsOk());
163   ASSERT_TRUE(nullptr != entry);
164 
165   // The bulk of the test runs from within the callback, on the cache thread.
166   RunTaskForTest(base::BindOnce(&DiskCacheEntryTest::InternalSyncIOBackground,
167                                 base::Unretained(this), entry));
168 
169   entry->Doom();
170   entry->Close();
171   FlushQueueForTest();
172   EXPECT_EQ(0, cache_->GetEntryCount());
173 }
174 
TEST_F(DiskCacheEntryTest,InternalSyncIO)175 TEST_F(DiskCacheEntryTest, InternalSyncIO) {
176   InitCache();
177   InternalSyncIO();
178 }
179 
TEST_F(DiskCacheEntryTest,MemoryOnlyInternalSyncIO)180 TEST_F(DiskCacheEntryTest, MemoryOnlyInternalSyncIO) {
181   SetMemoryOnlyMode();
182   InitCache();
183   InternalSyncIO();
184 }
185 
InternalAsyncIO()186 void DiskCacheEntryTest::InternalAsyncIO() {
187   disk_cache::Entry* entry = nullptr;
188   ASSERT_THAT(CreateEntry("the first key", &entry), IsOk());
189   ASSERT_TRUE(nullptr != entry);
190 
191   // Avoid using internal buffers for the test. We have to write something to
192   // the entry and close it so that we flush the internal buffer to disk. After
193   // that, IO operations will be really hitting the disk. We don't care about
194   // the content, so just extending the entry is enough (all extensions zero-
195   // fill any holes).
196   EXPECT_EQ(0, WriteData(entry, 0, 15 * 1024, nullptr, 0, false));
197   EXPECT_EQ(0, WriteData(entry, 1, 15 * 1024, nullptr, 0, false));
198   entry->Close();
199   ASSERT_THAT(OpenEntry("the first key", &entry), IsOk());
200 
201   MessageLoopHelper helper;
202   // Let's verify that each IO goes to the right callback object.
203   CallbackTest callback1(&helper, false);
204   CallbackTest callback2(&helper, false);
205   CallbackTest callback3(&helper, false);
206   CallbackTest callback4(&helper, false);
207   CallbackTest callback5(&helper, false);
208   CallbackTest callback6(&helper, false);
209   CallbackTest callback7(&helper, false);
210   CallbackTest callback8(&helper, false);
211   CallbackTest callback9(&helper, false);
212   CallbackTest callback10(&helper, false);
213   CallbackTest callback11(&helper, false);
214   CallbackTest callback12(&helper, false);
215   CallbackTest callback13(&helper, false);
216 
217   const int kSize1 = 10;
218   const int kSize2 = 5000;
219   const int kSize3 = 10000;
220   auto buffer1 = base::MakeRefCounted<net::IOBufferWithSize>(kSize1);
221   auto buffer2 = base::MakeRefCounted<net::IOBufferWithSize>(kSize2);
222   auto buffer3 = base::MakeRefCounted<net::IOBufferWithSize>(kSize3);
223   CacheTestFillBuffer(buffer1->data(), kSize1, false);
224   CacheTestFillBuffer(buffer2->data(), kSize2, false);
225   CacheTestFillBuffer(buffer3->data(), kSize3, false);
226 
227   EXPECT_EQ(0, entry->ReadData(0, 15 * 1024, buffer1.get(), kSize1,
228                                base::BindOnce(&CallbackTest::Run,
229                                               base::Unretained(&callback1))));
230   base::strlcpy(buffer1->data(), "the data", kSize1);
231   int expected = 0;
232   int ret = entry->WriteData(
233       0, 0, buffer1.get(), kSize1,
234       base::BindOnce(&CallbackTest::Run, base::Unretained(&callback2)), false);
235   EXPECT_TRUE(10 == ret || net::ERR_IO_PENDING == ret);
236   if (net::ERR_IO_PENDING == ret)
237     expected++;
238 
239   EXPECT_TRUE(helper.WaitUntilCacheIoFinished(expected));
240   memset(buffer2->data(), 0, kSize2);
241   ret = entry->ReadData(
242       0, 0, buffer2.get(), kSize1,
243       base::BindOnce(&CallbackTest::Run, base::Unretained(&callback3)));
244   EXPECT_TRUE(10 == ret || net::ERR_IO_PENDING == ret);
245   if (net::ERR_IO_PENDING == ret)
246     expected++;
247 
248   EXPECT_TRUE(helper.WaitUntilCacheIoFinished(expected));
249   EXPECT_STREQ("the data", buffer2->data());
250 
251   base::strlcpy(buffer2->data(), "The really big data goes here", kSize2);
252   ret = entry->WriteData(
253       1, 1500, buffer2.get(), kSize2,
254       base::BindOnce(&CallbackTest::Run, base::Unretained(&callback4)), true);
255   EXPECT_TRUE(5000 == ret || net::ERR_IO_PENDING == ret);
256   if (net::ERR_IO_PENDING == ret)
257     expected++;
258 
259   EXPECT_TRUE(helper.WaitUntilCacheIoFinished(expected));
260   memset(buffer3->data(), 0, kSize3);
261   ret = entry->ReadData(
262       1, 1511, buffer3.get(), kSize2,
263       base::BindOnce(&CallbackTest::Run, base::Unretained(&callback5)));
264   EXPECT_TRUE(4989 == ret || net::ERR_IO_PENDING == ret);
265   if (net::ERR_IO_PENDING == ret)
266     expected++;
267 
268   EXPECT_TRUE(helper.WaitUntilCacheIoFinished(expected));
269   EXPECT_STREQ("big data goes here", buffer3->data());
270   ret = entry->ReadData(
271       1, 0, buffer2.get(), kSize2,
272       base::BindOnce(&CallbackTest::Run, base::Unretained(&callback6)));
273   EXPECT_TRUE(5000 == ret || net::ERR_IO_PENDING == ret);
274   if (net::ERR_IO_PENDING == ret)
275     expected++;
276 
277   memset(buffer3->data(), 0, kSize3);
278 
279   EXPECT_TRUE(helper.WaitUntilCacheIoFinished(expected));
280   EXPECT_EQ(0, memcmp(buffer2->data(), buffer3->data(), 1500));
281   ret = entry->ReadData(
282       1, 5000, buffer2.get(), kSize2,
283       base::BindOnce(&CallbackTest::Run, base::Unretained(&callback7)));
284   EXPECT_TRUE(1500 == ret || net::ERR_IO_PENDING == ret);
285   if (net::ERR_IO_PENDING == ret)
286     expected++;
287 
288   ret = entry->ReadData(
289       1, 0, buffer3.get(), kSize3,
290       base::BindOnce(&CallbackTest::Run, base::Unretained(&callback9)));
291   EXPECT_TRUE(6500 == ret || net::ERR_IO_PENDING == ret);
292   if (net::ERR_IO_PENDING == ret)
293     expected++;
294 
295   ret = entry->WriteData(
296       1, 0, buffer3.get(), 8192,
297       base::BindOnce(&CallbackTest::Run, base::Unretained(&callback10)), true);
298   EXPECT_TRUE(8192 == ret || net::ERR_IO_PENDING == ret);
299   if (net::ERR_IO_PENDING == ret)
300     expected++;
301 
302   EXPECT_TRUE(helper.WaitUntilCacheIoFinished(expected));
303   ret = entry->ReadData(
304       1, 0, buffer3.get(), kSize3,
305       base::BindOnce(&CallbackTest::Run, base::Unretained(&callback11)));
306   EXPECT_TRUE(8192 == ret || net::ERR_IO_PENDING == ret);
307   if (net::ERR_IO_PENDING == ret)
308     expected++;
309 
310   EXPECT_EQ(8192, entry->GetDataSize(1));
311 
312   ret = entry->ReadData(
313       0, 0, buffer1.get(), kSize1,
314       base::BindOnce(&CallbackTest::Run, base::Unretained(&callback12)));
315   EXPECT_TRUE(10 == ret || net::ERR_IO_PENDING == ret);
316   if (net::ERR_IO_PENDING == ret)
317     expected++;
318 
319   ret = entry->ReadData(
320       1, 0, buffer2.get(), kSize2,
321       base::BindOnce(&CallbackTest::Run, base::Unretained(&callback13)));
322   EXPECT_TRUE(5000 == ret || net::ERR_IO_PENDING == ret);
323   if (net::ERR_IO_PENDING == ret)
324     expected++;
325 
326   EXPECT_TRUE(helper.WaitUntilCacheIoFinished(expected));
327 
328   EXPECT_FALSE(helper.callback_reused_error());
329 
330   entry->Doom();
331   entry->Close();
332   FlushQueueForTest();
333   EXPECT_EQ(0, cache_->GetEntryCount());
334 }
335 
TEST_F(DiskCacheEntryTest,InternalAsyncIO)336 TEST_F(DiskCacheEntryTest, InternalAsyncIO) {
337   InitCache();
338   InternalAsyncIO();
339 }
340 
TEST_F(DiskCacheEntryTest,MemoryOnlyInternalAsyncIO)341 TEST_F(DiskCacheEntryTest, MemoryOnlyInternalAsyncIO) {
342   SetMemoryOnlyMode();
343   InitCache();
344   InternalAsyncIO();
345 }
346 
347 // This part of the test runs on the background thread.
ExternalSyncIOBackground(disk_cache::Entry * entry)348 void DiskCacheEntryTest::ExternalSyncIOBackground(disk_cache::Entry* entry) {
349   const int kSize1 = 17000;
350   const int kSize2 = 25000;
351   auto buffer1 = base::MakeRefCounted<net::IOBufferWithSize>(kSize1);
352   auto buffer2 = base::MakeRefCounted<net::IOBufferWithSize>(kSize2);
353   CacheTestFillBuffer(buffer1->data(), kSize1, false);
354   CacheTestFillBuffer(buffer2->data(), kSize2, false);
355   base::strlcpy(buffer1->data(), "the data", kSize1);
356   EXPECT_EQ(17000, entry->WriteData(0, 0, buffer1.get(), kSize1,
357                                     net::CompletionOnceCallback(), false));
358   memset(buffer1->data(), 0, kSize1);
359   EXPECT_EQ(17000, entry->ReadData(0, 0, buffer1.get(), kSize1,
360                                    net::CompletionOnceCallback()));
361   EXPECT_STREQ("the data", buffer1->data());
362 
363   base::strlcpy(buffer2->data(), "The really big data goes here", kSize2);
364   EXPECT_EQ(25000, entry->WriteData(1, 10000, buffer2.get(), kSize2,
365                                     net::CompletionOnceCallback(), false));
366   memset(buffer2->data(), 0, kSize2);
367   EXPECT_EQ(24989, entry->ReadData(1, 10011, buffer2.get(), kSize2,
368                                    net::CompletionOnceCallback()));
369   EXPECT_STREQ("big data goes here", buffer2->data());
370   EXPECT_EQ(25000, entry->ReadData(1, 0, buffer2.get(), kSize2,
371                                    net::CompletionOnceCallback()));
372   EXPECT_EQ(5000, entry->ReadData(1, 30000, buffer2.get(), kSize2,
373                                   net::CompletionOnceCallback()));
374 
375   EXPECT_EQ(0, entry->ReadData(1, 35000, buffer2.get(), kSize2,
376                                net::CompletionOnceCallback()));
377   EXPECT_EQ(17000, entry->ReadData(1, 0, buffer1.get(), kSize1,
378                                    net::CompletionOnceCallback()));
379   EXPECT_EQ(17000, entry->WriteData(1, 20000, buffer1.get(), kSize1,
380                                     net::CompletionOnceCallback(), false));
381   EXPECT_EQ(37000, entry->GetDataSize(1));
382 
383   // We need to delete the memory buffer on this thread.
384   EXPECT_EQ(0, entry->WriteData(0, 0, nullptr, 0, net::CompletionOnceCallback(),
385                                 true));
386   EXPECT_EQ(0, entry->WriteData(1, 0, nullptr, 0, net::CompletionOnceCallback(),
387                                 true));
388 }
389 
ExternalSyncIO()390 void DiskCacheEntryTest::ExternalSyncIO() {
391   disk_cache::Entry* entry;
392   ASSERT_THAT(CreateEntry("the first key", &entry), IsOk());
393 
394   // The bulk of the test runs from within the callback, on the cache thread.
395   RunTaskForTest(base::BindOnce(&DiskCacheEntryTest::ExternalSyncIOBackground,
396                                 base::Unretained(this), entry));
397 
398   entry->Doom();
399   entry->Close();
400   FlushQueueForTest();
401   EXPECT_EQ(0, cache_->GetEntryCount());
402 }
403 
TEST_F(DiskCacheEntryTest,ExternalSyncIO)404 TEST_F(DiskCacheEntryTest, ExternalSyncIO) {
405   InitCache();
406   ExternalSyncIO();
407 }
408 
TEST_F(DiskCacheEntryTest,ExternalSyncIONoBuffer)409 TEST_F(DiskCacheEntryTest, ExternalSyncIONoBuffer) {
410   InitCache();
411   cache_impl_->SetFlags(disk_cache::kNoBuffering);
412   ExternalSyncIO();
413 }
414 
TEST_F(DiskCacheEntryTest,MemoryOnlyExternalSyncIO)415 TEST_F(DiskCacheEntryTest, MemoryOnlyExternalSyncIO) {
416   SetMemoryOnlyMode();
417   InitCache();
418   ExternalSyncIO();
419 }
420 
ExternalAsyncIO()421 void DiskCacheEntryTest::ExternalAsyncIO() {
422   disk_cache::Entry* entry;
423   ASSERT_THAT(CreateEntry("the first key", &entry), IsOk());
424 
425   int expected = 0;
426 
427   MessageLoopHelper helper;
428   // Let's verify that each IO goes to the right callback object.
429   CallbackTest callback1(&helper, false);
430   CallbackTest callback2(&helper, false);
431   CallbackTest callback3(&helper, false);
432   CallbackTest callback4(&helper, false);
433   CallbackTest callback5(&helper, false);
434   CallbackTest callback6(&helper, false);
435   CallbackTest callback7(&helper, false);
436   CallbackTest callback8(&helper, false);
437   CallbackTest callback9(&helper, false);
438 
439   const int kSize1 = 17000;
440   const int kSize2 = 25000;
441   const int kSize3 = 25000;
442   auto buffer1 = base::MakeRefCounted<net::IOBufferWithSize>(kSize1);
443   auto buffer2 = base::MakeRefCounted<net::IOBufferWithSize>(kSize2);
444   auto buffer3 = base::MakeRefCounted<net::IOBufferWithSize>(kSize3);
445   CacheTestFillBuffer(buffer1->data(), kSize1, false);
446   CacheTestFillBuffer(buffer2->data(), kSize2, false);
447   CacheTestFillBuffer(buffer3->data(), kSize3, false);
448   base::strlcpy(buffer1->data(), "the data", kSize1);
449   int ret = entry->WriteData(
450       0, 0, buffer1.get(), kSize1,
451       base::BindOnce(&CallbackTest::Run, base::Unretained(&callback1)), false);
452   EXPECT_TRUE(17000 == ret || net::ERR_IO_PENDING == ret);
453   if (net::ERR_IO_PENDING == ret)
454     expected++;
455 
456   EXPECT_TRUE(helper.WaitUntilCacheIoFinished(expected));
457 
458   memset(buffer2->data(), 0, kSize1);
459   ret = entry->ReadData(
460       0, 0, buffer2.get(), kSize1,
461       base::BindOnce(&CallbackTest::Run, base::Unretained(&callback2)));
462   EXPECT_TRUE(17000 == ret || net::ERR_IO_PENDING == ret);
463   if (net::ERR_IO_PENDING == ret)
464     expected++;
465 
466   EXPECT_TRUE(helper.WaitUntilCacheIoFinished(expected));
467   EXPECT_STREQ("the data", buffer2->data());
468 
469   base::strlcpy(buffer2->data(), "The really big data goes here", kSize2);
470   ret = entry->WriteData(
471       1, 10000, buffer2.get(), kSize2,
472       base::BindOnce(&CallbackTest::Run, base::Unretained(&callback3)), false);
473   EXPECT_TRUE(25000 == ret || net::ERR_IO_PENDING == ret);
474   if (net::ERR_IO_PENDING == ret)
475     expected++;
476 
477   EXPECT_TRUE(helper.WaitUntilCacheIoFinished(expected));
478 
479   memset(buffer3->data(), 0, kSize3);
480   ret = entry->ReadData(
481       1, 10011, buffer3.get(), kSize3,
482       base::BindOnce(&CallbackTest::Run, base::Unretained(&callback4)));
483   EXPECT_TRUE(24989 == ret || net::ERR_IO_PENDING == ret);
484   if (net::ERR_IO_PENDING == ret)
485     expected++;
486 
487   EXPECT_TRUE(helper.WaitUntilCacheIoFinished(expected));
488   EXPECT_STREQ("big data goes here", buffer3->data());
489   ret = entry->ReadData(
490       1, 0, buffer2.get(), kSize2,
491       base::BindOnce(&CallbackTest::Run, base::Unretained(&callback5)));
492   EXPECT_TRUE(25000 == ret || net::ERR_IO_PENDING == ret);
493   if (net::ERR_IO_PENDING == ret)
494     expected++;
495 
496   EXPECT_TRUE(helper.WaitUntilCacheIoFinished(expected));
497   memset(buffer3->data(), 0, kSize3);
498   EXPECT_EQ(0, memcmp(buffer2->data(), buffer3->data(), 10000));
499   ret = entry->ReadData(
500       1, 30000, buffer2.get(), kSize2,
501       base::BindOnce(&CallbackTest::Run, base::Unretained(&callback6)));
502   EXPECT_TRUE(5000 == ret || net::ERR_IO_PENDING == ret);
503   if (net::ERR_IO_PENDING == ret)
504     expected++;
505 
506   ret = entry->ReadData(
507       1, 35000, buffer2.get(), kSize2,
508       base::BindOnce(&CallbackTest::Run, base::Unretained(&callback7)));
509   EXPECT_TRUE(0 == ret || net::ERR_IO_PENDING == ret);
510   if (net::ERR_IO_PENDING == ret)
511     expected++;
512 
513   ret = entry->ReadData(
514       1, 0, buffer1.get(), kSize1,
515       base::BindOnce(&CallbackTest::Run, base::Unretained(&callback8)));
516   EXPECT_TRUE(17000 == ret || net::ERR_IO_PENDING == ret);
517   if (net::ERR_IO_PENDING == ret)
518     expected++;
519   ret = entry->WriteData(
520       1, 20000, buffer3.get(), kSize1,
521       base::BindOnce(&CallbackTest::Run, base::Unretained(&callback9)), false);
522   EXPECT_TRUE(17000 == ret || net::ERR_IO_PENDING == ret);
523   if (net::ERR_IO_PENDING == ret)
524     expected++;
525 
526   EXPECT_TRUE(helper.WaitUntilCacheIoFinished(expected));
527   EXPECT_EQ(37000, entry->GetDataSize(1));
528 
529   EXPECT_FALSE(helper.callback_reused_error());
530 
531   entry->Doom();
532   entry->Close();
533   FlushQueueForTest();
534   EXPECT_EQ(0, cache_->GetEntryCount());
535 }
536 
TEST_F(DiskCacheEntryTest,ExternalAsyncIO)537 TEST_F(DiskCacheEntryTest, ExternalAsyncIO) {
538   InitCache();
539   ExternalAsyncIO();
540 }
541 
542 // TODO(http://crbug.com/497101): This test is flaky.
543 #if BUILDFLAG(IS_IOS)
544 #define MAYBE_ExternalAsyncIONoBuffer DISABLED_ExternalAsyncIONoBuffer
545 #else
546 #define MAYBE_ExternalAsyncIONoBuffer ExternalAsyncIONoBuffer
547 #endif
TEST_F(DiskCacheEntryTest,MAYBE_ExternalAsyncIONoBuffer)548 TEST_F(DiskCacheEntryTest, MAYBE_ExternalAsyncIONoBuffer) {
549   InitCache();
550   cache_impl_->SetFlags(disk_cache::kNoBuffering);
551   ExternalAsyncIO();
552 }
553 
TEST_F(DiskCacheEntryTest,MemoryOnlyExternalAsyncIO)554 TEST_F(DiskCacheEntryTest, MemoryOnlyExternalAsyncIO) {
555   SetMemoryOnlyMode();
556   InitCache();
557   ExternalAsyncIO();
558 }
559 
560 // Tests that IOBuffers are not referenced after IO completes.
ReleaseBuffer(int stream_index)561 void DiskCacheEntryTest::ReleaseBuffer(int stream_index) {
562   disk_cache::Entry* entry = nullptr;
563   ASSERT_THAT(CreateEntry("the first key", &entry), IsOk());
564   ASSERT_TRUE(nullptr != entry);
565 
566   const int kBufferSize = 1024;
567   auto buffer = base::MakeRefCounted<net::IOBufferWithSize>(kBufferSize);
568   CacheTestFillBuffer(buffer->data(), kBufferSize, false);
569 
570   net::ReleaseBufferCompletionCallback cb(buffer.get());
571   int rv = entry->WriteData(
572       stream_index, 0, buffer.get(), kBufferSize, cb.callback(), false);
573   EXPECT_EQ(kBufferSize, cb.GetResult(rv));
574   entry->Close();
575 }
576 
TEST_F(DiskCacheEntryTest,ReleaseBuffer)577 TEST_F(DiskCacheEntryTest, ReleaseBuffer) {
578   InitCache();
579   cache_impl_->SetFlags(disk_cache::kNoBuffering);
580   ReleaseBuffer(0);
581 }
582 
TEST_F(DiskCacheEntryTest,MemoryOnlyReleaseBuffer)583 TEST_F(DiskCacheEntryTest, MemoryOnlyReleaseBuffer) {
584   SetMemoryOnlyMode();
585   InitCache();
586   ReleaseBuffer(0);
587 }
588 
StreamAccess()589 void DiskCacheEntryTest::StreamAccess() {
590   disk_cache::Entry* entry = nullptr;
591   ASSERT_THAT(CreateEntry("the first key", &entry), IsOk());
592   ASSERT_TRUE(nullptr != entry);
593 
594   const int kBufferSize = 1024;
595   const int kNumStreams = 3;
596   scoped_refptr<net::IOBuffer> reference_buffers[kNumStreams];
597   for (auto& reference_buffer : reference_buffers) {
598     reference_buffer = base::MakeRefCounted<net::IOBufferWithSize>(kBufferSize);
599     CacheTestFillBuffer(reference_buffer->data(), kBufferSize, false);
600   }
601   auto buffer1 = base::MakeRefCounted<net::IOBufferWithSize>(kBufferSize);
602   for (int i = 0; i < kNumStreams; i++) {
603     EXPECT_EQ(
604         kBufferSize,
605         WriteData(entry, i, 0, reference_buffers[i].get(), kBufferSize, false));
606     memset(buffer1->data(), 0, kBufferSize);
607     EXPECT_EQ(kBufferSize, ReadData(entry, i, 0, buffer1.get(), kBufferSize));
608     EXPECT_EQ(
609         0, memcmp(reference_buffers[i]->data(), buffer1->data(), kBufferSize));
610   }
611   EXPECT_EQ(net::ERR_INVALID_ARGUMENT,
612             ReadData(entry, kNumStreams, 0, buffer1.get(), kBufferSize));
613   entry->Close();
614 
615   // Open the entry and read it in chunks, including a read past the end.
616   ASSERT_THAT(OpenEntry("the first key", &entry), IsOk());
617   ASSERT_TRUE(nullptr != entry);
618   const int kReadBufferSize = 600;
619   const int kFinalReadSize = kBufferSize - kReadBufferSize;
620   static_assert(kFinalReadSize < kReadBufferSize,
621                 "should be exactly two reads");
622   auto buffer2 = base::MakeRefCounted<net::IOBufferWithSize>(kReadBufferSize);
623   for (int i = 0; i < kNumStreams; i++) {
624     memset(buffer2->data(), 0, kReadBufferSize);
625     EXPECT_EQ(kReadBufferSize,
626               ReadData(entry, i, 0, buffer2.get(), kReadBufferSize));
627     EXPECT_EQ(
628         0,
629         memcmp(reference_buffers[i]->data(), buffer2->data(), kReadBufferSize));
630 
631     memset(buffer2->data(), 0, kReadBufferSize);
632     EXPECT_EQ(
633         kFinalReadSize,
634         ReadData(entry, i, kReadBufferSize, buffer2.get(), kReadBufferSize));
635     EXPECT_EQ(0,
636               memcmp(reference_buffers[i]->data() + kReadBufferSize,
637                      buffer2->data(),
638                      kFinalReadSize));
639   }
640 
641   entry->Close();
642 }
643 
TEST_F(DiskCacheEntryTest,StreamAccess)644 TEST_F(DiskCacheEntryTest, StreamAccess) {
645   InitCache();
646   StreamAccess();
647 }
648 
TEST_F(DiskCacheEntryTest,MemoryOnlyStreamAccess)649 TEST_F(DiskCacheEntryTest, MemoryOnlyStreamAccess) {
650   SetMemoryOnlyMode();
651   InitCache();
652   StreamAccess();
653 }
654 
GetKey()655 void DiskCacheEntryTest::GetKey() {
656   std::string key("the first key");
657   disk_cache::Entry* entry;
658   ASSERT_THAT(CreateEntry(key, &entry), IsOk());
659   EXPECT_EQ(key, entry->GetKey()) << "short key";
660   entry->Close();
661 
662   int seed = static_cast<int>(Time::Now().ToInternalValue());
663   srand(seed);
664   char key_buffer[20000];
665 
666   CacheTestFillBuffer(key_buffer, 3000, true);
667   key_buffer[1000] = '\0';
668 
669   key = key_buffer;
670   ASSERT_THAT(CreateEntry(key, &entry), IsOk());
671   EXPECT_TRUE(key == entry->GetKey()) << "1000 bytes key";
672   entry->Close();
673 
674   key_buffer[1000] = 'p';
675   key_buffer[3000] = '\0';
676   key = key_buffer;
677   ASSERT_THAT(CreateEntry(key, &entry), IsOk());
678   EXPECT_TRUE(key == entry->GetKey()) << "medium size key";
679   entry->Close();
680 
681   CacheTestFillBuffer(key_buffer, sizeof(key_buffer), true);
682   key_buffer[19999] = '\0';
683 
684   key = key_buffer;
685   ASSERT_THAT(CreateEntry(key, &entry), IsOk());
686   EXPECT_TRUE(key == entry->GetKey()) << "long key";
687   entry->Close();
688 
689   CacheTestFillBuffer(key_buffer, 0x4000, true);
690   key_buffer[0x4000] = '\0';
691 
692   key = key_buffer;
693   ASSERT_THAT(CreateEntry(key, &entry), IsOk());
694   EXPECT_TRUE(key == entry->GetKey()) << "16KB key";
695   entry->Close();
696 }
697 
TEST_F(DiskCacheEntryTest,GetKey)698 TEST_F(DiskCacheEntryTest, GetKey) {
699   InitCache();
700   GetKey();
701 }
702 
TEST_F(DiskCacheEntryTest,MemoryOnlyGetKey)703 TEST_F(DiskCacheEntryTest, MemoryOnlyGetKey) {
704   SetMemoryOnlyMode();
705   InitCache();
706   GetKey();
707 }
708 
GetTimes(int stream_index)709 void DiskCacheEntryTest::GetTimes(int stream_index) {
710   std::string key("the first key");
711   disk_cache::Entry* entry;
712 
713   Time t1 = Time::Now();
714   ASSERT_THAT(CreateEntry(key, &entry), IsOk());
715   EXPECT_TRUE(entry->GetLastModified() >= t1);
716   EXPECT_TRUE(entry->GetLastModified() == entry->GetLastUsed());
717 
718   AddDelay();
719   Time t2 = Time::Now();
720   EXPECT_TRUE(t2 > t1);
721   EXPECT_EQ(0, WriteData(entry, stream_index, 200, nullptr, 0, false));
722   if (type_ == net::APP_CACHE) {
723     EXPECT_TRUE(entry->GetLastModified() < t2);
724   } else {
725     EXPECT_TRUE(entry->GetLastModified() >= t2);
726   }
727   EXPECT_TRUE(entry->GetLastModified() == entry->GetLastUsed());
728 
729   AddDelay();
730   Time t3 = Time::Now();
731   EXPECT_TRUE(t3 > t2);
732   const int kSize = 200;
733   auto buffer = base::MakeRefCounted<net::IOBufferWithSize>(kSize);
734   EXPECT_EQ(kSize, ReadData(entry, stream_index, 0, buffer.get(), kSize));
735   if (type_ == net::APP_CACHE) {
736     EXPECT_TRUE(entry->GetLastUsed() < t2);
737     EXPECT_TRUE(entry->GetLastModified() < t2);
738   } else if (type_ == net::SHADER_CACHE) {
739     EXPECT_TRUE(entry->GetLastUsed() < t3);
740     EXPECT_TRUE(entry->GetLastModified() < t3);
741   } else {
742     EXPECT_TRUE(entry->GetLastUsed() >= t3);
743     EXPECT_TRUE(entry->GetLastModified() < t3);
744   }
745   entry->Close();
746 }
747 
TEST_F(DiskCacheEntryTest,GetTimes)748 TEST_F(DiskCacheEntryTest, GetTimes) {
749   InitCache();
750   GetTimes(0);
751 }
752 
TEST_F(DiskCacheEntryTest,MemoryOnlyGetTimes)753 TEST_F(DiskCacheEntryTest, MemoryOnlyGetTimes) {
754   SetMemoryOnlyMode();
755   InitCache();
756   GetTimes(0);
757 }
758 
TEST_F(DiskCacheEntryTest,AppCacheGetTimes)759 TEST_F(DiskCacheEntryTest, AppCacheGetTimes) {
760   SetCacheType(net::APP_CACHE);
761   InitCache();
762   GetTimes(0);
763 }
764 
TEST_F(DiskCacheEntryTest,ShaderCacheGetTimes)765 TEST_F(DiskCacheEntryTest, ShaderCacheGetTimes) {
766   SetCacheType(net::SHADER_CACHE);
767   InitCache();
768   GetTimes(0);
769 }
770 
GrowData(int stream_index)771 void DiskCacheEntryTest::GrowData(int stream_index) {
772   std::string key1("the first key");
773   disk_cache::Entry* entry;
774   ASSERT_THAT(CreateEntry(key1, &entry), IsOk());
775 
776   const int kSize = 20000;
777   auto buffer1 = base::MakeRefCounted<net::IOBufferWithSize>(kSize);
778   auto buffer2 = base::MakeRefCounted<net::IOBufferWithSize>(kSize);
779   CacheTestFillBuffer(buffer1->data(), kSize, false);
780   memset(buffer2->data(), 0, kSize);
781 
782   base::strlcpy(buffer1->data(), "the data", kSize);
783   EXPECT_EQ(10, WriteData(entry, stream_index, 0, buffer1.get(), 10, false));
784   EXPECT_EQ(10, ReadData(entry, stream_index, 0, buffer2.get(), 10));
785   EXPECT_STREQ("the data", buffer2->data());
786   EXPECT_EQ(10, entry->GetDataSize(stream_index));
787 
788   EXPECT_EQ(2000,
789             WriteData(entry, stream_index, 0, buffer1.get(), 2000, false));
790   EXPECT_EQ(2000, entry->GetDataSize(stream_index));
791   EXPECT_EQ(2000, ReadData(entry, stream_index, 0, buffer2.get(), 2000));
792   EXPECT_TRUE(!memcmp(buffer1->data(), buffer2->data(), 2000));
793 
794   EXPECT_EQ(20000,
795             WriteData(entry, stream_index, 0, buffer1.get(), kSize, false));
796   EXPECT_EQ(20000, entry->GetDataSize(stream_index));
797   EXPECT_EQ(20000, ReadData(entry, stream_index, 0, buffer2.get(), kSize));
798   EXPECT_TRUE(!memcmp(buffer1->data(), buffer2->data(), kSize));
799   entry->Close();
800 
801   memset(buffer2->data(), 0, kSize);
802   std::string key2("Second key");
803   ASSERT_THAT(CreateEntry(key2, &entry), IsOk());
804   EXPECT_EQ(10, WriteData(entry, stream_index, 0, buffer1.get(), 10, false));
805   EXPECT_EQ(10, entry->GetDataSize(stream_index));
806   entry->Close();
807 
808   // Go from an internal address to a bigger block size.
809   ASSERT_THAT(OpenEntry(key2, &entry), IsOk());
810   EXPECT_EQ(2000,
811             WriteData(entry, stream_index, 0, buffer1.get(), 2000, false));
812   EXPECT_EQ(2000, entry->GetDataSize(stream_index));
813   EXPECT_EQ(2000, ReadData(entry, stream_index, 0, buffer2.get(), 2000));
814   EXPECT_TRUE(!memcmp(buffer1->data(), buffer2->data(), 2000));
815   entry->Close();
816   memset(buffer2->data(), 0, kSize);
817 
818   // Go from an internal address to an external one.
819   ASSERT_THAT(OpenEntry(key2, &entry), IsOk());
820   EXPECT_EQ(20000,
821             WriteData(entry, stream_index, 0, buffer1.get(), kSize, false));
822   EXPECT_EQ(20000, entry->GetDataSize(stream_index));
823   EXPECT_EQ(20000, ReadData(entry, stream_index, 0, buffer2.get(), kSize));
824   EXPECT_TRUE(!memcmp(buffer1->data(), buffer2->data(), kSize));
825   entry->Close();
826 
827   // Double check the size from disk.
828   ASSERT_THAT(OpenEntry(key2, &entry), IsOk());
829   EXPECT_EQ(20000, entry->GetDataSize(stream_index));
830 
831   // Now extend the entry without actual data.
832   EXPECT_EQ(0, WriteData(entry, stream_index, 45500, buffer1.get(), 0, false));
833   entry->Close();
834 
835   // And check again from disk.
836   ASSERT_THAT(OpenEntry(key2, &entry), IsOk());
837   EXPECT_EQ(45500, entry->GetDataSize(stream_index));
838   entry->Close();
839 }
840 
TEST_F(DiskCacheEntryTest,GrowData)841 TEST_F(DiskCacheEntryTest, GrowData) {
842   InitCache();
843   GrowData(0);
844 }
845 
TEST_F(DiskCacheEntryTest,GrowDataNoBuffer)846 TEST_F(DiskCacheEntryTest, GrowDataNoBuffer) {
847   InitCache();
848   cache_impl_->SetFlags(disk_cache::kNoBuffering);
849   GrowData(0);
850 }
851 
TEST_F(DiskCacheEntryTest,MemoryOnlyGrowData)852 TEST_F(DiskCacheEntryTest, MemoryOnlyGrowData) {
853   SetMemoryOnlyMode();
854   InitCache();
855   GrowData(0);
856 }
857 
TruncateData(int stream_index)858 void DiskCacheEntryTest::TruncateData(int stream_index) {
859   std::string key("the first key");
860   disk_cache::Entry* entry;
861   ASSERT_THAT(CreateEntry(key, &entry), IsOk());
862 
863   const int kSize1 = 20000;
864   const int kSize2 = 20000;
865   auto buffer1 = base::MakeRefCounted<net::IOBufferWithSize>(kSize1);
866   auto buffer2 = base::MakeRefCounted<net::IOBufferWithSize>(kSize2);
867 
868   CacheTestFillBuffer(buffer1->data(), kSize1, false);
869   memset(buffer2->data(), 0, kSize2);
870 
871   // Simple truncation:
872   EXPECT_EQ(200, WriteData(entry, stream_index, 0, buffer1.get(), 200, false));
873   EXPECT_EQ(200, entry->GetDataSize(stream_index));
874   EXPECT_EQ(100, WriteData(entry, stream_index, 0, buffer1.get(), 100, false));
875   EXPECT_EQ(200, entry->GetDataSize(stream_index));
876   EXPECT_EQ(100, WriteData(entry, stream_index, 0, buffer1.get(), 100, true));
877   EXPECT_EQ(100, entry->GetDataSize(stream_index));
878   EXPECT_EQ(0, WriteData(entry, stream_index, 50, buffer1.get(), 0, true));
879   EXPECT_EQ(50, entry->GetDataSize(stream_index));
880   EXPECT_EQ(0, WriteData(entry, stream_index, 0, buffer1.get(), 0, true));
881   EXPECT_EQ(0, entry->GetDataSize(stream_index));
882   entry->Close();
883   ASSERT_THAT(OpenEntry(key, &entry), IsOk());
884 
885   // Go to an external file.
886   EXPECT_EQ(20000,
887             WriteData(entry, stream_index, 0, buffer1.get(), 20000, true));
888   EXPECT_EQ(20000, entry->GetDataSize(stream_index));
889   EXPECT_EQ(20000, ReadData(entry, stream_index, 0, buffer2.get(), 20000));
890   EXPECT_TRUE(!memcmp(buffer1->data(), buffer2->data(), 20000));
891   memset(buffer2->data(), 0, kSize2);
892 
893   // External file truncation
894   EXPECT_EQ(18000,
895             WriteData(entry, stream_index, 0, buffer1.get(), 18000, false));
896   EXPECT_EQ(20000, entry->GetDataSize(stream_index));
897   EXPECT_EQ(18000,
898             WriteData(entry, stream_index, 0, buffer1.get(), 18000, true));
899   EXPECT_EQ(18000, entry->GetDataSize(stream_index));
900   EXPECT_EQ(0, WriteData(entry, stream_index, 17500, buffer1.get(), 0, true));
901   EXPECT_EQ(17500, entry->GetDataSize(stream_index));
902 
903   // And back to an internal block.
904   EXPECT_EQ(600,
905             WriteData(entry, stream_index, 1000, buffer1.get(), 600, true));
906   EXPECT_EQ(1600, entry->GetDataSize(stream_index));
907   EXPECT_EQ(600, ReadData(entry, stream_index, 1000, buffer2.get(), 600));
908   EXPECT_TRUE(!memcmp(buffer1->data(), buffer2->data(), 600));
909   EXPECT_EQ(1000, ReadData(entry, stream_index, 0, buffer2.get(), 1000));
910   EXPECT_TRUE(!memcmp(buffer1->data(), buffer2->data(), 1000))
911       << "Preserves previous data";
912 
913   // Go from external file to zero length.
914   EXPECT_EQ(20000,
915             WriteData(entry, stream_index, 0, buffer1.get(), 20000, true));
916   EXPECT_EQ(20000, entry->GetDataSize(stream_index));
917   EXPECT_EQ(0, WriteData(entry, stream_index, 0, buffer1.get(), 0, true));
918   EXPECT_EQ(0, entry->GetDataSize(stream_index));
919 
920   entry->Close();
921 }
922 
TEST_F(DiskCacheEntryTest,TruncateData)923 TEST_F(DiskCacheEntryTest, TruncateData) {
924   InitCache();
925   TruncateData(0);
926 }
927 
TEST_F(DiskCacheEntryTest,TruncateDataNoBuffer)928 TEST_F(DiskCacheEntryTest, TruncateDataNoBuffer) {
929   InitCache();
930   cache_impl_->SetFlags(disk_cache::kNoBuffering);
931   TruncateData(0);
932 }
933 
TEST_F(DiskCacheEntryTest,MemoryOnlyTruncateData)934 TEST_F(DiskCacheEntryTest, MemoryOnlyTruncateData) {
935   SetMemoryOnlyMode();
936   InitCache();
937   TruncateData(0);
938 }
939 
ZeroLengthIO(int stream_index)940 void DiskCacheEntryTest::ZeroLengthIO(int stream_index) {
941   std::string key("the first key");
942   disk_cache::Entry* entry;
943   ASSERT_THAT(CreateEntry(key, &entry), IsOk());
944 
945   EXPECT_EQ(0, ReadData(entry, stream_index, 0, nullptr, 0));
946   EXPECT_EQ(0, WriteData(entry, stream_index, 0, nullptr, 0, false));
947 
948   // This write should extend the entry.
949   EXPECT_EQ(0, WriteData(entry, stream_index, 1000, nullptr, 0, false));
950   EXPECT_EQ(0, ReadData(entry, stream_index, 500, nullptr, 0));
951   EXPECT_EQ(0, ReadData(entry, stream_index, 2000, nullptr, 0));
952   EXPECT_EQ(1000, entry->GetDataSize(stream_index));
953 
954   EXPECT_EQ(0, WriteData(entry, stream_index, 100000, nullptr, 0, true));
955   EXPECT_EQ(0, ReadData(entry, stream_index, 50000, nullptr, 0));
956   EXPECT_EQ(100000, entry->GetDataSize(stream_index));
957 
958   // Let's verify the actual content.
959   const int kSize = 20;
960   const char zeros[kSize] = {};
961   auto buffer = base::MakeRefCounted<net::IOBufferWithSize>(kSize);
962 
963   CacheTestFillBuffer(buffer->data(), kSize, false);
964   EXPECT_EQ(kSize, ReadData(entry, stream_index, 500, buffer.get(), kSize));
965   EXPECT_TRUE(!memcmp(buffer->data(), zeros, kSize));
966 
967   CacheTestFillBuffer(buffer->data(), kSize, false);
968   EXPECT_EQ(kSize, ReadData(entry, stream_index, 5000, buffer.get(), kSize));
969   EXPECT_TRUE(!memcmp(buffer->data(), zeros, kSize));
970 
971   CacheTestFillBuffer(buffer->data(), kSize, false);
972   EXPECT_EQ(kSize, ReadData(entry, stream_index, 50000, buffer.get(), kSize));
973   EXPECT_TRUE(!memcmp(buffer->data(), zeros, kSize));
974 
975   entry->Close();
976 }
977 
TEST_F(DiskCacheEntryTest,ZeroLengthIO)978 TEST_F(DiskCacheEntryTest, ZeroLengthIO) {
979   InitCache();
980   ZeroLengthIO(0);
981 }
982 
TEST_F(DiskCacheEntryTest,ZeroLengthIONoBuffer)983 TEST_F(DiskCacheEntryTest, ZeroLengthIONoBuffer) {
984   InitCache();
985   cache_impl_->SetFlags(disk_cache::kNoBuffering);
986   ZeroLengthIO(0);
987 }
988 
TEST_F(DiskCacheEntryTest,MemoryOnlyZeroLengthIO)989 TEST_F(DiskCacheEntryTest, MemoryOnlyZeroLengthIO) {
990   SetMemoryOnlyMode();
991   InitCache();
992   ZeroLengthIO(0);
993 }
994 
995 // Tests that we handle the content correctly when buffering, a feature of the
996 // standard cache that permits fast responses to certain reads.
Buffering()997 void DiskCacheEntryTest::Buffering() {
998   std::string key("the first key");
999   disk_cache::Entry* entry;
1000   ASSERT_THAT(CreateEntry(key, &entry), IsOk());
1001 
1002   const int kSize = 200;
1003   auto buffer1 = base::MakeRefCounted<net::IOBufferWithSize>(kSize);
1004   auto buffer2 = base::MakeRefCounted<net::IOBufferWithSize>(kSize);
1005   CacheTestFillBuffer(buffer1->data(), kSize, true);
1006   CacheTestFillBuffer(buffer2->data(), kSize, true);
1007 
1008   EXPECT_EQ(kSize, WriteData(entry, 1, 0, buffer1.get(), kSize, false));
1009   entry->Close();
1010 
1011   // Write a little more and read what we wrote before.
1012   ASSERT_THAT(OpenEntry(key, &entry), IsOk());
1013   EXPECT_EQ(kSize, WriteData(entry, 1, 5000, buffer1.get(), kSize, false));
1014   EXPECT_EQ(kSize, ReadData(entry, 1, 0, buffer2.get(), kSize));
1015   EXPECT_TRUE(!memcmp(buffer2->data(), buffer1->data(), kSize));
1016 
1017   // Now go to an external file.
1018   EXPECT_EQ(kSize, WriteData(entry, 1, 18000, buffer1.get(), kSize, false));
1019   entry->Close();
1020 
1021   // Write something else and verify old data.
1022   ASSERT_THAT(OpenEntry(key, &entry), IsOk());
1023   EXPECT_EQ(kSize, WriteData(entry, 1, 10000, buffer1.get(), kSize, false));
1024   CacheTestFillBuffer(buffer2->data(), kSize, true);
1025   EXPECT_EQ(kSize, ReadData(entry, 1, 5000, buffer2.get(), kSize));
1026   EXPECT_TRUE(!memcmp(buffer2->data(), buffer1->data(), kSize));
1027   CacheTestFillBuffer(buffer2->data(), kSize, true);
1028   EXPECT_EQ(kSize, ReadData(entry, 1, 0, buffer2.get(), kSize));
1029   EXPECT_TRUE(!memcmp(buffer2->data(), buffer1->data(), kSize));
1030   CacheTestFillBuffer(buffer2->data(), kSize, true);
1031   EXPECT_EQ(kSize, ReadData(entry, 1, 18000, buffer2.get(), kSize));
1032   EXPECT_TRUE(!memcmp(buffer2->data(), buffer1->data(), kSize));
1033 
1034   // Extend the file some more.
1035   EXPECT_EQ(kSize, WriteData(entry, 1, 23000, buffer1.get(), kSize, false));
1036   entry->Close();
1037 
1038   // And now make sure that we can deal with data in both places (ram/disk).
1039   ASSERT_THAT(OpenEntry(key, &entry), IsOk());
1040   EXPECT_EQ(kSize, WriteData(entry, 1, 17000, buffer1.get(), kSize, false));
1041 
1042   // We should not overwrite the data at 18000 with this.
1043   EXPECT_EQ(kSize, WriteData(entry, 1, 19000, buffer1.get(), kSize, false));
1044   CacheTestFillBuffer(buffer2->data(), kSize, true);
1045   EXPECT_EQ(kSize, ReadData(entry, 1, 18000, buffer2.get(), kSize));
1046   EXPECT_TRUE(!memcmp(buffer2->data(), buffer1->data(), kSize));
1047   CacheTestFillBuffer(buffer2->data(), kSize, true);
1048   EXPECT_EQ(kSize, ReadData(entry, 1, 17000, buffer2.get(), kSize));
1049   EXPECT_TRUE(!memcmp(buffer2->data(), buffer1->data(), kSize));
1050 
1051   EXPECT_EQ(kSize, WriteData(entry, 1, 22900, buffer1.get(), kSize, false));
1052   CacheTestFillBuffer(buffer2->data(), kSize, true);
1053   EXPECT_EQ(100, ReadData(entry, 1, 23000, buffer2.get(), kSize));
1054   EXPECT_TRUE(!memcmp(buffer2->data(), buffer1->data() + 100, 100));
1055 
1056   CacheTestFillBuffer(buffer2->data(), kSize, true);
1057   EXPECT_EQ(100, ReadData(entry, 1, 23100, buffer2.get(), kSize));
1058   EXPECT_TRUE(!memcmp(buffer2->data(), buffer1->data() + 100, 100));
1059 
1060   // Extend the file again and read before without closing the entry.
1061   EXPECT_EQ(kSize, WriteData(entry, 1, 25000, buffer1.get(), kSize, false));
1062   EXPECT_EQ(kSize, WriteData(entry, 1, 45000, buffer1.get(), kSize, false));
1063   CacheTestFillBuffer(buffer2->data(), kSize, true);
1064   EXPECT_EQ(kSize, ReadData(entry, 1, 25000, buffer2.get(), kSize));
1065   EXPECT_TRUE(!memcmp(buffer2->data(), buffer1->data(), kSize));
1066   CacheTestFillBuffer(buffer2->data(), kSize, true);
1067   EXPECT_EQ(kSize, ReadData(entry, 1, 45000, buffer2.get(), kSize));
1068   EXPECT_TRUE(!memcmp(buffer2->data(), buffer1->data(), kSize));
1069 
1070   entry->Close();
1071 }
1072 
TEST_F(DiskCacheEntryTest,Buffering)1073 TEST_F(DiskCacheEntryTest, Buffering) {
1074   InitCache();
1075   Buffering();
1076 }
1077 
TEST_F(DiskCacheEntryTest,BufferingNoBuffer)1078 TEST_F(DiskCacheEntryTest, BufferingNoBuffer) {
1079   InitCache();
1080   cache_impl_->SetFlags(disk_cache::kNoBuffering);
1081   Buffering();
1082 }
1083 
1084 // Checks that entries are zero length when created.
SizeAtCreate()1085 void DiskCacheEntryTest::SizeAtCreate() {
1086   const char key[]  = "the first key";
1087   disk_cache::Entry* entry;
1088   ASSERT_THAT(CreateEntry(key, &entry), IsOk());
1089 
1090   const int kNumStreams = 3;
1091   for (int i = 0; i < kNumStreams; ++i)
1092     EXPECT_EQ(0, entry->GetDataSize(i));
1093   entry->Close();
1094 }
1095 
TEST_F(DiskCacheEntryTest,SizeAtCreate)1096 TEST_F(DiskCacheEntryTest, SizeAtCreate) {
1097   InitCache();
1098   SizeAtCreate();
1099 }
1100 
TEST_F(DiskCacheEntryTest,MemoryOnlySizeAtCreate)1101 TEST_F(DiskCacheEntryTest, MemoryOnlySizeAtCreate) {
1102   SetMemoryOnlyMode();
1103   InitCache();
1104   SizeAtCreate();
1105 }
1106 
1107 // Some extra tests to make sure that buffering works properly when changing
1108 // the entry size.
SizeChanges(int stream_index)1109 void DiskCacheEntryTest::SizeChanges(int stream_index) {
1110   std::string key("the first key");
1111   disk_cache::Entry* entry;
1112   ASSERT_THAT(CreateEntry(key, &entry), IsOk());
1113 
1114   const int kSize = 200;
1115   const char zeros[kSize] = {};
1116   auto buffer1 = base::MakeRefCounted<net::IOBufferWithSize>(kSize);
1117   auto buffer2 = base::MakeRefCounted<net::IOBufferWithSize>(kSize);
1118   CacheTestFillBuffer(buffer1->data(), kSize, true);
1119   CacheTestFillBuffer(buffer2->data(), kSize, true);
1120 
1121   EXPECT_EQ(kSize,
1122             WriteData(entry, stream_index, 0, buffer1.get(), kSize, true));
1123   EXPECT_EQ(kSize,
1124             WriteData(entry, stream_index, 17000, buffer1.get(), kSize, true));
1125   EXPECT_EQ(kSize,
1126             WriteData(entry, stream_index, 23000, buffer1.get(), kSize, true));
1127   entry->Close();
1128 
1129   // Extend the file and read between the old size and the new write.
1130   ASSERT_THAT(OpenEntry(key, &entry), IsOk());
1131   EXPECT_EQ(23000 + kSize, entry->GetDataSize(stream_index));
1132   EXPECT_EQ(kSize,
1133             WriteData(entry, stream_index, 25000, buffer1.get(), kSize, true));
1134   EXPECT_EQ(25000 + kSize, entry->GetDataSize(stream_index));
1135   EXPECT_EQ(kSize, ReadData(entry, stream_index, 24000, buffer2.get(), kSize));
1136   EXPECT_TRUE(!memcmp(buffer2->data(), zeros, kSize));
1137 
1138   // Read at the end of the old file size.
1139   EXPECT_EQ(
1140       kSize,
1141       ReadData(entry, stream_index, 23000 + kSize - 35, buffer2.get(), kSize));
1142   EXPECT_TRUE(!memcmp(buffer2->data(), buffer1->data() + kSize - 35, 35));
1143 
1144   // Read slightly before the last write.
1145   CacheTestFillBuffer(buffer2->data(), kSize, true);
1146   EXPECT_EQ(kSize, ReadData(entry, stream_index, 24900, buffer2.get(), kSize));
1147   EXPECT_TRUE(!memcmp(buffer2->data(), zeros, 100));
1148   EXPECT_TRUE(!memcmp(buffer2->data() + 100, buffer1->data(), kSize - 100));
1149 
1150   // Extend the entry a little more.
1151   EXPECT_EQ(kSize,
1152             WriteData(entry, stream_index, 26000, buffer1.get(), kSize, true));
1153   EXPECT_EQ(26000 + kSize, entry->GetDataSize(stream_index));
1154   CacheTestFillBuffer(buffer2->data(), kSize, true);
1155   EXPECT_EQ(kSize, ReadData(entry, stream_index, 25900, buffer2.get(), kSize));
1156   EXPECT_TRUE(!memcmp(buffer2->data(), zeros, 100));
1157   EXPECT_TRUE(!memcmp(buffer2->data() + 100, buffer1->data(), kSize - 100));
1158 
1159   // And now reduce the size.
1160   EXPECT_EQ(kSize,
1161             WriteData(entry, stream_index, 25000, buffer1.get(), kSize, true));
1162   EXPECT_EQ(25000 + kSize, entry->GetDataSize(stream_index));
1163   EXPECT_EQ(
1164       28,
1165       ReadData(entry, stream_index, 25000 + kSize - 28, buffer2.get(), kSize));
1166   EXPECT_TRUE(!memcmp(buffer2->data(), buffer1->data() + kSize - 28, 28));
1167 
1168   // Reduce the size with a buffer that is not extending the size.
1169   EXPECT_EQ(kSize,
1170             WriteData(entry, stream_index, 24000, buffer1.get(), kSize, false));
1171   EXPECT_EQ(25000 + kSize, entry->GetDataSize(stream_index));
1172   EXPECT_EQ(kSize,
1173             WriteData(entry, stream_index, 24500, buffer1.get(), kSize, true));
1174   EXPECT_EQ(24500 + kSize, entry->GetDataSize(stream_index));
1175   EXPECT_EQ(kSize, ReadData(entry, stream_index, 23900, buffer2.get(), kSize));
1176   EXPECT_TRUE(!memcmp(buffer2->data(), zeros, 100));
1177   EXPECT_TRUE(!memcmp(buffer2->data() + 100, buffer1->data(), kSize - 100));
1178 
1179   // And now reduce the size below the old size.
1180   EXPECT_EQ(kSize,
1181             WriteData(entry, stream_index, 19000, buffer1.get(), kSize, true));
1182   EXPECT_EQ(19000 + kSize, entry->GetDataSize(stream_index));
1183   EXPECT_EQ(kSize, ReadData(entry, stream_index, 18900, buffer2.get(), kSize));
1184   EXPECT_TRUE(!memcmp(buffer2->data(), zeros, 100));
1185   EXPECT_TRUE(!memcmp(buffer2->data() + 100, buffer1->data(), kSize - 100));
1186 
1187   // Verify that the actual file is truncated.
1188   entry->Close();
1189   ASSERT_THAT(OpenEntry(key, &entry), IsOk());
1190   EXPECT_EQ(19000 + kSize, entry->GetDataSize(stream_index));
1191 
1192   // Extend the newly opened file with a zero length write, expect zero fill.
1193   EXPECT_EQ(
1194       0,
1195       WriteData(entry, stream_index, 20000 + kSize, buffer1.get(), 0, false));
1196   EXPECT_EQ(kSize,
1197             ReadData(entry, stream_index, 19000 + kSize, buffer1.get(), kSize));
1198   EXPECT_EQ(0, memcmp(buffer1->data(), zeros, kSize));
1199 
1200   entry->Close();
1201 }
1202 
TEST_F(DiskCacheEntryTest,SizeChanges)1203 TEST_F(DiskCacheEntryTest, SizeChanges) {
1204   InitCache();
1205   SizeChanges(1);
1206 }
1207 
TEST_F(DiskCacheEntryTest,SizeChangesNoBuffer)1208 TEST_F(DiskCacheEntryTest, SizeChangesNoBuffer) {
1209   InitCache();
1210   cache_impl_->SetFlags(disk_cache::kNoBuffering);
1211   SizeChanges(1);
1212 }
1213 
1214 // Write more than the total cache capacity but to a single entry. |size| is the
1215 // amount of bytes to write each time.
ReuseEntry(int size,int stream_index)1216 void DiskCacheEntryTest::ReuseEntry(int size, int stream_index) {
1217   std::string key1("the first key");
1218   disk_cache::Entry* entry;
1219   ASSERT_THAT(CreateEntry(key1, &entry), IsOk());
1220 
1221   entry->Close();
1222   std::string key2("the second key");
1223   ASSERT_THAT(CreateEntry(key2, &entry), IsOk());
1224 
1225   auto buffer = base::MakeRefCounted<net::IOBufferWithSize>(size);
1226   CacheTestFillBuffer(buffer->data(), size, false);
1227 
1228   for (int i = 0; i < 15; i++) {
1229     EXPECT_EQ(0, WriteData(entry, stream_index, 0, buffer.get(), 0, true));
1230     EXPECT_EQ(size,
1231               WriteData(entry, stream_index, 0, buffer.get(), size, false));
1232     entry->Close();
1233     ASSERT_THAT(OpenEntry(key2, &entry), IsOk());
1234   }
1235 
1236   entry->Close();
1237   ASSERT_EQ(net::OK, OpenEntry(key1, &entry)) << "have not evicted this entry";
1238   entry->Close();
1239 }
1240 
TEST_F(DiskCacheEntryTest,ReuseExternalEntry)1241 TEST_F(DiskCacheEntryTest, ReuseExternalEntry) {
1242   SetMaxSize(200 * 1024);
1243   InitCache();
1244   ReuseEntry(20 * 1024, 0);
1245 }
1246 
TEST_F(DiskCacheEntryTest,MemoryOnlyReuseExternalEntry)1247 TEST_F(DiskCacheEntryTest, MemoryOnlyReuseExternalEntry) {
1248   SetMemoryOnlyMode();
1249   SetMaxSize(200 * 1024);
1250   InitCache();
1251   ReuseEntry(20 * 1024, 0);
1252 }
1253 
TEST_F(DiskCacheEntryTest,ReuseInternalEntry)1254 TEST_F(DiskCacheEntryTest, ReuseInternalEntry) {
1255   SetMaxSize(100 * 1024);
1256   InitCache();
1257   ReuseEntry(10 * 1024, 0);
1258 }
1259 
TEST_F(DiskCacheEntryTest,MemoryOnlyReuseInternalEntry)1260 TEST_F(DiskCacheEntryTest, MemoryOnlyReuseInternalEntry) {
1261   SetMemoryOnlyMode();
1262   SetMaxSize(100 * 1024);
1263   InitCache();
1264   ReuseEntry(10 * 1024, 0);
1265 }
1266 
1267 // Reading somewhere that was not written should return zeros.
InvalidData(int stream_index)1268 void DiskCacheEntryTest::InvalidData(int stream_index) {
1269   std::string key("the first key");
1270   disk_cache::Entry* entry;
1271   ASSERT_THAT(CreateEntry(key, &entry), IsOk());
1272 
1273   const int kSize1 = 20000;
1274   const int kSize2 = 20000;
1275   const int kSize3 = 20000;
1276   auto buffer1 = base::MakeRefCounted<net::IOBufferWithSize>(kSize1);
1277   auto buffer2 = base::MakeRefCounted<net::IOBufferWithSize>(kSize2);
1278   auto buffer3 = base::MakeRefCounted<net::IOBufferWithSize>(kSize3);
1279 
1280   CacheTestFillBuffer(buffer1->data(), kSize1, false);
1281   memset(buffer2->data(), 0, kSize2);
1282 
1283   // Simple data grow:
1284   EXPECT_EQ(200,
1285             WriteData(entry, stream_index, 400, buffer1.get(), 200, false));
1286   EXPECT_EQ(600, entry->GetDataSize(stream_index));
1287   EXPECT_EQ(100, ReadData(entry, stream_index, 300, buffer3.get(), 100));
1288   EXPECT_TRUE(!memcmp(buffer3->data(), buffer2->data(), 100));
1289   entry->Close();
1290   ASSERT_THAT(OpenEntry(key, &entry), IsOk());
1291 
1292   // The entry is now on disk. Load it and extend it.
1293   EXPECT_EQ(200,
1294             WriteData(entry, stream_index, 800, buffer1.get(), 200, false));
1295   EXPECT_EQ(1000, entry->GetDataSize(stream_index));
1296   EXPECT_EQ(100, ReadData(entry, stream_index, 700, buffer3.get(), 100));
1297   EXPECT_TRUE(!memcmp(buffer3->data(), buffer2->data(), 100));
1298   entry->Close();
1299   ASSERT_THAT(OpenEntry(key, &entry), IsOk());
1300 
1301   // This time using truncate.
1302   EXPECT_EQ(200,
1303             WriteData(entry, stream_index, 1800, buffer1.get(), 200, true));
1304   EXPECT_EQ(2000, entry->GetDataSize(stream_index));
1305   EXPECT_EQ(100, ReadData(entry, stream_index, 1500, buffer3.get(), 100));
1306   EXPECT_TRUE(!memcmp(buffer3->data(), buffer2->data(), 100));
1307 
1308   // Go to an external file.
1309   EXPECT_EQ(200,
1310             WriteData(entry, stream_index, 19800, buffer1.get(), 200, false));
1311   EXPECT_EQ(20000, entry->GetDataSize(stream_index));
1312   EXPECT_EQ(4000, ReadData(entry, stream_index, 14000, buffer3.get(), 4000));
1313   EXPECT_TRUE(!memcmp(buffer3->data(), buffer2->data(), 4000));
1314 
1315   // And back to an internal block.
1316   EXPECT_EQ(600,
1317             WriteData(entry, stream_index, 1000, buffer1.get(), 600, true));
1318   EXPECT_EQ(1600, entry->GetDataSize(stream_index));
1319   EXPECT_EQ(600, ReadData(entry, stream_index, 1000, buffer3.get(), 600));
1320   EXPECT_TRUE(!memcmp(buffer3->data(), buffer1->data(), 600));
1321 
1322   // Extend it again.
1323   EXPECT_EQ(600,
1324             WriteData(entry, stream_index, 2000, buffer1.get(), 600, false));
1325   EXPECT_EQ(2600, entry->GetDataSize(stream_index));
1326   EXPECT_EQ(200, ReadData(entry, stream_index, 1800, buffer3.get(), 200));
1327   EXPECT_TRUE(!memcmp(buffer3->data(), buffer2->data(), 200));
1328 
1329   // And again (with truncation flag).
1330   EXPECT_EQ(600,
1331             WriteData(entry, stream_index, 3000, buffer1.get(), 600, true));
1332   EXPECT_EQ(3600, entry->GetDataSize(stream_index));
1333   EXPECT_EQ(200, ReadData(entry, stream_index, 2800, buffer3.get(), 200));
1334   EXPECT_TRUE(!memcmp(buffer3->data(), buffer2->data(), 200));
1335 
1336   entry->Close();
1337 }
1338 
TEST_F(DiskCacheEntryTest,InvalidData)1339 TEST_F(DiskCacheEntryTest, InvalidData) {
1340   InitCache();
1341   InvalidData(0);
1342 }
1343 
TEST_F(DiskCacheEntryTest,InvalidDataNoBuffer)1344 TEST_F(DiskCacheEntryTest, InvalidDataNoBuffer) {
1345   InitCache();
1346   cache_impl_->SetFlags(disk_cache::kNoBuffering);
1347   InvalidData(0);
1348 }
1349 
TEST_F(DiskCacheEntryTest,MemoryOnlyInvalidData)1350 TEST_F(DiskCacheEntryTest, MemoryOnlyInvalidData) {
1351   SetMemoryOnlyMode();
1352   InitCache();
1353   InvalidData(0);
1354 }
1355 
1356 // Tests that the cache preserves the buffer of an IO operation.
ReadWriteDestroyBuffer(int stream_index)1357 void DiskCacheEntryTest::ReadWriteDestroyBuffer(int stream_index) {
1358   std::string key("the first key");
1359   disk_cache::Entry* entry;
1360   ASSERT_THAT(CreateEntry(key, &entry), IsOk());
1361 
1362   const int kSize = 200;
1363   auto buffer = base::MakeRefCounted<net::IOBufferWithSize>(kSize);
1364   CacheTestFillBuffer(buffer->data(), kSize, false);
1365 
1366   net::TestCompletionCallback cb;
1367   EXPECT_EQ(net::ERR_IO_PENDING,
1368             entry->WriteData(
1369                 stream_index, 0, buffer.get(), kSize, cb.callback(), false));
1370 
1371   // Release our reference to the buffer.
1372   buffer = nullptr;
1373   EXPECT_EQ(kSize, cb.WaitForResult());
1374 
1375   // And now test with a Read().
1376   buffer = base::MakeRefCounted<net::IOBufferWithSize>(kSize);
1377   CacheTestFillBuffer(buffer->data(), kSize, false);
1378 
1379   EXPECT_EQ(
1380       net::ERR_IO_PENDING,
1381       entry->ReadData(stream_index, 0, buffer.get(), kSize, cb.callback()));
1382   buffer = nullptr;
1383   EXPECT_EQ(kSize, cb.WaitForResult());
1384 
1385   entry->Close();
1386 }
1387 
TEST_F(DiskCacheEntryTest,ReadWriteDestroyBuffer)1388 TEST_F(DiskCacheEntryTest, ReadWriteDestroyBuffer) {
1389   InitCache();
1390   ReadWriteDestroyBuffer(0);
1391 }
1392 
DoomNormalEntry()1393 void DiskCacheEntryTest::DoomNormalEntry() {
1394   std::string key("the first key");
1395   disk_cache::Entry* entry;
1396   ASSERT_THAT(CreateEntry(key, &entry), IsOk());
1397   entry->Doom();
1398   entry->Close();
1399 
1400   const int kSize = 20000;
1401   auto buffer = base::MakeRefCounted<net::IOBufferWithSize>(kSize);
1402   CacheTestFillBuffer(buffer->data(), kSize, true);
1403   buffer->data()[19999] = '\0';
1404 
1405   key = buffer->data();
1406   ASSERT_THAT(CreateEntry(key, &entry), IsOk());
1407   EXPECT_EQ(20000, WriteData(entry, 0, 0, buffer.get(), kSize, false));
1408   EXPECT_EQ(20000, WriteData(entry, 1, 0, buffer.get(), kSize, false));
1409   entry->Doom();
1410   entry->Close();
1411 
1412   FlushQueueForTest();
1413   EXPECT_EQ(0, cache_->GetEntryCount());
1414 }
1415 
TEST_F(DiskCacheEntryTest,DoomEntry)1416 TEST_F(DiskCacheEntryTest, DoomEntry) {
1417   InitCache();
1418   DoomNormalEntry();
1419 }
1420 
TEST_F(DiskCacheEntryTest,MemoryOnlyDoomEntry)1421 TEST_F(DiskCacheEntryTest, MemoryOnlyDoomEntry) {
1422   SetMemoryOnlyMode();
1423   InitCache();
1424   DoomNormalEntry();
1425 }
1426 
1427 // Tests dooming an entry that's linked to an open entry.
DoomEntryNextToOpenEntry()1428 void DiskCacheEntryTest::DoomEntryNextToOpenEntry() {
1429   disk_cache::Entry* entry1;
1430   disk_cache::Entry* entry2;
1431   ASSERT_THAT(CreateEntry("fixed", &entry1), IsOk());
1432   entry1->Close();
1433   ASSERT_THAT(CreateEntry("foo", &entry1), IsOk());
1434   entry1->Close();
1435   ASSERT_THAT(CreateEntry("bar", &entry1), IsOk());
1436   entry1->Close();
1437 
1438   ASSERT_THAT(OpenEntry("foo", &entry1), IsOk());
1439   ASSERT_THAT(OpenEntry("bar", &entry2), IsOk());
1440   entry2->Doom();
1441   entry2->Close();
1442 
1443   ASSERT_THAT(OpenEntry("foo", &entry2), IsOk());
1444   entry2->Doom();
1445   entry2->Close();
1446   entry1->Close();
1447 
1448   ASSERT_THAT(OpenEntry("fixed", &entry1), IsOk());
1449   entry1->Close();
1450 }
1451 
TEST_F(DiskCacheEntryTest,DoomEntryNextToOpenEntry)1452 TEST_F(DiskCacheEntryTest, DoomEntryNextToOpenEntry) {
1453   InitCache();
1454   DoomEntryNextToOpenEntry();
1455 }
1456 
TEST_F(DiskCacheEntryTest,NewEvictionDoomEntryNextToOpenEntry)1457 TEST_F(DiskCacheEntryTest, NewEvictionDoomEntryNextToOpenEntry) {
1458   SetNewEviction();
1459   InitCache();
1460   DoomEntryNextToOpenEntry();
1461 }
1462 
TEST_F(DiskCacheEntryTest,AppCacheDoomEntryNextToOpenEntry)1463 TEST_F(DiskCacheEntryTest, AppCacheDoomEntryNextToOpenEntry) {
1464   SetCacheType(net::APP_CACHE);
1465   InitCache();
1466   DoomEntryNextToOpenEntry();
1467 }
1468 
1469 // Verify that basic operations work as expected with doomed entries.
DoomedEntry(int stream_index)1470 void DiskCacheEntryTest::DoomedEntry(int stream_index) {
1471   std::string key("the first key");
1472   disk_cache::Entry* entry;
1473   ASSERT_THAT(CreateEntry(key, &entry), IsOk());
1474   entry->Doom();
1475 
1476   FlushQueueForTest();
1477   EXPECT_EQ(0, cache_->GetEntryCount());
1478   Time initial = Time::Now();
1479   AddDelay();
1480 
1481   const int kSize1 = 2000;
1482   const int kSize2 = 2000;
1483   auto buffer1 = base::MakeRefCounted<net::IOBufferWithSize>(kSize1);
1484   auto buffer2 = base::MakeRefCounted<net::IOBufferWithSize>(kSize2);
1485   CacheTestFillBuffer(buffer1->data(), kSize1, false);
1486   memset(buffer2->data(), 0, kSize2);
1487 
1488   EXPECT_EQ(2000,
1489             WriteData(entry, stream_index, 0, buffer1.get(), 2000, false));
1490   EXPECT_EQ(2000, ReadData(entry, stream_index, 0, buffer2.get(), 2000));
1491   EXPECT_EQ(0, memcmp(buffer1->data(), buffer2->data(), kSize1));
1492   EXPECT_EQ(key, entry->GetKey());
1493   EXPECT_TRUE(initial < entry->GetLastModified());
1494   EXPECT_TRUE(initial < entry->GetLastUsed());
1495 
1496   entry->Close();
1497 }
1498 
TEST_F(DiskCacheEntryTest,DoomedEntry)1499 TEST_F(DiskCacheEntryTest, DoomedEntry) {
1500   InitCache();
1501   DoomedEntry(0);
1502 }
1503 
TEST_F(DiskCacheEntryTest,MemoryOnlyDoomedEntry)1504 TEST_F(DiskCacheEntryTest, MemoryOnlyDoomedEntry) {
1505   SetMemoryOnlyMode();
1506   InitCache();
1507   DoomedEntry(0);
1508 }
1509 
1510 // Tests that we discard entries if the data is missing.
TEST_F(DiskCacheEntryTest,MissingData)1511 TEST_F(DiskCacheEntryTest, MissingData) {
1512   InitCache();
1513 
1514   std::string key("the first key");
1515   disk_cache::Entry* entry;
1516   ASSERT_THAT(CreateEntry(key, &entry), IsOk());
1517 
1518   // Write to an external file.
1519   const int kSize = 20000;
1520   auto buffer = base::MakeRefCounted<net::IOBufferWithSize>(kSize);
1521   CacheTestFillBuffer(buffer->data(), kSize, false);
1522   EXPECT_EQ(kSize, WriteData(entry, 0, 0, buffer.get(), kSize, false));
1523   entry->Close();
1524   FlushQueueForTest();
1525 
1526   disk_cache::Addr address(0x80000001);
1527   base::FilePath name = cache_impl_->GetFileName(address);
1528   EXPECT_TRUE(base::DeleteFile(name));
1529 
1530   // Attempt to read the data.
1531   ASSERT_THAT(OpenEntry(key, &entry), IsOk());
1532   EXPECT_EQ(net::ERR_FILE_NOT_FOUND,
1533             ReadData(entry, 0, 0, buffer.get(), kSize));
1534   entry->Close();
1535 
1536   // The entry should be gone.
1537   ASSERT_NE(net::OK, OpenEntry(key, &entry));
1538 }
1539 
1540 // Test that child entries in a memory cache backend are not visible from
1541 // enumerations.
TEST_F(DiskCacheEntryTest,MemoryOnlyEnumerationWithSparseEntries)1542 TEST_F(DiskCacheEntryTest, MemoryOnlyEnumerationWithSparseEntries) {
1543   SetMemoryOnlyMode();
1544   InitCache();
1545 
1546   const int kSize = 4096;
1547   auto buf = base::MakeRefCounted<net::IOBufferWithSize>(kSize);
1548   CacheTestFillBuffer(buf->data(), kSize, false);
1549 
1550   std::string key("the first key");
1551   disk_cache::Entry* parent_entry;
1552   ASSERT_THAT(CreateEntry(key, &parent_entry), IsOk());
1553 
1554   // Writes to the parent entry.
1555   EXPECT_EQ(kSize, parent_entry->WriteSparseData(
1556                        0, buf.get(), kSize, net::CompletionOnceCallback()));
1557 
1558   // This write creates a child entry and writes to it.
1559   EXPECT_EQ(kSize, parent_entry->WriteSparseData(
1560                        8192, buf.get(), kSize, net::CompletionOnceCallback()));
1561 
1562   parent_entry->Close();
1563 
1564   // Perform the enumerations.
1565   std::unique_ptr<TestIterator> iter = CreateIterator();
1566   disk_cache::Entry* entry = nullptr;
1567   int count = 0;
1568   while (iter->OpenNextEntry(&entry) == net::OK) {
1569     ASSERT_TRUE(entry != nullptr);
1570     ++count;
1571     disk_cache::MemEntryImpl* mem_entry =
1572         reinterpret_cast<disk_cache::MemEntryImpl*>(entry);
1573     EXPECT_EQ(disk_cache::MemEntryImpl::EntryType::kParent, mem_entry->type());
1574     mem_entry->Close();
1575   }
1576   EXPECT_EQ(1, count);
1577 }
1578 
1579 // Writes |buf_1| to offset and reads it back as |buf_2|.
VerifySparseIO(disk_cache::Entry * entry,int64_t offset,net::IOBuffer * buf_1,int size,net::IOBuffer * buf_2)1580 void VerifySparseIO(disk_cache::Entry* entry,
1581                     int64_t offset,
1582                     net::IOBuffer* buf_1,
1583                     int size,
1584                     net::IOBuffer* buf_2) {
1585   net::TestCompletionCallback cb;
1586 
1587   memset(buf_2->data(), 0, size);
1588   int ret = entry->ReadSparseData(offset, buf_2, size, cb.callback());
1589   EXPECT_EQ(0, cb.GetResult(ret));
1590 
1591   ret = entry->WriteSparseData(offset, buf_1, size, cb.callback());
1592   EXPECT_EQ(size, cb.GetResult(ret));
1593 
1594   ret = entry->ReadSparseData(offset, buf_2, size, cb.callback());
1595   EXPECT_EQ(size, cb.GetResult(ret));
1596 
1597   EXPECT_EQ(0, memcmp(buf_1->data(), buf_2->data(), size));
1598 }
1599 
1600 // Reads |size| bytes from |entry| at |offset| and verifies that they are the
1601 // same as the content of the provided |buffer|.
VerifyContentSparseIO(disk_cache::Entry * entry,int64_t offset,char * buffer,int size)1602 void VerifyContentSparseIO(disk_cache::Entry* entry,
1603                            int64_t offset,
1604                            char* buffer,
1605                            int size) {
1606   net::TestCompletionCallback cb;
1607 
1608   auto buf_1 = base::MakeRefCounted<net::IOBufferWithSize>(size);
1609   memset(buf_1->data(), 0, size);
1610   int ret = entry->ReadSparseData(offset, buf_1.get(), size, cb.callback());
1611   EXPECT_EQ(size, cb.GetResult(ret));
1612   EXPECT_EQ(0, memcmp(buf_1->data(), buffer, size));
1613 }
1614 
BasicSparseIO()1615 void DiskCacheEntryTest::BasicSparseIO() {
1616   std::string key("the first key");
1617   disk_cache::Entry* entry;
1618   ASSERT_THAT(CreateEntry(key, &entry), IsOk());
1619 
1620   const int kSize = 2048;
1621   auto buf_1 = base::MakeRefCounted<net::IOBufferWithSize>(kSize);
1622   auto buf_2 = base::MakeRefCounted<net::IOBufferWithSize>(kSize);
1623   CacheTestFillBuffer(buf_1->data(), kSize, false);
1624 
1625   // Write at offset 0.
1626   VerifySparseIO(entry, 0, buf_1.get(), kSize, buf_2.get());
1627 
1628   // Write at offset 0x400000 (4 MB).
1629   VerifySparseIO(entry, 0x400000, buf_1.get(), kSize, buf_2.get());
1630 
1631   // Write at offset 0x800000000 (32 GB).
1632   VerifySparseIO(entry, 0x800000000LL, buf_1.get(), kSize, buf_2.get());
1633 
1634   entry->Close();
1635 
1636   // Check everything again.
1637   ASSERT_THAT(OpenEntry(key, &entry), IsOk());
1638   VerifyContentSparseIO(entry, 0, buf_1->data(), kSize);
1639   VerifyContentSparseIO(entry, 0x400000, buf_1->data(), kSize);
1640   VerifyContentSparseIO(entry, 0x800000000LL, buf_1->data(), kSize);
1641   entry->Close();
1642 }
1643 
TEST_F(DiskCacheEntryTest,BasicSparseIO)1644 TEST_F(DiskCacheEntryTest, BasicSparseIO) {
1645   InitCache();
1646   BasicSparseIO();
1647 }
1648 
TEST_F(DiskCacheEntryTest,MemoryOnlyBasicSparseIO)1649 TEST_F(DiskCacheEntryTest, MemoryOnlyBasicSparseIO) {
1650   SetMemoryOnlyMode();
1651   InitCache();
1652   BasicSparseIO();
1653 }
1654 
HugeSparseIO()1655 void DiskCacheEntryTest::HugeSparseIO() {
1656   std::string key("the first key");
1657   disk_cache::Entry* entry;
1658   ASSERT_THAT(CreateEntry(key, &entry), IsOk());
1659 
1660   // Write 1.2 MB so that we cover multiple entries.
1661   const int kSize = 1200 * 1024;
1662   auto buf_1 = base::MakeRefCounted<net::IOBufferWithSize>(kSize);
1663   auto buf_2 = base::MakeRefCounted<net::IOBufferWithSize>(kSize);
1664   CacheTestFillBuffer(buf_1->data(), kSize, false);
1665 
1666   // Write at offset 0x20F0000 (33 MB - 64 KB).
1667   VerifySparseIO(entry, 0x20F0000, buf_1.get(), kSize, buf_2.get());
1668   entry->Close();
1669 
1670   // Check it again.
1671   ASSERT_THAT(OpenEntry(key, &entry), IsOk());
1672   VerifyContentSparseIO(entry, 0x20F0000, buf_1->data(), kSize);
1673   entry->Close();
1674 }
1675 
TEST_F(DiskCacheEntryTest,HugeSparseIO)1676 TEST_F(DiskCacheEntryTest, HugeSparseIO) {
1677   InitCache();
1678   HugeSparseIO();
1679 }
1680 
TEST_F(DiskCacheEntryTest,MemoryOnlyHugeSparseIO)1681 TEST_F(DiskCacheEntryTest, MemoryOnlyHugeSparseIO) {
1682   SetMemoryOnlyMode();
1683   InitCache();
1684   HugeSparseIO();
1685 }
1686 
GetAvailableRangeTest()1687 void DiskCacheEntryTest::GetAvailableRangeTest() {
1688   std::string key("the first key");
1689   disk_cache::Entry* entry;
1690   ASSERT_THAT(CreateEntry(key, &entry), IsOk());
1691 
1692   const int kSize = 16 * 1024;
1693   auto buf = base::MakeRefCounted<net::IOBufferWithSize>(kSize);
1694   CacheTestFillBuffer(buf->data(), kSize, false);
1695 
1696   // Write at offset 0x20F0000 (33 MB - 64 KB), and 0x20F4400 (33 MB - 47 KB).
1697   EXPECT_EQ(kSize, WriteSparseData(entry, 0x20F0000, buf.get(), kSize));
1698   EXPECT_EQ(kSize, WriteSparseData(entry, 0x20F4400, buf.get(), kSize));
1699 
1700   // We stop at the first empty block.
1701   TestRangeResultCompletionCallback cb;
1702   RangeResult result = cb.GetResult(
1703       entry->GetAvailableRange(0x20F0000, kSize * 2, cb.callback()));
1704   EXPECT_EQ(net::OK, result.net_error);
1705   EXPECT_EQ(kSize, result.available_len);
1706   EXPECT_EQ(0x20F0000, result.start);
1707 
1708   result = cb.GetResult(entry->GetAvailableRange(0, kSize, cb.callback()));
1709   EXPECT_EQ(net::OK, result.net_error);
1710   EXPECT_EQ(0, result.available_len);
1711 
1712   result = cb.GetResult(
1713       entry->GetAvailableRange(0x20F0000 - kSize, kSize, cb.callback()));
1714   EXPECT_EQ(net::OK, result.net_error);
1715   EXPECT_EQ(0, result.available_len);
1716 
1717   result = cb.GetResult(entry->GetAvailableRange(0, 0x2100000, cb.callback()));
1718   EXPECT_EQ(net::OK, result.net_error);
1719   EXPECT_EQ(kSize, result.available_len);
1720   EXPECT_EQ(0x20F0000, result.start);
1721 
1722   // We should be able to Read based on the results of GetAvailableRange.
1723   net::TestCompletionCallback read_cb;
1724   result =
1725       cb.GetResult(entry->GetAvailableRange(0x2100000, kSize, cb.callback()));
1726   EXPECT_EQ(net::OK, result.net_error);
1727   EXPECT_EQ(0, result.available_len);
1728   int rv =
1729       entry->ReadSparseData(result.start, buf.get(), kSize, read_cb.callback());
1730   EXPECT_EQ(0, read_cb.GetResult(rv));
1731 
1732   result =
1733       cb.GetResult(entry->GetAvailableRange(0x20F2000, kSize, cb.callback()));
1734   EXPECT_EQ(net::OK, result.net_error);
1735   EXPECT_EQ(0x2000, result.available_len);
1736   EXPECT_EQ(0x20F2000, result.start);
1737   EXPECT_EQ(0x2000, ReadSparseData(entry, result.start, buf.get(), kSize));
1738 
1739   // Make sure that we respect the |len| argument.
1740   result = cb.GetResult(
1741       entry->GetAvailableRange(0x20F0001 - kSize, kSize, cb.callback()));
1742   EXPECT_EQ(net::OK, result.net_error);
1743   EXPECT_EQ(1, result.available_len);
1744   EXPECT_EQ(0x20F0000, result.start);
1745 
1746   // Use very small ranges. Write at offset 50.
1747   const int kTinyLen = 10;
1748   EXPECT_EQ(kTinyLen, WriteSparseData(entry, 50, buf.get(), kTinyLen));
1749 
1750   result = cb.GetResult(
1751       entry->GetAvailableRange(kTinyLen * 2, kTinyLen, cb.callback()));
1752   EXPECT_EQ(net::OK, result.net_error);
1753   EXPECT_EQ(0, result.available_len);
1754   EXPECT_EQ(kTinyLen * 2, result.start);
1755 
1756   // Get a huge range with maximum boundary
1757   result = cb.GetResult(entry->GetAvailableRange(
1758       0x2100000, std::numeric_limits<int32_t>::max(), cb.callback()));
1759   EXPECT_EQ(net::OK, result.net_error);
1760   EXPECT_EQ(0, result.available_len);
1761 
1762   entry->Close();
1763 }
1764 
TEST_F(DiskCacheEntryTest,GetAvailableRange)1765 TEST_F(DiskCacheEntryTest, GetAvailableRange) {
1766   InitCache();
1767   GetAvailableRangeTest();
1768 }
1769 
TEST_F(DiskCacheEntryTest,MemoryOnlyGetAvailableRange)1770 TEST_F(DiskCacheEntryTest, MemoryOnlyGetAvailableRange) {
1771   SetMemoryOnlyMode();
1772   InitCache();
1773   GetAvailableRangeTest();
1774 }
1775 
TEST_F(DiskCacheEntryTest,GetAvailableRangeBlockFileDiscontinuous)1776 TEST_F(DiskCacheEntryTest, GetAvailableRangeBlockFileDiscontinuous) {
1777   // crbug.com/791056 --- blockfile problem when there is a sub-KiB write before
1778   // a bunch of full 1KiB blocks, and a GetAvailableRange is issued to which
1779   // both are a potentially relevant.
1780   InitCache();
1781 
1782   std::string key("the first key");
1783   disk_cache::Entry* entry;
1784   ASSERT_THAT(CreateEntry(key, &entry), IsOk());
1785 
1786   auto buf_2k = base::MakeRefCounted<net::IOBufferWithSize>(2 * 1024);
1787   CacheTestFillBuffer(buf_2k->data(), 2 * 1024, false);
1788 
1789   const int kSmallSize = 612;  // sub-1k
1790   auto buf_small = base::MakeRefCounted<net::IOBufferWithSize>(kSmallSize);
1791   CacheTestFillBuffer(buf_small->data(), kSmallSize, false);
1792 
1793   // Sets some bits for blocks representing 1K ranges [1024, 3072),
1794   // which will be relevant for the next GetAvailableRange call.
1795   EXPECT_EQ(2 * 1024, WriteSparseData(entry, /* offset = */ 1024, buf_2k.get(),
1796                                       /* size = */ 2 * 1024));
1797 
1798   // Now record a partial write from start of the first kb.
1799   EXPECT_EQ(kSmallSize, WriteSparseData(entry, /* offset = */ 0,
1800                                         buf_small.get(), kSmallSize));
1801 
1802   // Try to query a range starting from that block 0.
1803   // The cache tracks: [0, 612) [1024, 3072).
1804   // The request is for: [812, 2059) so response should be [1024, 2059), which
1805   // has length = 1035. Previously this return a negative number for rv.
1806   TestRangeResultCompletionCallback cb;
1807   RangeResult result =
1808       cb.GetResult(entry->GetAvailableRange(812, 1247, cb.callback()));
1809   EXPECT_EQ(net::OK, result.net_error);
1810   EXPECT_EQ(1035, result.available_len);
1811   EXPECT_EQ(1024, result.start);
1812 
1813   // Now query [512, 1536). This matches both [512, 612) and [1024, 1536),
1814   // so this should return [512, 612).
1815   result = cb.GetResult(entry->GetAvailableRange(512, 1024, cb.callback()));
1816   EXPECT_EQ(net::OK, result.net_error);
1817   EXPECT_EQ(100, result.available_len);
1818   EXPECT_EQ(512, result.start);
1819 
1820   // Now query next portion, [612, 1636). This now just should produce
1821   // [1024, 1636)
1822   result = cb.GetResult(entry->GetAvailableRange(612, 1024, cb.callback()));
1823   EXPECT_EQ(net::OK, result.net_error);
1824   EXPECT_EQ(612, result.available_len);
1825   EXPECT_EQ(1024, result.start);
1826 
1827   // Do a continuous small write, this one at [3072, 3684).
1828   // This means the cache tracks [1024, 3072) via bitmaps and [3072, 3684)
1829   // as the last write.
1830   EXPECT_EQ(kSmallSize, WriteSparseData(entry, /* offset = */ 3072,
1831                                         buf_small.get(), kSmallSize));
1832 
1833   // Query [2048, 4096). Should get [2048, 3684)
1834   result = cb.GetResult(entry->GetAvailableRange(2048, 2048, cb.callback()));
1835   EXPECT_EQ(net::OK, result.net_error);
1836   EXPECT_EQ(1636, result.available_len);
1837   EXPECT_EQ(2048, result.start);
1838 
1839   // Now write at [4096, 4708). Since only one sub-kb thing is tracked, this
1840   // now tracks  [1024, 3072) via bitmaps and [4096, 4708) as the last write.
1841   EXPECT_EQ(kSmallSize, WriteSparseData(entry, /* offset = */ 4096,
1842                                         buf_small.get(), kSmallSize));
1843 
1844   // Query [2048, 4096). Should get [2048, 3072)
1845   result = cb.GetResult(entry->GetAvailableRange(2048, 2048, cb.callback()));
1846   EXPECT_EQ(net::OK, result.net_error);
1847   EXPECT_EQ(1024, result.available_len);
1848   EXPECT_EQ(2048, result.start);
1849 
1850   // Query 2K more after that: [3072, 5120). Should get [4096, 4708)
1851   result = cb.GetResult(entry->GetAvailableRange(3072, 2048, cb.callback()));
1852   EXPECT_EQ(net::OK, result.net_error);
1853   EXPECT_EQ(612, result.available_len);
1854   EXPECT_EQ(4096, result.start);
1855 
1856   // Also double-check that offsets within later children are correctly
1857   // computed.
1858   EXPECT_EQ(kSmallSize, WriteSparseData(entry, /* offset = */ 0x200400,
1859                                         buf_small.get(), kSmallSize));
1860   result =
1861       cb.GetResult(entry->GetAvailableRange(0x100000, 0x200000, cb.callback()));
1862   EXPECT_EQ(net::OK, result.net_error);
1863   EXPECT_EQ(kSmallSize, result.available_len);
1864   EXPECT_EQ(0x200400, result.start);
1865 
1866   entry->Close();
1867 }
1868 
1869 // Tests that non-sequential writes that are not aligned with the minimum sparse
1870 // data granularity (1024 bytes) do in fact result in dropped data.
TEST_F(DiskCacheEntryTest,SparseWriteDropped)1871 TEST_F(DiskCacheEntryTest, SparseWriteDropped) {
1872   InitCache();
1873   std::string key("the first key");
1874   disk_cache::Entry* entry;
1875   ASSERT_THAT(CreateEntry(key, &entry), IsOk());
1876 
1877   const int kSize = 180;
1878   auto buf_1 = base::MakeRefCounted<net::IOBufferWithSize>(kSize);
1879   auto buf_2 = base::MakeRefCounted<net::IOBufferWithSize>(kSize);
1880   CacheTestFillBuffer(buf_1->data(), kSize, false);
1881 
1882   // Do small writes (180 bytes) that get increasingly close to a 1024-byte
1883   // boundary. All data should be dropped until a boundary is crossed, at which
1884   // point the data after the boundary is saved (at least for a while).
1885   int offset = 1024 - 500;
1886   int rv = 0;
1887   net::TestCompletionCallback cb;
1888   TestRangeResultCompletionCallback range_cb;
1889   RangeResult result;
1890   for (int i = 0; i < 5; i++) {
1891     // Check result of last GetAvailableRange.
1892     EXPECT_EQ(0, result.available_len);
1893 
1894     rv = entry->WriteSparseData(offset, buf_1.get(), kSize, cb.callback());
1895     EXPECT_EQ(kSize, cb.GetResult(rv));
1896 
1897     result = range_cb.GetResult(
1898         entry->GetAvailableRange(offset - 100, kSize, range_cb.callback()));
1899     EXPECT_EQ(net::OK, result.net_error);
1900     EXPECT_EQ(0, result.available_len);
1901 
1902     result = range_cb.GetResult(
1903         entry->GetAvailableRange(offset, kSize, range_cb.callback()));
1904     if (!result.available_len) {
1905       rv = entry->ReadSparseData(offset, buf_2.get(), kSize, cb.callback());
1906       EXPECT_EQ(0, cb.GetResult(rv));
1907     }
1908     offset += 1024 * i + 100;
1909   }
1910 
1911   // The last write started 100 bytes below a bundary, so there should be 80
1912   // bytes after the boundary.
1913   EXPECT_EQ(80, result.available_len);
1914   EXPECT_EQ(1024 * 7, result.start);
1915   rv = entry->ReadSparseData(result.start, buf_2.get(), kSize, cb.callback());
1916   EXPECT_EQ(80, cb.GetResult(rv));
1917   EXPECT_EQ(0, memcmp(buf_1.get()->data() + 100, buf_2.get()->data(), 80));
1918 
1919   // And even that part is dropped when another write changes the offset.
1920   offset = result.start;
1921   rv = entry->WriteSparseData(0, buf_1.get(), kSize, cb.callback());
1922   EXPECT_EQ(kSize, cb.GetResult(rv));
1923 
1924   result = range_cb.GetResult(
1925       entry->GetAvailableRange(offset, kSize, range_cb.callback()));
1926   EXPECT_EQ(net::OK, result.net_error);
1927   EXPECT_EQ(0, result.available_len);
1928   entry->Close();
1929 }
1930 
1931 // Tests that small sequential writes are not dropped.
TEST_F(DiskCacheEntryTest,SparseSquentialWriteNotDropped)1932 TEST_F(DiskCacheEntryTest, SparseSquentialWriteNotDropped) {
1933   InitCache();
1934   std::string key("the first key");
1935   disk_cache::Entry* entry;
1936   ASSERT_THAT(CreateEntry(key, &entry), IsOk());
1937 
1938   const int kSize = 180;
1939   auto buf_1 = base::MakeRefCounted<net::IOBufferWithSize>(kSize);
1940   auto buf_2 = base::MakeRefCounted<net::IOBufferWithSize>(kSize);
1941   CacheTestFillBuffer(buf_1->data(), kSize, false);
1942 
1943   // Any starting offset is fine as long as it is 1024-bytes aligned.
1944   int rv = 0;
1945   RangeResult result;
1946   net::TestCompletionCallback cb;
1947   TestRangeResultCompletionCallback range_cb;
1948   int64_t offset = 1024 * 11;
1949   for (; offset < 20000; offset += kSize) {
1950     rv = entry->WriteSparseData(offset, buf_1.get(), kSize, cb.callback());
1951     EXPECT_EQ(kSize, cb.GetResult(rv));
1952 
1953     result = range_cb.GetResult(
1954         entry->GetAvailableRange(offset, kSize, range_cb.callback()));
1955     EXPECT_EQ(net::OK, result.net_error);
1956     EXPECT_EQ(kSize, result.available_len);
1957     EXPECT_EQ(offset, result.start);
1958 
1959     rv = entry->ReadSparseData(offset, buf_2.get(), kSize, cb.callback());
1960     EXPECT_EQ(kSize, cb.GetResult(rv));
1961     EXPECT_EQ(0, memcmp(buf_1.get()->data(), buf_2.get()->data(), kSize));
1962   }
1963 
1964   entry->Close();
1965   FlushQueueForTest();
1966 
1967   // Verify again the last write made.
1968   ASSERT_THAT(OpenEntry(key, &entry), IsOk());
1969   offset -= kSize;
1970   result = range_cb.GetResult(
1971       entry->GetAvailableRange(offset, kSize, range_cb.callback()));
1972   EXPECT_EQ(net::OK, result.net_error);
1973   EXPECT_EQ(kSize, result.available_len);
1974   EXPECT_EQ(offset, result.start);
1975 
1976   rv = entry->ReadSparseData(offset, buf_2.get(), kSize, cb.callback());
1977   EXPECT_EQ(kSize, cb.GetResult(rv));
1978   EXPECT_EQ(0, memcmp(buf_1.get()->data(), buf_2.get()->data(), kSize));
1979 
1980   entry->Close();
1981 }
1982 
CouldBeSparse()1983 void DiskCacheEntryTest::CouldBeSparse() {
1984   std::string key("the first key");
1985   disk_cache::Entry* entry;
1986   ASSERT_THAT(CreateEntry(key, &entry), IsOk());
1987 
1988   const int kSize = 16 * 1024;
1989   auto buf = base::MakeRefCounted<net::IOBufferWithSize>(kSize);
1990   CacheTestFillBuffer(buf->data(), kSize, false);
1991 
1992   // Write at offset 0x20F0000 (33 MB - 64 KB).
1993   EXPECT_EQ(kSize, WriteSparseData(entry, 0x20F0000, buf.get(), kSize));
1994 
1995   EXPECT_TRUE(entry->CouldBeSparse());
1996   entry->Close();
1997 
1998   ASSERT_THAT(OpenEntry(key, &entry), IsOk());
1999   EXPECT_TRUE(entry->CouldBeSparse());
2000   entry->Close();
2001 
2002   // Now verify a regular entry.
2003   key.assign("another key");
2004   ASSERT_THAT(CreateEntry(key, &entry), IsOk());
2005   EXPECT_FALSE(entry->CouldBeSparse());
2006 
2007   EXPECT_EQ(kSize, WriteData(entry, 0, 0, buf.get(), kSize, false));
2008   EXPECT_EQ(kSize, WriteData(entry, 1, 0, buf.get(), kSize, false));
2009   EXPECT_EQ(kSize, WriteData(entry, 2, 0, buf.get(), kSize, false));
2010 
2011   EXPECT_FALSE(entry->CouldBeSparse());
2012   entry->Close();
2013 
2014   ASSERT_THAT(OpenEntry(key, &entry), IsOk());
2015   EXPECT_FALSE(entry->CouldBeSparse());
2016   entry->Close();
2017 }
2018 
TEST_F(DiskCacheEntryTest,CouldBeSparse)2019 TEST_F(DiskCacheEntryTest, CouldBeSparse) {
2020   InitCache();
2021   CouldBeSparse();
2022 }
2023 
TEST_F(DiskCacheEntryTest,MemoryCouldBeSparse)2024 TEST_F(DiskCacheEntryTest, MemoryCouldBeSparse) {
2025   SetMemoryOnlyMode();
2026   InitCache();
2027   CouldBeSparse();
2028 }
2029 
TEST_F(DiskCacheEntryTest,MemoryOnlyMisalignedSparseIO)2030 TEST_F(DiskCacheEntryTest, MemoryOnlyMisalignedSparseIO) {
2031   SetMemoryOnlyMode();
2032   InitCache();
2033 
2034   const int kSize = 8192;
2035   auto buf_1 = base::MakeRefCounted<net::IOBufferWithSize>(kSize);
2036   auto buf_2 = base::MakeRefCounted<net::IOBufferWithSize>(kSize);
2037   CacheTestFillBuffer(buf_1->data(), kSize, false);
2038 
2039   std::string key("the first key");
2040   disk_cache::Entry* entry;
2041   ASSERT_THAT(CreateEntry(key, &entry), IsOk());
2042 
2043   // This loop writes back to back starting from offset 0 and 9000.
2044   for (int i = 0; i < kSize; i += 1024) {
2045     auto buf_3 =
2046         base::MakeRefCounted<net::WrappedIOBuffer>(buf_1->span().subspan(i));
2047     VerifySparseIO(entry, i, buf_3.get(), 1024, buf_2.get());
2048     VerifySparseIO(entry, 9000 + i, buf_3.get(), 1024, buf_2.get());
2049   }
2050 
2051   // Make sure we have data written.
2052   VerifyContentSparseIO(entry, 0, buf_1->data(), kSize);
2053   VerifyContentSparseIO(entry, 9000, buf_1->data(), kSize);
2054 
2055   // This tests a large write that spans 3 entries from a misaligned offset.
2056   VerifySparseIO(entry, 20481, buf_1.get(), 8192, buf_2.get());
2057 
2058   entry->Close();
2059 }
2060 
TEST_F(DiskCacheEntryTest,MemoryOnlyMisalignedGetAvailableRange)2061 TEST_F(DiskCacheEntryTest, MemoryOnlyMisalignedGetAvailableRange) {
2062   SetMemoryOnlyMode();
2063   InitCache();
2064 
2065   const int kSize = 8192;
2066   auto buf = base::MakeRefCounted<net::IOBufferWithSize>(kSize);
2067   CacheTestFillBuffer(buf->data(), kSize, false);
2068 
2069   disk_cache::Entry* entry;
2070   std::string key("the first key");
2071   ASSERT_THAT(CreateEntry(key, &entry), IsOk());
2072 
2073   // Writes in the middle of an entry.
2074   EXPECT_EQ(1024, entry->WriteSparseData(0, buf.get(), 1024,
2075                                          net::CompletionOnceCallback()));
2076   EXPECT_EQ(1024, entry->WriteSparseData(5120, buf.get(), 1024,
2077                                          net::CompletionOnceCallback()));
2078   EXPECT_EQ(1024, entry->WriteSparseData(10000, buf.get(), 1024,
2079                                          net::CompletionOnceCallback()));
2080 
2081   // Writes in the middle of an entry and spans 2 child entries.
2082   EXPECT_EQ(8192, entry->WriteSparseData(50000, buf.get(), 8192,
2083                                          net::CompletionOnceCallback()));
2084 
2085   TestRangeResultCompletionCallback cb;
2086   // Test that we stop at a discontinuous child at the second block.
2087   RangeResult result =
2088       cb.GetResult(entry->GetAvailableRange(0, 10000, cb.callback()));
2089   EXPECT_EQ(net::OK, result.net_error);
2090   EXPECT_EQ(1024, result.available_len);
2091   EXPECT_EQ(0, result.start);
2092 
2093   // Test that number of bytes is reported correctly when we start from the
2094   // middle of a filled region.
2095   result = cb.GetResult(entry->GetAvailableRange(512, 10000, cb.callback()));
2096   EXPECT_EQ(net::OK, result.net_error);
2097   EXPECT_EQ(512, result.available_len);
2098   EXPECT_EQ(512, result.start);
2099 
2100   // Test that we found bytes in the child of next block.
2101   result = cb.GetResult(entry->GetAvailableRange(1024, 10000, cb.callback()));
2102   EXPECT_EQ(net::OK, result.net_error);
2103   EXPECT_EQ(1024, result.available_len);
2104   EXPECT_EQ(5120, result.start);
2105 
2106   // Test that the desired length is respected. It starts within a filled
2107   // region.
2108   result = cb.GetResult(entry->GetAvailableRange(5500, 512, cb.callback()));
2109   EXPECT_EQ(net::OK, result.net_error);
2110   EXPECT_EQ(512, result.available_len);
2111   EXPECT_EQ(5500, result.start);
2112 
2113   // Test that the desired length is respected. It starts before a filled
2114   // region.
2115   result = cb.GetResult(entry->GetAvailableRange(5000, 620, cb.callback()));
2116   EXPECT_EQ(net::OK, result.net_error);
2117   EXPECT_EQ(500, result.available_len);
2118   EXPECT_EQ(5120, result.start);
2119 
2120   // Test that multiple blocks are scanned.
2121   result = cb.GetResult(entry->GetAvailableRange(40000, 20000, cb.callback()));
2122   EXPECT_EQ(net::OK, result.net_error);
2123   EXPECT_EQ(8192, result.available_len);
2124   EXPECT_EQ(50000, result.start);
2125 
2126   entry->Close();
2127 }
2128 
UpdateSparseEntry()2129 void DiskCacheEntryTest::UpdateSparseEntry() {
2130   std::string key("the first key");
2131   disk_cache::Entry* entry1;
2132   ASSERT_THAT(CreateEntry(key, &entry1), IsOk());
2133 
2134   const int kSize = 2048;
2135   auto buf_1 = base::MakeRefCounted<net::IOBufferWithSize>(kSize);
2136   auto buf_2 = base::MakeRefCounted<net::IOBufferWithSize>(kSize);
2137   CacheTestFillBuffer(buf_1->data(), kSize, false);
2138 
2139   // Write at offset 0.
2140   VerifySparseIO(entry1, 0, buf_1.get(), kSize, buf_2.get());
2141   entry1->Close();
2142 
2143   // Write at offset 2048.
2144   ASSERT_THAT(OpenEntry(key, &entry1), IsOk());
2145   VerifySparseIO(entry1, 2048, buf_1.get(), kSize, buf_2.get());
2146 
2147   disk_cache::Entry* entry2;
2148   ASSERT_THAT(CreateEntry("the second key", &entry2), IsOk());
2149 
2150   entry1->Close();
2151   entry2->Close();
2152   FlushQueueForTest();
2153   if (memory_only_ || simple_cache_mode_)
2154     EXPECT_EQ(2, cache_->GetEntryCount());
2155   else
2156     EXPECT_EQ(3, cache_->GetEntryCount());
2157 }
2158 
TEST_F(DiskCacheEntryTest,UpdateSparseEntry)2159 TEST_F(DiskCacheEntryTest, UpdateSparseEntry) {
2160   InitCache();
2161   UpdateSparseEntry();
2162 }
2163 
TEST_F(DiskCacheEntryTest,MemoryOnlyUpdateSparseEntry)2164 TEST_F(DiskCacheEntryTest, MemoryOnlyUpdateSparseEntry) {
2165   SetMemoryOnlyMode();
2166   InitCache();
2167   UpdateSparseEntry();
2168 }
2169 
DoomSparseEntry()2170 void DiskCacheEntryTest::DoomSparseEntry() {
2171   std::string key1("the first key");
2172   std::string key2("the second key");
2173   disk_cache::Entry *entry1, *entry2;
2174   ASSERT_THAT(CreateEntry(key1, &entry1), IsOk());
2175   ASSERT_THAT(CreateEntry(key2, &entry2), IsOk());
2176 
2177   const int kSize = 4 * 1024;
2178   auto buf = base::MakeRefCounted<net::IOBufferWithSize>(kSize);
2179   CacheTestFillBuffer(buf->data(), kSize, false);
2180 
2181   int64_t offset = 1024;
2182   // Write to a bunch of ranges.
2183   for (int i = 0; i < 12; i++) {
2184     EXPECT_EQ(kSize, WriteSparseData(entry1, offset, buf.get(), kSize));
2185     // Keep the second map under the default size.
2186     if (i < 9)
2187       EXPECT_EQ(kSize, WriteSparseData(entry2, offset, buf.get(), kSize));
2188 
2189     offset *= 4;
2190   }
2191 
2192   if (memory_only_ || simple_cache_mode_)
2193     EXPECT_EQ(2, cache_->GetEntryCount());
2194   else
2195     EXPECT_EQ(15, cache_->GetEntryCount());
2196 
2197   // Doom the first entry while it's still open.
2198   entry1->Doom();
2199   entry1->Close();
2200   entry2->Close();
2201 
2202   // Doom the second entry after it's fully saved.
2203   EXPECT_THAT(DoomEntry(key2), IsOk());
2204 
2205   // Make sure we do all needed work. This may fail for entry2 if between Close
2206   // and DoomEntry the system decides to remove all traces of the file from the
2207   // system cache so we don't see that there is pending IO.
2208   base::RunLoop().RunUntilIdle();
2209 
2210   if (memory_only_) {
2211     EXPECT_EQ(0, cache_->GetEntryCount());
2212   } else {
2213     if (5 == cache_->GetEntryCount()) {
2214       // Most likely we are waiting for the result of reading the sparse info
2215       // (it's always async on Posix so it is easy to miss). Unfortunately we
2216       // don't have any signal to watch for so we can only wait.
2217       base::PlatformThread::Sleep(base::Milliseconds(500));
2218       base::RunLoop().RunUntilIdle();
2219     }
2220     EXPECT_EQ(0, cache_->GetEntryCount());
2221   }
2222 }
2223 
TEST_F(DiskCacheEntryTest,DoomSparseEntry)2224 TEST_F(DiskCacheEntryTest, DoomSparseEntry) {
2225   UseCurrentThread();
2226   InitCache();
2227   DoomSparseEntry();
2228 }
2229 
TEST_F(DiskCacheEntryTest,MemoryOnlyDoomSparseEntry)2230 TEST_F(DiskCacheEntryTest, MemoryOnlyDoomSparseEntry) {
2231   SetMemoryOnlyMode();
2232   InitCache();
2233   DoomSparseEntry();
2234 }
2235 
2236 // A TestCompletionCallback wrapper that deletes the cache from within the
2237 // callback.  The way TestCompletionCallback works means that all tasks (even
2238 // new ones) are executed by the message loop before returning to the caller so
2239 // the only way to simulate a race is to execute what we want on the callback.
2240 class SparseTestCompletionCallback: public net::TestCompletionCallback {
2241  public:
SparseTestCompletionCallback(std::unique_ptr<disk_cache::Backend> cache)2242   explicit SparseTestCompletionCallback(
2243       std::unique_ptr<disk_cache::Backend> cache)
2244       : cache_(std::move(cache)) {}
2245 
2246   SparseTestCompletionCallback(const SparseTestCompletionCallback&) = delete;
2247   SparseTestCompletionCallback& operator=(const SparseTestCompletionCallback&) =
2248       delete;
2249 
2250  private:
SetResult(int result)2251   void SetResult(int result) override {
2252     cache_.reset();
2253     TestCompletionCallback::SetResult(result);
2254   }
2255 
2256   std::unique_ptr<disk_cache::Backend> cache_;
2257 };
2258 
2259 // Tests that we don't crash when the backend is deleted while we are working
2260 // deleting the sub-entries of a sparse entry.
TEST_F(DiskCacheEntryTest,DoomSparseEntry2)2261 TEST_F(DiskCacheEntryTest, DoomSparseEntry2) {
2262   UseCurrentThread();
2263   InitCache();
2264   std::string key("the key");
2265   disk_cache::Entry* entry;
2266   ASSERT_THAT(CreateEntry(key, &entry), IsOk());
2267 
2268   const int kSize = 4 * 1024;
2269   auto buf = base::MakeRefCounted<net::IOBufferWithSize>(kSize);
2270   CacheTestFillBuffer(buf->data(), kSize, false);
2271 
2272   int64_t offset = 1024;
2273   // Write to a bunch of ranges.
2274   for (int i = 0; i < 12; i++) {
2275     EXPECT_EQ(kSize, entry->WriteSparseData(offset, buf.get(), kSize,
2276                                             net::CompletionOnceCallback()));
2277     offset *= 4;
2278   }
2279   EXPECT_EQ(9, cache_->GetEntryCount());
2280 
2281   entry->Close();
2282   disk_cache::Backend* cache = cache_.get();
2283   SparseTestCompletionCallback cb(TakeCache());
2284   int rv = cache->DoomEntry(key, net::HIGHEST, cb.callback());
2285   EXPECT_THAT(rv, IsError(net::ERR_IO_PENDING));
2286   EXPECT_THAT(cb.WaitForResult(), IsOk());
2287 }
2288 
PartialSparseEntry()2289 void DiskCacheEntryTest::PartialSparseEntry() {
2290   std::string key("the first key");
2291   disk_cache::Entry* entry;
2292   ASSERT_THAT(CreateEntry(key, &entry), IsOk());
2293 
2294   // We should be able to deal with IO that is not aligned to the block size
2295   // of a sparse entry, at least to write a big range without leaving holes.
2296   const int kSize = 4 * 1024;
2297   const int kSmallSize = 128;
2298   auto buf1 = base::MakeRefCounted<net::IOBufferWithSize>(kSize);
2299   CacheTestFillBuffer(buf1->data(), kSize, false);
2300 
2301   // The first write is just to extend the entry. The third write occupies
2302   // a 1KB block partially, it may not be written internally depending on the
2303   // implementation.
2304   EXPECT_EQ(kSize, WriteSparseData(entry, 20000, buf1.get(), kSize));
2305   EXPECT_EQ(kSize, WriteSparseData(entry, 500, buf1.get(), kSize));
2306   EXPECT_EQ(kSmallSize,
2307             WriteSparseData(entry, 1080321, buf1.get(), kSmallSize));
2308   entry->Close();
2309   ASSERT_THAT(OpenEntry(key, &entry), IsOk());
2310 
2311   auto buf2 = base::MakeRefCounted<net::IOBufferWithSize>(kSize);
2312   memset(buf2->data(), 0, kSize);
2313   EXPECT_EQ(0, ReadSparseData(entry, 8000, buf2.get(), kSize));
2314 
2315   EXPECT_EQ(500, ReadSparseData(entry, kSize, buf2.get(), kSize));
2316   EXPECT_EQ(0, memcmp(buf2->data(), buf1->data() + kSize - 500, 500));
2317   EXPECT_EQ(0, ReadSparseData(entry, 0, buf2.get(), kSize));
2318 
2319   // This read should not change anything.
2320   if (memory_only_ || simple_cache_mode_)
2321     EXPECT_EQ(96, ReadSparseData(entry, 24000, buf2.get(), kSize));
2322   else
2323     EXPECT_EQ(0, ReadSparseData(entry, 24000, buf2.get(), kSize));
2324 
2325   EXPECT_EQ(500, ReadSparseData(entry, kSize, buf2.get(), kSize));
2326   EXPECT_EQ(0, ReadSparseData(entry, 99, buf2.get(), kSize));
2327 
2328   TestRangeResultCompletionCallback cb;
2329   RangeResult result;
2330   if (memory_only_ || simple_cache_mode_) {
2331     result = cb.GetResult(entry->GetAvailableRange(0, 600, cb.callback()));
2332     EXPECT_EQ(net::OK, result.net_error);
2333     EXPECT_EQ(100, result.available_len);
2334     EXPECT_EQ(500, result.start);
2335   } else {
2336     result = cb.GetResult(entry->GetAvailableRange(0, 2048, cb.callback()));
2337     EXPECT_EQ(net::OK, result.net_error);
2338     EXPECT_EQ(1024, result.available_len);
2339     EXPECT_EQ(1024, result.start);
2340   }
2341   result = cb.GetResult(entry->GetAvailableRange(kSize, kSize, cb.callback()));
2342   EXPECT_EQ(net::OK, result.net_error);
2343   EXPECT_EQ(500, result.available_len);
2344   EXPECT_EQ(kSize, result.start);
2345   result =
2346       cb.GetResult(entry->GetAvailableRange(20 * 1024, 10000, cb.callback()));
2347   EXPECT_EQ(net::OK, result.net_error);
2348   if (memory_only_ || simple_cache_mode_)
2349     EXPECT_EQ(3616, result.available_len);
2350   else
2351     EXPECT_EQ(3072, result.available_len);
2352 
2353   EXPECT_EQ(20 * 1024, result.start);
2354 
2355   // 1. Query before a filled 1KB block.
2356   // 2. Query within a filled 1KB block.
2357   // 3. Query beyond a filled 1KB block.
2358   if (memory_only_ || simple_cache_mode_) {
2359     result =
2360         cb.GetResult(entry->GetAvailableRange(19400, kSize, cb.callback()));
2361     EXPECT_EQ(net::OK, result.net_error);
2362     EXPECT_EQ(3496, result.available_len);
2363     EXPECT_EQ(20000, result.start);
2364   } else {
2365     result =
2366         cb.GetResult(entry->GetAvailableRange(19400, kSize, cb.callback()));
2367     EXPECT_EQ(net::OK, result.net_error);
2368     EXPECT_EQ(3016, result.available_len);
2369     EXPECT_EQ(20480, result.start);
2370   }
2371   result = cb.GetResult(entry->GetAvailableRange(3073, kSize, cb.callback()));
2372   EXPECT_EQ(net::OK, result.net_error);
2373   EXPECT_EQ(1523, result.available_len);
2374   EXPECT_EQ(3073, result.start);
2375   result = cb.GetResult(entry->GetAvailableRange(4600, kSize, cb.callback()));
2376   EXPECT_EQ(net::OK, result.net_error);
2377   EXPECT_EQ(0, result.available_len);
2378   EXPECT_EQ(4600, result.start);
2379 
2380   // Now make another write and verify that there is no hole in between.
2381   EXPECT_EQ(kSize, WriteSparseData(entry, 500 + kSize, buf1.get(), kSize));
2382   result = cb.GetResult(entry->GetAvailableRange(1024, 10000, cb.callback()));
2383   EXPECT_EQ(net::OK, result.net_error);
2384   EXPECT_EQ(7 * 1024 + 500, result.available_len);
2385   EXPECT_EQ(1024, result.start);
2386   EXPECT_EQ(kSize, ReadSparseData(entry, kSize, buf2.get(), kSize));
2387   EXPECT_EQ(0, memcmp(buf2->data(), buf1->data() + kSize - 500, 500));
2388   EXPECT_EQ(0, memcmp(buf2->data() + 500, buf1->data(), kSize - 500));
2389 
2390   entry->Close();
2391 }
2392 
TEST_F(DiskCacheEntryTest,PartialSparseEntry)2393 TEST_F(DiskCacheEntryTest, PartialSparseEntry) {
2394   InitCache();
2395   PartialSparseEntry();
2396 }
2397 
TEST_F(DiskCacheEntryTest,MemoryPartialSparseEntry)2398 TEST_F(DiskCacheEntryTest, MemoryPartialSparseEntry) {
2399   SetMemoryOnlyMode();
2400   InitCache();
2401   PartialSparseEntry();
2402 }
2403 
SparseInvalidArg()2404 void DiskCacheEntryTest::SparseInvalidArg() {
2405   std::string key("key");
2406   disk_cache::Entry* entry = nullptr;
2407   ASSERT_THAT(CreateEntry(key, &entry), IsOk());
2408 
2409   const int kSize = 2048;
2410   auto buf = base::MakeRefCounted<net::IOBufferWithSize>(kSize);
2411   CacheTestFillBuffer(buf->data(), kSize, false);
2412 
2413   EXPECT_EQ(net::ERR_INVALID_ARGUMENT,
2414             WriteSparseData(entry, -1, buf.get(), kSize));
2415   EXPECT_EQ(net::ERR_INVALID_ARGUMENT,
2416             WriteSparseData(entry, 0, buf.get(), -1));
2417 
2418   EXPECT_EQ(net::ERR_INVALID_ARGUMENT,
2419             ReadSparseData(entry, -1, buf.get(), kSize));
2420   EXPECT_EQ(net::ERR_INVALID_ARGUMENT, ReadSparseData(entry, 0, buf.get(), -1));
2421 
2422   int64_t start_out;
2423   EXPECT_EQ(net::ERR_INVALID_ARGUMENT,
2424             GetAvailableRange(entry, -1, kSize, &start_out));
2425   EXPECT_EQ(net::ERR_INVALID_ARGUMENT,
2426             GetAvailableRange(entry, 0, -1, &start_out));
2427 
2428   int rv = WriteSparseData(
2429       entry, std::numeric_limits<int64_t>::max() - kSize + 1, buf.get(), kSize);
2430   // Blockfile rejects anything over 64GiB with
2431   // net::ERR_CACHE_OPERATION_NOT_SUPPORTED, which is also OK here, as it's not
2432   // an overflow or something else nonsensical.
2433   EXPECT_TRUE(rv == net::ERR_INVALID_ARGUMENT ||
2434               rv == net::ERR_CACHE_OPERATION_NOT_SUPPORTED);
2435 
2436   entry->Close();
2437 }
2438 
TEST_F(DiskCacheEntryTest,SparseInvalidArg)2439 TEST_F(DiskCacheEntryTest, SparseInvalidArg) {
2440   InitCache();
2441   SparseInvalidArg();
2442 }
2443 
TEST_F(DiskCacheEntryTest,MemoryOnlySparseInvalidArg)2444 TEST_F(DiskCacheEntryTest, MemoryOnlySparseInvalidArg) {
2445   SetMemoryOnlyMode();
2446   InitCache();
2447   SparseInvalidArg();
2448 }
2449 
TEST_F(DiskCacheEntryTest,SimpleSparseInvalidArg)2450 TEST_F(DiskCacheEntryTest, SimpleSparseInvalidArg) {
2451   SetSimpleCacheMode();
2452   InitCache();
2453   SparseInvalidArg();
2454 }
2455 
SparseClipEnd(int64_t max_index,bool expect_unsupported)2456 void DiskCacheEntryTest::SparseClipEnd(int64_t max_index,
2457                                        bool expect_unsupported) {
2458   std::string key("key");
2459   disk_cache::Entry* entry = nullptr;
2460   ASSERT_THAT(CreateEntry(key, &entry), IsOk());
2461 
2462   const int kSize = 1024;
2463   auto buf = base::MakeRefCounted<net::IOBufferWithSize>(kSize);
2464   CacheTestFillBuffer(buf->data(), kSize, false);
2465 
2466   auto read_buf = base::MakeRefCounted<net::IOBufferWithSize>(kSize * 2);
2467   CacheTestFillBuffer(read_buf->data(), kSize * 2, false);
2468 
2469   const int64_t kOffset = max_index - kSize;
2470   int rv = WriteSparseData(entry, kOffset, buf.get(), kSize);
2471   EXPECT_EQ(
2472       rv, expect_unsupported ? net::ERR_CACHE_OPERATION_NOT_SUPPORTED : kSize);
2473 
2474   // Try to read further than offset range, should get clipped (if supported).
2475   rv = ReadSparseData(entry, kOffset, read_buf.get(), kSize * 2);
2476   if (expect_unsupported) {
2477     EXPECT_EQ(rv, net::ERR_CACHE_OPERATION_NOT_SUPPORTED);
2478   } else {
2479     EXPECT_EQ(kSize, rv);
2480     EXPECT_EQ(0, memcmp(buf->data(), read_buf->data(), kSize));
2481   }
2482 
2483   TestRangeResultCompletionCallback cb;
2484   RangeResult result = cb.GetResult(
2485       entry->GetAvailableRange(kOffset - kSize, kSize * 3, cb.callback()));
2486   if (expect_unsupported) {
2487     // GetAvailableRange just returns nothing found, not an error.
2488     EXPECT_EQ(net::OK, result.net_error);
2489     EXPECT_EQ(result.available_len, 0);
2490   } else {
2491     EXPECT_EQ(net::OK, result.net_error);
2492     EXPECT_EQ(kSize, result.available_len);
2493     EXPECT_EQ(kOffset, result.start);
2494   }
2495 
2496   entry->Close();
2497 }
2498 
TEST_F(DiskCacheEntryTest,SparseClipEnd)2499 TEST_F(DiskCacheEntryTest, SparseClipEnd) {
2500   InitCache();
2501 
2502   // Blockfile refuses to deal with sparse indices over 64GiB.
2503   SparseClipEnd(std::numeric_limits<int64_t>::max(),
2504                 /*expected_unsupported=*/true);
2505 }
2506 
TEST_F(DiskCacheEntryTest,SparseClipEnd2)2507 TEST_F(DiskCacheEntryTest, SparseClipEnd2) {
2508   InitCache();
2509 
2510   const int64_t kLimit = 64ll * 1024 * 1024 * 1024;
2511   // Separate test for blockfile for indices right at the edge of its address
2512   // space limit. kLimit must match kMaxEndOffset in sparse_control.cc
2513   SparseClipEnd(kLimit, /*expected_unsupported=*/false);
2514 
2515   // Test with things after kLimit, too, which isn't an issue for backends
2516   // supporting the entire 64-bit offset range.
2517   std::string key("key2");
2518   disk_cache::Entry* entry = nullptr;
2519   ASSERT_THAT(CreateEntry(key, &entry), IsOk());
2520 
2521   const int kSize = 1024;
2522   auto buf = base::MakeRefCounted<net::IOBufferWithSize>(kSize);
2523   CacheTestFillBuffer(buf->data(), kSize, false);
2524 
2525   // Try to write after --- fails.
2526   int rv = WriteSparseData(entry, kLimit, buf.get(), kSize);
2527   EXPECT_EQ(net::ERR_CACHE_OPERATION_NOT_SUPPORTED, rv);
2528 
2529   // Similarly for read.
2530   rv = ReadSparseData(entry, kLimit, buf.get(), kSize);
2531   EXPECT_EQ(net::ERR_CACHE_OPERATION_NOT_SUPPORTED, rv);
2532 
2533   // GetAvailableRange just returns nothing.
2534   TestRangeResultCompletionCallback cb;
2535   RangeResult result =
2536       cb.GetResult(entry->GetAvailableRange(kLimit, kSize * 3, cb.callback()));
2537   EXPECT_EQ(net::OK, result.net_error);
2538   EXPECT_EQ(0, result.available_len);
2539   entry->Close();
2540 }
2541 
TEST_F(DiskCacheEntryTest,MemoryOnlySparseClipEnd)2542 TEST_F(DiskCacheEntryTest, MemoryOnlySparseClipEnd) {
2543   SetMemoryOnlyMode();
2544   InitCache();
2545   SparseClipEnd(std::numeric_limits<int64_t>::max(),
2546                 /* expected_unsupported = */ false);
2547 }
2548 
TEST_F(DiskCacheEntryTest,SimpleSparseClipEnd)2549 TEST_F(DiskCacheEntryTest, SimpleSparseClipEnd) {
2550   SetSimpleCacheMode();
2551   InitCache();
2552   SparseClipEnd(std::numeric_limits<int64_t>::max(),
2553                 /* expected_unsupported = */ false);
2554 }
2555 
2556 // Tests that corrupt sparse children are removed automatically.
TEST_F(DiskCacheEntryTest,CleanupSparseEntry)2557 TEST_F(DiskCacheEntryTest, CleanupSparseEntry) {
2558   InitCache();
2559   std::string key("the first key");
2560   disk_cache::Entry* entry;
2561   ASSERT_THAT(CreateEntry(key, &entry), IsOk());
2562 
2563   const int kSize = 4 * 1024;
2564   auto buf1 = base::MakeRefCounted<net::IOBufferWithSize>(kSize);
2565   CacheTestFillBuffer(buf1->data(), kSize, false);
2566 
2567   const int k1Meg = 1024 * 1024;
2568   EXPECT_EQ(kSize, WriteSparseData(entry, 8192, buf1.get(), kSize));
2569   EXPECT_EQ(kSize, WriteSparseData(entry, k1Meg + 8192, buf1.get(), kSize));
2570   EXPECT_EQ(kSize, WriteSparseData(entry, 2 * k1Meg + 8192, buf1.get(), kSize));
2571   entry->Close();
2572   EXPECT_EQ(4, cache_->GetEntryCount());
2573 
2574   std::unique_ptr<TestIterator> iter = CreateIterator();
2575   int count = 0;
2576   std::string child_keys[2];
2577   while (iter->OpenNextEntry(&entry) == net::OK) {
2578     ASSERT_TRUE(entry != nullptr);
2579     // Writing to an entry will alter the LRU list and invalidate the iterator.
2580     if (entry->GetKey() != key && count < 2)
2581       child_keys[count++] = entry->GetKey();
2582     entry->Close();
2583   }
2584   for (const auto& child_key : child_keys) {
2585     ASSERT_THAT(OpenEntry(child_key, &entry), IsOk());
2586     // Overwrite the header's magic and signature.
2587     EXPECT_EQ(12, WriteData(entry, 2, 0, buf1.get(), 12, false));
2588     entry->Close();
2589   }
2590 
2591   EXPECT_EQ(4, cache_->GetEntryCount());
2592   ASSERT_THAT(OpenEntry(key, &entry), IsOk());
2593 
2594   // Two children should be gone. One while reading and one while writing.
2595   EXPECT_EQ(0, ReadSparseData(entry, 2 * k1Meg + 8192, buf1.get(), kSize));
2596   EXPECT_EQ(kSize, WriteSparseData(entry, k1Meg + 16384, buf1.get(), kSize));
2597   EXPECT_EQ(0, ReadSparseData(entry, k1Meg + 8192, buf1.get(), kSize));
2598 
2599   // We never touched this one.
2600   EXPECT_EQ(kSize, ReadSparseData(entry, 8192, buf1.get(), kSize));
2601   entry->Close();
2602 
2603   // We re-created one of the corrupt children.
2604   EXPECT_EQ(3, cache_->GetEntryCount());
2605 }
2606 
TEST_F(DiskCacheEntryTest,CancelSparseIO)2607 TEST_F(DiskCacheEntryTest, CancelSparseIO) {
2608   UseCurrentThread();
2609   InitCache();
2610   std::string key("the first key");
2611   disk_cache::Entry* entry;
2612   ASSERT_THAT(CreateEntry(key, &entry), IsOk());
2613 
2614   const int kSize = 40 * 1024;
2615   auto buf = base::MakeRefCounted<net::IOBufferWithSize>(kSize);
2616   CacheTestFillBuffer(buf->data(), kSize, false);
2617 
2618   // This will open and write two "real" entries.
2619   net::TestCompletionCallback cb1, cb2, cb3, cb4;
2620   int rv = entry->WriteSparseData(
2621       1024 * 1024 - 4096, buf.get(), kSize, cb1.callback());
2622   EXPECT_THAT(rv, IsError(net::ERR_IO_PENDING));
2623 
2624   TestRangeResultCompletionCallback cb5;
2625   RangeResult result =
2626       cb5.GetResult(entry->GetAvailableRange(0, kSize, cb5.callback()));
2627   if (!cb1.have_result()) {
2628     // We may or may not have finished writing to the entry. If we have not,
2629     // we cannot start another operation at this time.
2630     EXPECT_THAT(rv, IsError(net::ERR_CACHE_OPERATION_NOT_SUPPORTED));
2631   }
2632 
2633   // We cancel the pending operation, and register multiple notifications.
2634   entry->CancelSparseIO();
2635   EXPECT_THAT(entry->ReadyForSparseIO(cb2.callback()),
2636               IsError(net::ERR_IO_PENDING));
2637   EXPECT_THAT(entry->ReadyForSparseIO(cb3.callback()),
2638               IsError(net::ERR_IO_PENDING));
2639   entry->CancelSparseIO();  // Should be a no op at this point.
2640   EXPECT_THAT(entry->ReadyForSparseIO(cb4.callback()),
2641               IsError(net::ERR_IO_PENDING));
2642 
2643   if (!cb1.have_result()) {
2644     EXPECT_EQ(net::ERR_CACHE_OPERATION_NOT_SUPPORTED,
2645               entry->ReadSparseData(result.start, buf.get(), kSize,
2646                                     net::CompletionOnceCallback()));
2647     EXPECT_EQ(net::ERR_CACHE_OPERATION_NOT_SUPPORTED,
2648               entry->WriteSparseData(result.start, buf.get(), kSize,
2649                                      net::CompletionOnceCallback()));
2650   }
2651 
2652   // Now see if we receive all notifications. Note that we should not be able
2653   // to write everything (unless the timing of the system is really weird).
2654   rv = cb1.WaitForResult();
2655   EXPECT_TRUE(rv == 4096 || rv == kSize);
2656   EXPECT_THAT(cb2.WaitForResult(), IsOk());
2657   EXPECT_THAT(cb3.WaitForResult(), IsOk());
2658   EXPECT_THAT(cb4.WaitForResult(), IsOk());
2659 
2660   result = cb5.GetResult(
2661       entry->GetAvailableRange(result.start, kSize, cb5.callback()));
2662   EXPECT_EQ(net::OK, result.net_error);
2663   EXPECT_EQ(0, result.available_len);
2664   entry->Close();
2665 }
2666 
2667 // Tests that we perform sanity checks on an entry's key. Note that there are
2668 // other tests that exercise sanity checks by using saved corrupt files.
TEST_F(DiskCacheEntryTest,KeySanityCheck)2669 TEST_F(DiskCacheEntryTest, KeySanityCheck) {
2670   UseCurrentThread();
2671   InitCache();
2672   std::string key("the first key");
2673   disk_cache::Entry* entry;
2674   ASSERT_THAT(CreateEntry(key, &entry), IsOk());
2675 
2676   disk_cache::EntryImpl* entry_impl =
2677       static_cast<disk_cache::EntryImpl*>(entry);
2678   disk_cache::EntryStore* store = entry_impl->entry()->Data();
2679 
2680   // We have reserved space for a short key (one block), let's say that the key
2681   // takes more than one block, and remove the NULLs after the actual key.
2682   store->key_len = 800;
2683   memset(store->key + key.size(), 'k', sizeof(store->key) - key.size());
2684   entry_impl->entry()->set_modified();
2685   entry->Close();
2686 
2687   // We have a corrupt entry. Now reload it. We should NOT read beyond the
2688   // allocated buffer here.
2689   ASSERT_NE(net::OK, OpenEntry(key, &entry));
2690   DisableIntegrityCheck();
2691 }
2692 
TEST_F(DiskCacheEntryTest,KeySanityCheck2)2693 TEST_F(DiskCacheEntryTest, KeySanityCheck2) {
2694   UseCurrentThread();
2695   InitCache();
2696   std::string key("the first key");
2697   disk_cache::Entry* entry;
2698   ASSERT_THAT(CreateEntry(key, &entry), IsOk());
2699 
2700   disk_cache::EntryImpl* entry_impl =
2701       static_cast<disk_cache::EntryImpl*>(entry);
2702   disk_cache::EntryStore* store = entry_impl->entry()->Data();
2703 
2704   // Fill in the rest of inline key store with non-nulls. Unlike in
2705   // KeySanityCheck, this does not change the length to identify it as
2706   // stored under |long_key|.
2707   memset(store->key + key.size(), 'k', sizeof(store->key) - key.size());
2708   entry_impl->entry()->set_modified();
2709   entry->Close();
2710 
2711   // We have a corrupt entry. Now reload it. We should NOT read beyond the
2712   // allocated buffer here.
2713   ASSERT_NE(net::OK, OpenEntry(key, &entry));
2714   DisableIntegrityCheck();
2715 }
2716 
TEST_F(DiskCacheEntryTest,KeySanityCheck3)2717 TEST_F(DiskCacheEntryTest, KeySanityCheck3) {
2718   const size_t kVeryLong = 40 * 1024;
2719   UseCurrentThread();
2720   InitCache();
2721   std::string key(kVeryLong, 'a');
2722   disk_cache::Entry* entry;
2723   ASSERT_THAT(CreateEntry(key, &entry), IsOk());
2724 
2725   disk_cache::EntryImpl* entry_impl =
2726       static_cast<disk_cache::EntryImpl*>(entry);
2727   disk_cache::EntryStore* store = entry_impl->entry()->Data();
2728 
2729   // Test meaningful when using long keys; and also want this to be
2730   // an external file to avoid needing to duplicate offset math here.
2731   disk_cache::Addr key_addr(store->long_key);
2732   ASSERT_TRUE(key_addr.is_initialized());
2733   ASSERT_TRUE(key_addr.is_separate_file());
2734 
2735   // Close the entry before messing up its files.
2736   entry->Close();
2737 
2738   // Mess up the terminating null in the external key file.
2739   auto key_file =
2740       base::MakeRefCounted<disk_cache::File>(true /* want sync ops*/);
2741   ASSERT_TRUE(key_file->Init(cache_impl_->GetFileName(key_addr)));
2742 
2743   ASSERT_TRUE(key_file->Write("b", 1u, kVeryLong));
2744   key_file = nullptr;
2745 
2746   // This case gets graceful recovery.
2747   ASSERT_THAT(OpenEntry(key, &entry), IsOk());
2748 
2749   // Make sure the key object isn't messed up.
2750   EXPECT_EQ(kVeryLong, strlen(entry->GetKey().data()));
2751   entry->Close();
2752 }
2753 
TEST_F(DiskCacheEntryTest,SimpleCacheInternalAsyncIO)2754 TEST_F(DiskCacheEntryTest, SimpleCacheInternalAsyncIO) {
2755   SetSimpleCacheMode();
2756   InitCache();
2757   InternalAsyncIO();
2758 }
2759 
TEST_F(DiskCacheEntryTest,SimpleCacheExternalAsyncIO)2760 TEST_F(DiskCacheEntryTest, SimpleCacheExternalAsyncIO) {
2761   SetSimpleCacheMode();
2762   InitCache();
2763   ExternalAsyncIO();
2764 }
2765 
TEST_F(DiskCacheEntryTest,SimpleCacheReleaseBuffer)2766 TEST_F(DiskCacheEntryTest, SimpleCacheReleaseBuffer) {
2767   SetSimpleCacheMode();
2768   InitCache();
2769   for (int i = 0; i < disk_cache::kSimpleEntryStreamCount; ++i) {
2770     EXPECT_THAT(DoomAllEntries(), IsOk());
2771     ReleaseBuffer(i);
2772   }
2773 }
2774 
TEST_F(DiskCacheEntryTest,SimpleCacheStreamAccess)2775 TEST_F(DiskCacheEntryTest, SimpleCacheStreamAccess) {
2776   SetSimpleCacheMode();
2777   InitCache();
2778   StreamAccess();
2779 }
2780 
TEST_F(DiskCacheEntryTest,SimpleCacheGetKey)2781 TEST_F(DiskCacheEntryTest, SimpleCacheGetKey) {
2782   SetSimpleCacheMode();
2783   InitCache();
2784   GetKey();
2785 }
2786 
TEST_F(DiskCacheEntryTest,SimpleCacheGetTimes)2787 TEST_F(DiskCacheEntryTest, SimpleCacheGetTimes) {
2788   SetSimpleCacheMode();
2789   InitCache();
2790   for (int i = 0; i < disk_cache::kSimpleEntryStreamCount; ++i) {
2791     EXPECT_THAT(DoomAllEntries(), IsOk());
2792     GetTimes(i);
2793   }
2794 }
2795 
TEST_F(DiskCacheEntryTest,SimpleCacheGrowData)2796 TEST_F(DiskCacheEntryTest, SimpleCacheGrowData) {
2797   SetSimpleCacheMode();
2798   InitCache();
2799   for (int i = 0; i < disk_cache::kSimpleEntryStreamCount; ++i) {
2800     EXPECT_THAT(DoomAllEntries(), IsOk());
2801     GrowData(i);
2802   }
2803 }
2804 
TEST_F(DiskCacheEntryTest,SimpleCacheTruncateData)2805 TEST_F(DiskCacheEntryTest, SimpleCacheTruncateData) {
2806   SetSimpleCacheMode();
2807   InitCache();
2808   for (int i = 0; i < disk_cache::kSimpleEntryStreamCount; ++i) {
2809     EXPECT_THAT(DoomAllEntries(), IsOk());
2810     TruncateData(i);
2811   }
2812 }
2813 
TEST_F(DiskCacheEntryTest,SimpleCacheZeroLengthIO)2814 TEST_F(DiskCacheEntryTest, SimpleCacheZeroLengthIO) {
2815   SetSimpleCacheMode();
2816   InitCache();
2817   for (int i = 0; i < disk_cache::kSimpleEntryStreamCount; ++i) {
2818     EXPECT_THAT(DoomAllEntries(), IsOk());
2819     ZeroLengthIO(i);
2820   }
2821 }
2822 
TEST_F(DiskCacheEntryTest,SimpleCacheSizeAtCreate)2823 TEST_F(DiskCacheEntryTest, SimpleCacheSizeAtCreate) {
2824   SetSimpleCacheMode();
2825   InitCache();
2826   SizeAtCreate();
2827 }
2828 
TEST_F(DiskCacheEntryTest,SimpleCacheReuseExternalEntry)2829 TEST_F(DiskCacheEntryTest, SimpleCacheReuseExternalEntry) {
2830   SetSimpleCacheMode();
2831   SetMaxSize(200 * 1024);
2832   InitCache();
2833   for (int i = 0; i < disk_cache::kSimpleEntryStreamCount; ++i) {
2834     EXPECT_THAT(DoomAllEntries(), IsOk());
2835     ReuseEntry(20 * 1024, i);
2836   }
2837 }
2838 
TEST_F(DiskCacheEntryTest,SimpleCacheReuseInternalEntry)2839 TEST_F(DiskCacheEntryTest, SimpleCacheReuseInternalEntry) {
2840   SetSimpleCacheMode();
2841   SetMaxSize(100 * 1024);
2842   InitCache();
2843   for (int i = 0; i < disk_cache::kSimpleEntryStreamCount; ++i) {
2844     EXPECT_THAT(DoomAllEntries(), IsOk());
2845     ReuseEntry(10 * 1024, i);
2846   }
2847 }
2848 
TEST_F(DiskCacheEntryTest,SimpleCacheGiantEntry)2849 TEST_F(DiskCacheEntryTest, SimpleCacheGiantEntry) {
2850   const int kBufSize = 32 * 1024;
2851   auto buffer = base::MakeRefCounted<net::IOBufferWithSize>(kBufSize);
2852   CacheTestFillBuffer(buffer->data(), kBufSize, false);
2853 
2854   // Make sure SimpleCache can write up to 5MiB entry even with a 20MiB cache
2855   // size that Android WebView uses at the time of this test's writing.
2856   SetSimpleCacheMode();
2857   SetMaxSize(20 * 1024 * 1024);
2858   InitCache();
2859 
2860   {
2861     std::string key1("the first key");
2862     disk_cache::Entry* entry1 = nullptr;
2863     ASSERT_THAT(CreateEntry(key1, &entry1), IsOk());
2864 
2865     const int kSize1 = 5 * 1024 * 1024;
2866     EXPECT_EQ(kBufSize, WriteData(entry1, 1 /* stream */, kSize1 - kBufSize,
2867                                   buffer.get(), kBufSize, true /* truncate */));
2868     entry1->Close();
2869   }
2870 
2871   // ... but not bigger than that.
2872   {
2873     std::string key2("the second key");
2874     disk_cache::Entry* entry2 = nullptr;
2875     ASSERT_THAT(CreateEntry(key2, &entry2), IsOk());
2876 
2877     const int kSize2 = 5 * 1024 * 1024 + 1;
2878     EXPECT_EQ(net::ERR_FAILED,
2879               WriteData(entry2, 1 /* stream */, kSize2 - kBufSize, buffer.get(),
2880                         kBufSize, true /* truncate */));
2881     entry2->Close();
2882   }
2883 }
2884 
TEST_F(DiskCacheEntryTest,SimpleCacheSizeChanges)2885 TEST_F(DiskCacheEntryTest, SimpleCacheSizeChanges) {
2886   SetSimpleCacheMode();
2887   InitCache();
2888   for (int i = 0; i < disk_cache::kSimpleEntryStreamCount; ++i) {
2889     EXPECT_THAT(DoomAllEntries(), IsOk());
2890     SizeChanges(i);
2891   }
2892 }
2893 
TEST_F(DiskCacheEntryTest,SimpleCacheInvalidData)2894 TEST_F(DiskCacheEntryTest, SimpleCacheInvalidData) {
2895   SetSimpleCacheMode();
2896   InitCache();
2897   for (int i = 0; i < disk_cache::kSimpleEntryStreamCount; ++i) {
2898     EXPECT_THAT(DoomAllEntries(), IsOk());
2899     InvalidData(i);
2900   }
2901 }
2902 
TEST_F(DiskCacheEntryTest,SimpleCacheReadWriteDestroyBuffer)2903 TEST_F(DiskCacheEntryTest, SimpleCacheReadWriteDestroyBuffer) {
2904   // Proving that the test works well with optimistic operations enabled is
2905   // subtle, instead run only in APP_CACHE mode to disable optimistic
2906   // operations. Stream 0 always uses optimistic operations, so the test is not
2907   // run on stream 0.
2908   SetCacheType(net::APP_CACHE);
2909   SetSimpleCacheMode();
2910   InitCache();
2911   for (int i = 1; i < disk_cache::kSimpleEntryStreamCount; ++i) {
2912     EXPECT_THAT(DoomAllEntries(), IsOk());
2913     ReadWriteDestroyBuffer(i);
2914   }
2915 }
2916 
TEST_F(DiskCacheEntryTest,SimpleCacheDoomEntry)2917 TEST_F(DiskCacheEntryTest, SimpleCacheDoomEntry) {
2918   SetSimpleCacheMode();
2919   InitCache();
2920   DoomNormalEntry();
2921 }
2922 
TEST_F(DiskCacheEntryTest,SimpleCacheDoomEntryNextToOpenEntry)2923 TEST_F(DiskCacheEntryTest, SimpleCacheDoomEntryNextToOpenEntry) {
2924   SetSimpleCacheMode();
2925   InitCache();
2926   DoomEntryNextToOpenEntry();
2927 }
2928 
TEST_F(DiskCacheEntryTest,SimpleCacheDoomedEntry)2929 TEST_F(DiskCacheEntryTest, SimpleCacheDoomedEntry) {
2930   SetSimpleCacheMode();
2931   InitCache();
2932   // Stream 2 is excluded because the implementation does not support writing to
2933   // it on a doomed entry, if it was previously lazily omitted.
2934   for (int i = 0; i < disk_cache::kSimpleEntryStreamCount - 1; ++i) {
2935     EXPECT_THAT(DoomAllEntries(), IsOk());
2936     DoomedEntry(i);
2937   }
2938 }
2939 
2940 // Creates an entry with corrupted last byte in stream 0.
2941 // Requires SimpleCacheMode.
SimpleCacheMakeBadChecksumEntry(const std::string & key,int data_size)2942 bool DiskCacheEntryTest::SimpleCacheMakeBadChecksumEntry(const std::string& key,
2943                                                          int data_size) {
2944   disk_cache::Entry* entry = nullptr;
2945 
2946   if (CreateEntry(key, &entry) != net::OK || !entry) {
2947     LOG(ERROR) << "Could not create entry";
2948     return false;
2949   }
2950 
2951   auto buffer = base::MakeRefCounted<net::IOBufferWithSize>(data_size);
2952   memset(buffer->data(), 'A', data_size);
2953 
2954   EXPECT_EQ(data_size, WriteData(entry, 1, 0, buffer.get(), data_size, false));
2955   entry->Close();
2956   entry = nullptr;
2957 
2958   // Corrupt the last byte of the data.
2959   base::FilePath entry_file0_path = cache_path_.AppendASCII(
2960       disk_cache::simple_util::GetFilenameFromKeyAndFileIndex(key, 0));
2961   base::File entry_file0(entry_file0_path,
2962                          base::File::FLAG_WRITE | base::File::FLAG_OPEN);
2963   if (!entry_file0.IsValid())
2964     return false;
2965 
2966   int64_t file_offset =
2967       sizeof(disk_cache::SimpleFileHeader) + key.size() + data_size - 2;
2968   EXPECT_EQ(1, entry_file0.Write(file_offset, "X", 1));
2969   return true;
2970 }
2971 
TEST_F(DiskCacheEntryTest,SimpleCacheBadChecksum)2972 TEST_F(DiskCacheEntryTest, SimpleCacheBadChecksum) {
2973   SetSimpleCacheMode();
2974   InitCache();
2975 
2976   const char key[] = "the first key";
2977   const int kLargeSize = 50000;
2978   ASSERT_TRUE(SimpleCacheMakeBadChecksumEntry(key, kLargeSize));
2979 
2980   disk_cache::Entry* entry = nullptr;
2981 
2982   // Open the entry. Can't spot the checksum that quickly with it so
2983   // huge.
2984   ASSERT_THAT(OpenEntry(key, &entry), IsOk());
2985   ScopedEntryPtr entry_closer(entry);
2986 
2987   EXPECT_GE(kLargeSize, entry->GetDataSize(1));
2988   auto read_buffer = base::MakeRefCounted<net::IOBufferWithSize>(kLargeSize);
2989   EXPECT_EQ(net::ERR_CACHE_CHECKSUM_MISMATCH,
2990             ReadData(entry, 1, 0, read_buffer.get(), kLargeSize));
2991 }
2992 
2993 // Tests that an entry that has had an IO error occur can still be Doomed().
TEST_F(DiskCacheEntryTest,SimpleCacheErrorThenDoom)2994 TEST_F(DiskCacheEntryTest, SimpleCacheErrorThenDoom) {
2995   SetSimpleCacheMode();
2996   InitCache();
2997 
2998   const char key[] = "the first key";
2999   const int kLargeSize = 50000;
3000   ASSERT_TRUE(SimpleCacheMakeBadChecksumEntry(key, kLargeSize));
3001 
3002   disk_cache::Entry* entry = nullptr;
3003 
3004   // Open the entry, forcing an IO error.
3005   ASSERT_THAT(OpenEntry(key, &entry), IsOk());
3006   ScopedEntryPtr entry_closer(entry);
3007 
3008   EXPECT_GE(kLargeSize, entry->GetDataSize(1));
3009   auto read_buffer = base::MakeRefCounted<net::IOBufferWithSize>(kLargeSize);
3010   EXPECT_EQ(net::ERR_CACHE_CHECKSUM_MISMATCH,
3011             ReadData(entry, 1, 0, read_buffer.get(), kLargeSize));
3012   entry->Doom();  // Should not crash.
3013 }
3014 
TEST_F(DiskCacheEntryTest,SimpleCacheCreateAfterDiskLayerDoom)3015 TEST_F(DiskCacheEntryTest, SimpleCacheCreateAfterDiskLayerDoom) {
3016   // Code coverage for what happens when a queued create runs after failure
3017   // was noticed at SimpleSynchronousEntry layer.
3018   SetSimpleCacheMode();
3019   // Disable optimistic ops so we can block on CreateEntry and start
3020   // WriteData off with an empty op queue.
3021   SetCacheType(net::APP_CACHE);
3022   InitCache();
3023 
3024   const char key[] = "the key";
3025   const int kSize1 = 10;
3026   auto buffer1 = base::MakeRefCounted<net::IOBufferWithSize>(kSize1);
3027   CacheTestFillBuffer(buffer1->data(), kSize1, false);
3028 
3029   disk_cache::Entry* entry = nullptr;
3030   ASSERT_EQ(net::OK, CreateEntry(key, &entry));
3031   ASSERT_TRUE(entry != nullptr);
3032 
3033   // Make an empty _1 file, to cause a stream 2 write to fail.
3034   base::FilePath entry_file1_path = cache_path_.AppendASCII(
3035       disk_cache::simple_util::GetFilenameFromKeyAndFileIndex(key, 1));
3036   base::File entry_file1(entry_file1_path,
3037                          base::File::FLAG_WRITE | base::File::FLAG_CREATE);
3038   ASSERT_TRUE(entry_file1.IsValid());
3039 
3040   entry->WriteData(2, 0, buffer1.get(), kSize1, net::CompletionOnceCallback(),
3041                    /* truncate= */ true);
3042   entry->Close();
3043 
3044   // At this point we have put WriteData & Close on the queue, and WriteData
3045   // started, but we haven't given the event loop control so the failure
3046   // hasn't been reported and handled here, so the entry is still active
3047   // for the key. Queue up another create for same key, and run through the
3048   // events.
3049   disk_cache::Entry* entry2 = nullptr;
3050   ASSERT_EQ(net::ERR_FAILED, CreateEntry(key, &entry2));
3051   ASSERT_TRUE(entry2 == nullptr);
3052 
3053   EXPECT_EQ(0, cache_->GetEntryCount());
3054 
3055   // Should be able to create properly next time, though.
3056   disk_cache::Entry* entry3 = nullptr;
3057   ASSERT_EQ(net::OK, CreateEntry(key, &entry3));
3058   ASSERT_TRUE(entry3 != nullptr);
3059   entry3->Close();
3060 }
3061 
TEST_F(DiskCacheEntryTest,SimpleCacheQueuedOpenOnDoomedEntry)3062 TEST_F(DiskCacheEntryTest, SimpleCacheQueuedOpenOnDoomedEntry) {
3063   // This tests the following sequence of ops:
3064   // A = Create(K);
3065   // Close(A);
3066   // B = Open(K);
3067   // Doom(K);
3068   // Close(B);
3069   //
3070   // ... where the execution of the Open sits on the queue all the way till
3071   // Doom. This now succeeds, as the doom is merely queued at time of Open,
3072   // rather than completed.
3073 
3074   SetSimpleCacheMode();
3075   // Disable optimistic ops so we can block on CreateEntry and start
3076   // WriteData off with an empty op queue.
3077   SetCacheType(net::APP_CACHE);
3078   InitCache();
3079 
3080   const char key[] = "the key";
3081 
3082   disk_cache::Entry* entry = nullptr;
3083   ASSERT_EQ(net::OK, CreateEntry(key, &entry));  // event loop!
3084   ASSERT_TRUE(entry != nullptr);
3085 
3086   entry->Close();
3087 
3088   // Done via cache_ -> no event loop.
3089   TestEntryResultCompletionCallback cb;
3090   EntryResult result = cache_->OpenEntry(key, net::HIGHEST, cb.callback());
3091   ASSERT_EQ(net::ERR_IO_PENDING, result.net_error());
3092 
3093   net::TestCompletionCallback cb2;
3094   cache_->DoomEntry(key, net::HIGHEST, cb2.callback());
3095   // Now event loop.
3096   result = cb.WaitForResult();
3097   EXPECT_EQ(net::OK, result.net_error());
3098   result.ReleaseEntry()->Close();
3099 
3100   EXPECT_EQ(net::OK, cb2.WaitForResult());
3101   EXPECT_EQ(0, cache_->GetEntryCount());
3102 }
3103 
TEST_F(DiskCacheEntryTest,SimpleCacheDoomErrorRace)3104 TEST_F(DiskCacheEntryTest, SimpleCacheDoomErrorRace) {
3105   // Code coverage for a doom racing with a doom induced by a failure.
3106   SetSimpleCacheMode();
3107   // Disable optimistic ops so we can block on CreateEntry and start
3108   // WriteData off with an empty op queue.
3109   SetCacheType(net::APP_CACHE);
3110   InitCache();
3111 
3112   const char kKey[] = "the first key";
3113   const int kSize1 = 10;
3114   auto buffer1 = base::MakeRefCounted<net::IOBufferWithSize>(kSize1);
3115   CacheTestFillBuffer(buffer1->data(), kSize1, false);
3116 
3117   disk_cache::Entry* entry = nullptr;
3118   ASSERT_EQ(net::OK, CreateEntry(kKey, &entry));
3119   ASSERT_TRUE(entry != nullptr);
3120 
3121   // Now an empty _1 file, to cause a stream 2 write to fail.
3122   base::FilePath entry_file1_path = cache_path_.AppendASCII(
3123       disk_cache::simple_util::GetFilenameFromKeyAndFileIndex(kKey, 1));
3124   base::File entry_file1(entry_file1_path,
3125                          base::File::FLAG_WRITE | base::File::FLAG_CREATE);
3126   ASSERT_TRUE(entry_file1.IsValid());
3127 
3128   entry->WriteData(2, 0, buffer1.get(), kSize1, net::CompletionOnceCallback(),
3129                    /* truncate= */ true);
3130 
3131   net::TestCompletionCallback cb;
3132   cache_->DoomEntry(kKey, net::HIGHEST, cb.callback());
3133   entry->Close();
3134   EXPECT_EQ(0, cb.WaitForResult());
3135 }
3136 
TruncatePath(const base::FilePath & file_path,int64_t length)3137 bool TruncatePath(const base::FilePath& file_path, int64_t length) {
3138   base::File file(file_path, base::File::FLAG_WRITE | base::File::FLAG_OPEN);
3139   if (!file.IsValid())
3140     return false;
3141   return file.SetLength(length);
3142 }
3143 
TEST_F(DiskCacheEntryTest,SimpleCacheNoEOF)3144 TEST_F(DiskCacheEntryTest, SimpleCacheNoEOF) {
3145   SetSimpleCacheMode();
3146   InitCache();
3147 
3148   const std::string key("the first key");
3149 
3150   disk_cache::Entry* entry = nullptr;
3151   ASSERT_THAT(CreateEntry(key, &entry), IsOk());
3152   disk_cache::Entry* null = nullptr;
3153   EXPECT_NE(null, entry);
3154   entry->Close();
3155   entry = nullptr;
3156 
3157   // Force the entry to flush to disk, so subsequent platform file operations
3158   // succed.
3159   ASSERT_THAT(OpenEntry(key, &entry), IsOk());
3160   entry->Close();
3161   entry = nullptr;
3162 
3163   // Truncate the file such that the length isn't sufficient to have an EOF
3164   // record.
3165   int kTruncationBytes = -static_cast<int>(sizeof(disk_cache::SimpleFileEOF));
3166   const base::FilePath entry_path = cache_path_.AppendASCII(
3167       disk_cache::simple_util::GetFilenameFromKeyAndFileIndex(key, 0));
3168   const int64_t invalid_size = disk_cache::simple_util::GetFileSizeFromDataSize(
3169       key.size(), kTruncationBytes);
3170   EXPECT_TRUE(TruncatePath(entry_path, invalid_size));
3171   EXPECT_THAT(OpenEntry(key, &entry), IsError(net::ERR_FAILED));
3172   DisableIntegrityCheck();
3173 }
3174 
TEST_F(DiskCacheEntryTest,SimpleCacheNonOptimisticOperationsBasic)3175 TEST_F(DiskCacheEntryTest, SimpleCacheNonOptimisticOperationsBasic) {
3176   // Test sequence:
3177   // Create, Write, Read, Close.
3178   SetCacheType(net::APP_CACHE);  // APP_CACHE doesn't use optimistic operations.
3179   SetSimpleCacheMode();
3180   InitCache();
3181   disk_cache::Entry* const null_entry = nullptr;
3182 
3183   disk_cache::Entry* entry = nullptr;
3184   EXPECT_THAT(CreateEntry("my key", &entry), IsOk());
3185   ASSERT_NE(null_entry, entry);
3186   ScopedEntryPtr entry_closer(entry);
3187 
3188   const int kBufferSize = 10;
3189   scoped_refptr<net::IOBufferWithSize> write_buffer =
3190       base::MakeRefCounted<net::IOBufferWithSize>(kBufferSize);
3191   CacheTestFillBuffer(write_buffer->data(), write_buffer->size(), false);
3192   EXPECT_EQ(
3193       write_buffer->size(),
3194       WriteData(entry, 1, 0, write_buffer.get(), write_buffer->size(), false));
3195 
3196   scoped_refptr<net::IOBufferWithSize> read_buffer =
3197       base::MakeRefCounted<net::IOBufferWithSize>(kBufferSize);
3198   EXPECT_EQ(read_buffer->size(),
3199             ReadData(entry, 1, 0, read_buffer.get(), read_buffer->size()));
3200 }
3201 
TEST_F(DiskCacheEntryTest,SimpleCacheNonOptimisticOperationsDontBlock)3202 TEST_F(DiskCacheEntryTest, SimpleCacheNonOptimisticOperationsDontBlock) {
3203   // Test sequence:
3204   // Create, Write, Close.
3205   SetCacheType(net::APP_CACHE);  // APP_CACHE doesn't use optimistic operations.
3206   SetSimpleCacheMode();
3207   InitCache();
3208   disk_cache::Entry* const null_entry = nullptr;
3209 
3210   MessageLoopHelper helper;
3211   CallbackTest create_callback(&helper, false);
3212 
3213   int expected_callback_runs = 0;
3214   const int kBufferSize = 10;
3215   scoped_refptr<net::IOBufferWithSize> write_buffer =
3216       base::MakeRefCounted<net::IOBufferWithSize>(kBufferSize);
3217 
3218   disk_cache::Entry* entry = nullptr;
3219   EXPECT_THAT(CreateEntry("my key", &entry), IsOk());
3220   ASSERT_NE(null_entry, entry);
3221   ScopedEntryPtr entry_closer(entry);
3222 
3223   CacheTestFillBuffer(write_buffer->data(), write_buffer->size(), false);
3224   CallbackTest write_callback(&helper, false);
3225   int ret = entry->WriteData(
3226       1, 0, write_buffer.get(), write_buffer->size(),
3227       base::BindOnce(&CallbackTest::Run, base::Unretained(&write_callback)),
3228       false);
3229   ASSERT_THAT(ret, IsError(net::ERR_IO_PENDING));
3230   helper.WaitUntilCacheIoFinished(++expected_callback_runs);
3231 }
3232 
TEST_F(DiskCacheEntryTest,SimpleCacheNonOptimisticOperationsBasicsWithoutWaiting)3233 TEST_F(DiskCacheEntryTest,
3234        SimpleCacheNonOptimisticOperationsBasicsWithoutWaiting) {
3235   // Test sequence:
3236   // Create, Write, Read, Close.
3237   SetCacheType(net::APP_CACHE);  // APP_CACHE doesn't use optimistic operations.
3238   SetSimpleCacheMode();
3239   InitCache();
3240   disk_cache::Entry* const null_entry = nullptr;
3241   MessageLoopHelper helper;
3242 
3243   disk_cache::Entry* entry = nullptr;
3244   // Note that |entry| is only set once CreateEntry() completed which is why we
3245   // have to wait (i.e. use the helper CreateEntry() function).
3246   EXPECT_THAT(CreateEntry("my key", &entry), IsOk());
3247   ASSERT_NE(null_entry, entry);
3248   ScopedEntryPtr entry_closer(entry);
3249 
3250   const int kBufferSize = 10;
3251   scoped_refptr<net::IOBufferWithSize> write_buffer =
3252       base::MakeRefCounted<net::IOBufferWithSize>(kBufferSize);
3253   CacheTestFillBuffer(write_buffer->data(), write_buffer->size(), false);
3254   CallbackTest write_callback(&helper, false);
3255   int ret = entry->WriteData(
3256       1, 0, write_buffer.get(), write_buffer->size(),
3257       base::BindOnce(&CallbackTest::Run, base::Unretained(&write_callback)),
3258       false);
3259   EXPECT_THAT(ret, IsError(net::ERR_IO_PENDING));
3260   int expected_callback_runs = 1;
3261 
3262   scoped_refptr<net::IOBufferWithSize> read_buffer =
3263       base::MakeRefCounted<net::IOBufferWithSize>(kBufferSize);
3264   CallbackTest read_callback(&helper, false);
3265   ret = entry->ReadData(
3266       1, 0, read_buffer.get(), read_buffer->size(),
3267       base::BindOnce(&CallbackTest::Run, base::Unretained(&read_callback)));
3268   EXPECT_THAT(ret, IsError(net::ERR_IO_PENDING));
3269   ++expected_callback_runs;
3270 
3271   helper.WaitUntilCacheIoFinished(expected_callback_runs);
3272   ASSERT_EQ(read_buffer->size(), write_buffer->size());
3273   EXPECT_EQ(
3274       0,
3275       memcmp(read_buffer->data(), write_buffer->data(), read_buffer->size()));
3276 }
3277 
TEST_F(DiskCacheEntryTest,SimpleCacheOptimistic)3278 TEST_F(DiskCacheEntryTest, SimpleCacheOptimistic) {
3279   // Test sequence:
3280   // Create, Write, Read, Write, Read, Close.
3281   SetSimpleCacheMode();
3282   InitCache();
3283   disk_cache::Entry* null = nullptr;
3284   const char key[] = "the first key";
3285 
3286   MessageLoopHelper helper;
3287   CallbackTest callback1(&helper, false);
3288   CallbackTest callback2(&helper, false);
3289   CallbackTest callback3(&helper, false);
3290   CallbackTest callback4(&helper, false);
3291   CallbackTest callback5(&helper, false);
3292 
3293   int expected = 0;
3294   const int kSize1 = 10;
3295   const int kSize2 = 20;
3296   auto buffer1 = base::MakeRefCounted<net::IOBufferWithSize>(kSize1);
3297   auto buffer1_read = base::MakeRefCounted<net::IOBufferWithSize>(kSize1);
3298   auto buffer2 = base::MakeRefCounted<net::IOBufferWithSize>(kSize2);
3299   auto buffer2_read = base::MakeRefCounted<net::IOBufferWithSize>(kSize2);
3300   CacheTestFillBuffer(buffer1->data(), kSize1, false);
3301   CacheTestFillBuffer(buffer2->data(), kSize2, false);
3302 
3303   // Create is optimistic, must return OK.
3304   EntryResult result =
3305       cache_->CreateEntry(key, net::HIGHEST,
3306                           base::BindOnce(&CallbackTest::RunWithEntry,
3307                                          base::Unretained(&callback1)));
3308   ASSERT_EQ(net::OK, result.net_error());
3309   disk_cache::Entry* entry = result.ReleaseEntry();
3310   ASSERT_NE(null, entry);
3311   ScopedEntryPtr entry_closer(entry);
3312 
3313   // This write may or may not be optimistic (it depends if the previous
3314   // optimistic create already finished by the time we call the write here).
3315   int ret = entry->WriteData(
3316       1, 0, buffer1.get(), kSize1,
3317       base::BindOnce(&CallbackTest::Run, base::Unretained(&callback2)), false);
3318   EXPECT_TRUE(kSize1 == ret || net::ERR_IO_PENDING == ret);
3319   if (net::ERR_IO_PENDING == ret)
3320     expected++;
3321 
3322   // This Read must not be optimistic, since we don't support that yet.
3323   EXPECT_EQ(net::ERR_IO_PENDING,
3324             entry->ReadData(1, 0, buffer1_read.get(), kSize1,
3325                             base::BindOnce(&CallbackTest::Run,
3326                                            base::Unretained(&callback3))));
3327   expected++;
3328   EXPECT_TRUE(helper.WaitUntilCacheIoFinished(expected));
3329   EXPECT_EQ(0, memcmp(buffer1->data(), buffer1_read->data(), kSize1));
3330 
3331   // At this point after waiting, the pending operations queue on the entry
3332   // should be empty, so the next Write operation must run as optimistic.
3333   EXPECT_EQ(kSize2,
3334             entry->WriteData(1, 0, buffer2.get(), kSize2,
3335                              base::BindOnce(&CallbackTest::Run,
3336                                             base::Unretained(&callback4)),
3337                              false));
3338 
3339   // Lets do another read so we block until both the write and the read
3340   // operation finishes and we can then test for HasOneRef() below.
3341   EXPECT_EQ(net::ERR_IO_PENDING,
3342             entry->ReadData(1, 0, buffer2_read.get(), kSize2,
3343                             base::BindOnce(&CallbackTest::Run,
3344                                            base::Unretained(&callback5))));
3345   expected++;
3346 
3347   EXPECT_TRUE(helper.WaitUntilCacheIoFinished(expected));
3348   EXPECT_EQ(0, memcmp(buffer2->data(), buffer2_read->data(), kSize2));
3349 
3350   // Check that we are not leaking.
3351   EXPECT_NE(entry, null);
3352   EXPECT_TRUE(
3353       static_cast<disk_cache::SimpleEntryImpl*>(entry)->HasOneRef());
3354 }
3355 
TEST_F(DiskCacheEntryTest,SimpleCacheOptimistic2)3356 TEST_F(DiskCacheEntryTest, SimpleCacheOptimistic2) {
3357   // Test sequence:
3358   // Create, Open, Close, Close.
3359   SetSimpleCacheMode();
3360   InitCache();
3361   const char key[] = "the first key";
3362 
3363   MessageLoopHelper helper;
3364   CallbackTest callback1(&helper, false);
3365   CallbackTest callback2(&helper, false);
3366 
3367   EntryResult result =
3368       cache_->CreateEntry(key, net::HIGHEST,
3369                           base::BindOnce(&CallbackTest::RunWithEntry,
3370                                          base::Unretained(&callback1)));
3371   ASSERT_EQ(net::OK, result.net_error());
3372   disk_cache::Entry* entry = result.ReleaseEntry();
3373   ASSERT_NE(nullptr, entry);
3374   ScopedEntryPtr entry_closer(entry);
3375 
3376   EntryResult result2 =
3377       cache_->OpenEntry(key, net::HIGHEST,
3378                         base::BindOnce(&CallbackTest::RunWithEntry,
3379                                        base::Unretained(&callback2)));
3380   ASSERT_EQ(net::ERR_IO_PENDING, result2.net_error());
3381   ASSERT_TRUE(helper.WaitUntilCacheIoFinished(1));
3382   result2 = callback2.ReleaseLastEntryResult();
3383   EXPECT_EQ(net::OK, result2.net_error());
3384   disk_cache::Entry* entry2 = result2.ReleaseEntry();
3385   EXPECT_NE(nullptr, entry2);
3386   EXPECT_EQ(entry, entry2);
3387 
3388   // We have to call close twice, since we called create and open above.
3389   // (the other closes is from |entry_closer|).
3390   entry->Close();
3391 
3392   // Check that we are not leaking.
3393   EXPECT_TRUE(
3394       static_cast<disk_cache::SimpleEntryImpl*>(entry)->HasOneRef());
3395 }
3396 
TEST_F(DiskCacheEntryTest,SimpleCacheOptimistic3)3397 TEST_F(DiskCacheEntryTest, SimpleCacheOptimistic3) {
3398   // Test sequence:
3399   // Create, Close, Open, Close.
3400   SetSimpleCacheMode();
3401   InitCache();
3402   const char key[] = "the first key";
3403 
3404   EntryResult result =
3405       cache_->CreateEntry(key, net::HIGHEST, EntryResultCallback());
3406   ASSERT_EQ(net::OK, result.net_error());
3407   disk_cache::Entry* entry = result.ReleaseEntry();
3408   ASSERT_NE(nullptr, entry);
3409   entry->Close();
3410 
3411   TestEntryResultCompletionCallback cb;
3412   EntryResult result2 = cache_->OpenEntry(key, net::HIGHEST, cb.callback());
3413   ASSERT_EQ(net::ERR_IO_PENDING, result2.net_error());
3414   result2 = cb.WaitForResult();
3415   ASSERT_THAT(result2.net_error(), IsOk());
3416   disk_cache::Entry* entry2 = result2.ReleaseEntry();
3417   ScopedEntryPtr entry_closer(entry2);
3418 
3419   EXPECT_NE(nullptr, entry2);
3420   EXPECT_EQ(entry, entry2);
3421 
3422   // Check that we are not leaking.
3423   EXPECT_TRUE(
3424       static_cast<disk_cache::SimpleEntryImpl*>(entry2)->HasOneRef());
3425 }
3426 
TEST_F(DiskCacheEntryTest,SimpleCacheOptimistic4)3427 TEST_F(DiskCacheEntryTest, SimpleCacheOptimistic4) {
3428   // Test sequence:
3429   // Create, Close, Write, Open, Open, Close, Write, Read, Close.
3430   SetSimpleCacheMode();
3431   InitCache();
3432   const char key[] = "the first key";
3433 
3434   net::TestCompletionCallback cb;
3435   const int kSize1 = 10;
3436   auto buffer1 = base::MakeRefCounted<net::IOBufferWithSize>(kSize1);
3437   CacheTestFillBuffer(buffer1->data(), kSize1, false);
3438 
3439   EntryResult result =
3440       cache_->CreateEntry(key, net::HIGHEST, EntryResultCallback());
3441   ASSERT_EQ(net::OK, result.net_error());
3442   disk_cache::Entry* entry = result.ReleaseEntry();
3443   ASSERT_NE(nullptr, entry);
3444   entry->Close();
3445 
3446   // Lets do a Write so we block until both the Close and the Write
3447   // operation finishes. Write must fail since we are writing in a closed entry.
3448   EXPECT_EQ(
3449       net::ERR_IO_PENDING,
3450       entry->WriteData(1, 0, buffer1.get(), kSize1, cb.callback(), false));
3451   EXPECT_THAT(cb.GetResult(net::ERR_IO_PENDING), IsError(net::ERR_FAILED));
3452 
3453   // Finish running the pending tasks so that we fully complete the close
3454   // operation and destroy the entry object.
3455   base::RunLoop().RunUntilIdle();
3456 
3457   // At this point the |entry| must have been destroyed, and called
3458   // RemoveSelfFromBackend().
3459   TestEntryResultCompletionCallback cb2;
3460   EntryResult result2 = cache_->OpenEntry(key, net::HIGHEST, cb2.callback());
3461   ASSERT_EQ(net::ERR_IO_PENDING, result2.net_error());
3462   result2 = cb2.WaitForResult();
3463   ASSERT_THAT(result2.net_error(), IsOk());
3464   disk_cache::Entry* entry2 = result2.ReleaseEntry();
3465   EXPECT_NE(nullptr, entry2);
3466 
3467   EntryResult result3 = cache_->OpenEntry(key, net::HIGHEST, cb2.callback());
3468   ASSERT_EQ(net::ERR_IO_PENDING, result3.net_error());
3469   result3 = cb2.WaitForResult();
3470   ASSERT_THAT(result3.net_error(), IsOk());
3471   disk_cache::Entry* entry3 = result3.ReleaseEntry();
3472   EXPECT_NE(nullptr, entry3);
3473   EXPECT_EQ(entry2, entry3);
3474   entry3->Close();
3475 
3476   // The previous Close doesn't actually closes the entry since we opened it
3477   // twice, so the next Write operation must succeed and it must be able to
3478   // perform it optimistically, since there is no operation running on this
3479   // entry.
3480   EXPECT_EQ(kSize1, entry2->WriteData(1, 0, buffer1.get(), kSize1,
3481                                       net::CompletionOnceCallback(), false));
3482 
3483   // Lets do another read so we block until both the write and the read
3484   // operation finishes and we can then test for HasOneRef() below.
3485   EXPECT_EQ(net::ERR_IO_PENDING,
3486             entry2->ReadData(1, 0, buffer1.get(), kSize1, cb.callback()));
3487   EXPECT_EQ(kSize1, cb.GetResult(net::ERR_IO_PENDING));
3488 
3489   // Check that we are not leaking.
3490   EXPECT_TRUE(
3491       static_cast<disk_cache::SimpleEntryImpl*>(entry2)->HasOneRef());
3492   entry2->Close();
3493 }
3494 
TEST_F(DiskCacheEntryTest,SimpleCacheOptimistic5)3495 TEST_F(DiskCacheEntryTest, SimpleCacheOptimistic5) {
3496   // Test sequence:
3497   // Create, Doom, Write, Read, Close.
3498   SetSimpleCacheMode();
3499   InitCache();
3500   const char key[] = "the first key";
3501 
3502   net::TestCompletionCallback cb;
3503   const int kSize1 = 10;
3504   auto buffer1 = base::MakeRefCounted<net::IOBufferWithSize>(kSize1);
3505   CacheTestFillBuffer(buffer1->data(), kSize1, false);
3506 
3507   EntryResult result =
3508       cache_->CreateEntry(key, net::HIGHEST, EntryResultCallback());
3509   ASSERT_EQ(net::OK, result.net_error());
3510   disk_cache::Entry* entry = result.ReleaseEntry();
3511   ASSERT_NE(nullptr, entry);
3512   ScopedEntryPtr entry_closer(entry);
3513   entry->Doom();
3514 
3515   EXPECT_EQ(
3516       net::ERR_IO_PENDING,
3517       entry->WriteData(1, 0, buffer1.get(), kSize1, cb.callback(), false));
3518   EXPECT_EQ(kSize1, cb.GetResult(net::ERR_IO_PENDING));
3519 
3520   EXPECT_EQ(net::ERR_IO_PENDING,
3521             entry->ReadData(1, 0, buffer1.get(), kSize1, cb.callback()));
3522   EXPECT_EQ(kSize1, cb.GetResult(net::ERR_IO_PENDING));
3523 
3524   // Check that we are not leaking.
3525   EXPECT_TRUE(
3526       static_cast<disk_cache::SimpleEntryImpl*>(entry)->HasOneRef());
3527 }
3528 
TEST_F(DiskCacheEntryTest,SimpleCacheOptimistic6)3529 TEST_F(DiskCacheEntryTest, SimpleCacheOptimistic6) {
3530   // Test sequence:
3531   // Create, Write, Doom, Doom, Read, Doom, Close.
3532   SetSimpleCacheMode();
3533   InitCache();
3534   const char key[] = "the first key";
3535 
3536   net::TestCompletionCallback cb;
3537   const int kSize1 = 10;
3538   auto buffer1 = base::MakeRefCounted<net::IOBufferWithSize>(kSize1);
3539   auto buffer1_read = base::MakeRefCounted<net::IOBufferWithSize>(kSize1);
3540   CacheTestFillBuffer(buffer1->data(), kSize1, false);
3541 
3542   EntryResult result =
3543       cache_->CreateEntry(key, net::HIGHEST, EntryResultCallback());
3544   ASSERT_EQ(net::OK, result.net_error());
3545   disk_cache::Entry* entry = result.ReleaseEntry();
3546   EXPECT_NE(nullptr, entry);
3547   ScopedEntryPtr entry_closer(entry);
3548 
3549   EXPECT_EQ(
3550       net::ERR_IO_PENDING,
3551       entry->WriteData(1, 0, buffer1.get(), kSize1, cb.callback(), false));
3552   EXPECT_EQ(kSize1, cb.GetResult(net::ERR_IO_PENDING));
3553 
3554   entry->Doom();
3555   entry->Doom();
3556 
3557   // This Read must not be optimistic, since we don't support that yet.
3558   EXPECT_EQ(net::ERR_IO_PENDING,
3559             entry->ReadData(1, 0, buffer1_read.get(), kSize1, cb.callback()));
3560   EXPECT_EQ(kSize1, cb.GetResult(net::ERR_IO_PENDING));
3561   EXPECT_EQ(0, memcmp(buffer1->data(), buffer1_read->data(), kSize1));
3562 
3563   entry->Doom();
3564 }
3565 
3566 // Confirm that IO buffers are not referenced by the Simple Cache after a write
3567 // completes.
TEST_F(DiskCacheEntryTest,SimpleCacheOptimisticWriteReleases)3568 TEST_F(DiskCacheEntryTest, SimpleCacheOptimisticWriteReleases) {
3569   SetSimpleCacheMode();
3570   InitCache();
3571 
3572   const char key[] = "the first key";
3573 
3574   // First, an optimistic create.
3575   EntryResult result =
3576       cache_->CreateEntry(key, net::HIGHEST, EntryResultCallback());
3577   ASSERT_EQ(net::OK, result.net_error());
3578   disk_cache::Entry* entry = result.ReleaseEntry();
3579   ASSERT_TRUE(entry);
3580   ScopedEntryPtr entry_closer(entry);
3581 
3582   const int kWriteSize = 512;
3583   auto buffer1 = base::MakeRefCounted<net::IOBufferWithSize>(kWriteSize);
3584   EXPECT_TRUE(buffer1->HasOneRef());
3585   CacheTestFillBuffer(buffer1->data(), kWriteSize, false);
3586 
3587   // An optimistic write happens only when there is an empty queue of pending
3588   // operations. To ensure the queue is empty, we issue a write and wait until
3589   // it completes.
3590   EXPECT_EQ(kWriteSize,
3591             WriteData(entry, 1, 0, buffer1.get(), kWriteSize, false));
3592   EXPECT_TRUE(buffer1->HasOneRef());
3593 
3594   // Finally, we should perform an optimistic write and confirm that all
3595   // references to the IO buffer have been released.
3596   EXPECT_EQ(kWriteSize, entry->WriteData(1, 0, buffer1.get(), kWriteSize,
3597                                          net::CompletionOnceCallback(), false));
3598   EXPECT_TRUE(buffer1->HasOneRef());
3599 }
3600 
TEST_F(DiskCacheEntryTest,SimpleCacheCreateDoomRace)3601 TEST_F(DiskCacheEntryTest, SimpleCacheCreateDoomRace) {
3602   // Test sequence:
3603   // Create, Doom, Write, Close, Check files are not on disk anymore.
3604   SetSimpleCacheMode();
3605   InitCache();
3606   const char key[] = "the first key";
3607 
3608   net::TestCompletionCallback cb;
3609   const int kSize1 = 10;
3610   auto buffer1 = base::MakeRefCounted<net::IOBufferWithSize>(kSize1);
3611   CacheTestFillBuffer(buffer1->data(), kSize1, false);
3612 
3613   EntryResult result =
3614       cache_->CreateEntry(key, net::HIGHEST, EntryResultCallback());
3615   ASSERT_EQ(net::OK, result.net_error());
3616   disk_cache::Entry* entry = result.ReleaseEntry();
3617   EXPECT_NE(nullptr, entry);
3618 
3619   EXPECT_THAT(cache_->DoomEntry(key, net::HIGHEST, cb.callback()),
3620               IsError(net::ERR_IO_PENDING));
3621   EXPECT_THAT(cb.GetResult(net::ERR_IO_PENDING), IsOk());
3622 
3623   EXPECT_EQ(
3624       kSize1,
3625       entry->WriteData(0, 0, buffer1.get(), kSize1, cb.callback(), false));
3626 
3627   entry->Close();
3628 
3629   // Finish running the pending tasks so that we fully complete the close
3630   // operation and destroy the entry object.
3631   base::RunLoop().RunUntilIdle();
3632 
3633   for (int i = 0; i < disk_cache::kSimpleEntryNormalFileCount; ++i) {
3634     base::FilePath entry_file_path = cache_path_.AppendASCII(
3635         disk_cache::simple_util::GetFilenameFromKeyAndFileIndex(key, i));
3636     base::File::Info info;
3637     EXPECT_FALSE(base::GetFileInfo(entry_file_path, &info));
3638   }
3639 }
3640 
TEST_F(DiskCacheEntryTest,SimpleCacheDoomCreateRace)3641 TEST_F(DiskCacheEntryTest, SimpleCacheDoomCreateRace) {
3642   // This test runs as APP_CACHE to make operations more synchronous. Test
3643   // sequence:
3644   // Create, Doom, Create.
3645   SetCacheType(net::APP_CACHE);
3646   SetSimpleCacheMode();
3647   InitCache();
3648   const char key[] = "the first key";
3649 
3650   TestEntryResultCompletionCallback create_callback;
3651 
3652   EntryResult result1 = create_callback.GetResult(
3653       cache_->CreateEntry(key, net::HIGHEST, create_callback.callback()));
3654   ASSERT_EQ(net::OK, result1.net_error());
3655   disk_cache::Entry* entry1 = result1.ReleaseEntry();
3656   ScopedEntryPtr entry1_closer(entry1);
3657   EXPECT_NE(nullptr, entry1);
3658 
3659   net::TestCompletionCallback doom_callback;
3660   EXPECT_EQ(net::ERR_IO_PENDING,
3661             cache_->DoomEntry(key, net::HIGHEST, doom_callback.callback()));
3662 
3663   EntryResult result2 = create_callback.GetResult(
3664       cache_->CreateEntry(key, net::HIGHEST, create_callback.callback()));
3665   ASSERT_EQ(net::OK, result2.net_error());
3666   disk_cache::Entry* entry2 = result2.ReleaseEntry();
3667   ScopedEntryPtr entry2_closer(entry2);
3668   EXPECT_THAT(doom_callback.GetResult(net::ERR_IO_PENDING), IsOk());
3669 }
3670 
TEST_F(DiskCacheEntryTest,SimpleCacheDoomCreateOptimistic)3671 TEST_F(DiskCacheEntryTest, SimpleCacheDoomCreateOptimistic) {
3672   // Test that we optimize the doom -> create sequence when optimistic ops
3673   // are on.
3674   SetSimpleCacheMode();
3675   InitCache();
3676   const char kKey[] = "the key";
3677 
3678   // Create entry and initiate its Doom.
3679   disk_cache::Entry* entry1 = nullptr;
3680   ASSERT_THAT(CreateEntry(kKey, &entry1), IsOk());
3681   ASSERT_TRUE(entry1 != nullptr);
3682 
3683   net::TestCompletionCallback doom_callback;
3684   cache_->DoomEntry(kKey, net::HIGHEST, doom_callback.callback());
3685 
3686   TestEntryResultCompletionCallback create_callback;
3687   // Open entry2, with same key. With optimistic ops, this should succeed
3688   // immediately, hence us using cache_->CreateEntry directly rather than using
3689   // the DiskCacheTestWithCache::CreateEntry wrapper which blocks when needed.
3690   EntryResult result2 =
3691       cache_->CreateEntry(kKey, net::HIGHEST, create_callback.callback());
3692   ASSERT_EQ(net::OK, result2.net_error());
3693   disk_cache::Entry* entry2 = result2.ReleaseEntry();
3694   ASSERT_NE(nullptr, entry2);
3695 
3696   // Do some I/O to make sure it's alive.
3697   const int kSize = 2048;
3698   auto buf_1 = base::MakeRefCounted<net::IOBufferWithSize>(kSize);
3699   auto buf_2 = base::MakeRefCounted<net::IOBufferWithSize>(kSize);
3700   CacheTestFillBuffer(buf_1->data(), kSize, false);
3701 
3702   EXPECT_EQ(kSize, WriteData(entry2, /* index = */ 1, /* offset = */ 0,
3703                              buf_1.get(), kSize, /* truncate = */ false));
3704   EXPECT_EQ(kSize, ReadData(entry2, /* index = */ 1, /* offset = */ 0,
3705                             buf_2.get(), kSize));
3706 
3707   doom_callback.WaitForResult();
3708 
3709   entry1->Close();
3710   entry2->Close();
3711 }
3712 
TEST_F(DiskCacheEntryTest,SimpleCacheDoomCreateOptimisticMassDoom)3713 TEST_F(DiskCacheEntryTest, SimpleCacheDoomCreateOptimisticMassDoom) {
3714   // Test that shows that a certain DCHECK in mass doom code had to be removed
3715   // once optimistic doom -> create was added.
3716   SetSimpleCacheMode();
3717   InitCache();
3718   const char kKey[] = "the key";
3719 
3720   // Create entry and initiate its Doom.
3721   disk_cache::Entry* entry1 = nullptr;
3722   ASSERT_THAT(CreateEntry(kKey, &entry1), IsOk());
3723   ASSERT_TRUE(entry1 != nullptr);
3724 
3725   net::TestCompletionCallback doom_callback;
3726   cache_->DoomEntry(kKey, net::HIGHEST, doom_callback.callback());
3727 
3728   TestEntryResultCompletionCallback create_callback;
3729   // Open entry2, with same key. With optimistic ops, this should succeed
3730   // immediately, hence us using cache_->CreateEntry directly rather than using
3731   // the DiskCacheTestWithCache::CreateEntry wrapper which blocks when needed.
3732   EntryResult result =
3733       cache_->CreateEntry(kKey, net::HIGHEST, create_callback.callback());
3734   ASSERT_EQ(net::OK, result.net_error());
3735   disk_cache::Entry* entry2 = result.ReleaseEntry();
3736   ASSERT_NE(nullptr, entry2);
3737 
3738   net::TestCompletionCallback doomall_callback;
3739 
3740   // This is what had code that had a no-longer valid DCHECK.
3741   cache_->DoomAllEntries(doomall_callback.callback());
3742 
3743   doom_callback.WaitForResult();
3744   doomall_callback.WaitForResult();
3745 
3746   entry1->Close();
3747   entry2->Close();
3748 }
3749 
TEST_F(DiskCacheEntryTest,SimpleCacheDoomOpenOptimistic)3750 TEST_F(DiskCacheEntryTest, SimpleCacheDoomOpenOptimistic) {
3751   // Test that we optimize the doom -> optimize sequence when optimistic ops
3752   // are on.
3753   SetSimpleCacheMode();
3754   InitCache();
3755   const char kKey[] = "the key";
3756 
3757   // Create entry and initiate its Doom.
3758   disk_cache::Entry* entry1 = nullptr;
3759   ASSERT_THAT(CreateEntry(kKey, &entry1), IsOk());
3760   ASSERT_TRUE(entry1 != nullptr);
3761   entry1->Close();
3762 
3763   net::TestCompletionCallback doom_callback;
3764   cache_->DoomEntry(kKey, net::HIGHEST, doom_callback.callback());
3765 
3766   // Try to open entry. This should detect a miss immediately, since it's
3767   // the only thing after a doom.
3768 
3769   EntryResult result2 =
3770       cache_->OpenEntry(kKey, net::HIGHEST, EntryResultCallback());
3771   EXPECT_EQ(net::ERR_FAILED, result2.net_error());
3772   EXPECT_EQ(nullptr, result2.ReleaseEntry());
3773   doom_callback.WaitForResult();
3774 }
3775 
TEST_F(DiskCacheEntryTest,SimpleCacheDoomDoom)3776 TEST_F(DiskCacheEntryTest, SimpleCacheDoomDoom) {
3777   // Test sequence:
3778   // Create, Doom, Create, Doom (1st entry), Open.
3779   SetSimpleCacheMode();
3780   InitCache();
3781   disk_cache::Entry* null = nullptr;
3782 
3783   const char key[] = "the first key";
3784 
3785   disk_cache::Entry* entry1 = nullptr;
3786   ASSERT_THAT(CreateEntry(key, &entry1), IsOk());
3787   ScopedEntryPtr entry1_closer(entry1);
3788   EXPECT_NE(null, entry1);
3789 
3790   EXPECT_THAT(DoomEntry(key), IsOk());
3791 
3792   disk_cache::Entry* entry2 = nullptr;
3793   ASSERT_THAT(CreateEntry(key, &entry2), IsOk());
3794   ScopedEntryPtr entry2_closer(entry2);
3795   EXPECT_NE(null, entry2);
3796 
3797   // Redundantly dooming entry1 should not delete entry2.
3798   disk_cache::SimpleEntryImpl* simple_entry1 =
3799       static_cast<disk_cache::SimpleEntryImpl*>(entry1);
3800   net::TestCompletionCallback cb;
3801   EXPECT_EQ(net::OK,
3802             cb.GetResult(simple_entry1->DoomEntry(cb.callback())));
3803 
3804   disk_cache::Entry* entry3 = nullptr;
3805   ASSERT_THAT(OpenEntry(key, &entry3), IsOk());
3806   ScopedEntryPtr entry3_closer(entry3);
3807   EXPECT_NE(null, entry3);
3808 }
3809 
TEST_F(DiskCacheEntryTest,SimpleCacheDoomCreateDoom)3810 TEST_F(DiskCacheEntryTest, SimpleCacheDoomCreateDoom) {
3811   // Test sequence:
3812   // Create, Doom, Create, Doom.
3813   SetSimpleCacheMode();
3814   InitCache();
3815 
3816   disk_cache::Entry* null = nullptr;
3817 
3818   const char key[] = "the first key";
3819 
3820   disk_cache::Entry* entry1 = nullptr;
3821   ASSERT_THAT(CreateEntry(key, &entry1), IsOk());
3822   ScopedEntryPtr entry1_closer(entry1);
3823   EXPECT_NE(null, entry1);
3824 
3825   entry1->Doom();
3826 
3827   disk_cache::Entry* entry2 = nullptr;
3828   ASSERT_THAT(CreateEntry(key, &entry2), IsOk());
3829   ScopedEntryPtr entry2_closer(entry2);
3830   EXPECT_NE(null, entry2);
3831 
3832   entry2->Doom();
3833 
3834   // This test passes if it doesn't crash.
3835 }
3836 
TEST_F(DiskCacheEntryTest,SimpleCacheDoomCloseCreateCloseOpen)3837 TEST_F(DiskCacheEntryTest, SimpleCacheDoomCloseCreateCloseOpen) {
3838   // Test sequence: Create, Doom, Close, Create, Close, Open.
3839   SetSimpleCacheMode();
3840   InitCache();
3841 
3842   disk_cache::Entry* null = nullptr;
3843 
3844   const char key[] = "this is a key";
3845 
3846   disk_cache::Entry* entry1 = nullptr;
3847   ASSERT_THAT(CreateEntry(key, &entry1), IsOk());
3848   ScopedEntryPtr entry1_closer(entry1);
3849   EXPECT_NE(null, entry1);
3850 
3851   entry1->Doom();
3852   entry1_closer.reset();
3853   entry1 = nullptr;
3854 
3855   disk_cache::Entry* entry2 = nullptr;
3856   ASSERT_THAT(CreateEntry(key, &entry2), IsOk());
3857   ScopedEntryPtr entry2_closer(entry2);
3858   EXPECT_NE(null, entry2);
3859 
3860   entry2_closer.reset();
3861   entry2 = nullptr;
3862 
3863   disk_cache::Entry* entry3 = nullptr;
3864   ASSERT_THAT(OpenEntry(key, &entry3), IsOk());
3865   ScopedEntryPtr entry3_closer(entry3);
3866   EXPECT_NE(null, entry3);
3867 }
3868 
3869 // Checks that an optimistic Create would fail later on a racing Open.
TEST_F(DiskCacheEntryTest,SimpleCacheOptimisticCreateFailsOnOpen)3870 TEST_F(DiskCacheEntryTest, SimpleCacheOptimisticCreateFailsOnOpen) {
3871   SetSimpleCacheMode();
3872   InitCache();
3873 
3874   // Create a corrupt file in place of a future entry. Optimistic create should
3875   // initially succeed, but realize later that creation failed.
3876   const std::string key = "the key";
3877   disk_cache::Entry* entry = nullptr;
3878   disk_cache::Entry* entry2 = nullptr;
3879 
3880   EXPECT_TRUE(disk_cache::simple_util::CreateCorruptFileForTests(
3881       key, cache_path_));
3882   EntryResult result =
3883       cache_->CreateEntry(key, net::HIGHEST, EntryResultCallback());
3884   EXPECT_THAT(result.net_error(), IsOk());
3885   entry = result.ReleaseEntry();
3886   ASSERT_TRUE(entry);
3887   ScopedEntryPtr entry_closer(entry);
3888   ASSERT_NE(net::OK, OpenEntry(key, &entry2));
3889 
3890   // Check that we are not leaking.
3891   EXPECT_TRUE(
3892       static_cast<disk_cache::SimpleEntryImpl*>(entry)->HasOneRef());
3893 
3894   DisableIntegrityCheck();
3895 }
3896 
3897 // Tests that old entries are evicted while new entries remain in the index.
3898 // This test relies on non-mandatory properties of the simple Cache Backend:
3899 // LRU eviction, specific values of high-watermark and low-watermark etc.
3900 // When changing the eviction algorithm, the test will have to be re-engineered.
TEST_F(DiskCacheEntryTest,SimpleCacheEvictOldEntries)3901 TEST_F(DiskCacheEntryTest, SimpleCacheEvictOldEntries) {
3902   const int kMaxSize = 200 * 1024;
3903   const int kWriteSize = kMaxSize / 10;
3904   const int kNumExtraEntries = 12;
3905   SetSimpleCacheMode();
3906   SetMaxSize(kMaxSize);
3907   InitCache();
3908 
3909   std::string key1("the first key");
3910   disk_cache::Entry* entry;
3911   ASSERT_THAT(CreateEntry(key1, &entry), IsOk());
3912   auto buffer = base::MakeRefCounted<net::IOBufferWithSize>(kWriteSize);
3913   CacheTestFillBuffer(buffer->data(), kWriteSize, false);
3914   EXPECT_EQ(kWriteSize,
3915             WriteData(entry, 1, 0, buffer.get(), kWriteSize, false));
3916   entry->Close();
3917   AddDelay();
3918 
3919   std::string key2("the key prefix");
3920   for (int i = 0; i < kNumExtraEntries; i++) {
3921     if (i == kNumExtraEntries - 2) {
3922       // Create a distinct timestamp for the last two entries. These entries
3923       // will be checked for outliving the eviction.
3924       AddDelay();
3925     }
3926     ASSERT_THAT(CreateEntry(key2 + base::NumberToString(i), &entry), IsOk());
3927     ScopedEntryPtr entry_closer(entry);
3928     EXPECT_EQ(kWriteSize,
3929               WriteData(entry, 1, 0, buffer.get(), kWriteSize, false));
3930   }
3931 
3932   // TODO(pasko): Find a way to wait for the eviction task(s) to finish by using
3933   // the internal knowledge about |SimpleBackendImpl|.
3934   ASSERT_NE(net::OK, OpenEntry(key1, &entry))
3935       << "Should have evicted the old entry";
3936   for (int i = 0; i < 2; i++) {
3937     int entry_no = kNumExtraEntries - i - 1;
3938     // Generally there is no guarantee that at this point the backround eviction
3939     // is finished. We are testing the positive case, i.e. when the eviction
3940     // never reaches this entry, should be non-flaky.
3941     ASSERT_EQ(net::OK, OpenEntry(key2 + base::NumberToString(entry_no), &entry))
3942         << "Should not have evicted fresh entry " << entry_no;
3943     entry->Close();
3944   }
3945 }
3946 
3947 // Tests that if a read and a following in-flight truncate are both in progress
3948 // simultaniously that they both can occur successfully. See
3949 // http://crbug.com/239223
TEST_F(DiskCacheEntryTest,SimpleCacheInFlightTruncate)3950 TEST_F(DiskCacheEntryTest, SimpleCacheInFlightTruncate)  {
3951   SetSimpleCacheMode();
3952   InitCache();
3953 
3954   const char key[] = "the first key";
3955 
3956   // We use a very large entry size here to make sure this doesn't hit
3957   // the prefetch path for any concievable setting. Hitting prefetch would
3958   // make us serve the read below from memory entirely on I/O thread, missing
3959   // the point of the test which coverred two concurrent disk ops, with
3960   // portions of work happening on the workpool.
3961   const int kBufferSize = 50000;
3962   auto write_buffer = base::MakeRefCounted<net::IOBufferWithSize>(kBufferSize);
3963   CacheTestFillBuffer(write_buffer->data(), kBufferSize, false);
3964 
3965   disk_cache::Entry* entry = nullptr;
3966   ASSERT_THAT(CreateEntry(key, &entry), IsOk());
3967 
3968   EXPECT_EQ(kBufferSize,
3969             WriteData(entry, 1, 0, write_buffer.get(), kBufferSize, false));
3970   entry->Close();
3971   entry = nullptr;
3972 
3973   ASSERT_THAT(OpenEntry(key, &entry), IsOk());
3974   ScopedEntryPtr entry_closer(entry);
3975 
3976   MessageLoopHelper helper;
3977   int expected = 0;
3978 
3979   // Make a short read.
3980   const int kReadBufferSize = 512;
3981   auto read_buffer =
3982       base::MakeRefCounted<net::IOBufferWithSize>(kReadBufferSize);
3983   CallbackTest read_callback(&helper, false);
3984   EXPECT_EQ(net::ERR_IO_PENDING,
3985             entry->ReadData(1, 0, read_buffer.get(), kReadBufferSize,
3986                             base::BindOnce(&CallbackTest::Run,
3987                                            base::Unretained(&read_callback))));
3988   ++expected;
3989 
3990   // Truncate the entry to the length of that read.
3991   auto truncate_buffer =
3992       base::MakeRefCounted<net::IOBufferWithSize>(kReadBufferSize);
3993   CacheTestFillBuffer(truncate_buffer->data(), kReadBufferSize, false);
3994   CallbackTest truncate_callback(&helper, false);
3995   EXPECT_EQ(
3996       net::ERR_IO_PENDING,
3997       entry->WriteData(1, 0, truncate_buffer.get(), kReadBufferSize,
3998                        base::BindOnce(&CallbackTest::Run,
3999                                       base::Unretained(&truncate_callback)),
4000                        true));
4001   ++expected;
4002 
4003   // Wait for both the read and truncation to finish, and confirm that both
4004   // succeeded.
4005   EXPECT_TRUE(helper.WaitUntilCacheIoFinished(expected));
4006   EXPECT_EQ(kReadBufferSize, read_callback.last_result());
4007   EXPECT_EQ(kReadBufferSize, truncate_callback.last_result());
4008   EXPECT_EQ(0,
4009             memcmp(write_buffer->data(), read_buffer->data(), kReadBufferSize));
4010 }
4011 
4012 // Tests that if a write and a read dependant on it are both in flight
4013 // simultaneiously that they both can complete successfully without erroneous
4014 // early returns. See http://crbug.com/239223
TEST_F(DiskCacheEntryTest,SimpleCacheInFlightRead)4015 TEST_F(DiskCacheEntryTest, SimpleCacheInFlightRead) {
4016   SetSimpleCacheMode();
4017   InitCache();
4018 
4019   const char key[] = "the first key";
4020   EntryResult result =
4021       cache_->CreateEntry(key, net::HIGHEST, EntryResultCallback());
4022   ASSERT_EQ(net::OK, result.net_error());
4023   disk_cache::Entry* entry = result.ReleaseEntry();
4024   ScopedEntryPtr entry_closer(entry);
4025 
4026   const int kBufferSize = 1024;
4027   auto write_buffer = base::MakeRefCounted<net::IOBufferWithSize>(kBufferSize);
4028   CacheTestFillBuffer(write_buffer->data(), kBufferSize, false);
4029 
4030   MessageLoopHelper helper;
4031   int expected = 0;
4032 
4033   CallbackTest write_callback(&helper, false);
4034   EXPECT_EQ(net::ERR_IO_PENDING,
4035             entry->WriteData(1, 0, write_buffer.get(), kBufferSize,
4036                              base::BindOnce(&CallbackTest::Run,
4037                                             base::Unretained(&write_callback)),
4038                              true));
4039   ++expected;
4040 
4041   auto read_buffer = base::MakeRefCounted<net::IOBufferWithSize>(kBufferSize);
4042   CallbackTest read_callback(&helper, false);
4043   EXPECT_EQ(net::ERR_IO_PENDING,
4044             entry->ReadData(1, 0, read_buffer.get(), kBufferSize,
4045                             base::BindOnce(&CallbackTest::Run,
4046                                            base::Unretained(&read_callback))));
4047   ++expected;
4048 
4049   EXPECT_TRUE(helper.WaitUntilCacheIoFinished(expected));
4050   EXPECT_EQ(kBufferSize, write_callback.last_result());
4051   EXPECT_EQ(kBufferSize, read_callback.last_result());
4052   EXPECT_EQ(0, memcmp(write_buffer->data(), read_buffer->data(), kBufferSize));
4053 }
4054 
TEST_F(DiskCacheEntryTest,SimpleCacheOpenCreateRaceWithNoIndex)4055 TEST_F(DiskCacheEntryTest, SimpleCacheOpenCreateRaceWithNoIndex) {
4056   SetSimpleCacheMode();
4057   DisableSimpleCacheWaitForIndex();
4058   DisableIntegrityCheck();
4059   InitCache();
4060 
4061   // Assume the index is not initialized, which is likely, since we are blocking
4062   // the IO thread from executing the index finalization step.
4063   TestEntryResultCompletionCallback cb1;
4064   TestEntryResultCompletionCallback cb2;
4065   EntryResult rv1 = cache_->OpenEntry("key", net::HIGHEST, cb1.callback());
4066   EntryResult rv2 = cache_->CreateEntry("key", net::HIGHEST, cb2.callback());
4067 
4068   rv1 = cb1.GetResult(std::move(rv1));
4069   EXPECT_THAT(rv1.net_error(), IsError(net::ERR_FAILED));
4070   rv2 = cb2.GetResult(std::move(rv2));
4071   ASSERT_THAT(rv2.net_error(), IsOk());
4072   disk_cache::Entry* entry2 = rv2.ReleaseEntry();
4073 
4074   // Try to get an alias for entry2. Open should succeed, and return the same
4075   // pointer.
4076   disk_cache::Entry* entry3 = nullptr;
4077   ASSERT_EQ(net::OK, OpenEntry("key", &entry3));
4078   EXPECT_EQ(entry3, entry2);
4079 
4080   entry2->Close();
4081   entry3->Close();
4082 }
4083 
4084 // Checking one more scenario of overlapped reading of a bad entry.
4085 // Differs from the |SimpleCacheMultipleReadersCheckCRC| only by the order of
4086 // last two reads.
TEST_F(DiskCacheEntryTest,SimpleCacheMultipleReadersCheckCRC2)4087 TEST_F(DiskCacheEntryTest, SimpleCacheMultipleReadersCheckCRC2) {
4088   SetSimpleCacheMode();
4089   InitCache();
4090 
4091   const char key[] = "key";
4092   int size = 50000;
4093   ASSERT_TRUE(SimpleCacheMakeBadChecksumEntry(key, size));
4094 
4095   auto read_buffer1 = base::MakeRefCounted<net::IOBufferWithSize>(size);
4096   auto read_buffer2 = base::MakeRefCounted<net::IOBufferWithSize>(size);
4097 
4098   // Advance the first reader a little.
4099   disk_cache::Entry* entry = nullptr;
4100   ASSERT_THAT(OpenEntry(key, &entry), IsOk());
4101   ScopedEntryPtr entry_closer(entry);
4102   EXPECT_EQ(1, ReadData(entry, 1, 0, read_buffer1.get(), 1));
4103 
4104   // Advance the 2nd reader by the same amount.
4105   disk_cache::Entry* entry2 = nullptr;
4106   EXPECT_THAT(OpenEntry(key, &entry2), IsOk());
4107   ScopedEntryPtr entry2_closer(entry2);
4108   EXPECT_EQ(1, ReadData(entry2, 1, 0, read_buffer2.get(), 1));
4109 
4110   // Continue reading 1st.
4111   EXPECT_GT(0, ReadData(entry, 1, 1, read_buffer1.get(), size));
4112 
4113   // This read should fail as well because we have previous read failures.
4114   EXPECT_GT(0, ReadData(entry2, 1, 1, read_buffer2.get(), 1));
4115   DisableIntegrityCheck();
4116 }
4117 
4118 // Test if we can sequentially read each subset of the data until all the data
4119 // is read, then the CRC is calculated correctly and the reads are successful.
TEST_F(DiskCacheEntryTest,SimpleCacheReadCombineCRC)4120 TEST_F(DiskCacheEntryTest, SimpleCacheReadCombineCRC) {
4121   // Test sequence:
4122   // Create, Write, Read (first half of data), Read (second half of data),
4123   // Close.
4124   SetSimpleCacheMode();
4125   InitCache();
4126   disk_cache::Entry* null = nullptr;
4127   const char key[] = "the first key";
4128 
4129   const int kHalfSize = 200;
4130   const int kSize = 2 * kHalfSize;
4131   auto buffer1 = base::MakeRefCounted<net::IOBufferWithSize>(kSize);
4132   CacheTestFillBuffer(buffer1->data(), kSize, false);
4133   disk_cache::Entry* entry = nullptr;
4134 
4135   ASSERT_THAT(CreateEntry(key, &entry), IsOk());
4136   EXPECT_NE(null, entry);
4137 
4138   EXPECT_EQ(kSize, WriteData(entry, 1, 0, buffer1.get(), kSize, false));
4139   entry->Close();
4140 
4141   disk_cache::Entry* entry2 = nullptr;
4142   ASSERT_THAT(OpenEntry(key, &entry2), IsOk());
4143   EXPECT_EQ(entry, entry2);
4144 
4145   // Read the first half of the data.
4146   int offset = 0;
4147   int buf_len = kHalfSize;
4148   auto buffer1_read1 = base::MakeRefCounted<net::IOBufferWithSize>(buf_len);
4149   EXPECT_EQ(buf_len, ReadData(entry2, 1, offset, buffer1_read1.get(), buf_len));
4150   EXPECT_EQ(0, memcmp(buffer1->data(), buffer1_read1->data(), buf_len));
4151 
4152   // Read the second half of the data.
4153   offset = buf_len;
4154   buf_len = kHalfSize;
4155   auto buffer1_read2 = base::MakeRefCounted<net::IOBufferWithSize>(buf_len);
4156   EXPECT_EQ(buf_len, ReadData(entry2, 1, offset, buffer1_read2.get(), buf_len));
4157   char* buffer1_data = buffer1->data() + offset;
4158   EXPECT_EQ(0, memcmp(buffer1_data, buffer1_read2->data(), buf_len));
4159 
4160   // Check that we are not leaking.
4161   EXPECT_NE(entry, null);
4162   EXPECT_TRUE(
4163       static_cast<disk_cache::SimpleEntryImpl*>(entry)->HasOneRef());
4164   entry->Close();
4165   entry = nullptr;
4166 }
4167 
4168 // Test if we can write the data not in sequence and read correctly. In
4169 // this case the CRC will not be present.
TEST_F(DiskCacheEntryTest,SimpleCacheNonSequentialWrite)4170 TEST_F(DiskCacheEntryTest, SimpleCacheNonSequentialWrite) {
4171   // Test sequence:
4172   // Create, Write (second half of data), Write (first half of data), Read,
4173   // Close.
4174   SetSimpleCacheMode();
4175   InitCache();
4176   disk_cache::Entry* null = nullptr;
4177   const char key[] = "the first key";
4178 
4179   const int kHalfSize = 200;
4180   const int kSize = 2 * kHalfSize;
4181   auto buffer1 = base::MakeRefCounted<net::IOBufferWithSize>(kSize);
4182   auto buffer2 = base::MakeRefCounted<net::IOBufferWithSize>(kSize);
4183   CacheTestFillBuffer(buffer1->data(), kSize, false);
4184   char* buffer1_data = buffer1->data() + kHalfSize;
4185   memcpy(buffer2->data(), buffer1_data, kHalfSize);
4186 
4187   disk_cache::Entry* entry = nullptr;
4188   ASSERT_THAT(CreateEntry(key, &entry), IsOk());
4189   entry->Close();
4190   for (int i = 0; i < disk_cache::kSimpleEntryStreamCount; ++i) {
4191     ASSERT_THAT(OpenEntry(key, &entry), IsOk());
4192     EXPECT_NE(null, entry);
4193 
4194     int offset = kHalfSize;
4195     int buf_len = kHalfSize;
4196 
4197     EXPECT_EQ(buf_len,
4198               WriteData(entry, i, offset, buffer2.get(), buf_len, false));
4199     offset = 0;
4200     buf_len = kHalfSize;
4201     EXPECT_EQ(buf_len,
4202               WriteData(entry, i, offset, buffer1.get(), buf_len, false));
4203     entry->Close();
4204 
4205     ASSERT_THAT(OpenEntry(key, &entry), IsOk());
4206 
4207     auto buffer1_read1 = base::MakeRefCounted<net::IOBufferWithSize>(kSize);
4208     EXPECT_EQ(kSize, ReadData(entry, i, 0, buffer1_read1.get(), kSize));
4209     EXPECT_EQ(0, memcmp(buffer1->data(), buffer1_read1->data(), kSize));
4210     // Check that we are not leaking.
4211     ASSERT_NE(entry, null);
4212     EXPECT_TRUE(static_cast<disk_cache::SimpleEntryImpl*>(entry)->HasOneRef());
4213     entry->Close();
4214   }
4215 }
4216 
4217 // Test that changing stream1 size does not affect stream0 (stream0 and stream1
4218 // are stored in the same file in Simple Cache).
TEST_F(DiskCacheEntryTest,SimpleCacheStream1SizeChanges)4219 TEST_F(DiskCacheEntryTest, SimpleCacheStream1SizeChanges) {
4220   SetSimpleCacheMode();
4221   InitCache();
4222   disk_cache::Entry* entry = nullptr;
4223   const std::string key("the key");
4224   const int kSize = 100;
4225   auto buffer = base::MakeRefCounted<net::IOBufferWithSize>(kSize);
4226   auto buffer_read = base::MakeRefCounted<net::IOBufferWithSize>(kSize);
4227   CacheTestFillBuffer(buffer->data(), kSize, false);
4228 
4229   ASSERT_THAT(CreateEntry(key, &entry), IsOk());
4230   EXPECT_TRUE(entry);
4231 
4232   // Write something into stream0.
4233   EXPECT_EQ(kSize, WriteData(entry, 0, 0, buffer.get(), kSize, false));
4234   EXPECT_EQ(kSize, ReadData(entry, 0, 0, buffer_read.get(), kSize));
4235   EXPECT_EQ(0, memcmp(buffer->data(), buffer_read->data(), kSize));
4236   entry->Close();
4237 
4238   // Extend stream1.
4239   ASSERT_THAT(OpenEntry(key, &entry), IsOk());
4240   int stream1_size = 100;
4241   EXPECT_EQ(0, WriteData(entry, 1, stream1_size, buffer.get(), 0, false));
4242   EXPECT_EQ(stream1_size, entry->GetDataSize(1));
4243   entry->Close();
4244 
4245   // Check that stream0 data has not been modified and that the EOF record for
4246   // stream 0 contains a crc.
4247   // The entry needs to be reopened before checking the crc: Open will perform
4248   // the synchronization with the previous Close. This ensures the EOF records
4249   // have been written to disk before we attempt to read them independently.
4250   ASSERT_THAT(OpenEntry(key, &entry), IsOk());
4251   base::FilePath entry_file0_path = cache_path_.AppendASCII(
4252       disk_cache::simple_util::GetFilenameFromKeyAndFileIndex(key, 0));
4253   base::File entry_file0(entry_file0_path,
4254                          base::File::FLAG_READ | base::File::FLAG_OPEN);
4255   ASSERT_TRUE(entry_file0.IsValid());
4256 
4257   int data_size[disk_cache::kSimpleEntryStreamCount] = {kSize, stream1_size, 0};
4258   int sparse_data_size = 0;
4259   disk_cache::SimpleEntryStat entry_stat(
4260       base::Time::Now(), base::Time::Now(), data_size, sparse_data_size);
4261   int eof_offset = entry_stat.GetEOFOffsetInFile(key.size(), 0);
4262   disk_cache::SimpleFileEOF eof_record;
4263   ASSERT_EQ(static_cast<int>(sizeof(eof_record)),
4264             entry_file0.Read(eof_offset, reinterpret_cast<char*>(&eof_record),
4265                              sizeof(eof_record)));
4266   EXPECT_EQ(disk_cache::kSimpleFinalMagicNumber, eof_record.final_magic_number);
4267   EXPECT_TRUE((eof_record.flags & disk_cache::SimpleFileEOF::FLAG_HAS_CRC32) ==
4268               disk_cache::SimpleFileEOF::FLAG_HAS_CRC32);
4269 
4270   buffer_read = base::MakeRefCounted<net::IOBufferWithSize>(kSize);
4271   EXPECT_EQ(kSize, ReadData(entry, 0, 0, buffer_read.get(), kSize));
4272   EXPECT_EQ(0, memcmp(buffer->data(), buffer_read->data(), kSize));
4273 
4274   // Shrink stream1.
4275   stream1_size = 50;
4276   EXPECT_EQ(0, WriteData(entry, 1, stream1_size, buffer.get(), 0, true));
4277   EXPECT_EQ(stream1_size, entry->GetDataSize(1));
4278   entry->Close();
4279 
4280   // Check that stream0 data has not been modified.
4281   buffer_read = base::MakeRefCounted<net::IOBufferWithSize>(kSize);
4282   ASSERT_THAT(OpenEntry(key, &entry), IsOk());
4283   EXPECT_EQ(kSize, ReadData(entry, 0, 0, buffer_read.get(), kSize));
4284   EXPECT_EQ(0, memcmp(buffer->data(), buffer_read->data(), kSize));
4285   entry->Close();
4286   entry = nullptr;
4287 }
4288 
4289 // Test that writing within the range for which the crc has already been
4290 // computed will properly invalidate the computed crc.
TEST_F(DiskCacheEntryTest,SimpleCacheCRCRewrite)4291 TEST_F(DiskCacheEntryTest, SimpleCacheCRCRewrite) {
4292   // Test sequence:
4293   // Create, Write (big data), Write (small data in the middle), Close.
4294   // Open, Read (all), Close.
4295   SetSimpleCacheMode();
4296   InitCache();
4297   disk_cache::Entry* null = nullptr;
4298   const char key[] = "the first key";
4299 
4300   const int kHalfSize = 200;
4301   const int kSize = 2 * kHalfSize;
4302   auto buffer1 = base::MakeRefCounted<net::IOBufferWithSize>(kSize);
4303   auto buffer2 = base::MakeRefCounted<net::IOBufferWithSize>(kHalfSize);
4304   CacheTestFillBuffer(buffer1->data(), kSize, false);
4305   CacheTestFillBuffer(buffer2->data(), kHalfSize, false);
4306 
4307   disk_cache::Entry* entry = nullptr;
4308   ASSERT_THAT(CreateEntry(key, &entry), IsOk());
4309   EXPECT_NE(null, entry);
4310   entry->Close();
4311 
4312   for (int i = 0; i < disk_cache::kSimpleEntryStreamCount; ++i) {
4313     ASSERT_THAT(OpenEntry(key, &entry), IsOk());
4314     int offset = 0;
4315     int buf_len = kSize;
4316 
4317     EXPECT_EQ(buf_len,
4318               WriteData(entry, i, offset, buffer1.get(), buf_len, false));
4319     offset = kHalfSize;
4320     buf_len = kHalfSize;
4321     EXPECT_EQ(buf_len,
4322               WriteData(entry, i, offset, buffer2.get(), buf_len, false));
4323     entry->Close();
4324 
4325     ASSERT_THAT(OpenEntry(key, &entry), IsOk());
4326 
4327     auto buffer1_read1 = base::MakeRefCounted<net::IOBufferWithSize>(kSize);
4328     EXPECT_EQ(kSize, ReadData(entry, i, 0, buffer1_read1.get(), kSize));
4329     EXPECT_EQ(0, memcmp(buffer1->data(), buffer1_read1->data(), kHalfSize));
4330     EXPECT_EQ(
4331         0,
4332         memcmp(buffer2->data(), buffer1_read1->data() + kHalfSize, kHalfSize));
4333 
4334     entry->Close();
4335   }
4336 }
4337 
SimpleCacheThirdStreamFileExists(const char * key)4338 bool DiskCacheEntryTest::SimpleCacheThirdStreamFileExists(const char* key) {
4339   int third_stream_file_index =
4340       disk_cache::simple_util::GetFileIndexFromStreamIndex(2);
4341   base::FilePath third_stream_file_path = cache_path_.AppendASCII(
4342       disk_cache::simple_util::GetFilenameFromKeyAndFileIndex(
4343           key, third_stream_file_index));
4344   return PathExists(third_stream_file_path);
4345 }
4346 
SyncDoomEntry(const char * key)4347 void DiskCacheEntryTest::SyncDoomEntry(const char* key) {
4348   net::TestCompletionCallback callback;
4349   cache_->DoomEntry(key, net::HIGHEST, callback.callback());
4350   callback.WaitForResult();
4351 }
4352 
CreateEntryWithHeaderBodyAndSideData(const std::string & key,int data_size)4353 void DiskCacheEntryTest::CreateEntryWithHeaderBodyAndSideData(
4354     const std::string& key,
4355     int data_size) {
4356   // Use one buffer for simplicity.
4357   auto buffer = base::MakeRefCounted<net::IOBufferWithSize>(data_size);
4358   CacheTestFillBuffer(buffer->data(), data_size, false);
4359 
4360   disk_cache::Entry* entry = nullptr;
4361   ASSERT_THAT(CreateEntry(key, &entry), IsOk());
4362   for (int i = 0; i < disk_cache::kSimpleEntryStreamCount; ++i) {
4363     EXPECT_EQ(data_size, WriteData(entry, i, /* offset */ 0, buffer.get(),
4364                                    data_size, false));
4365   }
4366   entry->Close();
4367 }
4368 
TruncateFileFromEnd(int file_index,const std::string & key,int data_size,int truncate_size)4369 void DiskCacheEntryTest::TruncateFileFromEnd(int file_index,
4370                                              const std::string& key,
4371                                              int data_size,
4372                                              int truncate_size) {
4373   // Remove last eof bytes from cache file.
4374   ASSERT_GT(data_size, truncate_size);
4375   const int64_t new_size =
4376       disk_cache::simple_util::GetFileSizeFromDataSize(key.size(), data_size) -
4377       truncate_size;
4378   const base::FilePath entry_path = cache_path_.AppendASCII(
4379       disk_cache::simple_util::GetFilenameFromKeyAndFileIndex(key, file_index));
4380   EXPECT_TRUE(TruncatePath(entry_path, new_size));
4381 }
4382 
UseAfterBackendDestruction()4383 void DiskCacheEntryTest::UseAfterBackendDestruction() {
4384   disk_cache::Entry* entry = nullptr;
4385   ASSERT_THAT(CreateEntry("the first key", &entry), IsOk());
4386   ResetCaches();
4387 
4388   const int kSize = 100;
4389   auto buffer = base::MakeRefCounted<net::IOBufferWithSize>(kSize);
4390   CacheTestFillBuffer(buffer->data(), kSize, false);
4391 
4392   // Do some writes and reads, but don't change the result. We're OK
4393   // with them failing, just not them crashing.
4394   WriteData(entry, 1, 0, buffer.get(), kSize, false);
4395   ReadData(entry, 1, 0, buffer.get(), kSize);
4396   WriteSparseData(entry, 20000, buffer.get(), kSize);
4397 
4398   entry->Close();
4399 }
4400 
CloseSparseAfterBackendDestruction()4401 void DiskCacheEntryTest::CloseSparseAfterBackendDestruction() {
4402   const int kSize = 100;
4403   auto buffer = base::MakeRefCounted<net::IOBufferWithSize>(kSize);
4404   CacheTestFillBuffer(buffer->data(), kSize, false);
4405 
4406   disk_cache::Entry* entry = nullptr;
4407   ASSERT_THAT(CreateEntry("the first key", &entry), IsOk());
4408   WriteSparseData(entry, 20000, buffer.get(), kSize);
4409 
4410   ResetCaches();
4411 
4412   // This call shouldn't DCHECK or crash.
4413   entry->Close();
4414 }
4415 
4416 // Check that a newly-created entry with no third-stream writes omits the
4417 // third stream file.
TEST_F(DiskCacheEntryTest,SimpleCacheOmittedThirdStream1)4418 TEST_F(DiskCacheEntryTest, SimpleCacheOmittedThirdStream1) {
4419   SetSimpleCacheMode();
4420   InitCache();
4421 
4422   const char key[] = "key";
4423 
4424   disk_cache::Entry* entry;
4425 
4426   // Create entry and close without writing: third stream file should be
4427   // omitted, since the stream is empty.
4428   ASSERT_THAT(CreateEntry(key, &entry), IsOk());
4429   entry->Close();
4430   EXPECT_FALSE(SimpleCacheThirdStreamFileExists(key));
4431 
4432   SyncDoomEntry(key);
4433   EXPECT_FALSE(SimpleCacheThirdStreamFileExists(key));
4434 }
4435 
4436 // Check that a newly-created entry with only a single zero-offset, zero-length
4437 // write omits the third stream file.
TEST_F(DiskCacheEntryTest,SimpleCacheOmittedThirdStream2)4438 TEST_F(DiskCacheEntryTest, SimpleCacheOmittedThirdStream2) {
4439   SetSimpleCacheMode();
4440   InitCache();
4441 
4442   const int kHalfSize = 8;
4443   const int kSize = kHalfSize * 2;
4444   const char key[] = "key";
4445   auto buffer = base::MakeRefCounted<net::IOBufferWithSize>(kSize);
4446   CacheTestFillBuffer(buffer->data(), kHalfSize, false);
4447 
4448   disk_cache::Entry* entry;
4449 
4450   // Create entry, write empty buffer to third stream, and close: third stream
4451   // should still be omitted, since the entry ignores writes that don't modify
4452   // data or change the length.
4453   ASSERT_THAT(CreateEntry(key, &entry), IsOk());
4454   EXPECT_EQ(0, WriteData(entry, 2, 0, buffer.get(), 0, true));
4455   entry->Close();
4456   EXPECT_FALSE(SimpleCacheThirdStreamFileExists(key));
4457 
4458   SyncDoomEntry(key);
4459   EXPECT_FALSE(SimpleCacheThirdStreamFileExists(key));
4460 }
4461 
4462 // Check that we can read back data written to the third stream.
TEST_F(DiskCacheEntryTest,SimpleCacheOmittedThirdStream3)4463 TEST_F(DiskCacheEntryTest, SimpleCacheOmittedThirdStream3) {
4464   SetSimpleCacheMode();
4465   InitCache();
4466 
4467   const int kHalfSize = 8;
4468   const int kSize = kHalfSize * 2;
4469   const char key[] = "key";
4470   auto buffer1 = base::MakeRefCounted<net::IOBufferWithSize>(kSize);
4471   auto buffer2 = base::MakeRefCounted<net::IOBufferWithSize>(kSize);
4472   CacheTestFillBuffer(buffer1->data(), kHalfSize, false);
4473 
4474   disk_cache::Entry* entry;
4475 
4476   // Create entry, write data to third stream, and close: third stream should
4477   // not be omitted, since it contains data.  Re-open entry and ensure there
4478   // are that many bytes in the third stream.
4479   ASSERT_THAT(CreateEntry(key, &entry), IsOk());
4480   EXPECT_EQ(kHalfSize, WriteData(entry, 2, 0, buffer1.get(), kHalfSize, true));
4481   entry->Close();
4482   EXPECT_TRUE(SimpleCacheThirdStreamFileExists(key));
4483 
4484   ASSERT_THAT(OpenEntry(key, &entry), IsOk());
4485   EXPECT_EQ(kHalfSize, ReadData(entry, 2, 0, buffer2.get(), kSize));
4486   EXPECT_EQ(0, memcmp(buffer1->data(), buffer2->data(), kHalfSize));
4487   entry->Close();
4488   EXPECT_TRUE(SimpleCacheThirdStreamFileExists(key));
4489 
4490   SyncDoomEntry(key);
4491   EXPECT_FALSE(SimpleCacheThirdStreamFileExists(key));
4492 }
4493 
4494 // Check that we remove the third stream file upon opening an entry and finding
4495 // the third stream empty.  (This is the upgrade path for entries written
4496 // before the third stream was optional.)
TEST_F(DiskCacheEntryTest,SimpleCacheOmittedThirdStream4)4497 TEST_F(DiskCacheEntryTest, SimpleCacheOmittedThirdStream4) {
4498   SetSimpleCacheMode();
4499   InitCache();
4500 
4501   const int kHalfSize = 8;
4502   const int kSize = kHalfSize * 2;
4503   const char key[] = "key";
4504   auto buffer1 = base::MakeRefCounted<net::IOBufferWithSize>(kSize);
4505   auto buffer2 = base::MakeRefCounted<net::IOBufferWithSize>(kSize);
4506   CacheTestFillBuffer(buffer1->data(), kHalfSize, false);
4507 
4508   disk_cache::Entry* entry;
4509 
4510   // Create entry, write data to third stream, truncate third stream back to
4511   // empty, and close: third stream will not initially be omitted, since entry
4512   // creates the file when the first significant write comes in, and only
4513   // removes it on open if it is empty.  Reopen, ensure that the file is
4514   // deleted, and that there's no data in the third stream.
4515   ASSERT_THAT(CreateEntry(key, &entry), IsOk());
4516   EXPECT_EQ(kHalfSize, WriteData(entry, 2, 0, buffer1.get(), kHalfSize, true));
4517   EXPECT_EQ(0, WriteData(entry, 2, 0, buffer1.get(), 0, true));
4518   entry->Close();
4519   EXPECT_TRUE(SimpleCacheThirdStreamFileExists(key));
4520 
4521   ASSERT_THAT(OpenEntry(key, &entry), IsOk());
4522   EXPECT_FALSE(SimpleCacheThirdStreamFileExists(key));
4523   EXPECT_EQ(0, ReadData(entry, 2, 0, buffer2.get(), kSize));
4524   entry->Close();
4525   EXPECT_FALSE(SimpleCacheThirdStreamFileExists(key));
4526 
4527   SyncDoomEntry(key);
4528   EXPECT_FALSE(SimpleCacheThirdStreamFileExists(key));
4529 }
4530 
4531 // Check that we don't accidentally create the third stream file once the entry
4532 // has been doomed.
TEST_F(DiskCacheEntryTest,SimpleCacheOmittedThirdStream5)4533 TEST_F(DiskCacheEntryTest, SimpleCacheOmittedThirdStream5) {
4534   SetSimpleCacheMode();
4535   InitCache();
4536 
4537   const int kHalfSize = 8;
4538   const int kSize = kHalfSize * 2;
4539   const char key[] = "key";
4540   auto buffer = base::MakeRefCounted<net::IOBufferWithSize>(kSize);
4541   CacheTestFillBuffer(buffer->data(), kHalfSize, false);
4542 
4543   disk_cache::Entry* entry;
4544 
4545   // Create entry, doom entry, write data to third stream, and close: third
4546   // stream should not exist.  (Note: We don't care if the write fails, just
4547   // that it doesn't cause the file to be created on disk.)
4548   ASSERT_THAT(CreateEntry(key, &entry), IsOk());
4549   entry->Doom();
4550   WriteData(entry, 2, 0, buffer.get(), kHalfSize, true);
4551   entry->Close();
4552   EXPECT_FALSE(SimpleCacheThirdStreamFileExists(key));
4553 }
4554 
4555 // There could be a race between Doom and an optimistic write.
TEST_F(DiskCacheEntryTest,SimpleCacheDoomOptimisticWritesRace)4556 TEST_F(DiskCacheEntryTest, SimpleCacheDoomOptimisticWritesRace) {
4557   // Test sequence:
4558   // Create, first Write, second Write, Close.
4559   // Open, Close.
4560   SetSimpleCacheMode();
4561   InitCache();
4562   disk_cache::Entry* null = nullptr;
4563   const char key[] = "the first key";
4564 
4565   const int kSize = 200;
4566   auto buffer1 = base::MakeRefCounted<net::IOBufferWithSize>(kSize);
4567   auto buffer2 = base::MakeRefCounted<net::IOBufferWithSize>(kSize);
4568   CacheTestFillBuffer(buffer1->data(), kSize, false);
4569   CacheTestFillBuffer(buffer2->data(), kSize, false);
4570 
4571   // The race only happens on stream 1 and stream 2.
4572   for (int i = 0; i < disk_cache::kSimpleEntryStreamCount; ++i) {
4573     ASSERT_THAT(DoomAllEntries(), IsOk());
4574     disk_cache::Entry* entry = nullptr;
4575 
4576     ASSERT_THAT(CreateEntry(key, &entry), IsOk());
4577     EXPECT_NE(null, entry);
4578     entry->Close();
4579     entry = nullptr;
4580 
4581     ASSERT_THAT(DoomAllEntries(), IsOk());
4582     ASSERT_THAT(CreateEntry(key, &entry), IsOk());
4583     EXPECT_NE(null, entry);
4584 
4585     int offset = 0;
4586     int buf_len = kSize;
4587     // This write should not be optimistic (since create is).
4588     EXPECT_EQ(buf_len,
4589               WriteData(entry, i, offset, buffer1.get(), buf_len, false));
4590 
4591     offset = kSize;
4592     // This write should be optimistic.
4593     EXPECT_EQ(buf_len,
4594               WriteData(entry, i, offset, buffer2.get(), buf_len, false));
4595     entry->Close();
4596 
4597     ASSERT_THAT(OpenEntry(key, &entry), IsOk());
4598     EXPECT_NE(null, entry);
4599 
4600     entry->Close();
4601     entry = nullptr;
4602   }
4603 }
4604 
4605 // Tests for a regression in crbug.com/317138 , in which deleting an already
4606 // doomed entry was removing the active entry from the index.
TEST_F(DiskCacheEntryTest,SimpleCachePreserveActiveEntries)4607 TEST_F(DiskCacheEntryTest, SimpleCachePreserveActiveEntries) {
4608   SetSimpleCacheMode();
4609   InitCache();
4610 
4611   disk_cache::Entry* null = nullptr;
4612 
4613   const char key[] = "this is a key";
4614 
4615   disk_cache::Entry* entry1 = nullptr;
4616   ASSERT_THAT(CreateEntry(key, &entry1), IsOk());
4617   ScopedEntryPtr entry1_closer(entry1);
4618   EXPECT_NE(null, entry1);
4619   entry1->Doom();
4620 
4621   disk_cache::Entry* entry2 = nullptr;
4622   ASSERT_THAT(CreateEntry(key, &entry2), IsOk());
4623   ScopedEntryPtr entry2_closer(entry2);
4624   EXPECT_NE(null, entry2);
4625   entry2_closer.reset();
4626 
4627   // Closing then reopening entry2 insures that entry2 is serialized, and so
4628   // it can be opened from files without error.
4629   entry2 = nullptr;
4630   ASSERT_THAT(OpenEntry(key, &entry2), IsOk());
4631   EXPECT_NE(null, entry2);
4632   entry2_closer.reset(entry2);
4633 
4634   scoped_refptr<disk_cache::SimpleEntryImpl>
4635       entry1_refptr = static_cast<disk_cache::SimpleEntryImpl*>(entry1);
4636 
4637   // If crbug.com/317138 has regressed, this will remove |entry2| from
4638   // the backend's |active_entries_| while |entry2| is still alive and its
4639   // files are still on disk.
4640   entry1_closer.reset();
4641   entry1 = nullptr;
4642 
4643   // Close does not have a callback. However, we need to be sure the close is
4644   // finished before we continue the test. We can take advantage of how the ref
4645   // counting of a SimpleEntryImpl works to fake out a callback: When the
4646   // last Close() call is made to an entry, an IO operation is sent to the
4647   // synchronous entry to close the platform files. This IO operation holds a
4648   // ref pointer to the entry, which expires when the operation is done. So,
4649   // we take a refpointer, and watch the SimpleEntry object until it has only
4650   // one ref; this indicates the IO operation is complete.
4651   while (!entry1_refptr->HasOneRef()) {
4652     base::PlatformThread::YieldCurrentThread();
4653     base::RunLoop().RunUntilIdle();
4654   }
4655   entry1_refptr = nullptr;
4656 
4657   // In the bug case, this new entry ends up being a duplicate object pointing
4658   // at the same underlying files.
4659   disk_cache::Entry* entry3 = nullptr;
4660   EXPECT_THAT(OpenEntry(key, &entry3), IsOk());
4661   ScopedEntryPtr entry3_closer(entry3);
4662   EXPECT_NE(null, entry3);
4663 
4664   // The test passes if these two dooms do not crash.
4665   entry2->Doom();
4666   entry3->Doom();
4667 }
4668 
TEST_F(DiskCacheEntryTest,SimpleCacheBasicSparseIO)4669 TEST_F(DiskCacheEntryTest, SimpleCacheBasicSparseIO) {
4670   SetSimpleCacheMode();
4671   InitCache();
4672   BasicSparseIO();
4673 }
4674 
TEST_F(DiskCacheEntryTest,SimpleCacheHugeSparseIO)4675 TEST_F(DiskCacheEntryTest, SimpleCacheHugeSparseIO) {
4676   SetSimpleCacheMode();
4677   InitCache();
4678   HugeSparseIO();
4679 }
4680 
TEST_F(DiskCacheEntryTest,SimpleCacheGetAvailableRange)4681 TEST_F(DiskCacheEntryTest, SimpleCacheGetAvailableRange) {
4682   SetSimpleCacheMode();
4683   InitCache();
4684   GetAvailableRangeTest();
4685 }
4686 
TEST_F(DiskCacheEntryTest,SimpleCacheUpdateSparseEntry)4687 TEST_F(DiskCacheEntryTest, SimpleCacheUpdateSparseEntry) {
4688   SetSimpleCacheMode();
4689   InitCache();
4690   UpdateSparseEntry();
4691 }
4692 
TEST_F(DiskCacheEntryTest,SimpleCacheDoomSparseEntry)4693 TEST_F(DiskCacheEntryTest, SimpleCacheDoomSparseEntry) {
4694   SetSimpleCacheMode();
4695   InitCache();
4696   DoomSparseEntry();
4697 }
4698 
TEST_F(DiskCacheEntryTest,SimpleCachePartialSparseEntry)4699 TEST_F(DiskCacheEntryTest, SimpleCachePartialSparseEntry) {
4700   SetSimpleCacheMode();
4701   InitCache();
4702   PartialSparseEntry();
4703 }
4704 
TEST_F(DiskCacheEntryTest,SimpleCacheTruncateLargeSparseFile)4705 TEST_F(DiskCacheEntryTest, SimpleCacheTruncateLargeSparseFile) {
4706   const int kSize = 1024;
4707 
4708   SetSimpleCacheMode();
4709   // An entry is allowed sparse data 1/10 the size of the cache, so this size
4710   // allows for one |kSize|-sized range plus overhead, but not two ranges.
4711   SetMaxSize(kSize * 15);
4712   InitCache();
4713 
4714   const char key[] = "key";
4715   disk_cache::Entry* null = nullptr;
4716   disk_cache::Entry* entry;
4717   ASSERT_THAT(CreateEntry(key, &entry), IsOk());
4718   EXPECT_NE(null, entry);
4719 
4720   auto buffer = base::MakeRefCounted<net::IOBufferWithSize>(kSize);
4721   CacheTestFillBuffer(buffer->data(), kSize, false);
4722   net::TestCompletionCallback callback;
4723   int ret;
4724 
4725   // Verify initial conditions.
4726   ret = entry->ReadSparseData(0, buffer.get(), kSize, callback.callback());
4727   EXPECT_EQ(0, callback.GetResult(ret));
4728 
4729   ret = entry->ReadSparseData(kSize, buffer.get(), kSize, callback.callback());
4730   EXPECT_EQ(0, callback.GetResult(ret));
4731 
4732   // Write a range and make sure it reads back.
4733   ret = entry->WriteSparseData(0, buffer.get(), kSize, callback.callback());
4734   EXPECT_EQ(kSize, callback.GetResult(ret));
4735 
4736   ret = entry->ReadSparseData(0, buffer.get(), kSize, callback.callback());
4737   EXPECT_EQ(kSize, callback.GetResult(ret));
4738 
4739   // Write another range and make sure it reads back.
4740   ret = entry->WriteSparseData(kSize, buffer.get(), kSize, callback.callback());
4741   EXPECT_EQ(kSize, callback.GetResult(ret));
4742 
4743   ret = entry->ReadSparseData(kSize, buffer.get(), kSize, callback.callback());
4744   EXPECT_EQ(kSize, callback.GetResult(ret));
4745 
4746   // Make sure the first range was removed when the second was written.
4747   ret = entry->ReadSparseData(0, buffer.get(), kSize, callback.callback());
4748   EXPECT_EQ(0, callback.GetResult(ret));
4749 
4750   // Close and reopen the entry and make sure the first entry is still absent
4751   // and the second entry is still present.
4752   entry->Close();
4753   ASSERT_THAT(OpenEntry(key, &entry), IsOk());
4754 
4755   ret = entry->ReadSparseData(0, buffer.get(), kSize, callback.callback());
4756   EXPECT_EQ(0, callback.GetResult(ret));
4757 
4758   ret = entry->ReadSparseData(kSize, buffer.get(), kSize, callback.callback());
4759   EXPECT_EQ(kSize, callback.GetResult(ret));
4760 
4761   entry->Close();
4762 }
4763 
TEST_F(DiskCacheEntryTest,SimpleCacheNoBodyEOF)4764 TEST_F(DiskCacheEntryTest, SimpleCacheNoBodyEOF) {
4765   SetSimpleCacheMode();
4766   InitCache();
4767 
4768   const std::string key("the first key");
4769   const int kSize = 1024;
4770   CreateEntryWithHeaderBodyAndSideData(key, kSize);
4771 
4772   disk_cache::Entry* entry = nullptr;
4773   ASSERT_THAT(OpenEntry(key, &entry), IsOk());
4774   entry->Close();
4775 
4776   TruncateFileFromEnd(0 /*header and body file index*/, key, kSize,
4777                       static_cast<int>(sizeof(disk_cache::SimpleFileEOF)));
4778   EXPECT_THAT(OpenEntry(key, &entry), IsError(net::ERR_FAILED));
4779 }
4780 
TEST_F(DiskCacheEntryTest,SimpleCacheNoSideDataEOF)4781 TEST_F(DiskCacheEntryTest, SimpleCacheNoSideDataEOF) {
4782   SetSimpleCacheMode();
4783   InitCache();
4784 
4785   const char key[] = "the first key";
4786   const int kSize = 1024;
4787   CreateEntryWithHeaderBodyAndSideData(key, kSize);
4788 
4789   disk_cache::Entry* entry = nullptr;
4790   ASSERT_THAT(OpenEntry(key, &entry), IsOk());
4791   entry->Close();
4792 
4793   TruncateFileFromEnd(1 /*side data file_index*/, key, kSize,
4794                       static_cast<int>(sizeof(disk_cache::SimpleFileEOF)));
4795   EXPECT_THAT(OpenEntry(key, &entry), IsOk());
4796   // The corrupted stream should have been deleted.
4797   EXPECT_FALSE(SimpleCacheThirdStreamFileExists(key));
4798   // _0 should still exist.
4799   base::FilePath path_0 = cache_path_.AppendASCII(
4800       disk_cache::simple_util::GetFilenameFromKeyAndFileIndex(key, 0));
4801   EXPECT_TRUE(base::PathExists(path_0));
4802 
4803   auto check_stream_data = base::MakeRefCounted<net::IOBufferWithSize>(kSize);
4804   EXPECT_EQ(kSize, ReadData(entry, 0, 0, check_stream_data.get(), kSize));
4805   EXPECT_EQ(kSize, ReadData(entry, 1, 0, check_stream_data.get(), kSize));
4806   EXPECT_EQ(0, entry->GetDataSize(2));
4807   entry->Close();
4808 }
4809 
TEST_F(DiskCacheEntryTest,SimpleCacheReadWithoutKeySHA256)4810 TEST_F(DiskCacheEntryTest, SimpleCacheReadWithoutKeySHA256) {
4811   // This test runs as APP_CACHE to make operations more synchronous.
4812   SetCacheType(net::APP_CACHE);
4813   SetSimpleCacheMode();
4814   InitCache();
4815   disk_cache::Entry* entry;
4816   std::string key("a key");
4817   ASSERT_THAT(CreateEntry(key, &entry), IsOk());
4818 
4819   const std::string stream_0_data = "data for stream zero";
4820   auto stream_0_iobuffer =
4821       base::MakeRefCounted<net::StringIOBuffer>(stream_0_data);
4822   EXPECT_EQ(static_cast<int>(stream_0_data.size()),
4823             WriteData(entry, 0, 0, stream_0_iobuffer.get(),
4824                       stream_0_data.size(), false));
4825   const std::string stream_1_data = "FOR STREAM ONE, QUITE DIFFERENT THINGS";
4826   auto stream_1_iobuffer =
4827       base::MakeRefCounted<net::StringIOBuffer>(stream_1_data);
4828   EXPECT_EQ(static_cast<int>(stream_1_data.size()),
4829             WriteData(entry, 1, 0, stream_1_iobuffer.get(),
4830                       stream_1_data.size(), false));
4831   entry->Close();
4832 
4833   base::RunLoop().RunUntilIdle();
4834   disk_cache::FlushCacheThreadForTesting();
4835   base::RunLoop().RunUntilIdle();
4836 
4837   EXPECT_TRUE(
4838       disk_cache::simple_util::RemoveKeySHA256FromEntry(key, cache_path_));
4839   ASSERT_THAT(OpenEntry(key, &entry), IsOk());
4840   ScopedEntryPtr entry_closer(entry);
4841 
4842   EXPECT_EQ(static_cast<int>(stream_0_data.size()), entry->GetDataSize(0));
4843   auto check_stream_0_data =
4844       base::MakeRefCounted<net::IOBufferWithSize>(stream_0_data.size());
4845   EXPECT_EQ(
4846       static_cast<int>(stream_0_data.size()),
4847       ReadData(entry, 0, 0, check_stream_0_data.get(), stream_0_data.size()));
4848   EXPECT_EQ(0, stream_0_data.compare(0, std::string::npos,
4849                                      check_stream_0_data->data(),
4850                                      stream_0_data.size()));
4851 
4852   EXPECT_EQ(static_cast<int>(stream_1_data.size()), entry->GetDataSize(1));
4853   auto check_stream_1_data =
4854       base::MakeRefCounted<net::IOBufferWithSize>(stream_1_data.size());
4855   EXPECT_EQ(
4856       static_cast<int>(stream_1_data.size()),
4857       ReadData(entry, 1, 0, check_stream_1_data.get(), stream_1_data.size()));
4858   EXPECT_EQ(0, stream_1_data.compare(0, std::string::npos,
4859                                      check_stream_1_data->data(),
4860                                      stream_1_data.size()));
4861 }
4862 
TEST_F(DiskCacheEntryTest,SimpleCacheDoubleOpenWithoutKeySHA256)4863 TEST_F(DiskCacheEntryTest, SimpleCacheDoubleOpenWithoutKeySHA256) {
4864   // This test runs as APP_CACHE to make operations more synchronous.
4865   SetCacheType(net::APP_CACHE);
4866   SetSimpleCacheMode();
4867   InitCache();
4868   disk_cache::Entry* entry;
4869   std::string key("a key");
4870   ASSERT_THAT(CreateEntry(key, &entry), IsOk());
4871   entry->Close();
4872 
4873   base::RunLoop().RunUntilIdle();
4874   disk_cache::FlushCacheThreadForTesting();
4875   base::RunLoop().RunUntilIdle();
4876 
4877   EXPECT_TRUE(
4878       disk_cache::simple_util::RemoveKeySHA256FromEntry(key, cache_path_));
4879   ASSERT_THAT(OpenEntry(key, &entry), IsOk());
4880   entry->Close();
4881 
4882   base::RunLoop().RunUntilIdle();
4883   disk_cache::FlushCacheThreadForTesting();
4884   base::RunLoop().RunUntilIdle();
4885 
4886   ASSERT_THAT(OpenEntry(key, &entry), IsOk());
4887   entry->Close();
4888 }
4889 
TEST_F(DiskCacheEntryTest,SimpleCacheReadCorruptKeySHA256)4890 TEST_F(DiskCacheEntryTest, SimpleCacheReadCorruptKeySHA256) {
4891   // This test runs as APP_CACHE to make operations more synchronous.
4892   SetCacheType(net::APP_CACHE);
4893   SetSimpleCacheMode();
4894   InitCache();
4895   disk_cache::Entry* entry;
4896   std::string key("a key");
4897   ASSERT_THAT(CreateEntry(key, &entry), IsOk());
4898   entry->Close();
4899 
4900   base::RunLoop().RunUntilIdle();
4901   disk_cache::FlushCacheThreadForTesting();
4902   base::RunLoop().RunUntilIdle();
4903 
4904   EXPECT_TRUE(
4905       disk_cache::simple_util::CorruptKeySHA256FromEntry(key, cache_path_));
4906   EXPECT_NE(net::OK, OpenEntry(key, &entry));
4907 }
4908 
TEST_F(DiskCacheEntryTest,SimpleCacheReadCorruptLength)4909 TEST_F(DiskCacheEntryTest, SimpleCacheReadCorruptLength) {
4910   SetCacheType(net::APP_CACHE);
4911   SetSimpleCacheMode();
4912   InitCache();
4913   disk_cache::Entry* entry;
4914   std::string key("a key");
4915   ASSERT_EQ(net::OK, CreateEntry(key, &entry));
4916   entry->Close();
4917 
4918   base::RunLoop().RunUntilIdle();
4919   disk_cache::FlushCacheThreadForTesting();
4920   base::RunLoop().RunUntilIdle();
4921 
4922   EXPECT_TRUE(
4923       disk_cache::simple_util::CorruptStream0LengthFromEntry(key, cache_path_));
4924   EXPECT_NE(net::OK, OpenEntry(key, &entry));
4925 }
4926 
TEST_F(DiskCacheEntryTest,SimpleCacheCreateRecoverFromRmdir)4927 TEST_F(DiskCacheEntryTest, SimpleCacheCreateRecoverFromRmdir) {
4928   // This test runs as APP_CACHE to make operations more synchronous.
4929   // (in particular we want to see if create succeeded or not, so we don't
4930   //  want an optimistic one).
4931   SetCacheType(net::APP_CACHE);
4932   SetSimpleCacheMode();
4933   InitCache();
4934 
4935   // Pretend someone deleted the cache dir. This shouldn't be too scary in
4936   // the test since cache_path_ is set as:
4937   //   CHECK(temp_dir_.CreateUniqueTempDir());
4938   //   cache_path_ = temp_dir_.GetPath().AppendASCII("cache");
4939   disk_cache::DeleteCache(cache_path_,
4940                           true /* delete the dir, what we really want*/);
4941 
4942   disk_cache::Entry* entry;
4943   std::string key("a key");
4944   ASSERT_THAT(CreateEntry(key, &entry), IsOk());
4945   entry->Close();
4946 }
4947 
TEST_F(DiskCacheEntryTest,SimpleCacheSparseErrorHandling)4948 TEST_F(DiskCacheEntryTest, SimpleCacheSparseErrorHandling) {
4949   // If there is corruption in sparse file, we should delete all the files
4950   // before returning the failure. Further additional sparse operations in
4951   // failure state should fail gracefully.
4952   SetSimpleCacheMode();
4953   InitCache();
4954 
4955   std::string key("a key");
4956 
4957   disk_cache::SimpleFileTracker::EntryFileKey num_key(
4958       disk_cache::simple_util::GetEntryHashKey(key));
4959   base::FilePath path_0 = cache_path_.AppendASCII(
4960       disk_cache::simple_util::GetFilenameFromEntryFileKeyAndFileIndex(num_key,
4961                                                                        0));
4962   base::FilePath path_s = cache_path_.AppendASCII(
4963       disk_cache::simple_util::GetSparseFilenameFromEntryFileKey(num_key));
4964 
4965   disk_cache::Entry* entry = nullptr;
4966   ASSERT_THAT(CreateEntry(key, &entry), IsOk());
4967 
4968   const int kSize = 1024;
4969   auto buffer = base::MakeRefCounted<net::IOBufferWithSize>(kSize);
4970   CacheTestFillBuffer(buffer->data(), kSize, false);
4971 
4972   EXPECT_EQ(kSize, WriteSparseData(entry, 0, buffer.get(), kSize));
4973   entry->Close();
4974 
4975   disk_cache::FlushCacheThreadForTesting();
4976   EXPECT_TRUE(base::PathExists(path_0));
4977   EXPECT_TRUE(base::PathExists(path_s));
4978 
4979   // Now corrupt the _s file in a way that makes it look OK on open, but not on
4980   // read.
4981   base::File file_s(path_s, base::File::FLAG_OPEN | base::File::FLAG_READ |
4982                                 base::File::FLAG_WRITE);
4983   ASSERT_TRUE(file_s.IsValid());
4984   file_s.SetLength(sizeof(disk_cache::SimpleFileHeader) +
4985                    sizeof(disk_cache::SimpleFileSparseRangeHeader) +
4986                    key.size());
4987   file_s.Close();
4988 
4989   // Re-open, it should still be fine.
4990   ASSERT_THAT(OpenEntry(key, &entry), IsOk());
4991 
4992   // Read should fail though.
4993   EXPECT_EQ(net::ERR_CACHE_READ_FAILURE,
4994             ReadSparseData(entry, 0, buffer.get(), kSize));
4995 
4996   // At the point read returns to us, the files should already been gone.
4997   EXPECT_FALSE(base::PathExists(path_0));
4998   EXPECT_FALSE(base::PathExists(path_s));
4999 
5000   // Re-trying should still fail. Not DCHECK-fail.
5001   EXPECT_EQ(net::ERR_FAILED, ReadSparseData(entry, 0, buffer.get(), kSize));
5002 
5003   // Similarly for other ops.
5004   EXPECT_EQ(net::ERR_FAILED, WriteSparseData(entry, 0, buffer.get(), kSize));
5005   net::TestCompletionCallback cb;
5006 
5007   TestRangeResultCompletionCallback range_cb;
5008   RangeResult result = range_cb.GetResult(
5009       entry->GetAvailableRange(0, 1024, range_cb.callback()));
5010   EXPECT_EQ(net::ERR_FAILED, result.net_error);
5011 
5012   entry->Close();
5013   disk_cache::FlushCacheThreadForTesting();
5014 
5015   // Closing shouldn't resurrect files, either.
5016   EXPECT_FALSE(base::PathExists(path_0));
5017   EXPECT_FALSE(base::PathExists(path_s));
5018 }
5019 
TEST_F(DiskCacheEntryTest,SimpleCacheCreateCollision)5020 TEST_F(DiskCacheEntryTest, SimpleCacheCreateCollision) {
5021   // These two keys collide; this test is that we properly handled creation
5022   // of both.
5023   const char kCollKey1[] =
5024       "\xfb\x4e\x9c\x1d\x66\x71\xf7\x54\xa3\x11\xa0\x7e\x16\xa5\x68\xf6";
5025   const char kCollKey2[] =
5026       "\xbc\x60\x64\x92\xbc\xa0\x5c\x15\x17\x93\x29\x2d\xe4\x21\xbd\x03";
5027 
5028   const int kSize = 256;
5029   auto buffer1 = base::MakeRefCounted<net::IOBufferWithSize>(kSize);
5030   auto buffer2 = base::MakeRefCounted<net::IOBufferWithSize>(kSize);
5031   auto read_buffer = base::MakeRefCounted<net::IOBufferWithSize>(kSize);
5032   CacheTestFillBuffer(buffer1->data(), kSize, false);
5033   CacheTestFillBuffer(buffer2->data(), kSize, false);
5034 
5035   SetSimpleCacheMode();
5036   InitCache();
5037 
5038   disk_cache::Entry* entry1;
5039   ASSERT_THAT(CreateEntry(kCollKey1, &entry1), IsOk());
5040 
5041   disk_cache::Entry* entry2;
5042   ASSERT_THAT(CreateEntry(kCollKey2, &entry2), IsOk());
5043 
5044   // Make sure that entry was actually created and we didn't just succeed
5045   // optimistically. (Oddly I can't seem to hit the sequence of events required
5046   // for the bug that used to be here if I just set this to APP_CACHE).
5047   EXPECT_EQ(kSize, WriteData(entry2, 0, 0, buffer2.get(), kSize, false));
5048 
5049   // entry1 is still usable, though, and distinct (we just won't be able to
5050   // re-open it).
5051   EXPECT_EQ(kSize, WriteData(entry1, 0, 0, buffer1.get(), kSize, false));
5052   EXPECT_EQ(kSize, ReadData(entry1, 0, 0, read_buffer.get(), kSize));
5053   EXPECT_EQ(0, memcmp(buffer1->data(), read_buffer->data(), kSize));
5054 
5055   EXPECT_EQ(kSize, ReadData(entry2, 0, 0, read_buffer.get(), kSize));
5056   EXPECT_EQ(0, memcmp(buffer2->data(), read_buffer->data(), kSize));
5057 
5058   entry1->Close();
5059   entry2->Close();
5060 }
5061 
TEST_F(DiskCacheEntryTest,SimpleCacheConvertToSparseStream2LeftOver)5062 TEST_F(DiskCacheEntryTest, SimpleCacheConvertToSparseStream2LeftOver) {
5063   // Testcase for what happens when we have a sparse stream and a left over
5064   // empty stream 2 file.
5065   const int kSize = 10;
5066   auto buffer = base::MakeRefCounted<net::IOBufferWithSize>(kSize);
5067   CacheTestFillBuffer(buffer->data(), kSize, false);
5068 
5069   SetSimpleCacheMode();
5070   InitCache();
5071   disk_cache::Entry* entry;
5072   std::string key("a key");
5073   ASSERT_THAT(CreateEntry(key, &entry), IsOk());
5074   // Create an empty stream 2. To do that, we first make a non-empty one, then
5075   // truncate it (since otherwise the write would just get ignored).
5076   EXPECT_EQ(kSize, WriteData(entry, /* stream = */ 2, /* offset = */ 0,
5077                              buffer.get(), kSize, false));
5078   EXPECT_EQ(0, WriteData(entry, /* stream = */ 2, /* offset = */ 0,
5079                          buffer.get(), 0, true));
5080 
5081   EXPECT_EQ(kSize, WriteSparseData(entry, 5, buffer.get(), kSize));
5082   entry->Close();
5083 
5084   // Reopen, and try to get the sparse data back.
5085   ASSERT_THAT(OpenEntry(key, &entry), IsOk());
5086   auto buffer2 = base::MakeRefCounted<net::IOBufferWithSize>(kSize);
5087   EXPECT_EQ(kSize, ReadSparseData(entry, 5, buffer2.get(), kSize));
5088   EXPECT_EQ(0, memcmp(buffer->data(), buffer2->data(), kSize));
5089   entry->Close();
5090 }
5091 
TEST_F(DiskCacheEntryTest,SimpleCacheLazyStream2CreateFailure)5092 TEST_F(DiskCacheEntryTest, SimpleCacheLazyStream2CreateFailure) {
5093   // Testcase for what happens when lazy-creation of stream 2 fails.
5094   const int kSize = 10;
5095   auto buffer = base::MakeRefCounted<net::IOBufferWithSize>(kSize);
5096   CacheTestFillBuffer(buffer->data(), kSize, false);
5097 
5098   // Synchronous ops, for ease of disk state;
5099   SetCacheType(net::APP_CACHE);
5100   SetSimpleCacheMode();
5101   InitCache();
5102 
5103   const char kKey[] = "a key";
5104   disk_cache::Entry* entry = nullptr;
5105   ASSERT_THAT(CreateEntry(kKey, &entry), IsOk());
5106 
5107   // Create _1 file for stream 2; this should inject a failure when the cache
5108   // tries to create it itself.
5109   base::FilePath entry_file1_path = cache_path_.AppendASCII(
5110       disk_cache::simple_util::GetFilenameFromKeyAndFileIndex(kKey, 1));
5111   base::File entry_file1(entry_file1_path,
5112                          base::File::FLAG_WRITE | base::File::FLAG_CREATE);
5113   ASSERT_TRUE(entry_file1.IsValid());
5114   entry_file1.Close();
5115 
5116   EXPECT_EQ(net::ERR_CACHE_WRITE_FAILURE,
5117             WriteData(entry, /* index = */ 2, /* offset = */ 0, buffer.get(),
5118                       kSize, /* truncate = */ false));
5119   entry->Close();
5120 }
5121 
TEST_F(DiskCacheEntryTest,SimpleCacheChecksumpScrewUp)5122 TEST_F(DiskCacheEntryTest, SimpleCacheChecksumpScrewUp) {
5123   // Test for a bug that occurred during development of  movement of CRC
5124   // computation off I/O thread.
5125   const int kSize = 10;
5126   auto buffer = base::MakeRefCounted<net::IOBufferWithSize>(kSize);
5127   CacheTestFillBuffer(buffer->data(), kSize, false);
5128 
5129   const int kDoubleSize = kSize * 2;
5130   auto big_buffer = base::MakeRefCounted<net::IOBufferWithSize>(kDoubleSize);
5131   CacheTestFillBuffer(big_buffer->data(), kDoubleSize, false);
5132 
5133   SetSimpleCacheMode();
5134   InitCache();
5135 
5136   const char kKey[] = "a key";
5137   disk_cache::Entry* entry = nullptr;
5138   ASSERT_THAT(CreateEntry(kKey, &entry), IsOk());
5139 
5140   // Write out big_buffer for the double range. Checksum will be set to this.
5141   ASSERT_EQ(kDoubleSize,
5142             WriteData(entry, 1, 0, big_buffer.get(), kDoubleSize, false));
5143 
5144   // Reset remembered position to 0 by writing at an earlier non-zero offset.
5145   ASSERT_EQ(1, WriteData(entry, /* stream = */ 1, /* offset = */ 1,
5146                          big_buffer.get(), /* len = */ 1, false));
5147 
5148   // Now write out the half-range twice. An intermediate revision would
5149   // incorrectly compute checksum as if payload was buffer followed by buffer
5150   // rather than buffer followed by end of big_buffer.
5151   ASSERT_EQ(kSize, WriteData(entry, 1, 0, buffer.get(), kSize, false));
5152   ASSERT_EQ(kSize, WriteData(entry, 1, 0, buffer.get(), kSize, false));
5153   entry->Close();
5154 
5155   ASSERT_THAT(OpenEntry(kKey, &entry), IsOk());
5156   auto buffer2 = base::MakeRefCounted<net::IOBufferWithSize>(kSize);
5157   EXPECT_EQ(kSize, ReadData(entry, 1, 0, buffer2.get(), kSize));
5158   EXPECT_EQ(0, memcmp(buffer->data(), buffer2->data(), kSize));
5159   EXPECT_EQ(kSize, ReadData(entry, 1, kSize, buffer2.get(), kSize));
5160   EXPECT_EQ(0, memcmp(big_buffer->data() + kSize, buffer2->data(), kSize));
5161   entry->Close();
5162 }
5163 
TEST_F(DiskCacheEntryTest,SimpleUseAfterBackendDestruction)5164 TEST_F(DiskCacheEntryTest, SimpleUseAfterBackendDestruction) {
5165   SetSimpleCacheMode();
5166   InitCache();
5167   UseAfterBackendDestruction();
5168 }
5169 
TEST_F(DiskCacheEntryTest,MemoryOnlyUseAfterBackendDestruction)5170 TEST_F(DiskCacheEntryTest, MemoryOnlyUseAfterBackendDestruction) {
5171   // https://crbug.com/741620
5172   SetMemoryOnlyMode();
5173   InitCache();
5174   UseAfterBackendDestruction();
5175 }
5176 
TEST_F(DiskCacheEntryTest,SimpleCloseSparseAfterBackendDestruction)5177 TEST_F(DiskCacheEntryTest, SimpleCloseSparseAfterBackendDestruction) {
5178   SetSimpleCacheMode();
5179   InitCache();
5180   CloseSparseAfterBackendDestruction();
5181 }
5182 
TEST_F(DiskCacheEntryTest,MemoryOnlyCloseSparseAfterBackendDestruction)5183 TEST_F(DiskCacheEntryTest, MemoryOnlyCloseSparseAfterBackendDestruction) {
5184   // https://crbug.com/946434
5185   SetMemoryOnlyMode();
5186   InitCache();
5187   CloseSparseAfterBackendDestruction();
5188 }
5189 
LastUsedTimePersists()5190 void DiskCacheEntryTest::LastUsedTimePersists() {
5191   // Make sure that SetLastUsedTimeForTest persists. When used with SimpleCache,
5192   // this also checks that Entry::GetLastUsed is based on information in index,
5193   // when available, not atime on disk, which can be inaccurate.
5194   const char kKey[] = "a key";
5195   InitCache();
5196 
5197   disk_cache::Entry* entry1 = nullptr;
5198   ASSERT_THAT(CreateEntry(kKey, &entry1), IsOk());
5199   ASSERT_TRUE(nullptr != entry1);
5200   base::Time modified_last_used = entry1->GetLastUsed() - base::Minutes(5);
5201   entry1->SetLastUsedTimeForTest(modified_last_used);
5202   entry1->Close();
5203 
5204   disk_cache::Entry* entry2 = nullptr;
5205   ASSERT_THAT(OpenEntry(kKey, &entry2), IsOk());
5206   ASSERT_TRUE(nullptr != entry2);
5207 
5208   base::TimeDelta diff = modified_last_used - entry2->GetLastUsed();
5209   EXPECT_LT(diff, base::Seconds(2));
5210   EXPECT_GT(diff, -base::Seconds(2));
5211   entry2->Close();
5212 }
5213 
TEST_F(DiskCacheEntryTest,LastUsedTimePersists)5214 TEST_F(DiskCacheEntryTest, LastUsedTimePersists) {
5215   LastUsedTimePersists();
5216 }
5217 
TEST_F(DiskCacheEntryTest,SimpleLastUsedTimePersists)5218 TEST_F(DiskCacheEntryTest, SimpleLastUsedTimePersists) {
5219   SetSimpleCacheMode();
5220   LastUsedTimePersists();
5221 }
5222 
TEST_F(DiskCacheEntryTest,MemoryOnlyLastUsedTimePersists)5223 TEST_F(DiskCacheEntryTest, MemoryOnlyLastUsedTimePersists) {
5224   SetMemoryOnlyMode();
5225   LastUsedTimePersists();
5226 }
5227 
TruncateBackwards()5228 void DiskCacheEntryTest::TruncateBackwards() {
5229   const char kKey[] = "a key";
5230 
5231   disk_cache::Entry* entry = nullptr;
5232   ASSERT_THAT(CreateEntry(kKey, &entry), IsOk());
5233   ASSERT_TRUE(entry != nullptr);
5234 
5235   const int kBigSize = 40 * 1024;
5236   const int kSmallSize = 9727;
5237 
5238   auto buffer = base::MakeRefCounted<net::IOBufferWithSize>(kBigSize);
5239   CacheTestFillBuffer(buffer->data(), kBigSize, false);
5240   auto read_buf = base::MakeRefCounted<net::IOBufferWithSize>(kBigSize);
5241 
5242   ASSERT_EQ(kSmallSize, WriteData(entry, /* index = */ 0,
5243                                   /* offset = */ kBigSize, buffer.get(),
5244                                   /* size = */ kSmallSize,
5245                                   /* truncate = */ false));
5246   memset(read_buf->data(), 0, kBigSize);
5247   ASSERT_EQ(kSmallSize, ReadData(entry, /* index = */ 0,
5248                                  /* offset = */ kBigSize, read_buf.get(),
5249                                  /* size = */ kSmallSize));
5250   EXPECT_EQ(0, memcmp(read_buf->data(), buffer->data(), kSmallSize));
5251 
5252   // A partly overlapping truncate before the previous write.
5253   ASSERT_EQ(kBigSize,
5254             WriteData(entry, /* index = */ 0,
5255                       /* offset = */ 3, buffer.get(), /* size = */ kBigSize,
5256                       /* truncate = */ true));
5257   memset(read_buf->data(), 0, kBigSize);
5258   ASSERT_EQ(kBigSize,
5259             ReadData(entry, /* index = */ 0,
5260                      /* offset = */ 3, read_buf.get(), /* size = */ kBigSize));
5261   EXPECT_EQ(0, memcmp(read_buf->data(), buffer->data(), kBigSize));
5262   EXPECT_EQ(kBigSize + 3, entry->GetDataSize(0));
5263   entry->Close();
5264 }
5265 
TEST_F(DiskCacheEntryTest,TruncateBackwards)5266 TEST_F(DiskCacheEntryTest, TruncateBackwards) {
5267   // https://crbug.com/946539/
5268   InitCache();
5269   TruncateBackwards();
5270 }
5271 
TEST_F(DiskCacheEntryTest,SimpleTruncateBackwards)5272 TEST_F(DiskCacheEntryTest, SimpleTruncateBackwards) {
5273   SetSimpleCacheMode();
5274   InitCache();
5275   TruncateBackwards();
5276 }
5277 
TEST_F(DiskCacheEntryTest,MemoryOnlyTruncateBackwards)5278 TEST_F(DiskCacheEntryTest, MemoryOnlyTruncateBackwards) {
5279   SetMemoryOnlyMode();
5280   InitCache();
5281   TruncateBackwards();
5282 }
5283 
ZeroWriteBackwards()5284 void DiskCacheEntryTest::ZeroWriteBackwards() {
5285   const char kKey[] = "a key";
5286 
5287   disk_cache::Entry* entry = nullptr;
5288   ASSERT_THAT(CreateEntry(kKey, &entry), IsOk());
5289   ASSERT_TRUE(entry != nullptr);
5290 
5291   const int kSize = 1024;
5292   auto buffer = base::MakeRefCounted<net::IOBufferWithSize>(kSize);
5293   CacheTestFillBuffer(buffer->data(), kSize, false);
5294 
5295   // Offset here needs to be > blockfile's kMaxBlockSize to hit
5296   // https://crbug.com/946538, as writes close to beginning are handled
5297   // specially.
5298   EXPECT_EQ(0, WriteData(entry, /* index = */ 0,
5299                          /* offset = */ 17000, buffer.get(),
5300                          /* size = */ 0, /* truncate = */ true));
5301 
5302   EXPECT_EQ(0, WriteData(entry, /* index = */ 0,
5303                          /* offset = */ 0, buffer.get(),
5304                          /* size = */ 0, /* truncate = */ false));
5305 
5306   EXPECT_EQ(kSize, ReadData(entry, /* index = */ 0,
5307                             /* offset = */ 0, buffer.get(),
5308                             /* size = */ kSize));
5309   for (int i = 0; i < kSize; ++i) {
5310     EXPECT_EQ(0, buffer->data()[i]) << i;
5311   }
5312   entry->Close();
5313 }
5314 
TEST_F(DiskCacheEntryTest,ZeroWriteBackwards)5315 TEST_F(DiskCacheEntryTest, ZeroWriteBackwards) {
5316   // https://crbug.com/946538/
5317   InitCache();
5318   ZeroWriteBackwards();
5319 }
5320 
TEST_F(DiskCacheEntryTest,SimpleZeroWriteBackwards)5321 TEST_F(DiskCacheEntryTest, SimpleZeroWriteBackwards) {
5322   SetSimpleCacheMode();
5323   InitCache();
5324   ZeroWriteBackwards();
5325 }
5326 
TEST_F(DiskCacheEntryTest,MemoryOnlyZeroWriteBackwards)5327 TEST_F(DiskCacheEntryTest, MemoryOnlyZeroWriteBackwards) {
5328   SetMemoryOnlyMode();
5329   InitCache();
5330   ZeroWriteBackwards();
5331 }
5332 
SparseOffset64Bit()5333 void DiskCacheEntryTest::SparseOffset64Bit() {
5334   // Offsets to sparse ops are 64-bit, make sure we keep track of all of them.
5335   // (Or, as at least in case of blockfile, fail things cleanly, as it has a
5336   //  cap on max offset that's much lower).
5337   bool blockfile = !memory_only_ && !simple_cache_mode_;
5338   InitCache();
5339 
5340   const char kKey[] = "a key";
5341 
5342   disk_cache::Entry* entry = nullptr;
5343   ASSERT_THAT(CreateEntry(kKey, &entry), IsOk());
5344   ASSERT_TRUE(entry != nullptr);
5345 
5346   const int kSize = 1024;
5347   // One bit set very high, so intermediate truncations to 32-bit would drop it
5348   // even if they happen after a bunch of shifting right.
5349   const int64_t kOffset = (1ll << 61);
5350 
5351   auto buffer = base::MakeRefCounted<net::IOBufferWithSize>(kSize);
5352   CacheTestFillBuffer(buffer->data(), kSize, false);
5353 
5354   EXPECT_EQ(blockfile ? net::ERR_CACHE_OPERATION_NOT_SUPPORTED : kSize,
5355             WriteSparseData(entry, kOffset, buffer.get(), kSize));
5356 
5357   int64_t start_out = -1;
5358   EXPECT_EQ(0, GetAvailableRange(entry, /* offset = */ 0, kSize, &start_out));
5359 
5360   start_out = -1;
5361   EXPECT_EQ(blockfile ? 0 : kSize,
5362             GetAvailableRange(entry, kOffset, kSize, &start_out));
5363   EXPECT_EQ(kOffset, start_out);
5364 
5365   entry->Close();
5366 }
5367 
TEST_F(DiskCacheEntryTest,SparseOffset64Bit)5368 TEST_F(DiskCacheEntryTest, SparseOffset64Bit) {
5369   InitCache();
5370   SparseOffset64Bit();
5371 }
5372 
TEST_F(DiskCacheEntryTest,SimpleSparseOffset64Bit)5373 TEST_F(DiskCacheEntryTest, SimpleSparseOffset64Bit) {
5374   SetSimpleCacheMode();
5375   InitCache();
5376   SparseOffset64Bit();
5377 }
5378 
TEST_F(DiskCacheEntryTest,MemoryOnlySparseOffset64Bit)5379 TEST_F(DiskCacheEntryTest, MemoryOnlySparseOffset64Bit) {
5380   // https://crbug.com/946436
5381   SetMemoryOnlyMode();
5382   InitCache();
5383   SparseOffset64Bit();
5384 }
5385 
TEST_F(DiskCacheEntryTest,SimpleCacheCloseResurrection)5386 TEST_F(DiskCacheEntryTest, SimpleCacheCloseResurrection) {
5387   const int kSize = 10;
5388   auto buffer = base::MakeRefCounted<net::IOBufferWithSize>(kSize);
5389   CacheTestFillBuffer(buffer->data(), kSize, false);
5390 
5391   const char kKey[] = "key";
5392   SetSimpleCacheMode();
5393   InitCache();
5394 
5395   disk_cache::Entry* entry = nullptr;
5396   ASSERT_THAT(CreateEntry(kKey, &entry), IsOk());
5397   ASSERT_TRUE(entry != nullptr);
5398 
5399   // Let optimistic create finish.
5400   base::RunLoop().RunUntilIdle();
5401   disk_cache::FlushCacheThreadForTesting();
5402   base::RunLoop().RunUntilIdle();
5403 
5404   int rv = entry->WriteData(1, 0, buffer.get(), kSize,
5405                             net::CompletionOnceCallback(), false);
5406 
5407   // Write should be optimistic.
5408   ASSERT_EQ(kSize, rv);
5409 
5410   // Since the write is still pending, the open will get queued...
5411   TestEntryResultCompletionCallback cb_open;
5412   EntryResult result2 =
5413       cache_->OpenEntry(kKey, net::HIGHEST, cb_open.callback());
5414   EXPECT_EQ(net::ERR_IO_PENDING, result2.net_error());
5415 
5416   // ... as the open is queued, this Close will temporarily reduce the number
5417   // of external references to 0.  This should not break things.
5418   entry->Close();
5419 
5420   // Wait till open finishes.
5421   result2 = cb_open.GetResult(std::move(result2));
5422   ASSERT_EQ(net::OK, result2.net_error());
5423   disk_cache::Entry* entry2 = result2.ReleaseEntry();
5424   ASSERT_TRUE(entry2 != nullptr);
5425 
5426   // Get first close a chance to finish.
5427   base::RunLoop().RunUntilIdle();
5428   disk_cache::FlushCacheThreadForTesting();
5429   base::RunLoop().RunUntilIdle();
5430 
5431   // Make sure |entry2| is still usable.
5432   auto buffer2 = base::MakeRefCounted<net::IOBufferWithSize>(kSize);
5433   memset(buffer2->data(), 0, kSize);
5434   EXPECT_EQ(kSize, ReadData(entry2, 1, 0, buffer2.get(), kSize));
5435   EXPECT_EQ(0, memcmp(buffer->data(), buffer2->data(), kSize));
5436   entry2->Close();
5437 }
5438 
TEST_F(DiskCacheEntryTest,BlockFileSparsePendingAfterDtor)5439 TEST_F(DiskCacheEntryTest, BlockFileSparsePendingAfterDtor) {
5440   // Test of behavior of ~EntryImpl for sparse entry that runs after backend
5441   // destruction.
5442   //
5443   // Hand-creating the backend for realistic shutdown behavior.
5444   CleanupCacheDir();
5445   CreateBackend(disk_cache::kNone);
5446 
5447   disk_cache::Entry* entry = nullptr;
5448   ASSERT_THAT(CreateEntry("key", &entry), IsOk());
5449   ASSERT_TRUE(entry != nullptr);
5450 
5451   const int kSize = 61184;
5452 
5453   auto buf = base::MakeRefCounted<net::IOBufferWithSize>(kSize);
5454   CacheTestFillBuffer(buf->data(), kSize, false);
5455 
5456   // The write pattern here avoids the second write being handled by the
5457   // buffering layer, making SparseControl have to deal with its asynchrony.
5458   EXPECT_EQ(1, WriteSparseData(entry, 65535, buf.get(), 1));
5459   EXPECT_EQ(net::ERR_IO_PENDING,
5460             entry->WriteSparseData(2560, buf.get(), kSize, base::DoNothing()));
5461   entry->Close();
5462   ResetCaches();
5463 
5464   // Create a new instance as a way of flushing the thread.
5465   InitCache();
5466   FlushQueueForTest();
5467 }
5468 
5469 class DiskCacheSimplePrefetchTest : public DiskCacheEntryTest {
5470  public:
5471   DiskCacheSimplePrefetchTest() = default;
5472 
5473   enum { kEntrySize = 1024 };
5474 
SetUp()5475   void SetUp() override {
5476     payload_ = base::MakeRefCounted<net::IOBufferWithSize>(kEntrySize);
5477     CacheTestFillBuffer(payload_->data(), kEntrySize, false);
5478     DiskCacheEntryTest::SetUp();
5479   }
5480 
SetupFullAndTrailerPrefetch(int full_size,int trailer_speculative_size)5481   void SetupFullAndTrailerPrefetch(int full_size,
5482                                    int trailer_speculative_size) {
5483     std::map<std::string, std::string> params;
5484     params[disk_cache::kSimpleCacheFullPrefetchBytesParam] =
5485         base::NumberToString(full_size);
5486     params[disk_cache::kSimpleCacheTrailerPrefetchSpeculativeBytesParam] =
5487         base::NumberToString(trailer_speculative_size);
5488     scoped_feature_list_.InitAndEnableFeatureWithParameters(
5489         disk_cache::kSimpleCachePrefetchExperiment, params);
5490   }
5491 
SetupFullPrefetch(int size)5492   void SetupFullPrefetch(int size) { SetupFullAndTrailerPrefetch(size, 0); }
5493 
InitCacheAndCreateEntry(const std::string & key)5494   void InitCacheAndCreateEntry(const std::string& key) {
5495     SetSimpleCacheMode();
5496     SetCacheType(SimpleCacheType());
5497     InitCache();
5498 
5499     disk_cache::Entry* entry;
5500     ASSERT_EQ(net::OK, CreateEntry(key, &entry));
5501     // Use stream 1 since that's what new prefetch stuff is about.
5502     ASSERT_EQ(kEntrySize,
5503               WriteData(entry, 1, 0, payload_.get(), kEntrySize, false));
5504     entry->Close();
5505   }
5506 
SimpleCacheType() const5507   virtual net::CacheType SimpleCacheType() const { return net::DISK_CACHE; }
5508 
InitCacheAndCreateEntryWithNoCrc(const std::string & key)5509   void InitCacheAndCreateEntryWithNoCrc(const std::string& key) {
5510     const int kHalfSize = kEntrySize / 2;
5511     const int kRemSize = kEntrySize - kHalfSize;
5512 
5513     SetSimpleCacheMode();
5514     InitCache();
5515 
5516     disk_cache::Entry* entry;
5517     ASSERT_EQ(net::OK, CreateEntry(key, &entry));
5518     // Use stream 1 since that's what new prefetch stuff is about.
5519     ASSERT_EQ(kEntrySize,
5520               WriteData(entry, 1, 0, payload_.get(), kEntrySize, false));
5521 
5522     // Overwrite later part of the buffer, since we can't keep track of
5523     // the checksum in that case.  Do it with identical contents, though,
5524     // so that the only difference between here and InitCacheAndCreateEntry()
5525     // would be whether the result has a checkum or not.
5526     auto second_half = base::MakeRefCounted<net::IOBufferWithSize>(kRemSize);
5527     memcpy(second_half->data(), payload_->data() + kHalfSize, kRemSize);
5528     ASSERT_EQ(kRemSize, WriteData(entry, 1, kHalfSize, second_half.get(),
5529                                   kRemSize, false));
5530     entry->Close();
5531   }
5532 
TryRead(const std::string & key,bool expect_preread_stream1)5533   void TryRead(const std::string& key, bool expect_preread_stream1) {
5534     disk_cache::Entry* entry = nullptr;
5535     ASSERT_THAT(OpenEntry(key, &entry), IsOk());
5536     auto read_buf = base::MakeRefCounted<net::IOBufferWithSize>(kEntrySize);
5537     net::TestCompletionCallback cb;
5538     int rv = entry->ReadData(1, 0, read_buf.get(), kEntrySize, cb.callback());
5539 
5540     // if preload happened, sync reply is expected.
5541     if (expect_preread_stream1)
5542       EXPECT_EQ(kEntrySize, rv);
5543     else
5544       EXPECT_EQ(net::ERR_IO_PENDING, rv);
5545     rv = cb.GetResult(rv);
5546     EXPECT_EQ(kEntrySize, rv);
5547     EXPECT_EQ(0, memcmp(read_buf->data(), payload_->data(), kEntrySize));
5548     entry->Close();
5549   }
5550 
5551  protected:
5552   scoped_refptr<net::IOBuffer> payload_;
5553   base::test::ScopedFeatureList scoped_feature_list_;
5554 };
5555 
TEST_F(DiskCacheSimplePrefetchTest,NoPrefetch)5556 TEST_F(DiskCacheSimplePrefetchTest, NoPrefetch) {
5557   base::HistogramTester histogram_tester;
5558   SetupFullPrefetch(0);
5559 
5560   const char kKey[] = "a key";
5561   InitCacheAndCreateEntry(kKey);
5562   TryRead(kKey, /* expect_preread_stream1 */ false);
5563 
5564   histogram_tester.ExpectUniqueSample("SimpleCache.Http.SyncOpenPrefetchMode",
5565                                       disk_cache::OPEN_PREFETCH_NONE, 1);
5566 }
5567 
TEST_F(DiskCacheSimplePrefetchTest,YesPrefetch)5568 TEST_F(DiskCacheSimplePrefetchTest, YesPrefetch) {
5569   base::HistogramTester histogram_tester;
5570   SetupFullPrefetch(2 * kEntrySize);
5571 
5572   const char kKey[] = "a key";
5573   InitCacheAndCreateEntry(kKey);
5574   TryRead(kKey, /* expect_preread_stream1 */ true);
5575 
5576   histogram_tester.ExpectUniqueSample("SimpleCache.Http.SyncOpenPrefetchMode",
5577                                       disk_cache::OPEN_PREFETCH_FULL, 1);
5578 }
5579 
TEST_F(DiskCacheSimplePrefetchTest,YesPrefetchNoRead)5580 TEST_F(DiskCacheSimplePrefetchTest, YesPrefetchNoRead) {
5581   base::HistogramTester histogram_tester;
5582   SetupFullPrefetch(2 * kEntrySize);
5583 
5584   const char kKey[] = "a key";
5585   InitCacheAndCreateEntry(kKey);
5586 
5587   disk_cache::Entry* entry = nullptr;
5588   ASSERT_THAT(OpenEntry(kKey, &entry), IsOk());
5589   entry->Close();
5590 
5591   histogram_tester.ExpectUniqueSample("SimpleCache.Http.SyncOpenPrefetchMode",
5592                                       disk_cache::OPEN_PREFETCH_FULL, 1);
5593 }
5594 
5595 // This makes sure we detect checksum error on entry that's small enough to be
5596 // prefetched. This is like DiskCacheEntryTest.BadChecksum, but we make sure
5597 // to configure prefetch explicitly.
TEST_F(DiskCacheSimplePrefetchTest,BadChecksumSmall)5598 TEST_F(DiskCacheSimplePrefetchTest, BadChecksumSmall) {
5599   SetupFullPrefetch(1024);  // bigger than stuff below.
5600   SetSimpleCacheMode();
5601   InitCache();
5602 
5603   const char key[] = "the first key";
5604   ASSERT_TRUE(SimpleCacheMakeBadChecksumEntry(key, 10));
5605 
5606   disk_cache::Entry* entry = nullptr;
5607 
5608   // Open the entry. Since we made a small entry, we will detect the CRC
5609   // problem at open.
5610   EXPECT_THAT(OpenEntry(key, &entry), IsError(net::ERR_FAILED));
5611 }
5612 
TEST_F(DiskCacheSimplePrefetchTest,ChecksumNoPrefetch)5613 TEST_F(DiskCacheSimplePrefetchTest, ChecksumNoPrefetch) {
5614   base::HistogramTester histogram_tester;
5615 
5616   SetupFullPrefetch(0);
5617   const char kKey[] = "a key";
5618   InitCacheAndCreateEntry(kKey);
5619   TryRead(kKey, /* expect_preread_stream1 */ false);
5620 
5621   histogram_tester.ExpectUniqueSample("SimpleCache.Http.SyncCheckEOFResult",
5622                                       disk_cache::CHECK_EOF_RESULT_SUCCESS, 2);
5623 }
5624 
TEST_F(DiskCacheSimplePrefetchTest,NoChecksumNoPrefetch)5625 TEST_F(DiskCacheSimplePrefetchTest, NoChecksumNoPrefetch) {
5626   base::HistogramTester histogram_tester;
5627 
5628   SetupFullPrefetch(0);
5629   const char kKey[] = "a key";
5630   InitCacheAndCreateEntryWithNoCrc(kKey);
5631   TryRead(kKey, /* expect_preread_stream1 */ false);
5632 
5633   histogram_tester.ExpectUniqueSample("SimpleCache.Http.SyncCheckEOFResult",
5634                                       disk_cache::CHECK_EOF_RESULT_SUCCESS, 2);
5635 }
5636 
TEST_F(DiskCacheSimplePrefetchTest,ChecksumPrefetch)5637 TEST_F(DiskCacheSimplePrefetchTest, ChecksumPrefetch) {
5638   base::HistogramTester histogram_tester;
5639 
5640   SetupFullPrefetch(2 * kEntrySize);
5641   const char kKey[] = "a key";
5642   InitCacheAndCreateEntry(kKey);
5643   TryRead(kKey, /* expect_preread_stream1 */ true);
5644 
5645   histogram_tester.ExpectUniqueSample("SimpleCache.Http.SyncCheckEOFResult",
5646                                       disk_cache::CHECK_EOF_RESULT_SUCCESS, 2);
5647 }
5648 
TEST_F(DiskCacheSimplePrefetchTest,NoChecksumPrefetch)5649 TEST_F(DiskCacheSimplePrefetchTest, NoChecksumPrefetch) {
5650   base::HistogramTester histogram_tester;
5651 
5652   SetupFullPrefetch(2 * kEntrySize);
5653   const char kKey[] = "a key";
5654   InitCacheAndCreateEntryWithNoCrc(kKey);
5655   TryRead(kKey, /* expect_preread_stream1 */ true);
5656 
5657   // EOF check is recorded even if there is no CRC there.
5658   histogram_tester.ExpectUniqueSample("SimpleCache.Http.SyncCheckEOFResult",
5659                                       disk_cache::CHECK_EOF_RESULT_SUCCESS, 2);
5660 }
5661 
TEST_F(DiskCacheSimplePrefetchTest,PrefetchReadsSync)5662 TEST_F(DiskCacheSimplePrefetchTest, PrefetchReadsSync) {
5663   // Make sure we can read things synchronously after prefetch.
5664   SetupFullPrefetch(32768);  // way bigger than kEntrySize
5665   const char kKey[] = "a key";
5666   InitCacheAndCreateEntry(kKey);
5667 
5668   disk_cache::Entry* entry = nullptr;
5669   ASSERT_THAT(OpenEntry(kKey, &entry), IsOk());
5670   auto read_buf = base::MakeRefCounted<net::IOBufferWithSize>(kEntrySize);
5671 
5672   // That this is entry->ReadData(...) rather than ReadData(entry, ...) is
5673   // meaningful here, as the latter is a helper in the test fixture that blocks
5674   // if needed.
5675   EXPECT_EQ(kEntrySize, entry->ReadData(1, 0, read_buf.get(), kEntrySize,
5676                                         net::CompletionOnceCallback()));
5677   EXPECT_EQ(0, memcmp(read_buf->data(), payload_->data(), kEntrySize));
5678   entry->Close();
5679 }
5680 
TEST_F(DiskCacheSimplePrefetchTest,NoFullNoSpeculative)5681 TEST_F(DiskCacheSimplePrefetchTest, NoFullNoSpeculative) {
5682   base::HistogramTester histogram_tester;
5683   SetupFullAndTrailerPrefetch(0, 0);
5684 
5685   const char kKey[] = "a key";
5686   InitCacheAndCreateEntry(kKey);
5687   TryRead(kKey, /* expect_preread_stream1 */ false);
5688 
5689   histogram_tester.ExpectUniqueSample("SimpleCache.Http.SyncOpenPrefetchMode",
5690                                       disk_cache::OPEN_PREFETCH_NONE, 1);
5691 }
5692 
TEST_F(DiskCacheSimplePrefetchTest,NoFullSmallSpeculative)5693 TEST_F(DiskCacheSimplePrefetchTest, NoFullSmallSpeculative) {
5694   base::HistogramTester histogram_tester;
5695   SetupFullAndTrailerPrefetch(0, kEntrySize / 2);
5696 
5697   const char kKey[] = "a key";
5698   InitCacheAndCreateEntry(kKey);
5699   TryRead(kKey, /* expect_preread_stream1 */ false);
5700 
5701   histogram_tester.ExpectUniqueSample("SimpleCache.Http.SyncOpenPrefetchMode",
5702                                       disk_cache::OPEN_PREFETCH_TRAILER, 1);
5703 }
5704 
TEST_F(DiskCacheSimplePrefetchTest,NoFullLargeSpeculative)5705 TEST_F(DiskCacheSimplePrefetchTest, NoFullLargeSpeculative) {
5706   base::HistogramTester histogram_tester;
5707   // A large speculative trailer prefetch that exceeds the entry file
5708   // size should effectively trigger full prefetch behavior.
5709   SetupFullAndTrailerPrefetch(0, kEntrySize * 2);
5710 
5711   const char kKey[] = "a key";
5712   InitCacheAndCreateEntry(kKey);
5713   TryRead(kKey, /* expect_preread_stream1 */ true);
5714 
5715   histogram_tester.ExpectUniqueSample("SimpleCache.Http.SyncOpenPrefetchMode",
5716                                       disk_cache::OPEN_PREFETCH_FULL, 1);
5717 }
5718 
TEST_F(DiskCacheSimplePrefetchTest,SmallFullNoSpeculative)5719 TEST_F(DiskCacheSimplePrefetchTest, SmallFullNoSpeculative) {
5720   base::HistogramTester histogram_tester;
5721   SetupFullAndTrailerPrefetch(kEntrySize / 2, 0);
5722 
5723   const char kKey[] = "a key";
5724   InitCacheAndCreateEntry(kKey);
5725   TryRead(kKey, /* expect_preread_stream1 */ false);
5726 
5727   histogram_tester.ExpectUniqueSample("SimpleCache.Http.SyncOpenPrefetchMode",
5728                                       disk_cache::OPEN_PREFETCH_NONE, 1);
5729 }
5730 
TEST_F(DiskCacheSimplePrefetchTest,LargeFullNoSpeculative)5731 TEST_F(DiskCacheSimplePrefetchTest, LargeFullNoSpeculative) {
5732   base::HistogramTester histogram_tester;
5733   SetupFullAndTrailerPrefetch(kEntrySize * 2, 0);
5734 
5735   const char kKey[] = "a key";
5736   InitCacheAndCreateEntry(kKey);
5737   TryRead(kKey, /* expect_preread_stream1 */ true);
5738 
5739   histogram_tester.ExpectUniqueSample("SimpleCache.Http.SyncOpenPrefetchMode",
5740                                       disk_cache::OPEN_PREFETCH_FULL, 1);
5741 }
5742 
TEST_F(DiskCacheSimplePrefetchTest,SmallFullSmallSpeculative)5743 TEST_F(DiskCacheSimplePrefetchTest, SmallFullSmallSpeculative) {
5744   base::HistogramTester histogram_tester;
5745   SetupFullAndTrailerPrefetch(kEntrySize / 2, kEntrySize / 2);
5746 
5747   const char kKey[] = "a key";
5748   InitCacheAndCreateEntry(kKey);
5749   TryRead(kKey, /* expect_preread_stream1 */ false);
5750 
5751   histogram_tester.ExpectUniqueSample("SimpleCache.Http.SyncOpenPrefetchMode",
5752                                       disk_cache::OPEN_PREFETCH_TRAILER, 1);
5753 }
5754 
TEST_F(DiskCacheSimplePrefetchTest,LargeFullSmallSpeculative)5755 TEST_F(DiskCacheSimplePrefetchTest, LargeFullSmallSpeculative) {
5756   base::HistogramTester histogram_tester;
5757   // Full prefetch takes precedence over a trailer speculative prefetch.
5758   SetupFullAndTrailerPrefetch(kEntrySize * 2, kEntrySize / 2);
5759 
5760   const char kKey[] = "a key";
5761   InitCacheAndCreateEntry(kKey);
5762   TryRead(kKey, /* expect_preread_stream1 */ true);
5763 
5764   histogram_tester.ExpectUniqueSample("SimpleCache.Http.SyncOpenPrefetchMode",
5765                                       disk_cache::OPEN_PREFETCH_FULL, 1);
5766 }
5767 
5768 class DiskCacheSimpleAppCachePrefetchTest : public DiskCacheSimplePrefetchTest {
5769  public:
5770   // APP_CACHE mode will enable trailer prefetch hint support.
SimpleCacheType() const5771   net::CacheType SimpleCacheType() const override { return net::APP_CACHE; }
5772 };
5773 
TEST_F(DiskCacheSimpleAppCachePrefetchTest,NoFullNoSpeculative)5774 TEST_F(DiskCacheSimpleAppCachePrefetchTest, NoFullNoSpeculative) {
5775   base::HistogramTester histogram_tester;
5776   SetupFullAndTrailerPrefetch(0, 0);
5777 
5778   const char kKey[] = "a key";
5779   InitCacheAndCreateEntry(kKey);
5780   TryRead(kKey, /* expect_preread_stream1 */ false);
5781 
5782   histogram_tester.ExpectUniqueSample("SimpleCache.App.SyncOpenPrefetchMode",
5783                                       disk_cache::OPEN_PREFETCH_TRAILER, 1);
5784 }
5785 
TEST_F(DiskCacheSimpleAppCachePrefetchTest,NoFullSmallSpeculative)5786 TEST_F(DiskCacheSimpleAppCachePrefetchTest, NoFullSmallSpeculative) {
5787   base::HistogramTester histogram_tester;
5788   SetupFullAndTrailerPrefetch(0, kEntrySize / 2);
5789 
5790   const char kKey[] = "a key";
5791   InitCacheAndCreateEntry(kKey);
5792   TryRead(kKey, /* expect_preread_stream1 */ false);
5793 
5794   histogram_tester.ExpectUniqueSample("SimpleCache.App.SyncOpenPrefetchMode",
5795                                       disk_cache::OPEN_PREFETCH_TRAILER, 1);
5796 }
5797 
TEST_F(DiskCacheSimpleAppCachePrefetchTest,NoFullLargeSpeculative)5798 TEST_F(DiskCacheSimpleAppCachePrefetchTest, NoFullLargeSpeculative) {
5799   base::HistogramTester histogram_tester;
5800   // Even though the speculative trailer prefetch size is larger than the
5801   // file size, the hint should take precedence and still perform a limited
5802   // trailer prefetch.
5803   SetupFullAndTrailerPrefetch(0, kEntrySize * 2);
5804 
5805   const char kKey[] = "a key";
5806   InitCacheAndCreateEntry(kKey);
5807   TryRead(kKey, /* expect_preread_stream1 */ false);
5808 
5809   histogram_tester.ExpectUniqueSample("SimpleCache.App.SyncOpenPrefetchMode",
5810                                       disk_cache::OPEN_PREFETCH_TRAILER, 1);
5811 }
5812 
TEST_F(DiskCacheSimpleAppCachePrefetchTest,SmallFullNoSpeculative)5813 TEST_F(DiskCacheSimpleAppCachePrefetchTest, SmallFullNoSpeculative) {
5814   base::HistogramTester histogram_tester;
5815   SetupFullAndTrailerPrefetch(kEntrySize / 2, 0);
5816 
5817   const char kKey[] = "a key";
5818   InitCacheAndCreateEntry(kKey);
5819   TryRead(kKey, /* expect_preread_stream1 */ false);
5820 
5821   histogram_tester.ExpectUniqueSample("SimpleCache.App.SyncOpenPrefetchMode",
5822                                       disk_cache::OPEN_PREFETCH_TRAILER, 1);
5823 }
5824 
TEST_F(DiskCacheSimpleAppCachePrefetchTest,LargeFullNoSpeculative)5825 TEST_F(DiskCacheSimpleAppCachePrefetchTest, LargeFullNoSpeculative) {
5826   base::HistogramTester histogram_tester;
5827   // Full prefetch takes precedence over a trailer hint prefetch.
5828   SetupFullAndTrailerPrefetch(kEntrySize * 2, 0);
5829 
5830   const char kKey[] = "a key";
5831   InitCacheAndCreateEntry(kKey);
5832   TryRead(kKey, /* expect_preread_stream1 */ true);
5833 
5834   histogram_tester.ExpectUniqueSample("SimpleCache.App.SyncOpenPrefetchMode",
5835                                       disk_cache::OPEN_PREFETCH_FULL, 1);
5836 }
5837 
TEST_F(DiskCacheSimpleAppCachePrefetchTest,SmallFullSmallSpeculative)5838 TEST_F(DiskCacheSimpleAppCachePrefetchTest, SmallFullSmallSpeculative) {
5839   base::HistogramTester histogram_tester;
5840   SetupFullAndTrailerPrefetch(kEntrySize / 2, kEntrySize / 2);
5841 
5842   const char kKey[] = "a key";
5843   InitCacheAndCreateEntry(kKey);
5844   TryRead(kKey, /* expect_preread_stream1 */ false);
5845 
5846   histogram_tester.ExpectUniqueSample("SimpleCache.App.SyncOpenPrefetchMode",
5847                                       disk_cache::OPEN_PREFETCH_TRAILER, 1);
5848 }
5849 
TEST_F(DiskCacheSimpleAppCachePrefetchTest,LargeFullSmallSpeculative)5850 TEST_F(DiskCacheSimpleAppCachePrefetchTest, LargeFullSmallSpeculative) {
5851   base::HistogramTester histogram_tester;
5852   // Full prefetch takes precedence over a trailer speculative prefetch.
5853   SetupFullAndTrailerPrefetch(kEntrySize * 2, kEntrySize / 2);
5854 
5855   const char kKey[] = "a key";
5856   InitCacheAndCreateEntry(kKey);
5857   TryRead(kKey, /* expect_preread_stream1 */ true);
5858 
5859   histogram_tester.ExpectUniqueSample("SimpleCache.App.SyncOpenPrefetchMode",
5860                                       disk_cache::OPEN_PREFETCH_FULL, 1);
5861 }
5862