version_set_test.cc 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331
  1. // Copyright (c) 2011 The LevelDB Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file. See the AUTHORS file for names of contributors.
  4. #include "db/version_set.h"
  5. #include "gtest/gtest.h"
  6. #include "util/logging.h"
  7. #include "util/testutil.h"
  8. namespace leveldb {
  9. class FindFileTest : public testing::Test {
  10. public:
  11. FindFileTest() : disjoint_sorted_files_(true) {}
  12. ~FindFileTest() {
  13. for (int i = 0; i < files_.size(); i++) {
  14. delete files_[i];
  15. }
  16. }
  17. void Add(const char* smallest, const char* largest,
  18. SequenceNumber smallest_seq = 100,
  19. SequenceNumber largest_seq = 100) {
  20. FileMetaData* f = new FileMetaData;
  21. f->number = files_.size() + 1;
  22. f->smallest = InternalKey(smallest, smallest_seq, kTypeValue);
  23. f->largest = InternalKey(largest, largest_seq, kTypeValue);
  24. files_.push_back(f);
  25. }
  26. int Find(const char* key) {
  27. InternalKey target(key, 100, kTypeValue);
  28. InternalKeyComparator cmp(BytewiseComparator());
  29. return FindFile(cmp, files_, target.Encode());
  30. }
  31. bool Overlaps(const char* smallest, const char* largest) {
  32. InternalKeyComparator cmp(BytewiseComparator());
  33. Slice s(smallest != nullptr ? smallest : "");
  34. Slice l(largest != nullptr ? largest : "");
  35. return SomeFileOverlapsRange(cmp, disjoint_sorted_files_, files_,
  36. (smallest != nullptr ? &s : nullptr),
  37. (largest != nullptr ? &l : nullptr));
  38. }
  39. bool disjoint_sorted_files_;
  40. private:
  41. std::vector<FileMetaData*> files_;
  42. };
  43. TEST_F(FindFileTest, Empty) {
  44. ASSERT_EQ(0, Find("foo"));
  45. ASSERT_TRUE(!Overlaps("a", "z"));
  46. ASSERT_TRUE(!Overlaps(nullptr, "z"));
  47. ASSERT_TRUE(!Overlaps("a", nullptr));
  48. ASSERT_TRUE(!Overlaps(nullptr, nullptr));
  49. }
  50. TEST_F(FindFileTest, Single) {
  51. Add("p", "q");
  52. ASSERT_EQ(0, Find("a"));
  53. ASSERT_EQ(0, Find("p"));
  54. ASSERT_EQ(0, Find("p1"));
  55. ASSERT_EQ(0, Find("q"));
  56. ASSERT_EQ(1, Find("q1"));
  57. ASSERT_EQ(1, Find("z"));
  58. ASSERT_TRUE(!Overlaps("a", "b"));
  59. ASSERT_TRUE(!Overlaps("z1", "z2"));
  60. ASSERT_TRUE(Overlaps("a", "p"));
  61. ASSERT_TRUE(Overlaps("a", "q"));
  62. ASSERT_TRUE(Overlaps("a", "z"));
  63. ASSERT_TRUE(Overlaps("p", "p1"));
  64. ASSERT_TRUE(Overlaps("p", "q"));
  65. ASSERT_TRUE(Overlaps("p", "z"));
  66. ASSERT_TRUE(Overlaps("p1", "p2"));
  67. ASSERT_TRUE(Overlaps("p1", "z"));
  68. ASSERT_TRUE(Overlaps("q", "q"));
  69. ASSERT_TRUE(Overlaps("q", "q1"));
  70. ASSERT_TRUE(!Overlaps(nullptr, "j"));
  71. ASSERT_TRUE(!Overlaps("r", nullptr));
  72. ASSERT_TRUE(Overlaps(nullptr, "p"));
  73. ASSERT_TRUE(Overlaps(nullptr, "p1"));
  74. ASSERT_TRUE(Overlaps("q", nullptr));
  75. ASSERT_TRUE(Overlaps(nullptr, nullptr));
  76. }
  77. TEST_F(FindFileTest, Multiple) {
  78. Add("150", "200");
  79. Add("200", "250");
  80. Add("300", "350");
  81. Add("400", "450");
  82. ASSERT_EQ(0, Find("100"));
  83. ASSERT_EQ(0, Find("150"));
  84. ASSERT_EQ(0, Find("151"));
  85. ASSERT_EQ(0, Find("199"));
  86. ASSERT_EQ(0, Find("200"));
  87. ASSERT_EQ(1, Find("201"));
  88. ASSERT_EQ(1, Find("249"));
  89. ASSERT_EQ(1, Find("250"));
  90. ASSERT_EQ(2, Find("251"));
  91. ASSERT_EQ(2, Find("299"));
  92. ASSERT_EQ(2, Find("300"));
  93. ASSERT_EQ(2, Find("349"));
  94. ASSERT_EQ(2, Find("350"));
  95. ASSERT_EQ(3, Find("351"));
  96. ASSERT_EQ(3, Find("400"));
  97. ASSERT_EQ(3, Find("450"));
  98. ASSERT_EQ(4, Find("451"));
  99. ASSERT_TRUE(!Overlaps("100", "149"));
  100. ASSERT_TRUE(!Overlaps("251", "299"));
  101. ASSERT_TRUE(!Overlaps("451", "500"));
  102. ASSERT_TRUE(!Overlaps("351", "399"));
  103. ASSERT_TRUE(Overlaps("100", "150"));
  104. ASSERT_TRUE(Overlaps("100", "200"));
  105. ASSERT_TRUE(Overlaps("100", "300"));
  106. ASSERT_TRUE(Overlaps("100", "400"));
  107. ASSERT_TRUE(Overlaps("100", "500"));
  108. ASSERT_TRUE(Overlaps("375", "400"));
  109. ASSERT_TRUE(Overlaps("450", "450"));
  110. ASSERT_TRUE(Overlaps("450", "500"));
  111. }
  112. TEST_F(FindFileTest, MultipleNullBoundaries) {
  113. Add("150", "200");
  114. Add("200", "250");
  115. Add("300", "350");
  116. Add("400", "450");
  117. ASSERT_TRUE(!Overlaps(nullptr, "149"));
  118. ASSERT_TRUE(!Overlaps("451", nullptr));
  119. ASSERT_TRUE(Overlaps(nullptr, nullptr));
  120. ASSERT_TRUE(Overlaps(nullptr, "150"));
  121. ASSERT_TRUE(Overlaps(nullptr, "199"));
  122. ASSERT_TRUE(Overlaps(nullptr, "200"));
  123. ASSERT_TRUE(Overlaps(nullptr, "201"));
  124. ASSERT_TRUE(Overlaps(nullptr, "400"));
  125. ASSERT_TRUE(Overlaps(nullptr, "800"));
  126. ASSERT_TRUE(Overlaps("100", nullptr));
  127. ASSERT_TRUE(Overlaps("200", nullptr));
  128. ASSERT_TRUE(Overlaps("449", nullptr));
  129. ASSERT_TRUE(Overlaps("450", nullptr));
  130. }
  131. TEST_F(FindFileTest, OverlapSequenceChecks) {
  132. Add("200", "200", 5000, 3000);
  133. ASSERT_TRUE(!Overlaps("199", "199"));
  134. ASSERT_TRUE(!Overlaps("201", "300"));
  135. ASSERT_TRUE(Overlaps("200", "200"));
  136. ASSERT_TRUE(Overlaps("190", "200"));
  137. ASSERT_TRUE(Overlaps("200", "210"));
  138. }
  139. TEST_F(FindFileTest, OverlappingFiles) {
  140. Add("150", "600");
  141. Add("400", "500");
  142. disjoint_sorted_files_ = false;
  143. ASSERT_TRUE(!Overlaps("100", "149"));
  144. ASSERT_TRUE(!Overlaps("601", "700"));
  145. ASSERT_TRUE(Overlaps("100", "150"));
  146. ASSERT_TRUE(Overlaps("100", "200"));
  147. ASSERT_TRUE(Overlaps("100", "300"));
  148. ASSERT_TRUE(Overlaps("100", "400"));
  149. ASSERT_TRUE(Overlaps("100", "500"));
  150. ASSERT_TRUE(Overlaps("375", "400"));
  151. ASSERT_TRUE(Overlaps("450", "450"));
  152. ASSERT_TRUE(Overlaps("450", "500"));
  153. ASSERT_TRUE(Overlaps("450", "700"));
  154. ASSERT_TRUE(Overlaps("600", "700"));
  155. }
  156. void AddBoundaryInputs(const InternalKeyComparator& icmp,
  157. const std::vector<FileMetaData*>& level_files,
  158. std::vector<FileMetaData*>* compaction_files);
  159. class AddBoundaryInputsTest : public testing::Test {
  160. public:
  161. std::vector<FileMetaData*> level_files_;
  162. std::vector<FileMetaData*> compaction_files_;
  163. std::vector<FileMetaData*> all_files_;
  164. InternalKeyComparator icmp_;
  165. AddBoundaryInputsTest() : icmp_(BytewiseComparator()) {}
  166. ~AddBoundaryInputsTest() {
  167. for (size_t i = 0; i < all_files_.size(); ++i) {
  168. delete all_files_[i];
  169. }
  170. all_files_.clear();
  171. }
  172. FileMetaData* CreateFileMetaData(uint64_t number, InternalKey smallest,
  173. InternalKey largest) {
  174. FileMetaData* f = new FileMetaData();
  175. f->number = number;
  176. f->smallest = smallest;
  177. f->largest = largest;
  178. all_files_.push_back(f);
  179. return f;
  180. }
  181. };
  182. TEST_F(AddBoundaryInputsTest, TestEmptyFileSets) {
  183. AddBoundaryInputs(icmp_, level_files_, &compaction_files_);
  184. ASSERT_TRUE(compaction_files_.empty());
  185. ASSERT_TRUE(level_files_.empty());
  186. }
  187. TEST_F(AddBoundaryInputsTest, TestEmptyLevelFiles) {
  188. FileMetaData* f1 =
  189. CreateFileMetaData(1, InternalKey("100", 2, kTypeValue),
  190. InternalKey(InternalKey("100", 1, kTypeValue)));
  191. compaction_files_.push_back(f1);
  192. AddBoundaryInputs(icmp_, level_files_, &compaction_files_);
  193. ASSERT_EQ(1, compaction_files_.size());
  194. ASSERT_EQ(f1, compaction_files_[0]);
  195. ASSERT_TRUE(level_files_.empty());
  196. }
  197. TEST_F(AddBoundaryInputsTest, TestEmptyCompactionFiles) {
  198. FileMetaData* f1 =
  199. CreateFileMetaData(1, InternalKey("100", 2, kTypeValue),
  200. InternalKey(InternalKey("100", 1, kTypeValue)));
  201. level_files_.push_back(f1);
  202. AddBoundaryInputs(icmp_, level_files_, &compaction_files_);
  203. ASSERT_TRUE(compaction_files_.empty());
  204. ASSERT_EQ(1, level_files_.size());
  205. ASSERT_EQ(f1, level_files_[0]);
  206. }
  207. TEST_F(AddBoundaryInputsTest, TestNoBoundaryFiles) {
  208. FileMetaData* f1 =
  209. CreateFileMetaData(1, InternalKey("100", 2, kTypeValue),
  210. InternalKey(InternalKey("100", 1, kTypeValue)));
  211. FileMetaData* f2 =
  212. CreateFileMetaData(1, InternalKey("200", 2, kTypeValue),
  213. InternalKey(InternalKey("200", 1, kTypeValue)));
  214. FileMetaData* f3 =
  215. CreateFileMetaData(1, InternalKey("300", 2, kTypeValue),
  216. InternalKey(InternalKey("300", 1, kTypeValue)));
  217. level_files_.push_back(f3);
  218. level_files_.push_back(f2);
  219. level_files_.push_back(f1);
  220. compaction_files_.push_back(f2);
  221. compaction_files_.push_back(f3);
  222. AddBoundaryInputs(icmp_, level_files_, &compaction_files_);
  223. ASSERT_EQ(2, compaction_files_.size());
  224. }
  225. TEST_F(AddBoundaryInputsTest, TestOneBoundaryFiles) {
  226. FileMetaData* f1 =
  227. CreateFileMetaData(1, InternalKey("100", 3, kTypeValue),
  228. InternalKey(InternalKey("100", 2, kTypeValue)));
  229. FileMetaData* f2 =
  230. CreateFileMetaData(1, InternalKey("100", 1, kTypeValue),
  231. InternalKey(InternalKey("200", 3, kTypeValue)));
  232. FileMetaData* f3 =
  233. CreateFileMetaData(1, InternalKey("300", 2, kTypeValue),
  234. InternalKey(InternalKey("300", 1, kTypeValue)));
  235. level_files_.push_back(f3);
  236. level_files_.push_back(f2);
  237. level_files_.push_back(f1);
  238. compaction_files_.push_back(f1);
  239. AddBoundaryInputs(icmp_, level_files_, &compaction_files_);
  240. ASSERT_EQ(2, compaction_files_.size());
  241. ASSERT_EQ(f1, compaction_files_[0]);
  242. ASSERT_EQ(f2, compaction_files_[1]);
  243. }
  244. TEST_F(AddBoundaryInputsTest, TestTwoBoundaryFiles) {
  245. FileMetaData* f1 =
  246. CreateFileMetaData(1, InternalKey("100", 6, kTypeValue),
  247. InternalKey(InternalKey("100", 5, kTypeValue)));
  248. FileMetaData* f2 =
  249. CreateFileMetaData(1, InternalKey("100", 2, kTypeValue),
  250. InternalKey(InternalKey("300", 1, kTypeValue)));
  251. FileMetaData* f3 =
  252. CreateFileMetaData(1, InternalKey("100", 4, kTypeValue),
  253. InternalKey(InternalKey("100", 3, kTypeValue)));
  254. level_files_.push_back(f2);
  255. level_files_.push_back(f3);
  256. level_files_.push_back(f1);
  257. compaction_files_.push_back(f1);
  258. AddBoundaryInputs(icmp_, level_files_, &compaction_files_);
  259. ASSERT_EQ(3, compaction_files_.size());
  260. ASSERT_EQ(f1, compaction_files_[0]);
  261. ASSERT_EQ(f3, compaction_files_[1]);
  262. ASSERT_EQ(f2, compaction_files_[2]);
  263. }
  264. TEST_F(AddBoundaryInputsTest, TestDisjoinFilePointers) {
  265. FileMetaData* f1 =
  266. CreateFileMetaData(1, InternalKey("100", 6, kTypeValue),
  267. InternalKey(InternalKey("100", 5, kTypeValue)));
  268. FileMetaData* f2 =
  269. CreateFileMetaData(1, InternalKey("100", 6, kTypeValue),
  270. InternalKey(InternalKey("100", 5, kTypeValue)));
  271. FileMetaData* f3 =
  272. CreateFileMetaData(1, InternalKey("100", 2, kTypeValue),
  273. InternalKey(InternalKey("300", 1, kTypeValue)));
  274. FileMetaData* f4 =
  275. CreateFileMetaData(1, InternalKey("100", 4, kTypeValue),
  276. InternalKey(InternalKey("100", 3, kTypeValue)));
  277. level_files_.push_back(f2);
  278. level_files_.push_back(f3);
  279. level_files_.push_back(f4);
  280. compaction_files_.push_back(f1);
  281. AddBoundaryInputs(icmp_, level_files_, &compaction_files_);
  282. ASSERT_EQ(3, compaction_files_.size());
  283. ASSERT_EQ(f1, compaction_files_[0]);
  284. ASSERT_EQ(f4, compaction_files_[1]);
  285. ASSERT_EQ(f3, compaction_files_[2]);
  286. }
  287. } // namespace leveldb