Index: unittests/tst_models.h =================================================================== diff -u -r7777127f3b60d5f884cd07adc9d586353d914f69 -rf6c480d06e4b8c770012115d20df2a44e0da8031 --- unittests/tst_models.h (.../tst_models.h) (revision 7777127f3b60d5f884cd07adc9d586353d914f69) +++ unittests/tst_models.h (.../tst_models.h) (revision f6c480d06e4b8c770012115d20df2a44e0da8031) @@ -1,15 +1,15 @@ /*! * - * Copyright (c) 2019-2020 Diality Inc. - All Rights Reserved. + * Copyright (c) 2020-2024 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_models.h - * \author (last) Peter Lucia - * \date (last) 02-Sep-2020 - * \author (original) Behrouz NematiPour - * \date (original) 21-Apr-2020 + * \file tst_models.h + * \author (last) Behrouz NematiPour + * \date (last) 22-Feb-2024 + * \author (original) Behrouz NematiPour + * \date (original) 21-Apr-2020 * */ #pragma once @@ -32,11 +32,9 @@ void tst_MTreatmentRanges (); // Treatment Start / Stop - void tst_MStartTreatmentResponse_data(); - void tst_MStartTreatmentResponse(); - void tst_MEndTreatmentResponse_data(); - void tst_MEndTreatmentResponse(); - void tst_MStartTreatmentRequest(); + void tst_MAdjustInitTreatmentResponse_data(); + void tst_MAdjustInitTreatmentResponse(); + void tst_MInitTreatmentRequest(); void tst_MEndTreatmentRequest(); // - Treatment Adjustments @@ -69,10 +67,6 @@ void tst_MAdjustPressuresLimitsResponse_data (); void tst_MAdjustPressuresLimitsResponse (); - // -- Treatment Saline Bolus - void tst_MSalineBolusResponse_data(); - void tst_MSalineBolusResponse(); - // -- Treatment Heparin void tst_MHeparinResponse_data(); void tst_MHeparinResponse(); @@ -116,25 +110,387 @@ void tst_MTreatmentHeparinData(); void tst_MPowerOff_data(); void tst_MPowerOff(); - void tst_MPrimingData_data(); - void tst_MPrimingData(); + void tst_MPreTreatmentPrime_data(); + void tst_MPreTreatmentPrime(); + // Treatment Parameters + void tst_MTreatmentParametersResp_data(); + void tst_MTreatmentParametersResp(); + void tst_MAdjustTreatmentLogResponse_data(); + void tst_MAdjustTreatmentLogResponse(); + void tst_MHDSyringePump_data(); + void tst_MHDSyringePump(); + void tst_MHDAirTrapData_data(); + void tst_MHDAirTrapData(); + void tst_MHDBloodLeakData_data(); + void tst_MHDBloodLeakData(); + void tst_MHDAccelerometer_data(); + void tst_MHDAccelerometer(); + void tst_MHDUsageInfoResponse_data(); + void tst_MHDUsageInfoResponse(); + void tst_MHDAirBubbleData_data(); + void tst_MHDAirBubbleData(); + void tst_MPreTreatmentStates_data(); + void tst_MPreTreatmentStates(); + void tst_MPreTreatmentSelfTestNoCartridge_data(); + void tst_MPreTreatmentSelfTestNoCartridge(); + void tst_MPreTreatmentSelfTestDry_data(); + void tst_MPreTreatmentSelfTestDry(); + void tst_MPostTreatmentStates_data(); + void tst_MPostTreatmentStates(); + void tst_MTreatmentStop_data(); + void tst_MTreatmentStop(); + void tst_MTreatmentRinseback_data(); + void tst_MTreatmentRinseback(); + void tst_MTreatmentRecirculate_data(); + void tst_MTreatmentRecirculate(); + void tst_MTreatmentBloodPrime_data(); + void tst_MTreatmentBloodPrime(); + void tst_MTreatmentLogEventData_data(); + void tst_MTreatmentLogEventData(); + void tst_MTreatmentLogAvrgeData_data(); + void tst_MTreatmentLogAvrgeData(); + void tst_MTreatmentLogAlarmData_data(); + void tst_MTreatmentLogAlarmData(); + + // data post + void tst_MHDRTCEpochData_data(); + void tst_MHDRTCEpochData(); + void tst_MHDPostSingleResult_data(); + void tst_MHDPostSingleResult(); + void tst_MHDPostFinalResult_data(); + void tst_MHDPostFinalResult(); + + // hd/adjustments/settings + void tst_MAdjustHDAlarmVolumeResponse_data(); + void tst_MAdjustHDAlarmVolumeResponse(); + void tst_MAdjustHDDateTimeResponse_data(); + void tst_MAdjustHDDateTimeResponse(); + void tst_MAdjustServiceModeResponse_data(); + void tst_MAdjustServiceModeResponse(); + void tst_MAdjustVersionsHDResponse_data(); + void tst_MAdjustVersionsHDResponse(); + void tst_MAdjustServiceDatesHDResponse_data(); + void tst_MAdjustServiceDatesHDResponse(); + + // hd/adjustments/treatment + void tst_MAdjustRinsebackResponse_data(); + void tst_MAdjustRinsebackResponse(); + void tst_MAdjustRecirculateResponse_data(); + void tst_MAdjustRecirculateResponse(); + void tst_MAdjustTreatmentEndResponse_data(); + void tst_MAdjustTreatmentEndResponse(); + void tst_MAdjustSalineResponse_data(); + void tst_MAdjustSalineResponse(); + + // hd/adjustments/pretreatment + void tst_MAdjustWaterSampleResponse_data(); + void tst_MAdjustWaterSampleResponse(); + void tst_MAdjustStartTreatmentResponse_data(); + void tst_MAdjustStartTreatmentResponse(); + void tst_MAdjustPatientConnectionConfirmResponse_data(); + void tst_MAdjustPatientConnectionConfirmResponse(); + void tst_MAdjustPatientConnectionBeginResponse_data(); + void tst_MAdjustPatientConnectionBeginResponse(); + void tst_MAdjustDisposablesPrimeResponse_data(); + void tst_MAdjustDisposablesPrimeResponse(); + void tst_MAdjustDisposablesConfirmResponse_data(); + void tst_MAdjustDisposablesConfirmResponse(); + + // hd/adjustments/posttreatment + void tst_MAdjustPatientDisconnectionConfirmResponse_data(); + void tst_MAdjustPatientDisconnectionConfirmResponse(); + void tst_MAdjustDisposablesRemovalConfirmResponse_data(); + void tst_MAdjustDisposablesRemovalConfirmResponse(); + + // hd/adjustments/disinfect + void tst_MAdjustDisinfectStartResponse_data(); + void tst_MAdjustDisinfectStartResponse(); + void tst_MAdjustDisinfectModeResponse_data(); + void tst_MAdjustDisinfectModeResponse(); + + // hd/alarm/ + void tst_MAlarmActiveListResponse_data(); + void tst_MAlarmActiveListResponse(); + void tst_MAlarmClearedCondition_data(); + void tst_MAlarmClearedCondition(); + + // dg/adjustment/settings + void tst_MAdjustDGCleaningUsageResponse_data(); + void tst_MAdjustDGCleaningUsageResponse(); + void tst_MAdjustDGDateTimeResponse_data(); + void tst_MAdjustDGDateTimeResponse(); + void tst_MAdjustServiceDatesDGResponse_data(); + void tst_MAdjustServiceDatesDGResponse(); + void tst_MAdjustVersionsDGResponse_data(); + void tst_MAdjustVersionsDGResponse(); + void tst_MDGConductivityData_data(); + void tst_MDGConductivityData(); + void tst_MDuetRoWaterModeDGr_data(); + void tst_MDuetRoWaterModeDGr(); + + // dg/data + void tst_MDGAccelerometer_data(); + void tst_MDGAccelerometer(); + + // dg/data/pretreatment + void tst_MDGFilterFlush_data(); + void tst_MDGFilterFlush(); + + // dg/data/post + void tst_MDGPostSingleResult_data(); + void tst_MDGPostSingleResult(); + void tst_MDGPostFinalResult_data(); + void tst_MDGPostFinalResult(); + + // ui/data + void tst_MUIBloodPressure_data(); + void tst_MUIBloodPressure(); + + // confirm + void tst_MDuetConfirmHDi_data(); + void tst_MDuetConfirmHDi(); + // Alarms void tst_MAlarmStatus_text(); - void tst_MAlarmStatus_data(); void tst_MAlarmStatus(); - void tst_MAlarmTriggered_data(); void tst_MAlarmTriggered(); - + void tst_MAbstractDynamic_data(); + void tst_MAbstractDynamic(); void tst_MAlarmCleared_data(); void tst_MAlarmCleared(); - void tst_MAlarmAcknowledgeRequest(); + //Misc function code coverage + void tst_DG_headerCoverage(); + void tst_HD_headerCoverage(); + void tst_MDisinfectAdjustModeRequests_ToStrings(); + void tst_MPostTreatmentAdjustRequests_ToStrings(); + void tst_modelsHeader_Coverage(); +private: + class HelperFunctions_tstModel + { + protected: + explicit HelperFunctions_tstModel() {} - // Treatment Parameters - void tst_MTreatmentParametersResp_data(); - void tst_MTreatmentParametersResp(); + public : + /* + * generateDataSet + * @params vDataNames - the list of string names of the data structure's member variable. + * + * @brief The main purpose of this function is to properly generate the QTest::newRow for data used in the testing + * This function is making use of two additional helper functions that will create the appropriate test data + * + * For example, if the Model::MSomeExampleModel has a data structure that is: + * struct { + * Types::U32 mAccepted ; + * Types::U32 mReason ; + * Types::U32 mBloodFlowRate ; + * Types::U32 mDialysateFlowRate ; + * } _data; + * + * We would expect the data set to be the following: + * QTest::addColumn("errorIndex"); + * QTest::addColumn("data"); + * QTest::newRow("msg complete") << 0 << QByteArray::fromHex(QByteArray("00" "01" "02" "03" "04" "05" "06" "07" "08" "09" "0A" "0B")); + * QTest::newRow("mAccepted ") << 1 << QByteArray::fromHex(QByteArray()); + * QTest::newRow("mAccepted ") << 1 << QByteArray::fromHex(QByteArray("00")); + * QTest::newRow("mAccepted ") << 1 << QByteArray::fromHex(QByteArray("00" "01")); + * QTest::newRow("mAccepted ") << 1 << QByteArray::fromHex(QByteArray("00" "01" "02")); + * QTest::newRow("mReason ") << 2 << QByteArray::fromHex(QByteArray("00" "01" "02" "03")); + * QTest::newRow("mReason ") << 2 << QByteArray::fromHex(QByteArray("00" "01" "02" "03" "04")); + * QTest::newRow("mReason ") << 2 << QByteArray::fromHex(QByteArray("00" "01" "02" "03" "04" "05")); + * QTest::newRow("mReason ") << 2 << QByteArray::fromHex(QByteArray("00" "01" "02" "03" "04" "05" "06")); + * QTest::newRow("mBloodFlowRate") << 3 << QByteArray::fromHex(QByteArray("00" "01" "02" "03" "04" "05" "06" "07")); + * QTest::newRow("mBloodFlowRate") << 3 << QByteArray::fromHex(QByteArray("00" "01" "02" "03" "04" "05" "06" "07" "08")); + * QTest::newRow("mBloodFlowRate") << 3 << QByteArray::fromHex(QByteArray("00" "01" "02" "03" "04" "05" "06" "07" "08" "09")); + * QTest::newRow("mBloodFlowRate") << 3 << QByteArray::fromHex(QByteArray("00" "01" "02" "03" "04" "05" "06" "07" "08" "09" "0A")); + * QTest::newRow("mDialysateFlowRate") << 4 << QByteArray::fromHex(QByteArray("00" "01" "02" "03" "04" "05" "06" "07" "08" "09" "0A" "0B")); + * QTest::newRow("mDialysateFlowRate") << 4 << QByteArray::fromHex(QByteArray("00" "01" "02" "03" "04" "05" "06" "07" "08" "09" "0A" "0B" "0C")); + * QTest::newRow("mDialysateFlowRate") << 4 << QByteArray::fromHex(QByteArray("00" "01" "02" "03" "04" "05" "06" "07" "08" "09" "0A" "0B" "0C" "0D")); + * QTest::newRow("mDialysateFlowRate") << 4 << QByteArray::fromHex(QByteArray("00" "01" "02" "03" "04" "05" "06" "07" "08" "09" "0A" "0B" "0C" "0D" "0E")); + * + * This function is called as : + * HelperFunctions_tstModel::generate_ByteDataSet( { "mAccepted", "mReason", "mBloodFlowRate", "mDialysateFlowRate" } ); + * + * Overall Structure: + * - There are two columns: errorIndex and data. + * - The row with the dataTag as "msg complete" will contain the number of variables * 4 (bytes), which is a complete message with all the data elements + * - The first parameter is handled as a special case where it will contain a zero array, a one, two, three element array. + * - All the other parameters beyond the first one contains four rows, where each row contains one more element than the last to build up from an incomplete + * data element. + * - The errorIndex only incrementals with each set of four rows. + * + * - totalNameLength overrides the total length count of dataNames for the "msg complete" data set. default, it uses the length of the passed QStringList + */ + static int generate_ByteDataSet(const QStringList& vDataNames, int totalNameLength = -1 ) + { + QTest::addColumn("errorIndex"); + QTest::addColumn("data"); + + int errorIndex = 0; + const int totalLengthForComplete = totalNameLength > 0 ? totalNameLength : vDataNames.length(); + QTest::newRow("msg complete") << errorIndex << QByteArray::fromHex(createByteDataArray(totalLengthForComplete*4)); + + // Special case for the first parameter of the data list: + errorIndex++; // increment vErrorIndex to 1 + QTest::newRow(vDataNames.at(0).toUtf8()) << errorIndex << QByteArray::fromHex(QByteArray()); + QTest::newRow(vDataNames.at(0).toUtf8()) << errorIndex << QByteArray::fromHex(QByteArray("00")); + QTest::newRow(vDataNames.at(0).toUtf8()) << errorIndex << QByteArray::fromHex(QByteArray("00" "01")); + QTest::newRow(vDataNames.at(0).toUtf8()) << errorIndex << QByteArray::fromHex(QByteArray("00" "01" "02")); + + // do the newRow for the rest of the parameters + int lastElementCount = 3; // The number of elements in the last row + for(int dataNameIndex = 1; dataNameIndex < vDataNames.length(); dataNameIndex++) + { + errorIndex++; // increment the error index for each set of 4 rows + QString paramName = vDataNames.at(dataNameIndex); + lastElementCount = addRowsForByteData(paramName.toUtf8(), errorIndex, lastElementCount+1); + } + return errorIndex; + } + + + /* + * addBit_Data + * @params dataTag - the row tag + * @params errorIndexStart - the starting index for errorIndex variable/column + * @params flagStartAt - The initial starting point to set flag to true + * @params totalRows - the total number of rows to generate, default is 8 rows for 8-bits + * + * @brief The main purpose of this function is to properly generate the QTest::newRow for data used in the testing + * This function is making use of one additional helper function that will convert the bit array to a byte array before + * inserting into the row + * + * For example, if the Model::MSomeExampleModel has a data structure that is: + * struct { + * Types::U8 mAccepted ; + * } _data; + * + * We would expect the data set to be the following: + * QTest::addColumn("errorIndex"); + * QTest::addColumn("data"); + * QTest::newRow("mAccepted ") << 1 << converted_bitArray(one_byte_first_bit_set); + * QTest::newRow("mAccepted ") << 1 << converted_bitArray(one_byte_second_bit_set); + * QTest::newRow("mAccepted ") << 1 << converted_bitArray(one_byte_third_bit_set); + * ...and so on for 8 rows, since 8-bits = 1 byte + * + * This function is called as : + * HelperFunctions::addBit_Data( "mAccepted", 0, 0); // default 8-bits so 8 rows + * + * Overall Structure: + * - There are two columns: errorIndex and data. + * -- if vExpectedIndex is not negative, it is expected that there are three columns (errorIndex, data, and expectedIndex) + */ + static int addTestDataRow_bitRows(const QString& vDataTag, const int vErrorIndex, const int vBitCount, const int vExpectedIndex = -1) + { + int currentBitCount = vBitCount; + for(int i=0; i<8; i++) + { + if(vExpectedIndex < 0) + { + QTest::newRow(vDataTag.toUtf8()) << vErrorIndex << HelperFunctions_tstModel::makeByteArray(currentBitCount++); + } + else + { + QTest::newRow(vDataTag.toUtf8()) << vErrorIndex << HelperFunctions_tstModel::makeByteArray(currentBitCount++) << vExpectedIndex; + } + } + return currentBitCount; + } + + static int generate_bitDataRow(const QString& vDataTag, const int vErrorIndexStart, const int vFlagStartAt, const int vTotalRows = 8) + { + int currentFlags = 0; + for(int rowCountIndex = 0; rowCountIndex < vTotalRows; rowCountIndex++) + { + currentFlags = vFlagStartAt + rowCountIndex; + QTest::newRow(vDataTag.toUtf8()) << vErrorIndexStart << makeByteArray(currentFlags); + } + return currentFlags; + } + + static QByteArray makeByteArray(const int vNumberOfBits, bool vDefaultSet = true) + { + QBitArray flag(vNumberOfBits, vDefaultSet); + QByteArray dataByteArray = bitsToBytes(flag); + return dataByteArray; + } + + static QByteArray createByteDataArray(int vCount) + { + /* + * Based on the existing tests and test data, this helper function will reduce the need to copy-paste + * and creating data sets by hand. The function generates a QByteArray of elements "00"..."xx" up to + * vCount of them. + * + * Expected return for a vCount == 5 is: + * { "00" "01" "02" "03" "04" } + */ + QByteArray returnArray = {}; + for(int i = 0; i int expectedIndex + */ + int elementCount = vStartArrayCount; + if(vExpectedIndex < 0) + { + QTest::newRow(vKey) << vErrorIndex << QByteArray::fromHex(createByteDataArray(elementCount)); elementCount++; + QTest::newRow(vKey) << vErrorIndex << QByteArray::fromHex(createByteDataArray(elementCount)); elementCount++; + QTest::newRow(vKey) << vErrorIndex << QByteArray::fromHex(createByteDataArray(elementCount)); elementCount++; + QTest::newRow(vKey) << vErrorIndex << QByteArray::fromHex(createByteDataArray(elementCount)); + } else { + QTest::newRow(vKey) << vErrorIndex << QByteArray::fromHex(createByteDataArray(elementCount)) << vExpectedIndex; elementCount++; + QTest::newRow(vKey) << vErrorIndex << QByteArray::fromHex(createByteDataArray(elementCount)) << vExpectedIndex; elementCount++; + QTest::newRow(vKey) << vErrorIndex << QByteArray::fromHex(createByteDataArray(elementCount)) << vExpectedIndex; elementCount++; + QTest::newRow(vKey) << vErrorIndex << QByteArray::fromHex(createByteDataArray(elementCount)) << vExpectedIndex; + } + return elementCount; // returns the last element count used + } + private: + static QByteArray bitsToBytes(QBitArray bits) { + /* + * Converts a QBitArray to a QByteArray + * + */ + QByteArray bytes; + + // Determine if there is a partially full byte + bool isPartialByteExist = (bits.count() % 8) > 0 ; + int addPartialByte = isPartialByteExist ? 1 : 0; + int fullBytesCount = bits.count() / 8 ; + + // Resize byte array to fit expected bytes for bits passed + bytes.resize(fullBytesCount + addPartialByte); + + // initialize with 0s + bytes.fill(0); + + // copy the bits into the byte array based on index + for(int bit = 0; bit < bits.count(); ++bit) + bytes[bit/8] = ( bytes.at(bit/8) | ((bits[bit]?1:0)<<(bit%8))); + + return bytes; + } + + }; };