Imported Upstream version 1.57.0
[platform/upstream/boost.git] / libs / lexical_cast / test / lexical_cast_integral_types_test.cpp
1 //  Unit test for boost::lexical_cast.
2 //
3 //  See http://www.boost.org for most recent version, including documentation.
4 //
5 //  Copyright Terje Sletteb and Kevlin Henney, 2005.
6 //  Copyright Alexander Nasonov, 2006.
7 //  Copyright Antony Polukhin, 2011-2012.
8 //
9 //  Distributed under the Boost
10 //  Software License, Version 1.0. (See accompanying file
11 //  LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt).
12 //
13 // Note: The unit test no longer compile on MSVC 6, but lexical_cast itself works for it.
14
15 //
16 // We need this #define before any #includes: otherwise msvc will emit warnings
17 // deep within std::string, resulting from our (perfectly legal) use of basic_string
18 // with a custom traits class:
19 //
20 #define _SCL_SECURE_NO_WARNINGS
21
22 #include <boost/config.hpp>
23
24 #if defined(__INTEL_COMPILER)
25 #pragma warning(disable: 193 383 488 981 1418 1419)
26 #elif defined(BOOST_MSVC)
27 #pragma warning(disable: 4097 4100 4121 4127 4146 4244 4245 4511 4512 4701 4800)
28 #endif
29
30 #include <boost/lexical_cast.hpp>
31
32 #include <boost/cstdint.hpp>
33 #include <boost/test/unit_test.hpp>
34 #include <boost/test/floating_point_comparison.hpp>
35
36 #include <boost/type_traits/integral_promotion.hpp>
37 #include <boost/type_traits/make_unsigned.hpp>
38 #include <string>
39 #include <vector>
40 #include <memory>
41
42 #if (defined(BOOST_HAS_LONG_LONG) || defined(BOOST_HAS_MS_INT64)) \
43     && !(defined(BOOST_MSVC) && BOOST_MSVC < 1300)
44 #define LCAST_TEST_LONGLONG
45 #endif
46
47 #if defined(BOOST_NO_STRINGSTREAM) || defined(BOOST_NO_STD_WSTRING)
48 #define BOOST_LCAST_NO_WCHAR_T
49 #endif
50
51 // Test all 65536 values if true:
52 bool const lcast_test_small_integral_types_completely = false;
53
54 // lcast_integral_test_counter: use when testing all values of an integral
55 // types is not possible. Max. portable value is 32767.
56 int const lcast_integral_test_counter=500;
57
58 using namespace boost;
59
60
61
62 void test_conversion_from_to_short();
63 void test_conversion_from_to_ushort();
64 void test_conversion_from_to_int();
65 void test_conversion_from_to_uint();
66 void test_conversion_from_to_long();
67 void test_conversion_from_to_ulong();
68 void test_conversion_from_to_intmax_t();
69 void test_conversion_from_to_uintmax_t();
70 #ifdef LCAST_TEST_LONGLONG
71 void test_conversion_from_to_longlong();
72 void test_conversion_from_to_ulonglong();
73 #endif
74 #ifdef BOOST_HAS_INT128
75 void test_conversion_from_to_int128();
76 void test_conversion_from_to_uint128();
77 #endif
78 void test_integral_conversions_on_min_max();
79
80
81 unit_test::test_suite *init_unit_test_suite(int, char *[])
82 {
83     unit_test::test_suite *suite =
84         BOOST_TEST_SUITE("lexical_cast unit test on integral types");
85
86     suite->add(BOOST_TEST_CASE(&test_conversion_from_to_short));
87     suite->add(BOOST_TEST_CASE(&test_conversion_from_to_ushort));
88     suite->add(BOOST_TEST_CASE(&test_conversion_from_to_int));
89     suite->add(BOOST_TEST_CASE(&test_conversion_from_to_uint));
90     suite->add(BOOST_TEST_CASE(&test_conversion_from_to_long));
91     suite->add(BOOST_TEST_CASE(&test_conversion_from_to_ulong));
92     suite->add(BOOST_TEST_CASE(&test_conversion_from_to_intmax_t));
93     suite->add(BOOST_TEST_CASE(&test_conversion_from_to_uintmax_t));
94 #ifdef LCAST_TEST_LONGLONG
95     suite->add(BOOST_TEST_CASE(&test_conversion_from_to_longlong));
96     suite->add(BOOST_TEST_CASE(&test_conversion_from_to_ulonglong));
97 #endif
98 #ifdef BOOST_HAS_INT128
99     suite->add(BOOST_TEST_CASE(&test_conversion_from_to_int128));
100     suite->add(BOOST_TEST_CASE(&test_conversion_from_to_uint128));
101 #endif
102     suite->add(BOOST_TEST_CASE(&test_integral_conversions_on_min_max));
103
104     return suite;
105 }
106
107 template<class T, class CharT>
108 void test_conversion_from_integral_to_char(CharT zero)
109 {
110     BOOST_CHECK(lexical_cast<CharT>(static_cast<T>(0)) == zero + 0);
111     BOOST_CHECK(lexical_cast<CharT>(static_cast<T>(1)) == zero + 1);
112     BOOST_CHECK(lexical_cast<CharT>(static_cast<T>(2)) == zero + 2);
113     BOOST_CHECK(lexical_cast<CharT>(static_cast<T>(3)) == zero + 3);
114     BOOST_CHECK(lexical_cast<CharT>(static_cast<T>(4)) == zero + 4);
115     BOOST_CHECK(lexical_cast<CharT>(static_cast<T>(5)) == zero + 5);
116     BOOST_CHECK(lexical_cast<CharT>(static_cast<T>(6)) == zero + 6);
117     BOOST_CHECK(lexical_cast<CharT>(static_cast<T>(7)) == zero + 7);
118     BOOST_CHECK(lexical_cast<CharT>(static_cast<T>(8)) == zero + 8);
119     BOOST_CHECK(lexical_cast<CharT>(static_cast<T>(9)) == zero + 9);
120
121     BOOST_CHECK_THROW(lexical_cast<CharT>(static_cast<T>(10)), bad_lexical_cast);
122
123     T t = (std::numeric_limits<T>::max)();
124     BOOST_CHECK_THROW(lexical_cast<CharT>(t), bad_lexical_cast);
125 }
126
127 template<class T, class CharT>
128 void test_conversion_from_char_to_integral(CharT zero)
129 {
130     BOOST_CHECK(lexical_cast<T>( static_cast<CharT>(zero + 0)) == static_cast<T>(0) );
131     BOOST_CHECK(lexical_cast<T>( static_cast<CharT>(zero + 1)) == static_cast<T>(1) );
132     BOOST_CHECK(lexical_cast<T>( static_cast<CharT>(zero + 2)) == static_cast<T>(2) );
133     BOOST_CHECK(lexical_cast<T>( static_cast<CharT>(zero + 3)) == static_cast<T>(3) );
134     BOOST_CHECK(lexical_cast<T>( static_cast<CharT>(zero + 4)) == static_cast<T>(4) );
135     BOOST_CHECK(lexical_cast<T>( static_cast<CharT>(zero + 5)) == static_cast<T>(5) );
136     BOOST_CHECK(lexical_cast<T>( static_cast<CharT>(zero + 6)) == static_cast<T>(6) );
137     BOOST_CHECK(lexical_cast<T>( static_cast<CharT>(zero + 7)) == static_cast<T>(7) );
138     BOOST_CHECK(lexical_cast<T>( static_cast<CharT>(zero + 8)) == static_cast<T>(8) );
139     BOOST_CHECK(lexical_cast<T>( static_cast<CharT>(zero + 9)) == static_cast<T>(9) );
140
141     BOOST_CHECK_THROW(lexical_cast<T>( static_cast<CharT>(zero + 10)), bad_lexical_cast);
142     BOOST_CHECK_THROW(lexical_cast<T>( static_cast<CharT>(zero - 1)), bad_lexical_cast);
143 }
144
145 template<class T>
146 void test_conversion_from_integral_to_integral()
147 {
148     T t = 0;
149     BOOST_CHECK(lexical_cast<T>(t) == t);
150
151     // Next two variables are used to supress warnings.
152     int st = 32767; unsigned int ut = st;
153     t = st;
154     BOOST_CHECK(lexical_cast<short>(t) == st);
155     BOOST_CHECK(lexical_cast<unsigned short>(t) == ut);
156     BOOST_CHECK(lexical_cast<int>(t) == st);
157     BOOST_CHECK(lexical_cast<unsigned int>(t) == ut);
158     BOOST_CHECK(lexical_cast<long>(t) == st);
159     BOOST_CHECK(lexical_cast<unsigned long>(t) == ut);
160
161     t = (std::numeric_limits<T>::max)();
162     BOOST_CHECK(lexical_cast<T>(t) == t);
163
164     t = (std::numeric_limits<T>::min)();
165     BOOST_CHECK(lexical_cast<T>(t) == t);
166 }
167
168
169
170
171 // Replace "-,999" with "-999".
172 template<class CharT>
173 std::basic_string<CharT> to_str_gcc_workaround(std::basic_string<CharT> str)
174 {
175     std::locale loc;
176     std::numpunct<CharT> const& np = BOOST_USE_FACET(std::numpunct<CharT>, loc);
177     std::ctype<CharT> const& ct = BOOST_USE_FACET(std::ctype<CharT>, loc);
178
179     if(np.grouping().empty())
180         return str;
181
182     CharT prefix[3] = { ct.widen('-'), np.thousands_sep(), CharT() };
183
184     if(str.find(prefix) != 0)
185         return str;
186
187     prefix[1] = CharT();
188     str.replace(0, 2, prefix);
189     return str;
190 }
191
192 template<class CharT, class T>
193 std::basic_string<CharT> to_str(T t)
194 {
195     std::basic_ostringstream<CharT> o;
196     o << t;
197     return to_str_gcc_workaround(o.str());
198 }
199
200
201 template<class T, class CharT>
202 void test_conversion_from_integral_to_string(CharT)
203 {
204     typedef std::numeric_limits<T> limits;
205     typedef std::basic_string<CharT> string_type;
206
207     T t;
208
209     t = (limits::min)();
210     BOOST_CHECK(lexical_cast<string_type>(t) == to_str<CharT>(t));
211
212     t = (limits::max)();
213     BOOST_CHECK(lexical_cast<string_type>(t) == to_str<CharT>(t));
214
215     if(limits::digits <= 16 && lcast_test_small_integral_types_completely)
216         // min and max have already been tested.
217         for(t = 1 + (limits::min)(); t != (limits::max)(); ++t)
218             BOOST_CHECK(lexical_cast<string_type>(t) == to_str<CharT>(t));
219     else
220     {
221         T const min_val = (limits::min)();
222         T const max_val = (limits::max)();
223         T const half_max_val = max_val / 2;
224         T const cnt = lcast_integral_test_counter; // to supress warnings
225         unsigned int const counter = cnt < half_max_val ? cnt : half_max_val;
226
227         unsigned int i;
228
229         // Test values around min:
230         t = min_val;
231         for(i = 0; i < counter; ++i, ++t)
232             BOOST_CHECK(lexical_cast<string_type>(t) == to_str<CharT>(t));
233
234         // Test values around max:
235         t = max_val;
236         for(i = 0; i < counter; ++i, --t)
237             BOOST_CHECK(lexical_cast<string_type>(t) == to_str<CharT>(t));
238
239         // Test values around zero:
240         if(limits::is_signed)
241             for(t = static_cast<T>(-counter); t < static_cast<T>(counter); ++t)
242                 BOOST_CHECK(lexical_cast<string_type>(t) == to_str<CharT>(t));
243
244         // Test values around 100, 1000, 10000, ...
245         T ten_power = 100;
246         for(int e = 2; e < limits::digits10; ++e, ten_power *= 10)
247         {
248             // ten_power + 100 probably never overflows
249             for(t = ten_power - 100; t != ten_power + 100; ++t)
250                 BOOST_CHECK(lexical_cast<string_type>(t) == to_str<CharT>(t));
251         }
252     }
253 }
254
255 template<class T, class CharT>
256 void test_conversion_from_string_to_integral(CharT)
257 {
258     typedef std::numeric_limits<T> limits;
259     typedef std::basic_string<CharT> string_type;
260
261     string_type s;
262     string_type const zero = to_str<CharT>(0);
263     string_type const nine = to_str<CharT>(9);
264     T const min_val = (limits::min)();
265     T const max_val = (limits::max)();
266
267     s = to_str<CharT>(min_val);
268     BOOST_CHECK_EQUAL(lexical_cast<T>(s), min_val);
269     if(limits::is_signed)
270     {
271         BOOST_CHECK_THROW(lexical_cast<T>(s + zero), bad_lexical_cast);
272         BOOST_CHECK_THROW(lexical_cast<T>(s + nine), bad_lexical_cast);
273     }
274
275     s = to_str<CharT>(max_val);
276     BOOST_CHECK_EQUAL(lexical_cast<T>(s), max_val);
277     {
278         BOOST_CHECK_THROW(lexical_cast<T>(s + zero), bad_lexical_cast);
279         BOOST_CHECK_THROW(lexical_cast<T>(s + nine), bad_lexical_cast);
280
281         s = to_str<CharT>(max_val);
282         for (int i =1; i <=10; ++i) {
283             s[s.size()-1] += 1;
284             BOOST_CHECK_THROW(lexical_cast<T>( s ), bad_lexical_cast);
285         }
286
287         s = to_str<CharT>(max_val);
288         std::locale loc;
289         typedef std::numpunct<char> numpunct;
290         if ( BOOST_USE_FACET(numpunct, loc).grouping().empty() ) {
291             // Following tests work well for locale C
292             BOOST_CHECK_EQUAL(lexical_cast<T>(to_str<CharT>(0)+s), max_val);
293             BOOST_CHECK_EQUAL(lexical_cast<T>(to_str<CharT>(0)+to_str<CharT>(0)+s), max_val);
294             BOOST_CHECK_EQUAL(lexical_cast<T>(to_str<CharT>(0)+to_str<CharT>(0)+to_str<CharT>(0)+s), max_val);
295         }
296
297         for (int i =1; i <=256; ++i) {
298             BOOST_CHECK_THROW(lexical_cast<T>( to_str<CharT>(i)+s ), bad_lexical_cast);
299         }
300
301         typedef BOOST_DEDUCED_TYPENAME boost::integral_promotion<T>::type promoted;
302         if ( !(boost::is_same<T, promoted>::value) )
303         {
304             promoted prom = max_val;
305             s = to_str<CharT>(max_val);
306             for (int i =1; i <=256; ++i) {
307                 BOOST_CHECK_THROW(lexical_cast<T>( to_str<CharT>(prom+i) ), bad_lexical_cast);
308                 BOOST_CHECK_THROW(lexical_cast<T>( to_str<CharT>(i)+s ), bad_lexical_cast);
309             }
310         }
311     }
312
313     if(limits::digits <= 16 && lcast_test_small_integral_types_completely)
314         // min and max have already been tested.
315         for(T t = 1 + min_val; t != max_val; ++t)
316             BOOST_CHECK(lexical_cast<T>(to_str<CharT>(t)) == t);
317     else
318     {
319         T const half_max_val = max_val / 2;
320         T const cnt = lcast_integral_test_counter; // to supress warnings
321         unsigned int const counter = cnt < half_max_val ? cnt : half_max_val;
322
323         T t;
324         unsigned int i;
325
326         // Test values around min:
327         t = min_val;
328         for(i = 0; i < counter; ++i, ++t)
329             BOOST_CHECK(lexical_cast<T>(to_str<CharT>(t)) == t);
330
331         // Test values around max:
332         t = max_val;
333         for(i = 0; i < counter; ++i, --t)
334             BOOST_CHECK(lexical_cast<T>(to_str<CharT>(t)) == t);
335
336         // Test values around zero:
337         if(limits::is_signed)
338             for(t = static_cast<T>(-counter); t < static_cast<T>(counter); ++t)
339                 BOOST_CHECK(lexical_cast<T>(to_str<CharT>(t)) == t);
340
341         // Test values around 100, 1000, 10000, ...
342         T ten_power = 100;
343         for(int e = 2; e < limits::digits10; ++e, ten_power *= 10)
344         {
345             // ten_power + 100 probably never overflows
346             for(t = ten_power - 100; t != ten_power + 100; ++t)
347                 BOOST_CHECK(lexical_cast<T>(to_str<CharT>(t)) == t);
348         }
349     }
350 }
351
352 template<class T>
353 void test_conversion_from_to_integral_for_locale()
354 {
355     std::locale current_locale;
356     typedef std::numpunct<char> numpunct;
357     numpunct const& np = BOOST_USE_FACET(numpunct, current_locale);
358     if ( !np.grouping().empty() )
359     {
360         BOOST_CHECK_THROW(
361                 lexical_cast<T>( std::string("100") + np.thousands_sep() + np.thousands_sep() + "0" )
362                 , bad_lexical_cast);
363         BOOST_CHECK_THROW(lexical_cast<T>( std::string("100") + np.thousands_sep() ), bad_lexical_cast);
364         BOOST_CHECK_THROW(lexical_cast<T>( np.thousands_sep() + std::string("100") ), bad_lexical_cast);
365
366         // Exception must not be thrown, when we are using no separators at all
367         BOOST_CHECK( lexical_cast<T>("30000") == static_cast<T>(30000) );
368     }
369
370
371     test_conversion_from_integral_to_integral<T>();
372
373     // This is a part of test_conversion_from_integral_to_string<T>('0') method,
374     // but with BOOST_CHECK_EQUAL instead of BOOST_CHECK. It is required to see 
375     // what is produced by the to_str<char>(t) method in situations when result 
376     // is different. BOOST_CHECK does not work with wchar_t.
377     typedef std::numeric_limits<T> limits;
378     T t = (limits::min)();
379     BOOST_CHECK_EQUAL(lexical_cast<std::string>(t), to_str<char>(t));
380
381     test_conversion_from_integral_to_string<T>('0');
382     test_conversion_from_string_to_integral<T>('0');
383 #if !defined(BOOST_LCAST_NO_WCHAR_T)
384     if (lexical_cast<std::wstring>(t) != to_str<wchar_t>(t)) {
385         // Something went wrong, and now we are attempting to find and print the 
386         // difference.
387         std::wstring wstr = to_str<wchar_t>(t);
388         std::string lcast_str = lexical_cast<std::string>(t);
389         std::string str;
390         str.reserve(wstr.size());
391         for (std::size_t i = 0; i < wstr.size(); ++i) {
392             str.push_back(static_cast<char>(wstr[i]));
393         }
394         
395         BOOST_CHECK_EQUAL(lcast_str.length(), lexical_cast<std::wstring>(t).length());
396         BOOST_CHECK_EQUAL(to_str<char>(t), str);
397         BOOST_CHECK_EQUAL(lcast_str, str);
398     }
399
400     test_conversion_from_integral_to_string<T>(L'0');
401     test_conversion_from_string_to_integral<T>(L'0');
402 #endif
403 }
404
405 struct restore_oldloc
406 {
407     std::locale oldloc;
408     ~restore_oldloc() { std::locale::global(oldloc); }
409 };
410
411 template<class T>
412 void test_conversion_from_to_integral_minimal()
413 {
414     char const zero = '0';
415     signed char const szero = '0';
416     unsigned char const uzero = '0';
417     test_conversion_from_integral_to_char<T>(zero);
418     test_conversion_from_char_to_integral<T>(zero);
419     test_conversion_from_integral_to_char<T>(szero);
420     test_conversion_from_char_to_integral<T>(szero);
421     test_conversion_from_integral_to_char<T>(uzero);
422     test_conversion_from_char_to_integral<T>(uzero);
423 #if !defined(BOOST_LCAST_NO_WCHAR_T) && !defined(BOOST_NO_INTRINSIC_WCHAR_T)
424     wchar_t const wzero = L'0';
425     test_conversion_from_integral_to_char<T>(wzero);
426     test_conversion_from_char_to_integral<T>(wzero);
427 #endif
428 #if !defined(BOOST_NO_CXX11_CHAR16_T) && !defined(BOOST_NO_CXX11_UNICODE_LITERALS) && !defined(_LIBCPP_VERSION)
429     char16_t const u16zero = u'0';
430     test_conversion_from_integral_to_char<T>(u16zero);
431     test_conversion_from_char_to_integral<T>(u16zero);
432 #endif
433 #if !defined(BOOST_NO_CXX11_CHAR32_T) && !defined(BOOST_NO_CXX11_UNICODE_LITERALS) && !defined(_LIBCPP_VERSION)
434     char32_t const u32zero = u'0';
435     test_conversion_from_integral_to_char<T>(u32zero);
436     test_conversion_from_char_to_integral<T>(u32zero);
437 #endif
438
439     BOOST_CHECK(lexical_cast<T>("-1") == static_cast<T>(-1));
440     BOOST_CHECK(lexical_cast<T>("-9") == static_cast<T>(-9));
441     BOOST_CHECK(lexical_cast<T>(-1) == static_cast<T>(-1));
442     BOOST_CHECK(lexical_cast<T>(-9) == static_cast<T>(-9));
443
444     BOOST_CHECK_THROW(lexical_cast<T>("-1.0"), bad_lexical_cast);
445     BOOST_CHECK_THROW(lexical_cast<T>("-9.0"), bad_lexical_cast);
446     BOOST_CHECK(lexical_cast<T>(-1.0) == static_cast<T>(-1));
447     BOOST_CHECK(lexical_cast<T>(-9.0) == static_cast<T>(-9));
448
449     BOOST_CHECK(lexical_cast<T>(static_cast<T>(1)) == static_cast<T>(1));
450     BOOST_CHECK(lexical_cast<T>(static_cast<T>(9)) == static_cast<T>(9));
451     BOOST_CHECK_THROW(lexical_cast<T>(1.1f), bad_lexical_cast);
452     BOOST_CHECK_THROW(lexical_cast<T>(1.1), bad_lexical_cast);
453     BOOST_CHECK_THROW(lexical_cast<T>(1.1L), bad_lexical_cast);
454     BOOST_CHECK_THROW(lexical_cast<T>(1.0001f), bad_lexical_cast);
455     BOOST_CHECK_THROW(lexical_cast<T>(1.0001), bad_lexical_cast);
456     BOOST_CHECK_THROW(lexical_cast<T>(1.0001L), bad_lexical_cast);
457
458     BOOST_CHECK(lexical_cast<T>("+1") == static_cast<T>(1) );
459     BOOST_CHECK(lexical_cast<T>("+9") == static_cast<T>(9) );
460     BOOST_CHECK(lexical_cast<T>("+10") == static_cast<T>(10) );
461     BOOST_CHECK(lexical_cast<T>("+90") == static_cast<T>(90) );
462     BOOST_CHECK_THROW(lexical_cast<T>("++1"), bad_lexical_cast);
463     BOOST_CHECK_THROW(lexical_cast<T>("-+9"), bad_lexical_cast);
464     BOOST_CHECK_THROW(lexical_cast<T>("--1"), bad_lexical_cast);
465     BOOST_CHECK_THROW(lexical_cast<T>("+-9"), bad_lexical_cast);
466     // test_conversion_from_to_integral_for_locale
467
468     // Overflow test case from David W. Birdsall
469     std::string must_owerflow_str =             (sizeof(T) < 16 ?  "160000000000000000000" :  "1600000000000000000000000000000000000000");
470     std::string must_owerflow_negative_str =    (sizeof(T) < 16 ? "-160000000000000000000" : "-1600000000000000000000000000000000000000");
471     for (int i = 0; i < 15; ++i) {
472         BOOST_CHECK_THROW(lexical_cast<T>(must_owerflow_str), bad_lexical_cast);
473         BOOST_CHECK_THROW(lexical_cast<T>(must_owerflow_negative_str), bad_lexical_cast);
474
475         must_owerflow_str += '0';
476         must_owerflow_negative_str += '0';
477     }
478 }
479
480 template<class T>
481 void test_conversion_from_to_integral()
482 {
483     test_conversion_from_to_integral_minimal<T>();
484     typedef std::numpunct<char> numpunct;
485
486     restore_oldloc guard;
487     std::locale const& oldloc = guard.oldloc;
488
489     std::string grouping1 = BOOST_USE_FACET(numpunct, oldloc).grouping();
490     std::string grouping2(grouping1);
491
492     test_conversion_from_to_integral_for_locale<T>();
493
494     try
495     {
496         std::locale newloc("");
497         std::locale::global(newloc);
498
499         grouping2 = BOOST_USE_FACET(numpunct, newloc).grouping();
500     }
501     catch(std::exception const& ex)
502     {
503         std::string msg("Failed to set system locale: ");
504         msg += ex.what();
505         BOOST_TEST_MESSAGE(msg);
506     }
507
508     if(grouping1 != grouping2)
509         test_conversion_from_to_integral_for_locale<T>();
510
511     if(grouping1.empty() && grouping2.empty())
512         BOOST_TEST_MESSAGE("Formatting with thousands_sep has not been tested");
513 }
514
515 void test_conversion_from_to_short()
516 {
517     test_conversion_from_to_integral<short>();
518 }
519
520 void test_conversion_from_to_ushort()
521 {
522     test_conversion_from_to_integral<unsigned short>();
523 }
524
525 void test_conversion_from_to_int()
526 {
527     test_conversion_from_to_integral<int>();
528 }
529
530 void test_conversion_from_to_uint()
531 {
532     test_conversion_from_to_integral<unsigned int>();
533 }
534
535 void test_conversion_from_to_long()
536 {
537     test_conversion_from_to_integral<long>();
538 }
539
540 void test_conversion_from_to_ulong()
541 {
542     test_conversion_from_to_integral<unsigned long>();
543 }
544
545 void test_conversion_from_to_intmax_t()
546 {
547     test_conversion_from_to_integral<boost::intmax_t>();
548 }
549
550 void test_conversion_from_to_uintmax_t()
551 {
552     test_conversion_from_to_integral<boost::uintmax_t>();
553 }
554
555 #if defined(BOOST_HAS_LONG_LONG)
556
557 void test_conversion_from_to_longlong()
558 {
559     test_conversion_from_to_integral<boost::long_long_type>();
560 }
561
562 void test_conversion_from_to_ulonglong()
563 {
564     test_conversion_from_to_integral<boost::ulong_long_type>();
565 }
566
567 #elif defined(BOOST_HAS_MS_INT64)
568
569 void test_conversion_from_to_longlong()
570 {
571     test_conversion_from_to_integral<__int64>();
572 }
573
574 void test_conversion_from_to_ulonglong()
575 {
576     test_conversion_from_to_integral<unsigned __int64>();
577 }
578
579 #endif
580
581
582 #ifdef BOOST_HAS_INT128
583
584 template <bool Specialized, class T>
585 struct test_if_specialized {
586     static void test() {}
587 };
588
589 template <class T>
590 struct test_if_specialized<true, T> {
591     static void test() {
592         test_conversion_from_to_integral_minimal<T>();
593     }
594 };
595
596 void test_conversion_from_to_int128()
597 {
598     test_if_specialized<
599         std::numeric_limits<boost::int128_type>::is_specialized, 
600         boost::int128_type
601     >::test();
602 }
603
604 void test_conversion_from_to_uint128()
605 {
606     test_if_specialized<
607         std::numeric_limits<boost::int128_type>::is_specialized, 
608         boost::uint128_type
609     >::test();
610 }
611 #endif
612
613 template <typename SignedT>
614 void test_integral_conversions_on_min_max_impl()
615 {
616     typedef SignedT signed_t;
617     typedef BOOST_DEDUCED_TYPENAME boost::make_unsigned<signed_t>::type unsigned_t;
618     
619     typedef std::numeric_limits<signed_t> s_limits;
620     typedef std::numeric_limits<unsigned_t> uns_limits;
621
622     BOOST_CHECK_EQUAL(lexical_cast<unsigned_t>((uns_limits::max)()), (uns_limits::max)());
623     BOOST_CHECK_EQUAL(lexical_cast<unsigned_t>((uns_limits::min)()), (uns_limits::min)());
624
625     BOOST_CHECK_EQUAL(lexical_cast<signed_t>((s_limits::max)()), (s_limits::max)());
626     BOOST_CHECK_EQUAL(lexical_cast<signed_t>((uns_limits::min)()), static_cast<signed_t>((uns_limits::min)()));
627
628     BOOST_CHECK_EQUAL(lexical_cast<unsigned_t>((s_limits::max)()), static_cast<unsigned_t>((s_limits::max)()));
629     BOOST_CHECK_EQUAL(lexical_cast<unsigned_t>((s_limits::min)()), static_cast<unsigned_t>((s_limits::min)()));
630 }
631
632 void test_integral_conversions_on_min_max()
633 {
634     test_integral_conversions_on_min_max_impl<int>();
635     test_integral_conversions_on_min_max_impl<short>();
636
637 #ifdef _MSC_VER
638     test_integral_conversions_on_min_max_impl<long int>();
639
640 #if defined(BOOST_HAS_LONG_LONG)
641     test_integral_conversions_on_min_max_impl<boost::long_long_type>();
642 #elif defined(BOOST_HAS_MS_INT64)
643     test_integral_conversions_on_min_max_impl<__int64>();
644 #endif
645
646 #ifdef BOOST_HAS_INT128
647     test_integral_conversions_on_min_max_impl<boost::int128_type>();
648 #endif
649 #endif
650
651 }
652
653