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 // See https://llvm.org/PR20183
10 // XFAIL: use_system_cxx_lib && target={{.+}}-apple-macosx10.{{9|10|11}}
11 
12 // The behavior of std::random_device changed on Apple platforms with
13 // https://llvm.org/D116045.
14 // XFAIL: use_system_cxx_lib && target={{.+}}-apple-macosx10.{{9|10|11|12|13|14|15}}
15 // XFAIL: use_system_cxx_lib && target={{.+}}-apple-macosx{{11.0|12.0}}
16 
17 // UNSUPPORTED: no-random-device
18 
19 // <random>
20 
21 // class random_device;
22 
23 // explicit random_device(const string& token = implementation-defined); // before C++20
24 // random_device() : random_device(implementation-defined) {}            // C++20
25 // explicit random_device(const string& token);                          // C++20
26 
27 // For the following ctors, the standard states: "The semantics and default
28 // value of the token parameter are implementation-defined". Implementations
29 // therefore aren't required to accept any string, but the default shouldn't
30 // throw.
31 
32 #include <random>
33 #include <system_error>
34 #include <cassert>
35 
36 #if !defined(_WIN32)
37 #include <unistd.h>
38 #endif
39 
40 #include "test_macros.h"
41 #if TEST_STD_VER >= 11
42 #include "test_convertible.h"
43 #endif
44 
check_random_device_valid(const std::string & token)45 void check_random_device_valid(const std::string &token) {
46   std::random_device r(token);
47 }
48 
check_random_device_invalid(const std::string & token)49 void check_random_device_invalid(const std::string &token) {
50 #ifndef TEST_HAS_NO_EXCEPTIONS
51   try {
52     std::random_device r(token);
53     LIBCPP_ASSERT(false);
54   } catch (const std::system_error&) {
55   }
56 #else
57   ((void)token);
58 #endif
59 }
60 
main(int,char **)61 int main(int, char**) {
62   {
63     std::random_device r;
64   }
65   // Check the validity of various tokens
66   {
67 #if defined(_LIBCPP_USING_ARC4_RANDOM)
68     check_random_device_valid("/dev/urandom");
69     check_random_device_valid("/dev/random");
70     check_random_device_valid("/dev/null");
71     check_random_device_valid("/dev/nonexistent");
72     check_random_device_valid("wrong file");
73 #elif defined(_LIBCPP_USING_DEV_RANDOM)
74     check_random_device_valid("/dev/urandom");
75     check_random_device_valid("/dev/random");
76     check_random_device_valid("/dev/null");
77     check_random_device_invalid("/dev/nonexistent");
78     check_random_device_invalid("wrong file");
79 #else
80     check_random_device_valid("/dev/urandom");
81     check_random_device_invalid("/dev/random");
82     check_random_device_invalid("/dev/null");
83     check_random_device_invalid("/dev/nonexistent");
84     check_random_device_invalid("wrong file");
85 #endif
86   }
87 
88 #if !defined(_WIN32)
89 // Test that random_device(const string&) properly handles getting
90 // a file descriptor with the value '0'. Do this by closing the standard
91 // streams so that the descriptor '0' is available.
92   {
93     int ec;
94     ec = close(STDIN_FILENO);
95     assert(!ec);
96     ec = close(STDOUT_FILENO);
97     assert(!ec);
98     ec = close(STDERR_FILENO);
99     assert(!ec);
100     std::random_device r;
101   }
102 #endif // !defined(_WIN32)
103 
104 #if TEST_STD_VER >= 11
105   static_assert(test_convertible<std::random_device>(), "");
106 #endif
107 
108   return 0;
109 }
110