1868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/stringprintf.h" 6868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 7c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include <errno.h> 8c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/basictypes.h" 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h" 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace base { 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// A helper for the StringAppendV test that follows. 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Just forwards its args to StringAppendV. 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void StringAppendVTestHelper(std::string* out, const char* format, ...) { 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) va_list ap; 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) va_start(ap, format); 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) StringAppendV(out, format, ap); 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) va_end(ap); 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(StringPrintfTest, StringPrintfEmpty) { 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ("", StringPrintf("%s", "")); 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(StringPrintfTest, StringPrintfMisc) { 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ("123hello w", StringPrintf("%3d%2s %1c", 123, "hello", 'w')); 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if !defined(OS_ANDROID) 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(L"123hello w", StringPrintf(L"%3d%2ls %1lc", 123, L"hello", 'w')); 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(StringPrintfTest, StringAppendfEmptyString) { 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string value("Hello"); 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) StringAppendF(&value, "%s", ""); 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ("Hello", value); 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if !defined(OS_ANDROID) 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::wstring valuew(L"Hello"); 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) StringAppendF(&valuew, L"%ls", L""); 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(L"Hello", valuew); 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(StringPrintfTest, StringAppendfString) { 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string value("Hello"); 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) StringAppendF(&value, " %s", "World"); 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ("Hello World", value); 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if !defined(OS_ANDROID) 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::wstring valuew(L"Hello"); 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) StringAppendF(&valuew, L" %ls", L"World"); 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(L"Hello World", valuew); 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(StringPrintfTest, StringAppendfInt) { 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string value("Hello"); 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) StringAppendF(&value, " %d", 123); 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ("Hello 123", value); 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if !defined(OS_ANDROID) 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::wstring valuew(L"Hello"); 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) StringAppendF(&valuew, L" %d", 123); 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(L"Hello 123", valuew); 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Make sure that lengths exactly around the initial buffer size are handled 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// correctly. 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(StringPrintfTest, StringPrintfBounds) { 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const int kSrcLen = 1026; 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char src[kSrcLen]; 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < arraysize(src); i++) 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) src[i] = 'A'; 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) wchar_t srcw[kSrcLen]; 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < arraysize(srcw); i++) 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) srcw[i] = 'A'; 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (int i = 1; i < 3; i++) { 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) src[kSrcLen - i] = 0; 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string out; 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SStringPrintf(&out, "%s", src); 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_STREQ(src, out.c_str()); 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if !defined(OS_ANDROID) 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) srcw[kSrcLen - i] = 0; 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::wstring outw; 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SStringPrintf(&outw, L"%ls", srcw); 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_STREQ(srcw, outw.c_str()); 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Test very large sprintfs that will cause the buffer to grow. 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(StringPrintfTest, Grow) { 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char src[1026]; 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < arraysize(src); i++) 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) src[i] = 'A'; 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) src[1025] = 0; 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char* fmt = "%sB%sB%sB%sB%sB%sB%s"; 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string out; 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SStringPrintf(&out, fmt, src, src, src, src, src, src, src); 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const int kRefSize = 320000; 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char* ref = new char[kRefSize]; 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN) 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sprintf_s(ref, kRefSize, fmt, src, src, src, src, src, src, src); 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#elif defined(OS_POSIX) 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) snprintf(ref, kRefSize, fmt, src, src, src, src, src, src, src); 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_STREQ(ref, out.c_str()); 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delete[] ref; 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(StringPrintfTest, StringAppendV) { 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string out; 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) StringAppendVTestHelper(&out, "%d foo %s", 1, "bar"); 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ("1 foo bar", out); 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Test the boundary condition for the size of the string_util's 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// internal buffer. 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(StringPrintfTest, GrowBoundary) { 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const int string_util_buf_len = 1024; 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Our buffer should be one larger than the size of StringAppendVT's stack 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // buffer. 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const int buf_len = string_util_buf_len + 1; 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char src[buf_len + 1]; // Need extra one for NULL-terminator. 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (int i = 0; i < buf_len; ++i) 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) src[i] = 'a'; 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) src[buf_len] = 0; 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string out; 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SStringPrintf(&out, "%s", src); 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_STREQ(src, out.c_str()); 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TODO(evanm): what's the proper cross-platform test here? 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN) 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// sprintf in Visual Studio fails when given U+FFFF. This tests that the 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// failure case is gracefuly handled. 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(StringPrintfTest, Invalid) { 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) wchar_t invalid[2]; 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) invalid[0] = 0xffff; 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) invalid[1] = 0; 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::wstring out; 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SStringPrintf(&out, L"%ls", invalid); 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_STREQ(L"", out.c_str()); 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Test that the positional parameters work. 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(StringPrintfTest, PositionalParameters) { 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string out; 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SStringPrintf(&out, "%1$s %1$s", "test"); 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_STREQ("test test", out.c_str()); 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN) 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::wstring wout; 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SStringPrintf(&wout, L"%1$ls %1$ls", L"test"); 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_STREQ(L"test test", wout.c_str()); 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 178c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Test that StringPrintf and StringAppendV do not change errno. 179c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)TEST(StringPrintfTest, StringPrintfErrno) { 180c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) errno = 1; 181c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) EXPECT_EQ("", StringPrintf("%s", "")); 182c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) EXPECT_EQ(1, errno); 183c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) std::string out; 184c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) StringAppendVTestHelper(&out, "%d foo %s", 1, "bar"); 185c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) EXPECT_EQ(1, errno); 186c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 187c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace base 189