summaryrefslogtreecommitdiffstats
path: root/src/testlib/qpropertytesthelper_p.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/testlib/qpropertytesthelper_p.h')
-rw-r--r--src/testlib/qpropertytesthelper_p.h117
1 files changed, 103 insertions, 14 deletions
diff --git a/src/testlib/qpropertytesthelper_p.h b/src/testlib/qpropertytesthelper_p.h
index b5bd8d2583..c691802a39 100644
--- a/src/testlib/qpropertytesthelper_p.h
+++ b/src/testlib/qpropertytesthelper_p.h
@@ -84,6 +84,14 @@ namespace QTestPrivate {
allocate its returned string using \c {new char[]}, so that it can be used
in place of \l {QTest::toString()}.
+ The \a helperConstructor method is used to create another instance of
+ \c TestedClass. This instance is used to test for binding loops. By default,
+ the method returns a default-constructed \c TestedClass. A custom
+ \a helperConstructor should be provided if \c TestedClass is not
+ default-constructible. Some very specific properties cannot be tested for
+ binding loops. Pass a lambda that returns an \c {std::nullptr} as
+ \a helperConstructor in such case.
+
\note Any test calling this method will need to call
\code
if (QTest::currentTestFailed())
@@ -100,7 +108,9 @@ void testReadWritePropertyBasics(
std::function<bool(const PropertyType &, const PropertyType &)> comparator =
[](const PropertyType &lhs, const PropertyType &rhs) { return lhs == rhs; },
std::function<char *(const PropertyType &)> represent =
- [](const PropertyType &val) { return QTest::toString(val); })
+ [](const PropertyType &val) { return QTest::toString(val); },
+ std::function<std::unique_ptr<TestedClass>(void)> helperConstructor =
+ []() { return std::make_unique<TestedClass>(); })
{
// get the property
const QMetaObject *metaObject = instance.metaObject();
@@ -129,7 +139,7 @@ void testReadWritePropertyBasics(
testedObj.property(propertyName).template value<PropertyType>(), initial, comparator,
represent);
if (spy)
- QCOMPARE(spy->count(), 1);
+ QCOMPARE(spy->size(), 1);
QUntypedBindable bindable = metaProperty.bindable(&instance);
@@ -148,7 +158,7 @@ void testReadWritePropertyBasics(
QPROPERTY_TEST_COMPARISON_HELPER(propObserver.value(), changed, comparator, represent);
QPROPERTY_TEST_COMPARISON_HELPER(propObserverLambda.value(), changed, comparator, represent);
if (spy)
- QCOMPARE(spy->count(), 2);
+ QCOMPARE(spy->size(), 2);
// Bind object's property to other property
QProperty<PropertyType> propSetter(initial);
@@ -162,7 +172,7 @@ void testReadWritePropertyBasics(
QPROPERTY_TEST_COMPARISON_HELPER(propObserver.value(), initial, comparator, represent);
QPROPERTY_TEST_COMPARISON_HELPER(propObserverLambda.value(), initial, comparator, represent);
if (spy)
- QCOMPARE(spy->count(), 3);
+ QCOMPARE(spy->size(), 3);
// Count notifications triggered; should only happen on actual change.
int updateCount = 0;
@@ -177,7 +187,7 @@ void testReadWritePropertyBasics(
QPROPERTY_TEST_COMPARISON_HELPER(propObserverLambda.value(), changed, comparator, represent);
QCOMPARE(updateCount, 1);
if (spy)
- QCOMPARE(spy->count(), 4);
+ QCOMPARE(spy->size(), 4);
// Test that manually setting the value (even the same one) breaks the
// binding.
@@ -188,7 +198,46 @@ void testReadWritePropertyBasics(
// value didn't change -> the signal should not be emitted
if (spy)
- QCOMPARE(spy->count(), 4);
+ QCOMPARE(spy->size(), 4);
+
+ // test binding loop
+ if (std::unique_ptr<TestedClass> helperObj = helperConstructor()) {
+ // Reset to 'initial', so that the binding loop test could check the
+ // 'changed' value, because some tests already rely on the 'instance' to
+ // have the 'changed' value once this test passes
+ testedObj.setProperty(propertyName, QVariant::fromValue(initial));
+ const QPropertyBinding<PropertyType> binding([&]() {
+ QObject *obj = static_cast<QObject *>(helperObj.get());
+ obj->setProperty(propertyName, QVariant::fromValue(changed));
+ return obj->property(propertyName).template value<PropertyType>();
+ }, {});
+ bindable.setBinding(binding);
+ QPROPERTY_TEST_COMPARISON_HELPER(
+ testedObj.property(propertyName).template value<PropertyType>(), changed,
+ comparator, represent);
+ QVERIFY2(!binding.error().hasError(), qPrintable(binding.error().description()));
+ }
+}
+
+/*!
+ \internal
+ \overload
+
+ This overload supports the case where the caller only needs to override
+ the default for \a helperConstructor. It uses the defaults for all the other
+ parameters.
+*/
+template<typename TestedClass, typename PropertyType>
+void testReadWritePropertyBasics(
+ TestedClass &instance, const PropertyType &initial, const PropertyType &changed,
+ const char *propertyName,
+ std::function<std::unique_ptr<TestedClass>(void)> helperConstructor)
+{
+ testReadWritePropertyBasics<TestedClass, PropertyType>(
+ instance, initial, changed, propertyName,
+ [](const PropertyType &lhs, const PropertyType &rhs) { return lhs == rhs; },
+ [](const PropertyType &val) { return QTest::toString(val); },
+ helperConstructor);
}
/*!
@@ -224,6 +273,14 @@ void testReadWritePropertyBasics(
allocate its returned string using \c {new char[]}, so that it can be used
in place of \l {QTest::toString()}.
+ The \a helperConstructor method is used to create another instance of
+ \c TestedClass. This instance is used to test for binding loops. By default,
+ the method returns a default-constructed \c TestedClass. A custom
+ \a helperConstructor should be provided if \c TestedClass is not
+ default-constructible. Some very specific properties cannot be tested for
+ binding loops. Pass a lambda that returns an \c {std::nullptr} as
+ \a helperConstructor in such case.
+
\note Any test calling this method will need to call
\code
if (QTest::currentTestFailed())
@@ -242,7 +299,9 @@ void testWriteOncePropertyBasics(
std::function<bool(const PropertyType &, const PropertyType &)> comparator =
[](const PropertyType &lhs, const PropertyType &rhs) { return lhs == rhs; },
std::function<char *(const PropertyType &)> represent =
- [](const PropertyType &val) { return QTest::toString(val); })
+ [](const PropertyType &val) { return QTest::toString(val); },
+ std::function<std::unique_ptr<TestedClass>(void)> helperConstructor =
+ []() { return std::make_unique<TestedClass>(); })
{
// get the property
const QMetaObject *metaObject = instance.metaObject();
@@ -276,10 +335,19 @@ void testWriteOncePropertyBasics(
propObserver.setBinding(bindable.makeBinding());
QPROPERTY_TEST_COMPARISON_HELPER(propObserver.value(), prior, comparator, represent);
- // Create a binding that sets the 'changed' value to the property
- QProperty<PropertyType> propSetter(changed);
+ // Create a binding that sets the 'changed' value to the property.
+ // This also tests binding loops.
QVERIFY(!bindable.hasBinding());
- bindable.setBinding(Qt::makePropertyBinding(propSetter));
+ std::unique_ptr<TestedClass> helperObj = helperConstructor();
+ QProperty<PropertyType> propSetter(changed); // if the helperConstructor() returns nullptr
+ const QPropertyBinding<PropertyType> binding = helperObj
+ ? Qt::makePropertyBinding([&]() {
+ QObject *obj = static_cast<QObject *>(helperObj.get());
+ obj->setProperty(propertyName, QVariant::fromValue(changed));
+ return obj->property(propertyName).template value<PropertyType>();
+ })
+ : Qt::makePropertyBinding(propSetter);
+ bindable.setBinding(binding);
QVERIFY(bindable.hasBinding());
QPROPERTY_TEST_COMPARISON_HELPER(
@@ -287,7 +355,7 @@ void testWriteOncePropertyBasics(
represent);
QPROPERTY_TEST_COMPARISON_HELPER(propObserver.value(), changed, comparator, represent);
if (spy)
- QCOMPARE(spy->count(), 1);
+ QCOMPARE(spy->size(), 1);
// Attempt to set back the 'prior' value and verify that it has no effect
testedObj.setProperty(propertyName, QVariant::fromValue(prior));
@@ -296,13 +364,34 @@ void testWriteOncePropertyBasics(
represent);
QPROPERTY_TEST_COMPARISON_HELPER(propObserver.value(), changed, comparator, represent);
if (spy)
- QCOMPARE(spy->count(), 1);
+ QCOMPARE(spy->size(), 1);
if (bindingPreservedOnWrite)
QVERIFY(bindable.hasBinding());
else
QVERIFY(!bindable.hasBinding());
}
+/*!
+ \internal
+ \overload
+
+ This overload supports the case where the caller only needs to override
+ the default for \a helperConstructor. It uses the defaults for all the other
+ parameters.
+*/
+template<typename TestedClass, typename PropertyType>
+void testWriteOncePropertyBasics(
+ TestedClass &instance, const PropertyType &prior, const PropertyType &changed,
+ const char *propertyName,
+ bool bindingPreservedOnWrite,
+ std::function<std::unique_ptr<TestedClass>(void)> helperConstructor)
+{
+ testWriteOncePropertyBasics<TestedClass, PropertyType>(
+ instance, prior, changed, propertyName, bindingPreservedOnWrite,
+ [](const PropertyType &lhs, const PropertyType &rhs) { return lhs == rhs; },
+ [](const PropertyType &val) { return QTest::toString(val); },
+ helperConstructor);
+}
/*!
\internal
@@ -386,7 +475,7 @@ void testReadOnlyPropertyBasics(
testedObj.property(propertyName).template value<PropertyType>(), initial, comparator,
represent);
if (spy)
- QCOMPARE(spy->count(), 0);
+ QCOMPARE(spy->size(), 0);
QProperty<PropertyType> propObserver;
propObserver.setBinding(bindable.makeBinding());
@@ -402,7 +491,7 @@ void testReadOnlyPropertyBasics(
QPROPERTY_TEST_COMPARISON_HELPER(propObserver.value(), changed, comparator, represent);
if (spy)
- QCOMPARE(spy->count(), 1);
+ QCOMPARE(spy->size(), 1);
}
} // namespace QTestPrivate