1 //===----------------------------------------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 // UNSUPPORTED: c++03
10 // UNSUPPORTED: no-filesystem
11 // UNSUPPORTED: availability-filesystem-missing
12 
13 // <filesystem>
14 
15 // bool equivalent(path const& lhs, path const& rhs);
16 // bool equivalent(path const& lhs, path const& rhs, std::error_code& ec) noexcept;
17 
18 #include "filesystem_include.h"
19 #include <type_traits>
20 #include <cassert>
21 
22 #include "assert_macros.h"
23 #include "test_macros.h"
24 #include "filesystem_test_helper.h"
25 
26 using namespace fs;
27 
28 static void signature_test() {
29   const path p;
30   ((void)p);
31   std::error_code ec;
32   ((void)ec);
33   ASSERT_NOEXCEPT(equivalent(p, p, ec));
34   ASSERT_NOT_NOEXCEPT(equivalent(p, p));
35 }
36 
37 static void equivalent_test() {
38   static_test_env static_env;
39   struct TestCase {
40     path lhs;
41     path rhs;
42     bool expect;
43   };
44   const TestCase testCases[] = {
45       {static_env.Dir, static_env.Dir, true},
46       {static_env.File, static_env.Dir, false},
47       {static_env.Dir, static_env.SymlinkToDir, true},
48       {static_env.Dir, static_env.SymlinkToFile, false},
49       {static_env.File, static_env.File, true},
50       {static_env.File, static_env.SymlinkToFile, true},
51   };
52   for (auto& TC : testCases) {
53     std::error_code ec;
54     assert(equivalent(TC.lhs, TC.rhs, ec) == TC.expect);
55     assert(!ec);
56   }
57 }
58 
59 static void equivalent_reports_error_if_input_dne() {
60   static_test_env static_env;
61   const path E = static_env.File;
62   const path DNE = static_env.DNE;
63   { // Test that an error is reported when either of the paths don't exist
64     std::error_code ec = GetTestEC();
65     assert(equivalent(E, DNE, ec) == false);
66     assert(ec);
67     assert(ec != GetTestEC());
68   }
69   {
70     std::error_code ec = GetTestEC();
71     assert(equivalent(DNE, E, ec) == false);
72     assert(ec);
73     assert(ec != GetTestEC());
74   }
75   {
76     TEST_THROWS_TYPE(filesystem_error, equivalent(DNE, E));
77     TEST_THROWS_TYPE(filesystem_error, equivalent(E, DNE));
78   }
79   { // Test that an exception is thrown if both paths do not exist.
80     TEST_THROWS_TYPE(filesystem_error, equivalent(DNE, DNE));
81   }
82   {
83     std::error_code ec = GetTestEC();
84     assert(equivalent(DNE, DNE, ec) == false);
85     assert(ec);
86     assert(ec != GetTestEC());
87   }
88 }
89 
90 static void equivalent_hardlink_succeeds() {
91   scoped_test_env env;
92   path const file = env.create_file("file", 42);
93   const path hl1 = env.create_hardlink(file, "hl1");
94   const path hl2 = env.create_hardlink(file, "hl2");
95   assert(equivalent(file, hl1));
96   assert(equivalent(file, hl2));
97   assert(equivalent(hl1, hl2));
98 }
99 
100 #ifndef _WIN32
101 static void equivalent_is_other_succeeds() {
102   scoped_test_env env;
103   path const file = env.create_file("file", 42);
104   const path fifo1 = env.create_fifo("fifo1");
105   const path fifo2 = env.create_fifo("fifo2");
106   // Required to test behavior for inputs where is_other(p) is true.
107   assert(is_other(fifo1));
108   assert(!equivalent(file, fifo1));
109   assert(!equivalent(fifo2, file));
110   assert(!equivalent(fifo1, fifo2));
111   assert(equivalent(fifo1, fifo1));
112 }
113 #endif // _WIN32
114 
115 int main(int, char**) {
116   signature_test();
117   equivalent_test();
118   equivalent_reports_error_if_input_dne();
119   equivalent_hardlink_succeeds();
120 #ifndef _WIN32
121   equivalent_is_other_succeeds();
122 #endif
123 
124   return 0;
125 }
126