32 #include <gtest/gtest.h>
35 #include <sys/socket.h>
52 using std::system_error;
58 struct FsTest :
public testing::Test
65 fs::remove_all(
"sandbox", &err);
72 fs::remove_all(
"sandbox", &err);
80 struct sockaddr_un addr;
81 addr.sun_family = AF_UNIX;
82 std::strcpy(addr.sun_path,
"sandbox/sock");
83 int fd = socket(PF_UNIX, SOCK_STREAM, 0);
84 bind(fd, (
struct sockaddr*)&addr,
sizeof addr);
89 TEST_F(FsTest, list_current)
91 cout <<
"listing current directory contents" << endl;
93 ASSERT_GT(files.size(), 0);
96 cout << f.first <<
" type: " << f.second << endl;
100 TEST_F(FsTest, list_sandbox)
102 cout <<
"creating sandbox directory files" << endl;
104 cout <<
"listing sandbox directory contents" << endl;
106 ASSERT_GT(files.size(), 0);
107 for (
auto& f : files)
109 cout << f.first <<
" type: " << f.second << endl;
114 static bool reg_filt(
const string& s,
FileType t)
116 if (s ==
"reg" && t == FileType::reg)
126 ASSERT_EQ(files.size(), 1);
127 ASSERT_EQ(files.begin()->first,
"reg");
128 ASSERT_EQ(files.begin()->second, FileType::reg);
138 cout <<
"tmp file: " << n << endl;
142 cout << f.first <<
" type: " << f.second << endl;
144 ASSERT_EQ(d.size(), 2);
145 ASSERT_NE(d.find(
"test"), d.end());
149 ASSERT_EQ(d.size(), 1);
152 fs::remove_all(
"sandbox");
154 ASSERT_EQ(d.find(
"sandbox"), d.end());
156 ASSERT_THROW(
fs::remove(
"sandbox"), system_error);
159 TEST_F(FsTest, create_types)
167 cout <<
"sandbox/" << f.first <<
" type: " << f.second <<
":" << endl;
170 ASSERT_EQ(f.second, ty.type);
176 cout <<
"/dev/zero " << ty << endl;
177 ASSERT_EQ(ty.type, FileType::chr);
181 auto i = std::find_if(d.begin(), d.end(), [](
const auto& x) ->
bool
183 return x.second == FileType::block;
185 ASSERT_NE(i, d.end());
187 cout <<
"/dev/" << i->first <<
" " << ty << endl;
188 ASSERT_EQ(ty.type, FileType::block);
191 TEST_F(FsTest, attributes)
200 const uint64_t NS = 1000000000;
201 const uint64_t DAY = 24*60*60*NS;
204 fs::set_times(
"reg2", st.access_time-DAY, st.mod_time-2*DAY);
210 cout <<
"sandbox/" << f.first <<
" type: " << f.second <<
":" << endl;
216 ASSERT_EQ(streg.mode, 0660);
219 ASSERT_EQ(streg2.mode, 0600);
220 ASSERT_EQ(streg2.access_time, streg.access_time-DAY);
221 ASSERT_EQ(streg2.mod_time, streg.mod_time-2*DAY);
224 ASSERT_EQ(stlink.mode, 0777);
231 TEST(FsExampleTest, sparse_and_trunc)
234 fs::remove_all(
"sandbox", &err);
237 cout <<
"curdir: " << curdir << endl;
241 string s(
"this is a test of the emergency sizing system\n");
242 cout <<
"sparse test with string len=" << s.size() << endl;
244 string fn(
"sparse_file");
246 auto write_sparse = [&fn, &s](off_t loc)
254 lseek(fd, loc, SEEK_SET);
257 cout <<
"wrote " << s.size() <<
" bytes at loc " << loc << endl;
264 cout <<
"12288 hole at start of file:\n" << st << endl;
266 ASSERT_EQ(st.size, 16384);
267 ASSERT_EQ(st.alloc_size, 4096);
270 cout << setw(6) <<
"start" << setw(6) <<
"data" << endl;
273 cout << setw(6) << x.first << setw(6) << x.second << endl;
276 std::map<int64_t,int64_t> ver;
284 cout <<
"8192 hole in middle of file\n" << st << endl;
286 ASSERT_EQ(st.alloc_size, 8192);
289 cout << setw(6) <<
"start" << setw(6) <<
"data" << endl;
292 cout << setw(6) << x.first << setw(6) << x.second << endl;
302 cout <<
"8192 hole at end of file\n" << st << endl;
304 ASSERT_EQ(st.alloc_size, 4096);
307 cout << setw(6) <<
"start" << setw(6) <<
"data" << endl;
310 cout << setw(6) << x.first << setw(6) << x.second << endl;
320 val.resize(s.size(),
'\x01');
321 f.read(&val[0], val.size());
325 fs::remove_all(
"sandbox");
331 auto t = [](
const std::string& b,
const std::string& p) -> std::string
334 cout <<
"base:" <<
">" << b <<
"< path: >" << p <<
"< norm: >" << x <<
"<" << endl;
338 ASSERT_EQ(t(
"",
""),
".");
339 ASSERT_EQ(t(
"",
"."),
".");
340 ASSERT_EQ(t(
".",
""),
".");
341 ASSERT_EQ(t(
".",
"."),
".");
343 ASSERT_EQ(t(
"",
"test/.."),
".");
344 ASSERT_EQ(t(
"",
"test/../.."),
"./..");
346 ASSERT_EQ(t(
"",
"/"),
"/");
347 ASSERT_EQ(t(
"",
"/test"),
"/test");
348 ASSERT_EQ(t(
"",
"/test/"),
"/test/");
349 ASSERT_EQ(t(
"/",
""),
"/");
350 ASSERT_EQ(t(
"/",
"/"),
"/");
352 ASSERT_EQ(t(
"base",
"../../sandbox/../../path"),
"./../../path");
354 ASSERT_EQ(t(
"/base/",
""),
"/base/");
355 ASSERT_EQ(t(
"/base/",
"."),
"/base");
356 ASSERT_EQ(t(
"/base/",
"root"),
"/base/root");
357 ASSERT_EQ(t(
"/base",
"root"),
"/base/root");
358 ASSERT_EQ(t(
"/base/",
"sandbox/rel/path"),
"/base/sandbox/rel/path");
359 ASSERT_EQ(t(
"/base/sandbox",
"../sandbox/path"),
"/base/sandbox/path");
360 ASSERT_EQ(t(
"/base/next/../again",
"sandbox/next/../path"),
"/base/again/sandbox/path");
362 ASSERT_EQ(t(
"",
"sandbox/rel/path"),
"./sandbox/rel/path");
363 ASSERT_EQ(t(
"",
"sandbox/rel/../path"),
"./sandbox/path");
364 ASSERT_EQ(t(
"",
"./sandbox/rel/../path"),
"./sandbox/path");
365 ASSERT_EQ(t(
"",
"/sandbox/path"),
"/sandbox/path");
366 ASSERT_EQ(t(
"",
"/sandbox/path/"),
"/sandbox/path/");
367 ASSERT_EQ(t(
"",
"/sandbox/path"),
"/sandbox/path");
368 ASSERT_EQ(t(
"",
"/base/../sandbox/next/../../path"),
"/path");
369 ASSERT_EQ(t(
"",
"/this/../is/a/big/long/path/../../../../../"),
"/");
371 ASSERT_EQ(t(
"",
"/this/../is/a/path/../../../../."),
"/..");
372 ASSERT_EQ(t(
"../",
"../../sandbox/../../"),
"./../../../../");
Common file system utilities.
static std::string get_current_dir(std::system_error *=nullptr)
Get working directory.
static void create_reg(const std::string &, std::system_error *=nullptr)
Create a regular file.
static std::string norm_path(const std::string &, const std::string &) noexcept
Normalize a path with base directory.
static void create_symlink(const std::string &, const std::string &, std::system_error *=nullptr)
Create a symbolic link.
static void create_link(const std::string &, const std::string &, std::system_error *=nullptr)
Create a hard link.
static void create_fifo(const std::string &, std::system_error *=nullptr)
Create a named pipe (FIFO).
static std::map< std::string, FileType > scan_dir(const std::string &, std::function< bool(const std::string &, FileType)>=default_scan_filter, std::system_error *=nullptr)
Scan a directory, and return a map of names and file types.
static FileStat file_stat(const std::string &, std::system_error *=nullptr)
Get the file stat.
static std::string read_symlink(const std::string &, std::system_error *=nullptr)
Read the location of a symbolic link target.
static void set_size(const std::string &, off_t, std::system_error *=nullptr)
Set the file size.
static std::string create_tmp_reg(const std::string &, std::system_error *=nullptr)
Create a temporary regular file.
static void change_dir(const std::string &, std::system_error *=nullptr)
Change working directory.
static void remove(const std::string &, std::system_error *=nullptr)
Remove the file or directory.
static std::map< off_t, off_t > sparse_map(const std::string &, std::system_error *=nullptr)
Map of file sparseness.
static void create_dir(const std::string &, std::system_error *=nullptr)
Create a directory.
static void set_mode(const std::string &, unsigned, std::system_error *=nullptr)
Set the file mode.
static void set_times(const std::string &, uint64_t, uint64_t, std::system_error *=nullptr)
Set the file times.
Common file system utilities.
int safe_close(int fd)
Signal safe close.
ssize_t safe_write_throw(int fd, const void *buf, size_t count)
Signal safe write, throws system_error on error.
int safe_open_throw(const char *pathname, int flags)
Signal safe open, throws system_error on error.
Signal-safe C library wrapper.
TEST_F(FsTest, create_and_delete)
[Scan directory]
TEST(FsExampleTest, sparse_and_trunc)
[Sparse file]