Chromium Code Reviews| Index: net/spdy/spdy_network_transaction_spdy2_unittest.cc |
| =================================================================== |
| --- net/spdy/spdy_network_transaction_spdy2_unittest.cc (revision 149736) |
| +++ net/spdy/spdy_network_transaction_spdy2_unittest.cc (working copy) |
| @@ -5130,6 +5130,129 @@ |
| EXPECT_TRUE(data.at_write_eof()); |
| } |
| +TEST_P(SpdyNetworkTransactionSpdy2Test, ServerPushWithNoStatusHeaderFrames) { |
|
Ryan Hamilton
2012/08/03 19:52:14
I want to confirm that if you run this test with t
ramant (doing other things)
2012/08/03 20:50:40
Yes it does. It crashes the code.
|
| + // We push a stream and attempt to claim it before the headers come down. |
| + static const unsigned char kPushBodyFrame[] = { |
| + 0x00, 0x00, 0x00, 0x02, // header, ID |
| + 0x01, 0x00, 0x00, 0x06, // FIN, length |
| + 'p', 'u', 's', 'h', 'e', 'd' // "pushed" |
| + }; |
| + scoped_ptr<SpdyFrame> |
| + stream1_syn(ConstructSpdyGet(NULL, 0, false, 1, LOWEST)); |
| + scoped_ptr<SpdyFrame> |
| + stream1_body(ConstructSpdyBodyFrame(1, true)); |
| + MockWrite writes[] = { |
| + CreateMockWrite(*stream1_syn, 0, SYNCHRONOUS), |
| + }; |
| + |
| + static const char* const kInitialHeaders[] = { |
| + "url", |
| + "http://www.google.com/foo.dat", |
| + }; |
| + static const char* const kMiddleHeaders[] = { |
| + "hello", |
| + "bye", |
| + }; |
| + scoped_ptr<SpdyFrame> |
| + stream2_syn(ConstructSpdyControlFrame(kInitialHeaders, |
| + arraysize(kInitialHeaders) / 2, |
| + false, |
| + 2, |
| + LOWEST, |
| + SYN_STREAM, |
| + CONTROL_FLAG_NONE, |
| + NULL, |
| + 0, |
| + 1)); |
| + scoped_ptr<SpdyFrame> |
| + stream2_headers1(ConstructSpdyControlFrame(kMiddleHeaders, |
| + arraysize(kMiddleHeaders) / 2, |
| + false, |
| + 2, |
| + LOWEST, |
| + HEADERS, |
| + CONTROL_FLAG_NONE, |
| + NULL, |
| + 0, |
| + 0)); |
| + |
| + scoped_ptr<SpdyFrame> |
| + stream1_reply(ConstructSpdyGetSynReply(NULL, 0, 1)); |
| + MockRead reads[] = { |
| + CreateMockRead(*stream1_reply, 1), |
| + CreateMockRead(*stream2_syn, 2), |
| + CreateMockRead(*stream1_body, 3), |
| + CreateMockRead(*stream2_headers1, 4), |
| + MockRead(ASYNC, reinterpret_cast<const char*>(kPushBodyFrame), |
| + arraysize(kPushBodyFrame), 5), |
| + MockRead(ASYNC, 0, 6), // EOF |
| + }; |
| + |
| + DeterministicSocketData data(reads, arraysize(reads), |
| + writes, arraysize(writes)); |
| + |
| + NormalSpdyTransactionHelper helper(CreateGetRequest(), |
| + BoundNetLog(), GetParam(), NULL); |
| + helper.SetDeterministic(); |
| + helper.AddDeterministicData(&data); |
| + helper.RunPreTestSetup(); |
| + |
| + HttpNetworkTransaction* trans = helper.trans(); |
| + |
| + // Run until we've received the primary SYN_STREAM, the pushed SYN_STREAM, |
| + // the first HEADERS frame, and the body of the primary stream, but before |
| + // we've received the final HEADERS for the pushed stream. |
| + data.SetStop(4); |
| + |
| + // Start the transaction. |
| + TestCompletionCallback callback; |
| + int rv = trans->Start( |
| + &CreateGetRequest(), callback.callback(), BoundNetLog()); |
| + EXPECT_EQ(ERR_IO_PENDING, rv); |
| + data.Run(); |
| + rv = callback.WaitForResult(); |
| + EXPECT_EQ(0, rv); |
| + |
| + // Request the pushed path. At this point, we've received the push, but the |
| + // headers are not yet complete. |
| + scoped_ptr<HttpNetworkTransaction> trans2( |
| + new HttpNetworkTransaction(helper.session())); |
| + rv = trans2->Start( |
| + &CreateGetPushRequest(), callback.callback(), BoundNetLog()); |
| + EXPECT_EQ(ERR_IO_PENDING, rv); |
| + data.RunFor(2); |
| + MessageLoop::current()->RunAllPending(); |
| + |
| + // Read the server push body. |
| + std::string result2; |
| + ReadResult(trans2.get(), &data, &result2); |
| + // Read the response body. |
| + std::string result; |
| + ReadResult(trans, &data, &result); |
| + EXPECT_EQ("hello!", result); |
| + |
| + // Verify that we haven't received any push data. |
| + EXPECT_EQ("", result2); |
| + |
| + // Verify the SYN_REPLY. |
| + // Copy the response info, because trans goes away. |
| + HttpResponseInfo response = *trans->GetResponseInfo(); |
| + ASSERT_TRUE(trans2->GetResponseInfo() == NULL); |
| + |
| + VerifyStreamsClosed(helper); |
| + |
| + // Verify the SYN_REPLY. |
| + EXPECT_TRUE(response.headers != NULL); |
| + EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine()); |
| + |
| + // Read the final EOF (which will close the session). |
| + data.RunFor(1); |
| + |
| + // Verify that we consumed all test data. |
| + EXPECT_TRUE(data.at_read_eof()); |
| + EXPECT_TRUE(data.at_write_eof()); |
| +} |
| + |
| TEST_P(SpdyNetworkTransactionSpdy2Test, SynReplyWithHeaders) { |
| scoped_ptr<SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST)); |
| MockWrite writes[] = { CreateMockWrite(*req) }; |