OLD | NEW |
---|---|
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "net/http/http_cache.h" | 5 #include "net/http/mock_http_cache.h" |
6 | 6 |
7 #include "base/bind.h" | 7 #include "base/bind.h" |
8 #include "base/hash_tables.h" | |
9 #include "base/memory/scoped_vector.h" | |
10 #include "base/message_loop.h" | 8 #include "base/message_loop.h" |
11 #include "base/string_util.h" | |
12 #include "base/stringprintf.h" | |
13 #include "net/base/cache_type.h" | |
14 #include "net/base/cert_status_flags.h" | |
15 #include "net/base/host_port_pair.h" | |
16 #include "net/base/load_flags.h" | |
17 #include "net/base/net_errors.h" | 9 #include "net/base/net_errors.h" |
18 #include "net/base/net_log_unittest.h" | |
19 #include "net/base/ssl_cert_request_info.h" | |
20 #include "net/base/ssl_config_service.h" | |
21 #include "net/disk_cache/disk_cache.h" | |
22 #include "net/http/disk_cache_based_ssl_host_info.h" | |
23 #include "net/http/http_byte_range.h" | |
24 #include "net/http/http_request_headers.h" | |
25 #include "net/http/http_request_info.h" | |
26 #include "net/http/http_response_headers.h" | |
27 #include "net/http/http_response_info.h" | |
28 #include "net/http/http_transaction.h" | |
29 #include "net/http/http_transaction_unittest.h" | |
30 #include "net/http/http_util.h" | |
31 #include "testing/gtest/include/gtest/gtest.h" | 10 #include "testing/gtest/include/gtest/gtest.h" |
32 | 11 |
33 using base::Time; | |
34 | |
35 namespace { | 12 namespace { |
36 | 13 |
37 int GetTestModeForEntry(const std::string& key) { | 14 int GetTestModeForEntry(const std::string& key) { |
38 // 'key' is prefixed with an identifier if it corresponds to a cached POST. | 15 // 'key' is prefixed with an identifier if it corresponds to a cached POST. |
39 // Skip past that to locate the actual URL. | 16 // Skip past that to locate the actual URL. |
40 // | 17 // |
41 // TODO(darin): It breaks the abstraction a bit that we assume 'key' is an | 18 // TODO(darin): It breaks the abstraction a bit that we assume 'key' is an |
42 // URL corresponding to a registered MockTransaction. It would be good to | 19 // URL corresponding to a registered MockTransaction. It would be good to |
43 // have another way to access the test_mode. | 20 // have another way to access the test_mode. |
44 GURL url; | 21 GURL url; |
45 if (isdigit(key[0])) { | 22 if (isdigit(key[0])) { |
46 size_t slash = key.find('/'); | 23 size_t slash = key.find('/'); |
47 DCHECK(slash != std::string::npos); | 24 DCHECK(slash != std::string::npos); |
48 url = GURL(key.substr(slash + 1)); | 25 url = GURL(key.substr(slash + 1)); |
49 } else { | 26 } else { |
50 url = GURL(key); | 27 url = GURL(key); |
51 } | 28 } |
52 const MockTransaction* t = FindMockTransaction(url); | 29 const MockTransaction* t = FindMockTransaction(url); |
53 DCHECK(t); | 30 DCHECK(t); |
54 return t->test_mode; | 31 return t->test_mode; |
55 } | 32 } |
56 | 33 |
57 // We can override the test mode for a given operation by setting this global | 34 // We can override the test mode for a given operation by setting this global |
58 // variable. Just remember to reset it after the test!. | 35 // variable. |
59 int g_test_mode = 0; | 36 int g_test_mode = 0; |
60 | 37 |
61 // Returns the test mode after considering the global override. | 38 } // namespace |
62 int GetEffectiveTestMode(int test_mode) { | 39 |
63 if (!g_test_mode) | 40 //----------------------------------------------------------------------------- |
64 return test_mode; | 41 |
65 | 42 struct MockDiskEntry::CallbackInfo { |
66 return g_test_mode; | 43 scoped_refptr<MockDiskEntry> entry; |
67 } | 44 net::OldCompletionCallback* callback; |
68 | 45 int result; |
69 //----------------------------------------------------------------------------- | 46 }; |
70 // mock disk cache (a very basic memory cache implementation) | 47 |
71 | 48 MockDiskEntry::MockDiskEntry() |
72 static const int kNumCacheEntryDataIndices = 3; | 49 : test_mode_(0), doomed_(false), sparse_(false), |
73 | 50 fail_requests_(false), busy_(false), delayed_(false) { |
74 class MockDiskEntry : public disk_cache::Entry, | 51 } |
75 public base::RefCounted<MockDiskEntry> { | 52 |
76 public: | 53 MockDiskEntry::MockDiskEntry(const std::string& key) |
77 MockDiskEntry() | 54 : key_(key), doomed_(false), sparse_(false), |
78 : test_mode_(0), doomed_(false), sparse_(false), | 55 fail_requests_(false), busy_(false), delayed_(false) { |
79 fail_requests_(false), busy_(false), delayed_(false) { | 56 test_mode_ = GetTestModeForEntry(key); |
80 } | 57 } |
81 | 58 |
82 explicit MockDiskEntry(const std::string& key) | 59 void MockDiskEntry::Doom() { |
83 : key_(key), doomed_(false), sparse_(false), | 60 doomed_ = true; |
84 fail_requests_(false), busy_(false), delayed_(false) { | 61 } |
85 test_mode_ = GetTestModeForEntry(key); | 62 |
86 } | 63 void MockDiskEntry::Close() { |
87 | 64 Release(); |
88 bool is_doomed() const { return doomed_; } | 65 } |
89 | 66 |
90 virtual void Doom() { | 67 std::string MockDiskEntry::GetKey() const { |
91 doomed_ = true; | 68 if (fail_requests_) |
92 } | 69 return std::string(); |
93 | 70 return key_; |
94 virtual void Close() { | 71 } |
95 Release(); | 72 |
96 } | 73 base::Time MockDiskEntry::GetLastUsed() const { |
97 | 74 return base::Time::FromInternalValue(0); |
98 virtual std::string GetKey() const { | 75 } |
99 if (fail_requests_) | 76 |
100 return std::string(); | 77 base::Time MockDiskEntry::GetLastModified() const { |
101 return key_; | 78 return base::Time::FromInternalValue(0); |
102 } | 79 } |
103 | 80 |
104 virtual Time GetLastUsed() const { | 81 int32 MockDiskEntry::GetDataSize(int index) const { |
105 return Time::FromInternalValue(0); | 82 DCHECK(index >= 0 && index < kNumCacheEntryDataIndices); |
106 } | 83 return static_cast<int32>(data_[index].size()); |
107 | 84 } |
108 virtual Time GetLastModified() const { | 85 |
109 return Time::FromInternalValue(0); | 86 int MockDiskEntry::ReadData(int index, int offset, net::IOBuffer* buf, |
110 } | 87 int buf_len, net::OldCompletionCallback* callback) { |
111 | 88 DCHECK(index >= 0 && index < kNumCacheEntryDataIndices); |
112 virtual int32 GetDataSize(int index) const { | 89 DCHECK(callback); |
113 DCHECK(index >= 0 && index < kNumCacheEntryDataIndices); | 90 |
114 return static_cast<int32>(data_[index].size()); | 91 if (fail_requests_) |
115 } | 92 return net::ERR_CACHE_READ_FAILURE; |
116 | 93 |
117 virtual int ReadData(int index, int offset, net::IOBuffer* buf, int buf_len, | 94 if (offset < 0 || offset > static_cast<int>(data_[index].size())) |
118 net::OldCompletionCallback* callback) { | 95 return net::ERR_FAILED; |
119 DCHECK(index >= 0 && index < kNumCacheEntryDataIndices); | 96 if (static_cast<size_t>(offset) == data_[index].size()) |
120 DCHECK(callback); | 97 return 0; |
121 | 98 |
122 if (fail_requests_) | 99 int num = std::min(buf_len, static_cast<int>(data_[index].size()) - offset); |
123 return net::ERR_CACHE_READ_FAILURE; | 100 memcpy(buf->data(), &data_[index][offset], num); |
124 | 101 |
125 if (offset < 0 || offset > static_cast<int>(data_[index].size())) | 102 if (MockHttpCache::GetTestMode(test_mode_) & TEST_MODE_SYNC_CACHE_READ) |
126 return net::ERR_FAILED; | 103 return num; |
127 if (static_cast<size_t>(offset) == data_[index].size()) | 104 |
128 return 0; | 105 CallbackLater(callback, num); |
129 | 106 return net::ERR_IO_PENDING; |
130 int num = std::min(buf_len, static_cast<int>(data_[index].size()) - offset); | 107 } |
131 memcpy(buf->data(), &data_[index][offset], num); | 108 |
132 | 109 int MockDiskEntry::WriteData(int index, int offset, net::IOBuffer* buf, |
133 if (GetEffectiveTestMode(test_mode_) & TEST_MODE_SYNC_CACHE_READ) | 110 int buf_len, net::OldCompletionCallback* callback, |
134 return num; | 111 bool truncate) { |
135 | 112 DCHECK(index >= 0 && index < kNumCacheEntryDataIndices); |
136 CallbackLater(callback, num); | 113 DCHECK(callback); |
114 DCHECK(truncate); | |
115 | |
116 if (fail_requests_) { | |
117 CallbackLater(callback, net::ERR_CACHE_READ_FAILURE); | |
137 return net::ERR_IO_PENDING; | 118 return net::ERR_IO_PENDING; |
138 } | 119 } |
139 | 120 |
140 virtual int WriteData(int index, int offset, net::IOBuffer* buf, int buf_len, | 121 if (offset < 0 || offset > static_cast<int>(data_[index].size())) |
141 net::OldCompletionCallback* callback, bool truncate) { | 122 return net::ERR_FAILED; |
142 DCHECK(index >= 0 && index < kNumCacheEntryDataIndices); | 123 |
143 DCHECK(callback); | 124 data_[index].resize(offset + buf_len); |
144 DCHECK(truncate); | 125 if (buf_len) |
145 | 126 memcpy(&data_[index][offset], buf->data(), buf_len); |
146 if (fail_requests_) { | 127 |
147 CallbackLater(callback, net::ERR_CACHE_READ_FAILURE); | 128 if (MockHttpCache::GetTestMode(test_mode_) & TEST_MODE_SYNC_CACHE_WRITE) |
148 return net::ERR_IO_PENDING; | 129 return buf_len; |
130 | |
131 CallbackLater(callback, buf_len); | |
132 return net::ERR_IO_PENDING; | |
133 } | |
134 | |
135 int MockDiskEntry::ReadSparseData(int64 offset, net::IOBuffer* buf, int buf_len, | |
136 net::OldCompletionCallback* callback) { | |
137 DCHECK(callback); | |
138 if (!sparse_ || busy_) | |
139 return net::ERR_CACHE_OPERATION_NOT_SUPPORTED; | |
140 if (offset < 0) | |
141 return net::ERR_FAILED; | |
142 | |
143 if (fail_requests_) | |
144 return net::ERR_CACHE_READ_FAILURE; | |
145 | |
146 DCHECK(offset < kint32max); | |
147 int real_offset = static_cast<int>(offset); | |
148 if (!buf_len) | |
149 return 0; | |
150 | |
151 int num = std::min(static_cast<int>(data_[1].size()) - real_offset, | |
152 buf_len); | |
153 memcpy(buf->data(), &data_[1][real_offset], num); | |
154 | |
155 if (MockHttpCache::GetTestMode(test_mode_) & TEST_MODE_SYNC_CACHE_READ) | |
156 return num; | |
157 | |
158 CallbackLater(callback, num); | |
159 busy_ = true; | |
160 delayed_ = false; | |
161 return net::ERR_IO_PENDING; | |
162 } | |
163 | |
164 int MockDiskEntry::WriteSparseData(int64 offset, net::IOBuffer* buf, | |
165 int buf_len, | |
166 net::OldCompletionCallback* callback) { | |
167 DCHECK(callback); | |
168 if (busy_) | |
169 return net::ERR_CACHE_OPERATION_NOT_SUPPORTED; | |
170 if (!sparse_) { | |
171 if (data_[1].size()) | |
172 return net::ERR_CACHE_OPERATION_NOT_SUPPORTED; | |
173 sparse_ = true; | |
174 } | |
175 if (offset < 0) | |
176 return net::ERR_FAILED; | |
177 if (!buf_len) | |
178 return 0; | |
179 | |
180 if (fail_requests_) | |
181 return net::ERR_CACHE_READ_FAILURE; | |
182 | |
183 DCHECK(offset < kint32max); | |
184 int real_offset = static_cast<int>(offset); | |
185 | |
186 if (static_cast<int>(data_[1].size()) < real_offset + buf_len) | |
187 data_[1].resize(real_offset + buf_len); | |
188 | |
189 memcpy(&data_[1][real_offset], buf->data(), buf_len); | |
190 if (MockHttpCache::GetTestMode(test_mode_) & TEST_MODE_SYNC_CACHE_WRITE) | |
191 return buf_len; | |
192 | |
193 CallbackLater(callback, buf_len); | |
194 return net::ERR_IO_PENDING; | |
195 } | |
196 | |
197 int MockDiskEntry::GetAvailableRange(int64 offset, int len, int64* start, | |
198 net::OldCompletionCallback* callback) { | |
199 DCHECK(callback); | |
200 if (!sparse_ || busy_) | |
201 return net::ERR_CACHE_OPERATION_NOT_SUPPORTED; | |
202 if (offset < 0) | |
203 return net::ERR_FAILED; | |
204 | |
205 if (fail_requests_) | |
206 return net::ERR_CACHE_READ_FAILURE; | |
207 | |
208 *start = offset; | |
209 DCHECK(offset < kint32max); | |
210 int real_offset = static_cast<int>(offset); | |
211 if (static_cast<int>(data_[1].size()) < real_offset) | |
212 return 0; | |
213 | |
214 int num = std::min(static_cast<int>(data_[1].size()) - real_offset, len); | |
215 int count = 0; | |
216 for (; num > 0; num--, real_offset++) { | |
217 if (!count) { | |
218 if (data_[1][real_offset]) { | |
219 count++; | |
220 *start = real_offset; | |
221 } | |
222 } else { | |
223 if (!data_[1][real_offset]) | |
224 break; | |
225 count++; | |
149 } | 226 } |
150 | 227 } |
151 if (offset < 0 || offset > static_cast<int>(data_[index].size())) | 228 if (MockHttpCache::GetTestMode(test_mode_) & TEST_MODE_SYNC_CACHE_WRITE) |
152 return net::ERR_FAILED; | 229 return count; |
153 | 230 |
154 data_[index].resize(offset + buf_len); | 231 CallbackLater(callback, count); |
155 if (buf_len) | 232 return net::ERR_IO_PENDING; |
156 memcpy(&data_[index][offset], buf->data(), buf_len); | 233 } |
157 | 234 |
158 if (GetEffectiveTestMode(test_mode_) & TEST_MODE_SYNC_CACHE_WRITE) | 235 bool MockDiskEntry::CouldBeSparse() const { |
159 return buf_len; | 236 return sparse_; |
160 | 237 } |
161 CallbackLater(callback, buf_len); | 238 |
162 return net::ERR_IO_PENDING; | 239 void MockDiskEntry::CancelSparseIO() { |
163 } | 240 cancel_ = true; |
164 | 241 } |
165 virtual int ReadSparseData(int64 offset, net::IOBuffer* buf, int buf_len, | 242 |
166 net::OldCompletionCallback* callback) { | 243 int MockDiskEntry::ReadyForSparseIO(net::OldCompletionCallback* callback) { |
167 DCHECK(callback); | 244 if (!cancel_) |
168 if (!sparse_ || busy_) | 245 return net::OK; |
169 return net::ERR_CACHE_OPERATION_NOT_SUPPORTED; | 246 |
170 if (offset < 0) | 247 cancel_ = false; |
171 return net::ERR_FAILED; | 248 DCHECK(callback); |
172 | 249 if (MockHttpCache::GetTestMode(test_mode_) & TEST_MODE_SYNC_CACHE_READ) |
173 if (fail_requests_) | 250 return net::OK; |
174 return net::ERR_CACHE_READ_FAILURE; | 251 |
175 | 252 // The pending operation is already in the message loop (and hopefuly |
176 DCHECK(offset < kint32max); | 253 // already in the second pass). Just notify the caller that it finished. |
177 int real_offset = static_cast<int>(offset); | 254 CallbackLater(callback, 0); |
178 if (!buf_len) | 255 return net::ERR_IO_PENDING; |
179 return 0; | 256 } |
180 | 257 |
181 int num = std::min(static_cast<int>(data_[1].size()) - real_offset, | 258 // If |value| is true, don't deliver any completion callbacks until called |
182 buf_len); | 259 // again with |value| set to false. Caution: remember to enable callbacks |
183 memcpy(buf->data(), &data_[1][real_offset], num); | 260 // again or all subsequent tests will fail. |
184 | 261 // Static. |
185 if (GetEffectiveTestMode(test_mode_) & TEST_MODE_SYNC_CACHE_READ) | 262 void MockDiskEntry::IgnoreCallbacks(bool value) { |
186 return num; | 263 if (ignore_callbacks_ == value) |
187 | 264 return; |
188 CallbackLater(callback, num); | 265 ignore_callbacks_ = value; |
189 busy_ = true; | 266 if (!value) |
190 delayed_ = false; | 267 StoreAndDeliverCallbacks(false, NULL, NULL, 0); |
191 return net::ERR_IO_PENDING; | 268 } |
192 } | 269 |
193 | 270 MockDiskEntry::~MockDiskEntry() { |
194 virtual int WriteSparseData(int64 offset, net::IOBuffer* buf, int buf_len, | 271 } |
195 net::OldCompletionCallback* callback) { | 272 |
196 DCHECK(callback); | 273 // Unlike the callbacks for MockHttpTransaction, we want this one to run even |
197 if (busy_) | 274 // if the consumer called Close on the MockDiskEntry. We achieve that by |
198 return net::ERR_CACHE_OPERATION_NOT_SUPPORTED; | 275 // leveraging the fact that this class is reference counted. |
199 if (!sparse_) { | 276 void MockDiskEntry::CallbackLater(net::OldCompletionCallback* callback, |
200 if (data_[1].size()) | 277 int result) { |
201 return net::ERR_CACHE_OPERATION_NOT_SUPPORTED; | 278 if (ignore_callbacks_) |
202 sparse_ = true; | 279 return StoreAndDeliverCallbacks(true, this, callback, result); |
280 MessageLoop::current()->PostTask(FROM_HERE, base::Bind( | |
281 &MockDiskEntry::RunCallback, this, callback, result)); | |
282 } | |
283 | |
284 void MockDiskEntry::RunCallback(net::OldCompletionCallback* callback, int result ) { | |
gavinp
2011/11/18 14:26:22
80 chars.
rvargas (doing something else)
2011/11/18 19:24:58
This will go away when OldCompletionCallback is re
gavinp
2011/11/22 18:33:48
SGTM! Just CC me or add me as a reviewer when tha
rvargas (doing something else)
2011/11/22 18:58:10
I'm not the one working on that change. Will is do
| |
285 if (busy_) { | |
286 // This is kind of hacky, but controlling the behavior of just this entry | |
287 // from a test is sort of complicated. What we really want to do is | |
288 // delay the delivery of a sparse IO operation a little more so that the | |
289 // request start operation (async) will finish without seeing the end of | |
290 // this operation (already posted to the message loop)... and without | |
291 // just delaying for n mS (which may cause trouble with slow bots). So | |
292 // we re-post this operation (all async sparse IO operations will take two | |
293 // trips trhough the message loop instead of one). | |
294 if (!delayed_) { | |
295 delayed_ = true; | |
296 return CallbackLater(callback, result); | |
203 } | 297 } |
204 if (offset < 0) | 298 } |
205 return net::ERR_FAILED; | 299 busy_ = false; |
206 if (!buf_len) | 300 callback->Run(result); |
207 return 0; | 301 } |
208 | 302 |
209 if (fail_requests_) | 303 // When |store| is true, stores the callback to be delivered later; otherwise |
210 return net::ERR_CACHE_READ_FAILURE; | 304 // delivers any callback previously stored. |
211 | 305 // Static. |
212 DCHECK(offset < kint32max); | 306 void MockDiskEntry::StoreAndDeliverCallbacks(bool store, MockDiskEntry* entry, |
213 int real_offset = static_cast<int>(offset); | 307 net::OldCompletionCallback* callbac k, |
gavinp
2011/11/18 14:26:22
80 chars.
| |
214 | 308 int result) { |
215 if (static_cast<int>(data_[1].size()) < real_offset + buf_len) | 309 static std::vector<CallbackInfo> callback_list; |
216 data_[1].resize(real_offset + buf_len); | 310 if (store) { |
217 | 311 CallbackInfo c = {entry, callback, result}; |
218 memcpy(&data_[1][real_offset], buf->data(), buf_len); | 312 callback_list.push_back(c); |
219 if (GetEffectiveTestMode(test_mode_) & TEST_MODE_SYNC_CACHE_WRITE) | 313 } else { |
220 return buf_len; | 314 for (size_t i = 0; i < callback_list.size(); i++) { |
221 | 315 CallbackInfo& c = callback_list[i]; |
222 CallbackLater(callback, buf_len); | 316 c.entry->CallbackLater(c.callback, c.result); |
223 return net::ERR_IO_PENDING; | |
224 } | |
225 | |
226 virtual int GetAvailableRange(int64 offset, int len, int64* start, | |
227 net::OldCompletionCallback* callback) { | |
228 DCHECK(callback); | |
229 if (!sparse_ || busy_) | |
230 return net::ERR_CACHE_OPERATION_NOT_SUPPORTED; | |
231 if (offset < 0) | |
232 return net::ERR_FAILED; | |
233 | |
234 if (fail_requests_) | |
235 return net::ERR_CACHE_READ_FAILURE; | |
236 | |
237 *start = offset; | |
238 DCHECK(offset < kint32max); | |
239 int real_offset = static_cast<int>(offset); | |
240 if (static_cast<int>(data_[1].size()) < real_offset) | |
241 return 0; | |
242 | |
243 int num = std::min(static_cast<int>(data_[1].size()) - real_offset, len); | |
244 int count = 0; | |
245 for (; num > 0; num--, real_offset++) { | |
246 if (!count) { | |
247 if (data_[1][real_offset]) { | |
248 count++; | |
249 *start = real_offset; | |
250 } | |
251 } else { | |
252 if (!data_[1][real_offset]) | |
253 break; | |
254 count++; | |
255 } | |
256 } | 317 } |
257 if (GetEffectiveTestMode(test_mode_) & TEST_MODE_SYNC_CACHE_WRITE) | 318 callback_list.clear(); |
258 return count; | 319 } |
259 | 320 } |
260 CallbackLater(callback, count); | |
261 return net::ERR_IO_PENDING; | |
262 } | |
263 | |
264 virtual bool CouldBeSparse() const { | |
265 return sparse_; | |
266 } | |
267 | |
268 virtual void CancelSparseIO() { cancel_ = true; } | |
269 | |
270 virtual int ReadyForSparseIO(net::OldCompletionCallback* completion_callback) { | |
271 if (!cancel_) | |
272 return net::OK; | |
273 | |
274 cancel_ = false; | |
275 DCHECK(completion_callback); | |
276 if (GetEffectiveTestMode(test_mode_) & TEST_MODE_SYNC_CACHE_READ) | |
277 return net::OK; | |
278 | |
279 // The pending operation is already in the message loop (and hopefuly | |
280 // already in the second pass). Just notify the caller that it finished. | |
281 CallbackLater(completion_callback, 0); | |
282 return net::ERR_IO_PENDING; | |
283 } | |
284 | |
285 // Fail most subsequent requests. | |
286 void set_fail_requests() { fail_requests_ = true; } | |
287 | |
288 // If |value| is true, don't deliver any completion callbacks until called | |
289 // again with |value| set to false. Caution: remember to enable callbacks | |
290 // again or all subsequent tests will fail. | |
291 static void IgnoreCallbacks(bool value) { | |
292 if (ignore_callbacks_ == value) | |
293 return; | |
294 ignore_callbacks_ = value; | |
295 if (!value) | |
296 StoreAndDeliverCallbacks(false, NULL, NULL, 0); | |
297 } | |
298 | |
299 private: | |
300 friend class base::RefCounted<MockDiskEntry>; | |
301 | |
302 struct CallbackInfo { | |
303 scoped_refptr<MockDiskEntry> entry; | |
304 net::OldCompletionCallback* callback; | |
305 int result; | |
306 }; | |
307 | |
308 ~MockDiskEntry() {} | |
309 | |
310 // Unlike the callbacks for MockHttpTransaction, we want this one to run even | |
311 // if the consumer called Close on the MockDiskEntry. We achieve that by | |
312 // leveraging the fact that this class is reference counted. | |
313 void CallbackLater(net::OldCompletionCallback* callback, int result) { | |
314 if (ignore_callbacks_) | |
315 return StoreAndDeliverCallbacks(true, this, callback, result); | |
316 MessageLoop::current()->PostTask(FROM_HERE, base::Bind( | |
317 &MockDiskEntry::RunCallback, this, callback, result)); | |
318 } | |
319 void RunCallback(net::OldCompletionCallback* callback, int result) { | |
320 if (busy_) { | |
321 // This is kind of hacky, but controlling the behavior of just this entry | |
322 // from a test is sort of complicated. What we really want to do is | |
323 // delay the delivery of a sparse IO operation a little more so that the | |
324 // request start operation (async) will finish without seeing the end of | |
325 // this operation (already posted to the message loop)... and without | |
326 // just delaying for n mS (which may cause trouble with slow bots). So | |
327 // we re-post this operation (all async sparse IO operations will take two | |
328 // trips trhough the message loop instead of one). | |
329 if (!delayed_) { | |
330 delayed_ = true; | |
331 return CallbackLater(callback, result); | |
332 } | |
333 } | |
334 busy_ = false; | |
335 callback->Run(result); | |
336 } | |
337 | |
338 // When |store| is true, stores the callback to be delivered later; otherwise | |
339 // delivers any callback previously stored. | |
340 static void StoreAndDeliverCallbacks(bool store, MockDiskEntry* entry, | |
341 net::OldCompletionCallback* callback, | |
342 int result) { | |
343 static std::vector<CallbackInfo> callback_list; | |
344 if (store) { | |
345 CallbackInfo c = {entry, callback, result}; | |
346 callback_list.push_back(c); | |
347 } else { | |
348 for (size_t i = 0; i < callback_list.size(); i++) { | |
349 CallbackInfo& c = callback_list[i]; | |
350 c.entry->CallbackLater(c.callback, c.result); | |
351 } | |
352 callback_list.clear(); | |
353 } | |
354 } | |
355 | |
356 std::string key_; | |
357 std::vector<char> data_[kNumCacheEntryDataIndices]; | |
358 int test_mode_; | |
359 bool doomed_; | |
360 bool sparse_; | |
361 bool fail_requests_; | |
362 bool busy_; | |
363 bool delayed_; | |
364 static bool cancel_; | |
365 static bool ignore_callbacks_; | |
366 }; | |
367 | 321 |
368 // Statics. | 322 // Statics. |
369 bool MockDiskEntry::cancel_ = false; | 323 bool MockDiskEntry::cancel_ = false; |
370 bool MockDiskEntry::ignore_callbacks_ = false; | 324 bool MockDiskEntry::ignore_callbacks_ = false; |
371 | 325 |
372 class MockDiskCache : public disk_cache::Backend { | 326 //----------------------------------------------------------------------------- |
327 | |
328 class MockDiskCache::CallbackRunner : public Task { | |
373 public: | 329 public: |
374 MockDiskCache() | 330 CallbackRunner(net::OldCompletionCallback* callback, int result) |
375 : open_count_(0), create_count_(0), fail_requests_(false), | 331 : callback_(callback), result_(result) {} |
376 soft_failures_(false) { | 332 virtual void Run() { |
377 } | 333 callback_->Run(result_); |
378 | 334 } |
379 ~MockDiskCache() { | 335 |
380 ReleaseAll(); | 336 private: |
381 } | 337 net::OldCompletionCallback* callback_; |
382 | 338 int result_; |
383 virtual int32 GetEntryCount() const { | 339 DISALLOW_COPY_AND_ASSIGN(CallbackRunner); |
384 return static_cast<int32>(entries_.size()); | 340 }; |
385 } | 341 |
386 | 342 MockDiskCache::MockDiskCache() |
387 virtual int OpenEntry(const std::string& key, disk_cache::Entry** entry, | 343 : open_count_(0), create_count_(0), fail_requests_(false), |
388 net::OldCompletionCallback* callback) { | 344 soft_failures_(false) { |
389 DCHECK(callback); | 345 } |
390 if (fail_requests_) | 346 |
391 return net::ERR_CACHE_OPEN_FAILURE; | 347 MockDiskCache::~MockDiskCache() { |
392 | 348 ReleaseAll(); |
393 EntryMap::iterator it = entries_.find(key); | 349 } |
394 if (it == entries_.end()) | 350 |
395 return net::ERR_CACHE_OPEN_FAILURE; | 351 int32 MockDiskCache::GetEntryCount() const { |
396 | 352 return static_cast<int32>(entries_.size()); |
397 if (it->second->is_doomed()) { | 353 } |
398 it->second->Release(); | 354 |
399 entries_.erase(it); | 355 int MockDiskCache::OpenEntry(const std::string& key, disk_cache::Entry** entry, |
400 return net::ERR_CACHE_OPEN_FAILURE; | 356 net::OldCompletionCallback* callback) { |
401 } | 357 DCHECK(callback); |
402 | 358 if (fail_requests_) |
403 open_count_++; | 359 return net::ERR_CACHE_OPEN_FAILURE; |
404 | 360 |
405 it->second->AddRef(); | 361 EntryMap::iterator it = entries_.find(key); |
406 *entry = it->second; | 362 if (it == entries_.end()) |
407 | 363 return net::ERR_CACHE_OPEN_FAILURE; |
408 if (soft_failures_) | 364 |
409 it->second->set_fail_requests(); | 365 if (it->second->is_doomed()) { |
410 | 366 it->second->Release(); |
411 if (GetTestModeForEntry(key) & TEST_MODE_SYNC_CACHE_START) | 367 entries_.erase(it); |
412 return net::OK; | 368 return net::ERR_CACHE_OPEN_FAILURE; |
413 | 369 } |
414 CallbackLater(callback, net::OK); | 370 |
415 return net::ERR_IO_PENDING; | 371 open_count_++; |
416 } | 372 |
417 | 373 it->second->AddRef(); |
418 virtual int CreateEntry(const std::string& key, disk_cache::Entry** entry, | 374 *entry = it->second; |
419 net::OldCompletionCallback* callback) { | 375 |
420 DCHECK(callback); | 376 if (soft_failures_) |
421 if (fail_requests_) | 377 it->second->set_fail_requests(); |
422 return net::ERR_CACHE_CREATE_FAILURE; | 378 |
423 | 379 if (GetTestModeForEntry(key) & TEST_MODE_SYNC_CACHE_START) |
424 EntryMap::iterator it = entries_.find(key); | 380 return net::OK; |
425 if (it != entries_.end()) { | 381 |
426 DCHECK(it->second->is_doomed()); | 382 CallbackLater(callback, net::OK); |
427 it->second->Release(); | 383 return net::ERR_IO_PENDING; |
428 entries_.erase(it); | 384 } |
429 } | 385 |
430 | 386 int MockDiskCache::CreateEntry(const std::string& key, |
431 create_count_++; | 387 disk_cache::Entry** entry, |
432 | 388 net::OldCompletionCallback* callback) { |
433 MockDiskEntry* new_entry = new MockDiskEntry(key); | 389 DCHECK(callback); |
434 | 390 if (fail_requests_) |
435 new_entry->AddRef(); | 391 return net::ERR_CACHE_CREATE_FAILURE; |
436 entries_[key] = new_entry; | 392 |
437 | 393 EntryMap::iterator it = entries_.find(key); |
438 new_entry->AddRef(); | 394 if (it != entries_.end()) { |
439 *entry = new_entry; | 395 DCHECK(it->second->is_doomed()); |
440 | 396 it->second->Release(); |
441 if (soft_failures_) | 397 entries_.erase(it); |
442 new_entry->set_fail_requests(); | 398 } |
443 | 399 |
444 if (GetTestModeForEntry(key) & TEST_MODE_SYNC_CACHE_START) | 400 create_count_++; |
445 return net::OK; | 401 |
446 | 402 MockDiskEntry* new_entry = new MockDiskEntry(key); |
447 CallbackLater(callback, net::OK); | 403 |
448 return net::ERR_IO_PENDING; | 404 new_entry->AddRef(); |
449 } | 405 entries_[key] = new_entry; |
450 | 406 |
451 virtual int DoomEntry(const std::string& key, | 407 new_entry->AddRef(); |
452 net::OldCompletionCallback* callback) { | 408 *entry = new_entry; |
453 DCHECK(callback); | 409 |
454 EntryMap::iterator it = entries_.find(key); | 410 if (soft_failures_) |
455 if (it != entries_.end()) { | 411 new_entry->set_fail_requests(); |
456 it->second->Release(); | 412 |
457 entries_.erase(it); | 413 if (GetTestModeForEntry(key) & TEST_MODE_SYNC_CACHE_START) |
458 } | 414 return net::OK; |
459 | 415 |
460 if (GetTestModeForEntry(key) & TEST_MODE_SYNC_CACHE_START) | 416 CallbackLater(callback, net::OK); |
461 return net::OK; | 417 return net::ERR_IO_PENDING; |
462 | 418 } |
463 CallbackLater(callback, net::OK); | 419 |
464 return net::ERR_IO_PENDING; | 420 int MockDiskCache::DoomEntry(const std::string& key, |
465 } | 421 net::OldCompletionCallback* callback) { |
466 | 422 DCHECK(callback); |
467 virtual int DoomAllEntries(net::OldCompletionCallback* callback) { | 423 EntryMap::iterator it = entries_.find(key); |
468 return net::ERR_NOT_IMPLEMENTED; | 424 if (it != entries_.end()) { |
469 } | 425 it->second->Release(); |
470 | 426 entries_.erase(it); |
471 virtual int DoomEntriesBetween(const base::Time initial_time, | 427 } |
472 const base::Time end_time, | 428 |
429 if (GetTestModeForEntry(key) & TEST_MODE_SYNC_CACHE_START) | |
430 return net::OK; | |
431 | |
432 CallbackLater(callback, net::OK); | |
433 return net::ERR_IO_PENDING; | |
434 } | |
435 | |
436 int MockDiskCache::DoomAllEntries(net::OldCompletionCallback* callback) { | |
437 return net::ERR_NOT_IMPLEMENTED; | |
438 } | |
439 | |
440 int MockDiskCache::DoomEntriesBetween(const base::Time initial_time, | |
441 const base::Time end_time, | |
442 net::OldCompletionCallback* callback) { | |
443 return net::ERR_NOT_IMPLEMENTED; | |
444 } | |
445 | |
446 int MockDiskCache::DoomEntriesSince(const base::Time initial_time, | |
447 net::OldCompletionCallback* callback) { | |
448 return net::ERR_NOT_IMPLEMENTED; | |
449 } | |
450 | |
451 int MockDiskCache::OpenNextEntry(void** iter, disk_cache::Entry** next_entry, | |
473 net::OldCompletionCallback* callback) { | 452 net::OldCompletionCallback* callback) { |
474 return net::ERR_NOT_IMPLEMENTED; | 453 return net::ERR_NOT_IMPLEMENTED; |
475 } | 454 } |
476 | 455 |
477 virtual int DoomEntriesSince(const base::Time initial_time, | 456 void MockDiskCache::EndEnumeration(void** iter) { |
478 net::OldCompletionCallback* callback) { | 457 } |
479 return net::ERR_NOT_IMPLEMENTED; | 458 |
480 } | 459 void MockDiskCache::GetStats( |
481 | 460 std::vector<std::pair<std::string, std::string> >* stats) { |
482 virtual int OpenNextEntry(void** iter, disk_cache::Entry** next_entry, | 461 } |
483 net::OldCompletionCallback* callback) { | 462 |
484 return net::ERR_NOT_IMPLEMENTED; | 463 void MockDiskCache::OnExternalCacheHit(const std::string& key) { |
485 } | 464 } |
486 | 465 |
487 virtual void EndEnumeration(void** iter) {} | 466 void MockDiskCache::ReleaseAll() { |
488 | 467 EntryMap::iterator it = entries_.begin(); |
489 virtual void GetStats( | 468 for (; it != entries_.end(); ++it) |
490 std::vector<std::pair<std::string, std::string> >* stats) { | 469 it->second->Release(); |
491 } | 470 entries_.clear(); |
492 | 471 } |
493 virtual void OnExternalCacheHit(const std::string& key) {} | 472 |
494 | 473 void MockDiskCache::CallbackLater(net::OldCompletionCallback* callback, |
495 // returns number of times a cache entry was successfully opened | 474 int result) { |
496 int open_count() const { return open_count_; } | 475 MessageLoop::current()->PostTask(FROM_HERE, |
497 | 476 new CallbackRunner(callback, result)); |
498 // returns number of times a cache entry was successfully created | 477 } |
499 int create_count() const { return create_count_; } | 478 |
500 | 479 //----------------------------------------------------------------------------- |
501 // Fail any subsequent CreateEntry and OpenEntry. | 480 |
502 void set_fail_requests() { fail_requests_ = true; } | 481 int MockBackendFactory::CreateBackend(net::NetLog* net_log, |
503 | 482 disk_cache::Backend** backend, |
504 // Return entries that fail some of their requests. | 483 net::OldCompletionCallback* callback) { |
505 void set_soft_failures(bool value) { soft_failures_ = value; } | 484 *backend = new MockDiskCache(); |
506 | 485 return net::OK; |
507 void ReleaseAll() { | 486 } |
508 EntryMap::iterator it = entries_.begin(); | 487 |
509 for (; it != entries_.end(); ++it) | 488 //----------------------------------------------------------------------------- |
510 it->second->Release(); | 489 |
511 entries_.clear(); | 490 MockHttpCache::MockHttpCache() |
512 } | 491 : http_cache_(new MockNetworkLayer(), NULL, new MockBackendFactory()) { |
513 | 492 } |
514 private: | 493 |
515 typedef base::hash_map<std::string, MockDiskEntry*> EntryMap; | 494 MockHttpCache::MockHttpCache(net::HttpCache::BackendFactory* disk_cache_factory) |
516 | 495 : http_cache_(new MockNetworkLayer(), NULL, disk_cache_factory) { |
517 class CallbackRunner : public Task { | 496 } |
518 public: | 497 |
519 CallbackRunner(net::OldCompletionCallback* callback, int result) | 498 MockDiskCache* MockHttpCache::disk_cache() { |
520 : callback_(callback), result_(result) {} | 499 TestOldCompletionCallback cb; |
521 virtual void Run() { | 500 disk_cache::Backend* backend; |
522 callback_->Run(result_); | 501 int rv = http_cache_.GetBackend(&backend, &cb); |
523 } | 502 rv = cb.GetResult(rv); |
524 | 503 return (rv == net::OK) ? static_cast<MockDiskCache*>(backend) : NULL; |
525 private: | 504 } |
526 net::OldCompletionCallback* callback_; | 505 |
527 int result_; | 506 bool MockHttpCache::ReadResponseInfo(disk_cache::Entry* disk_entry, |
528 DISALLOW_COPY_AND_ASSIGN(CallbackRunner); | 507 net::HttpResponseInfo* response_info, |
529 }; | 508 bool* response_truncated) { |
530 | 509 int size = disk_entry->GetDataSize(0); |
531 void CallbackLater(net::OldCompletionCallback* callback, int result) { | 510 |
532 MessageLoop::current()->PostTask(FROM_HERE, | 511 TestOldCompletionCallback cb; |
533 new CallbackRunner(callback, result)); | 512 scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(size)); |
534 } | 513 int rv = disk_entry->ReadData(0, 0, buffer, size, &cb); |
535 | 514 rv = cb.GetResult(rv); |
536 EntryMap entries_; | 515 EXPECT_EQ(size, rv); |
537 int open_count_; | 516 |
538 int create_count_; | 517 return net::HttpCache::ParseResponseInfo(buffer->data(), size, |
539 bool fail_requests_; | 518 response_info, |
540 bool soft_failures_; | 519 response_truncated); |
541 }; | 520 } |
542 | 521 |
543 class MockBackendFactory : public net::HttpCache::BackendFactory { | 522 bool MockHttpCache::WriteResponseInfo( |
544 public: | 523 disk_cache::Entry* disk_entry, const net::HttpResponseInfo* response_info, |
545 virtual int CreateBackend(net::NetLog* /* net_log */, | 524 bool skip_transient_headers, bool response_truncated) { |
546 disk_cache::Backend** backend, | 525 Pickle pickle; |
547 net::OldCompletionCallback* callback) { | 526 response_info->Persist( |
548 *backend = new MockDiskCache(); | 527 &pickle, skip_transient_headers, response_truncated); |
549 return net::OK; | 528 |
550 } | 529 TestOldCompletionCallback cb; |
551 }; | 530 scoped_refptr<net::WrappedIOBuffer> data(new net::WrappedIOBuffer( |
552 | 531 reinterpret_cast<const char*>(pickle.data()))); |
553 class MockHttpCache { | 532 int len = static_cast<int>(pickle.size()); |
554 public: | 533 |
555 MockHttpCache() | 534 int rv = disk_entry->WriteData(0, 0, data, len, &cb, true); |
556 : http_cache_(new MockNetworkLayer(), NULL, new MockBackendFactory()) { | 535 rv = cb.GetResult(rv); |
557 } | 536 return (rv == len); |
558 | 537 } |
559 explicit MockHttpCache(net::HttpCache::BackendFactory* disk_cache_factory) | 538 |
560 : http_cache_(new MockNetworkLayer(), NULL, disk_cache_factory) { | 539 bool MockHttpCache::OpenBackendEntry(const std::string& key, |
561 } | 540 disk_cache::Entry** entry) { |
562 | 541 TestOldCompletionCallback cb; |
563 net::HttpCache* http_cache() { return &http_cache_; } | 542 int rv = disk_cache()->OpenEntry(key, entry, &cb); |
564 | 543 return (cb.GetResult(rv) == net::OK); |
565 MockNetworkLayer* network_layer() { | 544 } |
566 return static_cast<MockNetworkLayer*>(http_cache_.network_layer()); | 545 |
567 } | 546 bool MockHttpCache::CreateBackendEntry(const std::string& key, |
568 MockDiskCache* disk_cache() { | 547 disk_cache::Entry** entry, |
569 TestOldCompletionCallback cb; | 548 net::NetLog* net_log) { |
570 disk_cache::Backend* backend; | 549 TestOldCompletionCallback cb; |
571 int rv = http_cache_.GetBackend(&backend, &cb); | 550 int rv = disk_cache()->CreateEntry(key, entry, &cb); |
572 rv = cb.GetResult(rv); | 551 return (cb.GetResult(rv) == net::OK); |
573 return (rv == net::OK) ? static_cast<MockDiskCache*>(backend) : NULL; | 552 } |
574 } | |
575 | |
576 // Helper function for reading response info from the disk cache. | |
577 static bool ReadResponseInfo(disk_cache::Entry* disk_entry, | |
578 net::HttpResponseInfo* response_info, | |
579 bool* response_truncated) { | |
580 int size = disk_entry->GetDataSize(0); | |
581 | |
582 TestOldCompletionCallback cb; | |
583 scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(size)); | |
584 int rv = disk_entry->ReadData(0, 0, buffer, size, &cb); | |
585 rv = cb.GetResult(rv); | |
586 EXPECT_EQ(size, rv); | |
587 | |
588 return net::HttpCache::ParseResponseInfo(buffer->data(), size, | |
589 response_info, | |
590 response_truncated); | |
591 } | |
592 | |
593 // Helper function for writing response info into the disk cache. | |
594 static bool WriteResponseInfo(disk_cache::Entry* disk_entry, | |
595 const net::HttpResponseInfo* response_info, | |
596 bool skip_transient_headers, | |
597 bool response_truncated) { | |
598 Pickle pickle; | |
599 response_info->Persist( | |
600 &pickle, skip_transient_headers, response_truncated); | |
601 | |
602 TestOldCompletionCallback cb; | |
603 scoped_refptr<net::WrappedIOBuffer> data(new net::WrappedIOBuffer( | |
604 reinterpret_cast<const char*>(pickle.data()))); | |
605 int len = static_cast<int>(pickle.size()); | |
606 | |
607 int rv = disk_entry->WriteData(0, 0, data, len, &cb, true); | |
608 rv = cb.GetResult(rv); | |
609 return (rv == len); | |
610 } | |
611 | |
612 // Helper function to synchronously open a backend entry. | |
613 bool OpenBackendEntry(const std::string& key, disk_cache::Entry** entry) { | |
614 TestOldCompletionCallback cb; | |
615 int rv = disk_cache()->OpenEntry(key, entry, &cb); | |
616 return (cb.GetResult(rv) == net::OK); | |
617 } | |
618 | |
619 // Helper function to synchronously create a backend entry. | |
620 bool CreateBackendEntry(const std::string& key, disk_cache::Entry** entry, | |
621 net::NetLog* /* net_log */) { | |
622 TestOldCompletionCallback cb; | |
623 int rv = disk_cache()->CreateEntry(key, entry, &cb); | |
624 return (cb.GetResult(rv) == net::OK); | |
625 } | |
626 | |
627 private: | |
628 net::HttpCache http_cache_; | |
629 }; | |
630 | |
631 // This version of the disk cache doesn't invoke CreateEntry callbacks. | |
632 class MockDiskCacheNoCB : public MockDiskCache { | |
633 virtual int CreateEntry(const std::string& key, disk_cache::Entry** entry, | |
634 net::OldCompletionCallback* callback) { | |
635 return net::ERR_IO_PENDING; | |
636 } | |
637 }; | |
638 | |
639 class MockBackendNoCbFactory : public net::HttpCache::BackendFactory { | |
640 public: | |
641 virtual int CreateBackend(net::NetLog* /* net_log */, | |
642 disk_cache::Backend** backend, | |
643 net::OldCompletionCallback* callback) { | |
644 *backend = new MockDiskCacheNoCB(); | |
645 return net::OK; | |
646 } | |
647 }; | |
648 | |
649 // This backend factory allows us to control the backend instantiation. | |
650 class MockBlockingBackendFactory : public net::HttpCache::BackendFactory { | |
651 public: | |
652 MockBlockingBackendFactory() | |
653 : backend_(NULL), callback_(NULL), block_(true), fail_(false) {} | |
654 | |
655 virtual int CreateBackend(net::NetLog* /* net_log */, | |
656 disk_cache::Backend** backend, | |
657 net::OldCompletionCallback* callback) { | |
658 if (!block_) { | |
659 if (!fail_) | |
660 *backend = new MockDiskCache(); | |
661 return Result(); | |
662 } | |
663 | |
664 backend_ = backend; | |
665 callback_ = callback; | |
666 return net::ERR_IO_PENDING; | |
667 } | |
668 | |
669 // Completes the backend creation. Any blocked call will be notified via the | |
670 // provided callback. | |
671 void FinishCreation() { | |
672 block_ = false; | |
673 if (callback_) { | |
674 if (!fail_) | |
675 *backend_ = new MockDiskCache(); | |
676 net::OldCompletionCallback* cb = callback_; | |
677 callback_ = NULL; | |
678 cb->Run(Result()); // This object can be deleted here. | |
679 } | |
680 } | |
681 | |
682 disk_cache::Backend** backend() { return backend_; } | |
683 void set_fail(bool fail) { fail_ = fail; } | |
684 | |
685 net::OldCompletionCallback* callback() { return callback_; } | |
686 | |
687 private: | |
688 int Result() { return fail_ ? net::ERR_FAILED : net::OK; } | |
689 | |
690 disk_cache::Backend** backend_; | |
691 net::OldCompletionCallback* callback_; | |
692 bool block_; | |
693 bool fail_; | |
694 }; | |
695 | |
696 class DeleteCacheOldCompletionCallback : public TestOldCompletionCallback { | |
697 public: | |
698 explicit DeleteCacheOldCompletionCallback(MockHttpCache* cache) | |
699 : cache_(cache) {} | |
700 | |
701 virtual void RunWithParams(const Tuple1<int>& params) { | |
702 delete cache_; | |
703 TestOldCompletionCallback::RunWithParams(params); | |
704 } | |
705 | |
706 private: | |
707 MockHttpCache* cache_; | |
708 }; | |
709 | |
710 //----------------------------------------------------------------------------- | |
711 // helpers | |
712 | |
713 void ReadAndVerifyTransaction(net::HttpTransaction* trans, | |
714 const MockTransaction& trans_info) { | |
715 std::string content; | |
716 int rv = ReadTransaction(trans, &content); | |
717 | |
718 EXPECT_EQ(net::OK, rv); | |
719 std::string expected(trans_info.data); | |
720 EXPECT_EQ(expected, content); | |
721 } | |
722 | |
723 void RunTransactionTestWithRequestAndLog(net::HttpCache* cache, | |
724 const MockTransaction& trans_info, | |
725 const MockHttpRequest& request, | |
726 net::HttpResponseInfo* response_info, | |
727 const net::BoundNetLog& net_log) { | |
728 TestOldCompletionCallback callback; | |
729 | |
730 // write to the cache | |
731 | |
732 scoped_ptr<net::HttpTransaction> trans; | |
733 int rv = cache->CreateTransaction(&trans); | |
734 EXPECT_EQ(net::OK, rv); | |
735 ASSERT_TRUE(trans.get()); | |
736 | |
737 rv = trans->Start(&request, &callback, net_log); | |
738 if (rv == net::ERR_IO_PENDING) | |
739 rv = callback.WaitForResult(); | |
740 ASSERT_EQ(net::OK, rv); | |
741 | |
742 const net::HttpResponseInfo* response = trans->GetResponseInfo(); | |
743 ASSERT_TRUE(response); | |
744 | |
745 if (response_info) | |
746 *response_info = *response; | |
747 | |
748 ReadAndVerifyTransaction(trans.get(), trans_info); | |
749 } | |
750 | |
751 void RunTransactionTestWithRequest(net::HttpCache* cache, | |
752 const MockTransaction& trans_info, | |
753 const MockHttpRequest& request, | |
754 net::HttpResponseInfo* response_info) { | |
755 RunTransactionTestWithRequestAndLog(cache, trans_info, request, | |
756 response_info, net::BoundNetLog()); | |
757 } | |
758 | |
759 void RunTransactionTestWithLog(net::HttpCache* cache, | |
760 const MockTransaction& trans_info, | |
761 const net::BoundNetLog& log) { | |
762 RunTransactionTestWithRequestAndLog( | |
763 cache, trans_info, MockHttpRequest(trans_info), NULL, log); | |
764 } | |
765 | |
766 void RunTransactionTest(net::HttpCache* cache, | |
767 const MockTransaction& trans_info) { | |
768 RunTransactionTestWithLog(cache, trans_info, net::BoundNetLog()); | |
769 } | |
770 | |
771 void RunTransactionTestWithResponseInfo(net::HttpCache* cache, | |
772 const MockTransaction& trans_info, | |
773 net::HttpResponseInfo* response) { | |
774 RunTransactionTestWithRequest( | |
775 cache, trans_info, MockHttpRequest(trans_info), response); | |
776 } | |
777 | |
778 void RunTransactionTestWithResponse(net::HttpCache* cache, | |
779 const MockTransaction& trans_info, | |
780 std::string* response_headers) { | |
781 net::HttpResponseInfo response; | |
782 RunTransactionTestWithResponseInfo(cache, trans_info, &response); | |
783 response.headers->GetNormalizedHeaders(response_headers); | |
784 } | |
785 | |
786 // This class provides a handler for kFastNoStoreGET_Transaction so that the | |
787 // no-store header can be included on demand. | |
788 class FastTransactionServer { | |
789 public: | |
790 FastTransactionServer() { | |
791 no_store = false; | |
792 } | |
793 ~FastTransactionServer() {} | |
794 | |
795 void set_no_store(bool value) { no_store = value; } | |
796 | |
797 static void FastNoStoreHandler(const net::HttpRequestInfo* request, | |
798 std::string* response_status, | |
799 std::string* response_headers, | |
800 std::string* response_data) { | |
801 if (no_store) | |
802 *response_headers = "Cache-Control: no-store\n"; | |
803 } | |
804 | |
805 private: | |
806 static bool no_store; | |
807 DISALLOW_COPY_AND_ASSIGN(FastTransactionServer); | |
808 }; | |
809 bool FastTransactionServer::no_store; | |
810 | |
811 const MockTransaction kFastNoStoreGET_Transaction = { | |
812 "http://www.google.com/nostore", | |
813 "GET", | |
814 base::Time(), | |
815 "", | |
816 net::LOAD_VALIDATE_CACHE, | |
817 "HTTP/1.1 200 OK", | |
818 "Cache-Control: max-age=10000\n", | |
819 base::Time(), | |
820 "<html><body>Google Blah Blah</body></html>", | |
821 TEST_MODE_SYNC_NET_START, | |
822 &FastTransactionServer::FastNoStoreHandler, | |
823 0 | |
824 }; | |
825 | |
826 // This class provides a handler for kRangeGET_TransactionOK so that the range | |
827 // request can be served on demand. | |
828 class RangeTransactionServer { | |
829 public: | |
830 RangeTransactionServer() { | |
831 not_modified_ = false; | |
832 modified_ = false; | |
833 bad_200_ = false; | |
834 } | |
835 ~RangeTransactionServer() { | |
836 not_modified_ = false; | |
837 modified_ = false; | |
838 bad_200_ = false; | |
839 } | |
840 | |
841 // Returns only 416 or 304 when set. | |
842 void set_not_modified(bool value) { not_modified_ = value; } | |
843 | |
844 // Returns 206 when revalidating a range (instead of 304). | |
845 void set_modified(bool value) { modified_ = value; } | |
846 | |
847 // Returns 200 instead of 206 (a malformed response overall). | |
848 void set_bad_200(bool value) { bad_200_ = value; } | |
849 | |
850 static void RangeHandler(const net::HttpRequestInfo* request, | |
851 std::string* response_status, | |
852 std::string* response_headers, | |
853 std::string* response_data); | |
854 | |
855 private: | |
856 static bool not_modified_; | |
857 static bool modified_; | |
858 static bool bad_200_; | |
859 DISALLOW_COPY_AND_ASSIGN(RangeTransactionServer); | |
860 }; | |
861 bool RangeTransactionServer::not_modified_ = false; | |
862 bool RangeTransactionServer::modified_ = false; | |
863 bool RangeTransactionServer::bad_200_ = false; | |
864 | |
865 // A dummy extra header that must be preserved on a given request. | |
866 #define EXTRA_HEADER "Extra: header" | |
867 static const char kExtraHeaderKey[] = "Extra"; | |
868 | 553 |
869 // Static. | 554 // Static. |
870 void RangeTransactionServer::RangeHandler(const net::HttpRequestInfo* request, | 555 int MockHttpCache::GetTestMode(int test_mode) { |
871 std::string* response_status, | 556 if (!g_test_mode) |
872 std::string* response_headers, | 557 return test_mode; |
873 std::string* response_data) { | 558 |
874 if (request->extra_headers.IsEmpty()) { | 559 return g_test_mode; |
875 response_status->assign("HTTP/1.1 416 Requested Range Not Satisfiable"); | 560 } |
876 response_data->clear(); | 561 |
877 return; | 562 // Static. |
878 } | 563 void MockHttpCache::SetTestMode(int test_mode) { |
879 | 564 g_test_mode = test_mode; |
880 // We want to make sure we don't delete extra headers. | 565 } |
881 EXPECT_TRUE(request->extra_headers.HasHeader(kExtraHeaderKey)); | 566 |
882 | 567 //----------------------------------------------------------------------------- |
883 if (not_modified_) { | 568 |
884 response_status->assign("HTTP/1.1 304 Not Modified"); | 569 int MockDiskCacheNoCB::CreateEntry(const std::string& key, |
885 response_data->clear(); | 570 disk_cache::Entry** entry, |
886 return; | 571 net::OldCompletionCallback* callback) { |
887 } | 572 return net::ERR_IO_PENDING; |
888 | 573 } |
889 std::vector<net::HttpByteRange> ranges; | 574 |
890 std::string range_header; | 575 //----------------------------------------------------------------------------- |
891 if (!request->extra_headers.GetHeader( | 576 |
892 net::HttpRequestHeaders::kRange, &range_header) || | 577 int MockBackendNoCbFactory::CreateBackend(net::NetLog* net_log, |
893 !net::HttpUtil::ParseRangeHeader(range_header, &ranges) || bad_200_ || | 578 disk_cache::Backend** backend, |
894 ranges.size() != 1) { | 579 net::OldCompletionCallback* callback) { |
895 // This is not a byte range request. We return 200. | 580 *backend = new MockDiskCacheNoCB(); |
896 response_status->assign("HTTP/1.1 200 OK"); | 581 return net::OK; |
897 response_headers->assign("Date: Wed, 28 Nov 2007 09:40:09 GMT"); | 582 } |
898 response_data->assign("Not a range"); | 583 |
899 return; | 584 //----------------------------------------------------------------------------- |
900 } | 585 |
901 | 586 MockBlockingBackendFactory::MockBlockingBackendFactory() |
902 // We can handle this range request. | 587 : backend_(NULL), callback_(NULL), block_(true), fail_(false) { |
903 net::HttpByteRange byte_range = ranges[0]; | 588 } |
904 if (byte_range.first_byte_position() > 79) { | 589 |
905 response_status->assign("HTTP/1.1 416 Requested Range Not Satisfiable"); | 590 int MockBlockingBackendFactory::CreateBackend( |
906 response_data->clear(); | 591 net::NetLog* net_log, disk_cache::Backend** backend, |
907 return; | 592 net::OldCompletionCallback* callback) { |
908 } | 593 if (!block_) { |
909 | 594 if (!fail_) |
910 EXPECT_TRUE(byte_range.ComputeBounds(80)); | 595 *backend = new MockDiskCache(); |
911 int start = static_cast<int>(byte_range.first_byte_position()); | 596 return Result(); |
912 int end = static_cast<int>(byte_range.last_byte_position()); | 597 } |
913 | 598 |
914 EXPECT_LT(end, 80); | 599 backend_ = backend; |
915 | 600 callback_ = callback; |
916 std::string content_range = base::StringPrintf( | 601 return net::ERR_IO_PENDING; |
917 "Content-Range: bytes %d-%d/80\n", start, end); | 602 } |
918 response_headers->append(content_range); | 603 |
919 | 604 void MockBlockingBackendFactory::FinishCreation() { |
920 if (!request->extra_headers.HasHeader("If-None-Match") || modified_) { | 605 block_ = false; |
921 std::string data; | 606 if (callback_) { |
922 if (end == start) { | 607 if (!fail_) |
923 EXPECT_EQ(0, end % 10); | 608 *backend_ = new MockDiskCache(); |
924 data = "r"; | 609 net::OldCompletionCallback* cb = callback_; |
925 } else { | 610 callback_ = NULL; |
926 EXPECT_EQ(9, (end - start) % 10); | 611 cb->Run(Result()); // This object can be deleted here. |
927 for (int block_start = start; block_start < end; block_start += 10) { | 612 } |
928 base::StringAppendF(&data, "rg: %02d-%02d ", | 613 } |
929 block_start, block_start + 9); | |
930 } | |
931 } | |
932 *response_data = data; | |
933 | |
934 if (end - start != 9) { | |
935 // We also have to fix content-length. | |
936 int len = end - start + 1; | |
937 std::string content_length = base::StringPrintf("Content-Length: %d\n", | |
938 len); | |
939 response_headers->replace(response_headers->find("Content-Length:"), | |
940 content_length.size(), content_length); | |
941 } | |
942 } else { | |
943 response_status->assign("HTTP/1.1 304 Not Modified"); | |
944 response_data->clear(); | |
945 } | |
946 } | |
947 | |
948 const MockTransaction kRangeGET_TransactionOK = { | |
949 "http://www.google.com/range", | |
950 "GET", | |
951 base::Time(), | |
952 "Range: bytes = 40-49\r\n" | |
953 EXTRA_HEADER, | |
954 net::LOAD_NORMAL, | |
955 "HTTP/1.1 206 Partial Content", | |
956 "Last-Modified: Sat, 18 Apr 2007 01:10:43 GMT\n" | |
957 "ETag: \"foo\"\n" | |
958 "Accept-Ranges: bytes\n" | |
959 "Content-Length: 10\n", | |
960 base::Time(), | |
961 "rg: 40-49 ", | |
962 TEST_MODE_NORMAL, | |
963 &RangeTransactionServer::RangeHandler, | |
964 0 | |
965 }; | |
966 | |
967 // Verifies the response headers (|response|) match a partial content | |
968 // response for the range starting at |start| and ending at |end|. | |
969 void Verify206Response(std::string response, int start, int end) { | |
970 std::string raw_headers(net::HttpUtil::AssembleRawHeaders(response.data(), | |
971 response.size())); | |
972 scoped_refptr<net::HttpResponseHeaders> headers( | |
973 new net::HttpResponseHeaders(raw_headers)); | |
974 | |
975 ASSERT_EQ(206, headers->response_code()); | |
976 | |
977 int64 range_start, range_end, object_size; | |
978 ASSERT_TRUE( | |
979 headers->GetContentRange(&range_start, &range_end, &object_size)); | |
980 int64 content_length = headers->GetContentLength(); | |
981 | |
982 int length = end - start + 1; | |
983 ASSERT_EQ(length, content_length); | |
984 ASSERT_EQ(start, range_start); | |
985 ASSERT_EQ(end, range_end); | |
986 } | |
987 | |
988 // Creates a truncated entry that can be resumed using byte ranges. | |
989 void CreateTruncatedEntry(std::string raw_headers, MockHttpCache* cache) { | |
990 // Create a disk cache entry that stores an incomplete resource. | |
991 disk_cache::Entry* entry; | |
992 ASSERT_TRUE(cache->CreateBackendEntry(kRangeGET_TransactionOK.url, &entry, | |
993 NULL)); | |
994 | |
995 raw_headers = net::HttpUtil::AssembleRawHeaders(raw_headers.data(), | |
996 raw_headers.size()); | |
997 | |
998 net::HttpResponseInfo response; | |
999 response.response_time = base::Time::Now(); | |
1000 response.request_time = base::Time::Now(); | |
1001 response.headers = new net::HttpResponseHeaders(raw_headers); | |
1002 // Set the last argument for this to be an incomplete request. | |
1003 EXPECT_TRUE(MockHttpCache::WriteResponseInfo(entry, &response, true, true)); | |
1004 | |
1005 scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(100)); | |
1006 int len = static_cast<int>(base::strlcpy(buf->data(), | |
1007 "rg: 00-09 rg: 10-19 ", 100)); | |
1008 TestOldCompletionCallback cb; | |
1009 int rv = entry->WriteData(1, 0, buf, len, &cb, true); | |
1010 EXPECT_EQ(len, cb.GetResult(rv)); | |
1011 entry->Close(); | |
1012 } | |
1013 | |
1014 // Helper to represent a network HTTP response. | |
1015 struct Response { | |
1016 // Set this response into |trans|. | |
1017 void AssignTo(MockTransaction* trans) const { | |
1018 trans->status = status; | |
1019 trans->response_headers = headers; | |
1020 trans->data = body; | |
1021 } | |
1022 | |
1023 std::string status_and_headers() const { | |
1024 return std::string(status) + "\n" + std::string(headers); | |
1025 } | |
1026 | |
1027 const char* status; | |
1028 const char* headers; | |
1029 const char* body; | |
1030 }; | |
1031 | |
1032 struct Context { | |
1033 Context() : result(net::ERR_IO_PENDING) {} | |
1034 | |
1035 int result; | |
1036 TestOldCompletionCallback callback; | |
1037 scoped_ptr<net::HttpTransaction> trans; | |
1038 }; | |
1039 | |
1040 } // namespace | |
1041 | |
1042 | |
1043 //----------------------------------------------------------------------------- | |
1044 // HttpCache tests | |
1045 | |
1046 TEST(HttpCache, CreateThenDestroy) { | |
1047 MockHttpCache cache; | |
1048 | |
1049 scoped_ptr<net::HttpTransaction> trans; | |
1050 int rv = cache.http_cache()->CreateTransaction(&trans); | |
1051 EXPECT_EQ(net::OK, rv); | |
1052 ASSERT_TRUE(trans.get()); | |
1053 } | |
1054 | |
1055 TEST(HttpCache, GetBackend) { | |
1056 MockHttpCache cache(net::HttpCache::DefaultBackend::InMemory(0)); | |
1057 | |
1058 disk_cache::Backend* backend; | |
1059 TestOldCompletionCallback cb; | |
1060 // This will lazily initialize the backend. | |
1061 int rv = cache.http_cache()->GetBackend(&backend, &cb); | |
1062 EXPECT_EQ(net::OK, cb.GetResult(rv)); | |
1063 } | |
1064 | |
1065 TEST(HttpCache, SimpleGET) { | |
1066 MockHttpCache cache; | |
1067 | |
1068 // write to the cache | |
1069 RunTransactionTest(cache.http_cache(), kSimpleGET_Transaction); | |
1070 | |
1071 EXPECT_EQ(1, cache.network_layer()->transaction_count()); | |
1072 EXPECT_EQ(0, cache.disk_cache()->open_count()); | |
1073 EXPECT_EQ(1, cache.disk_cache()->create_count()); | |
1074 } | |
1075 | |
1076 TEST(HttpCache, SimpleGETNoDiskCache) { | |
1077 MockHttpCache cache; | |
1078 | |
1079 cache.disk_cache()->set_fail_requests(); | |
1080 | |
1081 net::CapturingBoundNetLog log(net::CapturingNetLog::kUnbounded); | |
1082 log.SetLogLevel(net::NetLog::LOG_BASIC); | |
1083 | |
1084 // Read from the network, and don't use the cache. | |
1085 RunTransactionTestWithLog(cache.http_cache(), kSimpleGET_Transaction, | |
1086 log.bound()); | |
1087 | |
1088 // Check that the NetLog was filled as expected. | |
1089 // (We attempted to both Open and Create entries, but both failed). | |
1090 net::CapturingNetLog::EntryList entries; | |
1091 log.GetEntries(&entries); | |
1092 | |
1093 EXPECT_EQ(6u, entries.size()); | |
1094 EXPECT_TRUE(net::LogContainsBeginEvent( | |
1095 entries, 0, net::NetLog::TYPE_HTTP_CACHE_GET_BACKEND)); | |
1096 EXPECT_TRUE(net::LogContainsEndEvent( | |
1097 entries, 1, net::NetLog::TYPE_HTTP_CACHE_GET_BACKEND)); | |
1098 EXPECT_TRUE(net::LogContainsBeginEvent( | |
1099 entries, 2, net::NetLog::TYPE_HTTP_CACHE_OPEN_ENTRY)); | |
1100 EXPECT_TRUE(net::LogContainsEndEvent( | |
1101 entries, 3, net::NetLog::TYPE_HTTP_CACHE_OPEN_ENTRY)); | |
1102 EXPECT_TRUE(net::LogContainsBeginEvent( | |
1103 entries, 4, net::NetLog::TYPE_HTTP_CACHE_CREATE_ENTRY)); | |
1104 EXPECT_TRUE(net::LogContainsEndEvent( | |
1105 entries, 5, net::NetLog::TYPE_HTTP_CACHE_CREATE_ENTRY)); | |
1106 | |
1107 EXPECT_EQ(1, cache.network_layer()->transaction_count()); | |
1108 EXPECT_EQ(0, cache.disk_cache()->open_count()); | |
1109 EXPECT_EQ(0, cache.disk_cache()->create_count()); | |
1110 } | |
1111 | |
1112 TEST(HttpCache, SimpleGETNoDiskCache2) { | |
1113 // This will initialize a cache object with NULL backend. | |
1114 MockBlockingBackendFactory* factory = new MockBlockingBackendFactory(); | |
1115 factory->set_fail(true); | |
1116 factory->FinishCreation(); // We'll complete synchronously. | |
1117 MockHttpCache cache(factory); | |
1118 | |
1119 // Read from the network, and don't use the cache. | |
1120 RunTransactionTest(cache.http_cache(), kSimpleGET_Transaction); | |
1121 | |
1122 EXPECT_EQ(1, cache.network_layer()->transaction_count()); | |
1123 EXPECT_FALSE(cache.http_cache()->GetCurrentBackend()); | |
1124 } | |
1125 | |
1126 TEST(HttpCache, SimpleGETWithDiskFailures) { | |
1127 MockHttpCache cache; | |
1128 | |
1129 cache.disk_cache()->set_soft_failures(true); | |
1130 | |
1131 // Read from the network, and fail to write to the cache. | |
1132 RunTransactionTest(cache.http_cache(), kSimpleGET_Transaction); | |
1133 | |
1134 EXPECT_EQ(1, cache.network_layer()->transaction_count()); | |
1135 EXPECT_EQ(0, cache.disk_cache()->open_count()); | |
1136 EXPECT_EQ(1, cache.disk_cache()->create_count()); | |
1137 | |
1138 // This one should see an empty cache again. | |
1139 RunTransactionTest(cache.http_cache(), kSimpleGET_Transaction); | |
1140 | |
1141 EXPECT_EQ(2, cache.network_layer()->transaction_count()); | |
1142 EXPECT_EQ(0, cache.disk_cache()->open_count()); | |
1143 EXPECT_EQ(2, cache.disk_cache()->create_count()); | |
1144 } | |
1145 | |
1146 // Tests that disk failures after the transaction has started don't cause the | |
1147 // request to fail. | |
1148 TEST(HttpCache, SimpleGETWithDiskFailures2) { | |
1149 MockHttpCache cache; | |
1150 | |
1151 MockHttpRequest request(kSimpleGET_Transaction); | |
1152 | |
1153 scoped_ptr<Context> c(new Context()); | |
1154 int rv = cache.http_cache()->CreateTransaction(&c->trans); | |
1155 EXPECT_EQ(net::OK, rv); | |
1156 | |
1157 rv = c->trans->Start(&request, &c->callback, net::BoundNetLog()); | |
1158 EXPECT_EQ(net::ERR_IO_PENDING, rv); | |
1159 rv = c->callback.WaitForResult(); | |
1160 | |
1161 // Start failing request now. | |
1162 cache.disk_cache()->set_soft_failures(true); | |
1163 | |
1164 // We have to open the entry again to propagate the failure flag. | |
1165 disk_cache::Entry* en; | |
1166 ASSERT_TRUE(cache.OpenBackendEntry(kSimpleGET_Transaction.url, &en)); | |
1167 en->Close(); | |
1168 | |
1169 ReadAndVerifyTransaction(c->trans.get(), kSimpleGET_Transaction); | |
1170 c.reset(); | |
1171 | |
1172 EXPECT_EQ(1, cache.network_layer()->transaction_count()); | |
1173 EXPECT_EQ(1, cache.disk_cache()->open_count()); | |
1174 EXPECT_EQ(1, cache.disk_cache()->create_count()); | |
1175 | |
1176 // This one should see an empty cache again. | |
1177 RunTransactionTest(cache.http_cache(), kSimpleGET_Transaction); | |
1178 | |
1179 EXPECT_EQ(2, cache.network_layer()->transaction_count()); | |
1180 EXPECT_EQ(1, cache.disk_cache()->open_count()); | |
1181 EXPECT_EQ(2, cache.disk_cache()->create_count()); | |
1182 } | |
1183 | |
1184 // Tests that we don't crash after failures to read from the cache. | |
1185 TEST(HttpCache, SimpleGETWithDiskFailures3) { | |
1186 MockHttpCache cache; | |
1187 | |
1188 // Read from the network, and write to the cache. | |
1189 RunTransactionTest(cache.http_cache(), kSimpleGET_Transaction); | |
1190 | |
1191 EXPECT_EQ(1, cache.network_layer()->transaction_count()); | |
1192 EXPECT_EQ(0, cache.disk_cache()->open_count()); | |
1193 EXPECT_EQ(1, cache.disk_cache()->create_count()); | |
1194 | |
1195 cache.disk_cache()->set_soft_failures(true); | |
1196 | |
1197 // Now fail to read from the cache. | |
1198 scoped_ptr<Context> c(new Context()); | |
1199 int rv = cache.http_cache()->CreateTransaction(&c->trans); | |
1200 EXPECT_EQ(net::OK, rv); | |
1201 | |
1202 MockHttpRequest request(kSimpleGET_Transaction); | |
1203 rv = c->trans->Start(&request, &c->callback, net::BoundNetLog()); | |
1204 EXPECT_EQ(net::ERR_CACHE_READ_FAILURE, c->callback.GetResult(rv)); | |
1205 } | |
1206 | |
1207 TEST(HttpCache, SimpleGET_LoadOnlyFromCache_Hit) { | |
1208 MockHttpCache cache; | |
1209 | |
1210 net::CapturingBoundNetLog log(net::CapturingNetLog::kUnbounded); | |
1211 | |
1212 // This prevents a number of write events from being logged. | |
1213 log.SetLogLevel(net::NetLog::LOG_BASIC); | |
1214 | |
1215 // write to the cache | |
1216 RunTransactionTestWithLog(cache.http_cache(), kSimpleGET_Transaction, | |
1217 log.bound()); | |
1218 | |
1219 // Check that the NetLog was filled as expected. | |
1220 net::CapturingNetLog::EntryList entries; | |
1221 log.GetEntries(&entries); | |
1222 | |
1223 EXPECT_EQ(8u, entries.size()); | |
1224 EXPECT_TRUE(net::LogContainsBeginEvent( | |
1225 entries, 0, net::NetLog::TYPE_HTTP_CACHE_GET_BACKEND)); | |
1226 EXPECT_TRUE(net::LogContainsEndEvent( | |
1227 entries, 1, net::NetLog::TYPE_HTTP_CACHE_GET_BACKEND)); | |
1228 EXPECT_TRUE(net::LogContainsBeginEvent( | |
1229 entries, 2, net::NetLog::TYPE_HTTP_CACHE_OPEN_ENTRY)); | |
1230 EXPECT_TRUE(net::LogContainsEndEvent( | |
1231 entries, 3, net::NetLog::TYPE_HTTP_CACHE_OPEN_ENTRY)); | |
1232 EXPECT_TRUE(net::LogContainsBeginEvent( | |
1233 entries, 4, net::NetLog::TYPE_HTTP_CACHE_CREATE_ENTRY)); | |
1234 EXPECT_TRUE(net::LogContainsEndEvent( | |
1235 entries, 5, net::NetLog::TYPE_HTTP_CACHE_CREATE_ENTRY)); | |
1236 EXPECT_TRUE(net::LogContainsBeginEvent( | |
1237 entries, 6, net::NetLog::TYPE_HTTP_CACHE_ADD_TO_ENTRY)); | |
1238 EXPECT_TRUE(net::LogContainsEndEvent( | |
1239 entries, 7, net::NetLog::TYPE_HTTP_CACHE_ADD_TO_ENTRY)); | |
1240 | |
1241 // force this transaction to read from the cache | |
1242 MockTransaction transaction(kSimpleGET_Transaction); | |
1243 transaction.load_flags |= net::LOAD_ONLY_FROM_CACHE; | |
1244 | |
1245 log.Clear(); | |
1246 | |
1247 RunTransactionTestWithLog(cache.http_cache(), transaction, log.bound()); | |
1248 | |
1249 // Check that the NetLog was filled as expected. | |
1250 log.GetEntries(&entries); | |
1251 | |
1252 EXPECT_EQ(8u, entries.size()); | |
1253 EXPECT_TRUE(net::LogContainsBeginEvent( | |
1254 entries, 0, net::NetLog::TYPE_HTTP_CACHE_GET_BACKEND)); | |
1255 EXPECT_TRUE(net::LogContainsEndEvent( | |
1256 entries, 1, net::NetLog::TYPE_HTTP_CACHE_GET_BACKEND)); | |
1257 EXPECT_TRUE(net::LogContainsBeginEvent( | |
1258 entries, 2, net::NetLog::TYPE_HTTP_CACHE_OPEN_ENTRY)); | |
1259 EXPECT_TRUE(net::LogContainsEndEvent( | |
1260 entries, 3, net::NetLog::TYPE_HTTP_CACHE_OPEN_ENTRY)); | |
1261 EXPECT_TRUE(net::LogContainsBeginEvent( | |
1262 entries, 4, net::NetLog::TYPE_HTTP_CACHE_ADD_TO_ENTRY)); | |
1263 EXPECT_TRUE(net::LogContainsEndEvent( | |
1264 entries, 5, net::NetLog::TYPE_HTTP_CACHE_ADD_TO_ENTRY)); | |
1265 EXPECT_TRUE(net::LogContainsBeginEvent( | |
1266 entries, 6, net::NetLog::TYPE_HTTP_CACHE_READ_INFO)); | |
1267 EXPECT_TRUE(net::LogContainsEndEvent( | |
1268 entries, 7, net::NetLog::TYPE_HTTP_CACHE_READ_INFO)); | |
1269 | |
1270 EXPECT_EQ(1, cache.network_layer()->transaction_count()); | |
1271 EXPECT_EQ(1, cache.disk_cache()->open_count()); | |
1272 EXPECT_EQ(1, cache.disk_cache()->create_count()); | |
1273 } | |
1274 | |
1275 TEST(HttpCache, SimpleGET_LoadOnlyFromCache_Miss) { | |
1276 MockHttpCache cache; | |
1277 | |
1278 // force this transaction to read from the cache | |
1279 MockTransaction transaction(kSimpleGET_Transaction); | |
1280 transaction.load_flags |= net::LOAD_ONLY_FROM_CACHE; | |
1281 | |
1282 MockHttpRequest request(transaction); | |
1283 TestOldCompletionCallback callback; | |
1284 | |
1285 scoped_ptr<net::HttpTransaction> trans; | |
1286 int rv = cache.http_cache()->CreateTransaction(&trans); | |
1287 EXPECT_EQ(net::OK, rv); | |
1288 ASSERT_TRUE(trans.get()); | |
1289 | |
1290 rv = trans->Start(&request, &callback, net::BoundNetLog()); | |
1291 if (rv == net::ERR_IO_PENDING) | |
1292 rv = callback.WaitForResult(); | |
1293 ASSERT_EQ(net::ERR_CACHE_MISS, rv); | |
1294 | |
1295 trans.reset(); | |
1296 | |
1297 EXPECT_EQ(0, cache.network_layer()->transaction_count()); | |
1298 EXPECT_EQ(0, cache.disk_cache()->open_count()); | |
1299 EXPECT_EQ(0, cache.disk_cache()->create_count()); | |
1300 } | |
1301 | |
1302 TEST(HttpCache, SimpleGET_LoadPreferringCache_Hit) { | |
1303 MockHttpCache cache; | |
1304 | |
1305 // write to the cache | |
1306 RunTransactionTest(cache.http_cache(), kSimpleGET_Transaction); | |
1307 | |
1308 // force this transaction to read from the cache if valid | |
1309 MockTransaction transaction(kSimpleGET_Transaction); | |
1310 transaction.load_flags |= net::LOAD_PREFERRING_CACHE; | |
1311 | |
1312 RunTransactionTest(cache.http_cache(), transaction); | |
1313 | |
1314 EXPECT_EQ(1, cache.network_layer()->transaction_count()); | |
1315 EXPECT_EQ(1, cache.disk_cache()->open_count()); | |
1316 EXPECT_EQ(1, cache.disk_cache()->create_count()); | |
1317 } | |
1318 | |
1319 TEST(HttpCache, SimpleGET_LoadPreferringCache_Miss) { | |
1320 MockHttpCache cache; | |
1321 | |
1322 // force this transaction to read from the cache if valid | |
1323 MockTransaction transaction(kSimpleGET_Transaction); | |
1324 transaction.load_flags |= net::LOAD_PREFERRING_CACHE; | |
1325 | |
1326 RunTransactionTest(cache.http_cache(), transaction); | |
1327 | |
1328 EXPECT_EQ(1, cache.network_layer()->transaction_count()); | |
1329 EXPECT_EQ(0, cache.disk_cache()->open_count()); | |
1330 EXPECT_EQ(1, cache.disk_cache()->create_count()); | |
1331 } | |
1332 | |
1333 TEST(HttpCache, SimpleGET_LoadBypassCache) { | |
1334 MockHttpCache cache; | |
1335 | |
1336 // Write to the cache. | |
1337 RunTransactionTest(cache.http_cache(), kSimpleGET_Transaction); | |
1338 | |
1339 // Force this transaction to write to the cache again. | |
1340 MockTransaction transaction(kSimpleGET_Transaction); | |
1341 transaction.load_flags |= net::LOAD_BYPASS_CACHE; | |
1342 | |
1343 net::CapturingBoundNetLog log(net::CapturingNetLog::kUnbounded); | |
1344 | |
1345 // This prevents a number of write events from being logged. | |
1346 log.SetLogLevel(net::NetLog::LOG_BASIC); | |
1347 | |
1348 RunTransactionTestWithLog(cache.http_cache(), transaction, log.bound()); | |
1349 | |
1350 // Check that the NetLog was filled as expected. | |
1351 net::CapturingNetLog::EntryList entries; | |
1352 log.GetEntries(&entries); | |
1353 | |
1354 EXPECT_EQ(8u, entries.size()); | |
1355 EXPECT_TRUE(net::LogContainsBeginEvent( | |
1356 entries, 0, net::NetLog::TYPE_HTTP_CACHE_GET_BACKEND)); | |
1357 EXPECT_TRUE(net::LogContainsEndEvent( | |
1358 entries, 1, net::NetLog::TYPE_HTTP_CACHE_GET_BACKEND)); | |
1359 EXPECT_TRUE(net::LogContainsBeginEvent( | |
1360 entries, 2, net::NetLog::TYPE_HTTP_CACHE_DOOM_ENTRY)); | |
1361 EXPECT_TRUE(net::LogContainsEndEvent( | |
1362 entries, 3, net::NetLog::TYPE_HTTP_CACHE_DOOM_ENTRY)); | |
1363 EXPECT_TRUE(net::LogContainsBeginEvent( | |
1364 entries, 4, net::NetLog::TYPE_HTTP_CACHE_CREATE_ENTRY)); | |
1365 EXPECT_TRUE(net::LogContainsEndEvent( | |
1366 entries, 5, net::NetLog::TYPE_HTTP_CACHE_CREATE_ENTRY)); | |
1367 EXPECT_TRUE(net::LogContainsBeginEvent( | |
1368 entries, 6, net::NetLog::TYPE_HTTP_CACHE_ADD_TO_ENTRY)); | |
1369 EXPECT_TRUE(net::LogContainsEndEvent( | |
1370 entries, 7, net::NetLog::TYPE_HTTP_CACHE_ADD_TO_ENTRY)); | |
1371 | |
1372 EXPECT_EQ(2, cache.network_layer()->transaction_count()); | |
1373 EXPECT_EQ(0, cache.disk_cache()->open_count()); | |
1374 EXPECT_EQ(2, cache.disk_cache()->create_count()); | |
1375 } | |
1376 | |
1377 TEST(HttpCache, SimpleGET_LoadBypassCache_Implicit) { | |
1378 MockHttpCache cache; | |
1379 | |
1380 // write to the cache | |
1381 RunTransactionTest(cache.http_cache(), kSimpleGET_Transaction); | |
1382 | |
1383 // force this transaction to write to the cache again | |
1384 MockTransaction transaction(kSimpleGET_Transaction); | |
1385 transaction.request_headers = "pragma: no-cache"; | |
1386 | |
1387 RunTransactionTest(cache.http_cache(), transaction); | |
1388 | |
1389 EXPECT_EQ(2, cache.network_layer()->transaction_count()); | |
1390 EXPECT_EQ(0, cache.disk_cache()->open_count()); | |
1391 EXPECT_EQ(2, cache.disk_cache()->create_count()); | |
1392 } | |
1393 | |
1394 TEST(HttpCache, SimpleGET_LoadBypassCache_Implicit2) { | |
1395 MockHttpCache cache; | |
1396 | |
1397 // write to the cache | |
1398 RunTransactionTest(cache.http_cache(), kSimpleGET_Transaction); | |
1399 | |
1400 // force this transaction to write to the cache again | |
1401 MockTransaction transaction(kSimpleGET_Transaction); | |
1402 transaction.request_headers = "cache-control: no-cache"; | |
1403 | |
1404 RunTransactionTest(cache.http_cache(), transaction); | |
1405 | |
1406 EXPECT_EQ(2, cache.network_layer()->transaction_count()); | |
1407 EXPECT_EQ(0, cache.disk_cache()->open_count()); | |
1408 EXPECT_EQ(2, cache.disk_cache()->create_count()); | |
1409 } | |
1410 | |
1411 TEST(HttpCache, SimpleGET_LoadValidateCache) { | |
1412 MockHttpCache cache; | |
1413 | |
1414 // write to the cache | |
1415 RunTransactionTest(cache.http_cache(), kSimpleGET_Transaction); | |
1416 | |
1417 // read from the cache | |
1418 RunTransactionTest(cache.http_cache(), kSimpleGET_Transaction); | |
1419 | |
1420 // force this transaction to validate the cache | |
1421 MockTransaction transaction(kSimpleGET_Transaction); | |
1422 transaction.load_flags |= net::LOAD_VALIDATE_CACHE; | |
1423 | |
1424 RunTransactionTest(cache.http_cache(), transaction); | |
1425 | |
1426 EXPECT_EQ(2, cache.network_layer()->transaction_count()); | |
1427 EXPECT_EQ(1, cache.disk_cache()->open_count()); | |
1428 EXPECT_EQ(1, cache.disk_cache()->create_count()); | |
1429 } | |
1430 | |
1431 TEST(HttpCache, SimpleGET_LoadValidateCache_Implicit) { | |
1432 MockHttpCache cache; | |
1433 | |
1434 // write to the cache | |
1435 RunTransactionTest(cache.http_cache(), kSimpleGET_Transaction); | |
1436 | |
1437 // read from the cache | |
1438 RunTransactionTest(cache.http_cache(), kSimpleGET_Transaction); | |
1439 | |
1440 // force this transaction to validate the cache | |
1441 MockTransaction transaction(kSimpleGET_Transaction); | |
1442 transaction.request_headers = "cache-control: max-age=0"; | |
1443 | |
1444 RunTransactionTest(cache.http_cache(), transaction); | |
1445 | |
1446 EXPECT_EQ(2, cache.network_layer()->transaction_count()); | |
1447 EXPECT_EQ(1, cache.disk_cache()->open_count()); | |
1448 EXPECT_EQ(1, cache.disk_cache()->create_count()); | |
1449 } | |
1450 | |
1451 static void PreserveRequestHeaders_Handler( | |
1452 const net::HttpRequestInfo* request, | |
1453 std::string* response_status, | |
1454 std::string* response_headers, | |
1455 std::string* response_data) { | |
1456 EXPECT_TRUE(request->extra_headers.HasHeader(kExtraHeaderKey)); | |
1457 } | |
1458 | |
1459 // Tests that we don't remove extra headers for simple requests. | |
1460 TEST(HttpCache, SimpleGET_PreserveRequestHeaders) { | |
1461 MockHttpCache cache; | |
1462 | |
1463 MockTransaction transaction(kSimpleGET_Transaction); | |
1464 transaction.handler = PreserveRequestHeaders_Handler; | |
1465 transaction.request_headers = EXTRA_HEADER; | |
1466 transaction.response_headers = "Cache-Control: max-age=0\n"; | |
1467 AddMockTransaction(&transaction); | |
1468 | |
1469 // Write, then revalidate the entry. | |
1470 RunTransactionTest(cache.http_cache(), transaction); | |
1471 RunTransactionTest(cache.http_cache(), transaction); | |
1472 | |
1473 EXPECT_EQ(2, cache.network_layer()->transaction_count()); | |
1474 EXPECT_EQ(1, cache.disk_cache()->open_count()); | |
1475 EXPECT_EQ(1, cache.disk_cache()->create_count()); | |
1476 RemoveMockTransaction(&transaction); | |
1477 } | |
1478 | |
1479 // Tests that we don't remove extra headers for conditionalized requests. | |
1480 TEST(HttpCache, ConditionalizedGET_PreserveRequestHeaders) { | |
1481 MockHttpCache cache; | |
1482 | |
1483 // Write to the cache. | |
1484 RunTransactionTest(cache.http_cache(), kETagGET_Transaction); | |
1485 | |
1486 MockTransaction transaction(kETagGET_Transaction); | |
1487 transaction.handler = PreserveRequestHeaders_Handler; | |
1488 transaction.request_headers = "If-None-Match: \"foopy\"\r\n" | |
1489 EXTRA_HEADER; | |
1490 AddMockTransaction(&transaction); | |
1491 | |
1492 RunTransactionTest(cache.http_cache(), transaction); | |
1493 | |
1494 EXPECT_EQ(2, cache.network_layer()->transaction_count()); | |
1495 EXPECT_EQ(1, cache.disk_cache()->open_count()); | |
1496 EXPECT_EQ(1, cache.disk_cache()->create_count()); | |
1497 RemoveMockTransaction(&transaction); | |
1498 } | |
1499 | |
1500 TEST(HttpCache, SimpleGET_ManyReaders) { | |
1501 MockHttpCache cache; | |
1502 | |
1503 MockHttpRequest request(kSimpleGET_Transaction); | |
1504 | |
1505 std::vector<Context*> context_list; | |
1506 const int kNumTransactions = 5; | |
1507 | |
1508 for (int i = 0; i < kNumTransactions; ++i) { | |
1509 context_list.push_back(new Context()); | |
1510 Context* c = context_list[i]; | |
1511 | |
1512 c->result = cache.http_cache()->CreateTransaction(&c->trans); | |
1513 EXPECT_EQ(net::OK, c->result); | |
1514 EXPECT_EQ(net::LOAD_STATE_IDLE, c->trans->GetLoadState()); | |
1515 | |
1516 c->result = c->trans->Start(&request, &c->callback, net::BoundNetLog()); | |
1517 } | |
1518 | |
1519 // All requests are waiting for the active entry. | |
1520 for (int i = 0; i < kNumTransactions; ++i) { | |
1521 Context* c = context_list[i]; | |
1522 EXPECT_EQ(net::LOAD_STATE_WAITING_FOR_CACHE, c->trans->GetLoadState()); | |
1523 } | |
1524 | |
1525 // Allow all requests to move from the Create queue to the active entry. | |
1526 MessageLoop::current()->RunAllPending(); | |
1527 | |
1528 // The first request should be a writer at this point, and the subsequent | |
1529 // requests should be pending. | |
1530 | |
1531 EXPECT_EQ(1, cache.network_layer()->transaction_count()); | |
1532 EXPECT_EQ(0, cache.disk_cache()->open_count()); | |
1533 EXPECT_EQ(1, cache.disk_cache()->create_count()); | |
1534 | |
1535 // All requests depend on the writer, and the writer is between Start and | |
1536 // Read, i.e. idle. | |
1537 for (int i = 0; i < kNumTransactions; ++i) { | |
1538 Context* c = context_list[i]; | |
1539 EXPECT_EQ(net::LOAD_STATE_IDLE, c->trans->GetLoadState()); | |
1540 } | |
1541 | |
1542 for (int i = 0; i < kNumTransactions; ++i) { | |
1543 Context* c = context_list[i]; | |
1544 if (c->result == net::ERR_IO_PENDING) | |
1545 c->result = c->callback.WaitForResult(); | |
1546 ReadAndVerifyTransaction(c->trans.get(), kSimpleGET_Transaction); | |
1547 } | |
1548 | |
1549 // We should not have had to re-open the disk entry | |
1550 | |
1551 EXPECT_EQ(1, cache.network_layer()->transaction_count()); | |
1552 EXPECT_EQ(0, cache.disk_cache()->open_count()); | |
1553 EXPECT_EQ(1, cache.disk_cache()->create_count()); | |
1554 | |
1555 for (int i = 0; i < kNumTransactions; ++i) { | |
1556 Context* c = context_list[i]; | |
1557 delete c; | |
1558 } | |
1559 } | |
1560 | |
1561 // This is a test for http://code.google.com/p/chromium/issues/detail?id=4769. | |
1562 // If cancelling a request is racing with another request for the same resource | |
1563 // finishing, we have to make sure that we remove both transactions from the | |
1564 // entry. | |
1565 TEST(HttpCache, SimpleGET_RacingReaders) { | |
1566 MockHttpCache cache; | |
1567 | |
1568 MockHttpRequest request(kSimpleGET_Transaction); | |
1569 MockHttpRequest reader_request(kSimpleGET_Transaction); | |
1570 reader_request.load_flags = net::LOAD_ONLY_FROM_CACHE; | |
1571 | |
1572 std::vector<Context*> context_list; | |
1573 const int kNumTransactions = 5; | |
1574 | |
1575 for (int i = 0; i < kNumTransactions; ++i) { | |
1576 context_list.push_back(new Context()); | |
1577 Context* c = context_list[i]; | |
1578 | |
1579 c->result = cache.http_cache()->CreateTransaction(&c->trans); | |
1580 EXPECT_EQ(net::OK, c->result); | |
1581 | |
1582 MockHttpRequest* this_request = &request; | |
1583 if (i == 1 || i == 2) | |
1584 this_request = &reader_request; | |
1585 | |
1586 c->result = c->trans->Start(this_request, &c->callback, net::BoundNetLog()); | |
1587 } | |
1588 | |
1589 // Allow all requests to move from the Create queue to the active entry. | |
1590 MessageLoop::current()->RunAllPending(); | |
1591 | |
1592 // The first request should be a writer at this point, and the subsequent | |
1593 // requests should be pending. | |
1594 | |
1595 EXPECT_EQ(1, cache.network_layer()->transaction_count()); | |
1596 EXPECT_EQ(0, cache.disk_cache()->open_count()); | |
1597 EXPECT_EQ(1, cache.disk_cache()->create_count()); | |
1598 | |
1599 Context* c = context_list[0]; | |
1600 ASSERT_EQ(net::ERR_IO_PENDING, c->result); | |
1601 c->result = c->callback.WaitForResult(); | |
1602 ReadAndVerifyTransaction(c->trans.get(), kSimpleGET_Transaction); | |
1603 | |
1604 // Now we have 2 active readers and two queued transactions. | |
1605 | |
1606 EXPECT_EQ(net::LOAD_STATE_IDLE, | |
1607 context_list[2]->trans->GetLoadState()); | |
1608 EXPECT_EQ(net::LOAD_STATE_WAITING_FOR_CACHE, | |
1609 context_list[3]->trans->GetLoadState()); | |
1610 | |
1611 c = context_list[1]; | |
1612 ASSERT_EQ(net::ERR_IO_PENDING, c->result); | |
1613 c->result = c->callback.WaitForResult(); | |
1614 if (c->result == net::OK) | |
1615 ReadAndVerifyTransaction(c->trans.get(), kSimpleGET_Transaction); | |
1616 | |
1617 // At this point we have one reader, two pending transactions and a task on | |
1618 // the queue to move to the next transaction. Now we cancel the request that | |
1619 // is the current reader, and expect the queued task to be able to start the | |
1620 // next request. | |
1621 | |
1622 c = context_list[2]; | |
1623 c->trans.reset(); | |
1624 | |
1625 for (int i = 3; i < kNumTransactions; ++i) { | |
1626 Context* c = context_list[i]; | |
1627 if (c->result == net::ERR_IO_PENDING) | |
1628 c->result = c->callback.WaitForResult(); | |
1629 if (c->result == net::OK) | |
1630 ReadAndVerifyTransaction(c->trans.get(), kSimpleGET_Transaction); | |
1631 } | |
1632 | |
1633 // We should not have had to re-open the disk entry. | |
1634 | |
1635 EXPECT_EQ(1, cache.network_layer()->transaction_count()); | |
1636 EXPECT_EQ(0, cache.disk_cache()->open_count()); | |
1637 EXPECT_EQ(1, cache.disk_cache()->create_count()); | |
1638 | |
1639 for (int i = 0; i < kNumTransactions; ++i) { | |
1640 Context* c = context_list[i]; | |
1641 delete c; | |
1642 } | |
1643 } | |
1644 | |
1645 // Tests that we can doom an entry with pending transactions and delete one of | |
1646 // the pending transactions before the first one completes. | |
1647 // See http://code.google.com/p/chromium/issues/detail?id=25588 | |
1648 TEST(HttpCache, SimpleGET_DoomWithPending) { | |
1649 // We need simultaneous doomed / not_doomed entries so let's use a real cache. | |
1650 MockHttpCache cache(net::HttpCache::DefaultBackend::InMemory(1024 * 1024)); | |
1651 | |
1652 MockHttpRequest request(kSimpleGET_Transaction); | |
1653 MockHttpRequest writer_request(kSimpleGET_Transaction); | |
1654 writer_request.load_flags = net::LOAD_BYPASS_CACHE; | |
1655 | |
1656 ScopedVector<Context> context_list; | |
1657 const int kNumTransactions = 4; | |
1658 | |
1659 for (int i = 0; i < kNumTransactions; ++i) { | |
1660 context_list.push_back(new Context()); | |
1661 Context* c = context_list[i]; | |
1662 | |
1663 c->result = cache.http_cache()->CreateTransaction(&c->trans); | |
1664 EXPECT_EQ(net::OK, c->result); | |
1665 | |
1666 MockHttpRequest* this_request = &request; | |
1667 if (i == 3) | |
1668 this_request = &writer_request; | |
1669 | |
1670 c->result = c->trans->Start(this_request, &c->callback, net::BoundNetLog()); | |
1671 } | |
1672 | |
1673 // The first request should be a writer at this point, and the two subsequent | |
1674 // requests should be pending. The last request doomed the first entry. | |
1675 | |
1676 EXPECT_EQ(2, cache.network_layer()->transaction_count()); | |
1677 | |
1678 // Cancel the first queued transaction. | |
1679 delete context_list[1]; | |
1680 context_list.get()[1] = NULL; | |
1681 | |
1682 for (int i = 0; i < kNumTransactions; ++i) { | |
1683 if (i == 1) | |
1684 continue; | |
1685 Context* c = context_list[i]; | |
1686 ASSERT_EQ(net::ERR_IO_PENDING, c->result); | |
1687 c->result = c->callback.WaitForResult(); | |
1688 ReadAndVerifyTransaction(c->trans.get(), kSimpleGET_Transaction); | |
1689 } | |
1690 } | |
1691 | |
1692 // This is a test for http://code.google.com/p/chromium/issues/detail?id=4731. | |
1693 // We may attempt to delete an entry synchronously with the act of adding a new | |
1694 // transaction to said entry. | |
1695 TEST(HttpCache, FastNoStoreGET_DoneWithPending) { | |
1696 MockHttpCache cache; | |
1697 | |
1698 // The headers will be served right from the call to Start() the request. | |
1699 MockHttpRequest request(kFastNoStoreGET_Transaction); | |
1700 FastTransactionServer request_handler; | |
1701 AddMockTransaction(&kFastNoStoreGET_Transaction); | |
1702 | |
1703 std::vector<Context*> context_list; | |
1704 const int kNumTransactions = 3; | |
1705 | |
1706 for (int i = 0; i < kNumTransactions; ++i) { | |
1707 context_list.push_back(new Context()); | |
1708 Context* c = context_list[i]; | |
1709 | |
1710 c->result = cache.http_cache()->CreateTransaction(&c->trans); | |
1711 EXPECT_EQ(net::OK, c->result); | |
1712 | |
1713 c->result = c->trans->Start(&request, &c->callback, net::BoundNetLog()); | |
1714 } | |
1715 | |
1716 // Allow all requests to move from the Create queue to the active entry. | |
1717 MessageLoop::current()->RunAllPending(); | |
1718 | |
1719 // The first request should be a writer at this point, and the subsequent | |
1720 // requests should be pending. | |
1721 | |
1722 EXPECT_EQ(1, cache.network_layer()->transaction_count()); | |
1723 EXPECT_EQ(0, cache.disk_cache()->open_count()); | |
1724 EXPECT_EQ(1, cache.disk_cache()->create_count()); | |
1725 | |
1726 // Now, make sure that the second request asks for the entry not to be stored. | |
1727 request_handler.set_no_store(true); | |
1728 | |
1729 for (int i = 0; i < kNumTransactions; ++i) { | |
1730 Context* c = context_list[i]; | |
1731 if (c->result == net::ERR_IO_PENDING) | |
1732 c->result = c->callback.WaitForResult(); | |
1733 ReadAndVerifyTransaction(c->trans.get(), kFastNoStoreGET_Transaction); | |
1734 delete c; | |
1735 } | |
1736 | |
1737 EXPECT_EQ(3, cache.network_layer()->transaction_count()); | |
1738 EXPECT_EQ(0, cache.disk_cache()->open_count()); | |
1739 EXPECT_EQ(2, cache.disk_cache()->create_count()); | |
1740 | |
1741 RemoveMockTransaction(&kFastNoStoreGET_Transaction); | |
1742 } | |
1743 | |
1744 TEST(HttpCache, SimpleGET_ManyWriters_CancelFirst) { | |
1745 MockHttpCache cache; | |
1746 | |
1747 MockHttpRequest request(kSimpleGET_Transaction); | |
1748 | |
1749 std::vector<Context*> context_list; | |
1750 const int kNumTransactions = 2; | |
1751 | |
1752 for (int i = 0; i < kNumTransactions; ++i) { | |
1753 context_list.push_back(new Context()); | |
1754 Context* c = context_list[i]; | |
1755 | |
1756 c->result = cache.http_cache()->CreateTransaction(&c->trans); | |
1757 EXPECT_EQ(net::OK, c->result); | |
1758 | |
1759 c->result = c->trans->Start(&request, &c->callback, net::BoundNetLog()); | |
1760 } | |
1761 | |
1762 // Allow all requests to move from the Create queue to the active entry. | |
1763 MessageLoop::current()->RunAllPending(); | |
1764 | |
1765 // The first request should be a writer at this point, and the subsequent | |
1766 // requests should be pending. | |
1767 | |
1768 EXPECT_EQ(1, cache.network_layer()->transaction_count()); | |
1769 EXPECT_EQ(0, cache.disk_cache()->open_count()); | |
1770 EXPECT_EQ(1, cache.disk_cache()->create_count()); | |
1771 | |
1772 for (int i = 0; i < kNumTransactions; ++i) { | |
1773 Context* c = context_list[i]; | |
1774 if (c->result == net::ERR_IO_PENDING) | |
1775 c->result = c->callback.WaitForResult(); | |
1776 // Destroy only the first transaction. | |
1777 if (i == 0) { | |
1778 delete c; | |
1779 context_list[i] = NULL; | |
1780 } | |
1781 } | |
1782 | |
1783 // Complete the rest of the transactions. | |
1784 for (int i = 1; i < kNumTransactions; ++i) { | |
1785 Context* c = context_list[i]; | |
1786 ReadAndVerifyTransaction(c->trans.get(), kSimpleGET_Transaction); | |
1787 } | |
1788 | |
1789 // We should have had to re-open the disk entry. | |
1790 | |
1791 EXPECT_EQ(2, cache.network_layer()->transaction_count()); | |
1792 EXPECT_EQ(0, cache.disk_cache()->open_count()); | |
1793 EXPECT_EQ(2, cache.disk_cache()->create_count()); | |
1794 | |
1795 for (int i = 1; i < kNumTransactions; ++i) { | |
1796 Context* c = context_list[i]; | |
1797 delete c; | |
1798 } | |
1799 } | |
1800 | |
1801 // Tests that we can cancel requests that are queued waiting to open the disk | |
1802 // cache entry. | |
1803 TEST(HttpCache, SimpleGET_ManyWriters_CancelCreate) { | |
1804 MockHttpCache cache; | |
1805 | |
1806 MockHttpRequest request(kSimpleGET_Transaction); | |
1807 | |
1808 std::vector<Context*> context_list; | |
1809 const int kNumTransactions = 5; | |
1810 | |
1811 for (int i = 0; i < kNumTransactions; i++) { | |
1812 context_list.push_back(new Context()); | |
1813 Context* c = context_list[i]; | |
1814 | |
1815 c->result = cache.http_cache()->CreateTransaction(&c->trans); | |
1816 EXPECT_EQ(net::OK, c->result); | |
1817 | |
1818 c->result = c->trans->Start(&request, &c->callback, net::BoundNetLog()); | |
1819 } | |
1820 | |
1821 // The first request should be creating the disk cache entry and the others | |
1822 // should be pending. | |
1823 | |
1824 EXPECT_EQ(0, cache.network_layer()->transaction_count()); | |
1825 EXPECT_EQ(0, cache.disk_cache()->open_count()); | |
1826 EXPECT_EQ(1, cache.disk_cache()->create_count()); | |
1827 | |
1828 // Cancel a request from the pending queue. | |
1829 delete context_list[3]; | |
1830 context_list[3] = NULL; | |
1831 | |
1832 // Cancel the request that is creating the entry. This will force the pending | |
1833 // operations to restart. | |
1834 delete context_list[0]; | |
1835 context_list[0] = NULL; | |
1836 | |
1837 // Complete the rest of the transactions. | |
1838 for (int i = 1; i < kNumTransactions; i++) { | |
1839 Context* c = context_list[i]; | |
1840 if (c) { | |
1841 c->result = c->callback.GetResult(c->result); | |
1842 ReadAndVerifyTransaction(c->trans.get(), kSimpleGET_Transaction); | |
1843 } | |
1844 } | |
1845 | |
1846 // We should have had to re-create the disk entry. | |
1847 | |
1848 EXPECT_EQ(1, cache.network_layer()->transaction_count()); | |
1849 EXPECT_EQ(0, cache.disk_cache()->open_count()); | |
1850 EXPECT_EQ(2, cache.disk_cache()->create_count()); | |
1851 | |
1852 for (int i = 1; i < kNumTransactions; ++i) { | |
1853 delete context_list[i]; | |
1854 } | |
1855 } | |
1856 | |
1857 // Tests that we can cancel a single request to open a disk cache entry. | |
1858 TEST(HttpCache, SimpleGET_CancelCreate) { | |
1859 MockHttpCache cache; | |
1860 | |
1861 MockHttpRequest request(kSimpleGET_Transaction); | |
1862 | |
1863 Context* c = new Context(); | |
1864 | |
1865 c->result = cache.http_cache()->CreateTransaction(&c->trans); | |
1866 EXPECT_EQ(net::OK, c->result); | |
1867 | |
1868 c->result = c->trans->Start(&request, &c->callback, net::BoundNetLog()); | |
1869 EXPECT_EQ(net::ERR_IO_PENDING, c->result); | |
1870 | |
1871 // Release the reference that the mock disk cache keeps for this entry, so | |
1872 // that we test that the http cache handles the cancelation correctly. | |
1873 cache.disk_cache()->ReleaseAll(); | |
1874 delete c; | |
1875 | |
1876 MessageLoop::current()->RunAllPending(); | |
1877 EXPECT_EQ(1, cache.disk_cache()->create_count()); | |
1878 } | |
1879 | |
1880 // Tests that we delete/create entries even if multiple requests are queued. | |
1881 TEST(HttpCache, SimpleGET_ManyWriters_BypassCache) { | |
1882 MockHttpCache cache; | |
1883 | |
1884 MockHttpRequest request(kSimpleGET_Transaction); | |
1885 request.load_flags = net::LOAD_BYPASS_CACHE; | |
1886 | |
1887 std::vector<Context*> context_list; | |
1888 const int kNumTransactions = 5; | |
1889 | |
1890 for (int i = 0; i < kNumTransactions; i++) { | |
1891 context_list.push_back(new Context()); | |
1892 Context* c = context_list[i]; | |
1893 | |
1894 c->result = cache.http_cache()->CreateTransaction(&c->trans); | |
1895 EXPECT_EQ(net::OK, c->result); | |
1896 | |
1897 c->result = c->trans->Start(&request, &c->callback, net::BoundNetLog()); | |
1898 } | |
1899 | |
1900 // The first request should be deleting the disk cache entry and the others | |
1901 // should be pending. | |
1902 | |
1903 EXPECT_EQ(0, cache.network_layer()->transaction_count()); | |
1904 EXPECT_EQ(0, cache.disk_cache()->open_count()); | |
1905 EXPECT_EQ(0, cache.disk_cache()->create_count()); | |
1906 | |
1907 // Complete the transactions. | |
1908 for (int i = 0; i < kNumTransactions; i++) { | |
1909 Context* c = context_list[i]; | |
1910 c->result = c->callback.GetResult(c->result); | |
1911 ReadAndVerifyTransaction(c->trans.get(), kSimpleGET_Transaction); | |
1912 } | |
1913 | |
1914 // We should have had to re-create the disk entry multiple times. | |
1915 | |
1916 EXPECT_EQ(5, cache.network_layer()->transaction_count()); | |
1917 EXPECT_EQ(0, cache.disk_cache()->open_count()); | |
1918 EXPECT_EQ(5, cache.disk_cache()->create_count()); | |
1919 | |
1920 for (int i = 0; i < kNumTransactions; ++i) { | |
1921 delete context_list[i]; | |
1922 } | |
1923 } | |
1924 | |
1925 TEST(HttpCache, SimpleGET_AbandonedCacheRead) { | |
1926 MockHttpCache cache; | |
1927 | |
1928 // write to the cache | |
1929 RunTransactionTest(cache.http_cache(), kSimpleGET_Transaction); | |
1930 | |
1931 MockHttpRequest request(kSimpleGET_Transaction); | |
1932 TestOldCompletionCallback callback; | |
1933 | |
1934 scoped_ptr<net::HttpTransaction> trans; | |
1935 int rv = cache.http_cache()->CreateTransaction(&trans); | |
1936 EXPECT_EQ(net::OK, rv); | |
1937 rv = trans->Start(&request, &callback, net::BoundNetLog()); | |
1938 if (rv == net::ERR_IO_PENDING) | |
1939 rv = callback.WaitForResult(); | |
1940 ASSERT_EQ(net::OK, rv); | |
1941 | |
1942 scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(256)); | |
1943 rv = trans->Read(buf, 256, &callback); | |
1944 EXPECT_EQ(net::ERR_IO_PENDING, rv); | |
1945 | |
1946 // Test that destroying the transaction while it is reading from the cache | |
1947 // works properly. | |
1948 trans.reset(); | |
1949 | |
1950 // Make sure we pump any pending events, which should include a call to | |
1951 // HttpCache::Transaction::OnCacheReadCompleted. | |
1952 MessageLoop::current()->RunAllPending(); | |
1953 } | |
1954 | |
1955 // Tests that we can delete the HttpCache and deal with queued transactions | |
1956 // ("waiting for the backend" as opposed to Active or Doomed entries). | |
1957 TEST(HttpCache, SimpleGET_ManyWriters_DeleteCache) { | |
1958 scoped_ptr<MockHttpCache> cache(new MockHttpCache( | |
1959 new MockBackendNoCbFactory())); | |
1960 | |
1961 MockHttpRequest request(kSimpleGET_Transaction); | |
1962 | |
1963 std::vector<Context*> context_list; | |
1964 const int kNumTransactions = 5; | |
1965 | |
1966 for (int i = 0; i < kNumTransactions; i++) { | |
1967 context_list.push_back(new Context()); | |
1968 Context* c = context_list[i]; | |
1969 | |
1970 c->result = cache->http_cache()->CreateTransaction(&c->trans); | |
1971 EXPECT_EQ(net::OK, c->result); | |
1972 | |
1973 c->result = c->trans->Start(&request, &c->callback, net::BoundNetLog()); | |
1974 } | |
1975 | |
1976 // The first request should be creating the disk cache entry and the others | |
1977 // should be pending. | |
1978 | |
1979 EXPECT_EQ(0, cache->network_layer()->transaction_count()); | |
1980 EXPECT_EQ(0, cache->disk_cache()->open_count()); | |
1981 EXPECT_EQ(0, cache->disk_cache()->create_count()); | |
1982 | |
1983 cache.reset(); | |
1984 | |
1985 // There is not much to do with the transactions at this point... they are | |
1986 // waiting for a callback that will not fire. | |
1987 for (int i = 0; i < kNumTransactions; ++i) { | |
1988 delete context_list[i]; | |
1989 } | |
1990 } | |
1991 | |
1992 // Tests that we queue requests when initializing the backend. | |
1993 TEST(HttpCache, SimpleGET_WaitForBackend) { | |
1994 MockBlockingBackendFactory* factory = new MockBlockingBackendFactory(); | |
1995 MockHttpCache cache(factory); | |
1996 | |
1997 MockHttpRequest request0(kSimpleGET_Transaction); | |
1998 MockHttpRequest request1(kTypicalGET_Transaction); | |
1999 MockHttpRequest request2(kETagGET_Transaction); | |
2000 | |
2001 std::vector<Context*> context_list; | |
2002 const int kNumTransactions = 3; | |
2003 | |
2004 for (int i = 0; i < kNumTransactions; i++) { | |
2005 context_list.push_back(new Context()); | |
2006 Context* c = context_list[i]; | |
2007 | |
2008 c->result = cache.http_cache()->CreateTransaction(&c->trans); | |
2009 EXPECT_EQ(net::OK, c->result); | |
2010 } | |
2011 | |
2012 context_list[0]->result = context_list[0]->trans->Start( | |
2013 &request0, &context_list[0]->callback, net::BoundNetLog()); | |
2014 context_list[1]->result = context_list[1]->trans->Start( | |
2015 &request1, &context_list[1]->callback, net::BoundNetLog()); | |
2016 context_list[2]->result = context_list[2]->trans->Start( | |
2017 &request2, &context_list[2]->callback, net::BoundNetLog()); | |
2018 | |
2019 // Just to make sure that everything is still pending. | |
2020 MessageLoop::current()->RunAllPending(); | |
2021 | |
2022 // The first request should be creating the disk cache. | |
2023 EXPECT_FALSE(context_list[0]->callback.have_result()); | |
2024 | |
2025 factory->FinishCreation(); | |
2026 | |
2027 MessageLoop::current()->RunAllPending(); | |
2028 EXPECT_EQ(3, cache.network_layer()->transaction_count()); | |
2029 EXPECT_EQ(3, cache.disk_cache()->create_count()); | |
2030 | |
2031 for (int i = 0; i < kNumTransactions; ++i) { | |
2032 EXPECT_TRUE(context_list[i]->callback.have_result()); | |
2033 delete context_list[i]; | |
2034 } | |
2035 } | |
2036 | |
2037 // Tests that we can cancel requests that are queued waiting for the backend | |
2038 // to be initialized. | |
2039 TEST(HttpCache, SimpleGET_WaitForBackend_CancelCreate) { | |
2040 MockBlockingBackendFactory* factory = new MockBlockingBackendFactory(); | |
2041 MockHttpCache cache(factory); | |
2042 | |
2043 MockHttpRequest request0(kSimpleGET_Transaction); | |
2044 MockHttpRequest request1(kTypicalGET_Transaction); | |
2045 MockHttpRequest request2(kETagGET_Transaction); | |
2046 | |
2047 std::vector<Context*> context_list; | |
2048 const int kNumTransactions = 3; | |
2049 | |
2050 for (int i = 0; i < kNumTransactions; i++) { | |
2051 context_list.push_back(new Context()); | |
2052 Context* c = context_list[i]; | |
2053 | |
2054 c->result = cache.http_cache()->CreateTransaction(&c->trans); | |
2055 EXPECT_EQ(net::OK, c->result); | |
2056 } | |
2057 | |
2058 context_list[0]->result = context_list[0]->trans->Start( | |
2059 &request0, &context_list[0]->callback, net::BoundNetLog()); | |
2060 context_list[1]->result = context_list[1]->trans->Start( | |
2061 &request1, &context_list[1]->callback, net::BoundNetLog()); | |
2062 context_list[2]->result = context_list[2]->trans->Start( | |
2063 &request2, &context_list[2]->callback, net::BoundNetLog()); | |
2064 | |
2065 // Just to make sure that everything is still pending. | |
2066 MessageLoop::current()->RunAllPending(); | |
2067 | |
2068 // The first request should be creating the disk cache. | |
2069 EXPECT_FALSE(context_list[0]->callback.have_result()); | |
2070 | |
2071 // Cancel a request from the pending queue. | |
2072 delete context_list[1]; | |
2073 context_list[1] = NULL; | |
2074 | |
2075 // Cancel the request that is creating the entry. | |
2076 delete context_list[0]; | |
2077 context_list[0] = NULL; | |
2078 | |
2079 // Complete the last transaction. | |
2080 factory->FinishCreation(); | |
2081 | |
2082 context_list[2]->result = | |
2083 context_list[2]->callback.GetResult(context_list[2]->result); | |
2084 ReadAndVerifyTransaction(context_list[2]->trans.get(), kETagGET_Transaction); | |
2085 | |
2086 EXPECT_EQ(1, cache.network_layer()->transaction_count()); | |
2087 EXPECT_EQ(1, cache.disk_cache()->create_count()); | |
2088 | |
2089 delete context_list[2]; | |
2090 } | |
2091 | |
2092 // Tests that we can delete the cache while creating the backend. | |
2093 TEST(HttpCache, DeleteCacheWaitingForBackend) { | |
2094 MockBlockingBackendFactory* factory = new MockBlockingBackendFactory(); | |
2095 scoped_ptr<MockHttpCache> cache(new MockHttpCache(factory)); | |
2096 | |
2097 MockHttpRequest request(kSimpleGET_Transaction); | |
2098 | |
2099 scoped_ptr<Context> c(new Context()); | |
2100 c->result = cache->http_cache()->CreateTransaction(&c->trans); | |
2101 EXPECT_EQ(net::OK, c->result); | |
2102 | |
2103 c->trans->Start(&request, &c->callback, net::BoundNetLog()); | |
2104 | |
2105 // Just to make sure that everything is still pending. | |
2106 MessageLoop::current()->RunAllPending(); | |
2107 | |
2108 // The request should be creating the disk cache. | |
2109 EXPECT_FALSE(c->callback.have_result()); | |
2110 | |
2111 // We cannot call FinishCreation because the factory itself will go away with | |
2112 // the cache, so grab the callback and attempt to use it. | |
2113 net::OldCompletionCallback* callback = factory->callback(); | |
2114 disk_cache::Backend** backend = factory->backend(); | |
2115 | |
2116 cache.reset(); | |
2117 MessageLoop::current()->RunAllPending(); | |
2118 | |
2119 *backend = NULL; | |
2120 callback->Run(net::ERR_ABORTED); | |
2121 } | |
2122 | |
2123 // Tests that we can delete the cache while creating the backend, from within | |
2124 // one of the callbacks. | |
2125 TEST(HttpCache, DeleteCacheWaitingForBackend2) { | |
2126 MockBlockingBackendFactory* factory = new MockBlockingBackendFactory(); | |
2127 MockHttpCache* cache = new MockHttpCache(factory); | |
2128 | |
2129 DeleteCacheOldCompletionCallback cb(cache); | |
2130 disk_cache::Backend* backend; | |
2131 int rv = cache->http_cache()->GetBackend(&backend, &cb); | |
2132 EXPECT_EQ(net::ERR_IO_PENDING, rv); | |
2133 | |
2134 // Now let's queue a regular transaction | |
2135 MockHttpRequest request(kSimpleGET_Transaction); | |
2136 | |
2137 scoped_ptr<Context> c(new Context()); | |
2138 c->result = cache->http_cache()->CreateTransaction(&c->trans); | |
2139 EXPECT_EQ(net::OK, c->result); | |
2140 | |
2141 c->trans->Start(&request, &c->callback, net::BoundNetLog()); | |
2142 | |
2143 // And another direct backend request. | |
2144 TestOldCompletionCallback cb2; | |
2145 rv = cache->http_cache()->GetBackend(&backend, &cb2); | |
2146 EXPECT_EQ(net::ERR_IO_PENDING, rv); | |
2147 | |
2148 // Just to make sure that everything is still pending. | |
2149 MessageLoop::current()->RunAllPending(); | |
2150 | |
2151 // The request should be queued. | |
2152 EXPECT_FALSE(c->callback.have_result()); | |
2153 | |
2154 // Generate the callback. | |
2155 factory->FinishCreation(); | |
2156 rv = cb.WaitForResult(); | |
2157 | |
2158 // The cache should be gone by now. | |
2159 MessageLoop::current()->RunAllPending(); | |
2160 EXPECT_EQ(net::OK, c->callback.GetResult(c->result)); | |
2161 EXPECT_FALSE(cb2.have_result()); | |
2162 } | |
2163 | |
2164 TEST(HttpCache, TypicalGET_ConditionalRequest) { | |
2165 MockHttpCache cache; | |
2166 | |
2167 // write to the cache | |
2168 RunTransactionTest(cache.http_cache(), kTypicalGET_Transaction); | |
2169 | |
2170 EXPECT_EQ(1, cache.network_layer()->transaction_count()); | |
2171 EXPECT_EQ(0, cache.disk_cache()->open_count()); | |
2172 EXPECT_EQ(1, cache.disk_cache()->create_count()); | |
2173 | |
2174 // get the same URL again, but this time we expect it to result | |
2175 // in a conditional request. | |
2176 RunTransactionTest(cache.http_cache(), kTypicalGET_Transaction); | |
2177 | |
2178 EXPECT_EQ(2, cache.network_layer()->transaction_count()); | |
2179 EXPECT_EQ(1, cache.disk_cache()->open_count()); | |
2180 EXPECT_EQ(1, cache.disk_cache()->create_count()); | |
2181 } | |
2182 | |
2183 static void ETagGet_ConditionalRequest_Handler( | |
2184 const net::HttpRequestInfo* request, | |
2185 std::string* response_status, | |
2186 std::string* response_headers, | |
2187 std::string* response_data) { | |
2188 EXPECT_TRUE( | |
2189 request->extra_headers.HasHeader(net::HttpRequestHeaders::kIfNoneMatch)); | |
2190 response_status->assign("HTTP/1.1 304 Not Modified"); | |
2191 response_headers->assign(kETagGET_Transaction.response_headers); | |
2192 response_data->clear(); | |
2193 } | |
2194 | |
2195 TEST(HttpCache, ETagGET_ConditionalRequest_304) { | |
2196 MockHttpCache cache; | |
2197 | |
2198 ScopedMockTransaction transaction(kETagGET_Transaction); | |
2199 | |
2200 // write to the cache | |
2201 RunTransactionTest(cache.http_cache(), transaction); | |
2202 | |
2203 EXPECT_EQ(1, cache.network_layer()->transaction_count()); | |
2204 EXPECT_EQ(0, cache.disk_cache()->open_count()); | |
2205 EXPECT_EQ(1, cache.disk_cache()->create_count()); | |
2206 | |
2207 // get the same URL again, but this time we expect it to result | |
2208 // in a conditional request. | |
2209 transaction.load_flags = net::LOAD_VALIDATE_CACHE; | |
2210 transaction.handler = ETagGet_ConditionalRequest_Handler; | |
2211 RunTransactionTest(cache.http_cache(), transaction); | |
2212 | |
2213 EXPECT_EQ(2, cache.network_layer()->transaction_count()); | |
2214 EXPECT_EQ(1, cache.disk_cache()->open_count()); | |
2215 EXPECT_EQ(1, cache.disk_cache()->create_count()); | |
2216 } | |
2217 | |
2218 static void ETagGet_UnconditionalRequest_Handler( | |
2219 const net::HttpRequestInfo* request, | |
2220 std::string* response_status, | |
2221 std::string* response_headers, | |
2222 std::string* response_data) { | |
2223 EXPECT_FALSE( | |
2224 request->extra_headers.HasHeader(net::HttpRequestHeaders::kIfNoneMatch)); | |
2225 } | |
2226 | |
2227 TEST(HttpCache, ETagGET_Http10) { | |
2228 MockHttpCache cache; | |
2229 | |
2230 ScopedMockTransaction transaction(kETagGET_Transaction); | |
2231 transaction.status = "HTTP/1.0 200 OK"; | |
2232 | |
2233 // Write to the cache. | |
2234 RunTransactionTest(cache.http_cache(), transaction); | |
2235 | |
2236 EXPECT_EQ(1, cache.network_layer()->transaction_count()); | |
2237 EXPECT_EQ(0, cache.disk_cache()->open_count()); | |
2238 EXPECT_EQ(1, cache.disk_cache()->create_count()); | |
2239 | |
2240 // Get the same URL again, without generating a conditional request. | |
2241 transaction.load_flags = net::LOAD_VALIDATE_CACHE; | |
2242 transaction.handler = ETagGet_UnconditionalRequest_Handler; | |
2243 RunTransactionTest(cache.http_cache(), transaction); | |
2244 | |
2245 EXPECT_EQ(2, cache.network_layer()->transaction_count()); | |
2246 EXPECT_EQ(1, cache.disk_cache()->open_count()); | |
2247 EXPECT_EQ(1, cache.disk_cache()->create_count()); | |
2248 } | |
2249 | |
2250 TEST(HttpCache, ETagGET_Http10_Range) { | |
2251 MockHttpCache cache; | |
2252 | |
2253 ScopedMockTransaction transaction(kETagGET_Transaction); | |
2254 transaction.status = "HTTP/1.0 200 OK"; | |
2255 | |
2256 // Write to the cache. | |
2257 RunTransactionTest(cache.http_cache(), transaction); | |
2258 | |
2259 EXPECT_EQ(1, cache.network_layer()->transaction_count()); | |
2260 EXPECT_EQ(0, cache.disk_cache()->open_count()); | |
2261 EXPECT_EQ(1, cache.disk_cache()->create_count()); | |
2262 | |
2263 // Get the same URL again, but use a byte range request. | |
2264 transaction.load_flags = net::LOAD_VALIDATE_CACHE; | |
2265 transaction.handler = ETagGet_UnconditionalRequest_Handler; | |
2266 transaction.request_headers = "Range: bytes = 5-"; | |
2267 RunTransactionTest(cache.http_cache(), transaction); | |
2268 | |
2269 EXPECT_EQ(2, cache.network_layer()->transaction_count()); | |
2270 EXPECT_EQ(1, cache.disk_cache()->open_count()); | |
2271 EXPECT_EQ(2, cache.disk_cache()->create_count()); | |
2272 } | |
2273 | |
2274 static void ETagGet_ConditionalRequest_NoStore_Handler( | |
2275 const net::HttpRequestInfo* request, | |
2276 std::string* response_status, | |
2277 std::string* response_headers, | |
2278 std::string* response_data) { | |
2279 EXPECT_TRUE( | |
2280 request->extra_headers.HasHeader(net::HttpRequestHeaders::kIfNoneMatch)); | |
2281 response_status->assign("HTTP/1.1 304 Not Modified"); | |
2282 response_headers->assign("Cache-Control: no-store\n"); | |
2283 response_data->clear(); | |
2284 } | |
2285 | |
2286 TEST(HttpCache, ETagGET_ConditionalRequest_304_NoStore) { | |
2287 MockHttpCache cache; | |
2288 | |
2289 ScopedMockTransaction transaction(kETagGET_Transaction); | |
2290 | |
2291 // Write to the cache. | |
2292 RunTransactionTest(cache.http_cache(), transaction); | |
2293 | |
2294 EXPECT_EQ(1, cache.network_layer()->transaction_count()); | |
2295 EXPECT_EQ(0, cache.disk_cache()->open_count()); | |
2296 EXPECT_EQ(1, cache.disk_cache()->create_count()); | |
2297 | |
2298 // Get the same URL again, but this time we expect it to result | |
2299 // in a conditional request. | |
2300 transaction.load_flags = net::LOAD_VALIDATE_CACHE; | |
2301 transaction.handler = ETagGet_ConditionalRequest_NoStore_Handler; | |
2302 RunTransactionTest(cache.http_cache(), transaction); | |
2303 | |
2304 EXPECT_EQ(2, cache.network_layer()->transaction_count()); | |
2305 EXPECT_EQ(1, cache.disk_cache()->open_count()); | |
2306 EXPECT_EQ(1, cache.disk_cache()->create_count()); | |
2307 | |
2308 ScopedMockTransaction transaction2(kETagGET_Transaction); | |
2309 | |
2310 // Write to the cache again. This should create a new entry. | |
2311 RunTransactionTest(cache.http_cache(), transaction2); | |
2312 | |
2313 EXPECT_EQ(3, cache.network_layer()->transaction_count()); | |
2314 EXPECT_EQ(1, cache.disk_cache()->open_count()); | |
2315 EXPECT_EQ(2, cache.disk_cache()->create_count()); | |
2316 } | |
2317 | |
2318 TEST(HttpCache, SimplePOST_SkipsCache) { | |
2319 MockHttpCache cache; | |
2320 | |
2321 // Test that we skip the cache for POST requests that do not have an upload | |
2322 // identifier. | |
2323 | |
2324 RunTransactionTest(cache.http_cache(), kSimplePOST_Transaction); | |
2325 | |
2326 EXPECT_EQ(1, cache.network_layer()->transaction_count()); | |
2327 EXPECT_EQ(0, cache.disk_cache()->open_count()); | |
2328 EXPECT_EQ(0, cache.disk_cache()->create_count()); | |
2329 } | |
2330 | |
2331 // Helper that does 4 requests using HttpCache: | |
2332 // | |
2333 // (1) loads |kUrl| -- expects |net_response_1| to be returned. | |
2334 // (2) loads |kUrl| from cache only -- expects |net_response_1| to be returned. | |
2335 // (3) loads |kUrl| using |extra_request_headers| -- expects |net_response_2| to | |
2336 // be returned. | |
2337 // (4) loads |kUrl| from cache only -- expects |cached_response_2| to be | |
2338 // returned. | |
2339 static void ConditionalizedRequestUpdatesCacheHelper( | |
2340 const Response& net_response_1, | |
2341 const Response& net_response_2, | |
2342 const Response& cached_response_2, | |
2343 const char* extra_request_headers) { | |
2344 MockHttpCache cache; | |
2345 | |
2346 // The URL we will be requesting. | |
2347 const char* kUrl = "http://foobar.com/main.css"; | |
2348 | |
2349 // Junk network response. | |
2350 static const Response kUnexpectedResponse = { | |
2351 "HTTP/1.1 500 Unexpected", | |
2352 "Server: unexpected_header", | |
2353 "unexpected body" | |
2354 }; | |
2355 | |
2356 // We will control the network layer's responses for |kUrl| using | |
2357 // |mock_network_response|. | |
2358 MockTransaction mock_network_response = { 0 }; | |
2359 mock_network_response.url = kUrl; | |
2360 AddMockTransaction(&mock_network_response); | |
2361 | |
2362 // Request |kUrl| for the first time. It should hit the network and | |
2363 // receive |kNetResponse1|, which it saves into the HTTP cache. | |
2364 | |
2365 MockTransaction request = { 0 }; | |
2366 request.url = kUrl; | |
2367 request.method = "GET"; | |
2368 request.request_headers = ""; | |
2369 | |
2370 net_response_1.AssignTo(&mock_network_response); // Network mock. | |
2371 net_response_1.AssignTo(&request); // Expected result. | |
2372 | |
2373 std::string response_headers; | |
2374 RunTransactionTestWithResponse( | |
2375 cache.http_cache(), request, &response_headers); | |
2376 | |
2377 EXPECT_EQ(net_response_1.status_and_headers(), response_headers); | |
2378 EXPECT_EQ(1, cache.network_layer()->transaction_count()); | |
2379 EXPECT_EQ(0, cache.disk_cache()->open_count()); | |
2380 EXPECT_EQ(1, cache.disk_cache()->create_count()); | |
2381 | |
2382 // Request |kUrl| a second time. Now |kNetResponse1| it is in the HTTP | |
2383 // cache, so we don't hit the network. | |
2384 | |
2385 request.load_flags = net::LOAD_ONLY_FROM_CACHE; | |
2386 | |
2387 kUnexpectedResponse.AssignTo(&mock_network_response); // Network mock. | |
2388 net_response_1.AssignTo(&request); // Expected result. | |
2389 | |
2390 RunTransactionTestWithResponse( | |
2391 cache.http_cache(), request, &response_headers); | |
2392 | |
2393 EXPECT_EQ(net_response_1.status_and_headers(), response_headers); | |
2394 EXPECT_EQ(1, cache.network_layer()->transaction_count()); | |
2395 EXPECT_EQ(1, cache.disk_cache()->open_count()); | |
2396 EXPECT_EQ(1, cache.disk_cache()->create_count()); | |
2397 | |
2398 // Request |kUrl| yet again, but this time give the request an | |
2399 // "If-Modified-Since" header. This will cause the request to re-hit the | |
2400 // network. However now the network response is going to be | |
2401 // different -- this simulates a change made to the CSS file. | |
2402 | |
2403 request.request_headers = extra_request_headers; | |
2404 request.load_flags = net::LOAD_NORMAL; | |
2405 | |
2406 net_response_2.AssignTo(&mock_network_response); // Network mock. | |
2407 net_response_2.AssignTo(&request); // Expected result. | |
2408 | |
2409 RunTransactionTestWithResponse( | |
2410 cache.http_cache(), request, &response_headers); | |
2411 | |
2412 EXPECT_EQ(net_response_2.status_and_headers(), response_headers); | |
2413 EXPECT_EQ(2, cache.network_layer()->transaction_count()); | |
2414 EXPECT_EQ(1, cache.disk_cache()->open_count()); | |
2415 EXPECT_EQ(1, cache.disk_cache()->create_count()); | |
2416 | |
2417 // Finally, request |kUrl| again. This request should be serviced from | |
2418 // the cache. Moreover, the value in the cache should be |kNetResponse2| | |
2419 // and NOT |kNetResponse1|. The previous step should have replaced the | |
2420 // value in the cache with the modified response. | |
2421 | |
2422 request.request_headers = ""; | |
2423 request.load_flags = net::LOAD_ONLY_FROM_CACHE; | |
2424 | |
2425 kUnexpectedResponse.AssignTo(&mock_network_response); // Network mock. | |
2426 cached_response_2.AssignTo(&request); // Expected result. | |
2427 | |
2428 RunTransactionTestWithResponse( | |
2429 cache.http_cache(), request, &response_headers); | |
2430 | |
2431 EXPECT_EQ(cached_response_2.status_and_headers(), response_headers); | |
2432 EXPECT_EQ(2, cache.network_layer()->transaction_count()); | |
2433 EXPECT_EQ(2, cache.disk_cache()->open_count()); | |
2434 EXPECT_EQ(1, cache.disk_cache()->create_count()); | |
2435 | |
2436 RemoveMockTransaction(&mock_network_response); | |
2437 } | |
2438 | |
2439 // Check that when an "if-modified-since" header is attached | |
2440 // to the request, the result still updates the cached entry. | |
2441 TEST(HttpCache, ConditionalizedRequestUpdatesCache1) { | |
2442 // First network response for |kUrl|. | |
2443 static const Response kNetResponse1 = { | |
2444 "HTTP/1.1 200 OK", | |
2445 "Date: Fri, 12 Jun 2009 21:46:42 GMT\n" | |
2446 "Last-Modified: Wed, 06 Feb 2008 22:38:21 GMT\n", | |
2447 "body1" | |
2448 }; | |
2449 | |
2450 // Second network response for |kUrl|. | |
2451 static const Response kNetResponse2 = { | |
2452 "HTTP/1.1 200 OK", | |
2453 "Date: Wed, 22 Jul 2009 03:15:26 GMT\n" | |
2454 "Last-Modified: Fri, 03 Jul 2009 02:14:27 GMT\n", | |
2455 "body2" | |
2456 }; | |
2457 | |
2458 const char* extra_headers = | |
2459 "If-Modified-Since: Wed, 06 Feb 2008 22:38:21 GMT\n"; | |
2460 | |
2461 ConditionalizedRequestUpdatesCacheHelper( | |
2462 kNetResponse1, kNetResponse2, kNetResponse2, extra_headers); | |
2463 } | |
2464 | |
2465 // Check that when an "if-none-match" header is attached | |
2466 // to the request, the result updates the cached entry. | |
2467 TEST(HttpCache, ConditionalizedRequestUpdatesCache2) { | |
2468 // First network response for |kUrl|. | |
2469 static const Response kNetResponse1 = { | |
2470 "HTTP/1.1 200 OK", | |
2471 "Date: Fri, 12 Jun 2009 21:46:42 GMT\n" | |
2472 "Etag: \"ETAG1\"\n" | |
2473 "Expires: Wed, 7 Sep 2033 21:46:42 GMT\n", // Should never expire. | |
2474 "body1" | |
2475 }; | |
2476 | |
2477 // Second network response for |kUrl|. | |
2478 static const Response kNetResponse2 = { | |
2479 "HTTP/1.1 200 OK", | |
2480 "Date: Wed, 22 Jul 2009 03:15:26 GMT\n" | |
2481 "Etag: \"ETAG2\"\n" | |
2482 "Expires: Wed, 7 Sep 2033 21:46:42 GMT\n", // Should never expire. | |
2483 "body2" | |
2484 }; | |
2485 | |
2486 const char* extra_headers = "If-None-Match: \"ETAG1\"\n"; | |
2487 | |
2488 ConditionalizedRequestUpdatesCacheHelper( | |
2489 kNetResponse1, kNetResponse2, kNetResponse2, extra_headers); | |
2490 } | |
2491 | |
2492 // Check that when an "if-modified-since" header is attached | |
2493 // to a request, the 304 (not modified result) result updates the cached | |
2494 // headers, and the 304 response is returned rather than the cached response. | |
2495 TEST(HttpCache, ConditionalizedRequestUpdatesCache3) { | |
2496 // First network response for |kUrl|. | |
2497 static const Response kNetResponse1 = { | |
2498 "HTTP/1.1 200 OK", | |
2499 "Date: Fri, 12 Jun 2009 21:46:42 GMT\n" | |
2500 "Server: server1\n" | |
2501 "Last-Modified: Wed, 06 Feb 2008 22:38:21 GMT\n", | |
2502 "body1" | |
2503 }; | |
2504 | |
2505 // Second network response for |kUrl|. | |
2506 static const Response kNetResponse2 = { | |
2507 "HTTP/1.1 304 Not Modified", | |
2508 "Date: Wed, 22 Jul 2009 03:15:26 GMT\n" | |
2509 "Server: server2\n" | |
2510 "Last-Modified: Wed, 06 Feb 2008 22:38:21 GMT\n", | |
2511 "" | |
2512 }; | |
2513 | |
2514 static const Response kCachedResponse2 = { | |
2515 "HTTP/1.1 200 OK", | |
2516 "Date: Wed, 22 Jul 2009 03:15:26 GMT\n" | |
2517 "Server: server2\n" | |
2518 "Last-Modified: Wed, 06 Feb 2008 22:38:21 GMT\n", | |
2519 "body1" | |
2520 }; | |
2521 | |
2522 const char* extra_headers = | |
2523 "If-Modified-Since: Wed, 06 Feb 2008 22:38:21 GMT\n"; | |
2524 | |
2525 ConditionalizedRequestUpdatesCacheHelper( | |
2526 kNetResponse1, kNetResponse2, kCachedResponse2, extra_headers); | |
2527 } | |
2528 | |
2529 // Test that when doing an externally conditionalized if-modified-since | |
2530 // and there is no corresponding cache entry, a new cache entry is NOT | |
2531 // created (304 response). | |
2532 TEST(HttpCache, ConditionalizedRequestUpdatesCache4) { | |
2533 MockHttpCache cache; | |
2534 | |
2535 const char* kUrl = "http://foobar.com/main.css"; | |
2536 | |
2537 static const Response kNetResponse = { | |
2538 "HTTP/1.1 304 Not Modified", | |
2539 "Date: Wed, 22 Jul 2009 03:15:26 GMT\n" | |
2540 "Last-Modified: Wed, 06 Feb 2008 22:38:21 GMT\n", | |
2541 "" | |
2542 }; | |
2543 | |
2544 const char* kExtraRequestHeaders = | |
2545 "If-Modified-Since: Wed, 06 Feb 2008 22:38:21 GMT"; | |
2546 | |
2547 // We will control the network layer's responses for |kUrl| using | |
2548 // |mock_network_response|. | |
2549 MockTransaction mock_network_response = { 0 }; | |
2550 mock_network_response.url = kUrl; | |
2551 AddMockTransaction(&mock_network_response); | |
2552 | |
2553 MockTransaction request = { 0 }; | |
2554 request.url = kUrl; | |
2555 request.method = "GET"; | |
2556 request.request_headers = kExtraRequestHeaders; | |
2557 | |
2558 kNetResponse.AssignTo(&mock_network_response); // Network mock. | |
2559 kNetResponse.AssignTo(&request); // Expected result. | |
2560 | |
2561 std::string response_headers; | |
2562 RunTransactionTestWithResponse( | |
2563 cache.http_cache(), request, &response_headers); | |
2564 | |
2565 EXPECT_EQ(kNetResponse.status_and_headers(), response_headers); | |
2566 EXPECT_EQ(1, cache.network_layer()->transaction_count()); | |
2567 EXPECT_EQ(0, cache.disk_cache()->open_count()); | |
2568 EXPECT_EQ(0, cache.disk_cache()->create_count()); | |
2569 | |
2570 RemoveMockTransaction(&mock_network_response); | |
2571 } | |
2572 | |
2573 // Test that when doing an externally conditionalized if-modified-since | |
2574 // and there is no corresponding cache entry, a new cache entry is NOT | |
2575 // created (200 response). | |
2576 TEST(HttpCache, ConditionalizedRequestUpdatesCache5) { | |
2577 MockHttpCache cache; | |
2578 | |
2579 const char* kUrl = "http://foobar.com/main.css"; | |
2580 | |
2581 static const Response kNetResponse = { | |
2582 "HTTP/1.1 200 OK", | |
2583 "Date: Wed, 22 Jul 2009 03:15:26 GMT\n" | |
2584 "Last-Modified: Wed, 06 Feb 2008 22:38:21 GMT\n", | |
2585 "foobar!!!" | |
2586 }; | |
2587 | |
2588 const char* kExtraRequestHeaders = | |
2589 "If-Modified-Since: Wed, 06 Feb 2008 22:38:21 GMT"; | |
2590 | |
2591 // We will control the network layer's responses for |kUrl| using | |
2592 // |mock_network_response|. | |
2593 MockTransaction mock_network_response = { 0 }; | |
2594 mock_network_response.url = kUrl; | |
2595 AddMockTransaction(&mock_network_response); | |
2596 | |
2597 MockTransaction request = { 0 }; | |
2598 request.url = kUrl; | |
2599 request.method = "GET"; | |
2600 request.request_headers = kExtraRequestHeaders; | |
2601 | |
2602 kNetResponse.AssignTo(&mock_network_response); // Network mock. | |
2603 kNetResponse.AssignTo(&request); // Expected result. | |
2604 | |
2605 std::string response_headers; | |
2606 RunTransactionTestWithResponse( | |
2607 cache.http_cache(), request, &response_headers); | |
2608 | |
2609 EXPECT_EQ(kNetResponse.status_and_headers(), response_headers); | |
2610 EXPECT_EQ(1, cache.network_layer()->transaction_count()); | |
2611 EXPECT_EQ(0, cache.disk_cache()->open_count()); | |
2612 EXPECT_EQ(0, cache.disk_cache()->create_count()); | |
2613 | |
2614 RemoveMockTransaction(&mock_network_response); | |
2615 } | |
2616 | |
2617 // Test that when doing an externally conditionalized if-modified-since | |
2618 // if the date does not match the cache entry's last-modified date, | |
2619 // then we do NOT use the response (304) to update the cache. | |
2620 // (the if-modified-since date is 2 days AFTER the cache's modification date). | |
2621 TEST(HttpCache, ConditionalizedRequestUpdatesCache6) { | |
2622 static const Response kNetResponse1 = { | |
2623 "HTTP/1.1 200 OK", | |
2624 "Date: Fri, 12 Jun 2009 21:46:42 GMT\n" | |
2625 "Server: server1\n" | |
2626 "Last-Modified: Wed, 06 Feb 2008 22:38:21 GMT\n", | |
2627 "body1" | |
2628 }; | |
2629 | |
2630 // Second network response for |kUrl|. | |
2631 static const Response kNetResponse2 = { | |
2632 "HTTP/1.1 304 Not Modified", | |
2633 "Date: Wed, 22 Jul 2009 03:15:26 GMT\n" | |
2634 "Server: server2\n" | |
2635 "Last-Modified: Wed, 06 Feb 2008 22:38:21 GMT\n", | |
2636 "" | |
2637 }; | |
2638 | |
2639 // This is two days in the future from the original response's last-modified | |
2640 // date! | |
2641 const char* kExtraRequestHeaders = | |
2642 "If-Modified-Since: Fri, 08 Feb 2008 22:38:21 GMT\n"; | |
2643 | |
2644 ConditionalizedRequestUpdatesCacheHelper( | |
2645 kNetResponse1, kNetResponse2, kNetResponse1, kExtraRequestHeaders); | |
2646 } | |
2647 | |
2648 // Test that when doing an externally conditionalized if-none-match | |
2649 // if the etag does not match the cache entry's etag, then we do not use the | |
2650 // response (304) to update the cache. | |
2651 TEST(HttpCache, ConditionalizedRequestUpdatesCache7) { | |
2652 static const Response kNetResponse1 = { | |
2653 "HTTP/1.1 200 OK", | |
2654 "Date: Fri, 12 Jun 2009 21:46:42 GMT\n" | |
2655 "Etag: \"Foo1\"\n" | |
2656 "Last-Modified: Wed, 06 Feb 2008 22:38:21 GMT\n", | |
2657 "body1" | |
2658 }; | |
2659 | |
2660 // Second network response for |kUrl|. | |
2661 static const Response kNetResponse2 = { | |
2662 "HTTP/1.1 304 Not Modified", | |
2663 "Date: Wed, 22 Jul 2009 03:15:26 GMT\n" | |
2664 "Etag: \"Foo2\"\n" | |
2665 "Last-Modified: Wed, 06 Feb 2008 22:38:21 GMT\n", | |
2666 "" | |
2667 }; | |
2668 | |
2669 // Different etag from original response. | |
2670 const char* kExtraRequestHeaders = "If-None-Match: \"Foo2\"\n"; | |
2671 | |
2672 ConditionalizedRequestUpdatesCacheHelper( | |
2673 kNetResponse1, kNetResponse2, kNetResponse1, kExtraRequestHeaders); | |
2674 } | |
2675 | |
2676 // Test that doing an externally conditionalized request with both if-none-match | |
2677 // and if-modified-since updates the cache. | |
2678 TEST(HttpCache, ConditionalizedRequestUpdatesCache8) { | |
2679 static const Response kNetResponse1 = { | |
2680 "HTTP/1.1 200 OK", | |
2681 "Date: Fri, 12 Jun 2009 21:46:42 GMT\n" | |
2682 "Etag: \"Foo1\"\n" | |
2683 "Last-Modified: Wed, 06 Feb 2008 22:38:21 GMT\n", | |
2684 "body1" | |
2685 }; | |
2686 | |
2687 // Second network response for |kUrl|. | |
2688 static const Response kNetResponse2 = { | |
2689 "HTTP/1.1 200 OK", | |
2690 "Date: Wed, 22 Jul 2009 03:15:26 GMT\n" | |
2691 "Etag: \"Foo2\"\n" | |
2692 "Last-Modified: Fri, 03 Jul 2009 02:14:27 GMT\n", | |
2693 "body2" | |
2694 }; | |
2695 | |
2696 const char* kExtraRequestHeaders = | |
2697 "If-Modified-Since: Wed, 06 Feb 2008 22:38:21 GMT\r\n" | |
2698 "If-None-Match: \"Foo1\"\r\n"; | |
2699 | |
2700 ConditionalizedRequestUpdatesCacheHelper( | |
2701 kNetResponse1, kNetResponse2, kNetResponse2, kExtraRequestHeaders); | |
2702 } | |
2703 | |
2704 // Test that doing an externally conditionalized request with both if-none-match | |
2705 // and if-modified-since does not update the cache with only one match. | |
2706 TEST(HttpCache, ConditionalizedRequestUpdatesCache9) { | |
2707 static const Response kNetResponse1 = { | |
2708 "HTTP/1.1 200 OK", | |
2709 "Date: Fri, 12 Jun 2009 21:46:42 GMT\n" | |
2710 "Etag: \"Foo1\"\n" | |
2711 "Last-Modified: Wed, 06 Feb 2008 22:38:21 GMT\n", | |
2712 "body1" | |
2713 }; | |
2714 | |
2715 // Second network response for |kUrl|. | |
2716 static const Response kNetResponse2 = { | |
2717 "HTTP/1.1 200 OK", | |
2718 "Date: Wed, 22 Jul 2009 03:15:26 GMT\n" | |
2719 "Etag: \"Foo2\"\n" | |
2720 "Last-Modified: Fri, 03 Jul 2009 02:14:27 GMT\n", | |
2721 "body2" | |
2722 }; | |
2723 | |
2724 // The etag doesn't match what we have stored. | |
2725 const char* kExtraRequestHeaders = | |
2726 "If-Modified-Since: Wed, 06 Feb 2008 22:38:21 GMT\n" | |
2727 "If-None-Match: \"Foo2\"\n"; | |
2728 | |
2729 ConditionalizedRequestUpdatesCacheHelper( | |
2730 kNetResponse1, kNetResponse2, kNetResponse1, kExtraRequestHeaders); | |
2731 } | |
2732 | |
2733 // Test that doing an externally conditionalized request with both if-none-match | |
2734 // and if-modified-since does not update the cache with only one match. | |
2735 TEST(HttpCache, ConditionalizedRequestUpdatesCache10) { | |
2736 static const Response kNetResponse1 = { | |
2737 "HTTP/1.1 200 OK", | |
2738 "Date: Fri, 12 Jun 2009 21:46:42 GMT\n" | |
2739 "Etag: \"Foo1\"\n" | |
2740 "Last-Modified: Wed, 06 Feb 2008 22:38:21 GMT\n", | |
2741 "body1" | |
2742 }; | |
2743 | |
2744 // Second network response for |kUrl|. | |
2745 static const Response kNetResponse2 = { | |
2746 "HTTP/1.1 200 OK", | |
2747 "Date: Wed, 22 Jul 2009 03:15:26 GMT\n" | |
2748 "Etag: \"Foo2\"\n" | |
2749 "Last-Modified: Fri, 03 Jul 2009 02:14:27 GMT\n", | |
2750 "body2" | |
2751 }; | |
2752 | |
2753 // The modification date doesn't match what we have stored. | |
2754 const char* kExtraRequestHeaders = | |
2755 "If-Modified-Since: Fri, 08 Feb 2008 22:38:21 GMT\n" | |
2756 "If-None-Match: \"Foo1\"\n"; | |
2757 | |
2758 ConditionalizedRequestUpdatesCacheHelper( | |
2759 kNetResponse1, kNetResponse2, kNetResponse1, kExtraRequestHeaders); | |
2760 } | |
2761 | |
2762 // Test that doing an externally conditionalized request with two conflicting | |
2763 // headers does not update the cache. | |
2764 TEST(HttpCache, ConditionalizedRequestUpdatesCache11) { | |
2765 static const Response kNetResponse1 = { | |
2766 "HTTP/1.1 200 OK", | |
2767 "Date: Fri, 12 Jun 2009 21:46:42 GMT\n" | |
2768 "Etag: \"Foo1\"\n" | |
2769 "Last-Modified: Wed, 06 Feb 2008 22:38:21 GMT\n", | |
2770 "body1" | |
2771 }; | |
2772 | |
2773 // Second network response for |kUrl|. | |
2774 static const Response kNetResponse2 = { | |
2775 "HTTP/1.1 200 OK", | |
2776 "Date: Wed, 22 Jul 2009 03:15:26 GMT\n" | |
2777 "Etag: \"Foo2\"\n" | |
2778 "Last-Modified: Fri, 03 Jul 2009 02:14:27 GMT\n", | |
2779 "body2" | |
2780 }; | |
2781 | |
2782 // Two dates, the second matches what we have stored. | |
2783 const char* kExtraRequestHeaders = | |
2784 "If-Modified-Since: Mon, 04 Feb 2008 22:38:21 GMT\n" | |
2785 "If-Modified-Since: Wed, 06 Feb 2008 22:38:21 GMT\n"; | |
2786 | |
2787 ConditionalizedRequestUpdatesCacheHelper( | |
2788 kNetResponse1, kNetResponse2, kNetResponse1, kExtraRequestHeaders); | |
2789 } | |
2790 | |
2791 TEST(HttpCache, UrlContainingHash) { | |
2792 MockHttpCache cache; | |
2793 | |
2794 // Do a typical GET request -- should write an entry into our cache. | |
2795 MockTransaction trans(kTypicalGET_Transaction); | |
2796 RunTransactionTest(cache.http_cache(), trans); | |
2797 | |
2798 EXPECT_EQ(1, cache.network_layer()->transaction_count()); | |
2799 EXPECT_EQ(0, cache.disk_cache()->open_count()); | |
2800 EXPECT_EQ(1, cache.disk_cache()->create_count()); | |
2801 | |
2802 // Request the same URL, but this time with a reference section (hash). | |
2803 // Since the cache key strips the hash sections, this should be a cache hit. | |
2804 std::string url_with_hash = std::string(trans.url) + "#multiple#hashes"; | |
2805 trans.url = url_with_hash.c_str(); | |
2806 trans.load_flags = net::LOAD_ONLY_FROM_CACHE; | |
2807 | |
2808 RunTransactionTest(cache.http_cache(), trans); | |
2809 | |
2810 EXPECT_EQ(1, cache.network_layer()->transaction_count()); | |
2811 EXPECT_EQ(1, cache.disk_cache()->open_count()); | |
2812 EXPECT_EQ(1, cache.disk_cache()->create_count()); | |
2813 } | |
2814 | |
2815 TEST(HttpCache, SimplePOST_LoadOnlyFromCache_Miss) { | |
2816 MockHttpCache cache; | |
2817 | |
2818 // Test that we skip the cache for POST requests. Eventually, we will want | |
2819 // to cache these, but we'll still have cases where skipping the cache makes | |
2820 // sense, so we want to make sure that it works properly. | |
2821 | |
2822 MockTransaction transaction(kSimplePOST_Transaction); | |
2823 transaction.load_flags |= net::LOAD_ONLY_FROM_CACHE; | |
2824 | |
2825 MockHttpRequest request(transaction); | |
2826 TestOldCompletionCallback callback; | |
2827 | |
2828 scoped_ptr<net::HttpTransaction> trans; | |
2829 int rv = cache.http_cache()->CreateTransaction(&trans); | |
2830 EXPECT_EQ(net::OK, rv); | |
2831 ASSERT_TRUE(trans.get()); | |
2832 | |
2833 rv = trans->Start(&request, &callback, net::BoundNetLog()); | |
2834 if (rv == net::ERR_IO_PENDING) | |
2835 rv = callback.WaitForResult(); | |
2836 ASSERT_EQ(net::ERR_CACHE_MISS, rv); | |
2837 | |
2838 trans.reset(); | |
2839 | |
2840 EXPECT_EQ(0, cache.network_layer()->transaction_count()); | |
2841 EXPECT_EQ(0, cache.disk_cache()->open_count()); | |
2842 EXPECT_EQ(0, cache.disk_cache()->create_count()); | |
2843 } | |
2844 | |
2845 TEST(HttpCache, SimplePOST_LoadOnlyFromCache_Hit) { | |
2846 MockHttpCache cache; | |
2847 | |
2848 // Test that we hit the cache for POST requests. | |
2849 | |
2850 MockTransaction transaction(kSimplePOST_Transaction); | |
2851 | |
2852 const int64 kUploadId = 1; // Just a dummy value. | |
2853 | |
2854 MockHttpRequest request(transaction); | |
2855 request.upload_data = new net::UploadData(); | |
2856 request.upload_data->set_identifier(kUploadId); | |
2857 request.upload_data->AppendBytes("hello", 5); | |
2858 | |
2859 // Populate the cache. | |
2860 RunTransactionTestWithRequest(cache.http_cache(), transaction, request, NULL); | |
2861 | |
2862 EXPECT_EQ(1, cache.network_layer()->transaction_count()); | |
2863 EXPECT_EQ(0, cache.disk_cache()->open_count()); | |
2864 EXPECT_EQ(1, cache.disk_cache()->create_count()); | |
2865 | |
2866 // Load from cache. | |
2867 request.load_flags |= net::LOAD_ONLY_FROM_CACHE; | |
2868 RunTransactionTestWithRequest(cache.http_cache(), transaction, request, NULL); | |
2869 | |
2870 EXPECT_EQ(1, cache.network_layer()->transaction_count()); | |
2871 EXPECT_EQ(1, cache.disk_cache()->open_count()); | |
2872 EXPECT_EQ(1, cache.disk_cache()->create_count()); | |
2873 } | |
2874 | |
2875 TEST(HttpCache, RangeGET_SkipsCache) { | |
2876 MockHttpCache cache; | |
2877 | |
2878 // Test that we skip the cache for range GET requests. Eventually, we will | |
2879 // want to cache these, but we'll still have cases where skipping the cache | |
2880 // makes sense, so we want to make sure that it works properly. | |
2881 | |
2882 RunTransactionTest(cache.http_cache(), kRangeGET_Transaction); | |
2883 | |
2884 EXPECT_EQ(1, cache.network_layer()->transaction_count()); | |
2885 EXPECT_EQ(0, cache.disk_cache()->open_count()); | |
2886 EXPECT_EQ(0, cache.disk_cache()->create_count()); | |
2887 | |
2888 MockTransaction transaction(kSimpleGET_Transaction); | |
2889 transaction.request_headers = "If-None-Match: foo"; | |
2890 RunTransactionTest(cache.http_cache(), transaction); | |
2891 | |
2892 EXPECT_EQ(2, cache.network_layer()->transaction_count()); | |
2893 EXPECT_EQ(0, cache.disk_cache()->open_count()); | |
2894 EXPECT_EQ(0, cache.disk_cache()->create_count()); | |
2895 | |
2896 transaction.request_headers = | |
2897 "If-Modified-Since: Wed, 28 Nov 2007 00:45:20 GMT"; | |
2898 RunTransactionTest(cache.http_cache(), transaction); | |
2899 | |
2900 EXPECT_EQ(3, cache.network_layer()->transaction_count()); | |
2901 EXPECT_EQ(0, cache.disk_cache()->open_count()); | |
2902 EXPECT_EQ(0, cache.disk_cache()->create_count()); | |
2903 } | |
2904 | |
2905 // Test that we skip the cache for range requests that include a validation | |
2906 // header. | |
2907 TEST(HttpCache, RangeGET_SkipsCache2) { | |
2908 MockHttpCache cache; | |
2909 | |
2910 MockTransaction transaction(kRangeGET_Transaction); | |
2911 transaction.request_headers = "If-None-Match: foo\r\n" | |
2912 EXTRA_HEADER | |
2913 "\r\nRange: bytes = 40-49"; | |
2914 RunTransactionTest(cache.http_cache(), transaction); | |
2915 | |
2916 EXPECT_EQ(1, cache.network_layer()->transaction_count()); | |
2917 EXPECT_EQ(0, cache.disk_cache()->open_count()); | |
2918 EXPECT_EQ(0, cache.disk_cache()->create_count()); | |
2919 | |
2920 transaction.request_headers = | |
2921 "If-Modified-Since: Wed, 28 Nov 2007 00:45:20 GMT\r\n" | |
2922 EXTRA_HEADER | |
2923 "\r\nRange: bytes = 40-49"; | |
2924 RunTransactionTest(cache.http_cache(), transaction); | |
2925 | |
2926 EXPECT_EQ(2, cache.network_layer()->transaction_count()); | |
2927 EXPECT_EQ(0, cache.disk_cache()->open_count()); | |
2928 EXPECT_EQ(0, cache.disk_cache()->create_count()); | |
2929 | |
2930 transaction.request_headers = "If-Range: bla\r\n" | |
2931 EXTRA_HEADER | |
2932 "\r\nRange: bytes = 40-49\n"; | |
2933 RunTransactionTest(cache.http_cache(), transaction); | |
2934 | |
2935 EXPECT_EQ(3, cache.network_layer()->transaction_count()); | |
2936 EXPECT_EQ(0, cache.disk_cache()->open_count()); | |
2937 EXPECT_EQ(0, cache.disk_cache()->create_count()); | |
2938 } | |
2939 | |
2940 // Tests that receiving 206 for a regular request is handled correctly. | |
2941 TEST(HttpCache, GET_Crazy206) { | |
2942 MockHttpCache cache; | |
2943 | |
2944 // Write to the cache. | |
2945 MockTransaction transaction(kRangeGET_TransactionOK); | |
2946 AddMockTransaction(&transaction); | |
2947 transaction.request_headers = EXTRA_HEADER; | |
2948 transaction.handler = NULL; | |
2949 RunTransactionTest(cache.http_cache(), transaction); | |
2950 | |
2951 EXPECT_EQ(1, cache.network_layer()->transaction_count()); | |
2952 EXPECT_EQ(0, cache.disk_cache()->open_count()); | |
2953 EXPECT_EQ(1, cache.disk_cache()->create_count()); | |
2954 | |
2955 // This should read again from the net. | |
2956 RunTransactionTest(cache.http_cache(), transaction); | |
2957 | |
2958 EXPECT_EQ(2, cache.network_layer()->transaction_count()); | |
2959 EXPECT_EQ(0, cache.disk_cache()->open_count()); | |
2960 EXPECT_EQ(2, cache.disk_cache()->create_count()); | |
2961 RemoveMockTransaction(&transaction); | |
2962 } | |
2963 | |
2964 // Tests that we don't cache partial responses that can't be validated. | |
2965 TEST(HttpCache, RangeGET_NoStrongValidators) { | |
2966 MockHttpCache cache; | |
2967 std::string headers; | |
2968 | |
2969 // Attempt to write to the cache (40-49). | |
2970 MockTransaction transaction(kRangeGET_TransactionOK); | |
2971 AddMockTransaction(&transaction); | |
2972 transaction.response_headers = "Content-Length: 10\n" | |
2973 "ETag: w/\"foo\"\n"; | |
2974 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers); | |
2975 | |
2976 Verify206Response(headers, 40, 49); | |
2977 EXPECT_EQ(1, cache.network_layer()->transaction_count()); | |
2978 EXPECT_EQ(0, cache.disk_cache()->open_count()); | |
2979 EXPECT_EQ(1, cache.disk_cache()->create_count()); | |
2980 | |
2981 // Now verify that there's no cached data. | |
2982 RunTransactionTestWithResponse(cache.http_cache(), kRangeGET_TransactionOK, | |
2983 &headers); | |
2984 | |
2985 Verify206Response(headers, 40, 49); | |
2986 EXPECT_EQ(2, cache.network_layer()->transaction_count()); | |
2987 EXPECT_EQ(0, cache.disk_cache()->open_count()); | |
2988 EXPECT_EQ(2, cache.disk_cache()->create_count()); | |
2989 | |
2990 RemoveMockTransaction(&transaction); | |
2991 } | |
2992 | |
2993 // Tests that we can cache range requests and fetch random blocks from the | |
2994 // cache and the network. | |
2995 TEST(HttpCache, RangeGET_OK) { | |
2996 MockHttpCache cache; | |
2997 AddMockTransaction(&kRangeGET_TransactionOK); | |
2998 std::string headers; | |
2999 | |
3000 // Write to the cache (40-49). | |
3001 RunTransactionTestWithResponse(cache.http_cache(), kRangeGET_TransactionOK, | |
3002 &headers); | |
3003 | |
3004 Verify206Response(headers, 40, 49); | |
3005 EXPECT_EQ(1, cache.network_layer()->transaction_count()); | |
3006 EXPECT_EQ(0, cache.disk_cache()->open_count()); | |
3007 EXPECT_EQ(1, cache.disk_cache()->create_count()); | |
3008 | |
3009 // Read from the cache (40-49). | |
3010 RunTransactionTestWithResponse(cache.http_cache(), kRangeGET_TransactionOK, | |
3011 &headers); | |
3012 | |
3013 Verify206Response(headers, 40, 49); | |
3014 EXPECT_EQ(1, cache.network_layer()->transaction_count()); | |
3015 EXPECT_EQ(1, cache.disk_cache()->open_count()); | |
3016 EXPECT_EQ(1, cache.disk_cache()->create_count()); | |
3017 | |
3018 // Make sure we are done with the previous transaction. | |
3019 MessageLoop::current()->RunAllPending(); | |
3020 | |
3021 // Write to the cache (30-39). | |
3022 MockTransaction transaction(kRangeGET_TransactionOK); | |
3023 transaction.request_headers = "Range: bytes = 30-39\r\n" EXTRA_HEADER; | |
3024 transaction.data = "rg: 30-39 "; | |
3025 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers); | |
3026 | |
3027 Verify206Response(headers, 30, 39); | |
3028 EXPECT_EQ(2, cache.network_layer()->transaction_count()); | |
3029 EXPECT_EQ(2, cache.disk_cache()->open_count()); | |
3030 EXPECT_EQ(1, cache.disk_cache()->create_count()); | |
3031 | |
3032 // Make sure we are done with the previous transaction. | |
3033 MessageLoop::current()->RunAllPending(); | |
3034 | |
3035 // Write and read from the cache (20-59). | |
3036 transaction.request_headers = "Range: bytes = 20-59\r\n" EXTRA_HEADER; | |
3037 transaction.data = "rg: 20-29 rg: 30-39 rg: 40-49 rg: 50-59 "; | |
3038 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers); | |
3039 | |
3040 Verify206Response(headers, 20, 59); | |
3041 EXPECT_EQ(4, cache.network_layer()->transaction_count()); | |
3042 EXPECT_EQ(3, cache.disk_cache()->open_count()); | |
3043 EXPECT_EQ(1, cache.disk_cache()->create_count()); | |
3044 | |
3045 RemoveMockTransaction(&kRangeGET_TransactionOK); | |
3046 } | |
3047 | |
3048 // Tests that we can cache range requests and fetch random blocks from the | |
3049 // cache and the network, with synchronous responses. | |
3050 TEST(HttpCache, RangeGET_SyncOK) { | |
3051 MockHttpCache cache; | |
3052 | |
3053 MockTransaction transaction(kRangeGET_TransactionOK); | |
3054 transaction.test_mode = TEST_MODE_SYNC_ALL; | |
3055 AddMockTransaction(&transaction); | |
3056 | |
3057 // Write to the cache (40-49). | |
3058 std::string headers; | |
3059 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers); | |
3060 | |
3061 Verify206Response(headers, 40, 49); | |
3062 EXPECT_EQ(1, cache.network_layer()->transaction_count()); | |
3063 EXPECT_EQ(0, cache.disk_cache()->open_count()); | |
3064 EXPECT_EQ(1, cache.disk_cache()->create_count()); | |
3065 | |
3066 // Read from the cache (40-49). | |
3067 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers); | |
3068 | |
3069 Verify206Response(headers, 40, 49); | |
3070 EXPECT_EQ(1, cache.network_layer()->transaction_count()); | |
3071 EXPECT_EQ(0, cache.disk_cache()->open_count()); | |
3072 EXPECT_EQ(1, cache.disk_cache()->create_count()); | |
3073 | |
3074 // Make sure we are done with the previous transaction. | |
3075 MessageLoop::current()->RunAllPending(); | |
3076 | |
3077 // Write to the cache (30-39). | |
3078 transaction.request_headers = "Range: bytes = 30-39\r\n" EXTRA_HEADER; | |
3079 transaction.data = "rg: 30-39 "; | |
3080 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers); | |
3081 | |
3082 Verify206Response(headers, 30, 39); | |
3083 EXPECT_EQ(2, cache.network_layer()->transaction_count()); | |
3084 EXPECT_EQ(1, cache.disk_cache()->open_count()); | |
3085 EXPECT_EQ(1, cache.disk_cache()->create_count()); | |
3086 | |
3087 // Make sure we are done with the previous transaction. | |
3088 MessageLoop::current()->RunAllPending(); | |
3089 | |
3090 // Write and read from the cache (20-59). | |
3091 transaction.request_headers = "Range: bytes = 20-59\r\n" EXTRA_HEADER; | |
3092 transaction.data = "rg: 20-29 rg: 30-39 rg: 40-49 rg: 50-59 "; | |
3093 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers); | |
3094 | |
3095 Verify206Response(headers, 20, 59); | |
3096 EXPECT_EQ(4, cache.network_layer()->transaction_count()); | |
3097 EXPECT_EQ(2, cache.disk_cache()->open_count()); | |
3098 EXPECT_EQ(1, cache.disk_cache()->create_count()); | |
3099 | |
3100 RemoveMockTransaction(&transaction); | |
3101 } | |
3102 | |
3103 // Tests that we don't revalidate an entry unless we are required to do so. | |
3104 TEST(HttpCache, RangeGET_Revalidate1) { | |
3105 MockHttpCache cache; | |
3106 std::string headers; | |
3107 | |
3108 // Write to the cache (40-49). | |
3109 MockTransaction transaction(kRangeGET_TransactionOK); | |
3110 transaction.response_headers = | |
3111 "Last-Modified: Sat, 18 Apr 2009 01:10:43 GMT\n" | |
3112 "Expires: Wed, 7 Sep 2033 21:46:42 GMT\n" // Should never expire. | |
3113 "ETag: \"foo\"\n" | |
3114 "Accept-Ranges: bytes\n" | |
3115 "Content-Length: 10\n"; | |
3116 AddMockTransaction(&transaction); | |
3117 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers); | |
3118 | |
3119 Verify206Response(headers, 40, 49); | |
3120 EXPECT_EQ(1, cache.network_layer()->transaction_count()); | |
3121 EXPECT_EQ(0, cache.disk_cache()->open_count()); | |
3122 EXPECT_EQ(1, cache.disk_cache()->create_count()); | |
3123 | |
3124 // Read from the cache (40-49). | |
3125 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers); | |
3126 Verify206Response(headers, 40, 49); | |
3127 | |
3128 EXPECT_EQ(1, cache.network_layer()->transaction_count()); | |
3129 EXPECT_EQ(1, cache.disk_cache()->open_count()); | |
3130 EXPECT_EQ(1, cache.disk_cache()->create_count()); | |
3131 | |
3132 // Read again forcing the revalidation. | |
3133 transaction.load_flags |= net::LOAD_VALIDATE_CACHE; | |
3134 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers); | |
3135 | |
3136 Verify206Response(headers, 40, 49); | |
3137 EXPECT_EQ(2, cache.network_layer()->transaction_count()); | |
3138 EXPECT_EQ(1, cache.disk_cache()->open_count()); | |
3139 EXPECT_EQ(1, cache.disk_cache()->create_count()); | |
3140 | |
3141 RemoveMockTransaction(&transaction); | |
3142 } | |
3143 | |
3144 // Checks that we revalidate an entry when the headers say so. | |
3145 TEST(HttpCache, RangeGET_Revalidate2) { | |
3146 MockHttpCache cache; | |
3147 std::string headers; | |
3148 | |
3149 // Write to the cache (40-49). | |
3150 MockTransaction transaction(kRangeGET_TransactionOK); | |
3151 transaction.response_headers = | |
3152 "Last-Modified: Sat, 18 Apr 2009 01:10:43 GMT\n" | |
3153 "Expires: Sat, 18 Apr 2009 01:10:43 GMT\n" // Expired. | |
3154 "ETag: \"foo\"\n" | |
3155 "Accept-Ranges: bytes\n" | |
3156 "Content-Length: 10\n"; | |
3157 AddMockTransaction(&transaction); | |
3158 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers); | |
3159 | |
3160 Verify206Response(headers, 40, 49); | |
3161 EXPECT_EQ(1, cache.network_layer()->transaction_count()); | |
3162 EXPECT_EQ(0, cache.disk_cache()->open_count()); | |
3163 EXPECT_EQ(1, cache.disk_cache()->create_count()); | |
3164 | |
3165 // Read from the cache (40-49). | |
3166 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers); | |
3167 Verify206Response(headers, 40, 49); | |
3168 | |
3169 EXPECT_EQ(2, cache.network_layer()->transaction_count()); | |
3170 EXPECT_EQ(1, cache.disk_cache()->open_count()); | |
3171 EXPECT_EQ(1, cache.disk_cache()->create_count()); | |
3172 | |
3173 RemoveMockTransaction(&transaction); | |
3174 } | |
3175 | |
3176 // Tests that we deal with 304s for range requests. | |
3177 TEST(HttpCache, RangeGET_304) { | |
3178 MockHttpCache cache; | |
3179 AddMockTransaction(&kRangeGET_TransactionOK); | |
3180 std::string headers; | |
3181 | |
3182 // Write to the cache (40-49). | |
3183 RunTransactionTestWithResponse(cache.http_cache(), kRangeGET_TransactionOK, | |
3184 &headers); | |
3185 | |
3186 Verify206Response(headers, 40, 49); | |
3187 EXPECT_EQ(1, cache.network_layer()->transaction_count()); | |
3188 EXPECT_EQ(0, cache.disk_cache()->open_count()); | |
3189 EXPECT_EQ(1, cache.disk_cache()->create_count()); | |
3190 | |
3191 // Read from the cache (40-49). | |
3192 RangeTransactionServer handler; | |
3193 handler.set_not_modified(true); | |
3194 MockTransaction transaction(kRangeGET_TransactionOK); | |
3195 transaction.load_flags |= net::LOAD_VALIDATE_CACHE; | |
3196 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers); | |
3197 | |
3198 Verify206Response(headers, 40, 49); | |
3199 EXPECT_EQ(2, cache.network_layer()->transaction_count()); | |
3200 EXPECT_EQ(1, cache.disk_cache()->open_count()); | |
3201 EXPECT_EQ(1, cache.disk_cache()->create_count()); | |
3202 | |
3203 RemoveMockTransaction(&kRangeGET_TransactionOK); | |
3204 } | |
3205 | |
3206 // Tests that we deal with 206s when revalidating range requests. | |
3207 TEST(HttpCache, RangeGET_ModifiedResult) { | |
3208 MockHttpCache cache; | |
3209 AddMockTransaction(&kRangeGET_TransactionOK); | |
3210 std::string headers; | |
3211 | |
3212 // Write to the cache (40-49). | |
3213 RunTransactionTestWithResponse(cache.http_cache(), kRangeGET_TransactionOK, | |
3214 &headers); | |
3215 | |
3216 Verify206Response(headers, 40, 49); | |
3217 EXPECT_EQ(1, cache.network_layer()->transaction_count()); | |
3218 EXPECT_EQ(0, cache.disk_cache()->open_count()); | |
3219 EXPECT_EQ(1, cache.disk_cache()->create_count()); | |
3220 | |
3221 // Attempt to read from the cache (40-49). | |
3222 RangeTransactionServer handler; | |
3223 handler.set_modified(true); | |
3224 MockTransaction transaction(kRangeGET_TransactionOK); | |
3225 transaction.load_flags |= net::LOAD_VALIDATE_CACHE; | |
3226 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers); | |
3227 | |
3228 Verify206Response(headers, 40, 49); | |
3229 EXPECT_EQ(2, cache.network_layer()->transaction_count()); | |
3230 EXPECT_EQ(1, cache.disk_cache()->open_count()); | |
3231 EXPECT_EQ(1, cache.disk_cache()->create_count()); | |
3232 | |
3233 // And the entry should be gone. | |
3234 RunTransactionTest(cache.http_cache(), kRangeGET_TransactionOK); | |
3235 EXPECT_EQ(3, cache.network_layer()->transaction_count()); | |
3236 EXPECT_EQ(1, cache.disk_cache()->open_count()); | |
3237 EXPECT_EQ(2, cache.disk_cache()->create_count()); | |
3238 | |
3239 RemoveMockTransaction(&kRangeGET_TransactionOK); | |
3240 } | |
3241 | |
3242 // Tests that we can cache range requests when the start or end is unknown. | |
3243 // We start with one suffix request, followed by a request from a given point. | |
3244 TEST(HttpCache, UnknownRangeGET_1) { | |
3245 MockHttpCache cache; | |
3246 AddMockTransaction(&kRangeGET_TransactionOK); | |
3247 std::string headers; | |
3248 | |
3249 // Write to the cache (70-79). | |
3250 MockTransaction transaction(kRangeGET_TransactionOK); | |
3251 transaction.request_headers = "Range: bytes = -10\r\n" EXTRA_HEADER; | |
3252 transaction.data = "rg: 70-79 "; | |
3253 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers); | |
3254 | |
3255 Verify206Response(headers, 70, 79); | |
3256 EXPECT_EQ(1, cache.network_layer()->transaction_count()); | |
3257 EXPECT_EQ(0, cache.disk_cache()->open_count()); | |
3258 EXPECT_EQ(1, cache.disk_cache()->create_count()); | |
3259 | |
3260 // Make sure we are done with the previous transaction. | |
3261 MessageLoop::current()->RunAllPending(); | |
3262 | |
3263 // Write and read from the cache (60-79). | |
3264 transaction.request_headers = "Range: bytes = 60-\r\n" EXTRA_HEADER; | |
3265 transaction.data = "rg: 60-69 rg: 70-79 "; | |
3266 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers); | |
3267 | |
3268 Verify206Response(headers, 60, 79); | |
3269 EXPECT_EQ(2, cache.network_layer()->transaction_count()); | |
3270 EXPECT_EQ(1, cache.disk_cache()->open_count()); | |
3271 EXPECT_EQ(1, cache.disk_cache()->create_count()); | |
3272 | |
3273 RemoveMockTransaction(&kRangeGET_TransactionOK); | |
3274 } | |
3275 | |
3276 // Tests that we can cache range requests when the start or end is unknown. | |
3277 // We start with one request from a given point, followed by a suffix request. | |
3278 // We'll also verify that synchronous cache responses work as intended. | |
3279 TEST(HttpCache, UnknownRangeGET_2) { | |
3280 MockHttpCache cache; | |
3281 std::string headers; | |
3282 | |
3283 MockTransaction transaction(kRangeGET_TransactionOK); | |
3284 transaction.test_mode = TEST_MODE_SYNC_CACHE_START | | |
3285 TEST_MODE_SYNC_CACHE_READ | | |
3286 TEST_MODE_SYNC_CACHE_WRITE; | |
3287 AddMockTransaction(&transaction); | |
3288 | |
3289 // Write to the cache (70-79). | |
3290 transaction.request_headers = "Range: bytes = 70-\r\n" EXTRA_HEADER; | |
3291 transaction.data = "rg: 70-79 "; | |
3292 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers); | |
3293 | |
3294 Verify206Response(headers, 70, 79); | |
3295 EXPECT_EQ(1, cache.network_layer()->transaction_count()); | |
3296 EXPECT_EQ(0, cache.disk_cache()->open_count()); | |
3297 EXPECT_EQ(1, cache.disk_cache()->create_count()); | |
3298 | |
3299 // Make sure we are done with the previous transaction. | |
3300 MessageLoop::current()->RunAllPending(); | |
3301 | |
3302 // Write and read from the cache (60-79). | |
3303 transaction.request_headers = "Range: bytes = -20\r\n" EXTRA_HEADER; | |
3304 transaction.data = "rg: 60-69 rg: 70-79 "; | |
3305 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers); | |
3306 | |
3307 Verify206Response(headers, 60, 79); | |
3308 EXPECT_EQ(2, cache.network_layer()->transaction_count()); | |
3309 EXPECT_EQ(1, cache.disk_cache()->open_count()); | |
3310 EXPECT_EQ(1, cache.disk_cache()->create_count()); | |
3311 | |
3312 RemoveMockTransaction(&transaction); | |
3313 } | |
3314 | |
3315 // Tests that receiving Not Modified when asking for an open range doesn't mess | |
3316 // up things. | |
3317 TEST(HttpCache, UnknownRangeGET_304) { | |
3318 MockHttpCache cache; | |
3319 std::string headers; | |
3320 | |
3321 MockTransaction transaction(kRangeGET_TransactionOK); | |
3322 AddMockTransaction(&transaction); | |
3323 | |
3324 RangeTransactionServer handler; | |
3325 handler.set_not_modified(true); | |
3326 | |
3327 // Ask for the end of the file, without knowing the length. | |
3328 transaction.request_headers = "Range: bytes = 70-\r\n" EXTRA_HEADER; | |
3329 transaction.data = ""; | |
3330 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers); | |
3331 | |
3332 // We just bypass the cache. | |
3333 EXPECT_EQ(0U, headers.find("HTTP/1.1 304 Not Modified\n")); | |
3334 EXPECT_EQ(1, cache.network_layer()->transaction_count()); | |
3335 EXPECT_EQ(0, cache.disk_cache()->open_count()); | |
3336 EXPECT_EQ(1, cache.disk_cache()->create_count()); | |
3337 | |
3338 RunTransactionTest(cache.http_cache(), transaction); | |
3339 EXPECT_EQ(2, cache.disk_cache()->create_count()); | |
3340 | |
3341 RemoveMockTransaction(&transaction); | |
3342 } | |
3343 | |
3344 // Tests that we can handle non-range requests when we have cached a range. | |
3345 TEST(HttpCache, GET_Previous206) { | |
3346 MockHttpCache cache; | |
3347 AddMockTransaction(&kRangeGET_TransactionOK); | |
3348 std::string headers; | |
3349 | |
3350 // Write to the cache (40-49). | |
3351 RunTransactionTestWithResponse(cache.http_cache(), kRangeGET_TransactionOK, | |
3352 &headers); | |
3353 | |
3354 Verify206Response(headers, 40, 49); | |
3355 EXPECT_EQ(1, cache.network_layer()->transaction_count()); | |
3356 EXPECT_EQ(0, cache.disk_cache()->open_count()); | |
3357 EXPECT_EQ(1, cache.disk_cache()->create_count()); | |
3358 | |
3359 // Write and read from the cache (0-79), when not asked for a range. | |
3360 MockTransaction transaction(kRangeGET_TransactionOK); | |
3361 transaction.request_headers = EXTRA_HEADER; | |
3362 transaction.data = "rg: 00-09 rg: 10-19 rg: 20-29 rg: 30-39 rg: 40-49 " | |
3363 "rg: 50-59 rg: 60-69 rg: 70-79 "; | |
3364 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers); | |
3365 | |
3366 EXPECT_EQ(0U, headers.find("HTTP/1.1 200 OK\n")); | |
3367 EXPECT_EQ(3, cache.network_layer()->transaction_count()); | |
3368 EXPECT_EQ(1, cache.disk_cache()->open_count()); | |
3369 EXPECT_EQ(1, cache.disk_cache()->create_count()); | |
3370 | |
3371 RemoveMockTransaction(&kRangeGET_TransactionOK); | |
3372 } | |
3373 | |
3374 // Tests that we can handle non-range requests when we have cached the first | |
3375 // part of the object and the server replies with 304 (Not Modified). | |
3376 TEST(HttpCache, GET_Previous206_NotModified) { | |
3377 MockHttpCache cache; | |
3378 | |
3379 MockTransaction transaction(kRangeGET_TransactionOK); | |
3380 AddMockTransaction(&transaction); | |
3381 std::string headers; | |
3382 | |
3383 // Write to the cache (0-9). | |
3384 transaction.request_headers = "Range: bytes = 0-9\r\n" EXTRA_HEADER; | |
3385 transaction.data = "rg: 00-09 "; | |
3386 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers); | |
3387 Verify206Response(headers, 0, 9); | |
3388 | |
3389 // Write to the cache (70-79). | |
3390 transaction.request_headers = "Range: bytes = 70-79\r\n" EXTRA_HEADER; | |
3391 transaction.data = "rg: 70-79 "; | |
3392 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers); | |
3393 Verify206Response(headers, 70, 79); | |
3394 | |
3395 EXPECT_EQ(2, cache.network_layer()->transaction_count()); | |
3396 EXPECT_EQ(1, cache.disk_cache()->open_count()); | |
3397 EXPECT_EQ(1, cache.disk_cache()->create_count()); | |
3398 | |
3399 // Read from the cache (0-9), write and read from cache (10 - 79). | |
3400 transaction.load_flags |= net::LOAD_VALIDATE_CACHE; | |
3401 transaction.request_headers = "Foo: bar\r\n" EXTRA_HEADER; | |
3402 transaction.data = "rg: 00-09 rg: 10-19 rg: 20-29 rg: 30-39 rg: 40-49 " | |
3403 "rg: 50-59 rg: 60-69 rg: 70-79 "; | |
3404 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers); | |
3405 | |
3406 EXPECT_EQ(0U, headers.find("HTTP/1.1 200 OK\n")); | |
3407 EXPECT_EQ(4, cache.network_layer()->transaction_count()); | |
3408 EXPECT_EQ(2, cache.disk_cache()->open_count()); | |
3409 EXPECT_EQ(1, cache.disk_cache()->create_count()); | |
3410 | |
3411 RemoveMockTransaction(&transaction); | |
3412 } | |
3413 | |
3414 // Tests that we can handle a regular request to a sparse entry, that results in | |
3415 // new content provided by the server (206). | |
3416 TEST(HttpCache, GET_Previous206_NewContent) { | |
3417 MockHttpCache cache; | |
3418 AddMockTransaction(&kRangeGET_TransactionOK); | |
3419 std::string headers; | |
3420 | |
3421 // Write to the cache (0-9). | |
3422 MockTransaction transaction(kRangeGET_TransactionOK); | |
3423 transaction.request_headers = "Range: bytes = 0-9\r\n" EXTRA_HEADER; | |
3424 transaction.data = "rg: 00-09 "; | |
3425 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers); | |
3426 | |
3427 Verify206Response(headers, 0, 9); | |
3428 EXPECT_EQ(1, cache.network_layer()->transaction_count()); | |
3429 EXPECT_EQ(0, cache.disk_cache()->open_count()); | |
3430 EXPECT_EQ(1, cache.disk_cache()->create_count()); | |
3431 | |
3432 // Now we'll issue a request without any range that should result first in a | |
3433 // 206 (when revalidating), and then in a weird standard answer: the test | |
3434 // server will not modify the response so we'll get the default range... a | |
3435 // real server will answer with 200. | |
3436 MockTransaction transaction2(kRangeGET_TransactionOK); | |
3437 transaction2.request_headers = EXTRA_HEADER; | |
3438 transaction2.load_flags |= net::LOAD_VALIDATE_CACHE; | |
3439 transaction2.data = "Not a range"; | |
3440 RangeTransactionServer handler; | |
3441 handler.set_modified(true); | |
3442 RunTransactionTestWithResponse(cache.http_cache(), transaction2, &headers); | |
3443 | |
3444 EXPECT_EQ(0U, headers.find("HTTP/1.1 200 OK\n")); | |
3445 EXPECT_EQ(3, cache.network_layer()->transaction_count()); | |
3446 EXPECT_EQ(1, cache.disk_cache()->open_count()); | |
3447 EXPECT_EQ(1, cache.disk_cache()->create_count()); | |
3448 | |
3449 // Verify that the previous request deleted the entry. | |
3450 RunTransactionTest(cache.http_cache(), transaction); | |
3451 EXPECT_EQ(2, cache.disk_cache()->create_count()); | |
3452 | |
3453 RemoveMockTransaction(&transaction); | |
3454 } | |
3455 | |
3456 // Tests that we can handle cached 206 responses that are not sparse. | |
3457 TEST(HttpCache, GET_Previous206_NotSparse) { | |
3458 MockHttpCache cache; | |
3459 | |
3460 // Create a disk cache entry that stores 206 headers while not being sparse. | |
3461 disk_cache::Entry* entry; | |
3462 ASSERT_TRUE(cache.CreateBackendEntry(kSimpleGET_Transaction.url, &entry, | |
3463 NULL)); | |
3464 | |
3465 std::string raw_headers(kRangeGET_TransactionOK.status); | |
3466 raw_headers.append("\n"); | |
3467 raw_headers.append(kRangeGET_TransactionOK.response_headers); | |
3468 raw_headers = net::HttpUtil::AssembleRawHeaders(raw_headers.data(), | |
3469 raw_headers.size()); | |
3470 | |
3471 net::HttpResponseInfo response; | |
3472 response.headers = new net::HttpResponseHeaders(raw_headers); | |
3473 EXPECT_TRUE(MockHttpCache::WriteResponseInfo(entry, &response, true, false)); | |
3474 | |
3475 scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(500)); | |
3476 int len = static_cast<int>(base::strlcpy(buf->data(), | |
3477 kRangeGET_TransactionOK.data, 500)); | |
3478 TestOldCompletionCallback cb; | |
3479 int rv = entry->WriteData(1, 0, buf, len, &cb, true); | |
3480 EXPECT_EQ(len, cb.GetResult(rv)); | |
3481 entry->Close(); | |
3482 | |
3483 // Now see that we don't use the stored entry. | |
3484 std::string headers; | |
3485 RunTransactionTestWithResponse(cache.http_cache(), kSimpleGET_Transaction, | |
3486 &headers); | |
3487 | |
3488 // We are expecting a 200. | |
3489 std::string expected_headers(kSimpleGET_Transaction.status); | |
3490 expected_headers.append("\n"); | |
3491 expected_headers.append(kSimpleGET_Transaction.response_headers); | |
3492 EXPECT_EQ(expected_headers, headers); | |
3493 EXPECT_EQ(1, cache.network_layer()->transaction_count()); | |
3494 EXPECT_EQ(1, cache.disk_cache()->open_count()); | |
3495 EXPECT_EQ(2, cache.disk_cache()->create_count()); | |
3496 } | |
3497 | |
3498 // Tests that we can handle cached 206 responses that are not sparse. This time | |
3499 // we issue a range request and expect to receive a range. | |
3500 TEST(HttpCache, RangeGET_Previous206_NotSparse_2) { | |
3501 MockHttpCache cache; | |
3502 AddMockTransaction(&kRangeGET_TransactionOK); | |
3503 | |
3504 // Create a disk cache entry that stores 206 headers while not being sparse. | |
3505 disk_cache::Entry* entry; | |
3506 ASSERT_TRUE(cache.CreateBackendEntry(kRangeGET_TransactionOK.url, &entry, | |
3507 NULL)); | |
3508 | |
3509 std::string raw_headers(kRangeGET_TransactionOK.status); | |
3510 raw_headers.append("\n"); | |
3511 raw_headers.append(kRangeGET_TransactionOK.response_headers); | |
3512 raw_headers = net::HttpUtil::AssembleRawHeaders(raw_headers.data(), | |
3513 raw_headers.size()); | |
3514 | |
3515 net::HttpResponseInfo response; | |
3516 response.headers = new net::HttpResponseHeaders(raw_headers); | |
3517 EXPECT_TRUE(MockHttpCache::WriteResponseInfo(entry, &response, true, false)); | |
3518 | |
3519 scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(500)); | |
3520 int len = static_cast<int>(base::strlcpy(buf->data(), | |
3521 kRangeGET_TransactionOK.data, 500)); | |
3522 TestOldCompletionCallback cb; | |
3523 int rv = entry->WriteData(1, 0, buf, len, &cb, true); | |
3524 EXPECT_EQ(len, cb.GetResult(rv)); | |
3525 entry->Close(); | |
3526 | |
3527 // Now see that we don't use the stored entry. | |
3528 std::string headers; | |
3529 RunTransactionTestWithResponse(cache.http_cache(), kRangeGET_TransactionOK, | |
3530 &headers); | |
3531 | |
3532 // We are expecting a 206. | |
3533 Verify206Response(headers, 40, 49); | |
3534 EXPECT_EQ(1, cache.network_layer()->transaction_count()); | |
3535 EXPECT_EQ(1, cache.disk_cache()->open_count()); | |
3536 EXPECT_EQ(2, cache.disk_cache()->create_count()); | |
3537 | |
3538 RemoveMockTransaction(&kRangeGET_TransactionOK); | |
3539 } | |
3540 | |
3541 // Tests that we can handle cached 206 responses that can't be validated. | |
3542 TEST(HttpCache, GET_Previous206_NotValidation) { | |
3543 MockHttpCache cache; | |
3544 | |
3545 // Create a disk cache entry that stores 206 headers. | |
3546 disk_cache::Entry* entry; | |
3547 ASSERT_TRUE(cache.CreateBackendEntry(kSimpleGET_Transaction.url, &entry, | |
3548 NULL)); | |
3549 | |
3550 // Make sure that the headers cannot be validated with the server. | |
3551 std::string raw_headers(kRangeGET_TransactionOK.status); | |
3552 raw_headers.append("\n"); | |
3553 raw_headers.append("Content-Length: 80\n"); | |
3554 raw_headers = net::HttpUtil::AssembleRawHeaders(raw_headers.data(), | |
3555 raw_headers.size()); | |
3556 | |
3557 net::HttpResponseInfo response; | |
3558 response.headers = new net::HttpResponseHeaders(raw_headers); | |
3559 EXPECT_TRUE(MockHttpCache::WriteResponseInfo(entry, &response, true, false)); | |
3560 | |
3561 scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(500)); | |
3562 int len = static_cast<int>(base::strlcpy(buf->data(), | |
3563 kRangeGET_TransactionOK.data, 500)); | |
3564 TestOldCompletionCallback cb; | |
3565 int rv = entry->WriteData(1, 0, buf, len, &cb, true); | |
3566 EXPECT_EQ(len, cb.GetResult(rv)); | |
3567 entry->Close(); | |
3568 | |
3569 // Now see that we don't use the stored entry. | |
3570 std::string headers; | |
3571 RunTransactionTestWithResponse(cache.http_cache(), kSimpleGET_Transaction, | |
3572 &headers); | |
3573 | |
3574 // We are expecting a 200. | |
3575 std::string expected_headers(kSimpleGET_Transaction.status); | |
3576 expected_headers.append("\n"); | |
3577 expected_headers.append(kSimpleGET_Transaction.response_headers); | |
3578 EXPECT_EQ(expected_headers, headers); | |
3579 EXPECT_EQ(1, cache.network_layer()->transaction_count()); | |
3580 EXPECT_EQ(1, cache.disk_cache()->open_count()); | |
3581 EXPECT_EQ(2, cache.disk_cache()->create_count()); | |
3582 } | |
3583 | |
3584 // Tests that we can handle range requests with cached 200 responses. | |
3585 TEST(HttpCache, RangeGET_Previous200) { | |
3586 MockHttpCache cache; | |
3587 | |
3588 // Store the whole thing with status 200. | |
3589 MockTransaction transaction(kTypicalGET_Transaction); | |
3590 transaction.url = kRangeGET_TransactionOK.url; | |
3591 transaction.data = "rg: 00-09 rg: 10-19 rg: 20-29 rg: 30-39 rg: 40-49 " | |
3592 "rg: 50-59 rg: 60-69 rg: 70-79 "; | |
3593 AddMockTransaction(&transaction); | |
3594 RunTransactionTest(cache.http_cache(), transaction); | |
3595 EXPECT_EQ(1, cache.network_layer()->transaction_count()); | |
3596 EXPECT_EQ(0, cache.disk_cache()->open_count()); | |
3597 EXPECT_EQ(1, cache.disk_cache()->create_count()); | |
3598 | |
3599 RemoveMockTransaction(&transaction); | |
3600 AddMockTransaction(&kRangeGET_TransactionOK); | |
3601 | |
3602 // Now see that we use the stored entry. | |
3603 std::string headers; | |
3604 MockTransaction transaction2(kRangeGET_TransactionOK); | |
3605 RangeTransactionServer handler; | |
3606 handler.set_not_modified(true); | |
3607 RunTransactionTestWithResponse(cache.http_cache(), transaction2, &headers); | |
3608 | |
3609 // We are expecting a 206. | |
3610 Verify206Response(headers, 40, 49); | |
3611 EXPECT_EQ(2, cache.network_layer()->transaction_count()); | |
3612 EXPECT_EQ(1, cache.disk_cache()->open_count()); | |
3613 EXPECT_EQ(1, cache.disk_cache()->create_count()); | |
3614 | |
3615 // The last transaction has finished so make sure the entry is deactivated. | |
3616 MessageLoop::current()->RunAllPending(); | |
3617 | |
3618 // Make a request for an invalid range. | |
3619 MockTransaction transaction3(kRangeGET_TransactionOK); | |
3620 transaction3.request_headers = "Range: bytes = 80-90\r\n" EXTRA_HEADER; | |
3621 transaction3.data = ""; | |
3622 transaction3.load_flags = net::LOAD_PREFERRING_CACHE; | |
3623 RunTransactionTestWithResponse(cache.http_cache(), transaction3, &headers); | |
3624 EXPECT_EQ(2, cache.disk_cache()->open_count()); | |
3625 EXPECT_EQ(0U, headers.find("HTTP/1.1 416 ")); | |
3626 EXPECT_NE(std::string::npos, headers.find("Content-Range: bytes 0-0/80")); | |
3627 EXPECT_NE(std::string::npos, headers.find("Content-Length: 0")); | |
3628 | |
3629 // Make sure the entry is deactivated. | |
3630 MessageLoop::current()->RunAllPending(); | |
3631 | |
3632 // Even though the request was invalid, we should have the entry. | |
3633 RunTransactionTest(cache.http_cache(), transaction2); | |
3634 EXPECT_EQ(3, cache.disk_cache()->open_count()); | |
3635 | |
3636 // Make sure the entry is deactivated. | |
3637 MessageLoop::current()->RunAllPending(); | |
3638 | |
3639 // Now we should receive a range from the server and drop the stored entry. | |
3640 handler.set_not_modified(false); | |
3641 transaction2.request_headers = kRangeGET_TransactionOK.request_headers; | |
3642 RunTransactionTestWithResponse(cache.http_cache(), transaction2, &headers); | |
3643 Verify206Response(headers, 40, 49); | |
3644 EXPECT_EQ(5, cache.network_layer()->transaction_count()); | |
3645 EXPECT_EQ(4, cache.disk_cache()->open_count()); | |
3646 EXPECT_EQ(1, cache.disk_cache()->create_count()); | |
3647 | |
3648 RunTransactionTest(cache.http_cache(), transaction2); | |
3649 EXPECT_EQ(2, cache.disk_cache()->create_count()); | |
3650 | |
3651 RemoveMockTransaction(&kRangeGET_TransactionOK); | |
3652 } | |
3653 | |
3654 // Tests that we can handle a 200 response when dealing with sparse entries. | |
3655 TEST(HttpCache, RangeRequestResultsIn200) { | |
3656 MockHttpCache cache; | |
3657 AddMockTransaction(&kRangeGET_TransactionOK); | |
3658 std::string headers; | |
3659 | |
3660 // Write to the cache (70-79). | |
3661 MockTransaction transaction(kRangeGET_TransactionOK); | |
3662 transaction.request_headers = "Range: bytes = -10\r\n" EXTRA_HEADER; | |
3663 transaction.data = "rg: 70-79 "; | |
3664 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers); | |
3665 | |
3666 Verify206Response(headers, 70, 79); | |
3667 EXPECT_EQ(1, cache.network_layer()->transaction_count()); | |
3668 EXPECT_EQ(0, cache.disk_cache()->open_count()); | |
3669 EXPECT_EQ(1, cache.disk_cache()->create_count()); | |
3670 | |
3671 // Now we'll issue a request that results in a plain 200 response, but to | |
3672 // the to the same URL that we used to store sparse data, and making sure | |
3673 // that we ask for a range. | |
3674 RemoveMockTransaction(&kRangeGET_TransactionOK); | |
3675 MockTransaction transaction2(kSimpleGET_Transaction); | |
3676 transaction2.url = kRangeGET_TransactionOK.url; | |
3677 transaction2.request_headers = kRangeGET_TransactionOK.request_headers; | |
3678 AddMockTransaction(&transaction2); | |
3679 | |
3680 RunTransactionTestWithResponse(cache.http_cache(), transaction2, &headers); | |
3681 | |
3682 std::string expected_headers(kSimpleGET_Transaction.status); | |
3683 expected_headers.append("\n"); | |
3684 expected_headers.append(kSimpleGET_Transaction.response_headers); | |
3685 EXPECT_EQ(expected_headers, headers); | |
3686 EXPECT_EQ(2, cache.network_layer()->transaction_count()); | |
3687 EXPECT_EQ(1, cache.disk_cache()->open_count()); | |
3688 EXPECT_EQ(1, cache.disk_cache()->create_count()); | |
3689 | |
3690 RemoveMockTransaction(&transaction2); | |
3691 } | |
3692 | |
3693 // Tests that a range request that falls outside of the size that we know about | |
3694 // only deletes the entry if the resource has indeed changed. | |
3695 TEST(HttpCache, RangeGET_MoreThanCurrentSize) { | |
3696 MockHttpCache cache; | |
3697 AddMockTransaction(&kRangeGET_TransactionOK); | |
3698 std::string headers; | |
3699 | |
3700 // Write to the cache (40-49). | |
3701 RunTransactionTestWithResponse(cache.http_cache(), kRangeGET_TransactionOK, | |
3702 &headers); | |
3703 | |
3704 Verify206Response(headers, 40, 49); | |
3705 EXPECT_EQ(1, cache.network_layer()->transaction_count()); | |
3706 EXPECT_EQ(0, cache.disk_cache()->open_count()); | |
3707 EXPECT_EQ(1, cache.disk_cache()->create_count()); | |
3708 | |
3709 // A weird request should not delete this entry. Ask for bytes 120-. | |
3710 MockTransaction transaction(kRangeGET_TransactionOK); | |
3711 transaction.request_headers = "Range: bytes = 120-\r\n" EXTRA_HEADER; | |
3712 transaction.data = ""; | |
3713 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers); | |
3714 | |
3715 EXPECT_EQ(0U, headers.find("HTTP/1.1 416 ")); | |
3716 EXPECT_EQ(2, cache.network_layer()->transaction_count()); | |
3717 EXPECT_EQ(1, cache.disk_cache()->open_count()); | |
3718 EXPECT_EQ(1, cache.disk_cache()->create_count()); | |
3719 | |
3720 RunTransactionTest(cache.http_cache(), kRangeGET_TransactionOK); | |
3721 EXPECT_EQ(2, cache.disk_cache()->open_count()); | |
3722 EXPECT_EQ(1, cache.disk_cache()->create_count()); | |
3723 | |
3724 RemoveMockTransaction(&kRangeGET_TransactionOK); | |
3725 } | |
3726 | |
3727 // Tests that we don't delete a sparse entry when we cancel a request. | |
3728 TEST(HttpCache, RangeGET_Cancel) { | |
3729 MockHttpCache cache; | |
3730 AddMockTransaction(&kRangeGET_TransactionOK); | |
3731 | |
3732 MockHttpRequest request(kRangeGET_TransactionOK); | |
3733 | |
3734 Context* c = new Context(); | |
3735 int rv = cache.http_cache()->CreateTransaction(&c->trans); | |
3736 EXPECT_EQ(net::OK, rv); | |
3737 | |
3738 rv = c->trans->Start(&request, &c->callback, net::BoundNetLog()); | |
3739 if (rv == net::ERR_IO_PENDING) | |
3740 rv = c->callback.WaitForResult(); | |
3741 | |
3742 EXPECT_EQ(1, cache.network_layer()->transaction_count()); | |
3743 EXPECT_EQ(0, cache.disk_cache()->open_count()); | |
3744 EXPECT_EQ(1, cache.disk_cache()->create_count()); | |
3745 | |
3746 // Make sure that the entry has some data stored. | |
3747 scoped_refptr<net::IOBufferWithSize> buf(new net::IOBufferWithSize(10)); | |
3748 rv = c->trans->Read(buf, buf->size(), &c->callback); | |
3749 if (rv == net::ERR_IO_PENDING) | |
3750 rv = c->callback.WaitForResult(); | |
3751 EXPECT_EQ(buf->size(), rv); | |
3752 | |
3753 // Destroy the transaction. | |
3754 delete c; | |
3755 | |
3756 // Verify that the entry has not been deleted. | |
3757 disk_cache::Entry* entry; | |
3758 ASSERT_TRUE(cache.OpenBackendEntry(kRangeGET_TransactionOK.url, &entry)); | |
3759 entry->Close(); | |
3760 RemoveMockTransaction(&kRangeGET_TransactionOK); | |
3761 } | |
3762 | |
3763 // Tests that we don't delete a sparse entry when we start a new request after | |
3764 // cancelling the previous one. | |
3765 TEST(HttpCache, RangeGET_Cancel2) { | |
3766 MockHttpCache cache; | |
3767 AddMockTransaction(&kRangeGET_TransactionOK); | |
3768 | |
3769 RunTransactionTest(cache.http_cache(), kRangeGET_TransactionOK); | |
3770 MockHttpRequest request(kRangeGET_TransactionOK); | |
3771 request.load_flags |= net::LOAD_VALIDATE_CACHE; | |
3772 | |
3773 Context* c = new Context(); | |
3774 int rv = cache.http_cache()->CreateTransaction(&c->trans); | |
3775 EXPECT_EQ(net::OK, rv); | |
3776 | |
3777 rv = c->trans->Start(&request, &c->callback, net::BoundNetLog()); | |
3778 if (rv == net::ERR_IO_PENDING) | |
3779 rv = c->callback.WaitForResult(); | |
3780 | |
3781 EXPECT_EQ(2, cache.network_layer()->transaction_count()); | |
3782 EXPECT_EQ(1, cache.disk_cache()->open_count()); | |
3783 EXPECT_EQ(1, cache.disk_cache()->create_count()); | |
3784 | |
3785 // Make sure that we revalidate the entry and read from the cache (a single | |
3786 // read will return while waiting for the network). | |
3787 scoped_refptr<net::IOBufferWithSize> buf(new net::IOBufferWithSize(5)); | |
3788 rv = c->trans->Read(buf, buf->size(), &c->callback); | |
3789 EXPECT_EQ(5, c->callback.GetResult(rv)); | |
3790 rv = c->trans->Read(buf, buf->size(), &c->callback); | |
3791 EXPECT_EQ(net::ERR_IO_PENDING, rv); | |
3792 | |
3793 // Destroy the transaction before completing the read. | |
3794 delete c; | |
3795 | |
3796 // We have the read and the delete (OnProcessPendingQueue) waiting on the | |
3797 // message loop. This means that a new transaction will just reuse the same | |
3798 // active entry (no open or create). | |
3799 | |
3800 RunTransactionTest(cache.http_cache(), kRangeGET_TransactionOK); | |
3801 | |
3802 EXPECT_EQ(2, cache.network_layer()->transaction_count()); | |
3803 EXPECT_EQ(1, cache.disk_cache()->open_count()); | |
3804 EXPECT_EQ(1, cache.disk_cache()->create_count()); | |
3805 RemoveMockTransaction(&kRangeGET_TransactionOK); | |
3806 } | |
3807 | |
3808 // A slight variation of the previous test, this time we cancel two requests in | |
3809 // a row, making sure that the second is waiting for the entry to be ready. | |
3810 TEST(HttpCache, RangeGET_Cancel3) { | |
3811 MockHttpCache cache; | |
3812 AddMockTransaction(&kRangeGET_TransactionOK); | |
3813 | |
3814 RunTransactionTest(cache.http_cache(), kRangeGET_TransactionOK); | |
3815 MockHttpRequest request(kRangeGET_TransactionOK); | |
3816 request.load_flags |= net::LOAD_VALIDATE_CACHE; | |
3817 | |
3818 Context* c = new Context(); | |
3819 int rv = cache.http_cache()->CreateTransaction(&c->trans); | |
3820 EXPECT_EQ(net::OK, rv); | |
3821 | |
3822 rv = c->trans->Start(&request, &c->callback, net::BoundNetLog()); | |
3823 EXPECT_EQ(net::ERR_IO_PENDING, rv); | |
3824 rv = c->callback.WaitForResult(); | |
3825 | |
3826 EXPECT_EQ(2, cache.network_layer()->transaction_count()); | |
3827 EXPECT_EQ(1, cache.disk_cache()->open_count()); | |
3828 EXPECT_EQ(1, cache.disk_cache()->create_count()); | |
3829 | |
3830 // Make sure that we revalidate the entry and read from the cache (a single | |
3831 // read will return while waiting for the network). | |
3832 scoped_refptr<net::IOBufferWithSize> buf(new net::IOBufferWithSize(5)); | |
3833 rv = c->trans->Read(buf, buf->size(), &c->callback); | |
3834 EXPECT_EQ(5, c->callback.GetResult(rv)); | |
3835 rv = c->trans->Read(buf, buf->size(), &c->callback); | |
3836 EXPECT_EQ(net::ERR_IO_PENDING, rv); | |
3837 | |
3838 // Destroy the transaction before completing the read. | |
3839 delete c; | |
3840 | |
3841 // We have the read and the delete (OnProcessPendingQueue) waiting on the | |
3842 // message loop. This means that a new transaction will just reuse the same | |
3843 // active entry (no open or create). | |
3844 | |
3845 c = new Context(); | |
3846 rv = cache.http_cache()->CreateTransaction(&c->trans); | |
3847 EXPECT_EQ(net::OK, rv); | |
3848 | |
3849 rv = c->trans->Start(&request, &c->callback, net::BoundNetLog()); | |
3850 EXPECT_EQ(net::ERR_IO_PENDING, rv); | |
3851 | |
3852 MockDiskEntry::IgnoreCallbacks(true); | |
3853 MessageLoop::current()->RunAllPending(); | |
3854 MockDiskEntry::IgnoreCallbacks(false); | |
3855 | |
3856 // The new transaction is waiting for the query range callback. | |
3857 delete c; | |
3858 | |
3859 // And we should not crash when the callback is delivered. | |
3860 MessageLoop::current()->RunAllPending(); | |
3861 | |
3862 EXPECT_EQ(2, cache.network_layer()->transaction_count()); | |
3863 EXPECT_EQ(1, cache.disk_cache()->open_count()); | |
3864 EXPECT_EQ(1, cache.disk_cache()->create_count()); | |
3865 RemoveMockTransaction(&kRangeGET_TransactionOK); | |
3866 } | |
3867 | |
3868 // Tests that an invalid range response results in no cached entry. | |
3869 TEST(HttpCache, RangeGET_InvalidResponse1) { | |
3870 MockHttpCache cache; | |
3871 std::string headers; | |
3872 | |
3873 MockTransaction transaction(kRangeGET_TransactionOK); | |
3874 transaction.handler = NULL; | |
3875 transaction.response_headers = "Content-Range: bytes 40-49/45\n" | |
3876 "Content-Length: 10\n"; | |
3877 AddMockTransaction(&transaction); | |
3878 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers); | |
3879 | |
3880 std::string expected(transaction.status); | |
3881 expected.append("\n"); | |
3882 expected.append(transaction.response_headers); | |
3883 EXPECT_EQ(expected, headers); | |
3884 | |
3885 EXPECT_EQ(1, cache.network_layer()->transaction_count()); | |
3886 EXPECT_EQ(0, cache.disk_cache()->open_count()); | |
3887 EXPECT_EQ(1, cache.disk_cache()->create_count()); | |
3888 | |
3889 // Verify that we don't have a cached entry. | |
3890 disk_cache::Entry* entry; | |
3891 EXPECT_FALSE(cache.OpenBackendEntry(kRangeGET_TransactionOK.url, &entry)); | |
3892 | |
3893 RemoveMockTransaction(&kRangeGET_TransactionOK); | |
3894 } | |
3895 | |
3896 // Tests that we reject a range that doesn't match the content-length. | |
3897 TEST(HttpCache, RangeGET_InvalidResponse2) { | |
3898 MockHttpCache cache; | |
3899 std::string headers; | |
3900 | |
3901 MockTransaction transaction(kRangeGET_TransactionOK); | |
3902 transaction.handler = NULL; | |
3903 transaction.response_headers = "Content-Range: bytes 40-49/80\n" | |
3904 "Content-Length: 20\n"; | |
3905 AddMockTransaction(&transaction); | |
3906 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers); | |
3907 | |
3908 std::string expected(transaction.status); | |
3909 expected.append("\n"); | |
3910 expected.append(transaction.response_headers); | |
3911 EXPECT_EQ(expected, headers); | |
3912 | |
3913 EXPECT_EQ(1, cache.network_layer()->transaction_count()); | |
3914 EXPECT_EQ(0, cache.disk_cache()->open_count()); | |
3915 EXPECT_EQ(1, cache.disk_cache()->create_count()); | |
3916 | |
3917 // Verify that we don't have a cached entry. | |
3918 disk_cache::Entry* entry; | |
3919 EXPECT_FALSE(cache.OpenBackendEntry(kRangeGET_TransactionOK.url, &entry)); | |
3920 | |
3921 RemoveMockTransaction(&kRangeGET_TransactionOK); | |
3922 } | |
3923 | |
3924 // Tests that if a server tells us conflicting information about a resource we | |
3925 // ignore the response. | |
3926 TEST(HttpCache, RangeGET_InvalidResponse3) { | |
3927 MockHttpCache cache; | |
3928 std::string headers; | |
3929 | |
3930 MockTransaction transaction(kRangeGET_TransactionOK); | |
3931 transaction.handler = NULL; | |
3932 transaction.request_headers = "Range: bytes = 50-59\r\n" EXTRA_HEADER; | |
3933 std::string response_headers(transaction.response_headers); | |
3934 response_headers.append("Content-Range: bytes 50-59/160\n"); | |
3935 transaction.response_headers = response_headers.c_str(); | |
3936 AddMockTransaction(&transaction); | |
3937 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers); | |
3938 | |
3939 Verify206Response(headers, 50, 59); | |
3940 EXPECT_EQ(1, cache.network_layer()->transaction_count()); | |
3941 EXPECT_EQ(0, cache.disk_cache()->open_count()); | |
3942 EXPECT_EQ(1, cache.disk_cache()->create_count()); | |
3943 | |
3944 RemoveMockTransaction(&transaction); | |
3945 AddMockTransaction(&kRangeGET_TransactionOK); | |
3946 | |
3947 // This transaction will report a resource size of 80 bytes, and we think it's | |
3948 // 160 so we should ignore the response. | |
3949 RunTransactionTestWithResponse(cache.http_cache(), kRangeGET_TransactionOK, | |
3950 &headers); | |
3951 | |
3952 Verify206Response(headers, 40, 49); | |
3953 EXPECT_EQ(2, cache.network_layer()->transaction_count()); | |
3954 EXPECT_EQ(1, cache.disk_cache()->open_count()); | |
3955 EXPECT_EQ(1, cache.disk_cache()->create_count()); | |
3956 | |
3957 // Verify that we cached the first response but not the second one. | |
3958 disk_cache::Entry* en; | |
3959 ASSERT_TRUE(cache.OpenBackendEntry(kRangeGET_TransactionOK.url, &en)); | |
3960 | |
3961 int64 cached_start = 0; | |
3962 TestOldCompletionCallback cb; | |
3963 int rv = en->GetAvailableRange(40, 20, &cached_start, &cb); | |
3964 EXPECT_EQ(10, cb.GetResult(rv)); | |
3965 EXPECT_EQ(50, cached_start); | |
3966 en->Close(); | |
3967 | |
3968 RemoveMockTransaction(&kRangeGET_TransactionOK); | |
3969 } | |
3970 | |
3971 // Tests that we handle large range values properly. | |
3972 TEST(HttpCache, RangeGET_LargeValues) { | |
3973 // We need a real sparse cache for this test. | |
3974 MockHttpCache cache(net::HttpCache::DefaultBackend::InMemory(1024 * 1024)); | |
3975 std::string headers; | |
3976 | |
3977 MockTransaction transaction(kRangeGET_TransactionOK); | |
3978 transaction.handler = NULL; | |
3979 transaction.request_headers = "Range: bytes = 4294967288-4294967297\r\n" | |
3980 EXTRA_HEADER; | |
3981 transaction.response_headers = | |
3982 "ETag: \"foo\"\n" | |
3983 "Content-Range: bytes 4294967288-4294967297/4294967299\n" | |
3984 "Content-Length: 10\n"; | |
3985 AddMockTransaction(&transaction); | |
3986 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers); | |
3987 | |
3988 std::string expected(transaction.status); | |
3989 expected.append("\n"); | |
3990 expected.append(transaction.response_headers); | |
3991 EXPECT_EQ(expected, headers); | |
3992 | |
3993 EXPECT_EQ(1, cache.network_layer()->transaction_count()); | |
3994 | |
3995 // Verify that we have a cached entry. | |
3996 disk_cache::Entry* en; | |
3997 ASSERT_TRUE(cache.OpenBackendEntry(kRangeGET_TransactionOK.url, &en)); | |
3998 en->Close(); | |
3999 | |
4000 RemoveMockTransaction(&kRangeGET_TransactionOK); | |
4001 } | |
4002 | |
4003 // Tests that we don't crash with a range request if the disk cache was not | |
4004 // initialized properly. | |
4005 TEST(HttpCache, RangeGET_NoDiskCache) { | |
4006 MockBlockingBackendFactory* factory = new MockBlockingBackendFactory(); | |
4007 factory->set_fail(true); | |
4008 factory->FinishCreation(); // We'll complete synchronously. | |
4009 MockHttpCache cache(factory); | |
4010 | |
4011 AddMockTransaction(&kRangeGET_TransactionOK); | |
4012 | |
4013 RunTransactionTest(cache.http_cache(), kRangeGET_TransactionOK); | |
4014 EXPECT_EQ(1, cache.network_layer()->transaction_count()); | |
4015 | |
4016 RemoveMockTransaction(&kRangeGET_TransactionOK); | |
4017 } | |
4018 | |
4019 // Tests that we handle byte range requests that skip the cache. | |
4020 TEST(HttpCache, RangeHEAD) { | |
4021 MockHttpCache cache; | |
4022 AddMockTransaction(&kRangeGET_TransactionOK); | |
4023 | |
4024 MockTransaction transaction(kRangeGET_TransactionOK); | |
4025 transaction.request_headers = "Range: bytes = -10\r\n" EXTRA_HEADER; | |
4026 transaction.method = "HEAD"; | |
4027 transaction.data = "rg: 70-79 "; | |
4028 | |
4029 std::string headers; | |
4030 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers); | |
4031 | |
4032 Verify206Response(headers, 70, 79); | |
4033 EXPECT_EQ(1, cache.network_layer()->transaction_count()); | |
4034 EXPECT_EQ(0, cache.disk_cache()->open_count()); | |
4035 EXPECT_EQ(0, cache.disk_cache()->create_count()); | |
4036 | |
4037 RemoveMockTransaction(&kRangeGET_TransactionOK); | |
4038 } | |
4039 | |
4040 // Tests that we don't crash when after reading from the cache we issue a | |
4041 // request for the next range and the server gives us a 200 synchronously. | |
4042 TEST(HttpCache, RangeGET_FastFlakyServer) { | |
4043 MockHttpCache cache; | |
4044 | |
4045 MockTransaction transaction(kRangeGET_TransactionOK); | |
4046 transaction.request_headers = "Range: bytes = 40-\r\n" EXTRA_HEADER; | |
4047 transaction.test_mode = TEST_MODE_SYNC_NET_START; | |
4048 transaction.load_flags |= net::LOAD_VALIDATE_CACHE; | |
4049 AddMockTransaction(&transaction); | |
4050 | |
4051 // Write to the cache. | |
4052 RunTransactionTest(cache.http_cache(), kRangeGET_TransactionOK); | |
4053 | |
4054 // And now read from the cache and the network. | |
4055 RangeTransactionServer handler; | |
4056 handler.set_bad_200(true); | |
4057 transaction.data = "Not a range"; | |
4058 RunTransactionTest(cache.http_cache(), transaction); | |
4059 | |
4060 EXPECT_EQ(3, cache.network_layer()->transaction_count()); | |
4061 EXPECT_EQ(1, cache.disk_cache()->open_count()); | |
4062 EXPECT_EQ(1, cache.disk_cache()->create_count()); | |
4063 | |
4064 RemoveMockTransaction(&transaction); | |
4065 } | |
4066 | |
4067 // Tests that when the server gives us less data than expected, we don't keep | |
4068 // asking for more data. | |
4069 TEST(HttpCache, RangeGET_FastFlakyServer2) { | |
4070 MockHttpCache cache; | |
4071 | |
4072 // First, check with an empty cache (WRITE mode). | |
4073 MockTransaction transaction(kRangeGET_TransactionOK); | |
4074 transaction.request_headers = "Range: bytes = 40-49\r\n" EXTRA_HEADER; | |
4075 transaction.data = "rg: 40-"; // Less than expected. | |
4076 transaction.handler = NULL; | |
4077 std::string headers(transaction.response_headers); | |
4078 headers.append("Content-Range: bytes 40-49/80\n"); | |
4079 transaction.response_headers = headers.c_str(); | |
4080 | |
4081 AddMockTransaction(&transaction); | |
4082 | |
4083 // Write to the cache. | |
4084 RunTransactionTest(cache.http_cache(), transaction); | |
4085 | |
4086 EXPECT_EQ(1, cache.network_layer()->transaction_count()); | |
4087 EXPECT_EQ(0, cache.disk_cache()->open_count()); | |
4088 EXPECT_EQ(1, cache.disk_cache()->create_count()); | |
4089 | |
4090 // Now verify that even in READ_WRITE mode, we forward the bad response to | |
4091 // the caller. | |
4092 transaction.request_headers = "Range: bytes = 60-69\r\n" EXTRA_HEADER; | |
4093 transaction.data = "rg: 60-"; // Less than expected. | |
4094 headers = kRangeGET_TransactionOK.response_headers; | |
4095 headers.append("Content-Range: bytes 60-69/80\n"); | |
4096 transaction.response_headers = headers.c_str(); | |
4097 | |
4098 RunTransactionTest(cache.http_cache(), transaction); | |
4099 | |
4100 EXPECT_EQ(2, cache.network_layer()->transaction_count()); | |
4101 EXPECT_EQ(1, cache.disk_cache()->open_count()); | |
4102 EXPECT_EQ(1, cache.disk_cache()->create_count()); | |
4103 | |
4104 RemoveMockTransaction(&transaction); | |
4105 } | |
4106 | |
4107 #if defined(NDEBUG) && !defined(DCHECK_ALWAYS_ON) | |
4108 // This test hits a NOTREACHED so it is a release mode only test. | |
4109 TEST(HttpCache, RangeGET_OK_LoadOnlyFromCache) { | |
4110 MockHttpCache cache; | |
4111 AddMockTransaction(&kRangeGET_TransactionOK); | |
4112 | |
4113 // Write to the cache (40-49). | |
4114 RunTransactionTest(cache.http_cache(), kRangeGET_TransactionOK); | |
4115 EXPECT_EQ(1, cache.network_layer()->transaction_count()); | |
4116 EXPECT_EQ(0, cache.disk_cache()->open_count()); | |
4117 EXPECT_EQ(1, cache.disk_cache()->create_count()); | |
4118 | |
4119 // Force this transaction to read from the cache. | |
4120 MockTransaction transaction(kRangeGET_TransactionOK); | |
4121 transaction.load_flags |= net::LOAD_ONLY_FROM_CACHE; | |
4122 | |
4123 MockHttpRequest request(transaction); | |
4124 TestOldCompletionCallback callback; | |
4125 | |
4126 scoped_ptr<net::HttpTransaction> trans; | |
4127 int rv = cache.http_cache()->CreateTransaction(&trans); | |
4128 EXPECT_EQ(net::OK, rv); | |
4129 ASSERT_TRUE(trans.get()); | |
4130 | |
4131 rv = trans->Start(&request, &callback, net::BoundNetLog()); | |
4132 if (rv == net::ERR_IO_PENDING) | |
4133 rv = callback.WaitForResult(); | |
4134 ASSERT_EQ(net::ERR_CACHE_MISS, rv); | |
4135 | |
4136 trans.reset(); | |
4137 | |
4138 EXPECT_EQ(1, cache.network_layer()->transaction_count()); | |
4139 EXPECT_EQ(1, cache.disk_cache()->open_count()); | |
4140 EXPECT_EQ(1, cache.disk_cache()->create_count()); | |
4141 | |
4142 RemoveMockTransaction(&kRangeGET_TransactionOK); | |
4143 } | |
4144 #endif | |
4145 | |
4146 // Tests the handling of the "truncation" flag. | |
4147 TEST(HttpCache, WriteResponseInfo_Truncated) { | |
4148 MockHttpCache cache; | |
4149 disk_cache::Entry* entry; | |
4150 ASSERT_TRUE(cache.CreateBackendEntry("http://www.google.com", &entry, | |
4151 NULL)); | |
4152 | |
4153 std::string headers("HTTP/1.1 200 OK"); | |
4154 headers = net::HttpUtil::AssembleRawHeaders(headers.data(), headers.size()); | |
4155 net::HttpResponseInfo response; | |
4156 response.headers = new net::HttpResponseHeaders(headers); | |
4157 | |
4158 // Set the last argument for this to be an incomplete request. | |
4159 EXPECT_TRUE(MockHttpCache::WriteResponseInfo(entry, &response, true, true)); | |
4160 bool truncated = false; | |
4161 EXPECT_TRUE(MockHttpCache::ReadResponseInfo(entry, &response, &truncated)); | |
4162 EXPECT_TRUE(truncated); | |
4163 | |
4164 // And now test the opposite case. | |
4165 EXPECT_TRUE(MockHttpCache::WriteResponseInfo(entry, &response, true, false)); | |
4166 truncated = true; | |
4167 EXPECT_TRUE(MockHttpCache::ReadResponseInfo(entry, &response, &truncated)); | |
4168 EXPECT_FALSE(truncated); | |
4169 entry->Close(); | |
4170 } | |
4171 | |
4172 // Tests basic pickling/unpickling of HttpResponseInfo. | |
4173 TEST(HttpCache, PersistHttpResponseInfo) { | |
4174 // Set some fields (add more if needed.) | |
4175 net::HttpResponseInfo response1; | |
4176 response1.was_cached = false; | |
4177 response1.socket_address = net::HostPortPair("1.2.3.4", 80); | |
4178 response1.headers = new net::HttpResponseHeaders("HTTP/1.1 200 OK"); | |
4179 | |
4180 // Pickle. | |
4181 Pickle pickle; | |
4182 response1.Persist(&pickle, false, false); | |
4183 | |
4184 // Unpickle. | |
4185 net::HttpResponseInfo response2; | |
4186 bool response_truncated; | |
4187 EXPECT_TRUE(response2.InitFromPickle(pickle, &response_truncated)); | |
4188 EXPECT_FALSE(response_truncated); | |
4189 | |
4190 // Verify fields. | |
4191 EXPECT_TRUE(response2.was_cached); // InitFromPickle sets this flag. | |
4192 EXPECT_EQ("1.2.3.4", response2.socket_address.host()); | |
4193 EXPECT_EQ(80, response2.socket_address.port()); | |
4194 EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine()); | |
4195 } | |
4196 | |
4197 // Tests that we delete an entry when the request is cancelled before starting | |
4198 // to read from the network. | |
4199 TEST(HttpCache, DoomOnDestruction) { | |
4200 MockHttpCache cache; | |
4201 | |
4202 MockHttpRequest request(kSimpleGET_Transaction); | |
4203 | |
4204 Context* c = new Context(); | |
4205 int rv = cache.http_cache()->CreateTransaction(&c->trans); | |
4206 EXPECT_EQ(net::OK, rv); | |
4207 | |
4208 rv = c->trans->Start(&request, &c->callback, net::BoundNetLog()); | |
4209 if (rv == net::ERR_IO_PENDING) | |
4210 c->result = c->callback.WaitForResult(); | |
4211 | |
4212 EXPECT_EQ(1, cache.network_layer()->transaction_count()); | |
4213 EXPECT_EQ(0, cache.disk_cache()->open_count()); | |
4214 EXPECT_EQ(1, cache.disk_cache()->create_count()); | |
4215 | |
4216 // Destroy the transaction. We only have the headers so we should delete this | |
4217 // entry. | |
4218 delete c; | |
4219 | |
4220 RunTransactionTest(cache.http_cache(), kSimpleGET_Transaction); | |
4221 | |
4222 EXPECT_EQ(2, cache.network_layer()->transaction_count()); | |
4223 EXPECT_EQ(0, cache.disk_cache()->open_count()); | |
4224 EXPECT_EQ(2, cache.disk_cache()->create_count()); | |
4225 } | |
4226 | |
4227 // Tests that we delete an entry when the request is cancelled if the response | |
4228 // does not have content-length and strong validators. | |
4229 TEST(HttpCache, DoomOnDestruction2) { | |
4230 MockHttpCache cache; | |
4231 | |
4232 MockHttpRequest request(kSimpleGET_Transaction); | |
4233 | |
4234 Context* c = new Context(); | |
4235 int rv = cache.http_cache()->CreateTransaction(&c->trans); | |
4236 EXPECT_EQ(net::OK, rv); | |
4237 | |
4238 rv = c->trans->Start(&request, &c->callback, net::BoundNetLog()); | |
4239 if (rv == net::ERR_IO_PENDING) | |
4240 rv = c->callback.WaitForResult(); | |
4241 | |
4242 EXPECT_EQ(1, cache.network_layer()->transaction_count()); | |
4243 EXPECT_EQ(0, cache.disk_cache()->open_count()); | |
4244 EXPECT_EQ(1, cache.disk_cache()->create_count()); | |
4245 | |
4246 // Make sure that the entry has some data stored. | |
4247 scoped_refptr<net::IOBufferWithSize> buf(new net::IOBufferWithSize(10)); | |
4248 rv = c->trans->Read(buf, buf->size(), &c->callback); | |
4249 if (rv == net::ERR_IO_PENDING) | |
4250 rv = c->callback.WaitForResult(); | |
4251 EXPECT_EQ(buf->size(), rv); | |
4252 | |
4253 // Destroy the transaction. | |
4254 delete c; | |
4255 | |
4256 RunTransactionTest(cache.http_cache(), kSimpleGET_Transaction); | |
4257 | |
4258 EXPECT_EQ(2, cache.network_layer()->transaction_count()); | |
4259 EXPECT_EQ(0, cache.disk_cache()->open_count()); | |
4260 EXPECT_EQ(2, cache.disk_cache()->create_count()); | |
4261 } | |
4262 | |
4263 // Tests that we delete an entry when the request is cancelled if the response | |
4264 // has an "Accept-Ranges: none" header. | |
4265 TEST(HttpCache, DoomOnDestruction3) { | |
4266 MockHttpCache cache; | |
4267 | |
4268 MockTransaction transaction(kSimpleGET_Transaction); | |
4269 transaction.response_headers = | |
4270 "Last-Modified: Wed, 28 Nov 2007 00:40:09 GMT\n" | |
4271 "Content-Length: 22\n" | |
4272 "Accept-Ranges: none\n" | |
4273 "Etag: foopy\n"; | |
4274 AddMockTransaction(&transaction); | |
4275 MockHttpRequest request(transaction); | |
4276 | |
4277 Context* c = new Context(); | |
4278 int rv = cache.http_cache()->CreateTransaction(&c->trans); | |
4279 EXPECT_EQ(net::OK, rv); | |
4280 | |
4281 rv = c->trans->Start(&request, &c->callback, net::BoundNetLog()); | |
4282 if (rv == net::ERR_IO_PENDING) | |
4283 rv = c->callback.WaitForResult(); | |
4284 | |
4285 EXPECT_EQ(1, cache.network_layer()->transaction_count()); | |
4286 EXPECT_EQ(0, cache.disk_cache()->open_count()); | |
4287 EXPECT_EQ(1, cache.disk_cache()->create_count()); | |
4288 | |
4289 // Make sure that the entry has some data stored. | |
4290 scoped_refptr<net::IOBufferWithSize> buf(new net::IOBufferWithSize(10)); | |
4291 rv = c->trans->Read(buf, buf->size(), &c->callback); | |
4292 if (rv == net::ERR_IO_PENDING) | |
4293 rv = c->callback.WaitForResult(); | |
4294 EXPECT_EQ(buf->size(), rv); | |
4295 | |
4296 // Destroy the transaction. | |
4297 delete c; | |
4298 | |
4299 RunTransactionTest(cache.http_cache(), kSimpleGET_Transaction); | |
4300 | |
4301 EXPECT_EQ(2, cache.network_layer()->transaction_count()); | |
4302 EXPECT_EQ(0, cache.disk_cache()->open_count()); | |
4303 EXPECT_EQ(2, cache.disk_cache()->create_count()); | |
4304 | |
4305 RemoveMockTransaction(&transaction); | |
4306 } | |
4307 | |
4308 // Tests that we mark an entry as incomplete when the request is cancelled. | |
4309 TEST(HttpCache, SetTruncatedFlag) { | |
4310 MockHttpCache cache; | |
4311 | |
4312 MockTransaction transaction(kSimpleGET_Transaction); | |
4313 transaction.response_headers = | |
4314 "Last-Modified: Wed, 28 Nov 2007 00:40:09 GMT\n" | |
4315 "Content-Length: 22\n" | |
4316 "Etag: foopy\n"; | |
4317 AddMockTransaction(&transaction); | |
4318 MockHttpRequest request(transaction); | |
4319 | |
4320 scoped_ptr<Context> c(new Context()); | |
4321 int rv = cache.http_cache()->CreateTransaction(&c->trans); | |
4322 EXPECT_EQ(net::OK, rv); | |
4323 | |
4324 rv = c->trans->Start(&request, &c->callback, net::BoundNetLog()); | |
4325 if (rv == net::ERR_IO_PENDING) | |
4326 rv = c->callback.WaitForResult(); | |
4327 | |
4328 EXPECT_EQ(1, cache.network_layer()->transaction_count()); | |
4329 EXPECT_EQ(0, cache.disk_cache()->open_count()); | |
4330 EXPECT_EQ(1, cache.disk_cache()->create_count()); | |
4331 | |
4332 // Make sure that the entry has some data stored. | |
4333 scoped_refptr<net::IOBufferWithSize> buf(new net::IOBufferWithSize(10)); | |
4334 rv = c->trans->Read(buf, buf->size(), &c->callback); | |
4335 if (rv == net::ERR_IO_PENDING) | |
4336 rv = c->callback.WaitForResult(); | |
4337 EXPECT_EQ(buf->size(), rv); | |
4338 | |
4339 // We want to cancel the request when the transaction is busy. | |
4340 rv = c->trans->Read(buf, buf->size(), &c->callback); | |
4341 EXPECT_EQ(net::ERR_IO_PENDING, rv); | |
4342 EXPECT_FALSE(c->callback.have_result()); | |
4343 | |
4344 g_test_mode = TEST_MODE_SYNC_ALL; | |
4345 | |
4346 // Destroy the transaction. | |
4347 c->trans.reset(); | |
4348 g_test_mode = 0; | |
4349 | |
4350 // Make sure that we don't invoke the callback. We may have an issue if the | |
4351 // UrlRequestJob is killed directly (without cancelling the UrlRequest) so we | |
4352 // could end up with the transaction being deleted twice if we send any | |
4353 // notification from the transaction destructor (see http://crbug.com/31723). | |
4354 EXPECT_FALSE(c->callback.have_result()); | |
4355 | |
4356 // Verify that the entry is marked as incomplete. | |
4357 disk_cache::Entry* entry; | |
4358 ASSERT_TRUE(cache.OpenBackendEntry(kSimpleGET_Transaction.url, &entry)); | |
4359 net::HttpResponseInfo response; | |
4360 bool truncated = false; | |
4361 EXPECT_TRUE(MockHttpCache::ReadResponseInfo(entry, &response, &truncated)); | |
4362 EXPECT_TRUE(truncated); | |
4363 entry->Close(); | |
4364 | |
4365 RemoveMockTransaction(&transaction); | |
4366 } | |
4367 | |
4368 // Tests that we don't mark an entry as truncated when we read everything. | |
4369 TEST(HttpCache, DontSetTruncatedFlag) { | |
4370 MockHttpCache cache; | |
4371 | |
4372 MockTransaction transaction(kSimpleGET_Transaction); | |
4373 transaction.response_headers = | |
4374 "Last-Modified: Wed, 28 Nov 2007 00:40:09 GMT\n" | |
4375 "Content-Length: 22\n" | |
4376 "Etag: foopy\n"; | |
4377 AddMockTransaction(&transaction); | |
4378 MockHttpRequest request(transaction); | |
4379 | |
4380 scoped_ptr<Context> c(new Context()); | |
4381 int rv = cache.http_cache()->CreateTransaction(&c->trans); | |
4382 EXPECT_EQ(net::OK, rv); | |
4383 | |
4384 rv = c->trans->Start(&request, &c->callback, net::BoundNetLog()); | |
4385 EXPECT_EQ(net::OK, c->callback.GetResult(rv)); | |
4386 | |
4387 // Read everything. | |
4388 scoped_refptr<net::IOBufferWithSize> buf(new net::IOBufferWithSize(22)); | |
4389 rv = c->trans->Read(buf, buf->size(), &c->callback); | |
4390 EXPECT_EQ(buf->size(), c->callback.GetResult(rv)); | |
4391 | |
4392 // Destroy the transaction. | |
4393 c->trans.reset(); | |
4394 | |
4395 // Verify that the entry is not marked as truncated. | |
4396 disk_cache::Entry* entry; | |
4397 ASSERT_TRUE(cache.OpenBackendEntry(kSimpleGET_Transaction.url, &entry)); | |
4398 net::HttpResponseInfo response; | |
4399 bool truncated = true; | |
4400 EXPECT_TRUE(MockHttpCache::ReadResponseInfo(entry, &response, &truncated)); | |
4401 EXPECT_FALSE(truncated); | |
4402 entry->Close(); | |
4403 | |
4404 RemoveMockTransaction(&transaction); | |
4405 } | |
4406 | |
4407 // Tests that we can continue with a request that was interrupted. | |
4408 TEST(HttpCache, GET_IncompleteResource) { | |
4409 MockHttpCache cache; | |
4410 AddMockTransaction(&kRangeGET_TransactionOK); | |
4411 | |
4412 std::string raw_headers("HTTP/1.1 200 OK\n" | |
4413 "Last-Modified: Sat, 18 Apr 2007 01:10:43 GMT\n" | |
4414 "ETag: \"foo\"\n" | |
4415 "Accept-Ranges: bytes\n" | |
4416 "Content-Length: 80\n"); | |
4417 CreateTruncatedEntry(raw_headers, &cache); | |
4418 | |
4419 // Now make a regular request. | |
4420 std::string headers; | |
4421 MockTransaction transaction(kRangeGET_TransactionOK); | |
4422 transaction.request_headers = EXTRA_HEADER; | |
4423 transaction.data = "rg: 00-09 rg: 10-19 rg: 20-29 rg: 30-39 rg: 40-49 " | |
4424 "rg: 50-59 rg: 60-69 rg: 70-79 "; | |
4425 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers); | |
4426 | |
4427 // We update the headers with the ones received while revalidating. | |
4428 std::string expected_headers( | |
4429 "HTTP/1.1 200 OK\n" | |
4430 "Last-Modified: Sat, 18 Apr 2007 01:10:43 GMT\n" | |
4431 "Accept-Ranges: bytes\n" | |
4432 "ETag: \"foo\"\n" | |
4433 "Content-Length: 80\n"); | |
4434 | |
4435 EXPECT_EQ(expected_headers, headers); | |
4436 EXPECT_EQ(2, cache.network_layer()->transaction_count()); | |
4437 EXPECT_EQ(1, cache.disk_cache()->open_count()); | |
4438 EXPECT_EQ(1, cache.disk_cache()->create_count()); | |
4439 | |
4440 // Verify that the disk entry was updated. | |
4441 disk_cache::Entry* entry; | |
4442 ASSERT_TRUE(cache.OpenBackendEntry(kRangeGET_TransactionOK.url, &entry)); | |
4443 EXPECT_EQ(80, entry->GetDataSize(1)); | |
4444 bool truncated = true; | |
4445 net::HttpResponseInfo response; | |
4446 EXPECT_TRUE(MockHttpCache::ReadResponseInfo(entry, &response, &truncated)); | |
4447 EXPECT_FALSE(truncated); | |
4448 entry->Close(); | |
4449 | |
4450 RemoveMockTransaction(&kRangeGET_TransactionOK); | |
4451 } | |
4452 | |
4453 // Tests that we delete truncated entries if the server changes its mind midway. | |
4454 TEST(HttpCache, GET_IncompleteResource2) { | |
4455 MockHttpCache cache; | |
4456 AddMockTransaction(&kRangeGET_TransactionOK); | |
4457 | |
4458 // Content-length will be intentionally bad. | |
4459 std::string raw_headers("HTTP/1.1 200 OK\n" | |
4460 "Last-Modified: Sat, 18 Apr 2007 01:10:43 GMT\n" | |
4461 "ETag: \"foo\"\n" | |
4462 "Accept-Ranges: bytes\n" | |
4463 "Content-Length: 50\n"); | |
4464 CreateTruncatedEntry(raw_headers, &cache); | |
4465 | |
4466 // Now make a regular request. We expect the code to fail the validation and | |
4467 // retry the request without using byte ranges. | |
4468 std::string headers; | |
4469 MockTransaction transaction(kRangeGET_TransactionOK); | |
4470 transaction.request_headers = EXTRA_HEADER; | |
4471 transaction.data = "Not a range"; | |
4472 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers); | |
4473 | |
4474 // The server will return 200 instead of a byte range. | |
4475 std::string expected_headers( | |
4476 "HTTP/1.1 200 OK\n" | |
4477 "Date: Wed, 28 Nov 2007 09:40:09 GMT\n"); | |
4478 | |
4479 EXPECT_EQ(expected_headers, headers); | |
4480 EXPECT_EQ(2, cache.network_layer()->transaction_count()); | |
4481 EXPECT_EQ(1, cache.disk_cache()->open_count()); | |
4482 EXPECT_EQ(1, cache.disk_cache()->create_count()); | |
4483 | |
4484 // Verify that the disk entry was deleted. | |
4485 disk_cache::Entry* entry; | |
4486 ASSERT_FALSE(cache.OpenBackendEntry(kRangeGET_TransactionOK.url, &entry)); | |
4487 RemoveMockTransaction(&kRangeGET_TransactionOK); | |
4488 } | |
4489 | |
4490 // Tests that we always validate a truncated request. | |
4491 TEST(HttpCache, GET_IncompleteResource3) { | |
4492 MockHttpCache cache; | |
4493 AddMockTransaction(&kRangeGET_TransactionOK); | |
4494 | |
4495 // This should not require validation for 10 hours. | |
4496 std::string raw_headers("HTTP/1.1 200 OK\n" | |
4497 "Last-Modified: Sat, 18 Apr 2009 01:10:43 GMT\n" | |
4498 "ETag: \"foo\"\n" | |
4499 "Cache-Control: max-age= 36000\n" | |
4500 "Accept-Ranges: bytes\n" | |
4501 "Content-Length: 80\n"); | |
4502 CreateTruncatedEntry(raw_headers, &cache); | |
4503 | |
4504 // Now make a regular request. | |
4505 std::string headers; | |
4506 MockTransaction transaction(kRangeGET_TransactionOK); | |
4507 transaction.request_headers = EXTRA_HEADER; | |
4508 transaction.data = "rg: 00-09 rg: 10-19 rg: 20-29 rg: 30-39 rg: 40-49 " | |
4509 "rg: 50-59 rg: 60-69 rg: 70-79 "; | |
4510 | |
4511 scoped_ptr<Context> c(new Context); | |
4512 EXPECT_EQ(net::OK, cache.http_cache()->CreateTransaction(&c->trans)); | |
4513 | |
4514 MockHttpRequest request(transaction); | |
4515 int rv = c->trans->Start(&request, &c->callback, net::BoundNetLog()); | |
4516 EXPECT_EQ(net::OK, c->callback.GetResult(rv)); | |
4517 | |
4518 // We should have checked with the server before finishing Start(). | |
4519 EXPECT_EQ(1, cache.network_layer()->transaction_count()); | |
4520 EXPECT_EQ(1, cache.disk_cache()->open_count()); | |
4521 EXPECT_EQ(1, cache.disk_cache()->create_count()); | |
4522 | |
4523 RemoveMockTransaction(&kRangeGET_TransactionOK); | |
4524 } | |
4525 | |
4526 // Tests that we cache a 200 response to the validation request. | |
4527 TEST(HttpCache, GET_IncompleteResource4) { | |
4528 MockHttpCache cache; | |
4529 AddMockTransaction(&kRangeGET_TransactionOK); | |
4530 | |
4531 std::string raw_headers("HTTP/1.1 200 OK\n" | |
4532 "Last-Modified: Sat, 18 Apr 2009 01:10:43 GMT\n" | |
4533 "ETag: \"foo\"\n" | |
4534 "Accept-Ranges: bytes\n" | |
4535 "Content-Length: 80\n"); | |
4536 CreateTruncatedEntry(raw_headers, &cache); | |
4537 | |
4538 // Now make a regular request. | |
4539 std::string headers; | |
4540 MockTransaction transaction(kRangeGET_TransactionOK); | |
4541 transaction.request_headers = EXTRA_HEADER; | |
4542 transaction.data = "Not a range"; | |
4543 RangeTransactionServer handler; | |
4544 handler.set_bad_200(true); | |
4545 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers); | |
4546 | |
4547 EXPECT_EQ(1, cache.network_layer()->transaction_count()); | |
4548 EXPECT_EQ(1, cache.disk_cache()->open_count()); | |
4549 EXPECT_EQ(1, cache.disk_cache()->create_count()); | |
4550 | |
4551 // Verify that the disk entry was updated. | |
4552 disk_cache::Entry* entry; | |
4553 ASSERT_TRUE(cache.OpenBackendEntry(kRangeGET_TransactionOK.url, &entry)); | |
4554 EXPECT_EQ(11, entry->GetDataSize(1)); | |
4555 bool truncated = true; | |
4556 net::HttpResponseInfo response; | |
4557 EXPECT_TRUE(MockHttpCache::ReadResponseInfo(entry, &response, &truncated)); | |
4558 EXPECT_FALSE(truncated); | |
4559 entry->Close(); | |
4560 | |
4561 RemoveMockTransaction(&kRangeGET_TransactionOK); | |
4562 } | |
4563 | |
4564 // Tests that when we cancel a request that was interrupted, we mark it again | |
4565 // as truncated. | |
4566 TEST(HttpCache, GET_CancelIncompleteResource) { | |
4567 MockHttpCache cache; | |
4568 AddMockTransaction(&kRangeGET_TransactionOK); | |
4569 | |
4570 std::string raw_headers("HTTP/1.1 200 OK\n" | |
4571 "Last-Modified: Sat, 18 Apr 2009 01:10:43 GMT\n" | |
4572 "ETag: \"foo\"\n" | |
4573 "Accept-Ranges: bytes\n" | |
4574 "Content-Length: 80\n"); | |
4575 CreateTruncatedEntry(raw_headers, &cache); | |
4576 | |
4577 // Now make a regular request. | |
4578 MockTransaction transaction(kRangeGET_TransactionOK); | |
4579 transaction.request_headers = EXTRA_HEADER; | |
4580 | |
4581 MockHttpRequest request(transaction); | |
4582 Context* c = new Context(); | |
4583 EXPECT_EQ(net::OK, cache.http_cache()->CreateTransaction(&c->trans)); | |
4584 | |
4585 int rv = c->trans->Start(&request, &c->callback, net::BoundNetLog()); | |
4586 EXPECT_EQ(net::OK, c->callback.GetResult(rv)); | |
4587 | |
4588 // Read 20 bytes from the cache, and 10 from the net. | |
4589 scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(100)); | |
4590 rv = c->trans->Read(buf, 20, &c->callback); | |
4591 EXPECT_EQ(20, c->callback.GetResult(rv)); | |
4592 rv = c->trans->Read(buf, 10, &c->callback); | |
4593 EXPECT_EQ(10, c->callback.GetResult(rv)); | |
4594 | |
4595 // At this point, we are already reading so canceling the request should leave | |
4596 // a truncated one. | |
4597 delete c; | |
4598 | |
4599 EXPECT_EQ(2, cache.network_layer()->transaction_count()); | |
4600 EXPECT_EQ(1, cache.disk_cache()->open_count()); | |
4601 EXPECT_EQ(1, cache.disk_cache()->create_count()); | |
4602 | |
4603 // Verify that the disk entry was updated: now we have 30 bytes. | |
4604 disk_cache::Entry* entry; | |
4605 ASSERT_TRUE(cache.OpenBackendEntry(kRangeGET_TransactionOK.url, &entry)); | |
4606 EXPECT_EQ(30, entry->GetDataSize(1)); | |
4607 bool truncated = false; | |
4608 net::HttpResponseInfo response; | |
4609 EXPECT_TRUE(MockHttpCache::ReadResponseInfo(entry, &response, &truncated)); | |
4610 EXPECT_TRUE(truncated); | |
4611 entry->Close(); | |
4612 RemoveMockTransaction(&kRangeGET_TransactionOK); | |
4613 } | |
4614 | |
4615 // Tests that we can handle range requests when we have a truncated entry. | |
4616 TEST(HttpCache, RangeGET_IncompleteResource) { | |
4617 MockHttpCache cache; | |
4618 AddMockTransaction(&kRangeGET_TransactionOK); | |
4619 | |
4620 // Content-length will be intentionally bogus. | |
4621 std::string raw_headers("HTTP/1.1 200 OK\n" | |
4622 "Last-Modified: something\n" | |
4623 "ETag: \"foo\"\n" | |
4624 "Accept-Ranges: bytes\n" | |
4625 "Content-Length: 10\n"); | |
4626 CreateTruncatedEntry(raw_headers, &cache); | |
4627 | |
4628 // Now make a range request. | |
4629 std::string headers; | |
4630 RunTransactionTestWithResponse(cache.http_cache(), kRangeGET_TransactionOK, | |
4631 &headers); | |
4632 | |
4633 Verify206Response(headers, 40, 49); | |
4634 EXPECT_EQ(1, cache.network_layer()->transaction_count()); | |
4635 EXPECT_EQ(1, cache.disk_cache()->open_count()); | |
4636 EXPECT_EQ(2, cache.disk_cache()->create_count()); | |
4637 | |
4638 RemoveMockTransaction(&kRangeGET_TransactionOK); | |
4639 } | |
4640 | |
4641 TEST(HttpCache, SyncRead) { | |
4642 MockHttpCache cache; | |
4643 | |
4644 // This test ensures that a read that completes synchronously does not cause | |
4645 // any problems. | |
4646 | |
4647 ScopedMockTransaction transaction(kSimpleGET_Transaction); | |
4648 transaction.test_mode |= (TEST_MODE_SYNC_CACHE_START | | |
4649 TEST_MODE_SYNC_CACHE_READ | | |
4650 TEST_MODE_SYNC_CACHE_WRITE); | |
4651 | |
4652 MockHttpRequest r1(transaction), | |
4653 r2(transaction), | |
4654 r3(transaction); | |
4655 | |
4656 TestTransactionConsumer c1(cache.http_cache()), | |
4657 c2(cache.http_cache()), | |
4658 c3(cache.http_cache()); | |
4659 | |
4660 c1.Start(&r1, net::BoundNetLog()); | |
4661 | |
4662 r2.load_flags |= net::LOAD_ONLY_FROM_CACHE; | |
4663 c2.Start(&r2, net::BoundNetLog()); | |
4664 | |
4665 r3.load_flags |= net::LOAD_ONLY_FROM_CACHE; | |
4666 c3.Start(&r3, net::BoundNetLog()); | |
4667 | |
4668 MessageLoop::current()->Run(); | |
4669 | |
4670 EXPECT_TRUE(c1.is_done()); | |
4671 EXPECT_TRUE(c2.is_done()); | |
4672 EXPECT_TRUE(c3.is_done()); | |
4673 | |
4674 EXPECT_EQ(net::OK, c1.error()); | |
4675 EXPECT_EQ(net::OK, c2.error()); | |
4676 EXPECT_EQ(net::OK, c3.error()); | |
4677 } | |
4678 | |
4679 TEST(HttpCache, ValidationResultsIn200) { | |
4680 MockHttpCache cache; | |
4681 | |
4682 // This test ensures that a conditional request, which results in a 200 | |
4683 // instead of a 304, properly truncates the existing response data. | |
4684 | |
4685 // write to the cache | |
4686 RunTransactionTest(cache.http_cache(), kETagGET_Transaction); | |
4687 | |
4688 // force this transaction to validate the cache | |
4689 MockTransaction transaction(kETagGET_Transaction); | |
4690 transaction.load_flags |= net::LOAD_VALIDATE_CACHE; | |
4691 RunTransactionTest(cache.http_cache(), transaction); | |
4692 | |
4693 // read from the cache | |
4694 RunTransactionTest(cache.http_cache(), kETagGET_Transaction); | |
4695 } | |
4696 | |
4697 TEST(HttpCache, CachedRedirect) { | |
4698 MockHttpCache cache; | |
4699 | |
4700 ScopedMockTransaction kTestTransaction(kSimpleGET_Transaction); | |
4701 kTestTransaction.status = "HTTP/1.1 301 Moved Permanently"; | |
4702 kTestTransaction.response_headers = "Location: http://www.bar.com/\n"; | |
4703 | |
4704 MockHttpRequest request(kTestTransaction); | |
4705 TestOldCompletionCallback callback; | |
4706 | |
4707 // write to the cache | |
4708 { | |
4709 scoped_ptr<net::HttpTransaction> trans; | |
4710 int rv = cache.http_cache()->CreateTransaction(&trans); | |
4711 EXPECT_EQ(net::OK, rv); | |
4712 ASSERT_TRUE(trans.get()); | |
4713 | |
4714 rv = trans->Start(&request, &callback, net::BoundNetLog()); | |
4715 if (rv == net::ERR_IO_PENDING) | |
4716 rv = callback.WaitForResult(); | |
4717 ASSERT_EQ(net::OK, rv); | |
4718 | |
4719 const net::HttpResponseInfo* info = trans->GetResponseInfo(); | |
4720 ASSERT_TRUE(info); | |
4721 | |
4722 EXPECT_EQ(info->headers->response_code(), 301); | |
4723 | |
4724 std::string location; | |
4725 info->headers->EnumerateHeader(NULL, "Location", &location); | |
4726 EXPECT_EQ(location, "http://www.bar.com/"); | |
4727 | |
4728 // Destroy transaction when going out of scope. We have not actually | |
4729 // read the response body -- want to test that it is still getting cached. | |
4730 } | |
4731 EXPECT_EQ(1, cache.network_layer()->transaction_count()); | |
4732 EXPECT_EQ(0, cache.disk_cache()->open_count()); | |
4733 EXPECT_EQ(1, cache.disk_cache()->create_count()); | |
4734 | |
4735 // read from the cache | |
4736 { | |
4737 scoped_ptr<net::HttpTransaction> trans; | |
4738 int rv = cache.http_cache()->CreateTransaction(&trans); | |
4739 EXPECT_EQ(net::OK, rv); | |
4740 ASSERT_TRUE(trans.get()); | |
4741 | |
4742 rv = trans->Start(&request, &callback, net::BoundNetLog()); | |
4743 if (rv == net::ERR_IO_PENDING) | |
4744 rv = callback.WaitForResult(); | |
4745 ASSERT_EQ(net::OK, rv); | |
4746 | |
4747 const net::HttpResponseInfo* info = trans->GetResponseInfo(); | |
4748 ASSERT_TRUE(info); | |
4749 | |
4750 EXPECT_EQ(info->headers->response_code(), 301); | |
4751 | |
4752 std::string location; | |
4753 info->headers->EnumerateHeader(NULL, "Location", &location); | |
4754 EXPECT_EQ(location, "http://www.bar.com/"); | |
4755 | |
4756 // Destroy transaction when going out of scope. We have not actually | |
4757 // read the response body -- want to test that it is still getting cached. | |
4758 } | |
4759 EXPECT_EQ(1, cache.network_layer()->transaction_count()); | |
4760 EXPECT_EQ(1, cache.disk_cache()->open_count()); | |
4761 EXPECT_EQ(1, cache.disk_cache()->create_count()); | |
4762 } | |
4763 | |
4764 TEST(HttpCache, CacheControlNoStore) { | |
4765 MockHttpCache cache; | |
4766 | |
4767 ScopedMockTransaction transaction(kSimpleGET_Transaction); | |
4768 transaction.response_headers = "cache-control: no-store\n"; | |
4769 | |
4770 // initial load | |
4771 RunTransactionTest(cache.http_cache(), transaction); | |
4772 | |
4773 EXPECT_EQ(1, cache.network_layer()->transaction_count()); | |
4774 EXPECT_EQ(0, cache.disk_cache()->open_count()); | |
4775 EXPECT_EQ(1, cache.disk_cache()->create_count()); | |
4776 | |
4777 // try loading again; it should result in a network fetch | |
4778 RunTransactionTest(cache.http_cache(), transaction); | |
4779 | |
4780 EXPECT_EQ(2, cache.network_layer()->transaction_count()); | |
4781 EXPECT_EQ(0, cache.disk_cache()->open_count()); | |
4782 EXPECT_EQ(2, cache.disk_cache()->create_count()); | |
4783 | |
4784 disk_cache::Entry* entry; | |
4785 EXPECT_FALSE(cache.OpenBackendEntry(transaction.url, &entry)); | |
4786 } | |
4787 | |
4788 TEST(HttpCache, CacheControlNoStore2) { | |
4789 // this test is similar to the above test, except that the initial response | |
4790 // is cachable, but when it is validated, no-store is received causing the | |
4791 // cached document to be deleted. | |
4792 MockHttpCache cache; | |
4793 | |
4794 ScopedMockTransaction transaction(kETagGET_Transaction); | |
4795 | |
4796 // initial load | |
4797 RunTransactionTest(cache.http_cache(), transaction); | |
4798 | |
4799 EXPECT_EQ(1, cache.network_layer()->transaction_count()); | |
4800 EXPECT_EQ(0, cache.disk_cache()->open_count()); | |
4801 EXPECT_EQ(1, cache.disk_cache()->create_count()); | |
4802 | |
4803 // try loading again; it should result in a network fetch | |
4804 transaction.load_flags = net::LOAD_VALIDATE_CACHE; | |
4805 transaction.response_headers = "cache-control: no-store\n"; | |
4806 RunTransactionTest(cache.http_cache(), transaction); | |
4807 | |
4808 EXPECT_EQ(2, cache.network_layer()->transaction_count()); | |
4809 EXPECT_EQ(1, cache.disk_cache()->open_count()); | |
4810 EXPECT_EQ(1, cache.disk_cache()->create_count()); | |
4811 | |
4812 disk_cache::Entry* entry; | |
4813 EXPECT_FALSE(cache.OpenBackendEntry(transaction.url, &entry)); | |
4814 } | |
4815 | |
4816 TEST(HttpCache, CacheControlNoStore3) { | |
4817 // this test is similar to the above test, except that the response is a 304 | |
4818 // instead of a 200. this should never happen in practice, but it seems like | |
4819 // a good thing to verify that we still destroy the cache entry. | |
4820 MockHttpCache cache; | |
4821 | |
4822 ScopedMockTransaction transaction(kETagGET_Transaction); | |
4823 | |
4824 // initial load | |
4825 RunTransactionTest(cache.http_cache(), transaction); | |
4826 | |
4827 EXPECT_EQ(1, cache.network_layer()->transaction_count()); | |
4828 EXPECT_EQ(0, cache.disk_cache()->open_count()); | |
4829 EXPECT_EQ(1, cache.disk_cache()->create_count()); | |
4830 | |
4831 // try loading again; it should result in a network fetch | |
4832 transaction.load_flags = net::LOAD_VALIDATE_CACHE; | |
4833 transaction.response_headers = "cache-control: no-store\n"; | |
4834 transaction.status = "HTTP/1.1 304 Not Modified"; | |
4835 RunTransactionTest(cache.http_cache(), transaction); | |
4836 | |
4837 EXPECT_EQ(2, cache.network_layer()->transaction_count()); | |
4838 EXPECT_EQ(1, cache.disk_cache()->open_count()); | |
4839 EXPECT_EQ(1, cache.disk_cache()->create_count()); | |
4840 | |
4841 disk_cache::Entry* entry; | |
4842 EXPECT_FALSE(cache.OpenBackendEntry(transaction.url, &entry)); | |
4843 } | |
4844 | |
4845 // Ensure that we don't cache requests served over bad HTTPS. | |
4846 TEST(HttpCache, SimpleGET_SSLError) { | |
4847 MockHttpCache cache; | |
4848 | |
4849 MockTransaction transaction = kSimpleGET_Transaction; | |
4850 transaction.cert_status = net::CERT_STATUS_REVOKED; | |
4851 ScopedMockTransaction scoped_transaction(transaction); | |
4852 | |
4853 // write to the cache | |
4854 RunTransactionTest(cache.http_cache(), transaction); | |
4855 | |
4856 // Test that it was not cached. | |
4857 transaction.load_flags |= net::LOAD_ONLY_FROM_CACHE; | |
4858 | |
4859 MockHttpRequest request(transaction); | |
4860 TestOldCompletionCallback callback; | |
4861 | |
4862 scoped_ptr<net::HttpTransaction> trans; | |
4863 int rv = cache.http_cache()->CreateTransaction(&trans); | |
4864 EXPECT_EQ(net::OK, rv); | |
4865 ASSERT_TRUE(trans.get()); | |
4866 | |
4867 rv = trans->Start(&request, &callback, net::BoundNetLog()); | |
4868 if (rv == net::ERR_IO_PENDING) | |
4869 rv = callback.WaitForResult(); | |
4870 ASSERT_EQ(net::ERR_CACHE_MISS, rv); | |
4871 } | |
4872 | |
4873 // Ensure that we don't crash by if left-behind transactions. | |
4874 TEST(HttpCache, OutlivedTransactions) { | |
4875 MockHttpCache* cache = new MockHttpCache; | |
4876 | |
4877 scoped_ptr<net::HttpTransaction> trans; | |
4878 int rv = cache->http_cache()->CreateTransaction(&trans); | |
4879 EXPECT_EQ(net::OK, rv); | |
4880 | |
4881 delete cache; | |
4882 trans.reset(); | |
4883 } | |
4884 | |
4885 // Test that the disabled mode works. | |
4886 TEST(HttpCache, CacheDisabledMode) { | |
4887 MockHttpCache cache; | |
4888 | |
4889 // write to the cache | |
4890 RunTransactionTest(cache.http_cache(), kSimpleGET_Transaction); | |
4891 | |
4892 // go into disabled mode | |
4893 cache.http_cache()->set_mode(net::HttpCache::DISABLE); | |
4894 | |
4895 // force this transaction to write to the cache again | |
4896 MockTransaction transaction(kSimpleGET_Transaction); | |
4897 | |
4898 RunTransactionTest(cache.http_cache(), transaction); | |
4899 | |
4900 EXPECT_EQ(2, cache.network_layer()->transaction_count()); | |
4901 EXPECT_EQ(0, cache.disk_cache()->open_count()); | |
4902 EXPECT_EQ(1, cache.disk_cache()->create_count()); | |
4903 } | |
4904 | |
4905 // Other tests check that the response headers of the cached response | |
4906 // get updated on 304. Here we specifically check that the | |
4907 // HttpResponseHeaders::request_time and HttpResponseHeaders::response_time | |
4908 // fields also gets updated. | |
4909 // http://crbug.com/20594. | |
4910 TEST(HttpCache, UpdatesRequestResponseTimeOn304) { | |
4911 MockHttpCache cache; | |
4912 | |
4913 const char* kUrl = "http://foobar"; | |
4914 const char* kData = "body"; | |
4915 | |
4916 MockTransaction mock_network_response = { 0 }; | |
4917 mock_network_response.url = kUrl; | |
4918 | |
4919 AddMockTransaction(&mock_network_response); | |
4920 | |
4921 // Request |kUrl|, causing |kNetResponse1| to be written to the cache. | |
4922 | |
4923 MockTransaction request = { 0 }; | |
4924 request.url = kUrl; | |
4925 request.method = "GET"; | |
4926 request.request_headers = ""; | |
4927 request.data = kData; | |
4928 | |
4929 static const Response kNetResponse1 = { | |
4930 "HTTP/1.1 200 OK", | |
4931 "Date: Fri, 12 Jun 2009 21:46:42 GMT\n" | |
4932 "Last-Modified: Wed, 06 Feb 2008 22:38:21 GMT\n", | |
4933 kData | |
4934 }; | |
4935 | |
4936 kNetResponse1.AssignTo(&mock_network_response); | |
4937 | |
4938 RunTransactionTest(cache.http_cache(), request); | |
4939 | |
4940 // Request |kUrl| again, this time validating the cache and getting | |
4941 // a 304 back. | |
4942 | |
4943 request.load_flags = net::LOAD_VALIDATE_CACHE; | |
4944 | |
4945 static const Response kNetResponse2 = { | |
4946 "HTTP/1.1 304 Not Modified", | |
4947 "Date: Wed, 22 Jul 2009 03:15:26 GMT\n", | |
4948 "" | |
4949 }; | |
4950 | |
4951 kNetResponse2.AssignTo(&mock_network_response); | |
4952 | |
4953 base::Time request_time = base::Time() + base::TimeDelta::FromHours(1234); | |
4954 base::Time response_time = base::Time() + base::TimeDelta::FromHours(1235); | |
4955 | |
4956 mock_network_response.request_time = request_time; | |
4957 mock_network_response.response_time = response_time; | |
4958 | |
4959 net::HttpResponseInfo response; | |
4960 RunTransactionTestWithResponseInfo(cache.http_cache(), request, &response); | |
4961 | |
4962 // The request and response times should have been updated. | |
4963 EXPECT_EQ(request_time.ToInternalValue(), | |
4964 response.request_time.ToInternalValue()); | |
4965 EXPECT_EQ(response_time.ToInternalValue(), | |
4966 response.response_time.ToInternalValue()); | |
4967 | |
4968 std::string headers; | |
4969 response.headers->GetNormalizedHeaders(&headers); | |
4970 | |
4971 EXPECT_EQ("HTTP/1.1 200 OK\n" | |
4972 "Date: Wed, 22 Jul 2009 03:15:26 GMT\n" | |
4973 "Last-Modified: Wed, 06 Feb 2008 22:38:21 GMT\n", | |
4974 headers); | |
4975 | |
4976 RemoveMockTransaction(&mock_network_response); | |
4977 } | |
4978 | |
4979 // Tests that we can write metadata to an entry. | |
4980 TEST(HttpCache, WriteMetadata_OK) { | |
4981 MockHttpCache cache; | |
4982 | |
4983 // Write to the cache | |
4984 net::HttpResponseInfo response; | |
4985 RunTransactionTestWithResponseInfo(cache.http_cache(), kSimpleGET_Transaction, | |
4986 &response); | |
4987 EXPECT_TRUE(response.metadata.get() == NULL); | |
4988 | |
4989 // Trivial call. | |
4990 cache.http_cache()->WriteMetadata(GURL("foo"), Time::Now(), NULL, 0); | |
4991 | |
4992 // Write meta data to the same entry. | |
4993 scoped_refptr<net::IOBufferWithSize> buf(new net::IOBufferWithSize(50)); | |
4994 memset(buf->data(), 0, buf->size()); | |
4995 base::strlcpy(buf->data(), "Hi there", buf->size()); | |
4996 cache.http_cache()->WriteMetadata(GURL(kSimpleGET_Transaction.url), | |
4997 response.response_time, buf, buf->size()); | |
4998 | |
4999 // Release the buffer before the operation takes place. | |
5000 buf = NULL; | |
5001 | |
5002 // Makes sure we finish pending operations. | |
5003 MessageLoop::current()->RunAllPending(); | |
5004 | |
5005 RunTransactionTestWithResponseInfo(cache.http_cache(), kSimpleGET_Transaction, | |
5006 &response); | |
5007 ASSERT_TRUE(response.metadata.get() != NULL); | |
5008 EXPECT_EQ(50, response.metadata->size()); | |
5009 EXPECT_EQ(0, strcmp(response.metadata->data(), "Hi there")); | |
5010 | |
5011 EXPECT_EQ(1, cache.network_layer()->transaction_count()); | |
5012 EXPECT_EQ(2, cache.disk_cache()->open_count()); | |
5013 EXPECT_EQ(1, cache.disk_cache()->create_count()); | |
5014 } | |
5015 | |
5016 // Tests that we only write metadata to an entry if the time stamp matches. | |
5017 TEST(HttpCache, WriteMetadata_Fail) { | |
5018 MockHttpCache cache; | |
5019 | |
5020 // Write to the cache | |
5021 net::HttpResponseInfo response; | |
5022 RunTransactionTestWithResponseInfo(cache.http_cache(), kSimpleGET_Transaction, | |
5023 &response); | |
5024 EXPECT_TRUE(response.metadata.get() == NULL); | |
5025 | |
5026 // Attempt to write meta data to the same entry. | |
5027 scoped_refptr<net::IOBufferWithSize> buf(new net::IOBufferWithSize(50)); | |
5028 memset(buf->data(), 0, buf->size()); | |
5029 base::strlcpy(buf->data(), "Hi there", buf->size()); | |
5030 base::Time expected_time = response.response_time - | |
5031 base::TimeDelta::FromMilliseconds(20); | |
5032 cache.http_cache()->WriteMetadata(GURL(kSimpleGET_Transaction.url), | |
5033 expected_time, buf, buf->size()); | |
5034 | |
5035 // Makes sure we finish pending operations. | |
5036 MessageLoop::current()->RunAllPending(); | |
5037 | |
5038 RunTransactionTestWithResponseInfo(cache.http_cache(), kSimpleGET_Transaction, | |
5039 &response); | |
5040 EXPECT_TRUE(response.metadata.get() == NULL); | |
5041 | |
5042 EXPECT_EQ(1, cache.network_layer()->transaction_count()); | |
5043 EXPECT_EQ(2, cache.disk_cache()->open_count()); | |
5044 EXPECT_EQ(1, cache.disk_cache()->create_count()); | |
5045 } | |
5046 | |
5047 // Tests that we can read metadata after validating the entry and with READ mode | |
5048 // transactions. | |
5049 TEST(HttpCache, ReadMetadata) { | |
5050 MockHttpCache cache; | |
5051 | |
5052 // Write to the cache | |
5053 net::HttpResponseInfo response; | |
5054 RunTransactionTestWithResponseInfo(cache.http_cache(), | |
5055 kTypicalGET_Transaction, &response); | |
5056 EXPECT_TRUE(response.metadata.get() == NULL); | |
5057 | |
5058 // Write meta data to the same entry. | |
5059 scoped_refptr<net::IOBufferWithSize> buf(new net::IOBufferWithSize(50)); | |
5060 memset(buf->data(), 0, buf->size()); | |
5061 base::strlcpy(buf->data(), "Hi there", buf->size()); | |
5062 cache.http_cache()->WriteMetadata(GURL(kTypicalGET_Transaction.url), | |
5063 response.response_time, buf, buf->size()); | |
5064 | |
5065 // Makes sure we finish pending operations. | |
5066 MessageLoop::current()->RunAllPending(); | |
5067 | |
5068 // Start with a READ mode transaction. | |
5069 MockTransaction trans1(kTypicalGET_Transaction); | |
5070 trans1.load_flags = net::LOAD_ONLY_FROM_CACHE; | |
5071 | |
5072 RunTransactionTestWithResponseInfo(cache.http_cache(), trans1, &response); | |
5073 ASSERT_TRUE(response.metadata.get() != NULL); | |
5074 EXPECT_EQ(50, response.metadata->size()); | |
5075 EXPECT_EQ(0, strcmp(response.metadata->data(), "Hi there")); | |
5076 | |
5077 EXPECT_EQ(1, cache.network_layer()->transaction_count()); | |
5078 EXPECT_EQ(2, cache.disk_cache()->open_count()); | |
5079 EXPECT_EQ(1, cache.disk_cache()->create_count()); | |
5080 MessageLoop::current()->RunAllPending(); | |
5081 | |
5082 // Now make sure that the entry is re-validated with the server. | |
5083 trans1.load_flags = net::LOAD_VALIDATE_CACHE; | |
5084 trans1.status = "HTTP/1.1 304 Not Modified"; | |
5085 AddMockTransaction(&trans1); | |
5086 | |
5087 response.metadata = NULL; | |
5088 RunTransactionTestWithResponseInfo(cache.http_cache(), trans1, &response); | |
5089 EXPECT_TRUE(response.metadata.get() != NULL); | |
5090 | |
5091 EXPECT_EQ(2, cache.network_layer()->transaction_count()); | |
5092 EXPECT_EQ(3, cache.disk_cache()->open_count()); | |
5093 EXPECT_EQ(1, cache.disk_cache()->create_count()); | |
5094 MessageLoop::current()->RunAllPending(); | |
5095 RemoveMockTransaction(&trans1); | |
5096 | |
5097 // Now return 200 when validating the entry so the metadata will be lost. | |
5098 MockTransaction trans2(kTypicalGET_Transaction); | |
5099 trans2.load_flags = net::LOAD_VALIDATE_CACHE; | |
5100 RunTransactionTestWithResponseInfo(cache.http_cache(), trans2, &response); | |
5101 EXPECT_TRUE(response.metadata.get() == NULL); | |
5102 | |
5103 EXPECT_EQ(3, cache.network_layer()->transaction_count()); | |
5104 EXPECT_EQ(4, cache.disk_cache()->open_count()); | |
5105 EXPECT_EQ(1, cache.disk_cache()->create_count()); | |
5106 } | |
5107 | |
5108 // Tests that we don't mark entries as truncated when a filter detects the end | |
5109 // of the stream. | |
5110 TEST(HttpCache, FilterCompletion) { | |
5111 MockHttpCache cache; | |
5112 TestOldCompletionCallback callback; | |
5113 | |
5114 { | |
5115 scoped_ptr<net::HttpTransaction> trans; | |
5116 int rv = cache.http_cache()->CreateTransaction(&trans); | |
5117 EXPECT_EQ(net::OK, rv); | |
5118 | |
5119 MockHttpRequest request(kSimpleGET_Transaction); | |
5120 rv = trans->Start(&request, &callback, net::BoundNetLog()); | |
5121 EXPECT_EQ(net::OK, callback.GetResult(rv)); | |
5122 | |
5123 scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(256)); | |
5124 rv = trans->Read(buf, 256, &callback); | |
5125 EXPECT_GT(callback.GetResult(rv), 0); | |
5126 | |
5127 // Now make sure that the entry is preserved. | |
5128 trans->DoneReading(); | |
5129 } | |
5130 | |
5131 // Make sure that the ActiveEntry is gone. | |
5132 MessageLoop::current()->RunAllPending(); | |
5133 | |
5134 // Read from the cache. | |
5135 RunTransactionTest(cache.http_cache(), kSimpleGET_Transaction); | |
5136 | |
5137 EXPECT_EQ(1, cache.network_layer()->transaction_count()); | |
5138 EXPECT_EQ(1, cache.disk_cache()->open_count()); | |
5139 EXPECT_EQ(1, cache.disk_cache()->create_count()); | |
5140 } | |
5141 | |
5142 // Tests that we detect truncated rersources from the net when there is | |
5143 // a Content-Length header. | |
5144 TEST(HttpCache, TruncatedByContentLength) { | |
5145 MockHttpCache cache; | |
5146 TestOldCompletionCallback callback; | |
5147 | |
5148 MockTransaction transaction(kSimpleGET_Transaction); | |
5149 AddMockTransaction(&transaction); | |
5150 transaction.response_headers = "Cache-Control: max-age=10000\n" | |
5151 "Content-Length: 100\n"; | |
5152 RunTransactionTest(cache.http_cache(), transaction); | |
5153 RemoveMockTransaction(&transaction); | |
5154 | |
5155 // Read from the cache. | |
5156 RunTransactionTest(cache.http_cache(), kSimpleGET_Transaction); | |
5157 | |
5158 EXPECT_EQ(2, cache.network_layer()->transaction_count()); | |
5159 EXPECT_EQ(0, cache.disk_cache()->open_count()); | |
5160 EXPECT_EQ(2, cache.disk_cache()->create_count()); | |
5161 } | |
5162 | |
5163 // Tests that we actually flag entries as truncated when we detect an error | |
5164 // from the net. | |
5165 TEST(HttpCache, TruncatedByContentLength2) { | |
5166 MockHttpCache cache; | |
5167 TestOldCompletionCallback callback; | |
5168 | |
5169 MockTransaction transaction(kSimpleGET_Transaction); | |
5170 AddMockTransaction(&transaction); | |
5171 transaction.response_headers = "Cache-Control: max-age=10000\n" | |
5172 "Content-Length: 100\n" | |
5173 "Etag: foo\n"; | |
5174 RunTransactionTest(cache.http_cache(), transaction); | |
5175 RemoveMockTransaction(&transaction); | |
5176 | |
5177 // Verify that the entry is marked as incomplete. | |
5178 disk_cache::Entry* entry; | |
5179 ASSERT_TRUE(cache.OpenBackendEntry(kSimpleGET_Transaction.url, &entry)); | |
5180 net::HttpResponseInfo response; | |
5181 bool truncated = false; | |
5182 EXPECT_TRUE(MockHttpCache::ReadResponseInfo(entry, &response, &truncated)); | |
5183 EXPECT_TRUE(truncated); | |
5184 entry->Close(); | |
5185 } | |
5186 | |
5187 //----------------------------------------------------------------------------- | |
5188 // DiskCacheBasedSSLHostInfo tests | |
5189 | |
5190 class DeleteSSLHostInfoOldCompletionCallback : public TestOldCompletionCallback { | |
5191 public: | |
5192 explicit DeleteSSLHostInfoOldCompletionCallback(net::SSLHostInfo* ssl_host_inf o) | |
5193 : ssl_host_info_(ssl_host_info) {} | |
5194 | |
5195 virtual void RunWithParams(const Tuple1<int>& params) { | |
5196 delete ssl_host_info_; | |
5197 TestOldCompletionCallback::RunWithParams(params); | |
5198 } | |
5199 | |
5200 private: | |
5201 net::SSLHostInfo* ssl_host_info_; | |
5202 }; | |
5203 | |
5204 // Tests that we can delete a DiskCacheBasedSSLHostInfo object in a | |
5205 // completion callback for DiskCacheBasedSSLHostInfo::WaitForDataReady. | |
5206 TEST(DiskCacheBasedSSLHostInfo, DeleteInCallback) { | |
5207 net::CertVerifier cert_verifier; | |
5208 // Use the blocking mock backend factory to force asynchronous completion | |
5209 // of ssl_host_info->WaitForDataReady(), so that the callback will run. | |
5210 MockBlockingBackendFactory* factory = new MockBlockingBackendFactory(); | |
5211 MockHttpCache cache(factory); | |
5212 net::SSLConfig ssl_config; | |
5213 net::SSLHostInfo* ssl_host_info = | |
5214 new net::DiskCacheBasedSSLHostInfo("https://www.verisign.com", ssl_config, | |
5215 &cert_verifier, cache.http_cache()); | |
5216 ssl_host_info->Start(); | |
5217 DeleteSSLHostInfoOldCompletionCallback callback(ssl_host_info); | |
5218 int rv = ssl_host_info->WaitForDataReady(&callback); | |
5219 EXPECT_EQ(net::ERR_IO_PENDING, rv); | |
5220 // Now complete the backend creation and let the callback run. | |
5221 factory->FinishCreation(); | |
5222 EXPECT_EQ(net::OK, callback.GetResult(rv)); | |
5223 } | |
OLD | NEW |