1 | //===---- IncludeInserterTest.cpp - clang-tidy ----------------------------===// |
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 "../clang-tidy/utils/IncludeInserter.h" |
10 | #include "clang/Lex/Preprocessor.h" |
11 | #include "clang/Frontend/CompilerInstance.h" |
12 | #include "ClangTidyTest.h" |
13 | #include "gtest/gtest.h" |
14 | |
15 | // FIXME: Canonicalize paths correctly on windows. |
16 | // Currently, adding virtual files will canonicalize the paths before |
17 | // storing the virtual entries. |
18 | // When resolving virtual entries in the FileManager, the paths (for |
19 | // example coming from a #include directive) are not canonicalized |
20 | // to native paths; thus, the virtual file is not found. |
21 | // This needs to be fixed in the FileManager before we can make |
22 | // clang-tidy tests work. |
23 | #if !defined(_WIN32) |
24 | |
25 | namespace clang { |
26 | namespace tidy { |
27 | namespace { |
28 | |
29 | class IncludeInserterCheckBase : public ClangTidyCheck { |
30 | public: |
31 | IncludeInserterCheckBase(StringRef CheckName, ClangTidyContext *Context, |
32 | utils::IncludeSorter::IncludeStyle Style = |
33 | utils::IncludeSorter::IS_Google, |
34 | bool SelfContainedDiags = false) |
35 | : ClangTidyCheck(CheckName, Context), |
36 | Inserter(Style, SelfContainedDiags) {} |
37 | |
38 | void registerPPCallbacks(const SourceManager &SM, Preprocessor *PP, |
39 | Preprocessor *ModuleExpanderPP) override { |
40 | Inserter.registerPreprocessor(PP); |
41 | } |
42 | |
43 | void registerMatchers(ast_matchers::MatchFinder *Finder) override { |
44 | Finder->addMatcher(NodeMatch: ast_matchers::declStmt().bind(ID: "stmt" ), Action: this); |
45 | } |
46 | |
47 | void check(const ast_matchers::MatchFinder::MatchResult &Result) override { |
48 | auto Diag = diag(Loc: Result.Nodes.getNodeAs<DeclStmt>(ID: "stmt" )->getBeginLoc(), |
49 | Description: "foo, bar" ); |
50 | for (StringRef : headersToInclude()) { |
51 | Diag << Inserter.createMainFileIncludeInsertion(Header); |
52 | } |
53 | } |
54 | |
55 | virtual std::vector<StringRef> () const = 0; |
56 | |
57 | utils::IncludeInserter Inserter; |
58 | }; |
59 | |
60 | class : public IncludeInserterCheckBase { |
61 | public: |
62 | (StringRef CheckName, ClangTidyContext *Context) |
63 | : IncludeInserterCheckBase(CheckName, Context) {} |
64 | |
65 | std::vector<StringRef> () const override { |
66 | return {"path/to/header.h" }; |
67 | } |
68 | }; |
69 | |
70 | class : public IncludeInserterCheckBase { |
71 | public: |
72 | (StringRef CheckName, ClangTidyContext *Context) |
73 | : IncludeInserterCheckBase(CheckName, Context) {} |
74 | |
75 | std::vector<StringRef> () const override { |
76 | return {"a/header.h" }; |
77 | } |
78 | }; |
79 | |
80 | class : public IncludeInserterCheckBase { |
81 | public: |
82 | (StringRef CheckName, ClangTidyContext *Context) |
83 | : IncludeInserterCheckBase(CheckName, Context) {} |
84 | |
85 | std::vector<StringRef> () const override { |
86 | return {"path/to/header.h" , "path/to/header2.h" , "path/to/header.h" }; |
87 | } |
88 | }; |
89 | |
90 | class : public IncludeInserterCheckBase { |
91 | public: |
92 | (StringRef CheckName, |
93 | ClangTidyContext *Context) |
94 | : IncludeInserterCheckBase(CheckName, Context, |
95 | utils::IncludeSorter::IS_Google, |
96 | /*SelfContainedDiags=*/true) {} |
97 | |
98 | std::vector<StringRef> () const override { |
99 | return {"path/to/header.h" , "path/to/header2.h" , "path/to/header.h" }; |
100 | } |
101 | }; |
102 | |
103 | class CSystemIncludeInserterCheck : public IncludeInserterCheckBase { |
104 | public: |
105 | CSystemIncludeInserterCheck(StringRef CheckName, ClangTidyContext *Context) |
106 | : IncludeInserterCheckBase(CheckName, Context) {} |
107 | |
108 | std::vector<StringRef> () const override { |
109 | return {"<stdlib.h>" }; |
110 | } |
111 | }; |
112 | |
113 | class CXXSystemIncludeInserterCheck : public IncludeInserterCheckBase { |
114 | public: |
115 | CXXSystemIncludeInserterCheck(StringRef CheckName, ClangTidyContext *Context) |
116 | : IncludeInserterCheckBase(CheckName, Context) {} |
117 | |
118 | std::vector<StringRef> () const override { return {"<set>" }; } |
119 | }; |
120 | |
121 | class InvalidIncludeInserterCheck : public IncludeInserterCheckBase { |
122 | public: |
123 | InvalidIncludeInserterCheck(StringRef CheckName, ClangTidyContext *Context) |
124 | : IncludeInserterCheckBase(CheckName, Context) {} |
125 | |
126 | std::vector<StringRef> () const override { |
127 | return {"a.h" , "<stdlib.h" , "cstdlib>" , "b.h" , "<c.h>" , "<d>" }; |
128 | } |
129 | }; |
130 | |
131 | class : public IncludeInserterCheckBase { |
132 | public: |
133 | (StringRef CheckName, |
134 | ClangTidyContext *Context) |
135 | : IncludeInserterCheckBase(CheckName, Context, |
136 | utils::IncludeSorter::IS_Google_ObjC) {} |
137 | |
138 | std::vector<StringRef> () const override { |
139 | return {"a/header.h" }; |
140 | } |
141 | }; |
142 | |
143 | class : public IncludeInserterCheckBase { |
144 | public: |
145 | (StringRef CheckName, |
146 | ClangTidyContext *Context) |
147 | : IncludeInserterCheckBase(CheckName, Context, |
148 | utils::IncludeSorter::IS_Google_ObjC) {} |
149 | |
150 | std::vector<StringRef> () const override { |
151 | return {"top_level_test_header+foo.h" }; |
152 | } |
153 | }; |
154 | |
155 | class : public IncludeInserterCheckBase { |
156 | public: |
157 | (StringRef CheckName, |
158 | ClangTidyContext *Context) |
159 | : IncludeInserterCheckBase(CheckName, Context, |
160 | utils::IncludeSorter::IS_Google_ObjC) {} |
161 | |
162 | std::vector<StringRef> () const override { |
163 | return {"clang_tidy/tests/generated_file.proto.h" }; |
164 | } |
165 | }; |
166 | |
167 | template <typename Check> |
168 | std::string runCheckOnCode(StringRef Code, StringRef Filename) { |
169 | std::vector<ClangTidyError> Errors; |
170 | return test::runCheckOnCode<Check>(Code, &Errors, Filename, std::nullopt, |
171 | ClangTidyOptions(), |
172 | {// Main file include |
173 | {"clang_tidy/tests/" |
174 | "insert_includes_test_header.h" , |
175 | "\n" }, |
176 | // Top-level main file include + |
177 | // category. |
178 | {"top_level_test_header.h" , "\n" }, |
179 | {"top_level_test_header+foo.h" , "\n" }, |
180 | // ObjC category. |
181 | {"clang_tidy/tests/" |
182 | "insert_includes_test_header+foo.h" , |
183 | "\n" }, |
184 | // Non system headers |
185 | {"a/header.h" , "\n" }, |
186 | {"path/to/a/header.h" , "\n" }, |
187 | {"path/to/z/header.h" , "\n" }, |
188 | {"path/to/header.h" , "\n" }, |
189 | {"path/to/header2.h" , "\n" }, |
190 | // Generated headers |
191 | {"clang_tidy/tests/" |
192 | "generated_file.proto.h" , |
193 | "\n" }, |
194 | // Fake system headers. |
195 | {"stdlib.h" , "\n" }, |
196 | {"unistd.h" , "\n" }, |
197 | {"list" , "\n" }, |
198 | {"map" , "\n" }, |
199 | {"set" , "\n" }, |
200 | {"vector" , "\n" }}); |
201 | } |
202 | |
203 | TEST(IncludeInserterTest, InsertAfterLastNonSystemInclude) { |
204 | const char *PreCode = R"( |
205 | #include "clang_tidy/tests/insert_includes_test_header.h" |
206 | |
207 | #include <list> |
208 | #include <map> |
209 | |
210 | #include "path/to/a/header.h" |
211 | |
212 | void foo() { |
213 | int a = 0; |
214 | })" ; |
215 | const char *PostCode = R"( |
216 | #include "clang_tidy/tests/insert_includes_test_header.h" |
217 | |
218 | #include <list> |
219 | #include <map> |
220 | |
221 | #include "path/to/a/header.h" |
222 | #include "path/to/header.h" |
223 | |
224 | void foo() { |
225 | int a = 0; |
226 | })" ; |
227 | |
228 | EXPECT_EQ(PostCode, |
229 | runCheckOnCode<NonSystemHeaderInserterCheck>( |
230 | PreCode, "clang_tidy/tests/insert_includes_test_input2.cc" )); |
231 | } |
232 | |
233 | TEST(IncludeInserterTest, InsertMultipleIncludesAndDeduplicate) { |
234 | const char *PreCode = R"( |
235 | #include "clang_tidy/tests/insert_includes_test_header.h" |
236 | |
237 | #include <list> |
238 | #include <map> |
239 | |
240 | #include "path/to/a/header.h" |
241 | |
242 | void foo() { |
243 | int a = 0; |
244 | })" ; |
245 | const char *PostCode = R"( |
246 | #include "clang_tidy/tests/insert_includes_test_header.h" |
247 | |
248 | #include <list> |
249 | #include <map> |
250 | |
251 | #include "path/to/a/header.h" |
252 | #include "path/to/header.h" |
253 | #include "path/to/header2.h" |
254 | |
255 | void foo() { |
256 | int a = 0; |
257 | })" ; |
258 | |
259 | EXPECT_EQ(PostCode, |
260 | runCheckOnCode<MultipleHeaderInserterCheck>( |
261 | PreCode, "clang_tidy/tests/insert_includes_test_input2.cc" )); |
262 | } |
263 | |
264 | TEST(IncludeInserterTest, InsertMultipleIncludesNoDeduplicate) { |
265 | const char *PreCode = R"( |
266 | #include "clang_tidy/tests/insert_includes_test_header.h" |
267 | |
268 | #include <list> |
269 | #include <map> |
270 | |
271 | #include "path/to/a/header.h" |
272 | |
273 | void foo() { |
274 | int a = 0; |
275 | })" ; |
276 | // FIXME: ClangFormat bug - https://bugs.llvm.org/show_bug.cgi?id=49298 |
277 | // clang-format off |
278 | const char *PostCode = R"( |
279 | #include "clang_tidy/tests/insert_includes_test_header.h" |
280 | |
281 | #include <list> |
282 | #include <map> |
283 | |
284 | #include "path/to/a/header.h" |
285 | #include "path/to/header.h" |
286 | #include "path/to/header2.h" |
287 | #include "path/to/header.h" |
288 | |
289 | void foo() { |
290 | int a = 0; |
291 | })" ; |
292 | // clang-format on |
293 | |
294 | EXPECT_EQ(PostCode, |
295 | runCheckOnCode<MultipleHeaderSingleInserterCheck>( |
296 | PreCode, "clang_tidy/tests/insert_includes_test_input2.cc" )); |
297 | } |
298 | |
299 | TEST(IncludeInserterTest, InsertBeforeFirstNonSystemInclude) { |
300 | const char *PreCode = R"( |
301 | #include "clang_tidy/tests/insert_includes_test_header.h" |
302 | |
303 | #include <list> |
304 | #include <map> |
305 | |
306 | #include "path/to/z/header.h" |
307 | |
308 | void foo() { |
309 | int a = 0; |
310 | })" ; |
311 | const char *PostCode = R"( |
312 | #include "clang_tidy/tests/insert_includes_test_header.h" |
313 | |
314 | #include <list> |
315 | #include <map> |
316 | |
317 | #include "path/to/header.h" |
318 | #include "path/to/z/header.h" |
319 | |
320 | void foo() { |
321 | int a = 0; |
322 | })" ; |
323 | |
324 | EXPECT_EQ(PostCode, |
325 | runCheckOnCode<NonSystemHeaderInserterCheck>( |
326 | PreCode, "clang_tidy/tests/insert_includes_test_input2.cc" )); |
327 | } |
328 | |
329 | TEST(IncludeInserterTest, InsertBetweenNonSystemIncludes) { |
330 | const char *PreCode = R"( |
331 | #include "clang_tidy/tests/insert_includes_test_header.h" |
332 | |
333 | #include <list> |
334 | #include <map> |
335 | |
336 | #include "path/to/a/header.h" |
337 | #include "path/to/z/header.h" |
338 | |
339 | void foo() { |
340 | int a = 0; |
341 | })" ; |
342 | const char *PostCode = R"( |
343 | #include "clang_tidy/tests/insert_includes_test_header.h" |
344 | |
345 | #include <list> |
346 | #include <map> |
347 | |
348 | #include "path/to/a/header.h" |
349 | #include "path/to/header.h" |
350 | #include "path/to/z/header.h" |
351 | |
352 | void foo() { |
353 | int a = 0; |
354 | })" ; |
355 | |
356 | EXPECT_EQ(PostCode, |
357 | runCheckOnCode<NonSystemHeaderInserterCheck>( |
358 | PreCode, "clang_tidy/tests/insert_includes_test_input2.cc" )); |
359 | } |
360 | |
361 | TEST(IncludeInserterTest, NonSystemIncludeAlreadyIncluded) { |
362 | const char *PreCode = R"( |
363 | #include "clang_tidy/tests/insert_includes_test_header.h" |
364 | |
365 | #include <list> |
366 | #include <map> |
367 | |
368 | #include "path/to/a/header.h" |
369 | #include "path/to/header.h" |
370 | #include "path/to/z/header.h" |
371 | |
372 | void foo() { |
373 | int a = 0; |
374 | })" ; |
375 | EXPECT_EQ(PreCode, |
376 | runCheckOnCode<NonSystemHeaderInserterCheck>( |
377 | PreCode, "clang_tidy/tests/insert_includes_test_input2.cc" )); |
378 | } |
379 | |
380 | TEST(IncludeInserterTest, InsertNonSystemIncludeAfterLastCXXSystemInclude) { |
381 | const char *PreCode = R"( |
382 | #include "clang_tidy/tests/insert_includes_test_header.h" |
383 | |
384 | #include <list> |
385 | #include <map> |
386 | |
387 | void foo() { |
388 | int a = 0; |
389 | })" ; |
390 | const char *PostCode = R"( |
391 | #include "clang_tidy/tests/insert_includes_test_header.h" |
392 | |
393 | #include <list> |
394 | #include <map> |
395 | |
396 | #include "path/to/header.h" |
397 | |
398 | void foo() { |
399 | int a = 0; |
400 | })" ; |
401 | |
402 | EXPECT_EQ(PostCode, |
403 | runCheckOnCode<NonSystemHeaderInserterCheck>( |
404 | PreCode, "clang_tidy/tests/insert_includes_test_header.cc" )); |
405 | } |
406 | |
407 | TEST(IncludeInserterTest, InsertNonSystemIncludeAfterMainFileInclude) { |
408 | const char *PreCode = R"( |
409 | #include "clang_tidy/tests/insert_includes_test_header.h" |
410 | |
411 | void foo() { |
412 | int a = 0; |
413 | })" ; |
414 | const char *PostCode = R"( |
415 | #include "clang_tidy/tests/insert_includes_test_header.h" |
416 | |
417 | #include "path/to/header.h" |
418 | |
419 | void foo() { |
420 | int a = 0; |
421 | })" ; |
422 | |
423 | EXPECT_EQ(PostCode, |
424 | runCheckOnCode<NonSystemHeaderInserterCheck>( |
425 | PreCode, "clang_tidy/tests/insert_includes_test_header.cc" )); |
426 | } |
427 | |
428 | TEST(IncludeInserterTest, InsertCXXSystemIncludeAfterLastCXXSystemInclude) { |
429 | const char *PreCode = R"( |
430 | #include "clang_tidy/tests/insert_includes_test_header.h" |
431 | |
432 | #include <list> |
433 | #include <map> |
434 | |
435 | #include "path/to/a/header.h" |
436 | |
437 | void foo() { |
438 | int a = 0; |
439 | })" ; |
440 | const char *PostCode = R"( |
441 | #include "clang_tidy/tests/insert_includes_test_header.h" |
442 | |
443 | #include <list> |
444 | #include <map> |
445 | #include <set> |
446 | |
447 | #include "path/to/a/header.h" |
448 | |
449 | void foo() { |
450 | int a = 0; |
451 | })" ; |
452 | |
453 | EXPECT_EQ(PostCode, |
454 | runCheckOnCode<CXXSystemIncludeInserterCheck>( |
455 | PreCode, "clang_tidy/tests/insert_includes_test_header.cc" )); |
456 | } |
457 | |
458 | TEST(IncludeInserterTest, InsertCXXSystemIncludeBeforeFirstCXXSystemInclude) { |
459 | const char *PreCode = R"( |
460 | #include "clang_tidy/tests/insert_includes_test_header.h" |
461 | |
462 | #include <vector> |
463 | |
464 | #include "path/to/a/header.h" |
465 | |
466 | void foo() { |
467 | int a = 0; |
468 | })" ; |
469 | const char *PostCode = R"( |
470 | #include "clang_tidy/tests/insert_includes_test_header.h" |
471 | |
472 | #include <set> |
473 | #include <vector> |
474 | |
475 | #include "path/to/a/header.h" |
476 | |
477 | void foo() { |
478 | int a = 0; |
479 | })" ; |
480 | |
481 | EXPECT_EQ(PostCode, |
482 | runCheckOnCode<CXXSystemIncludeInserterCheck>( |
483 | PreCode, "clang_tidy/tests/insert_includes_test_header.cc" )); |
484 | } |
485 | |
486 | TEST(IncludeInserterTest, InsertCXXSystemIncludeBetweenCXXSystemIncludes) { |
487 | const char *PreCode = R"( |
488 | #include "clang_tidy/tests/insert_includes_test_header.h" |
489 | |
490 | #include <map> |
491 | #include <vector> |
492 | |
493 | #include "path/to/a/header.h" |
494 | |
495 | void foo() { |
496 | int a = 0; |
497 | })" ; |
498 | const char *PostCode = R"( |
499 | #include "clang_tidy/tests/insert_includes_test_header.h" |
500 | |
501 | #include <map> |
502 | #include <set> |
503 | #include <vector> |
504 | |
505 | #include "path/to/a/header.h" |
506 | |
507 | void foo() { |
508 | int a = 0; |
509 | })" ; |
510 | |
511 | EXPECT_EQ(PostCode, |
512 | runCheckOnCode<CXXSystemIncludeInserterCheck>( |
513 | PreCode, "clang_tidy/tests/insert_includes_test_header.cc" )); |
514 | } |
515 | |
516 | TEST(IncludeInserterTest, InsertCXXSystemIncludeAfterMainFileInclude) { |
517 | const char *PreCode = R"( |
518 | #include "clang_tidy/tests/insert_includes_test_header.h" |
519 | |
520 | #include "path/to/a/header.h" |
521 | |
522 | void foo() { |
523 | int a = 0; |
524 | })" ; |
525 | const char *PostCode = R"( |
526 | #include "clang_tidy/tests/insert_includes_test_header.h" |
527 | |
528 | #include <set> |
529 | |
530 | #include "path/to/a/header.h" |
531 | |
532 | void foo() { |
533 | int a = 0; |
534 | })" ; |
535 | |
536 | EXPECT_EQ(PostCode, |
537 | runCheckOnCode<CXXSystemIncludeInserterCheck>( |
538 | PreCode, "clang_tidy/tests/insert_includes_test_header.cc" )); |
539 | } |
540 | |
541 | TEST(IncludeInserterTest, InsertCXXSystemIncludeAfterCSystemInclude) { |
542 | const char *PreCode = R"( |
543 | #include "clang_tidy/tests/insert_includes_test_header.h" |
544 | |
545 | #include <stdlib.h> |
546 | |
547 | #include "path/to/a/header.h" |
548 | |
549 | void foo() { |
550 | int a = 0; |
551 | })" ; |
552 | const char *PostCode = R"( |
553 | #include "clang_tidy/tests/insert_includes_test_header.h" |
554 | |
555 | #include <stdlib.h> |
556 | |
557 | #include <set> |
558 | |
559 | #include "path/to/a/header.h" |
560 | |
561 | void foo() { |
562 | int a = 0; |
563 | })" ; |
564 | |
565 | EXPECT_EQ(PostCode, |
566 | runCheckOnCode<CXXSystemIncludeInserterCheck>( |
567 | PreCode, "clang_tidy/tests/insert_includes_test_header.cc" )); |
568 | } |
569 | |
570 | TEST(IncludeInserterTest, InsertCXXSystemIncludeBeforeNonSystemInclude) { |
571 | const char *PreCode = R"( |
572 | #include "path/to/a/header.h" |
573 | |
574 | void foo() { |
575 | int a = 0; |
576 | })" ; |
577 | const char *PostCode = R"( |
578 | #include <set> |
579 | |
580 | #include "path/to/a/header.h" |
581 | |
582 | void foo() { |
583 | int a = 0; |
584 | })" ; |
585 | |
586 | EXPECT_EQ( |
587 | PostCode, |
588 | runCheckOnCode<CXXSystemIncludeInserterCheck>( |
589 | PreCode, "repo/clang_tidy/tests/insert_includes_test_header.cc" )); |
590 | } |
591 | |
592 | TEST(IncludeInserterTest, InsertCSystemIncludeBeforeCXXSystemInclude) { |
593 | const char *PreCode = R"( |
594 | #include <set> |
595 | |
596 | #include "path/to/a/header.h" |
597 | |
598 | void foo() { |
599 | int a = 0; |
600 | })" ; |
601 | const char *PostCode = R"( |
602 | #include <stdlib.h> |
603 | |
604 | #include <set> |
605 | |
606 | #include "path/to/a/header.h" |
607 | |
608 | void foo() { |
609 | int a = 0; |
610 | })" ; |
611 | |
612 | EXPECT_EQ( |
613 | PostCode, |
614 | runCheckOnCode<CSystemIncludeInserterCheck>( |
615 | PreCode, "repo/clang_tidy/tests/insert_includes_test_header.cc" )); |
616 | } |
617 | |
618 | TEST(IncludeInserterTest, InsertIncludeIfThereWasNoneBefore) { |
619 | const char *PreCode = R"( |
620 | void foo() { |
621 | int a = 0; |
622 | })" ; |
623 | const char *PostCode = R"(#include <set> |
624 | |
625 | |
626 | void foo() { |
627 | int a = 0; |
628 | })" ; |
629 | |
630 | EXPECT_EQ( |
631 | PostCode, |
632 | runCheckOnCode<CXXSystemIncludeInserterCheck>( |
633 | PreCode, "repo/clang_tidy/tests/insert_includes_test_header.cc" )); |
634 | } |
635 | |
636 | TEST(IncludeInserterTest, DontInsertDuplicateIncludeEvenIfMiscategorized) { |
637 | const char *PreCode = R"( |
638 | #include "clang_tidy/tests/insert_includes_test_header.h" |
639 | |
640 | #include <map> |
641 | #include <set> |
642 | #include <vector> |
643 | |
644 | #include "a/header.h" |
645 | #include "path/to/a/header.h" |
646 | #include "path/to/header.h" |
647 | |
648 | void foo() { |
649 | int a = 0; |
650 | })" ; |
651 | |
652 | const char *PostCode = R"( |
653 | #include "clang_tidy/tests/insert_includes_test_header.h" |
654 | |
655 | #include <map> |
656 | #include <set> |
657 | #include <vector> |
658 | |
659 | #include "a/header.h" |
660 | #include "path/to/a/header.h" |
661 | #include "path/to/header.h" |
662 | |
663 | void foo() { |
664 | int a = 0; |
665 | })" ; |
666 | |
667 | EXPECT_EQ(PostCode, runCheckOnCode<EarlyInAlphabetHeaderInserterCheck>( |
668 | PreCode, "workspace_folder/clang_tidy/tests/" |
669 | "insert_includes_test_header.cc" )); |
670 | } |
671 | |
672 | TEST(IncludeInserterTest, HandleOrderInSubdirectory) { |
673 | const char *PreCode = R"( |
674 | #include "clang_tidy/tests/insert_includes_test_header.h" |
675 | |
676 | #include <map> |
677 | #include <set> |
678 | #include <vector> |
679 | |
680 | #include "path/to/a/header.h" |
681 | #include "path/to/header.h" |
682 | |
683 | void foo() { |
684 | int a = 0; |
685 | })" ; |
686 | |
687 | const char *PostCode = R"( |
688 | #include "clang_tidy/tests/insert_includes_test_header.h" |
689 | |
690 | #include <map> |
691 | #include <set> |
692 | #include <vector> |
693 | |
694 | #include "a/header.h" |
695 | #include "path/to/a/header.h" |
696 | #include "path/to/header.h" |
697 | |
698 | void foo() { |
699 | int a = 0; |
700 | })" ; |
701 | |
702 | EXPECT_EQ(PostCode, runCheckOnCode<EarlyInAlphabetHeaderInserterCheck>( |
703 | PreCode, "workspace_folder/clang_tidy/tests/" |
704 | "insert_includes_test_header.cc" )); |
705 | } |
706 | |
707 | TEST(IncludeInserterTest, InvalidHeaderName) { |
708 | const char *PreCode = R"( |
709 | #include "clang_tidy/tests/insert_includes_test_header.h" |
710 | |
711 | #include <list> |
712 | #include <map> |
713 | |
714 | #include "path/to/a/header.h" |
715 | |
716 | void foo() { |
717 | int a = 0; |
718 | })" ; |
719 | const char *PostCode = R"( |
720 | #include "clang_tidy/tests/insert_includes_test_header.h" |
721 | |
722 | #include <c.h> |
723 | |
724 | #include <d> |
725 | #include <list> |
726 | #include <map> |
727 | |
728 | #include "a.h" |
729 | #include "b.h" |
730 | #include "path/to/a/header.h" |
731 | |
732 | void foo() { |
733 | int a = 0; |
734 | })" ; |
735 | |
736 | EXPECT_EQ(PostCode, |
737 | runCheckOnCode<InvalidIncludeInserterCheck>( |
738 | PreCode, "clang_tidy/tests/insert_includes_test_header.cc" )); |
739 | } |
740 | |
741 | TEST(IncludeInserterTest, InsertHeaderObjectiveC) { |
742 | const char *PreCode = R"( |
743 | #import "clang_tidy/tests/insert_includes_test_header.h" |
744 | |
745 | void foo() { |
746 | int a = 0; |
747 | })" ; |
748 | const char *PostCode = R"( |
749 | #import "clang_tidy/tests/insert_includes_test_header.h" |
750 | |
751 | #import "a/header.h" |
752 | |
753 | void foo() { |
754 | int a = 0; |
755 | })" ; |
756 | |
757 | EXPECT_EQ( |
758 | PostCode, |
759 | runCheckOnCode<ObjCEarlyInAlphabetHeaderInserterCheck>( |
760 | PreCode, "repo/clang_tidy/tests/insert_includes_test_header.mm" )); |
761 | } |
762 | |
763 | TEST(IncludeInserterTest, InsertCategoryHeaderObjectiveC) { |
764 | const char *PreCode = R"( |
765 | #import "top_level_test_header.h" |
766 | |
767 | void foo() { |
768 | int a = 0; |
769 | })" ; |
770 | const char *PostCode = R"( |
771 | #import "top_level_test_header.h" |
772 | #import "top_level_test_header+foo.h" |
773 | |
774 | void foo() { |
775 | int a = 0; |
776 | })" ; |
777 | |
778 | EXPECT_EQ(PostCode, runCheckOnCode<ObjCCategoryHeaderInserterCheck>( |
779 | PreCode, "top_level_test_header.mm" )); |
780 | } |
781 | |
782 | TEST(IncludeInserterTest, InsertGeneratedHeaderObjectiveC) { |
783 | const char *PreCode = R"( |
784 | #import "clang_tidy/tests/insert_includes_test_header.h" |
785 | |
786 | #include <list> |
787 | #include <map> |
788 | |
789 | #include "path/to/a/header.h" |
790 | |
791 | void foo() { |
792 | int a = 0; |
793 | })" ; |
794 | const char *PostCode = R"( |
795 | #import "clang_tidy/tests/insert_includes_test_header.h" |
796 | |
797 | #include <list> |
798 | #include <map> |
799 | |
800 | #include "path/to/a/header.h" |
801 | |
802 | #import "clang_tidy/tests/generated_file.proto.h" |
803 | |
804 | void foo() { |
805 | int a = 0; |
806 | })" ; |
807 | |
808 | EXPECT_EQ( |
809 | PostCode, |
810 | runCheckOnCode<ObjCGeneratedHeaderInserterCheck>( |
811 | PreCode, "repo/clang_tidy/tests/insert_includes_test_header.mm" )); |
812 | } |
813 | |
814 | } // anonymous namespace |
815 | } // namespace tidy |
816 | } // namespace clang |
817 | |
818 | #endif |
819 | |