| // Copyright 2021 Google Inc. All rights reserved. |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| package android |
| |
| import ( |
| "fmt" |
| "testing" |
| |
| "android/soong/android/allowlists" |
| "android/soong/bazel" |
| |
| "github.com/google/blueprint" |
| "github.com/google/blueprint/proptools" |
| ) |
| |
| func TestConvertAllModulesInPackage(t *testing.T) { |
| testCases := []struct { |
| prefixes allowlists.Bp2BuildConfig |
| packageDir string |
| }{ |
| { |
| prefixes: allowlists.Bp2BuildConfig{ |
| "a": allowlists.Bp2BuildDefaultTrueRecursively, |
| }, |
| packageDir: "a", |
| }, |
| { |
| prefixes: allowlists.Bp2BuildConfig{ |
| "a/b": allowlists.Bp2BuildDefaultTrueRecursively, |
| }, |
| packageDir: "a/b", |
| }, |
| { |
| prefixes: allowlists.Bp2BuildConfig{ |
| "a/b": allowlists.Bp2BuildDefaultTrueRecursively, |
| "a/b/c": allowlists.Bp2BuildDefaultTrueRecursively, |
| }, |
| packageDir: "a/b", |
| }, |
| { |
| prefixes: allowlists.Bp2BuildConfig{ |
| "a": allowlists.Bp2BuildDefaultTrueRecursively, |
| "d/e/f": allowlists.Bp2BuildDefaultTrueRecursively, |
| }, |
| packageDir: "a/b", |
| }, |
| { |
| prefixes: allowlists.Bp2BuildConfig{ |
| "a": allowlists.Bp2BuildDefaultFalse, |
| "a/b": allowlists.Bp2BuildDefaultTrueRecursively, |
| "a/b/c": allowlists.Bp2BuildDefaultFalse, |
| }, |
| packageDir: "a/b", |
| }, |
| { |
| prefixes: allowlists.Bp2BuildConfig{ |
| "a": allowlists.Bp2BuildDefaultTrueRecursively, |
| "a/b": allowlists.Bp2BuildDefaultFalse, |
| "a/b/c": allowlists.Bp2BuildDefaultTrueRecursively, |
| }, |
| packageDir: "a", |
| }, |
| { |
| prefixes: allowlists.Bp2BuildConfig{ |
| "a": allowlists.Bp2BuildDefaultFalseRecursively, |
| "a/b": allowlists.Bp2BuildDefaultTrue, |
| }, |
| packageDir: "a/b", |
| }, |
| { |
| prefixes: allowlists.Bp2BuildConfig{ |
| "a": allowlists.Bp2BuildDefaultFalseRecursively, |
| "a/b": allowlists.Bp2BuildDefaultTrueRecursively, |
| }, |
| packageDir: "a/b/c", |
| }, |
| } |
| |
| for _, test := range testCases { |
| if ok, _ := bp2buildDefaultTrueRecursively(test.packageDir, test.prefixes); !ok { |
| t.Errorf("Expected to convert all modules in %s based on %v, but failed.", test.packageDir, test.prefixes) |
| } |
| } |
| } |
| |
| func TestModuleOptIn(t *testing.T) { |
| testCases := []struct { |
| prefixes allowlists.Bp2BuildConfig |
| packageDir string |
| }{ |
| { |
| prefixes: allowlists.Bp2BuildConfig{ |
| "a/b": allowlists.Bp2BuildDefaultFalse, |
| }, |
| packageDir: "a/b", |
| }, |
| { |
| prefixes: allowlists.Bp2BuildConfig{ |
| "a": allowlists.Bp2BuildDefaultFalse, |
| "a/b": allowlists.Bp2BuildDefaultTrueRecursively, |
| }, |
| packageDir: "a", |
| }, |
| { |
| prefixes: allowlists.Bp2BuildConfig{ |
| "a/b": allowlists.Bp2BuildDefaultTrueRecursively, |
| }, |
| packageDir: "a", // opt-in by default |
| }, |
| { |
| prefixes: allowlists.Bp2BuildConfig{ |
| "a/b/c": allowlists.Bp2BuildDefaultTrueRecursively, |
| }, |
| packageDir: "a/b", |
| }, |
| { |
| prefixes: allowlists.Bp2BuildConfig{ |
| "a": allowlists.Bp2BuildDefaultTrueRecursively, |
| "d/e/f": allowlists.Bp2BuildDefaultTrueRecursively, |
| }, |
| packageDir: "foo/bar", |
| }, |
| { |
| prefixes: allowlists.Bp2BuildConfig{ |
| "a": allowlists.Bp2BuildDefaultTrueRecursively, |
| "a/b": allowlists.Bp2BuildDefaultFalse, |
| "a/b/c": allowlists.Bp2BuildDefaultTrueRecursively, |
| }, |
| packageDir: "a/b", |
| }, |
| { |
| prefixes: allowlists.Bp2BuildConfig{ |
| "a": allowlists.Bp2BuildDefaultFalse, |
| "a/b": allowlists.Bp2BuildDefaultTrueRecursively, |
| "a/b/c": allowlists.Bp2BuildDefaultFalse, |
| }, |
| packageDir: "a", |
| }, |
| { |
| prefixes: allowlists.Bp2BuildConfig{ |
| "a": allowlists.Bp2BuildDefaultFalseRecursively, |
| "a/b": allowlists.Bp2BuildDefaultTrue, |
| }, |
| packageDir: "a/b/c", |
| }, |
| { |
| prefixes: allowlists.Bp2BuildConfig{ |
| "a": allowlists.Bp2BuildDefaultTrueRecursively, |
| "a/b": allowlists.Bp2BuildDefaultFalseRecursively, |
| }, |
| packageDir: "a/b/c", |
| }, |
| } |
| |
| for _, test := range testCases { |
| if ok, _ := bp2buildDefaultTrueRecursively(test.packageDir, test.prefixes); ok { |
| t.Errorf("Expected to allow module opt-in in %s based on %v, but failed.", test.packageDir, test.prefixes) |
| } |
| } |
| } |
| |
| type TestBazelModule struct { |
| bazel.TestModuleInfo |
| BazelModuleBase |
| } |
| |
| var _ blueprint.Module = TestBazelModule{} |
| |
| func (m TestBazelModule) Name() string { |
| return m.TestModuleInfo.ModuleName |
| } |
| |
| func (m TestBazelModule) GenerateBuildActions(blueprint.ModuleContext) { |
| } |
| |
| type TestBazelConversionContext struct { |
| omc bazel.OtherModuleTestContext |
| allowlist Bp2BuildConversionAllowlist |
| errors []string |
| } |
| |
| var _ bazelOtherModuleContext = &TestBazelConversionContext{} |
| |
| func (bcc *TestBazelConversionContext) OtherModuleType(m blueprint.Module) string { |
| return bcc.omc.OtherModuleType(m) |
| } |
| |
| func (bcc *TestBazelConversionContext) OtherModuleName(m blueprint.Module) string { |
| return bcc.omc.OtherModuleName(m) |
| } |
| |
| func (bcc *TestBazelConversionContext) OtherModuleDir(m blueprint.Module) string { |
| return bcc.omc.OtherModuleDir(m) |
| } |
| |
| func (bcc *TestBazelConversionContext) ModuleErrorf(format string, args ...interface{}) { |
| bcc.errors = append(bcc.errors, fmt.Sprintf(format, args...)) |
| } |
| |
| func (bcc *TestBazelConversionContext) Config() Config { |
| return Config{ |
| &config{ |
| Bp2buildPackageConfig: bcc.allowlist, |
| }, |
| } |
| } |
| |
| var bazelableBazelModuleBase = BazelModuleBase{ |
| bazelProperties: properties{ |
| Bazel_module: BazelModuleProperties{ |
| CanConvertToBazel: true, |
| }, |
| }, |
| } |
| |
| func TestBp2BuildAllowlist(t *testing.T) { |
| testCases := []struct { |
| description string |
| shouldConvert bool |
| expectedErrors []string |
| module TestBazelModule |
| allowlist Bp2BuildConversionAllowlist |
| }{ |
| { |
| description: "allowlist enables module", |
| shouldConvert: true, |
| module: TestBazelModule{ |
| TestModuleInfo: bazel.TestModuleInfo{ |
| ModuleName: "foo", |
| Typ: "rule1", |
| Dir: "dir1", |
| }, |
| BazelModuleBase: bazelableBazelModuleBase, |
| }, |
| allowlist: Bp2BuildConversionAllowlist{ |
| moduleAlwaysConvert: map[string]bool{ |
| "foo": true, |
| }, |
| }, |
| }, |
| { |
| description: "module in name allowlist and type allowlist fails", |
| shouldConvert: false, |
| expectedErrors: []string{"A module cannot be in moduleAlwaysConvert and also be in moduleTypeAlwaysConvert"}, |
| module: TestBazelModule{ |
| TestModuleInfo: bazel.TestModuleInfo{ |
| ModuleName: "foo", |
| Typ: "rule1", |
| Dir: "dir1", |
| }, |
| BazelModuleBase: bazelableBazelModuleBase, |
| }, |
| allowlist: Bp2BuildConversionAllowlist{ |
| moduleAlwaysConvert: map[string]bool{ |
| "foo": true, |
| }, |
| moduleTypeAlwaysConvert: map[string]bool{ |
| "rule1": true, |
| }, |
| }, |
| }, |
| { |
| description: "module in allowlist and denylist fails", |
| shouldConvert: false, |
| expectedErrors: []string{"a module cannot be in moduleDoNotConvert and also be in moduleAlwaysConvert"}, |
| module: TestBazelModule{ |
| TestModuleInfo: bazel.TestModuleInfo{ |
| ModuleName: "foo", |
| Typ: "rule1", |
| Dir: "dir1", |
| }, |
| BazelModuleBase: bazelableBazelModuleBase, |
| }, |
| allowlist: Bp2BuildConversionAllowlist{ |
| moduleAlwaysConvert: map[string]bool{ |
| "foo": true, |
| }, |
| moduleDoNotConvert: map[string]bool{ |
| "foo": true, |
| }, |
| }, |
| }, |
| { |
| description: "module allowlist and enabled directory", |
| shouldConvert: false, |
| expectedErrors: []string{"A module cannot be in a directory marked Bp2BuildDefaultTrue or Bp2BuildDefaultTrueRecursively and also be in moduleAlwaysConvert. Directory: 'existing/build/dir' Module: 'foo'"}, |
| module: TestBazelModule{ |
| TestModuleInfo: bazel.TestModuleInfo{ |
| ModuleName: "foo", |
| Typ: "rule1", |
| Dir: "existing/build/dir", |
| }, |
| BazelModuleBase: bazelableBazelModuleBase, |
| }, |
| allowlist: Bp2BuildConversionAllowlist{ |
| moduleAlwaysConvert: map[string]bool{ |
| "foo": true, |
| }, |
| defaultConfig: allowlists.Bp2BuildConfig{ |
| "existing/build/dir": allowlists.Bp2BuildDefaultTrue, |
| }, |
| }, |
| }, |
| { |
| description: "module allowlist and enabled subdirectory", |
| shouldConvert: false, |
| expectedErrors: []string{"A module cannot be in a directory marked Bp2BuildDefaultTrue or Bp2BuildDefaultTrueRecursively and also be in moduleAlwaysConvert. Directory: 'existing/build/dir' Module: 'foo'"}, |
| module: TestBazelModule{ |
| TestModuleInfo: bazel.TestModuleInfo{ |
| ModuleName: "foo", |
| Typ: "rule1", |
| Dir: "existing/build/dir/subdir", |
| }, |
| BazelModuleBase: bazelableBazelModuleBase, |
| }, |
| allowlist: Bp2BuildConversionAllowlist{ |
| moduleAlwaysConvert: map[string]bool{ |
| "foo": true, |
| }, |
| defaultConfig: allowlists.Bp2BuildConfig{ |
| "existing/build/dir": allowlists.Bp2BuildDefaultTrueRecursively, |
| }, |
| }, |
| }, |
| { |
| description: "module enabled in unit test short-circuits other allowlists", |
| shouldConvert: true, |
| module: TestBazelModule{ |
| TestModuleInfo: bazel.TestModuleInfo{ |
| ModuleName: "foo", |
| Typ: "rule1", |
| Dir: ".", |
| }, |
| BazelModuleBase: BazelModuleBase{ |
| bazelProperties: properties{ |
| Bazel_module: BazelModuleProperties{ |
| CanConvertToBazel: true, |
| Bp2build_available: proptools.BoolPtr(true), |
| }, |
| }, |
| }, |
| }, |
| allowlist: Bp2BuildConversionAllowlist{ |
| moduleAlwaysConvert: map[string]bool{ |
| "foo": true, |
| }, |
| moduleDoNotConvert: map[string]bool{ |
| "foo": true, |
| }, |
| }, |
| }, |
| } |
| |
| for _, test := range testCases { |
| t.Run(test.description, func(t *testing.T) { |
| bcc := &TestBazelConversionContext{ |
| omc: bazel.OtherModuleTestContext{ |
| Modules: []bazel.TestModuleInfo{ |
| test.module.TestModuleInfo, |
| }, |
| }, |
| allowlist: test.allowlist, |
| } |
| |
| shouldConvert := test.module.shouldConvertWithBp2build(bcc, test.module.TestModuleInfo) |
| if test.shouldConvert != shouldConvert { |
| t.Errorf("Module shouldConvert expected to be: %v, but was: %v", test.shouldConvert, shouldConvert) |
| } |
| |
| errorsMatch := true |
| if len(test.expectedErrors) != len(bcc.errors) { |
| errorsMatch = false |
| } else { |
| for i, err := range test.expectedErrors { |
| if err != bcc.errors[i] { |
| errorsMatch = false |
| } |
| } |
| } |
| if !errorsMatch { |
| t.Errorf("Expected errors to be: %v, but were: %v", test.expectedErrors, bcc.errors) |
| } |
| }) |
| } |
| } |
| |
| func TestBp2buildAllowList(t *testing.T) { |
| allowlist := GetBp2BuildAllowList() |
| for k, v := range allowlists.Bp2buildDefaultConfig { |
| if allowlist.defaultConfig[k] != v { |
| t.Errorf("bp2build default config of %s: expected: %v, got: %v", k, v, allowlist.defaultConfig[k]) |
| } |
| } |
| for k, v := range allowlists.Bp2buildKeepExistingBuildFile { |
| if allowlist.keepExistingBuildFile[k] != v { |
| t.Errorf("bp2build keep existing build file of %s: expected: %v, got: %v", k, v, allowlist.keepExistingBuildFile[k]) |
| } |
| } |
| for _, k := range allowlists.Bp2buildModuleTypeAlwaysConvertList { |
| if !allowlist.moduleTypeAlwaysConvert[k] { |
| t.Errorf("bp2build module type always convert of %s: expected: true, got: %v", k, allowlist.moduleTypeAlwaysConvert[k]) |
| } |
| } |
| for _, k := range allowlists.Bp2buildModuleDoNotConvertList { |
| if !allowlist.moduleDoNotConvert[k] { |
| t.Errorf("bp2build module do not convert of %s: expected: true, got: %v", k, allowlist.moduleDoNotConvert[k]) |
| } |
| } |
| } |
| |
| func TestShouldKeepExistingBuildFileForDir(t *testing.T) { |
| allowlist := NewBp2BuildAllowlist() |
| // entry "a/b2/c2" is moot because of its parent "a/b2" |
| allowlist.SetKeepExistingBuildFile(map[string]bool{"a": false, "a/b1": false, "a/b2": true, "a/b1/c1": true, "a/b2/c2": false}) |
| truths := []string{"a", "a/b1", "a/b2", "a/b1/c1", "a/b2/c", "a/b2/c2", "a/b2/c2/d"} |
| falsities := []string{"a1", "a/b", "a/b1/c"} |
| for _, dir := range truths { |
| if !allowlist.ShouldKeepExistingBuildFileForDir(dir) { |
| t.Errorf("%s expected TRUE but was FALSE", dir) |
| } |
| } |
| for _, dir := range falsities { |
| if allowlist.ShouldKeepExistingBuildFileForDir(dir) { |
| t.Errorf("%s expected FALSE but was TRUE", dir) |
| } |
| } |
| } |