| 1 | //===- FormatTest.cpp - TableGen Format Utility Tests ---------------------===// |
| 2 | // |
| 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| 4 | // See https://llvm.org/LICENSE.txt for license information. |
| 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| 6 | // |
| 7 | //===----------------------------------------------------------------------===// |
| 8 | |
| 9 | #include "mlir/TableGen/Format.h" |
| 10 | #include "gmock/gmock.h" |
| 11 | |
| 12 | using mlir::tblgen::FmtContext; |
| 13 | using mlir::tblgen::tgfmt; |
| 14 | using ::testing::StrEq; |
| 15 | |
| 16 | TEST(FormatTest, EmptyFmtStr) { |
| 17 | FmtContext ctx; |
| 18 | std::string result = std::string(tgfmt(fmt: "" , ctx: &ctx)); |
| 19 | EXPECT_TRUE(result.empty()); |
| 20 | } |
| 21 | |
| 22 | /// Allow extra unused positional parameters. |
| 23 | TEST(FormatTest, EmptyFmtStrExtraParams) { |
| 24 | FmtContext ctx; |
| 25 | std::string result = std::string(tgfmt(fmt: "" , ctx: &ctx, vals: "a" , vals: "b" , vals: "c" )); |
| 26 | EXPECT_TRUE(result.empty()); |
| 27 | } |
| 28 | |
| 29 | /// Allow unused placeholder substitution in context. |
| 30 | TEST(FormatTest, EmptyFmtStrPopulatedCtx) { |
| 31 | FmtContext ctx; |
| 32 | ctx.withBuilder(subst: "builder" ); |
| 33 | std::string result = std::string(tgfmt(fmt: "" , ctx: &ctx)); |
| 34 | EXPECT_TRUE(result.empty()); |
| 35 | } |
| 36 | |
| 37 | TEST(FormatTest, LiteralFmtStr) { |
| 38 | FmtContext ctx; |
| 39 | std::string result = std::string(tgfmt(fmt: "void foo {}" , ctx: &ctx)); |
| 40 | EXPECT_THAT(result, StrEq("void foo {}" )); |
| 41 | } |
| 42 | |
| 43 | /// Print single dollar literally. |
| 44 | TEST(FormatTest, AdjacentDollar) { |
| 45 | FmtContext ctx; |
| 46 | std::string result = std::string(tgfmt(fmt: "$" , ctx: &ctx)); |
| 47 | EXPECT_THAT(result, StrEq("$" )); |
| 48 | } |
| 49 | |
| 50 | /// Print dangling dollar literally. |
| 51 | TEST(FormatTest, DanglingDollar) { |
| 52 | FmtContext ctx; |
| 53 | std::string result = std::string(tgfmt(fmt: "foo bar baz$" , ctx: &ctx)); |
| 54 | EXPECT_THAT(result, StrEq("foo bar baz$" )); |
| 55 | } |
| 56 | |
| 57 | /// Allow escape dollars with '$$'. |
| 58 | TEST(FormatTest, EscapeDollars) { |
| 59 | FmtContext ctx; |
| 60 | std::string result = |
| 61 | std::string(tgfmt(fmt: "$$ $$$$ $$$0 $$$_self" , ctx: &ctx.withSelf(subst: "self" ), vals: "-0" )); |
| 62 | EXPECT_THAT(result, StrEq("$ $$ $-0 $self" )); |
| 63 | } |
| 64 | |
| 65 | TEST(FormatTest, PositionalFmtStr) { |
| 66 | FmtContext ctx; |
| 67 | std::string b = "b" ; |
| 68 | int c = 42; |
| 69 | char d = 'd'; |
| 70 | std::string result = |
| 71 | std::string(tgfmt(fmt: "$0 $1 $2 $3" , ctx: &ctx, vals: "a" , vals&: b, vals: c + 1, vals&: d)); |
| 72 | EXPECT_THAT(result, StrEq("a b 43 d" )); |
| 73 | } |
| 74 | |
| 75 | /// Output the placeholder if missing substitution. |
| 76 | TEST(FormatTest, PositionalFmtStrMissingParams) { |
| 77 | FmtContext ctx; |
| 78 | std::string result = std::string(tgfmt(fmt: "$0 %1 $2" , ctx: &ctx)); |
| 79 | EXPECT_THAT(result, StrEq("$0<no-subst-found> %1 $2<no-subst-found>" )); |
| 80 | } |
| 81 | |
| 82 | /// Allow flexible reference of positional parameters. |
| 83 | TEST(FormatTest, PositionalFmtStrFlexibleRef) { |
| 84 | FmtContext ctx; |
| 85 | std::string result = std::string(tgfmt(fmt: "$2 $0 $2" , ctx: &ctx, vals: "a" , vals: "b" , vals: "c" )); |
| 86 | EXPECT_THAT(result, StrEq("c a c" )); |
| 87 | } |
| 88 | |
| 89 | TEST(FormatTest, PositionalFmtStrNoWhitespace) { |
| 90 | FmtContext ctx; |
| 91 | std::string result = std::string(tgfmt(fmt: "foo$0bar" , ctx: &ctx, vals: "-" )); |
| 92 | EXPECT_THAT(result, StrEq("foo-bar" )); |
| 93 | } |
| 94 | |
| 95 | TEST(FormatTest, PlaceHolderFmtStrWithSelf) { |
| 96 | FmtContext ctx; |
| 97 | std::string result = std::string(tgfmt(fmt: "$_self" , ctx: &ctx.withSelf(subst: "sss" ))); |
| 98 | EXPECT_THAT(result, StrEq("sss" )); |
| 99 | } |
| 100 | |
| 101 | TEST(FormatTest, PlaceHolderFmtStrWithBuilder) { |
| 102 | FmtContext ctx; |
| 103 | |
| 104 | std::string result = std::string(tgfmt(fmt: "$_builder" , ctx: &ctx.withBuilder(subst: "bbb" ))); |
| 105 | EXPECT_THAT(result, StrEq("bbb" )); |
| 106 | } |
| 107 | |
| 108 | TEST(FormatTest, PlaceHolderMissingCtx) { |
| 109 | std::string result = std::string(tgfmt(fmt: "$_op" , ctx: nullptr)); |
| 110 | EXPECT_THAT(result, StrEq("$_op<no-subst-found>" )); |
| 111 | } |
| 112 | |
| 113 | TEST(FormatTest, PlaceHolderMissingSubst) { |
| 114 | FmtContext ctx; |
| 115 | std::string result = std::string(tgfmt(fmt: "$_op" , ctx: &ctx.withBuilder(subst: "builder" ))); |
| 116 | EXPECT_THAT(result, StrEq("$_op<no-subst-found>" )); |
| 117 | } |
| 118 | |
| 119 | /// Test commonly used delimiters in C++. |
| 120 | TEST(FormatTest, PlaceHolderFmtStrDelimiter) { |
| 121 | FmtContext ctx; |
| 122 | ctx.addSubst(placeholder: "m" , subst: "" ); |
| 123 | std::string result = std::string(tgfmt(fmt: "$m{$m($m[$m]$m)$m}$m|" , ctx: &ctx)); |
| 124 | EXPECT_THAT(result, StrEq("{([])}|" )); |
| 125 | } |
| 126 | |
| 127 | /// Test allowed characters in placeholder symbol. |
| 128 | TEST(FormatTest, CustomPlaceHolderFmtStrPlaceHolderChars) { |
| 129 | FmtContext ctx; |
| 130 | ctx.addSubst(placeholder: "m" , subst: "0 " ); |
| 131 | ctx.addSubst(placeholder: "m1" , subst: "1 " ); |
| 132 | ctx.addSubst(placeholder: "m2C" , subst: "2 " ); |
| 133 | ctx.addSubst(placeholder: "M_3" , subst: "3 " ); |
| 134 | std::string result = std::string(tgfmt(fmt: "$m$m1$m2C$M_3" , ctx: &ctx)); |
| 135 | EXPECT_THAT(result, StrEq("0 1 2 3 " )); |
| 136 | } |
| 137 | |
| 138 | TEST(FormatTest, CustomPlaceHolderFmtStrUnregisteredPlaceHolders) { |
| 139 | FmtContext ctx; |
| 140 | std::string result = std::string(tgfmt(fmt: "foo($awesome, $param)" , ctx: &ctx)); |
| 141 | EXPECT_THAT(result, |
| 142 | StrEq("foo($awesome<no-subst-found>, $param<no-subst-found>)" )); |
| 143 | } |
| 144 | |
| 145 | TEST(FormatTest, MixedFmtStr) { |
| 146 | FmtContext ctx; |
| 147 | ctx.withBuilder(subst: "bbb" ); |
| 148 | |
| 149 | std::string result = std::string(tgfmt(fmt: "$_builder.build($_self, {$0, $1})" , |
| 150 | ctx: &ctx.withSelf(subst: "sss" ), vals: "a" , vals: "b" )); |
| 151 | EXPECT_THAT(result, StrEq("bbb.build(sss, {a, b})" )); |
| 152 | } |
| 153 | |