nf7/iface/common/future_test.cc
2023-07-23 21:23:47 +09:00

272 lines
6.3 KiB
C++

// No copyright
#include "iface/common/future.hh"
#include <gtest/gtest.h>
#include <cstdint>
#include <optional>
#include <utility>
#include "iface/common/exception.hh"
TEST(Future, ImmediateValue) {
nf7::Future<int32_t> sut {int32_t {777}};
EXPECT_FALSE(sut.yet());
EXPECT_TRUE(sut.done());
EXPECT_FALSE(sut.error());
EXPECT_EQ(sut.value(), int32_t {777});
}
TEST(Future, ImmediateError) {
nf7::Future<int32_t> sut {std::make_exception_ptr(nf7::Exception("hello"))};
EXPECT_FALSE(sut.yet());
EXPECT_FALSE(sut.done());
EXPECT_TRUE(sut.error());
EXPECT_THROW(std::rethrow_exception(sut.error()), nf7::Exception);
EXPECT_THROW(sut.value(), nf7::Exception);
}
TEST(Future, LazyComplete) {
nf7::Future<int32_t>::Completer completer;
nf7::Future<int32_t> sut = completer.future();
completer.Complete(int32_t {777});
EXPECT_FALSE(sut.yet());
EXPECT_TRUE(sut.done());
EXPECT_FALSE(sut.error());
EXPECT_EQ(sut.value(), int32_t {777});
}
TEST(Future, LazyThrow) {
nf7::Future<int32_t>::Completer completer;
nf7::Future<int32_t> sut = completer.future();
completer.Throw(std::make_exception_ptr(nf7::Exception {"hello"}));
EXPECT_FALSE(sut.yet());
EXPECT_FALSE(sut.done());
EXPECT_TRUE(sut.error());
EXPECT_THROW(std::rethrow_exception(sut.error()), nf7::Exception);
EXPECT_THROW(sut.value(), nf7::Exception);
}
TEST(Future, LazyIncomplete) {
nf7::Future<int32_t>::Completer completer;
nf7::Future<int32_t> sut = completer.future();
EXPECT_TRUE(sut.yet());
EXPECT_FALSE(sut.done());
EXPECT_FALSE(sut.error());
}
TEST(Future, LazyForgotten) {
std::optional<nf7::Future<int32_t>> sut;
{
std::optional<nf7::Future<int32_t>::Completer> completer;
nf7::Future<int32_t> sut2 {*sut};
{
nf7::Future<int32_t>::Completer completer2;
sut.emplace(completer2.future());
completer.emplace(completer2);
}
EXPECT_TRUE(sut->yet());
EXPECT_FALSE(sut->done());
EXPECT_FALSE(sut->error());
}
EXPECT_FALSE(sut->yet());
EXPECT_FALSE(sut->done());
EXPECT_TRUE(sut->error());
}
TEST(Future, ListenImmediateValue) {
nf7::Future<int32_t> sut {int32_t {777}};
auto called = int32_t {0};
sut.Listen([&](auto& fu) {
++called;
EXPECT_EQ(fu.value(), int32_t {777});
});
EXPECT_EQ(called, 1);
}
TEST(Future, ListenImmediateError) {
nf7::Future<int32_t> sut {std::make_exception_ptr(nf7::Exception {"hello"})};
auto called = int32_t {0};
sut.Listen([&](auto& fu) {
++called;
EXPECT_THROW(fu.value(), nf7::Exception);
});
EXPECT_EQ(called, 1);
}
TEST(Future, ListenLazyComplete) {
nf7::Future<int32_t>::Completer completer;
nf7::Future<int32_t> sut = completer.future();
auto called = int32_t {0};
sut.Listen([&](auto& fu) {
++called;
EXPECT_EQ(fu.value(), int32_t {777});
});
completer.Complete(int32_t {777});
EXPECT_EQ(called, 1);
}
TEST(Future, ListenLazyThrow) {
nf7::Future<int32_t>::Completer completer;
nf7::Future<int32_t> sut = completer.future();
auto called = int32_t {0};
sut.Listen([&](auto& fu) {
++called;
EXPECT_THROW(fu.value(), nf7::Exception);
});
completer.Throw(std::make_exception_ptr(nf7::Exception {"hello"}));
EXPECT_EQ(called, 1);
}
TEST(Future, ListenLazyIncomplete) {
nf7::Future<int32_t>::Completer completer;
nf7::Future<int32_t> sut = completer.future();
auto called = int32_t {0};
sut.Listen([&](auto&) { ++called; });
EXPECT_EQ(called, 0);
}
TEST(Future, ListenLazyForgotten) {
auto called = int32_t {0};
{
nf7::Future<int32_t>::Completer completer;
nf7::Future<int32_t> sut = completer.future();
sut.Listen([&](auto& fu) {
++called;
EXPECT_THROW(fu.value(), nf7::Exception);
});
}
EXPECT_EQ(called, 1);
}
TEST(Future, ThenWhenDone) {
nf7::Future<int32_t> sut {int32_t {777}};
auto called = int32_t {0};
sut.Then([&](auto& x) {
++called;
EXPECT_EQ(x, int32_t {777});
});
EXPECT_EQ(called, 1);
}
TEST(Future, ThenWhenError) {
nf7::Future<int32_t> sut {std::make_exception_ptr(nf7::Exception {"hello"})};
auto called = int32_t {0};
sut.Then([&](auto&) { ++called; });
EXPECT_EQ(called, 0);
}
TEST(Future, CatchWhenDone) {
nf7::Future<int32_t> sut {int32_t {777}};
auto called = int32_t {0};
sut.Catch([&](auto&) { ++called; });
EXPECT_EQ(called, int32_t {0});
}
TEST(Future, CatchWhenError) {
nf7::Future<int32_t> sut {std::make_exception_ptr(nf7::Exception {"hello"})};
auto called = int32_t {0};
sut.Catch([&](auto&) { ++called; });
EXPECT_EQ(called, 1);
}
TEST(Future, ThenAndWhenDone) {
nf7::Future<int32_t> sut {int32_t {777}};
auto called1 = int32_t {0};
auto called2 = int32_t {0};
sut
.ThenAnd([&](auto& x) {
++called1;
EXPECT_EQ(x, int32_t {777});
return int32_t {666};
})
.Then([&](auto& x) {
++called2;
EXPECT_EQ(x, int32_t {666});
});
EXPECT_EQ(called1, 1);
EXPECT_EQ(called2, 1);
}
TEST(Future, ThenAndWhenError) {
nf7::Future<int32_t> sut {std::make_exception_ptr(nf7::Exception {"hello"})};
auto called1 = int32_t {0};
auto called2 = int32_t {0};
sut
.ThenAnd([&](auto&) {
++called1;
return int32_t {666};
})
.Then([&](auto&) {
++called2;
});
EXPECT_EQ(called1, 0);
EXPECT_EQ(called2, 0);
}
TEST(Future_Completer, CompleteAfterCopy) {
std::optional<nf7::Future<int32_t>> fut;
{
std::optional<nf7::Future<int32_t>::Completer> sut;
{
nf7::Future<int32_t>::Completer sut2;
fut.emplace(sut2.future());
sut.emplace(sut2);
}
sut->Complete(int32_t {777});
}
EXPECT_TRUE(fut->done());
}
TEST(Future_Completer, CompleteAfterMove) {
std::optional<nf7::Future<int32_t>> fut;
{
std::optional<nf7::Future<int32_t>::Completer> sut;
{
nf7::Future<int32_t>::Completer sut2;
fut.emplace(sut2.future());
sut.emplace(std::move(sut2));
}
sut->Complete(int32_t {777});
}
EXPECT_TRUE(fut->done());
}
#if !defined(NDEBUG)
TEST(Future, DeathByListenInCallback) {
nf7::Future<int32_t> sut {int32_t{777}};
sut.Listen([&](auto&) {
ASSERT_DEATH_IF_SUPPORTED(sut.Listen([](auto&){}), "");
});
}
TEST(Future, DeathByListenInLazyCallback) {
nf7::Future<int32_t>::Completer completer;
nf7::Future<int32_t> sut = completer.future();
sut.Listen([&](auto&) {
ASSERT_DEATH_IF_SUPPORTED(sut.Listen([](auto&){}), "");
});
completer.Complete(int32_t{777});
}
#endif