diff --git a/CHANGELOG.md b/CHANGELOG.md index e2dcbe81c..c7d3b90b7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -32,6 +32,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ## Additions - Linux HAL: Add wiretapping option for I2C. Enabled with `FSFW_HAL_I2C_WIRETAPPING` defined to 1 +- Dedicated Version class and constant `fsfw::FSFW_VERSION` containing version information + inside `fsfw/version.h` PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/559 # [v4.0.0] diff --git a/src/fsfw/CMakeLists.txt b/src/fsfw/CMakeLists.txt index 12c673ed6..efb9f6c73 100644 --- a/src/fsfw/CMakeLists.txt +++ b/src/fsfw/CMakeLists.txt @@ -1,3 +1,7 @@ +target_sources(${LIB_FSFW_NAME} PRIVATE + version.cpp +) + # Core add_subdirectory(action) diff --git a/src/fsfw/FSFWVersion.h.in b/src/fsfw/FSFWVersion.h.in index 7935b2f61..19a562143 100644 --- a/src/fsfw/FSFWVersion.h.in +++ b/src/fsfw/FSFWVersion.h.in @@ -2,8 +2,8 @@ #define FSFW_VERSION_H_ // Versioning is kept in project CMakeLists.txt file -#define FSFW_VERSION @FSFW_VERSION@ -#define FSFW_SUBVERSION @FSFW_SUBVERSION@ -#define FSFW_REVISION @FSFW_REVISION@ +#define FSFW_VERSION_MAJOR @FSFW_VERSION@ +#define FSFW_VERSION_MINOR @FSFW_SUBVERSION@ +#define FSFW_VERSION_REVISION @FSFW_REVISION@ #endif /* FSFW_VERSION_H_ */ diff --git a/src/fsfw/version.cpp b/src/fsfw/version.cpp new file mode 100644 index 000000000..926e465ff --- /dev/null +++ b/src/fsfw/version.cpp @@ -0,0 +1,22 @@ +#include "version.h" +#include "fsfw/FSFWVersion.h" + +#include + +#ifdef major +#undef major +#endif + +#ifdef minor +#undef minor +#endif + +const fsfw::Version fsfw::FSFW_VERSION = {FSFW_VERSION_MAJOR, FSFW_VERSION_MINOR, + FSFW_VERSION_REVISION}; + +fsfw::Version::Version(uint32_t major, uint32_t minor, uint32_t revision) + : major(major), minor(minor), revision(revision) {} + +void fsfw::Version::getVersion(char* str, size_t maxLen) const { + snprintf(str, maxLen, "%d.%d.%d", major, minor, revision); +} diff --git a/src/fsfw/version.h b/src/fsfw/version.h new file mode 100644 index 000000000..7cddf1938 --- /dev/null +++ b/src/fsfw/version.h @@ -0,0 +1,64 @@ +#ifndef FSFW_SRC_FSFW_VERSION_H_ +#define FSFW_SRC_FSFW_VERSION_H_ + +#include "fsfw/FSFW.h" + +#if FSFW_CPP_OSTREAM_ENABLED == 1 +#include +#endif +#include + +namespace fsfw { + +class Version { + public: + Version(uint32_t major, uint32_t minor, uint32_t revision); + uint32_t major = 0; + uint32_t minor = 0; + uint32_t revision = 0; + + friend bool operator==(const Version& v1, const Version& v2) { + return (v1.major == v2.major and v1.minor == v2.minor and v1.revision == v2.revision); + } + + friend bool operator!=(const Version& v1, const Version& v2) { return not(v1 == v2); } + + friend bool operator<(const Version& v1, const Version& v2) { + return ((v1.major < v2.major) or (v1.major == v2.major and v1.minor < v2.minor) or + (v1.major == v2.major and v1.minor == v2.minor and v1.revision < v2.revision)); + } + + friend bool operator>(const Version& v1, const Version& v2) { + return not (v1 < v2) and not (v1 == v2); + } + + friend bool operator<=(const Version& v1, const Version& v2) { return ((v1 == v2) or (v1 < v2)); } + + friend bool operator>=(const Version& v1, const Version& v2) { return ((v1 == v2) or (v1 > v2)); } + +#if FSFW_CPP_OSTREAM_ENABLED == 1 + /** + * Print format to given ostream using format "major.minor.revision" + * @param os + * @param v + * @return + */ + friend std::ostream& operator<<(std::ostream& os, const Version& v) { + os << v.major << "." << v.minor << "." << v.revision; + return os; + } +#endif + + /** + * Get version as format "major.minor.revision" + * @param str + * @param maxLen + */ + void getVersion(char* str, size_t maxLen) const; +}; + +extern const fsfw::Version FSFW_VERSION; + +} // namespace fsfw + +#endif /* FSFW_SRC_FSFW_VERSION_H_ */ diff --git a/tests/src/fsfw_tests/unit/CMakeLists.txt b/tests/src/fsfw_tests/unit/CMakeLists.txt index a83e2f7f8..a8d31d88a 100644 --- a/tests/src/fsfw_tests/unit/CMakeLists.txt +++ b/tests/src/fsfw_tests/unit/CMakeLists.txt @@ -2,14 +2,13 @@ target_sources(${FSFW_TEST_TGT} PRIVATE CatchDefinitions.cpp CatchFactory.cpp printChar.cpp + version.cpp ) -# if(FSFW_CUSTOM_UNITTEST_RUNNER) - target_sources(${FSFW_TEST_TGT} PRIVATE - CatchRunner.cpp - CatchSetup.cpp - ) -# endif() +target_sources(${FSFW_TEST_TGT} PRIVATE + CatchRunner.cpp + CatchSetup.cpp +) add_subdirectory(testcfg) add_subdirectory(action) diff --git a/tests/src/fsfw_tests/unit/version.cpp b/tests/src/fsfw_tests/unit/version.cpp new file mode 100644 index 000000000..92a930dcc --- /dev/null +++ b/tests/src/fsfw_tests/unit/version.cpp @@ -0,0 +1,92 @@ + +#include "fsfw/version.h" + +#include + +#include "fsfw/serviceinterface.h" +#include "fsfw_tests/unit/CatchDefinitions.h" + +TEST_CASE("Version API Tests", "[TestVersionAPI]") { + // Check that major version is non-zero + REQUIRE(fsfw::FSFW_VERSION.major > 0); + uint32_t fsfwMajor = fsfw::FSFW_VERSION.major; + REQUIRE(fsfw::Version(255, 0, 0) > fsfw::FSFW_VERSION); + REQUIRE(fsfw::Version(255, 0, 0) >= fsfw::FSFW_VERSION); + REQUIRE(fsfw::Version(0, 0, 0) < fsfw::FSFW_VERSION); + REQUIRE(fsfw::Version(0, 0, 0) <= fsfw::FSFW_VERSION); + fsfw::Version v1 = fsfw::Version(1, 1, 1); + fsfw::Version v2 = fsfw::Version(1, 1, 1); + REQUIRE(v1 == v2); + REQUIRE(not (v1 < v2)); + REQUIRE(not (v1 > v2)); + REQUIRE(v1 <= v2); + REQUIRE(v1 >= v2); + v1.revision -= 1; + REQUIRE(v1 != v2); + REQUIRE(not (v1 == v2)); + REQUIRE(not (v1 > v2)); + REQUIRE(not (v1 >= v2)); + REQUIRE(v1 < v2); + REQUIRE(v1 <= v2); + v1.revision += 1; + v1.minor -= 1; + REQUIRE(v1 != v2); + REQUIRE(v1 < v2); + REQUIRE(v1 <= v2); + REQUIRE(not (v1 == v2)); + REQUIRE(not (v1 > v2)); + REQUIRE(not (v1 >= v2)); + v1.minor += 1; + v1.major -= 1; + REQUIRE(v1 != v2); + REQUIRE(v1 < v2); + REQUIRE(v1 <= v2); + REQUIRE(not (v1 == v2)); + REQUIRE(not (v1 > v2)); + REQUIRE(not (v1 >= v2)); + v1.major += 1; + REQUIRE(v1 == v2); + REQUIRE(v1 <= v2); + REQUIRE(v1 >= v2); + REQUIRE(not (v1 != v2)); + REQUIRE(not (v1 > v2)); + REQUIRE(not (v1 < v2)); + v1.major += 1; + v1.minor -= 1; + REQUIRE(v1 != v2); + REQUIRE(v1 > v2); + REQUIRE(v1 >= v2); + REQUIRE(not (v1 == v2)); + REQUIRE(not (v1 < v2)); + REQUIRE(not (v1 <= v2)); + v1.major -= 1; + v1.minor += 2; + v1.revision -= 1; + REQUIRE(v1 != v2); + REQUIRE(v1 > v2); + REQUIRE(v1 >= v2); + REQUIRE(not (v1 == v2)); + REQUIRE(not (v1 < v2)); + REQUIRE(not (v1 <= v2)); + v1.minor -= 1; + v1.revision += 2; + REQUIRE(v1 != v2); + REQUIRE(v1 > v2); + REQUIRE(v1 >= v2); + REQUIRE(not (v1 == v2)); + REQUIRE(not (v1 < v2)); + REQUIRE(not (v1 <= v2)); + v1.revision -= 1; + REQUIRE(v1 == v2); + REQUIRE(v1 <= v2); + REQUIRE(v1 >= v2); + REQUIRE(not (v1 != v2)); +#if FSFW_CPP_OSTREAM_ENABLED == 1 + sif::info << "v" << fsfw::FSFW_VERSION << std::endl; +#endif + char verString[10] = {}; + fsfw::FSFW_VERSION.getVersion(verString, sizeof(verString)); +#if FSFW_DISABLE_PRINTOUT == 0 + printf("v%s\n",verString); +#endif +}