-
Notifications
You must be signed in to change notification settings - Fork 35
Expand file tree
/
Copy pathtest_usd.py
More file actions
128 lines (102 loc) · 4.25 KB
/
test_usd.py
File metadata and controls
128 lines (102 loc) · 4.25 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
# Copyright (c) Meta Platforms, Inc. and affiliates.
#
# This source code is licensed under the MIT license found in the
# LICENSE file in the root directory of this source tree.
# pyre-strict
import os
import tempfile
import unittest
from typing import Optional
import pymomentum.geometry as pym_geometry
def load_tests(
loader: unittest.TestLoader,
standard_tests: unittest.TestSuite,
pattern: Optional[str],
) -> unittest.TestSuite:
"""
Custom test loader that excludes USD tests when USD is unavailable.
This prevents 'Skipping' notifications in CI by not discovering
the tests at all, rather than discovering and then skipping them.
Works with uses_legacy_listing = True (static listing handles
this correctly by finding 0 tests when load_tests returns empty).
"""
if not pym_geometry.is_usd_available():
return unittest.TestSuite()
return standard_tests
class TestUsd(unittest.TestCase):
def test_is_usd_available(self) -> None:
"""Test that USD support is available.
Note: USD is only available in ARVR BUCK builds, not fbcode builds.
In fbcode builds, USD is disabled to avoid binary size explosion
(OpenUSD is >4GB). This test only runs when USD is available;
otherwise load_tests() returns an empty suite.
"""
result = pym_geometry.is_usd_available()
self.assertIsInstance(result, bool)
# When this test runs, USD should be available
self.assertTrue(result)
def test_save_and_load_usd_character(self) -> None:
"""Test saving and reloading a USD character."""
# Create a test character
char = pym_geometry.create_test_character()
# Save to temporary file
with tempfile.NamedTemporaryFile(suffix=".usda", delete=False) as f:
temp_path = f.name
try:
pym_geometry.Character.save_usd(temp_path, char) # type: ignore[attr-defined]
# Verify file was created
self.assertTrue(os.path.exists(temp_path))
self.assertGreater(os.path.getsize(temp_path), 0)
# Reload and verify
loaded_char = pym_geometry.Character.load_usd(temp_path) # type: ignore[attr-defined]
# Verify skeleton joints match
self.assertEqual(
len(loaded_char.skeleton.joints),
len(char.skeleton.joints),
)
# Verify joint names match
for i, (loaded_joint, orig_joint) in enumerate(
zip(loaded_char.skeleton.joints, char.skeleton.joints)
):
self.assertEqual(
loaded_joint.name,
orig_joint.name,
f"Joint name mismatch at index {i}",
)
# Verify mesh vertices match
if char.mesh is not None:
self.assertIsNotNone(loaded_char.mesh)
self.assertEqual(
len(loaded_char.mesh.vertices),
len(char.mesh.vertices),
)
finally:
# Clean up
if os.path.exists(temp_path):
os.remove(temp_path)
def test_load_usd_from_bytes(self) -> None:
"""Test loading a USD character from bytes after saving."""
# Create a test character and save it
char = pym_geometry.create_test_character()
with tempfile.NamedTemporaryFile(suffix=".usda", delete=False) as f:
temp_path = f.name
try:
pym_geometry.Character.save_usd(temp_path, char) # type: ignore[attr-defined]
# Read file contents
with open(temp_path, "rb") as f:
usd_bytes = f.read()
# Load from bytes
loaded_char = pym_geometry.Character.load_usd_from_bytes(usd_bytes) # type: ignore[attr-defined]
# Verify skeleton was loaded
self.assertGreater(len(loaded_char.skeleton.joints), 0)
# Verify skeleton joints match
self.assertEqual(
len(loaded_char.skeleton.joints),
len(char.skeleton.joints),
)
finally:
# Clean up
if os.path.exists(temp_path):
os.remove(temp_path)
if __name__ == "__main__":
unittest.main()