diff --git a/Tests/AK/TestOptional.cpp b/Tests/AK/TestOptional.cpp index 427046eab8..485a37f248 100644 --- a/Tests/AK/TestOptional.cpp +++ b/Tests/AK/TestOptional.cpp @@ -1,5 +1,6 @@ /* * Copyright (c) 2018-2020, Andreas Kling + * Copyright (c) 2021, Daniel Bertalan * * SPDX-License-Identifier: BSD-2-Clause */ @@ -96,3 +97,95 @@ TEST_CASE(comparison_with_numeric_types) EXPECT_EQ(opt1, 7u); EXPECT_NE(opt1, -2); } + +TEST_CASE(test_copy_ctor_and_dtor_called) +{ +#ifdef AK_HAVE_CONDITIONALLY_TRIVIAL + static_assert(IsTriviallyDestructible>); + static_assert(IsTriviallyCopyable>); + static_assert(IsTriviallyCopyConstructible>); + static_assert(IsTriviallyCopyAssignable>); + // These can't be trivial as we have to clear the original object. + static_assert(!IsTriviallyMoveConstructible>); + static_assert(!IsTriviallyMoveAssignable>); +#endif + + struct DestructionChecker { + explicit DestructionChecker(bool& was_destroyed) + : m_was_destroyed(was_destroyed) + { + } + + ~DestructionChecker() + { + m_was_destroyed = true; + } + bool& m_was_destroyed; + }; + + static_assert(!IsTriviallyDestructible>); + + bool was_destroyed = false; + { + Optional test_optional = DestructionChecker { was_destroyed }; + } + EXPECT(was_destroyed); + + struct CopyChecker { + explicit CopyChecker(bool& was_copy_constructed) + : m_was_copy_constructed(was_copy_constructed) + { + } + + CopyChecker(const CopyChecker& other) + : m_was_copy_constructed(other.m_was_copy_constructed) + { + m_was_copy_constructed = true; + } + + bool& m_was_copy_constructed; + }; + + static_assert(IsCopyConstructible>); + static_assert(!IsTriviallyCopyConstructible>); + + bool was_copy_constructed = false; + Optional copy1 = CopyChecker { was_copy_constructed }; + Optional copy2 = copy1; + EXPECT(was_copy_constructed); + + struct MoveChecker { + explicit MoveChecker(bool& was_move_constructed) + : m_was_move_constructed(was_move_constructed) + { + } + + MoveChecker(const MoveChecker& other) + : m_was_move_constructed(other.m_was_move_constructed) + { + EXPECT(false); + }; + + MoveChecker(MoveChecker&& other) + : m_was_move_constructed(other.m_was_move_constructed) + { + m_was_move_constructed = true; + }; + + bool& m_was_move_constructed; + }; + static_assert(IsMoveConstructible>); + static_assert(!IsTriviallyMoveConstructible>); + + bool was_moved = false; + Optional move1 = MoveChecker { was_moved }; + Optional move2 = move(move1); + EXPECT(was_moved); + +#ifdef AK_HAVE_CONDITIONALLY_TRIVIAL + struct NonDestructible { + ~NonDestructible() = delete; + }; + static_assert(!IsDestructible>); +#endif +}