Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Add unit tests for ClockVector
authorMaxwell Pirtle <maxwellpirtle@gmail.com>
Mon, 15 May 2023 07:04:11 +0000 (09:04 +0200)
committerMaxwell Pirtle <maxwellpirtle@gmail.com>
Mon, 15 May 2023 07:04:11 +0000 (09:04 +0200)
MANIFEST.in
src/mc/api/ClockVector.hpp
src/mc/explo/odpor/ClockVector_test.cpp [new file with mode: 0644]
tools/cmake/Tests.cmake

index 718c24d..ec8c8d1 100644 (file)
@@ -2191,6 +2191,7 @@ include src/mc/explo/LivenessChecker.cpp
 include src/mc/explo/LivenessChecker.hpp
 include src/mc/explo/UdporChecker.cpp
 include src/mc/explo/UdporChecker.hpp
+include src/mc/explo/odpor/ClockVector_test.cpp
 include src/mc/explo/odpor/Execution.cpp
 include src/mc/explo/odpor/Execution.hpp
 include src/mc/explo/odpor/Execution_test.cpp
index d4dfa37..9390035 100644 (file)
@@ -9,6 +9,7 @@
 #include "simgrid/forward.h"
 
 #include <cstdint>
+#include <initializer_list>
 #include <optional>
 #include <unordered_map>
 
@@ -28,6 +29,7 @@ public:
   ClockVector(const ClockVector&)            = default;
   ClockVector& operator=(ClockVector const&) = default;
   ClockVector(ClockVector&&)                 = default;
+  ClockVector(std::initializer_list<std::pair<const aid_t, uint32_t>> init) : contents(std::move(init)) {}
 
   /**
    * @brief The number of components in this
diff --git a/src/mc/explo/odpor/ClockVector_test.cpp b/src/mc/explo/odpor/ClockVector_test.cpp
new file mode 100644 (file)
index 0000000..da266b0
--- /dev/null
@@ -0,0 +1,335 @@
+/* Copyright (c) 2017-2023. The SimGrid Team. All rights reserved.               */
+
+/* This program is free software; you can redistribute it and/or modify it
+ * under the terms of the license (GNU LGPL) which comes with this package. */
+
+#include "src/3rd-party/catch.hpp"
+#include "src/mc/api/ClockVector.hpp"
+
+using namespace simgrid::mc;
+
+TEST_CASE("simgrid::mc::ClockVector: Constructing Vectors")
+{
+  ClockVector cv;
+  REQUIRE(cv.size() == 0);
+
+  // Verify `cv` doesn't map any values
+  REQUIRE_FALSE(cv.get(0).has_value());
+  REQUIRE_FALSE(cv.get(1).has_value());
+  REQUIRE_FALSE(cv.get(2).has_value());
+  REQUIRE_FALSE(cv.get(3).has_value());
+}
+
+TEST_CASE("simgrid::mc::ClockVector: Testing operator[]")
+{
+  ClockVector cv;
+  cv[0] = 1;
+  REQUIRE(cv.size() == 1);
+
+  REQUIRE(cv.get(0).has_value());
+  REQUIRE(cv.get(0).value() == 1);
+
+  // Verify `cv` doesn't map other values
+  REQUIRE_FALSE(cv.get(2).has_value());
+  REQUIRE_FALSE(cv.get(3).has_value());
+
+  cv[10] = 31;
+  REQUIRE(cv.size() == 2);
+
+  // Old values are still mapped
+  REQUIRE(cv.get(0).has_value());
+  REQUIRE(cv.get(0).value() == 1);
+  REQUIRE(cv[0] == 1);
+  REQUIRE(cv.get(10).has_value());
+  REQUIRE(cv.get(10).value() == 31);
+  REQUIRE(cv[10] == 31);
+
+  // Verify `cv` doesn't map other values
+  REQUIRE_FALSE(cv.get(2).has_value());
+  REQUIRE_FALSE(cv.get(3).has_value());
+}
+
+TEST_CASE("simgrid::mc::ClockVector: Testing Maximal Clock Vectors")
+{
+  SECTION("Max with zero clock vector yields self")
+  {
+    ClockVector cv1{
+        {1, 2},
+        {2, 10},
+        {3, 5},
+    };
+    ClockVector cv2;
+    ClockVector maxCV = ClockVector::max(cv1, cv2);
+
+    REQUIRE(maxCV.size() == 3);
+    REQUIRE(maxCV.get(1).has_value());
+    REQUIRE(maxCV.get(1).value() == 2);
+    REQUIRE(maxCV[1] == 2);
+
+    REQUIRE(maxCV.get(2).has_value());
+    REQUIRE(maxCV.get(2).value() == 10);
+    REQUIRE(maxCV[2] == 10);
+
+    REQUIRE(maxCV.get(3).has_value());
+    REQUIRE(maxCV.get(3).value() == 5);
+    REQUIRE(maxCV[3] == 5);
+  }
+
+  SECTION("Max with self clock vector yields self")
+  {
+    ClockVector cv1{
+        {1, 2},
+        {2, 10},
+        {3, 5},
+    };
+    ClockVector maxCV = ClockVector::max(cv1, cv1);
+
+    REQUIRE(maxCV.size() == 3);
+    REQUIRE(maxCV.get(1).has_value());
+    REQUIRE(maxCV.get(1).value() == 2);
+    REQUIRE(maxCV[1] == 2);
+
+    REQUIRE(maxCV.get(2).has_value());
+    REQUIRE(maxCV.get(2).value() == 10);
+    REQUIRE(maxCV[2] == 10);
+
+    REQUIRE(maxCV.get(3).has_value());
+    REQUIRE(maxCV.get(3).value() == 5);
+    REQUIRE(maxCV[3] == 5);
+  }
+
+  SECTION("Testing with partial overlaps")
+  {
+    SECTION("Example 1")
+    {
+      ClockVector cv1{
+          {1, 2},
+          {2, 10},
+          {3, 5},
+      };
+      ClockVector cv2{
+          {1, 5},
+          {3, 1},
+          {7, 10},
+      };
+      ClockVector maxCV = ClockVector::max(cv1, cv2);
+
+      REQUIRE(maxCV.size() == 4);
+      REQUIRE(maxCV.get(1).has_value());
+      REQUIRE(maxCV.get(1).value() == 5);
+      REQUIRE(maxCV[1] == 5);
+
+      REQUIRE(maxCV.get(2).has_value());
+      REQUIRE(maxCV.get(2).value() == 10);
+      REQUIRE(maxCV[2] == 10);
+
+      REQUIRE(maxCV.get(3).has_value());
+      REQUIRE(maxCV.get(3).value() == 5);
+      REQUIRE(maxCV[3] == 5);
+
+      REQUIRE(maxCV.get(7).has_value());
+      REQUIRE(maxCV.get(7).value() == 10);
+      REQUIRE(maxCV[7] == 10);
+    }
+
+    SECTION("Example 2")
+    {
+      ClockVector cv1{
+          {1, 2}, {2, 10}, {3, 5}, {4, 40}, {11, 3}, {12, 8},
+      };
+      ClockVector cv2{
+          {1, 18}, {2, 4}, {4, 41}, {10, 3}, {12, 8},
+      };
+      ClockVector maxCV = ClockVector::max(cv1, cv2);
+
+      REQUIRE(maxCV.size() == 7);
+      REQUIRE(maxCV.get(1).has_value());
+      REQUIRE(maxCV.get(1).value() == 18);
+      REQUIRE(maxCV[1] == 18);
+
+      REQUIRE(maxCV.get(2).has_value());
+      REQUIRE(maxCV.get(2).value() == 10);
+      REQUIRE(maxCV[2] == 10);
+
+      REQUIRE(maxCV.get(3).has_value());
+      REQUIRE(maxCV.get(3).value() == 5);
+      REQUIRE(maxCV[3] == 5);
+
+      REQUIRE(maxCV.get(4).has_value());
+      REQUIRE(maxCV.get(4).value() == 41);
+      REQUIRE(maxCV[4] == 41);
+
+      REQUIRE(maxCV.get(10).has_value());
+      REQUIRE(maxCV.get(10).value() == 3);
+      REQUIRE(maxCV[10] == 3);
+
+      REQUIRE(maxCV.get(11).has_value());
+      REQUIRE(maxCV.get(11).value() == 3);
+      REQUIRE(maxCV[11] == 3);
+
+      REQUIRE(maxCV.get(12).has_value());
+      REQUIRE(maxCV.get(12).value() == 8);
+      REQUIRE(maxCV[12] == 8);
+    }
+
+    SECTION("Example 3")
+    {
+      ClockVector cv1{{1, 2}, {4, 41}, {12, 0}, {100, 5}};
+      ClockVector cv2{{2, 4}, {4, 10}, {10, 3}, {12, 8}, {19, 0}, {21, 6}, {22, 0}};
+      ClockVector cv3{{21, 60}, {22, 6}, {100, 3}};
+      ClockVector maxCV = ClockVector::max(cv1, cv2);
+      maxCV             = ClockVector::max(maxCV, cv3);
+
+      REQUIRE(maxCV.size() == 9);
+      REQUIRE(maxCV.get(1).has_value());
+      REQUIRE(maxCV.get(1).value() == 2);
+      REQUIRE(maxCV[1] == 2);
+
+      REQUIRE(maxCV.get(2).has_value());
+      REQUIRE(maxCV.get(2).value() == 4);
+      REQUIRE(maxCV[2] == 4);
+
+      REQUIRE(maxCV.get(4).has_value());
+      REQUIRE(maxCV.get(4).value() == 41);
+      REQUIRE(maxCV[4] == 41);
+
+      REQUIRE(maxCV.get(10).has_value());
+      REQUIRE(maxCV.get(10).value() == 3);
+      REQUIRE(maxCV[10] == 3);
+
+      REQUIRE(maxCV.get(12).has_value());
+      REQUIRE(maxCV.get(12).value() == 8);
+      REQUIRE(maxCV[12] == 8);
+
+      REQUIRE(maxCV.get(19).has_value());
+      REQUIRE(maxCV.get(19).value() == 0);
+      REQUIRE(maxCV[19] == 0);
+
+      REQUIRE(maxCV.get(21).has_value());
+      REQUIRE(maxCV.get(21).value() == 60);
+      REQUIRE(maxCV[21] == 60);
+
+      REQUIRE(maxCV.get(22).has_value());
+      REQUIRE(maxCV.get(22).value() == 6);
+      REQUIRE(maxCV[22] == 6);
+
+      REQUIRE(maxCV.get(100).has_value());
+      REQUIRE(maxCV.get(100).value() == 5);
+      REQUIRE(maxCV[100] == 5);
+    }
+  }
+
+  SECTION("Testing without overlaps")
+  {
+    SECTION("Example 1")
+    {
+      ClockVector cv1{{1, 2}};
+      ClockVector cv2{
+          {2, 4},
+          {4, 41},
+          {10, 3},
+          {12, 8},
+      };
+      ClockVector maxCV = ClockVector::max(cv1, cv2);
+
+      REQUIRE(maxCV.size() == 5);
+      REQUIRE(maxCV.get(1).has_value());
+      REQUIRE(maxCV.get(1).value() == 2);
+      REQUIRE(maxCV[1] == 2);
+
+      REQUIRE(maxCV.get(2).has_value());
+      REQUIRE(maxCV.get(2).value() == 4);
+      REQUIRE(maxCV[2] == 4);
+
+      REQUIRE(maxCV.get(4).has_value());
+      REQUIRE(maxCV.get(4).value() == 41);
+      REQUIRE(maxCV[4] == 41);
+
+      REQUIRE(maxCV.get(10).has_value());
+      REQUIRE(maxCV.get(10).value() == 3);
+      REQUIRE(maxCV[10] == 3);
+
+      REQUIRE(maxCV.get(12).has_value());
+      REQUIRE(maxCV.get(12).value() == 8);
+      REQUIRE(maxCV[12] == 8);
+    }
+
+    SECTION("Example 2")
+    {
+      ClockVector cv1{{1, 2}, {4, 41}};
+      ClockVector cv2{
+          {2, 4},
+          {10, 3},
+          {12, 8},
+      };
+      ClockVector maxCV = ClockVector::max(cv1, cv2);
+
+      REQUIRE(maxCV.size() == 5);
+      REQUIRE(maxCV.get(1).has_value());
+      REQUIRE(maxCV.get(1).value() == 2);
+      REQUIRE(maxCV[1] == 2);
+
+      REQUIRE(maxCV.get(2).has_value());
+      REQUIRE(maxCV.get(2).value() == 4);
+      REQUIRE(maxCV[2] == 4);
+
+      REQUIRE(maxCV.get(4).has_value());
+      REQUIRE(maxCV.get(4).value() == 41);
+      REQUIRE(maxCV[4] == 41);
+
+      REQUIRE(maxCV.get(10).has_value());
+      REQUIRE(maxCV.get(10).value() == 3);
+      REQUIRE(maxCV[10] == 3);
+
+      REQUIRE(maxCV.get(12).has_value());
+      REQUIRE(maxCV.get(12).value() == 8);
+      REQUIRE(maxCV[12] == 8);
+    }
+
+    SECTION("Example 3")
+    {
+      ClockVector cv1{{1, 2}, {4, 41}};
+      ClockVector cv2{{2, 4}, {10, 3}, {12, 8}, {19, 0}, {21, 6}};
+      ClockVector cv3{{22, 6}, {100, 3}};
+      ClockVector maxCV = ClockVector::max(cv1, cv2);
+      maxCV             = ClockVector::max(maxCV, cv3);
+
+      REQUIRE(maxCV.size() == 9);
+      REQUIRE(maxCV.get(1).has_value());
+      REQUIRE(maxCV.get(1).value() == 2);
+      REQUIRE(maxCV[1] == 2);
+
+      REQUIRE(maxCV.get(2).has_value());
+      REQUIRE(maxCV.get(2).value() == 4);
+      REQUIRE(maxCV[2] == 4);
+
+      REQUIRE(maxCV.get(4).has_value());
+      REQUIRE(maxCV.get(4).value() == 41);
+      REQUIRE(maxCV[4] == 41);
+
+      REQUIRE(maxCV.get(10).has_value());
+      REQUIRE(maxCV.get(10).value() == 3);
+      REQUIRE(maxCV[10] == 3);
+
+      REQUIRE(maxCV.get(12).has_value());
+      REQUIRE(maxCV.get(12).value() == 8);
+      REQUIRE(maxCV[12] == 8);
+
+      REQUIRE(maxCV.get(19).has_value());
+      REQUIRE(maxCV.get(19).value() == 0);
+      REQUIRE(maxCV[19] == 0);
+
+      REQUIRE(maxCV.get(21).has_value());
+      REQUIRE(maxCV.get(21).value() == 6);
+      REQUIRE(maxCV[21] == 6);
+
+      REQUIRE(maxCV.get(22).has_value());
+      REQUIRE(maxCV.get(22).value() == 6);
+      REQUIRE(maxCV[22] == 6);
+
+      REQUIRE(maxCV.get(100).has_value());
+      REQUIRE(maxCV.get(100).value() == 3);
+      REQUIRE(maxCV[100] == 3);
+    }
+  }
+}
\ No newline at end of file
index 625ce5e..e516702 100644 (file)
@@ -132,6 +132,7 @@ set(UNIT_TESTS  src/xbt/unit-tests_main.cpp
 
 set(MC_UNIT_TESTS src/mc/sosp/Snapshot_test.cpp 
                   src/mc/sosp/PageStore_test.cpp
+                  src/mc/explo/odpor/ClockVector_test.cpp
                   src/mc/explo/odpor/Execution_test.cpp
                   src/mc/explo/udpor/EventSet_test.cpp
                   src/mc/explo/udpor/Unfolding_test.cpp