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