xref: /llvm-project/clang/unittests/Format/SortIncludesTest.cpp (revision 84048e234f8f0d81871caab842dbed84b84aa86f)
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, MainFileHeader) {
155   std::string Code = "#include <string>\n"
156                      "\n"
157                      "#include \"a/extra_action.proto.h\"\n";
158   FmtStyle = getGoogleStyle(FormatStyle::LK_Cpp);
159   EXPECT_TRUE(
160       sortIncludes(FmtStyle, Code, GetCodeRange(Code), "a/extra_action.cc")
161           .empty());
162 
163   EXPECT_EQ("#include \"foo.bar.h\"\n"
164             "\n"
165             "#include \"a.h\"\n",
166             sort("#include \"a.h\"\n"
167                  "#include \"foo.bar.h\"\n",
168                  "foo.bar.cc"));
169 }
170 
171 TEST_F(SortIncludesTest, SortedIncludesInMultipleBlocksAreMerged) {
172   Style.IncludeBlocks = tooling::IncludeStyle::IBS_Merge;
173   EXPECT_EQ("#include \"a.h\"\n"
174             "#include \"b.h\"\n"
175             "#include \"c.h\"\n",
176             sort("#include \"a.h\"\n"
177                  "#include \"c.h\"\n"
178                  "\n"
179                  "\n"
180                  "#include \"b.h\"\n"));
181 
182   Style.IncludeBlocks = tooling::IncludeStyle::IBS_Regroup;
183   EXPECT_EQ("#include \"a.h\"\n"
184             "#include \"b.h\"\n"
185             "#include \"c.h\"\n",
186             sort("#include \"a.h\"\n"
187                  "#include \"c.h\"\n"
188                  "\n"
189                  "\n"
190                  "#include \"b.h\"\n"));
191 }
192 
193 TEST_F(SortIncludesTest, SupportClangFormatOff) {
194   EXPECT_EQ("#include <a>\n"
195             "#include <b>\n"
196             "#include <c>\n"
197             "// clang-format off\n"
198             "#include <b>\n"
199             "#include <a>\n"
200             "#include <c>\n"
201             "// clang-format on\n",
202             sort("#include <b>\n"
203                  "#include <a>\n"
204                  "#include <c>\n"
205                  "// clang-format off\n"
206                  "#include <b>\n"
207                  "#include <a>\n"
208                  "#include <c>\n"
209                  "// clang-format on\n"));
210 }
211 
212 TEST_F(SortIncludesTest, SupportClangFormatOffCStyle) {
213   EXPECT_EQ("#include <a>\n"
214             "#include <b>\n"
215             "#include <c>\n"
216             "/* clang-format off */\n"
217             "#include <b>\n"
218             "#include <a>\n"
219             "#include <c>\n"
220             "/* clang-format on */\n",
221             sort("#include <b>\n"
222                  "#include <a>\n"
223                  "#include <c>\n"
224                  "/* clang-format off */\n"
225                  "#include <b>\n"
226                  "#include <a>\n"
227                  "#include <c>\n"
228                  "/* clang-format on */\n"));
229 
230   // Not really turning it off
231   EXPECT_EQ("#include <a>\n"
232             "#include <b>\n"
233             "#include <c>\n"
234             "/* clang-format offically */\n"
235             "#include <a>\n"
236             "#include <b>\n"
237             "#include <c>\n"
238             "/* clang-format onwards */\n",
239             sort("#include <b>\n"
240                  "#include <a>\n"
241                  "#include <c>\n"
242                  "/* clang-format offically */\n"
243                  "#include <b>\n"
244                  "#include <a>\n"
245                  "#include <c>\n"
246                  "/* clang-format onwards */\n",
247                  "input.h", 2));
248 }
249 
250 TEST_F(SortIncludesTest, IncludeSortingCanBeDisabled) {
251   FmtStyle.SortIncludes = false;
252   EXPECT_EQ("#include \"a.h\"\n"
253             "#include \"c.h\"\n"
254             "#include \"b.h\"\n",
255             sort("#include \"a.h\"\n"
256                  "#include \"c.h\"\n"
257                  "#include \"b.h\"\n",
258                  "input.h", 0));
259 }
260 
261 TEST_F(SortIncludesTest, MixIncludeAndImport) {
262   EXPECT_EQ("#include \"a.h\"\n"
263             "#import \"b.h\"\n"
264             "#include \"c.h\"\n",
265             sort("#include \"a.h\"\n"
266                  "#include \"c.h\"\n"
267                  "#import \"b.h\"\n"));
268 }
269 
270 TEST_F(SortIncludesTest, FixTrailingComments) {
271   EXPECT_EQ("#include \"a.h\"  // comment\n"
272             "#include \"bb.h\" // comment\n"
273             "#include \"ccc.h\"\n",
274             sort("#include \"a.h\" // comment\n"
275                  "#include \"ccc.h\"\n"
276                  "#include \"bb.h\" // comment\n"));
277 }
278 
279 TEST_F(SortIncludesTest, LeadingWhitespace) {
280   EXPECT_EQ("#include \"a.h\"\n"
281             "#include \"b.h\"\n"
282             "#include \"c.h\"\n",
283             sort(" #include \"a.h\"\n"
284                  "  #include \"c.h\"\n"
285                  "   #include \"b.h\"\n"));
286   EXPECT_EQ("#include \"a.h\"\n"
287             "#include \"b.h\"\n"
288             "#include \"c.h\"\n",
289             sort("# include \"a.h\"\n"
290                  "#  include \"c.h\"\n"
291                  "#   include \"b.h\"\n"));
292 }
293 
294 TEST_F(SortIncludesTest, GreaterInComment) {
295   EXPECT_EQ("#include \"a.h\"\n"
296             "#include \"b.h\" // >\n"
297             "#include \"c.h\"\n",
298             sort("#include \"a.h\"\n"
299                  "#include \"c.h\"\n"
300                  "#include \"b.h\" // >\n"));
301 }
302 
303 TEST_F(SortIncludesTest, SortsLocallyInEachBlock) {
304   EXPECT_EQ("#include \"a.h\"\n"
305             "#include \"c.h\"\n"
306             "\n"
307             "#include \"b.h\"\n",
308             sort("#include \"a.h\"\n"
309                  "#include \"c.h\"\n"
310                  "\n"
311                  "#include \"b.h\"\n",
312                  "input.h", 0));
313 }
314 
315 TEST_F(SortIncludesTest, SortsAllBlocksWhenMerging) {
316   Style.IncludeBlocks = tooling::IncludeStyle::IBS_Merge;
317   EXPECT_EQ("#include \"a.h\"\n"
318             "#include \"b.h\"\n"
319             "#include \"c.h\"\n",
320             sort("#include \"a.h\"\n"
321                  "#include \"c.h\"\n"
322                  "\n"
323                  "#include \"b.h\"\n"));
324 }
325 
326 TEST_F(SortIncludesTest, CommentsAlwaysSeparateGroups) {
327   EXPECT_EQ("#include \"a.h\"\n"
328             "#include \"c.h\"\n"
329             "// comment\n"
330             "#include \"b.h\"\n",
331             sort("#include \"c.h\"\n"
332                  "#include \"a.h\"\n"
333                  "// comment\n"
334                  "#include \"b.h\"\n"));
335 
336   Style.IncludeBlocks = tooling::IncludeStyle::IBS_Merge;
337   EXPECT_EQ("#include \"a.h\"\n"
338             "#include \"c.h\"\n"
339             "// comment\n"
340             "#include \"b.h\"\n",
341             sort("#include \"c.h\"\n"
342                  "#include \"a.h\"\n"
343                  "// comment\n"
344                  "#include \"b.h\"\n"));
345 
346   Style.IncludeBlocks = tooling::IncludeStyle::IBS_Regroup;
347   EXPECT_EQ("#include \"a.h\"\n"
348             "#include \"c.h\"\n"
349             "// comment\n"
350             "#include \"b.h\"\n",
351             sort("#include \"c.h\"\n"
352                  "#include \"a.h\"\n"
353                  "// comment\n"
354                  "#include \"b.h\"\n"));
355 }
356 
357 TEST_F(SortIncludesTest, HandlesAngledIncludesAsSeparateBlocks) {
358   EXPECT_EQ("#include \"a.h\"\n"
359             "#include \"c.h\"\n"
360             "#include <array>\n"
361             "#include <b.h>\n"
362             "#include <d.h>\n"
363             "#include <vector>\n",
364             sort("#include <vector>\n"
365                  "#include <d.h>\n"
366                  "#include <array>\n"
367                  "#include <b.h>\n"
368                  "#include \"c.h\"\n"
369                  "#include \"a.h\"\n"));
370 
371   FmtStyle = getGoogleStyle(FormatStyle::LK_Cpp);
372   EXPECT_EQ("#include <b.h>\n"
373             "#include <d.h>\n"
374             "\n"
375             "#include <array>\n"
376             "#include <vector>\n"
377             "\n"
378             "#include \"a.h\"\n"
379             "#include \"c.h\"\n",
380             sort("#include <vector>\n"
381                  "#include <d.h>\n"
382                  "#include <array>\n"
383                  "#include <b.h>\n"
384                  "#include \"c.h\"\n"
385                  "#include \"a.h\"\n"));
386 }
387 
388 TEST_F(SortIncludesTest, RegroupsAngledIncludesInSeparateBlocks) {
389   Style.IncludeBlocks = tooling::IncludeStyle::IBS_Regroup;
390   EXPECT_EQ("#include \"a.h\"\n"
391             "#include \"c.h\"\n"
392             "\n"
393             "#include <b.h>\n"
394             "#include <d.h>\n",
395             sort("#include <d.h>\n"
396                  "#include <b.h>\n"
397                  "#include \"c.h\"\n"
398                  "#include \"a.h\"\n"));
399 }
400 
401 TEST_F(SortIncludesTest, HandlesMultilineIncludes) {
402   EXPECT_EQ("#include \"a.h\"\n"
403             "#include \"b.h\"\n"
404             "#include \"c.h\"\n",
405             sort("#include \"a.h\"\n"
406                  "#include \\\n"
407                  "\"c.h\"\n"
408                  "#include \"b.h\"\n"));
409 }
410 
411 TEST_F(SortIncludesTest, LeavesMainHeaderFirst) {
412   Style.IncludeIsMainRegex = "([-_](test|unittest))?$";
413   EXPECT_EQ("#include \"llvm/a.h\"\n"
414             "#include \"b.h\"\n"
415             "#include \"c.h\"\n",
416             sort("#include \"llvm/a.h\"\n"
417                  "#include \"c.h\"\n"
418                  "#include \"b.h\"\n",
419                  "a.cc"));
420   EXPECT_EQ("#include \"llvm/a.h\"\n"
421             "#include \"b.h\"\n"
422             "#include \"c.h\"\n",
423             sort("#include \"llvm/a.h\"\n"
424                  "#include \"c.h\"\n"
425                  "#include \"b.h\"\n",
426                  "a_test.cc"));
427   EXPECT_EQ("#include \"llvm/input.h\"\n"
428             "#include \"b.h\"\n"
429             "#include \"c.h\"\n",
430             sort("#include \"llvm/input.h\"\n"
431                  "#include \"c.h\"\n"
432                  "#include \"b.h\"\n",
433                  "input.mm"));
434 
435   // Don't allow prefixes.
436   EXPECT_EQ("#include \"b.h\"\n"
437             "#include \"c.h\"\n"
438             "#include \"llvm/not_a.h\"\n",
439             sort("#include \"llvm/not_a.h\"\n"
440                  "#include \"c.h\"\n"
441                  "#include \"b.h\"\n",
442                  "a.cc"));
443 
444   // Don't do this for _main and other suffixes.
445   EXPECT_EQ("#include \"b.h\"\n"
446             "#include \"c.h\"\n"
447             "#include \"llvm/a.h\"\n",
448             sort("#include \"llvm/a.h\"\n"
449                  "#include \"c.h\"\n"
450                  "#include \"b.h\"\n",
451                  "a_main.cc"));
452 
453   // Don't do this in headers.
454   EXPECT_EQ("#include \"b.h\"\n"
455             "#include \"c.h\"\n"
456             "#include \"llvm/a.h\"\n",
457             sort("#include \"llvm/a.h\"\n"
458                  "#include \"c.h\"\n"
459                  "#include \"b.h\"\n",
460                  "a.h"));
461 
462   // Only do this in the first #include block.
463   EXPECT_EQ("#include <a>\n"
464             "\n"
465             "#include \"b.h\"\n"
466             "#include \"c.h\"\n"
467             "#include \"llvm/a.h\"\n",
468             sort("#include <a>\n"
469                  "\n"
470                  "#include \"llvm/a.h\"\n"
471                  "#include \"c.h\"\n"
472                  "#include \"b.h\"\n",
473                  "a.cc"));
474 
475   // Only recognize the first #include with a matching basename as main include.
476   EXPECT_EQ("#include \"a.h\"\n"
477             "#include \"b.h\"\n"
478             "#include \"c.h\"\n"
479             "#include \"llvm/a.h\"\n",
480             sort("#include \"b.h\"\n"
481                  "#include \"a.h\"\n"
482                  "#include \"c.h\"\n"
483                  "#include \"llvm/a.h\"\n",
484                  "a.cc"));
485 }
486 
487 TEST_F(SortIncludesTest, LeavesMainHeaderFirstInAdditionalExtensions) {
488   Style.IncludeIsMainRegex = "([-_](test|unittest))?|(Impl)?$";
489   EXPECT_EQ("#include \"b.h\"\n"
490             "#include \"c.h\"\n"
491             "#include \"llvm/a.h\"\n",
492             sort("#include \"llvm/a.h\"\n"
493                  "#include \"c.h\"\n"
494                  "#include \"b.h\"\n",
495                  "a_test.xxx"));
496   EXPECT_EQ("#include \"b.h\"\n"
497             "#include \"c.h\"\n"
498             "#include \"llvm/a.h\"\n",
499             sort("#include \"llvm/a.h\"\n"
500                  "#include \"c.h\"\n"
501                  "#include \"b.h\"\n",
502                  "aImpl.hpp"));
503 
504   // .cpp extension is considered "main" by default
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                  "aImpl.cpp"));
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                  "a_test.cpp"));
519 
520   // Allow additional filenames / extensions
521   Style.IncludeIsMainSourceRegex = "(Impl\\.hpp)|(\\.xxx)$";
522   EXPECT_EQ("#include \"llvm/a.h\"\n"
523             "#include \"b.h\"\n"
524             "#include \"c.h\"\n",
525             sort("#include \"llvm/a.h\"\n"
526                  "#include \"c.h\"\n"
527                  "#include \"b.h\"\n",
528                  "a_test.xxx"));
529   EXPECT_EQ("#include \"llvm/a.h\"\n"
530             "#include \"b.h\"\n"
531             "#include \"c.h\"\n",
532             sort("#include \"llvm/a.h\"\n"
533                  "#include \"c.h\"\n"
534                  "#include \"b.h\"\n",
535                  "aImpl.hpp"));
536 }
537 
538 TEST_F(SortIncludesTest, RecognizeMainHeaderInAllGroups) {
539   Style.IncludeIsMainRegex = "([-_](test|unittest))?$";
540   Style.IncludeBlocks = tooling::IncludeStyle::IBS_Merge;
541 
542   EXPECT_EQ("#include \"c.h\"\n"
543             "#include \"a.h\"\n"
544             "#include \"b.h\"\n",
545             sort("#include \"b.h\"\n"
546                  "\n"
547                  "#include \"a.h\"\n"
548                  "#include \"c.h\"\n",
549                  "c.cc"));
550 }
551 
552 TEST_F(SortIncludesTest, MainHeaderIsSeparatedWhenRegroupping) {
553   Style.IncludeIsMainRegex = "([-_](test|unittest))?$";
554   Style.IncludeBlocks = tooling::IncludeStyle::IBS_Regroup;
555 
556   EXPECT_EQ("#include \"a.h\"\n"
557             "\n"
558             "#include \"b.h\"\n"
559             "#include \"c.h\"\n",
560             sort("#include \"b.h\"\n"
561                  "\n"
562                  "#include \"a.h\"\n"
563                  "#include \"c.h\"\n",
564                  "a.cc"));
565 }
566 
567 TEST_F(SortIncludesTest, SupportCaseInsensitiveMatching) {
568   // Setup an regex for main includes so we can cover those as well.
569   Style.IncludeIsMainRegex = "([-_](test|unittest))?$";
570 
571   // Ensure both main header detection and grouping work in a case insensitive
572   // manner.
573   EXPECT_EQ("#include \"llvm/A.h\"\n"
574             "#include \"b.h\"\n"
575             "#include \"c.h\"\n"
576             "#include \"LLVM/z.h\"\n"
577             "#include \"llvm/X.h\"\n"
578             "#include \"GTest/GTest.h\"\n"
579             "#include \"gmock/gmock.h\"\n",
580             sort("#include \"c.h\"\n"
581                  "#include \"b.h\"\n"
582                  "#include \"GTest/GTest.h\"\n"
583                  "#include \"llvm/A.h\"\n"
584                  "#include \"gmock/gmock.h\"\n"
585                  "#include \"llvm/X.h\"\n"
586                  "#include \"LLVM/z.h\"\n",
587                  "a_TEST.cc"));
588 }
589 
590 TEST_F(SortIncludesTest, NegativePriorities) {
591   Style.IncludeCategories = {{".*important_os_header.*", -1, 0}, {".*", 1, 0}};
592   EXPECT_EQ("#include \"important_os_header.h\"\n"
593             "#include \"c_main.h\"\n"
594             "#include \"a_other.h\"\n",
595             sort("#include \"c_main.h\"\n"
596                  "#include \"a_other.h\"\n"
597                  "#include \"important_os_header.h\"\n",
598                  "c_main.cc"));
599 
600   // check stable when re-run
601   EXPECT_EQ("#include \"important_os_header.h\"\n"
602             "#include \"c_main.h\"\n"
603             "#include \"a_other.h\"\n",
604             sort("#include \"important_os_header.h\"\n"
605                  "#include \"c_main.h\"\n"
606                  "#include \"a_other.h\"\n",
607                  "c_main.cc", 0));
608 }
609 
610 TEST_F(SortIncludesTest, PriorityGroupsAreSeparatedWhenRegroupping) {
611   Style.IncludeCategories = {{".*important_os_header.*", -1, 0}, {".*", 1, 0}};
612   Style.IncludeBlocks = tooling::IncludeStyle::IBS_Regroup;
613 
614   EXPECT_EQ("#include \"important_os_header.h\"\n"
615             "\n"
616             "#include \"c_main.h\"\n"
617             "\n"
618             "#include \"a_other.h\"\n",
619             sort("#include \"c_main.h\"\n"
620                  "#include \"a_other.h\"\n"
621                  "#include \"important_os_header.h\"\n",
622                  "c_main.cc"));
623 
624   // check stable when re-run
625   EXPECT_EQ("#include \"important_os_header.h\"\n"
626             "\n"
627             "#include \"c_main.h\"\n"
628             "\n"
629             "#include \"a_other.h\"\n",
630             sort("#include \"important_os_header.h\"\n"
631                  "\n"
632                  "#include \"c_main.h\"\n"
633                  "\n"
634                  "#include \"a_other.h\"\n",
635                  "c_main.cc", 0));
636 }
637 
638 TEST_F(SortIncludesTest, CalculatesCorrectCursorPosition) {
639   std::string Code = "#include <ccc>\n"    // Start of line: 0
640                      "#include <bbbbbb>\n" // Start of line: 15
641                      "#include <a>\n";     // Start of line: 33
642   EXPECT_EQ(31u, newCursor(Code, 0));
643   EXPECT_EQ(13u, newCursor(Code, 15));
644   EXPECT_EQ(0u, newCursor(Code, 33));
645 
646   EXPECT_EQ(41u, newCursor(Code, 10));
647   EXPECT_EQ(23u, newCursor(Code, 25));
648   EXPECT_EQ(10u, newCursor(Code, 43));
649 }
650 
651 TEST_F(SortIncludesTest, DeduplicateIncludes) {
652   EXPECT_EQ("#include <a>\n"
653             "#include <b>\n"
654             "#include <c>\n",
655             sort("#include <a>\n"
656                  "#include <b>\n"
657                  "#include <b>\n"
658                  "#include <b>\n"
659                  "#include <b>\n"
660                  "#include <c>\n"));
661 
662   Style.IncludeBlocks = tooling::IncludeStyle::IBS_Merge;
663   EXPECT_EQ("#include <a>\n"
664             "#include <b>\n"
665             "#include <c>\n",
666             sort("#include <a>\n"
667                  "#include <b>\n"
668                  "\n"
669                  "#include <b>\n"
670                  "\n"
671                  "#include <b>\n"
672                  "#include <c>\n"));
673 
674   Style.IncludeBlocks = tooling::IncludeStyle::IBS_Regroup;
675   EXPECT_EQ("#include <a>\n"
676             "#include <b>\n"
677             "#include <c>\n",
678             sort("#include <a>\n"
679                  "#include <b>\n"
680                  "\n"
681                  "#include <b>\n"
682                  "\n"
683                  "#include <b>\n"
684                  "#include <c>\n"));
685 }
686 
687 TEST_F(SortIncludesTest, SortAndDeduplicateIncludes) {
688   EXPECT_EQ("#include <a>\n"
689             "#include <b>\n"
690             "#include <c>\n",
691             sort("#include <b>\n"
692                  "#include <a>\n"
693                  "#include <b>\n"
694                  "#include <b>\n"
695                  "#include <c>\n"
696                  "#include <b>\n"));
697 
698   Style.IncludeBlocks = tooling::IncludeStyle::IBS_Merge;
699   EXPECT_EQ("#include <a>\n"
700             "#include <b>\n"
701             "#include <c>\n",
702             sort("#include <b>\n"
703                  "#include <a>\n"
704                  "\n"
705                  "#include <b>\n"
706                  "\n"
707                  "#include <c>\n"
708                  "#include <b>\n"));
709 
710   Style.IncludeBlocks = tooling::IncludeStyle::IBS_Regroup;
711   EXPECT_EQ("#include <a>\n"
712             "#include <b>\n"
713             "#include <c>\n",
714             sort("#include <b>\n"
715                  "#include <a>\n"
716                  "\n"
717                  "#include <b>\n"
718                  "\n"
719                  "#include <c>\n"
720                  "#include <b>\n"));
721 }
722 
723 TEST_F(SortIncludesTest, CalculatesCorrectCursorPositionAfterDeduplicate) {
724   std::string Code = "#include <b>\n"      // Start of line: 0
725                      "#include <a>\n"      // Start of line: 13
726                      "#include <b>\n"      // Start of line: 26
727                      "#include <b>\n"      // Start of line: 39
728                      "#include <c>\n"      // Start of line: 52
729                      "#include <b>\n";     // Start of line: 65
730   std::string Expected = "#include <a>\n"  // Start of line: 0
731                          "#include <b>\n"  // Start of line: 13
732                          "#include <c>\n"; // Start of line: 26
733   EXPECT_EQ(Expected, sort(Code));
734   // Cursor on 'i' in "#include <a>".
735   EXPECT_EQ(1u, newCursor(Code, 14));
736   // Cursor on 'b' in "#include <b>".
737   EXPECT_EQ(23u, newCursor(Code, 10));
738   EXPECT_EQ(23u, newCursor(Code, 36));
739   EXPECT_EQ(23u, newCursor(Code, 49));
740   EXPECT_EQ(23u, newCursor(Code, 36));
741   EXPECT_EQ(23u, newCursor(Code, 75));
742   // Cursor on '#' in "#include <c>".
743   EXPECT_EQ(26u, newCursor(Code, 52));
744 }
745 
746 TEST_F(SortIncludesTest, DeduplicateLocallyInEachBlock) {
747   EXPECT_EQ("#include <a>\n"
748             "#include <b>\n"
749             "\n"
750             "#include <b>\n"
751             "#include <c>\n",
752             sort("#include <a>\n"
753                  "#include <b>\n"
754                  "\n"
755                  "#include <c>\n"
756                  "#include <b>\n"
757                  "#include <b>\n"));
758 }
759 
760 TEST_F(SortIncludesTest, ValidAffactedRangesAfterDeduplicatingIncludes) {
761   std::string Code = "#include <a>\n"
762                      "#include <b>\n"
763                      "#include <a>\n"
764                      "#include <a>\n"
765                      "\n"
766                      "   int     x ;";
767   std::vector<tooling::Range> Ranges = {tooling::Range(0, 52)};
768   auto Replaces = sortIncludes(FmtStyle, Code, Ranges, "input.cpp");
769   Ranges = tooling::calculateRangesAfterReplacements(Replaces, Ranges);
770   EXPECT_EQ(1u, Ranges.size());
771   EXPECT_EQ(0u, Ranges[0].getOffset());
772   EXPECT_EQ(26u, Ranges[0].getLength());
773 }
774 
775 TEST_F(SortIncludesTest, DoNotSortLikelyXml) {
776   EXPECT_EQ("<!--;\n"
777             "#include <b>\n"
778             "#include <a>\n"
779             "-->",
780             sort("<!--;\n"
781                  "#include <b>\n"
782                  "#include <a>\n"
783                  "-->",
784                  "input.h", 0));
785 }
786 
787 TEST_F(SortIncludesTest, DoNotOutputReplacementsForSortedBlocksWithRegrouping) {
788   Style.IncludeBlocks = Style.IBS_Regroup;
789   std::string Code = R"(
790 #include "b.h"
791 
792 #include <a.h>
793 )";
794   EXPECT_EQ(Code, sort(Code, "input.h", 0));
795 }
796 
797 TEST_F(SortIncludesTest,
798        DoNotOutputReplacementsForSortedBlocksWithRegroupingWindows) {
799   Style.IncludeBlocks = Style.IBS_Regroup;
800   std::string Code = "#include \"b.h\"\r\n"
801                      "\r\n"
802                      "#include <a.h>\r\n";
803   EXPECT_EQ(Code, sort(Code, "input.h", 0));
804 }
805 
806 TEST_F(SortIncludesTest, DoNotRegroupGroupsInGoogleObjCStyle) {
807   FmtStyle = getGoogleStyle(FormatStyle::LK_ObjC);
808 
809   EXPECT_EQ("#include <a.h>\n"
810             "#include <b.h>\n"
811             "#include \"a.h\"",
812             sort("#include <b.h>\n"
813                  "#include <a.h>\n"
814                  "#include \"a.h\""));
815 }
816 
817 } // end namespace
818 } // end namespace format
819 } // end namespace clang
820