--- /dev/null
+// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
+// vim: ts=8 sw=2 smarttab
+
+#include "test/crimson/seastore/test_block.h"
+
+namespace crimson::os::seastore {
+
+
+ceph::bufferlist TestBlock::get_delta() {
+ ceph::bufferlist bl;
+ ::encode(delta, bl);
+ return bl;
+}
+
+
+void TestBlock::apply_delta(const ceph::bufferlist &bl) {
+ auto biter = bl.begin();
+ decltype(delta) deltas;
+ ::decode(deltas, biter);
+ for (auto &&d : deltas) {
+ set_contents(d.val, d.offset, d.len);
+ }
+}
+
+}
#pragma once
+#include <random>
+
#include "crimson/os/seastore/transaction_manager.h"
namespace crimson::os::seastore {
}
};
+struct test_block_delta_t {
+ int8_t val = 0;
+ uint16_t offset = 0;
+ uint16_t len = 0;
+
+
+ DENC(test_block_delta_t, v, p) {
+ DENC_START(1, 1, p);
+ denc(v.val, p);
+ denc(v.offset, p);
+ denc(v.len, p);
+ DENC_FINISH(p);
+ }
+};
+
inline std::ostream &operator<<(
std::ostream &lhs, const test_extent_desc_t &rhs) {
return lhs << "test_extent_desc_t(len=" << rhs.len
constexpr static segment_off_t SIZE = 4<<10;
using Ref = TCachedExtentRef<TestBlock>;
- TestBlock(ceph::bufferptr &&ptr) : LogicalCachedExtent(std::move(ptr)) {}
- TestBlock(const TestBlock &other) : LogicalCachedExtent(other) {}
+ std::vector<test_block_delta_t> delta = {};
+
+ TestBlock(ceph::bufferptr &&ptr)
+ : LogicalCachedExtent(std::move(ptr)) {}
+ TestBlock(const TestBlock &other)
+ : LogicalCachedExtent(other) {}
CachedExtentRef duplicate_for_write() final {
return CachedExtentRef(new TestBlock(*this));
return TYPE;
}
- ceph::bufferlist get_delta() final {
- return ceph::bufferlist();
+ ceph::bufferlist get_delta() final;
+
+ void set_contents(char c, uint16_t offset, uint16_t len) {
+ ::memset(get_bptr().c_str() + offset, c, len);
+ delta.push_back({c, offset, len});
}
void set_contents(char c) {
- ::memset(get_bptr().c_str(), c, get_length());
+ set_contents(c, 0, get_length());
}
int checksum() {
return { get_length(), get_crc32c(1) };
}
- void apply_delta(const ceph::bufferlist &bl) final {
- ceph_assert(0 == "TODO");
- }
+ void apply_delta(const ceph::bufferlist &bl) final;
};
using TestBlockRef = TCachedExtentRef<TestBlock>;
+struct test_block_mutator_t {
+ std::uniform_int_distribution<int8_t>
+ contents_distribution = std::uniform_int_distribution<int8_t>(
+ std::numeric_limits<int8_t>::min(),
+ std::numeric_limits<int8_t>::max());
+
+ std::uniform_int_distribution<uint16_t>
+ offset_distribution = std::uniform_int_distribution<uint16_t>(
+ 0, TestBlock::SIZE - 1);
+
+ std::default_random_engine generator = std::default_random_engine(0);
+
+ std::uniform_int_distribution<uint16_t> length_distribution(uint16_t offset) {
+ return std::uniform_int_distribution<uint16_t>(
+ 0, TestBlock::SIZE - offset - 1);
+ }
+
+
+ void mutate(TestBlock &block) {
+ auto offset = offset_distribution(generator);
+ block.set_contents(
+ contents_distribution(generator),
+ offset,
+ length_distribution(offset)(generator));
+ }
+};
+
}
+
+WRITE_CLASS_DENC_BOUNDED(crimson::os::seastore::test_block_delta_t)
return extent;
}
+ void replay() {
+ tm.close().unsafe_get();
+ tm.mount().unsafe_get();
+ }
+
void check_mappings() {
auto t = create_transaction();
check_mappings(t);
return ext;
}
+ test_block_mutator_t mutator;
TestBlockRef mutate_extent(
test_transaction_t &t,
- TestBlockRef ref,
- char contents) {
+ TestBlockRef ref) {
ceph_assert(t.mappings.count(ref->get_laddr()));
ceph_assert(t.mappings[ref->get_laddr()].desc.len == ref->get_length());
auto ext = tm.get_mutable_extent(*t.t, ref)->cast<TestBlock>();
EXPECT_EQ(ext->get_laddr(), ref->get_laddr());
EXPECT_EQ(ext->get_desc(), ref->get_desc());
- ext->set_contents(contents);
+ mutator.mutate(*ext);
t.mappings[ext->get_laddr()].update(ext->get_desc());
return ext;
}
submit_transaction(std::move(t));
check_mappings();
}
+ replay();
{
auto t = create_transaction();
auto ext = get_extent(
t,
ADDR,
SIZE);
- auto mut = mutate_extent(t, ext, 'c');
+ auto mut = mutate_extent(t, ext);
check_mappings(t);
check_mappings();
submit_transaction(std::move(t));
check_mappings();
}
+ replay();
+ check_mappings();
});
}
submit_transaction(std::move(t));
check_mappings();
}
+ replay();
{
auto t = create_transaction();
inc_ref(t, ADDR);
submit_transaction(std::move(t));
check_mappings();
}
+ replay();
{
auto t = create_transaction();
dec_ref(t, ADDR);