From cc844be19d3ac7acf89f52a1da13fe11024cf779 Mon Sep 17 00:00:00 2001 From: Mathias Kraus Date: Wed, 6 Sep 2023 22:45:51 +0200 Subject: [PATCH] iox-#1755 Distinct overloads for arithmetic types for 'LogStream' --- .../include/iox/detail/log/logstream.inl | 119 ++++++++++++++---- .../reporting/include/iox/log/logstream.hpp | 77 ++++++++++-- .../moduletests/test_reporting_logstream.cpp | 113 +++++++++++++++++ 3 files changed, 278 insertions(+), 31 deletions(-) diff --git a/iceoryx_hoofs/reporting/include/iox/detail/log/logstream.inl b/iceoryx_hoofs/reporting/include/iox/detail/log/logstream.inl index 7c4d99faa1..bde9292dab 100644 --- a/iceoryx_hoofs/reporting/include/iox/detail/log/logstream.inl +++ b/iceoryx_hoofs/reporting/include/iox/detail/log/logstream.inl @@ -1,5 +1,6 @@ // Copyright (c) 2019 - 2021 by Robert Bosch GmbH. All rights reserved. // Copyright (c) 2021 - 2022 by Apex.AI Inc. All rights reserved. +// Copyright (c) 2023 by Mathias Kraus . All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -108,9 +109,10 @@ inline LogStream& LogStream::self() noexcept return *this; } -// AXIVION Next Construct AutosarC++19_03-A3.9.1 : See at declaration in header -// AXIVION Next Construct AutosarC++19_03-M5.17.1 : This is not used as shift operator but as stream operator and does +// AXIVION DISABLE STYLE AutosarC++19_03-M5.17.1 : This is not used as shift operator but as stream operator and does // not require to implement '<<=' + +// AXIVION Next Construct AutosarC++19_03-A3.9.1 : See at declaration in header inline LogStream& LogStream::operator<<(const char* cstr) noexcept { m_logger.logString(cstr); @@ -118,8 +120,6 @@ inline LogStream& LogStream::operator<<(const char* cstr) noexcept return *this; } -// AXIVION Next Construct AutosarC++19_03-M5.17.1 : This is not used as shift operator but as stream operator and does -// not require to implement '<<=' inline LogStream& LogStream::operator<<(const std::string& str) noexcept { m_logger.logString(str.c_str()); @@ -127,26 +127,107 @@ inline LogStream& LogStream::operator<<(const std::string& str) noexcept return *this; } -// AXIVION Next Construct AutosarC++19_03-M5.17.1 : This is not used as shift operator but as stream operator and does -// not require to implement '<<=' inline LogStream& LogStream::operator<<(const bool val) noexcept { m_logger.logBool(val); return *this; } -// AXIVION Next Construct AutosarC++19_03-M5.17.1 : This is not used as shift operator but as stream operator and does -// not require to implement '<<=' -template ::value, bool>> -inline LogStream& LogStream::operator<<(const T val) noexcept +// AXIVION DISABLE STYLE AutosarC++19_03-A3.9.1 : See at declaration in header + +inline LogStream& LogStream::operator<<(const signed char val) noexcept { m_logger.logDec(val); m_isFlushed = false; return *this; } -// AXIVION Next Construct AutosarC++19_03-M5.17.1 : This is not used as shift operator but as stream operator and does -// not require to implement '<<=' +inline LogStream& LogStream::operator<<(const unsigned char val) noexcept +{ + m_logger.logDec(val); + m_isFlushed = false; + return *this; +} + +inline LogStream& LogStream::operator<<(const short val) noexcept +{ + m_logger.logDec(val); + m_isFlushed = false; + return *this; +} + +inline LogStream& LogStream::operator<<(const unsigned short val) noexcept +{ + m_logger.logDec(val); + m_isFlushed = false; + return *this; +} + +inline LogStream& LogStream::operator<<(const int val) noexcept +{ + m_logger.logDec(val); + m_isFlushed = false; + return *this; +} + +inline LogStream& LogStream::operator<<(const unsigned int val) noexcept +{ + m_logger.logDec(val); + m_isFlushed = false; + return *this; +} + +inline LogStream& LogStream::operator<<(const long val) noexcept +{ + m_logger.logDec(val); + m_isFlushed = false; + return *this; +} + +inline LogStream& LogStream::operator<<(const unsigned long val) noexcept +{ + m_logger.logDec(val); + m_isFlushed = false; + return *this; +} + +inline LogStream& LogStream::operator<<(const long long val) noexcept +{ + m_logger.logDec(val); + m_isFlushed = false; + return *this; +} + +inline LogStream& LogStream::operator<<(const unsigned long long val) noexcept +{ + m_logger.logDec(val); + m_isFlushed = false; + return *this; +} + +inline LogStream& LogStream::operator<<(const float val) noexcept +{ + m_logger.logDec(val); + m_isFlushed = false; + return *this; +} + +inline LogStream& LogStream::operator<<(const double val) noexcept +{ + m_logger.logDec(val); + m_isFlushed = false; + return *this; +} + +inline LogStream& LogStream::operator<<(const long double val) noexcept +{ + m_logger.logDec(val); + m_isFlushed = false; + return *this; +} + +// AXIVION ENABLE STYLE AutosarC++19_03-A3.9.1 + template ::value, bool>> inline LogStream& LogStream::operator<<(const LogHex val) noexcept { @@ -156,8 +237,6 @@ inline LogStream& LogStream::operator<<(const LogHex val) noexcept return *this; } -// AXIVION Next Construct AutosarC++19_03-M5.17.1 : This is not used as shift operator but as stream operator and does -// not require to implement '<<=' template ::value, bool>> inline LogStream& LogStream::operator<<(const LogHex val) noexcept { @@ -166,8 +245,6 @@ inline LogStream& LogStream::operator<<(const LogHex val) noexcept return *this; } -// AXIVION Next Construct AutosarC++19_03-M5.17.1 : This is not used as shift operator but as stream operator and does -// not require to implement '<<=' inline LogStream& LogStream::operator<<(const LogHex val) noexcept { m_logger.logHex(val.m_value); @@ -175,8 +252,6 @@ inline LogStream& LogStream::operator<<(const LogHex val) noe return *this; } -// AXIVION Next Construct AutosarC++19_03-M5.17.1 : This is not used as shift operator but as stream operator and does -// not require to implement '<<=' template ::value, bool>> inline LogStream& LogStream::operator<<(const LogOct val) noexcept { @@ -186,16 +261,12 @@ inline LogStream& LogStream::operator<<(const LogOct val) noexcept return *this; } -// AXIVION Next Construct AutosarC++19_03-M5.17.1 : This is not used as shift operator but as stream operator and does -// not require to implement '<<=' template inline LogStream& LogStream::operator<<(const Callable& c) noexcept { return c(*this); } -// AXIVION Next Construct AutosarC++19_03-M5.17.1 : This is not used as shift operator but as stream operator and does -// not require to implement '<<=' inline LogStream& LogStream::operator<<(const LogLevel value) noexcept { m_logger.logString(asStringLiteral(value)); @@ -214,8 +285,6 @@ inline LogStreamOff& LogStreamOff::self() noexcept return *this; } -// AXIVION Next Construct AutosarC++19_03-M5.17.1 : This is not used as shift operator but as stream operator and does -// not require to implement '<<=' template inline LogStreamOff& LogStreamOff::operator<<(T&&) noexcept { @@ -223,6 +292,8 @@ inline LogStreamOff& LogStreamOff::operator<<(T&&) noexcept } } // namespace internal +// AXIVION ENABLE STYLE AutosarC++19_03-M5.17.1 + } // namespace log } // namespace iox diff --git a/iceoryx_hoofs/reporting/include/iox/log/logstream.hpp b/iceoryx_hoofs/reporting/include/iox/log/logstream.hpp index 9809f568be..7f18e4b39e 100644 --- a/iceoryx_hoofs/reporting/include/iox/log/logstream.hpp +++ b/iceoryx_hoofs/reporting/include/iox/log/logstream.hpp @@ -1,5 +1,6 @@ // Copyright (c) 2019 - 2021 by Robert Bosch GmbH. All rights reserved. // Copyright (c) 2021 - 2022 by Apex.AI Inc. All rights reserved. +// Copyright (c) 2023 by Mathias Kraus . All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -156,17 +157,79 @@ class LogStream /// and avoid the std::string dependency; alternatively this could be implemented as free function LogStream& operator<<(const std::string& str) noexcept; - /// @brief Logging support for boolean - /// @param[in] val is the boolean to log + // AXIVION DISABLE STYLE AutosarC++19_03-A3.9.1 : Basic numeric types are used in order to cover als basic numeric types, independent of the type alias + + /// @brief Logging support for 'boolean' + /// @param[in] val is the 'boolean' to log /// @return a reference to the LogStream instance LogStream& operator<<(const bool val) noexcept; - /// @brief Logging support for arithmetic numbers in decimal format - /// @tparam[in] T is the arithmetic data type of the value to log - /// @param[in] val is the number to log + /// @brief Logging support for 'signed char' + /// @param[in] val is the 'signed char' to log + /// @return a reference to the LogStream instance + LogStream& operator<<(const signed char val) noexcept; + + /// @brief Logging support for 'unsigned char' + /// @param[in] val is the 'unsigned char' to log + /// @return a reference to the LogStream instance + LogStream& operator<<(const unsigned char val) noexcept; + + /// @brief Logging support for 'short' + /// @param[in] val is the 'short' to log + /// @return a reference to the LogStream instance + LogStream& operator<<(const short val) noexcept; + + /// @brief Logging support for 'unsigned shor' + /// @param[in] val is the 'unsigned shor' to log + /// @return a reference to the LogStream instance + LogStream& operator<<(const unsigned short val) noexcept; + + /// @brief Logging support for 'int' + /// @param[in] val is the 'int' to log + /// @return a reference to the LogStream instance + LogStream& operator<<(const int val) noexcept; + + /// @brief Logging support for 'unsigned int' + /// @param[in] val is the 'unsigned int' to log + /// @return a reference to the LogStream instance + LogStream& operator<<(const unsigned int val) noexcept; + + /// @brief Logging support for 'long' + /// @param[in] val is the 'long' to log /// @return a reference to the LogStream instance - template ::value, bool> = 0> - LogStream& operator<<(const T val) noexcept; + LogStream& operator<<(const long val) noexcept; + + /// @brief Logging support for 'unsigned long' + /// @param[in] val is the 'unsigned long' to log + /// @return a reference to the LogStream instance + LogStream& operator<<(const unsigned long val) noexcept; + + /// @brief Logging support for 'long long' + /// @param[in] val is the 'long long' to log + /// @return a reference to the LogStream instance + LogStream& operator<<(const long long val) noexcept; + + /// @brief Logging support for 'unsigned long long' + /// @param[in] val is the 'unsigned long long' to log + /// @return a reference to the LogStream instance + LogStream& operator<<(const unsigned long long val) noexcept; + + /// @brief Logging support for 'float' + /// @param[in] val is the 'float' to log + /// @return a reference to the LogStream instance + LogStream& operator<<(const float val) noexcept; + + /// @brief Logging support for 'double' + /// @param[in] val is the 'double' to log + /// @return a reference to the LogStream instance + LogStream& operator<<(const double val) noexcept; + + /// @brief Logging support for 'long double' + /// @param[in] val is the 'long double' to log + /// @return a reference to the LogStream instance + LogStream& operator<<(const long double val) noexcept; + + // AXIVION ENABLE STYLE AutosarC++19_03-A3.9.1 /// @brief Logging support for integral numbers in hexadecimal format /// @tparam[in] T is the integral data type of the value to log diff --git a/iceoryx_hoofs/test/moduletests/test_reporting_logstream.cpp b/iceoryx_hoofs/test/moduletests/test_reporting_logstream.cpp index e1e18af962..41995cdd4c 100644 --- a/iceoryx_hoofs/test/moduletests/test_reporting_logstream.cpp +++ b/iceoryx_hoofs/test/moduletests/test_reporting_logstream.cpp @@ -1,5 +1,6 @@ // Copyright (c) 2019, 2021 by Robert Bosch GmbH. All rights reserved. // Copyright (c) 2021 by Apex.AI Inc. All rights reserved. +// Copyright (c) 2023 by Mathias Kraus . All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -350,6 +351,26 @@ TYPED_TEST(IoxLogStreamHexFloatingPoint_test, StreamOperatorLogHex_ValueMax) testStreamOperatorLogHexFloatingPoint(this->loggerMock, this->LogValueMax); } +template +class Wrapper +{ + public: + constexpr explicit Wrapper(T value) noexcept + : m_value(value) + { + } + + // NOLINTJUSTIFICATION Implicit conversion is required for the test + // NOLINTNEXTLINE(hicpp-explicit-conversions) + constexpr operator T() const noexcept + { + return m_value; + } + + private: + T m_value{}; +}; + using ArithmeticTypes = Types; @@ -359,6 +380,8 @@ template class IoxLogStreamArithmetic_test : public IoxLogStream_test { public: + using type_t = Arithmetic; + Arithmetic LogValueLow = std::numeric_limits::lowest(); Arithmetic LogValueMin = std::numeric_limits::min(); Arithmetic LogValueMax = std::numeric_limits::max(); @@ -436,6 +459,36 @@ TYPED_TEST(IoxLogStreamArithmetic_test, StreamOperator_ValueMax) EXPECT_THAT(this->loggerMock.logs[0].message, StrEq(convertToString(this->LogValueMax))); } +TYPED_TEST(IoxLogStreamArithmetic_test, StreamOperator_WrappedAndImplicitelyConverted_ValueLow) +{ + ::testing::Test::RecordProperty("TEST_ID", "86dccc28-0007-4ab3-88c6-216eeb861fef"); + using type_t = typename TestFixture::type_t; + LogStreamSut(this->loggerMock) << Wrapper(this->LogValueLow); + + ASSERT_THAT(this->loggerMock.logs.size(), Eq(1U)); + EXPECT_THAT(this->loggerMock.logs[0].message, StrEq(convertToString(this->LogValueLow))); +} + +TYPED_TEST(IoxLogStreamArithmetic_test, StreamOperator_WrappedAndImplicitelyConverted_ValueMin) +{ + ::testing::Test::RecordProperty("TEST_ID", "72bc51fe-a23f-4c7d-a17f-0e4ad29bee9f"); + using type_t = typename TestFixture::type_t; + LogStreamSut(this->loggerMock) << Wrapper(this->LogValueMin); + + ASSERT_THAT(this->loggerMock.logs.size(), Eq(1U)); + EXPECT_THAT(this->loggerMock.logs[0].message, StrEq(convertToString(this->LogValueMin))); +} + +TYPED_TEST(IoxLogStreamArithmetic_test, StreamOperator_WrappedAndImplicitelyConverted_ValueMax) +{ + ::testing::Test::RecordProperty("TEST_ID", "49e79c8b-98c0-4074-aed1-25293bf49bd0"); + using type_t = typename TestFixture::type_t; + LogStreamSut(this->loggerMock) << Wrapper(this->LogValueMax); + + ASSERT_THAT(this->loggerMock.logs.size(), Eq(1U)); + EXPECT_THAT(this->loggerMock.logs[0].message, StrEq(convertToString(this->LogValueMax))); +} + TYPED_TEST(IoxLogStreamArithmetic_test, StreamOperator_ConstValueLow) { ::testing::Test::RecordProperty("TEST_ID", "65cfbc9b-a535-47fa-a543-0c31ba63d4ba"); @@ -463,6 +516,36 @@ TYPED_TEST(IoxLogStreamArithmetic_test, StreamOperator_ConstValueMax) EXPECT_THAT(this->loggerMock.logs[0].message, StrEq(convertToString(this->ConstLogValueMax))); } +TYPED_TEST(IoxLogStreamArithmetic_test, StreamOperator_WrappedAndImplicitelyConverted_ConstValueLow) +{ + ::testing::Test::RecordProperty("TEST_ID", "77cb68ac-bffb-4cf5-a4c2-119e5aaae307"); + using type_t = typename TestFixture::type_t; + LogStreamSut(this->loggerMock) << Wrapper(this->ConstLogValueLow); + + ASSERT_THAT(this->loggerMock.logs.size(), Eq(1U)); + EXPECT_THAT(this->loggerMock.logs[0].message, StrEq(convertToString(this->ConstLogValueLow))); +} + +TYPED_TEST(IoxLogStreamArithmetic_test, StreamOperator_WrappedAndImplicitelyConverted_ConstValueMin) +{ + ::testing::Test::RecordProperty("TEST_ID", "3b042ec2-0a6d-4d24-9a12-dab81736847f"); + using type_t = typename TestFixture::type_t; + LogStreamSut(this->loggerMock) << Wrapper(this->ConstLogValueMin); + + ASSERT_THAT(this->loggerMock.logs.size(), Eq(1U)); + EXPECT_THAT(this->loggerMock.logs[0].message, StrEq(convertToString(this->ConstLogValueMin))); +} + +TYPED_TEST(IoxLogStreamArithmetic_test, StreamOperator_WrappedAndImplicitelyConverted_ConstValueMax) +{ + ::testing::Test::RecordProperty("TEST_ID", "83194cc1-3c2a-4c0e-a413-972a95f36b66"); + using type_t = typename TestFixture::type_t; + LogStreamSut(this->loggerMock) << Wrapper(this->ConstLogValueMax); + + ASSERT_THAT(this->loggerMock.logs.size(), Eq(1)); + EXPECT_THAT(this->loggerMock.logs[0].message, StrEq(convertToString(this->ConstLogValueMax))); +} + TYPED_TEST(IoxLogStreamArithmetic_test, StreamOperator_ConstexprValueLow) { ::testing::Test::RecordProperty("TEST_ID", "e9688979-d209-4718-9810-49684fdd9261"); @@ -490,4 +573,34 @@ TYPED_TEST(IoxLogStreamArithmetic_test, StreamOperator_ConstexprValueMax) EXPECT_THAT(this->loggerMock.logs[0].message, StrEq(convertToString(this->ConstexprLogValueMax))); } +TYPED_TEST(IoxLogStreamArithmetic_test, StreamOperator_WrappedAndImplicitelyConverted_ConstexprValueLow) +{ + ::testing::Test::RecordProperty("TEST_ID", "3025b6e3-3abd-49e8-8d3c-f6fa0c164011"); + using type_t = typename TestFixture::type_t; + LogStreamSut(this->loggerMock) << Wrapper(this->ConstexprLogValueLow); + + ASSERT_THAT(this->loggerMock.logs.size(), Eq(1U)); + EXPECT_THAT(this->loggerMock.logs[0].message, StrEq(convertToString(this->ConstexprLogValueLow))); +} + +TYPED_TEST(IoxLogStreamArithmetic_test, StreamOperator_WrappedAndImplicitelyConverted_ConstexprValueMin) +{ + ::testing::Test::RecordProperty("TEST_ID", "c49ad58d-948a-499a-9e2b-8bbdeb9b5c5e"); + using type_t = typename TestFixture::type_t; + LogStreamSut(this->loggerMock) << Wrapper(this->ConstexprLogValueMin); + + ASSERT_THAT(this->loggerMock.logs.size(), Eq(1U)); + EXPECT_THAT(this->loggerMock.logs[0].message, StrEq(convertToString(this->ConstexprLogValueMin))); +} + +TYPED_TEST(IoxLogStreamArithmetic_test, StreamOperator_WrappedAndImplicitelyConverted_ConstexprValueMax) +{ + ::testing::Test::RecordProperty("TEST_ID", "8c7637ce-8155-4edc-88e2-a155169934f2"); + using type_t = typename TestFixture::type_t; + LogStreamSut(this->loggerMock) << Wrapper(this->ConstexprLogValueMax); + + ASSERT_THAT(this->loggerMock.logs.size(), Eq(1U)); + EXPECT_THAT(this->loggerMock.logs[0].message, StrEq(convertToString(this->ConstexprLogValueMax))); +} + } // namespace