diff --git a/bench/CMakeLists.txt b/bench/CMakeLists.txt index d087cf66..0ea88423 100644 --- a/bench/CMakeLists.txt +++ b/bench/CMakeLists.txt @@ -24,5 +24,3 @@ target_link_libraries(latency PRIVATE benchmark::benchmark spdlog::spdlog) add_executable(formatter-bench formatter-bench.cpp) target_link_libraries(formatter-bench PRIVATE benchmark::benchmark spdlog::spdlog) - -file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/logs") diff --git a/bench/latency.cpp b/bench/latency.cpp index 730226ca..cd8717d9 100644 --- a/bench/latency.cpp +++ b/bench/latency.cpp @@ -16,26 +16,6 @@ #include "spdlog/sinks/null_sink.h" #include "spdlog/sinks/rotating_file_sink.h" -void prepare_logdir() -{ - spdlog::info("Preparing latency_logs directory.."); -#ifdef _WIN32 - system("if not exist logs mkdir latency_logs"); - system("del /F /Q logs\\*"); -#else - auto rv = system("mkdir -p latency_logs"); - if (rv != 0) - { - throw std::runtime_error("Failed to mkdir -p latency_logs"); - } - rv = system("rm -f latency_logs/*"); - if (rv != 0) - { - throw std::runtime_error("Failed to rm -f latency_logs/*"); - } -#endif -} - void bench_c_string(benchmark::State &state, std::shared_ptr logger) { const char *msg = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vestibulum pharetra metus cursus " @@ -83,8 +63,6 @@ int main(int argc, char *argv[]) size_t rotating_files = 5; int n_threads = benchmark::CPUInfo::Get().num_cpus; - prepare_logdir(); - // disabled loggers auto disabled_logger = std::make_shared("bench", std::make_shared()); disabled_logger->set_level(spdlog::level::off); diff --git a/bench/meson.build b/bench/meson.build index c2604271..c877b6ac 100644 --- a/bench/meson.build +++ b/bench/meson.build @@ -12,4 +12,3 @@ foreach i : bench_matrix benchmark('bench_' + i[0], bench_exe, args: i[2]) endforeach -run_command(find_program('mkdir'), meson.current_build_dir() + '/logs') diff --git a/example/CMakeLists.txt b/example/CMakeLists.txt index b5fc4060..458ca952 100644 --- a/example/CMakeLists.txt +++ b/example/CMakeLists.txt @@ -25,5 +25,3 @@ if(SPDLOG_BUILD_EXAMPLE_HO) target_link_libraries(example_header_only PRIVATE spdlog::spdlog_header_only) endif() -# Create logs directory -file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/logs") diff --git a/example/meson.build b/example/meson.build index 7e29abb2..c37c4c3c 100644 --- a/example/meson.build +++ b/example/meson.build @@ -1,5 +1,4 @@ executable('example', 'example.cpp', dependencies: spdlog_dep) executable('example_header_only', 'example.cpp', dependencies: spdlog_headeronly_dep) -run_command(find_program('mkdir'), meson.current_build_dir() + '/logs') diff --git a/include/spdlog/details/file_helper-inl.h b/include/spdlog/details/file_helper-inl.h index 440cb290..669999b4 100644 --- a/include/spdlog/details/file_helper-inl.h +++ b/include/spdlog/details/file_helper-inl.h @@ -28,28 +28,31 @@ SPDLOG_INLINE file_helper::~file_helper() SPDLOG_INLINE void file_helper::open(const filename_t &fname, bool truncate) { close(); + filename_ = fname; auto *mode = truncate ? SPDLOG_FILENAME_T("wb") : SPDLOG_FILENAME_T("ab"); - _filename = fname; - for (int tries = 0; tries < open_tries; ++tries) + + for (int tries = 0; tries < open_tries_; ++tries) { + // create containing folder if not exists already. + os::create_dir(os::dir_name(fname)); if (!os::fopen_s(&fd_, fname, mode)) { return; } - details::os::sleep_for_millis(open_interval); + details::os::sleep_for_millis(open_interval_); } - SPDLOG_THROW(spdlog_ex("Failed opening file " + os::filename_to_str(_filename) + " for writing", errno)); + SPDLOG_THROW(spdlog_ex("Failed opening file " + os::filename_to_str(filename_) + " for writing", errno)); } SPDLOG_INLINE void file_helper::reopen(bool truncate) { - if (_filename.empty()) + if (filename_.empty()) { SPDLOG_THROW(spdlog_ex("Failed re opening file - was not opened before")); } - open(_filename, truncate); + this->open(filename_, truncate); } SPDLOG_INLINE void file_helper::flush() @@ -72,7 +75,7 @@ SPDLOG_INLINE void file_helper::write(const memory_buf_t &buf) auto data = buf.data(); if (std::fwrite(data, 1, msg_size, fd_) != msg_size) { - SPDLOG_THROW(spdlog_ex("Failed writing to file " + os::filename_to_str(_filename), errno)); + SPDLOG_THROW(spdlog_ex("Failed writing to file " + os::filename_to_str(filename_), errno)); } } @@ -80,19 +83,14 @@ SPDLOG_INLINE size_t file_helper::size() const { if (fd_ == nullptr) { - SPDLOG_THROW(spdlog_ex("Cannot use size() on closed file " + os::filename_to_str(_filename))); + SPDLOG_THROW(spdlog_ex("Cannot use size() on closed file " + os::filename_to_str(filename_))); } return os::filesize(fd_); } SPDLOG_INLINE const filename_t &file_helper::filename() const { - return _filename; -} - -SPDLOG_INLINE bool file_helper::file_exists(const filename_t &fname) -{ - return os::file_exists(fname); + return filename_; } // @@ -129,5 +127,6 @@ SPDLOG_INLINE std::tuple file_helper::split_by_extension // finally - return a valid base and extension tuple return std::make_tuple(fname.substr(0, ext_index), fname.substr(ext_index)); } + } // namespace details } // namespace spdlog diff --git a/include/spdlog/details/file_helper.h b/include/spdlog/details/file_helper.h index 990d99e3..5ac4c27b 100644 --- a/include/spdlog/details/file_helper.h +++ b/include/spdlog/details/file_helper.h @@ -29,7 +29,6 @@ public: void write(const memory_buf_t &buf); size_t size() const; const filename_t &filename() const; - static bool file_exists(const filename_t &fname); // // return file path and its extension: @@ -47,10 +46,10 @@ public: static std::tuple split_by_extension(const filename_t &fname); private: - const int open_tries = 5; - const int open_interval = 10; + const int open_tries_ = 5; + const int open_interval_ = 10; std::FILE *fd_{nullptr}; - filename_t _filename; + filename_t filename_; }; } // namespace details } // namespace spdlog diff --git a/include/spdlog/details/os-inl.h b/include/spdlog/details/os-inl.h index f436b0d1..35a8934a 100644 --- a/include/spdlog/details/os-inl.h +++ b/include/spdlog/details/os-inl.h @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include @@ -42,6 +43,8 @@ #include #endif +#include // for _mkdir/_wmkdir + #else // unix #include @@ -91,17 +94,17 @@ SPDLOG_INLINE std::tm localtime(const std::time_t &time_tt) SPDLOG_NOEXCEPT #ifdef _WIN32 std::tm tm; - localtime_s(&tm, &time_tt); + ::localtime_s(&tm, &time_tt); #else std::tm tm; - localtime_r(&time_tt, &tm); + ::localtime_r(&time_tt, &tm); #endif return tm; } SPDLOG_INLINE std::tm localtime() SPDLOG_NOEXCEPT { - std::time_t now_t = time(nullptr); + std::time_t now_t = ::time(nullptr); return localtime(now_t); } @@ -110,17 +113,17 @@ SPDLOG_INLINE std::tm gmtime(const std::time_t &time_tt) SPDLOG_NOEXCEPT #ifdef _WIN32 std::tm tm; - gmtime_s(&tm, &time_tt); + ::gmtime_s(&tm, &time_tt); #else std::tm tm; - gmtime_r(&time_tt, &tm); + ::gmtime_r(&time_tt, &tm); #endif return tm; } SPDLOG_INLINE std::tm gmtime() SPDLOG_NOEXCEPT { - std::time_t now_t = time(nullptr); + std::time_t now_t = ::time(nullptr); return gmtime(now_t); } @@ -129,13 +132,13 @@ SPDLOG_INLINE void prevent_child_fd(FILE *f) #ifdef _WIN32 #if !defined(__cplusplus_winrt) - auto file_handle = reinterpret_cast(_get_osfhandle(_fileno(f))); + auto file_handle = reinterpret_cast(_get_osfhandle(::_fileno(f))); if (!::SetHandleInformation(file_handle, HANDLE_FLAG_INHERIT, 0)) SPDLOG_THROW(spdlog_ex("SetHandleInformation failed", errno)); #endif #else - auto fd = fileno(f); - if (fcntl(fd, F_SETFD, FD_CLOEXEC) == -1) + auto fd = ::fileno(f); + if (::fcntl(fd, F_SETFD, FD_CLOEXEC) == -1) { SPDLOG_THROW(spdlog_ex("fcntl with FD_CLOEXEC failed", errno)); } @@ -147,12 +150,12 @@ SPDLOG_INLINE bool fopen_s(FILE **fp, const filename_t &filename, const filename { #ifdef _WIN32 #ifdef SPDLOG_WCHAR_FILENAMES - *fp = _wfsopen((filename.c_str()), mode.c_str(), _SH_DENYNO); + *fp = ::_wfsopen((filename.c_str()), mode.c_str(), _SH_DENYNO); #else - *fp = _fsopen((filename.c_str()), mode.c_str(), _SH_DENYNO); + *fp = ::_fsopen((filename.c_str()), mode.c_str(), _SH_DENYNO); #endif #else // unix - *fp = fopen((filename.c_str()), mode.c_str()); + *fp = ::fopen((filename.c_str()), mode.c_str()); #endif #ifdef SPDLOG_PREVENT_CHILD_FD @@ -167,7 +170,7 @@ SPDLOG_INLINE bool fopen_s(FILE **fp, const filename_t &filename, const filename SPDLOG_INLINE int remove(const filename_t &filename) SPDLOG_NOEXCEPT { #if defined(_WIN32) && defined(SPDLOG_WCHAR_FILENAMES) - return _wremove(filename.c_str()); + return ::_wremove(filename.c_str()); #else return std::remove(filename.c_str()); #endif @@ -175,28 +178,28 @@ SPDLOG_INLINE int remove(const filename_t &filename) SPDLOG_NOEXCEPT SPDLOG_INLINE int remove_if_exists(const filename_t &filename) SPDLOG_NOEXCEPT { - return file_exists(filename) ? remove(filename) : 0; + return path_exists(filename) ? remove(filename) : 0; } SPDLOG_INLINE int rename(const filename_t &filename1, const filename_t &filename2) SPDLOG_NOEXCEPT { #if defined(_WIN32) && defined(SPDLOG_WCHAR_FILENAMES) - return _wrename(filename1.c_str(), filename2.c_str()); + return ::_wrename(filename1.c_str(), filename2.c_str()); #else return std::rename(filename1.c_str(), filename2.c_str()); #endif } -// Return true if file exists -SPDLOG_INLINE bool file_exists(const filename_t &filename) SPDLOG_NOEXCEPT +// Return true if path exists (file or directory) +SPDLOG_INLINE bool path_exists(const filename_t &filename) SPDLOG_NOEXCEPT { #ifdef _WIN32 #ifdef SPDLOG_WCHAR_FILENAMES - auto attribs = GetFileAttributesW(filename.c_str()); + auto attribs = ::GetFileAttributesW(filename.c_str()); #else - auto attribs = GetFileAttributesA(filename.c_str()); + auto attribs = ::GetFileAttributesA(filename.c_str()); #endif - return (attribs != INVALID_FILE_ATTRIBUTES && !(attribs & FILE_ATTRIBUTE_DIRECTORY)); + return attribs != INVALID_FILE_ATTRIBUTES; #else // common linux/unix all have the stat system call struct stat buffer; return (::stat(filename.c_str(), &buffer) == 0); @@ -211,16 +214,16 @@ SPDLOG_INLINE size_t filesize(FILE *f) SPDLOG_THROW(spdlog_ex("Failed getting file size. fd is null")); } #if defined(_WIN32) && !defined(__CYGWIN__) - int fd = _fileno(f); + int fd = ::_fileno(f); #if _WIN64 // 64 bits - __int64 ret = _filelengthi64(fd); + __int64 ret = ::_filelengthi64(fd); if (ret >= 0) { return static_cast(ret); } #else // windows 32 bits - long ret = _filelength(fd); + long ret = ::_filelength(fd); if (ret >= 0) { return static_cast(ret); @@ -228,7 +231,7 @@ SPDLOG_INLINE size_t filesize(FILE *f) #endif #else // unix - int fd = fileno(f); + int fd = ::fileno(f); // 64 bits(but not in osx or cygwin, where fstat64 is deprecated) #if (defined(__linux__) || defined(__sun) || defined(_AIX)) && (defined(__LP64__) || defined(_LP64)) struct stat64 st; @@ -255,10 +258,10 @@ SPDLOG_INLINE int utc_minutes_offset(const std::tm &tm) #ifdef _WIN32 #if _WIN32_WINNT < _WIN32_WINNT_WS08 TIME_ZONE_INFORMATION tzinfo; - auto rv = GetTimeZoneInformation(&tzinfo); + auto rv = ::GetTimeZoneInformation(&tzinfo); #else DYNAMIC_TIME_ZONE_INFORMATION tzinfo; - auto rv = GetDynamicTimeZoneInformation(&tzinfo); + auto rv = ::GetDynamicTimeZoneInformation(&tzinfo); #endif if (rv == TIME_ZONE_ID_INVALID) SPDLOG_THROW(spdlog::spdlog_ex("Failed getting timezone info. ", errno)); @@ -324,15 +327,15 @@ SPDLOG_INLINE size_t _thread_id() SPDLOG_NOEXCEPT #if defined(__ANDROID__) && defined(__ANDROID_API__) && (__ANDROID_API__ < 21) #define SYS_gettid __NR_gettid #endif - return static_cast(syscall(SYS_gettid)); + return static_cast(::syscall(SYS_gettid)); #elif defined(_AIX) || defined(__DragonFly__) || defined(__FreeBSD__) - return static_cast(pthread_getthreadid_np()); + return static_cast(::pthread_getthreadid_np()); #elif defined(__NetBSD__) - return static_cast(_lwp_self()); + return static_cast(::_lwp_self()); #elif defined(__OpenBSD__) - return static_cast(getthrid()); + return static_cast(::getthrid()); #elif defined(__sun) - return static_cast(thr_self()); + return static_cast(::thr_self()); #elif __APPLE__ uint64_t tid; pthread_threadid_np(nullptr, &tid); @@ -417,9 +420,9 @@ SPDLOG_INLINE bool in_terminal(FILE *file) SPDLOG_NOEXCEPT { #ifdef _WIN32 - return _isatty(_fileno(file)) != 0; + return ::_isatty(_fileno(file)) != 0; #else - return isatty(fileno(file)) != 0; + return ::isatty(fileno(file)) != 0; #endif } @@ -460,6 +463,77 @@ SPDLOG_INLINE void wstr_to_utf8buf(wstring_view_t wstr, memory_buf_t &target) } #endif // (defined(SPDLOG_WCHAR_TO_UTF8_SUPPORT) || defined(SPDLOG_WCHAR_FILENAMES)) && defined(_WIN32) +// return true on success +SPDLOG_INLINE bool mkdir_(const filename_t &path) +{ +#ifdef _WIN32 +#ifdef SPDLOG_WCHAR_FILENAMES + return ::_wmkdir(path.c_str()) == 0; +#else + return ::_mkdir(path.c_str()) == 0; +#endif +#else + return ::mkdir(path.c_str(), mode_t(0755)) == 0; +#endif +} + +// create the given directory - and all directories leading to it +// return true on success or if the directory already exists +SPDLOG_INLINE bool create_dir(filename_t path) +{ + if (path_exists(path)) + { + return true; + } + + if(path.empty()) + { + return false; + } + +#ifdef _WIN32 + // support forward slash in windows + std::replace(path.begin(), path.end(), '/', folder_sep); +#endif + + size_t search_offset = 0; + do + { + fmt::string_view t; + auto token_pos = path.find(folder_sep, search_offset); + // treat the entire path as a folder if no folder separator not found + if (token_pos == filename_t::npos) + { + token_pos = path.size(); + } + + auto subdir = path.substr(0, token_pos); + + if (!subdir.empty() && !path_exists(subdir) && !mkdir_(subdir)) + { + return false; // return error if failed creating dir + } + search_offset = token_pos + 1; + } while (search_offset < path.size()); + + return true; +} + +// Return directory name from given path or empty string +// "abc/file" => "abc" +// "abc/" => "abc" +// "abc" => "" +// "abc///" => "abc//" +SPDLOG_INLINE filename_t dir_name(filename_t path) +{ +#ifdef _WIN32 + // support forward slash in windows + std::replace(path.begin(), path.end(), '/', folder_sep); +#endif + auto pos = path.find_last_of(folder_sep); + return pos != filename_t::npos ? path.substr(0, pos) : filename_t{}; +} + } // namespace os } // namespace details } // namespace spdlog diff --git a/include/spdlog/details/os.h b/include/spdlog/details/os.h index a4a57b7f..e275a40f 100644 --- a/include/spdlog/details/os.h +++ b/include/spdlog/details/os.h @@ -33,7 +33,7 @@ SPDLOG_CONSTEXPR static const char *default_eol = SPDLOG_EOL; // folder separator #ifdef _WIN32 -const char folder_sep = '\\'; +static const char folder_sep = '\\'; #else SPDLOG_CONSTEXPR static const char folder_sep = '/'; #endif @@ -53,7 +53,7 @@ int remove_if_exists(const filename_t &filename) SPDLOG_NOEXCEPT; int rename(const filename_t &filename1, const filename_t &filename2) SPDLOG_NOEXCEPT; // Return if file exists. -bool file_exists(const filename_t &filename) SPDLOG_NOEXCEPT; +bool path_exists(const filename_t &filename) SPDLOG_NOEXCEPT; // Return file size according to open FILE* object size_t filesize(FILE *f); @@ -89,6 +89,17 @@ bool in_terminal(FILE *file) SPDLOG_NOEXCEPT; void wstr_to_utf8buf(wstring_view_t wstr, memory_buf_t &target); #endif +// Return directory name from given path or empty string +// "abc/file" => "abc" +// "abc/" => "abc" +// "abc" => "" +// "abc///" => "abc//" +filename_t dir_name(filename_t path); + +// Create a dir from the given path. +// Return true if succeeded or if this dir already exists. +bool create_dir(filename_t path); + } // namespace os } // namespace details } // namespace spdlog diff --git a/include/spdlog/sinks/rotating_file_sink-inl.h b/include/spdlog/sinks/rotating_file_sink-inl.h index 15443c5a..82347001 100644 --- a/include/spdlog/sinks/rotating_file_sink-inl.h +++ b/include/spdlog/sinks/rotating_file_sink-inl.h @@ -88,11 +88,12 @@ template SPDLOG_INLINE void rotating_file_sink::rotate_() { using details::os::filename_to_str; + using details::os::path_exists; file_helper_.close(); for (auto i = max_files_; i > 0; --i) { filename_t src = calc_filename(base_filename_, i - 1); - if (!details::file_helper::file_exists(src)) + if (!path_exists(src)) { continue; } diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 55175bc1..5fd9900c 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -25,7 +25,8 @@ set(SPDLOG_UTESTS_SOURCES test_fmt_helper.cpp test_stdout_api.cpp test_dup_filter.cpp - test_backtrace.cpp) + test_backtrace.cpp + test_create_dir.cpp) if(NOT SPDLOG_NO_EXCEPTIONS) list(APPEND SPDLOG_UTESTS_SOURCES test_errors.cpp) @@ -35,7 +36,6 @@ if(systemd_FOUND) list(APPEND SPDLOG_UTESTS_SOURCES test_systemd.cpp) endif() -file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/logs") enable_testing() function(spdlog_prepare_test test_target spdlog_lib) diff --git a/tests/meson.build b/tests/meson.build index 73d7b8f8..98b40797 100644 --- a/tests/meson.build +++ b/tests/meson.build @@ -35,7 +35,6 @@ if systemd_dep.found() global_test_deps += systemd_dep endif -run_command('mkdir', 'logs') # -------------------------------------- # --- Build the test executables --- # -------------------------------------- @@ -49,5 +48,3 @@ foreach i : test_matrix test_exe = executable(i[0], test_sources, dependencies: global_test_deps + [i[1]]) test('test_' + i[0], test_exe) endforeach - -run_command(find_program('mkdir'), meson.current_build_dir() + '/logs') \ No newline at end of file diff --git a/tests/test_async.cpp b/tests/test_async.cpp index 6f86cf6c..166ac21e 100644 --- a/tests/test_async.cpp +++ b/tests/test_async.cpp @@ -157,7 +157,7 @@ TEST_CASE("to_file", "[async]") prepare_logdir(); size_t messages = 1024; size_t tp_threads = 1; - std::string filename = "logs/async_test.log"; + std::string filename = "test_logs/async_test.log"; { auto file_sink = std::make_shared(filename, true); auto tp = std::make_shared(messages, tp_threads); @@ -179,7 +179,7 @@ TEST_CASE("to_file multi-workers", "[async]") prepare_logdir(); size_t messages = 1024 * 10; size_t tp_threads = 10; - std::string filename = "logs/async_test.log"; + std::string filename = "test_logs/async_test.log"; { auto file_sink = std::make_shared(filename, true); auto tp = std::make_shared(messages, tp_threads); diff --git a/tests/test_create_dir.cpp b/tests/test_create_dir.cpp new file mode 100644 index 00000000..b538e80e --- /dev/null +++ b/tests/test_create_dir.cpp @@ -0,0 +1,80 @@ +/* + * This content is released under the MIT License as specified in https://raw.githubusercontent.com/gabime/spdlog/master/LICENSE + */ +#include "includes.h" + +using spdlog::details::os::create_dir; +using spdlog::details::os::path_exists; + +bool try_create_dir(const char *path, const char *normalized_path) +{ + auto rv = create_dir(path); + REQUIRE(rv == true); + return path_exists(normalized_path); +} + +TEST_CASE("create_dir", "[create_dir]") +{ + prepare_logdir(); + + REQUIRE(try_create_dir("test_logs/dir1/dir1", "test_logs/dir1/dir1")); + REQUIRE(try_create_dir("test_logs/dir1/dir1", "test_logs/dir1/dir1")); // test existing + REQUIRE(try_create_dir("test_logs/dir1///dir2//", "test_logs/dir1/dir2")); + REQUIRE(try_create_dir("./test_logs/dir1/dir3", "test_logs/dir1/dir3")); + REQUIRE(try_create_dir("test_logs/../test_logs/dir1/dir4", "test_logs/dir1/dir4")); + +#ifdef WIN32 + // test backslash folder separator + REQUIRE(try_create_dir("test_logs\\dir1\\dir222", "test_logs\\dir1\\dir222")); + REQUIRE(try_create_dir("test_logs\\dir1\\dir223\\", "test_logs\\dir1\\dir223\\")); + REQUIRE(try_create_dir(".\\test_logs\\dir1\\dir2\\dir99\\..\\dir23", "test_logs\\dir1\\dir2\\dir23")); + REQUIRE(try_create_dir("test_logs\\..\\test_logs\\dir1\\dir5", "test_logs\\dir1\\dir5")); +#endif +} + +TEST_CASE("create_invalid_dir", "[create_dir]") +{ + REQUIRE(create_dir("") == false); + REQUIRE(create_dir(spdlog::filename_t{}) == false); +#ifdef __linux__ + REQUIRE(create_dir("/proc/spdlog-utest") == false); +#endif +} + +TEST_CASE("dir_name", "[create_dir]") +{ + using spdlog::details::os::dir_name; + REQUIRE(dir_name("").empty()); + REQUIRE(dir_name("dir").empty()); + +#ifdef WIN32 + REQUIRE(dir_name(R"(dir\)") == "dir"); + REQUIRE(dir_name(R"(dir\\\)") == R"(dir\\)"); + REQUIRE(dir_name(R"(dir\file)") == "dir"); + REQUIRE(dir_name(R"(dir/file)") == "dir"); + REQUIRE(dir_name(R"(dir\file.txt)") == "dir"); + REQUIRE(dir_name(R"(dir/file)") == "dir"); + REQUIRE(dir_name(R"(dir\file.txt\)") == R"(dir\file.txt)"); + REQUIRE(dir_name(R"(dir/file.txt/)") == R"(dir\file.txt)"); + REQUIRE(dir_name(R"(\dir\file.txt)") == R"(\dir)"); + REQUIRE(dir_name(R"(/dir/file.txt)") == R"(\dir)"); + REQUIRE(dir_name(R"(\\dir\file.txt)") == R"(\\dir)"); + REQUIRE(dir_name(R"(//dir/file.txt)") == R"(\\dir)"); + REQUIRE(dir_name(R"(..\file.txt)") == ".."); + REQUIRE(dir_name(R"(../file.txt)") == ".."); + REQUIRE(dir_name(R"(.\file.txt)") == "."); + REQUIRE(dir_name(R"(./file.txt)") == "."); + REQUIRE(dir_name(R"(c:\\a\b\c\d\file.txt)") == R"(c:\\a\b\c\d)"); + REQUIRE(dir_name(R"(c://a/b/c/d/file.txt)") == R"(c:\\a\b\c\d)"); +#else + REQUIRE(dir_name("dir/") == "dir"); + REQUIRE(dir_name("dir///") == "dir//"); + REQUIRE(dir_name("dir/file") == "dir"); + REQUIRE(dir_name("dir/file.txt") == "dir"); + REQUIRE(dir_name("dir/file.txt/") == "dir/file.txt"); + REQUIRE(dir_name("/dir/file.txt") == "/dir"); + REQUIRE(dir_name("//dir/file.txt") == "//dir"); + REQUIRE(dir_name("../file.txt") == ".."); + REQUIRE(dir_name("./file.txt") == "."); +#endif +} diff --git a/tests/test_daily_logger.cpp b/tests/test_daily_logger.cpp index c89ef171..cf2002a3 100644 --- a/tests/test_daily_logger.cpp +++ b/tests/test_daily_logger.cpp @@ -10,7 +10,7 @@ TEST_CASE("daily_logger with dateonly calculator", "[daily_logger]") prepare_logdir(); // calculate filename (time based) - std::string basename = "logs/daily_dateonly"; + std::string basename = "test_logs/daily_dateonly"; std::tm tm = spdlog::details::os::localtime(); spdlog::memory_buf_t w; fmt::format_to(w, "{}_{:04d}-{:02d}-{:02d}", basename, tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday); @@ -44,7 +44,7 @@ TEST_CASE("daily_logger with custom calculator", "[daily_logger]") prepare_logdir(); // calculate filename (time based) - std::string basename = "logs/daily_dateonly"; + std::string basename = "test_logs/daily_dateonly"; std::tm tm = spdlog::details::os::localtime(); spdlog::memory_buf_t w; fmt::format_to(w, "{}{:04d}{:02d}{:02d}", basename, tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday); @@ -119,7 +119,7 @@ static void test_rotate(int days_to_run, uint16_t max_days, uint16_t expected_n_ prepare_logdir(); - std::string basename = "logs/daily_rotate.txt"; + std::string basename = "test_logs/daily_rotate.txt"; daily_file_sink_st sink{basename, 2, 30, true, max_days}; // simulate messages with 24 intervals @@ -130,7 +130,7 @@ static void test_rotate(int days_to_run, uint16_t max_days, uint16_t expected_n_ sink.log(create_msg(offset)); } - REQUIRE(count_files("logs") == static_cast(expected_n_files)); + REQUIRE(count_files("test_logs") == static_cast(expected_n_files)); } TEST_CASE("daily_logger rotate", "[daily_file_sink]") diff --git a/tests/test_errors.cpp b/tests/test_errors.cpp index 65185d3c..4fc40594 100644 --- a/tests/test_errors.cpp +++ b/tests/test_errors.cpp @@ -26,7 +26,7 @@ protected: TEST_CASE("default_error_handler", "[errors]]") { prepare_logdir(); - std::string filename = "logs/simple_log.txt"; + std::string filename = "test_logs/simple_log.txt"; auto logger = spdlog::create("test-error", filename, true); logger->set_pattern("%v"); @@ -43,7 +43,7 @@ struct custom_ex TEST_CASE("custom_error_handler", "[errors]]") { prepare_logdir(); - std::string filename = "logs/simple_log.txt"; + std::string filename = "test_logs/simple_log.txt"; auto logger = spdlog::create("logger", filename, true); logger->flush_on(spdlog::level::info); logger->set_error_handler([=](const std::string &) { throw custom_ex(); }); @@ -75,15 +75,15 @@ TEST_CASE("async_error_handler", "[errors]]") prepare_logdir(); std::string err_msg("log failed with some msg"); - std::string filename = "logs/simple_async_log.txt"; + std::string filename = "test_logs/simple_async_log.txt"; { spdlog::init_thread_pool(128, 1); auto logger = spdlog::create_async("logger", filename, true); logger->set_error_handler([=](const std::string &) { - std::ofstream ofs("logs/custom_err.txt"); + std::ofstream ofs("test_logs/custom_err.txt"); if (!ofs) { - throw std::runtime_error("Failed open logs/custom_err.txt"); + throw std::runtime_error("Failed open test_logs/custom_err.txt"); } ofs << err_msg; }); @@ -94,7 +94,7 @@ TEST_CASE("async_error_handler", "[errors]]") } spdlog::init_thread_pool(128, 1); REQUIRE(count_lines(filename) == 2); - REQUIRE(file_contents("logs/custom_err.txt") == err_msg); + REQUIRE(file_contents("test_logs/custom_err.txt") == err_msg); } // Make sure async error handler is executed @@ -103,12 +103,13 @@ TEST_CASE("async_error_handler2", "[errors]]") prepare_logdir(); std::string err_msg("This is async handler error message"); { + spdlog::details::os::create_dir("test_logs"); spdlog::init_thread_pool(128, 1); auto logger = spdlog::create_async("failed_logger"); logger->set_error_handler([=](const std::string &) { - std::ofstream ofs("logs/custom_err2.txt"); + std::ofstream ofs("test_logs/custom_err2.txt"); if (!ofs) - throw std::runtime_error("Failed open logs/custom_err2.txt"); + throw std::runtime_error("Failed open test_logs/custom_err2.txt"); ofs << err_msg; }); logger->info("Hello failure"); @@ -116,5 +117,5 @@ TEST_CASE("async_error_handler2", "[errors]]") } spdlog::init_thread_pool(128, 1); - REQUIRE(file_contents("logs/custom_err2.txt") == err_msg); + REQUIRE(file_contents("test_logs/custom_err2.txt") == err_msg); } diff --git a/tests/test_file_helper.cpp b/tests/test_file_helper.cpp index 74e3744e..3a3545fe 100644 --- a/tests/test_file_helper.cpp +++ b/tests/test_file_helper.cpp @@ -6,7 +6,7 @@ using spdlog::details::file_helper; using spdlog::details::log_msg; -static const std::string target_filename = "logs/file_helper_test.txt"; +static const std::string target_filename = "test_logs/file_helper_test.txt"; static void write_with_helper(file_helper &helper, size_t howmany) { @@ -38,15 +38,6 @@ TEST_CASE("file_helper_size", "[file_helper::size()]]") REQUIRE(get_filesize(target_filename) == expected_size); } -TEST_CASE("file_helper_exists", "[file_helper::file_exists()]]") -{ - prepare_logdir(); - REQUIRE(!file_helper::file_exists(target_filename)); - file_helper helper; - helper.open(target_filename); - REQUIRE(file_helper::file_exists(target_filename)); -} - TEST_CASE("file_helper_reopen", "[file_helper::reopen()]]") { prepare_logdir(); diff --git a/tests/test_file_logging.cpp b/tests/test_file_logging.cpp index 7563cf65..a8f9b2bb 100644 --- a/tests/test_file_logging.cpp +++ b/tests/test_file_logging.cpp @@ -6,7 +6,7 @@ TEST_CASE("simple_file_logger", "[simple_logger]]") { prepare_logdir(); - std::string filename = "logs/simple_log"; + std::string filename = "test_logs/simple_log"; auto logger = spdlog::create("logger", filename); logger->set_pattern("%v"); @@ -22,7 +22,7 @@ TEST_CASE("simple_file_logger", "[simple_logger]]") TEST_CASE("flush_on", "[flush_on]]") { prepare_logdir(); - std::string filename = "logs/simple_log"; + std::string filename = "test_logs/simple_log"; auto logger = spdlog::create("logger", filename); logger->set_pattern("%v"); @@ -42,7 +42,7 @@ TEST_CASE("rotating_file_logger1", "[rotating_logger]]") { prepare_logdir(); size_t max_size = 1024 * 10; - std::string basename = "logs/rotating_log"; + std::string basename = "test_logs/rotating_log"; auto logger = spdlog::rotating_logger_mt("logger", basename, max_size, 0); for (int i = 0; i < 10; ++i) @@ -59,7 +59,7 @@ TEST_CASE("rotating_file_logger2", "[rotating_logger]]") { prepare_logdir(); size_t max_size = 1024 * 10; - std::string basename = "logs/rotating_log"; + std::string basename = "test_logs/rotating_log"; { // make an initial logger to create the first output file diff --git a/tests/test_macros.cpp b/tests/test_macros.cpp index 26b03cdf..75f53ab2 100644 --- a/tests/test_macros.cpp +++ b/tests/test_macros.cpp @@ -12,7 +12,7 @@ TEST_CASE("debug and trace w/o format string", "[macros]]") { prepare_logdir(); - std::string filename = "logs/simple_log"; + std::string filename = "test_logs/simple_log"; auto logger = spdlog::create("logger", filename); logger->set_pattern("%v"); diff --git a/tests/utils.cpp b/tests/utils.cpp index 6c7f3662..255a4fec 100644 --- a/tests/utils.cpp +++ b/tests/utils.cpp @@ -9,18 +9,12 @@ void prepare_logdir() { spdlog::drop_all(); #ifdef _WIN32 - system("if not exist logs mkdir logs"); - system("del /F /Q logs\\*"); + system("rmdir /S /Q test_logs"); #else - auto rv = system("mkdir -p logs"); + auto rv = system("rm -rf test_logs"); if (rv != 0) { - throw std::runtime_error("Failed to mkdir -p logs"); - } - rv = system("rm -f logs/*"); - if (rv != 0) - { - throw std::runtime_error("Failed to rm -f logs/*"); + throw std::runtime_error("Failed to rm -rf test_logs"); } #endif }