Pull subtracting_span_iterator out into separate file + test.
This commit is contained in:
parent
bf75b5c827
commit
4cb19a06ba
101
persistent-data/space-maps/subtracting_span_iterator.h
Normal file
101
persistent-data/space-maps/subtracting_span_iterator.h
Normal file
@ -0,0 +1,101 @@
|
|||||||
|
#ifndef SPAN_ITERATOR_H
|
||||||
|
#define SPAN_ITERATOR_H
|
||||||
|
|
||||||
|
#include "persistent-data/space_map.h"
|
||||||
|
|
||||||
|
#include <set>
|
||||||
|
|
||||||
|
//----------------------------------------------------------------
|
||||||
|
|
||||||
|
namespace persistent_data {
|
||||||
|
// FIXME: rewrite with tests using the run_list stuff.
|
||||||
|
class subtracting_span_iterator : public space_map::span_iterator {
|
||||||
|
public:
|
||||||
|
typedef set<block_address> block_set;
|
||||||
|
typedef space_map::span span;
|
||||||
|
|
||||||
|
subtracting_span_iterator(span_iterator &sub_it,
|
||||||
|
block_set const &forbidden_blocks)
|
||||||
|
: sub_it_(sub_it),
|
||||||
|
forbidden_blocks_(forbidden_blocks),
|
||||||
|
current_begin_() {
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual maybe_span first() {
|
||||||
|
current_span_ = sub_it_.first();
|
||||||
|
|
||||||
|
if (current_span_)
|
||||||
|
current_begin_ = current_span_->first;
|
||||||
|
|
||||||
|
return next();
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual maybe_span next() {
|
||||||
|
maybe_span r;
|
||||||
|
|
||||||
|
while (more_spans()) {
|
||||||
|
r = next_();
|
||||||
|
if (r)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool more_spans() const {
|
||||||
|
return current_span_;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool span_consumed() const {
|
||||||
|
return current_begin_ == current_span_->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool forbidden_block(block_address b) const {
|
||||||
|
return forbidden_blocks_.count(b) > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void skip_forbidden_blocks() {
|
||||||
|
while (!span_consumed() && forbidden_block(current_begin_))
|
||||||
|
current_begin_++;
|
||||||
|
}
|
||||||
|
|
||||||
|
span get_span() {
|
||||||
|
block_address b = current_begin_;
|
||||||
|
|
||||||
|
while (!span_consumed() && !forbidden_block(current_begin_))
|
||||||
|
current_begin_++;
|
||||||
|
|
||||||
|
return span(b, current_begin_);
|
||||||
|
}
|
||||||
|
|
||||||
|
void get_current_span_from_sub_it() {
|
||||||
|
current_span_ = sub_it_.next();
|
||||||
|
current_begin_ = current_span_->first;
|
||||||
|
}
|
||||||
|
|
||||||
|
maybe_span next_() {
|
||||||
|
if (span_consumed())
|
||||||
|
get_current_span_from_sub_it();
|
||||||
|
|
||||||
|
if (!more_spans())
|
||||||
|
return maybe_span();
|
||||||
|
|
||||||
|
skip_forbidden_blocks();
|
||||||
|
|
||||||
|
if (!span_consumed())
|
||||||
|
return maybe_span(get_span());
|
||||||
|
else
|
||||||
|
return maybe_span();
|
||||||
|
}
|
||||||
|
|
||||||
|
span_iterator &sub_it_;
|
||||||
|
block_set const &forbidden_blocks_;
|
||||||
|
maybe_span current_span_;
|
||||||
|
block_address current_begin_;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------
|
||||||
|
|
||||||
|
#endif
|
183
unit-tests/span_iterator_t.cc
Normal file
183
unit-tests/span_iterator_t.cc
Normal file
@ -0,0 +1,183 @@
|
|||||||
|
#include "gmock/gmock.h"
|
||||||
|
|
||||||
|
#include "persistent-data/space-maps/subtracting_span_iterator.h"
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
using namespace persistent_data;
|
||||||
|
using namespace testing;
|
||||||
|
|
||||||
|
//----------------------------------------------------------------
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
typedef space_map::span span;
|
||||||
|
typedef space_map::maybe_span maybe_span;
|
||||||
|
|
||||||
|
class regular_span_iterator : public space_map::span_iterator {
|
||||||
|
public:
|
||||||
|
regular_span_iterator(block_address span_length,
|
||||||
|
block_address gap_length,
|
||||||
|
unsigned span_count)
|
||||||
|
: span_length_(span_length),
|
||||||
|
gap_length_(gap_length),
|
||||||
|
span_count_(span_count),
|
||||||
|
current_span_(0) {
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual maybe_span first() {
|
||||||
|
current_span_ = 0;
|
||||||
|
return current_span();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
virtual maybe_span next() {
|
||||||
|
current_span_++;
|
||||||
|
return current_span();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
maybe_span current_span() const {
|
||||||
|
if (current_span_ >= span_count_)
|
||||||
|
return maybe_span();
|
||||||
|
|
||||||
|
block_address begin = (span_length_ + gap_length_) * current_span_;
|
||||||
|
block_address end = begin + span_length_;
|
||||||
|
return maybe_span(space_map::span(begin, end));
|
||||||
|
}
|
||||||
|
|
||||||
|
block_address span_length_;
|
||||||
|
block_address gap_length_;
|
||||||
|
unsigned span_count_;
|
||||||
|
|
||||||
|
unsigned current_span_;
|
||||||
|
};
|
||||||
|
|
||||||
|
class span_iterator_mock : public space_map::span_iterator {
|
||||||
|
public:
|
||||||
|
MOCK_METHOD0(first, maybe_span());
|
||||||
|
MOCK_METHOD0(next, maybe_span());
|
||||||
|
};
|
||||||
|
|
||||||
|
class SpanItTests : public Test {
|
||||||
|
public:
|
||||||
|
SpanItTests()
|
||||||
|
: it(mock_it, forbidden) {
|
||||||
|
|
||||||
|
EXPECT_CALL(mock_it, first()).
|
||||||
|
Times(1).
|
||||||
|
WillOnce(Return(maybe_span(span(23, 47))));
|
||||||
|
EXPECT_CALL(mock_it, next()).
|
||||||
|
Times(1).
|
||||||
|
WillOnce(Return(maybe_span(span(59, 103))));
|
||||||
|
}
|
||||||
|
|
||||||
|
span_iterator_mock mock_it;
|
||||||
|
set<block_address> forbidden;
|
||||||
|
subtracting_span_iterator it;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------
|
||||||
|
|
||||||
|
TEST(RegularSpanItTests, regular_span_iterator)
|
||||||
|
{
|
||||||
|
regular_span_iterator it(5, 3, 5);
|
||||||
|
|
||||||
|
static struct {
|
||||||
|
block_address b;
|
||||||
|
block_address e;
|
||||||
|
} expected[] = {
|
||||||
|
{0, 5},
|
||||||
|
{8, 13},
|
||||||
|
{16, 21},
|
||||||
|
{24, 29},
|
||||||
|
{32, 37}
|
||||||
|
};
|
||||||
|
|
||||||
|
ASSERT_THAT(it.first(), Eq(maybe_span(span(expected[0].b, expected[0].e))));
|
||||||
|
|
||||||
|
for (unsigned count = 1; count < 5; count++)
|
||||||
|
ASSERT_THAT(it.next(), Eq(maybe_span(span(expected[count].b, expected[count].e))));
|
||||||
|
|
||||||
|
ASSERT_THAT(it.next(), Eq(maybe_span()));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(SpanItTests, sub_it_with_no_removed_blocks)
|
||||||
|
{
|
||||||
|
ASSERT_THAT(it.first(), Eq(maybe_span(span(23, 47))));
|
||||||
|
ASSERT_THAT(it.next(), Eq(maybe_span(span(59, 103))));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(SpanItTests, sub_it_with_removed_first_block)
|
||||||
|
{
|
||||||
|
forbidden.insert(23);
|
||||||
|
|
||||||
|
ASSERT_THAT(it.first(), Eq(maybe_span(span(24, 47))));
|
||||||
|
ASSERT_THAT(it.next(), Eq(maybe_span(span(59, 103))));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(SpanItTests, sub_it_with_removed_run_overlapping_front_of_first_block)
|
||||||
|
{
|
||||||
|
for (block_address i = 19; i < 26; i++)
|
||||||
|
forbidden.insert(i);
|
||||||
|
|
||||||
|
ASSERT_THAT(it.first(), Eq(maybe_span(span(26, 47))));
|
||||||
|
ASSERT_THAT(it.next(), Eq(maybe_span(span(59, 103))));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(SpanItTests, sub_it_with_removed_mid_block)
|
||||||
|
{
|
||||||
|
forbidden.insert(40);
|
||||||
|
|
||||||
|
ASSERT_THAT(it.first(), Eq(maybe_span(span(23, 40))));
|
||||||
|
ASSERT_THAT(it.next(), Eq(maybe_span(span(41, 47))));
|
||||||
|
ASSERT_THAT(it.next(), Eq(maybe_span(span(59, 103))));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(SpanItTests, sub_it_with_removed_run_mid_block)
|
||||||
|
{
|
||||||
|
for (block_address i = 26; i < 36; i++)
|
||||||
|
forbidden.insert(i);
|
||||||
|
|
||||||
|
ASSERT_THAT(it.first(), Eq(maybe_span(span(23, 26))));
|
||||||
|
ASSERT_THAT(it.next(), Eq(maybe_span(span(36, 47))));
|
||||||
|
ASSERT_THAT(it.next(), Eq(maybe_span(span(59, 103))));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(SpanItTests, sub_it_with_removed_end_block)
|
||||||
|
{
|
||||||
|
forbidden.insert(46);
|
||||||
|
|
||||||
|
ASSERT_THAT(it.first(), Eq(maybe_span(span(23, 46))));
|
||||||
|
ASSERT_THAT(it.next(), Eq(maybe_span(span(59, 103))));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(SpanItTests, sub_it_with_removed_run_end_block)
|
||||||
|
{
|
||||||
|
for (block_address i = 26; i < 50; i++)
|
||||||
|
forbidden.insert(i);
|
||||||
|
|
||||||
|
ASSERT_THAT(it.first(), Eq(maybe_span(span(23, 26))));
|
||||||
|
ASSERT_THAT(it.next(), Eq(maybe_span(span(59, 103))));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(SpanItTests, sub_it_with_removed_run_overlapping_2_blocks)
|
||||||
|
{
|
||||||
|
for (block_address i = 26; i < 70; i++)
|
||||||
|
forbidden.insert(i);
|
||||||
|
|
||||||
|
ASSERT_THAT(it.first(), Eq(maybe_span(span(23, 26))));
|
||||||
|
ASSERT_THAT(it.next(), Eq(maybe_span(span(70, 103))));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(SpanItTests, sub_it_with_removed_intermediate_blocks)
|
||||||
|
{
|
||||||
|
forbidden.insert(53);
|
||||||
|
forbidden.insert(54);
|
||||||
|
forbidden.insert(57);
|
||||||
|
forbidden.insert(58);
|
||||||
|
|
||||||
|
ASSERT_THAT(it.first(), Eq(maybe_span(span(23, 47))));
|
||||||
|
ASSERT_THAT(it.next(), Eq(maybe_span(span(59, 103))));
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------
|
Loading…
Reference in New Issue
Block a user