1 | // (C) Copyright Andy Tompkins 2010. Permission to copy, use, modify, sell and |
2 | // distribute this software is granted provided this copyright notice appears |
3 | // in all copies. This software is provided "as is" without express or implied |
4 | // warranty, and with no claim as to its suitability for any purpose. |
5 | |
6 | // Distributed under the Boost Software License, Version 1.0. (See |
7 | // accompanying file LICENSE_1_0.txt or copy at |
8 | // https://www.boost.org/LICENSE_1_0.txt) |
9 | |
10 | // libs/uuid/test/test_random_generator.cpp -------------------------------// |
11 | |
12 | #include <boost/core/ignore_unused.hpp> |
13 | #include <boost/detail/lightweight_test.hpp> |
14 | #include <boost/predef/library/c/cloudabi.h> |
15 | #include <boost/random.hpp> |
16 | #include <boost/uuid/entropy_error.hpp> |
17 | #include <boost/uuid/random_generator.hpp> |
18 | #include <boost/uuid/uuid_io.hpp> |
19 | #include <boost/uuid/uuid.hpp> |
20 | #include <boost/move/utility_core.hpp> |
21 | |
22 | template <typename RandomUuidGenerator> |
23 | void check_random_generator(RandomUuidGenerator& uuid_gen) |
24 | { |
25 | boost::uuids::uuid u1 = uuid_gen(); |
26 | boost::uuids::uuid u2 = uuid_gen(); |
27 | |
28 | BOOST_TEST_NE(u1, u2); |
29 | |
30 | // check variant |
31 | BOOST_TEST_EQ(u1.variant(), boost::uuids::uuid::variant_rfc_4122); |
32 | |
33 | // version |
34 | BOOST_TEST_EQ(u1.version(), boost::uuids::uuid::version_random_number_based); |
35 | } |
36 | |
37 | // This is the example block from the documentation - ensure it works! |
38 | void test_examples() |
39 | { |
40 | // Depending on the platform there may be a setup cost in |
41 | // initializing the generator so plan to reuse it if you can. |
42 | boost::uuids::random_generator gen; |
43 | boost::uuids::uuid id = gen(); |
44 | boost::uuids::uuid id2 = gen(); |
45 | #if !BOOST_LIB_C_CLOUDABI |
46 | std::cout << id << std::endl; |
47 | std::cout << id2 << std::endl; |
48 | #endif |
49 | BOOST_TEST_NE(id, id2); |
50 | boost::ignore_unused(id); |
51 | boost::ignore_unused(id2); |
52 | |
53 | // You can still use a PseudoRandomNumberGenerator to create |
54 | // UUIDs, however this is not the preferred mechanism. For |
55 | // large numbers of UUIDs this may be more CPU efficient but |
56 | // it comes with all the perils of a PRNG. The test code |
57 | // in test_bench_random identifies the transition point for |
58 | // a given system. |
59 | boost::uuids::random_generator_mt19937 bulkgen; |
60 | for (size_t i = 0; i < 1000; ++i) |
61 | { |
62 | boost::uuids::uuid u = bulkgen(); |
63 | // do something with u |
64 | boost::ignore_unused(u); |
65 | } |
66 | } |
67 | |
68 | int main(int, char*[]) |
69 | { |
70 | using namespace boost::uuids; |
71 | |
72 | // default random number generator |
73 | { |
74 | random_generator uuid_gen1; |
75 | check_random_generator(uuid_gen&: uuid_gen1); |
76 | #if !BOOST_LIB_C_CLOUDABI |
77 | // dump 10 of them to cout for observation |
78 | for (size_t i = 0; i < 10; ++i) |
79 | { |
80 | std::cout << uuid_gen1() << std::endl; |
81 | } |
82 | #endif |
83 | } |
84 | |
85 | // specific random number generator |
86 | { |
87 | basic_random_generator<boost::rand48> uuid_gen2; |
88 | check_random_generator(uuid_gen&: uuid_gen2); |
89 | } |
90 | |
91 | // pass by reference |
92 | { |
93 | boost::ecuyer1988 ecuyer1988_gen; |
94 | basic_random_generator<boost::ecuyer1988> uuid_gen3(ecuyer1988_gen); |
95 | check_random_generator(uuid_gen&: uuid_gen3); |
96 | } |
97 | |
98 | // pass by pointer |
99 | { |
100 | boost::lagged_fibonacci607 lagged_fibonacci607_gen; |
101 | basic_random_generator<boost::lagged_fibonacci607> uuid_gen4(&lagged_fibonacci607_gen); |
102 | check_random_generator(uuid_gen&: uuid_gen4); |
103 | } |
104 | |
105 | // check move construction |
106 | { |
107 | random_generator uuid_gen1; |
108 | random_generator uuid_gen2(boost::move(t&: uuid_gen1)); |
109 | boost::ignore_unused(uuid_gen2); |
110 | } |
111 | { |
112 | basic_random_generator<boost::rand48> uuid_gen1; |
113 | basic_random_generator<boost::rand48> uuid_gen2(boost::move(t&: uuid_gen1)); |
114 | boost::ignore_unused(uuid_gen2); |
115 | } |
116 | |
117 | // check move assignment |
118 | { |
119 | random_generator uuid_gen1, uuid_gen2; |
120 | uuid_gen2 = boost::move(t&: uuid_gen1); |
121 | boost::ignore_unused(uuid_gen2); |
122 | } |
123 | { |
124 | basic_random_generator<boost::rand48> uuid_gen1, uuid_gen2; |
125 | uuid_gen2 = boost::move(t&: uuid_gen1); |
126 | boost::ignore_unused(uuid_gen2); |
127 | } |
128 | |
129 | // there was a bug in basic_random_generator where it did not |
130 | // produce very random numbers. This checks for that bug. |
131 | { |
132 | random_generator_mt19937 bulkgen; |
133 | uuid u = bulkgen(); |
134 | if ((u.data[4] == u.data[12]) && |
135 | (u.data[5] == u.data[9] && u.data[5] == u.data[13]) && |
136 | (u.data[7] == u.data[11] && u.data[7] == u.data[15]) && |
137 | (u.data[10] == u.data[14])) |
138 | { |
139 | BOOST_ERROR("basic_random_generator is not producing random uuids" ); |
140 | } |
141 | |
142 | // pseudo |
143 | check_random_generator(uuid_gen&: bulkgen); |
144 | } |
145 | |
146 | // make sure default construction seeding is happening for PRNGs |
147 | { |
148 | random_generator_mt19937 gen1; |
149 | random_generator_mt19937 gen2; |
150 | BOOST_TEST_NE(gen1(), gen2()); |
151 | } |
152 | |
153 | // The example code snippet in the documentation |
154 | test_examples(); |
155 | |
156 | return boost::report_errors(); |
157 | } |
158 | |