---
 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

Reply via email to