1// Copyright (c) 2010 The Chromium 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 "base/basictypes.h"
6#include "base/stringprintf.h"
7#include "testing/gtest/include/gtest/gtest.h"
8
9namespace base {
10
11namespace {
12
13// A helper for the StringAppendV test that follows.
14//
15// Just forwards its args to StringAppendV.
16static void StringAppendVTestHelper(std::string* out, const char* format, ...) {
17  va_list ap;
18  va_start(ap, format);
19  StringAppendV(out, format, ap);
20  va_end(ap);
21}
22
23}  // namespace
24
25TEST(StringPrintfTest, StringPrintfEmpty) {
26  EXPECT_EQ("", StringPrintf("%s", ""));
27}
28
29TEST(StringPrintfTest, StringPrintfMisc) {
30  EXPECT_EQ("123hello w", StringPrintf("%3d%2s %1c", 123, "hello", 'w'));
31  EXPECT_EQ(L"123hello w", StringPrintf(L"%3d%2ls %1lc", 123, L"hello", 'w'));
32}
33
34TEST(StringPrintfTest, StringAppendfEmptyString) {
35  std::string value("Hello");
36  StringAppendF(&value, "%s", "");
37  EXPECT_EQ("Hello", value);
38
39  std::wstring valuew(L"Hello");
40  StringAppendF(&valuew, L"%ls", L"");
41  EXPECT_EQ(L"Hello", valuew);
42}
43
44TEST(StringPrintfTest, StringAppendfString) {
45  std::string value("Hello");
46  StringAppendF(&value, " %s", "World");
47  EXPECT_EQ("Hello World", value);
48
49  std::wstring valuew(L"Hello");
50  StringAppendF(&valuew, L" %ls", L"World");
51  EXPECT_EQ(L"Hello World", valuew);
52}
53
54TEST(StringPrintfTest, StringAppendfInt) {
55  std::string value("Hello");
56  StringAppendF(&value, " %d", 123);
57  EXPECT_EQ("Hello 123", value);
58
59  std::wstring valuew(L"Hello");
60  StringAppendF(&valuew, L" %d", 123);
61  EXPECT_EQ(L"Hello 123", valuew);
62}
63
64// Make sure that lengths exactly around the initial buffer size are handled
65// correctly.
66TEST(StringPrintfTest, StringPrintfBounds) {
67  const int kSrcLen = 1026;
68  char src[kSrcLen];
69  for (size_t i = 0; i < arraysize(src); i++)
70    src[i] = 'A';
71
72  wchar_t srcw[kSrcLen];
73  for (size_t i = 0; i < arraysize(srcw); i++)
74    srcw[i] = 'A';
75
76  for (int i = 1; i < 3; i++) {
77    src[kSrcLen - i] = 0;
78    std::string out;
79    SStringPrintf(&out, "%s", src);
80    EXPECT_STREQ(src, out.c_str());
81
82    srcw[kSrcLen - i] = 0;
83    std::wstring outw;
84    SStringPrintf(&outw, L"%ls", srcw);
85    EXPECT_STREQ(srcw, outw.c_str());
86  }
87}
88
89// Test very large sprintfs that will cause the buffer to grow.
90TEST(StringPrintfTest, Grow) {
91  char src[1026];
92  for (size_t i = 0; i < arraysize(src); i++)
93    src[i] = 'A';
94  src[1025] = 0;
95
96  const char* fmt = "%sB%sB%sB%sB%sB%sB%s";
97
98  std::string out;
99  SStringPrintf(&out, fmt, src, src, src, src, src, src, src);
100
101  const int kRefSize = 320000;
102  char* ref = new char[kRefSize];
103#if defined(OS_WIN)
104  sprintf_s(ref, kRefSize, fmt, src, src, src, src, src, src, src);
105#elif defined(OS_POSIX)
106  snprintf(ref, kRefSize, fmt, src, src, src, src, src, src, src);
107#endif
108
109  EXPECT_STREQ(ref, out.c_str());
110  delete[] ref;
111}
112
113TEST(StringPrintfTest, StringAppendV) {
114  std::string out;
115  StringAppendVTestHelper(&out, "%d foo %s", 1, "bar");
116  EXPECT_EQ("1 foo bar", out);
117}
118
119// Test the boundary condition for the size of the string_util's
120// internal buffer.
121TEST(StringPrintfTest, GrowBoundary) {
122  const int string_util_buf_len = 1024;
123  // Our buffer should be one larger than the size of StringAppendVT's stack
124  // buffer.
125  const int buf_len = string_util_buf_len + 1;
126  char src[buf_len + 1];  // Need extra one for NULL-terminator.
127  for (int i = 0; i < buf_len; ++i)
128    src[i] = 'a';
129  src[buf_len] = 0;
130
131  std::string out;
132  SStringPrintf(&out, "%s", src);
133
134  EXPECT_STREQ(src, out.c_str());
135}
136
137// TODO(evanm): what's the proper cross-platform test here?
138#if defined(OS_WIN)
139// sprintf in Visual Studio fails when given U+FFFF. This tests that the
140// failure case is gracefuly handled.
141TEST(StringPrintfTest, Invalid) {
142  wchar_t invalid[2];
143  invalid[0] = 0xffff;
144  invalid[1] = 0;
145
146  std::wstring out;
147  SStringPrintf(&out, L"%ls", invalid);
148  EXPECT_STREQ(L"", out.c_str());
149}
150#endif
151
152}  // namespace base
153