xref: /aosp_15_r20/external/grpc-grpc/test/core/transport/connectivity_state_test.cc (revision cc02d7e222339f7a4f6ba5f422e6413f4bd931f2)
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