alarm_test.cc 10 KB

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