diff --git a/ChangeLog.md b/ChangeLog.md index 2f8c7a77f..3764af281 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -79,6 +79,7 @@ Nazara Engine: - Fixed ConvexCollider3D::GetType returning Compound instead of ConvexHull. - Dual-stack sockets are now supported (by using NetProtocol_Any at creation/opening) - Fixed IPv6 addresses not being correctly encoded/decoded from the socket API. +- Fix copy and move semantic on HandledObject and ObjectHandle Nazara Development Kit: - Added ImageWidget (#139) diff --git a/include/Nazara/Core/HandledObject.inl b/include/Nazara/Core/HandledObject.inl index 2b0bb3f23..9a7ebcc41 100644 --- a/include/Nazara/Core/HandledObject.inl +++ b/include/Nazara/Core/HandledObject.inl @@ -86,9 +86,12 @@ namespace Nz template HandledObject& HandledObject::operator=(HandledObject&& object) { - m_handles = std::move(object.m_handles); - for (ObjectHandle* handle : m_handles) + m_handles.reserve(m_handles.size() + object.m_handles.size()); + for (ObjectHandle* handle : object.m_handles) + { + m_handles.push_back(handle); handle->OnObjectMoved(static_cast(this)); + } return *this; } diff --git a/tests/Engine/Core/ObjectHandle.cpp b/tests/Engine/Core/ObjectHandle.cpp new file mode 100644 index 000000000..8fd8099fd --- /dev/null +++ b/tests/Engine/Core/ObjectHandle.cpp @@ -0,0 +1,141 @@ +#include +#include +#include + +class Test; + +using TestHandle = Nz::ObjectHandle; + +struct Test : public Nz::HandledObject +{ + Test(int value) : + i(value) + { + } + + int i; +}; + +SCENARIO("Handle", "[CORE][HandledObject][ObjectHandle]") +{ + GIVEN("One test with two handles") + { + int defaultValue = 1; + Test test(defaultValue); + + Nz::ObjectHandle handle1 = test.CreateHandle(); + Nz::ObjectHandle handle2 = test.CreateHandle(); + + WHEN("We modify from one") + { + const int newI = 2; + handle1->i = newI; + + THEN("The other one should also be modified") + { + REQUIRE(handle2->i == newI); + } + } + + WHEN("We copy construct") + { + Test other(test); + Nz::ObjectHandle otherHandle = other.CreateHandle(); + + THEN("Handles should point to 1") + { + CHECK(handle1->i == defaultValue); + CHECK(handle2->i == defaultValue); + CHECK(otherHandle->i == defaultValue); + CHECK(handle2.GetObject() == &test); + CHECK(otherHandle.GetObject() == &other); + } + } + + WHEN("We move construct") + { + Test other(std::move(test)); + Nz::ObjectHandle otherHandle = other.CreateHandle(); + + THEN("Handles should point to 1") + { + CHECK(handle1->i == defaultValue); + CHECK(handle2->i == defaultValue); + CHECK(otherHandle->i == defaultValue); + CHECK(handle1.GetObject() == &other); + } + } + + WHEN("We copy assign") + { + int copyValue = 3; + Test other(copyValue); + Nz::ObjectHandle otherHandle = other.CreateHandle(); + test = other; + + THEN("Handles should point to 3") + { + CHECK(handle1->i == copyValue); + CHECK(handle2->i == copyValue); + CHECK(otherHandle->i == copyValue); + CHECK(handle1.GetObject() == &test); + CHECK(otherHandle.GetObject() == &other); + } + } + + WHEN("We move assign") + { + int moveValue = 4; + Test other(moveValue); + Nz::ObjectHandle otherHandle = other.CreateHandle(); + test = std::move(other); + + THEN("Handles should point to 4") + { + CHECK(handle1->i == moveValue); + CHECK(handle2->i == moveValue); + CHECK(otherHandle->i == moveValue); + CHECK(handle1.GetObject() == &test); + CHECK(otherHandle.GetObject() == &test); + } + } + } + + GIVEN("One handle pointing to a default test") + { + Test test(1); + Nz::ObjectHandle invalidHandle(&test); + + WHEN("We bind it to a HandledObject which is going to die") + { + { + Test dyingTest(5); + invalidHandle.Reset(&dyingTest); + } + + THEN("It should not be valid") + { + REQUIRE(!invalidHandle.IsValid()); + } + } + } + + GIVEN("Two handle pointing to two different tests") + { + Test test1(1); + Nz::ObjectHandle test1Handle = test1.CreateHandle(); + Test test2(2); + Nz::ObjectHandle test2Handle = test2.CreateHandle(); + + WHEN("We swap their content") + { + test1Handle.Swap(test2Handle); + + THEN("They should be pointing to the correct one") + { + CHECK(test1Handle.GetObject() == &test2); + CHECK(test2Handle.GetObject() == &test1); + } + } + } +}