From a803f92003749a4eb493a7461265b010441ef59d Mon Sep 17 00:00:00 2001 From: archi Date: Fri, 26 Aug 2022 16:45:06 +0300 Subject: [PATCH] Introduce `HeapSize()` This PR adds the possibility to determine for a chain of eventuals the maximum amount of heap memory that needs to get allocated. --- eventuals/catch.h | 5 +++++ eventuals/closure.h | 5 +++++ eventuals/concurrent-ordered.h | 9 ++++++++ eventuals/concurrent.h | 5 +++++ eventuals/conditional.h | 5 +++++ eventuals/do-all.h | 5 +++++ eventuals/eventual.h | 5 +++++ eventuals/expected.h | 5 +++++ eventuals/filter.h | 5 +++++ eventuals/finally.h | 5 +++++ eventuals/flat-map.h | 5 +++++ eventuals/head.h | 5 +++++ eventuals/if.h | 5 +++++ eventuals/lock.h | 13 +++++++++++ eventuals/loop.h | 5 +++++ eventuals/map.h | 5 +++++ eventuals/on-begin.h | 5 +++++ eventuals/on-ended.h | 5 +++++ eventuals/raise.h | 5 +++++ eventuals/range.h | 5 +++++ eventuals/reduce.h | 5 +++++ eventuals/repeat.h | 5 +++++ eventuals/scheduler.h | 13 +++++++++++ eventuals/stream.h | 5 +++++ eventuals/take.h | 9 ++++++++ eventuals/terminal.h | 5 +++++ eventuals/then.h | 9 ++++++++ eventuals/until.h | 5 +++++ test/catch.cc | 26 ++++++++++++++++++++++ test/closure.cc | 17 +++++++++++++++ test/concurrent/success.cc | 2 ++ test/conditional.cc | 19 ++++++++++++++++ test/do-all.cc | 17 +++++++++++++++ test/eventual.cc | 16 ++++++++++++++ test/filter.cc | 22 ++++++++++++++++++- test/finally.cc | 19 +++++++++++++++- test/flat-map.cc | 16 ++++++++++++++ test/if.cc | 20 +++++++++++++++++ test/lock.cc | 6 +++++ test/range.cc | 15 ++++++++++++- test/repeat.cc | 2 ++ test/stream.cc | 34 +++++++++++++++++++++++++++-- test/take.cc | 40 +++++++++++++++++++++++++++++++++- 43 files changed, 433 insertions(+), 6 deletions(-) diff --git a/eventuals/catch.h b/eventuals/catch.h index 5516e40a1..d78cc5f53 100644 --- a/eventuals/catch.h +++ b/eventuals/catch.h @@ -7,6 +7,7 @@ #include "eventuals/terminal.h" #include "eventuals/then.h" #include "eventuals/type-traits.h" +#include "stout/bytes.h" //////////////////////////////////////////////////////////////////////// @@ -174,6 +175,10 @@ struct _Catch final { // the handler. } + Bytes StaticHeapSize() { + return Bytes(0) + k_.StaticHeapSize(); + } + std::tuple catch_handlers_; Interrupt* interrupt_ = nullptr; diff --git a/eventuals/closure.h b/eventuals/closure.h index e397019ed..4dc4d705d 100644 --- a/eventuals/closure.h +++ b/eventuals/closure.h @@ -5,6 +5,7 @@ #include "eventuals/compose.h" #include "eventuals/interrupt.h" #include "eventuals/type-erased-stream.h" +#include "stout/bytes.h" //////////////////////////////////////////////////////////////////////// @@ -63,6 +64,10 @@ struct _Closure final { return *continuation_; } + Bytes StaticHeapSize() { + return Bytes(0) + k_.StaticHeapSize(); + } + F_ f_; Interrupt* interrupt_ = nullptr; diff --git a/eventuals/concurrent-ordered.h b/eventuals/concurrent-ordered.h index dd1951dcf..7db3993fd 100644 --- a/eventuals/concurrent-ordered.h +++ b/eventuals/concurrent-ordered.h @@ -13,6 +13,7 @@ #include "eventuals/map.h" #include "eventuals/stream.h" #include "eventuals/terminal.h" +#include "stout/bytes.h" ///////////////////////////////////////////////////////////////////// @@ -94,6 +95,10 @@ struct _ReorderAdaptor final { upstream_->Done(); } + Bytes StaticHeapSize() { + return Bytes(0) + k_.StaticHeapSize(); + } + TypeErasedStream* upstream_ = nullptr; std::map> buffer_; @@ -208,6 +213,10 @@ struct _ConcurrentOrderedAdaptor final { upstream_->Done(); } + Bytes StaticHeapSize() { + return Bytes(0) + k_.StaticHeapSize(); + } + bool ended_ = false; std::optional index_; diff --git a/eventuals/concurrent.h b/eventuals/concurrent.h index 10df0818b..9e4c64b8f 100644 --- a/eventuals/concurrent.h +++ b/eventuals/concurrent.h @@ -14,6 +14,7 @@ #include "eventuals/terminal.h" #include "eventuals/then.h" #include "eventuals/until.h" +#include "stout/bytes.h" //////////////////////////////////////////////////////////////////////// @@ -705,6 +706,10 @@ struct _Concurrent final { handler_->Install(); } + Bytes StaticHeapSize() { + return Bytes(0) + k_.StaticHeapSize(); + } + Adaptor adaptor_; TypeErasedStream* stream_ = nullptr; diff --git a/eventuals/conditional.h b/eventuals/conditional.h index e666a0d21..16203a596 100644 --- a/eventuals/conditional.h +++ b/eventuals/conditional.h @@ -2,6 +2,7 @@ #include "eventuals/then.h" // For '_Then::Adaptor'. #include "eventuals/type-traits.h" // For 'type_identity'. +#include "stout/bytes.h" //////////////////////////////////////////////////////////////////////// @@ -78,6 +79,10 @@ struct _Conditional { k_.Register(interrupt); } + Bytes StaticHeapSize() { + return Bytes(0) + k_.StaticHeapSize(); + } + Condition_ condition_; Then_ then_; Else_ else_; diff --git a/eventuals/do-all.h b/eventuals/do-all.h index 1fe8ef2d4..3e24b09fb 100644 --- a/eventuals/do-all.h +++ b/eventuals/do-all.h @@ -8,6 +8,7 @@ #include "eventuals/compose.h" #include "eventuals/scheduler.h" #include "eventuals/terminal.h" +#include "stout/bytes.h" //////////////////////////////////////////////////////////////////////// @@ -285,6 +286,10 @@ struct _DoAll final { handler_->Install(); } + Bytes StaticHeapSize() { + return Bytes(0) + k_.StaticHeapSize(); + } + // NOTE: need to destruct the fibers LAST since they have a // Scheduler::Context which may get borrowed in 'adaptor_' and // it's continuations so those need to be destructed first. diff --git a/eventuals/eventual.h b/eventuals/eventual.h index dd55911db..0e85351ea 100644 --- a/eventuals/eventual.h +++ b/eventuals/eventual.h @@ -6,6 +6,7 @@ #include "eventuals/interrupt.h" #include "eventuals/scheduler.h" #include "eventuals/undefined.h" +#include "stout/bytes.h" // TODO(benh): catch exceptions from 'start', 'fail', 'stop', etc. @@ -170,6 +171,10 @@ struct _Eventual { return adaptor_; } + Bytes StaticHeapSize() { + return Bytes(0) + k_.StaticHeapSize(); + } + Context_ context_; Start_ start_; Fail_ fail_; diff --git a/eventuals/expected.h b/eventuals/expected.h index a5cf2b3e8..f51f879ad 100644 --- a/eventuals/expected.h +++ b/eventuals/expected.h @@ -2,6 +2,7 @@ #include "eventuals/compose.h" #include "eventuals/eventual.h" +#include "stout/bytes.h" #include "tl/expected.hpp" //////////////////////////////////////////////////////////////////////// @@ -102,6 +103,10 @@ class expected : public tl::expected { .template k(std::move(k)); } + Bytes StaticHeapSize() { + return Bytes(0); + } + using tl::expected::expected; template diff --git a/eventuals/filter.h b/eventuals/filter.h index 8b1d37ef0..1ebf85da0 100644 --- a/eventuals/filter.h +++ b/eventuals/filter.h @@ -1,6 +1,7 @@ #pragma once #include "eventuals/stream.h" +#include "stout/bytes.h" //////////////////////////////////////////////////////////////////////// @@ -46,6 +47,10 @@ struct _Filter final { k_.Register(interrupt); } + Bytes StaticHeapSize() { + return Bytes(0) + k_.StaticHeapSize(); + } + F_ f_; TypeErasedStream* stream_ = nullptr; diff --git a/eventuals/finally.h b/eventuals/finally.h index 29189c7ef..81202d3d0 100644 --- a/eventuals/finally.h +++ b/eventuals/finally.h @@ -3,6 +3,7 @@ #include "eventuals/expected.h" #include "eventuals/terminal.h" // For 'StoppedException'. #include "eventuals/then.h" +#include "stout/bytes.h" //////////////////////////////////////////////////////////////////////// @@ -41,6 +42,10 @@ struct _Finally final { k_.Register(interrupt); } + Bytes StaticHeapSize() { + return Bytes(0) + k_.StaticHeapSize(); + } + K_ k_; }; diff --git a/eventuals/flat-map.h b/eventuals/flat-map.h index 8cf89e424..366285c07 100644 --- a/eventuals/flat-map.h +++ b/eventuals/flat-map.h @@ -4,6 +4,7 @@ #include "eventuals/stream.h" #include "eventuals/terminal.h" +#include "stout/bytes.h" //////////////////////////////////////////////////////////////////////// @@ -129,6 +130,10 @@ struct _FlatMap final { }); } + Bytes StaticHeapSize() { + return Bytes(0) + k_.StaticHeapSize(); + } + F_ f_; TypeErasedStream* outer_ = nullptr; diff --git a/eventuals/head.h b/eventuals/head.h index 9b63adbdc..67dc9e68d 100644 --- a/eventuals/head.h +++ b/eventuals/head.h @@ -1,6 +1,7 @@ #pragma once #include "eventuals/stream.h" +#include "stout/bytes.h" //////////////////////////////////////////////////////////////////////// @@ -45,6 +46,10 @@ struct _Head final { k_.Register(interrupt); } + Bytes StaticHeapSize() { + return Bytes(0) + k_.StaticHeapSize(); + } + std::optional arg_; TypeErasedStream* stream_ = nullptr; diff --git a/eventuals/if.h b/eventuals/if.h index 780670a7f..71cbab158 100644 --- a/eventuals/if.h +++ b/eventuals/if.h @@ -3,6 +3,7 @@ #include "eventuals/eventual.h" #include "eventuals/then.h" // For '_Then::Adaptor'. #include "eventuals/type-traits.h" +#include "stout/bytes.h" //////////////////////////////////////////////////////////////////////// @@ -57,6 +58,10 @@ struct _If final { k_.Register(interrupt); } + Bytes StaticHeapSize() { + return Bytes(0) + k_.StaticHeapSize(); + } + bool condition_; YesE_ yes_; NoE_ no_; diff --git a/eventuals/lock.h b/eventuals/lock.h index 98eb69af5..b88ff4534 100644 --- a/eventuals/lock.h +++ b/eventuals/lock.h @@ -10,6 +10,7 @@ #include "eventuals/stream.h" #include "eventuals/then.h" #include "eventuals/undefined.h" +#include "stout/bytes.h" //////////////////////////////////////////////////////////////////////// @@ -456,6 +457,10 @@ struct _Acquire final { k_.Register(interrupt); } + Bytes StaticHeapSize() { + return Bytes(0) + k_.StaticHeapSize(); + } + Lock* lock_; Lock::Waiter waiter_; std::optional< @@ -548,6 +553,10 @@ struct _Release final { k_.Register(interrupt); } + Bytes StaticHeapSize() { + return Bytes(0) + k_.StaticHeapSize(); + } + Lock* lock_; // NOTE: we store 'k_' as the _last_ member so it will be @@ -776,6 +785,10 @@ struct _Wait final { k_.Register(interrupt); } + Bytes StaticHeapSize() { + return Bytes(0) + k_.StaticHeapSize(); + } + Lock* lock_; F_ f_; diff --git a/eventuals/loop.h b/eventuals/loop.h index f710d8423..aa0e7b3e9 100644 --- a/eventuals/loop.h +++ b/eventuals/loop.h @@ -6,6 +6,7 @@ #include "eventuals/stream.h" #include "eventuals/type-traits.h" #include "eventuals/undefined.h" +#include "stout/bytes.h" //////////////////////////////////////////////////////////////////////// @@ -216,6 +217,10 @@ struct _Loop final { return adaptor_; } + Bytes StaticHeapSize() { + return Bytes(0) + k_.StaticHeapSize(); + } + Context_ context_; Begin_ begin_; Body_ body_; diff --git a/eventuals/map.h b/eventuals/map.h index 902125a8d..3613053a6 100644 --- a/eventuals/map.h +++ b/eventuals/map.h @@ -3,6 +3,7 @@ #include "eventuals/compose.h" // For 'HasValueFrom'. #include "eventuals/stream.h" #include "eventuals/then.h" +#include "stout/bytes.h" //////////////////////////////////////////////////////////////////////// @@ -78,6 +79,10 @@ struct _Map final { k_.Register(interrupt); } + Bytes StaticHeapSize() { + return Bytes(0) + k_.StaticHeapSize(); + } + E_ e_; using Adapted_ = decltype(std::declval().template k( diff --git a/eventuals/on-begin.h b/eventuals/on-begin.h index 1ea942226..955ca7351 100644 --- a/eventuals/on-begin.h +++ b/eventuals/on-begin.h @@ -3,6 +3,7 @@ #include "eventuals/eventual.h" #include "eventuals/stream.h" #include "eventuals/then.h" +#include "stout/bytes.h" //////////////////////////////////////////////////////////////////////// @@ -89,6 +90,10 @@ struct _OnBegin final { k_.Register(interrupt); } + Bytes StaticHeapSize() { + return Bytes(0) + k_.StaticHeapSize(); + } + E_ e_; Interrupt* interrupt_ = nullptr; diff --git a/eventuals/on-ended.h b/eventuals/on-ended.h index 57f50dcec..0f0ebf27d 100644 --- a/eventuals/on-ended.h +++ b/eventuals/on-ended.h @@ -3,6 +3,7 @@ #include "eventuals/eventual.h" #include "eventuals/stream.h" #include "eventuals/then.h" +#include "stout/bytes.h" //////////////////////////////////////////////////////////////////////// @@ -92,6 +93,10 @@ struct _OnEnded final { k_.Register(interrupt); } + Bytes StaticHeapSize() { + return Bytes(0) + k_.StaticHeapSize(); + } + E_ e_; Interrupt* interrupt_ = nullptr; diff --git a/eventuals/raise.h b/eventuals/raise.h index 9e562726c..244edfe00 100644 --- a/eventuals/raise.h +++ b/eventuals/raise.h @@ -4,6 +4,7 @@ #include "eventuals/interrupt.h" #include "eventuals/type-traits.h" +#include "stout/bytes.h" //////////////////////////////////////////////////////////////////////// @@ -36,6 +37,10 @@ struct _Raise final { k_.Register(interrupt); } + Bytes StaticHeapSize() { + return Bytes(0) + k_.StaticHeapSize(); + } + T_ t_; // NOTE: we store 'k_' as the _last_ member so it will be diff --git a/eventuals/range.h b/eventuals/range.h index 3555fd91a..196176e91 100644 --- a/eventuals/range.h +++ b/eventuals/range.h @@ -1,6 +1,7 @@ #pragma once #include "eventuals/stream.h" +#include "stout/bytes.h" //////////////////////////////////////////////////////////////////////// @@ -66,6 +67,10 @@ struct _Range final { }); } + Bytes StaticHeapSize() { + return Bytes(0) + k_.StaticHeapSize(); + } + int from_; const int to_; const int step_; diff --git a/eventuals/reduce.h b/eventuals/reduce.h index 201acf15a..fe40f479d 100644 --- a/eventuals/reduce.h +++ b/eventuals/reduce.h @@ -1,6 +1,7 @@ #pragma once #include "eventuals/stream.h" +#include "stout/bytes.h" //////////////////////////////////////////////////////////////////////// @@ -84,6 +85,10 @@ struct _Reduce final { k_.Register(interrupt); } + Bytes StaticHeapSize() { + return Bytes(0) + k_.StaticHeapSize(); + } + T_ t_; F_ f_; diff --git a/eventuals/repeat.h b/eventuals/repeat.h index fa2a1b409..69046cc2a 100644 --- a/eventuals/repeat.h +++ b/eventuals/repeat.h @@ -3,6 +3,7 @@ #include "eventuals/compose.h" // For 'HasValueFrom'. #include "eventuals/map.h" #include "eventuals/stream.h" +#include "stout/bytes.h" //////////////////////////////////////////////////////////////////////// @@ -53,6 +54,10 @@ struct _Repeat final { }); } + Bytes StaticHeapSize() { + return Bytes(0) + k_.StaticHeapSize(); + } + stout::borrowed_ptr previous_; // NOTE: we store 'k_' as the _last_ member so it will be diff --git a/eventuals/scheduler.h b/eventuals/scheduler.h index 0706e08bc..4f10ade0b 100644 --- a/eventuals/scheduler.h +++ b/eventuals/scheduler.h @@ -15,6 +15,7 @@ #include "eventuals/terminal.h" #include "eventuals/undefined.h" #include "stout/borrowable.h" +#include "stout/bytes.h" #include "stout/stringify.h" //////////////////////////////////////////////////////////////////////// @@ -288,6 +289,10 @@ struct _Reschedule final { k_.Register(interrupt); } + Bytes StaticHeapSize() { + return Bytes(0) + k_.StaticHeapSize(); + } + stout::borrowed_ref context_; std::optional< @@ -392,6 +397,10 @@ struct Reschedulable final { interrupt_ = &interrupt; } + Bytes StaticHeapSize() { + return Bytes(0) + k_.StaticHeapSize(); + } + Interrupt* interrupt_ = nullptr; using Continuation_ = @@ -471,6 +480,10 @@ struct _Preempt final { } } + Bytes StaticHeapSize() { + return Bytes(0) + k_.StaticHeapSize(); + } + Scheduler::Context context_; E_ e_; diff --git a/eventuals/stream.h b/eventuals/stream.h index d511c56c2..4ec4dd632 100644 --- a/eventuals/stream.h +++ b/eventuals/stream.h @@ -21,6 +21,7 @@ #include "eventuals/type-traits.h" #include "eventuals/undefined.h" #include "stout/borrowed_ptr.h" +#include "stout/bytes.h" //////////////////////////////////////////////////////////////////////// @@ -303,6 +304,10 @@ struct _Stream final { return adaptor_; } + Bytes StaticHeapSize() { + return Bytes(0) + k_.StaticHeapSize(); + } + Context_ context_; Begin_ begin_; Next_ next_; diff --git a/eventuals/take.h b/eventuals/take.h index 9f23af081..5ed928153 100644 --- a/eventuals/take.h +++ b/eventuals/take.h @@ -6,6 +6,7 @@ #include "eventuals/eventual.h" #include "eventuals/filter.h" #include "eventuals/stream.h" +#include "stout/bytes.h" //////////////////////////////////////////////////////////////////////// @@ -94,6 +95,10 @@ struct _TakeLast final { }); } + Bytes StaticHeapSize() { + return Bytes(0) + k_.StaticHeapSize(); + } + size_t n_; // NOTE: because we are "taking" we need a value type here (not @@ -212,6 +217,10 @@ struct _TakeRange final { k_.Register(interrupt); } + Bytes StaticHeapSize() { + return Bytes(0) + k_.StaticHeapSize(); + } + size_t begin_; size_t amount_; size_t i_ = 0; diff --git a/eventuals/terminal.h b/eventuals/terminal.h index 266c87539..c5ab27370 100644 --- a/eventuals/terminal.h +++ b/eventuals/terminal.h @@ -3,6 +3,7 @@ #include "eventuals/compose.h" #include "eventuals/interrupt.h" #include "eventuals/undefined.h" +#include "stout/bytes.h" //////////////////////////////////////////////////////////////////////// @@ -57,6 +58,10 @@ struct _Terminal final { void Register(Interrupt&) {} + Bytes StaticHeapSize() { + return Bytes(0); + } + Context_ context_; Start_ start_; Fail_ fail_; diff --git a/eventuals/then.h b/eventuals/then.h index 8a92ad7c6..65854e045 100644 --- a/eventuals/then.h +++ b/eventuals/then.h @@ -3,6 +3,7 @@ #include "eventuals/compose.h" #include "eventuals/eventual.h" #include "eventuals/just.h" +#include "stout/bytes.h" //////////////////////////////////////////////////////////////////////// @@ -151,6 +152,10 @@ struct _Then::Continuation final { k_.Register(interrupt); } + Bytes StaticHeapSize() { + return Bytes(0) + k_.StaticHeapSize(); + } + F_ f_; // NOTE: we store 'k_' as the _last_ member so it will be @@ -195,6 +200,10 @@ struct _Then::Continuation final { k_.Register(interrupt); } + Bytes StaticHeapSize() { + return Bytes(0) + k_.StaticHeapSize(); + } + F_ f_; Interrupt* interrupt_ = nullptr; diff --git a/eventuals/until.h b/eventuals/until.h index 8314c7e14..920160779 100644 --- a/eventuals/until.h +++ b/eventuals/until.h @@ -2,6 +2,7 @@ #include "eventuals/stream.h" #include "eventuals/then.h" +#include "stout/bytes.h" //////////////////////////////////////////////////////////////////////// @@ -154,6 +155,10 @@ struct _Until::Continuation final { k_.Ended(); } + Bytes StaticHeapSize() { + return Bytes(0) + k_.StaticHeapSize(); + } + F_ f_; TypeErasedStream* stream_ = nullptr; diff --git a/test/catch.cc b/test/catch.cc index 55fcbf7d9..b0a2fe333 100644 --- a/test/catch.cc +++ b/test/catch.cc @@ -292,6 +292,8 @@ TEST(CatchTest, Interrupt) { auto [future, k] = PromisifyForTest(e()); + EXPECT_EQ(0, k.StaticHeapSize().bytes()); + Interrupt interrupt; k.Register(interrupt); @@ -301,5 +303,29 @@ TEST(CatchTest, Interrupt) { EXPECT_EQ(future.get(), "100"); } +TEST(CatchTest, StaticHeapSize) { + auto e = []() { + return Just("error") + >> Then([](const char* i) { + return; + }) + >> Catch() + .raised([](std::exception&& error) { + EXPECT_STREQ(error.what(), "error"); + }) + >> Then([]() { + return 1; + }); + }; + + auto [future, k] = PromisifyForTest(e()); + + k.Start(); + + EXPECT_EQ(0, k.StaticHeapSize().bytes()); + + EXPECT_EQ(1, future.get()); +} + } // namespace } // namespace eventuals::test diff --git a/test/closure.cc b/test/closure.cc index 0b13e915b..61fb75b6a 100644 --- a/test/closure.cc +++ b/test/closure.cc @@ -158,5 +158,22 @@ TEST(ClosureTest, Interrupt) { EXPECT_THROW(future.get(), eventuals::StoppedException); } +TEST(ClosureTest, StaticHeapSize) { + auto e = []() { + return Just(1) + >> Closure([i = 41]() { + return Then([&](int value) { return i + value; }); + }); + }; + + auto [future, k] = PromisifyForTest(e()); + + k.Start(); + + EXPECT_EQ(0, k.StaticHeapSize().bytes()); + + EXPECT_EQ(42, future.get()); +} + } // namespace } // namespace eventuals::test diff --git a/test/concurrent/success.cc b/test/concurrent/success.cc index 0f7b81a68..a159aab30 100644 --- a/test/concurrent/success.cc +++ b/test/concurrent/success.cc @@ -49,6 +49,8 @@ TYPED_TEST(ConcurrentTypedTest, Success) { k.Start(); + EXPECT_EQ(0, k.StaticHeapSize().bytes()); + ASSERT_EQ(2, callbacks.size()); EXPECT_EQ( diff --git a/test/conditional.cc b/test/conditional.cc index 855edcf21..c180a996b 100644 --- a/test/conditional.cc +++ b/test/conditional.cc @@ -184,5 +184,24 @@ TEST(ConditionalTest, Raise) { EXPECT_EQ(2, *c()); } +TEST(ConditionalTest, StaticHeapSize) { + auto e = []() { + return Just(1) + >> Then([](int i) { return i + 1; }) + >> Conditional( + [](int i) { return i > 1; }, + [](int i) { return Just(i); }, + [](int i) { return Raise("raise"); }); + }; + + auto [future, k] = PromisifyForTest(e()); + + k.Start(); + + EXPECT_EQ(0, k.StaticHeapSize().bytes()); + + EXPECT_EQ(2, future.get()); +} + } // namespace } // namespace eventuals::test diff --git a/test/do-all.cc b/test/do-all.cc index 874b6af43..add303d58 100644 --- a/test/do-all.cc +++ b/test/do-all.cc @@ -127,5 +127,22 @@ TEST(DoAllTest, Interrupt) { EXPECT_THROW(future.get(), eventuals::StoppedException); } +TEST(DoAllTest, StaticHeapSize) { + auto e = []() { + return DoAll( + Eventual([](auto& k) { k.Start(42); }), + Eventual([](auto& k) { k.Start(std::string("hello")); }), + Eventual([](auto& k) { k.Start(); })); + }; + + auto [future, k] = PromisifyForTest(e()); + + k.Start(); + + EXPECT_EQ(0, k.StaticHeapSize().bytes()); + + EXPECT_EQ(std::make_tuple(42, "hello", std::monostate{}), future.get()); +} + } // namespace } // namespace eventuals::test diff --git a/test/eventual.cc b/test/eventual.cc index fe217ca82..0d5ca694c 100644 --- a/test/eventual.cc +++ b/test/eventual.cc @@ -332,5 +332,21 @@ TEST(EventualTest, Ref) { EXPECT_EQ(110, x); } +TEST(EventualTest, StaticHeapSize) { + auto e = []() { + return Eventual([](auto& k) { + k.Start(1); + }); + }; + + auto [future, k] = PromisifyForTest(e()); + + k.Start(); + + EXPECT_EQ(0, k.StaticHeapSize().bytes()); + + EXPECT_EQ(1, future.get()); +} + } // namespace } // namespace eventuals::test diff --git a/test/filter.cc b/test/filter.cc index ba41e17d6..ed4c5928f 100644 --- a/test/filter.cc +++ b/test/filter.cc @@ -8,9 +8,9 @@ #include "eventuals/iterate.h" #include "eventuals/loop.h" #include "eventuals/map.h" -#include "eventuals/promisify.h" #include "gmock/gmock.h" #include "gtest/gtest.h" +#include "test/promisify-for-test.h" namespace eventuals::test { namespace { @@ -93,5 +93,25 @@ TEST(Filter, OddMapCollectFlow) { EXPECT_THAT(*s(), UnorderedElementsAre(6, 18)); } +TEST(Filter, StaticHeapSize) { + std::vector v = {5, 12, 17}; + auto begin = v.begin(); + auto end = v.end(); + + auto e = [&]() { + return Iterate(begin, end) + >> Filter([](int x) { return x % 2 == 1; }) + >> Collect(); + }; + + auto [future, k] = PromisifyForTest(e()); + + k.Start(); + + EXPECT_EQ(0, k.StaticHeapSize().bytes()); + + EXPECT_EQ((std::set{5, 17}), future.get()); +} + } // namespace } // namespace eventuals::test diff --git a/test/finally.cc b/test/finally.cc index f2554b06a..34fbff650 100644 --- a/test/finally.cc +++ b/test/finally.cc @@ -6,11 +6,11 @@ #include "eventuals/finally.h" #include "eventuals/if.h" #include "eventuals/just.h" -#include "eventuals/promisify.h" #include "eventuals/raise.h" #include "eventuals/then.h" #include "gmock/gmock.h" #include "gtest/gtest.h" +#include "test/promisify-for-test.h" namespace eventuals::test { namespace { @@ -151,5 +151,22 @@ TEST(Finally, FinallyInsideThen) { EXPECT_NO_THROW(*e()); } +TEST(Finally, StaticHeapSize) { + auto e = []() { + return Just(42) + >> Finally([](expected&& expected) { + return Just(std::move(expected)); + }); + }; + + auto [future, k] = PromisifyForTest(e()); + + k.Start(); + + EXPECT_EQ(0, k.StaticHeapSize().bytes()); + + EXPECT_EQ(42, future.get()); +} + } // namespace } // namespace eventuals::test diff --git a/test/flat-map.cc b/test/flat-map.cc index 5fdb516e5..cf481cc47 100644 --- a/test/flat-map.cc +++ b/test/flat-map.cc @@ -277,5 +277,21 @@ TEST(FlatMap, InterruptReturn) { EXPECT_THROW(future.get(), eventuals::StoppedException); } +TEST(FlatMap, StaticHeapSize) { + auto s = []() { + return Range(2) + >> FlatMap([](int x) { return Range(2); }) + >> Collect(); + }; + + auto [future, k] = PromisifyForTest(s()); + + k.Start(); + + EXPECT_EQ(0, k.StaticHeapSize().bytes()); + + EXPECT_EQ((std::vector{0, 1, 0, 1}), future.get()); +} + } // namespace } // namespace eventuals::test diff --git a/test/if.cc b/test/if.cc index dd01f4359..c1f055cd2 100644 --- a/test/if.cc +++ b/test/if.cc @@ -130,5 +130,25 @@ TEST(IfTest, Raise) { EXPECT_EQ(42, *e()); } + +TEST(IfTest, StaticHeapSize) { + auto e = []() { + return Just(1) + >> Then([](int i) { + return If(i == 1) + .yes([]() { return Just("yes"); }) + .no([]() { return Just("no"); }); + }); + }; + + auto [future, k] = PromisifyForTest(e()); + + k.Start(); + + EXPECT_EQ(0, k.StaticHeapSize().bytes()); + + EXPECT_EQ("yes", future.get()); +} + } // namespace } // namespace eventuals::test diff --git a/test/lock.cc b/test/lock.cc index f6ff16e73..75fe6881a 100644 --- a/test/lock.cc +++ b/test/lock.cc @@ -60,12 +60,18 @@ TEST(LockTest, Succeed) { t1.Start(); + EXPECT_EQ(0, t1.StaticHeapSize().bytes()); + EXPECT_EQ("t1", future1.get()); t2.Start(); + EXPECT_EQ(0, t2.StaticHeapSize().bytes()); + t3.Start(); + EXPECT_EQ(0, t3.StaticHeapSize().bytes()); + EXPECT_STREQ("t3", future3.get()); EXPECT_EQ("t2", future2.get()); diff --git a/test/range.cc b/test/range.cc index 0a5e1f7ff..a44efa437 100644 --- a/test/range.cc +++ b/test/range.cc @@ -3,9 +3,9 @@ #include #include "eventuals/collect.h" -#include "eventuals/promisify.h" #include "gmock/gmock.h" #include "gtest/gtest.h" +#include "test/promisify-for-test.h" namespace eventuals::test { namespace { @@ -89,5 +89,18 @@ TEST(Range, SpecifiedStepNegative) { EXPECT_THAT(*s, ElementsAre(0, -2, -4, -6, -8)); } +TEST(Range, StaticHeapSize) { + auto s = []() { return Range(0, 5) + >> Collect(); }; + + auto [future, k] = PromisifyForTest(s()); + + k.Start(); + + EXPECT_EQ(0, k.StaticHeapSize().bytes()); + + EXPECT_EQ((std::vector{0, 1, 2, 3, 4}), future.get()); +} + } // namespace } // namespace eventuals::test diff --git a/test/repeat.cc b/test/repeat.cc index 1efd47051..eab359773 100644 --- a/test/repeat.cc +++ b/test/repeat.cc @@ -121,6 +121,8 @@ TEST(RepeatTest, Interrupt) { k.Register(interrupt); + EXPECT_EQ(0, k.StaticHeapSize().bytes()); + EXPECT_CALL(start, Call()) .WillOnce([&]() { interrupt.Trigger(); diff --git a/test/stream.cc b/test/stream.cc index d59f8592d..c1d65d6e5 100644 --- a/test/stream.cc +++ b/test/stream.cc @@ -362,7 +362,13 @@ TEST(StreamTest, MapThenLoop) { }); }; - EXPECT_EQ(20, *s()); + auto [future, k] = PromisifyForTest(s()); + + k.Start(); + + EXPECT_EQ(0, k.StaticHeapSize().bytes()); + + EXPECT_EQ(20, future.get()); } @@ -393,7 +399,13 @@ TEST(StreamTest, MapThenReduce) { }); }; - EXPECT_EQ(20, *s()); + auto [future, k] = PromisifyForTest(s()); + + k.Start(); + + EXPECT_EQ(0, k.StaticHeapSize().bytes()); + + EXPECT_EQ(20, future.get()); } @@ -499,5 +511,23 @@ TEST(StreamTest, ThrowGeneralError) { ThrowsMessage(StrEq("error"))); } +TEST(StreamTest, HeadHeapSize) { + auto s = []() { + return Stream() + .next([](auto& k) { + k.Emit(42); + }) + >> Head(); + }; + + auto [future, k] = PromisifyForTest(s()); + + k.Start(); + + EXPECT_EQ(0, k.StaticHeapSize().bytes()); + + EXPECT_EQ(42, future.get()); +} + } // namespace } // namespace eventuals::test diff --git a/test/take.cc b/test/take.cc index 24500a05b..709e745cc 100644 --- a/test/take.cc +++ b/test/take.cc @@ -5,9 +5,9 @@ #include "eventuals/collect.h" #include "eventuals/filter.h" #include "eventuals/iterate.h" -#include "eventuals/promisify.h" #include "gmock/gmock.h" #include "gtest/gtest.h" +#include "test/promisify-for-test.h" namespace eventuals::test { namespace { @@ -174,5 +174,43 @@ TEST(Take, TakeRangeInfiniteStream) { EXPECT_THAT(*s(), ElementsAre(0, 1)); } +TEST(Take, TakeLastStaticHeapSize) { + std::vector v = {5, 12, 17, 3}; + + auto s = [&]() { + return Iterate(v) + >> TakeLast(2) + >> Collect(); + }; + + EXPECT_THAT(*s(), ElementsAre(17, 3)); + + auto [future, k] = PromisifyForTest(s()); + + k.Start(); + + EXPECT_EQ(0, k.StaticHeapSize().bytes()); + + EXPECT_THAT(future.get(), ElementsAre(17, 3)); +} + +TEST(Take, TakeRangeStaticHeapSize) { + std::vector v = {5, 12, 17, 20, 22, 1, 1, 1}; + + auto s = [&]() { + return Iterate(v) + >> TakeRange(1, 2) + >> Collect(); + }; + + auto [future, k] = PromisifyForTest(s()); + + k.Start(); + + EXPECT_EQ(0, k.StaticHeapSize().bytes()); + + EXPECT_THAT(future.get(), ElementsAre(12, 17)); +} + } // namespace } // namespace eventuals::test