blob: 16ebb75f8cfb01bb73688afa3843379c7aaf1c92 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
|
#define ENABLE_IMPLICIT_FILEPATH_CONVERSIONS
#include "3rd-party/catch.hpp"
#include "filepath.h"
using namespace newsboat;
TEST_CASE("Can be constructed from a string and converted back into a string",
"[Filepath]")
{
const auto example = Filepath::from_locale_string("/etc/hosts");
REQUIRE(example.to_locale_string() == "/etc/hosts");
}
TEST_CASE("Can be constructed from non-Unicode data", "[Filepath]")
{
// See Table 3-7 "Well-Formed UTF-8 Byte Sequences"
// https://www.unicode.org/versions/Unicode15.0.0/ch03.pdf#G27506
const std::string input("/invalid: \x81\x82 but it's fine");
const auto filepath = Filepath::from_locale_string(input);
REQUIRE(filepath.to_locale_string() == input);
}
TEST_CASE("Can be displayed even if it contains non-Unicode characters", "[Filepath]")
{
// See Table 3-7 "Well-Formed UTF-8 Byte Sequences"
// https://www.unicode.org/versions/Unicode15.0.0/ch03.pdf#G27506
const std::string input("/invalid: \x80 but it's fine");
const auto filepath = Filepath::from_locale_string(input);
// 0xef 0xbf 0xbd is UTF-8 encoding of U+FFFD REPLACEMENT CHARACTER
REQUIRE(filepath.display() == "/invalid: \xEF\xBF\xBD but it's fine");
}
TEST_CASE("push() adds a new component to the path", "[Filepath]")
{
auto dir = Filepath::from_locale_string("/tmp");
dir.push(Filepath::from_locale_string("newsboat"));
REQUIRE(dir == Filepath::from_locale_string("/tmp/newsboat"));
dir.push(Filepath::from_locale_string(".local/share/cache/cache.db"));
REQUIRE(dir == Filepath::from_locale_string("/tmp/newsboat/.local/share/cache/cache.db"));
}
TEST_CASE("Can be extended with join()", "[Filepath]")
{
const auto tmp = Filepath::from_locale_string("/tmp");
const auto subdir = tmp.join("newsboat").join("tests");
REQUIRE(subdir == Filepath::from_locale_string("/tmp/newsboat/tests"));
}
TEST_CASE("Can be copied", "[Filepath]")
{
auto original = Filepath::from_locale_string("/etc/hosts");
const auto check = [&original](const Filepath& copy) {
REQUIRE(original == copy);
REQUIRE(original.display() == "/etc/hosts");
// Demonstrate that changing the original object doesn't modify the copy
original.push(Filepath::from_locale_string(" a bit more"));
REQUIRE(original.display() == "/etc/hosts/ a bit more");
REQUIRE(copy.display() == "/etc/hosts");
};
SECTION("with copy constructor") {
const Filepath copy(original);
check(copy);
}
SECTION("with copy assignment operator") {
const Filepath copy = original;
check(copy);
}
}
TEST_CASE("Can't set extension for an empty path", "[Filepath]")
{
Filepath path;
REQUIRE_FALSE(path.set_extension("exe"));
}
TEST_CASE("Can set extension for non-empty path", "[Filepath]")
{
Filepath path("file");
SECTION("extension is UTF-8") {
REQUIRE(path.set_extension("exe"));
REQUIRE(path == "file.exe");
}
SECTION("extension is not a valid UTF-8 string") {
REQUIRE(path.set_extension("\x80"));
REQUIRE(path == Filepath::from_locale_string("file.\x80"));
}
}
TEST_CASE("Can check if path is absolute", "[Filepath]")
{
Filepath path;
SECTION("empty path is not absolute") {
REQUIRE_FALSE(path.is_absolute());
}
SECTION("path that starts with a slash is absolute") {
path.push("/etc");
REQUIRE(path.display() == "/etc");
REQUIRE(path.is_absolute());
path.push("ca-certificates");
REQUIRE(path.display() == "/etc/ca-certificates");
REQUIRE(path.is_absolute());
}
SECTION("path that doesn't start with a slash is not absolute") {
path.push("vmlinuz");
REQUIRE(path.display() == "vmlinuz");
REQUIRE_FALSE(path.is_absolute());
path.push("undefined");
REQUIRE(path.display() == "vmlinuz/undefined");
REQUIRE_FALSE(path.is_absolute());
}
}
TEST_CASE("Can check if path starts with a given base path", "[Filepath]")
{
SECTION("Empty path") {
const Filepath path;
SECTION("Base path is empty") {
REQUIRE(path.starts_with(Filepath{}));
}
SECTION("Base path is not empty") {
REQUIRE_FALSE(path.starts_with(Filepath::from_locale_string("/etc")));
}
}
SECTION("Non-empty path that doesn't start with the base") {
const auto path = Filepath::from_locale_string("/etcetera");
const auto base = Filepath::from_locale_string("/etc");
REQUIRE_FALSE(path.starts_with(base));
}
SECTION("Non-empty path that starts with the base") {
const auto path = Filepath::from_locale_string("/usr/local/bin/newsboat");
const auto base = Filepath::from_locale_string("/usr/local");
REQUIRE(path.starts_with(base));
}
SECTION("Base is not a valid UTF-8 string") {
const auto path = Filepath::from_locale_string("/test\x81\x82/foobar");
SECTION("Path doesn't start with base") {
const auto base = Filepath::from_locale_string("baz\x80quux");
REQUIRE_FALSE(path.starts_with(base));
}
SECTION("Path starts with base") {
const auto base = Filepath::from_locale_string("/test\x81\x82/");
REQUIRE(path.starts_with(base));
}
}
}
TEST_CASE("Can extract the final component of the path (file or directory name)",
"[Filepath]")
{
SECTION("Empty path has no final component") {
const Filepath path;
REQUIRE(path.file_name() == nonstd::nullopt);
}
SECTION("The final component of a path with single level is the path itself") {
const auto path = Filepath::from_locale_string("hello");
REQUIRE(path.file_name().value() == path);
}
SECTION("Multi-level path") {
const auto path = Filepath::from_locale_string("/dev/pts/0");
REQUIRE(path.file_name().value() == Filepath::from_locale_string("0"));
}
SECTION("Final component is not a valid UTF-8 string") {
const auto path = Filepath::from_locale_string("/whatever/one\x80two");
REQUIRE(path.file_name().value() == Filepath::from_locale_string("one\x80two"));
}
}
|