File indexing completed on 2025-01-19 03:42:37
0001 /* 0002 * SPDX-FileCopyrightText: 2020 Arjen Hiemstra <ahiemstra@heimr.nl> 0003 * 0004 * SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL 0005 */ 0006 0007 #include <QTest> 0008 0009 #include "datasource/HistoryProxySource.h" 0010 #include "datasource/ModelSource.h" 0011 #include "datasource/SingleValueSource.h" 0012 0013 #define qs QStringLiteral 0014 0015 class TestModel : public QAbstractListModel 0016 { 0017 Q_OBJECT 0018 Q_PROPERTY(int minimum READ minimum NOTIFY minimumChanged) 0019 Q_PROPERTY(int maximum READ maximum NOTIFY maximumChanged) 0020 0021 public: 0022 TestModel(QObject *parent = nullptr) 0023 : QAbstractListModel(parent) 0024 { 0025 m_items.fill(1, 10); 0026 } 0027 0028 int rowCount(const QModelIndex &parent) const override 0029 { 0030 if (parent.isValid()) { 0031 return 0; 0032 } else { 0033 return 10; 0034 } 0035 } 0036 0037 QVariant data(const QModelIndex &index, int role) const override 0038 { 0039 Q_UNUSED(role) 0040 0041 if (!checkIndex(index, CheckIndexOption::IndexIsValid | CheckIndexOption::ParentIsInvalid)) { 0042 qDebug() << "index invalid"; 0043 return QVariant{}; 0044 } 0045 0046 return m_items.at(index.row()); 0047 } 0048 0049 void set(int item, int value) 0050 { 0051 if (item < 0 || item >= 10) { 0052 return; 0053 } 0054 0055 m_items[item] = value; 0056 Q_EMIT dataChanged(index(item, 0), index(item, 0)); 0057 Q_EMIT minimumChanged(); 0058 Q_EMIT maximumChanged(); 0059 } 0060 0061 int minimum() 0062 { 0063 return *std::min_element(m_items.cbegin(), m_items.cend()); 0064 } 0065 0066 int maximum() 0067 { 0068 return *std::max_element(m_items.cbegin(), m_items.cend()); 0069 } 0070 0071 Q_SIGNAL void minimumChanged(); 0072 Q_SIGNAL void maximumChanged(); 0073 0074 private: 0075 QList<int> m_items; 0076 }; 0077 0078 class HistoryProxySourceTest : public QObject 0079 { 0080 Q_OBJECT 0081 0082 private Q_SLOTS: 0083 void testCreate() 0084 { 0085 // Basic creation should create an empty source. 0086 auto source = new HistoryProxySource{}; 0087 0088 QCOMPARE(source->itemCount(), 0); 0089 QCOMPARE(source->item(0), QVariant{}); 0090 QCOMPARE(source->minimum(), QVariant{}); 0091 QCOMPARE(source->maximum(), QVariant{}); 0092 QCOMPARE(source->source(), nullptr); 0093 } 0094 0095 void testWithValue() 0096 { 0097 auto valueSource = std::make_unique<SingleValueSource>(); 0098 0099 // Simple case first, using default values for maximum history and fill 0100 // mode. This should lead to 10 history items with the most recent value 0101 // being the first item. 0102 auto historySource = std::make_unique<HistoryProxySource>(); 0103 historySource->setSource(valueSource.get()); 0104 historySource->setMaximumHistory(10); 0105 historySource->setFillMode(HistoryProxySource::DoNotFill); 0106 0107 for (int i = 0; i < 15; i++) { 0108 valueSource->setValue(i); 0109 QCOMPARE(historySource->itemCount(), std::min(i + 1, 10)); 0110 0111 for (int item = 0; item < historySource->itemCount(); ++item) { 0112 QCOMPARE(historySource->item(item), i - item); 0113 } 0114 } 0115 0116 // Minimum and maximum should be minimum and maximum of current history 0117 // items. 0118 QCOMPARE(historySource->minimum(), 5); 0119 QCOMPARE(historySource->maximum(), 14); 0120 0121 // Clearing will reset the history. 0122 QCOMPARE(historySource->itemCount(), 10); 0123 historySource->clear(); 0124 QCOMPARE(historySource->itemCount(), 0); 0125 0126 valueSource->setValue(5); 0127 0128 // With an interval, we should be getting maximumHistory items of the 0129 // same value if we simply wait for at least interval * 10 milliseconds. 0130 historySource->setInterval(50); 0131 0132 QTest::qWait(750); 0133 0134 QCOMPARE(historySource->itemCount(), 10); 0135 for (int i = 0; i < historySource->itemCount(); ++i) { 0136 QCOMPARE(historySource->item(i), 5); 0137 } 0138 0139 historySource->setInterval(0); 0140 0141 // Increasing history size does not delete existing history. 0142 historySource->setMaximumHistory(20); 0143 0144 QCOMPARE(historySource->itemCount(), 10); 0145 0146 // Changing fill mode resets history and should now report 0147 // maximumHistory number of items. Empty items should use the same 0148 // QVariant type as the value source does. 0149 0150 historySource->setFillMode(HistoryProxySource::FillFromStart); 0151 0152 QCOMPARE(historySource->item(0), QVariant{QMetaType(QMetaType::Int)}); 0153 QCOMPARE(historySource->itemCount(), 20); 0154 QCOMPARE(historySource->item(19), QVariant{QMetaType(QMetaType::Int)}); 0155 0156 // Using the FillFromEnd fill mode adds items to the end while itemCount 0157 // is less than maximumHistory. 0158 0159 historySource->setFillMode(HistoryProxySource::FillFromEnd); 0160 QCOMPARE(historySource->itemCount(), 20); 0161 0162 for (int i = 0; i < 19; ++i) { 0163 valueSource->setValue(i); 0164 QCOMPARE(historySource->item(0), QVariant{QMetaType(QMetaType::Int)}); 0165 for (int item = 19; item > 1; --item) { 0166 if ((item - 19) + i < 0) { 0167 QCOMPARE(historySource->item(item), QVariant{QMetaType(QMetaType::Int)}); 0168 } else { 0169 QCOMPARE(historySource->item(item), 19 - item); 0170 } 0171 } 0172 } 0173 } 0174 0175 void testWithModel() 0176 { 0177 auto model = std::make_unique<TestModel>(); 0178 auto modelSource = std::make_unique<ModelSource>(); 0179 modelSource->setModel(model.get()); 0180 modelSource->setRole(Qt::DisplayRole); 0181 0182 auto historySource = std::make_unique<HistoryProxySource>(); 0183 historySource->setSource(modelSource.get()); 0184 historySource->setMaximumHistory(10); 0185 historySource->setFillMode(HistoryProxySource::DoNotFill); 0186 0187 // When there is a source with an itemCount > 1, we can use setItem to 0188 // indicate which item should be watched. 0189 historySource->setItem(2); 0190 0191 // When we then change the model, the history source should record an 0192 // item. 0193 for (int i = 0; i < 10; ++i) { 0194 model->set(2, i); 0195 QCOMPARE(historySource->itemCount(), i + 1); 0196 for (int item = 0; item < historySource->itemCount(); ++item) { 0197 QCOMPARE(historySource->item(item), i - item); 0198 } 0199 } 0200 0201 historySource->clear(); 0202 0203 model->set(2, 5); 0204 model->set(2, 2); 0205 0206 // When the model has a minimum and a maximum property, those will be 0207 // used for the history source's minimum and maximum rather than 0208 // calculating it based on the items in the history. 0209 0210 QCOMPARE(historySource->minimum(), 1); 0211 QCOMPARE(historySource->maximum(), 2); 0212 } 0213 }; 0214 0215 QTEST_GUILESS_MAIN(HistoryProxySourceTest) 0216 0217 #include "HistoryProxySourceTest.moc"