• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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>
check_random_generator(RandomUuidGenerator & uuid_gen)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!
test_examples()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 
main(int,char * [])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_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_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_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_gen4);
103     }
104 
105     // check move construction
106     {
107         random_generator uuid_gen1;
108         random_generator uuid_gen2(boost::move(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(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(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(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(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