diff options
author | Jan Arve Sæther <jan-arve.saether@qt.io> | 2017-12-01 11:19:28 +0100 |
---|---|---|
committer | Jan Arve Sæther <jan-arve.saether@qt.io> | 2017-12-02 19:58:30 +0000 |
commit | 0c9e379dd8c57fab9d8e6ba8d35a0dca8ac05a0a (patch) | |
tree | a5a806ddf6ea5728d1f2857e8119a26c787ed1e8 /tests/auto/corelib/animation/qpropertyanimation/tst_qpropertyanimation.cpp | |
parent | 306c32f50e289c401e4636976c97dc2b40fdd69b (diff) | |
download | qtbase-0c9e379dd8c57fab9d8e6ba8d35a0dca8ac05a0a.tar.gz |
Use a custom QAnimationDriver to take control over time
This should reduce flakyness of tests.
Change-Id: I26e0a97f7cd3e7cee2ffb44188300c37578cddd7
Reviewed-by: Jędrzej Nowacki <jedrzej.nowacki@qt.io>
Diffstat (limited to 'tests/auto/corelib/animation/qpropertyanimation/tst_qpropertyanimation.cpp')
-rw-r--r-- | tests/auto/corelib/animation/qpropertyanimation/tst_qpropertyanimation.cpp | 235 |
1 files changed, 162 insertions, 73 deletions
diff --git a/tests/auto/corelib/animation/qpropertyanimation/tst_qpropertyanimation.cpp b/tests/auto/corelib/animation/qpropertyanimation/tst_qpropertyanimation.cpp index cf4c4e1bdb..41a051a719 100644 --- a/tests/auto/corelib/animation/qpropertyanimation/tst_qpropertyanimation.cpp +++ b/tests/auto/corelib/animation/qpropertyanimation/tst_qpropertyanimation.cpp @@ -29,6 +29,7 @@ #include <QtTest/QtTest> #include <QtCore/qpropertyanimation.h> #include <QtCore/qvariantanimation.h> +#include <private/qabstractanimation_p.h> #include <QtGui/qtouchdevice.h> #include <QtWidgets/qwidget.h> @@ -74,6 +75,80 @@ public: MyObject o; }; +class TestAnimationDriver : public QAnimationDriver +{ +public: + TestAnimationDriver() + : QAnimationDriver() + , m_elapsed(0) + { + QUnifiedTimer::instance()->installAnimationDriver(this); + } + + ~TestAnimationDriver() + { + // This is to ensure that running animations are removed from the list of actual running + // animations. + QCoreApplication::sendPostedEvents(); + QUnifiedTimer::instance()->uninstallAnimationDriver(this); + } + + void wait(qint64 ms) + { + /* + * When QAbstractAnimation::start() is called it will end up calling + * QAnimationTimer::registerAnimation(). This will do + * + * QMetaObject::invokeMethod(inst, "startAnimations", Qt::QueuedConnection); // typeof(inst) == QAnimationTimer + * + * startAnimations() will again fire a queued connection to actually add the animation + * to the list of running animations: + * + * QMetaObject::invokeMethod(inst, "startTimers", Qt::QueuedConnection); // typeof(inst) == QUnifiedTimer + * + * We therefore have to call QCoreApplication::sendPostedEvents() twice here. + */ + QCoreApplication::sendPostedEvents(); + QCoreApplication::sendPostedEvents(); + + // Simulates the ideal animation update freqency (approx. 60Hz) + static const int interval = 1000/60; + qint64 until = m_elapsed + ms; + while (m_elapsed < until) { + advanceAnimation(m_elapsed); + m_elapsed += interval; + } + advanceAnimation(m_elapsed); + // This is to make sure that animations that were started with DeleteWhenStopped + // will actually delete themselves within the test function. + // Normally, they won't be deleted until the main event loop is processed. + // Therefore, have to explicitly say that we want to process DeferredDelete events. Same + // trick is used by QTest::qWait(). + QCoreApplication::sendPostedEvents(nullptr, QEvent::DeferredDelete); + } + + qint64 elapsed() const override + { + return m_elapsed; + } + + void start() override + { + d_func()->running = true; + m_elapsed = 0; + emit started(); + } + + void stop() override + { + d_func()->running = false; + emit stopped(); + } + +private: + qint64 m_elapsed; + Q_DECLARE_PRIVATE(QAnimationDriver) +}; class tst_QPropertyAnimation : public QObject { @@ -261,40 +336,44 @@ void tst_QPropertyAnimation::statesAndSignals() QCOMPARE(currentLoopSpy.count(), 2); runningSpy.clear(); - anim->start(); - QTest::qWait(1000); - QTRY_COMPARE(anim->state(), QAnimationGroup::Stopped); - QCOMPARE(runningSpy.count(), 2); //started and stopped again - runningSpy.clear(); - QCOMPARE(finishedSpy.count(), 1); - QCOMPARE(anim->currentLoopTime(), 100); - QCOMPARE(anim->currentLoop(), 2); - QCOMPARE(currentLoopSpy.count(), 4); - - anim->start(); // auto-rewinds - QCOMPARE(anim->state(), QAnimationGroup::Running); - QCOMPARE(anim->currentTime(), 0); - QCOMPARE(anim->currentLoop(), 0); - QCOMPARE(currentLoopSpy.count(), 5); - QCOMPARE(runningSpy.count(), 1); // anim has started - QCOMPARE(finishedSpy.count(), 1); - QCOMPARE(anim->currentLoop(), 0); - runningSpy.clear(); - - QTest::qWait(1000); - - QCOMPARE(currentLoopSpy.count(), 7); - QCOMPARE(anim->state(), QAnimationGroup::Stopped); - QCOMPARE(anim->currentLoop(), 2); - QCOMPARE(runningSpy.count(), 1); // anim has stopped - QCOMPARE(finishedSpy.count(), 2); - QCOMPARE(anim->currentLoopTime(), 100); - - delete anim; + { + TestAnimationDriver timeDriver; + anim->start(); + timeDriver.wait(1000); + QCOMPARE(anim->state(), QAnimationGroup::Stopped); + QCOMPARE(runningSpy.count(), 2); //started and stopped again + runningSpy.clear(); + QCOMPARE(finishedSpy.count(), 1); + QCOMPARE(anim->currentLoopTime(), 100); + QCOMPARE(anim->currentLoop(), 2); + QCOMPARE(currentLoopSpy.count(), 4); + + anim->start(); // auto-rewinds + QCOMPARE(anim->state(), QAnimationGroup::Running); + QCOMPARE(anim->currentTime(), 0); + QCOMPARE(anim->currentLoop(), 0); + QCOMPARE(currentLoopSpy.count(), 5); + QCOMPARE(runningSpy.count(), 1); // anim has started + QCOMPARE(finishedSpy.count(), 1); + QCOMPARE(anim->currentLoop(), 0); + runningSpy.clear(); + + timeDriver.wait(1000); + + QCOMPARE(currentLoopSpy.count(), 7); + QCOMPARE(anim->state(), QAnimationGroup::Stopped); + QCOMPARE(anim->currentLoop(), 2); + QCOMPARE(runningSpy.count(), 1); // anim has stopped + QCOMPARE(finishedSpy.count(), 2); + QCOMPARE(anim->currentLoopTime(), 100); + + delete anim; + } } void tst_QPropertyAnimation::deletion1() { + TestAnimationDriver timeDriver; QObject *object = new QWidget; QPointer<QPropertyAnimation> anim = new QPropertyAnimation(object, "minimumWidth"); @@ -312,23 +391,23 @@ void tst_QPropertyAnimation::deletion1() QVERIFY(anim); QCOMPARE(anim->state(), QAnimationGroup::Running); - QTest::qWait(100); + timeDriver.wait(100); QVERIFY(anim); QCOMPARE(anim->state(), QAnimationGroup::Running); - QTest::qWait(150); + timeDriver.wait(150); QVERIFY(anim); //The animation should not have been deleted - QTRY_COMPARE(anim->state(), QAnimationGroup::Stopped); + QCOMPARE(anim->state(), QAnimationGroup::Stopped); QCOMPARE(runningSpy.count(), 2); QCOMPARE(finishedSpy.count(), 1); anim->start(QVariantAnimation::DeleteWhenStopped); QVERIFY(anim); QCOMPARE(anim->state(), QAnimationGroup::Running); - QTest::qWait(100); + timeDriver.wait(100); QVERIFY(anim); QCOMPARE(anim->state(), QAnimationGroup::Running); - QTest::qWait(150); - QTRY_COMPARE(runningSpy.count(), 4); + timeDriver.wait(150); + QCOMPARE(runningSpy.count(), 4); QCOMPARE(finishedSpy.count(), 2); QVERIFY(!anim); //The animation must have been deleted delete object; @@ -336,6 +415,7 @@ void tst_QPropertyAnimation::deletion1() void tst_QPropertyAnimation::deletion2() { + TestAnimationDriver timeDriver; //test that the animation get deleted if the object is deleted QObject *object = new QWidget; QPointer<QPropertyAnimation> anim = new QPropertyAnimation(object,"minimumWidth"); @@ -354,7 +434,7 @@ void tst_QPropertyAnimation::deletion2() anim->setDuration(200); anim->start(); - QTest::qWait(50); + timeDriver.wait(50); QVERIFY(anim); QCOMPARE(anim->state(), QAnimationGroup::Running); @@ -363,7 +443,7 @@ void tst_QPropertyAnimation::deletion2() //we can't call deletaLater directly because the delete would only happen in the next loop of _this_ event loop QTimer::singleShot(0, object, SLOT(deleteLater())); - QTest::qWait(50); + timeDriver.wait(50); QVERIFY(!anim->targetObject()); } @@ -371,6 +451,7 @@ void tst_QPropertyAnimation::deletion2() void tst_QPropertyAnimation::deletion3() { //test that the stopped signal is emit when the animation is destroyed + TestAnimationDriver timeDriver; QObject *object = new QWidget; QPropertyAnimation *anim = new QPropertyAnimation(object,"minimumWidth"); anim->setStartValue(10); @@ -385,7 +466,7 @@ void tst_QPropertyAnimation::deletion3() anim->start(); - QTest::qWait(50); + timeDriver.wait(50); QCOMPARE(anim->state(), QAnimationGroup::Running); QCOMPARE(runningSpy.count(), 1); QCOMPARE(finishedSpy.count(), 0); @@ -432,6 +513,7 @@ public: void tst_QPropertyAnimation::noStartValue() { + TestAnimationDriver timeDriver; StartValueTester o; o.setProperty("ole", 42); o.values.clear(); @@ -441,7 +523,8 @@ void tst_QPropertyAnimation::noStartValue() a.setDuration(250); a.start(); - QTRY_COMPARE(o.values.value(o.values.size() - 1, -1), 420); + timeDriver.wait(a.duration()); + QCOMPARE(o.values.value(o.values.size() - 1, -1), 420); QCOMPARE(o.values.first(), 42); } @@ -471,6 +554,7 @@ void tst_QPropertyAnimation::startWhenAnotherIsRunning() StartValueTester o; o.setProperty("ole", 42); o.values.clear(); + TestAnimationDriver timeDriver; { //normal case: the animation finishes and is deleted @@ -479,18 +563,17 @@ void tst_QPropertyAnimation::startWhenAnotherIsRunning() QSignalSpy runningSpy(anim.data(), &QVariantAnimation::stateChanged); QVERIFY(runningSpy.isValid()); anim->start(QVariantAnimation::DeleteWhenStopped); - QTest::qWait(anim->duration() + 100); - QTRY_COMPARE(runningSpy.count(), 2); //started and then stopped + timeDriver.wait(anim->duration()); + QCOMPARE(runningSpy.count(), 2); //started and then stopped QVERIFY(!anim); } - { QPointer<QVariantAnimation> anim = new QPropertyAnimation(&o, "ole"); anim->setEndValue(100); QSignalSpy runningSpy(anim.data(), &QVariantAnimation::stateChanged); QVERIFY(runningSpy.isValid()); anim->start(QVariantAnimation::DeleteWhenStopped); - QTest::qWait(anim->duration()/2); + timeDriver.wait(anim->duration()/2); QPointer<QVariantAnimation> anim2 = new QPropertyAnimation(&o, "ole"); anim2->setEndValue(100); QCOMPARE(runningSpy.count(), 1); @@ -498,11 +581,11 @@ void tst_QPropertyAnimation::startWhenAnotherIsRunning() //anim2 will interrupt anim1 QMetaObject::invokeMethod(anim2, "start", Qt::QueuedConnection, Q_ARG(QAbstractAnimation::DeletionPolicy, QVariantAnimation::DeleteWhenStopped)); - QTest::qWait(50); + timeDriver.wait(50); QVERIFY(!anim); //anim should have been deleted QVERIFY(anim2); - QTest::qWait(anim2->duration()); - QTRY_VERIFY(!anim2); //anim2 is finished: it should have been deleted by now + timeDriver.wait(anim2->duration()); + QVERIFY(!anim2); //anim2 is finished: it should have been deleted by now QVERIFY(!anim); } @@ -559,6 +642,7 @@ void tst_QPropertyAnimation::easingcurve() void tst_QPropertyAnimation::startWithoutStartValue() { + TestAnimationDriver timeDriver; QObject o; o.setProperty("ole", 42); QCOMPARE(o.property("ole").toInt(), 42); @@ -568,14 +652,14 @@ void tst_QPropertyAnimation::startWithoutStartValue() anim.start(); - QTest::qWait(100); + timeDriver.wait(100); int current = anim.currentValue().toInt(); //it is somewhere in the animation QVERIFY(current > 42); QVERIFY(current < 100); - QTest::qWait(200); - QTRY_COMPARE(anim.state(), QVariantAnimation::Stopped); + timeDriver.wait(200); + QCOMPARE(anim.state(), QVariantAnimation::Stopped); current = anim.currentValue().toInt(); QCOMPARE(current, 100); QCOMPARE(o.property("ole").toInt(), current); @@ -586,7 +670,7 @@ void tst_QPropertyAnimation::startWithoutStartValue() // the default start value will reevaluate the current property // and set it to the end value of the last iteration QCOMPARE(current, 100); - QTest::qWait(100); + timeDriver.wait(100); current = anim.currentValue().toInt(); //it is somewhere in the animation QVERIFY(current >= 100); @@ -595,6 +679,7 @@ void tst_QPropertyAnimation::startWithoutStartValue() void tst_QPropertyAnimation::startBackwardWithoutEndValue() { + TestAnimationDriver timeDriver; QObject o; o.setProperty("ole", 42); QCOMPARE(o.property("ole").toInt(), 42); @@ -608,14 +693,14 @@ void tst_QPropertyAnimation::startBackwardWithoutEndValue() QCOMPARE(anim.state(), QAbstractAnimation::Running); QCOMPARE(o.property("ole").toInt(), 42); //the initial value - QTest::qWait(100); + timeDriver.wait(100); int current = anim.currentValue().toInt(); //it is somewhere in the animation QVERIFY(current > 42); QVERIFY(current < 100); - QTest::qWait(200); - QTRY_COMPARE(anim.state(), QVariantAnimation::Stopped); + timeDriver.wait(200); + QCOMPARE(anim.state(), QVariantAnimation::Stopped); current = anim.currentValue().toInt(); QCOMPARE(current, 100); QCOMPARE(o.property("ole").toInt(), current); @@ -626,7 +711,7 @@ void tst_QPropertyAnimation::startBackwardWithoutEndValue() // the default start value will reevaluate the current property // and set it to the end value of the last iteration QCOMPARE(current, 100); - QTest::qWait(100); + timeDriver.wait(100); current = anim.currentValue().toInt(); //it is somewhere in the animation QVERIFY(current >= 100); @@ -636,6 +721,7 @@ void tst_QPropertyAnimation::startBackwardWithoutEndValue() void tst_QPropertyAnimation::playForwardBackward() { + TestAnimationDriver timeDriver; QObject o; o.setProperty("ole", 0); QCOMPARE(o.property("ole").toInt(), 0); @@ -644,16 +730,16 @@ void tst_QPropertyAnimation::playForwardBackward() anim.setStartValue(0); anim.setEndValue(100); anim.start(); - QTest::qWait(anim.duration() + 100); - QTRY_COMPARE(anim.state(), QAbstractAnimation::Stopped); + timeDriver.wait(anim.duration()); + QCOMPARE(anim.state(), QAbstractAnimation::Stopped); QCOMPARE(anim.currentTime(), anim.duration()); //the animation is at the end anim.setDirection(QVariantAnimation::Backward); anim.start(); QCOMPARE(anim.state(), QAbstractAnimation::Running); - QTest::qWait(anim.duration() + 100); - QTRY_COMPARE(anim.state(), QAbstractAnimation::Stopped); + timeDriver.wait(anim.duration()); + QCOMPARE(anim.state(), QAbstractAnimation::Stopped); QCOMPARE(anim.currentTime(), 0); //the direction is backward @@ -661,8 +747,8 @@ void tst_QPropertyAnimation::playForwardBackward() anim.start(); QCOMPARE(anim.state(), QAbstractAnimation::Running); QCOMPARE(anim.currentTime(), anim.duration()); - QTest::qWait(anim.duration() + 100); - QTRY_COMPARE(anim.state(), QAbstractAnimation::Stopped); + timeDriver.wait(anim.duration()); + QCOMPARE(anim.state(), QAbstractAnimation::Stopped); QCOMPARE(anim.currentTime(), 0); } @@ -1106,21 +1192,21 @@ void tst_QPropertyAnimation::restart() void tst_QPropertyAnimation::valueChanged() { - + TestAnimationDriver timeDriver; //we check that we receive the valueChanged signal MyErrorObject o; o.setOle(0); QCOMPARE(o.property("ole").toInt(), 0); QPropertyAnimation anim(&o, "ole"); anim.setEndValue(5); - anim.setDuration(1000); + anim.setDuration(200); QSignalSpy spy(&anim, &QPropertyAnimation::valueChanged); QVERIFY(spy.isValid()); anim.start(); + // Drive animation forward to its end + timeDriver.wait(anim.duration()); - QTest::qWait(anim.duration() + 100); - - QTRY_COMPARE(anim.state(), QAbstractAnimation::Stopped); + QCOMPARE(anim.state(), QAbstractAnimation::Stopped); QCOMPARE(anim.currentTime(), anim.duration()); //let's check that the values go forward @@ -1153,6 +1239,7 @@ public: void tst_QPropertyAnimation::twoAnimations() { + TestAnimationDriver timeDriver; MySyncObject o1, o2; o1.setOle(0); o2.setOle(0); @@ -1169,8 +1256,8 @@ void tst_QPropertyAnimation::twoAnimations() o1.anim.start(); o2.anim.start(); - QTest::qWait(o1.anim.duration() + 100); - QTRY_COMPARE(o1.anim.state(), QAbstractAnimation::Stopped); + timeDriver.wait(o1.anim.duration()); + QCOMPARE(o1.anim.state(), QAbstractAnimation::Stopped); QCOMPARE(o2.anim.state(), QAbstractAnimation::Stopped); QCOMPARE(o1.ole(), 1000); @@ -1209,6 +1296,7 @@ public: void tst_QPropertyAnimation::deletedInUpdateCurrentTime() { + TestAnimationDriver timeDriver; // this test case reproduces an animation being deleted in the updateCurrentTime of // another animation(was causing segfault). // the deleted animation must have been started after the animation that is deleting. @@ -1219,9 +1307,9 @@ void tst_QPropertyAnimation::deletedInUpdateCurrentTime() MyComposedAnimation composedAnimation(&o, "value", "realValue"); composedAnimation.start(); QCOMPARE(composedAnimation.state(), QAbstractAnimation::Running); - QTest::qWait(composedAnimation.duration() + 100); + timeDriver.wait(composedAnimation.duration()); - QTRY_COMPARE(composedAnimation.state(), QAbstractAnimation::Stopped); + QCOMPARE(composedAnimation.state(), QAbstractAnimation::Stopped); QCOMPARE(o.value(), 1000); } @@ -1293,6 +1381,7 @@ public: void tst_QPropertyAnimation::recursiveAnimations() { + TestAnimationDriver timeDriver; RecursiveObject o; QPropertyAnimation anim; anim.setTargetObject(&o); @@ -1301,9 +1390,9 @@ void tst_QPropertyAnimation::recursiveAnimations() anim.setEndValue(4000); anim.start(); - QTest::qWait(anim.duration() + o.animation.duration()); - QTRY_COMPARE(anim.state(), QAbstractAnimation::Stopped); - QTRY_COMPARE(o.animation.state(), QAbstractAnimation::Stopped); + timeDriver.wait(anim.duration() + o.animation.duration()); + QCOMPARE(anim.state(), QAbstractAnimation::Stopped); + QCOMPARE(o.animation.state(), QAbstractAnimation::Stopped); QCOMPARE(o.y(), qreal(4000)); } |