diff options
Diffstat (limited to 'tests/auto/integration/qwindowcapturebackend/fixture.h')
-rw-r--r-- | tests/auto/integration/qwindowcapturebackend/fixture.h | 147 |
1 files changed, 147 insertions, 0 deletions
diff --git a/tests/auto/integration/qwindowcapturebackend/fixture.h b/tests/auto/integration/qwindowcapturebackend/fixture.h new file mode 100644 index 000000000..2f72c3468 --- /dev/null +++ b/tests/auto/integration/qwindowcapturebackend/fixture.h @@ -0,0 +1,147 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +#ifndef WINDOW_CAPTURE_FIXTURE_H +#define WINDOW_CAPTURE_FIXTURE_H + +#include "grabber.h" +#include "widget.h" + +#include <chrono> +#include <qmediacapturesession.h> +#include <qmediarecorder.h> +#include <qobject.h> +#include <qsignalspy.h> +#include <qtest.h> +#include <qvideoframe.h> +#include <qwindowcapture.h> +#include <qprocess.h> + +QT_USE_NAMESPACE + +constexpr inline std::chrono::milliseconds s_testTimeout = std::chrono::seconds(60); + +/*! + Utility used to hide application cursor for image comparison tests. + On Windows, the mouse cursor is captured as part of the window capture. + This and can cause differences when comparing captured images with images + from QWindow::grab() which is used as a reference. +*/ +struct DisableCursor final +{ + DisableCursor(); + ~DisableCursor(); + + DisableCursor(const DisableCursor &) = delete; + DisableCursor &operator=(const DisableCursor &) = delete; +}; + +/*! + Fixture class that orchestrates setup/teardown of window capturing +*/ +class WindowCaptureFixture : public QObject +{ + Q_OBJECT + +public: + WindowCaptureFixture(); + + /*! + Compare two images, ignoring format. + If images differ, diagnostic output is logged and images are saved to file. + */ + static bool compareImages(QImage actual, const QImage &expected, + const QString &fileSuffix = ""); + + QMediaCaptureSession m_session; + QWindowCapture m_capture; + FrameGrabber m_grabber; + + QSignalSpy m_errors{ &m_capture, &QWindowCapture::errorOccurred }; + QSignalSpy m_activations{ &m_capture, &QWindowCapture::activeChanged }; + +private: + /*! + Calculate a result path based upon a single filename. + On CI, the file will be located in COIN_CTEST_RESULTSDIR, and on developer + computers, the file will be located in TEMP. + + The file name is on the form "testCase_testFunction_[dataTag_]fileName" + */ + static QString getResultsPath(const QString &fileName); +}; + +/*! + Fixture class that extends window capture fixture with a capturable widget +*/ +class WindowCaptureWithWidgetFixture : public WindowCaptureFixture +{ + Q_OBJECT + +public: + /*! + Starts capturing and returns true if successful. + + Two phase initialization is used to be able to detect + failure to find widget window as a capturable window. + */ + bool start(QSize size = { 60, 40 }); + + /*! + Waits until the a captured frame is received and returns it + */ + QVideoFrame waitForFrame(qint64 noOlderThanTime = 0); + + DisableCursor m_cursorDisabled; // Avoid mouse cursor causing image differences + TestWidget m_widget; + QCapturableWindow m_captureWindow; + +protected: + static QCapturableWindow findCaptureWindow(const QString &windowTitle); +}; + +class WindowCaptureWithWidgetInOtherProcessFixture : public WindowCaptureWithWidgetFixture +{ + Q_OBJECT + +public: + ~WindowCaptureWithWidgetInOtherProcessFixture() { m_windowProcess.close(); } + + /*! + Create widget in separate process and start capturing its content + */ + bool start(); + + QProcess m_windowProcess; +}; + +class WindowCaptureWithWidgetAndRecorderFixture : public WindowCaptureWithWidgetFixture +{ + Q_OBJECT + +public: + void start(QSize size = { 60, 40 }, bool togglePattern = true); + + /*! + Stop recording. + + Since recorder finalizes the file asynchronously, even after destructors are called, + we need to explicitly wait for the stopped state before ending the test. If we don't + do this, the media file can not be deleted by the QTemporaryDir at destruction. + */ + bool stop(); + + bool testVideoFilePlayback(const QString& fileName); + +public slots: + void recorderStateChanged(QMediaRecorder::RecorderState state); + +public: + QTemporaryDir m_tempDir; + const QString m_mediaFile = m_tempDir.filePath("test.mp4"); + QMediaRecorder m_recorder; + QMediaRecorder::RecorderState m_recorderState = QMediaRecorder::StoppedState; + QSignalSpy m_recorderErrors{ &m_recorder, &QMediaRecorder::errorOccurred }; +}; + +#endif |