diff options
author | Juha Vuolle <juha.vuolle@insta.fi> | 2021-02-23 15:33:34 +0200 |
---|---|---|
committer | Juha Vuolle <juha.vuolle@insta.fi> | 2021-05-03 13:51:54 +0300 |
commit | 00f3ec2b5c11aa399d72f8daaf0a45150905123e (patch) | |
tree | e91db0d8ed1fc227fe71ea4dbd94f27a77214e2e /tests/auto | |
parent | f87d6ad8eabc03be67bc23136ec0bae488d8ee28 (diff) |
QtStateMachine QML-facing properties' bindable support part 1
This commit covers these QML-facing classes:
QHistoryState
QState
QAbstractState
Task-number: QTBUG-91375
Change-Id: Ic66977c4f25198c19052f48754a956042caa3632
Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
Diffstat (limited to 'tests/auto')
-rw-r--r-- | tests/auto/qml/scxmlqmlcpp/tst_scxmlqmlcpp.cpp | 69 | ||||
-rw-r--r-- | tests/auto/qstatemachine/qstatemachine/tst_qstatemachine.cpp | 59 | ||||
-rw-r--r-- | tests/auto/shared/bindableutils.h | 104 |
3 files changed, 164 insertions, 68 deletions
diff --git a/tests/auto/qml/scxmlqmlcpp/tst_scxmlqmlcpp.cpp b/tests/auto/qml/scxmlqmlcpp/tst_scxmlqmlcpp.cpp index 408530e..73d4a8e 100644 --- a/tests/auto/qml/scxmlqmlcpp/tst_scxmlqmlcpp.cpp +++ b/tests/auto/qml/scxmlqmlcpp/tst_scxmlqmlcpp.cpp @@ -38,6 +38,7 @@ #include <QtQml/QQmlEngine> #include <QtQml/QQmlComponent> #include <memory> +#include "../../shared/bindableutils.h" #include <QDebug> @@ -46,74 +47,6 @@ class tst_scxmlqmlcpp: public QObject Q_OBJECT private slots: void bindings(); -private: - - // This is a helper function to test basics of typical bindable - // properties that are writable. Primarily ensure: - // - properties work as before bindings - // - added bindable aspects work - // - // "TestedClass" is the class type we are testing - // "TestedData" is the data type of the property we are testing - // "testedClass" is an instance of the class we are interested testing - // "data1" and "data2" are two different instances of property data to set and get - // "propertyName" is the name of the property we are interested in testing - template<typename TestedClass, typename TestedData> - void testWritableBindableBasics(TestedClass& testedClass, TestedData data1, - TestedData data2, const char* propertyName) - { - // Get the property we are testing - const QMetaObject *metaObject = testedClass.metaObject(); - QMetaProperty metaProperty = metaObject->property(metaObject->indexOfProperty(propertyName)); - - // Generate a string to help identify failures (as this is a generic template) - QString id(metaObject->className()); - id.append(QStringLiteral("::")); - id.append(metaProperty.name()); - - // Fail gracefully if preconditions to use this helper function are not met: - QVERIFY2(metaProperty.isBindable() && metaProperty.isWritable() - && metaProperty.hasNotifySignal(), qPrintable(id)); - // Create a signal spy for the property changed -signal - QSignalSpy spy(&testedClass, metaProperty.notifySignal()); - QUntypedBindable bindable = metaProperty.bindable(&testedClass); - - // Test basic property read and write - testedClass.setProperty(propertyName, QVariant::fromValue(data1)); - QVERIFY2(testedClass.property(propertyName).template value<TestedData>() == data1, qPrintable(id)); - QVERIFY2(spy.count() == 1, qPrintable(id + ", actual: " + QString::number(spy.count()))); - - // Test setting a binding as a source for the property - QProperty<TestedData> property1(data1); - QProperty<TestedData> property2(data2); - QVERIFY2(!bindable.hasBinding(), qPrintable(id)); - bindable.setBinding(Qt::makePropertyBinding(property2)); - QVERIFY2(bindable.hasBinding(), qPrintable(id)); - // Check that the value also changed - QVERIFY2(testedClass.property(propertyName).template value<TestedData>() == data2, qPrintable(id)); - QVERIFY2(spy.count() == 2, qPrintable(id + ", actual: " + QString::number(spy.count()))); - // Same test but with a lambda binding (cast to be able to set the lambda directly) - QBindable<TestedData> *typedBindable = static_cast<QBindable<TestedData>*>(&bindable); - typedBindable->setBinding([&](){ return property1.value(); }); - QVERIFY2(typedBindable->hasBinding(), qPrintable(id)); - QVERIFY2(testedClass.property(propertyName).template value<TestedData>() == data1, qPrintable(id)); - QVERIFY2(spy.count() == 3, qPrintable(id + ", actual: " + QString::number(spy.count()))); - - // Remove binding by setting a value directly - QVERIFY2(bindable.hasBinding(), qPrintable(id)); - testedClass.setProperty(propertyName, QVariant::fromValue(data2)); - QVERIFY2(testedClass.property(propertyName).template value<TestedData>() == data2, qPrintable(id)); - QVERIFY2(!bindable.hasBinding(), qPrintable(id)); - QVERIFY2(spy.count() == 4, qPrintable(id + ", actual: " + QString::number(spy.count()))); - - // Test using the property as the source in a binding - QProperty<bool> data1Used([&](){ - return testedClass.property(propertyName).template value<TestedData>() == data1; - }); - QVERIFY2(data1Used == false, qPrintable(id)); - testedClass.setProperty(propertyName, QVariant::fromValue(data1)); - QVERIFY2(data1Used == true, qPrintable(id)); - } }; void tst_scxmlqmlcpp::bindings() { diff --git a/tests/auto/qstatemachine/qstatemachine/tst_qstatemachine.cpp b/tests/auto/qstatemachine/qstatemachine/tst_qstatemachine.cpp index de132df..4aecf8f 100644 --- a/tests/auto/qstatemachine/qstatemachine/tst_qstatemachine.cpp +++ b/tests/auto/qstatemachine/qstatemachine/tst_qstatemachine.cpp @@ -48,6 +48,8 @@ #include "private/qstate_p.h" #include "private/qstatemachine_p.h" +#include "../../shared/bindableutils.h" + static int globalTick; // Run exec for a maximum of TIMEOUT msecs @@ -260,6 +262,7 @@ private slots: void cancelDelayedEventWithChrono(); void postDelayedEventWithChronoAndStop(); void postDelayedEventWithChronoFromThread(); + void bindings(); }; class TestState : public QState @@ -6858,5 +6861,61 @@ void tst_QStateMachine::postDelayedEventWithChronoFromThread() #endif } +void tst_QStateMachine::bindings() +{ + QStateMachine machine; + TestState *state1 = new TestState(&machine); + TestTransition *transition1 = new TestTransition(state1); + TestTransition *transition2 = new TestTransition(state1); + + // -- QHistoryState::defaultTransition + QHistoryState *historyState = new QHistoryState(&machine); + testWritableBindableBasics<QHistoryState, QAbstractTransition*>( + *historyState, transition1, transition2, "defaultTransition"); + + // -- QHistoryState::historyType + QHistoryState::HistoryType type1 = QHistoryState::HistoryType::DeepHistory; + QHistoryState::HistoryType type2 = QHistoryState::HistoryType::ShallowHistory; + testWritableBindableBasics<QHistoryState, QHistoryState::HistoryType>( + *historyState, type1, type2, "historyType"); + + // -- QState::initialState + QAbstractState *is1 = new QState(state1); + QAbstractState *is2 = new QState(state1); + testWritableBindableBasics<QState, QAbstractState*>( + *state1, is1, is2, "initialState"); + + // -- QState::errorState + testWritableBindableBasics<QState, QAbstractState*>( + *state1, is1, is2, "errorState"); + + // -- QState::childMode + // Make a new state as re-use of state1 would yield irrelevant warnings + TestState *state2 = new TestState(&machine); + QState::ChildMode mode1 = QState::ChildMode::ParallelStates; + QState::ChildMode mode2 = QState::ChildMode::ExclusiveStates; + testWritableBindableBasics<QState, QState::ChildMode>( + *state2, mode1, mode2, "childMode"); + + // -- QAbstractState::active + QState *startState = new QState(&machine); + QFinalState *endState = new QFinalState(&machine); + DEFINE_ACTIVE_SPY(startState); + DEFINE_ACTIVE_SPY(endState); + machine.setInitialState(startState); + startState->addTransition(endState); + + // Create a binding to the "active" property + QProperty<bool> active([&](){ return endState->active(); }); + QVERIFY(!active); + machine.start(); + // startState should get "enter/active == true" + "exit/active == false" + QTRY_COMPARE(startState_activeSpy.count(), 2); + // endState should get "enter/active == true" + QTRY_COMPARE(endState_activeSpy.count(), 1); + // Verify that the "active" value changed via binding + QVERIFY(active); +} + QTEST_MAIN(tst_QStateMachine) #include "tst_qstatemachine.moc" diff --git a/tests/auto/shared/bindableutils.h b/tests/auto/shared/bindableutils.h new file mode 100644 index 0000000..3e93752 --- /dev/null +++ b/tests/auto/shared/bindableutils.h @@ -0,0 +1,104 @@ +/**************************************************************************** +** +** Copyright (C) 2021 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtScxml module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef BINDABLEUTILS_H +#define BINDABLEUTILS_H + +#include <QtTest> +#include <QObject> + +// This is a helper function to test basics of typical bindable +// properties that are writable. Primarily ensure: +// - properties work as before bindings +// - added bindable aspects work +// +// "TestedClass" is the class type we are testing +// "TestedData" is the data type of the property we are testing +// "testedClass" is an instance of the class we are interested testing +// "data1" and "data2" are two different instances of property data to set and get +// The "data1" and "data2" must differ from one another, and +// the "data1" must differ from instance property's initial state +// "propertyName" is the name of the property we are interested in testing +template<typename TestedClass, typename TestedData> +void testWritableBindableBasics(TestedClass& testedClass, TestedData data1, + TestedData data2, const char* propertyName) +{ + // Get the property we are testing + const QMetaObject *metaObject = testedClass.metaObject(); + QMetaProperty metaProperty = metaObject->property(metaObject->indexOfProperty(propertyName)); + + // Generate a string to help identify failures (as this is a generic template) + QString id(metaObject->className()); + id.append(QStringLiteral("::")); + id.append(propertyName); + + // Fail gracefully if preconditions to use this helper function are not met: + QVERIFY2(metaProperty.isBindable() && metaProperty.isWritable() + && metaProperty.hasNotifySignal(), qPrintable(id)); + // Create a signal spy for the property changed -signal + QSignalSpy spy(&testedClass, metaProperty.notifySignal()); + QUntypedBindable bindable = metaProperty.bindable(&testedClass); + + // Test basic property read and write + testedClass.setProperty(propertyName, QVariant::fromValue(data1)); + QVERIFY2(testedClass.property(propertyName).template value<TestedData>() == data1, qPrintable(id)); + QVERIFY2(spy.count() == 1, qPrintable(id + ", actual: " + QString::number(spy.count()))); + + // Test setting a binding as a source for the property + QProperty<TestedData> property1(data1); + QProperty<TestedData> property2(data2); + QVERIFY2(!bindable.hasBinding(), qPrintable(id)); + bindable.setBinding(Qt::makePropertyBinding(property2)); + QVERIFY2(bindable.hasBinding(), qPrintable(id)); + // Check that the value also changed + QVERIFY2(testedClass.property(propertyName).template value<TestedData>() == data2, qPrintable(id)); + QVERIFY2(spy.count() == 2, qPrintable(id + ", actual: " + QString::number(spy.count()))); + // Same test but with a lambda binding (cast to be able to set the lambda directly) + QBindable<TestedData> *typedBindable = static_cast<QBindable<TestedData>*>(&bindable); + typedBindable->setBinding([&](){ return property1.value(); }); + QVERIFY2(typedBindable->hasBinding(), qPrintable(id)); + QVERIFY2(testedClass.property(propertyName).template value<TestedData>() == data1, qPrintable(id)); + QVERIFY2(spy.count() == 3, qPrintable(id + ", actual: " + QString::number(spy.count()))); + + // Remove binding by setting a value directly + QVERIFY2(bindable.hasBinding(), qPrintable(id)); + testedClass.setProperty(propertyName, QVariant::fromValue(data2)); + QVERIFY2(testedClass.property(propertyName).template value<TestedData>() == data2, qPrintable(id)); + QVERIFY2(!bindable.hasBinding(), qPrintable(id)); + QVERIFY2(spy.count() == 4, qPrintable(id + ", actual: " + QString::number(spy.count()))); + + // Test using the property as the source in a binding + QProperty<bool> data1Used([&](){ + return testedClass.property(propertyName).template value<TestedData>() == data1; + }); + QVERIFY2(data1Used == false, qPrintable(id)); + testedClass.setProperty(propertyName, QVariant::fromValue(data1)); + QVERIFY2(data1Used == true, qPrintable(id)); +} + +#endif // BINDABLEUTILS_H |