Skip to content

Commit b4043d6

Browse files
committed
Refactor EXPECT_SAME_FILE: don't rely on canonicalize_path
canonicalize_path might be buggy, so we shouldn't rely on it in our assertions. Reimplement EXPECT_SAME_FILE using more reliable primitives.
1 parent b996144 commit b4043d6

File tree

1 file changed

+43
-9
lines changed

1 file changed

+43
-9
lines changed

test/quick-lint-js/file-matcher.h

Lines changed: 43 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,29 +4,63 @@
44
#ifndef QUICK_LINT_JS_FILE_MATCHER_H
55
#define QUICK_LINT_JS_FILE_MATCHER_H
66

7+
#include <cerrno>
8+
#include <cstring>
79
#include <gtest/gtest.h>
810
#include <quick-lint-js/file.h>
11+
#include <quick-lint-js/have.h>
12+
13+
#if QLJS_HAVE_STD_FILESYSTEM
14+
#include <filesystem>
15+
#endif
16+
17+
#if QLJS_HAVE_SYS_STAT_H
18+
#include <sys/stat.h>
19+
#endif
920

1021
#define EXPECT_SAME_FILE(path_a, path_b) \
1122
EXPECT_PRED_FORMAT2(::quick_lint_js::assert_same_file, path_a, path_b)
1223

1324
namespace quick_lint_js {
14-
template <class String>
15-
::testing::AssertionResult assert_same_file(const char *lhs_expr,
16-
const char *rhs_expr,
17-
String lhs_path, String rhs_path) {
18-
canonical_path_result lhs_canonical = canonicalize_path(lhs_path);
19-
EXPECT_TRUE(lhs_canonical.ok()) << std::move(lhs_canonical).error();
20-
canonical_path_result rhs_canonical = canonicalize_path(rhs_path);
21-
EXPECT_TRUE(rhs_canonical.ok()) << std::move(rhs_canonical).error();
22-
if (lhs_canonical.path() == rhs_canonical.path()) {
25+
inline ::testing::AssertionResult assert_same_file(const char* lhs_expr,
26+
const char* rhs_expr,
27+
const char* lhs_path,
28+
const char* rhs_path) {
29+
bool same;
30+
#if QLJS_HAVE_STD_FILESYSTEM
31+
// TODO(strager): std::filesystem::equivalent treats differnt symlinks
32+
// pointing to the same file as equivalent. This behavior differs from our
33+
// lstat-based implementation below.
34+
same = std::filesystem::equivalent(lhs_path, rhs_path);
35+
#elif QLJS_HAVE_SYS_STAT_H
36+
{
37+
struct stat lhs_stat = {};
38+
EXPECT_EQ(::lstat(lhs_path, &lhs_stat), 0) << std::strerror(errno);
39+
40+
struct stat rhs_stat = {};
41+
EXPECT_EQ(::lstat(rhs_path, &rhs_stat), 0) << std::strerror(errno);
42+
43+
same = lhs_stat.st_dev == rhs_stat.st_dev &&
44+
lhs_stat.st_ino == rhs_stat.st_ino;
45+
}
46+
#else
47+
#error "Unsupported platform"
48+
#endif
49+
if (same) {
2350
return ::testing::AssertionSuccess();
2451
} else {
2552
return ::testing::AssertionFailure()
2653
<< lhs_expr << " (" << lhs_path << ") is not the same file as "
2754
<< rhs_expr << " (" << rhs_path << ')';
2855
}
2956
}
57+
58+
inline ::testing::AssertionResult assert_same_file(
59+
const char* lhs_expr, const char* rhs_expr, const std::string& lhs_path,
60+
const std::string& rhs_path) {
61+
return assert_same_file(lhs_expr, rhs_expr, lhs_path.c_str(),
62+
rhs_path.c_str());
63+
}
3064
}
3165

3266
#endif

0 commit comments

Comments
 (0)