TEST(RouterFilterUtilityTest, FinalTimeout) {
  {
    NiceMock<MockRouteEntry> route;
    EXPECT_CALL(route, timeout()).WillOnce(Return(std::chrono::milliseconds(10)));
    Http::TestRequestHeaderMapImpl headers;
    FilterUtility::TimeoutData timeout =
        FilterUtility::finalTimeout(route, headers, true, false, false, false);
    EXPECT_EQ(std::chrono::milliseconds(10), timeout.global_timeout_);
    EXPECT_EQ(std::chrono::milliseconds(0), timeout.per_try_timeout_);
  }
  {
    NiceMock<MockRouteEntry> route;
    EXPECT_CALL(route, timeout()).WillOnce(Return(std::chrono::milliseconds(10)));
    Http::TestRequestHeaderMapImpl headers{{"x-envoy-upstream-rq-timeout-ms", "15"}};
    FilterUtility::TimeoutData timeout =
        FilterUtility::finalTimeout(route, headers, true, false, false, false);
    EXPECT_EQ(std::chrono::milliseconds(15), timeout.global_timeout_);
    EXPECT_EQ(std::chrono::milliseconds(0), timeout.per_try_timeout_);
    EXPECT_FALSE(headers.has("x-envoy-upstream-rq-timeout-ms"));
    EXPECT_EQ("15", headers.get_("x-envoy-expected-rq-timeout-ms"));
    EXPECT_FALSE(headers.has("grpc-timeout"));
  }
  {
    NiceMock<MockRouteEntry> route;
    EXPECT_CALL(route, timeout()).WillOnce(Return(std::chrono::milliseconds(10)));
    Http::TestRequestHeaderMapImpl headers{{"x-envoy-upstream-rq-timeout-ms", "bad"}};
    FilterUtility::TimeoutData timeout =
        FilterUtility::finalTimeout(route, headers, true, false, false, false);
    EXPECT_EQ(std::chrono::milliseconds(10), timeout.global_timeout_);
    EXPECT_EQ(std::chrono::milliseconds(0), timeout.per_try_timeout_);
    EXPECT_FALSE(headers.has("x-envoy-upstream-rq-timeout-ms"));
    EXPECT_EQ("10", headers.get_("x-envoy-expected-rq-timeout-ms"));
    EXPECT_FALSE(headers.has("grpc-timeout"));
  }
  {
    NiceMock<MockRouteEntry> route;
    EXPECT_CALL(route, timeout()).WillOnce(Return(std::chrono::milliseconds(10)));
    Http::TestRequestHeaderMapImpl headers{{"x-envoy-upstream-rq-timeout-ms", "15"},
                                           {"x-envoy-upstream-rq-per-try-timeout-ms", "15"}};
    FilterUtility::TimeoutData timeout =
        FilterUtility::finalTimeout(route, headers, true, false, false, false);
    EXPECT_EQ(std::chrono::milliseconds(15), timeout.global_timeout_);
    EXPECT_EQ(std::chrono::milliseconds(0), timeout.per_try_timeout_);
    EXPECT_FALSE(headers.has("x-envoy-upstream-rq-timeout-ms"));
    EXPECT_FALSE(headers.has("x-envoy-upstream-rq-per-try-timeout-ms"));
    EXPECT_EQ("15", headers.get_("x-envoy-expected-rq-timeout-ms"));
    EXPECT_FALSE(headers.has("grpc-timeout"));
  }
  {
    NiceMock<MockRouteEntry> route;
    EXPECT_CALL(route, timeout()).WillOnce(Return(std::chrono::milliseconds(10)));
    Http::TestRequestHeaderMapImpl headers{{"x-envoy-upstream-rq-timeout-ms", "15"},
                                           {"x-envoy-upstream-rq-per-try-timeout-ms", "5"}};
    FilterUtility::TimeoutData timeout =
        FilterUtility::finalTimeout(route, headers, true, false, false, false);
    EXPECT_EQ(std::chrono::milliseconds(15), timeout.global_timeout_);
    EXPECT_EQ(std::chrono::milliseconds(5), timeout.per_try_timeout_);
    EXPECT_FALSE(headers.has("x-envoy-upstream-rq-timeout-ms"));
    EXPECT_FALSE(headers.has("x-envoy-upstream-rq-per-try-timeout-ms"));
    EXPECT_EQ("5", headers.get_("x-envoy-expected-rq-timeout-ms"));
    EXPECT_FALSE(headers.has("grpc-timeout"));
  }
  {
    NiceMock<MockRouteEntry> route;
    EXPECT_CALL(route, timeout()).WillOnce(Return(std::chrono::milliseconds(10)));
    Http::TestRequestHeaderMapImpl headers{{"x-envoy-upstream-rq-timeout-ms", "15"},
                                           {"x-envoy-upstream-rq-per-try-timeout-ms", "5"}};
    FilterUtility::TimeoutData timeout =
        FilterUtility::finalTimeout(route, headers, true, false, true, false);
    EXPECT_EQ(std::chrono::milliseconds(15), timeout.global_timeout_);
    EXPECT_EQ(std::chrono::milliseconds(5), timeout.per_try_timeout_);
    EXPECT_FALSE(headers.has("x-envoy-upstream-rq-timeout-ms"));
    EXPECT_FALSE(headers.has("x-envoy-upstream-rq-per-try-timeout-ms"));
    EXPECT_EQ("15", headers.get_("x-envoy-expected-rq-timeout-ms"));
    EXPECT_FALSE(headers.has("grpc-timeout"));
  }
  {
    NiceMock<MockRouteEntry> route;
    EXPECT_CALL(route, maxGrpcTimeout())
        .WillRepeatedly(Return(absl::optional<std::chrono::milliseconds>(10)));
    Http::TestRequestHeaderMapImpl headers{{"x-envoy-upstream-rq-timeout-ms", "15"},
                                           {"x-envoy-upstream-rq-per-try-timeout-ms", "5"}};
    FilterUtility::TimeoutData timeout =
        FilterUtility::finalTimeout(route, headers, true, true, true, false);
    EXPECT_EQ(std::chrono::milliseconds(15), timeout.global_timeout_);
    EXPECT_EQ(std::chrono::milliseconds(5), timeout.per_try_timeout_);
    EXPECT_FALSE(headers.has("x-envoy-upstream-rq-timeout-ms"));
    EXPECT_FALSE(headers.has("x-envoy-upstream-rq-per-try-timeout-ms"));
    EXPECT_EQ("15", headers.get_("x-envoy-expected-rq-timeout-ms"));
    EXPECT_EQ("15m", headers.get_("grpc-timeout"));
  }
  {
    NiceMock<MockRouteEntry> route;
    route.retry_policy_.per_try_timeout_ = std::chrono::milliseconds(7);
    EXPECT_CALL(route, timeout()).WillOnce(Return(std::chrono::milliseconds(10)));
    Http::TestRequestHeaderMapImpl headers{{"x-envoy-upstream-rq-timeout-ms", "15"}};
    FilterUtility::TimeoutData timeout =
        FilterUtility::finalTimeout(route, headers, true, false, false, false);
    EXPECT_EQ(std::chrono::milliseconds(15), timeout.global_timeout_);
    EXPECT_EQ(std::chrono::milliseconds(7), timeout.per_try_timeout_);
    EXPECT_FALSE(headers.has("x-envoy-upstream-rq-timeout-ms"));
    EXPECT_FALSE(headers.has("x-envoy-upstream-rq-per-try-timeout-ms"));
    EXPECT_EQ("7", headers.get_("x-envoy-expected-rq-timeout-ms"));
    EXPECT_FALSE(headers.has("grpc-timeout"));
  }
  {
    NiceMock<MockRouteEntry> route;
    route.retry_policy_.per_try_timeout_ = std::chrono::milliseconds(10);
    EXPECT_CALL(route, timeout()).WillOnce(Return(std::chrono::milliseconds(0)));
    Http::TestRequestHeaderMapImpl headers;
    FilterUtility::TimeoutData timeout =
        FilterUtility::finalTimeout(route, headers, true, false, false, false);
    EXPECT_EQ(std::chrono::milliseconds(0), timeout.global_timeout_);
    EXPECT_EQ(std::chrono::milliseconds(10), timeout.per_try_timeout_);
    EXPECT_FALSE(headers.has("x-envoy-upstream-rq-timeout-ms"));
    EXPECT_FALSE(headers.has("x-envoy-upstream-rq-per-try-timeout-ms"));
    EXPECT_EQ("10", headers.get_("x-envoy-expected-rq-timeout-ms"));
    EXPECT_FALSE(headers.has("grpc-timeout"));
  }
  {
    NiceMock<MockRouteEntry> route;
    route.retry_policy_.per_try_timeout_ = std::chrono::milliseconds(7);
    EXPECT_CALL(route, timeout()).WillOnce(Return(std::chrono::milliseconds(10)));
    Http::TestRequestHeaderMapImpl headers{{"x-envoy-upstream-rq-timeout-ms", "15"},
                                           {"x-envoy-upstream-rq-per-try-timeout-ms", "5"}};
    FilterUtility::TimeoutData timeout =
        FilterUtility::finalTimeout(route, headers, true, false, false, false);
    EXPECT_EQ(std::chrono::milliseconds(15), timeout.global_timeout_);
    EXPECT_EQ(std::chrono::milliseconds(5), timeout.per_try_timeout_);
    EXPECT_FALSE(headers.has("x-envoy-upstream-rq-timeout-ms"));
    EXPECT_FALSE(headers.has("x-envoy-upstream-rq-per-try-timeout-ms"));
    EXPECT_EQ("5", headers.get_("x-envoy-expected-rq-timeout-ms"));
    EXPECT_FALSE(headers.has("grpc-timeout"));
  }
  {
    NiceMock<MockRouteEntry> route;
    EXPECT_CALL(route, maxGrpcTimeout())
        .WillRepeatedly(Return(absl::optional<std::chrono::milliseconds>(0)));
    Http::TestRequestHeaderMapImpl headers{{"content-type", "application/grpc"}};
    FilterUtility::TimeoutData timeout =
        FilterUtility::finalTimeout(route, headers, true, true, false, false);
    EXPECT_EQ(std::chrono::milliseconds(0), timeout.global_timeout_);
    EXPECT_EQ(std::chrono::milliseconds(0), timeout.per_try_timeout_);
    EXPECT_FALSE(headers.has("grpc-timeout"));
  }
  {
    NiceMock<MockRouteEntry> route;
    EXPECT_CALL(route, maxGrpcTimeout()).WillRepeatedly(Return(absl::nullopt));
    EXPECT_CALL(route, timeout()).WillOnce(Return(std::chrono::milliseconds(10)));
    Http::TestRequestHeaderMapImpl headers{{"content-type", "application/grpc"}};
    FilterUtility::TimeoutData timeout =
        FilterUtility::finalTimeout(route, headers, true, true, false, false);
    EXPECT_EQ(std::chrono::milliseconds(10), timeout.global_timeout_);
    EXPECT_EQ(std::chrono::milliseconds(0), timeout.per_try_timeout_);
    EXPECT_FALSE(headers.has("grpc-timeout"));
  }
  {
    NiceMock<MockRouteEntry> route;
    EXPECT_CALL(route, maxGrpcTimeout())
        .WillRepeatedly(Return(absl::optional<std::chrono::milliseconds>(0)));
    Http::TestRequestHeaderMapImpl headers{{"content-type", "application/grpc"},
                                           {"grpc-timeout", "1000m"}};
    FilterUtility::TimeoutData timeout =
        FilterUtility::finalTimeout(route, headers, true, true, false, false);
    EXPECT_EQ(std::chrono::milliseconds(1000), timeout.global_timeout_);
    EXPECT_EQ(std::chrono::milliseconds(0), timeout.per_try_timeout_);
    EXPECT_EQ("1000m", headers.get_("grpc-timeout"));
  }
  {
    NiceMock<MockRouteEntry> route;
    EXPECT_CALL(route, maxGrpcTimeout())
        .WillRepeatedly(Return(absl::optional<std::chrono::milliseconds>(999)));
    Http::TestRequestHeaderMapImpl headers{{"content-type", "application/grpc"},
                                           {"grpc-timeout", "1000m"}};
    FilterUtility::TimeoutData timeout =
        FilterUtility::finalTimeout(route, headers, true, true, false, false);
    EXPECT_EQ(std::chrono::milliseconds(999), timeout.global_timeout_);
    EXPECT_EQ(std::chrono::milliseconds(0), timeout.per_try_timeout_);
    EXPECT_EQ("999m", headers.get_("grpc-timeout"));
  }
  {
    NiceMock<MockRouteEntry> route;
    EXPECT_CALL(route, maxGrpcTimeout())
        .WillRepeatedly(Return(absl::optional<std::chrono::milliseconds>(999)));
    Http::TestRequestHeaderMapImpl headers{{"content-type", "application/grpc"},
                                           {"grpc-timeout", "0m"}};
    FilterUtility::TimeoutData timeout =
        FilterUtility::finalTimeout(route, headers, true, true, false, false);
    EXPECT_EQ(std::chrono::milliseconds(999), timeout.global_timeout_);
    EXPECT_EQ(std::chrono::milliseconds(0), timeout.per_try_timeout_);
    EXPECT_EQ("999m", headers.get_("grpc-timeout"));
  }
  {
    NiceMock<MockRouteEntry> route;
    EXPECT_CALL(route, maxGrpcTimeout())
        .WillRepeatedly(Return(absl::optional<std::chrono::milliseconds>(999)));
    EXPECT_CALL(route, grpcTimeoutOffset())
        .WillRepeatedly(Return(absl::optional<std::chrono::milliseconds>(10)));
    Http::TestRequestHeaderMapImpl headers{{"content-type", "application/grpc"},
                                           {"grpc-timeout", "100m"}};
    FilterUtility::TimeoutData timeout =
        FilterUtility::finalTimeout(route, headers, true, true, false, false);
    EXPECT_EQ(std::chrono::milliseconds(90), timeout.global_timeout_);
    EXPECT_EQ(std::chrono::milliseconds(0), timeout.per_try_timeout_);
  }
  {
    NiceMock<MockRouteEntry> route;
    EXPECT_CALL(route, maxGrpcTimeout())
        .WillRepeatedly(Return(absl::optional<std::chrono::milliseconds>(999)));
    EXPECT_CALL(route, grpcTimeoutOffset())
        .WillRepeatedly(Return(absl::optional<std::chrono::milliseconds>(10)));
    Http::TestRequestHeaderMapImpl headers{{"content-type", "application/grpc"},
                                           {"grpc-timeout", "1m"}};
    FilterUtility::TimeoutData timeout =
        FilterUtility::finalTimeout(route, headers, true, true, false, false);
    EXPECT_EQ(std::chrono::milliseconds(1), timeout.global_timeout_);
    EXPECT_EQ(std::chrono::milliseconds(0), timeout.per_try_timeout_);
  }
  {
    NiceMock<MockRouteEntry> route;
    EXPECT_CALL(route, maxGrpcTimeout())
        .WillRepeatedly(Return(absl::optional<std::chrono::milliseconds>(0)));
    Http::TestRequestHeaderMapImpl headers{{"content-type", "application/grpc"},
                                           {"grpc-timeout", "1000m"},
                                           {"x-envoy-upstream-rq-timeout-ms", "15"}};
    FilterUtility::TimeoutData timeout =
        FilterUtility::finalTimeout(route, headers, true, true, false, false);
    EXPECT_EQ(std::chrono::milliseconds(15), timeout.global_timeout_);
    EXPECT_EQ(std::chrono::milliseconds(0), timeout.per_try_timeout_);
    EXPECT_FALSE(headers.has("x-envoy-upstream-rq-timeout-ms"));
    EXPECT_EQ("15", headers.get_("x-envoy-expected-rq-timeout-ms"));
    EXPECT_EQ("15m", headers.get_("grpc-timeout"));
  }
  {
    NiceMock<MockRouteEntry> route;
    EXPECT_CALL(route, maxGrpcTimeout())
        .WillRepeatedly(Return(absl::optional<std::chrono::milliseconds>(0)));
    Http::TestRequestHeaderMapImpl headers{{"content-type", "application/grpc"},
                                           {"grpc-timeout", "1000m"},
                                           {"x-envoy-upstream-rq-timeout-ms", "bad"}};
    FilterUtility::TimeoutData timeout =
        FilterUtility::finalTimeout(route, headers, true, true, false, false);
    EXPECT_EQ(std::chrono::milliseconds(1000), timeout.global_timeout_);
    EXPECT_EQ(std::chrono::milliseconds(0), timeout.per_try_timeout_);
    EXPECT_FALSE(headers.has("x-envoy-upstream-rq-timeout-ms"));
    EXPECT_EQ("1000", headers.get_("x-envoy-expected-rq-timeout-ms"));
    EXPECT_EQ("1000m", headers.get_("grpc-timeout"));
  }
  {
    NiceMock<MockRouteEntry> route;
    EXPECT_CALL(route, maxGrpcTimeout())
        .WillRepeatedly(Return(absl::optional<std::chrono::milliseconds>(0)));
    Http::TestRequestHeaderMapImpl headers{{"content-type", "application/grpc"},
                                           {"grpc-timeout", "1000m"},
                                           {"x-envoy-upstream-rq-timeout-ms", "15"},
                                           {"x-envoy-upstream-rq-per-try-timeout-ms", "15"}};
    FilterUtility::TimeoutData timeout =
        FilterUtility::finalTimeout(route, headers, true, true, false, false);
    EXPECT_EQ(std::chrono::milliseconds(15), timeout.global_timeout_);
    EXPECT_EQ(std::chrono::milliseconds(0), timeout.per_try_timeout_);
    EXPECT_FALSE(headers.has("x-envoy-upstream-rq-timeout-ms"));
    EXPECT_FALSE(headers.has("x-envoy-upstream-rq-per-try-timeout-ms"));
    EXPECT_EQ("15", headers.get_("x-envoy-expected-rq-timeout-ms"));
    EXPECT_EQ("15m", headers.get_("grpc-timeout"));
  }
  {
    NiceMock<MockRouteEntry> route;
    EXPECT_CALL(route, maxGrpcTimeout())
        .WillRepeatedly(Return(absl::optional<std::chrono::milliseconds>(0)));
    Http::TestRequestHeaderMapImpl headers{{"content-type", "application/grpc"},
                                           {"grpc-timeout", "1000m"},
                                           {"x-envoy-upstream-rq-timeout-ms", "15"},
                                           {"x-envoy-upstream-rq-per-try-timeout-ms", "5"}};
    FilterUtility::TimeoutData timeout =
        FilterUtility::finalTimeout(route, headers, true, true, false, false);
    EXPECT_EQ(std::chrono::milliseconds(15), timeout.global_timeout_);
    EXPECT_EQ(std::chrono::milliseconds(5), timeout.per_try_timeout_);
    EXPECT_FALSE(headers.has("x-envoy-upstream-rq-timeout-ms"));
    EXPECT_FALSE(headers.has("x-envoy-upstream-rq-per-try-timeout-ms"));
    EXPECT_EQ("5", headers.get_("x-envoy-expected-rq-timeout-ms"));
    EXPECT_EQ("5m", headers.get_("grpc-timeout"));
  }
  {
    NiceMock<MockRouteEntry> route;
    EXPECT_CALL(route, maxGrpcTimeout())
        .WillRepeatedly(Return(absl::optional<std::chrono::milliseconds>(0)));
    route.retry_policy_.per_try_timeout_ = std::chrono::milliseconds(7);
    Http::TestRequestHeaderMapImpl headers{{"content-type", "application/grpc"},
                                           {"grpc-timeout", "1000m"},
                                           {"x-envoy-upstream-rq-timeout-ms", "15"}};
    FilterUtility::TimeoutData timeout =
        FilterUtility::finalTimeout(route, headers, true, true, false, false);
    EXPECT_EQ(std::chrono::milliseconds(15), timeout.global_timeout_);
    EXPECT_EQ(std::chrono::milliseconds(7), timeout.per_try_timeout_);
    EXPECT_FALSE(headers.has("x-envoy-upstream-rq-timeout-ms"));
    EXPECT_FALSE(headers.has("x-envoy-upstream-rq-per-try-timeout-ms"));
    EXPECT_EQ("7", headers.get_("x-envoy-expected-rq-timeout-ms"));
    EXPECT_EQ("7m", headers.get_("grpc-timeout"));
  }
  {
    NiceMock<MockRouteEntry> route;
    EXPECT_CALL(route, maxGrpcTimeout())
        .WillRepeatedly(Return(absl::optional<std::chrono::milliseconds>(0)));
    route.retry_policy_.per_try_timeout_ = std::chrono::milliseconds(7);
    Http::TestRequestHeaderMapImpl headers{{"content-type", "application/grpc"},
                                           {"grpc-timeout", "1000m"},
                                           {"x-envoy-upstream-rq-timeout-ms", "15"},
                                           {"x-envoy-upstream-rq-per-try-timeout-ms", "5"}};
    FilterUtility::TimeoutData timeout =
        FilterUtility::finalTimeout(route, headers, true, true, false, false);
    EXPECT_EQ(std::chrono::milliseconds(15), timeout.global_timeout_);
    EXPECT_EQ(std::chrono::milliseconds(5), timeout.per_try_timeout_);
    EXPECT_FALSE(headers.has("x-envoy-upstream-rq-timeout-ms"));
    EXPECT_FALSE(headers.has("x-envoy-upstream-rq-per-try-timeout-ms"));
    EXPECT_EQ("5", headers.get_("x-envoy-expected-rq-timeout-ms"));
    EXPECT_EQ("5m", headers.get_("grpc-timeout"));
  }
  {
    NiceMock<MockRouteEntry> route;
    EXPECT_CALL(route, maxGrpcTimeout())
        .WillRepeatedly(Return(absl::optional<std::chrono::milliseconds>(10000)));
    Http::TestRequestHeaderMapImpl headers{{"content-type", "application/grpc"},
                                           {"grpc-timeout", "6666666666666H"}};
    FilterUtility::finalTimeout(route, headers, true, true, false, false);
    EXPECT_EQ("10000", headers.get_("x-envoy-expected-rq-timeout-ms"));
    EXPECT_EQ("10000m", headers.get_("grpc-timeout"));
  }
  {
    NiceMock<MockRouteEntry> route;
    EXPECT_CALL(route, timeout()).WillOnce(Return(std::chrono::milliseconds(10)));
    Http::TestRequestHeaderMapImpl headers{{"x-envoy-expected-rq-timeout-ms", "8"}};
    // Make ingress envoy respect `x-envoy-expected-rq-timeout-ms` header.
    bool respect_expected_rq_timeout = true;
    FilterUtility::TimeoutData timeout = FilterUtility::finalTimeout(
        route, headers, true, false, false, respect_expected_rq_timeout);
    EXPECT_EQ(std::chrono::milliseconds(8), timeout.global_timeout_);
    EXPECT_EQ(std::chrono::milliseconds(0), timeout.per_try_timeout_);
    EXPECT_EQ("8", headers.get_("x-envoy-expected-rq-timeout-ms"));
    EXPECT_FALSE(headers.has("grpc-timeout"));
  }
  {
    NiceMock<MockRouteEntry> route;
    EXPECT_CALL(route, timeout()).WillOnce(Return(std::chrono::milliseconds(10)));
    Http::TestRequestHeaderMapImpl headers{{"x-envoy-expected-rq-timeout-ms", "8"},
                                           {"x-envoy-upstream-rq-per-try-timeout-ms", "4"}};
    // Make ingress envoy respect `x-envoy-expected-rq-timeout-ms` header.
    bool respect_expected_rq_timeout = true;
    FilterUtility::TimeoutData timeout = FilterUtility::finalTimeout(
        route, headers, true, false, false, respect_expected_rq_timeout);
    EXPECT_EQ(std::chrono::milliseconds(8), timeout.global_timeout_);
    EXPECT_EQ(std::chrono::milliseconds(4), timeout.per_try_timeout_);
    EXPECT_EQ("4", headers.get_("x-envoy-expected-rq-timeout-ms"));
    EXPECT_FALSE(headers.has("grpc-timeout"));
  }
  {
    NiceMock<MockRouteEntry> route;
    EXPECT_CALL(route, timeout()).WillOnce(Return(std::chrono::milliseconds(10)));
    Http::TestRequestHeaderMapImpl headers{{"x-envoy-upstream-rq-timeout-ms", "8"}};
    // Test that ingress envoy populates `x-envoy-expected-rq-timeout-ms` header if it has not been
    // set by egress envoy.
    bool respect_expected_rq_timeout = true;
    FilterUtility::TimeoutData timeout = FilterUtility::finalTimeout(
        route, headers, true, false, false, respect_expected_rq_timeout);
    EXPECT_EQ(std::chrono::milliseconds(8), timeout.global_timeout_);
    EXPECT_EQ(std::chrono::milliseconds(0), timeout.per_try_timeout_);
    EXPECT_FALSE(headers.has("x-envoy-upstream-rq-timeout-ms"));
    EXPECT_FALSE(headers.has("x-envoy-upstream-rq-per-try-timeout-ms"));
    EXPECT_EQ("8", headers.get_("x-envoy-expected-rq-timeout-ms"));
    EXPECT_FALSE(headers.has("grpc-timeout"));
  }
  {
    NiceMock<MockRouteEntry> route;
    EXPECT_CALL(route, timeout()).WillOnce(Return(std::chrono::milliseconds(10)));
    Http::TestRequestHeaderMapImpl headers{{"x-envoy-upstream-rq-timeout-ms", "8"}};
    // Make envoy override `x-envoy-expected-rq-timeout-ms` header.
    // Test that ingress envoy sets `x-envoy-expected-rq-timeout-ms` header.
    bool respect_expected_rq_timeout = false;
    FilterUtility::TimeoutData timeout = FilterUtility::finalTimeout(
        route, headers, true, false, false, respect_expected_rq_timeout);
    EXPECT_EQ(std::chrono::milliseconds(8), timeout.global_timeout_);
    EXPECT_EQ(std::chrono::milliseconds(0), timeout.per_try_timeout_);
    EXPECT_FALSE(headers.has("x-envoy-upstream-rq-timeout-ms"));
    EXPECT_FALSE(headers.has("x-envoy-upstream-rq-per-try-timeout-ms"));
    EXPECT_EQ("8", headers.get_("x-envoy-expected-rq-timeout-ms"));
    EXPECT_FALSE(headers.has("grpc-timeout"));
  }
}
TEST(RouterFilterUtilityTest, FinalTimeout) {
  {
    NiceMock<MockRouteEntry> route;
    EXPECT_CALL(route, timeout()).WillOnce(Return(std::chrono::milliseconds(10)));
    Http::TestRequestHeaderMapImpl headers;
    FilterUtility::TimeoutData timeout =
        FilterUtility::finalTimeout(route, headers, true, false, false, false);
    EXPECT_EQ(std::chrono::milliseconds(10), timeout.global_timeout_);
    EXPECT_EQ(std::chrono::milliseconds(0), timeout.per_try_timeout_);
  }
  {
    NiceMock<MockRouteEntry> route;
    EXPECT_CALL(route, timeout()).WillOnce(Return(std::chrono::milliseconds(10)));
    Http::TestRequestHeaderMapImpl headers{{"x-envoy-upstream-rq-timeout-ms", "15"}};
    FilterUtility::TimeoutData timeout =
        FilterUtility::finalTimeout(route, headers, true, false, false, false);
    EXPECT_EQ(std::chrono::milliseconds(15), timeout.global_timeout_);
    EXPECT_EQ(std::chrono::milliseconds(0), timeout.per_try_timeout_);
    EXPECT_FALSE(headers.has("x-envoy-upstream-rq-timeout-ms"));
    EXPECT_EQ("15", headers.get_("x-envoy-expected-rq-timeout-ms"));
    EXPECT_FALSE(headers.has("grpc-timeout"));
  }
  {
    NiceMock<MockRouteEntry> route;
    EXPECT_CALL(route, timeout()).WillOnce(Return(std::chrono::milliseconds(10)));
    Http::TestRequestHeaderMapImpl headers{{"x-envoy-upstream-rq-timeout-ms", "bad"}};
    FilterUtility::TimeoutData timeout =
        FilterUtility::finalTimeout(route, headers, true, false, false, false);
    EXPECT_EQ(std::chrono::milliseconds(10), timeout.global_timeout_);
    EXPECT_EQ(std::chrono::milliseconds(0), timeout.per_try_timeout_);
    EXPECT_FALSE(headers.has("x-envoy-upstream-rq-timeout-ms"));
    EXPECT_EQ("10", headers.get_("x-envoy-expected-rq-timeout-ms"));
    EXPECT_FALSE(headers.has("grpc-timeout"));
  }
  {
    NiceMock<MockRouteEntry> route;
    EXPECT_CALL(route, timeout()).WillOnce(Return(std::chrono::milliseconds(10)));
    Http::TestRequestHeaderMapImpl headers{{"x-envoy-upstream-rq-timeout-ms", "15"},
                                           {"x-envoy-upstream-rq-per-try-timeout-ms", "15"}};
    FilterUtility::TimeoutData timeout =
        FilterUtility::finalTimeout(route, headers, true, false, false, false);
    EXPECT_EQ(std::chrono::milliseconds(15), timeout.global_timeout_);
    EXPECT_EQ(std::chrono::milliseconds(0), timeout.per_try_timeout_);
    EXPECT_FALSE(headers.has("x-envoy-upstream-rq-timeout-ms"));
    EXPECT_FALSE(headers.has("x-envoy-upstream-rq-per-try-timeout-ms"));
    EXPECT_EQ("15", headers.get_("x-envoy-expected-rq-timeout-ms"));
    EXPECT_FALSE(headers.has("grpc-timeout"));
  }
  {
    NiceMock<MockRouteEntry> route;
    EXPECT_CALL(route, timeout()).WillOnce(Return(std::chrono::milliseconds(10)));
    Http::TestRequestHeaderMapImpl headers{{"x-envoy-upstream-rq-timeout-ms", "15"},
                                           {"x-envoy-upstream-rq-per-try-timeout-ms", "5"}};
    FilterUtility::TimeoutData timeout =
        FilterUtility::finalTimeout(route, headers, true, false, false, false);
    EXPECT_EQ(std::chrono::milliseconds(15), timeout.global_timeout_);
    EXPECT_EQ(std::chrono::milliseconds(5), timeout.per_try_timeout_);
    EXPECT_FALSE(headers.has("x-envoy-upstream-rq-timeout-ms"));
    EXPECT_FALSE(headers.has("x-envoy-upstream-rq-per-try-timeout-ms"));
    EXPECT_EQ("5", headers.get_("x-envoy-expected-rq-timeout-ms"));
    EXPECT_FALSE(headers.has("grpc-timeout"));
  }
  {
    NiceMock<MockRouteEntry> route;
    EXPECT_CALL(route, timeout()).WillOnce(Return(std::chrono::milliseconds(10)));
    Http::TestRequestHeaderMapImpl headers{{"x-envoy-upstream-rq-timeout-ms", "15"},
                                           {"x-envoy-upstream-rq-per-try-timeout-ms", "5"}};
    FilterUtility::TimeoutData timeout =
        FilterUtility::finalTimeout(route, headers, true, false, true, false);
    EXPECT_EQ(std::chrono::milliseconds(15), timeout.global_timeout_);
    EXPECT_EQ(std::chrono::milliseconds(5), timeout.per_try_timeout_);
    EXPECT_FALSE(headers.has("x-envoy-upstream-rq-timeout-ms"));
    EXPECT_FALSE(headers.has("x-envoy-upstream-rq-per-try-timeout-ms"));
    EXPECT_EQ("15", headers.get_("x-envoy-expected-rq-timeout-ms"));
    EXPECT_FALSE(headers.has("grpc-timeout"));
  }
  {
    NiceMock<MockRouteEntry> route;
    EXPECT_CALL(route, maxGrpcTimeout())
        .WillRepeatedly(Return(absl::optional<std::chrono::milliseconds>(10)));
    Http::TestRequestHeaderMapImpl headers{{"x-envoy-upstream-rq-timeout-ms", "15"},
                                           {"x-envoy-upstream-rq-per-try-timeout-ms", "5"}};
    FilterUtility::TimeoutData timeout =
        FilterUtility::finalTimeout(route, headers, true, true, true, false);
    EXPECT_EQ(std::chrono::milliseconds(15), timeout.global_timeout_);
    EXPECT_EQ(std::chrono::milliseconds(5), timeout.per_try_timeout_);
    EXPECT_FALSE(headers.has("x-envoy-upstream-rq-timeout-ms"));
    EXPECT_FALSE(headers.has("x-envoy-upstream-rq-per-try-timeout-ms"));
    EXPECT_EQ("15", headers.get_("x-envoy-expected-rq-timeout-ms"));
    EXPECT_EQ("15m", headers.get_("grpc-timeout"));
  }
  {
    NiceMock<MockRouteEntry> route;
    route.retry_policy_.per_try_timeout_ = std::chrono::milliseconds(7);
    EXPECT_CALL(route, timeout()).WillOnce(Return(std::chrono::milliseconds(10)));
    Http::TestRequestHeaderMapImpl headers{{"x-envoy-upstream-rq-timeout-ms", "15"}};
    FilterUtility::TimeoutData timeout =
        FilterUtility::finalTimeout(route, headers, true, false, false, false);
    EXPECT_EQ(std::chrono::milliseconds(15), timeout.global_timeout_);
    EXPECT_EQ(std::chrono::milliseconds(7), timeout.per_try_timeout_);
    EXPECT_FALSE(headers.has("x-envoy-upstream-rq-timeout-ms"));
    EXPECT_FALSE(headers.has("x-envoy-upstream-rq-per-try-timeout-ms"));
    EXPECT_EQ("7", headers.get_("x-envoy-expected-rq-timeout-ms"));
    EXPECT_FALSE(headers.has("grpc-timeout"));
  }
  {
    NiceMock<MockRouteEntry> route;
    route.retry_policy_.per_try_timeout_ = std::chrono::milliseconds(10);
    EXPECT_CALL(route, timeout()).WillOnce(Return(std::chrono::milliseconds(0)));
    Http::TestRequestHeaderMapImpl headers;
    FilterUtility::TimeoutData timeout =
        FilterUtility::finalTimeout(route, headers, true, false, false, false);
    EXPECT_EQ(std::chrono::milliseconds(0), timeout.global_timeout_);
    EXPECT_EQ(std::chrono::milliseconds(10), timeout.per_try_timeout_);
    EXPECT_FALSE(headers.has("x-envoy-upstream-rq-timeout-ms"));
    EXPECT_FALSE(headers.has("x-envoy-upstream-rq-per-try-timeout-ms"));
    EXPECT_EQ("10", headers.get_("x-envoy-expected-rq-timeout-ms"));
    EXPECT_FALSE(headers.has("grpc-timeout"));
  }
  {
    NiceMock<MockRouteEntry> route;
    route.retry_policy_.per_try_timeout_ = std::chrono::milliseconds(7);
    EXPECT_CALL(route, timeout()).WillOnce(Return(std::chrono::milliseconds(10)));
    Http::TestRequestHeaderMapImpl headers{{"x-envoy-upstream-rq-timeout-ms", "15"},
                                           {"x-envoy-upstream-rq-per-try-timeout-ms", "5"}};
    FilterUtility::TimeoutData timeout =
        FilterUtility::finalTimeout(route, headers, true, false, false, false);
    EXPECT_EQ(std::chrono::milliseconds(15), timeout.global_timeout_);
    EXPECT_EQ(std::chrono::milliseconds(5), timeout.per_try_timeout_);
    EXPECT_FALSE(headers.has("x-envoy-upstream-rq-timeout-ms"));
    EXPECT_FALSE(headers.has("x-envoy-upstream-rq-per-try-timeout-ms"));
    EXPECT_EQ("5", headers.get_("x-envoy-expected-rq-timeout-ms"));
    EXPECT_FALSE(headers.has("grpc-timeout"));
  }
  {
    NiceMock<MockRouteEntry> route;
    EXPECT_CALL(route, maxGrpcTimeout())
        .WillRepeatedly(Return(absl::optional<std::chrono::milliseconds>(0)));
    Http::TestRequestHeaderMapImpl headers{{"content-type", "application/grpc"}};
    FilterUtility::TimeoutData timeout =
        FilterUtility::finalTimeout(route, headers, true, true, false, false);
    EXPECT_EQ(std::chrono::milliseconds(0), timeout.global_timeout_);
    EXPECT_EQ(std::chrono::milliseconds(0), timeout.per_try_timeout_);
    EXPECT_FALSE(headers.has("grpc-timeout"));
  }
  {
    NiceMock<MockRouteEntry> route;
    EXPECT_CALL(route, maxGrpcTimeout()).WillRepeatedly(Return(absl::nullopt));
    EXPECT_CALL(route, timeout()).WillOnce(Return(std::chrono::milliseconds(10)));
    Http::TestRequestHeaderMapImpl headers{{"content-type", "application/grpc"}};
    FilterUtility::TimeoutData timeout =
        FilterUtility::finalTimeout(route, headers, true, true, false, false);
    EXPECT_EQ(std::chrono::milliseconds(10), timeout.global_timeout_);
    EXPECT_EQ(std::chrono::milliseconds(0), timeout.per_try_timeout_);
    EXPECT_FALSE(headers.has("grpc-timeout"));
  }
  {
    NiceMock<MockRouteEntry> route;
    EXPECT_CALL(route, maxGrpcTimeout())
        .WillRepeatedly(Return(absl::optional<std::chrono::milliseconds>(0)));
    Http::TestRequestHeaderMapImpl headers{{"content-type", "application/grpc"},
                                           {"grpc-timeout", "1000m"}};
    FilterUtility::TimeoutData timeout =
        FilterUtility::finalTimeout(route, headers, true, true, false, false);
    EXPECT_EQ(std::chrono::milliseconds(1000), timeout.global_timeout_);
    EXPECT_EQ(std::chrono::milliseconds(0), timeout.per_try_timeout_);
    EXPECT_EQ("1000m", headers.get_("grpc-timeout"));
  }
  {
    NiceMock<MockRouteEntry> route;
    EXPECT_CALL(route, maxGrpcTimeout())
        .WillRepeatedly(Return(absl::optional<std::chrono::milliseconds>(999)));
    Http::TestRequestHeaderMapImpl headers{{"content-type", "application/grpc"},
                                           {"grpc-timeout", "1000m"}};
    FilterUtility::TimeoutData timeout =
        FilterUtility::finalTimeout(route, headers, true, true, false, false);
    EXPECT_EQ(std::chrono::milliseconds(999), timeout.global_timeout_);
    EXPECT_EQ(std::chrono::milliseconds(0), timeout.per_try_timeout_);
    EXPECT_EQ("999m", headers.get_("grpc-timeout"));
  }
  {
    NiceMock<MockRouteEntry> route;
    EXPECT_CALL(route, maxGrpcTimeout())
        .WillRepeatedly(Return(absl::optional<std::chrono::milliseconds>(999)));
    Http::TestRequestHeaderMapImpl headers{{"content-type", "application/grpc"},
                                           {"grpc-timeout", "0m"}};
    FilterUtility::TimeoutData timeout =
        FilterUtility::finalTimeout(route, headers, true, true, false, false);
    EXPECT_EQ(std::chrono::milliseconds(999), timeout.global_timeout_);
    EXPECT_EQ(std::chrono::milliseconds(0), timeout.per_try_timeout_);
    EXPECT_EQ("999m", headers.get_("grpc-timeout"));
  }
  {
    NiceMock<MockRouteEntry> route;
    EXPECT_CALL(route, maxGrpcTimeout())
        .WillRepeatedly(Return(absl::optional<std::chrono::milliseconds>(999)));
    EXPECT_CALL(route, grpcTimeoutOffset())
        .WillRepeatedly(Return(absl::optional<std::chrono::milliseconds>(10)));
    Http::TestRequestHeaderMapImpl headers{{"content-type", "application/grpc"},
                                           {"grpc-timeout", "100m"}};
    FilterUtility::TimeoutData timeout =
        FilterUtility::finalTimeout(route, headers, true, true, false, false);
    EXPECT_EQ(std::chrono::milliseconds(90), timeout.global_timeout_);
    EXPECT_EQ(std::chrono::milliseconds(0), timeout.per_try_timeout_);
  }
  {
    NiceMock<MockRouteEntry> route;
    EXPECT_CALL(route, maxGrpcTimeout())
        .WillRepeatedly(Return(absl::optional<std::chrono::milliseconds>(999)));
    EXPECT_CALL(route, grpcTimeoutOffset())
        .WillRepeatedly(Return(absl::optional<std::chrono::milliseconds>(10)));
    Http::TestRequestHeaderMapImpl headers{{"content-type", "application/grpc"},
                                           {"grpc-timeout", "1m"}};
    FilterUtility::TimeoutData timeout =
        FilterUtility::finalTimeout(route, headers, true, true, false, false);
    EXPECT_EQ(std::chrono::milliseconds(1), timeout.global_timeout_);
    EXPECT_EQ(std::chrono::milliseconds(0), timeout.per_try_timeout_);
  }
  {
    NiceMock<MockRouteEntry> route;
    EXPECT_CALL(route, maxGrpcTimeout())
        .WillRepeatedly(Return(absl::optional<std::chrono::milliseconds>(0)));
    Http::TestRequestHeaderMapImpl headers{{"content-type", "application/grpc"},
                                           {"grpc-timeout", "1000m"},
                                           {"x-envoy-upstream-rq-timeout-ms", "15"}};
    FilterUtility::TimeoutData timeout =
        FilterUtility::finalTimeout(route, headers, true, true, false, false);
    EXPECT_EQ(std::chrono::milliseconds(15), timeout.global_timeout_);
    EXPECT_EQ(std::chrono::milliseconds(0), timeout.per_try_timeout_);
    EXPECT_FALSE(headers.has("x-envoy-upstream-rq-timeout-ms"));
    EXPECT_EQ("15", headers.get_("x-envoy-expected-rq-timeout-ms"));
    EXPECT_EQ("15m", headers.get_("grpc-timeout"));
  }
  {
    NiceMock<MockRouteEntry> route;
    EXPECT_CALL(route, maxGrpcTimeout())
        .WillRepeatedly(Return(absl::optional<std::chrono::milliseconds>(0)));
    Http::TestRequestHeaderMapImpl headers{{"content-type", "application/grpc"},
                                           {"grpc-timeout", "1000m"},
                                           {"x-envoy-upstream-rq-timeout-ms", "bad"}};
    FilterUtility::TimeoutData timeout =
        FilterUtility::finalTimeout(route, headers, true, true, false, false);
    EXPECT_EQ(std::chrono::milliseconds(1000), timeout.global_timeout_);
    EXPECT_EQ(std::chrono::milliseconds(0), timeout.per_try_timeout_);
    EXPECT_FALSE(headers.has("x-envoy-upstream-rq-timeout-ms"));
    EXPECT_EQ("1000", headers.get_("x-envoy-expected-rq-timeout-ms"));
    EXPECT_EQ("1000m", headers.get_("grpc-timeout"));
  }
  {
    NiceMock<MockRouteEntry> route;
    EXPECT_CALL(route, maxGrpcTimeout())
        .WillRepeatedly(Return(absl::optional<std::chrono::milliseconds>(0)));
    Http::TestRequestHeaderMapImpl headers{{"content-type", "application/grpc"},
                                           {"grpc-timeout", "1000m"},
                                           {"x-envoy-upstream-rq-timeout-ms", "15"},
                                           {"x-envoy-upstream-rq-per-try-timeout-ms", "15"}};
    FilterUtility::TimeoutData timeout =
        FilterUtility::finalTimeout(route, headers, true, true, false, false);
    EXPECT_EQ(std::chrono::milliseconds(15), timeout.global_timeout_);
    EXPECT_EQ(std::chrono::milliseconds(0), timeout.per_try_timeout_);
    EXPECT_FALSE(headers.has("x-envoy-upstream-rq-timeout-ms"));
    EXPECT_FALSE(headers.has("x-envoy-upstream-rq-per-try-timeout-ms"));
    EXPECT_EQ("15", headers.get_("x-envoy-expected-rq-timeout-ms"));
    EXPECT_EQ("15m", headers.get_("grpc-timeout"));
  }
  {
    NiceMock<MockRouteEntry> route;
    EXPECT_CALL(route, maxGrpcTimeout())
        .WillRepeatedly(Return(absl::optional<std::chrono::milliseconds>(0)));
    Http::TestRequestHeaderMapImpl headers{{"content-type", "application/grpc"},
                                           {"grpc-timeout", "1000m"},
                                           {"x-envoy-upstream-rq-timeout-ms", "15"},
                                           {"x-envoy-upstream-rq-per-try-timeout-ms", "5"}};
    FilterUtility::TimeoutData timeout =
        FilterUtility::finalTimeout(route, headers, true, true, false, false);
    EXPECT_EQ(std::chrono::milliseconds(15), timeout.global_timeout_);
    EXPECT_EQ(std::chrono::milliseconds(5), timeout.per_try_timeout_);
    EXPECT_FALSE(headers.has("x-envoy-upstream-rq-timeout-ms"));
    EXPECT_FALSE(headers.has("x-envoy-upstream-rq-per-try-timeout-ms"));
    EXPECT_EQ("5", headers.get_("x-envoy-expected-rq-timeout-ms"));
    EXPECT_EQ("5m", headers.get_("grpc-timeout"));
  }
  {
    NiceMock<MockRouteEntry> route;
    EXPECT_CALL(route, maxGrpcTimeout())
        .WillRepeatedly(Return(absl::optional<std::chrono::milliseconds>(0)));
    route.retry_policy_.per_try_timeout_ = std::chrono::milliseconds(7);
    Http::TestRequestHeaderMapImpl headers{{"content-type", "application/grpc"},
                                           {"grpc-timeout", "1000m"},
                                           {"x-envoy-upstream-rq-timeout-ms", "15"}};
    FilterUtility::TimeoutData timeout =
        FilterUtility::finalTimeout(route, headers, true, true, false, false);
    EXPECT_EQ(std::chrono::milliseconds(15), timeout.global_timeout_);
    EXPECT_EQ(std::chrono::milliseconds(7), timeout.per_try_timeout_);
    EXPECT_FALSE(headers.has("x-envoy-upstream-rq-timeout-ms"));
    EXPECT_FALSE(headers.has("x-envoy-upstream-rq-per-try-timeout-ms"));
    EXPECT_EQ("7", headers.get_("x-envoy-expected-rq-timeout-ms"));
    EXPECT_EQ("7m", headers.get_("grpc-timeout"));
  }
  {
    NiceMock<MockRouteEntry> route;
    EXPECT_CALL(route, maxGrpcTimeout())
        .WillRepeatedly(Return(absl::optional<std::chrono::milliseconds>(0)));
    route.retry_policy_.per_try_timeout_ = std::chrono::milliseconds(7);
    Http::TestRequestHeaderMapImpl headers{{"content-type", "application/grpc"},
                                           {"grpc-timeout", "1000m"},
                                           {"x-envoy-upstream-rq-timeout-ms", "15"},
                                           {"x-envoy-upstream-rq-per-try-timeout-ms", "5"}};
    FilterUtility::TimeoutData timeout =
        FilterUtility::finalTimeout(route, headers, true, true, false, false);
    EXPECT_EQ(std::chrono::milliseconds(15), timeout.global_timeout_);
    EXPECT_EQ(std::chrono::milliseconds(5), timeout.per_try_timeout_);
    EXPECT_FALSE(headers.has("x-envoy-upstream-rq-timeout-ms"));
    EXPECT_FALSE(headers.has("x-envoy-upstream-rq-per-try-timeout-ms"));
    EXPECT_EQ("5", headers.get_("x-envoy-expected-rq-timeout-ms"));
    EXPECT_EQ("5m", headers.get_("grpc-timeout"));
  }
  {
    NiceMock<MockRouteEntry> route;
    EXPECT_CALL(route, maxGrpcTimeout())
        .WillRepeatedly(Return(absl::optional<std::chrono::milliseconds>(10000)));
    Http::TestRequestHeaderMapImpl headers{{"content-type", "application/grpc"},
                                           {"grpc-timeout", "6666666666666H"}};
    FilterUtility::finalTimeout(route, headers, true, true, false, false);
    EXPECT_EQ("10000", headers.get_("x-envoy-expected-rq-timeout-ms"));
    EXPECT_EQ("10000m", headers.get_("grpc-timeout"));
  }
  {
    NiceMock<MockRouteEntry> route;
    EXPECT_CALL(route, timeout()).WillOnce(Return(std::chrono::milliseconds(10)));
    Http::TestRequestHeaderMapImpl headers{{"x-envoy-expected-rq-timeout-ms", "8"}};
     
    bool respect_expected_rq_timeout = true;
    FilterUtility::TimeoutData timeout = FilterUtility::finalTimeout(
        route, headers, true, false, false, respect_expected_rq_timeout);
    EXPECT_EQ(std::chrono::milliseconds(8), timeout.global_timeout_);
    EXPECT_EQ(std::chrono::milliseconds(0), timeout.per_try_timeout_);
    EXPECT_EQ("8", headers.get_("x-envoy-expected-rq-timeout-ms"));
    EXPECT_FALSE(headers.has("grpc-timeout"));
  }
  {
    NiceMock<MockRouteEntry> route;
    EXPECT_CALL(route, timeout()).WillOnce(Return(std::chrono::milliseconds(10)));
    Http::TestRequestHeaderMapImpl headers{{"x-envoy-expected-rq-timeout-ms", "8"},
                                           {"x-envoy-upstream-rq-per-try-timeout-ms", "4"}};
     
    bool respect_expected_rq_timeout = true;
    FilterUtility::TimeoutData timeout = FilterUtility::finalTimeout(
        route, headers, true, false, false, respect_expected_rq_timeout);
    EXPECT_EQ(std::chrono::milliseconds(8), timeout.global_timeout_);
    EXPECT_EQ(std::chrono::milliseconds(4), timeout.per_try_timeout_);
    EXPECT_EQ("4", headers.get_("x-envoy-expected-rq-timeout-ms"));
    EXPECT_FALSE(headers.has("grpc-timeout"));
  }
  {
    NiceMock<MockRouteEntry> route;
    EXPECT_CALL(route, timeout()).WillOnce(Return(std::chrono::milliseconds(10)));
    Http::TestRequestHeaderMapImpl headers{{"x-envoy-upstream-rq-timeout-ms", "8"}};
     
     
    bool respect_expected_rq_timeout = true;
    FilterUtility::TimeoutData timeout = FilterUtility::finalTimeout(
        route, headers, true, false, false, respect_expected_rq_timeout);
    EXPECT_EQ(std::chrono::milliseconds(8), timeout.global_timeout_);
    EXPECT_EQ(std::chrono::milliseconds(0), timeout.per_try_timeout_);
    EXPECT_FALSE(headers.has("x-envoy-upstream-rq-timeout-ms"));
    EXPECT_FALSE(headers.has("x-envoy-upstream-rq-per-try-timeout-ms"));
    EXPECT_EQ("8", headers.get_("x-envoy-expected-rq-timeout-ms"));
    EXPECT_FALSE(headers.has("grpc-timeout"));
  }
  {
    NiceMock<MockRouteEntry> route;
    EXPECT_CALL(route, timeout()).WillOnce(Return(std::chrono::milliseconds(10)));
    Http::TestRequestHeaderMapImpl headers{{"x-envoy-upstream-rq-timeout-ms", "8"}};
     
     
    bool respect_expected_rq_timeout = false;
    FilterUtility::TimeoutData timeout = FilterUtility::finalTimeout(
        route, headers, true, false, false, respect_expected_rq_timeout);
    EXPECT_EQ(std::chrono::milliseconds(8), timeout.global_timeout_);
    EXPECT_EQ(std::chrono::milliseconds(0), timeout.per_try_timeout_);
    EXPECT_FALSE(headers.has("x-envoy-upstream-rq-timeout-ms"));
    EXPECT_FALSE(headers.has("x-envoy-upstream-rq-per-try-timeout-ms"));
    EXPECT_EQ("8", headers.get_("x-envoy-expected-rq-timeout-ms"));
    EXPECT_FALSE(headers.has("grpc-timeout"));
  }
}