Uploaded image for project: 'Qt'
  1. Qt
  2. QTBUG-120105

Unreliable QML Timer / qmltest wait() / QTest:qWait() with offscreen platform

    XMLWordPrintable

Details

    • 198a90f56 (dev), b156a1f1f (6.7), 11dcf2d22 (6.6), 5e4b4b02f (tqtc/lts-6.5), 0c8694d8b (tqtc/lts-6.2)

    Description

      [This is a /possible/ regression from Qt 6.2.3, although I'm not sure if this has ever been intentionally reliable / documented / described behavior.]

      Consider the following qml testcase. A 7000ms timer is started, we wait 6900ms, check that the timer is still running, then wait another 200ms and check that the timer has stopped. Running this test using qmltestrunner, default platform, is (as) stable (as a walltime based test can be).

      import QtQuick 2.0
      import QtTest  1.2
      
      TestCase {
          Timer {
              id: timer
              interval: 7000
          }
      
          function test_wait() {
              timer.start();
              wait(6900);
              verify(timer.running)
              wait(200);
              verify(!timer.running)
          }
      }
      

      Now run the same testcase, but add '-platform offscreen'. The test now becomes flaky and unreliable. TL;DR scroll to end.

      The reason seems to be that wait() (qtbase/src/corelib/kernel/qtestsupport_core.cpp:72 QTest::qWait()) makes use of a QDeadLineTimer with Qt::PreciseTimer precision, which, for the sake of the wait function itself, is IMO a good thing. In contrast, QML Timer (src/qml/types/qqmltimer.cpp), which is driven by a QPauseAnimationJob (src/qml/animations/qpauseanimationjob.cpp) whose timer is a thread-local QQmlAnimationTimer which uses QUnifiedTimer which ends up using Qt::CoarseTimer because the pause is so long.

      Qt::CoarseTimer (https://doc.qt.io/qt-6/qt.html#TimerType-enum) is documented to have a slack of 5% on the scheduled expiry. So when starting a coarse 7000ms timer, the timer could trigger between 6650ms and 7350ms, the exact delay depending on what time it is right now. (OT, it looks like the unix timerinfo implementation never snaps to more than 1 second.)

      TL;DR: Making this test reliable is quite hard. But it would be nice if QML's own test framework's wait function(s) could be used to reliably test QML's own timers and/or animations. For test cases, and in particular the offscreen case, what are the benefits of using Qt::CoarseTimer? And also, shouldn't the user be allowed to specify whether it's OK if a QML Timer of 7000ms misses its deadline by between -350ms and +350ms?

      Attachments

        For Gerrit Dashboard: QTBUG-120105
        # Subject Branch Project Status CR V

        Activity

          People

            ulherman Ulf Hermann
            andrhans Andreas Aardal Hanssen
            Votes:
            0 Vote for this issue
            Watchers:
            5 Start watching this issue

            Dates

              Created:
              Updated:
              Resolved:

              Gerrit Reviews