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
// Check the run list to see if this class is mentioned.
var functionsToRun = qtest_results.functionsToRun
if (functionsToRun.length > 0) {
let checkNames = false
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 list = []
if (name.length > 0) {
var prefix = name + "::"
for (var index in functionsToRun) {
if (functionsToRun[index].indexOf(prefix) == 0) {
list.push(functionsToRun[index])
for (var index in qtest_results.functionsToRun) {
let caseFuncName = qtest_results.functionsToRun[index]
if (caseFuncName.indexOf(name + "::") != 0)
continue
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) {
@ -1809,7 +1820,6 @@ Item {
qtest_results.testCaseName = ""
return
}
functionsToRun = list
}
// Run the initTestCase function.
@ -1834,17 +1844,15 @@ Item {
}
testList.sort()
}
var checkNames = (functionsToRun.length > 0)
for (var index in testList) {
var prop = testList[index]
if (checkNames && !(prop in testsToRun))
continue
var datafunc = prop + "_data"
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
if (!(datafunc in testCase))
@ -1854,12 +1862,22 @@ Item {
if (qtest_runInternal(datafunc)) {
var table = qtest_testCaseResult
var haveData = false
let checkTags = (checkNames && testsToRun[prop].length > 0)
qtest_results.initTestTable()
for (var index in table) {
haveData = true
var row = table[index]
if (!row.tag)
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
if (isBenchmark)
qtest_runBenchmarkFunction(prop, row)
@ -1884,6 +1902,9 @@ Item {
}
qtest_results.finishTestFunction()
qtest_results.skipped = false
if (checkNames && testsToRun[prop].length <= 0)
delete testsToRun[prop]
}
// Run the cleanupTestCase function.
@ -1892,8 +1913,21 @@ Item {
qtest_runInternal("cleanupTestCase")
// Complain about missing functions that we were supposed to run.
if (functionsToRun.length > 0)
qtest_results.fail("Could not find functions: " + functionsToRun, "", 0)
if (checkNames) {
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.
running = false

View File

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

View File

@ -188,7 +188,7 @@ void SelectionHighlight::showName(const QPointF &displayPoint)
{
m_displayPoint = displayPoint;
m_nameDisplayActive = true;
QTimer::singleShot(1500, this, SLOT(disableNameDisplay()));
QTimer::singleShot(1500, this, &SelectionHighlight::disableNameDisplay);
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
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
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++
types into the runtime.
\section1 Project settings for the plugin
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
the plugin target name and various other details:
@ -61,6 +63,8 @@ TARGET = qmlqtimeexampleplugin
SOURCES += qexampleqmlplugin.cpp
\endcode
\section1 Plugin definition in the qmldir
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
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)
{
forwardDebugMessages(last.timestamp());
eventReceiver->addEvent(last);
}
void QQmlProfilerClientPrivate::forwardDebugMessages(qint64 untilTimestamp)
{
while (!pendingDebugMessages.isEmpty()
&& pendingDebugMessages.front().timestamp() <= last.timestamp()) {
&& pendingDebugMessages.front().timestamp() <= untilTimestamp) {
eventReceiver->addEvent(pendingDebugMessages.dequeue());
}
eventReceiver->addEvent(last);
}
void QQmlProfilerClientPrivate::processCurrentEvent()
@ -142,7 +147,7 @@ void QQmlProfilerClientPrivate::processCurrentEvent()
int typeIndex = resolveType(currentEvent);
currentEvent.event.setTypeIndex(typeIndex);
if (rangesInProgress.isEmpty())
eventReceiver->addEvent(currentEvent.event);
forwardEvents(currentEvent.event);
else
pendingMessages.enqueue(currentEvent.event);
break;
@ -228,8 +233,7 @@ void QQmlProfilerClientPrivate::finalize()
currentEvent.event.setTimestamp(maximumTime);
processCurrentEvent();
}
while (!pendingDebugMessages.isEmpty())
eventReceiver->addEvent(pendingDebugMessages.dequeue());
forwardDebugMessages(std::numeric_limits<qint64>::max());
}
@ -345,12 +349,14 @@ void QQmlProfilerClient::messageReceived(const QByteArray &data)
&& d->currentEvent.type.detailType() == StartTrace) {
const QList<int> engineIds = d->currentEvent.event.numbers<QList<int>, qint32>();
d->trackedEngines.append(engineIds);
d->forwardDebugMessages(d->currentEvent.event.timestamp());
emit traceStarted(d->currentEvent.event.timestamp(), engineIds);
} else if (d->currentEvent.type.message() == Event
&& d->currentEvent.type.detailType() == EndTrace) {
const QList<int> engineIds = d->currentEvent.event.numbers<QList<int>, qint32>();
for (int engineId : engineIds)
d->trackedEngines.removeAll(engineId);
d->forwardDebugMessages(d->currentEvent.event.timestamp());
emit traceFinished(d->currentEvent.event.timestamp(), engineIds);
} else if (d->updateFeatures(d->currentEvent.type.feature())) {
d->processCurrentEvent();

View File

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

View File

@ -380,6 +380,16 @@ QStringList QuickTestResult::functionsToRun() const
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()

View File

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

View File

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

View File

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

View File

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

View File

@ -38,6 +38,10 @@ private slots:
void twoFilters();
void twoFiltersWithOneMatch();
void manyFilters();
void filterTestWithDefaultDataTags();
void filterTestWithDataTags();
void filterTestByDataTag();
void filterInvalidDataTag();
};
@ -131,6 +135,62 @@ void tst_TestFiltering::manyFilters()
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);
#include "tst_testfiltering.moc"