Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(181)

Side by Side Diff: net/base/client_socket_pool_unittest.cc

Issue 42541: Prioritize which HTTP requests get a socket first by adding a priority level ... (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 11 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « net/base/client_socket_pool.cc ('k') | net/http/http_network_transaction.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "base/message_loop.h" 5 #include "base/message_loop.h"
6 #include "net/base/client_socket.h" 6 #include "net/base/client_socket.h"
7 #include "net/base/client_socket_handle.h" 7 #include "net/base/client_socket_handle.h"
8 #include "net/base/client_socket_pool.h" 8 #include "net/base/client_socket_pool.h"
9 #include "net/base/net_errors.h" 9 #include "net/base/net_errors.h"
10 #include "testing/gtest/include/gtest/gtest.h" 10 #include "testing/gtest/include/gtest/gtest.h"
11 11
12 namespace { 12 namespace {
13 13
14 typedef testing::Test ClientSocketPoolTest; 14 const int kMaxSocketsPerGroup = 6;
15 15
16 const int kMaxSocketsPerGroup = 6; 16 // Note that the first and the last are the same, the first should be handled
17 // before the last, since it was inserted first.
18 const int kPriorities[10] = { 1, 7, 9, 5, 6, 2, 8, 3, 4, 1 };
19
20 // This is the number of extra requests beyond the first few that use up all
21 // available sockets in the socket group.
22 const int kNumPendingRequests = arraysize(kPriorities);
17 23
18 class MockClientSocket : public net::ClientSocket { 24 class MockClientSocket : public net::ClientSocket {
19 public: 25 public:
20 MockClientSocket() : connected_(false) { 26 MockClientSocket() : connected_(false) {
21 allocation_count++; 27 allocation_count++;
22 } 28 }
23 29
24 // ClientSocket methods: 30 // ClientSocket methods:
25 virtual int Connect(net::CompletionCallback* callback) { 31 virtual int Connect(net::CompletionCallback* callback) {
26 connected_ = true; 32 connected_ = true;
(...skipping 25 matching lines...) Expand all
52 static int allocation_count; 58 static int allocation_count;
53 59
54 private: 60 private:
55 bool connected_; 61 bool connected_;
56 }; 62 };
57 63
58 int MockClientSocket::allocation_count = 0; 64 int MockClientSocket::allocation_count = 0;
59 65
60 class TestSocketRequest : public CallbackRunner< Tuple1<int> > { 66 class TestSocketRequest : public CallbackRunner< Tuple1<int> > {
61 public: 67 public:
62 explicit TestSocketRequest(net::ClientSocketPool* pool) : handle(pool) {} 68 TestSocketRequest(
69 net::ClientSocketPool* pool,
70 std::vector<TestSocketRequest*>* request_order)
71 : handle(pool), request_order_(request_order) {}
63 72
64 net::ClientSocketHandle handle; 73 net::ClientSocketHandle handle;
65 74
66 void EnsureSocket() { 75 void EnsureSocket() {
67 DCHECK(handle.is_initialized()); 76 DCHECK(handle.is_initialized());
77 request_order_->push_back(this);
68 if (!handle.socket()) { 78 if (!handle.socket()) {
69 handle.set_socket(new MockClientSocket()); 79 handle.set_socket(new MockClientSocket());
70 handle.socket()->Connect(NULL); 80 handle.socket()->Connect(NULL);
71 } 81 }
72 } 82 }
73 83
74 virtual void RunWithParams(const Tuple1<int>& params) { 84 virtual void RunWithParams(const Tuple1<int>& params) {
75 DCHECK(params.a == net::OK); 85 DCHECK(params.a == net::OK);
76 completion_count++; 86 completion_count++;
77 EnsureSocket(); 87 EnsureSocket();
78 } 88 }
79 89
80 static int completion_count; 90 static int completion_count;
91
92 private:
93 std::vector<TestSocketRequest*>* request_order_;
81 }; 94 };
82 95
83 int TestSocketRequest::completion_count = 0; 96 int TestSocketRequest::completion_count = 0;
84 97
85 } // namespace 98 class ClientSocketPoolTest : public testing::Test {
99 protected:
100 ClientSocketPoolTest()
101 : pool_(new net::ClientSocketPool(kMaxSocketsPerGroup)) {}
86 102
87 TEST(ClientSocketPoolTest, Basic) { 103 virtual void SetUp() {
88 scoped_refptr<net::ClientSocketPool> pool = 104 MockClientSocket::allocation_count = 0;
89 new net::ClientSocketPool(kMaxSocketsPerGroup); 105 TestSocketRequest::completion_count = 0;
106 }
90 107
91 TestSocketRequest r(pool); 108 scoped_refptr<net::ClientSocketPool> pool_;
109 std::vector<TestSocketRequest*> request_order_;
110 };
111
112 TEST_F(ClientSocketPoolTest, Basic) {
113 TestSocketRequest r(pool_.get(), &request_order_);
92 int rv; 114 int rv;
93 115
94 rv = r.handle.Init("a", &r); 116 rv = r.handle.Init("a", 0, &r);
95 EXPECT_EQ(net::OK, rv); 117 EXPECT_EQ(net::OK, rv);
96 EXPECT_TRUE(r.handle.is_initialized()); 118 EXPECT_TRUE(r.handle.is_initialized());
97 119
98 r.handle.Reset(); 120 r.handle.Reset();
99 121
100 // The handle's Reset method may have posted a task. 122 // The handle's Reset method may have posted a task.
101 MessageLoop::current()->RunAllPending(); 123 MessageLoop::current()->RunAllPending();
102 } 124 }
103 125
104 TEST(ClientSocketPoolTest, WithIdleConnection) { 126 TEST_F(ClientSocketPoolTest, WithIdleConnection) {
105 scoped_refptr<net::ClientSocketPool> pool = 127 TestSocketRequest r(pool_.get(), &request_order_);
106 new net::ClientSocketPool(kMaxSocketsPerGroup);
107
108 TestSocketRequest r(pool);
109 int rv; 128 int rv;
110 129
111 rv = r.handle.Init("a", &r); 130 rv = r.handle.Init("a", 0, &r);
112 EXPECT_EQ(net::OK, rv); 131 EXPECT_EQ(net::OK, rv);
113 EXPECT_TRUE(r.handle.is_initialized()); 132 EXPECT_TRUE(r.handle.is_initialized());
114 133
115 // Create a socket. 134 // Create a socket.
116 r.EnsureSocket(); 135 r.EnsureSocket();
117 136
118 // Release the socket. It should find its way into the idle list. We're 137 // Release the socket. It should find its way into the idle list. We're
119 // testing that this does not trigger a crash. 138 // testing that this does not trigger a crash.
120 r.handle.Reset(); 139 r.handle.Reset();
121 140
122 // The handle's Reset method may have posted a task. 141 // The handle's Reset method may have posted a task.
123 MessageLoop::current()->RunAllPending(); 142 MessageLoop::current()->RunAllPending();
124 } 143 }
125 144
126 TEST(ClientSocketPoolTest, PendingRequests) { 145 TEST_F(ClientSocketPoolTest, PendingRequests) {
127 scoped_refptr<net::ClientSocketPool> pool =
128 new net::ClientSocketPool(kMaxSocketsPerGroup);
129
130 int rv; 146 int rv;
131 147
132 scoped_ptr<TestSocketRequest> reqs[kMaxSocketsPerGroup + 10]; 148 scoped_ptr<TestSocketRequest> reqs[kMaxSocketsPerGroup + kNumPendingRequests];
149
133 for (size_t i = 0; i < arraysize(reqs); ++i) 150 for (size_t i = 0; i < arraysize(reqs); ++i)
134 reqs[i].reset(new TestSocketRequest(pool)); 151 reqs[i].reset(new TestSocketRequest(pool_.get(), &request_order_));
135
136 // Reset
137 MockClientSocket::allocation_count = 0;
138 TestSocketRequest::completion_count = 0;
139 152
140 // Create connections or queue up requests. 153 // Create connections or queue up requests.
141 for (size_t i = 0; i < arraysize(reqs); ++i) { 154 for (int i = 0; i < kMaxSocketsPerGroup; ++i) {
142 rv = reqs[i]->handle.Init("a", reqs[i].get()); 155 rv = reqs[i]->handle.Init("a", 5, reqs[i].get());
143 if (rv != net::ERR_IO_PENDING) { 156 EXPECT_EQ(net::OK, rv);
144 EXPECT_EQ(net::OK, rv); 157 reqs[i]->EnsureSocket();
145 reqs[i]->EnsureSocket(); 158 }
146 } 159 for (int i = 0; i < kNumPendingRequests; ++i) {
160 rv = reqs[kMaxSocketsPerGroup + i]->handle.Init(
161 "a", kPriorities[i], reqs[kMaxSocketsPerGroup + i].get());
162 EXPECT_EQ(net::ERR_IO_PENDING, rv);
147 } 163 }
148 164
149 // Release any connections until we have no connections. 165 // Release any connections until we have no connections.
150 bool released_one; 166 bool released_one;
151 do { 167 do {
152 released_one = false; 168 released_one = false;
153 for (size_t i = 0; i < arraysize(reqs); ++i) { 169 for (size_t i = 0; i < arraysize(reqs); ++i) {
154 if (reqs[i]->handle.is_initialized()) { 170 if (reqs[i]->handle.is_initialized()) {
155 reqs[i]->handle.Reset(); 171 reqs[i]->handle.Reset();
156 MessageLoop::current()->RunAllPending(); 172 MessageLoop::current()->RunAllPending();
157 released_one = true; 173 released_one = true;
158 } 174 }
159 } 175 }
160 } while (released_one); 176 } while (released_one);
161 177
162 EXPECT_EQ(kMaxSocketsPerGroup, MockClientSocket::allocation_count); 178 EXPECT_EQ(kMaxSocketsPerGroup, MockClientSocket::allocation_count);
163 EXPECT_EQ(10, TestSocketRequest::completion_count); 179 EXPECT_EQ(kNumPendingRequests, TestSocketRequest::completion_count);
180
181 for (int i = 0; i < kMaxSocketsPerGroup; ++i) {
182 EXPECT_EQ(request_order_[i], reqs[i].get()) <<
183 "Request " << i << " was not in order.";
184 }
185
186 for (int i = 0; i < kNumPendingRequests - 1; ++i) {
187 int index_in_queue = (kNumPendingRequests - 1) - kPriorities[i];
188 EXPECT_EQ(request_order_[kMaxSocketsPerGroup + index_in_queue],
189 reqs[kMaxSocketsPerGroup + i].get()) <<
190 "Request " << kMaxSocketsPerGroup + i << " was not in order.";
191 }
192
193 EXPECT_EQ(request_order_[arraysize(reqs) - 1],
194 reqs[arraysize(reqs) - 1].get()) <<
195 "The last request with priority 1 should not have been inserted "
196 "earlier into the queue.";
164 } 197 }
165 198
166 TEST(ClientSocketPoolTest, PendingRequests_NoKeepAlive) { 199 TEST_F(ClientSocketPoolTest, PendingRequests_NoKeepAlive) {
167 scoped_refptr<net::ClientSocketPool> pool =
168 new net::ClientSocketPool(kMaxSocketsPerGroup);
169
170 int rv; 200 int rv;
171 201
172 scoped_ptr<TestSocketRequest> reqs[kMaxSocketsPerGroup + 10]; 202 scoped_ptr<TestSocketRequest> reqs[kMaxSocketsPerGroup + kNumPendingRequests];
173 for (size_t i = 0; i < arraysize(reqs); ++i) 203 for (size_t i = 0; i < arraysize(reqs); ++i)
174 reqs[i].reset(new TestSocketRequest(pool)); 204 reqs[i].reset(new TestSocketRequest(pool_.get(), &request_order_));
175
176 // Reset
177 MockClientSocket::allocation_count = 0;
178 TestSocketRequest::completion_count = 0;
179 205
180 // Create connections or queue up requests. 206 // Create connections or queue up requests.
181 for (size_t i = 0; i < arraysize(reqs); ++i) { 207 for (size_t i = 0; i < arraysize(reqs); ++i) {
182 rv = reqs[i]->handle.Init("a", reqs[i].get()); 208 rv = reqs[i]->handle.Init("a", 0, reqs[i].get());
183 if (rv != net::ERR_IO_PENDING) { 209 if (rv != net::ERR_IO_PENDING) {
184 EXPECT_EQ(net::OK, rv); 210 EXPECT_EQ(net::OK, rv);
185 reqs[i]->EnsureSocket(); 211 reqs[i]->EnsureSocket();
186 } 212 }
187 } 213 }
188 214
189 // Release any connections until we have no connections. 215 // Release any connections until we have no connections.
190 bool released_one; 216 bool released_one;
191 do { 217 do {
192 released_one = false; 218 released_one = false;
193 for (size_t i = 0; i < arraysize(reqs); ++i) { 219 for (size_t i = 0; i < arraysize(reqs); ++i) {
194 if (reqs[i]->handle.is_initialized()) { 220 if (reqs[i]->handle.is_initialized()) {
195 reqs[i]->handle.socket()->Disconnect(); 221 reqs[i]->handle.socket()->Disconnect();
196 reqs[i]->handle.Reset(); 222 reqs[i]->handle.Reset();
197 MessageLoop::current()->RunAllPending(); 223 MessageLoop::current()->RunAllPending();
198 released_one = true; 224 released_one = true;
199 } 225 }
200 } 226 }
201 } while (released_one); 227 } while (released_one);
202 228
203 EXPECT_EQ(kMaxSocketsPerGroup + 10, MockClientSocket::allocation_count); 229 EXPECT_EQ(kMaxSocketsPerGroup + kNumPendingRequests,
204 EXPECT_EQ(10, TestSocketRequest::completion_count); 230 MockClientSocket::allocation_count);
231 EXPECT_EQ(kNumPendingRequests, TestSocketRequest::completion_count);
205 } 232 }
206 233
207 TEST(ClientSocketPoolTest, CancelRequest) { 234 TEST_F(ClientSocketPoolTest, CancelRequest) {
208 scoped_refptr<net::ClientSocketPool> pool =
209 new net::ClientSocketPool(kMaxSocketsPerGroup);
210
211 int rv; 235 int rv;
212 236
213 scoped_ptr<TestSocketRequest> reqs[kMaxSocketsPerGroup + 10]; 237 scoped_ptr<TestSocketRequest> reqs[kMaxSocketsPerGroup + kNumPendingRequests];
238
214 for (size_t i = 0; i < arraysize(reqs); ++i) 239 for (size_t i = 0; i < arraysize(reqs); ++i)
215 reqs[i].reset(new TestSocketRequest(pool)); 240 reqs[i].reset(new TestSocketRequest(pool_.get(), &request_order_));
216
217 // Reset
218 MockClientSocket::allocation_count = 0;
219 TestSocketRequest::completion_count = 0;
220 241
221 // Create connections or queue up requests. 242 // Create connections or queue up requests.
222 for (size_t i = 0; i < arraysize(reqs); ++i) { 243 for (int i = 0; i < kMaxSocketsPerGroup; ++i) {
223 rv = reqs[i]->handle.Init("a", reqs[i].get()); 244 rv = reqs[i]->handle.Init("a", 5, reqs[i].get());
224 if (rv != net::ERR_IO_PENDING) { 245 EXPECT_EQ(net::OK, rv);
225 EXPECT_EQ(net::OK, rv); 246 reqs[i]->EnsureSocket();
226 reqs[i]->EnsureSocket(); 247 }
227 } 248 for (int i = 0; i < kNumPendingRequests; ++i) {
249 rv = reqs[kMaxSocketsPerGroup + i]->handle.Init(
250 "a", kPriorities[i], reqs[kMaxSocketsPerGroup + i].get());
251 EXPECT_EQ(net::ERR_IO_PENDING, rv);
228 } 252 }
229 253
230 // Cancel a request. 254 // Cancel a request.
231 size_t index_to_cancel = kMaxSocketsPerGroup + 2; 255 size_t index_to_cancel = kMaxSocketsPerGroup + 2;
232 EXPECT_TRUE(!reqs[index_to_cancel]->handle.is_initialized()); 256 EXPECT_TRUE(!reqs[index_to_cancel]->handle.is_initialized());
233 reqs[index_to_cancel]->handle.Reset(); 257 reqs[index_to_cancel]->handle.Reset();
234 258
235 // Release any connections until we have no connections. 259 // Release any connections until we have no connections.
236 bool released_one; 260 bool released_one;
237 do { 261 do {
238 released_one = false; 262 released_one = false;
239 for (size_t i = 0; i < arraysize(reqs); ++i) { 263 for (size_t i = 0; i < arraysize(reqs); ++i) {
240 if (reqs[i]->handle.is_initialized()) { 264 if (reqs[i]->handle.is_initialized()) {
241 reqs[i]->handle.Reset(); 265 reqs[i]->handle.Reset();
242 MessageLoop::current()->RunAllPending(); 266 MessageLoop::current()->RunAllPending();
243 released_one = true; 267 released_one = true;
244 } 268 }
245 } 269 }
246 } while (released_one); 270 } while (released_one);
247 271
248 EXPECT_EQ(kMaxSocketsPerGroup, MockClientSocket::allocation_count); 272 EXPECT_EQ(kMaxSocketsPerGroup, MockClientSocket::allocation_count);
249 EXPECT_EQ(9, TestSocketRequest::completion_count); 273 EXPECT_EQ(kNumPendingRequests - 1, TestSocketRequest::completion_count);
274 for (int i = 0; i < kMaxSocketsPerGroup; ++i) {
275 EXPECT_EQ(request_order_[i], reqs[i].get()) <<
276 "Request " << i << " was not in order.";
277 }
278
279 for (int i = 0; i < kNumPendingRequests - 1; ++i) {
280 if (i == 2) continue;
281 int index_in_queue = (kNumPendingRequests - 1) - kPriorities[i];
282 if (kPriorities[i] < kPriorities[index_to_cancel - kMaxSocketsPerGroup])
283 index_in_queue--;
284 EXPECT_EQ(request_order_[kMaxSocketsPerGroup + index_in_queue],
285 reqs[kMaxSocketsPerGroup + i].get()) <<
286 "Request " << kMaxSocketsPerGroup + i << " was not in order.";
287 }
288
289 EXPECT_EQ(request_order_[arraysize(reqs) - 2],
290 reqs[arraysize(reqs) - 1].get()) <<
291 "The last request with priority 1 should not have been inserted "
292 "earlier into the queue.";
250 } 293 }
294
295 } // namespace
OLDNEW
« no previous file with comments | « net/base/client_socket_pool.cc ('k') | net/http/http_network_transaction.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698