TEST_F(HttpConnectionManagerImplTest, DelegatingRouteEntryAllCalls) {
  setup(false, "");
  setupFilterChain(2, 0);

  // Cluster mock: foo
  // For when decoder_filters_[0] invokes setRoute
  const std::string foo_cluster_name = "foo";
  std::shared_ptr<Upstream::MockThreadLocalCluster> foo_cluster =
      std::make_shared<NiceMock<Upstream::MockThreadLocalCluster>>();
  EXPECT_CALL(cluster_manager_, getThreadLocalCluster(absl::string_view{foo_cluster_name}))
      .Times(1)
      .WillRepeatedly(Return(foo_cluster.get()));

  // Cluster mock: default
  // For decoder_filters_[0] invokes decodeHeaders and subsequently refreshCachedRoute
  const std::string default_cluster_name = "default";
  std::shared_ptr<Upstream::MockThreadLocalCluster> default_cluster =
      std::make_shared<NiceMock<Upstream::MockThreadLocalCluster>>();
  EXPECT_CALL(cluster_manager_, getThreadLocalCluster(absl::string_view{default_cluster_name}))
      .Times(1)
      .WillRepeatedly(Return(default_cluster.get()));

  // Route mock: default
  // For when decoder_filters_[0] invokes decodeHeaders and subsequently refreshCachedRoute
  std::shared_ptr<Router::MockRoute> default_route =
      std::make_shared<NiceMock<Router::MockRoute>>();
  EXPECT_CALL(*route_config_provider_.route_config_, route(_, _, _, _))
      .Times(1)
      .WillRepeatedly(Return(default_route));
  EXPECT_CALL(default_route->route_entry_, clusterName())
      .Times(1)
      .WillRepeatedly(ReturnRef(default_cluster_name));

  // DelegatingRoute: foo
  std::shared_ptr<const Router::ExampleDerivedDelegatingRoute> delegating_route_foo(nullptr);

  EXPECT_CALL(*decoder_filters_[0], decodeHeaders(_, true))
      .WillOnce(InvokeWithoutArgs([&]() -> FilterHeadersStatus {
        // Instantiate a DelegatingRoute child class object and invoke setRoute from
        // StreamFilterCallbacks to manually override the cached route for the current request.
        delegating_route_foo = std::make_shared<Router::ExampleDerivedDelegatingRoute>(
            default_route, foo_cluster_name);
        decoder_filters_[0]->callbacks_->setRoute(delegating_route_foo);

        return FilterHeadersStatus::Continue;
      }));
  EXPECT_CALL(*decoder_filters_[0], decodeComplete());

  EXPECT_CALL(*decoder_filters_[1], decodeHeaders(_, true))
      .WillOnce(InvokeWithoutArgs([&]() -> FilterHeadersStatus {
        // Check that cached_route was correctly set to the delegating route.
        EXPECT_EQ(delegating_route_foo, decoder_filters_[1]->callbacks_->route());

        // Check that delegating route correctly overrides the routeEntry()->clusterName()
        EXPECT_EQ(foo_cluster_name, delegating_route_foo->routeEntry()->clusterName());

        // Check that all other routeEntry calls are delegated correctly
        EXPECT_EQ(default_route->routeEntry()->clusterNotFoundResponseCode(),
                  delegating_route_foo->routeEntry()->clusterNotFoundResponseCode());
        EXPECT_EQ(default_route->routeEntry()->corsPolicy(),
                  delegating_route_foo->routeEntry()->corsPolicy());

        auto test_req_headers = Http::TestRequestHeaderMapImpl{{":authority", "www.choice.com"},
                                                               {":path", "/new_endpoint/foo"},
                                                               {":method", "GET"},
                                                               {"x-forwarded-proto", "http"}};
        EXPECT_EQ(default_route->routeEntry()->currentUrlPathAfterRewrite(test_req_headers),
                  delegating_route_foo->routeEntry()->currentUrlPathAfterRewrite(test_req_headers));

        EXPECT_EQ(default_route->routeEntry()->hashPolicy(),
                  delegating_route_foo->routeEntry()->hashPolicy());

        // HedgePolicy objects don't have valid comparison operator, so compare 2 attributes at
        // random. Will apply this strategy for all objects that don't have a valid comparison
        // operator (next example being RetryPolicy).
        EXPECT_EQ(default_route->routeEntry()->hedgePolicy().additionalRequestChance().numerator(),
                  delegating_route_foo->routeEntry()
                      ->hedgePolicy()
                      .additionalRequestChance()
                      .numerator());
        EXPECT_EQ(default_route->routeEntry()->hedgePolicy().initialRequests(),
                  delegating_route_foo->routeEntry()->hedgePolicy().initialRequests());

        EXPECT_EQ(default_route->routeEntry()->priority(),
                  delegating_route_foo->routeEntry()->priority());

        EXPECT_EQ(default_route->routeEntry()->rateLimitPolicy().empty(),
                  delegating_route_foo->routeEntry()->rateLimitPolicy().empty());
        EXPECT_EQ(default_route->routeEntry()->rateLimitPolicy().getApplicableRateLimit(0).empty(),
                  delegating_route_foo->routeEntry()
                      ->rateLimitPolicy()
                      .getApplicableRateLimit(0)
                      .empty());

        EXPECT_EQ(default_route->routeEntry()->retryPolicy().numRetries(),
                  delegating_route_foo->routeEntry()->retryPolicy().numRetries());
        EXPECT_EQ(default_route->routeEntry()->retryPolicy().retryOn(),
                  delegating_route_foo->routeEntry()->retryPolicy().retryOn());

        EXPECT_EQ(default_route->routeEntry()->internalRedirectPolicy().enabled(),
                  delegating_route_foo->routeEntry()->internalRedirectPolicy().enabled());
        EXPECT_EQ(
            default_route->routeEntry()->internalRedirectPolicy().shouldRedirectForResponseCode(
                Code::OK),
            delegating_route_foo->routeEntry()
                ->internalRedirectPolicy()
                .shouldRedirectForResponseCode(Code::OK));

        EXPECT_EQ(default_route->routeEntry()->retryShadowBufferLimit(),
                  delegating_route_foo->routeEntry()->retryShadowBufferLimit());
        EXPECT_EQ(default_route->routeEntry()->shadowPolicies().empty(),
                  delegating_route_foo->routeEntry()->shadowPolicies().empty());
        EXPECT_EQ(default_route->routeEntry()->timeout(),
                  delegating_route_foo->routeEntry()->timeout());
        EXPECT_EQ(default_route->routeEntry()->idleTimeout(),
                  delegating_route_foo->routeEntry()->idleTimeout());
        EXPECT_EQ(default_route->routeEntry()->usingNewTimeouts(),
                  delegating_route_foo->routeEntry()->usingNewTimeouts());
        EXPECT_EQ(default_route->routeEntry()->maxStreamDuration(),
                  delegating_route_foo->routeEntry()->maxStreamDuration());
        EXPECT_EQ(default_route->routeEntry()->grpcTimeoutHeaderMax(),
                  delegating_route_foo->routeEntry()->grpcTimeoutHeaderMax());
        EXPECT_EQ(default_route->routeEntry()->grpcTimeoutHeaderOffset(),
                  delegating_route_foo->routeEntry()->grpcTimeoutHeaderOffset());
        EXPECT_EQ(default_route->routeEntry()->maxGrpcTimeout(),
                  delegating_route_foo->routeEntry()->maxGrpcTimeout());
        EXPECT_EQ(default_route->routeEntry()->grpcTimeoutOffset(),
                  delegating_route_foo->routeEntry()->grpcTimeoutOffset());
        EXPECT_EQ(default_route->routeEntry()->virtualCluster(test_req_headers),
                  delegating_route_foo->routeEntry()->virtualCluster(test_req_headers));

        EXPECT_EQ(default_route->routeEntry()->virtualHost().corsPolicy(),
                  delegating_route_foo->routeEntry()->virtualHost().corsPolicy());
        EXPECT_EQ(default_route->routeEntry()->virtualHost().rateLimitPolicy().empty(),
                  delegating_route_foo->routeEntry()->virtualHost().rateLimitPolicy().empty());

        EXPECT_EQ(default_route->routeEntry()->autoHostRewrite(),
                  delegating_route_foo->routeEntry()->autoHostRewrite());
        EXPECT_EQ(default_route->routeEntry()->metadataMatchCriteria(),
                  delegating_route_foo->routeEntry()->metadataMatchCriteria());
        EXPECT_EQ(default_route->routeEntry()->opaqueConfig(),
                  delegating_route_foo->routeEntry()->opaqueConfig());
        EXPECT_EQ(default_route->routeEntry()->includeVirtualHostRateLimits(),
                  delegating_route_foo->routeEntry()->includeVirtualHostRateLimits());

        // NOTE: no coverage for routeEntry()->typedMetadata()
        // "The mock function has no default action set, and its return type has no default value
        // set"

        EXPECT_EQ(default_route->routeEntry()->metadata().filter_metadata().size(),
                  delegating_route_foo->routeEntry()->metadata().filter_metadata().size());
        EXPECT_EQ(default_route->routeEntry()->tlsContextMatchCriteria(),
                  delegating_route_foo->routeEntry()->tlsContextMatchCriteria());

        EXPECT_EQ(default_route->routeEntry()->pathMatchCriterion().matcher(),
                  delegating_route_foo->routeEntry()->pathMatchCriterion().matcher());
        EXPECT_EQ(default_route->routeEntry()->pathMatchCriterion().matchType(),
                  delegating_route_foo->routeEntry()->pathMatchCriterion().matchType());

        EXPECT_EQ(default_route->routeEntry()->perFilterConfig("bar"),
                  delegating_route_foo->routeEntry()->perFilterConfig("bar"));
        EXPECT_EQ(default_route->routeEntry()->includeAttemptCountInRequest(),
                  delegating_route_foo->routeEntry()->includeAttemptCountInRequest());
        EXPECT_EQ(default_route->routeEntry()->includeAttemptCountInResponse(),
                  delegating_route_foo->routeEntry()->includeAttemptCountInResponse());
        EXPECT_EQ(default_route->routeEntry()->upgradeMap(),
                  delegating_route_foo->routeEntry()->upgradeMap());

        EXPECT_EQ(default_route->routeEntry()->connectConfig().has_value(),
                  delegating_route_foo->routeEntry()->connectConfig().has_value());
        if (default_route->routeEntry()->connectConfig().has_value()) {
          EXPECT_EQ(default_route->routeEntry()->connectConfig().value().allow_post(),
                    delegating_route_foo->routeEntry()->connectConfig().value().allow_post());
        }

        EXPECT_EQ(default_route->routeEntry()->routeName(),
                  delegating_route_foo->routeEntry()->routeName());

        // Coverage for finalizeRequestHeaders
        NiceMock<Envoy::StreamInfo::MockStreamInfo> stream_info;
        delegating_route_foo->routeEntry()->finalizeRequestHeaders(test_req_headers, stream_info,
                                                                   true);
        EXPECT_EQ("/new_endpoint/foo", test_req_headers.get_(Http::Headers::get().Path));

        // Coverage for finalizeResponseHeaders
        Http::TestResponseHeaderMapImpl test_resp_headers;
        delegating_route_foo->routeEntry()->finalizeResponseHeaders(test_resp_headers, stream_info);
        EXPECT_EQ(test_resp_headers, Http::TestResponseHeaderMapImpl{});

        return FilterHeadersStatus::StopIteration;
      }));
  EXPECT_CALL(*decoder_filters_[1], decodeComplete());

  // Kick off the incoming data. end_stream set to true to indicate this is a header only request.
  startRequest(true);

  // Clean up.
  expectOnDestroy();
  filter_callbacks_.connection_.raiseEvent(Network::ConnectionEvent::RemoteClose);
}