From d714272191ba8612525137475da6a7f12df849f6 Mon Sep 17 00:00:00 2001 From: Milan Kriz Date: Mon, 25 Nov 2024 13:16:32 +0100 Subject: [PATCH] Add alignment tests --- extension/freemarker/Choice.cpp.ftl | 1 + extension/freemarker/Structure.cpp.ftl | 1 + extension/freemarker/Union.cpp.ftl | 1 + test/language/alignment/CMakeLists.txt | 26 ++++ .../alignment/ClangTidySuppressions.txt | 1 + .../cpp/AutoOptionalMemberAlignmentTest.cpp | 106 ++++++++++++++ .../alignment/cpp/BitAlignmentTest.cpp | 131 ++++++++++++++++++ .../cpp/OptionalMemberAlignmentTest.cpp | 104 ++++++++++++++ 8 files changed, 371 insertions(+) create mode 100644 test/language/alignment/CMakeLists.txt create mode 100644 test/language/alignment/ClangTidySuppressions.txt create mode 100644 test/language/alignment/cpp/AutoOptionalMemberAlignmentTest.cpp create mode 100644 test/language/alignment/cpp/BitAlignmentTest.cpp create mode 100644 test/language/alignment/cpp/OptionalMemberAlignmentTest.cpp diff --git a/extension/freemarker/Choice.cpp.ftl b/extension/freemarker/Choice.cpp.ftl index 2026193..1d55c9e 100644 --- a/extension/freemarker/Choice.cpp.ftl +++ b/extension/freemarker/Choice.cpp.ftl @@ -4,6 +4,7 @@ <#include "CompoundParameter.inc.ftl"> <@file_header generatorDescription/> +#include #include #include #include diff --git a/extension/freemarker/Structure.cpp.ftl b/extension/freemarker/Structure.cpp.ftl index ae7807b..7b29161 100644 --- a/extension/freemarker/Structure.cpp.ftl +++ b/extension/freemarker/Structure.cpp.ftl @@ -2,6 +2,7 @@ <#include "Structure.inc.ftl"> <@file_header generatorDescription/> +#include #include #include #include diff --git a/extension/freemarker/Union.cpp.ftl b/extension/freemarker/Union.cpp.ftl index 169b9ac..30cfa0d 100644 --- a/extension/freemarker/Union.cpp.ftl +++ b/extension/freemarker/Union.cpp.ftl @@ -4,6 +4,7 @@ <#include "CompoundParameter.inc.ftl"> <@file_header generatorDescription/> +#include #include #include #include diff --git a/test/language/alignment/CMakeLists.txt b/test/language/alignment/CMakeLists.txt new file mode 100644 index 0000000..cdb25a0 --- /dev/null +++ b/test/language/alignment/CMakeLists.txt @@ -0,0 +1,26 @@ +add_library(alignment_zs STATIC ${TEST_ZS_ROOT}/alignment.zs) +zserio_generate_cpp( + TARGET alignment_zs + SRC_DIR ${TEST_ZS_ROOT} + GEN_DIR ${CMAKE_CURRENT_BINARY_DIR}/gen + EXTRA_ARGS ${ZSERIO_EXTRA_ARGS} + GENERATED_SOURCES_VAR GENERATED_SOURCES + OUTPUT_VAR ZSERIO_LOG + ERROR_VAR ZSERIO_LOG +) +target_link_libraries(alignment_zs PUBLIC ZserioCpp17Runtime) +if (ZSERIO_LOG) + file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/zserio_log.txt "${ZSERIO_LOG}") + check_zserio_warnings("${ZSERIO_LOG}" 0) +endif () + +add_custom_test(alignment + DEPENDS + alignment_zs + SOURCES + ${CMAKE_CURRENT_SOURCE_DIR}/cpp/AutoOptionalMemberAlignmentTest.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/cpp/BitAlignmentTest.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/cpp/OptionalMemberAlignmentTest.cpp + GENERATED_SOURCES + ${GENERATED_SOURCES} +) diff --git a/test/language/alignment/ClangTidySuppressions.txt b/test/language/alignment/ClangTidySuppressions.txt new file mode 100644 index 0000000..88498ed --- /dev/null +++ b/test/language/alignment/ClangTidySuppressions.txt @@ -0,0 +1 @@ + readability-simplify-boolean-expr:gen/alignment/optional_member_alignment/OptionalMemberAlignment.cpp diff --git a/test/language/alignment/cpp/AutoOptionalMemberAlignmentTest.cpp b/test/language/alignment/cpp/AutoOptionalMemberAlignmentTest.cpp new file mode 100644 index 0000000..aba80d5 --- /dev/null +++ b/test/language/alignment/cpp/AutoOptionalMemberAlignmentTest.cpp @@ -0,0 +1,106 @@ +#include "alignment/auto_optional_member_alignment/AutoOptionalMemberAlignment.h" +#include "gtest/gtest.h" +#include "test_utils/TestUtility.h" + +namespace alignment +{ +namespace auto_optional_member_alignment +{ + +class AutoOptionalMemberAlignmentTest : public ::testing::Test +{ +protected: + static void writeData( + zserio::BitStreamWriter& writer, bool hasAutoOptional, int32_t autoOptionalField, int32_t field) + { + writer.writeBool(hasAutoOptional); + + if (hasAutoOptional) + { + writer.writeUnsignedBits32(0, 31); + writer.writeSignedBits32(autoOptionalField, 32); + } + + writer.writeSignedBits32(field, 32); + } + + static void fillData( + AutoOptionalMemberAlignment& data, bool hasAutoOptional, int32_t autoOptionalField, int32_t field) + { + if (hasAutoOptional) + { + data.autoOptionalField = autoOptionalField; + } + data.field = field; + } + + static constexpr size_t WITH_OPTIONAL_MEMBER_ALIGNMENT_BIT_SIZE = 96; + static constexpr size_t WITHOUT_OPTIONAL_MEMBER_ALIGNMENT_BIT_SIZE = 33; +}; + +TEST_F(AutoOptionalMemberAlignmentTest, readWithOptional) +{ + const bool hasAutoOptional = true; + const int32_t autoOptionalField = 0x1234; + const int32_t field = 0x7654; + AutoOptionalMemberAlignment data; + fillData(data, hasAutoOptional, autoOptionalField, field); + + test_utils::readTest( + std::bind(writeData, std::placeholders::_1, hasAutoOptional, autoOptionalField, field), data); +} + +TEST_F(AutoOptionalMemberAlignmentTest, readWithoutOptional) +{ + const bool hasAutoOptional = false; + const int32_t autoOptionalField = 0; + const int32_t field = 0x2222; + AutoOptionalMemberAlignment data; + fillData(data, hasAutoOptional, autoOptionalField, field); + + test_utils::readTest( + std::bind(writeData, std::placeholders::_1, hasAutoOptional, autoOptionalField, field), data); +} + +TEST_F(AutoOptionalMemberAlignmentTest, bitSizeOfWithOptional) +{ + AutoOptionalMemberAlignment data; + fillData(data, true, 0x4433, 0x1122); + zserio::View view(data); + + ASSERT_EQ(WITH_OPTIONAL_MEMBER_ALIGNMENT_BIT_SIZE, zserio::detail::bitSizeOf(view)); +} + +TEST_F(AutoOptionalMemberAlignmentTest, bitSizeOfWithoutOptional) +{ + AutoOptionalMemberAlignment data; + fillData(data, false, 0, 0x7624); + zserio::View view(data); + + ASSERT_EQ(WITHOUT_OPTIONAL_MEMBER_ALIGNMENT_BIT_SIZE, zserio::detail::bitSizeOf(view)); +} + +TEST_F(AutoOptionalMemberAlignmentTest, writeWithOptional) +{ + const bool hasAutoOptional = true; + const int32_t autoOptionalField = 0x9ADB; + const int32_t field = 0x8ACD; + AutoOptionalMemberAlignment data; + fillData(data, hasAutoOptional, autoOptionalField, field); + + test_utils::writeReadTest(data); +} + +TEST_F(AutoOptionalMemberAlignmentTest, writeWithoutOptional) +{ + const bool hasAutoOptional = true; + const int32_t autoOptionalField = 0; + const int32_t field = 0x7ACF; + AutoOptionalMemberAlignment data; + fillData(data, hasAutoOptional, autoOptionalField, field); + + test_utils::writeReadTest(data); +} + +} // namespace auto_optional_member_alignment +} // namespace alignment diff --git a/test/language/alignment/cpp/BitAlignmentTest.cpp b/test/language/alignment/cpp/BitAlignmentTest.cpp new file mode 100644 index 0000000..74b8e5d --- /dev/null +++ b/test/language/alignment/cpp/BitAlignmentTest.cpp @@ -0,0 +1,131 @@ +#include "alignment/bit_alignment/BitAlignment.h" +#include "gtest/gtest.h" +#include "test_utils/TestUtility.h" +namespace alignment +{ +namespace bit_alignment +{ + +class BitAlignmentTest : public ::testing::Test +{ +protected: + static void writeData(zserio::BitStreamWriter& writer) + { + writer.writeUnsignedBits32(ALIGNED1_FIELD_VALUE, 1); + + writer.writeUnsignedBits32(0, 1); + writer.writeUnsignedBits32(ALIGNED2_FIELD_VALUE, 2); + + writer.writeUnsignedBits32(0, 2); + writer.writeUnsignedBits32(ALIGNED3_FIELD_VALUE, 3); + + writer.writeUnsignedBits32(0, 3); + writer.writeUnsignedBits32(ALIGNED4_FIELD_VALUE, 4); + + writer.writeUnsignedBits32(0, 4); + writer.writeUnsignedBits32(ALIGNED5_FIELD_VALUE, 5); + + writer.writeUnsignedBits32(0, 5); + writer.writeUnsignedBits32(ALIGNED6_FIELD_VALUE, 6); + + writer.writeUnsignedBits32(0, 6); + writer.writeUnsignedBits32(ALIGNED7_FIELD_VALUE, 7); + + writer.writeUnsignedBits32(0, 7); + writer.writeUnsignedBits32(ALIGNED8_FIELD_VALUE, 8); + + writer.writeUnsignedBits32(0, 1); + writer.writeUnsignedBits32(0, 15); + writer.writeUnsignedBits32(ALIGNED16_FIELD_VALUE, 16); + + writer.writeUnsignedBits32(0, 1); + writer.writeUnsignedBits32(0, 31); + writer.writeUnsignedBits32(ALIGNED32_FIELD_VALUE, 32); + + writer.writeUnsignedBits64(0, 33); + writer.writeUnsignedBits64(0, 63); + writer.writeUnsignedBits64(ALIGNED64_FIELD_VALUE, 64); + } + + static void fillData(BitAlignment& data) + { + data.aligned1Field = ALIGNED1_FIELD_VALUE; + data.aligned2Field = ALIGNED2_FIELD_VALUE; + data.aligned3Field = ALIGNED3_FIELD_VALUE; + data.aligned4Field = ALIGNED4_FIELD_VALUE; + data.aligned5Field = ALIGNED5_FIELD_VALUE; + data.aligned6Field = ALIGNED6_FIELD_VALUE; + data.aligned7Field = ALIGNED7_FIELD_VALUE; + data.aligned8Field = ALIGNED8_FIELD_VALUE; + data.alignment16Break = ALIGNMENT16_BREAK; + data.aligned16Field = ALIGNED16_FIELD_VALUE; + data.alignment32Break = ALIGNMENT32_BREAK; + data.aligned32Field = ALIGNED32_FIELD_VALUE; + data.alignment64Break = ALIGNMENT64_BREAK; + data.aligned64Field = ALIGNED64_FIELD_VALUE; + } + + // constants + static constexpr size_t BIT_ALIGNMENT_BIT_SIZE = 320; + + static constexpr uint8_t ALIGNED1_FIELD_VALUE = 1; + static constexpr uint8_t ALIGNED2_FIELD_VALUE = 2; + static constexpr uint8_t ALIGNED3_FIELD_VALUE = 5; + static constexpr uint8_t ALIGNED4_FIELD_VALUE = 13; + static constexpr uint8_t ALIGNED5_FIELD_VALUE = 26; + static constexpr uint8_t ALIGNED6_FIELD_VALUE = 56; + static constexpr uint8_t ALIGNED7_FIELD_VALUE = 88; + static constexpr uint8_t ALIGNED8_FIELD_VALUE = 222; + static constexpr uint8_t ALIGNMENT16_BREAK = 0; + static constexpr uint16_t ALIGNED16_FIELD_VALUE = 0xcafe; + static constexpr uint8_t ALIGNMENT32_BREAK = 0; + static constexpr uint32_t ALIGNED32_FIELD_VALUE = 0xcafec0de; + static constexpr uint64_t ALIGNMENT64_BREAK = UINT64_C(0); + static constexpr uint64_t ALIGNED64_FIELD_VALUE = UINT64_C(0xcafec0dedeadface); +}; + +TEST_F(BitAlignmentTest, read) +{ + BitAlignment data; + fillData(data); + + test_utils::readTest(writeData, data); +} + +TEST_F(BitAlignmentTest, bitSizeOf) +{ + BitAlignment data; + fillData(data); + zserio::View view(data); + + // test default argument + ASSERT_EQ(BIT_ALIGNMENT_BIT_SIZE, zserio::detail::bitSizeOf(view)); +} + +TEST_F(BitAlignmentTest, bitSizeOfWithPosition) +{ + BitAlignment data; + fillData(data); + zserio::View view(data); + + // starting up to bit position 77, the structure still fits into original size thanks to alignments + zserio::BitSize startBitPosition = 0; + for (; startBitPosition < 78; ++startBitPosition) + { + ASSERT_EQ(BIT_ALIGNMENT_BIT_SIZE - startBitPosition, zserio::detail::bitSizeOf(view, startBitPosition)); + } + // starting at bit position 78, also next 64bits are needed + ASSERT_EQ( + BIT_ALIGNMENT_BIT_SIZE - startBitPosition + 64, zserio::detail::bitSizeOf(view, startBitPosition)); +} + +TEST_F(BitAlignmentTest, writeRead) +{ + BitAlignment data; + fillData(data); + + test_utils::writeReadTest(data); +} + +} // namespace bit_alignment +} // namespace alignment diff --git a/test/language/alignment/cpp/OptionalMemberAlignmentTest.cpp b/test/language/alignment/cpp/OptionalMemberAlignmentTest.cpp new file mode 100644 index 0000000..c748592 --- /dev/null +++ b/test/language/alignment/cpp/OptionalMemberAlignmentTest.cpp @@ -0,0 +1,104 @@ +#include "alignment/optional_member_alignment/OptionalMemberAlignment.h" +#include "gtest/gtest.h" +#include "test_utils/TestUtility.h" + +namespace alignment +{ +namespace optional_member_alignment +{ + +class OptionalMemberAlignmentTest : public ::testing::Test +{ +protected: + static void writeData( + zserio::BitStreamWriter& writer, bool hasOptional, int32_t optionalField, int32_t field) + { + writer.writeBool(hasOptional); + + if (hasOptional) + { + writer.writeUnsignedBits32(0, 31); + writer.writeSignedBits32(optionalField, 32); + } + + writer.writeSignedBits32(field, 32); + } + + static void fillData(OptionalMemberAlignment& data, bool hasOptional, int32_t optionalField, int32_t field) + { + data.hasOptional = hasOptional; + if (hasOptional) + { + data.optionalField = optionalField; + } + data.field = field; + } + + static constexpr size_t WITH_OPTIONAL_MEMBER_ALIGNMENT_BIT_SIZE = 96; + static constexpr size_t WITHOUT_OPTIONAL_MEMBER_ALIGNMENT_BIT_SIZE = 33; +}; + +TEST_F(OptionalMemberAlignmentTest, readWithOptional) +{ + const bool hasOptional = true; + const int32_t optionalField = 0x1234; + const int32_t field = 0x7654; + OptionalMemberAlignment data; + fillData(data, hasOptional, optionalField, field); + + test_utils::readTest(std::bind(writeData, std::placeholders::_1, hasOptional, optionalField, field), data); +} + +TEST_F(OptionalMemberAlignmentTest, readWithoutOptional) +{ + const bool hasOptional = false; + const int32_t optionalField = 0; + const int32_t field = 0x2222; + OptionalMemberAlignment data; + fillData(data, hasOptional, optionalField, field); + + test_utils::readTest(std::bind(writeData, std::placeholders::_1, hasOptional, optionalField, field), data); +} + +TEST_F(OptionalMemberAlignmentTest, bitSizeOfWithOptional) +{ + OptionalMemberAlignment data; + fillData(data, true, 0x4433, 0x1122); + zserio::View view(data); + + ASSERT_EQ(WITH_OPTIONAL_MEMBER_ALIGNMENT_BIT_SIZE, zserio::detail::bitSizeOf(view)); +} + +TEST_F(OptionalMemberAlignmentTest, bitSizeOfWithoutOptional) +{ + OptionalMemberAlignment data; + fillData(data, false, 0, 0x7624); + zserio::View view(data); + + ASSERT_EQ(WITHOUT_OPTIONAL_MEMBER_ALIGNMENT_BIT_SIZE, zserio::detail::bitSizeOf(view)); +} + +TEST_F(OptionalMemberAlignmentTest, writeReadWithOptional) +{ + const bool hasOptional = true; + const int32_t optionalField = 0x9ADB; + const int32_t field = 0x8ACD; + OptionalMemberAlignment data; + fillData(data, hasOptional, optionalField, field); + + test_utils::writeReadTest(data); +} + +TEST_F(OptionalMemberAlignmentTest, writeReadWithoutOptional) +{ + const bool hasOptional = true; + const int32_t optionalField = 0; + const int32_t field = 0x7ACF; + OptionalMemberAlignment data; + fillData(data, hasOptional, optionalField, field); + + test_utils::writeReadTest(data); +} + +} // namespace optional_member_alignment +} // namespace alignment