1*333d2b36SAndroid Build Coastguard Worker// Copyright 2017 Google Inc. All rights reserved. 2*333d2b36SAndroid Build Coastguard Worker// 3*333d2b36SAndroid Build Coastguard Worker// Licensed under the Apache License, Version 2.0 (the "License"); 4*333d2b36SAndroid Build Coastguard Worker// you may not use this file except in compliance with the License. 5*333d2b36SAndroid Build Coastguard Worker// You may obtain a copy of the License at 6*333d2b36SAndroid Build Coastguard Worker// 7*333d2b36SAndroid Build Coastguard Worker// http://www.apache.org/licenses/LICENSE-2.0 8*333d2b36SAndroid Build Coastguard Worker// 9*333d2b36SAndroid Build Coastguard Worker// Unless required by applicable law or agreed to in writing, software 10*333d2b36SAndroid Build Coastguard Worker// distributed under the License is distributed on an "AS IS" BASIS, 11*333d2b36SAndroid Build Coastguard Worker// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12*333d2b36SAndroid Build Coastguard Worker// See the License for the specific language governing permissions and 13*333d2b36SAndroid Build Coastguard Worker// limitations under the License. 14*333d2b36SAndroid Build Coastguard Worker 15*333d2b36SAndroid Build Coastguard Workerpackage android 16*333d2b36SAndroid Build Coastguard Worker 17*333d2b36SAndroid Build Coastguard Workerimport ( 18*333d2b36SAndroid Build Coastguard Worker "bytes" 19*333d2b36SAndroid Build Coastguard Worker "fmt" 20*333d2b36SAndroid Build Coastguard Worker "path/filepath" 21*333d2b36SAndroid Build Coastguard Worker "regexp" 22*333d2b36SAndroid Build Coastguard Worker "runtime" 23*333d2b36SAndroid Build Coastguard Worker "sort" 24*333d2b36SAndroid Build Coastguard Worker "strings" 25*333d2b36SAndroid Build Coastguard Worker "sync" 26*333d2b36SAndroid Build Coastguard Worker "testing" 27*333d2b36SAndroid Build Coastguard Worker 28*333d2b36SAndroid Build Coastguard Worker mkparser "android/soong/androidmk/parser" 29*333d2b36SAndroid Build Coastguard Worker 30*333d2b36SAndroid Build Coastguard Worker "github.com/google/blueprint" 31*333d2b36SAndroid Build Coastguard Worker "github.com/google/blueprint/proptools" 32*333d2b36SAndroid Build Coastguard Worker) 33*333d2b36SAndroid Build Coastguard Worker 34*333d2b36SAndroid Build Coastguard Workerfunc newTestContextForFixture(config Config) *TestContext { 35*333d2b36SAndroid Build Coastguard Worker ctx := &TestContext{ 36*333d2b36SAndroid Build Coastguard Worker Context: &Context{blueprint.NewContext(), config}, 37*333d2b36SAndroid Build Coastguard Worker } 38*333d2b36SAndroid Build Coastguard Worker 39*333d2b36SAndroid Build Coastguard Worker ctx.postDeps = append(ctx.postDeps, registerPathDepsMutator) 40*333d2b36SAndroid Build Coastguard Worker 41*333d2b36SAndroid Build Coastguard Worker ctx.SetFs(ctx.config.fs) 42*333d2b36SAndroid Build Coastguard Worker if ctx.config.mockBpList != "" { 43*333d2b36SAndroid Build Coastguard Worker ctx.SetModuleListFile(ctx.config.mockBpList) 44*333d2b36SAndroid Build Coastguard Worker } 45*333d2b36SAndroid Build Coastguard Worker 46*333d2b36SAndroid Build Coastguard Worker return ctx 47*333d2b36SAndroid Build Coastguard Worker} 48*333d2b36SAndroid Build Coastguard Worker 49*333d2b36SAndroid Build Coastguard Workerfunc NewTestContext(config Config) *TestContext { 50*333d2b36SAndroid Build Coastguard Worker ctx := newTestContextForFixture(config) 51*333d2b36SAndroid Build Coastguard Worker 52*333d2b36SAndroid Build Coastguard Worker nameResolver := NewNameResolver(config) 53*333d2b36SAndroid Build Coastguard Worker ctx.NameResolver = nameResolver 54*333d2b36SAndroid Build Coastguard Worker ctx.SetNameInterface(nameResolver) 55*333d2b36SAndroid Build Coastguard Worker 56*333d2b36SAndroid Build Coastguard Worker return ctx 57*333d2b36SAndroid Build Coastguard Worker} 58*333d2b36SAndroid Build Coastguard Worker 59*333d2b36SAndroid Build Coastguard Workervar PrepareForTestWithArchMutator = GroupFixturePreparers( 60*333d2b36SAndroid Build Coastguard Worker // Configure architecture targets in the fixture config. 61*333d2b36SAndroid Build Coastguard Worker FixtureModifyConfig(modifyTestConfigToSupportArchMutator), 62*333d2b36SAndroid Build Coastguard Worker 63*333d2b36SAndroid Build Coastguard Worker // Add the arch mutator to the context. 64*333d2b36SAndroid Build Coastguard Worker FixtureRegisterWithContext(func(ctx RegistrationContext) { 65*333d2b36SAndroid Build Coastguard Worker ctx.PreDepsMutators(registerArchMutator) 66*333d2b36SAndroid Build Coastguard Worker }), 67*333d2b36SAndroid Build Coastguard Worker) 68*333d2b36SAndroid Build Coastguard Worker 69*333d2b36SAndroid Build Coastguard Workervar PrepareForTestWithDefaults = FixtureRegisterWithContext(func(ctx RegistrationContext) { 70*333d2b36SAndroid Build Coastguard Worker ctx.PreArchMutators(RegisterDefaultsPreArchMutators) 71*333d2b36SAndroid Build Coastguard Worker}) 72*333d2b36SAndroid Build Coastguard Worker 73*333d2b36SAndroid Build Coastguard Workervar PrepareForTestWithComponentsMutator = FixtureRegisterWithContext(func(ctx RegistrationContext) { 74*333d2b36SAndroid Build Coastguard Worker ctx.PreArchMutators(RegisterComponentsMutator) 75*333d2b36SAndroid Build Coastguard Worker}) 76*333d2b36SAndroid Build Coastguard Worker 77*333d2b36SAndroid Build Coastguard Workervar PrepareForTestWithPrebuilts = FixtureRegisterWithContext(RegisterPrebuiltMutators) 78*333d2b36SAndroid Build Coastguard Worker 79*333d2b36SAndroid Build Coastguard Workervar PrepareForTestWithOverrides = FixtureRegisterWithContext(func(ctx RegistrationContext) { 80*333d2b36SAndroid Build Coastguard Worker ctx.PostDepsMutators(RegisterOverridePostDepsMutators) 81*333d2b36SAndroid Build Coastguard Worker}) 82*333d2b36SAndroid Build Coastguard Worker 83*333d2b36SAndroid Build Coastguard Workervar PrepareForTestWithLicenses = GroupFixturePreparers( 84*333d2b36SAndroid Build Coastguard Worker FixtureRegisterWithContext(RegisterLicenseKindBuildComponents), 85*333d2b36SAndroid Build Coastguard Worker FixtureRegisterWithContext(RegisterLicenseBuildComponents), 86*333d2b36SAndroid Build Coastguard Worker FixtureRegisterWithContext(registerLicenseMutators), 87*333d2b36SAndroid Build Coastguard Worker) 88*333d2b36SAndroid Build Coastguard Worker 89*333d2b36SAndroid Build Coastguard Workervar PrepareForTestWithGenNotice = FixtureRegisterWithContext(RegisterGenNoticeBuildComponents) 90*333d2b36SAndroid Build Coastguard Worker 91*333d2b36SAndroid Build Coastguard Workerfunc registerLicenseMutators(ctx RegistrationContext) { 92*333d2b36SAndroid Build Coastguard Worker ctx.PreArchMutators(RegisterLicensesPackageMapper) 93*333d2b36SAndroid Build Coastguard Worker ctx.PreArchMutators(RegisterLicensesPropertyGatherer) 94*333d2b36SAndroid Build Coastguard Worker ctx.PostDepsMutators(RegisterLicensesDependencyChecker) 95*333d2b36SAndroid Build Coastguard Worker} 96*333d2b36SAndroid Build Coastguard Worker 97*333d2b36SAndroid Build Coastguard Workervar PrepareForTestWithLicenseDefaultModules = GroupFixturePreparers( 98*333d2b36SAndroid Build Coastguard Worker FixtureAddTextFile("build/soong/licenses/Android.bp", ` 99*333d2b36SAndroid Build Coastguard Worker license { 100*333d2b36SAndroid Build Coastguard Worker name: "Android-Apache-2.0", 101*333d2b36SAndroid Build Coastguard Worker package_name: "Android", 102*333d2b36SAndroid Build Coastguard Worker license_kinds: ["SPDX-license-identifier-Apache-2.0"], 103*333d2b36SAndroid Build Coastguard Worker copyright_notice: "Copyright (C) The Android Open Source Project", 104*333d2b36SAndroid Build Coastguard Worker license_text: ["LICENSE"], 105*333d2b36SAndroid Build Coastguard Worker } 106*333d2b36SAndroid Build Coastguard Worker 107*333d2b36SAndroid Build Coastguard Worker license_kind { 108*333d2b36SAndroid Build Coastguard Worker name: "SPDX-license-identifier-Apache-2.0", 109*333d2b36SAndroid Build Coastguard Worker conditions: ["notice"], 110*333d2b36SAndroid Build Coastguard Worker url: "https://spdx.org/licenses/Apache-2.0.html", 111*333d2b36SAndroid Build Coastguard Worker } 112*333d2b36SAndroid Build Coastguard Worker 113*333d2b36SAndroid Build Coastguard Worker license_kind { 114*333d2b36SAndroid Build Coastguard Worker name: "legacy_unencumbered", 115*333d2b36SAndroid Build Coastguard Worker conditions: ["unencumbered"], 116*333d2b36SAndroid Build Coastguard Worker } 117*333d2b36SAndroid Build Coastguard Worker `), 118*333d2b36SAndroid Build Coastguard Worker FixtureAddFile("build/soong/licenses/LICENSE", nil), 119*333d2b36SAndroid Build Coastguard Worker) 120*333d2b36SAndroid Build Coastguard Worker 121*333d2b36SAndroid Build Coastguard Workervar PrepareForTestWithNamespace = FixtureRegisterWithContext(func(ctx RegistrationContext) { 122*333d2b36SAndroid Build Coastguard Worker registerNamespaceBuildComponents(ctx) 123*333d2b36SAndroid Build Coastguard Worker ctx.PreArchMutators(RegisterNamespaceMutator) 124*333d2b36SAndroid Build Coastguard Worker}) 125*333d2b36SAndroid Build Coastguard Worker 126*333d2b36SAndroid Build Coastguard Workervar PrepareForTestWithMakevars = FixtureRegisterWithContext(func(ctx RegistrationContext) { 127*333d2b36SAndroid Build Coastguard Worker ctx.RegisterSingletonType("makevars", makeVarsSingletonFunc) 128*333d2b36SAndroid Build Coastguard Worker}) 129*333d2b36SAndroid Build Coastguard Worker 130*333d2b36SAndroid Build Coastguard Workervar PrepareForTestVintfFragmentModules = FixtureRegisterWithContext(func(ctx RegistrationContext) { 131*333d2b36SAndroid Build Coastguard Worker registerVintfFragmentComponents(ctx) 132*333d2b36SAndroid Build Coastguard Worker}) 133*333d2b36SAndroid Build Coastguard Worker 134*333d2b36SAndroid Build Coastguard Worker// Test fixture preparer that will register most java build components. 135*333d2b36SAndroid Build Coastguard Worker// 136*333d2b36SAndroid Build Coastguard Worker// Singletons and mutators should only be added here if they are needed for a majority of java 137*333d2b36SAndroid Build Coastguard Worker// module types, otherwise they should be added under a separate preparer to allow them to be 138*333d2b36SAndroid Build Coastguard Worker// selected only when needed to reduce test execution time. 139*333d2b36SAndroid Build Coastguard Worker// 140*333d2b36SAndroid Build Coastguard Worker// Module types do not have much of an overhead unless they are used so this should include as many 141*333d2b36SAndroid Build Coastguard Worker// module types as possible. The exceptions are those module types that require mutators and/or 142*333d2b36SAndroid Build Coastguard Worker// singletons in order to function in which case they should be kept together in a separate 143*333d2b36SAndroid Build Coastguard Worker// preparer. 144*333d2b36SAndroid Build Coastguard Worker// 145*333d2b36SAndroid Build Coastguard Worker// The mutators in this group were chosen because they are needed by the vast majority of tests. 146*333d2b36SAndroid Build Coastguard Workervar PrepareForTestWithAndroidBuildComponents = GroupFixturePreparers( 147*333d2b36SAndroid Build Coastguard Worker // Sorted alphabetically as the actual order does not matter as tests automatically enforce the 148*333d2b36SAndroid Build Coastguard Worker // correct order. 149*333d2b36SAndroid Build Coastguard Worker PrepareForTestWithArchMutator, 150*333d2b36SAndroid Build Coastguard Worker PrepareForTestWithComponentsMutator, 151*333d2b36SAndroid Build Coastguard Worker PrepareForTestWithDefaults, 152*333d2b36SAndroid Build Coastguard Worker PrepareForTestWithFilegroup, 153*333d2b36SAndroid Build Coastguard Worker PrepareForTestWithOverrides, 154*333d2b36SAndroid Build Coastguard Worker PrepareForTestWithPackageModule, 155*333d2b36SAndroid Build Coastguard Worker PrepareForTestWithPrebuilts, 156*333d2b36SAndroid Build Coastguard Worker PrepareForTestWithVisibility, 157*333d2b36SAndroid Build Coastguard Worker PrepareForTestVintfFragmentModules, 158*333d2b36SAndroid Build Coastguard Worker) 159*333d2b36SAndroid Build Coastguard Worker 160*333d2b36SAndroid Build Coastguard Worker// Prepares an integration test with all build components from the android package. 161*333d2b36SAndroid Build Coastguard Worker// 162*333d2b36SAndroid Build Coastguard Worker// This should only be used by tests that want to run with as much of the build enabled as possible. 163*333d2b36SAndroid Build Coastguard Workervar PrepareForIntegrationTestWithAndroid = GroupFixturePreparers( 164*333d2b36SAndroid Build Coastguard Worker PrepareForTestWithAndroidBuildComponents, 165*333d2b36SAndroid Build Coastguard Worker) 166*333d2b36SAndroid Build Coastguard Worker 167*333d2b36SAndroid Build Coastguard Worker// Prepares a test that may be missing dependencies by setting allow_missing_dependencies to 168*333d2b36SAndroid Build Coastguard Worker// true. 169*333d2b36SAndroid Build Coastguard Workervar PrepareForTestWithAllowMissingDependencies = GroupFixturePreparers( 170*333d2b36SAndroid Build Coastguard Worker FixtureModifyProductVariables(func(variables FixtureProductVariables) { 171*333d2b36SAndroid Build Coastguard Worker variables.Allow_missing_dependencies = proptools.BoolPtr(true) 172*333d2b36SAndroid Build Coastguard Worker }), 173*333d2b36SAndroid Build Coastguard Worker FixtureModifyContext(func(ctx *TestContext) { 174*333d2b36SAndroid Build Coastguard Worker ctx.SetAllowMissingDependencies(true) 175*333d2b36SAndroid Build Coastguard Worker }), 176*333d2b36SAndroid Build Coastguard Worker) 177*333d2b36SAndroid Build Coastguard Worker 178*333d2b36SAndroid Build Coastguard Worker// Prepares a test that disallows non-existent paths. 179*333d2b36SAndroid Build Coastguard Workervar PrepareForTestDisallowNonExistentPaths = FixtureModifyConfig(func(config Config) { 180*333d2b36SAndroid Build Coastguard Worker config.TestAllowNonExistentPaths = false 181*333d2b36SAndroid Build Coastguard Worker}) 182*333d2b36SAndroid Build Coastguard Worker 183*333d2b36SAndroid Build Coastguard Worker// PrepareForTestWithBuildFlag returns a FixturePreparer that sets the given flag to the given value. 184*333d2b36SAndroid Build Coastguard Workerfunc PrepareForTestWithBuildFlag(flag, value string) FixturePreparer { 185*333d2b36SAndroid Build Coastguard Worker return FixtureModifyProductVariables(func(variables FixtureProductVariables) { 186*333d2b36SAndroid Build Coastguard Worker if variables.BuildFlags == nil { 187*333d2b36SAndroid Build Coastguard Worker variables.BuildFlags = make(map[string]string) 188*333d2b36SAndroid Build Coastguard Worker } 189*333d2b36SAndroid Build Coastguard Worker variables.BuildFlags[flag] = value 190*333d2b36SAndroid Build Coastguard Worker }) 191*333d2b36SAndroid Build Coastguard Worker} 192*333d2b36SAndroid Build Coastguard Worker 193*333d2b36SAndroid Build Coastguard Worker// PrepareForNativeBridgeEnabled sets configuration with targets including: 194*333d2b36SAndroid Build Coastguard Worker// - X86_64 (primary) 195*333d2b36SAndroid Build Coastguard Worker// - X86 (secondary) 196*333d2b36SAndroid Build Coastguard Worker// - Arm64 on X86_64 (native bridge) 197*333d2b36SAndroid Build Coastguard Worker// - Arm on X86 (native bridge) 198*333d2b36SAndroid Build Coastguard Workervar PrepareForNativeBridgeEnabled = FixtureModifyConfig( 199*333d2b36SAndroid Build Coastguard Worker func(config Config) { 200*333d2b36SAndroid Build Coastguard Worker config.Targets[Android] = []Target{ 201*333d2b36SAndroid Build Coastguard Worker {Os: Android, Arch: Arch{ArchType: X86_64, ArchVariant: "silvermont", Abi: []string{"arm64-v8a"}}, 202*333d2b36SAndroid Build Coastguard Worker NativeBridge: NativeBridgeDisabled, NativeBridgeHostArchName: "", NativeBridgeRelativePath: ""}, 203*333d2b36SAndroid Build Coastguard Worker {Os: Android, Arch: Arch{ArchType: X86, ArchVariant: "silvermont", Abi: []string{"armeabi-v7a"}}, 204*333d2b36SAndroid Build Coastguard Worker NativeBridge: NativeBridgeDisabled, NativeBridgeHostArchName: "", NativeBridgeRelativePath: ""}, 205*333d2b36SAndroid Build Coastguard Worker {Os: Android, Arch: Arch{ArchType: Arm64, ArchVariant: "armv8-a", Abi: []string{"arm64-v8a"}}, 206*333d2b36SAndroid Build Coastguard Worker NativeBridge: NativeBridgeEnabled, NativeBridgeHostArchName: "x86_64", NativeBridgeRelativePath: "arm64"}, 207*333d2b36SAndroid Build Coastguard Worker {Os: Android, Arch: Arch{ArchType: Arm, ArchVariant: "armv7-a-neon", Abi: []string{"armeabi-v7a"}}, 208*333d2b36SAndroid Build Coastguard Worker NativeBridge: NativeBridgeEnabled, NativeBridgeHostArchName: "x86", NativeBridgeRelativePath: "arm"}, 209*333d2b36SAndroid Build Coastguard Worker } 210*333d2b36SAndroid Build Coastguard Worker }, 211*333d2b36SAndroid Build Coastguard Worker) 212*333d2b36SAndroid Build Coastguard Worker 213*333d2b36SAndroid Build Coastguard Workerfunc NewTestArchContext(config Config) *TestContext { 214*333d2b36SAndroid Build Coastguard Worker ctx := NewTestContext(config) 215*333d2b36SAndroid Build Coastguard Worker ctx.preDeps = append(ctx.preDeps, registerArchMutator) 216*333d2b36SAndroid Build Coastguard Worker return ctx 217*333d2b36SAndroid Build Coastguard Worker} 218*333d2b36SAndroid Build Coastguard Worker 219*333d2b36SAndroid Build Coastguard Workertype TestContext struct { 220*333d2b36SAndroid Build Coastguard Worker *Context 221*333d2b36SAndroid Build Coastguard Worker preArch, preDeps, postDeps, postApex, finalDeps []RegisterMutatorFunc 222*333d2b36SAndroid Build Coastguard Worker NameResolver *NameResolver 223*333d2b36SAndroid Build Coastguard Worker 224*333d2b36SAndroid Build Coastguard Worker // The list of singletons registered for the test. 225*333d2b36SAndroid Build Coastguard Worker singletons sortableComponents 226*333d2b36SAndroid Build Coastguard Worker 227*333d2b36SAndroid Build Coastguard Worker // The order in which the mutators and singletons will be run in this test 228*333d2b36SAndroid Build Coastguard Worker // context; for debugging. 229*333d2b36SAndroid Build Coastguard Worker mutatorOrder, singletonOrder []string 230*333d2b36SAndroid Build Coastguard Worker} 231*333d2b36SAndroid Build Coastguard Worker 232*333d2b36SAndroid Build Coastguard Workerfunc (ctx *TestContext) PreArchMutators(f RegisterMutatorFunc) { 233*333d2b36SAndroid Build Coastguard Worker ctx.preArch = append(ctx.preArch, f) 234*333d2b36SAndroid Build Coastguard Worker} 235*333d2b36SAndroid Build Coastguard Worker 236*333d2b36SAndroid Build Coastguard Workerfunc (ctx *TestContext) HardCodedPreArchMutators(f RegisterMutatorFunc) { 237*333d2b36SAndroid Build Coastguard Worker // Register mutator function as normal for testing. 238*333d2b36SAndroid Build Coastguard Worker ctx.PreArchMutators(f) 239*333d2b36SAndroid Build Coastguard Worker} 240*333d2b36SAndroid Build Coastguard Worker 241*333d2b36SAndroid Build Coastguard Workerfunc (ctx *TestContext) otherModuleProvider(m blueprint.Module, p blueprint.AnyProviderKey) (any, bool) { 242*333d2b36SAndroid Build Coastguard Worker return ctx.Context.ModuleProvider(m, p) 243*333d2b36SAndroid Build Coastguard Worker} 244*333d2b36SAndroid Build Coastguard Worker 245*333d2b36SAndroid Build Coastguard Workerfunc (ctx *TestContext) PreDepsMutators(f RegisterMutatorFunc) { 246*333d2b36SAndroid Build Coastguard Worker ctx.preDeps = append(ctx.preDeps, f) 247*333d2b36SAndroid Build Coastguard Worker} 248*333d2b36SAndroid Build Coastguard Worker 249*333d2b36SAndroid Build Coastguard Workerfunc (ctx *TestContext) PostDepsMutators(f RegisterMutatorFunc) { 250*333d2b36SAndroid Build Coastguard Worker ctx.postDeps = append(ctx.postDeps, f) 251*333d2b36SAndroid Build Coastguard Worker} 252*333d2b36SAndroid Build Coastguard Worker 253*333d2b36SAndroid Build Coastguard Workerfunc (ctx *TestContext) PostApexMutators(f RegisterMutatorFunc) { 254*333d2b36SAndroid Build Coastguard Worker ctx.postApex = append(ctx.postApex, f) 255*333d2b36SAndroid Build Coastguard Worker} 256*333d2b36SAndroid Build Coastguard Worker 257*333d2b36SAndroid Build Coastguard Workerfunc (ctx *TestContext) FinalDepsMutators(f RegisterMutatorFunc) { 258*333d2b36SAndroid Build Coastguard Worker ctx.finalDeps = append(ctx.finalDeps, f) 259*333d2b36SAndroid Build Coastguard Worker} 260*333d2b36SAndroid Build Coastguard Worker 261*333d2b36SAndroid Build Coastguard Workerfunc (ctx *TestContext) OtherModuleProviderAdaptor() OtherModuleProviderContext { 262*333d2b36SAndroid Build Coastguard Worker return NewOtherModuleProviderAdaptor(func(module blueprint.Module, provider blueprint.AnyProviderKey) (any, bool) { 263*333d2b36SAndroid Build Coastguard Worker return ctx.otherModuleProvider(module, provider) 264*333d2b36SAndroid Build Coastguard Worker }) 265*333d2b36SAndroid Build Coastguard Worker} 266*333d2b36SAndroid Build Coastguard Worker 267*333d2b36SAndroid Build Coastguard Workerfunc (ctx *TestContext) OtherModulePropertyErrorf(module Module, property string, fmt_ string, args ...interface{}) { 268*333d2b36SAndroid Build Coastguard Worker panic(fmt.Sprintf(fmt_, args...)) 269*333d2b36SAndroid Build Coastguard Worker} 270*333d2b36SAndroid Build Coastguard Worker 271*333d2b36SAndroid Build Coastguard Worker// registeredComponentOrder defines the order in which a sortableComponent type is registered at 272*333d2b36SAndroid Build Coastguard Worker// runtime and provides support for reordering the components registered for a test in the same 273*333d2b36SAndroid Build Coastguard Worker// way. 274*333d2b36SAndroid Build Coastguard Workertype registeredComponentOrder struct { 275*333d2b36SAndroid Build Coastguard Worker // The name of the component type, used for error messages. 276*333d2b36SAndroid Build Coastguard Worker componentType string 277*333d2b36SAndroid Build Coastguard Worker 278*333d2b36SAndroid Build Coastguard Worker // The names of the registered components in the order in which they were registered. 279*333d2b36SAndroid Build Coastguard Worker namesInOrder []string 280*333d2b36SAndroid Build Coastguard Worker 281*333d2b36SAndroid Build Coastguard Worker // Maps from the component name to its position in the runtime ordering. 282*333d2b36SAndroid Build Coastguard Worker namesToIndex map[string]int 283*333d2b36SAndroid Build Coastguard Worker 284*333d2b36SAndroid Build Coastguard Worker // A function that defines the order between two named components that can be used to sort a slice 285*333d2b36SAndroid Build Coastguard Worker // of component names into the same order as they appear in namesInOrder. 286*333d2b36SAndroid Build Coastguard Worker less func(string, string) bool 287*333d2b36SAndroid Build Coastguard Worker} 288*333d2b36SAndroid Build Coastguard Worker 289*333d2b36SAndroid Build Coastguard Worker// registeredComponentOrderFromExistingOrder takes an existing slice of sortableComponents and 290*333d2b36SAndroid Build Coastguard Worker// creates a registeredComponentOrder that contains a less function that can be used to sort a 291*333d2b36SAndroid Build Coastguard Worker// subset of that list of names so it is in the same order as the original sortableComponents. 292*333d2b36SAndroid Build Coastguard Workerfunc registeredComponentOrderFromExistingOrder(componentType string, existingOrder sortableComponents) registeredComponentOrder { 293*333d2b36SAndroid Build Coastguard Worker // Only the names from the existing order are needed for this so create a list of component names 294*333d2b36SAndroid Build Coastguard Worker // in the correct order. 295*333d2b36SAndroid Build Coastguard Worker namesInOrder := componentsToNames(existingOrder) 296*333d2b36SAndroid Build Coastguard Worker 297*333d2b36SAndroid Build Coastguard Worker // Populate the map from name to position in the list. 298*333d2b36SAndroid Build Coastguard Worker nameToIndex := make(map[string]int) 299*333d2b36SAndroid Build Coastguard Worker for i, n := range namesInOrder { 300*333d2b36SAndroid Build Coastguard Worker nameToIndex[n] = i 301*333d2b36SAndroid Build Coastguard Worker } 302*333d2b36SAndroid Build Coastguard Worker 303*333d2b36SAndroid Build Coastguard Worker // A function to use to map from a name to an index in the original order. 304*333d2b36SAndroid Build Coastguard Worker indexOf := func(name string) int { 305*333d2b36SAndroid Build Coastguard Worker index, ok := nameToIndex[name] 306*333d2b36SAndroid Build Coastguard Worker if !ok { 307*333d2b36SAndroid Build Coastguard Worker // Should never happen as tests that use components that are not known at runtime do not sort 308*333d2b36SAndroid Build Coastguard Worker // so should never use this function. 309*333d2b36SAndroid Build Coastguard Worker panic(fmt.Errorf("internal error: unknown %s %q should be one of %s", componentType, name, strings.Join(namesInOrder, ", "))) 310*333d2b36SAndroid Build Coastguard Worker } 311*333d2b36SAndroid Build Coastguard Worker return index 312*333d2b36SAndroid Build Coastguard Worker } 313*333d2b36SAndroid Build Coastguard Worker 314*333d2b36SAndroid Build Coastguard Worker // The less function. 315*333d2b36SAndroid Build Coastguard Worker less := func(n1, n2 string) bool { 316*333d2b36SAndroid Build Coastguard Worker i1 := indexOf(n1) 317*333d2b36SAndroid Build Coastguard Worker i2 := indexOf(n2) 318*333d2b36SAndroid Build Coastguard Worker return i1 < i2 319*333d2b36SAndroid Build Coastguard Worker } 320*333d2b36SAndroid Build Coastguard Worker 321*333d2b36SAndroid Build Coastguard Worker return registeredComponentOrder{ 322*333d2b36SAndroid Build Coastguard Worker componentType: componentType, 323*333d2b36SAndroid Build Coastguard Worker namesInOrder: namesInOrder, 324*333d2b36SAndroid Build Coastguard Worker namesToIndex: nameToIndex, 325*333d2b36SAndroid Build Coastguard Worker less: less, 326*333d2b36SAndroid Build Coastguard Worker } 327*333d2b36SAndroid Build Coastguard Worker} 328*333d2b36SAndroid Build Coastguard Worker 329*333d2b36SAndroid Build Coastguard Worker// componentsToNames maps from the slice of components to a slice of their names. 330*333d2b36SAndroid Build Coastguard Workerfunc componentsToNames(components sortableComponents) []string { 331*333d2b36SAndroid Build Coastguard Worker names := make([]string, len(components)) 332*333d2b36SAndroid Build Coastguard Worker for i, c := range components { 333*333d2b36SAndroid Build Coastguard Worker names[i] = c.componentName() 334*333d2b36SAndroid Build Coastguard Worker } 335*333d2b36SAndroid Build Coastguard Worker return names 336*333d2b36SAndroid Build Coastguard Worker} 337*333d2b36SAndroid Build Coastguard Worker 338*333d2b36SAndroid Build Coastguard Worker// enforceOrdering enforces the supplied components are in the same order as is defined in this 339*333d2b36SAndroid Build Coastguard Worker// object. 340*333d2b36SAndroid Build Coastguard Worker// 341*333d2b36SAndroid Build Coastguard Worker// If the supplied components contains any components that are not registered at runtime, i.e. test 342*333d2b36SAndroid Build Coastguard Worker// specific components, then it is impossible to sort them into an order that both matches the 343*333d2b36SAndroid Build Coastguard Worker// runtime and also preserves the implicit ordering defined in the test. In that case it will not 344*333d2b36SAndroid Build Coastguard Worker// sort the components, instead it will just check that the components are in the correct order. 345*333d2b36SAndroid Build Coastguard Worker// 346*333d2b36SAndroid Build Coastguard Worker// Otherwise, this will sort the supplied components in place. 347*333d2b36SAndroid Build Coastguard Workerfunc (o *registeredComponentOrder) enforceOrdering(components sortableComponents) { 348*333d2b36SAndroid Build Coastguard Worker // Check to see if the list of components contains any components that are 349*333d2b36SAndroid Build Coastguard Worker // not registered at runtime. 350*333d2b36SAndroid Build Coastguard Worker var unknownComponents []string 351*333d2b36SAndroid Build Coastguard Worker testOrder := componentsToNames(components) 352*333d2b36SAndroid Build Coastguard Worker for _, name := range testOrder { 353*333d2b36SAndroid Build Coastguard Worker if _, ok := o.namesToIndex[name]; !ok { 354*333d2b36SAndroid Build Coastguard Worker unknownComponents = append(unknownComponents, name) 355*333d2b36SAndroid Build Coastguard Worker break 356*333d2b36SAndroid Build Coastguard Worker } 357*333d2b36SAndroid Build Coastguard Worker } 358*333d2b36SAndroid Build Coastguard Worker 359*333d2b36SAndroid Build Coastguard Worker // If the slice contains some unknown components then it is not possible to 360*333d2b36SAndroid Build Coastguard Worker // sort them into an order that matches the runtime while also preserving the 361*333d2b36SAndroid Build Coastguard Worker // order expected from the test, so in that case don't sort just check that 362*333d2b36SAndroid Build Coastguard Worker // the order of the known mutators does match. 363*333d2b36SAndroid Build Coastguard Worker if len(unknownComponents) > 0 { 364*333d2b36SAndroid Build Coastguard Worker // Check order. 365*333d2b36SAndroid Build Coastguard Worker o.checkTestOrder(testOrder, unknownComponents) 366*333d2b36SAndroid Build Coastguard Worker } else { 367*333d2b36SAndroid Build Coastguard Worker // Sort the components. 368*333d2b36SAndroid Build Coastguard Worker sort.Slice(components, func(i, j int) bool { 369*333d2b36SAndroid Build Coastguard Worker n1 := components[i].componentName() 370*333d2b36SAndroid Build Coastguard Worker n2 := components[j].componentName() 371*333d2b36SAndroid Build Coastguard Worker return o.less(n1, n2) 372*333d2b36SAndroid Build Coastguard Worker }) 373*333d2b36SAndroid Build Coastguard Worker } 374*333d2b36SAndroid Build Coastguard Worker} 375*333d2b36SAndroid Build Coastguard Worker 376*333d2b36SAndroid Build Coastguard Worker// checkTestOrder checks that the supplied testOrder matches the one defined by this object, 377*333d2b36SAndroid Build Coastguard Worker// panicking if it does not. 378*333d2b36SAndroid Build Coastguard Workerfunc (o *registeredComponentOrder) checkTestOrder(testOrder []string, unknownComponents []string) { 379*333d2b36SAndroid Build Coastguard Worker lastMatchingTest := -1 380*333d2b36SAndroid Build Coastguard Worker matchCount := 0 381*333d2b36SAndroid Build Coastguard Worker // Take a copy of the runtime order as it is modified during the comparison. 382*333d2b36SAndroid Build Coastguard Worker runtimeOrder := append([]string(nil), o.namesInOrder...) 383*333d2b36SAndroid Build Coastguard Worker componentType := o.componentType 384*333d2b36SAndroid Build Coastguard Worker for i, j := 0, 0; i < len(testOrder) && j < len(runtimeOrder); { 385*333d2b36SAndroid Build Coastguard Worker test := testOrder[i] 386*333d2b36SAndroid Build Coastguard Worker runtime := runtimeOrder[j] 387*333d2b36SAndroid Build Coastguard Worker 388*333d2b36SAndroid Build Coastguard Worker if test == runtime { 389*333d2b36SAndroid Build Coastguard Worker testOrder[i] = test + fmt.Sprintf(" <-- matched with runtime %s %d", componentType, j) 390*333d2b36SAndroid Build Coastguard Worker runtimeOrder[j] = runtime + fmt.Sprintf(" <-- matched with test %s %d", componentType, i) 391*333d2b36SAndroid Build Coastguard Worker lastMatchingTest = i 392*333d2b36SAndroid Build Coastguard Worker i += 1 393*333d2b36SAndroid Build Coastguard Worker j += 1 394*333d2b36SAndroid Build Coastguard Worker matchCount += 1 395*333d2b36SAndroid Build Coastguard Worker } else if _, ok := o.namesToIndex[test]; !ok { 396*333d2b36SAndroid Build Coastguard Worker // The test component is not registered globally so assume it is the correct place, treat it 397*333d2b36SAndroid Build Coastguard Worker // as having matched and skip it. 398*333d2b36SAndroid Build Coastguard Worker i += 1 399*333d2b36SAndroid Build Coastguard Worker matchCount += 1 400*333d2b36SAndroid Build Coastguard Worker } else { 401*333d2b36SAndroid Build Coastguard Worker // Assume that the test list is in the same order as the runtime list but the runtime list 402*333d2b36SAndroid Build Coastguard Worker // contains some components that are not present in the tests. So, skip the runtime component 403*333d2b36SAndroid Build Coastguard Worker // to try and find the next one that matches the current test component. 404*333d2b36SAndroid Build Coastguard Worker j += 1 405*333d2b36SAndroid Build Coastguard Worker } 406*333d2b36SAndroid Build Coastguard Worker } 407*333d2b36SAndroid Build Coastguard Worker 408*333d2b36SAndroid Build Coastguard Worker // If every item in the test order was either test specific or matched one in the runtime then 409*333d2b36SAndroid Build Coastguard Worker // it is in the correct order. Otherwise, it was not so fail. 410*333d2b36SAndroid Build Coastguard Worker if matchCount != len(testOrder) { 411*333d2b36SAndroid Build Coastguard Worker // The test component names were not all matched with a runtime component name so there must 412*333d2b36SAndroid Build Coastguard Worker // either be a component present in the test that is not present in the runtime or they must be 413*333d2b36SAndroid Build Coastguard Worker // in the wrong order. 414*333d2b36SAndroid Build Coastguard Worker testOrder[lastMatchingTest+1] = testOrder[lastMatchingTest+1] + " <--- unmatched" 415*333d2b36SAndroid Build Coastguard Worker panic(fmt.Errorf("the tests uses test specific components %q and so cannot be automatically sorted."+ 416*333d2b36SAndroid Build Coastguard Worker " Unfortunately it uses %s components in the wrong order.\n"+ 417*333d2b36SAndroid Build Coastguard Worker "test order:\n %s\n"+ 418*333d2b36SAndroid Build Coastguard Worker "runtime order\n %s\n", 419*333d2b36SAndroid Build Coastguard Worker SortedUniqueStrings(unknownComponents), 420*333d2b36SAndroid Build Coastguard Worker componentType, 421*333d2b36SAndroid Build Coastguard Worker strings.Join(testOrder, "\n "), 422*333d2b36SAndroid Build Coastguard Worker strings.Join(runtimeOrder, "\n "))) 423*333d2b36SAndroid Build Coastguard Worker } 424*333d2b36SAndroid Build Coastguard Worker} 425*333d2b36SAndroid Build Coastguard Worker 426*333d2b36SAndroid Build Coastguard Worker// registrationSorter encapsulates the information needed to ensure that the test mutators are 427*333d2b36SAndroid Build Coastguard Worker// registered, and thereby executed, in the same order as they are at runtime. 428*333d2b36SAndroid Build Coastguard Worker// 429*333d2b36SAndroid Build Coastguard Worker// It MUST be populated lazily AFTER all package initialization has been done otherwise it will 430*333d2b36SAndroid Build Coastguard Worker// only define the order for a subset of all the registered build components that are available for 431*333d2b36SAndroid Build Coastguard Worker// the packages being tested. 432*333d2b36SAndroid Build Coastguard Worker// 433*333d2b36SAndroid Build Coastguard Worker// e.g if this is initialized during say the cc package initialization then any tests run in the 434*333d2b36SAndroid Build Coastguard Worker// java package will not sort build components registered by the java package's init() functions. 435*333d2b36SAndroid Build Coastguard Workertype registrationSorter struct { 436*333d2b36SAndroid Build Coastguard Worker // Used to ensure that this is only created once. 437*333d2b36SAndroid Build Coastguard Worker once sync.Once 438*333d2b36SAndroid Build Coastguard Worker 439*333d2b36SAndroid Build Coastguard Worker // The order of mutators 440*333d2b36SAndroid Build Coastguard Worker mutatorOrder registeredComponentOrder 441*333d2b36SAndroid Build Coastguard Worker 442*333d2b36SAndroid Build Coastguard Worker // The order of singletons 443*333d2b36SAndroid Build Coastguard Worker singletonOrder registeredComponentOrder 444*333d2b36SAndroid Build Coastguard Worker} 445*333d2b36SAndroid Build Coastguard Worker 446*333d2b36SAndroid Build Coastguard Worker// populate initializes this structure from globally registered build components. 447*333d2b36SAndroid Build Coastguard Worker// 448*333d2b36SAndroid Build Coastguard Worker// Only the first call has any effect. 449*333d2b36SAndroid Build Coastguard Workerfunc (s *registrationSorter) populate() { 450*333d2b36SAndroid Build Coastguard Worker s.once.Do(func() { 451*333d2b36SAndroid Build Coastguard Worker // Created an ordering from the globally registered mutators. 452*333d2b36SAndroid Build Coastguard Worker globallyRegisteredMutators := collateGloballyRegisteredMutators() 453*333d2b36SAndroid Build Coastguard Worker s.mutatorOrder = registeredComponentOrderFromExistingOrder("mutator", globallyRegisteredMutators) 454*333d2b36SAndroid Build Coastguard Worker 455*333d2b36SAndroid Build Coastguard Worker // Create an ordering from the globally registered singletons. 456*333d2b36SAndroid Build Coastguard Worker globallyRegisteredSingletons := collateGloballyRegisteredSingletons() 457*333d2b36SAndroid Build Coastguard Worker s.singletonOrder = registeredComponentOrderFromExistingOrder("singleton", globallyRegisteredSingletons) 458*333d2b36SAndroid Build Coastguard Worker }) 459*333d2b36SAndroid Build Coastguard Worker} 460*333d2b36SAndroid Build Coastguard Worker 461*333d2b36SAndroid Build Coastguard Worker// Provides support for enforcing the same order in which build components are registered globally 462*333d2b36SAndroid Build Coastguard Worker// to the order in which they are registered during tests. 463*333d2b36SAndroid Build Coastguard Worker// 464*333d2b36SAndroid Build Coastguard Worker// MUST only be accessed via the globallyRegisteredComponentsOrder func. 465*333d2b36SAndroid Build Coastguard Workervar globalRegistrationSorter registrationSorter 466*333d2b36SAndroid Build Coastguard Worker 467*333d2b36SAndroid Build Coastguard Worker// globallyRegisteredComponentsOrder returns the globalRegistrationSorter after ensuring it is 468*333d2b36SAndroid Build Coastguard Worker// correctly populated. 469*333d2b36SAndroid Build Coastguard Workerfunc globallyRegisteredComponentsOrder() *registrationSorter { 470*333d2b36SAndroid Build Coastguard Worker globalRegistrationSorter.populate() 471*333d2b36SAndroid Build Coastguard Worker return &globalRegistrationSorter 472*333d2b36SAndroid Build Coastguard Worker} 473*333d2b36SAndroid Build Coastguard Worker 474*333d2b36SAndroid Build Coastguard Workerfunc (ctx *TestContext) Register() { 475*333d2b36SAndroid Build Coastguard Worker globalOrder := globallyRegisteredComponentsOrder() 476*333d2b36SAndroid Build Coastguard Worker 477*333d2b36SAndroid Build Coastguard Worker mutators := collateRegisteredMutators(ctx.preArch, ctx.preDeps, ctx.postDeps, ctx.postApex, ctx.finalDeps) 478*333d2b36SAndroid Build Coastguard Worker // Ensure that the mutators used in the test are in the same order as they are used at runtime. 479*333d2b36SAndroid Build Coastguard Worker globalOrder.mutatorOrder.enforceOrdering(mutators) 480*333d2b36SAndroid Build Coastguard Worker mutators.registerAll(ctx.Context) 481*333d2b36SAndroid Build Coastguard Worker 482*333d2b36SAndroid Build Coastguard Worker // Ensure that the singletons used in the test are in the same order as they are used at runtime. 483*333d2b36SAndroid Build Coastguard Worker globalOrder.singletonOrder.enforceOrdering(ctx.singletons) 484*333d2b36SAndroid Build Coastguard Worker ctx.singletons.registerAll(ctx.Context) 485*333d2b36SAndroid Build Coastguard Worker 486*333d2b36SAndroid Build Coastguard Worker // Save the sorted components order away to make them easy to access while debugging. 487*333d2b36SAndroid Build Coastguard Worker ctx.mutatorOrder = componentsToNames(mutators) 488*333d2b36SAndroid Build Coastguard Worker ctx.singletonOrder = componentsToNames(singletons) 489*333d2b36SAndroid Build Coastguard Worker} 490*333d2b36SAndroid Build Coastguard Worker 491*333d2b36SAndroid Build Coastguard Workerfunc (ctx *TestContext) ParseFileList(rootDir string, filePaths []string) (deps []string, errs []error) { 492*333d2b36SAndroid Build Coastguard Worker // This function adapts the old style ParseFileList calls that are spread throughout the tests 493*333d2b36SAndroid Build Coastguard Worker // to the new style that takes a config. 494*333d2b36SAndroid Build Coastguard Worker return ctx.Context.ParseFileList(rootDir, filePaths, ctx.config) 495*333d2b36SAndroid Build Coastguard Worker} 496*333d2b36SAndroid Build Coastguard Worker 497*333d2b36SAndroid Build Coastguard Workerfunc (ctx *TestContext) ParseBlueprintsFiles(rootDir string) (deps []string, errs []error) { 498*333d2b36SAndroid Build Coastguard Worker // This function adapts the old style ParseBlueprintsFiles calls that are spread throughout the 499*333d2b36SAndroid Build Coastguard Worker // tests to the new style that takes a config. 500*333d2b36SAndroid Build Coastguard Worker return ctx.Context.ParseBlueprintsFiles(rootDir, ctx.config) 501*333d2b36SAndroid Build Coastguard Worker} 502*333d2b36SAndroid Build Coastguard Worker 503*333d2b36SAndroid Build Coastguard Workerfunc (ctx *TestContext) RegisterModuleType(name string, factory ModuleFactory) { 504*333d2b36SAndroid Build Coastguard Worker ctx.Context.RegisterModuleType(name, ModuleFactoryAdaptor(factory)) 505*333d2b36SAndroid Build Coastguard Worker} 506*333d2b36SAndroid Build Coastguard Worker 507*333d2b36SAndroid Build Coastguard Workerfunc (ctx *TestContext) RegisterSingletonModuleType(name string, factory SingletonModuleFactory) { 508*333d2b36SAndroid Build Coastguard Worker s, m := SingletonModuleFactoryAdaptor(name, factory) 509*333d2b36SAndroid Build Coastguard Worker ctx.RegisterSingletonType(name, s) 510*333d2b36SAndroid Build Coastguard Worker ctx.RegisterModuleType(name, m) 511*333d2b36SAndroid Build Coastguard Worker} 512*333d2b36SAndroid Build Coastguard Worker 513*333d2b36SAndroid Build Coastguard Workerfunc (ctx *TestContext) RegisterParallelSingletonModuleType(name string, factory SingletonModuleFactory) { 514*333d2b36SAndroid Build Coastguard Worker s, m := SingletonModuleFactoryAdaptor(name, factory) 515*333d2b36SAndroid Build Coastguard Worker ctx.RegisterParallelSingletonType(name, s) 516*333d2b36SAndroid Build Coastguard Worker ctx.RegisterModuleType(name, m) 517*333d2b36SAndroid Build Coastguard Worker} 518*333d2b36SAndroid Build Coastguard Worker 519*333d2b36SAndroid Build Coastguard Workerfunc (ctx *TestContext) RegisterSingletonType(name string, factory SingletonFactory) { 520*333d2b36SAndroid Build Coastguard Worker ctx.singletons = append(ctx.singletons, newSingleton(name, factory, false)) 521*333d2b36SAndroid Build Coastguard Worker} 522*333d2b36SAndroid Build Coastguard Worker 523*333d2b36SAndroid Build Coastguard Workerfunc (ctx *TestContext) RegisterParallelSingletonType(name string, factory SingletonFactory) { 524*333d2b36SAndroid Build Coastguard Worker ctx.singletons = append(ctx.singletons, newSingleton(name, factory, true)) 525*333d2b36SAndroid Build Coastguard Worker} 526*333d2b36SAndroid Build Coastguard Worker 527*333d2b36SAndroid Build Coastguard Worker// ModuleVariantForTests selects a specific variant of the module with the given 528*333d2b36SAndroid Build Coastguard Worker// name by matching the variations map against the variations of each module 529*333d2b36SAndroid Build Coastguard Worker// variant. A module variant matches the map if every variation that exists in 530*333d2b36SAndroid Build Coastguard Worker// both have the same value. Both the module and the map are allowed to have 531*333d2b36SAndroid Build Coastguard Worker// extra variations that the other doesn't have. Panics if not exactly one 532*333d2b36SAndroid Build Coastguard Worker// module variant matches. 533*333d2b36SAndroid Build Coastguard Workerfunc (ctx *TestContext) ModuleVariantForTests(name string, matchVariations map[string]string) TestingModule { 534*333d2b36SAndroid Build Coastguard Worker modules := []Module{} 535*333d2b36SAndroid Build Coastguard Worker ctx.VisitAllModules(func(m blueprint.Module) { 536*333d2b36SAndroid Build Coastguard Worker if ctx.ModuleName(m) == name { 537*333d2b36SAndroid Build Coastguard Worker am := m.(Module) 538*333d2b36SAndroid Build Coastguard Worker amMut := am.base().commonProperties.DebugMutators 539*333d2b36SAndroid Build Coastguard Worker amVar := am.base().commonProperties.DebugVariations 540*333d2b36SAndroid Build Coastguard Worker matched := true 541*333d2b36SAndroid Build Coastguard Worker for i, mut := range amMut { 542*333d2b36SAndroid Build Coastguard Worker if wantedVar, found := matchVariations[mut]; found && amVar[i] != wantedVar { 543*333d2b36SAndroid Build Coastguard Worker matched = false 544*333d2b36SAndroid Build Coastguard Worker break 545*333d2b36SAndroid Build Coastguard Worker } 546*333d2b36SAndroid Build Coastguard Worker } 547*333d2b36SAndroid Build Coastguard Worker if matched { 548*333d2b36SAndroid Build Coastguard Worker modules = append(modules, am) 549*333d2b36SAndroid Build Coastguard Worker } 550*333d2b36SAndroid Build Coastguard Worker } 551*333d2b36SAndroid Build Coastguard Worker }) 552*333d2b36SAndroid Build Coastguard Worker 553*333d2b36SAndroid Build Coastguard Worker if len(modules) == 0 { 554*333d2b36SAndroid Build Coastguard Worker // Show all the modules or module variants that do exist. 555*333d2b36SAndroid Build Coastguard Worker var allModuleNames []string 556*333d2b36SAndroid Build Coastguard Worker var allVariants []string 557*333d2b36SAndroid Build Coastguard Worker ctx.VisitAllModules(func(m blueprint.Module) { 558*333d2b36SAndroid Build Coastguard Worker allModuleNames = append(allModuleNames, ctx.ModuleName(m)) 559*333d2b36SAndroid Build Coastguard Worker if ctx.ModuleName(m) == name { 560*333d2b36SAndroid Build Coastguard Worker allVariants = append(allVariants, m.(Module).String()) 561*333d2b36SAndroid Build Coastguard Worker } 562*333d2b36SAndroid Build Coastguard Worker }) 563*333d2b36SAndroid Build Coastguard Worker 564*333d2b36SAndroid Build Coastguard Worker if len(allVariants) == 0 { 565*333d2b36SAndroid Build Coastguard Worker panic(fmt.Errorf("failed to find module %q. All modules:\n %s", 566*333d2b36SAndroid Build Coastguard Worker name, strings.Join(SortedUniqueStrings(allModuleNames), "\n "))) 567*333d2b36SAndroid Build Coastguard Worker } else { 568*333d2b36SAndroid Build Coastguard Worker sort.Strings(allVariants) 569*333d2b36SAndroid Build Coastguard Worker panic(fmt.Errorf("failed to find module %q matching %v. All variants:\n %s", 570*333d2b36SAndroid Build Coastguard Worker name, matchVariations, strings.Join(allVariants, "\n "))) 571*333d2b36SAndroid Build Coastguard Worker } 572*333d2b36SAndroid Build Coastguard Worker } 573*333d2b36SAndroid Build Coastguard Worker 574*333d2b36SAndroid Build Coastguard Worker if len(modules) > 1 { 575*333d2b36SAndroid Build Coastguard Worker moduleStrings := []string{} 576*333d2b36SAndroid Build Coastguard Worker for _, m := range modules { 577*333d2b36SAndroid Build Coastguard Worker moduleStrings = append(moduleStrings, m.String()) 578*333d2b36SAndroid Build Coastguard Worker } 579*333d2b36SAndroid Build Coastguard Worker sort.Strings(moduleStrings) 580*333d2b36SAndroid Build Coastguard Worker panic(fmt.Errorf("module %q has more than one variant that match %v:\n %s", 581*333d2b36SAndroid Build Coastguard Worker name, matchVariations, strings.Join(moduleStrings, "\n "))) 582*333d2b36SAndroid Build Coastguard Worker } 583*333d2b36SAndroid Build Coastguard Worker 584*333d2b36SAndroid Build Coastguard Worker return newTestingModule(ctx.config, modules[0]) 585*333d2b36SAndroid Build Coastguard Worker} 586*333d2b36SAndroid Build Coastguard Worker 587*333d2b36SAndroid Build Coastguard Workerfunc (ctx *TestContext) ModuleForTests(name, variant string) TestingModule { 588*333d2b36SAndroid Build Coastguard Worker var module Module 589*333d2b36SAndroid Build Coastguard Worker ctx.VisitAllModules(func(m blueprint.Module) { 590*333d2b36SAndroid Build Coastguard Worker if ctx.ModuleName(m) == name && ctx.ModuleSubDir(m) == variant { 591*333d2b36SAndroid Build Coastguard Worker module = m.(Module) 592*333d2b36SAndroid Build Coastguard Worker } 593*333d2b36SAndroid Build Coastguard Worker }) 594*333d2b36SAndroid Build Coastguard Worker 595*333d2b36SAndroid Build Coastguard Worker if module == nil { 596*333d2b36SAndroid Build Coastguard Worker // find all the modules that do exist 597*333d2b36SAndroid Build Coastguard Worker var allModuleNames []string 598*333d2b36SAndroid Build Coastguard Worker var allVariants []string 599*333d2b36SAndroid Build Coastguard Worker ctx.VisitAllModules(func(m blueprint.Module) { 600*333d2b36SAndroid Build Coastguard Worker allModuleNames = append(allModuleNames, ctx.ModuleName(m)) 601*333d2b36SAndroid Build Coastguard Worker if ctx.ModuleName(m) == name { 602*333d2b36SAndroid Build Coastguard Worker allVariants = append(allVariants, ctx.ModuleSubDir(m)) 603*333d2b36SAndroid Build Coastguard Worker } 604*333d2b36SAndroid Build Coastguard Worker }) 605*333d2b36SAndroid Build Coastguard Worker sort.Strings(allVariants) 606*333d2b36SAndroid Build Coastguard Worker 607*333d2b36SAndroid Build Coastguard Worker if len(allVariants) == 0 { 608*333d2b36SAndroid Build Coastguard Worker panic(fmt.Errorf("failed to find module %q. All modules:\n %s", 609*333d2b36SAndroid Build Coastguard Worker name, strings.Join(SortedUniqueStrings(allModuleNames), "\n "))) 610*333d2b36SAndroid Build Coastguard Worker } else { 611*333d2b36SAndroid Build Coastguard Worker panic(fmt.Errorf("failed to find module %q variant %q. All variants:\n %s", 612*333d2b36SAndroid Build Coastguard Worker name, variant, strings.Join(allVariants, "\n "))) 613*333d2b36SAndroid Build Coastguard Worker } 614*333d2b36SAndroid Build Coastguard Worker } 615*333d2b36SAndroid Build Coastguard Worker 616*333d2b36SAndroid Build Coastguard Worker return newTestingModule(ctx.config, module) 617*333d2b36SAndroid Build Coastguard Worker} 618*333d2b36SAndroid Build Coastguard Worker 619*333d2b36SAndroid Build Coastguard Workerfunc (ctx *TestContext) ModuleVariantsForTests(name string) []string { 620*333d2b36SAndroid Build Coastguard Worker var variants []string 621*333d2b36SAndroid Build Coastguard Worker ctx.VisitAllModules(func(m blueprint.Module) { 622*333d2b36SAndroid Build Coastguard Worker if ctx.ModuleName(m) == name { 623*333d2b36SAndroid Build Coastguard Worker variants = append(variants, ctx.ModuleSubDir(m)) 624*333d2b36SAndroid Build Coastguard Worker } 625*333d2b36SAndroid Build Coastguard Worker }) 626*333d2b36SAndroid Build Coastguard Worker return variants 627*333d2b36SAndroid Build Coastguard Worker} 628*333d2b36SAndroid Build Coastguard Worker 629*333d2b36SAndroid Build Coastguard Worker// SingletonForTests returns a TestingSingleton for the singleton registered with the given name. 630*333d2b36SAndroid Build Coastguard Workerfunc (ctx *TestContext) SingletonForTests(name string) TestingSingleton { 631*333d2b36SAndroid Build Coastguard Worker allSingletonNames := []string{} 632*333d2b36SAndroid Build Coastguard Worker for _, s := range ctx.Singletons() { 633*333d2b36SAndroid Build Coastguard Worker n := ctx.SingletonName(s) 634*333d2b36SAndroid Build Coastguard Worker if n == name { 635*333d2b36SAndroid Build Coastguard Worker return TestingSingleton{ 636*333d2b36SAndroid Build Coastguard Worker baseTestingComponent: newBaseTestingComponent(ctx.config, s.(testBuildProvider)), 637*333d2b36SAndroid Build Coastguard Worker singleton: s.(*singletonAdaptor).Singleton, 638*333d2b36SAndroid Build Coastguard Worker } 639*333d2b36SAndroid Build Coastguard Worker } 640*333d2b36SAndroid Build Coastguard Worker allSingletonNames = append(allSingletonNames, n) 641*333d2b36SAndroid Build Coastguard Worker } 642*333d2b36SAndroid Build Coastguard Worker 643*333d2b36SAndroid Build Coastguard Worker panic(fmt.Errorf("failed to find singleton %q."+ 644*333d2b36SAndroid Build Coastguard Worker "\nall singletons: %v", name, allSingletonNames)) 645*333d2b36SAndroid Build Coastguard Worker} 646*333d2b36SAndroid Build Coastguard Worker 647*333d2b36SAndroid Build Coastguard Workertype InstallMakeRule struct { 648*333d2b36SAndroid Build Coastguard Worker Target string 649*333d2b36SAndroid Build Coastguard Worker Deps []string 650*333d2b36SAndroid Build Coastguard Worker OrderOnlyDeps []string 651*333d2b36SAndroid Build Coastguard Worker} 652*333d2b36SAndroid Build Coastguard Worker 653*333d2b36SAndroid Build Coastguard Workerfunc parseMkRules(t *testing.T, config Config, nodes []mkparser.Node) []InstallMakeRule { 654*333d2b36SAndroid Build Coastguard Worker var rules []InstallMakeRule 655*333d2b36SAndroid Build Coastguard Worker for _, node := range nodes { 656*333d2b36SAndroid Build Coastguard Worker if mkParserRule, ok := node.(*mkparser.Rule); ok { 657*333d2b36SAndroid Build Coastguard Worker var rule InstallMakeRule 658*333d2b36SAndroid Build Coastguard Worker 659*333d2b36SAndroid Build Coastguard Worker if targets := mkParserRule.Target.Words(); len(targets) == 0 { 660*333d2b36SAndroid Build Coastguard Worker t.Fatalf("no targets for rule %s", mkParserRule.Dump()) 661*333d2b36SAndroid Build Coastguard Worker } else if len(targets) > 1 { 662*333d2b36SAndroid Build Coastguard Worker t.Fatalf("unsupported multiple targets for rule %s", mkParserRule.Dump()) 663*333d2b36SAndroid Build Coastguard Worker } else if !targets[0].Const() { 664*333d2b36SAndroid Build Coastguard Worker t.Fatalf("unsupported non-const target for rule %s", mkParserRule.Dump()) 665*333d2b36SAndroid Build Coastguard Worker } else { 666*333d2b36SAndroid Build Coastguard Worker rule.Target = normalizeStringRelativeToTop(config, targets[0].Value(nil)) 667*333d2b36SAndroid Build Coastguard Worker } 668*333d2b36SAndroid Build Coastguard Worker 669*333d2b36SAndroid Build Coastguard Worker prereqList := &rule.Deps 670*333d2b36SAndroid Build Coastguard Worker for _, prereq := range mkParserRule.Prerequisites.Words() { 671*333d2b36SAndroid Build Coastguard Worker if !prereq.Const() { 672*333d2b36SAndroid Build Coastguard Worker t.Fatalf("unsupported non-const prerequisite for rule %s", mkParserRule.Dump()) 673*333d2b36SAndroid Build Coastguard Worker } 674*333d2b36SAndroid Build Coastguard Worker 675*333d2b36SAndroid Build Coastguard Worker if prereq.Value(nil) == "|" { 676*333d2b36SAndroid Build Coastguard Worker prereqList = &rule.OrderOnlyDeps 677*333d2b36SAndroid Build Coastguard Worker continue 678*333d2b36SAndroid Build Coastguard Worker } 679*333d2b36SAndroid Build Coastguard Worker 680*333d2b36SAndroid Build Coastguard Worker *prereqList = append(*prereqList, normalizeStringRelativeToTop(config, prereq.Value(nil))) 681*333d2b36SAndroid Build Coastguard Worker } 682*333d2b36SAndroid Build Coastguard Worker 683*333d2b36SAndroid Build Coastguard Worker rules = append(rules, rule) 684*333d2b36SAndroid Build Coastguard Worker } 685*333d2b36SAndroid Build Coastguard Worker } 686*333d2b36SAndroid Build Coastguard Worker 687*333d2b36SAndroid Build Coastguard Worker return rules 688*333d2b36SAndroid Build Coastguard Worker} 689*333d2b36SAndroid Build Coastguard Worker 690*333d2b36SAndroid Build Coastguard Workerfunc (ctx *TestContext) InstallMakeRulesForTesting(t *testing.T) []InstallMakeRule { 691*333d2b36SAndroid Build Coastguard Worker installs := ctx.SingletonForTests("makevars").Singleton().(*makeVarsSingleton).installsForTesting 692*333d2b36SAndroid Build Coastguard Worker buf := bytes.NewBuffer(append([]byte(nil), installs...)) 693*333d2b36SAndroid Build Coastguard Worker parser := mkparser.NewParser("makevars", buf) 694*333d2b36SAndroid Build Coastguard Worker 695*333d2b36SAndroid Build Coastguard Worker nodes, errs := parser.Parse() 696*333d2b36SAndroid Build Coastguard Worker if len(errs) > 0 { 697*333d2b36SAndroid Build Coastguard Worker t.Fatalf("error parsing install rules: %s", errs[0]) 698*333d2b36SAndroid Build Coastguard Worker } 699*333d2b36SAndroid Build Coastguard Worker 700*333d2b36SAndroid Build Coastguard Worker return parseMkRules(t, ctx.config, nodes) 701*333d2b36SAndroid Build Coastguard Worker} 702*333d2b36SAndroid Build Coastguard Worker 703*333d2b36SAndroid Build Coastguard Worker// MakeVarVariable provides access to make vars that will be written by the makeVarsSingleton 704*333d2b36SAndroid Build Coastguard Workertype MakeVarVariable interface { 705*333d2b36SAndroid Build Coastguard Worker // Name is the name of the variable. 706*333d2b36SAndroid Build Coastguard Worker Name() string 707*333d2b36SAndroid Build Coastguard Worker 708*333d2b36SAndroid Build Coastguard Worker // Value is the value of the variable. 709*333d2b36SAndroid Build Coastguard Worker Value() string 710*333d2b36SAndroid Build Coastguard Worker} 711*333d2b36SAndroid Build Coastguard Worker 712*333d2b36SAndroid Build Coastguard Workerfunc (v makeVarsVariable) Name() string { 713*333d2b36SAndroid Build Coastguard Worker return v.name 714*333d2b36SAndroid Build Coastguard Worker} 715*333d2b36SAndroid Build Coastguard Worker 716*333d2b36SAndroid Build Coastguard Workerfunc (v makeVarsVariable) Value() string { 717*333d2b36SAndroid Build Coastguard Worker return v.value 718*333d2b36SAndroid Build Coastguard Worker} 719*333d2b36SAndroid Build Coastguard Worker 720*333d2b36SAndroid Build Coastguard Worker// PrepareForTestAccessingMakeVars sets up the test so that MakeVarsForTesting will work. 721*333d2b36SAndroid Build Coastguard Workervar PrepareForTestAccessingMakeVars = GroupFixturePreparers( 722*333d2b36SAndroid Build Coastguard Worker PrepareForTestWithAndroidMk, 723*333d2b36SAndroid Build Coastguard Worker PrepareForTestWithMakevars, 724*333d2b36SAndroid Build Coastguard Worker) 725*333d2b36SAndroid Build Coastguard Worker 726*333d2b36SAndroid Build Coastguard Worker// MakeVarsForTesting returns a filtered list of MakeVarVariable objects that represent the 727*333d2b36SAndroid Build Coastguard Worker// variables that will be written out. 728*333d2b36SAndroid Build Coastguard Worker// 729*333d2b36SAndroid Build Coastguard Worker// It is necessary to use PrepareForTestAccessingMakeVars in tests that want to call this function. 730*333d2b36SAndroid Build Coastguard Worker// Along with any other preparers needed to add the make vars. 731*333d2b36SAndroid Build Coastguard Workerfunc (ctx *TestContext) MakeVarsForTesting(filter func(variable MakeVarVariable) bool) []MakeVarVariable { 732*333d2b36SAndroid Build Coastguard Worker vars := ctx.SingletonForTests("makevars").Singleton().(*makeVarsSingleton).varsForTesting 733*333d2b36SAndroid Build Coastguard Worker result := make([]MakeVarVariable, 0, len(vars)) 734*333d2b36SAndroid Build Coastguard Worker for _, v := range vars { 735*333d2b36SAndroid Build Coastguard Worker if filter(v) { 736*333d2b36SAndroid Build Coastguard Worker result = append(result, v) 737*333d2b36SAndroid Build Coastguard Worker } 738*333d2b36SAndroid Build Coastguard Worker } 739*333d2b36SAndroid Build Coastguard Worker 740*333d2b36SAndroid Build Coastguard Worker return result 741*333d2b36SAndroid Build Coastguard Worker} 742*333d2b36SAndroid Build Coastguard Worker 743*333d2b36SAndroid Build Coastguard Workerfunc (ctx *TestContext) Config() Config { 744*333d2b36SAndroid Build Coastguard Worker return ctx.config 745*333d2b36SAndroid Build Coastguard Worker} 746*333d2b36SAndroid Build Coastguard Worker 747*333d2b36SAndroid Build Coastguard Workertype testBuildProvider interface { 748*333d2b36SAndroid Build Coastguard Worker BuildParamsForTests() []BuildParams 749*333d2b36SAndroid Build Coastguard Worker RuleParamsForTests() map[blueprint.Rule]blueprint.RuleParams 750*333d2b36SAndroid Build Coastguard Worker} 751*333d2b36SAndroid Build Coastguard Worker 752*333d2b36SAndroid Build Coastguard Workertype TestingBuildParams struct { 753*333d2b36SAndroid Build Coastguard Worker BuildParams 754*333d2b36SAndroid Build Coastguard Worker RuleParams blueprint.RuleParams 755*333d2b36SAndroid Build Coastguard Worker 756*333d2b36SAndroid Build Coastguard Worker config Config 757*333d2b36SAndroid Build Coastguard Worker} 758*333d2b36SAndroid Build Coastguard Worker 759*333d2b36SAndroid Build Coastguard Worker// RelativeToTop creates a new instance of this which has had any usages of the current test's 760*333d2b36SAndroid Build Coastguard Worker// temporary and test specific build directory replaced with a path relative to the notional top. 761*333d2b36SAndroid Build Coastguard Worker// 762*333d2b36SAndroid Build Coastguard Worker// The parts of this structure which are changed are: 763*333d2b36SAndroid Build Coastguard Worker// * BuildParams 764*333d2b36SAndroid Build Coastguard Worker// - Args 765*333d2b36SAndroid Build Coastguard Worker// - All Path, Paths, WritablePath and WritablePaths fields. 766*333d2b36SAndroid Build Coastguard Worker// 767*333d2b36SAndroid Build Coastguard Worker// * RuleParams 768*333d2b36SAndroid Build Coastguard Worker// - Command 769*333d2b36SAndroid Build Coastguard Worker// - Depfile 770*333d2b36SAndroid Build Coastguard Worker// - Rspfile 771*333d2b36SAndroid Build Coastguard Worker// - RspfileContent 772*333d2b36SAndroid Build Coastguard Worker// - CommandDeps 773*333d2b36SAndroid Build Coastguard Worker// - CommandOrderOnly 774*333d2b36SAndroid Build Coastguard Worker// 775*333d2b36SAndroid Build Coastguard Worker// See PathRelativeToTop for more details. 776*333d2b36SAndroid Build Coastguard Worker// 777*333d2b36SAndroid Build Coastguard Worker// deprecated: this is no longer needed as TestingBuildParams are created in this form. 778*333d2b36SAndroid Build Coastguard Workerfunc (p TestingBuildParams) RelativeToTop() TestingBuildParams { 779*333d2b36SAndroid Build Coastguard Worker // If this is not a valid params then just return it back. That will make it easy to use with the 780*333d2b36SAndroid Build Coastguard Worker // Maybe...() methods. 781*333d2b36SAndroid Build Coastguard Worker if p.Rule == nil { 782*333d2b36SAndroid Build Coastguard Worker return p 783*333d2b36SAndroid Build Coastguard Worker } 784*333d2b36SAndroid Build Coastguard Worker if p.config.config == nil { 785*333d2b36SAndroid Build Coastguard Worker return p 786*333d2b36SAndroid Build Coastguard Worker } 787*333d2b36SAndroid Build Coastguard Worker // Take a copy of the build params and replace any args that contains test specific temporary 788*333d2b36SAndroid Build Coastguard Worker // paths with paths relative to the top. 789*333d2b36SAndroid Build Coastguard Worker bparams := p.BuildParams 790*333d2b36SAndroid Build Coastguard Worker bparams.Depfile = normalizeWritablePathRelativeToTop(bparams.Depfile) 791*333d2b36SAndroid Build Coastguard Worker bparams.Output = normalizeWritablePathRelativeToTop(bparams.Output) 792*333d2b36SAndroid Build Coastguard Worker bparams.Outputs = bparams.Outputs.RelativeToTop() 793*333d2b36SAndroid Build Coastguard Worker bparams.ImplicitOutput = normalizeWritablePathRelativeToTop(bparams.ImplicitOutput) 794*333d2b36SAndroid Build Coastguard Worker bparams.ImplicitOutputs = bparams.ImplicitOutputs.RelativeToTop() 795*333d2b36SAndroid Build Coastguard Worker bparams.Input = normalizePathRelativeToTop(bparams.Input) 796*333d2b36SAndroid Build Coastguard Worker bparams.Inputs = bparams.Inputs.RelativeToTop() 797*333d2b36SAndroid Build Coastguard Worker bparams.Implicit = normalizePathRelativeToTop(bparams.Implicit) 798*333d2b36SAndroid Build Coastguard Worker bparams.Implicits = bparams.Implicits.RelativeToTop() 799*333d2b36SAndroid Build Coastguard Worker bparams.OrderOnly = bparams.OrderOnly.RelativeToTop() 800*333d2b36SAndroid Build Coastguard Worker bparams.Validation = normalizePathRelativeToTop(bparams.Validation) 801*333d2b36SAndroid Build Coastguard Worker bparams.Validations = bparams.Validations.RelativeToTop() 802*333d2b36SAndroid Build Coastguard Worker bparams.Args = normalizeStringMapRelativeToTop(p.config, bparams.Args) 803*333d2b36SAndroid Build Coastguard Worker 804*333d2b36SAndroid Build Coastguard Worker // Ditto for any fields in the RuleParams. 805*333d2b36SAndroid Build Coastguard Worker rparams := p.RuleParams 806*333d2b36SAndroid Build Coastguard Worker rparams.Command = normalizeStringRelativeToTop(p.config, rparams.Command) 807*333d2b36SAndroid Build Coastguard Worker rparams.Depfile = normalizeStringRelativeToTop(p.config, rparams.Depfile) 808*333d2b36SAndroid Build Coastguard Worker rparams.Rspfile = normalizeStringRelativeToTop(p.config, rparams.Rspfile) 809*333d2b36SAndroid Build Coastguard Worker rparams.RspfileContent = normalizeStringRelativeToTop(p.config, rparams.RspfileContent) 810*333d2b36SAndroid Build Coastguard Worker rparams.CommandDeps = normalizeStringArrayRelativeToTop(p.config, rparams.CommandDeps) 811*333d2b36SAndroid Build Coastguard Worker rparams.CommandOrderOnly = normalizeStringArrayRelativeToTop(p.config, rparams.CommandOrderOnly) 812*333d2b36SAndroid Build Coastguard Worker 813*333d2b36SAndroid Build Coastguard Worker return TestingBuildParams{ 814*333d2b36SAndroid Build Coastguard Worker BuildParams: bparams, 815*333d2b36SAndroid Build Coastguard Worker RuleParams: rparams, 816*333d2b36SAndroid Build Coastguard Worker } 817*333d2b36SAndroid Build Coastguard Worker} 818*333d2b36SAndroid Build Coastguard Worker 819*333d2b36SAndroid Build Coastguard Workerfunc normalizeWritablePathRelativeToTop(path WritablePath) WritablePath { 820*333d2b36SAndroid Build Coastguard Worker if path == nil { 821*333d2b36SAndroid Build Coastguard Worker return nil 822*333d2b36SAndroid Build Coastguard Worker } 823*333d2b36SAndroid Build Coastguard Worker return path.RelativeToTop().(WritablePath) 824*333d2b36SAndroid Build Coastguard Worker} 825*333d2b36SAndroid Build Coastguard Worker 826*333d2b36SAndroid Build Coastguard Workerfunc normalizePathRelativeToTop(path Path) Path { 827*333d2b36SAndroid Build Coastguard Worker if path == nil { 828*333d2b36SAndroid Build Coastguard Worker return nil 829*333d2b36SAndroid Build Coastguard Worker } 830*333d2b36SAndroid Build Coastguard Worker return path.RelativeToTop() 831*333d2b36SAndroid Build Coastguard Worker} 832*333d2b36SAndroid Build Coastguard Worker 833*333d2b36SAndroid Build Coastguard Workerfunc allOutputs(p BuildParams) []string { 834*333d2b36SAndroid Build Coastguard Worker outputs := append(WritablePaths(nil), p.Outputs...) 835*333d2b36SAndroid Build Coastguard Worker outputs = append(outputs, p.ImplicitOutputs...) 836*333d2b36SAndroid Build Coastguard Worker if p.Output != nil { 837*333d2b36SAndroid Build Coastguard Worker outputs = append(outputs, p.Output) 838*333d2b36SAndroid Build Coastguard Worker } 839*333d2b36SAndroid Build Coastguard Worker return outputs.Strings() 840*333d2b36SAndroid Build Coastguard Worker} 841*333d2b36SAndroid Build Coastguard Worker 842*333d2b36SAndroid Build Coastguard Worker// AllOutputs returns all 'BuildParams.Output's and 'BuildParams.Outputs's in their full path string forms. 843*333d2b36SAndroid Build Coastguard Workerfunc (p TestingBuildParams) AllOutputs() []string { 844*333d2b36SAndroid Build Coastguard Worker return allOutputs(p.BuildParams) 845*333d2b36SAndroid Build Coastguard Worker} 846*333d2b36SAndroid Build Coastguard Worker 847*333d2b36SAndroid Build Coastguard Worker// baseTestingComponent provides functionality common to both TestingModule and TestingSingleton. 848*333d2b36SAndroid Build Coastguard Workertype baseTestingComponent struct { 849*333d2b36SAndroid Build Coastguard Worker config Config 850*333d2b36SAndroid Build Coastguard Worker provider testBuildProvider 851*333d2b36SAndroid Build Coastguard Worker} 852*333d2b36SAndroid Build Coastguard Worker 853*333d2b36SAndroid Build Coastguard Workerfunc newBaseTestingComponent(config Config, provider testBuildProvider) baseTestingComponent { 854*333d2b36SAndroid Build Coastguard Worker return baseTestingComponent{config, provider} 855*333d2b36SAndroid Build Coastguard Worker} 856*333d2b36SAndroid Build Coastguard Worker 857*333d2b36SAndroid Build Coastguard Worker// A function that will normalize a string containing paths, e.g. ninja command, by replacing 858*333d2b36SAndroid Build Coastguard Worker// any references to the test specific temporary build directory that changes with each run to a 859*333d2b36SAndroid Build Coastguard Worker// fixed path relative to a notional top directory. 860*333d2b36SAndroid Build Coastguard Worker// 861*333d2b36SAndroid Build Coastguard Worker// This is similar to StringPathRelativeToTop except that assumes the string is a single path 862*333d2b36SAndroid Build Coastguard Worker// containing at most one instance of the temporary build directory at the start of the path while 863*333d2b36SAndroid Build Coastguard Worker// this assumes that there can be any number at any position. 864*333d2b36SAndroid Build Coastguard Workerfunc normalizeStringRelativeToTop(config Config, s string) string { 865*333d2b36SAndroid Build Coastguard Worker // The outDir usually looks something like: /tmp/testFoo2345/001 866*333d2b36SAndroid Build Coastguard Worker // 867*333d2b36SAndroid Build Coastguard Worker // Replace any usage of the outDir with out/soong, e.g. replace "/tmp/testFoo2345/001" with 868*333d2b36SAndroid Build Coastguard Worker // "out/soong". 869*333d2b36SAndroid Build Coastguard Worker outSoongDir := filepath.Clean(config.soongOutDir) 870*333d2b36SAndroid Build Coastguard Worker re := regexp.MustCompile(`\Q` + outSoongDir + `\E\b`) 871*333d2b36SAndroid Build Coastguard Worker s = re.ReplaceAllString(s, "out/soong") 872*333d2b36SAndroid Build Coastguard Worker 873*333d2b36SAndroid Build Coastguard Worker // Replace any usage of the outDir/.. with out, e.g. replace "/tmp/testFoo2345" with 874*333d2b36SAndroid Build Coastguard Worker // "out". This must come after the previous replacement otherwise this would replace 875*333d2b36SAndroid Build Coastguard Worker // "/tmp/testFoo2345/001" with "out/001" instead of "out/soong". 876*333d2b36SAndroid Build Coastguard Worker outDir := filepath.Dir(outSoongDir) 877*333d2b36SAndroid Build Coastguard Worker re = regexp.MustCompile(`\Q` + outDir + `\E\b`) 878*333d2b36SAndroid Build Coastguard Worker s = re.ReplaceAllString(s, "out") 879*333d2b36SAndroid Build Coastguard Worker 880*333d2b36SAndroid Build Coastguard Worker return s 881*333d2b36SAndroid Build Coastguard Worker} 882*333d2b36SAndroid Build Coastguard Worker 883*333d2b36SAndroid Build Coastguard Worker// normalizeStringArrayRelativeToTop creates a new slice constructed by applying 884*333d2b36SAndroid Build Coastguard Worker// normalizeStringRelativeToTop to each item in the slice. 885*333d2b36SAndroid Build Coastguard Workerfunc normalizeStringArrayRelativeToTop(config Config, slice []string) []string { 886*333d2b36SAndroid Build Coastguard Worker newSlice := make([]string, len(slice)) 887*333d2b36SAndroid Build Coastguard Worker for i, s := range slice { 888*333d2b36SAndroid Build Coastguard Worker newSlice[i] = normalizeStringRelativeToTop(config, s) 889*333d2b36SAndroid Build Coastguard Worker } 890*333d2b36SAndroid Build Coastguard Worker return newSlice 891*333d2b36SAndroid Build Coastguard Worker} 892*333d2b36SAndroid Build Coastguard Worker 893*333d2b36SAndroid Build Coastguard Worker// normalizeStringMapRelativeToTop creates a new map constructed by applying 894*333d2b36SAndroid Build Coastguard Worker// normalizeStringRelativeToTop to each value in the map. 895*333d2b36SAndroid Build Coastguard Workerfunc normalizeStringMapRelativeToTop(config Config, m map[string]string) map[string]string { 896*333d2b36SAndroid Build Coastguard Worker newMap := map[string]string{} 897*333d2b36SAndroid Build Coastguard Worker for k, v := range m { 898*333d2b36SAndroid Build Coastguard Worker newMap[k] = normalizeStringRelativeToTop(config, v) 899*333d2b36SAndroid Build Coastguard Worker } 900*333d2b36SAndroid Build Coastguard Worker return newMap 901*333d2b36SAndroid Build Coastguard Worker} 902*333d2b36SAndroid Build Coastguard Worker 903*333d2b36SAndroid Build Coastguard Workerfunc (b baseTestingComponent) newTestingBuildParams(bparams BuildParams) TestingBuildParams { 904*333d2b36SAndroid Build Coastguard Worker return TestingBuildParams{ 905*333d2b36SAndroid Build Coastguard Worker config: b.config, 906*333d2b36SAndroid Build Coastguard Worker BuildParams: bparams, 907*333d2b36SAndroid Build Coastguard Worker RuleParams: b.provider.RuleParamsForTests()[bparams.Rule], 908*333d2b36SAndroid Build Coastguard Worker }.RelativeToTop() 909*333d2b36SAndroid Build Coastguard Worker} 910*333d2b36SAndroid Build Coastguard Worker 911*333d2b36SAndroid Build Coastguard Workerfunc (b baseTestingComponent) maybeBuildParamsFromRule(rule string) (TestingBuildParams, []string) { 912*333d2b36SAndroid Build Coastguard Worker var searchedRules []string 913*333d2b36SAndroid Build Coastguard Worker buildParams := b.provider.BuildParamsForTests() 914*333d2b36SAndroid Build Coastguard Worker for _, p := range buildParams { 915*333d2b36SAndroid Build Coastguard Worker ruleAsString := p.Rule.String() 916*333d2b36SAndroid Build Coastguard Worker searchedRules = append(searchedRules, ruleAsString) 917*333d2b36SAndroid Build Coastguard Worker if strings.Contains(ruleAsString, rule) { 918*333d2b36SAndroid Build Coastguard Worker return b.newTestingBuildParams(p), searchedRules 919*333d2b36SAndroid Build Coastguard Worker } 920*333d2b36SAndroid Build Coastguard Worker } 921*333d2b36SAndroid Build Coastguard Worker return TestingBuildParams{}, searchedRules 922*333d2b36SAndroid Build Coastguard Worker} 923*333d2b36SAndroid Build Coastguard Worker 924*333d2b36SAndroid Build Coastguard Workerfunc (b baseTestingComponent) buildParamsFromRule(rule string) TestingBuildParams { 925*333d2b36SAndroid Build Coastguard Worker p, searchRules := b.maybeBuildParamsFromRule(rule) 926*333d2b36SAndroid Build Coastguard Worker if p.Rule == nil { 927*333d2b36SAndroid Build Coastguard Worker panic(fmt.Errorf("couldn't find rule %q.\nall rules:\n%s", rule, strings.Join(searchRules, "\n"))) 928*333d2b36SAndroid Build Coastguard Worker } 929*333d2b36SAndroid Build Coastguard Worker return p 930*333d2b36SAndroid Build Coastguard Worker} 931*333d2b36SAndroid Build Coastguard Worker 932*333d2b36SAndroid Build Coastguard Workerfunc (b baseTestingComponent) maybeBuildParamsFromDescription(desc string) (TestingBuildParams, []string) { 933*333d2b36SAndroid Build Coastguard Worker var searchedDescriptions []string 934*333d2b36SAndroid Build Coastguard Worker for _, p := range b.provider.BuildParamsForTests() { 935*333d2b36SAndroid Build Coastguard Worker searchedDescriptions = append(searchedDescriptions, p.Description) 936*333d2b36SAndroid Build Coastguard Worker if strings.Contains(p.Description, desc) { 937*333d2b36SAndroid Build Coastguard Worker return b.newTestingBuildParams(p), searchedDescriptions 938*333d2b36SAndroid Build Coastguard Worker } 939*333d2b36SAndroid Build Coastguard Worker } 940*333d2b36SAndroid Build Coastguard Worker return TestingBuildParams{}, searchedDescriptions 941*333d2b36SAndroid Build Coastguard Worker} 942*333d2b36SAndroid Build Coastguard Worker 943*333d2b36SAndroid Build Coastguard Workerfunc (b baseTestingComponent) buildParamsFromDescription(desc string) TestingBuildParams { 944*333d2b36SAndroid Build Coastguard Worker p, searchedDescriptions := b.maybeBuildParamsFromDescription(desc) 945*333d2b36SAndroid Build Coastguard Worker if p.Rule == nil { 946*333d2b36SAndroid Build Coastguard Worker panic(fmt.Errorf("couldn't find description %q\nall descriptions:\n%s", desc, strings.Join(searchedDescriptions, "\n"))) 947*333d2b36SAndroid Build Coastguard Worker } 948*333d2b36SAndroid Build Coastguard Worker return p 949*333d2b36SAndroid Build Coastguard Worker} 950*333d2b36SAndroid Build Coastguard Worker 951*333d2b36SAndroid Build Coastguard Workerfunc (b baseTestingComponent) maybeBuildParamsFromOutput(file string) (TestingBuildParams, []string) { 952*333d2b36SAndroid Build Coastguard Worker searchedOutputs := WritablePaths(nil) 953*333d2b36SAndroid Build Coastguard Worker for _, p := range b.provider.BuildParamsForTests() { 954*333d2b36SAndroid Build Coastguard Worker outputs := append(WritablePaths(nil), p.Outputs...) 955*333d2b36SAndroid Build Coastguard Worker outputs = append(outputs, p.ImplicitOutputs...) 956*333d2b36SAndroid Build Coastguard Worker if p.Output != nil { 957*333d2b36SAndroid Build Coastguard Worker outputs = append(outputs, p.Output) 958*333d2b36SAndroid Build Coastguard Worker } 959*333d2b36SAndroid Build Coastguard Worker for _, f := range outputs { 960*333d2b36SAndroid Build Coastguard Worker if f.String() == file || f.Rel() == file || PathRelativeToTop(f) == file { 961*333d2b36SAndroid Build Coastguard Worker return b.newTestingBuildParams(p), nil 962*333d2b36SAndroid Build Coastguard Worker } 963*333d2b36SAndroid Build Coastguard Worker searchedOutputs = append(searchedOutputs, f) 964*333d2b36SAndroid Build Coastguard Worker } 965*333d2b36SAndroid Build Coastguard Worker } 966*333d2b36SAndroid Build Coastguard Worker 967*333d2b36SAndroid Build Coastguard Worker formattedOutputs := []string{} 968*333d2b36SAndroid Build Coastguard Worker for _, f := range searchedOutputs { 969*333d2b36SAndroid Build Coastguard Worker formattedOutputs = append(formattedOutputs, 970*333d2b36SAndroid Build Coastguard Worker fmt.Sprintf("%s (rel=%s)", PathRelativeToTop(f), f.Rel())) 971*333d2b36SAndroid Build Coastguard Worker } 972*333d2b36SAndroid Build Coastguard Worker 973*333d2b36SAndroid Build Coastguard Worker return TestingBuildParams{}, formattedOutputs 974*333d2b36SAndroid Build Coastguard Worker} 975*333d2b36SAndroid Build Coastguard Worker 976*333d2b36SAndroid Build Coastguard Workerfunc (b baseTestingComponent) buildParamsFromOutput(file string) TestingBuildParams { 977*333d2b36SAndroid Build Coastguard Worker p, searchedOutputs := b.maybeBuildParamsFromOutput(file) 978*333d2b36SAndroid Build Coastguard Worker if p.Rule == nil { 979*333d2b36SAndroid Build Coastguard Worker panic(fmt.Errorf("couldn't find output %q.\nall outputs:\n %s\n", 980*333d2b36SAndroid Build Coastguard Worker file, strings.Join(searchedOutputs, "\n "))) 981*333d2b36SAndroid Build Coastguard Worker } 982*333d2b36SAndroid Build Coastguard Worker return p 983*333d2b36SAndroid Build Coastguard Worker} 984*333d2b36SAndroid Build Coastguard Worker 985*333d2b36SAndroid Build Coastguard Workerfunc (b baseTestingComponent) allOutputs() []string { 986*333d2b36SAndroid Build Coastguard Worker var outputFullPaths []string 987*333d2b36SAndroid Build Coastguard Worker for _, p := range b.provider.BuildParamsForTests() { 988*333d2b36SAndroid Build Coastguard Worker outputFullPaths = append(outputFullPaths, allOutputs(p)...) 989*333d2b36SAndroid Build Coastguard Worker } 990*333d2b36SAndroid Build Coastguard Worker return outputFullPaths 991*333d2b36SAndroid Build Coastguard Worker} 992*333d2b36SAndroid Build Coastguard Worker 993*333d2b36SAndroid Build Coastguard Worker// MaybeRule finds a call to ctx.Build with BuildParams.Rule set to a rule with the given name. Returns an empty 994*333d2b36SAndroid Build Coastguard Worker// BuildParams if no rule is found. 995*333d2b36SAndroid Build Coastguard Workerfunc (b baseTestingComponent) MaybeRule(rule string) TestingBuildParams { 996*333d2b36SAndroid Build Coastguard Worker r, _ := b.maybeBuildParamsFromRule(rule) 997*333d2b36SAndroid Build Coastguard Worker return r 998*333d2b36SAndroid Build Coastguard Worker} 999*333d2b36SAndroid Build Coastguard Worker 1000*333d2b36SAndroid Build Coastguard Worker// Rule finds a call to ctx.Build with BuildParams.Rule set to a rule with the given name. Panics if no rule is found. 1001*333d2b36SAndroid Build Coastguard Workerfunc (b baseTestingComponent) Rule(rule string) TestingBuildParams { 1002*333d2b36SAndroid Build Coastguard Worker return b.buildParamsFromRule(rule) 1003*333d2b36SAndroid Build Coastguard Worker} 1004*333d2b36SAndroid Build Coastguard Worker 1005*333d2b36SAndroid Build Coastguard Worker// MaybeDescription finds a call to ctx.Build with BuildParams.Description set to a the given string. Returns an empty 1006*333d2b36SAndroid Build Coastguard Worker// BuildParams if no rule is found. 1007*333d2b36SAndroid Build Coastguard Workerfunc (b baseTestingComponent) MaybeDescription(desc string) TestingBuildParams { 1008*333d2b36SAndroid Build Coastguard Worker p, _ := b.maybeBuildParamsFromDescription(desc) 1009*333d2b36SAndroid Build Coastguard Worker return p 1010*333d2b36SAndroid Build Coastguard Worker} 1011*333d2b36SAndroid Build Coastguard Worker 1012*333d2b36SAndroid Build Coastguard Worker// Description finds a call to ctx.Build with BuildParams.Description set to a the given string. Panics if no rule is 1013*333d2b36SAndroid Build Coastguard Worker// found. 1014*333d2b36SAndroid Build Coastguard Workerfunc (b baseTestingComponent) Description(desc string) TestingBuildParams { 1015*333d2b36SAndroid Build Coastguard Worker return b.buildParamsFromDescription(desc) 1016*333d2b36SAndroid Build Coastguard Worker} 1017*333d2b36SAndroid Build Coastguard Worker 1018*333d2b36SAndroid Build Coastguard Worker// MaybeOutput finds a call to ctx.Build with a BuildParams.Output or BuildParams.Outputs whose String() or Rel() 1019*333d2b36SAndroid Build Coastguard Worker// value matches the provided string. Returns an empty BuildParams if no rule is found. 1020*333d2b36SAndroid Build Coastguard Workerfunc (b baseTestingComponent) MaybeOutput(file string) TestingBuildParams { 1021*333d2b36SAndroid Build Coastguard Worker p, _ := b.maybeBuildParamsFromOutput(file) 1022*333d2b36SAndroid Build Coastguard Worker return p 1023*333d2b36SAndroid Build Coastguard Worker} 1024*333d2b36SAndroid Build Coastguard Worker 1025*333d2b36SAndroid Build Coastguard Worker// Output finds a call to ctx.Build with a BuildParams.Output or BuildParams.Outputs whose String() or Rel() 1026*333d2b36SAndroid Build Coastguard Worker// value matches the provided string. Panics if no rule is found. 1027*333d2b36SAndroid Build Coastguard Workerfunc (b baseTestingComponent) Output(file string) TestingBuildParams { 1028*333d2b36SAndroid Build Coastguard Worker return b.buildParamsFromOutput(file) 1029*333d2b36SAndroid Build Coastguard Worker} 1030*333d2b36SAndroid Build Coastguard Worker 1031*333d2b36SAndroid Build Coastguard Worker// AllOutputs returns all 'BuildParams.Output's and 'BuildParams.Outputs's in their full path string forms. 1032*333d2b36SAndroid Build Coastguard Workerfunc (b baseTestingComponent) AllOutputs() []string { 1033*333d2b36SAndroid Build Coastguard Worker return b.allOutputs() 1034*333d2b36SAndroid Build Coastguard Worker} 1035*333d2b36SAndroid Build Coastguard Worker 1036*333d2b36SAndroid Build Coastguard Worker// TestingModule is wrapper around an android.Module that provides methods to find information about individual 1037*333d2b36SAndroid Build Coastguard Worker// ctx.Build parameters for verification in tests. 1038*333d2b36SAndroid Build Coastguard Workertype TestingModule struct { 1039*333d2b36SAndroid Build Coastguard Worker baseTestingComponent 1040*333d2b36SAndroid Build Coastguard Worker module Module 1041*333d2b36SAndroid Build Coastguard Worker} 1042*333d2b36SAndroid Build Coastguard Worker 1043*333d2b36SAndroid Build Coastguard Workerfunc newTestingModule(config Config, module Module) TestingModule { 1044*333d2b36SAndroid Build Coastguard Worker return TestingModule{ 1045*333d2b36SAndroid Build Coastguard Worker newBaseTestingComponent(config, module), 1046*333d2b36SAndroid Build Coastguard Worker module, 1047*333d2b36SAndroid Build Coastguard Worker } 1048*333d2b36SAndroid Build Coastguard Worker} 1049*333d2b36SAndroid Build Coastguard Worker 1050*333d2b36SAndroid Build Coastguard Worker// Module returns the Module wrapped by the TestingModule. 1051*333d2b36SAndroid Build Coastguard Workerfunc (m TestingModule) Module() Module { 1052*333d2b36SAndroid Build Coastguard Worker return m.module 1053*333d2b36SAndroid Build Coastguard Worker} 1054*333d2b36SAndroid Build Coastguard Worker 1055*333d2b36SAndroid Build Coastguard Worker// VariablesForTestsRelativeToTop returns a copy of the Module.VariablesForTests() with every value 1056*333d2b36SAndroid Build Coastguard Worker// having any temporary build dir usages replaced with paths relative to a notional top. 1057*333d2b36SAndroid Build Coastguard Workerfunc (m TestingModule) VariablesForTestsRelativeToTop() map[string]string { 1058*333d2b36SAndroid Build Coastguard Worker return normalizeStringMapRelativeToTop(m.config, m.module.VariablesForTests()) 1059*333d2b36SAndroid Build Coastguard Worker} 1060*333d2b36SAndroid Build Coastguard Worker 1061*333d2b36SAndroid Build Coastguard Worker// OutputFiles checks if module base outputFiles property has any output 1062*333d2b36SAndroid Build Coastguard Worker// files can be used to return. 1063*333d2b36SAndroid Build Coastguard Worker// Exits the test immediately if there is an error and 1064*333d2b36SAndroid Build Coastguard Worker// otherwise returns the result of calling Paths.RelativeToTop 1065*333d2b36SAndroid Build Coastguard Worker// on the returned Paths. 1066*333d2b36SAndroid Build Coastguard Workerfunc (m TestingModule) OutputFiles(ctx *TestContext, t *testing.T, tag string) Paths { 1067*333d2b36SAndroid Build Coastguard Worker outputFiles := OtherModuleProviderOrDefault(ctx.OtherModuleProviderAdaptor(), m.Module(), OutputFilesProvider) 1068*333d2b36SAndroid Build Coastguard Worker if tag == "" && outputFiles.DefaultOutputFiles != nil { 1069*333d2b36SAndroid Build Coastguard Worker return outputFiles.DefaultOutputFiles.RelativeToTop() 1070*333d2b36SAndroid Build Coastguard Worker } else if taggedOutputFiles, hasTag := outputFiles.TaggedOutputFiles[tag]; hasTag { 1071*333d2b36SAndroid Build Coastguard Worker return taggedOutputFiles.RelativeToTop() 1072*333d2b36SAndroid Build Coastguard Worker } 1073*333d2b36SAndroid Build Coastguard Worker 1074*333d2b36SAndroid Build Coastguard Worker t.Fatal(fmt.Errorf("No test output file has been set for tag %q", tag)) 1075*333d2b36SAndroid Build Coastguard Worker return nil 1076*333d2b36SAndroid Build Coastguard Worker} 1077*333d2b36SAndroid Build Coastguard Worker 1078*333d2b36SAndroid Build Coastguard Worker// TestingSingleton is wrapper around an android.Singleton that provides methods to find information about individual 1079*333d2b36SAndroid Build Coastguard Worker// ctx.Build parameters for verification in tests. 1080*333d2b36SAndroid Build Coastguard Workertype TestingSingleton struct { 1081*333d2b36SAndroid Build Coastguard Worker baseTestingComponent 1082*333d2b36SAndroid Build Coastguard Worker singleton Singleton 1083*333d2b36SAndroid Build Coastguard Worker} 1084*333d2b36SAndroid Build Coastguard Worker 1085*333d2b36SAndroid Build Coastguard Worker// Singleton returns the Singleton wrapped by the TestingSingleton. 1086*333d2b36SAndroid Build Coastguard Workerfunc (s TestingSingleton) Singleton() Singleton { 1087*333d2b36SAndroid Build Coastguard Worker return s.singleton 1088*333d2b36SAndroid Build Coastguard Worker} 1089*333d2b36SAndroid Build Coastguard Worker 1090*333d2b36SAndroid Build Coastguard Workerfunc FailIfErrored(t *testing.T, errs []error) { 1091*333d2b36SAndroid Build Coastguard Worker t.Helper() 1092*333d2b36SAndroid Build Coastguard Worker if len(errs) > 0 { 1093*333d2b36SAndroid Build Coastguard Worker for _, err := range errs { 1094*333d2b36SAndroid Build Coastguard Worker t.Error(err) 1095*333d2b36SAndroid Build Coastguard Worker } 1096*333d2b36SAndroid Build Coastguard Worker t.FailNow() 1097*333d2b36SAndroid Build Coastguard Worker } 1098*333d2b36SAndroid Build Coastguard Worker} 1099*333d2b36SAndroid Build Coastguard Worker 1100*333d2b36SAndroid Build Coastguard Worker// Fail if no errors that matched the regular expression were found. 1101*333d2b36SAndroid Build Coastguard Worker// 1102*333d2b36SAndroid Build Coastguard Worker// Returns true if a matching error was found, false otherwise. 1103*333d2b36SAndroid Build Coastguard Workerfunc FailIfNoMatchingErrors(t *testing.T, pattern string, errs []error) bool { 1104*333d2b36SAndroid Build Coastguard Worker t.Helper() 1105*333d2b36SAndroid Build Coastguard Worker 1106*333d2b36SAndroid Build Coastguard Worker matcher, err := regexp.Compile(pattern) 1107*333d2b36SAndroid Build Coastguard Worker if err != nil { 1108*333d2b36SAndroid Build Coastguard Worker t.Fatalf("failed to compile regular expression %q because %s", pattern, err) 1109*333d2b36SAndroid Build Coastguard Worker } 1110*333d2b36SAndroid Build Coastguard Worker 1111*333d2b36SAndroid Build Coastguard Worker found := false 1112*333d2b36SAndroid Build Coastguard Worker for _, err := range errs { 1113*333d2b36SAndroid Build Coastguard Worker if matcher.FindStringIndex(err.Error()) != nil { 1114*333d2b36SAndroid Build Coastguard Worker found = true 1115*333d2b36SAndroid Build Coastguard Worker break 1116*333d2b36SAndroid Build Coastguard Worker } 1117*333d2b36SAndroid Build Coastguard Worker } 1118*333d2b36SAndroid Build Coastguard Worker if !found { 1119*333d2b36SAndroid Build Coastguard Worker t.Errorf("could not match the expected error regex %q (checked %d error(s))", pattern, len(errs)) 1120*333d2b36SAndroid Build Coastguard Worker for i, err := range errs { 1121*333d2b36SAndroid Build Coastguard Worker t.Errorf("errs[%d] = %q", i, err) 1122*333d2b36SAndroid Build Coastguard Worker } 1123*333d2b36SAndroid Build Coastguard Worker } 1124*333d2b36SAndroid Build Coastguard Worker 1125*333d2b36SAndroid Build Coastguard Worker return found 1126*333d2b36SAndroid Build Coastguard Worker} 1127*333d2b36SAndroid Build Coastguard Worker 1128*333d2b36SAndroid Build Coastguard Workerfunc CheckErrorsAgainstExpectations(t *testing.T, errs []error, expectedErrorPatterns []string) { 1129*333d2b36SAndroid Build Coastguard Worker t.Helper() 1130*333d2b36SAndroid Build Coastguard Worker 1131*333d2b36SAndroid Build Coastguard Worker if expectedErrorPatterns == nil { 1132*333d2b36SAndroid Build Coastguard Worker FailIfErrored(t, errs) 1133*333d2b36SAndroid Build Coastguard Worker } else { 1134*333d2b36SAndroid Build Coastguard Worker for _, expectedError := range expectedErrorPatterns { 1135*333d2b36SAndroid Build Coastguard Worker FailIfNoMatchingErrors(t, expectedError, errs) 1136*333d2b36SAndroid Build Coastguard Worker } 1137*333d2b36SAndroid Build Coastguard Worker if len(errs) > len(expectedErrorPatterns) { 1138*333d2b36SAndroid Build Coastguard Worker t.Errorf("additional errors found, expected %d, found %d", 1139*333d2b36SAndroid Build Coastguard Worker len(expectedErrorPatterns), len(errs)) 1140*333d2b36SAndroid Build Coastguard Worker for i, expectedError := range expectedErrorPatterns { 1141*333d2b36SAndroid Build Coastguard Worker t.Errorf("expectedErrors[%d] = %s", i, expectedError) 1142*333d2b36SAndroid Build Coastguard Worker } 1143*333d2b36SAndroid Build Coastguard Worker for i, err := range errs { 1144*333d2b36SAndroid Build Coastguard Worker t.Errorf("errs[%d] = %s", i, err) 1145*333d2b36SAndroid Build Coastguard Worker } 1146*333d2b36SAndroid Build Coastguard Worker t.FailNow() 1147*333d2b36SAndroid Build Coastguard Worker } 1148*333d2b36SAndroid Build Coastguard Worker } 1149*333d2b36SAndroid Build Coastguard Worker} 1150*333d2b36SAndroid Build Coastguard Worker 1151*333d2b36SAndroid Build Coastguard Workerfunc SetKatiEnabledForTests(config Config) { 1152*333d2b36SAndroid Build Coastguard Worker config.katiEnabled = true 1153*333d2b36SAndroid Build Coastguard Worker} 1154*333d2b36SAndroid Build Coastguard Worker 1155*333d2b36SAndroid Build Coastguard Workerfunc AndroidMkEntriesForTest(t *testing.T, ctx *TestContext, mod blueprint.Module) []AndroidMkEntries { 1156*333d2b36SAndroid Build Coastguard Worker t.Helper() 1157*333d2b36SAndroid Build Coastguard Worker var p AndroidMkEntriesProvider 1158*333d2b36SAndroid Build Coastguard Worker var ok bool 1159*333d2b36SAndroid Build Coastguard Worker if p, ok = mod.(AndroidMkEntriesProvider); !ok { 1160*333d2b36SAndroid Build Coastguard Worker t.Errorf("module does not implement AndroidMkEntriesProvider: " + mod.Name()) 1161*333d2b36SAndroid Build Coastguard Worker } 1162*333d2b36SAndroid Build Coastguard Worker 1163*333d2b36SAndroid Build Coastguard Worker entriesList := p.AndroidMkEntries() 1164*333d2b36SAndroid Build Coastguard Worker aconfigUpdateAndroidMkEntries(ctx, mod.(Module), &entriesList) 1165*333d2b36SAndroid Build Coastguard Worker for i := range entriesList { 1166*333d2b36SAndroid Build Coastguard Worker entriesList[i].fillInEntries(ctx, mod) 1167*333d2b36SAndroid Build Coastguard Worker } 1168*333d2b36SAndroid Build Coastguard Worker return entriesList 1169*333d2b36SAndroid Build Coastguard Worker} 1170*333d2b36SAndroid Build Coastguard Worker 1171*333d2b36SAndroid Build Coastguard Workerfunc AndroidMkInfoForTest(t *testing.T, ctx *TestContext, mod blueprint.Module) *AndroidMkProviderInfo { 1172*333d2b36SAndroid Build Coastguard Worker if runtime.GOOS == "darwin" && mod.(Module).base().Os() != Darwin { 1173*333d2b36SAndroid Build Coastguard Worker // The AndroidMkInfo provider is not set in this case. 1174*333d2b36SAndroid Build Coastguard Worker t.Skip("AndroidMkInfo provider is not set on darwin") 1175*333d2b36SAndroid Build Coastguard Worker } 1176*333d2b36SAndroid Build Coastguard Worker 1177*333d2b36SAndroid Build Coastguard Worker t.Helper() 1178*333d2b36SAndroid Build Coastguard Worker var ok bool 1179*333d2b36SAndroid Build Coastguard Worker if _, ok = mod.(AndroidMkProviderInfoProducer); !ok { 1180*333d2b36SAndroid Build Coastguard Worker t.Errorf("module does not implement AndroidMkProviderInfoProducer: " + mod.Name()) 1181*333d2b36SAndroid Build Coastguard Worker } 1182*333d2b36SAndroid Build Coastguard Worker 1183*333d2b36SAndroid Build Coastguard Worker info := OtherModuleProviderOrDefault(ctx, mod, AndroidMkInfoProvider) 1184*333d2b36SAndroid Build Coastguard Worker aconfigUpdateAndroidMkInfos(ctx, mod.(Module), info) 1185*333d2b36SAndroid Build Coastguard Worker info.PrimaryInfo.fillInEntries(ctx, mod) 1186*333d2b36SAndroid Build Coastguard Worker if len(info.ExtraInfo) > 0 { 1187*333d2b36SAndroid Build Coastguard Worker for _, ei := range info.ExtraInfo { 1188*333d2b36SAndroid Build Coastguard Worker ei.fillInEntries(ctx, mod) 1189*333d2b36SAndroid Build Coastguard Worker } 1190*333d2b36SAndroid Build Coastguard Worker } 1191*333d2b36SAndroid Build Coastguard Worker 1192*333d2b36SAndroid Build Coastguard Worker return info 1193*333d2b36SAndroid Build Coastguard Worker} 1194*333d2b36SAndroid Build Coastguard Worker 1195*333d2b36SAndroid Build Coastguard Workerfunc AndroidMkDataForTest(t *testing.T, ctx *TestContext, mod blueprint.Module) AndroidMkData { 1196*333d2b36SAndroid Build Coastguard Worker t.Helper() 1197*333d2b36SAndroid Build Coastguard Worker var p AndroidMkDataProvider 1198*333d2b36SAndroid Build Coastguard Worker var ok bool 1199*333d2b36SAndroid Build Coastguard Worker if p, ok = mod.(AndroidMkDataProvider); !ok { 1200*333d2b36SAndroid Build Coastguard Worker t.Fatalf("module does not implement AndroidMkDataProvider: " + mod.Name()) 1201*333d2b36SAndroid Build Coastguard Worker } 1202*333d2b36SAndroid Build Coastguard Worker data := p.AndroidMk() 1203*333d2b36SAndroid Build Coastguard Worker data.fillInData(ctx, mod) 1204*333d2b36SAndroid Build Coastguard Worker aconfigUpdateAndroidMkData(ctx, mod.(Module), &data) 1205*333d2b36SAndroid Build Coastguard Worker return data 1206*333d2b36SAndroid Build Coastguard Worker} 1207*333d2b36SAndroid Build Coastguard Worker 1208*333d2b36SAndroid Build Coastguard Worker// Normalize the path for testing. 1209*333d2b36SAndroid Build Coastguard Worker// 1210*333d2b36SAndroid Build Coastguard Worker// If the path is relative to the build directory then return the relative path 1211*333d2b36SAndroid Build Coastguard Worker// to avoid tests having to deal with the dynamically generated build directory. 1212*333d2b36SAndroid Build Coastguard Worker// 1213*333d2b36SAndroid Build Coastguard Worker// Otherwise, return the supplied path as it is almost certainly a source path 1214*333d2b36SAndroid Build Coastguard Worker// that is relative to the root of the source tree. 1215*333d2b36SAndroid Build Coastguard Worker// 1216*333d2b36SAndroid Build Coastguard Worker// The build and source paths should be distinguishable based on their contents. 1217*333d2b36SAndroid Build Coastguard Worker// 1218*333d2b36SAndroid Build Coastguard Worker// deprecated: use PathRelativeToTop instead as it handles make install paths and differentiates 1219*333d2b36SAndroid Build Coastguard Worker// between output and source properly. 1220*333d2b36SAndroid Build Coastguard Workerfunc NormalizePathForTesting(path Path) string { 1221*333d2b36SAndroid Build Coastguard Worker if path == nil { 1222*333d2b36SAndroid Build Coastguard Worker return "<nil path>" 1223*333d2b36SAndroid Build Coastguard Worker } 1224*333d2b36SAndroid Build Coastguard Worker p := path.String() 1225*333d2b36SAndroid Build Coastguard Worker if w, ok := path.(WritablePath); ok { 1226*333d2b36SAndroid Build Coastguard Worker rel, err := filepath.Rel(w.getSoongOutDir(), p) 1227*333d2b36SAndroid Build Coastguard Worker if err != nil { 1228*333d2b36SAndroid Build Coastguard Worker panic(err) 1229*333d2b36SAndroid Build Coastguard Worker } 1230*333d2b36SAndroid Build Coastguard Worker return rel 1231*333d2b36SAndroid Build Coastguard Worker } 1232*333d2b36SAndroid Build Coastguard Worker return p 1233*333d2b36SAndroid Build Coastguard Worker} 1234*333d2b36SAndroid Build Coastguard Worker 1235*333d2b36SAndroid Build Coastguard Worker// NormalizePathsForTesting creates a slice of strings where each string is the result of applying 1236*333d2b36SAndroid Build Coastguard Worker// NormalizePathForTesting to the corresponding Path in the input slice. 1237*333d2b36SAndroid Build Coastguard Worker// 1238*333d2b36SAndroid Build Coastguard Worker// deprecated: use PathsRelativeToTop instead as it handles make install paths and differentiates 1239*333d2b36SAndroid Build Coastguard Worker// between output and source properly. 1240*333d2b36SAndroid Build Coastguard Workerfunc NormalizePathsForTesting(paths Paths) []string { 1241*333d2b36SAndroid Build Coastguard Worker var result []string 1242*333d2b36SAndroid Build Coastguard Worker for _, path := range paths { 1243*333d2b36SAndroid Build Coastguard Worker relative := NormalizePathForTesting(path) 1244*333d2b36SAndroid Build Coastguard Worker result = append(result, relative) 1245*333d2b36SAndroid Build Coastguard Worker } 1246*333d2b36SAndroid Build Coastguard Worker return result 1247*333d2b36SAndroid Build Coastguard Worker} 1248*333d2b36SAndroid Build Coastguard Worker 1249*333d2b36SAndroid Build Coastguard Worker// PathRelativeToTop returns a string representation of the path relative to a notional top 1250*333d2b36SAndroid Build Coastguard Worker// directory. 1251*333d2b36SAndroid Build Coastguard Worker// 1252*333d2b36SAndroid Build Coastguard Worker// It return "<nil path>" if the supplied path is nil, otherwise it returns the result of calling 1253*333d2b36SAndroid Build Coastguard Worker// Path.RelativeToTop to obtain a relative Path and then calling Path.String on that to get the 1254*333d2b36SAndroid Build Coastguard Worker// string representation. 1255*333d2b36SAndroid Build Coastguard Workerfunc PathRelativeToTop(path Path) string { 1256*333d2b36SAndroid Build Coastguard Worker if path == nil { 1257*333d2b36SAndroid Build Coastguard Worker return "<nil path>" 1258*333d2b36SAndroid Build Coastguard Worker } 1259*333d2b36SAndroid Build Coastguard Worker return path.RelativeToTop().String() 1260*333d2b36SAndroid Build Coastguard Worker} 1261*333d2b36SAndroid Build Coastguard Worker 1262*333d2b36SAndroid Build Coastguard Worker// PathsRelativeToTop creates a slice of strings where each string is the result of applying 1263*333d2b36SAndroid Build Coastguard Worker// PathRelativeToTop to the corresponding Path in the input slice. 1264*333d2b36SAndroid Build Coastguard Workerfunc PathsRelativeToTop(paths Paths) []string { 1265*333d2b36SAndroid Build Coastguard Worker var result []string 1266*333d2b36SAndroid Build Coastguard Worker for _, path := range paths { 1267*333d2b36SAndroid Build Coastguard Worker relative := PathRelativeToTop(path) 1268*333d2b36SAndroid Build Coastguard Worker result = append(result, relative) 1269*333d2b36SAndroid Build Coastguard Worker } 1270*333d2b36SAndroid Build Coastguard Worker return result 1271*333d2b36SAndroid Build Coastguard Worker} 1272*333d2b36SAndroid Build Coastguard Worker 1273*333d2b36SAndroid Build Coastguard Worker// StringPathRelativeToTop returns a string representation of the path relative to a notional top 1274*333d2b36SAndroid Build Coastguard Worker// directory. 1275*333d2b36SAndroid Build Coastguard Worker// 1276*333d2b36SAndroid Build Coastguard Worker// See Path.RelativeToTop for more details as to what `relative to top` means. 1277*333d2b36SAndroid Build Coastguard Worker// 1278*333d2b36SAndroid Build Coastguard Worker// This is provided for processing paths that have already been converted into a string, e.g. paths 1279*333d2b36SAndroid Build Coastguard Worker// in AndroidMkEntries structures. As a result it needs to be supplied the soong output dir against 1280*333d2b36SAndroid Build Coastguard Worker// which it can try and relativize paths. PathRelativeToTop must be used for process Path objects. 1281*333d2b36SAndroid Build Coastguard Workerfunc StringPathRelativeToTop(soongOutDir string, path string) string { 1282*333d2b36SAndroid Build Coastguard Worker ensureTestOnly() 1283*333d2b36SAndroid Build Coastguard Worker 1284*333d2b36SAndroid Build Coastguard Worker // A relative path must be a source path so leave it as it is. 1285*333d2b36SAndroid Build Coastguard Worker if !filepath.IsAbs(path) { 1286*333d2b36SAndroid Build Coastguard Worker return path 1287*333d2b36SAndroid Build Coastguard Worker } 1288*333d2b36SAndroid Build Coastguard Worker 1289*333d2b36SAndroid Build Coastguard Worker // Check to see if the path is relative to the soong out dir. 1290*333d2b36SAndroid Build Coastguard Worker rel, isRel, err := maybeRelErr(soongOutDir, path) 1291*333d2b36SAndroid Build Coastguard Worker if err != nil { 1292*333d2b36SAndroid Build Coastguard Worker panic(err) 1293*333d2b36SAndroid Build Coastguard Worker } 1294*333d2b36SAndroid Build Coastguard Worker 1295*333d2b36SAndroid Build Coastguard Worker if isRel { 1296*333d2b36SAndroid Build Coastguard Worker if strings.HasSuffix(soongOutDir, testOutSoongSubDir) { 1297*333d2b36SAndroid Build Coastguard Worker // The path is in the soong out dir so indicate that in the relative path. 1298*333d2b36SAndroid Build Coastguard Worker return filepath.Join(TestOutSoongDir, rel) 1299*333d2b36SAndroid Build Coastguard Worker } else { 1300*333d2b36SAndroid Build Coastguard Worker // Handle the PathForArbitraryOutput case 1301*333d2b36SAndroid Build Coastguard Worker return filepath.Join(testOutDir, rel) 1302*333d2b36SAndroid Build Coastguard Worker 1303*333d2b36SAndroid Build Coastguard Worker } 1304*333d2b36SAndroid Build Coastguard Worker } 1305*333d2b36SAndroid Build Coastguard Worker 1306*333d2b36SAndroid Build Coastguard Worker // Check to see if the path is relative to the top level out dir. 1307*333d2b36SAndroid Build Coastguard Worker outDir := filepath.Dir(soongOutDir) 1308*333d2b36SAndroid Build Coastguard Worker rel, isRel, err = maybeRelErr(outDir, path) 1309*333d2b36SAndroid Build Coastguard Worker if err != nil { 1310*333d2b36SAndroid Build Coastguard Worker panic(err) 1311*333d2b36SAndroid Build Coastguard Worker } 1312*333d2b36SAndroid Build Coastguard Worker 1313*333d2b36SAndroid Build Coastguard Worker if isRel { 1314*333d2b36SAndroid Build Coastguard Worker // The path is in the out dir so indicate that in the relative path. 1315*333d2b36SAndroid Build Coastguard Worker return filepath.Join("out", rel) 1316*333d2b36SAndroid Build Coastguard Worker } 1317*333d2b36SAndroid Build Coastguard Worker 1318*333d2b36SAndroid Build Coastguard Worker // This should never happen. 1319*333d2b36SAndroid Build Coastguard Worker panic(fmt.Errorf("internal error: absolute path %s is not relative to the out dir %s", path, outDir)) 1320*333d2b36SAndroid Build Coastguard Worker} 1321*333d2b36SAndroid Build Coastguard Worker 1322*333d2b36SAndroid Build Coastguard Worker// StringPathsRelativeToTop creates a slice of strings where each string is the result of applying 1323*333d2b36SAndroid Build Coastguard Worker// StringPathRelativeToTop to the corresponding string path in the input slice. 1324*333d2b36SAndroid Build Coastguard Worker// 1325*333d2b36SAndroid Build Coastguard Worker// This is provided for processing paths that have already been converted into a string, e.g. paths 1326*333d2b36SAndroid Build Coastguard Worker// in AndroidMkEntries structures. As a result it needs to be supplied the soong output dir against 1327*333d2b36SAndroid Build Coastguard Worker// which it can try and relativize paths. PathsRelativeToTop must be used for process Paths objects. 1328*333d2b36SAndroid Build Coastguard Workerfunc StringPathsRelativeToTop(soongOutDir string, paths []string) []string { 1329*333d2b36SAndroid Build Coastguard Worker var result []string 1330*333d2b36SAndroid Build Coastguard Worker for _, path := range paths { 1331*333d2b36SAndroid Build Coastguard Worker relative := StringPathRelativeToTop(soongOutDir, path) 1332*333d2b36SAndroid Build Coastguard Worker result = append(result, relative) 1333*333d2b36SAndroid Build Coastguard Worker } 1334*333d2b36SAndroid Build Coastguard Worker return result 1335*333d2b36SAndroid Build Coastguard Worker} 1336*333d2b36SAndroid Build Coastguard Worker 1337*333d2b36SAndroid Build Coastguard Worker// StringRelativeToTop will normalize a string containing paths, e.g. ninja command, by replacing 1338*333d2b36SAndroid Build Coastguard Worker// any references to the test specific temporary build directory that changes with each run to a 1339*333d2b36SAndroid Build Coastguard Worker// fixed path relative to a notional top directory. 1340*333d2b36SAndroid Build Coastguard Worker// 1341*333d2b36SAndroid Build Coastguard Worker// This is similar to StringPathRelativeToTop except that assumes the string is a single path 1342*333d2b36SAndroid Build Coastguard Worker// containing at most one instance of the temporary build directory at the start of the path while 1343*333d2b36SAndroid Build Coastguard Worker// this assumes that there can be any number at any position. 1344*333d2b36SAndroid Build Coastguard Workerfunc StringRelativeToTop(config Config, command string) string { 1345*333d2b36SAndroid Build Coastguard Worker return normalizeStringRelativeToTop(config, command) 1346*333d2b36SAndroid Build Coastguard Worker} 1347*333d2b36SAndroid Build Coastguard Worker 1348*333d2b36SAndroid Build Coastguard Worker// StringsRelativeToTop will return a new slice such that each item in the new slice is the result 1349*333d2b36SAndroid Build Coastguard Worker// of calling StringRelativeToTop on the corresponding item in the input slice. 1350*333d2b36SAndroid Build Coastguard Workerfunc StringsRelativeToTop(config Config, command []string) []string { 1351*333d2b36SAndroid Build Coastguard Worker return normalizeStringArrayRelativeToTop(config, command) 1352*333d2b36SAndroid Build Coastguard Worker} 1353*333d2b36SAndroid Build Coastguard Worker 1354*333d2b36SAndroid Build Coastguard Workerfunc EnsureListContainsSuffix(t *testing.T, result []string, expected string) { 1355*333d2b36SAndroid Build Coastguard Worker t.Helper() 1356*333d2b36SAndroid Build Coastguard Worker if !SuffixInList(result, expected) { 1357*333d2b36SAndroid Build Coastguard Worker t.Errorf("%q is not found in %v", expected, result) 1358*333d2b36SAndroid Build Coastguard Worker } 1359*333d2b36SAndroid Build Coastguard Worker} 1360*333d2b36SAndroid Build Coastguard Worker 1361*333d2b36SAndroid Build Coastguard Workertype panickingConfigAndErrorContext struct { 1362*333d2b36SAndroid Build Coastguard Worker ctx *TestContext 1363*333d2b36SAndroid Build Coastguard Worker} 1364*333d2b36SAndroid Build Coastguard Worker 1365*333d2b36SAndroid Build Coastguard Workerfunc (ctx *panickingConfigAndErrorContext) OtherModulePropertyErrorf(module Module, property, fmt string, args ...interface{}) { 1366*333d2b36SAndroid Build Coastguard Worker panic(ctx.ctx.PropertyErrorf(module, property, fmt, args...).Error()) 1367*333d2b36SAndroid Build Coastguard Worker} 1368*333d2b36SAndroid Build Coastguard Worker 1369*333d2b36SAndroid Build Coastguard Workerfunc (ctx *panickingConfigAndErrorContext) Config() Config { 1370*333d2b36SAndroid Build Coastguard Worker return ctx.ctx.Config() 1371*333d2b36SAndroid Build Coastguard Worker} 1372*333d2b36SAndroid Build Coastguard Worker 1373*333d2b36SAndroid Build Coastguard Workerfunc (ctx *panickingConfigAndErrorContext) HasMutatorFinished(mutatorName string) bool { 1374*333d2b36SAndroid Build Coastguard Worker return ctx.ctx.HasMutatorFinished(mutatorName) 1375*333d2b36SAndroid Build Coastguard Worker} 1376*333d2b36SAndroid Build Coastguard Worker 1377*333d2b36SAndroid Build Coastguard Workerfunc (ctx *panickingConfigAndErrorContext) otherModuleProvider(m blueprint.Module, p blueprint.AnyProviderKey) (any, bool) { 1378*333d2b36SAndroid Build Coastguard Worker return ctx.ctx.otherModuleProvider(m, p) 1379*333d2b36SAndroid Build Coastguard Worker} 1380*333d2b36SAndroid Build Coastguard Worker 1381*333d2b36SAndroid Build Coastguard Workerfunc PanickingConfigAndErrorContext(ctx *TestContext) ConfigurableEvaluatorContext { 1382*333d2b36SAndroid Build Coastguard Worker return &panickingConfigAndErrorContext{ 1383*333d2b36SAndroid Build Coastguard Worker ctx: ctx, 1384*333d2b36SAndroid Build Coastguard Worker } 1385*333d2b36SAndroid Build Coastguard Worker} 1386