diff --git a/src/test/util_tests.cpp b/src/test/util_tests.cpp index 3995a3c73..02303d0f6 100644 --- a/src/test/util_tests.cpp +++ b/src/test/util_tests.cpp @@ -13,6 +13,7 @@ #include #include #include +#include #include #include @@ -1714,4 +1715,109 @@ BOOST_AUTO_TEST_CASE(test_LogEscapeMessage) BOOST_CHECK_EQUAL(BCLog::LogEscapeMessage(NUL), R"(O\x00O)"); } +namespace { + +struct Tracker +{ + //! Points to the original object (possibly itself) we moved/copied from + const Tracker* origin; + //! How many copies where involved between the original object and this one (moves are not counted) + int copies; + + Tracker() noexcept : origin(this), copies(0) {} + Tracker(const Tracker& t) noexcept : origin(t.origin), copies(t.copies + 1) {} + Tracker(Tracker&& t) noexcept : origin(t.origin), copies(t.copies) {} + Tracker& operator=(const Tracker& t) noexcept + { + origin = t.origin; + copies = t.copies + 1; + return *this; + } + Tracker& operator=(Tracker&& t) noexcept + { + origin = t.origin; + copies = t.copies; + return *this; + } +}; + +} + +BOOST_AUTO_TEST_CASE(test_tracked_vector) +{ + Tracker t1; + Tracker t2; + Tracker t3; + + BOOST_CHECK(t1.origin == &t1); + BOOST_CHECK(t2.origin == &t2); + BOOST_CHECK(t3.origin == &t3); + + auto v1 = Vector(t1); + BOOST_CHECK_EQUAL(v1.size(), 1); + BOOST_CHECK(v1[0].origin == &t1); + BOOST_CHECK_EQUAL(v1[0].copies, 1); + + auto v2 = Vector(std::move(t2)); + BOOST_CHECK_EQUAL(v2.size(), 1); + BOOST_CHECK(v2[0].origin == &t2); + BOOST_CHECK_EQUAL(v2[0].copies, 0); + + auto v3 = Vector(t1, std::move(t2)); + BOOST_CHECK_EQUAL(v3.size(), 2); + BOOST_CHECK(v3[0].origin == &t1); + BOOST_CHECK(v3[1].origin == &t2); + BOOST_CHECK_EQUAL(v3[0].copies, 1); + BOOST_CHECK_EQUAL(v3[1].copies, 0); + + auto v4 = Vector(std::move(v3[0]), v3[1], std::move(t3)); + BOOST_CHECK_EQUAL(v4.size(), 3); + BOOST_CHECK(v4[0].origin == &t1); + BOOST_CHECK(v4[1].origin == &t2); + BOOST_CHECK(v4[2].origin == &t3); + BOOST_CHECK_EQUAL(v4[0].copies, 1); + BOOST_CHECK_EQUAL(v4[1].copies, 1); + BOOST_CHECK_EQUAL(v4[2].copies, 0); + + auto v5 = Cat(v1, v4); + BOOST_CHECK_EQUAL(v5.size(), 4); + BOOST_CHECK(v5[0].origin == &t1); + BOOST_CHECK(v5[1].origin == &t1); + BOOST_CHECK(v5[2].origin == &t2); + BOOST_CHECK(v5[3].origin == &t3); + BOOST_CHECK_EQUAL(v5[0].copies, 2); + BOOST_CHECK_EQUAL(v5[1].copies, 2); + BOOST_CHECK_EQUAL(v5[2].copies, 2); + BOOST_CHECK_EQUAL(v5[3].copies, 1); + + auto v6 = Cat(std::move(v1), v3); + BOOST_CHECK_EQUAL(v6.size(), 3); + BOOST_CHECK(v6[0].origin == &t1); + BOOST_CHECK(v6[1].origin == &t1); + BOOST_CHECK(v6[2].origin == &t2); + BOOST_CHECK_EQUAL(v6[0].copies, 1); + BOOST_CHECK_EQUAL(v6[1].copies, 2); + BOOST_CHECK_EQUAL(v6[2].copies, 1); + + auto v7 = Cat(v2, std::move(v4)); + BOOST_CHECK_EQUAL(v7.size(), 4); + BOOST_CHECK(v7[0].origin == &t2); + BOOST_CHECK(v7[1].origin == &t1); + BOOST_CHECK(v7[2].origin == &t2); + BOOST_CHECK(v7[3].origin == &t3); + BOOST_CHECK_EQUAL(v7[0].copies, 1); + BOOST_CHECK_EQUAL(v7[1].copies, 1); + BOOST_CHECK_EQUAL(v7[2].copies, 1); + BOOST_CHECK_EQUAL(v7[3].copies, 0); + + auto v8 = Cat(std::move(v2), std::move(v3)); + BOOST_CHECK_EQUAL(v8.size(), 3); + BOOST_CHECK(v8[0].origin == &t2); + BOOST_CHECK(v8[1].origin == &t1); + BOOST_CHECK(v8[2].origin == &t2); + BOOST_CHECK_EQUAL(v8[0].copies, 0); + BOOST_CHECK_EQUAL(v8[1].copies, 1); + BOOST_CHECK_EQUAL(v8[2].copies, 0); +} + BOOST_AUTO_TEST_SUITE_END()