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 bugs.llvm.org/PR20183
10 //
11 // XFAIL: with_system_cxx_lib=macosx10.11
12 // XFAIL: with_system_cxx_lib=macosx10.10
13 // XFAIL: with_system_cxx_lib=macosx10.9
14 
15 // UNSUPPORTED: libcpp-has-no-random-device
16 
17 // <random>
18 
19 // class random_device;
20 
21 // explicit random_device(const string& token = implementation-defined);
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 <system_error>
30 #include <cassert>
31 
32 #if !defined(_WIN32)
33 #include <unistd.h>
34 #endif
35 
36 #include "test_macros.h"
37 
38 
is_valid_random_device(const std::string & token)39 bool is_valid_random_device(const std::string &token) {
40 #if defined(_LIBCPP_USING_DEV_RANDOM)
41   // Not an exhaustive list: they're the only tokens that are tested below.
42   return token == "/dev/urandom" || token == "/dev/random";
43 #else
44   return token == "/dev/urandom";
45 #endif
46 }
47 
check_random_device_valid(const std::string & token)48 void check_random_device_valid(const std::string &token) {
49   std::random_device r(token);
50 }
51 
check_random_device_invalid(const std::string & token)52 void check_random_device_invalid(const std::string &token) {
53 #ifndef TEST_HAS_NO_EXCEPTIONS
54   try {
55     std::random_device r(token);
56     LIBCPP_ASSERT(false);
57   } catch (const std::system_error&) {
58   }
59 #else
60   ((void)token);
61 #endif
62 }
63 
64 
main(int,char **)65 int main(int, char**) {
66   {
67     std::random_device r;
68   }
69   {
70     std::string token = "wrong file";
71     check_random_device_invalid(token);
72   }
73   {
74     std::string token = "/dev/urandom";
75     if (is_valid_random_device(token))
76       check_random_device_valid(token);
77     else
78       check_random_device_invalid(token);
79   }
80   {
81     std::string token = "/dev/random";
82     if (is_valid_random_device(token))
83       check_random_device_valid(token);
84     else
85       check_random_device_invalid(token);
86   }
87 #if !defined(_WIN32)
88 // Test that random_device(const string&) properly handles getting
89 // a file descriptor with the value '0'. Do this by closing the standard
90 // streams so that the descriptor '0' is available.
91   {
92     int ec;
93     ec = close(STDIN_FILENO);
94     assert(!ec);
95     ec = close(STDOUT_FILENO);
96     assert(!ec);
97     ec = close(STDERR_FILENO);
98     assert(!ec);
99     std::random_device r;
100   }
101 #endif // !defined(_WIN32)
102 
103   return 0;
104 }
105