fs_tests.cpp
1 // Copyright (c) 2011-present 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 9 #include <boost/test/unit_test.hpp> 10 11 #include <fstream> 12 #include <ios> 13 #include <string> 14 15 BOOST_FIXTURE_TEST_SUITE(fs_tests, BasicTestingSetup) 16 17 BOOST_AUTO_TEST_CASE(fsbridge_pathtostring) 18 { 19 std::string u8_str = "fs_tests_₿_🏃"; 20 std::u8string str8{u8"fs_tests_₿_🏃"}; 21 BOOST_CHECK_EQUAL(fs::PathToString(fs::PathFromString(u8_str)), u8_str); 22 BOOST_CHECK_EQUAL(fs::u8path(u8_str).utf8string(), u8_str); 23 BOOST_CHECK_EQUAL(fs::path(str8).utf8string(), u8_str); 24 BOOST_CHECK(fs::path(str8).u8string() == str8); 25 BOOST_CHECK_EQUAL(fs::PathFromString(u8_str).utf8string(), u8_str); 26 BOOST_CHECK_EQUAL(fs::PathToString(fs::u8path(u8_str)), u8_str); 27 #ifndef WIN32 28 // On non-windows systems, verify that arbitrary byte strings containing 29 // invalid UTF-8 can be round tripped successfully with PathToString and 30 // PathFromString. On non-windows systems, paths are just byte strings so 31 // these functions do not do any encoding. On windows, paths are Unicode, 32 // and these functions do encoding and decoding, so the behavior of this 33 // test would be undefined. 34 std::string invalid_u8_str = "\xf0"; 35 BOOST_CHECK_EQUAL(invalid_u8_str.size(), 1); 36 BOOST_CHECK_EQUAL(fs::PathToString(fs::PathFromString(invalid_u8_str)), invalid_u8_str); 37 #endif 38 } 39 40 BOOST_AUTO_TEST_CASE(fsbridge_stem) 41 { 42 std::string test_filename = "fs_tests_₿_🏃.dat"; 43 std::string expected_stem = "fs_tests_₿_🏃"; 44 BOOST_CHECK_EQUAL(fs::PathToString(fs::PathFromString(test_filename).stem()), expected_stem); 45 } 46 47 BOOST_AUTO_TEST_CASE(fsbridge_fstream) 48 { 49 fs::path tmpfolder = m_args.GetDataDirBase(); 50 // tmpfile1 should be the same as tmpfile2 51 fs::path tmpfile1 = tmpfolder / fs::u8path("fs_tests_₿_🏃"); 52 fs::path tmpfile2 = tmpfolder / fs::path(u8"fs_tests_₿_🏃"); 53 { 54 std::ofstream file{tmpfile1.std_path()}; 55 file << "bitcoin"; 56 } 57 { 58 std::ifstream file{tmpfile2.std_path()}; 59 std::string input_buffer; 60 file >> input_buffer; 61 BOOST_CHECK_EQUAL(input_buffer, "bitcoin"); 62 } 63 { 64 std::ifstream file{tmpfile1.std_path(), std::ios_base::in | std::ios_base::ate}; 65 std::string input_buffer; 66 file >> input_buffer; 67 BOOST_CHECK_EQUAL(input_buffer, ""); 68 } 69 { 70 std::ofstream file{tmpfile2.std_path(), std::ios_base::out | std::ios_base::app}; 71 file << "tests"; 72 } 73 { 74 std::ifstream file{tmpfile1.std_path()}; 75 std::string input_buffer; 76 file >> input_buffer; 77 BOOST_CHECK_EQUAL(input_buffer, "bitcointests"); 78 } 79 { 80 std::ofstream file{tmpfile2.std_path(), std::ios_base::out | std::ios_base::trunc}; 81 file << "bitcoin"; 82 } 83 { 84 std::ifstream file{tmpfile1.std_path()}; 85 std::string input_buffer; 86 file >> input_buffer; 87 BOOST_CHECK_EQUAL(input_buffer, "bitcoin"); 88 } 89 { 90 // Join an absolute path and a relative path. 91 fs::path p = fsbridge::AbsPathJoin(tmpfolder, fs::u8path("fs_tests_₿_🏃")); 92 BOOST_CHECK(p.is_absolute()); 93 BOOST_CHECK_EQUAL(tmpfile1, p); 94 } 95 { 96 // Join two absolute paths. 97 fs::path p = fsbridge::AbsPathJoin(tmpfile1, tmpfile2); 98 BOOST_CHECK(p.is_absolute()); 99 BOOST_CHECK_EQUAL(tmpfile2, p); 100 } 101 { 102 // Ensure joining with empty paths does not add trailing path components. 103 BOOST_CHECK_EQUAL(tmpfile1, fsbridge::AbsPathJoin(tmpfile1, "")); 104 BOOST_CHECK_EQUAL(tmpfile1, fsbridge::AbsPathJoin(tmpfile1, {})); 105 } 106 } 107 108 BOOST_AUTO_TEST_CASE(rename) 109 { 110 const fs::path tmpfolder{m_args.GetDataDirBase()}; 111 112 const fs::path path1{tmpfolder / "a"}; 113 const fs::path path2{tmpfolder / "b"}; 114 115 const std::string path1_contents{"1111"}; 116 const std::string path2_contents{"2222"}; 117 118 { 119 std::ofstream file{path1.std_path()}; 120 file << path1_contents; 121 } 122 123 { 124 std::ofstream file{path2.std_path()}; 125 file << path2_contents; 126 } 127 128 // Rename path1 -> path2. 129 BOOST_CHECK(RenameOver(path1, path2)); 130 131 BOOST_CHECK(!fs::exists(path1)); 132 133 { 134 std::ifstream file{path2.std_path()}; 135 std::string contents; 136 file >> contents; 137 BOOST_CHECK_EQUAL(contents, path1_contents); 138 } 139 fs::remove(path2); 140 } 141 142 BOOST_AUTO_TEST_SUITE_END()