Loading android/config.go +0 −58 Original line number Diff line number Diff line Loading @@ -1356,10 +1356,6 @@ func (c *config) FrameworksBaseDirExists(ctx PathGlobContext) bool { return ExistentPathForSource(ctx, "frameworks", "base", "Android.bp").Valid() } func (c *config) VndkSnapshotBuildArtifacts() bool { return Bool(c.productVariables.VndkSnapshotBuildArtifacts) } func (c *config) HasMultilibConflict(arch ArchType) bool { return c.multilibConflicts[arch] } Loading Loading @@ -1423,10 +1419,6 @@ func (c *deviceConfig) VendorPath() string { return "vendor" } func (c *deviceConfig) RecoverySnapshotVersion() string { return String(c.config.productVariables.RecoverySnapshotVersion) } func (c *deviceConfig) CurrentApiLevelForVendorModules() string { return StringDefault(c.config.productVariables.DeviceCurrentApiLevelForVendorModules, "current") } Loading Loading @@ -1804,22 +1796,6 @@ func (c *deviceConfig) IsPartnerTrebleSepolicyTestEnabled() bool { return c.SystemExtSepolicyPrebuiltApiDir() != "" || c.ProductSepolicyPrebuiltApiDir() != "" } func (c *deviceConfig) DirectedVendorSnapshot() bool { return c.config.productVariables.DirectedVendorSnapshot } func (c *deviceConfig) VendorSnapshotModules() map[string]bool { return c.config.productVariables.VendorSnapshotModules } func (c *deviceConfig) DirectedRecoverySnapshot() bool { return c.config.productVariables.DirectedRecoverySnapshot } func (c *deviceConfig) RecoverySnapshotModules() map[string]bool { return c.config.productVariables.RecoverySnapshotModules } func createDirsMap(previous map[string]bool, dirs []string) (map[string]bool, error) { var ret = make(map[string]bool) for _, dir := range dirs { Loading @@ -1846,40 +1822,6 @@ func (c *deviceConfig) createDirsMapOnce(onceKey OnceKey, previous map[string]bo return dirMap.(map[string]bool) } var vendorSnapshotDirsExcludedKey = NewOnceKey("VendorSnapshotDirsExcludedMap") func (c *deviceConfig) VendorSnapshotDirsExcludedMap() map[string]bool { return c.createDirsMapOnce(vendorSnapshotDirsExcludedKey, nil, c.config.productVariables.VendorSnapshotDirsExcluded) } var vendorSnapshotDirsIncludedKey = NewOnceKey("VendorSnapshotDirsIncludedMap") func (c *deviceConfig) VendorSnapshotDirsIncludedMap() map[string]bool { excludedMap := c.VendorSnapshotDirsExcludedMap() return c.createDirsMapOnce(vendorSnapshotDirsIncludedKey, excludedMap, c.config.productVariables.VendorSnapshotDirsIncluded) } var recoverySnapshotDirsExcludedKey = NewOnceKey("RecoverySnapshotDirsExcludedMap") func (c *deviceConfig) RecoverySnapshotDirsExcludedMap() map[string]bool { return c.createDirsMapOnce(recoverySnapshotDirsExcludedKey, nil, c.config.productVariables.RecoverySnapshotDirsExcluded) } var recoverySnapshotDirsIncludedKey = NewOnceKey("RecoverySnapshotDirsIncludedMap") func (c *deviceConfig) RecoverySnapshotDirsIncludedMap() map[string]bool { excludedMap := c.RecoverySnapshotDirsExcludedMap() return c.createDirsMapOnce(recoverySnapshotDirsIncludedKey, excludedMap, c.config.productVariables.RecoverySnapshotDirsIncluded) } func (c *deviceConfig) HostFakeSnapshotEnabled() bool { return c.config.productVariables.HostFakeSnapshotEnabled } func (c *deviceConfig) ShippingApiLevel() ApiLevel { if c.config.productVariables.Shipping_api_level == nil { return NoneApiLevel Loading android/variable.go +0 −16 Original line number Diff line number Diff line Loading @@ -239,8 +239,6 @@ type ProductVariables struct { VendorApiLevel *string `json:",omitempty"` RecoverySnapshotVersion *string `json:",omitempty"` DeviceSecondaryArch *string `json:",omitempty"` DeviceSecondaryArchVariant *string `json:",omitempty"` DeviceSecondaryCpuVariant *string `json:",omitempty"` Loading Loading @@ -373,20 +371,6 @@ type ProductVariables struct { PgoAdditionalProfileDirs []string `json:",omitempty"` VndkSnapshotBuildArtifacts *bool `json:",omitempty"` DirectedVendorSnapshot bool `json:",omitempty"` VendorSnapshotModules map[string]bool `json:",omitempty"` DirectedRecoverySnapshot bool `json:",omitempty"` RecoverySnapshotModules map[string]bool `json:",omitempty"` VendorSnapshotDirsIncluded []string `json:",omitempty"` VendorSnapshotDirsExcluded []string `json:",omitempty"` RecoverySnapshotDirsExcluded []string `json:",omitempty"` RecoverySnapshotDirsIncluded []string `json:",omitempty"` HostFakeSnapshotEnabled bool `json:",omitempty"` MultitreeUpdateMeta bool `json:",omitempty"` BoardVendorSepolicyDirs []string `json:",omitempty"` Loading snapshot/Android.bp +0 −1 Original line number Diff line number Diff line Loading @@ -14,7 +14,6 @@ bootstrap_go_package { // Source file name convention is to include _snapshot as a // file suffix for files that are generating snapshots. srcs: [ "host_fake_snapshot.go", "host_snapshot.go", "snapshot_base.go", "util.go", Loading snapshot/host_fake_snapshot.godeleted 100644 → 0 +0 −164 Original line number Diff line number Diff line // Copyright 2021 The Android Open Source Project // // 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 snapshot import ( "encoding/json" "path/filepath" "android/soong/android" ) // The host_snapshot module creates a snapshot of host tools to be used // in a minimal source tree. In order to create the host_snapshot the // user must explicitly list the modules to be included. The // host-fake-snapshot, defined in this file, is a utility to help determine // which host modules are being used in the minimal source tree. // // The host-fake-snapshot is designed to run in a full source tree and // will result in a snapshot that contains an empty file for each host // tool found in the tree. The fake snapshot is only used to determine // the host modules that the minimal source tree depends on, hence the // snapshot uses an empty file for each module and saves on having to // actually build any tool to generate the snapshot. The fake snapshot // is compatible with an actual host_snapshot and is installed into a // minimal source tree via the development/vendor_snapshot/update.py // script. // // After generating the fake snapshot and installing into the minimal // source tree, the dependent modules are determined via the // development/vendor_snapshot/update.py script (see script for more // information). These modules are then used to define the actual // host_snapshot to be used. This is a similar process to the other // snapshots (vendor, recovery,...) // // Example // // Full source tree: // 1/ Generate fake host snapshot // // Minimal source tree: // 2/ Install the fake host snapshot // 3/ List the host modules used from the snapshot // 4/ Remove fake host snapshot // // Full source tree: // 4/ Create host_snapshot with modules identified in step 3 // // Minimal source tree: // 5/ Install host snapshot // 6/ Build // // The host-fake-snapshot is a singleton module, that will be built // if HOST_FAKE_SNAPSHOT_ENABLE=true. func init() { registerHostSnapshotComponents(android.InitRegistrationContext) } // Add prebuilt information to snapshot data type hostSnapshotFakeJsonFlags struct { SnapshotJsonFlags Prebuilt bool `json:",omitempty"` } func registerHostSnapshotComponents(ctx android.RegistrationContext) { ctx.RegisterParallelSingletonType("host-fake-snapshot", HostToolsFakeAndroidSingleton) } type hostFakeSingleton struct { snapshotDir string zipFile android.OptionalPath } func (c *hostFakeSingleton) init() { c.snapshotDir = "host-fake-snapshot" } func HostToolsFakeAndroidSingleton() android.Singleton { singleton := &hostFakeSingleton{} singleton.init() return singleton } func (c *hostFakeSingleton) GenerateBuildActions(ctx android.SingletonContext) { if !ctx.DeviceConfig().HostFakeSnapshotEnabled() { return } // Find all host binary modules add 'fake' versions to snapshot var outputs android.Paths seen := make(map[string]bool) var jsonData []hostSnapshotFakeJsonFlags prebuilts := make(map[string]bool) ctx.VisitAllModules(func(module android.Module) { if module.Target().Os != ctx.Config().BuildOSTarget.Os { return } if module.Target().Arch.ArchType != ctx.Config().BuildOSTarget.Arch.ArchType { return } if android.IsModulePrebuilt(module) { // Add non-prebuilt module name to map of prebuilts prebuilts[android.RemoveOptionalPrebuiltPrefix(module.Name())] = true return } if !module.Enabled(ctx) || module.IsHideFromMake() { return } apexInfo, _ := android.SingletonModuleProvider(ctx, module, android.ApexInfoProvider) if !apexInfo.IsForPlatform() { return } path := hostToolPath(module) if path.Valid() && path.String() != "" { outFile := filepath.Join(c.snapshotDir, path.String()) if !seen[outFile] { seen[outFile] = true outputs = append(outputs, WriteStringToFileRule(ctx, "", outFile)) jsonData = append(jsonData, hostSnapshotFakeJsonFlags{*hostJsonDesc(ctx, module), false}) } } }) // Update any module prebuilt information for idx := range jsonData { if _, ok := prebuilts[jsonData[idx].ModuleName]; ok { // Prebuilt exists for this module jsonData[idx].Prebuilt = true } } marsh, err := json.Marshal(jsonData) if err != nil { ctx.Errorf("host fake snapshot json marshal failure: %#v", err) return } outputs = append(outputs, WriteStringToFileRule(ctx, string(marsh), filepath.Join(c.snapshotDir, "host_snapshot.json"))) c.zipFile = zipSnapshot(ctx, c.snapshotDir, c.snapshotDir, outputs) } func (c *hostFakeSingleton) MakeVars(ctx android.MakeVarsContext) { if !c.zipFile.Valid() { return } ctx.Phony( "host-fake-snapshot", c.zipFile.Path()) ctx.DistForGoal( "host-fake-snapshot", c.zipFile.Path()) } snapshot/host_test.go +0 −39 Original line number Diff line number Diff line Loading @@ -107,17 +107,6 @@ var prepareForHostModTest = android.GroupFixturePreparers( var prepareForFakeHostTest = android.GroupFixturePreparers( prepareForHostTest, android.FixtureWithRootAndroidBp(hostTestBp), android.FixtureRegisterWithContext(func(ctx android.RegistrationContext) { registerHostSnapshotComponents(ctx) }), ) // Prepare for fake host snapshot test enabled var prepareForFakeHostTestEnabled = android.GroupFixturePreparers( prepareForFakeHostTest, android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) { variables.HostFakeSnapshotEnabled = true }), ) // Validate that a hostSnapshot object is created containing zip files and JSON file Loading @@ -140,31 +129,3 @@ func TestHostSnapshot(t *testing.T) { } } // Validate fake host snapshot contains binary modules as well as the JSON meta file func TestFakeHostSnapshotEnable(t *testing.T) { result := prepareForFakeHostTestEnabled.RunTest(t) t.Helper() bins := []string{"foo", "bar"} ctx := result.TestContext.SingletonForTests("host-fake-snapshot") if ctx.MaybeOutput(filepath.Join("host-fake-snapshot", "host_snapshot.json")).Rule == nil { t.Error("Manifest file not found") } for _, bin := range bins { if ctx.MaybeOutput(filepath.Join("host-fake-snapshot", hostTestBinOut(bin))).Rule == nil { t.Error("Binary file ", bin, "not found") } } } // Validate not fake host snapshot if HostFakeSnapshotEnabled has not been set to true func TestFakeHostSnapshotDisable(t *testing.T) { result := prepareForFakeHostTest.RunTest(t) t.Helper() ctx := result.TestContext.SingletonForTests("host-fake-snapshot") if len(ctx.AllOutputs()) != 0 { t.Error("Fake host snapshot not empty when disabled") } } Loading
android/config.go +0 −58 Original line number Diff line number Diff line Loading @@ -1356,10 +1356,6 @@ func (c *config) FrameworksBaseDirExists(ctx PathGlobContext) bool { return ExistentPathForSource(ctx, "frameworks", "base", "Android.bp").Valid() } func (c *config) VndkSnapshotBuildArtifacts() bool { return Bool(c.productVariables.VndkSnapshotBuildArtifacts) } func (c *config) HasMultilibConflict(arch ArchType) bool { return c.multilibConflicts[arch] } Loading Loading @@ -1423,10 +1419,6 @@ func (c *deviceConfig) VendorPath() string { return "vendor" } func (c *deviceConfig) RecoverySnapshotVersion() string { return String(c.config.productVariables.RecoverySnapshotVersion) } func (c *deviceConfig) CurrentApiLevelForVendorModules() string { return StringDefault(c.config.productVariables.DeviceCurrentApiLevelForVendorModules, "current") } Loading Loading @@ -1804,22 +1796,6 @@ func (c *deviceConfig) IsPartnerTrebleSepolicyTestEnabled() bool { return c.SystemExtSepolicyPrebuiltApiDir() != "" || c.ProductSepolicyPrebuiltApiDir() != "" } func (c *deviceConfig) DirectedVendorSnapshot() bool { return c.config.productVariables.DirectedVendorSnapshot } func (c *deviceConfig) VendorSnapshotModules() map[string]bool { return c.config.productVariables.VendorSnapshotModules } func (c *deviceConfig) DirectedRecoverySnapshot() bool { return c.config.productVariables.DirectedRecoverySnapshot } func (c *deviceConfig) RecoverySnapshotModules() map[string]bool { return c.config.productVariables.RecoverySnapshotModules } func createDirsMap(previous map[string]bool, dirs []string) (map[string]bool, error) { var ret = make(map[string]bool) for _, dir := range dirs { Loading @@ -1846,40 +1822,6 @@ func (c *deviceConfig) createDirsMapOnce(onceKey OnceKey, previous map[string]bo return dirMap.(map[string]bool) } var vendorSnapshotDirsExcludedKey = NewOnceKey("VendorSnapshotDirsExcludedMap") func (c *deviceConfig) VendorSnapshotDirsExcludedMap() map[string]bool { return c.createDirsMapOnce(vendorSnapshotDirsExcludedKey, nil, c.config.productVariables.VendorSnapshotDirsExcluded) } var vendorSnapshotDirsIncludedKey = NewOnceKey("VendorSnapshotDirsIncludedMap") func (c *deviceConfig) VendorSnapshotDirsIncludedMap() map[string]bool { excludedMap := c.VendorSnapshotDirsExcludedMap() return c.createDirsMapOnce(vendorSnapshotDirsIncludedKey, excludedMap, c.config.productVariables.VendorSnapshotDirsIncluded) } var recoverySnapshotDirsExcludedKey = NewOnceKey("RecoverySnapshotDirsExcludedMap") func (c *deviceConfig) RecoverySnapshotDirsExcludedMap() map[string]bool { return c.createDirsMapOnce(recoverySnapshotDirsExcludedKey, nil, c.config.productVariables.RecoverySnapshotDirsExcluded) } var recoverySnapshotDirsIncludedKey = NewOnceKey("RecoverySnapshotDirsIncludedMap") func (c *deviceConfig) RecoverySnapshotDirsIncludedMap() map[string]bool { excludedMap := c.RecoverySnapshotDirsExcludedMap() return c.createDirsMapOnce(recoverySnapshotDirsIncludedKey, excludedMap, c.config.productVariables.RecoverySnapshotDirsIncluded) } func (c *deviceConfig) HostFakeSnapshotEnabled() bool { return c.config.productVariables.HostFakeSnapshotEnabled } func (c *deviceConfig) ShippingApiLevel() ApiLevel { if c.config.productVariables.Shipping_api_level == nil { return NoneApiLevel Loading
android/variable.go +0 −16 Original line number Diff line number Diff line Loading @@ -239,8 +239,6 @@ type ProductVariables struct { VendorApiLevel *string `json:",omitempty"` RecoverySnapshotVersion *string `json:",omitempty"` DeviceSecondaryArch *string `json:",omitempty"` DeviceSecondaryArchVariant *string `json:",omitempty"` DeviceSecondaryCpuVariant *string `json:",omitempty"` Loading Loading @@ -373,20 +371,6 @@ type ProductVariables struct { PgoAdditionalProfileDirs []string `json:",omitempty"` VndkSnapshotBuildArtifacts *bool `json:",omitempty"` DirectedVendorSnapshot bool `json:",omitempty"` VendorSnapshotModules map[string]bool `json:",omitempty"` DirectedRecoverySnapshot bool `json:",omitempty"` RecoverySnapshotModules map[string]bool `json:",omitempty"` VendorSnapshotDirsIncluded []string `json:",omitempty"` VendorSnapshotDirsExcluded []string `json:",omitempty"` RecoverySnapshotDirsExcluded []string `json:",omitempty"` RecoverySnapshotDirsIncluded []string `json:",omitempty"` HostFakeSnapshotEnabled bool `json:",omitempty"` MultitreeUpdateMeta bool `json:",omitempty"` BoardVendorSepolicyDirs []string `json:",omitempty"` Loading
snapshot/Android.bp +0 −1 Original line number Diff line number Diff line Loading @@ -14,7 +14,6 @@ bootstrap_go_package { // Source file name convention is to include _snapshot as a // file suffix for files that are generating snapshots. srcs: [ "host_fake_snapshot.go", "host_snapshot.go", "snapshot_base.go", "util.go", Loading
snapshot/host_fake_snapshot.godeleted 100644 → 0 +0 −164 Original line number Diff line number Diff line // Copyright 2021 The Android Open Source Project // // 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 snapshot import ( "encoding/json" "path/filepath" "android/soong/android" ) // The host_snapshot module creates a snapshot of host tools to be used // in a minimal source tree. In order to create the host_snapshot the // user must explicitly list the modules to be included. The // host-fake-snapshot, defined in this file, is a utility to help determine // which host modules are being used in the minimal source tree. // // The host-fake-snapshot is designed to run in a full source tree and // will result in a snapshot that contains an empty file for each host // tool found in the tree. The fake snapshot is only used to determine // the host modules that the minimal source tree depends on, hence the // snapshot uses an empty file for each module and saves on having to // actually build any tool to generate the snapshot. The fake snapshot // is compatible with an actual host_snapshot and is installed into a // minimal source tree via the development/vendor_snapshot/update.py // script. // // After generating the fake snapshot and installing into the minimal // source tree, the dependent modules are determined via the // development/vendor_snapshot/update.py script (see script for more // information). These modules are then used to define the actual // host_snapshot to be used. This is a similar process to the other // snapshots (vendor, recovery,...) // // Example // // Full source tree: // 1/ Generate fake host snapshot // // Minimal source tree: // 2/ Install the fake host snapshot // 3/ List the host modules used from the snapshot // 4/ Remove fake host snapshot // // Full source tree: // 4/ Create host_snapshot with modules identified in step 3 // // Minimal source tree: // 5/ Install host snapshot // 6/ Build // // The host-fake-snapshot is a singleton module, that will be built // if HOST_FAKE_SNAPSHOT_ENABLE=true. func init() { registerHostSnapshotComponents(android.InitRegistrationContext) } // Add prebuilt information to snapshot data type hostSnapshotFakeJsonFlags struct { SnapshotJsonFlags Prebuilt bool `json:",omitempty"` } func registerHostSnapshotComponents(ctx android.RegistrationContext) { ctx.RegisterParallelSingletonType("host-fake-snapshot", HostToolsFakeAndroidSingleton) } type hostFakeSingleton struct { snapshotDir string zipFile android.OptionalPath } func (c *hostFakeSingleton) init() { c.snapshotDir = "host-fake-snapshot" } func HostToolsFakeAndroidSingleton() android.Singleton { singleton := &hostFakeSingleton{} singleton.init() return singleton } func (c *hostFakeSingleton) GenerateBuildActions(ctx android.SingletonContext) { if !ctx.DeviceConfig().HostFakeSnapshotEnabled() { return } // Find all host binary modules add 'fake' versions to snapshot var outputs android.Paths seen := make(map[string]bool) var jsonData []hostSnapshotFakeJsonFlags prebuilts := make(map[string]bool) ctx.VisitAllModules(func(module android.Module) { if module.Target().Os != ctx.Config().BuildOSTarget.Os { return } if module.Target().Arch.ArchType != ctx.Config().BuildOSTarget.Arch.ArchType { return } if android.IsModulePrebuilt(module) { // Add non-prebuilt module name to map of prebuilts prebuilts[android.RemoveOptionalPrebuiltPrefix(module.Name())] = true return } if !module.Enabled(ctx) || module.IsHideFromMake() { return } apexInfo, _ := android.SingletonModuleProvider(ctx, module, android.ApexInfoProvider) if !apexInfo.IsForPlatform() { return } path := hostToolPath(module) if path.Valid() && path.String() != "" { outFile := filepath.Join(c.snapshotDir, path.String()) if !seen[outFile] { seen[outFile] = true outputs = append(outputs, WriteStringToFileRule(ctx, "", outFile)) jsonData = append(jsonData, hostSnapshotFakeJsonFlags{*hostJsonDesc(ctx, module), false}) } } }) // Update any module prebuilt information for idx := range jsonData { if _, ok := prebuilts[jsonData[idx].ModuleName]; ok { // Prebuilt exists for this module jsonData[idx].Prebuilt = true } } marsh, err := json.Marshal(jsonData) if err != nil { ctx.Errorf("host fake snapshot json marshal failure: %#v", err) return } outputs = append(outputs, WriteStringToFileRule(ctx, string(marsh), filepath.Join(c.snapshotDir, "host_snapshot.json"))) c.zipFile = zipSnapshot(ctx, c.snapshotDir, c.snapshotDir, outputs) } func (c *hostFakeSingleton) MakeVars(ctx android.MakeVarsContext) { if !c.zipFile.Valid() { return } ctx.Phony( "host-fake-snapshot", c.zipFile.Path()) ctx.DistForGoal( "host-fake-snapshot", c.zipFile.Path()) }
snapshot/host_test.go +0 −39 Original line number Diff line number Diff line Loading @@ -107,17 +107,6 @@ var prepareForHostModTest = android.GroupFixturePreparers( var prepareForFakeHostTest = android.GroupFixturePreparers( prepareForHostTest, android.FixtureWithRootAndroidBp(hostTestBp), android.FixtureRegisterWithContext(func(ctx android.RegistrationContext) { registerHostSnapshotComponents(ctx) }), ) // Prepare for fake host snapshot test enabled var prepareForFakeHostTestEnabled = android.GroupFixturePreparers( prepareForFakeHostTest, android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) { variables.HostFakeSnapshotEnabled = true }), ) // Validate that a hostSnapshot object is created containing zip files and JSON file Loading @@ -140,31 +129,3 @@ func TestHostSnapshot(t *testing.T) { } } // Validate fake host snapshot contains binary modules as well as the JSON meta file func TestFakeHostSnapshotEnable(t *testing.T) { result := prepareForFakeHostTestEnabled.RunTest(t) t.Helper() bins := []string{"foo", "bar"} ctx := result.TestContext.SingletonForTests("host-fake-snapshot") if ctx.MaybeOutput(filepath.Join("host-fake-snapshot", "host_snapshot.json")).Rule == nil { t.Error("Manifest file not found") } for _, bin := range bins { if ctx.MaybeOutput(filepath.Join("host-fake-snapshot", hostTestBinOut(bin))).Rule == nil { t.Error("Binary file ", bin, "not found") } } } // Validate not fake host snapshot if HostFakeSnapshotEnabled has not been set to true func TestFakeHostSnapshotDisable(t *testing.T) { result := prepareForFakeHostTest.RunTest(t) t.Helper() ctx := result.TestContext.SingletonForTests("host-fake-snapshot") if len(ctx.AllOutputs()) != 0 { t.Error("Fake host snapshot not empty when disabled") } }