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