1 //
2 //
3 // Copyright 2016 gRPC authors.
4 //
5 // Licensed under the Apache License, Version 2.0 (the "License");
6 // you may not use this file except in compliance with the License.
7 // You may obtain a copy of the License at
8 //
9 // http://www.apache.org/licenses/LICENSE-2.0
10 //
11 // Unless required by applicable law or agreed to in writing, software
12 // distributed under the License is distributed on an "AS IS" BASIS,
13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 // See the License for the specific language governing permissions and
15 // limitations under the License.
16 //
17 //
18
19 /// \file Verify that status ordering rules are obeyed.
20 /// \ref doc/status_ordering.md
21
22 #include <memory>
23
24 #include "gtest/gtest.h"
25
26 #include <grpc/status.h>
27
28 #include "src/core/lib/gprpp/time.h"
29 #include "test/core/end2end/end2end_tests.h"
30
31 namespace grpc_core {
32 namespace {
33
34 // Client sends a request with payload, potentially requesting status early. The
35 // server reads and streams responses. The client cancels the RPC to get an
36 // error status. (Server sending a non-OK status is not considered an error
37 // status.)
CORE_END2END_TEST(CoreEnd2endTest,StreamingErrorResponse)38 CORE_END2END_TEST(CoreEnd2endTest, StreamingErrorResponse) {
39 SKIP_IF_CHAOTIC_GOOD();
40 auto c = NewClientCall("/foo").Timeout(Duration::Seconds(5)).Create();
41 CoreEnd2endTest::IncomingMetadata server_initial_metadata;
42 CoreEnd2endTest::IncomingMessage response_payload1_recv;
43 c.NewBatch(1)
44 .SendInitialMetadata({})
45 .SendCloseFromClient()
46 .RecvInitialMetadata(server_initial_metadata)
47 .RecvMessage(response_payload1_recv);
48 auto s = RequestCall(101);
49 Expect(101, true);
50 Step();
51 s.NewBatch(102).SendInitialMetadata({}).SendMessage("hello");
52 Expect(102, true);
53 Expect(1, true);
54 Step();
55 s.NewBatch(103).SendMessage("world");
56 // The success of the op depends on whether the payload is written before the
57 // transport sees the end of stream. If the stream has been write closed
58 // before the write completes, it would fail, otherwise it would succeed.
59 // Since this behavior is dependent on the transport implementation, we allow
60 // any success status with this op.
61 Expect(103, AnyStatus());
62 CoreEnd2endTest::IncomingMessage response_payload2_recv;
63 c.NewBatch(2).RecvMessage(response_payload2_recv);
64 Expect(2, true);
65 Step();
66 EXPECT_FALSE(response_payload2_recv.is_end_of_stream());
67 // Cancel the call so that the client sets up an error status.
68 c.Cancel();
69 CoreEnd2endTest::IncomingCloseOnServer client_close;
70 s.NewBatch(104).RecvCloseOnServer(client_close);
71 Expect(104, true);
72 Step();
73 CoreEnd2endTest::IncomingStatusOnClient server_status;
74 c.NewBatch(3).RecvStatusOnClient(server_status);
75 Expect(3, true);
76 Step();
77 EXPECT_FALSE(response_payload1_recv.is_end_of_stream());
78 EXPECT_FALSE(response_payload2_recv.is_end_of_stream());
79 EXPECT_EQ(server_status.status(), GRPC_STATUS_CANCELLED);
80 EXPECT_TRUE(client_close.was_cancelled());
81 }
82
CORE_END2END_TEST(CoreEnd2endTest,StreamingErrorResponseRequestStatusEarly)83 CORE_END2END_TEST(CoreEnd2endTest, StreamingErrorResponseRequestStatusEarly) {
84 SKIP_IF_CHAOTIC_GOOD();
85 auto c = NewClientCall("/foo").Timeout(Duration::Seconds(5)).Create();
86 CoreEnd2endTest::IncomingMetadata server_initial_metadata;
87 CoreEnd2endTest::IncomingMessage response_payload1_recv;
88 CoreEnd2endTest::IncomingStatusOnClient server_status;
89 c.NewBatch(1)
90 .SendInitialMetadata({})
91 .SendCloseFromClient()
92 .RecvInitialMetadata(server_initial_metadata)
93 .RecvMessage(response_payload1_recv)
94 .RecvStatusOnClient(server_status);
95 auto s = RequestCall(101);
96 Expect(101, true);
97 Step();
98 s.NewBatch(102).SendInitialMetadata({}).SendMessage("hello");
99 Expect(102, true);
100 Step();
101 s.NewBatch(103).SendMessage("world");
102 // The success of the op depends on whether the payload is written before the
103 // transport sees the end of stream. If the stream has been write closed
104 // before the write completes, it would fail, otherwise it would succeed.
105 // Since this behavior is dependent on the transport implementation, we allow
106 // any success status with this op.
107 Expect(103, AnyStatus());
108 // Cancel the call so that the client sets up an error status.
109 c.Cancel();
110 CoreEnd2endTest::IncomingCloseOnServer client_close;
111 s.NewBatch(104).RecvCloseOnServer(client_close);
112 Expect(104, true);
113 Expect(1, true);
114 Step();
115 EXPECT_EQ(server_status.status(), GRPC_STATUS_CANCELLED);
116 EXPECT_TRUE(client_close.was_cancelled());
117 }
118
CORE_END2END_TEST(CoreEnd2endTest,StreamingErrorResponseRequestStatusEarlyAndRecvMessageSeparately)119 CORE_END2END_TEST(
120 CoreEnd2endTest,
121 StreamingErrorResponseRequestStatusEarlyAndRecvMessageSeparately) {
122 SKIP_IF_CHAOTIC_GOOD();
123 auto c = NewClientCall("/foo").Timeout(Duration::Seconds(5)).Create();
124 CoreEnd2endTest::IncomingMetadata server_initial_metadata;
125 CoreEnd2endTest::IncomingStatusOnClient server_status;
126 c.NewBatch(1)
127 .SendInitialMetadata({})
128 .SendCloseFromClient()
129 .RecvInitialMetadata(server_initial_metadata)
130 .RecvStatusOnClient(server_status);
131 auto s = RequestCall(101);
132 Expect(101, true);
133 Step();
134 s.NewBatch(102).SendInitialMetadata({}).SendMessage("hello");
135 CoreEnd2endTest::IncomingMessage response_payload1_recv;
136 c.NewBatch(4).RecvMessage(response_payload1_recv);
137 Expect(102, true);
138 Expect(4, true);
139 Step();
140 s.NewBatch(103).SendMessage("world");
141 // The success of the op depends on whether the payload is written before the
142 // transport sees the end of stream. If the stream has been write closed
143 // before the write completes, it would fail, otherwise it would succeed.
144 // Since this behavior is dependent on the transport implementation, we allow
145 // any success status with this op.
146 Expect(103, AnyStatus());
147 // Cancel the call so that the client sets up an error status.
148 c.Cancel();
149 CoreEnd2endTest::IncomingCloseOnServer client_close;
150 s.NewBatch(104).RecvCloseOnServer(client_close);
151 Expect(104, true);
152 Expect(1, true);
153 Step();
154 EXPECT_EQ(server_status.status(), GRPC_STATUS_CANCELLED);
155 EXPECT_TRUE(client_close.was_cancelled());
156 }
157
158 } // namespace
159 } // namespace grpc_core
160