]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
test/crimson/seastore/test_btree_lba_manager: add LBABtree level unit tests
authorSamuel Just <sjust@redhat.com>
Fri, 22 Oct 2021 06:15:33 +0000 (23:15 -0700)
committerSamuel Just <sjust@redhat.com>
Mon, 25 Oct 2021 19:59:33 +0000 (19:59 +0000)
Signed-off-by: Samuel Just <sjust@redhat.com>
src/test/crimson/seastore/test_btree_lba_manager.cc

index 121b4c4d6e3cab7e16185b81abe621e1efb0949c..f3e34e6f0c4a4b257639c2aaa0c7fa43fe32e026 100644 (file)
@@ -114,6 +114,154 @@ struct btree_test_base :
   }
 };
 
+struct lba_btree_test : btree_test_base {
+  std::map<laddr_t, lba_map_val_t> check;
+
+  auto get_op_context(Transaction &t) {
+    return op_context_t{cache, t};
+  }
+
+  LBAManager::mkfs_ret test_structure_setup(Transaction &t) final {
+    return cache.get_root(
+      t
+    ).si_then([this, &t](RootBlockRef croot) {
+      auto mut_croot = cache.duplicate_for_write(
+       t, croot
+      )->cast<RootBlock>();
+      mut_croot->root.lba_root = LBABtree::mkfs(get_op_context(t));
+    });
+  }
+
+  void update_if_dirty(Transaction &t, LBABtree &btree, RootBlockRef croot) {
+    if (btree.is_root_dirty()) {
+      auto mut_croot = cache.duplicate_for_write(
+       t, croot
+      )->cast<RootBlock>();
+      mut_croot->root.lba_root = btree.get_root_undirty();
+    }
+  }
+
+  template <typename F>
+  auto lba_btree_update(F &&f) {
+    auto tref = cache.create_transaction(Transaction::src_t::MUTATE);
+    auto &t = *tref;
+    with_trans_intr(
+      t,
+      [this, tref=std::move(tref), f=std::forward<F>(f)](auto &t) mutable {
+       return cache.get_root(
+         t
+       ).si_then([this, f=std::move(f), &t](RootBlockRef croot) {
+         return seastar::do_with(
+           LBABtree(croot->root.lba_root),
+           [this, croot, f=std::move(f), &t](auto &btree) mutable {
+             return std::invoke(
+               std::move(f), btree, t
+             ).si_then([this, croot, &t, &btree] {
+               update_if_dirty(t, btree, croot);
+               return seastar::now();
+             });
+           });
+       }).si_then([this, tref=std::move(tref)]() mutable {
+         return submit_transaction(std::move(tref));
+       });
+      }).unsafe_get0();
+  }
+
+  template <typename F>
+  auto lba_btree_read(F &&f) {
+    auto t = cache.create_transaction(Transaction::src_t::READ);
+    return with_trans_intr(
+      *t,
+      [this, f=std::forward<F>(f)](auto &t) mutable {
+       return cache.get_root(
+         t
+       ).si_then([f=std::move(f), &t](RootBlockRef croot) mutable {
+         return seastar::do_with(
+           LBABtree(croot->root.lba_root),
+           [f=std::move(f), &t](auto &btree) mutable {
+             return std::invoke(
+               std::move(f), btree, t
+             );
+           });
+       });
+      }).unsafe_get0();
+  }
+
+  static auto get_map_val(extent_len_t len) {
+    return lba_map_val_t{0, P_ADDR_NULL, len, 0};
+  }
+
+  void insert(laddr_t addr, extent_len_t len) {
+    ceph_assert(check.count(addr) == 0);
+    check.emplace(addr, get_map_val(len));
+    lba_btree_update([=](auto &btree, auto &t) {
+      return btree.insert(
+       get_op_context(t), addr, get_map_val(len)
+      ).si_then([](auto){});
+    });
+  }
+
+  void remove(laddr_t addr) {
+    auto iter = check.find(addr);
+    ceph_assert(iter != check.end());
+    auto len = iter->second.len;
+    check.erase(iter++);
+    lba_btree_update([=](auto &btree, auto &t) {
+      return btree.lower_bound(
+       get_op_context(t), addr
+      ).si_then([this, len, addr, &btree, &t](auto iter) {
+       EXPECT_FALSE(iter.is_end());
+       EXPECT_TRUE(iter.get_key() == addr);
+       EXPECT_TRUE(iter.get_val().len == len);
+       return btree.remove(
+         get_op_context(t), iter 
+       );
+      });
+    });
+  }
+
+  void check_lower_bound(laddr_t addr) {
+    auto iter = check.lower_bound(addr);
+    auto result = lba_btree_read([=](auto &btree, auto &t) {
+      return btree.lower_bound(
+       get_op_context(t), addr
+      ).si_then([](auto iter)
+               -> std::optional<std::pair<const laddr_t, const lba_map_val_t>> {
+       if (iter.is_end()) {
+         return std::nullopt;
+       } else {
+         return std::make_optional(
+           std::make_pair(iter.get_key(), iter.get_val()));
+       }
+      });
+    });
+    if (iter == check.end()) {
+      EXPECT_FALSE(result);
+    } else {
+      EXPECT_TRUE(result);
+      decltype(result) to_check = *iter;
+      EXPECT_EQ(to_check, *result);
+    }
+  }
+};
+
+TEST_F(lba_btree_test, basic)
+{
+  run_async([this] {
+    constexpr unsigned total = 16<<10;
+    for (unsigned i = 0; i < total; i += 16) {
+      insert(i, 8);
+    }
+
+    for (unsigned i = 0; i < total; i += 16) {
+      check_lower_bound(i);
+      check_lower_bound(i + 4);
+      check_lower_bound(i + 8);
+      check_lower_bound(i + 12);
+    }
+  });
+}
+
 struct btree_lba_manager_test : btree_test_base {
   BtreeLBAManagerRef lba_manager;