aboutsummaryrefslogtreecommitdiffstats
path: root/nihil.core/generator.test.cc
diff options
context:
space:
mode:
authorLexi Winter <lexi@le-fay.org>2025-07-02 05:49:47 +0100
committerLexi Winter <lexi@le-fay.org>2025-07-02 05:49:47 +0100
commitebe4cb0bdeabd06a31072547af47cacaab7f78c0 (patch)
tree65a81c2c86260b595107ee6c5505583f9afaf39d /nihil.core/generator.test.cc
parent5adeb648f74c1771164c0686d6e0fc584cf36d9e (diff)
downloadnihil-ebe4cb0bdeabd06a31072547af47cacaab7f78c0.tar.gz
nihil-ebe4cb0bdeabd06a31072547af47cacaab7f78c0.tar.bz2
replace nihil::generator
the new implementation is much simpler and PD-licensed. the only downside is it doesn't support elements_of. while here, move it to nihil.core.
Diffstat (limited to 'nihil.core/generator.test.cc')
-rw-r--r--nihil.core/generator.test.cc109
1 files changed, 109 insertions, 0 deletions
diff --git a/nihil.core/generator.test.cc b/nihil.core/generator.test.cc
new file mode 100644
index 0000000..1fc0f22
--- /dev/null
+++ b/nihil.core/generator.test.cc
@@ -0,0 +1,109 @@
+// This source code is released into the public domain.
+
+#include <catch2/catch_test_macros.hpp>
+
+import nihil.std;
+import nihil.core;
+
+namespace {
+inline auto constexpr test_tags = "[nihil][nihil.generator]";
+
+SCENARIO("A generator that yields values", test_tags)
+{
+ GIVEN ("A generator that yields values") {
+ auto fn = [&]() -> nihil::generator<int> {
+ co_yield 1;
+ co_yield 2;
+ };
+
+ THEN ("The generator yields the original values") {
+ REQUIRE(std::ranges::equal(fn(), std::vector{1, 2}));
+ }
+ }
+}
+
+SCENARIO("A generator that yields references", test_tags)
+{
+ GIVEN ("A generator that yields references") {
+ auto one = 1, two = 2;
+ auto fn = [&]() -> nihil::generator<int &> {
+ co_yield one;
+ co_yield two;
+ };
+ auto range = fn();
+
+ THEN ("The references refer to the original values") {
+ auto it = std::ranges::begin(range);
+ REQUIRE(&*it == &one);
+ ++it;
+ REQUIRE(&*it == &two);
+ ++it;
+ REQUIRE(it == std::ranges::end(range));
+ }
+ }
+}
+
+SCENARIO("A generator that yields pointers", test_tags)
+{
+ GIVEN ("A generator that yields pointers") {
+ auto one = 1, two = 2;
+ auto fn = [&]() -> nihil::generator<int *> {
+ co_yield &one;
+ co_yield &two;
+ };
+
+ THEN ("The pointers point to the original values") {
+ REQUIRE(std::ranges::equal(fn(), std::vector{&one, &two}));
+ }
+ }
+}
+
+SCENARIO("A generator that yields lvalues", test_tags)
+{
+ GIVEN ("A generator that yields pointers") {
+ auto one = 1, two = 2;
+ auto fn = [&]() -> nihil::generator<int> {
+ co_yield one;
+ co_yield two;
+ };
+
+ THEN ("The pointers point to the original values") {
+ REQUIRE(std::ranges::equal(fn(), std::vector{1, 2}));
+ }
+ }
+}
+
+TEST_CASE("generator: exceptions", "[generator]")
+{
+ auto fn = []() -> nihil::generator<int> {
+ co_yield 1;
+ throw std::runtime_error("test");
+ };
+
+ auto range = fn();
+ auto it = std::ranges::begin(range);
+ REQUIRE(*it == 1);
+ REQUIRE_THROWS_AS(it++, std::runtime_error);
+}
+
+#if 0
+// TODO: Re-enable this test once we have a standard-compliant generator.
+TEST_CASE("generator: elements_of", "[generator]")
+{
+ auto fn1 = [] -> nihil::generator<int> {
+ co_yield 1;
+ co_yield 2;
+ co_yield 3;
+ };
+
+ auto fn2 = [&fn1] -> nihil::generator<int> {
+ co_yield nihil::elements_of(fn1());
+ };
+
+ auto values = std::vector<int>();
+ std::ranges::copy(fn2(), std::back_inserter(values));
+
+ REQUIRE(values == std::vector{1, 2, 3});
+}
+#endif
+} // anonymous namespace