Skip to content

Commit 21f6b0a

Browse files
committed
Add tests for mesh ownership accessors
1 parent 4bf71cd commit 21f6b0a

File tree

3 files changed

+157
-0
lines changed

3 files changed

+157
-0
lines changed

tests/unit/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ dart_add_test(
7373
"unit" UNIT_dynamics_BodyNodePotentialEnergy dynamics/test_BodyNodePotentialEnergy.cpp)
7474
dart_add_test("unit" UNIT_dynamics_ShapeNodeInertia dynamics/test_ShapeNodeInertia.cpp)
7575
dart_add_test("unit" UNIT_dynamics_SkeletonClone dynamics/test_SkeletonClone.cpp)
76+
dart_add_test("unit" UNIT_dynamics_SkeletonAccessors dynamics/test_SkeletonAccessors.cpp)
7677
dart_add_test("unit" UNIT_dynamics_Noexcept dynamics/test_Noexcept.cpp)
7778
dart_add_test(
7879
"unit" UNIT_dynamics_BodyNodeCollisionSignals dynamics/test_BodyNodeCollisionSignals.cpp)

tests/unit/dynamics/test_MeshShape.cpp

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
#include "dart/common/LocalResourceRetriever.hpp"
22
#include "dart/common/Uri.hpp"
33
#include "dart/config.hpp"
4+
#include "dart/dynamics/ArrowShape.hpp"
45
#include "dart/dynamics/AssimpInputResourceAdaptor.hpp"
56
#include "dart/dynamics/MeshShape.hpp"
67

8+
#include <Eigen/Core>
79
#include <assimp/cimport.h>
810
#include <assimp/config.h>
911
#include <assimp/postprocess.h>
@@ -54,6 +56,28 @@ class AliasUriResourceRetriever final : public common::ResourceRetriever
5456
common::LocalResourceRetrieverPtr mDelegate;
5557
};
5658

59+
class RecordingRetriever final : public common::ResourceRetriever
60+
{
61+
public:
62+
bool exists(const common::Uri&) override
63+
{
64+
return true;
65+
}
66+
67+
common::ResourcePtr retrieve(const common::Uri&) override
68+
{
69+
return nullptr;
70+
}
71+
72+
std::string getFilePath(const common::Uri& uri) override
73+
{
74+
lastUri = uri.toString();
75+
return "/virtual/path/from/retriever";
76+
}
77+
78+
std::string lastUri;
79+
};
80+
5781
const aiScene* loadMeshWithOverrides(
5882
const std::string& uri,
5983
const common::ResourceRetrieverPtr& retriever,
@@ -246,3 +270,64 @@ TEST(MeshShapeTest, RespectsCustomMeshDeleter)
246270

247271
EXPECT_EQ(deleted.load(), 1);
248272
}
273+
274+
TEST(MeshShapeTest, TracksOwnershipAndUriMetadata)
275+
{
276+
auto retriever = std::make_shared<RecordingRetriever>();
277+
const common::Uri fileUri
278+
= common::Uri::createFromStringOrPath("/tmp/manual-mesh.dae");
279+
280+
auto* manualScene = new aiScene;
281+
dynamics::MeshShape shape(
282+
Eigen::Vector3d::Ones(),
283+
manualScene,
284+
fileUri,
285+
retriever,
286+
dynamics::MeshShape::MeshOwnership::Manual);
287+
EXPECT_EQ(shape.getMesh(), manualScene);
288+
EXPECT_EQ(shape.getMeshPath(), fileUri.getFilesystemPath());
289+
EXPECT_EQ(shape.getMeshUri(), fileUri.toString());
290+
291+
const common::Uri retrieverUri("package://example/mesh.dae");
292+
auto* retrieverScene = new aiScene;
293+
shape.setMesh(
294+
retrieverScene,
295+
dynamics::MeshShape::MeshOwnership::Manual,
296+
retrieverUri,
297+
retriever);
298+
EXPECT_EQ(retriever->lastUri, retrieverUri.toString());
299+
EXPECT_EQ(shape.getMeshPath(), "/virtual/path/from/retriever");
300+
EXPECT_EQ(shape.getMesh(), retrieverScene);
301+
302+
// No-op when the mesh pointer and ownership are unchanged.
303+
shape.setMesh(
304+
shape.getMesh(),
305+
dynamics::MeshShape::MeshOwnership::Manual,
306+
retrieverUri,
307+
retriever);
308+
309+
// Clearing the mesh resets related metadata.
310+
shape.setMesh(
311+
nullptr,
312+
dynamics::MeshShape::MeshOwnership::Manual,
313+
common::Uri(),
314+
nullptr);
315+
EXPECT_EQ(shape.getMesh(), nullptr);
316+
EXPECT_TRUE(shape.getMeshPath().empty());
317+
EXPECT_TRUE(shape.getMeshUri().empty());
318+
}
319+
320+
TEST(ArrowShapeTest, CloneUsesMeshOwnershipSemantics)
321+
{
322+
dynamics::ArrowShape arrow(
323+
Eigen::Vector3d::Zero(),
324+
Eigen::Vector3d::UnitX(),
325+
dynamics::ArrowShape::Properties(),
326+
Eigen::Vector4d::Ones(),
327+
4);
328+
329+
auto cloned = std::dynamic_pointer_cast<dynamics::ArrowShape>(arrow.clone());
330+
ASSERT_TRUE(cloned);
331+
ASSERT_NE(cloned->getMesh(), nullptr);
332+
EXPECT_NE(cloned->getMesh(), arrow.getMesh());
333+
}
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
/*
2+
* Copyright (c) 2011-2025, The DART development contributors
3+
* All rights reserved.
4+
*
5+
* The list of contributors can be found at:
6+
* https://github.com/dartsim/dart/blob/main/LICENSE
7+
*
8+
* This file is provided under the following "BSD-style" License:
9+
* Redistribution and use in source and binary forms, with or
10+
* without modification, are permitted provided that the following
11+
* conditions are met:
12+
* * Redistributions of source code must retain the above copyright
13+
* notice, this list of conditions and the following disclaimer.
14+
* * Redistributions in binary form must reproduce the above
15+
* copyright notice, this list of conditions and the following
16+
* disclaimer in the documentation and/or other materials provided
17+
* with the distribution.
18+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
19+
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
20+
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
21+
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22+
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
23+
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24+
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25+
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
26+
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
27+
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28+
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
29+
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30+
* POSSIBILITY OF SUCH DAMAGE.
31+
*/
32+
33+
#include <dart/dynamics/FreeJoint.hpp>
34+
#include <dart/dynamics/Group.hpp>
35+
#include <dart/dynamics/Skeleton.hpp>
36+
37+
#include <dart/common/Deprecated.hpp>
38+
39+
#include <gtest/gtest.h>
40+
41+
using namespace dart::dynamics;
42+
43+
//==============================================================================
44+
TEST(SkeletonAccessors, ReturnsMutableBodyNodeVector)
45+
{
46+
auto skeleton = Skeleton::create("skeleton");
47+
auto pair = skeleton->createJointAndBodyNodePair<FreeJoint>();
48+
auto* body = pair.second;
49+
50+
DART_SUPPRESS_DEPRECATED_BEGIN
51+
auto& nodes = skeleton->getBodyNodes();
52+
DART_SUPPRESS_DEPRECATED_END
53+
ASSERT_EQ(nodes.size(), 1u);
54+
EXPECT_EQ(nodes.front(), body);
55+
}
56+
57+
//==============================================================================
58+
TEST(ReferentialSkeletonAccessors, ReturnsMutableBodyNodeVector)
59+
{
60+
auto skeleton = Skeleton::create("skeleton");
61+
auto pair = skeleton->createJointAndBodyNodePair<FreeJoint>();
62+
63+
auto group = Group::create("group");
64+
ASSERT_TRUE(group->addComponent(pair.second));
65+
66+
DART_SUPPRESS_DEPRECATED_BEGIN
67+
auto& nodes = group->getBodyNodes();
68+
DART_SUPPRESS_DEPRECATED_END
69+
ASSERT_EQ(nodes.size(), 1u);
70+
EXPECT_EQ(nodes.front(), pair.second);
71+
}

0 commit comments

Comments
 (0)