/*! * * Copyright (c) 2019-2025 Diality Inc. - All Rights Reserved. * \copyright * THIS CODE MAY NOT BE COPIED OR REPRODUCED IN ANY FORM, IN PART OR IN * WHOLE, WITHOUT THE EXPLICIT PERMISSION OF THE COPYRIGHT OWNER. * * \file tst_canbus.cpp * \author (last) Behrouz NematiPour * \date (last) 10-Aug-2021 * \author (original) Behrouz NematiPour * \date (original) 19-Dec-2019 * */ #include "tst_canbus.h" // Project #include "CanInterface.h" #include "FrameInterface.h" using namespace Can; /*! * \brief tst_canbus::tst_canbus * \details Constructor * \param parent - QObject parent owner object. * Qt handles the children destruction by their parent objects life-cycle. */ tst_canbus::tst_canbus(QObject *parent) : QObject(parent) { } void tst_canbus::initTestCase() { } void tst_canbus::initTestCase_data() { } void tst_canbus::init() { _emited = false; _Logger.init(); } void tst_canbus::tst_CanInterface_Connect_Error_Interface() { QString mTr = tr("Connection"); _CanInterface._canInterface = "can1"; _CanInterface._init = false; _CanInterface.init(); _CanInterface.enableConsoleOut(false); QCOMPARE(_CanInterface.status().left(mTr.length()), mTr); } void tst_canbus::tst_CanInterface_Connect_NoError() { _CanInterface._canInterface = "can0"; _CanInterface._init = false; _CanInterface.init(); _CanInterface.enableConsoleOut(true); QString mTr = tr("Connected"); QCOMPARE(_CanInterface.status().left(mTr.length()), mTr); _CanInterface.onFrameReceive (); } void tst_canbus::tst_FrameInterface_Init() { _FrameInterface .init(); _MessageDispatcher .init(); _MessageDispatcher .enableConsoleOut(true); connect(&_MessageDispatcher , SIGNAL(didFrameTransmit(Can_Id , const QByteArray &)), this , SLOT( onFrameTransmit(Can_Id , const QByteArray &))); connect(&_MessageDispatcher , SIGNAL(didActionReceive(GuiActionType , const QVariantList &)), this , SLOT( onActionReceive(GuiActionType , const QVariantList &))); } void tst_canbus::tst_FrameInterface_ReInit() { QVERIFY( ! _FrameInterface .init() ); // Coverage QVERIFY( ! _MessageDispatcher .init() ); // Coverage } void tst_canbus::tst_FrameInterface_ActionTransmit_KeepAlive() { _expected = "A5.01.00.07.00.00.30.00"; _MessageDispatcher.onActionTransmit(Gui::GuiActionType::ID_KeepAlive, {}); QVERIFY(_emited); } void tst_canbus::tst_FrameInterface_TransmitFrame_LongerData() { _expected = QByteArray("123456789"); _FrameInterface.transmitFrame(Can_Id::eChlid_HD_UI, _expected); QVERIFY( ! _emited ); //there is no signal call - Code Coverage only : Error : "Payload cannot be larger than 8 bytes" } void tst_canbus::tst_FrameInterface_ActionTransmit_PowerOff_Accepted() { _expected = "A5.02.00.01.00.01.01.F0"; QVariantList mData {static_cast(Gui::GuiActionData::Accepted)}; _MessageDispatcher.onActionTransmit(Gui::GuiActionType::ID_PowerOff, mData); QVERIFY(_emited); } void tst_canbus::tst_FrameInterface_ActionTransmit_PowerOff_Rejected() { _expected = "A5.03.00.01.00.01.02.F4"; QVariantList mData {static_cast(Gui::GuiActionData::Rejected)}; _MessageDispatcher.onActionTransmit(Gui::GuiActionType::ID_PowerOff, mData); QVERIFY(_emited); } void tst_canbus::tst_FrameInterface_ActionTransmit_PowerOff() { _expected = "A5.04.00.01.00.01.00.02"; QVariantList mData {static_cast(Gui::GuiActionData::NoData)}; _MessageDispatcher.onActionTransmit(Gui::GuiActionType::ID_PowerOff, mData); QVERIFY(_emited); } void tst_canbus::tst_FrameInterface_ActionTransmit_Raw() { // An example of longest data transmission by Gui::GuiActionType::String // which can be as long as 255 byte. _expected = "A5.05.00.FF.FE.01.41.18"; // A QVariantList mData {"A"}; _MessageDispatcher.onActionTransmit(Gui::GuiActionType::ID_RawData, mData); QVERIFY(_emited); } void tst_canbus::tst_FrameInterface_ActionTransmit_ShortPayload() { _expected = "A5.06.00.01.00.00.00.00"; QVariantList mData {}; _MessageDispatcher.onActionTransmit(Gui::GuiActionType::ID_PowerOff, mData); QVERIFY(! _emited); // not emitted due to short payload len } void tst_canbus::tst_FrameInterface_ActionTransmit_Unknown() { _expected = ""; _MessageDispatcher.onActionTransmit(Gui::GuiActionType::ID_Unknown, {}); QVERIFY( ! _emited ); // should not emit the signal due to unknown action } void tst_canbus::tst_FrameInterface_FrameReceived_PowerOff() { _action = Gui::GuiActionType::ID_PowerOff; _data = {0}; QCanBusFrame mFrame; QString mPayload; mFrame.setFrameId(Can_Id::eChlid_HD_UI); mPayload = "A5.01.00.01.00.01.00.38"; mFrame.setPayload(QByteArray::fromHex(mPayload.remove(QLatin1Char('.')).toLatin1())); emit _CanInterface.didFrameReceive(mFrame); QVERIFY(_emited); } void tst_canbus::tst_FrameInterface_FrameReceived_PowerOff_Timeout() { _action = Gui::GuiActionType::ID_PowerOff; _data = {1}; QCanBusFrame mFrame; QString mPayload; mFrame.setFrameId(Can_Id::eChlid_HD_UI); mPayload = "A5.02.00.01.00.01.01.F0"; mFrame.setPayload(QByteArray::fromHex(mPayload.remove(QLatin1Char('.')).toLatin1())); emit _CanInterface.didFrameReceive(mFrame); QVERIFY(_emited); } void tst_canbus::tst_FrameInterface_FrameReceived_Channel_NotListen() { _action = Gui::GuiActionType::ID_PowerOff; _data = {1}; QCanBusFrame mFrame; QString mPayload; mFrame.setFrameId(Can_Id::eChlid_HD_DG); mPayload = "A5.03.00.01.00.01.01.XX"; mFrame.setPayload(QByteArray::fromHex(mPayload.remove(QLatin1Char('.')).toLatin1())); emit _CanInterface.didFrameReceive(mFrame); QVERIFY( ! _emited ); // should not be emitted due to not listening channel } void tst_canbus::tst_FrameInterface_FrameReceived_Channel_Incorrect() { _action = Gui::GuiActionType::ID_PowerOff; _data = {1}; QCanBusFrame mFrame; QString mPayload; mFrame.setFrameId(0x999); mPayload = "A5.01.00.01.01.5E.00.00"; mFrame.setPayload(QByteArray::fromHex(mPayload.remove(QLatin1Char('.')).toLatin1())); emit _CanInterface.didFrameReceive(mFrame); QVERIFY( ! _emited ); // should not be emitted due to not listening channel } void tst_canbus::tst_FrameInterface_FrameReceived_CRC_Error() { _action = Gui::GuiActionType::ID_PowerOff; _data = {0}; QCanBusFrame mFrame; QString mPayload; mFrame.setFrameId(Can_Id::eChlid_HD_UI); mPayload = "A5.01.00.01.00.66.00.00"; mFrame.setPayload(QByteArray::fromHex(mPayload.remove(QLatin1Char('.')).toLatin1())); emit _CanInterface.didFrameReceive(mFrame); QCOMPARE(_emited, false); // Should not emit due to crc error } void tst_canbus::tst_FrameInterface_FrameReceived_ShortFrame_Error() { _action = Gui::GuiActionType::ID_PowerOff; _data = {0}; QCanBusFrame mFrame; QString mPayload; mFrame.setFrameId(Can_Id::eChlid_HD_UI); mPayload = "A5.01.00.01.00.6F"; mFrame.setPayload(QByteArray::fromHex(mPayload.remove(QLatin1Char('.')).toLatin1())); emit _CanInterface.didFrameReceive(mFrame); QVERIFY( ! _emited); // Should not emit due to frame length less than 8 } void tst_canbus::tst_FrameInterface_FrameReceived_LongFrame_Error() { _action = Gui::GuiActionType::ID_PowerOff; _data = {0}; QCanBusFrame mFrame; QString mPayload; mFrame.setFrameId(Can_Id::eChlid_HD_UI); mPayload = "A5.04.00.01.00.01.00.6F.FF.FF"; mFrame.setPayload(QByteArray::fromHex(mPayload.remove(QLatin1Char('.')).toLatin1())); emit _CanInterface.didFrameReceive(mFrame); QVERIFY( ! _emited); // Should not emit due to crc error } void tst_canbus::tst_FrameInterface_FrameReceived_LongFrame_BloodFlow() { _action = Gui::GuiActionType::ID_BloodFlow; _data = { -400, -397.50f, -26.20f, -2000.00f, -2002.50f, 648.75f, 62.50f }; QCanBusFrame mFrame; mFrame.setFrameId(Can_Id::eChlid_HD_Sync); QStringList mPayloadList { "a5.0a.00.05.00.1c.70.fe" , "ff.ff.00.c0.c6.c3.9a.99" , "d1.c1.00.00.fa.c4.00.50" , "fa.c4.00.30.22.44.00.00" , "7a.42.fb.00.00.00.00.00" , }; for ( QString payload : mPayloadList ) { mFrame.setPayload(QByteArray::fromHex(payload.remove(QLatin1Char('.')).toLatin1())); emit _CanInterface.didFrameReceive(mFrame); } QVERIFY(_emited); } void tst_canbus::tst_FrameInterface_FrameReceived_LongFrame_BloodFlow_LessData() { _action = Gui::GuiActionType::ID_BloodFlow; _data = { -400, -397.50f, -26.20f, -2000.00f, -2002.50f, 648.75f, 62.50f }; QCanBusFrame mFrame; mFrame.setFrameId(Can_Id::eChlid_HD_Sync); QStringList mPayloadList { "a5.05.00.1c.70.fe.ff.ff" , "00.c0.c6.c3.9a.99.d1.c1" , "00.00.fa.c4.00.50.fa.c4" , "00.30.22.44.00.00.7a.42" , }; for ( QString payload : mPayloadList ) { mFrame.setPayload(QByteArray::fromHex(payload.remove(QLatin1Char('.')).toLatin1())); emit _CanInterface.didFrameReceive(mFrame); } QVERIFY( ! _emited ); // Should not emit due to - ERROR : "Incorrect data for Message ID (HD) '0x0500'" } void tst_canbus::tst_FrameInterface_FrameReceived_LongFrame_AlarmStatus_LessData() { _action = Gui::GuiActionType::ID_AlarmStatus; _data = { 2, 10, 60, 30, false,true ,false,false, // 0100 true ,false,false,false, // 1000 true ,true ,false,false, // 1100 false,false,false,false, // 0000 }; QCanBusFrame mFrame; mFrame.setFrameId(Can_Id::eChlid_HD_Alarm); QStringList mPayloadList { "a5.02.00.12.02.00.00.00" , "0a.00.00.00.3c.00.00.00" , }; for ( QString payload : mPayloadList ) { mFrame.setPayload(QByteArray::fromHex(payload.remove(QLatin1Char('.')).toLatin1())); qDebug() << " ~ @ ~ : " << mFrame.payload(); emit _CanInterface.didFrameReceive(mFrame); } QVERIFY( ! _emited ); // Should not emit due to - ERROR : "Incorrect data for Message ID (HD) '0x0200'" } void tst_canbus::tst_FrameInterface_FrameReceived_removeHead_EmptyList() { FrameInterface frame; frame.init(); QVERIFY(frame._txFrameList.isEmpty()); frame.removeHead(); // if the code does not work and calls the removeFirst of and empty list it will assert. QVERIFY(true); } void tst_canbus::cleanup() { } void tst_canbus::cleanupTestCase() { _CanInterface.quitDevice(); QString mTr = tr("Disconnected"); QCOMPARE(_CanInterface.status().left(mTr.length()), mTr); } void tst_canbus::onFrameTransmit(Can_Id vCan_Id, const QByteArray &vPayload) { Q_UNUSED(vCan_Id) _emited = true; QCOMPARE(Format::toHexString(vPayload), _expected); } void tst_canbus::onActionReceive(Gui::GuiActionType vAction, const QVariantList &vData) { _emited = true; QVERIFY(vAction == _action); qDebug() << " ~ @ ~ : " << vData; for (int i = 0; i < vData.length(); i++) { if (! strcmp(vData[i].typeName(), "float")) { float f1 = vData[i].toFloat(); float f2 = _data[i].toFloat(); QVERIFY(Types::floatCompare(f1, f2)); } else { QCOMPARE(vData, _data); } } }