diff options
author | Steve Winslow <swinslow@gmail.com> | 2018-12-06 13:49:23 +0900 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-12-06 13:49:23 +0900 |
commit | b7ba1c5e88bf4fecc99d5c1b7eaa8181b1b812ef (patch) | |
tree | 30450e3e9c63bf4082312d85bfeb991e87cdbb86 | |
parent | f2a02a074474f548200d5efda6317dc39f004f0f (diff) | |
parent | c7f466f2e6a0afb7a52546fb5ab6b248e024e7bd (diff) | |
download | spdx-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.md | 1 | ||||
-rw-r--r-- | docs/licensediff-assumptions.md | 7 | ||||
-rw-r--r-- | examples/6-licensediff/example_licensediff.go | 106 | ||||
-rw-r--r-- | examples/README.md | 11 | ||||
-rw-r--r-- | v0/licensediff/licensediff.go | 81 | ||||
-rw-r--r-- | v0/licensediff/licensediff_test.go | 499 |
6 files changed, 705 insertions, 0 deletions
@@ -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) + } + +} |