1 /****************************************************************************
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
7 ** This file is part of the test suite of the Qt Toolkit.
9 ** $QT_BEGIN_LICENSE:LGPL$
10 ** GNU Lesser General Public License Usage
11 ** This file may be used under the terms of the GNU Lesser General Public
12 ** License version 2.1 as published by the Free Software Foundation and
13 ** appearing in the file LICENSE.LGPL included in the packaging of this
14 ** file. Please review the following information to ensure the GNU Lesser
15 ** General Public License version 2.1 requirements will be met:
16 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
18 ** In addition, as a special exception, Nokia gives you certain additional
19 ** rights. These rights are described in the Nokia Qt LGPL Exception
20 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
22 ** GNU General Public License Usage
23 ** Alternatively, this file may be used under the terms of the GNU General
24 ** Public License version 3.0 as published by the Free Software Foundation
25 ** and appearing in the file LICENSE.GPL included in the packaging of this
26 ** file. Please review the following information to ensure the GNU General
27 ** Public License version 3.0 requirements will be met:
28 ** http://www.gnu.org/copyleft/gpl.html.
31 ** Alternatively, this file may be used in accordance with the terms and
32 ** conditions contained in a signed written agreement between you and Nokia.
40 ****************************************************************************/
42 #include <QtTest/QtTest>
44 #include <qtimeline.h>
46 class tst_QTimeLine : public QObject
60 void toggleDirection();
65 void multipleTimeLines();
69 void stateInFinishedSignal();
77 QTimeLine::State state;
81 void tst_QTimeLine::range()
83 #ifdef Q_OS_WINCE //On WinCE timer resolution is bad - using longer times instead
84 QTimeLine timeLine(2000);
86 QTimeLine timeLine(200);
88 QCOMPARE(timeLine.startFrame(), 0);
89 QCOMPARE(timeLine.endFrame(), 0);
90 timeLine.setFrameRange(0, 1);
91 QCOMPARE(timeLine.startFrame(), 0);
92 QCOMPARE(timeLine.endFrame(), 1);
93 timeLine.setFrameRange(10, 20);
94 QCOMPARE(timeLine.startFrame(), 10);
95 QCOMPARE(timeLine.endFrame(), 20);
97 timeLine.setStartFrame(6);
98 QCOMPARE(timeLine.startFrame(), 6);
99 timeLine.setEndFrame(16);
100 QCOMPARE(timeLine.endFrame(), 16);
102 // Verify that you can change the range in the timeLine
103 timeLine.setFrameRange(10, 20);
104 QSignalSpy spy(&timeLine, SIGNAL(frameChanged(int)));
105 QVERIFY(spy.isValid());
112 QCOMPARE(timeLine.state(), QTimeLine::Running);
113 int oldValue = timeLine.currentFrame();
114 timeLine.setFrameRange(0, 5);
115 QVERIFY(timeLine.currentFrame() < oldValue);
116 timeLine.setEndFrame(100);
117 timeLine.setStartFrame(50);
118 QVERIFY(timeLine.currentFrame() > oldValue);
119 timeLine.setFrameRange(0, 5);
125 QVERIFY(spy.count() > 1);
126 QVERIFY(timeLine.currentFrame() < oldValue);
129 void tst_QTimeLine::currentTime()
131 QTimeLine timeLine(2000);
132 timeLine.setUpdateInterval((timeLine.duration()/2) / 33);
133 qRegisterMetaType<qreal>("qreal");
134 QSignalSpy spy(&timeLine, SIGNAL(valueChanged(qreal)));
135 QVERIFY(spy.isValid());
136 timeLine.setFrameRange(10, 20);
137 QCOMPARE(timeLine.currentTime(), 0);
139 QTest::qWait(timeLine.duration()/2);
140 QCOMPARE(timeLine.state(), QTimeLine::Running);
141 QVERIFY(timeLine.currentTime() > timeLine.duration()/2 - timeLine.duration()/10);
142 QVERIFY(timeLine.currentTime() < timeLine.duration()/2 + timeLine.duration()/10);
143 QTest::qWait(timeLine.duration()/4 + timeLine.duration());
144 QCOMPARE(timeLine.state(), QTimeLine::NotRunning);
145 QCOMPARE(timeLine.currentTime(), timeLine.duration());
148 timeLine.setCurrentTime(timeLine.duration()/2);
149 timeLine.setCurrentTime(timeLine.duration()/2);
150 QCOMPARE(spy.count(), 1);
152 QCOMPARE(timeLine.currentTime(), timeLine.duration()/2);
154 // Let it update on its own
155 QTest::qWait(timeLine.duration()/4);
156 QCOMPARE(timeLine.state(), QTimeLine::Running);
157 QVERIFY(timeLine.currentTime() > timeLine.duration()/2);
158 QVERIFY(timeLine.currentTime() < timeLine.duration());
159 QTest::qWait(timeLine.duration()/4 + timeLine.duration());
160 QCOMPARE(timeLine.state(), QTimeLine::NotRunning);
161 QVERIFY(timeLine.currentTime() == timeLine.duration());
163 // Reverse should decrease the currentTime
164 timeLine.setCurrentTime(timeLine.duration()/2);
166 // Let it update on its own
167 QTest::qWait(timeLine.duration()/4);
168 QCOMPARE(timeLine.state(), QTimeLine::Running);
169 int currentTime = timeLine.currentTime();
170 timeLine.setDirection(QTimeLine::Backward);
171 QTest::qWait(timeLine.duration()/4);
172 QVERIFY(timeLine.currentTime() < currentTime);
176 void tst_QTimeLine::duration()
178 QTimeLine timeLine(200);
179 timeLine.setFrameRange(10, 20);
180 QCOMPARE(timeLine.duration(), 200);
181 timeLine.setDuration(1000);
182 QCOMPARE(timeLine.duration(), 1000);
186 QCOMPARE(timeLine.state(), QTimeLine::Running);
187 QVERIFY(timeLine.currentTime() > 0.9);
189 QCOMPARE(timeLine.state(), QTimeLine::NotRunning);
190 // The duration shouldn't change
191 QCOMPARE(timeLine.duration(), 1000);
194 void tst_QTimeLine::frameRate()
197 timeLine.setFrameRange(10, 20);
198 QCOMPARE(timeLine.updateInterval(), 1000 / 25);
199 timeLine.setUpdateInterval(1000 / 60);
200 QCOMPARE(timeLine.updateInterval(), 1000 / 60);
203 timeLine.setUpdateInterval(1000 / 33);
204 QSignalSpy spy(&timeLine, SIGNAL(frameChanged(int)));
205 QVERIFY(spy.isValid());
207 QTest::qWait(timeLine.duration()*2);
208 QCOMPARE(timeLine.state(), QTimeLine::NotRunning);
209 int slowCount = spy.count();
212 timeLine.setUpdateInterval(1000 / 100);
214 timeLine.setCurrentTime(0);
216 QTest::qWait(timeLine.duration()*2);
217 QCOMPARE(timeLine.state(), QTimeLine::NotRunning);
218 QVERIFY(slowCount < spy.count());
221 void tst_QTimeLine::value()
223 QTimeLine timeLine(2000);
224 QVERIFY(timeLine.currentValue() == 0.0);
227 qRegisterMetaType<qreal>("qreal");
228 QSignalSpy spy(&timeLine, SIGNAL(valueChanged(qreal)));
229 QVERIFY(spy.isValid());
231 QTest::qWait(timeLine.duration()/3);
232 QVERIFY(timeLine.currentValue() > 0);
233 QTest::qWait(timeLine.duration());
234 QCOMPARE(timeLine.state(), QTimeLine::NotRunning);
235 qreal currentValue = timeLine.currentValue();
236 QVERIFY(currentValue == 1);
237 QVERIFY(spy.count() > 0);
239 // Reverse should decrease the value
240 timeLine.setCurrentTime(100);
242 // Let it update on its own
244 QCOMPARE(timeLine.state(), QTimeLine::Running);
245 qreal value = timeLine.currentValue();
246 timeLine.setDirection(QTimeLine::Backward);
248 QVERIFY(timeLine.currentValue() < value);
252 void tst_QTimeLine::currentFrame()
254 QTimeLine timeLine(2000);
255 timeLine.setFrameRange(10, 20);
256 QCOMPARE(timeLine.currentFrame(), 10);
259 QSignalSpy spy(&timeLine, SIGNAL(frameChanged(int)));
260 QVERIFY(spy.isValid());
262 QTest::qWait(timeLine.duration()/3);
263 QVERIFY(timeLine.currentFrame() > 10);
264 QTest::qWait(timeLine.duration());
265 QCOMPARE(timeLine.state(), QTimeLine::NotRunning);
266 QCOMPARE(timeLine.currentFrame(), 20);
268 // Reverse should decrease the value
269 timeLine.setCurrentTime(timeLine.duration()/2);
271 // Let it update on its own
272 QTest::qWait(timeLine.duration()/4);
273 QCOMPARE(timeLine.state(), QTimeLine::Running);
274 int value = timeLine.currentFrame();
275 timeLine.setDirection(QTimeLine::Backward);
276 QTest::qWait(timeLine.duration()/2);
277 QVERIFY(timeLine.currentFrame() < value);
281 void tst_QTimeLine::loopCount()
283 QTimeLine timeLine(200);
284 QCOMPARE(timeLine.loopCount(), 1);
285 timeLine.setFrameRange(10, 20);
286 QCOMPARE(timeLine.loopCount(), 1);
287 timeLine.setLoopCount(0);
288 QCOMPARE(timeLine.loopCount(), 0);
290 // Default speed infiniti looping
291 QSignalSpy spy(&timeLine, SIGNAL(frameChanged(int)));
292 QVERIFY(spy.isValid());
294 QTest::qWait(timeLine.duration());
295 QCOMPARE(timeLine.state(), QTimeLine::Running);
296 //QCOMPARE(timeLine.currentFrame(), 20);
297 QTest::qWait(timeLine.duration()*6);
298 QCOMPARE(timeLine.state(), QTimeLine::Running);
299 QVERIFY(timeLine.currentTime() >= 0);
300 QVERIFY(timeLine.currentFrame() >= 10);
301 QVERIFY(timeLine.currentFrame() <= 20);
302 QCOMPARE(timeLine.state(), QTimeLine::Running);
305 timeLine.setDuration(2500); // ### some platforms have a very low resolution timer
306 timeLine.setFrameRange(0, 2);
307 timeLine.setLoopCount(4);
309 QSignalSpy finishedSpy(&timeLine, SIGNAL(finished()));
310 QSignalSpy frameChangedSpy(&timeLine, SIGNAL(frameChanged(int)));
311 QVERIFY(finishedSpy.isValid());
312 QVERIFY(frameChangedSpy.isValid());
314 connect(&timeLine, SIGNAL(finished()), &loop, SLOT(quit()));
317 for(int i=0;i<2;i++) {
320 //we clear te list after the start so we don't catch
321 //a frameChanged signal for the frame 0 at the beginning
323 frameChangedSpy.clear();
327 QCOMPARE(finishedSpy.count(), 1);
328 QCOMPARE(frameChangedSpy.count(), 11);
329 for (int i = 0; i < 11; ++i) {
330 QCOMPARE(frameChangedSpy.at(i).at(0).toInt(), (i+1) % 3);
334 timeLine.setDirection(QTimeLine::Backward);
338 QCOMPARE(finishedSpy.count(), 2);
339 QCOMPARE(frameChangedSpy.count(), 22);
340 for (int i = 11; i < 22; ++i) {
341 QCOMPARE(frameChangedSpy.at(i).at(0).toInt(), 2 - (i+2) % 3);
345 void tst_QTimeLine::interpolation()
347 QTimeLine timeLine(400);
348 QCOMPARE(timeLine.curveShape(), QTimeLine::EaseInOutCurve);
349 timeLine.setFrameRange(100, 200);
350 timeLine.setCurveShape(QTimeLine::LinearCurve);
351 QCOMPARE(timeLine.curveShape(), QTimeLine::LinearCurve);
354 timeLine.setCurveShape(QTimeLine::EaseInOutCurve);
357 QCOMPARE(timeLine.state(), QTimeLine::Running);
358 int firstValue = timeLine.currentFrame();
360 int endValue = timeLine.currentFrame();
362 timeLine.setCurrentTime(0);
365 timeLine.setCurveShape(QTimeLine::LinearCurve);
368 QCOMPARE(timeLine.state(), QTimeLine::Running);
370 // Smooth accellerates slowly so in the beginning so it is farther behind
371 QVERIFY(firstValue < timeLine.currentFrame());
373 QVERIFY(endValue > timeLine.currentFrame());
377 void tst_QTimeLine::reverse_data()
379 QTest::addColumn<int>("duration");
380 QTest::addColumn<int>("start");
381 QTest::addColumn<int>("end");
382 QTest::addColumn<int>("direction");
383 QTest::addColumn<int>("direction2");
384 QTest::addColumn<int>("direction3");
385 QTest::addColumn<int>("startTime");
386 QTest::addColumn<int>("currentFrame");
387 QTest::addColumn<qreal>("currentValue");
388 QTest::addColumn<int>("wait");
389 QTest::addColumn<int>("state");
390 QTest::addColumn<int>("wait2");
392 QTest::newRow("start at end") << 200 << 1000 << 2000 << (int)QTimeLine::Backward << (int)QTimeLine::Forward << (int)QTimeLine::Backward << 200 << 2000 << qreal(1.0) << 40 << (int)QTimeLine::Running << 140;
393 QTest::newRow("start at half") << 200 << 1000 << 2000 << (int)QTimeLine::Backward << (int)QTimeLine::Forward << (int)QTimeLine::Backward << 100 << 1500 << qreal(0.5) << 40 << (int)QTimeLine::Running << 140;
394 QTest::newRow("start at quarter") << 200 << 1000 << 2000 << (int)QTimeLine::Backward << (int)QTimeLine::Forward << (int)QTimeLine::Backward << 50 << 1250 << qreal(0.25) << 40 << (int)QTimeLine::Running << 140;
397 void tst_QTimeLine::reverse()
399 QFETCH(int, duration);
402 QFETCH(int, direction);
403 QFETCH(int, direction2);
404 QFETCH(int, direction3);
405 QFETCH(int, startTime);
406 QFETCH(int, currentFrame);
407 QFETCH(qreal, currentValue);
412 QTimeLine timeLine(duration);
413 timeLine.setCurveShape(QTimeLine::LinearCurve);
414 timeLine.setFrameRange(start, end);
416 timeLine.setDirection((QTimeLine::Direction)direction);
417 timeLine.setDirection((QTimeLine::Direction)direction2);
418 timeLine.setDirection((QTimeLine::Direction)direction3);
419 QCOMPARE(timeLine.direction(), ((QTimeLine::Direction)direction));
421 timeLine.setCurrentTime(startTime);
422 timeLine.setDirection((QTimeLine::Direction)direction);
423 timeLine.setDirection((QTimeLine::Direction)direction2);
424 timeLine.setDirection((QTimeLine::Direction)direction3);
426 QCOMPARE(timeLine.currentFrame(), currentFrame);
427 QCOMPARE(timeLine.currentValue(), currentValue);
431 QCOMPARE(timeLine.state(), (QTimeLine::State)state);
432 int firstValue = timeLine.currentFrame();
433 timeLine.setDirection((QTimeLine::Direction)direction2);
434 timeLine.setDirection((QTimeLine::Direction)direction3);
435 timeLine.setDirection((QTimeLine::Direction)direction2);
436 timeLine.setDirection((QTimeLine::Direction)direction3);
438 int endValue = timeLine.currentFrame();
439 QVERIFY(endValue < firstValue);
444 void tst_QTimeLine::toggleDirection()
446 // Note: enum values are cast to int so that QCOMPARE will show
447 // the values if they don't match.
449 QCOMPARE(int(timeLine.direction()), int(QTimeLine::Forward));
450 timeLine.toggleDirection();
451 QCOMPARE(int(timeLine.direction()), int(QTimeLine::Backward));
452 timeLine.toggleDirection();
453 QCOMPARE(int(timeLine.direction()), int(QTimeLine::Forward));
456 void tst_QTimeLine::frameChanged()
459 timeLine.setFrameRange(0,9);
460 timeLine.setUpdateInterval(1000);
461 QSignalSpy spy(&timeLine, SIGNAL(frameChanged(int)));
462 QVERIFY(spy.isValid());
464 QTest::qWait(timeLine.duration()*2);
465 QCOMPARE(timeLine.state(), QTimeLine::NotRunning);
467 QVERIFY(spy.count() <= 10 && spy.count() > 0);
469 timeLine.setUpdateInterval(5);
471 timeLine.setCurrentTime(0);
473 QTest::qWait(timeLine.duration()*2);
474 QCOMPARE(timeLine.state(), QTimeLine::NotRunning);
476 QVERIFY(spy.count() <= 10 && spy.count() > 0);
479 void tst_QTimeLine::stopped()
482 timeLine.setFrameRange(0, 9);
483 qRegisterMetaType<QTimeLine::State>("QTimeLine::State");
484 QSignalSpy spy(&timeLine, SIGNAL(stateChanged(QTimeLine::State)));
485 QVERIFY(spy.isValid());
487 QTest::qWait(timeLine.duration()*2);
488 QCOMPARE(timeLine.state(), QTimeLine::NotRunning);
489 QCOMPARE(spy.count(), 2);
493 QCOMPARE(spy.count(), 2);
494 timeLine.setDirection(QTimeLine::Backward);
495 QCOMPARE(timeLine.loopCount(), 1);
498 void tst_QTimeLine::finished()
501 timeLine.setFrameRange(0,9);
502 QSignalSpy spy(&timeLine, SIGNAL(finished()));
503 QVERIFY(spy.isValid());
505 QTest::qWait(timeLine.duration()*2);
506 QCOMPARE(timeLine.state(), QTimeLine::NotRunning);
507 QCOMPARE(spy.count(), 1);
512 QCOMPARE(spy.count(), 0);
515 void tst_QTimeLine::isRunning()
518 timeLine.setFrameRange(0,9);
519 QCOMPARE(timeLine.state(), QTimeLine::NotRunning);
521 QCOMPARE(timeLine.state(), QTimeLine::Running);
523 QCOMPARE(timeLine.state(), QTimeLine::NotRunning);
526 QTest::qWait(timeLine.duration()*2);
527 QCOMPARE(timeLine.state(), QTimeLine::NotRunning);
530 void tst_QTimeLine::multipleTimeLines()
532 // Stopping a timer shouldn't affect the other timers
533 QTimeLine timeLine(200);
534 timeLine.setFrameRange(0,99);
535 QSignalSpy spy(&timeLine, SIGNAL(finished()));
536 QVERIFY(spy.isValid());
538 QTimeLine timeLineKiller;
539 timeLineKiller.setFrameRange(0,99);
541 timeLineKiller.start();
543 timeLineKiller.stop();
544 QTest::qWait(timeLine.duration()*2);
545 QCOMPARE(spy.count(), 1);
548 void tst_QTimeLine::sineCurve()
550 QTimeLine timeLine(1000);
551 timeLine.setCurveShape(QTimeLine::SineCurve);
552 QCOMPARE(timeLine.valueForTime(0), qreal(0));
553 QCOMPARE(timeLine.valueForTime(250), qreal(0.5));
554 QCOMPARE(timeLine.valueForTime(500), qreal(1));
555 QCOMPARE(timeLine.valueForTime(750), qreal(0.5));
556 QCOMPARE(timeLine.valueForTime(1000), qreal(0));
559 void tst_QTimeLine::cosineCurve()
561 QTimeLine timeLine(1000);
562 timeLine.setCurveShape(QTimeLine::CosineCurve);
563 QCOMPARE(timeLine.valueForTime(0), qreal(0.5));
564 QCOMPARE(timeLine.valueForTime(250), qreal(1));
565 QCOMPARE(timeLine.valueForTime(500), qreal(0.5));
566 QCOMPARE(timeLine.valueForTime(750), qreal(0));
567 QCOMPARE(timeLine.valueForTime(1000), qreal(0.5));
570 void tst_QTimeLine::outOfRange()
572 QTimeLine timeLine(1000);
573 QCOMPARE(timeLine.valueForTime(-100), qreal(0));
574 QCOMPARE(timeLine.valueForTime(2000), qreal(1));
576 timeLine.setCurveShape(QTimeLine::SineCurve);
577 QCOMPARE(timeLine.valueForTime(2000), qreal(0));
580 void tst_QTimeLine::stateInFinishedSignal()
582 QTimeLine timeLine(50);
584 connect(&timeLine, SIGNAL(finished()), this, SLOT(finishedSlot()));
585 state = QTimeLine::State(-1);
590 QCOMPARE(state, QTimeLine::NotRunning);
593 void tst_QTimeLine::finishedSlot()
595 QTimeLine *timeLine = qobject_cast<QTimeLine *>(sender());
597 state = timeLine->state();
600 void tst_QTimeLine::resume()
602 QTimeLine timeLine(1000);
604 QCOMPARE(timeLine.currentTime(), 0);
608 int oldCurrentTime = timeLine.currentTime();
609 QVERIFY(oldCurrentTime > 0);
610 QVERIFY(oldCurrentTime < 1000);
614 int currentTime = timeLine.currentTime();
615 QVERIFY(currentTime > oldCurrentTime);
616 QVERIFY(currentTime < 1000);
618 timeLine.setDirection(QTimeLine::Backward);
620 timeLine.setCurrentTime(1000);
621 QCOMPARE(timeLine.currentTime(), 1000);
625 int oldCurrentTime = timeLine.currentTime();
626 QVERIFY(oldCurrentTime < 1000);
627 QVERIFY(oldCurrentTime > 0);
631 int currentTime = timeLine.currentTime();
632 QVERIFY(currentTime < oldCurrentTime);
633 QVERIFY(currentTime > 0);
637 void tst_QTimeLine::restart()
639 QTimeLine timeLine(100);
640 timeLine.setFrameRange(0,9);
643 QTest::qWait(timeLine.duration()*2);
644 QCOMPARE(timeLine.currentFrame(), timeLine.endFrame());
645 QCOMPARE(timeLine.state(), QTimeLine::NotRunning);
647 // A restart with the same duration
649 QCOMPARE(timeLine.state(), QTimeLine::Running);
650 QCOMPARE(timeLine.currentFrame(), timeLine.startFrame());
651 QCOMPARE(timeLine.currentTime(), 0);
653 QCOMPARE(timeLine.currentFrame(), timeLine.endFrame());
654 QCOMPARE(timeLine.state(), QTimeLine::NotRunning);
656 // Set a smaller duration and restart
657 timeLine.setDuration(50);
659 QCOMPARE(timeLine.state(), QTimeLine::Running);
660 QCOMPARE(timeLine.currentFrame(), timeLine.startFrame());
661 QCOMPARE(timeLine.currentTime(), 0);
663 QCOMPARE(timeLine.currentFrame(), timeLine.endFrame());
664 QCOMPARE(timeLine.state(), QTimeLine::NotRunning);
666 // Set a longer duration and restart
667 timeLine.setDuration(150);
669 QCOMPARE(timeLine.state(), QTimeLine::Running);
670 QCOMPARE(timeLine.currentFrame(), timeLine.startFrame());
671 QCOMPARE(timeLine.currentTime(), 0);
674 QTEST_MAIN(tst_QTimeLine)
676 #include "tst_qtimeline.moc"