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 "android/soong/java" 20 "io/ioutil" 21 "os" 22 "strings" 23 "testing" 24) 25 26var buildDir string 27 28func TestBpContainsTestHostPropsThrowsError(t *testing.T) { 29 createContextAndConfigExpectingErrors(t, ` 30 csuite_test { 31 name: "plan_name", 32 test_config_template: "config_template.xml", 33 data_native_bins: "bin" 34 } 35 `, 36 "unrecognized property", 37 ) 38} 39 40func TestBpContainsManifestThrowsError(t *testing.T) { 41 createContextAndConfigExpectingErrors(t, ` 42 csuite_test { 43 name: "plan_name", 44 test_config_template: "config_template.xml", 45 test_config: "AndroidTest.xml" 46 } 47 `, 48 "unrecognized property", 49 ) 50} 51 52func TestBpMissingNameThrowsError(t *testing.T) { 53 createContextAndConfigExpectingErrors(t, ` 54 csuite_test { 55 test_config_template: "config_template.xml" 56 } 57 `, 58 `'name' is missing`, 59 ) 60} 61 62func TestBpMissingTemplatePathThrowsError(t *testing.T) { 63 createContextAndConfigExpectingErrors(t, ` 64 csuite_test { 65 name: "plan_name", 66 } 67 `, 68 `'test_config_template' is missing`, 69 ) 70} 71 72func TestBpTemplatePathUnexpectedFileExtensionThrowsError(t *testing.T) { 73 createContextAndConfigExpectingErrors(t, ` 74 csuite_test { 75 name: "plan_name", 76 test_config_template: "config_template.xml.template" 77 } 78 `, 79 `Config template path should ends with .xml`, 80 ) 81} 82 83func TestBpExtraTemplateUnexpectedFileExtensionThrowsError(t *testing.T) { 84 createContextAndConfigExpectingErrors(t, ` 85 csuite_test { 86 name: "plan_name", 87 test_config_template: "config_template.xml", 88 extra_test_config_templates: ["another.xml.template"] 89 } 90 `, 91 `Config template path should ends with .xml`, 92 ) 93} 94 95func TestBpValidExtraTemplateDoesNotThrowError(t *testing.T) { 96 createContextAndConfig(t, ` 97 csuite_test { 98 name: "plan_name", 99 test_config_template: "config_template.xml", 100 extra_test_config_templates: ["another.xml"] 101 } 102 `) 103} 104 105func TestValidBpMissingPlanIncludeDoesNotThrowError(t *testing.T) { 106 createContextAndConfig(t, ` 107 csuite_test { 108 name: "plan_name", 109 test_config_template: "config_template.xml" 110 } 111 `) 112} 113 114func TestValidBpMissingPlanIncludeGeneratesPlanXmlWithoutPlaceholders(t *testing.T) { 115 ctx, config := createContextAndConfig(t, ` 116 csuite_test { 117 name: "plan_name", 118 test_config_template: "config_template.xml" 119 } 120 `) 121 122 module := ctx.ModuleForTests("plan_name", config.BuildOS.String()+"_common") 123 content := android.ContentFromFileRuleForTests(t, ctx, module.Output("config/plan_name.xml")) 124 if strings.Contains(content, "{") || strings.Contains(content, "}") { 125 t.Errorf("The generated plan name contains a placeholder: %s", content) 126 } 127} 128 129func TestGeneratedTestPlanContainsPlanName(t *testing.T) { 130 ctx, config := createContextAndConfig(t, ` 131 csuite_test { 132 name: "plan_name", 133 test_config_template: "config_template.xml" 134 } 135 `) 136 137 module := ctx.ModuleForTests("plan_name", config.BuildOS.String()+"_common") 138 content := android.ContentFromFileRuleForTests(t, ctx, module.Output("config/plan_name.xml")) 139 if !strings.Contains(content, "plan_name") { 140 t.Errorf("The plan name is missing from the generated plan: %s", content) 141 } 142} 143 144func TestGeneratedTestPlanContainsTemplatePath(t *testing.T) { 145 ctx, config := createContextAndConfig(t, ` 146 csuite_test { 147 name: "plan_name", 148 test_config_template: "config_template.xml" 149 } 150 `) 151 152 module := ctx.ModuleForTests("plan_name", config.BuildOS.String()+"_common") 153 content := android.ContentFromFileRuleForTests(t, ctx, module.Output("config/plan_name.xml")) 154 if !strings.Contains(content, "config/plan_name/config_template.xml.template") { 155 t.Errorf("The template path is missing from the generated plan: %s", content) 156 } 157} 158 159func TestGeneratedTestPlanContainsExtraTemplatePath(t *testing.T) { 160 ctx, config := createContextAndConfig(t, ` 161 csuite_test { 162 name: "plan_name", 163 test_config_template: "config_template.xml", 164 extra_test_config_templates: ["extra.xml"] 165 } 166 `) 167 168 module := ctx.ModuleForTests("plan_name", config.BuildOS.String()+"_common") 169 content := android.ContentFromFileRuleForTests(t, ctx, module.Output("config/plan_name.xml")) 170 if !strings.Contains(content, "config/plan_name/extra.xml.template") { 171 t.Errorf("The extra template path is missing from the generated plan: %s", content) 172 } 173 if !strings.Contains(content, "extra-templates") { 174 t.Errorf("The extra-templates param is missing from the generated plan: %s", content) 175 } 176} 177 178func TestGeneratedTestPlanDoesNotContainExtraTemplatePath(t *testing.T) { 179 ctx, config := createContextAndConfig(t, ` 180 csuite_test { 181 name: "plan_name", 182 test_config_template: "config_template.xml" 183 } 184 `) 185 186 module := ctx.ModuleForTests("plan_name", config.BuildOS.String()+"_common") 187 content := android.ContentFromFileRuleForTests(t, ctx, module.Output("config/plan_name.xml")) 188 if strings.Contains(content, "extra-templates") { 189 t.Errorf("The extra-templates param should not be included in the generated plan: %s", content) 190 } 191} 192 193func TestTemplateFileCopyRuleExists(t *testing.T) { 194 ctx, config := createContextAndConfig(t, ` 195 csuite_test { 196 name: "plan_name", 197 test_config_template: "config_template.xml" 198 } 199 `) 200 201 params := ctx.ModuleForTests("plan_name", config.BuildOS.String()+"_common").Rule("CSuite") 202 assertFileCopyRuleExists(t, params, "config_template.xml", "config/plan_name/config_template.xml.template") 203} 204 205func TestExtraTemplateFileCopyRuleExists(t *testing.T) { 206 ctx, config := createContextAndConfig(t, ` 207 csuite_test { 208 name: "plan_name", 209 test_config_template: "config_template.xml", 210 extra_test_config_templates: ["extra.xml"] 211 } 212 `) 213 214 params := ctx.ModuleForTests("plan_name", config.BuildOS.String()+"_common").Rule("CSuite") 215 assertFileCopyRuleExists(t, params, "config_template.xml", "config/plan_name/extra.xml.template") 216} 217 218func TestGeneratedTestPlanContainsPlanInclude(t *testing.T) { 219 ctx, config := createContextAndConfig(t, ` 220 csuite_test { 221 name: "plan_name", 222 test_config_template: "config_template.xml", 223 test_plan_include: "include.xml" 224 } 225 `) 226 227 module := ctx.ModuleForTests("plan_name", config.BuildOS.String()+"_common") 228 content := android.ContentFromFileRuleForTests(t, ctx, module.Output("config/plan_name.xml")) 229 if !strings.Contains(content, `"includes/plan_name.xml"`) { 230 t.Errorf("The plan include path is missing from the generated plan: %s", content) 231 } 232} 233 234func TestPlanIncludeFileCopyRuleExists(t *testing.T) { 235 ctx, config := createContextAndConfig(t, ` 236 csuite_test { 237 name: "plan_name", 238 test_config_template: "config_template.xml", 239 test_plan_include: "include.xml" 240 } 241 `) 242 243 params := ctx.ModuleForTests("plan_name", config.BuildOS.String()+"_common").Rule("CSuite") 244 assertFileCopyRuleExists(t, params, "include.xml", "config/includes/plan_name.xml") 245} 246 247func TestMain(m *testing.M) { 248 run := func() int { 249 setUp() 250 defer tearDown() 251 252 return m.Run() 253 } 254 255 os.Exit(run()) 256} 257 258func assertFileCopyRuleExists(t *testing.T, params android.TestingBuildParams, src string, dst string) { 259 assertPathsContains(t, getAllInputPaths(params), src) 260 assertWritablePathsContainsRel(t, getAllOutputPaths(params), dst) 261 if !strings.HasPrefix(params.RuleParams.Command, "cp") { 262 t.Errorf("'cp' command is missing.") 263 } 264} 265 266func assertPathsContains(t *testing.T, paths android.Paths, path string) { 267 for _, p := range paths { 268 if p.String() == path { 269 return 270 } 271 } 272 t.Errorf("Cannot find expected path %s", path) 273} 274 275func assertWritablePathsContainsRel(t *testing.T, paths android.WritablePaths, relPath string) { 276 for _, path := range paths { 277 if path.Rel() == relPath { 278 return 279 } 280 } 281 t.Errorf("Cannot find expected relative path %s", relPath) 282} 283 284func getAllOutputPaths(params android.TestingBuildParams) android.WritablePaths { 285 var paths []android.WritablePath 286 if params.Output != nil { 287 paths = append(paths, params.Output) 288 } 289 if params.ImplicitOutput != nil { 290 paths = append(paths, params.ImplicitOutput) 291 } 292 paths = append(paths, params.Outputs...) 293 paths = append(paths, params.ImplicitOutputs...) 294 295 return paths 296} 297 298func getAllInputPaths(params android.TestingBuildParams) android.Paths { 299 var paths []android.Path 300 if params.Input != nil { 301 paths = append(paths, params.Input) 302 } 303 if params.Implicit != nil { 304 paths = append(paths, params.Implicit) 305 } 306 paths = append(paths, params.Inputs...) 307 paths = append(paths, params.Implicits...) 308 309 return paths 310} 311 312func setUp() { 313 var err error 314 buildDir, err = ioutil.TempDir("", "soong_csuite_test") 315 if err != nil { 316 panic(err) 317 } 318} 319 320func tearDown() { 321 os.RemoveAll(buildDir) 322} 323 324func createContextAndConfig(t *testing.T, bp string) (*android.TestContext, android.Config) { 325 return createContextAndConfigExpectingErrors(t, bp, "") 326} 327 328func createContextAndConfigExpectingErrors(t *testing.T, bp string, error string) (*android.TestContext, android.Config) { 329 t.Helper() 330 331 testPreparer := android.GroupFixturePreparers( 332 java.PrepareForTestWithJavaDefaultModules, 333 android.FixtureRegisterWithContext(func(ctx android.RegistrationContext) { 334 ctx.RegisterModuleType("csuite_test", CSuiteTestFactory) 335 }), 336 android.FixtureWithRootAndroidBp(bp), 337 ) 338 339 if error != "" { 340 testPreparer = testPreparer.ExtendWithErrorHandler(android.FixtureExpectsOneErrorPattern(error)) 341 } 342 343 result := testPreparer.RunTest(t) 344 345 return result.TestContext, result.Config 346} 347