Files
SDL3CPlusPlus/MaterialX/source/MaterialXTest/MaterialXFormat/File.cpp
2026-01-06 13:25:49 +00:00

208 lines
7.9 KiB
C++

//
// Copyright Contributors to the MaterialX Project
// SPDX-License-Identifier: Apache-2.0
//
#include <MaterialXTest/External/Catch/catch.hpp>
#include <MaterialXFormat/File.h>
#include <MaterialXFormat/Util.h>
namespace mx = MaterialX;
TEST_CASE("Syntactic operations", "[file]")
{
using InputPair = std::pair<std::string, mx::FilePath::Format>;
std::vector<InputPair> inputPairs =
{
{"D:\\Assets\\Materials\\Robot.mtlx", mx::FilePath::FormatWindows},
{"\\\\Show\\Assets\\Materials\\Robot.mtlx", mx::FilePath::FormatWindows},
{"Materials\\Robot.mtlx", mx::FilePath::FormatWindows},
{"/Assets/Materials/Robot.mtlx", mx::FilePath::FormatPosix},
{"Assets/Materials/Robot.mtlx", mx::FilePath::FormatPosix},
{"Materials/Robot.mtlx", mx::FilePath::FormatPosix}
};
for (const InputPair& pair : inputPairs)
{
mx::FilePath path(pair.first);
REQUIRE(path.asString(pair.second) == pair.first);
}
}
TEST_CASE("File system operations", "[file]")
{
mx::FileSearchPath searchPath = mx::getDefaultDataSearchPath();
mx::FilePathVec examplePaths =
{
"libraries/stdlib/stdlib_defs.mtlx",
"resources/Materials/Examples/StandardSurface/standard_surface_brass_tiled.mtlx",
"resources/Materials/Examples/StandardSurface/standard_surface_marble_solid.mtlx",
};
for (const mx::FilePath& path : examplePaths)
{
REQUIRE(searchPath.find(path).exists());
}
REQUIRE(mx::FilePath::getCurrentPath().exists());
REQUIRE(mx::FilePath::getModulePath().exists());
}
TEST_CASE("File search path operations", "[file]")
{
mx::FileSearchPath searchPath = mx::getDefaultDataSearchPath();
searchPath.append(searchPath.find("libraries/stdlib"));
searchPath.append(searchPath.find("resources/Materials/Examples/StandardSurface"));
mx::FilePathVec filenames =
{
"stdlib_defs.mtlx",
"standard_surface_brass_tiled.mtlx",
"standard_surface_marble_solid.mtlx",
};
for (const mx::FilePath& filename : filenames)
{
REQUIRE(searchPath.find(filename).exists());
}
}
TEST_CASE("Flatten filenames", "[file]")
{
const mx::FilePath TEST_FILE_PREFIX_STRING("resources\\Images\\");
const mx::FilePath TEST_IMAGE_STRING1("brass_roughness.jpg");
const mx::FilePath TEST_IMAGE_STRING2("brass_color.jpg");
mx::DocumentPtr doc1 = mx::createDocument();
// Set up document
mx::NodeGraphPtr nodeGraph = doc1->addNodeGraph();
nodeGraph->setFilePrefix(TEST_FILE_PREFIX_STRING.asString() + "\\"); // Note this is required as filepath->string strips out last separator
mx::NodePtr image1 = nodeGraph->addNode("image");
image1->setInputValue("file", "brass_roughness.jpg", mx::FILENAME_TYPE_STRING);
mx::NodePtr image2 = nodeGraph->addNode("image");
image2->setInputValue("file", "brass_color.jpg", mx::FILENAME_TYPE_STRING);
// 1. Test resolving fileprefix
mx::flattenFilenames(doc1);
REQUIRE(nodeGraph->getFilePrefix() == mx::EMPTY_STRING);
mx::FilePath resolvedPath(image1->getInputValue("file")->getValueString());
REQUIRE(resolvedPath == (TEST_FILE_PREFIX_STRING / TEST_IMAGE_STRING1));
resolvedPath = image2->getInputValue("file")->getValueString();
REQUIRE(resolvedPath == (TEST_FILE_PREFIX_STRING / TEST_IMAGE_STRING2));
// Reset document
nodeGraph->setFilePrefix(TEST_FILE_PREFIX_STRING.asString() + "\\");
image1->setInputValue("file", "brass_roughness.jpg", mx::FILENAME_TYPE_STRING);
image2->setInputValue("file", "brass_color.jpg", mx::FILENAME_TYPE_STRING);
// 2. Test resolving to absolute paths
mx::FileSearchPath searchPath = mx::getDefaultDataSearchPath();
mx::FilePath rootPath = searchPath.isEmpty() ? mx::FilePath() : searchPath[0];
mx::flattenFilenames(doc1, searchPath);
REQUIRE(nodeGraph->getFilePrefix() == mx::EMPTY_STRING);
resolvedPath = image1->getInputValue("file")->getValueString();
REQUIRE(resolvedPath.asString() == (rootPath / TEST_FILE_PREFIX_STRING / TEST_IMAGE_STRING1).asString());
resolvedPath = image2->getInputValue("file")->getValueString();
REQUIRE(resolvedPath.asString() == (rootPath / TEST_FILE_PREFIX_STRING / TEST_IMAGE_STRING2).asString());
// Reset document
nodeGraph->setFilePrefix(TEST_FILE_PREFIX_STRING.asString() + "\\");
image1->setInputValue("file", "brass_roughness.jpg", mx::FILENAME_TYPE_STRING);
image2->setInputValue("file", "brass_color.jpg", mx::FILENAME_TYPE_STRING);
// 3. Test with additional resolvers
// - Create resolver to replace all Windows separators with POSIX ones
mx::StringResolverPtr separatorReplacer = mx::StringResolver::create();
separatorReplacer->setFilenameSubstitution("\\\\", "/");
separatorReplacer->setFilenameSubstitution("\\", "/");
mx::flattenFilenames(doc1, searchPath, separatorReplacer);
REQUIRE(nodeGraph->getFilePrefix() == mx::EMPTY_STRING);
std::string resolvedPathString = image1->getInputValue("file")->getValueString();
REQUIRE(resolvedPathString == (rootPath / TEST_FILE_PREFIX_STRING / TEST_IMAGE_STRING1).asString(mx::FilePath::FormatPosix));
resolvedPathString = image2->getInputValue("file")->getValueString();
REQUIRE(resolvedPathString == (rootPath / TEST_FILE_PREFIX_STRING / TEST_IMAGE_STRING2).asString(mx::FilePath::FormatPosix));
// 4. Test with pre-resolved filenames
nodeGraph->setFilePrefix(TEST_FILE_PREFIX_STRING.asString() + "\\");
mx::flattenFilenames(doc1, searchPath, separatorReplacer);
REQUIRE(nodeGraph->getFilePrefix() == mx::EMPTY_STRING);
resolvedPathString = image1->getInputValue("file")->getValueString();
REQUIRE(resolvedPathString == (rootPath / TEST_FILE_PREFIX_STRING / TEST_IMAGE_STRING1).asString(mx::FilePath::FormatPosix));
resolvedPathString = image2->getInputValue("file")->getValueString();
REQUIRE(resolvedPathString == (rootPath / TEST_FILE_PREFIX_STRING / TEST_IMAGE_STRING2).asString(mx::FilePath::FormatPosix));
}
TEST_CASE("Path normalization test", "[file]")
{
const mx::FilePath REFERENCE_REL_PATH("a/b");
const mx::FilePath REFERENCE_ABS_PREFIX("/assets");
std::vector<mx::FilePath> examplePaths =
{
"a/./b",
"././a/b",
"c/../d/../a/b",
"a/b/./c/d/../.."
};
for (const mx::FilePath& path : examplePaths)
{
REQUIRE(path.getNormalized() == REFERENCE_REL_PATH);
REQUIRE((REFERENCE_ABS_PREFIX / path).getNormalized() == (REFERENCE_ABS_PREFIX / REFERENCE_REL_PATH));
}
}
TEST_CASE("Get all files in directory", "[file]")
{
mx::FileSearchPath searchPath = mx::getDefaultDataSearchPath();
mx::FilePath lightsDir = searchPath.find("resources/Lights");
mx::FilePathVec mtlxFilenames =
{
"environment_map.mtlx",
"goegap_split.mtlx",
"san_giuseppe_bridge_split.mtlx",
"table_mountain_split.mtlx"
};
mx::FilePathVec hdrFilenames =
{
"goegap.hdr",
"goegap_split.hdr",
"san_giuseppe_bridge.hdr",
"san_giuseppe_bridge_split.hdr",
"table_mountain.hdr",
"table_mountain_split.hdr",
};
mx::FilePathVec allFilesnames = hdrFilenames;
allFilesnames.insert(allFilesnames.begin(), mtlxFilenames.begin(), mtlxFilenames.end());
mx::FilePathVec results;
results = lightsDir.getFilesInDirectory("mtlx");
REQUIRE(results.size() > 0);
for (const mx::FilePath& filename : mtlxFilenames)
{
REQUIRE(std::find(results.begin(), results.end(), filename) != results.end());
}
results = lightsDir.getFilesInDirectory("hdr");
REQUIRE(results.size() > 0);
for (const mx::FilePath& filename : hdrFilenames)
{
REQUIRE(std::find(results.begin(), results.end(), filename) != results.end());
}
results = lightsDir.getFilesInDirectory();
REQUIRE(results.size() > 0);
for (const mx::FilePath& filename : allFilesnames)
{
REQUIRE(std::find(results.begin(), results.end(), filename) != results.end());
}
}