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. |
| 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(); |
| 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; |
| 65 int rv = entry_->ReadData(index, offset, buf, buf_len, cb.callback()); |
| 66 rv = cb.GetResult(rv); |
| 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_; |
| 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: |
| 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); |
| 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()); |
| 154 EXPECT_TRUE(std::equal(kData, kData + kDataSize, read_buffer)); |
| 155 } |
| 156 |
| 157 TEST_F(UploadDiskCacheEntryElementReaderTest, ReadPartially) { |
| 158 UploadDiskCacheEntryElementReader reader(entry(), kTestDiskCacheStreamIndex, |
| 159 0, kDataSize); |
| 160 EXPECT_EQ(static_cast<uint64>(kDataSize), reader.BytesRemaining()); |
| 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; |
| 166 scoped_refptr<IOBuffer> iobuffer1 = new WrappedIOBuffer(read_buffer); |
| 167 |
| 168 const size_t iobuffer2_size = kDataSize - iobuffer1_size; |
| 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()); |
| 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 } |
| 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()); |
| 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 |