1// Copyright 2018 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 etc 16 17import ( 18 "io/ioutil" 19 "os" 20 "path/filepath" 21 "reflect" 22 "testing" 23 24 "android/soong/android" 25) 26 27var buildDir string 28 29func setUp() { 30 var err error 31 buildDir, err = ioutil.TempDir("", "soong_etc_test") 32 if err != nil { 33 panic(err) 34 } 35} 36 37func tearDown() { 38 os.RemoveAll(buildDir) 39} 40 41func TestMain(m *testing.M) { 42 run := func() int { 43 setUp() 44 defer tearDown() 45 46 return m.Run() 47 } 48 49 os.Exit(run()) 50} 51 52func testPrebuiltEtcContext(t *testing.T, bp string) (*android.TestContext, android.Config) { 53 fs := map[string][]byte{ 54 "foo.conf": nil, 55 "bar.conf": nil, 56 "baz.conf": nil, 57 } 58 59 config := android.TestArchConfig(buildDir, nil, bp, fs) 60 61 ctx := android.NewTestArchContext() 62 ctx.RegisterModuleType("prebuilt_etc", PrebuiltEtcFactory) 63 ctx.RegisterModuleType("prebuilt_etc_host", PrebuiltEtcHostFactory) 64 ctx.RegisterModuleType("prebuilt_usr_share", PrebuiltUserShareFactory) 65 ctx.RegisterModuleType("prebuilt_usr_share_host", PrebuiltUserShareHostFactory) 66 ctx.RegisterModuleType("prebuilt_font", PrebuiltFontFactory) 67 ctx.RegisterModuleType("prebuilt_firmware", PrebuiltFirmwareFactory) 68 ctx.RegisterModuleType("prebuilt_dsp", PrebuiltDSPFactory) 69 ctx.Register(config) 70 71 return ctx, config 72} 73 74func testPrebuiltEtc(t *testing.T, bp string) (*android.TestContext, android.Config) { 75 t.Helper() 76 77 ctx, config := testPrebuiltEtcContext(t, bp) 78 _, errs := ctx.ParseFileList(".", []string{"Android.bp"}) 79 android.FailIfErrored(t, errs) 80 _, errs = ctx.PrepareBuildActions(config) 81 android.FailIfErrored(t, errs) 82 83 return ctx, config 84} 85 86func testPrebuiltEtcError(t *testing.T, pattern, bp string) { 87 t.Helper() 88 89 ctx, config := testPrebuiltEtcContext(t, bp) 90 _, errs := ctx.ParseFileList(".", []string{"Android.bp"}) 91 if len(errs) > 0 { 92 android.FailIfNoMatchingErrors(t, pattern, errs) 93 return 94 } 95 96 _, errs = ctx.PrepareBuildActions(config) 97 if len(errs) > 0 { 98 android.FailIfNoMatchingErrors(t, pattern, errs) 99 return 100 } 101 102 t.Fatalf("missing expected error %q (0 errors are returned)", pattern) 103} 104func TestPrebuiltEtcVariants(t *testing.T) { 105 ctx, _ := testPrebuiltEtc(t, ` 106 prebuilt_etc { 107 name: "foo.conf", 108 src: "foo.conf", 109 } 110 prebuilt_etc { 111 name: "bar.conf", 112 src: "bar.conf", 113 recovery_available: true, 114 } 115 prebuilt_etc { 116 name: "baz.conf", 117 src: "baz.conf", 118 recovery: true, 119 } 120 `) 121 122 foo_variants := ctx.ModuleVariantsForTests("foo.conf") 123 if len(foo_variants) != 1 { 124 t.Errorf("expected 1, got %#v", foo_variants) 125 } 126 127 bar_variants := ctx.ModuleVariantsForTests("bar.conf") 128 if len(bar_variants) != 2 { 129 t.Errorf("expected 2, got %#v", bar_variants) 130 } 131 132 baz_variants := ctx.ModuleVariantsForTests("baz.conf") 133 if len(baz_variants) != 1 { 134 t.Errorf("expected 1, got %#v", bar_variants) 135 } 136} 137 138func TestPrebuiltEtcOutputPath(t *testing.T) { 139 ctx, _ := testPrebuiltEtc(t, ` 140 prebuilt_etc { 141 name: "foo.conf", 142 src: "foo.conf", 143 filename: "foo.installed.conf", 144 } 145 `) 146 147 p := ctx.ModuleForTests("foo.conf", "android_arm64_armv8-a").Module().(*PrebuiltEtc) 148 if p.outputFilePath.Base() != "foo.installed.conf" { 149 t.Errorf("expected foo.installed.conf, got %q", p.outputFilePath.Base()) 150 } 151} 152 153func TestPrebuiltEtcGlob(t *testing.T) { 154 ctx, _ := testPrebuiltEtc(t, ` 155 prebuilt_etc { 156 name: "my_foo", 157 src: "foo.*", 158 } 159 prebuilt_etc { 160 name: "my_bar", 161 src: "bar.*", 162 filename_from_src: true, 163 } 164 `) 165 166 p := ctx.ModuleForTests("my_foo", "android_arm64_armv8-a").Module().(*PrebuiltEtc) 167 if p.outputFilePath.Base() != "my_foo" { 168 t.Errorf("expected my_foo, got %q", p.outputFilePath.Base()) 169 } 170 171 p = ctx.ModuleForTests("my_bar", "android_arm64_armv8-a").Module().(*PrebuiltEtc) 172 if p.outputFilePath.Base() != "bar.conf" { 173 t.Errorf("expected bar.conf, got %q", p.outputFilePath.Base()) 174 } 175} 176 177func TestPrebuiltEtcAndroidMk(t *testing.T) { 178 ctx, config := testPrebuiltEtc(t, ` 179 prebuilt_etc { 180 name: "foo", 181 src: "foo.conf", 182 owner: "abc", 183 filename_from_src: true, 184 required: ["modA", "moduleB"], 185 host_required: ["hostModA", "hostModB"], 186 target_required: ["targetModA"], 187 } 188 `) 189 190 expected := map[string][]string{ 191 "LOCAL_MODULE": {"foo"}, 192 "LOCAL_MODULE_CLASS": {"ETC"}, 193 "LOCAL_MODULE_OWNER": {"abc"}, 194 "LOCAL_INSTALLED_MODULE_STEM": {"foo.conf"}, 195 "LOCAL_REQUIRED_MODULES": {"modA", "moduleB"}, 196 "LOCAL_HOST_REQUIRED_MODULES": {"hostModA", "hostModB"}, 197 "LOCAL_TARGET_REQUIRED_MODULES": {"targetModA"}, 198 } 199 200 mod := ctx.ModuleForTests("foo", "android_arm64_armv8-a").Module().(*PrebuiltEtc) 201 entries := android.AndroidMkEntriesForTest(t, config, "", mod)[0] 202 for k, expectedValue := range expected { 203 if value, ok := entries.EntryMap[k]; ok { 204 if !reflect.DeepEqual(value, expectedValue) { 205 t.Errorf("Incorrect %s '%s', expected '%s'", k, value, expectedValue) 206 } 207 } else { 208 t.Errorf("No %s defined, saw %q", k, entries.EntryMap) 209 } 210 } 211} 212 213func TestPrebuiltEtcRelativeInstallPathInstallDirPath(t *testing.T) { 214 ctx, _ := testPrebuiltEtc(t, ` 215 prebuilt_etc { 216 name: "foo.conf", 217 src: "foo.conf", 218 relative_install_path: "bar", 219 } 220 `) 221 222 p := ctx.ModuleForTests("foo.conf", "android_arm64_armv8-a").Module().(*PrebuiltEtc) 223 expected := buildDir + "/target/product/test_device/system/etc/bar" 224 if p.installDirPath.String() != expected { 225 t.Errorf("expected %q, got %q", expected, p.installDirPath.String()) 226 } 227} 228 229func TestPrebuiltEtcCannotSetRelativeInstallPathAndSubDir(t *testing.T) { 230 testPrebuiltEtcError(t, "relative_install_path is set. Cannot set sub_dir", ` 231 prebuilt_etc { 232 name: "foo.conf", 233 src: "foo.conf", 234 sub_dir: "bar", 235 relative_install_path: "bar", 236 } 237 `) 238} 239 240func TestPrebuiltEtcHost(t *testing.T) { 241 ctx, _ := testPrebuiltEtc(t, ` 242 prebuilt_etc_host { 243 name: "foo.conf", 244 src: "foo.conf", 245 } 246 `) 247 248 buildOS := android.BuildOs.String() 249 p := ctx.ModuleForTests("foo.conf", buildOS+"_common").Module().(*PrebuiltEtc) 250 if !p.Host() { 251 t.Errorf("host bit is not set for a prebuilt_etc_host module.") 252 } 253} 254 255func TestPrebuiltUserShareInstallDirPath(t *testing.T) { 256 ctx, _ := testPrebuiltEtc(t, ` 257 prebuilt_usr_share { 258 name: "foo.conf", 259 src: "foo.conf", 260 sub_dir: "bar", 261 } 262 `) 263 264 p := ctx.ModuleForTests("foo.conf", "android_arm64_armv8-a").Module().(*PrebuiltEtc) 265 expected := buildDir + "/target/product/test_device/system/usr/share/bar" 266 if p.installDirPath.String() != expected { 267 t.Errorf("expected %q, got %q", expected, p.installDirPath.String()) 268 } 269} 270 271func TestPrebuiltUserShareHostInstallDirPath(t *testing.T) { 272 ctx, config := testPrebuiltEtc(t, ` 273 prebuilt_usr_share_host { 274 name: "foo.conf", 275 src: "foo.conf", 276 sub_dir: "bar", 277 } 278 `) 279 280 buildOS := android.BuildOs.String() 281 p := ctx.ModuleForTests("foo.conf", buildOS+"_common").Module().(*PrebuiltEtc) 282 expected := filepath.Join(buildDir, "host", config.PrebuiltOS(), "usr", "share", "bar") 283 if p.installDirPath.String() != expected { 284 t.Errorf("expected %q, got %q", expected, p.installDirPath.String()) 285 } 286} 287 288func TestPrebuiltFontInstallDirPath(t *testing.T) { 289 ctx, _ := testPrebuiltEtc(t, ` 290 prebuilt_font { 291 name: "foo.conf", 292 src: "foo.conf", 293 } 294 `) 295 296 p := ctx.ModuleForTests("foo.conf", "android_arm64_armv8-a").Module().(*PrebuiltEtc) 297 expected := buildDir + "/target/product/test_device/system/fonts" 298 if p.installDirPath.String() != expected { 299 t.Errorf("expected %q, got %q", expected, p.installDirPath.String()) 300 } 301} 302 303func TestPrebuiltFirmwareDirPath(t *testing.T) { 304 targetPath := buildDir + "/target/product/test_device" 305 tests := []struct { 306 description string 307 config string 308 expectedPath string 309 }{{ 310 description: "prebuilt: system firmware", 311 config: ` 312 prebuilt_firmware { 313 name: "foo.conf", 314 src: "foo.conf", 315 }`, 316 expectedPath: filepath.Join(targetPath, "system/etc/firmware"), 317 }, { 318 description: "prebuilt: vendor firmware", 319 config: ` 320 prebuilt_firmware { 321 name: "foo.conf", 322 src: "foo.conf", 323 soc_specific: true, 324 sub_dir: "sub_dir", 325 }`, 326 expectedPath: filepath.Join(targetPath, "vendor/firmware/sub_dir"), 327 }} 328 for _, tt := range tests { 329 t.Run(tt.description, func(t *testing.T) { 330 ctx, _ := testPrebuiltEtc(t, tt.config) 331 p := ctx.ModuleForTests("foo.conf", "android_arm64_armv8-a").Module().(*PrebuiltEtc) 332 if p.installDirPath.String() != tt.expectedPath { 333 t.Errorf("expected %q, got %q", tt.expectedPath, p.installDirPath) 334 } 335 }) 336 } 337} 338 339func TestPrebuiltDSPDirPath(t *testing.T) { 340 targetPath := filepath.Join(buildDir, "/target/product/test_device") 341 tests := []struct { 342 description string 343 config string 344 expectedPath string 345 }{{ 346 description: "prebuilt: system dsp", 347 config: ` 348 prebuilt_dsp { 349 name: "foo.conf", 350 src: "foo.conf", 351 }`, 352 expectedPath: filepath.Join(targetPath, "system/etc/dsp"), 353 }, { 354 description: "prebuilt: vendor dsp", 355 config: ` 356 prebuilt_dsp { 357 name: "foo.conf", 358 src: "foo.conf", 359 soc_specific: true, 360 sub_dir: "sub_dir", 361 }`, 362 expectedPath: filepath.Join(targetPath, "vendor/dsp/sub_dir"), 363 }} 364 for _, tt := range tests { 365 t.Run(tt.description, func(t *testing.T) { 366 ctx, _ := testPrebuiltEtc(t, tt.config) 367 p := ctx.ModuleForTests("foo.conf", "android_arm64_armv8-a").Module().(*PrebuiltEtc) 368 if p.installDirPath.String() != tt.expectedPath { 369 t.Errorf("expected %q, got %q", tt.expectedPath, p.installDirPath) 370 } 371 }) 372 } 373} 374