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 // REQUIRES: can-create-symlinks
10 // UNSUPPORTED: c++03, c++11, c++14
11 // UNSUPPORTED: no-filesystem
12 // UNSUPPORTED: availability-filesystem-missing
13 
14 // Starting in Android N (API 24), SELinux policy prevents the shell user from
15 // creating a hard link.
16 // XFAIL: LIBCXX-ANDROID-FIXME && !android-device-api={{21|22|23}}
17 
18 // <filesystem>
19 
20 // bool equivalent(path const& lhs, path const& rhs);
21 // bool equivalent(path const& lhs, path const& rhs, std::error_code& ec) noexcept;
22 
23 #include <filesystem>
24 #include <type_traits>
25 #include <cassert>
26 
27 #include "assert_macros.h"
28 #include "test_macros.h"
29 #include "filesystem_test_helper.h"
30 namespace fs = std::filesystem;
31 using namespace fs;
32 
signature_test()33 static void signature_test() {
34   const path p;
35   ((void)p);
36   std::error_code ec;
37   ((void)ec);
38   ASSERT_NOEXCEPT(equivalent(p, p, ec));
39   ASSERT_NOT_NOEXCEPT(equivalent(p, p));
40 }
41 
equivalent_test()42 static void equivalent_test() {
43   static_test_env static_env;
44   struct TestCase {
45     path lhs;
46     path rhs;
47     bool expect;
48   };
49   const TestCase testCases[] = {
50       {static_env.Dir, static_env.Dir, true},
51       {static_env.File, static_env.Dir, false},
52       {static_env.Dir, static_env.SymlinkToDir, true},
53       {static_env.Dir, static_env.SymlinkToFile, false},
54       {static_env.File, static_env.File, true},
55       {static_env.File, static_env.SymlinkToFile, true},
56   };
57   for (auto& TC : testCases) {
58     std::error_code ec;
59     assert(equivalent(TC.lhs, TC.rhs, ec) == TC.expect);
60     assert(!ec);
61   }
62 }
63 
equivalent_reports_error_if_input_dne()64 static void equivalent_reports_error_if_input_dne() {
65   static_test_env static_env;
66   const path E = static_env.File;
67   const path DNE = static_env.DNE;
68   { // Test that an error is reported when either of the paths don't exist
69     std::error_code ec = GetTestEC();
70     assert(equivalent(E, DNE, ec) == false);
71     assert(ec);
72     assert(ec != GetTestEC());
73   }
74   {
75     std::error_code ec = GetTestEC();
76     assert(equivalent(DNE, E, ec) == false);
77     assert(ec);
78     assert(ec != GetTestEC());
79   }
80   {
81     TEST_THROWS_TYPE(filesystem_error, equivalent(DNE, E));
82     TEST_THROWS_TYPE(filesystem_error, equivalent(E, DNE));
83   }
84   { // Test that an exception is thrown if both paths do not exist.
85     TEST_THROWS_TYPE(filesystem_error, equivalent(DNE, DNE));
86   }
87   {
88     std::error_code ec = GetTestEC();
89     assert(equivalent(DNE, DNE, ec) == false);
90     assert(ec);
91     assert(ec != GetTestEC());
92   }
93 }
94 
equivalent_hardlink_succeeds()95 static void equivalent_hardlink_succeeds() {
96   scoped_test_env env;
97   path const file = env.create_file("file", 42);
98   const path hl1 = env.create_hardlink(file, "hl1");
99   const path hl2 = env.create_hardlink(file, "hl2");
100   assert(equivalent(file, hl1));
101   assert(equivalent(file, hl2));
102   assert(equivalent(hl1, hl2));
103 }
104 
105 #ifndef _WIN32
equivalent_is_other_succeeds()106 static void equivalent_is_other_succeeds() {
107   scoped_test_env env;
108   path const file = env.create_file("file", 42);
109   const path fifo1 = env.create_fifo("fifo1");
110   const path fifo2 = env.create_fifo("fifo2");
111   // Required to test behavior for inputs where is_other(p) is true.
112   assert(is_other(fifo1));
113   assert(!equivalent(file, fifo1));
114   assert(!equivalent(fifo2, file));
115   assert(!equivalent(fifo1, fifo2));
116   assert(equivalent(fifo1, fifo1));
117 }
118 #endif // _WIN32
119 
main(int,char **)120 int main(int, char**) {
121   signature_test();
122   equivalent_test();
123   equivalent_reports_error_if_input_dne();
124   equivalent_hardlink_succeeds();
125 #ifndef _WIN32
126   equivalent_is_other_succeeds();
127 #endif
128 
129   return 0;
130 }
131