11cb0ef41Sopenharmony_ci#include "debug_utils-inl.h"
21cb0ef41Sopenharmony_ci#include "env-inl.h"
31cb0ef41Sopenharmony_ci#include "gtest/gtest.h"
41cb0ef41Sopenharmony_ci#include "simdutf.h"
51cb0ef41Sopenharmony_ci#include "util-inl.h"
61cb0ef41Sopenharmony_ci
71cb0ef41Sopenharmony_ciusing node::Calloc;
81cb0ef41Sopenharmony_ciusing node::Malloc;
91cb0ef41Sopenharmony_ciusing node::MaybeStackBuffer;
101cb0ef41Sopenharmony_ciusing node::SPrintF;
111cb0ef41Sopenharmony_ciusing node::StringEqualNoCase;
121cb0ef41Sopenharmony_ciusing node::StringEqualNoCaseN;
131cb0ef41Sopenharmony_ciusing node::ToLower;
141cb0ef41Sopenharmony_ciusing node::UncheckedCalloc;
151cb0ef41Sopenharmony_ciusing node::UncheckedMalloc;
161cb0ef41Sopenharmony_ci
171cb0ef41Sopenharmony_ciTEST(UtilTest, ListHead) {
181cb0ef41Sopenharmony_ci  struct Item { node::ListNode<Item> node_; };
191cb0ef41Sopenharmony_ci  typedef node::ListHead<Item, &Item::node_> List;
201cb0ef41Sopenharmony_ci
211cb0ef41Sopenharmony_ci  List list;
221cb0ef41Sopenharmony_ci  EXPECT_TRUE(list.IsEmpty());
231cb0ef41Sopenharmony_ci
241cb0ef41Sopenharmony_ci  Item one;
251cb0ef41Sopenharmony_ci  EXPECT_TRUE(one.node_.IsEmpty());
261cb0ef41Sopenharmony_ci
271cb0ef41Sopenharmony_ci  list.PushBack(&one);
281cb0ef41Sopenharmony_ci  EXPECT_FALSE(list.IsEmpty());
291cb0ef41Sopenharmony_ci  EXPECT_FALSE(one.node_.IsEmpty());
301cb0ef41Sopenharmony_ci
311cb0ef41Sopenharmony_ci  {
321cb0ef41Sopenharmony_ci    List::Iterator it = list.begin();
331cb0ef41Sopenharmony_ci    EXPECT_NE(list.end(), it);
341cb0ef41Sopenharmony_ci    EXPECT_EQ(&one, *it);
351cb0ef41Sopenharmony_ci    ++it;
361cb0ef41Sopenharmony_ci    EXPECT_FALSE(it != list.end());  // Iterator only implements != operator.
371cb0ef41Sopenharmony_ci  }
381cb0ef41Sopenharmony_ci
391cb0ef41Sopenharmony_ci  Item two;
401cb0ef41Sopenharmony_ci  list.PushBack(&two);
411cb0ef41Sopenharmony_ci
421cb0ef41Sopenharmony_ci  {
431cb0ef41Sopenharmony_ci    List::Iterator it = list.begin();
441cb0ef41Sopenharmony_ci    EXPECT_NE(list.end(), it);
451cb0ef41Sopenharmony_ci    EXPECT_EQ(&one, *it);
461cb0ef41Sopenharmony_ci    ++it;
471cb0ef41Sopenharmony_ci    EXPECT_NE(list.end(), it);
481cb0ef41Sopenharmony_ci    EXPECT_EQ(&two, *it);
491cb0ef41Sopenharmony_ci    ++it;
501cb0ef41Sopenharmony_ci    EXPECT_FALSE(it != list.end());  // Iterator only implements != operator.
511cb0ef41Sopenharmony_ci  }
521cb0ef41Sopenharmony_ci
531cb0ef41Sopenharmony_ci  EXPECT_EQ(&one, list.PopFront());
541cb0ef41Sopenharmony_ci  EXPECT_TRUE(one.node_.IsEmpty());
551cb0ef41Sopenharmony_ci  EXPECT_FALSE(list.IsEmpty());
561cb0ef41Sopenharmony_ci
571cb0ef41Sopenharmony_ci  {
581cb0ef41Sopenharmony_ci    List::Iterator it = list.begin();
591cb0ef41Sopenharmony_ci    EXPECT_NE(list.end(), it);
601cb0ef41Sopenharmony_ci    EXPECT_EQ(&two, *it);
611cb0ef41Sopenharmony_ci    ++it;
621cb0ef41Sopenharmony_ci    EXPECT_FALSE(it != list.end());  // Iterator only implements != operator.
631cb0ef41Sopenharmony_ci  }
641cb0ef41Sopenharmony_ci
651cb0ef41Sopenharmony_ci  EXPECT_EQ(&two, list.PopFront());
661cb0ef41Sopenharmony_ci  EXPECT_TRUE(two.node_.IsEmpty());
671cb0ef41Sopenharmony_ci  EXPECT_TRUE(list.IsEmpty());
681cb0ef41Sopenharmony_ci  EXPECT_FALSE(list.begin() != list.end());
691cb0ef41Sopenharmony_ci}
701cb0ef41Sopenharmony_ci
711cb0ef41Sopenharmony_ciTEST(UtilTest, StringEqualNoCase) {
721cb0ef41Sopenharmony_ci  EXPECT_FALSE(StringEqualNoCase("a", "b"));
731cb0ef41Sopenharmony_ci  EXPECT_TRUE(StringEqualNoCase("", ""));
741cb0ef41Sopenharmony_ci  EXPECT_TRUE(StringEqualNoCase("equal", "equal"));
751cb0ef41Sopenharmony_ci  EXPECT_TRUE(StringEqualNoCase("equal", "EQUAL"));
761cb0ef41Sopenharmony_ci  EXPECT_TRUE(StringEqualNoCase("EQUAL", "EQUAL"));
771cb0ef41Sopenharmony_ci  EXPECT_FALSE(StringEqualNoCase("equal", "equals"));
781cb0ef41Sopenharmony_ci  EXPECT_FALSE(StringEqualNoCase("equals", "equal"));
791cb0ef41Sopenharmony_ci}
801cb0ef41Sopenharmony_ci
811cb0ef41Sopenharmony_ciTEST(UtilTest, StringEqualNoCaseN) {
821cb0ef41Sopenharmony_ci  EXPECT_FALSE(StringEqualNoCaseN("a", "b", strlen("a")));
831cb0ef41Sopenharmony_ci  EXPECT_TRUE(StringEqualNoCaseN("", "", strlen("")));
841cb0ef41Sopenharmony_ci  EXPECT_TRUE(StringEqualNoCaseN("equal", "equal", strlen("equal")));
851cb0ef41Sopenharmony_ci  EXPECT_TRUE(StringEqualNoCaseN("equal", "EQUAL", strlen("equal")));
861cb0ef41Sopenharmony_ci  EXPECT_TRUE(StringEqualNoCaseN("EQUAL", "EQUAL", strlen("equal")));
871cb0ef41Sopenharmony_ci  EXPECT_TRUE(StringEqualNoCaseN("equal", "equals", strlen("equal")));
881cb0ef41Sopenharmony_ci  EXPECT_FALSE(StringEqualNoCaseN("equal", "equals", strlen("equals")));
891cb0ef41Sopenharmony_ci  EXPECT_TRUE(StringEqualNoCaseN("equals", "equal", strlen("equal")));
901cb0ef41Sopenharmony_ci  EXPECT_FALSE(StringEqualNoCaseN("equals", "equal", strlen("equals")));
911cb0ef41Sopenharmony_ci  EXPECT_TRUE(StringEqualNoCaseN("abc\0abc", "abc\0efg", strlen("abcdefgh")));
921cb0ef41Sopenharmony_ci  EXPECT_FALSE(StringEqualNoCaseN("abc\0abc", "abcd\0efg", strlen("abcdefgh")));
931cb0ef41Sopenharmony_ci}
941cb0ef41Sopenharmony_ci
951cb0ef41Sopenharmony_ciTEST(UtilTest, ToLower) {
961cb0ef41Sopenharmony_ci  EXPECT_EQ('0', ToLower('0'));
971cb0ef41Sopenharmony_ci  EXPECT_EQ('a', ToLower('a'));
981cb0ef41Sopenharmony_ci  EXPECT_EQ('a', ToLower('A'));
991cb0ef41Sopenharmony_ci}
1001cb0ef41Sopenharmony_ci
1011cb0ef41Sopenharmony_ci#define TEST_AND_FREE(expression, size)                                        \
1021cb0ef41Sopenharmony_ci  do {                                                                         \
1031cb0ef41Sopenharmony_ci    auto pointer = expression(size);                                           \
1041cb0ef41Sopenharmony_ci    EXPECT_EQ(pointer == nullptr, size == 0);                                  \
1051cb0ef41Sopenharmony_ci    free(pointer);                                                             \
1061cb0ef41Sopenharmony_ci  } while (0)
1071cb0ef41Sopenharmony_ci
1081cb0ef41Sopenharmony_ciTEST(UtilTest, Malloc) {
1091cb0ef41Sopenharmony_ci  TEST_AND_FREE(Malloc<char>, 0);
1101cb0ef41Sopenharmony_ci  TEST_AND_FREE(Malloc<char>, 1);
1111cb0ef41Sopenharmony_ci  TEST_AND_FREE(Malloc, 0);
1121cb0ef41Sopenharmony_ci  TEST_AND_FREE(Malloc, 1);
1131cb0ef41Sopenharmony_ci}
1141cb0ef41Sopenharmony_ci
1151cb0ef41Sopenharmony_ciTEST(UtilTest, Calloc) {
1161cb0ef41Sopenharmony_ci  TEST_AND_FREE(Calloc<char>, 0);
1171cb0ef41Sopenharmony_ci  TEST_AND_FREE(Calloc<char>, 1);
1181cb0ef41Sopenharmony_ci  TEST_AND_FREE(Calloc, 0);
1191cb0ef41Sopenharmony_ci  TEST_AND_FREE(Calloc, 1);
1201cb0ef41Sopenharmony_ci}
1211cb0ef41Sopenharmony_ci
1221cb0ef41Sopenharmony_ciTEST(UtilTest, UncheckedMalloc) {
1231cb0ef41Sopenharmony_ci  TEST_AND_FREE(UncheckedMalloc<char>, 0);
1241cb0ef41Sopenharmony_ci  TEST_AND_FREE(UncheckedMalloc<char>, 1);
1251cb0ef41Sopenharmony_ci  TEST_AND_FREE(UncheckedMalloc, 0);
1261cb0ef41Sopenharmony_ci  TEST_AND_FREE(UncheckedMalloc, 1);
1271cb0ef41Sopenharmony_ci}
1281cb0ef41Sopenharmony_ci
1291cb0ef41Sopenharmony_ciTEST(UtilTest, UncheckedCalloc) {
1301cb0ef41Sopenharmony_ci  TEST_AND_FREE(UncheckedCalloc<char>, 0);
1311cb0ef41Sopenharmony_ci  TEST_AND_FREE(UncheckedCalloc<char>, 1);
1321cb0ef41Sopenharmony_ci  TEST_AND_FREE(UncheckedCalloc, 0);
1331cb0ef41Sopenharmony_ci  TEST_AND_FREE(UncheckedCalloc, 1);
1341cb0ef41Sopenharmony_ci}
1351cb0ef41Sopenharmony_ci
1361cb0ef41Sopenharmony_citemplate <typename T>
1371cb0ef41Sopenharmony_cistatic void MaybeStackBufferBasic() {
1381cb0ef41Sopenharmony_ci  MaybeStackBuffer<T> buf;
1391cb0ef41Sopenharmony_ci  size_t old_length;
1401cb0ef41Sopenharmony_ci  size_t old_capacity;
1411cb0ef41Sopenharmony_ci
1421cb0ef41Sopenharmony_ci  // Default constructor.
1431cb0ef41Sopenharmony_ci  EXPECT_EQ(0U, buf.length());
1441cb0ef41Sopenharmony_ci  EXPECT_FALSE(buf.IsAllocated());
1451cb0ef41Sopenharmony_ci  EXPECT_GT(buf.capacity(), buf.length());
1461cb0ef41Sopenharmony_ci
1471cb0ef41Sopenharmony_ci  // SetLength() expansion.
1481cb0ef41Sopenharmony_ci  buf.SetLength(buf.capacity());
1491cb0ef41Sopenharmony_ci  EXPECT_EQ(buf.capacity(), buf.length());
1501cb0ef41Sopenharmony_ci  EXPECT_FALSE(buf.IsAllocated());
1511cb0ef41Sopenharmony_ci
1521cb0ef41Sopenharmony_ci  // Means of accessing raw buffer.
1531cb0ef41Sopenharmony_ci  EXPECT_EQ(buf.out(), *buf);
1541cb0ef41Sopenharmony_ci  EXPECT_EQ(&buf[0], *buf);
1551cb0ef41Sopenharmony_ci
1561cb0ef41Sopenharmony_ci  // Basic I/O.
1571cb0ef41Sopenharmony_ci  for (size_t i = 0; i < buf.length(); i++)
1581cb0ef41Sopenharmony_ci    buf[i] = static_cast<T>(i);
1591cb0ef41Sopenharmony_ci  for (size_t i = 0; i < buf.length(); i++)
1601cb0ef41Sopenharmony_ci    EXPECT_EQ(static_cast<T>(i), buf[i]);
1611cb0ef41Sopenharmony_ci
1621cb0ef41Sopenharmony_ci  // SetLengthAndZeroTerminate().
1631cb0ef41Sopenharmony_ci  buf.SetLengthAndZeroTerminate(buf.capacity() - 1);
1641cb0ef41Sopenharmony_ci  EXPECT_EQ(buf.capacity() - 1, buf.length());
1651cb0ef41Sopenharmony_ci  for (size_t i = 0; i < buf.length(); i++)
1661cb0ef41Sopenharmony_ci    EXPECT_EQ(static_cast<T>(i), buf[i]);
1671cb0ef41Sopenharmony_ci  buf.SetLength(buf.capacity());
1681cb0ef41Sopenharmony_ci  EXPECT_EQ(0, buf[buf.length() - 1]);
1691cb0ef41Sopenharmony_ci
1701cb0ef41Sopenharmony_ci  // Initial Realloc.
1711cb0ef41Sopenharmony_ci  old_length = buf.length() - 1;
1721cb0ef41Sopenharmony_ci  old_capacity = buf.capacity();
1731cb0ef41Sopenharmony_ci  buf.AllocateSufficientStorage(buf.capacity() * 2);
1741cb0ef41Sopenharmony_ci  EXPECT_EQ(buf.capacity(), buf.length());
1751cb0ef41Sopenharmony_ci  EXPECT_TRUE(buf.IsAllocated());
1761cb0ef41Sopenharmony_ci  for (size_t i = 0; i < old_length; i++)
1771cb0ef41Sopenharmony_ci    EXPECT_EQ(static_cast<T>(i), buf[i]);
1781cb0ef41Sopenharmony_ci  EXPECT_EQ(0, buf[old_length]);
1791cb0ef41Sopenharmony_ci
1801cb0ef41Sopenharmony_ci  // SetLength() reduction and expansion.
1811cb0ef41Sopenharmony_ci  for (size_t i = 0; i < buf.length(); i++)
1821cb0ef41Sopenharmony_ci    buf[i] = static_cast<T>(i);
1831cb0ef41Sopenharmony_ci  buf.SetLength(10);
1841cb0ef41Sopenharmony_ci  for (size_t i = 0; i < buf.length(); i++)
1851cb0ef41Sopenharmony_ci    EXPECT_EQ(static_cast<T>(i), buf[i]);
1861cb0ef41Sopenharmony_ci  buf.SetLength(buf.capacity());
1871cb0ef41Sopenharmony_ci  for (size_t i = 0; i < buf.length(); i++)
1881cb0ef41Sopenharmony_ci    EXPECT_EQ(static_cast<T>(i), buf[i]);
1891cb0ef41Sopenharmony_ci
1901cb0ef41Sopenharmony_ci  // Subsequent Realloc.
1911cb0ef41Sopenharmony_ci  old_length = buf.length();
1921cb0ef41Sopenharmony_ci  old_capacity = buf.capacity();
1931cb0ef41Sopenharmony_ci  buf.AllocateSufficientStorage(old_capacity * 1.5);
1941cb0ef41Sopenharmony_ci  EXPECT_EQ(buf.capacity(), buf.length());
1951cb0ef41Sopenharmony_ci  EXPECT_EQ(static_cast<size_t>(old_capacity * 1.5), buf.length());
1961cb0ef41Sopenharmony_ci  EXPECT_TRUE(buf.IsAllocated());
1971cb0ef41Sopenharmony_ci  for (size_t i = 0; i < old_length; i++)
1981cb0ef41Sopenharmony_ci    EXPECT_EQ(static_cast<T>(i), buf[i]);
1991cb0ef41Sopenharmony_ci
2001cb0ef41Sopenharmony_ci  // Basic I/O on Realloc'd buffer.
2011cb0ef41Sopenharmony_ci  for (size_t i = 0; i < buf.length(); i++)
2021cb0ef41Sopenharmony_ci    buf[i] = static_cast<T>(i);
2031cb0ef41Sopenharmony_ci  for (size_t i = 0; i < buf.length(); i++)
2041cb0ef41Sopenharmony_ci    EXPECT_EQ(static_cast<T>(i), buf[i]);
2051cb0ef41Sopenharmony_ci
2061cb0ef41Sopenharmony_ci  // Release().
2071cb0ef41Sopenharmony_ci  T* rawbuf = buf.out();
2081cb0ef41Sopenharmony_ci  buf.Release();
2091cb0ef41Sopenharmony_ci  EXPECT_EQ(0U, buf.length());
2101cb0ef41Sopenharmony_ci  EXPECT_FALSE(buf.IsAllocated());
2111cb0ef41Sopenharmony_ci  EXPECT_GT(buf.capacity(), buf.length());
2121cb0ef41Sopenharmony_ci  free(rawbuf);
2131cb0ef41Sopenharmony_ci}
2141cb0ef41Sopenharmony_ci
2151cb0ef41Sopenharmony_ciTEST(UtilTest, MaybeStackBuffer) {
2161cb0ef41Sopenharmony_ci  MaybeStackBufferBasic<uint8_t>();
2171cb0ef41Sopenharmony_ci  MaybeStackBufferBasic<uint16_t>();
2181cb0ef41Sopenharmony_ci
2191cb0ef41Sopenharmony_ci  // Constructor with size parameter.
2201cb0ef41Sopenharmony_ci  {
2211cb0ef41Sopenharmony_ci    MaybeStackBuffer<unsigned char> buf(100);
2221cb0ef41Sopenharmony_ci    EXPECT_EQ(100U, buf.length());
2231cb0ef41Sopenharmony_ci    EXPECT_FALSE(buf.IsAllocated());
2241cb0ef41Sopenharmony_ci    EXPECT_GT(buf.capacity(), buf.length());
2251cb0ef41Sopenharmony_ci    buf.SetLength(buf.capacity());
2261cb0ef41Sopenharmony_ci    EXPECT_EQ(buf.capacity(), buf.length());
2271cb0ef41Sopenharmony_ci    EXPECT_FALSE(buf.IsAllocated());
2281cb0ef41Sopenharmony_ci    for (size_t i = 0; i < buf.length(); i++)
2291cb0ef41Sopenharmony_ci      buf[i] = static_cast<unsigned char>(i);
2301cb0ef41Sopenharmony_ci    for (size_t i = 0; i < buf.length(); i++)
2311cb0ef41Sopenharmony_ci      EXPECT_EQ(static_cast<unsigned char>(i), buf[i]);
2321cb0ef41Sopenharmony_ci
2331cb0ef41Sopenharmony_ci    MaybeStackBuffer<unsigned char> bigbuf(10000);
2341cb0ef41Sopenharmony_ci    EXPECT_EQ(10000U, bigbuf.length());
2351cb0ef41Sopenharmony_ci    EXPECT_TRUE(bigbuf.IsAllocated());
2361cb0ef41Sopenharmony_ci    EXPECT_EQ(bigbuf.length(), bigbuf.capacity());
2371cb0ef41Sopenharmony_ci    for (size_t i = 0; i < bigbuf.length(); i++)
2381cb0ef41Sopenharmony_ci      bigbuf[i] = static_cast<unsigned char>(i);
2391cb0ef41Sopenharmony_ci    for (size_t i = 0; i < bigbuf.length(); i++)
2401cb0ef41Sopenharmony_ci      EXPECT_EQ(static_cast<unsigned char>(i), bigbuf[i]);
2411cb0ef41Sopenharmony_ci  }
2421cb0ef41Sopenharmony_ci
2431cb0ef41Sopenharmony_ci  // Invalidated buffer.
2441cb0ef41Sopenharmony_ci  {
2451cb0ef41Sopenharmony_ci    MaybeStackBuffer<char> buf;
2461cb0ef41Sopenharmony_ci    buf.Invalidate();
2471cb0ef41Sopenharmony_ci    EXPECT_TRUE(buf.IsInvalidated());
2481cb0ef41Sopenharmony_ci    EXPECT_FALSE(buf.IsAllocated());
2491cb0ef41Sopenharmony_ci    EXPECT_EQ(0U, buf.length());
2501cb0ef41Sopenharmony_ci    EXPECT_EQ(0U, buf.capacity());
2511cb0ef41Sopenharmony_ci    buf.Invalidate();
2521cb0ef41Sopenharmony_ci    EXPECT_TRUE(buf.IsInvalidated());
2531cb0ef41Sopenharmony_ci  }
2541cb0ef41Sopenharmony_ci}
2551cb0ef41Sopenharmony_ci
2561cb0ef41Sopenharmony_ciTEST(UtilTest, SPrintF) {
2571cb0ef41Sopenharmony_ci  // %d, %u and %s all do the same thing. The actual C++ type is used to infer
2581cb0ef41Sopenharmony_ci  // the right representation.
2591cb0ef41Sopenharmony_ci  EXPECT_EQ(SPrintF("%s", false), "false");
2601cb0ef41Sopenharmony_ci  EXPECT_EQ(SPrintF("%s", true), "true");
2611cb0ef41Sopenharmony_ci  EXPECT_EQ(SPrintF("%d", true), "true");
2621cb0ef41Sopenharmony_ci  EXPECT_EQ(SPrintF("%u", true), "true");
2631cb0ef41Sopenharmony_ci  EXPECT_EQ(SPrintF("%d", 10000000000LL), "10000000000");
2641cb0ef41Sopenharmony_ci  EXPECT_EQ(SPrintF("%d", -10000000000LL), "-10000000000");
2651cb0ef41Sopenharmony_ci  EXPECT_EQ(SPrintF("%u", 10000000000LL), "10000000000");
2661cb0ef41Sopenharmony_ci  EXPECT_EQ(SPrintF("%u", -10000000000LL), "-10000000000");
2671cb0ef41Sopenharmony_ci  EXPECT_EQ(SPrintF("%i", 10), "10");
2681cb0ef41Sopenharmony_ci  EXPECT_EQ(SPrintF("%d", 10), "10");
2691cb0ef41Sopenharmony_ci  EXPECT_EQ(SPrintF("%x", 15), "f");
2701cb0ef41Sopenharmony_ci  EXPECT_EQ(SPrintF("%x", 16), "10");
2711cb0ef41Sopenharmony_ci  EXPECT_EQ(SPrintF("%X", 15), "F");
2721cb0ef41Sopenharmony_ci  EXPECT_EQ(SPrintF("%X", 16), "10");
2731cb0ef41Sopenharmony_ci  EXPECT_EQ(SPrintF("%o", 7), "7");
2741cb0ef41Sopenharmony_ci  EXPECT_EQ(SPrintF("%o", 8), "10");
2751cb0ef41Sopenharmony_ci
2761cb0ef41Sopenharmony_ci  EXPECT_EQ(atof(SPrintF("%s", 0.5).c_str()), 0.5);
2771cb0ef41Sopenharmony_ci  EXPECT_EQ(atof(SPrintF("%s", -0.5).c_str()), -0.5);
2781cb0ef41Sopenharmony_ci
2791cb0ef41Sopenharmony_ci  void (*fn)() = []() {};
2801cb0ef41Sopenharmony_ci  void* p = reinterpret_cast<void*>(&fn);
2811cb0ef41Sopenharmony_ci  EXPECT_GE(SPrintF("%p", fn).size(), 4u);
2821cb0ef41Sopenharmony_ci  EXPECT_GE(SPrintF("%p", p).size(), 4u);
2831cb0ef41Sopenharmony_ci
2841cb0ef41Sopenharmony_ci  const std::string foo = "foo";
2851cb0ef41Sopenharmony_ci  const char* bar = "bar";
2861cb0ef41Sopenharmony_ci  EXPECT_EQ(SPrintF("%s %s", foo, "bar"), "foo bar");
2871cb0ef41Sopenharmony_ci  EXPECT_EQ(SPrintF("%s %s", foo, bar), "foo bar");
2881cb0ef41Sopenharmony_ci  EXPECT_EQ(SPrintF("%s", nullptr), "(null)");
2891cb0ef41Sopenharmony_ci
2901cb0ef41Sopenharmony_ci  EXPECT_EQ(SPrintF("[%% %s %%]", foo), "[% foo %]");
2911cb0ef41Sopenharmony_ci
2921cb0ef41Sopenharmony_ci  struct HasToString {
2931cb0ef41Sopenharmony_ci    std::string ToString() const {
2941cb0ef41Sopenharmony_ci      return "meow";
2951cb0ef41Sopenharmony_ci    }
2961cb0ef41Sopenharmony_ci  };
2971cb0ef41Sopenharmony_ci  EXPECT_EQ(SPrintF("%s", HasToString{}), "meow");
2981cb0ef41Sopenharmony_ci
2991cb0ef41Sopenharmony_ci  const std::string with_zero = std::string("a") + '\0' + 'b';
3001cb0ef41Sopenharmony_ci  EXPECT_EQ(SPrintF("%s", with_zero), with_zero);
3011cb0ef41Sopenharmony_ci}
302