blob: 1b79314cc3910554f388851e209fce1f69c65a78 [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 Wu2930be12016-11-08 19:55:13 +0000183runClangMoveOnCode(const move::ClangMoveTool::MoveDefinitionSpec &Spec,
184 const char *const Header = TestHeader,
185 const char *const CC = TestCC) {
Haojian Wu357ef992016-09-21 13:18:19 +0000186 clang::RewriterTestContext Context;
187
188 std::map<llvm::StringRef, clang::FileID> FileToFileID;
189 std::vector<std::pair<std::string, std::string>> FileToSourceText = {
Haojian Wu2930be12016-11-08 19:55:13 +0000190 {TestHeaderName, Header}, {TestCCName, CC}};
Haojian Wu357ef992016-09-21 13:18:19 +0000191
192 auto CreateFiles = [&FileToSourceText, &Context, &FileToFileID](
193 llvm::StringRef Name, llvm::StringRef Code) {
194 if (!Name.empty()) {
Haojian Wu357ef992016-09-21 13:18:19 +0000195 FileToFileID[Name] = Context.createInMemoryFile(Name, Code);
196 }
197 };
198 CreateFiles(Spec.NewCC, "");
199 CreateFiles(Spec.NewHeader, "");
Haojian Wu2930be12016-11-08 19:55:13 +0000200 CreateFiles(Spec.OldHeader, Header);
201 CreateFiles(Spec.OldCC, CC);
Haojian Wu357ef992016-09-21 13:18:19 +0000202
203 std::map<std::string, tooling::Replacements> FileToReplacements;
Haojian Wud2a6d7b2016-10-04 09:05:31 +0000204 llvm::SmallString<128> InitialDirectory;
205 std::error_code EC = llvm::sys::fs::current_path(InitialDirectory);
206 assert(!EC);
207 (void)EC;
Haojian Wu357ef992016-09-21 13:18:19 +0000208 auto Factory = llvm::make_unique<clang::move::ClangMoveActionFactory>(
Haojian Wu253d5962016-10-06 08:29:32 +0000209 Spec, FileToReplacements, InitialDirectory.str(), "LLVM");
Haojian Wu357ef992016-09-21 13:18:19 +0000210
211 tooling::runToolOnCodeWithArgs(
Haojian Wu2930be12016-11-08 19:55:13 +0000212 Factory->create(), CC, {"-std=c++11", "-fparse-all-comments"},
Haojian Wu9abbeaa2016-10-06 08:59:24 +0000213 TestCCName, "clang-move", std::make_shared<PCHContainerOperations>(),
214 FileToSourceText);
Haojian Wu357ef992016-09-21 13:18:19 +0000215 formatAndApplyAllReplacements(FileToReplacements, Context.Rewrite, "llvm");
216 // The Key is file name, value is the new code after moving the class.
217 std::map<std::string, std::string> Results;
218 for (const auto &It : FileToReplacements) {
219 StringRef FilePath = It.first;
220 Results[FilePath] = Context.getRewrittenText(FileToFileID[FilePath]);
221 }
222 return Results;
223}
224
225TEST(ClangMove, MoveHeaderAndCC) {
226 move::ClangMoveTool::MoveDefinitionSpec Spec;
NAKAMURA Takumi0cfbbae2016-10-17 05:09:58 +0000227 Spec.Names = {std::string("a::b::Foo")};
Haojian Wu357ef992016-09-21 13:18:19 +0000228 Spec.OldHeader = "foo.h";
229 Spec.OldCC = "foo.cc";
230 Spec.NewHeader = "new_foo.h";
231 Spec.NewCC = "new_foo.cc";
Haojian Wu9abbeaa2016-10-06 08:59:24 +0000232 std::string ExpectedHeader = "#include \"" + Spec.NewHeader + "\"\n\n";
Haojian Wu357ef992016-09-21 13:18:19 +0000233 auto Results = runClangMoveOnCode(Spec);
234 EXPECT_EQ(ExpectedTestHeader, Results[Spec.OldHeader]);
235 EXPECT_EQ(ExpectedTestCC, Results[Spec.OldCC]);
236 EXPECT_EQ(ExpectedNewHeader, Results[Spec.NewHeader]);
Haojian Wudaf4cb82016-09-23 13:28:38 +0000237 EXPECT_EQ(ExpectedHeader + ExpectedNewCC, Results[Spec.NewCC]);
Haojian Wu357ef992016-09-21 13:18:19 +0000238}
239
240TEST(ClangMove, MoveHeaderOnly) {
241 move::ClangMoveTool::MoveDefinitionSpec Spec;
NAKAMURA Takumi0cfbbae2016-10-17 05:09:58 +0000242 Spec.Names = {std::string("a::b::Foo")};
Haojian Wu357ef992016-09-21 13:18:19 +0000243 Spec.OldHeader = "foo.h";
244 Spec.NewHeader = "new_foo.h";
245 auto Results = runClangMoveOnCode(Spec);
Haojian Wu62ba4462016-09-21 15:19:04 +0000246 EXPECT_EQ(2u, Results.size());
Haojian Wu357ef992016-09-21 13:18:19 +0000247 EXPECT_EQ(ExpectedTestHeader, Results[Spec.OldHeader]);
248 EXPECT_EQ(ExpectedNewHeader, Results[Spec.NewHeader]);
249}
250
251TEST(ClangMove, MoveCCOnly) {
252 move::ClangMoveTool::MoveDefinitionSpec Spec;
NAKAMURA Takumi0cfbbae2016-10-17 05:09:58 +0000253 Spec.Names = {std::string("a::b::Foo")};
Haojian Wu357ef992016-09-21 13:18:19 +0000254 Spec.OldCC = "foo.cc";
255 Spec.NewCC = "new_foo.cc";
Haojian Wu9abbeaa2016-10-06 08:59:24 +0000256 std::string ExpectedHeader = "#include \"foo.h\"\n\n";
Haojian Wu357ef992016-09-21 13:18:19 +0000257 auto Results = runClangMoveOnCode(Spec);
Haojian Wu62ba4462016-09-21 15:19:04 +0000258 EXPECT_EQ(2u, Results.size());
Haojian Wu357ef992016-09-21 13:18:19 +0000259 EXPECT_EQ(ExpectedTestCC, Results[Spec.OldCC]);
Haojian Wudaf4cb82016-09-23 13:28:38 +0000260 EXPECT_EQ(ExpectedHeader + ExpectedNewCC, Results[Spec.NewCC]);
Haojian Wu357ef992016-09-21 13:18:19 +0000261}
262
263TEST(ClangMove, MoveNonExistClass) {
264 move::ClangMoveTool::MoveDefinitionSpec Spec;
NAKAMURA Takumi0cfbbae2016-10-17 05:09:58 +0000265 Spec.Names = {std::string("NonExistFoo")};
Haojian Wu357ef992016-09-21 13:18:19 +0000266 Spec.OldHeader = "foo.h";
267 Spec.OldCC = "foo.cc";
268 Spec.NewHeader = "new_foo.h";
269 Spec.NewCC = "new_foo.cc";
270 auto Results = runClangMoveOnCode(Spec);
Haojian Wu62ba4462016-09-21 15:19:04 +0000271 EXPECT_EQ(0u, Results.size());
Haojian Wu357ef992016-09-21 13:18:19 +0000272}
273
Haojian Wu2930be12016-11-08 19:55:13 +0000274TEST(ClangMove, MoveAll) {
275 std::vector<std::string> TestHeaders = {
276 "class A {\npublic:\n int f();\n};",
277 // forward declaration.
278 "class B;\nclass A {\npublic:\n int f();\n};",
279 // template forward declaration.
280 "template <typename T> class B;\nclass A {\npublic:\n int f();\n};",
281 "namespace a {}\nclass A {\npublic:\n int f();\n};",
282 "namespace a {}\nusing namespace a;\nclass A {\npublic:\n int f();\n};",
283 };
284 const char Code[] = "#include \"foo.h\"\nint A::f() { return 0; }";
285 move::ClangMoveTool::MoveDefinitionSpec Spec;
286 Spec.Names.push_back("A");
287 Spec.OldHeader = "foo.h";
288 Spec.OldCC = "foo.cc";
289 Spec.NewHeader = "new_foo.h";
290 Spec.NewCC = "new_foo.cc";
291 for (const auto& Header : TestHeaders) {
292 auto Results = runClangMoveOnCode(Spec, Header.c_str(), Code);
293 EXPECT_EQ(Header, Results[Spec.NewHeader]);
294 EXPECT_EQ("", Results[Spec.OldHeader]);
295 EXPECT_EQ("", Results[Spec.OldCC]);
296 }
297}
298
299TEST(ClangMove, MoveAllMultipleClasses) {
300 move::ClangMoveTool::MoveDefinitionSpec Spec;
301 std::vector<std::string> TestHeaders = {
302 "class C;\nclass A {\npublic:\n int f();\n};\nclass B {};",
303 "class C;\nclass B;\nclass A {\npublic:\n int f();\n};\nclass B {};",
304 };
305 const char Code[] = "#include \"foo.h\"\nint A::f() { return 0; }";
306 Spec.Names = {std::string("A"), std::string("B")};
307 Spec.OldHeader = "foo.h";
308 Spec.OldCC = "foo.cc";
309 Spec.NewHeader = "new_foo.h";
310 Spec.NewCC = "new_foo.cc";
311 for (const auto& Header : TestHeaders) {
312 auto Results = runClangMoveOnCode(Spec, Header.c_str(), Code);
313 EXPECT_EQ(Header, Results[Spec.NewHeader]);
314 EXPECT_EQ("", Results[Spec.OldHeader]);
315 EXPECT_EQ("", Results[Spec.OldCC]);
316 }
317}
318
319TEST(ClangMove, DontMoveAll) {
320 const char ExpectedHeader[] = "#ifndef NEW_FOO_H\n"
321 "#define NEW_FOO_H\n"
Haojian Wu53315a72016-11-15 09:06:59 +0000322 "\n"
Haojian Wu2930be12016-11-08 19:55:13 +0000323 "class A {\npublic:\n int f();\n};\n"
Haojian Wu53315a72016-11-15 09:06:59 +0000324 "\n"
Haojian Wu2930be12016-11-08 19:55:13 +0000325 "#endif // NEW_FOO_H\n";
326 const char Code[] = "#include \"foo.h\"\nint A::f() { return 0; }";
327 std::vector<std::string> TestHeaders = {
Haojian Wu53315a72016-11-15 09:06:59 +0000328 "typedef int Int;\nclass A {\npublic:\n int f();\n};\n",
329 "using Int=int;\nclass A {\npublic:\n int f();\n};\n",
330 "class B {};\nclass A {\npublic:\n int f();\n};\n",
331 "void f() {};\nclass A {\npublic:\n int f();\n};\n",
332 "enum Color { RED };\nclass A {\npublic:\n int f();\n};\n",
Haojian Wu2930be12016-11-08 19:55:13 +0000333 };
334 move::ClangMoveTool::MoveDefinitionSpec Spec;
335 Spec.Names.push_back("A");
336 Spec.OldHeader = "foo.h";
337 Spec.OldCC = "foo.cc";
338 Spec.NewHeader = "new_foo.h";
339 Spec.NewCC = "new_foo.cc";
340 for (const auto& Header : TestHeaders) {
341 auto Results = runClangMoveOnCode(Spec, Header.c_str(), Code);
342 EXPECT_EQ(ExpectedHeader, Results[Spec.NewHeader]);
343 // The expected old header should not contain class A definition.
Haojian Wu53315a72016-11-15 09:06:59 +0000344 std::string ExpectedOldHeader = Header.substr(0, Header.size() - 32);
Haojian Wu2930be12016-11-08 19:55:13 +0000345 EXPECT_EQ(ExpectedOldHeader, Results[Spec.OldHeader]);
346 }
347}
348
Haojian Wu24675392016-11-14 14:46:48 +0000349TEST(ClangMove, MacroInFunction) {
350 const char TestHeader[] = "#define INT int\n"
351 "class A {\npublic:\n int f();\n};\n"
352 "class B {};\n";
353 const char TestCode[] = "#include \"foo.h\"\n"
354 "INT A::f() { return 0; }\n";
355 const char ExpectedNewCode[] = "#include \"new_foo.h\"\n\n"
356 "INT A::f() { return 0; }\n";
357 move::ClangMoveTool::MoveDefinitionSpec Spec;
358 Spec.Names.push_back("A");
359 Spec.OldHeader = "foo.h";
360 Spec.OldCC = "foo.cc";
361 Spec.NewHeader = "new_foo.h";
362 Spec.NewCC = "new_foo.cc";
363 auto Results = runClangMoveOnCode(Spec, TestHeader, TestCode);
364 EXPECT_EQ(ExpectedNewCode, Results[Spec.NewCC]);
365}
366
Haojian Wu53315a72016-11-15 09:06:59 +0000367TEST(ClangMove, WellFormattedCode) {
368 const std::string CommonHeader =
369 "namespace a {\n"
370 "namespace b {\n"
371 "namespace c {\n"
372 "class C;\n"
373 "\n"
374 "class A {\npublic:\n void f();\n void f2();\n};\n"
375 "} // namespace c\n"
376 "} // namespace b\n"
377 "\n"
378 "namespace d {\n"
379 "namespace e {\n"
380 "class B {\npublic:\n void f();\n};\n"
381 "} // namespace e\n"
382 "} // namespace d\n"
383 "} // namespace a\n";
384 const std::string CommonCode = "\n"
385 "namespace a {\n"
386 "namespace b {\n"
387 "namespace c {\n"
388 "void A::f() {}\n"
389 "\n"
390 "void A::f2() {}\n"
391 "} // namespace c\n"
392 "} // namespace b\n"
393 "\n"
394 "namespace d {\n"
395 "namespace e {\n"
396 "void B::f() {}\n"
397 "} // namespace e\n"
398 "} // namespace d\n"
399 "} // namespace a\n";
400 // Add dummy class to prevent behavior of moving all declarations from header.
401 const std::string TestHeader = CommonHeader + "class D {};\n";
402 const std::string TestCode = "#include \"foo.h\"\n" + CommonCode;
403 const std::string ExpectedNewHeader = "#ifndef NEW_FOO_H\n"
404 "#define NEW_FOO_H\n"
405 "\n" +
406 CommonHeader +
407 "\n"
408 "#endif // NEW_FOO_H\n";
409 const std::string ExpectedNewCC = "#include \"new_foo.h\"\n" + CommonCode;
410 move::ClangMoveTool::MoveDefinitionSpec Spec;
411 Spec.Names.push_back("a::b::c::A");
412 Spec.Names.push_back("a::d::e::B");
413 Spec.OldHeader = "foo.h";
414 Spec.OldCC = "foo.cc";
415 Spec.NewHeader = "new_foo.h";
416 Spec.NewCC = "new_foo.cc";
417 auto Results = runClangMoveOnCode(Spec, TestHeader.c_str(), TestCode.c_str());
418 EXPECT_EQ(ExpectedNewCC, Results[Spec.NewCC]);
419 EXPECT_EQ(ExpectedNewHeader, Results[Spec.NewHeader]);
420}
421
Haojian Wu48ac3042016-11-23 10:04:19 +0000422TEST(ClangMove, AddDependentNewHeader) {
423 const char TestHeader[] = "class A {};\n"
424 "class B {};\n";
425 const char TestCode[] = "#include \"foo.h\"\n";
426 const char ExpectedOldHeader[] = "#include \"new_foo.h\"\nclass B {};\n";
427 const char ExpectedNewHeader[] = "#ifndef NEW_FOO_H\n"
428 "#define NEW_FOO_H\n"
429 "\n"
430 "class A {};\n"
431 "\n"
432 "#endif // NEW_FOO_H\n";
433 move::ClangMoveTool::MoveDefinitionSpec Spec;
434 Spec.Names.push_back("A");
435 Spec.OldHeader = "foo.h";
436 Spec.OldCC = "foo.cc";
437 Spec.NewHeader = "new_foo.h";
438 Spec.NewCC = "new_foo.cc";
439 Spec.OldDependOnNew = true;
440 auto Results = runClangMoveOnCode(Spec, TestHeader, TestCode);
441 EXPECT_EQ(ExpectedOldHeader, Results[Spec.OldHeader]);
442 EXPECT_EQ(ExpectedNewHeader, Results[Spec.NewHeader]);
443}
444
445TEST(ClangMove, AddDependentOldHeader) {
446 const char TestHeader[] = "class A {};\n"
447 "class B {};\n";
448 const char TestCode[] = "#include \"foo.h\"\n";
449 const char ExpectedNewHeader[] = "#ifndef NEW_FOO_H\n"
450 "#define NEW_FOO_H\n"
451 "\n"
452 "#include \"foo.h\"\n"
453 "\n"
454 "class B {};\n"
455 "\n"
456 "#endif // NEW_FOO_H\n";
457 const char ExpectedOldHeader[] = "class A {};\n";
458 move::ClangMoveTool::MoveDefinitionSpec Spec;
459 Spec.Names.push_back("B");
460 Spec.OldHeader = "foo.h";
461 Spec.OldCC = "foo.cc";
462 Spec.NewHeader = "new_foo.h";
463 Spec.NewCC = "new_foo.cc";
464 Spec.NewDependOnOld = true;
465 auto Results = runClangMoveOnCode(Spec, TestHeader, TestCode);
466 EXPECT_EQ(ExpectedNewHeader, Results[Spec.NewHeader]);
467 EXPECT_EQ(ExpectedOldHeader, Results[Spec.OldHeader]);
468}
469
Haojian Wu357ef992016-09-21 13:18:19 +0000470} // namespace
471} // namespce move
472} // namespace clang