Home | History | Annotate | Download | only in gn
      1 // Copyright 2014 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 <sstream>
      6 
      7 #include "testing/gtest/include/gtest/gtest.h"
      8 #include "tools/gn/ninja_target_writer.h"
      9 #include "tools/gn/target.h"
     10 #include "tools/gn/test_with_scope.h"
     11 
     12 namespace {
     13 
     14 class TestingNinjaTargetWriter : public NinjaTargetWriter {
     15  public:
     16   TestingNinjaTargetWriter(const Target* target,
     17                            const Toolchain* toolchain,
     18                            std::ostream& out)
     19       : NinjaTargetWriter(target, out) {
     20   }
     21 
     22   virtual void Run() OVERRIDE {}
     23 
     24   // Make this public so the test can call it.
     25   OutputFile WriteInputDepsStampAndGetDep(
     26       const std::vector<const Target*>& extra_hard_deps) {
     27     return NinjaTargetWriter::WriteInputDepsStampAndGetDep(extra_hard_deps);
     28   }
     29 };
     30 
     31 }  // namespace
     32 
     33 TEST(NinjaTargetWriter, WriteInputDepsStampAndGetDep) {
     34   TestWithScope setup;
     35   Err err;
     36 
     37   // Make a base target that's a hard dep (action).
     38   Target base_target(setup.settings(), Label(SourceDir("//foo/"), "base"));
     39   base_target.set_output_type(Target::ACTION);
     40   base_target.visibility().SetPublic();
     41   base_target.SetToolchain(setup.toolchain());
     42   base_target.action_values().set_script(SourceFile("//foo/script.py"));
     43 
     44   // Dependent target that also includes a source prerequisite (should get
     45   // included) and a source (should not be included).
     46   Target target(setup.settings(), Label(SourceDir("//foo/"), "target"));
     47   target.set_output_type(Target::EXECUTABLE);
     48   target.visibility().SetPublic();
     49   target.SetToolchain(setup.toolchain());
     50   target.inputs().push_back(SourceFile("//foo/input.txt"));
     51   target.sources().push_back(SourceFile("//foo/source.txt"));
     52   target.public_deps().push_back(LabelTargetPair(&base_target));
     53 
     54   // Dependent action to test that action sources will be treated the same as
     55   // inputs.
     56   Target action(setup.settings(), Label(SourceDir("//foo/"), "action"));
     57   action.set_output_type(Target::ACTION);
     58   action.visibility().SetPublic();
     59   action.SetToolchain(setup.toolchain());
     60   action.action_values().set_script(SourceFile("//foo/script.py"));
     61   action.sources().push_back(SourceFile("//foo/action_source.txt"));
     62   action.public_deps().push_back(LabelTargetPair(&target));
     63 
     64   ASSERT_TRUE(base_target.OnResolved(&err));
     65   ASSERT_TRUE(target.OnResolved(&err));
     66   ASSERT_TRUE(action.OnResolved(&err));
     67 
     68   // Input deps for the base (should be only the script itself).
     69   {
     70     std::ostringstream stream;
     71     TestingNinjaTargetWriter writer(&base_target, setup.toolchain(), stream);
     72     OutputFile dep =
     73         writer.WriteInputDepsStampAndGetDep(std::vector<const Target*>());
     74 
     75     EXPECT_EQ("obj/foo/base.inputdeps.stamp", dep.value());
     76     EXPECT_EQ("build obj/foo/base.inputdeps.stamp: stamp "
     77                   "../../foo/script.py\n",
     78               stream.str());
     79   }
     80 
     81   // Input deps for the target (should depend on the base).
     82   {
     83     std::ostringstream stream;
     84     TestingNinjaTargetWriter writer(&target, setup.toolchain(), stream);
     85     OutputFile dep =
     86         writer.WriteInputDepsStampAndGetDep(std::vector<const Target*>());
     87 
     88     EXPECT_EQ("obj/foo/target.inputdeps.stamp", dep.value());
     89     EXPECT_EQ("build obj/foo/target.inputdeps.stamp: stamp "
     90                   "../../foo/input.txt obj/foo/base.stamp\n",
     91               stream.str());
     92   }
     93 
     94   // Input deps for action which should depend on the base since its a hard dep
     95   // that is a (indirect) dependency, as well as the the action source.
     96   {
     97     std::ostringstream stream;
     98     TestingNinjaTargetWriter writer(&action, setup.toolchain(), stream);
     99     OutputFile dep =
    100         writer.WriteInputDepsStampAndGetDep(std::vector<const Target*>());
    101 
    102     EXPECT_EQ("obj/foo/action.inputdeps.stamp", dep.value());
    103     EXPECT_EQ("build obj/foo/action.inputdeps.stamp: stamp ../../foo/script.py "
    104                   "../../foo/action_source.txt obj/foo/base.stamp\n",
    105               stream.str());
    106   }
    107 }
    108 
    109 // Tests WriteInputDepsStampAndGetDep when toolchain deps are present.
    110 TEST(NinjaTargetWriter, WriteInputDepsStampAndGetDepWithToolchainDeps) {
    111   TestWithScope setup;
    112   Err err;
    113 
    114   // Toolchain dependency. Here we make a target in the same toolchain for
    115   // simplicity, but in real life (using the Builder) this would be rejected
    116   // because it would be a circular dependency (the target depends on its
    117   // toolchain, and the toolchain depends on this target).
    118   Target toolchain_dep_target(setup.settings(),
    119                               Label(SourceDir("//foo/"), "setup"));
    120   toolchain_dep_target.set_output_type(Target::ACTION);
    121   toolchain_dep_target.SetToolchain(setup.toolchain());
    122   ASSERT_TRUE(toolchain_dep_target.OnResolved(&err));
    123   setup.toolchain()->deps().push_back(LabelTargetPair(&toolchain_dep_target));
    124 
    125   // Make a binary target
    126   Target target(setup.settings(), Label(SourceDir("//foo/"), "target"));
    127   target.set_output_type(Target::EXECUTABLE);
    128   target.SetToolchain(setup.toolchain());
    129   ASSERT_TRUE(target.OnResolved(&err));
    130 
    131   std::ostringstream stream;
    132   TestingNinjaTargetWriter writer(&target, setup.toolchain(), stream);
    133   OutputFile dep =
    134       writer.WriteInputDepsStampAndGetDep(std::vector<const Target*>());
    135 
    136   EXPECT_EQ("obj/foo/target.inputdeps.stamp", dep.value());
    137   EXPECT_EQ("build obj/foo/target.inputdeps.stamp: stamp "
    138                 "obj/foo/setup.stamp\n",
    139             stream.str());
    140 }
    141