Map QuicErrorCodes to proper IETF QUIC Close Connection information. THis CL maps a QuicErrorCode to either an IETF QUIC Application Connection Close or Transport Connection Close. In the latter case, the mapping also produces the correct IETF QUIC TransportErrorCode to use. gfe-relnote: N/A code exercised only for IETF QUIC. PiperOrigin-RevId: 261741702 Change-Id: I1e928046b18c86ff0a7cbcf013e0d9219c27d2dd
diff --git a/quic/core/quic_connection_test.cc b/quic/core/quic_connection_test.cc index 773db66..39d2760 100644 --- a/quic/core/quic_connection_test.cc +++ b/quic/core/quic_connection_test.cc
@@ -1437,11 +1437,27 @@ header.packet_number = QuicPacketNumber(number); - QuicConnectionCloseFrame qccf(QUIC_PEER_GOING_AWAY, ""); + QuicErrorCode kQuicErrorCode = QUIC_PEER_GOING_AWAY; + // This QuicConnectionCloseFrame will default to being for a Google QUIC + // close. If doing IETF QUIC then set fields appropriately for CC/T or CC/A, + // depending on the mapping. + QuicConnectionCloseFrame qccf(kQuicErrorCode, ""); if (VersionHasIetfQuicFrames(peer_framer_.transport_version())) { - // Default close-type is Google QUIC. If doing IETF QUIC then - // set close type to be IETF CC/T. - qccf.close_type = IETF_QUIC_TRANSPORT_CONNECTION_CLOSE; + QuicErrorCodeToIetfMapping mapping = + QuicErrorCodeToTransportErrorCode(kQuicErrorCode); + if (mapping.is_transport_close_) { + // Maps to a transport close + qccf.close_type = IETF_QUIC_TRANSPORT_CONNECTION_CLOSE; + qccf.transport_error_code = mapping.transport_error_code_; + // TODO(fkastenholz) need to change "0" to get the frame type currently + // being processed so that it can be inserted into the frame. + qccf.transport_close_frame_type = 0; + } else { + // Maps to an application close. + qccf.close_type = IETF_QUIC_APPLICATION_CONNECTION_CLOSE; + qccf.application_error_code = mapping.application_error_code_; + } + qccf.extracted_error_code = kQuicErrorCode; } QuicFrames frames; @@ -1556,7 +1572,32 @@ const std::vector<QuicConnectionCloseFrame>& connection_close_frames = writer_->connection_close_frames(); ASSERT_EQ(1u, connection_close_frames.size()); - EXPECT_EQ(expected_code, connection_close_frames[0].quic_error_code); + if (!VersionHasIetfQuicFrames(version().transport_version)) { + EXPECT_EQ(expected_code, connection_close_frames[0].quic_error_code); + EXPECT_EQ(GOOGLE_QUIC_CONNECTION_CLOSE, + connection_close_frames[0].close_type); + return; + } + + QuicErrorCodeToIetfMapping mapping = + QuicErrorCodeToTransportErrorCode(expected_code); + + if (mapping.is_transport_close_) { + // This Google QUIC Error Code maps to a transport close, + EXPECT_EQ(IETF_QUIC_TRANSPORT_CONNECTION_CLOSE, + connection_close_frames[0].close_type); + EXPECT_EQ(mapping.transport_error_code_, + connection_close_frames[0].transport_error_code); + // TODO(fkastenholz): when the extracted error code CL lands, + // need to test that extracted==expected. + } else { + // This maps to an application close. + EXPECT_EQ(expected_code, connection_close_frames[0].quic_error_code); + EXPECT_EQ(IETF_QUIC_APPLICATION_CONNECTION_CLOSE, + connection_close_frames[0].close_type); + // TODO(fkastenholz): when the extracted error code CL lands, + // need to test that extracted==expected. + } } QuicConnectionId connection_id_; @@ -1597,6 +1638,36 @@ QuicConnectionTest, ::testing::ValuesIn(GetTestParams())); +// These two tests ensure that the QuicErrorCode mapping works correctly. +// Both tests expect to see a Google QUIC close if not running IETF QUIC. +// If running IETF QUIC, the first will generate a transport connection +// close, the second an application connection close. +// The connection close codes for the two tests are manually chosen; +// they are expected to always map to transport- and application- +// closes, respectively. If that changes, mew codes should be chosen. +TEST_P(QuicConnectionTest, CloseErrorCodeTestTransport) { + EXPECT_TRUE(connection_.connected()); + EXPECT_CALL(visitor_, OnConnectionClosed(_, _)); + connection_.CloseConnection( + IETF_QUIC_PROTOCOL_VIOLATION, "Should be transport close", + ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET); + EXPECT_FALSE(connection_.connected()); + TestConnectionCloseQuicErrorCode(IETF_QUIC_PROTOCOL_VIOLATION); +} + +// Test that the IETF QUIC Error code mapping function works +// properly for application connection close codes. +TEST_P(QuicConnectionTest, CloseErrorCodeTestApplication) { + EXPECT_TRUE(connection_.connected()); + EXPECT_CALL(visitor_, OnConnectionClosed(_, _)); + connection_.CloseConnection( + QUIC_HEADERS_STREAM_DATA_DECOMPRESS_FAILURE, + "Should be application close", + ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET); + EXPECT_FALSE(connection_.connected()); + TestConnectionCloseQuicErrorCode(QUIC_HEADERS_STREAM_DATA_DECOMPRESS_FAILURE); +} + TEST_P(QuicConnectionTest, SelfAddressChangeAtClient) { EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_)); @@ -1942,8 +2013,13 @@ TestConnectionCloseQuicErrorCode(QUIC_INTERNAL_ERROR); const std::vector<QuicConnectionCloseFrame>& connection_close_frames = writer_->connection_close_frames(); - EXPECT_EQ("Packet written out of order.", - connection_close_frames[0].error_details); + if (VersionHasIetfQuicFrames(version().transport_version)) { + EXPECT_EQ("1:Packet written out of order.", + connection_close_frames[0].error_details); + } else { + EXPECT_EQ("Packet written out of order.", + connection_close_frames[0].error_details); + } } TEST_P(QuicConnectionTest, DiscardQueuedPacketsAfterConnectionClose) {