aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSteve Winslow <swinslow@gmail.com>2018-12-06 13:49:23 +0900
committerGitHub <noreply@github.com>2018-12-06 13:49:23 +0900
commitb7ba1c5e88bf4fecc99d5c1b7eaa8181b1b812ef (patch)
tree30450e3e9c63bf4082312d85bfeb991e87cdbb86
parentf2a02a074474f548200d5efda6317dc39f004f0f (diff)
parentc7f466f2e6a0afb7a52546fb5ab6b248e024e7bd (diff)
downloadspdx-tools-b7ba1c5e88bf4fecc99d5c1b7eaa8181b1b812ef.tar.gz
Merge pull request #32 from swinslow/licensediff
Enable making diff of licenses between two SPDX Packages Signed-off-by: Steve Winslow <swinslow@gmail.com>
-rw-r--r--README.md1
-rw-r--r--docs/licensediff-assumptions.md7
-rw-r--r--examples/6-licensediff/example_licensediff.go106
-rw-r--r--examples/README.md11
-rw-r--r--v0/licensediff/licensediff.go81
-rw-r--r--v0/licensediff/licensediff_test.go499
6 files changed, 705 insertions, 0 deletions
diff --git a/README.md b/README.md
index c0a53e9..c78d768 100644
--- a/README.md
+++ b/README.md
@@ -22,6 +22,7 @@ spdx-go provides the following packages:
* *v0/tvsaver* - tag-value file saver
* *v0/builder* - builds "empty" SPDX document (with hashes) for directory contents
* *v0/idsearcher* - searches for [SPDX short-form IDs](https://spdx.org/ids/) and builds SPDX document
+* *v0/licensediff* - compares concluded licenses between files in two packages
* *v0/reporter* - generates basic license count report from SPDX document
* *v0/utils* - various utility functions that support the other spdx-go packages
diff --git a/docs/licensediff-assumptions.md b/docs/licensediff-assumptions.md
new file mode 100644
index 0000000..d587791
--- /dev/null
+++ b/docs/licensediff-assumptions.md
@@ -0,0 +1,7 @@
+SPDX-License-Identifier: CC-BY-4.0
+
+The License diff tool in `package licensediff` makes the following assumptions:
+
+- In any single Package, a given filename will only appear once. This may or may
+ not be required by the SPDX spec, but it's kind of implicit in being able to
+ create a diff indexed by filename. \ No newline at end of file
diff --git a/examples/6-licensediff/example_licensediff.go b/examples/6-licensediff/example_licensediff.go
new file mode 100644
index 0000000..d7ff562
--- /dev/null
+++ b/examples/6-licensediff/example_licensediff.go
@@ -0,0 +1,106 @@
+// SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
+
+// Example for: *licensediff*, *tvloader*
+
+// This example demonstrates loading two SPDX tag-value files from disk into
+// memory, and generating a diff of the concluded licenses for Files in the
+// first-listed Packages in each document.
+// This is generally only useful when run with two SPDX documents that
+// describe licenses for subsequent versions of the same set of files.
+
+package main
+
+import (
+ "fmt"
+ "os"
+
+ "github.com/swinslow/spdx-go/v0/licensediff"
+ "github.com/swinslow/spdx-go/v0/tvloader"
+)
+
+func main() {
+
+ // check that we've received the right number of arguments
+ args := os.Args
+ if len(args) != 3 {
+ fmt.Printf("Usage: %v <spdx-file-first> <spdx-file-second>\n", args[0])
+ fmt.Printf(" Load SPDX 2.1 tag-value files <spdx-file-first> and <spdx-file-second>,\n")
+ fmt.Printf(" run a diff between their concluded licenses, and print basic results.\n")
+ return
+ }
+
+ // open the first SPDX file
+ filenameFirst := args[1]
+ r, err := os.Open(filenameFirst)
+ if err != nil {
+ fmt.Printf("Error while opening %v for reading: %v", filenameFirst, err)
+ return
+ }
+ defer r.Close()
+
+ // try to load the first SPDX file's contents as a tag-value file, version 2.1
+ docFirst, err := tvloader.Load2_1(r)
+ if err != nil {
+ fmt.Printf("Error while parsing %v: %v", filenameFirst, err)
+ return
+ }
+ // make sure it has at least one Package
+ if len(docFirst.Packages) < 1 {
+ fmt.Printf("Error, no packages found in SPDX file %s\n", filenameFirst)
+ return
+ }
+
+ // if we got here, the file is now loaded into memory.
+ fmt.Printf("Successfully loaded first SPDX file %s\n", filenameFirst)
+
+ // open the second SPDX file
+ filenameSecond := args[2]
+ r, err = os.Open(filenameSecond)
+ if err != nil {
+ fmt.Printf("Error while opening %v for reading: %v", filenameSecond, err)
+ return
+ }
+ defer r.Close()
+
+ // try to load the second SPDX file's contents as a tag-value file, version 2.1
+ docSecond, err := tvloader.Load2_1(r)
+ if err != nil {
+ fmt.Printf("Error while parsing %v: %v", filenameSecond, err)
+ return
+ }
+ // make sure it has at least one Package
+ if len(docSecond.Packages) < 1 {
+ fmt.Printf("Error, no packages found in SPDX file %s\n", filenameSecond)
+ return
+ }
+
+ // if we got here, the file is now loaded into memory.
+ fmt.Printf("Successfully loaded second SPDX file %s\n\n", filenameSecond)
+
+ // extract the first-listed package from each Document.
+ // (there could be more than one Package within a Document. For
+ // purposes of this example, we'll just look at the first one.)
+ // we've already confirmed above that each has at least one Package.
+ p1 := docFirst.Packages[0]
+ p2 := docSecond.Packages[0]
+
+ // now, run a diff between the two
+ pairs, err := licensediff.MakePairs(p1, p2)
+ if err != nil {
+ fmt.Printf("Error generating licensediff pairs: %v\n", err)
+ return
+ }
+
+ // take the pairs and turn them into a more structured results set
+ resultSet, err := licensediff.MakeResults(pairs)
+ if err != nil {
+ fmt.Printf("Error generating licensediff results set: %v\n", err)
+ return
+ }
+
+ // print some information about the results
+ fmt.Printf("Files in first only: %d\n", len(resultSet.InFirstOnly))
+ fmt.Printf("Files in second only: %d\n", len(resultSet.InSecondOnly))
+ fmt.Printf("Files in both with different licenses: %d\n", len(resultSet.InBothChanged))
+ fmt.Printf("Files in both with same licenses: %d\n", len(resultSet.InBothSame))
+}
diff --git a/examples/README.md b/examples/README.md
index 64e41f2..19a58b9 100644
--- a/examples/README.md
+++ b/examples/README.md
@@ -42,3 +42,14 @@ Package and File license fields; and saving the resulting document to disk.
This example demonstrates loading an SPDX tag-value file from disk into memory,
generating a basic report listing counts of the concluded licenses for its
files, and printing the report to standard output.
+
+## 6-licensediff
+
+*licensediff*, *tvloader*
+
+This example demonstrates loading two SPDX tag-value files from disk into
+memory, and generating a diff of the concluded licenses for Files in the
+first-listed Packages in each document.
+
+This is generally only useful when run with two SPDX documents that describe
+licenses for subsequent versions of the same set of files.
diff --git a/v0/licensediff/licensediff.go b/v0/licensediff/licensediff.go
new file mode 100644
index 0000000..1b78a57
--- /dev/null
+++ b/v0/licensediff/licensediff.go
@@ -0,0 +1,81 @@
+// Package licensediff is used to generate a "diff" between the concluded
+// licenses in two SPDX Packages, using the filename as the match point.
+// SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
+package licensediff
+
+import (
+ "github.com/swinslow/spdx-go/v0/spdx"
+)
+
+// LicensePair is a result set where we are talking about two license strings,
+// potentially differing, for a single filename between two SPDX Packages.
+type LicensePair struct {
+ First string
+ Second string
+}
+
+// MakePairs essentially just consolidates all files and LicenseConcluded
+// strings into a single data structure.
+func MakePairs(p1 *spdx.Package2_1, p2 *spdx.Package2_1) (map[string]LicensePair, error) {
+ pairs := map[string]LicensePair{}
+
+ // first, go through and add all files/licenses from p1
+ for _, f := range p1.Files {
+ pair := LicensePair{First: f.LicenseConcluded, Second: ""}
+ pairs[f.FileName] = pair
+ }
+
+ // now, go through all files/licenses from p2. If already
+ // present, add as .second; if not, create new pair
+ for _, f := range p2.Files {
+ firstLic := ""
+ existingPair, ok := pairs[f.FileName]
+ if ok {
+ // already present; update it
+ firstLic = existingPair.First
+ }
+ // now, update what's there, either way
+ pair := LicensePair{First: firstLic, Second: f.LicenseConcluded}
+ pairs[f.FileName] = pair
+ }
+
+ return pairs, nil
+}
+
+// LicenseDiff is a structured version of the output of MakePairs. It is
+// meant to make it easier to find and report on, e.g., just the files that
+// have different licenses, or those that are in just one scan.
+type LicenseDiff struct {
+ InBothChanged map[string]LicensePair
+ InBothSame map[string]string
+ InFirstOnly map[string]string
+ InSecondOnly map[string]string
+}
+
+// MakeResults creates a more structured set of results from the output
+// of MakePairs.
+func MakeResults(pairs map[string]LicensePair) (*LicenseDiff, error) {
+ diff := &LicenseDiff{
+ InBothChanged: map[string]LicensePair{},
+ InBothSame: map[string]string{},
+ InFirstOnly: map[string]string{},
+ InSecondOnly: map[string]string{},
+ }
+
+ // walk through pairs and allocate them where they belong
+ for filename, pair := range pairs {
+ if pair.First == pair.Second {
+ diff.InBothSame[filename] = pair.First
+ } else {
+ if pair.First == "" {
+ diff.InSecondOnly[filename] = pair.Second
+ } else if pair.Second == "" {
+ diff.InFirstOnly[filename] = pair.First
+ } else {
+ diff.InBothChanged[filename] = pair
+ }
+ }
+ }
+
+ return diff, nil
+}
diff --git a/v0/licensediff/licensediff_test.go b/v0/licensediff/licensediff_test.go
new file mode 100644
index 0000000..b12cc60
--- /dev/null
+++ b/v0/licensediff/licensediff_test.go
@@ -0,0 +1,499 @@
+// SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
+
+package licensediff
+
+import (
+ "testing"
+
+ "github.com/swinslow/spdx-go/v0/spdx"
+)
+
+// ===== License diff top-level function tests =====
+func TestDifferCanCreateDiffPairs(t *testing.T) {
+ // create files to be used in diff
+ // f1 will be identical in both
+ f1 := &spdx.File2_1{
+ FileName: "/project/file1.txt",
+ FileSPDXIdentifier: "SPDXRef-File561",
+ FileChecksumSHA1: "6c92dc8bc462b6889d9b1c0bc16c54d19a2cbdd3",
+ LicenseConcluded: "Apache-2.0",
+ LicenseInfoInFile: []string{
+ "LicenseRef-We-will-ignore-LicenseInfoInFile",
+ },
+ FileCopyrightText: "We'll ignore copyright values",
+ }
+
+ // f2 will only appear in the first Package
+ f2 := &spdx.File2_1{
+ FileName: "/project/file2.txt",
+ FileSPDXIdentifier: "SPDXRef-File562",
+ FileChecksumSHA1: "066c5139bd9a43d15812ec1a1755b08ccf199824",
+ LicenseConcluded: "GPL-2.0-or-later",
+ LicenseInfoInFile: []string{
+ "NOASSERTION",
+ },
+ FileCopyrightText: "NOASSERTION",
+ }
+
+ // f3 will only appear in the second Package
+ f3 := &spdx.File2_1{
+ FileName: "/project/file3.txt",
+ FileSPDXIdentifier: "SPDXRef-File563",
+ FileChecksumSHA1: "bd0f4863b15fad2b79b35303af54fcb5baaf7c68",
+ LicenseConcluded: "MPL-2.0",
+ LicenseInfoInFile: []string{
+ "NOASSERTION",
+ },
+ FileCopyrightText: "NOASSERTION",
+ }
+
+ // f4_1 and f4_2 will appear in first and second,
+ // with same name, same hash and different license
+ f4_1 := &spdx.File2_1{
+ FileName: "/project/file4.txt",
+ FileSPDXIdentifier: "SPDXRef-File564",
+ FileChecksumSHA1: "bc417a575ceae93435bcb7bfd382ac28cbdaa8b5",
+ LicenseConcluded: "MIT",
+ LicenseInfoInFile: []string{
+ "NOASSERTION",
+ },
+ FileCopyrightText: "NOASSERTION",
+ }
+ f4_2 := &spdx.File2_1{
+ FileName: "/project/file4.txt",
+ FileSPDXIdentifier: "SPDXRef-File564",
+ FileChecksumSHA1: "bc417a575ceae93435bcb7bfd382ac28cbdaa8b5",
+ LicenseConcluded: "Apache-2.0 AND MIT",
+ LicenseInfoInFile: []string{
+ "NOASSERTION",
+ },
+ FileCopyrightText: "NOASSERTION",
+ }
+
+ // f5_1 and f5_2 will appear in first and second,
+ // with same name, different hash and same license
+ f5_1 := &spdx.File2_1{
+ FileName: "/project/file5.txt",
+ FileSPDXIdentifier: "SPDXRef-File565",
+ FileChecksumSHA1: "ba226db943bbbf455da77afab6f16dbab156d000",
+ LicenseConcluded: "BSD-3-Clause",
+ LicenseInfoInFile: []string{
+ "NOASSERTION",
+ },
+ FileCopyrightText: "NOASSERTION",
+ }
+ f5_2 := &spdx.File2_1{
+ FileName: "/project/file5.txt",
+ FileSPDXIdentifier: "SPDXRef-File565",
+ FileChecksumSHA1: "b6e0ec7d085c5699b46f6f8d425413702652874d",
+ LicenseConcluded: "BSD-3-Clause",
+ LicenseInfoInFile: []string{
+ "NOASSERTION",
+ },
+ FileCopyrightText: "NOASSERTION",
+ }
+
+ // f6_1 and f6_2 will appear in first and second,
+ // with same name, different hash and different license
+ f6_1 := &spdx.File2_1{
+ FileName: "/project/file6.txt",
+ FileSPDXIdentifier: "SPDXRef-File566",
+ FileChecksumSHA1: "ba226db943bbbf455da77afab6f16dbab156d000",
+ LicenseConcluded: "CC0-1.0",
+ LicenseInfoInFile: []string{
+ "NOASSERTION",
+ },
+ FileCopyrightText: "NOASSERTION",
+ }
+ f6_2 := &spdx.File2_1{
+ FileName: "/project/file6.txt",
+ FileSPDXIdentifier: "SPDXRef-File566",
+ FileChecksumSHA1: "b6e0ec7d085c5699b46f6f8d425413702652874d",
+ LicenseConcluded: "Unlicense",
+ LicenseInfoInFile: []string{
+ "NOASSERTION",
+ },
+ FileCopyrightText: "NOASSERTION",
+ }
+
+ // create Packages
+ p1 := &spdx.Package2_1{
+ IsUnpackaged: false,
+ PackageName: "p1",
+ PackageSPDXIdentifier: "SPDXRef-p1",
+ PackageDownloadLocation: "NOASSERTION",
+ FilesAnalyzed: true,
+ IsFilesAnalyzedTagPresent: true,
+ // fake the verification code for present purposes
+ PackageVerificationCode: "abc123abc123",
+ PackageLicenseConcluded: "NOASSERTION",
+ PackageLicenseInfoFromFiles: []string{
+ "NOASSERTION",
+ },
+ PackageLicenseDeclared: "NOASSERTION",
+ PackageCopyrightText: "NOASSERTION",
+ Files: []*spdx.File2_1{
+ f1,
+ f2,
+ f4_1,
+ f5_1,
+ f6_1,
+ },
+ }
+ p2 := &spdx.Package2_1{
+ IsUnpackaged: false,
+ PackageName: "p2",
+ PackageSPDXIdentifier: "SPDXRef-p2",
+ PackageDownloadLocation: "NOASSERTION",
+ FilesAnalyzed: true,
+ IsFilesAnalyzedTagPresent: true,
+ // fake the verification code for present purposes
+ PackageVerificationCode: "def456def456",
+ PackageLicenseConcluded: "NOASSERTION",
+ PackageLicenseInfoFromFiles: []string{
+ "NOASSERTION",
+ },
+ PackageLicenseDeclared: "NOASSERTION",
+ PackageCopyrightText: "NOASSERTION",
+ Files: []*spdx.File2_1{
+ f1,
+ f3,
+ f4_2,
+ f5_2,
+ f6_2,
+ },
+ }
+
+ // run the diff between the two packages
+ diffMap, err := MakePairs(p1, p2)
+ if err != nil {
+ t.Fatalf("Expected nil error, got %v", err)
+ }
+
+ // check that the diff results are what we expect
+ // there should be 6 entries, one for each unique filename
+ if len(diffMap) != 6 {
+ t.Fatalf("Expected %d, got %d", 6, len(diffMap))
+ }
+
+ // check each filename is present, and check its pair
+ // pair 1 -- same in both
+ pair1, ok := diffMap["/project/file1.txt"]
+ if !ok {
+ t.Fatalf("Couldn't get pair1")
+ }
+ if pair1.First != f1.LicenseConcluded {
+ t.Errorf("Expected %s, got %s", f1.LicenseConcluded, pair1.First)
+ }
+ if pair1.Second != f1.LicenseConcluded {
+ t.Errorf("Expected %s, got %s", f2.LicenseConcluded, pair1.Second)
+ }
+
+ // pair 2 -- only in first
+ pair2, ok := diffMap["/project/file2.txt"]
+ if !ok {
+ t.Fatalf("Couldn't get pair2")
+ }
+ if pair2.First != f2.LicenseConcluded {
+ t.Errorf("Expected %s, got %s", f2.LicenseConcluded, pair2.First)
+ }
+ if pair2.Second != "" {
+ t.Errorf("Expected %s, got %s", "", pair2.Second)
+ }
+
+ // pair 3 -- only in second
+ pair3, ok := diffMap["/project/file3.txt"]
+ if !ok {
+ t.Fatalf("Couldn't get pair3")
+ }
+ if pair3.First != "" {
+ t.Errorf("Expected %s, got %s", "", pair3.First)
+ }
+ if pair3.Second != f3.LicenseConcluded {
+ t.Errorf("Expected %s, got %s", f3.LicenseConcluded, pair3.Second)
+ }
+
+ // pair 4 -- in both but different license
+ pair4, ok := diffMap["/project/file4.txt"]
+ if !ok {
+ t.Fatalf("Couldn't get pair4")
+ }
+ if pair4.First != f4_1.LicenseConcluded {
+ t.Errorf("Expected %s, got %s", f4_1.LicenseConcluded, pair4.First)
+ }
+ if pair4.Second != f4_2.LicenseConcluded {
+ t.Errorf("Expected %s, got %s", f4_2.LicenseConcluded, pair4.Second)
+ }
+
+ // pair 5 -- in both but different hash, same license
+ pair5, ok := diffMap["/project/file5.txt"]
+ if !ok {
+ t.Fatalf("Couldn't get pair5")
+ }
+ if pair5.First != f5_1.LicenseConcluded {
+ t.Errorf("Expected %s, got %s", f5_1.LicenseConcluded, pair5.First)
+ }
+ if pair5.Second != f5_2.LicenseConcluded {
+ t.Errorf("Expected %s, got %s", f5_2.LicenseConcluded, pair5.Second)
+ }
+
+ // pair 6 -- in both but different hash, different license
+ pair6, ok := diffMap["/project/file6.txt"]
+ if !ok {
+ t.Fatalf("Couldn't get pair6")
+ }
+ if pair6.First != f6_1.LicenseConcluded {
+ t.Errorf("Expected %s, got %s", f6_1.LicenseConcluded, pair6.First)
+ }
+ if pair6.Second != f6_2.LicenseConcluded {
+ t.Errorf("Expected %s, got %s", f6_2.LicenseConcluded, pair6.Second)
+ }
+}
+
+func TestDifferCanCreateDiffStructuredResults(t *testing.T) {
+ // create files to be used in diff
+ // f1 will be identical in both
+ f1 := &spdx.File2_1{
+ FileName: "/project/file1.txt",
+ FileSPDXIdentifier: "SPDXRef-File561",
+ FileChecksumSHA1: "6c92dc8bc462b6889d9b1c0bc16c54d19a2cbdd3",
+ LicenseConcluded: "Apache-2.0",
+ LicenseInfoInFile: []string{
+ "LicenseRef-We-will-ignore-LicenseInfoInFile",
+ },
+ FileCopyrightText: "We'll ignore copyright values",
+ }
+
+ // f2 will only appear in the first Package
+ f2 := &spdx.File2_1{
+ FileName: "/project/file2.txt",
+ FileSPDXIdentifier: "SPDXRef-File562",
+ FileChecksumSHA1: "066c5139bd9a43d15812ec1a1755b08ccf199824",
+ LicenseConcluded: "GPL-2.0-or-later",
+ LicenseInfoInFile: []string{
+ "NOASSERTION",
+ },
+ FileCopyrightText: "NOASSERTION",
+ }
+
+ // f3 will only appear in the second Package
+ f3 := &spdx.File2_1{
+ FileName: "/project/file3.txt",
+ FileSPDXIdentifier: "SPDXRef-File563",
+ FileChecksumSHA1: "bd0f4863b15fad2b79b35303af54fcb5baaf7c68",
+ LicenseConcluded: "MPL-2.0",
+ LicenseInfoInFile: []string{
+ "NOASSERTION",
+ },
+ FileCopyrightText: "NOASSERTION",
+ }
+
+ // f4_1 and f4_2 will appear in first and second,
+ // with same name, same hash and different license
+ f4_1 := &spdx.File2_1{
+ FileName: "/project/file4.txt",
+ FileSPDXIdentifier: "SPDXRef-File564",
+ FileChecksumSHA1: "bc417a575ceae93435bcb7bfd382ac28cbdaa8b5",
+ LicenseConcluded: "MIT",
+ LicenseInfoInFile: []string{
+ "NOASSERTION",
+ },
+ FileCopyrightText: "NOASSERTION",
+ }
+ f4_2 := &spdx.File2_1{
+ FileName: "/project/file4.txt",
+ FileSPDXIdentifier: "SPDXRef-File564",
+ FileChecksumSHA1: "bc417a575ceae93435bcb7bfd382ac28cbdaa8b5",
+ LicenseConcluded: "Apache-2.0 AND MIT",
+ LicenseInfoInFile: []string{
+ "NOASSERTION",
+ },
+ FileCopyrightText: "NOASSERTION",
+ }
+
+ // f5_1 and f5_2 will appear in first and second,
+ // with same name, different hash and same license
+ f5_1 := &spdx.File2_1{
+ FileName: "/project/file5.txt",
+ FileSPDXIdentifier: "SPDXRef-File565",
+ FileChecksumSHA1: "ba226db943bbbf455da77afab6f16dbab156d000",
+ LicenseConcluded: "BSD-3-Clause",
+ LicenseInfoInFile: []string{
+ "NOASSERTION",
+ },
+ FileCopyrightText: "NOASSERTION",
+ }
+ f5_2 := &spdx.File2_1{
+ FileName: "/project/file5.txt",
+ FileSPDXIdentifier: "SPDXRef-File565",
+ FileChecksumSHA1: "b6e0ec7d085c5699b46f6f8d425413702652874d",
+ LicenseConcluded: "BSD-3-Clause",
+ LicenseInfoInFile: []string{
+ "NOASSERTION",
+ },
+ FileCopyrightText: "NOASSERTION",
+ }
+
+ // f6_1 and f6_2 will appear in first and second,
+ // with same name, different hash and different license
+ f6_1 := &spdx.File2_1{
+ FileName: "/project/file6.txt",
+ FileSPDXIdentifier: "SPDXRef-File566",
+ FileChecksumSHA1: "ba226db943bbbf455da77afab6f16dbab156d000",
+ LicenseConcluded: "CC0-1.0",
+ LicenseInfoInFile: []string{
+ "NOASSERTION",
+ },
+ FileCopyrightText: "NOASSERTION",
+ }
+ f6_2 := &spdx.File2_1{
+ FileName: "/project/file6.txt",
+ FileSPDXIdentifier: "SPDXRef-File566",
+ FileChecksumSHA1: "b6e0ec7d085c5699b46f6f8d425413702652874d",
+ LicenseConcluded: "Unlicense",
+ LicenseInfoInFile: []string{
+ "NOASSERTION",
+ },
+ FileCopyrightText: "NOASSERTION",
+ }
+
+ // create Packages
+ p1 := &spdx.Package2_1{
+ IsUnpackaged: false,
+ PackageName: "p1",
+ PackageSPDXIdentifier: "SPDXRef-p1",
+ PackageDownloadLocation: "NOASSERTION",
+ FilesAnalyzed: true,
+ IsFilesAnalyzedTagPresent: true,
+ // fake the verification code for present purposes
+ PackageVerificationCode: "abc123abc123",
+ PackageLicenseConcluded: "NOASSERTION",
+ PackageLicenseInfoFromFiles: []string{
+ "NOASSERTION",
+ },
+ PackageLicenseDeclared: "NOASSERTION",
+ PackageCopyrightText: "NOASSERTION",
+ Files: []*spdx.File2_1{
+ f1,
+ f2,
+ f4_1,
+ f5_1,
+ f6_1,
+ },
+ }
+ p2 := &spdx.Package2_1{
+ IsUnpackaged: false,
+ PackageName: "p2",
+ PackageSPDXIdentifier: "SPDXRef-p2",
+ PackageDownloadLocation: "NOASSERTION",
+ FilesAnalyzed: true,
+ IsFilesAnalyzedTagPresent: true,
+ // fake the verification code for present purposes
+ PackageVerificationCode: "def456def456",
+ PackageLicenseConcluded: "NOASSERTION",
+ PackageLicenseInfoFromFiles: []string{
+ "NOASSERTION",
+ },
+ PackageLicenseDeclared: "NOASSERTION",
+ PackageCopyrightText: "NOASSERTION",
+ Files: []*spdx.File2_1{
+ f1,
+ f3,
+ f4_2,
+ f5_2,
+ f6_2,
+ },
+ }
+
+ // run the diff between the two packages
+ diffMap, err := MakePairs(p1, p2)
+ if err != nil {
+ t.Fatalf("Expected nil error, got %v", err)
+ }
+
+ // now, create the LicenseDiff structured results from the pairs
+ diffResults, err := MakeResults(diffMap)
+ if err != nil {
+ t.Fatalf("Expected nil error, got %v", err)
+ }
+
+ // check that the diff results are the expected lengths
+ if len(diffResults.InBothChanged) != 2 {
+ t.Fatalf("Expected %d, got %d", 2, len(diffResults.InBothChanged))
+ }
+ if len(diffResults.InBothSame) != 2 {
+ t.Fatalf("Expected %d, got %d", 2, len(diffResults.InBothSame))
+ }
+ if len(diffResults.InFirstOnly) != 1 {
+ t.Fatalf("Expected %d, got %d", 1, len(diffResults.InFirstOnly))
+ }
+ if len(diffResults.InSecondOnly) != 1 {
+ t.Fatalf("Expected %d, got %d", 1, len(diffResults.InSecondOnly))
+ }
+
+ // check each filename is present where it belongs, and check license(s)
+
+ // in both and different license: f4 and f6
+ // filename will map to a LicensePair
+ check4, ok := diffResults.InBothChanged["/project/file4.txt"]
+ if !ok {
+ t.Fatalf("Couldn't get check4")
+ }
+ if check4.First != f4_1.LicenseConcluded {
+ t.Errorf("Expected %s, got %s", f4_1.LicenseConcluded, check4.First)
+ }
+ if check4.Second != f4_2.LicenseConcluded {
+ t.Errorf("Expected %s, got %s", f4_2.LicenseConcluded, check4.Second)
+ }
+ check6, ok := diffResults.InBothChanged["/project/file6.txt"]
+ if !ok {
+ t.Fatalf("Couldn't get check6")
+ }
+ if check6.First != f6_1.LicenseConcluded {
+ t.Errorf("Expected %s, got %s", f6_1.LicenseConcluded, check6.First)
+ }
+ if check6.Second != f6_2.LicenseConcluded {
+ t.Errorf("Expected %s, got %s", f6_2.LicenseConcluded, check6.Second)
+ }
+
+ // in both and same license: f1 and f5
+ // filename will map to a string
+ check1, ok := diffResults.InBothSame["/project/file1.txt"]
+ if !ok {
+ t.Fatalf("Couldn't get check1")
+ }
+ if check1 != f1.LicenseConcluded {
+ t.Errorf("Expected %s, got %s", f1.LicenseConcluded, check1)
+ }
+ check5, ok := diffResults.InBothSame["/project/file5.txt"]
+ if !ok {
+ t.Fatalf("Couldn't get check5")
+ }
+ if check5 != f5_1.LicenseConcluded {
+ t.Errorf("Expected %s, got %s", f5_1.LicenseConcluded, check5)
+ }
+ if check5 != f5_2.LicenseConcluded {
+ t.Errorf("Expected %s, got %s", f5_2.LicenseConcluded, check5)
+ }
+
+ // in first only: f2
+ // filename will map to a string
+ check2, ok := diffResults.InFirstOnly["/project/file2.txt"]
+ if !ok {
+ t.Fatalf("Couldn't get check2")
+ }
+ if check2 != f2.LicenseConcluded {
+ t.Errorf("Expected %s, got %s", f2.LicenseConcluded, check2)
+ }
+
+ // in second only: f3
+ // filename will map to a string
+ check3, ok := diffResults.InSecondOnly["/project/file3.txt"]
+ if !ok {
+ t.Fatalf("Couldn't get check3")
+ }
+ if check3 != f3.LicenseConcluded {
+ t.Errorf("Expected %s, got %s", f3.LicenseConcluded, check2)
+ }
+
+}