Branch data Line data Source code
1 : : // Copyright (c) 2011-2022 The Bitcoin Core developers 2 : : // Distributed under the MIT software license, see the accompanying 3 : : // file COPYING or http://www.opensource.org/licenses/mit-license.php. 4 : : // 5 : : #include <test/util/setup_common.h> 6 : : #include <util/fs.h> 7 : : #include <util/fs_helpers.h> 8 : : #include <util/getuniquepath.h> 9 : : 10 : : #include <boost/test/unit_test.hpp> 11 : : 12 : : #include <fstream> 13 : : #include <ios> 14 : : #include <string> 15 : : 16 : 0 : BOOST_FIXTURE_TEST_SUITE(fs_tests, BasicTestingSetup) 17 : : 18 : 0 : BOOST_AUTO_TEST_CASE(fsbridge_pathtostring) 19 : : { 20 : 0 : std::string u8_str = "fs_tests_₿_🏃"; 21 : 0 : BOOST_CHECK_EQUAL(fs::PathToString(fs::PathFromString(u8_str)), u8_str); 22 : 0 : BOOST_CHECK_EQUAL(fs::u8path(u8_str).u8string(), u8_str); 23 : 0 : BOOST_CHECK_EQUAL(fs::PathFromString(u8_str).u8string(), u8_str); 24 : 0 : BOOST_CHECK_EQUAL(fs::PathToString(fs::u8path(u8_str)), u8_str); 25 : : #ifndef WIN32 26 : : // On non-windows systems, verify that arbitrary byte strings containing 27 : : // invalid UTF-8 can be round tripped successfully with PathToString and 28 : : // PathFromString. On non-windows systems, paths are just byte strings so 29 : : // these functions do not do any encoding. On windows, paths are Unicode, 30 : : // and these functions do encoding and decoding, so the behavior of this 31 : : // test would be undefined. 32 : 0 : std::string invalid_u8_str = "\xf0"; 33 : 0 : BOOST_CHECK_EQUAL(invalid_u8_str.size(), 1); 34 : 0 : BOOST_CHECK_EQUAL(fs::PathToString(fs::PathFromString(invalid_u8_str)), invalid_u8_str); 35 : : #endif 36 : 0 : } 37 : : 38 : 0 : BOOST_AUTO_TEST_CASE(fsbridge_stem) 39 : : { 40 : 0 : std::string test_filename = "fs_tests_₿_🏃.dat"; 41 : 0 : std::string expected_stem = "fs_tests_₿_🏃"; 42 : 0 : BOOST_CHECK_EQUAL(fs::PathToString(fs::PathFromString(test_filename).stem()), expected_stem); 43 : 0 : } 44 : : 45 : 0 : BOOST_AUTO_TEST_CASE(fsbridge_fstream) 46 : : { 47 : 0 : fs::path tmpfolder = m_args.GetDataDirBase(); 48 : : // tmpfile1 should be the same as tmpfile2 49 : 0 : fs::path tmpfile1 = tmpfolder / fs::u8path("fs_tests_₿_🏃"); 50 : 0 : fs::path tmpfile2 = tmpfolder / fs::u8path("fs_tests_₿_🏃"); 51 : : { 52 : 0 : std::ofstream file{tmpfile1}; 53 : 0 : file << "bitcoin"; 54 : 0 : } 55 : : { 56 : 0 : std::ifstream file{tmpfile2}; 57 : 0 : std::string input_buffer; 58 : 0 : file >> input_buffer; 59 : 0 : BOOST_CHECK_EQUAL(input_buffer, "bitcoin"); 60 : 0 : } 61 : : { 62 : 0 : std::ifstream file{tmpfile1, std::ios_base::in | std::ios_base::ate}; 63 : 0 : std::string input_buffer; 64 : 0 : file >> input_buffer; 65 : 0 : BOOST_CHECK_EQUAL(input_buffer, ""); 66 : 0 : } 67 : : { 68 : 0 : std::ofstream file{tmpfile2, std::ios_base::out | std::ios_base::app}; 69 : 0 : file << "tests"; 70 : 0 : } 71 : : { 72 : 0 : std::ifstream file{tmpfile1}; 73 : 0 : std::string input_buffer; 74 : 0 : file >> input_buffer; 75 : 0 : BOOST_CHECK_EQUAL(input_buffer, "bitcointests"); 76 : 0 : } 77 : : { 78 : 0 : std::ofstream file{tmpfile2, std::ios_base::out | std::ios_base::trunc}; 79 : 0 : file << "bitcoin"; 80 : 0 : } 81 : : { 82 : 0 : std::ifstream file{tmpfile1}; 83 : 0 : std::string input_buffer; 84 : 0 : file >> input_buffer; 85 : 0 : BOOST_CHECK_EQUAL(input_buffer, "bitcoin"); 86 : 0 : } 87 : : { 88 : : // Join an absolute path and a relative path. 89 : 0 : fs::path p = fsbridge::AbsPathJoin(tmpfolder, fs::u8path("fs_tests_₿_🏃")); 90 : 0 : BOOST_CHECK(p.is_absolute()); 91 : 0 : BOOST_CHECK_EQUAL(tmpfile1, p); 92 : 0 : } 93 : : { 94 : : // Join two absolute paths. 95 : 0 : fs::path p = fsbridge::AbsPathJoin(tmpfile1, tmpfile2); 96 : 0 : BOOST_CHECK(p.is_absolute()); 97 : 0 : BOOST_CHECK_EQUAL(tmpfile2, p); 98 : 0 : } 99 : : { 100 : : // Ensure joining with empty paths does not add trailing path components. 101 : 0 : BOOST_CHECK_EQUAL(tmpfile1, fsbridge::AbsPathJoin(tmpfile1, "")); 102 : 0 : BOOST_CHECK_EQUAL(tmpfile1, fsbridge::AbsPathJoin(tmpfile1, {})); 103 : : } 104 : : { 105 : 0 : fs::path p1 = GetUniquePath(tmpfolder); 106 : 0 : fs::path p2 = GetUniquePath(tmpfolder); 107 : 0 : fs::path p3 = GetUniquePath(tmpfolder); 108 : : 109 : : // Ensure that the parent path is always the same. 110 : 0 : BOOST_CHECK_EQUAL(tmpfolder, p1.parent_path()); 111 : 0 : BOOST_CHECK_EQUAL(tmpfolder, p2.parent_path()); 112 : 0 : BOOST_CHECK_EQUAL(tmpfolder, p3.parent_path()); 113 : : 114 : : // Ensure that generated paths are actually different. 115 : 0 : BOOST_CHECK(p1 != p2); 116 : 0 : BOOST_CHECK(p2 != p3); 117 : 0 : BOOST_CHECK(p1 != p3); 118 : 0 : } 119 : 0 : } 120 : : 121 : 0 : BOOST_AUTO_TEST_CASE(rename) 122 : : { 123 : 0 : const fs::path tmpfolder{m_args.GetDataDirBase()}; 124 : : 125 : 0 : const fs::path path1{GetUniquePath(tmpfolder)}; 126 : 0 : const fs::path path2{GetUniquePath(tmpfolder)}; 127 : : 128 : 0 : const std::string path1_contents{"1111"}; 129 : 0 : const std::string path2_contents{"2222"}; 130 : : 131 : : { 132 : 0 : std::ofstream file{path1}; 133 : 0 : file << path1_contents; 134 : 0 : } 135 : : 136 : : { 137 : 0 : std::ofstream file{path2}; 138 : 0 : file << path2_contents; 139 : 0 : } 140 : : 141 : : // Rename path1 -> path2. 142 : 0 : BOOST_CHECK(RenameOver(path1, path2)); 143 : : 144 : 0 : BOOST_CHECK(!fs::exists(path1)); 145 : : 146 : : { 147 : 0 : std::ifstream file{path2}; 148 : 0 : std::string contents; 149 : 0 : file >> contents; 150 : 0 : BOOST_CHECK_EQUAL(contents, path1_contents); 151 : 0 : } 152 : 0 : fs::remove(path2); 153 : 0 : } 154 : : 155 : : #ifndef __MINGW64__ // no symlinks on mingw 156 : 0 : BOOST_AUTO_TEST_CASE(create_directories) 157 : : { 158 : : // Test fs::create_directories workaround. 159 : 0 : const fs::path tmpfolder{m_args.GetDataDirBase()}; 160 : : 161 : 0 : const fs::path dir{GetUniquePath(tmpfolder)}; 162 : 0 : fs::create_directory(dir); 163 : 0 : BOOST_CHECK(fs::exists(dir)); 164 : 0 : BOOST_CHECK(fs::is_directory(dir)); 165 : 0 : BOOST_CHECK(!fs::create_directories(dir)); 166 : : 167 : 0 : const fs::path symlink{GetUniquePath(tmpfolder)}; 168 : 0 : fs::create_directory_symlink(dir, symlink); 169 : 0 : BOOST_CHECK(fs::exists(symlink)); 170 : 0 : BOOST_CHECK(fs::is_symlink(symlink)); 171 : 0 : BOOST_CHECK(fs::is_directory(symlink)); 172 : 0 : BOOST_CHECK(!fs::create_directories(symlink)); 173 : : 174 : 0 : fs::remove(symlink); 175 : 0 : fs::remove(dir); 176 : 0 : } 177 : : #endif // __MINGW64__ 178 : : 179 : 0 : BOOST_AUTO_TEST_SUITE_END()