Skip to content

Commit b6e248d

Browse files
committed
usdValidation: usdUtils: MissingReferenceValidator
created implementation, test, as well as associated entries in plugInfo.json & validatorTokens.h
1 parent be52dc6 commit b6e248d

File tree

4 files changed

+96
-10
lines changed

4 files changed

+96
-10
lines changed

pxr/usdValidation/usdUtilsValidators/plugInfo.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@
33
{
44
"Info": {
55
"Validators": {
6+
"MissingReferenceValidator": {
7+
"doc": "The composed USD stage should not contain any unresolvable asset dependencies (in every possible variation of the asset), when using the default asset resolver."
8+
},
69
"PackageEncapsulationValidator": {
710
"doc": "If the root layer is a package, then its recommended for the composed stage to not contain references to files outside the package. The package should be self-contained, warn if not.",
811
"keywords": [

pxr/usdValidation/usdUtilsValidators/testenv/testUsdUtilsValidators.cpp

Lines changed: 47 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
#include "pxr/base/arch/systemInfo.h"
99
#include "pxr/base/tf/pathUtils.h"
10+
#include "pxr/usd/usdGeom/xform.h"
1011
#include "pxr/usdValidation/usdUtilsValidators/validatorTokens.h"
1112
#include "pxr/usdValidation/usdValidation/error.h"
1213
#include "pxr/usdValidation/usdValidation/registry.h"
@@ -30,7 +31,7 @@ TestUsdUsdzValidators()
3031
UsdValidationValidatorMetadataVector metadata
3132
= registry.GetValidatorMetadataForPlugin(
3233
_tokens->usdUtilsValidatorsPlugin);
33-
TF_AXIOM(metadata.size() == 1);
34+
TF_AXIOM(metadata.size() == 2);
3435
// Since other validators can be registered with a UsdUtilsValidators
3536
// keyword, our validators registered in usd are a subset of the entire
3637
// set.
@@ -40,7 +41,8 @@ TestUsdUsdzValidators()
4041
}
4142

4243
const std::set<TfToken> expectedValidatorNames
43-
= { UsdUtilsValidatorNameTokens->packageEncapsulationValidator };
44+
= { UsdUtilsValidatorNameTokens->packageEncapsulationValidator,
45+
UsdUtilsValidatorNameTokens->missingReferenceValidator };
4446

4547
TF_AXIOM(validatorMetadataNameSet == expectedValidatorNames);
4648
}
@@ -113,11 +115,54 @@ TestPackageEncapsulationValidator()
113115
TF_AXIOM(errors.empty());
114116
}
115117

118+
static void
119+
TestMissingReferenceValidator()
120+
{
121+
UsdValidationRegistry& registry = UsdValidationRegistry::GetInstance();
122+
123+
// Verify the validator exists
124+
const UsdValidationValidator *validator = registry.GetOrLoadValidatorByName(
125+
UsdUtilsValidatorNameTokens->missingReferenceValidator);
126+
127+
TF_AXIOM(validator);
128+
129+
// Create stage with a reference that does not exist
130+
const UsdStageRefPtr& stage = UsdStage::CreateInMemory();
131+
132+
const UsdGeomXform xform = UsdGeomXform::Define(stage, SdfPath("/Xform"));
133+
const SdfReference badReference("doesNotExist.usd");
134+
xform.GetPrim().GetReferences().AddReference(badReference);
135+
136+
UsdValidationErrorVector errors = validator->Validate(stage);
137+
138+
// Verify both the layer & asset errors are present
139+
const TfToken expectedIdentifier =
140+
TfToken(
141+
"usdUtilsValidators:MissingReferenceValidator.UnresolvableDependency");
142+
TF_AXIOM(errors.size() == 1);
143+
TF_AXIOM(errors[0].GetIdentifier() == expectedIdentifier);
144+
TF_AXIOM(errors[0].GetType() == UsdValidationErrorType::Error);
145+
TF_AXIOM(errors[0].GetSites().size() == 1);
146+
TF_AXIOM(!errors[0].GetSites()[0].GetLayer().IsInvalid());
147+
const std::string expectedErrorMessage = "Found unresolvable external "
148+
"dependency 'doesNotExist.usd'.";
149+
TF_AXIOM(errors[0].GetMessage() == expectedErrorMessage);
150+
151+
// Remove the nonexistent reference, add an existing reference
152+
xform.GetPrim().GetReferences().RemoveReference(badReference);
153+
xform.GetPrim().GetReferences().AddReference("pass.usdz");
154+
errors = validator->Validate(stage);
155+
156+
// Verify the errors are gone
157+
TF_AXIOM(errors.empty());
158+
}
159+
116160
int
117161
main()
118162
{
119163
TestUsdUsdzValidators();
120164
TestPackageEncapsulationValidator();
165+
TestMissingReferenceValidator();
121166

122167
return EXIT_SUCCESS;
123168
}

pxr/usdValidation/usdUtilsValidators/validatorTokens.h

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -16,18 +16,21 @@
1616

1717
PXR_NAMESPACE_OPEN_SCOPE
1818

19-
#define USD_UTILS_VALIDATOR_NAME_TOKENS \
20-
((packageEncapsulationValidator, \
19+
#define USD_UTILS_VALIDATOR_NAME_TOKENS \
20+
((missingReferenceValidator, \
21+
"usdUtilsValidators:MissingReferenceValidator")) \
22+
((packageEncapsulationValidator, \
2123
"usdUtilsValidators:PackageEncapsulationValidator"))
2224

23-
#define USD_UTILS_VALIDATOR_KEYWORD_TOKENS \
24-
(UsdUtilsValidators) \
25+
#define USD_UTILS_VALIDATOR_KEYWORD_TOKENS \
26+
(UsdUtilsValidators) \
2527
(UsdzValidators)
2628

27-
#define USD_UTILS_VALIDATION_ERROR_NAME_TOKENS \
28-
((layerNotInPackage, "LayerNotInPackage")) \
29-
((assetNotInPackage, "AssetNotInPackage")) \
30-
((invalidLayerInPackage, "InvalidLayerInPackage"))
29+
#define USD_UTILS_VALIDATION_ERROR_NAME_TOKENS \
30+
((layerNotInPackage, "LayerNotInPackage")) \
31+
((assetNotInPackage, "AssetNotInPackage")) \
32+
((invalidLayerInPackage, "InvalidLayerInPackage")) \
33+
((unresolvableDependency, "UnresolvableDependency"))
3134

3235
///\def
3336
/// Tokens representing validator names. Note that for plugin provided

pxr/usdValidation/usdUtilsValidators/validators.cpp

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,9 +97,44 @@ _PackageEncapsulationValidator(const UsdStagePtr &usdStage)
9797
return errors;
9898
}
9999

100+
static
101+
UsdValidationErrorVector
102+
_MissingReferenceValidator(const UsdStagePtr& usdStage) {
103+
const SdfLayerRefPtr& rootLayer = usdStage->GetRootLayer();
104+
105+
SdfLayerRefPtrVector layers;
106+
std::vector<std::basic_string<char>> assets, unresolvedPaths;
107+
const SdfAssetPath& path = SdfAssetPath(rootLayer->GetIdentifier());
108+
109+
UsdUtilsComputeAllDependencies(path, &layers, &assets, &unresolvedPaths,
110+
nullptr);
111+
112+
UsdValidationErrorVector errors;
113+
for(const std::basic_string<char>& unresolvedPath : unresolvedPaths)
114+
{
115+
errors.emplace_back(
116+
UsdUtilsValidationErrorNameTokens->unresolvableDependency,
117+
UsdValidationErrorType::Error,
118+
UsdValidationErrorSites {
119+
UsdValidationErrorSite(
120+
rootLayer, SdfPath(unresolvedPath))
121+
},
122+
TfStringPrintf(
123+
("Found unresolvable external dependency "
124+
"'%s'."), unresolvedPath.c_str())
125+
);
126+
}
127+
128+
return errors;
129+
}
130+
100131
TF_REGISTRY_FUNCTION(UsdValidationRegistry)
101132
{
102133
UsdValidationRegistry &registry = UsdValidationRegistry::GetInstance();
134+
135+
registry.RegisterPluginValidator(
136+
UsdUtilsValidatorNameTokens->missingReferenceValidator, _MissingReferenceValidator);
137+
103138
registry.RegisterPluginValidator(
104139
UsdUtilsValidatorNameTokens->packageEncapsulationValidator,
105140
_PackageEncapsulationValidator);

0 commit comments

Comments
 (0)