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