From 916883e70f121ded7fedf54c0d8732f828542895 Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Mon, 7 May 2018 13:26:05 +0200 Subject: [PATCH] Tracing: Move event storage out of trace manager This is a step toward making the trace manager non-virtual. It should just juggle the storages for types and events, and manage the threads to access them. It doesn't need to know what exactly it stores. Change-Id: I45093c60d8ae921e68aeb09bd48d24d5877ce306 Reviewed-by: Christian Kandeler --- src/libs/tracing/timelinetracemanager.cpp | 35 +++- src/libs/tracing/timelinetracemanager.h | 18 ++- src/libs/tracing/tracestashfile.h | 4 +- src/plugins/qmlprofiler/flamegraphmodel.cpp | 6 +- .../qmlprofiler/qmlprofilermodelmanager.cpp | 151 ++++++++++++------ .../qmlprofiler/qmlprofilermodelmanager.h | 5 +- .../qmlprofilerstatisticsmodel.cpp | 6 +- .../qmlprofiler/qmlprofilertraceclient.cpp | 16 +- .../qmlprofiler/qmlprofilertracefile.cpp | 21 +-- .../tests/debugmessagesmodel_test.cpp | 5 +- .../tests/flamegraphmodel_test.cpp | 16 +- .../tests/inputeventsmodel_test.cpp | 4 +- .../tests/memoryusagemodel_test.cpp | 16 +- .../tests/pixmapcachemodel_test.cpp | 32 ++-- .../tests/qmlprofileranimationsmodel_test.cpp | 2 +- .../tests/qmlprofilertool_test.cpp | 4 +- .../tests/qmlprofilertraceclient_test.cpp | 13 +- 17 files changed, 218 insertions(+), 136 deletions(-) diff --git a/src/libs/tracing/timelinetracemanager.cpp b/src/libs/tracing/timelinetracemanager.cpp index 89c3737d04b..73c686f7ca7 100644 --- a/src/libs/tracing/timelinetracemanager.cpp +++ b/src/libs/tracing/timelinetracemanager.cpp @@ -41,10 +41,16 @@ TraceEventTypeStorage::~TraceEventTypeStorage() { } +TraceEventStorage::~TraceEventStorage() +{ +} + class TimelineTraceManager::TimelineTraceManagerPrivate { public: std::unique_ptr typeStorage; + std::unique_ptr eventStorage; + TimelineNotesModel *notesModel = nullptr; int numEvents = 0; @@ -66,10 +72,12 @@ public: void updateTraceTime(qint64 time); }; -TimelineTraceManager::TimelineTraceManager(std::unique_ptr &&typeStorage, +TimelineTraceManager::TimelineTraceManager(std::unique_ptr &&eventStorage, + std::unique_ptr &&typeStorage, QObject *parent) : QObject(parent), d(new TimelineTraceManagerPrivate) { + d->eventStorage = std::move(eventStorage); d->typeStorage = std::move(typeStorage); } @@ -85,7 +93,7 @@ TimelineNotesModel *TimelineTraceManager::notesModel() const bool TimelineTraceManager::isEmpty() const { - return d->numEvents == 0; + return d->eventStorage->size() == 0; } int TimelineTraceManager::numEvents() const @@ -98,14 +106,20 @@ int TimelineTraceManager::numEventTypes() const return d->typeStorage->size(); } +const TraceEventStorage *TimelineTraceManager::eventStorage() const +{ + return d->eventStorage.get(); +} + const TraceEventTypeStorage *TimelineTraceManager::typeStorage() const { return d->typeStorage.get(); } -void TimelineTraceManager::addEvent(const TraceEvent &event) +void TimelineTraceManager::appendEvent(TraceEvent &&event) { d->dispatch(event, d->typeStorage->get(event.typeIndex())); + d->eventStorage->append(std::move(event)); } const TraceEventType &TimelineTraceManager::eventType(int typeId) const @@ -205,6 +219,8 @@ void TimelineTraceManager::initialize() void TimelineTraceManager::finalize() { + d->eventStorage->finalize(); + // Load notes after the timeline models have been initialized ... // which happens on stateChanged(Done). @@ -237,7 +253,8 @@ QFuture TimelineTraceManager::save(const QString &filename) file->close(); file->remove(); delete file; - emit error(message); + if (!message.isEmpty()) + emit error(message); }, Qt::QueuedConnection); connect(writer, &TimelineTraceFile::success, this, [file]() { @@ -292,7 +309,8 @@ QFuture TimelineTraceManager::load(const QString &filename) connect(reader, &TimelineTraceFile::error, this, [this, reader](const QString &message) { clearAll(); delete reader; - emit error(message); + if (!message.isEmpty()) + emit error(message); }, Qt::QueuedConnection); connect(reader, &TimelineTraceFile::canceled, this, [this, reader]() { @@ -369,6 +387,7 @@ void TimelineTraceManager::clearEventStorage() d->notesModel->clear(); setVisibleFeatures(0); setRecordedFeatures(0); + d->eventStorage->clear(); } void TimelineTraceManager::clearTypeStorage() @@ -406,8 +425,10 @@ void TimelineTraceManager::restrictByFilter(TraceEventFilter filter) d->notesModel->restore(); finalize(); }, [this](const QString &message) { - emit error(tr("Could not re-read events from temporary trace file: %1\n" - "The trace data is lost.").arg(message)); + if (!message.isEmpty()) { + emit error(tr("Could not re-read events from temporary trace file: %1\n" + "The trace data is lost.").arg(message)); + } clearAll(); }, future); } diff --git a/src/libs/tracing/timelinetracemanager.h b/src/libs/tracing/timelinetracemanager.h index 07bcae705ff..fb8cd561d88 100644 --- a/src/libs/tracing/timelinetracemanager.h +++ b/src/libs/tracing/timelinetracemanager.h @@ -49,6 +49,17 @@ public: virtual void clear() = 0; }; +class TRACING_EXPORT TraceEventStorage +{ +public: + virtual ~TraceEventStorage(); + virtual int append(TraceEvent &&event) = 0; + virtual int size() const = 0; + virtual void clear() = 0; + virtual void finalize() = 0; + virtual bool replay(const std::function &receiver) const = 0; +}; + class TimelineTraceFile; class TRACING_EXPORT TimelineTraceManager : public QObject { @@ -61,7 +72,8 @@ public: typedef std::function Clearer; typedef std::function ErrorHandler; - explicit TimelineTraceManager(std::unique_ptr &&typeStorage, + explicit TimelineTraceManager(std::unique_ptr &&eventStorage, + std::unique_ptr &&typeStorage, QObject *parent = nullptr); ~TimelineTraceManager() override; @@ -78,6 +90,7 @@ public: int numEvents() const; int numEventTypes() const; + const TraceEventStorage *eventStorage() const; const TraceEventTypeStorage *typeStorage() const; void registerFeatures(quint64 features, TraceEventLoader eventLoader, @@ -117,8 +130,7 @@ protected: void restrictByFilter(TraceEventFilter filter); - void addEvent(const TraceEvent &event); - + void appendEvent(TraceEvent &&event); const TraceEventType &eventType(int typeId) const; void setEventType(int typeId, TraceEventType &&type); int appendEventType(TraceEventType &&type); diff --git a/src/libs/tracing/tracestashfile.h b/src/libs/tracing/tracestashfile.h index d860ece9221..aa811b6befd 100644 --- a/src/libs/tracing/tracestashfile.h +++ b/src/libs/tracing/tracestashfile.h @@ -67,12 +67,12 @@ public: return ReplayOpenFailed; QDataStream readStream(&readFile); - Event event; while (!readStream.atEnd()) { + Event event; readStream >> event; if (readStream.status() == QDataStream::ReadPastEnd) return ReplayReadPastEnd; - if (!loader(event)) + if (!loader(std::move(event))) return ReplayLoadFailed; } diff --git a/src/plugins/qmlprofiler/flamegraphmodel.cpp b/src/plugins/qmlprofiler/flamegraphmodel.cpp index 250bb8cbdbf..952631b577d 100644 --- a/src/plugins/qmlprofiler/flamegraphmodel.cpp +++ b/src/plugins/qmlprofiler/flamegraphmodel.cpp @@ -170,8 +170,10 @@ void FlameGraphModel::restrictToFeatures(quint64 visibleFeatures) std::bind(&FlameGraphModel::beginResetModel, this), std::bind(&FlameGraphModel::finalize, this), [this](const QString &message) { - emit m_modelManager->error(tr("Could not re-read events from temporary trace file: %1") - .arg(message)); + if (!message.isEmpty()) { + emit m_modelManager->error(tr("Could not re-read events from temporary trace file: %1") + .arg(message)); + } endResetModel(); clear(); }, future); diff --git a/src/plugins/qmlprofiler/qmlprofilermodelmanager.cpp b/src/plugins/qmlprofiler/qmlprofilermodelmanager.cpp index f859a0f027a..033a4b48332 100644 --- a/src/plugins/qmlprofiler/qmlprofilermodelmanager.cpp +++ b/src/plugins/qmlprofiler/qmlprofilermodelmanager.cpp @@ -74,19 +74,37 @@ private: std::vector m_types; }; +class QmlProfilerEventStorage : public Timeline::TraceEventStorage +{ + Q_DECLARE_TR_FUNCTIONS(QmlProfilerEventStorage) +public: + using ErrorHandler = std::function; + + QmlProfilerEventStorage(const ErrorHandler &errorHandler); + + int append(Timeline::TraceEvent &&event) override; + int size() const override; + void clear() override; + bool replay(const std::function &receiver) const override; + void finalize() override; + + ErrorHandler errorHandler() const; + void setErrorHandler(const ErrorHandler &errorHandler); + +private: + Timeline::TraceStashFile m_file; + std::function m_errorHandler; + int m_size = 0; +}; + class QmlProfilerModelManager::QmlProfilerModelManagerPrivate { public: - QmlProfilerModelManagerPrivate() : file("qmlprofiler-data") {} - Internal::QmlProfilerTextMarkModel *textMarkModel = nullptr; Internal::QmlProfilerDetailsRewriter *detailsRewriter = nullptr; - Timeline::TraceStashFile file; - bool isRestrictedToRange = false; - void writeToStream(const QmlEvent &event); void addEventType(const QmlEventType &eventType); void handleError(const QString &message); @@ -94,7 +112,10 @@ public: }; QmlProfilerModelManager::QmlProfilerModelManager(QObject *parent) : - Timeline::TimelineTraceManager(std::make_unique(), parent), + Timeline::TimelineTraceManager( + std::make_unique( + std::bind(&Timeline::TimelineTraceManager::error, this, std::placeholders::_1)), + std::make_unique(), parent), d(new QmlProfilerModelManagerPrivate) { setNotesModel(new QmlProfilerNotesModel(this)); @@ -106,9 +127,6 @@ QmlProfilerModelManager::QmlProfilerModelManager(QObject *parent) : connect(d->detailsRewriter, &Internal::QmlProfilerDetailsRewriter::eventDetailsChanged, this, &QmlProfilerModelManager::typeDetailsFinished); - if (!d->file.open()) - emit error(tr("Cannot open temporary trace file to store events.")); - quint64 allFeatures = 0; for (quint8 i = 0; i <= MaximumProfileFeature; ++i) allFeatures |= (1ull << i); @@ -138,12 +156,6 @@ void QmlProfilerModelManager::registerFeatures(quint64 features, QmlEventLoader finalizer, clearer); } -void QmlProfilerModelManager::addEvents(const QVector &events) -{ - for (const QmlEvent &event : events) - addEvent(event); -} - const QmlEventType &QmlProfilerModelManager::eventType(int typeId) const { return static_cast(TimelineTraceManager::eventType(typeId)); @@ -174,31 +186,19 @@ void QmlProfilerModelManager::replayQmlEvents(QmlEventLoader loader, if (initializer) initializer(); - const auto result = d->file.replay([&](const QmlEvent &event) { + const auto result = eventStorage()->replay([&](Timeline::TraceEvent &&event) { if (future.isCanceled()) return false; - loader(event, eventType(event.typeIndex())); + loader(static_cast(event), eventType(event.typeIndex())); return true; }); - switch (result) { - case Timeline::TraceStashFile::ReplaySuccess: - if (finalizer) - finalizer(); - break; - case Timeline::TraceStashFile::ReplayOpenFailed: - if (errorHandler) - errorHandler(tr("Could not re-open temporary trace file")); - break; - case Timeline::TraceStashFile::ReplayLoadFailed: - if (errorHandler) - errorHandler(tr("Could not load events from temporary trace file")); - break; - case Timeline::TraceStashFile::ReplayReadPastEnd: - if (errorHandler) - errorHandler(tr("Read past end in temporary trace file")); - break; + if (!result && errorHandler) { + errorHandler(future.isCanceled() ? QString() + : tr("Failed to replay QML events from stash file.")); + } else if (result && finalizer) { + finalizer(); } } @@ -236,11 +236,6 @@ static QString getInitialDetails(const QmlEventType &event) return details; } -void QmlProfilerModelManager::QmlProfilerModelManagerPrivate::writeToStream(const QmlEvent &event) -{ - file.append(event); -} - void QmlProfilerModelManager::QmlProfilerModelManagerPrivate::handleError(const QString &message) { // What to do here? @@ -254,8 +249,6 @@ const char *QmlProfilerModelManager::featureName(ProfileFeature feature) void QmlProfilerModelManager::finalize() { - if (!d->file.flush()) - emit error(tr("Failed to flush temporary trace file")); d->detailsRewriter->reloadDocuments(); // Load notes after the timeline models have been initialized ... @@ -299,14 +292,6 @@ void QmlProfilerModelManager::restrictByFilter(QmlProfilerModelManager::QmlEvent }); } -void QmlProfilerModelManager::clearEventStorage() -{ - TimelineTraceManager::clearEventStorage(); - d->file.clear(); - if (!d->file.open()) - emit error(tr("Failed to reset temporary trace file")); -} - int QmlProfilerModelManager::appendEventType(QmlEventType &&type) { type.setDisplayName(getDisplayName(type)); @@ -351,10 +336,9 @@ void QmlProfilerModelManager::setEventType(int typeIndex, QmlEventType &&type) } -void QmlProfilerModelManager::addEvent(const QmlEvent &event) +void QmlProfilerModelManager::appendEvent(QmlEvent &&event) { - d->writeToStream(event); - TimelineTraceManager::addEvent(event); + TimelineTraceManager::appendEvent(std::move(event)); } void QmlProfilerModelManager::restrictToRange(qint64 start, qint64 end) @@ -480,4 +464,67 @@ void QmlProfilerEventTypeStorage::clear() m_types.clear(); } +QmlProfilerEventStorage::QmlProfilerEventStorage( + const std::function &errorHandler) + : m_file("qmlprofiler-data"), m_errorHandler(errorHandler) +{ + if (!m_file.open()) + errorHandler(tr("Cannot open temporary trace file to store events.")); +} + +int QmlProfilerEventStorage::append(Timeline::TraceEvent &&event) +{ + m_file.append(std::move(static_cast(event))); + return m_size++; +} + +int QmlProfilerEventStorage::size() const +{ + return m_size; +} + +void QmlProfilerEventStorage::clear() +{ + m_size = 0; + m_file.clear(); + if (!m_file.open()) + m_errorHandler(tr("Failed to reset temporary trace file")); +} + +void QmlProfilerEventStorage::finalize() +{ + if (!m_file.flush()) + m_errorHandler(tr("Failed to flush temporary trace file")); +} + +QmlProfilerEventStorage::ErrorHandler QmlProfilerEventStorage::errorHandler() const +{ + return m_errorHandler; +} + +void QmlProfilerEventStorage::setErrorHandler( + const QmlProfilerEventStorage::ErrorHandler &errorHandler) +{ + m_errorHandler = errorHandler; +} + +bool QmlProfilerEventStorage::replay( + const std::function &receiver) const +{ + switch (m_file.replay(receiver)) { + case Timeline::TraceStashFile::ReplaySuccess: + return true; + case Timeline::TraceStashFile::ReplayOpenFailed: + m_errorHandler(tr("Could not re-open temporary trace file")); + break; + case Timeline::TraceStashFile::ReplayLoadFailed: + // Happens if the loader rejects an event. Not an actual error + break; + case Timeline::TraceStashFile::ReplayReadPastEnd: + m_errorHandler(tr("Read past end in temporary trace file")); + break; + } + return false; +} + } // namespace QmlProfiler diff --git a/src/plugins/qmlprofiler/qmlprofilermodelmanager.h b/src/plugins/qmlprofiler/qmlprofilermodelmanager.h index 8b4350f80b4..a14c37042ce 100644 --- a/src/plugins/qmlprofiler/qmlprofilermodelmanager.h +++ b/src/plugins/qmlprofiler/qmlprofilermodelmanager.h @@ -61,7 +61,6 @@ public: Initializer initializer = nullptr, Finalizer finalizer = nullptr, Clearer clearer = nullptr); - void addEvents(const QVector &events); const QmlEventType &eventType(int typeId) const; void replayQmlEvents(QmlEventLoader loader, Initializer initializer, Finalizer finalizer, @@ -76,7 +75,7 @@ public: int appendEventType(QmlEventType &&type); void setEventType(int typeId, QmlEventType &&type); - void addEvent(const QmlEvent &event); + void appendEvent(QmlEvent &&event); void restrictToRange(qint64 start, qint64 end); bool isRestrictedToRange() const; @@ -91,8 +90,6 @@ private: void detailsChanged(int typeId, const QString &newString); void restrictByFilter(QmlEventFilter filter); - void clearEventStorage() override; - Timeline::TimelineTraceFile *createTraceFile() override; void replayEvents(TraceEventLoader loader, Initializer initializer, Finalizer finalizer, ErrorHandler errorHandler, QFutureInterface &future) const override; diff --git a/src/plugins/qmlprofiler/qmlprofilerstatisticsmodel.cpp b/src/plugins/qmlprofiler/qmlprofilerstatisticsmodel.cpp index 81e1168f25d..867b95273bb 100644 --- a/src/plugins/qmlprofiler/qmlprofilerstatisticsmodel.cpp +++ b/src/plugins/qmlprofiler/qmlprofilerstatisticsmodel.cpp @@ -112,8 +112,10 @@ void QmlProfilerStatisticsModel::restrictToFeatures(quint64 features) notesChanged(QmlProfilerStatisticsModel::s_invalidTypeId); // Reload notes }, [this](const QString &message) { endResetModel(); - emit m_modelManager->error(tr("Could not re-read events from temporary trace file: %1") - .arg(message)); + if (!message.isEmpty()) { + emit m_modelManager->error(tr("Could not re-read events from temporary trace file: %1") + .arg(message)); + } clear(); }, future); } diff --git a/src/plugins/qmlprofiler/qmlprofilertraceclient.cpp b/src/plugins/qmlprofiler/qmlprofilertraceclient.cpp index 7db75acbec1..79183a77b1f 100644 --- a/src/plugins/qmlprofiler/qmlprofilertraceclient.cpp +++ b/src/plugins/qmlprofiler/qmlprofilertraceclient.cpp @@ -75,7 +75,7 @@ public: bool updateFeatures(quint8 feature); int resolveType(const QmlTypedEvent &type); int resolveStackTop(); - void forwardEvents(const QmlEvent &last); + void forwardEvents(QmlEvent &&last); void processCurrentEvent(); void finalize(); @@ -143,17 +143,17 @@ int QmlProfilerTraceClientPrivate::resolveStackTop() && pendingMessages.head().timestamp() < typedEvent.event.timestamp()) { forwardEvents(pendingMessages.dequeue()); } - forwardEvents(typedEvent.event); + forwardEvents(QmlEvent(typedEvent.event)); return typeIndex; } -void QmlProfilerTraceClientPrivate::forwardEvents(const QmlEvent &last) +void QmlProfilerTraceClientPrivate::forwardEvents(QmlEvent &&last) { while (!pendingDebugMessages.isEmpty() && pendingDebugMessages.front().timestamp() <= last.timestamp()) { - modelManager->addEvent(pendingDebugMessages.dequeue()); + modelManager->appendEvent(pendingDebugMessages.dequeue()); } - modelManager->addEvent(last); + modelManager->appendEvent(std::move(last)); } void QmlProfilerTraceClientPrivate::processCurrentEvent() @@ -176,7 +176,7 @@ void QmlProfilerTraceClientPrivate::processCurrentEvent() currentEvent.event.setTypeIndex(typeIndex); while (!pendingMessages.isEmpty()) forwardEvents(pendingMessages.dequeue()); - forwardEvents(currentEvent.event); + forwardEvents(QmlEvent(currentEvent.event)); rangesInProgress.pop(); break; } @@ -196,7 +196,7 @@ void QmlProfilerTraceClientPrivate::processCurrentEvent() int typeIndex = resolveType(currentEvent); currentEvent.event.setTypeIndex(typeIndex); if (rangesInProgress.isEmpty()) - forwardEvents(currentEvent.event); + forwardEvents(QmlEvent(currentEvent.event)); else pendingMessages.enqueue(currentEvent.event); break; @@ -214,7 +214,7 @@ void QmlProfilerTraceClientPrivate::finalize() } QTC_CHECK(pendingMessages.isEmpty()); while (!pendingDebugMessages.isEmpty()) - modelManager->addEvent(pendingDebugMessages.dequeue()); + modelManager->appendEvent(pendingDebugMessages.dequeue()); } void QmlProfilerTraceClientPrivate::sendRecordingStatus(int engineId) diff --git a/src/plugins/qmlprofiler/qmlprofilertracefile.cpp b/src/plugins/qmlprofiler/qmlprofilertracefile.cpp index 9844b30c5cc..7055cd265d0 100644 --- a/src/plugins/qmlprofiler/qmlprofilertracefile.cpp +++ b/src/plugins/qmlprofiler/qmlprofilertracefile.cpp @@ -261,7 +261,6 @@ void QmlProfilerTraceFile::loadQzt(QIODevice *device) setDeviceProgress(device); } - QVector eventBuffer; while (!stream.atEnd() && !isCanceled()) { stream >> data; buffer.setData(qUncompress(data)); @@ -285,10 +284,8 @@ void QmlProfilerTraceFile::loadQzt(QIODevice *device) } else { Q_UNREACHABLE(); } - eventBuffer.append(event); + manager->appendEvent(std::move(event)); } - manager->addEvents(eventBuffer); - eventBuffer.clear(); buffer.close(); setDeviceProgress(device); } @@ -296,7 +293,6 @@ void QmlProfilerTraceFile::loadQzt(QIODevice *device) if (isCanceled()) { emit canceled(); } else { - manager->addEvents(eventBuffer); emit success(); } } @@ -447,7 +443,7 @@ public: void addEvent(const QmlEvent &event); void addRange(const QmlEvent &start, const QmlEvent &end); - QVector finalize(); + void finalize(QmlProfilerModelManager *modelManager); private: struct QmlRange { @@ -468,7 +464,7 @@ void EventList::addRange(const QmlEvent &start, const QmlEvent &end) ranges.append({start, end}); } -QVector EventList::finalize() +void EventList::finalize(QmlProfilerModelManager *modelManager) { std::sort(ranges.begin(), ranges.end(), [](const QmlRange &a, const QmlRange &b) { if (a.begin.timestamp() < b.begin.timestamp()) @@ -482,15 +478,13 @@ QVector EventList::finalize() }); QList ends; - QVector result; while (!ranges.isEmpty()) { // This is more expensive than just iterating, but we don't want to double the already // high memory footprint. QmlRange range = ranges.takeFirst(); while (!ends.isEmpty() && ends.last().timestamp() <= range.begin.timestamp()) - result.append(ends.takeLast()); + modelManager->appendEvent(ends.takeLast()); - result.append(range.begin); if (range.end.isValid()) { auto it = ends.end(); for (auto begin = ends.begin(); it != begin;) { @@ -501,11 +495,10 @@ QVector EventList::finalize() } ends.insert(it, range.end); } + modelManager->appendEvent(std::move(range.begin)); } while (!ends.isEmpty()) - result.append(ends.takeLast()); - - return result; + modelManager->appendEvent(ends.takeLast()); } void QmlProfilerTraceFile::loadEvents(QXmlStreamReader &stream) @@ -585,7 +578,7 @@ void QmlProfilerTraceFile::loadEvents(QXmlStreamReader &stream) case QXmlStreamReader::EndElement: { if (elementName == _("profilerDataModel")) { // done reading profilerDataModel - modelManager()->addEvents(events.finalize()); + events.finalize(modelManager()); return; } break; diff --git a/src/plugins/qmlprofiler/tests/debugmessagesmodel_test.cpp b/src/plugins/qmlprofiler/tests/debugmessagesmodel_test.cpp index 3d71534a99e..49812707cbd 100644 --- a/src/plugins/qmlprofiler/tests/debugmessagesmodel_test.cpp +++ b/src/plugins/qmlprofiler/tests/debugmessagesmodel_test.cpp @@ -40,17 +40,16 @@ DebugMessagesModelTest::DebugMessagesModelTest(QObject *parent) : void DebugMessagesModelTest::initTestCase() { manager.initialize(); - QmlEvent event; - event.setTypeIndex(-1); for (int i = 0; i < 10; ++i) { + QmlEvent event; event.setTimestamp(i); event.setString(QString::fromLatin1("message %1").arg(i)); QmlEventType type(DebugMessage, MaximumRangeType, i % (QtMsgType::QtInfoMsg + 1), QmlEventLocation("somefile.js", i, 10 - i)); event.setTypeIndex(manager.numEventTypes()); manager.appendEventType(std::move(type)); - manager.addEvent(event); + manager.appendEvent(std::move(event)); } manager.finalize(); } diff --git a/src/plugins/qmlprofiler/tests/flamegraphmodel_test.cpp b/src/plugins/qmlprofiler/tests/flamegraphmodel_test.cpp index 152fdef75c3..9e388196c8e 100644 --- a/src/plugins/qmlprofiler/tests/flamegraphmodel_test.cpp +++ b/src/plugins/qmlprofiler/tests/flamegraphmodel_test.cpp @@ -46,14 +46,13 @@ int FlameGraphModelTest::generateData(QmlProfilerModelManager *manager, manager->notesModel()->addTimelineModel(rangeModel); manager->initialize(); - QmlEvent event; - event.setTypeIndex(-1); QStack typeIndices; int i = 0; + int typeIndex = -1; while (i < 10) { - int typeIndex = -1; + QmlEvent event; if (i < 5) { typeIndex = manager->appendEventType( QmlEventType(MaximumMessage, @@ -66,26 +65,29 @@ int FlameGraphModelTest::generateData(QmlProfilerModelManager *manager, event.setTypeIndex(typeIndex); event.setTimestamp(++i); event.setRangeStage(RangeStart); - manager->addEvent(event); + manager->appendEvent(std::move(event)); typeIndices.push(typeIndex); } + QmlEvent event; + event.setTypeIndex(typeIndex); event.setRangeStage(RangeEnd); event.setTypeIndex(typeIndices.pop()); event.setTimestamp(++i); - manager->addEvent(event); + manager->appendEvent(QmlEvent(event)); event.setRangeStage(RangeStart); event.setTypeIndex(0); // Have it accepted by the JavaScript range model above typeIndices.push(0); event.setTimestamp(++i); - manager->addEvent(event); + manager->appendEvent(std::move(event)); while (!typeIndices.isEmpty()) { + QmlEvent event; event.setTimestamp(++i); event.setRangeStage(RangeEnd); event.setTypeIndex(typeIndices.pop()); - manager->addEvent(event); + manager->appendEvent(std::move(event)); } manager->finalize(); diff --git a/src/plugins/qmlprofiler/tests/inputeventsmodel_test.cpp b/src/plugins/qmlprofiler/tests/inputeventsmodel_test.cpp index 1749eaa0324..7a111913edd 100644 --- a/src/plugins/qmlprofiler/tests/inputeventsmodel_test.cpp +++ b/src/plugins/qmlprofiler/tests/inputeventsmodel_test.cpp @@ -48,16 +48,16 @@ InputEventsModelTest::InputEventsModelTest(QObject *parent) : void InputEventsModelTest::initTestCase() { manager.initialize(); - QmlEvent event; for (int i = 0; i < 10; ++i) { + QmlEvent event; event.setTimestamp(i); InputEventType type = inputType(i); event.setTypeIndex(type <= InputKeyUnknown ? keyTypeId : mouseTypeId); event.setNumbers({static_cast(type), (i * 32) % 256, static_cast((i * 0x02000000) & Qt::KeyboardModifierMask)}); - manager.addEvent(event); + manager.appendEvent(std::move(event)); } manager.finalize(); diff --git a/src/plugins/qmlprofiler/tests/memoryusagemodel_test.cpp b/src/plugins/qmlprofiler/tests/memoryusagemodel_test.cpp index e7d2d2e8cc2..694bc58bed9 100644 --- a/src/plugins/qmlprofiler/tests/memoryusagemodel_test.cpp +++ b/src/plugins/qmlprofiler/tests/memoryusagemodel_test.cpp @@ -52,23 +52,23 @@ void MemoryUsageModelTest::initTestCase() event.setTimestamp(++timestamp); event.setTypeIndex(heapPageTypeId); event.setNumbers({2048}); - manager.addEvent(event); - manager.addEvent(event); // allocate two of them and make the model summarize + manager.appendEvent(QmlEvent(event)); + manager.appendEvent(QmlEvent(event)); // allocate two of them and make the model summarize event.setTimestamp(++timestamp); event.setTypeIndex(smallItemTypeId); event.setNumbers({32}); - manager.addEvent(event); + manager.appendEvent(QmlEvent(event)); event.setTimestamp(++timestamp); event.setTypeIndex(largeItemTypeId); event.setNumbers({1024}); - manager.addEvent(event); + manager.appendEvent(QmlEvent(event)); event.setTimestamp(++timestamp); event.setTypeIndex(smallItemTypeId); event.setNumbers({-32}); - manager.addEvent(event); + manager.appendEvent(std::move(event)); }; addMemoryEvents(); @@ -82,19 +82,19 @@ void MemoryUsageModelTest::initTestCase() event.setRangeStage(RangeStart); event.setTimestamp(++timestamp); event.setTypeIndex(rangeTypeId); - manager.addEvent(event); + manager.appendEvent(QmlEvent(event)); addMemoryEvents(); addMemoryEvents(); // twice to also trigger summary in first row event.setRangeStage(RangeEnd); event.setTimestamp(++timestamp); - manager.addEvent(event); + manager.appendEvent(QmlEvent(event)); event.setTimestamp(++timestamp); event.setTypeIndex(largeItemTypeId); event.setNumbers({-1024}); - manager.addEvent(event); + manager.appendEvent(std::move(event)); manager.finalize(); QCOMPARE(model.count(), 11); diff --git a/src/plugins/qmlprofiler/tests/pixmapcachemodel_test.cpp b/src/plugins/qmlprofiler/tests/pixmapcachemodel_test.cpp index d8cfd4ec5b1..f97c5991865 100644 --- a/src/plugins/qmlprofiler/tests/pixmapcachemodel_test.cpp +++ b/src/plugins/qmlprofiler/tests/pixmapcachemodel_test.cpp @@ -53,7 +53,7 @@ void PixmapCacheModelTest::initTestCase() event.setTypeIndex(eventTypeIndices[(i * 13) % MaximumPixmapEventType]); event.setTimestamp(i); event.setNumbers({i + 1, i - 1, i * 2}); - manager.addEvent(event); + manager.appendEvent(std::move(event)); } for (int i = 0; i < MaximumPixmapEventType; ++i) { @@ -68,27 +68,27 @@ void PixmapCacheModelTest::initTestCase() QmlEvent event; event.setTypeIndex(eventTypeIndices[MaximumPixmapEventType + PixmapLoadingStarted]); event.setTimestamp(101); - manager.addEvent(event); + manager.appendEvent(QmlEvent(event)); QCOMPARE(model.cacheState(nextItem), PixmapCacheModel::Uncached); QCOMPARE(model.loadState(nextItem), PixmapCacheModel::Loading); event.setTypeIndex(eventTypeIndices[MaximumPixmapEventType + PixmapCacheCountChanged]); event.setNumbers({0, 0, 200}); // cache count increase event.setTimestamp(102); - manager.addEvent(event); + manager.appendEvent(QmlEvent(event)); QCOMPARE(model.cacheState(nextItem), PixmapCacheModel::ToBeCached); QCOMPARE(model.loadState(nextItem), PixmapCacheModel::Loading); event.setTypeIndex(eventTypeIndices[MaximumPixmapEventType + PixmapLoadingError]); event.setTimestamp(103); - manager.addEvent(event); + manager.appendEvent(QmlEvent(event)); QCOMPARE(model.cacheState(nextItem), PixmapCacheModel::Corrupt); QCOMPARE(model.loadState(nextItem), PixmapCacheModel::Error); event.setTypeIndex(eventTypeIndices[MaximumPixmapEventType + PixmapCacheCountChanged]); event.setNumbers({0, 0, 199}); // cache count decrease event.setTimestamp(104); - manager.addEvent(event); + manager.appendEvent(QmlEvent(event)); QCOMPARE(model.cacheState(nextItem), PixmapCacheModel::Uncacheable); QCOMPARE(model.loadState(nextItem), PixmapCacheModel::Error); @@ -97,13 +97,13 @@ void PixmapCacheModelTest::initTestCase() QCOMPARE(model.count(), nextItem); event.setTypeIndex(eventTypeIndices[MaximumPixmapEventType + PixmapLoadingStarted]); event.setTimestamp(105); - manager.addEvent(event); + manager.appendEvent(QmlEvent(event)); QCOMPARE(model.cacheState(nextItem), PixmapCacheModel::Uncached); QCOMPARE(model.loadState(nextItem), PixmapCacheModel::Loading); event.setTypeIndex(eventTypeIndices[MaximumPixmapEventType + PixmapLoadingError]); event.setTimestamp(106); - manager.addEvent(event); + manager.appendEvent(QmlEvent(event)); QCOMPARE(model.cacheState(nextItem), PixmapCacheModel::Uncacheable); QCOMPARE(model.loadState(nextItem), PixmapCacheModel::Error); @@ -112,7 +112,7 @@ void PixmapCacheModelTest::initTestCase() // This way we get a corrupt cache entry ... event.setNumbers({0, 0, 200}); event.setTimestamp(107); - manager.addEvent(event); + manager.appendEvent(QmlEvent(event)); QCOMPARE(model.cacheState(nextItem - 1), PixmapCacheModel::Corrupt); QCOMPARE(model.loadState(nextItem - 1), PixmapCacheModel::Error); QCOMPARE(model.cacheState(nextItem), PixmapCacheModel::Uncacheable); @@ -122,7 +122,7 @@ void PixmapCacheModelTest::initTestCase() event.setTypeIndex(eventTypeIndices[MaximumPixmapEventType + PixmapCacheCountChanged]); event.setNumbers({0, 0, 199}); // cache count decrease, removes the corrupt entry event.setTimestamp(108); - manager.addEvent(event); + manager.appendEvent(QmlEvent(event)); QCOMPARE(model.cacheState(nextItem - 1), PixmapCacheModel::Uncacheable); QCOMPARE(model.loadState(nextItem - 1), PixmapCacheModel::Error); QCOMPARE(model.cacheState(nextItem), PixmapCacheModel::Uncacheable); @@ -133,28 +133,28 @@ void PixmapCacheModelTest::initTestCase() QCOMPARE(model.count(), nextItem); event.setTypeIndex(eventTypeIndices[MaximumPixmapEventType + PixmapLoadingStarted]); event.setTimestamp(109); - manager.addEvent(event); + manager.appendEvent(QmlEvent(event)); QCOMPARE(model.cacheState(nextItem), PixmapCacheModel::Uncached); QCOMPARE(model.loadState(nextItem), PixmapCacheModel::Loading); event.setTypeIndex(eventTypeIndices[MaximumPixmapEventType + PixmapCacheCountChanged]); event.setNumbers({0, 0, 200}); // cache count increase event.setTimestamp(110); - manager.addEvent(event); + manager.appendEvent(QmlEvent(event)); QCOMPARE(model.cacheState(nextItem), PixmapCacheModel::ToBeCached); QCOMPARE(model.loadState(nextItem), PixmapCacheModel::Loading); event.setTypeIndex(eventTypeIndices[MaximumPixmapEventType + PixmapSizeKnown]); event.setNumbers({50, 50}); event.setTimestamp(111); - manager.addEvent(event); + manager.appendEvent(QmlEvent(event)); QCOMPARE(model.cacheState(nextItem), PixmapCacheModel::Cached); QCOMPARE(model.loadState(nextItem), PixmapCacheModel::Loading); event.setTypeIndex(eventTypeIndices[MaximumPixmapEventType + PixmapCacheCountChanged]); event.setNumbers({0, 0, 199}); // cache count decrease event.setTimestamp(112); - manager.addEvent(event); + manager.appendEvent(QmlEvent(event)); QCOMPARE(model.cacheState(nextItem), PixmapCacheModel::Uncached); QCOMPARE(model.loadState(nextItem), PixmapCacheModel::Loading); @@ -163,13 +163,13 @@ void PixmapCacheModelTest::initTestCase() event.setTypeIndex(eventTypeIndices[MaximumPixmapEventType + PixmapSizeKnown]); event.setNumbers({20, 30}); event.setTimestamp(113); - manager.addEvent(event); // Results in Uncached, with valid size + manager.appendEvent(QmlEvent(event)); // Results in Uncached, with valid size QCOMPARE(model.count(), nextItem + 3); // no item added here; we just store the size event.setTypeIndex(eventTypeIndices[MaximumPixmapEventType + PixmapLoadingError]); event.setTimestamp(114); // terminates the still loading item, adding another cache count change - manager.addEvent(event); + manager.appendEvent(std::move(event)); QCOMPARE(model.count(), nextItem + 4); QCOMPARE(model.cacheState(nextItem), PixmapCacheModel::Uncacheable); QCOMPARE(model.loadState(nextItem), PixmapCacheModel::Error); @@ -182,7 +182,7 @@ void PixmapCacheModelTest::initTestCase() event.setTypeIndex(eventTypeIndices[i]); event.setTimestamp(i + j + 200); event.setNumbers({i + 1, i - 1, i - j}); - manager.addEvent(event); + manager.appendEvent(std::move(event)); } } diff --git a/src/plugins/qmlprofiler/tests/qmlprofileranimationsmodel_test.cpp b/src/plugins/qmlprofiler/tests/qmlprofileranimationsmodel_test.cpp index 03fd9e7e9c5..f299c8e6d96 100644 --- a/src/plugins/qmlprofiler/tests/qmlprofileranimationsmodel_test.cpp +++ b/src/plugins/qmlprofiler/tests/qmlprofileranimationsmodel_test.cpp @@ -51,7 +51,7 @@ void QmlProfilerAnimationsModelTest::initTestCase() for (int i = 0; i < 10; ++i) { event.setTimestamp(i); event.setNumbers({frameRate(i), 9 - i, (i % 2) ? RenderThread : GuiThread}); - manager.addEvent(event); + manager.appendEvent(QmlEvent(event)); } manager.finalize(); } diff --git a/src/plugins/qmlprofiler/tests/qmlprofilertool_test.cpp b/src/plugins/qmlprofiler/tests/qmlprofilertool_test.cpp index a010c55c4a5..fdba15f03db 100644 --- a/src/plugins/qmlprofiler/tests/qmlprofilertool_test.cpp +++ b/src/plugins/qmlprofiler/tests/qmlprofilertool_test.cpp @@ -102,7 +102,7 @@ void QmlProfilerToolTest::testClearEvents() QCOMPARE(modelManager->numEvents(), 0); const int typeIndex = modelManager->appendEventType(QmlEventType()); QCOMPARE(typeIndex, 0); - modelManager->addEvent(QmlEvent(0, typeIndex, "")); + modelManager->appendEvent(QmlEvent(0, typeIndex, "")); QCOMPARE(modelManager->numEventTypes(), 1); QCOMPARE(modelManager->numEvents(), 1); stateManager->setServerRecording(false); @@ -111,7 +111,7 @@ void QmlProfilerToolTest::testClearEvents() stateManager->setServerRecording(true); // clears previous events, but not types QCOMPARE(modelManager->numEventTypes(), 1); QCOMPARE(modelManager->numEvents(), 0); - modelManager->addEvent(QmlEvent(0, typeIndex, "")); + modelManager->appendEvent(QmlEvent(0, typeIndex, "")); QCOMPARE(modelManager->numEventTypes(), 1); QCOMPARE(modelManager->numEvents(), 1); } diff --git a/src/plugins/qmlprofiler/tests/qmlprofilertraceclient_test.cpp b/src/plugins/qmlprofiler/tests/qmlprofilertraceclient_test.cpp index f8c189b275c..32aa45a5272 100644 --- a/src/plugins/qmlprofiler/tests/qmlprofilertraceclient_test.cpp +++ b/src/plugins/qmlprofiler/tests/qmlprofilertraceclient_test.cpp @@ -70,6 +70,11 @@ void QmlProfilerTraceClientTest::testMessageReceived() traceClient.stateChanged(QmlDebug::QmlDebugClient::NotConnected); QFutureInterface future; + + QString lastError; + connect(&modelManager, &Timeline::TimelineTraceManager::error, + this, [&](const QString &message) { lastError = message; }); + modelManager.replayQmlEvents([&](const QmlEvent &event, const QmlEventType &type) { qint64 timestamp; qint32 message; @@ -81,14 +86,16 @@ void QmlProfilerTraceClientTest::testMessageReceived() }, nullptr, [this]() { modelManager.clearAll(); traceClient.clear(); - }, [this](const QString &message) { - if (message == QmlProfilerModelManager::tr("Read past end in temporary trace file")) { + }, [this, &lastError](const QString &message) { + QVERIFY(!message.isEmpty()); + if (lastError == QmlProfilerModelManager::tr("Read past end in temporary trace file")) { // Ignore read-past-end errors: Our test traces are somewhat dirty and don't end on // packet boundaries modelManager.clearAll(); traceClient.clear(); + lastError.clear(); } else { - QFAIL(message.toUtf8().constData()); + QFAIL((message + " " + lastError).toUtf8().constData()); } }, future); }