1// Copyright 2020 Google Inc. All rights reserved. 2// 3// Licensed under the Apache License, Version 2.0 (the "License"); 4// you may not use this file except in compliance with the License. 5// You may obtain a copy of the License at 6// 7// http://www.apache.org/licenses/LICENSE-2.0 8// 9// Unless required by applicable law or agreed to in writing, software 10// distributed under the License is distributed on an "AS IS" BASIS, 11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12// See the License for the specific language governing permissions and 13// limitations under the License. 14 15package csuite 16 17import ( 18 "android/soong/android" 19 "io/ioutil" 20 "os" 21 "strings" 22 "testing" 23) 24 25var buildDir string 26 27func TestBpContainsTestHostPropsThrowsError(t *testing.T) { 28 ctx, _ := createContextAndConfig(t, ` 29 csuite_test { 30 name: "plan_name", 31 test_config_template: "test_config.xml.template", 32 data_native_bins: "bin" 33 } 34 `) 35 36 _, errs := ctx.ParseBlueprintsFiles("Android.bp") 37 38 android.FailIfNoMatchingErrors(t, `unrecognized property`, errs) 39} 40 41func TestBpContainsManifestThrowsError(t *testing.T) { 42 ctx, _ := createContextAndConfig(t, ` 43 csuite_test { 44 name: "plan_name", 45 test_config_template: "test_config.xml.template", 46 test_config: "AndroidTest.xml" 47 } 48 `) 49 50 _, errs := ctx.ParseBlueprintsFiles("Android.bp") 51 52 android.FailIfNoMatchingErrors(t, `unrecognized property`, errs) 53} 54 55func TestBpMissingNameThrowsError(t *testing.T) { 56 ctx, _ := createContextAndConfig(t, ` 57 csuite_test { 58 test_config_template: "test_config.xml.template" 59 } 60 `) 61 62 _, errs := ctx.ParseBlueprintsFiles("Android.bp") 63 64 android.FailIfNoMatchingErrors(t, `'name' is missing`, errs) 65} 66 67func TestBpMissingTemplatePathThrowsError(t *testing.T) { 68 ctx, config := createContextAndConfig(t, ` 69 csuite_test { 70 name: "plan_name", 71 } 72 `) 73 74 ctx.ParseBlueprintsFiles("Android.bp") 75 _, errs := ctx.PrepareBuildActions(config) 76 77 android.FailIfNoMatchingErrors(t, `'test_config_template' is missing`, errs) 78} 79 80func TestValidBpMissingPlanIncludeDoesNotThrowError(t *testing.T) { 81 ctx, config := createContextAndConfig(t, ` 82 csuite_test { 83 name: "plan_name", 84 test_config_template: "test_config.xml.template" 85 } 86 `) 87 88 parseBpAndBuild(t, ctx, config) 89} 90 91func TestValidBpMissingPlanIncludeGeneratesPlanXmlWithoutPlaceholders(t *testing.T) { 92 ctx, config := createContextAndConfig(t, ` 93 csuite_test { 94 name: "plan_name", 95 test_config_template: "test_config.xml.template" 96 } 97 `) 98 99 parseBpAndBuild(t, ctx, config) 100 101 module := ctx.ModuleForTests("plan_name", android.BuildOs.String()+"_common") 102 content := android.ContentFromFileRuleForTests(t, module.Output("config/plan_name.xml")) 103 if strings.Contains(content, "{") || strings.Contains(content, "}") { 104 t.Errorf("The generated plan name contains a placeholder: %s", content) 105 } 106} 107 108func TestGeneratedTestPlanContainsPlanName(t *testing.T) { 109 ctx, config := createContextAndConfig(t, ` 110 csuite_test { 111 name: "plan_name", 112 test_config_template: "test_config.xml.template" 113 } 114 `) 115 116 parseBpAndBuild(t, ctx, config) 117 118 module := ctx.ModuleForTests("plan_name", android.BuildOs.String()+"_common") 119 content := android.ContentFromFileRuleForTests(t, module.Output("config/plan_name.xml")) 120 if !strings.Contains(content, "plan_name") { 121 t.Errorf("The plan name is missing from the generated plan: %s", content) 122 } 123} 124 125func TestGeneratedTestPlanContainsTemplatePath(t *testing.T) { 126 ctx, config := createContextAndConfig(t, ` 127 csuite_test { 128 name: "plan_name", 129 test_config_template: "test_config.xml.template" 130 } 131 `) 132 133 parseBpAndBuild(t, ctx, config) 134 135 module := ctx.ModuleForTests("plan_name", android.BuildOs.String()+"_common") 136 content := android.ContentFromFileRuleForTests(t, module.Output("config/plan_name.xml")) 137 if !strings.Contains(content, "config/plan_name.xml.template") { 138 t.Errorf("The template path is missing from the generated plan: %s", content) 139 } 140} 141 142func TestTemplateFileCopyRuleExists(t *testing.T) { 143 ctx, config := createContextAndConfig(t, ` 144 csuite_test { 145 name: "plan_name", 146 test_config_template: "test_config.xml.template" 147 } 148 `) 149 150 parseBpAndBuild(t, ctx, config) 151 152 params := ctx.ModuleForTests("plan_name", android.BuildOs.String()+"_common").Rule("CSuite") 153 assertFileCopyRuleExists(t, params, "test_config.xml.template", "config/plan_name.xml.template") 154} 155 156func TestGeneratedTestPlanContainsPlanInclude(t *testing.T) { 157 ctx, config := createContextAndConfig(t, ` 158 csuite_test { 159 name: "plan_name", 160 test_config_template: "test_config.xml.template", 161 test_plan_include: "include.xml" 162 } 163 `) 164 165 parseBpAndBuild(t, ctx, config) 166 167 module := ctx.ModuleForTests("plan_name", android.BuildOs.String()+"_common") 168 content := android.ContentFromFileRuleForTests(t, module.Output("config/plan_name.xml")) 169 if !strings.Contains(content, `"includes/plan_name.xml"`) { 170 t.Errorf("The plan include path is missing from the generated plan: %s", content) 171 } 172} 173 174func TestPlanIncludeFileCopyRuleExists(t *testing.T) { 175 ctx, config := createContextAndConfig(t, ` 176 csuite_test { 177 name: "plan_name", 178 test_config_template: "test_config.xml.template", 179 test_plan_include: "include.xml" 180 } 181 `) 182 183 parseBpAndBuild(t, ctx, config) 184 185 params := ctx.ModuleForTests("plan_name", android.BuildOs.String()+"_common").Rule("CSuite") 186 assertFileCopyRuleExists(t, params, "include.xml", "config/includes/plan_name.xml") 187} 188 189func TestMain(m *testing.M) { 190 run := func() int { 191 setUp() 192 defer tearDown() 193 194 return m.Run() 195 } 196 197 os.Exit(run()) 198} 199 200func parseBpAndBuild(t *testing.T, ctx *android.TestContext, config android.Config) { 201 _, parsingErrs := ctx.ParseBlueprintsFiles("Android.bp") 202 _, buildErrs := ctx.PrepareBuildActions(config) 203 204 android.FailIfErrored(t, parsingErrs) 205 android.FailIfErrored(t, buildErrs) 206} 207 208func assertFileCopyRuleExists(t *testing.T, params android.TestingBuildParams, src string, dst string) { 209 assertPathsContains(t, getAllInputPaths(params), src) 210 assertWritablePathsContainsRel(t, getAllOutputPaths(params), dst) 211 if !strings.HasPrefix(params.RuleParams.Command, "cp") { 212 t.Errorf("'cp' command is missing.") 213 } 214} 215 216func assertPathsContains(t *testing.T, paths android.Paths, path string) { 217 for _, p := range paths { 218 if p.String() == path { 219 return 220 } 221 } 222 t.Errorf("Cannot find expected path %s", path) 223} 224 225func assertWritablePathsContainsRel(t *testing.T, paths android.WritablePaths, relPath string) { 226 for _, path := range paths { 227 if path.Rel() == relPath { 228 return 229 } 230 } 231 t.Errorf("Cannot find expected relative path %s", relPath) 232} 233 234func getAllOutputPaths(params android.TestingBuildParams) android.WritablePaths { 235 var paths []android.WritablePath 236 if params.Output != nil { 237 paths = append(paths, params.Output) 238 } 239 if params.ImplicitOutput != nil { 240 paths = append(paths, params.ImplicitOutput) 241 } 242 if params.SymlinkOutput != nil { 243 paths = append(paths, params.SymlinkOutput) 244 } 245 paths = append(paths, params.Outputs...) 246 paths = append(paths, params.ImplicitOutputs...) 247 paths = append(paths, params.SymlinkOutputs...) 248 249 return paths 250} 251 252func getAllInputPaths(params android.TestingBuildParams) android.Paths { 253 var paths []android.Path 254 if params.Input != nil { 255 paths = append(paths, params.Input) 256 } 257 if params.Implicit != nil { 258 paths = append(paths, params.Implicit) 259 } 260 paths = append(paths, params.Inputs...) 261 paths = append(paths, params.Implicits...) 262 263 return paths 264} 265 266func setUp() { 267 var err error 268 buildDir, err = ioutil.TempDir("", "soong_csuite_test") 269 if err != nil { 270 panic(err) 271 } 272} 273 274func tearDown() { 275 os.RemoveAll(buildDir) 276} 277 278func createContextAndConfig(t *testing.T, bp string) (*android.TestContext, android.Config) { 279 t.Helper() 280 config := android.TestArchConfig(buildDir, nil, bp, nil) 281 ctx := android.NewTestArchContext(config) 282 ctx.RegisterModuleType("csuite_test", CSuiteTestFactory) 283 ctx.Register() 284 285 return ctx, config 286} 287