Export provenance metadata for prebuilt APKs and APEXes.
Bug: 217434690 Test: atest --host gen_provenance_metadata_test Test: m provenance_metadata Change-Id: I91c184b6e6fe5ccfc3fc65b55b09e7a3da9502a0
This commit is contained in:
parent
85b935eff2
commit
340ee8e699
15 changed files with 672 additions and 41 deletions
|
@ -14,6 +14,7 @@ bootstrap_go_package {
|
|||
"soong-cc",
|
||||
"soong-filesystem",
|
||||
"soong-java",
|
||||
"soong-provenance",
|
||||
"soong-python",
|
||||
"soong-rust",
|
||||
"soong-sh",
|
||||
|
|
|
@ -3889,7 +3889,7 @@ func TestVndkApexWithBinder32(t *testing.T) {
|
|||
}),
|
||||
withBinder32bit,
|
||||
withTargets(map[android.OsType][]android.Target{
|
||||
android.Android: []android.Target{
|
||||
android.Android: {
|
||||
{Os: android.Android, Arch: android.Arch{ArchType: android.Arm, ArchVariant: "armv7-a-neon", Abi: []string{"armeabi-v7a"}},
|
||||
NativeBridge: android.NativeBridgeDisabled, NativeBridgeHostArchName: "", NativeBridgeRelativePath: ""},
|
||||
},
|
||||
|
@ -4570,12 +4570,20 @@ func TestPrebuilt(t *testing.T) {
|
|||
}
|
||||
`)
|
||||
|
||||
prebuilt := ctx.ModuleForTests("myapex", "android_common_myapex").Module().(*Prebuilt)
|
||||
testingModule := ctx.ModuleForTests("myapex", "android_common_myapex")
|
||||
prebuilt := testingModule.Module().(*Prebuilt)
|
||||
|
||||
expectedInput := "myapex-arm64.apex"
|
||||
if prebuilt.inputApex.String() != expectedInput {
|
||||
t.Errorf("inputApex invalid. expected: %q, actual: %q", expectedInput, prebuilt.inputApex.String())
|
||||
}
|
||||
android.AssertStringDoesContain(t, "Invalid provenance metadata file",
|
||||
prebuilt.ProvenanceMetaDataFile().String(), "soong/.intermediates/provenance_metadata/myapex/provenance_metadata.textproto")
|
||||
rule := testingModule.Rule("genProvenanceMetaData")
|
||||
android.AssertStringEquals(t, "Invalid input", "myapex-arm64.apex", rule.Inputs[0].String())
|
||||
android.AssertStringEquals(t, "Invalid output", "out/soong/.intermediates/provenance_metadata/myapex/provenance_metadata.textproto", rule.Output.String())
|
||||
android.AssertStringEquals(t, "Invalid args", "myapex", rule.Args["module_name"])
|
||||
android.AssertStringEquals(t, "Invalid args", "/system/apex/myapex.apex", rule.Args["install_path"])
|
||||
}
|
||||
|
||||
func TestPrebuiltMissingSrc(t *testing.T) {
|
||||
|
@ -4595,12 +4603,18 @@ func TestPrebuiltFilenameOverride(t *testing.T) {
|
|||
}
|
||||
`)
|
||||
|
||||
p := ctx.ModuleForTests("myapex", "android_common_myapex").Module().(*Prebuilt)
|
||||
testingModule := ctx.ModuleForTests("myapex", "android_common_myapex")
|
||||
p := testingModule.Module().(*Prebuilt)
|
||||
|
||||
expected := "notmyapex.apex"
|
||||
if p.installFilename != expected {
|
||||
t.Errorf("installFilename invalid. expected: %q, actual: %q", expected, p.installFilename)
|
||||
}
|
||||
rule := testingModule.Rule("genProvenanceMetaData")
|
||||
android.AssertStringEquals(t, "Invalid input", "myapex-arm.apex", rule.Inputs[0].String())
|
||||
android.AssertStringEquals(t, "Invalid output", "out/soong/.intermediates/provenance_metadata/myapex/provenance_metadata.textproto", rule.Output.String())
|
||||
android.AssertStringEquals(t, "Invalid args", "myapex", rule.Args["module_name"])
|
||||
android.AssertStringEquals(t, "Invalid args", "/system/apex/notmyapex.apex", rule.Args["install_path"])
|
||||
}
|
||||
|
||||
func TestApexSetFilenameOverride(t *testing.T) {
|
||||
|
@ -4643,13 +4657,19 @@ func TestPrebuiltOverrides(t *testing.T) {
|
|||
}
|
||||
`)
|
||||
|
||||
p := ctx.ModuleForTests("myapex.prebuilt", "android_common_myapex.prebuilt").Module().(*Prebuilt)
|
||||
testingModule := ctx.ModuleForTests("myapex.prebuilt", "android_common_myapex.prebuilt")
|
||||
p := testingModule.Module().(*Prebuilt)
|
||||
|
||||
expected := []string{"myapex"}
|
||||
actual := android.AndroidMkEntriesForTest(t, ctx, p)[0].EntryMap["LOCAL_OVERRIDES_MODULES"]
|
||||
if !reflect.DeepEqual(actual, expected) {
|
||||
t.Errorf("Incorrect LOCAL_OVERRIDES_MODULES value '%s', expected '%s'", actual, expected)
|
||||
}
|
||||
rule := testingModule.Rule("genProvenanceMetaData")
|
||||
android.AssertStringEquals(t, "Invalid input", "myapex-arm.apex", rule.Inputs[0].String())
|
||||
android.AssertStringEquals(t, "Invalid output", "out/soong/.intermediates/provenance_metadata/myapex.prebuilt/provenance_metadata.textproto", rule.Output.String())
|
||||
android.AssertStringEquals(t, "Invalid args", "myapex.prebuilt", rule.Args["module_name"])
|
||||
android.AssertStringEquals(t, "Invalid args", "/system/apex/myapex.prebuilt.apex", rule.Args["install_path"])
|
||||
}
|
||||
|
||||
func TestPrebuiltApexName(t *testing.T) {
|
||||
|
|
|
@ -23,7 +23,7 @@ import (
|
|||
|
||||
"android/soong/android"
|
||||
"android/soong/java"
|
||||
|
||||
"android/soong/provenance"
|
||||
"github.com/google/blueprint"
|
||||
"github.com/google/blueprint/proptools"
|
||||
)
|
||||
|
@ -482,6 +482,8 @@ type Prebuilt struct {
|
|||
properties PrebuiltProperties
|
||||
|
||||
inputApex android.Path
|
||||
|
||||
provenanceMetaDataFile android.OutputPath
|
||||
}
|
||||
|
||||
type ApexFileProperties struct {
|
||||
|
@ -778,9 +780,14 @@ func (p *Prebuilt) GenerateAndroidBuildActions(ctx android.ModuleContext) {
|
|||
|
||||
if p.installable() {
|
||||
p.installedFile = ctx.InstallFile(p.installDir, p.installFilename, p.inputApex, p.compatSymlinks.Paths()...)
|
||||
p.provenanceMetaDataFile = provenance.GenerateArtifactProvenanceMetaData(ctx, p.inputApex, p.installedFile)
|
||||
}
|
||||
}
|
||||
|
||||
func (p *Prebuilt) ProvenanceMetaDataFile() android.OutputPath {
|
||||
return p.provenanceMetaDataFile
|
||||
}
|
||||
|
||||
// prebuiltApexExtractorModule is a private module type that is only created by the prebuilt_apex
|
||||
// module. It extracts the correct apex to use and makes it available for use by apex_set.
|
||||
type prebuiltApexExtractorModule struct {
|
||||
|
|
|
@ -25,6 +25,7 @@ blueprint_go_binary {
|
|||
"golang-protobuf-android",
|
||||
"soong",
|
||||
"soong-android",
|
||||
"soong-provenance",
|
||||
"soong-bp2build",
|
||||
"soong-ui-metrics_proto",
|
||||
],
|
||||
|
|
|
@ -15,6 +15,7 @@ bootstrap_go_package {
|
|||
"soong-dexpreopt",
|
||||
"soong-genrule",
|
||||
"soong-java-config",
|
||||
"soong-provenance",
|
||||
"soong-python",
|
||||
"soong-remoteexec",
|
||||
"soong-tradefed",
|
||||
|
|
|
@ -22,6 +22,7 @@ import (
|
|||
"github.com/google/blueprint/proptools"
|
||||
|
||||
"android/soong/android"
|
||||
"android/soong/provenance"
|
||||
)
|
||||
|
||||
func init() {
|
||||
|
@ -57,6 +58,8 @@ type AndroidAppImport struct {
|
|||
installPath android.InstallPath
|
||||
|
||||
hideApexVariantFromMake bool
|
||||
|
||||
provenanceMetaDataFile android.OutputPath
|
||||
}
|
||||
|
||||
type AndroidAppImportProperties struct {
|
||||
|
@ -343,6 +346,8 @@ func (a *AndroidAppImport) generateAndroidBuildActions(ctx android.ModuleContext
|
|||
|
||||
if apexInfo.IsForPlatform() {
|
||||
a.installPath = ctx.InstallFile(installDir, apkFilename, a.outputFile)
|
||||
artifactPath := android.PathForModuleSrc(ctx, *a.properties.Apk)
|
||||
a.provenanceMetaDataFile = provenance.GenerateArtifactProvenanceMetaData(ctx, artifactPath, a.installPath)
|
||||
}
|
||||
|
||||
// TODO: androidmk converter jni libs
|
||||
|
@ -368,6 +373,10 @@ func (a *AndroidAppImport) Certificate() Certificate {
|
|||
return a.certificate
|
||||
}
|
||||
|
||||
func (a *AndroidAppImport) ProvenanceMetaDataFile() android.OutputPath {
|
||||
return a.provenanceMetaDataFile
|
||||
}
|
||||
|
||||
var dpiVariantGroupType reflect.Type
|
||||
var archVariantGroupType reflect.Type
|
||||
var supportedDpis = []string{"ldpi", "mdpi", "hdpi", "xhdpi", "xxhdpi", "xxxhdpi"}
|
||||
|
|
|
@ -53,6 +53,11 @@ func TestAndroidAppImport(t *testing.T) {
|
|||
if expected != signingFlag {
|
||||
t.Errorf("Incorrect signing flags, expected: %q, got: %q", expected, signingFlag)
|
||||
}
|
||||
rule := variant.Rule("genProvenanceMetaData")
|
||||
android.AssertStringEquals(t, "Invalid input", "prebuilts/apk/app.apk", rule.Inputs[0].String())
|
||||
android.AssertStringEquals(t, "Invalid output", "out/soong/.intermediates/provenance_metadata/foo/provenance_metadata.textproto", rule.Output.String())
|
||||
android.AssertStringEquals(t, "Invalid args", "foo", rule.Args["module_name"])
|
||||
android.AssertStringEquals(t, "Invalid args", "/system/app/foo/foo.apk", rule.Args["install_path"])
|
||||
}
|
||||
|
||||
func TestAndroidAppImport_NoDexPreopt(t *testing.T) {
|
||||
|
@ -74,6 +79,12 @@ func TestAndroidAppImport_NoDexPreopt(t *testing.T) {
|
|||
variant.MaybeOutput("dexpreopt/oat/arm64/package.odex").Rule != nil {
|
||||
t.Errorf("dexpreopt shouldn't have run.")
|
||||
}
|
||||
|
||||
rule := variant.Rule("genProvenanceMetaData")
|
||||
android.AssertStringEquals(t, "Invalid input", "prebuilts/apk/app.apk", rule.Inputs[0].String())
|
||||
android.AssertStringEquals(t, "Invalid output", "out/soong/.intermediates/provenance_metadata/foo/provenance_metadata.textproto", rule.Output.String())
|
||||
android.AssertStringEquals(t, "Invalid args", "foo", rule.Args["module_name"])
|
||||
android.AssertStringEquals(t, "Invalid args", "/system/app/foo/foo.apk", rule.Args["install_path"])
|
||||
}
|
||||
|
||||
func TestAndroidAppImport_Presigned(t *testing.T) {
|
||||
|
@ -102,6 +113,12 @@ func TestAndroidAppImport_Presigned(t *testing.T) {
|
|||
if variant.MaybeOutput("zip-aligned/foo.apk").Rule == nil {
|
||||
t.Errorf("can't find aligning rule")
|
||||
}
|
||||
|
||||
rule := variant.Rule("genProvenanceMetaData")
|
||||
android.AssertStringEquals(t, "Invalid input", "prebuilts/apk/app.apk", rule.Inputs[0].String())
|
||||
android.AssertStringEquals(t, "Invalid output", "out/soong/.intermediates/provenance_metadata/foo/provenance_metadata.textproto", rule.Output.String())
|
||||
android.AssertStringEquals(t, "Invalid args", "foo", rule.Args["module_name"])
|
||||
android.AssertStringEquals(t, "Invalid args", "/system/app/foo/foo.apk", rule.Args["install_path"])
|
||||
}
|
||||
|
||||
func TestAndroidAppImport_SigningLineage(t *testing.T) {
|
||||
|
@ -137,6 +154,12 @@ func TestAndroidAppImport_SigningLineage(t *testing.T) {
|
|||
if expected != signingFlag {
|
||||
t.Errorf("Incorrect signing flags, expected: %q, got: %q", expected, signingFlag)
|
||||
}
|
||||
|
||||
rule := variant.Rule("genProvenanceMetaData")
|
||||
android.AssertStringEquals(t, "Invalid input", "prebuilts/apk/app.apk", rule.Inputs[0].String())
|
||||
android.AssertStringEquals(t, "Invalid output", "out/soong/.intermediates/provenance_metadata/foo/provenance_metadata.textproto", rule.Output.String())
|
||||
android.AssertStringEquals(t, "Invalid args", "foo", rule.Args["module_name"])
|
||||
android.AssertStringEquals(t, "Invalid args", "/system/app/foo/foo.apk", rule.Args["install_path"])
|
||||
}
|
||||
|
||||
func TestAndroidAppImport_SigningLineageFilegroup(t *testing.T) {
|
||||
|
@ -163,6 +186,12 @@ func TestAndroidAppImport_SigningLineageFilegroup(t *testing.T) {
|
|||
if expected != signingFlag {
|
||||
t.Errorf("Incorrect signing flags, expected: %q, got: %q", expected, signingFlag)
|
||||
}
|
||||
|
||||
rule := variant.Rule("genProvenanceMetaData")
|
||||
android.AssertStringEquals(t, "Invalid input", "prebuilts/apk/app.apk", rule.Inputs[0].String())
|
||||
android.AssertStringEquals(t, "Invalid output", "out/soong/.intermediates/provenance_metadata/foo/provenance_metadata.textproto", rule.Output.String())
|
||||
android.AssertStringEquals(t, "Invalid args", "foo", rule.Args["module_name"])
|
||||
android.AssertStringEquals(t, "Invalid args", "/system/app/foo/foo.apk", rule.Args["install_path"])
|
||||
}
|
||||
|
||||
func TestAndroidAppImport_DefaultDevCert(t *testing.T) {
|
||||
|
@ -192,6 +221,12 @@ func TestAndroidAppImport_DefaultDevCert(t *testing.T) {
|
|||
if expected != signingFlag {
|
||||
t.Errorf("Incorrect signing flags, expected: %q, got: %q", expected, signingFlag)
|
||||
}
|
||||
|
||||
rule := variant.Rule("genProvenanceMetaData")
|
||||
android.AssertStringEquals(t, "Invalid input", "prebuilts/apk/app.apk", rule.Inputs[0].String())
|
||||
android.AssertStringEquals(t, "Invalid output", "out/soong/.intermediates/provenance_metadata/foo/provenance_metadata.textproto", rule.Output.String())
|
||||
android.AssertStringEquals(t, "Invalid args", "foo", rule.Args["module_name"])
|
||||
android.AssertStringEquals(t, "Invalid args", "/system/app/foo/foo.apk", rule.Args["install_path"])
|
||||
}
|
||||
|
||||
func TestAndroidAppImport_DpiVariants(t *testing.T) {
|
||||
|
@ -214,40 +249,46 @@ func TestAndroidAppImport_DpiVariants(t *testing.T) {
|
|||
}
|
||||
`
|
||||
testCases := []struct {
|
||||
name string
|
||||
aaptPreferredConfig *string
|
||||
aaptPrebuiltDPI []string
|
||||
expected string
|
||||
name string
|
||||
aaptPreferredConfig *string
|
||||
aaptPrebuiltDPI []string
|
||||
expected string
|
||||
expectedProvenanceMetaDataArtifactPath string
|
||||
}{
|
||||
{
|
||||
name: "no preferred",
|
||||
aaptPreferredConfig: nil,
|
||||
aaptPrebuiltDPI: []string{},
|
||||
expected: "verify_uses_libraries/apk/app.apk",
|
||||
name: "no preferred",
|
||||
aaptPreferredConfig: nil,
|
||||
aaptPrebuiltDPI: []string{},
|
||||
expected: "verify_uses_libraries/apk/app.apk",
|
||||
expectedProvenanceMetaDataArtifactPath: "prebuilts/apk/app.apk",
|
||||
},
|
||||
{
|
||||
name: "AAPTPreferredConfig matches",
|
||||
aaptPreferredConfig: proptools.StringPtr("xhdpi"),
|
||||
aaptPrebuiltDPI: []string{"xxhdpi", "ldpi"},
|
||||
expected: "verify_uses_libraries/apk/app_xhdpi.apk",
|
||||
name: "AAPTPreferredConfig matches",
|
||||
aaptPreferredConfig: proptools.StringPtr("xhdpi"),
|
||||
aaptPrebuiltDPI: []string{"xxhdpi", "ldpi"},
|
||||
expected: "verify_uses_libraries/apk/app_xhdpi.apk",
|
||||
expectedProvenanceMetaDataArtifactPath: "prebuilts/apk/app_xhdpi.apk",
|
||||
},
|
||||
{
|
||||
name: "AAPTPrebuiltDPI matches",
|
||||
aaptPreferredConfig: proptools.StringPtr("mdpi"),
|
||||
aaptPrebuiltDPI: []string{"xxhdpi", "xhdpi"},
|
||||
expected: "verify_uses_libraries/apk/app_xxhdpi.apk",
|
||||
name: "AAPTPrebuiltDPI matches",
|
||||
aaptPreferredConfig: proptools.StringPtr("mdpi"),
|
||||
aaptPrebuiltDPI: []string{"xxhdpi", "xhdpi"},
|
||||
expected: "verify_uses_libraries/apk/app_xxhdpi.apk",
|
||||
expectedProvenanceMetaDataArtifactPath: "prebuilts/apk/app_xxhdpi.apk",
|
||||
},
|
||||
{
|
||||
name: "non-first AAPTPrebuiltDPI matches",
|
||||
aaptPreferredConfig: proptools.StringPtr("mdpi"),
|
||||
aaptPrebuiltDPI: []string{"ldpi", "xhdpi"},
|
||||
expected: "verify_uses_libraries/apk/app_xhdpi.apk",
|
||||
name: "non-first AAPTPrebuiltDPI matches",
|
||||
aaptPreferredConfig: proptools.StringPtr("mdpi"),
|
||||
aaptPrebuiltDPI: []string{"ldpi", "xhdpi"},
|
||||
expected: "verify_uses_libraries/apk/app_xhdpi.apk",
|
||||
expectedProvenanceMetaDataArtifactPath: "prebuilts/apk/app_xhdpi.apk",
|
||||
},
|
||||
{
|
||||
name: "no matches",
|
||||
aaptPreferredConfig: proptools.StringPtr("mdpi"),
|
||||
aaptPrebuiltDPI: []string{"ldpi", "xxxhdpi"},
|
||||
expected: "verify_uses_libraries/apk/app.apk",
|
||||
name: "no matches",
|
||||
aaptPreferredConfig: proptools.StringPtr("mdpi"),
|
||||
aaptPrebuiltDPI: []string{"ldpi", "xxxhdpi"},
|
||||
expected: "verify_uses_libraries/apk/app.apk",
|
||||
expectedProvenanceMetaDataArtifactPath: "prebuilts/apk/app.apk",
|
||||
},
|
||||
}
|
||||
|
||||
|
@ -270,6 +311,12 @@ func TestAndroidAppImport_DpiVariants(t *testing.T) {
|
|||
if strings.HasSuffix(matches[1], test.expected) {
|
||||
t.Errorf("wrong src apk, expected: %q got: %q", test.expected, matches[1])
|
||||
}
|
||||
|
||||
provenanceMetaDataRule := variant.Rule("genProvenanceMetaData")
|
||||
android.AssertStringEquals(t, "Invalid input", test.expectedProvenanceMetaDataArtifactPath, provenanceMetaDataRule.Inputs[0].String())
|
||||
android.AssertStringEquals(t, "Invalid output", "out/soong/.intermediates/provenance_metadata/foo/provenance_metadata.textproto", provenanceMetaDataRule.Output.String())
|
||||
android.AssertStringEquals(t, "Invalid args", "foo", provenanceMetaDataRule.Args["module_name"])
|
||||
android.AssertStringEquals(t, "Invalid args", "/system/app/foo/foo.apk", provenanceMetaDataRule.Args["install_path"])
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -290,16 +337,25 @@ func TestAndroidAppImport_Filename(t *testing.T) {
|
|||
`)
|
||||
|
||||
testCases := []struct {
|
||||
name string
|
||||
expected string
|
||||
name string
|
||||
expected string
|
||||
onDevice string
|
||||
expectedArtifactPath string
|
||||
expectedMetaDataPath string
|
||||
}{
|
||||
{
|
||||
name: "foo",
|
||||
expected: "foo.apk",
|
||||
name: "foo",
|
||||
expected: "foo.apk",
|
||||
onDevice: "/system/app/foo/foo.apk",
|
||||
expectedArtifactPath: "prebuilts/apk/app.apk",
|
||||
expectedMetaDataPath: "out/soong/.intermediates/provenance_metadata/foo/provenance_metadata.textproto",
|
||||
},
|
||||
{
|
||||
name: "bar",
|
||||
expected: "bar_sample.apk",
|
||||
name: "bar",
|
||||
expected: "bar_sample.apk",
|
||||
onDevice: "/system/app/bar/bar_sample.apk",
|
||||
expectedArtifactPath: "prebuilts/apk/app.apk",
|
||||
expectedMetaDataPath: "out/soong/.intermediates/provenance_metadata/bar/provenance_metadata.textproto",
|
||||
},
|
||||
}
|
||||
|
||||
|
@ -316,15 +372,23 @@ func TestAndroidAppImport_Filename(t *testing.T) {
|
|||
t.Errorf("Incorrect LOCAL_INSTALLED_MODULE_STEM value '%s', expected '%s'",
|
||||
actualValues, expectedValues)
|
||||
}
|
||||
rule := variant.Rule("genProvenanceMetaData")
|
||||
android.AssertStringEquals(t, "Invalid input", test.expectedArtifactPath, rule.Inputs[0].String())
|
||||
android.AssertStringEquals(t, "Invalid output", test.expectedMetaDataPath, rule.Output.String())
|
||||
android.AssertStringEquals(t, "Invalid args", test.name, rule.Args["module_name"])
|
||||
android.AssertStringEquals(t, "Invalid args", test.onDevice, rule.Args["install_path"])
|
||||
}
|
||||
}
|
||||
|
||||
func TestAndroidAppImport_ArchVariants(t *testing.T) {
|
||||
// The test config's target arch is ARM64.
|
||||
testCases := []struct {
|
||||
name string
|
||||
bp string
|
||||
expected string
|
||||
name string
|
||||
bp string
|
||||
expected string
|
||||
artifactPath string
|
||||
metaDataPath string
|
||||
installPath string
|
||||
}{
|
||||
{
|
||||
name: "matching arch",
|
||||
|
@ -343,7 +407,9 @@ func TestAndroidAppImport_ArchVariants(t *testing.T) {
|
|||
},
|
||||
}
|
||||
`,
|
||||
expected: "verify_uses_libraries/apk/app_arm64.apk",
|
||||
expected: "verify_uses_libraries/apk/app_arm64.apk",
|
||||
artifactPath: "prebuilts/apk/app_arm64.apk",
|
||||
installPath: "/system/app/foo/foo.apk",
|
||||
},
|
||||
{
|
||||
name: "no matching arch",
|
||||
|
@ -362,7 +428,9 @@ func TestAndroidAppImport_ArchVariants(t *testing.T) {
|
|||
},
|
||||
}
|
||||
`,
|
||||
expected: "verify_uses_libraries/apk/app.apk",
|
||||
expected: "verify_uses_libraries/apk/app.apk",
|
||||
artifactPath: "prebuilts/apk/app.apk",
|
||||
installPath: "/system/app/foo/foo.apk",
|
||||
},
|
||||
{
|
||||
name: "no matching arch without default",
|
||||
|
@ -380,7 +448,9 @@ func TestAndroidAppImport_ArchVariants(t *testing.T) {
|
|||
},
|
||||
}
|
||||
`,
|
||||
expected: "",
|
||||
expected: "",
|
||||
artifactPath: "prebuilts/apk/app_arm.apk",
|
||||
installPath: "/system/app/foo/foo.apk",
|
||||
},
|
||||
}
|
||||
|
||||
|
@ -393,6 +463,8 @@ func TestAndroidAppImport_ArchVariants(t *testing.T) {
|
|||
if variant.Module().Enabled() {
|
||||
t.Error("module should have been disabled, but wasn't")
|
||||
}
|
||||
rule := variant.MaybeRule("genProvenanceMetaData")
|
||||
android.AssertDeepEquals(t, "Provenance metadata is not empty", android.TestingBuildParams{}, rule)
|
||||
continue
|
||||
}
|
||||
jniRuleCommand := variant.Output("jnis-uncompressed/foo.apk").RuleParams.Command
|
||||
|
@ -403,6 +475,11 @@ func TestAndroidAppImport_ArchVariants(t *testing.T) {
|
|||
if strings.HasSuffix(matches[1], test.expected) {
|
||||
t.Errorf("wrong src apk, expected: %q got: %q", test.expected, matches[1])
|
||||
}
|
||||
rule := variant.Rule("genProvenanceMetaData")
|
||||
android.AssertStringEquals(t, "Invalid input", test.artifactPath, rule.Inputs[0].String())
|
||||
android.AssertStringEquals(t, "Invalid output", "out/soong/.intermediates/provenance_metadata/foo/provenance_metadata.textproto", rule.Output.String())
|
||||
android.AssertStringEquals(t, "Invalid args", "foo", rule.Args["module_name"])
|
||||
android.AssertStringEquals(t, "Invalid args", test.installPath, rule.Args["install_path"])
|
||||
}
|
||||
}
|
||||
|
||||
|
|
36
provenance/Android.bp
Normal file
36
provenance/Android.bp
Normal file
|
@ -0,0 +1,36 @@
|
|||
/*
|
||||
* Copyright (C) 2022 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 {
|
||||
default_applicable_licenses: ["Android-Apache-2.0"],
|
||||
}
|
||||
|
||||
bootstrap_go_package {
|
||||
name: "soong-provenance",
|
||||
pkgPath: "android/soong/provenance",
|
||||
srcs: [
|
||||
"provenance_singleton.go",
|
||||
],
|
||||
deps: [
|
||||
"soong-android",
|
||||
],
|
||||
testSrcs: [
|
||||
"provenance_singleton_test.go",
|
||||
],
|
||||
pluginFor: [
|
||||
"soong_build",
|
||||
],
|
||||
}
|
34
provenance/provenance_metadata_proto/Android.bp
Normal file
34
provenance/provenance_metadata_proto/Android.bp
Normal file
|
@ -0,0 +1,34 @@
|
|||
/*
|
||||
* Copyright (C) 2022 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 {
|
||||
default_applicable_licenses: ["Android-Apache-2.0"],
|
||||
}
|
||||
|
||||
python_library_host {
|
||||
name: "provenance_metadata_proto",
|
||||
version: {
|
||||
py3: {
|
||||
enabled: true,
|
||||
},
|
||||
},
|
||||
srcs: [
|
||||
"provenance_metadata.proto",
|
||||
],
|
||||
proto: {
|
||||
canonical_path_from_root: false,
|
||||
},
|
||||
}
|
|
@ -0,0 +1,47 @@
|
|||
/*
|
||||
* Copyright (C) 2022 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.
|
||||
*/
|
||||
|
||||
syntax = "proto3";
|
||||
|
||||
package provenance_metadata_proto;
|
||||
option go_package = "android/soong/provenance/provenance_metadata_proto";
|
||||
|
||||
// Provenance metadata of artifacts.
|
||||
message ProvenanceMetadata {
|
||||
// Name of the module/target that creates the artifact.
|
||||
// It is either a Soong module name or Bazel target label.
|
||||
string module_name = 1;
|
||||
|
||||
// The path to the prebuilt artifacts, which is relative to the source tree
|
||||
// directory. For example, “prebuilts/runtime/mainline/i18n/apex/com.android.i18n-arm.apex”.
|
||||
string artifact_path = 2;
|
||||
|
||||
// The SHA256 hash of the artifact.
|
||||
string artifact_sha256 = 3;
|
||||
|
||||
// The install path of the artifact in filesystem images.
|
||||
// This is the absolute path of the artifact on the device.
|
||||
string artifact_install_path = 4;
|
||||
|
||||
// Path of the attestation file of a prebuilt artifact, which is relative to
|
||||
// the source tree directory. This is for prebuilt artifacts which have
|
||||
// corresponding attestation files checked in the source tree.
|
||||
string attestation_path = 5;
|
||||
}
|
||||
|
||||
message ProvenanceMetaDataList {
|
||||
repeated ProvenanceMetadata metadata = 1;
|
||||
}
|
112
provenance/provenance_singleton.go
Normal file
112
provenance/provenance_singleton.go
Normal file
|
@ -0,0 +1,112 @@
|
|||
/*
|
||||
* Copyright (C) 2022 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 provenance
|
||||
|
||||
import (
|
||||
"android/soong/android"
|
||||
"github.com/google/blueprint"
|
||||
)
|
||||
|
||||
var (
|
||||
pctx = android.NewPackageContext("android/soong/provenance")
|
||||
rule = pctx.HostBinToolVariable("gen_provenance_metadata", "gen_provenance_metadata")
|
||||
|
||||
genProvenanceMetaData = pctx.AndroidStaticRule("genProvenanceMetaData",
|
||||
blueprint.RuleParams{
|
||||
Command: `rm -rf "$out" && ` +
|
||||
`${gen_provenance_metadata} --module_name=${module_name} ` +
|
||||
`--artifact_path=$in --install_path=${install_path} --metadata_path=$out`,
|
||||
CommandDeps: []string{"${gen_provenance_metadata}"},
|
||||
}, "module_name", "install_path")
|
||||
|
||||
mergeProvenanceMetaData = pctx.AndroidStaticRule("mergeProvenanceMetaData",
|
||||
blueprint.RuleParams{
|
||||
Command: `rm -rf $out $out.temp && ` +
|
||||
`echo -e "# proto-file: build/soong/provenance/proto/provenance_metadata.proto\n# proto-message: ProvenanceMetaDataList" > $out && ` +
|
||||
`touch $out.temp && cat $out.temp $in | grep -v "^#.*" >> $out && rm -rf $out.temp`,
|
||||
})
|
||||
)
|
||||
|
||||
type ProvenanceMetadata interface {
|
||||
ProvenanceMetaDataFile() android.OutputPath
|
||||
}
|
||||
|
||||
func init() {
|
||||
RegisterProvenanceSingleton(android.InitRegistrationContext)
|
||||
}
|
||||
|
||||
func RegisterProvenanceSingleton(ctx android.RegistrationContext) {
|
||||
ctx.RegisterSingletonType("provenance_metadata_singleton", provenanceInfoSingletonFactory)
|
||||
}
|
||||
|
||||
var PrepareForTestWithProvenanceSingleton = android.FixtureRegisterWithContext(RegisterProvenanceSingleton)
|
||||
|
||||
func provenanceInfoSingletonFactory() android.Singleton {
|
||||
return &provenanceInfoSingleton{}
|
||||
}
|
||||
|
||||
type provenanceInfoSingleton struct {
|
||||
}
|
||||
|
||||
func (b *provenanceInfoSingleton) GenerateBuildActions(context android.SingletonContext) {
|
||||
allMetaDataFiles := make([]android.Path, 0)
|
||||
context.VisitAllModulesIf(moduleFilter, func(module android.Module) {
|
||||
if p, ok := module.(ProvenanceMetadata); ok {
|
||||
allMetaDataFiles = append(allMetaDataFiles, p.ProvenanceMetaDataFile())
|
||||
}
|
||||
})
|
||||
mergedMetaDataFile := android.PathForOutput(context, "provenance_metadata.textproto")
|
||||
context.Build(pctx, android.BuildParams{
|
||||
Rule: mergeProvenanceMetaData,
|
||||
Description: "merge provenance metadata",
|
||||
Inputs: allMetaDataFiles,
|
||||
Output: mergedMetaDataFile,
|
||||
})
|
||||
|
||||
context.Build(pctx, android.BuildParams{
|
||||
Rule: blueprint.Phony,
|
||||
Description: "phony rule of merge provenance metadata",
|
||||
Inputs: []android.Path{mergedMetaDataFile},
|
||||
Output: android.PathForPhony(context, "provenance_metadata"),
|
||||
})
|
||||
}
|
||||
|
||||
func moduleFilter(module android.Module) bool {
|
||||
if !module.Enabled() || module.IsSkipInstall() {
|
||||
return false
|
||||
}
|
||||
if p, ok := module.(ProvenanceMetadata); ok {
|
||||
return p.ProvenanceMetaDataFile().String() != ""
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func GenerateArtifactProvenanceMetaData(ctx android.ModuleContext, artifactPath android.Path, installedFile android.InstallPath) android.OutputPath {
|
||||
onDevicePathOfInstalledFile := android.InstallPathToOnDevicePath(ctx, installedFile)
|
||||
artifactMetaDataFile := android.PathForIntermediates(ctx, "provenance_metadata", ctx.ModuleDir(), ctx.ModuleName(), "provenance_metadata.textproto")
|
||||
ctx.Build(pctx, android.BuildParams{
|
||||
Rule: genProvenanceMetaData,
|
||||
Description: "generate artifact provenance metadata",
|
||||
Inputs: []android.Path{artifactPath},
|
||||
Output: artifactMetaDataFile,
|
||||
Args: map[string]string{
|
||||
"module_name": ctx.ModuleName(),
|
||||
"install_path": onDevicePathOfInstalledFile,
|
||||
}})
|
||||
|
||||
return artifactMetaDataFile
|
||||
}
|
48
provenance/provenance_singleton_test.go
Normal file
48
provenance/provenance_singleton_test.go
Normal file
|
@ -0,0 +1,48 @@
|
|||
/*
|
||||
* Copyright (C) 2022 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 provenance
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"android/soong/android"
|
||||
)
|
||||
|
||||
func TestProvenanceSingleton(t *testing.T) {
|
||||
result := android.GroupFixturePreparers(
|
||||
PrepareForTestWithProvenanceSingleton,
|
||||
android.PrepareForTestWithAndroidMk).RunTestWithBp(t, "")
|
||||
|
||||
outputs := result.SingletonForTests("provenance_metadata_singleton").AllOutputs()
|
||||
for _, output := range outputs {
|
||||
testingBuildParam := result.SingletonForTests("provenance_metadata_singleton").Output(output)
|
||||
switch {
|
||||
case strings.Contains(output, "soong/provenance_metadata.textproto"):
|
||||
android.AssertStringEquals(t, "Invalid build rule", "android/soong/provenance.mergeProvenanceMetaData", testingBuildParam.Rule.String())
|
||||
android.AssertIntEquals(t, "Invalid input", len(testingBuildParam.Inputs), 0)
|
||||
android.AssertStringDoesContain(t, "Invalid output path", output, "soong/provenance_metadata.textproto")
|
||||
android.AssertIntEquals(t, "Invalid args", len(testingBuildParam.Args), 0)
|
||||
|
||||
case strings.HasSuffix(output, "provenance_metadata"):
|
||||
android.AssertStringEquals(t, "Invalid build rule", "<builtin>:phony", testingBuildParam.Rule.String())
|
||||
android.AssertStringEquals(t, "Invalid input", testingBuildParam.Inputs[0].String(), "out/soong/provenance_metadata.textproto")
|
||||
android.AssertStringEquals(t, "Invalid output path", output, "provenance_metadata")
|
||||
android.AssertIntEquals(t, "Invalid args", len(testingBuildParam.Args), 0)
|
||||
}
|
||||
}
|
||||
}
|
47
provenance/tools/Android.bp
Normal file
47
provenance/tools/Android.bp
Normal file
|
@ -0,0 +1,47 @@
|
|||
/*
|
||||
* Copyright (C) 2022 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.
|
||||
*/
|
||||
|
||||
python_binary_host {
|
||||
name: "gen_provenance_metadata",
|
||||
srcs: [
|
||||
"gen_provenance_metadata.py",
|
||||
],
|
||||
version: {
|
||||
py3: {
|
||||
embedded_launcher: true,
|
||||
},
|
||||
},
|
||||
libs: [
|
||||
"provenance_metadata_proto",
|
||||
"libprotobuf-python",
|
||||
],
|
||||
}
|
||||
|
||||
python_test_host {
|
||||
name: "gen_provenance_metadata_test",
|
||||
main: "gen_provenance_metadata_test.py",
|
||||
srcs: [
|
||||
"gen_provenance_metadata_test.py",
|
||||
],
|
||||
data: [
|
||||
":gen_provenance_metadata",
|
||||
],
|
||||
libs: [
|
||||
"provenance_metadata_proto",
|
||||
"libprotobuf-python",
|
||||
],
|
||||
test_suites: ["general-tests"],
|
||||
}
|
66
provenance/tools/gen_provenance_metadata.py
Normal file
66
provenance/tools/gen_provenance_metadata.py
Normal file
|
@ -0,0 +1,66 @@
|
|||
#!/usr/bin/env python3
|
||||
#
|
||||
# Copyright (C) 2022 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.
|
||||
|
||||
import argparse
|
||||
import hashlib
|
||||
import sys
|
||||
|
||||
import google.protobuf.text_format as text_format
|
||||
import provenance_metadata_pb2
|
||||
|
||||
def Log(*info):
|
||||
if args.verbose:
|
||||
for i in info:
|
||||
print(i)
|
||||
|
||||
def ParseArgs(argv):
|
||||
parser = argparse.ArgumentParser(description='Create provenance metadata for a prebuilt artifact')
|
||||
parser.add_argument('-v', '--verbose', action='store_true', help='Print more information in execution')
|
||||
parser.add_argument('--module_name', help='Module name', required=True)
|
||||
parser.add_argument('--artifact_path', help='Relative path of the prebuilt artifact in source tree', required=True)
|
||||
parser.add_argument('--install_path', help='Absolute path of the artifact in the filesystem images', required=True)
|
||||
parser.add_argument('--metadata_path', help='Path of the provenance metadata file created for the artifact', required=True)
|
||||
return parser.parse_args(argv)
|
||||
|
||||
def main(argv):
|
||||
global args
|
||||
args = ParseArgs(argv)
|
||||
Log("Args:", vars(args))
|
||||
|
||||
provenance_metadata = provenance_metadata_pb2.ProvenanceMetadata()
|
||||
provenance_metadata.module_name = args.module_name
|
||||
provenance_metadata.artifact_path = args.artifact_path
|
||||
provenance_metadata.artifact_install_path = args.install_path
|
||||
|
||||
Log("Generating SHA256 hash")
|
||||
h = hashlib.sha256()
|
||||
with open(args.artifact_path, "rb") as artifact_file:
|
||||
h.update(artifact_file.read())
|
||||
provenance_metadata.artifact_sha256 = h.hexdigest()
|
||||
|
||||
text_proto = [
|
||||
"# proto-file: build/soong/provenance/proto/provenance_metadata.proto",
|
||||
"# proto-message: ProvenanceMetaData",
|
||||
"",
|
||||
text_format.MessageToString(provenance_metadata)
|
||||
]
|
||||
with open(args.metadata_path, "wt") as metadata_file:
|
||||
file_content = "\n".join(text_proto)
|
||||
Log("Writing provenance metadata in textproto:", file_content)
|
||||
metadata_file.write(file_content)
|
||||
|
||||
if __name__ == '__main__':
|
||||
main(sys.argv[1:])
|
125
provenance/tools/gen_provenance_metadata_test.py
Normal file
125
provenance/tools/gen_provenance_metadata_test.py
Normal file
|
@ -0,0 +1,125 @@
|
|||
#!/usr/bin/env python3
|
||||
#
|
||||
# Copyright (C) 2022 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.
|
||||
|
||||
import hashlib
|
||||
import logging
|
||||
import os
|
||||
import subprocess
|
||||
import tempfile
|
||||
import unittest
|
||||
|
||||
import google.protobuf.text_format as text_format
|
||||
import provenance_metadata_pb2
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
def run(args, verbose=None, **kwargs):
|
||||
"""Creates and returns a subprocess.Popen object.
|
||||
|
||||
Args:
|
||||
args: The command represented as a list of strings.
|
||||
verbose: Whether the commands should be shown. Default to the global
|
||||
verbosity if unspecified.
|
||||
kwargs: Any additional args to be passed to subprocess.Popen(), such as env,
|
||||
stdin, etc. stdout and stderr will default to subprocess.PIPE and
|
||||
subprocess.STDOUT respectively unless caller specifies any of them.
|
||||
universal_newlines will default to True, as most of the users in
|
||||
releasetools expect string output.
|
||||
|
||||
Returns:
|
||||
A subprocess.Popen object.
|
||||
"""
|
||||
if 'stdout' not in kwargs and 'stderr' not in kwargs:
|
||||
kwargs['stdout'] = subprocess.PIPE
|
||||
kwargs['stderr'] = subprocess.STDOUT
|
||||
if 'universal_newlines' not in kwargs:
|
||||
kwargs['universal_newlines'] = True
|
||||
if verbose:
|
||||
logger.info(" Running: \"%s\"", " ".join(args))
|
||||
return subprocess.Popen(args, **kwargs)
|
||||
|
||||
|
||||
def run_and_check_output(args, verbose=None, **kwargs):
|
||||
"""Runs the given command and returns the output.
|
||||
|
||||
Args:
|
||||
args: The command represented as a list of strings.
|
||||
verbose: Whether the commands should be shown. Default to the global
|
||||
verbosity if unspecified.
|
||||
kwargs: Any additional args to be passed to subprocess.Popen(), such as env,
|
||||
stdin, etc. stdout and stderr will default to subprocess.PIPE and
|
||||
subprocess.STDOUT respectively unless caller specifies any of them.
|
||||
|
||||
Returns:
|
||||
The output string.
|
||||
|
||||
Raises:
|
||||
ExternalError: On non-zero exit from the command.
|
||||
"""
|
||||
proc = run(args, verbose=verbose, **kwargs)
|
||||
output, _ = proc.communicate()
|
||||
if output is None:
|
||||
output = ""
|
||||
if verbose:
|
||||
logger.info("%s", output.rstrip())
|
||||
if proc.returncode != 0:
|
||||
raise RuntimeError(
|
||||
"Failed to run command '{}' (exit code {}):\n{}".format(
|
||||
args, proc.returncode, output))
|
||||
return output
|
||||
|
||||
def run_host_command(args, verbose=None, **kwargs):
|
||||
host_build_top = os.environ.get("ANDROID_BUILD_TOP")
|
||||
if host_build_top:
|
||||
host_command_dir = os.path.join(host_build_top, "out/host/linux-x86/bin")
|
||||
args[0] = os.path.join(host_command_dir, args[0])
|
||||
return run_and_check_output(args, verbose, **kwargs)
|
||||
|
||||
def sha256(s):
|
||||
h = hashlib.sha256()
|
||||
h.update(bytearray(s, 'utf-8'))
|
||||
return h.hexdigest()
|
||||
|
||||
class ProvenanceMetaDataToolTest(unittest.TestCase):
|
||||
|
||||
def test_gen_provenance_metadata(self):
|
||||
artifact_content = "test artifact"
|
||||
artifact_file = tempfile.mktemp()
|
||||
with open(artifact_file,"wt") as f:
|
||||
f.write(artifact_content)
|
||||
metadata_file = tempfile.mktemp()
|
||||
cmd = ["gen_provenance_metadata"]
|
||||
cmd.extend(["--module_name", "a"])
|
||||
cmd.extend(["--artifact_path", artifact_file])
|
||||
cmd.extend(["--install_path", "b"])
|
||||
cmd.extend(["--metadata_path", metadata_file])
|
||||
output = run_host_command(cmd)
|
||||
self.assertEqual(output, "")
|
||||
|
||||
with open(metadata_file,"rt") as f:
|
||||
data = f.read()
|
||||
provenance_metadata = provenance_metadata_pb2.ProvenanceMetadata()
|
||||
text_format.Parse(data, provenance_metadata)
|
||||
self.assertEqual(provenance_metadata.module_name, "a")
|
||||
self.assertEqual(provenance_metadata.artifact_path, artifact_file)
|
||||
self.assertEqual(provenance_metadata.artifact_install_path, "b")
|
||||
self.assertEqual(provenance_metadata.artifact_sha256, sha256(artifact_content))
|
||||
|
||||
os.remove(artifact_file)
|
||||
os.remove(metadata_file)
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main(verbosity=2)
|
Loading…
Reference in a new issue