Home | History | Annotate | Download | only in gn
      1 // Copyright (c) 2013 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/escape.h"
      9 #include "tools/gn/file_template.h"
     10 #include "tools/gn/test_with_scope.h"
     11 
     12 TEST(FileTemplate, Static) {
     13   TestWithScope setup;
     14 
     15   std::vector<std::string> templates;
     16   templates.push_back("something_static");
     17   FileTemplate t(setup.settings(), templates);
     18   EXPECT_FALSE(t.has_substitutions());
     19 
     20   std::vector<std::string> result;
     21   t.Apply(SourceFile("//foo/bar"), &result);
     22   ASSERT_EQ(1u, result.size());
     23   EXPECT_EQ("something_static", result[0]);
     24 }
     25 
     26 TEST(FileTemplate, Typical) {
     27   TestWithScope setup;
     28 
     29   std::vector<std::string> templates;
     30   templates.push_back("foo/{{source_name_part}}.cc");
     31   templates.push_back("foo/{{source_name_part}}.h");
     32   FileTemplate t(setup.settings(), templates);
     33   EXPECT_TRUE(t.has_substitutions());
     34 
     35   std::vector<std::string> result;
     36   t.Apply(SourceFile("//sources/ha.idl"), &result);
     37   ASSERT_EQ(2u, result.size());
     38   EXPECT_EQ("foo/ha.cc", result[0]);
     39   EXPECT_EQ("foo/ha.h", result[1]);
     40 }
     41 
     42 TEST(FileTemplate, Weird) {
     43   TestWithScope setup;
     44 
     45   std::vector<std::string> templates;
     46   templates.push_back("{{{source}}{{source}}{{");
     47   FileTemplate t(setup.settings(), templates);
     48   EXPECT_TRUE(t.has_substitutions());
     49 
     50   std::vector<std::string> result;
     51   t.Apply(SourceFile("//foo/lalala.c"), &result);
     52   ASSERT_EQ(1u, result.size());
     53   EXPECT_EQ("{../../foo/lalala.c../../foo/lalala.c{{", result[0]);
     54 }
     55 
     56 TEST(FileTemplate, NinjaExpansions) {
     57   TestWithScope setup;
     58 
     59   std::vector<std::string> templates;
     60   templates.push_back("-i");
     61   templates.push_back("{{source}}");
     62   templates.push_back("--out=foo bar\"{{source_name_part}}\".o");
     63   templates.push_back("");  // Test empty string.
     64 
     65   FileTemplate t(setup.settings(), templates);
     66 
     67   std::ostringstream out;
     68   t.WriteWithNinjaExpansions(out);
     69 
     70 #if defined(OS_WIN)
     71   // The third argument should get quoted since it contains a space, and the
     72   // embedded quotes should get shell escaped.
     73   EXPECT_EQ(
     74       " -i ${source} \"--out=foo$ bar\\\"${source_name_part}\\\".o\" \"\"",
     75       out.str());
     76 #else
     77   // On Posix we don't need to quote the whole thing and can escape all
     78   // individual bad chars.
     79   EXPECT_EQ(
     80       " -i ${source} --out=foo\\$ bar\\\"${source_name_part}\\\".o \"\"",
     81       out.str());
     82 #endif
     83 }
     84 
     85 TEST(FileTemplate, NinjaVariables) {
     86   TestWithScope setup;
     87 
     88   std::vector<std::string> templates;
     89   templates.push_back("-i");
     90   templates.push_back("{{source}}");
     91   templates.push_back("--out=foo bar\"{{source_name_part}}\".o");
     92   templates.push_back("{{source_file_part}}");
     93   templates.push_back("{{source_dir}}");
     94   templates.push_back("{{source_root_relative_dir}}");
     95   templates.push_back("{{source_gen_dir}}");
     96   templates.push_back("{{source_out_dir}}");
     97 
     98   FileTemplate t(setup.settings(), templates);
     99 
    100   std::ostringstream out;
    101   EscapeOptions options;
    102   options.mode = ESCAPE_NINJA_COMMAND;
    103   t.WriteNinjaVariablesForSubstitution(out, setup.settings(),
    104                                        SourceFile("//foo/bar.txt"), options);
    105 
    106   // Just the variables used above should be written.
    107   EXPECT_EQ(
    108       "  source = ../../foo/bar.txt\n"
    109       "  source_name_part = bar\n"
    110       "  source_file_part = bar.txt\n"
    111       "  source_dir = ../../foo\n"
    112       "  source_root_rel_dir = foo\n"
    113       "  source_gen_dir = gen/foo\n"
    114       "  source_out_dir = obj/foo\n",
    115       out.str());
    116 }
    117 
    118 // Tests in isolation different types of substitutions and that the right
    119 // things are generated.
    120 TEST(FileTemplate, Substitutions) {
    121   TestWithScope setup;
    122 
    123   #define GetSubst(str, what) \
    124       FileTemplate::GetSubstitution(setup.settings(), \
    125                                     SourceFile(str), \
    126                                     FileTemplate::Subrange::what)
    127 
    128   // Try all possible templates with a normal looking string.
    129   EXPECT_EQ("../../foo/bar/baz.txt", GetSubst("//foo/bar/baz.txt", SOURCE));
    130   EXPECT_EQ("baz", GetSubst("//foo/bar/baz.txt", NAME_PART));
    131   EXPECT_EQ("baz.txt", GetSubst("//foo/bar/baz.txt", FILE_PART));
    132   EXPECT_EQ("../../foo/bar", GetSubst("//foo/bar/baz.txt", SOURCE_DIR));
    133   EXPECT_EQ("foo/bar", GetSubst("//foo/bar/baz.txt", ROOT_RELATIVE_DIR));
    134   EXPECT_EQ("gen/foo/bar", GetSubst("//foo/bar/baz.txt", SOURCE_GEN_DIR));
    135   EXPECT_EQ("obj/foo/bar", GetSubst("//foo/bar/baz.txt", SOURCE_OUT_DIR));
    136 
    137   // Operations on an absolute path.
    138   EXPECT_EQ("/baz.txt", GetSubst("/baz.txt", SOURCE));
    139   EXPECT_EQ("/.", GetSubst("/baz.txt", SOURCE_DIR));
    140   EXPECT_EQ("gen", GetSubst("/baz.txt", SOURCE_GEN_DIR));
    141   EXPECT_EQ("obj", GetSubst("/baz.txt", SOURCE_OUT_DIR));
    142 
    143   EXPECT_EQ(".", GetSubst("//baz.txt", ROOT_RELATIVE_DIR));
    144 
    145   #undef GetSubst
    146 }
    147