Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #include "net/base/upload_disk_cache_entry_element_reader.h" | |
| 6 | |
| 7 #include <algorithm> | |
| 8 #include <string> | |
| 9 | |
| 10 #include "base/bind.h" | |
| 11 #include "base/callback.h" | |
| 12 #include "base/macros.h" | |
| 13 #include "base/memory/scoped_ptr.h" | |
| 14 #include "base/time/time.h" | |
| 15 #include "net/base/io_buffer.h" | |
| 16 #include "net/base/net_errors.h" | |
| 17 #include "net/base/test_completion_callback.h" | |
| 18 #include "net/disk_cache/disk_cache.h" | |
| 19 #include "testing/gtest/include/gtest/gtest.h" | |
| 20 #include "testing/platform_test.h" | |
| 21 | |
| 22 namespace net { | |
| 23 namespace { | |
| 24 | |
| 25 const int kTestDiskCacheStreamIndex = 0; | |
| 26 | |
| 27 const char kDataKey[] = "a key"; | |
| 28 | |
| 29 const char kData[] = "this is data in a disk cache entry"; | |
| 30 const size_t kDataSize = arraysize(kData) - 1; | |
| 31 | |
| 32 // A disk_cache::Entry that arbitrarily delays the completion of a | |
| 33 // read operation to allow testing some races without flake. | |
|
mmenke
2015/06/16 18:51:19
We're using an in-memory cache, which always retur
gavinp
2015/06/16 22:28:02
Done.
| |
| 34 class DelayedReadEntry : public disk_cache::Entry { | |
| 35 public: | |
| 36 explicit DelayedReadEntry(disk_cache::ScopedEntryPtr entry) | |
| 37 : entry_(entry.Pass()) {} | |
| 38 ~DelayedReadEntry() override { EXPECT_FALSE(HasPendingReadCallbacks()); } | |
| 39 | |
| 40 bool HasPendingReadCallbacks() { return !pending_read_callbacks_.empty(); } | |
| 41 | |
| 42 void RunPendingReadCallbacks() { | |
| 43 for (const auto& callback : pending_read_callbacks_) | |
| 44 callback.Run(); | |
|
mmenke
2015/06/16 18:51:19
This seems scary. Can we swap out the pending_rea
gavinp
2015/06/16 22:28:01
Done.
| |
| 45 pending_read_callbacks_.clear(); | |
| 46 } | |
| 47 | |
| 48 // From disk_cache::Entry: | |
| 49 void Doom() override { entry_->Doom(); } | |
| 50 void Close() override { delete this; } // Note this is required by the API. | |
| 51 std::string GetKey() const override { return entry_->GetKey(); } | |
| 52 base::Time GetLastUsed() const override { return entry_->GetLastUsed(); } | |
| 53 base::Time GetLastModified() const override { | |
| 54 return entry_->GetLastModified(); | |
| 55 } | |
| 56 int32 GetDataSize(int index) const override { | |
| 57 return entry_->GetDataSize(index); | |
| 58 } | |
| 59 int ReadData(int index, | |
| 60 int offset, | |
| 61 IOBuffer* buf, | |
| 62 int buf_len, | |
| 63 const CompletionCallback& original_callback) override { | |
| 64 TestCompletionCallback cb; | |
|
mmenke
2015/06/16 18:51:19
Google style guide discourages abbreviations. In
gavinp
2015/06/16 22:28:02
Done. Except in disk_cache code, which is where I
| |
| 65 int rv = entry_->ReadData(index, offset, buf, buf_len, cb.callback()); | |
| 66 rv = cb.GetResult(rv); | |
|
mmenke
2015/06/16 18:51:19
The memory cache always returns synchronously, doe
gavinp
2015/06/16 22:28:02
Done. Left the TestCompletionCallback in to avoid
| |
| 67 pending_read_callbacks_.push_back(base::Bind(original_callback, rv)); | |
| 68 return ERR_IO_PENDING; | |
| 69 } | |
| 70 int WriteData(int index, | |
| 71 int offset, | |
| 72 IOBuffer* buf, | |
| 73 int buf_len, | |
| 74 const CompletionCallback& callback, | |
| 75 bool truncate) override { | |
| 76 return entry_->WriteData(index, offset, buf, buf_len, callback, truncate); | |
| 77 } | |
| 78 int ReadSparseData(int64 offset, | |
| 79 IOBuffer* buf, | |
| 80 int buf_len, | |
| 81 const CompletionCallback& callback) override { | |
| 82 return entry_->ReadSparseData(offset, buf, buf_len, callback); | |
| 83 } | |
| 84 int WriteSparseData(int64 offset, | |
| 85 IOBuffer* buf, | |
| 86 int buf_len, | |
| 87 const CompletionCallback& callback) override { | |
| 88 return entry_->WriteSparseData(offset, buf, buf_len, callback); | |
| 89 } | |
| 90 int GetAvailableRange(int64 offset, | |
| 91 int len, | |
| 92 int64* start, | |
| 93 const CompletionCallback& callback) override { | |
| 94 return entry_->GetAvailableRange(offset, len, start, callback); | |
| 95 } | |
| 96 bool CouldBeSparse() const override { return entry_->CouldBeSparse(); } | |
| 97 void CancelSparseIO() override { entry_->CancelSparseIO(); } | |
| 98 int ReadyForSparseIO(const CompletionCallback& callback) override { | |
| 99 return ReadyForSparseIO(callback); | |
| 100 } | |
| 101 | |
| 102 private: | |
| 103 disk_cache::ScopedEntryPtr entry_; | |
| 104 std::vector<base::Callback<void(void)>> pending_read_callbacks_; | |
|
mmenke
2015/06/16 18:51:19
include <vector>
gavinp
2015/06/16 22:28:02
Done.
| |
| 105 }; | |
| 106 | |
| 107 class UploadDiskCacheEntryElementReaderTest : public PlatformTest { | |
| 108 public: | |
| 109 UploadDiskCacheEntryElementReaderTest() {} | |
| 110 | |
| 111 ~UploadDiskCacheEntryElementReaderTest() override {} | |
| 112 | |
| 113 void SetUp() override { | |
| 114 TestCompletionCallback cb; | |
| 115 int rv = disk_cache::CreateCacheBackend(MEMORY_CACHE, CACHE_BACKEND_DEFAULT, | |
| 116 base::FilePath(), 0, false, NULL, | |
| 117 NULL, &cache_, cb.callback()); | |
| 118 ASSERT_EQ(OK, cb.GetResult(rv)); | |
| 119 | |
| 120 disk_cache::Entry* tmp_entry = nullptr; | |
| 121 rv = cache_->CreateEntry(kDataKey, &tmp_entry, cb.callback()); | |
| 122 ASSERT_EQ(OK, cb.GetResult(rv)); | |
| 123 entry_.reset(tmp_entry); | |
| 124 | |
| 125 scoped_refptr<IOBuffer> iobuffer = new WrappedIOBuffer(kData); | |
| 126 rv = entry_->WriteData(kTestDiskCacheStreamIndex, 0, iobuffer.get(), | |
| 127 kDataSize, cb.callback(), false); | |
| 128 EXPECT_EQ(static_cast<int>(kDataSize), cb.GetResult(rv)); | |
| 129 } | |
| 130 | |
| 131 protected: | |
|
mmenke
2015/06/16 18:51:19
protected not needed in test fixtures
gavinp
2015/06/16 22:28:02
Done.
| |
| 132 void set_entry(disk_cache::ScopedEntryPtr entry) { entry_.swap(entry); } | |
| 133 disk_cache::Entry* entry() { return entry_.get(); } | |
| 134 disk_cache::ScopedEntryPtr release_entry() { return entry_.Pass(); } | |
| 135 | |
| 136 private: | |
| 137 scoped_ptr<disk_cache::Backend> cache_; | |
| 138 disk_cache::ScopedEntryPtr entry_; | |
| 139 }; | |
| 140 | |
| 141 TEST_F(UploadDiskCacheEntryElementReaderTest, ReadAll) { | |
| 142 UploadDiskCacheEntryElementReader reader(entry(), kTestDiskCacheStreamIndex, | |
| 143 0, kDataSize); | |
| 144 EXPECT_EQ(static_cast<uint64>(kDataSize), reader.BytesRemaining()); | |
| 145 | |
| 146 char read_buffer[kDataSize]; | |
| 147 std::fill(read_buffer, read_buffer + arraysize(read_buffer), '\0'); | |
| 148 | |
| 149 scoped_refptr<IOBuffer> iobuffer = new WrappedIOBuffer(read_buffer); | |
|
mmenke
2015/06/16 18:51:19
include ref_counted
mmenke
2015/06/16 18:51:19
nit: io_buffer
gavinp
2015/06/16 22:28:02
Done.
gavinp
2015/06/16 22:28:02
Done.
| |
| 150 TestCompletionCallback cb; | |
| 151 int rv = reader.Read(iobuffer.get(), kDataSize, cb.callback()); | |
| 152 EXPECT_EQ(static_cast<int>(kDataSize), cb.GetResult(rv)); | |
| 153 EXPECT_EQ(0U, reader.BytesRemaining()); | |
|
mmenke
2015/06/16 18:51:19
We're relying on the underlying cache to handle re
gavinp
2015/06/16 22:28:02
Done.
| |
| 154 EXPECT_TRUE(std::equal(kData, kData + kDataSize, read_buffer)); | |
|
mmenke
2015/06/16 18:51:19
Suggest comparing them as strings using EXPECT_EQ,
gavinp
2015/06/16 22:28:01
Done.
| |
| 155 } | |
| 156 | |
| 157 TEST_F(UploadDiskCacheEntryElementReaderTest, ReadPartially) { | |
| 158 UploadDiskCacheEntryElementReader reader(entry(), kTestDiskCacheStreamIndex, | |
| 159 0, kDataSize); | |
| 160 EXPECT_EQ(static_cast<uint64>(kDataSize), reader.BytesRemaining()); | |
|
mmenke
2015/06/16 18:51:19
uint64_t (Not going to mark the rest of these)
gavinp
2015/06/16 22:28:02
Done.
| |
| 161 | |
| 162 char read_buffer[kDataSize]; | |
| 163 std::fill(read_buffer, read_buffer + arraysize(read_buffer), '\0'); | |
| 164 | |
| 165 const size_t iobuffer1_size = kDataSize / 3; | |
|
mmenke
2015/06/16 18:51:19
Think these should kConstantNaming
gavinp
2015/06/16 22:28:02
Done.
| |
| 166 scoped_refptr<IOBuffer> iobuffer1 = new WrappedIOBuffer(read_buffer); | |
| 167 | |
| 168 const size_t iobuffer2_size = kDataSize - iobuffer1_size; | |
|
mmenke
2015/06/16 18:51:19
Out of paranoia, suggest separate buffers, with no
gavinp
2015/06/16 22:28:02
Done. But I don't know what you meant by "no extra
| |
| 169 scoped_refptr<IOBuffer> iobuffer2 = | |
| 170 new WrappedIOBuffer(read_buffer + iobuffer1_size); | |
| 171 | |
| 172 TestCompletionCallback cb; | |
| 173 int rv = reader.Read(iobuffer1.get(), iobuffer1_size, cb.callback()); | |
| 174 EXPECT_EQ(static_cast<int>(iobuffer1_size), cb.GetResult(rv)); | |
| 175 EXPECT_EQ(static_cast<uint64>(iobuffer2_size), reader.BytesRemaining()); | |
|
mmenke
2015/06/16 18:51:19
uint64_t? And include <stdint>
gavinp
2015/06/16 22:28:02
Done. Went with <cstdint> and so std::size_t every
gavinp
2015/06/16 22:47:32
Switched back to <stdint.h>, see the discussion in
| |
| 176 | |
| 177 rv = reader.Read(iobuffer2.get(), iobuffer2_size, cb.callback()); | |
| 178 EXPECT_EQ(static_cast<int>(iobuffer2_size), cb.GetResult(rv)); | |
| 179 EXPECT_EQ(0U, reader.BytesRemaining()); | |
| 180 | |
| 181 EXPECT_TRUE(std::equal(kData, kData + kDataSize, read_buffer)); | |
| 182 } | |
| 183 | |
| 184 TEST_F(UploadDiskCacheEntryElementReaderTest, ReadTooMuch) { | |
| 185 UploadDiskCacheEntryElementReader reader(entry(), kTestDiskCacheStreamIndex, | |
| 186 0, kDataSize); | |
| 187 EXPECT_EQ(static_cast<uint64>(kDataSize), reader.BytesRemaining()); | |
| 188 | |
| 189 const size_t kTooLargeSize = kDataSize + kDataSize / 2; | |
| 190 | |
| 191 char read_buffer[kTooLargeSize]; | |
| 192 std::fill(read_buffer, read_buffer + arraysize(read_buffer), '\0'); | |
| 193 | |
| 194 scoped_refptr<IOBuffer> iobuffer = new WrappedIOBuffer(read_buffer); | |
| 195 TestCompletionCallback cb; | |
| 196 int rv = reader.Read(iobuffer.get(), kTooLargeSize, cb.callback()); | |
| 197 EXPECT_EQ(static_cast<int>(kDataSize), cb.GetResult(rv)); | |
| 198 EXPECT_EQ(0U, reader.BytesRemaining()); | |
| 199 EXPECT_TRUE(std::equal(kData, kData + kDataSize, read_buffer)); | |
| 200 } | |
| 201 | |
| 202 TEST_F(UploadDiskCacheEntryElementReaderTest, MultipleInit) { | |
| 203 UploadDiskCacheEntryElementReader reader(entry(), kTestDiskCacheStreamIndex, | |
| 204 0, kDataSize); | |
| 205 char read_buffer[kDataSize]; | |
| 206 std::fill(read_buffer, read_buffer + arraysize(read_buffer), '\0'); | |
| 207 | |
| 208 scoped_refptr<IOBuffer> iobuffer = new WrappedIOBuffer(read_buffer); | |
| 209 TestCompletionCallback cb; | |
| 210 int rv = reader.Read(iobuffer.get(), kDataSize, cb.callback()); | |
| 211 EXPECT_EQ(static_cast<int>(kDataSize), cb.GetResult(rv)); | |
| 212 EXPECT_TRUE(std::equal(kData, kData + kDataSize, read_buffer)); | |
| 213 | |
| 214 rv = reader.Init(cb.callback()); | |
| 215 EXPECT_EQ(OK, cb.GetResult(rv)); | |
| 216 EXPECT_EQ(static_cast<uint64>(kDataSize), reader.BytesRemaining()); | |
| 217 rv = reader.Read(iobuffer.get(), kDataSize, cb.callback()); | |
| 218 EXPECT_EQ(static_cast<int>(kDataSize), cb.GetResult(rv)); | |
| 219 EXPECT_TRUE(std::equal(kData, kData + kDataSize, read_buffer)); | |
| 220 } | |
|
mmenke
2015/06/16 18:51:19
Should have a generic async test (Per earlier comm
gavinp
2015/06/16 22:28:02
Done.
More problematically, UploadFileElementRead
| |
| 221 | |
| 222 TEST_F(UploadDiskCacheEntryElementReaderTest, InitDuringAsyncOperation) { | |
| 223 DelayedReadEntry* delayed_read_entry = new DelayedReadEntry(release_entry()); | |
| 224 set_entry(disk_cache::ScopedEntryPtr(delayed_read_entry)); | |
| 225 | |
| 226 UploadDiskCacheEntryElementReader reader(entry(), kTestDiskCacheStreamIndex, | |
| 227 0, kDataSize); | |
| 228 char read_buffer[kDataSize]; | |
| 229 std::fill(read_buffer, read_buffer + arraysize(read_buffer), '\0'); | |
| 230 | |
| 231 scoped_refptr<IOBuffer> iobuffer = new WrappedIOBuffer(read_buffer); | |
| 232 int rv = reader.Read(iobuffer.get(), kDataSize, CompletionCallback()); | |
| 233 EXPECT_EQ(ERR_IO_PENDING, rv); | |
| 234 EXPECT_TRUE(delayed_read_entry->HasPendingReadCallbacks()); | |
| 235 EXPECT_EQ(static_cast<uint64>(kDataSize), reader.BytesRemaining()); | |
| 236 | |
| 237 TestCompletionCallback cb; | |
| 238 rv = reader.Init(cb.callback()); | |
| 239 EXPECT_EQ(OK, cb.GetResult(rv)); | |
| 240 | |
| 241 delayed_read_entry->RunPendingReadCallbacks(); | |
| 242 EXPECT_EQ(static_cast<uint64>(kDataSize), reader.BytesRemaining()); | |
|
mmenke
2015/06/16 18:51:19
Should do a second read here (To a different buffe
gavinp
2015/06/16 22:28:02
Done.
| |
| 243 } | |
| 244 | |
| 245 TEST_F(UploadDiskCacheEntryElementReaderTest, Range) { | |
| 246 const size_t kOffset = kDataSize / 4; | |
| 247 const size_t kLength = kDataSize / 3; | |
| 248 | |
| 249 UploadDiskCacheEntryElementReader reader(entry(), kTestDiskCacheStreamIndex, | |
| 250 kOffset, kLength); | |
| 251 EXPECT_EQ(static_cast<uint64>(kLength), reader.BytesRemaining()); | |
| 252 | |
| 253 char read_buffer[kLength]; | |
| 254 std::fill(read_buffer, read_buffer + arraysize(read_buffer), '\0'); | |
| 255 | |
| 256 scoped_refptr<IOBuffer> iobuffer = new WrappedIOBuffer(read_buffer); | |
| 257 TestCompletionCallback cb; | |
| 258 int rv = reader.Read(iobuffer.get(), kLength, cb.callback()); | |
| 259 EXPECT_EQ(static_cast<int>(kLength), cb.GetResult(rv)); | |
| 260 EXPECT_EQ(0U, reader.BytesRemaining()); | |
| 261 EXPECT_TRUE( | |
| 262 std::equal(kData + kOffset, kData + kOffset + kLength, read_buffer)); | |
| 263 } | |
| 264 | |
| 265 } // namespace | |
| 266 } // namespace net | |
| OLD | NEW |