1/*
2 * Copyright (C) 2012 Apple Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 *    notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 *    notice, this list of conditions and the following disclaimer in the
11 *    documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23 * THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26#include "config.h"
27
28#include "wtf/StringExtras.h"
29#include "wtf/text/CString.h"
30#include "wtf/text/WTFString.h"
31#include <gtest/gtest.h>
32#include <limits>
33
34namespace {
35
36template<typename IntegerType> struct PrintfFormatTrait { static const char format[]; };
37
38template<> struct PrintfFormatTrait<short> { static const char format[]; };
39const char PrintfFormatTrait<short>::format[] = "%hd";
40
41template<> struct PrintfFormatTrait<int> { static const char format[]; };
42const char PrintfFormatTrait<int>::format[] = "%d";
43
44template<> struct PrintfFormatTrait<long> { static const char format[]; };
45const char PrintfFormatTrait<long>::format[] = "%ld";
46
47template<> struct PrintfFormatTrait<long long> { static const char format[]; };
48#if OS(WIN)
49const char PrintfFormatTrait<long long>::format[] = "%I64i";
50#else
51const char PrintfFormatTrait<long long>::format[] = "%lli";
52#endif // OS(WIN)
53
54template<> struct PrintfFormatTrait<unsigned short> { static const char format[]; };
55const char PrintfFormatTrait<unsigned short>::format[] = "%hu";
56
57template<> struct PrintfFormatTrait<unsigned> { static const char format[]; };
58const char PrintfFormatTrait<unsigned>::format[] = "%u";
59
60template<> struct PrintfFormatTrait<unsigned long> { static const char format[]; };
61const char PrintfFormatTrait<unsigned long>::format[] = "%lu";
62
63template<> struct PrintfFormatTrait<unsigned long long> { static const char format[]; };
64#if OS(WIN)
65const char PrintfFormatTrait<unsigned long long>::format[] = "%I64u";
66#else
67const char PrintfFormatTrait<unsigned long long>::format[] = "%llu";
68#endif // OS(WIN)
69
70
71// FIXME: use snprintf from StringExtras.h
72template<typename IntegerType>
73void testBoundaries()
74{
75    const unsigned bufferSize = 256;
76    Vector<char, bufferSize> buffer;
77    buffer.resize(bufferSize);
78
79    const IntegerType min = std::numeric_limits<IntegerType>::min();
80    CString minStringData = String::number(min).latin1();
81    snprintf(buffer.data(), bufferSize, PrintfFormatTrait<IntegerType>::format, min);
82    EXPECT_STREQ(buffer.data(), minStringData.data());
83
84    const IntegerType max = std::numeric_limits<IntegerType>::max();
85    CString maxStringData = String::number(max).latin1();
86    snprintf(buffer.data(), bufferSize, PrintfFormatTrait<IntegerType>::format, max);
87    EXPECT_STREQ(buffer.data(), maxStringData.data());
88}
89
90template<typename IntegerType>
91void testNumbers()
92{
93    const unsigned bufferSize = 256;
94    Vector<char, bufferSize> buffer;
95    buffer.resize(bufferSize);
96
97    for (int i = -100; i < 100; ++i) {
98        const IntegerType number = static_cast<IntegerType>(i);
99        CString numberStringData = String::number(number).latin1();
100        snprintf(buffer.data(), bufferSize, PrintfFormatTrait<IntegerType>::format, number);
101        EXPECT_STREQ(buffer.data(), numberStringData.data());
102    }
103}
104
105TEST(StringExtraTest, IntegerToStringConversionSignedIntegerBoundaries)
106{
107    testBoundaries<short>();
108    testBoundaries<int>();
109    testBoundaries<long>();
110    testBoundaries<long long>();
111}
112
113TEST(StringExtraTest, IntegerToStringConversionSignedIntegerRegularNumbers)
114{
115    testNumbers<short>();
116    testNumbers<int>();
117    testNumbers<long>();
118    testNumbers<long long>();
119}
120
121TEST(StringExtraTest, IntegerToStringConversionUnsignedIntegerBoundaries)
122{
123    testBoundaries<unsigned short>();
124    testBoundaries<unsigned>();
125    testBoundaries<unsigned long>();
126    testBoundaries<unsigned long long>();
127}
128
129TEST(StringExtraTest, IntegerToStringConversionUnsignedIntegerRegularNumbers)
130{
131    testNumbers<unsigned short>();
132    testNumbers<unsigned>();
133    testNumbers<unsigned long>();
134    testNumbers<unsigned long long>();
135}
136
137} // namespace
138