1*333d2b36SAndroid Build Coastguard Worker// Copyright 2019 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 sdk 16*333d2b36SAndroid Build Coastguard Worker 17*333d2b36SAndroid Build Coastguard Workerimport ( 18*333d2b36SAndroid Build Coastguard Worker "fmt" 19*333d2b36SAndroid Build Coastguard Worker "path/filepath" 20*333d2b36SAndroid Build Coastguard Worker "strings" 21*333d2b36SAndroid Build Coastguard Worker "testing" 22*333d2b36SAndroid Build Coastguard Worker 23*333d2b36SAndroid Build Coastguard Worker "android/soong/android" 24*333d2b36SAndroid Build Coastguard Worker "android/soong/apex" 25*333d2b36SAndroid Build Coastguard Worker "android/soong/cc" 26*333d2b36SAndroid Build Coastguard Worker "android/soong/genrule" 27*333d2b36SAndroid Build Coastguard Worker "android/soong/java" 28*333d2b36SAndroid Build Coastguard Worker 29*333d2b36SAndroid Build Coastguard Worker "github.com/google/blueprint/proptools" 30*333d2b36SAndroid Build Coastguard Worker) 31*333d2b36SAndroid Build Coastguard Worker 32*333d2b36SAndroid Build Coastguard Worker// Prepare for running an sdk test with an apex. 33*333d2b36SAndroid Build Coastguard Workervar prepareForSdkTestWithApex = android.GroupFixturePreparers( 34*333d2b36SAndroid Build Coastguard Worker apex.PrepareForTestWithApexBuildComponents, 35*333d2b36SAndroid Build Coastguard Worker android.FixtureAddTextFile("sdk/tests/Android.bp", ` 36*333d2b36SAndroid Build Coastguard Worker apex_key { 37*333d2b36SAndroid Build Coastguard Worker name: "myapex.key", 38*333d2b36SAndroid Build Coastguard Worker public_key: "myapex.avbpubkey", 39*333d2b36SAndroid Build Coastguard Worker private_key: "myapex.pem", 40*333d2b36SAndroid Build Coastguard Worker } 41*333d2b36SAndroid Build Coastguard Worker 42*333d2b36SAndroid Build Coastguard Worker android_app_certificate { 43*333d2b36SAndroid Build Coastguard Worker name: "myapex.cert", 44*333d2b36SAndroid Build Coastguard Worker certificate: "myapex", 45*333d2b36SAndroid Build Coastguard Worker } 46*333d2b36SAndroid Build Coastguard Worker `), 47*333d2b36SAndroid Build Coastguard Worker 48*333d2b36SAndroid Build Coastguard Worker android.FixtureMergeMockFs(map[string][]byte{ 49*333d2b36SAndroid Build Coastguard Worker "apex_manifest.json": nil, 50*333d2b36SAndroid Build Coastguard Worker "system/sepolicy/apex/myapex-file_contexts": nil, 51*333d2b36SAndroid Build Coastguard Worker "system/sepolicy/apex/myapex2-file_contexts": nil, 52*333d2b36SAndroid Build Coastguard Worker "system/sepolicy/apex/mysdkapex-file_contexts": nil, 53*333d2b36SAndroid Build Coastguard Worker "sdk/tests/myapex.avbpubkey": nil, 54*333d2b36SAndroid Build Coastguard Worker "sdk/tests/myapex.pem": nil, 55*333d2b36SAndroid Build Coastguard Worker "sdk/tests/myapex.x509.pem": nil, 56*333d2b36SAndroid Build Coastguard Worker "sdk/tests/myapex.pk8": nil, 57*333d2b36SAndroid Build Coastguard Worker }), 58*333d2b36SAndroid Build Coastguard Worker) 59*333d2b36SAndroid Build Coastguard Worker 60*333d2b36SAndroid Build Coastguard Worker// Legacy preparer used for running tests within the sdk package. 61*333d2b36SAndroid Build Coastguard Worker// 62*333d2b36SAndroid Build Coastguard Worker// This includes everything that was needed to run any test in the sdk package prior to the 63*333d2b36SAndroid Build Coastguard Worker// introduction of the test fixtures. Tests that are being converted to use fixtures directly 64*333d2b36SAndroid Build Coastguard Worker// rather than through the testSdkError() and testSdkWithFs() methods should avoid using this and 65*333d2b36SAndroid Build Coastguard Worker// instead should use the various preparers directly using android.GroupFixturePreparers(...) to 66*333d2b36SAndroid Build Coastguard Worker// group them when necessary. 67*333d2b36SAndroid Build Coastguard Worker// 68*333d2b36SAndroid Build Coastguard Worker// deprecated 69*333d2b36SAndroid Build Coastguard Workervar prepareForSdkTest = android.GroupFixturePreparers( 70*333d2b36SAndroid Build Coastguard Worker cc.PrepareForTestWithCcDefaultModules, 71*333d2b36SAndroid Build Coastguard Worker genrule.PrepareForTestWithGenRuleBuildComponents, 72*333d2b36SAndroid Build Coastguard Worker java.PrepareForTestWithJavaBuildComponents, 73*333d2b36SAndroid Build Coastguard Worker PrepareForTestWithSdkBuildComponents, 74*333d2b36SAndroid Build Coastguard Worker 75*333d2b36SAndroid Build Coastguard Worker prepareForSdkTestWithApex, 76*333d2b36SAndroid Build Coastguard Worker 77*333d2b36SAndroid Build Coastguard Worker cc.PrepareForTestOnWindows, 78*333d2b36SAndroid Build Coastguard Worker android.FixtureModifyConfig(func(config android.Config) { 79*333d2b36SAndroid Build Coastguard Worker // Add windows as a default disable OS to test behavior when some OS variants 80*333d2b36SAndroid Build Coastguard Worker // are disabled. 81*333d2b36SAndroid Build Coastguard Worker config.Targets[android.Windows] = []android.Target{ 82*333d2b36SAndroid Build Coastguard Worker {android.Windows, android.Arch{ArchType: android.X86_64}, android.NativeBridgeDisabled, "", "", true}, 83*333d2b36SAndroid Build Coastguard Worker } 84*333d2b36SAndroid Build Coastguard Worker }), 85*333d2b36SAndroid Build Coastguard Worker 86*333d2b36SAndroid Build Coastguard Worker // Add a build number file. 87*333d2b36SAndroid Build Coastguard Worker android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) { 88*333d2b36SAndroid Build Coastguard Worker variables.BuildNumberFile = proptools.StringPtr(BUILD_NUMBER_FILE) 89*333d2b36SAndroid Build Coastguard Worker }), 90*333d2b36SAndroid Build Coastguard Worker 91*333d2b36SAndroid Build Coastguard Worker // Make sure that every test provides all the source files. 92*333d2b36SAndroid Build Coastguard Worker android.PrepareForTestDisallowNonExistentPaths, 93*333d2b36SAndroid Build Coastguard Worker android.MockFS{ 94*333d2b36SAndroid Build Coastguard Worker "Test.java": nil, 95*333d2b36SAndroid Build Coastguard Worker }.AddToFixture(), 96*333d2b36SAndroid Build Coastguard Worker) 97*333d2b36SAndroid Build Coastguard Worker 98*333d2b36SAndroid Build Coastguard Workervar PrepareForTestWithSdkBuildComponents = android.GroupFixturePreparers( 99*333d2b36SAndroid Build Coastguard Worker android.FixtureRegisterWithContext(registerModuleExportsBuildComponents), 100*333d2b36SAndroid Build Coastguard Worker android.FixtureRegisterWithContext(registerSdkBuildComponents), 101*333d2b36SAndroid Build Coastguard Worker) 102*333d2b36SAndroid Build Coastguard Worker 103*333d2b36SAndroid Build Coastguard Workerfunc testSdkWithFs(t *testing.T, bp string, fs android.MockFS) *android.TestResult { 104*333d2b36SAndroid Build Coastguard Worker t.Helper() 105*333d2b36SAndroid Build Coastguard Worker return android.GroupFixturePreparers( 106*333d2b36SAndroid Build Coastguard Worker prepareForSdkTest, 107*333d2b36SAndroid Build Coastguard Worker fs.AddToFixture(), 108*333d2b36SAndroid Build Coastguard Worker ).RunTestWithBp(t, bp) 109*333d2b36SAndroid Build Coastguard Worker} 110*333d2b36SAndroid Build Coastguard Worker 111*333d2b36SAndroid Build Coastguard Workerfunc testSdkError(t *testing.T, pattern, bp string) { 112*333d2b36SAndroid Build Coastguard Worker t.Helper() 113*333d2b36SAndroid Build Coastguard Worker prepareForSdkTest. 114*333d2b36SAndroid Build Coastguard Worker ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern(pattern)). 115*333d2b36SAndroid Build Coastguard Worker RunTestWithBp(t, bp) 116*333d2b36SAndroid Build Coastguard Worker} 117*333d2b36SAndroid Build Coastguard Worker 118*333d2b36SAndroid Build Coastguard Workerfunc ensureListContains(t *testing.T, result []string, expected string) { 119*333d2b36SAndroid Build Coastguard Worker t.Helper() 120*333d2b36SAndroid Build Coastguard Worker if !android.InList(expected, result) { 121*333d2b36SAndroid Build Coastguard Worker t.Errorf("%q is not found in %v", expected, result) 122*333d2b36SAndroid Build Coastguard Worker } 123*333d2b36SAndroid Build Coastguard Worker} 124*333d2b36SAndroid Build Coastguard Worker 125*333d2b36SAndroid Build Coastguard Worker// Analyse the sdk build rules to extract information about what it is doing. 126*333d2b36SAndroid Build Coastguard Worker// 127*333d2b36SAndroid Build Coastguard Worker// e.g. find the src/dest pairs from each cp command, the various zip files 128*333d2b36SAndroid Build Coastguard Worker// generated, etc. 129*333d2b36SAndroid Build Coastguard Workerfunc getSdkSnapshotBuildInfo(t *testing.T, result *android.TestResult, sdk *sdk) *snapshotBuildInfo { 130*333d2b36SAndroid Build Coastguard Worker info := &snapshotBuildInfo{ 131*333d2b36SAndroid Build Coastguard Worker t: t, 132*333d2b36SAndroid Build Coastguard Worker r: result, 133*333d2b36SAndroid Build Coastguard Worker androidBpContents: sdk.GetAndroidBpContentsForTests(), 134*333d2b36SAndroid Build Coastguard Worker infoContents: sdk.GetInfoContentsForTests(), 135*333d2b36SAndroid Build Coastguard Worker snapshotTestCustomizations: map[snapshotTest]*snapshotTestCustomization{}, 136*333d2b36SAndroid Build Coastguard Worker targetBuildRelease: sdk.builderForTests.targetBuildRelease, 137*333d2b36SAndroid Build Coastguard Worker } 138*333d2b36SAndroid Build Coastguard Worker 139*333d2b36SAndroid Build Coastguard Worker buildParams := sdk.BuildParamsForTests() 140*333d2b36SAndroid Build Coastguard Worker copyRules := &strings.Builder{} 141*333d2b36SAndroid Build Coastguard Worker otherCopyRules := &strings.Builder{} 142*333d2b36SAndroid Build Coastguard Worker snapshotDirPrefix := sdk.builderForTests.snapshotDir.String() + "/" 143*333d2b36SAndroid Build Coastguard Worker 144*333d2b36SAndroid Build Coastguard Worker seenBuildNumberFile := false 145*333d2b36SAndroid Build Coastguard Worker for _, bp := range buildParams { 146*333d2b36SAndroid Build Coastguard Worker switch bp.Rule.String() { 147*333d2b36SAndroid Build Coastguard Worker case android.Cp.String(): 148*333d2b36SAndroid Build Coastguard Worker output := bp.Output 149*333d2b36SAndroid Build Coastguard Worker // Get destination relative to the snapshot root 150*333d2b36SAndroid Build Coastguard Worker dest := output.Rel() 151*333d2b36SAndroid Build Coastguard Worker src := android.NormalizePathForTesting(bp.Input) 152*333d2b36SAndroid Build Coastguard Worker // We differentiate between copy rules for the snapshot, and copy rules for the install file. 153*333d2b36SAndroid Build Coastguard Worker if strings.HasPrefix(output.String(), snapshotDirPrefix) { 154*333d2b36SAndroid Build Coastguard Worker // Don't include the build-number.txt file in the copy rules as that would break lots of 155*333d2b36SAndroid Build Coastguard Worker // tests, just verify that it is copied here as it should appear in every snapshot. 156*333d2b36SAndroid Build Coastguard Worker if output.Base() == BUILD_NUMBER_FILE { 157*333d2b36SAndroid Build Coastguard Worker seenBuildNumberFile = true 158*333d2b36SAndroid Build Coastguard Worker } else { 159*333d2b36SAndroid Build Coastguard Worker // Get source relative to build directory. 160*333d2b36SAndroid Build Coastguard Worker _, _ = fmt.Fprintf(copyRules, "%s -> %s\n", src, dest) 161*333d2b36SAndroid Build Coastguard Worker } 162*333d2b36SAndroid Build Coastguard Worker info.snapshotContents = append(info.snapshotContents, dest) 163*333d2b36SAndroid Build Coastguard Worker } else { 164*333d2b36SAndroid Build Coastguard Worker _, _ = fmt.Fprintf(otherCopyRules, "%s -> %s\n", src, dest) 165*333d2b36SAndroid Build Coastguard Worker } 166*333d2b36SAndroid Build Coastguard Worker 167*333d2b36SAndroid Build Coastguard Worker case repackageZip.String(): 168*333d2b36SAndroid Build Coastguard Worker // Add the destdir to the snapshot contents as that is effectively where 169*333d2b36SAndroid Build Coastguard Worker // the content of the repackaged zip is copied. 170*333d2b36SAndroid Build Coastguard Worker dest := bp.Args["destdir"] 171*333d2b36SAndroid Build Coastguard Worker info.snapshotContents = append(info.snapshotContents, dest) 172*333d2b36SAndroid Build Coastguard Worker 173*333d2b36SAndroid Build Coastguard Worker case zipFiles.String(): 174*333d2b36SAndroid Build Coastguard Worker // This could be an intermediate zip file and not the actual output zip. 175*333d2b36SAndroid Build Coastguard Worker // In that case this will be overridden when the rule to merge the zips 176*333d2b36SAndroid Build Coastguard Worker // is processed. 177*333d2b36SAndroid Build Coastguard Worker info.outputZip = android.NormalizePathForTesting(bp.Output) 178*333d2b36SAndroid Build Coastguard Worker 179*333d2b36SAndroid Build Coastguard Worker case mergeZips.String(): 180*333d2b36SAndroid Build Coastguard Worker // Copy the current outputZip to the intermediateZip. 181*333d2b36SAndroid Build Coastguard Worker info.intermediateZip = info.outputZip 182*333d2b36SAndroid Build Coastguard Worker mergeInput := android.NormalizePathForTesting(bp.Input) 183*333d2b36SAndroid Build Coastguard Worker if info.intermediateZip != mergeInput { 184*333d2b36SAndroid Build Coastguard Worker t.Errorf("Expected intermediate zip %s to be an input to merge zips but found %s instead", 185*333d2b36SAndroid Build Coastguard Worker info.intermediateZip, mergeInput) 186*333d2b36SAndroid Build Coastguard Worker } 187*333d2b36SAndroid Build Coastguard Worker 188*333d2b36SAndroid Build Coastguard Worker // Override output zip (which was actually the intermediate zip file) with the actual 189*333d2b36SAndroid Build Coastguard Worker // output zip. 190*333d2b36SAndroid Build Coastguard Worker info.outputZip = android.NormalizePathForTesting(bp.Output) 191*333d2b36SAndroid Build Coastguard Worker 192*333d2b36SAndroid Build Coastguard Worker // Save the zips to be merged into the intermediate zip. 193*333d2b36SAndroid Build Coastguard Worker info.mergeZips = android.NormalizePathsForTesting(bp.Inputs) 194*333d2b36SAndroid Build Coastguard Worker } 195*333d2b36SAndroid Build Coastguard Worker } 196*333d2b36SAndroid Build Coastguard Worker 197*333d2b36SAndroid Build Coastguard Worker if !seenBuildNumberFile { 198*333d2b36SAndroid Build Coastguard Worker panic(fmt.Sprintf("Every snapshot must include the %s file", BUILD_NUMBER_FILE)) 199*333d2b36SAndroid Build Coastguard Worker } 200*333d2b36SAndroid Build Coastguard Worker 201*333d2b36SAndroid Build Coastguard Worker info.copyRules = copyRules.String() 202*333d2b36SAndroid Build Coastguard Worker info.otherCopyRules = otherCopyRules.String() 203*333d2b36SAndroid Build Coastguard Worker 204*333d2b36SAndroid Build Coastguard Worker return info 205*333d2b36SAndroid Build Coastguard Worker} 206*333d2b36SAndroid Build Coastguard Worker 207*333d2b36SAndroid Build Coastguard Worker// The enum of different sdk snapshot tests performed by CheckSnapshot. 208*333d2b36SAndroid Build Coastguard Workertype snapshotTest int 209*333d2b36SAndroid Build Coastguard Worker 210*333d2b36SAndroid Build Coastguard Workerconst ( 211*333d2b36SAndroid Build Coastguard Worker // The enumeration of the different test configurations. 212*333d2b36SAndroid Build Coastguard Worker // A test with the snapshot/Android.bp file but without the original Android.bp file. 213*333d2b36SAndroid Build Coastguard Worker checkSnapshotWithoutSource snapshotTest = iota 214*333d2b36SAndroid Build Coastguard Worker 215*333d2b36SAndroid Build Coastguard Worker // A test with both the original source and the snapshot, with the source preferred. 216*333d2b36SAndroid Build Coastguard Worker checkSnapshotWithSourcePreferred 217*333d2b36SAndroid Build Coastguard Worker 218*333d2b36SAndroid Build Coastguard Worker // A test with both the original source and the snapshot, with the snapshot preferred. 219*333d2b36SAndroid Build Coastguard Worker checkSnapshotPreferredWithSource 220*333d2b36SAndroid Build Coastguard Worker 221*333d2b36SAndroid Build Coastguard Worker // The directory into which the snapshot will be 'unpacked'. 222*333d2b36SAndroid Build Coastguard Worker snapshotSubDir = "snapshot" 223*333d2b36SAndroid Build Coastguard Worker) 224*333d2b36SAndroid Build Coastguard Worker 225*333d2b36SAndroid Build Coastguard Worker// Check the snapshot build rules. 226*333d2b36SAndroid Build Coastguard Worker// 227*333d2b36SAndroid Build Coastguard Worker// Takes a list of functions which check different facets of the snapshot build rules. 228*333d2b36SAndroid Build Coastguard Worker// Allows each test to customize what is checked without duplicating lots of code 229*333d2b36SAndroid Build Coastguard Worker// or proliferating check methods of different flavors. 230*333d2b36SAndroid Build Coastguard Workerfunc CheckSnapshot(t *testing.T, result *android.TestResult, name string, dir string, checkers ...snapshotBuildInfoChecker) { 231*333d2b36SAndroid Build Coastguard Worker t.Helper() 232*333d2b36SAndroid Build Coastguard Worker 233*333d2b36SAndroid Build Coastguard Worker // The sdk CommonOS variant is always responsible for generating the snapshot. 234*333d2b36SAndroid Build Coastguard Worker variant := android.CommonOS.Name 235*333d2b36SAndroid Build Coastguard Worker 236*333d2b36SAndroid Build Coastguard Worker sdk := result.Module(name, variant).(*sdk) 237*333d2b36SAndroid Build Coastguard Worker 238*333d2b36SAndroid Build Coastguard Worker snapshotBuildInfo := getSdkSnapshotBuildInfo(t, result, sdk) 239*333d2b36SAndroid Build Coastguard Worker 240*333d2b36SAndroid Build Coastguard Worker // Check state of the snapshot build. 241*333d2b36SAndroid Build Coastguard Worker for _, checker := range checkers { 242*333d2b36SAndroid Build Coastguard Worker checker(snapshotBuildInfo) 243*333d2b36SAndroid Build Coastguard Worker } 244*333d2b36SAndroid Build Coastguard Worker 245*333d2b36SAndroid Build Coastguard Worker // Make sure that the generated zip file is in the correct place. 246*333d2b36SAndroid Build Coastguard Worker actual := snapshotBuildInfo.outputZip 247*333d2b36SAndroid Build Coastguard Worker if dir != "" { 248*333d2b36SAndroid Build Coastguard Worker dir = filepath.Clean(dir) + "/" 249*333d2b36SAndroid Build Coastguard Worker } 250*333d2b36SAndroid Build Coastguard Worker suffix := "-" + soongSdkSnapshotVersionCurrent 251*333d2b36SAndroid Build Coastguard Worker 252*333d2b36SAndroid Build Coastguard Worker expectedZipPath := fmt.Sprintf(".intermediates/%s%s/%s/%s%s.zip", dir, name, variant, name, suffix) 253*333d2b36SAndroid Build Coastguard Worker android.AssertStringEquals(t, "Snapshot zip file in wrong place", expectedZipPath, actual) 254*333d2b36SAndroid Build Coastguard Worker 255*333d2b36SAndroid Build Coastguard Worker // Populate a mock filesystem with the files that would have been copied by 256*333d2b36SAndroid Build Coastguard Worker // the rules. 257*333d2b36SAndroid Build Coastguard Worker fs := android.MockFS{} 258*333d2b36SAndroid Build Coastguard Worker for _, dest := range snapshotBuildInfo.snapshotContents { 259*333d2b36SAndroid Build Coastguard Worker fs[filepath.Join(snapshotSubDir, dest)] = nil 260*333d2b36SAndroid Build Coastguard Worker } 261*333d2b36SAndroid Build Coastguard Worker fs[filepath.Join(snapshotSubDir, "Android.bp")] = []byte(snapshotBuildInfo.androidBpContents) 262*333d2b36SAndroid Build Coastguard Worker 263*333d2b36SAndroid Build Coastguard Worker // If the generated snapshot builders not for the current release then it cannot be loaded by 264*333d2b36SAndroid Build Coastguard Worker // the current release. 265*333d2b36SAndroid Build Coastguard Worker if snapshotBuildInfo.targetBuildRelease != buildReleaseCurrent { 266*333d2b36SAndroid Build Coastguard Worker return 267*333d2b36SAndroid Build Coastguard Worker } 268*333d2b36SAndroid Build Coastguard Worker 269*333d2b36SAndroid Build Coastguard Worker // The preparers from the original source fixture. 270*333d2b36SAndroid Build Coastguard Worker sourcePreparers := result.Preparer() 271*333d2b36SAndroid Build Coastguard Worker 272*333d2b36SAndroid Build Coastguard Worker // Preparer to combine the snapshot and the source. 273*333d2b36SAndroid Build Coastguard Worker snapshotPreparer := android.GroupFixturePreparers(sourcePreparers, fs.AddToFixture()) 274*333d2b36SAndroid Build Coastguard Worker 275*333d2b36SAndroid Build Coastguard Worker var runSnapshotTestWithCheckers = func(t *testing.T, testConfig snapshotTest, extraPreparer android.FixturePreparer) { 276*333d2b36SAndroid Build Coastguard Worker t.Helper() 277*333d2b36SAndroid Build Coastguard Worker customization := snapshotBuildInfo.snapshotTestCustomization(testConfig) 278*333d2b36SAndroid Build Coastguard Worker customizedPreparers := android.GroupFixturePreparers(customization.preparers...) 279*333d2b36SAndroid Build Coastguard Worker 280*333d2b36SAndroid Build Coastguard Worker // TODO(b/183184375): Set Config.TestAllowNonExistentPaths = false to verify that all the 281*333d2b36SAndroid Build Coastguard Worker // files the snapshot needs are actually copied into the snapshot. 282*333d2b36SAndroid Build Coastguard Worker 283*333d2b36SAndroid Build Coastguard Worker // Run the snapshot with the snapshot preparer and the extra preparer, which must come after as 284*333d2b36SAndroid Build Coastguard Worker // it may need to modify parts of the MockFS populated by the snapshot preparer. 285*333d2b36SAndroid Build Coastguard Worker result := android.GroupFixturePreparers(snapshotPreparer, extraPreparer, customizedPreparers). 286*333d2b36SAndroid Build Coastguard Worker ExtendWithErrorHandler(customization.errorHandler). 287*333d2b36SAndroid Build Coastguard Worker RunTest(t) 288*333d2b36SAndroid Build Coastguard Worker 289*333d2b36SAndroid Build Coastguard Worker // Perform any additional checks the test need on the result of processing the snapshot. 290*333d2b36SAndroid Build Coastguard Worker for _, checker := range customization.checkers { 291*333d2b36SAndroid Build Coastguard Worker checker(t, result) 292*333d2b36SAndroid Build Coastguard Worker } 293*333d2b36SAndroid Build Coastguard Worker } 294*333d2b36SAndroid Build Coastguard Worker 295*333d2b36SAndroid Build Coastguard Worker t.Run("snapshot without source", func(t *testing.T) { 296*333d2b36SAndroid Build Coastguard Worker // Remove the source Android.bp file to make sure it works without. 297*333d2b36SAndroid Build Coastguard Worker removeSourceAndroidBp := android.FixtureModifyMockFS(func(fs android.MockFS) { 298*333d2b36SAndroid Build Coastguard Worker delete(fs, "Android.bp") 299*333d2b36SAndroid Build Coastguard Worker }) 300*333d2b36SAndroid Build Coastguard Worker 301*333d2b36SAndroid Build Coastguard Worker runSnapshotTestWithCheckers(t, checkSnapshotWithoutSource, removeSourceAndroidBp) 302*333d2b36SAndroid Build Coastguard Worker }) 303*333d2b36SAndroid Build Coastguard Worker 304*333d2b36SAndroid Build Coastguard Worker t.Run("snapshot with source preferred", func(t *testing.T) { 305*333d2b36SAndroid Build Coastguard Worker runSnapshotTestWithCheckers(t, checkSnapshotWithSourcePreferred, android.NullFixturePreparer) 306*333d2b36SAndroid Build Coastguard Worker }) 307*333d2b36SAndroid Build Coastguard Worker 308*333d2b36SAndroid Build Coastguard Worker t.Run("snapshot preferred with source", func(t *testing.T) { 309*333d2b36SAndroid Build Coastguard Worker // Replace the snapshot/Android.bp file with one where "prefer: false," has been replaced with 310*333d2b36SAndroid Build Coastguard Worker // "prefer: true," 311*333d2b36SAndroid Build Coastguard Worker preferPrebuilts := android.FixtureModifyMockFS(func(fs android.MockFS) { 312*333d2b36SAndroid Build Coastguard Worker snapshotBpFile := filepath.Join(snapshotSubDir, "Android.bp") 313*333d2b36SAndroid Build Coastguard Worker unpreferred := string(fs[snapshotBpFile]) 314*333d2b36SAndroid Build Coastguard Worker fs[snapshotBpFile] = []byte(strings.ReplaceAll(unpreferred, "prefer: false,", "prefer: true,")) 315*333d2b36SAndroid Build Coastguard Worker }) 316*333d2b36SAndroid Build Coastguard Worker 317*333d2b36SAndroid Build Coastguard Worker runSnapshotTestWithCheckers(t, checkSnapshotPreferredWithSource, preferPrebuilts) 318*333d2b36SAndroid Build Coastguard Worker }) 319*333d2b36SAndroid Build Coastguard Worker} 320*333d2b36SAndroid Build Coastguard Worker 321*333d2b36SAndroid Build Coastguard Workertype snapshotBuildInfoChecker func(info *snapshotBuildInfo) 322*333d2b36SAndroid Build Coastguard Worker 323*333d2b36SAndroid Build Coastguard Worker// Check that the snapshot's generated Android.bp is correct. 324*333d2b36SAndroid Build Coastguard Worker// 325*333d2b36SAndroid Build Coastguard Worker// Both the expected and actual string are both trimmed before comparing. 326*333d2b36SAndroid Build Coastguard Workerfunc checkAndroidBpContents(expected string) snapshotBuildInfoChecker { 327*333d2b36SAndroid Build Coastguard Worker return func(info *snapshotBuildInfo) { 328*333d2b36SAndroid Build Coastguard Worker info.t.Helper() 329*333d2b36SAndroid Build Coastguard Worker android.AssertTrimmedStringEquals(info.t, "Android.bp contents do not match", expected, info.androidBpContents) 330*333d2b36SAndroid Build Coastguard Worker } 331*333d2b36SAndroid Build Coastguard Worker} 332*333d2b36SAndroid Build Coastguard Worker 333*333d2b36SAndroid Build Coastguard Worker// Check that the snapshot's copy rules are correct. 334*333d2b36SAndroid Build Coastguard Worker// 335*333d2b36SAndroid Build Coastguard Worker// The copy rules are formatted as <src> -> <dest>, one per line and then compared 336*333d2b36SAndroid Build Coastguard Worker// to the supplied expected string. Both the expected and actual string are trimmed 337*333d2b36SAndroid Build Coastguard Worker// before comparing. 338*333d2b36SAndroid Build Coastguard Workerfunc checkAllCopyRules(expected string) snapshotBuildInfoChecker { 339*333d2b36SAndroid Build Coastguard Worker return func(info *snapshotBuildInfo) { 340*333d2b36SAndroid Build Coastguard Worker info.t.Helper() 341*333d2b36SAndroid Build Coastguard Worker android.AssertTrimmedStringEquals(info.t, "Incorrect copy rules", expected, info.copyRules) 342*333d2b36SAndroid Build Coastguard Worker } 343*333d2b36SAndroid Build Coastguard Worker} 344*333d2b36SAndroid Build Coastguard Worker 345*333d2b36SAndroid Build Coastguard Workerfunc checkAllOtherCopyRules(expected string) snapshotBuildInfoChecker { 346*333d2b36SAndroid Build Coastguard Worker return func(info *snapshotBuildInfo) { 347*333d2b36SAndroid Build Coastguard Worker info.t.Helper() 348*333d2b36SAndroid Build Coastguard Worker android.AssertTrimmedStringEquals(info.t, "Incorrect copy rules", expected, info.otherCopyRules) 349*333d2b36SAndroid Build Coastguard Worker } 350*333d2b36SAndroid Build Coastguard Worker} 351*333d2b36SAndroid Build Coastguard Worker 352*333d2b36SAndroid Build Coastguard Worker// Check that the specified paths match the list of zips to merge with the intermediate zip. 353*333d2b36SAndroid Build Coastguard Workerfunc checkMergeZips(expected ...string) snapshotBuildInfoChecker { 354*333d2b36SAndroid Build Coastguard Worker return func(info *snapshotBuildInfo) { 355*333d2b36SAndroid Build Coastguard Worker info.t.Helper() 356*333d2b36SAndroid Build Coastguard Worker if info.intermediateZip == "" { 357*333d2b36SAndroid Build Coastguard Worker info.t.Errorf("No intermediate zip file was created") 358*333d2b36SAndroid Build Coastguard Worker } 359*333d2b36SAndroid Build Coastguard Worker 360*333d2b36SAndroid Build Coastguard Worker android.AssertDeepEquals(info.t, "mismatching merge zip files", expected, info.mergeZips) 361*333d2b36SAndroid Build Coastguard Worker } 362*333d2b36SAndroid Build Coastguard Worker} 363*333d2b36SAndroid Build Coastguard Worker 364*333d2b36SAndroid Build Coastguard Worker// Check that the snapshot's info contents are ciorrect. 365*333d2b36SAndroid Build Coastguard Worker// 366*333d2b36SAndroid Build Coastguard Worker// Both the expected and actual string are both trimmed before comparing. 367*333d2b36SAndroid Build Coastguard Workerfunc checkInfoContents(config android.Config, expected string) snapshotBuildInfoChecker { 368*333d2b36SAndroid Build Coastguard Worker return func(info *snapshotBuildInfo) { 369*333d2b36SAndroid Build Coastguard Worker info.t.Helper() 370*333d2b36SAndroid Build Coastguard Worker android.AssertTrimmedStringEquals(info.t, "info contents do not match", 371*333d2b36SAndroid Build Coastguard Worker expected, android.StringRelativeToTop(config, info.infoContents)) 372*333d2b36SAndroid Build Coastguard Worker } 373*333d2b36SAndroid Build Coastguard Worker} 374*333d2b36SAndroid Build Coastguard Worker 375*333d2b36SAndroid Build Coastguard Workertype resultChecker func(t *testing.T, result *android.TestResult) 376*333d2b36SAndroid Build Coastguard Worker 377*333d2b36SAndroid Build Coastguard Worker// snapshotTestPreparer registers a preparer that will be used to customize the specified 378*333d2b36SAndroid Build Coastguard Worker// snapshotTest. 379*333d2b36SAndroid Build Coastguard Workerfunc snapshotTestPreparer(snapshotTest snapshotTest, preparer android.FixturePreparer) snapshotBuildInfoChecker { 380*333d2b36SAndroid Build Coastguard Worker return func(info *snapshotBuildInfo) { 381*333d2b36SAndroid Build Coastguard Worker customization := info.snapshotTestCustomization(snapshotTest) 382*333d2b36SAndroid Build Coastguard Worker customization.preparers = append(customization.preparers, preparer) 383*333d2b36SAndroid Build Coastguard Worker } 384*333d2b36SAndroid Build Coastguard Worker} 385*333d2b36SAndroid Build Coastguard Worker 386*333d2b36SAndroid Build Coastguard Worker// snapshotTestChecker registers a checker that will be run against the result of processing the 387*333d2b36SAndroid Build Coastguard Worker// generated snapshot for the specified snapshotTest. 388*333d2b36SAndroid Build Coastguard Workerfunc snapshotTestChecker(snapshotTest snapshotTest, checker resultChecker) snapshotBuildInfoChecker { 389*333d2b36SAndroid Build Coastguard Worker return func(info *snapshotBuildInfo) { 390*333d2b36SAndroid Build Coastguard Worker customization := info.snapshotTestCustomization(snapshotTest) 391*333d2b36SAndroid Build Coastguard Worker customization.checkers = append(customization.checkers, checker) 392*333d2b36SAndroid Build Coastguard Worker } 393*333d2b36SAndroid Build Coastguard Worker} 394*333d2b36SAndroid Build Coastguard Worker 395*333d2b36SAndroid Build Coastguard Worker// snapshotTestErrorHandler registers an error handler to use when processing the snapshot 396*333d2b36SAndroid Build Coastguard Worker// in the specific test case. 397*333d2b36SAndroid Build Coastguard Worker// 398*333d2b36SAndroid Build Coastguard Worker// Generally, the snapshot should work with all the test cases but some do not and just in case 399*333d2b36SAndroid Build Coastguard Worker// there are a lot of issues to resolve, or it will take a lot of time this is a 400*333d2b36SAndroid Build Coastguard Worker// get-out-of-jail-free card that allows progress to be made. 401*333d2b36SAndroid Build Coastguard Worker// 402*333d2b36SAndroid Build Coastguard Worker// deprecated: should only be used as a temporary workaround with an attached to do and bug. 403*333d2b36SAndroid Build Coastguard Workerfunc snapshotTestErrorHandler(snapshotTest snapshotTest, handler android.FixtureErrorHandler) snapshotBuildInfoChecker { 404*333d2b36SAndroid Build Coastguard Worker return func(info *snapshotBuildInfo) { 405*333d2b36SAndroid Build Coastguard Worker customization := info.snapshotTestCustomization(snapshotTest) 406*333d2b36SAndroid Build Coastguard Worker customization.errorHandler = handler 407*333d2b36SAndroid Build Coastguard Worker } 408*333d2b36SAndroid Build Coastguard Worker} 409*333d2b36SAndroid Build Coastguard Worker 410*333d2b36SAndroid Build Coastguard Worker// Encapsulates information provided by each test to customize a specific snapshotTest. 411*333d2b36SAndroid Build Coastguard Workertype snapshotTestCustomization struct { 412*333d2b36SAndroid Build Coastguard Worker // Preparers that are used to customize the test fixture before running the test. 413*333d2b36SAndroid Build Coastguard Worker preparers []android.FixturePreparer 414*333d2b36SAndroid Build Coastguard Worker 415*333d2b36SAndroid Build Coastguard Worker // Checkers that are run on the result of processing the preferred snapshot in a specific test 416*333d2b36SAndroid Build Coastguard Worker // case. 417*333d2b36SAndroid Build Coastguard Worker checkers []resultChecker 418*333d2b36SAndroid Build Coastguard Worker 419*333d2b36SAndroid Build Coastguard Worker // Specify an error handler for when processing a specific test case. 420*333d2b36SAndroid Build Coastguard Worker // 421*333d2b36SAndroid Build Coastguard Worker // In some cases the generated snapshot cannot be used in a test configuration. Those cases are 422*333d2b36SAndroid Build Coastguard Worker // invariably bugs that need to be resolved but sometimes that can take a while. This provides a 423*333d2b36SAndroid Build Coastguard Worker // mechanism to temporarily ignore that error. 424*333d2b36SAndroid Build Coastguard Worker errorHandler android.FixtureErrorHandler 425*333d2b36SAndroid Build Coastguard Worker} 426*333d2b36SAndroid Build Coastguard Worker 427*333d2b36SAndroid Build Coastguard Worker// Encapsulates information about the snapshot build structure in order to insulate tests from 428*333d2b36SAndroid Build Coastguard Worker// knowing too much about internal structures. 429*333d2b36SAndroid Build Coastguard Worker// 430*333d2b36SAndroid Build Coastguard Worker// All source/input paths are relative either the build directory. All dest/output paths are 431*333d2b36SAndroid Build Coastguard Worker// relative to the snapshot root directory. 432*333d2b36SAndroid Build Coastguard Workertype snapshotBuildInfo struct { 433*333d2b36SAndroid Build Coastguard Worker t *testing.T 434*333d2b36SAndroid Build Coastguard Worker 435*333d2b36SAndroid Build Coastguard Worker // The result from RunTest() 436*333d2b36SAndroid Build Coastguard Worker r *android.TestResult 437*333d2b36SAndroid Build Coastguard Worker 438*333d2b36SAndroid Build Coastguard Worker // The contents of the generated Android.bp file 439*333d2b36SAndroid Build Coastguard Worker androidBpContents string 440*333d2b36SAndroid Build Coastguard Worker 441*333d2b36SAndroid Build Coastguard Worker // The contents of the info file. 442*333d2b36SAndroid Build Coastguard Worker infoContents string 443*333d2b36SAndroid Build Coastguard Worker 444*333d2b36SAndroid Build Coastguard Worker // The paths, relative to the snapshot root, of all files and directories copied into the 445*333d2b36SAndroid Build Coastguard Worker // snapshot. 446*333d2b36SAndroid Build Coastguard Worker snapshotContents []string 447*333d2b36SAndroid Build Coastguard Worker 448*333d2b36SAndroid Build Coastguard Worker // A formatted representation of the src/dest pairs for a snapshot, one pair per line, 449*333d2b36SAndroid Build Coastguard Worker // of the format src -> dest 450*333d2b36SAndroid Build Coastguard Worker copyRules string 451*333d2b36SAndroid Build Coastguard Worker 452*333d2b36SAndroid Build Coastguard Worker // A formatted representation of the src/dest pairs for files not in a snapshot, one pair 453*333d2b36SAndroid Build Coastguard Worker // per line, of the format src -> dest 454*333d2b36SAndroid Build Coastguard Worker otherCopyRules string 455*333d2b36SAndroid Build Coastguard Worker 456*333d2b36SAndroid Build Coastguard Worker // The path to the intermediate zip, which is a zip created from the source files copied 457*333d2b36SAndroid Build Coastguard Worker // into the snapshot directory and which will be merged with other zips to form the final output. 458*333d2b36SAndroid Build Coastguard Worker // Is am empty string if there is no intermediate zip because there are no zips to merge in. 459*333d2b36SAndroid Build Coastguard Worker intermediateZip string 460*333d2b36SAndroid Build Coastguard Worker 461*333d2b36SAndroid Build Coastguard Worker // The paths to the zips to merge into the output zip, does not include the intermediate 462*333d2b36SAndroid Build Coastguard Worker // zip. 463*333d2b36SAndroid Build Coastguard Worker mergeZips []string 464*333d2b36SAndroid Build Coastguard Worker 465*333d2b36SAndroid Build Coastguard Worker // The final output zip. 466*333d2b36SAndroid Build Coastguard Worker outputZip string 467*333d2b36SAndroid Build Coastguard Worker 468*333d2b36SAndroid Build Coastguard Worker // The target build release. 469*333d2b36SAndroid Build Coastguard Worker targetBuildRelease *buildRelease 470*333d2b36SAndroid Build Coastguard Worker 471*333d2b36SAndroid Build Coastguard Worker // The test specific customizations for each snapshot test. 472*333d2b36SAndroid Build Coastguard Worker snapshotTestCustomizations map[snapshotTest]*snapshotTestCustomization 473*333d2b36SAndroid Build Coastguard Worker} 474*333d2b36SAndroid Build Coastguard Worker 475*333d2b36SAndroid Build Coastguard Worker// snapshotTestCustomization gets the test specific customization for the specified snapshotTest. 476*333d2b36SAndroid Build Coastguard Worker// 477*333d2b36SAndroid Build Coastguard Worker// If no customization was created previously then it creates a default customization. 478*333d2b36SAndroid Build Coastguard Workerfunc (i *snapshotBuildInfo) snapshotTestCustomization(snapshotTest snapshotTest) *snapshotTestCustomization { 479*333d2b36SAndroid Build Coastguard Worker customization := i.snapshotTestCustomizations[snapshotTest] 480*333d2b36SAndroid Build Coastguard Worker if customization == nil { 481*333d2b36SAndroid Build Coastguard Worker customization = &snapshotTestCustomization{ 482*333d2b36SAndroid Build Coastguard Worker errorHandler: android.FixtureExpectsNoErrors, 483*333d2b36SAndroid Build Coastguard Worker } 484*333d2b36SAndroid Build Coastguard Worker i.snapshotTestCustomizations[snapshotTest] = customization 485*333d2b36SAndroid Build Coastguard Worker } 486*333d2b36SAndroid Build Coastguard Worker return customization 487*333d2b36SAndroid Build Coastguard Worker} 488