Files
dbc/tests/dbc_tree_model_test.cpp
T
2026-10-06 17:14:50 -04:00

137 lines
7.2 KiB
C++

#include "dbc_parser.h"
#include "dbc_tree_builder.h"
#include "dbc_tree_model.h"
#include <QAbstractItemModelTester>
#include <QSignalSpy>
#include <QTemporaryFile>
#include <QtTest>
#include <limits>
static std::unique_ptr<TreeNode> ParsedTree() {
QTemporaryFile fixture;
if (!fixture.open()) throw std::runtime_error("Fixture creation failed");
fixture.write("BO_ 256 Status: 8 ECU\n SG_ State : 0|8@1+ (1,0) [0|255] \"rpm\" ECU\n"
" SG_ Other : 8|8@1+ (1,0) [0|255] \"\" ECU\n"
"BO_ 257 Second: 8 ECU\n SG_ Value : 0|8@1+ (1,0) [0|255] \"\" ECU\n"
"CM_ BO_ 256 \"Frame comment\";\nCM_ SG_ 256 State \"Signal comment\";\n"
"VAL_ 256 State -1 \"Negative\" 0 \"Off\" 18446744073709551615 \"Maximum\";\n");
fixture.flush();
return DbcTreeBuilder().Build(DbcParser().ParseFile(fixture.fileName().toStdString()));
}
class ModelTest : public QObject {
Q_OBJECT
private Q_SLOTS:
void navigation() {
DbcTreeModel model;
QAbstractItemModelTester tester(&model, QAbstractItemModelTester::FailureReportingMode::QtTest);
QCOMPARE(model.rowCount(), 0);
model.SetTree(ParsedTree());
QCOMPARE(model.rowCount(), 2);
for (int row = 0; row < model.rowCount(); ++row) {
const QModelIndex frame = model.index(row, 0);
for (int column = 0; column < model.columnCount(); ++column) {
const QModelIndex frameColumn = model.index(row, column);
QVERIFY(!model.parent(frameColumn).isValid());
QCOMPARE(model.rowCount(frameColumn), column == 0 ? (row == 0 ? 2 : 1) : 0);
for (int signalRow = 0; signalRow < model.rowCount(frame); ++signalRow) {
const QModelIndex signal = model.index(signalRow, column, frame);
QCOMPARE(model.parent(signal), frame);
QCOMPARE(model.rowCount(signal), 0);
QVERIFY(!model.index(0, 0, signal).isValid());
QCOMPARE(model.flags(signal), Qt::ItemIsEnabled | Qt::ItemIsSelectable);
}
}
}
QVERIFY(!model.index(-1, 0).isValid());
QVERIFY(!model.index(2, 0).isValid());
QVERIFY(!model.index(0, -1).isValid());
QVERIFY(!model.index(0, model.columnCount()).isValid());
QVERIFY(!model.index(0, 0, model.index(0, 1)).isValid());
QVERIFY(!model.parent({}).isValid());
QVERIFY(!model.data({}).isValid());
QCOMPARE(model.flags({}), Qt::NoItemFlags);
DbcTreeModel other;
other.SetTree(ParsedTree());
const QModelIndex foreign = other.index(0, 0);
QVERIFY(!model.index(0, 0, foreign).isValid());
QVERIFY(!model.parent(foreign).isValid());
QCOMPARE(model.rowCount(foreign), 0);
QCOMPARE(model.columnCount(foreign), 0);
QVERIFY(!model.data(foreign).isValid());
QCOMPARE(model.flags(foreign), Qt::NoItemFlags);
}
void metadata() {
DbcTreeModel model;
model.SetTree(ParsedTree());
const QModelIndex frame = model.index(0, 0);
const QModelIndex signal = model.index(0, 0, frame);
QCOMPARE(model.data(frame).toString(), QString("Status"));
QCOMPARE(model.data(model.index(0, DbcTreeModel::CanId)).toString(), QString("0X100"));
QCOMPARE(model.data(frame, DbcTreeModel::CanIdRole).toUInt(), 256U);
QCOMPARE(model.data(frame, DbcTreeModel::PayloadLengthRole).toInt(), 8);
QCOMPARE(model.data(signal, DbcTreeModel::UnitRole).toString(), QString("rpm"));
const QVariantList expectedSignal = {"State", QVariant(), QVariant(), 0U, 8U,
"Intel", "Unsigned", "rpm", "Signal comment"};
const QVariantList expectedFrame = {"Status", "0X100", 8, QVariant(), QVariant(),
QVariant(), QVariant(), QVariant(), "Frame comment"};
for (int column = 0; column < model.columnCount(); ++column) {
QCOMPARE(model.data(model.index(0, column, frame)), expectedSignal.at(column));
QCOMPARE(model.data(model.index(0, column)), expectedFrame.at(column));
}
QCOMPARE(model.data(frame, DbcTreeModel::NodeTypeRole).toInt(), static_cast<int>(NodeType::Frame));
QCOMPARE(model.data(signal, DbcTreeModel::NodeTypeRole).toInt(), static_cast<int>(NodeType::Signal));
QCOMPARE(model.data(frame, DbcTreeModel::ExtendedRole).toBool(), false);
QVERIFY(!model.data(frame, DbcTreeModel::ValueDescriptionsRole).isValid());
QVERIFY(model.data(model.index(1, 0, frame), DbcTreeModel::ValueDescriptionsRole).toList().isEmpty());
QCOMPARE(model.data(signal, Qt::ToolTipRole).toString(), QString("Signal comment"));
QCOMPARE(model.data(signal, DbcTreeModel::StartBitRole).toUInt(), 0U);
QCOMPARE(model.data(signal, DbcTreeModel::BitLengthRole).toUInt(), 8U);
QCOMPARE(model.data(signal, DbcTreeModel::LittleEndianRole).toBool(), true);
QCOMPARE(model.data(signal, DbcTreeModel::SignedRole).toBool(), false);
QVERIFY(!model.data(signal, DbcTreeModel::CanIdRole).isValid());
QVERIFY(!model.data(frame, DbcTreeModel::UnitRole).isValid());
QVERIFY(!model.data(frame, Qt::EditRole).isValid());
const QVariantList values = model.data(signal, DbcTreeModel::ValueDescriptionsRole).toList();
QCOMPARE(values.size(), 3);
QCOMPARE(values.at(0).toMap().value("value").toLongLong(), -1LL);
QCOMPARE(values.at(2).toMap().value("value").toULongLong(), std::numeric_limits<qulonglong>::max());
QCOMPARE(values.at(2).toMap().value("description").toString(), QString("Maximum"));
for (int column = 0; column < model.columnCount(); ++column) {
QVERIFY(model.headerData(column, Qt::Horizontal).isValid());
QCOMPARE(model.data(model.index(0, column, frame), DbcTreeModel::ValueDescriptionsRole), QVariant(values));
}
QVERIFY(!model.headerData(-1, Qt::Horizontal).isValid());
QVERIFY(!model.headerData(model.columnCount(), Qt::Horizontal).isValid());
QVERIFY(!model.headerData(0, Qt::Vertical).isValid());
}
void replacement() {
DbcTreeModel model;
QAbstractItemModelTester tester(&model, QAbstractItemModelTester::FailureReportingMode::QtTest);
QSignalSpy resets(&model, &QAbstractItemModel::modelReset);
model.SetTree(ParsedTree());
QPersistentModelIndex frame(model.index(0, 0));
QPersistentModelIndex signal(model.index(0, 4, frame));
model.SetTree(ParsedTree());
QVERIFY(!frame.isValid());
QVERIFY(!signal.isValid());
QCOMPARE(model.rowCount(), 2);
QPersistentModelIndex replacement(model.index(1, 0));
model.SetTree(nullptr);
QVERIFY(!replacement.isValid());
QCOMPARE(model.rowCount(), 0);
QVERIFY(!model.index(0, 0).isValid());
model.SetTree(nullptr);
QCOMPARE(resets.count(), 4);
try {
model.SetTree(std::unique_ptr<TreeNode>(new TreeNode(FrameInfo())));
QFAIL("A frame cannot be the invisible model root");
} catch (const std::invalid_argument &) {
}
QCOMPARE(resets.count(), 4);
}
};
QTEST_GUILESS_MAIN(ModelTest)
#include "dbc_tree_model_test.moc"