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/core/quic_session.h" | 5 #include "net/quic/core/quic_session.h" |
6 | 6 |
7 #include <cstdint> | 7 #include <cstdint> |
8 #include <set> | 8 #include <set> |
9 #include <utility> | 9 #include <utility> |
10 | 10 |
(...skipping 265 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
276 } | 276 } |
277 | 277 |
278 void CloseStream(QuicStreamId id) { | 278 void CloseStream(QuicStreamId id) { |
279 EXPECT_CALL(*connection_, SendRstStream(id, _, _)); | 279 EXPECT_CALL(*connection_, SendRstStream(id, _, _)); |
280 session_.CloseStream(id); | 280 session_.CloseStream(id); |
281 closed_streams_.insert(id); | 281 closed_streams_.insert(id); |
282 } | 282 } |
283 | 283 |
284 QuicVersion version() const { return connection_->version(); } | 284 QuicVersion version() const { return connection_->version(); } |
285 | 285 |
| 286 QuicStreamId GetNthClientInitiatedId(int n) { |
| 287 return QuicSpdySessionPeer::GetNthClientInitiatedStreamId(session_, n); |
| 288 } |
| 289 |
| 290 QuicStreamId GetNthServerInitiatedId(int n) { |
| 291 return QuicSpdySessionPeer::GetNthServerInitiatedStreamId(session_, n); |
| 292 } |
| 293 |
| 294 QuicStreamId NextId() { return QuicSpdySessionPeer::NextStreamId(session_); } |
| 295 |
286 MockQuicConnectionHelper helper_; | 296 MockQuicConnectionHelper helper_; |
287 MockAlarmFactory alarm_factory_; | 297 MockAlarmFactory alarm_factory_; |
288 StrictMock<MockQuicConnection>* connection_; | 298 StrictMock<MockQuicConnection>* connection_; |
289 TestSession session_; | 299 TestSession session_; |
290 std::set<QuicStreamId> closed_streams_; | 300 std::set<QuicStreamId> closed_streams_; |
291 SpdyHeaderBlock headers_; | 301 SpdyHeaderBlock headers_; |
292 }; | 302 }; |
293 | 303 |
294 class QuicSessionTestServer : public QuicSessionTestBase { | 304 class QuicSessionTestServer : public QuicSessionTestBase { |
295 protected: | 305 protected: |
(...skipping 27 matching lines...) Expand all Loading... |
323 ASSERT_TRUE(session_.GetOrCreateDynamicStream(9) != nullptr); | 333 ASSERT_TRUE(session_.GetOrCreateDynamicStream(9) != nullptr); |
324 // Both 5 and 7 should be available. | 334 // Both 5 and 7 should be available. |
325 EXPECT_TRUE(QuicSessionPeer::IsStreamAvailable(&session_, 5)); | 335 EXPECT_TRUE(QuicSessionPeer::IsStreamAvailable(&session_, 5)); |
326 EXPECT_TRUE(QuicSessionPeer::IsStreamAvailable(&session_, 7)); | 336 EXPECT_TRUE(QuicSessionPeer::IsStreamAvailable(&session_, 7)); |
327 ASSERT_TRUE(session_.GetOrCreateDynamicStream(7) != nullptr); | 337 ASSERT_TRUE(session_.GetOrCreateDynamicStream(7) != nullptr); |
328 ASSERT_TRUE(session_.GetOrCreateDynamicStream(5) != nullptr); | 338 ASSERT_TRUE(session_.GetOrCreateDynamicStream(5) != nullptr); |
329 } | 339 } |
330 | 340 |
331 TEST_P(QuicSessionTestServer, IsClosedStreamLocallyCreated) { | 341 TEST_P(QuicSessionTestServer, IsClosedStreamLocallyCreated) { |
332 TestStream* stream2 = session_.CreateOutgoingDynamicStream(kDefaultPriority); | 342 TestStream* stream2 = session_.CreateOutgoingDynamicStream(kDefaultPriority); |
333 EXPECT_EQ(2u, stream2->id()); | 343 EXPECT_EQ(GetNthServerInitiatedId(0), stream2->id()); |
334 TestStream* stream4 = session_.CreateOutgoingDynamicStream(kDefaultPriority); | 344 QuicSpdyStream* stream4 = |
335 EXPECT_EQ(4u, stream4->id()); | 345 session_.CreateOutgoingDynamicStream(kDefaultPriority); |
| 346 EXPECT_EQ(GetNthServerInitiatedId(1), stream4->id()); |
336 | 347 |
337 CheckClosedStreams(); | 348 CheckClosedStreams(); |
338 CloseStream(4); | 349 CloseStream(GetNthServerInitiatedId(0)); |
339 CheckClosedStreams(); | 350 CheckClosedStreams(); |
340 CloseStream(2); | 351 CloseStream(GetNthServerInitiatedId(1)); |
341 CheckClosedStreams(); | 352 CheckClosedStreams(); |
342 } | 353 } |
343 | 354 |
344 TEST_P(QuicSessionTestServer, IsClosedStreamPeerCreated) { | 355 TEST_P(QuicSessionTestServer, IsClosedStreamPeerCreated) { |
345 QuicStreamId stream_id1 = kClientDataStreamId1; | 356 QuicStreamId stream_id1 = GetNthClientInitiatedId(0); |
346 QuicStreamId stream_id2 = kClientDataStreamId2; | 357 QuicStreamId stream_id2 = GetNthClientInitiatedId(1); |
347 session_.GetOrCreateDynamicStream(stream_id1); | 358 session_.GetOrCreateDynamicStream(stream_id1); |
348 session_.GetOrCreateDynamicStream(stream_id2); | 359 session_.GetOrCreateDynamicStream(stream_id2); |
349 | 360 |
350 CheckClosedStreams(); | 361 CheckClosedStreams(); |
351 CloseStream(stream_id1); | 362 CloseStream(stream_id1); |
352 CheckClosedStreams(); | 363 CheckClosedStreams(); |
353 CloseStream(stream_id2); | 364 CloseStream(stream_id2); |
354 // Create a stream, and make another available. | 365 // Create a stream, and make another available. |
355 QuicStream* stream3 = session_.GetOrCreateDynamicStream(stream_id2 + 4); | 366 QuicStream* stream3 = session_.GetOrCreateDynamicStream(stream_id2 + 4); |
356 CheckClosedStreams(); | 367 CheckClosedStreams(); |
357 // Close one, but make sure the other is still not closed | 368 // Close one, but make sure the other is still not closed |
358 CloseStream(stream3->id()); | 369 CloseStream(stream3->id()); |
359 CheckClosedStreams(); | 370 CheckClosedStreams(); |
360 } | 371 } |
361 | 372 |
362 TEST_P(QuicSessionTestServer, MaximumAvailableOpenedStreams) { | 373 TEST_P(QuicSessionTestServer, MaximumAvailableOpenedStreams) { |
363 QuicStreamId stream_id = kClientDataStreamId1; | 374 QuicStreamId stream_id = GetNthClientInitiatedId(0); |
364 session_.GetOrCreateDynamicStream(stream_id); | 375 session_.GetOrCreateDynamicStream(stream_id); |
365 EXPECT_CALL(*connection_, CloseConnection(_, _, _)).Times(0); | 376 EXPECT_CALL(*connection_, CloseConnection(_, _, _)).Times(0); |
366 EXPECT_NE(nullptr, | 377 EXPECT_NE(nullptr, |
367 session_.GetOrCreateDynamicStream( | 378 session_.GetOrCreateDynamicStream( |
368 stream_id + 2 * (session_.max_open_incoming_streams() - 1))); | 379 stream_id + 2 * (session_.max_open_incoming_streams() - 1))); |
369 } | 380 } |
370 | 381 |
371 TEST_P(QuicSessionTestServer, TooManyAvailableStreams) { | 382 TEST_P(QuicSessionTestServer, TooManyAvailableStreams) { |
372 QuicStreamId stream_id1 = kClientDataStreamId1; | 383 QuicStreamId stream_id1 = GetNthClientInitiatedId(0); |
373 QuicStreamId stream_id2; | 384 QuicStreamId stream_id2; |
374 EXPECT_NE(nullptr, session_.GetOrCreateDynamicStream(stream_id1)); | 385 EXPECT_NE(nullptr, session_.GetOrCreateDynamicStream(stream_id1)); |
375 // A stream ID which is too large to create. | 386 // A stream ID which is too large to create. |
376 stream_id2 = stream_id1 + 2 * session_.MaxAvailableStreams() + 4; | 387 stream_id2 = GetNthClientInitiatedId(2 * session_.MaxAvailableStreams() + 4); |
377 EXPECT_CALL(*connection_, | 388 EXPECT_CALL(*connection_, |
378 CloseConnection(QUIC_TOO_MANY_AVAILABLE_STREAMS, _, _)); | 389 CloseConnection(QUIC_TOO_MANY_AVAILABLE_STREAMS, _, _)); |
379 EXPECT_EQ(nullptr, session_.GetOrCreateDynamicStream(stream_id2)); | 390 EXPECT_EQ(nullptr, session_.GetOrCreateDynamicStream(stream_id2)); |
380 } | 391 } |
381 | 392 |
382 TEST_P(QuicSessionTestServer, ManyAvailableStreams) { | 393 TEST_P(QuicSessionTestServer, ManyAvailableStreams) { |
383 // When max_open_streams_ is 200, should be able to create 200 streams | 394 // When max_open_streams_ is 200, should be able to create 200 streams |
384 // out-of-order, that is, creating the one with the largest stream ID first. | 395 // out-of-order, that is, creating the one with the largest stream ID first. |
385 QuicSessionPeer::SetMaxOpenIncomingStreams(&session_, 200); | 396 QuicSessionPeer::SetMaxOpenIncomingStreams(&session_, 200); |
386 QuicStreamId stream_id = kClientDataStreamId1; | 397 QuicStreamId stream_id = GetNthClientInitiatedId(0); |
387 // Create one stream. | 398 // Create one stream. |
388 session_.GetOrCreateDynamicStream(stream_id); | 399 session_.GetOrCreateDynamicStream(stream_id); |
389 EXPECT_CALL(*connection_, CloseConnection(_, _, _)).Times(0); | 400 EXPECT_CALL(*connection_, CloseConnection(_, _, _)).Times(0); |
390 // Create the largest stream ID of a threatened total of 200 streams. | 401 // Create the largest stream ID of a threatened total of 200 streams. |
391 session_.GetOrCreateDynamicStream(stream_id + 2 * (200 - 1)); | 402 session_.GetOrCreateDynamicStream(stream_id + 2 * (200 - 1)); |
392 } | 403 } |
393 | 404 |
394 TEST_P(QuicSessionTestServer, DebugDFatalIfMarkingClosedStreamWriteBlocked) { | 405 TEST_P(QuicSessionTestServer, DebugDFatalIfMarkingClosedStreamWriteBlocked) { |
395 TestStream* stream2 = session_.CreateOutgoingDynamicStream(kDefaultPriority); | 406 TestStream* stream2 = session_.CreateOutgoingDynamicStream(kDefaultPriority); |
396 QuicStreamId closed_stream_id = stream2->id(); | 407 QuicStreamId closed_stream_id = stream2->id(); |
397 // Close the stream. | 408 // Close the stream. |
398 EXPECT_CALL(*connection_, SendRstStream(closed_stream_id, _, _)); | 409 EXPECT_CALL(*connection_, SendRstStream(closed_stream_id, _, _)); |
399 stream2->Reset(QUIC_BAD_APPLICATION_PAYLOAD); | 410 stream2->Reset(QUIC_BAD_APPLICATION_PAYLOAD); |
| 411 string msg = |
| 412 QuicStrCat("Marking unknown stream ", closed_stream_id, " blocked."); |
400 EXPECT_QUIC_BUG(session_.MarkConnectionLevelWriteBlocked(closed_stream_id), | 413 EXPECT_QUIC_BUG(session_.MarkConnectionLevelWriteBlocked(closed_stream_id), |
401 "Marking unknown stream 2 blocked."); | 414 msg); |
402 } | 415 } |
403 | 416 |
404 TEST_P(QuicSessionTestServer, OnCanWrite) { | 417 TEST_P(QuicSessionTestServer, OnCanWrite) { |
405 session_.set_writev_consumes_all_data(true); | 418 session_.set_writev_consumes_all_data(true); |
406 TestStream* stream2 = session_.CreateOutgoingDynamicStream(kDefaultPriority); | 419 TestStream* stream2 = session_.CreateOutgoingDynamicStream(kDefaultPriority); |
407 TestStream* stream4 = session_.CreateOutgoingDynamicStream(kDefaultPriority); | 420 TestStream* stream4 = session_.CreateOutgoingDynamicStream(kDefaultPriority); |
408 TestStream* stream6 = session_.CreateOutgoingDynamicStream(kDefaultPriority); | 421 TestStream* stream6 = session_.CreateOutgoingDynamicStream(kDefaultPriority); |
409 | 422 |
410 session_.MarkConnectionLevelWriteBlocked(stream2->id()); | 423 session_.MarkConnectionLevelWriteBlocked(stream2->id()); |
411 session_.MarkConnectionLevelWriteBlocked(stream6->id()); | 424 session_.MarkConnectionLevelWriteBlocked(stream6->id()); |
(...skipping 381 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
793 EXPECT_EQ(kInitialIdleTimeoutSecs + 3, | 806 EXPECT_EQ(kInitialIdleTimeoutSecs + 3, |
794 QuicConnectionPeer::GetNetworkTimeout(connection_).ToSeconds()); | 807 QuicConnectionPeer::GetNetworkTimeout(connection_).ToSeconds()); |
795 CryptoHandshakeMessage msg; | 808 CryptoHandshakeMessage msg; |
796 session_.GetMutableCryptoStream()->OnHandshakeMessage(msg); | 809 session_.GetMutableCryptoStream()->OnHandshakeMessage(msg); |
797 EXPECT_EQ(kMaximumIdleTimeoutSecs + 3, | 810 EXPECT_EQ(kMaximumIdleTimeoutSecs + 3, |
798 QuicConnectionPeer::GetNetworkTimeout(connection_).ToSeconds()); | 811 QuicConnectionPeer::GetNetworkTimeout(connection_).ToSeconds()); |
799 } | 812 } |
800 | 813 |
801 TEST_P(QuicSessionTestServer, RstStreamBeforeHeadersDecompressed) { | 814 TEST_P(QuicSessionTestServer, RstStreamBeforeHeadersDecompressed) { |
802 // Send two bytes of payload. | 815 // Send two bytes of payload. |
803 QuicStreamFrame data1(kClientDataStreamId1, false, 0, QuicStringPiece("HT")); | 816 QuicStreamFrame data1(GetNthClientInitiatedId(0), false, 0, |
| 817 QuicStringPiece("HT")); |
804 session_.OnStreamFrame(data1); | 818 session_.OnStreamFrame(data1); |
805 EXPECT_EQ(1u, session_.GetNumOpenIncomingStreams()); | 819 EXPECT_EQ(1u, session_.GetNumOpenIncomingStreams()); |
806 | 820 |
807 EXPECT_CALL(*connection_, SendRstStream(kClientDataStreamId1, _, _)); | 821 EXPECT_CALL(*connection_, SendRstStream(GetNthClientInitiatedId(0), _, _)); |
808 QuicRstStreamFrame rst1(kClientDataStreamId1, QUIC_ERROR_PROCESSING_STREAM, | 822 QuicRstStreamFrame rst1(GetNthClientInitiatedId(0), |
809 0); | 823 QUIC_ERROR_PROCESSING_STREAM, 0); |
810 session_.OnRstStream(rst1); | 824 session_.OnRstStream(rst1); |
811 EXPECT_EQ(0u, session_.GetNumOpenIncomingStreams()); | 825 EXPECT_EQ(0u, session_.GetNumOpenIncomingStreams()); |
812 // Connection should remain alive. | 826 // Connection should remain alive. |
813 EXPECT_TRUE(connection_->connected()); | 827 EXPECT_TRUE(connection_->connected()); |
814 } | 828 } |
815 | 829 |
816 TEST_P(QuicSessionTestServer, HandshakeUnblocksFlowControlBlockedStream) { | 830 TEST_P(QuicSessionTestServer, HandshakeUnblocksFlowControlBlockedStream) { |
817 // Test that if a stream is flow control blocked, then on receipt of the SHLO | 831 // Test that if a stream is flow control blocked, then on receipt of the SHLO |
818 // containing a suitable send window offset, the stream becomes unblocked. | 832 // containing a suitable send window offset, the stream becomes unblocked. |
819 | 833 |
(...skipping 328 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1148 EXPECT_FALSE(headers_stream->flow_controller()->IsBlocked()); | 1162 EXPECT_FALSE(headers_stream->flow_controller()->IsBlocked()); |
1149 EXPECT_FALSE(session_.IsConnectionFlowControlBlocked()); | 1163 EXPECT_FALSE(session_.IsConnectionFlowControlBlocked()); |
1150 EXPECT_FALSE(session_.IsStreamFlowControlBlocked()); | 1164 EXPECT_FALSE(session_.IsStreamFlowControlBlocked()); |
1151 } | 1165 } |
1152 | 1166 |
1153 TEST_P(QuicSessionTestServer, TooManyUnfinishedStreamsCauseServerRejectStream) { | 1167 TEST_P(QuicSessionTestServer, TooManyUnfinishedStreamsCauseServerRejectStream) { |
1154 // If a buggy/malicious peer creates too many streams that are not ended | 1168 // If a buggy/malicious peer creates too many streams that are not ended |
1155 // with a FIN or RST then we send an RST to refuse streams. | 1169 // with a FIN or RST then we send an RST to refuse streams. |
1156 const QuicStreamId kMaxStreams = 5; | 1170 const QuicStreamId kMaxStreams = 5; |
1157 QuicSessionPeer::SetMaxOpenIncomingStreams(&session_, kMaxStreams); | 1171 QuicSessionPeer::SetMaxOpenIncomingStreams(&session_, kMaxStreams); |
1158 const QuicStreamId kFirstStreamId = kClientDataStreamId1; | 1172 const QuicStreamId kFirstStreamId = GetNthClientInitiatedId(0); |
1159 const QuicStreamId kFinalStreamId = kClientDataStreamId1 + 2 * kMaxStreams; | 1173 const QuicStreamId kFinalStreamId = GetNthClientInitiatedId(kMaxStreams); |
1160 | |
1161 // Create kMaxStreams data streams, and close them all without receiving a | 1174 // Create kMaxStreams data streams, and close them all without receiving a |
1162 // FIN or a RST_STREAM from the client. | 1175 // FIN or a RST_STREAM from the client. |
1163 for (QuicStreamId i = kFirstStreamId; i < kFinalStreamId; i += 2) { | 1176 const QuicStreamId kNextId = QuicSpdySessionPeer::NextStreamId(session_); |
| 1177 for (QuicStreamId i = kFirstStreamId; i < kFinalStreamId; i += kNextId) { |
1164 QuicStreamFrame data1(i, false, 0, QuicStringPiece("HT")); | 1178 QuicStreamFrame data1(i, false, 0, QuicStringPiece("HT")); |
1165 session_.OnStreamFrame(data1); | 1179 session_.OnStreamFrame(data1); |
1166 // EXPECT_EQ(1u, session_.GetNumOpenStreams()); | 1180 // EXPECT_EQ(1u, session_.GetNumOpenStreams()); |
1167 EXPECT_CALL(*connection_, SendRstStream(i, _, _)); | 1181 EXPECT_CALL(*connection_, SendRstStream(i, _, _)); |
1168 session_.CloseStream(i); | 1182 session_.CloseStream(i); |
1169 } | 1183 } |
1170 | 1184 |
1171 EXPECT_CALL(*connection_, | 1185 EXPECT_CALL(*connection_, |
1172 SendRstStream(kFinalStreamId, QUIC_REFUSED_STREAM, _)) | 1186 SendRstStream(kFinalStreamId, QUIC_REFUSED_STREAM, _)) |
1173 .Times(1); | 1187 .Times(1); |
1174 // Create one more data streams to exceed limit of open stream. | 1188 // Create one more data streams to exceed limit of open stream. |
1175 QuicStreamFrame data1(kFinalStreamId, false, 0, QuicStringPiece("HT")); | 1189 QuicStreamFrame data1(kFinalStreamId, false, 0, QuicStringPiece("HT")); |
1176 session_.OnStreamFrame(data1); | 1190 session_.OnStreamFrame(data1); |
1177 | 1191 |
1178 // Called after any new data is received by the session, and triggers the | 1192 // Called after any new data is received by the session, and triggers the |
1179 // call to close the connection. | 1193 // call to close the connection. |
1180 session_.PostProcessAfterData(); | 1194 session_.PostProcessAfterData(); |
1181 } | 1195 } |
1182 | 1196 |
1183 TEST_P(QuicSessionTestServer, DrainingStreamsDoNotCountAsOpened) { | 1197 TEST_P(QuicSessionTestServer, DrainingStreamsDoNotCountAsOpened) { |
1184 // Verify that a draining stream (which has received a FIN but not consumed | 1198 // Verify that a draining stream (which has received a FIN but not consumed |
1185 // it) does not count against the open quota (because it is closed from the | 1199 // it) does not count against the open quota (because it is closed from the |
1186 // protocol point of view). | 1200 // protocol point of view). |
1187 EXPECT_CALL(*connection_, SendRstStream(_, QUIC_REFUSED_STREAM, _)).Times(0); | 1201 EXPECT_CALL(*connection_, SendRstStream(_, QUIC_REFUSED_STREAM, _)).Times(0); |
1188 const QuicStreamId kMaxStreams = 5; | 1202 const QuicStreamId kMaxStreams = 5; |
1189 QuicSessionPeer::SetMaxOpenIncomingStreams(&session_, kMaxStreams); | 1203 QuicSessionPeer::SetMaxOpenIncomingStreams(&session_, kMaxStreams); |
1190 | 1204 |
1191 // Create kMaxStreams + 1 data streams, and mark them draining. | 1205 // Create kMaxStreams + 1 data streams, and mark them draining. |
1192 const QuicStreamId kFirstStreamId = kClientDataStreamId1; | 1206 const QuicStreamId kFirstStreamId = GetNthClientInitiatedId(0); |
1193 const QuicStreamId kFinalStreamId = | 1207 const QuicStreamId kFinalStreamId = |
1194 kClientDataStreamId1 + 2 * kMaxStreams + 1; | 1208 GetNthClientInitiatedId(2 * kMaxStreams + 1); |
1195 for (QuicStreamId i = kFirstStreamId; i < kFinalStreamId; i += 2) { | 1209 for (QuicStreamId i = kFirstStreamId; i < kFinalStreamId; i += NextId()) { |
1196 QuicStreamFrame data1(i, true, 0, QuicStringPiece("HT")); | 1210 QuicStreamFrame data1(i, true, 0, QuicStringPiece("HT")); |
1197 session_.OnStreamFrame(data1); | 1211 session_.OnStreamFrame(data1); |
1198 EXPECT_EQ(1u, session_.GetNumOpenIncomingStreams()); | 1212 EXPECT_EQ(1u, session_.GetNumOpenIncomingStreams()); |
1199 session_.StreamDraining(i); | 1213 session_.StreamDraining(i); |
1200 EXPECT_EQ(0u, session_.GetNumOpenIncomingStreams()); | 1214 EXPECT_EQ(0u, session_.GetNumOpenIncomingStreams()); |
1201 } | 1215 } |
1202 | 1216 |
1203 // Called after any new data is received by the session, and triggers the call | 1217 // Called after any new data is received by the session, and triggers the call |
1204 // to close the connection. | 1218 // to close the connection. |
1205 session_.PostProcessAfterData(); | 1219 session_.PostProcessAfterData(); |
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1312 if (version() != QUIC_VERSION_36) { | 1326 if (version() != QUIC_VERSION_36) { |
1313 EXPECT_FALSE(session_.force_hol_blocking()); | 1327 EXPECT_FALSE(session_.force_hol_blocking()); |
1314 } else { | 1328 } else { |
1315 EXPECT_TRUE(session_.force_hol_blocking()); | 1329 EXPECT_TRUE(session_.force_hol_blocking()); |
1316 } | 1330 } |
1317 } | 1331 } |
1318 | 1332 |
1319 } // namespace | 1333 } // namespace |
1320 } // namespace test | 1334 } // namespace test |
1321 } // namespace net | 1335 } // namespace net |
OLD | NEW |