1 //===- unittest/Format/SortIncludesTest.cpp - Include sort unit 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 "FormatTestUtils.h"
10 #include "clang/Format/Format.h"
11 #include "llvm/ADT/None.h"
12 #include "llvm/Support/Debug.h"
13 #include "gtest/gtest.h"
14 
15 #define DEBUG_TYPE "format-test"
16 
17 namespace clang {
18 namespace format {
19 namespace {
20 
21 class SortIncludesTest : public ::testing::Test {
22 protected:
23   std::vector<tooling::Range> GetCodeRange(StringRef Code) {
24     return std::vector<tooling::Range>(1, tooling::Range(0, Code.size()));
25   }
26 
27   std::string sort(StringRef Code, std::vector<tooling::Range> Ranges,
28                    StringRef FileName = "input.cc",
29                    unsigned ExpectedNumRanges = 1) {
30     auto Replaces = sortIncludes(FmtStyle, Code, Ranges, FileName);
31     Ranges = tooling::calculateRangesAfterReplacements(Replaces, Ranges);
32     EXPECT_EQ(ExpectedNumRanges, Replaces.size());
33     auto Sorted = applyAllReplacements(Code, Replaces);
34     EXPECT_TRUE(static_cast<bool>(Sorted));
35     auto Result = applyAllReplacements(
36         *Sorted, reformat(FmtStyle, *Sorted, Ranges, FileName));
37     EXPECT_TRUE(static_cast<bool>(Result));
38     return *Result;
39   }
40 
41   std::string sort(StringRef Code,
42                    StringRef FileName = "input.cpp",
43                    unsigned ExpectedNumRanges = 1) {
44     return sort(Code, GetCodeRange(Code), FileName, ExpectedNumRanges);
45   }
46 
47   unsigned newCursor(llvm::StringRef Code, unsigned Cursor) {
48     sortIncludes(FmtStyle, Code, GetCodeRange(Code), "input.cpp", &Cursor);
49     return Cursor;
50   }
51 
52   FormatStyle FmtStyle = getLLVMStyle();
53   tooling::IncludeStyle &Style = FmtStyle.IncludeStyle;
54 };
55 
56 TEST_F(SortIncludesTest, BasicSorting) {
57   EXPECT_EQ("#include \"a.h\"\n"
58             "#include \"b.h\"\n"
59             "#include \"c.h\"\n",
60             sort("#include \"a.h\"\n"
61                  "#include \"c.h\"\n"
62                  "#include \"b.h\"\n"));
63 
64   EXPECT_EQ("// comment\n"
65             "#include <a>\n"
66             "#include <b>\n",
67             sort("// comment\n"
68                  "#include <b>\n"
69                  "#include <a>\n",
70                  {tooling::Range(25, 1)}));
71 }
72 
73 TEST_F(SortIncludesTest, SortedIncludesUsingSortPriorityAttribute) {
74   FmtStyle.IncludeStyle.IncludeBlocks = tooling::IncludeStyle::IBS_Regroup;
75   FmtStyle.IncludeStyle.IncludeCategories = {
76       {"^<sys/param\\.h>", 1, 0},
77       {"^<sys/types\\.h>", 1, 1},
78       {"^<sys.*/", 1, 2},
79       {"^<uvm/", 2, 3},
80       {"^<machine/", 3, 4},
81       {"^<dev/", 4, 5},
82       {"^<net.*/", 5, 6},
83       {"^<protocols/", 5, 7},
84       {"^<(fs|miscfs|msdosfs|nfs|ntfs|ufs)/", 6, 8},
85       {"^<(x86|amd64|i386|xen)/", 7, 8},
86       {"<path", 9, 11},
87       {"^<[^/].*\\.h>", 8, 10},
88       {"^\".*\\.h\"", 10, 12}};
89   EXPECT_EQ("#include <sys/param.h>\n"
90             "#include <sys/types.h>\n"
91             "#include <sys/ioctl.h>\n"
92             "#include <sys/socket.h>\n"
93             "#include <sys/stat.h>\n"
94             "#include <sys/wait.h>\n"
95             "\n"
96             "#include <net/if.h>\n"
97             "#include <net/if_dl.h>\n"
98             "#include <net/route.h>\n"
99             "#include <netinet/in.h>\n"
100             "#include <protocols/rwhod.h>\n"
101             "\n"
102             "#include <assert.h>\n"
103             "#include <errno.h>\n"
104             "#include <inttypes.h>\n"
105             "#include <stdio.h>\n"
106             "#include <stdlib.h>\n"
107             "\n"
108             "#include <paths.h>\n"
109             "\n"
110             "#include \"pathnames.h\"\n",
111             sort("#include <sys/param.h>\n"
112                  "#include <sys/types.h>\n"
113                  "#include <sys/ioctl.h>\n"
114                  "#include <net/if_dl.h>\n"
115                  "#include <net/route.h>\n"
116                  "#include <netinet/in.h>\n"
117                  "#include <sys/socket.h>\n"
118                  "#include <sys/stat.h>\n"
119                  "#include <sys/wait.h>\n"
120                  "#include <net/if.h>\n"
121                  "#include <protocols/rwhod.h>\n"
122                  "#include <assert.h>\n"
123                  "#include <paths.h>\n"
124                  "#include \"pathnames.h\"\n"
125                  "#include <errno.h>\n"
126                  "#include <inttypes.h>\n"
127                  "#include <stdio.h>\n"
128                  "#include <stdlib.h>\n"));
129 }
130 TEST_F(SortIncludesTest, SortPriorityNotDefined) {
131   FmtStyle = getLLVMStyle();
132   EXPECT_EQ("#include \"FormatTestUtils.h\"\n"
133             "#include \"clang/Format/Format.h\"\n"
134             "#include \"llvm/ADT/None.h\"\n"
135             "#include \"llvm/Support/Debug.h\"\n"
136             "#include \"gtest/gtest.h\"\n",
137             sort("#include \"clang/Format/Format.h\"\n"
138                  "#include \"llvm/ADT/None.h\"\n"
139                  "#include \"FormatTestUtils.h\"\n"
140                  "#include \"gtest/gtest.h\"\n"
141                  "#include \"llvm/Support/Debug.h\"\n"));
142 }
143 
144 TEST_F(SortIncludesTest, NoReplacementsForValidIncludes) {
145   // Identical #includes have led to a failure with an unstable sort.
146   std::string Code = "#include <a>\n"
147                      "#include <b>\n"
148                      "#include <c>\n"
149                      "#include <d>\n"
150                      "#include <e>\n"
151                      "#include <f>\n";
152   EXPECT_TRUE(sortIncludes(FmtStyle, Code, GetCodeRange(Code), "a.cc").empty());
153 }
154 
155 TEST_F(SortIncludesTest, SortedIncludesInMultipleBlocksAreMerged) {
156   Style.IncludeBlocks = tooling::IncludeStyle::IBS_Merge;
157   EXPECT_EQ("#include \"a.h\"\n"
158             "#include \"b.h\"\n"
159             "#include \"c.h\"\n",
160             sort("#include \"a.h\"\n"
161                  "#include \"c.h\"\n"
162                  "\n"
163                  "\n"
164                  "#include \"b.h\"\n"));
165 
166   Style.IncludeBlocks = tooling::IncludeStyle::IBS_Regroup;
167   EXPECT_EQ("#include \"a.h\"\n"
168             "#include \"b.h\"\n"
169             "#include \"c.h\"\n",
170             sort("#include \"a.h\"\n"
171                  "#include \"c.h\"\n"
172                  "\n"
173                  "\n"
174                  "#include \"b.h\"\n"));
175 }
176 
177 TEST_F(SortIncludesTest, SupportClangFormatOff) {
178   EXPECT_EQ("#include <a>\n"
179             "#include <b>\n"
180             "#include <c>\n"
181             "// clang-format off\n"
182             "#include <b>\n"
183             "#include <a>\n"
184             "#include <c>\n"
185             "// clang-format on\n",
186             sort("#include <b>\n"
187                  "#include <a>\n"
188                  "#include <c>\n"
189                  "// clang-format off\n"
190                  "#include <b>\n"
191                  "#include <a>\n"
192                  "#include <c>\n"
193                  "// clang-format on\n"));
194 }
195 
196 TEST_F(SortIncludesTest, SupportClangFormatOffCStyle) {
197   EXPECT_EQ("#include <a>\n"
198             "#include <b>\n"
199             "#include <c>\n"
200             "/* clang-format off */\n"
201             "#include <b>\n"
202             "#include <a>\n"
203             "#include <c>\n"
204             "/* clang-format on */\n",
205             sort("#include <b>\n"
206                  "#include <a>\n"
207                  "#include <c>\n"
208                  "/* clang-format off */\n"
209                  "#include <b>\n"
210                  "#include <a>\n"
211                  "#include <c>\n"
212                  "/* clang-format on */\n"));
213 
214   // Not really turning it off
215   EXPECT_EQ("#include <a>\n"
216             "#include <b>\n"
217             "#include <c>\n"
218             "/* clang-format offically */\n"
219             "#include <a>\n"
220             "#include <b>\n"
221             "#include <c>\n"
222             "/* clang-format onwards */\n",
223             sort("#include <b>\n"
224                  "#include <a>\n"
225                  "#include <c>\n"
226                  "/* clang-format offically */\n"
227                  "#include <b>\n"
228                  "#include <a>\n"
229                  "#include <c>\n"
230                  "/* clang-format onwards */\n", "input.h", 2));
231 }
232 
233 TEST_F(SortIncludesTest, IncludeSortingCanBeDisabled) {
234   FmtStyle.SortIncludes = false;
235   EXPECT_EQ("#include \"a.h\"\n"
236             "#include \"c.h\"\n"
237             "#include \"b.h\"\n",
238             sort("#include \"a.h\"\n"
239                  "#include \"c.h\"\n"
240                  "#include \"b.h\"\n",
241                  "input.h", 0));
242 }
243 
244 TEST_F(SortIncludesTest, MixIncludeAndImport) {
245   EXPECT_EQ("#include \"a.h\"\n"
246             "#import \"b.h\"\n"
247             "#include \"c.h\"\n",
248             sort("#include \"a.h\"\n"
249                  "#include \"c.h\"\n"
250                  "#import \"b.h\"\n"));
251 }
252 
253 TEST_F(SortIncludesTest, FixTrailingComments) {
254   EXPECT_EQ("#include \"a.h\"  // comment\n"
255             "#include \"bb.h\" // comment\n"
256             "#include \"ccc.h\"\n",
257             sort("#include \"a.h\" // comment\n"
258                  "#include \"ccc.h\"\n"
259                  "#include \"bb.h\" // comment\n"));
260 }
261 
262 TEST_F(SortIncludesTest, LeadingWhitespace) {
263   EXPECT_EQ("#include \"a.h\"\n"
264             "#include \"b.h\"\n"
265             "#include \"c.h\"\n",
266             sort(" #include \"a.h\"\n"
267                  "  #include \"c.h\"\n"
268                  "   #include \"b.h\"\n"));
269   EXPECT_EQ("#include \"a.h\"\n"
270             "#include \"b.h\"\n"
271             "#include \"c.h\"\n",
272             sort("# include \"a.h\"\n"
273                  "#  include \"c.h\"\n"
274                  "#   include \"b.h\"\n"));
275 }
276 
277 TEST_F(SortIncludesTest, GreaterInComment) {
278   EXPECT_EQ("#include \"a.h\"\n"
279             "#include \"b.h\" // >\n"
280             "#include \"c.h\"\n",
281             sort("#include \"a.h\"\n"
282                  "#include \"c.h\"\n"
283                  "#include \"b.h\" // >\n"));
284 }
285 
286 TEST_F(SortIncludesTest, SortsLocallyInEachBlock) {
287   EXPECT_EQ("#include \"a.h\"\n"
288             "#include \"c.h\"\n"
289             "\n"
290             "#include \"b.h\"\n",
291             sort("#include \"a.h\"\n"
292                  "#include \"c.h\"\n"
293                  "\n"
294                  "#include \"b.h\"\n", "input.h", 0));
295 }
296 
297 TEST_F(SortIncludesTest, SortsAllBlocksWhenMerging) {
298   Style.IncludeBlocks = tooling::IncludeStyle::IBS_Merge;
299   EXPECT_EQ("#include \"a.h\"\n"
300             "#include \"b.h\"\n"
301             "#include \"c.h\"\n",
302             sort("#include \"a.h\"\n"
303                  "#include \"c.h\"\n"
304                  "\n"
305                  "#include \"b.h\"\n"));
306 }
307 
308 TEST_F(SortIncludesTest, CommentsAlwaysSeparateGroups) {
309   EXPECT_EQ("#include \"a.h\"\n"
310             "#include \"c.h\"\n"
311             "// comment\n"
312             "#include \"b.h\"\n",
313             sort("#include \"c.h\"\n"
314                  "#include \"a.h\"\n"
315                  "// comment\n"
316                  "#include \"b.h\"\n"));
317 
318   Style.IncludeBlocks = tooling::IncludeStyle::IBS_Merge;
319   EXPECT_EQ("#include \"a.h\"\n"
320             "#include \"c.h\"\n"
321             "// comment\n"
322             "#include \"b.h\"\n",
323             sort("#include \"c.h\"\n"
324                  "#include \"a.h\"\n"
325                  "// comment\n"
326                  "#include \"b.h\"\n"));
327 
328   Style.IncludeBlocks = tooling::IncludeStyle::IBS_Regroup;
329   EXPECT_EQ("#include \"a.h\"\n"
330             "#include \"c.h\"\n"
331             "// comment\n"
332             "#include \"b.h\"\n",
333             sort("#include \"c.h\"\n"
334                  "#include \"a.h\"\n"
335                  "// comment\n"
336                  "#include \"b.h\"\n"));
337 }
338 
339 TEST_F(SortIncludesTest, HandlesAngledIncludesAsSeparateBlocks) {
340   EXPECT_EQ("#include \"a.h\"\n"
341             "#include \"c.h\"\n"
342             "#include <array>\n"
343             "#include <b.h>\n"
344             "#include <d.h>\n"
345             "#include <vector>\n",
346             sort("#include <vector>\n"
347                  "#include <d.h>\n"
348                  "#include <array>\n"
349                  "#include <b.h>\n"
350                  "#include \"c.h\"\n"
351                  "#include \"a.h\"\n"));
352 
353   FmtStyle = getGoogleStyle(FormatStyle::LK_Cpp);
354   EXPECT_EQ("#include <b.h>\n"
355             "#include <d.h>\n"
356             "\n"
357             "#include <array>\n"
358             "#include <vector>\n"
359             "\n"
360             "#include \"a.h\"\n"
361             "#include \"c.h\"\n",
362             sort("#include <vector>\n"
363                  "#include <d.h>\n"
364                  "#include <array>\n"
365                  "#include <b.h>\n"
366                  "#include \"c.h\"\n"
367                  "#include \"a.h\"\n"));
368 }
369 
370 TEST_F(SortIncludesTest, RegroupsAngledIncludesInSeparateBlocks) {
371   Style.IncludeBlocks = tooling::IncludeStyle::IBS_Regroup;
372   EXPECT_EQ("#include \"a.h\"\n"
373             "#include \"c.h\"\n"
374             "\n"
375             "#include <b.h>\n"
376             "#include <d.h>\n",
377             sort("#include <d.h>\n"
378                  "#include <b.h>\n"
379                  "#include \"c.h\"\n"
380                  "#include \"a.h\"\n"));
381 }
382 
383 TEST_F(SortIncludesTest, HandlesMultilineIncludes) {
384   EXPECT_EQ("#include \"a.h\"\n"
385             "#include \"b.h\"\n"
386             "#include \"c.h\"\n",
387             sort("#include \"a.h\"\n"
388                  "#include \\\n"
389                  "\"c.h\"\n"
390                  "#include \"b.h\"\n"));
391 }
392 
393 TEST_F(SortIncludesTest, LeavesMainHeaderFirst) {
394   Style.IncludeIsMainRegex = "([-_](test|unittest))?$";
395   EXPECT_EQ("#include \"llvm/a.h\"\n"
396             "#include \"b.h\"\n"
397             "#include \"c.h\"\n",
398             sort("#include \"llvm/a.h\"\n"
399                  "#include \"c.h\"\n"
400                  "#include \"b.h\"\n",
401                  "a.cc"));
402   EXPECT_EQ("#include \"llvm/a.h\"\n"
403             "#include \"b.h\"\n"
404             "#include \"c.h\"\n",
405             sort("#include \"llvm/a.h\"\n"
406                  "#include \"c.h\"\n"
407                  "#include \"b.h\"\n",
408                  "a_test.cc"));
409   EXPECT_EQ("#include \"llvm/input.h\"\n"
410             "#include \"b.h\"\n"
411             "#include \"c.h\"\n",
412             sort("#include \"llvm/input.h\"\n"
413                  "#include \"c.h\"\n"
414                  "#include \"b.h\"\n",
415                  "input.mm"));
416 
417   // Don't allow prefixes.
418   EXPECT_EQ("#include \"b.h\"\n"
419             "#include \"c.h\"\n"
420             "#include \"llvm/not_a.h\"\n",
421             sort("#include \"llvm/not_a.h\"\n"
422                  "#include \"c.h\"\n"
423                  "#include \"b.h\"\n",
424                  "a.cc"));
425 
426   // Don't do this for _main and other suffixes.
427   EXPECT_EQ("#include \"b.h\"\n"
428             "#include \"c.h\"\n"
429             "#include \"llvm/a.h\"\n",
430             sort("#include \"llvm/a.h\"\n"
431                  "#include \"c.h\"\n"
432                  "#include \"b.h\"\n",
433                  "a_main.cc"));
434 
435   // Don't do this in headers.
436   EXPECT_EQ("#include \"b.h\"\n"
437             "#include \"c.h\"\n"
438             "#include \"llvm/a.h\"\n",
439             sort("#include \"llvm/a.h\"\n"
440                  "#include \"c.h\"\n"
441                  "#include \"b.h\"\n",
442                  "a.h"));
443 
444   // Only do this in the first #include block.
445   EXPECT_EQ("#include <a>\n"
446             "\n"
447             "#include \"b.h\"\n"
448             "#include \"c.h\"\n"
449             "#include \"llvm/a.h\"\n",
450             sort("#include <a>\n"
451                  "\n"
452                  "#include \"llvm/a.h\"\n"
453                  "#include \"c.h\"\n"
454                  "#include \"b.h\"\n",
455                  "a.cc"));
456 
457   // Only recognize the first #include with a matching basename as main include.
458   EXPECT_EQ("#include \"a.h\"\n"
459             "#include \"b.h\"\n"
460             "#include \"c.h\"\n"
461             "#include \"llvm/a.h\"\n",
462             sort("#include \"b.h\"\n"
463                  "#include \"a.h\"\n"
464                  "#include \"c.h\"\n"
465                  "#include \"llvm/a.h\"\n",
466                  "a.cc"));
467 }
468 
469 TEST_F(SortIncludesTest, RecognizeMainHeaderInAllGroups) {
470   Style.IncludeIsMainRegex = "([-_](test|unittest))?$";
471   Style.IncludeBlocks = tooling::IncludeStyle::IBS_Merge;
472 
473   EXPECT_EQ("#include \"c.h\"\n"
474             "#include \"a.h\"\n"
475             "#include \"b.h\"\n",
476             sort("#include \"b.h\"\n"
477                  "\n"
478                  "#include \"a.h\"\n"
479                  "#include \"c.h\"\n",
480                  "c.cc"));
481 }
482 
483 TEST_F(SortIncludesTest, MainHeaderIsSeparatedWhenRegroupping) {
484   Style.IncludeIsMainRegex = "([-_](test|unittest))?$";
485   Style.IncludeBlocks = tooling::IncludeStyle::IBS_Regroup;
486 
487   EXPECT_EQ("#include \"a.h\"\n"
488             "\n"
489             "#include \"b.h\"\n"
490             "#include \"c.h\"\n",
491             sort("#include \"b.h\"\n"
492                  "\n"
493                  "#include \"a.h\"\n"
494                  "#include \"c.h\"\n",
495                  "a.cc"));
496 }
497 
498 TEST_F(SortIncludesTest, SupportCaseInsensitiveMatching) {
499   // Setup an regex for main includes so we can cover those as well.
500   Style.IncludeIsMainRegex = "([-_](test|unittest))?$";
501 
502   // Ensure both main header detection and grouping work in a case insensitive
503   // manner.
504   EXPECT_EQ("#include \"llvm/A.h\"\n"
505             "#include \"b.h\"\n"
506             "#include \"c.h\"\n"
507             "#include \"LLVM/z.h\"\n"
508             "#include \"llvm/X.h\"\n"
509             "#include \"GTest/GTest.h\"\n"
510             "#include \"gmock/gmock.h\"\n",
511             sort("#include \"c.h\"\n"
512                  "#include \"b.h\"\n"
513                  "#include \"GTest/GTest.h\"\n"
514                  "#include \"llvm/A.h\"\n"
515                  "#include \"gmock/gmock.h\"\n"
516                  "#include \"llvm/X.h\"\n"
517                  "#include \"LLVM/z.h\"\n",
518                  "a_TEST.cc"));
519 }
520 
521 TEST_F(SortIncludesTest, NegativePriorities) {
522   Style.IncludeCategories = {{".*important_os_header.*", -1, 0}, {".*", 1, 0}};
523   EXPECT_EQ("#include \"important_os_header.h\"\n"
524             "#include \"c_main.h\"\n"
525             "#include \"a_other.h\"\n",
526             sort("#include \"c_main.h\"\n"
527                  "#include \"a_other.h\"\n"
528                  "#include \"important_os_header.h\"\n",
529                  "c_main.cc"));
530 
531   // check stable when re-run
532   EXPECT_EQ("#include \"important_os_header.h\"\n"
533             "#include \"c_main.h\"\n"
534             "#include \"a_other.h\"\n",
535             sort("#include \"important_os_header.h\"\n"
536                  "#include \"c_main.h\"\n"
537                  "#include \"a_other.h\"\n",
538                  "c_main.cc", 0));
539 }
540 
541 TEST_F(SortIncludesTest, PriorityGroupsAreSeparatedWhenRegroupping) {
542   Style.IncludeCategories = {{".*important_os_header.*", -1, 0}, {".*", 1, 0}};
543   Style.IncludeBlocks = tooling::IncludeStyle::IBS_Regroup;
544 
545   EXPECT_EQ("#include \"important_os_header.h\"\n"
546             "\n"
547             "#include \"c_main.h\"\n"
548             "\n"
549             "#include \"a_other.h\"\n",
550             sort("#include \"c_main.h\"\n"
551                  "#include \"a_other.h\"\n"
552                  "#include \"important_os_header.h\"\n",
553                  "c_main.cc"));
554 
555   // check stable when re-run
556   EXPECT_EQ("#include \"important_os_header.h\"\n"
557             "\n"
558             "#include \"c_main.h\"\n"
559             "\n"
560             "#include \"a_other.h\"\n",
561             sort("#include \"important_os_header.h\"\n"
562                  "\n"
563                  "#include \"c_main.h\"\n"
564                  "\n"
565                  "#include \"a_other.h\"\n",
566                  "c_main.cc", 0));
567 }
568 
569 TEST_F(SortIncludesTest, CalculatesCorrectCursorPosition) {
570   std::string Code = "#include <ccc>\n"    // Start of line: 0
571                      "#include <bbbbbb>\n" // Start of line: 15
572                      "#include <a>\n";     // Start of line: 33
573   EXPECT_EQ(31u, newCursor(Code, 0));
574   EXPECT_EQ(13u, newCursor(Code, 15));
575   EXPECT_EQ(0u, newCursor(Code, 33));
576 
577   EXPECT_EQ(41u, newCursor(Code, 10));
578   EXPECT_EQ(23u, newCursor(Code, 25));
579   EXPECT_EQ(10u, newCursor(Code, 43));
580 }
581 
582 TEST_F(SortIncludesTest, DeduplicateIncludes) {
583   EXPECT_EQ("#include <a>\n"
584             "#include <b>\n"
585             "#include <c>\n",
586             sort("#include <a>\n"
587                  "#include <b>\n"
588                  "#include <b>\n"
589                  "#include <b>\n"
590                  "#include <b>\n"
591                  "#include <c>\n"));
592 
593   Style.IncludeBlocks = tooling::IncludeStyle::IBS_Merge;
594   EXPECT_EQ("#include <a>\n"
595             "#include <b>\n"
596             "#include <c>\n",
597             sort("#include <a>\n"
598                  "#include <b>\n"
599                  "\n"
600                  "#include <b>\n"
601                  "\n"
602                  "#include <b>\n"
603                  "#include <c>\n"));
604 
605   Style.IncludeBlocks = tooling::IncludeStyle::IBS_Regroup;
606   EXPECT_EQ("#include <a>\n"
607             "#include <b>\n"
608             "#include <c>\n",
609             sort("#include <a>\n"
610                  "#include <b>\n"
611                  "\n"
612                  "#include <b>\n"
613                  "\n"
614                  "#include <b>\n"
615                  "#include <c>\n"));
616 }
617 
618 TEST_F(SortIncludesTest, SortAndDeduplicateIncludes) {
619   EXPECT_EQ("#include <a>\n"
620             "#include <b>\n"
621             "#include <c>\n",
622             sort("#include <b>\n"
623                  "#include <a>\n"
624                  "#include <b>\n"
625                  "#include <b>\n"
626                  "#include <c>\n"
627                  "#include <b>\n"));
628 
629   Style.IncludeBlocks = tooling::IncludeStyle::IBS_Merge;
630   EXPECT_EQ("#include <a>\n"
631             "#include <b>\n"
632             "#include <c>\n",
633             sort("#include <b>\n"
634                  "#include <a>\n"
635                  "\n"
636                  "#include <b>\n"
637                  "\n"
638                  "#include <c>\n"
639                  "#include <b>\n"));
640 
641   Style.IncludeBlocks = tooling::IncludeStyle::IBS_Regroup;
642   EXPECT_EQ("#include <a>\n"
643             "#include <b>\n"
644             "#include <c>\n",
645             sort("#include <b>\n"
646                  "#include <a>\n"
647                  "\n"
648                  "#include <b>\n"
649                  "\n"
650                  "#include <c>\n"
651                  "#include <b>\n"));
652 }
653 
654 TEST_F(SortIncludesTest, CalculatesCorrectCursorPositionAfterDeduplicate) {
655   std::string Code = "#include <b>\n"      // Start of line: 0
656                      "#include <a>\n"      // Start of line: 13
657                      "#include <b>\n"      // Start of line: 26
658                      "#include <b>\n"      // Start of line: 39
659                      "#include <c>\n"      // Start of line: 52
660                      "#include <b>\n";     // Start of line: 65
661   std::string Expected = "#include <a>\n"  // Start of line: 0
662                          "#include <b>\n"  // Start of line: 13
663                          "#include <c>\n"; // Start of line: 26
664   EXPECT_EQ(Expected, sort(Code));
665   // Cursor on 'i' in "#include <a>".
666   EXPECT_EQ(1u, newCursor(Code, 14));
667   // Cursor on 'b' in "#include <b>".
668   EXPECT_EQ(23u, newCursor(Code, 10));
669   EXPECT_EQ(23u, newCursor(Code, 36));
670   EXPECT_EQ(23u, newCursor(Code, 49));
671   EXPECT_EQ(23u, newCursor(Code, 36));
672   EXPECT_EQ(23u, newCursor(Code, 75));
673   // Cursor on '#' in "#include <c>".
674   EXPECT_EQ(26u, newCursor(Code, 52));
675 }
676 
677 TEST_F(SortIncludesTest, DeduplicateLocallyInEachBlock) {
678   EXPECT_EQ("#include <a>\n"
679             "#include <b>\n"
680             "\n"
681             "#include <b>\n"
682             "#include <c>\n",
683             sort("#include <a>\n"
684                  "#include <b>\n"
685                  "\n"
686                  "#include <c>\n"
687                  "#include <b>\n"
688                  "#include <b>\n"));
689 }
690 
691 TEST_F(SortIncludesTest, ValidAffactedRangesAfterDeduplicatingIncludes) {
692   std::string Code = "#include <a>\n"
693                      "#include <b>\n"
694                      "#include <a>\n"
695                      "#include <a>\n"
696                      "\n"
697                      "   int     x ;";
698   std::vector<tooling::Range> Ranges = {tooling::Range(0, 52)};
699   auto Replaces = sortIncludes(FmtStyle, Code, Ranges, "input.cpp");
700   Ranges = tooling::calculateRangesAfterReplacements(Replaces, Ranges);
701   EXPECT_EQ(1u, Ranges.size());
702   EXPECT_EQ(0u, Ranges[0].getOffset());
703   EXPECT_EQ(26u, Ranges[0].getLength());
704 }
705 
706 TEST_F(SortIncludesTest, DoNotSortLikelyXml) {
707   EXPECT_EQ("<!--;\n"
708             "#include <b>\n"
709             "#include <a>\n"
710             "-->",
711             sort("<!--;\n"
712                  "#include <b>\n"
713                  "#include <a>\n"
714                  "-->", "input.h", 0));
715 }
716 
717 TEST_F(SortIncludesTest, DoNotOutputReplacementsForSortedBlocksWithRegrouping) {
718   Style.IncludeBlocks = Style.IBS_Regroup;
719   std::string Code = R"(
720 #include "b.h"
721 
722 #include <a.h>
723 )";
724   EXPECT_EQ(Code, sort(Code, "input.h", 0));
725 }
726 
727 TEST_F(SortIncludesTest,
728        DoNotOutputReplacementsForSortedBlocksWithRegroupingWindows) {
729   Style.IncludeBlocks = Style.IBS_Regroup;
730   std::string Code = "#include \"b.h\"\r\n"
731                      "\r\n"
732                      "#include <a.h>\r\n";
733   EXPECT_EQ(Code, sort(Code, "input.h", 0));
734 }
735 
736 TEST_F(SortIncludesTest, DoNotRegroupGroupsInGoogleObjCStyle) {
737   FmtStyle = getGoogleStyle(FormatStyle::LK_ObjC);
738 
739   EXPECT_EQ("#include <a.h>\n"
740             "#include <b.h>\n"
741             "#include \"a.h\"",
742             sort("#include <b.h>\n"
743                  "#include <a.h>\n"
744                  "#include \"a.h\""));
745 }
746 
747 } // end namespace
748 } // end namespace format
749 } // end namespace clang
750