• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // Copyright 2024 gRPC authors.
3 //
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 //     http://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 //
16 
17 #include <gmock/gmock.h>
18 #include <gtest/gtest.h>
19 
20 #include <string>
21 #include <vector>
22 
23 #include "absl/log/log.h"
24 #include "absl/strings/str_cat.h"
25 #include "absl/strings/str_format.h"
26 #include "envoy/config/core/v3/address.pb.h"
27 #include "envoy/extensions/transport_sockets/http_11_proxy/v3/upstream_http_11_connect.pb.h"
28 #include "src/core/client_channel/backup_poller.h"
29 #include "src/core/config/config_vars.h"
30 #include "test/core/end2end/fixtures/http_proxy_fixture.h"
31 #include "test/core/test_util/resolve_localhost_ip46.h"
32 #include "test/core/test_util/scoped_env_var.h"
33 #include "test/cpp/end2end/xds/xds_end2end_test_lib.h"
34 
35 namespace grpc {
36 namespace testing {
37 namespace {
38 
39 using envoy::extensions::transport_sockets::http_11_proxy::v3::
40     Http11ProxyUpstreamTransport;
41 
42 class XdsHttpProxyTest : public XdsEnd2endTest {
43  protected:
SetUp()44   void SetUp() override {
45     http_proxy_ = grpc_end2end_http_proxy_create(nullptr);
46     XdsEnd2endTest::SetUp();
47   }
48 
TearDown()49   void TearDown() override {
50     XdsEnd2endTest::TearDown();
51     grpc_end2end_http_proxy_destroy(http_proxy_);
52   }
53 
54   grpc_end2end_http_proxy* http_proxy_;
55 };
56 
57 INSTANTIATE_TEST_SUITE_P(XdsTest, XdsHttpProxyTest,
58                          ::testing::Values(XdsTestType()), &XdsTestType::Name);
59 
TEST_P(XdsHttpProxyTest,TransportProxyInClusterAndProxyAddressInEndpoint)60 TEST_P(XdsHttpProxyTest, TransportProxyInClusterAndProxyAddressInEndpoint) {
61   grpc_core::testing::ScopedExperimentalEnvVar env(
62       "GRPC_EXPERIMENTAL_XDS_HTTP_CONNECT");
63   CreateAndStartBackends(1);
64   // Set transport socket in CDS.
65   Cluster cluster = default_cluster_;
66   cluster.mutable_transport_socket()->mutable_typed_config()->PackFrom(
67       Http11ProxyUpstreamTransport());
68   balancer_->ads_service()->SetCdsResource(cluster);
69   // Set proxy address in EDS metadata.
70   ClusterLoadAssignment endpoints = BuildEdsResource(
71       EdsResourceArgs({{"locality0", CreateEndpointsForBackends()}}));
72   envoy::config::core::v3::Address proxy_address_proto;
73   auto* socket_address = proxy_address_proto.mutable_socket_address();
74   socket_address->set_address(grpc_core::LocalIp());
75   socket_address->set_port_value(
76       grpc_end2end_http_proxy_get_proxy_port(http_proxy_));
77   auto& metadata_map = *endpoints.mutable_endpoints(0)
78                             ->mutable_lb_endpoints(0)
79                             ->mutable_metadata()
80                             ->mutable_typed_filter_metadata();
81   metadata_map["envoy.http11_proxy_transport_socket.proxy_address"].PackFrom(
82       proxy_address_proto);
83   balancer_->ads_service()->SetEdsResource(endpoints);
84   // Everything should work.
85   CheckRpcSendOk(DEBUG_LOCATION);
86   // Proxy should have seen one connection.
87   EXPECT_EQ(grpc_end2end_http_proxy_num_connections(http_proxy_), 1);
88 }
89 
TEST_P(XdsHttpProxyTest,TransportProxyInClusterButNoProxyAddressInEndpoint)90 TEST_P(XdsHttpProxyTest, TransportProxyInClusterButNoProxyAddressInEndpoint) {
91   grpc_core::testing::ScopedExperimentalEnvVar env(
92       "GRPC_EXPERIMENTAL_XDS_HTTP_CONNECT");
93   CreateAndStartBackends(1);
94   // Set transport socket in CDS.
95   Cluster cluster = default_cluster_;
96   cluster.mutable_transport_socket()->mutable_typed_config()->PackFrom(
97       Http11ProxyUpstreamTransport());
98   balancer_->ads_service()->SetCdsResource(cluster);
99   // Set proxy address in EDS metadata.
100   ClusterLoadAssignment endpoints = BuildEdsResource(
101       EdsResourceArgs({{"locality0", CreateEndpointsForBackends()}}));
102   balancer_->ads_service()->SetEdsResource(endpoints);
103   // Everything should work.
104   CheckRpcSendOk(DEBUG_LOCATION);
105   // Proxy should not have seen any connections.
106   EXPECT_EQ(grpc_end2end_http_proxy_num_connections(http_proxy_), 0);
107 }
108 
TEST_P(XdsHttpProxyTest,ProxyAddressInEndpointButNoTransportProxyInCluster)109 TEST_P(XdsHttpProxyTest, ProxyAddressInEndpointButNoTransportProxyInCluster) {
110   grpc_core::testing::ScopedExperimentalEnvVar env(
111       "GRPC_EXPERIMENTAL_XDS_HTTP_CONNECT");
112   CreateAndStartBackends(1);
113   // Set proxy address in EDS metadata.
114   ClusterLoadAssignment endpoints = BuildEdsResource(
115       EdsResourceArgs({{"locality0", CreateEndpointsForBackends()}}));
116   envoy::config::core::v3::Address proxy_address_proto;
117   auto* socket_address = proxy_address_proto.mutable_socket_address();
118   socket_address->set_address(grpc_core::LocalIp());
119   socket_address->set_port_value(
120       grpc_end2end_http_proxy_get_proxy_port(http_proxy_));
121   auto& metadata_map = *endpoints.mutable_endpoints(0)
122                             ->mutable_lb_endpoints(0)
123                             ->mutable_metadata()
124                             ->mutable_typed_filter_metadata();
125   metadata_map["envoy.http11_proxy_transport_socket.proxy_address"].PackFrom(
126       proxy_address_proto);
127   balancer_->ads_service()->SetEdsResource(endpoints);
128   // Everything should work.
129   CheckRpcSendOk(DEBUG_LOCATION);
130   // Proxy should not have seen any connections.
131   EXPECT_EQ(grpc_end2end_http_proxy_num_connections(http_proxy_), 0);
132 }
133 
TEST_P(XdsHttpProxyTest,CdsNackedWhenNotEnabled)134 TEST_P(XdsHttpProxyTest, CdsNackedWhenNotEnabled) {
135   // Set transport socket in CDS.
136   Cluster cluster = default_cluster_;
137   cluster.mutable_transport_socket()->mutable_typed_config()->PackFrom(
138       Http11ProxyUpstreamTransport());
139   balancer_->ads_service()->SetCdsResource(cluster);
140   // Wait for NACK.
141   const auto response_state = WaitForCdsNack(DEBUG_LOCATION);
142   ASSERT_TRUE(response_state.has_value()) << "timed out waiting for NACK";
143   EXPECT_EQ(response_state->error_message,
144             "xDS response validation errors: ["
145             "resource index 0: cluster_name: "
146             "INVALID_ARGUMENT: errors validating Cluster resource: ["
147             "field:transport_socket.typed_config.value["
148             "envoy.extensions.transport_sockets.http_11_proxy.v3"
149             ".Http11ProxyUpstreamTransport].type_url "
150             "error:unsupported transport socket type]]");
151 }
152 
153 }  // namespace
154 }  // namespace testing
155 }  // namespace grpc
156 
main(int argc,char ** argv)157 int main(int argc, char** argv) {
158   grpc::testing::TestEnvironment env(&argc, argv);
159   ::testing::InitGoogleTest(&argc, argv);
160   // Make the backup poller poll very frequently in order to pick up
161   // updates from all the subchannels's FDs.
162   grpc_core::ConfigVars::Overrides overrides;
163   overrides.client_channel_backup_poll_interval_ms = 1;
164   grpc_core::ConfigVars::SetOverrides(overrides);
165 #if TARGET_OS_IPHONE
166   // Workaround Apple CFStream bug
167   grpc_core::SetEnv("grpc_cfstream", "0");
168 #endif
169   grpc_init();
170   const auto result = RUN_ALL_TESTS();
171   grpc_shutdown();
172   return result;
173 }
174