cosmopolitan/test/libcxx/filesystem_test.cc

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

342 lines
8.1 KiB
C++
Raw Normal View History

#include <chrono>
#include <cstdio>
#include <filesystem>
#include <fstream>
#include <random>
#include <string>
#include <thread>
#define ASSERT(condition) \
if (!(condition)) { \
fprintf(stderr, "%s:%d: test failed: %s\n", __FILE__, __LINE__, \
#condition); \
return 1; \
}
namespace fs = std::filesystem;
fs::path g_temp_path;
fs::path g_orig_path;
std::string g_tmpdir;
void setup() {
g_orig_path = fs::current_path();
fs::path temp_path = fs::temp_directory_path();
auto now = std::chrono::system_clock::now();
auto now_ms = std::chrono::time_point_cast<std::chrono::milliseconds>(now);
auto value = now_ms.time_since_epoch();
long duration = value.count();
std::random_device rd;
std::mt19937 gen(rd());
std::uniform_int_distribution<> dis(0, 999999);
int random_number = dis(gen);
std::string dir_name =
"temp_" + std::to_string(duration) + "_" + std::to_string(random_number);
g_temp_path = temp_path / dir_name;
fs::create_directory(g_temp_path);
fs::current_path(g_temp_path);
fs::create_directory("tmp");
g_tmpdir = fs::absolute("tmp");
setenv("TMPDIR", g_tmpdir.c_str(), true);
}
void teardown() {
fs::current_path(g_orig_path);
fs::remove_all(g_temp_path);
}
int test_create_directory() {
fs::path dir = "test_dir";
ASSERT(fs::create_directory(dir));
ASSERT(fs::is_directory(dir));
ASSERT(!fs::create_directory(dir));
fs::remove(dir);
return 0;
}
int test_create_directories() {
fs::path dirs = "test_dir/nested/deep";
ASSERT(fs::create_directories(dirs));
ASSERT(fs::is_directory(dirs));
ASSERT(!fs::create_directories(dirs));
fs::remove_all("test_dir");
return 0;
}
int test_remove() {
fs::path file = "test_file.txt";
std::ofstream(file).put('a');
ASSERT(fs::remove(file));
ASSERT(!fs::remove(file));
return 0;
}
int test_remove_all() {
fs::path dir = "test_dir/nested/deep";
fs::create_directories(dir);
ASSERT(fs::remove_all("test_dir") > 0);
ASSERT(fs::remove_all("test_dir") == 0);
return 0;
}
int test_rename() {
fs::path old_name = "old.txt";
fs::path new_name = "new.txt";
std::ofstream(old_name).put('a');
fs::rename(old_name, new_name);
ASSERT(!fs::exists(old_name));
ASSERT(fs::exists(new_name));
fs::remove(new_name);
return 0;
}
int test_copy() {
fs::path src = "src.txt";
fs::path dst = "dst.txt";
std::ofstream(src) << "test";
fs::copy(src, dst);
ASSERT(fs::exists(dst));
ASSERT(fs::file_size(src) == fs::file_size(dst));
fs::remove(src);
fs::remove(dst);
return 0;
}
int test_copy_file() {
fs::path src = "src.txt";
fs::path dst = "dst.txt";
std::ofstream(src) << "test";
ASSERT(fs::copy_file(src, dst));
ASSERT(!fs::copy_file(src, dst, fs::copy_options::skip_existing));
fs::remove(src);
fs::remove(dst);
return 0;
}
int test_exists() {
fs::path file = "test.txt";
ASSERT(!fs::exists(file));
std::ofstream(file).put('a');
ASSERT(fs::exists(file));
fs::remove(file);
return 0;
}
int test_is_regular_file() {
fs::path file = "test.txt";
fs::path dir = "test_dir";
std::ofstream(file).put('a');
fs::create_directory(dir);
ASSERT(fs::is_regular_file(file));
ASSERT(!fs::is_regular_file(dir));
fs::remove(file);
fs::remove(dir);
return 0;
}
int test_is_directory() {
fs::path file = "test.txt";
fs::path dir = "test_dir";
std::ofstream(file).put('a');
fs::create_directory(dir);
ASSERT(!fs::is_directory(file));
ASSERT(fs::is_directory(dir));
fs::remove(file);
fs::remove(dir);
return 0;
}
int test_is_symlink() {
fs::path file = "test.txt";
fs::path link = "test_link";
std::ofstream(file).put('a');
fs::create_symlink(file, link);
ASSERT(!fs::is_symlink(file));
ASSERT(fs::is_symlink(link));
fs::remove(file);
fs::remove(link);
return 0;
}
int test_file_size() {
fs::path file = "test.txt";
std::ofstream(file) << "test";
ASSERT(fs::file_size(file) == 4);
fs::remove(file);
return 0;
}
int test_last_write_time() {
fs::path file = "test.txt";
auto now = fs::file_time_type::clock::now();
std::ofstream(file).put('a');
fs::last_write_time(file, now);
ASSERT(fs::last_write_time(file) == now);
fs::remove(file);
return 0;
}
int test_permissions() {
fs::path file = "test.txt";
std::ofstream(file).put('a');
fs::permissions(file, fs::perms::owner_read | fs::perms::owner_write);
auto perms = fs::status(file).permissions();
ASSERT((perms & fs::perms::owner_read) != fs::perms::none);
ASSERT((perms & fs::perms::owner_write) != fs::perms::none);
ASSERT((perms & fs::perms::owner_exec) == fs::perms::none);
fs::remove(file);
return 0;
}
int test_current_path() {
auto original_path = fs::current_path();
fs::path new_path = fs::temp_directory_path();
fs::current_path(new_path);
ASSERT(fs::current_path() == new_path);
fs::current_path(original_path);
return 0;
}
int test_absolute() {
fs::path relative = "test.txt";
auto abs_path = fs::absolute(relative);
ASSERT(abs_path.is_absolute());
return 0;
}
int test_canonical() {
fs::path dir = "test_dir";
fs::path file = dir / "test.txt";
fs::create_directories(dir);
std::ofstream(file).put('a');
auto can_path = fs::canonical(file);
ASSERT(can_path.is_absolute());
ASSERT(!can_path.lexically_normal().string().empty());
fs::remove_all(dir);
return 0;
}
int test_read_symlink() {
fs::path file = "test.txt";
fs::path link = "test_link";
std::ofstream(file).put('a');
fs::create_symlink(file, link);
ASSERT(fs::read_symlink(link) == file);
fs::remove(file);
fs::remove(link);
return 0;
}
int test_create_symlink_and_hard_link() {
fs::path file = "test.txt";
fs::path symlink = "test_symlink";
fs::path hardlink = "test_hardlink";
std::ofstream(file).put('a');
fs::create_symlink(file, symlink);
fs::create_hard_link(file, hardlink);
ASSERT(fs::exists(symlink));
ASSERT(fs::exists(hardlink));
ASSERT(fs::is_symlink(symlink));
ASSERT(!fs::is_symlink(hardlink));
fs::remove(file);
fs::remove(symlink);
fs::remove(hardlink);
return 0;
}
int test_space() {
auto space_info = fs::space(".");
ASSERT(space_info.capacity > 0);
ASSERT(space_info.free > 0);
ASSERT(space_info.available > 0);
return 0;
}
int test_equivalent() {
fs::path file1 = "test1.txt";
fs::path file2 = "test2.txt";
std::ofstream(file1).put('a');
fs::create_hard_link(file1, file2);
ASSERT(fs::equivalent(file1, file2));
fs::remove(file1);
fs::remove(file2);
return 0;
}
int test_resize_file() {
fs::path file = "test.txt";
std::ofstream(file) << "test";
fs::resize_file(file, 10);
ASSERT(fs::file_size(file) == 10);
fs::remove(file);
return 0;
}
int test_status() {
fs::path file = "test.txt";
std::ofstream(file).put('a');
auto status = fs::status(file);
ASSERT(status.type() == fs::file_type::regular);
fs::remove(file);
return 0;
}
int test_copy_enoent() {
fs::path src = "non_existent_file.txt";
fs::path dst = "destination.txt";
try {
fs::copy(src, dst);
ASSERT(false);
} catch (const fs::filesystem_error& e) {
if (e.code() == std::errc::no_such_file_or_directory) {
return 0;
} else {
ASSERT(false);
}
} catch (const std::exception& e) {
ASSERT(false);
}
}
#define RUN(func) \
result = func(); \
if (result) \
return result
int test() {
int result = 0;
RUN(test_copy_enoent);
RUN(test_create_directory);
RUN(test_create_directories);
RUN(test_remove);
RUN(test_remove_all);
RUN(test_rename);
RUN(test_copy);
RUN(test_copy_file);
RUN(test_exists);
RUN(test_is_regular_file);
RUN(test_is_directory);
RUN(test_is_symlink);
RUN(test_file_size);
RUN(test_last_write_time);
RUN(test_permissions);
RUN(test_current_path);
RUN(test_absolute);
RUN(test_canonical);
RUN(test_read_symlink);
RUN(test_create_symlink_and_hard_link);
RUN(test_space);
RUN(test_equivalent);
RUN(test_resize_file);
RUN(test_status);
return 0;
}
int main() {
int rc;
setup();
rc = test();
teardown();
return rc;
}