• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <condition_variable>
20 #include <memory>
21 #include <mutex>
22 #include <thread>
23 
24 #include <grpcpp/alarm.h>
25 #include <grpcpp/completion_queue.h>
26 
27 #include <gtest/gtest.h>
28 
29 #include "test/core/util/test_config.h"
30 
31 namespace grpc {
32 namespace {
33 
TEST(AlarmTest,RegularExpiry)34 TEST(AlarmTest, RegularExpiry) {
35   CompletionQueue cq;
36   void* junk = reinterpret_cast<void*>(1618033);
37   Alarm alarm;
38   alarm.Set(&cq, grpc_timeout_seconds_to_deadline(1), junk);
39 
40   void* output_tag;
41   bool ok;
42   const CompletionQueue::NextStatus status =
43       cq.AsyncNext(&output_tag, &ok, grpc_timeout_seconds_to_deadline(10));
44 
45   EXPECT_EQ(status, CompletionQueue::GOT_EVENT);
46   EXPECT_TRUE(ok);
47   EXPECT_EQ(junk, output_tag);
48 }
49 
50 struct Completion {
51   bool completed = false;
52   std::mutex mu;
53   std::condition_variable cv;
54 };
55 
TEST(AlarmTest,CallbackRegularExpiry)56 TEST(AlarmTest, CallbackRegularExpiry) {
57   Alarm alarm;
58 
59   auto c = std::make_shared<Completion>();
60   alarm.experimental().Set(
61       std::chrono::system_clock::now() + std::chrono::seconds(1), [c](bool ok) {
62         EXPECT_TRUE(ok);
63         std::lock_guard<std::mutex> l(c->mu);
64         c->completed = true;
65         c->cv.notify_one();
66       });
67 
68   std::unique_lock<std::mutex> l(c->mu);
69   EXPECT_TRUE(c->cv.wait_until(
70       l, std::chrono::system_clock::now() + std::chrono::seconds(10),
71       [c] { return c->completed; }));
72 }
73 
TEST(AlarmTest,CallbackZeroExpiry)74 TEST(AlarmTest, CallbackZeroExpiry) {
75   Alarm alarm;
76 
77   auto c = std::make_shared<Completion>();
78   alarm.experimental().Set(grpc_timeout_seconds_to_deadline(0), [c](bool ok) {
79     EXPECT_TRUE(ok);
80     std::lock_guard<std::mutex> l(c->mu);
81     c->completed = true;
82     c->cv.notify_one();
83   });
84 
85   std::unique_lock<std::mutex> l(c->mu);
86   EXPECT_TRUE(c->cv.wait_until(
87       l, std::chrono::system_clock::now() + std::chrono::seconds(10),
88       [c] { return c->completed; }));
89 }
90 
TEST(AlarmTest,CallbackNegativeExpiry)91 TEST(AlarmTest, CallbackNegativeExpiry) {
92   Alarm alarm;
93 
94   auto c = std::make_shared<Completion>();
95   alarm.experimental().Set(
96       std::chrono::system_clock::now() + std::chrono::seconds(-1),
97       [c](bool ok) {
98         EXPECT_TRUE(ok);
99         std::lock_guard<std::mutex> l(c->mu);
100         c->completed = true;
101         c->cv.notify_one();
102       });
103 
104   std::unique_lock<std::mutex> l(c->mu);
105   EXPECT_TRUE(c->cv.wait_until(
106       l, std::chrono::system_clock::now() + std::chrono::seconds(10),
107       [c] { return c->completed; }));
108 }
109 
TEST(AlarmTest,MultithreadedRegularExpiry)110 TEST(AlarmTest, MultithreadedRegularExpiry) {
111   CompletionQueue cq;
112   void* junk = reinterpret_cast<void*>(1618033);
113   void* output_tag;
114   bool ok;
115   CompletionQueue::NextStatus status;
116   Alarm alarm;
117 
118   std::thread t1([&alarm, &cq, &junk] {
119     alarm.Set(&cq, grpc_timeout_seconds_to_deadline(1), junk);
120   });
121 
122   std::thread t2([&cq, &ok, &output_tag, &status] {
123     status =
124         cq.AsyncNext(&output_tag, &ok, grpc_timeout_seconds_to_deadline(10));
125   });
126 
127   t1.join();
128   t2.join();
129   EXPECT_EQ(status, CompletionQueue::GOT_EVENT);
130   EXPECT_TRUE(ok);
131   EXPECT_EQ(junk, output_tag);
132 }
133 
TEST(AlarmTest,DeprecatedRegularExpiry)134 TEST(AlarmTest, DeprecatedRegularExpiry) {
135   CompletionQueue cq;
136   void* junk = reinterpret_cast<void*>(1618033);
137   Alarm alarm(&cq, grpc_timeout_seconds_to_deadline(1), junk);
138 
139   void* output_tag;
140   bool ok;
141   const CompletionQueue::NextStatus status =
142       cq.AsyncNext(&output_tag, &ok, grpc_timeout_seconds_to_deadline(10));
143 
144   EXPECT_EQ(status, CompletionQueue::GOT_EVENT);
145   EXPECT_TRUE(ok);
146   EXPECT_EQ(junk, output_tag);
147 }
148 
TEST(AlarmTest,MoveConstructor)149 TEST(AlarmTest, MoveConstructor) {
150   CompletionQueue cq;
151   void* junk = reinterpret_cast<void*>(1618033);
152   Alarm first;
153   first.Set(&cq, grpc_timeout_seconds_to_deadline(1), junk);
154   Alarm second(std::move(first));
155   void* output_tag;
156   bool ok;
157   const CompletionQueue::NextStatus status =
158       cq.AsyncNext(&output_tag, &ok, grpc_timeout_seconds_to_deadline(10));
159   EXPECT_EQ(status, CompletionQueue::GOT_EVENT);
160   EXPECT_TRUE(ok);
161   EXPECT_EQ(junk, output_tag);
162 }
163 
TEST(AlarmTest,MoveAssignment)164 TEST(AlarmTest, MoveAssignment) {
165   CompletionQueue cq;
166   void* junk = reinterpret_cast<void*>(1618033);
167   Alarm first;
168   first.Set(&cq, grpc_timeout_seconds_to_deadline(1), junk);
169   Alarm second(std::move(first));
170   first = std::move(second);
171 
172   void* output_tag;
173   bool ok;
174   const CompletionQueue::NextStatus status =
175       cq.AsyncNext(&output_tag, &ok, grpc_timeout_seconds_to_deadline(10));
176 
177   EXPECT_EQ(status, CompletionQueue::GOT_EVENT);
178   EXPECT_TRUE(ok);
179   EXPECT_EQ(junk, output_tag);
180 }
181 
TEST(AlarmTest,RegularExpiryChrono)182 TEST(AlarmTest, RegularExpiryChrono) {
183   CompletionQueue cq;
184   void* junk = reinterpret_cast<void*>(1618033);
185   std::chrono::system_clock::time_point one_sec_deadline =
186       std::chrono::system_clock::now() + std::chrono::seconds(1);
187   Alarm alarm;
188   alarm.Set(&cq, one_sec_deadline, junk);
189 
190   void* output_tag;
191   bool ok;
192   const CompletionQueue::NextStatus status =
193       cq.AsyncNext(&output_tag, &ok, grpc_timeout_seconds_to_deadline(10));
194 
195   EXPECT_EQ(status, CompletionQueue::GOT_EVENT);
196   EXPECT_TRUE(ok);
197   EXPECT_EQ(junk, output_tag);
198 }
199 
TEST(AlarmTest,ZeroExpiry)200 TEST(AlarmTest, ZeroExpiry) {
201   CompletionQueue cq;
202   void* junk = reinterpret_cast<void*>(1618033);
203   Alarm alarm;
204   alarm.Set(&cq, grpc_timeout_seconds_to_deadline(0), junk);
205 
206   void* output_tag;
207   bool ok;
208   const CompletionQueue::NextStatus status =
209       cq.AsyncNext(&output_tag, &ok, grpc_timeout_seconds_to_deadline(1));
210 
211   EXPECT_EQ(status, CompletionQueue::GOT_EVENT);
212   EXPECT_TRUE(ok);
213   EXPECT_EQ(junk, output_tag);
214 }
215 
TEST(AlarmTest,NegativeExpiry)216 TEST(AlarmTest, NegativeExpiry) {
217   CompletionQueue cq;
218   void* junk = reinterpret_cast<void*>(1618033);
219   Alarm alarm;
220   alarm.Set(&cq, grpc_timeout_seconds_to_deadline(-1), junk);
221 
222   void* output_tag;
223   bool ok;
224   const CompletionQueue::NextStatus status =
225       cq.AsyncNext(&output_tag, &ok, grpc_timeout_seconds_to_deadline(1));
226 
227   EXPECT_EQ(status, CompletionQueue::GOT_EVENT);
228   EXPECT_TRUE(ok);
229   EXPECT_EQ(junk, output_tag);
230 }
231 
TEST(AlarmTest,Cancellation)232 TEST(AlarmTest, Cancellation) {
233   CompletionQueue cq;
234   void* junk = reinterpret_cast<void*>(1618033);
235   Alarm alarm;
236   alarm.Set(&cq, grpc_timeout_seconds_to_deadline(10), junk);
237   alarm.Cancel();
238 
239   void* output_tag;
240   bool ok;
241   const CompletionQueue::NextStatus status =
242       cq.AsyncNext(&output_tag, &ok, grpc_timeout_seconds_to_deadline(1));
243 
244   EXPECT_EQ(status, CompletionQueue::GOT_EVENT);
245   EXPECT_FALSE(ok);
246   EXPECT_EQ(junk, output_tag);
247 }
248 
TEST(AlarmTest,CallbackCancellation)249 TEST(AlarmTest, CallbackCancellation) {
250   Alarm alarm;
251 
252   auto c = std::make_shared<Completion>();
253   alarm.experimental().Set(
254       std::chrono::system_clock::now() + std::chrono::seconds(10),
255       [c](bool ok) {
256         EXPECT_FALSE(ok);
257         std::lock_guard<std::mutex> l(c->mu);
258         c->completed = true;
259         c->cv.notify_one();
260       });
261   alarm.Cancel();
262 
263   std::unique_lock<std::mutex> l(c->mu);
264   EXPECT_TRUE(c->cv.wait_until(
265       l, std::chrono::system_clock::now() + std::chrono::seconds(1),
266       [c] { return c->completed; }));
267 }
268 
TEST(AlarmTest,SetDestruction)269 TEST(AlarmTest, SetDestruction) {
270   CompletionQueue cq;
271   void* junk = reinterpret_cast<void*>(1618033);
272   {
273     Alarm alarm;
274     alarm.Set(&cq, grpc_timeout_seconds_to_deadline(10), junk);
275   }
276 
277   void* output_tag;
278   bool ok;
279   const CompletionQueue::NextStatus status =
280       cq.AsyncNext(&output_tag, &ok, grpc_timeout_seconds_to_deadline(1));
281 
282   EXPECT_EQ(status, CompletionQueue::GOT_EVENT);
283   EXPECT_FALSE(ok);
284   EXPECT_EQ(junk, output_tag);
285 }
286 
TEST(AlarmTest,CallbackSetDestruction)287 TEST(AlarmTest, CallbackSetDestruction) {
288   auto c = std::make_shared<Completion>();
289   {
290     Alarm alarm;
291     alarm.experimental().Set(
292         std::chrono::system_clock::now() + std::chrono::seconds(10),
293         [c](bool ok) {
294           EXPECT_FALSE(ok);
295           std::lock_guard<std::mutex> l(c->mu);
296           c->completed = true;
297           c->cv.notify_one();
298         });
299   }
300 
301   std::unique_lock<std::mutex> l(c->mu);
302   EXPECT_TRUE(c->cv.wait_until(
303       l, std::chrono::system_clock::now() + std::chrono::seconds(1),
304       [c] { return c->completed; }));
305 }
306 
TEST(AlarmTest,UnsetDestruction)307 TEST(AlarmTest, UnsetDestruction) {
308   CompletionQueue cq;
309   Alarm alarm;
310 }
311 
312 }  // namespace
313 }  // namespace grpc
314 
main(int argc,char ** argv)315 int main(int argc, char** argv) {
316   grpc_test_init(argc, argv);
317   ::testing::InitGoogleTest(&argc, argv);
318   return RUN_ALL_TESTS();
319 }
320