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

Side by Side Diff: net/spdy/spdy_network_transaction_unittest.cc

Issue 18114008: [SPDY] Organize tests by minimum version needed (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 7 years, 5 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/spdy/spdy_http_stream_unittest.cc ('k') | net/spdy/spdy_session_unittest.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) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 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 <string> 5 #include <string>
6 #include <vector> 6 #include <vector>
7 7
8 #include "base/bind.h" 8 #include "base/bind.h"
9 #include "base/bind_helpers.h" 9 #include "base/bind_helpers.h"
10 #include "base/file_util.h" 10 #include "base/file_util.h"
(...skipping 2139 matching lines...) Expand 10 before | Expand all | Expand 10 after
2150 ASSERT_TRUE(response != NULL); 2150 ASSERT_TRUE(response != NULL);
2151 EXPECT_TRUE(response->headers.get() != NULL); 2151 EXPECT_TRUE(response->headers.get() != NULL);
2152 EXPECT_TRUE(response->was_fetched_via_spdy); 2152 EXPECT_TRUE(response->was_fetched_via_spdy);
2153 std::string response_data; 2153 std::string response_data;
2154 rv = ReadTransaction(trans, &response_data); 2154 rv = ReadTransaction(trans, &response_data);
2155 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, rv); 2155 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, rv);
2156 2156
2157 helper.VerifyDataConsumed(); 2157 helper.VerifyDataConsumed();
2158 } 2158 }
2159 2159
2160 // Test that sent data frames and received WINDOW_UPDATE frames change
2161 // the send_window_size_ correctly.
2162
2163 // WINDOW_UPDATE is different than most other frames in that it can arrive
2164 // while the client is still sending the request body. In order to enforce
2165 // this scenario, we feed a couple of dummy frames and give a delay of 0 to
2166 // socket data provider, so that initial read that is done as soon as the
2167 // stream is created, succeeds and schedules another read. This way reads
2168 // and writes are interleaved; after doing a full frame write, SpdyStream
2169 // will break out of DoLoop and will read and process a WINDOW_UPDATE.
2170 // Once our WINDOW_UPDATE is read, we cannot send SYN_REPLY right away
2171 // since request has not been completely written, therefore we feed
2172 // enough number of WINDOW_UPDATEs to finish the first read and cause a
2173 // write, leading to a complete write of request body; after that we send
2174 // a reply with a body, to cause a graceful shutdown.
2175
2176 // TODO(agayev): develop a socket data provider where both, reads and
2177 // writes are ordered so that writing tests like these are easy and rewrite
2178 // all these tests using it. Right now we are working around the
2179 // limitations as described above and it's not deterministic, tests may
2180 // fail under specific circumstances.
2181 TEST_P(SpdyNetworkTransactionTest, WindowUpdateReceived) {
2182 if (GetParam().protocol < kProtoSPDY3)
2183 return;
2184
2185 static int kFrameCount = 2;
2186 scoped_ptr<std::string> content(
2187 new std::string(kMaxSpdyFrameChunkSize, 'a'));
2188 scoped_ptr<SpdyFrame> req(spdy_util_.ConstructSpdyPost(
2189 kRequestUrl, 1, kMaxSpdyFrameChunkSize * kFrameCount, LOWEST, NULL, 0));
2190 scoped_ptr<SpdyFrame> body(
2191 spdy_util_.ConstructSpdyBodyFrame(
2192 1, content->c_str(), content->size(), false));
2193 scoped_ptr<SpdyFrame> body_end(
2194 spdy_util_.ConstructSpdyBodyFrame(
2195 1, content->c_str(), content->size(), true));
2196
2197 MockWrite writes[] = {
2198 CreateMockWrite(*req, 0),
2199 CreateMockWrite(*body, 1),
2200 CreateMockWrite(*body_end, 2),
2201 };
2202
2203 static const int32 kDeltaWindowSize = 0xff;
2204 static const int kDeltaCount = 4;
2205 scoped_ptr<SpdyFrame> window_update(
2206 spdy_util_.ConstructSpdyWindowUpdate(1, kDeltaWindowSize));
2207 scoped_ptr<SpdyFrame> window_update_dummy(
2208 spdy_util_.ConstructSpdyWindowUpdate(2, kDeltaWindowSize));
2209 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
2210 MockRead reads[] = {
2211 CreateMockRead(*window_update_dummy, 3),
2212 CreateMockRead(*window_update_dummy, 4),
2213 CreateMockRead(*window_update_dummy, 5),
2214 CreateMockRead(*window_update, 6), // Four updates, therefore window
2215 CreateMockRead(*window_update, 7), // size should increase by
2216 CreateMockRead(*window_update, 8), // kDeltaWindowSize * 4
2217 CreateMockRead(*window_update, 9),
2218 CreateMockRead(*resp, 10),
2219 CreateMockRead(*body_end, 11),
2220 MockRead(ASYNC, 0, 0, 12) // EOF
2221 };
2222
2223 DeterministicSocketData data(reads, arraysize(reads),
2224 writes, arraysize(writes));
2225
2226 ScopedVector<UploadElementReader> element_readers;
2227 for (int i = 0; i < kFrameCount; ++i) {
2228 element_readers.push_back(
2229 new UploadBytesElementReader(content->c_str(), content->size()));
2230 }
2231 UploadDataStream upload_data_stream(&element_readers, 0);
2232
2233 // Setup the request
2234 HttpRequestInfo request;
2235 request.method = "POST";
2236 request.url = GURL(kDefaultURL);
2237 request.upload_data_stream = &upload_data_stream;
2238
2239 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY,
2240 BoundNetLog(), GetParam(), NULL);
2241 helper.SetDeterministic();
2242 helper.AddDeterministicData(&data);
2243 helper.RunPreTestSetup();
2244
2245 HttpNetworkTransaction* trans = helper.trans();
2246
2247 TestCompletionCallback callback;
2248 int rv = trans->Start(&helper.request(), callback.callback(), BoundNetLog());
2249
2250 EXPECT_EQ(ERR_IO_PENDING, rv);
2251
2252 data.RunFor(11);
2253
2254 SpdyHttpStream* stream = static_cast<SpdyHttpStream*>(trans->stream_.get());
2255 ASSERT_TRUE(stream != NULL);
2256 ASSERT_TRUE(stream->stream() != NULL);
2257 EXPECT_EQ(static_cast<int>(kSpdyStreamInitialWindowSize) +
2258 kDeltaWindowSize * kDeltaCount -
2259 kMaxSpdyFrameChunkSize * kFrameCount,
2260 stream->stream()->send_window_size());
2261
2262 data.RunFor(1);
2263
2264 rv = callback.WaitForResult();
2265 EXPECT_EQ(OK, rv);
2266
2267 helper.VerifyDataConsumed();
2268 }
2269
2270 // Test that received data frames and sent WINDOW_UPDATE frames change
2271 // the recv_window_size_ correctly.
2272 TEST_P(SpdyNetworkTransactionTest, WindowUpdateSent) {
2273 if (GetParam().protocol < kProtoSPDY3)
2274 return;
2275
2276 // Set the data in the body frame large enough to trigger sending a
2277 // WINDOW_UPDATE by the stream.
2278 const std::string body_data(kSpdyStreamInitialWindowSize / 2 + 1, 'x');
2279
2280 scoped_ptr<SpdyFrame> req(
2281 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
2282 scoped_ptr<SpdyFrame> session_window_update(
2283 spdy_util_.ConstructSpdyWindowUpdate(0, body_data.size()));
2284 scoped_ptr<SpdyFrame> window_update(
2285 spdy_util_.ConstructSpdyWindowUpdate(1, body_data.size()));
2286
2287 std::vector<MockWrite> writes;
2288 writes.push_back(CreateMockWrite(*req));
2289 if (GetParam().protocol >= kProtoSPDY31)
2290 writes.push_back(CreateMockWrite(*session_window_update));
2291 writes.push_back(CreateMockWrite(*window_update));
2292
2293 scoped_ptr<SpdyFrame> resp(
2294 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2295 scoped_ptr<SpdyFrame> body_no_fin(
2296 spdy_util_.ConstructSpdyBodyFrame(
2297 1, body_data.data(), body_data.size(), false));
2298 scoped_ptr<SpdyFrame> body_fin(
2299 spdy_util_.ConstructSpdyBodyFrame(1, NULL, 0, true));
2300 MockRead reads[] = {
2301 CreateMockRead(*resp),
2302 CreateMockRead(*body_no_fin),
2303 MockRead(ASYNC, ERR_IO_PENDING, 0), // Force a pause
2304 CreateMockRead(*body_fin),
2305 MockRead(ASYNC, ERR_IO_PENDING, 0), // Force a pause
2306 MockRead(ASYNC, 0, 0) // EOF
2307 };
2308
2309 DelayedSocketData data(1, reads, arraysize(reads),
2310 vector_as_array(&writes), writes.size());
2311
2312 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
2313 BoundNetLog(), GetParam(), NULL);
2314 helper.AddData(&data);
2315 helper.RunPreTestSetup();
2316 HttpNetworkTransaction* trans = helper.trans();
2317
2318 TestCompletionCallback callback;
2319 int rv = trans->Start(&helper.request(), callback.callback(), BoundNetLog());
2320
2321 EXPECT_EQ(ERR_IO_PENDING, rv);
2322 rv = callback.WaitForResult();
2323 EXPECT_EQ(OK, rv);
2324
2325 SpdyHttpStream* stream =
2326 static_cast<SpdyHttpStream*>(trans->stream_.get());
2327 ASSERT_TRUE(stream != NULL);
2328 ASSERT_TRUE(stream->stream() != NULL);
2329
2330 EXPECT_EQ(
2331 static_cast<int>(kSpdyStreamInitialWindowSize - body_data.size()),
2332 stream->stream()->recv_window_size());
2333
2334 const HttpResponseInfo* response = trans->GetResponseInfo();
2335 ASSERT_TRUE(response != NULL);
2336 ASSERT_TRUE(response->headers.get() != NULL);
2337 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
2338 EXPECT_TRUE(response->was_fetched_via_spdy);
2339
2340 // Issue a read which will cause a WINDOW_UPDATE to be sent and window
2341 // size increased to default.
2342 scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(body_data.size()));
2343 rv = trans->Read(buf.get(), body_data.size(), CompletionCallback());
2344 EXPECT_EQ(static_cast<int>(body_data.size()), rv);
2345 std::string content(buf->data(), buf->data() + body_data.size());
2346 EXPECT_EQ(body_data, content);
2347
2348 // Schedule the reading of empty data frame with FIN
2349 data.CompleteRead();
2350
2351 // Force write of WINDOW_UPDATE which was scheduled during the above
2352 // read.
2353 base::MessageLoop::current()->RunUntilIdle();
2354
2355 // Read EOF.
2356 data.CompleteRead();
2357
2358 helper.VerifyDataConsumed();
2359 }
2360
2361 // Test that WINDOW_UPDATE frame causing overflow is handled correctly.
2362 TEST_P(SpdyNetworkTransactionTest, WindowUpdateOverflow) {
2363 if (GetParam().protocol < kProtoSPDY3)
2364 return;
2365
2366 // Number of full frames we hope to write (but will not, used to
2367 // set content-length header correctly)
2368 static int kFrameCount = 3;
2369
2370 scoped_ptr<std::string> content(
2371 new std::string(kMaxSpdyFrameChunkSize, 'a'));
2372 scoped_ptr<SpdyFrame> req(spdy_util_.ConstructSpdyPost(
2373 kRequestUrl, 1, kMaxSpdyFrameChunkSize * kFrameCount, LOWEST, NULL, 0));
2374 scoped_ptr<SpdyFrame> body(
2375 spdy_util_.ConstructSpdyBodyFrame(
2376 1, content->c_str(), content->size(), false));
2377 scoped_ptr<SpdyFrame> rst(
2378 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_FLOW_CONTROL_ERROR));
2379
2380 // We're not going to write a data frame with FIN, we'll receive a bad
2381 // WINDOW_UPDATE while sending a request and will send a RST_STREAM frame.
2382 MockWrite writes[] = {
2383 CreateMockWrite(*req, 0),
2384 CreateMockWrite(*body, 2),
2385 CreateMockWrite(*rst, 3),
2386 };
2387
2388 static const int32 kDeltaWindowSize = 0x7fffffff; // cause an overflow
2389 scoped_ptr<SpdyFrame> window_update(
2390 spdy_util_.ConstructSpdyWindowUpdate(1, kDeltaWindowSize));
2391 MockRead reads[] = {
2392 CreateMockRead(*window_update, 1),
2393 MockRead(ASYNC, 0, 4) // EOF
2394 };
2395
2396 DeterministicSocketData data(reads, arraysize(reads),
2397 writes, arraysize(writes));
2398
2399 ScopedVector<UploadElementReader> element_readers;
2400 for (int i = 0; i < kFrameCount; ++i) {
2401 element_readers.push_back(
2402 new UploadBytesElementReader(content->c_str(), content->size()));
2403 }
2404 UploadDataStream upload_data_stream(&element_readers, 0);
2405
2406 // Setup the request
2407 HttpRequestInfo request;
2408 request.method = "POST";
2409 request.url = GURL("http://www.google.com/");
2410 request.upload_data_stream = &upload_data_stream;
2411
2412 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY,
2413 BoundNetLog(), GetParam(), NULL);
2414 helper.SetDeterministic();
2415 helper.RunPreTestSetup();
2416 helper.AddDeterministicData(&data);
2417 HttpNetworkTransaction* trans = helper.trans();
2418
2419 TestCompletionCallback callback;
2420 int rv = trans->Start(&helper.request(), callback.callback(), BoundNetLog());
2421 ASSERT_EQ(ERR_IO_PENDING, rv);
2422
2423 data.RunFor(5);
2424 ASSERT_TRUE(callback.have_result());
2425 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, callback.WaitForResult());
2426 helper.VerifyDataConsumed();
2427 }
2428
2429 // Test that after hitting a send window size of 0, the write process
2430 // stalls and upon receiving WINDOW_UPDATE frame write resumes.
2431
2432 // This test constructs a POST request followed by enough data frames
2433 // containing 'a' that would make the window size 0, followed by another
2434 // data frame containing default content (which is "hello!") and this frame
2435 // also contains a FIN flag. DelayedSocketData is used to enforce all
2436 // writes go through before a read could happen. However, the last frame
2437 // ("hello!") is not supposed to go through since by the time its turn
2438 // arrives, window size is 0. At this point MessageLoop::Run() called via
2439 // callback would block. Therefore we call MessageLoop::RunUntilIdle()
2440 // which returns after performing all possible writes. We use DCHECKS to
2441 // ensure that last data frame is still there and stream has stalled.
2442 // After that, next read is artifically enforced, which causes a
2443 // WINDOW_UPDATE to be read and I/O process resumes.
2444 TEST_P(SpdyNetworkTransactionTest, FlowControlStallResume) {
2445 if (GetParam().protocol < kProtoSPDY3)
2446 return;
2447
2448 // Number of frames we need to send to zero out the window size: data
2449 // frames plus SYN_STREAM plus the last data frame; also we need another
2450 // data frame that we will send once the WINDOW_UPDATE is received,
2451 // therefore +3.
2452 size_t num_writes = kSpdyStreamInitialWindowSize / kMaxSpdyFrameChunkSize + 3;
2453
2454 // Calculate last frame's size; 0 size data frame is legal.
2455 size_t last_frame_size =
2456 kSpdyStreamInitialWindowSize % kMaxSpdyFrameChunkSize;
2457
2458 // Construct content for a data frame of maximum size.
2459 std::string content(kMaxSpdyFrameChunkSize, 'a');
2460
2461 scoped_ptr<SpdyFrame> req(spdy_util_.ConstructSpdyPost(
2462 kRequestUrl, 1, kSpdyStreamInitialWindowSize + kUploadDataSize,
2463 LOWEST, NULL, 0));
2464
2465 // Full frames.
2466 scoped_ptr<SpdyFrame> body1(
2467 spdy_util_.ConstructSpdyBodyFrame(
2468 1, content.c_str(), content.size(), false));
2469
2470 // Last frame to zero out the window size.
2471 scoped_ptr<SpdyFrame> body2(
2472 spdy_util_.ConstructSpdyBodyFrame(
2473 1, content.c_str(), last_frame_size, false));
2474
2475 // Data frame to be sent once WINDOW_UPDATE frame is received.
2476 scoped_ptr<SpdyFrame> body3(spdy_util_.ConstructSpdyBodyFrame(1, true));
2477
2478 // Fill in mock writes.
2479 scoped_ptr<MockWrite[]> writes(new MockWrite[num_writes]);
2480 size_t i = 0;
2481 writes[i] = CreateMockWrite(*req);
2482 for (i = 1; i < num_writes - 2; i++)
2483 writes[i] = CreateMockWrite(*body1);
2484 writes[i++] = CreateMockWrite(*body2);
2485 writes[i] = CreateMockWrite(*body3);
2486
2487 // Construct read frame, give enough space to upload the rest of the
2488 // data.
2489 scoped_ptr<SpdyFrame> session_window_update(
2490 spdy_util_.ConstructSpdyWindowUpdate(0, kUploadDataSize));
2491 scoped_ptr<SpdyFrame> window_update(
2492 spdy_util_.ConstructSpdyWindowUpdate(1, kUploadDataSize));
2493 scoped_ptr<SpdyFrame> reply(spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
2494 MockRead reads[] = {
2495 CreateMockRead(*session_window_update),
2496 CreateMockRead(*session_window_update),
2497 CreateMockRead(*window_update),
2498 CreateMockRead(*window_update),
2499 CreateMockRead(*reply),
2500 CreateMockRead(*body2),
2501 CreateMockRead(*body3),
2502 MockRead(ASYNC, 0, 0) // EOF
2503 };
2504
2505 // Skip the session window updates unless we're using SPDY/3.1 and
2506 // above.
2507 size_t read_offset = (GetParam().protocol >= kProtoSPDY31) ? 0 : 2;
2508 size_t num_reads = arraysize(reads) - read_offset;
2509
2510 // Force all writes to happen before any read, last write will not
2511 // actually queue a frame, due to window size being 0.
2512 DelayedSocketData data(num_writes, reads + read_offset, num_reads,
2513 writes.get(), num_writes);
2514
2515 ScopedVector<UploadElementReader> element_readers;
2516 std::string upload_data_string(kSpdyStreamInitialWindowSize, 'a');
2517 upload_data_string.append(kUploadData, kUploadDataSize);
2518 element_readers.push_back(new UploadBytesElementReader(
2519 upload_data_string.c_str(), upload_data_string.size()));
2520 UploadDataStream upload_data_stream(&element_readers, 0);
2521
2522 HttpRequestInfo request;
2523 request.method = "POST";
2524 request.url = GURL("http://www.google.com/");
2525 request.upload_data_stream = &upload_data_stream;
2526 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY,
2527 BoundNetLog(), GetParam(), NULL);
2528 helper.AddData(&data);
2529 helper.RunPreTestSetup();
2530
2531 HttpNetworkTransaction* trans = helper.trans();
2532
2533 TestCompletionCallback callback;
2534 int rv = trans->Start(&helper.request(), callback.callback(), BoundNetLog());
2535 EXPECT_EQ(ERR_IO_PENDING, rv);
2536
2537 base::MessageLoop::current()->RunUntilIdle(); // Write as much as we can.
2538
2539 SpdyHttpStream* stream = static_cast<SpdyHttpStream*>(trans->stream_.get());
2540 ASSERT_TRUE(stream != NULL);
2541 ASSERT_TRUE(stream->stream() != NULL);
2542 EXPECT_EQ(0, stream->stream()->send_window_size());
2543 // All the body data should have been read.
2544 // TODO(satorux): This is because of the weirdness in reading the request
2545 // body in OnSendBodyComplete(). See crbug.com/113107.
2546 EXPECT_TRUE(upload_data_stream.IsEOF());
2547 // But the body is not yet fully sent (kUploadData is not yet sent)
2548 // since we're send-stalled.
2549 EXPECT_TRUE(stream->stream()->send_stalled_by_flow_control());
2550
2551 data.ForceNextRead(); // Read in WINDOW_UPDATE frame.
2552 rv = callback.WaitForResult();
2553 helper.VerifyDataConsumed();
2554 }
2555
2556 // Test we correctly handle the case where the SETTINGS frame results in
2557 // unstalling the send window.
2558 TEST_P(SpdyNetworkTransactionTest, FlowControlStallResumeAfterSettings) {
2559 if (GetParam().protocol < kProtoSPDY3)
2560 return;
2561
2562 // Number of frames we need to send to zero out the window size: data
2563 // frames plus SYN_STREAM plus the last data frame; also we need another
2564 // data frame that we will send once the SETTING is received, therefore +3.
2565 size_t num_writes = kSpdyStreamInitialWindowSize / kMaxSpdyFrameChunkSize + 3;
2566
2567 // Calculate last frame's size; 0 size data frame is legal.
2568 size_t last_frame_size =
2569 kSpdyStreamInitialWindowSize % kMaxSpdyFrameChunkSize;
2570
2571 // Construct content for a data frame of maximum size.
2572 std::string content(kMaxSpdyFrameChunkSize, 'a');
2573
2574 scoped_ptr<SpdyFrame> req(spdy_util_.ConstructSpdyPost(
2575 kRequestUrl, 1, kSpdyStreamInitialWindowSize + kUploadDataSize,
2576 LOWEST, NULL, 0));
2577
2578 // Full frames.
2579 scoped_ptr<SpdyFrame> body1(
2580 spdy_util_.ConstructSpdyBodyFrame(
2581 1, content.c_str(), content.size(), false));
2582
2583 // Last frame to zero out the window size.
2584 scoped_ptr<SpdyFrame> body2(
2585 spdy_util_.ConstructSpdyBodyFrame(
2586 1, content.c_str(), last_frame_size, false));
2587
2588 // Data frame to be sent once SETTINGS frame is received.
2589 scoped_ptr<SpdyFrame> body3(spdy_util_.ConstructSpdyBodyFrame(1, true));
2590
2591 // Fill in mock reads/writes.
2592 std::vector<MockRead> reads;
2593 std::vector<MockWrite> writes;
2594 size_t i = 0;
2595 writes.push_back(CreateMockWrite(*req, i++));
2596 while (i < num_writes - 2)
2597 writes.push_back(CreateMockWrite(*body1, i++));
2598 writes.push_back(CreateMockWrite(*body2, i++));
2599
2600 // Construct read frame for SETTINGS that gives enough space to upload the
2601 // rest of the data.
2602 SettingsMap settings;
2603 settings[SETTINGS_INITIAL_WINDOW_SIZE] =
2604 SettingsFlagsAndValue(
2605 SETTINGS_FLAG_NONE, kSpdyStreamInitialWindowSize * 2);
2606 scoped_ptr<SpdyFrame> settings_frame_large(
2607 spdy_util_.ConstructSpdySettings(settings));
2608
2609 reads.push_back(CreateMockRead(*settings_frame_large, i++));
2610
2611 scoped_ptr<SpdyFrame> session_window_update(
2612 spdy_util_.ConstructSpdyWindowUpdate(0, kUploadDataSize));
2613 if (GetParam().protocol >= kProtoSPDY31)
2614 reads.push_back(CreateMockRead(*session_window_update, i++));
2615
2616 writes.push_back(CreateMockWrite(*body3, i++));
2617
2618 scoped_ptr<SpdyFrame> reply(spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
2619 reads.push_back(CreateMockRead(*reply, i++));
2620 reads.push_back(CreateMockRead(*body2, i++));
2621 reads.push_back(CreateMockRead(*body3, i++));
2622 reads.push_back(MockRead(ASYNC, 0, i++)); // EOF
2623
2624 // Force all writes to happen before any read, last write will not
2625 // actually queue a frame, due to window size being 0.
2626 DeterministicSocketData data(vector_as_array(&reads), reads.size(),
2627 vector_as_array(&writes), writes.size());
2628
2629 ScopedVector<UploadElementReader> element_readers;
2630 std::string upload_data_string(kSpdyStreamInitialWindowSize, 'a');
2631 upload_data_string.append(kUploadData, kUploadDataSize);
2632 element_readers.push_back(new UploadBytesElementReader(
2633 upload_data_string.c_str(), upload_data_string.size()));
2634 UploadDataStream upload_data_stream(&element_readers, 0);
2635
2636 HttpRequestInfo request;
2637 request.method = "POST";
2638 request.url = GURL("http://www.google.com/");
2639 request.upload_data_stream = &upload_data_stream;
2640 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY,
2641 BoundNetLog(), GetParam(), NULL);
2642 helper.SetDeterministic();
2643 helper.RunPreTestSetup();
2644 helper.AddDeterministicData(&data);
2645
2646 HttpNetworkTransaction* trans = helper.trans();
2647
2648 TestCompletionCallback callback;
2649 int rv = trans->Start(&helper.request(), callback.callback(), BoundNetLog());
2650 EXPECT_EQ(ERR_IO_PENDING, rv);
2651
2652 data.RunFor(num_writes - 1); // Write as much as we can.
2653
2654 SpdyHttpStream* stream = static_cast<SpdyHttpStream*>(trans->stream_.get());
2655 ASSERT_TRUE(stream != NULL);
2656 ASSERT_TRUE(stream->stream() != NULL);
2657 EXPECT_EQ(0, stream->stream()->send_window_size());
2658
2659 // All the body data should have been read.
2660 // TODO(satorux): This is because of the weirdness in reading the request
2661 // body in OnSendBodyComplete(). See crbug.com/113107.
2662 EXPECT_TRUE(upload_data_stream.IsEOF());
2663 // But the body is not yet fully sent (kUploadData is not yet sent)
2664 // since we're send-stalled.
2665 EXPECT_TRUE(stream->stream()->send_stalled_by_flow_control());
2666
2667 data.RunFor(6); // Read in SETTINGS frame to unstall.
2668 rv = callback.WaitForResult();
2669 helper.VerifyDataConsumed();
2670 // If stream is NULL, that means it was unstalled and closed.
2671 EXPECT_TRUE(stream->stream() == NULL);
2672 }
2673
2674 // Test we correctly handle the case where the SETTINGS frame results in a
2675 // negative send window size.
2676 TEST_P(SpdyNetworkTransactionTest, FlowControlNegativeSendWindowSize) {
2677 if (GetParam().protocol < kProtoSPDY3)
2678 return;
2679
2680 // Number of frames we need to send to zero out the window size: data
2681 // frames plus SYN_STREAM plus the last data frame; also we need another
2682 // data frame that we will send once the SETTING is received, therefore +3.
2683 size_t num_writes = kSpdyStreamInitialWindowSize / kMaxSpdyFrameChunkSize + 3;
2684
2685 // Calculate last frame's size; 0 size data frame is legal.
2686 size_t last_frame_size =
2687 kSpdyStreamInitialWindowSize % kMaxSpdyFrameChunkSize;
2688
2689 // Construct content for a data frame of maximum size.
2690 std::string content(kMaxSpdyFrameChunkSize, 'a');
2691
2692 scoped_ptr<SpdyFrame> req(spdy_util_.ConstructSpdyPost(
2693 kRequestUrl, 1, kSpdyStreamInitialWindowSize + kUploadDataSize,
2694 LOWEST, NULL, 0));
2695
2696 // Full frames.
2697 scoped_ptr<SpdyFrame> body1(
2698 spdy_util_.ConstructSpdyBodyFrame(
2699 1, content.c_str(), content.size(), false));
2700
2701 // Last frame to zero out the window size.
2702 scoped_ptr<SpdyFrame> body2(
2703 spdy_util_.ConstructSpdyBodyFrame(
2704 1, content.c_str(), last_frame_size, false));
2705
2706 // Data frame to be sent once SETTINGS frame is received.
2707 scoped_ptr<SpdyFrame> body3(spdy_util_.ConstructSpdyBodyFrame(1, true));
2708
2709 // Fill in mock reads/writes.
2710 std::vector<MockRead> reads;
2711 std::vector<MockWrite> writes;
2712 size_t i = 0;
2713 writes.push_back(CreateMockWrite(*req, i++));
2714 while (i < num_writes - 2)
2715 writes.push_back(CreateMockWrite(*body1, i++));
2716 writes.push_back(CreateMockWrite(*body2, i++));
2717
2718 // Construct read frame for SETTINGS that makes the send_window_size
2719 // negative.
2720 SettingsMap new_settings;
2721 new_settings[SETTINGS_INITIAL_WINDOW_SIZE] =
2722 SettingsFlagsAndValue(
2723 SETTINGS_FLAG_NONE, kSpdyStreamInitialWindowSize / 2);
2724 scoped_ptr<SpdyFrame> settings_frame_small(
2725 spdy_util_.ConstructSpdySettings(new_settings));
2726 // Construct read frames for WINDOW_UPDATE that makes the send_window_size
2727 // positive.
2728 scoped_ptr<SpdyFrame> session_window_update_init_size(
2729 spdy_util_.ConstructSpdyWindowUpdate(0, kSpdyStreamInitialWindowSize));
2730 scoped_ptr<SpdyFrame> window_update_init_size(
2731 spdy_util_.ConstructSpdyWindowUpdate(1, kSpdyStreamInitialWindowSize));
2732
2733 reads.push_back(CreateMockRead(*settings_frame_small, i++));
2734
2735 if (GetParam().protocol >= kProtoSPDY3)
2736 reads.push_back(CreateMockRead(*session_window_update_init_size, i++));
2737
2738 reads.push_back(CreateMockRead(*window_update_init_size, i++));
2739
2740 writes.push_back(CreateMockWrite(*body3, i++));
2741
2742 scoped_ptr<SpdyFrame> reply(spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
2743 reads.push_back(CreateMockRead(*reply, i++));
2744 reads.push_back(CreateMockRead(*body2, i++));
2745 reads.push_back(CreateMockRead(*body3, i++));
2746 reads.push_back(MockRead(ASYNC, 0, i++)); // EOF
2747
2748 // Force all writes to happen before any read, last write will not
2749 // actually queue a frame, due to window size being 0.
2750 DeterministicSocketData data(vector_as_array(&reads), reads.size(),
2751 vector_as_array(&writes), writes.size());
2752
2753 ScopedVector<UploadElementReader> element_readers;
2754 std::string upload_data_string(kSpdyStreamInitialWindowSize, 'a');
2755 upload_data_string.append(kUploadData, kUploadDataSize);
2756 element_readers.push_back(new UploadBytesElementReader(
2757 upload_data_string.c_str(), upload_data_string.size()));
2758 UploadDataStream upload_data_stream(&element_readers, 0);
2759
2760 HttpRequestInfo request;
2761 request.method = "POST";
2762 request.url = GURL("http://www.google.com/");
2763 request.upload_data_stream = &upload_data_stream;
2764 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY,
2765 BoundNetLog(), GetParam(), NULL);
2766 helper.SetDeterministic();
2767 helper.RunPreTestSetup();
2768 helper.AddDeterministicData(&data);
2769
2770 HttpNetworkTransaction* trans = helper.trans();
2771
2772 TestCompletionCallback callback;
2773 int rv = trans->Start(&helper.request(), callback.callback(), BoundNetLog());
2774 EXPECT_EQ(ERR_IO_PENDING, rv);
2775
2776 data.RunFor(num_writes - 1); // Write as much as we can.
2777
2778 SpdyHttpStream* stream = static_cast<SpdyHttpStream*>(trans->stream_.get());
2779 ASSERT_TRUE(stream != NULL);
2780 ASSERT_TRUE(stream->stream() != NULL);
2781 EXPECT_EQ(0, stream->stream()->send_window_size());
2782
2783 // All the body data should have been read.
2784 // TODO(satorux): This is because of the weirdness in reading the request
2785 // body in OnSendBodyComplete(). See crbug.com/113107.
2786 EXPECT_TRUE(upload_data_stream.IsEOF());
2787 // But the body is not yet fully sent (kUploadData is not yet sent)
2788 // since we're send-stalled.
2789 EXPECT_TRUE(stream->stream()->send_stalled_by_flow_control());
2790
2791 // Read in WINDOW_UPDATE or SETTINGS frame.
2792 data.RunFor((GetParam().protocol >= kProtoSPDY31) ? 8 : 7);
2793 rv = callback.WaitForResult();
2794 helper.VerifyDataConsumed();
2795 }
2796
2797 TEST_P(SpdyNetworkTransactionTest, ResetReplyWithTransferEncoding) { 2160 TEST_P(SpdyNetworkTransactionTest, ResetReplyWithTransferEncoding) {
2798 // Construct the request. 2161 // Construct the request.
2799 scoped_ptr<SpdyFrame> req( 2162 scoped_ptr<SpdyFrame> req(
2800 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true)); 2163 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
2801 scoped_ptr<SpdyFrame> rst( 2164 scoped_ptr<SpdyFrame> rst(
2802 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_PROTOCOL_ERROR)); 2165 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_PROTOCOL_ERROR));
2803 MockWrite writes[] = { 2166 MockWrite writes[] = {
2804 CreateMockWrite(*req), 2167 CreateMockWrite(*req),
2805 CreateMockWrite(*rst), 2168 CreateMockWrite(*rst),
2806 }; 2169 };
(...skipping 1094 matching lines...) Expand 10 before | Expand all | Expand 10 after
3901 } 3264 }
3902 } 3265 }
3903 3266
3904 // Verify that various SynReply headers parse vary fields correctly 3267 // Verify that various SynReply headers parse vary fields correctly
3905 // through the HTTP layer, and the response matches the request. 3268 // through the HTTP layer, and the response matches the request.
3906 TEST_P(SpdyNetworkTransactionTest, SynReplyHeadersVary) { 3269 TEST_P(SpdyNetworkTransactionTest, SynReplyHeadersVary) {
3907 static const SpdyHeaderInfo syn_reply_info = { 3270 static const SpdyHeaderInfo syn_reply_info = {
3908 SYN_REPLY, // Syn Reply 3271 SYN_REPLY, // Syn Reply
3909 1, // Stream ID 3272 1, // Stream ID
3910 0, // Associated Stream ID 3273 0, // Associated Stream ID
3274 ConvertRequestPriorityToSpdyPriority(
3275 LOWEST, spdy_util_.spdy_version()),
3276 kSpdyCredentialSlotUnused,
3277 CONTROL_FLAG_NONE, // Control Flags
3278 false, // Compressed
3279 RST_STREAM_INVALID, // Status
3280 NULL, // Data
3281 0, // Data Length
3282 DATA_FLAG_NONE // Data Flags
3283 };
3284 // Modify the following data to change/add test cases:
3285 struct SynReplyTests {
3286 const SpdyHeaderInfo* syn_reply;
3287 bool vary_matches;
3288 int num_headers[2];
3289 const char* extra_headers[2][16];
3290 } test_cases[] = {
3291 // Test the case of a multi-valued cookie. When the value is delimited
3292 // with NUL characters, it needs to be unfolded into multiple headers.
3293 {
3294 &syn_reply_info,
3295 true,
3296 { 1, 4 },
3297 { { "cookie", "val1,val2",
3298 NULL
3299 },
3300 { "vary", "cookie",
3301 spdy_util_.GetStatusKey(), "200",
3302 spdy_util_.GetPathKey(), "/index.php",
3303 spdy_util_.GetVersionKey(), "HTTP/1.1",
3304 NULL
3305 }
3306 }
3307 }, { // Multiple vary fields.
3308 &syn_reply_info,
3309 true,
3310 { 2, 5 },
3311 { { "friend", "barney",
3312 "enemy", "snaggletooth",
3313 NULL
3314 },
3315 { "vary", "friend",
3316 "vary", "enemy",
3317 spdy_util_.GetStatusKey(), "200",
3318 spdy_util_.GetPathKey(), "/index.php",
3319 spdy_util_.GetVersionKey(), "HTTP/1.1",
3320 NULL
3321 }
3322 }
3323 }, { // Test a '*' vary field.
3324 &syn_reply_info,
3325 false,
3326 { 1, 4 },
3327 { { "cookie", "val1,val2",
3328 NULL
3329 },
3330 { "vary", "*",
3331 spdy_util_.GetStatusKey(), "200",
3332 spdy_util_.GetPathKey(), "/index.php",
3333 spdy_util_.GetVersionKey(), "HTTP/1.1",
3334 NULL
3335 }
3336 }
3337 }, { // Multiple comma-separated vary fields.
3338 &syn_reply_info,
3339 true,
3340 { 2, 4 },
3341 { { "friend", "barney",
3342 "enemy", "snaggletooth",
3343 NULL
3344 },
3345 { "vary", "friend,enemy",
3346 spdy_util_.GetStatusKey(), "200",
3347 spdy_util_.GetPathKey(), "/index.php",
3348 spdy_util_.GetVersionKey(), "HTTP/1.1",
3349 NULL
3350 }
3351 }
3352 }
3353 };
3354
3355 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_cases); ++i) {
3356 // Construct the request.
3357 scoped_ptr<SpdyFrame> frame_req(
3358 spdy_util_.ConstructSpdyGet(test_cases[i].extra_headers[0],
3359 test_cases[i].num_headers[0],
3360 false, 1, LOWEST, true));
3361
3362 MockWrite writes[] = {
3363 CreateMockWrite(*frame_req),
3364 };
3365
3366 // Construct the reply.
3367 scoped_ptr<SpdyFrame> frame_reply(
3368 spdy_util_.ConstructSpdyFrame(*test_cases[i].syn_reply,
3369 test_cases[i].extra_headers[1],
3370 test_cases[i].num_headers[1],
3371 NULL,
3372 0));
3373
3374 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
3375 MockRead reads[] = {
3376 CreateMockRead(*frame_reply),
3377 CreateMockRead(*body),
3378 MockRead(ASYNC, 0, 0) // EOF
3379 };
3380
3381 // Attach the headers to the request.
3382 int header_count = test_cases[i].num_headers[0];
3383
3384 HttpRequestInfo request = CreateGetRequest();
3385 for (int ct = 0; ct < header_count; ct++) {
3386 const char* header_key = test_cases[i].extra_headers[0][ct * 2];
3387 const char* header_value = test_cases[i].extra_headers[0][ct * 2 + 1];
3388 request.extra_headers.SetHeader(header_key, header_value);
3389 }
3390
3391 DelayedSocketData data(1, reads, arraysize(reads),
3392 writes, arraysize(writes));
3393 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY,
3394 BoundNetLog(), GetParam(), NULL);
3395 helper.RunToCompletion(&data);
3396 TransactionHelperResult out = helper.output();
3397
3398 EXPECT_EQ(OK, out.rv) << i;
3399 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line) << i;
3400 EXPECT_EQ("hello!", out.response_data) << i;
3401
3402 // Test the response information.
3403 EXPECT_TRUE(out.response_info.response_time >
3404 out.response_info.request_time) << i;
3405 base::TimeDelta test_delay = out.response_info.response_time -
3406 out.response_info.request_time;
3407 base::TimeDelta min_expected_delay;
3408 min_expected_delay.FromMilliseconds(10);
3409 EXPECT_GT(test_delay.InMillisecondsF(),
3410 min_expected_delay.InMillisecondsF()) << i;
3411 EXPECT_EQ(out.response_info.vary_data.is_valid(),
3412 test_cases[i].vary_matches) << i;
3413
3414 // Check the headers.
3415 scoped_refptr<HttpResponseHeaders> headers = out.response_info.headers;
3416 ASSERT_TRUE(headers.get() != NULL) << i;
3417 void* iter = NULL;
3418 std::string name, value, lines;
3419 while (headers->EnumerateHeaderLines(&iter, &name, &value)) {
3420 lines.append(name);
3421 lines.append(": ");
3422 lines.append(value);
3423 lines.append("\n");
3424 }
3425
3426 // Construct the expected header reply string.
3427 SpdyHeaderBlock reply_headers;
3428 AppendToHeaderBlock(test_cases[i].extra_headers[1],
3429 test_cases[i].num_headers[1],
3430 &reply_headers);
3431 std::string expected_reply =
3432 spdy_util_.ConstructSpdyReplyString(reply_headers);
3433 EXPECT_EQ(expected_reply, lines) << i;
3434 }
3435 }
3436
3437 // Verify that we don't crash on invalid SynReply responses.
3438 TEST_P(SpdyNetworkTransactionTest, InvalidSynReply) {
3439 const SpdyHeaderInfo kSynStartHeader = {
3440 SYN_REPLY, // Kind = SynReply
3441 1, // Stream ID
3442 0, // Associated stream ID
3443 ConvertRequestPriorityToSpdyPriority(
3444 LOWEST, spdy_util_.spdy_version()),
3445 kSpdyCredentialSlotUnused,
3446 CONTROL_FLAG_NONE, // Control Flags
3447 false, // Compressed
3448 RST_STREAM_INVALID, // Status
3449 NULL, // Data
3450 0, // Length
3451 DATA_FLAG_NONE // Data Flags
3452 };
3453
3454 struct InvalidSynReplyTests {
3455 int num_headers;
3456 const char* headers[10];
3457 } test_cases[] = {
3458 // SYN_REPLY missing status header
3459 { 4,
3460 { "cookie", "val1",
3461 "cookie", "val2",
3462 spdy_util_.GetPathKey(), "/index.php",
3463 spdy_util_.GetVersionKey(), "HTTP/1.1",
3464 NULL
3465 },
3466 },
3467 // SYN_REPLY missing version header
3468 { 2,
3469 { "status", "200",
3470 spdy_util_.GetPathKey(), "/index.php",
3471 NULL
3472 },
3473 },
3474 // SYN_REPLY with no headers
3475 { 0, { NULL }, },
3476 };
3477
3478 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_cases); ++i) {
3479 scoped_ptr<SpdyFrame> req(
3480 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
3481 scoped_ptr<SpdyFrame> rst(
3482 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_PROTOCOL_ERROR));
3483 MockWrite writes[] = {
3484 CreateMockWrite(*req),
3485 CreateMockWrite(*rst),
3486 };
3487
3488 scoped_ptr<SpdyFrame> resp(
3489 spdy_util_.ConstructSpdyFrame(kSynStartHeader,
3490 NULL, 0,
3491 test_cases[i].headers,
3492 test_cases[i].num_headers));
3493 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
3494 MockRead reads[] = {
3495 CreateMockRead(*resp),
3496 MockRead(ASYNC, 0, 0) // EOF
3497 };
3498
3499 DelayedSocketData data(1, reads, arraysize(reads),
3500 writes, arraysize(writes));
3501 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
3502 BoundNetLog(), GetParam(), NULL);
3503 helper.RunToCompletion(&data);
3504 TransactionHelperResult out = helper.output();
3505 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, out.rv);
3506 }
3507 }
3508
3509 // Verify that we don't crash on some corrupt frames.
3510 TEST_P(SpdyNetworkTransactionTest, CorruptFrameSessionError) {
3511 // This is the length field that's too short.
3512 scoped_ptr<SpdyFrame> syn_reply_wrong_length(
3513 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3514 BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
3515 size_t right_size =
3516 (spdy_util_.spdy_version() < SPDY4) ?
3517 syn_reply_wrong_length->size() - framer.GetControlFrameHeaderSize() :
3518 syn_reply_wrong_length->size();
3519 size_t wrong_size = right_size - 4;
3520 test::SetFrameLength(syn_reply_wrong_length.get(),
3521 wrong_size,
3522 spdy_util_.spdy_version());
3523
3524 struct SynReplyTests {
3525 const SpdyFrame* syn_reply;
3526 } test_cases[] = {
3527 { syn_reply_wrong_length.get(), },
3528 };
3529
3530 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_cases); ++i) {
3531 scoped_ptr<SpdyFrame> req(
3532 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
3533 MockWrite writes[] = { CreateMockWrite(*req), MockWrite(ASYNC, 0, 0) // EOF
3534 };
3535
3536 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
3537 MockRead reads[] = {
3538 MockRead(ASYNC, test_cases[i].syn_reply->data(), wrong_size),
3539 CreateMockRead(*body),
3540 MockRead(ASYNC, 0, 0) // EOF
3541 };
3542
3543 DelayedSocketData data(1, reads, arraysize(reads),
3544 writes, arraysize(writes));
3545 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
3546 BoundNetLog(), GetParam(), NULL);
3547 helper.RunToCompletion(&data);
3548 TransactionHelperResult out = helper.output();
3549 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, out.rv);
3550 }
3551 }
3552
3553 // Test that we shutdown correctly on write errors.
3554 TEST_P(SpdyNetworkTransactionTest, WriteError) {
3555 scoped_ptr<SpdyFrame> req(
3556 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
3557 MockWrite writes[] = {
3558 // We'll write 10 bytes successfully
3559 MockWrite(ASYNC, req->data(), 10),
3560 // Followed by ERROR!
3561 MockWrite(ASYNC, ERR_FAILED),
3562 };
3563
3564 DelayedSocketData data(2, NULL, 0,
3565 writes, arraysize(writes));
3566 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
3567 BoundNetLog(), GetParam(), NULL);
3568 helper.RunToCompletion(&data);
3569 TransactionHelperResult out = helper.output();
3570 EXPECT_EQ(ERR_FAILED, out.rv);
3571 data.Reset();
3572 }
3573
3574 // Test that partial writes work.
3575 TEST_P(SpdyNetworkTransactionTest, PartialWrite) {
3576 // Chop the SYN_STREAM frame into 5 chunks.
3577 scoped_ptr<SpdyFrame> req(
3578 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
3579 const int kChunks = 5;
3580 scoped_ptr<MockWrite[]> writes(ChopWriteFrame(*req.get(), kChunks));
3581
3582 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3583 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
3584 MockRead reads[] = {
3585 CreateMockRead(*resp),
3586 CreateMockRead(*body),
3587 MockRead(ASYNC, 0, 0) // EOF
3588 };
3589
3590 DelayedSocketData data(kChunks, reads, arraysize(reads),
3591 writes.get(), kChunks);
3592 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
3593 BoundNetLog(), GetParam(), NULL);
3594 helper.RunToCompletion(&data);
3595 TransactionHelperResult out = helper.output();
3596 EXPECT_EQ(OK, out.rv);
3597 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
3598 EXPECT_EQ("hello!", out.response_data);
3599 }
3600
3601 // In this test, we enable compression, but get a uncompressed SynReply from
3602 // the server. Verify that teardown is all clean.
3603 TEST_P(SpdyNetworkTransactionTest, DecompressFailureOnSynReply) {
3604 scoped_ptr<SpdyFrame> compressed(
3605 spdy_util_.ConstructSpdyGet(NULL, 0, true, 1, LOWEST, true));
3606 scoped_ptr<SpdyFrame> rst(
3607 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_PROTOCOL_ERROR));
3608 MockWrite writes[] = {
3609 CreateMockWrite(*compressed),
3610 };
3611
3612 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3613 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
3614 MockRead reads[] = {
3615 CreateMockRead(*resp),
3616 };
3617
3618 DelayedSocketData data(1, reads, arraysize(reads),
3619 writes, arraysize(writes));
3620 SpdySessionDependencies* session_deps =
3621 CreateSpdySessionDependencies(GetParam());
3622 session_deps->enable_compression = true;
3623 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
3624 BoundNetLog(), GetParam(), session_deps);
3625 helper.RunToCompletion(&data);
3626 TransactionHelperResult out = helper.output();
3627 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, out.rv);
3628 data.Reset();
3629 }
3630
3631 // Test that the NetLog contains good data for a simple GET request.
3632 TEST_P(SpdyNetworkTransactionTest, NetLog) {
3633 static const char* const kExtraHeaders[] = {
3634 "user-agent", "Chrome",
3635 };
3636 scoped_ptr<SpdyFrame> req(
3637 spdy_util_.ConstructSpdyGet(kExtraHeaders, 1, false, 1, LOWEST, true));
3638 MockWrite writes[] = { CreateMockWrite(*req) };
3639
3640 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3641 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
3642 MockRead reads[] = {
3643 CreateMockRead(*resp),
3644 CreateMockRead(*body),
3645 MockRead(ASYNC, 0, 0) // EOF
3646 };
3647
3648 CapturingBoundNetLog log;
3649
3650 DelayedSocketData data(1, reads, arraysize(reads),
3651 writes, arraysize(writes));
3652 NormalSpdyTransactionHelper helper(CreateGetRequestWithUserAgent(),
3653 DEFAULT_PRIORITY,
3654 log.bound(), GetParam(), NULL);
3655 helper.RunToCompletion(&data);
3656 TransactionHelperResult out = helper.output();
3657 EXPECT_EQ(OK, out.rv);
3658 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
3659 EXPECT_EQ("hello!", out.response_data);
3660
3661 // Check that the NetLog was filled reasonably.
3662 // This test is intentionally non-specific about the exact ordering of the
3663 // log; instead we just check to make sure that certain events exist, and that
3664 // they are in the right order.
3665 net::CapturingNetLog::CapturedEntryList entries;
3666 log.GetEntries(&entries);
3667
3668 EXPECT_LT(0u, entries.size());
3669 int pos = 0;
3670 pos = net::ExpectLogContainsSomewhere(entries, 0,
3671 net::NetLog::TYPE_HTTP_TRANSACTION_SEND_REQUEST,
3672 net::NetLog::PHASE_BEGIN);
3673 pos = net::ExpectLogContainsSomewhere(entries, pos + 1,
3674 net::NetLog::TYPE_HTTP_TRANSACTION_SEND_REQUEST,
3675 net::NetLog::PHASE_END);
3676 pos = net::ExpectLogContainsSomewhere(entries, pos + 1,
3677 net::NetLog::TYPE_HTTP_TRANSACTION_READ_HEADERS,
3678 net::NetLog::PHASE_BEGIN);
3679 pos = net::ExpectLogContainsSomewhere(entries, pos + 1,
3680 net::NetLog::TYPE_HTTP_TRANSACTION_READ_HEADERS,
3681 net::NetLog::PHASE_END);
3682 pos = net::ExpectLogContainsSomewhere(entries, pos + 1,
3683 net::NetLog::TYPE_HTTP_TRANSACTION_READ_BODY,
3684 net::NetLog::PHASE_BEGIN);
3685 pos = net::ExpectLogContainsSomewhere(entries, pos + 1,
3686 net::NetLog::TYPE_HTTP_TRANSACTION_READ_BODY,
3687 net::NetLog::PHASE_END);
3688
3689 // Check that we logged all the headers correctly
3690 pos = net::ExpectLogContainsSomewhere(
3691 entries, 0,
3692 net::NetLog::TYPE_SPDY_SESSION_SYN_STREAM,
3693 net::NetLog::PHASE_NONE);
3694
3695 base::ListValue* header_list;
3696 ASSERT_TRUE(entries[pos].params.get());
3697 ASSERT_TRUE(entries[pos].params->GetList("headers", &header_list));
3698
3699 std::vector<std::string> expected;
3700 expected.push_back(std::string(spdy_util_.GetHostKey()) + ": www.google.com");
3701 expected.push_back(std::string(spdy_util_.GetPathKey()) + ": /");
3702 expected.push_back(std::string(spdy_util_.GetSchemeKey()) + ": http");
3703 expected.push_back(std::string(spdy_util_.GetVersionKey()) + ": HTTP/1.1");
3704 expected.push_back(std::string(spdy_util_.GetMethodKey()) + ": GET");
3705 expected.push_back("user-agent: Chrome");
3706 EXPECT_EQ(expected.size(), header_list->GetSize());
3707 for (std::vector<std::string>::const_iterator it = expected.begin();
3708 it != expected.end();
3709 ++it) {
3710 base::StringValue header(*it);
3711 EXPECT_NE(header_list->end(), header_list->Find(header)) <<
3712 "Header not found: " << *it;
3713 }
3714 }
3715
3716 // Since we buffer the IO from the stream to the renderer, this test verifies
3717 // that when we read out the maximum amount of data (e.g. we received 50 bytes
3718 // on the network, but issued a Read for only 5 of those bytes) that the data
3719 // flow still works correctly.
3720 TEST_P(SpdyNetworkTransactionTest, BufferFull) {
3721 BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
3722
3723 scoped_ptr<SpdyFrame> req(
3724 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
3725 MockWrite writes[] = { CreateMockWrite(*req) };
3726
3727 // 2 data frames in a single read.
3728 scoped_ptr<SpdyFrame> data_frame_1(
3729 framer.CreateDataFrame(1, "goodby", 6, DATA_FLAG_NONE));
3730 scoped_ptr<SpdyFrame> data_frame_2(
3731 framer.CreateDataFrame(1, "e worl", 6, DATA_FLAG_NONE));
3732 const SpdyFrame* data_frames[2] = {
3733 data_frame_1.get(),
3734 data_frame_2.get(),
3735 };
3736 char combined_data_frames[100];
3737 int combined_data_frames_len =
3738 CombineFrames(data_frames, arraysize(data_frames),
3739 combined_data_frames, arraysize(combined_data_frames));
3740 scoped_ptr<SpdyFrame> last_frame(
3741 framer.CreateDataFrame(1, "d", 1, DATA_FLAG_FIN));
3742
3743 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3744 MockRead reads[] = {
3745 CreateMockRead(*resp),
3746 MockRead(ASYNC, ERR_IO_PENDING), // Force a pause
3747 MockRead(ASYNC, combined_data_frames, combined_data_frames_len),
3748 MockRead(ASYNC, ERR_IO_PENDING), // Force a pause
3749 CreateMockRead(*last_frame),
3750 MockRead(ASYNC, 0, 0) // EOF
3751 };
3752
3753 DelayedSocketData data(1, reads, arraysize(reads),
3754 writes, arraysize(writes));
3755
3756 TestCompletionCallback callback;
3757
3758 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
3759 BoundNetLog(), GetParam(), NULL);
3760 helper.RunPreTestSetup();
3761 helper.AddData(&data);
3762 HttpNetworkTransaction* trans = helper.trans();
3763 int rv = trans->Start(
3764 &CreateGetRequest(), callback.callback(), BoundNetLog());
3765 EXPECT_EQ(ERR_IO_PENDING, rv);
3766
3767 TransactionHelperResult out = helper.output();
3768 out.rv = callback.WaitForResult();
3769 EXPECT_EQ(out.rv, OK);
3770
3771 const HttpResponseInfo* response = trans->GetResponseInfo();
3772 EXPECT_TRUE(response->headers.get() != NULL);
3773 EXPECT_TRUE(response->was_fetched_via_spdy);
3774 out.status_line = response->headers->GetStatusLine();
3775 out.response_info = *response; // Make a copy so we can verify.
3776
3777 // Read Data
3778 TestCompletionCallback read_callback;
3779
3780 std::string content;
3781 do {
3782 // Read small chunks at a time.
3783 const int kSmallReadSize = 3;
3784 scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(kSmallReadSize));
3785 rv = trans->Read(buf.get(), kSmallReadSize, read_callback.callback());
3786 if (rv == net::ERR_IO_PENDING) {
3787 data.CompleteRead();
3788 rv = read_callback.WaitForResult();
3789 }
3790 if (rv > 0) {
3791 content.append(buf->data(), rv);
3792 } else if (rv < 0) {
3793 NOTREACHED();
3794 }
3795 } while (rv > 0);
3796
3797 out.response_data.swap(content);
3798
3799 // Flush the MessageLoop while the SpdySessionDependencies (in particular, the
3800 // MockClientSocketFactory) are still alive.
3801 base::MessageLoop::current()->RunUntilIdle();
3802
3803 // Verify that we consumed all test data.
3804 helper.VerifyDataConsumed();
3805
3806 EXPECT_EQ(OK, out.rv);
3807 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
3808 EXPECT_EQ("goodbye world", out.response_data);
3809 }
3810
3811 // Verify that basic buffering works; when multiple data frames arrive
3812 // at the same time, ensure that we don't notify a read completion for
3813 // each data frame individually.
3814 TEST_P(SpdyNetworkTransactionTest, Buffering) {
3815 BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
3816
3817 scoped_ptr<SpdyFrame> req(
3818 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
3819 MockWrite writes[] = { CreateMockWrite(*req) };
3820
3821 // 4 data frames in a single read.
3822 scoped_ptr<SpdyFrame> data_frame(
3823 framer.CreateDataFrame(1, "message", 7, DATA_FLAG_NONE));
3824 scoped_ptr<SpdyFrame> data_frame_fin(
3825 framer.CreateDataFrame(1, "message", 7, DATA_FLAG_FIN));
3826 const SpdyFrame* data_frames[4] = {
3827 data_frame.get(),
3828 data_frame.get(),
3829 data_frame.get(),
3830 data_frame_fin.get()
3831 };
3832 char combined_data_frames[100];
3833 int combined_data_frames_len =
3834 CombineFrames(data_frames, arraysize(data_frames),
3835 combined_data_frames, arraysize(combined_data_frames));
3836
3837 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3838 MockRead reads[] = {
3839 CreateMockRead(*resp),
3840 MockRead(ASYNC, ERR_IO_PENDING), // Force a pause
3841 MockRead(ASYNC, combined_data_frames, combined_data_frames_len),
3842 MockRead(ASYNC, 0, 0) // EOF
3843 };
3844
3845 DelayedSocketData data(1, reads, arraysize(reads),
3846 writes, arraysize(writes));
3847
3848 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
3849 BoundNetLog(), GetParam(), NULL);
3850 helper.RunPreTestSetup();
3851 helper.AddData(&data);
3852 HttpNetworkTransaction* trans = helper.trans();
3853
3854 TestCompletionCallback callback;
3855 int rv = trans->Start(
3856 &CreateGetRequest(), callback.callback(), BoundNetLog());
3857 EXPECT_EQ(ERR_IO_PENDING, rv);
3858
3859 TransactionHelperResult out = helper.output();
3860 out.rv = callback.WaitForResult();
3861 EXPECT_EQ(out.rv, OK);
3862
3863 const HttpResponseInfo* response = trans->GetResponseInfo();
3864 EXPECT_TRUE(response->headers.get() != NULL);
3865 EXPECT_TRUE(response->was_fetched_via_spdy);
3866 out.status_line = response->headers->GetStatusLine();
3867 out.response_info = *response; // Make a copy so we can verify.
3868
3869 // Read Data
3870 TestCompletionCallback read_callback;
3871
3872 std::string content;
3873 int reads_completed = 0;
3874 do {
3875 // Read small chunks at a time.
3876 const int kSmallReadSize = 14;
3877 scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(kSmallReadSize));
3878 rv = trans->Read(buf.get(), kSmallReadSize, read_callback.callback());
3879 if (rv == net::ERR_IO_PENDING) {
3880 data.CompleteRead();
3881 rv = read_callback.WaitForResult();
3882 }
3883 if (rv > 0) {
3884 EXPECT_EQ(kSmallReadSize, rv);
3885 content.append(buf->data(), rv);
3886 } else if (rv < 0) {
3887 FAIL() << "Unexpected read error: " << rv;
3888 }
3889 reads_completed++;
3890 } while (rv > 0);
3891
3892 EXPECT_EQ(3, reads_completed); // Reads are: 14 bytes, 14 bytes, 0 bytes.
3893
3894 out.response_data.swap(content);
3895
3896 // Flush the MessageLoop while the SpdySessionDependencies (in particular, the
3897 // MockClientSocketFactory) are still alive.
3898 base::MessageLoop::current()->RunUntilIdle();
3899
3900 // Verify that we consumed all test data.
3901 helper.VerifyDataConsumed();
3902
3903 EXPECT_EQ(OK, out.rv);
3904 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
3905 EXPECT_EQ("messagemessagemessagemessage", out.response_data);
3906 }
3907
3908 // Verify the case where we buffer data but read it after it has been buffered.
3909 TEST_P(SpdyNetworkTransactionTest, BufferedAll) {
3910 BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
3911
3912 scoped_ptr<SpdyFrame> req(
3913 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
3914 MockWrite writes[] = { CreateMockWrite(*req) };
3915
3916 // 5 data frames in a single read.
3917 scoped_ptr<SpdyFrame> syn_reply(
3918 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3919 // turn off FIN bit
3920 test::SetFrameFlags(
3921 syn_reply.get(), CONTROL_FLAG_NONE, spdy_util_.spdy_version());
3922 scoped_ptr<SpdyFrame> data_frame(
3923 framer.CreateDataFrame(1, "message", 7, DATA_FLAG_NONE));
3924 scoped_ptr<SpdyFrame> data_frame_fin(
3925 framer.CreateDataFrame(1, "message", 7, DATA_FLAG_FIN));
3926 const SpdyFrame* frames[5] = {
3927 syn_reply.get(),
3928 data_frame.get(),
3929 data_frame.get(),
3930 data_frame.get(),
3931 data_frame_fin.get()
3932 };
3933 char combined_frames[200];
3934 int combined_frames_len =
3935 CombineFrames(frames, arraysize(frames),
3936 combined_frames, arraysize(combined_frames));
3937
3938 MockRead reads[] = {
3939 MockRead(ASYNC, combined_frames, combined_frames_len),
3940 MockRead(ASYNC, 0, 0) // EOF
3941 };
3942
3943 DelayedSocketData data(1, reads, arraysize(reads),
3944 writes, arraysize(writes));
3945
3946 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
3947 BoundNetLog(), GetParam(), NULL);
3948 helper.RunPreTestSetup();
3949 helper.AddData(&data);
3950 HttpNetworkTransaction* trans = helper.trans();
3951
3952 TestCompletionCallback callback;
3953 int rv = trans->Start(
3954 &CreateGetRequest(), callback.callback(), BoundNetLog());
3955 EXPECT_EQ(ERR_IO_PENDING, rv);
3956
3957 TransactionHelperResult out = helper.output();
3958 out.rv = callback.WaitForResult();
3959 EXPECT_EQ(out.rv, OK);
3960
3961 const HttpResponseInfo* response = trans->GetResponseInfo();
3962 EXPECT_TRUE(response->headers.get() != NULL);
3963 EXPECT_TRUE(response->was_fetched_via_spdy);
3964 out.status_line = response->headers->GetStatusLine();
3965 out.response_info = *response; // Make a copy so we can verify.
3966
3967 // Read Data
3968 TestCompletionCallback read_callback;
3969
3970 std::string content;
3971 int reads_completed = 0;
3972 do {
3973 // Read small chunks at a time.
3974 const int kSmallReadSize = 14;
3975 scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(kSmallReadSize));
3976 rv = trans->Read(buf.get(), kSmallReadSize, read_callback.callback());
3977 if (rv > 0) {
3978 EXPECT_EQ(kSmallReadSize, rv);
3979 content.append(buf->data(), rv);
3980 } else if (rv < 0) {
3981 FAIL() << "Unexpected read error: " << rv;
3982 }
3983 reads_completed++;
3984 } while (rv > 0);
3985
3986 EXPECT_EQ(3, reads_completed);
3987
3988 out.response_data.swap(content);
3989
3990 // Flush the MessageLoop while the SpdySessionDependencies (in particular, the
3991 // MockClientSocketFactory) are still alive.
3992 base::MessageLoop::current()->RunUntilIdle();
3993
3994 // Verify that we consumed all test data.
3995 helper.VerifyDataConsumed();
3996
3997 EXPECT_EQ(OK, out.rv);
3998 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
3999 EXPECT_EQ("messagemessagemessagemessage", out.response_data);
4000 }
4001
4002 // Verify the case where we buffer data and close the connection.
4003 TEST_P(SpdyNetworkTransactionTest, BufferedClosed) {
4004 BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
4005
4006 scoped_ptr<SpdyFrame> req(
4007 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
4008 MockWrite writes[] = { CreateMockWrite(*req) };
4009
4010 // All data frames in a single read.
4011 // NOTE: We don't FIN the stream.
4012 scoped_ptr<SpdyFrame> data_frame(
4013 framer.CreateDataFrame(1, "message", 7, DATA_FLAG_NONE));
4014 const SpdyFrame* data_frames[4] = {
4015 data_frame.get(),
4016 data_frame.get(),
4017 data_frame.get(),
4018 data_frame.get()
4019 };
4020 char combined_data_frames[100];
4021 int combined_data_frames_len =
4022 CombineFrames(data_frames, arraysize(data_frames),
4023 combined_data_frames, arraysize(combined_data_frames));
4024 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
4025 MockRead reads[] = {
4026 CreateMockRead(*resp),
4027 MockRead(ASYNC, ERR_IO_PENDING), // Force a wait
4028 MockRead(ASYNC, combined_data_frames, combined_data_frames_len),
4029 MockRead(ASYNC, 0, 0) // EOF
4030 };
4031
4032 DelayedSocketData data(1, reads, arraysize(reads),
4033 writes, arraysize(writes));
4034
4035 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
4036 BoundNetLog(), GetParam(), NULL);
4037 helper.RunPreTestSetup();
4038 helper.AddData(&data);
4039 HttpNetworkTransaction* trans = helper.trans();
4040
4041 TestCompletionCallback callback;
4042
4043 int rv = trans->Start(
4044 &CreateGetRequest(), callback.callback(), BoundNetLog());
4045 EXPECT_EQ(ERR_IO_PENDING, rv);
4046
4047 TransactionHelperResult out = helper.output();
4048 out.rv = callback.WaitForResult();
4049 EXPECT_EQ(out.rv, OK);
4050
4051 const HttpResponseInfo* response = trans->GetResponseInfo();
4052 EXPECT_TRUE(response->headers.get() != NULL);
4053 EXPECT_TRUE(response->was_fetched_via_spdy);
4054 out.status_line = response->headers->GetStatusLine();
4055 out.response_info = *response; // Make a copy so we can verify.
4056
4057 // Read Data
4058 TestCompletionCallback read_callback;
4059
4060 std::string content;
4061 int reads_completed = 0;
4062 do {
4063 // Read small chunks at a time.
4064 const int kSmallReadSize = 14;
4065 scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(kSmallReadSize));
4066 rv = trans->Read(buf.get(), kSmallReadSize, read_callback.callback());
4067 if (rv == net::ERR_IO_PENDING) {
4068 data.CompleteRead();
4069 rv = read_callback.WaitForResult();
4070 }
4071 if (rv > 0) {
4072 content.append(buf->data(), rv);
4073 } else if (rv < 0) {
4074 // This test intentionally closes the connection, and will get an error.
4075 EXPECT_EQ(ERR_CONNECTION_CLOSED, rv);
4076 break;
4077 }
4078 reads_completed++;
4079 } while (rv > 0);
4080
4081 EXPECT_EQ(0, reads_completed);
4082
4083 out.response_data.swap(content);
4084
4085 // Flush the MessageLoop while the SpdySessionDependencies (in particular, the
4086 // MockClientSocketFactory) are still alive.
4087 base::MessageLoop::current()->RunUntilIdle();
4088
4089 // Verify that we consumed all test data.
4090 helper.VerifyDataConsumed();
4091 }
4092
4093 // Verify the case where we buffer data and cancel the transaction.
4094 TEST_P(SpdyNetworkTransactionTest, BufferedCancelled) {
4095 BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
4096
4097 scoped_ptr<SpdyFrame> req(
4098 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
4099 MockWrite writes[] = { CreateMockWrite(*req) };
4100
4101 // NOTE: We don't FIN the stream.
4102 scoped_ptr<SpdyFrame> data_frame(
4103 framer.CreateDataFrame(1, "message", 7, DATA_FLAG_NONE));
4104
4105 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
4106 MockRead reads[] = {
4107 CreateMockRead(*resp),
4108 MockRead(ASYNC, ERR_IO_PENDING), // Force a wait
4109 CreateMockRead(*data_frame),
4110 MockRead(ASYNC, 0, 0) // EOF
4111 };
4112
4113 DelayedSocketData data(1, reads, arraysize(reads),
4114 writes, arraysize(writes));
4115
4116 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
4117 BoundNetLog(), GetParam(), NULL);
4118 helper.RunPreTestSetup();
4119 helper.AddData(&data);
4120 HttpNetworkTransaction* trans = helper.trans();
4121 TestCompletionCallback callback;
4122
4123 int rv = trans->Start(
4124 &CreateGetRequest(), callback.callback(), BoundNetLog());
4125 EXPECT_EQ(ERR_IO_PENDING, rv);
4126
4127 TransactionHelperResult out = helper.output();
4128 out.rv = callback.WaitForResult();
4129 EXPECT_EQ(out.rv, OK);
4130
4131 const HttpResponseInfo* response = trans->GetResponseInfo();
4132 EXPECT_TRUE(response->headers.get() != NULL);
4133 EXPECT_TRUE(response->was_fetched_via_spdy);
4134 out.status_line = response->headers->GetStatusLine();
4135 out.response_info = *response; // Make a copy so we can verify.
4136
4137 // Read Data
4138 TestCompletionCallback read_callback;
4139
4140 do {
4141 const int kReadSize = 256;
4142 scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(kReadSize));
4143 rv = trans->Read(buf.get(), kReadSize, read_callback.callback());
4144 if (rv == net::ERR_IO_PENDING) {
4145 // Complete the read now, which causes buffering to start.
4146 data.CompleteRead();
4147 // Destroy the transaction, causing the stream to get cancelled
4148 // and orphaning the buffered IO task.
4149 helper.ResetTrans();
4150 break;
4151 }
4152 // We shouldn't get here in this test.
4153 FAIL() << "Unexpected read: " << rv;
4154 } while (rv > 0);
4155
4156 // Flush the MessageLoop; this will cause the buffered IO task
4157 // to run for the final time.
4158 base::MessageLoop::current()->RunUntilIdle();
4159
4160 // Verify that we consumed all test data.
4161 helper.VerifyDataConsumed();
4162 }
4163
4164 // Test that if the server requests persistence of settings, that we save
4165 // the settings in the HttpServerProperties.
4166 TEST_P(SpdyNetworkTransactionTest, SettingsSaved) {
4167 static const SpdyHeaderInfo kSynReplyInfo = {
4168 SYN_REPLY, // Syn Reply
4169 1, // Stream ID
4170 0, // Associated Stream ID
3911 ConvertRequestPriorityToSpdyPriority( 4171 ConvertRequestPriorityToSpdyPriority(
3912 LOWEST, spdy_util_.spdy_version()), 4172 LOWEST, spdy_util_.spdy_version()),
3913 kSpdyCredentialSlotUnused, 4173 kSpdyCredentialSlotUnused,
3914 CONTROL_FLAG_NONE, // Control Flags 4174 CONTROL_FLAG_NONE, // Control Flags
3915 false, // Compressed 4175 false, // Compressed
3916 RST_STREAM_INVALID, // Status 4176 RST_STREAM_INVALID, // Status
3917 NULL, // Data 4177 NULL, // Data
3918 0, // Data Length 4178 0, // Data Length
3919 DATA_FLAG_NONE // Data Flags 4179 DATA_FLAG_NONE // Data Flags
3920 }; 4180 };
3921 // Modify the following data to change/add test cases:
3922 struct SynReplyTests {
3923 const SpdyHeaderInfo* syn_reply;
3924 bool vary_matches;
3925 int num_headers[2];
3926 const char* extra_headers[2][16];
3927 } test_cases[] = {
3928 // Test the case of a multi-valued cookie. When the value is delimited
3929 // with NUL characters, it needs to be unfolded into multiple headers.
3930 {
3931 &syn_reply_info,
3932 true,
3933 { 1, 4 },
3934 { { "cookie", "val1,val2",
3935 NULL
3936 },
3937 { "vary", "cookie",
3938 spdy_util_.GetStatusKey(), "200",
3939 spdy_util_.GetPathKey(), "/index.php",
3940 spdy_util_.GetVersionKey(), "HTTP/1.1",
3941 NULL
3942 }
3943 }
3944 }, { // Multiple vary fields.
3945 &syn_reply_info,
3946 true,
3947 { 2, 5 },
3948 { { "friend", "barney",
3949 "enemy", "snaggletooth",
3950 NULL
3951 },
3952 { "vary", "friend",
3953 "vary", "enemy",
3954 spdy_util_.GetStatusKey(), "200",
3955 spdy_util_.GetPathKey(), "/index.php",
3956 spdy_util_.GetVersionKey(), "HTTP/1.1",
3957 NULL
3958 }
3959 }
3960 }, { // Test a '*' vary field.
3961 &syn_reply_info,
3962 false,
3963 { 1, 4 },
3964 { { "cookie", "val1,val2",
3965 NULL
3966 },
3967 { "vary", "*",
3968 spdy_util_.GetStatusKey(), "200",
3969 spdy_util_.GetPathKey(), "/index.php",
3970 spdy_util_.GetVersionKey(), "HTTP/1.1",
3971 NULL
3972 }
3973 }
3974 }, { // Multiple comma-separated vary fields.
3975 &syn_reply_info,
3976 true,
3977 { 2, 4 },
3978 { { "friend", "barney",
3979 "enemy", "snaggletooth",
3980 NULL
3981 },
3982 { "vary", "friend,enemy",
3983 spdy_util_.GetStatusKey(), "200",
3984 spdy_util_.GetPathKey(), "/index.php",
3985 spdy_util_.GetVersionKey(), "HTTP/1.1",
3986 NULL
3987 }
3988 }
3989 }
3990 };
3991
3992 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_cases); ++i) {
3993 // Construct the request.
3994 scoped_ptr<SpdyFrame> frame_req(
3995 spdy_util_.ConstructSpdyGet(test_cases[i].extra_headers[0],
3996 test_cases[i].num_headers[0],
3997 false, 1, LOWEST, true));
3998
3999 MockWrite writes[] = {
4000 CreateMockWrite(*frame_req),
4001 };
4002
4003 // Construct the reply.
4004 scoped_ptr<SpdyFrame> frame_reply(
4005 spdy_util_.ConstructSpdyFrame(*test_cases[i].syn_reply,
4006 test_cases[i].extra_headers[1],
4007 test_cases[i].num_headers[1],
4008 NULL,
4009 0));
4010
4011 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
4012 MockRead reads[] = {
4013 CreateMockRead(*frame_reply),
4014 CreateMockRead(*body),
4015 MockRead(ASYNC, 0, 0) // EOF
4016 };
4017
4018 // Attach the headers to the request.
4019 int header_count = test_cases[i].num_headers[0];
4020
4021 HttpRequestInfo request = CreateGetRequest();
4022 for (int ct = 0; ct < header_count; ct++) {
4023 const char* header_key = test_cases[i].extra_headers[0][ct * 2];
4024 const char* header_value = test_cases[i].extra_headers[0][ct * 2 + 1];
4025 request.extra_headers.SetHeader(header_key, header_value);
4026 }
4027
4028 DelayedSocketData data(1, reads, arraysize(reads),
4029 writes, arraysize(writes));
4030 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY,
4031 BoundNetLog(), GetParam(), NULL);
4032 helper.RunToCompletion(&data);
4033 TransactionHelperResult out = helper.output();
4034
4035 EXPECT_EQ(OK, out.rv) << i;
4036 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line) << i;
4037 EXPECT_EQ("hello!", out.response_data) << i;
4038
4039 // Test the response information.
4040 EXPECT_TRUE(out.response_info.response_time >
4041 out.response_info.request_time) << i;
4042 base::TimeDelta test_delay = out.response_info.response_time -
4043 out.response_info.request_time;
4044 base::TimeDelta min_expected_delay;
4045 min_expected_delay.FromMilliseconds(10);
4046 EXPECT_GT(test_delay.InMillisecondsF(),
4047 min_expected_delay.InMillisecondsF()) << i;
4048 EXPECT_EQ(out.response_info.vary_data.is_valid(),
4049 test_cases[i].vary_matches) << i;
4050
4051 // Check the headers.
4052 scoped_refptr<HttpResponseHeaders> headers = out.response_info.headers;
4053 ASSERT_TRUE(headers.get() != NULL) << i;
4054 void* iter = NULL;
4055 std::string name, value, lines;
4056 while (headers->EnumerateHeaderLines(&iter, &name, &value)) {
4057 lines.append(name);
4058 lines.append(": ");
4059 lines.append(value);
4060 lines.append("\n");
4061 }
4062
4063 // Construct the expected header reply string.
4064 SpdyHeaderBlock reply_headers;
4065 AppendToHeaderBlock(test_cases[i].extra_headers[1],
4066 test_cases[i].num_headers[1],
4067 &reply_headers);
4068 std::string expected_reply =
4069 spdy_util_.ConstructSpdyReplyString(reply_headers);
4070 EXPECT_EQ(expected_reply, lines) << i;
4071 }
4072 }
4073
4074 // Verify that we don't crash on invalid SynReply responses.
4075 TEST_P(SpdyNetworkTransactionTest, InvalidSynReply) {
4076 const SpdyHeaderInfo kSynStartHeader = {
4077 SYN_REPLY, // Kind = SynReply
4078 1, // Stream ID
4079 0, // Associated stream ID
4080 ConvertRequestPriorityToSpdyPriority(
4081 LOWEST, spdy_util_.spdy_version()),
4082 kSpdyCredentialSlotUnused,
4083 CONTROL_FLAG_NONE, // Control Flags
4084 false, // Compressed
4085 RST_STREAM_INVALID, // Status
4086 NULL, // Data
4087 0, // Length
4088 DATA_FLAG_NONE // Data Flags
4089 };
4090
4091 struct InvalidSynReplyTests {
4092 int num_headers;
4093 const char* headers[10];
4094 } test_cases[] = {
4095 // SYN_REPLY missing status header
4096 { 4,
4097 { "cookie", "val1",
4098 "cookie", "val2",
4099 spdy_util_.GetPathKey(), "/index.php",
4100 spdy_util_.GetVersionKey(), "HTTP/1.1",
4101 NULL
4102 },
4103 },
4104 // SYN_REPLY missing version header
4105 { 2,
4106 { "status", "200",
4107 spdy_util_.GetPathKey(), "/index.php",
4108 NULL
4109 },
4110 },
4111 // SYN_REPLY with no headers
4112 { 0, { NULL }, },
4113 };
4114
4115 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_cases); ++i) {
4116 scoped_ptr<SpdyFrame> req(
4117 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
4118 scoped_ptr<SpdyFrame> rst(
4119 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_PROTOCOL_ERROR));
4120 MockWrite writes[] = {
4121 CreateMockWrite(*req),
4122 CreateMockWrite(*rst),
4123 };
4124
4125 scoped_ptr<SpdyFrame> resp(
4126 spdy_util_.ConstructSpdyFrame(kSynStartHeader,
4127 NULL, 0,
4128 test_cases[i].headers,
4129 test_cases[i].num_headers));
4130 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
4131 MockRead reads[] = {
4132 CreateMockRead(*resp),
4133 MockRead(ASYNC, 0, 0) // EOF
4134 };
4135
4136 DelayedSocketData data(1, reads, arraysize(reads),
4137 writes, arraysize(writes));
4138 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
4139 BoundNetLog(), GetParam(), NULL);
4140 helper.RunToCompletion(&data);
4141 TransactionHelperResult out = helper.output();
4142 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, out.rv);
4143 }
4144 }
4145
4146 // Verify that we don't crash on some corrupt frames.
4147 TEST_P(SpdyNetworkTransactionTest, CorruptFrameSessionError) {
4148 // This is the length field that's too short.
4149 scoped_ptr<SpdyFrame> syn_reply_wrong_length(
4150 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
4151 BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
4152 size_t right_size =
4153 (spdy_util_.spdy_version() < SPDY4) ?
4154 syn_reply_wrong_length->size() - framer.GetControlFrameHeaderSize() :
4155 syn_reply_wrong_length->size();
4156 size_t wrong_size = right_size - 4;
4157 test::SetFrameLength(syn_reply_wrong_length.get(),
4158 wrong_size,
4159 spdy_util_.spdy_version());
4160
4161 struct SynReplyTests {
4162 const SpdyFrame* syn_reply;
4163 } test_cases[] = {
4164 { syn_reply_wrong_length.get(), },
4165 };
4166
4167 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_cases); ++i) {
4168 scoped_ptr<SpdyFrame> req(
4169 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
4170 MockWrite writes[] = { CreateMockWrite(*req), MockWrite(ASYNC, 0, 0) // EOF
4171 };
4172
4173 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
4174 MockRead reads[] = {
4175 MockRead(ASYNC, test_cases[i].syn_reply->data(), wrong_size),
4176 CreateMockRead(*body),
4177 MockRead(ASYNC, 0, 0) // EOF
4178 };
4179
4180 DelayedSocketData data(1, reads, arraysize(reads),
4181 writes, arraysize(writes));
4182 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
4183 BoundNetLog(), GetParam(), NULL);
4184 helper.RunToCompletion(&data);
4185 TransactionHelperResult out = helper.output();
4186 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, out.rv);
4187 }
4188 }
4189
4190 // Test that we shutdown correctly on write errors.
4191 TEST_P(SpdyNetworkTransactionTest, WriteError) {
4192 scoped_ptr<SpdyFrame> req(
4193 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
4194 MockWrite writes[] = {
4195 // We'll write 10 bytes successfully
4196 MockWrite(ASYNC, req->data(), 10),
4197 // Followed by ERROR!
4198 MockWrite(ASYNC, ERR_FAILED),
4199 };
4200
4201 DelayedSocketData data(2, NULL, 0,
4202 writes, arraysize(writes));
4203 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
4204 BoundNetLog(), GetParam(), NULL);
4205 helper.RunToCompletion(&data);
4206 TransactionHelperResult out = helper.output();
4207 EXPECT_EQ(ERR_FAILED, out.rv);
4208 data.Reset();
4209 }
4210
4211 // Test that partial writes work.
4212 TEST_P(SpdyNetworkTransactionTest, PartialWrite) {
4213 // Chop the SYN_STREAM frame into 5 chunks.
4214 scoped_ptr<SpdyFrame> req(
4215 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
4216 const int kChunks = 5;
4217 scoped_ptr<MockWrite[]> writes(ChopWriteFrame(*req.get(), kChunks));
4218
4219 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
4220 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
4221 MockRead reads[] = {
4222 CreateMockRead(*resp),
4223 CreateMockRead(*body),
4224 MockRead(ASYNC, 0, 0) // EOF
4225 };
4226
4227 DelayedSocketData data(kChunks, reads, arraysize(reads),
4228 writes.get(), kChunks);
4229 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
4230 BoundNetLog(), GetParam(), NULL);
4231 helper.RunToCompletion(&data);
4232 TransactionHelperResult out = helper.output();
4233 EXPECT_EQ(OK, out.rv);
4234 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
4235 EXPECT_EQ("hello!", out.response_data);
4236 }
4237
4238 // In this test, we enable compression, but get a uncompressed SynReply from
4239 // the server. Verify that teardown is all clean.
4240 TEST_P(SpdyNetworkTransactionTest, DecompressFailureOnSynReply) {
4241 scoped_ptr<SpdyFrame> compressed(
4242 spdy_util_.ConstructSpdyGet(NULL, 0, true, 1, LOWEST, true));
4243 scoped_ptr<SpdyFrame> rst(
4244 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_PROTOCOL_ERROR));
4245 MockWrite writes[] = {
4246 CreateMockWrite(*compressed),
4247 };
4248
4249 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
4250 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
4251 MockRead reads[] = {
4252 CreateMockRead(*resp),
4253 };
4254
4255 DelayedSocketData data(1, reads, arraysize(reads),
4256 writes, arraysize(writes));
4257 SpdySessionDependencies* session_deps =
4258 CreateSpdySessionDependencies(GetParam());
4259 session_deps->enable_compression = true;
4260 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
4261 BoundNetLog(), GetParam(), session_deps);
4262 helper.RunToCompletion(&data);
4263 TransactionHelperResult out = helper.output();
4264 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, out.rv);
4265 data.Reset();
4266 }
4267
4268 // Test that the NetLog contains good data for a simple GET request.
4269 TEST_P(SpdyNetworkTransactionTest, NetLog) {
4270 static const char* const kExtraHeaders[] = {
4271 "user-agent", "Chrome",
4272 };
4273 scoped_ptr<SpdyFrame> req(
4274 spdy_util_.ConstructSpdyGet(kExtraHeaders, 1, false, 1, LOWEST, true));
4275 MockWrite writes[] = { CreateMockWrite(*req) };
4276
4277 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
4278 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
4279 MockRead reads[] = {
4280 CreateMockRead(*resp),
4281 CreateMockRead(*body),
4282 MockRead(ASYNC, 0, 0) // EOF
4283 };
4284
4285 CapturingBoundNetLog log;
4286
4287 DelayedSocketData data(1, reads, arraysize(reads),
4288 writes, arraysize(writes));
4289 NormalSpdyTransactionHelper helper(CreateGetRequestWithUserAgent(),
4290 DEFAULT_PRIORITY,
4291 log.bound(), GetParam(), NULL);
4292 helper.RunToCompletion(&data);
4293 TransactionHelperResult out = helper.output();
4294 EXPECT_EQ(OK, out.rv);
4295 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
4296 EXPECT_EQ("hello!", out.response_data);
4297
4298 // Check that the NetLog was filled reasonably.
4299 // This test is intentionally non-specific about the exact ordering of the
4300 // log; instead we just check to make sure that certain events exist, and that
4301 // they are in the right order.
4302 net::CapturingNetLog::CapturedEntryList entries;
4303 log.GetEntries(&entries);
4304
4305 EXPECT_LT(0u, entries.size());
4306 int pos = 0;
4307 pos = net::ExpectLogContainsSomewhere(entries, 0,
4308 net::NetLog::TYPE_HTTP_TRANSACTION_SEND_REQUEST,
4309 net::NetLog::PHASE_BEGIN);
4310 pos = net::ExpectLogContainsSomewhere(entries, pos + 1,
4311 net::NetLog::TYPE_HTTP_TRANSACTION_SEND_REQUEST,
4312 net::NetLog::PHASE_END);
4313 pos = net::ExpectLogContainsSomewhere(entries, pos + 1,
4314 net::NetLog::TYPE_HTTP_TRANSACTION_READ_HEADERS,
4315 net::NetLog::PHASE_BEGIN);
4316 pos = net::ExpectLogContainsSomewhere(entries, pos + 1,
4317 net::NetLog::TYPE_HTTP_TRANSACTION_READ_HEADERS,
4318 net::NetLog::PHASE_END);
4319 pos = net::ExpectLogContainsSomewhere(entries, pos + 1,
4320 net::NetLog::TYPE_HTTP_TRANSACTION_READ_BODY,
4321 net::NetLog::PHASE_BEGIN);
4322 pos = net::ExpectLogContainsSomewhere(entries, pos + 1,
4323 net::NetLog::TYPE_HTTP_TRANSACTION_READ_BODY,
4324 net::NetLog::PHASE_END);
4325
4326 // Check that we logged all the headers correctly
4327 pos = net::ExpectLogContainsSomewhere(
4328 entries, 0,
4329 net::NetLog::TYPE_SPDY_SESSION_SYN_STREAM,
4330 net::NetLog::PHASE_NONE);
4331
4332 base::ListValue* header_list;
4333 ASSERT_TRUE(entries[pos].params.get());
4334 ASSERT_TRUE(entries[pos].params->GetList("headers", &header_list));
4335
4336 std::vector<std::string> expected;
4337 expected.push_back(std::string(spdy_util_.GetHostKey()) + ": www.google.com");
4338 expected.push_back(std::string(spdy_util_.GetPathKey()) + ": /");
4339 expected.push_back(std::string(spdy_util_.GetSchemeKey()) + ": http");
4340 expected.push_back(std::string(spdy_util_.GetVersionKey()) + ": HTTP/1.1");
4341 expected.push_back(std::string(spdy_util_.GetMethodKey()) + ": GET");
4342 expected.push_back("user-agent: Chrome");
4343 EXPECT_EQ(expected.size(), header_list->GetSize());
4344 for (std::vector<std::string>::const_iterator it = expected.begin();
4345 it != expected.end();
4346 ++it) {
4347 base::StringValue header(*it);
4348 EXPECT_NE(header_list->end(), header_list->Find(header)) <<
4349 "Header not found: " << *it;
4350 }
4351 }
4352
4353 // Since we buffer the IO from the stream to the renderer, this test verifies
4354 // that when we read out the maximum amount of data (e.g. we received 50 bytes
4355 // on the network, but issued a Read for only 5 of those bytes) that the data
4356 // flow still works correctly.
4357 TEST_P(SpdyNetworkTransactionTest, BufferFull) {
4358 BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
4359
4360 scoped_ptr<SpdyFrame> req(
4361 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
4362 MockWrite writes[] = { CreateMockWrite(*req) };
4363
4364 // 2 data frames in a single read.
4365 scoped_ptr<SpdyFrame> data_frame_1(
4366 framer.CreateDataFrame(1, "goodby", 6, DATA_FLAG_NONE));
4367 scoped_ptr<SpdyFrame> data_frame_2(
4368 framer.CreateDataFrame(1, "e worl", 6, DATA_FLAG_NONE));
4369 const SpdyFrame* data_frames[2] = {
4370 data_frame_1.get(),
4371 data_frame_2.get(),
4372 };
4373 char combined_data_frames[100];
4374 int combined_data_frames_len =
4375 CombineFrames(data_frames, arraysize(data_frames),
4376 combined_data_frames, arraysize(combined_data_frames));
4377 scoped_ptr<SpdyFrame> last_frame(
4378 framer.CreateDataFrame(1, "d", 1, DATA_FLAG_FIN));
4379
4380 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
4381 MockRead reads[] = {
4382 CreateMockRead(*resp),
4383 MockRead(ASYNC, ERR_IO_PENDING), // Force a pause
4384 MockRead(ASYNC, combined_data_frames, combined_data_frames_len),
4385 MockRead(ASYNC, ERR_IO_PENDING), // Force a pause
4386 CreateMockRead(*last_frame),
4387 MockRead(ASYNC, 0, 0) // EOF
4388 };
4389
4390 DelayedSocketData data(1, reads, arraysize(reads),
4391 writes, arraysize(writes));
4392
4393 TestCompletionCallback callback;
4394
4395 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
4396 BoundNetLog(), GetParam(), NULL);
4397 helper.RunPreTestSetup();
4398 helper.AddData(&data);
4399 HttpNetworkTransaction* trans = helper.trans();
4400 int rv = trans->Start(
4401 &CreateGetRequest(), callback.callback(), BoundNetLog());
4402 EXPECT_EQ(ERR_IO_PENDING, rv);
4403
4404 TransactionHelperResult out = helper.output();
4405 out.rv = callback.WaitForResult();
4406 EXPECT_EQ(out.rv, OK);
4407
4408 const HttpResponseInfo* response = trans->GetResponseInfo();
4409 EXPECT_TRUE(response->headers.get() != NULL);
4410 EXPECT_TRUE(response->was_fetched_via_spdy);
4411 out.status_line = response->headers->GetStatusLine();
4412 out.response_info = *response; // Make a copy so we can verify.
4413
4414 // Read Data
4415 TestCompletionCallback read_callback;
4416
4417 std::string content;
4418 do {
4419 // Read small chunks at a time.
4420 const int kSmallReadSize = 3;
4421 scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(kSmallReadSize));
4422 rv = trans->Read(buf.get(), kSmallReadSize, read_callback.callback());
4423 if (rv == net::ERR_IO_PENDING) {
4424 data.CompleteRead();
4425 rv = read_callback.WaitForResult();
4426 }
4427 if (rv > 0) {
4428 content.append(buf->data(), rv);
4429 } else if (rv < 0) {
4430 NOTREACHED();
4431 }
4432 } while (rv > 0);
4433
4434 out.response_data.swap(content);
4435
4436 // Flush the MessageLoop while the SpdySessionDependencies (in particular, the
4437 // MockClientSocketFactory) are still alive.
4438 base::MessageLoop::current()->RunUntilIdle();
4439
4440 // Verify that we consumed all test data.
4441 helper.VerifyDataConsumed();
4442
4443 EXPECT_EQ(OK, out.rv);
4444 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
4445 EXPECT_EQ("goodbye world", out.response_data);
4446 }
4447
4448 // Verify that basic buffering works; when multiple data frames arrive
4449 // at the same time, ensure that we don't notify a read completion for
4450 // each data frame individually.
4451 TEST_P(SpdyNetworkTransactionTest, Buffering) {
4452 BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
4453
4454 scoped_ptr<SpdyFrame> req(
4455 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
4456 MockWrite writes[] = { CreateMockWrite(*req) };
4457
4458 // 4 data frames in a single read.
4459 scoped_ptr<SpdyFrame> data_frame(
4460 framer.CreateDataFrame(1, "message", 7, DATA_FLAG_NONE));
4461 scoped_ptr<SpdyFrame> data_frame_fin(
4462 framer.CreateDataFrame(1, "message", 7, DATA_FLAG_FIN));
4463 const SpdyFrame* data_frames[4] = {
4464 data_frame.get(),
4465 data_frame.get(),
4466 data_frame.get(),
4467 data_frame_fin.get()
4468 };
4469 char combined_data_frames[100];
4470 int combined_data_frames_len =
4471 CombineFrames(data_frames, arraysize(data_frames),
4472 combined_data_frames, arraysize(combined_data_frames));
4473
4474 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
4475 MockRead reads[] = {
4476 CreateMockRead(*resp),
4477 MockRead(ASYNC, ERR_IO_PENDING), // Force a pause
4478 MockRead(ASYNC, combined_data_frames, combined_data_frames_len),
4479 MockRead(ASYNC, 0, 0) // EOF
4480 };
4481
4482 DelayedSocketData data(1, reads, arraysize(reads),
4483 writes, arraysize(writes));
4484
4485 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
4486 BoundNetLog(), GetParam(), NULL);
4487 helper.RunPreTestSetup();
4488 helper.AddData(&data);
4489 HttpNetworkTransaction* trans = helper.trans();
4490
4491 TestCompletionCallback callback;
4492 int rv = trans->Start(
4493 &CreateGetRequest(), callback.callback(), BoundNetLog());
4494 EXPECT_EQ(ERR_IO_PENDING, rv);
4495
4496 TransactionHelperResult out = helper.output();
4497 out.rv = callback.WaitForResult();
4498 EXPECT_EQ(out.rv, OK);
4499
4500 const HttpResponseInfo* response = trans->GetResponseInfo();
4501 EXPECT_TRUE(response->headers.get() != NULL);
4502 EXPECT_TRUE(response->was_fetched_via_spdy);
4503 out.status_line = response->headers->GetStatusLine();
4504 out.response_info = *response; // Make a copy so we can verify.
4505
4506 // Read Data
4507 TestCompletionCallback read_callback;
4508
4509 std::string content;
4510 int reads_completed = 0;
4511 do {
4512 // Read small chunks at a time.
4513 const int kSmallReadSize = 14;
4514 scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(kSmallReadSize));
4515 rv = trans->Read(buf.get(), kSmallReadSize, read_callback.callback());
4516 if (rv == net::ERR_IO_PENDING) {
4517 data.CompleteRead();
4518 rv = read_callback.WaitForResult();
4519 }
4520 if (rv > 0) {
4521 EXPECT_EQ(kSmallReadSize, rv);
4522 content.append(buf->data(), rv);
4523 } else if (rv < 0) {
4524 FAIL() << "Unexpected read error: " << rv;
4525 }
4526 reads_completed++;
4527 } while (rv > 0);
4528
4529 EXPECT_EQ(3, reads_completed); // Reads are: 14 bytes, 14 bytes, 0 bytes.
4530
4531 out.response_data.swap(content);
4532
4533 // Flush the MessageLoop while the SpdySessionDependencies (in particular, the
4534 // MockClientSocketFactory) are still alive.
4535 base::MessageLoop::current()->RunUntilIdle();
4536
4537 // Verify that we consumed all test data.
4538 helper.VerifyDataConsumed();
4539
4540 EXPECT_EQ(OK, out.rv);
4541 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
4542 EXPECT_EQ("messagemessagemessagemessage", out.response_data);
4543 }
4544
4545 // Verify the case where we buffer data but read it after it has been buffered.
4546 TEST_P(SpdyNetworkTransactionTest, BufferedAll) {
4547 BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
4548
4549 scoped_ptr<SpdyFrame> req(
4550 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
4551 MockWrite writes[] = { CreateMockWrite(*req) };
4552
4553 // 5 data frames in a single read.
4554 scoped_ptr<SpdyFrame> syn_reply(
4555 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
4556 // turn off FIN bit
4557 test::SetFrameFlags(
4558 syn_reply.get(), CONTROL_FLAG_NONE, spdy_util_.spdy_version());
4559 scoped_ptr<SpdyFrame> data_frame(
4560 framer.CreateDataFrame(1, "message", 7, DATA_FLAG_NONE));
4561 scoped_ptr<SpdyFrame> data_frame_fin(
4562 framer.CreateDataFrame(1, "message", 7, DATA_FLAG_FIN));
4563 const SpdyFrame* frames[5] = {
4564 syn_reply.get(),
4565 data_frame.get(),
4566 data_frame.get(),
4567 data_frame.get(),
4568 data_frame_fin.get()
4569 };
4570 char combined_frames[200];
4571 int combined_frames_len =
4572 CombineFrames(frames, arraysize(frames),
4573 combined_frames, arraysize(combined_frames));
4574
4575 MockRead reads[] = {
4576 MockRead(ASYNC, combined_frames, combined_frames_len),
4577 MockRead(ASYNC, 0, 0) // EOF
4578 };
4579
4580 DelayedSocketData data(1, reads, arraysize(reads),
4581 writes, arraysize(writes));
4582
4583 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
4584 BoundNetLog(), GetParam(), NULL);
4585 helper.RunPreTestSetup();
4586 helper.AddData(&data);
4587 HttpNetworkTransaction* trans = helper.trans();
4588
4589 TestCompletionCallback callback;
4590 int rv = trans->Start(
4591 &CreateGetRequest(), callback.callback(), BoundNetLog());
4592 EXPECT_EQ(ERR_IO_PENDING, rv);
4593
4594 TransactionHelperResult out = helper.output();
4595 out.rv = callback.WaitForResult();
4596 EXPECT_EQ(out.rv, OK);
4597
4598 const HttpResponseInfo* response = trans->GetResponseInfo();
4599 EXPECT_TRUE(response->headers.get() != NULL);
4600 EXPECT_TRUE(response->was_fetched_via_spdy);
4601 out.status_line = response->headers->GetStatusLine();
4602 out.response_info = *response; // Make a copy so we can verify.
4603
4604 // Read Data
4605 TestCompletionCallback read_callback;
4606
4607 std::string content;
4608 int reads_completed = 0;
4609 do {
4610 // Read small chunks at a time.
4611 const int kSmallReadSize = 14;
4612 scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(kSmallReadSize));
4613 rv = trans->Read(buf.get(), kSmallReadSize, read_callback.callback());
4614 if (rv > 0) {
4615 EXPECT_EQ(kSmallReadSize, rv);
4616 content.append(buf->data(), rv);
4617 } else if (rv < 0) {
4618 FAIL() << "Unexpected read error: " << rv;
4619 }
4620 reads_completed++;
4621 } while (rv > 0);
4622
4623 EXPECT_EQ(3, reads_completed);
4624
4625 out.response_data.swap(content);
4626
4627 // Flush the MessageLoop while the SpdySessionDependencies (in particular, the
4628 // MockClientSocketFactory) are still alive.
4629 base::MessageLoop::current()->RunUntilIdle();
4630
4631 // Verify that we consumed all test data.
4632 helper.VerifyDataConsumed();
4633
4634 EXPECT_EQ(OK, out.rv);
4635 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
4636 EXPECT_EQ("messagemessagemessagemessage", out.response_data);
4637 }
4638
4639 // Verify the case where we buffer data and close the connection.
4640 TEST_P(SpdyNetworkTransactionTest, BufferedClosed) {
4641 BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
4642
4643 scoped_ptr<SpdyFrame> req(
4644 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
4645 MockWrite writes[] = { CreateMockWrite(*req) };
4646
4647 // All data frames in a single read.
4648 // NOTE: We don't FIN the stream.
4649 scoped_ptr<SpdyFrame> data_frame(
4650 framer.CreateDataFrame(1, "message", 7, DATA_FLAG_NONE));
4651 const SpdyFrame* data_frames[4] = {
4652 data_frame.get(),
4653 data_frame.get(),
4654 data_frame.get(),
4655 data_frame.get()
4656 };
4657 char combined_data_frames[100];
4658 int combined_data_frames_len =
4659 CombineFrames(data_frames, arraysize(data_frames),
4660 combined_data_frames, arraysize(combined_data_frames));
4661 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
4662 MockRead reads[] = {
4663 CreateMockRead(*resp),
4664 MockRead(ASYNC, ERR_IO_PENDING), // Force a wait
4665 MockRead(ASYNC, combined_data_frames, combined_data_frames_len),
4666 MockRead(ASYNC, 0, 0) // EOF
4667 };
4668
4669 DelayedSocketData data(1, reads, arraysize(reads),
4670 writes, arraysize(writes));
4671
4672 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
4673 BoundNetLog(), GetParam(), NULL);
4674 helper.RunPreTestSetup();
4675 helper.AddData(&data);
4676 HttpNetworkTransaction* trans = helper.trans();
4677
4678 TestCompletionCallback callback;
4679
4680 int rv = trans->Start(
4681 &CreateGetRequest(), callback.callback(), BoundNetLog());
4682 EXPECT_EQ(ERR_IO_PENDING, rv);
4683
4684 TransactionHelperResult out = helper.output();
4685 out.rv = callback.WaitForResult();
4686 EXPECT_EQ(out.rv, OK);
4687
4688 const HttpResponseInfo* response = trans->GetResponseInfo();
4689 EXPECT_TRUE(response->headers.get() != NULL);
4690 EXPECT_TRUE(response->was_fetched_via_spdy);
4691 out.status_line = response->headers->GetStatusLine();
4692 out.response_info = *response; // Make a copy so we can verify.
4693
4694 // Read Data
4695 TestCompletionCallback read_callback;
4696
4697 std::string content;
4698 int reads_completed = 0;
4699 do {
4700 // Read small chunks at a time.
4701 const int kSmallReadSize = 14;
4702 scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(kSmallReadSize));
4703 rv = trans->Read(buf.get(), kSmallReadSize, read_callback.callback());
4704 if (rv == net::ERR_IO_PENDING) {
4705 data.CompleteRead();
4706 rv = read_callback.WaitForResult();
4707 }
4708 if (rv > 0) {
4709 content.append(buf->data(), rv);
4710 } else if (rv < 0) {
4711 // This test intentionally closes the connection, and will get an error.
4712 EXPECT_EQ(ERR_CONNECTION_CLOSED, rv);
4713 break;
4714 }
4715 reads_completed++;
4716 } while (rv > 0);
4717
4718 EXPECT_EQ(0, reads_completed);
4719
4720 out.response_data.swap(content);
4721
4722 // Flush the MessageLoop while the SpdySessionDependencies (in particular, the
4723 // MockClientSocketFactory) are still alive.
4724 base::MessageLoop::current()->RunUntilIdle();
4725
4726 // Verify that we consumed all test data.
4727 helper.VerifyDataConsumed();
4728 }
4729
4730 // Verify the case where we buffer data and cancel the transaction.
4731 TEST_P(SpdyNetworkTransactionTest, BufferedCancelled) {
4732 BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
4733
4734 scoped_ptr<SpdyFrame> req(
4735 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
4736 MockWrite writes[] = { CreateMockWrite(*req) };
4737
4738 // NOTE: We don't FIN the stream.
4739 scoped_ptr<SpdyFrame> data_frame(
4740 framer.CreateDataFrame(1, "message", 7, DATA_FLAG_NONE));
4741
4742 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
4743 MockRead reads[] = {
4744 CreateMockRead(*resp),
4745 MockRead(ASYNC, ERR_IO_PENDING), // Force a wait
4746 CreateMockRead(*data_frame),
4747 MockRead(ASYNC, 0, 0) // EOF
4748 };
4749
4750 DelayedSocketData data(1, reads, arraysize(reads),
4751 writes, arraysize(writes));
4752
4753 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
4754 BoundNetLog(), GetParam(), NULL);
4755 helper.RunPreTestSetup();
4756 helper.AddData(&data);
4757 HttpNetworkTransaction* trans = helper.trans();
4758 TestCompletionCallback callback;
4759
4760 int rv = trans->Start(
4761 &CreateGetRequest(), callback.callback(), BoundNetLog());
4762 EXPECT_EQ(ERR_IO_PENDING, rv);
4763
4764 TransactionHelperResult out = helper.output();
4765 out.rv = callback.WaitForResult();
4766 EXPECT_EQ(out.rv, OK);
4767
4768 const HttpResponseInfo* response = trans->GetResponseInfo();
4769 EXPECT_TRUE(response->headers.get() != NULL);
4770 EXPECT_TRUE(response->was_fetched_via_spdy);
4771 out.status_line = response->headers->GetStatusLine();
4772 out.response_info = *response; // Make a copy so we can verify.
4773
4774 // Read Data
4775 TestCompletionCallback read_callback;
4776
4777 do {
4778 const int kReadSize = 256;
4779 scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(kReadSize));
4780 rv = trans->Read(buf.get(), kReadSize, read_callback.callback());
4781 if (rv == net::ERR_IO_PENDING) {
4782 // Complete the read now, which causes buffering to start.
4783 data.CompleteRead();
4784 // Destroy the transaction, causing the stream to get cancelled
4785 // and orphaning the buffered IO task.
4786 helper.ResetTrans();
4787 break;
4788 }
4789 // We shouldn't get here in this test.
4790 FAIL() << "Unexpected read: " << rv;
4791 } while (rv > 0);
4792
4793 // Flush the MessageLoop; this will cause the buffered IO task
4794 // to run for the final time.
4795 base::MessageLoop::current()->RunUntilIdle();
4796
4797 // Verify that we consumed all test data.
4798 helper.VerifyDataConsumed();
4799 }
4800
4801 // Test that if the server requests persistence of settings, that we save
4802 // the settings in the HttpServerProperties.
4803 TEST_P(SpdyNetworkTransactionTest, SettingsSaved) {
4804 static const SpdyHeaderInfo kSynReplyInfo = {
4805 SYN_REPLY, // Syn Reply
4806 1, // Stream ID
4807 0, // Associated Stream ID
4808 ConvertRequestPriorityToSpdyPriority(
4809 LOWEST, spdy_util_.spdy_version()),
4810 kSpdyCredentialSlotUnused,
4811 CONTROL_FLAG_NONE, // Control Flags
4812 false, // Compressed
4813 RST_STREAM_INVALID, // Status
4814 NULL, // Data
4815 0, // Data Length
4816 DATA_FLAG_NONE // Data Flags
4817 };
4818 4181
4819 BoundNetLog net_log; 4182 BoundNetLog net_log;
4820 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY, 4183 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
4821 net_log, GetParam(), NULL); 4184 net_log, GetParam(), NULL);
4822 helper.RunPreTestSetup(); 4185 helper.RunPreTestSetup();
4823 4186
4824 // Verify that no settings exist initially. 4187 // Verify that no settings exist initially.
4825 HostPortPair host_port_pair("www.google.com", helper.port()); 4188 HostPortPair host_port_pair("www.google.com", helper.port());
4826 SpdySessionPool* spdy_session_pool = helper.session()->spdy_session_pool(); 4189 SpdySessionPool* spdy_session_pool = helper.session()->spdy_session_pool();
4827 EXPECT_TRUE(spdy_session_pool->http_server_properties()->GetSpdySettings( 4190 EXPECT_TRUE(spdy_session_pool->http_server_properties()->GetSpdySettings(
(...skipping 1549 matching lines...) Expand 10 before | Expand all | Expand 10 after
6377 5740
6378 // And now we can allow everything else to run to completion. 5741 // And now we can allow everything else to run to completion.
6379 data.SetStop(10); 5742 data.SetStop(10);
6380 data.Run(); 5743 data.Run();
6381 EXPECT_EQ(OK, callback2.WaitForResult()); 5744 EXPECT_EQ(OK, callback2.WaitForResult());
6382 EXPECT_EQ(OK, callback3.WaitForResult()); 5745 EXPECT_EQ(OK, callback3.WaitForResult());
6383 5746
6384 helper.VerifyDataConsumed(); 5747 helper.VerifyDataConsumed();
6385 } 5748 }
6386 5749
5750 // The tests below are only for SPDY/3 and above.
5751
5752 // Test that sent data frames and received WINDOW_UPDATE frames change
5753 // the send_window_size_ correctly.
5754
5755 // WINDOW_UPDATE is different than most other frames in that it can arrive
5756 // while the client is still sending the request body. In order to enforce
5757 // this scenario, we feed a couple of dummy frames and give a delay of 0 to
5758 // socket data provider, so that initial read that is done as soon as the
5759 // stream is created, succeeds and schedules another read. This way reads
5760 // and writes are interleaved; after doing a full frame write, SpdyStream
5761 // will break out of DoLoop and will read and process a WINDOW_UPDATE.
5762 // Once our WINDOW_UPDATE is read, we cannot send SYN_REPLY right away
5763 // since request has not been completely written, therefore we feed
5764 // enough number of WINDOW_UPDATEs to finish the first read and cause a
5765 // write, leading to a complete write of request body; after that we send
5766 // a reply with a body, to cause a graceful shutdown.
5767
5768 // TODO(agayev): develop a socket data provider where both, reads and
5769 // writes are ordered so that writing tests like these are easy and rewrite
5770 // all these tests using it. Right now we are working around the
5771 // limitations as described above and it's not deterministic, tests may
5772 // fail under specific circumstances.
5773 TEST_P(SpdyNetworkTransactionTest, WindowUpdateReceived) {
5774 if (GetParam().protocol < kProtoSPDY3)
5775 return;
5776
5777 static int kFrameCount = 2;
5778 scoped_ptr<std::string> content(
5779 new std::string(kMaxSpdyFrameChunkSize, 'a'));
5780 scoped_ptr<SpdyFrame> req(spdy_util_.ConstructSpdyPost(
5781 kRequestUrl, 1, kMaxSpdyFrameChunkSize * kFrameCount, LOWEST, NULL, 0));
5782 scoped_ptr<SpdyFrame> body(
5783 spdy_util_.ConstructSpdyBodyFrame(
5784 1, content->c_str(), content->size(), false));
5785 scoped_ptr<SpdyFrame> body_end(
5786 spdy_util_.ConstructSpdyBodyFrame(
5787 1, content->c_str(), content->size(), true));
5788
5789 MockWrite writes[] = {
5790 CreateMockWrite(*req, 0),
5791 CreateMockWrite(*body, 1),
5792 CreateMockWrite(*body_end, 2),
5793 };
5794
5795 static const int32 kDeltaWindowSize = 0xff;
5796 static const int kDeltaCount = 4;
5797 scoped_ptr<SpdyFrame> window_update(
5798 spdy_util_.ConstructSpdyWindowUpdate(1, kDeltaWindowSize));
5799 scoped_ptr<SpdyFrame> window_update_dummy(
5800 spdy_util_.ConstructSpdyWindowUpdate(2, kDeltaWindowSize));
5801 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
5802 MockRead reads[] = {
5803 CreateMockRead(*window_update_dummy, 3),
5804 CreateMockRead(*window_update_dummy, 4),
5805 CreateMockRead(*window_update_dummy, 5),
5806 CreateMockRead(*window_update, 6), // Four updates, therefore window
5807 CreateMockRead(*window_update, 7), // size should increase by
5808 CreateMockRead(*window_update, 8), // kDeltaWindowSize * 4
5809 CreateMockRead(*window_update, 9),
5810 CreateMockRead(*resp, 10),
5811 CreateMockRead(*body_end, 11),
5812 MockRead(ASYNC, 0, 0, 12) // EOF
5813 };
5814
5815 DeterministicSocketData data(reads, arraysize(reads),
5816 writes, arraysize(writes));
5817
5818 ScopedVector<UploadElementReader> element_readers;
5819 for (int i = 0; i < kFrameCount; ++i) {
5820 element_readers.push_back(
5821 new UploadBytesElementReader(content->c_str(), content->size()));
5822 }
5823 UploadDataStream upload_data_stream(&element_readers, 0);
5824
5825 // Setup the request
5826 HttpRequestInfo request;
5827 request.method = "POST";
5828 request.url = GURL(kDefaultURL);
5829 request.upload_data_stream = &upload_data_stream;
5830
5831 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY,
5832 BoundNetLog(), GetParam(), NULL);
5833 helper.SetDeterministic();
5834 helper.AddDeterministicData(&data);
5835 helper.RunPreTestSetup();
5836
5837 HttpNetworkTransaction* trans = helper.trans();
5838
5839 TestCompletionCallback callback;
5840 int rv = trans->Start(&helper.request(), callback.callback(), BoundNetLog());
5841
5842 EXPECT_EQ(ERR_IO_PENDING, rv);
5843
5844 data.RunFor(11);
5845
5846 SpdyHttpStream* stream = static_cast<SpdyHttpStream*>(trans->stream_.get());
5847 ASSERT_TRUE(stream != NULL);
5848 ASSERT_TRUE(stream->stream() != NULL);
5849 EXPECT_EQ(static_cast<int>(kSpdyStreamInitialWindowSize) +
5850 kDeltaWindowSize * kDeltaCount -
5851 kMaxSpdyFrameChunkSize * kFrameCount,
5852 stream->stream()->send_window_size());
5853
5854 data.RunFor(1);
5855
5856 rv = callback.WaitForResult();
5857 EXPECT_EQ(OK, rv);
5858
5859 helper.VerifyDataConsumed();
5860 }
5861
5862 // Test that received data frames and sent WINDOW_UPDATE frames change
5863 // the recv_window_size_ correctly.
5864 TEST_P(SpdyNetworkTransactionTest, WindowUpdateSent) {
5865 if (GetParam().protocol < kProtoSPDY3)
5866 return;
5867
5868 // Set the data in the body frame large enough to trigger sending a
5869 // WINDOW_UPDATE by the stream.
5870 const std::string body_data(kSpdyStreamInitialWindowSize / 2 + 1, 'x');
5871
5872 scoped_ptr<SpdyFrame> req(
5873 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
5874 scoped_ptr<SpdyFrame> session_window_update(
5875 spdy_util_.ConstructSpdyWindowUpdate(0, body_data.size()));
5876 scoped_ptr<SpdyFrame> window_update(
5877 spdy_util_.ConstructSpdyWindowUpdate(1, body_data.size()));
5878
5879 std::vector<MockWrite> writes;
5880 writes.push_back(CreateMockWrite(*req));
5881 if (GetParam().protocol >= kProtoSPDY31)
5882 writes.push_back(CreateMockWrite(*session_window_update));
5883 writes.push_back(CreateMockWrite(*window_update));
5884
5885 scoped_ptr<SpdyFrame> resp(
5886 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
5887 scoped_ptr<SpdyFrame> body_no_fin(
5888 spdy_util_.ConstructSpdyBodyFrame(
5889 1, body_data.data(), body_data.size(), false));
5890 scoped_ptr<SpdyFrame> body_fin(
5891 spdy_util_.ConstructSpdyBodyFrame(1, NULL, 0, true));
5892 MockRead reads[] = {
5893 CreateMockRead(*resp),
5894 CreateMockRead(*body_no_fin),
5895 MockRead(ASYNC, ERR_IO_PENDING, 0), // Force a pause
5896 CreateMockRead(*body_fin),
5897 MockRead(ASYNC, ERR_IO_PENDING, 0), // Force a pause
5898 MockRead(ASYNC, 0, 0) // EOF
5899 };
5900
5901 DelayedSocketData data(1, reads, arraysize(reads),
5902 vector_as_array(&writes), writes.size());
5903
5904 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
5905 BoundNetLog(), GetParam(), NULL);
5906 helper.AddData(&data);
5907 helper.RunPreTestSetup();
5908 HttpNetworkTransaction* trans = helper.trans();
5909
5910 TestCompletionCallback callback;
5911 int rv = trans->Start(&helper.request(), callback.callback(), BoundNetLog());
5912
5913 EXPECT_EQ(ERR_IO_PENDING, rv);
5914 rv = callback.WaitForResult();
5915 EXPECT_EQ(OK, rv);
5916
5917 SpdyHttpStream* stream =
5918 static_cast<SpdyHttpStream*>(trans->stream_.get());
5919 ASSERT_TRUE(stream != NULL);
5920 ASSERT_TRUE(stream->stream() != NULL);
5921
5922 EXPECT_EQ(
5923 static_cast<int>(kSpdyStreamInitialWindowSize - body_data.size()),
5924 stream->stream()->recv_window_size());
5925
5926 const HttpResponseInfo* response = trans->GetResponseInfo();
5927 ASSERT_TRUE(response != NULL);
5928 ASSERT_TRUE(response->headers.get() != NULL);
5929 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
5930 EXPECT_TRUE(response->was_fetched_via_spdy);
5931
5932 // Issue a read which will cause a WINDOW_UPDATE to be sent and window
5933 // size increased to default.
5934 scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(body_data.size()));
5935 rv = trans->Read(buf.get(), body_data.size(), CompletionCallback());
5936 EXPECT_EQ(static_cast<int>(body_data.size()), rv);
5937 std::string content(buf->data(), buf->data() + body_data.size());
5938 EXPECT_EQ(body_data, content);
5939
5940 // Schedule the reading of empty data frame with FIN
5941 data.CompleteRead();
5942
5943 // Force write of WINDOW_UPDATE which was scheduled during the above
5944 // read.
5945 base::MessageLoop::current()->RunUntilIdle();
5946
5947 // Read EOF.
5948 data.CompleteRead();
5949
5950 helper.VerifyDataConsumed();
5951 }
5952
5953 // Test that WINDOW_UPDATE frame causing overflow is handled correctly.
5954 TEST_P(SpdyNetworkTransactionTest, WindowUpdateOverflow) {
5955 if (GetParam().protocol < kProtoSPDY3)
5956 return;
5957
5958 // Number of full frames we hope to write (but will not, used to
5959 // set content-length header correctly)
5960 static int kFrameCount = 3;
5961
5962 scoped_ptr<std::string> content(
5963 new std::string(kMaxSpdyFrameChunkSize, 'a'));
5964 scoped_ptr<SpdyFrame> req(spdy_util_.ConstructSpdyPost(
5965 kRequestUrl, 1, kMaxSpdyFrameChunkSize * kFrameCount, LOWEST, NULL, 0));
5966 scoped_ptr<SpdyFrame> body(
5967 spdy_util_.ConstructSpdyBodyFrame(
5968 1, content->c_str(), content->size(), false));
5969 scoped_ptr<SpdyFrame> rst(
5970 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_FLOW_CONTROL_ERROR));
5971
5972 // We're not going to write a data frame with FIN, we'll receive a bad
5973 // WINDOW_UPDATE while sending a request and will send a RST_STREAM frame.
5974 MockWrite writes[] = {
5975 CreateMockWrite(*req, 0),
5976 CreateMockWrite(*body, 2),
5977 CreateMockWrite(*rst, 3),
5978 };
5979
5980 static const int32 kDeltaWindowSize = 0x7fffffff; // cause an overflow
5981 scoped_ptr<SpdyFrame> window_update(
5982 spdy_util_.ConstructSpdyWindowUpdate(1, kDeltaWindowSize));
5983 MockRead reads[] = {
5984 CreateMockRead(*window_update, 1),
5985 MockRead(ASYNC, 0, 4) // EOF
5986 };
5987
5988 DeterministicSocketData data(reads, arraysize(reads),
5989 writes, arraysize(writes));
5990
5991 ScopedVector<UploadElementReader> element_readers;
5992 for (int i = 0; i < kFrameCount; ++i) {
5993 element_readers.push_back(
5994 new UploadBytesElementReader(content->c_str(), content->size()));
5995 }
5996 UploadDataStream upload_data_stream(&element_readers, 0);
5997
5998 // Setup the request
5999 HttpRequestInfo request;
6000 request.method = "POST";
6001 request.url = GURL("http://www.google.com/");
6002 request.upload_data_stream = &upload_data_stream;
6003
6004 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY,
6005 BoundNetLog(), GetParam(), NULL);
6006 helper.SetDeterministic();
6007 helper.RunPreTestSetup();
6008 helper.AddDeterministicData(&data);
6009 HttpNetworkTransaction* trans = helper.trans();
6010
6011 TestCompletionCallback callback;
6012 int rv = trans->Start(&helper.request(), callback.callback(), BoundNetLog());
6013 ASSERT_EQ(ERR_IO_PENDING, rv);
6014
6015 data.RunFor(5);
6016 ASSERT_TRUE(callback.have_result());
6017 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, callback.WaitForResult());
6018 helper.VerifyDataConsumed();
6019 }
6020
6021 // Test that after hitting a send window size of 0, the write process
6022 // stalls and upon receiving WINDOW_UPDATE frame write resumes.
6023
6024 // This test constructs a POST request followed by enough data frames
6025 // containing 'a' that would make the window size 0, followed by another
6026 // data frame containing default content (which is "hello!") and this frame
6027 // also contains a FIN flag. DelayedSocketData is used to enforce all
6028 // writes go through before a read could happen. However, the last frame
6029 // ("hello!") is not supposed to go through since by the time its turn
6030 // arrives, window size is 0. At this point MessageLoop::Run() called via
6031 // callback would block. Therefore we call MessageLoop::RunUntilIdle()
6032 // which returns after performing all possible writes. We use DCHECKS to
6033 // ensure that last data frame is still there and stream has stalled.
6034 // After that, next read is artifically enforced, which causes a
6035 // WINDOW_UPDATE to be read and I/O process resumes.
6036 TEST_P(SpdyNetworkTransactionTest, FlowControlStallResume) {
6037 if (GetParam().protocol < kProtoSPDY3)
6038 return;
6039
6040 // Number of frames we need to send to zero out the window size: data
6041 // frames plus SYN_STREAM plus the last data frame; also we need another
6042 // data frame that we will send once the WINDOW_UPDATE is received,
6043 // therefore +3.
6044 size_t num_writes = kSpdyStreamInitialWindowSize / kMaxSpdyFrameChunkSize + 3;
6045
6046 // Calculate last frame's size; 0 size data frame is legal.
6047 size_t last_frame_size =
6048 kSpdyStreamInitialWindowSize % kMaxSpdyFrameChunkSize;
6049
6050 // Construct content for a data frame of maximum size.
6051 std::string content(kMaxSpdyFrameChunkSize, 'a');
6052
6053 scoped_ptr<SpdyFrame> req(spdy_util_.ConstructSpdyPost(
6054 kRequestUrl, 1, kSpdyStreamInitialWindowSize + kUploadDataSize,
6055 LOWEST, NULL, 0));
6056
6057 // Full frames.
6058 scoped_ptr<SpdyFrame> body1(
6059 spdy_util_.ConstructSpdyBodyFrame(
6060 1, content.c_str(), content.size(), false));
6061
6062 // Last frame to zero out the window size.
6063 scoped_ptr<SpdyFrame> body2(
6064 spdy_util_.ConstructSpdyBodyFrame(
6065 1, content.c_str(), last_frame_size, false));
6066
6067 // Data frame to be sent once WINDOW_UPDATE frame is received.
6068 scoped_ptr<SpdyFrame> body3(spdy_util_.ConstructSpdyBodyFrame(1, true));
6069
6070 // Fill in mock writes.
6071 scoped_ptr<MockWrite[]> writes(new MockWrite[num_writes]);
6072 size_t i = 0;
6073 writes[i] = CreateMockWrite(*req);
6074 for (i = 1; i < num_writes - 2; i++)
6075 writes[i] = CreateMockWrite(*body1);
6076 writes[i++] = CreateMockWrite(*body2);
6077 writes[i] = CreateMockWrite(*body3);
6078
6079 // Construct read frame, give enough space to upload the rest of the
6080 // data.
6081 scoped_ptr<SpdyFrame> session_window_update(
6082 spdy_util_.ConstructSpdyWindowUpdate(0, kUploadDataSize));
6083 scoped_ptr<SpdyFrame> window_update(
6084 spdy_util_.ConstructSpdyWindowUpdate(1, kUploadDataSize));
6085 scoped_ptr<SpdyFrame> reply(spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
6086 MockRead reads[] = {
6087 CreateMockRead(*session_window_update),
6088 CreateMockRead(*session_window_update),
6089 CreateMockRead(*window_update),
6090 CreateMockRead(*window_update),
6091 CreateMockRead(*reply),
6092 CreateMockRead(*body2),
6093 CreateMockRead(*body3),
6094 MockRead(ASYNC, 0, 0) // EOF
6095 };
6096
6097 // Skip the session window updates unless we're using SPDY/3.1 and
6098 // above.
6099 size_t read_offset = (GetParam().protocol >= kProtoSPDY31) ? 0 : 2;
6100 size_t num_reads = arraysize(reads) - read_offset;
6101
6102 // Force all writes to happen before any read, last write will not
6103 // actually queue a frame, due to window size being 0.
6104 DelayedSocketData data(num_writes, reads + read_offset, num_reads,
6105 writes.get(), num_writes);
6106
6107 ScopedVector<UploadElementReader> element_readers;
6108 std::string upload_data_string(kSpdyStreamInitialWindowSize, 'a');
6109 upload_data_string.append(kUploadData, kUploadDataSize);
6110 element_readers.push_back(new UploadBytesElementReader(
6111 upload_data_string.c_str(), upload_data_string.size()));
6112 UploadDataStream upload_data_stream(&element_readers, 0);
6113
6114 HttpRequestInfo request;
6115 request.method = "POST";
6116 request.url = GURL("http://www.google.com/");
6117 request.upload_data_stream = &upload_data_stream;
6118 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY,
6119 BoundNetLog(), GetParam(), NULL);
6120 helper.AddData(&data);
6121 helper.RunPreTestSetup();
6122
6123 HttpNetworkTransaction* trans = helper.trans();
6124
6125 TestCompletionCallback callback;
6126 int rv = trans->Start(&helper.request(), callback.callback(), BoundNetLog());
6127 EXPECT_EQ(ERR_IO_PENDING, rv);
6128
6129 base::MessageLoop::current()->RunUntilIdle(); // Write as much as we can.
6130
6131 SpdyHttpStream* stream = static_cast<SpdyHttpStream*>(trans->stream_.get());
6132 ASSERT_TRUE(stream != NULL);
6133 ASSERT_TRUE(stream->stream() != NULL);
6134 EXPECT_EQ(0, stream->stream()->send_window_size());
6135 // All the body data should have been read.
6136 // TODO(satorux): This is because of the weirdness in reading the request
6137 // body in OnSendBodyComplete(). See crbug.com/113107.
6138 EXPECT_TRUE(upload_data_stream.IsEOF());
6139 // But the body is not yet fully sent (kUploadData is not yet sent)
6140 // since we're send-stalled.
6141 EXPECT_TRUE(stream->stream()->send_stalled_by_flow_control());
6142
6143 data.ForceNextRead(); // Read in WINDOW_UPDATE frame.
6144 rv = callback.WaitForResult();
6145 helper.VerifyDataConsumed();
6146 }
6147
6148 // Test we correctly handle the case where the SETTINGS frame results in
6149 // unstalling the send window.
6150 TEST_P(SpdyNetworkTransactionTest, FlowControlStallResumeAfterSettings) {
6151 if (GetParam().protocol < kProtoSPDY3)
6152 return;
6153
6154 // Number of frames we need to send to zero out the window size: data
6155 // frames plus SYN_STREAM plus the last data frame; also we need another
6156 // data frame that we will send once the SETTING is received, therefore +3.
6157 size_t num_writes = kSpdyStreamInitialWindowSize / kMaxSpdyFrameChunkSize + 3;
6158
6159 // Calculate last frame's size; 0 size data frame is legal.
6160 size_t last_frame_size =
6161 kSpdyStreamInitialWindowSize % kMaxSpdyFrameChunkSize;
6162
6163 // Construct content for a data frame of maximum size.
6164 std::string content(kMaxSpdyFrameChunkSize, 'a');
6165
6166 scoped_ptr<SpdyFrame> req(spdy_util_.ConstructSpdyPost(
6167 kRequestUrl, 1, kSpdyStreamInitialWindowSize + kUploadDataSize,
6168 LOWEST, NULL, 0));
6169
6170 // Full frames.
6171 scoped_ptr<SpdyFrame> body1(
6172 spdy_util_.ConstructSpdyBodyFrame(
6173 1, content.c_str(), content.size(), false));
6174
6175 // Last frame to zero out the window size.
6176 scoped_ptr<SpdyFrame> body2(
6177 spdy_util_.ConstructSpdyBodyFrame(
6178 1, content.c_str(), last_frame_size, false));
6179
6180 // Data frame to be sent once SETTINGS frame is received.
6181 scoped_ptr<SpdyFrame> body3(spdy_util_.ConstructSpdyBodyFrame(1, true));
6182
6183 // Fill in mock reads/writes.
6184 std::vector<MockRead> reads;
6185 std::vector<MockWrite> writes;
6186 size_t i = 0;
6187 writes.push_back(CreateMockWrite(*req, i++));
6188 while (i < num_writes - 2)
6189 writes.push_back(CreateMockWrite(*body1, i++));
6190 writes.push_back(CreateMockWrite(*body2, i++));
6191
6192 // Construct read frame for SETTINGS that gives enough space to upload the
6193 // rest of the data.
6194 SettingsMap settings;
6195 settings[SETTINGS_INITIAL_WINDOW_SIZE] =
6196 SettingsFlagsAndValue(
6197 SETTINGS_FLAG_NONE, kSpdyStreamInitialWindowSize * 2);
6198 scoped_ptr<SpdyFrame> settings_frame_large(
6199 spdy_util_.ConstructSpdySettings(settings));
6200
6201 reads.push_back(CreateMockRead(*settings_frame_large, i++));
6202
6203 scoped_ptr<SpdyFrame> session_window_update(
6204 spdy_util_.ConstructSpdyWindowUpdate(0, kUploadDataSize));
6205 if (GetParam().protocol >= kProtoSPDY31)
6206 reads.push_back(CreateMockRead(*session_window_update, i++));
6207
6208 writes.push_back(CreateMockWrite(*body3, i++));
6209
6210 scoped_ptr<SpdyFrame> reply(spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
6211 reads.push_back(CreateMockRead(*reply, i++));
6212 reads.push_back(CreateMockRead(*body2, i++));
6213 reads.push_back(CreateMockRead(*body3, i++));
6214 reads.push_back(MockRead(ASYNC, 0, i++)); // EOF
6215
6216 // Force all writes to happen before any read, last write will not
6217 // actually queue a frame, due to window size being 0.
6218 DeterministicSocketData data(vector_as_array(&reads), reads.size(),
6219 vector_as_array(&writes), writes.size());
6220
6221 ScopedVector<UploadElementReader> element_readers;
6222 std::string upload_data_string(kSpdyStreamInitialWindowSize, 'a');
6223 upload_data_string.append(kUploadData, kUploadDataSize);
6224 element_readers.push_back(new UploadBytesElementReader(
6225 upload_data_string.c_str(), upload_data_string.size()));
6226 UploadDataStream upload_data_stream(&element_readers, 0);
6227
6228 HttpRequestInfo request;
6229 request.method = "POST";
6230 request.url = GURL("http://www.google.com/");
6231 request.upload_data_stream = &upload_data_stream;
6232 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY,
6233 BoundNetLog(), GetParam(), NULL);
6234 helper.SetDeterministic();
6235 helper.RunPreTestSetup();
6236 helper.AddDeterministicData(&data);
6237
6238 HttpNetworkTransaction* trans = helper.trans();
6239
6240 TestCompletionCallback callback;
6241 int rv = trans->Start(&helper.request(), callback.callback(), BoundNetLog());
6242 EXPECT_EQ(ERR_IO_PENDING, rv);
6243
6244 data.RunFor(num_writes - 1); // Write as much as we can.
6245
6246 SpdyHttpStream* stream = static_cast<SpdyHttpStream*>(trans->stream_.get());
6247 ASSERT_TRUE(stream != NULL);
6248 ASSERT_TRUE(stream->stream() != NULL);
6249 EXPECT_EQ(0, stream->stream()->send_window_size());
6250
6251 // All the body data should have been read.
6252 // TODO(satorux): This is because of the weirdness in reading the request
6253 // body in OnSendBodyComplete(). See crbug.com/113107.
6254 EXPECT_TRUE(upload_data_stream.IsEOF());
6255 // But the body is not yet fully sent (kUploadData is not yet sent)
6256 // since we're send-stalled.
6257 EXPECT_TRUE(stream->stream()->send_stalled_by_flow_control());
6258
6259 data.RunFor(6); // Read in SETTINGS frame to unstall.
6260 rv = callback.WaitForResult();
6261 helper.VerifyDataConsumed();
6262 // If stream is NULL, that means it was unstalled and closed.
6263 EXPECT_TRUE(stream->stream() == NULL);
6264 }
6265
6266 // Test we correctly handle the case where the SETTINGS frame results in a
6267 // negative send window size.
6268 TEST_P(SpdyNetworkTransactionTest, FlowControlNegativeSendWindowSize) {
6269 if (GetParam().protocol < kProtoSPDY3)
6270 return;
6271
6272 // Number of frames we need to send to zero out the window size: data
6273 // frames plus SYN_STREAM plus the last data frame; also we need another
6274 // data frame that we will send once the SETTING is received, therefore +3.
6275 size_t num_writes = kSpdyStreamInitialWindowSize / kMaxSpdyFrameChunkSize + 3;
6276
6277 // Calculate last frame's size; 0 size data frame is legal.
6278 size_t last_frame_size =
6279 kSpdyStreamInitialWindowSize % kMaxSpdyFrameChunkSize;
6280
6281 // Construct content for a data frame of maximum size.
6282 std::string content(kMaxSpdyFrameChunkSize, 'a');
6283
6284 scoped_ptr<SpdyFrame> req(spdy_util_.ConstructSpdyPost(
6285 kRequestUrl, 1, kSpdyStreamInitialWindowSize + kUploadDataSize,
6286 LOWEST, NULL, 0));
6287
6288 // Full frames.
6289 scoped_ptr<SpdyFrame> body1(
6290 spdy_util_.ConstructSpdyBodyFrame(
6291 1, content.c_str(), content.size(), false));
6292
6293 // Last frame to zero out the window size.
6294 scoped_ptr<SpdyFrame> body2(
6295 spdy_util_.ConstructSpdyBodyFrame(
6296 1, content.c_str(), last_frame_size, false));
6297
6298 // Data frame to be sent once SETTINGS frame is received.
6299 scoped_ptr<SpdyFrame> body3(spdy_util_.ConstructSpdyBodyFrame(1, true));
6300
6301 // Fill in mock reads/writes.
6302 std::vector<MockRead> reads;
6303 std::vector<MockWrite> writes;
6304 size_t i = 0;
6305 writes.push_back(CreateMockWrite(*req, i++));
6306 while (i < num_writes - 2)
6307 writes.push_back(CreateMockWrite(*body1, i++));
6308 writes.push_back(CreateMockWrite(*body2, i++));
6309
6310 // Construct read frame for SETTINGS that makes the send_window_size
6311 // negative.
6312 SettingsMap new_settings;
6313 new_settings[SETTINGS_INITIAL_WINDOW_SIZE] =
6314 SettingsFlagsAndValue(
6315 SETTINGS_FLAG_NONE, kSpdyStreamInitialWindowSize / 2);
6316 scoped_ptr<SpdyFrame> settings_frame_small(
6317 spdy_util_.ConstructSpdySettings(new_settings));
6318 // Construct read frames for WINDOW_UPDATE that makes the send_window_size
6319 // positive.
6320 scoped_ptr<SpdyFrame> session_window_update_init_size(
6321 spdy_util_.ConstructSpdyWindowUpdate(0, kSpdyStreamInitialWindowSize));
6322 scoped_ptr<SpdyFrame> window_update_init_size(
6323 spdy_util_.ConstructSpdyWindowUpdate(1, kSpdyStreamInitialWindowSize));
6324
6325 reads.push_back(CreateMockRead(*settings_frame_small, i++));
6326
6327 if (GetParam().protocol >= kProtoSPDY3)
6328 reads.push_back(CreateMockRead(*session_window_update_init_size, i++));
6329
6330 reads.push_back(CreateMockRead(*window_update_init_size, i++));
6331
6332 writes.push_back(CreateMockWrite(*body3, i++));
6333
6334 scoped_ptr<SpdyFrame> reply(spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
6335 reads.push_back(CreateMockRead(*reply, i++));
6336 reads.push_back(CreateMockRead(*body2, i++));
6337 reads.push_back(CreateMockRead(*body3, i++));
6338 reads.push_back(MockRead(ASYNC, 0, i++)); // EOF
6339
6340 // Force all writes to happen before any read, last write will not
6341 // actually queue a frame, due to window size being 0.
6342 DeterministicSocketData data(vector_as_array(&reads), reads.size(),
6343 vector_as_array(&writes), writes.size());
6344
6345 ScopedVector<UploadElementReader> element_readers;
6346 std::string upload_data_string(kSpdyStreamInitialWindowSize, 'a');
6347 upload_data_string.append(kUploadData, kUploadDataSize);
6348 element_readers.push_back(new UploadBytesElementReader(
6349 upload_data_string.c_str(), upload_data_string.size()));
6350 UploadDataStream upload_data_stream(&element_readers, 0);
6351
6352 HttpRequestInfo request;
6353 request.method = "POST";
6354 request.url = GURL("http://www.google.com/");
6355 request.upload_data_stream = &upload_data_stream;
6356 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY,
6357 BoundNetLog(), GetParam(), NULL);
6358 helper.SetDeterministic();
6359 helper.RunPreTestSetup();
6360 helper.AddDeterministicData(&data);
6361
6362 HttpNetworkTransaction* trans = helper.trans();
6363
6364 TestCompletionCallback callback;
6365 int rv = trans->Start(&helper.request(), callback.callback(), BoundNetLog());
6366 EXPECT_EQ(ERR_IO_PENDING, rv);
6367
6368 data.RunFor(num_writes - 1); // Write as much as we can.
6369
6370 SpdyHttpStream* stream = static_cast<SpdyHttpStream*>(trans->stream_.get());
6371 ASSERT_TRUE(stream != NULL);
6372 ASSERT_TRUE(stream->stream() != NULL);
6373 EXPECT_EQ(0, stream->stream()->send_window_size());
6374
6375 // All the body data should have been read.
6376 // TODO(satorux): This is because of the weirdness in reading the request
6377 // body in OnSendBodyComplete(). See crbug.com/113107.
6378 EXPECT_TRUE(upload_data_stream.IsEOF());
6379 // But the body is not yet fully sent (kUploadData is not yet sent)
6380 // since we're send-stalled.
6381 EXPECT_TRUE(stream->stream()->send_stalled_by_flow_control());
6382
6383 // Read in WINDOW_UPDATE or SETTINGS frame.
6384 data.RunFor((GetParam().protocol >= kProtoSPDY31) ? 8 : 7);
6385 rv = callback.WaitForResult();
6386 helper.VerifyDataConsumed();
6387 }
6388
6387 } // namespace net 6389 } // namespace net
OLDNEW
« no previous file with comments | « net/spdy/spdy_http_stream_unittest.cc ('k') | net/spdy/spdy_session_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698