Files
fahnen_esp32/.pio/libdeps/esp01_1m/FastLED/tests/test_invoke.cpp

281 lines
8.7 KiB
C++

#include "test.h"
#include "fl/functional.h"
#include "fl/function.h"
#include "fl/ptr.h"
#include "fl/scoped_ptr.h"
using namespace fl;
// Test data and functions
static int add(int a, int b) {
return a + b;
}
static int multiply(int a, int b) {
return a * b;
}
struct TestClass {
int value = 42;
int getValue() const {
return value;
}
void setValue(int v) {
value = v;
}
int add(int x) const {
return value + x;
}
int multiply(int x) {
return value * x;
}
};
struct Functor {
int operator()(int a, int b) const {
return a * b + 10;
}
};
// Test free function pointers
TEST_CASE("fl::invoke with free function pointers") {
// Test function pointer
auto result1 = fl::invoke(add, 5, 3);
CHECK_EQ(8, result1);
auto result2 = fl::invoke(multiply, 4, 7);
CHECK_EQ(28, result2);
// Test function reference
auto result3 = fl::invoke(&add, 10, 20);
CHECK_EQ(30, result3);
}
// Test member function pointers with object references
TEST_CASE("fl::invoke with member function pointers and objects") {
TestClass obj;
// Test const member function with object reference
auto result1 = fl::invoke(&TestClass::getValue, obj);
CHECK_EQ(42, result1);
// Test non-const member function with object reference
fl::invoke(&TestClass::setValue, obj, 100);
CHECK_EQ(100, obj.value);
// Test member function with arguments
auto result2 = fl::invoke(&TestClass::add, obj, 10);
CHECK_EQ(110, result2);
auto result3 = fl::invoke(&TestClass::multiply, obj, 3);
CHECK_EQ(300, result3);
}
// Test member function pointers with pointers
TEST_CASE("fl::invoke with member function pointers and pointers") {
TestClass obj;
TestClass* ptr = &obj;
// Test const member function with pointer
auto result1 = fl::invoke(&TestClass::getValue, ptr);
CHECK_EQ(42, result1);
// Test non-const member function with pointer
fl::invoke(&TestClass::setValue, ptr, 200);
CHECK_EQ(200, obj.value);
// Test member function with arguments and pointer
auto result2 = fl::invoke(&TestClass::add, ptr, 15);
CHECK_EQ(215, result2);
auto result3 = fl::invoke(&TestClass::multiply, ptr, 2);
CHECK_EQ(400, result3);
}
// Test member data pointers with object references
TEST_CASE("fl::invoke with member data pointers and objects") {
TestClass obj;
obj.value = 123;
// Test member data access with object reference
auto result1 = fl::invoke(&TestClass::value, obj);
CHECK_EQ(123, result1);
// Test member data modification
fl::invoke(&TestClass::value, obj) = 456;
CHECK_EQ(456, obj.value);
}
// Test member data pointers with pointers
TEST_CASE("fl::invoke with member data pointers and pointers") {
TestClass obj;
obj.value = 789;
TestClass* ptr = &obj;
// Test member data access with pointer
auto result1 = fl::invoke(&TestClass::value, ptr);
CHECK_EQ(789, result1);
// Test member data modification with pointer
fl::invoke(&TestClass::value, ptr) = 999;
CHECK_EQ(999, obj.value);
}
// Test callable objects (functors, lambdas)
TEST_CASE("fl::invoke with callable objects") {
// Test functor
Functor f;
auto result1 = fl::invoke(f, 5, 6);
CHECK_EQ(40, result1); // 5 * 6 + 10 = 40
// Test lambda
auto lambda = [](int a, int b) { return a - b; };
auto result2 = fl::invoke(lambda, 10, 3);
CHECK_EQ(7, result2);
// Test lambda with capture
int multiplier = 5;
auto capturing_lambda = [multiplier](int x) { return x * multiplier; };
auto result3 = fl::invoke(capturing_lambda, 8);
CHECK_EQ(40, result3);
}
// Test edge cases
TEST_CASE("fl::invoke edge cases") {
// Test with no arguments
auto no_args = []() { return 42; };
auto result1 = fl::invoke(no_args);
CHECK_EQ(42, result1);
// Test with const object
const TestClass const_obj;
auto result2 = fl::invoke(&TestClass::getValue, const_obj);
CHECK_EQ(42, result2);
// Test with temporary object
auto result3 = fl::invoke(&TestClass::getValue, TestClass{});
CHECK_EQ(42, result3);
// Test with const pointer
const TestClass const_obj2;
const TestClass* const_ptr = &const_obj2;
auto result4 = fl::invoke(&TestClass::getValue, const_ptr);
CHECK_EQ(42, result4);
}
// Test fl::invoke with fl::scoped_ptr smart pointers
TEST_CASE("fl::invoke with scoped_ptr smart pointers") {
struct TestScopedPtrClass {
int value = 42;
int getValue() const { return value; }
void setValue(int v) { value = v; }
int add(int x) const { return value + x; }
int multiply(int x) { return value * x; }
};
// Test with scoped_ptr
fl::scoped_ptr<TestScopedPtrClass> scopedPtr(new TestScopedPtrClass);
// Member function: const getter
CHECK_EQ(42, fl::invoke(&TestScopedPtrClass::getValue, scopedPtr));
// Member function: setter
fl::invoke(&TestScopedPtrClass::setValue, scopedPtr, 123);
CHECK_EQ(123, scopedPtr->value);
// Member function with additional arg, const
CHECK_EQ(133, fl::invoke(&TestScopedPtrClass::add, scopedPtr, 10));
// Member function with additional arg, non-const
CHECK_EQ(246, fl::invoke(&TestScopedPtrClass::multiply, scopedPtr, 2));
// Member data pointer access and modification
CHECK_EQ(123, fl::invoke(&TestScopedPtrClass::value, scopedPtr));
fl::invoke(&TestScopedPtrClass::value, scopedPtr) = 999;
CHECK_EQ(999, scopedPtr->value);
// Test with custom deleter
struct CustomDeleter {
void operator()(TestScopedPtrClass* ptr) {
delete ptr;
}
};
fl::scoped_ptr<TestScopedPtrClass, CustomDeleter> customScopedPtr(new TestScopedPtrClass, CustomDeleter{});
// Member function with custom deleter scoped_ptr
CHECK_EQ(42, fl::invoke(&TestScopedPtrClass::getValue, customScopedPtr));
fl::invoke(&TestScopedPtrClass::setValue, customScopedPtr, 555);
CHECK_EQ(555, customScopedPtr->value);
CHECK_EQ(565, fl::invoke(&TestScopedPtrClass::add, customScopedPtr, 10));
}
// Test fl::invoke with fl::function objects
TEST_CASE("fl::invoke with fl::function objects") {
struct TestFunctionClass {
int value = 100;
int getValue() const { return value; }
void setValue(int v) { value = v; }
int add(int x) const { return value + x; }
int multiply(int x) { return value * x; }
};
// 1. Test fl::function with free function
fl::function<int(int, int)> free_func = add;
auto result1 = fl::invoke(free_func, 10, 20);
CHECK_EQ(30, result1);
// 2. Test fl::function with lambda
fl::function<int(int, int)> lambda_func = [](int a, int b) { return a * b; };
auto result2 = fl::invoke(lambda_func, 6, 7);
CHECK_EQ(42, result2);
// 3. Test fl::function with member function bound to object
TestFunctionClass obj;
fl::function<int()> member_func = fl::function<int()>(&TestFunctionClass::getValue, &obj);
auto result3 = fl::invoke(member_func);
CHECK_EQ(100, result3);
// 4. Test fl::function with member function bound to raw pointer
TestFunctionClass* raw_ptr = &obj;
fl::function<void(int)> setter_func = fl::function<void(int)>(&TestFunctionClass::setValue, raw_ptr);
fl::invoke(setter_func, 200);
CHECK_EQ(200, obj.value);
// 5. Test fl::function with member function bound to scoped_ptr
fl::scoped_ptr<TestFunctionClass> scoped_ptr(new TestFunctionClass);
scoped_ptr->setValue(300);
// Create function bound to scoped_ptr
fl::function<int()> scoped_getter = fl::function<int()>(&TestFunctionClass::getValue, scoped_ptr.get());
auto result4 = fl::invoke(scoped_getter);
CHECK_EQ(300, result4);
// 6. Test fl::function with member function with args bound to scoped_ptr
fl::function<int(int)> scoped_adder = fl::function<int(int)>(&TestFunctionClass::add, scoped_ptr.get());
auto result5 = fl::invoke(scoped_adder, 50);
CHECK_EQ(350, result5);
// 7. Test fl::function with complex lambda capturing scoped_ptr
auto complex_lambda = [&scoped_ptr](int multiplier) {
return fl::invoke(&TestFunctionClass::multiply, scoped_ptr, multiplier);
};
fl::function<int(int)> complex_func = complex_lambda;
auto result6 = fl::invoke(complex_func, 3);
CHECK_EQ(900, result6); // 300 * 3 = 900
// 8. Test nested fl::invoke calls
fl::function<int(int)> nested_func = [&scoped_ptr](int x) {
// Use fl::invoke inside a function that's also invoked with fl::invoke
return fl::invoke(&TestFunctionClass::add, scoped_ptr, x) * 2;
};
auto result7 = fl::invoke(nested_func, 25);
CHECK_EQ(650, result7); // (300 + 25) * 2 = 650
}