diff --git a/FppTest/array/FormatTest.cpp b/FppTest/array/FormatTest.cpp index 4cda42e8e9..56ae8d64ab 100644 --- a/FppTest/array/FormatTest.cpp +++ b/FppTest/array/FormatTest.cpp @@ -11,19 +11,19 @@ // ====================================================================== #include "FppTest/array/FormatBoolArrayAc.hpp" -#include "FppTest/array/FormatU8ArrayAc.hpp" -#include "FppTest/array/FormatU16DecArrayAc.hpp" -#include "FppTest/array/FormatU32OctArrayAc.hpp" -#include "FppTest/array/FormatU64HexArrayAc.hpp" -#include "FppTest/array/FormatI8ArrayAc.hpp" -#include "FppTest/array/FormatI16DecArrayAc.hpp" -#include "FppTest/array/FormatI32OctArrayAc.hpp" -#include "FppTest/array/FormatI64HexArrayAc.hpp" +#include "FppTest/array/FormatCharArrayAc.hpp" #include "FppTest/array/FormatF32eArrayAc.hpp" #include "FppTest/array/FormatF32fArrayAc.hpp" #include "FppTest/array/FormatF64gArrayAc.hpp" +#include "FppTest/array/FormatI16DecArrayAc.hpp" +#include "FppTest/array/FormatI32OctArrayAc.hpp" +#include "FppTest/array/FormatI64HexArrayAc.hpp" +#include "FppTest/array/FormatI8ArrayAc.hpp" #include "FppTest/array/FormatStringArrayAc.hpp" -#include "FppTest/array/FormatCharArrayAc.hpp" +#include "FppTest/array/FormatU16DecArrayAc.hpp" +#include "FppTest/array/FormatU32OctArrayAc.hpp" +#include "FppTest/array/FormatU64HexArrayAc.hpp" +#include "FppTest/array/FormatU8ArrayAc.hpp" #include "FppTest/utils/Utils.hpp" #include "gtest/gtest.h" @@ -243,11 +243,11 @@ TEST_F(FormatTest, F64G) { } TEST_F(FormatTest, String) { - FormatString::StringSize80 testVals[FormatString::SIZE]; - char buf[80]; + Fw::ExternalString testVals[FormatString::SIZE]; + char buf[FormatString::SIZE][FormatString::ELEMENT_BUFFER_SIZE]; for (U32 i = 0; i < FormatString::SIZE; i++) { - FppTest::Utils::setString(buf, sizeof(buf)); - testVals[i] = buf; + testVals[i].setBuffer(&buf[i][0], sizeof buf[i]); + FppTest::Utils::setString(&buf[i][0], sizeof buf[i]); } FormatString a(testVals); diff --git a/FppTest/array/README.md b/FppTest/array/README.md index e2b06345e7..d08734e7f9 100644 --- a/FppTest/array/README.md +++ b/FppTest/array/README.md @@ -2,11 +2,11 @@ This directory contains unit tests for the FPP array code generator. -* ArrayToStringTest: Tests array toString() and ostream operator functions -* FormatTest: Tests FPP format strings +* `ArrayToStringTest`: Tests array `toString()` and `ostream` operator functions +* `FormatTest`: Tests FPP format strings To use this directory, you must have installed F Prime, and you must be inside the F Prime Python virtual environment. * To build the tests, run `fprime-util build --ut`. -* To run the tests, run `fprime-util check`. \ No newline at end of file +* To run the tests, run `fprime-util check`. diff --git a/FppTest/array/main.cpp b/FppTest/array/main.cpp index 45760e5b38..98cdbdf7c8 100644 --- a/FppTest/array/main.cpp +++ b/FppTest/array/main.cpp @@ -14,12 +14,11 @@ #include "FppTest/array/StringArrayAc.hpp" #include "FppTest/array/StructArrayAc.hpp" #include "FppTest/array/Uint32ArrayArrayAc.hpp" -#include "FppTest/array/String100ArrayAc.hpp" - #include "FppTest/typed_tests/ArrayTest.hpp" #include "FppTest/typed_tests/StringTest.hpp" #include "FppTest/utils/Utils.hpp" - +#include "Fw/Types/ExternalString.hpp" +#include "Fw/Types/StringTemplate.hpp" #include "STest/Random/Random.hpp" #include "gtest/gtest.h" @@ -56,13 +55,26 @@ void FppTest::Array::setTestVals(E (&a)[Enum::SIZE]) { } } +static char stringDefaultValsBuffer[::String::SIZE][::String::ELEMENT_BUFFER_SIZE]; + +template<> +void FppTest::Array::setDefaultVals + (Fw::ExternalString (&a)[::String::SIZE]) { + for (U32 i = 0; i < ::String::SIZE; i++) { + char *const buffer = &stringDefaultValsBuffer[i][0]; + a[i].setBuffer(buffer, ::String::ELEMENT_BUFFER_SIZE); + } +} + +static char stringTestValsBuffer[::String::SIZE][::String::ELEMENT_BUFFER_SIZE]; + template<> void FppTest::Array::setTestVals - (::String::StringSize80 (&a)[::String::SIZE]) { - char buf[80]; + (Fw::ExternalString (&a)[::String::SIZE]) { for (U32 i = 0; i < ::String::SIZE; i++) { - FppTest::Utils::setString(buf, sizeof(buf)); - a[i] = buf; + char *const buffer = &stringTestValsBuffer[i][0]; + a[i].setBuffer(buffer, ::String::ELEMENT_BUFFER_SIZE); + FppTest::Utils::setString(buffer, ::String::ELEMENT_BUFFER_SIZE, 1); } } @@ -97,7 +109,7 @@ Enum FppTest::Array::getMultiElementConstructedArray template<> ::String FppTest::Array::getMultiElementConstructedArray<::String> - (::String::StringSize80 (&a)[::String::SIZE]) { + (Fw::ExternalString (&a)[::String::SIZE]) { return ::String(a[0], a[1], a[2]); } @@ -116,11 +128,11 @@ Uint32Array FppTest::Array::getMultiElementConstructedArray // Specializations for serialized size template <> U32 FppTest::Array::getSerializedSize<::String> - (::String::StringSize80 (&a)[::String::SIZE]) { + (Fw::ExternalString (&a)[::String::SIZE]) { U32 serializedSize = 0; for (U32 i = 0; i < ::String::SIZE; i++) { - serializedSize += a[i].length() + sizeof(FwBuffSizeType); + serializedSize += a[i].serializedSize(); } return serializedSize; @@ -128,16 +140,11 @@ U32 FppTest::Array::getSerializedSize<::String> // Instantiate string tests for arrays using StringTestImplementations = ::testing::Types< - String::StringSize80, - String100::StringSize100 + Fw::StringTemplate<80>, + Fw::StringTemplate<100> >; INSTANTIATE_TYPED_TEST_SUITE_P(Array, StringTest, StringTestImplementations); -template<> -U32 FppTest::String::getSize() { - return 100; -} - int main(int argc, char* argv[]) { ::testing::InitGoogleTest(&argc, argv); STest::Random::seed(); diff --git a/FppTest/array/string.fpp b/FppTest/array/string.fpp index fc2c052005..027398be8a 100644 --- a/FppTest/array/string.fpp +++ b/FppTest/array/string.fpp @@ -1,3 +1 @@ array String = [3] string - -array String100 = [3] string size 100 diff --git a/FppTest/component/README.md b/FppTest/component/README.md index 6d89772c69..319458b4f6 100644 --- a/FppTest/component/README.md +++ b/FppTest/component/README.md @@ -5,5 +5,14 @@ This directory contains unit tests for the FPP component code generator. To use this directory, you must have installed F Prime, and you must be inside the F Prime Python virtual environment. +The following subdirectories contain tests that you can run: + +* `active`: Active component tests +* `passive`: Passive component tests +* `queued`: Queued component tests +* `empty`: Basic tests of an empty component + +In any of these directories, you can do the following: + * To build the tests, run `fprime-util build --ut`. * To run the tests, run `fprime-util check`. diff --git a/FppTest/component/active/ActiveTest.cpp b/FppTest/component/active/ActiveTest.cpp index 1a82380e39..6035e50318 100644 --- a/FppTest/component/active/ActiveTest.cpp +++ b/FppTest/component/active/ActiveTest.cpp @@ -104,10 +104,10 @@ void ActiveTest :: stringArgsAsync_handler( const NATIVE_INT_TYPE portNum, - const str80String &str80, - str80RefString &str80Ref, - const str100String &str100, - str100RefString &str100Ref + const Fw::StringBase &str80, + Fw::StringBase &str80Ref, + const Fw::StringBase &str100, + Fw::StringBase &str100Ref ) { this->stringArgsOut_out( @@ -332,10 +332,10 @@ void ActiveTest :: stringArgsGuarded_handler( const NATIVE_INT_TYPE portNum, - const str80String &str80, - str80RefString &str80Ref, - const str100String &str100, - str100RefString &str100Ref + const Fw::StringBase &str80, + Fw::StringBase &str80Ref, + const Fw::StringBase &str100, + Fw::StringBase &str100Ref ) { this->stringArgsOut_out( @@ -350,10 +350,10 @@ void ActiveTest :: stringArgsSync_handler( const NATIVE_INT_TYPE portNum, - const str80String &str80, - str80RefString &str80Ref, - const str100String &str100, - str100RefString &str100Ref + const Fw::StringBase &str80, + Fw::StringBase &str80Ref, + const Fw::StringBase &str100, + Fw::StringBase &str100Ref ) { this->stringArgsOut_out( diff --git a/FppTest/component/active/ActiveTest.hpp b/FppTest/component/active/ActiveTest.hpp index 91905d665f..b984dd0d42 100644 --- a/FppTest/component/active/ActiveTest.hpp +++ b/FppTest/component/active/ActiveTest.hpp @@ -203,28 +203,28 @@ class ActiveTest : //! Handler implementation for stringArgsAsync void stringArgsAsync_handler( NATIVE_INT_TYPE portNum, //!< The port number - const StringArgsPortStrings::StringSize80& str80, //!< A string of size 80 - StringArgsPortStrings::StringSize80& str80Ref, - const StringArgsPortStrings::StringSize100& str100, //!< A string of size 100 - StringArgsPortStrings::StringSize100& str100Ref + const Fw::StringBase& str80, //!< A string of size 80 + Fw::StringBase& str80Ref, + const Fw::StringBase& str100, //!< A string of size 100 + Fw::StringBase& str100Ref ); //! Handler implementation for stringArgsGuarded void stringArgsGuarded_handler( NATIVE_INT_TYPE portNum, //!< The port number - const StringArgsPortStrings::StringSize80& str80, //!< A string of size 80 - StringArgsPortStrings::StringSize80& str80Ref, - const StringArgsPortStrings::StringSize100& str100, //!< A string of size 100 - StringArgsPortStrings::StringSize100& str100Ref + const Fw::StringBase& str80, //!< A string of size 80 + Fw::StringBase& str80Ref, + const Fw::StringBase& str100, //!< A string of size 100 + Fw::StringBase& str100Ref ); //! Handler implementation for stringArgsSync void stringArgsSync_handler( NATIVE_INT_TYPE portNum, //!< The port number - const StringArgsPortStrings::StringSize80& str80, //!< A string of size 80 - StringArgsPortStrings::StringSize80& str80Ref, - const StringArgsPortStrings::StringSize100& str100, //!< A string of size 100 - StringArgsPortStrings::StringSize100& str100Ref + const Fw::StringBase& str80, //!< A string of size 80 + Fw::StringBase& str80Ref, + const Fw::StringBase& str100, //!< A string of size 100 + Fw::StringBase& str100Ref ); //! Handler implementation for structArgsAsync diff --git a/FppTest/component/active/test/ut/Tester.hpp b/FppTest/component/active/test/ut/Tester.hpp index 9282618a66..117df5b272 100644 --- a/FppTest/component/active/test/ut/Tester.hpp +++ b/FppTest/component/active/test/ut/Tester.hpp @@ -76,7 +76,7 @@ class Tester : public ActiveTestGTestBase { FormalParamArray& aRef /*!< An array ref */ - ); + ) final; //! Handler for from_arrayReturnOut //! @@ -87,7 +87,7 @@ class Tester : public ActiveTestGTestBase { FormalParamArray& aRef /*!< An array ref */ - ); + ) final; //! Handler for from_enumArgsOut //! @@ -98,7 +98,7 @@ class Tester : public ActiveTestGTestBase { FormalParamEnum& enRef /*!< An enum ref */ - ); + ) final; //! Handler for from_enumReturnOut //! @@ -109,17 +109,17 @@ class Tester : public ActiveTestGTestBase { FormalParamEnum& enRef /*!< An enum ref */ - ); + ) final; //! Handler for from_noArgsOut //! void from_noArgsOut_handler(const NATIVE_INT_TYPE portNum /*!< The port number*/ - ); + ) final; //! Handler for from_noArgsReturnOut //! bool from_noArgsReturnOut_handler(const NATIVE_INT_TYPE portNum /*!< The port number*/ - ); + ) final; //! Handler for from_primitiveArgsOut //! @@ -129,7 +129,7 @@ class Tester : public ActiveTestGTestBase { F32 f32, F32& f32Ref, bool b, - bool& bRef); + bool& bRef) final; //! Handler for from_primitiveReturnOut //! @@ -139,7 +139,7 @@ class Tester : public ActiveTestGTestBase { F32 f32, F32& f32Ref, bool b, - bool& bRef); + bool& bRef) final; //! Handler for from_prmGetIn //! @@ -150,7 +150,7 @@ class Tester : public ActiveTestGTestBase { Fw::ParamBuffer& val /*!< Buffer containing serialized parameter value */ - ); + ) final; //! Handler for from_prmGetIn //! @@ -161,19 +161,7 @@ class Tester : public ActiveTestGTestBase { Fw::ParamBuffer& val /*!< Buffer containing serialized parameter value */ - ); - - //! Handler for from_stringArgsOut - //! - void from_stringArgsOut_handler(const NATIVE_INT_TYPE portNum, /*!< The port number*/ - const str80String& str80, /*!< - A string of size 80 - */ - str80RefString& str80Ref, - const str100String& str100, /*!< - A string of size 100 - */ - str100RefString& str100Ref); + ) final; //! Handler for from_structArgsOut //! @@ -184,7 +172,7 @@ class Tester : public ActiveTestGTestBase { FormalParamStruct& sRef /*!< A struct ref */ - ); + ) final; //! Handler for from_structReturnOut //! @@ -195,7 +183,7 @@ class Tester : public ActiveTestGTestBase { FormalParamStruct& sRef /*!< A struct ref */ - ); + ) final; PRIVATE: // ---------------------------------------------------------------------- @@ -206,7 +194,7 @@ class Tester : public ActiveTestGTestBase { //! void from_serialOut_handler(NATIVE_INT_TYPE portNum, /*!< The port number*/ Fw::SerializeBufferBase& Buffer /*!< The serialization buffer*/ - ); + ) final; public: // ---------------------------------------------------------------------- diff --git a/FppTest/component/passive/.gitignore b/FppTest/component/passive/.gitignore new file mode 100644 index 0000000000..ec92599425 --- /dev/null +++ b/FppTest/component/passive/.gitignore @@ -0,0 +1,5 @@ +FppTest_component_passive_ut_exe +cached +seed +seed-history +show-rules diff --git a/FppTest/component/passive/PassiveTest.cpp b/FppTest/component/passive/PassiveTest.cpp index acd3908cf6..efde416db1 100644 --- a/FppTest/component/passive/PassiveTest.cpp +++ b/FppTest/component/passive/PassiveTest.cpp @@ -252,10 +252,10 @@ void PassiveTest :: stringArgsGuarded_handler( const NATIVE_INT_TYPE portNum, - const str80String &str80, - str80RefString &str80Ref, - const str100String &str100, - str100RefString &str100Ref + const Fw::StringBase &str80, + Fw::StringBase &str80Ref, + const Fw::StringBase &str100, + Fw::StringBase &str100Ref ) { this->stringArgsOut_out( @@ -270,10 +270,10 @@ void PassiveTest :: stringArgsSync_handler( const NATIVE_INT_TYPE portNum, - const str80String &str80, - str80RefString &str80Ref, - const str100String &str100, - str100RefString &str100Ref + const Fw::StringBase &str80, + Fw::StringBase &str80Ref, + const Fw::StringBase &str100, + Fw::StringBase &str100Ref ) { this->stringArgsOut_out( diff --git a/FppTest/component/passive/PassiveTest.hpp b/FppTest/component/passive/PassiveTest.hpp index 0eea8e98f0..386e054fde 100644 --- a/FppTest/component/passive/PassiveTest.hpp +++ b/FppTest/component/passive/PassiveTest.hpp @@ -171,19 +171,19 @@ class PassiveTest : //! Handler implementation for stringArgsGuarded void stringArgsGuarded_handler( NATIVE_INT_TYPE portNum, //!< The port number - const StringArgsPortStrings::StringSize80& str80, //!< A string of size 80 - StringArgsPortStrings::StringSize80& str80Ref, - const StringArgsPortStrings::StringSize100& str100, //!< A string of size 100 - StringArgsPortStrings::StringSize100& str100Ref + const Fw::StringBase& str80, //!< A string of size 80 + Fw::StringBase& str80Ref, + const Fw::StringBase& str100, //!< A string of size 100 + Fw::StringBase& str100Ref ); //! Handler implementation for stringArgsSync void stringArgsSync_handler( NATIVE_INT_TYPE portNum, //!< The port number - const StringArgsPortStrings::StringSize80& str80, //!< A string of size 80 - StringArgsPortStrings::StringSize80& str80Ref, - const StringArgsPortStrings::StringSize100& str100, //!< A string of size 100 - StringArgsPortStrings::StringSize100& str100Ref + const Fw::StringBase& str80, //!< A string of size 80 + Fw::StringBase& str80Ref, + const Fw::StringBase& str100, //!< A string of size 100 + Fw::StringBase& str100Ref ); //! Handler implementation for structArgsGuarded diff --git a/FppTest/component/passive/test/ut/Tester.hpp b/FppTest/component/passive/test/ut/Tester.hpp index bc0b5c1b70..e6036f996f 100644 --- a/FppTest/component/passive/test/ut/Tester.hpp +++ b/FppTest/component/passive/test/ut/Tester.hpp @@ -159,18 +159,6 @@ class Tester : public PassiveTestGTestBase { */ ); - //! Handler for from_stringArgsOut - //! - void from_stringArgsOut_handler(const NATIVE_INT_TYPE portNum, /*!< The port number*/ - const str80String& str80, /*!< - A string of size 80 - */ - str80RefString& str80Ref, - const str100String& str100, /*!< - A string of size 100 - */ - str100RefString& str100Ref); - //! Handler for from_structArgsOut //! void from_structArgsOut_handler(const NATIVE_INT_TYPE portNum, /*!< The port number*/ diff --git a/FppTest/component/queued/.gitignore b/FppTest/component/queued/.gitignore new file mode 100644 index 0000000000..25e8f9e48e --- /dev/null +++ b/FppTest/component/queued/.gitignore @@ -0,0 +1,5 @@ +FppTest_component_queued_ut_exe +cached +seed +seed-history +show-rules diff --git a/FppTest/component/queued/QueuedTest.cpp b/FppTest/component/queued/QueuedTest.cpp index 682f200914..4733b735f9 100644 --- a/FppTest/component/queued/QueuedTest.cpp +++ b/FppTest/component/queued/QueuedTest.cpp @@ -104,10 +104,10 @@ void QueuedTest :: stringArgsAsync_handler( const NATIVE_INT_TYPE portNum, - const str80String &str80, - str80RefString &str80Ref, - const str100String &str100, - str100RefString &str100Ref + const Fw::StringBase &str80, + Fw::StringBase &str80Ref, + const Fw::StringBase &str100, + Fw::StringBase &str100Ref ) { this->stringArgsOut_out( @@ -332,10 +332,10 @@ void QueuedTest :: stringArgsGuarded_handler( const NATIVE_INT_TYPE portNum, - const str80String &str80, - str80RefString &str80Ref, - const str100String &str100, - str100RefString &str100Ref + const Fw::StringBase &str80, + Fw::StringBase &str80Ref, + const Fw::StringBase &str100, + Fw::StringBase &str100Ref ) { this->stringArgsOut_out( @@ -350,10 +350,10 @@ void QueuedTest :: stringArgsSync_handler( const NATIVE_INT_TYPE portNum, - const str80String &str80, - str80RefString &str80Ref, - const str100String &str100, - str100RefString &str100Ref + const Fw::StringBase &str80, + Fw::StringBase &str80Ref, + const Fw::StringBase &str100, + Fw::StringBase &str100Ref ) { this->stringArgsOut_out( diff --git a/FppTest/component/queued/QueuedTest.hpp b/FppTest/component/queued/QueuedTest.hpp index 6b3c6ceca9..dc8c2a453d 100644 --- a/FppTest/component/queued/QueuedTest.hpp +++ b/FppTest/component/queued/QueuedTest.hpp @@ -203,28 +203,28 @@ class QueuedTest : //! Handler implementation for stringArgsAsync void stringArgsAsync_handler( NATIVE_INT_TYPE portNum, //!< The port number - const StringArgsPortStrings::StringSize80& str80, //!< A string of size 80 - StringArgsPortStrings::StringSize80& str80Ref, - const StringArgsPortStrings::StringSize100& str100, //!< A string of size 100 - StringArgsPortStrings::StringSize100& str100Ref + const Fw::StringBase& str80, //!< A string of size 80 + Fw::StringBase& str80Ref, + const Fw::StringBase& str100, //!< A string of size 100 + Fw::StringBase& str100Ref ); //! Handler implementation for stringArgsGuarded void stringArgsGuarded_handler( NATIVE_INT_TYPE portNum, //!< The port number - const StringArgsPortStrings::StringSize80& str80, //!< A string of size 80 - StringArgsPortStrings::StringSize80& str80Ref, - const StringArgsPortStrings::StringSize100& str100, //!< A string of size 100 - StringArgsPortStrings::StringSize100& str100Ref + const Fw::StringBase& str80, //!< A string of size 80 + Fw::StringBase& str80Ref, + const Fw::StringBase& str100, //!< A string of size 100 + Fw::StringBase& str100Ref ); //! Handler implementation for stringArgsSync void stringArgsSync_handler( NATIVE_INT_TYPE portNum, //!< The port number - const StringArgsPortStrings::StringSize80& str80, //!< A string of size 80 - StringArgsPortStrings::StringSize80& str80Ref, - const StringArgsPortStrings::StringSize100& str100, //!< A string of size 100 - StringArgsPortStrings::StringSize100& str100Ref + const Fw::StringBase& str80, //!< A string of size 80 + Fw::StringBase& str80Ref, + const Fw::StringBase& str100, //!< A string of size 100 + Fw::StringBase& str100Ref ); //! Handler implementation for structArgsAsync diff --git a/FppTest/component/queued/test/ut/Tester.hpp b/FppTest/component/queued/test/ut/Tester.hpp index a03948ef38..c13d839eeb 100644 --- a/FppTest/component/queued/test/ut/Tester.hpp +++ b/FppTest/component/queued/test/ut/Tester.hpp @@ -163,18 +163,6 @@ class Tester : public QueuedTestGTestBase { */ ); - //! Handler for from_stringArgsOut - //! - void from_stringArgsOut_handler(const NATIVE_INT_TYPE portNum, /*!< The port number*/ - const str80String& str80, /*!< - A string of size 80 - */ - str80RefString& str80Ref, - const str100String& str100, /*!< - A string of size 100 - */ - str100RefString& str100Ref); - //! Handler for from_structArgsOut //! void from_structArgsOut_handler(const NATIVE_INT_TYPE portNum, /*!< The port number*/ diff --git a/FppTest/component/tests/PortTests.hpp b/FppTest/component/tests/PortTests.hpp index b909e54465..ba3d2858de 100644 --- a/FppTest/component/tests/PortTests.hpp +++ b/FppTest/component/tests/PortTests.hpp @@ -375,7 +375,7 @@ this->checkSerializeStatusBufferEmpty(); \ \ /* Check unsuccessful deserialization of second parameter */ \ - U8 invalidData2[StringArgsPortStrings::StringSize80::SERIALIZED_SIZE]; \ + U8 invalidData2[FppTest::Types::String1::SERIALIZED_SIZE]; \ Fw::SerialBuffer invalidBuf2(invalidData2, sizeof(invalidData2)); \ \ status = invalidBuf2.serialize(port.args.val1); \ @@ -386,7 +386,7 @@ this->checkSerializeStatusBufferEmpty(); \ \ /* Check unsuccessful deserialization of third parameter */ \ - U8 invalidData3[StringArgsPortStrings::StringSize80::SERIALIZED_SIZE * 2]; \ + U8 invalidData3[FppTest::Types::String1::SERIALIZED_SIZE * 2]; \ Fw::SerialBuffer invalidBuf3(invalidData3, sizeof(invalidData3)); \ \ status = invalidBuf3.serialize(port.args.val1); \ @@ -400,8 +400,7 @@ this->checkSerializeStatusBufferEmpty(); \ \ /* Check unsuccessful deserialization of fourth parameter */ \ - U8 invalidData4[(StringArgsPortStrings::StringSize80::SERIALIZED_SIZE * 2) + \ - StringArgsPortStrings::StringSize100::SERIALIZED_SIZE]; \ + U8 invalidData4[(FppTest::Types::String1::SERIALIZED_SIZE * 2) + FppTest::Types::String2::SERIALIZED_SIZE]; \ Fw::SerialBuffer invalidBuf4(invalidData4, sizeof(invalidData4)); \ \ status = invalidBuf4.serialize(port.args.val1); \ @@ -666,8 +665,8 @@ \ void Tester ::test##PORT_KIND##PortCheckSerial(FppTest::Types::PortStringParams& port) { \ Fw::SerializeStatus status; \ - StringArgsPortStrings::StringSize80 str80, str80Ref; \ - StringArgsPortStrings::StringSize100 str100, str100Ref; \ + FppTest::Types::String1 str80, str80Ref; \ + FppTest::Types::String2 str100, str100Ref; \ \ status = this->stringBuf.deserialize(str80); \ ASSERT_EQ(status, Fw::FW_SERIALIZE_OK); \ diff --git a/FppTest/component/tests/TesterHandlers.cpp b/FppTest/component/tests/TesterHandlers.cpp index 640e0ff348..73be0402de 100644 --- a/FppTest/component/tests/TesterHandlers.cpp +++ b/FppTest/component/tests/TesterHandlers.cpp @@ -72,14 +72,6 @@ U32 Tester ::from_primitiveReturnOut_handler(const NATIVE_INT_TYPE portNum, return primitiveReturnVal.val; } -void Tester ::from_stringArgsOut_handler(const NATIVE_INT_TYPE portNum, - const str80String& str80, - str80RefString& str80Ref, - const str100String& str100, - str100RefString& str100Ref) { - this->pushFromPortEntry_stringArgsOut(str80, str80Ref, str100, str100Ref); -} - void Tester ::from_structArgsOut_handler(const NATIVE_INT_TYPE portNum, const FormalParamStruct& s, FormalParamStruct& sRef) { diff --git a/FppTest/component/tests/Tests.cpp b/FppTest/component/tests/Tests.cpp index 808018b1d9..d0673afbc0 100644 --- a/FppTest/component/tests/Tests.cpp +++ b/FppTest/component/tests/Tests.cpp @@ -48,15 +48,10 @@ INSTANTIATE_TYPED_TEST_SUITE_P(FppTest, SerialPortTest, SerialPortTestImplementa // String tests using StringTestImplementations = - ::testing::Types; + ::testing::Types; INSTANTIATE_TYPED_TEST_SUITE_P(Array, StringTest, StringTestImplementations); -template <> -U32 FppTest::String::getSize() { - return 100; -} - // Command tests using CommandTestImplementations = ::testing::Types str(buf); Utils::setString(buf, sizeof(buf)); s.set(STest::Pick::any(), str); diff --git a/FppTest/component/types/FormalParamTypes.hpp b/FppTest/component/types/FormalParamTypes.hpp index b8fbdaade7..aed452aeb2 100644 --- a/FppTest/component/types/FormalParamTypes.hpp +++ b/FppTest/component/types/FormalParamTypes.hpp @@ -19,6 +19,7 @@ #include "Fw/Tlm/TlmString.hpp" #include "Fw/Types/InternalInterfaceString.hpp" #include "Fw/Types/SerialBuffer.hpp" +#include "Fw/Types/StringTemplate.hpp" #include "FppTest/component/active/FormalParamArrayArrayAc.hpp" #include "FppTest/component/active/FormalParamEnumEnumAc.hpp" @@ -123,19 +124,22 @@ struct StructTypes { // String types // ---------------------------------------------------------------------- +using String1 = Fw::StringTemplate<80>; +using String2 = Fw::StringTemplate<100>; + struct PortStringType { PortStringType(); - StringArgsPortStrings::StringSize80 val; + String1 val; }; struct PortStringTypes { PortStringTypes(); - StringArgsPortStrings::StringSize80 val1; - StringArgsPortStrings::StringSize80 val2; - StringArgsPortStrings::StringSize100 val3; - StringArgsPortStrings::StringSize100 val4; + String1 val1; + String1 val2; + String2 val3; + String2 val4; }; struct InternalInterfaceStringType { diff --git a/FppTest/dp/DpTest.cpp b/FppTest/dp/DpTest.cpp index a780db89b3..7fe41b8690 100644 --- a/FppTest/dp/DpTest.cpp +++ b/FppTest/dp/DpTest.cpp @@ -117,6 +117,8 @@ void DpTest ::dpRecv_Container1_handler(DpContainer& container, Fw::Success::T s } // Use the time stamp from the time get port this->dpSend(this->m_container); + // Check that buffer is no longer valid + FW_ASSERT(!this->m_container.getBuffer().isValid()); } } @@ -135,6 +137,8 @@ void DpTest ::dpRecv_Container2_handler(DpContainer& container, Fw::Success::T s } // Provide an explicit time stamp this->dpSend(this->m_container, this->sendTime); + // Check that buffer is no longer valid + FW_ASSERT(!this->m_container.getBuffer().isValid()); } } @@ -153,6 +157,8 @@ void DpTest ::dpRecv_Container3_handler(DpContainer& container, Fw::Success::T s } // Use the time stamp from the time get port this->dpSend(this->m_container); + // Check that buffer is no longer valid + FW_ASSERT(!this->m_container.getBuffer().isValid()); } } @@ -171,6 +177,8 @@ void DpTest ::dpRecv_Container4_handler(DpContainer& container, Fw::Success::T s } // Use the time stamp from the time get port this->dpSend(this->m_container); + // Check that buffer is no longer valid + FW_ASSERT(!this->m_container.getBuffer().isValid()); } } @@ -189,6 +197,8 @@ void DpTest ::dpRecv_Container5_handler(DpContainer& container, Fw::Success::T s } // Use the time stamp from the time get port this->dpSend(this->m_container); + // Check that buffer is no longer valid + FW_ASSERT(!this->m_container.getBuffer().isValid()); } } @@ -206,6 +216,8 @@ void DpTest ::dpRecv_Container6_handler(DpContainer& container, Fw::Success::T s } // Use the time stamp from the time get port this->dpSend(this->m_container); + // Check that buffer is no longer valid + FW_ASSERT(!this->m_container.getBuffer().isValid()); } } @@ -224,6 +236,8 @@ void DpTest ::dpRecv_Container7_handler(DpContainer& container, Fw::Success::T s } // Use the time stamp from the time get port this->dpSend(this->m_container); + // Check that buffer is no longer valid + FW_ASSERT(!this->m_container.getBuffer().isValid()); } } diff --git a/FppTest/dp/DpTest.hpp b/FppTest/dp/DpTest.hpp index 61424074b1..490d2eecbf 100644 --- a/FppTest/dp/DpTest.hpp +++ b/FppTest/dp/DpTest.hpp @@ -39,7 +39,7 @@ class DpTest : public DpTestComponentBase { static constexpr FwSizeType CONTAINER_7_DATA_SIZE = 1000; static constexpr FwSizeType CONTAINER_7_PACKET_SIZE = DpContainer::getPacketSizeForDataSize(CONTAINER_7_DATA_SIZE); - static constexpr FwSizeType STRING_ARRAY_RECORD_ARRAY_SIZE = 100; + static constexpr FwSizeType STRING_ARRAY_RECORD_ARRAY_SIZE = 10; public: // ---------------------------------------------------------------------- diff --git a/FppTest/dp/test/ut/Tester.cpp b/FppTest/dp/test/ut/Tester.cpp index 201613a6d5..e12d70bb99 100644 --- a/FppTest/dp/test/ut/Tester.cpp +++ b/FppTest/dp/test/ut/Tester.cpp @@ -83,6 +83,9 @@ void Tester::schedIn_OK() { void Tester::productRecvIn_Container1_SUCCESS() { Fw::Buffer buffer; FwSizeType expectedNumElts; + // Check the record size + constexpr FwSizeType recordSize = DpTestComponentBase::SIZE_OF_U32Record_RECORD; + ASSERT_EQ(recordSize, sizeof(FwDpIdType) + sizeof(U32)); // Invoke the port and check the header this->productRecvIn_InvokeAndCheckHeader(DpTest::ContainerId::Container1, sizeof(U32), DpTest::ContainerPriority::Container1, this->container1Buffer, buffer, @@ -110,6 +113,9 @@ void Tester::productRecvIn_Container1_FAILURE() { void Tester::productRecvIn_Container2_SUCCESS() { Fw::Buffer buffer; FwSizeType expectedNumElts; + // Check the record size + constexpr FwSizeType recordSize = DpTestComponentBase::SIZE_OF_DataRecord_RECORD; + ASSERT_EQ(recordSize, sizeof(FwDpIdType) + DpTest_Data::SERIALIZED_SIZE); // Invoke the port and check the header this->productRecvIn_InvokeAndCheckHeader(DpTest::ContainerId::Container2, DpTest_Data::SERIALIZED_SIZE, DpTest::ContainerPriority::Container2, this->container2Buffer, buffer, @@ -138,7 +144,11 @@ void Tester::productRecvIn_Container3_SUCCESS() { Fw::Buffer buffer; FwSizeType expectedNumElts; // Compute the data element size - const FwSizeType dataEltSize = sizeof(FwSizeStoreType) + this->u8ArrayRecordData.size(); + const FwSizeType arraySize = this->u8ArrayRecordData.size(); + const FwSizeType dataEltSize = sizeof(FwSizeStoreType) + arraySize; + // Check the record size + const FwSizeType recordSize = DpTestComponentBase::SIZE_OF_U8ArrayRecord_RECORD(arraySize); + ASSERT_EQ(recordSize, sizeof(FwDpIdType) + dataEltSize); // Invoke the port and check the header this->productRecvIn_InvokeAndCheckHeader(DpTest::ContainerId::Container3, dataEltSize, DpTest::ContainerPriority::Container3, this->container3Buffer, buffer, @@ -175,7 +185,11 @@ void Tester::productRecvIn_Container4_SUCCESS() { Fw::Buffer buffer; FwSizeType expectedNumElts; // Compute the data element size - const FwSizeType dataEltSize = sizeof(FwSizeStoreType) + this->u32ArrayRecordData.size() * sizeof(U32); + const FwSizeType arraySize = this->u32ArrayRecordData.size(); + const FwSizeType dataEltSize = sizeof(FwSizeStoreType) + arraySize * sizeof(U32); + // Check the record size + const FwSizeType recordSize = DpTestComponentBase::SIZE_OF_U32ArrayRecord_RECORD(arraySize); + ASSERT_EQ(recordSize, sizeof(FwDpIdType) + dataEltSize); // Invoke the port and check the header this->productRecvIn_InvokeAndCheckHeader(DpTest::ContainerId::Container4, dataEltSize, DpTest::ContainerPriority::Container4, this->container4Buffer, buffer, @@ -212,8 +226,11 @@ void Tester::productRecvIn_Container5_SUCCESS() { Fw::Buffer buffer; FwSizeType expectedNumElts; // Compute the data element size - const FwSizeType dataEltSize = - sizeof(FwSizeStoreType) + this->dataArrayRecordData.size() * DpTest_Data::SERIALIZED_SIZE; + const FwSizeType arraySize = this->dataArrayRecordData.size(); + const FwSizeType dataEltSize = sizeof(FwSizeStoreType) + arraySize * DpTest_Data::SERIALIZED_SIZE; + // Check the record size + const FwSizeType recordSize = DpTestComponentBase::SIZE_OF_DataArrayRecord_RECORD(arraySize); + ASSERT_EQ(recordSize, sizeof(FwDpIdType) + dataEltSize); // Invoke the port and check the header this->productRecvIn_InvokeAndCheckHeader(DpTest::ContainerId::Container5, dataEltSize, DpTest::ContainerPriority::Container5, this->container5Buffer, buffer, @@ -249,9 +266,11 @@ void Tester::productRecvIn_Container5_FAILURE() { void Tester::productRecvIn_Container6_SUCCESS() { Fw::Buffer buffer; FwSizeType expectedNumElts; + // Check the record size + constexpr FwSizeType recordSize = DpTestComponentBase::SIZE_OF_StringRecord_RECORD; + ASSERT_EQ(recordSize, sizeof(FwDpIdType) + Fw::StringBase::STATIC_SERIALIZED_SIZE(DpTest_stringSize)); // Construct the possibly truncated string - // Add one to the string size to account for the null terminator - char esData[DpTest_stringSize+1]; + char esData[Fw::StringBase::BUFFER_SIZE(DpTest_stringSize)]; Fw::ExternalString es(esData, sizeof esData, this->stringRecordData); // Invoke the port and check the header this->productRecvIn_InvokeAndCheckHeader(DpTest::ContainerId::Container6, es.serializedSize(), @@ -280,11 +299,15 @@ void Tester::productRecvIn_Container6_FAILURE() { void Tester::productRecvIn_Container7_SUCCESS() { Fw::Buffer buffer; FwSizeType expectedNumElts; + // Check the record size + const FwSizeType arraySize = DpTest::STRING_ARRAY_RECORD_ARRAY_SIZE; + const FwSizeType recordSize = DpTestComponentBase::SIZE_OF_StringArrayRecord_RECORD(arraySize); + const FwSizeType expectedRecordSize = sizeof(FwDpIdType) + sizeof(FwSizeStoreType) + + arraySize * Fw::StringBase::STATIC_SERIALIZED_SIZE(DpTest_stringSize); + ASSERT_EQ(recordSize, expectedRecordSize); // Construct the possibly truncated string - // Add one to the string size to account for the null terminator - char esData[DpTest_stringSize+1]; + char esData[Fw::StringBase::BUFFER_SIZE(DpTest_stringSize)]; Fw::ExternalString es(esData, sizeof esData, this->stringRecordData); - const FwSizeType arraySize = DpTest::STRING_ARRAY_RECORD_ARRAY_SIZE; const FwSizeType dataEltSize = sizeof(FwSizeStoreType) + arraySize * es.serializedSize(); // Invoke the port and check the header this->productRecvIn_InvokeAndCheckHeader(DpTest::ContainerId::Container7, dataEltSize, diff --git a/FppTest/enum/README.md b/FppTest/enum/README.md index f984de13d9..7b89edd04d 100644 --- a/FppTest/enum/README.md +++ b/FppTest/enum/README.md @@ -2,8 +2,8 @@ This directory contains unit tests for the FPP enum code generator. -* EnumToStringTest: Tests enum toString() and ostream operator functions -* IsValidTest: Additional tests for isValid() function with boundary values +* `EnumToStringTest`: Tests enum `toString()` and `ostream` operator functions +* `IsValidTest`: Additional tests for `isValid()` function with boundary values To use this directory, you must have installed F Prime, and you must be inside the F Prime Python virtual environment. diff --git a/FppTest/struct/NonPrimitiveStructTest.cpp b/FppTest/struct/NonPrimitiveStructTest.cpp index 9ae847347b..f4f35f4ac2 100644 --- a/FppTest/struct/NonPrimitiveStructTest.cpp +++ b/FppTest/struct/NonPrimitiveStructTest.cpp @@ -14,6 +14,7 @@ #include "FppTest/utils/Utils.hpp" #include "Fw/Types/SerialBuffer.hpp" +#include "Fw/Types/StringTemplate.hpp" #include "Fw/Types/StringUtils.hpp" #include "STest/Pick/Pick.hpp" @@ -88,7 +89,7 @@ class NonPrimitiveStructTest : public ::testing::Test { ASSERT_NE(status, Fw::FW_SERIALIZE_OK); } - NonPrimitive::StringSize80 testString; + Fw::StringTemplate<80> testString; StructEnum testEnum; StructArray testArray; Primitive testStruct; @@ -107,7 +108,7 @@ TEST_F(NonPrimitiveStructTest, Default) { // Constants ASSERT_EQ( NonPrimitive::SERIALIZED_SIZE, - NonPrimitive::StringSize80::SERIALIZED_SIZE + Fw::StringBase::STATIC_SERIALIZED_SIZE(80) + StructEnum::SERIALIZED_SIZE + StructArray::SERIALIZED_SIZE + Primitive::SERIALIZED_SIZE @@ -266,7 +267,7 @@ TEST_F(NonPrimitiveStructTest, Serialization) { U32 stringSerializedSize = testString.length() + sizeof(FwBuffSizeType); U32 serializedSize = NonPrimitive::SERIALIZED_SIZE - - NonPrimitive::StringSize80::SERIALIZED_SIZE + - Fw::StringBase::STATIC_SERIALIZED_SIZE(80) + stringSerializedSize; Fw::SerializeStatus status; @@ -325,9 +326,7 @@ TEST_F(NonPrimitiveStructTest, ToString) { << " )"; // Truncate string output - char buf2Str[FW_SERIALIZABLE_TO_STRING_BUFFER_SIZE]; - Fw::StringUtils::string_copy(buf2Str, buf2.str().c_str(), - FW_SERIALIZABLE_TO_STRING_BUFFER_SIZE); + Fw::String s2(buf2.str().c_str()); - ASSERT_STREQ(buf1.str().c_str(), buf2Str); + ASSERT_STREQ(buf1.str().c_str(), s2.toChar()); } diff --git a/FppTest/struct/main.cpp b/FppTest/struct/main.cpp index 60a72d7d63..33b5735129 100644 --- a/FppTest/struct/main.cpp +++ b/FppTest/struct/main.cpp @@ -10,32 +10,22 @@ // // ====================================================================== -#include "FppTest/struct/NonPrimitiveSerializableAc.hpp" #include "FppTest/struct/MultiStringSerializableAc.hpp" +#include "FppTest/struct/NonPrimitiveSerializableAc.hpp" #include "FppTest/typed_tests/StringTest.hpp" +#include "Fw/Types/StringTemplate.hpp" #include "STest/Random/Random.hpp" #include "gtest/gtest.h" // Instantiate string tests for structs using StringTestImplementations = ::testing::Types< - NonPrimitive::StringSize80, - MultiString::StringSize50, - MultiString::StringSize60, - MultiString::StringSize80 + Fw::StringTemplate<80>, + Fw::StringTemplate<50>, + Fw::StringTemplate<60> >; INSTANTIATE_TYPED_TEST_SUITE_P(Struct, StringTest, StringTestImplementations); -template<> -U32 FppTest::String::getSize() { - return 50; -} - -template<> -U32 FppTest::String::getSize() { - return 60; -} - int main(int argc, char* argv[]) { ::testing::InitGoogleTest(&argc, argv); STest::Random::seed(); diff --git a/FppTest/typed_tests/ArrayTest.hpp b/FppTest/typed_tests/ArrayTest.hpp index 12cea993ad..6759aa1233 100644 --- a/FppTest/typed_tests/ArrayTest.hpp +++ b/FppTest/typed_tests/ArrayTest.hpp @@ -49,13 +49,13 @@ namespace FppTest { } // namespace FppTest + // Test an array class template class ArrayTest : public ::testing::Test { protected: void SetUp() override { FppTest::Array::setDefaultVals(defaultVals); - FppTest::Array::setTestVals(testVals); ASSERT_FALSE(valsAreEqual()); }; @@ -82,10 +82,6 @@ TYPED_TEST_P(ArrayTest, Default) { // Constants ASSERT_EQ(TypeParam::SIZE, 3); - ASSERT_EQ( - TypeParam::SERIALIZED_SIZE, - TypeParam::SIZE * TypeParam::ElementType::SERIALIZED_SIZE - ); // Default constructor for (U32 i = 0; i < TypeParam::SIZE; i++) { diff --git a/FppTest/typed_tests/README.md b/FppTest/typed_tests/README.md index ab2062d749..20ec6052f4 100644 --- a/FppTest/typed_tests/README.md +++ b/FppTest/typed_tests/README.md @@ -1,17 +1,27 @@ # FppTest/typed_tests -This directory contains the following type-parametrized test suites for +This directory contains the following type-parameterized test suites for C++ code generated by the FPP autocoder. -* `EnumTest`: Tests an enum class * `ArrayTest`: Tests an array class -* `StringTest`: Tests a nested string class within an array of struct class +* `EnumTest`: Tests an enum class * `PortTest`: Tests typed-to-typed, typed-to-serial, serial-to-typed, and serial-to-serial port connections +* `StringTest`: Tests string classes, i.e., subclasses of `Fw::StringBase`. + +**Note on the StringTest suite:** +In an earlier version of the C++ back end, FPP generated string classes. +In that version, `StringTest` suite was used to provide code coverage for those +classes. +The code generation strategy for strings has changed, and FPP no longer generates +string classes. +However, we have retained the `StringTest` suite. +It can be used to test other string implementations, e.g., the string +implementations in `Fw/Types`. ## Instantiating a Test Suite -To use a type-parametrized test suite, instantiate it with a list of types: +To use a type-parameterized test suite, instantiate it with a list of types: ```c++ #include "FppTest/typed_tests/TestSuite.hpp" @@ -116,17 +126,6 @@ this function will need to be implemented for arrays containing string values. (typename ArrayType::ElementType (&a)[ArrayType::SIZE]); ``` -### `StringTest` Suite - -- `getSize()`: Returns the size of a string type. The default implementation -returns the default string size of 80. - - ```c++ - // Function signature - template - U32 FppTest::String::getSize(); - ``` - ## Example For example, to use the `ArrayTest` suite with array types `U32Array`, an array diff --git a/FppTest/typed_tests/StringTest.hpp b/FppTest/typed_tests/StringTest.hpp index ea2008cc46..db29a7d2da 100644 --- a/FppTest/typed_tests/StringTest.hpp +++ b/FppTest/typed_tests/StringTest.hpp @@ -20,41 +20,27 @@ #include "gtest/gtest.h" -namespace FppTest { - - namespace String { - - // Get the size of a string type - template - U32 getSize() { - return 80; - } - - } // namespace String - -} // namespace FppTest - -// Test a nested string class +// Test a string type template class StringTest : public ::testing::Test { protected: void SetUp() override { - size = FppTest::String::getSize(); - FppTest::Utils::setString(src, size); + FppTest::Utils::setString(this->src, sizeof this->src); - char fwStrBuf1[Fw::String::STRING_SIZE]; + char fwStrBuf1[Fw::StringBase::BUFFER_SIZE(Fw::String::STRING_SIZE)]; FppTest::Utils::setString(fwStrBuf1, sizeof(fwStrBuf1)); fwStr = fwStrBuf1; // Truncate fwStr for comparison - char fwStrBuf2[size]; - Fw::StringUtils::string_copy(fwStrBuf2, fwStr.toChar(), size); + char fwStrBuf2[bufferSize]; + Fw::StringUtils::string_copy(fwStrBuf2, fwStr.toChar(), sizeof fwStrBuf2); fwSubstr = fwStrBuf2; } - U32 size; - char src[StringType::SERIALIZED_SIZE]; + static constexpr FwSizeType size = StringType::STRING_SIZE; + static constexpr FwSizeType bufferSize = Fw::StringBase::BUFFER_SIZE(size); + char src[bufferSize]; Fw::String fwStr; Fw::String fwSubstr; @@ -67,12 +53,13 @@ TYPED_TEST_P(StringTest, Default) { TypeParam str; // Capacity - ASSERT_EQ(str.getCapacity(), this->size); + const FwSizeType bufferSizeObject = this->bufferSize; + ASSERT_EQ(str.getCapacity(), bufferSizeObject); // Serialized size ASSERT_EQ( TypeParam::SERIALIZED_SIZE, - this->size + sizeof(FwBuffSizeType) + Fw::StringBase::STATIC_SERIALIZED_SIZE(this->size) ); // Default constructors diff --git a/Fw/Cfg/ConfigCheck.cpp b/Fw/Cfg/ConfigCheck.cpp index e4ed04c6af..4eb0a69efd 100644 --- a/Fw/Cfg/ConfigCheck.cpp +++ b/Fw/Cfg/ConfigCheck.cpp @@ -1,10 +1,10 @@ /** - * \file - * \author T. Canham - * \brief Configuration checks for ISF configuration macros + * \file ConfigCheck.cpp + * \author F Prime + * \brief Static assertions for F Prime configuration macros * * \copyright - * Copyright 2009-2016, by the California Institute of Technology. + * Copyright 2009-2024, by the California Institute of Technology. * ALL RIGHTS RESERVED. United States Government Sponsorship * acknowledged. * @@ -13,21 +13,38 @@ #include #include +// Check that Fw::String is big enough to hold any string that can be given a +// default value in FPP. + +static_assert(FW_FIXED_LENGTH_STRING_SIZE >= FW_CMD_STRING_MAX_SIZE, + "A generic string should be able to hold a command string"); +static_assert(FW_FIXED_LENGTH_STRING_SIZE >= FW_LOG_STRING_MAX_SIZE, + "A generic string should be able to hold an event string"); +static_assert(FW_FIXED_LENGTH_STRING_SIZE >= FW_TLM_STRING_MAX_SIZE, + "A generic string should be able to hold a telemetry string"); +static_assert(FW_FIXED_LENGTH_STRING_SIZE >= FW_PARAM_STRING_MAX_SIZE, + "A generic string should be able to hold a parameter string"); + // Check that command/telemetry strings are not larger than an argument buffer -static_assert(FW_CMD_STRING_MAX_SIZE <= FW_CMD_ARG_BUFFER_MAX_SIZE, "FW_CMD_STRING_MAX_SIZE cannot be larger than FW_CMD_ARG_BUFFER_MAX_SIZE"); -static_assert(FW_LOG_STRING_MAX_SIZE <= FW_LOG_BUFFER_MAX_SIZE, "FW_LOG_STRING_MAX_SIZE cannot be larger than FW_LOG_BUFFER_MAX_SIZE"); -static_assert(FW_TLM_STRING_MAX_SIZE <= FW_TLM_BUFFER_MAX_SIZE, "FW_TLM_STRING_MAX_SIZE cannot be larger than FW_TLM_BUFFER_MAX_SIZE"); -static_assert(FW_PARAM_STRING_MAX_SIZE <= FW_PARAM_BUFFER_MAX_SIZE, "FW_PARAM_STRING_MAX_SIZE cannot be larger than FW_PARAM_BUFFER_MAX_SIZE"); +static_assert(FW_CMD_STRING_MAX_SIZE <= FW_CMD_ARG_BUFFER_MAX_SIZE, + "FW_CMD_STRING_MAX_SIZE cannot be larger than FW_CMD_ARG_BUFFER_MAX_SIZE"); +static_assert(FW_LOG_STRING_MAX_SIZE <= FW_LOG_BUFFER_MAX_SIZE, + "FW_LOG_STRING_MAX_SIZE cannot be larger than FW_LOG_BUFFER_MAX_SIZE"); +static_assert(FW_TLM_STRING_MAX_SIZE <= FW_TLM_BUFFER_MAX_SIZE, + "FW_TLM_STRING_MAX_SIZE cannot be larger than FW_TLM_BUFFER_MAX_SIZE"); +static_assert(FW_PARAM_STRING_MAX_SIZE <= FW_PARAM_BUFFER_MAX_SIZE, + "FW_PARAM_STRING_MAX_SIZE cannot be larger than FW_PARAM_BUFFER_MAX_SIZE"); // Text logging needs the code generator for serializables to generate a stringified version of the // value. -static_assert((FW_ENABLE_TEXT_LOGGING == 0) || ( FW_SERIALIZABLE_TO_STRING == 1), "FW_SERIALIZABLE_TO_STRING must be enabled to enable FW_ENABLE_TEXT_LOGGING"); +static_assert((FW_ENABLE_TEXT_LOGGING == 0) || (FW_SERIALIZABLE_TO_STRING == 1), + "FW_SERIALIZABLE_TO_STRING must be enabled to enable FW_ENABLE_TEXT_LOGGING"); static_assert(std::numeric_limits::max() == std::numeric_limits::max() && - std::numeric_limits::min() == std::numeric_limits::min(), + std::numeric_limits::min() == std::numeric_limits::min(), "FwBuffSizeType must be equivalent to FwExternalSizeType"); static_assert(std::numeric_limits::max() >= std::numeric_limits::max() && - std::numeric_limits::min() <= std::numeric_limits::min(), + std::numeric_limits::min() <= std::numeric_limits::min(), "FwSizeType cannot entirely store values of type FwExternalSizeType"); diff --git a/Fw/Dp/DpContainer.hpp b/Fw/Dp/DpContainer.hpp index 4d5c589b44..a9d9e3030c 100644 --- a/Fw/Dp/DpContainer.hpp +++ b/Fw/Dp/DpContainer.hpp @@ -170,6 +170,11 @@ class DpContainer { void setBuffer(const Buffer& buffer //!< The packet buffer ); + //! Invalidate the packet buffer + void invalidateBuffer() { + this->m_buffer = Fw::Buffer(); + } + //! Get the stored header hash //! \return The hash Utils::HashBuffer getHeaderHash() const; diff --git a/Fw/Dp/test/ut/TestMain.cpp b/Fw/Dp/test/ut/TestMain.cpp index d17d3b0137..90a7d8b058 100644 --- a/Fw/Dp/test/ut/TestMain.cpp +++ b/Fw/Dp/test/ut/TestMain.cpp @@ -151,6 +151,10 @@ TEST(Header, BufferSet) { checkHeader(id, buffer, container); // Check the buffers checkBuffers(container, sizeof bufferData); + // Invalidate the buffer + container.invalidateBuffer(); + // Check that the buffer is invalid + ASSERT_EQ(container.getBuffer(), Fw::Buffer()); } TEST(Header, BadPacketDescriptor) { diff --git a/Fw/Types/ExternalString.hpp b/Fw/Types/ExternalString.hpp index ca237a677c..ae8b450e1a 100644 --- a/Fw/Types/ExternalString.hpp +++ b/Fw/Types/ExternalString.hpp @@ -20,6 +20,9 @@ class ExternalString final : public Fw::StringBase { // Construction and destruction // ---------------------------------------------------------------------- + //! Deleted copy constructor + ExternalString(const ExternalString&) = delete; + //! Constructor (uninitialized buffer) ExternalString() : StringBase(), m_bufferPtr(nullptr), m_bufferSize(0) {} @@ -71,8 +74,8 @@ class ExternalString final : public Fw::StringBase { // ---------------------------------------------------------------------- //! Set the buffer and initialize it to the empty string - void setBuffer(char* bufferPtr, //!< The buffer pointer - FwSizeType bufferSize //!< The buffer size + void setBuffer(char* bufferPtr, //!< The buffer pointer + StringBase::SizeType bufferSize //!< The buffer size ) { this->m_bufferPtr = bufferPtr; this->m_bufferSize = bufferSize; diff --git a/Fw/Types/StringTemplate.hpp b/Fw/Types/StringTemplate.hpp new file mode 100644 index 0000000000..7cc34d2e48 --- /dev/null +++ b/Fw/Types/StringTemplate.hpp @@ -0,0 +1,57 @@ +// ====================================================================== +// @file StringTemplate.hpp +// @author Rob Bocchino +// @brief A string template parameterized by size +// ====================================================================== + +#ifndef FW_STRING_TEMPLATE_HPP +#define FW_STRING_TEMPLATE_HPP + +#include + +#include "Fw/Types/StringBase.hpp" + +namespace Fw { + +template class StringTemplate final : public StringBase { + public: + enum { + STRING_SIZE = size, + SERIALIZED_SIZE = STATIC_SERIALIZED_SIZE(STRING_SIZE), + }; + + StringTemplate() : StringBase() { *this = ""; } + + explicit StringTemplate(const StringTemplate& src) : StringBase() { *this = src; } + + explicit StringTemplate(const StringBase& src) : StringBase() { *this = src; } + + explicit StringTemplate(const char* src) : StringBase() { *this = src; } + + ~StringTemplate() {} + + StringTemplate& operator=(const StringTemplate& src) { + (void)StringBase::operator=(src); + return *this; + } + + StringTemplate& operator=(const StringBase& src) { + (void)StringBase::operator=(src); + return *this; + } + + StringTemplate& operator=(const char* src) { + (void)StringBase::operator=(src); + return *this; + } + + const char* toChar() const { return this->m_buf; } + + StringBase::SizeType getCapacity() const { return sizeof this->m_buf; } + + private: + char m_buf[BUFFER_SIZE(size)]; +}; +} // namespace Fw + +#endif diff --git a/Fw/Types/test/ut/TypesTest.cpp b/Fw/Types/test/ut/TypesTest.cpp index ef61f38639..197aade022 100644 --- a/Fw/Types/test/ut/TypesTest.cpp +++ b/Fw/Types/test/ut/TypesTest.cpp @@ -7,6 +7,7 @@ #include #include #include +#include #include #include // @@ -607,6 +608,14 @@ TEST(SerializationTest, Serialization1) { str1.serialize(buff); str2.deserialize(buff); ASSERT_EQ(str1, str2); + + // serialize string template + Fw::StringTemplate<80> strTmpl1("Foo"); + Fw::StringTemplate<80> strTmpl2("Bar"); + buff.resetSer(); + strTmpl1.serialize(buff); + strTmpl2.deserialize(buff); + ASSERT_EQ(strTmpl1, strTmpl2); } struct TestStruct { diff --git a/Ref/SignalGen/SignalGen.cpp b/Ref/SignalGen/SignalGen.cpp index 3f1f40f779..7ec1c9423a 100644 --- a/Ref/SignalGen/SignalGen.cpp +++ b/Ref/SignalGen/SignalGen.cpp @@ -224,7 +224,7 @@ namespace Ref { } // get DP buffer - this->dpGet_DataContainer(records*(SignalInfo::SERIALIZED_SIZE + sizeof(FwDpIdType)),this->m_dpContainer); + this->dpGet_DataContainer(records*SIZE_OF_DataRecord_RECORD,this->m_dpContainer); this->m_dpInProgress = true; this->m_numDps = records; this->m_currDp = 0; diff --git a/Svc/DpCatalog/DpCatalog.hpp b/Svc/DpCatalog/DpCatalog.hpp index 350288c982..2eb78eb5c1 100644 --- a/Svc/DpCatalog/DpCatalog.hpp +++ b/Svc/DpCatalog/DpCatalog.hpp @@ -186,7 +186,7 @@ namespace Svc { bool m_xmitInProgress; //!< set if DP files are in the process of being sent DpSortedList* m_currXmitRecord; //!< current record being transmitted - Svc::sourceFileNameString m_currXmitFileName; //!< current file being transmitted + Fw::FileNameString m_currXmitFileName; //!< current file being transmitted bool m_xmitCmdWait; //!< true if waiting for transmission complete to complete xmit command U64 m_xmitBytes; //!< bytes transmitted for downlink session diff --git a/Svc/DpCatalog/test/ut/DpCatalogTester.cpp b/Svc/DpCatalog/test/ut/DpCatalogTester.cpp index 61001e7f06..3eca28348b 100644 --- a/Svc/DpCatalog/test/ut/DpCatalogTester.cpp +++ b/Svc/DpCatalog/test/ut/DpCatalogTester.cpp @@ -202,8 +202,8 @@ namespace Svc { Svc::SendFileResponse DpCatalogTester :: from_fileOut_handler( NATIVE_INT_TYPE portNum, - const Svc::SendFileRequestPortStrings::StringSize100& sourceFileName, - const Svc::SendFileRequestPortStrings::StringSize100& destFileName, + const Fw::StringBase& sourceFileName, + const Fw::StringBase& destFileName, U32 offset, U32 length ) diff --git a/Svc/DpCatalog/test/ut/DpCatalogTester.hpp b/Svc/DpCatalog/test/ut/DpCatalogTester.hpp index a649f7d9fb..6577ab4d80 100644 --- a/Svc/DpCatalog/test/ut/DpCatalogTester.hpp +++ b/Svc/DpCatalog/test/ut/DpCatalogTester.hpp @@ -99,8 +99,8 @@ namespace Svc { //! Handler implementation for fileOut Svc::SendFileResponse from_fileOut_handler( NATIVE_INT_TYPE portNum, //!< The port number - const Svc::SendFileRequestPortStrings::StringSize100& sourceFileName, //!< Path of file to downlink - const Svc::SendFileRequestPortStrings::StringSize100& destFileName, //!< Path to store downlinked file at + const Fw::StringBase& sourceFileName, //!< Path of file to downlink + const Fw::StringBase& destFileName, //!< Path to store downlinked file at U32 offset, //!< Amount of data in bytes to downlink from file. 0 to read until end of file U32 length //!< Amount of data in bytes to downlink from file. 0 to read until end of file ) override; diff --git a/Svc/DpWriter/DpWriter.cpp b/Svc/DpWriter/DpWriter.cpp index 1eda1283d2..3501194130 100644 --- a/Svc/DpWriter/DpWriter.cpp +++ b/Svc/DpWriter/DpWriter.cpp @@ -5,6 +5,7 @@ // ====================================================================== #include "Fw/Com/ComPacket.hpp" +#include "Fw/Types/FileNameString.hpp" #include "Fw/Types/Serializable.hpp" #include "Os/File.hpp" #include "Svc/DpWriter/DpWriter.hpp" @@ -224,11 +225,9 @@ void DpWriter::sendNotification(const Fw::DpContainer& container, const Fw::FileNameString& fileName, FwSizeType fileSize) { if (isConnected_dpWrittenOut_OutputPort(0)) { - // Construct the file name - fileNameString portFileName(fileName.toChar()); // Get the priority const FwDpPriorityType priority = container.getPriority(); - this->dpWrittenOut_out(0, portFileName, priority, fileSize); + this->dpWrittenOut_out(0, fileName, priority, fileSize); } } diff --git a/Svc/FileDownlink/FileDownlink.cpp b/Svc/FileDownlink/FileDownlink.cpp index 47cb420f19..d52ef0737e 100644 --- a/Svc/FileDownlink/FileDownlink.cpp +++ b/Svc/FileDownlink/FileDownlink.cpp @@ -149,8 +149,8 @@ namespace Svc { Svc::SendFileResponse FileDownlink :: SendFile_handler( const NATIVE_INT_TYPE portNum, - const sourceFileNameString& sourceFilename, // lgtm[cpp/large-parameter] dictated by command architecture - const destFileNameString& destFilename, // lgtm[cpp/large-parameter] dictated by command architecture + const Fw::StringBase& sourceFilename, // lgtm[cpp/large-parameter] dictated by command architecture + const Fw::StringBase& destFilename, // lgtm[cpp/large-parameter] dictated by command architecture U32 offset, U32 length ) diff --git a/Svc/FileDownlink/FileDownlink.hpp b/Svc/FileDownlink/FileDownlink.hpp index dd51dc3297..efc34ec95c 100644 --- a/Svc/FileDownlink/FileDownlink.hpp +++ b/Svc/FileDownlink/FileDownlink.hpp @@ -312,8 +312,8 @@ namespace Svc { //! Svc::SendFileResponse SendFile_handler( const NATIVE_INT_TYPE portNum, /*!< The port number*/ - const sourceFileNameString& sourceFilename, /*!< Path of file to downlink*/ - const destFileNameString& destFilename, /*!< Path to store downlinked file at*/ + const Fw::StringBase& sourceFilename, /*!< Path of file to downlink*/ + const Fw::StringBase& destFilename, /*!< Path to store downlinked file at*/ U32 offset, /*!< Amount of data in bytes to downlink from file. 0 to read until end of file*/ U32 length /*!< Amount of data in bytes to downlink from file. 0 to read until end of file*/ ); diff --git a/Svc/FileDownlink/test/ut/FileDownlinkTester.cpp b/Svc/FileDownlink/test/ut/FileDownlinkTester.cpp index 7ecf3fd765..c4a68137d5 100644 --- a/Svc/FileDownlink/test/ut/FileDownlinkTester.cpp +++ b/Svc/FileDownlink/test/ut/FileDownlinkTester.cpp @@ -334,8 +334,8 @@ namespace Svc { FileBuffer fileBufferOut(data, sizeof(data)); fileBufferOut.write(sourceFileName); - sourceFileNameString srcFileArg(sourceFileName); - destFileNameString destFileArg(destFileName); + Fw::String srcFileArg(sourceFileName); + Fw::String destFileArg(destFileName); Svc::SendFileResponse resp = this->invoke_to_SendFile(0, srcFileArg, destFileArg, 0, 0); ASSERT_EQ(resp.getstatus(), SendFileStatus::STATUS_OK); diff --git a/config/FpConfig.h b/config/FpConfig.h index cf04c7002f..5ec0813380 100644 --- a/config/FpConfig.h +++ b/config/FpConfig.h @@ -384,13 +384,15 @@ typedef FwIndexType FwQueueSizeType; #ifndef FW_USE_TIME_CONTEXT #define FW_USE_TIME_CONTEXT 1 //!< Whether or not to serialize the time context #endif -// -// These defines used for the FilepathCharString type + +// Configuration for Fw::String #ifndef FW_FIXED_LENGTH_STRING_SIZE -#define FW_FIXED_LENGTH_STRING_SIZE 256 //!< Character array size for the filepath character type +#define FW_FIXED_LENGTH_STRING_SIZE 256 //!< Character array size for Fw::String #endif +// OS configuration + #ifndef FW_HANDLE_MAX_SIZE #define FW_HANDLE_MAX_SIZE 24 //!< Maximum size of a handle for OS resources (files, queues, locks, etc.) #endif @@ -403,7 +405,6 @@ typedef FwIndexType FwQueueSizeType; #define FW_FILE_CHUNK_SIZE 512 //!< Chunk size for working with files #endif - // *** NOTE configuration checks are in Fw/Cfg/ConfigCheck.cpp in order to have // the type definitions in Fw/Types/BasicTypes available. diff --git a/docs/Design/data-products.md b/docs/Design/data-products.md index 6ec7500866..62e57fed37 100644 --- a/docs/Design/data-products.md +++ b/docs/Design/data-products.md @@ -2,7 +2,10 @@ ## 1. Introduction -F' provides several features for managing the generation, storage, +A **data product** is any data that is produced by an embedded +system, stored on board the system, and transmitted to the ground, +typically in priority order. +F Prime provides several features for managing the generation, storage, and downlink of data products. In this section, we document those features. @@ -12,7 +15,7 @@ First we explain some basic concepts. ### 2.1. Records, Containers, and Dictionaries -F' data products are based on **records** and **containers**. +F Prime data products are based on **records** and **containers**. A record is a basic unit of data. For example, it may be a struct, an array of typed objects of statically known size, or an array of bytes of statically unknown size. @@ -21,11 +24,11 @@ In C++, a container is represented as a class object with member fields that (1) store header data and (2) store an `Fw::Buffer` object pointing to the memory that stores the records. -The set of all containers forms the **data product dictionary**. +The set of all container specifications forms the **data product dictionary**. To manage the data product dictionary, F Prime uses the same general approach as for commands, telemetry, events, and parameters: -1. Each component _C_ defines records and containers. +1. Each component _C_ specifies records and containers. The container IDs are local to _C_. Typically they have the values 0, 1, 2, ... . @@ -36,12 +39,12 @@ the local identifier for _c_. For example, if the base identifier is 0x1000, then the global identifiers might be 0x1000, 0x1001, 0x1002, ... . -3. For any topology _T_, the global identifiers _I.c_ for all the instances _T_ -form the data product dictionary for _T_. +3. For any topology _T_, the global identifiers _I.c_ for all the component +instances of _T_ form the data product dictionary for _T_. -### 2.2. F' Components +### 2.2. F Prime Components -Typically a data product system in an F' application consists of the following +Typically a data product system in an F Prime application consists of the following components: 1. One or more **data product producers**. @@ -63,15 +66,15 @@ components: 1. A **data product catalog**. This component maintains a database of available data products. By command, it downlinks and deletes data products. - See TODO. + See [`Svc::DpCatalog`](../../Svc/DpCatalog/docs/sdd.md). 1. A **data product processor**. - This component performs in-memory processing on data + This component is not yet developed. + When it is developed, it will perform in-memory processing on data product containers. - See TODO. Note that when using data products, you need to develop only the -producer components. The other components are provided by F'. +producer components. The other components are provided by F Prime. ## 3. Producer Components @@ -84,8 +87,9 @@ as often as necessary: 1. Request a container from a data manager component. -2. When the container is received, fill the container with -data by serializing records into the container. +2. When the container is received, serialize records into the +container. +This action fills the container with data. 3. When the container is full, send the container to the data product manager, which forwards it to the data @@ -99,8 +103,9 @@ We discuss these features in the following sections. In this section we summarize the features of the FPP modeling language used in constructing data product producer components. -Each of these features is fully documented in _The FPP User's Guide_ -and _The FPP Language Specification_. +Each of these features is fully documented in +[_The FPP User's Guide_](https://nasa.github.io/fpp/fpp-users-guide.html) +and [_The FPP Language Specification_](https://nasa.github.io/fpp/fpp-spec.html). #### 3.2.1. Ports @@ -220,8 +225,8 @@ For the serialized format of each record, see the documentation for [`Fw::DpContainer`](../../Fw/Dp/docs/sdd.md). 1. If _C_ has a `product` `get` port, a member function `dpGet_` -_c_ for each container defined in _C_. -This function takes a container ID, a data size, and a reference +_c_ for each container _c_ defined in _C_. +This function takes a data size and a reference to a data product container _D_. It invokes `productGetOut`, which is typically connected to a data product manager component. @@ -232,8 +237,8 @@ It returns a status value indicating whether the buffer allocation succeeded. 1. If _C_ has a `product` `request` port, a member function -`dpRequest_` _c_ for each container defined in _C_. -This function takes a container ID and a data size. +`dpRequest_` _c_ for each container _c_ defined in _C_. +This function takes a data size. It sends out a request on `productRequestOut`, which is typically connected to a data product manager component. The request is for a buffer large enough to store a data @@ -267,6 +272,24 @@ It does the following: 1. Send _c_ on `productSendOut`. +1. Constant expressions representing the sizes of the records. + + 1. If a record _R_ holds a single value, then + the expression `SIZE_OF_` _R_ `_RECORD` + evaluates to the size of that record. + + 1. Otherwise _R_ is an array record. In this case + the expression `SIZE_OF_` _R_ `_RECORD(` _size_ `)` + evaluates to the size of an array record _R_ with + _size_ array elements. + + You can use these expressions to compute data sizes + when requesting data product buffers. For example, + if a component specifies a record `Image`, + then inside the component implementation the expression + `10 * SIZE_OF_Image_RECORD` represents the size of the + storage necessary to hold 10 `Image` records. + ### 3.4. Unit Test Support In F Prime, each component _C_ comes with auto-generated @@ -440,7 +463,8 @@ The component referred to as `producer` in that document is a data product producer. **Cataloging and downlinking data products:** -TODO +For a preliminary implementation of the data product catalog, +see [`Svc::DpCatalog`](../../Svc/DpCatalog/docs/sdd.md). **Processing data products:** TODO diff --git a/requirements.txt b/requirements.txt index c04fe3357b..43a2ccc506 100644 --- a/requirements.txt +++ b/requirements.txt @@ -18,18 +18,18 @@ fprime-fpl-convert-xml==1.0.3 fprime-fpl-extract-xml==1.0.3 fprime-fpl-layout==1.0.3 fprime-fpl-write-pic==1.0.3 -fprime-fpp-check==2.1.0a10 -fprime-fpp-depend==2.1.0a10 -fprime-fpp-filenames==2.1.0a10 -fprime-fpp-format==2.1.0a10 -fprime-fpp-from-xml==2.1.0a10 -fprime-fpp-locate-defs==2.1.0a10 -fprime-fpp-locate-uses==2.1.0a10 -fprime-fpp-syntax==2.1.0a10 -fprime-fpp-to-cpp==2.1.0a10 -fprime-fpp-to-dict==2.1.0a10 -fprime-fpp-to-json==2.1.0a10 -fprime-fpp-to-xml==2.1.0a10 +fprime-fpp-check==2.1.0a11 +fprime-fpp-depend==2.1.0a11 +fprime-fpp-filenames==2.1.0a11 +fprime-fpp-format==2.1.0a11 +fprime-fpp-from-xml==2.1.0a11 +fprime-fpp-locate-defs==2.1.0a11 +fprime-fpp-locate-uses==2.1.0a11 +fprime-fpp-syntax==2.1.0a11 +fprime-fpp-to-cpp==2.1.0a11 +fprime-fpp-to-dict==2.1.0a11 +fprime-fpp-to-json==2.1.0a11 +fprime-fpp-to-xml==2.1.0a11 fprime-gds==3.4.3 fprime-tools==3.4.4 fprime-visual==1.0.2