forked from qt-creator/qt-creator
Change-Id: I0965916f5ce302e9bdcb47ae7126262327f63613 Reviewed-by: Christian Stenger <christian.stenger@qt.io> Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
469 lines
14 KiB
C++
469 lines
14 KiB
C++
// Copyright (C) 2016 The Qt Company Ltd.
|
|
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
|
|
|
|
#include <QtTest>
|
|
#include <QColor>
|
|
#include <tracing/timelinemodel_p.h>
|
|
#include <tracing/timelinemodelaggregator.h>
|
|
|
|
using namespace Timeline;
|
|
|
|
static const int NumItems = 32;
|
|
static const qint64 ItemDuration = 1 << 19;
|
|
static const qint64 ItemSpacing = 1 << 20;
|
|
|
|
class DummyModel : public TimelineModel
|
|
{
|
|
Q_OBJECT
|
|
friend class tst_TimelineModel;
|
|
public:
|
|
DummyModel(TimelineModelAggregator *parent);
|
|
DummyModel(QString displayName, TimelineModelAggregator *parent);
|
|
int expandedRow(int) const { return 2; }
|
|
int collapsedRow(int) const { return 1; }
|
|
|
|
protected:
|
|
void loadData();
|
|
};
|
|
|
|
class tst_TimelineModel : public QObject
|
|
{
|
|
Q_OBJECT
|
|
|
|
public:
|
|
const int DefaultRowHeight;
|
|
tst_TimelineModel();
|
|
|
|
private slots:
|
|
void isEmpty();
|
|
void modelId();
|
|
void rowHeight();
|
|
void rowOffset();
|
|
void height();
|
|
void count();
|
|
void times();
|
|
void selectionId();
|
|
void firstLast();
|
|
void expand();
|
|
void hide();
|
|
void displayName();
|
|
void defaultValues();
|
|
void row();
|
|
void colorByHue();
|
|
void colorBySelectionId();
|
|
void colorByFraction();
|
|
void supportedRenderPasses();
|
|
void insertStartEnd();
|
|
void rowCount();
|
|
void prevNext();
|
|
void parentingOfEqualStarts();
|
|
|
|
private:
|
|
TimelineModelAggregator aggregator;
|
|
};
|
|
|
|
DummyModel::DummyModel(TimelineModelAggregator *parent) :
|
|
TimelineModel(parent)
|
|
{
|
|
}
|
|
|
|
DummyModel::DummyModel(QString displayName, TimelineModelAggregator *parent) :
|
|
TimelineModel(parent)
|
|
{
|
|
setDisplayName(displayName);
|
|
}
|
|
|
|
void DummyModel::loadData()
|
|
{
|
|
// TimelineModel is clever enough to sort the longer events before the short ones with the same
|
|
// start time to avoid unnecessary complications when assigning parents. So, if you do e.g.
|
|
// firstIndex(0) you get the first event insered in the third iteration of the loop.
|
|
|
|
for (int i = 0; i < NumItems / 4; ++i) {
|
|
insert((i / 3) * ItemSpacing, ItemDuration * (i + 1) + 2, 4);
|
|
insert((i / 3) * ItemSpacing + 1, ItemDuration * (i + 1), 5);
|
|
insert(i * ItemSpacing / 3 + 1, ItemDuration * (i + 1) + 3, 6);
|
|
insert(i * ItemSpacing / 3 + 2, 1, 7);
|
|
}
|
|
computeNesting();
|
|
setCollapsedRowCount(2);
|
|
setExpandedRowCount(3);
|
|
emit contentChanged();
|
|
}
|
|
|
|
tst_TimelineModel::tst_TimelineModel() :
|
|
DefaultRowHeight(TimelineModel::defaultRowHeight())
|
|
{
|
|
}
|
|
|
|
void tst_TimelineModel::isEmpty()
|
|
{
|
|
DummyModel dummy(&aggregator);
|
|
QVERIFY(dummy.isEmpty());
|
|
dummy.loadData();
|
|
QVERIFY(!dummy.isEmpty());
|
|
dummy.clear();
|
|
QVERIFY(dummy.isEmpty());
|
|
}
|
|
|
|
void tst_TimelineModel::modelId()
|
|
{
|
|
DummyModel dummy(&aggregator);
|
|
QCOMPARE(dummy.modelId(), aggregator.generateModelId() - 1);
|
|
}
|
|
|
|
void tst_TimelineModel::rowHeight()
|
|
{
|
|
DummyModel dummy(&aggregator);
|
|
QCOMPARE(dummy.rowHeight(0), DefaultRowHeight);
|
|
QCOMPARE(dummy.collapsedRowHeight(0), DefaultRowHeight);
|
|
QCOMPARE(dummy.expandedRowHeight(0), DefaultRowHeight);
|
|
|
|
dummy.setExpandedRowHeight(0, 100);
|
|
QCOMPARE(dummy.rowHeight(0), DefaultRowHeight);
|
|
QCOMPARE(dummy.collapsedRowHeight(0), DefaultRowHeight);
|
|
QCOMPARE(dummy.expandedRowHeight(0), 100);
|
|
|
|
dummy.setExpanded(true);
|
|
QCOMPARE(dummy.rowHeight(0), 100);
|
|
|
|
// Cannot set smaller than default
|
|
dummy.setExpandedRowHeight(0, DefaultRowHeight - 1);
|
|
QCOMPARE(dummy.rowHeight(0), DefaultRowHeight);
|
|
|
|
dummy.setExpandedRowHeight(0, 100);
|
|
QCOMPARE(dummy.rowHeight(0), 100);
|
|
|
|
dummy.loadData();
|
|
dummy.setExpandedRowHeight(1, 50);
|
|
QCOMPARE(dummy.rowHeight(0), 100);
|
|
QCOMPARE(dummy.rowHeight(1), 50);
|
|
|
|
// Row heights ignored while collapsed ...
|
|
dummy.setExpanded(false);
|
|
QCOMPARE(dummy.rowHeight(0), DefaultRowHeight);
|
|
QCOMPARE(dummy.rowHeight(1), DefaultRowHeight);
|
|
|
|
// ... but restored when re-expanding
|
|
dummy.setExpanded(true);
|
|
QCOMPARE(dummy.rowHeight(0), 100);
|
|
QCOMPARE(dummy.rowHeight(1), 50);
|
|
|
|
QSignalSpy expandedSpy(&dummy, &TimelineModel::expandedRowHeightChanged);
|
|
dummy.clear();
|
|
QCOMPARE(expandedSpy.count(), 1);
|
|
}
|
|
|
|
void tst_TimelineModel::rowOffset()
|
|
{
|
|
DummyModel dummy(&aggregator);
|
|
QCOMPARE(dummy.rowOffset(0), 0);
|
|
|
|
dummy.loadData();
|
|
dummy.setExpanded(true);
|
|
QCOMPARE(dummy.rowOffset(0), 0);
|
|
QCOMPARE(dummy.rowOffset(1), DefaultRowHeight);
|
|
QCOMPARE(dummy.collapsedRowOffset(1), DefaultRowHeight);
|
|
QCOMPARE(dummy.expandedRowOffset(1), DefaultRowHeight);
|
|
|
|
dummy.setExpandedRowHeight(0, 100);
|
|
QCOMPARE(dummy.rowOffset(0), 0);
|
|
QCOMPARE(dummy.rowOffset(1), 100);
|
|
QCOMPARE(dummy.collapsedRowOffset(1), DefaultRowHeight);
|
|
QCOMPARE(dummy.expandedRowOffset(1), 100);
|
|
QCOMPARE(dummy.expandedRowOffset(2), 100 + DefaultRowHeight);
|
|
|
|
dummy.setExpandedRowHeight(1, 50);
|
|
QCOMPARE(dummy.rowOffset(0), 0);
|
|
QCOMPARE(dummy.rowOffset(1), 100);
|
|
|
|
// Row heights ignored while collapsed ...
|
|
dummy.setExpanded(false);
|
|
QCOMPARE(dummy.rowOffset(0), 0);
|
|
QCOMPARE(dummy.rowOffset(1), DefaultRowHeight);
|
|
QCOMPARE(dummy.collapsedRowOffset(1), DefaultRowHeight);
|
|
QCOMPARE(dummy.expandedRowOffset(1), 100);
|
|
QCOMPARE(dummy.expandedRowOffset(2), 150);
|
|
|
|
// ... but restored when re-expanding
|
|
dummy.setExpanded(true);
|
|
QCOMPARE(dummy.rowOffset(0), 0);
|
|
QCOMPARE(dummy.rowOffset(1), 100);
|
|
}
|
|
|
|
void tst_TimelineModel::height()
|
|
{
|
|
DummyModel dummy(&aggregator);
|
|
int heightAfterLastSignal = 0;
|
|
int heightChangedSignals = 0;
|
|
connect(&dummy, &TimelineModel::heightChanged, [&] {
|
|
++heightChangedSignals;
|
|
heightAfterLastSignal = dummy.height();
|
|
});
|
|
QCOMPARE(dummy.height(), 0);
|
|
|
|
dummy.loadData();
|
|
QCOMPARE(heightChangedSignals, 1);
|
|
QCOMPARE(heightAfterLastSignal, dummy.height());
|
|
QCOMPARE(dummy.height(), 2 * DefaultRowHeight);
|
|
|
|
dummy.setExpanded(true);
|
|
QCOMPARE(heightChangedSignals, 2);
|
|
QCOMPARE(heightAfterLastSignal, dummy.height());
|
|
QCOMPARE(dummy.height(), 3 * DefaultRowHeight);
|
|
|
|
dummy.setExpandedRowHeight(1, 80);
|
|
QCOMPARE(heightChangedSignals, 3);
|
|
QCOMPARE(heightAfterLastSignal, dummy.height());
|
|
QCOMPARE(dummy.height(), 2 * DefaultRowHeight + 80);
|
|
|
|
dummy.setHidden(true);
|
|
QCOMPARE(heightChangedSignals, 4);
|
|
QCOMPARE(heightAfterLastSignal, dummy.height());
|
|
QCOMPARE(dummy.height(), 0);
|
|
|
|
dummy.clear();
|
|
// When clearing the height can change several times in a row.
|
|
QVERIFY(heightChangedSignals > 4);
|
|
QCOMPARE(heightAfterLastSignal, dummy.height());
|
|
|
|
dummy.loadData();
|
|
dummy.setExpanded(true);
|
|
QCOMPARE(heightAfterLastSignal, dummy.height());
|
|
QCOMPARE(dummy.rowHeight(1), DefaultRowHeight); // Make sure the row height gets reset.
|
|
}
|
|
|
|
void tst_TimelineModel::count()
|
|
{
|
|
DummyModel dummy(&aggregator);
|
|
QCOMPARE(dummy.count(), 0);
|
|
dummy.loadData();
|
|
QCOMPARE(dummy.count(), NumItems);
|
|
QSignalSpy emptySpy(&dummy, &TimelineModel::contentChanged);
|
|
dummy.clear();
|
|
QCOMPARE(emptySpy.count(), 1);
|
|
QCOMPARE(dummy.count(), 0);
|
|
}
|
|
|
|
void tst_TimelineModel::times()
|
|
{
|
|
DummyModel dummy(&aggregator);
|
|
dummy.loadData();
|
|
QCOMPARE(dummy.startTime(0), 0);
|
|
QCOMPARE(dummy.duration(0), ItemDuration * 3 + 2);
|
|
QCOMPARE(dummy.endTime(0), ItemDuration * 3 + 2);
|
|
|
|
}
|
|
|
|
void tst_TimelineModel::selectionId()
|
|
{
|
|
DummyModel dummy(&aggregator);
|
|
dummy.loadData();
|
|
QCOMPARE(dummy.selectionId(0), 4);
|
|
}
|
|
|
|
void tst_TimelineModel::firstLast()
|
|
{
|
|
DummyModel dummy(&aggregator);
|
|
QCOMPARE(dummy.firstIndex(0), -1);
|
|
QCOMPARE(dummy.firstIndex(ItemSpacing), -1);
|
|
QCOMPARE(dummy.lastIndex(0), -1);
|
|
QCOMPARE(dummy.lastIndex(ItemSpacing), -1);
|
|
dummy.insert(0, 10, 5); // test special case for only one item
|
|
QCOMPARE(dummy.firstIndex(5), 0);
|
|
QCOMPARE(dummy.lastIndex(5), 0);
|
|
dummy.clear();
|
|
dummy.loadData();
|
|
QCOMPARE(dummy.firstIndex(0), 0);
|
|
QCOMPARE(dummy.firstIndex(ItemSpacing + 1), 0);
|
|
QCOMPARE(dummy.lastIndex(0), -1);
|
|
QCOMPARE(dummy.lastIndex(ItemSpacing + 1), 14);
|
|
QCOMPARE(dummy.firstIndex(ItemDuration * 5000), -1);
|
|
QCOMPARE(dummy.lastIndex(ItemDuration * 5000), NumItems - 1);
|
|
}
|
|
|
|
void tst_TimelineModel::expand()
|
|
{
|
|
DummyModel dummy(&aggregator);
|
|
QSignalSpy spy(&dummy, &TimelineModel::expandedChanged);
|
|
QVERIFY(!dummy.expanded());
|
|
dummy.setExpanded(true);
|
|
QVERIFY(dummy.expanded());
|
|
QCOMPARE(spy.count(), 1);
|
|
dummy.setExpanded(true);
|
|
QVERIFY(dummy.expanded());
|
|
QCOMPARE(spy.count(), 1);
|
|
dummy.setExpanded(false);
|
|
QVERIFY(!dummy.expanded());
|
|
QCOMPARE(spy.count(), 2);
|
|
dummy.setExpanded(false);
|
|
QVERIFY(!dummy.expanded());
|
|
QCOMPARE(spy.count(), 2);
|
|
}
|
|
|
|
void tst_TimelineModel::hide()
|
|
{
|
|
DummyModel dummy(&aggregator);
|
|
QSignalSpy spy(&dummy, &TimelineModel::hiddenChanged);
|
|
QVERIFY(!dummy.hidden());
|
|
dummy.setHidden(true);
|
|
QVERIFY(dummy.hidden());
|
|
QCOMPARE(spy.count(), 1);
|
|
dummy.setHidden(true);
|
|
QVERIFY(dummy.hidden());
|
|
QCOMPARE(spy.count(), 1);
|
|
dummy.setHidden(false);
|
|
QVERIFY(!dummy.hidden());
|
|
QCOMPARE(spy.count(), 2);
|
|
dummy.setHidden(false);
|
|
QVERIFY(!dummy.hidden());
|
|
QCOMPARE(spy.count(), 2);
|
|
}
|
|
|
|
void tst_TimelineModel::displayName()
|
|
{
|
|
QLatin1String name("testest");
|
|
DummyModel dummy(name, &aggregator);
|
|
QSignalSpy spy(&dummy, &TimelineModel::displayNameChanged);
|
|
QCOMPARE(dummy.displayName(), name);
|
|
QCOMPARE(spy.count(), 0);
|
|
dummy.setDisplayName(name);
|
|
QCOMPARE(dummy.displayName(), name);
|
|
QCOMPARE(spy.count(), 0);
|
|
name = QLatin1String("testerei");
|
|
dummy.setDisplayName(name);
|
|
QCOMPARE(dummy.displayName(), name);
|
|
QCOMPARE(spy.count(), 1);
|
|
}
|
|
|
|
void tst_TimelineModel::defaultValues()
|
|
{
|
|
TimelineModel dummy(&aggregator);
|
|
QCOMPARE(dummy.location(0), QVariantMap());
|
|
QCOMPARE(dummy.handlesTypeId(0), false);
|
|
QCOMPARE(dummy.relativeHeight(0), 1.0);
|
|
QCOMPARE(dummy.rowMinValue(0), 0);
|
|
QCOMPARE(dummy.rowMaxValue(0), 0);
|
|
QCOMPARE(dummy.typeId(0), -1);
|
|
QCOMPARE(dummy.color(0), QRgb());
|
|
QCOMPARE(dummy.labels(), QVariantList());
|
|
QCOMPARE(dummy.details(0), QVariantMap());
|
|
QCOMPARE(dummy.collapsedRow(0), 0);
|
|
QCOMPARE(dummy.expandedRow(0), 0);
|
|
}
|
|
|
|
void tst_TimelineModel::row()
|
|
{
|
|
DummyModel dummy(&aggregator);
|
|
dummy.loadData();
|
|
QCOMPARE(dummy.row(0), 1);
|
|
dummy.setExpanded(true);
|
|
QCOMPARE(dummy.row(0), 2);
|
|
}
|
|
|
|
void tst_TimelineModel::colorByHue()
|
|
{
|
|
TimelineModelAggregator aggregator;
|
|
DummyModel dummy(&aggregator);
|
|
QCOMPARE(dummy.colorByHue(10), QColor::fromHsl(10, 150, 166).rgb());
|
|
QCOMPARE(dummy.colorByHue(500), QColor::fromHsl(140, 150, 166).rgb());
|
|
}
|
|
|
|
void tst_TimelineModel::colorBySelectionId()
|
|
{
|
|
DummyModel dummy(&aggregator);
|
|
dummy.loadData();
|
|
QCOMPARE(dummy.colorBySelectionId(5), QColor::fromHsl(6 * 25, 150, 166).rgb());
|
|
}
|
|
|
|
void tst_TimelineModel::colorByFraction()
|
|
{
|
|
DummyModel dummy(&aggregator);
|
|
QCOMPARE(dummy.colorByFraction(0.5), QColor::fromHsl(0.5 * 96 + 10, 150, 166).rgb());
|
|
}
|
|
|
|
void tst_TimelineModel::supportedRenderPasses()
|
|
{
|
|
DummyModel dummy(&aggregator);
|
|
QVERIFY(!dummy.supportedRenderPasses().isEmpty());
|
|
}
|
|
|
|
void tst_TimelineModel::insertStartEnd()
|
|
{
|
|
DummyModel dummy(&aggregator);
|
|
int id = dummy.insertStart(10, 0);
|
|
dummy.insertEnd(id, 10);
|
|
QCOMPARE(dummy.startTime(id), 10);
|
|
QCOMPARE(dummy.endTime(id), 20);
|
|
int id2 = dummy.insertStart(5, 3);
|
|
dummy.insertEnd(id2, 10);
|
|
QCOMPARE(dummy.startTime(id2), 5);
|
|
QCOMPARE(dummy.endTime(id2), 15);
|
|
|
|
int id3 = dummy.insertStart(10, 1);
|
|
QVERIFY(id3 > id);
|
|
dummy.insertEnd(id3, 20);
|
|
|
|
// Make sure that even though the new range is larger than the one pointed to by id, we still
|
|
// get to search from id when looking up a timestamp which is in both ranges.
|
|
QCOMPARE(dummy.firstIndex(11), id);
|
|
}
|
|
|
|
void tst_TimelineModel::rowCount()
|
|
{
|
|
DummyModel dummy(&aggregator);
|
|
QSignalSpy contentSpy(&dummy, &TimelineModel::contentChanged);
|
|
QCOMPARE(dummy.rowCount(), 1);
|
|
dummy.setExpanded(true);
|
|
QCOMPARE(dummy.rowCount(), 1);
|
|
dummy.loadData();
|
|
QCOMPARE(contentSpy.count(), 1);
|
|
QCOMPARE(dummy.rowCount(), 3);
|
|
dummy.setExpanded(false);
|
|
QCOMPARE(dummy.rowCount(), 2);
|
|
dummy.clear();
|
|
QCOMPARE(contentSpy.count(), 2);
|
|
QCOMPARE(dummy.rowCount(), 1);
|
|
}
|
|
|
|
void tst_TimelineModel::prevNext()
|
|
{
|
|
DummyModel dummy(&aggregator);
|
|
QCOMPARE(dummy.nextItemBySelectionId(5, 10, 5), -1);
|
|
QCOMPARE(dummy.prevItemBySelectionId(5, 10, 5), -1);
|
|
|
|
dummy.loadData();
|
|
QCOMPARE(dummy.nextItemBySelectionId(5, 5000 * ItemSpacing, -1), 3);
|
|
QCOMPARE(dummy.prevItemBySelectionId(5, 5000 * ItemSpacing, -1), 28);
|
|
|
|
QCOMPARE(dummy.nextItemBySelectionId(15, 10, -1), -1);
|
|
QCOMPARE(dummy.prevItemBySelectionId(15, 10, -1), -1);
|
|
|
|
QCOMPARE(dummy.nextItemBySelectionId(5, 10, -1), 15);
|
|
QCOMPARE(dummy.prevItemBySelectionId(5, 10, -1), 6);
|
|
QCOMPARE(dummy.nextItemBySelectionId(5, 10, 5), 6);
|
|
QCOMPARE(dummy.prevItemBySelectionId(5, 10, 5), 4);
|
|
QCOMPARE(dummy.nextItemByTypeId(-1, 10, 5), 6);
|
|
QCOMPARE(dummy.prevItemByTypeId(-1, 10, 5), 4);
|
|
}
|
|
|
|
void tst_TimelineModel::parentingOfEqualStarts()
|
|
{
|
|
DummyModel dummy(&aggregator);
|
|
// Trick it so that it cannot reorder the events and has to parent them in the "wrong" way ...
|
|
QCOMPARE(dummy.insert(1, 10, 998), 0);
|
|
QCOMPARE(dummy.insertStart(1, 999), 1);
|
|
dummy.insertEnd(1, 20);
|
|
dummy.computeNesting();
|
|
|
|
// .. which is reflected in the resulting order.
|
|
QCOMPARE(dummy.selectionId(0), 998);
|
|
QCOMPARE(dummy.selectionId(1), 999);
|
|
QCOMPARE(dummy.firstIndex(10), 0);
|
|
QCOMPARE(dummy.lastIndex(2), 1);
|
|
}
|
|
|
|
QTEST_GUILESS_MAIN(tst_TimelineModel)
|
|
|
|
#include "tst_timelinemodel.moc"
|