copy_file_large.pass.cpp (3276B)
1 //===----------------------------------------------------------------------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is dual licensed under the MIT and the University of Illinois Open 6 // Source Licenses. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 // UNSUPPORTED: c++98, c++03 11 // REQUIRES: long_tests 12 13 // <filesystem> 14 15 // bool copy_file(const path& from, const path& to); 16 // bool copy_file(const path& from, const path& to, error_code& ec) noexcept; 17 // bool copy_file(const path& from, const path& to, copy_options options); 18 // bool copy_file(const path& from, const path& to, copy_options options, 19 // error_code& ec) noexcept; 20 21 #include "filesystem_include.hpp" 22 #include <type_traits> 23 #include <chrono> 24 #include <cassert> 25 26 #include "test_macros.h" 27 #include "rapid-cxx-test.hpp" 28 #include "filesystem_test_helper.hpp" 29 30 using namespace fs; 31 32 TEST_SUITE(filesystem_copy_file_test_suite) 33 34 static std::string random_hex_chars(uintmax_t size) { 35 std::string data; 36 data.reserve(size); 37 for (uintmax_t I = 0; I < size; ++I) 38 data.push_back(random_utils::random_hex_char()); 39 return data; 40 } 41 42 // This test is intended to test 'sendfile's 2gb limit for a single call, and 43 // to ensure that libc++ correctly copies files larger than that limit. 44 // However it requires allocating ~5GB of filesystem space. This might not 45 // be acceptable on all systems. 46 TEST_CASE(large_file) { 47 using namespace fs; 48 constexpr uintmax_t sendfile_size_limit = 2147479552ull; 49 constexpr uintmax_t additional_size = 1024; 50 constexpr uintmax_t test_file_size = sendfile_size_limit + additional_size; 51 static_assert(test_file_size > sendfile_size_limit, ""); 52 53 scoped_test_env env; 54 55 // Check that we have more than sufficient room to create the files needed 56 // to perform the test. 57 if (space(env.test_root).available < 3 * test_file_size) { 58 TEST_UNSUPPORTED(); 59 } 60 61 // Use python to create a file right at the size limit. 62 const path file = env.create_file("source", sendfile_size_limit); 63 // Create some random data that looks different than the data before the 64 // size limit. 65 const std::string additional_data = random_hex_chars(additional_size); 66 // Append this known data to the end of the source file. 67 { 68 std::ofstream outf(file.native(), std::ios_base::app); 69 TEST_REQUIRE(outf.good()); 70 outf << additional_data; 71 TEST_REQUIRE(outf); 72 } 73 TEST_REQUIRE(file_size(file) == test_file_size); 74 const path dest = env.make_env_path("dest"); 75 76 std::error_code ec = GetTestEC(); 77 TEST_CHECK(copy_file(file, dest, ec)); 78 TEST_CHECK(!ec); 79 80 TEST_REQUIRE(is_regular_file(dest)); 81 TEST_CHECK(file_size(dest) == test_file_size); 82 83 // Read the data from the end of the destination file, and ensure it matches 84 // the data at the end of the source file. 85 std::string out_data; 86 out_data.reserve(additional_size); 87 { 88 std::ifstream dest_file(dest.native()); 89 TEST_REQUIRE(dest_file); 90 dest_file.seekg(sendfile_size_limit); 91 TEST_REQUIRE(dest_file); 92 dest_file >> out_data; 93 TEST_CHECK(dest_file.eof()); 94 } 95 TEST_CHECK(out_data.size() == additional_data.size()); 96 TEST_CHECK(out_data == additional_data); 97 } 98 99 TEST_SUITE_END()