]> git.tdb.fi Git - libs/core.git/blob - tests/lexicalcast.cpp
Make certain functions pure virtual so I won't forget to implement them
[libs/core.git] / tests / lexicalcast.cpp
1 #include <limits>
2 #include <msp/core/inttypes.h>
3 #include <msp/strings/utils.h>
4 #include <msp/test/test.h>
5
6 using namespace std;
7 using namespace Msp;
8
9 class LexicalCastTests: public Test::RegisteredTest<LexicalCastTests>
10 {
11 private:
12         template<typename T>
13         struct Value
14         {
15                 T value;
16                 const char *format;
17                 const char *result;
18         };
19
20 public:
21         LexicalCastTests();
22
23         static const char *get_name() { return "lexical_cast"; }
24
25 private:
26         void basic_integers();
27         void hex_integers();
28         void oct_integers();
29         void bin_integers();
30         void integer_limits();
31         void float_fixed();
32         void float_auto();
33         void float_sci();
34         void float_corner_cases();
35
36         template<typename T>
37         void test_values(const Value<T> *);
38 };
39
40 LexicalCastTests::LexicalCastTests()
41 {
42         add(&LexicalCastTests::basic_integers, "Basic integers");
43         add(&LexicalCastTests::hex_integers, "Hexadecimal integers");
44         add(&LexicalCastTests::oct_integers, "Octal integers");
45         add(&LexicalCastTests::bin_integers, "Binary integers");
46         add(&LexicalCastTests::integer_limits, "Integer limits");
47         add(&LexicalCastTests::float_fixed, "Fixed-precision floats");
48         add(&LexicalCastTests::float_auto, "Automatic floats");
49         add(&LexicalCastTests::float_sci, "Scientific floats");
50         add(&LexicalCastTests::float_corner_cases, "Float corner cases");
51 }
52
53 void LexicalCastTests::basic_integers()
54 {
55         Value<int> values[] =
56         {
57                 { 0, "%d", "0" },
58                 { 1, "%4d", "   1" },
59                 { 1, "%04d", "0001" },
60                 { 1, "%-04d", "1   " },
61                 { 1, "%+4d", "  +1" },
62                 { 1, "%+04d", "+001" },
63                 { 1, "%+-4d", "+1  " },
64                 { -1, "%d", "-1" },
65                 { -1, "%04d", "-001" },
66                 { 999999999, "%d", "999999999" },
67                 { 1000000000, "%d", "1000000000" },
68                 { 1234567890, "%d", "1234567890" },
69                 { 0, 0, 0 }
70         };
71         test_values<int>(values);
72 }
73
74 void LexicalCastTests::hex_integers()
75 {
76         Value<int> values[] =
77         {
78                 { 0xabcd, "%x", "abcd" },
79                 { 0xabcd, "%#x", "0xabcd" },
80                 { 0xabcd, "%#8x", "  0xabcd" },
81                 { 0xabcd, "%-#8x", "0xabcd  " },
82                 { 0xabcd, "%#08x", "0x00abcd" },
83                 { 0xabcd, "%#X", "0XABCD" },
84                 { 0xabcd, "%+#x", "+0xabcd" },
85                 { -0xabcd, "%#x", "-0xabcd" },
86                 { 0, 0, 0 }
87         };
88         test_values<int>(values);
89 }
90
91 void LexicalCastTests::oct_integers()
92 {
93         Value<int> values[] =
94         {
95                 { 012345, "%o", "12345" },
96                 { 012345, "%#o", "012345" },
97                 { 012345, "%#8o", "  012345" },
98                 { 012345, "%-#8o", "012345  " },
99                 { 012345, "%#08o", "00012345" },
100                 { 012345, "%+#o", "+012345" },
101                 { -012345, "%#o", "-012345" },
102                 { 0, 0, 0 }
103         };
104         test_values<int>(values);
105 }
106
107 void LexicalCastTests::bin_integers()
108 {
109         Value<int> values[] =
110         {
111                 { 0xcf3, "%b", "110011110011" },
112                 { 0xcf3, "%#b", "0b110011110011" },
113                 { 0xcf3, "%#16b", "  0b110011110011" },
114                 { 0xcf3, "%-#16b", "0b110011110011  " },
115                 { 0xcf3, "%#016b", "0b00110011110011" },
116                 { 0xcf3, "%+#b", "+0b110011110011" },
117                 { -0xcf3, "%#b", "-0b110011110011" },
118                 { 0, 0, 0 }
119         };
120         test_values<int>(values);
121 }
122
123 void LexicalCastTests::integer_limits()
124 {
125         Value<Int32> int32_values[] =
126         {
127                 { numeric_limits<Int32>::max(), "%d", "2147483647" },
128                 { numeric_limits<Int32>::max(), "%x", "7fffffff" },
129                 { numeric_limits<Int32>::min(), "%d", "-2147483648" },
130                 { numeric_limits<Int32>::min(), "%x", "-80000000" },
131                 { 0, 0, 0 }
132         };
133         test_values<Int32>(int32_values);
134
135         Value<UInt32> uint32_values[] =
136         {
137                 { numeric_limits<UInt32>::max(), "%d", "4294967295" },
138                 { numeric_limits<UInt32>::max(), "%x", "ffffffff" },
139                 { 0, 0, 0 }
140         };
141         test_values<UInt32>(uint32_values);
142 }
143
144 void LexicalCastTests::float_fixed()
145 {
146         Value<float> float_values[] =
147         {
148                 { 0, "%f", "0.000000" },
149                 { 1, "%.0f", "1" },
150                 { 1, "%#.0f", "1." },
151                 { 1, "%06.2f", "001.00" },
152                 { 1, "%.1f", "1.0" },
153                 { 0.0987, "%f", "0.098700" },
154                 { 0.0987, "%.3f", "0.099" },
155                 { 0.0987, "%.2f", "0.10" },
156                 { 0, 0, 0 }
157         };
158         test_values<float>(float_values);
159 }
160
161 void LexicalCastTests::float_auto()
162 {
163         Value<float> float_values[] =
164         {
165                 { 0, "%g", "0" },
166                 { 1, "%#g", "1.00000" },
167                 { 100, "%.3g", "100" },
168                 { 1000, "%.3g", "1e+03" },
169                 { 1100, "%.3g", "1.1e+03" },
170                 { 1e-5, "%g", "1e-05" },
171                 { 0.0987, "%g", "0.0987" },
172                 { 0.0987, "%.3g", "0.0987" },
173                 { 0.0987, "%.2g", "0.099" },
174                 { 0, 0, 0 }
175         };
176         test_values<float>(float_values);
177 }
178
179 void LexicalCastTests::float_sci()
180 {
181         Value<float> float_values[] =
182         {
183                 { 0, "%e", "0.000000e+00" },
184                 { 0.0987, "%e", "9.870000e-02" },
185                 { 0.0987, "%.3e", "9.870e-02" },
186                 { 0.0987, "%.1e", "9.9e-02" },
187                 { 0, 0, 0 }
188         };
189         test_values<float>(float_values);
190 }
191
192 void LexicalCastTests::float_corner_cases()
193 {
194         Value<float> float_values[] =
195         {
196                 { 10, "%.20f", "10.00000000000000000000" },
197                 { 10, "%.20g", "10" },
198                 { 99.99, "%#.3g", "100." },
199                 { 999.9, "%.3g", "1e+03" },
200                 { 0.09999999, "%.3g", "0.1" },
201                 { 0.09999999, "%.3f", "0.100" },
202                 { 0, 0, 0 }
203         };
204         test_values<float>(float_values);
205 }
206
207 template<typename T>
208 void LexicalCastTests::test_values(const Value<T> *values)
209 {
210         for(const Value<T> *i=values; i->format; ++i)
211         {
212                 string result = lexical_cast<string>(i->value, i->format);
213                 expect_equal(result, result==i->result, format("result == \"%s\"", c_escape(i->result)));
214         }
215 }