aboutsummaryrefslogtreecommitdiffhomepage
path: root/tensorflow/core/lib/strings/stringprintf_test.cc
diff options
context:
space:
mode:
Diffstat (limited to 'tensorflow/core/lib/strings/stringprintf_test.cc')
-rw-r--r--tensorflow/core/lib/strings/stringprintf_test.cc113
1 files changed, 113 insertions, 0 deletions
diff --git a/tensorflow/core/lib/strings/stringprintf_test.cc b/tensorflow/core/lib/strings/stringprintf_test.cc
new file mode 100644
index 0000000000..737ed5c0e0
--- /dev/null
+++ b/tensorflow/core/lib/strings/stringprintf_test.cc
@@ -0,0 +1,113 @@
+#include "tensorflow/core/lib/strings/stringprintf.h"
+
+#include <string>
+
+#include <gtest/gtest.h>
+
+namespace tensorflow {
+namespace strings {
+namespace {
+
+TEST(PrintfTest, Empty) {
+ EXPECT_EQ("", Printf("%s", string().c_str()));
+ EXPECT_EQ("", Printf("%s", ""));
+}
+
+TEST(PrintfTest, Misc) {
+// MSVC does not support $ format specifier.
+#if !defined(COMPILER_MSVC)
+ EXPECT_EQ("123hello w", Printf("%3$d%2$s %1$c", 'w', "hello", 123));
+#endif // !COMPILER_MSVC
+}
+
+TEST(AppendfTest, Empty) {
+ string value("Hello");
+ const char* empty = "";
+ Appendf(&value, "%s", empty);
+ EXPECT_EQ("Hello", value);
+}
+
+TEST(AppendfTest, EmptyString) {
+ string value("Hello");
+ Appendf(&value, "%s", "");
+ EXPECT_EQ("Hello", value);
+}
+
+TEST(AppendfTest, String) {
+ string value("Hello");
+ Appendf(&value, " %s", "World");
+ EXPECT_EQ("Hello World", value);
+}
+
+TEST(AppendfTest, Int) {
+ string value("Hello");
+ Appendf(&value, " %d", 123);
+ EXPECT_EQ("Hello 123", value);
+}
+
+TEST(PrintfTest, Multibyte) {
+ // If we are in multibyte mode and feed invalid multibyte sequence,
+ // Printf should return an empty string instead of running
+ // out of memory while trying to determine destination buffer size.
+ // see b/4194543.
+
+ char* old_locale = setlocale(LC_CTYPE, NULL);
+ // Push locale with multibyte mode
+ setlocale(LC_CTYPE, "en_US.utf8");
+
+ const char kInvalidCodePoint[] = "\375\067s";
+ string value = Printf("%.*s", 3, kInvalidCodePoint);
+
+ // In some versions of glibc (e.g. eglibc-2.11.1, aka GRTEv2), snprintf
+ // returns error given an invalid codepoint. Other versions
+ // (e.g. eglibc-2.15, aka pre-GRTEv3) emit the codepoint verbatim.
+ // We test that the output is one of the above.
+ EXPECT_TRUE(value.empty() || value == kInvalidCodePoint);
+
+ // Repeat with longer string, to make sure that the dynamically
+ // allocated path in StringAppendV is handled correctly.
+ int n = 2048;
+ char* buf = new char[n + 1];
+ memset(buf, ' ', n - 3);
+ memcpy(buf + n - 3, kInvalidCodePoint, 4);
+ value = Printf("%.*s", n, buf);
+ // See GRTEv2 vs. GRTEv3 comment above.
+ EXPECT_TRUE(value.empty() || value == buf);
+ delete[] buf;
+
+ setlocale(LC_CTYPE, old_locale);
+}
+
+TEST(PrintfTest, NoMultibyte) {
+ // No multibyte handling, but the string contains funny chars.
+ char* old_locale = setlocale(LC_CTYPE, NULL);
+ setlocale(LC_CTYPE, "POSIX");
+ string value = Printf("%.*s", 3, "\375\067s");
+ setlocale(LC_CTYPE, old_locale);
+ EXPECT_EQ("\375\067s", value);
+}
+
+TEST(PrintfTest, DontOverwriteErrno) {
+ // Check that errno isn't overwritten unless we're printing
+ // something significantly larger than what people are normally
+ // printing in their badly written PLOG() statements.
+ errno = ECHILD;
+ string value = Printf("Hello, %s!", "World");
+ EXPECT_EQ(ECHILD, errno);
+}
+
+TEST(PrintfTest, LargeBuf) {
+ // Check that the large buffer is handled correctly.
+ int n = 2048;
+ char* buf = new char[n + 1];
+ memset(buf, ' ', n);
+ buf[n] = 0;
+ string value = Printf("%s", buf);
+ EXPECT_EQ(buf, value);
+ delete[] buf;
+}
+
+} // namespace
+
+} // namespace strings
+} // namespace tensorflow