Revision control

Copy as Markdown

// Copyright (C) 2024 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtGraphs/QBarSeries>
#include <QtGraphs/QBarSet>
#include <QtGraphs/QValueAxis>
#include <QtGraphs/QBarCategoryAxis>
#include <QtTest/QtTest>
// QBarSeries::componentComplete() is protected; expose it so the test can emulate what the QML
// engine does after creating the object.
class CompleteProbe : public QBarSeries
{
public:
using QBarSeries::componentComplete;
};
class tst_bars : public QObject
{
Q_OBJECT
private slots:
void initTestCase();
void cleanupTestCase();
void init();
void cleanup();
void construct();
void modifySeries();
void initialProperties();
void initializeProperties();
void invalidProperties();
void clearThenComplete();
private:
QBarSeries *m_series;
};
void tst_bars::initTestCase() {}
void tst_bars::cleanupTestCase() {}
void tst_bars::init()
{
m_series = new QBarSeries();
}
void tst_bars::cleanup()
{
delete m_series;
}
void tst_bars::construct()
{
QBarSeries *series = new QBarSeries();
QVERIFY(series);
delete series;
}
void tst_bars::initialProperties()
{
QVERIFY(m_series);
// Properties from QBarSeries
QCOMPARE(m_series->barWidth(), 0.5);
QCOMPARE(m_series->count(), 0);
QCOMPARE(m_series->labelsVisible(), false);
QCOMPARE(m_series->labelsFormat(), "");
QCOMPARE(m_series->labelsPosition(), QBarSeries::LabelsPosition::Center);
QCOMPARE(m_series->labelsMargin(), 0);
QCOMPARE(m_series->labelsAngle(), 0);
QCOMPARE(m_series->labelsPrecision(), 6);
QCOMPARE(m_series->seriesColors(), {});
// Properties from QAbstractSeries
QCOMPARE(m_series->name(), "");
QCOMPARE(m_series->isVisible(), true);
QCOMPARE(m_series->isSelectable(), false);
QCOMPARE(m_series->isHoverable(), false);
QCOMPARE(m_series->opacity(), 1.0);
QCOMPARE(m_series->valuesMultiplier(), 1.0);
}
void tst_bars::initializeProperties()
{
QVERIFY(m_series);
QSignalSpy spy0(m_series, &QBarSeries::barWidthChanged);
QSignalSpy spy1(m_series, &QBarSeries::labelsVisibleChanged);
QSignalSpy spy2(m_series, &QBarSeries::labelsFormatChanged);
QSignalSpy spy3(m_series, &QBarSeries::labelsPositionChanged);
QSignalSpy spy4(m_series, &QBarSeries::labelsMarginChanged);
QSignalSpy spy5(m_series, &QBarSeries::labelsAngleChanged);
QSignalSpy spy6(m_series, &QBarSeries::labelsPrecisionChanged);
QSignalSpy spy7(m_series, &QBarSeries::seriesColorsChanged);
QSignalSpy spy8(m_series, &QBarSeries::borderColorsChanged);
QSignalSpy spy9(m_series, &QBarSeries::nameChanged);
QSignalSpy spy10(m_series, &QBarSeries::visibleChanged);
QSignalSpy spy11(m_series, &QBarSeries::selectableChanged);
QSignalSpy spy12(m_series, &QBarSeries::hoverableChanged);
QSignalSpy spy13(m_series, &QBarSeries::opacityChanged);
QSignalSpy spy14(m_series, &QBarSeries::valuesMultiplierChanged);
auto colors1 = QList<QColor> {QColor(255, 255, 255)};
auto colors2 = QList<QColor> {QColor(0, 0, 0)};
auto set = new QBarSet(this);
m_series->setBarWidth(0.75);
m_series->setLabelsVisible(true);
m_series->setLabelsFormat("i");
m_series->setLabelsPosition(QBarSeries::LabelsPosition::InsideBase);
m_series->setLabelsMargin(10.0);
m_series->setLabelsAngle(45.0);
m_series->setLabelsPrecision(10);
m_series->append(set);
m_series->setSeriesColors(colors1);
m_series->setBorderColors(colors2);
m_series->setName("BarSeries");
m_series->setVisible(false);
m_series->setSelectable(true);
m_series->setHoverable(true);
m_series->setOpacity(0.5);
m_series->setValuesMultiplier(0.5);
QCOMPARE(m_series->barWidth(), 0.75);
QCOMPARE(m_series->count(), 1);
QCOMPARE(m_series->labelsVisible(), true);
QCOMPARE(m_series->labelsFormat(), "i");
QCOMPARE(m_series->labelsPosition(), QBarSeries::LabelsPosition::InsideBase);
QCOMPARE(m_series->labelsMargin(), 10.0);
QCOMPARE(m_series->labelsAngle(), 45.0);
QCOMPARE(m_series->labelsPrecision(), 10);
QCOMPARE(m_series->seriesColors(), colors1);
QCOMPARE(m_series->borderColors(), colors2);
QCOMPARE(m_series->name(), "BarSeries");
QCOMPARE(m_series->isVisible(), false);
QCOMPARE(m_series->isSelectable(), true);
QCOMPARE(m_series->isHoverable(), true);
QCOMPARE(m_series->opacity(), 0.5);
QCOMPARE(m_series->valuesMultiplier(), 0.5);
QCOMPARE(spy0.size(), 1);
QCOMPARE(spy1.size(), 1);
QCOMPARE(spy2.size(), 1);
QCOMPARE(spy3.size(), 1);
QCOMPARE(spy4.size(), 1);
QCOMPARE(spy5.size(), 1);
QCOMPARE(spy6.size(), 1);
QCOMPARE(spy7.size(), 1);
QCOMPARE(spy8.size(), 1);
QCOMPARE(spy9.size(), 1);
QCOMPARE(spy10.size(), 1);
QCOMPARE(spy11.size(), 1);
QCOMPARE(spy12.size(), 1);
QCOMPARE(spy13.size(), 1);
QCOMPARE(spy14.size(), 1);
}
void tst_bars::invalidProperties()
{
QVERIFY(m_series);
m_series->setBarWidth(2.0); // range 0...1
m_series->setValuesMultiplier(2.0); // range 0...1
QCOMPARE(m_series->barWidth(), 1.0);
QCOMPARE(m_series->valuesMultiplier(), 1.0);
m_series->setBarWidth(-1.0); // range 0...1
m_series->setValuesMultiplier(-1.0); // range 0...1
QCOMPARE(m_series->barWidth(), 0.0);
QCOMPARE(m_series->valuesMultiplier(), 0.0);
}
void tst_bars::modifySeries()
{
QVERIFY(m_series);
QSignalSpy spy0(m_series, &QBarSeries::barsetsAdded);
QSignalSpy spy1(m_series, &QBarSeries::barsetsReplaced);
QSignalSpy spy2(m_series, &QBarSeries::barsetsRemoved);
QSignalSpy spy3(m_series, &QBarSeries::countChanged);
QSignalSpy spy4(m_series, &QBarSeries::setValueChanged);
QSignalSpy spy5(m_series, &QBarSeries::setValueAdded);
QSignalSpy spy6(m_series, &QBarSeries::setValueRemoved);
QSignalSpy spy7(m_series, &QBarSeries::barSetsChanged); // unused
auto set1 = new QBarSet("Set 1", m_series);
auto set2 = new QBarSet("Set 2", m_series);
auto set3 = new QBarSet("Set 3", m_series);
auto set4 = new QBarSet("Set 4", m_series);
auto set5 = new QBarSet("Set 5", m_series);
auto set6 = new QBarSet("Set 6", m_series);
auto set7 = new QBarSet("Set 7", m_series);
auto newSet = new QBarSet("New Set", m_series);
auto pointerBarset = new QBarSet("Set pointer", m_series);
auto insertSet = new QBarSet("insertSet", m_series);
// append
m_series->append(set1);
m_series->append(set2);
m_series->append(set3);
m_series->append(set4);
m_series->append(set5);
m_series->append(set6);
m_series->append(set7);
auto sets = m_series->barSets();
QCOMPARE(sets[0], set1);
QCOMPARE(sets[1], set2);
QCOMPARE(sets[2], set3);
QCOMPARE(sets[3], set4);
QCOMPARE(sets[4], set5);
QCOMPARE(sets[5], set6);
QCOMPARE(sets[6], set7);
QCOMPARE(spy0.size(), 7);
QCOMPARE(spy3.size(), 7);
QCOMPARE(spy7.size(), 7);
// pointer remove
m_series->remove(set3);
sets = m_series->barSets();
QCOMPARE(sets[0], set1);
QCOMPARE(sets[1], set2);
QCOMPARE(sets[2], set4);
QCOMPARE(sets[3], set5);
QCOMPARE(sets[4], set6);
QCOMPARE(sets[5], set7);
QCOMPARE(spy2.size(), 1);
QCOMPARE(spy3.size(), 8);
QCOMPARE(spy7.size(), 8);
// index remove
QVERIFY(!m_series->remove(-1));
QVERIFY(!m_series->remove(100));
QVERIFY(m_series->remove(2));
sets = m_series->barSets();
QCOMPARE(sets[0], set1);
QCOMPARE(sets[1], set2);
QCOMPARE(sets[2], set5);
QCOMPARE(sets[3], set6);
QCOMPARE(sets[4], set7);
QCOMPARE(spy2.size(), 2);
QCOMPARE(spy3.size(), 9);
QCOMPARE(spy7.size(), 9);
// index replace
m_series->replace(2, newSet);
sets = m_series->barSets();
QCOMPARE(sets[0], set1);
QCOMPARE(sets[1], set2);
QCOMPARE(sets[2], newSet);
QCOMPARE(sets[3], set6);
QCOMPARE(sets[4], set7);
QCOMPARE(spy1.size(), 1);
QCOMPARE(spy7.size(), 10);
// multiple remove
m_series->removeMultiple(-1, -1);
m_series->removeMultiple(0, 100);
m_series->removeMultiple(1, 2);
sets = m_series->barSets();
QCOMPARE(sets.size(), 3);
QCOMPARE(sets[0], set1);
QCOMPARE(sets[1], set6);
QCOMPARE(sets[2], set7);
QCOMPARE(spy2.size(), 5);
QCOMPARE(spy3.size(), 12);
QCOMPARE(spy7.size(), 12);
// pointer replace
QVERIFY(!m_series->replace(nullptr, nullptr));
QVERIFY(!m_series->replace(pointerBarset, pointerBarset));
QVERIFY(m_series->replace(set6, pointerBarset));
sets = m_series->barSets();
QCOMPARE(sets[0], set1);
QCOMPARE(sets[1], pointerBarset);
QCOMPARE(sets[2], set7);
QCOMPARE(spy1.size(), 2);
//at
auto atSet1 = m_series->at(2);
auto atSet2 = m_series->at(-10);
auto atSet3 = m_series->at(100);
QCOMPARE(atSet1, set7);
QCOMPARE(atSet2, nullptr);
QCOMPARE(atSet3, nullptr);
//find
auto fSet1 = m_series->find(newSet);
auto fSet2 = m_series->find(set2);
auto fSet3 = m_series->find(pointerBarset);
auto fSet4 = m_series->find(set7);
QCOMPARE(fSet4, 2);
QCOMPARE(fSet1, -1);
QCOMPARE(fSet2, -1);
QCOMPARE(fSet3, 1);
// take
QVERIFY(m_series->take(pointerBarset));
QCOMPARE(m_series->count(), 2);
QCOMPARE(spy2.size(), 7);
QCOMPARE(spy3.size(), 14);
QCOMPARE(spy7.size(), 14);
// full replace
QList<QBarSet *> bars = {new QBarSet("new set 1", m_series),
new QBarSet("new set 2", m_series),
new QBarSet("new set 3", m_series)};
QVERIFY(m_series->replace(bars));
sets = m_series->barSets();
QCOMPARE(sets[0], bars[0]);
QCOMPARE(sets[1], bars[1]);
QCOMPARE(sets[2], bars[2]);
QCOMPARE(spy7.size(), 16);
//append value to barset
for (qsizetype i = 0; i < m_series->barSets().size(); ++i)
m_series->barSets().at(i)->append(10);
QCOMPARE(spy5.size(), 3);
//replace value from barset
for (qsizetype i = 0; i < m_series->barSets().size(); ++i)
m_series->barSets().at(i)->replace(0, 20);
QCOMPARE(spy4.size(), 3);
//remove value from barset
for (qsizetype i = 0; i < m_series->barSets().size(); ++i)
m_series->barSets().at(i)->remove(0);
QCOMPARE(spy6.size(), 3);
//insert
m_series->insert(0, insertSet);
sets = m_series->barSets();
QCOMPARE(sets[0], insertSet);
QCOMPARE(spy7.size(), 17);
m_series->barSets().at(0)->append(10);
m_series->barSets().at(0)->replace(0, 20);
m_series->barSets().at(0)->remove(0);
QCOMPARE(spy0.size(), 8);
QCOMPARE(spy1.size(), 3);
QCOMPARE(spy2.size(), 9);
QCOMPARE(spy3.size(), 17);
QCOMPARE(spy4.size(), 4);
QCOMPARE(spy5.size(), 4);
QCOMPARE(spy6.size(), 4);
QCOMPARE(spy7.size(), 17);
}
void tst_bars::clearThenComplete()
{
// clear() must detach removed sets from the series. Otherwise componentComplete() finds them
// among the children and appends them again, and they dangle once the deferred delete runs.
CompleteProbe series;
QPointer<QBarSet> set1 = new QBarSet(QStringLiteral("set1"));
QPointer<QBarSet> set2 = new QBarSet(QStringLiteral("set2"));
series.append(set1);
series.append(set2);
QCOMPARE(series.count(), 2);
series.clear();
QCOMPARE(series.count(), 0);
QVERIFY(series.findChildren<QBarSet *>(Qt::FindDirectChildrenOnly).isEmpty());
series.componentComplete();
QCOMPARE(series.count(), 0);
QVERIFY(series.barSets().isEmpty());
QCoreApplication::sendPostedEvents(nullptr, QEvent::DeferredDelete);
QVERIFY(!set1);
QVERIFY(!set2);
QVERIFY(series.barSets().isEmpty());
}
QTEST_MAIN(tst_bars)
#include "tst_bars.moc"