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