1 // Copyright 2023 gRPC authors.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 #include <memory>
16
17 #include "gtest/gtest.h"
18
19 #include <grpc/grpc.h>
20 #include <grpc/impl/channel_arg_names.h>
21 #include <grpc/slice.h>
22
23 #include "src/core/ext/transport/chttp2/transport/chttp2_transport.h"
24 #include "src/core/ext/transport/chttp2/transport/internal.h"
25 #include "src/core/ext/transport/chttp2/transport/legacy_frame.h"
26 #include "src/core/ext/transport/chttp2/transport/ping_abuse_policy.h"
27 #include "src/core/ext/transport/chttp2/transport/ping_rate_policy.h"
28 #include "src/core/lib/channel/channel_args.h"
29 #include "src/core/lib/event_engine/default_event_engine.h"
30 #include "src/core/lib/experiments/config.h"
31 #include "src/core/lib/gprpp/time.h"
32 #include "src/core/lib/iomgr/endpoint.h"
33 #include "src/core/lib/iomgr/exec_ctx.h"
34 #include "src/core/lib/resource_quota/resource_quota.h"
35 #include "test/core/util/mock_endpoint.h"
36 #include "test/core/util/test_config.h"
37
38 namespace grpc_core {
39 namespace {
40
41 class ConfigurationTest : public ::testing::Test {
42 protected:
ConfigurationTest()43 ConfigurationTest() {
44 mock_endpoint_ = grpc_mock_endpoint_create(DiscardWrite);
45 grpc_mock_endpoint_finish_put_reads(mock_endpoint_);
46 args_ = args_.SetObject(ResourceQuota::Default());
47 args_ = args_.SetObject(
48 grpc_event_engine::experimental::GetDefaultEventEngine());
49 }
50
51 grpc_endpoint* mock_endpoint_ = nullptr;
52 ChannelArgs args_;
53
54 private:
DiscardWrite(grpc_slice)55 static void DiscardWrite(grpc_slice /*slice*/) {}
56 };
57
TEST_F(ConfigurationTest,ClientKeepaliveDefaults)58 TEST_F(ConfigurationTest, ClientKeepaliveDefaults) {
59 ExecCtx exec_ctx;
60 grpc_chttp2_transport* t = reinterpret_cast<grpc_chttp2_transport*>(
61 grpc_create_chttp2_transport(args_, mock_endpoint_, /*is_client=*/true));
62 EXPECT_EQ(t->keepalive_time, Duration::Infinity());
63 EXPECT_EQ(t->keepalive_timeout, Duration::Infinity());
64 EXPECT_EQ(t->keepalive_permit_without_calls, false);
65 EXPECT_EQ(t->ping_rate_policy.TestOnlyMaxPingsWithoutData(), 2);
66 t->Orphan();
67 }
68
TEST_F(ConfigurationTest,ClientKeepaliveExplicitArgs)69 TEST_F(ConfigurationTest, ClientKeepaliveExplicitArgs) {
70 ExecCtx exec_ctx;
71 args_ = args_.Set(GRPC_ARG_KEEPALIVE_TIME_MS, 20000);
72 args_ = args_.Set(GRPC_ARG_KEEPALIVE_TIMEOUT_MS, 10000);
73 args_ = args_.Set(GRPC_ARG_KEEPALIVE_PERMIT_WITHOUT_CALLS, true);
74 args_ = args_.Set(GRPC_ARG_HTTP2_MAX_PINGS_WITHOUT_DATA, 3);
75 grpc_chttp2_transport* t = reinterpret_cast<grpc_chttp2_transport*>(
76 grpc_create_chttp2_transport(args_, mock_endpoint_, /*is_client=*/true));
77 EXPECT_EQ(t->keepalive_time, Duration::Seconds(20));
78 EXPECT_EQ(t->keepalive_timeout, Duration::Seconds(10));
79 EXPECT_EQ(t->keepalive_permit_without_calls, true);
80 EXPECT_EQ(t->ping_rate_policy.TestOnlyMaxPingsWithoutData(), 3);
81 t->Orphan();
82 }
83
TEST_F(ConfigurationTest,ServerKeepaliveDefaults)84 TEST_F(ConfigurationTest, ServerKeepaliveDefaults) {
85 ExecCtx exec_ctx;
86 grpc_chttp2_transport* t = reinterpret_cast<grpc_chttp2_transport*>(
87 grpc_create_chttp2_transport(args_, mock_endpoint_, /*is_client=*/false));
88 EXPECT_EQ(t->keepalive_time, Duration::Hours(2));
89 EXPECT_EQ(t->keepalive_timeout, Duration::Seconds(20));
90 EXPECT_EQ(t->keepalive_permit_without_calls, false);
91 // Server never limits based on number of pings without data.
92 EXPECT_EQ(t->ping_rate_policy.TestOnlyMaxPingsWithoutData(), 0);
93 EXPECT_EQ(t->ping_abuse_policy.TestOnlyMinPingIntervalWithoutData(),
94 Duration::Minutes(5));
95 EXPECT_EQ(t->ping_abuse_policy.TestOnlyMaxPingStrikes(), 2);
96 t->Orphan();
97 }
98
TEST_F(ConfigurationTest,ServerKeepaliveExplicitArgs)99 TEST_F(ConfigurationTest, ServerKeepaliveExplicitArgs) {
100 ExecCtx exec_ctx;
101 args_ = args_.Set(GRPC_ARG_KEEPALIVE_TIME_MS, 20000);
102 args_ = args_.Set(GRPC_ARG_KEEPALIVE_TIMEOUT_MS, 10000);
103 args_ = args_.Set(GRPC_ARG_KEEPALIVE_PERMIT_WITHOUT_CALLS, true);
104 args_ = args_.Set(GRPC_ARG_HTTP2_MAX_PINGS_WITHOUT_DATA, 3);
105 args_ =
106 args_.Set(GRPC_ARG_HTTP2_MIN_RECV_PING_INTERVAL_WITHOUT_DATA_MS, 20000);
107 args_ = args_.Set(GRPC_ARG_HTTP2_MAX_PING_STRIKES, 0);
108 grpc_chttp2_transport* t = reinterpret_cast<grpc_chttp2_transport*>(
109 grpc_create_chttp2_transport(args_, mock_endpoint_, /*is_client=*/false));
110 EXPECT_EQ(t->keepalive_time, Duration::Seconds(20));
111 EXPECT_EQ(t->keepalive_timeout, Duration::Seconds(10));
112 EXPECT_EQ(t->keepalive_permit_without_calls, true);
113 // Server never limits based on number of pings without data.
114 EXPECT_EQ(t->ping_rate_policy.TestOnlyMaxPingsWithoutData(), 0);
115 EXPECT_EQ(t->ping_abuse_policy.TestOnlyMinPingIntervalWithoutData(),
116 Duration::Seconds(20));
117 EXPECT_EQ(t->ping_abuse_policy.TestOnlyMaxPingStrikes(), 0);
118 t->Orphan();
119 }
120
121 // This test modifies the defaults of the client side settings, so it would
122 // affect any test that is run after this.
123 // TODO(yashykt): If adding more client side tests after this, add a reset to
124 // defaults function.
TEST_F(ConfigurationTest,ModifyClientDefaults)125 TEST_F(ConfigurationTest, ModifyClientDefaults) {
126 ExecCtx exec_ctx;
127 // Note that we are creating a new args object to override the defaults.
128 ChannelArgs args = args_.Set(GRPC_ARG_KEEPALIVE_TIME_MS, 20000);
129 args = args.Set(GRPC_ARG_KEEPALIVE_TIMEOUT_MS, 10000);
130 args = args.Set(GRPC_ARG_KEEPALIVE_PERMIT_WITHOUT_CALLS, true);
131 args = args.Set(GRPC_ARG_HTTP2_MAX_PINGS_WITHOUT_DATA, 3);
132 grpc_chttp2_config_default_keepalive_args(args, /*is_client=*/true);
133 // Note that we are using the original args_ object for creating the transport
134 // which does not override the defaults.
135 grpc_chttp2_transport* t = reinterpret_cast<grpc_chttp2_transport*>(
136 grpc_create_chttp2_transport(args_, mock_endpoint_, /*is_client=*/true));
137 EXPECT_EQ(t->keepalive_time, Duration::Seconds(20));
138 EXPECT_EQ(t->keepalive_timeout, Duration::Seconds(10));
139 EXPECT_EQ(t->keepalive_permit_without_calls, true);
140 EXPECT_EQ(t->ping_rate_policy.TestOnlyMaxPingsWithoutData(), 3);
141 t->Orphan();
142 }
143
144 // This test modifies the defaults of the client side settings, so it would
145 // affect any test that is run after this.
146 // TODO(yashykt): If adding more server side tests after this, add a reset to
147 // defaults function.
TEST_F(ConfigurationTest,ModifyServerDefaults)148 TEST_F(ConfigurationTest, ModifyServerDefaults) {
149 ExecCtx exec_ctx;
150 // Note that we are creating a new args object to override the defaults.
151 ChannelArgs args = args_.Set(GRPC_ARG_KEEPALIVE_TIME_MS, 20000);
152 args = args.Set(GRPC_ARG_KEEPALIVE_TIMEOUT_MS, 10000);
153 args = args.Set(GRPC_ARG_KEEPALIVE_PERMIT_WITHOUT_CALLS, true);
154 args = args.Set(GRPC_ARG_HTTP2_MAX_PINGS_WITHOUT_DATA, 3);
155 args = args.Set(GRPC_ARG_HTTP2_MIN_RECV_PING_INTERVAL_WITHOUT_DATA_MS, 20000);
156 args = args.Set(GRPC_ARG_HTTP2_MAX_PING_STRIKES, 0);
157 grpc_chttp2_config_default_keepalive_args(args, /*is_client=*/false);
158 // Note that we are using the original args_ object for creating the transport
159 // which does not override the defaults.
160 grpc_chttp2_transport* t = reinterpret_cast<grpc_chttp2_transport*>(
161 grpc_create_chttp2_transport(args_, mock_endpoint_, /*is_client=*/false));
162 EXPECT_EQ(t->keepalive_time, Duration::Seconds(20));
163 EXPECT_EQ(t->keepalive_timeout, Duration::Seconds(10));
164 EXPECT_EQ(t->keepalive_permit_without_calls, true);
165 // Server never limits based on number of pings without data.
166 EXPECT_EQ(t->ping_rate_policy.TestOnlyMaxPingsWithoutData(), 0);
167 EXPECT_EQ(t->ping_abuse_policy.TestOnlyMinPingIntervalWithoutData(),
168 Duration::Seconds(20));
169 EXPECT_EQ(t->ping_abuse_policy.TestOnlyMaxPingStrikes(), 0);
170 t->Orphan();
171 }
172
173 } // namespace
174 } // namespace grpc_core
175
main(int argc,char ** argv)176 int main(int argc, char** argv) {
177 ::testing::InitGoogleTest(&argc, argv);
178 grpc::testing::TestEnvironment env(&argc, argv);
179 grpc_core::ForceEnableExperiment("keepalive_fix", true);
180 grpc_core::ForceEnableExperiment("keepalive_server_fix", true);
181 grpc_init();
182 auto ret = RUN_ALL_TESTS();
183 grpc_shutdown();
184 return ret;
185 }
186