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