Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b9518073 authored by Jooyung Han's avatar Jooyung Han
Browse files

Add apex_test.skip_validations

Run validations for apex_test modules as well. If a test apex needs to
be invalid for testing, it needs to specify which validation it needs to
skip. This is to prevent cases like using apex_test to avoid a certain
validation, but accidentally skipping all validations.

For now, host_apex_verifier/apex_sepolicy_tests can be skipped.

Bug: 363090062
Test: m nothing --no-skip-soong-tests
Test: mmma system/apex
Change-Id: I2d14f25f579eabe92ed2bd0e28b5ed19583df99d
parent 1a6f176c
Loading
Loading
Loading
Loading
+27 −4
Original line number Diff line number Diff line
@@ -434,6 +434,7 @@ type apexBundle struct {
	archProperties        apexArchBundleProperties
	overridableProperties overridableProperties
	vndkProperties        apexVndkProperties // only for apex_vndk modules
	testProperties        apexTestProperties // only for apex_test modules

	///////////////////////////////////////////////////////////////////////////////////////////
	// Inputs
@@ -1296,6 +1297,23 @@ func (a *apexBundle) UsePlatformApis() bool {
	return proptools.BoolDefault(a.properties.Platform_apis, false)
}

type apexValidationType int

const (
	hostApexVerifier apexValidationType = iota
	apexSepolicyTests
)

func (a *apexBundle) skipValidation(validationType apexValidationType) bool {
	switch validationType {
	case hostApexVerifier:
		return proptools.Bool(a.testProperties.Skip_validations.Host_apex_verifier)
	case apexSepolicyTests:
		return proptools.Bool(a.testProperties.Skip_validations.Apex_sepolicy_tests)
	}
	panic("Unknown validation type")
}

// getCertString returns the name of the cert that should be used to sign this APEX. This is
// basically from the "certificate" property, but could be overridden by the device config.
func (a *apexBundle) getCertString(ctx android.BaseModuleContext) string {
@@ -2427,10 +2445,14 @@ func newApexBundle() *apexBundle {
	return module
}

func ApexBundleFactory(testApex bool) android.Module {
	bundle := newApexBundle()
	bundle.testApex = testApex
	return bundle
type apexTestProperties struct {
	// Boolean flags for validation checks. Test APEXes can turn on/off individual checks.
	Skip_validations struct {
		// Skips `Apex_sepolicy_tests` check if true
		Apex_sepolicy_tests *bool
		// Skips `Host_apex_verifier` check if true
		Host_apex_verifier *bool
	}
}

// apex_test is an APEX for testing. The difference from the ordinary apex module type is that
@@ -2438,6 +2460,7 @@ func ApexBundleFactory(testApex bool) android.Module {
func TestApexBundleFactory() android.Module {
	bundle := newApexBundle()
	bundle.testApex = true
	bundle.AddProperties(&bundle.testProperties)
	return bundle
}

+45 −0
Original line number Diff line number Diff line
@@ -7101,6 +7101,51 @@ func TestApexAvailable_PrefixMatch(t *testing.T) {
	`)
}

func TestApexValidation_TestApexCanSkipInitRcCheck(t *testing.T) {
	t.Parallel()
	ctx := testApex(t, `
		apex_test {
			name: "myapex",
			key: "myapex.key",
			skip_validations: {
				host_apex_verifier: true,
			},
			updatable: false,
		}
		apex_key {
			name: "myapex.key",
			public_key: "testkey.avbpubkey",
			private_key: "testkey.pem",
		}
	`)

	validations := ctx.ModuleForTests("myapex", "android_common_myapex").Rule("signapk").Validations.Strings()
	if android.SuffixInList(validations, "host_apex_verifier.timestamp") {
		t.Error("should not run host_apex_verifier")
	}
}

func TestApexValidation_TestApexCheckInitRc(t *testing.T) {
	t.Parallel()
	ctx := testApex(t, `
		apex_test {
			name: "myapex",
			key: "myapex.key",
			updatable: false,
		}
		apex_key {
			name: "myapex.key",
			public_key: "testkey.avbpubkey",
			private_key: "testkey.pem",
		}
	`)

	validations := ctx.ModuleForTests("myapex", "android_common_myapex").Rule("signapk").Validations.Strings()
	if !android.SuffixInList(validations, "host_apex_verifier.timestamp") {
		t.Error("should run host_apex_verifier")
	}
}

func TestOverrideApex(t *testing.T) {
	t.Parallel()
	ctx := testApex(t, `
+3 −3
Original line number Diff line number Diff line
@@ -924,14 +924,14 @@ func (a *apexBundle) buildApex(ctx android.ModuleContext) {
	var validations android.Paths
	validations = append(validations, runApexLinkerconfigValidation(ctx, unsignedOutputFile, imageDir))
	// TODO(b/279688635) deapexer supports [ext4]
	if !a.testApex && suffix == imageApexSuffix && ext4 == a.payloadFsType {
	if !a.skipValidation(apexSepolicyTests) && suffix == imageApexSuffix && ext4 == a.payloadFsType {
		validations = append(validations, runApexSepolicyTests(ctx, unsignedOutputFile))
	}
	if !a.testApex && len(a.properties.Unwanted_transitive_deps) > 0 {
		validations = append(validations,
			runApexElfCheckerUnwanted(ctx, unsignedOutputFile, a.properties.Unwanted_transitive_deps))
	}
	if !a.testApex && android.InList(a.payloadFsType, []fsType{ext4, erofs}) {
	if !a.skipValidation(hostApexVerifier) && android.InList(a.payloadFsType, []fsType{ext4, erofs}) {
		validations = append(validations, runApexHostVerifier(ctx, a, unsignedOutputFile))
	}
	ctx.Build(pctx, android.BuildParams{
@@ -1220,7 +1220,7 @@ func runApexLinkerconfigValidation(ctx android.ModuleContext, apexFile android.P
// $ deapexer list -Z {apex_file} > {file_contexts}
// $ apex_sepolicy_tests -f {file_contexts}
func runApexSepolicyTests(ctx android.ModuleContext, apexFile android.Path) android.Path {
	timestamp := android.PathForModuleOut(ctx, "sepolicy_tests.timestamp")
	timestamp := android.PathForModuleOut(ctx, "apex_sepolicy_tests.timestamp")
	ctx.Build(pctx, android.BuildParams{
		Rule:   apexSepolicyTestsRule,
		Input:  apexFile,