d482e810090942fb7c1dd742491c5499bd251b00
[profile/ivi/qtdeclarative.git] / tests / auto / qml / debugger / qv8profilerservice / tst_qv8profilerservice.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
45 #include "debugutil_p.h"
46 #include "qqmldebugclient.h"
47 #include "../../../shared/util.h"
48
49 #define PORT 13774
50 #define STR_PORT "13774"
51
52 struct QV8ProfilerData
53 {
54     int messageType;
55     QString filename;
56     QString functionname;
57     int lineNumber;
58     double totalTime;
59     double selfTime;
60     int treeLevel;
61
62     QByteArray toByteArray() const;
63 };
64
65 class QV8ProfilerClient : public QQmlDebugClient
66 {
67     Q_OBJECT
68
69 public:
70     enum MessageType {
71         V8Entry,
72         V8Complete,
73         V8SnapshotChunk,
74         V8SnapshotComplete,
75         V8Started,
76
77         V8MaximumMessage
78     };
79
80     enum ServiceState { NotRunning, Running } serviceState;
81
82     QV8ProfilerClient(QQmlDebugConnection *connection)
83         : QQmlDebugClient(QLatin1String("V8Profiler"), connection)
84         , serviceState(NotRunning)
85     {
86     }
87
88     void startProfiling(const QString &name) {
89         QByteArray message;
90         QDataStream stream(&message, QIODevice::WriteOnly);
91         stream << QByteArray("V8PROFILER") << QByteArray("start") << name;
92         sendMessage(message);
93     }
94
95     void stopProfiling(const QString &name) {
96         QByteArray message;
97         QDataStream stream(&message, QIODevice::WriteOnly);
98         stream << QByteArray("V8PROFILER") << QByteArray("stop") << name;
99         sendMessage(message);
100     }
101
102     void takeSnapshot() {
103         QByteArray message;
104         QDataStream stream(&message, QIODevice::WriteOnly);
105         stream << QByteArray("V8SNAPSHOT") << QByteArray("full");
106         sendMessage(message);
107     }
108
109     void deleteSnapshots() {
110         QByteArray message;
111         QDataStream stream(&message, QIODevice::WriteOnly);
112         stream << QByteArray("V8SNAPSHOT") << QByteArray("delete");
113         sendMessage(message);
114     }
115
116     QList<QV8ProfilerData> traceMessages;
117     QList<QByteArray> snapshotMessages;
118
119 signals:
120     void started();
121     void complete();
122     void snapshot();
123
124 protected:
125     void messageReceived(const QByteArray &message);
126 };
127
128 class tst_QV8ProfilerService : public QQmlDataTest
129 {
130     Q_OBJECT
131
132 public:
133     tst_QV8ProfilerService()
134         : m_process(0)
135         , m_connection(0)
136         , m_client(0)
137     {
138     }
139
140 private:
141     QQmlDebugProcess *m_process;
142     QQmlDebugConnection *m_connection;
143     QV8ProfilerClient *m_client;
144
145     bool connect(bool block, const QString &testFile, QString *error);
146
147 private slots:
148     void cleanup();
149
150     void blockingConnectWithTraceEnabled();
151     void blockingConnectWithTraceDisabled();
152     void nonBlockingConnect();
153     void snapshot();
154     void profileOnExit();
155     void console();
156 };
157
158 void QV8ProfilerClient::messageReceived(const QByteArray &message)
159 {
160     QByteArray msg = message;
161     QDataStream stream(&msg, QIODevice::ReadOnly);
162
163     int messageType;
164     stream >> messageType;
165
166     QVERIFY(messageType >= 0);
167     QVERIFY(messageType < QV8ProfilerClient::V8MaximumMessage);
168
169     switch (messageType) {
170     case QV8ProfilerClient::V8Entry: {
171         QCOMPARE(serviceState, Running);
172         QV8ProfilerData entry;
173         stream >> entry.filename >> entry.functionname >> entry.lineNumber >> entry.totalTime >> entry.selfTime >> entry.treeLevel;
174         traceMessages.append(entry);
175         break;
176     }
177     case QV8ProfilerClient::V8Complete:
178         QCOMPARE(serviceState, Running);
179         serviceState = NotRunning;
180         emit complete();
181         break;
182     case QV8ProfilerClient::V8SnapshotChunk: {
183         QByteArray json;
184         stream >> json;
185         snapshotMessages.append(json);
186         break;
187     }
188     case QV8ProfilerClient::V8SnapshotComplete:
189         emit snapshot();
190         break;
191     case QV8ProfilerClient::V8Started:
192         QCOMPARE(serviceState, NotRunning);
193         serviceState = Running;
194         emit started();
195         break;
196     default:
197         QString failMessage = QString("Unknown message type: %1").arg(messageType);
198         QFAIL(qPrintable(failMessage));
199     }
200
201     QVERIFY(stream.atEnd());
202 }
203
204 bool tst_QV8ProfilerService::connect(bool block, const QString &testFile,
205                                      QString *error)
206 {
207     const QString executable = QLibraryInfo::location(QLibraryInfo::BinariesPath) + "/qmlscene";
208     QStringList arguments;
209
210     if (block)
211         arguments << QString("-qmljsdebugger=port:"STR_PORT",block");
212     else
213         arguments << QString("-qmljsdebugger=port:"STR_PORT);
214
215     arguments << QQmlDataTest::instance()->testFile(testFile);
216
217     m_connection = new QQmlDebugConnection();
218     m_client = new QV8ProfilerClient(m_connection);
219
220     m_process = new QQmlDebugProcess(executable);
221     m_process->start(QStringList() << arguments);
222     if (!m_process->waitForSessionStart()) {
223         *error = QLatin1String("Could not launch app ") + executable;
224         return false;
225     }
226
227     m_connection->connectToHost(QLatin1String("127.0.0.1"), PORT);
228     if (!m_connection->waitForConnected()) {
229         *error = QLatin1String("Could not connect to debugger port.");
230         return false;
231     }
232     return true;
233 }
234
235 void tst_QV8ProfilerService::cleanup()
236 {
237     if (QTest::currentTestFailed())
238         qDebug() << "Application Output:" << m_process->output();
239
240     delete m_client;
241     delete m_process;
242     delete m_connection;
243 }
244
245 void tst_QV8ProfilerService::blockingConnectWithTraceEnabled()
246 {
247     QString error;
248     if (!connect(true, "test.qml", &error))
249         QFAIL(qPrintable(error));
250
251     QTRY_COMPARE(m_client->state(), QQmlDebugClient::Enabled);
252
253     m_client->startProfiling("");
254     m_client->stopProfiling("");
255     QVERIFY2(QQmlDebugTest::waitForSignal(m_client, SIGNAL(complete())),
256              "No trace received in time.");
257 }
258
259 void tst_QV8ProfilerService::blockingConnectWithTraceDisabled()
260 {
261     QString error;
262     if (!connect(true, "test.qml", &error))
263         QFAIL(qPrintable(error));
264
265     QTRY_COMPARE(m_client->state(), QQmlDebugClient::Enabled);
266
267     m_client->stopProfiling("");
268     if (QQmlDebugTest::waitForSignal(m_client, SIGNAL(complete()), 1000)) {
269         QString failMsg
270                 = QString("Unexpected trace received! App output: %1\n\n").arg(m_process->output());
271         QFAIL(qPrintable(failMsg));
272     }
273     m_client->startProfiling("");
274     m_client->stopProfiling("");
275     QVERIFY2(QQmlDebugTest::waitForSignal(m_client, SIGNAL(complete())),
276              "No trace received in time.");
277 }
278
279 void tst_QV8ProfilerService::nonBlockingConnect()
280 {
281     QString error;
282     if (!connect(false, "test.qml", &error))
283         QFAIL(qPrintable(error));
284
285     QTRY_COMPARE(m_client->state(), QQmlDebugClient::Enabled);
286
287     m_client->startProfiling("");
288     m_client->stopProfiling("");
289     QVERIFY2(QQmlDebugTest::waitForSignal(m_client, SIGNAL(complete())),
290              "No trace received in time.");
291 }
292
293 void tst_QV8ProfilerService::snapshot()
294 {
295     QString error;
296     if (!connect(false, "test.qml", &error))
297         QFAIL(qPrintable(error));
298
299     QTRY_COMPARE(m_client->state(), QQmlDebugClient::Enabled);
300
301     m_client->takeSnapshot();
302     QVERIFY2(QQmlDebugTest::waitForSignal(m_client, SIGNAL(snapshot())),
303              "No trace received in time.");
304 }
305
306 void tst_QV8ProfilerService::profileOnExit()
307 {
308     QString error;
309     if (!connect(true, "exit.qml", &error))
310         QFAIL(qPrintable(error));
311
312     QTRY_COMPARE(m_client->state(), QQmlDebugClient::Enabled);
313
314     m_client->startProfiling("");
315     QVERIFY2(QQmlDebugTest::waitForSignal(m_client, SIGNAL(complete())),
316              "No trace received in time.");
317 }
318
319 void tst_QV8ProfilerService::console()
320 {
321     QString error;
322     if (!connect(true, "console.qml", &error))
323         QFAIL(qPrintable(error));
324
325     QTRY_COMPARE(m_client->state(), QQmlDebugClient::Enabled);
326
327     m_client->stopProfiling("");
328
329     QVERIFY2(QQmlDebugTest::waitForSignal(m_client, SIGNAL(complete())),
330              "No trace received in time.");
331     QVERIFY(!m_client->traceMessages.isEmpty());
332 }
333
334 QTEST_MAIN(tst_QV8ProfilerService)
335
336 #include "tst_qv8profilerservice.moc"