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 // <filesystem>
15 
16 // path read_symlink(const path& p);
17 // path read_symlink(const path& p, error_code& ec);
18 
19 #include <filesystem>
20 
21 #include "test_macros.h"
22 #include "filesystem_test_helper.h"
23 namespace fs = std::filesystem;
24 using namespace fs;
25 
test_signatures()26 static void test_signatures()
27 {
28     const path p; ((void)p);
29     std::error_code ec; ((void)ec);
30     ASSERT_SAME_TYPE(decltype(fs::read_symlink(p)), fs::path);
31     ASSERT_SAME_TYPE(decltype(fs::read_symlink(p, ec)), fs::path);
32 
33     ASSERT_NOT_NOEXCEPT(fs::read_symlink(p));
34     // Not noexcept because of narrow contract
35     ASSERT_NOT_NOEXCEPT(fs::read_symlink(p, ec));
36 }
37 
test_error_reporting()38 static void test_error_reporting()
39 {
40     auto checkThrow = [](path const& f, const std::error_code& ec)
41     {
42 #ifndef TEST_HAS_NO_EXCEPTIONS
43         try {
44             (void)fs::read_symlink(f);
45             return false;
46         } catch (filesystem_error const& err) {
47             return err.path1() == f
48                 && err.path2() == ""
49                 && err.code() == ec;
50         }
51 #else
52         ((void)f); ((void)ec);
53         return true;
54 #endif
55     };
56 
57     scoped_test_env env;
58     const path cases[] = {
59         env.make_env_path("dne"),
60         env.create_file("file", 42),
61         env.create_dir("dir")
62     };
63     for (path const& p : cases) {
64         std::error_code ec;
65         const path ret = fs::read_symlink(p, ec);
66         assert(ec);
67         assert(ret == path{});
68         assert(checkThrow(p, ec));
69     }
70 
71 }
72 
basic_symlink_test()73 static void basic_symlink_test()
74 {
75     scoped_test_env env;
76     const path dne = env.make_env_path("dne");
77     const path file = env.create_file("file", 42);
78     const path dir = env.create_dir("dir");
79     const path link = env.create_symlink(dne, "link");
80     const path nested_link = env.make_env_path("nested_link");
81     create_symlink(link, nested_link);
82     struct TestCase {
83       path symlink;
84       path expected;
85     } testCases[] = {
86         {env.create_symlink(dne, "dne_link"), dne},
87         {env.create_symlink(file, "file_link"), file},
88         {env.create_directory_symlink(dir, "dir_link"), dir},
89         {nested_link, link}
90     };
91     for (auto& TC : testCases) {
92         std::error_code ec = std::make_error_code(std::errc::address_in_use);
93         const path ret = read_symlink(TC.symlink, ec);
94         assert(!ec);
95         assert(ret == TC.expected);
96     }
97 }
98 
main(int,char **)99 int main(int, char**) {
100     test_signatures();
101     test_error_reporting();
102     basic_symlink_test();
103 
104     return 0;
105 }
106