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

Side by Side Diff: net/websockets/websocket_job_test.cc

Issue 221833002: Test for WebSocketJob being deleted on the stack (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: Created 6 years, 8 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
« no previous file with comments | « net/websockets/websocket_job.cc ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "net/websockets/websocket_job.h" 5 #include "net/websockets/websocket_job.h"
6 6
7 #include <string> 7 #include <string>
8 #include <vector> 8 #include <vector>
9 9
10 #include "base/bind.h" 10 #include "base/bind.h"
(...skipping 298 matching lines...) Expand 10 before | Expand all | Expand 10 after
309 309
310 private: 310 private:
311 OrderedSocketData* data_; 311 OrderedSocketData* data_;
312 scoped_ptr<SpdySessionDependencies> session_deps_; 312 scoped_ptr<SpdySessionDependencies> session_deps_;
313 scoped_refptr<HttpNetworkSession> http_session_; 313 scoped_refptr<HttpNetworkSession> http_session_;
314 base::WeakPtr<SpdySession> session_; 314 base::WeakPtr<SpdySession> session_;
315 HostPortPair host_port_pair_; 315 HostPortPair host_port_pair_;
316 SpdySessionKey spdy_session_key_; 316 SpdySessionKey spdy_session_key_;
317 }; 317 };
318 318
319 class DeletingSocketStreamDelegate : public SocketStream::Delegate {
320 public:
321 DeletingSocketStreamDelegate()
322 : delete_next_(false) {}
323
324 // Since this class needs to be able to delete |job_|, it must be the only
325 // reference holder (except for temporary references). Provide access to the
326 // pointer for tests to use.
327 WebSocketJob* job() { return job_.get(); }
328
329 void set_job(WebSocketJob* job) { job_ = job; }
330
331 // After calling this, the next call to a method on this delegate will delete
332 // the WebSocketJob object.
333 void set_delete_next(bool delete_next) { delete_next_ = delete_next; }
334
335 void DeleteJobMaybe() {
336 if (delete_next_) {
337 job_->DetachContext();
338 job_->DetachDelegate();
339 job_ = NULL;
340 }
341 }
342
343 // SocketStream::Delegate implementation
344
345 // OnStartOpenConnection() is not implemented by SocketStreamDispatcherHost
346
347 virtual void OnConnected(SocketStream* socket,
348 int max_pending_send_allowed) OVERRIDE {
349 DeleteJobMaybe();
350 }
351
352 virtual void OnSentData(SocketStream* socket, int amount_sent) OVERRIDE {
353 DeleteJobMaybe();
354 }
355
356 virtual void OnReceivedData(SocketStream* socket,
357 const char* data,
358 int len) OVERRIDE {
359 DeleteJobMaybe();
360 }
361
362 virtual void OnClose(SocketStream* socket) OVERRIDE { DeleteJobMaybe(); }
363
364 virtual void OnAuthRequired(SocketStream* socket,
365 AuthChallengeInfo* auth_info) OVERRIDE {
366 DeleteJobMaybe();
367 }
368
369 virtual void OnSSLCertificateError(SocketStream* socket,
370 const SSLInfo& ssl_info,
371 bool fatal) OVERRIDE {
372 DeleteJobMaybe();
373 }
374
375 virtual void OnError(const SocketStream* socket, int error) OVERRIDE {
376 DeleteJobMaybe();
377 }
378
379 // CanGetCookies() and CanSetCookies() do not appear to be able to delete the
380 // WebSocketJob object.
381
382 private:
383 scoped_refptr<WebSocketJob> job_;
384 bool delete_next_;
385 };
386
319 } // namespace 387 } // namespace
320 388
321 class WebSocketJobTest : public PlatformTest, 389 class WebSocketJobTest : public PlatformTest,
322 public ::testing::WithParamInterface<NextProto> { 390 public ::testing::WithParamInterface<NextProto> {
323 public: 391 public:
324 WebSocketJobTest() : spdy_util_(GetParam()) {} 392 WebSocketJobTest() : spdy_util_(GetParam()) {}
325 393
326 virtual void SetUp() OVERRIDE { 394 virtual void SetUp() OVERRIDE {
327 stream_type_ = STREAM_INVALID; 395 stream_type_ = STREAM_INVALID;
328 cookie_store_ = new MockCookieStore; 396 cookie_store_ = new MockCookieStore;
(...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after
473 static const char* const kHandshakeResponseForSpdy[]; 541 static const char* const kHandshakeResponseForSpdy[];
474 static const size_t kHandshakeRequestWithoutCookieLength; 542 static const size_t kHandshakeRequestWithoutCookieLength;
475 static const size_t kHandshakeRequestWithCookieLength; 543 static const size_t kHandshakeRequestWithCookieLength;
476 static const size_t kHandshakeRequestWithFilteredCookieLength; 544 static const size_t kHandshakeRequestWithFilteredCookieLength;
477 static const size_t kHandshakeResponseWithoutCookieLength; 545 static const size_t kHandshakeResponseWithoutCookieLength;
478 static const size_t kHandshakeResponseWithCookieLength; 546 static const size_t kHandshakeResponseWithCookieLength;
479 static const size_t kDataHelloLength; 547 static const size_t kDataHelloLength;
480 static const size_t kDataWorldLength; 548 static const size_t kDataWorldLength;
481 }; 549 };
482 550
551 // Tests using this fixture verify that the WebSocketJob can handle being
552 // deleted while calling back to the delegate correctly. These tests need to be
553 // run under AddressSanitizer or other systems for detecting use-after-free
554 // errors in order to find problems.
555 class WebSocketJobDeleteTest : public ::testing::Test {
556 protected:
557 WebSocketJobDeleteTest()
558 : delegate_(new DeletingSocketStreamDelegate),
559 cookie_store_(new MockCookieStore),
560 context_(new MockURLRequestContext(cookie_store_.get())) {
561 WebSocketJob* websocket = new WebSocketJob(delegate_.get());
562 delegate_->set_job(websocket);
563
564 socket_ = new MockSocketStream(
565 GURL("ws://127.0.0.1/"), websocket, context_.get(), NULL);
566
567 websocket->InitSocketStream(socket_.get());
568 }
569
570 void SetDeleteNext() { return delegate_->set_delete_next(true); }
571 WebSocketJob* job() { return delegate_->job(); }
572
573 scoped_ptr<DeletingSocketStreamDelegate> delegate_;
574 scoped_refptr<MockCookieStore> cookie_store_;
575 scoped_ptr<MockURLRequestContext> context_;
576 scoped_refptr<SocketStream> socket_;
577 };
578
483 const char WebSocketJobTest::kHandshakeRequestWithoutCookie[] = 579 const char WebSocketJobTest::kHandshakeRequestWithoutCookie[] =
484 "GET /demo HTTP/1.1\r\n" 580 "GET /demo HTTP/1.1\r\n"
485 "Host: example.com\r\n" 581 "Host: example.com\r\n"
486 "Upgrade: WebSocket\r\n" 582 "Upgrade: WebSocket\r\n"
487 "Connection: Upgrade\r\n" 583 "Connection: Upgrade\r\n"
488 "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n" 584 "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"
489 "Origin: http://example.com\r\n" 585 "Origin: http://example.com\r\n"
490 "Sec-WebSocket-Protocol: sample\r\n" 586 "Sec-WebSocket-Protocol: sample\r\n"
491 "Sec-WebSocket-Version: 13\r\n" 587 "Sec-WebSocket-Version: 13\r\n"
492 "\r\n"; 588 "\r\n";
(...skipping 622 matching lines...) Expand 10 before | Expand all | Expand 10 after
1115 TEST_P(WebSocketJobTest, ThrottlingSpdy) { 1211 TEST_P(WebSocketJobTest, ThrottlingSpdy) {
1116 WebSocketJob::set_websocket_over_spdy_enabled(false); 1212 WebSocketJob::set_websocket_over_spdy_enabled(false);
1117 TestConnectBySpdy(SPDY_OFF, THROTTLING_ON); 1213 TestConnectBySpdy(SPDY_OFF, THROTTLING_ON);
1118 } 1214 }
1119 1215
1120 TEST_P(WebSocketJobTest, ThrottlingSpdySpdyEnabled) { 1216 TEST_P(WebSocketJobTest, ThrottlingSpdySpdyEnabled) {
1121 WebSocketJob::set_websocket_over_spdy_enabled(true); 1217 WebSocketJob::set_websocket_over_spdy_enabled(true);
1122 TestConnectBySpdy(SPDY_ON, THROTTLING_ON); 1218 TestConnectBySpdy(SPDY_ON, THROTTLING_ON);
1123 } 1219 }
1124 1220
1221 TEST_F(WebSocketJobDeleteTest, OnClose) {
1222 SetDeleteNext();
1223 // This one is tricky because OnClose() sets WebSocketJob::_socket to NULL,
1224 // so detaching it from within DeletingSocketStreamDelegate::DeleteJobMaybe()
1225 // doesn't work. Detach it first to prevent a DCHECK() failure.
tyoshino (SeeGerritForStatus) 2014/04/03 05:21:56 Which DCHECK?
Adam Rice 2014/04/03 06:03:04 socket_stream.cc:328 I have clarified the comment
1226 socket_->DetachDelegate();
1227 job()->OnClose(socket_.get());
1228 }
1229
1230 TEST_F(WebSocketJobDeleteTest, OnAuthRequired) {
1231 SetDeleteNext();
1232 job()->OnAuthRequired(socket_.get(), NULL);
1233 }
1234
1235 TEST_F(WebSocketJobDeleteTest, OnSSLCertificateError) {
1236 SSLInfo ssl_info;
1237 SetDeleteNext();
1238 job()->OnSSLCertificateError(socket_.get(), ssl_info, true);
1239 }
1240
1241 TEST_F(WebSocketJobDeleteTest, OnError) {
1242 SetDeleteNext();
1243 job()->OnError(socket_.get(), ERR_CONNECTION_RESET);
1244 }
1245
1246 TEST_F(WebSocketJobDeleteTest, OnSentSpdyHeaders) {
1247 job()->Connect();
1248 SetDeleteNext();
1249 job()->OnSentSpdyHeaders();
1250 }
1251
1252 TEST_F(WebSocketJobDeleteTest, OnSentHandshakeRequest) {
1253 static const char kMinimalRequest[] =
1254 "GET /demo HTTP/1.1\r\n"
1255 "Host: example.com\r\n"
1256 "Upgrade: WebSocket\r\n"
1257 "Connection: Upgrade\r\n"
1258 "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"
1259 "Origin: http://example.com\r\n"
1260 "Sec-WebSocket-Version: 13\r\n"
1261 "\r\n";
1262 const size_t kMinimalRequestSize = arraysize(kMinimalRequest) - 1;
1263 job()->Connect();
1264 job()->SendData(kMinimalRequest, kMinimalRequestSize);
1265 SetDeleteNext();
1266 job()->OnSentData(socket_.get(), kMinimalRequestSize);
1267 }
1268
1269 TEST_F(WebSocketJobDeleteTest, NotifyHeadersComplete) {
1270 static const char kMinimalResponse[] =
1271 "HTTP/1.1 101 Switching Protocols\r\n"
1272 "Upgrade: websocket\r\n"
1273 "Connection: Upgrade\r\n"
1274 "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n"
1275 "\r\n";
1276 job()->Connect();
1277 SetDeleteNext();
1278 job()->OnReceivedData(
1279 socket_.get(), kMinimalResponse, arraysize(kMinimalResponse) - 1);
1280 }
1281
tyoshino (SeeGerritForStatus) 2014/04/03 05:21:56 let's check that delegate_->job() is NULL at the e
Adam Rice 2014/04/03 06:03:04 Done.
1125 // TODO(toyoshim): Add tests to verify throttling, SPDY stream limitation. 1282 // TODO(toyoshim): Add tests to verify throttling, SPDY stream limitation.
1126 // TODO(toyoshim,yutak): Add tests to verify closing handshake. 1283 // TODO(toyoshim,yutak): Add tests to verify closing handshake.
1127 } // namespace net 1284 } // namespace net
OLDNEW
« no previous file with comments | « net/websockets/websocket_job.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698