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 | |