diff options
Diffstat (limited to 'src/testlib/qpropertytesthelper_p.h')
-rw-r--r-- | src/testlib/qpropertytesthelper_p.h | 99 |
1 files changed, 94 insertions, 5 deletions
diff --git a/src/testlib/qpropertytesthelper_p.h b/src/testlib/qpropertytesthelper_p.h index f2cb82cdd7..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(); @@ -189,6 +199,45 @@ void testReadWritePropertyBasics( // value didn't change -> the signal should not be emitted if (spy) 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( @@ -303,6 +371,27 @@ void testWriteOncePropertyBasics( 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 |