cleanable_test.cc 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277
  1. // Copyright (c) 2011-present, Facebook, Inc. All rights reserved.
  2. // This source code is licensed under both the GPLv2 (found in the
  3. // COPYING file in the root directory) and Apache 2.0 License
  4. // (found in the LICENSE.Apache file in the root directory).
  5. #include <functional>
  6. #include "port/port.h"
  7. #include "port/stack_trace.h"
  8. #include "rocksdb/iostats_context.h"
  9. #include "rocksdb/perf_context.h"
  10. #include "test_util/testharness.h"
  11. #include "test_util/testutil.h"
  12. namespace ROCKSDB_NAMESPACE {
  13. class CleanableTest : public testing::Test {};
  14. // Use this to keep track of the cleanups that were actually performed
  15. void Multiplier(void* arg1, void* arg2) {
  16. int* res = reinterpret_cast<int*>(arg1);
  17. int* num = reinterpret_cast<int*>(arg2);
  18. *res *= *num;
  19. }
  20. // the first Cleanup is on stack and the rest on heap, so test with both cases
  21. TEST_F(CleanableTest, Register) {
  22. int n2 = 2, n3 = 3;
  23. int res = 1;
  24. { Cleanable c1; }
  25. // ~Cleanable
  26. ASSERT_EQ(1, res);
  27. res = 1;
  28. {
  29. Cleanable c1;
  30. c1.RegisterCleanup(Multiplier, &res, &n2); // res = 2;
  31. }
  32. // ~Cleanable
  33. ASSERT_EQ(2, res);
  34. res = 1;
  35. {
  36. Cleanable c1;
  37. c1.RegisterCleanup(Multiplier, &res, &n2); // res = 2;
  38. c1.RegisterCleanup(Multiplier, &res, &n3); // res = 2 * 3;
  39. }
  40. // ~Cleanable
  41. ASSERT_EQ(6, res);
  42. // Test the Reset does cleanup
  43. res = 1;
  44. {
  45. Cleanable c1;
  46. c1.RegisterCleanup(Multiplier, &res, &n2); // res = 2;
  47. c1.RegisterCleanup(Multiplier, &res, &n3); // res = 2 * 3;
  48. c1.Reset();
  49. ASSERT_EQ(6, res);
  50. }
  51. // ~Cleanable
  52. ASSERT_EQ(6, res);
  53. // Test Clenable is usable after Reset
  54. res = 1;
  55. {
  56. Cleanable c1;
  57. c1.RegisterCleanup(Multiplier, &res, &n2); // res = 2;
  58. c1.Reset();
  59. ASSERT_EQ(2, res);
  60. c1.RegisterCleanup(Multiplier, &res, &n3); // res = 2 * 3;
  61. }
  62. // ~Cleanable
  63. ASSERT_EQ(6, res);
  64. }
  65. // the first Cleanup is on stack and the rest on heap,
  66. // so test all the combinations of them
  67. TEST_F(CleanableTest, Delegation) {
  68. int n2 = 2, n3 = 3, n5 = 5, n7 = 7;
  69. int res = 1;
  70. {
  71. Cleanable c2;
  72. {
  73. Cleanable c1;
  74. c1.RegisterCleanup(Multiplier, &res, &n2); // res = 2;
  75. c1.DelegateCleanupsTo(&c2);
  76. }
  77. // ~Cleanable
  78. ASSERT_EQ(1, res);
  79. }
  80. // ~Cleanable
  81. ASSERT_EQ(2, res);
  82. res = 1;
  83. {
  84. Cleanable c2;
  85. {
  86. Cleanable c1;
  87. c1.DelegateCleanupsTo(&c2);
  88. }
  89. // ~Cleanable
  90. ASSERT_EQ(1, res);
  91. }
  92. // ~Cleanable
  93. ASSERT_EQ(1, res);
  94. res = 1;
  95. {
  96. Cleanable c2;
  97. {
  98. Cleanable c1;
  99. c1.RegisterCleanup(Multiplier, &res, &n2); // res = 2;
  100. c1.RegisterCleanup(Multiplier, &res, &n3); // res = 2 * 3;
  101. c1.DelegateCleanupsTo(&c2);
  102. }
  103. // ~Cleanable
  104. ASSERT_EQ(1, res);
  105. }
  106. // ~Cleanable
  107. ASSERT_EQ(6, res);
  108. res = 1;
  109. {
  110. Cleanable c2;
  111. c2.RegisterCleanup(Multiplier, &res, &n5); // res = 5;
  112. {
  113. Cleanable c1;
  114. c1.RegisterCleanup(Multiplier, &res, &n2); // res = 2;
  115. c1.RegisterCleanup(Multiplier, &res, &n3); // res = 2 * 3;
  116. c1.DelegateCleanupsTo(&c2); // res = 2 * 3 * 5;
  117. }
  118. // ~Cleanable
  119. ASSERT_EQ(1, res);
  120. }
  121. // ~Cleanable
  122. ASSERT_EQ(30, res);
  123. res = 1;
  124. {
  125. Cleanable c2;
  126. c2.RegisterCleanup(Multiplier, &res, &n5); // res = 5;
  127. c2.RegisterCleanup(Multiplier, &res, &n7); // res = 5 * 7;
  128. {
  129. Cleanable c1;
  130. c1.RegisterCleanup(Multiplier, &res, &n2); // res = 2;
  131. c1.RegisterCleanup(Multiplier, &res, &n3); // res = 2 * 3;
  132. c1.DelegateCleanupsTo(&c2); // res = 2 * 3 * 5 * 7;
  133. }
  134. // ~Cleanable
  135. ASSERT_EQ(1, res);
  136. }
  137. // ~Cleanable
  138. ASSERT_EQ(210, res);
  139. res = 1;
  140. {
  141. Cleanable c2;
  142. c2.RegisterCleanup(Multiplier, &res, &n5); // res = 5;
  143. c2.RegisterCleanup(Multiplier, &res, &n7); // res = 5 * 7;
  144. {
  145. Cleanable c1;
  146. c1.RegisterCleanup(Multiplier, &res, &n2); // res = 2;
  147. c1.DelegateCleanupsTo(&c2); // res = 2 * 5 * 7;
  148. }
  149. // ~Cleanable
  150. ASSERT_EQ(1, res);
  151. }
  152. // ~Cleanable
  153. ASSERT_EQ(70, res);
  154. res = 1;
  155. {
  156. Cleanable c2;
  157. c2.RegisterCleanup(Multiplier, &res, &n5); // res = 5;
  158. c2.RegisterCleanup(Multiplier, &res, &n7); // res = 5 * 7;
  159. {
  160. Cleanable c1;
  161. c1.DelegateCleanupsTo(&c2); // res = 5 * 7;
  162. }
  163. // ~Cleanable
  164. ASSERT_EQ(1, res);
  165. }
  166. // ~Cleanable
  167. ASSERT_EQ(35, res);
  168. res = 1;
  169. {
  170. Cleanable c2;
  171. c2.RegisterCleanup(Multiplier, &res, &n5); // res = 5;
  172. {
  173. Cleanable c1;
  174. c1.DelegateCleanupsTo(&c2); // res = 5;
  175. }
  176. // ~Cleanable
  177. ASSERT_EQ(1, res);
  178. }
  179. // ~Cleanable
  180. ASSERT_EQ(5, res);
  181. }
  182. static void ReleaseStringHeap(void* s, void*) {
  183. delete reinterpret_cast<const std::string*>(s);
  184. }
  185. class PinnableSlice4Test : public PinnableSlice {
  186. public:
  187. void TestStringIsRegistered(std::string* s) {
  188. ASSERT_TRUE(cleanup_.function == ReleaseStringHeap);
  189. ASSERT_EQ(cleanup_.arg1, s);
  190. ASSERT_EQ(cleanup_.arg2, nullptr);
  191. ASSERT_EQ(cleanup_.next, nullptr);
  192. }
  193. };
  194. // Putting the PinnableSlice tests here due to similarity to Cleanable tests
  195. TEST_F(CleanableTest, PinnableSlice) {
  196. int n2 = 2;
  197. int res = 1;
  198. const std::string const_str = "123";
  199. {
  200. res = 1;
  201. PinnableSlice4Test value;
  202. Slice slice(const_str);
  203. value.PinSlice(slice, Multiplier, &res, &n2);
  204. std::string str;
  205. str.assign(value.data(), value.size());
  206. ASSERT_EQ(const_str, str);
  207. }
  208. // ~Cleanable
  209. ASSERT_EQ(2, res);
  210. {
  211. res = 1;
  212. PinnableSlice4Test value;
  213. Slice slice(const_str);
  214. {
  215. Cleanable c1;
  216. c1.RegisterCleanup(Multiplier, &res, &n2); // res = 2;
  217. value.PinSlice(slice, &c1);
  218. }
  219. // ~Cleanable
  220. ASSERT_EQ(1, res); // cleanups must have be delegated to value
  221. std::string str;
  222. str.assign(value.data(), value.size());
  223. ASSERT_EQ(const_str, str);
  224. }
  225. // ~Cleanable
  226. ASSERT_EQ(2, res);
  227. {
  228. PinnableSlice4Test value;
  229. Slice slice(const_str);
  230. value.PinSelf(slice);
  231. std::string str;
  232. str.assign(value.data(), value.size());
  233. ASSERT_EQ(const_str, str);
  234. }
  235. {
  236. PinnableSlice4Test value;
  237. std::string* self_str_ptr = value.GetSelf();
  238. self_str_ptr->assign(const_str);
  239. value.PinSelf();
  240. std::string str;
  241. str.assign(value.data(), value.size());
  242. ASSERT_EQ(const_str, str);
  243. }
  244. }
  245. } // namespace ROCKSDB_NAMESPACE
  246. int main(int argc, char** argv) {
  247. ROCKSDB_NAMESPACE::port::InstallStackTraceHandler();
  248. ::testing::InitGoogleTest(&argc, argv);
  249. return RUN_ALL_TESTS();
  250. }