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