Repository: envoyproxy/envoy
File: test/integration/ads_integration_test.cc (C++)

Code before:

  sendDiscoveryResponse<envoy::config::route::v3::VirtualHost>(
      Config::TestTypeUrl::get().VirtualHost, {},
      {buildVirtualHost("route_config_0/foo", "foo.com", "/foo", "cluster_0"),
       buildVirtualHost("route_config_0/bar", "bar.com", "/bar", "cluster_0"),
       buildVirtualHost("route_config_1/foo", "foo.com", "/foo", "cluster_1")},
      {}, "1");

  test_server_->waitForCounterGe("listener_manager.listener_create_success", 2);

  auto foo_request_headers = Http::TestRequestHeaderMapImpl{
      {":method", "GET"}, {":path", "/foo"}, {":scheme", "http"}, {":authority", "foo.com"}};
  auto bar_request_headers = Http::TestRequestHeaderMapImpl{
      {":method", "GET"}, {":path", "/bar"}, {":scheme", "http"}, {":authority", "bar.com"}};
  registerTestServerPorts({"http0", "http1", "http2"});

  auto send_request_and_verify = [this](const std::string& port_name,
                                        const Http::TestRequestHeaderMapImpl& headers,
                                        bool verify_404 = false) {
    codec_client_ = makeHttpConnection(makeClientConnection((lookupPort(port_name))));
    if (verify_404) {
      auto response = codec_client_->makeHeaderOnlyRequest(headers);
      ASSERT_TRUE(response->waitForEndStream());
      EXPECT_EQ("404", response->headers().getStatusValue());
    } else {
      auto response = sendRequestAndWaitForResponse(headers, 0, default_response_headers_, 0, 0);
      checkSimpleRequestSuccess(0U, 0U, response.get());
    }
    cleanupUpstreamAndDownstream();
  };

  // Verify all vhosts across all listeners are correctly configured.
  send_request_and_verify("http0", foo_request_headers);
  send_request_and_verify("http0", bar_request_headers);
  send_request_and_verify("http1", foo_request_headers);
  send_request_and_verify("http2", foo_request_headers);
  send_request_and_verify("http2", bar_request_headers);

  // Verify that removing listener_0 doesn't impact listener_2 that also references
  // route_config_0/foo and route_config_0/bar.
  sendDiscoveryResponse<envoy::config::listener::v3::Listener>(Config::TestTypeUrl::get().Listener,
                                                               {}, {}, {"listener_0"}, "1");
  send_request_and_verify("http2", foo_request_headers);
  send_request_and_verify("http2", bar_request_headers);

  // Verify that removing route_config_0/foo makes foo.com unreachable but bar.com is still
  // reachable from listener_2.
  sendDiscoveryResponse<envoy::config::route::v3::VirtualHost>(
      Config::TestTypeUrl::get().VirtualHost, {}, {}, {"route_config_0/foo"}, "1");
  send_request_and_verify("http2", foo_request_headers, true);
  send_request_and_verify("http2", bar_request_headers);

Review comment (suggestion):
FWIW, if there's no longer wildcard VHDS then there shouldn't be a difference between delta/SotW.
No need to change anything in this case, just highlighting this.

Code after:
  sendDiscoveryResponse<envoy::config::route::v3::RouteConfiguration>(
      Config::TestTypeUrl::get().RouteConfiguration,
      {buildRouteConfig("route_config_0", "replaced_cluster")},
      {buildRouteConfig("route_config_0", "replaced_cluster")}, {}, "replaced1", {},
      second_xds_stream_.get());
  EXPECT_TRUE(compareDiscoveryRequest(Config::TestTypeUrl::get().Listener, "replaced1", {}, {}, {},
                                      false, Grpc::Status::WellKnownGrpcStatus::Ok, "",
                                      second_xds_stream_.get()));
  EXPECT_TRUE(compareDiscoveryRequest(
      Config::TestTypeUrl::get().RouteConfiguration, "replaced1", {"route_config_0"}, {}, {}, false,
      Grpc::Status::WellKnownGrpcStatus::Ok, "", second_xds_stream_.get()));

  makeSingleRequest();
}

// Tests the following scenarios:
// - Multiple VHDS resources for the same route can be sent over ADS.
// - Removal of one listener doesn't impact another that references the same vhost over the same
// route config.
// - Removal of one vhost doesn't impact another vhost in the same route config.
// - Removal of a vhost from one route config doesn't impact the same vhost in another route config.
TEST_P(AdsIntegrationTest, MultipleVhdsOverAds) {
  if (sotw_or_delta_ != Grpc::SotwOrDelta::Delta &&
      sotw_or_delta_ != Grpc::SotwOrDelta::UnifiedDelta) {
    GTEST_SKIP_("This test is for delta only");
  }
  initialize();

  // Send initial configuration that sets up 3 listeners with the following vhosts:
  // listener_0 -> route_config_0/foo
  // listener_0 -> route_config_0/bar
  // listener_1 -> route_config_0/foo
  // listener_1 -> route_config_0/bar
  // listener_2 -> route_config_1/foo
  EXPECT_TRUE(compareDiscoveryRequest(Config::TestTypeUrl::get().Cluster, "", {}, {}, {}, true));
  sendDiscoveryResponse<envoy::config::cluster::v3::Cluster>(Config::TestTypeUrl::get().Cluster, {},
                                                             {
                                                                 buildCluster("cluster_0"),
                                                                 buildCluster("cluster_1"),
                                                             },
                                                             {}, "1");
  EXPECT_TRUE(compareDiscoveryRequest(Config::TestTypeUrl::get().ClusterLoadAssignment, "", {},
                                      {"cluster_0", "cluster_1"}, {}));
  sendDiscoveryResponse<envoy::config::endpoint::v3::ClusterLoadAssignment>(
      Config::TestTypeUrl::get().ClusterLoadAssignment, {},
      {buildClusterLoadAssignment("cluster_0"), buildClusterLoadAssignment("cluster_1")}, {}, "1");
  EXPECT_TRUE(compareDiscoveryRequest(Config::TestTypeUrl::get().Cluster, "", {}, {}, {}));

  EXPECT_TRUE(compareDiscoveryRequest(Config::TestTypeUrl::get().Listener, "", {}, {}, {}));
  sendDiscoveryResponse<envoy::config::listener::v3::Listener>(
      Config::TestTypeUrl::get().Listener, {},