diff --git a/src/common/util/src/file_util.cpp b/src/common/util/src/file_util.cpp index 89569a8bb95f2e..5436f26f03014a 100644 --- a/src/common/util/src/file_util.cpp +++ b/src/common/util/src/file_util.cpp @@ -294,12 +294,17 @@ void ov::util::create_directory_recursive(const std::wstring& path) { void ov::util::create_directory_recursive(const std::filesystem::path& path) { namespace fs = std::filesystem; auto dir_path = fs::weakly_canonical(path); - if (!dir_path.has_filename() || dir_path.has_extension()) { - dir_path = get_directory(dir_path); - } if (!dir_path.empty() && !directory_exists(dir_path)) { - if (std::error_code ec; !fs::create_directories(dir_path, ec)) { + // NOTE: Some standard library implementations (MSVC STL, libc++) may return `false` + // from create_directories(path, ec) (with ec == 0) when the path ends with a + // trailing separator (e.g. "a/b/c/"). Internally they create "a", "a/b", "a/b/c" + // and then the extra mkdir on "a/b/c/" yields an "already exists" condition, + // leading to a final `false` even though the directory tree was actually created. + // libstdc++ (GCC) returns `true` in that situation. The extra exists() check + // lets us treat "false + exists()" as success while still detecting a real failure + // ("false + !exists()"), keeping behavior consistent across platforms. + if (std::error_code ec; !fs::create_directories(dir_path, ec) && !std::filesystem::exists(dir_path)) { std::stringstream ss; ss << "Couldn't create directory [" << dir_path << "], err=" << ec.message() << ")"; throw std::runtime_error(ss.str()); diff --git a/src/core/src/pass/serialize.cpp b/src/core/src/pass/serialize.cpp index 4de66749b4fdff..e8ca7cc5526e2e 100644 --- a/src/core/src/pass/serialize.cpp +++ b/src/core/src/pass/serialize.cpp @@ -110,7 +110,7 @@ bool pass::Serialize::run_on_model(const std::shared_ptr& model) { if (m_xmlFile && m_binFile) { serialize_func(*m_xmlFile, *m_binFile, model, m_version); } else { - ov::util::create_directory_recursive(m_xmlPath); + ov::util::create_directory_recursive(m_xmlPath.parent_path()); std::ofstream bin_file(m_binPath, std::ios::binary); OPENVINO_ASSERT(bin_file, "Can't open bin file: \"", m_binPath, "\""); diff --git a/src/plugins/intel_gpu/tests/functional/subgraph_tests/serialize.cpp b/src/plugins/intel_gpu/tests/functional/subgraph_tests/serialize.cpp index 2eb46c8e4c3b01..09b5052df9dc07 100644 --- a/src/plugins/intel_gpu/tests/functional/subgraph_tests/serialize.cpp +++ b/src/plugins/intel_gpu/tests/functional/subgraph_tests/serialize.cpp @@ -4,6 +4,7 @@ #include "shared_test_classes/base/ov_subgraph.hpp" #include "subgraphs_builders.hpp" +#include "openvino/op/relu.hpp" namespace { @@ -65,4 +66,44 @@ TEST_F(LSTMSequenceTest, smoke_serialize) { TEST_F(GRUSequenceTest, smoke_serialize) { run(); } + +class GpuCacheDirWithDotsParamTest : public ::testing::TestWithParam { +protected: + ov::Core core; + std::string cacheDir; + + void SetUp() override { + std::stringstream ss; + ss << std::hex << std::hash{}(std::string(::testing::UnitTest::GetInstance()->current_test_info()->name())); + + // Base (no trailing slash first) + cacheDir = ss.str() + GetParam(); + + // Clean previous + ov::test::utils::removeFilesWithExt(cacheDir, "blob"); + ov::test::utils::removeFilesWithExt(cacheDir, "cl_cache"); + ov::test::utils::removeDir(cacheDir); + + core.set_property(ov::cache_dir(cacheDir)); + } + + void TearDown() override { + ov::test::utils::removeFilesWithExt(cacheDir, "blob"); + ov::test::utils::removeFilesWithExt(cacheDir, "cl_cache"); + ov::test::utils::removeDir(cacheDir); + } +}; + +TEST_P(GpuCacheDirWithDotsParamTest, smoke_PopulateAndReuseCache) { + auto param = std::make_shared(ov::element::f32, ov::Shape{1, 3, 8, 8}); + auto relu = std::make_shared(param); + auto res = std::make_shared(relu); + auto model = std::make_shared(ov::ResultVector{res}, ov::ParameterVector{param}, "CacheDotsModel"); + core.compile_model(model, "GPU"); +} + +INSTANTIATE_TEST_SUITE_P(CacheDirDotVariants, + GpuCacheDirWithDotsParamTest, + ::testing::Values("/test_encoder/test_encoder.encrypted/", "/test_encoder/test_encoder.encrypted")); + } // namespace