diff --git a/unit-tests/metadata_checker_t.cc b/unit-tests/metadata_checker_t.cc index a27e867..e56aa07 100644 --- a/unit-tests/metadata_checker_t.cc +++ b/unit-tests/metadata_checker_t.cc @@ -101,7 +101,8 @@ namespace { metadata::ptr md(new metadata(bm_, metadata::CREATE, 128, 10240)); emitter::ptr restorer = create_restore_emitter(md); - restorer->begin_superblock("test-generated", 0, 0, 128, 10240, boost::optional()); + restorer->begin_superblock("test-generated", 0, 0, 128, 10240, + boost::optional()); list::const_iterator it, end = devices_.end(); for (it = devices_.begin(); it != end; ++it) { @@ -122,6 +123,70 @@ namespace { list devices_; }; + class devices_visitor : public detail_tree::visitor { + public: + struct node_info { + bool leaf; + unsigned level; + block_address b; + range keys; + }; + + typedef btree_detail::node_location node_location; + typedef boost::shared_ptr ptr; + + virtual bool visit_internal(node_location const &loc, + detail_tree::internal_node const &n) { + record_node(false, loc.level, loc.key, n); + return true; + } + + virtual bool visit_internal_leaf(node_location const &loc, + detail_tree::internal_node const &n) { + record_node(true, loc.level, loc.key, n); + return true; + } + + + virtual bool visit_leaf(node_location const &loc, + detail_tree::leaf_node const &n) { + record_node(true, loc.level, loc.key, n); + return true; + } + + virtual void visit_complete() { + } + + list const &get_nodes() const { + return nodes_; + } + + private: + template + void record_node(bool leaf, unsigned level, + boost::optional key, + N const &n) { + node_info ni; + + ni.leaf = leaf; + ni.level = level; + ni.b = n.get_location(); + + if (n.get_nr_entries()) + ni.keys = range(n.key_at(0)); + else { + if (key) + ni.keys = range(*key); + else + ni.keys = range(); + } + + nodes_.push_back(ni); + } + + list nodes_; + }; + //-------------------------------- class damage_visitor_mock : public metadata_damage_visitor { @@ -141,7 +206,7 @@ namespace { class MetadataCheckerTests : public Test { public: MetadataCheckerTests() - : bm_(create_bm()), + : bm_(create_bm(NR_BLOCKS)), builder_(bm_) { } @@ -264,4 +329,28 @@ TEST_F(DeviceCheckerTests, fails_with_corrupt_root) (*damage->begin())->visit(v); } +TEST_F(DeviceCheckerTests, damaging_some_btree_nodes_results_in_the_correct_devices_being_flagged_as_missing) +{ + metadata_builder &b = get_builder(); + + for (unsigned i = 0; i < 1000; i++) + b.add_device(i); + + b.build(); + + devices_visitor::ptr scanner(new devices_visitor); + transaction_manager::ptr tm = open_temporary_tm(bm_); + detail_tree::ptr devices(new detail_tree(tm, devices_root(), + device_details_traits::ref_counter())); + devices->visit_depth_first(scanner); + + list::const_iterator it, end = scanner->get_nodes().end(); + for (it = scanner->get_nodes().begin(); it != end; ++it) { + cerr << "block " << it->b << ", keys" << it->keys << endl; + } + + damage_list_ptr damage = mk_checker()->check(); + ASSERT_THAT(damage->size(), Eq(1u)); +} + //----------------------------------------------------------------