123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323 |
- // Copyright 2015 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 (
- "errors"
- "fmt"
- "reflect"
- "strconv"
- "strings"
- "testing"
- "github.com/google/blueprint/proptools"
- )
- type strsTestCase struct {
- in []string
- out string
- err []error
- }
- var commonValidatePathTestCases = []strsTestCase{
- {
- in: []string{""},
- out: "",
- },
- {
- in: []string{"a/b"},
- out: "a/b",
- },
- {
- in: []string{"a/b", "c"},
- out: "a/b/c",
- },
- {
- in: []string{"a/.."},
- out: ".",
- },
- {
- in: []string{"."},
- out: ".",
- },
- {
- in: []string{".."},
- out: "",
- err: []error{errors.New("Path is outside directory: ..")},
- },
- {
- in: []string{"../a"},
- out: "",
- err: []error{errors.New("Path is outside directory: ../a")},
- },
- {
- in: []string{"b/../../a"},
- out: "",
- err: []error{errors.New("Path is outside directory: ../a")},
- },
- {
- in: []string{"/a"},
- out: "",
- err: []error{errors.New("Path is outside directory: /a")},
- },
- {
- in: []string{"a", "../b"},
- out: "",
- err: []error{errors.New("Path is outside directory: ../b")},
- },
- {
- in: []string{"a", "b/../../c"},
- out: "",
- err: []error{errors.New("Path is outside directory: ../c")},
- },
- {
- in: []string{"a", "./.."},
- out: "",
- err: []error{errors.New("Path is outside directory: ..")},
- },
- }
- var validateSafePathTestCases = append(commonValidatePathTestCases, []strsTestCase{
- {
- in: []string{"$host/../$a"},
- out: "$a",
- },
- }...)
- var validatePathTestCases = append(commonValidatePathTestCases, []strsTestCase{
- {
- in: []string{"$host/../$a"},
- out: "",
- err: []error{errors.New("Path contains invalid character($): $host/../$a")},
- },
- {
- in: []string{"$host/.."},
- out: "",
- err: []error{errors.New("Path contains invalid character($): $host/..")},
- },
- }...)
- func TestValidateSafePath(t *testing.T) {
- for _, testCase := range validateSafePathTestCases {
- t.Run(strings.Join(testCase.in, ","), func(t *testing.T) {
- ctx := &configErrorWrapper{}
- out, err := validateSafePath(testCase.in...)
- if err != nil {
- reportPathError(ctx, err)
- }
- check(t, "validateSafePath", p(testCase.in), out, ctx.errors, testCase.out, testCase.err)
- })
- }
- }
- func TestValidatePath(t *testing.T) {
- for _, testCase := range validatePathTestCases {
- t.Run(strings.Join(testCase.in, ","), func(t *testing.T) {
- ctx := &configErrorWrapper{}
- out, err := validatePath(testCase.in...)
- if err != nil {
- reportPathError(ctx, err)
- }
- check(t, "validatePath", p(testCase.in), out, ctx.errors, testCase.out, testCase.err)
- })
- }
- }
- func TestOptionalPath(t *testing.T) {
- var path OptionalPath
- checkInvalidOptionalPath(t, path)
- path = OptionalPathForPath(nil)
- checkInvalidOptionalPath(t, path)
- }
- func checkInvalidOptionalPath(t *testing.T, path OptionalPath) {
- t.Helper()
- if path.Valid() {
- t.Errorf("Uninitialized OptionalPath should not be valid")
- }
- if path.String() != "" {
- t.Errorf("Uninitialized OptionalPath String() should return \"\", not %q", path.String())
- }
- defer func() {
- if r := recover(); r == nil {
- t.Errorf("Expected a panic when calling Path() on an uninitialized OptionalPath")
- }
- }()
- path.Path()
- }
- func check(t *testing.T, testType, testString string,
- got interface{}, err []error,
- expected interface{}, expectedErr []error) {
- t.Helper()
- printedTestCase := false
- e := func(s string, expected, got interface{}) {
- t.Helper()
- if !printedTestCase {
- t.Errorf("test case %s: %s", testType, testString)
- printedTestCase = true
- }
- t.Errorf("incorrect %s", s)
- t.Errorf(" expected: %s", p(expected))
- t.Errorf(" got: %s", p(got))
- }
- if !reflect.DeepEqual(expectedErr, err) {
- e("errors:", expectedErr, err)
- }
- if !reflect.DeepEqual(expected, got) {
- e("output:", expected, got)
- }
- }
- func p(in interface{}) string {
- if v, ok := in.([]interface{}); ok {
- s := make([]string, len(v))
- for i := range v {
- s[i] = fmt.Sprintf("%#v", v[i])
- }
- return "[" + strings.Join(s, ", ") + "]"
- } else {
- return fmt.Sprintf("%#v", in)
- }
- }
- type moduleInstallPathContextImpl struct {
- baseModuleContext
- inData bool
- inTestcases bool
- inSanitizerDir bool
- inRamdisk bool
- inRecovery bool
- inRoot bool
- forceOS *OsType
- forceArch *ArchType
- }
- func (m moduleInstallPathContextImpl) Config() Config {
- return m.baseModuleContext.config
- }
- func (moduleInstallPathContextImpl) AddNinjaFileDeps(deps ...string) {}
- func (m moduleInstallPathContextImpl) InstallInData() bool {
- return m.inData
- }
- func (m moduleInstallPathContextImpl) InstallInTestcases() bool {
- return m.inTestcases
- }
- func (m moduleInstallPathContextImpl) InstallInSanitizerDir() bool {
- return m.inSanitizerDir
- }
- func (m moduleInstallPathContextImpl) InstallInRamdisk() bool {
- return m.inRamdisk
- }
- func (m moduleInstallPathContextImpl) InstallInRecovery() bool {
- return m.inRecovery
- }
- func (m moduleInstallPathContextImpl) InstallInRoot() bool {
- return m.inRoot
- }
- func (m moduleInstallPathContextImpl) InstallBypassMake() bool {
- return false
- }
- func (m moduleInstallPathContextImpl) InstallForceOS() (*OsType, *ArchType) {
- return m.forceOS, m.forceArch
- }
- func pathTestConfig(buildDir string) Config {
- return TestConfig(buildDir, nil, "", nil)
- }
- func TestPathForModuleInstall(t *testing.T) {
- testConfig := pathTestConfig("")
- hostTarget := Target{Os: Linux, Arch: Arch{ArchType: X86}}
- deviceTarget := Target{Os: Android, Arch: Arch{ArchType: Arm64}}
- testCases := []struct {
- name string
- ctx *moduleInstallPathContextImpl
- in []string
- out string
- }{
- {
- name: "host binary",
- ctx: &moduleInstallPathContextImpl{
- baseModuleContext: baseModuleContext{
- os: hostTarget.Os,
- target: hostTarget,
- },
- },
- in: []string{"bin", "my_test"},
- out: "host/linux-x86/bin/my_test",
- },
- {
- name: "system binary",
- ctx: &moduleInstallPathContextImpl{
- baseModuleContext: baseModuleContext{
- os: deviceTarget.Os,
- target: deviceTarget,
- },
- },
- in: []string{"bin", "my_test"},
- out: "target/product/test_device/system/bin/my_test",
- },
- {
- name: "vendor binary",
- ctx: &moduleInstallPathContextImpl{
- baseModuleContext: baseModuleContext{
- os: deviceTarget.Os,
- target: deviceTarget,
- earlyModuleContext: earlyModuleContext{
- kind: socSpecificModule,
- },
- },
- },
- in: []string{"bin", "my_test"},
- out: "target/product/test_device/vendor/bin/my_test",
- },
- {
- name: "odm binary",
- ctx: &moduleInstallPathContextImpl{
- baseModuleContext: baseModuleContext{
- os: deviceTarget.Os,
- target: deviceTarget,
- earlyModuleContext: earlyModuleContext{
- kind: deviceSpecificModule,
- },
- },
- },
- in: []string{"bin", "my_test"},
- out: "target/product/test_device/odm/bin/my_test",
- },
- {
- name: "product binary",
- ctx: &moduleInstallPathContextImpl{
- baseModuleContext: baseModuleContext{
- os: deviceTarget.Os,
- target: deviceTarget,
- earlyModuleContext: earlyModuleContext{
- kind: productSpecificModule,
- },
- },
- },
- in: []string{"bin", "my_test"},
- out: "target/product/test_device/product/bin/my_test",
- },
- {
- name: "system_ext binary",
- ctx: &moduleInstallPathContextImpl{
- baseModuleContext: baseModuleContext{
- os: deviceTarget.Os,
- target: deviceTarget,
- earlyModuleContext: earlyModuleContext{
- kind: systemExtSpecificModule,
- },
- },
- },
- in: []string{"bin", "my_test"},
- out: "target/product/test_device/system_ext/bin/my_test",
- },
- {
- name: "root binary",
- ctx: &moduleInstallPathContextImpl{
- baseModuleContext: baseModuleContext{
- os: deviceTarget.Os,
- target: deviceTarget,
- },
- inRoot: true,
- },
- in: []string{"my_test"},
- out: "target/product/test_device/root/my_test",
- },
- {
- name: "recovery binary",
- ctx: &moduleInstallPathContextImpl{
- baseModuleContext: baseModuleContext{
- os: deviceTarget.Os,
- target: deviceTarget,
- },
- inRecovery: true,
- },
- in: []string{"bin/my_test"},
- out: "target/product/test_device/recovery/root/system/bin/my_test",
- },
- {
- name: "recovery root binary",
- ctx: &moduleInstallPathContextImpl{
- baseModuleContext: baseModuleContext{
- os: deviceTarget.Os,
- target: deviceTarget,
- },
- inRecovery: true,
- inRoot: true,
- },
- in: []string{"my_test"},
- out: "target/product/test_device/recovery/root/my_test",
- },
- {
- name: "system native test binary",
- ctx: &moduleInstallPathContextImpl{
- baseModuleContext: baseModuleContext{
- os: deviceTarget.Os,
- target: deviceTarget,
- },
- inData: true,
- },
- in: []string{"nativetest", "my_test"},
- out: "target/product/test_device/data/nativetest/my_test",
- },
- {
- name: "vendor native test binary",
- ctx: &moduleInstallPathContextImpl{
- baseModuleContext: baseModuleContext{
- os: deviceTarget.Os,
- target: deviceTarget,
- earlyModuleContext: earlyModuleContext{
- kind: socSpecificModule,
- },
- },
- inData: true,
- },
- in: []string{"nativetest", "my_test"},
- out: "target/product/test_device/data/nativetest/my_test",
- },
- {
- name: "odm native test binary",
- ctx: &moduleInstallPathContextImpl{
- baseModuleContext: baseModuleContext{
- os: deviceTarget.Os,
- target: deviceTarget,
- earlyModuleContext: earlyModuleContext{
- kind: deviceSpecificModule,
- },
- },
- inData: true,
- },
- in: []string{"nativetest", "my_test"},
- out: "target/product/test_device/data/nativetest/my_test",
- },
- {
- name: "product native test binary",
- ctx: &moduleInstallPathContextImpl{
- baseModuleContext: baseModuleContext{
- os: deviceTarget.Os,
- target: deviceTarget,
- earlyModuleContext: earlyModuleContext{
- kind: productSpecificModule,
- },
- },
- inData: true,
- },
- in: []string{"nativetest", "my_test"},
- out: "target/product/test_device/data/nativetest/my_test",
- },
- {
- name: "system_ext native test binary",
- ctx: &moduleInstallPathContextImpl{
- baseModuleContext: baseModuleContext{
- os: deviceTarget.Os,
- target: deviceTarget,
- earlyModuleContext: earlyModuleContext{
- kind: systemExtSpecificModule,
- },
- },
- inData: true,
- },
- in: []string{"nativetest", "my_test"},
- out: "target/product/test_device/data/nativetest/my_test",
- },
- {
- name: "sanitized system binary",
- ctx: &moduleInstallPathContextImpl{
- baseModuleContext: baseModuleContext{
- os: deviceTarget.Os,
- target: deviceTarget,
- },
- inSanitizerDir: true,
- },
- in: []string{"bin", "my_test"},
- out: "target/product/test_device/data/asan/system/bin/my_test",
- },
- {
- name: "sanitized vendor binary",
- ctx: &moduleInstallPathContextImpl{
- baseModuleContext: baseModuleContext{
- os: deviceTarget.Os,
- target: deviceTarget,
- earlyModuleContext: earlyModuleContext{
- kind: socSpecificModule,
- },
- },
- inSanitizerDir: true,
- },
- in: []string{"bin", "my_test"},
- out: "target/product/test_device/data/asan/vendor/bin/my_test",
- },
- {
- name: "sanitized odm binary",
- ctx: &moduleInstallPathContextImpl{
- baseModuleContext: baseModuleContext{
- os: deviceTarget.Os,
- target: deviceTarget,
- earlyModuleContext: earlyModuleContext{
- kind: deviceSpecificModule,
- },
- },
- inSanitizerDir: true,
- },
- in: []string{"bin", "my_test"},
- out: "target/product/test_device/data/asan/odm/bin/my_test",
- },
- {
- name: "sanitized product binary",
- ctx: &moduleInstallPathContextImpl{
- baseModuleContext: baseModuleContext{
- os: deviceTarget.Os,
- target: deviceTarget,
- earlyModuleContext: earlyModuleContext{
- kind: productSpecificModule,
- },
- },
- inSanitizerDir: true,
- },
- in: []string{"bin", "my_test"},
- out: "target/product/test_device/data/asan/product/bin/my_test",
- },
- {
- name: "sanitized system_ext binary",
- ctx: &moduleInstallPathContextImpl{
- baseModuleContext: baseModuleContext{
- os: deviceTarget.Os,
- target: deviceTarget,
- earlyModuleContext: earlyModuleContext{
- kind: systemExtSpecificModule,
- },
- },
- inSanitizerDir: true,
- },
- in: []string{"bin", "my_test"},
- out: "target/product/test_device/data/asan/system_ext/bin/my_test",
- },
- {
- name: "sanitized system native test binary",
- ctx: &moduleInstallPathContextImpl{
- baseModuleContext: baseModuleContext{
- os: deviceTarget.Os,
- target: deviceTarget,
- },
- inData: true,
- inSanitizerDir: true,
- },
- in: []string{"nativetest", "my_test"},
- out: "target/product/test_device/data/asan/data/nativetest/my_test",
- },
- {
- name: "sanitized vendor native test binary",
- ctx: &moduleInstallPathContextImpl{
- baseModuleContext: baseModuleContext{
- os: deviceTarget.Os,
- target: deviceTarget,
- earlyModuleContext: earlyModuleContext{
- kind: socSpecificModule,
- },
- },
- inData: true,
- inSanitizerDir: true,
- },
- in: []string{"nativetest", "my_test"},
- out: "target/product/test_device/data/asan/data/nativetest/my_test",
- },
- {
- name: "sanitized odm native test binary",
- ctx: &moduleInstallPathContextImpl{
- baseModuleContext: baseModuleContext{
- os: deviceTarget.Os,
- target: deviceTarget,
- earlyModuleContext: earlyModuleContext{
- kind: deviceSpecificModule,
- },
- },
- inData: true,
- inSanitizerDir: true,
- },
- in: []string{"nativetest", "my_test"},
- out: "target/product/test_device/data/asan/data/nativetest/my_test",
- },
- {
- name: "sanitized product native test binary",
- ctx: &moduleInstallPathContextImpl{
- baseModuleContext: baseModuleContext{
- os: deviceTarget.Os,
- target: deviceTarget,
- earlyModuleContext: earlyModuleContext{
- kind: productSpecificModule,
- },
- },
- inData: true,
- inSanitizerDir: true,
- },
- in: []string{"nativetest", "my_test"},
- out: "target/product/test_device/data/asan/data/nativetest/my_test",
- },
- {
- name: "sanitized system_ext native test binary",
- ctx: &moduleInstallPathContextImpl{
- baseModuleContext: baseModuleContext{
- os: deviceTarget.Os,
- target: deviceTarget,
- earlyModuleContext: earlyModuleContext{
- kind: systemExtSpecificModule,
- },
- },
- inData: true,
- inSanitizerDir: true,
- },
- in: []string{"nativetest", "my_test"},
- out: "target/product/test_device/data/asan/data/nativetest/my_test",
- }, {
- name: "device testcases",
- ctx: &moduleInstallPathContextImpl{
- baseModuleContext: baseModuleContext{
- os: deviceTarget.Os,
- target: deviceTarget,
- },
- inTestcases: true,
- },
- in: []string{"my_test", "my_test_bin"},
- out: "target/product/test_device/testcases/my_test/my_test_bin",
- }, {
- name: "host testcases",
- ctx: &moduleInstallPathContextImpl{
- baseModuleContext: baseModuleContext{
- os: hostTarget.Os,
- target: hostTarget,
- },
- inTestcases: true,
- },
- in: []string{"my_test", "my_test_bin"},
- out: "host/linux-x86/testcases/my_test/my_test_bin",
- }, {
- name: "forced host testcases",
- ctx: &moduleInstallPathContextImpl{
- baseModuleContext: baseModuleContext{
- os: deviceTarget.Os,
- target: deviceTarget,
- },
- inTestcases: true,
- forceOS: &Linux,
- forceArch: &X86,
- },
- in: []string{"my_test", "my_test_bin"},
- out: "host/linux-x86/testcases/my_test/my_test_bin",
- },
- }
- for _, tc := range testCases {
- t.Run(tc.name, func(t *testing.T) {
- tc.ctx.baseModuleContext.config = testConfig
- output := PathForModuleInstall(tc.ctx, tc.in...)
- if output.basePath.path != tc.out {
- t.Errorf("unexpected path:\n got: %q\nwant: %q\n",
- output.basePath.path,
- tc.out)
- }
- })
- }
- }
- func TestDirectorySortedPaths(t *testing.T) {
- config := TestConfig("out", nil, "", map[string][]byte{
- "Android.bp": nil,
- "a.txt": nil,
- "a/txt": nil,
- "a/b/c": nil,
- "a/b/d": nil,
- "b": nil,
- "b/b.txt": nil,
- "a/a.txt": nil,
- })
- ctx := PathContextForTesting(config)
- makePaths := func() Paths {
- return Paths{
- PathForSource(ctx, "a.txt"),
- PathForSource(ctx, "a/txt"),
- PathForSource(ctx, "a/b/c"),
- PathForSource(ctx, "a/b/d"),
- PathForSource(ctx, "b"),
- PathForSource(ctx, "b/b.txt"),
- PathForSource(ctx, "a/a.txt"),
- }
- }
- expected := []string{
- "a.txt",
- "a/a.txt",
- "a/b/c",
- "a/b/d",
- "a/txt",
- "b",
- "b/b.txt",
- }
- paths := makePaths()
- reversePaths := ReversePaths(paths)
- sortedPaths := PathsToDirectorySortedPaths(paths)
- reverseSortedPaths := PathsToDirectorySortedPaths(reversePaths)
- if !reflect.DeepEqual(Paths(sortedPaths).Strings(), expected) {
- t.Fatalf("sorted paths:\n %#v\n != \n %#v", paths.Strings(), expected)
- }
- if !reflect.DeepEqual(Paths(reverseSortedPaths).Strings(), expected) {
- t.Fatalf("sorted reversed paths:\n %#v\n !=\n %#v", reversePaths.Strings(), expected)
- }
- expectedA := []string{
- "a/a.txt",
- "a/b/c",
- "a/b/d",
- "a/txt",
- }
- inA := sortedPaths.PathsInDirectory("a")
- if !reflect.DeepEqual(inA.Strings(), expectedA) {
- t.Errorf("FilesInDirectory(a):\n %#v\n != \n %#v", inA.Strings(), expectedA)
- }
- expectedA_B := []string{
- "a/b/c",
- "a/b/d",
- }
- inA_B := sortedPaths.PathsInDirectory("a/b")
- if !reflect.DeepEqual(inA_B.Strings(), expectedA_B) {
- t.Errorf("FilesInDirectory(a/b):\n %#v\n != \n %#v", inA_B.Strings(), expectedA_B)
- }
- expectedB := []string{
- "b/b.txt",
- }
- inB := sortedPaths.PathsInDirectory("b")
- if !reflect.DeepEqual(inB.Strings(), expectedB) {
- t.Errorf("FilesInDirectory(b):\n %#v\n != \n %#v", inA.Strings(), expectedA)
- }
- }
- func TestMaybeRel(t *testing.T) {
- testCases := []struct {
- name string
- base string
- target string
- out string
- isRel bool
- }{
- {
- name: "normal",
- base: "a/b/c",
- target: "a/b/c/d",
- out: "d",
- isRel: true,
- },
- {
- name: "parent",
- base: "a/b/c/d",
- target: "a/b/c",
- isRel: false,
- },
- {
- name: "not relative",
- base: "a/b",
- target: "c/d",
- isRel: false,
- },
- {
- name: "abs1",
- base: "/a",
- target: "a",
- isRel: false,
- },
- {
- name: "abs2",
- base: "a",
- target: "/a",
- isRel: false,
- },
- }
- for _, testCase := range testCases {
- t.Run(testCase.name, func(t *testing.T) {
- ctx := &configErrorWrapper{}
- out, isRel := MaybeRel(ctx, testCase.base, testCase.target)
- if len(ctx.errors) > 0 {
- t.Errorf("MaybeRel(..., %s, %s) reported unexpected errors %v",
- testCase.base, testCase.target, ctx.errors)
- }
- if isRel != testCase.isRel || out != testCase.out {
- t.Errorf("MaybeRel(..., %s, %s) want %v, %v got %v, %v",
- testCase.base, testCase.target, testCase.out, testCase.isRel, out, isRel)
- }
- })
- }
- }
- func TestPathForSource(t *testing.T) {
- testCases := []struct {
- name string
- buildDir string
- src string
- err string
- }{
- {
- name: "normal",
- buildDir: "out",
- src: "a/b/c",
- },
- {
- name: "abs",
- buildDir: "out",
- src: "/a/b/c",
- err: "is outside directory",
- },
- {
- name: "in out dir",
- buildDir: "out",
- src: "out/a/b/c",
- err: "is in output",
- },
- }
- funcs := []struct {
- name string
- f func(ctx PathContext, pathComponents ...string) (SourcePath, error)
- }{
- {"pathForSource", pathForSource},
- {"safePathForSource", safePathForSource},
- }
- for _, f := range funcs {
- t.Run(f.name, func(t *testing.T) {
- for _, test := range testCases {
- t.Run(test.name, func(t *testing.T) {
- testConfig := pathTestConfig(test.buildDir)
- ctx := &configErrorWrapper{config: testConfig}
- _, err := f.f(ctx, test.src)
- if len(ctx.errors) > 0 {
- t.Fatalf("unexpected errors %v", ctx.errors)
- }
- if err != nil {
- if test.err == "" {
- t.Fatalf("unexpected error %q", err.Error())
- } else if !strings.Contains(err.Error(), test.err) {
- t.Fatalf("incorrect error, want substring %q got %q", test.err, err.Error())
- }
- } else {
- if test.err != "" {
- t.Fatalf("missing error %q", test.err)
- }
- }
- })
- }
- })
- }
- }
- type pathForModuleSrcTestModule struct {
- ModuleBase
- props struct {
- Srcs []string `android:"path"`
- Exclude_srcs []string `android:"path"`
- Src *string `android:"path"`
- Module_handles_missing_deps bool
- }
- src string
- rel string
- srcs []string
- rels []string
- missingDeps []string
- }
- func pathForModuleSrcTestModuleFactory() Module {
- module := &pathForModuleSrcTestModule{}
- module.AddProperties(&module.props)
- InitAndroidModule(module)
- return module
- }
- func (p *pathForModuleSrcTestModule) GenerateAndroidBuildActions(ctx ModuleContext) {
- var srcs Paths
- if p.props.Module_handles_missing_deps {
- srcs, p.missingDeps = PathsAndMissingDepsForModuleSrcExcludes(ctx, p.props.Srcs, p.props.Exclude_srcs)
- } else {
- srcs = PathsForModuleSrcExcludes(ctx, p.props.Srcs, p.props.Exclude_srcs)
- }
- p.srcs = srcs.Strings()
- for _, src := range srcs {
- p.rels = append(p.rels, src.Rel())
- }
- if p.props.Src != nil {
- src := PathForModuleSrc(ctx, *p.props.Src)
- if src != nil {
- p.src = src.String()
- p.rel = src.Rel()
- }
- }
- if !p.props.Module_handles_missing_deps {
- p.missingDeps = ctx.GetMissingDependencies()
- }
- ctx.Build(pctx, BuildParams{
- Rule: Touch,
- Output: PathForModuleOut(ctx, "output"),
- })
- }
- type pathForModuleSrcOutputFileProviderModule struct {
- ModuleBase
- props struct {
- Outs []string
- Tagged []string
- }
- outs Paths
- tagged Paths
- }
- func pathForModuleSrcOutputFileProviderModuleFactory() Module {
- module := &pathForModuleSrcOutputFileProviderModule{}
- module.AddProperties(&module.props)
- InitAndroidModule(module)
- return module
- }
- func (p *pathForModuleSrcOutputFileProviderModule) GenerateAndroidBuildActions(ctx ModuleContext) {
- for _, out := range p.props.Outs {
- p.outs = append(p.outs, PathForModuleOut(ctx, out))
- }
- for _, tagged := range p.props.Tagged {
- p.tagged = append(p.tagged, PathForModuleOut(ctx, tagged))
- }
- }
- func (p *pathForModuleSrcOutputFileProviderModule) OutputFiles(tag string) (Paths, error) {
- switch tag {
- case "":
- return p.outs, nil
- case ".tagged":
- return p.tagged, nil
- default:
- return nil, fmt.Errorf("unsupported tag %q", tag)
- }
- }
- type pathForModuleSrcTestCase struct {
- name string
- bp string
- srcs []string
- rels []string
- src string
- rel string
- }
- func testPathForModuleSrc(t *testing.T, buildDir string, tests []pathForModuleSrcTestCase) {
- for _, test := range tests {
- t.Run(test.name, func(t *testing.T) {
- ctx := NewTestContext()
- ctx.RegisterModuleType("test", pathForModuleSrcTestModuleFactory)
- ctx.RegisterModuleType("output_file_provider", pathForModuleSrcOutputFileProviderModuleFactory)
- ctx.RegisterModuleType("filegroup", FileGroupFactory)
- fgBp := `
- filegroup {
- name: "a",
- srcs: ["src/a"],
- }
- `
- ofpBp := `
- output_file_provider {
- name: "b",
- outs: ["gen/b"],
- tagged: ["gen/c"],
- }
- `
- mockFS := map[string][]byte{
- "fg/Android.bp": []byte(fgBp),
- "foo/Android.bp": []byte(test.bp),
- "ofp/Android.bp": []byte(ofpBp),
- "fg/src/a": nil,
- "foo/src/b": nil,
- "foo/src/c": nil,
- "foo/src/d": nil,
- "foo/src/e/e": nil,
- "foo/src_special/$": nil,
- }
- config := TestConfig(buildDir, nil, "", mockFS)
- ctx.Register(config)
- _, errs := ctx.ParseFileList(".", []string{"fg/Android.bp", "foo/Android.bp", "ofp/Android.bp"})
- FailIfErrored(t, errs)
- _, errs = ctx.PrepareBuildActions(config)
- FailIfErrored(t, errs)
- m := ctx.ModuleForTests("foo", "").Module().(*pathForModuleSrcTestModule)
- if g, w := m.srcs, test.srcs; !reflect.DeepEqual(g, w) {
- t.Errorf("want srcs %q, got %q", w, g)
- }
- if g, w := m.rels, test.rels; !reflect.DeepEqual(g, w) {
- t.Errorf("want rels %q, got %q", w, g)
- }
- if g, w := m.src, test.src; g != w {
- t.Errorf("want src %q, got %q", w, g)
- }
- if g, w := m.rel, test.rel; g != w {
- t.Errorf("want rel %q, got %q", w, g)
- }
- })
- }
- }
- func TestPathsForModuleSrc(t *testing.T) {
- tests := []pathForModuleSrcTestCase{
- {
- name: "path",
- bp: `
- test {
- name: "foo",
- srcs: ["src/b"],
- }`,
- srcs: []string{"foo/src/b"},
- rels: []string{"src/b"},
- },
- {
- name: "glob",
- bp: `
- test {
- name: "foo",
- srcs: [
- "src/*",
- "src/e/*",
- ],
- }`,
- srcs: []string{"foo/src/b", "foo/src/c", "foo/src/d", "foo/src/e/e"},
- rels: []string{"src/b", "src/c", "src/d", "src/e/e"},
- },
- {
- name: "recursive glob",
- bp: `
- test {
- name: "foo",
- srcs: ["src/**/*"],
- }`,
- srcs: []string{"foo/src/b", "foo/src/c", "foo/src/d", "foo/src/e/e"},
- rels: []string{"src/b", "src/c", "src/d", "src/e/e"},
- },
- {
- name: "filegroup",
- bp: `
- test {
- name: "foo",
- srcs: [":a"],
- }`,
- srcs: []string{"fg/src/a"},
- rels: []string{"src/a"},
- },
- {
- name: "output file provider",
- bp: `
- test {
- name: "foo",
- srcs: [":b"],
- }`,
- srcs: []string{buildDir + "/.intermediates/ofp/b/gen/b"},
- rels: []string{"gen/b"},
- },
- {
- name: "output file provider tagged",
- bp: `
- test {
- name: "foo",
- srcs: [":b{.tagged}"],
- }`,
- srcs: []string{buildDir + "/.intermediates/ofp/b/gen/c"},
- rels: []string{"gen/c"},
- },
- {
- name: "output file provider with exclude",
- bp: `
- test {
- name: "foo",
- srcs: [":b", ":c"],
- exclude_srcs: [":c"]
- }
- output_file_provider {
- name: "c",
- outs: ["gen/c"],
- }`,
- srcs: []string{buildDir + "/.intermediates/ofp/b/gen/b"},
- rels: []string{"gen/b"},
- },
- {
- name: "special characters glob",
- bp: `
- test {
- name: "foo",
- srcs: ["src_special/*"],
- }`,
- srcs: []string{"foo/src_special/$"},
- rels: []string{"src_special/$"},
- },
- }
- testPathForModuleSrc(t, buildDir, tests)
- }
- func TestPathForModuleSrc(t *testing.T) {
- tests := []pathForModuleSrcTestCase{
- {
- name: "path",
- bp: `
- test {
- name: "foo",
- src: "src/b",
- }`,
- src: "foo/src/b",
- rel: "src/b",
- },
- {
- name: "glob",
- bp: `
- test {
- name: "foo",
- src: "src/e/*",
- }`,
- src: "foo/src/e/e",
- rel: "src/e/e",
- },
- {
- name: "filegroup",
- bp: `
- test {
- name: "foo",
- src: ":a",
- }`,
- src: "fg/src/a",
- rel: "src/a",
- },
- {
- name: "output file provider",
- bp: `
- test {
- name: "foo",
- src: ":b",
- }`,
- src: buildDir + "/.intermediates/ofp/b/gen/b",
- rel: "gen/b",
- },
- {
- name: "output file provider tagged",
- bp: `
- test {
- name: "foo",
- src: ":b{.tagged}",
- }`,
- src: buildDir + "/.intermediates/ofp/b/gen/c",
- rel: "gen/c",
- },
- {
- name: "special characters glob",
- bp: `
- test {
- name: "foo",
- src: "src_special/*",
- }`,
- src: "foo/src_special/$",
- rel: "src_special/$",
- },
- }
- testPathForModuleSrc(t, buildDir, tests)
- }
- func TestPathsForModuleSrc_AllowMissingDependencies(t *testing.T) {
- bp := `
- test {
- name: "foo",
- srcs: [":a"],
- exclude_srcs: [":b"],
- src: ":c",
- }
- test {
- name: "bar",
- srcs: [":d"],
- exclude_srcs: [":e"],
- module_handles_missing_deps: true,
- }
- `
- config := TestConfig(buildDir, nil, bp, nil)
- config.TestProductVariables.Allow_missing_dependencies = proptools.BoolPtr(true)
- ctx := NewTestContext()
- ctx.SetAllowMissingDependencies(true)
- ctx.RegisterModuleType("test", pathForModuleSrcTestModuleFactory)
- ctx.Register(config)
- _, errs := ctx.ParseFileList(".", []string{"Android.bp"})
- FailIfErrored(t, errs)
- _, errs = ctx.PrepareBuildActions(config)
- FailIfErrored(t, errs)
- foo := ctx.ModuleForTests("foo", "").Module().(*pathForModuleSrcTestModule)
- if g, w := foo.missingDeps, []string{"a", "b", "c"}; !reflect.DeepEqual(g, w) {
- t.Errorf("want foo missing deps %q, got %q", w, g)
- }
- if g, w := foo.srcs, []string{}; !reflect.DeepEqual(g, w) {
- t.Errorf("want foo srcs %q, got %q", w, g)
- }
- if g, w := foo.src, ""; g != w {
- t.Errorf("want foo src %q, got %q", w, g)
- }
- bar := ctx.ModuleForTests("bar", "").Module().(*pathForModuleSrcTestModule)
- if g, w := bar.missingDeps, []string{"d", "e"}; !reflect.DeepEqual(g, w) {
- t.Errorf("want bar missing deps %q, got %q", w, g)
- }
- if g, w := bar.srcs, []string{}; !reflect.DeepEqual(g, w) {
- t.Errorf("want bar srcs %q, got %q", w, g)
- }
- }
- func ExampleOutputPath_ReplaceExtension() {
- ctx := &configErrorWrapper{
- config: TestConfig("out", nil, "", nil),
- }
- p := PathForOutput(ctx, "system/framework").Join(ctx, "boot.art")
- p2 := p.ReplaceExtension(ctx, "oat")
- fmt.Println(p, p2)
- fmt.Println(p.Rel(), p2.Rel())
- // Output:
- // out/system/framework/boot.art out/system/framework/boot.oat
- // boot.art boot.oat
- }
- func ExampleOutputPath_FileInSameDir() {
- ctx := &configErrorWrapper{
- config: TestConfig("out", nil, "", nil),
- }
- p := PathForOutput(ctx, "system/framework").Join(ctx, "boot.art")
- p2 := p.InSameDir(ctx, "oat", "arm", "boot.vdex")
- fmt.Println(p, p2)
- fmt.Println(p.Rel(), p2.Rel())
- // Output:
- // out/system/framework/boot.art out/system/framework/oat/arm/boot.vdex
- // boot.art oat/arm/boot.vdex
- }
- func BenchmarkFirstUniquePaths(b *testing.B) {
- implementations := []struct {
- name string
- f func(Paths) Paths
- }{
- {
- name: "list",
- f: firstUniquePathsList,
- },
- {
- name: "map",
- f: firstUniquePathsMap,
- },
- }
- const maxSize = 1024
- uniquePaths := make(Paths, maxSize)
- for i := range uniquePaths {
- uniquePaths[i] = PathForTesting(strconv.Itoa(i))
- }
- samePath := make(Paths, maxSize)
- for i := range samePath {
- samePath[i] = uniquePaths[0]
- }
- f := func(b *testing.B, imp func(Paths) Paths, paths Paths) {
- for i := 0; i < b.N; i++ {
- b.ReportAllocs()
- paths = append(Paths(nil), paths...)
- imp(paths)
- }
- }
- for n := 1; n <= maxSize; n <<= 1 {
- b.Run(strconv.Itoa(n), func(b *testing.B) {
- for _, implementation := range implementations {
- b.Run(implementation.name, func(b *testing.B) {
- b.Run("same", func(b *testing.B) {
- f(b, implementation.f, samePath[:n])
- })
- b.Run("unique", func(b *testing.B) {
- f(b, implementation.f, uniquePaths[:n])
- })
- })
- }
- })
- }
- }
|