111db2642SZachary Turner //===- FormatVariadicTest.cpp - Unit tests for string formatting ----------===// 211db2642SZachary Turner // 311db2642SZachary Turner // The LLVM Compiler Infrastructure 411db2642SZachary Turner // 511db2642SZachary Turner // This file is distributed under the University of Illinois Open Source 611db2642SZachary Turner // License. See LICENSE.TXT for details. 711db2642SZachary Turner // 811db2642SZachary Turner //===----------------------------------------------------------------------===// 911db2642SZachary Turner 1011db2642SZachary Turner #include "llvm/Support/FormatAdapters.h" 1111db2642SZachary Turner #include "llvm/Support/FormatVariadic.h" 1211db2642SZachary Turner #include "gtest/gtest.h" 1311db2642SZachary Turner 1411db2642SZachary Turner using namespace llvm; 1511db2642SZachary Turner 16*fefefeb7SPavel Labath // Compile-time tests for the uses_format_member template 17*fefefeb7SPavel Labath namespace { 18*fefefeb7SPavel Labath struct ConstFormat { 19*fefefeb7SPavel Labath void format(raw_ostream &OS, StringRef Opt) const { OS << "ConstFormat"; } 20*fefefeb7SPavel Labath }; 21*fefefeb7SPavel Labath 22*fefefeb7SPavel Labath struct Format { 23*fefefeb7SPavel Labath void format(raw_ostream &OS, StringRef Opt) { OS << "Format"; } 24*fefefeb7SPavel Labath }; 25*fefefeb7SPavel Labath 26*fefefeb7SPavel Labath using detail::uses_format_member; 27*fefefeb7SPavel Labath 28*fefefeb7SPavel Labath static_assert(uses_format_member<Format>::value, ""); 29*fefefeb7SPavel Labath static_assert(uses_format_member<Format &>::value, ""); 30*fefefeb7SPavel Labath static_assert(uses_format_member<Format &&>::value, ""); 31*fefefeb7SPavel Labath static_assert(not uses_format_member<const Format>::value, ""); 32*fefefeb7SPavel Labath static_assert(not uses_format_member<const Format &>::value, ""); 33*fefefeb7SPavel Labath static_assert(not uses_format_member<const volatile Format>::value, ""); 34*fefefeb7SPavel Labath static_assert(not uses_format_member<const volatile Format &>::value, ""); 35*fefefeb7SPavel Labath 36*fefefeb7SPavel Labath static_assert(uses_format_member<ConstFormat>::value, ""); 37*fefefeb7SPavel Labath static_assert(uses_format_member<ConstFormat &>::value, ""); 38*fefefeb7SPavel Labath static_assert(uses_format_member<ConstFormat &&>::value, ""); 39*fefefeb7SPavel Labath static_assert(uses_format_member<const ConstFormat>::value, ""); 40*fefefeb7SPavel Labath static_assert(uses_format_member<const ConstFormat &>::value, ""); 41*fefefeb7SPavel Labath static_assert(uses_format_member<const volatile ConstFormat>::value, ""); 42*fefefeb7SPavel Labath static_assert(uses_format_member<const volatile ConstFormat &>::value, ""); 43*fefefeb7SPavel Labath } 44*fefefeb7SPavel Labath 4511db2642SZachary Turner TEST(FormatVariadicTest, EmptyFormatString) { 4611db2642SZachary Turner auto Replacements = formatv_object_base::parseFormatString(""); 4711db2642SZachary Turner EXPECT_EQ(0U, Replacements.size()); 4811db2642SZachary Turner } 4911db2642SZachary Turner 5011db2642SZachary Turner TEST(FormatVariadicTest, NoReplacements) { 5111db2642SZachary Turner const StringRef kFormatString = "This is a test"; 5211db2642SZachary Turner auto Replacements = formatv_object_base::parseFormatString(kFormatString); 5311db2642SZachary Turner ASSERT_EQ(1U, Replacements.size()); 5411db2642SZachary Turner EXPECT_EQ(kFormatString, Replacements[0].Spec); 5511db2642SZachary Turner EXPECT_EQ(ReplacementType::Literal, Replacements[0].Type); 5611db2642SZachary Turner } 5711db2642SZachary Turner 5811db2642SZachary Turner TEST(FormatVariadicTest, EscapedBrace) { 5911db2642SZachary Turner // {{ should be replaced with { 6011db2642SZachary Turner auto Replacements = formatv_object_base::parseFormatString("{{"); 6111db2642SZachary Turner ASSERT_EQ(1u, Replacements.size()); 6211db2642SZachary Turner EXPECT_EQ("{", Replacements[0].Spec); 6311db2642SZachary Turner EXPECT_EQ(ReplacementType::Literal, Replacements[0].Type); 6411db2642SZachary Turner 6511db2642SZachary Turner // An even number N of braces should be replaced with N/2 braces. 6611db2642SZachary Turner Replacements = formatv_object_base::parseFormatString("{{{{{{"); 6711db2642SZachary Turner ASSERT_EQ(1u, Replacements.size()); 6811db2642SZachary Turner EXPECT_EQ("{{{", Replacements[0].Spec); 6911db2642SZachary Turner EXPECT_EQ(ReplacementType::Literal, Replacements[0].Type); 7011db2642SZachary Turner } 7111db2642SZachary Turner 7211db2642SZachary Turner TEST(FormatVariadicTest, ValidReplacementSequence) { 7311db2642SZachary Turner // 1. Simple replacement - parameter index only 7411db2642SZachary Turner auto Replacements = formatv_object_base::parseFormatString("{0}"); 7511db2642SZachary Turner ASSERT_EQ(1u, Replacements.size()); 7611db2642SZachary Turner EXPECT_EQ(ReplacementType::Format, Replacements[0].Type); 7711db2642SZachary Turner EXPECT_EQ(0u, Replacements[0].Index); 7811db2642SZachary Turner EXPECT_EQ(0u, Replacements[0].Align); 7911db2642SZachary Turner EXPECT_EQ("", Replacements[0].Options); 8011db2642SZachary Turner 8111db2642SZachary Turner Replacements = formatv_object_base::parseFormatString("{1}"); 8211db2642SZachary Turner ASSERT_EQ(1u, Replacements.size()); 8311db2642SZachary Turner EXPECT_EQ(ReplacementType::Format, Replacements[0].Type); 8411db2642SZachary Turner EXPECT_EQ(1u, Replacements[0].Index); 8511db2642SZachary Turner EXPECT_EQ(0u, Replacements[0].Align); 8611db2642SZachary Turner EXPECT_EQ(AlignStyle::Right, Replacements[0].Where); 8711db2642SZachary Turner EXPECT_EQ("", Replacements[0].Options); 8811db2642SZachary Turner 8911db2642SZachary Turner // 2. Parameter index with right alignment 9011db2642SZachary Turner Replacements = formatv_object_base::parseFormatString("{0,3}"); 9111db2642SZachary Turner ASSERT_EQ(1u, Replacements.size()); 9211db2642SZachary Turner EXPECT_EQ(ReplacementType::Format, Replacements[0].Type); 9311db2642SZachary Turner EXPECT_EQ(0u, Replacements[0].Index); 9411db2642SZachary Turner EXPECT_EQ(3u, Replacements[0].Align); 9511db2642SZachary Turner EXPECT_EQ(AlignStyle::Right, Replacements[0].Where); 9611db2642SZachary Turner EXPECT_EQ("", Replacements[0].Options); 9711db2642SZachary Turner 9811db2642SZachary Turner // 3. And left alignment 9911db2642SZachary Turner Replacements = formatv_object_base::parseFormatString("{0,-3}"); 10011db2642SZachary Turner ASSERT_EQ(1u, Replacements.size()); 10111db2642SZachary Turner EXPECT_EQ(ReplacementType::Format, Replacements[0].Type); 10211db2642SZachary Turner EXPECT_EQ(0u, Replacements[0].Index); 10311db2642SZachary Turner EXPECT_EQ(3u, Replacements[0].Align); 10411db2642SZachary Turner EXPECT_EQ(AlignStyle::Left, Replacements[0].Where); 10511db2642SZachary Turner EXPECT_EQ("", Replacements[0].Options); 10611db2642SZachary Turner 10711db2642SZachary Turner // 4. And center alignment 10811db2642SZachary Turner Replacements = formatv_object_base::parseFormatString("{0,=3}"); 10911db2642SZachary Turner ASSERT_EQ(1u, Replacements.size()); 11011db2642SZachary Turner EXPECT_EQ(ReplacementType::Format, Replacements[0].Type); 11111db2642SZachary Turner EXPECT_EQ(0u, Replacements[0].Index); 11211db2642SZachary Turner EXPECT_EQ(3u, Replacements[0].Align); 11311db2642SZachary Turner EXPECT_EQ(AlignStyle::Center, Replacements[0].Where); 11411db2642SZachary Turner EXPECT_EQ("", Replacements[0].Options); 11511db2642SZachary Turner 11611db2642SZachary Turner // 4. Parameter index with option string 11711db2642SZachary Turner Replacements = formatv_object_base::parseFormatString("{0:foo}"); 11811db2642SZachary Turner ASSERT_EQ(1u, Replacements.size()); 11911db2642SZachary Turner EXPECT_EQ(ReplacementType::Format, Replacements[0].Type); 12011db2642SZachary Turner EXPECT_EQ(0u, Replacements[0].Index); 12111db2642SZachary Turner EXPECT_EQ(0u, Replacements[0].Align); 12211db2642SZachary Turner EXPECT_EQ(AlignStyle::Right, Replacements[0].Where); 12311db2642SZachary Turner EXPECT_EQ("foo", Replacements[0].Options); 12411db2642SZachary Turner 12511db2642SZachary Turner // 5. Parameter index with alignment before option string 12611db2642SZachary Turner Replacements = formatv_object_base::parseFormatString("{0,-3:foo}"); 12711db2642SZachary Turner ASSERT_EQ(1u, Replacements.size()); 12811db2642SZachary Turner EXPECT_EQ(ReplacementType::Format, Replacements[0].Type); 12911db2642SZachary Turner EXPECT_EQ(0u, Replacements[0].Index); 13011db2642SZachary Turner EXPECT_EQ(3u, Replacements[0].Align); 13111db2642SZachary Turner EXPECT_EQ(AlignStyle::Left, Replacements[0].Where); 13211db2642SZachary Turner EXPECT_EQ("foo", Replacements[0].Options); 13311db2642SZachary Turner 13411db2642SZachary Turner // 7. Parameter indices, options, and alignment can all have whitespace. 13511db2642SZachary Turner Replacements = formatv_object_base::parseFormatString("{ 0, -3 : foo }"); 13611db2642SZachary Turner ASSERT_EQ(1u, Replacements.size()); 13711db2642SZachary Turner EXPECT_EQ(ReplacementType::Format, Replacements[0].Type); 13811db2642SZachary Turner EXPECT_EQ(0u, Replacements[0].Index); 13911db2642SZachary Turner EXPECT_EQ(3u, Replacements[0].Align); 14011db2642SZachary Turner EXPECT_EQ(AlignStyle::Left, Replacements[0].Where); 14111db2642SZachary Turner EXPECT_EQ("foo", Replacements[0].Options); 14211db2642SZachary Turner 14311db2642SZachary Turner // 8. Everything after the first option specifier is part of the style, even 14411db2642SZachary Turner // if it contains another option specifier. 14511db2642SZachary Turner Replacements = formatv_object_base::parseFormatString("{0:0:1}"); 14611db2642SZachary Turner ASSERT_EQ(1u, Replacements.size()); 14711db2642SZachary Turner EXPECT_EQ("0:0:1", Replacements[0].Spec); 14811db2642SZachary Turner EXPECT_EQ(ReplacementType::Format, Replacements[0].Type); 14911db2642SZachary Turner EXPECT_EQ(0u, Replacements[0].Index); 15011db2642SZachary Turner EXPECT_EQ(0u, Replacements[0].Align); 15111db2642SZachary Turner EXPECT_EQ(AlignStyle::Right, Replacements[0].Where); 15211db2642SZachary Turner EXPECT_EQ("0:1", Replacements[0].Options); 15311db2642SZachary Turner } 15411db2642SZachary Turner 15511db2642SZachary Turner TEST(FormatVariadicTest, DefaultReplacementValues) { 15611db2642SZachary Turner // 2. If options string is missing, it defaults to empty. 15711db2642SZachary Turner auto Replacements = formatv_object_base::parseFormatString("{0,3}"); 15811db2642SZachary Turner ASSERT_EQ(1u, Replacements.size()); 15911db2642SZachary Turner EXPECT_EQ(ReplacementType::Format, Replacements[0].Type); 16011db2642SZachary Turner EXPECT_EQ(0u, Replacements[0].Index); 16111db2642SZachary Turner EXPECT_EQ(3u, Replacements[0].Align); 16211db2642SZachary Turner EXPECT_EQ("", Replacements[0].Options); 16311db2642SZachary Turner 16411db2642SZachary Turner // Including if the colon is present but contains no text. 16511db2642SZachary Turner Replacements = formatv_object_base::parseFormatString("{0,3:}"); 16611db2642SZachary Turner ASSERT_EQ(1u, Replacements.size()); 16711db2642SZachary Turner EXPECT_EQ(ReplacementType::Format, Replacements[0].Type); 16811db2642SZachary Turner EXPECT_EQ(0u, Replacements[0].Index); 16911db2642SZachary Turner EXPECT_EQ(3u, Replacements[0].Align); 17011db2642SZachary Turner EXPECT_EQ("", Replacements[0].Options); 17111db2642SZachary Turner 17211db2642SZachary Turner // 3. If alignment is missing, it defaults to 0, right, space 17311db2642SZachary Turner Replacements = formatv_object_base::parseFormatString("{0:foo}"); 17411db2642SZachary Turner ASSERT_EQ(1u, Replacements.size()); 17511db2642SZachary Turner EXPECT_EQ(ReplacementType::Format, Replacements[0].Type); 17611db2642SZachary Turner EXPECT_EQ(AlignStyle::Right, Replacements[0].Where); 17711db2642SZachary Turner EXPECT_EQ(' ', Replacements[0].Pad); 17811db2642SZachary Turner EXPECT_EQ(0u, Replacements[0].Index); 17911db2642SZachary Turner EXPECT_EQ(0u, Replacements[0].Align); 18011db2642SZachary Turner EXPECT_EQ("foo", Replacements[0].Options); 18111db2642SZachary Turner } 18211db2642SZachary Turner 18311db2642SZachary Turner TEST(FormatVariadicTest, MultipleReplacements) { 18411db2642SZachary Turner auto Replacements = 18511db2642SZachary Turner formatv_object_base::parseFormatString("{0} {1:foo}-{2,-3:bar}"); 18611db2642SZachary Turner ASSERT_EQ(5u, Replacements.size()); 18711db2642SZachary Turner // {0} 18811db2642SZachary Turner EXPECT_EQ(ReplacementType::Format, Replacements[0].Type); 18911db2642SZachary Turner EXPECT_EQ(0u, Replacements[0].Index); 19011db2642SZachary Turner EXPECT_EQ(0u, Replacements[0].Align); 19111db2642SZachary Turner EXPECT_EQ(AlignStyle::Right, Replacements[0].Where); 19211db2642SZachary Turner EXPECT_EQ("", Replacements[0].Options); 19311db2642SZachary Turner 19411db2642SZachary Turner // " " 19511db2642SZachary Turner EXPECT_EQ(ReplacementType::Literal, Replacements[1].Type); 19611db2642SZachary Turner EXPECT_EQ(" ", Replacements[1].Spec); 19711db2642SZachary Turner 19811db2642SZachary Turner // {1:foo} - Options=foo 19911db2642SZachary Turner EXPECT_EQ(ReplacementType::Format, Replacements[2].Type); 20011db2642SZachary Turner EXPECT_EQ(1u, Replacements[2].Index); 20111db2642SZachary Turner EXPECT_EQ(0u, Replacements[2].Align); 20211db2642SZachary Turner EXPECT_EQ(AlignStyle::Right, Replacements[2].Where); 20311db2642SZachary Turner EXPECT_EQ("foo", Replacements[2].Options); 20411db2642SZachary Turner 20511db2642SZachary Turner // "-" 20611db2642SZachary Turner EXPECT_EQ(ReplacementType::Literal, Replacements[3].Type); 20711db2642SZachary Turner EXPECT_EQ("-", Replacements[3].Spec); 20811db2642SZachary Turner 20911db2642SZachary Turner // {2:bar,-3} - Options=bar, Align=-3 21011db2642SZachary Turner EXPECT_EQ(ReplacementType::Format, Replacements[4].Type); 21111db2642SZachary Turner EXPECT_EQ(2u, Replacements[4].Index); 21211db2642SZachary Turner EXPECT_EQ(3u, Replacements[4].Align); 21311db2642SZachary Turner EXPECT_EQ(AlignStyle::Left, Replacements[4].Where); 21411db2642SZachary Turner EXPECT_EQ("bar", Replacements[4].Options); 21511db2642SZachary Turner } 21611db2642SZachary Turner 21711db2642SZachary Turner TEST(FormatVariadicTest, FormatNoReplacements) { 21811db2642SZachary Turner EXPECT_EQ("", formatv("").str()); 21911db2642SZachary Turner EXPECT_EQ("Test", formatv("Test").str()); 22011db2642SZachary Turner } 22111db2642SZachary Turner 22211db2642SZachary Turner TEST(FormatVariadicTest, FormatBasicTypesOneReplacement) { 22311db2642SZachary Turner EXPECT_EQ("1", formatv("{0}", 1).str()); 22411db2642SZachary Turner EXPECT_EQ("c", formatv("{0}", 'c').str()); 22511db2642SZachary Turner EXPECT_EQ("-3", formatv("{0}", -3).str()); 22611db2642SZachary Turner EXPECT_EQ("Test", formatv("{0}", "Test").str()); 22711db2642SZachary Turner EXPECT_EQ("Test2", formatv("{0}", StringRef("Test2")).str()); 22811db2642SZachary Turner EXPECT_EQ("Test3", formatv("{0}", std::string("Test3")).str()); 22911db2642SZachary Turner } 23011db2642SZachary Turner 23111db2642SZachary Turner TEST(FormatVariadicTest, IntegralHexFormatting) { 23211db2642SZachary Turner // 1. Trivial cases. Make sure hex is not the default. 23311db2642SZachary Turner EXPECT_EQ("0", formatv("{0}", 0).str()); 23411db2642SZachary Turner EXPECT_EQ("2748", formatv("{0}", 0xABC).str()); 23511db2642SZachary Turner EXPECT_EQ("-2748", formatv("{0}", -0xABC).str()); 23611db2642SZachary Turner 23711db2642SZachary Turner // 3. various hex prefixes. 23811db2642SZachary Turner EXPECT_EQ("0xFF", formatv("{0:X}", 255).str()); 23911db2642SZachary Turner EXPECT_EQ("0xFF", formatv("{0:X+}", 255).str()); 24011db2642SZachary Turner EXPECT_EQ("0xff", formatv("{0:x}", 255).str()); 24111db2642SZachary Turner EXPECT_EQ("0xff", formatv("{0:x+}", 255).str()); 24211db2642SZachary Turner EXPECT_EQ("FF", formatv("{0:X-}", 255).str()); 24311db2642SZachary Turner EXPECT_EQ("ff", formatv("{0:x-}", 255).str()); 24411db2642SZachary Turner 24511db2642SZachary Turner // 5. Precision pads left of the most significant digit but right of the 24611db2642SZachary Turner // prefix (if one exists). 24711db2642SZachary Turner EXPECT_EQ("0xFF", formatv("{0:X2}", 255).str()); 24811db2642SZachary Turner EXPECT_EQ("0xFF", formatv("{0:X+2}", 255).str()); 24911db2642SZachary Turner EXPECT_EQ("0x0ff", formatv("{0:x3}", 255).str()); 25011db2642SZachary Turner EXPECT_EQ("0x0ff", formatv("{0:x+3}", 255).str()); 25111db2642SZachary Turner EXPECT_EQ("00FF", formatv("{0:X-4}", 255).str()); 25211db2642SZachary Turner EXPECT_EQ("00ff", formatv("{0:x-4}", 255).str()); 25311db2642SZachary Turner 25411db2642SZachary Turner // 6. Try some larger types. 25511db2642SZachary Turner EXPECT_EQ("0xDEADBEEFDEADBEEF", 25611db2642SZachary Turner formatv("{0:X16}", -2401053088876216593LL).str()); 25711db2642SZachary Turner EXPECT_EQ("0xFEEBDAEDFEEBDAED", 25811db2642SZachary Turner formatv("{0:X16}", 0xFEEBDAEDFEEBDAEDULL).str()); 25911db2642SZachary Turner EXPECT_EQ("0x00000000DEADBEEF", formatv("{0:X16}", 0xDEADBEEF).str()); 26011db2642SZachary Turner 26111db2642SZachary Turner // 7. Padding should take into account the prefix 26211db2642SZachary Turner EXPECT_EQ("0xff", formatv("{0,4:x}", 255).str()); 26311db2642SZachary Turner EXPECT_EQ(" 0xff", formatv("{0,5:x+}", 255).str()); 26411db2642SZachary Turner EXPECT_EQ(" FF", formatv("{0,4:X-}", 255).str()); 26511db2642SZachary Turner EXPECT_EQ(" ff", formatv("{0,5:x-}", 255).str()); 26611db2642SZachary Turner 26711db2642SZachary Turner // 8. Including when it's been zero-padded 26811db2642SZachary Turner EXPECT_EQ(" 0x0ff", formatv("{0,7:x3}", 255).str()); 26911db2642SZachary Turner EXPECT_EQ(" 0x00ff", formatv("{0,7:x+4}", 255).str()); 27011db2642SZachary Turner EXPECT_EQ(" 000FF", formatv("{0,7:X-5}", 255).str()); 27111db2642SZachary Turner EXPECT_EQ(" 0000ff", formatv("{0,7:x-6}", 255).str()); 27211db2642SZachary Turner 27311db2642SZachary Turner // 9. Precision with default format specifier should work too 27411db2642SZachary Turner EXPECT_EQ(" 255", formatv("{0,7:3}", 255).str()); 27511db2642SZachary Turner EXPECT_EQ(" 0255", formatv("{0,7:4}", 255).str()); 27611db2642SZachary Turner EXPECT_EQ(" 00255", formatv("{0,7:5}", 255).str()); 27711db2642SZachary Turner EXPECT_EQ(" 000255", formatv("{0,7:6}", 255).str()); 27811db2642SZachary Turner } 27911db2642SZachary Turner 28011db2642SZachary Turner TEST(FormatVariadicTest, PointerFormatting) { 28111db2642SZachary Turner // 1. Trivial cases. Hex is default. Default Precision is pointer width. 28211db2642SZachary Turner if (sizeof(void *) == 4) { 28311db2642SZachary Turner EXPECT_EQ("0x00000000", formatv("{0}", (void *)0).str()); 28411db2642SZachary Turner EXPECT_EQ("0x00000ABC", formatv("{0}", (void *)0xABC).str()); 28511db2642SZachary Turner } else { 28611db2642SZachary Turner EXPECT_EQ("0x0000000000000000", formatv("{0}", (void *)0).str()); 28711db2642SZachary Turner EXPECT_EQ("0x0000000000000ABC", formatv("{0}", (void *)0xABC).str()); 28811db2642SZachary Turner } 28911db2642SZachary Turner 29011db2642SZachary Turner // 2. But we can reduce the precision explicitly. 29111db2642SZachary Turner EXPECT_EQ("0x0", formatv("{0:0}", (void *)0).str()); 29211db2642SZachary Turner EXPECT_EQ("0xABC", formatv("{0:0}", (void *)0xABC).str()); 29311db2642SZachary Turner EXPECT_EQ("0x0000", formatv("{0:4}", (void *)0).str()); 29411db2642SZachary Turner EXPECT_EQ("0x0ABC", formatv("{0:4}", (void *)0xABC).str()); 29511db2642SZachary Turner 29611db2642SZachary Turner // 3. various hex prefixes. 29711db2642SZachary Turner EXPECT_EQ("0x0ABC", formatv("{0:X4}", (void *)0xABC).str()); 29811db2642SZachary Turner EXPECT_EQ("0x0abc", formatv("{0:x4}", (void *)0xABC).str()); 29911db2642SZachary Turner EXPECT_EQ("0ABC", formatv("{0:X-4}", (void *)0xABC).str()); 30011db2642SZachary Turner EXPECT_EQ("0abc", formatv("{0:x-4}", (void *)0xABC).str()); 30111db2642SZachary Turner } 30211db2642SZachary Turner 30311db2642SZachary Turner TEST(FormatVariadicTest, IntegralNumberFormatting) { 30411db2642SZachary Turner // 1. Test comma grouping with default widths and precisions. 30511db2642SZachary Turner EXPECT_EQ("0", formatv("{0:N}", 0).str()); 30611db2642SZachary Turner EXPECT_EQ("10", formatv("{0:N}", 10).str()); 30711db2642SZachary Turner EXPECT_EQ("100", formatv("{0:N}", 100).str()); 30811db2642SZachary Turner EXPECT_EQ("1,000", formatv("{0:N}", 1000).str()); 30911db2642SZachary Turner EXPECT_EQ("1,234,567,890", formatv("{0:N}", 1234567890).str()); 31011db2642SZachary Turner EXPECT_EQ("-10", formatv("{0:N}", -10).str()); 31111db2642SZachary Turner EXPECT_EQ("-100", formatv("{0:N}", -100).str()); 31211db2642SZachary Turner EXPECT_EQ("-1,000", formatv("{0:N}", -1000).str()); 31311db2642SZachary Turner EXPECT_EQ("-1,234,567,890", formatv("{0:N}", -1234567890).str()); 31411db2642SZachary Turner 31511db2642SZachary Turner // 2. If there is no comma, width and precision pad to the same absolute 31611db2642SZachary Turner // size. 31711db2642SZachary Turner EXPECT_EQ(" 1", formatv("{0,2:N}", 1).str()); 31811db2642SZachary Turner 31911db2642SZachary Turner // 3. But if there is a comma or negative sign, width factors them in but 32011db2642SZachary Turner // precision doesn't. 32111db2642SZachary Turner EXPECT_EQ(" 1,000", formatv("{0,6:N}", 1000).str()); 32211db2642SZachary Turner EXPECT_EQ(" -1,000", formatv("{0,7:N}", -1000).str()); 32311db2642SZachary Turner 32411db2642SZachary Turner // 4. Large widths all line up. 32511db2642SZachary Turner EXPECT_EQ(" 1,000", formatv("{0,11:N}", 1000).str()); 32611db2642SZachary Turner EXPECT_EQ(" -1,000", formatv("{0,11:N}", -1000).str()); 32711db2642SZachary Turner EXPECT_EQ(" -100,000", formatv("{0,11:N}", -100000).str()); 32811db2642SZachary Turner } 32911db2642SZachary Turner 33011db2642SZachary Turner TEST(FormatVariadicTest, StringFormatting) { 33111db2642SZachary Turner const char FooArray[] = "FooArray"; 33211db2642SZachary Turner const char *FooPtr = "FooPtr"; 33311db2642SZachary Turner llvm::StringRef FooRef("FooRef"); 33411db2642SZachary Turner std::string FooString("FooString"); 33511db2642SZachary Turner // 1. Test that we can print various types of strings. 33611db2642SZachary Turner EXPECT_EQ(FooArray, formatv("{0}", FooArray).str()); 33711db2642SZachary Turner EXPECT_EQ(FooPtr, formatv("{0}", FooPtr).str()); 33811db2642SZachary Turner EXPECT_EQ(FooRef, formatv("{0}", FooRef).str()); 33911db2642SZachary Turner EXPECT_EQ(FooString, formatv("{0}", FooString).str()); 34011db2642SZachary Turner 34111db2642SZachary Turner // 2. Test that the precision specifier prints the correct number of 34211db2642SZachary Turner // characters. 34311db2642SZachary Turner EXPECT_EQ("FooA", formatv("{0:4}", FooArray).str()); 34411db2642SZachary Turner EXPECT_EQ("FooP", formatv("{0:4}", FooPtr).str()); 34511db2642SZachary Turner EXPECT_EQ("FooR", formatv("{0:4}", FooRef).str()); 34611db2642SZachary Turner EXPECT_EQ("FooS", formatv("{0:4}", FooString).str()); 34711db2642SZachary Turner 34811db2642SZachary Turner // 3. And that padding works. 34911db2642SZachary Turner EXPECT_EQ(" FooA", formatv("{0,6:4}", FooArray).str()); 35011db2642SZachary Turner EXPECT_EQ(" FooP", formatv("{0,6:4}", FooPtr).str()); 35111db2642SZachary Turner EXPECT_EQ(" FooR", formatv("{0,6:4}", FooRef).str()); 35211db2642SZachary Turner EXPECT_EQ(" FooS", formatv("{0,6:4}", FooString).str()); 35311db2642SZachary Turner } 35411db2642SZachary Turner 35511db2642SZachary Turner TEST(FormatVariadicTest, CharFormatting) { 35611db2642SZachary Turner // 1. Not much to see here. Just print a char with and without padding. 35711db2642SZachary Turner EXPECT_EQ("C", formatv("{0}", 'C').str()); 35811db2642SZachary Turner EXPECT_EQ(" C", formatv("{0,3}", 'C').str()); 35911db2642SZachary Turner 36011db2642SZachary Turner // 2. char is really an integral type though, where the only difference is 36111db2642SZachary Turner // that the "default" is to print the ASCII. So if a non-default presentation 36211db2642SZachary Turner // specifier exists, it should print as an integer. 36311db2642SZachary Turner EXPECT_EQ("37", formatv("{0:D}", (char)37).str()); 36411db2642SZachary Turner EXPECT_EQ(" 037", formatv("{0,5:D3}", (char)37).str()); 36511db2642SZachary Turner } 36611db2642SZachary Turner 36711db2642SZachary Turner TEST(FormatVariadicTest, BoolTest) { 36811db2642SZachary Turner // 1. Default style is lowercase text (same as 't') 36911db2642SZachary Turner EXPECT_EQ("true", formatv("{0}", true).str()); 37011db2642SZachary Turner EXPECT_EQ("false", formatv("{0}", false).str()); 37111db2642SZachary Turner EXPECT_EQ("true", formatv("{0:t}", true).str()); 37211db2642SZachary Turner EXPECT_EQ("false", formatv("{0:t}", false).str()); 37311db2642SZachary Turner 37411db2642SZachary Turner // 2. T - uppercase text 37511db2642SZachary Turner EXPECT_EQ("TRUE", formatv("{0:T}", true).str()); 37611db2642SZachary Turner EXPECT_EQ("FALSE", formatv("{0:T}", false).str()); 37711db2642SZachary Turner 37811db2642SZachary Turner // 3. D / d - integral 37911db2642SZachary Turner EXPECT_EQ("1", formatv("{0:D}", true).str()); 38011db2642SZachary Turner EXPECT_EQ("0", formatv("{0:D}", false).str()); 38111db2642SZachary Turner EXPECT_EQ("1", formatv("{0:d}", true).str()); 38211db2642SZachary Turner EXPECT_EQ("0", formatv("{0:d}", false).str()); 38311db2642SZachary Turner 38411db2642SZachary Turner // 4. Y - uppercase yes/no 38511db2642SZachary Turner EXPECT_EQ("YES", formatv("{0:Y}", true).str()); 38611db2642SZachary Turner EXPECT_EQ("NO", formatv("{0:Y}", false).str()); 38711db2642SZachary Turner 38811db2642SZachary Turner // 5. y - lowercase yes/no 38911db2642SZachary Turner EXPECT_EQ("yes", formatv("{0:y}", true).str()); 39011db2642SZachary Turner EXPECT_EQ("no", formatv("{0:y}", false).str()); 39111db2642SZachary Turner } 39211db2642SZachary Turner 39311db2642SZachary Turner TEST(FormatVariadicTest, DoubleFormatting) { 39411db2642SZachary Turner // Test exponents, fixed point, and percent formatting. 39511db2642SZachary Turner 39611db2642SZachary Turner // 1. Signed, unsigned, and zero exponent format. 39711db2642SZachary Turner EXPECT_EQ("0.000000E+00", formatv("{0:E}", 0.0).str()); 39811db2642SZachary Turner EXPECT_EQ("-0.000000E+00", formatv("{0:E}", -0.0).str()); 39911db2642SZachary Turner EXPECT_EQ("1.100000E+00", formatv("{0:E}", 1.1).str()); 40011db2642SZachary Turner EXPECT_EQ("-1.100000E+00", formatv("{0:E}", -1.1).str()); 40111db2642SZachary Turner EXPECT_EQ("1.234568E+03", formatv("{0:E}", 1234.5678).str()); 40211db2642SZachary Turner EXPECT_EQ("-1.234568E+03", formatv("{0:E}", -1234.5678).str()); 40311db2642SZachary Turner EXPECT_EQ("1.234568E-03", formatv("{0:E}", .0012345678).str()); 40411db2642SZachary Turner EXPECT_EQ("-1.234568E-03", formatv("{0:E}", -.0012345678).str()); 40511db2642SZachary Turner 40611db2642SZachary Turner // 2. With padding and precision. 40711db2642SZachary Turner EXPECT_EQ(" 0.000E+00", formatv("{0,11:E3}", 0.0).str()); 40811db2642SZachary Turner EXPECT_EQ(" -1.100E+00", formatv("{0,11:E3}", -1.1).str()); 40911db2642SZachary Turner EXPECT_EQ(" 1.235E+03", formatv("{0,11:E3}", 1234.5678).str()); 41011db2642SZachary Turner EXPECT_EQ(" -1.235E-03", formatv("{0,11:E3}", -.0012345678).str()); 41111db2642SZachary Turner 41211db2642SZachary Turner // 3. Signed, unsigned, and zero fixed point format. 41311db2642SZachary Turner EXPECT_EQ("0.00", formatv("{0:F}", 0.0).str()); 41411db2642SZachary Turner EXPECT_EQ("-0.00", formatv("{0:F}", -0.0).str()); 41511db2642SZachary Turner EXPECT_EQ("1.10", formatv("{0:F}", 1.1).str()); 41611db2642SZachary Turner EXPECT_EQ("-1.10", formatv("{0:F}", -1.1).str()); 41711db2642SZachary Turner EXPECT_EQ("1234.57", formatv("{0:F}", 1234.5678).str()); 41811db2642SZachary Turner EXPECT_EQ("-1234.57", formatv("{0:F}", -1234.5678).str()); 41911db2642SZachary Turner EXPECT_EQ("0.00", formatv("{0:F}", .0012345678).str()); 42011db2642SZachary Turner EXPECT_EQ("-0.00", formatv("{0:F}", -.0012345678).str()); 42111db2642SZachary Turner 42211db2642SZachary Turner // 2. With padding and precision. 42311db2642SZachary Turner EXPECT_EQ(" 0.000", formatv("{0,8:F3}", 0.0).str()); 42411db2642SZachary Turner EXPECT_EQ(" -1.100", formatv("{0,8:F3}", -1.1).str()); 42511db2642SZachary Turner EXPECT_EQ("1234.568", formatv("{0,8:F3}", 1234.5678).str()); 42611db2642SZachary Turner EXPECT_EQ(" -0.001", formatv("{0,8:F3}", -.0012345678).str()); 42711db2642SZachary Turner } 42811db2642SZachary Turner 42911db2642SZachary Turner struct format_tuple { 43011db2642SZachary Turner const char *Fmt; 43111db2642SZachary Turner explicit format_tuple(const char *Fmt) : Fmt(Fmt) {} 43211db2642SZachary Turner 43311db2642SZachary Turner template <typename... Ts> 43411db2642SZachary Turner auto operator()(Ts &&... Values) const 43511db2642SZachary Turner -> decltype(formatv(Fmt, std::forward<Ts>(Values)...)) { 43611db2642SZachary Turner return formatv(Fmt, std::forward<Ts>(Values)...); 43711db2642SZachary Turner } 43811db2642SZachary Turner }; 43911db2642SZachary Turner 44011db2642SZachary Turner TEST(FormatVariadicTest, BigTest) { 44111db2642SZachary Turner using Tuple = 44211db2642SZachary Turner std::tuple<char, int, const char *, StringRef, std::string, double, float, 44311db2642SZachary Turner void *, int, double, int64_t, uint64_t, double, uint8_t>; 44411db2642SZachary Turner Tuple Ts[] = { 44511db2642SZachary Turner Tuple('a', 1, "Str", StringRef(), std::string(), 3.14159, -.17532f, 44611db2642SZachary Turner (void *)nullptr, 123456, 6.02E23, -908234908423, 908234908422234, 44711db2642SZachary Turner std::numeric_limits<double>::quiet_NaN(), 0xAB), 44811db2642SZachary Turner Tuple('x', 0xDDB5B, "LongerStr", "StringRef", "std::string", -2.7, 44911db2642SZachary Turner .08215f, (void *)nullptr, 0, 6.62E-34, -908234908423, 45011db2642SZachary Turner 908234908422234, std::numeric_limits<double>::infinity(), 0x0)}; 45111db2642SZachary Turner // Test long string formatting with many edge cases combined. 45211db2642SZachary Turner const char *Intro = 45311db2642SZachary Turner "There are {{{0}} items in the tuple, and {{{1}} tuple(s) in the array."; 45411db2642SZachary Turner const char *Header = 45511db2642SZachary Turner "{0,6}|{1,8}|{2,=10}|{3,=10}|{4,=13}|{5,7}|{6,7}|{7,10}|{8," 45611db2642SZachary Turner "-7}|{9,10}|{10,16}|{11,17}|{12,6}|{13,4}"; 45711db2642SZachary Turner const char *Line = 45811db2642SZachary Turner "{0,6}|{1,8:X}|{2,=10}|{3,=10:5}|{4,=13}|{5,7:3}|{6,7:P2}|{7," 45911db2642SZachary Turner "10:X8}|{8,-7:N}|{9,10:E4}|{10,16:N}|{11,17:D}|{12,6}|{13," 46011db2642SZachary Turner "4:X}"; 46111db2642SZachary Turner 46211db2642SZachary Turner std::string S; 46311db2642SZachary Turner llvm::raw_string_ostream Stream(S); 46411db2642SZachary Turner Stream << formatv(Intro, std::tuple_size<Tuple>::value, 46511db2642SZachary Turner llvm::array_lengthof(Ts)) 46611db2642SZachary Turner << "\n"; 46711db2642SZachary Turner Stream << formatv(Header, "Char", "HexInt", "Str", "Ref", "std::str", 46811db2642SZachary Turner "double", "float", "pointer", "comma", "exp", "bigint", 46911db2642SZachary Turner "bigint2", "limit", "byte") 47011db2642SZachary Turner << "\n"; 47111db2642SZachary Turner for (auto &Item : Ts) { 47211db2642SZachary Turner Stream << llvm::apply_tuple(format_tuple(Line), Item) << "\n"; 47311db2642SZachary Turner } 47411db2642SZachary Turner Stream.flush(); 47511db2642SZachary Turner const char *Expected = 47611db2642SZachary Turner R"foo(There are {14} items in the tuple, and {2} tuple(s) in the array. 47711db2642SZachary Turner Char| HexInt| Str | Ref | std::str | double| float| pointer|comma | exp| bigint| bigint2| limit|byte 47811db2642SZachary Turner a| 0x1| Str | | | 3.142|-17.53%|0x00000000|123,456|6.0200E+23|-908,234,908,423| 908234908422234| nan|0xAB 47911db2642SZachary Turner x| 0xDDB5B|LongerStr | Strin | std::string | -2.700| 8.21%|0x00000000|0 |6.6200E-34|-908,234,908,423| 908234908422234| INF| 0x0 48011db2642SZachary Turner )foo"; 48111db2642SZachary Turner 48211db2642SZachary Turner EXPECT_EQ(Expected, S); 48311db2642SZachary Turner } 48411db2642SZachary Turner 48511db2642SZachary Turner TEST(FormatVariadicTest, Range) { 48611db2642SZachary Turner std::vector<int> IntRange = {1, 1, 2, 3, 5, 8, 13}; 48711db2642SZachary Turner 48811db2642SZachary Turner // 1. Simple range with default separator and element style. 48911db2642SZachary Turner EXPECT_EQ("1, 1, 2, 3, 5, 8, 13", 49011db2642SZachary Turner formatv("{0}", make_range(IntRange.begin(), IntRange.end())).str()); 49111db2642SZachary Turner EXPECT_EQ("1, 2, 3, 5, 8", 49211db2642SZachary Turner formatv("{0}", make_range(IntRange.begin() + 1, IntRange.end() - 1)) 49311db2642SZachary Turner .str()); 49411db2642SZachary Turner 49511db2642SZachary Turner // 2. Non-default separator 49611db2642SZachary Turner EXPECT_EQ( 49711db2642SZachary Turner "1/1/2/3/5/8/13", 49811db2642SZachary Turner formatv("{0:$[/]}", make_range(IntRange.begin(), IntRange.end())).str()); 49911db2642SZachary Turner 50011db2642SZachary Turner // 3. Default separator, non-default element style. 50111db2642SZachary Turner EXPECT_EQ( 50211db2642SZachary Turner "0x1, 0x1, 0x2, 0x3, 0x5, 0x8, 0xd", 50311db2642SZachary Turner formatv("{0:@[x]}", make_range(IntRange.begin(), IntRange.end())).str()); 50411db2642SZachary Turner 50511db2642SZachary Turner // 4. Non-default separator and element style. 50611db2642SZachary Turner EXPECT_EQ( 50711db2642SZachary Turner "0x1 + 0x1 + 0x2 + 0x3 + 0x5 + 0x8 + 0xd", 50811db2642SZachary Turner formatv("{0:$[ + ]@[x]}", make_range(IntRange.begin(), IntRange.end())) 50911db2642SZachary Turner .str()); 51011db2642SZachary Turner 51111db2642SZachary Turner // 5. Element style and/or separator using alternate delimeters to allow using 51211db2642SZachary Turner // delimeter characters as part of the separator. 51311db2642SZachary Turner EXPECT_EQ( 51411db2642SZachary Turner "<0x1><0x1><0x2><0x3><0x5><0x8><0xd>", 51511db2642SZachary Turner formatv("<{0:$[><]@(x)}>", make_range(IntRange.begin(), IntRange.end())) 51611db2642SZachary Turner .str()); 51711db2642SZachary Turner EXPECT_EQ( 51811db2642SZachary Turner "[0x1][0x1][0x2][0x3][0x5][0x8][0xd]", 51911db2642SZachary Turner formatv("[{0:$(][)@[x]}]", make_range(IntRange.begin(), IntRange.end())) 52011db2642SZachary Turner .str()); 52111db2642SZachary Turner EXPECT_EQ( 52211db2642SZachary Turner "(0x1)(0x1)(0x2)(0x3)(0x5)(0x8)(0xd)", 52311db2642SZachary Turner formatv("({0:$<)(>@<x>})", make_range(IntRange.begin(), IntRange.end())) 52411db2642SZachary Turner .str()); 52511db2642SZachary Turner 52611db2642SZachary Turner // 5. Empty range. 52711db2642SZachary Turner EXPECT_EQ("", formatv("{0:$[+]@[x]}", 52811db2642SZachary Turner make_range(IntRange.begin(), IntRange.begin())) 52911db2642SZachary Turner .str()); 53011db2642SZachary Turner 53111db2642SZachary Turner // 6. Empty separator and style. 53211db2642SZachary Turner EXPECT_EQ("11235813", 53311db2642SZachary Turner formatv("{0:$[]@<>}", make_range(IntRange.begin(), IntRange.end())) 53411db2642SZachary Turner .str()); 53511db2642SZachary Turner } 53611db2642SZachary Turner 53711db2642SZachary Turner TEST(FormatVariadicTest, Adapter) { 53811db2642SZachary Turner class Negative { 53911db2642SZachary Turner int N; 54011db2642SZachary Turner 54111db2642SZachary Turner public: 54211db2642SZachary Turner explicit Negative(int N) : N(N) {} 543*fefefeb7SPavel Labath void format(raw_ostream &S, StringRef Options) const { S << -N; } 54411db2642SZachary Turner }; 54511db2642SZachary Turner 54611db2642SZachary Turner EXPECT_EQ("-7", formatv("{0}", Negative(7)).str()); 54711db2642SZachary Turner 54811db2642SZachary Turner int N = 171; 54911db2642SZachary Turner 55011db2642SZachary Turner EXPECT_EQ(" 171 ", 55111db2642SZachary Turner formatv("{0}", fmt_align(N, AlignStyle::Center, 7)).str()); 55211db2642SZachary Turner EXPECT_EQ(" 171 ", formatv("{0}", fmt_pad(N, 1, 3)).str()); 55311db2642SZachary Turner EXPECT_EQ("171171171171171", formatv("{0}", fmt_repeat(N, 5)).str()); 55411db2642SZachary Turner 55511db2642SZachary Turner EXPECT_EQ(" ABABABABAB ", 55611db2642SZachary Turner formatv("{0:X-}", fmt_pad(fmt_repeat(N, 5), 1, 3)).str()); 55711db2642SZachary Turner EXPECT_EQ(" AB AB AB AB AB ", 55811db2642SZachary Turner formatv("{0,=34:X-}", fmt_repeat(fmt_pad(N, 1, 3), 5)).str()); 55911db2642SZachary Turner } 56011db2642SZachary Turner 56111db2642SZachary Turner TEST(FormatVariadicTest, ImplicitConversions) { 56211db2642SZachary Turner std::string S = formatv("{0} {1}", 1, 2); 56311db2642SZachary Turner EXPECT_EQ("1 2", S); 56411db2642SZachary Turner 56511db2642SZachary Turner SmallString<4> S2 = formatv("{0} {1}", 1, 2); 56611db2642SZachary Turner EXPECT_EQ("1 2", S2); 56711db2642SZachary Turner } 568*fefefeb7SPavel Labath 569*fefefeb7SPavel Labath TEST(FormatVariadicTest, FormatMember) { 570*fefefeb7SPavel Labath EXPECT_EQ("Format", formatv("{0}", Format()).str()); 571*fefefeb7SPavel Labath 572*fefefeb7SPavel Labath Format var; 573*fefefeb7SPavel Labath EXPECT_EQ("Format", formatv("{0}", var).str()); 574*fefefeb7SPavel Labath EXPECT_EQ("Format", formatv("{0}", std::move(var)).str()); 575*fefefeb7SPavel Labath 576*fefefeb7SPavel Labath // Not supposed to compile 577*fefefeb7SPavel Labath // const Format cvar{}; 578*fefefeb7SPavel Labath // EXPECT_EQ("Format", formatv("{0}", cvar).str()); 579*fefefeb7SPavel Labath } 580*fefefeb7SPavel Labath 581*fefefeb7SPavel Labath TEST(FormatVariadicTest, FormatMemberConst) { 582*fefefeb7SPavel Labath EXPECT_EQ("ConstFormat", formatv("{0}", ConstFormat()).str()); 583*fefefeb7SPavel Labath 584*fefefeb7SPavel Labath ConstFormat var; 585*fefefeb7SPavel Labath EXPECT_EQ("ConstFormat", formatv("{0}", var).str()); 586*fefefeb7SPavel Labath EXPECT_EQ("ConstFormat", formatv("{0}", std::move(var)).str()); 587*fefefeb7SPavel Labath 588*fefefeb7SPavel Labath const ConstFormat cvar{}; 589*fefefeb7SPavel Labath EXPECT_EQ("ConstFormat", formatv("{0}", cvar).str()); 590*fefefeb7SPavel Labath } 591