Skip to content

Commit

Permalink
generator - improve test coverage
Browse files Browse the repository at this point in the history
  • Loading branch information
petiaccja committed May 8, 2024
1 parent 869b4ec commit 7416c64
Show file tree
Hide file tree
Showing 2 changed files with 105 additions and 13 deletions.
28 changes: 16 additions & 12 deletions include/asyncpp/generator.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -63,33 +63,38 @@ namespace impl_generator {
explicit iterator(promise_type* promise) : m_promise(promise) {}

reference operator*() const {
assert(valid() && "iterator not dereferencable");
assert(dereferenceable() && "iterator not dereferencable");
return m_promise->get_result().get_or_throw();
}

iterator& operator++() {
assert(valid() && "iterator not incrementable");
get_handle().resume();
assert(incrementable() && "iterator not incrementable");
m_promise->get_result().clear();
if (!get_handle().done()) {
get_handle().resume();
}
return *this;
}

iterator operator++(int) {
auto copy = *this;
void operator++(int) {
++*this;
return copy;
}

bool operator==(const iterator& rhs) const noexcept {
return (m_promise == rhs.m_promise) || (!valid() && !rhs.m_promise);
return (m_promise == rhs.m_promise) || (!incrementable() && !rhs.incrementable());
}

bool operator!=(const iterator& rhs) const noexcept {
return !operator==(rhs);
}

private:
bool valid() const noexcept {
return m_promise && !get_handle().done();
bool dereferenceable() const noexcept {
return m_promise->get_result().has_value();
}

bool incrementable() const noexcept {
return m_promise && m_promise->get_result().has_value();
}

auto get_handle() const noexcept {
Expand All @@ -113,11 +118,10 @@ class [[nodiscard]] generator {

generator(promise_type* promise) : m_promise(promise) {}
generator() = default;
generator(generator&& rhs) noexcept : m_promise(rhs.m_promise) { rhs.m_promise = nullptr; }
generator(generator&& rhs) noexcept : m_promise(std::exchange(rhs.m_promise, nullptr)) {}
generator& operator=(generator&& rhs) noexcept {
release();
m_promise = rhs.m_promise;
rhs.m_promise = nullptr;
m_promise = std::exchange(rhs.m_promise, nullptr);
return *this;
}
generator(const generator&) = delete;
Expand Down
90 changes: 89 additions & 1 deletion test/test_generator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ TEST_CASE("Generator: sequence of references", "[Generator]") {
}


TEST_CASE("Generator: sequence of mvoeables", "[Generator]") {
TEST_CASE("Generator: sequence of movables", "[Generator]") {
static const auto coro = [](int count) -> generator<std::unique_ptr<int>> {
for (int i = 0; i < count; ++i) {
co_yield std::make_unique<int>(i);
Expand All @@ -48,4 +48,92 @@ TEST_CASE("Generator: sequence of mvoeables", "[Generator]") {
values.push_back(*item);
}
REQUIRE(values == std::vector{ 0, 1, 2, 3 });
}


TEST_CASE("Generator: const iterators", "[Generator]") {
static const auto coro = []() -> generator<int> {
co_yield 0;
};
const auto g = coro();
std::vector<int> values;
for (auto it = g.cbegin(); it != g.cend(); ++it) {
values.push_back(*it);
}
REQUIRE(values == std::vector{ 0 });
}


TEST_CASE("Generator: unhandled exceptions", "[Generator]") {
static const auto coro = []() -> generator<int> {
throw std::runtime_error("test");
co_return;
};
const auto g = coro();
REQUIRE_THROWS_AS(*g.begin(), std::runtime_error);
}


TEST_CASE("Generator: iterator++", "[Generator]") {
static const auto coro = []() -> generator<int> {
co_yield 0;
};
const auto g = coro();
auto it = g.begin();
it++;
REQUIRE(it == g.end());
}


TEST_CASE("Generator: ++iterator", "[Generator]") {
static const auto coro = []() -> generator<int> {
co_yield 0;
};
const auto g = coro();
auto it = g.begin();
++it;
REQUIRE(it == g.end());
}


TEST_CASE("Generator: iterator begin", "[Generator]") {
static const auto coro = []() -> generator<int> {
co_return;
};
const auto g = coro();
auto it = g.begin();
REQUIRE(it == g.begin());
}


TEST_CASE("Generator: move ctor", "[Generator]") {
static const auto coro = []() -> generator<int> {
co_yield 0;
co_yield 1;
};
auto g = coro();
auto m = std::move(g);
auto it = m.begin();
REQUIRE(*it == 0);
++it;
REQUIRE(*it == 1);
++it;
REQUIRE(it == m.end());
}


TEST_CASE("Generator: move assign", "[Generator]") {
static const auto coro = []() -> generator<int> {
co_yield 0;
co_yield 1;
};
auto g = coro();
generator<int> m = coro();
m = std::move(g);
auto it = m.begin();
REQUIRE(*it == 0);
++it;
REQUIRE(*it == 1);
++it;
REQUIRE(it == m.end());
}

0 comments on commit 7416c64

Please sign in to comment.