/* SPDX-FileCopyrightText: 2023 Blender Authors * * SPDX-License-Identifier: Apache-2.0 */ #include "BLI_function_ref.hh" #include "testing/testing.h" namespace blender::tests { static int perform_binary_operation(int a, int b, FunctionRef operation) { return operation(a, b); } TEST(function_ref, StatelessLambda) { const int result = perform_binary_operation(4, 6, [](int a, int b) { return a - b; }); EXPECT_EQ(result, -2); } TEST(function_ref, StatefullLambda) { const int factor = 10; const int result = perform_binary_operation( 2, 3, [&](int a, int b) { return factor * (a + b); }); EXPECT_EQ(result, 50); } static int add_two_numbers(int a, int b) { return a + b; } TEST(function_ref, StandaloneFunction) { const int result = perform_binary_operation(10, 5, add_two_numbers); EXPECT_EQ(result, 15); } TEST(function_ref, ConstantFunction) { auto f = []() { return 42; }; FunctionRef ref = f; EXPECT_EQ(ref(), 42); } TEST(function_ref, MutableStatefullLambda) { int counter = 0; auto f = [&]() mutable { return counter++; }; FunctionRef ref = f; EXPECT_EQ(ref(), 0); EXPECT_EQ(ref(), 1); EXPECT_EQ(ref(), 2); } TEST(function_ref, Null) { FunctionRef ref; EXPECT_FALSE(ref); auto f = []() { return 1; }; ref = f; EXPECT_TRUE(ref); ref = {}; EXPECT_FALSE(ref); } TEST(function_ref, CopyDoesNotReferenceFunctionRef) { auto f1 = []() { return 1; }; auto f2 = []() { return 2; }; FunctionRef x = f1; FunctionRef y = x; x = f2; EXPECT_EQ(y(), 1); } TEST(function_ref, CopyDoesNotReferenceFunctionRef2) { auto f = []() { return 1; }; FunctionRef x; FunctionRef y = f; FunctionRef z = static_cast &&>(y); x = z; y = {}; EXPECT_EQ(x(), 1); } TEST(function_ref, ReferenceAnotherFunctionRef) { auto f1 = []() { return 1; }; auto f2 = []() { return 2; }; FunctionRef x = f1; auto f3 = [&]() { return x(); }; FunctionRef y = f3; EXPECT_EQ(y(), 1); x = f2; EXPECT_EQ(y(), 2); } TEST(function_ref, InitializeWithNull) { FunctionRef f{nullptr}; EXPECT_FALSE(f); } static int overload_test(const FunctionRef /*fn*/) { return 1; } static int overload_test(const FunctionRef /*fn*/) { return 2; } TEST(function_ref, OverloadSelection) { const auto fn_1 = [](std::string /*x*/) {}; const auto fn_2 = [](int /*x*/) {}; EXPECT_EQ(overload_test(fn_1), 1); EXPECT_EQ(overload_test(fn_2), 2); } TEST(function_ref, FalsyStdFunction) { const std::function fn1; const std::function fn2 = [&]() {}; const FunctionRef fn_ref1(fn1); const FunctionRef fn_ref2(fn2); EXPECT_FALSE(fn_ref1); EXPECT_TRUE(fn_ref2); const FunctionRef fn_ref3(fn1); const FunctionRef fn_ref4(fn2); EXPECT_FALSE(fn_ref3); EXPECT_TRUE(fn_ref4); } TEST(function_ref, FalsyFunctionPointer) { using Fn = void (*)(); const Fn fn1 = nullptr; const Fn fn2 = []() {}; const FunctionRef fn_ref1(fn1); const FunctionRef fn_ref2(fn2); EXPECT_FALSE(fn_ref1); EXPECT_TRUE(fn_ref2); } } // namespace blender::tests