From 0ed18d846c0b425b0c50a2fefd7cc0fc148832c2 Mon Sep 17 00:00:00 2001
From: Robin Burchell <robin.burchell@jollamobile.com>
Date: Thu, 31 Jul 2014 12:49:16 +0200
Subject: [PATCH] QMediaNetworkPlaylistProvider: Upon error parsing, stop
 parsing.

When an error is found parsing a playlist, stop parsing. This will also prevent
the emission of the "loaded" signal when the parser finishes.

Some of the newly added testcases do not yet pass because the parser is overly
strict. These improvements are being tracked in QTBUG-40515.

Change-Id: I5c96b7eb488996f28eebd7b6c643940de8e2e0b9
Done-by: Andres Gomez <agomez@igalia.com>
Task-number: QTBUG-40513
Reviewed-by: Andrew den Exter <andrew.den.exter@qinetic.com.au>
---
 .../qmedianetworkplaylistprovider.cpp         |  2 +
 .../unit/qmediaplaylist/testdata/test.pls     | 27 ++++++
 .../testdata/totem-pl-example.pls             |  5 +
 .../unit/qmediaplaylist/testdata/trash.pls    |  2 +
 .../qmediaplaylist/tst_qmediaplaylist.cpp     | 92 ++++++++++++++++++-
 5 files changed, 127 insertions(+), 1 deletion(-)
 create mode 100644 tests/auto/unit/qmediaplaylist/testdata/test.pls
 create mode 100644 tests/auto/unit/qmediaplaylist/testdata/totem-pl-example.pls
 create mode 100644 tests/auto/unit/qmediaplaylist/testdata/trash.pls

diff --git a/src/multimedia/playback/qmedianetworkplaylistprovider.cpp b/src/multimedia/playback/qmedianetworkplaylistprovider.cpp
index a8d8c4b04..9bbd7f3a6 100644
--- a/src/multimedia/playback/qmedianetworkplaylistprovider.cpp
+++ b/src/multimedia/playback/qmedianetworkplaylistprovider.cpp
@@ -90,6 +90,8 @@ void QMediaNetworkPlaylistProviderPrivate::_q_handleParserError(QPlaylistFilePar
         break;
     }
 
+    parser.stop();
+
     emit q->loadFailed(playlistError, errorMessage);
 }
 
diff --git a/tests/auto/unit/qmediaplaylist/testdata/test.pls b/tests/auto/unit/qmediaplaylist/testdata/test.pls
new file mode 100644
index 000000000..42a14f395
--- /dev/null
+++ b/tests/auto/unit/qmediaplaylist/testdata/test.pls
@@ -0,0 +1,27 @@
+[playlist]
+
+File1=http://test.host/path
+Title1=First
+Length1=-1
+File2= http://test.host/path  
+Title2=Second
+Length2=-1
+File3=testfile
+Title3=Third
+Length3=-1
+
+
+
+File4=testdir/testfile
+Title4=Fourth
+Length4=-1
+File5=/testdir/testfile
+Title5=Fifth
+Length5=-1
+File6=file://path/name#suffix
+Title6=Sixth
+Length6=-1
+File7=testfile2#suffix
+Title7=Seventh
+Length7=-1
+NumberOfEntries=7
diff --git a/tests/auto/unit/qmediaplaylist/testdata/totem-pl-example.pls b/tests/auto/unit/qmediaplaylist/testdata/totem-pl-example.pls
new file mode 100644
index 000000000..385fe2a30
--- /dev/null
+++ b/tests/auto/unit/qmediaplaylist/testdata/totem-pl-example.pls
@@ -0,0 +1,5 @@
+[playlist]
+X-GNOME-Title=totem-pl-file-example
+NumberOfEntries=1
+File1=http://test.host/path
+Title1=Silence
diff --git a/tests/auto/unit/qmediaplaylist/testdata/trash.pls b/tests/auto/unit/qmediaplaylist/testdata/trash.pls
new file mode 100644
index 000000000..639c22b0c
--- /dev/null
+++ b/tests/auto/unit/qmediaplaylist/testdata/trash.pls
@@ -0,0 +1,2 @@
+[playlist]
+NumberOfEntries=100
diff --git a/tests/auto/unit/qmediaplaylist/tst_qmediaplaylist.cpp b/tests/auto/unit/qmediaplaylist/tst_qmediaplaylist.cpp
index 7aa8d7a5a..85c2af47f 100644
--- a/tests/auto/unit/qmediaplaylist/tst_qmediaplaylist.cpp
+++ b/tests/auto/unit/qmediaplaylist/tst_qmediaplaylist.cpp
@@ -86,6 +86,7 @@ private slots:
     void currentItem();
     void saveAndLoad();
     void loadM3uFile();
+    void loadPLSFile();
     void playbackMode();
     void playbackMode_data();
     void shuffle();
@@ -356,8 +357,10 @@ void tst_QMediaPlaylist::saveAndLoad()
     QVERIFY(playlist.error() == QMediaPlaylist::FormatNotSupportedError);
     QVERIFY(!playlist.errorString().isEmpty());
 
+    QSignalSpy loadedSignal(&playlist, SIGNAL(loaded()));
     QSignalSpy errorSignal(&playlist, SIGNAL(loadFailed()));
     playlist.load(&buffer, "unsupported_format");
+    QTRY_VERIFY(loadedSignal.isEmpty());
     QCOMPARE(errorSignal.size(), 1);
     QVERIFY(playlist.error() != QMediaPlaylist::NoError);
     QVERIFY(!playlist.errorString().isEmpty());
@@ -367,8 +370,10 @@ void tst_QMediaPlaylist::saveAndLoad()
     QVERIFY(playlist.error() != QMediaPlaylist::NoError);
     QVERIFY(!playlist.errorString().isEmpty());
 
+    loadedSignal.clear();
     errorSignal.clear();
     playlist.load(QUrl::fromLocalFile(QLatin1String("tmp.unsupported_format")), "unsupported_format");
+    QTRY_VERIFY(loadedSignal.isEmpty());
     QCOMPARE(errorSignal.size(), 1);
     QVERIFY(playlist.error() == QMediaPlaylist::FormatNotSupportedError);
     QVERIFY(!playlist.errorString().isEmpty());
@@ -380,7 +385,11 @@ void tst_QMediaPlaylist::saveAndLoad()
     buffer.seek(0);
 
     QMediaPlaylist playlist2;
+    QSignalSpy loadedSignal2(&playlist2, SIGNAL(loaded()));
+    QSignalSpy errorSignal2(&playlist2, SIGNAL(loadFailed()));
     playlist2.load(&buffer, "m3u");
+    QCOMPARE(loadedSignal2.size(), 1);
+    QTRY_VERIFY(errorSignal2.isEmpty());
     QCOMPARE(playlist.error(), QMediaPlaylist::NoError);
 
     QCOMPARE(playlist.mediaCount(), playlist2.mediaCount());
@@ -390,9 +399,13 @@ void tst_QMediaPlaylist::saveAndLoad()
     res = playlist.save(QUrl::fromLocalFile(QLatin1String("tmp.m3u")), "m3u");
     QVERIFY(res);
 
+    loadedSignal2.clear();
+    errorSignal2.clear();
     playlist2.clear();
     QVERIFY(playlist2.isEmpty());
     playlist2.load(QUrl::fromLocalFile(QLatin1String("tmp.m3u")), "m3u");
+    QCOMPARE(loadedSignal2.size(), 1);
+    QTRY_VERIFY(errorSignal2.isEmpty());
     QCOMPARE(playlist.error(), QMediaPlaylist::NoError);
 
     QCOMPARE(playlist.mediaCount(), playlist2.mediaCount());
@@ -406,12 +419,20 @@ void tst_QMediaPlaylist::loadM3uFile()
     QMediaPlaylist playlist;
 
     // Try to load playlist that does not exist in the testdata folder
+    QSignalSpy loadSpy(&playlist, SIGNAL(loaded()));
+    QSignalSpy loadFailedSpy(&playlist, SIGNAL(loadFailed()));
     QString testFileName = QFINDTESTDATA("testdata");
     playlist.load(QUrl::fromLocalFile(testFileName + "/missing_file.m3u"));
+    QTRY_VERIFY(loadSpy.isEmpty());
+    QVERIFY(!loadFailedSpy.isEmpty());
     QVERIFY(playlist.error() != QMediaPlaylist::NoError);
 
+    loadSpy.clear();
+    loadFailedSpy.clear();
     testFileName = QFINDTESTDATA("testdata/test.m3u");
     playlist.load(QUrl::fromLocalFile(testFileName));
+    QTRY_VERIFY(!loadSpy.isEmpty());
+    QVERIFY(loadFailedSpy.isEmpty());
     QCOMPARE(playlist.error(), QMediaPlaylist::NoError);
     QCOMPARE(playlist.mediaCount(), 7);
 
@@ -428,10 +449,79 @@ void tst_QMediaPlaylist::loadM3uFile()
     //ensure #2 suffix is not stripped from path
     testFileName = QFINDTESTDATA("testdata/testfile2#suffix");
     QCOMPARE(playlist.media(6).canonicalUrl(), QUrl::fromLocalFile(testFileName));
+
     // check ability to load from QNetworkRequest
+    loadSpy.clear();
+    loadFailedSpy.clear();
+    playlist.load(QNetworkRequest(QUrl::fromLocalFile(QFINDTESTDATA("testdata/test.m3u"))));
+    QTRY_VERIFY(!loadSpy.isEmpty());
+    QVERIFY(loadFailedSpy.isEmpty());
+}
+
+void tst_QMediaPlaylist::loadPLSFile()
+{
+    QMediaPlaylist playlist;
+
+    // Try to load playlist that does not exist in the testdata folder
     QSignalSpy loadSpy(&playlist, SIGNAL(loaded()));
     QSignalSpy loadFailedSpy(&playlist, SIGNAL(loadFailed()));
-    playlist.load(QNetworkRequest(QUrl::fromLocalFile(QFINDTESTDATA("testdata/test.m3u"))));
+    QString testFileName = QFINDTESTDATA("testdata");
+    playlist.load(QUrl::fromLocalFile(testFileName + "/missing_file.pls"));
+    QTRY_VERIFY(loadSpy.isEmpty());
+    QVERIFY(!loadFailedSpy.isEmpty());
+    QVERIFY(playlist.error() != QMediaPlaylist::NoError);
+
+    // Try to load bogus playlist
+    loadSpy.clear();
+    loadFailedSpy.clear();
+    testFileName = QFINDTESTDATA("testdata/trash.pls");
+    playlist.load(QUrl::fromLocalFile(testFileName));
+    QTRY_VERIFY(loadSpy.isEmpty());
+    QVERIFY(!loadFailedSpy.isEmpty());
+    QVERIFY(playlist.error() == QMediaPlaylist::FormatError);
+
+    // Try to load regular playlist
+    loadSpy.clear();
+    loadFailedSpy.clear();
+    testFileName = QFINDTESTDATA("testdata/test.pls");
+    playlist.load(QUrl::fromLocalFile(testFileName));
+    QTRY_VERIFY(!loadSpy.isEmpty());
+    QVERIFY(loadFailedSpy.isEmpty());
+    QCOMPARE(playlist.error(), QMediaPlaylist::NoError);
+    QCOMPARE(playlist.mediaCount(), 7);
+
+    QCOMPARE(playlist.media(0).canonicalUrl(), QUrl(QLatin1String("http://test.host/path")));
+    QCOMPARE(playlist.media(1).canonicalUrl(), QUrl(QLatin1String("http://test.host/path")));
+    testFileName = QFINDTESTDATA("testdata/testfile");
+    QEXPECT_FAIL("", "See QTBUG-40515", Continue);
+    QCOMPARE(playlist.media(2).canonicalUrl(),
+             QUrl::fromLocalFile(testFileName));
+    testFileName = QFINDTESTDATA("testdata");
+    QEXPECT_FAIL("", "See QTBUG-40515", Continue);
+    QCOMPARE(playlist.media(3).canonicalUrl(),
+             QUrl::fromLocalFile(testFileName + "/testdir/testfile"));
+    QEXPECT_FAIL("", "See QTBUG-40515", Continue);
+    QCOMPARE(playlist.media(4).canonicalUrl(), QUrl(QLatin1String("file:///testdir/testfile")));
+    QCOMPARE(playlist.media(5).canonicalUrl(), QUrl(QLatin1String("file://path/name#suffix")));
+    //ensure #2 suffix is not stripped from path
+    testFileName = QFINDTESTDATA("testdata/testfile2#suffix");
+    QEXPECT_FAIL("", "See QTBUG-40515", Continue);
+    QCOMPARE(playlist.media(6).canonicalUrl(), QUrl::fromLocalFile(testFileName));
+
+    // Try to load a totem-pl generated playlist
+    loadSpy.clear();
+    loadFailedSpy.clear();
+    testFileName = QFINDTESTDATA("testdata/totem-pl-example.pls");
+    playlist.load(QUrl::fromLocalFile(testFileName));
+    QEXPECT_FAIL("", "See QTBUG-40515", Continue);
+    QTRY_VERIFY(!loadSpy.isEmpty());
+    QEXPECT_FAIL("", "See QTBUG-40515", Continue);
+    QVERIFY(loadFailedSpy.isEmpty());
+
+    // check ability to load from QNetworkRequest
+    loadSpy.clear();
+    loadFailedSpy.clear();
+    playlist.load(QNetworkRequest(QUrl::fromLocalFile(QFINDTESTDATA("testdata/test.pls"))));
     QTRY_VERIFY(!loadSpy.isEmpty());
     QVERIFY(loadFailedSpy.isEmpty());
 }
-- 
GitLab