Files
unison/src/core/test/callback-test-suite.cc
2023-03-07 21:54:20 +00:00

1204 lines
34 KiB
C++

/*
* Copyright (c) 2009 University of Washington
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation;
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "ns3/callback.h"
#include "ns3/test.h"
#include <stdint.h>
using namespace ns3;
/**
* \file
* \ingroup callback-tests
* Callback test suite
*/
/**
* \ingroup core-tests
* \defgroup callback-tests Callback tests
*/
/**
* \ingroup callback-tests
*
* Test the basic Callback mechanism.
*/
class BasicCallbackTestCase : public TestCase
{
public:
BasicCallbackTestCase();
~BasicCallbackTestCase() override
{
}
/**
* Callback 1 target function.
*/
void Target1()
{
m_test1 = true;
}
/**
* Callback 2 target function.
* \return two.
*/
int Target2()
{
m_test2 = true;
return 2;
}
/**
* Callback 3 target function.
* \param a A parameter (unused).
*/
void Target3(double a [[maybe_unused]])
{
m_test3 = true;
}
/**
* Callback 4 target function.
* \param a A parameter (unused).
* \param b Another parameter (unused).
* \return four.
*/
int Target4(double a [[maybe_unused]], int b [[maybe_unused]])
{
m_test4 = true;
return 4;
}
private:
void DoRun() override;
void DoSetup() override;
bool m_test1; //!< true if Target1 has been called, false otherwise.
bool m_test2; //!< true if Target2 has been called, false otherwise.
bool m_test3; //!< true if Target3 has been called, false otherwise.
bool m_test4; //!< true if Target4 has been called, false otherwise.
};
/**
* Variable to verify that a callback has been called.
* @{
*/
static bool gBasicCallbackTest5;
static bool gBasicCallbackTest6;
static bool gBasicCallbackTest7;
static bool gBasicCallbackTest8;
/** @} */
/**
* Callback 5 target function.
*/
void
BasicCallbackTarget5()
{
gBasicCallbackTest5 = true;
}
/**
* Callback 6 target function.
*/
void
BasicCallbackTarget6(int)
{
gBasicCallbackTest6 = true;
}
/**
* Callback 6 target function.
* \param a The value passed by the callback.
* \return the value of the calling function.
*/
int
BasicCallbackTarget7(int a)
{
gBasicCallbackTest7 = true;
return a;
}
BasicCallbackTestCase::BasicCallbackTestCase()
: TestCase("Check basic Callback mechanism")
{
}
void
BasicCallbackTestCase::DoSetup()
{
m_test1 = false;
m_test2 = false;
m_test3 = false;
m_test4 = false;
gBasicCallbackTest5 = false;
gBasicCallbackTest6 = false;
gBasicCallbackTest7 = false;
gBasicCallbackTest8 = false;
}
void
BasicCallbackTestCase::DoRun()
{
//
// Make sure we can declare and compile a Callback pointing to a member
// function returning void and execute it.
//
Callback<void> target1(&BasicCallbackTestCase::Target1, this);
target1();
NS_TEST_ASSERT_MSG_EQ(m_test1, true, "Callback did not fire");
//
// Make sure we can declare and compile a Callback pointing to a member
// function that returns an int and execute it.
//
Callback<int> target2;
target2 = Callback<int>(&BasicCallbackTestCase::Target2, this);
target2();
NS_TEST_ASSERT_MSG_EQ(m_test2, true, "Callback did not fire");
//
// Make sure we can declare and compile a Callback pointing to a member
// function that returns void, takes a double parameter, and execute it.
//
Callback<void, double> target3 = Callback<void, double>(&BasicCallbackTestCase::Target3, this);
target3(0.0);
NS_TEST_ASSERT_MSG_EQ(m_test3, true, "Callback did not fire");
//
// Make sure we can declare and compile a Callback pointing to a member
// function that returns void, takes two parameters, and execute it.
//
Callback<int, double, int> target4 =
Callback<int, double, int>(&BasicCallbackTestCase::Target4, this);
target4(0.0, 1);
NS_TEST_ASSERT_MSG_EQ(m_test4, true, "Callback did not fire");
//
// Make sure we can declare and compile a Callback pointing to a non-member
// function that returns void, and execute it. This is a lower level call
// than MakeCallback so we have got to include at least two arguments to make
// sure that the constructor is properly disambiguated. If the arguments are
// not needed, we just pass in dummy values.
//
Callback<void> target5 = Callback<void>(&BasicCallbackTarget5);
target5();
NS_TEST_ASSERT_MSG_EQ(gBasicCallbackTest5, true, "Callback did not fire");
//
// Make sure we can declare and compile a Callback pointing to a non-member
// function that returns void, takes one integer argument and execute it.
//
Callback<void, int> target6 = Callback<void, int>(&BasicCallbackTarget6);
target6(1);
NS_TEST_ASSERT_MSG_EQ(gBasicCallbackTest6, true, "Callback did not fire");
//
// Make sure we can declare and compile a Callback pointing to a non-member
// function that returns int, takes one integer argument and execute it.
//
Callback<int, int> target7 = Callback<int, int>(&BasicCallbackTarget7);
target7(1);
NS_TEST_ASSERT_MSG_EQ(gBasicCallbackTest7, true, "Callback did not fire");
//
// Make sure we can create a callback pointing to a lambda.
//
Callback<double, int> target8([](int p) {
gBasicCallbackTest8 = true;
return p / 2.;
});
target8(5);
NS_TEST_ASSERT_MSG_EQ(gBasicCallbackTest8, true, "Callback did not fire");
}
/**
* \ingroup callback-tests
*
* Test the MakeCallback mechanism.
*/
class MakeCallbackTestCase : public TestCase
{
public:
MakeCallbackTestCase();
~MakeCallbackTestCase() override
{
}
/**
* Callback 1 target function.
*/
void Target1()
{
m_test1 = true;
}
/**
* Callback 2 target function.
* \return two.
*/
int Target2()
{
m_test2 = true;
return 2;
}
/**
* Callback 3 target function.
* \param a A parameter (unused).
*/
void Target3(double a [[maybe_unused]])
{
m_test3 = true;
}
/**
* Callback 4 target function.
* \param a A parameter (unused).
* \param b Another parameter (unused).
* \return four.
*/
int Target4(double a [[maybe_unused]], int b [[maybe_unused]])
{
m_test4 = true;
return 4;
}
private:
void DoRun() override;
void DoSetup() override;
bool m_test1; //!< true if Target1 has been called, false otherwise.
bool m_test2; //!< true if Target2 has been called, false otherwise.
bool m_test3; //!< true if Target3 has been called, false otherwise.
bool m_test4; //!< true if Target4 has been called, false otherwise.
};
/**
* Variable to verify that a callback has been called.
* @{
*/
static bool gMakeCallbackTest5;
static bool gMakeCallbackTest6;
static bool gMakeCallbackTest7;
/** @} */
/**
* MakeCallback 5 target function.
*/
void
MakeCallbackTarget5()
{
gMakeCallbackTest5 = true;
}
/**
* MakeCallback 6 target function.
*/
void
MakeCallbackTarget6(int)
{
gMakeCallbackTest6 = true;
}
/**
* MakeCallback 7 target function.
* \param a The value passed by the callback.
* \return the value of the calling function.
*/
int
MakeCallbackTarget7(int a)
{
gMakeCallbackTest7 = true;
return a;
}
MakeCallbackTestCase::MakeCallbackTestCase()
: TestCase("Check MakeCallback() mechanism")
{
}
void
MakeCallbackTestCase::DoSetup()
{
m_test1 = false;
m_test2 = false;
m_test3 = false;
m_test4 = false;
gMakeCallbackTest5 = false;
gMakeCallbackTest6 = false;
gMakeCallbackTest7 = false;
}
void
MakeCallbackTestCase::DoRun()
{
//
// Make sure we can declare and make a Callback pointing to a member
// function returning void and execute it.
//
Callback<void> target1 = MakeCallback(&MakeCallbackTestCase::Target1, this);
target1();
NS_TEST_ASSERT_MSG_EQ(m_test1, true, "Callback did not fire");
//
// Make sure we can declare and make a Callback pointing to a member
// function that returns an int and execute it.
//
Callback<int> target2 = MakeCallback(&MakeCallbackTestCase::Target2, this);
target2();
NS_TEST_ASSERT_MSG_EQ(m_test2, true, "Callback did not fire");
//
// Make sure we can declare and make a Callback pointing to a member
// function that returns void, takes a double parameter, and execute it.
//
Callback<void, double> target3 = MakeCallback(&MakeCallbackTestCase::Target3, this);
target3(0.0);
NS_TEST_ASSERT_MSG_EQ(m_test3, true, "Callback did not fire");
//
// Make sure we can declare and make a Callback pointing to a member
// function that returns void, takes two parameters, and execute it.
//
Callback<int, double, int> target4 = MakeCallback(&MakeCallbackTestCase::Target4, this);
target4(0.0, 1);
NS_TEST_ASSERT_MSG_EQ(m_test4, true, "Callback did not fire");
//
// Make sure we can declare and make a Callback pointing to a non-member
// function that returns void, and execute it. This uses a higher level call
// than in the basic tests so we do not need to include any dummy arguments
// here.
//
Callback<void> target5 = MakeCallback(&MakeCallbackTarget5);
target5();
NS_TEST_ASSERT_MSG_EQ(gMakeCallbackTest5, true, "Callback did not fire");
//
// Make sure we can declare and compile a Callback pointing to a non-member
// function that returns void, takes one integer argument and execute it.
// This uses a higher level call than in the basic tests so we do not need to
// include any dummy arguments here.
//
Callback<void, int> target6 = MakeCallback(&MakeCallbackTarget6);
target6(1);
NS_TEST_ASSERT_MSG_EQ(gMakeCallbackTest6, true, "Callback did not fire");
//
// Make sure we can declare and compile a Callback pointing to a non-member
// function that returns int, takes one integer argument and execute it.
// This uses a higher level call than in the basic tests so we do not need to
// include any dummy arguments here.
//
Callback<int, int> target7 = MakeCallback(&MakeCallbackTarget7);
target7(1);
NS_TEST_ASSERT_MSG_EQ(gMakeCallbackTest7, true, "Callback did not fire");
}
/**
* \ingroup callback-tests
*
* Test the MakeBoundCallback mechanism.
*/
class MakeBoundCallbackTestCase : public TestCase
{
public:
MakeBoundCallbackTestCase();
~MakeBoundCallbackTestCase() override
{
}
/**
* Member function to test the creation of a bound callback pointing to a member function
*
* \param a first argument
* \param b second argument
* \param c third argument
* \return the sum of the arguments
*/
int BoundTarget(int a, int b, int c)
{
return a + b + c;
}
private:
void DoRun() override;
void DoSetup() override;
};
/**
* Variable to verify that a callback has been called.
* @{
*/
static int gMakeBoundCallbackTest1;
static bool* gMakeBoundCallbackTest2;
static bool* gMakeBoundCallbackTest3a;
static int gMakeBoundCallbackTest3b;
static int gMakeBoundCallbackTest4a;
static int gMakeBoundCallbackTest4b;
static int gMakeBoundCallbackTest5a;
static int gMakeBoundCallbackTest5b;
static int gMakeBoundCallbackTest5c;
static int gMakeBoundCallbackTest6a;
static int gMakeBoundCallbackTest6b;
static int gMakeBoundCallbackTest6c;
static int gMakeBoundCallbackTest7a;
static int gMakeBoundCallbackTest7b;
static int gMakeBoundCallbackTest7c;
static int gMakeBoundCallbackTest8a;
static int gMakeBoundCallbackTest8b;
static int gMakeBoundCallbackTest8c;
static int gMakeBoundCallbackTest9a;
static int gMakeBoundCallbackTest9b;
static int gMakeBoundCallbackTest9c;
static int gMakeBoundCallbackTest9d;
/** @} */
// Note: doxygen compounds don not work due to params / return variability.
/**
* MakeBoundCallback 1 target function.
* \param a The value passed by the callback.
*/
void
MakeBoundCallbackTarget1(int a)
{
gMakeBoundCallbackTest1 = a;
}
/**
* MakeBoundCallback 2 target function.
* \param a The value passed by the callback.
*/
void
MakeBoundCallbackTarget2(bool* a)
{
gMakeBoundCallbackTest2 = a;
}
/**
* MakeBoundCallback 3 target function.
* \param a The value passed by the callback.
* \param b The value passed by the callback.
* \return the value 1234.
*/
int
MakeBoundCallbackTarget3(bool* a, int b)
{
gMakeBoundCallbackTest3a = a;
gMakeBoundCallbackTest3b = b;
return 1234;
}
/**
* MakeBoundCallback 4 target function.
* \param a The value passed by the callback.
* \param b The value passed by the callback.
*/
void
MakeBoundCallbackTarget4(int a, int b)
{
gMakeBoundCallbackTest4a = a;
gMakeBoundCallbackTest4b = b;
}
/**
* MakeBoundCallback 5 target function.
* \param a The value passed by the callback.
* \param b The value passed by the callback.
* \return the value 1234.
*/
int
MakeBoundCallbackTarget5(int a, int b)
{
gMakeBoundCallbackTest5a = a;
gMakeBoundCallbackTest5b = b;
return 1234;
}
/**
* MakeBoundCallback 5 target function.
* \param a The value passed by the callback.
* \param b The value passed by the callback.
* \param c The value passed by the callback.
* \return the value 1234.
*/
int
MakeBoundCallbackTarget6(int a, int b, int c)
{
gMakeBoundCallbackTest6a = a;
gMakeBoundCallbackTest6b = b;
gMakeBoundCallbackTest6c = c;
return 1234;
}
/**
* MakeBoundCallback 7 target function.
* \param a The value passed by the callback.
* \param b The value passed by the callback.
* \param c The value passed by the callback.
*/
void
MakeBoundCallbackTarget7(int a, int b, int c)
{
gMakeBoundCallbackTest7a = a;
gMakeBoundCallbackTest7b = b;
gMakeBoundCallbackTest7c = c;
}
/**
* MakeBoundCallback 8 target function.
* \param a The value passed by the callback.
* \param b The value passed by the callback.
* \param c The value passed by the callback.
* \return the value 1234.
*/
int
MakeBoundCallbackTarget8(int a, int b, int c)
{
gMakeBoundCallbackTest8a = a;
gMakeBoundCallbackTest8b = b;
gMakeBoundCallbackTest8c = c;
return 1234;
}
/**
* MakeBoundCallback 5 target function.
* \param a The value passed by the callback.
* \param b The value passed by the callback.
* \param c The value passed by the callback.
* \param d The value passed by the callback.
* \return the value 1234.
*/
int
MakeBoundCallbackTarget9(int a, int b, int c, int d)
{
gMakeBoundCallbackTest9a = a;
gMakeBoundCallbackTest9b = b;
gMakeBoundCallbackTest9c = c;
gMakeBoundCallbackTest9d = d;
return 1234;
}
MakeBoundCallbackTestCase::MakeBoundCallbackTestCase()
: TestCase("Check MakeBoundCallback() mechanism")
{
}
void
MakeBoundCallbackTestCase::DoSetup()
{
gMakeBoundCallbackTest1 = 0;
gMakeBoundCallbackTest2 = nullptr;
gMakeBoundCallbackTest3a = nullptr;
gMakeBoundCallbackTest3b = 0;
gMakeBoundCallbackTest4a = 0;
gMakeBoundCallbackTest4b = 0;
gMakeBoundCallbackTest5a = 0;
gMakeBoundCallbackTest5b = 0;
gMakeBoundCallbackTest5c = 0;
gMakeBoundCallbackTest6a = 0;
gMakeBoundCallbackTest6b = 0;
gMakeBoundCallbackTest6c = 0;
gMakeBoundCallbackTest7a = 0;
gMakeBoundCallbackTest7b = 0;
gMakeBoundCallbackTest7c = 0;
gMakeBoundCallbackTest8a = 0;
gMakeBoundCallbackTest8b = 0;
gMakeBoundCallbackTest8c = 0;
gMakeBoundCallbackTest9a = 0;
gMakeBoundCallbackTest9b = 0;
gMakeBoundCallbackTest9c = 0;
gMakeBoundCallbackTest9d = 0;
}
void
MakeBoundCallbackTestCase::DoRun()
{
//
// This is slightly tricky to explain. A bound Callback allows us to package
// up arguments for use later. The arguments are bound when the callback is
// created and the code that fires the Callback does not know they are there.
//
// Since the callback is *declared* according to the way it will be used, the
// arguments are not seen there. However, the target function of the callback
// will have the provided arguments present. The MakeBoundCallback template
// function is what connects the two together and where you provide the
// arguments to be bound.
//
// Here we declare a Callback that returns a void and takes no parameters.
// MakeBoundCallback connects this Callback to a target function that returns
// void and takes an integer argument. That integer argument is bound to the
// value 1234. When the Callback is fired, no integer argument is provided
// directly. The argument is provided by bound Callback mechanism.
//
Callback<void> target1 = MakeBoundCallback(&MakeBoundCallbackTarget1, 1234);
target1();
NS_TEST_ASSERT_MSG_EQ(gMakeBoundCallbackTest1,
1234,
"Callback did not fire or binding not correct");
//
// Make sure we can bind a pointer value (a common use case).
//
bool a;
Callback<void> target2 = MakeBoundCallback(&MakeBoundCallbackTarget2, &a);
target2();
NS_TEST_ASSERT_MSG_EQ(gMakeBoundCallbackTest2,
&a,
"Callback did not fire or binding not correct");
//
// Make sure we can mix and match bound and unbound arguments. This callback
// returns an integer so we should see that appear.
//
Callback<int, int> target3 = MakeBoundCallback(&MakeBoundCallbackTarget3, &a);
int result = target3(2468);
NS_TEST_ASSERT_MSG_EQ(result, 1234, "Return value of callback not correct");
NS_TEST_ASSERT_MSG_EQ(gMakeBoundCallbackTest3a,
&a,
"Callback did not fire or binding not correct");
NS_TEST_ASSERT_MSG_EQ(gMakeBoundCallbackTest3b,
2468,
"Callback did not fire or argument not correct");
//
// Test the TwoBound variant
//
Callback<void> target4 = MakeBoundCallback(&MakeBoundCallbackTarget4, 3456, 5678);
target4();
NS_TEST_ASSERT_MSG_EQ(gMakeBoundCallbackTest4a,
3456,
"Callback did not fire or binding not correct");
NS_TEST_ASSERT_MSG_EQ(gMakeBoundCallbackTest4b,
5678,
"Callback did not fire or binding not correct");
Callback<int> target5 = MakeBoundCallback(&MakeBoundCallbackTarget5, 3456, 5678);
int resultTwoA = target5();
NS_TEST_ASSERT_MSG_EQ(resultTwoA, 1234, "Return value of callback not correct");
NS_TEST_ASSERT_MSG_EQ(gMakeBoundCallbackTest5a,
3456,
"Callback did not fire or binding not correct");
NS_TEST_ASSERT_MSG_EQ(gMakeBoundCallbackTest5b,
5678,
"Callback did not fire or binding not correct");
Callback<int, int> target6 = MakeBoundCallback(&MakeBoundCallbackTarget6, 3456, 5678);
int resultTwoB = target6(6789);
NS_TEST_ASSERT_MSG_EQ(resultTwoB, 1234, "Return value of callback not correct");
NS_TEST_ASSERT_MSG_EQ(gMakeBoundCallbackTest6a,
3456,
"Callback did not fire or binding not correct");
NS_TEST_ASSERT_MSG_EQ(gMakeBoundCallbackTest6b,
5678,
"Callback did not fire or binding not correct");
NS_TEST_ASSERT_MSG_EQ(gMakeBoundCallbackTest6c,
6789,
"Callback did not fire or argument not correct");
//
// Test the ThreeBound variant
//
Callback<void> target7 = MakeBoundCallback(&MakeBoundCallbackTarget7, 2345, 3456, 4567);
target7();
NS_TEST_ASSERT_MSG_EQ(gMakeBoundCallbackTest7a,
2345,
"Callback did not fire or binding not correct");
NS_TEST_ASSERT_MSG_EQ(gMakeBoundCallbackTest7b,
3456,
"Callback did not fire or binding not correct");
NS_TEST_ASSERT_MSG_EQ(gMakeBoundCallbackTest7c,
4567,
"Callback did not fire or binding not correct");
Callback<int> target8 = MakeBoundCallback(&MakeBoundCallbackTarget8, 2345, 3456, 4567);
int resultThreeA = target8();
NS_TEST_ASSERT_MSG_EQ(resultThreeA, 1234, "Return value of callback not correct");
NS_TEST_ASSERT_MSG_EQ(gMakeBoundCallbackTest8a,
2345,
"Callback did not fire or binding not correct");
NS_TEST_ASSERT_MSG_EQ(gMakeBoundCallbackTest8b,
3456,
"Callback did not fire or binding not correct");
NS_TEST_ASSERT_MSG_EQ(gMakeBoundCallbackTest8c,
4567,
"Callback did not fire or binding not correct");
Callback<int, int> target9 = MakeBoundCallback(&MakeBoundCallbackTarget9, 2345, 3456, 4567);
int resultThreeB = target9(5678);
NS_TEST_ASSERT_MSG_EQ(resultThreeB, 1234, "Return value of callback not correct");
NS_TEST_ASSERT_MSG_EQ(gMakeBoundCallbackTest9a,
2345,
"Callback did not fire or binding not correct");
NS_TEST_ASSERT_MSG_EQ(gMakeBoundCallbackTest9b,
3456,
"Callback did not fire or binding not correct");
NS_TEST_ASSERT_MSG_EQ(gMakeBoundCallbackTest9c,
4567,
"Callback did not fire or binding not correct");
NS_TEST_ASSERT_MSG_EQ(gMakeBoundCallbackTest9d,
5678,
"Callback did not fire or binding not correct");
//
// Test creating a bound callback pointing to a member function. Also, make sure that
// an argument can be bound to a reference.
//
int b = 1;
Callback<int> target10 =
Callback<int>(&MakeBoundCallbackTestCase::BoundTarget, this, std::ref(b), 5, 2);
NS_TEST_ASSERT_MSG_EQ(target10(), 8, "Bound callback returned an unexpected value");
b = 3;
NS_TEST_ASSERT_MSG_EQ(target10(), 10, "Bound callback returned an unexpected value");
}
/**
* \ingroup callback-tests
*
* Test the callback equality implementation.
*/
class CallbackEqualityTestCase : public TestCase
{
public:
CallbackEqualityTestCase();
~CallbackEqualityTestCase() override
{
}
/**
* Member function used to test equality of callbacks.
*
* \param a first argument
* \param b second argument
* \return the sum of the arguments
*/
int TargetMember(double a, int b)
{
return static_cast<int>(a) + b;
}
private:
void DoRun() override;
void DoSetup() override;
};
/**
* Non-member function used to test equality of callbacks.
*
* \param a first argument
* \param b second argument
* \return the sum of the arguments
*/
int
CallbackEqualityTarget(double a, int b)
{
return static_cast<int>(a) + b;
}
CallbackEqualityTestCase::CallbackEqualityTestCase()
: TestCase("Check Callback equality test")
{
}
void
CallbackEqualityTestCase::DoSetup()
{
}
void
CallbackEqualityTestCase::DoRun()
{
//
// Make sure that two callbacks pointing to the same member function
// compare equal.
//
Callback<int, double, int> target1a(&CallbackEqualityTestCase::TargetMember, this);
Callback<int, double, int> target1b =
MakeCallback(&CallbackEqualityTestCase::TargetMember, this);
NS_TEST_ASSERT_MSG_EQ(target1a.IsEqual(target1b), true, "Equality test failed");
//
// Make sure that two callbacks pointing to the same member function
// compare equal, after binding the first argument.
//
Callback<int, int> target2a(&CallbackEqualityTestCase::TargetMember, this, 1.5);
Callback<int, int> target2b = target1b.Bind(1.5);
NS_TEST_ASSERT_MSG_EQ(target2a.IsEqual(target2b), true, "Equality test failed");
//
// Make sure that two callbacks pointing to the same member function
// compare equal, after binding the first two arguments.
//
Callback<int> target3a(target2a, 2);
Callback<int> target3b = target1b.Bind(1.5, 2);
NS_TEST_ASSERT_MSG_EQ(target3a.IsEqual(target3b), true, "Equality test failed");
//
// Make sure that two callbacks pointing to the same member function do
// not compare equal if they are bound to different arguments.
//
Callback<int> target3c = target1b.Bind(1.5, 3);
NS_TEST_ASSERT_MSG_EQ(target3c.IsEqual(target3b), false, "Equality test failed");
//
// Make sure that two callbacks pointing to the same non-member function
// compare equal.
//
Callback<int, double, int> target4a(&CallbackEqualityTarget);
Callback<int, double, int> target4b = MakeCallback(&CallbackEqualityTarget);
NS_TEST_ASSERT_MSG_EQ(target4a.IsEqual(target4b), true, "Equality test failed");
//
// Make sure that two callbacks pointing to the same non-member function
// compare equal, after binding the first argument.
//
Callback<int, int> target5a(&CallbackEqualityTarget, 1.5);
Callback<int, int> target5b = target4b.Bind(1.5);
NS_TEST_ASSERT_MSG_EQ(target5a.IsEqual(target5b), true, "Equality test failed");
//
// Make sure that two callbacks pointing to the same non-member function
// compare equal, after binding the first two arguments.
//
Callback<int> target6a(target5a, 2);
Callback<int> target6b = target4b.Bind(1.5, 2);
NS_TEST_ASSERT_MSG_EQ(target6a.IsEqual(target6b), true, "Equality test failed");
//
// Make sure that two callbacks pointing to the same non-member function do
// not compare equal if they are bound to different arguments.
//
Callback<int> target6c = target4b.Bind(1.5, 3);
NS_TEST_ASSERT_MSG_EQ(target6c.IsEqual(target6b), false, "Equality test failed");
//
// Check that we cannot compare lambdas.
//
Callback<double, int, double> target7a([](int p, double d) { return d + p / 2.; });
Callback<double, int, double> target7b([](int p, double d) { return d + p / 2.; });
NS_TEST_ASSERT_MSG_EQ(target7a.IsEqual(target7b), false, "Compared lambdas?");
//
// Make sure that a callback pointing to a lambda and a copy of it compare equal.
//
Callback<double, int, double> target7c(target7b);
NS_TEST_ASSERT_MSG_EQ(target7c.IsEqual(target7b), true, "Equality test failed");
//
// Make sure that a callback pointing to a lambda and a copy of it compare equal,
// after binding the first argument.
//
Callback<double, double> target8b = target7b.Bind(1);
Callback<double, double> target8c(target7c, 1);
NS_TEST_ASSERT_MSG_EQ(target8b.IsEqual(target8c), true, "Equality test failed");
//
// Make sure that a callback pointing to a lambda and a copy of it compare equal,
// after binding the first two arguments.
//
Callback<double> target9b = target8b.Bind(2.0);
Callback<double> target9c(target8c, 2.0);
NS_TEST_ASSERT_MSG_EQ(target9b.IsEqual(target9c), true, "Equality test failed");
//
// Make sure that a callback pointing to a lambda and a copy of it do not compare
// equal if they are bound to different arguments.
//
Callback<double> target9d = target8b.Bind(4);
NS_TEST_ASSERT_MSG_EQ(target9d.IsEqual(target9c), false, "Equality test failed");
}
/**
* \ingroup callback-tests
*
* Test the Nullify mechanism.
*/
class NullifyCallbackTestCase : public TestCase
{
public:
NullifyCallbackTestCase();
~NullifyCallbackTestCase() override
{
}
/**
* Callback 1 target function.
*/
void Target1()
{
m_test1 = true;
}
private:
void DoRun() override;
void DoSetup() override;
bool m_test1; //!< true if Target1 has been called, false otherwise.
};
NullifyCallbackTestCase::NullifyCallbackTestCase()
: TestCase("Check Nullify() and IsNull()")
{
}
void
NullifyCallbackTestCase::DoSetup()
{
m_test1 = false;
}
void
NullifyCallbackTestCase::DoRun()
{
//
// Make sure we can declare and make a Callback pointing to a member
// function returning void and execute it.
//
Callback<void> target1 = MakeCallback(&NullifyCallbackTestCase::Target1, this);
target1();
NS_TEST_ASSERT_MSG_EQ(m_test1, true, "Callback did not fire");
NS_TEST_ASSERT_MSG_EQ(target1.IsNull(), false, "Working Callback reports IsNull()");
target1.Nullify();
NS_TEST_ASSERT_MSG_EQ(target1.IsNull(), true, "Nullified Callback reports not IsNull()");
}
/**
* \ingroup callback-tests
*
* Make sure that various MakeCallback template functions compile and execute;
* doesn't check an results of the execution.
*/
class MakeCallbackTemplatesTestCase : public TestCase
{
public:
MakeCallbackTemplatesTestCase();
~MakeCallbackTemplatesTestCase() override
{
}
/**
* Callback 1 target function.
*/
void Target1()
{
m_test1 = true;
}
private:
void DoRun() override;
bool m_test1; //!< true if Target1 has been called, false otherwise.
};
/**
* Test function - does nothing.
* @{
*/
void TestFZero(){};
void TestFOne(int){};
void TestFTwo(int, int){};
void TestFThree(int, int, int){};
void TestFFour(int, int, int, int){};
void TestFFive(int, int, int, int, int){};
void TestFSix(int, int, int, int, int, int){};
void TestFROne(int&){};
void TestFRTwo(int&, int&){};
void TestFRThree(int&, int&, int&){};
void TestFRFour(int&, int&, int&, int&){};
void TestFRFive(int&, int&, int&, int&, int&){};
void TestFRSix(int&, int&, int&, int&, int&, int&){};
/** @} */
/**
* \ingroup callback-tests
*
* Class used to check the capability of callbacks to call
* public, protected, and private functions.
*/
class CallbackTestParent
{
public:
/// A public function.
void PublicParent()
{
}
protected:
/// A protected function.
void ProtectedParent()
{
}
/// A static protected function.
static void StaticProtectedParent()
{
}
private:
/// A private function.
void PrivateParent()
{
}
};
/**
* \ingroup callback-tests
*
* Derived class used to check the capability of callbacks to call
* public, protected, and private functions.
*/
class CallbackTestClass : public CallbackTestParent
{
public:
/**
* Test function - does nothing.
* @{
*/
void TestZero(){};
void TestOne(int){};
void TestTwo(int, int){};
void TestThree(int, int, int){};
void TestFour(int, int, int, int){};
void TestFive(int, int, int, int, int){};
void TestSix(int, int, int, int, int, int){};
void TestCZero() const {};
void TestCOne(int) const {};
void TestCTwo(int, int) const {};
void TestCThree(int, int, int) const {};
void TestCFour(int, int, int, int) const {};
void TestCFive(int, int, int, int, int) const {};
void TestCSix(int, int, int, int, int, int) const {};
/** @} */
/**
* Tries to make a callback to public and protected functions of a class.
* Private are not tested because, as expected, the compilation fails.
*/
void CheckParentalRights()
{
MakeCallback(&CallbackTestParent::StaticProtectedParent);
MakeCallback(&CallbackTestParent::PublicParent, this);
MakeCallback(&CallbackTestClass::ProtectedParent, this);
// as expected, fails.
// MakeCallback (&CallbackTestParent::PrivateParent, this);
// as expected, fails.
// Pointers do not carry the access restriction info, so it is forbidden
// to generate a pointer to a parent's protected function, because
// this could lead to un-protect them, e.g., by making it public.
// MakeCallback (&CallbackTestParent::ProtectedParent, this);
}
};
MakeCallbackTemplatesTestCase::MakeCallbackTemplatesTestCase()
: TestCase("Check various MakeCallback() template functions")
{
}
void
MakeCallbackTemplatesTestCase::DoRun()
{
CallbackTestClass that;
MakeCallback(&CallbackTestClass::TestZero, &that);
MakeCallback(&CallbackTestClass::TestOne, &that);
MakeCallback(&CallbackTestClass::TestTwo, &that);
MakeCallback(&CallbackTestClass::TestThree, &that);
MakeCallback(&CallbackTestClass::TestFour, &that);
MakeCallback(&CallbackTestClass::TestFive, &that);
MakeCallback(&CallbackTestClass::TestSix, &that);
MakeCallback(&CallbackTestClass::TestCZero, &that);
MakeCallback(&CallbackTestClass::TestCOne, &that);
MakeCallback(&CallbackTestClass::TestCTwo, &that);
MakeCallback(&CallbackTestClass::TestCThree, &that);
MakeCallback(&CallbackTestClass::TestCFour, &that);
MakeCallback(&CallbackTestClass::TestCFive, &that);
MakeCallback(&CallbackTestClass::TestCSix, &that);
MakeCallback(&TestFZero);
MakeCallback(&TestFOne);
MakeCallback(&TestFTwo);
MakeCallback(&TestFThree);
MakeCallback(&TestFFour);
MakeCallback(&TestFFive);
MakeCallback(&TestFSix);
MakeCallback(&TestFROne);
MakeCallback(&TestFRTwo);
MakeCallback(&TestFRThree);
MakeCallback(&TestFRFour);
MakeCallback(&TestFRFive);
MakeCallback(&TestFRSix);
MakeBoundCallback(&TestFOne, 1);
MakeBoundCallback(&TestFTwo, 1);
MakeBoundCallback(&TestFThree, 1);
MakeBoundCallback(&TestFFour, 1);
MakeBoundCallback(&TestFFive, 1);
MakeBoundCallback(&TestFROne, 1);
MakeBoundCallback(&TestFRTwo, 1);
MakeBoundCallback(&TestFRThree, 1);
MakeBoundCallback(&TestFRFour, 1);
MakeBoundCallback(&TestFRFive, 1);
that.CheckParentalRights();
}
/**
* \ingroup callback-tests
*
* \brief The callback Test Suite.
*/
class CallbackTestSuite : public TestSuite
{
public:
CallbackTestSuite();
};
CallbackTestSuite::CallbackTestSuite()
: TestSuite("callback", UNIT)
{
AddTestCase(new BasicCallbackTestCase, TestCase::QUICK);
AddTestCase(new MakeCallbackTestCase, TestCase::QUICK);
AddTestCase(new MakeBoundCallbackTestCase, TestCase::QUICK);
AddTestCase(new CallbackEqualityTestCase, TestCase::QUICK);
AddTestCase(new NullifyCallbackTestCase, TestCase::QUICK);
AddTestCase(new MakeCallbackTemplatesTestCase, TestCase::QUICK);
}
static CallbackTestSuite g_gallbackTestSuite; //!< Static variable for test initialization