Explicitly cast QuicIetfTransportErrorCodes to uint16_t when forwarded to QuicStrCat.

Otherwise, if a QuicIetfTransportErrorCodes is forwarded to QuicStrCat, chromium QuicStrCatImpl will call operator << on QuicIetfTransportErrorCodes again, which introduces an infinite loop.

gfe-relnote: n/a Version 99 only.
PiperOrigin-RevId: 266411556
Change-Id: Idfb7956effb9c512869ec77f857df4be64d32227
diff --git a/quic/core/quic_types.cc b/quic/core/quic_types.cc
index a7453e8..46f809d 100644
--- a/quic/core/quic_types.cc
+++ b/quic/core/quic_types.cc
@@ -4,6 +4,8 @@
 
 #include "net/third_party/quiche/src/quic/core/quic_types.h"
 
+#include <cstdint>
+
 #include "net/third_party/quiche/src/quic/platform/api/quic_str_cat.h"
 
 namespace quic {
@@ -83,7 +85,7 @@
 
 std::string QuicIetfTransportErrorCodeString(QuicIetfTransportErrorCodes c) {
   if (static_cast<uint16_t>(c) >= 0xff00u) {
-    return QuicStrCat("Private value: ", c);
+    return QuicStrCat("Private value: ", static_cast<uint16_t>(c));
   }
 
   switch (c) {
@@ -100,7 +102,8 @@
     RETURN_STRING_LITERAL(PROTOCOL_VIOLATION);
     RETURN_STRING_LITERAL(INVALID_MIGRATION);
     default:
-      return QuicStrCat("Unknown Transport Error Code Value: ", c);
+      return QuicStrCat("Unknown Transport Error Code Value: ",
+                        static_cast<uint16_t>(c));
   }
 }
 
diff --git a/quic/core/quic_types_test.cc b/quic/core/quic_types_test.cc
new file mode 100644
index 0000000..8b4df89
--- /dev/null
+++ b/quic/core/quic_types_test.cc
@@ -0,0 +1,40 @@
+// Copyright (c) 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "net/third_party/quiche/src/quic/core/quic_types.h"
+
+#include <cstdint>
+
+#include "net/third_party/quiche/src/quic/platform/api/quic_str_cat.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
+
+namespace quic {
+namespace test {
+namespace {
+
+class QuicUtilsTest : public QuicTest {};
+
+TEST_F(QuicUtilsTest, QuicIetfTransportErrorCodeString) {
+  // QuicIetfTransportErrorCode out of bound.
+  for (quic::QuicErrorCode error = quic::QUIC_ENCRYPTION_FAILURE;
+       error < quic::QUIC_LAST_ERROR;
+       error = static_cast<quic::QuicErrorCode>(error + 1)) {
+    QuicErrorCodeToIetfMapping mapping =
+        QuicErrorCodeToTransportErrorCode(error);
+    if (mapping.is_transport_close_) {
+      EXPECT_EQ(
+          QuicIetfTransportErrorCodeString(mapping.transport_error_code_),
+          QuicStrCat("Unknown Transport Error Code Value: ",
+                     static_cast<uint16_t>(mapping.transport_error_code_)));
+    } else {
+      // Some QuicErrorCodes are no longer valid.
+      EXPECT_EQ(QuicIetfTransportErrorCodeString(mapping.transport_error_code_),
+                "NO_IETF_QUIC_ERROR");
+    }
+  }
+}
+
+}  // namespace
+}  // namespace test
+}  // namespace quic