diff --git a/src/plugins/qmlprofiler/qmlprofiler.qbs b/src/plugins/qmlprofiler/qmlprofiler.qbs index d4b1c7d88ac..32056fa83ca 100644 --- a/src/plugins/qmlprofiler/qmlprofiler.qbs +++ b/src/plugins/qmlprofiler/qmlprofiler.qbs @@ -83,6 +83,7 @@ QtcPlugin { "flamegraphview_test.cpp", "flamegraphview_test.h", "inputeventsmodel_test.cpp", "inputeventsmodel_test.h", "localqmlprofilerrunner_test.cpp", "localqmlprofilerrunner_test.h", + "memoryusagemodel_test.cpp", "memoryusagemodel_test.h", ] } } diff --git a/src/plugins/qmlprofiler/qmlprofilerplugin.cpp b/src/plugins/qmlprofiler/qmlprofilerplugin.cpp index 88ce8e5432d..ab30f1971cb 100644 --- a/src/plugins/qmlprofiler/qmlprofilerplugin.cpp +++ b/src/plugins/qmlprofiler/qmlprofilerplugin.cpp @@ -36,6 +36,7 @@ #include "tests/flamegraphview_test.h" #include "tests/inputeventsmodel_test.h" #include "tests/localqmlprofilerrunner_test.h" +#include "tests/memoryusagemodel_test.h" #endif #include @@ -89,6 +90,7 @@ QList QmlProfiler::Internal::QmlProfilerPlugin::createTestObjects() c tests << new FlameGraphViewTest; tests << new InputEventsModelTest; tests << new LocalQmlProfilerRunnerTest; + tests << new MemoryUsageModelTest; #endif return tests; } diff --git a/src/plugins/qmlprofiler/tests/memoryusagemodel_test.cpp b/src/plugins/qmlprofiler/tests/memoryusagemodel_test.cpp new file mode 100644 index 00000000000..9666c3e6e16 --- /dev/null +++ b/src/plugins/qmlprofiler/tests/memoryusagemodel_test.cpp @@ -0,0 +1,251 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#include "memoryusagemodel_test.h" +#include + +namespace QmlProfiler { +namespace Internal { + +MemoryUsageModelTest::MemoryUsageModelTest(QObject *parent) : QObject(parent), + manager(nullptr), model(&manager) +{ +} + +void MemoryUsageModelTest::initTestCase() +{ + manager.startAcquiring(); + qint64 timestamp = 0; + + QmlEventType type; + type.message = MemoryAllocation; + type.rangeType = MaximumRangeType; + + type.detailType = HeapPage; + heapPageTypeId = manager.qmlModel()->addEventType(type); + type.detailType = SmallItem; + smallItemTypeId = manager.qmlModel()->addEventType(type); + type.detailType = LargeItem; + largeItemTypeId = manager.qmlModel()->addEventType(type); + + auto addMemoryEvents = [&]() { + QmlEvent event; + event.setTimestamp(++timestamp); + event.setTypeIndex(heapPageTypeId); + event.setNumbers({2048}); + manager.qmlModel()->addEvent(event); + manager.qmlModel()->addEvent(event); // allocate two of them and make the model summarize + + event.setTimestamp(++timestamp); + event.setTypeIndex(smallItemTypeId); + event.setNumbers({32}); + manager.qmlModel()->addEvent(event); + + event.setTimestamp(++timestamp); + event.setTypeIndex(largeItemTypeId); + event.setNumbers({1024}); + manager.qmlModel()->addEvent(event); + + event.setTimestamp(++timestamp); + event.setTypeIndex(smallItemTypeId); + event.setNumbers({-32}); + manager.qmlModel()->addEvent(event); + }; + + addMemoryEvents(); + QmlEventType rangeType; + rangeType.message = MaximumMessage; + rangeType.rangeType = Javascript; + rangeType.data = QString("funcfunc"); + rangeType.location = QmlEventLocation(QString("somefile.js"), 10, 20); + rangeTypeId = manager.qmlModel()->addEventType(rangeType); + + QmlEvent event; + event.setRangeStage(RangeStart); + event.setTimestamp(++timestamp); + event.setTypeIndex(rangeTypeId); + manager.qmlModel()->addEvent(event); + + addMemoryEvents(); + addMemoryEvents(); // twice to also trigger summary in first row + + event.setRangeStage(RangeEnd); + event.setTimestamp(++timestamp); + manager.qmlModel()->addEvent(event); + + event.setTimestamp(++timestamp); + event.setTypeIndex(largeItemTypeId); + event.setNumbers({-1024}); + manager.qmlModel()->addEvent(event); + + manager.acquiringDone(); + QCOMPARE(manager.state(), QmlProfilerModelManager::Done); + QCOMPARE(model.count(), 11); +} + +void MemoryUsageModelTest::testRowMaxValue() +{ + QCOMPARE(model.rowMaxValue(1), 3 * (1024 + 4096)); + QCOMPARE(model.rowMaxValue(2), 3 * (1024 + 4096)); +} + +void MemoryUsageModelTest::testTypeId() +{ + QCOMPARE(model.typeId(0), heapPageTypeId); + QCOMPARE(model.typeId(1), smallItemTypeId); + QCOMPARE(model.typeId(2), largeItemTypeId); + QCOMPARE(model.typeId(3), smallItemTypeId); + + for (int i = 4; i < 9; ++i) + QCOMPARE(model.typeId(i), rangeTypeId); + + QCOMPARE(model.typeId(9), largeItemTypeId); + QCOMPARE(model.typeId(10), largeItemTypeId); +} + +void MemoryUsageModelTest::testColor() +{ + QColor heapPageColor = model.color(0); + QColor smallItemColor = model.color(1); + QColor largeItemColor = model.color(2); + QVERIFY(smallItemColor != heapPageColor); + QVERIFY(largeItemColor != heapPageColor); + QVERIFY(smallItemColor != largeItemColor); + QCOMPARE(model.color(4), heapPageColor); + QCOMPARE(model.color(8), largeItemColor); +} + +void MemoryUsageModelTest::testLabels() +{ + const QVariantList labels = model.labels(); + + const QVariantMap allocations = labels[0].toMap(); + QCOMPARE(allocations[QString("description")].toString(), model.tr("Memory Allocation")); + QCOMPARE(allocations[QString("id")].toInt(), static_cast(HeapPage)); + + const QVariantMap usages = labels[1].toMap(); + QCOMPARE(usages[QString("description")].toString(), model.tr("Memory Usage")); + QCOMPARE(usages[QString("id")].toInt(), static_cast(SmallItem)); +} + +void MemoryUsageModelTest::testDetails() +{ + const QVariantMap allocated = model.details(0); + QCOMPARE(allocated[QString("displayName")].toString(), model.tr("Memory Allocated")); + QCOMPARE(allocated[model.tr("Total")].toString(), model.tr("%1 bytes").arg(4096)); + QCOMPARE(allocated[model.tr("Allocated")].toString(), model.tr("%1 bytes").arg(4096)); + QCOMPARE(allocated[model.tr("Allocations")].toString(), QString::number(2)); + QCOMPARE(allocated[model.tr("Type")].toString(), model.tr("Heap Allocation")); + QCOMPARE(allocated[model.tr("Location")].toString(), QmlProfilerDataModel::tr("")); + + QVERIFY(!allocated.contains(model.tr("Deallocated"))); + QVERIFY(!allocated.contains(model.tr("Deallocations"))); + + const QVariantMap large = model.details(2); + QCOMPARE(large[QString("displayName")].toString(), model.tr("Memory Allocated")); + QCOMPARE(large[model.tr("Total")].toString(), model.tr("%1 bytes").arg(5120)); + QCOMPARE(large[model.tr("Allocated")].toString(), model.tr("%1 bytes").arg(1024)); + QCOMPARE(large[model.tr("Allocations")].toString(), QString::number(1)); + QCOMPARE(large[model.tr("Type")].toString(), model.tr("Large Item Allocation")); + QCOMPARE(large[model.tr("Location")].toString(), QmlProfilerDataModel::tr("")); + + QVERIFY(!large.contains(model.tr("Deallocated"))); + QVERIFY(!large.contains(model.tr("Deallocations"))); + + const QVariantMap freed = model.details(9); + QCOMPARE(freed[QString("displayName")].toString(), model.tr("Memory Freed")); + QCOMPARE(freed[model.tr("Total")].toString(), model.tr("%1 bytes").arg(2048)); + QCOMPARE(freed[model.tr("Deallocated")].toString(), model.tr("%1 bytes").arg(1024)); + QCOMPARE(freed[model.tr("Deallocations")].toString(), QString::number(1)); + QCOMPARE(freed[model.tr("Type")].toString(), model.tr("Heap Usage")); + QCOMPARE(freed[model.tr("Location")].toString(), QmlProfilerDataModel::tr("")); + + QVERIFY(!freed.contains(model.tr("Allocated"))); + QVERIFY(!freed.contains(model.tr("Allocations"))); +} + +void MemoryUsageModelTest::testExpandedRow() +{ + QCOMPARE(model.expandedRow(0), 1); + QCOMPARE(model.expandedRow(1), 2); // LargeItem event is expanded to two timeline items + QCOMPARE(model.expandedRow(2), 1); + QCOMPARE(model.expandedRow(3), 2); // Allocate and free tracked separately outside ranges + QCOMPARE(model.expandedRow(4), 1); + QCOMPARE(model.expandedRow(5), 2); +} + +void MemoryUsageModelTest::testCollapsedRow() +{ + QCOMPARE(model.collapsedRow(0), 1); + QCOMPARE(model.collapsedRow(1), 2); // LargeItem event is expanded to two timeline items + QCOMPARE(model.collapsedRow(2), 1); + QCOMPARE(model.collapsedRow(3), 2); // Allocate and free tracked separately outside ranges + QCOMPARE(model.collapsedRow(4), 1); + QCOMPARE(model.collapsedRow(5), 2); +} + +void MemoryUsageModelTest::testLocation() +{ + const QVariantMap empty = model.location(0); + QVERIFY(empty[QString("file")].toString().isEmpty()); + QCOMPARE(empty[QString("line")].toInt(), -1); + QCOMPARE(empty[QString("column")].toInt(), -1); + + const QVariantMap range = model.location(6); + QCOMPARE(range[QString("file")].toString(), QString("somefile.js")); + QCOMPARE(range[QString("line")].toInt(), 10); + QCOMPARE(range[QString("column")].toInt(), 20); +} + +void MemoryUsageModelTest::testRelativeHeight() +{ + float heights[] = {0.266667f, 0.06875f, 0.333333f, 0.0666667f, 0.6f, 0.2f, + 0.666667f, 0.933333f, 1.0f, 0.133333f, 0.933333f}; + for (int i = 0; i < 11; ++i) + QCOMPARE(model.relativeHeight(i), heights[i]); +} + +void MemoryUsageModelTest::testAccepted() +{ + QmlEventType type; + QVERIFY(!model.accepted(type)); + type.detailType = HeapPage; + QVERIFY(!model.accepted(type)); + type.message = MemoryAllocation; + QVERIFY(model.accepted(type)); + + type.message = MaximumMessage; + type.rangeType = Javascript; + QVERIFY(model.accepted(type)); +} + +void MemoryUsageModelTest::cleanupTestCase() +{ + manager.clear(); + QCOMPARE(model.count(), 0); +} + +} // namespace Internal +} // namespace QmlProfiler diff --git a/src/plugins/qmlprofiler/tests/memoryusagemodel_test.h b/src/plugins/qmlprofiler/tests/memoryusagemodel_test.h new file mode 100644 index 00000000000..c8b1c4b8c12 --- /dev/null +++ b/src/plugins/qmlprofiler/tests/memoryusagemodel_test.h @@ -0,0 +1,66 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#pragma once + +#include +#include +#include + +namespace QmlProfiler { +namespace Internal { + +class MemoryUsageModelTest : public QObject +{ + Q_OBJECT +public: + MemoryUsageModelTest(QObject *parent = 0); + +private slots: + void initTestCase(); + void testRowMaxValue(); + void testTypeId(); + void testColor(); + void testLabels(); + void testDetails(); + void testExpandedRow(); + void testCollapsedRow(); + void testLocation(); + void testRelativeHeight(); + void testAccepted(); + void cleanupTestCase(); + +private: + QmlProfilerModelManager manager; + MemoryUsageModel model; + + int heapPageTypeId = -1; + int smallItemTypeId = -1; + int largeItemTypeId = -1; + int rangeTypeId = -1; +}; + +} // namespace Internal +} // namespace QmlProfiler diff --git a/src/plugins/qmlprofiler/tests/tests.pri b/src/plugins/qmlprofiler/tests/tests.pri index 938ac6836f7..9c5a8d894e0 100644 --- a/src/plugins/qmlprofiler/tests/tests.pri +++ b/src/plugins/qmlprofiler/tests/tests.pri @@ -4,7 +4,8 @@ SOURCES += \ $$PWD/flamegraphmodel_test.cpp \ $$PWD/flamegraphview_test.cpp \ $$PWD/inputeventsmodel_test.cpp \ - $$PWD/localqmlprofilerrunner_test.cpp + $$PWD/localqmlprofilerrunner_test.cpp \ + $$PWD/memoryusagemodel_test.cpp HEADERS += \ $$PWD/debugmessagesmodel_test.h \ @@ -12,4 +13,5 @@ HEADERS += \ $$PWD/flamegraphmodel_test.h \ $$PWD/flamegraphview_test.h \ $$PWD/inputeventsmodel_test.h \ - $$PWD/localqmlprofilerrunner_test.h + $$PWD/localqmlprofilerrunner_test.h \ + $$PWD/memoryusagemodel_test.h