diff --git a/src/Unittests/unittests_propertymanager.cc b/src/Unittests/unittests_propertymanager.cc index 24035186..5ee75c62 100644 --- a/src/Unittests/unittests_propertymanager.cc +++ b/src/Unittests/unittests_propertymanager.cc @@ -26,7 +26,7 @@ class OpenMeshPropertyManager : public OpenMeshBase { /* * ==================================================================== - * Define tests below + * General Tests * ==================================================================== */ @@ -92,11 +92,112 @@ TEST_F(OpenMeshPropertyManager, set_range_bool) { ASSERT_TRUE(pm_f_bool[*f_it]); } +/* + * ==================================================================== + * C++11 Specific Tests + * ==================================================================== + */ +#if _MSC_VER >= 1900 || __cplusplus > 199711L || defined(__GXX_EXPERIMENTAL_CXX0X__) +template +bool has_property(const Mesh& _mesh, const std::string& _name) { + auto dummy_handle = PropHandle{}; + return _mesh.get_property_handle(dummy_handle, _name); +} +/* + * Temporary property + */ +TEST_F(OpenMeshPropertyManager, cpp11_temp_property) { + using handle_type = OpenMesh::VPropHandleT; + const auto prop_name = "pm_v_test_property"; + ASSERT_FALSE(has_property(mesh_, prop_name)); + { + auto vprop = OpenMesh::makePropertyManagerFromNew(mesh_, prop_name); + static_cast(vprop); // Unused variable + ASSERT_TRUE(has_property(mesh_, prop_name)); + } + ASSERT_FALSE(has_property(mesh_, prop_name)); +} +/* + * Two temporary properties on a mesh using the same name and type. The second + * (inner) one shadows the first (outer) one instead of aliasing. + */ +TEST_F(OpenMeshPropertyManager, cpp11_temp_property_shadowing) { + auto vh = mesh_.add_vertex({0,0,0}); // Dummy vertex to attach properties to + using handle_type = OpenMesh::VPropHandleT; + const auto prop_name = "pm_v_test_property"; + + auto outer_prop = OpenMesh::makePropertyManagerFromNew(mesh_, prop_name); + outer_prop[vh] = 100; + ASSERT_EQ(100, outer_prop[vh]); + + { + // inner_prop uses same type and name as outer_prop + auto inner_prop = OpenMesh::makePropertyManagerFromNew(mesh_, prop_name); + inner_prop[vh] = 200; + ASSERT_EQ(200, inner_prop[vh]); + // End of scope: inner_prop is removed from mesh_ + } + + // Ensure outer_prop still exists and its data has not been overwritten by inner_prop + ASSERT_TRUE(has_property(mesh_, prop_name)); + ASSERT_EQ(100, outer_prop[vh]); +} + +/* + * In sequence: + * - add a persistent property to a mesh + * - retrieve an existing property of a mesh and modify it + * - obtain a non-owning property handle + * - attempt to obtain a non-owning handle to a non-existing property (throws) + */ +TEST_F(OpenMeshPropertyManager, cpp11_persistent_and_non_owning_properties) { + auto vh = mesh_.add_vertex({0,0,0}); // Dummy vertex to attach properties to + + using handle_type = OpenMesh::VPropHandleT; + const auto prop_name = "pm_v_test_property"; + + ASSERT_FALSE(has_property(mesh_, prop_name)); + + { + auto prop = OpenMesh::makePropertyManagerFromExistingOrNew(mesh_, prop_name); + prop[vh] = 100; + // End of scope, property persists + } + + ASSERT_TRUE(has_property(mesh_, prop_name)); + + { + // Since a property of the same name and type already exists, this refers to the existing property. + auto prop = OpenMesh::makePropertyManagerFromExistingOrNew(mesh_, prop_name); + ASSERT_EQ(100, prop[vh]); + prop[vh] = 200; + // End of scope, property persists + } + + ASSERT_TRUE(has_property(mesh_, prop_name)); + + { + // Acquire non-owning handle to the property, knowing it exists + auto prop = OpenMesh::makePropertyManagerFromExisting(mesh_, prop_name); + ASSERT_EQ(200, prop[vh]); + } + + ASSERT_TRUE(has_property(mesh_, prop_name)); + + { + // Attempt to acquire non-owning handle for a non-existing property + ASSERT_THROW(OpenMesh::makePropertyManagerFromExisting(mesh_, "wrong_property_name"), std::runtime_error); + } + + ASSERT_TRUE(has_property(mesh_, prop_name)); +} + +#endif }