Implement filesystem_error::what() and improve reporting.
This patch implements the `what()` for filesystem errors. The message
includes the 'what_arg', any paths that were specified, and the
error code message.
Additionally this patch refactors how errors are created, making it easier
to report them correctly.
llvm-svn: 337664
diff --git a/libcxx/test/support/filesystem_test_helper.hpp b/libcxx/test/support/filesystem_test_helper.hpp
index de06868c..f027928 100644
--- a/libcxx/test/support/filesystem_test_helper.hpp
+++ b/libcxx/test/support/filesystem_test_helper.hpp
@@ -9,8 +9,11 @@
#include <random>
#include <chrono>
#include <vector>
+#include <regex>
+#include "test_macros.h"
#include "rapid-cxx-test.hpp"
+#include "format_string.hpp"
// static test helpers
@@ -442,25 +445,77 @@
}
struct ExceptionChecker {
- std::vector<std::errc> expected_err_list;
+ std::errc expected_err;
fs::path expected_path1;
fs::path expected_path2;
+ unsigned num_paths;
+ const char* func_name;
+ std::string opt_message;
- template <class... ErrcT>
- explicit ExceptionChecker(fs::path p, std::errc first_err, ErrcT... rest_err)
- : expected_err_list({first_err, rest_err...}), expected_path1(p) {}
+ explicit ExceptionChecker(std::errc first_err, const char* func_name,
+ std::string opt_msg = {})
+ : expected_err{first_err}, num_paths(0), func_name(func_name),
+ opt_message(opt_msg) {}
+ explicit ExceptionChecker(fs::path p, std::errc first_err,
+ const char* func_name, std::string opt_msg = {})
+ : expected_err(first_err), expected_path1(p), num_paths(1),
+ func_name(func_name), opt_message(opt_msg) {}
- template <class... ErrcT>
explicit ExceptionChecker(fs::path p1, fs::path p2, std::errc first_err,
- ErrcT... rest_err)
- : expected_err_list({first_err, rest_err...}), expected_path1(p1),
- expected_path2(p2) {}
+ const char* func_name, std::string opt_msg = {})
+ : expected_err(first_err), expected_path1(p1), expected_path2(p2),
+ num_paths(2), func_name(func_name), opt_message(opt_msg) {}
- void operator()(fs::filesystem_error const& Err) const {
- TEST_CHECK(ErrorIsImp(Err.code(), expected_err_list));
+ void operator()(fs::filesystem_error const& Err) {
+ TEST_CHECK(ErrorIsImp(Err.code(), {expected_err}));
TEST_CHECK(Err.path1() == expected_path1);
TEST_CHECK(Err.path2() == expected_path2);
+ LIBCPP_ONLY(check_libcxx_string(Err));
}
+
+ void check_libcxx_string(fs::filesystem_error const& Err) {
+ std::string message = std::make_error_code(expected_err).message();
+
+ std::string additional_msg = "";
+ if (!opt_message.empty()) {
+ additional_msg = opt_message + ": ";
+ }
+ auto transform_path = [](const fs::path& p) {
+ if (p.native().empty())
+ return "\"\"";
+ return p.c_str();
+ };
+ std::string format = [&]() -> std::string {
+ switch (num_paths) {
+ case 0:
+ return format_string("filesystem error: in %s: %s%s", func_name,
+ additional_msg, message);
+ case 1:
+ return format_string("filesystem error: in %s: %s%s [%s]", func_name,
+ additional_msg, message,
+ transform_path(expected_path1));
+ case 2:
+ return format_string("filesystem error: in %s: %s%s [%s] [%s]",
+ func_name, additional_msg, message,
+ transform_path(expected_path1),
+ transform_path(expected_path2));
+ default:
+ TEST_CHECK(false && "unexpected case");
+ return "";
+ }
+ }();
+ TEST_CHECK(format == Err.what());
+ if (format != Err.what()) {
+ fprintf(stderr,
+ "filesystem_error::what() does not match expected output:\n");
+ fprintf(stderr, " expected: \"%s\"\n", format.c_str());
+ fprintf(stderr, " actual: \"%s\"\n\n", Err.what());
+ }
+ }
+
+ ExceptionChecker(ExceptionChecker const&) = delete;
+ ExceptionChecker& operator=(ExceptionChecker const&) = delete;
+
};
#endif /* FILESYSTEM_TEST_HELPER_HPP */