brintos

brintos / llvm-project-archived public Read only

0
0
Text · 10.0 KiB · 1c5c1f4 Raw
334 lines · cpp
1//===----------------------------------------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9// REQUIRES: can-create-symlinks10// UNSUPPORTED: c++03, c++11, c++1411// UNSUPPORTED: no-filesystem12 13// Starting in Android N (API 24), SELinux policy prevents the shell user from14// creating a FIFO file.15// XFAIL: LIBCXX-ANDROID-FIXME && !android-device-api={{21|22|23}}16 17// <filesystem>18 19// void copy(const path& from, const path& to);20// void copy(const path& from, const path& to, error_code& ec);21// void copy(const path& from, const path& to, copy_options options);22// void copy(const path& from, const path& to, copy_options options,23//           error_code& ec);24 25#include <filesystem>26#include <type_traits>27#include <cstddef>28#include <cassert>29 30#include "test_macros.h"31#include "filesystem_test_helper.h"32namespace fs = std::filesystem;33using namespace fs;34 35using CO = fs::copy_options;36 37static void signature_test()38{39    const path p; ((void)p);40    std::error_code ec; ((void)ec);41    const copy_options opts{}; ((void)opts);42    ASSERT_NOT_NOEXCEPT(fs::copy(p, p));43    ASSERT_NOT_NOEXCEPT(fs::copy(p, p, ec));44    ASSERT_NOT_NOEXCEPT(copy(p, p, opts));45    ASSERT_NOT_NOEXCEPT(copy(p, p, opts, ec));46}47 48// There are 4 cases is the proposal for absolute path.49// Each scope tests one of the cases.50static void test_error_reporting()51{52    auto checkThrow = [](path const& f, path const& t, const std::error_code& ec)53    {54#ifndef TEST_HAS_NO_EXCEPTIONS55        try {56            fs::copy(f, t);57            return false;58        } catch (filesystem_error const& err) {59            return err.path1() == f60                && err.path2() == t61                && err.code() == ec;62        }63#else64        ((void)f); ((void)t); ((void)ec);65        return true;66#endif67    };68 69    static_test_env static_env;70    scoped_test_env env;71    const path file = env.create_file("file1", 42);72    const path dir = env.create_dir("dir");73#ifndef _WIN3274    const path fifo = env.create_fifo("fifo");75    assert(is_other(fifo));76#endif77 78    const auto test_ec = GetTestEC();79 80    // !exists(f)81    {82        std::error_code ec = test_ec;83        const path f = static_env.DNE;84        const path t = env.test_root;85        fs::copy(f, t, ec);86        assert(ec);87        assert(ec != test_ec);88        assert(checkThrow(f, t, ec));89    }90    { // equivalent(f, t) == true91        std::error_code ec = test_ec;92        fs::copy(file, file, ec);93        assert(ec);94        assert(ec != test_ec);95        assert(checkThrow(file, file, ec));96    }97    { // is_directory(from) && is_file(to)98        std::error_code ec = test_ec;99        fs::copy(dir, file, ec);100        assert(ec);101        assert(ec != test_ec);102        assert(checkThrow(dir, file, ec));103    }104#ifndef _WIN32105    { // is_other(from)106        std::error_code ec = test_ec;107        fs::copy(fifo, dir, ec);108        assert(ec);109        assert(ec != test_ec);110        assert(checkThrow(fifo, dir, ec));111    }112    { // is_other(to)113        std::error_code ec = test_ec;114        fs::copy(file, fifo, ec);115        assert(ec);116        assert(ec != test_ec);117        assert(checkThrow(file, fifo, ec));118    }119#endif120}121 122static void from_is_symlink()123{124    scoped_test_env env;125    const path file = env.create_file("file", 42);126    const path symlink = env.create_symlink(file, "sym");127    const path dne = env.make_env_path("dne");128 129    { // skip symlinks130        std::error_code ec = GetTestEC();131        fs::copy(symlink, dne, copy_options::skip_symlinks, ec);132        assert(!ec);133        assert(!exists(dne));134    }135    {136        const path dest = env.make_env_path("dest");137        std::error_code ec = GetTestEC();138        fs::copy(symlink, dest, copy_options::copy_symlinks, ec);139        assert(!ec);140        assert(exists(dest));141        assert(is_symlink(dest));142    }143    { // copy symlink but target exists144        std::error_code ec = GetTestEC();145        fs::copy(symlink, file, copy_options::copy_symlinks, ec);146        assert(ec);147        assert(ec != GetTestEC());148    }149    { // create symlinks but target exists150        std::error_code ec = GetTestEC();151        fs::copy(symlink, file, copy_options::create_symlinks, ec);152        assert(ec);153        assert(ec != GetTestEC());154    }155}156 157static void from_is_regular_file()158{159    scoped_test_env env;160    const path file = env.create_file("file", 42);161    const path dir = env.create_dir("dir");162    { // skip copy because of directory163        const path dest = env.make_env_path("dest1");164        std::error_code ec = GetTestEC();165        fs::copy(file, dest, CO::directories_only, ec);166        assert(!ec);167        assert(!exists(dest));168    }169    { // create symlink to file170        const path dest = env.make_env_path("sym");171        std::error_code ec = GetTestEC();172        fs::copy(file, dest, CO::create_symlinks, ec);173        assert(!ec);174        assert(is_symlink(dest));175        assert(equivalent(file, canonical(dest)));176    }177    { // create hard link to file178        const path dest = env.make_env_path("hardlink");179        assert(hard_link_count(file) == 1);180        std::error_code ec = GetTestEC();181        fs::copy(file, dest, CO::create_hard_links, ec);182        assert(!ec);183        assert(exists(dest));184        assert(hard_link_count(file) == 2);185    }186    { // is_directory(t)187        const path dest_dir = env.create_dir("dest_dir");188        const path expect_dest = dest_dir / file.filename();189        std::error_code ec = GetTestEC();190        fs::copy(file, dest_dir, ec);191        assert(!ec);192        assert(is_regular_file(expect_dest));193    }194    { // otherwise copy_file(from, to, ...)195        const path dest = env.make_env_path("file_copy");196        std::error_code ec = GetTestEC();197        fs::copy(file, dest, ec);198        assert(!ec);199        assert(is_regular_file(dest));200    }201}202 203static void from_is_directory()204{205    struct FileInfo {206        path filename;207        std::size_t size;208    };209    const FileInfo files[] = {210        {"file1", 0},211        {"file2", 42},212        {"file3", 300}213    };214    scoped_test_env env;215    const path dir = env.create_dir("dir");216    const path nested_dir_name = "dir2";217    const path nested_dir = env.create_dir("dir/dir2");218 219    for (auto& FI : files) {220        env.create_file(dir / FI.filename, FI.size);221        env.create_file(nested_dir / FI.filename, FI.size);222    }223    { // test for non-existent directory224        const path dest = env.make_env_path("dest_dir1");225        std::error_code ec = GetTestEC();226        fs::copy(dir, dest, ec);227        assert(!ec);228        assert(is_directory(dest));229        for (auto& FI : files) {230            path created = dest / FI.filename;231            assert(is_regular_file(created));232            assert(file_size(created) == FI.size);233        }234        assert(!is_directory(dest / nested_dir_name));235    }236    { // test for existing directory237        const path dest = env.create_dir("dest_dir2");238        std::error_code ec = GetTestEC();239        fs::copy(dir, dest, ec);240        assert(!ec);241        assert(is_directory(dest));242        for (auto& FI : files) {243            path created = dest / FI.filename;244            assert(is_regular_file(created));245            assert(file_size(created) == FI.size);246        }247        assert(!is_directory(dest / nested_dir_name));248    }249    { // test recursive copy250        const path dest = env.make_env_path("dest_dir3");251        std::error_code ec = GetTestEC();252        fs::copy(dir, dest, CO::recursive, ec);253        assert(!ec);254        assert(is_directory(dest));255        const path nested_dest = dest / nested_dir_name;256        assert(is_directory(nested_dest));257        for (auto& FI : files) {258            path created = dest / FI.filename;259            path nested_created = nested_dest / FI.filename;260            assert(is_regular_file(created));261            assert(file_size(created) == FI.size);262            assert(is_regular_file(nested_created));263            assert(file_size(nested_created) == FI.size);264        }265    }266}267 268static void test_copy_symlinks_to_symlink_dir()269{270    scoped_test_env env;271    const path file1 = env.create_file("file1", 42);272    const path file2 = env.create_file("file2", 101);273    const path file2_sym = env.create_symlink(file2, "file2_sym");274    const path dir = env.create_dir("dir");275    const path dir_sym = env.create_directory_symlink(dir, "dir_sym");276    {277        std::error_code ec = GetTestEC();278        fs::copy(file1, dir_sym, copy_options::copy_symlinks, ec);279        assert(!ec);280        const path dest = env.make_env_path("dir/file1");281        assert(exists(dest));282        assert(!is_symlink(dest));283        assert(file_size(dest) == 42);284    }285}286 287 288static void test_dir_create_symlink()289{290    scoped_test_env env;291    const path dir = env.create_dir("dir1");292    const path dest = env.make_env_path("dne");293    {294        std::error_code ec = GetTestEC();295        fs::copy(dir, dest, copy_options::create_symlinks, ec);296        assert(ErrorIs(ec, std::errc::is_a_directory));297        assert(!exists(dest));298        assert(!is_symlink(dest));299    }300    {301        std::error_code ec = GetTestEC();302        fs::copy(dir, dest, copy_options::create_symlinks|copy_options::recursive, ec);303        assert(ErrorIs(ec, std::errc::is_a_directory));304        assert(!exists(dest));305        assert(!is_symlink(dest));306    }307}308 309static void test_otherwise_no_effects_clause()310{311    scoped_test_env env;312    const path dir = env.create_dir("dir1");313    { // skip copy because of directory314        const path dest = env.make_env_path("dest1");315        std::error_code ec;316        fs::copy(dir, dest, CO::directories_only, ec);317        assert(!ec);318        assert(!exists(dest));319    }320}321 322int main(int, char**) {323    signature_test();324    test_error_reporting();325    from_is_symlink();326    from_is_regular_file();327    from_is_directory();328    test_copy_symlinks_to_symlink_dir();329    test_dir_create_symlink();330    test_otherwise_no_effects_clause();331 332    return 0;333}334