Revision control

Copy as Markdown

// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include "qmockintegration.h"
#include "qmockmediaplayer.h"
#include "qmockaudiooutput.h"
#include <QtMultimediaTestLib/private/qmockresolvers_p.h>
#include <QtTest/qsignalspy.h>
#include <QtTest/qtest.h>
#include <QtMultimedia/qaudiooutput.h>
#include <QtMultimedia/qmediaplayer.h>
#include <QtMultimedia/qplaybackoptions.h>
#include <QtMultimedia/qvideosink.h>
#include <QtMultimedia/private/qmediaplayer_p.h>
#include <QtMultimedia/private/qplatformmediaplayer_p.h>
#include <QtCore/qbuffer.h>
#include <QtCore/qdebug.h>
#include <QtCore/qobject.h>
using namespace std::chrono_literals;
using namespace Qt::StringLiterals;
Q_ENABLE_MOCK_MULTIMEDIA_PLUGIN
class AutoConnection
{
public:
AutoConnection(QObject *sender, const char *signal, QObject *receiver, const char *method)
: sender(sender), signal(signal), receiver(receiver), method(method)
{
QObject::connect(sender, signal, receiver, method);
}
~AutoConnection()
{
QObject::disconnect(sender, signal, receiver, method);
}
private:
QObject *sender;
const char *signal;
QObject *receiver;
const char *method;
};
class tst_QMediaPlayer: public QObject
{
Q_OBJECT
public slots:
void initTestCase();
void cleanupTestCase();
void init();
void cleanup();
private slots:
void play_doesNotResetError();
void setSource_resetsError();
void setSourceDevice_resetsError();
void setSource_sameSource_doesNotStopPlayback();
void testValid();
void testMedia_data();
void testMedia();
void testMultipleMedia_data();
void testMultipleMedia();
void testDuration_data();
void testDuration();
void testPosition_data();
void testPosition();
void testVolume_data();
void testVolume();
void testMuted_data();
void testMuted();
void testIsAvailable();
void testVideoAvailable_data();
void testVideoAvailable();
void testBufferStatus_data();
void testBufferStatus();
void testSeekable_data();
void testSeekable();
void testPlaybackRate_data();
void testPlaybackRate();
void testError_data();
void testError();
void testErrorString_data();
void testErrorString();
void testService();
void testPlay_data();
void testPlay();
void testPause_data();
void testPause();
void testStop_data();
void testStop();
void testMediaStatus_data();
void testMediaStatus();
void testSetVideoOutput();
void testSetVideoOutputDestruction();
void debugEnums();
void testDestructor();
void testQrc_data();
void testQrc();
void playbackOptions_returnsDefaultAfterConstruction();
void setPlaybackOptions_setsPlaybackOptions();
void setPlaybackOptions_doesNotEmitChangeSignal_whenOptionsDidNotChange();
void resetPlaybackOptions_resetsPlaybackOptionsToDefault();
void testSourceResolver();
private:
void setupCommonTestData();
QMockMediaPlayer *mockPlayer;
QAudioOutput *audioOutput = nullptr;
QMediaPlayer *player;
};
class QtTestMediaPlayer : public QMediaPlayer
{
Q_OBJECT
Q_PROPERTY(int a READ a WRITE setA NOTIFY aChanged)
Q_PROPERTY(int b READ b WRITE setB NOTIFY bChanged)
Q_PROPERTY(int c READ c WRITE setC NOTIFY cChanged)
Q_PROPERTY(int d READ d WRITE setD)
public:
QtTestMediaPlayer() : QMediaPlayer() {}
[[nodiscard]] int a() const { return m_a; }
void setA(int a) { m_a = a; }
[[nodiscard]] int b() const { return m_b; }
void setB(int b) { m_b = b; }
[[nodiscard]] int c() const { return m_c; }
void setC(int c) { m_c = c; }
[[nodiscard]] int d() const { return m_d; }
void setD(int d) { m_d = d; }
Q_SIGNALS:
void aChanged(int a);
void bChanged(int b);
void cChanged(int c);
private:
int m_a = 0;
int m_b = 0;
int m_c = 0;
int m_d = 0;
};
void tst_QMediaPlayer::setupCommonTestData()
{
QTest::addColumn<bool>("valid");
QTest::addColumn<QMediaPlayer::PlaybackState>("state");
QTest::addColumn<QMediaPlayer::MediaStatus>("status");
QTest::addColumn<QUrl>("mediaContent");
QTest::addColumn<qint64>("duration");
QTest::addColumn<qint64>("position");
QTest::addColumn<bool>("seekable");
QTest::addColumn<int>("volume");
QTest::addColumn<bool>("muted");
QTest::addColumn<bool>("videoAvailable");
QTest::addColumn<int>("bufferProgress");
QTest::addColumn<qreal>("playbackRate");
QTest::addColumn<QMediaPlayer::Error>("error");
QTest::addColumn<QString>("errorString");
QTest::newRow("invalid") << false << QMediaPlayer::StoppedState << QMediaPlayer::InvalidMedia <<
QUrl() << qint64(0) << qint64(0) << false << 0 << false << false << 0 <<
qreal(0) << QMediaPlayer::NoError << QString();
QTest::newRow("valid+null") << true << QMediaPlayer::StoppedState << QMediaPlayer::InvalidMedia <<
QUrl() << qint64(0) << qint64(0) << false << 0 << false << false << 50 <<
qreal(0) << QMediaPlayer::NoError << QString();
QTest::newRow("valid+content+stopped") << true << QMediaPlayer::StoppedState << QMediaPlayer::InvalidMedia <<
QUrl(QUrl("file:///some.mp3")) << qint64(0) << qint64(0) << false << 50 << false << false << 0 <<
qreal(1) << QMediaPlayer::NoError << QString();
QTest::newRow("valid+content+playing") << true << QMediaPlayer::PlayingState << QMediaPlayer::LoadedMedia <<
QUrl(QUrl("file:///some.mp3")) << qint64(10000) << qint64(10) << true << 50 << true << false << 0 <<
qreal(1) << QMediaPlayer::NoError << QString();
QTest::newRow("valid+content+paused") << true << QMediaPlayer::PausedState << QMediaPlayer::LoadedMedia <<
QUrl(QUrl("file:///some.mp3")) << qint64(10000) << qint64(10) << true << 50 << true << false << 0 <<
qreal(1) << QMediaPlayer::NoError << QString();
QTest::newRow("valud+streaming") << true << QMediaPlayer::PlayingState << QMediaPlayer::LoadedMedia <<
QUrl(QUrl("http://example.com/stream")) << qint64(10000) << qint64(10000) << false << 50 << false << true << 0 <<
qreal(1) << QMediaPlayer::NoError << QString();
QTest::newRow("valid+error") << true << QMediaPlayer::StoppedState << QMediaPlayer::InvalidMedia <<
QUrl(QUrl("http://example.com/stream")) << qint64(0) << qint64(0) << false << 50 << false << false << 0 <<
qreal(0) << QMediaPlayer::ResourceError << QStringLiteral("Resource unavailable");
}
void tst_QMediaPlayer::initTestCase()
{
}
void tst_QMediaPlayer::cleanupTestCase()
{
}
void tst_QMediaPlayer::init()
{
player = new QMediaPlayer;
mockPlayer = QMockIntegration::instance()->lastPlayer();
QTEST_ASSERT(mockPlayer);
audioOutput = new QAudioOutput;
player->setAudioOutput(audioOutput);
QTEST_ASSERT(mockPlayer->m_audioOutput != nullptr);
}
void tst_QMediaPlayer::cleanup()
{
delete player;
}
void tst_QMediaPlayer::play_doesNotResetError()
{
player->setSource(QUrl{u"https://dummy/dummy.mp3"_s});
mockPlayer->setError(QMediaPlayer::AccessDeniedError);
mockPlayer->setErrorString(QStringLiteral(u"Error"));
QSignalSpy errorSpy{ player, &QMediaPlayer::errorChanged };
player->play();
QCOMPARE_EQ(player->error(), QMediaPlayer::AccessDeniedError);
QCOMPARE_EQ(player->errorString(), QStringLiteral(u"Error"));
QCOMPARE_EQ(errorSpy.size(), 0);
}
void tst_QMediaPlayer::setSource_resetsError()
{
mockPlayer->setError(QMediaPlayer::AccessDeniedError);
mockPlayer->setErrorString(QStringLiteral(u"Error"));
QSignalSpy errorSpy{ player, &QMediaPlayer::errorChanged };
player->setSource(QUrl{u"https://dummy/dummy.mp3"_s});
QCOMPARE_EQ(player->error(), QMediaPlayer::NoError);
QVERIFY(player->errorString().isEmpty());
QCOMPARE_EQ(errorSpy.size(), 1);
}
void tst_QMediaPlayer::setSourceDevice_resetsError()
{
mockPlayer->setError(QMediaPlayer::AccessDeniedError);
mockPlayer->setErrorString(QStringLiteral(u"Error"));
QSignalSpy errorSpy{ player, &QMediaPlayer::errorChanged };
player->setSourceDevice(nullptr, QUrl{u"https://dummy/dummy.mp3"_s});
QCOMPARE_EQ(player->error(), QMediaPlayer::NoError);
QVERIFY(player->errorString().isEmpty());
QCOMPARE_EQ(errorSpy.size(), 1);
}
void tst_QMediaPlayer::setSource_sameSource_doesNotStopPlayback()
{
const QUrl source{ u"file:///some.mp3"_s };
player->setSource(source);
mockPlayer->setIsValid(true);
mockPlayer->setState(QMediaPlayer::PlayingState, QMediaPlayer::LoadedMedia);
QCOMPARE_EQ(player->playbackState(), QMediaPlayer::PlayingState);
QVERIFY(player->isPlaying());
QSignalSpy stateSpy{ player, &QMediaPlayer::playbackStateChanged };
QSignalSpy playingSpy{ player, &QMediaPlayer::playingChanged };
QSignalSpy statusSpy{ player, &QMediaPlayer::mediaStatusChanged };
QSignalSpy sourceSpy{ player, &QMediaPlayer::sourceChanged };
player->setSource(source);
QCOMPARE_EQ(player->source(), source);
QCOMPARE_EQ(player->playbackState(), QMediaPlayer::PlayingState);
QVERIFY(player->isPlaying());
QCOMPARE_EQ(stateSpy.size(), 0);
QCOMPARE_EQ(playingSpy.size(), 0);
QCOMPARE_EQ(statusSpy.size(), 0);
QCOMPARE_EQ(sourceSpy.size(), 0);
}
void tst_QMediaPlayer::testValid()
{
/*
QFETCH(bool, valid);
mockService->setIsValid(valid);
QCOMPARE(player->isValid(), valid);
*/
}
void tst_QMediaPlayer::testMedia_data()
{
setupCommonTestData();
}
void tst_QMediaPlayer::testMedia()
{
QFETCH(QUrl, mediaContent);
player->setSource(mediaContent);
QCOMPARE(player->source(), mediaContent);
QBuffer stream;
player->setSourceDevice(&stream, mediaContent);
QCOMPARE(player->source(), mediaContent);
QCOMPARE(player->sourceDevice(), &stream);
}
void tst_QMediaPlayer::testMultipleMedia_data()
{
QTest::addColumn<QUrl>("mediaContent");
QTest::addColumn<QUrl>("anotherMediaContent");
QTest::newRow("multipleSources")
<< QUrl(QUrl("file:///some.mp3")) << QUrl(QUrl("file:///someother.mp3"));
}
void tst_QMediaPlayer::testMultipleMedia()
{
QFETCH(QUrl, mediaContent);
player->setSource(mediaContent);
QCOMPARE(player->source(), mediaContent);
QBuffer stream;
player->setSourceDevice(&stream, mediaContent);
QCOMPARE(player->source(), mediaContent);
QCOMPARE(player->sourceDevice(), &stream);
QFETCH(QUrl, anotherMediaContent);
player->setSource(anotherMediaContent);
QCOMPARE(player->source(), anotherMediaContent);
QBuffer anotherStream;
player->setSourceDevice(&anotherStream, anotherMediaContent);
QCOMPARE(player->source(), anotherMediaContent);
QCOMPARE(player->sourceDevice(), &anotherStream);
}
void tst_QMediaPlayer::testDuration_data()
{
setupCommonTestData();
}
void tst_QMediaPlayer::testDuration()
{
QFETCH(qint64, duration);
mockPlayer->setDuration(duration);
QVERIFY(player->duration() == duration);
}
void tst_QMediaPlayer::testPosition_data()
{
setupCommonTestData();
}
void tst_QMediaPlayer::testPosition()
{
QFETCH(bool, valid);
QFETCH(bool, seekable);
QFETCH(qint64, position);
QFETCH(qint64, duration);
mockPlayer->setIsValid(valid);
mockPlayer->setSeekable(seekable);
mockPlayer->setPosition(position);
mockPlayer->setDuration(duration);
QVERIFY(player->isSeekable() == seekable);
QVERIFY(player->position() == position);
QVERIFY(player->duration() == duration);
if (seekable) {
{
QSignalSpy spy(player, &QMediaPlayer::positionChanged);
player->setPosition(position);
QCOMPARE(player->position(), position);
QCOMPARE(spy.size(), 0);
}
mockPlayer->setPosition(position);
{
QSignalSpy spy(player, &QMediaPlayer::positionChanged);
player->setPosition(0);
QCOMPARE(player->position(), qint64(0));
QCOMPARE(spy.size(), position == 0 ? 0 : 1);
}
mockPlayer->setPosition(position);
{
QSignalSpy spy(player, &QMediaPlayer::positionChanged);
player->setPosition(duration);
QCOMPARE(player->position(), duration);
QCOMPARE(spy.size(), position == duration ? 0 : 1);
}
mockPlayer->setPosition(position);
{
QSignalSpy spy(player, &QMediaPlayer::positionChanged);
player->setPosition(-1);
QCOMPARE(player->position(), qint64(0));
QCOMPARE(spy.size(), position == 0 ? 0 : 1);
}
}
else {
QSignalSpy spy(player, &QMediaPlayer::positionChanged);
player->setPosition(position);
QCOMPARE(player->position(), position);
QCOMPARE(spy.size(), 0);
}
}
void tst_QMediaPlayer::testVolume_data()
{
setupCommonTestData();
}
void tst_QMediaPlayer::testVolume()
{
QFETCH(bool, valid);
QFETCH(int, volume);
float vol = volume/100.;
audioOutput->setVolume(vol);
QVERIFY(audioOutput->volume() == vol);
if (valid) {
{
QSignalSpy spy(audioOutput, &QAudioOutput::volumeChanged);
audioOutput->setVolume(.1f);
QCOMPARE(audioOutput->volume(), .1f);
QCOMPARE(spy.size(), 1);
}
{
QSignalSpy spy(audioOutput, &QAudioOutput::volumeChanged);
audioOutput->setVolume(-1000.f);
QCOMPARE(audioOutput->volume(), 0.f);
QCOMPARE(spy.size(), 1);
}
{
QSignalSpy spy(audioOutput, &QAudioOutput::volumeChanged);
audioOutput->setVolume(1.f);
QCOMPARE(audioOutput->volume(), 1.f);
QCOMPARE(spy.size(), 1);
}
{
QSignalSpy spy(audioOutput, &QAudioOutput::volumeChanged);
audioOutput->setVolume(1000.f);
QCOMPARE(audioOutput->volume(), 1.f);
QCOMPARE(spy.size(), 0);
}
}
}
void tst_QMediaPlayer::testMuted_data()
{
setupCommonTestData();
}
void tst_QMediaPlayer::testMuted()
{
QFETCH(bool, valid);
QFETCH(bool, muted);
QFETCH(int, volume);
float vol = volume/100.;
if (valid) {
audioOutput->setMuted(muted);
audioOutput->setVolume(vol);
QVERIFY(audioOutput->isMuted() == muted);
QSignalSpy spy(audioOutput, &QAudioOutput::mutedChanged);
audioOutput->setMuted(!muted);
QCOMPARE(audioOutput->isMuted(), !muted);
QCOMPARE(audioOutput->volume(), vol);
QCOMPARE(spy.size(), 1);
}
}
void tst_QMediaPlayer::testVideoAvailable_data()
{
setupCommonTestData();
}
void tst_QMediaPlayer::testVideoAvailable()
{
QFETCH(bool, videoAvailable);
mockPlayer->setVideoAvailable(videoAvailable);
QVERIFY(player->hasVideo() == videoAvailable);
}
void tst_QMediaPlayer::testBufferStatus_data()
{
setupCommonTestData();
}
void tst_QMediaPlayer::testBufferStatus()
{
QFETCH(int, bufferProgress);
mockPlayer->setBufferStatus(bufferProgress);
QVERIFY(player->bufferProgress() == bufferProgress);
}
void tst_QMediaPlayer::testSeekable_data()
{
setupCommonTestData();
}
void tst_QMediaPlayer::testSeekable()
{
QFETCH(bool, seekable);
mockPlayer->setSeekable(seekable);
QVERIFY(player->isSeekable() == seekable);
}
void tst_QMediaPlayer::testPlaybackRate_data()
{
setupCommonTestData();
}
void tst_QMediaPlayer::testPlaybackRate()
{
QFETCH(bool, valid);
QFETCH(qreal, playbackRate);
if (valid) {
mockPlayer->setPlaybackRate(playbackRate);
QVERIFY(player->playbackRate() == playbackRate);
QSignalSpy spy(player, &QMediaPlayer::playbackRateChanged);
player->setPlaybackRate(playbackRate + 0.5f);
QCOMPARE(player->playbackRate(), playbackRate + 0.5f);
QCOMPARE(spy.size(), 1);
}
}
void tst_QMediaPlayer::testError_data()
{
setupCommonTestData();
}
void tst_QMediaPlayer::testError()
{
QFETCH(QMediaPlayer::Error, error);
mockPlayer->setError(error);
QVERIFY(player->error() == error);
}
void tst_QMediaPlayer::testErrorString_data()
{
setupCommonTestData();
}
void tst_QMediaPlayer::testErrorString()
{
QFETCH(QString, errorString);
mockPlayer->setErrorString(errorString);
QVERIFY(player->errorString() == errorString);
}
void tst_QMediaPlayer::testIsAvailable()
{
QCOMPARE(player->isAvailable(), true);
}
void tst_QMediaPlayer::testService()
{
/*
QFETCH(bool, valid);
mockService->setIsValid(valid);
if (valid)
QVERIFY(player->service() != 0);
else
QVERIFY(player->service() == 0);
*/
}
void tst_QMediaPlayer::testPlay_data()
{
setupCommonTestData();
}
void tst_QMediaPlayer::testPlay()
{
QFETCH(bool, valid);
QFETCH(QUrl, mediaContent);
QFETCH(QMediaPlayer::PlaybackState, state);
mockPlayer->setIsValid(valid);
player->setSource(mediaContent);
mockPlayer->setState(state);
QCOMPARE(player->playbackState(), state);
QCOMPARE(player->isPlaying(), state == QMediaPlayer::PlayingState);
QCOMPARE(player->source(), mediaContent);
QSignalSpy spy(player, &QMediaPlayer::playbackStateChanged);
QSignalSpy playingChanged(player, &QMediaPlayer::playingChanged);
player->play();
if (!valid || mediaContent.isEmpty()) {
QCOMPARE(player->playbackState(), QMediaPlayer::StoppedState);
QVERIFY(!player->isPlaying());
QCOMPARE(spy.size(), 0);
QVERIFY(playingChanged.empty());
}
else {
QCOMPARE(player->playbackState(), QMediaPlayer::PlayingState);
QVERIFY(player->isPlaying());
QCOMPARE(spy.size(), state == QMediaPlayer::PlayingState ? 0 : 1);
QCOMPARE_EQ(playingChanged.size(), state == QMediaPlayer::PlayingState ? 0 : 1);
}
}
void tst_QMediaPlayer::testPause_data()
{
setupCommonTestData();
}
void tst_QMediaPlayer::testPause()
{
QFETCH(bool, valid);
QFETCH(QUrl, mediaContent);
QFETCH(QMediaPlayer::PlaybackState, state);
mockPlayer->setIsValid(valid);
player->setSource(mediaContent);
mockPlayer->setState(state);
QVERIFY(player->playbackState() == state);
QCOMPARE(player->isPlaying(), state == QMediaPlayer::PlayingState);
QVERIFY(player->source() == mediaContent);
QSignalSpy spy(player, &QMediaPlayer::playbackStateChanged);
QSignalSpy playingChanged(player, &QMediaPlayer::playingChanged);
player->pause();
QVERIFY(!player->isPlaying());
if (!valid || mediaContent.isEmpty()) {
QCOMPARE(player->playbackState(), QMediaPlayer::StoppedState);
QCOMPARE(spy.size(), 0);
QCOMPARE(playingChanged.size(), 0);
}
else {
QCOMPARE(player->playbackState(), QMediaPlayer::PausedState);
QCOMPARE(spy.size(), state == QMediaPlayer::PausedState ? 0 : 1);
QCOMPARE(playingChanged.size(), state == QMediaPlayer::PlayingState ? 1 : 0);
}
}
void tst_QMediaPlayer::testStop_data()
{
setupCommonTestData();
}
void tst_QMediaPlayer::testStop()
{
QFETCH(QUrl, mediaContent);
QFETCH(QMediaPlayer::PlaybackState, state);
player->setSource(mediaContent);
mockPlayer->setState(state);
QVERIFY(player->playbackState() == state);
QCOMPARE(player->isPlaying(), state == QMediaPlayer::PlayingState);
QVERIFY(player->source() == mediaContent);
QSignalSpy spy(player, &QMediaPlayer::playbackStateChanged);
QSignalSpy playingChanged(player, &QMediaPlayer::playingChanged);
player->stop();
QVERIFY(!player->isPlaying());
if (mediaContent.isEmpty() || state == QMediaPlayer::StoppedState) {
QCOMPARE(player->playbackState(), QMediaPlayer::StoppedState);
QCOMPARE(spy.size(), 0);
QCOMPARE(playingChanged.size(), 0);
}
else {
QCOMPARE(player->playbackState(), QMediaPlayer::StoppedState);
QCOMPARE(spy.size(), 1);
QCOMPARE(playingChanged.size(), state == QMediaPlayer::PlayingState ? 1 : 0);
}
}
void tst_QMediaPlayer::testMediaStatus_data()
{
setupCommonTestData();
}
void tst_QMediaPlayer::testMediaStatus()
{
QFETCH(int, bufferProgress);
int bufferSignals = 0;
mockPlayer->setMediaStatus(QMediaPlayer::NoMedia);
mockPlayer->setBufferStatus(bufferProgress);
QSignalSpy statusSpy(player, &QMediaPlayer::mediaStatusChanged);
QSignalSpy bufferSpy(player, &QMediaPlayer::bufferProgressChanged);
QCOMPARE(player->mediaStatus(), QMediaPlayer::NoMedia);
mockPlayer->setMediaStatus(QMediaPlayer::LoadingMedia);
QCOMPARE(player->mediaStatus(), QMediaPlayer::LoadingMedia);
QCOMPARE(statusSpy.size(), 1);
QCOMPARE(qvariant_cast<QMediaPlayer::MediaStatus>(statusSpy.last().value(0)),
QMediaPlayer::LoadingMedia);
mockPlayer->setMediaStatus(QMediaPlayer::LoadedMedia);
QCOMPARE(player->mediaStatus(), QMediaPlayer::LoadedMedia);
QCOMPARE(statusSpy.size(), 2);
QCOMPARE(qvariant_cast<QMediaPlayer::MediaStatus>(statusSpy.last().value(0)),
QMediaPlayer::LoadedMedia);
// Verify the bufferProgressChanged() signal isn't being emitted.
QCOMPARE(bufferSpy.size(), 0);
mockPlayer->setMediaStatus(QMediaPlayer::StalledMedia);
QCOMPARE(player->mediaStatus(), QMediaPlayer::StalledMedia);
QCOMPARE(statusSpy.size(), 3);
QCOMPARE(qvariant_cast<QMediaPlayer::MediaStatus>(statusSpy.last().value(0)),
QMediaPlayer::StalledMedia);
// Verify the bufferProgressChanged() signal is being emitted.
QVERIFY(bufferSpy.size() > bufferSignals);
QCOMPARE(bufferSpy.last().value(0).toInt(), bufferProgress);
bufferSignals = bufferSpy.size();
mockPlayer->setMediaStatus(QMediaPlayer::BufferingMedia);
QCOMPARE(player->mediaStatus(), QMediaPlayer::BufferingMedia);
QCOMPARE(statusSpy.size(), 4);
QCOMPARE(qvariant_cast<QMediaPlayer::MediaStatus>(statusSpy.last().value(0)),
QMediaPlayer::BufferingMedia);
// Verify the bufferProgressChanged() signal is being emitted.
QVERIFY(bufferSpy.size() > bufferSignals);
QCOMPARE(bufferSpy.last().value(0).toInt(), bufferProgress);
bufferSignals = bufferSpy.size();
mockPlayer->setMediaStatus(QMediaPlayer::BufferedMedia);
QCOMPARE(player->mediaStatus(), QMediaPlayer::BufferedMedia);
QCOMPARE(statusSpy.size(), 5);
QCOMPARE(qvariant_cast<QMediaPlayer::MediaStatus>(statusSpy.last().value(0)),
QMediaPlayer::BufferedMedia);
// Verify the bufferProgressChanged() signal isn't being emitted.
QCOMPARE(bufferSpy.size(), bufferSignals);
mockPlayer->setMediaStatus(QMediaPlayer::EndOfMedia);
QCOMPARE(player->mediaStatus(), QMediaPlayer::EndOfMedia);
QCOMPARE(statusSpy.size(), 6);
QCOMPARE(qvariant_cast<QMediaPlayer::MediaStatus>(statusSpy.last().value(0)),
QMediaPlayer::EndOfMedia);
}
void tst_QMediaPlayer::testDestructor()
{
/* create an object for player */
QMediaPlayer *victim = new QMediaPlayer;
/* check whether the object is created */
QVERIFY(victim);
/* delete the instance (a crash is a failure :) */
delete victim;
}
void tst_QMediaPlayer::testSetVideoOutput()
{
QVideoSink surface;
player->setVideoOutput(static_cast<QObject *>(nullptr));
// QCOMPARE(mockService->rendererRef, 0);
player->setVideoOutput(&surface);
// QVERIFY(mockService->rendererControl->surface() == &surface);
// QCOMPARE(mockService->rendererRef, 1);
player->setVideoOutput(reinterpret_cast<QVideoSink *>(0));
// QVERIFY(mockService->rendererControl->surface() == nullptr);
//rendererControl is released
// QCOMPARE(mockService->rendererRef, 0);
player->setVideoOutput(&surface);
// QVERIFY(mockService->rendererControl->surface() == &surface);
// QCOMPARE(mockService->rendererRef, 1);
player->setVideoOutput(static_cast<QObject *>(nullptr));
// QVERIFY(mockService->rendererControl->surface() == nullptr);
// //rendererControl is released
// QCOMPARE(mockService->rendererRef, 0);
player->setVideoOutput(&surface);
// QVERIFY(mockService->rendererControl->surface() == &surface);
// QCOMPARE(mockService->rendererRef, 1);
}
void tst_QMediaPlayer::testSetVideoOutputDestruction()
{
QVideoSink surface;
{
QMediaPlayer player;
player.setVideoOutput(&surface);
}
}
void tst_QMediaPlayer::debugEnums()
{
QTest::ignoreMessage(QtDebugMsg, "QMediaPlayer::PlayingState");
qDebug() << QMediaPlayer::PlayingState;
QTest::ignoreMessage(QtDebugMsg, "QMediaPlayer::NoMedia");
qDebug() << QMediaPlayer::NoMedia;
QTest::ignoreMessage(QtDebugMsg, "QMediaPlayer::NetworkError");
qDebug() << QMediaPlayer::NetworkError;
}
void tst_QMediaPlayer::testQrc_data()
{
QTest::addColumn<QUrl>("mediaContent");
QTest::addColumn<QList<QMediaPlayer::MediaStatus>>("status");
QTest::addColumn<QMediaPlayer::Error>("error");
QTest::addColumn<int>("errorCount");
QTest::addColumn<QString>("backendMediaContentScheme");
QTest::addColumn<bool>("backendHasStream");
QTest::newRow("invalid") << QUrl(QUrl(QLatin1String("qrc:/invalid.mp3")))
<< QList{QMediaPlayer::LoadingMedia, QMediaPlayer::InvalidMedia}
<< QMediaPlayer::ResourceError
<< 1 // error count
<< QString() // backend should not have got any media (empty URL scheme)
<< false; // backend should not have got any stream
QTest::newRow("valid+nostream") << QUrl(QUrl(QLatin1String("qrc:/testdata/nokia-tune.mp3")))
<< QList{QMediaPlayer::LoadingMedia}
<< QMediaPlayer::NoError
<< 0 // error count
<< QStringLiteral("file") // backend should have a got a temporary file
<< false; // backend should not have got any stream
QTest::newRow("valid+stream") << QUrl(QUrl(QLatin1String("qrc:/testdata/nokia-tune.mp3")))
<< QList{QMediaPlayer::LoadingMedia}
<< QMediaPlayer::NoError
<< 0 // error count
<< QStringLiteral("qrc")
<< true; // backend should have got a stream (QFile opened from the resource)
}
void tst_QMediaPlayer::testQrc()
{
QFETCH(QUrl, mediaContent);
QFETCH(QList<QMediaPlayer::MediaStatus>, status);
QFETCH(QMediaPlayer::Error, error);
QFETCH(int, errorCount);
QFETCH(QString, backendMediaContentScheme);
QFETCH(bool, backendHasStream);
mockPlayer->setState(QMediaPlayer::PlayingState, QMediaPlayer::NoMedia);
mockPlayer->setStreamPlaybackSupported(backendHasStream);
QSignalSpy mediaSpy(player, &QMediaPlayer::sourceChanged);
QSignalSpy statusSpy(player, &QMediaPlayer::mediaStatusChanged);
QSignalSpy errorSpy(player, &QMediaPlayer::errorOccurred);
player->setSource(mediaContent);
QTRY_COMPARE(player->mediaStatus(), status.back());
QList<QMediaPlayer::MediaStatus> spyStatus;
for (const auto &call : statusSpy)
spyStatus.append(qvariant_cast<QMediaPlayer::MediaStatus>(call.value(0)));
QCOMPARE(spyStatus, status);
QCOMPARE(player->source(), mediaContent);
QCOMPARE(mediaSpy.size(), 1);
QCOMPARE(qvariant_cast<QUrl>(mediaSpy.last().value(0)), mediaContent);
QCOMPARE(player->error(), error);
QCOMPARE(errorSpy.size(), errorCount);
if (errorCount > 0) {
QCOMPARE(qvariant_cast<QMediaPlayer::Error>(errorSpy.last().value(0)), error);
QVERIFY(!player->errorString().isEmpty());
}
// Check the media actually passed to the backend
QCOMPARE(mockPlayer->media().scheme(), backendMediaContentScheme);
QCOMPARE(bool(mockPlayer->mediaStream()), backendHasStream);
}
void tst_QMediaPlayer::playbackOptions_returnsDefaultAfterConstruction()
{
QCOMPARE_EQ(player->playbackOptions(), QPlaybackOptions{});
}
void tst_QMediaPlayer::setPlaybackOptions_setsPlaybackOptions()
{
QSignalSpy spy{ player, &QMediaPlayer::playbackOptionsChanged };
QPlaybackOptions options;
const std::chrono::milliseconds defaultNetworkTimeout = options.networkTimeout();
options.setNetworkTimeout(defaultNetworkTimeout + 1ms);
player->setPlaybackOptions(options);
QCOMPARE_NE(player->playbackOptions().networkTimeout(), defaultNetworkTimeout);
QCOMPARE_EQ(spy.size(), 1);
}
void tst_QMediaPlayer::setPlaybackOptions_doesNotEmitChangeSignal_whenOptionsDidNotChange()
{
QSignalSpy spy{ player, &QMediaPlayer::playbackOptionsChanged };
player->setPlaybackOptions(player->playbackOptions());
QCOMPARE_EQ(spy.size(), 0);
}
void tst_QMediaPlayer::resetPlaybackOptions_resetsPlaybackOptionsToDefault()
{
auto options = player->playbackOptions();
options.setNetworkTimeout(options.networkTimeout() + 1ms);
player->setPlaybackOptions(options);
player->resetPlaybackOptions();
QCOMPARE_EQ(player->playbackOptions(), QPlaybackOptions{});
}
void tst_QMediaPlayer::testSourceResolver()
{
using namespace QtMultimediaTest;
QMediaPlayer player;
auto *d = QMediaPlayerPrivate::get(&player);
auto mock = std::make_unique<MockSourceResolver>(QUrl(u"mock://resolved"_s));
MockSourceResolver *mockPtr = mock.get();
d->m_sourceResolver = std::move(mock);
player.setSource(QUrl(u"original://test"_s));
QCOMPARE(mockPtr->m_callCount, 1);
QCOMPARE(mockPtr->m_lastInput, QUrl(u"original://test"_s));
QCOMPARE(player.source(), QUrl(u"original://test"_s));
}
QTEST_GUILESS_MAIN(tst_QMediaPlayer)
#include "tst_qmediaplayer.moc"