Merge remote-tracking branch 'origin/5.12' into dev

Change-Id: I34aa0c2eb178862b40e63b62c6daa056e5e204c6
This commit is contained in:
Qt Forward Merge Bot 2018-11-16 01:00:48 +01:00
commit 0ae32e678e
12 changed files with 152 additions and 32 deletions

View File

@ -1787,17 +1787,28 @@ Item {
running = true running = true
// Check the run list to see if this class is mentioned. // Check the run list to see if this class is mentioned.
var functionsToRun = qtest_results.functionsToRun let checkNames = false
if (functionsToRun.length > 0) { let testsToRun = {} // explicitly provided function names to run and their tags for data-driven tests
if (qtest_results.functionsToRun.length > 0) {
checkNames = true
var found = false var found = false
var list = []
if (name.length > 0) { if (name.length > 0) {
var prefix = name + "::" for (var index in qtest_results.functionsToRun) {
for (var index in functionsToRun) { let caseFuncName = qtest_results.functionsToRun[index]
if (functionsToRun[index].indexOf(prefix) == 0) { if (caseFuncName.indexOf(name + "::") != 0)
list.push(functionsToRun[index]) continue
found = true
} found = true
let funcName = caseFuncName.substring(name.length + 2)
if (!(funcName in testsToRun))
testsToRun[funcName] = []
let tagName = qtest_results.tagsToRun[index]
if (tagName.length > 0) // empty tags mean run all rows
testsToRun[funcName].push(tagName)
} }
} }
if (!found) { if (!found) {
@ -1809,7 +1820,6 @@ Item {
qtest_results.testCaseName = "" qtest_results.testCaseName = ""
return return
} }
functionsToRun = list
} }
// Run the initTestCase function. // Run the initTestCase function.
@ -1834,17 +1844,15 @@ Item {
} }
testList.sort() testList.sort()
} }
var checkNames = (functionsToRun.length > 0)
for (var index in testList) { for (var index in testList) {
var prop = testList[index] var prop = testList[index]
if (checkNames && !(prop in testsToRun))
continue
var datafunc = prop + "_data" var datafunc = prop + "_data"
var isBenchmark = (prop.indexOf("benchmark_") == 0) var isBenchmark = (prop.indexOf("benchmark_") == 0)
if (checkNames) {
var index = functionsToRun.indexOf(name + "::" + prop)
if (index < 0)
continue
functionsToRun.splice(index, 1)
}
qtest_results.functionName = prop qtest_results.functionName = prop
if (!(datafunc in testCase)) if (!(datafunc in testCase))
@ -1854,12 +1862,22 @@ Item {
if (qtest_runInternal(datafunc)) { if (qtest_runInternal(datafunc)) {
var table = qtest_testCaseResult var table = qtest_testCaseResult
var haveData = false var haveData = false
let checkTags = (checkNames && testsToRun[prop].length > 0)
qtest_results.initTestTable() qtest_results.initTestTable()
for (var index in table) { for (var index in table) {
haveData = true haveData = true
var row = table[index] var row = table[index]
if (!row.tag) if (!row.tag)
row.tag = "row " + index // Must have something row.tag = "row " + index // Must have something
if (checkTags) {
let tags = testsToRun[prop]
let tagIdx = tags.indexOf(row.tag)
if (tagIdx < 0)
continue
tags.splice(tagIdx, 1)
}
qtest_results.dataTag = row.tag qtest_results.dataTag = row.tag
if (isBenchmark) if (isBenchmark)
qtest_runBenchmarkFunction(prop, row) qtest_runBenchmarkFunction(prop, row)
@ -1884,6 +1902,9 @@ Item {
} }
qtest_results.finishTestFunction() qtest_results.finishTestFunction()
qtest_results.skipped = false qtest_results.skipped = false
if (checkNames && testsToRun[prop].length <= 0)
delete testsToRun[prop]
} }
// Run the cleanupTestCase function. // Run the cleanupTestCase function.
@ -1892,8 +1913,21 @@ Item {
qtest_runInternal("cleanupTestCase") qtest_runInternal("cleanupTestCase")
// Complain about missing functions that we were supposed to run. // Complain about missing functions that we were supposed to run.
if (functionsToRun.length > 0) if (checkNames) {
qtest_results.fail("Could not find functions: " + functionsToRun, "", 0) let missingTests = []
for (var func in testsToRun) {
let caseFuncName = name + '::' + func
let tags = testsToRun[func]
if (tags.length <= 0)
missingTests.push(caseFuncName)
else
for (var i in tags)
missingTests.push(caseFuncName + ':' + tags[i])
}
missingTests.sort()
if (missingTests.length > 0)
qtest_results.fail("Could not find test functions: " + missingTests, "", 0)
}
// Clean up and exit. // Clean up and exit.
running = false running = false

View File

@ -195,6 +195,7 @@ Module {
Property { name: "failCount"; type: "int"; isReadonly: true } Property { name: "failCount"; type: "int"; isReadonly: true }
Property { name: "skipCount"; type: "int"; isReadonly: true } Property { name: "skipCount"; type: "int"; isReadonly: true }
Property { name: "functionsToRun"; type: "QStringList"; isReadonly: true } Property { name: "functionsToRun"; type: "QStringList"; isReadonly: true }
Property { name: "tagsToRun"; type: "QStringList"; isReadonly: true }
Signal { name: "programNameChanged" } Signal { name: "programNameChanged" }
Method { name: "reset" } Method { name: "reset" }
Method { name: "startLogging" } Method { name: "startLogging" }

View File

@ -188,7 +188,7 @@ void SelectionHighlight::showName(const QPointF &displayPoint)
{ {
m_displayPoint = displayPoint; m_displayPoint = displayPoint;
m_nameDisplayActive = true; m_nameDisplayActive = true;
QTimer::singleShot(1500, this, SLOT(disableNameDisplay())); QTimer::singleShot(1500, this, &SelectionHighlight::disableNameDisplay);
update(); update();
} }

View File

@ -23,7 +23,7 @@ plugins. Library plugins should limit themselves to registering types, as
any manipulation of the engine's root context may cause conflicts or other any manipulation of the engine's root context may cause conflicts or other
issues in the library user's code. issues in the library user's code.
\section1 Plugin Example \section1 TimeExample QML extension plugin
Suppose there is a new \c TimeModel C++ class that should be made available Suppose there is a new \c TimeModel C++ class that should be made available
as a new QML type. It provides the current time through \c hour and \c minute as a new QML type. It provides the current time through \c hour and \c minute
@ -47,6 +47,8 @@ imported correctly by any QML components that use this plugin. The
\l{Defining QML Types from C++} article has more information about registering C++ \l{Defining QML Types from C++} article has more information about registering C++
types into the runtime. types into the runtime.
\section1 Project settings for the plugin
Additionally, the project file (\c .pro) defines the project as a plugin library, Additionally, the project file (\c .pro) defines the project as a plugin library,
specifies it should be built into the \c imports/TimeExample directory, and registers specifies it should be built into the \c imports/TimeExample directory, and registers
the plugin target name and various other details: the plugin target name and various other details:
@ -61,6 +63,8 @@ TARGET = qmlqtimeexampleplugin
SOURCES += qexampleqmlplugin.cpp SOURCES += qexampleqmlplugin.cpp
\endcode \endcode
\section1 Plugin definition in the qmldir
Finally, a \l{Module Definition qmldir Files}{qmldir file} is required Finally, a \l{Module Definition qmldir Files}{qmldir file} is required
in the \c imports/TimeExample directory to describe the plugin and the types that it in the \c imports/TimeExample directory to describe the plugin and the types that it
exports. The plugin includes a \c Clock.qml file along with the \c qmlqtimeexampleplugin exports. The plugin includes a \c Clock.qml file along with the \c qmlqtimeexampleplugin

View File

@ -94,12 +94,17 @@ int QQmlProfilerClientPrivate::resolveStackTop()
} }
void QQmlProfilerClientPrivate::forwardEvents(const QQmlProfilerEvent &last) void QQmlProfilerClientPrivate::forwardEvents(const QQmlProfilerEvent &last)
{
forwardDebugMessages(last.timestamp());
eventReceiver->addEvent(last);
}
void QQmlProfilerClientPrivate::forwardDebugMessages(qint64 untilTimestamp)
{ {
while (!pendingDebugMessages.isEmpty() while (!pendingDebugMessages.isEmpty()
&& pendingDebugMessages.front().timestamp() <= last.timestamp()) { && pendingDebugMessages.front().timestamp() <= untilTimestamp) {
eventReceiver->addEvent(pendingDebugMessages.dequeue()); eventReceiver->addEvent(pendingDebugMessages.dequeue());
} }
eventReceiver->addEvent(last);
} }
void QQmlProfilerClientPrivate::processCurrentEvent() void QQmlProfilerClientPrivate::processCurrentEvent()
@ -142,7 +147,7 @@ void QQmlProfilerClientPrivate::processCurrentEvent()
int typeIndex = resolveType(currentEvent); int typeIndex = resolveType(currentEvent);
currentEvent.event.setTypeIndex(typeIndex); currentEvent.event.setTypeIndex(typeIndex);
if (rangesInProgress.isEmpty()) if (rangesInProgress.isEmpty())
eventReceiver->addEvent(currentEvent.event); forwardEvents(currentEvent.event);
else else
pendingMessages.enqueue(currentEvent.event); pendingMessages.enqueue(currentEvent.event);
break; break;
@ -228,8 +233,7 @@ void QQmlProfilerClientPrivate::finalize()
currentEvent.event.setTimestamp(maximumTime); currentEvent.event.setTimestamp(maximumTime);
processCurrentEvent(); processCurrentEvent();
} }
while (!pendingDebugMessages.isEmpty()) forwardDebugMessages(std::numeric_limits<qint64>::max());
eventReceiver->addEvent(pendingDebugMessages.dequeue());
} }
@ -345,12 +349,14 @@ void QQmlProfilerClient::messageReceived(const QByteArray &data)
&& d->currentEvent.type.detailType() == StartTrace) { && d->currentEvent.type.detailType() == StartTrace) {
const QList<int> engineIds = d->currentEvent.event.numbers<QList<int>, qint32>(); const QList<int> engineIds = d->currentEvent.event.numbers<QList<int>, qint32>();
d->trackedEngines.append(engineIds); d->trackedEngines.append(engineIds);
d->forwardDebugMessages(d->currentEvent.event.timestamp());
emit traceStarted(d->currentEvent.event.timestamp(), engineIds); emit traceStarted(d->currentEvent.event.timestamp(), engineIds);
} else if (d->currentEvent.type.message() == Event } else if (d->currentEvent.type.message() == Event
&& d->currentEvent.type.detailType() == EndTrace) { && d->currentEvent.type.detailType() == EndTrace) {
const QList<int> engineIds = d->currentEvent.event.numbers<QList<int>, qint32>(); const QList<int> engineIds = d->currentEvent.event.numbers<QList<int>, qint32>();
for (int engineId : engineIds) for (int engineId : engineIds)
d->trackedEngines.removeAll(engineId); d->trackedEngines.removeAll(engineId);
d->forwardDebugMessages(d->currentEvent.event.timestamp());
emit traceFinished(d->currentEvent.event.timestamp(), engineIds); emit traceFinished(d->currentEvent.event.timestamp(), engineIds);
} else if (d->updateFeatures(d->currentEvent.type.feature())) { } else if (d->updateFeatures(d->currentEvent.type.feature())) {
d->processCurrentEvent(); d->processCurrentEvent();

View File

@ -86,6 +86,7 @@ public:
int resolveType(const QQmlProfilerTypedEvent &type); int resolveType(const QQmlProfilerTypedEvent &type);
int resolveStackTop(); int resolveStackTop();
void forwardEvents(const QQmlProfilerEvent &last); void forwardEvents(const QQmlProfilerEvent &last);
void forwardDebugMessages(qint64 untilTimestamp);
void processCurrentEvent(); void processCurrentEvent();
void finalize(); void finalize();

View File

@ -380,6 +380,16 @@ QStringList QuickTestResult::functionsToRun() const
return QTest::testFunctions; return QTest::testFunctions;
} }
/*!
\qmlproperty list<string> TestResult::tagsToRun
This property returns the list of test function's data tags to be run
*/
QStringList QuickTestResult::tagsToRun() const
{
return QTest::testTags;
}
/*! /*!
\qmlmethod TestResult::reset() \qmlmethod TestResult::reset()

View File

@ -76,6 +76,7 @@ class Q_QUICK_TEST_EXPORT QuickTestResult : public QObject
Q_PROPERTY(int failCount READ failCount) Q_PROPERTY(int failCount READ failCount)
Q_PROPERTY(int skipCount READ skipCount) Q_PROPERTY(int skipCount READ skipCount)
Q_PROPERTY(QStringList functionsToRun READ functionsToRun) Q_PROPERTY(QStringList functionsToRun READ functionsToRun)
Q_PROPERTY(QStringList tagsToRun READ tagsToRun)
public: public:
QuickTestResult(QObject *parent = nullptr); QuickTestResult(QObject *parent = nullptr);
~QuickTestResult() override; ~QuickTestResult() override;
@ -107,6 +108,7 @@ public:
int skipCount() const; int skipCount() const;
QStringList functionsToRun() const; QStringList functionsToRun() const;
QStringList tagsToRun() const;
public Q_SLOTS: public Q_SLOTS:
void reset(); void reset();

View File

@ -69,6 +69,9 @@ public:
int numLoadedEventTypes() const override; int numLoadedEventTypes() const override;
void addEventType(const QQmlProfilerEventType &type) override; void addEventType(const QQmlProfilerEventType &type) override;
void addEvent(const QQmlProfilerEvent &event) override; void addEvent(const QQmlProfilerEvent &event) override;
private:
qint64 lastTimestamp = -1;
}; };
void QQmlProfilerTestClient::startTrace(qint64 timestamp, const QList<int> &engineIds) void QQmlProfilerTestClient::startTrace(qint64 timestamp, const QList<int> &engineIds)
@ -102,6 +105,9 @@ void QQmlProfilerTestClient::addEvent(const QQmlProfilerEvent &event)
const QQmlProfilerEventType &type = types[typeIndex]; const QQmlProfilerEventType &type = types[typeIndex];
QVERIFY(event.timestamp() >= lastTimestamp);
lastTimestamp = event.timestamp();
switch (type.message()) { switch (type.message()) {
case Event: { case Event: {
switch (type.detailType()) { switch (type.detailType()) {
@ -373,7 +379,7 @@ bool tst_QQmlProfilerService::verify(tst_QQmlProfilerService::MessageListType ty
return false; return false;
} }
uint position = expectedPosition; int position = expectedPosition;
qint64 timestamp = target->at(expectedPosition).timestamp(); qint64 timestamp = target->at(expectedPosition).timestamp();
while (position > 0 && target->at(position - 1).timestamp() == timestamp) while (position > 0 && target->at(position - 1).timestamp() == timestamp)
--position; --position;
@ -448,7 +454,7 @@ bool tst_QQmlProfilerService::verify(tst_QQmlProfilerService::MessageListType ty
} }
return true; return true;
} while (target->at(++position).timestamp() == timestamp); } while (++position < target->length() && target->at(position).timestamp() == timestamp);
foreach (const QString &message, warnings) foreach (const QString &message, warnings)
qWarning() << message.toLocal8Bit().constData(); qWarning() << message.toLocal8Bit().constData();

View File

@ -1,2 +0,0 @@
[canvasFocus]
osx-10.11

View File

@ -6,5 +6,3 @@ osx
[populateTransitions] [populateTransitions]
opensuse-42.1 opensuse-42.1
#QTBUG-65964 #QTBUG-65964
[QTBUG_34576_velocityZero]
osx-10.11 ci

View File

@ -38,6 +38,10 @@ private slots:
void twoFilters(); void twoFilters();
void twoFiltersWithOneMatch(); void twoFiltersWithOneMatch();
void manyFilters(); void manyFilters();
void filterTestWithDefaultDataTags();
void filterTestWithDataTags();
void filterTestByDataTag();
void filterInvalidDataTag();
}; };
@ -131,6 +135,62 @@ void tst_TestFiltering::manyFilters()
QCOMPARE(process.exitCode(), 0); QCOMPARE(process.exitCode(), 0);
} }
void tst_TestFiltering::filterTestWithDefaultDataTags()
{
QProcess process;
process.start(testExe, { QLatin1String("Third::test_default_tags"), });
QVERIFY(process.waitForFinished());
const QString output = process.readAll();
QVERIFY(output.contains(QLatin1String("Totals: 5 passed")));
QVERIFY(output.contains(QLatin1String(" 2 skipped")));
QCOMPARE(process.exitStatus(), QProcess::NormalExit);
QCOMPARE(process.exitCode(), 0);
}
void tst_TestFiltering::filterTestWithDataTags()
{
QProcess process;
process.start(testExe, { QLatin1String("Third::test_tags"), });
QVERIFY(process.waitForFinished());
const QString output = process.readAll();
QVERIFY(output.contains(QLatin1String("Totals: 4 passed")));
QVERIFY(output.contains(QLatin1String(" 1 skipped")));
QCOMPARE(process.exitStatus(), QProcess::NormalExit);
QCOMPARE(process.exitCode(), 0);
}
void tst_TestFiltering::filterTestByDataTag()
{
QProcess process;
process.start(testExe, { QLatin1String("Third::test_default_tags:init_2"),
QLatin1String("Third::test_default_tags:skip_3"),
QLatin1String("Third::test_tags:baz"),
QLatin1String("Third::test_tags:bar"), });
QVERIFY(process.waitForFinished());
const QString output = process.readAll();
QVERIFY(output.contains(QLatin1String("Totals: 4 passed")));
QVERIFY(output.contains(QLatin1String(" 2 skipped")));
QCOMPARE(process.exitStatus(), QProcess::NormalExit);
QCOMPARE(process.exitCode(), 0);
}
void tst_TestFiltering::filterInvalidDataTag()
{
QProcess process;
process.start(testExe, { QLatin1String("Third::test_tags:invalid_tag") });
QVERIFY(process.waitForFinished());
QCOMPARE(process.exitStatus(), QProcess::NormalExit);
QCOMPARE(process.exitCode(), 1);
}
QTEST_MAIN(tst_TestFiltering); QTEST_MAIN(tst_TestFiltering);
#include "tst_testfiltering.moc" #include "tst_testfiltering.moc"