1ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// Protocol Buffers - Google's data interchange format 2ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// Copyright 2012 Google Inc. All rights reserved. 3ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// http://code.google.com/p/protobuf/ 4ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// 5ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// Redistribution and use in source and binary forms, with or without 6ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// modification, are permitted provided that the following conditions are 7ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// met: 8ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// 9ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// * Redistributions of source code must retain the above copyright 10ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// notice, this list of conditions and the following disclaimer. 11ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// * Redistributions in binary form must reproduce the above 12ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// copyright notice, this list of conditions and the following disclaimer 13ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// in the documentation and/or other materials provided with the 14ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// distribution. 15ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// * Neither the name of Google Inc. nor the names of its 16ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// contributors may be used to endorse or promote products derived from 17ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// this software without specific prior written permission. 18ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// 19ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch 31ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// from google3/base/stringprintf_unittest.cc 32ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch 33ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch#include <google/protobuf/stubs/stringprintf.h> 34ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch 35ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch#include <cerrno> 36ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch#include <string> 37ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch 38ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch#include <google/protobuf/testing/googletest.h> 39ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch#include <gtest/gtest.h> 40ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch 41ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochnamespace google { 42ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochnamespace protobuf { 43ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochnamespace { 44ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch 45ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben MurdochTEST(StringPrintfTest, Empty) { 46ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch#if 0 47ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch // gcc 2.95.3, gcc 4.1.0, and gcc 4.2.2 all warn about this: 48ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch // warning: zero-length printf format string. 49ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch // so we do not allow them in google3. 50ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch EXPECT_EQ("", StringPrintf("")); 51ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch#endif 52ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch EXPECT_EQ("", StringPrintf("%s", string().c_str())); 53ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch EXPECT_EQ("", StringPrintf("%s", "")); 54ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch} 55ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch 56ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben MurdochTEST(StringPrintfTest, Misc) { 57ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// MSVC does not support $ format specifier. 58ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch#if !defined(_MSC_VER) 59ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch EXPECT_EQ("123hello w", StringPrintf("%3$d%2$s %1$c", 'w', "hello", 123)); 60ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch#endif // !_MSC_VER 61ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch} 62ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch 63ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben MurdochTEST(StringAppendFTest, Empty) { 64ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch string value("Hello"); 65ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch const char* empty = ""; 66ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch StringAppendF(&value, "%s", empty); 67ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch EXPECT_EQ("Hello", value); 68ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch} 69ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch 70ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben MurdochTEST(StringAppendFTest, EmptyString) { 71ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch string value("Hello"); 72ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch StringAppendF(&value, "%s", ""); 73ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch EXPECT_EQ("Hello", value); 74ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch} 75ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch 76ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben MurdochTEST(StringAppendFTest, String) { 77ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch string value("Hello"); 78ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch StringAppendF(&value, " %s", "World"); 79ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch EXPECT_EQ("Hello World", value); 80ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch} 81ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch 82ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben MurdochTEST(StringAppendFTest, Int) { 83ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch string value("Hello"); 84ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch StringAppendF(&value, " %d", 123); 85ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch EXPECT_EQ("Hello 123", value); 86ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch} 87ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch 88ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben MurdochTEST(StringPrintfTest, Multibyte) { 89ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch // If we are in multibyte mode and feed invalid multibyte sequence, 90ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch // StringPrintf should return an empty string instead of running 91ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch // out of memory while trying to determine destination buffer size. 92ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch // see b/4194543. 93ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch 94ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch char* old_locale = setlocale(LC_CTYPE, NULL); 95ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch // Push locale with multibyte mode 96ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch setlocale(LC_CTYPE, "en_US.utf8"); 97ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch 98ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch const char kInvalidCodePoint[] = "\375\067s"; 99ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch string value = StringPrintf("%.*s", 3, kInvalidCodePoint); 100ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch 101ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch // In some versions of glibc (e.g. eglibc-2.11.1, aka GRTEv2), snprintf 102ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch // returns error given an invalid codepoint. Other versions 103ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch // (e.g. eglibc-2.15, aka pre-GRTEv3) emit the codepoint verbatim. 104ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch // We test that the output is one of the above. 105ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch EXPECT_TRUE(value.empty() || value == kInvalidCodePoint); 106ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch 107ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch // Repeat with longer string, to make sure that the dynamically 108ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch // allocated path in StringAppendV is handled correctly. 109ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch int n = 2048; 110ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch char* buf = new char[n+1]; 111ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch memset(buf, ' ', n-3); 112ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch memcpy(buf + n - 3, kInvalidCodePoint, 4); 113ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch value = StringPrintf("%.*s", n, buf); 114ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch // See GRTEv2 vs. GRTEv3 comment above. 115ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch EXPECT_TRUE(value.empty() || value == buf); 116ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch delete[] buf; 117ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch 118ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch setlocale(LC_CTYPE, old_locale); 119ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch} 120ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch 121ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben MurdochTEST(StringPrintfTest, NoMultibyte) { 122ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch // No multibyte handling, but the string contains funny chars. 123ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch char* old_locale = setlocale(LC_CTYPE, NULL); 124ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch setlocale(LC_CTYPE, "POSIX"); 125ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch string value = StringPrintf("%.*s", 3, "\375\067s"); 126ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch setlocale(LC_CTYPE, old_locale); 127ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch EXPECT_EQ("\375\067s", value); 128ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch} 129ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch 130ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben MurdochTEST(StringPrintfTest, DontOverwriteErrno) { 131ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch // Check that errno isn't overwritten unless we're printing 132ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch // something significantly larger than what people are normally 133ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch // printing in their badly written PLOG() statements. 134ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch errno = ECHILD; 135ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch string value = StringPrintf("Hello, %s!", "World"); 136ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch EXPECT_EQ(ECHILD, errno); 137ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch} 138ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch 139ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben MurdochTEST(StringPrintfTest, LargeBuf) { 140ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch // Check that the large buffer is handled correctly. 141ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch int n = 2048; 142ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch char* buf = new char[n+1]; 143ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch memset(buf, ' ', n); 144ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch buf[n] = 0; 145ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch string value = StringPrintf("%s", buf); 146ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch EXPECT_EQ(buf, value); 147ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch delete[] buf; 148ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch} 149ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch 150ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch} // anonymous namespace 151ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch} // namespace protobuf 152ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch} // namespace google 153