Skip to content

Commit

Permalink
BUG: Now catch std::filesystem exceptions in parameters (#1127)
Browse files Browse the repository at this point in the history
* Added nx::core::filesystem::exists to wrap std::filesystem::exists
* Wrapped std::filesystem calls in try-catch blocks
* Currently only done for parameters to prevent issues during
preflight
---------

Signed-off-by: Jared Duffey <[email protected]>
  • Loading branch information
JDuffeyBQ authored Nov 11, 2024
1 parent e431b77 commit dade5e9
Show file tree
Hide file tree
Showing 5 changed files with 147 additions and 82 deletions.
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -336,6 +336,7 @@ set(SIMPLNX_HDRS
${SIMPLNX_SOURCE_DIR}/Common/DataTypeUtilities.hpp
${SIMPLNX_SOURCE_DIR}/Common/DataVector.hpp
${SIMPLNX_SOURCE_DIR}/Common/EulerAngle.hpp
${SIMPLNX_SOURCE_DIR}/Common/Filesystem.hpp
${SIMPLNX_SOURCE_DIR}/Common/IteratorUtility.hpp
${SIMPLNX_SOURCE_DIR}/Common/Numbers.hpp
${SIMPLNX_SOURCE_DIR}/Common/Range.hpp
Expand Down
21 changes: 21 additions & 0 deletions src/simplnx/Common/Filesystem.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
#pragma once

#include "simplnx/Common/Result.hpp"

#include <nonstd/expected.hpp>

#include <filesystem>

namespace nx::core::filesystem
{
inline Result<bool> exists(const std::filesystem::path& path)
{
std::error_code errorCode;
bool result = std::filesystem::exists(path, errorCode);
if(errorCode)
{
return MakeErrorResult<bool>(errorCode.value(), errorCode.message());
}
return {result};
}
} // namespace nx::core::filesystem
28 changes: 17 additions & 11 deletions src/simplnx/Parameters/Dream3dImportParameter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -156,21 +156,27 @@ Result<> Dream3dImportParameter::validate(const std::any& value) const
//-----------------------------------------------------------------------------
Result<> Dream3dImportParameter::validatePath(const ValueType& importData) const
{
std::filesystem::path path = importData.FilePath;
if(!fs::exists(path))
try
{
return MakeErrorResult(-2, fmt::format("Path '{}' does not exist", path.string()));
}
std::filesystem::path path = importData.FilePath;
if(!fs::exists(path))
{
return MakeErrorResult(-2, fmt::format("Path '{}' does not exist", path.string()));
}

if(!fs::is_regular_file(path))
{
return MakeErrorResult(-3, fmt::format("Path '{}' is not a file", path.string()));
}
if(!fs::is_regular_file(path))
{
return MakeErrorResult(-3, fmt::format("Path '{}' is not a file", path.string()));
}

nx::core::HDF5::FileReader fileReader(path);
if(!fileReader.isValid())
nx::core::HDF5::FileReader fileReader(path);
if(!fileReader.isValid())
{
return MakeErrorResult(-4, fmt::format("HDF5 file at path '{}' could not be read", path.string()));
}
} catch(const fs::filesystem_error& exception)
{
return MakeErrorResult(-4, fmt::format("HDF5 file at path '{}' could not be read", path.string()));
return MakeErrorResult(-5, fmt::format("Filesystem excpetion: {}", exception.what()));
}
return {};
}
Expand Down
130 changes: 81 additions & 49 deletions src/simplnx/Parameters/FileSystemPathParameter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,67 +25,93 @@ namespace
//-----------------------------------------------------------------------------
Result<> ValidateInputFile(const FileSystemPathParameter::ValueType& path)
{
if(!fs::exists(path))
try
{
return MakeErrorResult(-2, fmt::format("File System Path '{}' does not exist", path.string()));
}
if(!fs::exists(path))
{
return MakeErrorResult(-2, fmt::format("File System Path '{}' does not exist", path.string()));
}

if(!fs::is_regular_file(path))
if(!fs::is_regular_file(path))
{
return MakeErrorResult(-3, fmt::format("File System Path '{}' is not a file", path.string()));
}
} catch(const fs::filesystem_error& exception)
{
return MakeErrorResult(-3, fmt::format("File System Path '{}' is not a file", path.string()));
return MakeErrorResult(-9, fmt::format("Filesystem excpetion: {}", exception.what()));
}
return {};
}

//-----------------------------------------------------------------------------
Result<> ValidateInputDir(const FileSystemPathParameter::ValueType& path)
{
if(!fs::exists(path))

try
{
return MakeErrorResult(-4, fmt::format("File System Path '{}' does not exist", path.string()));
}
if(!fs::is_directory(path))
if(!fs::exists(path))
{
return MakeErrorResult(-4, fmt::format("File System Path '{}' does not exist", path.string()));
}
if(!fs::is_directory(path))
{
return MakeErrorResult(-5, fmt::format("File System Path '{}' is not a file", path.string()));
}
} catch(const fs::filesystem_error& exception)
{
return MakeErrorResult(-5, fmt::format("File System Path '{}' is not a file", path.string()));
return MakeErrorResult(-10, fmt::format("Filesystem excpetion: {}", exception.what()));
}

return {};
}

//-----------------------------------------------------------------------------
Result<> ValidateOutputFile(const FileSystemPathParameter::ValueType& path)
{
if(fs::exists(path) && fs::is_directory(path))
try
{
return MakeErrorResult(-8, fmt::format("File System Path '{}' exists AND is a directory. The Parameter is set to save a file.", path.string()));
}
if(fs::exists(path) && fs::is_directory(path))
{
return MakeErrorResult(-8, fmt::format("File System Path '{}' exists AND is a directory. The Parameter is set to save a file.", path.string()));
}

auto result = FileUtilities::ValidateDirectoryWritePermission(path, true);
if(result.invalid())
{
return result;
}
if(!fs::exists(path))
auto result = FileUtilities::ValidateDirectoryWritePermission(path, true);
if(result.invalid())
{
return result;
}
if(!fs::exists(path))
{
return MakeWarningVoidResult(-6, fmt::format("File System Path '{}' does not exist. It will be created during execution.", path.string()));
}
} catch(const fs::filesystem_error& exception)
{
return MakeWarningVoidResult(-6, fmt::format("File System Path '{}' does not exist. It will be created during execution.", path.string()));
return MakeErrorResult(-11, fmt::format("Filesystem excpetion: {}", exception.what()));
}

return {};
}

//-----------------------------------------------------------------------------
Result<> ValidateOutputDir(const FileSystemPathParameter::ValueType& path)
{
auto result = FileUtilities::ValidateDirectoryWritePermission(path, false);
if(result.invalid())
try
{
return result;
}
if(!fs::exists(path))
auto result = FileUtilities::ValidateDirectoryWritePermission(path, false);
if(result.invalid())
{
return result;
}
if(!fs::exists(path))
{
return MakeWarningVoidResult(-7, fmt::format("File System Path '{}' does not exist. It will be created during execution.", path.string()));
}
} catch(const fs::filesystem_error& exception)
{
return MakeWarningVoidResult(-7, fmt::format("File System Path '{}' does not exist. It will be created during execution.", path.string()));
return MakeErrorResult(-12, fmt::format("Filesystem excpetion: {}", exception.what()));
}
return {};
}

} // namespace

namespace nx::core
Expand Down Expand Up @@ -204,36 +230,42 @@ Result<> FileSystemPathParameter::validate(const std::any& value) const
//-----------------------------------------------------------------------------
Result<> FileSystemPathParameter::validatePath(const ValueType& path) const
{
const std::string prefix = fmt::format("Parameter Name: '{}'\n Parameter Key: '{}'\n Validation Error: ", humanName(), name());

if(path.empty())
try
{
return nx::core::MakeErrorResult(-3001, fmt::format("{} File System Path must not be empty", prefix));
}
const std::string prefix = fmt::format("Parameter Name: '{}'\n Parameter Key: '{}'\n Validation Error: ", humanName(), name());

if(!m_acceptAllExtensions && (m_PathType == nx::core::FileSystemPathParameter::PathType::InputFile || m_PathType == nx::core::FileSystemPathParameter::PathType::OutputFile))
{
if(!path.has_extension())
if(path.empty())
{
return {nonstd::make_unexpected(std::vector<Error>{{-3002, fmt::format("{} File System Path must include a file extension.\n FilePath: '{}'", prefix, path.string())}})};
return nx::core::MakeErrorResult(-3001, fmt::format("{} File System Path must not be empty", prefix));
}
std::string lowerExtension = nx::core::StringUtilities::toLower(path.extension().string());
if(path.has_extension() && !m_AvailableExtensions.empty() && m_AvailableExtensions.find(lowerExtension) == m_AvailableExtensions.end())

if(!m_acceptAllExtensions && (m_PathType == nx::core::FileSystemPathParameter::PathType::InputFile || m_PathType == nx::core::FileSystemPathParameter::PathType::OutputFile))
{
return {nonstd::make_unexpected(std::vector<Error>{{-3003, fmt::format("{} File extension '{}' is not a valid file extension", prefix, path.extension().string())}})};
if(!path.has_extension())
{
return {nonstd::make_unexpected(std::vector<Error>{{-3002, fmt::format("{} File System Path must include a file extension.\n FilePath: '{}'", prefix, path.string())}})};
}
std::string lowerExtension = nx::core::StringUtilities::toLower(path.extension().string());
if(path.has_extension() && !m_AvailableExtensions.empty() && m_AvailableExtensions.find(lowerExtension) == m_AvailableExtensions.end())
{
return {nonstd::make_unexpected(std::vector<Error>{{-3003, fmt::format("{} File extension '{}' is not a valid file extension", prefix, path.extension().string())}})};
}
}
}

switch(m_PathType)
switch(m_PathType)
{
case nx::core::FileSystemPathParameter::PathType::InputFile:
return ValidateInputFile(path);
case nx::core::FileSystemPathParameter::PathType::InputDir:
return ValidateInputDir(path);
case nx::core::FileSystemPathParameter::PathType::OutputFile:
return ValidateOutputFile(path);
case nx::core::FileSystemPathParameter::PathType::OutputDir:
return ValidateOutputDir(path);
}
} catch(const fs::filesystem_error& exception)
{
case nx::core::FileSystemPathParameter::PathType::InputFile:
return ValidateInputFile(path);
case nx::core::FileSystemPathParameter::PathType::InputDir:
return ValidateInputDir(path);
case nx::core::FileSystemPathParameter::PathType::OutputFile:
return ValidateOutputFile(path);
case nx::core::FileSystemPathParameter::PathType::OutputDir:
return ValidateOutputDir(path);
return MakeErrorResult(-9, fmt::format("Filesystem excpetion: {}", exception.what()));
}

return {};
Expand Down
49 changes: 27 additions & 22 deletions src/simplnx/Parameters/GeneratedFileListParameter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -150,36 +150,41 @@ std::any GeneratedFileListParameter::defaultValue() const
//-----------------------------------------------------------------------------
Result<> GeneratedFileListParameter::validate(const std::any& valueRef) const
{
const std::string prefix = fmt::format("Parameter Name: '{}'\n Parameter Key: '{}'\n Validation Error: ", humanName(), name());
try
{
const std::string prefix = fmt::format("Parameter Name: '{}'\n Parameter Key: '{}'\n Validation Error: ", humanName(), name());

const auto& value = GetAnyRef<ValueType>(valueRef);
const auto& value = GetAnyRef<ValueType>(valueRef);

if(value.inputPath.empty())
{
return nx::core::MakeErrorResult(nx::core::FilterParameter::Constants::k_Validate_Empty_Value, fmt::format("{}Input Path cannot be empty.", prefix));
}
if(value.inputPath.empty())
{
return nx::core::MakeErrorResult(nx::core::FilterParameter::Constants::k_Validate_Empty_Value, fmt::format("{}Input Path cannot be empty.", prefix));
}

if(value.startIndex > value.endIndex)
{
return nx::core::MakeErrorResult(-4002, fmt::format("{}startIndex must be less than or equal to endIndex.", prefix));
}
// Generate the file list
auto fileList = value.generate();
// Validate that they all exist
std::vector<Error> errors;
for(const auto& currentFilePath : fileList)
{
if(!fs::exists(currentFilePath))
if(value.startIndex > value.endIndex)
{
errors.push_back({-4003, fmt::format("{}FILE DOES NOT EXIST: '{}'", prefix, currentFilePath)});
return nx::core::MakeErrorResult(-4002, fmt::format("{}startIndex must be less than or equal to endIndex.", prefix));
}
// Generate the file list
auto fileList = value.generate();
// Validate that they all exist
std::vector<Error> errors;
for(const auto& currentFilePath : fileList)
{
if(!fs::exists(currentFilePath))
{
errors.push_back({-4003, fmt::format("{}FILE DOES NOT EXIST: '{}'", prefix, currentFilePath)});
}
}
}

if(!errors.empty())
if(!errors.empty())
{
return {nonstd::make_unexpected(std::move(errors))};
}
} catch(const fs::filesystem_error& exception)
{
return {nonstd::make_unexpected(std::move(errors))};
return MakeErrorResult(-4004, fmt::format("Filesystem excpetion: {}", exception.what()));
}

return {};
}

Expand Down

0 comments on commit dade5e9

Please sign in to comment.