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 |