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