From: Maxwell Pirtle Date: Mon, 15 May 2023 07:04:11 +0000 (+0200) Subject: Add unit tests for ClockVector X-Git-Tag: v3.34~68^2~46 X-Git-Url: http://info.iut-bm.univ-fcomte.fr/pub/gitweb/simgrid.git/commitdiff_plain/0bf32d746b6101fb9a539128c7db74abc2ef0b85 Add unit tests for ClockVector --- diff --git a/MANIFEST.in b/MANIFEST.in index 718c24d88b..ec8c8d1b1a 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -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 diff --git a/src/mc/api/ClockVector.hpp b/src/mc/api/ClockVector.hpp index d4dfa377cd..93900358c8 100644 --- a/src/mc/api/ClockVector.hpp +++ b/src/mc/api/ClockVector.hpp @@ -9,6 +9,7 @@ #include "simgrid/forward.h" #include +#include #include #include @@ -28,6 +29,7 @@ public: ClockVector(const ClockVector&) = default; ClockVector& operator=(ClockVector const&) = default; ClockVector(ClockVector&&) = default; + ClockVector(std::initializer_list> 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 index 0000000000..da266b03a9 --- /dev/null +++ b/src/mc/explo/odpor/ClockVector_test.cpp @@ -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 diff --git a/tools/cmake/Tests.cmake b/tools/cmake/Tests.cmake index 625ce5e8bd..e5167026ba 100644 --- a/tools/cmake/Tests.cmake +++ b/tools/cmake/Tests.cmake @@ -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