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