Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 76 case kProtoHTTP11: | 76 case kProtoHTTP11: |
| 77 case kProtoSPDY1: | 77 case kProtoSPDY1: |
| 78 case kProtoSPDY21: | 78 case kProtoSPDY21: |
| 79 break; | 79 break; |
| 80 } | 80 } |
| 81 | 81 |
| 82 NOTREACHED(); | 82 NOTREACHED(); |
| 83 return HttpResponseInfo::CONNECTION_INFO_SPDY2; | 83 return HttpResponseInfo::CONNECTION_INFO_SPDY2; |
| 84 } | 84 } |
| 85 | 85 |
| 86 AlternateProtocol NextProtoToAlternateProtocol(NextProto next_proto) { | |
| 87 switch (next_proto) { | |
| 88 case kProtoSPDY2: | |
| 89 return NPN_SPDY_2; | |
| 90 case kProtoSPDY3: | |
| 91 return NPN_SPDY_3; | |
| 92 case kProtoSPDY31: | |
| 93 return NPN_SPDY_3_1; | |
| 94 case kProtoSPDY4a2: | |
| 95 return NPN_SPDY_4A2; | |
| 96 | |
| 97 case kProtoUnknown: | |
| 98 case kProtoHTTP11: | |
| 99 case kProtoSPDY1: | |
| 100 case kProtoSPDY21: | |
| 101 break; | |
| 102 } | |
| 103 | |
| 104 NOTREACHED(); | |
| 105 return NPN_SPDY_2; | |
| 106 } | |
| 107 | |
| 108 SpdySessionDependencies* CreateSpdySessionDependencies( | 86 SpdySessionDependencies* CreateSpdySessionDependencies( |
| 109 SpdyNetworkTransactionTestParams test_params) { | 87 SpdyNetworkTransactionTestParams test_params) { |
| 110 return new SpdySessionDependencies(test_params.protocol); | 88 return new SpdySessionDependencies(test_params.protocol); |
| 111 } | 89 } |
| 112 | 90 |
| 113 SpdySessionDependencies* CreateSpdySessionDependencies( | 91 SpdySessionDependencies* CreateSpdySessionDependencies( |
| 114 SpdyNetworkTransactionTestParams test_params, | 92 SpdyNetworkTransactionTestParams test_params, |
| 115 ProxyService* proxy_service) { | 93 ProxyService* proxy_service) { |
| 116 return new SpdySessionDependencies(test_params.protocol, proxy_service); | 94 return new SpdySessionDependencies(test_params.protocol, proxy_service); |
| 117 } | 95 } |
| (...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 201 void RunPreTestSetup() { | 179 void RunPreTestSetup() { |
| 202 if (!session_deps_.get()) | 180 if (!session_deps_.get()) |
| 203 session_deps_.reset(CreateSpdySessionDependencies(test_params_)); | 181 session_deps_.reset(CreateSpdySessionDependencies(test_params_)); |
| 204 if (!session_.get()) | 182 if (!session_.get()) |
| 205 session_ = SpdySessionDependencies::SpdyCreateSession( | 183 session_ = SpdySessionDependencies::SpdyCreateSession( |
| 206 session_deps_.get()); | 184 session_deps_.get()); |
| 207 HttpStreamFactory::set_use_alternate_protocols(false); | 185 HttpStreamFactory::set_use_alternate_protocols(false); |
| 208 HttpStreamFactory::set_force_spdy_over_ssl(false); | 186 HttpStreamFactory::set_force_spdy_over_ssl(false); |
| 209 HttpStreamFactory::set_force_spdy_always(false); | 187 HttpStreamFactory::set_force_spdy_always(false); |
| 210 | 188 |
| 211 std::vector<std::string> next_protos; | 189 std::vector<std::string> next_protos = SpdyNextProtos(); |
| 212 next_protos.push_back("http/1.1"); | |
| 213 next_protos.push_back("spdy/2"); | |
| 214 | 190 |
| 215 switch (test_params_.ssl_type) { | 191 switch (test_params_.ssl_type) { |
| 216 case SPDYNPN: | 192 case SPDYNPN: |
| 217 session_->http_server_properties()->SetAlternateProtocol( | 193 session_->http_server_properties()->SetAlternateProtocol( |
| 218 HostPortPair("www.google.com", 80), 443, | 194 HostPortPair("www.google.com", 80), 443, |
| 219 NextProtoToAlternateProtocol(test_params_.protocol)); | 195 AlternateProtocolFromNextProto(test_params_.protocol)); |
| 220 HttpStreamFactory::set_use_alternate_protocols(true); | 196 HttpStreamFactory::set_use_alternate_protocols(true); |
| 221 HttpStreamFactory::SetNextProtos(next_protos); | 197 HttpStreamFactory::SetNextProtos(next_protos); |
| 222 break; | 198 break; |
| 223 case SPDYNOSSL: | 199 case SPDYNOSSL: |
| 224 HttpStreamFactory::set_force_spdy_over_ssl(false); | 200 HttpStreamFactory::set_force_spdy_over_ssl(false); |
| 225 HttpStreamFactory::set_force_spdy_always(true); | 201 HttpStreamFactory::set_force_spdy_always(true); |
| 226 break; | 202 break; |
| 227 case SPDYSSL: | 203 case SPDYSSL: |
| 228 HttpStreamFactory::set_force_spdy_over_ssl(true); | 204 HttpStreamFactory::set_force_spdy_over_ssl(true); |
| 229 HttpStreamFactory::set_force_spdy_always(true); | 205 HttpStreamFactory::set_force_spdy_always(true); |
| (...skipping 360 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 590 EXPECT_TRUE(pool->HasSession(key)); | 566 EXPECT_TRUE(pool->HasSession(key)); |
| 591 scoped_refptr<SpdySession> spdy_session(pool->Get(key, log)); | 567 scoped_refptr<SpdySession> spdy_session(pool->Get(key, log)); |
| 592 ASSERT_TRUE(spdy_session.get() != NULL); | 568 ASSERT_TRUE(spdy_session.get() != NULL); |
| 593 EXPECT_EQ(0u, spdy_session->num_active_streams()); | 569 EXPECT_EQ(0u, spdy_session->num_active_streams()); |
| 594 EXPECT_EQ(0u, spdy_session->num_unclaimed_pushed_streams()); | 570 EXPECT_EQ(0u, spdy_session->num_unclaimed_pushed_streams()); |
| 595 } | 571 } |
| 596 | 572 |
| 597 void RunServerPushTest(OrderedSocketData* data, | 573 void RunServerPushTest(OrderedSocketData* data, |
| 598 HttpResponseInfo* response, | 574 HttpResponseInfo* response, |
| 599 HttpResponseInfo* push_response, | 575 HttpResponseInfo* push_response, |
| 600 std::string& expected) { | 576 const std::string& expected) { |
| 601 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY, | 577 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY, |
| 602 BoundNetLog(), GetParam(), NULL); | 578 BoundNetLog(), GetParam(), NULL); |
| 603 helper.RunPreTestSetup(); | 579 helper.RunPreTestSetup(); |
| 604 helper.AddData(data); | 580 helper.AddData(data); |
| 605 | 581 |
| 606 HttpNetworkTransaction* trans = helper.trans(); | 582 HttpNetworkTransaction* trans = helper.trans(); |
| 607 | 583 |
| 608 // Start the transaction with basic parameters. | 584 // Start the transaction with basic parameters. |
| 609 TestCompletionCallback callback; | 585 TestCompletionCallback callback; |
| 610 int rv = trans->Start( | 586 int rv = trans->Start( |
| (...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 708 // Verify HttpNetworkTransaction constructor. | 684 // Verify HttpNetworkTransaction constructor. |
| 709 TEST_P(SpdyNetworkTransactionTest, Constructor) { | 685 TEST_P(SpdyNetworkTransactionTest, Constructor) { |
| 710 scoped_ptr<SpdySessionDependencies> session_deps( | 686 scoped_ptr<SpdySessionDependencies> session_deps( |
| 711 CreateSpdySessionDependencies(GetParam())); | 687 CreateSpdySessionDependencies(GetParam())); |
| 712 scoped_refptr<HttpNetworkSession> session( | 688 scoped_refptr<HttpNetworkSession> session( |
| 713 SpdySessionDependencies::SpdyCreateSession(session_deps.get())); | 689 SpdySessionDependencies::SpdyCreateSession(session_deps.get())); |
| 714 scoped_ptr<HttpTransaction> trans( | 690 scoped_ptr<HttpTransaction> trans( |
| 715 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); | 691 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); |
| 716 } | 692 } |
| 717 | 693 |
| 718 // TODO(akalin): Don't early-exit in the tests below for values > | |
| 719 // kProtoSPDY3. | |
| 720 | |
| 721 TEST_P(SpdyNetworkTransactionTest, Get) { | 694 TEST_P(SpdyNetworkTransactionTest, Get) { |
| 722 if (GetParam().protocol > kProtoSPDY3) | |
| 723 return; | |
| 724 | |
| 725 // Construct the request. | 695 // Construct the request. |
| 726 scoped_ptr<SpdyFrame> req( | 696 scoped_ptr<SpdyFrame> req( |
| 727 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true)); | 697 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true)); |
| 728 MockWrite writes[] = { CreateMockWrite(*req) }; | 698 MockWrite writes[] = { CreateMockWrite(*req) }; |
| 729 | 699 |
| 730 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); | 700 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); |
| 731 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true)); | 701 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true)); |
| 732 MockRead reads[] = { | 702 MockRead reads[] = { |
| 733 CreateMockRead(*resp), | 703 CreateMockRead(*resp), |
| 734 CreateMockRead(*body), | 704 CreateMockRead(*body), |
| 735 MockRead(ASYNC, 0, 0) // EOF | 705 MockRead(ASYNC, 0, 0) // EOF |
| 736 }; | 706 }; |
| 737 | 707 |
| 738 DelayedSocketData data(1, reads, arraysize(reads), | 708 DelayedSocketData data(1, reads, arraysize(reads), |
| 739 writes, arraysize(writes)); | 709 writes, arraysize(writes)); |
| 740 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY, | 710 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY, |
| 741 BoundNetLog(), GetParam(), NULL); | 711 BoundNetLog(), GetParam(), NULL); |
| 742 helper.RunToCompletion(&data); | 712 helper.RunToCompletion(&data); |
| 743 TransactionHelperResult out = helper.output(); | 713 TransactionHelperResult out = helper.output(); |
| 744 EXPECT_EQ(OK, out.rv); | 714 EXPECT_EQ(OK, out.rv); |
| 745 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line); | 715 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line); |
| 746 EXPECT_EQ("hello!", out.response_data); | 716 EXPECT_EQ("hello!", out.response_data); |
| 747 } | 717 } |
| 748 | 718 |
| 749 TEST_P(SpdyNetworkTransactionTest, GetAtEachPriority) { | 719 TEST_P(SpdyNetworkTransactionTest, GetAtEachPriority) { |
| 750 if (GetParam().protocol > kProtoSPDY3) | |
| 751 return; | |
| 752 | |
| 753 for (RequestPriority p = MINIMUM_PRIORITY; p < NUM_PRIORITIES; | 720 for (RequestPriority p = MINIMUM_PRIORITY; p < NUM_PRIORITIES; |
| 754 p = RequestPriority(p + 1)) { | 721 p = RequestPriority(p + 1)) { |
| 755 // Construct the request. | 722 // Construct the request. |
| 756 scoped_ptr<SpdyFrame> req( | 723 scoped_ptr<SpdyFrame> req( |
| 757 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, p, true)); | 724 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, p, true)); |
| 758 MockWrite writes[] = { CreateMockWrite(*req) }; | 725 MockWrite writes[] = { CreateMockWrite(*req) }; |
| 759 | 726 |
| 760 SpdyPriority spdy_prio = 0; | 727 SpdyPriority spdy_prio = 0; |
| 761 EXPECT_TRUE(GetSpdyPriority(spdy_util_.spdy_version(), *req, &spdy_prio)); | 728 EXPECT_TRUE(GetSpdyPriority(spdy_util_.spdy_version(), *req, &spdy_prio)); |
| 762 // this repeats the RequestPriority-->SpdyPriority mapping from | 729 // this repeats the RequestPriority-->SpdyPriority mapping from |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 828 // streams work properly. | 795 // streams work properly. |
| 829 | 796 |
| 830 // This can't use the TransactionHelper method, since it only | 797 // This can't use the TransactionHelper method, since it only |
| 831 // handles a single transaction, and finishes them as soon | 798 // handles a single transaction, and finishes them as soon |
| 832 // as it launches them. | 799 // as it launches them. |
| 833 | 800 |
| 834 // TODO(gavinp): create a working generalized TransactionHelper that | 801 // TODO(gavinp): create a working generalized TransactionHelper that |
| 835 // can allow multiple streams in flight. | 802 // can allow multiple streams in flight. |
| 836 | 803 |
| 837 TEST_P(SpdyNetworkTransactionTest, ThreeGets) { | 804 TEST_P(SpdyNetworkTransactionTest, ThreeGets) { |
| 838 if (GetParam().protocol > kProtoSPDY3) | |
| 839 return; | |
| 840 | |
| 841 scoped_ptr<SpdyFrame> req( | 805 scoped_ptr<SpdyFrame> req( |
| 842 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true)); | 806 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true)); |
| 843 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); | 807 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); |
| 844 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, false)); | 808 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, false)); |
| 845 scoped_ptr<SpdyFrame> fbody(spdy_util_.ConstructSpdyBodyFrame(1, true)); | 809 scoped_ptr<SpdyFrame> fbody(spdy_util_.ConstructSpdyBodyFrame(1, true)); |
| 846 | 810 |
| 847 scoped_ptr<SpdyFrame> req2( | 811 scoped_ptr<SpdyFrame> req2( |
| 848 spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, LOWEST, true)); | 812 spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, LOWEST, true)); |
| 849 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3)); | 813 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3)); |
| 850 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(3, false)); | 814 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(3, false)); |
| (...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 927 out.rv = ReadTransaction(trans1.get(), &out.response_data); | 891 out.rv = ReadTransaction(trans1.get(), &out.response_data); |
| 928 helper.VerifyDataConsumed(); | 892 helper.VerifyDataConsumed(); |
| 929 EXPECT_EQ(OK, out.rv); | 893 EXPECT_EQ(OK, out.rv); |
| 930 | 894 |
| 931 EXPECT_EQ(OK, out.rv); | 895 EXPECT_EQ(OK, out.rv); |
| 932 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line); | 896 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line); |
| 933 EXPECT_EQ("hello!hello!", out.response_data); | 897 EXPECT_EQ("hello!hello!", out.response_data); |
| 934 } | 898 } |
| 935 | 899 |
| 936 TEST_P(SpdyNetworkTransactionTest, TwoGetsLateBinding) { | 900 TEST_P(SpdyNetworkTransactionTest, TwoGetsLateBinding) { |
| 937 if (GetParam().protocol > kProtoSPDY3) | |
| 938 return; | |
| 939 | |
| 940 scoped_ptr<SpdyFrame> req( | 901 scoped_ptr<SpdyFrame> req( |
| 941 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true)); | 902 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true)); |
| 942 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); | 903 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); |
| 943 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, false)); | 904 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, false)); |
| 944 scoped_ptr<SpdyFrame> fbody(spdy_util_.ConstructSpdyBodyFrame(1, true)); | 905 scoped_ptr<SpdyFrame> fbody(spdy_util_.ConstructSpdyBodyFrame(1, true)); |
| 945 | 906 |
| 946 scoped_ptr<SpdyFrame> req2( | 907 scoped_ptr<SpdyFrame> req2( |
| 947 spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, LOWEST, true)); | 908 spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, LOWEST, true)); |
| 948 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3)); | 909 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3)); |
| 949 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(3, false)); | 910 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(3, false)); |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1017 out.response_info = *response2; | 978 out.response_info = *response2; |
| 1018 out.rv = ReadTransaction(trans2.get(), &out.response_data); | 979 out.rv = ReadTransaction(trans2.get(), &out.response_data); |
| 1019 EXPECT_EQ(OK, out.rv); | 980 EXPECT_EQ(OK, out.rv); |
| 1020 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line); | 981 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line); |
| 1021 EXPECT_EQ("hello!hello!", out.response_data); | 982 EXPECT_EQ("hello!hello!", out.response_data); |
| 1022 | 983 |
| 1023 helper.VerifyDataConsumed(); | 984 helper.VerifyDataConsumed(); |
| 1024 } | 985 } |
| 1025 | 986 |
| 1026 TEST_P(SpdyNetworkTransactionTest, TwoGetsLateBindingFromPreconnect) { | 987 TEST_P(SpdyNetworkTransactionTest, TwoGetsLateBindingFromPreconnect) { |
| 1027 if (GetParam().protocol > kProtoSPDY3) | |
| 1028 return; | |
| 1029 | |
| 1030 scoped_ptr<SpdyFrame> req( | 988 scoped_ptr<SpdyFrame> req( |
| 1031 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true)); | 989 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true)); |
| 1032 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); | 990 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); |
| 1033 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, false)); | 991 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, false)); |
| 1034 scoped_ptr<SpdyFrame> fbody(spdy_util_.ConstructSpdyBodyFrame(1, true)); | 992 scoped_ptr<SpdyFrame> fbody(spdy_util_.ConstructSpdyBodyFrame(1, true)); |
| 1035 | 993 |
| 1036 scoped_ptr<SpdyFrame> req2( | 994 scoped_ptr<SpdyFrame> req2( |
| 1037 spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, LOWEST, true)); | 995 spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, LOWEST, true)); |
| 1038 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3)); | 996 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3)); |
| 1039 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(3, false)); | 997 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(3, false)); |
| (...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1126 | 1084 |
| 1127 helper.VerifyDataConsumed(); | 1085 helper.VerifyDataConsumed(); |
| 1128 } | 1086 } |
| 1129 | 1087 |
| 1130 // Similar to ThreeGets above, however this test adds a SETTINGS | 1088 // Similar to ThreeGets above, however this test adds a SETTINGS |
| 1131 // frame. The SETTINGS frame is read during the IO loop waiting on | 1089 // frame. The SETTINGS frame is read during the IO loop waiting on |
| 1132 // the first transaction completion, and sets a maximum concurrent | 1090 // the first transaction completion, and sets a maximum concurrent |
| 1133 // stream limit of 1. This means that our IO loop exists after the | 1091 // stream limit of 1. This means that our IO loop exists after the |
| 1134 // second transaction completes, so we can assert on read_index(). | 1092 // second transaction completes, so we can assert on read_index(). |
| 1135 TEST_P(SpdyNetworkTransactionTest, ThreeGetsWithMaxConcurrent) { | 1093 TEST_P(SpdyNetworkTransactionTest, ThreeGetsWithMaxConcurrent) { |
| 1136 if (GetParam().protocol > kProtoSPDY3) | |
| 1137 return; | |
| 1138 | |
| 1139 // Construct the request. | 1094 // Construct the request. |
| 1140 scoped_ptr<SpdyFrame> req( | 1095 scoped_ptr<SpdyFrame> req( |
| 1141 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true)); | 1096 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true)); |
| 1142 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); | 1097 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); |
| 1143 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, false)); | 1098 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, false)); |
| 1144 scoped_ptr<SpdyFrame> fbody(spdy_util_.ConstructSpdyBodyFrame(1, true)); | 1099 scoped_ptr<SpdyFrame> fbody(spdy_util_.ConstructSpdyBodyFrame(1, true)); |
| 1145 | 1100 |
| 1146 scoped_ptr<SpdyFrame> req2( | 1101 scoped_ptr<SpdyFrame> req2( |
| 1147 spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, LOWEST, true)); | 1102 spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, LOWEST, true)); |
| 1148 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3)); | 1103 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3)); |
| (...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1262 } | 1217 } |
| 1263 EXPECT_EQ(OK, out.rv); | 1218 EXPECT_EQ(OK, out.rv); |
| 1264 } | 1219 } |
| 1265 | 1220 |
| 1266 // Similar to ThreeGetsWithMaxConcurrent above, however this test adds | 1221 // Similar to ThreeGetsWithMaxConcurrent above, however this test adds |
| 1267 // a fourth transaction. The third and fourth transactions have | 1222 // a fourth transaction. The third and fourth transactions have |
| 1268 // different data ("hello!" vs "hello!hello!") and because of the | 1223 // different data ("hello!" vs "hello!hello!") and because of the |
| 1269 // user specified priority, we expect to see them inverted in | 1224 // user specified priority, we expect to see them inverted in |
| 1270 // the response from the server. | 1225 // the response from the server. |
| 1271 TEST_P(SpdyNetworkTransactionTest, FourGetsWithMaxConcurrentPriority) { | 1226 TEST_P(SpdyNetworkTransactionTest, FourGetsWithMaxConcurrentPriority) { |
| 1272 if (GetParam().protocol > kProtoSPDY3) | |
| 1273 return; | |
| 1274 | |
| 1275 // Construct the request. | 1227 // Construct the request. |
| 1276 scoped_ptr<SpdyFrame> req( | 1228 scoped_ptr<SpdyFrame> req( |
| 1277 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true)); | 1229 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true)); |
| 1278 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); | 1230 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); |
| 1279 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, false)); | 1231 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, false)); |
| 1280 scoped_ptr<SpdyFrame> fbody(spdy_util_.ConstructSpdyBodyFrame(1, true)); | 1232 scoped_ptr<SpdyFrame> fbody(spdy_util_.ConstructSpdyBodyFrame(1, true)); |
| 1281 | 1233 |
| 1282 scoped_ptr<SpdyFrame> req2( | 1234 scoped_ptr<SpdyFrame> req2( |
| 1283 spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, LOWEST, true)); | 1235 spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, LOWEST, true)); |
| 1284 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3)); | 1236 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3)); |
| (...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1418 EXPECT_EQ("hello!", out.response_data); | 1370 EXPECT_EQ("hello!", out.response_data); |
| 1419 helper.VerifyDataConsumed(); | 1371 helper.VerifyDataConsumed(); |
| 1420 EXPECT_EQ(OK, out.rv); | 1372 EXPECT_EQ(OK, out.rv); |
| 1421 } | 1373 } |
| 1422 | 1374 |
| 1423 // Similar to ThreeGetsMaxConcurrrent above, however, this test | 1375 // Similar to ThreeGetsMaxConcurrrent above, however, this test |
| 1424 // deletes a session in the middle of the transaction to insure | 1376 // deletes a session in the middle of the transaction to insure |
| 1425 // that we properly remove pendingcreatestream objects from | 1377 // that we properly remove pendingcreatestream objects from |
| 1426 // the spdy_session | 1378 // the spdy_session |
| 1427 TEST_P(SpdyNetworkTransactionTest, ThreeGetsWithMaxConcurrentDelete) { | 1379 TEST_P(SpdyNetworkTransactionTest, ThreeGetsWithMaxConcurrentDelete) { |
| 1428 if (GetParam().protocol > kProtoSPDY3) | |
| 1429 return; | |
| 1430 | |
| 1431 // Construct the request. | 1380 // Construct the request. |
| 1432 scoped_ptr<SpdyFrame> req( | 1381 scoped_ptr<SpdyFrame> req( |
| 1433 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true)); | 1382 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true)); |
| 1434 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); | 1383 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); |
| 1435 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, false)); | 1384 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, false)); |
| 1436 scoped_ptr<SpdyFrame> fbody(spdy_util_.ConstructSpdyBodyFrame(1, true)); | 1385 scoped_ptr<SpdyFrame> fbody(spdy_util_.ConstructSpdyBodyFrame(1, true)); |
| 1437 | 1386 |
| 1438 scoped_ptr<SpdyFrame> req2( | 1387 scoped_ptr<SpdyFrame> req2( |
| 1439 spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, LOWEST, true)); | 1388 spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, LOWEST, true)); |
| 1440 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3)); | 1389 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3)); |
| (...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1557 HttpNetworkTransaction* transaction_; | 1506 HttpNetworkTransaction* transaction_; |
| 1558 CompletionCallback callback_; | 1507 CompletionCallback callback_; |
| 1559 }; | 1508 }; |
| 1560 | 1509 |
| 1561 } // namespace | 1510 } // namespace |
| 1562 | 1511 |
| 1563 // Similar to ThreeGetsMaxConcurrrentDelete above, however, this test | 1512 // Similar to ThreeGetsMaxConcurrrentDelete above, however, this test |
| 1564 // closes the socket while we have a pending transaction waiting for | 1513 // closes the socket while we have a pending transaction waiting for |
| 1565 // a pending stream creation. http://crbug.com/52901 | 1514 // a pending stream creation. http://crbug.com/52901 |
| 1566 TEST_P(SpdyNetworkTransactionTest, ThreeGetsWithMaxConcurrentSocketClose) { | 1515 TEST_P(SpdyNetworkTransactionTest, ThreeGetsWithMaxConcurrentSocketClose) { |
| 1567 if (GetParam().protocol > kProtoSPDY3) | |
| 1568 return; | |
| 1569 | |
| 1570 // Construct the request. | 1516 // Construct the request. |
| 1571 scoped_ptr<SpdyFrame> req( | 1517 scoped_ptr<SpdyFrame> req( |
| 1572 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true)); | 1518 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true)); |
| 1573 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); | 1519 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); |
| 1574 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, false)); | 1520 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, false)); |
| 1575 scoped_ptr<SpdyFrame> fin_body(spdy_util_.ConstructSpdyBodyFrame(1, true)); | 1521 scoped_ptr<SpdyFrame> fin_body(spdy_util_.ConstructSpdyBodyFrame(1, true)); |
| 1576 | 1522 |
| 1577 scoped_ptr<SpdyFrame> req2( | 1523 scoped_ptr<SpdyFrame> req2( |
| 1578 spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, LOWEST, true)); | 1524 spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, LOWEST, true)); |
| 1579 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3)); | 1525 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3)); |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1653 out.status_line = response2->headers->GetStatusLine(); | 1599 out.status_line = response2->headers->GetStatusLine(); |
| 1654 out.response_info = *response2; | 1600 out.response_info = *response2; |
| 1655 out.rv = ReadTransaction(&trans2, &out.response_data); | 1601 out.rv = ReadTransaction(&trans2, &out.response_data); |
| 1656 EXPECT_EQ(ERR_CONNECTION_RESET, out.rv); | 1602 EXPECT_EQ(ERR_CONNECTION_RESET, out.rv); |
| 1657 | 1603 |
| 1658 helper.VerifyDataConsumed(); | 1604 helper.VerifyDataConsumed(); |
| 1659 } | 1605 } |
| 1660 | 1606 |
| 1661 // Test that a simple PUT request works. | 1607 // Test that a simple PUT request works. |
| 1662 TEST_P(SpdyNetworkTransactionTest, Put) { | 1608 TEST_P(SpdyNetworkTransactionTest, Put) { |
| 1663 if (GetParam().protocol > kProtoSPDY3) | |
| 1664 return; | |
| 1665 | |
| 1666 // Setup the request | 1609 // Setup the request |
| 1667 HttpRequestInfo request; | 1610 HttpRequestInfo request; |
| 1668 request.method = "PUT"; | 1611 request.method = "PUT"; |
| 1669 request.url = GURL("http://www.google.com/"); | 1612 request.url = GURL("http://www.google.com/"); |
| 1670 | 1613 |
| 1671 const SpdyHeaderInfo kSynStartHeader = { | 1614 const SpdyHeaderInfo kSynStartHeader = { |
| 1672 SYN_STREAM, // Kind = Syn | 1615 SYN_STREAM, // Kind = Syn |
| 1673 1, // Stream ID | 1616 1, // Stream ID |
| 1674 0, // Associated stream ID | 1617 0, // Associated stream ID |
| 1675 ConvertRequestPriorityToSpdyPriority( | 1618 ConvertRequestPriorityToSpdyPriority( |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1723 BoundNetLog(), GetParam(), NULL); | 1666 BoundNetLog(), GetParam(), NULL); |
| 1724 helper.RunToCompletion(&data); | 1667 helper.RunToCompletion(&data); |
| 1725 TransactionHelperResult out = helper.output(); | 1668 TransactionHelperResult out = helper.output(); |
| 1726 | 1669 |
| 1727 EXPECT_EQ(OK, out.rv); | 1670 EXPECT_EQ(OK, out.rv); |
| 1728 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line); | 1671 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line); |
| 1729 } | 1672 } |
| 1730 | 1673 |
| 1731 // Test that a simple HEAD request works. | 1674 // Test that a simple HEAD request works. |
| 1732 TEST_P(SpdyNetworkTransactionTest, Head) { | 1675 TEST_P(SpdyNetworkTransactionTest, Head) { |
| 1733 if (GetParam().protocol > kProtoSPDY3) | |
| 1734 return; | |
| 1735 | |
| 1736 // Setup the request | 1676 // Setup the request |
| 1737 HttpRequestInfo request; | 1677 HttpRequestInfo request; |
| 1738 request.method = "HEAD"; | 1678 request.method = "HEAD"; |
| 1739 request.url = GURL("http://www.google.com/"); | 1679 request.url = GURL("http://www.google.com/"); |
| 1740 | 1680 |
| 1741 const SpdyHeaderInfo kSynStartHeader = { | 1681 const SpdyHeaderInfo kSynStartHeader = { |
| 1742 SYN_STREAM, // Kind = Syn | 1682 SYN_STREAM, // Kind = Syn |
| 1743 1, // Stream ID | 1683 1, // Stream ID |
| 1744 0, // Associated stream ID | 1684 0, // Associated stream ID |
| 1745 ConvertRequestPriorityToSpdyPriority( | 1685 ConvertRequestPriorityToSpdyPriority( |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1794 BoundNetLog(), GetParam(), NULL); | 1734 BoundNetLog(), GetParam(), NULL); |
| 1795 helper.RunToCompletion(&data); | 1735 helper.RunToCompletion(&data); |
| 1796 TransactionHelperResult out = helper.output(); | 1736 TransactionHelperResult out = helper.output(); |
| 1797 | 1737 |
| 1798 EXPECT_EQ(OK, out.rv); | 1738 EXPECT_EQ(OK, out.rv); |
| 1799 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line); | 1739 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line); |
| 1800 } | 1740 } |
| 1801 | 1741 |
| 1802 // Test that a simple POST works. | 1742 // Test that a simple POST works. |
| 1803 TEST_P(SpdyNetworkTransactionTest, Post) { | 1743 TEST_P(SpdyNetworkTransactionTest, Post) { |
| 1804 if (GetParam().protocol > kProtoSPDY3) | |
| 1805 return; | |
| 1806 | |
| 1807 scoped_ptr<SpdyFrame> req( | 1744 scoped_ptr<SpdyFrame> req( |
| 1808 spdy_util_.ConstructSpdyPost( | 1745 spdy_util_.ConstructSpdyPost( |
| 1809 kRequestUrl, 1, kUploadDataSize, LOWEST, NULL, 0)); | 1746 kRequestUrl, 1, kUploadDataSize, LOWEST, NULL, 0)); |
| 1810 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true)); | 1747 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true)); |
| 1811 MockWrite writes[] = { | 1748 MockWrite writes[] = { |
| 1812 CreateMockWrite(*req), | 1749 CreateMockWrite(*req), |
| 1813 CreateMockWrite(*body), // POST upload frame | 1750 CreateMockWrite(*body), // POST upload frame |
| 1814 }; | 1751 }; |
| 1815 | 1752 |
| 1816 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyPostSynReply(NULL, 0)); | 1753 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyPostSynReply(NULL, 0)); |
| 1817 MockRead reads[] = { | 1754 MockRead reads[] = { |
| 1818 CreateMockRead(*resp), | 1755 CreateMockRead(*resp), |
| 1819 CreateMockRead(*body), | 1756 CreateMockRead(*body), |
| 1820 MockRead(ASYNC, 0, 0) // EOF | 1757 MockRead(ASYNC, 0, 0) // EOF |
| 1821 }; | 1758 }; |
| 1822 | 1759 |
| 1823 DelayedSocketData data(2, reads, arraysize(reads), | 1760 DelayedSocketData data(2, reads, arraysize(reads), |
| 1824 writes, arraysize(writes)); | 1761 writes, arraysize(writes)); |
| 1825 NormalSpdyTransactionHelper helper(CreatePostRequest(), DEFAULT_PRIORITY, | 1762 NormalSpdyTransactionHelper helper(CreatePostRequest(), DEFAULT_PRIORITY, |
| 1826 BoundNetLog(), GetParam(), NULL); | 1763 BoundNetLog(), GetParam(), NULL); |
| 1827 helper.RunToCompletion(&data); | 1764 helper.RunToCompletion(&data); |
| 1828 TransactionHelperResult out = helper.output(); | 1765 TransactionHelperResult out = helper.output(); |
| 1829 EXPECT_EQ(OK, out.rv); | 1766 EXPECT_EQ(OK, out.rv); |
| 1830 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line); | 1767 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line); |
| 1831 EXPECT_EQ("hello!", out.response_data); | 1768 EXPECT_EQ("hello!", out.response_data); |
| 1832 } | 1769 } |
| 1833 | 1770 |
| 1834 // Test that a POST with a file works. | 1771 // Test that a POST with a file works. |
| 1835 TEST_P(SpdyNetworkTransactionTest, FilePost) { | 1772 TEST_P(SpdyNetworkTransactionTest, FilePost) { |
| 1836 if (GetParam().protocol > kProtoSPDY3) | |
| 1837 return; | |
| 1838 | |
| 1839 scoped_ptr<SpdyFrame> req( | 1773 scoped_ptr<SpdyFrame> req( |
| 1840 spdy_util_.ConstructSpdyPost( | 1774 spdy_util_.ConstructSpdyPost( |
| 1841 kRequestUrl, 1, kUploadDataSize, LOWEST, NULL, 0)); | 1775 kRequestUrl, 1, kUploadDataSize, LOWEST, NULL, 0)); |
| 1842 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true)); | 1776 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true)); |
| 1843 MockWrite writes[] = { | 1777 MockWrite writes[] = { |
| 1844 CreateMockWrite(*req), | 1778 CreateMockWrite(*req), |
| 1845 CreateMockWrite(*body), // POST upload frame | 1779 CreateMockWrite(*body), // POST upload frame |
| 1846 }; | 1780 }; |
| 1847 | 1781 |
| 1848 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyPostSynReply(NULL, 0)); | 1782 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyPostSynReply(NULL, 0)); |
| 1849 MockRead reads[] = { | 1783 MockRead reads[] = { |
| 1850 CreateMockRead(*resp), | 1784 CreateMockRead(*resp), |
| 1851 CreateMockRead(*body), | 1785 CreateMockRead(*body), |
| 1852 MockRead(ASYNC, 0, 0) // EOF | 1786 MockRead(ASYNC, 0, 0) // EOF |
| 1853 }; | 1787 }; |
| 1854 | 1788 |
| 1855 DelayedSocketData data(2, reads, arraysize(reads), | 1789 DelayedSocketData data(2, reads, arraysize(reads), |
| 1856 writes, arraysize(writes)); | 1790 writes, arraysize(writes)); |
| 1857 NormalSpdyTransactionHelper helper(CreateFilePostRequest(), DEFAULT_PRIORITY, | 1791 NormalSpdyTransactionHelper helper(CreateFilePostRequest(), DEFAULT_PRIORITY, |
| 1858 BoundNetLog(), GetParam(), NULL); | 1792 BoundNetLog(), GetParam(), NULL); |
| 1859 helper.RunToCompletion(&data); | 1793 helper.RunToCompletion(&data); |
| 1860 TransactionHelperResult out = helper.output(); | 1794 TransactionHelperResult out = helper.output(); |
| 1861 EXPECT_EQ(OK, out.rv); | 1795 EXPECT_EQ(OK, out.rv); |
| 1862 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line); | 1796 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line); |
| 1863 EXPECT_EQ("hello!", out.response_data); | 1797 EXPECT_EQ("hello!", out.response_data); |
| 1864 } | 1798 } |
| 1865 | 1799 |
| 1866 // Test that a complex POST works. | 1800 // Test that a complex POST works. |
| 1867 TEST_P(SpdyNetworkTransactionTest, ComplexPost) { | 1801 TEST_P(SpdyNetworkTransactionTest, ComplexPost) { |
| 1868 if (GetParam().protocol > kProtoSPDY3) | |
| 1869 return; | |
| 1870 | |
| 1871 scoped_ptr<SpdyFrame> req( | 1802 scoped_ptr<SpdyFrame> req( |
| 1872 spdy_util_.ConstructSpdyPost( | 1803 spdy_util_.ConstructSpdyPost( |
| 1873 kRequestUrl, 1, kUploadDataSize, LOWEST, NULL, 0)); | 1804 kRequestUrl, 1, kUploadDataSize, LOWEST, NULL, 0)); |
| 1874 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true)); | 1805 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true)); |
| 1875 MockWrite writes[] = { | 1806 MockWrite writes[] = { |
| 1876 CreateMockWrite(*req), | 1807 CreateMockWrite(*req), |
| 1877 CreateMockWrite(*body), // POST upload frame | 1808 CreateMockWrite(*body), // POST upload frame |
| 1878 }; | 1809 }; |
| 1879 | 1810 |
| 1880 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyPostSynReply(NULL, 0)); | 1811 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyPostSynReply(NULL, 0)); |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 1891 BoundNetLog(), GetParam(), NULL); | 1822 BoundNetLog(), GetParam(), NULL); |
| 1892 helper.RunToCompletion(&data); | 1823 helper.RunToCompletion(&data); |
| 1893 TransactionHelperResult out = helper.output(); | 1824 TransactionHelperResult out = helper.output(); |
| 1894 EXPECT_EQ(OK, out.rv); | 1825 EXPECT_EQ(OK, out.rv); |
| 1895 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line); | 1826 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line); |
| 1896 EXPECT_EQ("hello!", out.response_data); | 1827 EXPECT_EQ("hello!", out.response_data); |
| 1897 } | 1828 } |
| 1898 | 1829 |
| 1899 // Test that a chunked POST works. | 1830 // Test that a chunked POST works. |
| 1900 TEST_P(SpdyNetworkTransactionTest, ChunkedPost) { | 1831 TEST_P(SpdyNetworkTransactionTest, ChunkedPost) { |
| 1901 if (GetParam().protocol > kProtoSPDY3) | |
| 1902 return; | |
| 1903 | |
| 1904 scoped_ptr<SpdyFrame> req(spdy_util_.ConstructChunkedSpdyPost(NULL, 0)); | 1832 scoped_ptr<SpdyFrame> req(spdy_util_.ConstructChunkedSpdyPost(NULL, 0)); |
| 1905 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true)); | 1833 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true)); |
| 1906 MockWrite writes[] = { | 1834 MockWrite writes[] = { |
| 1907 CreateMockWrite(*req), | 1835 CreateMockWrite(*req), |
| 1908 CreateMockWrite(*body), | 1836 CreateMockWrite(*body), |
| 1909 }; | 1837 }; |
| 1910 | 1838 |
| 1911 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyPostSynReply(NULL, 0)); | 1839 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyPostSynReply(NULL, 0)); |
| 1912 MockRead reads[] = { | 1840 MockRead reads[] = { |
| 1913 CreateMockRead(*resp), | 1841 CreateMockRead(*resp), |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 1930 | 1858 |
| 1931 helper.RunToCompletion(&data); | 1859 helper.RunToCompletion(&data); |
| 1932 TransactionHelperResult out = helper.output(); | 1860 TransactionHelperResult out = helper.output(); |
| 1933 EXPECT_EQ(OK, out.rv); | 1861 EXPECT_EQ(OK, out.rv); |
| 1934 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line); | 1862 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line); |
| 1935 EXPECT_EQ(kUploadData, out.response_data); | 1863 EXPECT_EQ(kUploadData, out.response_data); |
| 1936 } | 1864 } |
| 1937 | 1865 |
| 1938 // Test that a chunked POST works with chunks appended after transaction starts. | 1866 // Test that a chunked POST works with chunks appended after transaction starts. |
| 1939 TEST_P(SpdyNetworkTransactionTest, DelayedChunkedPost) { | 1867 TEST_P(SpdyNetworkTransactionTest, DelayedChunkedPost) { |
| 1940 if (GetParam().protocol > kProtoSPDY3) | |
| 1941 return; | |
| 1942 | |
| 1943 scoped_ptr<SpdyFrame> req(spdy_util_.ConstructChunkedSpdyPost(NULL, 0)); | 1868 scoped_ptr<SpdyFrame> req(spdy_util_.ConstructChunkedSpdyPost(NULL, 0)); |
| 1944 scoped_ptr<SpdyFrame> chunk1(spdy_util_.ConstructSpdyBodyFrame(1, false)); | 1869 scoped_ptr<SpdyFrame> chunk1(spdy_util_.ConstructSpdyBodyFrame(1, false)); |
| 1945 scoped_ptr<SpdyFrame> chunk2(spdy_util_.ConstructSpdyBodyFrame(1, false)); | 1870 scoped_ptr<SpdyFrame> chunk2(spdy_util_.ConstructSpdyBodyFrame(1, false)); |
| 1946 scoped_ptr<SpdyFrame> chunk3(spdy_util_.ConstructSpdyBodyFrame(1, true)); | 1871 scoped_ptr<SpdyFrame> chunk3(spdy_util_.ConstructSpdyBodyFrame(1, true)); |
| 1947 MockWrite writes[] = { | 1872 MockWrite writes[] = { |
| 1948 CreateMockWrite(*req), | 1873 CreateMockWrite(*req), |
| 1949 CreateMockWrite(*chunk1), | 1874 CreateMockWrite(*chunk1), |
| 1950 CreateMockWrite(*chunk2), | 1875 CreateMockWrite(*chunk2), |
| 1951 CreateMockWrite(*chunk3), | 1876 CreateMockWrite(*chunk3), |
| 1952 }; | 1877 }; |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1989 expected_response += kUploadData; | 1914 expected_response += kUploadData; |
| 1990 | 1915 |
| 1991 TransactionHelperResult out = helper.output(); | 1916 TransactionHelperResult out = helper.output(); |
| 1992 EXPECT_EQ(OK, out.rv); | 1917 EXPECT_EQ(OK, out.rv); |
| 1993 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line); | 1918 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line); |
| 1994 EXPECT_EQ(expected_response, out.response_data); | 1919 EXPECT_EQ(expected_response, out.response_data); |
| 1995 } | 1920 } |
| 1996 | 1921 |
| 1997 // Test that a POST without any post data works. | 1922 // Test that a POST without any post data works. |
| 1998 TEST_P(SpdyNetworkTransactionTest, NullPost) { | 1923 TEST_P(SpdyNetworkTransactionTest, NullPost) { |
| 1999 if (GetParam().protocol > kProtoSPDY3) | |
| 2000 return; | |
| 2001 | |
| 2002 // Setup the request | 1924 // Setup the request |
| 2003 HttpRequestInfo request; | 1925 HttpRequestInfo request; |
| 2004 request.method = "POST"; | 1926 request.method = "POST"; |
| 2005 request.url = GURL(kRequestUrl); | 1927 request.url = GURL(kRequestUrl); |
| 2006 // Create an empty UploadData. | 1928 // Create an empty UploadData. |
| 2007 request.upload_data_stream = NULL; | 1929 request.upload_data_stream = NULL; |
| 2008 | 1930 |
| 2009 // When request.upload_data_stream is NULL for post, content-length is | 1931 // When request.upload_data_stream is NULL for post, content-length is |
| 2010 // expected to be 0. | 1932 // expected to be 0. |
| 2011 scoped_ptr<SpdyFrame> req( | 1933 scoped_ptr<SpdyFrame> req( |
| (...skipping 19 matching lines...) Expand all Loading... | |
| 2031 BoundNetLog(), GetParam(), NULL); | 1953 BoundNetLog(), GetParam(), NULL); |
| 2032 helper.RunToCompletion(&data); | 1954 helper.RunToCompletion(&data); |
| 2033 TransactionHelperResult out = helper.output(); | 1955 TransactionHelperResult out = helper.output(); |
| 2034 EXPECT_EQ(OK, out.rv); | 1956 EXPECT_EQ(OK, out.rv); |
| 2035 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line); | 1957 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line); |
| 2036 EXPECT_EQ("hello!", out.response_data); | 1958 EXPECT_EQ("hello!", out.response_data); |
| 2037 } | 1959 } |
| 2038 | 1960 |
| 2039 // Test that a simple POST works. | 1961 // Test that a simple POST works. |
| 2040 TEST_P(SpdyNetworkTransactionTest, EmptyPost) { | 1962 TEST_P(SpdyNetworkTransactionTest, EmptyPost) { |
| 2041 if (GetParam().protocol > kProtoSPDY3) | |
| 2042 return; | |
| 2043 | |
| 2044 // Create an empty UploadDataStream. | 1963 // Create an empty UploadDataStream. |
| 2045 ScopedVector<UploadElementReader> element_readers; | 1964 ScopedVector<UploadElementReader> element_readers; |
| 2046 UploadDataStream stream(&element_readers, 0); | 1965 UploadDataStream stream(&element_readers, 0); |
| 2047 | 1966 |
| 2048 // Setup the request | 1967 // Setup the request |
| 2049 HttpRequestInfo request; | 1968 HttpRequestInfo request; |
| 2050 request.method = "POST"; | 1969 request.method = "POST"; |
| 2051 request.url = GURL(kRequestUrl); | 1970 request.url = GURL(kRequestUrl); |
| 2052 request.upload_data_stream = &stream; | 1971 request.upload_data_stream = &stream; |
| 2053 | 1972 |
| (...skipping 21 matching lines...) Expand all Loading... | |
| 2075 BoundNetLog(), GetParam(), NULL); | 1994 BoundNetLog(), GetParam(), NULL); |
| 2076 helper.RunToCompletion(&data); | 1995 helper.RunToCompletion(&data); |
| 2077 TransactionHelperResult out = helper.output(); | 1996 TransactionHelperResult out = helper.output(); |
| 2078 EXPECT_EQ(OK, out.rv); | 1997 EXPECT_EQ(OK, out.rv); |
| 2079 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line); | 1998 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line); |
| 2080 EXPECT_EQ("hello!", out.response_data); | 1999 EXPECT_EQ("hello!", out.response_data); |
| 2081 } | 2000 } |
| 2082 | 2001 |
| 2083 // While we're doing a post, the server sends back a SYN_REPLY. | 2002 // While we're doing a post, the server sends back a SYN_REPLY. |
| 2084 TEST_P(SpdyNetworkTransactionTest, PostWithEarlySynReply) { | 2003 TEST_P(SpdyNetworkTransactionTest, PostWithEarlySynReply) { |
| 2085 if (GetParam().protocol > kProtoSPDY3) | |
| 2086 return; | |
| 2087 | |
| 2088 static const char upload[] = { "hello!" }; | 2004 static const char upload[] = { "hello!" }; |
| 2089 ScopedVector<UploadElementReader> element_readers; | 2005 ScopedVector<UploadElementReader> element_readers; |
| 2090 element_readers.push_back( | 2006 element_readers.push_back( |
| 2091 new UploadBytesElementReader(upload, sizeof(upload))); | 2007 new UploadBytesElementReader(upload, sizeof(upload))); |
| 2092 UploadDataStream stream(&element_readers, 0); | 2008 UploadDataStream stream(&element_readers, 0); |
| 2093 | 2009 |
| 2094 // Setup the request | 2010 // Setup the request |
| 2095 HttpRequestInfo request; | 2011 HttpRequestInfo request; |
| 2096 request.method = "POST"; | 2012 request.method = "POST"; |
| 2097 request.url = GURL(kRequestUrl); | 2013 request.url = GURL(kRequestUrl); |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2131 data.RunFor(2); | 2047 data.RunFor(2); |
| 2132 rv = callback.WaitForResult(); | 2048 rv = callback.WaitForResult(); |
| 2133 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, rv); | 2049 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, rv); |
| 2134 data.RunFor(1); | 2050 data.RunFor(1); |
| 2135 } | 2051 } |
| 2136 | 2052 |
| 2137 // The client upon cancellation tries to send a RST_STREAM frame. The mock | 2053 // The client upon cancellation tries to send a RST_STREAM frame. The mock |
| 2138 // socket causes the TCP write to return zero. This test checks that the client | 2054 // socket causes the TCP write to return zero. This test checks that the client |
| 2139 // tries to queue up the RST_STREAM frame again. | 2055 // tries to queue up the RST_STREAM frame again. |
| 2140 TEST_P(SpdyNetworkTransactionTest, SocketWriteReturnsZero) { | 2056 TEST_P(SpdyNetworkTransactionTest, SocketWriteReturnsZero) { |
| 2141 if (GetParam().protocol > kProtoSPDY3) | |
| 2142 return; | |
| 2143 | |
| 2144 scoped_ptr<SpdyFrame> req( | 2057 scoped_ptr<SpdyFrame> req( |
| 2145 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true)); | 2058 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true)); |
| 2146 scoped_ptr<SpdyFrame> rst( | 2059 scoped_ptr<SpdyFrame> rst( |
| 2147 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL)); | 2060 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL)); |
| 2148 MockWrite writes[] = { | 2061 MockWrite writes[] = { |
| 2149 CreateMockWrite(*req.get(), 0, SYNCHRONOUS), | 2062 CreateMockWrite(*req.get(), 0, SYNCHRONOUS), |
| 2150 MockWrite(SYNCHRONOUS, 0, 0, 2), | 2063 MockWrite(SYNCHRONOUS, 0, 0, 2), |
| 2151 CreateMockWrite(*rst.get(), 3, SYNCHRONOUS), | 2064 CreateMockWrite(*rst.get(), 3, SYNCHRONOUS), |
| 2152 }; | 2065 }; |
| 2153 | 2066 |
| (...skipping 21 matching lines...) Expand all Loading... | |
| 2175 data.Run(); | 2088 data.Run(); |
| 2176 helper.ResetTrans(); | 2089 helper.ResetTrans(); |
| 2177 data.SetStop(20); | 2090 data.SetStop(20); |
| 2178 data.Run(); | 2091 data.Run(); |
| 2179 | 2092 |
| 2180 helper.VerifyDataConsumed(); | 2093 helper.VerifyDataConsumed(); |
| 2181 } | 2094 } |
| 2182 | 2095 |
| 2183 // Test that the transaction doesn't crash when we don't have a reply. | 2096 // Test that the transaction doesn't crash when we don't have a reply. |
| 2184 TEST_P(SpdyNetworkTransactionTest, ResponseWithoutSynReply) { | 2097 TEST_P(SpdyNetworkTransactionTest, ResponseWithoutSynReply) { |
| 2185 if (GetParam().protocol > kProtoSPDY3) | |
| 2186 return; | |
| 2187 | |
| 2188 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true)); | 2098 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true)); |
| 2189 MockRead reads[] = { | 2099 MockRead reads[] = { |
| 2190 CreateMockRead(*body), | 2100 CreateMockRead(*body), |
| 2191 MockRead(ASYNC, 0, 0) // EOF | 2101 MockRead(ASYNC, 0, 0) // EOF |
| 2192 }; | 2102 }; |
| 2193 | 2103 |
| 2194 DelayedSocketData data(1, reads, arraysize(reads), NULL, 0); | 2104 DelayedSocketData data(1, reads, arraysize(reads), NULL, 0); |
| 2195 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY, | 2105 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY, |
| 2196 BoundNetLog(), GetParam(), NULL); | 2106 BoundNetLog(), GetParam(), NULL); |
| 2197 helper.RunToCompletion(&data); | 2107 helper.RunToCompletion(&data); |
| 2198 TransactionHelperResult out = helper.output(); | 2108 TransactionHelperResult out = helper.output(); |
| 2199 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, out.rv); | 2109 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, out.rv); |
| 2200 } | 2110 } |
| 2201 | 2111 |
| 2202 // Test that the transaction doesn't crash when we get two replies on the same | 2112 // Test that the transaction doesn't crash when we get two replies on the same |
| 2203 // stream ID. See http://crbug.com/45639. | 2113 // stream ID. See http://crbug.com/45639. |
| 2204 TEST_P(SpdyNetworkTransactionTest, ResponseWithTwoSynReplies) { | 2114 TEST_P(SpdyNetworkTransactionTest, ResponseWithTwoSynReplies) { |
| 2205 if (GetParam().protocol > kProtoSPDY3) | |
| 2206 return; | |
| 2207 | |
| 2208 scoped_ptr<SpdyFrame> req( | 2115 scoped_ptr<SpdyFrame> req( |
| 2209 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true)); | 2116 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true)); |
| 2210 scoped_ptr<SpdyFrame> rst( | 2117 scoped_ptr<SpdyFrame> rst( |
| 2211 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_STREAM_IN_USE)); | 2118 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_STREAM_IN_USE)); |
| 2212 MockWrite writes[] = { | 2119 MockWrite writes[] = { |
| 2213 CreateMockWrite(*req), | 2120 CreateMockWrite(*req), |
| 2214 CreateMockWrite(*rst), | 2121 CreateMockWrite(*rst), |
| 2215 }; | 2122 }; |
| 2216 | 2123 |
| 2217 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); | 2124 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); |
| (...skipping 25 matching lines...) Expand all Loading... | |
| 2243 ASSERT_TRUE(response != NULL); | 2150 ASSERT_TRUE(response != NULL); |
| 2244 EXPECT_TRUE(response->headers.get() != NULL); | 2151 EXPECT_TRUE(response->headers.get() != NULL); |
| 2245 EXPECT_TRUE(response->was_fetched_via_spdy); | 2152 EXPECT_TRUE(response->was_fetched_via_spdy); |
| 2246 std::string response_data; | 2153 std::string response_data; |
| 2247 rv = ReadTransaction(trans, &response_data); | 2154 rv = ReadTransaction(trans, &response_data); |
| 2248 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, rv); | 2155 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, rv); |
| 2249 | 2156 |
| 2250 helper.VerifyDataConsumed(); | 2157 helper.VerifyDataConsumed(); |
| 2251 } | 2158 } |
| 2252 | 2159 |
| 2253 // Test that sent data frames and received WINDOW_UPDATE frames change | |
|
Ryan Hamilton
2013/06/27 17:23:50
So this block appears to have been moved but it lo
akalin
2013/06/27 20:00:06
Moved back.
| |
| 2254 // the send_window_size_ correctly. | |
| 2255 | |
| 2256 // WINDOW_UPDATE is different than most other frames in that it can arrive | |
| 2257 // while the client is still sending the request body. In order to enforce | |
| 2258 // this scenario, we feed a couple of dummy frames and give a delay of 0 to | |
| 2259 // socket data provider, so that initial read that is done as soon as the | |
| 2260 // stream is created, succeeds and schedules another read. This way reads | |
| 2261 // and writes are interleaved; after doing a full frame write, SpdyStream | |
| 2262 // will break out of DoLoop and will read and process a WINDOW_UPDATE. | |
| 2263 // Once our WINDOW_UPDATE is read, we cannot send SYN_REPLY right away | |
| 2264 // since request has not been completely written, therefore we feed | |
| 2265 // enough number of WINDOW_UPDATEs to finish the first read and cause a | |
| 2266 // write, leading to a complete write of request body; after that we send | |
| 2267 // a reply with a body, to cause a graceful shutdown. | |
| 2268 | |
| 2269 // TODO(agayev): develop a socket data provider where both, reads and | |
| 2270 // writes are ordered so that writing tests like these are easy and rewrite | |
| 2271 // all these tests using it. Right now we are working around the | |
| 2272 // limitations as described above and it's not deterministic, tests may | |
| 2273 // fail under specific circumstances. | |
| 2274 TEST_P(SpdyNetworkTransactionTest, WindowUpdateReceived) { | |
| 2275 if (GetParam().protocol != kProtoSPDY3) | |
| 2276 return; | |
| 2277 | |
| 2278 static int kFrameCount = 2; | |
| 2279 scoped_ptr<std::string> content( | |
| 2280 new std::string(kMaxSpdyFrameChunkSize, 'a')); | |
| 2281 scoped_ptr<SpdyFrame> req(spdy_util_.ConstructSpdyPost( | |
| 2282 kRequestUrl, 1, kMaxSpdyFrameChunkSize * kFrameCount, LOWEST, NULL, 0)); | |
| 2283 scoped_ptr<SpdyFrame> body( | |
| 2284 spdy_util_.ConstructSpdyBodyFrame( | |
| 2285 1, content->c_str(), content->size(), false)); | |
| 2286 scoped_ptr<SpdyFrame> body_end( | |
| 2287 spdy_util_.ConstructSpdyBodyFrame( | |
| 2288 1, content->c_str(), content->size(), true)); | |
| 2289 | |
| 2290 MockWrite writes[] = { | |
| 2291 CreateMockWrite(*req, 0), | |
| 2292 CreateMockWrite(*body, 1), | |
| 2293 CreateMockWrite(*body_end, 2), | |
| 2294 }; | |
| 2295 | |
| 2296 static const int32 kDeltaWindowSize = 0xff; | |
| 2297 static const int kDeltaCount = 4; | |
| 2298 scoped_ptr<SpdyFrame> window_update( | |
| 2299 spdy_util_.ConstructSpdyWindowUpdate(1, kDeltaWindowSize)); | |
| 2300 scoped_ptr<SpdyFrame> window_update_dummy( | |
| 2301 spdy_util_.ConstructSpdyWindowUpdate(2, kDeltaWindowSize)); | |
| 2302 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyPostSynReply(NULL, 0)); | |
| 2303 MockRead reads[] = { | |
| 2304 CreateMockRead(*window_update_dummy, 3), | |
| 2305 CreateMockRead(*window_update_dummy, 4), | |
| 2306 CreateMockRead(*window_update_dummy, 5), | |
| 2307 CreateMockRead(*window_update, 6), // Four updates, therefore window | |
| 2308 CreateMockRead(*window_update, 7), // size should increase by | |
| 2309 CreateMockRead(*window_update, 8), // kDeltaWindowSize * 4 | |
| 2310 CreateMockRead(*window_update, 9), | |
| 2311 CreateMockRead(*resp, 10), | |
| 2312 CreateMockRead(*body_end, 11), | |
| 2313 MockRead(ASYNC, 0, 0, 12) // EOF | |
| 2314 }; | |
| 2315 | |
| 2316 DeterministicSocketData data(reads, arraysize(reads), | |
| 2317 writes, arraysize(writes)); | |
| 2318 | |
| 2319 ScopedVector<UploadElementReader> element_readers; | |
| 2320 for (int i = 0; i < kFrameCount; ++i) { | |
| 2321 element_readers.push_back( | |
| 2322 new UploadBytesElementReader(content->c_str(), content->size())); | |
| 2323 } | |
| 2324 UploadDataStream upload_data_stream(&element_readers, 0); | |
| 2325 | |
| 2326 // Setup the request | |
| 2327 HttpRequestInfo request; | |
| 2328 request.method = "POST"; | |
| 2329 request.url = GURL(kDefaultURL); | |
| 2330 request.upload_data_stream = &upload_data_stream; | |
| 2331 | |
| 2332 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY, | |
| 2333 BoundNetLog(), GetParam(), NULL); | |
| 2334 helper.SetDeterministic(); | |
| 2335 helper.AddDeterministicData(&data); | |
| 2336 helper.RunPreTestSetup(); | |
| 2337 | |
| 2338 HttpNetworkTransaction* trans = helper.trans(); | |
| 2339 | |
| 2340 TestCompletionCallback callback; | |
| 2341 int rv = trans->Start(&helper.request(), callback.callback(), BoundNetLog()); | |
| 2342 | |
| 2343 EXPECT_EQ(ERR_IO_PENDING, rv); | |
| 2344 | |
| 2345 data.RunFor(11); | |
| 2346 | |
| 2347 SpdyHttpStream* stream = static_cast<SpdyHttpStream*>(trans->stream_.get()); | |
| 2348 ASSERT_TRUE(stream != NULL); | |
| 2349 ASSERT_TRUE(stream->stream() != NULL); | |
| 2350 EXPECT_EQ(static_cast<int>(kSpdyStreamInitialWindowSize) + | |
| 2351 kDeltaWindowSize * kDeltaCount - | |
| 2352 kMaxSpdyFrameChunkSize * kFrameCount, | |
| 2353 stream->stream()->send_window_size()); | |
| 2354 | |
| 2355 data.RunFor(1); | |
| 2356 | |
| 2357 rv = callback.WaitForResult(); | |
| 2358 EXPECT_EQ(OK, rv); | |
| 2359 | |
| 2360 helper.VerifyDataConsumed(); | |
| 2361 } | |
| 2362 | |
| 2363 // Test that received data frames and sent WINDOW_UPDATE frames change | |
| 2364 // the recv_window_size_ correctly. | |
| 2365 TEST_P(SpdyNetworkTransactionTest, WindowUpdateSent) { | |
| 2366 if (GetParam().protocol != kProtoSPDY3) | |
| 2367 return; | |
| 2368 | |
| 2369 // Set the data in the body frame large enough to trigger sending a | |
| 2370 // WINDOW_UPDATE by the stream. | |
| 2371 const std::string body_data(kSpdyStreamInitialWindowSize / 2 + 1, 'x'); | |
| 2372 | |
| 2373 scoped_ptr<SpdyFrame> req( | |
| 2374 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true)); | |
| 2375 scoped_ptr<SpdyFrame> window_update( | |
| 2376 spdy_util_.ConstructSpdyWindowUpdate(1, body_data.size())); | |
| 2377 | |
| 2378 MockWrite writes[] = { | |
| 2379 CreateMockWrite(*req), | |
| 2380 CreateMockWrite(*window_update), | |
| 2381 }; | |
| 2382 | |
| 2383 scoped_ptr<SpdyFrame> resp( | |
| 2384 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); | |
| 2385 scoped_ptr<SpdyFrame> body_no_fin( | |
| 2386 spdy_util_.ConstructSpdyBodyFrame( | |
| 2387 1, body_data.data(), body_data.size(), false)); | |
| 2388 scoped_ptr<SpdyFrame> body_fin( | |
| 2389 spdy_util_.ConstructSpdyBodyFrame(1, NULL, 0, true)); | |
| 2390 MockRead reads[] = { | |
| 2391 CreateMockRead(*resp), | |
| 2392 CreateMockRead(*body_no_fin), | |
| 2393 MockRead(ASYNC, ERR_IO_PENDING, 0), // Force a pause | |
| 2394 CreateMockRead(*body_fin), | |
| 2395 MockRead(ASYNC, ERR_IO_PENDING, 0), // Force a pause | |
| 2396 MockRead(ASYNC, 0, 0) // EOF | |
| 2397 }; | |
| 2398 | |
| 2399 DelayedSocketData data(1, reads, arraysize(reads), | |
| 2400 writes, arraysize(writes)); | |
| 2401 | |
| 2402 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY, | |
| 2403 BoundNetLog(), GetParam(), NULL); | |
| 2404 helper.AddData(&data); | |
| 2405 helper.RunPreTestSetup(); | |
| 2406 HttpNetworkTransaction* trans = helper.trans(); | |
| 2407 | |
| 2408 TestCompletionCallback callback; | |
| 2409 int rv = trans->Start(&helper.request(), callback.callback(), BoundNetLog()); | |
| 2410 | |
| 2411 EXPECT_EQ(ERR_IO_PENDING, rv); | |
| 2412 rv = callback.WaitForResult(); | |
| 2413 EXPECT_EQ(OK, rv); | |
| 2414 | |
| 2415 SpdyHttpStream* stream = | |
| 2416 static_cast<SpdyHttpStream*>(trans->stream_.get()); | |
| 2417 ASSERT_TRUE(stream != NULL); | |
| 2418 ASSERT_TRUE(stream->stream() != NULL); | |
| 2419 | |
| 2420 EXPECT_EQ( | |
| 2421 static_cast<int>(kSpdyStreamInitialWindowSize - body_data.size()), | |
| 2422 stream->stream()->recv_window_size()); | |
| 2423 | |
| 2424 const HttpResponseInfo* response = trans->GetResponseInfo(); | |
| 2425 ASSERT_TRUE(response != NULL); | |
| 2426 ASSERT_TRUE(response->headers.get() != NULL); | |
| 2427 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine()); | |
| 2428 EXPECT_TRUE(response->was_fetched_via_spdy); | |
| 2429 | |
| 2430 // Issue a read which will cause a WINDOW_UPDATE to be sent and window | |
| 2431 // size increased to default. | |
| 2432 scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(body_data.size())); | |
| 2433 rv = trans->Read(buf.get(), body_data.size(), CompletionCallback()); | |
| 2434 EXPECT_EQ(static_cast<int>(body_data.size()), rv); | |
| 2435 std::string content(buf->data(), buf->data() + body_data.size()); | |
| 2436 EXPECT_EQ(body_data, content); | |
| 2437 | |
| 2438 // Schedule the reading of empty data frame with FIN | |
| 2439 data.CompleteRead(); | |
| 2440 | |
| 2441 // Force write of WINDOW_UPDATE which was scheduled during the above | |
| 2442 // read. | |
| 2443 base::MessageLoop::current()->RunUntilIdle(); | |
| 2444 | |
| 2445 // Read EOF. | |
| 2446 data.CompleteRead(); | |
| 2447 | |
| 2448 helper.VerifyDataConsumed(); | |
| 2449 } | |
| 2450 | |
| 2451 // Test that WINDOW_UPDATE frame causing overflow is handled correctly. | |
| 2452 TEST_P(SpdyNetworkTransactionTest, WindowUpdateOverflow) { | |
| 2453 if (GetParam().protocol != kProtoSPDY3) | |
| 2454 return; | |
| 2455 | |
| 2456 // Number of full frames we hope to write (but will not, used to | |
| 2457 // set content-length header correctly) | |
| 2458 static int kFrameCount = 3; | |
| 2459 | |
| 2460 scoped_ptr<std::string> content( | |
| 2461 new std::string(kMaxSpdyFrameChunkSize, 'a')); | |
| 2462 scoped_ptr<SpdyFrame> req(spdy_util_.ConstructSpdyPost( | |
| 2463 kRequestUrl, 1, kMaxSpdyFrameChunkSize * kFrameCount, LOWEST, NULL, 0)); | |
| 2464 scoped_ptr<SpdyFrame> body( | |
| 2465 spdy_util_.ConstructSpdyBodyFrame( | |
| 2466 1, content->c_str(), content->size(), false)); | |
| 2467 scoped_ptr<SpdyFrame> rst( | |
| 2468 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_FLOW_CONTROL_ERROR)); | |
| 2469 | |
| 2470 // We're not going to write a data frame with FIN, we'll receive a bad | |
| 2471 // WINDOW_UPDATE while sending a request and will send a RST_STREAM frame. | |
| 2472 MockWrite writes[] = { | |
| 2473 CreateMockWrite(*req, 0), | |
| 2474 CreateMockWrite(*body, 2), | |
| 2475 CreateMockWrite(*rst, 3), | |
| 2476 }; | |
| 2477 | |
| 2478 static const int32 kDeltaWindowSize = 0x7fffffff; // cause an overflow | |
| 2479 scoped_ptr<SpdyFrame> window_update( | |
| 2480 spdy_util_.ConstructSpdyWindowUpdate(1, kDeltaWindowSize)); | |
| 2481 MockRead reads[] = { | |
| 2482 CreateMockRead(*window_update, 1), | |
| 2483 MockRead(ASYNC, 0, 4) // EOF | |
| 2484 }; | |
| 2485 | |
| 2486 DeterministicSocketData data(reads, arraysize(reads), | |
| 2487 writes, arraysize(writes)); | |
| 2488 | |
| 2489 ScopedVector<UploadElementReader> element_readers; | |
| 2490 for (int i = 0; i < kFrameCount; ++i) { | |
| 2491 element_readers.push_back( | |
| 2492 new UploadBytesElementReader(content->c_str(), content->size())); | |
| 2493 } | |
| 2494 UploadDataStream upload_data_stream(&element_readers, 0); | |
| 2495 | |
| 2496 // Setup the request | |
| 2497 HttpRequestInfo request; | |
| 2498 request.method = "POST"; | |
| 2499 request.url = GURL("http://www.google.com/"); | |
| 2500 request.upload_data_stream = &upload_data_stream; | |
| 2501 | |
| 2502 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY, | |
| 2503 BoundNetLog(), GetParam(), NULL); | |
| 2504 helper.SetDeterministic(); | |
| 2505 helper.RunPreTestSetup(); | |
| 2506 helper.AddDeterministicData(&data); | |
| 2507 HttpNetworkTransaction* trans = helper.trans(); | |
| 2508 | |
| 2509 TestCompletionCallback callback; | |
| 2510 int rv = trans->Start(&helper.request(), callback.callback(), BoundNetLog()); | |
| 2511 ASSERT_EQ(ERR_IO_PENDING, rv); | |
| 2512 | |
| 2513 data.RunFor(5); | |
| 2514 ASSERT_TRUE(callback.have_result()); | |
| 2515 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, callback.WaitForResult()); | |
| 2516 helper.VerifyDataConsumed(); | |
| 2517 } | |
| 2518 | |
| 2519 // Test that after hitting a send window size of 0, the write process | |
| 2520 // stalls and upon receiving WINDOW_UPDATE frame write resumes. | |
| 2521 | |
| 2522 // This test constructs a POST request followed by enough data frames | |
| 2523 // containing 'a' that would make the window size 0, followed by another | |
| 2524 // data frame containing default content (which is "hello!") and this frame | |
| 2525 // also contains a FIN flag. DelayedSocketData is used to enforce all | |
| 2526 // writes go through before a read could happen. However, the last frame | |
| 2527 // ("hello!") is not supposed to go through since by the time its turn | |
| 2528 // arrives, window size is 0. At this point MessageLoop::Run() called via | |
| 2529 // callback would block. Therefore we call MessageLoop::RunUntilIdle() | |
| 2530 // which returns after performing all possible writes. We use DCHECKS to | |
| 2531 // ensure that last data frame is still there and stream has stalled. | |
| 2532 // After that, next read is artifically enforced, which causes a | |
| 2533 // WINDOW_UPDATE to be read and I/O process resumes. | |
| 2534 TEST_P(SpdyNetworkTransactionTest, FlowControlStallResume) { | |
| 2535 if (GetParam().protocol != kProtoSPDY3) | |
| 2536 return; | |
| 2537 | |
| 2538 // Number of frames we need to send to zero out the window size: data | |
| 2539 // frames plus SYN_STREAM plus the last data frame; also we need another | |
| 2540 // data frame that we will send once the WINDOW_UPDATE is received, | |
| 2541 // therefore +3. | |
| 2542 size_t num_writes = kSpdyStreamInitialWindowSize / kMaxSpdyFrameChunkSize + 3; | |
| 2543 | |
| 2544 // Calculate last frame's size; 0 size data frame is legal. | |
| 2545 size_t last_frame_size = | |
| 2546 kSpdyStreamInitialWindowSize % kMaxSpdyFrameChunkSize; | |
| 2547 | |
| 2548 // Construct content for a data frame of maximum size. | |
| 2549 std::string content(kMaxSpdyFrameChunkSize, 'a'); | |
| 2550 | |
| 2551 scoped_ptr<SpdyFrame> req(spdy_util_.ConstructSpdyPost( | |
| 2552 kRequestUrl, 1, kSpdyStreamInitialWindowSize + kUploadDataSize, | |
| 2553 LOWEST, NULL, 0)); | |
| 2554 | |
| 2555 // Full frames. | |
| 2556 scoped_ptr<SpdyFrame> body1( | |
| 2557 spdy_util_.ConstructSpdyBodyFrame( | |
| 2558 1, content.c_str(), content.size(), false)); | |
| 2559 | |
| 2560 // Last frame to zero out the window size. | |
| 2561 scoped_ptr<SpdyFrame> body2( | |
| 2562 spdy_util_.ConstructSpdyBodyFrame( | |
| 2563 1, content.c_str(), last_frame_size, false)); | |
| 2564 | |
| 2565 // Data frame to be sent once WINDOW_UPDATE frame is received. | |
| 2566 scoped_ptr<SpdyFrame> body3(spdy_util_.ConstructSpdyBodyFrame(1, true)); | |
| 2567 | |
| 2568 // Fill in mock writes. | |
| 2569 scoped_ptr<MockWrite[]> writes(new MockWrite[num_writes]); | |
| 2570 size_t i = 0; | |
| 2571 writes[i] = CreateMockWrite(*req); | |
| 2572 for (i = 1; i < num_writes - 2; i++) | |
| 2573 writes[i] = CreateMockWrite(*body1); | |
| 2574 writes[i++] = CreateMockWrite(*body2); | |
| 2575 writes[i] = CreateMockWrite(*body3); | |
| 2576 | |
| 2577 // Construct read frame, give enough space to upload the rest of the | |
| 2578 // data. | |
| 2579 scoped_ptr<SpdyFrame> window_update( | |
| 2580 spdy_util_.ConstructSpdyWindowUpdate(1, kUploadDataSize)); | |
| 2581 scoped_ptr<SpdyFrame> reply(spdy_util_.ConstructSpdyPostSynReply(NULL, 0)); | |
| 2582 MockRead reads[] = { | |
| 2583 CreateMockRead(*window_update), | |
| 2584 CreateMockRead(*window_update), | |
| 2585 CreateMockRead(*reply), | |
| 2586 CreateMockRead(*body2), | |
| 2587 CreateMockRead(*body3), | |
| 2588 MockRead(ASYNC, 0, 0) // EOF | |
| 2589 }; | |
| 2590 | |
| 2591 // Force all writes to happen before any read, last write will not | |
| 2592 // actually queue a frame, due to window size being 0. | |
| 2593 DelayedSocketData data(num_writes, reads, arraysize(reads), | |
| 2594 writes.get(), num_writes); | |
| 2595 | |
| 2596 ScopedVector<UploadElementReader> element_readers; | |
| 2597 std::string upload_data_string(kSpdyStreamInitialWindowSize, 'a'); | |
| 2598 upload_data_string.append(kUploadData, kUploadDataSize); | |
| 2599 element_readers.push_back(new UploadBytesElementReader( | |
| 2600 upload_data_string.c_str(), upload_data_string.size())); | |
| 2601 UploadDataStream upload_data_stream(&element_readers, 0); | |
| 2602 | |
| 2603 HttpRequestInfo request; | |
| 2604 request.method = "POST"; | |
| 2605 request.url = GURL("http://www.google.com/"); | |
| 2606 request.upload_data_stream = &upload_data_stream; | |
| 2607 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY, | |
| 2608 BoundNetLog(), GetParam(), NULL); | |
| 2609 helper.AddData(&data); | |
| 2610 helper.RunPreTestSetup(); | |
| 2611 | |
| 2612 HttpNetworkTransaction* trans = helper.trans(); | |
| 2613 | |
| 2614 TestCompletionCallback callback; | |
| 2615 int rv = trans->Start(&helper.request(), callback.callback(), BoundNetLog()); | |
| 2616 EXPECT_EQ(ERR_IO_PENDING, rv); | |
| 2617 | |
| 2618 base::MessageLoop::current()->RunUntilIdle(); // Write as much as we can. | |
| 2619 | |
| 2620 SpdyHttpStream* stream = static_cast<SpdyHttpStream*>(trans->stream_.get()); | |
| 2621 ASSERT_TRUE(stream != NULL); | |
| 2622 ASSERT_TRUE(stream->stream() != NULL); | |
| 2623 EXPECT_EQ(0, stream->stream()->send_window_size()); | |
| 2624 // All the body data should have been read. | |
| 2625 // TODO(satorux): This is because of the weirdness in reading the request | |
| 2626 // body in OnSendBodyComplete(). See crbug.com/113107. | |
| 2627 EXPECT_TRUE(upload_data_stream.IsEOF()); | |
| 2628 // But the body is not yet fully sent (kUploadData is not yet sent) | |
| 2629 // since we're send-stalled. | |
| 2630 EXPECT_TRUE(stream->stream()->send_stalled_by_flow_control()); | |
| 2631 | |
| 2632 data.ForceNextRead(); // Read in WINDOW_UPDATE frame. | |
| 2633 rv = callback.WaitForResult(); | |
| 2634 helper.VerifyDataConsumed(); | |
| 2635 } | |
| 2636 | |
| 2637 // Test we correctly handle the case where the SETTINGS frame results in | |
| 2638 // unstalling the send window. | |
| 2639 TEST_P(SpdyNetworkTransactionTest, FlowControlStallResumeAfterSettings) { | |
| 2640 if (GetParam().protocol != kProtoSPDY3) | |
| 2641 return; | |
| 2642 | |
| 2643 // Number of frames we need to send to zero out the window size: data | |
| 2644 // frames plus SYN_STREAM plus the last data frame; also we need another | |
| 2645 // data frame that we will send once the SETTING is received, therefore +3. | |
| 2646 size_t num_writes = kSpdyStreamInitialWindowSize / kMaxSpdyFrameChunkSize + 3; | |
| 2647 | |
| 2648 // Calculate last frame's size; 0 size data frame is legal. | |
| 2649 size_t last_frame_size = | |
| 2650 kSpdyStreamInitialWindowSize % kMaxSpdyFrameChunkSize; | |
| 2651 | |
| 2652 // Construct content for a data frame of maximum size. | |
| 2653 std::string content(kMaxSpdyFrameChunkSize, 'a'); | |
| 2654 | |
| 2655 scoped_ptr<SpdyFrame> req(spdy_util_.ConstructSpdyPost( | |
| 2656 kRequestUrl, 1, kSpdyStreamInitialWindowSize + kUploadDataSize, | |
| 2657 LOWEST, NULL, 0)); | |
| 2658 | |
| 2659 // Full frames. | |
| 2660 scoped_ptr<SpdyFrame> body1( | |
| 2661 spdy_util_.ConstructSpdyBodyFrame( | |
| 2662 1, content.c_str(), content.size(), false)); | |
| 2663 | |
| 2664 // Last frame to zero out the window size. | |
| 2665 scoped_ptr<SpdyFrame> body2( | |
| 2666 spdy_util_.ConstructSpdyBodyFrame( | |
| 2667 1, content.c_str(), last_frame_size, false)); | |
| 2668 | |
| 2669 // Data frame to be sent once SETTINGS frame is received. | |
| 2670 scoped_ptr<SpdyFrame> body3(spdy_util_.ConstructSpdyBodyFrame(1, true)); | |
| 2671 | |
| 2672 // Fill in mock reads/writes. | |
| 2673 std::vector<MockRead> reads; | |
| 2674 std::vector<MockWrite> writes; | |
| 2675 size_t i = 0; | |
| 2676 writes.push_back(CreateMockWrite(*req, i++)); | |
| 2677 while (i < num_writes - 2) | |
| 2678 writes.push_back(CreateMockWrite(*body1, i++)); | |
| 2679 writes.push_back(CreateMockWrite(*body2, i++)); | |
| 2680 | |
| 2681 // Construct read frame for SETTINGS that gives enough space to upload the | |
| 2682 // rest of the data. | |
| 2683 SettingsMap settings; | |
| 2684 settings[SETTINGS_INITIAL_WINDOW_SIZE] = | |
| 2685 SettingsFlagsAndValue( | |
| 2686 SETTINGS_FLAG_NONE, kSpdyStreamInitialWindowSize * 2); | |
| 2687 scoped_ptr<SpdyFrame> settings_frame_large( | |
| 2688 spdy_util_.ConstructSpdySettings(settings)); | |
| 2689 | |
| 2690 reads.push_back(CreateMockRead(*settings_frame_large, i++)); | |
| 2691 | |
| 2692 writes.push_back(CreateMockWrite(*body3, i++)); | |
| 2693 | |
| 2694 scoped_ptr<SpdyFrame> reply(spdy_util_.ConstructSpdyPostSynReply(NULL, 0)); | |
| 2695 reads.push_back(CreateMockRead(*reply, i++)); | |
| 2696 reads.push_back(CreateMockRead(*body2, i++)); | |
| 2697 reads.push_back(CreateMockRead(*body3, i++)); | |
| 2698 reads.push_back(MockRead(ASYNC, 0, i++)); // EOF | |
| 2699 | |
| 2700 // Force all writes to happen before any read, last write will not | |
| 2701 // actually queue a frame, due to window size being 0. | |
| 2702 DeterministicSocketData data(vector_as_array(&reads), reads.size(), | |
| 2703 vector_as_array(&writes), writes.size()); | |
| 2704 | |
| 2705 ScopedVector<UploadElementReader> element_readers; | |
| 2706 std::string upload_data_string(kSpdyStreamInitialWindowSize, 'a'); | |
| 2707 upload_data_string.append(kUploadData, kUploadDataSize); | |
| 2708 element_readers.push_back(new UploadBytesElementReader( | |
| 2709 upload_data_string.c_str(), upload_data_string.size())); | |
| 2710 UploadDataStream upload_data_stream(&element_readers, 0); | |
| 2711 | |
| 2712 HttpRequestInfo request; | |
| 2713 request.method = "POST"; | |
| 2714 request.url = GURL("http://www.google.com/"); | |
| 2715 request.upload_data_stream = &upload_data_stream; | |
| 2716 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY, | |
| 2717 BoundNetLog(), GetParam(), NULL); | |
| 2718 helper.SetDeterministic(); | |
| 2719 helper.RunPreTestSetup(); | |
| 2720 helper.AddDeterministicData(&data); | |
| 2721 | |
| 2722 HttpNetworkTransaction* trans = helper.trans(); | |
| 2723 | |
| 2724 TestCompletionCallback callback; | |
| 2725 int rv = trans->Start(&helper.request(), callback.callback(), BoundNetLog()); | |
| 2726 EXPECT_EQ(ERR_IO_PENDING, rv); | |
| 2727 | |
| 2728 data.RunFor(num_writes - 1); // Write as much as we can. | |
| 2729 | |
| 2730 SpdyHttpStream* stream = static_cast<SpdyHttpStream*>(trans->stream_.get()); | |
| 2731 ASSERT_TRUE(stream != NULL); | |
| 2732 ASSERT_TRUE(stream->stream() != NULL); | |
| 2733 EXPECT_EQ(0, stream->stream()->send_window_size()); | |
| 2734 | |
| 2735 // All the body data should have been read. | |
| 2736 // TODO(satorux): This is because of the weirdness in reading the request | |
| 2737 // body in OnSendBodyComplete(). See crbug.com/113107. | |
| 2738 EXPECT_TRUE(upload_data_stream.IsEOF()); | |
| 2739 // But the body is not yet fully sent (kUploadData is not yet sent) | |
| 2740 // since we're send-stalled. | |
| 2741 EXPECT_TRUE(stream->stream()->send_stalled_by_flow_control()); | |
| 2742 | |
| 2743 data.RunFor(6); // Read in SETTINGS frame to unstall. | |
| 2744 rv = callback.WaitForResult(); | |
| 2745 helper.VerifyDataConsumed(); | |
| 2746 // If stream is NULL, that means it was unstalled and closed. | |
| 2747 EXPECT_TRUE(stream->stream() == NULL); | |
| 2748 } | |
| 2749 | |
| 2750 // Test we correctly handle the case where the SETTINGS frame results in a | |
| 2751 // negative send window size. | |
| 2752 TEST_P(SpdyNetworkTransactionTest, FlowControlNegativeSendWindowSize) { | |
| 2753 if (GetParam().protocol != kProtoSPDY3) | |
| 2754 return; | |
| 2755 | |
| 2756 // Number of frames we need to send to zero out the window size: data | |
| 2757 // frames plus SYN_STREAM plus the last data frame; also we need another | |
| 2758 // data frame that we will send once the SETTING is received, therefore +3. | |
| 2759 size_t num_writes = kSpdyStreamInitialWindowSize / kMaxSpdyFrameChunkSize + 3; | |
| 2760 | |
| 2761 // Calculate last frame's size; 0 size data frame is legal. | |
| 2762 size_t last_frame_size = | |
| 2763 kSpdyStreamInitialWindowSize % kMaxSpdyFrameChunkSize; | |
| 2764 | |
| 2765 // Construct content for a data frame of maximum size. | |
| 2766 std::string content(kMaxSpdyFrameChunkSize, 'a'); | |
| 2767 | |
| 2768 scoped_ptr<SpdyFrame> req(spdy_util_.ConstructSpdyPost( | |
| 2769 kRequestUrl, 1, kSpdyStreamInitialWindowSize + kUploadDataSize, | |
| 2770 LOWEST, NULL, 0)); | |
| 2771 | |
| 2772 // Full frames. | |
| 2773 scoped_ptr<SpdyFrame> body1( | |
| 2774 spdy_util_.ConstructSpdyBodyFrame( | |
| 2775 1, content.c_str(), content.size(), false)); | |
| 2776 | |
| 2777 // Last frame to zero out the window size. | |
| 2778 scoped_ptr<SpdyFrame> body2( | |
| 2779 spdy_util_.ConstructSpdyBodyFrame( | |
| 2780 1, content.c_str(), last_frame_size, false)); | |
| 2781 | |
| 2782 // Data frame to be sent once SETTINGS frame is received. | |
| 2783 scoped_ptr<SpdyFrame> body3(spdy_util_.ConstructSpdyBodyFrame(1, true)); | |
| 2784 | |
| 2785 // Fill in mock reads/writes. | |
| 2786 std::vector<MockRead> reads; | |
| 2787 std::vector<MockWrite> writes; | |
| 2788 size_t i = 0; | |
| 2789 writes.push_back(CreateMockWrite(*req, i++)); | |
| 2790 while (i < num_writes - 2) | |
| 2791 writes.push_back(CreateMockWrite(*body1, i++)); | |
| 2792 writes.push_back(CreateMockWrite(*body2, i++)); | |
| 2793 | |
| 2794 // Construct read frame for SETTINGS that makes the send_window_size | |
| 2795 // negative. | |
| 2796 SettingsMap new_settings; | |
| 2797 new_settings[SETTINGS_INITIAL_WINDOW_SIZE] = | |
| 2798 SettingsFlagsAndValue( | |
| 2799 SETTINGS_FLAG_NONE, kSpdyStreamInitialWindowSize / 2); | |
| 2800 scoped_ptr<SpdyFrame> settings_frame_small( | |
| 2801 spdy_util_.ConstructSpdySettings(new_settings)); | |
| 2802 // Construct read frame for WINDOW_UPDATE that makes the send_window_size | |
| 2803 // postive. | |
| 2804 scoped_ptr<SpdyFrame> window_update_init_size( | |
| 2805 spdy_util_.ConstructSpdyWindowUpdate(1, kSpdyStreamInitialWindowSize)); | |
| 2806 | |
| 2807 reads.push_back(CreateMockRead(*settings_frame_small, i++)); | |
| 2808 reads.push_back(CreateMockRead(*window_update_init_size, i++)); | |
| 2809 | |
| 2810 writes.push_back(CreateMockWrite(*body3, i++)); | |
| 2811 | |
| 2812 scoped_ptr<SpdyFrame> reply(spdy_util_.ConstructSpdyPostSynReply(NULL, 0)); | |
| 2813 reads.push_back(CreateMockRead(*reply, i++)); | |
| 2814 reads.push_back(CreateMockRead(*body2, i++)); | |
| 2815 reads.push_back(CreateMockRead(*body3, i++)); | |
| 2816 reads.push_back(MockRead(ASYNC, 0, i++)); // EOF | |
| 2817 | |
| 2818 // Force all writes to happen before any read, last write will not | |
| 2819 // actually queue a frame, due to window size being 0. | |
| 2820 DeterministicSocketData data(vector_as_array(&reads), reads.size(), | |
| 2821 vector_as_array(&writes), writes.size()); | |
| 2822 | |
| 2823 ScopedVector<UploadElementReader> element_readers; | |
| 2824 std::string upload_data_string(kSpdyStreamInitialWindowSize, 'a'); | |
| 2825 upload_data_string.append(kUploadData, kUploadDataSize); | |
| 2826 element_readers.push_back(new UploadBytesElementReader( | |
| 2827 upload_data_string.c_str(), upload_data_string.size())); | |
| 2828 UploadDataStream upload_data_stream(&element_readers, 0); | |
| 2829 | |
| 2830 HttpRequestInfo request; | |
| 2831 request.method = "POST"; | |
| 2832 request.url = GURL("http://www.google.com/"); | |
| 2833 request.upload_data_stream = &upload_data_stream; | |
| 2834 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY, | |
| 2835 BoundNetLog(), GetParam(), NULL); | |
| 2836 helper.SetDeterministic(); | |
| 2837 helper.RunPreTestSetup(); | |
| 2838 helper.AddDeterministicData(&data); | |
| 2839 | |
| 2840 HttpNetworkTransaction* trans = helper.trans(); | |
| 2841 | |
| 2842 TestCompletionCallback callback; | |
| 2843 int rv = trans->Start(&helper.request(), callback.callback(), BoundNetLog()); | |
| 2844 EXPECT_EQ(ERR_IO_PENDING, rv); | |
| 2845 | |
| 2846 data.RunFor(num_writes - 1); // Write as much as we can. | |
| 2847 | |
| 2848 SpdyHttpStream* stream = static_cast<SpdyHttpStream*>(trans->stream_.get()); | |
| 2849 ASSERT_TRUE(stream != NULL); | |
| 2850 ASSERT_TRUE(stream->stream() != NULL); | |
| 2851 EXPECT_EQ(0, stream->stream()->send_window_size()); | |
| 2852 | |
| 2853 // All the body data should have been read. | |
| 2854 // TODO(satorux): This is because of the weirdness in reading the request | |
| 2855 // body in OnSendBodyComplete(). See crbug.com/113107. | |
| 2856 EXPECT_TRUE(upload_data_stream.IsEOF()); | |
| 2857 // But the body is not yet fully sent (kUploadData is not yet sent) | |
| 2858 // since we're send-stalled. | |
| 2859 EXPECT_TRUE(stream->stream()->send_stalled_by_flow_control()); | |
| 2860 | |
| 2861 data.RunFor(7); // Read in WINDOW_UPDATE or SETTINGS frame. | |
| 2862 rv = callback.WaitForResult(); | |
| 2863 helper.VerifyDataConsumed(); | |
| 2864 } | |
| 2865 | |
| 2866 TEST_P(SpdyNetworkTransactionTest, ResetReplyWithTransferEncoding) { | 2160 TEST_P(SpdyNetworkTransactionTest, ResetReplyWithTransferEncoding) { |
| 2867 if (GetParam().protocol > kProtoSPDY3) | |
| 2868 return; | |
| 2869 | |
| 2870 // Construct the request. | 2161 // Construct the request. |
| 2871 scoped_ptr<SpdyFrame> req( | 2162 scoped_ptr<SpdyFrame> req( |
| 2872 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true)); | 2163 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true)); |
| 2873 scoped_ptr<SpdyFrame> rst( | 2164 scoped_ptr<SpdyFrame> rst( |
| 2874 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_PROTOCOL_ERROR)); | 2165 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_PROTOCOL_ERROR)); |
| 2875 MockWrite writes[] = { | 2166 MockWrite writes[] = { |
| 2876 CreateMockWrite(*req), | 2167 CreateMockWrite(*req), |
| 2877 CreateMockWrite(*rst), | 2168 CreateMockWrite(*rst), |
| 2878 }; | 2169 }; |
| 2879 | 2170 |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 2896 BoundNetLog(), GetParam(), NULL); | 2187 BoundNetLog(), GetParam(), NULL); |
| 2897 helper.RunToCompletion(&data); | 2188 helper.RunToCompletion(&data); |
| 2898 TransactionHelperResult out = helper.output(); | 2189 TransactionHelperResult out = helper.output(); |
| 2899 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, out.rv); | 2190 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, out.rv); |
| 2900 | 2191 |
| 2901 helper.session()->spdy_session_pool()->CloseAllSessions(); | 2192 helper.session()->spdy_session_pool()->CloseAllSessions(); |
| 2902 helper.VerifyDataConsumed(); | 2193 helper.VerifyDataConsumed(); |
| 2903 } | 2194 } |
| 2904 | 2195 |
| 2905 TEST_P(SpdyNetworkTransactionTest, ResetPushWithTransferEncoding) { | 2196 TEST_P(SpdyNetworkTransactionTest, ResetPushWithTransferEncoding) { |
| 2906 if (GetParam().protocol > kProtoSPDY3) | |
| 2907 return; | |
| 2908 | |
| 2909 // Construct the request. | 2197 // Construct the request. |
| 2910 scoped_ptr<SpdyFrame> req( | 2198 scoped_ptr<SpdyFrame> req( |
| 2911 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true)); | 2199 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true)); |
| 2912 scoped_ptr<SpdyFrame> rst( | 2200 scoped_ptr<SpdyFrame> rst( |
| 2913 spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_PROTOCOL_ERROR)); | 2201 spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_PROTOCOL_ERROR)); |
| 2914 MockWrite writes[] = { | 2202 MockWrite writes[] = { |
| 2915 CreateMockWrite(*req), | 2203 CreateMockWrite(*req), |
| 2916 CreateMockWrite(*rst), | 2204 CreateMockWrite(*rst), |
| 2917 }; | 2205 }; |
| 2918 | 2206 |
| (...skipping 20 matching lines...) Expand all Loading... | |
| 2939 TransactionHelperResult out = helper.output(); | 2227 TransactionHelperResult out = helper.output(); |
| 2940 EXPECT_EQ(OK, out.rv); | 2228 EXPECT_EQ(OK, out.rv); |
| 2941 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line); | 2229 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line); |
| 2942 EXPECT_EQ("hello!", out.response_data); | 2230 EXPECT_EQ("hello!", out.response_data); |
| 2943 | 2231 |
| 2944 helper.session()->spdy_session_pool()->CloseAllSessions(); | 2232 helper.session()->spdy_session_pool()->CloseAllSessions(); |
| 2945 helper.VerifyDataConsumed(); | 2233 helper.VerifyDataConsumed(); |
| 2946 } | 2234 } |
| 2947 | 2235 |
| 2948 TEST_P(SpdyNetworkTransactionTest, CancelledTransaction) { | 2236 TEST_P(SpdyNetworkTransactionTest, CancelledTransaction) { |
| 2949 if (GetParam().protocol > kProtoSPDY3) | |
| 2950 return; | |
| 2951 | |
| 2952 // Construct the request. | 2237 // Construct the request. |
| 2953 scoped_ptr<SpdyFrame> req( | 2238 scoped_ptr<SpdyFrame> req( |
| 2954 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true)); | 2239 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true)); |
| 2955 MockWrite writes[] = { | 2240 MockWrite writes[] = { |
| 2956 CreateMockWrite(*req), | 2241 CreateMockWrite(*req), |
| 2957 }; | 2242 }; |
| 2958 | 2243 |
| 2959 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); | 2244 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); |
| 2960 MockRead reads[] = { | 2245 MockRead reads[] = { |
| 2961 CreateMockRead(*resp), | 2246 CreateMockRead(*resp), |
| (...skipping 20 matching lines...) Expand all Loading... | |
| 2982 helper.ResetTrans(); // Cancel the transaction. | 2267 helper.ResetTrans(); // Cancel the transaction. |
| 2983 | 2268 |
| 2984 // Flush the MessageLoop while the SpdySessionDependencies (in particular, the | 2269 // Flush the MessageLoop while the SpdySessionDependencies (in particular, the |
| 2985 // MockClientSocketFactory) are still alive. | 2270 // MockClientSocketFactory) are still alive. |
| 2986 base::MessageLoop::current()->RunUntilIdle(); | 2271 base::MessageLoop::current()->RunUntilIdle(); |
| 2987 helper.VerifyDataNotConsumed(); | 2272 helper.VerifyDataNotConsumed(); |
| 2988 } | 2273 } |
| 2989 | 2274 |
| 2990 // Verify that the client sends a Rst Frame upon cancelling the stream. | 2275 // Verify that the client sends a Rst Frame upon cancelling the stream. |
| 2991 TEST_P(SpdyNetworkTransactionTest, CancelledTransactionSendRst) { | 2276 TEST_P(SpdyNetworkTransactionTest, CancelledTransactionSendRst) { |
| 2992 if (GetParam().protocol > kProtoSPDY3) | |
| 2993 return; | |
| 2994 | |
| 2995 scoped_ptr<SpdyFrame> req( | 2277 scoped_ptr<SpdyFrame> req( |
| 2996 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true)); | 2278 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true)); |
| 2997 scoped_ptr<SpdyFrame> rst( | 2279 scoped_ptr<SpdyFrame> rst( |
| 2998 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL)); | 2280 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL)); |
| 2999 MockWrite writes[] = { | 2281 MockWrite writes[] = { |
| 3000 CreateMockWrite(*req, 0, SYNCHRONOUS), | 2282 CreateMockWrite(*req, 0, SYNCHRONOUS), |
| 3001 CreateMockWrite(*rst, 2, SYNCHRONOUS), | 2283 CreateMockWrite(*rst, 2, SYNCHRONOUS), |
| 3002 }; | 2284 }; |
| 3003 | 2285 |
| 3004 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); | 2286 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); |
| (...skipping 25 matching lines...) Expand all Loading... | |
| 3030 data.SetStop(20); | 2312 data.SetStop(20); |
| 3031 data.Run(); | 2313 data.Run(); |
| 3032 | 2314 |
| 3033 helper.VerifyDataConsumed(); | 2315 helper.VerifyDataConsumed(); |
| 3034 } | 2316 } |
| 3035 | 2317 |
| 3036 // Verify that the client can correctly deal with the user callback attempting | 2318 // Verify that the client can correctly deal with the user callback attempting |
| 3037 // to start another transaction on a session that is closing down. See | 2319 // to start another transaction on a session that is closing down. See |
| 3038 // http://crbug.com/47455 | 2320 // http://crbug.com/47455 |
| 3039 TEST_P(SpdyNetworkTransactionTest, StartTransactionOnReadCallback) { | 2321 TEST_P(SpdyNetworkTransactionTest, StartTransactionOnReadCallback) { |
| 3040 if (GetParam().protocol > kProtoSPDY3) | |
| 3041 return; | |
| 3042 | |
| 3043 scoped_ptr<SpdyFrame> req( | 2322 scoped_ptr<SpdyFrame> req( |
| 3044 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true)); | 2323 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true)); |
| 3045 MockWrite writes[] = { CreateMockWrite(*req) }; | 2324 MockWrite writes[] = { CreateMockWrite(*req) }; |
| 3046 MockWrite writes2[] = { CreateMockWrite(*req) }; | 2325 MockWrite writes2[] = { CreateMockWrite(*req) }; |
| 3047 | 2326 |
| 3048 // The indicated length of this frame is longer than its actual length. When | 2327 // The indicated length of this frame is longer than its actual length. When |
| 3049 // the session receives an empty frame after this one, it shuts down the | 2328 // the session receives an empty frame after this one, it shuts down the |
| 3050 // session, and calls the read callback with the incomplete data. | 2329 // session, and calls the read callback with the incomplete data. |
| 3051 const uint8 kGetBodyFrame2[] = { | 2330 const uint8 kGetBodyFrame2[] = { |
| 3052 0x00, 0x00, 0x00, 0x01, | 2331 0x00, 0x00, 0x00, 0x01, |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3097 data.CompleteRead(); | 2376 data.CompleteRead(); |
| 3098 // This finishes the read. | 2377 // This finishes the read. |
| 3099 data.CompleteRead(); | 2378 data.CompleteRead(); |
| 3100 helper.VerifyDataConsumed(); | 2379 helper.VerifyDataConsumed(); |
| 3101 } | 2380 } |
| 3102 | 2381 |
| 3103 // Verify that the client can correctly deal with the user callback deleting the | 2382 // Verify that the client can correctly deal with the user callback deleting the |
| 3104 // transaction. Failures will usually be valgrind errors. See | 2383 // transaction. Failures will usually be valgrind errors. See |
| 3105 // http://crbug.com/46925 | 2384 // http://crbug.com/46925 |
| 3106 TEST_P(SpdyNetworkTransactionTest, DeleteSessionOnReadCallback) { | 2385 TEST_P(SpdyNetworkTransactionTest, DeleteSessionOnReadCallback) { |
| 3107 if (GetParam().protocol > kProtoSPDY3) | |
| 3108 return; | |
| 3109 | |
| 3110 scoped_ptr<SpdyFrame> req( | 2386 scoped_ptr<SpdyFrame> req( |
| 3111 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true)); | 2387 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true)); |
| 3112 MockWrite writes[] = { CreateMockWrite(*req) }; | 2388 MockWrite writes[] = { CreateMockWrite(*req) }; |
| 3113 | 2389 |
| 3114 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); | 2390 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); |
| 3115 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true)); | 2391 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true)); |
| 3116 MockRead reads[] = { | 2392 MockRead reads[] = { |
| 3117 CreateMockRead(*resp.get(), 2), | 2393 CreateMockRead(*resp.get(), 2), |
| 3118 MockRead(ASYNC, ERR_IO_PENDING, 3), // Force a pause | 2394 MockRead(ASYNC, ERR_IO_PENDING, 3), // Force a pause |
| 3119 CreateMockRead(*body.get(), 4), | 2395 CreateMockRead(*body.get(), 4), |
| (...skipping 27 matching lines...) Expand all Loading... | |
| 3147 ASSERT_EQ(ERR_IO_PENDING, rv); | 2423 ASSERT_EQ(ERR_IO_PENDING, rv); |
| 3148 data.CompleteRead(); | 2424 data.CompleteRead(); |
| 3149 | 2425 |
| 3150 // Finish running rest of tasks. | 2426 // Finish running rest of tasks. |
| 3151 base::MessageLoop::current()->RunUntilIdle(); | 2427 base::MessageLoop::current()->RunUntilIdle(); |
| 3152 helper.VerifyDataConsumed(); | 2428 helper.VerifyDataConsumed(); |
| 3153 } | 2429 } |
| 3154 | 2430 |
| 3155 // Send a spdy request to www.google.com that gets redirected to www.foo.com. | 2431 // Send a spdy request to www.google.com that gets redirected to www.foo.com. |
| 3156 TEST_P(SpdyNetworkTransactionTest, RedirectGetRequest) { | 2432 TEST_P(SpdyNetworkTransactionTest, RedirectGetRequest) { |
| 3157 if (GetParam().protocol > kProtoSPDY3) | |
| 3158 return; | |
| 3159 | |
| 3160 const SpdyHeaderInfo kSynStartHeader = spdy_util_.MakeSpdyHeader(SYN_STREAM); | 2433 const SpdyHeaderInfo kSynStartHeader = spdy_util_.MakeSpdyHeader(SYN_STREAM); |
| 3161 scoped_ptr<SpdyHeaderBlock> headers( | 2434 scoped_ptr<SpdyHeaderBlock> headers( |
| 3162 spdy_util_.ConstructGetHeaderBlock("http://www.google.com/")); | 2435 spdy_util_.ConstructGetHeaderBlock("http://www.google.com/")); |
| 3163 (*headers)["user-agent"] = ""; | 2436 (*headers)["user-agent"] = ""; |
| 3164 (*headers)["accept-encoding"] = "gzip,deflate"; | 2437 (*headers)["accept-encoding"] = "gzip,deflate"; |
| 3165 scoped_ptr<SpdyHeaderBlock> headers2( | 2438 scoped_ptr<SpdyHeaderBlock> headers2( |
| 3166 spdy_util_.ConstructGetHeaderBlock("http://www.foo.com/index.php")); | 2439 spdy_util_.ConstructGetHeaderBlock("http://www.foo.com/index.php")); |
| 3167 (*headers2)["user-agent"] = ""; | 2440 (*headers2)["user-agent"] = ""; |
| 3168 (*headers2)["accept-encoding"] = "gzip,deflate"; | 2441 (*headers2)["accept-encoding"] = "gzip,deflate"; |
| 3169 | 2442 |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3226 } | 2499 } |
| 3227 EXPECT_TRUE(data.at_read_eof()); | 2500 EXPECT_TRUE(data.at_read_eof()); |
| 3228 EXPECT_TRUE(data.at_write_eof()); | 2501 EXPECT_TRUE(data.at_write_eof()); |
| 3229 EXPECT_TRUE(data2.at_read_eof()); | 2502 EXPECT_TRUE(data2.at_read_eof()); |
| 3230 EXPECT_TRUE(data2.at_write_eof()); | 2503 EXPECT_TRUE(data2.at_write_eof()); |
| 3231 } | 2504 } |
| 3232 | 2505 |
| 3233 // Send a spdy request to www.google.com. Get a pushed stream that redirects to | 2506 // Send a spdy request to www.google.com. Get a pushed stream that redirects to |
| 3234 // www.foo.com. | 2507 // www.foo.com. |
| 3235 TEST_P(SpdyNetworkTransactionTest, RedirectServerPush) { | 2508 TEST_P(SpdyNetworkTransactionTest, RedirectServerPush) { |
| 3236 if (GetParam().protocol > kProtoSPDY3) | |
| 3237 return; | |
| 3238 | |
| 3239 const SpdyHeaderInfo kSynStartHeader = spdy_util_.MakeSpdyHeader(SYN_STREAM); | 2509 const SpdyHeaderInfo kSynStartHeader = spdy_util_.MakeSpdyHeader(SYN_STREAM); |
| 3240 | 2510 |
| 3241 scoped_ptr<SpdyHeaderBlock> headers( | 2511 scoped_ptr<SpdyHeaderBlock> headers( |
| 3242 spdy_util_.ConstructGetHeaderBlock("http://www.google.com/")); | 2512 spdy_util_.ConstructGetHeaderBlock("http://www.google.com/")); |
| 3243 (*headers)["user-agent"] = ""; | 2513 (*headers)["user-agent"] = ""; |
| 3244 (*headers)["accept-encoding"] = "gzip,deflate"; | 2514 (*headers)["accept-encoding"] = "gzip,deflate"; |
| 3245 | 2515 |
| 3246 // Setup writes/reads to www.google.com | 2516 // Setup writes/reads to www.google.com |
| 3247 scoped_ptr<SpdyFrame> req( | 2517 scoped_ptr<SpdyFrame> req( |
| 3248 spdy_util_.ConstructSpdyFrame(kSynStartHeader, headers.Pass())); | 2518 spdy_util_.ConstructSpdyFrame(kSynStartHeader, headers.Pass())); |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3331 } | 2601 } |
| 3332 data.CompleteRead(); | 2602 data.CompleteRead(); |
| 3333 data2.CompleteRead(); | 2603 data2.CompleteRead(); |
| 3334 EXPECT_TRUE(data.at_read_eof()); | 2604 EXPECT_TRUE(data.at_read_eof()); |
| 3335 EXPECT_TRUE(data.at_write_eof()); | 2605 EXPECT_TRUE(data.at_write_eof()); |
| 3336 EXPECT_TRUE(data2.at_read_eof()); | 2606 EXPECT_TRUE(data2.at_read_eof()); |
| 3337 EXPECT_TRUE(data2.at_write_eof()); | 2607 EXPECT_TRUE(data2.at_write_eof()); |
| 3338 } | 2608 } |
| 3339 | 2609 |
| 3340 TEST_P(SpdyNetworkTransactionTest, ServerPushSingleDataFrame) { | 2610 TEST_P(SpdyNetworkTransactionTest, ServerPushSingleDataFrame) { |
| 3341 if (GetParam().protocol > kProtoSPDY3) | |
| 3342 return; | |
| 3343 | |
| 3344 static const unsigned char kPushBodyFrame[] = { | |
| 3345 0x00, 0x00, 0x00, 0x02, // header, ID | |
| 3346 0x01, 0x00, 0x00, 0x06, // FIN, length | |
| 3347 'p', 'u', 's', 'h', 'e', 'd' // "pushed" | |
| 3348 }; | |
| 3349 scoped_ptr<SpdyFrame> stream1_syn( | 2611 scoped_ptr<SpdyFrame> stream1_syn( |
| 3350 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true)); | 2612 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true)); |
| 3351 scoped_ptr<SpdyFrame> stream1_body( | 2613 scoped_ptr<SpdyFrame> stream1_body( |
| 2614 spdy_util_.ConstructSpdyBodyFrame(1, true)); | |
| 2615 MockWrite writes[] = { | |
| 2616 CreateMockWrite(*stream1_syn, 1), | |
| 2617 }; | |
| 2618 | |
| 2619 scoped_ptr<SpdyFrame> | |
| 2620 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); | |
| 2621 scoped_ptr<SpdyFrame> | |
| 2622 stream2_syn(spdy_util_.ConstructSpdyPush(NULL, | |
| 2623 0, | |
| 2624 2, | |
| 2625 1, | |
| 2626 "http://www.google.com/foo.dat")); | |
| 2627 const char kPushedData[] = "pushed"; | |
| 2628 scoped_ptr<SpdyFrame> stream2_body( | |
| 2629 spdy_util_.ConstructSpdyBodyFrame( | |
| 2630 2, kPushedData, strlen(kPushedData), true)); | |
| 2631 MockRead reads[] = { | |
| 2632 CreateMockRead(*stream1_reply, 2), | |
| 2633 CreateMockRead(*stream2_syn, 3), | |
| 2634 CreateMockRead(*stream1_body, 4, SYNCHRONOUS), | |
| 2635 CreateMockRead(*stream2_body, 5), | |
| 2636 MockRead(ASYNC, ERR_IO_PENDING, 6), // Force a pause | |
| 2637 }; | |
| 2638 | |
| 2639 HttpResponseInfo response; | |
| 2640 HttpResponseInfo response2; | |
| 2641 std::string expected_push_result("pushed"); | |
| 2642 OrderedSocketData data(reads, arraysize(reads), | |
| 2643 writes, arraysize(writes)); | |
| 2644 RunServerPushTest(&data, | |
| 2645 &response, | |
| 2646 &response2, | |
| 2647 expected_push_result); | |
| 2648 | |
| 2649 // Verify the SYN_REPLY. | |
| 2650 EXPECT_TRUE(response.headers.get() != NULL); | |
| 2651 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine()); | |
| 2652 | |
| 2653 // Verify the pushed stream. | |
| 2654 EXPECT_TRUE(response2.headers.get() != NULL); | |
| 2655 EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine()); | |
| 2656 } | |
| 2657 | |
| 2658 TEST_P(SpdyNetworkTransactionTest, ServerPushBeforeSynReply) { | |
| 2659 scoped_ptr<SpdyFrame> stream1_syn( | |
| 2660 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true)); | |
| 2661 scoped_ptr<SpdyFrame> stream1_body( | |
| 2662 spdy_util_.ConstructSpdyBodyFrame(1, true)); | |
| 2663 MockWrite writes[] = { | |
| 2664 CreateMockWrite(*stream1_syn, 1), | |
| 2665 }; | |
| 2666 | |
| 2667 scoped_ptr<SpdyFrame> | |
| 2668 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); | |
| 2669 scoped_ptr<SpdyFrame> | |
| 2670 stream2_syn(spdy_util_.ConstructSpdyPush(NULL, | |
| 2671 0, | |
| 2672 2, | |
| 2673 1, | |
| 2674 "http://www.google.com/foo.dat")); | |
| 2675 const char kPushedData[] = "pushed"; | |
| 2676 scoped_ptr<SpdyFrame> stream2_body( | |
| 2677 spdy_util_.ConstructSpdyBodyFrame( | |
| 2678 2, kPushedData, strlen(kPushedData), true)); | |
| 2679 MockRead reads[] = { | |
| 2680 CreateMockRead(*stream2_syn, 2), | |
| 2681 CreateMockRead(*stream1_reply, 3), | |
| 2682 CreateMockRead(*stream1_body, 4, SYNCHRONOUS), | |
| 2683 CreateMockRead(*stream2_body, 5), | |
| 2684 MockRead(ASYNC, ERR_IO_PENDING, 6), // Force a pause | |
| 2685 }; | |
| 2686 | |
| 2687 HttpResponseInfo response; | |
| 2688 HttpResponseInfo response2; | |
| 2689 std::string expected_push_result("pushed"); | |
| 2690 OrderedSocketData data(reads, arraysize(reads), | |
| 2691 writes, arraysize(writes)); | |
| 2692 RunServerPushTest(&data, | |
| 2693 &response, | |
| 2694 &response2, | |
| 2695 expected_push_result); | |
| 2696 | |
| 2697 // Verify the SYN_REPLY. | |
| 2698 EXPECT_TRUE(response.headers.get() != NULL); | |
| 2699 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine()); | |
| 2700 | |
| 2701 // Verify the pushed stream. | |
| 2702 EXPECT_TRUE(response2.headers.get() != NULL); | |
| 2703 EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine()); | |
| 2704 } | |
| 2705 | |
| 2706 TEST_P(SpdyNetworkTransactionTest, ServerPushSingleDataFrame2) { | |
| 2707 scoped_ptr<SpdyFrame> stream1_syn( | |
| 2708 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true)); | |
| 2709 MockWrite writes[] = { CreateMockWrite(*stream1_syn, 1), }; | |
| 2710 | |
| 2711 scoped_ptr<SpdyFrame> | |
| 2712 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); | |
| 2713 scoped_ptr<SpdyFrame> | |
| 2714 stream2_syn(spdy_util_.ConstructSpdyPush(NULL, | |
| 2715 0, | |
| 2716 2, | |
| 2717 1, | |
| 2718 "http://www.google.com/foo.dat")); | |
| 2719 const char kPushedData[] = "pushed"; | |
| 2720 scoped_ptr<SpdyFrame> stream2_body( | |
| 2721 spdy_util_.ConstructSpdyBodyFrame( | |
| 2722 2, kPushedData, strlen(kPushedData), true)); | |
| 2723 scoped_ptr<SpdyFrame> | |
| 2724 stream1_body(spdy_util_.ConstructSpdyBodyFrame(1, true)); | |
| 2725 MockRead reads[] = { | |
| 2726 CreateMockRead(*stream1_reply, 2), | |
| 2727 CreateMockRead(*stream2_syn, 3), | |
| 2728 CreateMockRead(*stream2_body, 4), | |
| 2729 CreateMockRead(*stream1_body, 5, SYNCHRONOUS), | |
| 2730 MockRead(ASYNC, ERR_IO_PENDING, 6), // Force a pause | |
| 2731 }; | |
| 2732 | |
| 2733 HttpResponseInfo response; | |
| 2734 HttpResponseInfo response2; | |
| 2735 std::string expected_push_result("pushed"); | |
| 2736 OrderedSocketData data(reads, arraysize(reads), | |
| 2737 writes, arraysize(writes)); | |
| 2738 RunServerPushTest(&data, | |
| 2739 &response, | |
| 2740 &response2, | |
| 2741 expected_push_result); | |
| 2742 | |
| 2743 // Verify the SYN_REPLY. | |
| 2744 EXPECT_TRUE(response.headers.get() != NULL); | |
| 2745 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine()); | |
| 2746 | |
| 2747 // Verify the pushed stream. | |
| 2748 EXPECT_TRUE(response2.headers.get() != NULL); | |
| 2749 EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine()); | |
| 2750 } | |
| 2751 | |
| 2752 TEST_P(SpdyNetworkTransactionTest, ServerPushServerAborted) { | |
| 2753 scoped_ptr<SpdyFrame> stream1_syn( | |
| 2754 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true)); | |
| 2755 scoped_ptr<SpdyFrame> stream1_body( | |
| 2756 spdy_util_.ConstructSpdyBodyFrame(1, true)); | |
| 2757 MockWrite writes[] = { | |
| 2758 CreateMockWrite(*stream1_syn, 1), | |
| 2759 }; | |
| 2760 | |
| 2761 scoped_ptr<SpdyFrame> | |
| 2762 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); | |
| 2763 scoped_ptr<SpdyFrame> | |
| 2764 stream2_syn(spdy_util_.ConstructSpdyPush(NULL, | |
| 2765 0, | |
| 2766 2, | |
| 2767 1, | |
| 2768 "http://www.google.com/foo.dat")); | |
| 2769 scoped_ptr<SpdyFrame> stream2_rst( | |
| 2770 spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_PROTOCOL_ERROR)); | |
| 2771 MockRead reads[] = { | |
| 2772 CreateMockRead(*stream1_reply, 2), | |
| 2773 CreateMockRead(*stream2_syn, 3), | |
| 2774 CreateMockRead(*stream2_rst, 4), | |
| 2775 CreateMockRead(*stream1_body, 5, SYNCHRONOUS), | |
| 2776 MockRead(ASYNC, ERR_IO_PENDING, 6), // Force a pause | |
| 2777 }; | |
| 2778 | |
| 2779 OrderedSocketData data(reads, arraysize(reads), | |
| 2780 writes, arraysize(writes)); | |
| 2781 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY, | |
| 2782 BoundNetLog(), GetParam(), NULL); | |
| 2783 | |
| 2784 helper.RunPreTestSetup(); | |
| 2785 helper.AddData(&data); | |
| 2786 | |
| 2787 HttpNetworkTransaction* trans = helper.trans(); | |
| 2788 | |
| 2789 // Start the transaction with basic parameters. | |
| 2790 TestCompletionCallback callback; | |
| 2791 int rv = trans->Start( | |
| 2792 &CreateGetRequest(), callback.callback(), BoundNetLog()); | |
| 2793 EXPECT_EQ(ERR_IO_PENDING, rv); | |
| 2794 rv = callback.WaitForResult(); | |
| 2795 EXPECT_EQ(OK, rv); | |
| 2796 | |
| 2797 // Verify that we consumed all test data. | |
| 2798 EXPECT_TRUE(data.at_read_eof()) << "Read count: " | |
| 2799 << data.read_count() | |
| 2800 << " Read index: " | |
| 2801 << data.read_index(); | |
| 2802 EXPECT_TRUE(data.at_write_eof()) << "Write count: " | |
| 2803 << data.write_count() | |
| 2804 << " Write index: " | |
| 2805 << data.write_index(); | |
| 2806 | |
| 2807 // Verify the SYN_REPLY. | |
| 2808 HttpResponseInfo response = *trans->GetResponseInfo(); | |
| 2809 EXPECT_TRUE(response.headers.get() != NULL); | |
| 2810 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine()); | |
| 2811 } | |
| 2812 | |
| 2813 // Verify that we don't leak streams and that we properly send a reset | |
| 2814 // if the server pushes the same stream twice. | |
| 2815 TEST_P(SpdyNetworkTransactionTest, ServerPushDuplicate) { | |
| 2816 scoped_ptr<SpdyFrame> stream1_syn( | |
| 2817 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true)); | |
| 2818 scoped_ptr<SpdyFrame> stream1_body( | |
| 2819 spdy_util_.ConstructSpdyBodyFrame(1, true)); | |
| 2820 scoped_ptr<SpdyFrame> stream3_rst( | |
| 2821 spdy_util_.ConstructSpdyRstStream(4, RST_STREAM_PROTOCOL_ERROR)); | |
| 2822 MockWrite writes[] = { | |
| 2823 CreateMockWrite(*stream1_syn, 1), | |
| 2824 CreateMockWrite(*stream3_rst, 5), | |
| 2825 }; | |
| 2826 | |
| 2827 scoped_ptr<SpdyFrame> | |
| 2828 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); | |
| 2829 scoped_ptr<SpdyFrame> | |
| 2830 stream2_syn(spdy_util_.ConstructSpdyPush(NULL, | |
| 2831 0, | |
| 2832 2, | |
| 2833 1, | |
| 2834 "http://www.google.com/foo.dat")); | |
| 2835 const char kPushedData[] = "pushed"; | |
| 2836 scoped_ptr<SpdyFrame> stream2_body( | |
| 2837 spdy_util_.ConstructSpdyBodyFrame( | |
| 2838 2, kPushedData, strlen(kPushedData), true)); | |
| 2839 scoped_ptr<SpdyFrame> | |
| 2840 stream3_syn(spdy_util_.ConstructSpdyPush(NULL, | |
| 2841 0, | |
| 2842 4, | |
| 2843 1, | |
| 2844 "http://www.google.com/foo.dat")); | |
| 2845 MockRead reads[] = { | |
| 2846 CreateMockRead(*stream1_reply, 2), | |
| 2847 CreateMockRead(*stream2_syn, 3), | |
| 2848 CreateMockRead(*stream3_syn, 4), | |
| 2849 CreateMockRead(*stream1_body, 6, SYNCHRONOUS), | |
| 2850 CreateMockRead(*stream2_body, 7), | |
| 2851 MockRead(ASYNC, ERR_IO_PENDING, 8), // Force a pause | |
| 2852 }; | |
| 2853 | |
| 2854 HttpResponseInfo response; | |
| 2855 HttpResponseInfo response2; | |
| 2856 std::string expected_push_result("pushed"); | |
| 2857 OrderedSocketData data(reads, arraysize(reads), | |
| 2858 writes, arraysize(writes)); | |
| 2859 RunServerPushTest(&data, | |
| 2860 &response, | |
| 2861 &response2, | |
| 2862 expected_push_result); | |
| 2863 | |
| 2864 // Verify the SYN_REPLY. | |
| 2865 EXPECT_TRUE(response.headers.get() != NULL); | |
| 2866 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine()); | |
| 2867 | |
| 2868 // Verify the pushed stream. | |
| 2869 EXPECT_TRUE(response2.headers.get() != NULL); | |
| 2870 EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine()); | |
| 2871 } | |
| 2872 | |
| 2873 TEST_P(SpdyNetworkTransactionTest, ServerPushMultipleDataFrame) { | |
| 2874 scoped_ptr<SpdyFrame> stream1_syn( | |
| 2875 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true)); | |
| 2876 scoped_ptr<SpdyFrame> stream1_body( | |
| 2877 spdy_util_.ConstructSpdyBodyFrame(1, true)); | |
| 2878 MockWrite writes[] = { | |
| 2879 CreateMockWrite(*stream1_syn, 1), | |
| 2880 }; | |
| 2881 | |
| 2882 scoped_ptr<SpdyFrame> | |
| 2883 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); | |
| 2884 scoped_ptr<SpdyFrame> | |
| 2885 stream2_syn(spdy_util_.ConstructSpdyPush(NULL, | |
| 2886 0, | |
| 2887 2, | |
| 2888 1, | |
| 2889 "http://www.google.com/foo.dat")); | |
| 2890 static const char kPushedData[] = "pushed my darling hello my baby"; | |
| 2891 scoped_ptr<SpdyFrame> stream2_body_base( | |
| 2892 spdy_util_.ConstructSpdyBodyFrame( | |
| 2893 2, kPushedData, strlen(kPushedData), true)); | |
| 2894 const size_t kChunkSize = strlen(kPushedData) / 4; | |
| 2895 scoped_ptr<SpdyFrame> stream2_body1( | |
| 2896 new SpdyFrame(stream2_body_base->data(), kChunkSize, false)); | |
| 2897 scoped_ptr<SpdyFrame> stream2_body2( | |
| 2898 new SpdyFrame(stream2_body_base->data() + kChunkSize, kChunkSize, false)); | |
| 2899 scoped_ptr<SpdyFrame> stream2_body3( | |
| 2900 new SpdyFrame(stream2_body_base->data() + 2 * kChunkSize, | |
| 2901 kChunkSize, false)); | |
| 2902 scoped_ptr<SpdyFrame> stream2_body4( | |
| 2903 new SpdyFrame(stream2_body_base->data() + 3 * kChunkSize, | |
| 2904 stream2_body_base->size() - 3 * kChunkSize, false)); | |
| 2905 MockRead reads[] = { | |
| 2906 CreateMockRead(*stream1_reply, 2), | |
| 2907 CreateMockRead(*stream2_syn, 3), | |
| 2908 CreateMockRead(*stream2_body1, 4), | |
| 2909 CreateMockRead(*stream2_body2, 5), | |
| 2910 CreateMockRead(*stream2_body3, 6), | |
| 2911 CreateMockRead(*stream2_body4, 7), | |
| 2912 CreateMockRead(*stream1_body, 8, SYNCHRONOUS), | |
| 2913 MockRead(ASYNC, ERR_IO_PENDING, 9), // Force a pause | |
| 2914 }; | |
| 2915 | |
| 2916 HttpResponseInfo response; | |
| 2917 HttpResponseInfo response2; | |
| 2918 std::string expected_push_result("pushed my darling hello my baby"); | |
| 2919 OrderedSocketData data(reads, arraysize(reads), | |
| 2920 writes, arraysize(writes)); | |
| 2921 RunServerPushTest(&data, &response, &response2, kPushedData); | |
| 2922 | |
| 2923 // Verify the SYN_REPLY. | |
| 2924 EXPECT_TRUE(response.headers.get() != NULL); | |
| 2925 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine()); | |
| 2926 | |
| 2927 // Verify the pushed stream. | |
| 2928 EXPECT_TRUE(response2.headers.get() != NULL); | |
| 2929 EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine()); | |
| 2930 } | |
| 2931 | |
| 2932 TEST_P(SpdyNetworkTransactionTest, ServerPushMultipleDataFrameInterrupted) { | |
| 2933 scoped_ptr<SpdyFrame> stream1_syn( | |
| 2934 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true)); | |
| 2935 scoped_ptr<SpdyFrame> stream1_body( | |
| 3352 spdy_util_.ConstructSpdyBodyFrame(1, true)); | 2936 spdy_util_.ConstructSpdyBodyFrame(1, true)); |
| 3353 MockWrite writes[] = { | 2937 MockWrite writes[] = { |
| 3354 CreateMockWrite(*stream1_syn, 1), | 2938 CreateMockWrite(*stream1_syn, 1), |
| 3355 }; | 2939 }; |
| 3356 | 2940 |
| 3357 scoped_ptr<SpdyFrame> | 2941 scoped_ptr<SpdyFrame> |
| 3358 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); | 2942 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); |
| 3359 scoped_ptr<SpdyFrame> | 2943 scoped_ptr<SpdyFrame> |
| 3360 stream2_syn(spdy_util_.ConstructSpdyPush(NULL, | 2944 stream2_syn(spdy_util_.ConstructSpdyPush(NULL, |
| 3361 0, | 2945 0, |
| 3362 2, | 2946 2, |
| 3363 1, | 2947 1, |
| 3364 "http://www.google.com/foo.dat")); | 2948 "http://www.google.com/foo.dat")); |
| 2949 static const char kPushedData[] = "pushed my darling hello my baby"; | |
| 2950 scoped_ptr<SpdyFrame> stream2_body_base( | |
| 2951 spdy_util_.ConstructSpdyBodyFrame( | |
| 2952 2, kPushedData, strlen(kPushedData), true)); | |
| 2953 const size_t kChunkSize = strlen(kPushedData) / 4; | |
| 2954 scoped_ptr<SpdyFrame> stream2_body1( | |
| 2955 new SpdyFrame(stream2_body_base->data(), kChunkSize, false)); | |
| 2956 scoped_ptr<SpdyFrame> stream2_body2( | |
| 2957 new SpdyFrame(stream2_body_base->data() + kChunkSize, kChunkSize, false)); | |
| 2958 scoped_ptr<SpdyFrame> stream2_body3( | |
| 2959 new SpdyFrame(stream2_body_base->data() + 2 * kChunkSize, | |
| 2960 kChunkSize, false)); | |
| 2961 scoped_ptr<SpdyFrame> stream2_body4( | |
| 2962 new SpdyFrame(stream2_body_base->data() + 3 * kChunkSize, | |
| 2963 stream2_body_base->size() - 3 * kChunkSize, false)); | |
| 3365 MockRead reads[] = { | 2964 MockRead reads[] = { |
| 3366 CreateMockRead(*stream1_reply, 2), | 2965 CreateMockRead(*stream1_reply, 2), |
| 3367 CreateMockRead(*stream2_syn, 3), | 2966 CreateMockRead(*stream2_syn, 3), |
| 3368 CreateMockRead(*stream1_body, 4, SYNCHRONOUS), | 2967 CreateMockRead(*stream2_body1, 4), |
| 3369 MockRead(ASYNC, reinterpret_cast<const char*>(kPushBodyFrame), | 2968 CreateMockRead(*stream2_body2, 5), |
| 3370 arraysize(kPushBodyFrame), 5), | |
| 3371 MockRead(ASYNC, ERR_IO_PENDING, 6), // Force a pause | 2969 MockRead(ASYNC, ERR_IO_PENDING, 6), // Force a pause |
| 2970 CreateMockRead(*stream2_body3, 7), | |
| 2971 CreateMockRead(*stream2_body4, 8), | |
| 2972 CreateMockRead(*stream1_body.get(), 9, SYNCHRONOUS), | |
| 2973 MockRead(ASYNC, ERR_IO_PENDING, 10) // Force a pause. | |
| 3372 }; | 2974 }; |
| 3373 | 2975 |
| 3374 HttpResponseInfo response; | 2976 HttpResponseInfo response; |
| 3375 HttpResponseInfo response2; | 2977 HttpResponseInfo response2; |
| 3376 std::string expected_push_result("pushed"); | |
| 3377 OrderedSocketData data(reads, arraysize(reads), | 2978 OrderedSocketData data(reads, arraysize(reads), |
| 3378 writes, arraysize(writes)); | 2979 writes, arraysize(writes)); |
| 3379 RunServerPushTest(&data, | 2980 RunServerPushTest(&data, &response, &response2, kPushedData); |
| 3380 &response, | |
| 3381 &response2, | |
| 3382 expected_push_result); | |
| 3383 | 2981 |
| 3384 // Verify the SYN_REPLY. | 2982 // Verify the SYN_REPLY. |
| 3385 EXPECT_TRUE(response.headers.get() != NULL); | 2983 EXPECT_TRUE(response.headers.get() != NULL); |
| 3386 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine()); | 2984 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine()); |
| 3387 | 2985 |
| 3388 // Verify the pushed stream. | 2986 // Verify the pushed stream. |
| 3389 EXPECT_TRUE(response2.headers.get() != NULL); | 2987 EXPECT_TRUE(response2.headers.get() != NULL); |
| 3390 EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine()); | 2988 EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine()); |
| 3391 } | 2989 } |
| 3392 | 2990 |
| 3393 TEST_P(SpdyNetworkTransactionTest, ServerPushBeforeSynReply) { | 2991 TEST_P(SpdyNetworkTransactionTest, ServerPushInvalidAssociatedStreamID0) { |
| 3394 if (GetParam().protocol > kProtoSPDY3) | |
| 3395 return; | |
| 3396 | |
| 3397 static const unsigned char kPushBodyFrame[] = { | |
| 3398 0x00, 0x00, 0x00, 0x02, // header, ID | |
| 3399 0x01, 0x00, 0x00, 0x06, // FIN, length | |
| 3400 'p', 'u', 's', 'h', 'e', 'd' // "pushed" | |
| 3401 }; | |
| 3402 scoped_ptr<SpdyFrame> stream1_syn( | 2992 scoped_ptr<SpdyFrame> stream1_syn( |
| 3403 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true)); | 2993 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true)); |
| 3404 scoped_ptr<SpdyFrame> stream1_body( | 2994 scoped_ptr<SpdyFrame> stream1_body( |
| 3405 spdy_util_.ConstructSpdyBodyFrame(1, true)); | 2995 spdy_util_.ConstructSpdyBodyFrame(1, true)); |
| 2996 scoped_ptr<SpdyFrame> stream2_rst( | |
| 2997 spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_REFUSED_STREAM)); | |
| 3406 MockWrite writes[] = { | 2998 MockWrite writes[] = { |
| 3407 CreateMockWrite(*stream1_syn, 1), | 2999 CreateMockWrite(*stream1_syn, 1), |
| 3000 CreateMockWrite(*stream2_rst, 4), | |
| 3408 }; | 3001 }; |
| 3409 | 3002 |
| 3410 scoped_ptr<SpdyFrame> | 3003 scoped_ptr<SpdyFrame> |
| 3411 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); | 3004 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); |
| 3412 scoped_ptr<SpdyFrame> | 3005 scoped_ptr<SpdyFrame> |
| 3413 stream2_syn(spdy_util_.ConstructSpdyPush(NULL, | 3006 stream2_syn(spdy_util_.ConstructSpdyPush(NULL, |
| 3414 0, | 3007 0, |
| 3415 2, | 3008 2, |
| 3416 1, | 3009 0, |
| 3417 "http://www.google.com/foo.dat")); | 3010 "http://www.google.com/foo.dat")); |
| 3418 MockRead reads[] = { | 3011 MockRead reads[] = { |
| 3419 CreateMockRead(*stream2_syn, 2), | |
| 3420 CreateMockRead(*stream1_reply, 3), | |
| 3421 CreateMockRead(*stream1_body, 4, SYNCHRONOUS), | |
| 3422 MockRead(ASYNC, reinterpret_cast<const char*>(kPushBodyFrame), | |
| 3423 arraysize(kPushBodyFrame), 5), | |
| 3424 MockRead(ASYNC, ERR_IO_PENDING, 6), // Force a pause | |
| 3425 }; | |
| 3426 | |
| 3427 HttpResponseInfo response; | |
| 3428 HttpResponseInfo response2; | |
| 3429 std::string expected_push_result("pushed"); | |
| 3430 OrderedSocketData data(reads, arraysize(reads), | |
| 3431 writes, arraysize(writes)); | |
| 3432 RunServerPushTest(&data, | |
| 3433 &response, | |
| 3434 &response2, | |
| 3435 expected_push_result); | |
| 3436 | |
| 3437 // Verify the SYN_REPLY. | |
| 3438 EXPECT_TRUE(response.headers.get() != NULL); | |
| 3439 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine()); | |
| 3440 | |
| 3441 // Verify the pushed stream. | |
| 3442 EXPECT_TRUE(response2.headers.get() != NULL); | |
| 3443 EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine()); | |
| 3444 } | |
| 3445 | |
| 3446 TEST_P(SpdyNetworkTransactionTest, ServerPushSingleDataFrame2) { | |
| 3447 if (GetParam().protocol > kProtoSPDY3) | |
| 3448 return; | |
| 3449 | |
| 3450 static const unsigned char kPushBodyFrame[] = { | |
| 3451 0x00, 0x00, 0x00, 0x02, // header, ID | |
| 3452 0x01, 0x00, 0x00, 0x06, // FIN, length | |
| 3453 'p', 'u', 's', 'h', 'e', 'd' // "pushed" | |
| 3454 }; | |
| 3455 scoped_ptr<SpdyFrame> stream1_syn( | |
| 3456 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true)); | |
| 3457 MockWrite writes[] = { CreateMockWrite(*stream1_syn, 1), }; | |
| 3458 | |
| 3459 scoped_ptr<SpdyFrame> | |
| 3460 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); | |
| 3461 scoped_ptr<SpdyFrame> | |
| 3462 stream2_syn(spdy_util_.ConstructSpdyPush(NULL, | |
| 3463 0, | |
| 3464 2, | |
| 3465 1, | |
| 3466 "http://www.google.com/foo.dat")); | |
| 3467 scoped_ptr<SpdyFrame> | |
| 3468 stream1_body(spdy_util_.ConstructSpdyBodyFrame(1, true)); | |
| 3469 MockRead reads[] = { | |
| 3470 CreateMockRead(*stream1_reply, 2), | 3012 CreateMockRead(*stream1_reply, 2), |
| 3471 CreateMockRead(*stream2_syn, 3), | 3013 CreateMockRead(*stream2_syn, 3), |
| 3472 MockRead(ASYNC, reinterpret_cast<const char*>(kPushBodyFrame), | 3014 CreateMockRead(*stream1_body, 4), |
| 3473 arraysize(kPushBodyFrame), 5), | 3015 MockRead(ASYNC, ERR_IO_PENDING, 5) // Force a pause |
| 3474 CreateMockRead(*stream1_body, 4, SYNCHRONOUS), | |
| 3475 MockRead(ASYNC, ERR_IO_PENDING, 6), // Force a pause | |
| 3476 }; | |
| 3477 | |
| 3478 HttpResponseInfo response; | |
| 3479 HttpResponseInfo response2; | |
| 3480 std::string expected_push_result("pushed"); | |
| 3481 OrderedSocketData data(reads, arraysize(reads), | |
| 3482 writes, arraysize(writes)); | |
| 3483 RunServerPushTest(&data, | |
| 3484 &response, | |
| 3485 &response2, | |
| 3486 expected_push_result); | |
| 3487 | |
| 3488 // Verify the SYN_REPLY. | |
| 3489 EXPECT_TRUE(response.headers.get() != NULL); | |
| 3490 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine()); | |
| 3491 | |
| 3492 // Verify the pushed stream. | |
| 3493 EXPECT_TRUE(response2.headers.get() != NULL); | |
| 3494 EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine()); | |
| 3495 } | |
| 3496 | |
| 3497 TEST_P(SpdyNetworkTransactionTest, ServerPushServerAborted) { | |
| 3498 if (GetParam().protocol > kProtoSPDY3) | |
| 3499 return; | |
| 3500 | |
| 3501 scoped_ptr<SpdyFrame> stream1_syn( | |
| 3502 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true)); | |
| 3503 scoped_ptr<SpdyFrame> stream1_body( | |
| 3504 spdy_util_.ConstructSpdyBodyFrame(1, true)); | |
| 3505 MockWrite writes[] = { | |
| 3506 CreateMockWrite(*stream1_syn, 1), | |
| 3507 }; | |
| 3508 | |
| 3509 scoped_ptr<SpdyFrame> | |
| 3510 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); | |
| 3511 scoped_ptr<SpdyFrame> | |
| 3512 stream2_syn(spdy_util_.ConstructSpdyPush(NULL, | |
| 3513 0, | |
| 3514 2, | |
| 3515 1, | |
| 3516 "http://www.google.com/foo.dat")); | |
| 3517 scoped_ptr<SpdyFrame> stream2_rst( | |
| 3518 spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_PROTOCOL_ERROR)); | |
| 3519 MockRead reads[] = { | |
| 3520 CreateMockRead(*stream1_reply, 2), | |
| 3521 CreateMockRead(*stream2_syn, 3), | |
| 3522 CreateMockRead(*stream2_rst, 4), | |
| 3523 CreateMockRead(*stream1_body, 5, SYNCHRONOUS), | |
| 3524 MockRead(ASYNC, ERR_IO_PENDING, 6), // Force a pause | |
| 3525 }; | 3016 }; |
| 3526 | 3017 |
| 3527 OrderedSocketData data(reads, arraysize(reads), | 3018 OrderedSocketData data(reads, arraysize(reads), |
| 3528 writes, arraysize(writes)); | 3019 writes, arraysize(writes)); |
| 3529 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY, | 3020 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY, |
| 3530 BoundNetLog(), GetParam(), NULL); | 3021 BoundNetLog(), GetParam(), NULL); |
| 3531 | 3022 |
| 3532 helper.RunPreTestSetup(); | 3023 helper.RunPreTestSetup(); |
| 3533 helper.AddData(&data); | 3024 helper.AddData(&data); |
| 3534 | 3025 |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 3551 << data.write_count() | 3042 << data.write_count() |
| 3552 << " Write index: " | 3043 << " Write index: " |
| 3553 << data.write_index(); | 3044 << data.write_index(); |
| 3554 | 3045 |
| 3555 // Verify the SYN_REPLY. | 3046 // Verify the SYN_REPLY. |
| 3556 HttpResponseInfo response = *trans->GetResponseInfo(); | 3047 HttpResponseInfo response = *trans->GetResponseInfo(); |
| 3557 EXPECT_TRUE(response.headers.get() != NULL); | 3048 EXPECT_TRUE(response.headers.get() != NULL); |
| 3558 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine()); | 3049 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine()); |
| 3559 } | 3050 } |
| 3560 | 3051 |
| 3561 TEST_P(SpdyNetworkTransactionTest, ServerPushDuplicate) { | 3052 TEST_P(SpdyNetworkTransactionTest, ServerPushInvalidAssociatedStreamID9) { |
| 3562 if (GetParam().protocol > kProtoSPDY3) | |
| 3563 return; | |
| 3564 | |
| 3565 // Verify that we don't leak streams and that we properly send a reset | |
| 3566 // if the server pushes the same stream twice. | |
| 3567 static const unsigned char kPushBodyFrame[] = { | |
| 3568 0x00, 0x00, 0x00, 0x02, // header, ID | |
| 3569 0x01, 0x00, 0x00, 0x06, // FIN, length | |
| 3570 'p', 'u', 's', 'h', 'e', 'd' // "pushed" | |
| 3571 }; | |
| 3572 | |
| 3573 scoped_ptr<SpdyFrame> stream1_syn( | |
| 3574 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true)); | |
| 3575 scoped_ptr<SpdyFrame> stream1_body( | |
| 3576 spdy_util_.ConstructSpdyBodyFrame(1, true)); | |
| 3577 scoped_ptr<SpdyFrame> stream3_rst( | |
| 3578 spdy_util_.ConstructSpdyRstStream(4, RST_STREAM_PROTOCOL_ERROR)); | |
| 3579 MockWrite writes[] = { | |
| 3580 CreateMockWrite(*stream1_syn, 1), | |
| 3581 CreateMockWrite(*stream3_rst, 5), | |
| 3582 }; | |
| 3583 | |
| 3584 scoped_ptr<SpdyFrame> | |
| 3585 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); | |
| 3586 scoped_ptr<SpdyFrame> | |
| 3587 stream2_syn(spdy_util_.ConstructSpdyPush(NULL, | |
| 3588 0, | |
| 3589 2, | |
| 3590 1, | |
| 3591 "http://www.google.com/foo.dat")); | |
| 3592 scoped_ptr<SpdyFrame> | |
| 3593 stream3_syn(spdy_util_.ConstructSpdyPush(NULL, | |
| 3594 0, | |
| 3595 4, | |
| 3596 1, | |
| 3597 "http://www.google.com/foo.dat")); | |
| 3598 MockRead reads[] = { | |
| 3599 CreateMockRead(*stream1_reply, 2), | |
| 3600 CreateMockRead(*stream2_syn, 3), | |
| 3601 CreateMockRead(*stream3_syn, 4), | |
| 3602 CreateMockRead(*stream1_body, 6, SYNCHRONOUS), | |
| 3603 MockRead(ASYNC, reinterpret_cast<const char*>(kPushBodyFrame), | |
| 3604 arraysize(kPushBodyFrame), 7), | |
| 3605 MockRead(ASYNC, ERR_IO_PENDING, 8), // Force a pause | |
| 3606 }; | |
| 3607 | |
| 3608 HttpResponseInfo response; | |
| 3609 HttpResponseInfo response2; | |
| 3610 std::string expected_push_result("pushed"); | |
| 3611 OrderedSocketData data(reads, arraysize(reads), | |
| 3612 writes, arraysize(writes)); | |
| 3613 RunServerPushTest(&data, | |
| 3614 &response, | |
| 3615 &response2, | |
| 3616 expected_push_result); | |
| 3617 | |
| 3618 // Verify the SYN_REPLY. | |
| 3619 EXPECT_TRUE(response.headers.get() != NULL); | |
| 3620 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine()); | |
| 3621 | |
| 3622 // Verify the pushed stream. | |
| 3623 EXPECT_TRUE(response2.headers.get() != NULL); | |
| 3624 EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine()); | |
| 3625 } | |
| 3626 | |
| 3627 TEST_P(SpdyNetworkTransactionTest, ServerPushMultipleDataFrame) { | |
| 3628 if (GetParam().protocol > kProtoSPDY3) | |
| 3629 return; | |
| 3630 | |
| 3631 static const unsigned char kPushBodyFrame1[] = { | |
| 3632 0x00, 0x00, 0x00, 0x02, // header, ID | |
| 3633 0x01, 0x00, 0x00, 0x1F, // FIN, length | |
| 3634 'p', 'u', 's', 'h', 'e', 'd' // "pushed" | |
| 3635 }; | |
| 3636 static const char kPushBodyFrame2[] = " my darling"; | |
| 3637 static const char kPushBodyFrame3[] = " hello"; | |
| 3638 static const char kPushBodyFrame4[] = " my baby"; | |
| 3639 | |
| 3640 scoped_ptr<SpdyFrame> stream1_syn( | |
| 3641 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true)); | |
| 3642 scoped_ptr<SpdyFrame> stream1_body( | |
| 3643 spdy_util_.ConstructSpdyBodyFrame(1, true)); | |
| 3644 MockWrite writes[] = { | |
| 3645 CreateMockWrite(*stream1_syn, 1), | |
| 3646 }; | |
| 3647 | |
| 3648 scoped_ptr<SpdyFrame> | |
| 3649 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); | |
| 3650 scoped_ptr<SpdyFrame> | |
| 3651 stream2_syn(spdy_util_.ConstructSpdyPush(NULL, | |
| 3652 0, | |
| 3653 2, | |
| 3654 1, | |
| 3655 "http://www.google.com/foo.dat")); | |
| 3656 MockRead reads[] = { | |
| 3657 CreateMockRead(*stream1_reply, 2), | |
| 3658 CreateMockRead(*stream2_syn, 3), | |
| 3659 MockRead(ASYNC, reinterpret_cast<const char*>(kPushBodyFrame1), | |
| 3660 arraysize(kPushBodyFrame1), 4), | |
| 3661 MockRead(ASYNC, reinterpret_cast<const char*>(kPushBodyFrame2), | |
| 3662 arraysize(kPushBodyFrame2) - 1, 5), | |
| 3663 MockRead(ASYNC, reinterpret_cast<const char*>(kPushBodyFrame3), | |
| 3664 arraysize(kPushBodyFrame3) - 1, 6), | |
| 3665 MockRead(ASYNC, reinterpret_cast<const char*>(kPushBodyFrame4), | |
| 3666 arraysize(kPushBodyFrame4) - 1, 7), | |
| 3667 CreateMockRead(*stream1_body, 8, SYNCHRONOUS), | |
| 3668 MockRead(ASYNC, ERR_IO_PENDING, 9), // Force a pause | |
| 3669 }; | |
| 3670 | |
| 3671 HttpResponseInfo response; | |
| 3672 HttpResponseInfo response2; | |
| 3673 std::string expected_push_result("pushed my darling hello my baby"); | |
| 3674 OrderedSocketData data(reads, arraysize(reads), | |
| 3675 writes, arraysize(writes)); | |
| 3676 RunServerPushTest(&data, | |
| 3677 &response, | |
| 3678 &response2, | |
| 3679 expected_push_result); | |
| 3680 | |
| 3681 // Verify the SYN_REPLY. | |
| 3682 EXPECT_TRUE(response.headers.get() != NULL); | |
| 3683 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine()); | |
| 3684 | |
| 3685 // Verify the pushed stream. | |
| 3686 EXPECT_TRUE(response2.headers.get() != NULL); | |
| 3687 EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine()); | |
| 3688 } | |
| 3689 | |
| 3690 TEST_P(SpdyNetworkTransactionTest, ServerPushMultipleDataFrameInterrupted) { | |
| 3691 if (GetParam().protocol > kProtoSPDY3) | |
| 3692 return; | |
| 3693 | |
| 3694 static const unsigned char kPushBodyFrame1[] = { | |
| 3695 0x00, 0x00, 0x00, 0x02, // header, ID | |
| 3696 0x01, 0x00, 0x00, 0x1F, // FIN, length | |
| 3697 'p', 'u', 's', 'h', 'e', 'd' // "pushed" | |
| 3698 }; | |
| 3699 static const char kPushBodyFrame2[] = " my darling"; | |
| 3700 static const char kPushBodyFrame3[] = " hello"; | |
| 3701 static const char kPushBodyFrame4[] = " my baby"; | |
| 3702 | |
| 3703 scoped_ptr<SpdyFrame> stream1_syn( | |
| 3704 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true)); | |
| 3705 scoped_ptr<SpdyFrame> stream1_body( | |
| 3706 spdy_util_.ConstructSpdyBodyFrame(1, true)); | |
| 3707 MockWrite writes[] = { | |
| 3708 CreateMockWrite(*stream1_syn, 1), | |
| 3709 }; | |
| 3710 | |
| 3711 scoped_ptr<SpdyFrame> | |
| 3712 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); | |
| 3713 scoped_ptr<SpdyFrame> | |
| 3714 stream2_syn(spdy_util_.ConstructSpdyPush(NULL, | |
| 3715 0, | |
| 3716 2, | |
| 3717 1, | |
| 3718 "http://www.google.com/foo.dat")); | |
| 3719 MockRead reads[] = { | |
| 3720 CreateMockRead(*stream1_reply, 2), | |
| 3721 CreateMockRead(*stream2_syn, 3), | |
| 3722 MockRead(ASYNC, reinterpret_cast<const char*>(kPushBodyFrame1), | |
| 3723 arraysize(kPushBodyFrame1), 4), | |
| 3724 MockRead(ASYNC, reinterpret_cast<const char*>(kPushBodyFrame2), | |
| 3725 arraysize(kPushBodyFrame2) - 1, 5), | |
| 3726 MockRead(ASYNC, ERR_IO_PENDING, 6), // Force a pause | |
| 3727 MockRead(ASYNC, reinterpret_cast<const char*>(kPushBodyFrame3), | |
| 3728 arraysize(kPushBodyFrame3) - 1, 7), | |
| 3729 MockRead(ASYNC, reinterpret_cast<const char*>(kPushBodyFrame4), | |
| 3730 arraysize(kPushBodyFrame4) - 1, 8), | |
| 3731 CreateMockRead(*stream1_body.get(), 9, SYNCHRONOUS), | |
| 3732 MockRead(ASYNC, ERR_IO_PENDING, 10) // Force a pause. | |
| 3733 }; | |
| 3734 | |
| 3735 HttpResponseInfo response; | |
| 3736 HttpResponseInfo response2; | |
| 3737 std::string expected_push_result("pushed my darling hello my baby"); | |
| 3738 OrderedSocketData data(reads, arraysize(reads), | |
| 3739 writes, arraysize(writes)); | |
| 3740 RunServerPushTest(&data, | |
| 3741 &response, | |
| 3742 &response2, | |
| 3743 expected_push_result); | |
| 3744 | |
| 3745 // Verify the SYN_REPLY. | |
| 3746 EXPECT_TRUE(response.headers.get() != NULL); | |
| 3747 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine()); | |
| 3748 | |
| 3749 // Verify the pushed stream. | |
| 3750 EXPECT_TRUE(response2.headers.get() != NULL); | |
| 3751 EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine()); | |
| 3752 } | |
| 3753 | |
| 3754 TEST_P(SpdyNetworkTransactionTest, ServerPushInvalidAssociatedStreamID0) { | |
| 3755 if (GetParam().protocol > kProtoSPDY3) | |
| 3756 return; | |
| 3757 | |
| 3758 scoped_ptr<SpdyFrame> stream1_syn( | 3053 scoped_ptr<SpdyFrame> stream1_syn( |
| 3759 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true)); | 3054 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true)); |
| 3760 scoped_ptr<SpdyFrame> stream1_body( | 3055 scoped_ptr<SpdyFrame> stream1_body( |
| 3761 spdy_util_.ConstructSpdyBodyFrame(1, true)); | 3056 spdy_util_.ConstructSpdyBodyFrame(1, true)); |
| 3762 scoped_ptr<SpdyFrame> stream2_rst( | 3057 scoped_ptr<SpdyFrame> stream2_rst( |
| 3763 spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_REFUSED_STREAM)); | 3058 spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_INVALID_STREAM)); |
| 3764 MockWrite writes[] = { | 3059 MockWrite writes[] = { |
| 3765 CreateMockWrite(*stream1_syn, 1), | 3060 CreateMockWrite(*stream1_syn, 1), |
| 3766 CreateMockWrite(*stream2_rst, 4), | 3061 CreateMockWrite(*stream2_rst, 4), |
| 3767 }; | 3062 }; |
| 3768 | 3063 |
| 3769 scoped_ptr<SpdyFrame> | 3064 scoped_ptr<SpdyFrame> |
| 3770 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); | 3065 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); |
| 3771 scoped_ptr<SpdyFrame> | 3066 scoped_ptr<SpdyFrame> |
| 3772 stream2_syn(spdy_util_.ConstructSpdyPush(NULL, | 3067 stream2_syn(spdy_util_.ConstructSpdyPush(NULL, |
| 3773 0, | 3068 0, |
| 3774 2, | 3069 2, |
| 3775 0, | 3070 9, |
| 3776 "http://www.google.com/foo.dat")); | 3071 "http://www.google.com/foo.dat")); |
| 3777 MockRead reads[] = { | 3072 MockRead reads[] = { |
| 3778 CreateMockRead(*stream1_reply, 2), | 3073 CreateMockRead(*stream1_reply, 2), |
| 3779 CreateMockRead(*stream2_syn, 3), | 3074 CreateMockRead(*stream2_syn, 3), |
| 3780 CreateMockRead(*stream1_body, 4), | 3075 CreateMockRead(*stream1_body, 4), |
| 3781 MockRead(ASYNC, ERR_IO_PENDING, 5) // Force a pause | 3076 MockRead(ASYNC, ERR_IO_PENDING, 5), // Force a pause |
| 3782 }; | 3077 }; |
| 3783 | 3078 |
| 3784 OrderedSocketData data(reads, arraysize(reads), | 3079 OrderedSocketData data(reads, arraysize(reads), |
| 3785 writes, arraysize(writes)); | 3080 writes, arraysize(writes)); |
| 3786 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY, | 3081 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY, |
| 3787 BoundNetLog(), GetParam(), NULL); | 3082 BoundNetLog(), GetParam(), NULL); |
| 3788 | 3083 |
| 3789 helper.RunPreTestSetup(); | 3084 helper.RunPreTestSetup(); |
| 3790 helper.AddData(&data); | 3085 helper.AddData(&data); |
| 3791 | 3086 |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 3808 << data.write_count() | 3103 << data.write_count() |
| 3809 << " Write index: " | 3104 << " Write index: " |
| 3810 << data.write_index(); | 3105 << data.write_index(); |
| 3811 | 3106 |
| 3812 // Verify the SYN_REPLY. | 3107 // Verify the SYN_REPLY. |
| 3813 HttpResponseInfo response = *trans->GetResponseInfo(); | 3108 HttpResponseInfo response = *trans->GetResponseInfo(); |
| 3814 EXPECT_TRUE(response.headers.get() != NULL); | 3109 EXPECT_TRUE(response.headers.get() != NULL); |
| 3815 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine()); | 3110 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine()); |
| 3816 } | 3111 } |
| 3817 | 3112 |
| 3818 TEST_P(SpdyNetworkTransactionTest, ServerPushInvalidAssociatedStreamID9) { | |
| 3819 if (GetParam().protocol > kProtoSPDY3) | |
| 3820 return; | |
| 3821 | |
| 3822 scoped_ptr<SpdyFrame> stream1_syn( | |
| 3823 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true)); | |
| 3824 scoped_ptr<SpdyFrame> stream1_body( | |
| 3825 spdy_util_.ConstructSpdyBodyFrame(1, true)); | |
| 3826 scoped_ptr<SpdyFrame> stream2_rst( | |
| 3827 spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_INVALID_STREAM)); | |
| 3828 MockWrite writes[] = { | |
| 3829 CreateMockWrite(*stream1_syn, 1), | |
| 3830 CreateMockWrite(*stream2_rst, 4), | |
| 3831 }; | |
| 3832 | |
| 3833 scoped_ptr<SpdyFrame> | |
| 3834 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); | |
| 3835 scoped_ptr<SpdyFrame> | |
| 3836 stream2_syn(spdy_util_.ConstructSpdyPush(NULL, | |
| 3837 0, | |
| 3838 2, | |
| 3839 9, | |
| 3840 "http://www.google.com/foo.dat")); | |
| 3841 MockRead reads[] = { | |
| 3842 CreateMockRead(*stream1_reply, 2), | |
| 3843 CreateMockRead(*stream2_syn, 3), | |
| 3844 CreateMockRead(*stream1_body, 4), | |
| 3845 MockRead(ASYNC, ERR_IO_PENDING, 5), // Force a pause | |
| 3846 }; | |
| 3847 | |
| 3848 OrderedSocketData data(reads, arraysize(reads), | |
| 3849 writes, arraysize(writes)); | |
| 3850 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY, | |
| 3851 BoundNetLog(), GetParam(), NULL); | |
| 3852 | |
| 3853 helper.RunPreTestSetup(); | |
| 3854 helper.AddData(&data); | |
| 3855 | |
| 3856 HttpNetworkTransaction* trans = helper.trans(); | |
| 3857 | |
| 3858 // Start the transaction with basic parameters. | |
| 3859 TestCompletionCallback callback; | |
| 3860 int rv = trans->Start( | |
| 3861 &CreateGetRequest(), callback.callback(), BoundNetLog()); | |
| 3862 EXPECT_EQ(ERR_IO_PENDING, rv); | |
| 3863 rv = callback.WaitForResult(); | |
| 3864 EXPECT_EQ(OK, rv); | |
| 3865 | |
| 3866 // Verify that we consumed all test data. | |
| 3867 EXPECT_TRUE(data.at_read_eof()) << "Read count: " | |
| 3868 << data.read_count() | |
| 3869 << " Read index: " | |
| 3870 << data.read_index(); | |
| 3871 EXPECT_TRUE(data.at_write_eof()) << "Write count: " | |
| 3872 << data.write_count() | |
| 3873 << " Write index: " | |
| 3874 << data.write_index(); | |
| 3875 | |
| 3876 // Verify the SYN_REPLY. | |
| 3877 HttpResponseInfo response = *trans->GetResponseInfo(); | |
| 3878 EXPECT_TRUE(response.headers.get() != NULL); | |
| 3879 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine()); | |
| 3880 } | |
| 3881 | |
| 3882 TEST_P(SpdyNetworkTransactionTest, ServerPushNoURL) { | 3113 TEST_P(SpdyNetworkTransactionTest, ServerPushNoURL) { |
| 3883 if (GetParam().protocol > kProtoSPDY3) | |
| 3884 return; | |
| 3885 | |
| 3886 scoped_ptr<SpdyFrame> stream1_syn( | 3114 scoped_ptr<SpdyFrame> stream1_syn( |
| 3887 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true)); | 3115 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true)); |
| 3888 scoped_ptr<SpdyFrame> stream1_body( | 3116 scoped_ptr<SpdyFrame> stream1_body( |
| 3889 spdy_util_.ConstructSpdyBodyFrame(1, true)); | 3117 spdy_util_.ConstructSpdyBodyFrame(1, true)); |
| 3890 scoped_ptr<SpdyFrame> stream2_rst( | 3118 scoped_ptr<SpdyFrame> stream2_rst( |
| 3891 spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_PROTOCOL_ERROR)); | 3119 spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_PROTOCOL_ERROR)); |
| 3892 MockWrite writes[] = { | 3120 MockWrite writes[] = { |
| 3893 CreateMockWrite(*stream1_syn, 1), | 3121 CreateMockWrite(*stream1_syn, 1), |
| 3894 CreateMockWrite(*stream2_rst, 4), | 3122 CreateMockWrite(*stream2_rst, 4), |
| 3895 }; | 3123 }; |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3945 | 3173 |
| 3946 // Verify the SYN_REPLY. | 3174 // Verify the SYN_REPLY. |
| 3947 HttpResponseInfo response = *trans->GetResponseInfo(); | 3175 HttpResponseInfo response = *trans->GetResponseInfo(); |
| 3948 EXPECT_TRUE(response.headers.get() != NULL); | 3176 EXPECT_TRUE(response.headers.get() != NULL); |
| 3949 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine()); | 3177 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine()); |
| 3950 } | 3178 } |
| 3951 | 3179 |
| 3952 // Verify that various SynReply headers parse correctly through the | 3180 // Verify that various SynReply headers parse correctly through the |
| 3953 // HTTP layer. | 3181 // HTTP layer. |
| 3954 TEST_P(SpdyNetworkTransactionTest, SynReplyHeaders) { | 3182 TEST_P(SpdyNetworkTransactionTest, SynReplyHeaders) { |
| 3955 if (GetParam().protocol > kProtoSPDY3) | |
| 3956 return; | |
| 3957 | |
| 3958 struct SynReplyHeadersTests { | 3183 struct SynReplyHeadersTests { |
| 3959 int num_headers; | 3184 int num_headers; |
| 3960 const char* extra_headers[5]; | 3185 const char* extra_headers[5]; |
| 3961 SpdyHeaderBlock expected_headers; | 3186 SpdyHeaderBlock expected_headers; |
| 3962 } test_cases[] = { | 3187 } test_cases[] = { |
| 3963 // This uses a multi-valued cookie header. | 3188 // This uses a multi-valued cookie header. |
| 3964 { 2, | 3189 { 2, |
| 3965 { "cookie", "val1", | 3190 { "cookie", "val1", |
| 3966 "cookie", "val2", // will get appended separated by NULL | 3191 "cookie", "val2", // will get appended separated by NULL |
| 3967 NULL | 3192 NULL |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4035 header_block[name] += value; | 3260 header_block[name] += value; |
| 4036 } | 3261 } |
| 4037 } | 3262 } |
| 4038 EXPECT_EQ(test_cases[i].expected_headers, header_block); | 3263 EXPECT_EQ(test_cases[i].expected_headers, header_block); |
| 4039 } | 3264 } |
| 4040 } | 3265 } |
| 4041 | 3266 |
| 4042 // Verify that various SynReply headers parse vary fields correctly | 3267 // Verify that various SynReply headers parse vary fields correctly |
| 4043 // through the HTTP layer, and the response matches the request. | 3268 // through the HTTP layer, and the response matches the request. |
| 4044 TEST_P(SpdyNetworkTransactionTest, SynReplyHeadersVary) { | 3269 TEST_P(SpdyNetworkTransactionTest, SynReplyHeadersVary) { |
| 4045 if (GetParam().protocol > kProtoSPDY3) | |
| 4046 return; | |
| 4047 | |
| 4048 static const SpdyHeaderInfo syn_reply_info = { | 3270 static const SpdyHeaderInfo syn_reply_info = { |
| 4049 SYN_REPLY, // Syn Reply | 3271 SYN_REPLY, // Syn Reply |
| 4050 1, // Stream ID | 3272 1, // Stream ID |
| 4051 0, // Associated Stream ID | 3273 0, // Associated Stream ID |
| 4052 ConvertRequestPriorityToSpdyPriority( | 3274 ConvertRequestPriorityToSpdyPriority( |
| 4053 LOWEST, spdy_util_.spdy_version()), | 3275 LOWEST, spdy_util_.spdy_version()), |
| 4054 kSpdyCredentialSlotUnused, | 3276 kSpdyCredentialSlotUnused, |
| 4055 CONTROL_FLAG_NONE, // Control Flags | 3277 CONTROL_FLAG_NONE, // Control Flags |
| 4056 false, // Compressed | 3278 false, // Compressed |
| 4057 RST_STREAM_INVALID, // Status | 3279 RST_STREAM_INVALID, // Status |
| (...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4207 test_cases[i].num_headers[1], | 3429 test_cases[i].num_headers[1], |
| 4208 &reply_headers); | 3430 &reply_headers); |
| 4209 std::string expected_reply = | 3431 std::string expected_reply = |
| 4210 spdy_util_.ConstructSpdyReplyString(reply_headers); | 3432 spdy_util_.ConstructSpdyReplyString(reply_headers); |
| 4211 EXPECT_EQ(expected_reply, lines) << i; | 3433 EXPECT_EQ(expected_reply, lines) << i; |
| 4212 } | 3434 } |
| 4213 } | 3435 } |
| 4214 | 3436 |
| 4215 // Verify that we don't crash on invalid SynReply responses. | 3437 // Verify that we don't crash on invalid SynReply responses. |
| 4216 TEST_P(SpdyNetworkTransactionTest, InvalidSynReply) { | 3438 TEST_P(SpdyNetworkTransactionTest, InvalidSynReply) { |
| 4217 if (GetParam().protocol > kProtoSPDY3) | |
| 4218 return; | |
| 4219 | |
| 4220 const SpdyHeaderInfo kSynStartHeader = { | 3439 const SpdyHeaderInfo kSynStartHeader = { |
| 4221 SYN_REPLY, // Kind = SynReply | 3440 SYN_REPLY, // Kind = SynReply |
| 4222 1, // Stream ID | 3441 1, // Stream ID |
| 4223 0, // Associated stream ID | 3442 0, // Associated stream ID |
| 4224 ConvertRequestPriorityToSpdyPriority( | 3443 ConvertRequestPriorityToSpdyPriority( |
| 4225 LOWEST, spdy_util_.spdy_version()), | 3444 LOWEST, spdy_util_.spdy_version()), |
| 4226 kSpdyCredentialSlotUnused, | 3445 kSpdyCredentialSlotUnused, |
| 4227 CONTROL_FLAG_NONE, // Control Flags | 3446 CONTROL_FLAG_NONE, // Control Flags |
| 4228 false, // Compressed | 3447 false, // Compressed |
| 4229 RST_STREAM_INVALID, // Status | 3448 RST_STREAM_INVALID, // Status |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4282 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY, | 3501 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY, |
| 4283 BoundNetLog(), GetParam(), NULL); | 3502 BoundNetLog(), GetParam(), NULL); |
| 4284 helper.RunToCompletion(&data); | 3503 helper.RunToCompletion(&data); |
| 4285 TransactionHelperResult out = helper.output(); | 3504 TransactionHelperResult out = helper.output(); |
| 4286 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, out.rv); | 3505 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, out.rv); |
| 4287 } | 3506 } |
| 4288 } | 3507 } |
| 4289 | 3508 |
| 4290 // Verify that we don't crash on some corrupt frames. | 3509 // Verify that we don't crash on some corrupt frames. |
| 4291 TEST_P(SpdyNetworkTransactionTest, CorruptFrameSessionError) { | 3510 TEST_P(SpdyNetworkTransactionTest, CorruptFrameSessionError) { |
| 4292 if (GetParam().protocol > kProtoSPDY3) | |
| 4293 return; | |
| 4294 | |
| 4295 // This is the length field that's too short. | 3511 // This is the length field that's too short. |
| 4296 scoped_ptr<SpdyFrame> syn_reply_wrong_length( | 3512 scoped_ptr<SpdyFrame> syn_reply_wrong_length( |
| 4297 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); | 3513 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); |
| 4298 size_t wrong_size = syn_reply_wrong_length->size() - 4; | |
| 4299 BufferedSpdyFramer framer(spdy_util_.spdy_version(), false); | 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; | |
| 4300 test::SetFrameLength(syn_reply_wrong_length.get(), | 3520 test::SetFrameLength(syn_reply_wrong_length.get(), |
| 4301 wrong_size - framer.GetControlFrameHeaderSize(), | 3521 wrong_size, |
| 4302 spdy_util_.spdy_version()); | 3522 spdy_util_.spdy_version()); |
| 4303 | 3523 |
| 4304 struct SynReplyTests { | 3524 struct SynReplyTests { |
| 4305 const SpdyFrame* syn_reply; | 3525 const SpdyFrame* syn_reply; |
| 4306 } test_cases[] = { | 3526 } test_cases[] = { |
| 4307 { syn_reply_wrong_length.get(), }, | 3527 { syn_reply_wrong_length.get(), }, |
| 4308 }; | 3528 }; |
| 4309 | 3529 |
| 4310 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_cases); ++i) { | 3530 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_cases); ++i) { |
| 4311 scoped_ptr<SpdyFrame> req( | 3531 scoped_ptr<SpdyFrame> req( |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 4325 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY, | 3545 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY, |
| 4326 BoundNetLog(), GetParam(), NULL); | 3546 BoundNetLog(), GetParam(), NULL); |
| 4327 helper.RunToCompletion(&data); | 3547 helper.RunToCompletion(&data); |
| 4328 TransactionHelperResult out = helper.output(); | 3548 TransactionHelperResult out = helper.output(); |
| 4329 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, out.rv); | 3549 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, out.rv); |
| 4330 } | 3550 } |
| 4331 } | 3551 } |
| 4332 | 3552 |
| 4333 // Test that we shutdown correctly on write errors. | 3553 // Test that we shutdown correctly on write errors. |
| 4334 TEST_P(SpdyNetworkTransactionTest, WriteError) { | 3554 TEST_P(SpdyNetworkTransactionTest, WriteError) { |
| 4335 if (GetParam().protocol > kProtoSPDY3) | |
| 4336 return; | |
| 4337 | |
| 4338 scoped_ptr<SpdyFrame> req( | 3555 scoped_ptr<SpdyFrame> req( |
| 4339 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true)); | 3556 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true)); |
| 4340 MockWrite writes[] = { | 3557 MockWrite writes[] = { |
| 4341 // We'll write 10 bytes successfully | 3558 // We'll write 10 bytes successfully |
| 4342 MockWrite(ASYNC, req->data(), 10), | 3559 MockWrite(ASYNC, req->data(), 10), |
| 4343 // Followed by ERROR! | 3560 // Followed by ERROR! |
| 4344 MockWrite(ASYNC, ERR_FAILED), | 3561 MockWrite(ASYNC, ERR_FAILED), |
| 4345 }; | 3562 }; |
| 4346 | 3563 |
| 4347 DelayedSocketData data(2, NULL, 0, | 3564 DelayedSocketData data(2, NULL, 0, |
| 4348 writes, arraysize(writes)); | 3565 writes, arraysize(writes)); |
| 4349 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY, | 3566 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY, |
| 4350 BoundNetLog(), GetParam(), NULL); | 3567 BoundNetLog(), GetParam(), NULL); |
| 4351 helper.RunToCompletion(&data); | 3568 helper.RunToCompletion(&data); |
| 4352 TransactionHelperResult out = helper.output(); | 3569 TransactionHelperResult out = helper.output(); |
| 4353 EXPECT_EQ(ERR_FAILED, out.rv); | 3570 EXPECT_EQ(ERR_FAILED, out.rv); |
| 4354 data.Reset(); | 3571 data.Reset(); |
| 4355 } | 3572 } |
| 4356 | 3573 |
| 4357 // Test that partial writes work. | 3574 // Test that partial writes work. |
| 4358 TEST_P(SpdyNetworkTransactionTest, PartialWrite) { | 3575 TEST_P(SpdyNetworkTransactionTest, PartialWrite) { |
| 4359 if (GetParam().protocol > kProtoSPDY3) | |
| 4360 return; | |
| 4361 | |
| 4362 // Chop the SYN_STREAM frame into 5 chunks. | 3576 // Chop the SYN_STREAM frame into 5 chunks. |
| 4363 scoped_ptr<SpdyFrame> req( | 3577 scoped_ptr<SpdyFrame> req( |
| 4364 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true)); | 3578 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true)); |
| 4365 const int kChunks = 5; | 3579 const int kChunks = 5; |
| 4366 scoped_ptr<MockWrite[]> writes(ChopWriteFrame(*req.get(), kChunks)); | 3580 scoped_ptr<MockWrite[]> writes(ChopWriteFrame(*req.get(), kChunks)); |
| 4367 | 3581 |
| 4368 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); | 3582 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); |
| 4369 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true)); | 3583 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true)); |
| 4370 MockRead reads[] = { | 3584 MockRead reads[] = { |
| 4371 CreateMockRead(*resp), | 3585 CreateMockRead(*resp), |
| 4372 CreateMockRead(*body), | 3586 CreateMockRead(*body), |
| 4373 MockRead(ASYNC, 0, 0) // EOF | 3587 MockRead(ASYNC, 0, 0) // EOF |
| 4374 }; | 3588 }; |
| 4375 | 3589 |
| 4376 DelayedSocketData data(kChunks, reads, arraysize(reads), | 3590 DelayedSocketData data(kChunks, reads, arraysize(reads), |
| 4377 writes.get(), kChunks); | 3591 writes.get(), kChunks); |
| 4378 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY, | 3592 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY, |
| 4379 BoundNetLog(), GetParam(), NULL); | 3593 BoundNetLog(), GetParam(), NULL); |
| 4380 helper.RunToCompletion(&data); | 3594 helper.RunToCompletion(&data); |
| 4381 TransactionHelperResult out = helper.output(); | 3595 TransactionHelperResult out = helper.output(); |
| 4382 EXPECT_EQ(OK, out.rv); | 3596 EXPECT_EQ(OK, out.rv); |
| 4383 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line); | 3597 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line); |
| 4384 EXPECT_EQ("hello!", out.response_data); | 3598 EXPECT_EQ("hello!", out.response_data); |
| 4385 } | 3599 } |
| 4386 | 3600 |
| 4387 // In this test, we enable compression, but get a uncompressed SynReply from | 3601 // In this test, we enable compression, but get a uncompressed SynReply from |
| 4388 // the server. Verify that teardown is all clean. | 3602 // the server. Verify that teardown is all clean. |
| 4389 TEST_P(SpdyNetworkTransactionTest, DecompressFailureOnSynReply) { | 3603 TEST_P(SpdyNetworkTransactionTest, DecompressFailureOnSynReply) { |
| 4390 if (GetParam().protocol > kProtoSPDY3) | |
| 4391 return; | |
| 4392 | |
| 4393 scoped_ptr<SpdyFrame> compressed( | 3604 scoped_ptr<SpdyFrame> compressed( |
| 4394 spdy_util_.ConstructSpdyGet(NULL, 0, true, 1, LOWEST, true)); | 3605 spdy_util_.ConstructSpdyGet(NULL, 0, true, 1, LOWEST, true)); |
| 4395 scoped_ptr<SpdyFrame> rst( | 3606 scoped_ptr<SpdyFrame> rst( |
| 4396 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_PROTOCOL_ERROR)); | 3607 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_PROTOCOL_ERROR)); |
| 4397 MockWrite writes[] = { | 3608 MockWrite writes[] = { |
| 4398 CreateMockWrite(*compressed), | 3609 CreateMockWrite(*compressed), |
| 4399 }; | 3610 }; |
| 4400 | 3611 |
| 4401 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); | 3612 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); |
| 4402 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true)); | 3613 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true)); |
| 4403 MockRead reads[] = { | 3614 MockRead reads[] = { |
| 4404 CreateMockRead(*resp), | 3615 CreateMockRead(*resp), |
| 4405 }; | 3616 }; |
| 4406 | 3617 |
| 4407 DelayedSocketData data(1, reads, arraysize(reads), | 3618 DelayedSocketData data(1, reads, arraysize(reads), |
| 4408 writes, arraysize(writes)); | 3619 writes, arraysize(writes)); |
| 4409 SpdySessionDependencies* session_deps = | 3620 SpdySessionDependencies* session_deps = |
| 4410 CreateSpdySessionDependencies(GetParam()); | 3621 CreateSpdySessionDependencies(GetParam()); |
| 4411 session_deps->enable_compression = true; | 3622 session_deps->enable_compression = true; |
| 4412 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY, | 3623 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY, |
| 4413 BoundNetLog(), GetParam(), session_deps); | 3624 BoundNetLog(), GetParam(), session_deps); |
| 4414 helper.RunToCompletion(&data); | 3625 helper.RunToCompletion(&data); |
| 4415 TransactionHelperResult out = helper.output(); | 3626 TransactionHelperResult out = helper.output(); |
| 4416 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, out.rv); | 3627 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, out.rv); |
| 4417 data.Reset(); | 3628 data.Reset(); |
| 4418 } | 3629 } |
| 4419 | 3630 |
| 4420 // Test that the NetLog contains good data for a simple GET request. | 3631 // Test that the NetLog contains good data for a simple GET request. |
| 4421 TEST_P(SpdyNetworkTransactionTest, NetLog) { | 3632 TEST_P(SpdyNetworkTransactionTest, NetLog) { |
| 4422 if (GetParam().protocol > kProtoSPDY3) | |
| 4423 return; | |
| 4424 | |
| 4425 static const char* const kExtraHeaders[] = { | 3633 static const char* const kExtraHeaders[] = { |
| 4426 "user-agent", "Chrome", | 3634 "user-agent", "Chrome", |
| 4427 }; | 3635 }; |
| 4428 scoped_ptr<SpdyFrame> req( | 3636 scoped_ptr<SpdyFrame> req( |
| 4429 spdy_util_.ConstructSpdyGet(kExtraHeaders, 1, false, 1, LOWEST, true)); | 3637 spdy_util_.ConstructSpdyGet(kExtraHeaders, 1, false, 1, LOWEST, true)); |
| 4430 MockWrite writes[] = { CreateMockWrite(*req) }; | 3638 MockWrite writes[] = { CreateMockWrite(*req) }; |
| 4431 | 3639 |
| 4432 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); | 3640 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); |
| 4433 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true)); | 3641 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true)); |
| 4434 MockRead reads[] = { | 3642 MockRead reads[] = { |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4503 EXPECT_NE(header_list->end(), header_list->Find(header)) << | 3711 EXPECT_NE(header_list->end(), header_list->Find(header)) << |
| 4504 "Header not found: " << *it; | 3712 "Header not found: " << *it; |
| 4505 } | 3713 } |
| 4506 } | 3714 } |
| 4507 | 3715 |
| 4508 // Since we buffer the IO from the stream to the renderer, this test verifies | 3716 // Since we buffer the IO from the stream to the renderer, this test verifies |
| 4509 // that when we read out the maximum amount of data (e.g. we received 50 bytes | 3717 // that when we read out the maximum amount of data (e.g. we received 50 bytes |
| 4510 // on the network, but issued a Read for only 5 of those bytes) that the data | 3718 // on the network, but issued a Read for only 5 of those bytes) that the data |
| 4511 // flow still works correctly. | 3719 // flow still works correctly. |
| 4512 TEST_P(SpdyNetworkTransactionTest, BufferFull) { | 3720 TEST_P(SpdyNetworkTransactionTest, BufferFull) { |
| 4513 if (GetParam().protocol > kProtoSPDY3) | |
| 4514 return; | |
| 4515 | |
| 4516 BufferedSpdyFramer framer(spdy_util_.spdy_version(), false); | 3721 BufferedSpdyFramer framer(spdy_util_.spdy_version(), false); |
| 4517 | 3722 |
| 4518 scoped_ptr<SpdyFrame> req( | 3723 scoped_ptr<SpdyFrame> req( |
| 4519 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true)); | 3724 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true)); |
| 4520 MockWrite writes[] = { CreateMockWrite(*req) }; | 3725 MockWrite writes[] = { CreateMockWrite(*req) }; |
| 4521 | 3726 |
| 4522 // 2 data frames in a single read. | 3727 // 2 data frames in a single read. |
| 4523 scoped_ptr<SpdyFrame> data_frame_1( | 3728 scoped_ptr<SpdyFrame> data_frame_1( |
| 4524 framer.CreateDataFrame(1, "goodby", 6, DATA_FLAG_NONE)); | 3729 framer.CreateDataFrame(1, "goodby", 6, DATA_FLAG_NONE)); |
| 4525 scoped_ptr<SpdyFrame> data_frame_2( | 3730 scoped_ptr<SpdyFrame> data_frame_2( |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4600 | 3805 |
| 4601 EXPECT_EQ(OK, out.rv); | 3806 EXPECT_EQ(OK, out.rv); |
| 4602 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line); | 3807 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line); |
| 4603 EXPECT_EQ("goodbye world", out.response_data); | 3808 EXPECT_EQ("goodbye world", out.response_data); |
| 4604 } | 3809 } |
| 4605 | 3810 |
| 4606 // Verify that basic buffering works; when multiple data frames arrive | 3811 // Verify that basic buffering works; when multiple data frames arrive |
| 4607 // at the same time, ensure that we don't notify a read completion for | 3812 // at the same time, ensure that we don't notify a read completion for |
| 4608 // each data frame individually. | 3813 // each data frame individually. |
| 4609 TEST_P(SpdyNetworkTransactionTest, Buffering) { | 3814 TEST_P(SpdyNetworkTransactionTest, Buffering) { |
| 4610 if (GetParam().protocol > kProtoSPDY3) | |
| 4611 return; | |
| 4612 | |
| 4613 BufferedSpdyFramer framer(spdy_util_.spdy_version(), false); | 3815 BufferedSpdyFramer framer(spdy_util_.spdy_version(), false); |
| 4614 | 3816 |
| 4615 scoped_ptr<SpdyFrame> req( | 3817 scoped_ptr<SpdyFrame> req( |
| 4616 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true)); | 3818 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true)); |
| 4617 MockWrite writes[] = { CreateMockWrite(*req) }; | 3819 MockWrite writes[] = { CreateMockWrite(*req) }; |
| 4618 | 3820 |
| 4619 // 4 data frames in a single read. | 3821 // 4 data frames in a single read. |
| 4620 scoped_ptr<SpdyFrame> data_frame( | 3822 scoped_ptr<SpdyFrame> data_frame( |
| 4621 framer.CreateDataFrame(1, "message", 7, DATA_FLAG_NONE)); | 3823 framer.CreateDataFrame(1, "message", 7, DATA_FLAG_NONE)); |
| 4622 scoped_ptr<SpdyFrame> data_frame_fin( | 3824 scoped_ptr<SpdyFrame> data_frame_fin( |
| (...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4698 // Verify that we consumed all test data. | 3900 // Verify that we consumed all test data. |
| 4699 helper.VerifyDataConsumed(); | 3901 helper.VerifyDataConsumed(); |
| 4700 | 3902 |
| 4701 EXPECT_EQ(OK, out.rv); | 3903 EXPECT_EQ(OK, out.rv); |
| 4702 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line); | 3904 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line); |
| 4703 EXPECT_EQ("messagemessagemessagemessage", out.response_data); | 3905 EXPECT_EQ("messagemessagemessagemessage", out.response_data); |
| 4704 } | 3906 } |
| 4705 | 3907 |
| 4706 // Verify the case where we buffer data but read it after it has been buffered. | 3908 // Verify the case where we buffer data but read it after it has been buffered. |
| 4707 TEST_P(SpdyNetworkTransactionTest, BufferedAll) { | 3909 TEST_P(SpdyNetworkTransactionTest, BufferedAll) { |
| 4708 if (GetParam().protocol > kProtoSPDY3) | |
| 4709 return; | |
| 4710 | |
| 4711 BufferedSpdyFramer framer(spdy_util_.spdy_version(), false); | 3910 BufferedSpdyFramer framer(spdy_util_.spdy_version(), false); |
| 4712 | 3911 |
| 4713 scoped_ptr<SpdyFrame> req( | 3912 scoped_ptr<SpdyFrame> req( |
| 4714 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true)); | 3913 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true)); |
| 4715 MockWrite writes[] = { CreateMockWrite(*req) }; | 3914 MockWrite writes[] = { CreateMockWrite(*req) }; |
| 4716 | 3915 |
| 4717 // 5 data frames in a single read. | 3916 // 5 data frames in a single read. |
| 4718 scoped_ptr<SpdyFrame> syn_reply( | 3917 scoped_ptr<SpdyFrame> syn_reply( |
| 4719 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); | 3918 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); |
| 4720 // turn off FIN bit | 3919 // turn off FIN bit |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4795 // Verify that we consumed all test data. | 3994 // Verify that we consumed all test data. |
| 4796 helper.VerifyDataConsumed(); | 3995 helper.VerifyDataConsumed(); |
| 4797 | 3996 |
| 4798 EXPECT_EQ(OK, out.rv); | 3997 EXPECT_EQ(OK, out.rv); |
| 4799 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line); | 3998 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line); |
| 4800 EXPECT_EQ("messagemessagemessagemessage", out.response_data); | 3999 EXPECT_EQ("messagemessagemessagemessage", out.response_data); |
| 4801 } | 4000 } |
| 4802 | 4001 |
| 4803 // Verify the case where we buffer data and close the connection. | 4002 // Verify the case where we buffer data and close the connection. |
| 4804 TEST_P(SpdyNetworkTransactionTest, BufferedClosed) { | 4003 TEST_P(SpdyNetworkTransactionTest, BufferedClosed) { |
| 4805 if (GetParam().protocol > kProtoSPDY3) | |
| 4806 return; | |
| 4807 | |
| 4808 BufferedSpdyFramer framer(spdy_util_.spdy_version(), false); | 4004 BufferedSpdyFramer framer(spdy_util_.spdy_version(), false); |
| 4809 | 4005 |
| 4810 scoped_ptr<SpdyFrame> req( | 4006 scoped_ptr<SpdyFrame> req( |
| 4811 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true)); | 4007 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true)); |
| 4812 MockWrite writes[] = { CreateMockWrite(*req) }; | 4008 MockWrite writes[] = { CreateMockWrite(*req) }; |
| 4813 | 4009 |
| 4814 // All data frames in a single read. | 4010 // All data frames in a single read. |
| 4815 // NOTE: We don't FIN the stream. | 4011 // NOTE: We don't FIN the stream. |
| 4816 scoped_ptr<SpdyFrame> data_frame( | 4012 scoped_ptr<SpdyFrame> data_frame( |
| 4817 framer.CreateDataFrame(1, "message", 7, DATA_FLAG_NONE)); | 4013 framer.CreateDataFrame(1, "message", 7, DATA_FLAG_NONE)); |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4889 // Flush the MessageLoop while the SpdySessionDependencies (in particular, the | 4085 // Flush the MessageLoop while the SpdySessionDependencies (in particular, the |
| 4890 // MockClientSocketFactory) are still alive. | 4086 // MockClientSocketFactory) are still alive. |
| 4891 base::MessageLoop::current()->RunUntilIdle(); | 4087 base::MessageLoop::current()->RunUntilIdle(); |
| 4892 | 4088 |
| 4893 // Verify that we consumed all test data. | 4089 // Verify that we consumed all test data. |
| 4894 helper.VerifyDataConsumed(); | 4090 helper.VerifyDataConsumed(); |
| 4895 } | 4091 } |
| 4896 | 4092 |
| 4897 // Verify the case where we buffer data and cancel the transaction. | 4093 // Verify the case where we buffer data and cancel the transaction. |
| 4898 TEST_P(SpdyNetworkTransactionTest, BufferedCancelled) { | 4094 TEST_P(SpdyNetworkTransactionTest, BufferedCancelled) { |
| 4899 if (GetParam().protocol > kProtoSPDY3) | |
| 4900 return; | |
| 4901 | |
| 4902 BufferedSpdyFramer framer(spdy_util_.spdy_version(), false); | 4095 BufferedSpdyFramer framer(spdy_util_.spdy_version(), false); |
| 4903 | 4096 |
| 4904 scoped_ptr<SpdyFrame> req( | 4097 scoped_ptr<SpdyFrame> req( |
| 4905 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true)); | 4098 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true)); |
| 4906 MockWrite writes[] = { CreateMockWrite(*req) }; | 4099 MockWrite writes[] = { CreateMockWrite(*req) }; |
| 4907 | 4100 |
| 4908 // NOTE: We don't FIN the stream. | 4101 // NOTE: We don't FIN the stream. |
| 4909 scoped_ptr<SpdyFrame> data_frame( | 4102 scoped_ptr<SpdyFrame> data_frame( |
| 4910 framer.CreateDataFrame(1, "message", 7, DATA_FLAG_NONE)); | 4103 framer.CreateDataFrame(1, "message", 7, DATA_FLAG_NONE)); |
| 4911 | 4104 |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4964 // to run for the final time. | 4157 // to run for the final time. |
| 4965 base::MessageLoop::current()->RunUntilIdle(); | 4158 base::MessageLoop::current()->RunUntilIdle(); |
| 4966 | 4159 |
| 4967 // Verify that we consumed all test data. | 4160 // Verify that we consumed all test data. |
| 4968 helper.VerifyDataConsumed(); | 4161 helper.VerifyDataConsumed(); |
| 4969 } | 4162 } |
| 4970 | 4163 |
| 4971 // Test that if the server requests persistence of settings, that we save | 4164 // Test that if the server requests persistence of settings, that we save |
| 4972 // the settings in the HttpServerProperties. | 4165 // the settings in the HttpServerProperties. |
| 4973 TEST_P(SpdyNetworkTransactionTest, SettingsSaved) { | 4166 TEST_P(SpdyNetworkTransactionTest, SettingsSaved) { |
| 4974 if (GetParam().protocol > kProtoSPDY3) | |
| 4975 return; | |
| 4976 | |
| 4977 static const SpdyHeaderInfo kSynReplyInfo = { | 4167 static const SpdyHeaderInfo kSynReplyInfo = { |
| 4978 SYN_REPLY, // Syn Reply | 4168 SYN_REPLY, // Syn Reply |
| 4979 1, // Stream ID | 4169 1, // Stream ID |
| 4980 0, // Associated Stream ID | 4170 0, // Associated Stream ID |
| 4981 ConvertRequestPriorityToSpdyPriority( | 4171 ConvertRequestPriorityToSpdyPriority( |
| 4982 LOWEST, spdy_util_.spdy_version()), | 4172 LOWEST, spdy_util_.spdy_version()), |
| 4983 kSpdyCredentialSlotUnused, | 4173 kSpdyCredentialSlotUnused, |
| 4984 CONTROL_FLAG_NONE, // Control Flags | 4174 CONTROL_FLAG_NONE, // Control Flags |
| 4985 false, // Compressed | 4175 false, // Compressed |
| 4986 RST_STREAM_INVALID, // Status | 4176 RST_STREAM_INVALID, // Status |
| (...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 5071 EXPECT_TRUE(it3 != settings_map.end()); | 4261 EXPECT_TRUE(it3 != settings_map.end()); |
| 5072 SettingsFlagsAndValue flags_and_value3 = it3->second; | 4262 SettingsFlagsAndValue flags_and_value3 = it3->second; |
| 5073 EXPECT_EQ(SETTINGS_FLAG_PERSISTED, flags_and_value3.first); | 4263 EXPECT_EQ(SETTINGS_FLAG_PERSISTED, flags_and_value3.first); |
| 5074 EXPECT_EQ(kSampleValue3, flags_and_value3.second); | 4264 EXPECT_EQ(kSampleValue3, flags_and_value3.second); |
| 5075 } | 4265 } |
| 5076 } | 4266 } |
| 5077 | 4267 |
| 5078 // Test that when there are settings saved that they are sent back to the | 4268 // Test that when there are settings saved that they are sent back to the |
| 5079 // server upon session establishment. | 4269 // server upon session establishment. |
| 5080 TEST_P(SpdyNetworkTransactionTest, SettingsPlayback) { | 4270 TEST_P(SpdyNetworkTransactionTest, SettingsPlayback) { |
| 5081 if (GetParam().protocol > kProtoSPDY3) | |
| 5082 return; | |
| 5083 | |
| 5084 static const SpdyHeaderInfo kSynReplyInfo = { | 4271 static const SpdyHeaderInfo kSynReplyInfo = { |
| 5085 SYN_REPLY, // Syn Reply | 4272 SYN_REPLY, // Syn Reply |
| 5086 1, // Stream ID | 4273 1, // Stream ID |
| 5087 0, // Associated Stream ID | 4274 0, // Associated Stream ID |
| 5088 ConvertRequestPriorityToSpdyPriority( | 4275 ConvertRequestPriorityToSpdyPriority( |
| 5089 LOWEST, spdy_util_.spdy_version()), | 4276 LOWEST, spdy_util_.spdy_version()), |
| 5090 kSpdyCredentialSlotUnused, | 4277 kSpdyCredentialSlotUnused, |
| 5091 CONTROL_FLAG_NONE, // Control Flags | 4278 CONTROL_FLAG_NONE, // Control Flags |
| 5092 false, // Compressed | 4279 false, // Compressed |
| 5093 RST_STREAM_INVALID, // Status | 4280 RST_STREAM_INVALID, // Status |
| (...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 5186 // Verify the second persisted setting. | 4373 // Verify the second persisted setting. |
| 5187 SettingsMap::const_iterator it2 = settings_map.find(kSampleId2); | 4374 SettingsMap::const_iterator it2 = settings_map.find(kSampleId2); |
| 5188 EXPECT_TRUE(it2 != settings_map.end()); | 4375 EXPECT_TRUE(it2 != settings_map.end()); |
| 5189 SettingsFlagsAndValue flags_and_value2 = it2->second; | 4376 SettingsFlagsAndValue flags_and_value2 = it2->second; |
| 5190 EXPECT_EQ(SETTINGS_FLAG_PERSISTED, flags_and_value2.first); | 4377 EXPECT_EQ(SETTINGS_FLAG_PERSISTED, flags_and_value2.first); |
| 5191 EXPECT_EQ(kSampleValue2, flags_and_value2.second); | 4378 EXPECT_EQ(kSampleValue2, flags_and_value2.second); |
| 5192 } | 4379 } |
| 5193 } | 4380 } |
| 5194 | 4381 |
| 5195 TEST_P(SpdyNetworkTransactionTest, GoAwayWithActiveStream) { | 4382 TEST_P(SpdyNetworkTransactionTest, GoAwayWithActiveStream) { |
| 5196 if (GetParam().protocol > kProtoSPDY3) | |
| 5197 return; | |
| 5198 | |
| 5199 scoped_ptr<SpdyFrame> req( | 4383 scoped_ptr<SpdyFrame> req( |
| 5200 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true)); | 4384 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true)); |
| 5201 MockWrite writes[] = { CreateMockWrite(*req) }; | 4385 MockWrite writes[] = { CreateMockWrite(*req) }; |
| 5202 | 4386 |
| 5203 scoped_ptr<SpdyFrame> go_away(spdy_util_.ConstructSpdyGoAway()); | 4387 scoped_ptr<SpdyFrame> go_away(spdy_util_.ConstructSpdyGoAway()); |
| 5204 MockRead reads[] = { | 4388 MockRead reads[] = { |
| 5205 CreateMockRead(*go_away), | 4389 CreateMockRead(*go_away), |
| 5206 MockRead(ASYNC, 0, 0), // EOF | 4390 MockRead(ASYNC, 0, 0), // EOF |
| 5207 }; | 4391 }; |
| 5208 | 4392 |
| 5209 DelayedSocketData data(1, reads, arraysize(reads), | 4393 DelayedSocketData data(1, reads, arraysize(reads), |
| 5210 writes, arraysize(writes)); | 4394 writes, arraysize(writes)); |
| 5211 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY, | 4395 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY, |
| 5212 BoundNetLog(), GetParam(), NULL); | 4396 BoundNetLog(), GetParam(), NULL); |
| 5213 helper.AddData(&data); | 4397 helper.AddData(&data); |
| 5214 helper.RunToCompletion(&data); | 4398 helper.RunToCompletion(&data); |
| 5215 TransactionHelperResult out = helper.output(); | 4399 TransactionHelperResult out = helper.output(); |
| 5216 EXPECT_EQ(ERR_ABORTED, out.rv); | 4400 EXPECT_EQ(ERR_ABORTED, out.rv); |
| 5217 } | 4401 } |
| 5218 | 4402 |
| 5219 TEST_P(SpdyNetworkTransactionTest, CloseWithActiveStream) { | 4403 TEST_P(SpdyNetworkTransactionTest, CloseWithActiveStream) { |
| 5220 if (GetParam().protocol > kProtoSPDY3) | |
| 5221 return; | |
| 5222 | |
| 5223 scoped_ptr<SpdyFrame> req( | 4404 scoped_ptr<SpdyFrame> req( |
| 5224 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true)); | 4405 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true)); |
| 5225 MockWrite writes[] = { CreateMockWrite(*req) }; | 4406 MockWrite writes[] = { CreateMockWrite(*req) }; |
| 5226 | 4407 |
| 5227 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); | 4408 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); |
| 5228 MockRead reads[] = { | 4409 MockRead reads[] = { |
| 5229 CreateMockRead(*resp), | 4410 CreateMockRead(*resp), |
| 5230 MockRead(SYNCHRONOUS, 0, 0) // EOF | 4411 MockRead(SYNCHRONOUS, 0, 0) // EOF |
| 5231 }; | 4412 }; |
| 5232 | 4413 |
| (...skipping 19 matching lines...) Expand all Loading... | |
| 5252 EXPECT_TRUE(response->was_fetched_via_spdy); | 4433 EXPECT_TRUE(response->was_fetched_via_spdy); |
| 5253 out.rv = ReadTransaction(trans, &out.response_data); | 4434 out.rv = ReadTransaction(trans, &out.response_data); |
| 5254 EXPECT_EQ(ERR_CONNECTION_CLOSED, out.rv); | 4435 EXPECT_EQ(ERR_CONNECTION_CLOSED, out.rv); |
| 5255 | 4436 |
| 5256 // Verify that we consumed all test data. | 4437 // Verify that we consumed all test data. |
| 5257 helper.VerifyDataConsumed(); | 4438 helper.VerifyDataConsumed(); |
| 5258 } | 4439 } |
| 5259 | 4440 |
| 5260 // Test to make sure we can correctly connect through a proxy. | 4441 // Test to make sure we can correctly connect through a proxy. |
| 5261 TEST_P(SpdyNetworkTransactionTest, ProxyConnect) { | 4442 TEST_P(SpdyNetworkTransactionTest, ProxyConnect) { |
| 5262 if (GetParam().protocol > kProtoSPDY3) | |
| 5263 return; | |
| 5264 | |
| 5265 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY, | 4443 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY, |
| 5266 BoundNetLog(), GetParam(), NULL); | 4444 BoundNetLog(), GetParam(), NULL); |
| 5267 helper.session_deps().reset(CreateSpdySessionDependencies( | 4445 helper.session_deps().reset(CreateSpdySessionDependencies( |
| 5268 GetParam(), | 4446 GetParam(), |
| 5269 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"))); | 4447 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"))); |
| 5270 helper.SetSession(make_scoped_refptr( | 4448 helper.SetSession(make_scoped_refptr( |
| 5271 SpdySessionDependencies::SpdyCreateSession(helper.session_deps().get()))); | 4449 SpdySessionDependencies::SpdyCreateSession(helper.session_deps().get()))); |
| 5272 helper.RunPreTestSetup(); | 4450 helper.RunPreTestSetup(); |
| 5273 HttpNetworkTransaction* trans = helper.trans(); | 4451 HttpNetworkTransaction* trans = helper.trans(); |
| 5274 | 4452 |
| (...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 5358 std::string response_data; | 4536 std::string response_data; |
| 5359 ASSERT_EQ(OK, ReadTransaction(trans, &response_data)); | 4537 ASSERT_EQ(OK, ReadTransaction(trans, &response_data)); |
| 5360 EXPECT_EQ("hello!", response_data); | 4538 EXPECT_EQ("hello!", response_data); |
| 5361 helper.VerifyDataConsumed(); | 4539 helper.VerifyDataConsumed(); |
| 5362 } | 4540 } |
| 5363 | 4541 |
| 5364 // Test to make sure we can correctly connect through a proxy to www.google.com, | 4542 // Test to make sure we can correctly connect through a proxy to www.google.com, |
| 5365 // if there already exists a direct spdy connection to www.google.com. See | 4543 // if there already exists a direct spdy connection to www.google.com. See |
| 5366 // http://crbug.com/49874 | 4544 // http://crbug.com/49874 |
| 5367 TEST_P(SpdyNetworkTransactionTest, DirectConnectProxyReconnect) { | 4545 TEST_P(SpdyNetworkTransactionTest, DirectConnectProxyReconnect) { |
| 5368 if (GetParam().protocol > kProtoSPDY3) | |
| 5369 return; | |
| 5370 | |
| 5371 // When setting up the first transaction, we store the SpdySessionPool so that | 4546 // When setting up the first transaction, we store the SpdySessionPool so that |
| 5372 // we can use the same pool in the second transaction. | 4547 // we can use the same pool in the second transaction. |
| 5373 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY, | 4548 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY, |
| 5374 BoundNetLog(), GetParam(), NULL); | 4549 BoundNetLog(), GetParam(), NULL); |
| 5375 | 4550 |
| 5376 // Use a proxy service which returns a proxy fallback list from DIRECT to | 4551 // Use a proxy service which returns a proxy fallback list from DIRECT to |
| 5377 // myproxy:70. For this test there will be no fallback, so it is equivalent | 4552 // myproxy:70. For this test there will be no fallback, so it is equivalent |
| 5378 // to simply DIRECT. The reason for appending the second proxy is to verify | 4553 // to simply DIRECT. The reason for appending the second proxy is to verify |
| 5379 // that the session pool key used does is just "DIRECT". | 4554 // that the session pool key used does is just "DIRECT". |
| 5380 helper.session_deps().reset(CreateSpdySessionDependencies( | 4555 helper.session_deps().reset(CreateSpdySessionDependencies( |
| (...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 5542 | 4717 |
| 5543 data.CompleteRead(); | 4718 data.CompleteRead(); |
| 5544 helper_proxy.VerifyDataConsumed(); | 4719 helper_proxy.VerifyDataConsumed(); |
| 5545 } | 4720 } |
| 5546 | 4721 |
| 5547 // When we get a TCP-level RST, we need to retry a HttpNetworkTransaction | 4722 // When we get a TCP-level RST, we need to retry a HttpNetworkTransaction |
| 5548 // on a new connection, if the connection was previously known to be good. | 4723 // on a new connection, if the connection was previously known to be good. |
| 5549 // This can happen when a server reboots without saying goodbye, or when | 4724 // This can happen when a server reboots without saying goodbye, or when |
| 5550 // we're behind a NAT that masked the RST. | 4725 // we're behind a NAT that masked the RST. |
| 5551 TEST_P(SpdyNetworkTransactionTest, VerifyRetryOnConnectionReset) { | 4726 TEST_P(SpdyNetworkTransactionTest, VerifyRetryOnConnectionReset) { |
| 5552 if (GetParam().protocol > kProtoSPDY3) | |
| 5553 return; | |
| 5554 | |
| 5555 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); | 4727 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); |
| 5556 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true)); | 4728 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true)); |
| 5557 MockRead reads[] = { | 4729 MockRead reads[] = { |
| 5558 CreateMockRead(*resp), | 4730 CreateMockRead(*resp), |
| 5559 CreateMockRead(*body), | 4731 CreateMockRead(*body), |
| 5560 MockRead(ASYNC, ERR_IO_PENDING), | 4732 MockRead(ASYNC, ERR_IO_PENDING), |
| 5561 MockRead(ASYNC, ERR_CONNECTION_RESET), | 4733 MockRead(ASYNC, ERR_CONNECTION_RESET), |
| 5562 }; | 4734 }; |
| 5563 | 4735 |
| 5564 MockRead reads2[] = { | 4736 MockRead reads2[] = { |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 5623 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine()); | 4795 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine()); |
| 5624 EXPECT_EQ("hello!", response_data); | 4796 EXPECT_EQ("hello!", response_data); |
| 5625 } | 4797 } |
| 5626 | 4798 |
| 5627 helper.VerifyDataConsumed(); | 4799 helper.VerifyDataConsumed(); |
| 5628 } | 4800 } |
| 5629 } | 4801 } |
| 5630 | 4802 |
| 5631 // Test that turning SPDY on and off works properly. | 4803 // Test that turning SPDY on and off works properly. |
| 5632 TEST_P(SpdyNetworkTransactionTest, SpdyOnOffToggle) { | 4804 TEST_P(SpdyNetworkTransactionTest, SpdyOnOffToggle) { |
| 5633 if (GetParam().protocol > kProtoSPDY3) | |
| 5634 return; | |
| 5635 | |
| 5636 net::HttpStreamFactory::set_spdy_enabled(true); | 4805 net::HttpStreamFactory::set_spdy_enabled(true); |
| 5637 scoped_ptr<SpdyFrame> req( | 4806 scoped_ptr<SpdyFrame> req( |
| 5638 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true)); | 4807 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true)); |
| 5639 MockWrite spdy_writes[] = { CreateMockWrite(*req) }; | 4808 MockWrite spdy_writes[] = { CreateMockWrite(*req) }; |
| 5640 | 4809 |
| 5641 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); | 4810 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); |
| 5642 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true)); | 4811 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true)); |
| 5643 MockRead spdy_reads[] = { | 4812 MockRead spdy_reads[] = { |
| 5644 CreateMockRead(*resp), | 4813 CreateMockRead(*resp), |
| 5645 CreateMockRead(*body), | 4814 CreateMockRead(*body), |
| (...skipping 24 matching lines...) Expand all Loading... | |
| 5670 TransactionHelperResult out2 = helper2.output(); | 4839 TransactionHelperResult out2 = helper2.output(); |
| 5671 EXPECT_EQ(OK, out2.rv); | 4840 EXPECT_EQ(OK, out2.rv); |
| 5672 EXPECT_EQ("HTTP/1.1 200 OK", out2.status_line); | 4841 EXPECT_EQ("HTTP/1.1 200 OK", out2.status_line); |
| 5673 EXPECT_EQ("hello from http", out2.response_data); | 4842 EXPECT_EQ("hello from http", out2.response_data); |
| 5674 | 4843 |
| 5675 net::HttpStreamFactory::set_spdy_enabled(true); | 4844 net::HttpStreamFactory::set_spdy_enabled(true); |
| 5676 } | 4845 } |
| 5677 | 4846 |
| 5678 // Tests that Basic authentication works over SPDY | 4847 // Tests that Basic authentication works over SPDY |
| 5679 TEST_P(SpdyNetworkTransactionTest, SpdyBasicAuth) { | 4848 TEST_P(SpdyNetworkTransactionTest, SpdyBasicAuth) { |
| 5680 if (GetParam().protocol > kProtoSPDY3) | |
| 5681 return; | |
| 5682 | |
| 5683 net::HttpStreamFactory::set_spdy_enabled(true); | 4849 net::HttpStreamFactory::set_spdy_enabled(true); |
| 5684 | 4850 |
| 5685 // The first request will be a bare GET, the second request will be a | 4851 // The first request will be a bare GET, the second request will be a |
| 5686 // GET with an Authorization header. | 4852 // GET with an Authorization header. |
| 5687 scoped_ptr<SpdyFrame> req_get( | 4853 scoped_ptr<SpdyFrame> req_get( |
| 5688 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true)); | 4854 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true)); |
| 5689 const char* const kExtraAuthorizationHeaders[] = { | 4855 const char* const kExtraAuthorizationHeaders[] = { |
| 5690 "authorization", "Basic Zm9vOmJhcg==" | 4856 "authorization", "Basic Zm9vOmJhcg==" |
| 5691 }; | 4857 }; |
| 5692 scoped_ptr<SpdyFrame> req_get_authorization( | 4858 scoped_ptr<SpdyFrame> req_get_authorization( |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 5763 // TODO(cbentzel): This is actually the same response object as before, but | 4929 // TODO(cbentzel): This is actually the same response object as before, but |
| 5764 // data has changed. | 4930 // data has changed. |
| 5765 const HttpResponseInfo* const response_restart = trans->GetResponseInfo(); | 4931 const HttpResponseInfo* const response_restart = trans->GetResponseInfo(); |
| 5766 ASSERT_TRUE(response_restart != NULL); | 4932 ASSERT_TRUE(response_restart != NULL); |
| 5767 ASSERT_TRUE(response_restart->headers.get() != NULL); | 4933 ASSERT_TRUE(response_restart->headers.get() != NULL); |
| 5768 EXPECT_EQ(200, response_restart->headers->response_code()); | 4934 EXPECT_EQ(200, response_restart->headers->response_code()); |
| 5769 EXPECT_TRUE(response_restart->auth_challenge.get() == NULL); | 4935 EXPECT_TRUE(response_restart->auth_challenge.get() == NULL); |
| 5770 } | 4936 } |
| 5771 | 4937 |
| 5772 TEST_P(SpdyNetworkTransactionTest, ServerPushWithHeaders) { | 4938 TEST_P(SpdyNetworkTransactionTest, ServerPushWithHeaders) { |
| 5773 if (GetParam().protocol > kProtoSPDY3) | |
| 5774 return; | |
| 5775 | |
| 5776 static const unsigned char kPushBodyFrame[] = { | |
| 5777 0x00, 0x00, 0x00, 0x02, // header, ID | |
| 5778 0x01, 0x00, 0x00, 0x06, // FIN, length | |
| 5779 'p', 'u', 's', 'h', 'e', 'd' // "pushed" | |
| 5780 }; | |
| 5781 scoped_ptr<SpdyFrame> stream1_syn( | 4939 scoped_ptr<SpdyFrame> stream1_syn( |
| 5782 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true)); | 4940 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true)); |
| 5783 scoped_ptr<SpdyFrame> stream1_body( | 4941 scoped_ptr<SpdyFrame> stream1_body( |
| 5784 spdy_util_.ConstructSpdyBodyFrame(1, true)); | 4942 spdy_util_.ConstructSpdyBodyFrame(1, true)); |
| 5785 MockWrite writes[] = { | 4943 MockWrite writes[] = { |
| 5786 CreateMockWrite(*stream1_syn, 1), | 4944 CreateMockWrite(*stream1_syn, 1), |
| 5787 }; | 4945 }; |
| 5788 | 4946 |
| 5789 scoped_ptr<SpdyHeaderBlock> initial_headers(new SpdyHeaderBlock()); | 4947 scoped_ptr<SpdyHeaderBlock> initial_headers(new SpdyHeaderBlock()); |
| 5790 spdy_util_.AddUrlToHeaderBlock( | 4948 spdy_util_.AddUrlToHeaderBlock( |
| (...skipping 15 matching lines...) Expand all Loading... | |
| 5806 spdy_util_.ConstructSpdyControlFrame(late_headers.Pass(), | 4964 spdy_util_.ConstructSpdyControlFrame(late_headers.Pass(), |
| 5807 false, | 4965 false, |
| 5808 2, | 4966 2, |
| 5809 LOWEST, | 4967 LOWEST, |
| 5810 HEADERS, | 4968 HEADERS, |
| 5811 CONTROL_FLAG_NONE, | 4969 CONTROL_FLAG_NONE, |
| 5812 0)); | 4970 0)); |
| 5813 | 4971 |
| 5814 scoped_ptr<SpdyFrame> | 4972 scoped_ptr<SpdyFrame> |
| 5815 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); | 4973 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); |
| 4974 const char kPushedData[] = "pushed"; | |
| 4975 scoped_ptr<SpdyFrame> stream2_body( | |
| 4976 spdy_util_.ConstructSpdyBodyFrame( | |
| 4977 2, kPushedData, strlen(kPushedData), true)); | |
| 5816 MockRead reads[] = { | 4978 MockRead reads[] = { |
| 5817 CreateMockRead(*stream1_reply, 2), | 4979 CreateMockRead(*stream1_reply, 2), |
| 5818 CreateMockRead(*stream2_syn, 3), | 4980 CreateMockRead(*stream2_syn, 3), |
| 5819 CreateMockRead(*stream2_headers, 4), | 4981 CreateMockRead(*stream2_headers, 4), |
| 5820 CreateMockRead(*stream1_body, 5, SYNCHRONOUS), | 4982 CreateMockRead(*stream1_body, 5, SYNCHRONOUS), |
| 5821 MockRead(ASYNC, reinterpret_cast<const char*>(kPushBodyFrame), | 4983 CreateMockRead(*stream2_body, 5), |
| 5822 arraysize(kPushBodyFrame), 6), | |
| 5823 MockRead(ASYNC, ERR_IO_PENDING, 7), // Force a pause | 4984 MockRead(ASYNC, ERR_IO_PENDING, 7), // Force a pause |
| 5824 }; | 4985 }; |
| 5825 | 4986 |
| 5826 HttpResponseInfo response; | 4987 HttpResponseInfo response; |
| 5827 HttpResponseInfo response2; | 4988 HttpResponseInfo response2; |
| 5828 std::string expected_push_result("pushed"); | 4989 std::string expected_push_result("pushed"); |
| 5829 OrderedSocketData data(reads, arraysize(reads), | 4990 OrderedSocketData data(reads, arraysize(reads), |
| 5830 writes, arraysize(writes)); | 4991 writes, arraysize(writes)); |
| 5831 RunServerPushTest(&data, | 4992 RunServerPushTest(&data, |
| 5832 &response, | 4993 &response, |
| 5833 &response2, | 4994 &response2, |
| 5834 expected_push_result); | 4995 expected_push_result); |
| 5835 | 4996 |
| 5836 // Verify the SYN_REPLY. | 4997 // Verify the SYN_REPLY. |
| 5837 EXPECT_TRUE(response.headers.get() != NULL); | 4998 EXPECT_TRUE(response.headers.get() != NULL); |
| 5838 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine()); | 4999 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine()); |
| 5839 | 5000 |
| 5840 // Verify the pushed stream. | 5001 // Verify the pushed stream. |
| 5841 EXPECT_TRUE(response2.headers.get() != NULL); | 5002 EXPECT_TRUE(response2.headers.get() != NULL); |
| 5842 EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine()); | 5003 EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine()); |
| 5843 } | 5004 } |
| 5844 | 5005 |
| 5845 TEST_P(SpdyNetworkTransactionTest, ServerPushClaimBeforeHeaders) { | 5006 TEST_P(SpdyNetworkTransactionTest, ServerPushClaimBeforeHeaders) { |
| 5846 if (GetParam().protocol > kProtoSPDY3) | |
| 5847 return; | |
| 5848 | |
| 5849 // We push a stream and attempt to claim it before the headers come down. | 5007 // We push a stream and attempt to claim it before the headers come down. |
| 5850 static const unsigned char kPushBodyFrame[] = { | |
| 5851 0x00, 0x00, 0x00, 0x02, // header, ID | |
| 5852 0x01, 0x00, 0x00, 0x06, // FIN, length | |
| 5853 'p', 'u', 's', 'h', 'e', 'd' // "pushed" | |
| 5854 }; | |
| 5855 scoped_ptr<SpdyFrame> stream1_syn( | 5008 scoped_ptr<SpdyFrame> stream1_syn( |
| 5856 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true)); | 5009 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true)); |
| 5857 scoped_ptr<SpdyFrame> stream1_body( | 5010 scoped_ptr<SpdyFrame> stream1_body( |
| 5858 spdy_util_.ConstructSpdyBodyFrame(1, true)); | 5011 spdy_util_.ConstructSpdyBodyFrame(1, true)); |
| 5859 MockWrite writes[] = { | 5012 MockWrite writes[] = { |
| 5860 CreateMockWrite(*stream1_syn, 0, SYNCHRONOUS), | 5013 CreateMockWrite(*stream1_syn, 0, SYNCHRONOUS), |
| 5861 }; | 5014 }; |
| 5862 | 5015 |
| 5863 scoped_ptr<SpdyHeaderBlock> initial_headers(new SpdyHeaderBlock()); | 5016 scoped_ptr<SpdyHeaderBlock> initial_headers(new SpdyHeaderBlock()); |
| 5864 spdy_util_.AddUrlToHeaderBlock( | 5017 spdy_util_.AddUrlToHeaderBlock( |
| (...skipping 15 matching lines...) Expand all Loading... | |
| 5880 spdy_util_.ConstructSpdyControlFrame(late_headers.Pass(), | 5033 spdy_util_.ConstructSpdyControlFrame(late_headers.Pass(), |
| 5881 false, | 5034 false, |
| 5882 2, | 5035 2, |
| 5883 LOWEST, | 5036 LOWEST, |
| 5884 HEADERS, | 5037 HEADERS, |
| 5885 CONTROL_FLAG_NONE, | 5038 CONTROL_FLAG_NONE, |
| 5886 0)); | 5039 0)); |
| 5887 | 5040 |
| 5888 scoped_ptr<SpdyFrame> | 5041 scoped_ptr<SpdyFrame> |
| 5889 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); | 5042 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); |
| 5043 const char kPushedData[] = "pushed"; | |
| 5044 scoped_ptr<SpdyFrame> stream2_body( | |
| 5045 spdy_util_.ConstructSpdyBodyFrame( | |
| 5046 2, kPushedData, strlen(kPushedData), true)); | |
| 5890 MockRead reads[] = { | 5047 MockRead reads[] = { |
| 5891 CreateMockRead(*stream1_reply, 1), | 5048 CreateMockRead(*stream1_reply, 1), |
| 5892 CreateMockRead(*stream2_syn, 2), | 5049 CreateMockRead(*stream2_syn, 2), |
| 5893 CreateMockRead(*stream1_body, 3), | 5050 CreateMockRead(*stream1_body, 3), |
| 5894 CreateMockRead(*stream2_headers, 4), | 5051 CreateMockRead(*stream2_headers, 4), |
| 5895 MockRead(ASYNC, reinterpret_cast<const char*>(kPushBodyFrame), | 5052 CreateMockRead(*stream2_body, 5), |
| 5896 arraysize(kPushBodyFrame), 5), | |
| 5897 MockRead(ASYNC, 0, 6), // EOF | 5053 MockRead(ASYNC, 0, 6), // EOF |
| 5898 }; | 5054 }; |
| 5899 | 5055 |
| 5900 HttpResponseInfo response; | 5056 HttpResponseInfo response; |
| 5901 HttpResponseInfo response2; | 5057 HttpResponseInfo response2; |
| 5902 std::string expected_push_result("pushed"); | 5058 std::string expected_push_result("pushed"); |
| 5903 DeterministicSocketData data(reads, arraysize(reads), | 5059 DeterministicSocketData data(reads, arraysize(reads), |
| 5904 writes, arraysize(writes)); | 5060 writes, arraysize(writes)); |
| 5905 | 5061 |
| 5906 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY, | 5062 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY, |
| 5907 BoundNetLog(), GetParam(), NULL); | 5063 BoundNetLog(), GetParam(), NULL); |
| 5908 helper.SetDeterministic(); | 5064 helper.SetDeterministic(); |
| 5909 helper.AddDeterministicData(&data); | 5065 helper.AddDeterministicData(&data); |
| 5066 helper.RunPreTestSetup(); | |
| 5067 | |
| 5068 HttpNetworkTransaction* trans = helper.trans(); | |
| 5069 | |
| 5070 // Run until we've received the primary SYN_STREAM, the pushed SYN_STREAM, | |
| 5071 // and the body of the primary stream, but before we've received the HEADERS | |
| 5072 // for the pushed stream. | |
| 5073 data.SetStop(3); | |
| 5074 | |
| 5075 // Start the transaction. | |
| 5076 TestCompletionCallback callback; | |
| 5077 int rv = trans->Start( | |
| 5078 &CreateGetRequest(), callback.callback(), BoundNetLog()); | |
| 5079 EXPECT_EQ(ERR_IO_PENDING, rv); | |
| 5080 data.Run(); | |
| 5081 rv = callback.WaitForResult(); | |
| 5082 EXPECT_EQ(0, rv); | |
| 5083 | |
| 5084 // Request the pushed path. At this point, we've received the push, but the | |
| 5085 // headers are not yet complete. | |
| 5086 scoped_ptr<HttpNetworkTransaction> trans2( | |
| 5087 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get())); | |
| 5088 rv = trans2->Start( | |
| 5089 &CreateGetPushRequest(), callback.callback(), BoundNetLog()); | |
| 5090 EXPECT_EQ(ERR_IO_PENDING, rv); | |
| 5091 data.RunFor(3); | |
| 5092 base::MessageLoop::current()->RunUntilIdle(); | |
| 5093 | |
| 5094 // Read the server push body. | |
| 5095 std::string result2; | |
| 5096 ReadResult(trans2.get(), &data, &result2); | |
| 5097 // Read the response body. | |
| 5098 std::string result; | |
| 5099 ReadResult(trans, &data, &result); | |
| 5100 | |
| 5101 // Verify that the received push data is same as the expected push data. | |
| 5102 EXPECT_EQ(result2.compare(expected_push_result), 0) | |
| 5103 << "Received data: " | |
| 5104 << result2 | |
| 5105 << "||||| Expected data: " | |
| 5106 << expected_push_result; | |
| 5107 | |
| 5108 // Verify the SYN_REPLY. | |
| 5109 // Copy the response info, because trans goes away. | |
| 5110 response = *trans->GetResponseInfo(); | |
| 5111 response2 = *trans2->GetResponseInfo(); | |
| 5112 | |
| 5113 VerifyStreamsClosed(helper); | |
| 5114 | |
| 5115 // Verify the SYN_REPLY. | |
| 5116 EXPECT_TRUE(response.headers.get() != NULL); | |
| 5117 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine()); | |
| 5118 | |
| 5119 // Verify the pushed stream. | |
| 5120 EXPECT_TRUE(response2.headers.get() != NULL); | |
| 5121 EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine()); | |
| 5122 | |
| 5123 // Read the final EOF (which will close the session) | |
| 5124 data.RunFor(1); | |
| 5125 | |
| 5126 // Verify that we consumed all test data. | |
| 5127 EXPECT_TRUE(data.at_read_eof()); | |
| 5128 EXPECT_TRUE(data.at_write_eof()); | |
| 5129 } | |
| 5130 | |
| 5131 TEST_P(SpdyNetworkTransactionTest, ServerPushWithTwoHeaderFrames) { | |
| 5132 // We push a stream and attempt to claim it before the headers come down. | |
| 5133 scoped_ptr<SpdyFrame> stream1_syn( | |
| 5134 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true)); | |
| 5135 scoped_ptr<SpdyFrame> stream1_body( | |
| 5136 spdy_util_.ConstructSpdyBodyFrame(1, true)); | |
| 5137 MockWrite writes[] = { | |
| 5138 CreateMockWrite(*stream1_syn, 0, SYNCHRONOUS), | |
| 5139 }; | |
| 5140 | |
| 5141 scoped_ptr<SpdyHeaderBlock> initial_headers(new SpdyHeaderBlock()); | |
| 5142 spdy_util_.AddUrlToHeaderBlock( | |
| 5143 "http://www.google.com/foo.dat", initial_headers.get()); | |
| 5144 scoped_ptr<SpdyFrame> stream2_syn( | |
| 5145 spdy_util_.ConstructSpdyControlFrame(initial_headers.Pass(), | |
| 5146 false, | |
| 5147 2, | |
| 5148 LOWEST, | |
| 5149 SYN_STREAM, | |
| 5150 CONTROL_FLAG_NONE, | |
| 5151 1)); | |
| 5152 | |
| 5153 scoped_ptr<SpdyHeaderBlock> middle_headers(new SpdyHeaderBlock()); | |
| 5154 (*middle_headers)["hello"] = "bye"; | |
| 5155 scoped_ptr<SpdyFrame> stream2_headers1( | |
| 5156 spdy_util_.ConstructSpdyControlFrame(middle_headers.Pass(), | |
| 5157 false, | |
| 5158 2, | |
| 5159 LOWEST, | |
| 5160 HEADERS, | |
| 5161 CONTROL_FLAG_NONE, | |
| 5162 0)); | |
| 5163 | |
| 5164 scoped_ptr<SpdyHeaderBlock> late_headers(new SpdyHeaderBlock()); | |
| 5165 (*late_headers)[spdy_util_.GetStatusKey()] = "200"; | |
| 5166 (*late_headers)[spdy_util_.GetVersionKey()] = "HTTP/1.1"; | |
| 5167 scoped_ptr<SpdyFrame> stream2_headers2( | |
| 5168 spdy_util_.ConstructSpdyControlFrame(late_headers.Pass(), | |
| 5169 false, | |
| 5170 2, | |
| 5171 LOWEST, | |
| 5172 HEADERS, | |
| 5173 CONTROL_FLAG_NONE, | |
| 5174 0)); | |
| 5175 | |
| 5176 scoped_ptr<SpdyFrame> | |
| 5177 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); | |
| 5178 const char kPushedData[] = "pushed"; | |
| 5179 scoped_ptr<SpdyFrame> stream2_body( | |
| 5180 spdy_util_.ConstructSpdyBodyFrame( | |
| 5181 2, kPushedData, strlen(kPushedData), true)); | |
| 5182 MockRead reads[] = { | |
| 5183 CreateMockRead(*stream1_reply, 1), | |
| 5184 CreateMockRead(*stream2_syn, 2), | |
| 5185 CreateMockRead(*stream1_body, 3), | |
| 5186 CreateMockRead(*stream2_headers1, 4), | |
| 5187 CreateMockRead(*stream2_headers2, 5), | |
| 5188 CreateMockRead(*stream2_body, 6), | |
| 5189 MockRead(ASYNC, 0, 7), // EOF | |
| 5190 }; | |
| 5191 | |
| 5192 HttpResponseInfo response; | |
| 5193 HttpResponseInfo response2; | |
| 5194 std::string expected_push_result("pushed"); | |
| 5195 DeterministicSocketData data(reads, arraysize(reads), | |
| 5196 writes, arraysize(writes)); | |
| 5197 | |
| 5198 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY, | |
| 5199 BoundNetLog(), GetParam(), NULL); | |
| 5200 helper.SetDeterministic(); | |
| 5201 helper.AddDeterministicData(&data); | |
| 5202 helper.RunPreTestSetup(); | |
| 5203 | |
| 5204 HttpNetworkTransaction* trans = helper.trans(); | |
| 5205 | |
| 5206 // Run until we've received the primary SYN_STREAM, the pushed SYN_STREAM, | |
| 5207 // the first HEADERS frame, and the body of the primary stream, but before | |
| 5208 // we've received the final HEADERS for the pushed stream. | |
| 5209 data.SetStop(4); | |
| 5210 | |
| 5211 // Start the transaction. | |
| 5212 TestCompletionCallback callback; | |
| 5213 int rv = trans->Start( | |
| 5214 &CreateGetRequest(), callback.callback(), BoundNetLog()); | |
| 5215 EXPECT_EQ(ERR_IO_PENDING, rv); | |
| 5216 data.Run(); | |
| 5217 rv = callback.WaitForResult(); | |
| 5218 EXPECT_EQ(0, rv); | |
| 5219 | |
| 5220 // Request the pushed path. At this point, we've received the push, but the | |
| 5221 // headers are not yet complete. | |
| 5222 scoped_ptr<HttpNetworkTransaction> trans2( | |
| 5223 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get())); | |
| 5224 rv = trans2->Start( | |
| 5225 &CreateGetPushRequest(), callback.callback(), BoundNetLog()); | |
| 5226 EXPECT_EQ(ERR_IO_PENDING, rv); | |
| 5227 data.RunFor(3); | |
| 5228 base::MessageLoop::current()->RunUntilIdle(); | |
| 5229 | |
| 5230 // Read the server push body. | |
| 5231 std::string result2; | |
| 5232 ReadResult(trans2.get(), &data, &result2); | |
| 5233 // Read the response body. | |
| 5234 std::string result; | |
| 5235 ReadResult(trans, &data, &result); | |
| 5236 | |
| 5237 // Verify that the received push data is same as the expected push data. | |
| 5238 EXPECT_EQ(expected_push_result, result2); | |
| 5239 | |
| 5240 // Verify the SYN_REPLY. | |
| 5241 // Copy the response info, because trans goes away. | |
| 5242 response = *trans->GetResponseInfo(); | |
| 5243 response2 = *trans2->GetResponseInfo(); | |
| 5244 | |
| 5245 VerifyStreamsClosed(helper); | |
| 5246 | |
| 5247 // Verify the SYN_REPLY. | |
| 5248 EXPECT_TRUE(response.headers.get() != NULL); | |
| 5249 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine()); | |
| 5250 | |
| 5251 // Verify the pushed stream. | |
| 5252 EXPECT_TRUE(response2.headers.get() != NULL); | |
| 5253 EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine()); | |
| 5254 | |
| 5255 // Verify we got all the headers | |
| 5256 if (spdy_util_.spdy_version() < SPDY3) { | |
| 5257 EXPECT_TRUE(response2.headers->HasHeaderValue( | |
| 5258 "url", | |
| 5259 "http://www.google.com/foo.dat")); | |
| 5260 } else { | |
| 5261 EXPECT_TRUE(response2.headers->HasHeaderValue( | |
| 5262 "scheme", "http")); | |
| 5263 EXPECT_TRUE(response2.headers->HasHeaderValue( | |
| 5264 "host", "www.google.com")); | |
| 5265 EXPECT_TRUE(response2.headers->HasHeaderValue( | |
| 5266 "path", "/foo.dat")); | |
| 5267 } | |
| 5268 EXPECT_TRUE(response2.headers->HasHeaderValue("hello", "bye")); | |
| 5269 EXPECT_TRUE(response2.headers->HasHeaderValue("status", "200")); | |
| 5270 EXPECT_TRUE(response2.headers->HasHeaderValue("version", "HTTP/1.1")); | |
| 5271 | |
| 5272 // Read the final EOF (which will close the session) | |
| 5273 data.RunFor(1); | |
| 5274 | |
| 5275 // Verify that we consumed all test data. | |
| 5276 EXPECT_TRUE(data.at_read_eof()); | |
| 5277 EXPECT_TRUE(data.at_write_eof()); | |
| 5278 } | |
| 5279 | |
| 5280 TEST_P(SpdyNetworkTransactionTest, ServerPushWithNoStatusHeaderFrames) { | |
| 5281 // We push a stream and attempt to claim it before the headers come down. | |
| 5282 scoped_ptr<SpdyFrame> stream1_syn( | |
| 5283 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true)); | |
| 5284 scoped_ptr<SpdyFrame> stream1_body( | |
| 5285 spdy_util_.ConstructSpdyBodyFrame(1, true)); | |
| 5286 MockWrite writes[] = { | |
| 5287 CreateMockWrite(*stream1_syn, 0, SYNCHRONOUS), | |
| 5288 }; | |
| 5289 | |
| 5290 scoped_ptr<SpdyHeaderBlock> initial_headers(new SpdyHeaderBlock()); | |
| 5291 spdy_util_.AddUrlToHeaderBlock( | |
| 5292 "http://www.google.com/foo.dat", initial_headers.get()); | |
| 5293 scoped_ptr<SpdyFrame> stream2_syn( | |
| 5294 spdy_util_.ConstructSpdyControlFrame(initial_headers.Pass(), | |
| 5295 false, | |
| 5296 2, | |
| 5297 LOWEST, | |
| 5298 SYN_STREAM, | |
| 5299 CONTROL_FLAG_NONE, | |
| 5300 1)); | |
| 5301 | |
| 5302 scoped_ptr<SpdyHeaderBlock> middle_headers(new SpdyHeaderBlock()); | |
| 5303 (*middle_headers)["hello"] = "bye"; | |
| 5304 scoped_ptr<SpdyFrame> stream2_headers1( | |
| 5305 spdy_util_.ConstructSpdyControlFrame(middle_headers.Pass(), | |
| 5306 false, | |
| 5307 2, | |
| 5308 LOWEST, | |
| 5309 HEADERS, | |
| 5310 CONTROL_FLAG_NONE, | |
| 5311 0)); | |
| 5312 | |
| 5313 scoped_ptr<SpdyFrame> | |
| 5314 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); | |
| 5315 const char kPushedData[] = "pushed"; | |
| 5316 scoped_ptr<SpdyFrame> stream2_body( | |
| 5317 spdy_util_.ConstructSpdyBodyFrame( | |
| 5318 2, kPushedData, strlen(kPushedData), true)); | |
| 5319 MockRead reads[] = { | |
| 5320 CreateMockRead(*stream1_reply, 1), | |
| 5321 CreateMockRead(*stream2_syn, 2), | |
| 5322 CreateMockRead(*stream1_body, 3), | |
| 5323 CreateMockRead(*stream2_headers1, 4), | |
| 5324 CreateMockRead(*stream2_body, 5), | |
| 5325 MockRead(ASYNC, 0, 6), // EOF | |
| 5326 }; | |
| 5327 | |
| 5328 DeterministicSocketData data(reads, arraysize(reads), | |
| 5329 writes, arraysize(writes)); | |
| 5330 | |
| 5331 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY, | |
| 5332 BoundNetLog(), GetParam(), NULL); | |
| 5333 helper.SetDeterministic(); | |
| 5334 helper.AddDeterministicData(&data); | |
| 5335 helper.RunPreTestSetup(); | |
| 5336 | |
| 5337 HttpNetworkTransaction* trans = helper.trans(); | |
| 5338 | |
| 5339 // Run until we've received the primary SYN_STREAM, the pushed SYN_STREAM, | |
| 5340 // the first HEADERS frame, and the body of the primary stream, but before | |
| 5341 // we've received the final HEADERS for the pushed stream. | |
| 5342 data.SetStop(4); | |
| 5343 | |
| 5344 // Start the transaction. | |
| 5345 TestCompletionCallback callback; | |
| 5346 int rv = trans->Start( | |
| 5347 &CreateGetRequest(), callback.callback(), BoundNetLog()); | |
| 5348 EXPECT_EQ(ERR_IO_PENDING, rv); | |
| 5349 data.Run(); | |
| 5350 rv = callback.WaitForResult(); | |
| 5351 EXPECT_EQ(0, rv); | |
| 5352 | |
| 5353 // Request the pushed path. At this point, we've received the push, but the | |
| 5354 // headers are not yet complete. | |
| 5355 scoped_ptr<HttpNetworkTransaction> trans2( | |
| 5356 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get())); | |
| 5357 rv = trans2->Start( | |
| 5358 &CreateGetPushRequest(), callback.callback(), BoundNetLog()); | |
| 5359 EXPECT_EQ(ERR_IO_PENDING, rv); | |
| 5360 data.RunFor(2); | |
| 5361 base::MessageLoop::current()->RunUntilIdle(); | |
| 5362 | |
| 5363 // Read the server push body. | |
| 5364 std::string result2; | |
| 5365 ReadResult(trans2.get(), &data, &result2); | |
| 5366 // Read the response body. | |
| 5367 std::string result; | |
| 5368 ReadResult(trans, &data, &result); | |
| 5369 EXPECT_EQ("hello!", result); | |
| 5370 | |
| 5371 // Verify that we haven't received any push data. | |
| 5372 EXPECT_EQ("", result2); | |
| 5373 | |
| 5374 // Verify the SYN_REPLY. | |
| 5375 // Copy the response info, because trans goes away. | |
| 5376 HttpResponseInfo response = *trans->GetResponseInfo(); | |
| 5377 ASSERT_TRUE(trans2->GetResponseInfo() == NULL); | |
| 5378 | |
| 5379 VerifyStreamsClosed(helper); | |
| 5380 | |
| 5381 // Verify the SYN_REPLY. | |
| 5382 EXPECT_TRUE(response.headers.get() != NULL); | |
| 5383 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine()); | |
| 5384 | |
| 5385 // Read the final EOF (which will close the session). | |
| 5386 data.RunFor(1); | |
| 5387 | |
| 5388 // Verify that we consumed all test data. | |
| 5389 EXPECT_TRUE(data.at_read_eof()); | |
| 5390 EXPECT_TRUE(data.at_write_eof()); | |
| 5391 } | |
| 5392 | |
| 5393 TEST_P(SpdyNetworkTransactionTest, SynReplyWithHeaders) { | |
| 5394 scoped_ptr<SpdyFrame> req( | |
| 5395 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true)); | |
| 5396 scoped_ptr<SpdyFrame> rst( | |
| 5397 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_PROTOCOL_ERROR)); | |
| 5398 MockWrite writes[] = { | |
| 5399 CreateMockWrite(*req), | |
| 5400 CreateMockWrite(*rst), | |
| 5401 }; | |
| 5402 | |
| 5403 scoped_ptr<SpdyHeaderBlock> initial_headers(new SpdyHeaderBlock()); | |
| 5404 (*initial_headers)[spdy_util_.GetStatusKey()] = "200 OK"; | |
| 5405 (*initial_headers)[spdy_util_.GetVersionKey()] = "HTTP/1.1"; | |
| 5406 scoped_ptr<SpdyFrame> stream1_reply( | |
| 5407 spdy_util_.ConstructSpdyControlFrame(initial_headers.Pass(), | |
| 5408 false, | |
| 5409 1, | |
| 5410 LOWEST, | |
| 5411 SYN_REPLY, | |
| 5412 CONTROL_FLAG_NONE, | |
| 5413 0)); | |
| 5414 | |
| 5415 scoped_ptr<SpdyHeaderBlock> late_headers(new SpdyHeaderBlock()); | |
| 5416 (*late_headers)["hello"] = "bye"; | |
| 5417 scoped_ptr<SpdyFrame> stream1_headers( | |
| 5418 spdy_util_.ConstructSpdyControlFrame(late_headers.Pass(), | |
| 5419 false, | |
| 5420 1, | |
| 5421 LOWEST, | |
| 5422 HEADERS, | |
| 5423 CONTROL_FLAG_NONE, | |
| 5424 0)); | |
| 5425 scoped_ptr<SpdyFrame> stream1_body( | |
| 5426 spdy_util_.ConstructSpdyBodyFrame(1, true)); | |
| 5427 MockRead reads[] = { | |
| 5428 CreateMockRead(*stream1_reply), | |
| 5429 CreateMockRead(*stream1_headers), | |
| 5430 CreateMockRead(*stream1_body), | |
| 5431 MockRead(ASYNC, 0, 0) // EOF | |
| 5432 }; | |
| 5433 | |
| 5434 DelayedSocketData data(1, reads, arraysize(reads), | |
| 5435 writes, arraysize(writes)); | |
| 5436 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY, | |
| 5437 BoundNetLog(), GetParam(), NULL); | |
| 5438 helper.RunToCompletion(&data); | |
| 5439 TransactionHelperResult out = helper.output(); | |
| 5440 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, out.rv); | |
| 5441 } | |
| 5442 | |
| 5443 TEST_P(SpdyNetworkTransactionTest, SynReplyWithLateHeaders) { | |
| 5444 scoped_ptr<SpdyFrame> req( | |
| 5445 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true)); | |
| 5446 scoped_ptr<SpdyFrame> rst( | |
| 5447 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_PROTOCOL_ERROR)); | |
| 5448 MockWrite writes[] = { | |
| 5449 CreateMockWrite(*req), | |
| 5450 CreateMockWrite(*rst), | |
| 5451 }; | |
| 5452 | |
| 5453 scoped_ptr<SpdyHeaderBlock> initial_headers(new SpdyHeaderBlock()); | |
| 5454 (*initial_headers)[spdy_util_.GetStatusKey()] = "200 OK"; | |
| 5455 (*initial_headers)[spdy_util_.GetVersionKey()] = "HTTP/1.1"; | |
| 5456 scoped_ptr<SpdyFrame> stream1_reply( | |
| 5457 spdy_util_.ConstructSpdyControlFrame(initial_headers.Pass(), | |
| 5458 false, | |
| 5459 1, | |
| 5460 LOWEST, | |
| 5461 SYN_REPLY, | |
| 5462 CONTROL_FLAG_NONE, | |
| 5463 0)); | |
| 5464 | |
| 5465 scoped_ptr<SpdyHeaderBlock> late_headers(new SpdyHeaderBlock()); | |
| 5466 (*late_headers)["hello"] = "bye"; | |
| 5467 scoped_ptr<SpdyFrame> stream1_headers( | |
| 5468 spdy_util_.ConstructSpdyControlFrame(late_headers.Pass(), | |
| 5469 false, | |
| 5470 1, | |
| 5471 LOWEST, | |
| 5472 HEADERS, | |
| 5473 CONTROL_FLAG_NONE, | |
| 5474 0)); | |
| 5475 scoped_ptr<SpdyFrame> stream1_body( | |
| 5476 spdy_util_.ConstructSpdyBodyFrame(1, false)); | |
| 5477 scoped_ptr<SpdyFrame> stream1_body2( | |
| 5478 spdy_util_.ConstructSpdyBodyFrame(1, true)); | |
| 5479 MockRead reads[] = { | |
| 5480 CreateMockRead(*stream1_reply), | |
| 5481 CreateMockRead(*stream1_body), | |
| 5482 CreateMockRead(*stream1_headers), | |
| 5483 CreateMockRead(*stream1_body2), | |
| 5484 MockRead(ASYNC, 0, 0) // EOF | |
| 5485 }; | |
| 5486 | |
| 5487 DelayedSocketData data(1, reads, arraysize(reads), | |
| 5488 writes, arraysize(writes)); | |
| 5489 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY, | |
| 5490 BoundNetLog(), GetParam(), NULL); | |
| 5491 helper.RunToCompletion(&data); | |
| 5492 TransactionHelperResult out = helper.output(); | |
| 5493 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, out.rv); | |
| 5494 } | |
| 5495 | |
| 5496 TEST_P(SpdyNetworkTransactionTest, ServerPushCrossOriginCorrectness) { | |
| 5497 // In this test we want to verify that we can't accidentally push content | |
| 5498 // which can't be pushed by this content server. | |
| 5499 // This test assumes that: | |
| 5500 // - if we're requesting http://www.foo.com/barbaz | |
| 5501 // - the browser has made a connection to "www.foo.com". | |
| 5502 | |
| 5503 // A list of the URL to fetch, followed by the URL being pushed. | |
| 5504 static const char* const kTestCases[] = { | |
| 5505 "http://www.google.com/foo.html", | |
| 5506 "http://www.google.com:81/foo.js", // Bad port | |
| 5507 | |
| 5508 "http://www.google.com/foo.html", | |
| 5509 "https://www.google.com/foo.js", // Bad protocol | |
| 5510 | |
| 5511 "http://www.google.com/foo.html", | |
| 5512 "ftp://www.google.com/foo.js", // Invalid Protocol | |
| 5513 | |
| 5514 "http://www.google.com/foo.html", | |
| 5515 "http://blat.www.google.com/foo.js", // Cross subdomain | |
| 5516 | |
| 5517 "http://www.google.com/foo.html", | |
| 5518 "http://www.foo.com/foo.js", // Cross domain | |
| 5519 }; | |
| 5520 | |
| 5521 for (size_t index = 0; index < arraysize(kTestCases); index += 2) { | |
| 5522 const char* url_to_fetch = kTestCases[index]; | |
| 5523 const char* url_to_push = kTestCases[index + 1]; | |
| 5524 | |
| 5525 scoped_ptr<SpdyFrame> stream1_syn( | |
| 5526 spdy_util_.ConstructSpdyGet(url_to_fetch, false, 1, LOWEST)); | |
| 5527 scoped_ptr<SpdyFrame> stream1_body( | |
| 5528 spdy_util_.ConstructSpdyBodyFrame(1, true)); | |
| 5529 scoped_ptr<SpdyFrame> push_rst( | |
| 5530 spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_REFUSED_STREAM)); | |
| 5531 MockWrite writes[] = { | |
| 5532 CreateMockWrite(*stream1_syn, 1), | |
| 5533 CreateMockWrite(*push_rst, 4), | |
| 5534 }; | |
| 5535 | |
| 5536 scoped_ptr<SpdyFrame> | |
| 5537 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); | |
| 5538 scoped_ptr<SpdyFrame> | |
| 5539 stream2_syn(spdy_util_.ConstructSpdyPush(NULL, | |
| 5540 0, | |
| 5541 2, | |
| 5542 1, | |
| 5543 url_to_push)); | |
| 5544 const char kPushedData[] = "pushed"; | |
| 5545 scoped_ptr<SpdyFrame> stream2_body( | |
| 5546 spdy_util_.ConstructSpdyBodyFrame( | |
| 5547 2, kPushedData, strlen(kPushedData), true)); | |
| 5548 scoped_ptr<SpdyFrame> rst( | |
| 5549 spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_CANCEL)); | |
| 5550 | |
| 5551 MockRead reads[] = { | |
| 5552 CreateMockRead(*stream1_reply, 2), | |
| 5553 CreateMockRead(*stream2_syn, 3), | |
| 5554 CreateMockRead(*stream1_body, 5, SYNCHRONOUS), | |
| 5555 CreateMockRead(*stream2_body, 6), | |
| 5556 MockRead(ASYNC, ERR_IO_PENDING, 7), // Force a pause | |
| 5557 }; | |
| 5558 | |
| 5559 HttpResponseInfo response; | |
| 5560 OrderedSocketData data(reads, arraysize(reads), | |
| 5561 writes, arraysize(writes)); | |
| 5562 | |
| 5563 HttpRequestInfo request; | |
| 5564 request.method = "GET"; | |
| 5565 request.url = GURL(url_to_fetch); | |
| 5566 request.load_flags = 0; | |
| 5567 | |
| 5568 // Enable cross-origin push. Since we are not using a proxy, this should | |
| 5569 // not actually enable cross-origin SPDY push. | |
| 5570 scoped_ptr<SpdySessionDependencies> session_deps( | |
| 5571 CreateSpdySessionDependencies(GetParam())); | |
| 5572 session_deps->trusted_spdy_proxy = "123.45.67.89:8080"; | |
| 5573 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY, | |
| 5574 BoundNetLog(), GetParam(), | |
| 5575 session_deps.release()); | |
| 5576 helper.RunPreTestSetup(); | |
| 5577 helper.AddData(&data); | |
| 5578 | |
| 5579 HttpNetworkTransaction* trans = helper.trans(); | |
| 5580 | |
| 5581 // Start the transaction with basic parameters. | |
| 5582 TestCompletionCallback callback; | |
| 5583 | |
| 5584 int rv = trans->Start(&request, callback.callback(), BoundNetLog()); | |
| 5585 EXPECT_EQ(ERR_IO_PENDING, rv); | |
| 5586 rv = callback.WaitForResult(); | |
| 5587 | |
| 5588 // Read the response body. | |
| 5589 std::string result; | |
| 5590 ReadResult(trans, &data, &result); | |
| 5591 | |
| 5592 // Verify that we consumed all test data. | |
| 5593 EXPECT_TRUE(data.at_read_eof()); | |
| 5594 EXPECT_TRUE(data.at_write_eof()); | |
| 5595 | |
| 5596 // Verify the SYN_REPLY. | |
| 5597 // Copy the response info, because trans goes away. | |
| 5598 response = *trans->GetResponseInfo(); | |
| 5599 | |
| 5600 VerifyStreamsClosed(helper); | |
| 5601 | |
| 5602 // Verify the SYN_REPLY. | |
| 5603 EXPECT_TRUE(response.headers.get() != NULL); | |
| 5604 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine()); | |
| 5605 } | |
| 5606 } | |
| 5607 | |
| 5608 TEST_P(SpdyNetworkTransactionTest, RetryAfterRefused) { | |
| 5609 // Construct the request. | |
| 5610 scoped_ptr<SpdyFrame> req( | |
| 5611 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true)); | |
| 5612 scoped_ptr<SpdyFrame> req2( | |
| 5613 spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, LOWEST, true)); | |
| 5614 MockWrite writes[] = { | |
| 5615 CreateMockWrite(*req, 1), | |
| 5616 CreateMockWrite(*req2, 3), | |
| 5617 }; | |
| 5618 | |
| 5619 scoped_ptr<SpdyFrame> refused( | |
| 5620 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_REFUSED_STREAM)); | |
| 5621 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3)); | |
| 5622 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(3, true)); | |
| 5623 MockRead reads[] = { | |
| 5624 CreateMockRead(*refused, 2), | |
| 5625 CreateMockRead(*resp, 4), | |
| 5626 CreateMockRead(*body, 5), | |
| 5627 MockRead(ASYNC, 0, 6) // EOF | |
| 5628 }; | |
| 5629 | |
| 5630 OrderedSocketData data(reads, arraysize(reads), | |
| 5631 writes, arraysize(writes)); | |
| 5632 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY, | |
| 5633 BoundNetLog(), GetParam(), NULL); | |
| 5634 | |
| 5635 helper.RunPreTestSetup(); | |
| 5636 helper.AddData(&data); | |
| 5637 | |
| 5638 HttpNetworkTransaction* trans = helper.trans(); | |
| 5639 | |
| 5640 // Start the transaction with basic parameters. | |
| 5641 TestCompletionCallback callback; | |
| 5642 int rv = trans->Start( | |
| 5643 &CreateGetRequest(), callback.callback(), BoundNetLog()); | |
| 5644 EXPECT_EQ(ERR_IO_PENDING, rv); | |
| 5645 rv = callback.WaitForResult(); | |
| 5646 EXPECT_EQ(OK, rv); | |
| 5647 | |
| 5648 // Verify that we consumed all test data. | |
| 5649 EXPECT_TRUE(data.at_read_eof()) << "Read count: " | |
| 5650 << data.read_count() | |
| 5651 << " Read index: " | |
| 5652 << data.read_index(); | |
| 5653 EXPECT_TRUE(data.at_write_eof()) << "Write count: " | |
| 5654 << data.write_count() | |
| 5655 << " Write index: " | |
| 5656 << data.write_index(); | |
| 5657 | |
| 5658 // Verify the SYN_REPLY. | |
| 5659 HttpResponseInfo response = *trans->GetResponseInfo(); | |
| 5660 EXPECT_TRUE(response.headers.get() != NULL); | |
| 5661 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine()); | |
| 5662 } | |
| 5663 | |
| 5664 TEST_P(SpdyNetworkTransactionTest, OutOfOrderSynStream) { | |
| 5665 // This first request will start to establish the SpdySession. | |
| 5666 // Then we will start the second (MEDIUM priority) and then third | |
| 5667 // (HIGHEST priority) request in such a way that the third will actually | |
| 5668 // start before the second, causing the second to be numbered differently | |
| 5669 // than the order they were created. | |
| 5670 scoped_ptr<SpdyFrame> req1( | |
| 5671 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true)); | |
| 5672 scoped_ptr<SpdyFrame> req2( | |
| 5673 spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, HIGHEST, true)); | |
| 5674 scoped_ptr<SpdyFrame> req3( | |
| 5675 spdy_util_.ConstructSpdyGet(NULL, 0, false, 5, MEDIUM, true)); | |
| 5676 MockWrite writes[] = { | |
| 5677 CreateMockWrite(*req1, 0), | |
| 5678 CreateMockWrite(*req2, 3), | |
| 5679 CreateMockWrite(*req3, 4), | |
| 5680 }; | |
| 5681 | |
| 5682 scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); | |
| 5683 scoped_ptr<SpdyFrame> body1(spdy_util_.ConstructSpdyBodyFrame(1, true)); | |
| 5684 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3)); | |
| 5685 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(3, true)); | |
| 5686 scoped_ptr<SpdyFrame> resp3(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 5)); | |
| 5687 scoped_ptr<SpdyFrame> body3(spdy_util_.ConstructSpdyBodyFrame(5, true)); | |
| 5688 MockRead reads[] = { | |
| 5689 CreateMockRead(*resp1, 1), | |
| 5690 CreateMockRead(*body1, 2), | |
| 5691 CreateMockRead(*resp2, 5), | |
| 5692 CreateMockRead(*body2, 6), | |
| 5693 CreateMockRead(*resp3, 7), | |
| 5694 CreateMockRead(*body3, 8), | |
| 5695 MockRead(ASYNC, 0, 9) // EOF | |
| 5696 }; | |
| 5697 | |
| 5698 DeterministicSocketData data(reads, arraysize(reads), | |
| 5699 writes, arraysize(writes)); | |
| 5700 NormalSpdyTransactionHelper helper(CreateGetRequest(), LOWEST, | |
| 5701 BoundNetLog(), GetParam(), NULL); | |
| 5702 helper.SetDeterministic(); | |
| 5703 helper.RunPreTestSetup(); | |
| 5704 helper.AddDeterministicData(&data); | |
| 5705 | |
| 5706 // Start the first transaction to set up the SpdySession | |
| 5707 HttpNetworkTransaction* trans = helper.trans(); | |
| 5708 TestCompletionCallback callback; | |
| 5709 HttpRequestInfo info1 = CreateGetRequest(); | |
| 5710 int rv = trans->Start(&info1, callback.callback(), BoundNetLog()); | |
| 5711 EXPECT_EQ(ERR_IO_PENDING, rv); | |
| 5712 | |
| 5713 // Run the message loop, but do not allow the write to complete. | |
| 5714 // This leaves the SpdySession with a write pending, which prevents | |
| 5715 // SpdySession from attempting subsequent writes until this write completes. | |
| 5716 base::MessageLoop::current()->RunUntilIdle(); | |
| 5717 | |
| 5718 // Now, start both new transactions | |
| 5719 HttpRequestInfo info2 = CreateGetRequest(); | |
| 5720 TestCompletionCallback callback2; | |
| 5721 scoped_ptr<HttpNetworkTransaction> trans2( | |
| 5722 new HttpNetworkTransaction(MEDIUM, helper.session().get())); | |
| 5723 rv = trans2->Start(&info2, callback2.callback(), BoundNetLog()); | |
| 5724 EXPECT_EQ(ERR_IO_PENDING, rv); | |
| 5725 base::MessageLoop::current()->RunUntilIdle(); | |
| 5726 | |
| 5727 HttpRequestInfo info3 = CreateGetRequest(); | |
| 5728 TestCompletionCallback callback3; | |
| 5729 scoped_ptr<HttpNetworkTransaction> trans3( | |
| 5730 new HttpNetworkTransaction(HIGHEST, helper.session().get())); | |
| 5731 rv = trans3->Start(&info3, callback3.callback(), BoundNetLog()); | |
| 5732 EXPECT_EQ(ERR_IO_PENDING, rv); | |
| 5733 base::MessageLoop::current()->RunUntilIdle(); | |
| 5734 | |
| 5735 // We now have two SYN_STREAM frames queued up which will be | |
| 5736 // dequeued only once the first write completes, which we | |
| 5737 // now allow to happen. | |
| 5738 data.RunFor(2); | |
| 5739 EXPECT_EQ(OK, callback.WaitForResult()); | |
| 5740 | |
| 5741 // And now we can allow everything else to run to completion. | |
| 5742 data.SetStop(10); | |
| 5743 data.Run(); | |
| 5744 EXPECT_EQ(OK, callback2.WaitForResult()); | |
| 5745 EXPECT_EQ(OK, callback3.WaitForResult()); | |
| 5746 | |
| 5747 helper.VerifyDataConsumed(); | |
| 5748 } | |
| 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); | |
| 5910 helper.RunPreTestSetup(); | 5835 helper.RunPreTestSetup(); |
| 5911 | 5836 |
| 5912 HttpNetworkTransaction* trans = helper.trans(); | 5837 HttpNetworkTransaction* trans = helper.trans(); |
| 5913 | 5838 |
| 5914 // Run until we've received the primary SYN_STREAM, the pushed SYN_STREAM, | |
| 5915 // and the body of the primary stream, but before we've received the HEADERS | |
| 5916 // for the pushed stream. | |
| 5917 data.SetStop(3); | |
| 5918 | |
| 5919 // Start the transaction. | |
| 5920 TestCompletionCallback callback; | 5839 TestCompletionCallback callback; |
| 5921 int rv = trans->Start( | 5840 int rv = trans->Start(&helper.request(), callback.callback(), BoundNetLog()); |
| 5922 &CreateGetRequest(), callback.callback(), BoundNetLog()); | 5841 |
| 5923 EXPECT_EQ(ERR_IO_PENDING, rv); | 5842 EXPECT_EQ(ERR_IO_PENDING, rv); |
| 5924 data.Run(); | 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 | |
| 5925 rv = callback.WaitForResult(); | 5856 rv = callback.WaitForResult(); |
| 5926 EXPECT_EQ(0, rv); | 5857 EXPECT_EQ(OK, rv); |
| 5927 | 5858 |
| 5928 // Request the pushed path. At this point, we've received the push, but the | 5859 helper.VerifyDataConsumed(); |
| 5929 // headers are not yet complete. | |
| 5930 scoped_ptr<HttpNetworkTransaction> trans2( | |
| 5931 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get())); | |
| 5932 rv = trans2->Start( | |
| 5933 &CreateGetPushRequest(), callback.callback(), BoundNetLog()); | |
| 5934 EXPECT_EQ(ERR_IO_PENDING, rv); | |
| 5935 data.RunFor(3); | |
| 5936 base::MessageLoop::current()->RunUntilIdle(); | |
| 5937 | |
| 5938 // Read the server push body. | |
| 5939 std::string result2; | |
| 5940 ReadResult(trans2.get(), &data, &result2); | |
| 5941 // Read the response body. | |
| 5942 std::string result; | |
| 5943 ReadResult(trans, &data, &result); | |
| 5944 | |
| 5945 // Verify that the received push data is same as the expected push data. | |
| 5946 EXPECT_EQ(result2.compare(expected_push_result), 0) | |
| 5947 << "Received data: " | |
| 5948 << result2 | |
| 5949 << "||||| Expected data: " | |
| 5950 << expected_push_result; | |
| 5951 | |
| 5952 // Verify the SYN_REPLY. | |
| 5953 // Copy the response info, because trans goes away. | |
| 5954 response = *trans->GetResponseInfo(); | |
| 5955 response2 = *trans2->GetResponseInfo(); | |
| 5956 | |
| 5957 VerifyStreamsClosed(helper); | |
| 5958 | |
| 5959 // Verify the SYN_REPLY. | |
| 5960 EXPECT_TRUE(response.headers.get() != NULL); | |
| 5961 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine()); | |
| 5962 | |
| 5963 // Verify the pushed stream. | |
| 5964 EXPECT_TRUE(response2.headers.get() != NULL); | |
| 5965 EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine()); | |
| 5966 | |
| 5967 // Read the final EOF (which will close the session) | |
| 5968 data.RunFor(1); | |
| 5969 | |
| 5970 // Verify that we consumed all test data. | |
| 5971 EXPECT_TRUE(data.at_read_eof()); | |
| 5972 EXPECT_TRUE(data.at_write_eof()); | |
| 5973 } | 5860 } |
| 5974 | 5861 |
| 5975 TEST_P(SpdyNetworkTransactionTest, ServerPushWithTwoHeaderFrames) { | 5862 // Test that received data frames and sent WINDOW_UPDATE frames change |
| 5976 if (GetParam().protocol > kProtoSPDY3) | 5863 // the recv_window_size_ correctly. |
| 5864 TEST_P(SpdyNetworkTransactionTest, WindowUpdateSent) { | |
| 5865 if (GetParam().protocol < kProtoSPDY3) | |
| 5977 return; | 5866 return; |
| 5978 | 5867 |
| 5979 // We push a stream and attempt to claim it before the headers come down. | 5868 // Set the data in the body frame large enough to trigger sending a |
| 5980 static const unsigned char kPushBodyFrame[] = { | 5869 // WINDOW_UPDATE by the stream. |
| 5981 0x00, 0x00, 0x00, 0x02, // header, ID | 5870 const std::string body_data(kSpdyStreamInitialWindowSize / 2 + 1, 'x'); |
| 5982 0x01, 0x00, 0x00, 0x06, // FIN, length | 5871 |
| 5983 'p', 'u', 's', 'h', 'e', 'd' // "pushed" | 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 | |
| 5984 }; | 5899 }; |
| 5985 scoped_ptr<SpdyFrame> stream1_syn( | 5900 |
| 5986 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true)); | 5901 DelayedSocketData data(1, reads, arraysize(reads), |
| 5987 scoped_ptr<SpdyFrame> stream1_body( | 5902 vector_as_array(&writes), writes.size()); |
| 5988 spdy_util_.ConstructSpdyBodyFrame(1, true)); | |
| 5989 MockWrite writes[] = { | |
| 5990 CreateMockWrite(*stream1_syn, 0, SYNCHRONOUS), | |
| 5991 }; | |
| 5992 | |
| 5993 scoped_ptr<SpdyHeaderBlock> initial_headers(new SpdyHeaderBlock()); | |
| 5994 spdy_util_.AddUrlToHeaderBlock( | |
| 5995 "http://www.google.com/foo.dat", initial_headers.get()); | |
| 5996 scoped_ptr<SpdyFrame> stream2_syn( | |
| 5997 spdy_util_.ConstructSpdyControlFrame(initial_headers.Pass(), | |
| 5998 false, | |
| 5999 2, | |
| 6000 LOWEST, | |
| 6001 SYN_STREAM, | |
| 6002 CONTROL_FLAG_NONE, | |
| 6003 1)); | |
| 6004 | |
| 6005 scoped_ptr<SpdyHeaderBlock> middle_headers(new SpdyHeaderBlock()); | |
| 6006 (*middle_headers)["hello"] = "bye"; | |
| 6007 scoped_ptr<SpdyFrame> stream2_headers1( | |
| 6008 spdy_util_.ConstructSpdyControlFrame(middle_headers.Pass(), | |
| 6009 false, | |
| 6010 2, | |
| 6011 LOWEST, | |
| 6012 HEADERS, | |
| 6013 CONTROL_FLAG_NONE, | |
| 6014 0)); | |
| 6015 | |
| 6016 scoped_ptr<SpdyHeaderBlock> late_headers(new SpdyHeaderBlock()); | |
| 6017 (*late_headers)[spdy_util_.GetStatusKey()] = "200"; | |
| 6018 (*late_headers)[spdy_util_.GetVersionKey()] = "HTTP/1.1"; | |
| 6019 scoped_ptr<SpdyFrame> stream2_headers2( | |
| 6020 spdy_util_.ConstructSpdyControlFrame(late_headers.Pass(), | |
| 6021 false, | |
| 6022 2, | |
| 6023 LOWEST, | |
| 6024 HEADERS, | |
| 6025 CONTROL_FLAG_NONE, | |
| 6026 0)); | |
| 6027 | |
| 6028 scoped_ptr<SpdyFrame> | |
| 6029 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); | |
| 6030 MockRead reads[] = { | |
| 6031 CreateMockRead(*stream1_reply, 1), | |
| 6032 CreateMockRead(*stream2_syn, 2), | |
| 6033 CreateMockRead(*stream1_body, 3), | |
| 6034 CreateMockRead(*stream2_headers1, 4), | |
| 6035 CreateMockRead(*stream2_headers2, 5), | |
| 6036 MockRead(ASYNC, reinterpret_cast<const char*>(kPushBodyFrame), | |
| 6037 arraysize(kPushBodyFrame), 6), | |
| 6038 MockRead(ASYNC, 0, 7), // EOF | |
| 6039 }; | |
| 6040 | |
| 6041 HttpResponseInfo response; | |
| 6042 HttpResponseInfo response2; | |
| 6043 std::string expected_push_result("pushed"); | |
| 6044 DeterministicSocketData data(reads, arraysize(reads), | |
| 6045 writes, arraysize(writes)); | |
| 6046 | 5903 |
| 6047 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY, | 5904 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY, |
| 6048 BoundNetLog(), GetParam(), NULL); | 5905 BoundNetLog(), GetParam(), NULL); |
| 6049 helper.SetDeterministic(); | 5906 helper.AddData(&data); |
| 6050 helper.AddDeterministicData(&data); | |
| 6051 helper.RunPreTestSetup(); | 5907 helper.RunPreTestSetup(); |
| 6052 | |
| 6053 HttpNetworkTransaction* trans = helper.trans(); | 5908 HttpNetworkTransaction* trans = helper.trans(); |
| 6054 | 5909 |
| 6055 // Run until we've received the primary SYN_STREAM, the pushed SYN_STREAM, | |
| 6056 // the first HEADERS frame, and the body of the primary stream, but before | |
| 6057 // we've received the final HEADERS for the pushed stream. | |
| 6058 data.SetStop(4); | |
| 6059 | |
| 6060 // Start the transaction. | |
| 6061 TestCompletionCallback callback; | 5910 TestCompletionCallback callback; |
| 6062 int rv = trans->Start( | 5911 int rv = trans->Start(&helper.request(), callback.callback(), BoundNetLog()); |
| 6063 &CreateGetRequest(), callback.callback(), BoundNetLog()); | 5912 |
| 6064 EXPECT_EQ(ERR_IO_PENDING, rv); | |
| 6065 data.Run(); | |
| 6066 rv = callback.WaitForResult(); | |
| 6067 EXPECT_EQ(0, rv); | |
| 6068 | |
| 6069 // Request the pushed path. At this point, we've received the push, but the | |
| 6070 // headers are not yet complete. | |
| 6071 scoped_ptr<HttpNetworkTransaction> trans2( | |
| 6072 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get())); | |
| 6073 rv = trans2->Start( | |
| 6074 &CreateGetPushRequest(), callback.callback(), BoundNetLog()); | |
| 6075 EXPECT_EQ(ERR_IO_PENDING, rv); | |
| 6076 data.RunFor(3); | |
| 6077 base::MessageLoop::current()->RunUntilIdle(); | |
| 6078 | |
| 6079 // Read the server push body. | |
| 6080 std::string result2; | |
| 6081 ReadResult(trans2.get(), &data, &result2); | |
| 6082 // Read the response body. | |
| 6083 std::string result; | |
| 6084 ReadResult(trans, &data, &result); | |
| 6085 | |
| 6086 // Verify that the received push data is same as the expected push data. | |
| 6087 EXPECT_EQ(expected_push_result, result2); | |
| 6088 | |
| 6089 // Verify the SYN_REPLY. | |
| 6090 // Copy the response info, because trans goes away. | |
| 6091 response = *trans->GetResponseInfo(); | |
| 6092 response2 = *trans2->GetResponseInfo(); | |
| 6093 | |
| 6094 VerifyStreamsClosed(helper); | |
| 6095 | |
| 6096 // Verify the SYN_REPLY. | |
| 6097 EXPECT_TRUE(response.headers.get() != NULL); | |
| 6098 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine()); | |
| 6099 | |
| 6100 // Verify the pushed stream. | |
| 6101 EXPECT_TRUE(response2.headers.get() != NULL); | |
| 6102 EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine()); | |
| 6103 | |
| 6104 // Verify we got all the headers | |
| 6105 if (spdy_util_.spdy_version() < SPDY3) { | |
| 6106 EXPECT_TRUE(response2.headers->HasHeaderValue( | |
| 6107 "url", | |
| 6108 "http://www.google.com/foo.dat")); | |
| 6109 } else { | |
| 6110 EXPECT_TRUE(response2.headers->HasHeaderValue( | |
| 6111 "scheme", "http")); | |
| 6112 EXPECT_TRUE(response2.headers->HasHeaderValue( | |
| 6113 "host", "www.google.com")); | |
| 6114 EXPECT_TRUE(response2.headers->HasHeaderValue( | |
| 6115 "path", "/foo.dat")); | |
| 6116 } | |
| 6117 EXPECT_TRUE(response2.headers->HasHeaderValue("hello", "bye")); | |
| 6118 EXPECT_TRUE(response2.headers->HasHeaderValue("status", "200")); | |
| 6119 EXPECT_TRUE(response2.headers->HasHeaderValue("version", "HTTP/1.1")); | |
| 6120 | |
| 6121 // Read the final EOF (which will close the session) | |
| 6122 data.RunFor(1); | |
| 6123 | |
| 6124 // Verify that we consumed all test data. | |
| 6125 EXPECT_TRUE(data.at_read_eof()); | |
| 6126 EXPECT_TRUE(data.at_write_eof()); | |
| 6127 } | |
| 6128 | |
| 6129 TEST_P(SpdyNetworkTransactionTest, ServerPushWithNoStatusHeaderFrames) { | |
| 6130 if (GetParam().protocol > kProtoSPDY3) | |
| 6131 return; | |
| 6132 | |
| 6133 // We push a stream and attempt to claim it before the headers come down. | |
| 6134 static const unsigned char kPushBodyFrame[] = { | |
| 6135 0x00, 0x00, 0x00, 0x02, // header, ID | |
| 6136 0x01, 0x00, 0x00, 0x06, // FIN, length | |
| 6137 'p', 'u', 's', 'h', 'e', 'd' // "pushed" | |
| 6138 }; | |
| 6139 scoped_ptr<SpdyFrame> stream1_syn( | |
| 6140 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true)); | |
| 6141 scoped_ptr<SpdyFrame> stream1_body( | |
| 6142 spdy_util_.ConstructSpdyBodyFrame(1, true)); | |
| 6143 MockWrite writes[] = { | |
| 6144 CreateMockWrite(*stream1_syn, 0, SYNCHRONOUS), | |
| 6145 }; | |
| 6146 | |
| 6147 scoped_ptr<SpdyHeaderBlock> initial_headers(new SpdyHeaderBlock()); | |
| 6148 spdy_util_.AddUrlToHeaderBlock( | |
| 6149 "http://www.google.com/foo.dat", initial_headers.get()); | |
| 6150 scoped_ptr<SpdyFrame> stream2_syn( | |
| 6151 spdy_util_.ConstructSpdyControlFrame(initial_headers.Pass(), | |
| 6152 false, | |
| 6153 2, | |
| 6154 LOWEST, | |
| 6155 SYN_STREAM, | |
| 6156 CONTROL_FLAG_NONE, | |
| 6157 1)); | |
| 6158 | |
| 6159 scoped_ptr<SpdyHeaderBlock> middle_headers(new SpdyHeaderBlock()); | |
| 6160 (*middle_headers)["hello"] = "bye"; | |
| 6161 scoped_ptr<SpdyFrame> stream2_headers1( | |
| 6162 spdy_util_.ConstructSpdyControlFrame(middle_headers.Pass(), | |
| 6163 false, | |
| 6164 2, | |
| 6165 LOWEST, | |
| 6166 HEADERS, | |
| 6167 CONTROL_FLAG_NONE, | |
| 6168 0)); | |
| 6169 | |
| 6170 scoped_ptr<SpdyFrame> | |
| 6171 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); | |
| 6172 MockRead reads[] = { | |
| 6173 CreateMockRead(*stream1_reply, 1), | |
| 6174 CreateMockRead(*stream2_syn, 2), | |
| 6175 CreateMockRead(*stream1_body, 3), | |
| 6176 CreateMockRead(*stream2_headers1, 4), | |
| 6177 MockRead(ASYNC, reinterpret_cast<const char*>(kPushBodyFrame), | |
| 6178 arraysize(kPushBodyFrame), 5), | |
| 6179 MockRead(ASYNC, 0, 6), // EOF | |
| 6180 }; | |
| 6181 | |
| 6182 DeterministicSocketData data(reads, arraysize(reads), | |
| 6183 writes, arraysize(writes)); | |
| 6184 | |
| 6185 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY, | |
| 6186 BoundNetLog(), GetParam(), NULL); | |
| 6187 helper.SetDeterministic(); | |
| 6188 helper.AddDeterministicData(&data); | |
| 6189 helper.RunPreTestSetup(); | |
| 6190 | |
| 6191 HttpNetworkTransaction* trans = helper.trans(); | |
| 6192 | |
| 6193 // Run until we've received the primary SYN_STREAM, the pushed SYN_STREAM, | |
| 6194 // the first HEADERS frame, and the body of the primary stream, but before | |
| 6195 // we've received the final HEADERS for the pushed stream. | |
| 6196 data.SetStop(4); | |
| 6197 | |
| 6198 // Start the transaction. | |
| 6199 TestCompletionCallback callback; | |
| 6200 int rv = trans->Start( | |
| 6201 &CreateGetRequest(), callback.callback(), BoundNetLog()); | |
| 6202 EXPECT_EQ(ERR_IO_PENDING, rv); | |
| 6203 data.Run(); | |
| 6204 rv = callback.WaitForResult(); | |
| 6205 EXPECT_EQ(0, rv); | |
| 6206 | |
| 6207 // Request the pushed path. At this point, we've received the push, but the | |
| 6208 // headers are not yet complete. | |
| 6209 scoped_ptr<HttpNetworkTransaction> trans2( | |
| 6210 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get())); | |
| 6211 rv = trans2->Start( | |
| 6212 &CreateGetPushRequest(), callback.callback(), BoundNetLog()); | |
| 6213 EXPECT_EQ(ERR_IO_PENDING, rv); | |
| 6214 data.RunFor(2); | |
| 6215 base::MessageLoop::current()->RunUntilIdle(); | |
| 6216 | |
| 6217 // Read the server push body. | |
| 6218 std::string result2; | |
| 6219 ReadResult(trans2.get(), &data, &result2); | |
| 6220 // Read the response body. | |
| 6221 std::string result; | |
| 6222 ReadResult(trans, &data, &result); | |
| 6223 EXPECT_EQ("hello!", result); | |
| 6224 | |
| 6225 // Verify that we haven't received any push data. | |
| 6226 EXPECT_EQ("", result2); | |
| 6227 | |
| 6228 // Verify the SYN_REPLY. | |
| 6229 // Copy the response info, because trans goes away. | |
| 6230 HttpResponseInfo response = *trans->GetResponseInfo(); | |
| 6231 ASSERT_TRUE(trans2->GetResponseInfo() == NULL); | |
| 6232 | |
| 6233 VerifyStreamsClosed(helper); | |
| 6234 | |
| 6235 // Verify the SYN_REPLY. | |
| 6236 EXPECT_TRUE(response.headers.get() != NULL); | |
| 6237 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine()); | |
| 6238 | |
| 6239 // Read the final EOF (which will close the session). | |
| 6240 data.RunFor(1); | |
| 6241 | |
| 6242 // Verify that we consumed all test data. | |
| 6243 EXPECT_TRUE(data.at_read_eof()); | |
| 6244 EXPECT_TRUE(data.at_write_eof()); | |
| 6245 } | |
| 6246 | |
| 6247 TEST_P(SpdyNetworkTransactionTest, SynReplyWithHeaders) { | |
| 6248 if (GetParam().protocol > kProtoSPDY3) | |
| 6249 return; | |
| 6250 | |
| 6251 scoped_ptr<SpdyFrame> req( | |
| 6252 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true)); | |
| 6253 scoped_ptr<SpdyFrame> rst( | |
| 6254 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_PROTOCOL_ERROR)); | |
| 6255 MockWrite writes[] = { | |
| 6256 CreateMockWrite(*req), | |
| 6257 CreateMockWrite(*rst), | |
| 6258 }; | |
| 6259 | |
| 6260 scoped_ptr<SpdyHeaderBlock> initial_headers(new SpdyHeaderBlock()); | |
| 6261 (*initial_headers)[spdy_util_.GetStatusKey()] = "200 OK"; | |
| 6262 (*initial_headers)[spdy_util_.GetVersionKey()] = "HTTP/1.1"; | |
| 6263 scoped_ptr<SpdyFrame> stream1_reply( | |
| 6264 spdy_util_.ConstructSpdyControlFrame(initial_headers.Pass(), | |
| 6265 false, | |
| 6266 1, | |
| 6267 LOWEST, | |
| 6268 SYN_REPLY, | |
| 6269 CONTROL_FLAG_NONE, | |
| 6270 0)); | |
| 6271 | |
| 6272 scoped_ptr<SpdyHeaderBlock> late_headers(new SpdyHeaderBlock()); | |
| 6273 (*late_headers)["hello"] = "bye"; | |
| 6274 scoped_ptr<SpdyFrame> stream1_headers( | |
| 6275 spdy_util_.ConstructSpdyControlFrame(late_headers.Pass(), | |
| 6276 false, | |
| 6277 1, | |
| 6278 LOWEST, | |
| 6279 HEADERS, | |
| 6280 CONTROL_FLAG_NONE, | |
| 6281 0)); | |
| 6282 scoped_ptr<SpdyFrame> stream1_body( | |
| 6283 spdy_util_.ConstructSpdyBodyFrame(1, true)); | |
| 6284 MockRead reads[] = { | |
| 6285 CreateMockRead(*stream1_reply), | |
| 6286 CreateMockRead(*stream1_headers), | |
| 6287 CreateMockRead(*stream1_body), | |
| 6288 MockRead(ASYNC, 0, 0) // EOF | |
| 6289 }; | |
| 6290 | |
| 6291 DelayedSocketData data(1, reads, arraysize(reads), | |
| 6292 writes, arraysize(writes)); | |
| 6293 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY, | |
| 6294 BoundNetLog(), GetParam(), NULL); | |
| 6295 helper.RunToCompletion(&data); | |
| 6296 TransactionHelperResult out = helper.output(); | |
| 6297 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, out.rv); | |
| 6298 } | |
| 6299 | |
| 6300 TEST_P(SpdyNetworkTransactionTest, SynReplyWithLateHeaders) { | |
| 6301 if (GetParam().protocol > kProtoSPDY3) | |
| 6302 return; | |
| 6303 | |
| 6304 scoped_ptr<SpdyFrame> req( | |
| 6305 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true)); | |
| 6306 scoped_ptr<SpdyFrame> rst( | |
| 6307 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_PROTOCOL_ERROR)); | |
| 6308 MockWrite writes[] = { | |
| 6309 CreateMockWrite(*req), | |
| 6310 CreateMockWrite(*rst), | |
| 6311 }; | |
| 6312 | |
| 6313 scoped_ptr<SpdyHeaderBlock> initial_headers(new SpdyHeaderBlock()); | |
| 6314 (*initial_headers)[spdy_util_.GetStatusKey()] = "200 OK"; | |
| 6315 (*initial_headers)[spdy_util_.GetVersionKey()] = "HTTP/1.1"; | |
| 6316 scoped_ptr<SpdyFrame> stream1_reply( | |
| 6317 spdy_util_.ConstructSpdyControlFrame(initial_headers.Pass(), | |
| 6318 false, | |
| 6319 1, | |
| 6320 LOWEST, | |
| 6321 SYN_REPLY, | |
| 6322 CONTROL_FLAG_NONE, | |
| 6323 0)); | |
| 6324 | |
| 6325 scoped_ptr<SpdyHeaderBlock> late_headers(new SpdyHeaderBlock()); | |
| 6326 (*late_headers)["hello"] = "bye"; | |
| 6327 scoped_ptr<SpdyFrame> stream1_headers( | |
| 6328 spdy_util_.ConstructSpdyControlFrame(late_headers.Pass(), | |
| 6329 false, | |
| 6330 1, | |
| 6331 LOWEST, | |
| 6332 HEADERS, | |
| 6333 CONTROL_FLAG_NONE, | |
| 6334 0)); | |
| 6335 scoped_ptr<SpdyFrame> stream1_body( | |
| 6336 spdy_util_.ConstructSpdyBodyFrame(1, false)); | |
| 6337 scoped_ptr<SpdyFrame> stream1_body2( | |
| 6338 spdy_util_.ConstructSpdyBodyFrame(1, true)); | |
| 6339 MockRead reads[] = { | |
| 6340 CreateMockRead(*stream1_reply), | |
| 6341 CreateMockRead(*stream1_body), | |
| 6342 CreateMockRead(*stream1_headers), | |
| 6343 CreateMockRead(*stream1_body2), | |
| 6344 MockRead(ASYNC, 0, 0) // EOF | |
| 6345 }; | |
| 6346 | |
| 6347 DelayedSocketData data(1, reads, arraysize(reads), | |
| 6348 writes, arraysize(writes)); | |
| 6349 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY, | |
| 6350 BoundNetLog(), GetParam(), NULL); | |
| 6351 helper.RunToCompletion(&data); | |
| 6352 TransactionHelperResult out = helper.output(); | |
| 6353 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, out.rv); | |
| 6354 } | |
| 6355 | |
| 6356 TEST_P(SpdyNetworkTransactionTest, ServerPushCrossOriginCorrectness) { | |
| 6357 if (GetParam().protocol > kProtoSPDY3) | |
| 6358 return; | |
| 6359 | |
| 6360 // In this test we want to verify that we can't accidentally push content | |
| 6361 // which can't be pushed by this content server. | |
| 6362 // This test assumes that: | |
| 6363 // - if we're requesting http://www.foo.com/barbaz | |
| 6364 // - the browser has made a connection to "www.foo.com". | |
| 6365 | |
| 6366 // A list of the URL to fetch, followed by the URL being pushed. | |
| 6367 static const char* const kTestCases[] = { | |
| 6368 "http://www.google.com/foo.html", | |
| 6369 "http://www.google.com:81/foo.js", // Bad port | |
| 6370 | |
| 6371 "http://www.google.com/foo.html", | |
| 6372 "https://www.google.com/foo.js", // Bad protocol | |
| 6373 | |
| 6374 "http://www.google.com/foo.html", | |
| 6375 "ftp://www.google.com/foo.js", // Invalid Protocol | |
| 6376 | |
| 6377 "http://www.google.com/foo.html", | |
| 6378 "http://blat.www.google.com/foo.js", // Cross subdomain | |
| 6379 | |
| 6380 "http://www.google.com/foo.html", | |
| 6381 "http://www.foo.com/foo.js", // Cross domain | |
| 6382 }; | |
| 6383 | |
| 6384 | |
| 6385 static const unsigned char kPushBodyFrame[] = { | |
| 6386 0x00, 0x00, 0x00, 0x02, // header, ID | |
| 6387 0x01, 0x00, 0x00, 0x06, // FIN, length | |
| 6388 'p', 'u', 's', 'h', 'e', 'd' // "pushed" | |
| 6389 }; | |
| 6390 | |
| 6391 for (size_t index = 0; index < arraysize(kTestCases); index += 2) { | |
| 6392 const char* url_to_fetch = kTestCases[index]; | |
| 6393 const char* url_to_push = kTestCases[index + 1]; | |
| 6394 | |
| 6395 scoped_ptr<SpdyFrame> stream1_syn( | |
| 6396 spdy_util_.ConstructSpdyGet(url_to_fetch, false, 1, LOWEST)); | |
| 6397 scoped_ptr<SpdyFrame> stream1_body( | |
| 6398 spdy_util_.ConstructSpdyBodyFrame(1, true)); | |
| 6399 scoped_ptr<SpdyFrame> push_rst( | |
| 6400 spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_REFUSED_STREAM)); | |
| 6401 MockWrite writes[] = { | |
| 6402 CreateMockWrite(*stream1_syn, 1), | |
| 6403 CreateMockWrite(*push_rst, 4), | |
| 6404 }; | |
| 6405 | |
| 6406 scoped_ptr<SpdyFrame> | |
| 6407 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); | |
| 6408 scoped_ptr<SpdyFrame> | |
| 6409 stream2_syn(spdy_util_.ConstructSpdyPush(NULL, | |
| 6410 0, | |
| 6411 2, | |
| 6412 1, | |
| 6413 url_to_push)); | |
| 6414 scoped_ptr<SpdyFrame> rst( | |
| 6415 spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_CANCEL)); | |
| 6416 | |
| 6417 MockRead reads[] = { | |
| 6418 CreateMockRead(*stream1_reply, 2), | |
| 6419 CreateMockRead(*stream2_syn, 3), | |
| 6420 CreateMockRead(*stream1_body, 5, SYNCHRONOUS), | |
| 6421 MockRead(ASYNC, reinterpret_cast<const char*>(kPushBodyFrame), | |
| 6422 arraysize(kPushBodyFrame), 6), | |
| 6423 MockRead(ASYNC, ERR_IO_PENDING, 7), // Force a pause | |
| 6424 }; | |
| 6425 | |
| 6426 HttpResponseInfo response; | |
| 6427 OrderedSocketData data(reads, arraysize(reads), | |
| 6428 writes, arraysize(writes)); | |
| 6429 | |
| 6430 HttpRequestInfo request; | |
| 6431 request.method = "GET"; | |
| 6432 request.url = GURL(url_to_fetch); | |
| 6433 request.load_flags = 0; | |
| 6434 | |
| 6435 // Enable cross-origin push. Since we are not using a proxy, this should | |
| 6436 // not actually enable cross-origin SPDY push. | |
| 6437 scoped_ptr<SpdySessionDependencies> session_deps( | |
| 6438 CreateSpdySessionDependencies(GetParam())); | |
| 6439 session_deps->trusted_spdy_proxy = "123.45.67.89:8080"; | |
| 6440 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY, | |
| 6441 BoundNetLog(), GetParam(), | |
| 6442 session_deps.release()); | |
| 6443 helper.RunPreTestSetup(); | |
| 6444 helper.AddData(&data); | |
| 6445 | |
| 6446 HttpNetworkTransaction* trans = helper.trans(); | |
| 6447 | |
| 6448 // Start the transaction with basic parameters. | |
| 6449 TestCompletionCallback callback; | |
| 6450 | |
| 6451 int rv = trans->Start(&request, callback.callback(), BoundNetLog()); | |
| 6452 EXPECT_EQ(ERR_IO_PENDING, rv); | |
| 6453 rv = callback.WaitForResult(); | |
| 6454 | |
| 6455 // Read the response body. | |
| 6456 std::string result; | |
| 6457 ReadResult(trans, &data, &result); | |
| 6458 | |
| 6459 // Verify that we consumed all test data. | |
| 6460 EXPECT_TRUE(data.at_read_eof()); | |
| 6461 EXPECT_TRUE(data.at_write_eof()); | |
| 6462 | |
| 6463 // Verify the SYN_REPLY. | |
| 6464 // Copy the response info, because trans goes away. | |
| 6465 response = *trans->GetResponseInfo(); | |
| 6466 | |
| 6467 VerifyStreamsClosed(helper); | |
| 6468 | |
| 6469 // Verify the SYN_REPLY. | |
| 6470 EXPECT_TRUE(response.headers.get() != NULL); | |
| 6471 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine()); | |
| 6472 } | |
| 6473 } | |
| 6474 | |
| 6475 TEST_P(SpdyNetworkTransactionTest, RetryAfterRefused) { | |
| 6476 if (GetParam().protocol > kProtoSPDY3) | |
| 6477 return; | |
| 6478 | |
| 6479 // Construct the request. | |
| 6480 scoped_ptr<SpdyFrame> req( | |
| 6481 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true)); | |
| 6482 scoped_ptr<SpdyFrame> req2( | |
| 6483 spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, LOWEST, true)); | |
| 6484 MockWrite writes[] = { | |
| 6485 CreateMockWrite(*req, 1), | |
| 6486 CreateMockWrite(*req2, 3), | |
| 6487 }; | |
| 6488 | |
| 6489 scoped_ptr<SpdyFrame> refused( | |
| 6490 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_REFUSED_STREAM)); | |
| 6491 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3)); | |
| 6492 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(3, true)); | |
| 6493 MockRead reads[] = { | |
| 6494 CreateMockRead(*refused, 2), | |
| 6495 CreateMockRead(*resp, 4), | |
| 6496 CreateMockRead(*body, 5), | |
| 6497 MockRead(ASYNC, 0, 6) // EOF | |
| 6498 }; | |
| 6499 | |
| 6500 OrderedSocketData data(reads, arraysize(reads), | |
| 6501 writes, arraysize(writes)); | |
| 6502 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY, | |
| 6503 BoundNetLog(), GetParam(), NULL); | |
| 6504 | |
| 6505 helper.RunPreTestSetup(); | |
| 6506 helper.AddData(&data); | |
| 6507 | |
| 6508 HttpNetworkTransaction* trans = helper.trans(); | |
| 6509 | |
| 6510 // Start the transaction with basic parameters. | |
| 6511 TestCompletionCallback callback; | |
| 6512 int rv = trans->Start( | |
| 6513 &CreateGetRequest(), callback.callback(), BoundNetLog()); | |
| 6514 EXPECT_EQ(ERR_IO_PENDING, rv); | 5913 EXPECT_EQ(ERR_IO_PENDING, rv); |
| 6515 rv = callback.WaitForResult(); | 5914 rv = callback.WaitForResult(); |
| 6516 EXPECT_EQ(OK, rv); | 5915 EXPECT_EQ(OK, rv); |
| 6517 | 5916 |
| 6518 // Verify that we consumed all test data. | 5917 SpdyHttpStream* stream = |
| 6519 EXPECT_TRUE(data.at_read_eof()) << "Read count: " | 5918 static_cast<SpdyHttpStream*>(trans->stream_.get()); |
| 6520 << data.read_count() | 5919 ASSERT_TRUE(stream != NULL); |
| 6521 << " Read index: " | 5920 ASSERT_TRUE(stream->stream() != NULL); |
| 6522 << data.read_index(); | 5921 |
| 6523 EXPECT_TRUE(data.at_write_eof()) << "Write count: " | 5922 EXPECT_EQ( |
| 6524 << data.write_count() | 5923 static_cast<int>(kSpdyStreamInitialWindowSize - body_data.size()), |
| 6525 << " Write index: " | 5924 stream->stream()->recv_window_size()); |
| 6526 << data.write_index(); | 5925 |
| 6527 | 5926 const HttpResponseInfo* response = trans->GetResponseInfo(); |
| 6528 // Verify the SYN_REPLY. | 5927 ASSERT_TRUE(response != NULL); |
| 6529 HttpResponseInfo response = *trans->GetResponseInfo(); | 5928 ASSERT_TRUE(response->headers.get() != NULL); |
| 6530 EXPECT_TRUE(response.headers.get() != NULL); | 5929 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine()); |
| 6531 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(); | |
| 6532 } | 5951 } |
| 6533 | 5952 |
| 6534 TEST_P(SpdyNetworkTransactionTest, OutOfOrderSynStream) { | 5953 // Test that WINDOW_UPDATE frame causing overflow is handled correctly. |
| 6535 if (GetParam().protocol > kProtoSPDY3) | 5954 TEST_P(SpdyNetworkTransactionTest, WindowUpdateOverflow) { |
| 5955 if (GetParam().protocol < kProtoSPDY3) | |
| 6536 return; | 5956 return; |
| 6537 | 5957 |
| 6538 // This first request will start to establish the SpdySession. | 5958 // Number of full frames we hope to write (but will not, used to |
| 6539 // Then we will start the second (MEDIUM priority) and then third | 5959 // set content-length header correctly) |
| 6540 // (HIGHEST priority) request in such a way that the third will actually | 5960 static int kFrameCount = 3; |
| 6541 // start before the second, causing the second to be numbered differently | 5961 |
| 6542 // than the order they were created. | 5962 scoped_ptr<std::string> content( |
| 6543 scoped_ptr<SpdyFrame> req1( | 5963 new std::string(kMaxSpdyFrameChunkSize, 'a')); |
| 6544 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true)); | 5964 scoped_ptr<SpdyFrame> req(spdy_util_.ConstructSpdyPost( |
| 6545 scoped_ptr<SpdyFrame> req2( | 5965 kRequestUrl, 1, kMaxSpdyFrameChunkSize * kFrameCount, LOWEST, NULL, 0)); |
| 6546 spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, HIGHEST, true)); | 5966 scoped_ptr<SpdyFrame> body( |
| 6547 scoped_ptr<SpdyFrame> req3( | 5967 spdy_util_.ConstructSpdyBodyFrame( |
| 6548 spdy_util_.ConstructSpdyGet(NULL, 0, false, 5, MEDIUM, true)); | 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. | |
| 6549 MockWrite writes[] = { | 5974 MockWrite writes[] = { |
| 6550 CreateMockWrite(*req1, 0), | 5975 CreateMockWrite(*req, 0), |
| 6551 CreateMockWrite(*req2, 3), | 5976 CreateMockWrite(*body, 2), |
| 6552 CreateMockWrite(*req3, 4), | 5977 CreateMockWrite(*rst, 3), |
| 6553 }; | 5978 }; |
| 6554 | 5979 |
| 6555 scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); | 5980 static const int32 kDeltaWindowSize = 0x7fffffff; // cause an overflow |
| 6556 scoped_ptr<SpdyFrame> body1(spdy_util_.ConstructSpdyBodyFrame(1, true)); | 5981 scoped_ptr<SpdyFrame> window_update( |
| 6557 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3)); | 5982 spdy_util_.ConstructSpdyWindowUpdate(1, kDeltaWindowSize)); |
| 6558 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(3, true)); | |
| 6559 scoped_ptr<SpdyFrame> resp3(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 5)); | |
| 6560 scoped_ptr<SpdyFrame> body3(spdy_util_.ConstructSpdyBodyFrame(5, true)); | |
| 6561 MockRead reads[] = { | 5983 MockRead reads[] = { |
| 6562 CreateMockRead(*resp1, 1), | 5984 CreateMockRead(*window_update, 1), |
| 6563 CreateMockRead(*body1, 2), | 5985 MockRead(ASYNC, 0, 4) // EOF |
| 6564 CreateMockRead(*resp2, 5), | |
| 6565 CreateMockRead(*body2, 6), | |
| 6566 CreateMockRead(*resp3, 7), | |
| 6567 CreateMockRead(*body3, 8), | |
| 6568 MockRead(ASYNC, 0, 9) // EOF | |
| 6569 }; | 5986 }; |
| 6570 | 5987 |
| 6571 DeterministicSocketData data(reads, arraysize(reads), | 5988 DeterministicSocketData data(reads, arraysize(reads), |
| 6572 writes, arraysize(writes)); | 5989 writes, arraysize(writes)); |
| 6573 NormalSpdyTransactionHelper helper(CreateGetRequest(), LOWEST, | 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, | |
| 6574 BoundNetLog(), GetParam(), NULL); | 6005 BoundNetLog(), GetParam(), NULL); |
| 6575 helper.SetDeterministic(); | 6006 helper.SetDeterministic(); |
| 6576 helper.RunPreTestSetup(); | 6007 helper.RunPreTestSetup(); |
| 6577 helper.AddDeterministicData(&data); | 6008 helper.AddDeterministicData(&data); |
| 6578 | |
| 6579 // Start the first transaction to set up the SpdySession | |
| 6580 HttpNetworkTransaction* trans = helper.trans(); | 6009 HttpNetworkTransaction* trans = helper.trans(); |
| 6010 | |
| 6581 TestCompletionCallback callback; | 6011 TestCompletionCallback callback; |
| 6582 HttpRequestInfo info1 = CreateGetRequest(); | 6012 int rv = trans->Start(&helper.request(), callback.callback(), BoundNetLog()); |
| 6583 int rv = trans->Start(&info1, callback.callback(), BoundNetLog()); | 6013 ASSERT_EQ(ERR_IO_PENDING, rv); |
| 6584 EXPECT_EQ(ERR_IO_PENDING, rv); | 6014 |
| 6585 | 6015 data.RunFor(5); |
| 6586 // Run the message loop, but do not allow the write to complete. | 6016 ASSERT_TRUE(callback.have_result()); |
| 6587 // This leaves the SpdySession with a write pending, which prevents | 6017 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, callback.WaitForResult()); |
| 6588 // SpdySession from attempting subsequent writes until this write completes. | |
| 6589 base::MessageLoop::current()->RunUntilIdle(); | |
| 6590 | |
| 6591 // Now, start both new transactions | |
| 6592 HttpRequestInfo info2 = CreateGetRequest(); | |
| 6593 TestCompletionCallback callback2; | |
| 6594 scoped_ptr<HttpNetworkTransaction> trans2( | |
| 6595 new HttpNetworkTransaction(MEDIUM, helper.session().get())); | |
| 6596 rv = trans2->Start(&info2, callback2.callback(), BoundNetLog()); | |
| 6597 EXPECT_EQ(ERR_IO_PENDING, rv); | |
| 6598 base::MessageLoop::current()->RunUntilIdle(); | |
| 6599 | |
| 6600 HttpRequestInfo info3 = CreateGetRequest(); | |
| 6601 TestCompletionCallback callback3; | |
| 6602 scoped_ptr<HttpNetworkTransaction> trans3( | |
| 6603 new HttpNetworkTransaction(HIGHEST, helper.session().get())); | |
| 6604 rv = trans3->Start(&info3, callback3.callback(), BoundNetLog()); | |
| 6605 EXPECT_EQ(ERR_IO_PENDING, rv); | |
| 6606 base::MessageLoop::current()->RunUntilIdle(); | |
| 6607 | |
| 6608 // We now have two SYN_STREAM frames queued up which will be | |
| 6609 // dequeued only once the first write completes, which we | |
| 6610 // now allow to happen. | |
| 6611 data.RunFor(2); | |
| 6612 EXPECT_EQ(OK, callback.WaitForResult()); | |
| 6613 | |
| 6614 // And now we can allow everything else to run to completion. | |
| 6615 data.SetStop(10); | |
| 6616 data.Run(); | |
| 6617 EXPECT_EQ(OK, callback2.WaitForResult()); | |
| 6618 EXPECT_EQ(OK, callback3.WaitForResult()); | |
| 6619 | |
| 6620 helper.VerifyDataConsumed(); | 6018 helper.VerifyDataConsumed(); |
| 6621 } | 6019 } |
| 6622 | 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 | |
| 6623 } // namespace net | 6389 } // namespace net |
| OLD | NEW |