Accept test_data attribute for file_contexts_test

If file_contexts_test is given a test_data attribute, it will use
`checkfc -t` to validate the file_context against it, instead of using
the policy. Both options are mutually exclusive.

Bug: 299839280
Test: m
Change-Id: I3f541e0d0bb5d03ed146e27d67bc811cda3164b1
diff --git a/build/soong/selinux_contexts.go b/build/soong/selinux_contexts.go
index 47a63d0..b053c7a 100644
--- a/build/soong/selinux_contexts.go
+++ b/build/soong/selinux_contexts.go
@@ -517,14 +517,20 @@
 	Sepolicy *string `android:"path"`
 }
 
+type fileContextsTestProperties struct {
+	// Test data. File passed to `checkfc -t` to validate how contexts are resolved.
+	Test_data *string `android:"path"`
+}
+
 type contextsTestModule struct {
 	android.ModuleBase
 
 	// The type of context.
 	context contextType
 
-	properties    contextsTestProperties
-	testTimestamp android.OutputPath
+	properties     contextsTestProperties
+	fileProperties fileContextsTestProperties
+	testTimestamp  android.OutputPath
 }
 
 type contextType int
@@ -547,6 +553,7 @@
 func fileContextsTestFactory() android.Module {
 	m := &contextsTestModule{context: FileContext}
 	m.AddProperties(&m.properties)
+	m.AddProperties(&m.fileProperties)
 	android.InitAndroidArchModule(m, android.DeviceSupported, android.MultilibCommon)
 	return m
 }
@@ -595,13 +602,26 @@
 		return
 	}
 
+	validateWithPolicy := true
 	if proptools.String(m.properties.Sepolicy) == "" {
-		ctx.PropertyErrorf("sepolicy", "can't be empty")
-		return
+		if m.context == FileContext {
+			if proptools.String(m.fileProperties.Test_data) == "" {
+				ctx.PropertyErrorf("test_data", "Either test_data or sepolicy should be provided")
+				return
+			}
+			validateWithPolicy = false
+		} else {
+			ctx.PropertyErrorf("sepolicy", "can't be empty")
+			return
+		}
 	}
 
 	flags := []string(nil)
 	switch m.context {
+	case FileContext:
+		if !validateWithPolicy {
+			flags = []string{"-t"}
+		}
 	case ServiceContext:
 		flags = []string{"-s" /* binder services */}
 	case HwServiceContext:
@@ -611,13 +631,21 @@
 	}
 
 	srcs := android.PathsForModuleSrc(ctx, m.properties.Srcs)
-	sepolicy := android.PathForModuleSrc(ctx, proptools.String(m.properties.Sepolicy))
-
 	rule := android.NewRuleBuilder(pctx, ctx)
-	rule.Command().BuiltTool(tool).
-		Flags(flags).
-		Input(sepolicy).
-		Inputs(srcs)
+
+	if validateWithPolicy {
+		sepolicy := android.PathForModuleSrc(ctx, proptools.String(m.properties.Sepolicy))
+		rule.Command().BuiltTool(tool).
+			Flags(flags).
+			Input(sepolicy).
+			Inputs(srcs)
+	} else {
+		test_data := android.PathForModuleSrc(ctx, proptools.String(m.fileProperties.Test_data))
+		rule.Command().BuiltTool(tool).
+			Flags(flags).
+			Inputs(srcs).
+			Input(test_data)
+	}
 
 	m.testTimestamp = pathForModuleOut(ctx, "timestamp")
 	rule.Command().Text("touch").Output(m.testTimestamp)