blob: ab522eaa21ceb37d5f6aef4e0bd4e6daf6d42ed2 [file] [log] [blame]
Haojian Wu357ef992016-09-21 13:18:19 +00001//===-- ClangMoveTest.cpp - clang-move unit tests -------------------------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#include "ClangMove.h"
11#include "unittests/Tooling/RewriterTestContext.h"
12#include "clang/Format/Format.h"
13#include "clang/Frontend/FrontendActions.h"
14#include "clang/Frontend/TextDiagnosticPrinter.h"
15#include "clang/Rewrite/Core/Rewriter.h"
16#include "clang/Tooling/Refactoring.h"
17#include "clang/Tooling/Tooling.h"
18#include "llvm/ADT/StringRef.h"
19#include "gtest/gtest.h"
20#include <string>
21#include <vector>
22
23namespace clang {
24namespace move {
25namespace {
26
27const char TestHeaderName[] = "foo.h";
28
29const char TestCCName[] = "foo.cc";
30
31const char TestHeader[] = "namespace a {\n"
Haojian Wu9abbeaa2016-10-06 08:59:24 +000032 "class C1; // test\n"
Haojian Wu29c38f72016-10-21 19:26:43 +000033 "template <typename T> class C2;\n"
Haojian Wu357ef992016-09-21 13:18:19 +000034 "namespace b {\n"
Haojian Wu9abbeaa2016-10-06 08:59:24 +000035 "// This is a Foo class\n"
36 "// which is used in\n"
37 "// test.\n"
Haojian Wu357ef992016-09-21 13:18:19 +000038 "class Foo {\n"
39 "public:\n"
40 " void f();\n"
41 "\n"
42 "private:\n"
43 " C1 *c1;\n"
44 " static int b;\n"
Haojian Wu9abbeaa2016-10-06 08:59:24 +000045 "}; // abc\n"
Haojian Wu357ef992016-09-21 13:18:19 +000046 "\n"
47 "class Foo2 {\n"
48 "public:\n"
49 " int f();\n"
50 "};\n"
51 "} // namespace b\n"
52 "} // namespace a\n";
53
54const char TestCC[] = "#include \"foo.h\"\n"
55 "namespace a {\n"
56 "namespace b {\n"
57 "namespace {\n"
Haojian Wu9abbeaa2016-10-06 08:59:24 +000058 "// comment1.\n"
Haojian Wu357ef992016-09-21 13:18:19 +000059 "void f1() {}\n"
Haojian Wu9abbeaa2016-10-06 08:59:24 +000060 "/// comment2.\n"
Haojian Wu357ef992016-09-21 13:18:19 +000061 "int kConstInt1 = 0;\n"
62 "} // namespace\n"
63 "\n"
Haojian Wu9abbeaa2016-10-06 08:59:24 +000064 "/* comment 3*/\n"
Haojian Wu357ef992016-09-21 13:18:19 +000065 "static int kConstInt2 = 1;\n"
66 "\n"
Haojian Wu9abbeaa2016-10-06 08:59:24 +000067 "/** comment4\n"
68 "*/\n"
Haojian Wu357ef992016-09-21 13:18:19 +000069 "static int help() {\n"
70 " int a = 0;\n"
71 " return a;\n"
72 "}\n"
73 "\n"
Haojian Wu9abbeaa2016-10-06 08:59:24 +000074 "// comment5\n"
75 "// comment5\n"
Haojian Wu357ef992016-09-21 13:18:19 +000076 "void Foo::f() { f1(); }\n"
77 "\n"
Haojian Wu9abbeaa2016-10-06 08:59:24 +000078 "/////////////\n"
79 "// comment //\n"
80 "/////////////\n"
Haojian Wu357ef992016-09-21 13:18:19 +000081 "int Foo::b = 2;\n"
82 "int Foo2::f() {\n"
83 " f1();\n"
84 " return 1;\n"
85 "}\n"
86 "} // namespace b\n"
87 "} // namespace a\n";
88
89const char ExpectedTestHeader[] = "namespace a {\n"
Haojian Wu9abbeaa2016-10-06 08:59:24 +000090 "class C1; // test\n"
Haojian Wu29c38f72016-10-21 19:26:43 +000091 "template <typename T> class C2;\n"
Haojian Wu357ef992016-09-21 13:18:19 +000092 "namespace b {\n"
93 "\n"
94 "class Foo2 {\n"
95 "public:\n"
96 " int f();\n"
97 "};\n"
98 "} // namespace b\n"
99 "} // namespace a\n";
100
101const char ExpectedTestCC[] = "#include \"foo.h\"\n"
102 "namespace a {\n"
103 "namespace b {\n"
104 "namespace {\n"
Haojian Wu9abbeaa2016-10-06 08:59:24 +0000105 "// comment1.\n"
Haojian Wu357ef992016-09-21 13:18:19 +0000106 "void f1() {}\n"
Haojian Wu9abbeaa2016-10-06 08:59:24 +0000107 "/// comment2.\n"
Haojian Wu357ef992016-09-21 13:18:19 +0000108 "int kConstInt1 = 0;\n"
109 "} // namespace\n"
110 "\n"
Haojian Wu9abbeaa2016-10-06 08:59:24 +0000111 "/* comment 3*/\n"
Haojian Wu357ef992016-09-21 13:18:19 +0000112 "static int kConstInt2 = 1;\n"
113 "\n"
Haojian Wu9abbeaa2016-10-06 08:59:24 +0000114 "/** comment4\n"
115 "*/\n"
Haojian Wu357ef992016-09-21 13:18:19 +0000116 "static int help() {\n"
117 " int a = 0;\n"
118 " return a;\n"
119 "}\n"
120 "\n"
121 "int Foo2::f() {\n"
122 " f1();\n"
123 " return 1;\n"
124 "}\n"
125 "} // namespace b\n"
126 "} // namespace a\n";
127
Haojian Wu220c7552016-10-14 13:01:36 +0000128const char ExpectedNewHeader[] = "#ifndef NEW_FOO_H\n"
129 "#define NEW_FOO_H\n"
Haojian Wu53315a72016-11-15 09:06:59 +0000130 "\n"
Haojian Wu220c7552016-10-14 13:01:36 +0000131 "namespace a {\n"
Haojian Wu9abbeaa2016-10-06 08:59:24 +0000132 "class C1; // test\n"
Haojian Wu53315a72016-11-15 09:06:59 +0000133 "\n"
Haojian Wu29c38f72016-10-21 19:26:43 +0000134 "template <typename T> class C2;\n"
Haojian Wu357ef992016-09-21 13:18:19 +0000135 "namespace b {\n"
Haojian Wu9abbeaa2016-10-06 08:59:24 +0000136 "// This is a Foo class\n"
137 "// which is used in\n"
138 "// test.\n"
Haojian Wu357ef992016-09-21 13:18:19 +0000139 "class Foo {\n"
140 "public:\n"
141 " void f();\n"
142 "\n"
143 "private:\n"
144 " C1 *c1;\n"
145 " static int b;\n"
Haojian Wu9abbeaa2016-10-06 08:59:24 +0000146 "}; // abc\n"
Haojian Wu357ef992016-09-21 13:18:19 +0000147 "} // namespace b\n"
Haojian Wu220c7552016-10-14 13:01:36 +0000148 "} // namespace a\n"
Haojian Wu53315a72016-11-15 09:06:59 +0000149 "\n"
Haojian Wu220c7552016-10-14 13:01:36 +0000150 "#endif // NEW_FOO_H\n";
Haojian Wu357ef992016-09-21 13:18:19 +0000151
Haojian Wudaf4cb82016-09-23 13:28:38 +0000152const char ExpectedNewCC[] = "namespace a {\n"
Haojian Wu357ef992016-09-21 13:18:19 +0000153 "namespace b {\n"
154 "namespace {\n"
Haojian Wu9abbeaa2016-10-06 08:59:24 +0000155 "// comment1.\n"
Haojian Wu357ef992016-09-21 13:18:19 +0000156 "void f1() {}\n"
Haojian Wu9abbeaa2016-10-06 08:59:24 +0000157 "/// comment2.\n"
Haojian Wu357ef992016-09-21 13:18:19 +0000158 "int kConstInt1 = 0;\n"
159 "} // namespace\n"
Haojian Wu53315a72016-11-15 09:06:59 +0000160 "\n"
Haojian Wu9abbeaa2016-10-06 08:59:24 +0000161 "/* comment 3*/\n"
Haojian Wu357ef992016-09-21 13:18:19 +0000162 "static int kConstInt2 = 1;\n"
Haojian Wu53315a72016-11-15 09:06:59 +0000163 "\n"
Haojian Wu9abbeaa2016-10-06 08:59:24 +0000164 "/** comment4\n"
165 "*/\n"
Haojian Wu357ef992016-09-21 13:18:19 +0000166 "static int help() {\n"
167 " int a = 0;\n"
168 " return a;\n"
169 "}\n"
Haojian Wu53315a72016-11-15 09:06:59 +0000170 "\n"
Haojian Wu9abbeaa2016-10-06 08:59:24 +0000171 "// comment5\n"
172 "// comment5\n"
Haojian Wu357ef992016-09-21 13:18:19 +0000173 "void Foo::f() { f1(); }\n"
Haojian Wu53315a72016-11-15 09:06:59 +0000174 "\n"
Haojian Wu9abbeaa2016-10-06 08:59:24 +0000175 "/////////////\n"
176 "// comment //\n"
177 "/////////////\n"
Haojian Wu357ef992016-09-21 13:18:19 +0000178 "int Foo::b = 2;\n"
179 "} // namespace b\n"
180 "} // namespace a\n";
181
182std::map<std::string, std::string>
Haojian Wub15c8da2016-11-24 10:17:17 +0000183runClangMoveOnCode(const move::MoveDefinitionSpec &Spec,
Haojian Wu2930be12016-11-08 19:55:13 +0000184 const char *const Header = TestHeader,
Haojian Wub15c8da2016-11-24 10:17:17 +0000185 const char *const CC = TestCC,
186 DeclarationReporter *const Reporter = nullptr) {
Haojian Wu357ef992016-09-21 13:18:19 +0000187 clang::RewriterTestContext Context;
188
189 std::map<llvm::StringRef, clang::FileID> FileToFileID;
190 std::vector<std::pair<std::string, std::string>> FileToSourceText = {
Haojian Wu2930be12016-11-08 19:55:13 +0000191 {TestHeaderName, Header}, {TestCCName, CC}};
Haojian Wu357ef992016-09-21 13:18:19 +0000192
193 auto CreateFiles = [&FileToSourceText, &Context, &FileToFileID](
194 llvm::StringRef Name, llvm::StringRef Code) {
195 if (!Name.empty()) {
Haojian Wu357ef992016-09-21 13:18:19 +0000196 FileToFileID[Name] = Context.createInMemoryFile(Name, Code);
197 }
198 };
199 CreateFiles(Spec.NewCC, "");
200 CreateFiles(Spec.NewHeader, "");
Haojian Wu2930be12016-11-08 19:55:13 +0000201 CreateFiles(Spec.OldHeader, Header);
202 CreateFiles(Spec.OldCC, CC);
Haojian Wu357ef992016-09-21 13:18:19 +0000203
204 std::map<std::string, tooling::Replacements> FileToReplacements;
Haojian Wud2a6d7b2016-10-04 09:05:31 +0000205 llvm::SmallString<128> InitialDirectory;
206 std::error_code EC = llvm::sys::fs::current_path(InitialDirectory);
207 assert(!EC);
208 (void)EC;
Haojian Wub15c8da2016-11-24 10:17:17 +0000209 ClangMoveContext MoveContext = {Spec, FileToReplacements,
210 InitialDirectory.str(), "LLVM",
211 Reporter != nullptr};
212
Haojian Wu357ef992016-09-21 13:18:19 +0000213 auto Factory = llvm::make_unique<clang::move::ClangMoveActionFactory>(
Haojian Wub15c8da2016-11-24 10:17:17 +0000214 &MoveContext, Reporter);
Haojian Wu357ef992016-09-21 13:18:19 +0000215
216 tooling::runToolOnCodeWithArgs(
Haojian Wu2930be12016-11-08 19:55:13 +0000217 Factory->create(), CC, {"-std=c++11", "-fparse-all-comments"},
Haojian Wu9abbeaa2016-10-06 08:59:24 +0000218 TestCCName, "clang-move", std::make_shared<PCHContainerOperations>(),
219 FileToSourceText);
Haojian Wu357ef992016-09-21 13:18:19 +0000220 formatAndApplyAllReplacements(FileToReplacements, Context.Rewrite, "llvm");
221 // The Key is file name, value is the new code after moving the class.
222 std::map<std::string, std::string> Results;
223 for (const auto &It : FileToReplacements) {
224 StringRef FilePath = It.first;
225 Results[FilePath] = Context.getRewrittenText(FileToFileID[FilePath]);
226 }
227 return Results;
228}
229
230TEST(ClangMove, MoveHeaderAndCC) {
Haojian Wub15c8da2016-11-24 10:17:17 +0000231 move::MoveDefinitionSpec Spec;
NAKAMURA Takumi0cfbbae2016-10-17 05:09:58 +0000232 Spec.Names = {std::string("a::b::Foo")};
Haojian Wu357ef992016-09-21 13:18:19 +0000233 Spec.OldHeader = "foo.h";
234 Spec.OldCC = "foo.cc";
235 Spec.NewHeader = "new_foo.h";
236 Spec.NewCC = "new_foo.cc";
Haojian Wu9abbeaa2016-10-06 08:59:24 +0000237 std::string ExpectedHeader = "#include \"" + Spec.NewHeader + "\"\n\n";
Haojian Wu357ef992016-09-21 13:18:19 +0000238 auto Results = runClangMoveOnCode(Spec);
239 EXPECT_EQ(ExpectedTestHeader, Results[Spec.OldHeader]);
240 EXPECT_EQ(ExpectedTestCC, Results[Spec.OldCC]);
241 EXPECT_EQ(ExpectedNewHeader, Results[Spec.NewHeader]);
Haojian Wudaf4cb82016-09-23 13:28:38 +0000242 EXPECT_EQ(ExpectedHeader + ExpectedNewCC, Results[Spec.NewCC]);
Haojian Wu357ef992016-09-21 13:18:19 +0000243}
244
245TEST(ClangMove, MoveHeaderOnly) {
Haojian Wub15c8da2016-11-24 10:17:17 +0000246 move::MoveDefinitionSpec Spec;
NAKAMURA Takumi0cfbbae2016-10-17 05:09:58 +0000247 Spec.Names = {std::string("a::b::Foo")};
Haojian Wu357ef992016-09-21 13:18:19 +0000248 Spec.OldHeader = "foo.h";
249 Spec.NewHeader = "new_foo.h";
250 auto Results = runClangMoveOnCode(Spec);
Haojian Wu62ba4462016-09-21 15:19:04 +0000251 EXPECT_EQ(2u, Results.size());
Haojian Wu357ef992016-09-21 13:18:19 +0000252 EXPECT_EQ(ExpectedTestHeader, Results[Spec.OldHeader]);
253 EXPECT_EQ(ExpectedNewHeader, Results[Spec.NewHeader]);
254}
255
256TEST(ClangMove, MoveCCOnly) {
Haojian Wub15c8da2016-11-24 10:17:17 +0000257 move::MoveDefinitionSpec Spec;
NAKAMURA Takumi0cfbbae2016-10-17 05:09:58 +0000258 Spec.Names = {std::string("a::b::Foo")};
Haojian Wu357ef992016-09-21 13:18:19 +0000259 Spec.OldCC = "foo.cc";
260 Spec.NewCC = "new_foo.cc";
Haojian Wu9abbeaa2016-10-06 08:59:24 +0000261 std::string ExpectedHeader = "#include \"foo.h\"\n\n";
Haojian Wu357ef992016-09-21 13:18:19 +0000262 auto Results = runClangMoveOnCode(Spec);
Haojian Wu62ba4462016-09-21 15:19:04 +0000263 EXPECT_EQ(2u, Results.size());
Haojian Wu357ef992016-09-21 13:18:19 +0000264 EXPECT_EQ(ExpectedTestCC, Results[Spec.OldCC]);
Haojian Wudaf4cb82016-09-23 13:28:38 +0000265 EXPECT_EQ(ExpectedHeader + ExpectedNewCC, Results[Spec.NewCC]);
Haojian Wu357ef992016-09-21 13:18:19 +0000266}
267
268TEST(ClangMove, MoveNonExistClass) {
Haojian Wub15c8da2016-11-24 10:17:17 +0000269 move::MoveDefinitionSpec Spec;
NAKAMURA Takumi0cfbbae2016-10-17 05:09:58 +0000270 Spec.Names = {std::string("NonExistFoo")};
Haojian Wu357ef992016-09-21 13:18:19 +0000271 Spec.OldHeader = "foo.h";
272 Spec.OldCC = "foo.cc";
273 Spec.NewHeader = "new_foo.h";
274 Spec.NewCC = "new_foo.cc";
275 auto Results = runClangMoveOnCode(Spec);
Haojian Wu62ba4462016-09-21 15:19:04 +0000276 EXPECT_EQ(0u, Results.size());
Haojian Wu357ef992016-09-21 13:18:19 +0000277}
278
Haojian Wu2930be12016-11-08 19:55:13 +0000279TEST(ClangMove, MoveAll) {
280 std::vector<std::string> TestHeaders = {
281 "class A {\npublic:\n int f();\n};",
282 // forward declaration.
283 "class B;\nclass A {\npublic:\n int f();\n};",
284 // template forward declaration.
285 "template <typename T> class B;\nclass A {\npublic:\n int f();\n};",
286 "namespace a {}\nclass A {\npublic:\n int f();\n};",
287 "namespace a {}\nusing namespace a;\nclass A {\npublic:\n int f();\n};",
288 };
289 const char Code[] = "#include \"foo.h\"\nint A::f() { return 0; }";
Haojian Wub15c8da2016-11-24 10:17:17 +0000290 move::MoveDefinitionSpec Spec;
Haojian Wu2930be12016-11-08 19:55:13 +0000291 Spec.Names.push_back("A");
292 Spec.OldHeader = "foo.h";
293 Spec.OldCC = "foo.cc";
294 Spec.NewHeader = "new_foo.h";
295 Spec.NewCC = "new_foo.cc";
296 for (const auto& Header : TestHeaders) {
297 auto Results = runClangMoveOnCode(Spec, Header.c_str(), Code);
298 EXPECT_EQ(Header, Results[Spec.NewHeader]);
299 EXPECT_EQ("", Results[Spec.OldHeader]);
300 EXPECT_EQ("", Results[Spec.OldCC]);
301 }
302}
303
304TEST(ClangMove, MoveAllMultipleClasses) {
Haojian Wub15c8da2016-11-24 10:17:17 +0000305 move::MoveDefinitionSpec Spec;
Haojian Wu2930be12016-11-08 19:55:13 +0000306 std::vector<std::string> TestHeaders = {
307 "class C;\nclass A {\npublic:\n int f();\n};\nclass B {};",
308 "class C;\nclass B;\nclass A {\npublic:\n int f();\n};\nclass B {};",
309 };
310 const char Code[] = "#include \"foo.h\"\nint A::f() { return 0; }";
311 Spec.Names = {std::string("A"), std::string("B")};
312 Spec.OldHeader = "foo.h";
313 Spec.OldCC = "foo.cc";
314 Spec.NewHeader = "new_foo.h";
315 Spec.NewCC = "new_foo.cc";
316 for (const auto& Header : TestHeaders) {
317 auto Results = runClangMoveOnCode(Spec, Header.c_str(), Code);
318 EXPECT_EQ(Header, Results[Spec.NewHeader]);
319 EXPECT_EQ("", Results[Spec.OldHeader]);
320 EXPECT_EQ("", Results[Spec.OldCC]);
321 }
322}
323
324TEST(ClangMove, DontMoveAll) {
325 const char ExpectedHeader[] = "#ifndef NEW_FOO_H\n"
326 "#define NEW_FOO_H\n"
Haojian Wu53315a72016-11-15 09:06:59 +0000327 "\n"
Haojian Wu2930be12016-11-08 19:55:13 +0000328 "class A {\npublic:\n int f();\n};\n"
Haojian Wu53315a72016-11-15 09:06:59 +0000329 "\n"
Haojian Wu2930be12016-11-08 19:55:13 +0000330 "#endif // NEW_FOO_H\n";
331 const char Code[] = "#include \"foo.h\"\nint A::f() { return 0; }";
332 std::vector<std::string> TestHeaders = {
Haojian Wu53315a72016-11-15 09:06:59 +0000333 "typedef int Int;\nclass A {\npublic:\n int f();\n};\n",
334 "using Int=int;\nclass A {\npublic:\n int f();\n};\n",
335 "class B {};\nclass A {\npublic:\n int f();\n};\n",
336 "void f() {};\nclass A {\npublic:\n int f();\n};\n",
337 "enum Color { RED };\nclass A {\npublic:\n int f();\n};\n",
Haojian Wu2930be12016-11-08 19:55:13 +0000338 };
Haojian Wub15c8da2016-11-24 10:17:17 +0000339 move::MoveDefinitionSpec Spec;
Haojian Wu2930be12016-11-08 19:55:13 +0000340 Spec.Names.push_back("A");
341 Spec.OldHeader = "foo.h";
342 Spec.OldCC = "foo.cc";
343 Spec.NewHeader = "new_foo.h";
344 Spec.NewCC = "new_foo.cc";
345 for (const auto& Header : TestHeaders) {
346 auto Results = runClangMoveOnCode(Spec, Header.c_str(), Code);
347 EXPECT_EQ(ExpectedHeader, Results[Spec.NewHeader]);
348 // The expected old header should not contain class A definition.
Haojian Wu53315a72016-11-15 09:06:59 +0000349 std::string ExpectedOldHeader = Header.substr(0, Header.size() - 32);
Haojian Wu2930be12016-11-08 19:55:13 +0000350 EXPECT_EQ(ExpectedOldHeader, Results[Spec.OldHeader]);
351 }
352}
353
Haojian Wu24675392016-11-14 14:46:48 +0000354TEST(ClangMove, MacroInFunction) {
355 const char TestHeader[] = "#define INT int\n"
356 "class A {\npublic:\n int f();\n};\n"
357 "class B {};\n";
358 const char TestCode[] = "#include \"foo.h\"\n"
359 "INT A::f() { return 0; }\n";
360 const char ExpectedNewCode[] = "#include \"new_foo.h\"\n\n"
361 "INT A::f() { return 0; }\n";
Haojian Wub15c8da2016-11-24 10:17:17 +0000362 move::MoveDefinitionSpec Spec;
Haojian Wu24675392016-11-14 14:46:48 +0000363 Spec.Names.push_back("A");
364 Spec.OldHeader = "foo.h";
365 Spec.OldCC = "foo.cc";
366 Spec.NewHeader = "new_foo.h";
367 Spec.NewCC = "new_foo.cc";
368 auto Results = runClangMoveOnCode(Spec, TestHeader, TestCode);
369 EXPECT_EQ(ExpectedNewCode, Results[Spec.NewCC]);
370}
371
Haojian Wu53315a72016-11-15 09:06:59 +0000372TEST(ClangMove, WellFormattedCode) {
373 const std::string CommonHeader =
374 "namespace a {\n"
375 "namespace b {\n"
376 "namespace c {\n"
377 "class C;\n"
378 "\n"
379 "class A {\npublic:\n void f();\n void f2();\n};\n"
380 "} // namespace c\n"
381 "} // namespace b\n"
382 "\n"
383 "namespace d {\n"
384 "namespace e {\n"
385 "class B {\npublic:\n void f();\n};\n"
386 "} // namespace e\n"
387 "} // namespace d\n"
388 "} // namespace a\n";
389 const std::string CommonCode = "\n"
390 "namespace a {\n"
391 "namespace b {\n"
392 "namespace c {\n"
393 "void A::f() {}\n"
394 "\n"
395 "void A::f2() {}\n"
396 "} // namespace c\n"
397 "} // namespace b\n"
398 "\n"
399 "namespace d {\n"
400 "namespace e {\n"
401 "void B::f() {}\n"
402 "} // namespace e\n"
403 "} // namespace d\n"
404 "} // namespace a\n";
405 // Add dummy class to prevent behavior of moving all declarations from header.
406 const std::string TestHeader = CommonHeader + "class D {};\n";
407 const std::string TestCode = "#include \"foo.h\"\n" + CommonCode;
408 const std::string ExpectedNewHeader = "#ifndef NEW_FOO_H\n"
409 "#define NEW_FOO_H\n"
410 "\n" +
411 CommonHeader +
412 "\n"
413 "#endif // NEW_FOO_H\n";
414 const std::string ExpectedNewCC = "#include \"new_foo.h\"\n" + CommonCode;
Haojian Wub15c8da2016-11-24 10:17:17 +0000415 move::MoveDefinitionSpec Spec;
Haojian Wu53315a72016-11-15 09:06:59 +0000416 Spec.Names.push_back("a::b::c::A");
417 Spec.Names.push_back("a::d::e::B");
418 Spec.OldHeader = "foo.h";
419 Spec.OldCC = "foo.cc";
420 Spec.NewHeader = "new_foo.h";
421 Spec.NewCC = "new_foo.cc";
422 auto Results = runClangMoveOnCode(Spec, TestHeader.c_str(), TestCode.c_str());
423 EXPECT_EQ(ExpectedNewCC, Results[Spec.NewCC]);
424 EXPECT_EQ(ExpectedNewHeader, Results[Spec.NewHeader]);
425}
426
Haojian Wu48ac3042016-11-23 10:04:19 +0000427TEST(ClangMove, AddDependentNewHeader) {
428 const char TestHeader[] = "class A {};\n"
429 "class B {};\n";
430 const char TestCode[] = "#include \"foo.h\"\n";
431 const char ExpectedOldHeader[] = "#include \"new_foo.h\"\nclass B {};\n";
432 const char ExpectedNewHeader[] = "#ifndef NEW_FOO_H\n"
433 "#define NEW_FOO_H\n"
434 "\n"
435 "class A {};\n"
436 "\n"
437 "#endif // NEW_FOO_H\n";
Haojian Wub15c8da2016-11-24 10:17:17 +0000438 move::MoveDefinitionSpec Spec;
Haojian Wu48ac3042016-11-23 10:04:19 +0000439 Spec.Names.push_back("A");
440 Spec.OldHeader = "foo.h";
441 Spec.OldCC = "foo.cc";
442 Spec.NewHeader = "new_foo.h";
443 Spec.NewCC = "new_foo.cc";
444 Spec.OldDependOnNew = true;
445 auto Results = runClangMoveOnCode(Spec, TestHeader, TestCode);
446 EXPECT_EQ(ExpectedOldHeader, Results[Spec.OldHeader]);
447 EXPECT_EQ(ExpectedNewHeader, Results[Spec.NewHeader]);
448}
449
450TEST(ClangMove, AddDependentOldHeader) {
451 const char TestHeader[] = "class A {};\n"
452 "class B {};\n";
453 const char TestCode[] = "#include \"foo.h\"\n";
454 const char ExpectedNewHeader[] = "#ifndef NEW_FOO_H\n"
455 "#define NEW_FOO_H\n"
456 "\n"
457 "#include \"foo.h\"\n"
458 "\n"
459 "class B {};\n"
460 "\n"
461 "#endif // NEW_FOO_H\n";
462 const char ExpectedOldHeader[] = "class A {};\n";
Haojian Wub15c8da2016-11-24 10:17:17 +0000463 move::MoveDefinitionSpec Spec;
Haojian Wu48ac3042016-11-23 10:04:19 +0000464 Spec.Names.push_back("B");
465 Spec.OldHeader = "foo.h";
466 Spec.OldCC = "foo.cc";
467 Spec.NewHeader = "new_foo.h";
468 Spec.NewCC = "new_foo.cc";
469 Spec.NewDependOnOld = true;
470 auto Results = runClangMoveOnCode(Spec, TestHeader, TestCode);
471 EXPECT_EQ(ExpectedNewHeader, Results[Spec.NewHeader]);
472 EXPECT_EQ(ExpectedOldHeader, Results[Spec.OldHeader]);
473}
474
Haojian Wub15c8da2016-11-24 10:17:17 +0000475TEST(ClangMove, DumpDecls) {
476 const char TestHeader[] = "template <typename T>\n"
477 "class A {\n"
478 " public:\n"
479 " void f();\n"
480 " template <typename U> void h();\n"
481 " static int b;\n"
482 "};\n"
483 "\n"
484 "template <typename T> void A<T>::f() {}\n"
485 "\n"
486 "template <typename T>\n"
487 "template <typename U>\n"
488 "void A<T>::h() {}\n"
489 "\n"
490 "template <typename T> int A<T>::b = 2;\n"
491 "\n"
492 "template <> class A<int> {};\n"
493 "\n"
494 "class B {};\n"
495 "\n"
496 "namespace a {\n"
497 "class Move1 {};\n"
498 "void f1() {}\n"
499 "void f2();\n"
500 "} // namespace a\n"
501 "\n"
502 "namespace a {\n"
503 "namespace b {\n"
504 "class Move1 { public : void f(); };\n"
505 "void f() {}\n"
506 "} // namespace b\n"
507 "} // namespace a\n";
508 const char TestCode[] = "#include \"foo.h\"\n";
509 move::MoveDefinitionSpec Spec;
510 Spec.Names.push_back("B");
511 Spec.OldHeader = "foo.h";
512 Spec.OldCC = "foo.cc";
513 Spec.NewHeader = "new_foo.h";
514 Spec.NewCC = "new_foo.cc";
515 DeclarationReporter Reporter;
516 std::vector<DeclarationReporter::DeclarationPair> ExpectedDeclarations = {
517 {"A", "Class"}, {"B", "Class"}, {"a::Move1", "Class"},
518 {"a::f1", "Function"}, {"a::f2", "Function"}, {"a::b::Move1", "Class"},
519 {"a::b::f", "Function"}};
520 runClangMoveOnCode(Spec, TestHeader, TestCode, &Reporter);
521 const auto& Results = Reporter.getDeclarationList();
522 auto ActualDeclIter = Results.begin();
523 auto ExpectedDeclIter = ExpectedDeclarations.begin();
524 while (ActualDeclIter != Results.end() && ExpectedDeclIter != Results.end()) {
525 EXPECT_EQ(*ActualDeclIter, *ExpectedDeclIter);
526 ++ActualDeclIter;
527 ++ExpectedDeclIter;
528 }
529 ASSERT_TRUE(ActualDeclIter == Results.end());
530 ASSERT_TRUE(ExpectedDeclIter == ExpectedDeclarations.end());
531}
532
Haojian Wu357ef992016-09-21 13:18:19 +0000533} // namespace
534} // namespce move
535} // namespace clang