Index: unittests/tst_models.h =================================================================== diff -u -r914a8c335771f23cc98780cfd5b0a48c9b44a3b9 -rded9f686d2c96837cc4a23f54a917d04cd257bd4 --- unittests/tst_models.h (.../tst_models.h) (revision 914a8c335771f23cc98780cfd5b0a48c9b44a3b9) +++ unittests/tst_models.h (.../tst_models.h) (revision ded9f686d2c96837cc4a23f54a917d04cd257bd4) @@ -260,4 +260,229 @@ void tst_MAlarmCleared_data(); void tst_MAlarmCleared(); void tst_MAlarmAcknowledgeRequest(); + +private: + class HelperFunctions_tstModel + { + protected: + explicit HelperFunctions_tstModel() {} + + 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; + } + + }; };