blob: 23b8544ff83c97e4b5b7742f03791c24e12eeaa1 [file] [log] [blame]
// Copyright 2016 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "lib/fxl/strings/string_printf.h"
#include <errno.h>
#include <stdarg.h>
#include <string>
#include "gtest/gtest.h"
namespace fxl {
namespace {
// Note: |runnable| can't be a reference since that'd make the behavior of
// |va_start()| undefined.
template <typename Runnable>
std::string VAListHelper(Runnable runnable, ...) {
va_list ap;
va_start(ap, runnable);
std::string rv = runnable(ap);
va_end(ap);
return rv;
}
TEST(StringPrintfTest, StringPrintf_Basic) {
EXPECT_EQ("", StringPrintf(""));
EXPECT_EQ("hello", StringPrintf("hello"));
EXPECT_EQ("hello-123", StringPrintf("hello%d", -123));
EXPECT_EQ("hello0123FACE", StringPrintf("%s%04d%X", "hello", 123, 0xfaceU));
}
TEST(StringPrintfTest, StringVPrintf_Basic) {
EXPECT_EQ("", VAListHelper([](va_list ap) -> std::string {
return StringVPrintf("", ap);
}));
EXPECT_EQ("hello", VAListHelper([](va_list ap) -> std::string {
return StringVPrintf("hello", ap);
}));
EXPECT_EQ("hello-123", VAListHelper(
[](va_list ap) -> std::string {
return StringVPrintf("hello%d", ap);
},
-123));
EXPECT_EQ("hello0123FACE", VAListHelper(
[](va_list ap) -> std::string {
return StringVPrintf("%s%04d%X", ap);
},
"hello", 123, 0xfaceU));
}
TEST(StringPrintfTest, StringAppendf_Basic) {
{
std::string s = "existing";
StringAppendf(&s, "");
EXPECT_EQ("existing", s);
}
{
std::string s = "existing";
StringAppendf(&s, "hello");
EXPECT_EQ("existinghello", s);
}
{
std::string s = "existing";
StringAppendf(&s, "hello%d", -123);
EXPECT_EQ("existinghello-123", s);
}
{
std::string s = "existing";
StringAppendf(&s, "%s%04d%X", "hello", 123, 0xfaceU);
EXPECT_EQ("existinghello0123FACE", s);
}
}
TEST(StringPrintfTest, StringVAppendf_Basic) {
EXPECT_EQ("existing", VAListHelper([](va_list ap) -> std::string {
std::string s = "existing";
StringVAppendf(&s, "", ap);
return s;
}));
EXPECT_EQ("existinghello", VAListHelper([](va_list ap) -> std::string {
std::string s = "existing";
StringVAppendf(&s, "hello", ap);
return s;
}));
EXPECT_EQ("existinghello-123", VAListHelper(
[](va_list ap) -> std::string {
std::string s = "existing";
StringVAppendf(&s, "hello%d", ap);
return s;
},
-123));
EXPECT_EQ("existinghello0123FACE", VAListHelper(
[](va_list ap) -> std::string {
std::string s = "existing";
StringVAppendf(&s, "%s%04d%X", ap);
return s;
},
"hello", 123, 0xfaceU));
}
// Generally, we assume that everything forwards to |StringVAppendf()|, so
// testing |StringPrintf()| more carefully suffices.
TEST(StringPrintfTest, StringPrintf_Boundary) {
// Note: The size of strings generated should cover the boundary cases in the
// constant |kStackBufferSize| in |StringVAppendf()|.
for (size_t i = 800; i < 1200; i++) {
std::string stuff(i, 'x');
std::string format = stuff + "%d" + "%s" + " world";
EXPECT_EQ(stuff + "123" + "hello world",
StringPrintf(format.c_str(), 123, "hello"))
<< i;
}
}
TEST(StringPrintfTest, StringPrintf_VeryBig) {
// 4 megabytes of exes (we'll generate 5 times this).
std::string stuff(4u << 20u, 'x');
std::string format = "%s" + stuff + "%s" + stuff + "%s";
EXPECT_EQ(stuff + stuff + stuff + stuff + stuff,
StringPrintf(format.c_str(), stuff.c_str(), stuff.c_str(),
stuff.c_str()));
}
} // namespace
} // namespace fxl