1 // Copyright 2015 PDFium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include <limits>
6
7 #include "build/build_config.h"
8 #include "core/fxcrt/fx_string.h"
9 #include "core/fxcrt/fx_system.h"
10 #include "testing/gtest/include/gtest/gtest.h"
11
12 // Unit test covering cases where PDFium replaces well-known library
13 // functionality on any given platformn.
14
15 #if !defined(OS_WIN)
16
17 namespace {
18
19 const char kSentinel = 0x7f;
20
Check32BitBase16Itoa(int32_t input,const char * expected_output)21 void Check32BitBase16Itoa(int32_t input, const char* expected_output) {
22 const size_t kBufLen = 11; // "-" + 8 digits + NUL + sentinel.
23 char buf[kBufLen];
24 buf[kBufLen - 1] = kSentinel;
25 FXSYS_itoa(input, buf, 16);
26 EXPECT_STREQ(expected_output, buf);
27 EXPECT_EQ(kSentinel, buf[kBufLen - 1]);
28 }
29
Check32BitBase10Itoa(int32_t input,const char * expected_output)30 void Check32BitBase10Itoa(int32_t input, const char* expected_output) {
31 const size_t kBufLen = 13; // "-" + 10 digits + NUL + sentinel.
32 char buf[kBufLen];
33 buf[kBufLen - 1] = kSentinel;
34 FXSYS_itoa(input, buf, 10);
35 EXPECT_STREQ(expected_output, buf);
36 EXPECT_EQ(kSentinel, buf[kBufLen - 1]);
37 }
38
Check32BitBase2Itoa(int32_t input,const char * expected_output)39 void Check32BitBase2Itoa(int32_t input, const char* expected_output) {
40 const size_t kBufLen = 35; // "-" + 32 digits + NUL + sentinel.
41 char buf[kBufLen];
42 buf[kBufLen - 1] = kSentinel;
43 FXSYS_itoa(input, buf, 2);
44 EXPECT_STREQ(expected_output, buf);
45 EXPECT_EQ(kSentinel, buf[kBufLen - 1]);
46 }
47
Check64BitBase16Itoa(int64_t input,const char * expected_output)48 void Check64BitBase16Itoa(int64_t input, const char* expected_output) {
49 const size_t kBufLen = 19; // "-" + 16 digits + NUL + sentinel.
50 char buf[kBufLen];
51 buf[kBufLen - 1] = kSentinel;
52 FXSYS_i64toa(input, buf, 16);
53 EXPECT_STREQ(expected_output, buf);
54 EXPECT_EQ(kSentinel, buf[kBufLen - 1]);
55 }
56
Check64BitBase10Itoa(int64_t input,const char * expected_output)57 void Check64BitBase10Itoa(int64_t input, const char* expected_output) {
58 const size_t kBufLen = 22; // "-" + 19 digits + NUL + sentinel.
59 char buf[kBufLen];
60 buf[kBufLen - 1] = kSentinel;
61 FXSYS_i64toa(input, buf, 10);
62 EXPECT_STREQ(expected_output, buf);
63 EXPECT_EQ(kSentinel, buf[kBufLen - 1]);
64 }
65
Check64BitBase2Itoa(int64_t input,const char * expected_output)66 void Check64BitBase2Itoa(int64_t input, const char* expected_output) {
67 const size_t kBufLen = 67; // "-" + 64 digits + NUL + sentinel.
68 char buf[kBufLen];
69 buf[kBufLen - 1] = kSentinel;
70 FXSYS_i64toa(input, buf, 2);
71 EXPECT_STREQ(expected_output, buf);
72 EXPECT_EQ(kSentinel, buf[kBufLen - 1]);
73 }
74
75 } // namespace
76
TEST(fxcrt,FXSYS_roundf)77 TEST(fxcrt, FXSYS_roundf) {
78 EXPECT_EQ(0, FXSYS_roundf(0.0f));
79 EXPECT_EQ(0, FXSYS_roundf(-0.0f));
80 EXPECT_EQ(0, FXSYS_roundf(0.00001f));
81 EXPECT_EQ(0, FXSYS_roundf(-0.00001f));
82 EXPECT_EQ(3, FXSYS_roundf(3.14159f));
83 EXPECT_EQ(4, FXSYS_roundf(3.5f));
84
85 // Check for smallest non-zero float values.
86 EXPECT_EQ(0, FXSYS_roundf(std::numeric_limits<float>::min()));
87 EXPECT_EQ(0, FXSYS_roundf(-std::numeric_limits<float>::min()));
88
89 // Function is a wrapper around standard C library function round(), so
90 // returns the integral value that is nearest to x, with halfway cases
91 // rounded away from zero.
92 EXPECT_EQ(-3, FXSYS_roundf(-3.14159f));
93 EXPECT_EQ(-4, FXSYS_roundf(-3.5f));
94
95 // Positive rounding stops at maximum int.
96 // MAX_INT=0x7FFFFFFF=2147483647=2.147483647e+9
97 // In IEEE-754 format, 2^31 yields exponent of 0x9E with mantissa of all
98 // zeroes which is 0x4f000000=2.14748365e+9, which is beyond max integer.
99 // Going to next smallest float by minus one from exponent and mantissa of
100 // all ones yields binary float representation of 0x4EFFFFFF=2.14748352e+9,
101 // which is 2147483520.
102 EXPECT_EQ(2147483520, FXSYS_roundf(2.14748352e+9f));
103
104 // Using a slightly larger value, expect to see it be capped at MAX_INT.
105 EXPECT_EQ(2147483647, FXSYS_roundf(2.14748365e+9f));
106
107 EXPECT_EQ(2147483647, FXSYS_roundf(2.14748365e+10f));
108 EXPECT_EQ(2147483647, FXSYS_roundf(std::numeric_limits<float>::max()));
109
110 // Negative rounding stops at minimum int.
111 // MIN_INT=0x80000000=-2147483648,=-2.147483648e+9
112 // In IEEE-754 format, 2^31 yields exponent of 0x9E with mantissa of all
113 // zeroes which is 0x4f000000=2.14748365e+9, and the sign bit set, which
114 // is 0xCF000000 and exactly matches the minimum integer. Going to next
115 // smallest negative float by minus one from exponent and mantissa of all
116 // ones yields binary float representation of 0xCEFFFFFF=-2.14748352e+9,
117 // which is -2147483520.
118 EXPECT_EQ(-2147483648, FXSYS_roundf(-2.147483648e+10f));
119 EXPECT_EQ(-2147483648, FXSYS_roundf(-2.147483648e+9f));
120 EXPECT_EQ(-2147483520, FXSYS_roundf(-2.14748352e+9f));
121 EXPECT_EQ(-2147483648, FXSYS_roundf(-std::numeric_limits<float>::max()));
122
123 // NaN should give zero.
124 EXPECT_EQ(0, FXSYS_roundf(NAN));
125 }
126
TEST(fxcrt,FXSYS_round)127 TEST(fxcrt, FXSYS_round) {
128 EXPECT_EQ(0, FXSYS_round(0.0));
129 EXPECT_EQ(0, FXSYS_round(-0.0));
130 EXPECT_EQ(0, FXSYS_round(0.00001));
131 EXPECT_EQ(0, FXSYS_round(-0.00001));
132 EXPECT_EQ(3, FXSYS_round(3.14159));
133 EXPECT_EQ(4, FXSYS_round(3.5));
134
135 // Check for smallest non-zero double values.
136 EXPECT_EQ(0, FXSYS_round(std::numeric_limits<double>::min()));
137 EXPECT_EQ(0, FXSYS_round(-std::numeric_limits<double>::min()));
138
139 // Function is a wrapper around standard C library function round(), so
140 // returns the integral value that is nearest to x, with halfway cases
141 // rounded away from zero.
142 EXPECT_EQ(-3, FXSYS_round(-3.14159));
143 EXPECT_EQ(-4, FXSYS_round(-3.5));
144
145 // Positive rounding stops at maximum int.
146 // MAX_INT=0x7FFFFFFF=2147483647=2.147483647e+9
147 // In IEEE-754 double precision format, 2^31 yields exponent of 0x41E with
148 // mantissa of all zeroes which is 0x41E0000000000000=2.14748365e+9, which
149 // is beyond max integer.
150 // Going to next smallest float by minus one from exponent and mantissa of
151 // all ones yields binary float representation of
152 // 41DFFFFFFFC00000=2.147483647e+9, which matches the max integer.
153 EXPECT_EQ(2147483647, FXSYS_round(2.147483647e+9));
154
155 // Using a slightly larger value, expect to see it be capped at MAX_INT.
156 EXPECT_EQ(2147483647, FXSYS_round(2.14748365e+9));
157
158 EXPECT_EQ(2147483647, FXSYS_round(2.14748365e+10));
159 EXPECT_EQ(2147483647, FXSYS_round(std::numeric_limits<double>::max()));
160
161 // Negative rounding stops at minimum int.
162 // MIN_INT=0x80000000=-2147483648,=-2.147483648e+9
163 // In IEEE-754 double precision format, 2^31 yields exponent of 0x41E with
164 // mantissa of all zeroes which is 0x41E0000000000000=2.14748365e+9, and the
165 // sign bit set, which is 0xC1E0000000000000 and exactly matches the minimum
166 // integer. Going to next smallest negative double by minus one from
167 // exponent and mantissa of all ones yields binary float representation of
168 // 0xC1DFFFFFFFFFFFFF=-2.1474836479999998e+9, which is -2147483648.
169 EXPECT_EQ(-2147483648, FXSYS_round(-2.1474836479999998e+9));
170 EXPECT_EQ(-2147483648, FXSYS_round(-2.147483648e+9));
171 EXPECT_EQ(-2147483648, FXSYS_round(-2.147483648e+10));
172 EXPECT_EQ(-2147483648, FXSYS_round(-std::numeric_limits<double>::max()));
173
174 // NaN should give zero.
175 EXPECT_EQ(0, FXSYS_round(NAN));
176 }
177
TEST(fxcrt,FXSYS_itoa_InvalidRadix)178 TEST(fxcrt, FXSYS_itoa_InvalidRadix) {
179 char buf[32];
180
181 FXSYS_itoa(42, buf, 17); // Ours stops at 16.
182 EXPECT_STREQ("", buf);
183
184 FXSYS_itoa(42, buf, 1);
185 EXPECT_STREQ("", buf);
186
187 FXSYS_itoa(42, buf, 0);
188 EXPECT_STREQ("", buf);
189
190 FXSYS_itoa(42, buf, -1);
191 EXPECT_STREQ("", buf);
192 }
193
TEST(fxcrt,FXSYS_itoa)194 TEST(fxcrt, FXSYS_itoa) {
195 Check32BitBase16Itoa(std::numeric_limits<int32_t>::min(), "-80000000");
196 Check32BitBase10Itoa(std::numeric_limits<int32_t>::min(), "-2147483648");
197 Check32BitBase2Itoa(std::numeric_limits<int32_t>::min(),
198 "-10000000000000000000000000000000");
199
200 Check32BitBase16Itoa(-1, "-1");
201 Check32BitBase10Itoa(-1, "-1");
202 Check32BitBase2Itoa(-1, "-1");
203
204 Check32BitBase16Itoa(0, "0");
205 Check32BitBase10Itoa(0, "0");
206 Check32BitBase2Itoa(0, "0");
207
208 Check32BitBase16Itoa(42, "2a");
209 Check32BitBase10Itoa(42, "42");
210 Check32BitBase2Itoa(42, "101010");
211
212 Check32BitBase16Itoa(std::numeric_limits<int32_t>::max(), "7fffffff");
213 Check32BitBase10Itoa(std::numeric_limits<int32_t>::max(), "2147483647");
214 Check32BitBase2Itoa(std::numeric_limits<int32_t>::max(),
215 "1111111111111111111111111111111");
216 }
217
TEST(fxcrt,FXSYS_i64toa_InvalidRadix)218 TEST(fxcrt, FXSYS_i64toa_InvalidRadix) {
219 char buf[32];
220
221 FXSYS_i64toa(42, buf, 17); // Ours stops at 16.
222 EXPECT_STREQ("", buf);
223
224 FXSYS_i64toa(42, buf, 1);
225 EXPECT_STREQ("", buf);
226
227 FXSYS_i64toa(42, buf, 0);
228 EXPECT_STREQ("", buf);
229
230 FXSYS_i64toa(42, buf, -1);
231 EXPECT_STREQ("", buf);
232 }
233
TEST(fxcrt,FXSYS_i64toa)234 TEST(fxcrt, FXSYS_i64toa) {
235 Check64BitBase16Itoa(std::numeric_limits<int64_t>::min(),
236 "-8000000000000000");
237 Check64BitBase10Itoa(std::numeric_limits<int64_t>::min(),
238 "-9223372036854775808");
239 Check64BitBase2Itoa(
240 std::numeric_limits<int64_t>::min(),
241 "-1000000000000000000000000000000000000000000000000000000000000000");
242
243 Check64BitBase16Itoa(-1, "-1");
244 Check64BitBase10Itoa(-1, "-1");
245 Check64BitBase2Itoa(-1, "-1");
246
247 Check64BitBase16Itoa(0, "0");
248 Check64BitBase10Itoa(0, "0");
249 Check64BitBase2Itoa(0, "0");
250
251 Check64BitBase16Itoa(42, "2a");
252 Check64BitBase10Itoa(42, "42");
253 Check64BitBase2Itoa(42, "101010");
254
255 Check64BitBase16Itoa(std::numeric_limits<int64_t>::max(), "7fffffffffffffff");
256 Check64BitBase10Itoa(std::numeric_limits<int64_t>::max(),
257 "9223372036854775807");
258 Check64BitBase2Itoa(
259 std::numeric_limits<int64_t>::max(),
260 "111111111111111111111111111111111111111111111111111111111111111");
261 }
262
263 #endif // !defined(OS_WIN)
264
TEST(fxcrt,FXSYS_wcsftime)265 TEST(fxcrt, FXSYS_wcsftime) {
266 struct tm good_time = {};
267 good_time.tm_year = 74; // 1900-based.
268 good_time.tm_mon = 7; // 0-based.
269 good_time.tm_mday = 9; // 1-based.
270 good_time.tm_hour = 11;
271 good_time.tm_min = 59;
272 good_time.tm_sec = 59;
273
274 wchar_t buf[100] = {};
275 EXPECT_EQ(19u, FXSYS_wcsftime(buf, FX_ArraySize(buf), L"%Y-%m-%dT%H:%M:%S",
276 &good_time));
277 EXPECT_STREQ(L"1974-08-09T11:59:59", buf);
278
279 // Ensure wcsftime handles a wide range of years without crashing.
280 struct tm year_time = {};
281 year_time.tm_mon = 7; // 0-based.
282 year_time.tm_mday = 9; // 1-based.
283 year_time.tm_hour = 11;
284 year_time.tm_min = 59;
285 year_time.tm_sec = 59;
286
287 for (int year = -2500; year <= 8500; ++year) {
288 year_time.tm_year = year;
289 wchar_t year_buf[100] = {};
290 FXSYS_wcsftime(year_buf, FX_ArraySize(year_buf), L"%Y-%m-%dT%H:%M:%S",
291 &year_time);
292 }
293
294 // Ensure wcsftime handles bad years, etc. without crashing.
295 struct tm bad_time = {};
296 bad_time.tm_year = -1;
297 bad_time.tm_mon = -1;
298 bad_time.tm_mday = -1;
299 bad_time.tm_hour = -1;
300 bad_time.tm_min = -1;
301 bad_time.tm_sec = -1;
302
303 FXSYS_wcsftime(buf, FX_ArraySize(buf), L"%y-%m-%dT%H:%M:%S", &bad_time);
304
305 // Ensure wcsftime handles bad-ish day without crashing (Feb 30).
306 struct tm feb_time = {};
307 feb_time.tm_year = 115; // 1900-based.
308 feb_time.tm_mon = 1; // 0-based.
309 feb_time.tm_mday = 30; // 1-based.
310 feb_time.tm_hour = 12;
311 feb_time.tm_min = 00;
312 feb_time.tm_sec = 00;
313
314 FXSYS_wcsftime(buf, FX_ArraySize(buf), L"%y-%m-%dT%H:%M:%S", &feb_time);
315 }
316
TEST(fxcrt,FXSYS_atoi)317 TEST(fxcrt, FXSYS_atoi) {
318 EXPECT_EQ(0, FXSYS_atoi(""));
319 EXPECT_EQ(0, FXSYS_atoi("0"));
320 EXPECT_EQ(-1, FXSYS_atoi("-1"));
321 EXPECT_EQ(2345, FXSYS_atoi("2345"));
322 EXPECT_EQ(-2147483647, FXSYS_atoi("-2147483647"));
323 // Handle the sign.
324 EXPECT_EQ(-2345, FXSYS_atoi("-2345"));
325 EXPECT_EQ(2345, FXSYS_atoi("+2345"));
326 // The max value.
327 EXPECT_EQ(2147483647, FXSYS_atoi("2147483647"));
328 // The min value. Written in -1 format to avoid "unary minus operator applied
329 // to unsigned type" warning.
330 EXPECT_EQ(-2147483647 - 1, FXSYS_atoi("-2147483648"));
331 // With invalid char.
332 EXPECT_EQ(9, FXSYS_atoi("9x9"));
333
334 // Out of range values.
335 EXPECT_EQ(2147483647, FXSYS_atoi("2147483623423412348"));
336 EXPECT_EQ(2147483647, FXSYS_atoi("2147483648"));
337 EXPECT_EQ(-2147483647 - 1, FXSYS_atoi("-2147483650"));
338 }
339
TEST(fxcrt,FXSYS_atoi64)340 TEST(fxcrt, FXSYS_atoi64) {
341 EXPECT_EQ(0, FXSYS_atoi64(""));
342 EXPECT_EQ(0, FXSYS_atoi64("0"));
343 EXPECT_EQ(-1, FXSYS_atoi64("-1"));
344 EXPECT_EQ(2345, FXSYS_atoi64("2345"));
345 EXPECT_EQ(-9223372036854775807LL, FXSYS_atoi64("-9223372036854775807"));
346 // Handle the sign.
347 EXPECT_EQ(-2345, FXSYS_atoi64("-2345"));
348 EXPECT_EQ(2345, FXSYS_atoi64("+2345"));
349 // The max value.
350 EXPECT_EQ(9223372036854775807LL, FXSYS_atoi64("9223372036854775807"));
351 // The min value. Written in -1 format to avoid implicit unsigned warning.
352 EXPECT_EQ(-9223372036854775807LL - 1LL, FXSYS_atoi64("-9223372036854775808"));
353 // With invalid char.
354 EXPECT_EQ(9, FXSYS_atoi64("9x9"));
355
356 // Out of range values.
357 EXPECT_EQ(9223372036854775807LL, FXSYS_atoi64("922337203685471234123475807"));
358 EXPECT_EQ(9223372036854775807LL, FXSYS_atoi64("9223372036854775808"));
359 EXPECT_EQ(-9223372036854775807LL - 1LL, FXSYS_atoi64("-9223372036854775810"));
360 }
361
TEST(fxcrt,FXSYS_wtoi)362 TEST(fxcrt, FXSYS_wtoi) {
363 EXPECT_EQ(0, FXSYS_wtoi(L""));
364 EXPECT_EQ(0, FXSYS_wtoi(L"0"));
365 EXPECT_EQ(-1, FXSYS_wtoi(L"-1"));
366 EXPECT_EQ(2345, FXSYS_wtoi(L"2345"));
367 EXPECT_EQ(-2147483647, FXSYS_wtoi(L"-2147483647"));
368 // The max value.
369 EXPECT_EQ(2147483647, FXSYS_wtoi(L"2147483647"));
370 // The min value.
371 EXPECT_EQ(-2147483647 - 1, FXSYS_wtoi(L"-2147483648"));
372
373 // Out of range values.
374 EXPECT_EQ(2147483647, FXSYS_wtoi(L"2147483623423412348"));
375 EXPECT_EQ(2147483647, FXSYS_wtoi(L"2147483648"));
376 EXPECT_EQ(-2147483647 - 1, FXSYS_wtoi(L"-2147483652"));
377 }
378
TEST(fxcrt,FXSYS_atoui)379 TEST(fxcrt, FXSYS_atoui) {
380 EXPECT_EQ(0u, FXSYS_atoui(""));
381 EXPECT_EQ(0u, FXSYS_atoui("0"));
382 EXPECT_EQ(4294967295, FXSYS_atoui("-1"));
383 EXPECT_EQ(2345u, FXSYS_atoui("2345"));
384 // Handle the sign.
385 EXPECT_EQ(4294964951, FXSYS_atoui("-2345"));
386 EXPECT_EQ(2345u, FXSYS_atoui("+2345"));
387 // The max value.
388 EXPECT_EQ(4294967295, FXSYS_atoui("4294967295"));
389 EXPECT_EQ(9u, FXSYS_atoui("9x9"));
390
391 // Out of range values.
392 EXPECT_EQ(4294967295, FXSYS_atoui("2147483623423412348"));
393 EXPECT_EQ(4294967295, FXSYS_atoui("4294967296"));
394 EXPECT_EQ(4294967295, FXSYS_atoui("-4294967345"));
395 }
396