--- src/base/Makefile.am | 6 +- src/base/sna.h | 108 ++++++++++++++++++++++++++++++++++++ src/base/tests/sna_test.cc | 109 +++++++++++++++++++++++++++++++++++++ 3 files changed, 221 insertions(+), 2 deletions(-) create mode 100755 src/base/sna.h create mode 100755 src/base/tests/sna_test.cc
diff --git a/src/base/Makefile.am b/src/base/Makefile.am index 025fb86a2..5082175cf 100644 --- a/src/base/Makefile.am +++ b/src/base/Makefile.am @@ -173,7 +173,8 @@ noinst_HEADERS += \ src/base/unix_client_socket.h \ src/base/unix_server_socket.h \ src/base/unix_socket.h \ - src/base/usrbuf.h + src/base/usrbuf.h \ + src/base/sna.h TESTS += bin/testleap bin/libbase_test bin/core_common_test @@ -237,7 +238,8 @@ bin_libbase_test_SOURCES = \ src/base/tests/time_compare_test.cc \ src/base/tests/time_convert_test.cc \ src/base/tests/time_subtract_test.cc \ - src/base/tests/unix_socket_test.cc + src/base/tests/unix_socket_test.cc \ + src/base/tests/sna_test.cc bin_libbase_test_LDADD = \ $(GTEST_DIR)/lib/libgtest.la \ diff --git a/src/base/sna.h b/src/base/sna.h new file mode 100755 index 000000000..8fc4da202 --- /dev/null +++ b/src/base/sna.h @@ -0,0 +1,108 @@ +/* -*- OpenSAF -*- + * + * Copyright Ericsson AB 2019 - All Rights Reserved. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. This file and program are licensed + * under the GNU Lesser General Public License Version 2.1, February 1999. + * The complete license can be accessed from the following location: + * http://opensource.org/licenses/lgpl-license.php + * See the Copying file included with the OpenSAF distribution for full + * licensing terms. + * + * Reference: Serial Number Arithmetic from RFC1982 + * + */ + +#ifndef BASE_SNA_H_ +#define BASE_SNA_H_ + +#include <typeinfo> +#include <stdexcept> + +#define MAX_16BITS 65536 // 2^16 +#define MAX_32BITS 4294967296 // 2^32 + +template <class T> +class _sna +{ + private: + T i; + uint64_t max() { + if (typeid(T) == typeid(uint64_t)) { + return MAX_32BITS; + } else if (typeid(T) == typeid(uint32_t)) { + return MAX_16BITS; + } else { + printf("Type:%s\n", typeid(T).name()); + throw std::out_of_range("Invalid type"); + } + } + public: + _sna(): i(0) {} + _sna(const _sna &t) { + i = t.i; + } + _sna(const uint32_t &n) { + if ((n < 0) || (n > (max()-1))) + throw std::out_of_range("SNA assign with invalid value"); + i = n; + } + _sna& operator=(const _sna &t) { + // check for self-assignment + if(&t == this) + return *this; + i = t.i; + return *this; + } + uint64_t value() { + return i; + } + _sna& operator+=(const uint64_t& n) { + if ((n < 0) || (n > (max()/2 - 1))) + throw std::out_of_range("SNA received invalid addition value"); + i = (i + n) % max(); + return *this; + } + friend _sna operator+(_sna m, const uint64_t& n) { + m += n; + return m; + } + // prefix ++ + _sna& operator++() { + *this += 1; + return *this; + } + // postfix ++ + _sna operator++(int) { + _sna tmp(*this); + operator++(); + return tmp; + } + bool operator==(const _sna& rhs) { + return i == rhs.i; + } + bool operator!=(const _sna& rhs) { + return i != rhs.i; + } + bool operator<(const _sna& rhs) { + return (i < rhs.i && rhs.i - i < max()/2) || \ + (i > rhs.i && i - rhs.i > max()/2); + } + bool operator>=(const _sna& rhs) { + return !(*this < rhs); + } + bool operator>(const _sna& rhs) { + return (i < rhs.i && rhs.i - i > max()/2) || \ + (i > rhs.i && i - rhs.i < max()/2); + } + bool operator<=(const _sna& rhs) { + return !(*this > rhs); + } +}; + +typedef _sna<uint32_t> uint16_sna_t; +typedef _sna<uint64_t> uint32_sna_t; + +#endif // BASE_SNA_H_ \ No newline at end of file diff --git a/src/base/tests/sna_test.cc b/src/base/tests/sna_test.cc new file mode 100755 index 000000000..9510dfbc0 --- /dev/null +++ b/src/base/tests/sna_test.cc @@ -0,0 +1,109 @@ +/* -*- OpenSAF -*- + * + * Copyright Ericsson AB 2019 - All Rights Reserved. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. This file and program are licensed + * under the GNU Lesser General Public License Version 2.1, February 1999. + * The complete license can be accessed from the following location: + * http://opensource.org/licenses/lgpl-license.php + * See the Copying file included with the OpenSAF distribution for full + * licensing terms. + * + * Reference: Serial Number Arithmetic from RFC1982 + * + */ + +#include "base/sna.h" +#include "gtest/gtest.h" + +template <class T> +int test_sna(T &x) +{ + int rc = 1; + printf("\n=============== START with x=%lu ===============\n", x.value()); + T y = x; + printf("x=%lu, y=%lu: check x == y++ is TRUE\n", x.value(), y.value()); + if (x == y++) { + printf("now y=%lu, reset y = x\n", y.value()); + y = x; + printf("x=%lu, y=%lu: check x != ++y is TRUE\n", x.value(), y.value()); + if (x != ++y) { + printf("now y=%lu, reset y = x\n", y.value()); + y = x; + printf("x=%lu, y=%lu: check x < ++y is TRUE\n", x.value(), y.value()); + if (x < ++y) { + printf("x=%lu: check x + 1 > x and x + 1 >= x is TRUE\n", x.value()); + if ((x + 1 > x) && (x + 1 >= x)) { + printf("x=%lu: check x < x + 1 and x <= x + 1 is TRUE\n", x.value()); + y = x + 1; + printf("y = x+1 => y=%lu\n", y.value()); + y = y + 1; + printf("y = y+1 => y=%lu\n", y.value()); + if ((x < x + 1) && (x <= x + 1)) { + try { + printf("x=%lu: add invalid (-1)\n", x.value()); + x = x + (-1); + } catch (const std::out_of_range& oor) { + printf("Expected error: %s\n", oor.what()); + try { + uint64_t max_value = 0; + if (typeid(T) == typeid(uint16_sna_t)) + max_value = MAX_16BITS; + else if (typeid(T) == typeid(uint32_sna_t)) + max_value = MAX_32BITS; + printf("x=%lu: add invalid (%lu)\n", x.value(), max_value); + x = x + max_value; + } catch (const std::out_of_range& oor) { + printf("Expected error: %s\n", oor.what()); + rc = 0; + } + } + } + } + } + } + } + printf("================ END with x=%lu ================\n", x.value()); + return rc; +} + + +class SnaTest : public ::testing::Test { + protected: + SnaTest() {} + virtual ~SnaTest() { + // Cleanup work that doesn't throw exceptions here. + } + virtual void SetUp() { + // Code here will be called immediately after the constructor (right + // before each test) + } + virtual void TearDown() {} +}; + +TEST_F(SnaTest, unit16_sna) { + uint16_sna_t x; + EXPECT_EQ(0, test_sna(x)); + x = 1; + EXPECT_EQ(0, test_sna(x)); + x = MAX_16BITS - 1; + EXPECT_EQ(0, test_sna(x)); +} + +TEST_F(SnaTest, unit32_sna) { + uint32_sna_t x; + EXPECT_EQ(0, test_sna(x)); + x = 1; + EXPECT_EQ(0, test_sna(x)); + x = MAX_32BITS - 1; + EXPECT_EQ(0, test_sna(x)); +} + + +int main(int argc, char **argv) +{ + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} -- 2.17.1 _______________________________________________ Opensaf-devel mailing list Opensaf-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/opensaf-devel