Home | History | Annotate | Download | only in url_request
      1 // Copyright (c) 2006-2009 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/url_request/request_tracker.h"
      6 
      7 #include "base/compiler_specific.h"
      8 #include "base/format_macros.h"
      9 #include "base/string_util.h"
     10 #include "testing/gtest/include/gtest/gtest.h"
     11 
     12 namespace {
     13 
     14 static const int kMaxNumLoadLogEntries = 1;
     15 
     16 class TestRequest {
     17  public:
     18   explicit TestRequest(const GURL& url)
     19       : url_(url),
     20         load_log_(new net::LoadLog(kMaxNumLoadLogEntries)),
     21         ALLOW_THIS_IN_INITIALIZER_LIST(request_tracker_node_(this)) {}
     22   ~TestRequest() {}
     23 
     24   // This method is used in RequestTrackerTest::Basic test.
     25   const GURL& original_url() const { return url_; }
     26 
     27  private:
     28   // RequestTracker<T> will access GetRecentRequestInfo() and
     29   // |request_tracker_node_|.
     30   friend class RequestTracker<TestRequest>;
     31 
     32   void GetInfoForTracker(
     33       RequestTracker<TestRequest>::RecentRequestInfo* info) const {
     34     info->original_url = url_;
     35     info->load_log = load_log_;
     36   }
     37 
     38   const GURL url_;
     39   scoped_refptr<net::LoadLog> load_log_;
     40 
     41   RequestTracker<TestRequest>::Node request_tracker_node_;
     42 
     43   DISALLOW_COPY_AND_ASSIGN(TestRequest);
     44 };
     45 
     46 
     47 TEST(RequestTrackerTest, BasicBounded) {
     48   RequestTracker<TestRequest> tracker;
     49   EXPECT_FALSE(tracker.IsUnbounded());
     50   EXPECT_EQ(0u, tracker.GetLiveRequests().size());
     51   EXPECT_EQ(0u, tracker.GetRecentlyDeceased().size());
     52 
     53   TestRequest req1(GURL("http://req1"));
     54   TestRequest req2(GURL("http://req2"));
     55   TestRequest req3(GURL("http://req3"));
     56   TestRequest req4(GURL("http://req4"));
     57   TestRequest req5(GURL("http://req5"));
     58 
     59   tracker.Add(&req1);
     60   tracker.Add(&req2);
     61   tracker.Add(&req3);
     62   tracker.Add(&req4);
     63   tracker.Add(&req5);
     64 
     65   std::vector<TestRequest*> live_reqs = tracker.GetLiveRequests();
     66 
     67   ASSERT_EQ(5u, live_reqs.size());
     68   EXPECT_EQ(GURL("http://req1"), live_reqs[0]->original_url());
     69   EXPECT_EQ(GURL("http://req2"), live_reqs[1]->original_url());
     70   EXPECT_EQ(GURL("http://req3"), live_reqs[2]->original_url());
     71   EXPECT_EQ(GURL("http://req4"), live_reqs[3]->original_url());
     72   EXPECT_EQ(GURL("http://req5"), live_reqs[4]->original_url());
     73 
     74   tracker.Remove(&req1);
     75   tracker.Remove(&req5);
     76   tracker.Remove(&req3);
     77 
     78   ASSERT_EQ(3u, tracker.GetRecentlyDeceased().size());
     79 
     80   live_reqs = tracker.GetLiveRequests();
     81 
     82   ASSERT_EQ(2u, live_reqs.size());
     83   EXPECT_EQ(GURL("http://req2"), live_reqs[0]->original_url());
     84   EXPECT_EQ(GURL("http://req4"), live_reqs[1]->original_url());
     85 }
     86 
     87 TEST(RequestTrackerTest, GraveyardBounded) {
     88   RequestTracker<TestRequest> tracker;
     89   EXPECT_FALSE(tracker.IsUnbounded());
     90   EXPECT_EQ(0u, tracker.GetLiveRequests().size());
     91   EXPECT_EQ(0u, tracker.GetRecentlyDeceased().size());
     92 
     93   // Add twice as many requests as will fit in the graveyard.
     94   for (size_t i = 0;
     95        i < RequestTracker<TestRequest>::kMaxGraveyardSize * 2;
     96        ++i) {
     97     TestRequest req(GURL(StringPrintf("http://req%" PRIuS, i).c_str()));
     98     tracker.Add(&req);
     99     tracker.Remove(&req);
    100   }
    101 
    102   // Check that only the last |kMaxGraveyardSize| requests are in-memory.
    103 
    104   RequestTracker<TestRequest>::RecentRequestInfoList recent_reqs =
    105       tracker.GetRecentlyDeceased();
    106 
    107   ASSERT_EQ(RequestTracker<TestRequest>::kMaxGraveyardSize, recent_reqs.size());
    108 
    109   for (size_t i = 0; i < RequestTracker<TestRequest>::kMaxGraveyardSize; ++i) {
    110     size_t req_number = i + RequestTracker<TestRequest>::kMaxGraveyardSize;
    111     GURL url(StringPrintf("http://req%" PRIuS, req_number).c_str());
    112     EXPECT_EQ(url, recent_reqs[i].original_url);
    113   }
    114 }
    115 
    116 TEST(RequestTrackerTest, GraveyardUnbounded) {
    117   RequestTracker<TestRequest> tracker;
    118   EXPECT_FALSE(tracker.IsUnbounded());
    119   EXPECT_EQ(0u, tracker.GetLiveRequests().size());
    120   EXPECT_EQ(0u, tracker.GetRecentlyDeceased().size());
    121 
    122   tracker.SetUnbounded(true);
    123 
    124   EXPECT_TRUE(tracker.IsUnbounded());
    125 
    126   // Add twice as many requests as would fit in the bounded graveyard.
    127 
    128   size_t kMaxSize = RequestTracker<TestRequest>::kMaxGraveyardSize * 2;
    129   for (size_t i = 0; i < kMaxSize; ++i) {
    130     TestRequest req(GURL(StringPrintf("http://req%" PRIuS, i).c_str()));
    131     tracker.Add(&req);
    132     tracker.Remove(&req);
    133   }
    134 
    135   // Check that all of them got saved.
    136 
    137   RequestTracker<TestRequest>::RecentRequestInfoList recent_reqs =
    138       tracker.GetRecentlyDeceased();
    139 
    140   ASSERT_EQ(kMaxSize, recent_reqs.size());
    141 
    142   for (size_t i = 0; i < kMaxSize; ++i) {
    143     GURL url(StringPrintf("http://req%" PRIuS, i).c_str());
    144     EXPECT_EQ(url, recent_reqs[i].original_url);
    145   }
    146 }
    147 
    148 // Check that very long URLs are truncated.
    149 TEST(RequestTrackerTest, GraveyardURLBounded) {
    150   RequestTracker<TestRequest> tracker;
    151   EXPECT_FALSE(tracker.IsUnbounded());
    152 
    153   std::string big_url_spec("http://");
    154   big_url_spec.resize(2 * RequestTracker<TestRequest>::kMaxGraveyardURLSize,
    155                       'x');
    156   GURL big_url(big_url_spec);
    157   TestRequest req(big_url);
    158 
    159   tracker.Add(&req);
    160   tracker.Remove(&req);
    161 
    162   ASSERT_EQ(1u, tracker.GetRecentlyDeceased().size());
    163   // The +1 is because GURL canonicalizes with a trailing '/' ... maybe
    164   // we should just save the std::string rather than the GURL.
    165   EXPECT_EQ(RequestTracker<TestRequest>::kMaxGraveyardURLSize + 1,
    166             tracker.GetRecentlyDeceased()[0].original_url.spec().size());
    167 }
    168 
    169 // Test the doesn't fail if the URL was invalid. http://crbug.com/21423.
    170 TEST(URLRequestTrackerTest, TrackingInvalidURL) {
    171   RequestTracker<TestRequest> tracker;
    172   EXPECT_FALSE(tracker.IsUnbounded());
    173 
    174   EXPECT_EQ(0u, tracker.GetLiveRequests().size());
    175   EXPECT_EQ(0u, tracker.GetRecentlyDeceased().size());
    176 
    177   GURL invalid_url("xabc");
    178   EXPECT_FALSE(invalid_url.is_valid());
    179   TestRequest req(invalid_url);
    180 
    181   tracker.Add(&req);
    182   tracker.Remove(&req);
    183 
    184   // Check that the invalid URL made it into graveyard.
    185   ASSERT_EQ(1u, tracker.GetRecentlyDeceased().size());
    186   EXPECT_FALSE(tracker.GetRecentlyDeceased()[0].original_url.is_valid());
    187 }
    188 
    189 bool ShouldRequestBeAddedToGraveyard(const GURL& url) {
    190   return !url.SchemeIs("chrome") && !url.SchemeIs("data");
    191 }
    192 
    193 // Check that we can exclude "chrome://" URLs and "data:" URLs from being
    194 // saved into the recent requests list (graveyard), by using a filter.
    195 TEST(RequestTrackerTest, GraveyardCanBeFiltered) {
    196   RequestTracker<TestRequest> tracker;
    197   EXPECT_FALSE(tracker.IsUnbounded());
    198 
    199   tracker.SetGraveyardFilter(ShouldRequestBeAddedToGraveyard);
    200 
    201   // This will be excluded.
    202   TestRequest req1(GURL("chrome://dontcare"));
    203   tracker.Add(&req1);
    204   tracker.Remove(&req1);
    205 
    206   // This will be be added to graveyard.
    207   TestRequest req2(GURL("chrome2://dontcare"));
    208   tracker.Add(&req2);
    209   tracker.Remove(&req2);
    210 
    211   // This will be be added to graveyard.
    212   TestRequest req3(GURL("http://foo"));
    213   tracker.Add(&req3);
    214   tracker.Remove(&req3);
    215 
    216   // This will be be excluded.
    217   TestRequest req4(GURL("data:sup"));
    218   tracker.Add(&req4);
    219   tracker.Remove(&req4);
    220 
    221   ASSERT_EQ(2u, tracker.GetRecentlyDeceased().size());
    222   EXPECT_EQ("chrome2://dontcare/",
    223             tracker.GetRecentlyDeceased()[0].original_url.spec());
    224   EXPECT_EQ("http://foo/",
    225             tracker.GetRecentlyDeceased()[1].original_url.spec());
    226 }
    227 
    228 // Convert an unbounded tracker back to being bounded.
    229 TEST(RequestTrackerTest, ConvertUnboundedToBounded) {
    230   RequestTracker<TestRequest> tracker;
    231   EXPECT_FALSE(tracker.IsUnbounded());
    232   EXPECT_EQ(0u, tracker.GetLiveRequests().size());
    233   EXPECT_EQ(0u, tracker.GetRecentlyDeceased().size());
    234 
    235   tracker.SetUnbounded(true);
    236   EXPECT_TRUE(tracker.IsUnbounded());
    237 
    238   // Add twice as many requests as would fit in the bounded graveyard.
    239 
    240   size_t kMaxSize = RequestTracker<TestRequest>::kMaxGraveyardSize * 2;
    241   for (size_t i = 0; i < kMaxSize; ++i) {
    242     TestRequest req(GURL(StringPrintf("http://req%" PRIuS, i).c_str()));
    243     tracker.Add(&req);
    244     tracker.Remove(&req);
    245   }
    246 
    247   // Check that all of them got saved.
    248   ASSERT_EQ(kMaxSize, tracker.GetRecentlyDeceased().size());
    249 
    250   // Now make the tracker bounded, and add more entries to its graveyard.
    251   tracker.SetUnbounded(false);
    252 
    253   kMaxSize = RequestTracker<TestRequest>::kMaxGraveyardSize;
    254   for (size_t i = 0; i < kMaxSize; ++i) {
    255     TestRequest req(GURL(StringPrintf("http://req%" PRIuS, i).c_str()));
    256     tracker.Add(&req);
    257     tracker.Remove(&req);
    258   }
    259 
    260   // We should only have kMaxGraveyardSize entries now.
    261   ASSERT_EQ(kMaxSize, tracker.GetRecentlyDeceased().size());
    262 }
    263 
    264 }  // namespace
    265