2019-01-31 02:32:39 +01:00
// Copyright 2019 Google Inc. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package android
import (
2019-02-02 01:42:32 +01:00
"fmt"
2019-01-31 02:32:39 +01:00
"path/filepath"
"reflect"
2019-02-02 01:42:32 +01:00
"strings"
2019-01-31 02:32:39 +01:00
"testing"
2019-04-12 20:11:38 +02:00
"github.com/google/blueprint"
"android/soong/shared"
2019-01-31 02:32:39 +01:00
)
2019-02-15 19:39:37 +01:00
func pathContext ( ) PathContext {
return PathContextForTesting ( TestConfig ( "out" , nil ) ,
map [ string ] [ ] byte {
"ld" : nil ,
"a.o" : nil ,
"b.o" : nil ,
"cp" : nil ,
"a" : nil ,
"b" : nil ,
"ls" : nil ,
"turbine" : nil ,
"java" : nil ,
2019-07-11 19:59:15 +02:00
"javac" : nil ,
2019-02-15 19:39:37 +01:00
} )
}
2019-02-02 01:42:32 +01:00
func ExampleRuleBuilder ( ) {
rule := NewRuleBuilder ( )
2019-02-15 19:39:37 +01:00
ctx := pathContext ( )
rule . Command ( ) .
Tool ( PathForSource ( ctx , "ld" ) ) .
Inputs ( PathsForTesting ( "a.o" , "b.o" ) ) .
FlagWithOutput ( "-o " , PathForOutput ( ctx , "linked" ) )
2019-02-02 01:42:32 +01:00
rule . Command ( ) . Text ( "echo success" )
// To add the command to the build graph:
// rule.Build(pctx, ctx, "link", "link")
fmt . Printf ( "commands: %q\n" , strings . Join ( rule . Commands ( ) , " && " ) )
fmt . Printf ( "tools: %q\n" , rule . Tools ( ) )
fmt . Printf ( "inputs: %q\n" , rule . Inputs ( ) )
fmt . Printf ( "outputs: %q\n" , rule . Outputs ( ) )
// Output:
2019-02-15 19:39:37 +01:00
// commands: "ld a.o b.o -o out/linked && echo success"
2019-02-02 01:42:32 +01:00
// tools: ["ld"]
// inputs: ["a.o" "b.o"]
2019-02-15 19:39:37 +01:00
// outputs: ["out/linked"]
2019-02-02 01:42:32 +01:00
}
2019-02-03 06:25:18 +01:00
func ExampleRuleBuilder_Temporary ( ) {
rule := NewRuleBuilder ( )
2019-02-15 19:39:37 +01:00
ctx := pathContext ( )
rule . Command ( ) .
Tool ( PathForSource ( ctx , "cp" ) ) .
Input ( PathForSource ( ctx , "a" ) ) .
Output ( PathForOutput ( ctx , "b" ) )
rule . Command ( ) .
Tool ( PathForSource ( ctx , "cp" ) ) .
Input ( PathForOutput ( ctx , "b" ) ) .
Output ( PathForOutput ( ctx , "c" ) )
rule . Temporary ( PathForOutput ( ctx , "b" ) )
2019-02-03 06:25:18 +01:00
fmt . Printf ( "commands: %q\n" , strings . Join ( rule . Commands ( ) , " && " ) )
fmt . Printf ( "tools: %q\n" , rule . Tools ( ) )
fmt . Printf ( "inputs: %q\n" , rule . Inputs ( ) )
fmt . Printf ( "outputs: %q\n" , rule . Outputs ( ) )
// Output:
2019-02-15 19:39:37 +01:00
// commands: "cp a out/b && cp out/b out/c"
2019-02-03 06:25:18 +01:00
// tools: ["cp"]
// inputs: ["a"]
2019-02-15 19:39:37 +01:00
// outputs: ["out/c"]
2019-02-03 06:25:18 +01:00
}
func ExampleRuleBuilder_DeleteTemporaryFiles ( ) {
rule := NewRuleBuilder ( )
2019-02-15 19:39:37 +01:00
ctx := pathContext ( )
rule . Command ( ) .
Tool ( PathForSource ( ctx , "cp" ) ) .
Input ( PathForSource ( ctx , "a" ) ) .
Output ( PathForOutput ( ctx , "b" ) )
rule . Command ( ) .
Tool ( PathForSource ( ctx , "cp" ) ) .
Input ( PathForOutput ( ctx , "b" ) ) .
Output ( PathForOutput ( ctx , "c" ) )
rule . Temporary ( PathForOutput ( ctx , "b" ) )
2019-02-03 06:25:18 +01:00
rule . DeleteTemporaryFiles ( )
fmt . Printf ( "commands: %q\n" , strings . Join ( rule . Commands ( ) , " && " ) )
fmt . Printf ( "tools: %q\n" , rule . Tools ( ) )
fmt . Printf ( "inputs: %q\n" , rule . Inputs ( ) )
fmt . Printf ( "outputs: %q\n" , rule . Outputs ( ) )
// Output:
2019-02-15 19:39:37 +01:00
// commands: "cp a out/b && cp out/b out/c && rm -f out/b"
2019-02-03 06:25:18 +01:00
// tools: ["cp"]
// inputs: ["a"]
2019-02-15 19:39:37 +01:00
// outputs: ["out/c"]
2019-02-03 06:25:18 +01:00
}
2019-02-11 23:11:09 +01:00
func ExampleRuleBuilder_Installs ( ) {
rule := NewRuleBuilder ( )
2019-02-15 19:39:37 +01:00
ctx := pathContext ( )
out := PathForOutput ( ctx , "linked" )
rule . Command ( ) .
Tool ( PathForSource ( ctx , "ld" ) ) .
Inputs ( PathsForTesting ( "a.o" , "b.o" ) ) .
FlagWithOutput ( "-o " , out )
rule . Install ( out , "/bin/linked" )
rule . Install ( out , "/sbin/linked" )
2019-02-11 23:11:09 +01:00
fmt . Printf ( "rule.Installs().String() = %q\n" , rule . Installs ( ) . String ( ) )
// Output:
2019-02-15 19:39:37 +01:00
// rule.Installs().String() = "out/linked:/bin/linked out/linked:/sbin/linked"
2019-02-11 23:11:09 +01:00
}
2019-02-02 01:42:32 +01:00
func ExampleRuleBuilderCommand ( ) {
rule := NewRuleBuilder ( )
2019-02-15 19:39:37 +01:00
ctx := pathContext ( )
2019-02-02 01:42:32 +01:00
// chained
2019-02-15 19:39:37 +01:00
rule . Command ( ) .
Tool ( PathForSource ( ctx , "ld" ) ) .
Inputs ( PathsForTesting ( "a.o" , "b.o" ) ) .
FlagWithOutput ( "-o " , PathForOutput ( ctx , "linked" ) )
2019-02-02 01:42:32 +01:00
// unchained
cmd := rule . Command ( )
2019-02-15 19:39:37 +01:00
cmd . Tool ( PathForSource ( ctx , "ld" ) )
cmd . Inputs ( PathsForTesting ( "a.o" , "b.o" ) )
cmd . FlagWithOutput ( "-o " , PathForOutput ( ctx , "linked" ) )
2019-02-02 01:42:32 +01:00
// mixed:
2019-02-15 19:39:37 +01:00
cmd = rule . Command ( ) . Tool ( PathForSource ( ctx , "ld" ) )
cmd . Inputs ( PathsForTesting ( "a.o" , "b.o" ) )
cmd . FlagWithOutput ( "-o " , PathForOutput ( ctx , "linked" ) )
2019-02-02 01:42:32 +01:00
}
func ExampleRuleBuilderCommand_Flag ( ) {
2019-02-15 19:39:37 +01:00
ctx := pathContext ( )
2019-02-02 01:42:32 +01:00
fmt . Println ( NewRuleBuilder ( ) . Command ( ) .
2019-02-15 19:39:37 +01:00
Tool ( PathForSource ( ctx , "ls" ) ) . Flag ( "-l" ) )
2019-02-02 01:42:32 +01:00
// Output:
// ls -l
}
2019-03-29 23:32:51 +01:00
func ExampleRuleBuilderCommand_Flags ( ) {
ctx := pathContext ( )
fmt . Println ( NewRuleBuilder ( ) . Command ( ) .
Tool ( PathForSource ( ctx , "ls" ) ) . Flags ( [ ] string { "-l" , "-a" } ) )
// Output:
// ls -l -a
}
2019-02-02 01:42:32 +01:00
func ExampleRuleBuilderCommand_FlagWithArg ( ) {
2019-02-15 19:39:37 +01:00
ctx := pathContext ( )
2019-02-02 01:42:32 +01:00
fmt . Println ( NewRuleBuilder ( ) . Command ( ) .
2019-02-15 19:39:37 +01:00
Tool ( PathForSource ( ctx , "ls" ) ) .
2019-02-02 01:42:32 +01:00
FlagWithArg ( "--sort=" , "time" ) )
// Output:
// ls --sort=time
}
2019-02-11 23:11:09 +01:00
func ExampleRuleBuilderCommand_FlagForEachArg ( ) {
2019-02-15 19:39:37 +01:00
ctx := pathContext ( )
2019-02-11 23:11:09 +01:00
fmt . Println ( NewRuleBuilder ( ) . Command ( ) .
2019-02-15 19:39:37 +01:00
Tool ( PathForSource ( ctx , "ls" ) ) .
2019-02-11 23:11:09 +01:00
FlagForEachArg ( "--sort=" , [ ] string { "time" , "size" } ) )
// Output:
// ls --sort=time --sort=size
}
2019-02-02 01:42:32 +01:00
func ExampleRuleBuilderCommand_FlagForEachInput ( ) {
2019-02-15 19:39:37 +01:00
ctx := pathContext ( )
2019-02-02 01:42:32 +01:00
fmt . Println ( NewRuleBuilder ( ) . Command ( ) .
2019-02-15 19:39:37 +01:00
Tool ( PathForSource ( ctx , "turbine" ) ) .
FlagForEachInput ( "--classpath " , PathsForTesting ( "a.jar" , "b.jar" ) ) )
2019-02-02 01:42:32 +01:00
// Output:
// turbine --classpath a.jar --classpath b.jar
}
func ExampleRuleBuilderCommand_FlagWithInputList ( ) {
2019-02-15 19:39:37 +01:00
ctx := pathContext ( )
2019-02-02 01:42:32 +01:00
fmt . Println ( NewRuleBuilder ( ) . Command ( ) .
2019-02-15 19:39:37 +01:00
Tool ( PathForSource ( ctx , "java" ) ) .
FlagWithInputList ( "-classpath=" , PathsForTesting ( "a.jar" , "b.jar" ) , ":" ) )
2019-02-02 01:42:32 +01:00
// Output:
// java -classpath=a.jar:b.jar
}
func ExampleRuleBuilderCommand_FlagWithInput ( ) {
2019-02-15 19:39:37 +01:00
ctx := pathContext ( )
2019-02-02 01:42:32 +01:00
fmt . Println ( NewRuleBuilder ( ) . Command ( ) .
2019-02-15 19:39:37 +01:00
Tool ( PathForSource ( ctx , "java" ) ) .
FlagWithInput ( "-classpath=" , PathForSource ( ctx , "a" ) ) )
2019-02-02 01:42:32 +01:00
// Output:
// java -classpath=a
}
func ExampleRuleBuilderCommand_FlagWithList ( ) {
2019-02-15 19:39:37 +01:00
ctx := pathContext ( )
2019-02-02 01:42:32 +01:00
fmt . Println ( NewRuleBuilder ( ) . Command ( ) .
2019-02-15 19:39:37 +01:00
Tool ( PathForSource ( ctx , "ls" ) ) .
2019-02-02 01:42:32 +01:00
FlagWithList ( "--sort=" , [ ] string { "time" , "size" } , "," ) )
// Output:
// ls --sort=time,size
}
2019-07-11 19:59:15 +02:00
func ExampleRuleBuilderCommand_FlagWithRspFileInputList ( ) {
ctx := pathContext ( )
fmt . Println ( NewRuleBuilder ( ) . Command ( ) .
Tool ( PathForSource ( ctx , "javac" ) ) .
FlagWithRspFileInputList ( "@" , PathsForTesting ( "a.java" , "b.java" ) ) .
NinjaEscapedString ( ) )
// Output:
// javac @$out.rsp
}
func ExampleRuleBuilderCommand_String ( ) {
fmt . Println ( NewRuleBuilder ( ) . Command ( ) .
Text ( "FOO=foo" ) .
Text ( "echo $FOO" ) .
String ( ) )
// Output:
// FOO=foo echo $FOO
}
func ExampleRuleBuilderCommand_NinjaEscapedString ( ) {
fmt . Println ( NewRuleBuilder ( ) . Command ( ) .
Text ( "FOO=foo" ) .
Text ( "echo $FOO" ) .
NinjaEscapedString ( ) )
// Output:
// FOO=foo echo $$FOO
}
2019-01-31 02:32:39 +01:00
func TestRuleBuilder ( t * testing . T ) {
2019-02-15 19:39:37 +01:00
fs := map [ string ] [ ] byte {
2019-03-29 23:33:06 +01:00
"dep_fixer" : nil ,
"input" : nil ,
"Implicit" : nil ,
"Input" : nil ,
"Tool" : nil ,
"input2" : nil ,
"tool2" : nil ,
"input3" : nil ,
2019-02-15 19:39:37 +01:00
}
ctx := PathContextForTesting ( TestConfig ( "out" , nil ) , fs )
2019-04-12 20:11:38 +02:00
addCommands := func ( rule * RuleBuilder ) {
cmd := rule . Command ( ) .
DepFile ( PathForOutput ( ctx , "DepFile" ) ) .
Flag ( "Flag" ) .
FlagWithArg ( "FlagWithArg=" , "arg" ) .
FlagWithDepFile ( "FlagWithDepFile=" , PathForOutput ( ctx , "depfile" ) ) .
FlagWithInput ( "FlagWithInput=" , PathForSource ( ctx , "input" ) ) .
FlagWithOutput ( "FlagWithOutput=" , PathForOutput ( ctx , "output" ) ) .
Implicit ( PathForSource ( ctx , "Implicit" ) ) .
ImplicitDepFile ( PathForOutput ( ctx , "ImplicitDepFile" ) ) .
ImplicitOutput ( PathForOutput ( ctx , "ImplicitOutput" ) ) .
Input ( PathForSource ( ctx , "Input" ) ) .
Output ( PathForOutput ( ctx , "Output" ) ) .
Text ( "Text" ) .
Tool ( PathForSource ( ctx , "Tool" ) )
rule . Command ( ) .
Text ( "command2" ) .
DepFile ( PathForOutput ( ctx , "depfile2" ) ) .
Input ( PathForSource ( ctx , "input2" ) ) .
Output ( PathForOutput ( ctx , "output2" ) ) .
Tool ( PathForSource ( ctx , "tool2" ) )
// Test updates to the first command after the second command has been started
cmd . Text ( "after command2" )
// Test updating a command when the previous update did not replace the cmd variable
cmd . Text ( "old cmd" )
// Test a command that uses the output of a previous command as an input
rule . Command ( ) .
Text ( "command3" ) .
Input ( PathForSource ( ctx , "input3" ) ) .
Input ( PathForOutput ( ctx , "output2" ) ) .
Output ( PathForOutput ( ctx , "output3" ) )
2019-01-31 02:32:39 +01:00
}
2019-03-29 23:33:06 +01:00
2019-02-15 19:39:37 +01:00
wantInputs := PathsForSource ( ctx , [ ] string { "Implicit" , "Input" , "input" , "input2" , "input3" } )
wantOutputs := PathsForOutput ( ctx , [ ] string { "ImplicitOutput" , "Output" , "output" , "output2" , "output3" } )
2019-03-29 23:33:06 +01:00
wantDepFiles := PathsForOutput ( ctx , [ ] string { "DepFile" , "depfile" , "ImplicitDepFile" , "depfile2" } )
2019-02-15 19:39:37 +01:00
wantTools := PathsForSource ( ctx , [ ] string { "Tool" , "tool2" } )
2019-01-31 02:32:39 +01:00
2019-04-12 20:11:38 +02:00
t . Run ( "normal" , func ( t * testing . T ) {
rule := NewRuleBuilder ( )
addCommands ( rule )
2019-03-29 23:33:06 +01:00
2019-04-12 20:11:38 +02:00
wantCommands := [ ] string {
"out/DepFile Flag FlagWithArg=arg FlagWithDepFile=out/depfile FlagWithInput=input FlagWithOutput=out/output Input out/Output Text Tool after command2 old cmd" ,
"command2 out/depfile2 input2 out/output2 tool2" ,
"command3 input3 out/output2 out/output3" ,
}
2019-03-29 23:33:06 +01:00
2019-04-12 20:11:38 +02:00
wantDepMergerCommand := "out/host/" + ctx . Config ( ) . PrebuiltOS ( ) + "/bin/dep_fixer out/DepFile out/depfile out/ImplicitDepFile out/depfile2"
if g , w := rule . Commands ( ) , wantCommands ; ! reflect . DeepEqual ( g , w ) {
t . Errorf ( "\nwant rule.Commands() = %#v\n got %#v" , w , g )
}
if g , w := rule . Inputs ( ) , wantInputs ; ! reflect . DeepEqual ( w , g ) {
t . Errorf ( "\nwant rule.Inputs() = %#v\n got %#v" , w , g )
}
if g , w := rule . Outputs ( ) , wantOutputs ; ! reflect . DeepEqual ( w , g ) {
t . Errorf ( "\nwant rule.Outputs() = %#v\n got %#v" , w , g )
}
if g , w := rule . DepFiles ( ) , wantDepFiles ; ! reflect . DeepEqual ( w , g ) {
t . Errorf ( "\nwant rule.DepFiles() = %#v\n got %#v" , w , g )
}
if g , w := rule . Tools ( ) , wantTools ; ! reflect . DeepEqual ( w , g ) {
t . Errorf ( "\nwant rule.Tools() = %#v\n got %#v" , w , g )
}
if g , w := rule . depFileMergerCmd ( ctx , rule . DepFiles ( ) ) . String ( ) , wantDepMergerCommand ; g != w {
t . Errorf ( "\nwant rule.depFileMergerCmd() = %#v\n got %#v" , w , g )
}
} )
t . Run ( "sbox" , func ( t * testing . T ) {
rule := NewRuleBuilder ( ) . Sbox ( PathForOutput ( ctx ) )
addCommands ( rule )
wantCommands := [ ] string {
"__SBOX_OUT_DIR__/DepFile Flag FlagWithArg=arg FlagWithDepFile=__SBOX_OUT_DIR__/depfile FlagWithInput=input FlagWithOutput=__SBOX_OUT_DIR__/output Input __SBOX_OUT_DIR__/Output Text Tool after command2 old cmd" ,
"command2 __SBOX_OUT_DIR__/depfile2 input2 __SBOX_OUT_DIR__/output2 tool2" ,
"command3 input3 __SBOX_OUT_DIR__/output2 __SBOX_OUT_DIR__/output3" ,
}
wantDepMergerCommand := "out/host/" + ctx . Config ( ) . PrebuiltOS ( ) + "/bin/dep_fixer __SBOX_OUT_DIR__/DepFile __SBOX_OUT_DIR__/depfile __SBOX_OUT_DIR__/ImplicitDepFile __SBOX_OUT_DIR__/depfile2"
if g , w := rule . Commands ( ) , wantCommands ; ! reflect . DeepEqual ( g , w ) {
t . Errorf ( "\nwant rule.Commands() = %#v\n got %#v" , w , g )
}
if g , w := rule . Inputs ( ) , wantInputs ; ! reflect . DeepEqual ( w , g ) {
t . Errorf ( "\nwant rule.Inputs() = %#v\n got %#v" , w , g )
}
if g , w := rule . Outputs ( ) , wantOutputs ; ! reflect . DeepEqual ( w , g ) {
t . Errorf ( "\nwant rule.Outputs() = %#v\n got %#v" , w , g )
}
if g , w := rule . DepFiles ( ) , wantDepFiles ; ! reflect . DeepEqual ( w , g ) {
t . Errorf ( "\nwant rule.DepFiles() = %#v\n got %#v" , w , g )
}
if g , w := rule . Tools ( ) , wantTools ; ! reflect . DeepEqual ( w , g ) {
t . Errorf ( "\nwant rule.Tools() = %#v\n got %#v" , w , g )
}
if g , w := rule . depFileMergerCmd ( ctx , rule . DepFiles ( ) ) . String ( ) , wantDepMergerCommand ; g != w {
t . Errorf ( "\nwant rule.depFileMergerCmd() = %#v\n got %#v" , w , g )
}
} )
2019-01-31 02:32:39 +01:00
}
func testRuleBuilderFactory ( ) Module {
module := & testRuleBuilderModule { }
module . AddProperties ( & module . properties )
InitAndroidModule ( module )
return module
}
type testRuleBuilderModule struct {
ModuleBase
properties struct {
Src string
2019-04-12 20:11:38 +02:00
Restat bool
Sbox bool
2019-01-31 02:32:39 +01:00
}
}
func ( t * testRuleBuilderModule ) GenerateAndroidBuildActions ( ctx ModuleContext ) {
in := PathForSource ( ctx , t . properties . Src )
out := PathForModuleOut ( ctx , ctx . ModuleName ( ) )
2019-04-12 20:11:38 +02:00
outDep := PathForModuleOut ( ctx , ctx . ModuleName ( ) + ".d" )
outDir := PathForModuleOut ( ctx )
2019-01-31 02:32:39 +01:00
2019-04-12 20:11:38 +02:00
testRuleBuilder_Build ( ctx , in , out , outDep , outDir , t . properties . Restat , t . properties . Sbox )
2019-02-02 01:41:11 +01:00
}
type testRuleBuilderSingleton struct { }
func testRuleBuilderSingletonFactory ( ) Singleton {
return & testRuleBuilderSingleton { }
}
func ( t * testRuleBuilderSingleton ) GenerateBuildActions ( ctx SingletonContext ) {
in := PathForSource ( ctx , "bar" )
out := PathForOutput ( ctx , "baz" )
2019-04-12 20:11:38 +02:00
outDep := PathForOutput ( ctx , "baz.d" )
outDir := PathForOutput ( ctx )
testRuleBuilder_Build ( ctx , in , out , outDep , outDir , true , false )
2019-02-02 01:41:11 +01:00
}
2019-04-12 20:11:38 +02:00
func testRuleBuilder_Build ( ctx BuilderContext , in Path , out , outDep , outDir WritablePath , restat , sbox bool ) {
2019-02-02 01:42:32 +01:00
rule := NewRuleBuilder ( )
2019-02-02 01:41:11 +01:00
2019-04-12 20:11:38 +02:00
if sbox {
rule . Sbox ( outDir )
}
rule . Command ( ) . Tool ( PathForSource ( ctx , "cp" ) ) . Input ( in ) . Output ( out ) . ImplicitDepFile ( outDep )
2019-01-31 02:32:39 +01:00
2019-04-12 20:11:38 +02:00
if restat {
rule . Restat ( )
}
2019-02-25 23:56:01 +01:00
2019-01-31 02:32:39 +01:00
rule . Build ( pctx , ctx , "rule" , "desc" )
}
func TestRuleBuilder_Build ( t * testing . T ) {
bp := `
rule_builder_test {
name : "foo" ,
src : "bar" ,
2019-04-12 20:11:38 +02:00
restat : true ,
}
rule_builder_test {
name : "foo_sbox" ,
src : "bar" ,
sbox : true ,
2019-01-31 02:32:39 +01:00
}
`
config := TestConfig ( buildDir , nil )
ctx := NewTestContext ( )
ctx . MockFileSystem ( map [ string ] [ ] byte {
"Android.bp" : [ ] byte ( bp ) ,
"bar" : nil ,
"cp" : nil ,
} )
ctx . RegisterModuleType ( "rule_builder_test" , ModuleFactoryAdaptor ( testRuleBuilderFactory ) )
2019-02-02 01:41:11 +01:00
ctx . RegisterSingletonType ( "rule_builder_test" , SingletonFactoryAdaptor ( testRuleBuilderSingletonFactory ) )
2019-01-31 02:32:39 +01:00
ctx . Register ( )
_ , errs := ctx . ParseFileList ( "." , [ ] string { "Android.bp" } )
FailIfErrored ( t , errs )
_ , errs = ctx . PrepareBuildActions ( config )
FailIfErrored ( t , errs )
2019-04-12 20:11:38 +02:00
check := func ( t * testing . T , params TestingBuildParams , wantCommand , wantOutput , wantDepfile string , wantRestat bool , extraCmdDeps [ ] string ) {
if params . RuleParams . Command != wantCommand {
t . Errorf ( "\nwant RuleParams.Command = %q\n got %q" , wantCommand , params . RuleParams . Command )
}
wantDeps := append ( [ ] string { "cp" } , extraCmdDeps ... )
if ! reflect . DeepEqual ( params . RuleParams . CommandDeps , wantDeps ) {
t . Errorf ( "\nwant RuleParams.CommandDeps = %q\n got %q" , wantDeps , params . RuleParams . CommandDeps )
}
if params . RuleParams . Restat != wantRestat {
t . Errorf ( "want RuleParams.Restat = %v, got %v" , wantRestat , params . RuleParams . Restat )
2019-02-25 23:54:28 +01:00
}
2019-01-31 02:32:39 +01:00
2019-02-25 23:54:28 +01:00
if len ( params . Implicits ) != 1 || params . Implicits [ 0 ] . String ( ) != "bar" {
t . Errorf ( "want Implicits = [%q], got %q" , "bar" , params . Implicits . Strings ( ) )
}
2019-01-31 02:32:39 +01:00
2019-03-29 23:33:06 +01:00
if params . Output . String ( ) != wantOutput {
t . Errorf ( "want Output = %q, got %q" , wantOutput , params . Output )
2019-02-25 23:54:28 +01:00
}
2019-02-25 23:56:01 +01:00
2019-04-12 20:11:38 +02:00
if len ( params . ImplicitOutputs ) != 0 {
t . Errorf ( "want ImplicitOutputs = [], got %q" , params . ImplicitOutputs . Strings ( ) )
}
if params . Depfile . String ( ) != wantDepfile {
t . Errorf ( "want Depfile = %q, got %q" , wantDepfile , params . Depfile )
}
if params . Deps != blueprint . DepsGCC {
t . Errorf ( "want Deps = %q, got %q" , blueprint . DepsGCC , params . Deps )
2019-02-25 23:56:01 +01:00
}
2019-01-31 02:32:39 +01:00
}
2019-02-25 23:54:28 +01:00
t . Run ( "module" , func ( t * testing . T ) {
2019-04-12 20:11:38 +02:00
outFile := filepath . Join ( buildDir , ".intermediates" , "foo" , "foo" )
2019-02-25 23:54:28 +01:00
check ( t , ctx . ModuleForTests ( "foo" , "" ) . Rule ( "rule" ) ,
2019-04-12 20:11:38 +02:00
"cp bar " + outFile ,
outFile , outFile + ".d" , true , nil )
} )
t . Run ( "sbox" , func ( t * testing . T ) {
outDir := filepath . Join ( buildDir , ".intermediates" , "foo_sbox" )
outFile := filepath . Join ( outDir , "foo_sbox" )
sbox := filepath . Join ( buildDir , "host" , config . PrebuiltOS ( ) , "bin/sbox" )
sandboxPath := shared . TempDirForOutDir ( buildDir )
cmd := sbox + ` -c 'cp bar __SBOX_OUT_DIR__/foo_sbox' --sandbox-path ` + sandboxPath + " --output-root " + outDir + " __SBOX_OUT_DIR__/foo_sbox __SBOX_OUT_DIR__/foo_sbox.d"
check ( t , ctx . ModuleForTests ( "foo_sbox" , "" ) . Rule ( "rule" ) ,
cmd , outFile , outFile + ".d" , false , [ ] string { sbox } )
2019-02-25 23:54:28 +01:00
} )
t . Run ( "singleton" , func ( t * testing . T ) {
2019-04-12 20:11:38 +02:00
outFile := filepath . Join ( buildDir , "baz" )
2019-02-25 23:54:28 +01:00
check ( t , ctx . SingletonForTests ( "rule_builder_test" ) . Rule ( "rule" ) ,
2019-04-12 20:11:38 +02:00
"cp bar " + outFile , outFile , outFile + ".d" , true , nil )
2019-02-25 23:54:28 +01:00
} )
2019-01-31 02:32:39 +01:00
}
2019-07-11 19:59:15 +02:00
func Test_ninjaEscapeExceptForSpans ( t * testing . T ) {
type args struct {
s string
spans [ ] [ 2 ] int
}
tests := [ ] struct {
name string
args args
want string
} {
{
name : "empty" ,
args : args {
s : "" ,
} ,
want : "" ,
} ,
{
name : "unescape none" ,
args : args {
s : "$abc" ,
} ,
want : "$$abc" ,
} ,
{
name : "unescape all" ,
args : args {
s : "$abc" ,
spans : [ ] [ 2 ] int { { 0 , 4 } } ,
} ,
want : "$abc" ,
} ,
{
name : "unescape first" ,
args : args {
s : "$abc$" ,
spans : [ ] [ 2 ] int { { 0 , 1 } } ,
} ,
want : "$abc$$" ,
} ,
{
name : "unescape last" ,
args : args {
s : "$abc$" ,
spans : [ ] [ 2 ] int { { 4 , 5 } } ,
} ,
want : "$$abc$" ,
} ,
{
name : "unescape middle" ,
args : args {
s : "$a$b$c$" ,
spans : [ ] [ 2 ] int { { 2 , 5 } } ,
} ,
want : "$$a$b$c$$" ,
} ,
{
name : "unescape multiple" ,
args : args {
s : "$a$b$c$" ,
spans : [ ] [ 2 ] int { { 2 , 3 } , { 4 , 5 } } ,
} ,
want : "$$a$b$c$$" ,
} ,
}
for _ , tt := range tests {
t . Run ( tt . name , func ( t * testing . T ) {
if got := ninjaEscapeExceptForSpans ( tt . args . s , tt . args . spans ) ; got != tt . want {
t . Errorf ( "ninjaEscapeExceptForSpans() = %v, want %v" , got , tt . want )
}
} )
}
}