6cce5b82f2220a87fd214908aa4fd85bd9fcb8bb
[profile/ivi/qtdeclarative.git] / tests / auto / quick / examples / tst_examples.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
5 **
6 ** This file is part of the test suite of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** GNU Lesser General Public License Usage
10 ** This file may be used under the terms of the GNU Lesser General Public
11 ** License version 2.1 as published by the Free Software Foundation and
12 ** appearing in the file LICENSE.LGPL included in the packaging of this
13 ** file. Please review the following information to ensure the GNU Lesser
14 ** General Public License version 2.1 requirements will be met:
15 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
16 **
17 ** In addition, as a special exception, Nokia gives you certain additional
18 ** rights. These rights are described in the Nokia Qt LGPL Exception
19 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
20 **
21 ** GNU General Public License Usage
22 ** Alternatively, this file may be used under the terms of the GNU General
23 ** Public License version 3.0 as published by the Free Software Foundation
24 ** and appearing in the file LICENSE.GPL included in the packaging of this
25 ** file. Please review the following information to ensure the GNU General
26 ** Public License version 3.0 requirements will be met:
27 ** http://www.gnu.org/copyleft/gpl.html.
28 **
29 ** Other Usage
30 ** Alternatively, this file may be used in accordance with the terms and
31 ** conditions contained in a signed written agreement between you and Nokia.
32 **
33 **
34 **
35 **
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42 #include <qtest.h>
43 #include <QLibraryInfo>
44 #include <QDir>
45 #include <QProcess>
46 #include <QDebug>
47 #include <QtQuick/QQuickItem>
48 #include <QtQuick/QQuickView>
49 #include <QQmlComponent>
50 #include <QQmlEngine>
51 #include <QQmlError>
52
53 static QtMsgHandler testlibMsgHandler = 0;
54 void msgHandlerFilter(QtMsgType type, const char *msg)
55 {
56     if (type == QtCriticalMsg || type == QtFatalMsg)
57         (*testlibMsgHandler)(type, msg);
58 }
59
60 class tst_examples : public QObject
61 {
62     Q_OBJECT
63 public:
64     tst_examples();
65     ~tst_examples();
66
67 private slots:
68     void init();
69     void cleanup();
70
71     void sgexamples_data();
72     void sgexamples();
73     void sgsnippets_data();
74     void sgsnippets();
75
76     void namingConvention();
77 private:
78     QStringList excludedDirs;
79     QStringList excludedFiles;
80
81     void namingConvention(const QDir &);
82     QStringList findQmlFiles(const QDir &);
83
84     QQmlEngine engine;
85
86     QQuickCanvas *canvas;
87 };
88
89 tst_examples::tst_examples() : canvas(0)
90 {
91     // Add files to exclude here
92     excludedFiles << "examples/quick/canvas/tiger/tiger.qml"; // QTBUG-26528
93     excludedFiles << "snippets/qml/listmodel/listmodel.qml"; //Just a ListModel, no root QQuickItem
94
95     // Add directories you want excluded here (don't add examples/, because they install to examples/qtdeclarative/)
96     excludedDirs << "shared"; //Not an example
97     excludedDirs << "qtquick/text/fonts"; // QTBUG-21415
98     excludedDirs << "snippets/qml/path"; //No root QQuickItem
99     excludedDirs << "tutorials/gettingStartedQml"; //C++ example, but no cpp files in root dir
100
101     // These snippets are not expected to run on their own.
102     excludedDirs << "snippets/qml/visualdatamodel_rootindex";
103     excludedDirs << "snippets/qml/qtbinding";
104     excludedDirs << "snippets/qml/imports";
105
106 #ifdef QT_NO_WEBKIT
107     excludedDirs << "qtquick/modelviews/webview";
108     excludedDirs << "demos/webbrowser";
109     excludedDirs << "doc/src/snippets/qml/webview";
110 #endif
111
112 #ifdef QT_NO_XMLPATTERNS
113     excludedDirs << "demos/twitter";
114     excludedDirs << "demos/flickr";
115     excludedDirs << "demos/photoviewer";
116     excludedDirs << "snippets/qml/xmlrole.qml";
117 #endif
118
119     // QTBUG-24034 - don't run customparticle examples
120     excludedDirs << "demos/flickr";
121     excludedDirs << "examples/particles/customparticle";
122 }
123
124 tst_examples::~tst_examples()
125 {
126     delete canvas;
127 }
128
129 void tst_examples::init()
130 {
131     if (!qstrcmp(QTest::currentTestFunction(), "sgsnippets"))
132         testlibMsgHandler = qInstallMsgHandler(msgHandlerFilter);
133 }
134
135 void tst_examples::cleanup()
136 {
137     if (!qstrcmp(QTest::currentTestFunction(), "sgsnippets"))
138         qInstallMsgHandler(testlibMsgHandler);
139 }
140
141 /*
142 This tests that the examples follow the naming convention required
143 to have them tested by the examples() test.
144 */
145 void tst_examples::namingConvention(const QDir &d)
146 {
147     for (int ii = 0; ii < excludedDirs.count(); ++ii) {
148         QString s = excludedDirs.at(ii);
149         if (d.absolutePath().endsWith(s))
150             return;
151     }
152
153     QStringList files = d.entryList(QStringList() << QLatin1String("*.qml"),
154                                     QDir::Files);
155
156     bool seenQml = !files.isEmpty();
157     bool seenLowercase = false;
158
159     foreach (const QString &file, files) {
160         if (file.at(0).isLower())
161             seenLowercase = true;
162     }
163
164     if (!seenQml) {
165         QStringList dirs = d.entryList(QDir::Dirs | QDir::NoDotAndDotDot |
166                 QDir::NoSymLinks);
167         foreach (const QString &dir, dirs) {
168             QDir sub = d;
169             sub.cd(dir);
170             namingConvention(sub);
171         }
172     } else if(!seenLowercase) {
173         QFAIL(qPrintable(QString(
174             "Directory %1 violates naming convention; expected at least one qml file "
175             "starting with lower case, got: %2"
176         ).arg(d.absolutePath()).arg(files.join(","))));
177     }
178 }
179
180 void tst_examples::namingConvention()
181 {
182     QString examples = QLibraryInfo::location(QLibraryInfo::ExamplesPath);
183
184     namingConvention(QDir(examples));
185 }
186
187 QStringList tst_examples::findQmlFiles(const QDir &d)
188 {
189     for (int ii = 0; ii < excludedDirs.count(); ++ii) {
190         QString s = excludedDirs.at(ii);
191         if (d.absolutePath().endsWith(s))
192             return QStringList();
193     }
194
195     QStringList rv;
196
197     QStringList cppfiles = d.entryList(QStringList() << QLatin1String("*.cpp"), QDir::Files);
198     if (cppfiles.isEmpty()) {
199         QStringList files = d.entryList(QStringList() << QLatin1String("*.qml"),
200                                         QDir::Files);
201         foreach (const QString &file, files) {
202             if (file.at(0).isLower()) {
203                 bool superContinue = false;
204                 for (int ii = 0; ii < excludedFiles.count(); ++ii) {
205                     QString e = excludedFiles.at(ii);
206                     if (d.absoluteFilePath(file).endsWith(e)) {
207                         superContinue = true;
208                         break;
209                     }
210                 }
211                 if (superContinue)
212                     continue;
213                 rv << d.absoluteFilePath(file);
214             }
215         }
216     }
217
218
219     QStringList dirs = d.entryList(QDir::Dirs | QDir::NoDotAndDotDot |
220                                    QDir::NoSymLinks);
221     foreach (const QString &dir, dirs) {
222         QDir sub = d;
223         sub.cd(dir);
224         rv << findQmlFiles(sub);
225     }
226
227     return rv;
228 }
229
230 /*
231 This test runs all the examples in the QtQml UI source tree and ensures
232 that they start and exit cleanly.
233
234 Examples are any .qml files under the examples/ directory that start
235 with a lower case letter.
236 */
237 void tst_examples::sgexamples_data()
238 {
239     QTest::addColumn<QString>("file");
240
241     QString examples = QLatin1String(SRCDIR) + "/../../../../examples/";
242
243     QStringList files;
244     files << findQmlFiles(QDir(examples));
245
246     foreach (const QString &file, files)
247         QTest::newRow(qPrintable(file)) << file;
248 }
249
250 void tst_examples::sgexamples()
251 {
252     QFETCH(QString, file);
253
254     QQmlComponent component(&engine, QUrl::fromLocalFile(file));
255     if (component.status() == QQmlComponent::Error)
256         qWarning() << component.errors();
257     QCOMPARE(component.status(), QQmlComponent::Ready);
258
259     QScopedPointer<QObject> object(component.beginCreate(engine.rootContext()));
260     QQuickItem *root = qobject_cast<QQuickItem *>(object.data());
261     if (!root)
262         component.completeCreate();
263     QVERIFY(root);
264
265     if (!canvas) {
266         canvas = new QQuickCanvas();
267         canvas->resize(240, 320);
268         canvas->show();
269         QTest::qWaitForWindowShown(canvas);
270     }
271     root->setParentItem(canvas->rootItem());
272     component.completeCreate();
273
274     qApp->processEvents();
275 }
276
277 void tst_examples::sgsnippets_data()
278 {
279     QTest::addColumn<QString>("file");
280
281     QString snippets = QLatin1String(SRCDIR) + "/../../../../src/qml/doc/snippets/qml";
282     QStringList files;
283     files << findQmlFiles(QDir(snippets));
284     foreach (const QString &file, files)
285         QTest::newRow(qPrintable(file)) << file;
286
287     snippets = QLatin1String(SRCDIR) + "/../../../../src/quick/doc/snippets/qml";
288     files.clear();
289     files << findQmlFiles(QDir(snippets));
290     foreach (const QString &file, files)
291         QTest::newRow(qPrintable(file)) << file;
292 }
293
294 void tst_examples::sgsnippets()
295 {
296     QFETCH(QString, file);
297
298     QQmlComponent component(&engine, QUrl::fromLocalFile(file));
299     if (component.status() == QQmlComponent::Error)
300         qWarning() << component.errors();
301     QCOMPARE(component.status(), QQmlComponent::Ready);
302
303     QScopedPointer<QObject> object(component.beginCreate(engine.rootContext()));
304     QQuickItem *root = qobject_cast<QQuickItem *>(object.data());
305     if (!root)
306         component.completeCreate();
307     QVERIFY(root);
308
309     if (!canvas) {
310         canvas = new QQuickCanvas();
311         canvas->resize(240, 320);
312         canvas->show();
313         QTest::qWaitForWindowShown(canvas);
314     }
315     root->setParentItem(canvas->rootItem());
316     component.completeCreate();
317
318     qApp->processEvents();
319 }
320
321 QTEST_MAIN(tst_examples)
322
323 #include "tst_examples.moc"