• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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