From 524394e37c594807ed874f4926bf13af990358d1 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Fri, 5 Oct 2012 16:03:19 +0200 Subject: Make the examples test for QtDeclarative pass. - Fix check to indicate immediate errors, skip the loading state (using QTRY_VERIFY from shared/utils.h) and check for errors after loading again. - Exclude all broken examples. - Exclude shaders if import path is missing or OpenGL is not present. - Exclude Mac .app folders - Fix the DeclarativeViewer to check for the presence of the ImageMagick and ffmpeg executables only once, reducing test time. - Do not check for ImageMagick by running its command line tool 'convert' on Windows, since Windows has a tool of the same name that converts file systems (!). - Fix doc snippets to load correctly. Task-number: QTQAINFRA-428 Change-Id: Icc0a983bc42857b41ab1d9e93336f8265bfbec36 Reviewed-by: Janne Anttila Reviewed-by: Caroline Chao Reviewed-by: Christopher Adams --- .../declarative/models/views-models-delegates.qml | 2 + .../declarative/models/visual-model-and-view.qml | 2 + .../declarative/mousearea/mousearea-snippet.qml | 6 +- tests/auto/declarative/examples/examples.pro | 2 - tests/auto/declarative/examples/tst_examples.cpp | 86 ++++++++++++++-------- tools/qml/qmlruntime.cpp | 49 ++++++++---- tools/qml/qmlruntime.h | 3 +- 7 files changed, 99 insertions(+), 51 deletions(-) diff --git a/doc/src/snippets/declarative/models/views-models-delegates.qml b/doc/src/snippets/declarative/models/views-models-delegates.qml index 6577581..4f4c0c0 100644 --- a/doc/src/snippets/declarative/models/views-models-delegates.qml +++ b/doc/src/snippets/declarative/models/views-models-delegates.qml @@ -38,6 +38,8 @@ ** ****************************************************************************/ +import QtQuick 1.0 + //! [rectangle] Rectangle { width: 200; height: 200 diff --git a/doc/src/snippets/declarative/models/visual-model-and-view.qml b/doc/src/snippets/declarative/models/visual-model-and-view.qml index b53081e..d78bbea 100644 --- a/doc/src/snippets/declarative/models/visual-model-and-view.qml +++ b/doc/src/snippets/declarative/models/visual-model-and-view.qml @@ -38,6 +38,8 @@ ** ****************************************************************************/ +import QtQuick 1.0 + Rectangle { width: 200; height: 200 diff --git a/doc/src/snippets/declarative/mousearea/mousearea-snippet.qml b/doc/src/snippets/declarative/mousearea/mousearea-snippet.qml index 2f70497..26a414d 100644 --- a/doc/src/snippets/declarative/mousearea/mousearea-snippet.qml +++ b/doc/src/snippets/declarative/mousearea/mousearea-snippet.qml @@ -50,7 +50,7 @@ Rectangle { Column { //! [anchor fill] Rectangle { - id: button + id: button1 width: 100; height: 100 MouseArea { @@ -65,7 +65,7 @@ Rectangle { //! [anchor fill] Rectangle { - id: button + id: button2 width: 100; height: 100 //! [enable handlers] @@ -79,7 +79,7 @@ Rectangle { } Rectangle { - id: button + id: button3 width: 100; height: 100 //! [mouse handlers] diff --git a/tests/auto/declarative/examples/examples.pro b/tests/auto/declarative/examples/examples.pro index 1f99b9e..fd4be3d 100644 --- a/tests/auto/declarative/examples/examples.pro +++ b/tests/auto/declarative/examples/examples.pro @@ -18,5 +18,3 @@ wince*|symbian: { } CONFIG += parallel_test - -CONFIG+=insignificant_test # QTQAINFRA-428 diff --git a/tests/auto/declarative/examples/tst_examples.cpp b/tests/auto/declarative/examples/tst_examples.cpp index 32a8af7..97450e3 100644 --- a/tests/auto/declarative/examples/tst_examples.cpp +++ b/tests/auto/declarative/examples/tst_examples.cpp @@ -40,9 +40,11 @@ ****************************************************************************/ #include #include +#include #include #include #include +#include "../../../shared/util.h" #include "qmlruntime.h" #include #include @@ -64,7 +66,6 @@ private slots: void namingConvention(); private: - QString qmlruntime; QStringList excludedDirs; void namingConvention(const QDir &); @@ -73,32 +74,42 @@ private: tst_examples::tst_examples() { - QString binaries = QLibraryInfo::location(QLibraryInfo::BinariesPath); - -#if defined(Q_WS_MAC) - qmlruntime = QDir(binaries).absoluteFilePath("qml.app/Contents/MacOS/qml"); -#elif defined(Q_WS_WIN) - qmlruntime = QDir(binaries).absoluteFilePath("qml.exe"); -#else - qmlruntime = QDir(binaries).absoluteFilePath("qml"); -#endif - - // Add directories you want excluded here - excludedDirs << "doc/src/snippets/declarative/visualdatamodel_rootindex"; - excludedDirs << "doc/src/snippets/declarative/qtbinding"; + excludedDirs << "doc/src/snippets/declarative/visualdatamodel_rootindex" + << "doc/src/snippets/declarative/qtbinding"; + // Known to violate naming conventions, QTQAINFRA-428 + excludedDirs << "demos/mobile/qtbubblelevel/qml" + << "demos/mobile/quickhit"; + // Layouts do not install, QTQAINFRA-428 + excludedDirs << "examples/declarative/cppextensions/qgraphicslayouts/qgraphicsgridlayout/qml/qgraphicsgridlayout" + << "examples/declarative/cppextensions/qgraphicslayouts/qgraphicslinearlayout/qml/qgraphicslinearlayout"; + // Various QML errors, QTQAINFRA-428 + excludedDirs << "doc/src/snippets/declarative/imports"; + + // Check shaders which are not present for configurations without OpenGL or when not built. + const QString shaderExample = QLatin1String("examples/declarative/shadereffects"); +#ifdef QT_NO_OPENGL + excludedDirs << shaderExample; +#else + const QString importPaths = QLibraryInfo::location(QLibraryInfo::ImportsPath); + if (!QFileInfo(importPaths + QLatin1String("/Qt/labs/shaders")).isDir()) + excludedDirs << shaderExample; +#endif // QT_NO_OPENGL #ifdef QT_NO_WEBKIT - excludedDirs << "examples/declarative/modelviews/webview"; - excludedDirs << "demos/declarative/webbrowser"; -#endif + excludedDirs << "examples/declarative/modelviews/webview" + << "demos/declarative/webbrowser" + << "doc/src/snippets/declarative/webview"; +#endif // QT_NO_WEBKIT #ifdef QT_NO_XMLPATTERNS - excludedDirs << "examples/declarative/xml/xmldata"; - excludedDirs << "demos/declarative/twitter"; - excludedDirs << "demos/declarative/flickr"; - excludedDirs << "demos/declarative/photoviewer"; -#endif + excludedDirs << "examples/declarative/xml/xmldata" + << "demos/declarative/twitter" + << "demos/declarative/flickr" + << "demos/declarative/photoviewer" + << "demos/declarative/rssnews/qml/rssnews" + << "doc/src/snippets/declarative"; +#endif // QT_NO_XMLPATTERNS } /* @@ -148,11 +159,14 @@ void tst_examples::namingConvention() QStringList tst_examples::findQmlFiles(const QDir &d) { - for (int ii = 0; ii < excludedDirs.count(); ++ii) { - QString s = excludedDirs.at(ii); - if (d.absolutePath().endsWith(s)) + const QString absolutePath = d.absolutePath(); +#ifdef Q_OS_MAC // Mac: Do not recurse into bundle folders of built examples. + if (absolutePath.endsWith(QLatin1String(".app"))) + return QStringList(); +#endif + foreach (const QString &excludedDir, excludedDirs) + if (absolutePath.endsWith(excludedDir)) return QStringList(); - } QStringList rv; @@ -206,23 +220,33 @@ static void silentErrorsMsgHandler(QtMsgType, const char *) { } +static inline QByteArray msgViewerErrors(const QList &l) +{ + QString errors; + QDebug(&errors) << '\n' << l; + return errors.toLocal8Bit(); +} + void tst_examples::examples() { QFETCH(QString, file); + QVERIFY2(QFileInfo(file).exists(), + qPrintable(QString::fromLatin1("'%1' does not exist.").arg(QDir::toNativeSeparators(file)))); QDeclarativeViewer viewer; QtMsgHandler old = qInstallMsgHandler(silentErrorsMsgHandler); QVERIFY(viewer.open(file)); qInstallMsgHandler(old); + QVERIFY2(viewer.view()->status() != QDeclarativeView::Error, + msgViewerErrors(viewer.view()->errors()).constData()); + QTRY_VERIFY(viewer.view()->status() != QDeclarativeView::Loading); + QVERIFY2(viewer.view()->status() == QDeclarativeView::Ready, + msgViewerErrors(viewer.view()->errors()).constData()); - if (viewer.view()->status() == QDeclarativeView::Error) - qWarning() << viewer.view()->errors(); - - QCOMPARE(viewer.view()->status(), QDeclarativeView::Ready); viewer.show(); - QTest::qWaitForWindowShown(&viewer); + QVERIFY(QTest::qWaitForWindowShown(&viewer)); } QTEST_MAIN(tst_examples) diff --git a/tools/qml/qmlruntime.cpp b/tools/qml/qmlruntime.cpp index 397e2ae..b0aa7b4 100644 --- a/tools/qml/qmlruntime.cpp +++ b/tools/qml/qmlruntime.cpp @@ -600,10 +600,30 @@ QString QDeclarativeViewer::getVideoFileName() return QFileDialog::getSaveFileName(this, title, QString(), types.join(QLatin1String(";; "))); } +// Check for presence of ImageMagick by launching its command line +// convert tool except on Windows, where convert.exe is a file system converter. +static bool senseImageMagick() +{ +#ifdef Q_OS_WIN + return false; +#else + static int imageMagickFound = -1; + if (imageMagickFound == -1) { + QProcess proc; + proc.start(QLatin1String("convert"), QStringList(QLatin1String("-h"))); + imageMagickFound = proc.waitForStarted() && proc.waitForFinished(2000) + && proc.readAllStandardOutput().contains("ImageMagick") ? + 1 : 0; + } + return imageMagickFound != 0; +#endif +} + QDeclarativeViewer::QDeclarativeViewer(QWidget *parent, Qt::WindowFlags flags) : QMainWindow(parent, flags) , loggerWindow(new LoggerWidget(this)) , frame_stream(0) + , convertAvailable(senseImageMagick()) , rotateAction(0) , orientation(0) , showWarningsWindow(0) @@ -628,7 +648,6 @@ QDeclarativeViewer::QDeclarativeViewer(QWidget *parent, Qt::WindowFlags flags) recdlg = new RecordingDialog(this); connect(recdlg->pickfile, SIGNAL(clicked()), this, SLOT(pickRecordingFile())); senseFfmpeg(); - senseImageMagick(); if (!ffmpegAvailable) recdlg->showffmpegOptions(false); if (!ffmpegAvailable && !convertAvailable) @@ -1221,23 +1240,27 @@ bool QDeclarativeViewer::event(QEvent *event) return QWidget::event(event); } -void QDeclarativeViewer::senseImageMagick() +// Detect ffmpeg, return its help string. +static inline QString detectFfmpeg() { - QProcess proc; - proc.start(QLatin1String("convert"), QStringList() << QLatin1String("-h")); - proc.waitForFinished(2000); - QString help = QString::fromAscii(proc.readAllStandardOutput()); - convertAvailable = help.contains(QLatin1String("ImageMagick")); + static QString ffmpegHelp; + if (ffmpegHelp.isNull()) { + QProcess proc; + proc.start(QLatin1String("ffmpeg"), QStringList(QLatin1String("-h"))); + if (proc.waitForStarted() && proc.waitForFinished(2000)) { + ffmpegHelp = QString::fromLocal8Bit(proc.readAllStandardOutput()); + } else { + ffmpegHelp = QLatin1String(""); + } + } + return ffmpegHelp; } void QDeclarativeViewer::senseFfmpeg() { - QProcess proc; - proc.start(QLatin1String("ffmpeg"), QStringList() << QLatin1String("-h")); - proc.waitForFinished(2000); - QString ffmpegHelp = QString::fromAscii(proc.readAllStandardOutput()); + const QString ffmpegHelp = detectFfmpeg(); ffmpegAvailable = ffmpegHelp.contains(QLatin1String("-s ")); - ffmpegHelp = tr("Video recording uses ffmpeg:") + QLatin1String("\n\n") + ffmpegHelp; + const QString text = tr("Video recording uses ffmpeg:") + QLatin1String("\n\n") + ffmpegHelp; QDialog *d = new QDialog(recdlg); QVBoxLayout *l = new QVBoxLayout(d); @@ -1245,7 +1268,7 @@ void QDeclarativeViewer::senseFfmpeg() QFont f = b->font(); f.setFamily(QLatin1String("courier")); b->setFont(f); - b->setText(ffmpegHelp); + b->setText(text); l->addWidget(b); d->setLayout(l); ffmpegHelpWindow = d; diff --git a/tools/qml/qmlruntime.h b/tools/qml/qmlruntime.h index 2fd5f96..76674d0 100644 --- a/tools/qml/qmlruntime.h +++ b/tools/qml/qmlruntime.h @@ -174,11 +174,10 @@ private: QAction *recordAction; RecordingDialog *recdlg; - void senseImageMagick(); void senseFfmpeg(); QWidget *ffmpegHelpWindow; bool ffmpegAvailable; - bool convertAvailable; + const bool convertAvailable; QAction *rotateAction; QActionGroup *orientation; -- cgit v0.12