diff --git a/tools/compliance/Android.bp b/tools/compliance/Android.bp
index 2527df727b..8e13f2f661 100644
--- a/tools/compliance/Android.bp
+++ b/tools/compliance/Android.bp
@@ -131,6 +131,17 @@ blueprint_go_binary {
testSrcs: ["cmd/xmlnotice/xmlnotice_test.go"],
}
+blueprint_go_binary {
+ name: "compliance_sbom",
+ srcs: ["cmd/sbom/sbom.go"],
+ deps: [
+ "compliance-module",
+ "blueprint-deptools",
+ "soong-response",
+ ],
+ testSrcs: ["cmd/sbom/sbom_test.go"],
+}
+
bootstrap_go_package {
name: "compliance-module",
srcs: [
diff --git a/tools/compliance/cmd/sbom/sbom.go b/tools/compliance/cmd/sbom/sbom.go
new file mode 100644
index 0000000000..afb377efb7
--- /dev/null
+++ b/tools/compliance/cmd/sbom/sbom.go
@@ -0,0 +1,399 @@
+// Copyright 2022 Google LLC
+//
+// 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 main
+
+import (
+ "bytes"
+ "flag"
+ "fmt"
+ "io"
+ "io/fs"
+ "os"
+ "path/filepath"
+ "sort"
+ "strings"
+ "time"
+
+ "android/soong/response"
+ "android/soong/tools/compliance"
+ "android/soong/tools/compliance/projectmetadata"
+
+ "github.com/google/blueprint/deptools"
+)
+
+var (
+ failNoneRequested = fmt.Errorf("\nNo license metadata files requested")
+ failNoLicenses = fmt.Errorf("No licenses found")
+)
+
+type context struct {
+ stdout io.Writer
+ stderr io.Writer
+ rootFS fs.FS
+ product string
+ stripPrefix []string
+ creationTime creationTimeGetter
+}
+
+func (ctx context) strip(installPath string) string {
+ for _, prefix := range ctx.stripPrefix {
+ if strings.HasPrefix(installPath, prefix) {
+ p := strings.TrimPrefix(installPath, prefix)
+ if 0 == len(p) {
+ p = ctx.product
+ }
+ if 0 == len(p) {
+ continue
+ }
+ return p
+ }
+ }
+ return installPath
+}
+
+// newMultiString creates a flag that allows multiple values in an array.
+func newMultiString(flags *flag.FlagSet, name, usage string) *multiString {
+ var f multiString
+ flags.Var(&f, name, usage)
+ return &f
+}
+
+// multiString implements the flag `Value` interface for multiple strings.
+type multiString []string
+
+func (ms *multiString) String() string { return strings.Join(*ms, ", ") }
+func (ms *multiString) Set(s string) error { *ms = append(*ms, s); return nil }
+
+func main() {
+ var expandedArgs []string
+ for _, arg := range os.Args[1:] {
+ if strings.HasPrefix(arg, "@") {
+ f, err := os.Open(strings.TrimPrefix(arg, "@"))
+ if err != nil {
+ fmt.Fprintln(os.Stderr, err.Error())
+ os.Exit(1)
+ }
+
+ respArgs, err := response.ReadRspFile(f)
+ f.Close()
+ if err != nil {
+ fmt.Fprintln(os.Stderr, err.Error())
+ os.Exit(1)
+ }
+ expandedArgs = append(expandedArgs, respArgs...)
+ } else {
+ expandedArgs = append(expandedArgs, arg)
+ }
+ }
+
+ flags := flag.NewFlagSet("flags", flag.ExitOnError)
+
+ flags.Usage = func() {
+ fmt.Fprintf(os.Stderr, `Usage: %s {options} file.meta_lic {file.meta_lic...}
+
+Outputs an SBOM.spdx.
+
+Options:
+`, filepath.Base(os.Args[0]))
+ flags.PrintDefaults()
+ }
+
+ outputFile := flags.String("o", "-", "Where to write the SBOM spdx file. (default stdout)")
+ depsFile := flags.String("d", "", "Where to write the deps file")
+ product := flags.String("product", "", "The name of the product for which the notice is generated.")
+ stripPrefix := newMultiString(flags, "strip_prefix", "Prefix to remove from paths. i.e. path to root (multiple allowed)")
+
+ flags.Parse(expandedArgs)
+
+ // Must specify at least one root target.
+ if flags.NArg() == 0 {
+ flags.Usage()
+ os.Exit(2)
+ }
+
+ if len(*outputFile) == 0 {
+ flags.Usage()
+ fmt.Fprintf(os.Stderr, "must specify file for -o; use - for stdout\n")
+ os.Exit(2)
+ } else {
+ dir, err := filepath.Abs(filepath.Dir(*outputFile))
+ if err != nil {
+ fmt.Fprintf(os.Stderr, "cannot determine path to %q: %s\n", *outputFile, err)
+ os.Exit(1)
+ }
+ fi, err := os.Stat(dir)
+ if err != nil {
+ fmt.Fprintf(os.Stderr, "cannot read directory %q of %q: %s\n", dir, *outputFile, err)
+ os.Exit(1)
+ }
+ if !fi.IsDir() {
+ fmt.Fprintf(os.Stderr, "parent %q of %q is not a directory\n", dir, *outputFile)
+ os.Exit(1)
+ }
+ }
+
+ var ofile io.Writer
+ ofile = os.Stdout
+ var obuf *bytes.Buffer
+ if *outputFile != "-" {
+ obuf = &bytes.Buffer{}
+ ofile = obuf
+ }
+
+ ctx := &context{ofile, os.Stderr, compliance.FS, *product, *stripPrefix, actualTime}
+
+ deps, err := sbomGenerator(ctx, flags.Args()...)
+ if err != nil {
+ if err == failNoneRequested {
+ flags.Usage()
+ }
+ fmt.Fprintf(os.Stderr, "%s\n", err.Error())
+ os.Exit(1)
+ }
+
+ if *outputFile != "-" {
+ err := os.WriteFile(*outputFile, obuf.Bytes(), 0666)
+ if err != nil {
+ fmt.Fprintf(os.Stderr, "could not write output to %q: %s\n", *outputFile, err)
+ os.Exit(1)
+ }
+ }
+
+ if *depsFile != "" {
+ err := deptools.WriteDepFile(*depsFile, *outputFile, deps)
+ if err != nil {
+ fmt.Fprintf(os.Stderr, "could not write deps to %q: %s\n", *depsFile, err)
+ os.Exit(1)
+ }
+ }
+ os.Exit(0)
+}
+
+type creationTimeGetter func() time.Time
+
+// actualTime returns current time in UTC
+func actualTime() time.Time {
+ return time.Now().UTC()
+}
+
+// replaceSlashes replaces "/" by "-" for the library path to be used for packages & files SPDXID
+func replaceSlashes(x string) string {
+ return strings.ReplaceAll(x, "/", "-")
+}
+
+// getPackageName returns a package name of a target Node
+func getPackageName(_ *context, tn *compliance.TargetNode) string {
+ return replaceSlashes(tn.Name())
+}
+
+// getDocumentName returns a package name of a target Node
+func getDocumentName(ctx *context, tn *compliance.TargetNode, pm *projectmetadata.ProjectMetadata) string {
+ if len(ctx.product) > 0 {
+ return replaceSlashes(ctx.product)
+ }
+ if len(tn.ModuleName()) > 0 {
+ if pm != nil {
+ return replaceSlashes(pm.Name() + ":" + tn.ModuleName())
+ }
+ return replaceSlashes(tn.ModuleName())
+ }
+
+ // TO DO: Replace tn.Name() with pm.Name() + parts of the target name
+ return replaceSlashes(tn.Name())
+}
+
+// getDownloadUrl returns the download URL if available (GIT, SVN, etc..),
+// or NOASSERTION if not available, none determined or ambiguous
+func getDownloadUrl(_ *context, pm *projectmetadata.ProjectMetadata) string {
+ if pm == nil {
+ return "NOASSERTION"
+ }
+
+ urlsByTypeName := pm.UrlsByTypeName()
+ if urlsByTypeName == nil {
+ return "NOASSERTION"
+ }
+
+ url := urlsByTypeName.DownloadUrl()
+ if url == "" {
+ return "NOASSERTION"
+ }
+ return url
+}
+
+// getProjectMetadata returns the project metadata for the target node
+func getProjectMetadata(_ *context, pmix *projectmetadata.Index,
+ tn *compliance.TargetNode) (*projectmetadata.ProjectMetadata, error) {
+ pms, err := pmix.MetadataForProjects(tn.Projects()...)
+ if err != nil {
+ return nil, fmt.Errorf("Unable to read projects for %q: %w\n", tn, err)
+ }
+ if len(pms) == 0 {
+ return nil, nil
+ }
+
+ // TO DO: skip first element if it doesn't have one of the three info needed
+ return pms[0], nil
+}
+
+// sbomGenerator implements the spdx bom utility
+
+// SBOM is part of the new government regulation issued to improve national cyber security
+// and enhance software supply chain and transparency, see https://www.cisa.gov/sbom
+
+// sbomGenerator uses the SPDX standard, see the SPDX specification (https://spdx.github.io/spdx-spec/)
+// sbomGenerator is also following the internal google SBOM styleguide (http://goto.google.com/spdx-style-guide)
+func sbomGenerator(ctx *context, files ...string) ([]string, error) {
+ // Must be at least one root file.
+ if len(files) < 1 {
+ return nil, failNoneRequested
+ }
+
+ pmix := projectmetadata.NewIndex(ctx.rootFS)
+
+ lg, err := compliance.ReadLicenseGraph(ctx.rootFS, ctx.stderr, files)
+
+ if err != nil {
+ return nil, fmt.Errorf("Unable to read license text file(s) for %q: %v\n", files, err)
+ }
+
+ // implementing the licenses references for the packages
+ licenses := make(map[string]string)
+ concludedLicenses := func(licenseTexts []string) string {
+ licenseRefs := make([]string, 0, len(licenseTexts))
+ for _, licenseText := range licenseTexts {
+ license := strings.SplitN(licenseText, ":", 2)[0]
+ if _, ok := licenses[license]; !ok {
+ licenseRef := "LicenseRef-" + replaceSlashes(license)
+ licenses[license] = licenseRef
+ }
+
+ licenseRefs = append(licenseRefs, licenses[license])
+ }
+ if len(licenseRefs) > 1 {
+ return "(" + strings.Join(licenseRefs, " AND ") + ")"
+ } else if len(licenseRefs) == 1 {
+ return licenseRefs[0]
+ }
+ return "NONE"
+ }
+
+ isMainPackage := true
+ var mainPackage string
+ visitedNodes := make(map[*compliance.TargetNode]struct{})
+
+ // performing a Breadth-first top down walk of licensegraph and building package information
+ compliance.WalkTopDownBreadthFirst(nil, lg,
+ func(lg *compliance.LicenseGraph, tn *compliance.TargetNode, path compliance.TargetEdgePath) bool {
+ if err != nil {
+ return false
+ }
+ var pm *projectmetadata.ProjectMetadata
+ pm, err = getProjectMetadata(ctx, pmix, tn)
+ if err != nil {
+ return false
+ }
+
+ if isMainPackage {
+ mainPackage = getDocumentName(ctx, tn, pm)
+ fmt.Fprintf(ctx.stdout, "SPDXVersion: SPDX-2.2\n")
+ fmt.Fprintf(ctx.stdout, "DataLicense: CC-1.0\n")
+ fmt.Fprintf(ctx.stdout, "DocumentName: %s\n", mainPackage)
+ fmt.Fprintf(ctx.stdout, "SPDXID: SPDXRef-DOCUMENT-%s\n", mainPackage)
+ fmt.Fprintf(ctx.stdout, "DocumentNamespace: Android\n")
+ fmt.Fprintf(ctx.stdout, "Creator: Organization: Google LLC\n")
+ fmt.Fprintf(ctx.stdout, "Created: %s\n", ctx.creationTime().Format("2006-01-02T15:04:05Z"))
+ isMainPackage = false
+ }
+
+ relationships := make([]string, 0, 1)
+ defer func() {
+ if r := recover(); r != nil {
+ panic(r)
+ }
+ for _, relationship := range relationships {
+ fmt.Fprintln(ctx.stdout, relationship)
+ }
+ }()
+ if len(path) == 0 {
+ relationships = append(relationships,
+ fmt.Sprintf("Relationship: SPDXRef-DOCUMENT-%s DESCRIBES SPDXRef-Package-%s",
+ mainPackage, getPackageName(ctx, tn)))
+ } else {
+ // Check parent and identify annotation
+ parent := path[len(path)-1]
+ targetEdge := parent.Edge()
+ if targetEdge.IsRuntimeDependency() {
+ // Adding the dynamic link annotation RUNTIME_DEPENDENCY_OF relationship
+ relationships = append(relationships, fmt.Sprintf("Relationship: SPDXRef-Package-%s RUNTIME_DEPENDENCY_OF SPDXRef-Package-%s", getPackageName(ctx, tn), getPackageName(ctx, targetEdge.Target())))
+
+ } else if targetEdge.IsDerivation() {
+ // Adding the derivation annotation as a CONTAINS relationship
+ relationships = append(relationships, fmt.Sprintf("Relationship: SPDXRef-Package-%s CONTAINS SPDXRef-Package-%s", getPackageName(ctx, targetEdge.Target()), getPackageName(ctx, tn)))
+
+ } else if targetEdge.IsBuildTool() {
+ // Adding the toolchain annotation as a BUILD_TOOL_OF relationship
+ relationships = append(relationships, fmt.Sprintf("Relationship: SPDXRef-Package-%s BUILD_TOOL_OF SPDXRef-Package-%s", getPackageName(ctx, tn), getPackageName(ctx, targetEdge.Target())))
+ } else {
+ panic(fmt.Errorf("Unknown dependency type: %v", targetEdge.Annotations()))
+ }
+ }
+
+ if _, alreadyVisited := visitedNodes[tn]; alreadyVisited {
+ return false
+ }
+ visitedNodes[tn] = struct{}{}
+ pkgName := getPackageName(ctx, tn)
+ fmt.Fprintf(ctx.stdout, "##### Package: %s\n", strings.Replace(pkgName, "-", "/", -2))
+ fmt.Fprintf(ctx.stdout, "PackageName: %s\n", pkgName)
+ if pm != nil && pm.Version() != "" {
+ fmt.Fprintf(ctx.stdout, "PackageVersion: %s\n", pm.Version())
+ }
+ fmt.Fprintf(ctx.stdout, "SPDXID: SPDXRef-Package-%s\n", pkgName)
+ fmt.Fprintf(ctx.stdout, "PackageDownloadLocation: %s\n", getDownloadUrl(ctx, pm))
+ fmt.Fprintf(ctx.stdout, "PackageLicenseConcluded: %s\n", concludedLicenses(tn.LicenseTexts()))
+ return true
+ })
+
+ fmt.Fprintf(ctx.stdout, "##### Non-standard license:\n")
+
+ licenseTexts := make([]string, 0, len(licenses))
+
+ for licenseText := range licenses {
+ licenseTexts = append(licenseTexts, licenseText)
+ }
+
+ sort.Strings(licenseTexts)
+
+ for _, licenseText := range licenseTexts {
+ fmt.Fprintf(ctx.stdout, "LicenseID: %s\n", licenses[licenseText])
+ // open the file
+ f, err := ctx.rootFS.Open(filepath.Clean(licenseText))
+ if err != nil {
+ return nil, fmt.Errorf("error opening license text file %q: %w", licenseText, err)
+ }
+
+ // read the file
+ text, err := io.ReadAll(f)
+ if err != nil {
+ return nil, fmt.Errorf("error reading license text file %q: %w", licenseText, err)
+ }
+ // adding the extracted license text
+ fmt.Fprintf(ctx.stdout, "ExtractedText: %v\n", string(text))
+ }
+
+ deps := licenseTexts
+ return deps, nil
+}
diff --git a/tools/compliance/cmd/sbom/sbom_test.go b/tools/compliance/cmd/sbom/sbom_test.go
new file mode 100644
index 0000000000..5e70580137
--- /dev/null
+++ b/tools/compliance/cmd/sbom/sbom_test.go
@@ -0,0 +1,1629 @@
+// Copyright 2022 Google LLC
+//
+// 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 main
+
+import (
+ "bufio"
+ "bytes"
+ "fmt"
+ "os"
+ "reflect"
+ "regexp"
+ "strings"
+ "testing"
+ "time"
+
+ "android/soong/tools/compliance"
+)
+
+var (
+ spdxVersionTag = regexp.MustCompile(`^\s*SPDXVersion: SPDX-2.2\s*$`)
+ spdxDataLicenseTag = regexp.MustCompile(`^\s*DataLicense: CC-1.0\s*$`)
+ spdxDocumentNameTag = regexp.MustCompile(`^\s*DocumentName:\s*Android*\s*$`)
+ spdxIDTag = regexp.MustCompile(`^\s*SPDXID:\s*SPDXRef-DOCUMENT-(.*)\s*$`)
+ spdxDocumentNameSpaceTag = regexp.MustCompile(`^\s*DocumentNamespace:\s*Android\s*$`)
+ spdxCreatorOrganizationTag = regexp.MustCompile(`^\s*Creator:\s*Organization:\s*Google LLC\s*$`)
+ spdxCreatedTimeTag = regexp.MustCompile(`^\s*Created: 1970-01-01T00:00:00Z\s*$`)
+ spdxPackageTag = regexp.MustCompile(`^\s*#####\s*Package:\s*(.*)\s*$`)
+ spdxPackageNameTag = regexp.MustCompile(`^\s*PackageName:\s*(.*)\s*$`)
+ spdxPkgIDTag = regexp.MustCompile(`^\s*SPDXID:\s*SPDXRef-Package-(.*)\s*$`)
+ spdxPkgDownloadLocationTag = regexp.MustCompile(`^\s*PackageDownloadLocation:\s*NOASSERTION\s*$`)
+ spdxPkgLicenseDeclaredTag = regexp.MustCompile(`^\s*PackageLicenseConcluded:\s*LicenseRef-(.*)\s*$`)
+ spdxRelationshipTag = regexp.MustCompile(`^\s*Relationship:\s*SPDXRef-(.*)\s*(DESCRIBES|CONTAINS|BUILD_TOOL_OF|RUNTIME_DEPENDENCY_OF)\s*SPDXRef-Package-(.*)\s*$`)
+ spdxLicenseTag = regexp.MustCompile(`^\s*##### Non-standard license:\s*$`)
+ spdxLicenseIDTag = regexp.MustCompile(`^\s*LicenseID: LicenseRef-(.*)\s*$`)
+ spdxExtractedTextTag = regexp.MustCompile(`^\s*ExtractedText:\s*(.*)\s*$`)
+ spdxExtractedClosingTextTag = regexp.MustCompile(`^\s*\s*$`)
+)
+
+func TestMain(m *testing.M) {
+ // Change into the parent directory before running the tests
+ // so they can find the testdata directory.
+ if err := os.Chdir(".."); err != nil {
+ fmt.Printf("failed to change to testdata directory: %s\n", err)
+ os.Exit(1)
+ }
+ os.Exit(m.Run())
+}
+
+func Test(t *testing.T) {
+ tests := []struct {
+ condition string
+ name string
+ outDir string
+ roots []string
+ stripPrefix string
+ expectedOut []matcher
+ expectedDeps []string
+ }{
+ {
+ condition: "firstparty",
+ name: "apex",
+ roots: []string{"highest.apex.meta_lic"},
+ expectedOut: []matcher{
+ spdxVersion{},
+ spdxDataLicense{},
+ spdxDocumentName{"Android"},
+ spdxID{"Android"},
+ spdxDocumentNameSpace{},
+ spdxCreatorOrganization{},
+ spdxCreatedTime{},
+ packageTag{"testdata/firstparty/highest.apex.meta_lic"},
+ packageName{"testdata/firstparty/highest.apex.meta_lic"},
+ spdxPkgID{"testdata/firstparty/highest.apex.meta_lic"},
+ spdxPkgDownloadLocation{"NOASSERTION"},
+ spdxPkgLicenseDeclared{"testdata-firstparty-FIRST_PARTY_LICENSE"},
+ spdxRelationship{"DOCUMENT-Android ", "testdata-firstparty-highest.apex.meta_lic", "DESCRIBES"},
+ packageTag{"testdata/firstparty/bin/bin1.meta_lic"},
+ packageName{"testdata/firstparty/bin/bin1.meta_lic"},
+ spdxPkgID{"testdata/firstparty/bin/bin1.meta_lic"},
+ spdxPkgDownloadLocation{"NOASSERTION"},
+ spdxPkgLicenseDeclared{"testdata-firstparty-FIRST_PARTY_LICENSE"},
+ spdxRelationship{"Package-testdata/firstparty/highest.apex.meta_lic ", "testdata/firstparty/bin/bin1.meta_lic", "CONTAINS"},
+ packageTag{"testdata/firstparty/bin/bin2.meta_lic"},
+ packageName{"testdata/firstparty/bin/bin2.meta_lic"},
+ spdxPkgID{"testdata/firstparty/bin/bin2.meta_lic"},
+ spdxPkgDownloadLocation{"NOASSERTION"},
+ spdxPkgLicenseDeclared{"testdata-firstparty-FIRST_PARTY_LICENSE"},
+ spdxRelationship{"Package-testdata/firstparty/highest.apex.meta_lic ", "testdata-firstparty-bin-bin2.meta_lic", "CONTAINS"},
+ packageTag{"testdata/firstparty/lib/liba.so.meta_lic"},
+ packageName{"testdata/firstparty/lib/liba.so.meta_lic"},
+ spdxPkgID{"testdata/firstparty/lib/liba.so.meta_lic"},
+ spdxPkgDownloadLocation{"NOASSERTION"},
+ spdxPkgLicenseDeclared{"testdata-firstparty-FIRST_PARTY_LICENSE"},
+ spdxRelationship{"Package-testdata/firstparty/highest.apex.meta_lic ", "testdata/firstparty/lib/liba.so.meta_lic", "CONTAINS"},
+ packageTag{"testdata/firstparty/lib/libb.so.meta_lic"},
+ packageName{"testdata/firstparty/lib/libb.so.meta_lic"},
+ spdxPkgID{"testdata/firstparty/lib/libb.so.meta_lic"},
+ spdxPkgDownloadLocation{"NOASSERTION"},
+ spdxPkgLicenseDeclared{"testdata-firstparty-FIRST_PARTY_LICENSE"},
+ spdxRelationship{"Package-testdata/firstparty/highest.apex.meta_lic ", "testdata/firstparty/lib/libb.so.meta_lic", "CONTAINS"},
+ spdxRelationship{"Package-testdata/firstparty/bin/bin1.meta_lic ", "testdata/firstparty/lib/liba.so.meta_lic", "CONTAINS"},
+ packageTag{"testdata/firstparty/lib/libc.a.meta_lic"},
+ packageName{"testdata/firstparty/lib/libc.a.meta_lic"},
+ spdxPkgID{"testdata/firstparty/lib/libc.a.meta_lic"},
+ spdxPkgDownloadLocation{"NOASSERTION"},
+ spdxPkgLicenseDeclared{"testdata-firstparty-FIRST_PARTY_LICENSE"},
+ spdxRelationship{"Package-testdata-firstparty-bin-bin1.meta_lic ", "testdata/firstparty/lib/libc.a.meta_lic", "CONTAINS"},
+ spdxRelationship{"Package-testdata/firstparty/lib/libb.so.meta_lic ", "testdata/firstparty/bin/bin2.meta_lic", "RUNTIME_DEPENDENCY_OF"},
+ packageTag{"testdata/firstparty/lib/libd.so.meta_lic"},
+ packageName{"testdata/firstparty/lib/libd.so.meta_lic"},
+ spdxPkgID{"testdata/firstparty/lib/libd.so.meta_lic"},
+ spdxPkgDownloadLocation{"NOASSERTION"},
+ spdxPkgLicenseDeclared{"testdata-firstparty-FIRST_PARTY_LICENSE"},
+ spdxRelationship{"Package-testdata/firstparty/lib/libd.so.meta_lic ", "testdata/firstparty/bin/bin2.meta_lic", "RUNTIME_DEPENDENCY_OF"},
+ spdxLicense{},
+ spdxLicenseID{"testdata-firstparty-FIRST_PARTY_LICENSE"},
+ spdxExtractedText{"&&&First Party License&&&"},
+ spdxExtractedClosingText{},
+ },
+ expectedDeps: []string{"testdata/firstparty/FIRST_PARTY_LICENSE"},
+ },
+ {
+ condition: "firstparty",
+ name: "application",
+ roots: []string{"application.meta_lic"},
+ expectedOut: []matcher{
+ spdxVersion{},
+ spdxDataLicense{},
+ spdxDocumentName{"Android"},
+ spdxID{"Android"},
+ spdxDocumentNameSpace{},
+ spdxCreatorOrganization{},
+ spdxCreatedTime{},
+ packageTag{"testdata/firstparty/application.meta_lic"},
+ packageName{"testdata/firstparty/application.meta_lic"},
+ spdxPkgID{"testdata/firstparty/application.meta_lic"},
+ spdxPkgDownloadLocation{"NOASSERTION"},
+ spdxPkgLicenseDeclared{"testdata-firstparty-FIRST_PARTY_LICENSE"},
+ spdxRelationship{"DOCUMENT-Android ", "testdata/firstparty/application.meta_lic", "DESCRIBES"},
+ packageTag{"testdata/firstparty/bin/bin3.meta_lic"},
+ packageName{"testdata/firstparty/bin/bin3.meta_lic"},
+ spdxPkgID{"testdata/firstparty/bin/bin3.meta_lic"},
+ spdxPkgDownloadLocation{"NOASSERTION"},
+ spdxPkgLicenseDeclared{"testdata-firstparty-FIRST_PARTY_LICENSE"},
+ spdxRelationship{"Package-testdata/firstparty/bin/bin3.meta_lic ", "testdata-firstparty-application.meta_lic", "BUILD_TOOL_OF"},
+ packageTag{"testdata/firstparty/lib/liba.so.meta_lic"},
+ packageName{"testdata/firstparty/lib/liba.so.meta_lic"},
+ spdxPkgID{"testdata/firstparty/lib/liba.so.meta_lic"},
+ spdxPkgDownloadLocation{"NOASSERTION"},
+ spdxPkgLicenseDeclared{"testdata-firstparty-FIRST_PARTY_LICENSE"},
+ spdxRelationship{"Package-testdata/firstparty/application.meta_lic ", "testdata/firstparty/lib/liba.so.meta_lic", "CONTAINS"},
+ packageTag{"testdata/firstparty/lib/libb.so.meta_lic"},
+ packageName{"testdata/firstparty/lib/libb.so.meta_lic"},
+ spdxPkgID{"testdata/firstparty/lib/libb.so.meta_lic"},
+ spdxPkgDownloadLocation{"NOASSERTION"},
+ spdxPkgLicenseDeclared{"testdata-firstparty-FIRST_PARTY_LICENSE"},
+ spdxRelationship{"Package-testdata/firstparty/lib/libb.so.meta_lic ", "testdata-firstparty-application.meta_lic", "RUNTIME_DEPENDENCY_OF"},
+ spdxLicense{},
+ spdxLicenseID{"testdata-firstparty-FIRST_PARTY_LICENSE"},
+ spdxExtractedText{"&&&First Party License&&&"},
+ spdxExtractedClosingText{},
+ },
+ expectedDeps: []string{"testdata/firstparty/FIRST_PARTY_LICENSE"},
+ },
+ {
+ condition: "firstparty",
+ name: "container",
+ roots: []string{"container.zip.meta_lic"},
+ expectedOut: []matcher{
+ spdxVersion{},
+ spdxDataLicense{},
+ spdxDocumentName{"Android"},
+ spdxID{"Android"},
+ spdxDocumentNameSpace{},
+ spdxCreatorOrganization{},
+ spdxCreatedTime{},
+ packageTag{"testdata/firstparty/container.zip.meta_lic"},
+ packageName{"testdata/firstparty/container.zip.meta_lic"},
+ spdxPkgID{"testdata/firstparty/container.zip.meta_lic"},
+ spdxPkgDownloadLocation{"NOASSERTION"},
+ spdxPkgLicenseDeclared{"testdata-firstparty-FIRST_PARTY_LICENSE"},
+ spdxRelationship{"DOCUMENT-Android ", "testdata/firstparty/container.zip.meta_lic", "DESCRIBES"},
+ packageTag{"testdata/firstparty/bin/bin1.meta_lic"},
+ packageName{"testdata/firstparty/bin/bin1.meta_lic"},
+ spdxPkgID{"testdata/firstparty/bin/bin1.meta_lic"},
+ spdxPkgDownloadLocation{"NOASSERTION"},
+ spdxPkgLicenseDeclared{"testdata-firstparty-FIRST_PARTY_LICENSE"},
+ spdxRelationship{"Package-testdata/firstparty/container.zip.meta_lic ", "testdata/firstparty/bin/bin1.meta_lic", "CONTAINS"},
+ packageTag{"testdata/firstparty/bin/bin2.meta_lic"},
+ packageName{"testdata/firstparty/bin/bin2.meta_lic"},
+ spdxPkgID{"testdata/firstparty/bin/bin2.meta_lic"},
+ spdxPkgDownloadLocation{"NOASSERTION"},
+ spdxPkgLicenseDeclared{"testdata-firstparty-FIRST_PARTY_LICENSE"},
+ spdxRelationship{"Package-testdata/firstparty/container.zip.meta_lic ", "testdata/firstparty/bin/bin2.meta_lic", "CONTAINS"},
+ packageTag{"testdata/firstparty/lib/liba.so.meta_lic"},
+ packageName{"testdata/firstparty/lib/liba.so.meta_lic"},
+ spdxPkgID{"testdata/firstparty/lib/liba.so.meta_lic"},
+ spdxPkgDownloadLocation{"NOASSERTION"},
+ spdxPkgLicenseDeclared{"testdata-firstparty-FIRST_PARTY_LICENSE"},
+ spdxRelationship{"Package-testdata/firstparty/container.zip.meta_lic ", "testdata/firstparty/lib/liba.so.meta_lic", "CONTAINS"},
+ packageTag{"testdata/firstparty/lib/libb.so.meta_lic"},
+ packageName{"testdata/firstparty/lib/libb.so.meta_lic"},
+ spdxPkgID{"testdata/firstparty/lib/libb.so.meta_lic"},
+ spdxPkgDownloadLocation{"NOASSERTION"},
+ spdxPkgLicenseDeclared{"testdata-firstparty-FIRST_PARTY_LICENSE"},
+ spdxRelationship{"Package-testdata/firstparty/container.zip.meta_lic ", "testdata/firstparty/lib/libb.so.meta_lic", "CONTAINS"},
+ spdxRelationship{"Package-testdata/firstparty/bin/bin1.meta_lic ", "testdata/firstparty/lib/liba.so.meta_lic", "CONTAINS"},
+ packageTag{"testdata/firstparty/lib/libc.a.meta_lic"},
+ packageName{"testdata/firstparty/lib/libc.a.meta_lic"},
+ spdxPkgID{"testdata/firstparty/lib/libc.a.meta_lic"},
+ spdxPkgDownloadLocation{"NOASSERTION"},
+ spdxPkgLicenseDeclared{"testdata-firstparty-FIRST_PARTY_LICENSE"},
+ spdxRelationship{"Package-testdata/firstparty/bin/bin1.meta_lic ", "testdata/firstparty/lib/libc.a.meta_lic", "CONTAINS"},
+ spdxRelationship{"Package-testdata/firstparty/lib/libb.so.meta_lic ", "testdata/firstparty/bin/bin2.meta_lic", "RUNTIME_DEPENDENCY_OF"},
+ packageTag{"testdata/firstparty/lib/libd.so.meta_lic"},
+ packageName{"testdata/firstparty/lib/libd.so.meta_lic"},
+ spdxPkgID{"testdata/firstparty/lib/libd.so.meta_lic"},
+ spdxPkgDownloadLocation{"NOASSERTION"},
+ spdxPkgLicenseDeclared{"testdata-firstparty-FIRST_PARTY_LICENSE"},
+ spdxRelationship{"Package-testdata/firstparty/lib/libd.so.meta_lic ", "testdata/firstparty/bin/bin2.meta_lic", "RUNTIME_DEPENDENCY_OF"},
+ spdxLicense{},
+ spdxLicenseID{"testdata-firstparty-FIRST_PARTY_LICENSE"},
+ spdxExtractedText{"&&&First Party License&&&"},
+ spdxExtractedClosingText{},
+ },
+ expectedDeps: []string{"testdata/firstparty/FIRST_PARTY_LICENSE"},
+ },
+ {
+ condition: "firstparty",
+ name: "binary",
+ roots: []string{"bin/bin1.meta_lic"},
+ expectedOut: []matcher{
+ spdxVersion{},
+ spdxDataLicense{},
+ spdxDocumentName{"Android"},
+ spdxID{"Android"},
+ spdxDocumentNameSpace{},
+ spdxCreatorOrganization{},
+ spdxCreatedTime{},
+ packageTag{"testdata/firstparty/bin/bin1.meta_lic"},
+ packageName{"testdata/firstparty/bin/bin1.meta_lic"},
+ spdxPkgID{"testdata/firstparty/bin/bin1.meta_lic"},
+ spdxPkgDownloadLocation{"NOASSERTION"},
+ spdxPkgLicenseDeclared{"testdata-firstparty-FIRST_PARTY_LICENSE"},
+ spdxRelationship{"DOCUMENT-Android ", "testdata/firstparty/bin/bin1.meta_lic", "DESCRIBES"},
+ packageTag{"testdata/firstparty/lib/liba.so.meta_lic"},
+ packageName{"testdata/firstparty/lib/liba.so.meta_lic"},
+ spdxPkgID{"testdata/firstparty/lib/liba.so.meta_lic"},
+ spdxPkgDownloadLocation{"NOASSERTION"},
+ spdxPkgLicenseDeclared{"testdata-firstparty-FIRST_PARTY_LICENSE"},
+ spdxRelationship{"Package-testdata/firstparty/bin/bin1.meta_lic ", "testdata/firstparty/lib/liba.so.meta_lic", "CONTAINS"},
+ packageTag{"testdata/firstparty/lib/libc.a.meta_lic"},
+ packageName{"testdata/firstparty/lib/libc.a.meta_lic"},
+ spdxPkgID{"testdata/firstparty/lib/libc.a.meta_lic"},
+ spdxPkgDownloadLocation{"NOASSERTION"},
+ spdxPkgLicenseDeclared{"testdata-firstparty-FIRST_PARTY_LICENSE"},
+ spdxRelationship{"Package-testdata/firstparty/bin/bin1.meta_lic ", "testdata/firstparty/lib/libc.a.meta_lic", "CONTAINS"},
+ spdxLicense{},
+ spdxLicenseID{"testdata-firstparty-FIRST_PARTY_LICENSE"},
+ spdxExtractedText{"&&&First Party License&&&"},
+ spdxExtractedClosingText{},
+ },
+ expectedDeps: []string{"testdata/firstparty/FIRST_PARTY_LICENSE"},
+ },
+ {
+ condition: "firstparty",
+ name: "library",
+ roots: []string{"lib/libd.so.meta_lic"},
+ expectedOut: []matcher{
+ spdxVersion{},
+ spdxDataLicense{},
+ spdxDocumentName{"Android"},
+ spdxID{"Android"},
+ spdxDocumentNameSpace{},
+ spdxCreatorOrganization{},
+ spdxCreatedTime{},
+ packageTag{"testdata/firstparty/lib/libd.so.meta_lic"},
+ packageName{"testdata/firstparty/lib/libd.so.meta_lic"},
+ spdxPkgID{"testdata/firstparty/lib/libd.so.meta_lic"},
+ spdxPkgDownloadLocation{"NOASSERTION"},
+ spdxPkgLicenseDeclared{"testdata-firstparty-FIRST_PARTY_LICENSE"},
+ spdxRelationship{"DOCUMENT-Android ", "testdata/firstparty/lib/libd.so.meta_lic", "DESCRIBES"},
+ spdxLicense{},
+ spdxLicenseID{"testdata-firstparty-FIRST_PARTY_LICENSE"},
+ spdxExtractedText{"&&&First Party License&&&"},
+ spdxExtractedClosingText{},
+ },
+ expectedDeps: []string{"testdata/firstparty/FIRST_PARTY_LICENSE"},
+ },
+ {
+ condition: "notice",
+ name: "apex",
+ roots: []string{"highest.apex.meta_lic"},
+ expectedOut: []matcher{
+ spdxVersion{},
+ spdxDataLicense{},
+ spdxDocumentName{"Android"},
+ spdxID{"Android"},
+ spdxDocumentNameSpace{},
+ spdxCreatorOrganization{},
+ spdxCreatedTime{},
+ packageTag{"testdata/notice/highest.apex.meta_lic"},
+ packageName{"testdata/notice/highest.apex.meta_lic"},
+ spdxPkgID{"testdata/notice/highest.apex.meta_lic"},
+ spdxPkgDownloadLocation{"NOASSERTION"},
+ spdxPkgLicenseDeclared{"testdata-firstparty-FIRST_PARTY_LICENSE"},
+ spdxRelationship{"DOCUMENT-Android ", "testdata/notice/highest.apex.meta_lic", "DESCRIBES"},
+ packageTag{"testdata/notice/bin/bin1.meta_lic"},
+ packageName{"testdata/notice/bin/bin1.meta_lic"},
+ spdxPkgID{"testdata/notice/bin/bin1.meta_lic"},
+ spdxPkgDownloadLocation{"NOASSERTION"},
+ spdxPkgLicenseDeclared{"testdata-firstparty-FIRST_PARTY_LICENSE"},
+ spdxRelationship{"Package-testdata/notice/highest.apex.meta_lic ", "testdata/notice/bin/bin1.meta_lic", "CONTAINS"},
+ packageTag{"testdata/notice/bin/bin2.meta_lic"},
+ packageName{"testdata/notice/bin/bin2.meta_lic"},
+ spdxPkgID{"testdata/notice/bin/bin2.meta_lic"},
+ spdxPkgDownloadLocation{"NOASSERTION"},
+ spdxPkgLicenseDeclared{"testdata-firstparty-FIRST_PARTY_LICENSE"},
+ spdxRelationship{"Package-testdata/notice/highest.apex.meta_lic ", "testdata/notice/bin/bin2.meta_lic", "CONTAINS"},
+ packageTag{"testdata/notice/lib/liba.so.meta_lic"},
+ packageName{"testdata/notice/lib/liba.so.meta_lic"},
+ spdxPkgID{"testdata/notice/lib/liba.so.meta_lic"},
+ spdxPkgDownloadLocation{"NOASSERTION"},
+ spdxPkgLicenseDeclared{"testdata-notice-NOTICE_LICENSE"},
+ spdxRelationship{"Package-testdata/notice/highest.apex.meta_lic ", "testdata/notice/lib/liba.so.meta_lic", "CONTAINS"},
+ packageTag{"testdata/notice/lib/libb.so.meta_lic"},
+ packageName{"testdata/notice/lib/libb.so.meta_lic"},
+ spdxPkgID{"testdata/notice/lib/libb.so.meta_lic"},
+ spdxPkgDownloadLocation{"NOASSERTION"},
+ spdxPkgLicenseDeclared{"testdata-firstparty-FIRST_PARTY_LICENSE"},
+ spdxRelationship{"Package-testdata/notice/highest.apex.meta_lic ", "testdata/notice/lib/libb.so.meta_lic", "CONTAINS"},
+ spdxRelationship{"Package-testdata/notice/bin/bin1.meta_lic ", "testdata/notice/lib/liba.so.meta_lic", "CONTAINS"},
+ packageTag{"testdata/notice/lib/libc.a.meta_lic"},
+ packageName{"testdata/notice/lib/libc.a.meta_lic"},
+ spdxPkgID{"testdata/notice/lib/libc.a.meta_lic"},
+ spdxPkgDownloadLocation{"NOASSERTION"},
+ spdxPkgLicenseDeclared{"testdata-notice-NOTICE_LICENSE"},
+ spdxRelationship{"Package-testdata/notice/bin/bin1.meta_lic ", "testdata/notice/lib/libc.a.meta_lic", "CONTAINS"},
+ spdxRelationship{"Package-testdata/notice/lib/libb.so.meta_lic ", "testdata/notice/bin/bin2.meta_lic", "RUNTIME_DEPENDENCY_OF"},
+ packageTag{"testdata/notice/lib/libd.so.meta_lic"},
+ packageName{"testdata/notice/lib/libd.so.meta_lic"},
+ spdxPkgID{"testdata/notice/lib/libd.so.meta_lic"},
+ spdxPkgDownloadLocation{"NOASSERTION"},
+ spdxPkgLicenseDeclared{"testdata-notice-NOTICE_LICENSE"},
+ spdxRelationship{"Package-testdata/notice/lib/libd.so.meta_lic ", "testdata/notice/bin/bin2.meta_lic", "RUNTIME_DEPENDENCY_OF"},
+ spdxLicense{},
+ spdxLicenseID{"testdata-firstparty-FIRST_PARTY_LICENSE"},
+ spdxExtractedText{"&&&First Party License&&&"},
+ spdxExtractedClosingText{},
+ spdxLicenseID{"testdata-notice-NOTICE_LICENSE"},
+ spdxExtractedText{"%%%Notice License%%%"},
+ spdxExtractedClosingText{},
+ },
+ expectedDeps: []string{
+ "testdata/firstparty/FIRST_PARTY_LICENSE",
+ "testdata/notice/NOTICE_LICENSE",
+ },
+ },
+ {
+ condition: "notice",
+ name: "container",
+ roots: []string{"container.zip.meta_lic"},
+ expectedOut: []matcher{
+ spdxVersion{},
+ spdxDataLicense{},
+ spdxDocumentName{"Android"},
+ spdxID{"Android"},
+ spdxDocumentNameSpace{},
+ spdxCreatorOrganization{},
+ spdxCreatedTime{},
+ packageTag{"testdata/notice/container.zip.meta_lic"},
+ packageName{"testdata/notice/container.zip.meta_lic"},
+ spdxPkgID{"testdata/notice/container.zip.meta_lic"},
+ spdxPkgDownloadLocation{"NOASSERTION"},
+ spdxPkgLicenseDeclared{"testdata-firstparty-FIRST_PARTY_LICENSE"},
+ spdxRelationship{"DOCUMENT-Android ", "testdata/notice/container.zip.meta_lic", "DESCRIBES"},
+ packageTag{"testdata/notice/bin/bin1.meta_lic"},
+ packageName{"testdata/notice/bin/bin1.meta_lic"},
+ spdxPkgID{"testdata/notice/bin/bin1.meta_lic"},
+ spdxPkgDownloadLocation{"NOASSERTION"},
+ spdxPkgLicenseDeclared{"testdata-firstparty-FIRST_PARTY_LICENSE"},
+ spdxRelationship{"Package-testdata/notice/container.zip.meta_lic ", "testdata/notice/bin/bin1.meta_lic", "CONTAINS"},
+ packageTag{"testdata/notice/bin/bin2.meta_lic"},
+ packageName{"testdata/notice/bin/bin2.meta_lic"},
+ spdxPkgID{"testdata/notice/bin/bin2.meta_lic"},
+ spdxPkgDownloadLocation{"NOASSERTION"},
+ spdxPkgLicenseDeclared{"testdata-firstparty-FIRST_PARTY_LICENSE"},
+ spdxRelationship{"Package-testdata/notice/container.zip.meta_lic ", "testdata/notice/bin/bin2.meta_lic", "CONTAINS"},
+ packageTag{"testdata/notice/lib/liba.so.meta_lic"},
+ packageName{"testdata/notice/lib/liba.so.meta_lic"},
+ spdxPkgID{"testdata/notice/lib/liba.so.meta_lic"},
+ spdxPkgDownloadLocation{"NOASSERTION"},
+ spdxPkgLicenseDeclared{"testdata-notice-NOTICE_LICENSE"},
+ spdxRelationship{"Package-testdata/notice/container.zip.meta_lic ", "testdata/notice/lib/liba.so.meta_lic", "CONTAINS"},
+ packageTag{"testdata/notice/lib/libb.so.meta_lic"},
+ packageName{"testdata/notice/lib/libb.so.meta_lic"},
+ spdxPkgID{"testdata/notice/lib/libb.so.meta_lic"},
+ spdxPkgDownloadLocation{"NOASSERTION"},
+ spdxPkgLicenseDeclared{"testdata-firstparty-FIRST_PARTY_LICENSE"},
+ spdxRelationship{"Package-testdata/notice/container.zip.meta_lic ", "testdata/notice/lib/libb.so.meta_lic", "CONTAINS"},
+ spdxRelationship{"Package-testdata/notice/bin/bin1.meta_lic ", "testdata/notice/lib/liba.so.meta_lic", "CONTAINS"},
+ packageTag{"testdata/notice/lib/libc.a.meta_lic"},
+ packageName{"testdata/notice/lib/libc.a.meta_lic"},
+ spdxPkgID{"testdata/notice/lib/libc.a.meta_lic"},
+ spdxPkgDownloadLocation{"NOASSERTION"},
+ spdxPkgLicenseDeclared{"testdata-notice-NOTICE_LICENSE"},
+ spdxRelationship{"Package-testdata/notice/bin/bin1.meta_lic ", "testdata/notice/lib/libc.a.meta_lic", "CONTAINS"},
+ spdxRelationship{"Package-testdata/notice/lib/libb.so.meta_lic ", "testdata/notice/bin/bin2.meta_lic", "RUNTIME_DEPENDENCY_OF"},
+ packageTag{"testdata/notice/lib/libd.so.meta_lic"},
+ packageName{"testdata/notice/lib/libd.so.meta_lic"},
+ spdxPkgID{"testdata/notice/lib/libd.so.meta_lic"},
+ spdxPkgDownloadLocation{"NOASSERTION"},
+ spdxPkgLicenseDeclared{"testdata-notice-NOTICE_LICENSE"},
+ spdxRelationship{"Package-testdata/notice/lib/libd.so.meta_lic ", "testdata/notice/bin/bin2.meta_lic", "RUNTIME_DEPENDENCY_OF"},
+ spdxLicense{},
+ spdxLicenseID{"testdata-firstparty-FIRST_PARTY_LICENSE"},
+ spdxExtractedText{"&&&First Party License&&&"},
+ spdxExtractedClosingText{},
+ spdxLicenseID{"testdata-notice-NOTICE_LICENSE"},
+ spdxExtractedText{"%%%Notice License%%%"},
+ spdxExtractedClosingText{},
+ },
+ expectedDeps: []string{
+ "testdata/firstparty/FIRST_PARTY_LICENSE",
+ "testdata/notice/NOTICE_LICENSE",
+ },
+ },
+ {
+ condition: "notice",
+ name: "application",
+ roots: []string{"application.meta_lic"},
+ expectedOut: []matcher{
+ spdxVersion{},
+ spdxDataLicense{},
+ spdxDocumentName{"Android"},
+ spdxID{"Android"},
+ spdxDocumentNameSpace{},
+ spdxCreatorOrganization{},
+ spdxCreatedTime{},
+ packageTag{"testdata/notice/application.meta_lic"},
+ packageName{"testdata/notice/application.meta_lic"},
+ spdxPkgID{"testdata/notice/application.meta_lic"},
+ spdxPkgDownloadLocation{"NOASSERTION"},
+ spdxPkgLicenseDeclared{"testdata-firstparty-FIRST_PARTY_LICENSE"},
+ spdxRelationship{"DOCUMENT-Android ", "testdata-notice-application.meta_lic", "DESCRIBES"},
+ packageTag{"testdata/notice/bin/bin3.meta_lic"},
+ packageName{"testdata/notice/bin/bin3.meta_lic"},
+ spdxPkgID{"testdata/notice/bin/bin3.meta_lic"},
+ spdxPkgDownloadLocation{"NOASSERTION"},
+ spdxPkgLicenseDeclared{"testdata-notice-NOTICE_LICENSE"},
+ spdxRelationship{"Package-testdata-notice-bin-bin3.meta_lic ", "testdata/notice/application.meta_lic", "BUILD_TOOL_OF"},
+ packageTag{"testdata/notice/lib/liba.so.meta_lic"},
+ packageName{"testdata/notice/lib/liba.so.meta_lic"},
+ spdxPkgID{"testdata/notice/lib/liba.so.meta_lic"},
+ spdxPkgDownloadLocation{"NOASSERTION"},
+ spdxPkgLicenseDeclared{"testdata-notice-NOTICE_LICENSE"},
+ spdxRelationship{"Package-testdata/notice/application.meta_lic ", "testdata-notice-lib-liba.so.meta_lic", "CONTAINS"},
+ packageTag{"testdata/notice/lib/libb.so.meta_lic"},
+ packageName{"testdata/notice/lib/libb.so.meta_lic"},
+ spdxPkgID{"testdata/notice/lib/libb.so.meta_lic"},
+ spdxPkgDownloadLocation{"NOASSERTION"},
+ spdxPkgLicenseDeclared{"testdata-firstparty-FIRST_PARTY_LICENSE"},
+ spdxRelationship{"Package-testdata-notice-lib-libb.so.meta_lic ", "testdata/notice/application.meta_lic", "RUNTIME_DEPENDENCY_OF"},
+ spdxLicense{},
+ spdxLicenseID{"testdata-firstparty-FIRST_PARTY_LICENSE"},
+ spdxExtractedText{"&&&First Party License&&&"},
+ spdxExtractedClosingText{},
+ spdxLicenseID{"testdata-notice-NOTICE_LICENSE"},
+ spdxExtractedText{"%%%Notice License%%%"},
+ spdxExtractedClosingText{},
+ },
+ expectedDeps: []string{
+ "testdata/firstparty/FIRST_PARTY_LICENSE",
+ "testdata/notice/NOTICE_LICENSE",
+ },
+ },
+ {
+ condition: "notice",
+ name: "binary",
+ roots: []string{"bin/bin1.meta_lic"},
+ expectedOut: []matcher{
+ spdxVersion{},
+ spdxDataLicense{},
+ spdxDocumentName{"Android"},
+ spdxID{"Android"},
+ spdxDocumentNameSpace{},
+ spdxCreatorOrganization{},
+ spdxCreatedTime{},
+ packageTag{"testdata/notice/bin/bin1.meta_lic"},
+ packageName{"testdata/notice/bin/bin1.meta_lic"},
+ spdxPkgID{"testdata/notice/bin/bin1.meta_lic"},
+ spdxPkgDownloadLocation{"NOASSERTION"},
+ spdxPkgLicenseDeclared{"testdata-firstparty-FIRST_PARTY_LICENSE"},
+ spdxRelationship{"DOCUMENT-Android ", "testdata/notice/bin/bin1.meta_lic", "DESCRIBES"},
+ packageTag{"testdata/notice/lib/liba.so.meta_lic"},
+ packageName{"testdata/notice/lib/liba.so.meta_lic"},
+ spdxPkgID{"testdata/notice/lib/liba.so.meta_lic"},
+ spdxPkgDownloadLocation{"NOASSERTION"},
+ spdxPkgLicenseDeclared{"testdata-notice-NOTICE_LICENSE"},
+ spdxRelationship{"Package-testdata/notice/bin/bin1.meta_lic ", "testdata/notice/lib/liba.so.meta_lic", "CONTAINS"},
+ packageTag{"testdata/notice/lib/libc.a.meta_lic"},
+ packageName{"testdata/notice/lib/libc.a.meta_lic"},
+ spdxPkgID{"testdata/notice/lib/libc.a.meta_lic"},
+ spdxPkgDownloadLocation{"NOASSERTION"},
+ spdxPkgLicenseDeclared{"testdata-notice-NOTICE_LICENSE"},
+ spdxRelationship{"Package-testdata/notice/bin/bin1.meta_lic ", "testdata/notice/lib/libc.a.meta_lic", "CONTAINS"},
+ spdxLicense{},
+ spdxLicenseID{"testdata-firstparty-FIRST_PARTY_LICENSE"},
+ spdxExtractedText{"&&&First Party License&&&"},
+ spdxExtractedClosingText{},
+ spdxLicenseID{"testdata-notice-NOTICE_LICENSE"},
+ spdxExtractedText{"%%%Notice License%%%"},
+ spdxExtractedClosingText{},
+ },
+ expectedDeps: []string{
+ "testdata/firstparty/FIRST_PARTY_LICENSE",
+ "testdata/notice/NOTICE_LICENSE",
+ },
+ },
+ {
+ condition: "notice",
+ name: "library",
+ roots: []string{"lib/libd.so.meta_lic"},
+ expectedOut: []matcher{
+ spdxVersion{},
+ spdxDataLicense{},
+ spdxDocumentName{"Android"},
+ spdxID{"Android"},
+ spdxDocumentNameSpace{},
+ spdxCreatorOrganization{},
+ spdxCreatedTime{},
+ packageTag{"testdata/notice/lib/libd.so.meta_lic"},
+ packageName{"testdata/notice/lib/libd.so.meta_lic"},
+ spdxPkgID{"testdata/notice/lib/libd.so.meta_lic"},
+ spdxPkgDownloadLocation{"NOASSERTION"},
+ spdxPkgLicenseDeclared{"testdata-notice-NOTICE_LICENSE"},
+ spdxRelationship{"DOCUMENT-Android ", "testdata/notice/lib/libd.so.meta_lic", "DESCRIBES"},
+ spdxLicense{},
+ spdxLicenseID{"testdata-notice-NOTICE_LICENSE"},
+ spdxExtractedText{"%%%Notice License%%%"},
+ spdxExtractedClosingText{},
+ },
+ expectedDeps: []string{"testdata/notice/NOTICE_LICENSE"},
+ },
+ {
+ condition: "reciprocal",
+ name: "apex",
+ roots: []string{"highest.apex.meta_lic"},
+ expectedOut: []matcher{
+ spdxVersion{},
+ spdxDataLicense{},
+ spdxDocumentName{"Android"},
+ spdxID{"Android"},
+ spdxDocumentNameSpace{},
+ spdxCreatorOrganization{},
+ spdxCreatedTime{},
+ packageTag{"testdata/reciprocal/highest.apex.meta_lic"},
+ packageName{"testdata/reciprocal/highest.apex.meta_lic"},
+ spdxPkgID{"testdata/reciprocal/highest.apex.meta_lic"},
+ spdxPkgDownloadLocation{"NOASSERTION"},
+ spdxPkgLicenseDeclared{"testdata-firstparty-FIRST_PARTY_LICENSE"},
+ spdxRelationship{"DOCUMENT-Android ", "testdata/reciprocal/highest.apex.meta_lic", "DESCRIBES"},
+ packageTag{"testdata/reciprocal/bin/bin1.meta_lic"},
+ packageName{"testdata/reciprocal/bin/bin1.meta_lic"},
+ spdxPkgID{"testdata/reciprocal/bin/bin1.meta_lic"},
+ spdxPkgDownloadLocation{"NOASSERTION"},
+ spdxPkgLicenseDeclared{"testdata-firstparty-FIRST_PARTY_LICENSE"},
+ spdxRelationship{"Package-testdata/reciprocal/highest.apex.meta_lic ", "testdata-reciprocal-bin-bin1.meta_lic", "CONTAINS"},
+ packageTag{"testdata/reciprocal/bin/bin2.meta_lic"},
+ packageName{"testdata/reciprocal/bin/bin2.meta_lic"},
+ spdxPkgID{"testdata/reciprocal/bin/bin2.meta_lic"},
+ spdxPkgDownloadLocation{"NOASSERTION"},
+ spdxPkgLicenseDeclared{"testdata-firstparty-FIRST_PARTY_LICENSE"},
+ spdxRelationship{"Package-testdata/reciprocal/highest.apex.meta_lic ", "testdata-reciprocal-bin-bin2.meta_lic", "CONTAINS"},
+ packageTag{"testdata/reciprocal/lib/liba.so.meta_lic"},
+ packageName{"testdata/reciprocal/lib/liba.so.meta_lic"},
+ spdxPkgID{"testdata/reciprocal/lib/liba.so.meta_lic"},
+ spdxPkgDownloadLocation{"NOASSERTION"},
+ spdxPkgLicenseDeclared{"testdata-reciprocal-RECIPROCAL_LICENSE"},
+ spdxRelationship{"Package-testdata/reciprocal/highest.apex.meta_lic ", "testdata/reciprocal/lib/liba.so.meta_lic", "CONTAINS"},
+ packageTag{"testdata/reciprocal/lib/libb.so.meta_lic"},
+ packageName{"testdata/reciprocal/lib/libb.so.meta_lic"},
+ spdxPkgID{"testdata/reciprocal/lib/libb.so.meta_lic"},
+ spdxPkgDownloadLocation{"NOASSERTION"},
+ spdxPkgLicenseDeclared{"testdata-firstparty-FIRST_PARTY_LICENSE"},
+ spdxRelationship{"Package-testdata/reciprocal/highest.apex.meta_lic ", "testdata/reciprocal/lib/libb.so.meta_lic", "CONTAINS"},
+ spdxRelationship{"Package-testdata/reciprocal/bin/bin1.meta_lic ", "testdata/reciprocal/lib/liba.so.meta_lic", "CONTAINS"},
+ packageTag{"testdata/reciprocal/lib/libc.a.meta_lic"},
+ packageName{"testdata/reciprocal/lib/libc.a.meta_lic"},
+ spdxPkgID{"testdata/reciprocal/lib/libc.a.meta_lic"},
+ spdxPkgDownloadLocation{"NOASSERTION"},
+ spdxPkgLicenseDeclared{"testdata-reciprocal-RECIPROCAL_LICENSE"},
+ spdxRelationship{"Package-testdata/reciprocal/bin/bin1.meta_lic ", "testdata/reciprocal/lib/libc.a.meta_lic", "CONTAINS"},
+ spdxRelationship{"Package-testdata/reciprocal/lib/libb.so.meta_lic ", "testdata/reciprocal/bin/bin2.meta_lic", "RUNTIME_DEPENDENCY_OF"},
+ packageTag{"testdata/reciprocal/lib/libd.so.meta_lic"},
+ packageName{"testdata/reciprocal/lib/libd.so.meta_lic"},
+ spdxPkgID{"testdata/reciprocal/lib/libd.so.meta_lic"},
+ spdxPkgDownloadLocation{"NOASSERTION"},
+ spdxPkgLicenseDeclared{"testdata-notice-NOTICE_LICENSE"},
+ spdxRelationship{"Package-testdata/reciprocal/lib/libd.so.meta_lic ", "testdata/reciprocal/bin/bin2.meta_lic", "RUNTIME_DEPENDENCY_OF"},
+ spdxLicense{},
+ spdxLicenseID{"testdata-firstparty-FIRST_PARTY_LICENSE"},
+ spdxExtractedText{"&&&First Party License&&&"},
+ spdxExtractedClosingText{},
+ spdxLicenseID{"testdata-notice-NOTICE_LICENSE"},
+ spdxExtractedText{"%%%Notice License%%%"},
+ spdxExtractedClosingText{},
+ spdxLicenseID{"testdata-reciprocal-RECIPROCAL_LICENSE"},
+ spdxExtractedText{"$$$Reciprocal License$$$"},
+ spdxExtractedClosingText{},
+ },
+ expectedDeps: []string{
+ "testdata/firstparty/FIRST_PARTY_LICENSE",
+ "testdata/notice/NOTICE_LICENSE",
+ "testdata/reciprocal/RECIPROCAL_LICENSE",
+ },
+ },
+ {
+ condition: "reciprocal",
+ name: "container",
+ roots: []string{"container.zip.meta_lic"},
+ expectedOut: []matcher{
+ spdxVersion{},
+ spdxDataLicense{},
+ spdxDocumentName{"Android"},
+ spdxID{"Android"},
+ spdxDocumentNameSpace{},
+ spdxCreatorOrganization{},
+ spdxCreatedTime{},
+ packageTag{"testdata/reciprocal/container.zip.meta_lic"},
+ packageName{"testdata/reciprocal/container.zip.meta_lic"},
+ spdxPkgID{"testdata/reciprocal/container.zip.meta_lic"},
+ spdxPkgDownloadLocation{"NOASSERTION"},
+ spdxPkgLicenseDeclared{"testdata-firstparty-FIRST_PARTY_LICENSE"},
+ spdxRelationship{"DOCUMENT-Android ", "testdata/reciprocal/container.zip.meta_lic", "DESCRIBES"},
+ packageTag{"testdata/reciprocal/bin/bin1.meta_lic"},
+ packageName{"testdata/reciprocal/bin/bin1.meta_lic"},
+ spdxPkgID{"testdata/reciprocal/bin/bin1.meta_lic"},
+ spdxPkgDownloadLocation{"NOASSERTION"},
+ spdxPkgLicenseDeclared{"testdata-firstparty-FIRST_PARTY_LICENSE"},
+ spdxRelationship{"Package-testdata/reciprocal/container.zip.meta_lic ", "testdata-reciprocal-bin-bin1.meta_lic", "CONTAINS"},
+ packageTag{"testdata/reciprocal/bin/bin2.meta_lic"},
+ packageName{"testdata/reciprocal/bin/bin2.meta_lic"},
+ spdxPkgID{"testdata/reciprocal/bin/bin2.meta_lic"},
+ spdxPkgDownloadLocation{"NOASSERTION"},
+ spdxPkgLicenseDeclared{"testdata-firstparty-FIRST_PARTY_LICENSE"},
+ spdxRelationship{"Package-testdata/reciprocal/container.zip.meta_lic ", "testdata-reciprocal-bin-bin2.meta_lic", "CONTAINS"},
+ packageTag{"testdata/reciprocal/lib/liba.so.meta_lic"},
+ packageName{"testdata/reciprocal/lib/liba.so.meta_lic"},
+ spdxPkgID{"testdata/reciprocal/lib/liba.so.meta_lic"},
+ spdxPkgDownloadLocation{"NOASSERTION"},
+ spdxPkgLicenseDeclared{"testdata-reciprocal-RECIPROCAL_LICENSE"},
+ spdxRelationship{"Package-testdata/reciprocal/container.zip.meta_lic ", "testdata/reciprocal/lib/liba.so.meta_lic", "CONTAINS"},
+ packageTag{"testdata/reciprocal/lib/libb.so.meta_lic"},
+ packageName{"testdata/reciprocal/lib/libb.so.meta_lic"},
+ spdxPkgID{"testdata/reciprocal/lib/libb.so.meta_lic"},
+ spdxPkgDownloadLocation{"NOASSERTION"},
+ spdxPkgLicenseDeclared{"testdata-firstparty-FIRST_PARTY_LICENSE"},
+ spdxRelationship{"Package-testdata/reciprocal/container.zip.meta_lic ", "testdata/reciprocal/lib/libb.so.meta_lic", "CONTAINS"},
+ spdxRelationship{"Package-testdata/reciprocal/bin/bin1.meta_lic ", "testdata/reciprocal/lib/liba.so.meta_lic", "CONTAINS"},
+ packageTag{"testdata/reciprocal/lib/libc.a.meta_lic"},
+ packageName{"testdata/reciprocal/lib/libc.a.meta_lic"},
+ spdxPkgID{"testdata/reciprocal/lib/libc.a.meta_lic"},
+ spdxPkgDownloadLocation{"NOASSERTION"},
+ spdxPkgLicenseDeclared{"testdata-reciprocal-RECIPROCAL_LICENSE"},
+ spdxRelationship{"Package-testdata/reciprocal/bin/bin1.meta_lic ", "testdata/reciprocal/lib/libc.a.meta_lic", "CONTAINS"},
+ spdxRelationship{"Package-testdata/reciprocal/lib/libb.so.meta_lic ", "testdata/reciprocal/bin/bin2.meta_lic", "RUNTIME_DEPENDENCY_OF"},
+ packageTag{"testdata/reciprocal/lib/libd.so.meta_lic"},
+ packageName{"testdata/reciprocal/lib/libd.so.meta_lic"},
+ spdxPkgID{"testdata/reciprocal/lib/libd.so.meta_lic"},
+ spdxPkgDownloadLocation{"NOASSERTION"},
+ spdxPkgLicenseDeclared{"testdata-notice-NOTICE_LICENSE"},
+ spdxRelationship{"Package-testdata/reciprocal/lib/libd.so.meta_lic ", "testdata/reciprocal/bin/bin2.meta_lic", "RUNTIME_DEPENDENCY_OF"},
+ spdxLicense{},
+ spdxLicenseID{"testdata-firstparty-FIRST_PARTY_LICENSE"},
+ spdxExtractedText{"&&&First Party License&&&"},
+ spdxExtractedClosingText{},
+ spdxLicenseID{"testdata-notice-NOTICE_LICENSE"},
+ spdxExtractedText{"%%%Notice License%%%"},
+ spdxExtractedClosingText{},
+ spdxLicenseID{"testdata-reciprocal-RECIPROCAL_LICENSE"},
+ spdxExtractedText{"$$$Reciprocal License$$$"},
+ spdxExtractedClosingText{},
+ },
+ expectedDeps: []string{
+ "testdata/firstparty/FIRST_PARTY_LICENSE",
+ "testdata/notice/NOTICE_LICENSE",
+ "testdata/reciprocal/RECIPROCAL_LICENSE",
+ },
+ },
+ {
+ condition: "reciprocal",
+ name: "application",
+ roots: []string{"application.meta_lic"},
+ expectedOut: []matcher{
+ spdxVersion{},
+ spdxDataLicense{},
+ spdxDocumentName{"Android"},
+ spdxID{"Android"},
+ spdxDocumentNameSpace{},
+ spdxCreatorOrganization{},
+ spdxCreatedTime{},
+ packageTag{"testdata/reciprocal/application.meta_lic"},
+ packageName{"testdata/reciprocal/application.meta_lic"},
+ spdxPkgID{"testdata/reciprocal/application.meta_lic"},
+ spdxPkgDownloadLocation{"NOASSERTION"},
+ spdxPkgLicenseDeclared{"testdata-firstparty-FIRST_PARTY_LICENSE"},
+ spdxRelationship{"DOCUMENT-Android ", "testdata/reciprocal/application.meta_lic", "DESCRIBES"},
+ packageTag{"testdata/reciprocal/bin/bin3.meta_lic"},
+ packageName{"testdata/reciprocal/bin/bin3.meta_lic"},
+ spdxPkgID{"testdata/reciprocal/bin/bin3.meta_lic"},
+ spdxPkgDownloadLocation{"NOASSERTION"},
+ spdxPkgLicenseDeclared{"testdata-notice-NOTICE_LICENSE"},
+ spdxRelationship{"Package-testdata-reciprocal-bin-bin3.meta_lic ", "testdata/reciprocal/application.meta_lic", "BUILD_TOOL_OF"},
+ packageTag{"testdata/reciprocal/lib/liba.so.meta_lic"},
+ packageName{"testdata/reciprocal/lib/liba.so.meta_lic"},
+ spdxPkgID{"testdata/reciprocal/lib/liba.so.meta_lic"},
+ spdxPkgDownloadLocation{"NOASSERTION"},
+ spdxPkgLicenseDeclared{"testdata-reciprocal-RECIPROCAL_LICENSE"},
+ spdxRelationship{"Package-testdata/reciprocal/application.meta_lic ", "testdata/reciprocal/lib/liba.so.meta_lic", "CONTAINS"},
+ packageTag{"testdata/reciprocal/lib/libb.so.meta_lic"},
+ packageName{"testdata/reciprocal/lib/libb.so.meta_lic"},
+ spdxPkgID{"testdata/reciprocal/lib/libb.so.meta_lic"},
+ spdxPkgDownloadLocation{"NOASSERTION"},
+ spdxPkgLicenseDeclared{"testdata-firstparty-FIRST_PARTY_LICENSE"},
+ spdxRelationship{"Package-testdata/reciprocal/lib/libb.so.meta_lic ", "testdata/reciprocal/application.meta_lic", "RUNTIME_DEPENDENCY_OF"},
+ spdxLicense{},
+ spdxLicenseID{"testdata-firstparty-FIRST_PARTY_LICENSE"},
+ spdxExtractedText{"&&&First Party License&&&"},
+ spdxExtractedClosingText{},
+ spdxLicenseID{"testdata-notice-NOTICE_LICENSE"},
+ spdxExtractedText{"%%%Notice License%%%"},
+ spdxExtractedClosingText{},
+ spdxLicenseID{"testdata-reciprocal-RECIPROCAL_LICENSE"},
+ spdxExtractedText{"$$$Reciprocal License$$$"},
+ spdxExtractedClosingText{},
+ },
+ expectedDeps: []string{
+ "testdata/firstparty/FIRST_PARTY_LICENSE",
+ "testdata/notice/NOTICE_LICENSE",
+ "testdata/reciprocal/RECIPROCAL_LICENSE",
+ },
+ },
+ {
+ condition: "reciprocal",
+ name: "binary",
+ roots: []string{"bin/bin1.meta_lic"},
+ expectedOut: []matcher{
+ spdxVersion{},
+ spdxDataLicense{},
+ spdxDocumentName{"Android"},
+ spdxID{"Android"},
+ spdxDocumentNameSpace{},
+ spdxCreatorOrganization{},
+ spdxCreatedTime{},
+ packageTag{"testdata/reciprocal/bin/bin1.meta_lic"},
+ packageName{"testdata/reciprocal/bin/bin1.meta_lic"},
+ spdxPkgID{"testdata/reciprocal/bin/bin1.meta_lic"},
+ spdxPkgDownloadLocation{"NOASSERTION"},
+ spdxPkgLicenseDeclared{"testdata-firstparty-FIRST_PARTY_LICENSE"},
+ spdxRelationship{"DOCUMENT-Android ", "testdata/reciprocal/bin/bin1.meta_lic", "DESCRIBES"},
+ packageTag{"testdata/reciprocal/lib/liba.so.meta_lic"},
+ packageName{"testdata/reciprocal/lib/liba.so.meta_lic"},
+ spdxPkgID{"testdata/reciprocal/lib/liba.so.meta_lic"},
+ spdxPkgDownloadLocation{"NOASSERTION"},
+ spdxPkgLicenseDeclared{"testdata-reciprocal-RECIPROCAL_LICENSE"},
+ spdxRelationship{"Package-testdata/reciprocal/bin/bin1.meta_lic ", "testdata/reciprocal/lib/liba.so.meta_lic", "CONTAINS"},
+ packageTag{"testdata/reciprocal/lib/libc.a.meta_lic"},
+ packageName{"testdata/reciprocal/lib/libc.a.meta_lic"},
+ spdxPkgID{"testdata/reciprocal/lib/libc.a.meta_lic"},
+ spdxPkgDownloadLocation{"NOASSERTION"},
+ spdxPkgLicenseDeclared{"testdata-reciprocal-RECIPROCAL_LICENSE"},
+ spdxRelationship{"Package-testdata/reciprocal/bin/bin1.meta_lic ", "testdata/reciprocal/lib/libc.a.meta_lic", "CONTAINS"},
+ spdxLicense{},
+ spdxLicenseID{"testdata-firstparty-FIRST_PARTY_LICENSE"},
+ spdxExtractedText{"&&&First Party License&&&"},
+ spdxExtractedClosingText{},
+ spdxLicenseID{"testdata-reciprocal-RECIPROCAL_LICENSE"},
+ spdxExtractedText{"$$$Reciprocal License$$$"},
+ spdxExtractedClosingText{},
+ },
+ expectedDeps: []string{
+ "testdata/firstparty/FIRST_PARTY_LICENSE",
+ "testdata/reciprocal/RECIPROCAL_LICENSE",
+ },
+ },
+ {
+ condition: "reciprocal",
+ name: "library",
+ roots: []string{"lib/libd.so.meta_lic"},
+ expectedOut: []matcher{
+ spdxVersion{},
+ spdxDataLicense{},
+ spdxDocumentName{"Android"},
+ spdxID{"Android"},
+ spdxDocumentNameSpace{},
+ spdxCreatorOrganization{},
+ spdxCreatedTime{},
+ packageTag{"testdata/reciprocal/lib/libd.so.meta_lic"},
+ packageName{"testdata/reciprocal/lib/libd.so.meta_lic"},
+ spdxPkgID{"testdata/reciprocal/lib/libd.so.meta_lic"},
+ spdxPkgDownloadLocation{"NOASSERTION"},
+ spdxPkgLicenseDeclared{"testdata-notice-NOTICE_LICENSE"},
+ spdxRelationship{"DOCUMENT-Android ", "testdata/reciprocal/lib/libd.so.meta_lic", "DESCRIBES"},
+ spdxLicense{},
+ spdxLicenseID{"testdata-notice-NOTICE_LICENSE"},
+ spdxExtractedText{"%%%Notice License%%%"},
+ spdxExtractedClosingText{},
+ },
+ expectedDeps: []string{
+ "testdata/notice/NOTICE_LICENSE",
+ },
+ },
+ {
+ condition: "restricted",
+ name: "apex",
+ roots: []string{"highest.apex.meta_lic"},
+ stripPrefix: "out/target/product/fictional/system/apex/",
+ expectedOut: []matcher{
+ spdxVersion{},
+ spdxDataLicense{},
+ spdxDocumentName{"Android"},
+ spdxID{"Android"},
+ spdxDocumentNameSpace{},
+ spdxCreatorOrganization{},
+ spdxCreatedTime{},
+ packageTag{"testdata/restricted/highest.apex.meta_lic"},
+ packageName{"testdata/restricted/highest.apex.meta_lic"},
+ spdxPkgID{"testdata/restricted/highest.apex.meta_lic"},
+ spdxPkgDownloadLocation{"NOASSERTION"},
+ spdxPkgLicenseDeclared{"testdata-firstparty-FIRST_PARTY_LICENSE"},
+ spdxRelationship{"DOCUMENT-Android ", "testdata/restricted/highest.apex.meta_lic", "DESCRIBES"},
+ packageTag{"testdata/restricted/bin/bin1.meta_lic"},
+ packageName{"testdata/restricted/bin/bin1.meta_lic"},
+ spdxPkgID{"testdata/restricted/bin/bin1.meta_lic"},
+ spdxPkgDownloadLocation{"NOASSERTION"},
+ spdxPkgLicenseDeclared{"testdata-firstparty-FIRST_PARTY_LICENSE"},
+ spdxRelationship{"Package-testdata/restricted/highest.apex.meta_lic ", "testdata/restricted/bin/bin1.meta_lic", "CONTAINS"},
+ packageTag{"testdata/restricted/bin/bin2.meta_lic"},
+ packageName{"testdata/restricted/bin/bin2.meta_lic"},
+ spdxPkgID{"testdata/restricted/bin/bin2.meta_lic"},
+ spdxPkgDownloadLocation{"NOASSERTION"},
+ spdxPkgLicenseDeclared{"testdata-firstparty-FIRST_PARTY_LICENSE"},
+ spdxRelationship{"Package-testdata/restricted/highest.apex.meta_lic ", "testdata/restricted/bin/bin2.meta_lic", "CONTAINS"},
+ packageTag{"testdata/restricted/lib/liba.so.meta_lic"},
+ packageName{"testdata/restricted/lib/liba.so.meta_lic"},
+ spdxPkgID{"testdata/restricted/lib/liba.so.meta_lic"},
+ spdxPkgDownloadLocation{"NOASSERTION"},
+ spdxPkgLicenseDeclared{"testdata-restricted-RESTRICTED_LICENSE"},
+ spdxRelationship{"Package-testdata/restricted/highest.apex.meta_lic ", "testdata/restricted/lib/liba.so.meta_lic", "CONTAINS"},
+ packageTag{"testdata/restricted/lib/libb.so.meta_lic"},
+ packageName{"testdata/restricted/lib/libb.so.meta_lic"},
+ spdxPkgID{"testdata/restricted/lib/libb.so.meta_lic"},
+ spdxPkgDownloadLocation{"NOASSERTION"},
+ spdxPkgLicenseDeclared{"testdata-restricted-RESTRICTED_LICENSE"},
+ spdxRelationship{"Package-testdata/restricted/highest.apex.meta_lic ", "testdata/restricted/lib/libb.so.meta_lic", "CONTAINS"},
+ spdxRelationship{"Package-testdata/restricted/bin/bin1.meta_lic ", "testdata/restricted/lib/liba.so.meta_lic", "CONTAINS"},
+ packageTag{"testdata/restricted/lib/libc.a.meta_lic"},
+ packageName{"testdata/restricted/lib/libc.a.meta_lic"},
+ spdxPkgID{"testdata/restricted/lib/libc.a.meta_lic"},
+ spdxPkgDownloadLocation{"NOASSERTION"},
+ spdxPkgLicenseDeclared{"testdata-reciprocal-RECIPROCAL_LICENSE"},
+ spdxRelationship{"Package-testdata/restricted/bin/bin1.meta_lic ", "testdata/restricted/lib/libc.a.meta_lic", "CONTAINS"},
+ spdxRelationship{"Package-testdata/restricted/lib/libb.so.meta_lic ", "testdata/restricted/bin/bin2.meta_lic", "RUNTIME_DEPENDENCY_OF"},
+ packageTag{"testdata/restricted/lib/libd.so.meta_lic"},
+ packageName{"testdata/restricted/lib/libd.so.meta_lic"},
+ spdxPkgID{"testdata/restricted/lib/libd.so.meta_lic"},
+ spdxPkgDownloadLocation{"NOASSERTION"},
+ spdxPkgLicenseDeclared{"testdata-notice-NOTICE_LICENSE"},
+ spdxRelationship{"Package-testdata/restricted/lib/libd.so.meta_lic ", "testdata/restricted/bin/bin2.meta_lic", "RUNTIME_DEPENDENCY_OF"},
+ spdxLicense{},
+ spdxLicenseID{"testdata-firstparty-FIRST_PARTY_LICENSE"},
+ spdxExtractedText{"&&&First Party License&&&"},
+ spdxExtractedClosingText{},
+ spdxLicenseID{"testdata-notice-NOTICE_LICENSE"},
+ spdxExtractedText{"%%%Notice License%%%"},
+ spdxExtractedClosingText{},
+ spdxLicenseID{"testdata-reciprocal-RECIPROCAL_LICENSE"},
+ spdxExtractedText{"$$$Reciprocal License$$$"},
+ spdxExtractedClosingText{},
+ spdxLicenseID{"testdata-restricted-RESTRICTED_LICENSE"},
+ spdxExtractedText{"###Restricted License###"},
+ spdxExtractedClosingText{},
+ },
+ expectedDeps: []string{
+ "testdata/firstparty/FIRST_PARTY_LICENSE",
+ "testdata/notice/NOTICE_LICENSE",
+ "testdata/reciprocal/RECIPROCAL_LICENSE",
+ "testdata/restricted/RESTRICTED_LICENSE",
+ },
+ },
+ {
+ condition: "restricted",
+ name: "container",
+ roots: []string{"container.zip.meta_lic"},
+ stripPrefix: "out/target/product/fictional/system/apex/",
+ expectedOut: []matcher{
+ spdxVersion{},
+ spdxDataLicense{},
+ spdxDocumentName{"Android"},
+ spdxID{"Android"},
+ spdxDocumentNameSpace{},
+ spdxCreatorOrganization{},
+ spdxCreatedTime{},
+ packageTag{"testdata/restricted/container.zip.meta_lic"},
+ packageName{"testdata/restricted/container.zip.meta_lic"},
+ spdxPkgID{"testdata/restricted/container.zip.meta_lic"},
+ spdxPkgDownloadLocation{"NOASSERTION"},
+ spdxPkgLicenseDeclared{"testdata-firstparty-FIRST_PARTY_LICENSE"},
+ spdxRelationship{"DOCUMENT-Android ", "testdata/restricted/container.zip.meta_lic", "DESCRIBES"},
+ packageTag{"testdata/restricted/bin/bin1.meta_lic"},
+ packageName{"testdata/restricted/bin/bin1.meta_lic"},
+ spdxPkgID{"testdata/restricted/bin/bin1.meta_lic"},
+ spdxPkgDownloadLocation{"NOASSERTION"},
+ spdxPkgLicenseDeclared{"testdata-firstparty-FIRST_PARTY_LICENSE"},
+ spdxRelationship{"Package-testdata/restricted/container.zip.meta_lic ", "testdata/restricted/bin/bin1.meta_lic", "CONTAINS"},
+ packageTag{"testdata/restricted/bin/bin2.meta_lic"},
+ packageName{"testdata/restricted/bin/bin2.meta_lic"},
+ spdxPkgID{"testdata/restricted/bin/bin2.meta_lic"},
+ spdxPkgDownloadLocation{"NOASSERTION"},
+ spdxPkgLicenseDeclared{"testdata-firstparty-FIRST_PARTY_LICENSE"},
+ spdxRelationship{"Package-testdata/restricted/container.zip.meta_lic ", "testdata/restricted/bin/bin2.meta_lic", "CONTAINS"},
+ packageTag{"testdata/restricted/lib/liba.so.meta_lic"},
+ packageName{"testdata/restricted/lib/liba.so.meta_lic"},
+ spdxPkgID{"testdata/restricted/lib/liba.so.meta_lic"},
+ spdxPkgDownloadLocation{"NOASSERTION"},
+ spdxPkgLicenseDeclared{"testdata-restricted-RESTRICTED_LICENSE"},
+ spdxRelationship{"Package-testdata/restricted/container.zip.meta_lic ", "testdata/restricted/lib/liba.so.meta_lic", "CONTAINS"},
+ packageTag{"testdata/restricted/lib/libb.so.meta_lic"},
+ packageName{"testdata/restricted/lib/libb.so.meta_lic"},
+ spdxPkgID{"testdata/restricted/lib/libb.so.meta_lic"},
+ spdxPkgDownloadLocation{"NOASSERTION"},
+ spdxPkgLicenseDeclared{"testdata-restricted-RESTRICTED_LICENSE"},
+ spdxRelationship{"Package-testdata/restricted/container.zip.meta_lic ", "testdata/restricted/lib/libb.so.meta_lic", "CONTAINS"},
+ spdxRelationship{"Package-testdata/restricted/bin/bin1.meta_lic ", "testdata/restricted/lib/liba.so.meta_lic", "CONTAINS"},
+ packageTag{"testdata/restricted/lib/libc.a.meta_lic"},
+ packageName{"testdata/restricted/lib/libc.a.meta_lic"},
+ spdxPkgID{"testdata/restricted/lib/libc.a.meta_lic"},
+ spdxPkgDownloadLocation{"NOASSERTION"},
+ spdxPkgLicenseDeclared{"testdata-reciprocal-RECIPROCAL_LICENSE"},
+ spdxRelationship{"Package-testdata/restricted/bin/bin1.meta_lic ", "testdata/restricted/lib/libc.a.meta_lic", "CONTAINS"},
+ spdxRelationship{"Package-testdata/restricted/lib/libb.so.meta_lic ", "testdata/restricted/bin/bin2.meta_lic", "RUNTIME_DEPENDENCY_OF"},
+ packageTag{"testdata/restricted/lib/libd.so.meta_lic"},
+ packageName{"testdata/restricted/lib/libd.so.meta_lic"},
+ spdxPkgID{"testdata/restricted/lib/libd.so.meta_lic"},
+ spdxPkgDownloadLocation{"NOASSERTION"},
+ spdxPkgLicenseDeclared{"testdata-notice-NOTICE_LICENSE"},
+ spdxRelationship{"Package-testdata/restricted/lib/libd.so.meta_lic ", "testdata/restricted/bin/bin2.meta_lic", "RUNTIME_DEPENDENCY_OF"},
+ spdxLicense{},
+ spdxLicenseID{"testdata-firstparty-FIRST_PARTY_LICENSE"},
+ spdxExtractedText{"&&&First Party License&&&"},
+ spdxExtractedClosingText{},
+ spdxLicenseID{"testdata-notice-NOTICE_LICENSE"},
+ spdxExtractedText{"%%%Notice License%%%"},
+ spdxExtractedClosingText{},
+ spdxLicenseID{"testdata-reciprocal-RECIPROCAL_LICENSE"},
+ spdxExtractedText{"$$$Reciprocal License$$$"},
+ spdxExtractedClosingText{},
+ spdxLicenseID{"testdata-restricted-RESTRICTED_LICENSE"},
+ spdxExtractedText{"###Restricted License###"},
+ spdxExtractedClosingText{},
+ },
+ expectedDeps: []string{
+ "testdata/firstparty/FIRST_PARTY_LICENSE",
+ "testdata/notice/NOTICE_LICENSE",
+ "testdata/reciprocal/RECIPROCAL_LICENSE",
+ "testdata/restricted/RESTRICTED_LICENSE",
+ },
+ },
+ {
+ condition: "restricted",
+ name: "binary",
+ roots: []string{"bin/bin1.meta_lic"},
+ expectedOut: []matcher{
+ spdxVersion{},
+ spdxDataLicense{},
+ spdxDocumentName{"Android"},
+ spdxID{"Android"},
+ spdxDocumentNameSpace{},
+ spdxCreatorOrganization{},
+ spdxCreatedTime{},
+ packageTag{"testdata/restricted/bin/bin1.meta_lic"},
+ packageName{"testdata/restricted/bin/bin1.meta_lic"},
+ spdxPkgID{"testdata/restricted/bin/bin1.meta_lic"},
+ spdxPkgDownloadLocation{"NOASSERTION"},
+ spdxPkgLicenseDeclared{"testdata-firstparty-FIRST_PARTY_LICENSE"},
+ spdxRelationship{"DOCUMENT-Android ", "testdata/restricted/bin/bin1.meta_lic", "DESCRIBES"},
+ packageTag{"testdata/restricted/lib/liba.so.meta_lic"},
+ packageName{"testdata/restricted/lib/liba.so.meta_lic"},
+ spdxPkgID{"testdata/restricted/lib/liba.so.meta_lic"},
+ spdxPkgDownloadLocation{"NOASSERTION"},
+ spdxPkgLicenseDeclared{"testdata-restricted-RESTRICTED_LICENSE"},
+ spdxRelationship{"Package-testdata/restricted/bin/bin1.meta_lic ", "testdata/restricted/lib/liba.so.meta_lic", "CONTAINS"},
+ packageTag{"testdata/restricted/lib/libc.a.meta_lic"},
+ packageName{"testdata/restricted/lib/libc.a.meta_lic"},
+ spdxPkgID{"testdata/restricted/lib/libc.a.meta_lic"},
+ spdxPkgDownloadLocation{"NOASSERTION"},
+ spdxPkgLicenseDeclared{"testdata-reciprocal-RECIPROCAL_LICENSE"},
+ spdxRelationship{"Package-testdata/restricted/bin/bin1.meta_lic ", "testdata/restricted/lib/libc.a.meta_lic", "CONTAINS"},
+ spdxLicense{},
+ spdxLicenseID{"testdata-firstparty-FIRST_PARTY_LICENSE"},
+ spdxExtractedText{"&&&First Party License&&&"},
+ spdxExtractedClosingText{},
+ spdxLicenseID{"testdata-reciprocal-RECIPROCAL_LICENSE"},
+ spdxExtractedText{"$$$Reciprocal License$$$"},
+ spdxExtractedClosingText{},
+ spdxLicenseID{"testdata-restricted-RESTRICTED_LICENSE"},
+ spdxExtractedText{"###Restricted License###"},
+ spdxExtractedClosingText{},
+ },
+ expectedDeps: []string{
+ "testdata/firstparty/FIRST_PARTY_LICENSE",
+ "testdata/reciprocal/RECIPROCAL_LICENSE",
+ "testdata/restricted/RESTRICTED_LICENSE",
+ },
+ },
+ {
+ condition: "restricted",
+ name: "library",
+ roots: []string{"lib/libd.so.meta_lic"},
+ expectedOut: []matcher{
+ spdxVersion{},
+ spdxDataLicense{},
+ spdxDocumentName{"Android"},
+ spdxID{"Android"},
+ spdxDocumentNameSpace{},
+ spdxCreatorOrganization{},
+ spdxCreatedTime{},
+ packageTag{"testdata/restricted/lib/libd.so.meta_lic"},
+ packageName{"testdata/restricted/lib/libd.so.meta_lic"},
+ spdxPkgID{"testdata/restricted/lib/libd.so.meta_lic"},
+ spdxPkgDownloadLocation{"NOASSERTION"},
+ spdxPkgLicenseDeclared{"testdata-notice-NOTICE_LICENSE"},
+ spdxRelationship{"DOCUMENT-Android ", "testdata/restricted/lib/libd.so.meta_lic", "DESCRIBES"},
+ spdxLicense{},
+ spdxLicenseID{"testdata-notice-NOTICE_LICENSE"},
+ spdxExtractedText{"%%%Notice License%%%"},
+ spdxExtractedClosingText{},
+ },
+ expectedDeps: []string{"testdata/notice/NOTICE_LICENSE"},
+ },
+ {
+ condition: "proprietary",
+ name: "apex",
+ roots: []string{"highest.apex.meta_lic"},
+ expectedOut: []matcher{
+ spdxVersion{},
+ spdxDataLicense{},
+ spdxDocumentName{"Android"},
+ spdxID{"Android"},
+ spdxDocumentNameSpace{},
+ spdxCreatorOrganization{},
+ spdxCreatedTime{},
+ packageTag{"testdata/proprietary/highest.apex.meta_lic"},
+ packageName{"testdata/proprietary/highest.apex.meta_lic"},
+ spdxPkgID{"testdata/proprietary/highest.apex.meta_lic"},
+ spdxPkgDownloadLocation{"NOASSERTION"},
+ spdxPkgLicenseDeclared{"testdata-firstparty-FIRST_PARTY_LICENSE"},
+ spdxRelationship{"DOCUMENT-Android ", "testdata/proprietary/highest.apex.meta_lic", "DESCRIBES"},
+ packageTag{"testdata/proprietary/bin/bin1.meta_lic"},
+ packageName{"testdata/proprietary/bin/bin1.meta_lic"},
+ spdxPkgID{"testdata/proprietary/bin/bin1.meta_lic"},
+ spdxPkgDownloadLocation{"NOASSERTION"},
+ spdxPkgLicenseDeclared{"testdata-firstparty-FIRST_PARTY_LICENSE"},
+ spdxRelationship{"Package-testdata/proprietary/highest.apex.meta_lic ", "testdata/proprietary/bin/bin1.meta_lic", "CONTAINS"},
+ packageTag{"testdata/proprietary/bin/bin2.meta_lic"},
+ packageName{"testdata/proprietary/bin/bin2.meta_lic"},
+ spdxPkgID{"testdata/proprietary/bin/bin2.meta_lic"},
+ spdxPkgDownloadLocation{"NOASSERTION"},
+ spdxPkgLicenseDeclared{"testdata-proprietary-PROPRIETARY_LICENSE"},
+ spdxRelationship{"Package-testdata/proprietary/highest.apex.meta_lic ", "testdata/proprietary/bin/bin2.meta_lic", "CONTAINS"},
+ packageTag{"testdata/proprietary/lib/liba.so.meta_lic"},
+ packageName{"testdata/proprietary/lib/liba.so.meta_lic"},
+ spdxPkgID{"testdata/proprietary/lib/liba.so.meta_lic"},
+ spdxPkgDownloadLocation{"NOASSERTION"},
+ spdxPkgLicenseDeclared{"testdata-proprietary-PROPRIETARY_LICENSE"},
+ spdxRelationship{"Package-testdata/proprietary/highest.apex.meta_lic ", "testdata/proprietary/lib/liba.so.meta_lic", "CONTAINS"},
+ packageTag{"testdata/proprietary/lib/libb.so.meta_lic"},
+ packageName{"testdata/proprietary/lib/libb.so.meta_lic"},
+ spdxPkgID{"testdata/proprietary/lib/libb.so.meta_lic"},
+ spdxPkgDownloadLocation{"NOASSERTION"},
+ spdxPkgLicenseDeclared{"testdata-restricted-RESTRICTED_LICENSE"},
+ spdxRelationship{"Package-testdata/proprietary/highest.apex.meta_lic ", "testdata/proprietary/lib/libb.so.meta_lic", "CONTAINS"},
+ spdxRelationship{"Package-testdata/proprietary/bin/bin1.meta_lic ", "testdata/proprietary/lib/liba.so.meta_lic", "CONTAINS"},
+ packageTag{"testdata/proprietary/lib/libc.a.meta_lic"},
+ packageName{"testdata/proprietary/lib/libc.a.meta_lic"},
+ spdxPkgID{"testdata/proprietary/lib/libc.a.meta_lic"},
+ spdxPkgDownloadLocation{"NOASSERTION"},
+ spdxPkgLicenseDeclared{"testdata-proprietary-PROPRIETARY_LICENSE"},
+ spdxRelationship{"Package-testdata/proprietary/bin/bin1.meta_lic ", "testdata/proprietary/lib/libc.a.meta_lic", "CONTAINS"},
+ spdxRelationship{"Package-testdata-proprietary-lib-libb.so.meta_lic ", "testdata/proprietary/bin/bin2.meta_lic", "RUNTIME_DEPENDENCY_OF"},
+ packageTag{"testdata/proprietary/lib/libd.so.meta_lic"},
+ packageName{"testdata/proprietary/lib/libd.so.meta_lic"},
+ spdxPkgID{"testdata/proprietary/lib/libd.so.meta_lic"},
+ spdxPkgDownloadLocation{"NOASSERTION"},
+ spdxPkgLicenseDeclared{"testdata-notice-NOTICE_LICENSE"},
+ spdxRelationship{"Package-testdata-proprietary-lib-libd.so.meta_lic ", "testdata/proprietary/bin/bin2.meta_lic", "RUNTIME_DEPENDENCY_OF"},
+ spdxLicense{},
+ spdxLicenseID{"testdata-firstparty-FIRST_PARTY_LICENSE"},
+ spdxExtractedText{"&&&First Party License&&&"},
+ spdxExtractedClosingText{},
+ spdxLicenseID{"testdata-notice-NOTICE_LICENSE"},
+ spdxExtractedText{"%%%Notice License%%%"},
+ spdxExtractedClosingText{},
+ spdxLicenseID{"testdata-proprietary-PROPRIETARY_LICENSE"},
+ spdxExtractedText{"@@@Proprietary License@@@"},
+ spdxExtractedClosingText{},
+ spdxLicenseID{"testdata-restricted-RESTRICTED_LICENSE"},
+ spdxExtractedText{"###Restricted License###"},
+ spdxExtractedClosingText{},
+ },
+ expectedDeps: []string{
+ "testdata/firstparty/FIRST_PARTY_LICENSE",
+ "testdata/notice/NOTICE_LICENSE",
+ "testdata/proprietary/PROPRIETARY_LICENSE",
+ "testdata/restricted/RESTRICTED_LICENSE",
+ },
+ },
+ {
+ condition: "proprietary",
+ name: "container",
+ roots: []string{"container.zip.meta_lic"},
+ expectedOut: []matcher{
+ spdxVersion{},
+ spdxDataLicense{},
+ spdxDocumentName{"Android"},
+ spdxID{"Android"},
+ spdxDocumentNameSpace{},
+ spdxCreatorOrganization{},
+ spdxCreatedTime{},
+ packageTag{"testdata/proprietary/container.zip.meta_lic"},
+ packageName{"testdata/proprietary/container.zip.meta_lic"},
+ spdxPkgID{"testdata/proprietary/container.zip.meta_lic"},
+ spdxPkgDownloadLocation{"NOASSERTION"},
+ spdxPkgLicenseDeclared{"testdata-firstparty-FIRST_PARTY_LICENSE"},
+ spdxRelationship{"DOCUMENT-Android ", "testdata/proprietary/container.zip.meta_lic", "DESCRIBES"},
+ packageTag{"testdata/proprietary/bin/bin1.meta_lic"},
+ packageName{"testdata/proprietary/bin/bin1.meta_lic"},
+ spdxPkgID{"testdata/proprietary/bin/bin1.meta_lic"},
+ spdxPkgDownloadLocation{"NOASSERTION"},
+ spdxPkgLicenseDeclared{"testdata-firstparty-FIRST_PARTY_LICENSE"},
+ spdxRelationship{"Package-testdata/proprietary/container.zip.meta_lic ", "testdata/proprietary/bin/bin1.meta_lic", "CONTAINS"},
+ packageTag{"testdata/proprietary/bin/bin2.meta_lic"},
+ packageName{"testdata/proprietary/bin/bin2.meta_lic"},
+ spdxPkgID{"testdata/proprietary/bin/bin2.meta_lic"},
+ spdxPkgDownloadLocation{"NOASSERTION"},
+ spdxPkgLicenseDeclared{"testdata-proprietary-PROPRIETARY_LICENSE"},
+ spdxRelationship{"Package-testdata/proprietary/container.zip.meta_lic ", "testdata/proprietary/bin/bin2.meta_lic", "CONTAINS"},
+ packageTag{"testdata/proprietary/lib/liba.so.meta_lic"},
+ packageName{"testdata/proprietary/lib/liba.so.meta_lic"},
+ spdxPkgID{"testdata/proprietary/lib/liba.so.meta_lic"},
+ spdxPkgDownloadLocation{"NOASSERTION"},
+ spdxPkgLicenseDeclared{"testdata-proprietary-PROPRIETARY_LICENSE"},
+ spdxRelationship{"Package-testdata/proprietary/container.zip.meta_lic ", "testdata/proprietary/lib/liba.so.meta_lic", "CONTAINS"},
+ packageTag{"testdata/proprietary/lib/libb.so.meta_lic"},
+ packageName{"testdata/proprietary/lib/libb.so.meta_lic"},
+ spdxPkgID{"testdata/proprietary/lib/libb.so.meta_lic"},
+ spdxPkgDownloadLocation{"NOASSERTION"},
+ spdxPkgLicenseDeclared{"testdata-restricted-RESTRICTED_LICENSE"},
+ spdxRelationship{"Package-testdata/proprietary/container.zip.meta_lic ", "testdata/proprietary/lib/libb.so.meta_lic", "CONTAINS"},
+ spdxRelationship{"Package-testdata/proprietary/bin/bin1.meta_lic ", "testdata/proprietary/lib/liba.so.meta_lic", "CONTAINS"},
+ packageTag{"testdata/proprietary/lib/libc.a.meta_lic"},
+ packageName{"testdata/proprietary/lib/libc.a.meta_lic"},
+ spdxPkgID{"testdata/proprietary/lib/libc.a.meta_lic"},
+ spdxPkgDownloadLocation{"NOASSERTION"},
+ spdxPkgLicenseDeclared{"testdata-proprietary-PROPRIETARY_LICENSE"},
+ spdxRelationship{"Package-testdata/proprietary/bin/bin1.meta_lic ", "testdata/proprietary/lib/libc.a.meta_lic", "CONTAINS"},
+ spdxRelationship{"Package-testdata-proprietary-lib-libb.so.meta_lic ", "testdata/proprietary/bin/bin2.meta_lic", "RUNTIME_DEPENDENCY_OF"},
+ packageTag{"testdata/proprietary/lib/libd.so.meta_lic"},
+ packageName{"testdata/proprietary/lib/libd.so.meta_lic"},
+ spdxPkgID{"testdata/proprietary/lib/libd.so.meta_lic"},
+ spdxPkgDownloadLocation{"NOASSERTION"},
+ spdxPkgLicenseDeclared{"testdata-notice-NOTICE_LICENSE"},
+ spdxRelationship{"Package-testdata-proprietary-lib-libd.so.meta_lic ", "testdata/proprietary/bin/bin2.meta_lic", "RUNTIME_DEPENDENCY_OF"},
+ spdxLicense{},
+ spdxLicenseID{"testdata-firstparty-FIRST_PARTY_LICENSE"},
+ spdxExtractedText{"&&&First Party License&&&"},
+ spdxExtractedClosingText{},
+ spdxLicenseID{"testdata-notice-NOTICE_LICENSE"},
+ spdxExtractedText{"%%%Notice License%%%"},
+ spdxExtractedClosingText{},
+ spdxLicenseID{"testdata-proprietary-PROPRIETARY_LICENSE"},
+ spdxExtractedText{"@@@Proprietary License@@@"},
+ spdxExtractedClosingText{},
+ spdxLicenseID{"testdata-restricted-RESTRICTED_LICENSE"},
+ spdxExtractedText{"###Restricted License###"},
+ spdxExtractedClosingText{},
+ },
+ expectedDeps: []string{
+ "testdata/firstparty/FIRST_PARTY_LICENSE",
+ "testdata/notice/NOTICE_LICENSE",
+ "testdata/proprietary/PROPRIETARY_LICENSE",
+ "testdata/restricted/RESTRICTED_LICENSE",
+ },
+ },
+ {
+ condition: "proprietary",
+ name: "application",
+ roots: []string{"application.meta_lic"},
+ expectedOut: []matcher{
+ spdxVersion{},
+ spdxDataLicense{},
+ spdxDocumentName{"Android"},
+ spdxID{"Android"},
+ spdxDocumentNameSpace{},
+ spdxCreatorOrganization{},
+ spdxCreatedTime{},
+ packageTag{"testdata/proprietary/application.meta_lic"},
+ packageName{"testdata/proprietary/application.meta_lic"},
+ spdxPkgID{"testdata/proprietary/application.meta_lic"},
+ spdxPkgDownloadLocation{"NOASSERTION"},
+ spdxPkgLicenseDeclared{"testdata-firstparty-FIRST_PARTY_LICENSE"},
+ spdxRelationship{"DOCUMENT-Android ", "testdata/proprietary/application.meta_lic", "DESCRIBES"},
+ packageTag{"testdata/proprietary/bin/bin3.meta_lic"},
+ packageName{"testdata/proprietary/bin/bin3.meta_lic"},
+ spdxPkgID{"testdata/proprietary/bin/bin3.meta_lic"},
+ spdxPkgDownloadLocation{"NOASSERTION"},
+ spdxPkgLicenseDeclared{"testdata-restricted-RESTRICTED_LICENSE"},
+ spdxRelationship{"Package-testdata/proprietary/bin/bin3.meta_lic ", "testdata/proprietary/application.meta_lic", "BUILD_TOOL_OF"},
+ packageTag{"testdata/proprietary/lib/liba.so.meta_lic"},
+ packageName{"testdata/proprietary/lib/liba.so.meta_lic"},
+ spdxPkgID{"testdata/proprietary/lib/liba.so.meta_lic"},
+ spdxPkgDownloadLocation{"NOASSERTION"},
+ spdxPkgLicenseDeclared{"testdata-proprietary-PROPRIETARY_LICENSE"},
+ spdxRelationship{"Package-testdata/proprietary/application.meta_lic ", "testdata/proprietary/lib/liba.so.meta_lic", "CONTAINS"},
+ packageTag{"testdata/proprietary/lib/libb.so.meta_lic"},
+ packageName{"testdata/proprietary/lib/libb.so.meta_lic"},
+ spdxPkgID{"testdata/proprietary/lib/libb.so.meta_lic"},
+ spdxPkgDownloadLocation{"NOASSERTION"},
+ spdxPkgLicenseDeclared{"testdata-restricted-RESTRICTED_LICENSE"},
+ spdxRelationship{"Package-testdata/proprietary/lib/libb.so.meta_lic ", "testdata/proprietary/application.meta_lic", "RUNTIME_DEPENDENCY_OF"},
+ spdxLicense{},
+ spdxLicenseID{"testdata-firstparty-FIRST_PARTY_LICENSE"},
+ spdxExtractedText{"&&&First Party License&&&"},
+ spdxExtractedClosingText{},
+ spdxLicenseID{"testdata-proprietary-PROPRIETARY_LICENSE"},
+ spdxExtractedText{"@@@Proprietary License@@@"},
+ spdxExtractedClosingText{},
+ spdxLicenseID{"testdata-restricted-RESTRICTED_LICENSE"},
+ spdxExtractedText{"###Restricted License###"},
+ spdxExtractedClosingText{},
+ },
+ expectedDeps: []string{
+ "testdata/firstparty/FIRST_PARTY_LICENSE",
+ "testdata/proprietary/PROPRIETARY_LICENSE",
+ "testdata/restricted/RESTRICTED_LICENSE",
+ },
+ },
+ {
+ condition: "proprietary",
+ name: "binary",
+ roots: []string{"bin/bin1.meta_lic"},
+ expectedOut: []matcher{
+ spdxVersion{},
+ spdxDataLicense{},
+ spdxDocumentName{"Android"},
+ spdxID{"Android"},
+ spdxDocumentNameSpace{},
+ spdxCreatorOrganization{},
+ spdxCreatedTime{},
+ packageTag{"testdata/proprietary/bin/bin1.meta_lic"},
+ packageName{"testdata/proprietary/bin/bin1.meta_lic"},
+ spdxPkgID{"testdata/proprietary/bin/bin1.meta_lic"},
+ spdxPkgDownloadLocation{"NOASSERTION"},
+ spdxPkgLicenseDeclared{"testdata-firstparty-FIRST_PARTY_LICENSE"},
+ spdxRelationship{"DOCUMENT-Android ", "testdata/proprietary/bin/bin1.meta_lic", "DESCRIBES"},
+ packageTag{"testdata/proprietary/lib/liba.so.meta_lic"},
+ packageName{"testdata/proprietary/lib/liba.so.meta_lic"},
+ spdxPkgID{"testdata/proprietary/lib/liba.so.meta_lic"},
+ spdxPkgDownloadLocation{"NOASSERTION"},
+ spdxPkgLicenseDeclared{"testdata-proprietary-PROPRIETARY_LICENSE"},
+ spdxRelationship{"Package-testdata/proprietary/bin/bin1.meta_lic ", "testdata/proprietary/lib/liba.so.meta_lic", "CONTAINS"},
+ packageTag{"testdata/proprietary/lib/libc.a.meta_lic"},
+ packageName{"testdata/proprietary/lib/libc.a.meta_lic"},
+ spdxPkgID{"testdata/proprietary/lib/libc.a.meta_lic"},
+ spdxPkgDownloadLocation{"NOASSERTION"},
+ spdxPkgLicenseDeclared{"testdata-proprietary-PROPRIETARY_LICENSE"},
+ spdxRelationship{"Package-testdata/proprietary/bin/bin1.meta_lic ", "testdata/proprietary/lib/libc.a.meta_lic", "CONTAINS"},
+ spdxLicense{},
+ spdxLicenseID{"testdata-firstparty-FIRST_PARTY_LICENSE"},
+ spdxExtractedText{"&&&First Party License&&&"},
+ spdxExtractedClosingText{},
+ spdxLicenseID{"testdata-proprietary-PROPRIETARY_LICENSE"},
+ spdxExtractedText{"@@@Proprietary License@@@"},
+ spdxExtractedClosingText{},
+ },
+ expectedDeps: []string{
+ "testdata/firstparty/FIRST_PARTY_LICENSE",
+ "testdata/proprietary/PROPRIETARY_LICENSE",
+ },
+ },
+ {
+ condition: "proprietary",
+ name: "library",
+ roots: []string{"lib/libd.so.meta_lic"},
+ expectedOut: []matcher{
+ spdxVersion{},
+ spdxDataLicense{},
+ spdxDocumentName{"Android"},
+ spdxID{"Android"},
+ spdxDocumentNameSpace{},
+ spdxCreatorOrganization{},
+ spdxCreatedTime{},
+ packageTag{"testdata/proprietary/lib/libd.so.meta_lic"},
+ packageName{"testdata/proprietary/lib/libd.so.meta_lic"},
+ spdxPkgID{"testdata/proprietary/lib/libd.so.meta_lic"},
+ spdxPkgDownloadLocation{"NOASSERTION"},
+ spdxPkgLicenseDeclared{"testdata-notice-NOTICE_LICENSE"},
+ spdxRelationship{"DOCUMENT-Android ", "testdata/proprietary/lib/libd.so.meta_lic", "DESCRIBES"},
+ spdxLicense{},
+ spdxLicenseID{"testdata-notice-NOTICE_LICENSE"},
+ spdxExtractedText{"%%%Notice License%%%"},
+ spdxExtractedClosingText{},
+ },
+ expectedDeps: []string{"testdata/notice/NOTICE_LICENSE"},
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.condition+" "+tt.name, func(t *testing.T) {
+ stdout := &bytes.Buffer{}
+ stderr := &bytes.Buffer{}
+
+ rootFiles := make([]string, 0, len(tt.roots))
+ for _, r := range tt.roots {
+ rootFiles = append(rootFiles, "testdata/"+tt.condition+"/"+r)
+ }
+
+ ctx := context{stdout, stderr, compliance.GetFS(tt.outDir), "Android", []string{tt.stripPrefix}, fakeTime}
+
+ deps, err := sbomGenerator(&ctx, rootFiles...)
+ if err != nil {
+ t.Fatalf("sbom: error = %v, stderr = %v", err, stderr)
+ return
+ }
+ if stderr.Len() > 0 {
+ t.Errorf("sbom: gotStderr = %v, want none", stderr)
+ }
+
+ t.Logf("got stdout: %s", stdout.String())
+
+ t.Logf("want stdout: %s", matcherList(tt.expectedOut).String())
+
+ out := bufio.NewScanner(stdout)
+ lineno := 0
+ for out.Scan() {
+ line := out.Text()
+ if strings.TrimLeft(line, " ") == "" {
+ continue
+ }
+ if len(tt.expectedOut) <= lineno {
+ t.Errorf("sbom: unexpected output at line %d: got %q, want nothing (wanted %d lines)", lineno+1, line, len(tt.expectedOut))
+ } else if !tt.expectedOut[lineno].isMatch(line) {
+ t.Errorf("sbom: unexpected output at line %d: got %q, want %q", lineno+1, line, tt.expectedOut[lineno])
+ }
+ lineno++
+ }
+ for ; lineno < len(tt.expectedOut); lineno++ {
+ t.Errorf("bom: missing output line %d: ended early, want %q", lineno+1, tt.expectedOut[lineno])
+ }
+
+ t.Logf("got deps: %q", deps)
+
+ t.Logf("want deps: %q", tt.expectedDeps)
+
+ if g, w := deps, tt.expectedDeps; !reflect.DeepEqual(g, w) {
+ t.Errorf("unexpected deps, wanted:\n%s\ngot:\n%s\n",
+ strings.Join(w, "\n"), strings.Join(g, "\n"))
+ }
+ })
+ }
+}
+
+type matcher interface {
+ isMatch(line string) bool
+ String() string
+}
+
+type packageTag struct {
+ name string
+}
+
+func (m packageTag) isMatch(line string) bool {
+ groups := spdxPackageTag.FindStringSubmatch(line)
+ if len(groups) != 2 {
+ return false
+ }
+ return groups[1] == m.name
+}
+
+func (m packageTag) String() string {
+ return "##### Package: " + m.name
+}
+
+type packageName struct {
+ name string
+}
+
+func (m packageName) isMatch(line string) bool {
+ groups := spdxPackageNameTag.FindStringSubmatch(line)
+ if len(groups) != 2 {
+ return false
+ }
+ return groups[1] == replaceSlashes(m.name)
+}
+
+func (m packageName) String() string {
+ return "PackageName: " + replaceSlashes(m.name)
+}
+
+type spdxID struct {
+ name string
+}
+
+func (m spdxID) isMatch(line string) bool {
+ groups := spdxIDTag.FindStringSubmatch(line)
+ if len(groups) != 2 {
+ return false
+ }
+ return groups[1] == replaceSlashes(m.name)
+}
+
+func (m spdxID) String() string {
+ return "SPDXID: SPDXRef-DOCUMENT-" + replaceSlashes(m.name)
+}
+
+type spdxPkgID struct {
+ name string
+}
+
+func (m spdxPkgID) isMatch(line string) bool {
+ groups := spdxPkgIDTag.FindStringSubmatch(line)
+ if len(groups) != 2 {
+ return false
+ }
+ return groups[1] == replaceSlashes(m.name)
+}
+
+func (m spdxPkgID) String() string {
+ return "SPDXID: SPDXRef-Package-" + replaceSlashes(m.name)
+}
+
+type spdxVersion struct{}
+
+func (m spdxVersion) isMatch(line string) bool {
+ return spdxVersionTag.MatchString(line)
+}
+
+func (m spdxVersion) String() string {
+ return "SPDXVersion: SPDX-2.2"
+}
+
+type spdxDataLicense struct{}
+
+func (m spdxDataLicense) isMatch(line string) bool {
+ return spdxDataLicenseTag.MatchString(line)
+}
+
+func (m spdxDataLicense) String() string {
+ return "DataLicense: CC-1.0"
+}
+
+type spdxDocumentName struct {
+ name string
+}
+
+func (m spdxDocumentName) isMatch(line string) bool {
+ return spdxDocumentNameTag.MatchString(line)
+}
+
+func (m spdxDocumentName) String() string {
+ return "DocumentName: " + m.name
+}
+
+type spdxDocumentNameSpace struct {
+ name string
+}
+
+func (m spdxDocumentNameSpace) isMatch(line string) bool {
+ return spdxDocumentNameSpaceTag.MatchString(line)
+}
+
+func (m spdxDocumentNameSpace) String() string {
+ return "DocumentNameSpace: Android"
+}
+
+type spdxCreatorOrganization struct{}
+
+func (m spdxCreatorOrganization) isMatch(line string) bool {
+ return spdxCreatorOrganizationTag.MatchString(line)
+}
+
+func (m spdxCreatorOrganization) String() string {
+ return "Creator: Organization: Google LLC"
+}
+
+func fakeTime() time.Time {
+ return time.UnixMicro(0)
+}
+
+type spdxCreatedTime struct{}
+
+func (m spdxCreatedTime) isMatch(line string) bool {
+ return spdxCreatedTimeTag.MatchString(line)
+}
+
+func (m spdxCreatedTime) String() string {
+ return "Created: 1970-01-01T00:00:00Z"
+}
+
+type spdxPkgDownloadLocation struct {
+ name string
+}
+
+func (m spdxPkgDownloadLocation) isMatch(line string) bool {
+ return spdxPkgDownloadLocationTag.MatchString(line)
+}
+
+func (m spdxPkgDownloadLocation) String() string {
+ return "PackageDownloadLocation: " + m.name
+}
+
+type spdxPkgLicenseDeclared struct {
+ name string
+}
+
+func (m spdxPkgLicenseDeclared) isMatch(line string) bool {
+ groups := spdxPkgLicenseDeclaredTag.FindStringSubmatch(line)
+ if len(groups) != 2 {
+ return false
+ }
+ return groups[1] == replaceSlashes(m.name)
+}
+
+func (m spdxPkgLicenseDeclared) String() string {
+ return "PackageLicenseConcluded: LicenseRef-" + m.name
+}
+
+type spdxRelationship struct {
+ pkg1 string
+ pkg2 string
+ relation string
+}
+
+func (m spdxRelationship) isMatch(line string) bool {
+ groups := spdxRelationshipTag.FindStringSubmatch(line)
+ if len(groups) != 4 {
+ return false
+ }
+ return groups[1] == replaceSlashes(m.pkg1) && groups[2] == m.relation && groups[3] == replaceSlashes(m.pkg2)
+}
+
+func (m spdxRelationship) String() string {
+ return "Relationship: SPDXRef-" + replaceSlashes(m.pkg1) + " " + m.relation + " SPDXRef-Package-" + replaceSlashes(m.pkg2)
+}
+
+type spdxLicense struct{}
+
+func (m spdxLicense) isMatch(line string) bool {
+ return spdxLicenseTag.MatchString(line)
+}
+
+func (m spdxLicense) String() string {
+ return "##### Non-standard license:"
+}
+
+type spdxLicenseID struct {
+ name string
+}
+
+func (m spdxLicenseID) isMatch(line string) bool {
+ groups := spdxLicenseIDTag.FindStringSubmatch(line)
+ if len(groups) != 2 {
+ return false
+ }
+ return groups[1] == replaceSlashes(m.name)
+}
+
+func (m spdxLicenseID) String() string {
+ return "LicenseID: LicenseRef-" + m.name
+}
+
+type spdxExtractedText struct {
+ name string
+}
+
+func (m spdxExtractedText) isMatch(line string) bool {
+ groups := spdxExtractedTextTag.FindStringSubmatch(line)
+ if len(groups) != 2 {
+ return false
+ }
+ return groups[1] == replaceSlashes(m.name)
+}
+
+func (m spdxExtractedText) String() string {
+ return "ExtractedText: " + m.name
+}
+
+type spdxExtractedClosingText struct{}
+
+func (m spdxExtractedClosingText) isMatch(line string) bool {
+ return spdxExtractedClosingTextTag.MatchString(line)
+}
+
+func (m spdxExtractedClosingText) String() string {
+ return ""
+}
+
+type matcherList []matcher
+
+func (l matcherList) String() string {
+ var sb strings.Builder
+ for _, m := range l {
+ s := m.String()
+ fmt.Fprintf(&sb, "%s\n", s)
+ }
+ return sb.String()
+}
diff --git a/tools/compliance/graph.go b/tools/compliance/graph.go
index cd5fd5908b..80a2f47e58 100644
--- a/tools/compliance/graph.go
+++ b/tools/compliance/graph.go
@@ -137,6 +137,24 @@ func (e *TargetEdge) Annotations() TargetEdgeAnnotations {
return e.annotations
}
+// IsRuntimeDependency returns true for edges representing shared libraries
+// linked dynamically at runtime.
+func (e *TargetEdge) IsRuntimeDependency() bool {
+ return edgeIsDynamicLink(e)
+}
+
+// IsDerivation returns true for edges where the target is a derivative
+// work of dependency.
+func (e *TargetEdge) IsDerivation() bool {
+ return edgeIsDerivation(e)
+}
+
+// IsBuildTool returns true for edges where the target is built
+// by dependency.
+func (e *TargetEdge) IsBuildTool() bool {
+ return !edgeIsDerivation(e) && !edgeIsDynamicLink(e)
+}
+
// String returns a human-readable string representation of the edge.
func (e *TargetEdge) String() string {
return fmt.Sprintf("%s -[%s]> %s", e.target.name, strings.Join(e.annotations.AsList(), ", "), e.dependency.name)
@@ -186,6 +204,11 @@ func (s TargetEdgePathSegment) Dependency() *TargetNode {
return s.edge.dependency
}
+// Edge describes the target edge.
+func (s TargetEdgePathSegment) Edge() *TargetEdge {
+ return s.edge
+}
+
// Annotations describes the type of edge by the set of annotations attached to
// it.
//
@@ -298,6 +321,11 @@ func (tn *TargetNode) PackageName() string {
return tn.proto.GetPackageName()
}
+// ModuleName returns the module name of the target.
+func (tn *TargetNode) ModuleName() string {
+ return tn.proto.GetModuleName()
+}
+
// Projects returns the projects defining the target node. (unordered)
//
// In an ideal world, only 1 project defines a target, but the interaction