slice_test.cc 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163
  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 "port/port.h"
  6. #include "port/stack_trace.h"
  7. #include "rocksdb/slice.h"
  8. #include "test_util/testharness.h"
  9. #include "test_util/testutil.h"
  10. namespace ROCKSDB_NAMESPACE {
  11. // Use this to keep track of the cleanups that were actually performed
  12. void Multiplier(void* arg1, void* arg2) {
  13. int* res = reinterpret_cast<int*>(arg1);
  14. int* num = reinterpret_cast<int*>(arg2);
  15. *res *= *num;
  16. }
  17. class PinnableSliceTest : public testing::Test {
  18. public:
  19. void AssertSameData(const std::string& expected,
  20. const PinnableSlice& slice) {
  21. std::string got;
  22. got.assign(slice.data(), slice.size());
  23. ASSERT_EQ(expected, got);
  24. }
  25. };
  26. // Test that the external buffer is moved instead of being copied.
  27. TEST_F(PinnableSliceTest, MoveExternalBuffer) {
  28. Slice s("123");
  29. std::string buf;
  30. PinnableSlice v1(&buf);
  31. v1.PinSelf(s);
  32. PinnableSlice v2(std::move(v1));
  33. ASSERT_EQ(buf.data(), v2.data());
  34. ASSERT_EQ(&buf, v2.GetSelf());
  35. PinnableSlice v3;
  36. v3 = std::move(v2);
  37. ASSERT_EQ(buf.data(), v3.data());
  38. ASSERT_EQ(&buf, v3.GetSelf());
  39. }
  40. TEST_F(PinnableSliceTest, Move) {
  41. int n2 = 2;
  42. int res = 1;
  43. const std::string const_str1 = "123";
  44. const std::string const_str2 = "ABC";
  45. Slice slice1(const_str1);
  46. Slice slice2(const_str2);
  47. {
  48. // Test move constructor on a pinned slice.
  49. res = 1;
  50. PinnableSlice v1;
  51. v1.PinSlice(slice1, Multiplier, &res, &n2);
  52. PinnableSlice v2(std::move(v1));
  53. // Since v1's Cleanable has been moved to v2,
  54. // no cleanup should happen in Reset.
  55. v1.Reset();
  56. ASSERT_EQ(1, res);
  57. AssertSameData(const_str1, v2);
  58. }
  59. // v2 is cleaned up.
  60. ASSERT_EQ(2, res);
  61. {
  62. // Test move constructor on an unpinned slice.
  63. PinnableSlice v1;
  64. v1.PinSelf(slice1);
  65. PinnableSlice v2(std::move(v1));
  66. AssertSameData(const_str1, v2);
  67. }
  68. {
  69. // Test move assignment from a pinned slice to
  70. // another pinned slice.
  71. res = 1;
  72. PinnableSlice v1;
  73. v1.PinSlice(slice1, Multiplier, &res, &n2);
  74. PinnableSlice v2;
  75. v2.PinSlice(slice2, Multiplier, &res, &n2);
  76. v2 = std::move(v1);
  77. // v2's Cleanable will be Reset before moving
  78. // anything from v1.
  79. ASSERT_EQ(2, res);
  80. // Since v1's Cleanable has been moved to v2,
  81. // no cleanup should happen in Reset.
  82. v1.Reset();
  83. ASSERT_EQ(2, res);
  84. AssertSameData(const_str1, v2);
  85. }
  86. // The Cleanable moved from v1 to v2 will be Reset.
  87. ASSERT_EQ(4, res);
  88. {
  89. // Test move assignment from a pinned slice to
  90. // an unpinned slice.
  91. res = 1;
  92. PinnableSlice v1;
  93. v1.PinSlice(slice1, Multiplier, &res, &n2);
  94. PinnableSlice v2;
  95. v2.PinSelf(slice2);
  96. v2 = std::move(v1);
  97. // Since v1's Cleanable has been moved to v2,
  98. // no cleanup should happen in Reset.
  99. v1.Reset();
  100. ASSERT_EQ(1, res);
  101. AssertSameData(const_str1, v2);
  102. }
  103. // The Cleanable moved from v1 to v2 will be Reset.
  104. ASSERT_EQ(2, res);
  105. {
  106. // Test move assignment from an upinned slice to
  107. // another unpinned slice.
  108. PinnableSlice v1;
  109. v1.PinSelf(slice1);
  110. PinnableSlice v2;
  111. v2.PinSelf(slice2);
  112. v2 = std::move(v1);
  113. AssertSameData(const_str1, v2);
  114. }
  115. {
  116. // Test move assignment from an upinned slice to
  117. // a pinned slice.
  118. res = 1;
  119. PinnableSlice v1;
  120. v1.PinSelf(slice1);
  121. PinnableSlice v2;
  122. v2.PinSlice(slice2, Multiplier, &res, &n2);
  123. v2 = std::move(v1);
  124. // v2's Cleanable will be Reset before moving
  125. // anything from v1.
  126. ASSERT_EQ(2, res);
  127. AssertSameData(const_str1, v2);
  128. }
  129. // No Cleanable is moved from v1 to v2, so no more cleanup.
  130. ASSERT_EQ(2, res);
  131. }
  132. } // namespace ROCKSDB_NAMESPACE
  133. int main(int argc, char** argv) {
  134. ROCKSDB_NAMESPACE::port::InstallStackTraceHandler();
  135. ::testing::InitGoogleTest(&argc, argv);
  136. return RUN_ALL_TESTS();
  137. }