1/* test_generator.ipp 2 * 3 * Copyright Steven Watanabe 2011 4 * Distributed under the Boost Software License, Version 1.0. (See 5 * accompanying file LICENSE_1_0.txt or copy at 6 * http://www.boost.org/LICENSE_1_0.txt) 7 * 8 * $Id$ 9 * 10 */ 11 12#include "concepts.hpp" 13#include <boost/random/seed_seq.hpp> 14 15#define BOOST_TEST_MAIN 16#include <boost/test/unit_test.hpp> 17 18using boost::random::test::RandomNumberEngine; 19BOOST_CONCEPT_ASSERT((RandomNumberEngine< BOOST_RANDOM_URNG >)); 20 21typedef BOOST_RANDOM_URNG::result_type result_type; 22typedef boost::random::detail::seed_type<result_type>::type seed_type; 23 24#ifdef BOOST_MSVC 25#pragma warning(push) 26#pragma warning(disable:4244) 27#endif 28 29#ifndef BOOST_RANDOM_DISCARD_COUNT1 30#define BOOST_RANDOM_DISCARD_COUNT1 9307 31#endif 32 33template<class Converted, class URNG, class T> 34void test_seed_conversion(URNG & urng, const T & t) 35{ 36 Converted c = static_cast<Converted>(t); 37 if(static_cast<T>(c) == t) { 38 URNG urng2(c); 39 std::ostringstream msg; 40 msg << "Testing seed: type " << typeid(Converted).name() << ", value " << c; 41 BOOST_CHECK_MESSAGE(urng == urng2, msg.str()); 42 urng2.seed(c); 43 BOOST_CHECK_MESSAGE(urng == urng2, msg.str()); 44 } 45} 46 47#ifdef BOOST_MSVC 48#pragma warning(pop) 49#endif 50 51void test_seed(seed_type value) 52{ 53 BOOST_RANDOM_URNG urng(value); 54 55 // integral types 56 test_seed_conversion<char>(urng, value); 57 test_seed_conversion<signed char>(urng, value); 58 test_seed_conversion<unsigned char>(urng, value); 59 test_seed_conversion<short>(urng, value); 60 test_seed_conversion<unsigned short>(urng, value); 61 test_seed_conversion<int>(urng, value); 62 test_seed_conversion<unsigned int>(urng, value); 63 test_seed_conversion<long>(urng, value); 64 test_seed_conversion<unsigned long>(urng, value); 65#if !defined(BOOST_NO_INT64_T) 66 test_seed_conversion<boost::int64_t>(urng, value); 67 test_seed_conversion<boost::uint64_t>(urng, value); 68#endif 69 70 // floating point types 71 test_seed_conversion<float>(urng, value); 72 test_seed_conversion<double>(urng, value); 73 test_seed_conversion<long double>(urng, value); 74} 75 76BOOST_AUTO_TEST_CASE(test_default_seed) 77{ 78 BOOST_RANDOM_URNG urng; 79 BOOST_RANDOM_URNG urng2; 80 urng2(); 81 BOOST_CHECK_NE(urng, urng2); 82 urng2.seed(); 83 BOOST_CHECK_EQUAL(urng, urng2); 84} 85 86BOOST_AUTO_TEST_CASE(test_arithmetic_seed) 87{ 88 test_seed(static_cast<seed_type>(0)); 89 test_seed(static_cast<seed_type>(127)); 90 test_seed(static_cast<seed_type>(539157235)); 91 test_seed(static_cast<seed_type>(~0u)); 92} 93 94BOOST_AUTO_TEST_CASE(test_iterator_seed) 95{ 96 const std::vector<int> v((std::max)(std::size_t(9999u), sizeof(BOOST_RANDOM_URNG) / 4), 0x41); 97 std::vector<int>::const_iterator it = v.begin(); 98 std::vector<int>::const_iterator it_end = v.end(); 99 BOOST_RANDOM_URNG urng(it, it_end); 100 BOOST_CHECK(it != v.begin()); 101 std::iterator_traits<std::vector<int>::const_iterator>::difference_type n_words = (it - v.begin()); 102 BOOST_CHECK_GT(n_words, 0); 103 BOOST_CHECK_EQUAL(n_words, BOOST_RANDOM_SEED_WORDS); 104 105 it = v.begin(); 106 BOOST_RANDOM_URNG urng2; 107 urng2.seed(it, it_end); 108 std::iterator_traits<std::vector<int>::const_iterator>::difference_type n_words2 = (it - v.begin()); 109 BOOST_CHECK_EQUAL(n_words, n_words2); 110 BOOST_CHECK_EQUAL(urng, urng2); 111 112 it = v.end(); 113 BOOST_CHECK_THROW(BOOST_RANDOM_URNG(it, it_end), std::invalid_argument); 114 BOOST_CHECK_THROW(urng.seed(it, it_end), std::invalid_argument); 115 116 if(n_words > 1) { 117 it = v.end(); 118 --it; 119 BOOST_CHECK_THROW(BOOST_RANDOM_URNG(it, it_end), std::invalid_argument); 120 it = v.end(); 121 --it; 122 BOOST_CHECK_THROW(urng.seed(it, it_end), std::invalid_argument); 123 } 124} 125 126BOOST_AUTO_TEST_CASE(test_seed_seq_seed) 127{ 128 boost::random::seed_seq q; 129 BOOST_RANDOM_URNG urng(q); 130 BOOST_RANDOM_URNG urng2; 131 BOOST_CHECK_NE(urng, urng2); 132 urng2.seed(q); 133 BOOST_CHECK_EQUAL(urng, urng2); 134} 135 136template<class CharT> 137void do_test_streaming(const BOOST_RANDOM_URNG& urng) 138{ 139 BOOST_RANDOM_URNG urng2; 140 std::basic_ostringstream<CharT> output; 141 output << urng; 142 BOOST_CHECK_NE(urng, urng2); 143 // restore old state 144 std::basic_istringstream<CharT> input(output.str()); 145 input >> urng2; 146 BOOST_CHECK_EQUAL(urng, urng2); 147} 148 149BOOST_AUTO_TEST_CASE(test_streaming) 150{ 151 BOOST_RANDOM_URNG urng; 152 urng.discard(9307); 153 do_test_streaming<char>(urng); 154#if !defined(BOOST_NO_STD_WSTREAMBUF) && !defined(BOOST_NO_STD_WSTRING) 155 do_test_streaming<wchar_t>(urng); 156#endif 157} 158 159BOOST_AUTO_TEST_CASE(test_discard) 160{ 161 BOOST_RANDOM_URNG urng; 162 BOOST_RANDOM_URNG urng2; 163 BOOST_CHECK_EQUAL(urng, urng2); 164 for(int i = 0; i < BOOST_RANDOM_DISCARD_COUNT1; ++i) 165 urng(); 166 BOOST_CHECK_NE(urng, urng2); 167 urng2.discard(BOOST_RANDOM_DISCARD_COUNT1); 168 BOOST_CHECK_EQUAL(urng, urng2); 169} 170 171#ifdef BOOST_RANDOM_DISCARD_COUNT2 172BOOST_AUTO_TEST_CASE(test_discard2) 173{ 174 BOOST_RANDOM_URNG urng; 175 BOOST_RANDOM_URNG urng2; 176 BOOST_CHECK_EQUAL(urng, urng2); 177 for(int i = 0; i < BOOST_RANDOM_DISCARD_COUNT2; ++i) 178 urng(); 179 BOOST_CHECK_NE(urng, urng2); 180 urng2.discard(BOOST_RANDOM_DISCARD_COUNT2); 181 BOOST_CHECK_EQUAL(urng, urng2); 182} 183#endif 184 185#ifdef BOOST_RANDOM_DISCARD_MAX 186BOOST_AUTO_TEST_CASE(test_discard_max) 187{ 188 boost::uintmax_t val = (std::numeric_limits<boost::uintmax_t>::max)(); 189 boost::uintmax_t half = val / 2; 190 BOOST_RANDOM_URNG urng; 191 BOOST_RANDOM_URNG urng2; 192 urng.discard(half); 193 urng.discard(half); 194 urng.discard(val - 2*half); 195 urng2.discard(val); 196 BOOST_CHECK_EQUAL(urng, urng2); 197} 198#endif 199 200BOOST_AUTO_TEST_CASE(test_copy) 201{ 202 BOOST_RANDOM_URNG urng; 203 urng.discard(9307); 204 { 205 BOOST_RANDOM_URNG urng2 = urng; 206 BOOST_CHECK_EQUAL(urng, urng2); 207 } 208 { 209 BOOST_RANDOM_URNG urng2(urng); 210 BOOST_CHECK_EQUAL(urng, urng2); 211 } 212 { 213 BOOST_RANDOM_URNG urng2; 214 urng2 = urng; 215 BOOST_CHECK_EQUAL(urng, urng2); 216 } 217} 218 219BOOST_AUTO_TEST_CASE(test_min_max) 220{ 221 BOOST_RANDOM_URNG urng; 222 for(int i = 0; i < 10000; ++i) { 223 result_type value = urng(); 224 BOOST_CHECK_GE(value, (BOOST_RANDOM_URNG::min)()); 225 BOOST_CHECK_LE(value, (BOOST_RANDOM_URNG::max)()); 226 } 227} 228 229BOOST_AUTO_TEST_CASE(test_comparison) 230{ 231 BOOST_RANDOM_URNG urng; 232 BOOST_RANDOM_URNG urng2; 233 BOOST_CHECK(urng == urng2); 234 BOOST_CHECK(!(urng != urng2)); 235 urng(); 236 BOOST_CHECK(urng != urng2); 237 BOOST_CHECK(!(urng == urng2)); 238} 239 240BOOST_AUTO_TEST_CASE(validate) 241{ 242 BOOST_RANDOM_URNG urng; 243 for(int i = 0; i < 9999; ++i) { 244 urng(); 245 } 246 BOOST_CHECK_EQUAL(urng(), BOOST_RANDOM_VALIDATION_VALUE); 247} 248 249BOOST_AUTO_TEST_CASE(validate_seed_seq) 250{ 251 boost::random::seed_seq seed; 252 BOOST_RANDOM_URNG urng(seed); 253 for(int i = 0; i < 9999; ++i) { 254 urng(); 255 } 256 BOOST_CHECK_EQUAL(urng(), BOOST_RANDOM_SEED_SEQ_VALIDATION_VALUE); 257} 258 259BOOST_AUTO_TEST_CASE(validate_iter) 260{ 261 const std::vector<int> v((std::max)(std::size_t(9999u), sizeof(BOOST_RANDOM_URNG) / 4), 0x41); 262 std::vector<int>::const_iterator it = v.begin(); 263 std::vector<int>::const_iterator it_end = v.end(); 264 BOOST_RANDOM_URNG urng(it, it_end); 265 for(int i = 0; i < 9999; ++i) { 266 urng(); 267 } 268 BOOST_CHECK_EQUAL(urng(), BOOST_RANDOM_ITERATOR_VALIDATION_VALUE); 269} 270 271BOOST_AUTO_TEST_CASE(test_generate) 272{ 273 BOOST_RANDOM_URNG urng; 274 boost::uint32_t expected[] = BOOST_RANDOM_GENERATE_VALUES; 275 static const std::size_t N = sizeof(expected)/sizeof(expected[0]); 276 boost::uint32_t actual[N]; 277 urng.generate(&actual[0], &actual[0] + N); 278 BOOST_CHECK_EQUAL_COLLECTIONS(actual, actual + N, expected, expected + N); 279} 280