• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "gn/analyzer.h"
6 
7 #include "gn/build_settings.h"
8 #include "gn/builder.h"
9 #include "gn/c_tool.h"
10 #include "gn/config.h"
11 #include "gn/general_tool.h"
12 #include "gn/loader.h"
13 #include "gn/pool.h"
14 #include "gn/settings.h"
15 #include "gn/source_file.h"
16 #include "gn/substitution_list.h"
17 #include "gn/target.h"
18 #include "gn/tool.h"
19 #include "gn/toolchain.h"
20 #include "util/test/test.h"
21 
22 namespace gn_analyzer_unittest {
23 
24 class MockLoader : public Loader {
25  public:
26   MockLoader() = default;
27 
Load(const SourceFile & file,const LocationRange & origin,const Label & toolchain_name)28   void Load(const SourceFile& file,
29             const LocationRange& origin,
30             const Label& toolchain_name) override {}
ToolchainLoaded(const Toolchain * toolchain)31   void ToolchainLoaded(const Toolchain* toolchain) override {}
GetDefaultToolchain() const32   Label GetDefaultToolchain() const override {
33     return Label(SourceDir("//tc/"), "default");
34   }
GetToolchainSettings(const Label & label) const35   const Settings* GetToolchainSettings(const Label& label) const override {
36     return nullptr;
37   }
BuildFileForLabel(const Label & label) const38   SourceFile BuildFileForLabel(const Label& label) const override {
39     return SourceFile(label.dir().value() + "BUILD.gn");
40   }
41 
42  private:
43   ~MockLoader() override = default;
44 };
45 
46 class AnalyzerTest : public testing::Test {
47  public:
AnalyzerTest()48   AnalyzerTest()
49       : loader_(new MockLoader),
50         builder_(loader_.get()),
51         settings_(&build_settings_, std::string()),
52         other_settings_(&build_settings_, std::string()) {
53     build_settings_.SetBuildDir(SourceDir("//out/"));
54 
55     settings_.set_toolchain_label(Label(SourceDir("//tc/"), "default"));
56     settings_.set_default_toolchain_label(settings_.toolchain_label());
57     tc_dir_ = settings_.toolchain_label().dir();
58     tc_name_ = settings_.toolchain_label().name();
59 
60     other_settings_.set_toolchain_label(Label(SourceDir("//other/"), "tc"));
61     other_settings_.set_default_toolchain_label(
62         other_settings_.toolchain_label());
63     tc_other_dir_ = other_settings_.toolchain_label().dir();
64     tc_other_name_ = other_settings_.toolchain_label().name();
65   }
66 
MakeTarget(const std::string & dir,const std::string & name)67   std::unique_ptr<Target> MakeTarget(const std::string& dir,
68                                      const std::string& name) {
69     Label label(SourceDir(dir), name, tc_dir_, tc_name_);
70     return std::make_unique<Target>(&settings_, label);
71   }
72 
MakeTargetOtherToolchain(const std::string & dir,const std::string & name)73   std::unique_ptr<Target> MakeTargetOtherToolchain(const std::string& dir,
74                                                    const std::string& name) {
75     Label label(SourceDir(dir), name, tc_other_dir_, tc_other_name_);
76     return std::make_unique<Target>(&other_settings_, label);
77   }
78 
MakeConfig(const std::string & dir,const std::string & name)79   std::unique_ptr<Config> MakeConfig(const std::string& dir,
80                                      const std::string& name) {
81     Label label(SourceDir(dir), name, tc_dir_, tc_name_);
82     return std::make_unique<Config>(&settings_, label);
83   }
84 
MakePool(const std::string & dir,const std::string & name)85   std::unique_ptr<Pool> MakePool(const std::string& dir,
86                                  const std::string& name) {
87     Label label(SourceDir(dir), name, tc_dir_, tc_name_);
88     return std::make_unique<Pool>(&settings_, label);
89   }
90 
RunAnalyzerTest(const std::string & input,const std::string & expected_output)91   void RunAnalyzerTest(const std::string& input,
92                        const std::string& expected_output) {
93     Analyzer analyzer(builder_, SourceFile("//build/config/BUILDCONFIG.gn"),
94                       SourceFile("//.gn"),
95                       {SourceFile("//out/debug/args.gn"),
96                        SourceFile("//build/default_args.gn")});
97     Err err;
98     std::string actual_output = analyzer.Analyze(input, &err);
99     EXPECT_EQ(err.has_error(), false);
100     EXPECT_EQ(expected_output, actual_output);
101   }
102 
103  protected:
104   scoped_refptr<MockLoader> loader_;
105   Builder builder_;
106   BuildSettings build_settings_;
107 
108   Settings settings_;
109   SourceDir tc_dir_;
110   std::string tc_name_;
111 
112   Settings other_settings_;
113   SourceDir tc_other_dir_;
114   std::string tc_other_name_;
115 };
116 
117 // Tests that a target is marked as affected if its sources are modified.
TEST_F(AnalyzerTest,TargetRefersToSources)118 TEST_F(AnalyzerTest, TargetRefersToSources) {
119   std::unique_ptr<Target> t = MakeTarget("//dir", "target_name");
120   Target* t_raw = t.get();
121   builder_.ItemDefined(std::move(t));
122   RunAnalyzerTest(
123       R"({
124        "files": [ "//dir/file_name.cc" ],
125        "additional_compile_targets": [ "all" ],
126        "test_targets": [ "//dir:target_name" ]
127        })",
128       "{"
129       R"("compile_targets":[],)"
130       R"/("status":"No dependency",)/"
131       R"("test_targets":[])"
132       "}");
133 
134   t_raw->sources().push_back(SourceFile("//dir/file_name.cc"));
135   RunAnalyzerTest(
136       R"({
137        "files": [ "//dir/file_name.cc" ],
138        "additional_compile_targets": [ "all" ],
139        "test_targets": [ "//dir:target_name" ]
140        })",
141       "{"
142       R"("compile_targets":["all"],)"
143       R"/("status":"Found dependency",)/"
144       R"("test_targets":["//dir:target_name"])"
145       "}");
146 }
147 
148 // Tests that a target is marked as affected if its public headers are modified.
TEST_F(AnalyzerTest,TargetRefersToPublicHeaders)149 TEST_F(AnalyzerTest, TargetRefersToPublicHeaders) {
150   std::unique_ptr<Target> t = MakeTarget("//dir", "target_name");
151   Target* t_raw = t.get();
152   builder_.ItemDefined(std::move(t));
153   RunAnalyzerTest(
154       R"({
155        "files": [ "//dir/header_name.h" ],
156        "additional_compile_targets": [ "all" ],
157        "test_targets": [ "//dir:target_name" ]
158        })",
159       "{"
160       R"("compile_targets":[],)"
161       R"/("status":"No dependency",)/"
162       R"("test_targets":[])"
163       "}");
164 
165   t_raw->public_headers().push_back(SourceFile("//dir/header_name.h"));
166   RunAnalyzerTest(
167       R"({
168        "files": [ "//dir/header_name.h" ],
169        "additional_compile_targets": [ "all" ],
170        "test_targets": [ "//dir:target_name" ]
171        })",
172       "{"
173       R"("compile_targets":["all"],)"
174       R"/("status":"Found dependency",)/"
175       R"("test_targets":["//dir:target_name"])"
176       "}");
177 }
178 
179 // Tests that a target is marked as affected if its inputs are modified.
TEST_F(AnalyzerTest,TargetRefersToInputs)180 TEST_F(AnalyzerTest, TargetRefersToInputs) {
181   std::unique_ptr<Target> t = MakeTarget("//dir", "target_name");
182   Target* t_raw = t.get();
183   builder_.ItemDefined(std::move(t));
184   RunAnalyzerTest(
185       R"({
186        "files": [ "//dir/extra_input.cc" ],
187        "additional_compile_targets": [ "all" ],
188        "test_targets": [ "//dir:target_name" ]
189        })",
190       "{"
191       R"("compile_targets":[],)"
192       R"/("status":"No dependency",)/"
193       R"("test_targets":[])"
194       "}");
195 
196   SourceFile extra_input(SourceFile("//dir/extra_input.cc"));
197   t_raw->config_values().inputs().push_back(extra_input);
198   RunAnalyzerTest(
199       R"({
200        "files": [ "//dir/extra_input.cc" ],
201        "additional_compile_targets": [ "all" ],
202        "test_targets": [ "//dir:target_name" ]
203        })",
204       "{"
205       R"("compile_targets":["all"],)"
206       R"/("status":"Found dependency",)/"
207       R"("test_targets":["//dir:target_name"])"
208       "}");
209 
210   t_raw->config_values().inputs().clear();
211   std::unique_ptr<Config> c = MakeConfig("//dir", "config_name");
212   c->own_values().inputs().push_back(extra_input);
213   t_raw->configs().push_back(LabelConfigPair(c.get()));
214   builder_.ItemDefined(std::move(c));
215 
216   RunAnalyzerTest(
217       R"({
218        "files": [ "//dir/extra_input.cc" ],
219        "additional_compile_targets": [ "all" ],
220        "test_targets": [ "//dir:target_name" ]
221        })",
222       "{"
223       R"("compile_targets":["all"],)"
224       R"/("status":"Found dependency",)/"
225       R"("test_targets":["//dir:target_name"])"
226       "}");
227 }
228 
229 // Tests that a target is marked as affected if a sub-config is modified.
230 //
231 // This test uses two levels of sub-configs to ensure the config hierarchy
232 // is completely traversed.
TEST_F(AnalyzerTest,SubConfigIsModified)233 TEST_F(AnalyzerTest, SubConfigIsModified) {
234   std::unique_ptr<Config> ssc = MakeConfig("//dir3", "subsubconfig_name");
235   ssc->build_dependency_files().insert(SourceFile("//dir3/BUILD.gn"));
236 
237   std::unique_ptr<Config> sc = MakeConfig("//dir2", "subconfig_name");
238   sc->configs().push_back(LabelConfigPair(ssc->label()));
239 
240   std::unique_ptr<Config> c = MakeConfig("//dir", "config_name");
241   c->configs().push_back(LabelConfigPair(sc->label()));
242 
243   std::unique_ptr<Target> t = MakeTarget("//dir", "target_name");
244   t->configs().push_back(LabelConfigPair(c.get()));
245 
246   builder_.ItemDefined(std::move(ssc));
247   builder_.ItemDefined(std::move(sc));
248   builder_.ItemDefined(std::move(c));
249   builder_.ItemDefined(std::move(t));
250   RunAnalyzerTest(
251       R"({
252        "files": [ "//dir3/BUILD.gn" ],
253        "additional_compile_targets": [],
254        "test_targets": [ "//dir:target_name" ]
255        })",
256       "{"
257       R"("compile_targets":[],)"
258       R"/("status":"Found dependency",)/"
259       R"("test_targets":["//dir:target_name"])"
260       "}");
261 }
262 
263 // Tests that a target is marked as affected if its data are modified.
TEST_F(AnalyzerTest,TargetRefersToData)264 TEST_F(AnalyzerTest, TargetRefersToData) {
265   std::unique_ptr<Target> t = MakeTarget("//dir", "target_name");
266   Target* t_raw = t.get();
267   builder_.ItemDefined(std::move(t));
268   RunAnalyzerTest(
269       R"({
270        "files": [ "//dir/data.html" ],
271        "additional_compile_targets": [ "all" ],
272        "test_targets": [ "//dir:target_name" ]
273        })",
274       "{"
275       R"("compile_targets":[],)"
276       R"/("status":"No dependency",)/"
277       R"("test_targets":[])"
278       "}");
279 
280   t_raw->data().push_back("//dir/data.html");
281   RunAnalyzerTest(
282       R"({
283        "files": [ "//dir/data.html" ],
284        "additional_compile_targets": [ "all" ],
285        "test_targets": [ "//dir:target_name" ]
286        })",
287       "{"
288       R"("compile_targets":["all"],)"
289       R"/("status":"Found dependency",)/"
290       R"("test_targets":["//dir:target_name"])"
291       "}");
292 }
293 
294 // Tests that a target is marked as affected if the target is an action and its
295 // action script is modified.
TEST_F(AnalyzerTest,TargetRefersToActionScript)296 TEST_F(AnalyzerTest, TargetRefersToActionScript) {
297   std::unique_ptr<Target> t = MakeTarget("//dir", "target_name");
298   Target* t_raw = t.get();
299   t->set_output_type(Target::ACTION);
300   builder_.ItemDefined(std::move(t));
301   RunAnalyzerTest(
302       R"({
303        "files": [ "//dir/script.py" ],
304        "additional_compile_targets": [ "all" ],
305        "test_targets": [ "//dir:target_name" ]
306        })",
307       "{"
308       R"("compile_targets":[],)"
309       R"/("status":"No dependency",)/"
310       R"("test_targets":[])"
311       "}");
312 
313   t_raw->action_values().set_script(SourceFile("//dir/script.py"));
314   RunAnalyzerTest(
315       R"({
316        "files": [ "//dir/script.py" ],
317        "additional_compile_targets": [ "all" ],
318        "test_targets": [ "//dir:target_name" ]
319        })",
320       "{"
321       R"("compile_targets":["all"],)"
322       R"/("status":"Found dependency",)/"
323       R"("test_targets":["//dir:target_name"])"
324       "}");
325 }
326 
327 // Tests that a target is marked as affected if its build dependency files are
328 // modified.
TEST_F(AnalyzerTest,TargetRefersToBuildDependencyFiles)329 TEST_F(AnalyzerTest, TargetRefersToBuildDependencyFiles) {
330   std::unique_ptr<Target> t = MakeTarget("//dir", "target_name");
331   Target* t_raw = t.get();
332   builder_.ItemDefined(std::move(t));
333   RunAnalyzerTest(
334       R"({
335        "files": [ "//dir/BUILD.gn" ],
336        "additional_compile_targets": [ "all" ],
337        "test_targets": [ "//dir:target_name" ]
338        })",
339       "{"
340       R"("compile_targets":[],)"
341       R"/("status":"No dependency",)/"
342       R"("test_targets":[])"
343       "}");
344 
345   t_raw->build_dependency_files().insert(SourceFile("//dir/BUILD.gn"));
346   RunAnalyzerTest(
347       R"({
348        "files": [ "//dir/BUILD.gn" ],
349        "additional_compile_targets": [ "all" ],
350        "test_targets": [ "//dir:target_name" ]
351        })",
352       "{"
353       R"("compile_targets":["all"],)"
354       R"/("status":"Found dependency",)/"
355       R"("test_targets":["//dir:target_name"])"
356       "}");
357 }
358 
359 // Tests that if a target is marked as affected, then it propagates to dependent
360 // test_targets.
TEST_F(AnalyzerTest,AffectedTargetpropagatesToDependentTargets)361 TEST_F(AnalyzerTest, AffectedTargetpropagatesToDependentTargets) {
362   std::unique_ptr<Target> t1 = MakeTarget("//dir", "target_name1");
363   std::unique_ptr<Target> t2 = MakeTarget("//dir", "target_name2");
364   std::unique_ptr<Target> t3 = MakeTarget("//dir", "target_name3");
365   t1->private_deps().push_back(LabelTargetPair(t2.get()));
366   t2->private_deps().push_back(LabelTargetPair(t3.get()));
367   builder_.ItemDefined(std::move(t1));
368   builder_.ItemDefined(std::move(t2));
369 
370   Target* t3_raw = t3.get();
371   builder_.ItemDefined(std::move(t3));
372 
373   RunAnalyzerTest(
374       R"({
375        "files": [ "//dir/BUILD.gn" ],
376        "additional_compile_targets": [ "all" ],
377        "test_targets": [ "//dir:target_name1", "//dir:target_name2" ]
378        })",
379       "{"
380       R"("compile_targets":[],)"
381       R"/("status":"No dependency",)/"
382       R"("test_targets":[])"
383       "}");
384 
385   t3_raw->build_dependency_files().insert(SourceFile("//dir/BUILD.gn"));
386   RunAnalyzerTest(
387       R"({
388        "files": [ "//dir/BUILD.gn" ],
389        "additional_compile_targets": [ "all" ],
390        "test_targets": [ "//dir:target_name1", "//dir:target_name2" ]
391        })",
392       "{"
393       R"("compile_targets":["all"],)"
394       R"/("status":"Found dependency",)/"
395       R"("test_targets":["//dir:target_name1","//dir:target_name2"])"
396       "}");
397 }
398 
399 // Tests that if a config is marked as affected, then it propagates to dependent
400 // test_targets.
TEST_F(AnalyzerTest,AffectedConfigpropagatesToDependentTargets)401 TEST_F(AnalyzerTest, AffectedConfigpropagatesToDependentTargets) {
402   std::unique_ptr<Config> c = MakeConfig("//dir", "config_name");
403   Config* c_raw = c.get();
404   std::unique_ptr<Target> t = MakeTarget("//dir", "target_name");
405   t->configs().push_back(LabelConfigPair(c.get()));
406   builder_.ItemDefined(std::move(t));
407   builder_.ItemDefined(std::move(c));
408   RunAnalyzerTest(
409       R"({
410        "files": [ "//dir/BUILD.gn" ],
411        "additional_compile_targets": [ "all" ],
412        "test_targets": [ "//dir:target_name" ]
413        })",
414       "{"
415       R"("compile_targets":[],)"
416       R"/("status":"No dependency",)/"
417       R"("test_targets":[])"
418       "}");
419 
420   c_raw->build_dependency_files().insert(SourceFile("//dir/BUILD.gn"));
421   RunAnalyzerTest(
422       R"({
423        "files": [ "//dir/BUILD.gn" ],
424        "additional_compile_targets": [ "all" ],
425        "test_targets": [ "//dir:target_name" ]
426        })",
427       "{"
428       R"("compile_targets":["all"],)"
429       R"/("status":"Found dependency",)/"
430       R"("test_targets":["//dir:target_name"])"
431       "}");
432 }
433 
434 // Tests that if toolchain is marked as affected, then it propagates to
435 // dependent test_targets.
TEST_F(AnalyzerTest,AffectedToolchainpropagatesToDependentTargets)436 TEST_F(AnalyzerTest, AffectedToolchainpropagatesToDependentTargets) {
437   std::unique_ptr<Target> target = MakeTarget("//dir", "target_name");
438   target->set_output_type(Target::EXECUTABLE);
439   Toolchain* toolchain = new Toolchain(&settings_, settings_.toolchain_label());
440 
441   // The tool is not used anywhere, but is required to construct the dependency
442   // between a target and the toolchain.
443   std::unique_ptr<Tool> fake_tool = Tool::CreateTool(CTool::kCToolLink);
444   fake_tool->set_outputs(
445       SubstitutionList::MakeForTest("//out/debug/output.txt"));
446   toolchain->SetTool(std::move(fake_tool));
447   builder_.ItemDefined(std::move(target));
448   builder_.ItemDefined(std::unique_ptr<Item>(toolchain));
449 
450   RunAnalyzerTest(
451       R"({
452          "files": [ "//tc/BUILD.gn" ],
453          "additional_compile_targets": [ "all" ],
454          "test_targets": [ "//dir:target_name" ]
455          })",
456       "{"
457       R"("compile_targets":[],)"
458       R"/("status":"No dependency",)/"
459       R"("test_targets":[])"
460       "}");
461 
462   toolchain->build_dependency_files().insert(SourceFile("//tc/BUILD.gn"));
463   RunAnalyzerTest(
464       R"({
465        "files": [ "//tc/BUILD.gn" ],
466        "additional_compile_targets": [ "all" ],
467        "test_targets": [ "//dir:target_name" ]
468        })",
469       "{"
470       R"("compile_targets":["all"],)"
471       R"/("status":"Found dependency",)/"
472       R"("test_targets":["//dir:target_name"])"
473       "}");
474 }
475 
476 // Tests that if a pool is marked as affected, then it propagates to dependent
477 // targets.
TEST_F(AnalyzerTest,AffectedPoolpropagatesToDependentTargets)478 TEST_F(AnalyzerTest, AffectedPoolpropagatesToDependentTargets) {
479   std::unique_ptr<Target> t = MakeTarget("//dir", "target_name");
480   t->set_output_type(Target::ACTION);
481   std::unique_ptr<Pool> p = MakePool("//dir", "pool_name");
482   Pool* p_raw = p.get();
483   t->set_pool(LabelPtrPair<Pool>(p.get()));
484 
485   builder_.ItemDefined(std::move(t));
486   builder_.ItemDefined(std::move(p));
487 
488   RunAnalyzerTest(
489       R"({
490        "files": [ "//dir/BUILD.gn" ],
491        "additional_compile_targets": [ "all" ],
492        "test_targets": [ "//dir:target_name" ]
493        })",
494       "{"
495       R"("compile_targets":[],)"
496       R"/("status":"No dependency",)/"
497       R"("test_targets":[])"
498       "}");
499 
500   p_raw->build_dependency_files().insert(SourceFile("//dir/BUILD.gn"));
501   RunAnalyzerTest(
502       R"({
503        "files": [ "//dir/BUILD.gn" ],
504        "additional_compile_targets": [ "all" ],
505        "test_targets": [ "//dir:target_name" ]
506        })",
507       "{"
508       R"("compile_targets":["all"],)"
509       R"/("status":"Found dependency",)/"
510       R"("test_targets":["//dir:target_name"])"
511       "}");
512 }
513 
514 // Tests that when dependency was found, the "compile_targets" in the output is
515 // not "all".
TEST_F(AnalyzerTest,CompileTargetsAllWasPruned)516 TEST_F(AnalyzerTest, CompileTargetsAllWasPruned) {
517   std::unique_ptr<Target> t1 = MakeTarget("//dir", "target_name1");
518   std::unique_ptr<Target> t2 = MakeTarget("//dir", "target_name2");
519   t2->build_dependency_files().insert(SourceFile("//dir/BUILD.gn"));
520   builder_.ItemDefined(std::move(t1));
521   builder_.ItemDefined(std::move(t2));
522 
523   RunAnalyzerTest(
524       R"({
525        "files": [ "//dir/BUILD.gn" ],
526        "additional_compile_targets": [ "all" ],
527        "test_targets": []
528        })",
529       "{"
530       R"("compile_targets":["//dir:target_name2"],)"
531       R"/("status":"Found dependency",)/"
532       R"("test_targets":[])"
533       "}");
534 }
535 
536 // Tests that output is "No dependency" when no dependency is found.
TEST_F(AnalyzerTest,NoDependency)537 TEST_F(AnalyzerTest, NoDependency) {
538   std::unique_ptr<Target> t = MakeTarget("//dir", "target_name");
539   builder_.ItemDefined(std::move(t));
540 
541   RunAnalyzerTest(
542       R"({
543        "files": [ "//dir/BUILD.gn" ],
544        "additional_compile_targets": [ "all" ],
545        "test_targets": []
546        })",
547       "{"
548       R"("compile_targets":[],)"
549       R"/("status":"No dependency",)/"
550       R"("test_targets":[])"
551       "}");
552 }
553 
554 // Tests that output is "No dependency" when no files or targets are provided.
TEST_F(AnalyzerTest,NoFilesNoTargets)555 TEST_F(AnalyzerTest, NoFilesNoTargets) {
556   RunAnalyzerTest(
557       R"({
558        "files": [],
559        "additional_compile_targets": [],
560        "test_targets": []
561       })",
562       "{"
563       R"("compile_targets":[],)"
564       R"("status":"No dependency",)"
565       R"("test_targets":[])"
566       "}");
567 }
568 
569 // Tests that output displays proper error message when given files aren't
570 // source-absolute or absolute path.
TEST_F(AnalyzerTest,FilesArentSourceAbsolute)571 TEST_F(AnalyzerTest, FilesArentSourceAbsolute) {
572   RunAnalyzerTest(
573       R"({
574        "files": [ "a.cc" ],
575        "additional_compile_targets": [],
576        "test_targets": [ "//dir:target_name" ]
577       })",
578       "{"
579       R"("error":)"
580       R"("\"a.cc\" is not a source-absolute or absolute path.",)"
581       R"("invalid_targets":[])"
582       "}");
583 }
584 
585 // Tests that output displays proper error message when input is ill-formed.
TEST_F(AnalyzerTest,WrongInputFields)586 TEST_F(AnalyzerTest, WrongInputFields) {
587   RunAnalyzerTest(
588       R"({
589        "files": [ "//a.cc" ],
590        "compile_targets": [],
591        "test_targets": [ "//dir:target_name" ]
592       })",
593       "{"
594       R"("error":)"
595       R"("Unknown analyze input key \"compile_targets\".",)"
596       R"("invalid_targets":[])"
597       "}");
598 }
599 
600 // Bails out early with "Found dependency (all)" if dot file is modified.
TEST_F(AnalyzerTest,DotFileWasModified)601 TEST_F(AnalyzerTest, DotFileWasModified) {
602   std::unique_ptr<Target> t = MakeTarget("//dir", "target_name");
603   builder_.ItemDefined(std::move(t));
604 
605   RunAnalyzerTest(
606       R"({
607        "files": [ "//.gn" ],
608        "additional_compile_targets": [],
609        "test_targets": [ "//dir:target_name" ]
610       })",
611       "{"
612       R"("compile_targets":["//dir:target_name"],)"
613       R"/("status":"Found dependency (all)",)/"
614       R"("test_targets":["//dir:target_name"])"
615       "}");
616 }
617 
618 // Bails out early with "Found dependency (all)" if master build config file is
619 // modified.
TEST_F(AnalyzerTest,BuildConfigFileWasModified)620 TEST_F(AnalyzerTest, BuildConfigFileWasModified) {
621   std::unique_ptr<Target> t = MakeTarget("//dir", "target_name");
622   builder_.ItemDefined(std::move(t));
623 
624   RunAnalyzerTest(
625       R"({
626        "files": [ "//build/config/BUILDCONFIG.gn" ],
627        "additional_compile_targets": [],
628        "test_targets": [ "//dir:target_name" ]
629       })",
630       "{"
631       R"("compile_targets":["//dir:target_name"],)"
632       R"/("status":"Found dependency (all)",)/"
633       R"("test_targets":["//dir:target_name"])"
634       "}");
635 }
636 
637 // Bails out early with "Found dependency (all)" if a build args dependency file
638 // is modified.
TEST_F(AnalyzerTest,BuildArgsDependencyFileWasModified)639 TEST_F(AnalyzerTest, BuildArgsDependencyFileWasModified) {
640   std::unique_ptr<Target> t = MakeTarget("//dir", "target_name");
641   builder_.ItemDefined(std::move(t));
642 
643   RunAnalyzerTest(
644       R"({
645        "files": [ "//build/default_args.gn" ],
646        "additional_compile_targets": [],
647        "test_targets": [ "//dir:target_name" ]
648       })",
649       "{"
650       R"("compile_targets":["//dir:target_name"],)"
651       R"/("status":"Found dependency (all)",)/"
652       R"("test_targets":["//dir:target_name"])"
653       "}");
654 }
655 
656 // Tests that targets in explicitly labelled with the default toolchain are
657 // included when their sources change.
658 // change.
TEST_F(AnalyzerTest,TargetToolchainSpecifiedRefersToSources)659 TEST_F(AnalyzerTest, TargetToolchainSpecifiedRefersToSources) {
660   std::unique_ptr<Target> t = MakeTarget("//dir", "target_name");
661   Target* t_raw = t.get();
662   builder_.ItemDefined(std::move(t));
663 
664   RunAnalyzerTest(
665       R"/({
666        "files": [ "//dir/file_name.cc" ],
667        "additional_compile_targets": ["all"],
668        "test_targets": [ "//dir:target_name(//tc:default)" ]
669        })/",
670       "{"
671       R"("compile_targets":[],)"
672       R"/("status":"No dependency",)/"
673       R"("test_targets":[])"
674       "}");
675 
676   t_raw->sources().push_back(SourceFile("//dir/file_name.cc"));
677 
678   RunAnalyzerTest(
679       R"*({
680        "files": [ "//dir/file_name.cc" ],
681        "additional_compile_targets": [],
682        "test_targets": [ "//dir:target_name(//tc:default)" ]
683        })*",
684       "{"
685       R"("compile_targets":[],)"
686       R"/("status":"Found dependency",)/"
687       R"/("test_targets":["//dir:target_name"])/"
688       "}");
689 }
690 
691 // Tests that targets in alternate toolchains are affected when their sources
692 // change.
TEST_F(AnalyzerTest,TargetAlternateToolchainRefersToSources)693 TEST_F(AnalyzerTest, TargetAlternateToolchainRefersToSources) {
694   std::unique_ptr<Target> t = MakeTarget("//dir", "target_name");
695   std::unique_ptr<Target> t_alt =
696       MakeTargetOtherToolchain("//dir", "target_name");
697   Target* t_raw = t.get();
698   Target* t_alt_raw = t_alt.get();
699   builder_.ItemDefined(std::move(t));
700   builder_.ItemDefined(std::move(t_alt));
701 
702   RunAnalyzerTest(
703       R"/({
704        "files": [ "//dir/file_name.cc" ],
705        "additional_compile_targets": ["all"],
706        "test_targets": [ "//dir:target_name", "//dir:target_name(//other:tc)" ]
707        })/",
708       "{"
709       R"("compile_targets":[],)"
710       R"/("status":"No dependency",)/"
711       R"("test_targets":[])"
712       "}");
713 
714   t_raw->sources().push_back(SourceFile("//dir/file_name.cc"));
715   t_alt_raw->sources().push_back(SourceFile("//dir/alt_file_name.cc"));
716 
717   RunAnalyzerTest(
718       R"*({
719        "files": [ "//dir/file_name.cc" ],
720        "additional_compile_targets": [],
721        "test_targets": [ "//dir:target_name", "//dir:target_name(//other:tc)" ]
722        })*",
723       "{"
724       R"("compile_targets":[],)"
725       R"/("status":"Found dependency",)/"
726       R"("test_targets":["//dir:target_name"])"
727       "}");
728 
729   RunAnalyzerTest(
730       R"*({
731        "files": [ "//dir/alt_file_name.cc" ],
732        "additional_compile_targets": [],
733        "test_targets": [ "//dir:target_name", "//dir:target_name(//other:tc)" ]
734        })*",
735       "{"
736       R"("compile_targets":[],)"
737       R"/("status":"Found dependency",)/"
738       R"/("test_targets":["//dir:target_name(//other:tc)"])/"
739       "}");
740 
741   RunAnalyzerTest(
742       R"*({
743        "files": [ "//dir/file_name.cc", "//dir/alt_file_name.cc" ],
744        "additional_compile_targets": [],
745        "test_targets": [ "//dir:target_name", "//dir:target_name(//other:tc)" ]
746        })*",
747       "{"
748       R"("compile_targets":[],)"
749       R"/("status":"Found dependency",)/"
750       R"/("test_targets":["//dir:target_name","//dir:target_name(//other:tc)"])/"
751       "}");
752 }
753 
754 }  // namespace gn_analyzer_unittest
755