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: use_system_cxx_lib && target={{.+}}-apple-macosx10.{{9|10|11}} 12 13 // UNSUPPORTED: libcpp-has-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 <system_error> 30 #include <cassert> 31 32 #if !defined(_WIN32) 33 #include <unistd.h> 34 #endif 35 36 #include "test_macros.h" 37 #if TEST_STD_VER >= 11 38 #include "test_convertible.h" 39 #endif 40 41 bool is_valid_random_device(const std::string &token) { 42 #if defined(_LIBCPP_USING_DEV_RANDOM) 43 // Not an exhaustive list: they're the only tokens that are tested below. 44 return token == "/dev/urandom" || token == "/dev/random"; 45 #else 46 return token == "/dev/urandom"; 47 #endif 48 } 49 50 void check_random_device_valid(const std::string &token) { 51 std::random_device r(token); 52 } 53 54 void check_random_device_invalid(const std::string &token) { 55 #ifndef TEST_HAS_NO_EXCEPTIONS 56 try { 57 std::random_device r(token); 58 LIBCPP_ASSERT(false); 59 } catch (const std::system_error&) { 60 } 61 #else 62 ((void)token); 63 #endif 64 } 65 66 int main(int, char**) { 67 { 68 std::random_device r; 69 } 70 { 71 std::string token = "wrong file"; 72 check_random_device_invalid(token); 73 } 74 { 75 std::string token = "/dev/urandom"; 76 if (is_valid_random_device(token)) 77 check_random_device_valid(token); 78 else 79 check_random_device_invalid(token); 80 } 81 { 82 std::string token = "/dev/random"; 83 if (is_valid_random_device(token)) 84 check_random_device_valid(token); 85 else 86 check_random_device_invalid(token); 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