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