diff options
author | bbiff <bbiff@yandex-team.com> | 2022-08-24 16:44:16 +0300 |
---|---|---|
committer | bbiff <bbiff@yandex-team.com> | 2022-08-24 16:44:16 +0300 |
commit | 7eeb61811ba1588f20d70abeadc7b9308dd785dd (patch) | |
tree | 71e1f4bcfd0bef1563239e2bea85d8de0e5eb275 /util/generic/function_ref_ut.cpp | |
parent | 653146b941fae8faaf0cf733e371816e7c69e7d2 (diff) | |
download | ydb-7eeb61811ba1588f20d70abeadc7b9308dd785dd.tar.gz |
added limit parameter
Diffstat (limited to 'util/generic/function_ref_ut.cpp')
-rw-r--r-- | util/generic/function_ref_ut.cpp | 150 |
1 files changed, 150 insertions, 0 deletions
diff --git a/util/generic/function_ref_ut.cpp b/util/generic/function_ref_ut.cpp new file mode 100644 index 0000000000..59f9ae35cd --- /dev/null +++ b/util/generic/function_ref_ut.cpp @@ -0,0 +1,150 @@ +#include "function_ref.h" + +#include <library/cpp/testing/unittest/registar.h> + +Y_UNIT_TEST_SUITE(TestFunctionRef) { + template <typename Signature> + struct TTestFunction; + + template <typename Ret, typename... Args, bool IsNoexcept> + struct TTestFunction<Ret(Args...) noexcept(IsNoexcept)> { + Ret operator()(Args...) const noexcept(IsNoexcept) { + return {}; + } + }; + + Y_UNIT_TEST(NonDefaultConstructible) { + static_assert(!std::is_default_constructible_v<TFunctionRef<void()>>); + static_assert(!std::is_default_constructible_v<TFunctionRef<void() noexcept>>); + static_assert(!std::is_default_constructible_v<TFunctionRef<int(double, void********* megaptr, TTestFunction<void(int)>)>>); + } + + int F1(bool x) { + if (x) + throw 19; + return 42; + } + + int F2(bool x) noexcept { + return 42 + x; + } + + static const TTestFunction<int(bool)> C1; + static const TTestFunction<int(bool) noexcept> C2; + + Y_UNIT_TEST(Noexcept) { + static_assert(std::is_constructible_v<TFunctionRef<int(bool)>, decltype(F1)>); + static_assert(std::is_constructible_v<TFunctionRef<int(bool)>, decltype(F2)>); + static_assert(!std::is_constructible_v<TFunctionRef<int(bool) noexcept>, decltype(F1)>); + static_assert(std::is_constructible_v<TFunctionRef<int(bool) noexcept>, decltype(F2)>); + + static_assert(std::is_constructible_v<TFunctionRef<int(bool)>, decltype(C1)>); + static_assert(std::is_constructible_v<TFunctionRef<int(bool)>, decltype(C2)>); + static_assert(!std::is_constructible_v<TFunctionRef<int(bool) noexcept>, decltype(C1)>); + static_assert(std::is_constructible_v<TFunctionRef<int(bool) noexcept>, decltype(C2)>); + } + + Y_UNIT_TEST(Deduction) { + TFunctionRef ref1(F1); + TFunctionRef ref2(F2); + TFunctionRef ref3(C1); + TFunctionRef ref4(C2); + + static_assert(!std::is_nothrow_invocable_r_v<int, decltype(ref1), bool>); + static_assert(std::is_nothrow_invocable_r_v<int, decltype(ref2), bool>); + static_assert(std::is_same_v<decltype(ref1)::TSignature, int(bool)>); + static_assert(std::is_same_v<decltype(ref2)::TSignature, int(bool) noexcept>); + } + + void WithCallback(TFunctionRef<double(double, int) noexcept>); + + void Iterate(int from, int to, TFunctionRef<void(int)> callback) { + while (from < to) { + callback(from++); + } + } + + void IterateNoexcept(int from, int to, TFunctionRef<void(int) noexcept> callback) { + while (from < to) { + callback(from++); + } + } + + Y_UNIT_TEST(AsArgument) { + int sum = 0; + Iterate(0, 10, [&](int x) { sum += x; }); + UNIT_ASSERT_EQUAL(sum, 45); + + Iterate(0, 10, [&](int x) noexcept { sum += x; }); + UNIT_ASSERT_EQUAL(sum, 90); + + IterateNoexcept(0, 10, [&](int x) noexcept { sum += x; }); + UNIT_ASSERT_EQUAL(sum, 135); + + auto summer = [&](int x) { sum += x; }; + Iterate(0, 10, summer); + Iterate(0, 10, summer); + Iterate(0, 10, summer); + UNIT_ASSERT_EQUAL(sum, 270); + + TFunctionRef ref = summer; + Iterate(0, 10, ref); + UNIT_ASSERT_EQUAL(sum, 315); + } + + int GlobalSum = 0; + void AddToGlobalSum(int x) { + GlobalSum += x; + } + + Y_UNIT_TEST(FunctionPointer) { + GlobalSum = 0; + Iterate(0, 10, AddToGlobalSum); + UNIT_ASSERT_EQUAL(GlobalSum, 45); + + TFunctionRef ref1 = AddToGlobalSum; + Iterate(0, 10, ref1); + UNIT_ASSERT_EQUAL(GlobalSum, 90); + + TFunctionRef ref2{AddToGlobalSum}; + Iterate(0, 10, ref2); + UNIT_ASSERT_EQUAL(GlobalSum, 135); + } + + Y_UNIT_TEST(Reassign) { + TFunctionRef kek = [](double) { return 42; }; + kek = [](double) { return 19; }; + kek = [](int) { return 22.8; }; + } + + const char* Greet() { + return "Hello, world!"; + } + + Y_UNIT_TEST(ImplicitCasts) { + TFunctionRef<void(int)> ref = [](int x) { return x; }; + ref = [](double x) { return x; }; + ref = [](char x) { return x; }; + + TFunctionRef<int()> ref1 = [] { return 0.5; }; + ref1 = [] { return 'a'; }; + ref1 = [] { return 124u; }; + + TFunctionRef<TStringBuf()> ref2{Greet}; + } + + Y_UNIT_TEST(StatelessLambdaLifetime) { + TFunctionRef<int(int, int)> ref{[](int a, int b) { return a + b; }}; + UNIT_ASSERT_EQUAL(ref(5, 5), 10); + } + + Y_UNIT_TEST(ForwardArguments) { + char x = 'x'; + TFunctionRef<void(std::unique_ptr<int>, char&)> ref = [](std::unique_ptr<int> ptr, char& ch) { + UNIT_ASSERT_EQUAL(*ptr, 5); + ch = 'a'; + }; + ref(std::make_unique<int>(5), x); + UNIT_ASSERT_EQUAL(x, 'a'); + } +} |