Bitcoin Core 28.99.0
P2P Digital Currency
fs_tests.cpp
Go to the documentation of this file.
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//
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
16
17BOOST_AUTO_TEST_CASE(fsbridge_pathtostring)
18{
19 std::string u8_str = "fs_tests_₿_🏃";
20 std::u8string str8{u8"fs_tests_₿_🏃"};
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);
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
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
47BOOST_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};
55 file << "bitcoin";
56 }
57 {
58 std::ifstream file{tmpfile2};
59 std::string input_buffer;
60 file >> input_buffer;
61 BOOST_CHECK_EQUAL(input_buffer, "bitcoin");
62 }
63 {
64 std::ifstream file{tmpfile1, 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::ios_base::out | std::ios_base::app};
71 file << "tests";
72 }
73 {
74 std::ifstream file{tmpfile1};
75 std::string input_buffer;
76 file >> input_buffer;
77 BOOST_CHECK_EQUAL(input_buffer, "bitcointests");
78 }
79 {
80 std::ofstream file{tmpfile2, std::ios_base::out | std::ios_base::trunc};
81 file << "bitcoin";
82 }
83 {
84 std::ifstream file{tmpfile1};
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
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};
120 file << path1_contents;
121 }
122
123 {
124 std::ofstream file{path2};
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};
135 std::string contents;
136 file >> contents;
137 BOOST_CHECK_EQUAL(contents, path1_contents);
138 }
139 fs::remove(path2);
140}
141
142#ifndef __MINGW64__ // no symlinks on mingw
144{
145 // Test fs::create_directories workaround.
146 const fs::path tmpfolder{m_args.GetDataDirBase()};
147
148 const fs::path dir{tmpfolder / "a"};
149 fs::create_directory(dir);
151 BOOST_CHECK(fs::is_directory(dir));
153
154 const fs::path symlink{tmpfolder / "b"};
155 fs::create_directory_symlink(dir, symlink);
156 BOOST_CHECK(fs::exists(symlink));
157 BOOST_CHECK(fs::is_symlink(symlink));
158 BOOST_CHECK(fs::is_directory(symlink));
160
161 fs::remove(symlink);
162 fs::remove(dir);
163}
164#endif // __MINGW64__
165
Path class wrapper to block calls to the fs::path(std::string) implicit constructor and the fs::path:...
Definition: fs.h:33
unsigned char u8
BOOST_FIXTURE_TEST_SUITE(cuckoocache_tests, BasicTestingSetup)
Test Suite for CuckooCache.
BOOST_AUTO_TEST_SUITE_END()
bool RenameOver(fs::path src, fs::path dest)
Rename src to dest.
Definition: fs_helpers.cpp:249
BOOST_AUTO_TEST_CASE(fsbridge_pathtostring)
Definition: fs_tests.cpp:17
static path u8path(const std::string &utf8_str)
Definition: fs.h:75
static bool create_directories(const std::filesystem::path &p)
Create directory (and if necessary its parents), unless the leaf directory already exists or is a sym...
Definition: fs.h:190
static bool exists(const path &p)
Definition: fs.h:89
static std::string PathToString(const path &path)
Convert path object to a byte string.
Definition: fs.h:151
static path PathFromString(const std::string &string)
Convert byte string to path object.
Definition: fs.h:174
fs::path AbsPathJoin(const fs::path &base, const fs::path &path)
Helper function for joining two paths.
Definition: fs.cpp:36
#define BOOST_CHECK_EQUAL(v1, v2)
Definition: object.cpp:18
#define BOOST_CHECK(expr)
Definition: object.cpp:17
Basic testing setup.
Definition: setup_common.h:63