wide_column_serialization_test.cc 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311
  1. // Copyright (c) Meta Platforms, Inc. and affiliates.
  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 "db/wide/wide_column_serialization.h"
  6. #include "db/wide/wide_columns_helper.h"
  7. #include "test_util/testharness.h"
  8. #include "util/coding.h"
  9. namespace ROCKSDB_NAMESPACE {
  10. TEST(WideColumnSerializationTest, Construct) {
  11. constexpr char foo[] = "foo";
  12. constexpr char bar[] = "bar";
  13. const std::string foo_str(foo);
  14. const std::string bar_str(bar);
  15. const Slice foo_slice(foo_str);
  16. const Slice bar_slice(bar_str);
  17. {
  18. WideColumn column(foo, bar);
  19. ASSERT_EQ(column.name(), foo);
  20. ASSERT_EQ(column.value(), bar);
  21. }
  22. {
  23. WideColumn column(foo_str, bar);
  24. ASSERT_EQ(column.name(), foo_str);
  25. ASSERT_EQ(column.value(), bar);
  26. }
  27. {
  28. WideColumn column(foo_slice, bar);
  29. ASSERT_EQ(column.name(), foo_slice);
  30. ASSERT_EQ(column.value(), bar);
  31. }
  32. {
  33. WideColumn column(foo, bar_str);
  34. ASSERT_EQ(column.name(), foo);
  35. ASSERT_EQ(column.value(), bar_str);
  36. }
  37. {
  38. WideColumn column(foo_str, bar_str);
  39. ASSERT_EQ(column.name(), foo_str);
  40. ASSERT_EQ(column.value(), bar_str);
  41. }
  42. {
  43. WideColumn column(foo_slice, bar_str);
  44. ASSERT_EQ(column.name(), foo_slice);
  45. ASSERT_EQ(column.value(), bar_str);
  46. }
  47. {
  48. WideColumn column(foo, bar_slice);
  49. ASSERT_EQ(column.name(), foo);
  50. ASSERT_EQ(column.value(), bar_slice);
  51. }
  52. {
  53. WideColumn column(foo_str, bar_slice);
  54. ASSERT_EQ(column.name(), foo_str);
  55. ASSERT_EQ(column.value(), bar_slice);
  56. }
  57. {
  58. WideColumn column(foo_slice, bar_slice);
  59. ASSERT_EQ(column.name(), foo_slice);
  60. ASSERT_EQ(column.value(), bar_slice);
  61. }
  62. {
  63. constexpr char foo_name[] = "foo_name";
  64. constexpr char bar_value[] = "bar_value";
  65. WideColumn column(std::piecewise_construct,
  66. std::forward_as_tuple(foo_name, sizeof(foo) - 1),
  67. std::forward_as_tuple(bar_value, sizeof(bar) - 1));
  68. ASSERT_EQ(column.name(), foo);
  69. ASSERT_EQ(column.value(), bar);
  70. }
  71. }
  72. TEST(WideColumnSerializationTest, SerializeDeserialize) {
  73. WideColumns columns{{"foo", "bar"}, {"hello", "world"}};
  74. std::string output;
  75. ASSERT_OK(WideColumnSerialization::Serialize(columns, output));
  76. Slice input(output);
  77. WideColumns deserialized_columns;
  78. ASSERT_OK(WideColumnSerialization::Deserialize(input, deserialized_columns));
  79. ASSERT_EQ(columns, deserialized_columns);
  80. {
  81. const auto it = WideColumnsHelper::Find(deserialized_columns.cbegin(),
  82. deserialized_columns.cend(), "foo");
  83. ASSERT_NE(it, deserialized_columns.cend());
  84. ASSERT_EQ(*it, deserialized_columns.front());
  85. }
  86. {
  87. const auto it = WideColumnsHelper::Find(
  88. deserialized_columns.cbegin(), deserialized_columns.cend(), "hello");
  89. ASSERT_NE(it, deserialized_columns.cend());
  90. ASSERT_EQ(*it, deserialized_columns.back());
  91. }
  92. {
  93. const auto it = WideColumnsHelper::Find(
  94. deserialized_columns.cbegin(), deserialized_columns.cend(), "fubar");
  95. ASSERT_EQ(it, deserialized_columns.cend());
  96. }
  97. {
  98. const auto it = WideColumnsHelper::Find(
  99. deserialized_columns.cbegin(), deserialized_columns.cend(), "snafu");
  100. ASSERT_EQ(it, deserialized_columns.cend());
  101. }
  102. }
  103. TEST(WideColumnSerializationTest, SerializeDuplicateError) {
  104. WideColumns columns{{"foo", "bar"}, {"foo", "baz"}};
  105. std::string output;
  106. ASSERT_TRUE(
  107. WideColumnSerialization::Serialize(columns, output).IsCorruption());
  108. }
  109. TEST(WideColumnSerializationTest, SerializeOutOfOrderError) {
  110. WideColumns columns{{"hello", "world"}, {"foo", "bar"}};
  111. std::string output;
  112. ASSERT_TRUE(
  113. WideColumnSerialization::Serialize(columns, output).IsCorruption());
  114. }
  115. TEST(WideColumnSerializationTest, DeserializeVersionError) {
  116. // Can't decode version
  117. std::string buf;
  118. Slice input(buf);
  119. WideColumns columns;
  120. const Status s = WideColumnSerialization::Deserialize(input, columns);
  121. ASSERT_TRUE(s.IsCorruption());
  122. ASSERT_TRUE(std::strstr(s.getState(), "version"));
  123. }
  124. TEST(WideColumnSerializationTest, DeserializeUnsupportedVersion) {
  125. // Unsupported version
  126. constexpr uint32_t future_version = 1000;
  127. std::string buf;
  128. PutVarint32(&buf, future_version);
  129. Slice input(buf);
  130. WideColumns columns;
  131. const Status s = WideColumnSerialization::Deserialize(input, columns);
  132. ASSERT_TRUE(s.IsNotSupported());
  133. ASSERT_TRUE(std::strstr(s.getState(), "version"));
  134. }
  135. TEST(WideColumnSerializationTest, DeserializeNumberOfColumnsError) {
  136. // Can't decode number of columns
  137. std::string buf;
  138. PutVarint32(&buf, WideColumnSerialization::kCurrentVersion);
  139. Slice input(buf);
  140. WideColumns columns;
  141. const Status s = WideColumnSerialization::Deserialize(input, columns);
  142. ASSERT_TRUE(s.IsCorruption());
  143. ASSERT_TRUE(std::strstr(s.getState(), "number"));
  144. }
  145. TEST(WideColumnSerializationTest, DeserializeColumnsError) {
  146. std::string buf;
  147. PutVarint32(&buf, WideColumnSerialization::kCurrentVersion);
  148. constexpr uint32_t num_columns = 2;
  149. PutVarint32(&buf, num_columns);
  150. // Can't decode the first column name
  151. {
  152. Slice input(buf);
  153. WideColumns columns;
  154. const Status s = WideColumnSerialization::Deserialize(input, columns);
  155. ASSERT_TRUE(s.IsCorruption());
  156. ASSERT_TRUE(std::strstr(s.getState(), "name"));
  157. }
  158. constexpr char first_column_name[] = "foo";
  159. PutLengthPrefixedSlice(&buf, first_column_name);
  160. // Can't decode the size of the first column value
  161. {
  162. Slice input(buf);
  163. WideColumns columns;
  164. const Status s = WideColumnSerialization::Deserialize(input, columns);
  165. ASSERT_TRUE(s.IsCorruption());
  166. ASSERT_TRUE(std::strstr(s.getState(), "value size"));
  167. }
  168. constexpr uint32_t first_value_size = 16;
  169. PutVarint32(&buf, first_value_size);
  170. // Can't decode the second column name
  171. {
  172. Slice input(buf);
  173. WideColumns columns;
  174. const Status s = WideColumnSerialization::Deserialize(input, columns);
  175. ASSERT_TRUE(s.IsCorruption());
  176. ASSERT_TRUE(std::strstr(s.getState(), "name"));
  177. }
  178. constexpr char second_column_name[] = "hello";
  179. PutLengthPrefixedSlice(&buf, second_column_name);
  180. // Can't decode the size of the second column value
  181. {
  182. Slice input(buf);
  183. WideColumns columns;
  184. const Status s = WideColumnSerialization::Deserialize(input, columns);
  185. ASSERT_TRUE(s.IsCorruption());
  186. ASSERT_TRUE(std::strstr(s.getState(), "value size"));
  187. }
  188. constexpr uint32_t second_value_size = 64;
  189. PutVarint32(&buf, second_value_size);
  190. // Can't decode the payload of the first column
  191. {
  192. Slice input(buf);
  193. WideColumns columns;
  194. const Status s = WideColumnSerialization::Deserialize(input, columns);
  195. ASSERT_TRUE(s.IsCorruption());
  196. ASSERT_TRUE(std::strstr(s.getState(), "payload"));
  197. }
  198. buf.append(first_value_size, '0');
  199. // Can't decode the payload of the second column
  200. {
  201. Slice input(buf);
  202. WideColumns columns;
  203. const Status s = WideColumnSerialization::Deserialize(input, columns);
  204. ASSERT_TRUE(s.IsCorruption());
  205. ASSERT_TRUE(std::strstr(s.getState(), "payload"));
  206. }
  207. buf.append(second_value_size, 'x');
  208. // Success
  209. {
  210. Slice input(buf);
  211. WideColumns columns;
  212. ASSERT_OK(WideColumnSerialization::Deserialize(input, columns));
  213. }
  214. }
  215. TEST(WideColumnSerializationTest, DeserializeColumnsOutOfOrder) {
  216. std::string buf;
  217. PutVarint32(&buf, WideColumnSerialization::kCurrentVersion);
  218. constexpr uint32_t num_columns = 2;
  219. PutVarint32(&buf, num_columns);
  220. constexpr char first_column_name[] = "b";
  221. PutLengthPrefixedSlice(&buf, first_column_name);
  222. constexpr uint32_t first_value_size = 16;
  223. PutVarint32(&buf, first_value_size);
  224. constexpr char second_column_name[] = "a";
  225. PutLengthPrefixedSlice(&buf, second_column_name);
  226. Slice input(buf);
  227. WideColumns columns;
  228. const Status s = WideColumnSerialization::Deserialize(input, columns);
  229. ASSERT_TRUE(s.IsCorruption());
  230. ASSERT_TRUE(std::strstr(s.getState(), "order"));
  231. }
  232. } // namespace ROCKSDB_NAMESPACE
  233. int main(int argc, char** argv) {
  234. ROCKSDB_NAMESPACE::port::InstallStackTraceHandler();
  235. ::testing::InitGoogleTest(&argc, argv);
  236. return RUN_ALL_TESTS();
  237. }