The Battle for Wesnoth 1.21.0-dev
 
Loading...
Searching...
No Matches
test_lexical_cast.cpp
Go to the documentation of this file.
1/*
2 Copyright (C) 2009 - 2025
3 by Mark de Wever <koraq@xs4all.nl>
4 Part of the Battle for Wesnoth Project https://www.wesnoth.org/
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY.
12
13 See the COPYING file for more details.
14*/
15
16#define GETTEXT_DOMAIN "wesnoth-test"
17
18#include "lexical_cast.hpp"
19#include "log.hpp"
20
21#include <boost/test/unit_test.hpp>
22
23#include <tuple>
24
25namespace test_throw {
26
27#ifdef _MSC_VER
28#pragma warning(push)
29#pragma warning(disable:4702)
30#endif
31
32#define LEXICAL_CAST_DEBUG
33#include "lexical_cast.hpp"
34
35#ifdef _MSC_VER
36#pragma warning(pop)
37#endif
38
39using test_bool_types = std::tuple<
40 /* note Wesnoth's coding style doesn't allow w_char so ignore them. */
41 bool>;
42
43using test_integral_types = std::tuple<
44 /*
45 * We don't want chars to match since a string cast of a char is
46 * ambiguous; does the user want it interpreted as a char or as a number?
47 * But as long as that hasn't been fixed, leave the char.
48 */
49 char, signed char, unsigned char,
50 short, int, long, long long,
51 unsigned short, unsigned int, unsigned long, unsigned long long
52 >;
53
54using test_floating_point_types = std::tuple<float, double, long double>;
55
56using test_match_types = decltype(std::tuple_cat(test_bool_types{}, test_integral_types{}));
57using test_nomatch_types = decltype(std::tuple_cat(test_floating_point_types{}));
58using test_types = decltype(std::tuple_cat(test_nomatch_types{}, test_match_types{}));
59
61
62namespace {
63
64 std::string result;
65
66bool validate(const char* str)
67{
68 if(str != result) {
69 PLAIN_LOG << "Received " << str << '\n'
70 << "Expected " << result << '\n';
71 return false;
72 } else {
73 return true;
74 }
75}
76
77template<typename Test, typename... Types>
78constexpr bool contains_type(std::tuple<Types...>)
79{
80 return (std::is_same_v<Test, Types> || ...);
81}
82
83} // namespace
84
85#define TEST_CASE(type_send) \
86 { \
87 type_send val = value; \
88 \
89 BOOST_CHECK_EXCEPTION( \
90 lexical_cast<std::string>(val), const char*, validate); \
91 }
92
93BOOST_AUTO_TEST_CASE_TEMPLATE(test_lexical_cast_throw, T, test_types)
94{
95 T value = T();
96
97 result = "specialized - To std::string - From arithmetic";
98
99
100 TEST_CASE(T);
101 TEST_CASE(const T);
102
103 TEST_CASE(T&);
104 TEST_CASE(const T&);
105}
106
107#undef TEST_CASE
108
110 test_lexical_arithmetic_signed, T, test_arithmetic_types)
111{
112 result = "specialized - To arithmetic - From string";
113
114 const char* value = "test";
115 BOOST_CHECK_EXCEPTION(lexical_cast<T>(
116 value), const char*, validate);
117 BOOST_CHECK_EXCEPTION(lexical_cast<T>(
118 const_cast<char*>(value)), const char*, validate);
119 BOOST_CHECK_EXCEPTION(lexical_cast<T>(
120 std::string(value)), const char*, validate);
121 BOOST_CHECK_EXCEPTION(lexical_cast<T>(
122 std::string_view(value)), const char*, validate);
123}
124
125BOOST_AUTO_TEST_CASE(test_lexical_cast_bool)
126{
127 result = "specialized - To bool - From string";
128
129 const char* value = "test";
130 BOOST_CHECK_EXCEPTION(lexical_cast<bool>(
131 value), const char*, validate);
132 BOOST_CHECK_EXCEPTION(lexical_cast<bool>(
133 const_cast<char*>(value)), const char*, validate);
134 BOOST_CHECK_EXCEPTION(lexical_cast<bool>(
135 std::string(value)), const char*, validate);
136 BOOST_CHECK_EXCEPTION(lexical_cast<bool>(
137 std::string_view(value)), const char*, validate);
138}
139
140} // namespace test_throw
141
142
143BOOST_AUTO_TEST_CASE(test_lexical_cast_result)
144{
145 BOOST_CHECK_EQUAL(lexical_cast<std::string>(true), "1");
146 BOOST_CHECK_EQUAL(lexical_cast<std::string>(false), "0");
147
148 BOOST_CHECK_EQUAL(lexical_cast<std::string>(1), "1");
149 BOOST_CHECK_EQUAL(lexical_cast<std::string>(1u), "1");
150
151 BOOST_CHECK_EQUAL(lexical_cast<std::string>(1.2f), "1.2");
152 BOOST_CHECK_EQUAL(lexical_cast<std::string>(1.2), "1.2");
153
154 BOOST_CHECK_EQUAL(lexical_cast<int>("1"), 1);
155 BOOST_CHECK_EQUAL(lexical_cast<int>("-1"), -1);
156 BOOST_CHECK_EQUAL(lexical_cast<unsigned>("1"), 1);
157 BOOST_CHECK_EQUAL(lexical_cast<double>("1.2"), 1.2);
158
159 // The unit [effect] code uses this a lot
160 BOOST_CHECK_EQUAL(lexical_cast_default<int>("80%"), 80);
161
162 BOOST_CHECK_EQUAL(lexical_cast<double>("0x11"), 0);
163
164 std::string a = "01234567890123456789";
165 BOOST_CHECK_EQUAL(lexical_cast<long long>(a), 1234567890123456789ll);
166 BOOST_CHECK_THROW(lexical_cast<int>(a), bad_lexical_cast);
167 BOOST_CHECK_EQUAL(lexical_cast<double>(a), 1.23456789012345678e18);
168 BOOST_CHECK_EQUAL(lexical_cast_default<long long>(a, 0ll), 1234567890123456789ll);
169 BOOST_CHECK_EQUAL(lexical_cast_default<int>(a, 0), 0);
170 BOOST_CHECK_EQUAL(lexical_cast_default<double>(a, 0.0), 1.23456789012345678e18);
171
172 std::string b = "99999999999999999999";
173 BOOST_CHECK_THROW(lexical_cast<long long>(b), bad_lexical_cast);
174 BOOST_CHECK_THROW(lexical_cast<int>(b), bad_lexical_cast);
175 BOOST_CHECK_EQUAL(lexical_cast<double>(b), 1e20);
176 BOOST_CHECK_EQUAL(lexical_cast_default<long long>(b, 0ll), 0ll);
177 BOOST_CHECK_EQUAL(lexical_cast_default<int>(b, 0), 0);
178 BOOST_CHECK_EQUAL(lexical_cast_default<double>(b, 0.0), 1e20);
179}
static void validate(boost::any &v, const std::vector< std::string > &values, two_strings *, int)
New lexcical_cast header.
Standard logging facilities (interface).
#define PLAIN_LOG
Definition log.hpp:296
std::tuple< char, signed char, unsigned char, short, int, long, long long, unsigned short, unsigned int, unsigned long, unsigned long long > test_integral_types
BOOST_AUTO_TEST_CASE(test_lexical_cast_bool)
decltype(std::tuple_cat(test_integral_types{}, test_floating_point_types{})) test_arithmetic_types
decltype(std::tuple_cat(test_bool_types{}, test_integral_types{})) test_match_types
std::tuple< float, double, long double > test_floating_point_types
decltype(std::tuple_cat(test_floating_point_types{})) test_nomatch_types
decltype(std::tuple_cat(test_nomatch_types{}, test_match_types{})) test_types
std::tuple< bool > test_bool_types
BOOST_AUTO_TEST_CASE_TEMPLATE(test_lexical_cast_throw, T, test_types)
std::unique_ptr< MIX_Audio, decltype(&MIX_DestroyAudio)> value
Definition sound.cpp:139
Thrown when a lexical_cast fails.
#define TEST_CASE(type_send)
BOOST_AUTO_TEST_CASE(test_lexical_cast_result)
#define b