fs_tests.cpp raw
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()
143