From 88438ea5863c358f7c3e06c3f59aec5b5b4a791f Mon Sep 17 00:00:00 2001 From: lains <383502+lains@users.noreply.github.com> Date: Wed, 15 May 2024 09:50:42 +0200 Subject: [PATCH] Adding TIC::DatasetView::labelEquals() and TIC::DatasetView::dataToUint32() with associated UTs --- include/TIC/DatasetView.h | 17 ++++ include/TIC/Unframer.h | 2 +- src/TIC/DatasetView.cpp | 19 ++++ test/src/TicDatasetView_tests.cpp | 156 +++++++++++++++++++++++++++++- 4 files changed, 192 insertions(+), 2 deletions(-) diff --git a/include/TIC/DatasetView.h b/include/TIC/DatasetView.h index fc63abf..514570b 100644 --- a/include/TIC/DatasetView.h +++ b/include/TIC/DatasetView.h @@ -124,6 +124,23 @@ class DatasetView { */ static uint32_t uint32FromValueBuffer(const uint8_t* buf, unsigned int cnt); + /** + * @brief Check if the current data label matches the one provided as argument + * + * @param cString The C-style string to compare to + * + * @return true if the data is valid and matches the provided string + */ + bool labelEquals(const char* cString) const; + + /** + * @brief Converts the current data value to an 32-bit unsigned int + * + * @return The decoded unsigned int value, or -1 in case of errors (value does not contain a positive number or dataset is invalid) + */ + uint32_t dataToUint32() const; + + private: static uint8_t computeCRC(const uint8_t* bytes, unsigned int count); diff --git a/include/TIC/Unframer.h b/include/TIC/Unframer.h index 9951244..b69af48 100644 --- a/include/TIC/Unframer.h +++ b/include/TIC/Unframer.h @@ -66,7 +66,7 @@ class Unframer { /** * @brief Construct a new TIC::Unframer object * - * @param onNewFrameBytes A FOnNewFrameBytesFunc function to invoke for each byte received in the current TIC frame received + * @param onNewFrameBytes A FOnNewFrameBytesFunc function to invoke for each byte received in the current TIC frame * @param onFrameComplete A FOnFrameCompleteFunc function to invoke after a full TiC frame has been received * @param parserFuncContext A user-defined pointer that will be passed as last argument when invoking onFrameComplete() * diff --git a/src/TIC/DatasetView.cpp b/src/TIC/DatasetView.cpp index 1780e80..2c2b6e6 100644 --- a/src/TIC/DatasetView.cpp +++ b/src/TIC/DatasetView.cpp @@ -262,6 +262,7 @@ horodate() { this->dataSz = 0; if (computedCrc != crcByte) { + // printf("Invalid CRC character, got '%c', expected '%c'\n", crcByte, computedCrc); this->decodedType = TIC::DatasetView::DatasetType::WrongCRC; this->labelSz = 0; this->dataSz = 0; @@ -337,6 +338,9 @@ uint8_t TIC::DatasetView::computeCRC(const uint8_t* bytes, unsigned int count) { uint32_t TIC::DatasetView::uint32FromValueBuffer(const uint8_t* buf, unsigned int cnt) { uint32_t result = 0; + if (cnt == 0) + return -1; /* No digit at all */ + for (unsigned int idx = 0; idx < cnt; idx++) { uint8_t digit = buf[idx]; if (digit < '0' || digit > '9') { /* Invalid decimal value */ @@ -353,3 +357,18 @@ uint32_t TIC::DatasetView::uint32FromValueBuffer(const uint8_t* buf, unsigned in } return result; } + +bool TIC::DatasetView::labelEquals(const char* cString) const { + if (cString == nullptr) + return false; + if (!this->isValid()) + return false; + size_t cStringLen = strlen(cString); + return (this->labelSz == cStringLen && memcmp(this->labelBuffer, cString, cStringLen) == 0); +} + +uint32_t TIC::DatasetView::dataToUint32() const { + if (!this->isValid() || this->dataBuffer == nullptr) + return -1; + return TIC::DatasetView::uint32FromValueBuffer(this->dataBuffer, this->dataSz); +} \ No newline at end of file diff --git a/test/src/TicDatasetView_tests.cpp b/test/src/TicDatasetView_tests.cpp index c4b7b53..1c1a24b 100644 --- a/test/src/TicDatasetView_tests.cpp +++ b/test/src/TicDatasetView_tests.cpp @@ -413,6 +413,37 @@ TEST(TicDatasetView_tests, TicDatasetView_standard_with_horodate_and_value) { } } +TEST(TicDatasetView_tests, TicDatasetView_historical_with_value) { + const char dataset[] = "PAPP 00750 -"; + const uint8_t* datasetBuf = reinterpret_cast(dataset); + + TIC::DatasetView dv((const uint8_t*)datasetBuf, static_cast(strlen(dataset))); + + if (!dv.isValid()) { + FAILF("Dataset shoud be valid"); + } + + if (dv.labelBuffer == nullptr) { + FAILF("NULL labelBuffer"); + } + std::vector labelBufferVec(dv.labelBuffer, dv.labelBuffer + dv.labelSz); + if (labelBufferVec != std::vector({'P', 'A', 'P', 'P'})) { + FAILF("Wrong dataset label: %s", vectorToHexString(labelBufferVec).c_str()); + } + + if (dv.dataBuffer == nullptr) { + FAILF("NULL dataBuffer"); + } + std::vector dataBufferVec(dv.dataBuffer, dv.dataBuffer + dv.dataSz); + if (dataBufferVec != std::vector({'0', '0', '7', '5', '0'})) { + FAILF("Wrong dataset data: %s", vectorToHexString(dataBufferVec).c_str()); + } + + if (dv.horodate.isValid) { + FAILF("Expected no horodate"); + } +} + /** * @brief Send the content of a file to a TIC::Unframer, cutting it into chunks * @@ -653,6 +684,120 @@ TEST(TicDatasetView_tests, TicDatasetView_uint32FromValueBuffer) { } } +TEST(TicDatasetView_tests, TicDatasetView_labelEquals) { + const char dataset[] = "PAPP 00750 -"; + const uint8_t* datasetBuf = reinterpret_cast(dataset); + + TIC::DatasetView dv((const uint8_t*)datasetBuf, static_cast(strlen(dataset))); + + if (dv.labelBuffer == nullptr) { + FAILF("NULL labelBuffer"); + } + + if (!dv.labelEquals("PAPP")) { + FAILF("Expected label match"); + } + if (dv.labelEquals("PAP")) { + FAILF("Expected label mismatch"); + } +} + +TEST(TicDatasetView_tests, TicDatasetView_dataToUint32OnValidValue) { + const char dataset[] = "URMS1\t230\t?"; + const uint8_t* datasetBuf = reinterpret_cast(dataset); + + TIC::DatasetView dv((const uint8_t*)datasetBuf, static_cast(strlen(dataset))); + + if (dv.dataBuffer == nullptr) { + FAILF("NULL dataBuffer"); + } + + if (dv.dataToUint32() != 230) { + FAILF("Failed to convert label to uint32"); + } +} + +TEST(TicDatasetView_tests, TicDatasetView_dataToUint32OnValidValueWith0Prefix) { + const char dataset[] = "PAPP 00750 -"; + const uint8_t* datasetBuf = reinterpret_cast(dataset); + + TIC::DatasetView dv((const uint8_t*)datasetBuf, static_cast(strlen(dataset))); + + if (dv.dataBuffer == nullptr) { + FAILF("NULL dataBuffer"); + } + if (dv.dataToUint32() != 750) { + FAILF("Failed to convert label to uint32"); + } +} + +TEST(TicDatasetView_tests, TicDatasetView_dataToUint32OnValidValue0) { + const char dataset[] = "EASD02\t000000000\t!"; + const uint8_t* datasetBuf = reinterpret_cast(dataset); + + TIC::DatasetView dv((const uint8_t*)datasetBuf, static_cast(strlen(dataset))); + + if (dv.dataBuffer == nullptr) { + FAILF("NULL dataBuffer"); + } + if (dv.dataToUint32() != 0) { + FAILF("Failed to convert label to uint32"); + } +} + +TEST(TicDatasetView_tests, TicDatasetView_dataToUint32OnNegativeValue) { + const char dataset[] = "IINST2 -002 8"; + const uint8_t* datasetBuf = reinterpret_cast(dataset); + + TIC::DatasetView dv((const uint8_t*)datasetBuf, static_cast(strlen(dataset))); + + if (dv.dataBuffer == nullptr) { + FAILF("NULL dataBuffer"); + } + if (!dv.isValid()) { + FAILF("Expecting a valid data"); + } + if (dv.dataToUint32() != (uint32_t)-1) { + FAILF("Should not convert invalid data to anything else than (uint32_t)-1"); + } +} + +TEST(TicDatasetView_tests, TicDatasetView_dataToUint32OnInvalidCRC) { + const char dataset[] = "PAPP 00750 A"; + const uint8_t* datasetBuf = reinterpret_cast(dataset); + + TIC::DatasetView dv((const uint8_t*)datasetBuf, static_cast(strlen(dataset))); + + if (dv.dataToUint32() != (uint32_t)-1) { + FAILF("Should not convert invalid data to anything else than (uint32_t)-1"); + } +} + +TEST(TicDatasetView_tests, TicDatasetView_dataToUint32OnNonDigitValue) { + const char dataset[] = "PAPP 0a75b P"; + const uint8_t* datasetBuf = reinterpret_cast(dataset); + + TIC::DatasetView dv((const uint8_t*)datasetBuf, static_cast(strlen(dataset))); + + if (!dv.isValid()) { + FAILF("Expecting a valid data"); + } + if (dv.dataToUint32() != (uint32_t)-1) { + FAILF("Should not convert invalid data to anything else than (uint32_t)-1"); + } +} + +TEST(TicDatasetView_tests, TicDatasetView_dataToUint32OnEmptyValue) { + const char dataset[] = "PAPP 1"; + const uint8_t* datasetBuf = reinterpret_cast(dataset); + + TIC::DatasetView dv((const uint8_t*)datasetBuf, static_cast(strlen(dataset))); + + if (dv.dataToUint32() != (uint32_t)-1) { + FAILF("Should not convert invalid data to anything else than (uint32_t)-1"); + } +} + TEST(TicHorodate_tests, TicHorodate_sample_date1) { char sampleHorodateAsCString[] = "H081225223518"; TIC::Horodate horodate = TIC::Horodate::fromLabelBytes(reinterpret_cast(sampleHorodateAsCString), strlen(sampleHorodateAsCString)); @@ -925,9 +1070,18 @@ void runTicDatasetViewAllUnitTests() { TicDatasetView_too_short(); TicDatasetView_valid_with_horodate_without_value(); TicDatasetView_standard_with_horodate_and_value(); - TicDatasetView_uint32FromValueBuffer(); + TicDatasetView_historical_with_value(); Chunked_sample_unframe_dsextract_decode_historical_TIC(); Chunked_sample_unframe_dsextract_decode_standard_TIC(); + TicDatasetView_uint32FromValueBuffer(); + TicDatasetView_labelEquals(); + TicDatasetView_dataToUint32OnValidValue(); + TicDatasetView_dataToUint32OnValidValueWith0Prefix(); + TicDatasetView_dataToUint32OnValidValue0(); + TicDatasetView_dataToUint32OnNegativeValue(); + TicDatasetView_dataToUint32OnInvalidCRC(); + TicDatasetView_dataToUint32OnNonDigitValue(); + TicDatasetView_dataToUint32OnEmptyValue(); TicHorodate_sample_date1(); TicHorodate_sample_date2(); TicHorodate_sample_season_NA();