aboutsummaryrefslogtreecommitdiffstats
path: root/library/cpp/yt/memory/unittests/function_view_ut.cpp
diff options
context:
space:
mode:
authorAlexander Smirnov <alex@ydb.tech>2024-04-16 09:11:59 +0000
committerAlexander Smirnov <alex@ydb.tech>2024-04-16 09:11:59 +0000
commit25de1d521ca218e2b040739fea77a39e9fc543e9 (patch)
tree21521d8866cf1462dbd52c071cf369974c29650e /library/cpp/yt/memory/unittests/function_view_ut.cpp
parentbf444b8ed4d0f6bf17fd753e2cf88f9440012e87 (diff)
parent0a63d9ddc516f206f2b8745ce5e5dfa60190d755 (diff)
downloadydb-25de1d521ca218e2b040739fea77a39e9fc543e9.tar.gz
Merge branch 'rightlib' into mergelibs-240416-0910
Diffstat (limited to 'library/cpp/yt/memory/unittests/function_view_ut.cpp')
-rw-r--r--library/cpp/yt/memory/unittests/function_view_ut.cpp194
1 files changed, 194 insertions, 0 deletions
diff --git a/library/cpp/yt/memory/unittests/function_view_ut.cpp b/library/cpp/yt/memory/unittests/function_view_ut.cpp
new file mode 100644
index 0000000000..99af41793c
--- /dev/null
+++ b/library/cpp/yt/memory/unittests/function_view_ut.cpp
@@ -0,0 +1,194 @@
+#include <library/cpp/testing/gtest/gtest.h>
+
+#include <library/cpp/yt/memory/function_view.h>
+
+#include <util/generic/string.h>
+#include <util/string/cast.h>
+
+namespace NYT {
+namespace {
+
+////////////////////////////////////////////////////////////////////////////////
+
+struct TNoCopy
+{
+ int Value = 42;
+
+ TNoCopy() = default;
+
+ TNoCopy(const TNoCopy&) = delete;
+
+ TNoCopy(TNoCopy&&)
+ { }
+};
+
+int Foo()
+{
+ return 42;
+}
+
+int& Bar()
+{
+ static int bar = 0;
+ return bar;
+}
+
+const TNoCopy& ImmutBar()
+{
+ static TNoCopy bar = {};
+ return bar;
+}
+
+TString Baz(const int& x)
+{
+ return ToString(x);
+}
+
+void NoExFoo() noexcept
+{ }
+
+struct TCallable
+{
+ int InvocationCount = 0;
+ mutable int ConstInvocationCount = 0;
+
+ void operator()() &
+ {
+ ++InvocationCount;
+ }
+
+ void operator()() const &
+ {
+ ++ConstInvocationCount;
+ }
+};
+
+////////////////////////////////////////////////////////////////////////////////
+
+TEST(TFunctionViewTest, JustWorks)
+{
+ auto stackLambda = [] (int val) {
+ return val + 1;
+ };
+
+ {
+ TFunctionView<int(int)> view(stackLambda);
+
+ EXPECT_EQ(view(42), 43);
+ }
+}
+
+TEST(TFunctionViewTest, FreeFunction)
+{
+ TFunctionView<int()> view(Foo);
+ EXPECT_EQ(view(), 42);
+}
+
+TEST(TFunctionViewTest, RefReturn)
+{
+ TFunctionView<int&()> view(Bar);
+ ++view();
+ EXPECT_EQ(view(), 1);
+
+ TFunctionView<const TNoCopy&()> immut_view(ImmutBar);
+ EXPECT_EQ(immut_view().Value, 42);
+}
+
+TEST(TFunctionViewTest, RefArgument)
+{
+ TFunctionView<TString(const int&)> view(Baz);
+ EXPECT_EQ(view(77), TString("77"));
+}
+
+TEST(TFunctionViewTest, NoExcept)
+{
+ TFunctionView<void() noexcept> view(NoExFoo);
+ static_assert(std::is_nothrow_invocable_r_v<void, decltype(view)>);
+
+ view();
+}
+
+TEST(TFunctionViewTest, CVOverloads)
+{
+ TCallable callable;
+
+ TFunctionView<void()> view(callable);
+ // NB: & overload overshadows every other overload.
+ // const auto& viewRef = view;
+ // viewRef();
+
+ view();
+ EXPECT_EQ(callable.InvocationCount, 1);
+ EXPECT_EQ(callable.ConstInvocationCount, 0);
+}
+
+TEST(TFunctionViewTest, CopyView)
+{
+ int counter = 0;
+ auto lambda = [&counter] {
+ ++counter;
+ };
+
+ TFunctionView<void()> view1(lambda);
+ TFunctionView<void()> view2 = view1;
+
+ view1();
+ EXPECT_EQ(counter, 1);
+ view2();
+ EXPECT_EQ(counter, 2);
+ view1();
+ EXPECT_EQ(counter, 3);
+}
+
+TEST(TFunctionViewTest, AssignView)
+{
+ int counter = 0;
+ auto lambda = [&counter] {
+ ++counter;
+ };
+
+ TFunctionView<void()> view(lambda);
+ view();
+ EXPECT_EQ(counter, 1);
+
+ {
+ auto innerCounter = 0;
+ auto lambda = [&innerCounter] {
+ ++innerCounter;
+ };
+
+ view = lambda;
+ view();
+ EXPECT_EQ(counter, 1);
+ EXPECT_EQ(innerCounter, 1);
+ }
+
+ // NB: Even though object is dead view will remain "valid".
+ // Be careful with lifetimes!
+ EXPECT_TRUE(view.IsValid());
+}
+
+TEST(TFunctionViewTest, ReleaseSemantics)
+{
+ int counter = 0;
+ auto lambda = [&counter] {
+ ++counter;
+ };
+
+ TFunctionView<void()> view1(lambda);
+ view1();
+ EXPECT_EQ(counter, 1);
+
+ TFunctionView view2 = view1.Release();
+ EXPECT_FALSE(view1.IsValid());
+
+ EXPECT_TRUE(view2.IsValid());
+
+ view2();
+ EXPECT_EQ(counter, 2);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+} // namespace
+} // namespace NYT