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 <memory>
18
19 #include "absl/strings/str_format.h"
20 #include "absl/types/optional.h"
21 #include "gtest/gtest.h"
22
23 #include <grpc/impl/channel_arg_names.h>
24 #include <grpc/status.h>
25
26 #include "src/core/lib/channel/channel_args.h"
27 #include "src/core/lib/gprpp/time.h"
28 #include "test/core/end2end/end2end_tests.h"
29 #include "test/core/util/test_config.h"
30
31 namespace grpc_core {
32 namespace {
33
34 // Tests perAttemptRecvTimeout:
35 // - 2 retries allowed for ABORTED status
36 // - first attempt does not receive a response until after perAttemptRecvTimeout
37 // - second attempt returns ABORTED
38 // - third attempt returns OK
CORE_END2END_TEST(RetryTest,RetryPerAttemptRecvTimeout)39 CORE_END2END_TEST(RetryTest, RetryPerAttemptRecvTimeout) {
40 InitServer(ChannelArgs());
41 InitClient(
42 ChannelArgs()
43 .Set(GRPC_ARG_EXPERIMENTAL_ENABLE_HEDGING, true)
44 .Set(
45 GRPC_ARG_SERVICE_CONFIG,
46 absl::StrFormat(
47 "{\n"
48 " \"methodConfig\": [ {\n"
49 " \"name\": [\n"
50 " { \"service\": \"service\", \"method\": \"method\" }\n"
51 " ],\n"
52 " \"retryPolicy\": {\n"
53 " \"maxAttempts\": 3,\n"
54 " \"initialBackoff\": \"1s\",\n"
55 " \"maxBackoff\": \"120s\",\n"
56 " \"backoffMultiplier\": 1.6,\n"
57 " \"perAttemptRecvTimeout\": \"%ds\",\n"
58 " \"retryableStatusCodes\": [ \"ABORTED\" ]\n"
59 " }\n"
60 " } ]\n"
61 "}",
62 2 * grpc_test_slowdown_factor())));
63 auto c =
64 NewClientCall("/service/method").Timeout(Duration::Seconds(10)).Create();
65 IncomingMessage server_message;
66 IncomingMetadata server_initial_metadata;
67 IncomingStatusOnClient server_status;
68 c.NewBatch(1)
69 .SendInitialMetadata({})
70 .SendMessage("foo")
71 .RecvMessage(server_message)
72 .SendCloseFromClient()
73 .RecvInitialMetadata(server_initial_metadata)
74 .RecvStatusOnClient(server_status);
75 // Server gets a call but does not respond to the call.
76 absl::optional<IncomingCall> s0 = RequestCall(101);
77 Expect(101, true);
78 Step();
79 // Make sure the "grpc-previous-rpc-attempts" header was not sent in the
80 // initial attempt.
81 EXPECT_EQ(s0->GetInitialMetadata("grpc-previous-rpc-attempts"),
82 absl::nullopt);
83 // Server gets a second call.
84 absl::optional<IncomingCall> s1 = RequestCall(201);
85 Expect(201, true);
86 Step();
87 // Now we can unref the first call.
88 s0.reset();
89 // Make sure the "grpc-previous-rpc-attempts" header was sent in the retry.
90 EXPECT_EQ(s1->GetInitialMetadata("grpc-previous-rpc-attempts"), "1");
91 EXPECT_NE(s1->GetPeer(), absl::nullopt);
92 EXPECT_NE(c.GetPeer(), absl::nullopt);
93 // Server sends status ABORTED.
94 IncomingCloseOnServer client_close1;
95 s1->NewBatch(202)
96 .SendInitialMetadata({})
97 .SendStatusFromServer(GRPC_STATUS_ABORTED, "xyz", {})
98 .RecvCloseOnServer(client_close1);
99 Expect(202, true);
100 Step();
101 s1.reset();
102 // Server gets a third call.
103 auto s2 = RequestCall(301);
104 Expect(301, true);
105 Step();
106 // Make sure the "grpc-previous-rpc-attempts" header was sent in the retry.
107 EXPECT_EQ(s2.GetInitialMetadata("grpc-previous-rpc-attempts"), "2");
108 IncomingMessage client_message2;
109 s2.NewBatch(302).RecvMessage(client_message2);
110 // Server sends OK status.
111 IncomingCloseOnServer client_close2;
112 s2.NewBatch(303)
113 .SendInitialMetadata({})
114 .SendMessage("bar")
115 .SendStatusFromServer(GRPC_STATUS_OK, "xyz", {})
116 .RecvCloseOnServer(client_close2);
117 Expect(302, true);
118 Expect(303, true);
119 Expect(1, true);
120 Step();
121 EXPECT_EQ(server_status.status(), GRPC_STATUS_OK);
122 EXPECT_EQ(server_status.message(), "xyz");
123 EXPECT_EQ(s2.method(), "/service/method");
124 EXPECT_FALSE(client_close2.was_cancelled());
125 }
126 } // namespace
127 } // namespace grpc_core
128