https://gcc.gnu.org/g:a40655524e12497378baeb3cc9fb4de12da8ca08
commit r16-7876-ga40655524e12497378baeb3cc9fb4de12da8ca08 Author: Adam Wood <[email protected]> Date: Wed Jan 28 19:08:25 2026 -0700 libstdc++: Add filesystem::copy_symlink tests [PR122217] libstdc++-v3/Changelog: PR libstdc++/122217 * testsuite/27_io/filesystem/operations/copy_symlink/1.cc: New test. * testsuite/27_io/filesystem/operations/copy_symlink/2.cc: New test. * testsuite/27_io/filesystem/operations/copy_symlink/3.cc: New test. * testsuite/27_io/filesystem/operations/copy_symlink/4.cc: New test. Diff: --- .../27_io/filesystem/operations/copy_symlink/1.cc | 63 ++++++++++++++++++++++ .../27_io/filesystem/operations/copy_symlink/2.cc | 43 +++++++++++++++ .../27_io/filesystem/operations/copy_symlink/3.cc | 47 ++++++++++++++++ .../27_io/filesystem/operations/copy_symlink/4.cc | 44 +++++++++++++++ 4 files changed, 197 insertions(+) diff --git a/libstdc++-v3/testsuite/27_io/filesystem/operations/copy_symlink/1.cc b/libstdc++-v3/testsuite/27_io/filesystem/operations/copy_symlink/1.cc new file mode 100644 index 000000000000..e04b2672e6dd --- /dev/null +++ b/libstdc++-v3/testsuite/27_io/filesystem/operations/copy_symlink/1.cc @@ -0,0 +1,63 @@ +// { dg-do run { target c++17 } } +// { dg-require-filesystem-ts "" } + +#include <filesystem> +#include <testsuite_hooks.h> +#include <testsuite_fs.h> + +// Test successful copies + +namespace fs = std::filesystem; + +void +test_successful_copy(const fs::path& p, + bool (*is_some_file_type)(const fs::path&)) +{ + const std::error_code bad_ec = make_error_code(std::errc::invalid_argument); + std::error_code ec; + + auto to1 = read_symlink(p); + + auto p2 = __gnu_test::nonexistent_path(); + ec = bad_ec; + copy_symlink(p, p2, ec); + VERIFY( !ec ); + VERIFY( exists(symlink_status(p2)) ); + VERIFY( is_symlink(p2) ); + VERIFY( is_some_file_type(p2) ); + auto to2 = read_symlink(p2); + VERIFY( to1 == to2 ); + + // Copy again without ec + remove(p2); + copy_symlink(p, p2); + VERIFY( exists(symlink_status(p2)) ); + VERIFY( is_symlink(p2) ); + VERIFY( is_some_file_type(p2) ); + to2 = read_symlink(p2); + VERIFY( to1 == to2 ); + + remove(p); + remove(p2); +} + +void +test01() +{ + __gnu_test::scoped_file f; + auto p = __gnu_test::nonexistent_path(); + create_symlink(f.path, p); + test_successful_copy(p, fs::is_regular_file); + + auto dir = __gnu_test::nonexistent_path(); + create_directory(dir); + create_directory_symlink(dir, p); + test_successful_copy(p, fs::is_directory); + remove_all(dir); +} + +int +main() +{ + test01(); +} diff --git a/libstdc++-v3/testsuite/27_io/filesystem/operations/copy_symlink/2.cc b/libstdc++-v3/testsuite/27_io/filesystem/operations/copy_symlink/2.cc new file mode 100644 index 000000000000..27caf4a1d4a0 --- /dev/null +++ b/libstdc++-v3/testsuite/27_io/filesystem/operations/copy_symlink/2.cc @@ -0,0 +1,43 @@ +// { dg-do run { target c++17 } } +// { dg-require-filesystem-ts "" } + +#include <filesystem> +#include <testsuite_hooks.h> +#include <testsuite_fs.h> + +// Test copying into an existing file + +void +test01() +{ + std::error_code ec, ec2; + __gnu_test::scoped_file f, f2; + + auto p = __gnu_test::nonexistent_path(); + create_symlink(f.path, p); + + copy_symlink(p, f2.path, ec); + VERIFY( ec ); + VERIFY( !is_symlink(f2.path) ); + + try + { + copy_symlink(p, f2.path); + } + catch (const std::filesystem::filesystem_error& ex) + { + ec2 = ex.code(); + VERIFY( ex.path1() == p ); + VERIFY( ex.path2() == f2.path ); + } + VERIFY( ec2 == ec ); + VERIFY( !is_symlink(f2.path) ); + + remove(p); +} + +int +main() +{ + test01(); +} diff --git a/libstdc++-v3/testsuite/27_io/filesystem/operations/copy_symlink/3.cc b/libstdc++-v3/testsuite/27_io/filesystem/operations/copy_symlink/3.cc new file mode 100644 index 000000000000..13e9dad20fcb --- /dev/null +++ b/libstdc++-v3/testsuite/27_io/filesystem/operations/copy_symlink/3.cc @@ -0,0 +1,47 @@ +// { dg-do run { target c++17 } } +// { dg-require-filesystem-ts "" } + +#include <filesystem> +#include <testsuite_hooks.h> +#include <testsuite_fs.h> + +// Test copying from a non-symlink + +namespace fs = std::filesystem; + +void +test_copy_from_non_symlink(const fs::path& from) +{ + std::error_code ec, ec2; + auto p = __gnu_test::nonexistent_path(); + copy_symlink(from, p, ec); + VERIFY( ec ); + VERIFY( !is_symlink(p) ); + + try + { + copy_symlink(from, p); + } + catch (const fs::filesystem_error& ex) + { + ec2 = ex.code(); + VERIFY( ex.path1() == from ); + VERIFY( ex.path2() == p ); + } + VERIFY( ec2 == ec ); + VERIFY( !is_symlink(p) ); +} + +void +test01() +{ + __gnu_test::scoped_file f; + test_copy_from_non_symlink(f.path); + test_copy_from_non_symlink(__gnu_test::nonexistent_path()); +} + +int +main() +{ + test01(); +} diff --git a/libstdc++-v3/testsuite/27_io/filesystem/operations/copy_symlink/4.cc b/libstdc++-v3/testsuite/27_io/filesystem/operations/copy_symlink/4.cc new file mode 100644 index 000000000000..2e4f300194ba --- /dev/null +++ b/libstdc++-v3/testsuite/27_io/filesystem/operations/copy_symlink/4.cc @@ -0,0 +1,44 @@ +// { dg-do run { target c++17 } } +// { dg-require-filesystem-ts "" } + +#include <filesystem> +#include <testsuite_hooks.h> +#include <testsuite_fs.h> + +// Test copying into an empty path + +namespace fs = std::filesystem; + +void +test01() +{ + std::error_code ec, ec2; + __gnu_test::scoped_file f, f2; + + auto p = __gnu_test::nonexistent_path(); + create_symlink(f.path, p); + + fs::path empty; + copy_symlink(p, empty, ec); + VERIFY( ec ); + + try + { + copy_symlink(p, empty); + } + catch (const std::filesystem::filesystem_error& ex) + { + ec2 = ex.code(); + VERIFY( ex.path1() == p ); + VERIFY( ex.path2() == empty ); + } + VERIFY( ec2 == ec ); + + remove(p); +} + +int +main() +{ + test01(); +}
