From d9538ec45a1cae3108125e67fdec9d938ca86ce4 Mon Sep 17 00:00:00 2001 From: Andy Date: Mon, 2 Dec 2024 18:06:03 -0500 Subject: [PATCH 1/3] usdValidation: usdUtils: FileExtensionValidator Added an implementation of the FileExtensionValidator --- .../usdUtilsValidators/plugInfo.json | 6 +++ .../testenv/testUsdUtilsValidators.cpp | 42 ++++++++++++++- .../allSupportedFiles.usdz | Bin 0 -> 22761 bytes .../failFileExtension.usdz | Bin 0 -> 1211 bytes .../usdUtilsValidators/validatorTokens.h | 8 ++- .../usdUtilsValidators/validators.cpp | 50 ++++++++++++++++++ 6 files changed, 102 insertions(+), 4 deletions(-) create mode 100644 pxr/usdValidation/usdUtilsValidators/testenv/testUsdUtilsValidators/allSupportedFiles.usdz create mode 100644 pxr/usdValidation/usdUtilsValidators/testenv/testUsdUtilsValidators/failFileExtension.usdz diff --git a/pxr/usdValidation/usdUtilsValidators/plugInfo.json b/pxr/usdValidation/usdUtilsValidators/plugInfo.json index 9a6dc55333..bcec631c70 100644 --- a/pxr/usdValidation/usdUtilsValidators/plugInfo.json +++ b/pxr/usdValidation/usdUtilsValidators/plugInfo.json @@ -3,6 +3,12 @@ { "Info": { "Validators": { + "FileExtensionValidator": { + "doc": "Only valid core layer extensions (.usd, .usda, .usdc, .usdz) and valid core texture extensions (.exr, .jpg, .jpeg, .png) are allowed in a package.", + "keywords": [ + "UsdzValidators" + ] + }, "PackageEncapsulationValidator": { "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.", "keywords": [ diff --git a/pxr/usdValidation/usdUtilsValidators/testenv/testUsdUtilsValidators.cpp b/pxr/usdValidation/usdUtilsValidators/testenv/testUsdUtilsValidators.cpp index 26c425722a..caec2c0aab 100644 --- a/pxr/usdValidation/usdUtilsValidators/testenv/testUsdUtilsValidators.cpp +++ b/pxr/usdValidation/usdUtilsValidators/testenv/testUsdUtilsValidators.cpp @@ -30,7 +30,7 @@ TestUsdUsdzValidators() UsdValidationValidatorMetadataVector metadata = registry.GetValidatorMetadataForPlugin( _tokens->usdUtilsValidatorsPlugin); - TF_AXIOM(metadata.size() == 1); + TF_AXIOM(metadata.size() == 2); // Since other validators can be registered with a UsdUtilsValidators // keyword, our validators registered in usd are a subset of the entire // set. @@ -40,7 +40,8 @@ TestUsdUsdzValidators() } const std::set expectedValidatorNames - = { UsdUtilsValidatorNameTokens->packageEncapsulationValidator }; + = { UsdUtilsValidatorNameTokens->packageEncapsulationValidator, + UsdUtilsValidatorNameTokens->fileExtensionValidator }; TF_AXIOM(validatorMetadataNameSet == expectedValidatorNames); } @@ -113,11 +114,48 @@ TestPackageEncapsulationValidator() TF_AXIOM(errors.empty()); } +static void +TestFileExtensionValidator() +{ + UsdValidationRegistry& registry = UsdValidationRegistry::GetInstance(); + + // Verify the validator exists + const UsdValidationValidator *validator = registry.GetOrLoadValidatorByName( + UsdUtilsValidatorNameTokens->fileExtensionValidator); + + TF_AXIOM(validator); + + const UsdStageRefPtr& stage = UsdStage::Open("failFileExtension.usdz"); + UsdValidationErrorVector errors = validator->Validate(stage); + + const TfToken expectedErrorIdentifier( + "usdUtilsValidators:FileExtensionValidator.UnsupportedFileExtensionInPackage"); + // Verify error occurs. + TF_AXIOM(errors.size() == 1); + TF_AXIOM(errors[0].GetIdentifier() == expectedErrorIdentifier); + TF_AXIOM(errors[0].GetType() == UsdValidationErrorType::Error); + TF_AXIOM(errors[0].GetSites().size() == 1); + std::string message = errors[0].GetMessage(); + const std::string expectedErrorMsg = + "File 'cube.invalid' in package 'failFileExtension.usdz' has an " + "unknown unsupported extension 'invalid'."; + TF_AXIOM(errors[0].GetMessage() == expectedErrorMsg); + + // Load a passing stage + const UsdStageRefPtr& passStage = UsdStage::Open("allSupportedFiles.usdz"); + + errors = validator->Validate(passStage); + + // Verify no errors occur with all valid extensions included + TF_AXIOM(errors.empty()); +} + int main() { TestUsdUsdzValidators(); TestPackageEncapsulationValidator(); + TestFileExtensionValidator(); return EXIT_SUCCESS; } diff --git a/pxr/usdValidation/usdUtilsValidators/testenv/testUsdUtilsValidators/allSupportedFiles.usdz b/pxr/usdValidation/usdUtilsValidators/testenv/testUsdUtilsValidators/allSupportedFiles.usdz new file mode 100644 index 0000000000000000000000000000000000000000..f38334d6eebbacd609f513cec81ddcecca8b5d6d GIT binary patch literal 22761 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 literal 0 HcmV?d00001 diff --git a/pxr/usdValidation/usdUtilsValidators/testenv/testUsdUtilsValidators/failFileExtension.usdz b/pxr/usdValidation/usdUtilsValidators/testenv/testUsdUtilsValidators/failFileExtension.usdz new file mode 100644 index 0000000000000000000000000000000000000000..ecc7fc3427af95823a57b307b5c3ef0195b2318a GIT binary patch literal 1211 zcmbtT&u&Ko<4A`=E?FR=S|xcj%Zmuqh3`tW)^8T2OZC(c2~Qtr99$#DIe$( zk5JbnwAQmd24(b2)&~ZTab&xk+(@ZuRb>iVz1^o>k*x*74kZrhSsEp6LP@VhcuG!R zZ4C~HZucHFJGPa(wOS;7wi6w$F{xu;UwvZ!xueSNXnlM7;!POfV*%GODR8o^PhW55 z%&hOM)G8Z!!~^PCXlBZV2*=5{#k0rH)}>sOWyzTLYeA^&3cn{jzHHuHNn@(o2uh3w z9M+cnq1~}q1tCiXxDILAZJSVdLx+@`U4lxh?+|Pcw~2d*Jgc$P$GnK-32@5KWhTRs zpGsD;v^qO&CXUEF3?y>d=+?2_y8|dC8a33tqI&Ts+$tyOAiHZ2)tqz@{{;$f!~n% rr4ak!&wuKICfw|YZ%*j_>sgKUKC validExtensions = {TfToken("usda"), + TfToken("usdc"), TfToken("usd"), TfToken("usdz"), TfToken("png"), + TfToken("jpg"), TfToken("jpeg"), TfToken("exr")}; + + const SdfLayerHandle& rootLayer = usdStage->GetRootLayer(); + const UsdZipFile& zipFile = UsdZipFile::Open(rootLayer->GetRealPath()); + + const std::vector fileNames = + std::vector(zipFile.begin(), zipFile.end()); + + for (const std::string& fileName : fileNames) + { + const std::string extension = ArGetResolver().GetExtension(fileName); + + if (std::find(validExtensions.begin(), validExtensions.end(), + extension) == validExtensions.end()) + { + return { + UsdValidationError { + UsdUtilsValidationErrorNameTokens-> + unsupportedFileExtensionInPackage, + UsdValidationErrorType::Error, + UsdValidationErrorSites { + UsdValidationErrorSite( + rootLayer, SdfPath(rootLayer->GetIdentifier())) + }, + TfStringPrintf("File '%s' in package '%s' has an unknown " + "unsupported extension '%s'.", + fileName.c_str(), + rootLayer->GetIdentifier().c_str(), + extension.c_str()) + } + }; + } + } + + return errors; +} + TF_REGISTRY_FUNCTION(UsdValidationRegistry) { UsdValidationRegistry ®istry = UsdValidationRegistry::GetInstance(); + registry.RegisterPluginValidator( UsdUtilsValidatorNameTokens->packageEncapsulationValidator, _PackageEncapsulationValidator); + + registry.RegisterPluginValidator( + UsdUtilsValidatorNameTokens->fileExtensionValidator, + _FileExtensionValidator); } PXR_NAMESPACE_CLOSE_SCOPE From 63f82df0a2717e1ae58b464e8fcf44ba724eadb0 Mon Sep 17 00:00:00 2001 From: Andy Date: Wed, 11 Dec 2024 01:18:34 -0500 Subject: [PATCH 2/3] fix: address PR comments - change vector of TfTokens to set - update test code to have it's own ValidateError function - scope errors to improve coding style --- .../testenv/testUsdUtilsValidators.cpp | 120 ++++++++++-------- .../usdUtilsValidators/validators.cpp | 2 +- 2 files changed, 66 insertions(+), 56 deletions(-) diff --git a/pxr/usdValidation/usdUtilsValidators/testenv/testUsdUtilsValidators.cpp b/pxr/usdValidation/usdUtilsValidators/testenv/testUsdUtilsValidators.cpp index caec2c0aab..162a278ec6 100644 --- a/pxr/usdValidation/usdUtilsValidators/testenv/testUsdUtilsValidators.cpp +++ b/pxr/usdValidation/usdUtilsValidators/testenv/testUsdUtilsValidators.cpp @@ -46,6 +46,21 @@ TestUsdUsdzValidators() TF_AXIOM(validatorMetadataNameSet == expectedValidatorNames); } + +void ValidateError(const UsdValidationError &error, + const std::string& expectedErrorMsg, + const TfToken& expectedErrorIdentifier, + UsdValidationErrorType expectedErrorType = + UsdValidationErrorType::Error) +{ + TF_AXIOM(error.GetIdentifier() == expectedErrorIdentifier); + TF_AXIOM(error.GetType() == expectedErrorType); + TF_AXIOM(error.GetSites().size() == 1u); + const UsdValidationErrorSite &errorSite = error.GetSites()[0]; + TF_AXIOM(!errorSite.GetLayer().IsInvalid()); + TF_AXIOM(error.GetMessage() == expectedErrorMsg); +} + static void TestPackageEncapsulationValidator() { @@ -61,57 +76,57 @@ TestPackageEncapsulationValidator() // that are not included in the package, but exist const UsdStageRefPtr &stage = UsdStage::Open("fail.usdz"); - UsdValidationErrorVector errors = validator->Validate(stage); - - // Verify both the layer & asset errors are present - TF_AXIOM(errors.size() == 2); - - // Note that we keep the referenced layer in normalized path to represent - // the layer identifier, whereas the asset path is platform specific path, - // as returned by UsdUtilsComputeAllDependencies - const SdfLayerRefPtr &rootLayer = stage->GetRootLayer(); - const std::string &rootLayerIdentifier = rootLayer->GetIdentifier(); - const std::string realUsdzPath = rootLayer->GetRealPath(); - const std::string errorLayer - = TfStringCatPaths(TfGetPathName(TfAbsPath(rootLayerIdentifier)), - "excludedDirectory/layer.usda"); - - std::filesystem::path parentDir - = std::filesystem::path(realUsdzPath).parent_path(); - const std::string errorAsset - = (parentDir / "excludedDirectory" / "image.jpg").string(); - - std::array expectedErrorMessages - = { TfStringPrintf(("Found referenced layer '%s' that does not " - "belong to the package '%s'."), - errorLayer.c_str(), realUsdzPath.c_str()), - TfStringPrintf(("Found asset reference '%s' that does not belong" - " to the package '%s'."), - errorAsset.c_str(), realUsdzPath.c_str()) }; - - std::array expectedErrorIdentifiers = { - TfToken( - "usdUtilsValidators:PackageEncapsulationValidator.LayerNotInPackage"), - TfToken( - "usdUtilsValidators:PackageEncapsulationValidator.AssetNotInPackage") - }; - - for (size_t i = 0; i < errors.size(); ++i) { - TF_AXIOM(errors[i].GetIdentifier() == expectedErrorIdentifiers[i]); - TF_AXIOM(errors[i].GetType() == UsdValidationErrorType::Warn); - TF_AXIOM(errors[i].GetSites().size() == 1); - TF_AXIOM(!errors[i].GetSites()[0].GetLayer().IsInvalid()); - TF_AXIOM(errors[i].GetMessage() == expectedErrorMessages[i]); + { + const UsdValidationErrorVector errors = validator->Validate(stage); + + // Verify both the layer & asset errors are present + TF_AXIOM(errors.size() == 2u); + + // Note that we keep the referenced layer in normalized path to represent + // the layer identifier, whereas the asset path is platform specific path, + // as returned by UsdUtilsComputeAllDependencies + const SdfLayerRefPtr &rootLayer = stage->GetRootLayer(); + const std::string &rootLayerIdentifier = rootLayer->GetIdentifier(); + const std::string realUsdzPath = rootLayer->GetRealPath(); + const std::string errorLayer + = TfStringCatPaths(TfGetPathName(TfAbsPath(rootLayerIdentifier)), + "excludedDirectory/layer.usda"); + + std::filesystem::path parentDir + = std::filesystem::path(realUsdzPath).parent_path(); + const std::string errorAsset + = (parentDir / "excludedDirectory" / "image.jpg").string(); + + std::array expectedErrorMessages + = { TfStringPrintf(("Found referenced layer '%s' that does not " + "belong to the package '%s'."), + errorLayer.c_str(), realUsdzPath.c_str()), + TfStringPrintf(("Found asset reference '%s' that does not belong" + " to the package '%s'."), + errorAsset.c_str(), realUsdzPath.c_str()) }; + + std::array expectedErrorIdentifiers = { + TfToken( + "usdUtilsValidators:PackageEncapsulationValidator.LayerNotInPackage"), + TfToken( + "usdUtilsValidators:PackageEncapsulationValidator.AssetNotInPackage") + }; + + for (size_t i = 0; i < errors.size(); ++i) { + ValidateError(errors[i], expectedErrorMessages[i], + expectedErrorIdentifiers[i], UsdValidationErrorType::Warn); + } } // Load the pre-created usdz stage with relative paths to both a reference // and an asset that are included in the package. const UsdStageRefPtr &passStage = UsdStage::Open("pass.usdz"); + { + const UsdValidationErrorVector errors = validator->Validate(passStage); - errors = validator->Validate(passStage); - - // Verify the errors are gone - TF_AXIOM(errors.empty()); + // Verify the errors are gone + TF_AXIOM(errors.empty()); + } } static void @@ -127,19 +142,14 @@ TestFileExtensionValidator() const UsdStageRefPtr& stage = UsdStage::Open("failFileExtension.usdz"); UsdValidationErrorVector errors = validator->Validate(stage); - - const TfToken expectedErrorIdentifier( - "usdUtilsValidators:FileExtensionValidator.UnsupportedFileExtensionInPackage"); - // Verify error occurs. - TF_AXIOM(errors.size() == 1); - TF_AXIOM(errors[0].GetIdentifier() == expectedErrorIdentifier); - TF_AXIOM(errors[0].GetType() == UsdValidationErrorType::Error); - TF_AXIOM(errors[0].GetSites().size() == 1); - std::string message = errors[0].GetMessage(); + TF_AXIOM(errors.size() == 1u); const std::string expectedErrorMsg = "File 'cube.invalid' in package 'failFileExtension.usdz' has an " "unknown unsupported extension 'invalid'."; - TF_AXIOM(errors[0].GetMessage() == expectedErrorMsg); + const TfToken expectedErrorIdentifier( + "usdUtilsValidators:FileExtensionValidator.UnsupportedFileExtensionInPackage"); + // Verify error occurs. + ValidateError(errors[0], expectedErrorMsg, expectedErrorIdentifier); // Load a passing stage const UsdStageRefPtr& passStage = UsdStage::Open("allSupportedFiles.usdz"); diff --git a/pxr/usdValidation/usdUtilsValidators/validators.cpp b/pxr/usdValidation/usdUtilsValidators/validators.cpp index cf299f4851..7b7c114bb0 100644 --- a/pxr/usdValidation/usdUtilsValidators/validators.cpp +++ b/pxr/usdValidation/usdUtilsValidators/validators.cpp @@ -103,7 +103,7 @@ static UsdValidationErrorVector _FileExtensionValidator(const UsdStagePtr& usdStage) { UsdValidationErrorVector errors; - const std::vector validExtensions = {TfToken("usda"), + const std::set validExtensions = {TfToken("usda"), TfToken("usdc"), TfToken("usd"), TfToken("usdz"), TfToken("png"), TfToken("jpg"), TfToken("jpeg"), TfToken("exr")}; From 0715bd78fbff34b0c14053c9f691587382865480 Mon Sep 17 00:00:00 2001 From: Andy Date: Thu, 12 Dec 2024 00:36:16 -0500 Subject: [PATCH 3/3] feat: add additional supported file formats --- pxr/usdValidation/usdUtilsValidators/validators.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pxr/usdValidation/usdUtilsValidators/validators.cpp b/pxr/usdValidation/usdUtilsValidators/validators.cpp index 7b7c114bb0..204274ab43 100644 --- a/pxr/usdValidation/usdUtilsValidators/validators.cpp +++ b/pxr/usdValidation/usdUtilsValidators/validators.cpp @@ -105,7 +105,8 @@ _FileExtensionValidator(const UsdStagePtr& usdStage) { const std::set validExtensions = {TfToken("usda"), TfToken("usdc"), TfToken("usd"), TfToken("usdz"), TfToken("png"), - TfToken("jpg"), TfToken("jpeg"), TfToken("exr")}; + TfToken("jpg"), TfToken("jpeg"), TfToken("exr"), TfToken("avif"), + TfToken("m4a"), TfToken("mp3"), TfToken("wav")}; const SdfLayerHandle& rootLayer = usdStage->GetRootLayer(); const UsdZipFile& zipFile = UsdZipFile::Open(rootLayer->GetRealPath());