| 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 "net/quic/quic_session.h" | 5 #include "net/quic/quic_session.h" |
| 6 | 6 |
| 7 #include <set> | 7 #include <set> |
| 8 | 8 |
| 9 #include "base/basictypes.h" | 9 #include "base/basictypes.h" |
| 10 #include "base/containers/hash_tables.h" | 10 #include "base/containers/hash_tables.h" |
| (...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 140 return nullptr; | 140 return nullptr; |
| 141 } else { | 141 } else { |
| 142 return new TestStream(id, this); | 142 return new TestStream(id, this); |
| 143 } | 143 } |
| 144 } | 144 } |
| 145 | 145 |
| 146 bool IsClosedStream(QuicStreamId id) { | 146 bool IsClosedStream(QuicStreamId id) { |
| 147 return QuicSession::IsClosedStream(id); | 147 return QuicSession::IsClosedStream(id); |
| 148 } | 148 } |
| 149 | 149 |
| 150 ReliableQuicStream* GetIncomingDynamicStream(QuicStreamId stream_id) { | 150 ReliableQuicStream* GetOrCreateDynamicStream(QuicStreamId stream_id) { |
| 151 return QuicSpdySession::GetIncomingDynamicStream(stream_id); | 151 return QuicSpdySession::GetOrCreateDynamicStream(stream_id); |
| 152 } | 152 } |
| 153 | 153 |
| 154 QuicConsumedData WritevData( | 154 QuicConsumedData WritevData( |
| 155 QuicStreamId id, | 155 QuicStreamId id, |
| 156 QuicIOVector data, | 156 QuicIOVector data, |
| 157 QuicStreamOffset offset, | 157 QuicStreamOffset offset, |
| 158 bool fin, | 158 bool fin, |
| 159 FecProtection fec_protection, | 159 FecProtection fec_protection, |
| 160 QuicAckListenerInterface* ack_notifier_delegate) override { | 160 QuicAckListenerInterface* ack_notifier_delegate) override { |
| 161 // Always consumes everything. | 161 // Always consumes everything. |
| (...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 238 } | 238 } |
| 239 | 239 |
| 240 void CloseStream(QuicStreamId id) { | 240 void CloseStream(QuicStreamId id) { |
| 241 EXPECT_CALL(*connection_, SendRstStream(id, _, _)); | 241 EXPECT_CALL(*connection_, SendRstStream(id, _, _)); |
| 242 session_.CloseStream(id); | 242 session_.CloseStream(id); |
| 243 closed_streams_.insert(id); | 243 closed_streams_.insert(id); |
| 244 } | 244 } |
| 245 | 245 |
| 246 QuicVersion version() const { return connection_->version(); } | 246 QuicVersion version() const { return connection_->version(); } |
| 247 | 247 |
| 248 MockHelper helper_; | 248 MockConnectionHelper helper_; |
| 249 StrictMock<MockConnection>* connection_; | 249 StrictMock<MockConnection>* connection_; |
| 250 TestSession session_; | 250 TestSession session_; |
| 251 set<QuicStreamId> closed_streams_; | 251 set<QuicStreamId> closed_streams_; |
| 252 SpdyHeaderBlock headers_; | 252 SpdyHeaderBlock headers_; |
| 253 }; | 253 }; |
| 254 | 254 |
| 255 class QuicSessionTestServer : public QuicSessionTestBase { | 255 class QuicSessionTestServer : public QuicSessionTestBase { |
| 256 protected: | 256 protected: |
| 257 QuicSessionTestServer() : QuicSessionTestBase(Perspective::IS_SERVER) {} | 257 QuicSessionTestServer() : QuicSessionTestBase(Perspective::IS_SERVER) {} |
| 258 }; | 258 }; |
| (...skipping 14 matching lines...) Expand all Loading... |
| 273 } | 273 } |
| 274 | 274 |
| 275 TEST_P(QuicSessionTestServer, IsClosedStreamDefault) { | 275 TEST_P(QuicSessionTestServer, IsClosedStreamDefault) { |
| 276 // Ensure that no streams are initially closed. | 276 // Ensure that no streams are initially closed. |
| 277 for (QuicStreamId i = kCryptoStreamId; i < 100; i++) { | 277 for (QuicStreamId i = kCryptoStreamId; i < 100; i++) { |
| 278 EXPECT_FALSE(session_.IsClosedStream(i)) << "stream id: " << i; | 278 EXPECT_FALSE(session_.IsClosedStream(i)) << "stream id: " << i; |
| 279 } | 279 } |
| 280 } | 280 } |
| 281 | 281 |
| 282 TEST_P(QuicSessionTestServer, AvailableStreams) { | 282 TEST_P(QuicSessionTestServer, AvailableStreams) { |
| 283 ASSERT_TRUE(session_.GetIncomingDynamicStream(9) != nullptr); | 283 ASSERT_TRUE(session_.GetOrCreateDynamicStream(9) != nullptr); |
| 284 // Both 5 and 7 should be available. | 284 // Both 5 and 7 should be available. |
| 285 EXPECT_TRUE(QuicSessionPeer::IsStreamAvailable(&session_, 5)); | 285 EXPECT_TRUE(QuicSessionPeer::IsStreamAvailable(&session_, 5)); |
| 286 EXPECT_TRUE(QuicSessionPeer::IsStreamAvailable(&session_, 7)); | 286 EXPECT_TRUE(QuicSessionPeer::IsStreamAvailable(&session_, 7)); |
| 287 ASSERT_TRUE(session_.GetIncomingDynamicStream(7) != nullptr); | 287 ASSERT_TRUE(session_.GetOrCreateDynamicStream(7) != nullptr); |
| 288 ASSERT_TRUE(session_.GetIncomingDynamicStream(5) != nullptr); | 288 ASSERT_TRUE(session_.GetOrCreateDynamicStream(5) != nullptr); |
| 289 } | 289 } |
| 290 | 290 |
| 291 TEST_P(QuicSessionTestServer, IsClosedStreamLocallyCreated) { | 291 TEST_P(QuicSessionTestServer, IsClosedStreamLocallyCreated) { |
| 292 TestStream* stream2 = session_.CreateOutgoingDynamicStream(); | 292 TestStream* stream2 = session_.CreateOutgoingDynamicStream(); |
| 293 EXPECT_EQ(2u, stream2->id()); | 293 EXPECT_EQ(2u, stream2->id()); |
| 294 TestStream* stream4 = session_.CreateOutgoingDynamicStream(); | 294 TestStream* stream4 = session_.CreateOutgoingDynamicStream(); |
| 295 EXPECT_EQ(4u, stream4->id()); | 295 EXPECT_EQ(4u, stream4->id()); |
| 296 | 296 |
| 297 CheckClosedStreams(); | 297 CheckClosedStreams(); |
| 298 CloseStream(4); | 298 CloseStream(4); |
| 299 CheckClosedStreams(); | 299 CheckClosedStreams(); |
| 300 CloseStream(2); | 300 CloseStream(2); |
| 301 CheckClosedStreams(); | 301 CheckClosedStreams(); |
| 302 } | 302 } |
| 303 | 303 |
| 304 TEST_P(QuicSessionTestServer, IsClosedStreamPeerCreated) { | 304 TEST_P(QuicSessionTestServer, IsClosedStreamPeerCreated) { |
| 305 QuicStreamId stream_id1 = kClientDataStreamId1; | 305 QuicStreamId stream_id1 = kClientDataStreamId1; |
| 306 QuicStreamId stream_id2 = kClientDataStreamId2; | 306 QuicStreamId stream_id2 = kClientDataStreamId2; |
| 307 session_.GetIncomingDynamicStream(stream_id1); | 307 session_.GetOrCreateDynamicStream(stream_id1); |
| 308 session_.GetIncomingDynamicStream(stream_id2); | 308 session_.GetOrCreateDynamicStream(stream_id2); |
| 309 | 309 |
| 310 CheckClosedStreams(); | 310 CheckClosedStreams(); |
| 311 CloseStream(stream_id1); | 311 CloseStream(stream_id1); |
| 312 CheckClosedStreams(); | 312 CheckClosedStreams(); |
| 313 CloseStream(stream_id2); | 313 CloseStream(stream_id2); |
| 314 // Create a stream, and make another available. | 314 // Create a stream, and make another available. |
| 315 ReliableQuicStream* stream3 = | 315 ReliableQuicStream* stream3 = |
| 316 session_.GetIncomingDynamicStream(stream_id2 + 4); | 316 session_.GetOrCreateDynamicStream(stream_id2 + 4); |
| 317 CheckClosedStreams(); | 317 CheckClosedStreams(); |
| 318 // Close one, but make sure the other is still not closed | 318 // Close one, but make sure the other is still not closed |
| 319 CloseStream(stream3->id()); | 319 CloseStream(stream3->id()); |
| 320 CheckClosedStreams(); | 320 CheckClosedStreams(); |
| 321 } | 321 } |
| 322 | 322 |
| 323 TEST_P(QuicSessionTestServer, MaximumAvailableOpenedStreams) { | 323 TEST_P(QuicSessionTestServer, MaximumAvailableOpenedStreams) { |
| 324 QuicStreamId stream_id = kClientDataStreamId1; | 324 QuicStreamId stream_id = kClientDataStreamId1; |
| 325 session_.GetIncomingDynamicStream(stream_id); | 325 session_.GetOrCreateDynamicStream(stream_id); |
| 326 EXPECT_CALL(*connection_, SendConnectionClose(_)).Times(0); | 326 EXPECT_CALL(*connection_, SendConnectionClose(_)).Times(0); |
| 327 EXPECT_NE(nullptr, | 327 EXPECT_NE(nullptr, |
| 328 session_.GetIncomingDynamicStream( | 328 session_.GetOrCreateDynamicStream( |
| 329 stream_id + 2 * (session_.get_max_open_streams() - 1))); | 329 stream_id + 2 * (session_.get_max_open_streams() - 1))); |
| 330 } | 330 } |
| 331 | 331 |
| 332 TEST_P(QuicSessionTestServer, TooManyAvailableStreams) { | 332 TEST_P(QuicSessionTestServer, TooManyAvailableStreams) { |
| 333 QuicStreamId stream_id1 = kClientDataStreamId1; | 333 QuicStreamId stream_id1 = kClientDataStreamId1; |
| 334 QuicStreamId stream_id2; | 334 QuicStreamId stream_id2; |
| 335 EXPECT_NE(nullptr, session_.GetIncomingDynamicStream(stream_id1)); | 335 EXPECT_NE(nullptr, session_.GetOrCreateDynamicStream(stream_id1)); |
| 336 // A stream ID which is too large to create. | 336 // A stream ID which is too large to create. |
| 337 if (FLAGS_allow_many_available_streams) { | 337 if (FLAGS_allow_many_available_streams) { |
| 338 stream_id2 = stream_id1 + 2 * session_.get_max_available_streams() + 4; | 338 stream_id2 = stream_id1 + 2 * session_.get_max_available_streams() + 4; |
| 339 EXPECT_CALL(*connection_, | 339 EXPECT_CALL(*connection_, |
| 340 SendConnectionClose(QUIC_TOO_MANY_AVAILABLE_STREAMS)); | 340 SendConnectionClose(QUIC_TOO_MANY_AVAILABLE_STREAMS)); |
| 341 } else { | 341 } else { |
| 342 stream_id2 = stream_id1 + 2 * session_.get_max_open_streams(); | 342 stream_id2 = stream_id1 + 2 * session_.get_max_open_streams(); |
| 343 EXPECT_CALL(*connection_, SendConnectionClose(QUIC_TOO_MANY_OPEN_STREAMS)); | 343 EXPECT_CALL(*connection_, SendConnectionClose(QUIC_TOO_MANY_OPEN_STREAMS)); |
| 344 } | 344 } |
| 345 EXPECT_EQ(nullptr, session_.GetIncomingDynamicStream(stream_id2)); | 345 EXPECT_EQ(nullptr, session_.GetOrCreateDynamicStream(stream_id2)); |
| 346 } | 346 } |
| 347 | 347 |
| 348 TEST_P(QuicSessionTestServer, ManyAvailableStreams) { | 348 TEST_P(QuicSessionTestServer, ManyAvailableStreams) { |
| 349 // When max_open_streams_ is 200, should be able to create 200 streams | 349 // When max_open_streams_ is 200, should be able to create 200 streams |
| 350 // out-of-order, that is, creating the one with the largest stream ID first. | 350 // out-of-order, that is, creating the one with the largest stream ID first. |
| 351 QuicSessionPeer::SetMaxOpenStreams(&session_, 200); | 351 QuicSessionPeer::SetMaxOpenStreams(&session_, 200); |
| 352 QuicStreamId stream_id = kClientDataStreamId1; | 352 QuicStreamId stream_id = kClientDataStreamId1; |
| 353 // Create one stream. | 353 // Create one stream. |
| 354 session_.GetIncomingDynamicStream(stream_id); | 354 session_.GetOrCreateDynamicStream(stream_id); |
| 355 EXPECT_CALL(*connection_, SendConnectionClose(_)).Times(0); | 355 EXPECT_CALL(*connection_, SendConnectionClose(_)).Times(0); |
| 356 // Create the largest stream ID of a threatened total of 200 streams. | 356 // Create the largest stream ID of a threatened total of 200 streams. |
| 357 session_.GetIncomingDynamicStream(stream_id + 2 * (200 - 1)); | 357 session_.GetOrCreateDynamicStream(stream_id + 2 * (200 - 1)); |
| 358 } | 358 } |
| 359 | 359 |
| 360 TEST_P(QuicSessionTestServer, DebugDFatalIfMarkingClosedStreamWriteBlocked) { | 360 TEST_P(QuicSessionTestServer, DebugDFatalIfMarkingClosedStreamWriteBlocked) { |
| 361 TestStream* stream2 = session_.CreateOutgoingDynamicStream(); | 361 TestStream* stream2 = session_.CreateOutgoingDynamicStream(); |
| 362 QuicStreamId closed_stream_id = stream2->id(); | 362 QuicStreamId closed_stream_id = stream2->id(); |
| 363 // Close the stream. | 363 // Close the stream. |
| 364 EXPECT_CALL(*connection_, SendRstStream(closed_stream_id, _, _)); | 364 EXPECT_CALL(*connection_, SendRstStream(closed_stream_id, _, _)); |
| 365 stream2->Reset(QUIC_BAD_APPLICATION_PAYLOAD); | 365 stream2->Reset(QUIC_BAD_APPLICATION_PAYLOAD); |
| 366 EXPECT_DEBUG_DFATAL(session_.MarkConnectionLevelWriteBlocked( | 366 EXPECT_DEBUG_DFATAL(session_.MarkConnectionLevelWriteBlocked( |
| 367 closed_stream_id, kSomeMiddlePriority), | 367 closed_stream_id, kSomeMiddlePriority), |
| (...skipping 218 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 586 .WillOnce(Return(WriteResult(WRITE_STATUS_OK, 0))); | 586 .WillOnce(Return(WriteResult(WRITE_STATUS_OK, 0))); |
| 587 EXPECT_CALL(*connection_, SendGoAway(_, _, _)) | 587 EXPECT_CALL(*connection_, SendGoAway(_, _, _)) |
| 588 .WillOnce(Invoke(connection_, &MockConnection::ReallySendGoAway)); | 588 .WillOnce(Invoke(connection_, &MockConnection::ReallySendGoAway)); |
| 589 session_.SendGoAway(QUIC_PEER_GOING_AWAY, "Going Away."); | 589 session_.SendGoAway(QUIC_PEER_GOING_AWAY, "Going Away."); |
| 590 EXPECT_TRUE(session_.goaway_sent()); | 590 EXPECT_TRUE(session_.goaway_sent()); |
| 591 | 591 |
| 592 const QuicStreamId kTestStreamId = 5u; | 592 const QuicStreamId kTestStreamId = 5u; |
| 593 EXPECT_CALL(*connection_, | 593 EXPECT_CALL(*connection_, |
| 594 SendRstStream(kTestStreamId, QUIC_STREAM_PEER_GOING_AWAY, 0)) | 594 SendRstStream(kTestStreamId, QUIC_STREAM_PEER_GOING_AWAY, 0)) |
| 595 .Times(0); | 595 .Times(0); |
| 596 EXPECT_TRUE(session_.GetIncomingDynamicStream(kTestStreamId)); | 596 EXPECT_TRUE(session_.GetOrCreateDynamicStream(kTestStreamId)); |
| 597 } | 597 } |
| 598 | 598 |
| 599 TEST_P(QuicSessionTestServer, IncreasedTimeoutAfterCryptoHandshake) { | 599 TEST_P(QuicSessionTestServer, IncreasedTimeoutAfterCryptoHandshake) { |
| 600 EXPECT_EQ(kInitialIdleTimeoutSecs + 3, | 600 EXPECT_EQ(kInitialIdleTimeoutSecs + 3, |
| 601 QuicConnectionPeer::GetNetworkTimeout(connection_).ToSeconds()); | 601 QuicConnectionPeer::GetNetworkTimeout(connection_).ToSeconds()); |
| 602 CryptoHandshakeMessage msg; | 602 CryptoHandshakeMessage msg; |
| 603 session_.GetCryptoStream()->OnHandshakeMessage(msg); | 603 session_.GetCryptoStream()->OnHandshakeMessage(msg); |
| 604 EXPECT_EQ(kMaximumIdleTimeoutSecs + 3, | 604 EXPECT_EQ(kMaximumIdleTimeoutSecs + 3, |
| 605 QuicConnectionPeer::GetNetworkTimeout(connection_).ToSeconds()); | 605 QuicConnectionPeer::GetNetworkTimeout(connection_).ToSeconds()); |
| 606 } | 606 } |
| 607 | 607 |
| 608 TEST_P(QuicSessionTestServer, RstStreamBeforeHeadersDecompressed) { | 608 TEST_P(QuicSessionTestServer, RstStreamBeforeHeadersDecompressed) { |
| 609 // Send two bytes of payload. | 609 // Send two bytes of payload. |
| 610 QuicStreamFrame data1(kClientDataStreamId1, false, 0, StringPiece("HT")); | 610 QuicStreamFrame data1(kClientDataStreamId1, false, 0, StringPiece("HT")); |
| 611 session_.OnStreamFrame(data1); | 611 session_.OnStreamFrame(data1); |
| 612 EXPECT_EQ(1u, session_.GetNumOpenStreams()); | 612 EXPECT_EQ(1u, session_.GetNumOpenStreams()); |
| 613 | 613 |
| 614 EXPECT_CALL(*connection_, SendRstStream(kClientDataStreamId1, _, _)); | 614 EXPECT_CALL(*connection_, SendRstStream(kClientDataStreamId1, _, _)); |
| 615 QuicRstStreamFrame rst1(kClientDataStreamId1, QUIC_STREAM_NO_ERROR, 0); | 615 QuicRstStreamFrame rst1(kClientDataStreamId1, QUIC_ERROR_PROCESSING_STREAM, |
| 616 0); |
| 616 session_.OnRstStream(rst1); | 617 session_.OnRstStream(rst1); |
| 617 EXPECT_EQ(0u, session_.GetNumOpenStreams()); | 618 EXPECT_EQ(0u, session_.GetNumOpenStreams()); |
| 618 // Connection should remain alive. | 619 // Connection should remain alive. |
| 619 EXPECT_TRUE(connection_->connected()); | 620 EXPECT_TRUE(connection_->connected()); |
| 620 } | 621 } |
| 621 | 622 |
| 622 TEST_P(QuicSessionTestServer, MultipleRstStreamsCauseSingleConnectionClose) { | 623 TEST_P(QuicSessionTestServer, MultipleRstStreamsCauseSingleConnectionClose) { |
| 623 // If multiple invalid reset stream frames arrive in a single packet, this | 624 // If multiple invalid reset stream frames arrive in a single packet, this |
| 624 // should trigger a connection close. However there is no need to send | 625 // should trigger a connection close. However there is no need to send |
| 625 // multiple connection close frames. | 626 // multiple connection close frames. |
| (...skipping 448 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1074 class QuicSessionTestClient : public QuicSessionTestBase { | 1075 class QuicSessionTestClient : public QuicSessionTestBase { |
| 1075 protected: | 1076 protected: |
| 1076 QuicSessionTestClient() : QuicSessionTestBase(Perspective::IS_CLIENT) {} | 1077 QuicSessionTestClient() : QuicSessionTestBase(Perspective::IS_CLIENT) {} |
| 1077 }; | 1078 }; |
| 1078 | 1079 |
| 1079 INSTANTIATE_TEST_CASE_P(Tests, | 1080 INSTANTIATE_TEST_CASE_P(Tests, |
| 1080 QuicSessionTestClient, | 1081 QuicSessionTestClient, |
| 1081 ::testing::ValuesIn(QuicSupportedVersions())); | 1082 ::testing::ValuesIn(QuicSupportedVersions())); |
| 1082 | 1083 |
| 1083 TEST_P(QuicSessionTestClient, AvailableStreamsClient) { | 1084 TEST_P(QuicSessionTestClient, AvailableStreamsClient) { |
| 1084 ASSERT_TRUE(session_.GetIncomingDynamicStream(6) != nullptr); | 1085 ASSERT_TRUE(session_.GetOrCreateDynamicStream(6) != nullptr); |
| 1085 // Both 2 and 4 should be available. | 1086 // Both 2 and 4 should be available. |
| 1086 EXPECT_TRUE(QuicSessionPeer::IsStreamAvailable(&session_, 2)); | 1087 EXPECT_TRUE(QuicSessionPeer::IsStreamAvailable(&session_, 2)); |
| 1087 EXPECT_TRUE(QuicSessionPeer::IsStreamAvailable(&session_, 4)); | 1088 EXPECT_TRUE(QuicSessionPeer::IsStreamAvailable(&session_, 4)); |
| 1088 ASSERT_TRUE(session_.GetIncomingDynamicStream(2) != nullptr); | 1089 ASSERT_TRUE(session_.GetOrCreateDynamicStream(2) != nullptr); |
| 1089 ASSERT_TRUE(session_.GetIncomingDynamicStream(4) != nullptr); | 1090 ASSERT_TRUE(session_.GetOrCreateDynamicStream(4) != nullptr); |
| 1090 // And 5 should be not available. | 1091 // And 5 should be not available. |
| 1091 EXPECT_FALSE(QuicSessionPeer::IsStreamAvailable(&session_, 5)); | 1092 EXPECT_FALSE(QuicSessionPeer::IsStreamAvailable(&session_, 5)); |
| 1092 } | 1093 } |
| 1093 | 1094 |
| 1094 TEST_P(QuicSessionTestClient, RecordFinAfterReadSideClosed) { | 1095 TEST_P(QuicSessionTestClient, RecordFinAfterReadSideClosed) { |
| 1095 // Verify that an incoming FIN is recorded in a stream object even if the read | 1096 // Verify that an incoming FIN is recorded in a stream object even if the read |
| 1096 // side has been closed. This prevents an entry from being made in | 1097 // side has been closed. This prevents an entry from being made in |
| 1097 // locally_closed_streams_highest_offset_ (which will never be deleted). | 1098 // locally_closed_streams_highest_offset_ (which will never be deleted). |
| 1098 TestStream* stream = session_.CreateOutgoingDynamicStream(); | 1099 TestStream* stream = session_.CreateOutgoingDynamicStream(); |
| 1099 QuicStreamId stream_id = stream->id(); | 1100 QuicStreamId stream_id = stream->id(); |
| (...skipping 22 matching lines...) Expand all Loading... |
| 1122 // Verify that there is no entry for the stream in | 1123 // Verify that there is no entry for the stream in |
| 1123 // locally_closed_streams_highest_offset_. | 1124 // locally_closed_streams_highest_offset_. |
| 1124 EXPECT_EQ( | 1125 EXPECT_EQ( |
| 1125 FLAGS_quic_fix_fin_accounting ? 0u : 1u, | 1126 FLAGS_quic_fix_fin_accounting ? 0u : 1u, |
| 1126 QuicSessionPeer::GetLocallyClosedStreamsHighestOffset(&session_).size()); | 1127 QuicSessionPeer::GetLocallyClosedStreamsHighestOffset(&session_).size()); |
| 1127 } | 1128 } |
| 1128 | 1129 |
| 1129 } // namespace | 1130 } // namespace |
| 1130 } // namespace test | 1131 } // namespace test |
| 1131 } // namespace net | 1132 } // namespace net |
| OLD | NEW |