1 //
2 //
3 // Copyright 2015 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 #include "src/core/lib/transport/connectivity_state.h"
20
21 #include "gtest/gtest.h"
22
23 #include <grpc/grpc.h>
24
25 #include "test/core/util/test_config.h"
26 #include "test/core/util/tracer_util.h"
27
28 namespace grpc_core {
29 namespace {
30
TEST(ConnectivityStateName,Basic)31 TEST(ConnectivityStateName, Basic) {
32 EXPECT_STREQ("IDLE", ConnectivityStateName(GRPC_CHANNEL_IDLE));
33 EXPECT_STREQ("CONNECTING", ConnectivityStateName(GRPC_CHANNEL_CONNECTING));
34 EXPECT_STREQ("READY", ConnectivityStateName(GRPC_CHANNEL_READY));
35 EXPECT_STREQ("TRANSIENT_FAILURE",
36 ConnectivityStateName(GRPC_CHANNEL_TRANSIENT_FAILURE));
37 EXPECT_STREQ("SHUTDOWN", ConnectivityStateName(GRPC_CHANNEL_SHUTDOWN));
38 }
39
40 class Watcher : public ConnectivityStateWatcherInterface {
41 public:
Watcher(int * count,grpc_connectivity_state * output,absl::Status * status,bool * destroyed=nullptr)42 Watcher(int* count, grpc_connectivity_state* output, absl::Status* status,
43 bool* destroyed = nullptr)
44 : count_(count),
45 output_(output),
46 status_(status),
47 destroyed_(destroyed) {}
48
~Watcher()49 ~Watcher() override {
50 if (destroyed_ != nullptr) *destroyed_ = true;
51 }
52
Notify(grpc_connectivity_state new_state,const absl::Status & status)53 void Notify(grpc_connectivity_state new_state,
54 const absl::Status& status) override {
55 ++*count_;
56 *output_ = new_state;
57 *status_ = status;
58 }
59
60 private:
61 int* count_;
62 grpc_connectivity_state* output_;
63 absl::Status* status_;
64 bool* destroyed_;
65 };
66
TEST(StateTracker,SetAndGetState)67 TEST(StateTracker, SetAndGetState) {
68 ConnectivityStateTracker tracker("xxx", GRPC_CHANNEL_CONNECTING,
69 absl::Status());
70 EXPECT_EQ(tracker.state(), GRPC_CHANNEL_CONNECTING);
71 EXPECT_TRUE(tracker.status().ok());
72 tracker.SetState(GRPC_CHANNEL_READY, absl::Status(), "whee");
73 EXPECT_EQ(tracker.state(), GRPC_CHANNEL_READY);
74 EXPECT_TRUE(tracker.status().ok());
75 absl::Status transient_failure_status(absl::StatusCode::kUnavailable,
76 "status for testing");
77 tracker.SetState(GRPC_CHANNEL_TRANSIENT_FAILURE, transient_failure_status,
78 "reason");
79 EXPECT_EQ(tracker.state(), GRPC_CHANNEL_TRANSIENT_FAILURE);
80 EXPECT_EQ(tracker.status(), transient_failure_status);
81 }
82
TEST(StateTracker,NotificationUponAddingWatcher)83 TEST(StateTracker, NotificationUponAddingWatcher) {
84 int count = 0;
85 grpc_connectivity_state state = GRPC_CHANNEL_IDLE;
86 absl::Status status;
87 ConnectivityStateTracker tracker("xxx", GRPC_CHANNEL_CONNECTING);
88 tracker.AddWatcher(GRPC_CHANNEL_IDLE,
89 MakeOrphanable<Watcher>(&count, &state, &status));
90 EXPECT_EQ(count, 1);
91 EXPECT_EQ(state, GRPC_CHANNEL_CONNECTING);
92 EXPECT_TRUE(status.ok());
93 }
94
TEST(StateTracker,NotificationUponAddingWatcherWithTransientFailure)95 TEST(StateTracker, NotificationUponAddingWatcherWithTransientFailure) {
96 int count = 0;
97 grpc_connectivity_state state = GRPC_CHANNEL_IDLE;
98 absl::Status status;
99 absl::Status transient_failure_status(absl::StatusCode::kUnavailable,
100 "status for testing");
101 ConnectivityStateTracker tracker("xxx", GRPC_CHANNEL_TRANSIENT_FAILURE,
102 transient_failure_status);
103 tracker.AddWatcher(GRPC_CHANNEL_IDLE,
104 MakeOrphanable<Watcher>(&count, &state, &status));
105 EXPECT_EQ(count, 1);
106 EXPECT_EQ(state, GRPC_CHANNEL_TRANSIENT_FAILURE);
107 EXPECT_EQ(status, transient_failure_status);
108 }
109
TEST(StateTracker,NotificationUponStateChange)110 TEST(StateTracker, NotificationUponStateChange) {
111 int count = 0;
112 grpc_connectivity_state state = GRPC_CHANNEL_IDLE;
113 absl::Status status;
114 ConnectivityStateTracker tracker("xxx", GRPC_CHANNEL_IDLE);
115 tracker.AddWatcher(GRPC_CHANNEL_IDLE,
116 MakeOrphanable<Watcher>(&count, &state, &status));
117 EXPECT_EQ(count, 0);
118 EXPECT_EQ(state, GRPC_CHANNEL_IDLE);
119 EXPECT_TRUE(status.ok());
120 absl::Status transient_failure_status(absl::StatusCode::kUnavailable,
121 "status for testing");
122 tracker.SetState(GRPC_CHANNEL_TRANSIENT_FAILURE, transient_failure_status,
123 "whee");
124 EXPECT_EQ(count, 1);
125 EXPECT_EQ(state, GRPC_CHANNEL_TRANSIENT_FAILURE);
126 EXPECT_EQ(status, transient_failure_status);
127 }
128
TEST(StateTracker,SubscribeThenUnsubscribe)129 TEST(StateTracker, SubscribeThenUnsubscribe) {
130 int count = 0;
131 grpc_connectivity_state state = GRPC_CHANNEL_IDLE;
132 absl::Status status;
133 bool destroyed = false;
134 ConnectivityStateTracker tracker("xxx", GRPC_CHANNEL_IDLE);
135 ConnectivityStateWatcherInterface* watcher =
136 new Watcher(&count, &state, &status, &destroyed);
137 tracker.AddWatcher(GRPC_CHANNEL_IDLE,
138 OrphanablePtr<ConnectivityStateWatcherInterface>(watcher));
139 // No initial notification, since we started the watch from the
140 // current state.
141 EXPECT_EQ(count, 0);
142 EXPECT_EQ(state, GRPC_CHANNEL_IDLE);
143 EXPECT_TRUE(status.ok());
144 // Cancel watch. This should not generate another notification.
145 tracker.RemoveWatcher(watcher);
146 EXPECT_TRUE(destroyed);
147 EXPECT_EQ(count, 0);
148 EXPECT_EQ(state, GRPC_CHANNEL_IDLE);
149 EXPECT_TRUE(status.ok());
150 }
151
TEST(StateTracker,OrphanUponShutdown)152 TEST(StateTracker, OrphanUponShutdown) {
153 int count = 0;
154 grpc_connectivity_state state = GRPC_CHANNEL_IDLE;
155 absl::Status status;
156 bool destroyed = false;
157 ConnectivityStateTracker tracker("xxx", GRPC_CHANNEL_IDLE);
158 ConnectivityStateWatcherInterface* watcher =
159 new Watcher(&count, &state, &status, &destroyed);
160 tracker.AddWatcher(GRPC_CHANNEL_IDLE,
161 OrphanablePtr<ConnectivityStateWatcherInterface>(watcher));
162 // No initial notification, since we started the watch from the
163 // current state.
164 EXPECT_EQ(count, 0);
165 EXPECT_EQ(state, GRPC_CHANNEL_IDLE);
166 EXPECT_TRUE(status.ok());
167 // Set state to SHUTDOWN.
168 tracker.SetState(GRPC_CHANNEL_SHUTDOWN, absl::Status(), "shutting down");
169 EXPECT_TRUE(destroyed);
170 EXPECT_EQ(count, 1);
171 EXPECT_EQ(state, GRPC_CHANNEL_SHUTDOWN);
172 EXPECT_TRUE(status.ok());
173 }
174
TEST(StateTracker,AddWhenAlreadyShutdown)175 TEST(StateTracker, AddWhenAlreadyShutdown) {
176 int count = 0;
177 grpc_connectivity_state state = GRPC_CHANNEL_IDLE;
178 absl::Status status;
179 bool destroyed = false;
180 ConnectivityStateTracker tracker("xxx", GRPC_CHANNEL_SHUTDOWN,
181 absl::Status());
182 ConnectivityStateWatcherInterface* watcher =
183 new Watcher(&count, &state, &status, &destroyed);
184 tracker.AddWatcher(GRPC_CHANNEL_IDLE,
185 OrphanablePtr<ConnectivityStateWatcherInterface>(watcher));
186 EXPECT_TRUE(destroyed);
187 EXPECT_EQ(count, 1);
188 EXPECT_EQ(state, GRPC_CHANNEL_SHUTDOWN);
189 EXPECT_TRUE(status.ok());
190 }
191
TEST(StateTracker,NotifyShutdownAtDestruction)192 TEST(StateTracker, NotifyShutdownAtDestruction) {
193 int count = 0;
194 grpc_connectivity_state state = GRPC_CHANNEL_IDLE;
195 absl::Status status;
196 {
197 ConnectivityStateTracker tracker("xxx", GRPC_CHANNEL_IDLE);
198 tracker.AddWatcher(GRPC_CHANNEL_IDLE,
199 MakeOrphanable<Watcher>(&count, &state, &status));
200 // No initial notification, since we started the watch from the
201 // current state.
202 EXPECT_EQ(count, 0);
203 EXPECT_EQ(state, GRPC_CHANNEL_IDLE);
204 }
205 // Upon tracker destruction, we get a notification for SHUTDOWN.
206 EXPECT_EQ(count, 1);
207 EXPECT_EQ(state, GRPC_CHANNEL_SHUTDOWN);
208 }
209
TEST(StateTracker,DoNotNotifyShutdownAtDestructionIfAlreadyInShutdown)210 TEST(StateTracker, DoNotNotifyShutdownAtDestructionIfAlreadyInShutdown) {
211 int count = 0;
212 grpc_connectivity_state state = GRPC_CHANNEL_SHUTDOWN;
213 absl::Status status;
214 {
215 ConnectivityStateTracker tracker("xxx", GRPC_CHANNEL_SHUTDOWN);
216 tracker.AddWatcher(GRPC_CHANNEL_SHUTDOWN,
217 MakeOrphanable<Watcher>(&count, &state, &status));
218 // No initial notification, since we started the watch from the
219 // current state.
220 EXPECT_EQ(count, 0);
221 EXPECT_EQ(state, GRPC_CHANNEL_SHUTDOWN);
222 }
223 // No additional notification upon tracker destruction, since we were
224 // already in state SHUTDOWN.
225 EXPECT_EQ(count, 0);
226 EXPECT_EQ(state, GRPC_CHANNEL_SHUTDOWN);
227 }
228
229 } // namespace
230 } // namespace grpc_core
231
main(int argc,char ** argv)232 int main(int argc, char** argv) {
233 grpc::testing::TestEnvironment env(&argc, argv);
234 ::testing::InitGoogleTest(&argc, argv);
235 grpc_init();
236 grpc_core::testing::grpc_tracer_enable_flag(
237 &grpc_core::grpc_connectivity_state_trace);
238 int ret = RUN_ALL_TESTS();
239 grpc_shutdown();
240 return ret;
241 }
242