1 //===- unittest/Support/YAMLRemarksSerializerTest.cpp --------------------===//
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 "llvm/Remarks/Remark.h"
10 #include "llvm/Remarks/YAMLRemarkSerializer.h"
11 #include "llvm/Support/Error.h"
12 #include "gtest/gtest.h"
13 
14 // We need to supprt Windows paths as well. In order to have paths with the same
15 // length, use a different path according to the platform.
16 #ifdef _WIN32
17 #define EXTERNALFILETESTPATH "C:/externalfi"
18 #else
19 #define EXTERNALFILETESTPATH "/externalfile"
20 #endif
21 
22 using namespace llvm;
23 
24 static void check(remarks::SerializerMode Mode, const remarks::Remark &R,
25                   StringRef ExpectedR, Optional<StringRef> ExpectedMeta,
26                   bool UseStrTab = false,
27                   Optional<remarks::StringTable> StrTab = None) {
28   std::string Buf;
29   raw_string_ostream OS(Buf);
30   Expected<std::unique_ptr<remarks::RemarkSerializer>> MaybeS = [&] {
31     if (UseStrTab) {
32       if (StrTab)
33         return createRemarkSerializer(remarks::Format::YAMLStrTab, Mode, OS,
34                                       std::move(*StrTab));
35       else
36         return createRemarkSerializer(remarks::Format::YAMLStrTab, Mode, OS);
37     } else
38       return createRemarkSerializer(remarks::Format::YAML, Mode, OS);
39   }();
40   EXPECT_FALSE(errorToBool(MaybeS.takeError()));
41   std::unique_ptr<remarks::RemarkSerializer> S = std::move(*MaybeS);
42 
43   S->emit(R);
44   EXPECT_EQ(OS.str(), ExpectedR);
45 
46   if (ExpectedMeta) {
47     Buf.clear();
48     std::unique_ptr<remarks::MetaSerializer> MS =
49         S->metaSerializer(OS, StringRef(EXTERNALFILETESTPATH));
50     MS->emit();
51     EXPECT_EQ(OS.str(), *ExpectedMeta);
52   }
53 }
54 
55 static void check(const remarks::Remark &R, StringRef ExpectedR,
56                   StringRef ExpectedMeta, bool UseStrTab = false,
57                   Optional<remarks::StringTable> StrTab = None) {
58   return check(remarks::SerializerMode::Separate, R, ExpectedR, ExpectedMeta,
59                UseStrTab, std::move(StrTab));
60 }
61 
62 static void checkStandalone(const remarks::Remark &R, StringRef ExpectedR,
63                             Optional<remarks::StringTable> StrTab = None) {
64   bool UseStrTab = StrTab.hasValue();
65   return check(remarks::SerializerMode::Standalone, R, ExpectedR,
66                /*ExpectedMeta=*/None, UseStrTab, std::move(StrTab));
67 }
68 
69 TEST(YAMLRemarks, SerializerRemark) {
70   remarks::Remark R;
71   R.RemarkType = remarks::Type::Missed;
72   R.PassName = "pass";
73   R.RemarkName = "name";
74   R.FunctionName = "func";
75   R.Loc = remarks::RemarkLocation{"path", 3, 4};
76   R.Hotness = 5;
77   R.Args.emplace_back();
78   R.Args.back().Key = "key";
79   R.Args.back().Val = "value";
80   R.Args.emplace_back();
81   R.Args.back().Key = "keydebug";
82   R.Args.back().Val = "valuedebug";
83   R.Args.back().Loc = remarks::RemarkLocation{"argpath", 6, 7};
84   check(R,
85         "--- !Missed\n"
86         "Pass:            pass\n"
87         "Name:            name\n"
88         "DebugLoc:        { File: path, Line: 3, Column: 4 }\n"
89         "Function:        func\n"
90         "Hotness:         5\n"
91         "Args:\n"
92         "  - key:             value\n"
93         "  - keydebug:        valuedebug\n"
94         "    DebugLoc:        { File: argpath, Line: 6, Column: 7 }\n"
95         "...\n",
96         StringRef("REMARKS\0"
97                   "\0\0\0\0\0\0\0\0"
98                   "\0\0\0\0\0\0\0\0"
99                   EXTERNALFILETESTPATH"\0",
100                   38));
101 }
102 
103 TEST(YAMLRemarks, SerializerRemarkStandalone) {
104   remarks::Remark R;
105   R.RemarkType = remarks::Type::Missed;
106   R.PassName = "pass";
107   R.RemarkName = "name";
108   R.FunctionName = "func";
109   R.Loc = remarks::RemarkLocation{"path", 3, 4};
110   R.Hotness = 5;
111   R.Args.emplace_back();
112   R.Args.back().Key = "key";
113   R.Args.back().Val = "value";
114   R.Args.emplace_back();
115   R.Args.back().Key = "keydebug";
116   R.Args.back().Val = "valuedebug";
117   R.Args.back().Loc = remarks::RemarkLocation{"argpath", 6, 7};
118   checkStandalone(
119       R,
120       StringRef("REMARKS\0"
121                 "\0\0\0\0\0\0\0\0"
122                 "\0\0\0\0\0\0\0\0"
123                 "--- !Missed\n"
124                 "Pass:            pass\n"
125                 "Name:            name\n"
126                 "DebugLoc:        { File: path, Line: 3, Column: 4 }\n"
127                 "Function:        func\n"
128                 "Hotness:         5\n"
129                 "Args:\n"
130                 "  - key:             value\n"
131                 "  - keydebug:        valuedebug\n"
132                 "    DebugLoc:        { File: argpath, Line: 6, Column: 7 }\n"
133                 "...\n",
134                 301));
135 }
136 
137 TEST(YAMLRemarks, SerializerRemarkStrTab) {
138   remarks::Remark R;
139   R.RemarkType = remarks::Type::Missed;
140   R.PassName = "pass";
141   R.RemarkName = "name";
142   R.FunctionName = "func";
143   R.Loc = remarks::RemarkLocation{"path", 3, 4};
144   R.Hotness = 5;
145   R.Args.emplace_back();
146   R.Args.back().Key = "key";
147   R.Args.back().Val = "value";
148   R.Args.emplace_back();
149   R.Args.back().Key = "keydebug";
150   R.Args.back().Val = "valuedebug";
151   R.Args.back().Loc = remarks::RemarkLocation{"argpath", 6, 7};
152   check(R,
153         "--- !Missed\n"
154         "Pass:            0\n"
155         "Name:            1\n"
156         "DebugLoc:        { File: 3, Line: 3, Column: 4 }\n"
157         "Function:        2\n"
158         "Hotness:         5\n"
159         "Args:\n"
160         "  - key:             4\n"
161         "  - keydebug:        5\n"
162         "    DebugLoc:        { File: 6, Line: 6, Column: 7 }\n"
163         "...\n",
164         StringRef("REMARKS\0"
165                   "\0\0\0\0\0\0\0\0"
166                   "\x2d\0\0\0\0\0\0\0"
167                   "pass\0name\0func\0path\0value\0valuedebug\0argpath\0"
168                   EXTERNALFILETESTPATH"\0",
169                   83),
170         /*UseStrTab=*/true);
171 }
172 
173 TEST(YAMLRemarks, SerializerRemarkParsedStrTab) {
174   StringRef StrTab("pass\0name\0func\0path\0value\0valuedebug\0argpath\0", 45);
175   remarks::Remark R;
176   R.RemarkType = remarks::Type::Missed;
177   R.PassName = "pass";
178   R.RemarkName = "name";
179   R.FunctionName = "func";
180   R.Loc = remarks::RemarkLocation{"path", 3, 4};
181   R.Hotness = 5;
182   R.Args.emplace_back();
183   R.Args.back().Key = "key";
184   R.Args.back().Val = "value";
185   R.Args.emplace_back();
186   R.Args.back().Key = "keydebug";
187   R.Args.back().Val = "valuedebug";
188   R.Args.back().Loc = remarks::RemarkLocation{"argpath", 6, 7};
189   check(R,
190         "--- !Missed\n"
191         "Pass:            0\n"
192         "Name:            1\n"
193         "DebugLoc:        { File: 3, Line: 3, Column: 4 }\n"
194         "Function:        2\n"
195         "Hotness:         5\n"
196         "Args:\n"
197         "  - key:             4\n"
198         "  - keydebug:        5\n"
199         "    DebugLoc:        { File: 6, Line: 6, Column: 7 }\n"
200         "...\n",
201         StringRef("REMARKS\0"
202                   "\0\0\0\0\0\0\0\0"
203                   "\x2d\0\0\0\0\0\0\0"
204                   "pass\0name\0func\0path\0value\0valuedebug\0argpath\0"
205                   EXTERNALFILETESTPATH"\0",
206                   83),
207         /*UseStrTab=*/true,
208         remarks::StringTable(remarks::ParsedStringTable(StrTab)));
209 }
210 
211 TEST(YAMLRemarks, SerializerRemarkParsedStrTabStandalone) {
212   StringRef StrTab("pass\0name\0func\0path\0value\0valuedebug\0argpath\0", 45);
213   remarks::ParsedStringTable ParsedStrTab(StrTab);
214   remarks::StringTable PreFilledStrTab(ParsedStrTab);
215   remarks::Remark R;
216   R.RemarkType = remarks::Type::Missed;
217   R.PassName = "pass";
218   R.RemarkName = "name";
219   R.FunctionName = "func";
220   R.Loc = remarks::RemarkLocation{"path", 3, 4};
221   R.Hotness = 5;
222   R.Args.emplace_back();
223   R.Args.back().Key = "key";
224   R.Args.back().Val = "value";
225   R.Args.emplace_back();
226   R.Args.back().Key = "keydebug";
227   R.Args.back().Val = "valuedebug";
228   R.Args.back().Loc = remarks::RemarkLocation{"argpath", 6, 7};
229   checkStandalone(
230       R,
231       StringRef("REMARKS\0"
232                 "\0\0\0\0\0\0\0\0"
233                 "\x2d\0\0\0\0\0\0\0"
234                 "pass\0name\0func\0path\0value\0valuedebug\0argpath\0"
235                 "--- !Missed\n"
236                 "Pass:            0\n"
237                 "Name:            1\n"
238                 "DebugLoc:        { File: 3, Line: 3, Column: 4 }\n"
239                 "Function:        2\n"
240                 "Hotness:         5\n"
241                 "Args:\n"
242                 "  - key:             4\n"
243                 "  - keydebug:        5\n"
244                 "    DebugLoc:        { File: 6, Line: 6, Column: 7 }\n"
245                 "...\n",
246                 315),
247       std::move(PreFilledStrTab));
248 }
249