Files
test2/source/blender/blenlib/tests/BLI_function_ref_test.cc
Jacques Lucke b79dd3fc5d BLI: improve FunctionRef constructor in case of a falsy callable
Previously, passing a falsy `std::function` (i.e. it is empty) or a null
function pointer would result in a `FunctionRef` which is thruthy and thus
appeared callable. Now, when the passed in callable is falsy, the resulting
`FunctionRef` will be too.

Pull Request: https://projects.blender.org/blender/blender/pulls/128823
2024-10-10 03:14:44 +02:00

156 lines
3.2 KiB
C++

/* 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<int(int, int)> 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<int()> ref = f;
EXPECT_EQ(ref(), 42);
}
TEST(function_ref, MutableStatefullLambda)
{
int counter = 0;
auto f = [&]() mutable { return counter++; };
FunctionRef<int()> ref = f;
EXPECT_EQ(ref(), 0);
EXPECT_EQ(ref(), 1);
EXPECT_EQ(ref(), 2);
}
TEST(function_ref, Null)
{
FunctionRef<int()> 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<int()> x = f1;
FunctionRef<int()> y = x;
x = f2;
EXPECT_EQ(y(), 1);
}
TEST(function_ref, CopyDoesNotReferenceFunctionRef2)
{
auto f = []() { return 1; };
FunctionRef<int()> x;
FunctionRef<int()> y = f;
FunctionRef<int()> z = static_cast<const FunctionRef<int()> &&>(y);
x = z;
y = {};
EXPECT_EQ(x(), 1);
}
TEST(function_ref, ReferenceAnotherFunctionRef)
{
auto f1 = []() { return 1; };
auto f2 = []() { return 2; };
FunctionRef<int()> x = f1;
auto f3 = [&]() { return x(); };
FunctionRef<int()> y = f3;
EXPECT_EQ(y(), 1);
x = f2;
EXPECT_EQ(y(), 2);
}
TEST(function_ref, InitializeWithNull)
{
FunctionRef<int(int, int)> f{nullptr};
EXPECT_FALSE(f);
}
static int overload_test(const FunctionRef<void(std::string)> /*fn*/)
{
return 1;
}
static int overload_test(const FunctionRef<void(int)> /*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<void()> fn1;
const std::function<void()> fn2 = [&]() {};
const FunctionRef<void()> fn_ref1(fn1);
const FunctionRef<void()> fn_ref2(fn2);
EXPECT_FALSE(fn_ref1);
EXPECT_TRUE(fn_ref2);
const FunctionRef<void()> fn_ref3(fn1);
const FunctionRef<void()> 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<void()> fn_ref1(fn1);
const FunctionRef<void()> fn_ref2(fn2);
EXPECT_FALSE(fn_ref1);
EXPECT_TRUE(fn_ref2);
}
} // namespace blender::tests