123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271 |
- /*
- * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
- * Copyright (c) 2021, Daniel Bertalan <dani@danielbertalan.dev>
- *
- * SPDX-License-Identifier: BSD-2-Clause
- */
- #include <LibTest/TestCase.h>
- #include <AK/Optional.h>
- #include <AK/String.h>
- #include <AK/Vector.h>
- TEST_CASE(basic_optional)
- {
- Optional<int> x;
- EXPECT_EQ(x.has_value(), false);
- x = 3;
- EXPECT_EQ(x.has_value(), true);
- EXPECT_EQ(x.value(), 3);
- }
- TEST_CASE(move_optional)
- {
- Optional<int> x;
- EXPECT_EQ(x.has_value(), false);
- x = 3;
- EXPECT_EQ(x.has_value(), true);
- EXPECT_EQ(x.value(), 3);
- Optional<int> y;
- y = move(x);
- EXPECT_EQ(y.has_value(), true);
- EXPECT_EQ(y.value(), 3);
- EXPECT_EQ(x.has_value(), false);
- }
- TEST_CASE(optional_rvalue_ref_qualified_getters)
- {
- struct DontCopyMe {
- DontCopyMe() { }
- ~DontCopyMe() = default;
- DontCopyMe(DontCopyMe&&) = default;
- DontCopyMe& operator=(DontCopyMe&&) = default;
- DontCopyMe(DontCopyMe const&) = delete;
- DontCopyMe& operator=(DontCopyMe const&) = delete;
- int x { 13 };
- };
- auto make_an_optional = []() -> Optional<DontCopyMe> {
- return DontCopyMe {};
- };
- EXPECT_EQ(make_an_optional().value().x, 13);
- EXPECT_EQ(make_an_optional().value_or(DontCopyMe {}).x, 13);
- }
- TEST_CASE(optional_leak_1)
- {
- struct Structure {
- Optional<String> str;
- };
- // This used to leak, it does not anymore.
- Vector<Structure> vec;
- vec.append({ "foo" });
- EXPECT_EQ(vec[0].str.has_value(), true);
- EXPECT_EQ(vec[0].str.value(), "foo");
- }
- TEST_CASE(short_notation)
- {
- Optional<StringView> value = "foo";
- EXPECT_EQ(value->length(), 3u);
- EXPECT_EQ(*value, "foo");
- }
- TEST_CASE(comparison_without_values)
- {
- Optional<StringView> opt0;
- Optional<StringView> opt1;
- Optional<String> opt2;
- EXPECT_EQ(opt0, opt1);
- EXPECT_EQ(opt0, opt2);
- }
- TEST_CASE(comparison_with_values)
- {
- Optional<StringView> opt0;
- Optional<StringView> opt1 = "foo";
- Optional<String> opt2 = "foo";
- Optional<StringView> opt3 = "bar";
- EXPECT_NE(opt0, opt1);
- EXPECT_EQ(opt1, opt2);
- EXPECT_NE(opt1, opt3);
- }
- TEST_CASE(comparison_to_underlying_types)
- {
- Optional<String> opt0;
- EXPECT_NE(opt0, String());
- EXPECT_NE(opt0, "foo");
- Optional<StringView> opt1 = "foo";
- EXPECT_EQ(opt1, "foo");
- EXPECT_NE(opt1, "bar");
- EXPECT_EQ(opt1, String("foo"));
- }
- TEST_CASE(comparison_with_numeric_types)
- {
- Optional<u8> opt0;
- EXPECT_NE(opt0, 0);
- Optional<u8> opt1 = 7;
- EXPECT_EQ(opt1, 7);
- EXPECT_EQ(opt1, 7.0);
- EXPECT_EQ(opt1, 7u);
- EXPECT_NE(opt1, -2);
- }
- TEST_CASE(test_copy_ctor_and_dtor_called)
- {
- #ifdef AK_HAVE_CONDITIONALLY_TRIVIAL
- static_assert(IsTriviallyDestructible<Optional<u8>>);
- static_assert(IsTriviallyCopyable<Optional<u8>>);
- static_assert(IsTriviallyCopyConstructible<Optional<u8>>);
- static_assert(IsTriviallyCopyAssignable<Optional<u8>>);
- // These can't be trivial as we have to clear the original object.
- static_assert(!IsTriviallyMoveConstructible<Optional<u8>>);
- static_assert(!IsTriviallyMoveAssignable<Optional<u8>>);
- #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<Optional<DestructionChecker>>);
- bool was_destroyed = false;
- {
- Optional<DestructionChecker> test_optional = DestructionChecker { was_destroyed };
- }
- EXPECT(was_destroyed);
- struct CopyChecker {
- explicit CopyChecker(bool& was_copy_constructed)
- : m_was_copy_constructed(was_copy_constructed)
- {
- }
- CopyChecker(CopyChecker const& other)
- : m_was_copy_constructed(other.m_was_copy_constructed)
- {
- m_was_copy_constructed = true;
- }
- bool& m_was_copy_constructed;
- };
- static_assert(IsCopyConstructible<Optional<CopyChecker>>);
- static_assert(!IsTriviallyCopyConstructible<Optional<CopyChecker>>);
- bool was_copy_constructed = false;
- Optional<CopyChecker> copy1 = CopyChecker { was_copy_constructed };
- Optional<CopyChecker> copy2 = copy1;
- EXPECT(was_copy_constructed);
- struct MoveChecker {
- explicit MoveChecker(bool& was_move_constructed)
- : m_was_move_constructed(was_move_constructed)
- {
- }
- MoveChecker(MoveChecker const& 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<Optional<MoveChecker>>);
- static_assert(!IsTriviallyMoveConstructible<Optional<MoveChecker>>);
- bool was_moved = false;
- Optional<MoveChecker> move1 = MoveChecker { was_moved };
- Optional<MoveChecker> move2 = move(move1);
- EXPECT(was_moved);
- #ifdef AK_HAVE_CONDITIONALLY_TRIVIAL
- struct NonDestructible {
- ~NonDestructible() = delete;
- };
- static_assert(!IsDestructible<Optional<NonDestructible>>);
- #endif
- }
- TEST_CASE(basic_optional_reference)
- {
- Optional<int&> x;
- EXPECT_EQ(x.has_value(), false);
- int a = 3;
- x = a;
- EXPECT_EQ(x.has_value(), true);
- EXPECT_EQ(x.value(), 3);
- EXPECT_EQ(&x.value(), &a);
- Optional<int const&> y;
- EXPECT_EQ(y.has_value(), false);
- int b = 3;
- y = b;
- EXPECT_EQ(y.has_value(), true);
- EXPECT_EQ(y.value(), 3);
- EXPECT_EQ(&y.value(), &b);
- static_assert(IsConst<RemoveReference<decltype(y.value())>>);
- }
- TEST_CASE(move_optional_reference)
- {
- Optional<int&> x;
- EXPECT_EQ(x.has_value(), false);
- int b = 3;
- x = b;
- EXPECT_EQ(x.has_value(), true);
- EXPECT_EQ(x.value(), 3);
- Optional<int&> y;
- y = move(x);
- EXPECT_EQ(y.has_value(), true);
- EXPECT_EQ(y.value(), 3);
- EXPECT_EQ(x.has_value(), false);
- }
- TEST_CASE(short_notation_reference)
- {
- StringView test = "foo";
- Optional<StringView&> value = test;
- EXPECT_EQ(value->length(), 3u);
- EXPECT_EQ(*value, "foo");
- }
- TEST_CASE(comparison_reference)
- {
- StringView test = "foo";
- Optional<StringView&> opt0;
- Optional<StringView const&> opt1 = test;
- Optional<String> opt2 = "foo";
- Optional<StringView> opt3 = "bar";
- EXPECT_NE(opt0, opt1);
- EXPECT_EQ(opt1, opt2);
- EXPECT_NE(opt1, opt3);
- }
|