/* * Copyright (c) 2021, Ali Mohammad Pur * * SPDX-License-Identifier: BSD-2-Clause */ #include #include TEST_CASE(basic) { Variant the_value { 42 }; EXPECT(the_value.has()); EXPECT_EQ(the_value.get(), 42); the_value = String("42"); EXPECT(the_value.has()); EXPECT_EQ(the_value.get(), "42"); } TEST_CASE(visit) { bool correct = false; Variant the_value { 42.0f }; the_value.visit( [&](const int&) { correct = false; }, [&](const String&) { correct = false; }, [&](const float&) { correct = true; }); EXPECT(correct); } TEST_CASE(destructor) { struct DestructionChecker { explicit DestructionChecker(bool& was_destroyed) : m_was_destroyed(was_destroyed) { } ~DestructionChecker() { m_was_destroyed = true; } bool& m_was_destroyed; }; bool was_destroyed = false; { Variant test_variant { DestructionChecker { was_destroyed } }; } EXPECT(was_destroyed); } TEST_CASE(move_moves) { struct NoCopy { AK_MAKE_NONCOPYABLE(NoCopy); public: NoCopy() = default; NoCopy(NoCopy&&) = default; }; Variant first_variant { 42 }; // Should not fail to compile first_variant = NoCopy {}; Variant second_variant = move(first_variant); EXPECT(second_variant.has()); } TEST_CASE(downcast) { Variant one_integer_to_rule_them_all { static_cast(42) }; auto fake_integer = one_integer_to_rule_them_all.downcast(); EXPECT(fake_integer.has()); EXPECT(one_integer_to_rule_them_all.has()); EXPECT_EQ(fake_integer.get(), 42); EXPECT_EQ(one_integer_to_rule_them_all.get(), 42); fake_integer = static_cast(60); one_integer_to_rule_them_all = fake_integer.downcast().downcast().downcast(); EXPECT(fake_integer.has()); EXPECT(one_integer_to_rule_them_all.has()); EXPECT_EQ(fake_integer.get(), 60); EXPECT_EQ(one_integer_to_rule_them_all.get(), 60); } TEST_CASE(moved_from_state) { // Note: This test requires that Vector's moved-from state be consistent // it need not be in a specific state (though as it is currently implemented, // a moved-from vector is the same as a newly-created vector) // This test does not make assumptions about the state itself, but rather that // it remains consistent when done on different instances. // Should this assumption be broken, we should probably switch to defining a local // class that has fixed semantics, but I doubt the moved-from state of Vector will // change any time soon :P Vector bunch_of_values { 1, 2, 3, 4, 5, 6, 7, 8 }; Variant, Empty> optionally_a_bunch_of_values { Vector { 1, 2, 3, 4, 5, 6, 7, 8 } }; { [[maybe_unused]] auto devnull_0 = move(bunch_of_values); [[maybe_unused]] auto devnull_1 = move(optionally_a_bunch_of_values); } // The moved-from state should be the same in both cases, and the variant should still contain a moved-from vector. // Note: Use after move is intentional. EXPECT(optionally_a_bunch_of_values.has>()); auto same_contents = __builtin_memcmp(&bunch_of_values, &optionally_a_bunch_of_values.get>(), sizeof(bunch_of_values)) == 0; EXPECT(same_contents); }