File indexing completed on 2024-10-06 06:35:10

0001 /*
0002     File                 : BLFFilterTest.cpp
0003     Project              : LabPlot
0004     Description          : Tests for the BLF Filter
0005     --------------------------------------------------------------------
0006     SPDX-FileCopyrightText: 2023 Martin Marmsoler <martin.marmsoler@gmail.com>
0007 
0008     SPDX-License-Identifier: GPL-2.0-or-later
0009 */
0010 
0011 #include "BLFFilterTest.h"
0012 #include "backend/datasources/filters/CANFilterPrivate.h"
0013 #include "backend/datasources/filters/VectorBLFFilter.h"
0014 #include "backend/spreadsheet/Spreadsheet.h"
0015 #include "qtestcase.h"
0016 #include <math.h>
0017 
0018 #ifdef HAVE_VECTOR_BLF
0019 
0020 #include <Vector/BLF.h>
0021 
0022 static const std::string PRIMITIVE_DBC =
0023     R"(VERSION "1.0.0"
0024 
0025 NS_ :
0026 
0027 BS_:
0028 
0029 BU_: DBG DRIVER IO MOTOR SENSOR
0030 
0031 )";
0032 
0033 // ##########################################################################################################
0034 // ##### Helper functions ###################################################################################
0035 // ##########################################################################################################
0036 void BLFFilterTest::createDBCFile(const QString& filename, const std::string& content) {
0037     auto* file = std::fopen(filename.toStdString().c_str(), "w");
0038     QVERIFY(file);
0039     std::fputs(PRIMITIVE_DBC.c_str(), file);
0040     std::fputs(content.c_str(), file);
0041     std::fclose(file);
0042 }
0043 
0044 Vector::BLF::CanMessage2* BLFFilterTest::createCANMessage(uint32_t id, uint64_t timestamp, const std::vector<uint8_t>& data) {
0045     auto* canMessage = new Vector::BLF::CanMessage2();
0046     canMessage->channel = 1;
0047     canMessage->flags = 1; // TX
0048     canMessage->dlc = std::min<uint8_t>(data.size(), 8);
0049     canMessage->id = id;
0050     canMessage->objectTimeStamp = timestamp;
0051     canMessage->objectFlags = Vector::BLF::ObjectHeader::ObjectFlags::TimeOneNans;
0052     if (canMessage->data.size() < canMessage->dlc)
0053         canMessage->data.resize(canMessage->dlc);
0054 
0055     for (int i = 0; i < canMessage->dlc; i++) {
0056         canMessage->data[i] = data.at(i);
0057     }
0058     return canMessage;
0059 }
0060 
0061 void BLFFilterTest::createBLFFile(const QString& filename, QVector<Vector::BLF::CanMessage2*> messages) {
0062     Vector::BLF::File blfFile;
0063     blfFile.open(filename.toStdString().c_str(), std::ios_base::out);
0064     QVERIFY(blfFile.is_open());
0065 
0066     for (auto msg : messages) {
0067         blfFile.write(msg);
0068     }
0069     // Finish creating files
0070     blfFile.close();
0071 }
0072 
0073 // ##########################################################################################################
0074 // ##### Test functions #####################################################################################
0075 // ##########################################################################################################
0076 void BLFFilterTest::testInvalidBLF() {
0077     VectorBLFFilter filter;
0078     QCOMPARE(filter.isValid(QStringLiteral("UnavailableBLFFile.blf")), false); // File not available
0079 
0080     // Create invalid blf file
0081     QTemporaryFile invalidBLFFile;
0082     QVERIFY(invalidBLFFile.open());
0083     QFile f(invalidBLFFile.fileName());
0084     QVERIFY(f.open(QIODevice::WriteOnly));
0085     f.write(QStringLiteral("InvalidFile.blf").toStdString().c_str());
0086     f.close();
0087     QCOMPARE(filter.isValid(invalidBLFFile.fileName()), false);
0088 }
0089 
0090 void BLFFilterTest::testNotFoundBLF() {
0091     VectorBLFFilter filter;
0092     QCOMPARE(filter.isValid(QStringLiteral("UnavailableBLFFile.blf")), false); // File not available
0093 }
0094 
0095 void BLFFilterTest::testInvalidDBC() {
0096     /* open file for writing */
0097     QTemporaryFile blfFileName(QStringLiteral("XXXXXX.blf"));
0098     QVERIFY(blfFileName.open());
0099     std::vector<uint8_t> data{0x01, 0x02};
0100     QVector<Vector::BLF::CanMessage2*> messages{createCANMessage(234, 5, data)};
0101     createBLFFile(blfFileName.fileName(), messages);
0102 
0103     QTemporaryFile dbcFile(QStringLiteral("XXXXXX.dbc"));
0104     QVERIFY(dbcFile.open());
0105     const auto dbcContent = R"(BO_ 234 MSG1: 8 Vector__XXX
0106 SG_ Sig1 : 0|8@0- (0.1,0) [-3276.8|-3276.7] "C" Vector__XXX
0107 SG_ Sig2 : 8|8@0- (0.1,0) [-3276.8|-3276.7] "C" Vector__XXX
0108 )";
0109     createDBCFile(dbcFile.fileName(), dbcContent);
0110 
0111     // Start Test
0112 
0113     VectorBLFFilter filter;
0114     QCOMPARE(filter.isValid(blfFileName.fileName()), true);
0115 
0116     // File is valid, but dbc file not
0117     Spreadsheet s(QStringLiteral("TestSpreadsheet"), false);
0118     filter.readDataFromFile(blfFileName.fileName(), &s);
0119     QCOMPARE(s.columnCount(), 2); // column count not changed means no data was added
0120 }
0121 
0122 void BLFFilterTest::testValidBLFValidDBCSingleMessageBigEndian() {
0123     /* open file for writing */
0124     QTemporaryFile blfFileName(QStringLiteral("XXXXXX.blf"));
0125     QVERIFY(blfFileName.open());
0126     std::vector<uint8_t> data{0x01, 0x02};
0127     QVector<Vector::BLF::CanMessage2*> messages{createCANMessage(234, 5, data)}; // time is in nanoseconds
0128     createBLFFile(blfFileName.fileName(), messages);
0129 
0130     QTemporaryFile dbcFile(QStringLiteral("XXXXXX.dbc"));
0131     QVERIFY(dbcFile.open());
0132     const auto dbcContent = R"(BO_ 234 MSG1: 8 Vector__XXX
0133  SG_ Sig1 : 7|8@0- (0.1,0) [-3276.8|-3276.7] "C" Vector__XXX
0134  SG_ Sig2 : 15|8@0- (0.1,0) [-3276.8|-3276.7] "C" Vector__XXX
0135 )";
0136     createDBCFile(dbcFile.fileName(), dbcContent);
0137 
0138     // Start Test
0139 
0140     VectorBLFFilter filter;
0141     QCOMPARE(filter.isValid(blfFileName.fileName()), true);
0142 
0143     // Valid blf and valid dbc
0144     filter.setDBCFile(dbcFile.fileName());
0145     Spreadsheet s(QStringLiteral("TestSpreadsheet"), false);
0146     filter.readDataFromFile(blfFileName.fileName(), &s);
0147     QCOMPARE(s.columnCount(), 3); // time + Sig1 + Sig2
0148 
0149     {
0150         // Time
0151         const auto* c = s.column(0);
0152         QCOMPARE(c->rowCount(), 1);
0153         QCOMPARE(c->valueAt(0), 5e-9); // nanoseconds
0154     }
0155 
0156     {
0157         // Sig1
0158         const auto* c = s.column(1);
0159         QCOMPARE(c->rowCount(), 1);
0160         QCOMPARE(c->valueAt(0), 0x01 * 0.1);
0161     }
0162 
0163     {
0164         // Sig2
0165         const auto* c = s.column(2);
0166         QCOMPARE(c->rowCount(), 1);
0167         QCOMPARE(c->valueAt(0), 0x02 * 0.1);
0168     }
0169 }
0170 
0171 // Use the previous value if there is no value at the current timestamp
0172 void BLFFilterTest::testUsePreviousValueBigEndian() {
0173     /* open file for writing */
0174     QTemporaryFile blfFileName(QStringLiteral("XXXXXX.blf"));
0175     QVERIFY(blfFileName.open());
0176     QVector<Vector::BLF::CanMessage2*> messages{
0177         createCANMessage(532, 5, {2, 62, 1, 161, 39, 6, 0, 214}),
0178         createCANMessage(565, 6, {0, 0, 0, 0, 0, 0, 0, 245}),
0179         createCANMessage(565, 8, {0, 0, 0, 0, 0, 0, 0, 148}),
0180         createCANMessage(532, 10, {2, 62, 1, 161, 39, 6, 0, 205}),
0181         createCANMessage(532, 12, {2, 62, 1, 161, 39, 6, 0, 206}),
0182         createCANMessage(532, 14, {2, 62, 1, 161, 39, 6, 0, 207}),
0183     }; // time is in nanoseconds
0184     createBLFFile(blfFileName.fileName(), messages);
0185 
0186     QTemporaryFile dbcFile(QStringLiteral("XXXXXX.dbc"));
0187     QVERIFY(dbcFile.open());
0188     const auto dbcContent = R"(BO_ 532 MSG1: 8 BMS1
0189  SG_ MSG1Sig1 : 39|16@0+ (0.01,0) [0|0] "%" Vector__XXX
0190  SG_ MSG1Sig2 : 23|16@0+ (0.1,0) [0|6553.5] "V" Vector__XXX
0191  SG_ MSG1Sig3 : 55|16@0- (0.1,0) [0|0] "" Vector__XXX
0192  SG_ MSG1Sig4 : 7|16@0+ (0.1,0) [0|6553.5] "V" Vector__XXX
0193 BO_ 565 MSG2: 8 Vector__XXX
0194  SG_ MSG2Sig1 : 55|16@0- (0.1,0) [0|0] "" Vector__XXX
0195 )";
0196     createDBCFile(dbcFile.fileName(), dbcContent);
0197 
0198     // Start Test
0199 
0200     VectorBLFFilter filter;
0201     filter.setTimeHandlingMode(CANFilter::TimeHandling::ConcatPrevious);
0202     QCOMPARE(filter.isValid(blfFileName.fileName()), true);
0203 
0204     // Valid blf and valid dbc
0205     filter.setDBCFile(dbcFile.fileName());
0206     Spreadsheet s(QStringLiteral("TestSpreadsheet"), false);
0207     filter.readDataFromFile(blfFileName.fileName(), &s);
0208     QCOMPARE(s.columnCount(), 6); // time + Msg1Sig1 + Msg1Sig2 + Msg1Sig3 + Msg1Sig4 + Msg2Sig1
0209 
0210     {
0211         const auto* c = s.column(0);
0212         QCOMPARE(c->name(), QStringLiteral("Time_s"));
0213         QCOMPARE(c->rowCount(), 6);
0214 
0215         QVector<double> refData{5e-9, 6e-9, 8e-9, 10e-9, 12e-9, 14e-9};
0216         QCOMPARE(refData.size(), 6);
0217         for (int i = 0; i < c->rowCount(); i++) {
0218             QCOMPARE(c->valueAt(i), refData.at(i));
0219         }
0220     }
0221 
0222     {
0223         const auto* c = s.column(1);
0224         QCOMPARE(c->name(), QStringLiteral("MSG1Sig1_%"));
0225         QCOMPARE(c->rowCount(), 6);
0226 
0227         QVector<double> refData{99.90, 99.90, 99.90, 99.90, 99.90, 99.90};
0228         QCOMPARE(refData.size(), 6);
0229         for (int i = 0; i < c->rowCount(); i++) {
0230             QCOMPARE(c->valueAt(i), refData.at(i));
0231         }
0232     }
0233 
0234     {
0235         const auto* c = s.column(2);
0236         QCOMPARE(c->name(), QStringLiteral("MSG1Sig2_V"));
0237         QCOMPARE(c->rowCount(), 6);
0238 
0239         QVector<double> refData{41.7, 41.7, 41.7, 41.7, 41.7, 41.7};
0240         QCOMPARE(refData.size(), 6);
0241         for (int i = 0; i < c->rowCount(); i++) {
0242             QCOMPARE(c->valueAt(i), refData.at(i));
0243         }
0244     }
0245 
0246     {
0247         const auto* c = s.column(3);
0248         QCOMPARE(c->name(), QStringLiteral("MSG1Sig3_"));
0249         QCOMPARE(c->rowCount(), 6);
0250 
0251         QVector<double> refData{21.4, 21.4, 21.4, 20.5, 20.6, 20.7};
0252         QCOMPARE(refData.size(), 6);
0253         for (int i = 0; i < c->rowCount(); i++) {
0254             QCOMPARE(c->valueAt(i), refData.at(i));
0255         }
0256     }
0257 
0258     {
0259         const auto* c = s.column(4);
0260         QCOMPARE(c->name(), QStringLiteral("MSG1Sig4_V"));
0261         QCOMPARE(c->rowCount(), 6);
0262 
0263         QVector<double> refData{57.4, 57.4, 57.4, 57.4, 57.4, 57.4};
0264         QCOMPARE(refData.size(), 6);
0265         for (int i = 0; i < c->rowCount(); i++) {
0266             QCOMPARE(c->valueAt(i), refData.at(i));
0267         }
0268     }
0269 
0270     {
0271         const auto* c = s.column(5);
0272         QCOMPARE(c->name(), QStringLiteral("MSG2Sig1_"));
0273         QCOMPARE(c->rowCount(), 6);
0274 
0275         QVector<double> refData{std::nan(""), 24.5, 14.8, 14.8, 14.8, 14.8};
0276         QCOMPARE(refData.size(), 6);
0277         for (int i = 0; i < c->rowCount(); i++) {
0278             QCOMPARE(c->valueAt(i), refData.at(i));
0279         }
0280     }
0281 }
0282 
0283 // Use NAN if the current message does not contain no value for the signal
0284 void BLFFilterTest::testUseNANBigEndian() {
0285     /* open file for writing */
0286     QTemporaryFile blfFileName(QStringLiteral("XXXXXX.blf"));
0287     QVERIFY(blfFileName.open());
0288     QVector<Vector::BLF::CanMessage2*> messages{
0289         createCANMessage(234, 5, {0x01, 0x02}),
0290         createCANMessage(123, 6, {0xFF, 0xA2}),
0291         createCANMessage(123, 8, {0x23, 0xE2}),
0292         createCANMessage(234, 10, {0xD3, 0xB2}),
0293         createCANMessage(234, 12, {0xE1, 0xC7}),
0294         createCANMessage(234, 14, {0xD1, 0xC7}),
0295     }; // time is in nanoseconds
0296     createBLFFile(blfFileName.fileName(), messages);
0297 
0298     QTemporaryFile dbcFile(QStringLiteral("XXXXXX.dbc"));
0299     QVERIFY(dbcFile.open());
0300     const auto dbcContent = R"(BO_ 234 MSG1: 8 Vector__XXX
0301  SG_ Msg1Sig1 : 7|8@0+ (1,0) [-3276.8|-3276.7] "C" Vector__XXX
0302  SG_ Msg1Sig2 : 15|8@0+ (1,0) [-3276.8|-3276.7] "km/h" Vector__XXX
0303 BO_ 123 MSG2: 8 Vector__XXX
0304  SG_ Msg2Sig1 : 7|8@0+ (1,0) [-3276.8|-3276.7] "mm" Vector__XXX
0305  SG_ Msg2Sig2 : 15|8@0+ (1,0) [-3276.8|-3276.7] "m" Vector__XXX
0306 )";
0307     createDBCFile(dbcFile.fileName(), dbcContent);
0308 
0309     // Start Test
0310 
0311     VectorBLFFilter filter;
0312     filter.setConvertTimeToSeconds(true);
0313     filter.setTimeHandlingMode(CANFilter::TimeHandling::ConcatNAN);
0314     QCOMPARE(filter.isValid(blfFileName.fileName()), true);
0315 
0316     // Valid blf and valid dbc
0317     filter.setDBCFile(dbcFile.fileName());
0318     Spreadsheet s(QStringLiteral("TestSpreadsheet"), false);
0319     filter.readDataFromFile(blfFileName.fileName(), &s);
0320     QCOMPARE(s.columnCount(), 5); // time + Msg1Sig1 + Msg1Sig2 + Msg2Sig1 + Msg2Sig2
0321 
0322     {
0323         // Time
0324         const auto* c = s.column(0);
0325         QCOMPARE(c->name(), QStringLiteral("Time_s"));
0326         QCOMPARE(c->rowCount(), 6);
0327 
0328         QVector<double> refData{5e-9, 6e-9, 8e-9, 10e-9, 12e-9, 14e-9};
0329         QCOMPARE(refData.size(), 6);
0330         for (int i = 0; i < c->rowCount(); i++) {
0331             QCOMPARE(c->valueAt(i), refData.at(i));
0332         }
0333     }
0334 
0335     {
0336         // Msg1Sig1
0337         const auto* c = s.column(1);
0338         QCOMPARE(c->name(), QStringLiteral("Msg1Sig1_C"));
0339         QCOMPARE(c->rowCount(), 6);
0340 
0341         QVector<double> refData{0x01, NAN, NAN, 0xD3, 0xE1, 0xD1};
0342         QCOMPARE(refData.size(), 6);
0343         for (int i = 0; i < c->rowCount(); i++) {
0344             QCOMPARE(c->valueAt(i), refData.at(i));
0345         }
0346     }
0347 
0348     {
0349         // Msg1Sig2
0350         const auto* c = s.column(2);
0351         QCOMPARE(c->name(), QStringLiteral("Msg1Sig2_km/h"));
0352         QCOMPARE(c->rowCount(), 6);
0353 
0354         QVector<double> refData{0x02, NAN, NAN, 0xB2, 0xC7, 0xC7};
0355         QCOMPARE(refData.size(), 6);
0356         for (int i = 0; i < c->rowCount(); i++) {
0357             QCOMPARE(c->valueAt(i), refData.at(i));
0358         }
0359     }
0360 
0361     {
0362         // Msg2Sig1
0363         const auto* c = s.column(3);
0364         QCOMPARE(c->name(), QStringLiteral("Msg2Sig1_mm"));
0365         QCOMPARE(c->rowCount(), 6);
0366 
0367         QVector<double> refData{NAN, 0xFF, 0x23, NAN, NAN, NAN};
0368         QCOMPARE(refData.size(), 6);
0369         for (int i = 0; i < c->rowCount(); i++) {
0370             QCOMPARE(c->valueAt(i), refData.at(i));
0371         }
0372     }
0373 
0374     {
0375         // Msg2Sig2
0376         const auto* c = s.column(4);
0377         QCOMPARE(c->name(), QStringLiteral("Msg2Sig2_m"));
0378         QCOMPARE(c->rowCount(), 6);
0379 
0380         QVector<double> refData{NAN, 0xA2, 0xE2, NAN, NAN, NAN};
0381         QCOMPARE(refData.size(), 6);
0382         for (int i = 0; i < c->rowCount(); i++) {
0383             QCOMPARE(c->valueAt(i), refData.at(i));
0384         }
0385     }
0386 }
0387 
0388 void BLFFilterTest::testTimeNative() {
0389     /* open file for writing */
0390     QTemporaryFile blfFileName(QStringLiteral("XXXXXX.blf"));
0391     QVERIFY(blfFileName.open());
0392     QVector<Vector::BLF::CanMessage2*> messages{
0393         createCANMessage(234, 5, {0x01, 0x02}),
0394         createCANMessage(123, 6, {0xFF, 0xA2}),
0395         createCANMessage(123, 8, {0x23, 0xE2}),
0396         createCANMessage(234, 10, {0xD3, 0xB2}),
0397         createCANMessage(234, 12, {0xE1, 0xC7}),
0398         createCANMessage(234, 14, {0xD1, 0xC7}),
0399     }; // time is in nanoseconds
0400     createBLFFile(blfFileName.fileName(), messages);
0401 
0402     QTemporaryFile dbcFile(QStringLiteral("XXXXXX.dbc"));
0403     QVERIFY(dbcFile.open());
0404     const auto dbcContent = R"(BO_ 234 MSG1: 8 Vector__XXX
0405  SG_ Msg1Sig1 : 0|8@0+ (1,0) [-3276.8|-3276.7] "C" Vector__XXX
0406  SG_ Msg1Sig2 : 8|8@0+ (1,0) [-3276.8|-3276.7] "km/h" Vector__XXX
0407 BO_ 123 MSG2: 8 Vector__XXX
0408  SG_ Msg2Sig1 : 0|8@0+ (1,0) [-3276.8|-3276.7] "mm" Vector__XXX
0409  SG_ Msg2Sig2 : 8|8@0+ (1,0) [-3276.8|-3276.7] "m" Vector__XXX
0410 )";
0411     createDBCFile(dbcFile.fileName(), dbcContent);
0412 
0413     // Start Test
0414 
0415     VectorBLFFilter filter;
0416     filter.setConvertTimeToSeconds(false);
0417     filter.setTimeHandlingMode(CANFilter::TimeHandling::ConcatNAN);
0418     QCOMPARE(filter.isValid(blfFileName.fileName()), true);
0419 
0420     // Valid blf and valid dbc
0421     filter.setDBCFile(dbcFile.fileName());
0422     Spreadsheet s(QStringLiteral("TestSpreadsheet"), false);
0423     filter.readDataFromFile(blfFileName.fileName(), &s);
0424     QCOMPARE(s.columnCount(), 5); // time + Msg1Sig1 + Msg1Sig2 + Msg2Sig1 + Msg2Sig2
0425 
0426     {
0427         // Time
0428         const auto* c = s.column(0);
0429         QCOMPARE(c->name(), QStringLiteral("Time_ns"));
0430         QCOMPARE(c->rowCount(), 6);
0431 
0432         QVector<double> refData{5, 6, 8, 10, 12, 14};
0433         QCOMPARE(refData.size(), 6);
0434         for (int i = 0; i < c->rowCount(); i++) {
0435             QCOMPARE(c->valueAt(i), refData.at(i));
0436         }
0437     }
0438 }
0439 
0440 // Value5 is a value larger than one byte, but not exactly a multiple
0441 // And is not aligned with a complete byte
0442 void BLFFilterTest::testBigNumberNotByteAlignedLittleEndian() {
0443     QTemporaryFile blfFileName(QStringLiteral("XXXXXX.blf"));
0444     QVERIFY(blfFileName.open());
0445     QVector<Vector::BLF::CanMessage2*> messages{
0446         createCANMessage(337, 5, {0, 4, 252, 19, 0, 0, 0, 0}),
0447         createCANMessage(337, 10, {47, 4, 60, 29, 0, 0, 0, 0}),
0448         createCANMessage(337, 15, {57, 4, 250, 29, 0, 0, 0, 0}),
0449     }; // time is in nanoseconds
0450     createBLFFile(blfFileName.fileName(), messages);
0451 
0452     QTemporaryFile dbcFile(QStringLiteral("XXXXXX.dbc"));
0453     QVERIFY(dbcFile.open());
0454     const auto dbcContent = R"(BO_ 337 STATUS: 8 Vector__XXX
0455  SG_ Value6 : 27|3@1+ (1,0) [0|7] ""  Vector__XXX
0456  SG_ Value5 : 16|11@1+ (0.1,-102) [-102|102] "%"  Vector__XXX
0457  SG_ Value2 : 8|2@1+ (1,0) [0|2] ""  Vector__XXX
0458  SG_ Value3 : 10|1@1+ (1,0) [0|1] ""  Vector__XXX
0459  SG_ Value7 : 30|2@1+ (1,0) [0|3] ""  Vector__XXX
0460  SG_ Value4 : 11|4@1+ (1,0) [0|3] ""  Vector__XXX
0461  SG_ Value1 : 0|8@1+ (1,0) [0|204] "Km/h"  Vector__XXX
0462 )";
0463     createDBCFile(dbcFile.fileName(), dbcContent);
0464 
0465     // Start Test
0466 
0467     VectorBLFFilter filter;
0468     filter.setConvertTimeToSeconds(true);
0469     filter.setTimeHandlingMode(CANFilter::TimeHandling::ConcatNAN);
0470     QCOMPARE(filter.isValid(blfFileName.fileName()), true);
0471 
0472     // Valid blf and valid dbc
0473     filter.setDBCFile(dbcFile.fileName());
0474     QCOMPARE(filter.d->readDataFromFile(blfFileName.fileName(), 4), 3);
0475     const auto dc = filter.dataContainer();
0476     QCOMPARE(dc.size(), 8); // Time + 7 signals
0477     {
0478         // Time
0479         const auto* v = static_cast<QVector<double>*>(dc.at(0));
0480         QCOMPARE(v->length(), 3);
0481         QCOMPARE(v->at(0), 5e-9);
0482         QCOMPARE(v->at(1), 10e-9);
0483         QCOMPARE(v->at(2), 15e-9);
0484     }
0485 
0486     {
0487         // Value6
0488         const auto* v = static_cast<QVector<double>*>(dc.at(1));
0489         QCOMPARE(v->length(), 3);
0490         QCOMPARE(v->at(0), 2.);
0491         QCOMPARE(v->at(1), 3.);
0492         QCOMPARE(v->at(2), 3.);
0493     }
0494 
0495     {
0496         // Value5
0497         const auto* v = static_cast<QVector<double>*>(dc.at(2));
0498         QCOMPARE(v->length(), 3);
0499         QCOMPARE(v->at(0), 0.);
0500         QCOMPARE(v->at(1), 32.);
0501         QCOMPARE(v->at(2), 51.);
0502     }
0503 
0504     {
0505         // Value2
0506         const auto* v = static_cast<QVector<double>*>(dc.at(3));
0507         QCOMPARE(v->length(), 3);
0508         QCOMPARE(v->at(0), 0.);
0509         QCOMPARE(v->at(1), 0.);
0510         QCOMPARE(v->at(2), 0.);
0511     }
0512 
0513     {
0514         // Value3
0515         const auto* v = static_cast<QVector<double>*>(dc.at(4));
0516         QCOMPARE(v->length(), 3);
0517         QCOMPARE(v->at(0), 1.);
0518         QCOMPARE(v->at(1), 1.);
0519         QCOMPARE(v->at(2), 1.);
0520     }
0521 
0522     {
0523         // Value7
0524         const auto* v = static_cast<QVector<double>*>(dc.at(5));
0525         QCOMPARE(v->length(), 3);
0526         QCOMPARE(v->at(0), 0.);
0527         QCOMPARE(v->at(1), 0.);
0528         QCOMPARE(v->at(2), 0.);
0529     }
0530 
0531     {
0532         // Value4
0533         const auto* v = static_cast<QVector<double>*>(dc.at(6));
0534         QCOMPARE(v->length(), 3);
0535         QCOMPARE(v->at(0), 0.);
0536         QCOMPARE(v->at(1), 0.);
0537         QCOMPARE(v->at(2), 0.);
0538     }
0539 
0540     {
0541         // Value1
0542         const auto* v = static_cast<QVector<double>*>(dc.at(7));
0543         QCOMPARE(v->length(), 3);
0544         QCOMPARE(v->at(0), 0.);
0545         QCOMPARE(v->at(1), 47.);
0546         QCOMPARE(v->at(2), 57.);
0547     }
0548 }
0549 
0550 // Use NAN if the current message does not contain no value for the signal
0551 void BLFFilterTest::testUseNANLittleEndian() {
0552     QTemporaryFile blfFileName(QStringLiteral("XXXXXX.blf"));
0553     QVERIFY(blfFileName.open());
0554     QVector<Vector::BLF::CanMessage2*> messages{
0555         createCANMessage(337, 5, {0, 4, 252, 19, 0, 0, 0, 0}),
0556         createCANMessage(541, 10, {7, 39, 118, 33, 250, 30, 76, 24}), // 99.91, 85.66, 79.3, 22.2
0557         createCANMessage(337, 15, {47, 4, 60, 29, 0, 0, 0, 0}),
0558         createCANMessage(337, 20, {57, 4, 250, 29, 0, 0, 0, 0}),
0559         createCANMessage(541, 25, {7, 39, 118, 33, 250, 30, 76, 24}), // 99.91, 85.66, 79.3, 22.2
0560     }; // time is in nanoseconds
0561     createBLFFile(blfFileName.fileName(), messages);
0562 
0563     QTemporaryFile dbcFile(QStringLiteral("XXXXXX.dbc"));
0564     QVERIFY(dbcFile.open());
0565     const auto dbcContent = R"(BO_ 337 STATUS: 8 Vector__XXX
0566  SG_ Value6 : 27|3@1+ (1,0) [0|7] ""  Vector__XXX
0567  SG_ Value5 : 16|11@1+ (0.1,-102) [-102|102] "%"  Vector__XXX
0568  SG_ Value2 : 8|2@1+ (1,0) [0|2] ""  Vector__XXX
0569  SG_ Value3 : 10|1@1+ (1,0) [0|1] ""  Vector__XXX
0570  SG_ Value7 : 30|2@1+ (1,0) [0|3] ""  Vector__XXX
0571  SG_ Value4 : 11|4@1+ (1,0) [0|3] ""  Vector__XXX
0572  SG_ Value1 : 0|8@1+ (1,0) [0|204] "Km/h"  Vector__XXX"
0573 BO_ 541 MSG2: 8 Vector__XXX
0574  SG_ MSG2Value4 : 48|16@1+ (0.01,-40) [-40|125] "C"  Vector__XXX
0575  SG_ MSG2Value1 : 0|16@1+ (0.01,0) [0|100] "%"  Vector__XXX
0576  SG_ MSG2Value3 : 32|16@1+ (0.01,0) [0|100] "%"  Vector__XXX
0577  SG_ MSG2Value2 : 16|16@1+ (0.01,0) [0|100] "%"  Vector__XXX
0578 )";
0579     createDBCFile(dbcFile.fileName(), dbcContent);
0580 
0581     // Start Test
0582 
0583     VectorBLFFilter filter;
0584     filter.setConvertTimeToSeconds(true);
0585     filter.setTimeHandlingMode(CANFilter::TimeHandling::ConcatNAN);
0586     QCOMPARE(filter.isValid(blfFileName.fileName()), true);
0587 
0588     // Valid blf and valid dbc
0589     filter.setDBCFile(dbcFile.fileName());
0590     Spreadsheet s(QStringLiteral("TestSpreadsheet"), false);
0591     filter.readDataFromFile(blfFileName.fileName(), &s);
0592     QCOMPARE(s.columnCount(), 12); // time + 7 * Msg1 + 4* Msg2
0593 
0594     {
0595         // Time
0596         const auto* c = s.column(0);
0597         QCOMPARE(c->name(), QStringLiteral("Time_s"));
0598         QCOMPARE(c->rowCount(), 5);
0599 
0600         QVector<double> refData{5e-9, 10e-9, 15e-9, 20e-9, 25e-9};
0601         QCOMPARE(refData.size(), 5);
0602         for (int i = 0; i < c->rowCount(); i++) {
0603             QCOMPARE(c->valueAt(i), refData.at(i));
0604         }
0605     }
0606 
0607     {
0608         // Msg1Sig6
0609         const auto* c = s.column(1);
0610         QCOMPARE(c->name(), QStringLiteral("Value6_"));
0611         QCOMPARE(c->rowCount(), 5);
0612 
0613         QVector<double> refData{2., std::nan("0"), 3., 3., std::nan("0")};
0614         QCOMPARE(refData.size(), 5);
0615         for (int i = 0; i < c->rowCount(); i++) {
0616             QCOMPARE(c->valueAt(i), refData.at(i));
0617         }
0618     }
0619 
0620     {
0621         // Msg1Sig5
0622         const auto* c = s.column(2);
0623         QCOMPARE(c->name(), QStringLiteral("Value5_%"));
0624         QCOMPARE(c->rowCount(), 5);
0625 
0626         QVector<double> refData{0., std::nan("0"), 32., 51., std::nan("0")};
0627         QCOMPARE(refData.size(), 5);
0628         for (int i = 0; i < c->rowCount(); i++) {
0629             QCOMPARE(c->valueAt(i), refData.at(i));
0630         }
0631     }
0632 
0633     {
0634         // Msg1Sig2
0635         const auto* c = s.column(3);
0636         QCOMPARE(c->name(), QStringLiteral("Value2_"));
0637         QCOMPARE(c->rowCount(), 5);
0638 
0639         QVector<double> refData{0., std::nan("0"), 0., 0., std::nan("0")};
0640         QCOMPARE(refData.size(), 5);
0641         for (int i = 0; i < c->rowCount(); i++) {
0642             QCOMPARE(c->valueAt(i), refData.at(i));
0643         }
0644     }
0645 
0646     {
0647         // Msg1Sig3
0648         const auto* c = s.column(4);
0649         QCOMPARE(c->name(), QStringLiteral("Value3_"));
0650         QCOMPARE(c->rowCount(), 5);
0651 
0652         QVector<double> refData{1., std::nan("0"), 1., 1., std::nan("0")};
0653         QCOMPARE(refData.size(), 5);
0654         for (int i = 0; i < c->rowCount(); i++) {
0655             QCOMPARE(c->valueAt(i), refData.at(i));
0656         }
0657     }
0658 
0659     {
0660         // Msg1Sig7
0661         const auto* c = s.column(5);
0662         QCOMPARE(c->name(), QStringLiteral("Value7_"));
0663         QCOMPARE(c->rowCount(), 5);
0664 
0665         QVector<double> refData{0., std::nan("0"), 0., 0., std::nan("0")};
0666         QCOMPARE(refData.size(), 5);
0667         for (int i = 0; i < c->rowCount(); i++) {
0668             QCOMPARE(c->valueAt(i), refData.at(i));
0669         }
0670     }
0671 
0672     {
0673         // Msg12Sig4
0674         const auto* c = s.column(6);
0675         QCOMPARE(c->name(), QStringLiteral("Value4_"));
0676         QCOMPARE(c->rowCount(), 5);
0677 
0678         QVector<double> refData{0., std::nan("0"), 0., 0., std::nan("0")};
0679         QCOMPARE(refData.size(), 5);
0680         for (int i = 0; i < c->rowCount(); i++) {
0681             QCOMPARE(c->valueAt(i), refData.at(i));
0682         }
0683     }
0684 
0685     {
0686         // Msg1Sig1
0687         const auto* c = s.column(7);
0688         QCOMPARE(c->name(), QStringLiteral("Value1_Km/h"));
0689         QCOMPARE(c->rowCount(), 5);
0690 
0691         QVector<double> refData{0., std::nan("0"), 47., 57., std::nan("0")};
0692         QCOMPARE(refData.size(), 5);
0693         for (int i = 0; i < c->rowCount(); i++) {
0694             QCOMPARE(c->valueAt(i), refData.at(i));
0695         }
0696     }
0697 
0698     {
0699         // Msg2Sig4
0700         const auto* c = s.column(8);
0701         QCOMPARE(c->name(), QStringLiteral("MSG2Value4_C"));
0702         QCOMPARE(c->rowCount(), 5);
0703 
0704         QVector<double> refData{std::nan("0"), 22.2, std::nan("0"), std::nan("0"), 22.2};
0705         QCOMPARE(refData.size(), 5);
0706         for (int i = 0; i < c->rowCount(); i++) {
0707             VALUES_EQUAL(c->valueAt(i), refData.at(i));
0708         }
0709     }
0710 
0711     {
0712         // Msg2Sig1
0713         const auto* c = s.column(9);
0714         QCOMPARE(c->name(), QStringLiteral("MSG2Value1_%"));
0715         QCOMPARE(c->rowCount(), 5);
0716 
0717         QVector<double> refData{std::nan("0"), 99.91, std::nan("0"), std::nan("0"), 99.91};
0718         QCOMPARE(refData.size(), 5);
0719         for (int i = 0; i < c->rowCount(); i++) {
0720             VALUES_EQUAL(c->valueAt(i), refData.at(i));
0721         }
0722     }
0723 
0724     {
0725         // Msg2Sig3
0726         const auto* c = s.column(10);
0727         QCOMPARE(c->name(), QStringLiteral("MSG2Value3_%"));
0728         QCOMPARE(c->rowCount(), 5);
0729 
0730         QVector<double> refData{std::nan("0"), 79.3, std::nan("0"), std::nan("0"), 79.3};
0731         QCOMPARE(refData.size(), 5);
0732         for (int i = 0; i < c->rowCount(); i++) {
0733             VALUES_EQUAL(c->valueAt(i), refData.at(i));
0734         }
0735     }
0736 
0737     {
0738         // Msg2Sig2
0739         const auto* c = s.column(11);
0740         QCOMPARE(c->name(), QStringLiteral("MSG2Value2_%"));
0741         QCOMPARE(c->rowCount(), 5);
0742 
0743         QVector<double> refData{std::nan("0"), 85.66, std::nan("0"), std::nan("0"), 85.66};
0744         QCOMPARE(refData.size(), 5);
0745         for (int i = 0; i < c->rowCount(); i++) {
0746             VALUES_EQUAL(c->valueAt(i), refData.at(i));
0747         }
0748     }
0749 }
0750 
0751 // Use previous value if the current message does not contain no value for the signal
0752 void BLFFilterTest::testUsePreviousValueLittleEndian() {
0753     QTemporaryFile blfFileName(QStringLiteral("XXXXXX.blf"));
0754     QVERIFY(blfFileName.open());
0755     QVector<Vector::BLF::CanMessage2*> messages{
0756         createCANMessage(337, 5, {0, 4, 252, 19, 0, 0, 0, 0}),
0757         createCANMessage(541, 10, {7, 39, 118, 33, 250, 30, 76, 24}), // 99.91, 85.66, 79.3, 22.2
0758         createCANMessage(337, 15, {47, 4, 60, 29, 0, 0, 0, 0}),
0759         createCANMessage(337, 20, {57, 4, 250, 29, 0, 0, 0, 0}),
0760         createCANMessage(541, 25, {7, 39, 118, 33, 250, 30, 76, 24}), // 99.91, 85.66, 79.3, 22.2
0761     }; // time is in nanoseconds
0762     createBLFFile(blfFileName.fileName(), messages);
0763 
0764     QTemporaryFile dbcFile(QStringLiteral("XXXXXX.dbc"));
0765     QVERIFY(dbcFile.open());
0766     const auto dbcContent = R"(BO_ 337 STATUS: 8 Vector__XXX
0767  SG_ Value6 : 27|3@1+ (1,0) [0|7] ""  Vector__XXX
0768  SG_ Value5 : 16|11@1+ (0.1,-102) [-102|102] "%"  Vector__XXX
0769  SG_ Value2 : 8|2@1+ (1,0) [0|2] ""  Vector__XXX
0770  SG_ Value3 : 10|1@1+ (1,0) [0|1] ""  Vector__XXX
0771  SG_ Value7 : 30|2@1+ (1,0) [0|3] ""  Vector__XXX
0772  SG_ Value4 : 11|4@1+ (1,0) [0|3] ""  Vector__XXX
0773  SG_ Value1 : 0|8@1+ (1,0) [0|204] "Km/h"  Vector__XXX"
0774 BO_ 541 MSG2: 8 Vector__XXX
0775  SG_ MSG2Value4 : 48|16@1+ (0.01,-40) [-40|125] "C"  Vector__XXX
0776  SG_ MSG2Value1 : 0|16@1+ (0.01,0) [0|100] "%"  Vector__XXX
0777  SG_ MSG2Value3 : 32|16@1+ (0.01,0) [0|100] "%"  Vector__XXX
0778  SG_ MSG2Value2 : 16|16@1+ (0.01,0) [0|100] "%"  Vector__XXX
0779 )";
0780     createDBCFile(dbcFile.fileName(), dbcContent);
0781 
0782     // Start Test
0783 
0784     VectorBLFFilter filter;
0785     filter.setConvertTimeToSeconds(true);
0786     filter.setTimeHandlingMode(CANFilter::TimeHandling::ConcatPrevious);
0787     QCOMPARE(filter.isValid(blfFileName.fileName()), true);
0788 
0789     // Valid blf and valid dbc
0790     filter.setDBCFile(dbcFile.fileName());
0791     Spreadsheet s(QStringLiteral("TestSpreadsheet"), false);
0792     filter.readDataFromFile(blfFileName.fileName(), &s);
0793     QCOMPARE(s.columnCount(), 12); // time + 7 * Msg1 + 4* Msg2
0794 
0795     {
0796         // Time
0797         const auto* c = s.column(0);
0798         QCOMPARE(c->name(), QStringLiteral("Time_s"));
0799         QCOMPARE(c->rowCount(), 5);
0800 
0801         QVector<double> refData{5e-9, 10e-9, 15e-9, 20e-9, 25e-9};
0802         QCOMPARE(refData.size(), 5);
0803         for (int i = 0; i < c->rowCount(); i++) {
0804             QCOMPARE(c->valueAt(i), refData.at(i));
0805         }
0806     }
0807 
0808     {
0809         // Msg1Sig6
0810         const auto* c = s.column(1);
0811         QCOMPARE(c->name(), QStringLiteral("Value6_"));
0812         QCOMPARE(c->rowCount(), 5);
0813 
0814         QVector<double> refData{2., 2., 3., 3., 3.};
0815         QCOMPARE(refData.size(), 5);
0816         for (int i = 0; i < c->rowCount(); i++) {
0817             QCOMPARE(c->valueAt(i), refData.at(i));
0818         }
0819     }
0820 
0821     {
0822         // Msg1Sig5
0823         const auto* c = s.column(2);
0824         QCOMPARE(c->name(), QStringLiteral("Value5_%"));
0825         QCOMPARE(c->rowCount(), 5);
0826 
0827         QVector<double> refData{0., 0., 32., 51., 51.};
0828         QCOMPARE(refData.size(), 5);
0829         for (int i = 0; i < c->rowCount(); i++) {
0830             QCOMPARE(c->valueAt(i), refData.at(i));
0831         }
0832     }
0833 
0834     {
0835         // Msg1Sig2
0836         const auto* c = s.column(3);
0837         QCOMPARE(c->name(), QStringLiteral("Value2_"));
0838         QCOMPARE(c->rowCount(), 5);
0839 
0840         QVector<double> refData{0., 0., 0., 0., 0.};
0841         QCOMPARE(refData.size(), 5);
0842         for (int i = 0; i < c->rowCount(); i++) {
0843             QCOMPARE(c->valueAt(i), refData.at(i));
0844         }
0845     }
0846 
0847     {
0848         // Msg1Sig3
0849         const auto* c = s.column(4);
0850         QCOMPARE(c->name(), QStringLiteral("Value3_"));
0851         QCOMPARE(c->rowCount(), 5);
0852 
0853         QVector<double> refData{1., 1., 1., 1., 1.};
0854         QCOMPARE(refData.size(), 5);
0855         for (int i = 0; i < c->rowCount(); i++) {
0856             QCOMPARE(c->valueAt(i), refData.at(i));
0857         }
0858     }
0859 
0860     {
0861         // Msg1Sig7
0862         const auto* c = s.column(5);
0863         QCOMPARE(c->name(), QStringLiteral("Value7_"));
0864         QCOMPARE(c->rowCount(), 5);
0865 
0866         QVector<double> refData{0., 0., 0., 0., 0.};
0867         QCOMPARE(refData.size(), 5);
0868         for (int i = 0; i < c->rowCount(); i++) {
0869             QCOMPARE(c->valueAt(i), refData.at(i));
0870         }
0871     }
0872 
0873     {
0874         // Msg12Sig4
0875         const auto* c = s.column(6);
0876         QCOMPARE(c->name(), QStringLiteral("Value4_"));
0877         QCOMPARE(c->rowCount(), 5);
0878 
0879         QVector<double> refData{0., 0., 0., 0., 0.};
0880         QCOMPARE(refData.size(), 5);
0881         for (int i = 0; i < c->rowCount(); i++) {
0882             QCOMPARE(c->valueAt(i), refData.at(i));
0883         }
0884     }
0885 
0886     {
0887         // Msg1Sig1
0888         const auto* c = s.column(7);
0889         QCOMPARE(c->name(), QStringLiteral("Value1_Km/h"));
0890         QCOMPARE(c->rowCount(), 5);
0891 
0892         QVector<double> refData{0., 0., 47., 57., 57.};
0893         QCOMPARE(refData.size(), 5);
0894         for (int i = 0; i < c->rowCount(); i++) {
0895             QCOMPARE(c->valueAt(i), refData.at(i));
0896         }
0897     }
0898 
0899     {
0900         // Msg2Sig4
0901         const auto* c = s.column(8);
0902         QCOMPARE(c->name(), QStringLiteral("MSG2Value4_C"));
0903         QCOMPARE(c->rowCount(), 5);
0904 
0905         QVector<double> refData{std::nan(""), 22.2, 22.2, 22.2, 22.2};
0906         QCOMPARE(refData.size(), 5);
0907         for (int i = 0; i < c->rowCount(); i++) {
0908             VALUES_EQUAL(c->valueAt(i), refData.at(i));
0909         }
0910     }
0911 
0912     {
0913         // Msg2Sig1
0914         const auto* c = s.column(9);
0915         QCOMPARE(c->name(), QStringLiteral("MSG2Value1_%"));
0916         QCOMPARE(c->rowCount(), 5);
0917 
0918         QVector<double> refData{std::nan(""), 99.91, 99.91, 99.91, 99.91};
0919         QCOMPARE(refData.size(), 5);
0920         for (int i = 0; i < c->rowCount(); i++) {
0921             VALUES_EQUAL(c->valueAt(i), refData.at(i));
0922         }
0923     }
0924 
0925     {
0926         // Msg2Sig3
0927         const auto* c = s.column(10);
0928         QCOMPARE(c->name(), QStringLiteral("MSG2Value3_%"));
0929         QCOMPARE(c->rowCount(), 5);
0930 
0931         QVector<double> refData{std::nan(""), 79.3, 79.3, 79.3, 79.3};
0932         QCOMPARE(refData.size(), 5);
0933         for (int i = 0; i < c->rowCount(); i++) {
0934             VALUES_EQUAL(c->valueAt(i), refData.at(i));
0935         }
0936     }
0937 
0938     {
0939         // Msg2Sig2
0940         const auto* c = s.column(11);
0941         QCOMPARE(c->name(), QStringLiteral("MSG2Value2_%"));
0942         QCOMPARE(c->rowCount(), 5);
0943 
0944         QVector<double> refData{std::nan(""), 85.66, 85.66, 85.66, 85.66};
0945         QCOMPARE(refData.size(), 5);
0946         for (int i = 0; i < c->rowCount(); i++) {
0947             VALUES_EQUAL(c->valueAt(i), refData.at(i));
0948         }
0949     }
0950 }
0951 
0952 #endif
0953 
0954 QTEST_MAIN(BLFFilterTest)