13d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch// Protocol Buffers - Google's data interchange format 23d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch// Copyright 2012 Google Inc. All rights reserved. 33d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch// http://code.google.com/p/protobuf/ 43d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch// 53d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch// Redistribution and use in source and binary forms, with or without 63d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch// modification, are permitted provided that the following conditions are 73d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch// met: 83d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch// 93d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch// * Redistributions of source code must retain the above copyright 103d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch// notice, this list of conditions and the following disclaimer. 113d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch// * Redistributions in binary form must reproduce the above 123d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch// copyright notice, this list of conditions and the following disclaimer 133d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch// in the documentation and/or other materials provided with the 143d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch// distribution. 153d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch// * Neither the name of Google Inc. nor the names of its 163d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch// contributors may be used to endorse or promote products derived from 173d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch// this software without specific prior written permission. 183d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch// 193d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 203d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 213d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 223d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 233d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 243d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 253d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 263d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 273d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 283d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 293d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 303d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch 313d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch// from google3/base/stringprintf_unittest.cc 323d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch 333d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch#include <google/protobuf/stubs/stringprintf.h> 343d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch 353d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch#include <cerrno> 363d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch#include <string> 373d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch 383d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch#include <google/protobuf/testing/googletest.h> 393d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch#include <gtest/gtest.h> 403d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch 413d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdochnamespace google { 423d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdochnamespace protobuf { 433d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdochnamespace { 443d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch 453d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben MurdochTEST(StringPrintfTest, Empty) { 463d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch#if 0 473d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch // gcc 2.95.3, gcc 4.1.0, and gcc 4.2.2 all warn about this: 483d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch // warning: zero-length printf format string. 493d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch // so we do not allow them in google3. 503d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch EXPECT_EQ("", StringPrintf("")); 513d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch#endif 523d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch EXPECT_EQ("", StringPrintf("%s", string().c_str())); 533d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch EXPECT_EQ("", StringPrintf("%s", "")); 543d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch} 553d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch 563d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben MurdochTEST(StringPrintfTest, Misc) { 573d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch// MSVC does not support $ format specifier. 583d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch#if !defined(_MSC_VER) 593d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch EXPECT_EQ("123hello w", StringPrintf("%3$d%2$s %1$c", 'w', "hello", 123)); 603d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch#endif // !_MSC_VER 613d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch} 623d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch 633d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben MurdochTEST(StringAppendFTest, Empty) { 643d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch string value("Hello"); 653d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch const char* empty = ""; 663d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch StringAppendF(&value, "%s", empty); 673d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch EXPECT_EQ("Hello", value); 683d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch} 693d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch 703d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben MurdochTEST(StringAppendFTest, EmptyString) { 713d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch string value("Hello"); 723d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch StringAppendF(&value, "%s", ""); 733d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch EXPECT_EQ("Hello", value); 743d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch} 753d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch 763d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben MurdochTEST(StringAppendFTest, String) { 773d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch string value("Hello"); 783d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch StringAppendF(&value, " %s", "World"); 793d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch EXPECT_EQ("Hello World", value); 803d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch} 813d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch 823d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben MurdochTEST(StringAppendFTest, Int) { 833d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch string value("Hello"); 843d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch StringAppendF(&value, " %d", 123); 853d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch EXPECT_EQ("Hello 123", value); 863d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch} 873d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch 883d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben MurdochTEST(StringPrintfTest, Multibyte) { 893d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch // If we are in multibyte mode and feed invalid multibyte sequence, 903d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch // StringPrintf should return an empty string instead of running 913d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch // out of memory while trying to determine destination buffer size. 923d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch // see b/4194543. 933d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch 943d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch char* old_locale = setlocale(LC_CTYPE, NULL); 953d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch // Push locale with multibyte mode 963d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch setlocale(LC_CTYPE, "en_US.utf8"); 973d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch 983d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch const char kInvalidCodePoint[] = "\375\067s"; 993d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch string value = StringPrintf("%.*s", 3, kInvalidCodePoint); 1003d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch 1013d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch // In some versions of glibc (e.g. eglibc-2.11.1, aka GRTEv2), snprintf 1023d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch // returns error given an invalid codepoint. Other versions 1033d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch // (e.g. eglibc-2.15, aka pre-GRTEv3) emit the codepoint verbatim. 1043d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch // We test that the output is one of the above. 1053d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch EXPECT_TRUE(value.empty() || value == kInvalidCodePoint); 1063d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch 1073d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch // Repeat with longer string, to make sure that the dynamically 1083d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch // allocated path in StringAppendV is handled correctly. 1093d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch int n = 2048; 1103d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch char* buf = new char[n+1]; 1113d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch memset(buf, ' ', n-3); 1123d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch memcpy(buf + n - 3, kInvalidCodePoint, 4); 1133d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch value = StringPrintf("%.*s", n, buf); 1143d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch // See GRTEv2 vs. GRTEv3 comment above. 1153d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch EXPECT_TRUE(value.empty() || value == buf); 1163d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch delete[] buf; 1173d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch 1183d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch setlocale(LC_CTYPE, old_locale); 1193d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch} 1203d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch 1213d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben MurdochTEST(StringPrintfTest, NoMultibyte) { 1223d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch // No multibyte handling, but the string contains funny chars. 1233d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch char* old_locale = setlocale(LC_CTYPE, NULL); 1243d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch setlocale(LC_CTYPE, "POSIX"); 1253d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch string value = StringPrintf("%.*s", 3, "\375\067s"); 1263d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch setlocale(LC_CTYPE, old_locale); 1273d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch EXPECT_EQ("\375\067s", value); 1283d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch} 1293d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch 1303d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben MurdochTEST(StringPrintfTest, DontOverwriteErrno) { 1313d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch // Check that errno isn't overwritten unless we're printing 1323d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch // something significantly larger than what people are normally 1333d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch // printing in their badly written PLOG() statements. 1343d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch errno = ECHILD; 1353d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch string value = StringPrintf("Hello, %s!", "World"); 1363d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch EXPECT_EQ(ECHILD, errno); 1373d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch} 1383d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch 1393d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben MurdochTEST(StringPrintfTest, LargeBuf) { 1403d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch // Check that the large buffer is handled correctly. 1413d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch int n = 2048; 1423d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch char* buf = new char[n+1]; 1433d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch memset(buf, ' ', n); 1443d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch buf[n] = 0; 1453d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch string value = StringPrintf("%s", buf); 1463d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch EXPECT_EQ(buf, value); 1473d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch delete[] buf; 1483d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch} 1493d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch 1503d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch} // anonymous namespace 1513d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch} // namespace protobuf 1523d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch} // namespace google 153