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 // <random>
16 
17 // class random_device;
18 
19 // explicit random_device(const string& token = implementation-defined);
20 
21 // For the following ctors, the standard states: "The semantics and default
22 // value of the token parameter are implementation-defined". Implementations
23 // therefore aren't required to accept any string, but the default shouldn't
24 // throw.
25 
26 #include <random>
27 #include <system_error>
28 #include <cassert>
29 
30 #if !defined(_WIN32)
31 #include <unistd.h>
32 #endif
33 
34 #include "test_macros.h"
35 
36 
37 bool is_valid_random_device(const std::string &token) {
38 #if defined(_LIBCPP_USING_DEV_RANDOM)
39   // Not an exhaustive list: they're the only tokens that are tested below.
40   return token == "/dev/urandom" || token == "/dev/random";
41 #else
42   return token == "/dev/urandom";
43 #endif
44 }
45 
46 void check_random_device_valid(const std::string &token) {
47   std::random_device r(token);
48 }
49 
50 void check_random_device_invalid(const std::string &token) {
51 #ifndef TEST_HAS_NO_EXCEPTIONS
52   try {
53     std::random_device r(token);
54     LIBCPP_ASSERT(false);
55   } catch (const std::system_error&) {
56   }
57 #else
58   ((void)token);
59 #endif
60 }
61 
62 
63 int main(int, char**) {
64   {
65     std::random_device r;
66   }
67   {
68     std::string token = "wrong file";
69     check_random_device_invalid(token);
70   }
71   {
72     std::string token = "/dev/urandom";
73     if (is_valid_random_device(token))
74       check_random_device_valid(token);
75     else
76       check_random_device_invalid(token);
77   }
78   {
79     std::string token = "/dev/random";
80     if (is_valid_random_device(token))
81       check_random_device_valid(token);
82     else
83       check_random_device_invalid(token);
84   }
85 #if !defined(_WIN32)
86 // Test that random_device(const string&) properly handles getting
87 // a file descriptor with the value '0'. Do this by closing the standard
88 // streams so that the descriptor '0' is available.
89   {
90     int ec;
91     ec = close(STDIN_FILENO);
92     assert(!ec);
93     ec = close(STDOUT_FILENO);
94     assert(!ec);
95     ec = close(STDERR_FILENO);
96     assert(!ec);
97     std::random_device r;
98   }
99 #endif // !defined(_WIN32)
100 
101   return 0;
102 }
103