1 //
2 // Copyright 2017 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 <stddef.h>
18
19 #include <algorithm>
20 #include <functional>
21 #include <memory>
22 #include <string>
23 #include <thread>
24 #include <vector>
25
26 #include "absl/strings/str_format.h"
27 #include "gtest/gtest.h"
28
29 #include <grpc/grpc.h>
30 #include <grpcpp/channel.h>
31 #include <grpcpp/create_channel.h>
32 #include <grpcpp/security/credentials.h>
33 #include <grpcpp/support/channel_arguments.h>
34
35 #include "src/core/lib/gprpp/env.h"
36 #include "test/core/util/fake_udp_and_tcp_server.h"
37 #include "test/core/util/port.h"
38 #include "test/core/util/test_config.h"
39
40 namespace {
41
TryConnectAndDestroy(const char * fake_metadata_server_address)42 void TryConnectAndDestroy(const char* fake_metadata_server_address) {
43 grpc::ChannelArguments args;
44 std::string target = "google-c2p:///servername_not_used";
45 args.SetInt("grpc.testing.google_c2p_resolver_pretend_running_on_gcp", 1);
46 args.SetString("grpc.testing.google_c2p_resolver_metadata_server_override",
47 fake_metadata_server_address);
48 auto channel = grpc::CreateCustomChannel(
49 target, grpc::InsecureChannelCredentials(), args);
50 // Start connecting, and give some time for the google-c2p resolver to begin
51 // resolution and start trying to contact the metadata server.
52 channel->GetState(true /* try_to_connect */);
53 ASSERT_FALSE(
54 channel->WaitForConnected(grpc_timeout_milliseconds_to_deadline(100)));
55 channel.reset();
56 };
57
58 // Exercise the machinery involved with shutting down the C2P resolver while
59 // it's waiting for its initial metadata server queries to finish.
TEST(DestroyGoogleC2pChannelWithActiveConnectStressTest,LoopTryConnectAndDestroyWithHangingMetadataServer)60 TEST(DestroyGoogleC2pChannelWithActiveConnectStressTest,
61 LoopTryConnectAndDestroyWithHangingMetadataServer) {
62 // Create a fake metadata server which hangs.
63 grpc_core::testing::FakeUdpAndTcpServer fake_metadata_server(
64 grpc_core::testing::FakeUdpAndTcpServer::AcceptMode::
65 kWaitForClientToSendFirstBytes,
66 grpc_core::testing::FakeUdpAndTcpServer::CloseSocketUponCloseFromPeer);
67 std::vector<std::unique_ptr<std::thread>> threads;
68 const int kNumThreads = 10;
69 threads.reserve(kNumThreads);
70 for (int i = 0; i < kNumThreads; i++) {
71 threads.emplace_back(
72 new std::thread(TryConnectAndDestroy, fake_metadata_server.address()));
73 }
74 for (size_t i = 0; i < threads.size(); i++) {
75 threads[i]->join();
76 }
77 }
78
79 // Exercise the machinery involved with shutting down the C2P resolver while
80 // it's waiting for its initial metadata server queries to finish.
TEST(DestroyGoogleC2pChannelWithActiveConnectStressTest,LoopTryConnectAndDestroyWithFastFailingMetadataServer)81 TEST(DestroyGoogleC2pChannelWithActiveConnectStressTest,
82 LoopTryConnectAndDestroyWithFastFailingMetadataServer) {
83 // Create a fake metadata server address which rejects connections
84 int port = grpc_pick_unused_port_or_die();
85 std::string address = absl::StrFormat("[::1]:%d", port);
86 std::vector<std::unique_ptr<std::thread>> threads;
87 const int kNumThreads = 10;
88 threads.reserve(kNumThreads);
89 for (int i = 0; i < kNumThreads; i++) {
90 threads.emplace_back(
91 new std::thread(TryConnectAndDestroy, address.c_str()));
92 }
93 for (size_t i = 0; i < threads.size(); i++) {
94 threads[i]->join();
95 }
96 }
97
98 } // namespace
99
main(int argc,char ** argv)100 int main(int argc, char** argv) {
101 grpc::testing::TestEnvironment env(&argc, argv);
102 ::testing::InitGoogleTest(&argc, argv);
103 grpc_init();
104 int result;
105 {
106 grpc_core::testing::FakeUdpAndTcpServer fake_xds_server(
107 grpc_core::testing::FakeUdpAndTcpServer::AcceptMode::
108 kWaitForClientToSendFirstBytes,
109 grpc_core::testing::FakeUdpAndTcpServer::
110 CloseSocketUponReceivingBytesFromPeer);
111 grpc_core::SetEnv("GRPC_TEST_ONLY_GOOGLE_C2P_RESOLVER_TRAFFIC_DIRECTOR_URI",
112 fake_xds_server.address());
113 result = RUN_ALL_TESTS();
114 }
115 grpc_shutdown();
116 return result;
117 }
118