Merge "compliance package policy and resolves" am: 45deca7ff7
am: e7d26816bb
Original change: https://android-review.googlesource.com/c/platform/build/+/1870078 Change-Id: I9b279f3a0a47517440cca2beba7c028f7c9e02fb
This commit is contained in:
@@ -24,6 +24,14 @@ bootstrap_go_package {
|
||||
"condition.go",
|
||||
"conditionset.go",
|
||||
"graph.go",
|
||||
"policy/policy.go",
|
||||
"policy/resolve.go",
|
||||
"policy/resolvenotices.go",
|
||||
"policy/resolveshare.go",
|
||||
"policy/resolveprivacy.go",
|
||||
"policy/shareprivacyconflicts.go",
|
||||
"policy/shipped.go",
|
||||
"policy/walk.go",
|
||||
"readgraph.go",
|
||||
"resolution.go",
|
||||
"resolutionset.go",
|
||||
@@ -32,6 +40,14 @@ bootstrap_go_package {
|
||||
"condition_test.go",
|
||||
"conditionset_test.go",
|
||||
"readgraph_test.go",
|
||||
"policy/policy_test.go",
|
||||
"policy/resolve_test.go",
|
||||
"policy/resolvenotices_test.go",
|
||||
"policy/resolveshare_test.go",
|
||||
"policy/resolveprivacy_test.go",
|
||||
"policy/shareprivacyconflicts_test.go",
|
||||
"policy/shipped_test.go",
|
||||
"policy/walk_test.go",
|
||||
"resolutionset_test.go",
|
||||
"test_util.go",
|
||||
],
|
||||
|
238
tools/compliance/policy/policy.go
Normal file
238
tools/compliance/policy/policy.go
Normal file
@@ -0,0 +1,238 @@
|
||||
// Copyright 2021 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 compliance
|
||||
|
||||
import (
|
||||
"regexp"
|
||||
"strings"
|
||||
)
|
||||
|
||||
var (
|
||||
// ImpliesUnencumbered lists the condition names representing an author attempt to disclaim copyright.
|
||||
ImpliesUnencumbered = ConditionNames{"unencumbered"}
|
||||
|
||||
// ImpliesPermissive lists the condition names representing copyrighted but "licensed without policy requirements".
|
||||
ImpliesPermissive = ConditionNames{"permissive"}
|
||||
|
||||
// ImpliesNotice lists the condition names implying a notice or attribution policy.
|
||||
ImpliesNotice = ConditionNames{"unencumbered", "permissive", "notice", "reciprocal", "restricted", "proprietary", "by_exception_only"}
|
||||
|
||||
// ImpliesReciprocal lists the condition names implying a local source-sharing policy.
|
||||
ImpliesReciprocal = ConditionNames{"reciprocal"}
|
||||
|
||||
// Restricted lists the condition names implying an infectious source-sharing policy.
|
||||
ImpliesRestricted = ConditionNames{"restricted"}
|
||||
|
||||
// ImpliesProprietary lists the condition names implying a confidentiality policy.
|
||||
ImpliesProprietary = ConditionNames{"proprietary"}
|
||||
|
||||
// ImpliesByExceptionOnly lists the condition names implying a policy for "license review and approval before use".
|
||||
ImpliesByExceptionOnly = ConditionNames{"proprietary", "by_exception_only"}
|
||||
|
||||
// ImpliesPrivate lists the condition names implying a source-code privacy policy.
|
||||
ImpliesPrivate = ConditionNames{"proprietary"}
|
||||
|
||||
// ImpliesShared lists the condition names implying a source-code sharing policy.
|
||||
ImpliesShared = ConditionNames{"reciprocal", "restricted"}
|
||||
)
|
||||
|
||||
var (
|
||||
anyLgpl = regexp.MustCompile(`^SPDX-license-identifier-LGPL.*`)
|
||||
versionedGpl = regexp.MustCompile(`^SPDX-license-identifier-GPL-\p{N}.*`)
|
||||
genericGpl = regexp.MustCompile(`^SPDX-license-identifier-GPL$`)
|
||||
ccBySa = regexp.MustCompile(`^SPDX-license-identifier-CC-BY.*-SA.*`)
|
||||
)
|
||||
|
||||
// Resolution happens in two passes:
|
||||
//
|
||||
// 1. A bottom-up traversal propagates license conditions up to targets from
|
||||
// dendencies as needed.
|
||||
//
|
||||
// 2. For each condition of interest, a top-down traversal adjusts the attached
|
||||
// conditions pushing restricted down from targets into linked dependencies.
|
||||
//
|
||||
// The behavior of the 2 passes gets controlled by the 2 functions below.
|
||||
//
|
||||
// The first function controls what happens during the bottom-up traversal. In
|
||||
// general conditions flow up through static links but not other dependencies;
|
||||
// except, restricted sometimes flows up through dynamic links.
|
||||
//
|
||||
// In general, too, the originating target gets acted on to resolve the
|
||||
// condition (e.g. providing notice), but again restricted is special in that
|
||||
// it requires acting on (i.e. sharing source of) both the originating module
|
||||
// and the target using the module.
|
||||
//
|
||||
// The latter function controls what happens during the top-down traversal. In
|
||||
// general, only restricted conditions flow down at all, and only through
|
||||
// static links.
|
||||
//
|
||||
// Not all restricted licenses are create equal. Some have special rules or
|
||||
// exceptions. e.g. LGPL or "with classpath excption".
|
||||
|
||||
// depActionsApplicableToTarget returns the actions which propagate up an
|
||||
// edge from dependency to target.
|
||||
//
|
||||
// This function sets the policy for the bottom-up traversal and how conditions
|
||||
// flow up the graph from dependencies to targets.
|
||||
//
|
||||
// If a pure aggregation is built into a derivative work that is not a pure
|
||||
// aggregation, per policy it ceases to be a pure aggregation in the context of
|
||||
// that derivative work. The `treatAsAggregate` parameter will be false for
|
||||
// non-aggregates and for aggregates in non-aggregate contexts.
|
||||
func depActionsApplicableToTarget(e TargetEdge, depActions actionSet, treatAsAggregate bool) actionSet {
|
||||
result := make(actionSet)
|
||||
if edgeIsDerivation(e) {
|
||||
result.addSet(depActions)
|
||||
for _, cs := range depActions.byName(ImpliesRestricted) {
|
||||
result.add(e.Target(), cs)
|
||||
}
|
||||
return result
|
||||
}
|
||||
if !edgeIsDynamicLink(e) {
|
||||
return result
|
||||
}
|
||||
|
||||
restricted := depActions.byName(ImpliesRestricted)
|
||||
for actsOn, cs := range restricted {
|
||||
for _, lc := range cs.AsList() {
|
||||
hasGpl := false
|
||||
hasLgpl := false
|
||||
hasClasspath := false
|
||||
hasGeneric := false
|
||||
hasOther := false
|
||||
for _, kind := range lc.origin.LicenseKinds() {
|
||||
if strings.HasSuffix(kind, "-with-classpath-exception") {
|
||||
hasClasspath = true
|
||||
} else if anyLgpl.MatchString(kind) {
|
||||
hasLgpl = true
|
||||
} else if versionedGpl.MatchString(kind) {
|
||||
hasGpl = true
|
||||
} else if genericGpl.MatchString(kind) {
|
||||
hasGeneric = true
|
||||
} else if kind == "legacy_restricted" || ccBySa.MatchString(kind) {
|
||||
hasOther = true
|
||||
}
|
||||
}
|
||||
if hasOther || hasGpl {
|
||||
result.addCondition(actsOn, lc)
|
||||
result.addCondition(e.Target(), lc)
|
||||
continue
|
||||
}
|
||||
if hasClasspath && !edgeNodesAreIndependentModules(e) {
|
||||
result.addCondition(actsOn, lc)
|
||||
result.addCondition(e.Target(), lc)
|
||||
continue
|
||||
}
|
||||
if hasLgpl || hasClasspath {
|
||||
continue
|
||||
}
|
||||
if !hasGeneric {
|
||||
continue
|
||||
}
|
||||
result.addCondition(actsOn, lc)
|
||||
result.addCondition(e.Target(), lc)
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
// targetConditionsApplicableToDep returns the conditions which propagate down
|
||||
// an edge from target to dependency.
|
||||
//
|
||||
// This function sets the policy for the top-down traversal and how conditions
|
||||
// flow down the graph from targets to dependencies.
|
||||
//
|
||||
// If a pure aggregation is built into a derivative work that is not a pure
|
||||
// aggregation, per policy it ceases to be a pure aggregation in the context of
|
||||
// that derivative work. The `treatAsAggregate` parameter will be false for
|
||||
// non-aggregates and for aggregates in non-aggregate contexts.
|
||||
func targetConditionsApplicableToDep(e TargetEdge, targetConditions *LicenseConditionSet, treatAsAggregate bool) *LicenseConditionSet {
|
||||
result := targetConditions.Copy()
|
||||
|
||||
// reverse direction -- none of these apply to things depended-on, only to targets depending-on.
|
||||
result.RemoveAllByName(ConditionNames{"unencumbered", "permissive", "notice", "reciprocal", "proprietary", "by_exception_only"})
|
||||
|
||||
if !edgeIsDerivation(e) && !edgeIsDynamicLink(e) {
|
||||
// target is not a derivative work of dependency and is not linked to dependency
|
||||
result.RemoveAllByName(ImpliesRestricted)
|
||||
return result
|
||||
}
|
||||
if treatAsAggregate {
|
||||
// If the author of a pure aggregate licenses it restricted, apply restricted to immediate dependencies.
|
||||
// Otherwise, restricted does not propagate back down to dependencies.
|
||||
restricted := result.ByName(ImpliesRestricted).AsList()
|
||||
for _, lc := range restricted {
|
||||
if lc.origin.name != e.e.target {
|
||||
result.Remove(lc)
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
if edgeIsDerivation(e) {
|
||||
return result
|
||||
}
|
||||
restricted := result.ByName(ImpliesRestricted).AsList()
|
||||
for _, lc := range restricted {
|
||||
hasGpl := false
|
||||
hasLgpl := false
|
||||
hasClasspath := false
|
||||
hasGeneric := false
|
||||
hasOther := false
|
||||
for _, kind := range lc.origin.LicenseKinds() {
|
||||
if strings.HasSuffix(kind, "-with-classpath-exception") {
|
||||
hasClasspath = true
|
||||
} else if anyLgpl.MatchString(kind) {
|
||||
hasLgpl = true
|
||||
} else if versionedGpl.MatchString(kind) {
|
||||
hasGpl = true
|
||||
} else if genericGpl.MatchString(kind) {
|
||||
hasGeneric = true
|
||||
} else if kind == "legacy_restricted" || ccBySa.MatchString(kind) {
|
||||
hasOther = true
|
||||
}
|
||||
}
|
||||
if hasOther || hasGpl {
|
||||
continue
|
||||
}
|
||||
if hasClasspath && !edgeNodesAreIndependentModules(e) {
|
||||
continue
|
||||
}
|
||||
if hasGeneric && !hasLgpl && !hasClasspath {
|
||||
continue
|
||||
}
|
||||
result.Remove(lc)
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
// edgeIsDynamicLink returns true for edges representing shared libraries
|
||||
// linked dynamically at runtime.
|
||||
func edgeIsDynamicLink(e TargetEdge) bool {
|
||||
return e.e.annotations.HasAnnotation("dynamic")
|
||||
}
|
||||
|
||||
// edgeIsDerivation returns true for edges where the target is a derivative
|
||||
// work of dependency.
|
||||
func edgeIsDerivation(e TargetEdge) bool {
|
||||
isDynamic := e.e.annotations.HasAnnotation("dynamic")
|
||||
isToolchain := e.e.annotations.HasAnnotation("toolchain")
|
||||
return !isDynamic && !isToolchain
|
||||
}
|
||||
|
||||
// edgeNodesAreIndependentModules returns true for edges where the target and
|
||||
// dependency are independent modules.
|
||||
func edgeNodesAreIndependentModules(e TargetEdge) bool {
|
||||
return e.Target().PackageName() != e.Dependency().PackageName()
|
||||
}
|
300
tools/compliance/policy/policy_test.go
Normal file
300
tools/compliance/policy/policy_test.go
Normal file
@@ -0,0 +1,300 @@
|
||||
// Copyright 2021 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 compliance
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"sort"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestPolicy_edgeConditions(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
edge annotated
|
||||
treatAsAggregate bool
|
||||
otherCondition string
|
||||
expectedDepActions []string
|
||||
expectedTargetConditions []string
|
||||
}{
|
||||
{
|
||||
name: "firstparty",
|
||||
edge: annotated{"apacheBin.meta_lic", "apacheLib.meta_lic", []string{"static"}},
|
||||
expectedDepActions: []string{"apacheLib.meta_lic:apacheLib.meta_lic:notice"},
|
||||
expectedTargetConditions: []string{},
|
||||
},
|
||||
{
|
||||
name: "notice",
|
||||
edge: annotated{"mitBin.meta_lic", "mitLib.meta_lic", []string{"static"}},
|
||||
expectedDepActions: []string{"mitLib.meta_lic:mitLib.meta_lic:notice"},
|
||||
expectedTargetConditions: []string{},
|
||||
},
|
||||
{
|
||||
name: "fponlgpl",
|
||||
edge: annotated{"apacheBin.meta_lic", "lgplLib.meta_lic", []string{"static"}},
|
||||
expectedDepActions: []string{
|
||||
"apacheBin.meta_lic:lgplLib.meta_lic:restricted",
|
||||
"lgplLib.meta_lic:lgplLib.meta_lic:restricted",
|
||||
},
|
||||
expectedTargetConditions: []string{},
|
||||
},
|
||||
{
|
||||
name: "fponlgpldynamic",
|
||||
edge: annotated{"apacheBin.meta_lic", "lgplLib.meta_lic", []string{"dynamic"}},
|
||||
expectedDepActions: []string{},
|
||||
expectedTargetConditions: []string{},
|
||||
},
|
||||
{
|
||||
name: "fpongpl",
|
||||
edge: annotated{"apacheBin.meta_lic", "gplLib.meta_lic", []string{"static"}},
|
||||
expectedDepActions: []string{
|
||||
"apacheBin.meta_lic:gplLib.meta_lic:restricted",
|
||||
"gplLib.meta_lic:gplLib.meta_lic:restricted",
|
||||
},
|
||||
expectedTargetConditions: []string{},
|
||||
},
|
||||
{
|
||||
name: "fpongpldynamic",
|
||||
edge: annotated{"apacheBin.meta_lic", "gplLib.meta_lic", []string{"dynamic"}},
|
||||
expectedDepActions: []string{
|
||||
"apacheBin.meta_lic:gplLib.meta_lic:restricted",
|
||||
"gplLib.meta_lic:gplLib.meta_lic:restricted",
|
||||
},
|
||||
expectedTargetConditions: []string{},
|
||||
},
|
||||
{
|
||||
name: "independentmodule",
|
||||
edge: annotated{"apacheBin.meta_lic", "gplWithClasspathException.meta_lic", []string{"dynamic"}},
|
||||
expectedDepActions: []string{},
|
||||
expectedTargetConditions: []string{},
|
||||
},
|
||||
{
|
||||
name: "independentmodulestatic",
|
||||
edge: annotated{"apacheBin.meta_lic", "gplWithClasspathException.meta_lic", []string{"static"}},
|
||||
expectedDepActions: []string{
|
||||
"apacheBin.meta_lic:gplWithClasspathException.meta_lic:restricted",
|
||||
"gplWithClasspathException.meta_lic:gplWithClasspathException.meta_lic:restricted",
|
||||
},
|
||||
expectedTargetConditions: []string{},
|
||||
},
|
||||
{
|
||||
name: "dependentmodule",
|
||||
edge: annotated{"dependentModule.meta_lic", "gplWithClasspathException.meta_lic", []string{"dynamic"}},
|
||||
expectedDepActions: []string{
|
||||
"dependentModule.meta_lic:gplWithClasspathException.meta_lic:restricted",
|
||||
"gplWithClasspathException.meta_lic:gplWithClasspathException.meta_lic:restricted",
|
||||
},
|
||||
expectedTargetConditions: []string{},
|
||||
},
|
||||
|
||||
{
|
||||
name: "lgplonfp",
|
||||
edge: annotated{"lgplBin.meta_lic", "apacheLib.meta_lic", []string{"static"}},
|
||||
expectedDepActions: []string{"apacheLib.meta_lic:apacheLib.meta_lic:notice"},
|
||||
expectedTargetConditions: []string{"lgplBin.meta_lic:restricted"},
|
||||
},
|
||||
{
|
||||
name: "lgplonfpdynamic",
|
||||
edge: annotated{"lgplBin.meta_lic", "apacheLib.meta_lic", []string{"dynamic"}},
|
||||
expectedDepActions: []string{},
|
||||
expectedTargetConditions: []string{},
|
||||
},
|
||||
{
|
||||
name: "gplonfp",
|
||||
edge: annotated{"gplBin.meta_lic", "apacheLib.meta_lic", []string{"static"}},
|
||||
expectedDepActions: []string{"apacheLib.meta_lic:apacheLib.meta_lic:notice"},
|
||||
expectedTargetConditions: []string{"gplBin.meta_lic:restricted"},
|
||||
},
|
||||
{
|
||||
name: "gplcontainer",
|
||||
edge: annotated{"gplContainer.meta_lic", "apacheLib.meta_lic", []string{"static"}},
|
||||
treatAsAggregate: true,
|
||||
expectedDepActions: []string{"apacheLib.meta_lic:apacheLib.meta_lic:notice"},
|
||||
expectedTargetConditions: []string{"gplContainer.meta_lic:restricted"},
|
||||
},
|
||||
{
|
||||
name: "gploncontainer",
|
||||
edge: annotated{"apacheContainer.meta_lic", "apacheLib.meta_lic", []string{"static"}},
|
||||
treatAsAggregate: true,
|
||||
otherCondition: "gplLib.meta_lic:restricted",
|
||||
expectedDepActions: []string{
|
||||
"apacheContainer.meta_lic:gplLib.meta_lic:restricted",
|
||||
"apacheLib.meta_lic:apacheLib.meta_lic:notice",
|
||||
"apacheLib.meta_lic:gplLib.meta_lic:restricted",
|
||||
"gplLib.meta_lic:gplLib.meta_lic:restricted",
|
||||
},
|
||||
expectedTargetConditions: []string{},
|
||||
},
|
||||
{
|
||||
name: "gplonbin",
|
||||
edge: annotated{"apacheBin.meta_lic", "apacheLib.meta_lic", []string{"static"}},
|
||||
treatAsAggregate: false,
|
||||
otherCondition: "gplLib.meta_lic:restricted",
|
||||
expectedDepActions: []string{
|
||||
"apacheBin.meta_lic:gplLib.meta_lic:restricted",
|
||||
"apacheLib.meta_lic:apacheLib.meta_lic:notice",
|
||||
"apacheLib.meta_lic:gplLib.meta_lic:restricted",
|
||||
"gplLib.meta_lic:gplLib.meta_lic:restricted",
|
||||
},
|
||||
expectedTargetConditions: []string{"gplLib.meta_lic:restricted"},
|
||||
},
|
||||
{
|
||||
name: "gplonfpdynamic",
|
||||
edge: annotated{"gplBin.meta_lic", "apacheLib.meta_lic", []string{"dynamic"}},
|
||||
expectedDepActions: []string{},
|
||||
expectedTargetConditions: []string{"gplBin.meta_lic:restricted"},
|
||||
},
|
||||
{
|
||||
name: "independentmodulereverse",
|
||||
edge: annotated{"gplWithClasspathException.meta_lic", "apacheBin.meta_lic", []string{"dynamic"}},
|
||||
expectedDepActions: []string{},
|
||||
expectedTargetConditions: []string{},
|
||||
},
|
||||
{
|
||||
name: "independentmodulereversestatic",
|
||||
edge: annotated{"gplWithClasspathException.meta_lic", "apacheBin.meta_lic", []string{"static"}},
|
||||
expectedDepActions: []string{"apacheBin.meta_lic:apacheBin.meta_lic:notice"},
|
||||
expectedTargetConditions: []string{"gplWithClasspathException.meta_lic:restricted"},
|
||||
},
|
||||
{
|
||||
name: "dependentmodulereverse",
|
||||
edge: annotated{"gplWithClasspathException.meta_lic", "dependentModule.meta_lic", []string{"dynamic"}},
|
||||
expectedDepActions: []string{},
|
||||
expectedTargetConditions: []string{"gplWithClasspathException.meta_lic:restricted"},
|
||||
},
|
||||
{
|
||||
name: "ponr",
|
||||
edge: annotated{"proprietary.meta_lic", "gplLib.meta_lic", []string{"static"}},
|
||||
expectedDepActions: []string{
|
||||
"proprietary.meta_lic:gplLib.meta_lic:restricted",
|
||||
"gplLib.meta_lic:gplLib.meta_lic:restricted",
|
||||
},
|
||||
expectedTargetConditions: []string{},
|
||||
},
|
||||
{
|
||||
name: "ronp",
|
||||
edge: annotated{"gplBin.meta_lic", "proprietary.meta_lic", []string{"static"}},
|
||||
expectedDepActions: []string{"proprietary.meta_lic:proprietary.meta_lic:proprietary"},
|
||||
expectedTargetConditions: []string{"gplBin.meta_lic:restricted"},
|
||||
},
|
||||
{
|
||||
name: "noticeonb_e_o",
|
||||
edge: annotated{"mitBin.meta_lic", "by_exception.meta_lic", []string{"static"}},
|
||||
expectedDepActions: []string{"by_exception.meta_lic:by_exception.meta_lic:by_exception_only"},
|
||||
expectedTargetConditions: []string{},
|
||||
},
|
||||
{
|
||||
name: "b_e_oonnotice",
|
||||
edge: annotated{"by_exception.meta_lic", "mitLib.meta_lic", []string{"static"}},
|
||||
expectedDepActions: []string{"mitLib.meta_lic:mitLib.meta_lic:notice"},
|
||||
expectedTargetConditions: []string{},
|
||||
},
|
||||
{
|
||||
name: "noticeonrecip",
|
||||
edge: annotated{"mitBin.meta_lic", "mplLib.meta_lic", []string{"static"}},
|
||||
expectedDepActions: []string{"mplLib.meta_lic:mplLib.meta_lic:reciprocal"},
|
||||
expectedTargetConditions: []string{},
|
||||
},
|
||||
{
|
||||
name: "reciponnotice",
|
||||
edge: annotated{"mplBin.meta_lic", "mitLib.meta_lic", []string{"static"}},
|
||||
expectedDepActions: []string{"mitLib.meta_lic:mitLib.meta_lic:notice"},
|
||||
expectedTargetConditions: []string{},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
fs := make(testFS)
|
||||
stderr := &bytes.Buffer{}
|
||||
target := meta[tt.edge.target] + fmt.Sprintf("deps: {\n file: \"%s\"\n", tt.edge.dep)
|
||||
for _, ann := range tt.edge.annotations {
|
||||
target += fmt.Sprintf(" annotations: \"%s\"\n", ann)
|
||||
}
|
||||
fs[tt.edge.target] = []byte(target + "}\n")
|
||||
fs[tt.edge.dep] = []byte(meta[tt.edge.dep])
|
||||
lg, err := ReadLicenseGraph(&fs, stderr, []string{tt.edge.target})
|
||||
if err != nil {
|
||||
t.Errorf("unexpected error reading graph: %w", err)
|
||||
return
|
||||
}
|
||||
// simulate a condition inherited from another edge/dependency.
|
||||
otherTarget := ""
|
||||
otherCondition := ""
|
||||
if len(tt.otherCondition) > 0 {
|
||||
fields := strings.Split(tt.otherCondition, ":")
|
||||
otherTarget = fields[0]
|
||||
otherCondition = fields[1]
|
||||
// other target must exist in graph
|
||||
lg.targets[otherTarget] = &TargetNode{name: otherTarget}
|
||||
lg.targets[otherTarget].proto.LicenseConditions = append(lg.targets[otherTarget].proto.LicenseConditions, otherCondition)
|
||||
}
|
||||
if tt.expectedDepActions != nil {
|
||||
depActions := make(actionSet)
|
||||
depActions[lg.targets[tt.edge.dep]] = lg.targets[tt.edge.dep].LicenseConditions()
|
||||
if otherTarget != "" {
|
||||
// simulate a sub-dependency's condition having already propagated up to dep and about to go to target
|
||||
otherCs := lg.targets[otherTarget].LicenseConditions()
|
||||
depActions[lg.targets[tt.edge.dep]].AddSet(otherCs)
|
||||
depActions[lg.targets[otherTarget]] = otherCs
|
||||
}
|
||||
asActual := depActionsApplicableToTarget(lg.Edges()[0], depActions, tt.treatAsAggregate)
|
||||
asExpected := make(actionSet)
|
||||
for _, triple := range tt.expectedDepActions {
|
||||
fields := strings.Split(triple, ":")
|
||||
actsOn := lg.targets[fields[0]]
|
||||
origin := lg.targets[fields[1]]
|
||||
expectedConditions := newLicenseConditionSet()
|
||||
expectedConditions.add(origin, fields[2:]...)
|
||||
if _, ok := asExpected[actsOn]; ok {
|
||||
asExpected[actsOn].AddSet(expectedConditions)
|
||||
} else {
|
||||
asExpected[actsOn] = expectedConditions
|
||||
}
|
||||
}
|
||||
|
||||
checkSameActions(lg, asActual, asExpected, t)
|
||||
}
|
||||
if tt.expectedTargetConditions != nil {
|
||||
targetConditions := lg.TargetNode(tt.edge.target).LicenseConditions()
|
||||
if otherTarget != "" {
|
||||
targetConditions.add(lg.targets[otherTarget], otherCondition)
|
||||
}
|
||||
cs := targetConditionsApplicableToDep(
|
||||
lg.Edges()[0],
|
||||
targetConditions,
|
||||
tt.treatAsAggregate)
|
||||
actual := make([]string, 0, cs.Count())
|
||||
for _, lc := range cs.AsList() {
|
||||
actual = append(actual, lc.asString(":"))
|
||||
}
|
||||
sort.Strings(actual)
|
||||
sort.Strings(tt.expectedTargetConditions)
|
||||
if len(actual) != len(tt.expectedTargetConditions) {
|
||||
t.Errorf("unexpected number of target conditions: got %v with %d conditions, want %v with %d conditions",
|
||||
actual, len(actual), tt.expectedTargetConditions, len(tt.expectedTargetConditions))
|
||||
} else {
|
||||
for i := 0; i < len(actual); i++ {
|
||||
if actual[i] != tt.expectedTargetConditions[i] {
|
||||
t.Errorf("unexpected target condition at element %d: got %q, want %q",
|
||||
i, actual[i], tt.expectedTargetConditions[i])
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
217
tools/compliance/policy/resolve.go
Normal file
217
tools/compliance/policy/resolve.go
Normal file
@@ -0,0 +1,217 @@
|
||||
// Copyright 2021 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 compliance
|
||||
|
||||
// ResolveBottomUpConditions performs a bottom-up walk of the LicenseGraph
|
||||
// propagating conditions up the graph as necessary according to the properties
|
||||
// of each edge and according to each license condition in question.
|
||||
//
|
||||
// Subsequent top-down walks of the graph will filter some resolutions and may
|
||||
// introduce new resolutions.
|
||||
//
|
||||
// e.g. if a "restricted" condition applies to a binary, it also applies to all
|
||||
// of the statically-linked libraries and the transitive closure of their static
|
||||
// dependencies; even if neither they nor the transitive closure of their
|
||||
// dependencies originate any "restricted" conditions. The bottom-up walk will
|
||||
// not resolve the library and its transitive closure, but the later top-down
|
||||
// walk will.
|
||||
func ResolveBottomUpConditions(lg *LicenseGraph) *ResolutionSet {
|
||||
|
||||
// short-cut if already walked and cached
|
||||
lg.mu.Lock()
|
||||
rs := lg.rsBU
|
||||
lg.mu.Unlock()
|
||||
|
||||
if rs != nil {
|
||||
return rs
|
||||
}
|
||||
|
||||
// must be indexed for fast lookup
|
||||
lg.indexForward()
|
||||
|
||||
rs = newResolutionSet()
|
||||
|
||||
// cmap contains an entry for every target that was previously walked as a pure aggregate only.
|
||||
cmap := make(map[string]bool)
|
||||
|
||||
var walk func(f string, treatAsAggregate bool) actionSet
|
||||
|
||||
walk = func(f string, treatAsAggregate bool) actionSet {
|
||||
target := lg.targets[f]
|
||||
result := make(actionSet)
|
||||
result[target] = newLicenseConditionSet()
|
||||
result[target].add(target, target.proto.LicenseConditions...)
|
||||
if preresolved, ok := rs.resolutions[target]; ok {
|
||||
if treatAsAggregate {
|
||||
result.addSet(preresolved)
|
||||
return result
|
||||
}
|
||||
if _, asAggregate := cmap[f]; !asAggregate {
|
||||
result.addSet(preresolved)
|
||||
return result
|
||||
}
|
||||
// previously walked in a pure aggregate context,
|
||||
// needs to walk again in non-aggregate context
|
||||
delete(cmap, f)
|
||||
}
|
||||
if treatAsAggregate {
|
||||
cmap[f] = true
|
||||
}
|
||||
|
||||
// add all the conditions from all the dependencies
|
||||
for _, edge := range lg.index[f] {
|
||||
// walk dependency to get its conditions
|
||||
as := walk(edge.dependency, treatAsAggregate && lg.targets[edge.dependency].IsContainer())
|
||||
|
||||
// turn those into the conditions that apply to the target
|
||||
as = depActionsApplicableToTarget(TargetEdge{lg, edge}, as, treatAsAggregate)
|
||||
|
||||
// add them to the result
|
||||
result.addSet(as)
|
||||
}
|
||||
|
||||
// record these conditions as applicable to the target
|
||||
rs.addConditions(target, result)
|
||||
rs.addSelf(target, result.byName(ImpliesRestricted))
|
||||
|
||||
// return this up the tree
|
||||
return result
|
||||
}
|
||||
|
||||
// walk each of the roots
|
||||
for _, r := range lg.rootFiles {
|
||||
_ = walk(r, lg.targets[r].IsContainer())
|
||||
}
|
||||
|
||||
// if not yet cached, save the result
|
||||
lg.mu.Lock()
|
||||
if lg.rsBU == nil {
|
||||
lg.rsBU = rs
|
||||
} else {
|
||||
// if we end up with 2, release the later for garbage collection
|
||||
rs = lg.rsBU
|
||||
}
|
||||
lg.mu.Unlock()
|
||||
|
||||
return rs
|
||||
}
|
||||
|
||||
// ResolveTopDownCondtions performs a top-down walk of the LicenseGraph
|
||||
// resolving all reachable nodes for `condition`. Policy establishes the rules
|
||||
// for transforming and propagating resolutions down the graph.
|
||||
//
|
||||
// e.g. For current policy, none of the conditions propagate from target to
|
||||
// dependency except restricted. For restricted, the policy is to share the
|
||||
// source of any libraries linked to restricted code and to provide notice.
|
||||
func ResolveTopDownConditions(lg *LicenseGraph) *ResolutionSet {
|
||||
|
||||
// short-cut if already walked and cached
|
||||
lg.mu.Lock()
|
||||
rs := lg.rsTD
|
||||
lg.mu.Unlock()
|
||||
|
||||
if rs != nil {
|
||||
return rs
|
||||
}
|
||||
|
||||
// start with the conditions propagated up the graph
|
||||
rs = ResolveBottomUpConditions(lg)
|
||||
|
||||
// rmap maps 'appliesTo' targets to their applicable conditions
|
||||
//
|
||||
// rmap is the resulting ResolutionSet
|
||||
rmap := make(map[*TargetNode]actionSet)
|
||||
for attachesTo, as := range rs.resolutions {
|
||||
rmap[attachesTo] = as.copy()
|
||||
}
|
||||
|
||||
path := make([]*dependencyEdge, 0, 32)
|
||||
|
||||
var walk func(f string, cs *LicenseConditionSet, treatAsAggregate bool)
|
||||
|
||||
walk = func(f string, cs *LicenseConditionSet, treatAsAggregate bool) {
|
||||
fnode := lg.targets[f]
|
||||
if !cs.IsEmpty() {
|
||||
parentsAllAggregate := true
|
||||
for _, e := range path {
|
||||
target := lg.targets[e.target]
|
||||
if _, ok := rmap[target]; !ok {
|
||||
rmap[target] = make(actionSet)
|
||||
}
|
||||
rmap[target].add(fnode, cs)
|
||||
if !target.IsContainer() {
|
||||
parentsAllAggregate = false
|
||||
break
|
||||
}
|
||||
}
|
||||
if parentsAllAggregate {
|
||||
if _, ok := rmap[fnode]; !ok {
|
||||
rmap[fnode] = make(actionSet)
|
||||
}
|
||||
rmap[fnode].add(fnode, cs)
|
||||
}
|
||||
}
|
||||
// add conditions attached to `f`
|
||||
cs = cs.Copy()
|
||||
for _, fcs := range rs.resolutions[fnode] {
|
||||
cs.AddSet(fcs)
|
||||
}
|
||||
// for each dependency
|
||||
for _, edge := range lg.index[f] {
|
||||
e := TargetEdge{lg, edge}
|
||||
// dcs holds the dpendency conditions inherited from the target
|
||||
dcs := targetConditionsApplicableToDep(e, cs, treatAsAggregate)
|
||||
if dcs.IsEmpty() {
|
||||
if !treatAsAggregate || (!edgeIsDerivation(e) && !edgeIsDynamicLink(e)) {
|
||||
continue
|
||||
}
|
||||
}
|
||||
path = append(path, edge)
|
||||
// add the conditions to the dependency
|
||||
walk(edge.dependency, dcs, treatAsAggregate && lg.targets[edge.dependency].IsContainer())
|
||||
path = path[:len(path)-1]
|
||||
}
|
||||
}
|
||||
|
||||
// walk each of the roots
|
||||
for _, r := range lg.rootFiles {
|
||||
as, ok := rs.resolutions[lg.targets[r]]
|
||||
if !ok {
|
||||
// no conditions in root or transitive closure of dependencies
|
||||
continue
|
||||
}
|
||||
if as.isEmpty() {
|
||||
continue
|
||||
}
|
||||
|
||||
path = path[:0]
|
||||
// add the conditions to the root and its transitive closure
|
||||
walk(r, newLicenseConditionSet(), lg.targets[r].IsContainer())
|
||||
}
|
||||
|
||||
rs = &ResolutionSet{rmap}
|
||||
|
||||
// if not yet cached, save the result
|
||||
lg.mu.Lock()
|
||||
if lg.rsTD == nil {
|
||||
lg.rsTD = rs
|
||||
} else {
|
||||
// if we end up with 2, release the later for garbage collection
|
||||
rs = lg.rsTD
|
||||
}
|
||||
lg.mu.Unlock()
|
||||
|
||||
return rs
|
||||
}
|
755
tools/compliance/policy/resolve_test.go
Normal file
755
tools/compliance/policy/resolve_test.go
Normal file
@@ -0,0 +1,755 @@
|
||||
// Copyright 2021 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 compliance
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestResolveBottomUpConditions(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
roots []string
|
||||
edges []annotated
|
||||
expectedResolutions []res
|
||||
}{
|
||||
{
|
||||
name: "firstparty",
|
||||
roots: []string{"apacheBin.meta_lic"},
|
||||
edges: []annotated{
|
||||
{"apacheBin.meta_lic", "apacheLib.meta_lic", []string{"static"}},
|
||||
},
|
||||
expectedResolutions: []res{
|
||||
{"apacheBin.meta_lic", "apacheBin.meta_lic", "apacheBin.meta_lic", "notice"},
|
||||
{"apacheBin.meta_lic", "apacheLib.meta_lic", "apacheLib.meta_lic", "notice"},
|
||||
{"apacheLib.meta_lic", "apacheLib.meta_lic", "apacheLib.meta_lic", "notice"},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "firstpartytool",
|
||||
roots: []string{"apacheBin.meta_lic"},
|
||||
edges: []annotated{
|
||||
{"apacheBin.meta_lic", "apacheLib.meta_lic", []string{"toolchain"}},
|
||||
},
|
||||
expectedResolutions: []res{
|
||||
{"apacheBin.meta_lic", "apacheBin.meta_lic", "apacheBin.meta_lic", "notice"},
|
||||
{"apacheLib.meta_lic", "apacheLib.meta_lic", "apacheLib.meta_lic", "notice"},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "firstpartydeep",
|
||||
roots: []string{"apacheContainer.meta_lic"},
|
||||
edges: []annotated{
|
||||
{"apacheContainer.meta_lic", "apacheBin.meta_lic", []string{"static"}},
|
||||
{"apacheBin.meta_lic", "apacheLib.meta_lic", []string{"static"}},
|
||||
},
|
||||
expectedResolutions: []res{
|
||||
{"apacheContainer.meta_lic", "apacheContainer.meta_lic", "apacheContainer.meta_lic", "notice"},
|
||||
{"apacheContainer.meta_lic", "apacheBin.meta_lic", "apacheBin.meta_lic", "notice"},
|
||||
{"apacheContainer.meta_lic", "apacheLib.meta_lic", "apacheLib.meta_lic", "notice"},
|
||||
{"apacheBin.meta_lic", "apacheBin.meta_lic", "apacheBin.meta_lic", "notice"},
|
||||
{"apacheBin.meta_lic", "apacheLib.meta_lic", "apacheLib.meta_lic", "notice"},
|
||||
{"apacheLib.meta_lic", "apacheLib.meta_lic", "apacheLib.meta_lic", "notice"},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "firstpartywide",
|
||||
roots: []string{"apacheContainer.meta_lic"},
|
||||
edges: []annotated{
|
||||
{"apacheContainer.meta_lic", "apacheBin.meta_lic", []string{"static"}},
|
||||
{"apacheContainer.meta_lic", "apacheLib.meta_lic", []string{"static"}},
|
||||
},
|
||||
expectedResolutions: []res{
|
||||
{"apacheContainer.meta_lic", "apacheContainer.meta_lic", "apacheContainer.meta_lic", "notice"},
|
||||
{"apacheContainer.meta_lic", "apacheBin.meta_lic", "apacheBin.meta_lic", "notice"},
|
||||
{"apacheContainer.meta_lic", "apacheLib.meta_lic", "apacheLib.meta_lic", "notice"},
|
||||
{"apacheBin.meta_lic", "apacheBin.meta_lic", "apacheBin.meta_lic", "notice"},
|
||||
{"apacheLib.meta_lic", "apacheLib.meta_lic", "apacheLib.meta_lic", "notice"},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "firstpartydynamic",
|
||||
roots: []string{"apacheBin.meta_lic"},
|
||||
edges: []annotated{
|
||||
{"apacheBin.meta_lic", "apacheLib.meta_lic", []string{"dynamic"}},
|
||||
},
|
||||
expectedResolutions: []res{
|
||||
{"apacheBin.meta_lic", "apacheBin.meta_lic", "apacheBin.meta_lic", "notice"},
|
||||
{"apacheLib.meta_lic", "apacheLib.meta_lic", "apacheLib.meta_lic", "notice"},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "firstpartydynamicdeep",
|
||||
roots: []string{"apacheContainer.meta_lic"},
|
||||
edges: []annotated{
|
||||
{"apacheContainer.meta_lic", "apacheBin.meta_lic", []string{"static"}},
|
||||
{"apacheBin.meta_lic", "apacheLib.meta_lic", []string{"dynamic"}},
|
||||
},
|
||||
expectedResolutions: []res{
|
||||
{"apacheContainer.meta_lic", "apacheContainer.meta_lic", "apacheContainer.meta_lic", "notice"},
|
||||
{"apacheContainer.meta_lic", "apacheBin.meta_lic", "apacheBin.meta_lic", "notice"},
|
||||
{"apacheBin.meta_lic", "apacheBin.meta_lic", "apacheBin.meta_lic", "notice"},
|
||||
{"apacheLib.meta_lic", "apacheLib.meta_lic", "apacheLib.meta_lic", "notice"},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "firstpartydynamicwide",
|
||||
roots: []string{"apacheContainer.meta_lic"},
|
||||
edges: []annotated{
|
||||
{"apacheContainer.meta_lic", "apacheBin.meta_lic", []string{"static"}},
|
||||
{"apacheContainer.meta_lic", "apacheLib.meta_lic", []string{"dynamic"}},
|
||||
},
|
||||
expectedResolutions: []res{
|
||||
{"apacheContainer.meta_lic", "apacheContainer.meta_lic", "apacheContainer.meta_lic", "notice"},
|
||||
{"apacheContainer.meta_lic", "apacheBin.meta_lic", "apacheBin.meta_lic", "notice"},
|
||||
{"apacheBin.meta_lic", "apacheBin.meta_lic", "apacheBin.meta_lic", "notice"},
|
||||
{"apacheLib.meta_lic", "apacheLib.meta_lic", "apacheLib.meta_lic", "notice"},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "restricted",
|
||||
roots: []string{"apacheBin.meta_lic"},
|
||||
edges: []annotated{
|
||||
{"apacheBin.meta_lic", "gplLib.meta_lic", []string{"static"}},
|
||||
},
|
||||
expectedResolutions: []res{
|
||||
{"apacheBin.meta_lic", "apacheBin.meta_lic", "apacheBin.meta_lic", "notice"},
|
||||
{"apacheBin.meta_lic", "apacheBin.meta_lic", "gplLib.meta_lic", "restricted"},
|
||||
{"apacheBin.meta_lic", "gplLib.meta_lic", "gplLib.meta_lic", "restricted"},
|
||||
{"gplLib.meta_lic", "gplLib.meta_lic", "gplLib.meta_lic", "restricted"},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "restrictedtool",
|
||||
roots: []string{"apacheBin.meta_lic"},
|
||||
edges: []annotated{
|
||||
{"apacheBin.meta_lic", "gplLib.meta_lic", []string{"toolchain"}},
|
||||
},
|
||||
expectedResolutions: []res{
|
||||
{"apacheBin.meta_lic", "apacheBin.meta_lic", "apacheBin.meta_lic", "notice"},
|
||||
{"gplLib.meta_lic", "gplLib.meta_lic", "gplLib.meta_lic", "restricted"},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "restricteddeep",
|
||||
roots: []string{"apacheContainer.meta_lic"},
|
||||
edges: []annotated{
|
||||
{"apacheContainer.meta_lic", "apacheBin.meta_lic", []string{"static"}},
|
||||
{"apacheBin.meta_lic", "gplLib.meta_lic", []string{"static"}},
|
||||
},
|
||||
expectedResolutions: []res{
|
||||
{"apacheContainer.meta_lic", "apacheContainer.meta_lic", "apacheContainer.meta_lic", "notice"},
|
||||
{"apacheContainer.meta_lic", "apacheContainer.meta_lic", "gplLib.meta_lic", "restricted"},
|
||||
{"apacheContainer.meta_lic", "apacheBin.meta_lic", "apacheBin.meta_lic", "notice"},
|
||||
{"apacheContainer.meta_lic", "apacheBin.meta_lic", "gplLib.meta_lic", "restricted"},
|
||||
{"apacheContainer.meta_lic", "gplLib.meta_lic", "gplLib.meta_lic", "restricted"},
|
||||
{"apacheBin.meta_lic", "apacheBin.meta_lic", "apacheBin.meta_lic", "notice"},
|
||||
{"apacheBin.meta_lic", "apacheBin.meta_lic", "gplLib.meta_lic", "restricted"},
|
||||
{"apacheBin.meta_lic", "gplLib.meta_lic", "gplLib.meta_lic", "restricted"},
|
||||
{"gplLib.meta_lic", "gplLib.meta_lic", "gplLib.meta_lic", "restricted"},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "restrictedwide",
|
||||
roots: []string{"apacheContainer.meta_lic"},
|
||||
edges: []annotated{
|
||||
{"apacheContainer.meta_lic", "apacheBin.meta_lic", []string{"static"}},
|
||||
{"apacheContainer.meta_lic", "gplLib.meta_lic", []string{"static"}},
|
||||
},
|
||||
expectedResolutions: []res{
|
||||
{"apacheContainer.meta_lic", "apacheContainer.meta_lic", "apacheContainer.meta_lic", "notice"},
|
||||
{"apacheContainer.meta_lic", "apacheContainer.meta_lic", "gplLib.meta_lic", "restricted"},
|
||||
{"apacheContainer.meta_lic", "apacheBin.meta_lic", "apacheBin.meta_lic", "notice"},
|
||||
{"apacheContainer.meta_lic", "gplLib.meta_lic", "gplLib.meta_lic", "restricted"},
|
||||
{"apacheBin.meta_lic", "apacheBin.meta_lic", "apacheBin.meta_lic", "notice"},
|
||||
{"gplLib.meta_lic", "gplLib.meta_lic", "gplLib.meta_lic", "restricted"},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "restricteddynamic",
|
||||
roots: []string{"apacheBin.meta_lic"},
|
||||
edges: []annotated{
|
||||
{"apacheBin.meta_lic", "gplLib.meta_lic", []string{"dynamic"}},
|
||||
},
|
||||
expectedResolutions: []res{
|
||||
{"apacheBin.meta_lic", "apacheBin.meta_lic", "apacheBin.meta_lic", "notice"},
|
||||
{"apacheBin.meta_lic", "apacheBin.meta_lic", "gplLib.meta_lic", "restricted"},
|
||||
{"apacheBin.meta_lic", "gplLib.meta_lic", "gplLib.meta_lic", "restricted"},
|
||||
{"gplLib.meta_lic", "gplLib.meta_lic", "gplLib.meta_lic", "restricted"},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "restricteddynamicdeep",
|
||||
roots: []string{"apacheContainer.meta_lic"},
|
||||
edges: []annotated{
|
||||
{"apacheContainer.meta_lic", "apacheBin.meta_lic", []string{"static"}},
|
||||
{"apacheBin.meta_lic", "gplLib.meta_lic", []string{"dynamic"}},
|
||||
},
|
||||
expectedResolutions: []res{
|
||||
{"apacheContainer.meta_lic", "apacheContainer.meta_lic", "apacheContainer.meta_lic", "notice"},
|
||||
{"apacheContainer.meta_lic", "apacheContainer.meta_lic", "gplLib.meta_lic", "restricted"},
|
||||
{"apacheContainer.meta_lic", "apacheBin.meta_lic", "apacheBin.meta_lic", "notice"},
|
||||
{"apacheContainer.meta_lic", "apacheBin.meta_lic", "gplLib.meta_lic", "restricted"},
|
||||
{"apacheContainer.meta_lic", "gplLib.meta_lic", "gplLib.meta_lic", "restricted"},
|
||||
{"apacheBin.meta_lic", "apacheBin.meta_lic", "apacheBin.meta_lic", "notice"},
|
||||
{"apacheBin.meta_lic", "apacheBin.meta_lic", "gplLib.meta_lic", "restricted"},
|
||||
{"apacheBin.meta_lic", "gplLib.meta_lic", "gplLib.meta_lic", "restricted"},
|
||||
{"gplLib.meta_lic", "gplLib.meta_lic", "gplLib.meta_lic", "restricted"},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "restricteddynamicwide",
|
||||
roots: []string{"apacheContainer.meta_lic"},
|
||||
edges: []annotated{
|
||||
{"apacheContainer.meta_lic", "apacheBin.meta_lic", []string{"static"}},
|
||||
{"apacheContainer.meta_lic", "gplLib.meta_lic", []string{"dynamic"}},
|
||||
},
|
||||
expectedResolutions: []res{
|
||||
{"apacheContainer.meta_lic", "apacheContainer.meta_lic", "apacheContainer.meta_lic", "notice"},
|
||||
{"apacheContainer.meta_lic", "apacheContainer.meta_lic", "gplLib.meta_lic", "restricted"},
|
||||
{"apacheContainer.meta_lic", "apacheBin.meta_lic", "apacheBin.meta_lic", "notice"},
|
||||
{"apacheContainer.meta_lic", "gplLib.meta_lic", "gplLib.meta_lic", "restricted"},
|
||||
{"apacheBin.meta_lic", "apacheBin.meta_lic", "apacheBin.meta_lic", "notice"},
|
||||
{"gplLib.meta_lic", "gplLib.meta_lic", "gplLib.meta_lic", "restricted"},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "weakrestricted",
|
||||
roots: []string{"apacheBin.meta_lic"},
|
||||
edges: []annotated{
|
||||
{"apacheBin.meta_lic", "lgplLib.meta_lic", []string{"static"}},
|
||||
},
|
||||
expectedResolutions: []res{
|
||||
{"apacheBin.meta_lic", "apacheBin.meta_lic", "apacheBin.meta_lic", "notice"},
|
||||
{"apacheBin.meta_lic", "apacheBin.meta_lic", "lgplLib.meta_lic", "restricted"},
|
||||
{"apacheBin.meta_lic", "lgplLib.meta_lic", "lgplLib.meta_lic", "restricted"},
|
||||
{"lgplLib.meta_lic", "lgplLib.meta_lic", "lgplLib.meta_lic", "restricted"},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "weakrestrictedtool",
|
||||
roots: []string{"apacheBin.meta_lic"},
|
||||
edges: []annotated{
|
||||
{"apacheBin.meta_lic", "lgplLib.meta_lic", []string{"toolchain"}},
|
||||
},
|
||||
expectedResolutions: []res{
|
||||
{"apacheBin.meta_lic", "apacheBin.meta_lic", "apacheBin.meta_lic", "notice"},
|
||||
{"lgplLib.meta_lic", "lgplLib.meta_lic", "lgplLib.meta_lic", "restricted"},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "weakrestricteddeep",
|
||||
roots: []string{"apacheContainer.meta_lic"},
|
||||
edges: []annotated{
|
||||
{"apacheContainer.meta_lic", "apacheBin.meta_lic", []string{"static"}},
|
||||
{"apacheBin.meta_lic", "lgplLib.meta_lic", []string{"static"}},
|
||||
},
|
||||
expectedResolutions: []res{
|
||||
{"apacheContainer.meta_lic", "apacheContainer.meta_lic", "apacheContainer.meta_lic", "notice"},
|
||||
{"apacheContainer.meta_lic", "apacheContainer.meta_lic", "lgplLib.meta_lic", "restricted"},
|
||||
{"apacheContainer.meta_lic", "apacheBin.meta_lic", "apacheBin.meta_lic", "notice"},
|
||||
{"apacheContainer.meta_lic", "apacheBin.meta_lic", "lgplLib.meta_lic", "restricted"},
|
||||
{"apacheContainer.meta_lic", "lgplLib.meta_lic", "lgplLib.meta_lic", "restricted"},
|
||||
{"apacheBin.meta_lic", "apacheBin.meta_lic", "apacheBin.meta_lic", "notice"},
|
||||
{"apacheBin.meta_lic", "apacheBin.meta_lic", "lgplLib.meta_lic", "restricted"},
|
||||
{"apacheBin.meta_lic", "lgplLib.meta_lic", "lgplLib.meta_lic", "restricted"},
|
||||
{"lgplLib.meta_lic", "lgplLib.meta_lic", "lgplLib.meta_lic", "restricted"},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "weakrestrictedwide",
|
||||
roots: []string{"apacheContainer.meta_lic"},
|
||||
edges: []annotated{
|
||||
{"apacheContainer.meta_lic", "apacheBin.meta_lic", []string{"static"}},
|
||||
{"apacheContainer.meta_lic", "lgplLib.meta_lic", []string{"static"}},
|
||||
},
|
||||
expectedResolutions: []res{
|
||||
{"apacheContainer.meta_lic", "apacheContainer.meta_lic", "apacheContainer.meta_lic", "notice"},
|
||||
{"apacheContainer.meta_lic", "apacheContainer.meta_lic", "lgplLib.meta_lic", "restricted"},
|
||||
{"apacheContainer.meta_lic", "apacheBin.meta_lic", "apacheBin.meta_lic", "notice"},
|
||||
{"apacheContainer.meta_lic", "lgplLib.meta_lic", "lgplLib.meta_lic", "restricted"},
|
||||
{"apacheBin.meta_lic", "apacheBin.meta_lic", "apacheBin.meta_lic", "notice"},
|
||||
{"lgplLib.meta_lic", "lgplLib.meta_lic", "lgplLib.meta_lic", "restricted"},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "weakrestricteddynamic",
|
||||
roots: []string{"apacheBin.meta_lic"},
|
||||
edges: []annotated{
|
||||
{"apacheBin.meta_lic", "lgplLib.meta_lic", []string{"dynamic"}},
|
||||
},
|
||||
expectedResolutions: []res{
|
||||
{"apacheBin.meta_lic", "apacheBin.meta_lic", "apacheBin.meta_lic", "notice"},
|
||||
{"lgplLib.meta_lic", "lgplLib.meta_lic", "lgplLib.meta_lic", "restricted"},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "weakrestricteddynamicdeep",
|
||||
roots: []string{"apacheContainer.meta_lic"},
|
||||
edges: []annotated{
|
||||
{"apacheContainer.meta_lic", "apacheBin.meta_lic", []string{"static"}},
|
||||
{"apacheBin.meta_lic", "lgplLib.meta_lic", []string{"dynamic"}},
|
||||
},
|
||||
expectedResolutions: []res{
|
||||
{"apacheContainer.meta_lic", "apacheContainer.meta_lic", "apacheContainer.meta_lic", "notice"},
|
||||
{"apacheContainer.meta_lic", "apacheBin.meta_lic", "apacheBin.meta_lic", "notice"},
|
||||
{"apacheBin.meta_lic", "apacheBin.meta_lic", "apacheBin.meta_lic", "notice"},
|
||||
{"lgplLib.meta_lic", "lgplLib.meta_lic", "lgplLib.meta_lic", "restricted"},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "weakrestricteddynamicwide",
|
||||
roots: []string{"apacheContainer.meta_lic"},
|
||||
edges: []annotated{
|
||||
{"apacheContainer.meta_lic", "apacheBin.meta_lic", []string{"static"}},
|
||||
{"apacheContainer.meta_lic", "lgplLib.meta_lic", []string{"dynamic"}},
|
||||
},
|
||||
expectedResolutions: []res{
|
||||
{"apacheContainer.meta_lic", "apacheContainer.meta_lic", "apacheContainer.meta_lic", "notice"},
|
||||
{"apacheContainer.meta_lic", "apacheBin.meta_lic", "apacheBin.meta_lic", "notice"},
|
||||
{"apacheBin.meta_lic", "apacheBin.meta_lic", "apacheBin.meta_lic", "notice"},
|
||||
{"lgplLib.meta_lic", "lgplLib.meta_lic", "lgplLib.meta_lic", "restricted"},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "classpath",
|
||||
roots: []string{"apacheBin.meta_lic"},
|
||||
edges: []annotated{
|
||||
{"apacheBin.meta_lic", "gplWithClasspathException.meta_lic", []string{"static"}},
|
||||
},
|
||||
expectedResolutions: []res{
|
||||
{"apacheBin.meta_lic", "apacheBin.meta_lic", "apacheBin.meta_lic", "notice"},
|
||||
{"apacheBin.meta_lic", "apacheBin.meta_lic", "gplWithClasspathException.meta_lic", "restricted"},
|
||||
{"apacheBin.meta_lic", "gplWithClasspathException.meta_lic", "gplWithClasspathException.meta_lic", "restricted"},
|
||||
{"gplWithClasspathException.meta_lic", "gplWithClasspathException.meta_lic", "gplWithClasspathException.meta_lic", "restricted"},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "classpathdependent",
|
||||
roots: []string{"dependentModule.meta_lic"},
|
||||
edges: []annotated{
|
||||
{"dependentModule.meta_lic", "gplWithClasspathException.meta_lic", []string{"static"}},
|
||||
},
|
||||
expectedResolutions: []res{
|
||||
{"dependentModule.meta_lic", "dependentModule.meta_lic", "dependentModule.meta_lic", "notice"},
|
||||
{"dependentModule.meta_lic", "dependentModule.meta_lic", "gplWithClasspathException.meta_lic", "restricted"},
|
||||
{"dependentModule.meta_lic", "gplWithClasspathException.meta_lic", "gplWithClasspathException.meta_lic", "restricted"},
|
||||
{"gplWithClasspathException.meta_lic", "gplWithClasspathException.meta_lic", "gplWithClasspathException.meta_lic", "restricted"},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "classpathdynamic",
|
||||
roots: []string{"apacheBin.meta_lic"},
|
||||
edges: []annotated{
|
||||
{"apacheBin.meta_lic", "gplWithClasspathException.meta_lic", []string{"dynamic"}},
|
||||
},
|
||||
expectedResolutions: []res{
|
||||
{"apacheBin.meta_lic", "apacheBin.meta_lic", "apacheBin.meta_lic", "notice"},
|
||||
{"gplWithClasspathException.meta_lic", "gplWithClasspathException.meta_lic", "gplWithClasspathException.meta_lic", "restricted"},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "classpathdependentdynamic",
|
||||
roots: []string{"dependentModule.meta_lic"},
|
||||
edges: []annotated{
|
||||
{"dependentModule.meta_lic", "gplWithClasspathException.meta_lic", []string{"dynamic"}},
|
||||
},
|
||||
expectedResolutions: []res{
|
||||
{"dependentModule.meta_lic", "dependentModule.meta_lic", "dependentModule.meta_lic", "notice"},
|
||||
{"dependentModule.meta_lic", "dependentModule.meta_lic", "gplWithClasspathException.meta_lic", "restricted"},
|
||||
{"dependentModule.meta_lic", "gplWithClasspathException.meta_lic", "gplWithClasspathException.meta_lic", "restricted"},
|
||||
{"gplWithClasspathException.meta_lic", "gplWithClasspathException.meta_lic", "gplWithClasspathException.meta_lic", "restricted"},
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
stderr := &bytes.Buffer{}
|
||||
lg, err := toGraph(stderr, tt.roots, tt.edges)
|
||||
if err != nil {
|
||||
t.Errorf("unexpected test data error: got %w, want no error", err)
|
||||
return
|
||||
}
|
||||
expectedRs := toResolutionSet(lg, tt.expectedResolutions)
|
||||
actualRs := ResolveBottomUpConditions(lg)
|
||||
checkSame(actualRs, expectedRs, t)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestResolveTopDownConditions(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
roots []string
|
||||
edges []annotated
|
||||
expectedResolutions []res
|
||||
}{
|
||||
{
|
||||
name: "firstparty",
|
||||
roots: []string{"apacheBin.meta_lic"},
|
||||
edges: []annotated{
|
||||
{"apacheBin.meta_lic", "apacheLib.meta_lic", []string{"static"}},
|
||||
},
|
||||
expectedResolutions: []res{
|
||||
{"apacheBin.meta_lic", "apacheBin.meta_lic", "apacheBin.meta_lic", "notice"},
|
||||
{"apacheBin.meta_lic", "apacheLib.meta_lic", "apacheLib.meta_lic", "notice"},
|
||||
{"apacheLib.meta_lic", "apacheLib.meta_lic", "apacheLib.meta_lic", "notice"},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "firstpartydynamic",
|
||||
roots: []string{"apacheBin.meta_lic"},
|
||||
edges: []annotated{
|
||||
{"apacheBin.meta_lic", "apacheLib.meta_lic", []string{"dynamic"}},
|
||||
},
|
||||
expectedResolutions: []res{
|
||||
{"apacheBin.meta_lic", "apacheBin.meta_lic", "apacheBin.meta_lic", "notice"},
|
||||
{"apacheLib.meta_lic", "apacheLib.meta_lic", "apacheLib.meta_lic", "notice"},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "restricted",
|
||||
roots: []string{"apacheBin.meta_lic"},
|
||||
edges: []annotated{
|
||||
{"apacheBin.meta_lic", "gplLib.meta_lic", []string{"static"}},
|
||||
{"apacheBin.meta_lic", "mitLib.meta_lic", []string{"static"}},
|
||||
},
|
||||
expectedResolutions: []res{
|
||||
{"apacheBin.meta_lic", "apacheBin.meta_lic", "apacheBin.meta_lic", "notice"},
|
||||
{"apacheBin.meta_lic", "apacheBin.meta_lic", "gplLib.meta_lic", "restricted"},
|
||||
{"apacheBin.meta_lic", "gplLib.meta_lic", "gplLib.meta_lic", "restricted"},
|
||||
{"apacheBin.meta_lic", "mitLib.meta_lic", "gplLib.meta_lic", "restricted"},
|
||||
{"apacheBin.meta_lic", "mitLib.meta_lic", "mitLib.meta_lic", "notice"},
|
||||
{"gplLib.meta_lic", "gplLib.meta_lic", "gplLib.meta_lic", "restricted"},
|
||||
{"mitLib.meta_lic", "mitLib.meta_lic", "mitLib.meta_lic", "notice"},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "restrictedtool",
|
||||
roots: []string{"apacheBin.meta_lic"},
|
||||
edges: []annotated{
|
||||
{"apacheBin.meta_lic", "gplBin.meta_lic", []string{"toolchain"}},
|
||||
{"apacheBin.meta_lic", "mitLib.meta_lic", []string{"static"}},
|
||||
},
|
||||
expectedResolutions: []res{
|
||||
{"apacheBin.meta_lic", "apacheBin.meta_lic", "apacheBin.meta_lic", "notice"},
|
||||
{"apacheBin.meta_lic", "mitLib.meta_lic", "mitLib.meta_lic", "notice"},
|
||||
{"gplBin.meta_lic", "gplBin.meta_lic", "gplBin.meta_lic", "restricted"},
|
||||
{"mitLib.meta_lic", "mitLib.meta_lic", "mitLib.meta_lic", "notice"},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "restricteddeep",
|
||||
roots: []string{"apacheContainer.meta_lic"},
|
||||
edges: []annotated{
|
||||
{"apacheContainer.meta_lic", "apacheBin.meta_lic", []string{"static"}},
|
||||
{"apacheContainer.meta_lic", "mitBin.meta_lic", []string{"static"}},
|
||||
{"apacheBin.meta_lic", "gplLib.meta_lic", []string{"static"}},
|
||||
{"apacheBin.meta_lic", "mplLib.meta_lic", []string{"static"}},
|
||||
{"mitBin.meta_lic", "mitLib.meta_lic", []string{"static"}},
|
||||
},
|
||||
expectedResolutions: []res{
|
||||
{"apacheContainer.meta_lic", "apacheContainer.meta_lic", "apacheContainer.meta_lic", "notice"},
|
||||
{"apacheContainer.meta_lic", "apacheContainer.meta_lic", "gplLib.meta_lic", "restricted"},
|
||||
{"apacheContainer.meta_lic", "apacheBin.meta_lic", "apacheBin.meta_lic", "notice"},
|
||||
{"apacheContainer.meta_lic", "apacheBin.meta_lic", "gplLib.meta_lic", "restricted"},
|
||||
{"apacheContainer.meta_lic", "gplLib.meta_lic", "gplLib.meta_lic", "restricted"},
|
||||
{"apacheContainer.meta_lic", "mitBin.meta_lic", "mitBin.meta_lic", "notice"},
|
||||
{"apacheContainer.meta_lic", "mitLib.meta_lic", "mitLib.meta_lic", "notice"},
|
||||
{"apacheContainer.meta_lic", "mplLib.meta_lic", "gplLib.meta_lic", "restricted"},
|
||||
{"apacheContainer.meta_lic", "mplLib.meta_lic", "mplLib.meta_lic", "reciprocal"},
|
||||
{"apacheBin.meta_lic", "apacheBin.meta_lic", "apacheBin.meta_lic", "notice"},
|
||||
{"apacheBin.meta_lic", "apacheBin.meta_lic", "gplLib.meta_lic", "restricted"},
|
||||
{"apacheBin.meta_lic", "gplLib.meta_lic", "gplLib.meta_lic", "restricted"},
|
||||
{"apacheBin.meta_lic", "mplLib.meta_lic", "gplLib.meta_lic", "restricted"},
|
||||
{"apacheBin.meta_lic", "mplLib.meta_lic", "mplLib.meta_lic", "reciprocal"},
|
||||
{"gplLib.meta_lic", "gplLib.meta_lic", "gplLib.meta_lic", "restricted"},
|
||||
{"mitBin.meta_lic", "mitBin.meta_lic", "mitBin.meta_lic", "notice"},
|
||||
{"mitBin.meta_lic", "mitLib.meta_lic", "mitLib.meta_lic", "notice"},
|
||||
{"mitLib.meta_lic", "mitLib.meta_lic", "mitLib.meta_lic", "notice"},
|
||||
{"mplLib.meta_lic", "mplLib.meta_lic", "mplLib.meta_lic", "reciprocal"},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "restrictedwide",
|
||||
roots: []string{"apacheContainer.meta_lic"},
|
||||
edges: []annotated{
|
||||
{"apacheContainer.meta_lic", "apacheBin.meta_lic", []string{"static"}},
|
||||
{"apacheContainer.meta_lic", "gplLib.meta_lic", []string{"static"}},
|
||||
},
|
||||
expectedResolutions: []res{
|
||||
{"apacheContainer.meta_lic", "apacheContainer.meta_lic", "apacheContainer.meta_lic", "notice"},
|
||||
{"apacheContainer.meta_lic", "apacheContainer.meta_lic", "gplLib.meta_lic", "restricted"},
|
||||
{"apacheContainer.meta_lic", "apacheBin.meta_lic", "apacheBin.meta_lic", "notice"},
|
||||
{"apacheContainer.meta_lic", "gplLib.meta_lic", "gplLib.meta_lic", "restricted"},
|
||||
{"apacheBin.meta_lic", "apacheBin.meta_lic", "apacheBin.meta_lic", "notice"},
|
||||
{"gplLib.meta_lic", "gplLib.meta_lic", "gplLib.meta_lic", "restricted"},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "restricteddynamic",
|
||||
roots: []string{"apacheBin.meta_lic"},
|
||||
edges: []annotated{
|
||||
{"apacheBin.meta_lic", "gplLib.meta_lic", []string{"dynamic"}},
|
||||
{"apacheBin.meta_lic", "mitLib.meta_lic", []string{"dynamic"}},
|
||||
},
|
||||
expectedResolutions: []res{
|
||||
{"apacheBin.meta_lic", "apacheBin.meta_lic", "apacheBin.meta_lic", "notice"},
|
||||
{"apacheBin.meta_lic", "apacheBin.meta_lic", "gplLib.meta_lic", "restricted"},
|
||||
{"apacheBin.meta_lic", "gplLib.meta_lic", "gplLib.meta_lic", "restricted"},
|
||||
{"apacheBin.meta_lic", "mitLib.meta_lic", "gplLib.meta_lic", "restricted"},
|
||||
{"gplLib.meta_lic", "gplLib.meta_lic", "gplLib.meta_lic", "restricted"},
|
||||
{"mitLib.meta_lic", "mitLib.meta_lic", "mitLib.meta_lic", "notice"},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "restricteddynamicdeep",
|
||||
roots: []string{"apacheContainer.meta_lic"},
|
||||
edges: []annotated{
|
||||
{"apacheContainer.meta_lic", "apacheBin.meta_lic", []string{"static"}},
|
||||
{"apacheContainer.meta_lic", "mitBin.meta_lic", []string{"static"}},
|
||||
{"apacheBin.meta_lic", "gplLib.meta_lic", []string{"dynamic"}},
|
||||
{"apacheBin.meta_lic", "mplLib.meta_lic", []string{"dynamic"}},
|
||||
{"mitBin.meta_lic", "mitLib.meta_lic", []string{"dynamic"}},
|
||||
},
|
||||
expectedResolutions: []res{
|
||||
{"apacheContainer.meta_lic", "apacheContainer.meta_lic", "apacheContainer.meta_lic", "notice"},
|
||||
{"apacheContainer.meta_lic", "apacheContainer.meta_lic", "gplLib.meta_lic", "restricted"},
|
||||
{"apacheContainer.meta_lic", "apacheBin.meta_lic", "apacheBin.meta_lic", "notice"},
|
||||
{"apacheContainer.meta_lic", "apacheBin.meta_lic", "gplLib.meta_lic", "restricted"},
|
||||
{"apacheContainer.meta_lic", "gplLib.meta_lic", "gplLib.meta_lic", "restricted"},
|
||||
{"apacheContainer.meta_lic", "mitBin.meta_lic", "mitBin.meta_lic", "notice"},
|
||||
{"apacheContainer.meta_lic", "mplLib.meta_lic", "gplLib.meta_lic", "restricted"},
|
||||
{"apacheBin.meta_lic", "apacheBin.meta_lic", "apacheBin.meta_lic", "notice"},
|
||||
{"apacheBin.meta_lic", "apacheBin.meta_lic", "gplLib.meta_lic", "restricted"},
|
||||
{"apacheBin.meta_lic", "gplLib.meta_lic", "gplLib.meta_lic", "restricted"},
|
||||
{"apacheBin.meta_lic", "mplLib.meta_lic", "gplLib.meta_lic", "restricted"},
|
||||
{"gplLib.meta_lic", "gplLib.meta_lic", "gplLib.meta_lic", "restricted"},
|
||||
{"mitBin.meta_lic", "mitBin.meta_lic", "mitBin.meta_lic", "notice"},
|
||||
{"mitLib.meta_lic", "mitLib.meta_lic", "mitLib.meta_lic", "notice"},
|
||||
{"mplLib.meta_lic", "mplLib.meta_lic", "mplLib.meta_lic", "reciprocal"},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "restricteddynamicwide",
|
||||
roots: []string{"apacheContainer.meta_lic"},
|
||||
edges: []annotated{
|
||||
{"apacheContainer.meta_lic", "apacheBin.meta_lic", []string{"static"}},
|
||||
{"apacheContainer.meta_lic", "gplLib.meta_lic", []string{"dynamic"}},
|
||||
},
|
||||
expectedResolutions: []res{
|
||||
{"apacheContainer.meta_lic", "apacheContainer.meta_lic", "apacheContainer.meta_lic", "notice"},
|
||||
{"apacheContainer.meta_lic", "apacheContainer.meta_lic", "gplLib.meta_lic", "restricted"},
|
||||
{"apacheContainer.meta_lic", "apacheBin.meta_lic", "apacheBin.meta_lic", "notice"},
|
||||
{"apacheContainer.meta_lic", "gplLib.meta_lic", "gplLib.meta_lic", "restricted"},
|
||||
{"apacheBin.meta_lic", "apacheBin.meta_lic", "apacheBin.meta_lic", "notice"},
|
||||
{"gplLib.meta_lic", "gplLib.meta_lic", "gplLib.meta_lic", "restricted"},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "weakrestricted",
|
||||
roots: []string{"apacheBin.meta_lic"},
|
||||
edges: []annotated{
|
||||
{"apacheBin.meta_lic", "lgplLib.meta_lic", []string{"static"}},
|
||||
{"apacheBin.meta_lic", "mitLib.meta_lic", []string{"static"}},
|
||||
},
|
||||
expectedResolutions: []res{
|
||||
{"apacheBin.meta_lic", "apacheBin.meta_lic", "apacheBin.meta_lic", "notice"},
|
||||
{"apacheBin.meta_lic", "apacheBin.meta_lic", "lgplLib.meta_lic", "restricted"},
|
||||
{"apacheBin.meta_lic", "lgplLib.meta_lic", "lgplLib.meta_lic", "restricted"},
|
||||
{"apacheBin.meta_lic", "mitLib.meta_lic", "mitLib.meta_lic", "notice"},
|
||||
{"apacheBin.meta_lic", "mitLib.meta_lic", "lgplLib.meta_lic", "restricted"},
|
||||
{"lgplLib.meta_lic", "lgplLib.meta_lic", "lgplLib.meta_lic", "restricted"},
|
||||
{"mitLib.meta_lic", "mitLib.meta_lic", "mitLib.meta_lic", "notice"},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "weakrestrictedtool",
|
||||
roots: []string{"apacheBin.meta_lic"},
|
||||
edges: []annotated{
|
||||
{"apacheBin.meta_lic", "lgplBin.meta_lic", []string{"toolchain"}},
|
||||
{"apacheBin.meta_lic", "mitLib.meta_lic", []string{"static"}},
|
||||
},
|
||||
expectedResolutions: []res{
|
||||
{"apacheBin.meta_lic", "apacheBin.meta_lic", "apacheBin.meta_lic", "notice"},
|
||||
{"apacheBin.meta_lic", "mitLib.meta_lic", "mitLib.meta_lic", "notice"},
|
||||
{"lgplBin.meta_lic", "lgplBin.meta_lic", "lgplBin.meta_lic", "restricted"},
|
||||
{"mitLib.meta_lic", "mitLib.meta_lic", "mitLib.meta_lic", "notice"},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "weakrestricteddeep",
|
||||
roots: []string{"apacheContainer.meta_lic"},
|
||||
edges: []annotated{
|
||||
{"apacheContainer.meta_lic", "apacheBin.meta_lic", []string{"static"}},
|
||||
{"apacheBin.meta_lic", "lgplLib.meta_lic", []string{"static"}},
|
||||
{"apacheBin.meta_lic", "mitLib.meta_lic", []string{"static"}},
|
||||
},
|
||||
expectedResolutions: []res{
|
||||
{"apacheContainer.meta_lic", "apacheContainer.meta_lic", "apacheContainer.meta_lic", "notice"},
|
||||
{"apacheContainer.meta_lic", "apacheContainer.meta_lic", "lgplLib.meta_lic", "restricted"},
|
||||
{"apacheContainer.meta_lic", "apacheBin.meta_lic", "apacheBin.meta_lic", "notice"},
|
||||
{"apacheContainer.meta_lic", "apacheBin.meta_lic", "lgplLib.meta_lic", "restricted"},
|
||||
{"apacheContainer.meta_lic", "lgplLib.meta_lic", "lgplLib.meta_lic", "restricted"},
|
||||
{"apacheContainer.meta_lic", "mitLib.meta_lic", "mitLib.meta_lic", "notice"},
|
||||
{"apacheContainer.meta_lic", "mitLib.meta_lic", "lgplLib.meta_lic", "restricted"},
|
||||
{"apacheBin.meta_lic", "apacheBin.meta_lic", "apacheBin.meta_lic", "notice"},
|
||||
{"apacheBin.meta_lic", "apacheBin.meta_lic", "lgplLib.meta_lic", "restricted"},
|
||||
{"apacheBin.meta_lic", "lgplLib.meta_lic", "lgplLib.meta_lic", "restricted"},
|
||||
{"apacheBin.meta_lic", "mitLib.meta_lic", "mitLib.meta_lic", "notice"},
|
||||
{"apacheBin.meta_lic", "mitLib.meta_lic", "lgplLib.meta_lic", "restricted"},
|
||||
{"lgplLib.meta_lic", "lgplLib.meta_lic", "lgplLib.meta_lic", "restricted"},
|
||||
{"mitLib.meta_lic", "mitLib.meta_lic", "mitLib.meta_lic", "notice"},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "weakrestrictedwide",
|
||||
roots: []string{"apacheContainer.meta_lic"},
|
||||
edges: []annotated{
|
||||
{"apacheContainer.meta_lic", "apacheBin.meta_lic", []string{"static"}},
|
||||
{"apacheContainer.meta_lic", "lgplLib.meta_lic", []string{"static"}},
|
||||
},
|
||||
expectedResolutions: []res{
|
||||
{"apacheContainer.meta_lic", "apacheContainer.meta_lic", "apacheContainer.meta_lic", "notice"},
|
||||
{"apacheContainer.meta_lic", "apacheContainer.meta_lic", "lgplLib.meta_lic", "restricted"},
|
||||
{"apacheContainer.meta_lic", "apacheBin.meta_lic", "apacheBin.meta_lic", "notice"},
|
||||
{"apacheContainer.meta_lic", "lgplLib.meta_lic", "lgplLib.meta_lic", "restricted"},
|
||||
{"apacheBin.meta_lic", "apacheBin.meta_lic", "apacheBin.meta_lic", "notice"},
|
||||
{"lgplLib.meta_lic", "lgplLib.meta_lic", "lgplLib.meta_lic", "restricted"},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "weakrestricteddynamic",
|
||||
roots: []string{"apacheBin.meta_lic"},
|
||||
edges: []annotated{
|
||||
{"apacheBin.meta_lic", "lgplLib.meta_lic", []string{"dynamic"}},
|
||||
{"apacheBin.meta_lic", "mitLib.meta_lic", []string{"static"}},
|
||||
},
|
||||
expectedResolutions: []res{
|
||||
{"apacheBin.meta_lic", "apacheBin.meta_lic", "apacheBin.meta_lic", "notice"},
|
||||
{"apacheBin.meta_lic", "mitLib.meta_lic", "mitLib.meta_lic", "notice"},
|
||||
{"lgplLib.meta_lic", "lgplLib.meta_lic", "lgplLib.meta_lic", "restricted"},
|
||||
{"mitLib.meta_lic", "mitLib.meta_lic", "mitLib.meta_lic", "notice"},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "weakrestricteddynamicdeep",
|
||||
roots: []string{"apacheContainer.meta_lic"},
|
||||
edges: []annotated{
|
||||
{"apacheContainer.meta_lic", "apacheBin.meta_lic", []string{"static"}},
|
||||
{"apacheBin.meta_lic", "lgplLib.meta_lic", []string{"dynamic"}},
|
||||
},
|
||||
expectedResolutions: []res{
|
||||
{"apacheContainer.meta_lic", "apacheContainer.meta_lic", "apacheContainer.meta_lic", "notice"},
|
||||
{"apacheContainer.meta_lic", "apacheBin.meta_lic", "apacheBin.meta_lic", "notice"},
|
||||
{"apacheBin.meta_lic", "apacheBin.meta_lic", "apacheBin.meta_lic", "notice"},
|
||||
{"lgplLib.meta_lic", "lgplLib.meta_lic", "lgplLib.meta_lic", "restricted"},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "weakrestricteddynamicwide",
|
||||
roots: []string{"apacheContainer.meta_lic"},
|
||||
edges: []annotated{
|
||||
{"apacheContainer.meta_lic", "apacheBin.meta_lic", []string{"static"}},
|
||||
{"apacheContainer.meta_lic", "lgplLib.meta_lic", []string{"dynamic"}},
|
||||
},
|
||||
expectedResolutions: []res{
|
||||
{"apacheContainer.meta_lic", "apacheContainer.meta_lic", "apacheContainer.meta_lic", "notice"},
|
||||
{"apacheContainer.meta_lic", "apacheBin.meta_lic", "apacheBin.meta_lic", "notice"},
|
||||
{"apacheBin.meta_lic", "apacheBin.meta_lic", "apacheBin.meta_lic", "notice"},
|
||||
{"lgplLib.meta_lic", "lgplLib.meta_lic", "lgplLib.meta_lic", "restricted"},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "classpath",
|
||||
roots: []string{"apacheBin.meta_lic"},
|
||||
edges: []annotated{
|
||||
{"apacheBin.meta_lic", "gplWithClasspathException.meta_lic", []string{"static"}},
|
||||
{"apacheBin.meta_lic", "mitLib.meta_lic", []string{"static"}},
|
||||
},
|
||||
expectedResolutions: []res{
|
||||
{"apacheBin.meta_lic", "apacheBin.meta_lic", "apacheBin.meta_lic", "notice"},
|
||||
{"apacheBin.meta_lic", "apacheBin.meta_lic", "gplWithClasspathException.meta_lic", "restricted"},
|
||||
{"apacheBin.meta_lic", "gplWithClasspathException.meta_lic", "gplWithClasspathException.meta_lic", "restricted"},
|
||||
{"apacheBin.meta_lic", "mitLib.meta_lic", "mitLib.meta_lic", "notice"},
|
||||
{"apacheBin.meta_lic", "mitLib.meta_lic", "gplWithClasspathException.meta_lic", "restricted"},
|
||||
{"gplWithClasspathException.meta_lic", "gplWithClasspathException.meta_lic", "gplWithClasspathException.meta_lic", "restricted"},
|
||||
{"mitLib.meta_lic", "mitLib.meta_lic", "mitLib.meta_lic", "notice"},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "classpathdependent",
|
||||
roots: []string{"dependentModule.meta_lic"},
|
||||
edges: []annotated{
|
||||
{"dependentModule.meta_lic", "gplWithClasspathException.meta_lic", []string{"static"}},
|
||||
{"dependentModule.meta_lic", "mitLib.meta_lic", []string{"static"}},
|
||||
},
|
||||
expectedResolutions: []res{
|
||||
{"dependentModule.meta_lic", "dependentModule.meta_lic", "dependentModule.meta_lic", "notice"},
|
||||
{"dependentModule.meta_lic", "dependentModule.meta_lic", "gplWithClasspathException.meta_lic", "restricted"},
|
||||
{"dependentModule.meta_lic", "gplWithClasspathException.meta_lic", "gplWithClasspathException.meta_lic", "restricted"},
|
||||
{"dependentModule.meta_lic", "mitLib.meta_lic", "mitLib.meta_lic", "notice"},
|
||||
{"dependentModule.meta_lic", "mitLib.meta_lic", "gplWithClasspathException.meta_lic", "restricted"},
|
||||
{"gplWithClasspathException.meta_lic", "gplWithClasspathException.meta_lic", "gplWithClasspathException.meta_lic", "restricted"},
|
||||
{"mitLib.meta_lic", "mitLib.meta_lic", "mitLib.meta_lic", "notice"},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "classpathdynamic",
|
||||
roots: []string{"apacheBin.meta_lic"},
|
||||
edges: []annotated{
|
||||
{"apacheBin.meta_lic", "gplWithClasspathException.meta_lic", []string{"dynamic"}},
|
||||
{"apacheBin.meta_lic", "mitLib.meta_lic", []string{"static"}},
|
||||
},
|
||||
expectedResolutions: []res{
|
||||
{"apacheBin.meta_lic", "apacheBin.meta_lic", "apacheBin.meta_lic", "notice"},
|
||||
{"apacheBin.meta_lic", "mitLib.meta_lic", "mitLib.meta_lic", "notice"},
|
||||
{"gplWithClasspathException.meta_lic", "gplWithClasspathException.meta_lic", "gplWithClasspathException.meta_lic", "restricted"},
|
||||
{"mitLib.meta_lic", "mitLib.meta_lic", "mitLib.meta_lic", "notice"},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "classpathdependentdynamic",
|
||||
roots: []string{"dependentModule.meta_lic"},
|
||||
edges: []annotated{
|
||||
{"dependentModule.meta_lic", "gplWithClasspathException.meta_lic", []string{"dynamic"}},
|
||||
{"dependentModule.meta_lic", "mitLib.meta_lic", []string{"static"}},
|
||||
},
|
||||
expectedResolutions: []res{
|
||||
{"dependentModule.meta_lic", "dependentModule.meta_lic", "dependentModule.meta_lic", "notice"},
|
||||
{"dependentModule.meta_lic", "dependentModule.meta_lic", "gplWithClasspathException.meta_lic", "restricted"},
|
||||
{"dependentModule.meta_lic", "gplWithClasspathException.meta_lic", "gplWithClasspathException.meta_lic", "restricted"},
|
||||
{"dependentModule.meta_lic", "mitLib.meta_lic", "mitLib.meta_lic", "notice"},
|
||||
{"dependentModule.meta_lic", "mitLib.meta_lic", "gplWithClasspathException.meta_lic", "restricted"},
|
||||
{"gplWithClasspathException.meta_lic", "gplWithClasspathException.meta_lic", "gplWithClasspathException.meta_lic", "restricted"},
|
||||
{"mitLib.meta_lic", "mitLib.meta_lic", "mitLib.meta_lic", "notice"},
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
stderr := &bytes.Buffer{}
|
||||
lg, err := toGraph(stderr, tt.roots, tt.edges)
|
||||
if err != nil {
|
||||
t.Errorf("unexpected test data error: got %w, want no error", err)
|
||||
return
|
||||
}
|
||||
expectedRs := toResolutionSet(lg, tt.expectedResolutions)
|
||||
actualRs := ResolveTopDownConditions(lg)
|
||||
checkSame(actualRs, expectedRs, t)
|
||||
})
|
||||
}
|
||||
}
|
21
tools/compliance/policy/resolvenotices.go
Normal file
21
tools/compliance/policy/resolvenotices.go
Normal file
@@ -0,0 +1,21 @@
|
||||
// Copyright 2021 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 compliance
|
||||
|
||||
// ResolveNotices implements the policy for notices.
|
||||
func ResolveNotices(lg *LicenseGraph) *ResolutionSet {
|
||||
rs := ResolveTopDownConditions(lg)
|
||||
return WalkResolutionsForCondition(lg, rs, ImpliesNotice)
|
||||
}
|
467
tools/compliance/policy/resolvenotices_test.go
Normal file
467
tools/compliance/policy/resolvenotices_test.go
Normal file
@@ -0,0 +1,467 @@
|
||||
// Copyright 2021 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 compliance
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestResolveNotices(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
roots []string
|
||||
edges []annotated
|
||||
expectedResolutions []res
|
||||
}{
|
||||
{
|
||||
name: "firstparty",
|
||||
roots: []string{"apacheBin.meta_lic"},
|
||||
edges: []annotated{
|
||||
{"apacheBin.meta_lic", "apacheLib.meta_lic", []string{"static"}},
|
||||
},
|
||||
expectedResolutions: []res{
|
||||
{"apacheBin.meta_lic", "apacheBin.meta_lic", "apacheBin.meta_lic", "notice"},
|
||||
{"apacheBin.meta_lic", "apacheLib.meta_lic", "apacheLib.meta_lic", "notice"},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "firstpartydynamic",
|
||||
roots: []string{"apacheBin.meta_lic"},
|
||||
edges: []annotated{
|
||||
{"apacheBin.meta_lic", "apacheLib.meta_lic", []string{"dynamic"}},
|
||||
},
|
||||
expectedResolutions: []res{
|
||||
{"apacheBin.meta_lic", "apacheBin.meta_lic", "apacheBin.meta_lic", "notice"},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "firstpartydynamicshipped",
|
||||
roots: []string{"apacheBin.meta_lic", "apacheLib.meta_lic"},
|
||||
edges: []annotated{
|
||||
{"apacheBin.meta_lic", "apacheLib.meta_lic", []string{"dynamic"}},
|
||||
},
|
||||
expectedResolutions: []res{
|
||||
{"apacheBin.meta_lic", "apacheBin.meta_lic", "apacheBin.meta_lic", "notice"},
|
||||
{"apacheLib.meta_lic", "apacheLib.meta_lic", "apacheLib.meta_lic", "notice"},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "restricted",
|
||||
roots: []string{"apacheBin.meta_lic"},
|
||||
edges: []annotated{
|
||||
{"apacheBin.meta_lic", "gplLib.meta_lic", []string{"static"}},
|
||||
{"apacheBin.meta_lic", "mitLib.meta_lic", []string{"static"}},
|
||||
},
|
||||
expectedResolutions: []res{
|
||||
{"apacheBin.meta_lic", "apacheBin.meta_lic", "apacheBin.meta_lic", "notice"},
|
||||
{"apacheBin.meta_lic", "apacheBin.meta_lic", "gplLib.meta_lic", "restricted"},
|
||||
{"apacheBin.meta_lic", "gplLib.meta_lic", "gplLib.meta_lic", "restricted"},
|
||||
{"apacheBin.meta_lic", "mitLib.meta_lic", "gplLib.meta_lic", "restricted"},
|
||||
{"apacheBin.meta_lic", "mitLib.meta_lic", "mitLib.meta_lic", "notice"},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "restrictedtool",
|
||||
roots: []string{"apacheBin.meta_lic"},
|
||||
edges: []annotated{
|
||||
{"apacheBin.meta_lic", "gplBin.meta_lic", []string{"toolchain"}},
|
||||
{"apacheBin.meta_lic", "mitLib.meta_lic", []string{"static"}},
|
||||
},
|
||||
expectedResolutions: []res{
|
||||
{"apacheBin.meta_lic", "apacheBin.meta_lic", "apacheBin.meta_lic", "notice"},
|
||||
{"apacheBin.meta_lic", "mitLib.meta_lic", "mitLib.meta_lic", "notice"},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "restricteddeep",
|
||||
roots: []string{"apacheContainer.meta_lic"},
|
||||
edges: []annotated{
|
||||
{"apacheContainer.meta_lic", "apacheBin.meta_lic", []string{"static"}},
|
||||
{"apacheContainer.meta_lic", "mitBin.meta_lic", []string{"static"}},
|
||||
{"apacheBin.meta_lic", "gplLib.meta_lic", []string{"static"}},
|
||||
{"apacheBin.meta_lic", "mplLib.meta_lic", []string{"static"}},
|
||||
{"mitBin.meta_lic", "mitLib.meta_lic", []string{"static"}},
|
||||
},
|
||||
expectedResolutions: []res{
|
||||
{"apacheContainer.meta_lic", "apacheContainer.meta_lic", "apacheContainer.meta_lic", "notice"},
|
||||
{"apacheContainer.meta_lic", "apacheContainer.meta_lic", "gplLib.meta_lic", "restricted"},
|
||||
{"apacheContainer.meta_lic", "apacheBin.meta_lic", "apacheBin.meta_lic", "notice"},
|
||||
{"apacheContainer.meta_lic", "apacheBin.meta_lic", "gplLib.meta_lic", "restricted"},
|
||||
{"apacheContainer.meta_lic", "gplLib.meta_lic", "gplLib.meta_lic", "restricted"},
|
||||
{"apacheContainer.meta_lic", "mitBin.meta_lic", "mitBin.meta_lic", "notice"},
|
||||
{"apacheContainer.meta_lic", "mitLib.meta_lic", "mitLib.meta_lic", "notice"},
|
||||
{"apacheContainer.meta_lic", "mplLib.meta_lic", "gplLib.meta_lic", "restricted"},
|
||||
{"apacheContainer.meta_lic", "mplLib.meta_lic", "mplLib.meta_lic", "reciprocal"},
|
||||
{"apacheBin.meta_lic", "apacheBin.meta_lic", "apacheBin.meta_lic", "notice"},
|
||||
{"apacheBin.meta_lic", "apacheBin.meta_lic", "gplLib.meta_lic", "restricted"},
|
||||
{"apacheBin.meta_lic", "gplLib.meta_lic", "gplLib.meta_lic", "restricted"},
|
||||
{"apacheBin.meta_lic", "mplLib.meta_lic", "gplLib.meta_lic", "restricted"},
|
||||
{"apacheBin.meta_lic", "mplLib.meta_lic", "mplLib.meta_lic", "reciprocal"},
|
||||
{"mitBin.meta_lic", "mitBin.meta_lic", "mitBin.meta_lic", "notice"},
|
||||
{"mitBin.meta_lic", "mitLib.meta_lic", "mitLib.meta_lic", "notice"},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "restrictedwide",
|
||||
roots: []string{"apacheContainer.meta_lic"},
|
||||
edges: []annotated{
|
||||
{"apacheContainer.meta_lic", "apacheBin.meta_lic", []string{"static"}},
|
||||
{"apacheContainer.meta_lic", "gplLib.meta_lic", []string{"static"}},
|
||||
},
|
||||
expectedResolutions: []res{
|
||||
{"apacheContainer.meta_lic", "apacheContainer.meta_lic", "apacheContainer.meta_lic", "notice"},
|
||||
{"apacheContainer.meta_lic", "apacheContainer.meta_lic", "gplLib.meta_lic", "restricted"},
|
||||
{"apacheContainer.meta_lic", "apacheBin.meta_lic", "apacheBin.meta_lic", "notice"},
|
||||
{"apacheContainer.meta_lic", "gplLib.meta_lic", "gplLib.meta_lic", "restricted"},
|
||||
{"apacheBin.meta_lic", "apacheBin.meta_lic", "apacheBin.meta_lic", "notice"},
|
||||
{"gplLib.meta_lic", "gplLib.meta_lic", "gplLib.meta_lic", "restricted"},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "restricteddynamic",
|
||||
roots: []string{"apacheBin.meta_lic"},
|
||||
edges: []annotated{
|
||||
{"apacheBin.meta_lic", "gplLib.meta_lic", []string{"dynamic"}},
|
||||
{"apacheBin.meta_lic", "mitLib.meta_lic", []string{"dynamic"}},
|
||||
},
|
||||
expectedResolutions: []res{
|
||||
{"apacheBin.meta_lic", "apacheBin.meta_lic", "apacheBin.meta_lic", "notice"},
|
||||
{"apacheBin.meta_lic", "apacheBin.meta_lic", "gplLib.meta_lic", "restricted"},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "restricteddynamicshipped",
|
||||
roots: []string{"apacheBin.meta_lic", "mitLib.meta_lic"},
|
||||
edges: []annotated{
|
||||
{"apacheBin.meta_lic", "gplLib.meta_lic", []string{"dynamic"}},
|
||||
{"apacheBin.meta_lic", "mitLib.meta_lic", []string{"dynamic"}},
|
||||
},
|
||||
expectedResolutions: []res{
|
||||
{"apacheBin.meta_lic", "apacheBin.meta_lic", "apacheBin.meta_lic", "notice"},
|
||||
{"apacheBin.meta_lic", "apacheBin.meta_lic", "gplLib.meta_lic", "restricted"},
|
||||
{"apacheBin.meta_lic", "mitLib.meta_lic", "gplLib.meta_lic", "restricted"},
|
||||
{"mitLib.meta_lic", "mitLib.meta_lic", "mitLib.meta_lic", "notice"},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "restricteddynamicdeep",
|
||||
roots: []string{"apacheContainer.meta_lic"},
|
||||
edges: []annotated{
|
||||
{"apacheContainer.meta_lic", "apacheBin.meta_lic", []string{"static"}},
|
||||
{"apacheContainer.meta_lic", "mitBin.meta_lic", []string{"static"}},
|
||||
{"apacheBin.meta_lic", "gplLib.meta_lic", []string{"dynamic"}},
|
||||
{"apacheBin.meta_lic", "mplLib.meta_lic", []string{"dynamic"}},
|
||||
{"mitBin.meta_lic", "mitLib.meta_lic", []string{"dynamic"}},
|
||||
},
|
||||
expectedResolutions: []res{
|
||||
{"apacheContainer.meta_lic", "apacheContainer.meta_lic", "apacheContainer.meta_lic", "notice"},
|
||||
{"apacheContainer.meta_lic", "apacheContainer.meta_lic", "gplLib.meta_lic", "restricted"},
|
||||
{"apacheContainer.meta_lic", "apacheBin.meta_lic", "apacheBin.meta_lic", "notice"},
|
||||
{"apacheContainer.meta_lic", "apacheBin.meta_lic", "gplLib.meta_lic", "restricted"},
|
||||
{"apacheContainer.meta_lic", "mitBin.meta_lic", "mitBin.meta_lic", "notice"},
|
||||
{"apacheBin.meta_lic", "apacheBin.meta_lic", "apacheBin.meta_lic", "notice"},
|
||||
{"apacheBin.meta_lic", "apacheBin.meta_lic", "gplLib.meta_lic", "restricted"},
|
||||
{"mitBin.meta_lic", "mitBin.meta_lic", "mitBin.meta_lic", "notice"},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "restricteddynamicwide",
|
||||
roots: []string{"apacheContainer.meta_lic"},
|
||||
edges: []annotated{
|
||||
{"apacheContainer.meta_lic", "apacheBin.meta_lic", []string{"static"}},
|
||||
{"apacheContainer.meta_lic", "gplLib.meta_lic", []string{"dynamic"}},
|
||||
},
|
||||
expectedResolutions: []res{
|
||||
{"apacheContainer.meta_lic", "apacheContainer.meta_lic", "apacheContainer.meta_lic", "notice"},
|
||||
{"apacheContainer.meta_lic", "apacheContainer.meta_lic", "gplLib.meta_lic", "restricted"},
|
||||
{"apacheContainer.meta_lic", "apacheBin.meta_lic", "apacheBin.meta_lic", "notice"},
|
||||
{"apacheBin.meta_lic", "apacheBin.meta_lic", "apacheBin.meta_lic", "notice"},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "restricteddynamicwideshipped",
|
||||
roots: []string{"apacheContainer.meta_lic", "gplLib.meta_lic"},
|
||||
edges: []annotated{
|
||||
{"apacheContainer.meta_lic", "apacheBin.meta_lic", []string{"static"}},
|
||||
{"apacheContainer.meta_lic", "gplLib.meta_lic", []string{"dynamic"}},
|
||||
},
|
||||
expectedResolutions: []res{
|
||||
{"apacheContainer.meta_lic", "apacheContainer.meta_lic", "apacheContainer.meta_lic", "notice"},
|
||||
{"apacheContainer.meta_lic", "apacheContainer.meta_lic", "gplLib.meta_lic", "restricted"},
|
||||
{"apacheContainer.meta_lic", "apacheBin.meta_lic", "apacheBin.meta_lic", "notice"},
|
||||
{"apacheContainer.meta_lic", "gplLib.meta_lic", "gplLib.meta_lic", "restricted"},
|
||||
{"apacheBin.meta_lic", "apacheBin.meta_lic", "apacheBin.meta_lic", "notice"},
|
||||
{"gplLib.meta_lic", "gplLib.meta_lic", "gplLib.meta_lic", "restricted"},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "weakrestricted",
|
||||
roots: []string{"apacheBin.meta_lic"},
|
||||
edges: []annotated{
|
||||
{"apacheBin.meta_lic", "lgplLib.meta_lic", []string{"static"}},
|
||||
{"apacheBin.meta_lic", "mitLib.meta_lic", []string{"static"}},
|
||||
},
|
||||
expectedResolutions: []res{
|
||||
{"apacheBin.meta_lic", "apacheBin.meta_lic", "apacheBin.meta_lic", "notice"},
|
||||
{"apacheBin.meta_lic", "apacheBin.meta_lic", "lgplLib.meta_lic", "restricted"},
|
||||
{"apacheBin.meta_lic", "lgplLib.meta_lic", "lgplLib.meta_lic", "restricted"},
|
||||
{"apacheBin.meta_lic", "mitLib.meta_lic", "mitLib.meta_lic", "notice"},
|
||||
{"apacheBin.meta_lic", "mitLib.meta_lic", "lgplLib.meta_lic", "restricted"},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "weakrestrictedtool",
|
||||
roots: []string{"apacheBin.meta_lic"},
|
||||
edges: []annotated{
|
||||
{"apacheBin.meta_lic", "lgplBin.meta_lic", []string{"toolchain"}},
|
||||
{"apacheBin.meta_lic", "mitLib.meta_lic", []string{"static"}},
|
||||
},
|
||||
expectedResolutions: []res{
|
||||
{"apacheBin.meta_lic", "apacheBin.meta_lic", "apacheBin.meta_lic", "notice"},
|
||||
{"apacheBin.meta_lic", "mitLib.meta_lic", "mitLib.meta_lic", "notice"},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "weakrestrictedtoolshipped",
|
||||
roots: []string{"apacheBin.meta_lic", "lgplBin.meta_lic"},
|
||||
edges: []annotated{
|
||||
{"apacheBin.meta_lic", "lgplBin.meta_lic", []string{"toolchain"}},
|
||||
{"apacheBin.meta_lic", "mitLib.meta_lic", []string{"static"}},
|
||||
},
|
||||
expectedResolutions: []res{
|
||||
{"apacheBin.meta_lic", "apacheBin.meta_lic", "apacheBin.meta_lic", "notice"},
|
||||
{"apacheBin.meta_lic", "mitLib.meta_lic", "mitLib.meta_lic", "notice"},
|
||||
{"lgplBin.meta_lic", "lgplBin.meta_lic", "lgplBin.meta_lic", "restricted"},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "weakrestricteddeep",
|
||||
roots: []string{"apacheContainer.meta_lic"},
|
||||
edges: []annotated{
|
||||
{"apacheContainer.meta_lic", "apacheBin.meta_lic", []string{"static"}},
|
||||
{"apacheBin.meta_lic", "lgplLib.meta_lic", []string{"static"}},
|
||||
{"apacheBin.meta_lic", "mitLib.meta_lic", []string{"static"}},
|
||||
},
|
||||
expectedResolutions: []res{
|
||||
{"apacheContainer.meta_lic", "apacheContainer.meta_lic", "apacheContainer.meta_lic", "notice"},
|
||||
{"apacheContainer.meta_lic", "apacheContainer.meta_lic", "lgplLib.meta_lic", "restricted"},
|
||||
{"apacheContainer.meta_lic", "apacheBin.meta_lic", "apacheBin.meta_lic", "notice"},
|
||||
{"apacheContainer.meta_lic", "apacheBin.meta_lic", "lgplLib.meta_lic", "restricted"},
|
||||
{"apacheContainer.meta_lic", "lgplLib.meta_lic", "lgplLib.meta_lic", "restricted"},
|
||||
{"apacheContainer.meta_lic", "mitLib.meta_lic", "mitLib.meta_lic", "notice"},
|
||||
{"apacheContainer.meta_lic", "mitLib.meta_lic", "lgplLib.meta_lic", "restricted"},
|
||||
{"apacheBin.meta_lic", "apacheBin.meta_lic", "apacheBin.meta_lic", "notice"},
|
||||
{"apacheBin.meta_lic", "apacheBin.meta_lic", "lgplLib.meta_lic", "restricted"},
|
||||
{"apacheBin.meta_lic", "lgplLib.meta_lic", "lgplLib.meta_lic", "restricted"},
|
||||
{"apacheBin.meta_lic", "mitLib.meta_lic", "mitLib.meta_lic", "notice"},
|
||||
{"apacheBin.meta_lic", "mitLib.meta_lic", "lgplLib.meta_lic", "restricted"},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "weakrestrictedwide",
|
||||
roots: []string{"apacheContainer.meta_lic"},
|
||||
edges: []annotated{
|
||||
{"apacheContainer.meta_lic", "apacheBin.meta_lic", []string{"static"}},
|
||||
{"apacheContainer.meta_lic", "lgplLib.meta_lic", []string{"static"}},
|
||||
},
|
||||
expectedResolutions: []res{
|
||||
{"apacheContainer.meta_lic", "apacheContainer.meta_lic", "apacheContainer.meta_lic", "notice"},
|
||||
{"apacheContainer.meta_lic", "apacheContainer.meta_lic", "lgplLib.meta_lic", "restricted"},
|
||||
{"apacheContainer.meta_lic", "apacheBin.meta_lic", "apacheBin.meta_lic", "notice"},
|
||||
{"apacheContainer.meta_lic", "lgplLib.meta_lic", "lgplLib.meta_lic", "restricted"},
|
||||
{"apacheBin.meta_lic", "apacheBin.meta_lic", "apacheBin.meta_lic", "notice"},
|
||||
{"lgplLib.meta_lic", "lgplLib.meta_lic", "lgplLib.meta_lic", "restricted"},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "weakrestricteddynamic",
|
||||
roots: []string{"apacheBin.meta_lic"},
|
||||
edges: []annotated{
|
||||
{"apacheBin.meta_lic", "lgplLib.meta_lic", []string{"dynamic"}},
|
||||
{"apacheBin.meta_lic", "mitLib.meta_lic", []string{"static"}},
|
||||
},
|
||||
expectedResolutions: []res{
|
||||
{"apacheBin.meta_lic", "apacheBin.meta_lic", "apacheBin.meta_lic", "notice"},
|
||||
{"apacheBin.meta_lic", "mitLib.meta_lic", "mitLib.meta_lic", "notice"},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "weakrestricteddynamicshipped",
|
||||
roots: []string{"apacheBin.meta_lic", "lgplLib.meta_lic"},
|
||||
edges: []annotated{
|
||||
{"apacheBin.meta_lic", "lgplLib.meta_lic", []string{"dynamic"}},
|
||||
{"apacheBin.meta_lic", "mitLib.meta_lic", []string{"static"}},
|
||||
},
|
||||
expectedResolutions: []res{
|
||||
{"apacheBin.meta_lic", "apacheBin.meta_lic", "apacheBin.meta_lic", "notice"},
|
||||
{"apacheBin.meta_lic", "mitLib.meta_lic", "mitLib.meta_lic", "notice"},
|
||||
{"lgplLib.meta_lic", "lgplLib.meta_lic", "lgplLib.meta_lic", "restricted"},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "weakrestricteddynamicdeep",
|
||||
roots: []string{"apacheContainer.meta_lic"},
|
||||
edges: []annotated{
|
||||
{"apacheContainer.meta_lic", "apacheBin.meta_lic", []string{"static"}},
|
||||
{"apacheBin.meta_lic", "lgplLib.meta_lic", []string{"dynamic"}},
|
||||
},
|
||||
expectedResolutions: []res{
|
||||
{"apacheContainer.meta_lic", "apacheContainer.meta_lic", "apacheContainer.meta_lic", "notice"},
|
||||
{"apacheContainer.meta_lic", "apacheBin.meta_lic", "apacheBin.meta_lic", "notice"},
|
||||
{"apacheBin.meta_lic", "apacheBin.meta_lic", "apacheBin.meta_lic", "notice"},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "weakrestricteddynamicdeepshipped",
|
||||
roots: []string{"apacheContainer.meta_lic", "lgplLib.meta_lic"},
|
||||
edges: []annotated{
|
||||
{"apacheContainer.meta_lic", "apacheBin.meta_lic", []string{"static"}},
|
||||
{"apacheBin.meta_lic", "lgplLib.meta_lic", []string{"dynamic"}},
|
||||
},
|
||||
expectedResolutions: []res{
|
||||
{"apacheContainer.meta_lic", "apacheContainer.meta_lic", "apacheContainer.meta_lic", "notice"},
|
||||
{"apacheContainer.meta_lic", "apacheBin.meta_lic", "apacheBin.meta_lic", "notice"},
|
||||
{"apacheBin.meta_lic", "apacheBin.meta_lic", "apacheBin.meta_lic", "notice"},
|
||||
{"lgplLib.meta_lic", "lgplLib.meta_lic", "lgplLib.meta_lic", "restricted"},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "weakrestricteddynamicwide",
|
||||
roots: []string{"apacheContainer.meta_lic"},
|
||||
edges: []annotated{
|
||||
{"apacheContainer.meta_lic", "apacheBin.meta_lic", []string{"static"}},
|
||||
{"apacheContainer.meta_lic", "lgplLib.meta_lic", []string{"dynamic"}},
|
||||
},
|
||||
expectedResolutions: []res{
|
||||
{"apacheContainer.meta_lic", "apacheContainer.meta_lic", "apacheContainer.meta_lic", "notice"},
|
||||
{"apacheContainer.meta_lic", "apacheBin.meta_lic", "apacheBin.meta_lic", "notice"},
|
||||
{"apacheBin.meta_lic", "apacheBin.meta_lic", "apacheBin.meta_lic", "notice"},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "weakrestricteddynamicwideshipped",
|
||||
roots: []string{"apacheContainer.meta_lic", "lgplLib.meta_lic"},
|
||||
edges: []annotated{
|
||||
{"apacheContainer.meta_lic", "apacheBin.meta_lic", []string{"static"}},
|
||||
{"apacheContainer.meta_lic", "lgplLib.meta_lic", []string{"dynamic"}},
|
||||
},
|
||||
expectedResolutions: []res{
|
||||
{"apacheContainer.meta_lic", "apacheContainer.meta_lic", "apacheContainer.meta_lic", "notice"},
|
||||
{"apacheContainer.meta_lic", "apacheBin.meta_lic", "apacheBin.meta_lic", "notice"},
|
||||
{"apacheBin.meta_lic", "apacheBin.meta_lic", "apacheBin.meta_lic", "notice"},
|
||||
{"lgplLib.meta_lic", "lgplLib.meta_lic", "lgplLib.meta_lic", "restricted"},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "classpath",
|
||||
roots: []string{"apacheBin.meta_lic"},
|
||||
edges: []annotated{
|
||||
{"apacheBin.meta_lic", "gplWithClasspathException.meta_lic", []string{"static"}},
|
||||
{"apacheBin.meta_lic", "mitLib.meta_lic", []string{"static"}},
|
||||
},
|
||||
expectedResolutions: []res{
|
||||
{"apacheBin.meta_lic", "apacheBin.meta_lic", "apacheBin.meta_lic", "notice"},
|
||||
{"apacheBin.meta_lic", "apacheBin.meta_lic", "gplWithClasspathException.meta_lic", "restricted"},
|
||||
{"apacheBin.meta_lic", "gplWithClasspathException.meta_lic", "gplWithClasspathException.meta_lic", "restricted"},
|
||||
{"apacheBin.meta_lic", "mitLib.meta_lic", "mitLib.meta_lic", "notice"},
|
||||
{"apacheBin.meta_lic", "mitLib.meta_lic", "gplWithClasspathException.meta_lic", "restricted"},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "classpathdependent",
|
||||
roots: []string{"dependentModule.meta_lic"},
|
||||
edges: []annotated{
|
||||
{"dependentModule.meta_lic", "gplWithClasspathException.meta_lic", []string{"static"}},
|
||||
{"dependentModule.meta_lic", "mitLib.meta_lic", []string{"static"}},
|
||||
},
|
||||
expectedResolutions: []res{
|
||||
{"dependentModule.meta_lic", "dependentModule.meta_lic", "dependentModule.meta_lic", "notice"},
|
||||
{"dependentModule.meta_lic", "dependentModule.meta_lic", "gplWithClasspathException.meta_lic", "restricted"},
|
||||
{"dependentModule.meta_lic", "gplWithClasspathException.meta_lic", "gplWithClasspathException.meta_lic", "restricted"},
|
||||
{"dependentModule.meta_lic", "mitLib.meta_lic", "mitLib.meta_lic", "notice"},
|
||||
{"dependentModule.meta_lic", "mitLib.meta_lic", "gplWithClasspathException.meta_lic", "restricted"},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "classpathdynamic",
|
||||
roots: []string{"apacheBin.meta_lic"},
|
||||
edges: []annotated{
|
||||
{"apacheBin.meta_lic", "gplWithClasspathException.meta_lic", []string{"dynamic"}},
|
||||
{"apacheBin.meta_lic", "mitLib.meta_lic", []string{"static"}},
|
||||
},
|
||||
expectedResolutions: []res{
|
||||
{"apacheBin.meta_lic", "apacheBin.meta_lic", "apacheBin.meta_lic", "notice"},
|
||||
{"apacheBin.meta_lic", "mitLib.meta_lic", "mitLib.meta_lic", "notice"},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "classpathdynamicshipped",
|
||||
roots: []string{"apacheBin.meta_lic", "gplWithClasspathException.meta_lic"},
|
||||
edges: []annotated{
|
||||
{"apacheBin.meta_lic", "gplWithClasspathException.meta_lic", []string{"dynamic"}},
|
||||
{"apacheBin.meta_lic", "mitLib.meta_lic", []string{"static"}},
|
||||
},
|
||||
expectedResolutions: []res{
|
||||
{"apacheBin.meta_lic", "apacheBin.meta_lic", "apacheBin.meta_lic", "notice"},
|
||||
{"apacheBin.meta_lic", "mitLib.meta_lic", "mitLib.meta_lic", "notice"},
|
||||
{"gplWithClasspathException.meta_lic", "gplWithClasspathException.meta_lic", "gplWithClasspathException.meta_lic", "restricted"},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "classpathdependentdynamic",
|
||||
roots: []string{"dependentModule.meta_lic"},
|
||||
edges: []annotated{
|
||||
{"dependentModule.meta_lic", "gplWithClasspathException.meta_lic", []string{"dynamic"}},
|
||||
{"dependentModule.meta_lic", "mitLib.meta_lic", []string{"static"}},
|
||||
},
|
||||
expectedResolutions: []res{
|
||||
{"dependentModule.meta_lic", "dependentModule.meta_lic", "dependentModule.meta_lic", "notice"},
|
||||
{"dependentModule.meta_lic", "dependentModule.meta_lic", "gplWithClasspathException.meta_lic", "restricted"},
|
||||
{"dependentModule.meta_lic", "mitLib.meta_lic", "mitLib.meta_lic", "notice"},
|
||||
{"dependentModule.meta_lic", "mitLib.meta_lic", "gplWithClasspathException.meta_lic", "restricted"},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "classpathdependentdynamicshipped",
|
||||
roots: []string{"dependentModule.meta_lic", "gplWithClasspathException.meta_lic"},
|
||||
edges: []annotated{
|
||||
{"dependentModule.meta_lic", "gplWithClasspathException.meta_lic", []string{"dynamic"}},
|
||||
{"dependentModule.meta_lic", "mitLib.meta_lic", []string{"static"}},
|
||||
},
|
||||
expectedResolutions: []res{
|
||||
{"dependentModule.meta_lic", "dependentModule.meta_lic", "dependentModule.meta_lic", "notice"},
|
||||
{"dependentModule.meta_lic", "dependentModule.meta_lic", "gplWithClasspathException.meta_lic", "restricted"},
|
||||
{"dependentModule.meta_lic", "gplWithClasspathException.meta_lic", "gplWithClasspathException.meta_lic", "restricted"},
|
||||
{"dependentModule.meta_lic", "mitLib.meta_lic", "mitLib.meta_lic", "notice"},
|
||||
{"dependentModule.meta_lic", "mitLib.meta_lic", "gplWithClasspathException.meta_lic", "restricted"},
|
||||
{"gplWithClasspathException.meta_lic", "gplWithClasspathException.meta_lic", "gplWithClasspathException.meta_lic", "restricted"},
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
stderr := &bytes.Buffer{}
|
||||
lg, err := toGraph(stderr, tt.roots, tt.edges)
|
||||
if err != nil {
|
||||
t.Errorf("unexpected test data error: got %w, want no error", err)
|
||||
return
|
||||
}
|
||||
expectedRs := toResolutionSet(lg, tt.expectedResolutions)
|
||||
actualRs := ResolveNotices(lg)
|
||||
checkSame(actualRs, expectedRs, t)
|
||||
})
|
||||
}
|
||||
}
|
21
tools/compliance/policy/resolveprivacy.go
Normal file
21
tools/compliance/policy/resolveprivacy.go
Normal file
@@ -0,0 +1,21 @@
|
||||
// Copyright 2021 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 compliance
|
||||
|
||||
// ResolveSourcePrivacy implements the policy for source privacy.
|
||||
func ResolveSourcePrivacy(lg *LicenseGraph) *ResolutionSet {
|
||||
rs := ResolveTopDownConditions(lg)
|
||||
return WalkResolutionsForCondition(lg, rs, ImpliesPrivate)
|
||||
}
|
87
tools/compliance/policy/resolveprivacy_test.go
Normal file
87
tools/compliance/policy/resolveprivacy_test.go
Normal file
@@ -0,0 +1,87 @@
|
||||
// Copyright 2021 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 compliance
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestResolveSourcePrivacy(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
roots []string
|
||||
edges []annotated
|
||||
expectedResolutions []res
|
||||
}{
|
||||
{
|
||||
name: "firstparty",
|
||||
roots: []string{"apacheBin.meta_lic"},
|
||||
edges: []annotated{
|
||||
{"apacheBin.meta_lic", "apacheLib.meta_lic", []string{"static"}},
|
||||
},
|
||||
expectedResolutions: []res{},
|
||||
},
|
||||
{
|
||||
name: "notice",
|
||||
roots: []string{"mitBin.meta_lic"},
|
||||
edges: []annotated{
|
||||
{"mitBin.meta_lic", "mitLib.meta_lic", []string{"static"}},
|
||||
},
|
||||
expectedResolutions: []res{},
|
||||
},
|
||||
{
|
||||
name: "lgpl",
|
||||
roots: []string{"lgplBin.meta_lic"},
|
||||
edges: []annotated{
|
||||
{"lgplBin.meta_lic", "apacheLib.meta_lic", []string{"static"}},
|
||||
},
|
||||
expectedResolutions: []res{},
|
||||
},
|
||||
{
|
||||
name: "proprietaryonresricted",
|
||||
roots: []string{"proprietary.meta_lic"},
|
||||
edges: []annotated{
|
||||
{"proprietary.meta_lic", "gplLib.meta_lic", []string{"static"}},
|
||||
},
|
||||
expectedResolutions: []res{
|
||||
{"proprietary.meta_lic", "proprietary.meta_lic", "proprietary.meta_lic", "proprietary"},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "restrictedonproprietary",
|
||||
roots: []string{"gplBin.meta_lic"},
|
||||
edges: []annotated{
|
||||
{"gplBin.meta_lic", "proprietary.meta_lic", []string{"static"}},
|
||||
},
|
||||
expectedResolutions: []res{
|
||||
{"gplBin.meta_lic", "proprietary.meta_lic", "proprietary.meta_lic", "proprietary"},
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
stderr := &bytes.Buffer{}
|
||||
lg, err := toGraph(stderr, tt.roots, tt.edges)
|
||||
if err != nil {
|
||||
t.Errorf("unexpected test data error: got %w, want no error", err)
|
||||
return
|
||||
}
|
||||
expectedRs := toResolutionSet(lg, tt.expectedResolutions)
|
||||
actualRs := ResolveSourcePrivacy(lg)
|
||||
checkSame(actualRs, expectedRs, t)
|
||||
})
|
||||
}
|
||||
}
|
21
tools/compliance/policy/resolveshare.go
Normal file
21
tools/compliance/policy/resolveshare.go
Normal file
@@ -0,0 +1,21 @@
|
||||
// Copyright 2021 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 compliance
|
||||
|
||||
// ResolveSourceSharing implements the policy for source-sharing.
|
||||
func ResolveSourceSharing(lg *LicenseGraph) *ResolutionSet {
|
||||
rs := ResolveTopDownConditions(lg)
|
||||
return WalkResolutionsForCondition(lg, rs, ImpliesShared)
|
||||
}
|
295
tools/compliance/policy/resolveshare_test.go
Normal file
295
tools/compliance/policy/resolveshare_test.go
Normal file
@@ -0,0 +1,295 @@
|
||||
// Copyright 2021 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 compliance
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestResolveSourceSharing(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
roots []string
|
||||
edges []annotated
|
||||
expectedResolutions []res
|
||||
}{
|
||||
{
|
||||
name: "independentmodulerestricted",
|
||||
roots: []string{"apacheBin.meta_lic"},
|
||||
edges: []annotated{
|
||||
{"apacheBin.meta_lic", "gplWithClasspathException.meta_lic", []string{"dynamic"}},
|
||||
},
|
||||
expectedResolutions: []res{},
|
||||
},
|
||||
{
|
||||
name: "independentmodulerestrictedshipped",
|
||||
roots: []string{"apacheBin.meta_lic", "gplWithClasspathException.meta_lic"},
|
||||
edges: []annotated{
|
||||
{"apacheBin.meta_lic", "gplWithClasspathException.meta_lic", []string{"dynamic"}},
|
||||
},
|
||||
expectedResolutions: []res{
|
||||
{"gplWithClasspathException.meta_lic", "gplWithClasspathException.meta_lic", "gplWithClasspathException.meta_lic", "restricted"},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "independentmodulestaticrestricted",
|
||||
roots: []string{"apacheBin.meta_lic"},
|
||||
edges: []annotated{
|
||||
{"apacheBin.meta_lic", "gplWithClasspathException.meta_lic", []string{"static"}},
|
||||
},
|
||||
expectedResolutions: []res{
|
||||
{"apacheBin.meta_lic", "apacheBin.meta_lic", "gplWithClasspathException.meta_lic", "restricted"},
|
||||
{"apacheBin.meta_lic", "gplWithClasspathException.meta_lic", "gplWithClasspathException.meta_lic", "restricted"},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "dependentmodulerestricted",
|
||||
roots: []string{"dependentModule.meta_lic"},
|
||||
edges: []annotated{
|
||||
{"dependentModule.meta_lic", "gplWithClasspathException.meta_lic", []string{"dynamic"}},
|
||||
},
|
||||
expectedResolutions: []res{
|
||||
{"dependentModule.meta_lic", "dependentModule.meta_lic", "gplWithClasspathException.meta_lic", "restricted"},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "dependentmodulerestrictedshipclasspath",
|
||||
roots: []string{"dependentModule.meta_lic", "gplWithClasspathException.meta_lic"},
|
||||
edges: []annotated{
|
||||
{"dependentModule.meta_lic", "gplWithClasspathException.meta_lic", []string{"dynamic"}},
|
||||
},
|
||||
expectedResolutions: []res{
|
||||
{"dependentModule.meta_lic", "dependentModule.meta_lic", "gplWithClasspathException.meta_lic", "restricted"},
|
||||
{"dependentModule.meta_lic", "gplWithClasspathException.meta_lic", "gplWithClasspathException.meta_lic", "restricted"},
|
||||
{"gplWithClasspathException.meta_lic", "gplWithClasspathException.meta_lic", "gplWithClasspathException.meta_lic", "restricted"},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "lgplonfprestricted",
|
||||
roots: []string{"lgplBin.meta_lic"},
|
||||
edges: []annotated{
|
||||
{"lgplBin.meta_lic", "apacheLib.meta_lic", []string{"static"}},
|
||||
},
|
||||
expectedResolutions: []res{
|
||||
{"lgplBin.meta_lic", "lgplBin.meta_lic", "lgplBin.meta_lic", "restricted"},
|
||||
{"lgplBin.meta_lic", "apacheLib.meta_lic", "lgplBin.meta_lic", "restricted"},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "lgplonfpdynamicrestricted",
|
||||
roots: []string{"lgplBin.meta_lic"},
|
||||
edges: []annotated{
|
||||
{"lgplBin.meta_lic", "apacheLib.meta_lic", []string{"dynamic"}},
|
||||
},
|
||||
expectedResolutions: []res{
|
||||
{"lgplBin.meta_lic", "lgplBin.meta_lic", "lgplBin.meta_lic", "restricted"},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "lgplonfpdynamicrestrictedshiplib",
|
||||
roots: []string{"lgplBin.meta_lic", "apacheLib.meta_lic"},
|
||||
edges: []annotated{
|
||||
{"lgplBin.meta_lic", "apacheLib.meta_lic", []string{"dynamic"}},
|
||||
},
|
||||
expectedResolutions: []res{
|
||||
{"lgplBin.meta_lic", "lgplBin.meta_lic", "lgplBin.meta_lic", "restricted"},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "gplonfprestricted",
|
||||
roots: []string{"gplBin.meta_lic"},
|
||||
edges: []annotated{
|
||||
{"gplBin.meta_lic", "apacheLib.meta_lic", []string{"static"}},
|
||||
},
|
||||
expectedResolutions: []res{
|
||||
{"gplBin.meta_lic", "gplBin.meta_lic", "gplBin.meta_lic", "restricted"},
|
||||
{"gplBin.meta_lic", "apacheLib.meta_lic", "gplBin.meta_lic", "restricted"},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "gplcontainerrestricted",
|
||||
roots: []string{"gplContainer.meta_lic"},
|
||||
edges: []annotated{
|
||||
{"gplContainer.meta_lic", "apacheLib.meta_lic", []string{"static"}},
|
||||
},
|
||||
expectedResolutions: []res{
|
||||
{"gplContainer.meta_lic", "gplContainer.meta_lic", "gplContainer.meta_lic", "restricted"},
|
||||
{"gplContainer.meta_lic", "apacheLib.meta_lic", "gplContainer.meta_lic", "restricted"},
|
||||
{"apacheLib.meta_lic", "apacheLib.meta_lic", "gplContainer.meta_lic", "restricted"},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "gploncontainerrestricted",
|
||||
roots: []string{"apacheContainer.meta_lic"},
|
||||
edges: []annotated{
|
||||
{"apacheContainer.meta_lic", "apacheLib.meta_lic", []string{"static"}},
|
||||
{"apacheContainer.meta_lic", "gplLib.meta_lic", []string{"static"}},
|
||||
},
|
||||
expectedResolutions: []res{
|
||||
{"apacheContainer.meta_lic", "apacheContainer.meta_lic", "gplLib.meta_lic", "restricted"},
|
||||
{"apacheContainer.meta_lic", "gplLib.meta_lic", "gplLib.meta_lic", "restricted"},
|
||||
{"gplLib.meta_lic", "gplLib.meta_lic", "gplLib.meta_lic", "restricted"},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "gplonbinrestricted",
|
||||
roots: []string{"apacheBin.meta_lic"},
|
||||
edges: []annotated{
|
||||
{"apacheBin.meta_lic", "apacheLib.meta_lic", []string{"static"}},
|
||||
{"apacheBin.meta_lic", "gplLib.meta_lic", []string{"static"}},
|
||||
},
|
||||
expectedResolutions: []res{
|
||||
{"apacheBin.meta_lic", "apacheBin.meta_lic", "gplLib.meta_lic", "restricted"},
|
||||
{"apacheBin.meta_lic", "gplLib.meta_lic", "gplLib.meta_lic", "restricted"},
|
||||
{"apacheBin.meta_lic", "apacheLib.meta_lic", "gplLib.meta_lic", "restricted"},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "gplonfpdynamicrestricted",
|
||||
roots: []string{"gplBin.meta_lic"},
|
||||
edges: []annotated{
|
||||
{"gplBin.meta_lic", "apacheLib.meta_lic", []string{"dynamic"}},
|
||||
},
|
||||
expectedResolutions: []res{
|
||||
{"gplBin.meta_lic", "gplBin.meta_lic", "gplBin.meta_lic", "restricted"},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "gplonfpdynamicrestrictedshiplib",
|
||||
roots: []string{"gplBin.meta_lic", "apacheLib.meta_lic"},
|
||||
edges: []annotated{
|
||||
{"gplBin.meta_lic", "apacheLib.meta_lic", []string{"dynamic"}},
|
||||
},
|
||||
expectedResolutions: []res{
|
||||
{"gplBin.meta_lic", "gplBin.meta_lic", "gplBin.meta_lic", "restricted"},
|
||||
{"gplBin.meta_lic", "apacheLib.meta_lic", "gplBin.meta_lic", "restricted"},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "independentmodulereverserestricted",
|
||||
roots: []string{"gplWithClasspathException.meta_lic"},
|
||||
edges: []annotated{
|
||||
{"gplWithClasspathException.meta_lic", "apacheBin.meta_lic", []string{"dynamic"}},
|
||||
},
|
||||
expectedResolutions: []res{
|
||||
{"gplWithClasspathException.meta_lic", "gplWithClasspathException.meta_lic", "gplWithClasspathException.meta_lic", "restricted"},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "independentmodulereversestaticrestricted",
|
||||
roots: []string{"gplWithClasspathException.meta_lic"},
|
||||
edges: []annotated{
|
||||
{"gplWithClasspathException.meta_lic", "apacheBin.meta_lic", []string{"static"}},
|
||||
},
|
||||
expectedResolutions: []res{
|
||||
{"gplWithClasspathException.meta_lic", "gplWithClasspathException.meta_lic", "gplWithClasspathException.meta_lic", "restricted"},
|
||||
{"gplWithClasspathException.meta_lic", "apacheBin.meta_lic", "gplWithClasspathException.meta_lic", "restricted"},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "dependentmodulereverserestricted",
|
||||
roots: []string{"gplWithClasspathException.meta_lic"},
|
||||
edges: []annotated{
|
||||
{"gplWithClasspathException.meta_lic", "dependentModule.meta_lic", []string{"dynamic"}},
|
||||
},
|
||||
expectedResolutions: []res{
|
||||
{"gplWithClasspathException.meta_lic", "gplWithClasspathException.meta_lic", "gplWithClasspathException.meta_lic", "restricted"},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "dependentmodulereverserestrictedshipdependent",
|
||||
roots: []string{"gplWithClasspathException.meta_lic", "dependentModule.meta_lic"},
|
||||
edges: []annotated{
|
||||
{"gplWithClasspathException.meta_lic", "dependentModule.meta_lic", []string{"dynamic"}},
|
||||
},
|
||||
expectedResolutions: []res{
|
||||
{"gplWithClasspathException.meta_lic", "gplWithClasspathException.meta_lic", "gplWithClasspathException.meta_lic", "restricted"},
|
||||
{"gplWithClasspathException.meta_lic", "dependentModule.meta_lic", "gplWithClasspathException.meta_lic", "restricted"},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "ponrrestricted",
|
||||
roots: []string{"proprietary.meta_lic"},
|
||||
edges: []annotated{
|
||||
{"proprietary.meta_lic", "gplLib.meta_lic", []string{"static"}},
|
||||
},
|
||||
expectedResolutions: []res{
|
||||
{"proprietary.meta_lic", "proprietary.meta_lic", "gplLib.meta_lic", "restricted"},
|
||||
{"proprietary.meta_lic", "gplLib.meta_lic", "gplLib.meta_lic", "restricted"},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "ronprestricted",
|
||||
roots: []string{"gplBin.meta_lic"},
|
||||
edges: []annotated{
|
||||
{"gplBin.meta_lic", "proprietary.meta_lic", []string{"static"}},
|
||||
},
|
||||
expectedResolutions: []res{
|
||||
{"gplBin.meta_lic", "gplBin.meta_lic", "gplBin.meta_lic", "restricted"},
|
||||
{"gplBin.meta_lic", "proprietary.meta_lic", "gplBin.meta_lic", "restricted"},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "noticeonb_e_orestricted",
|
||||
roots: []string{"mitBin.meta_lic"},
|
||||
edges: []annotated{
|
||||
{"mitBin.meta_lic", "by_exception.meta_lic", []string{"static"}},
|
||||
},
|
||||
expectedResolutions: []res{},
|
||||
},
|
||||
{
|
||||
name: "b_e_oonnoticerestricted",
|
||||
roots: []string{"by_exception.meta_lic"},
|
||||
edges: []annotated{
|
||||
{"by_exception.meta_lic", "mitLib.meta_lic", []string{"static"}},
|
||||
},
|
||||
expectedResolutions: []res{},
|
||||
},
|
||||
{
|
||||
name: "noticeonreciprecip",
|
||||
roots: []string{"mitBin.meta_lic"},
|
||||
edges: []annotated{
|
||||
{"mitBin.meta_lic", "mplLib.meta_lic", []string{"static"}},
|
||||
},
|
||||
expectedResolutions: []res{
|
||||
{"mitBin.meta_lic", "mplLib.meta_lic", "mplLib.meta_lic", "reciprocal"},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "reciponnoticerecip",
|
||||
roots: []string{"mplBin.meta_lic"},
|
||||
edges: []annotated{
|
||||
{"mplBin.meta_lic", "mitLib.meta_lic", []string{"static"}},
|
||||
},
|
||||
expectedResolutions: []res{
|
||||
{"mplBin.meta_lic", "mplBin.meta_lic", "mplBin.meta_lic", "reciprocal"},
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
stderr := &bytes.Buffer{}
|
||||
lg, err := toGraph(stderr, tt.roots, tt.edges)
|
||||
if err != nil {
|
||||
t.Errorf("unexpected test data error: got %w, want no error", err)
|
||||
return
|
||||
}
|
||||
expectedRs := toResolutionSet(lg, tt.expectedResolutions)
|
||||
actualRs := ResolveSourceSharing(lg)
|
||||
checkSame(actualRs, expectedRs, t)
|
||||
})
|
||||
}
|
||||
}
|
91
tools/compliance/policy/shareprivacyconflicts.go
Normal file
91
tools/compliance/policy/shareprivacyconflicts.go
Normal file
@@ -0,0 +1,91 @@
|
||||
// Copyright 2021 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 compliance
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
// SourceSharePrivacyConflict describes an individual conflict between a source-sharing
|
||||
// condition and a source privacy condition
|
||||
type SourceSharePrivacyConflict struct {
|
||||
SourceNode *TargetNode
|
||||
ShareCondition LicenseCondition
|
||||
PrivacyCondition LicenseCondition
|
||||
}
|
||||
|
||||
// Error returns a string describing the conflict.
|
||||
func (conflict SourceSharePrivacyConflict) Error() string {
|
||||
return fmt.Sprintf("%s %s from %s and must share from %s %s\n",
|
||||
conflict.SourceNode.name,
|
||||
conflict.PrivacyCondition.name, conflict.PrivacyCondition.origin.name,
|
||||
conflict.ShareCondition.name, conflict.ShareCondition.origin.name)
|
||||
}
|
||||
|
||||
// IsEqualTo returns true when `conflict` and `other` describe the same conflict.
|
||||
func (conflict SourceSharePrivacyConflict) IsEqualTo(other SourceSharePrivacyConflict) bool {
|
||||
return conflict.SourceNode.name == other.SourceNode.name &&
|
||||
conflict.ShareCondition.name == other.ShareCondition.name &&
|
||||
conflict.ShareCondition.origin.name == other.ShareCondition.origin.name &&
|
||||
conflict.PrivacyCondition.name == other.PrivacyCondition.name &&
|
||||
conflict.PrivacyCondition.origin.name == other.PrivacyCondition.origin.name
|
||||
}
|
||||
|
||||
// ConflictingSharedPrivateSource lists all of the targets where conflicting conditions to
|
||||
// share the source and to keep the source private apply to the target.
|
||||
func ConflictingSharedPrivateSource(lg *LicenseGraph) []SourceSharePrivacyConflict {
|
||||
// shareSource is the set of all source-sharing resolutions.
|
||||
shareSource := ResolveSourceSharing(lg)
|
||||
if shareSource.IsEmpty() {
|
||||
return []SourceSharePrivacyConflict{}
|
||||
}
|
||||
|
||||
// privateSource is the set of all source privacy resolutions.
|
||||
privateSource := ResolveSourcePrivacy(lg)
|
||||
if privateSource.IsEmpty() {
|
||||
return []SourceSharePrivacyConflict{}
|
||||
}
|
||||
|
||||
// combined is the combination of source-sharing and source privacy.
|
||||
combined := JoinResolutionSets(shareSource, privateSource)
|
||||
|
||||
// size is the size of the result
|
||||
size := 0
|
||||
for _, actsOn := range combined.ActsOn() {
|
||||
rl := combined.ResolutionsByActsOn(actsOn)
|
||||
size += rl.CountConditionsByName(ImpliesShared) * rl.CountConditionsByName(ImpliesPrivate)
|
||||
}
|
||||
if size == 0 {
|
||||
return []SourceSharePrivacyConflict{}
|
||||
}
|
||||
result := make([]SourceSharePrivacyConflict, 0, size)
|
||||
for _, actsOn := range combined.ActsOn() {
|
||||
rl := combined.ResolutionsByActsOn(actsOn)
|
||||
if len(rl) == 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
pconditions := rl.ByName(ImpliesPrivate).AllConditions().AsList()
|
||||
ssconditions := rl.ByName(ImpliesShared).AllConditions().AsList()
|
||||
|
||||
// report all conflicting condition combinations
|
||||
for _, p := range pconditions {
|
||||
for _, ss := range ssconditions {
|
||||
result = append(result, SourceSharePrivacyConflict{actsOn, ss, p})
|
||||
}
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
129
tools/compliance/policy/shareprivacyconflicts_test.go
Normal file
129
tools/compliance/policy/shareprivacyconflicts_test.go
Normal file
@@ -0,0 +1,129 @@
|
||||
// Copyright 2021 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 compliance
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"sort"
|
||||
"testing"
|
||||
)
|
||||
|
||||
// byConflict orders conflicts by target then share then privacy
|
||||
type byConflict []SourceSharePrivacyConflict
|
||||
|
||||
// Len returns the count of elements in the slice.
|
||||
func (l byConflict) Len() int { return len(l) }
|
||||
|
||||
// Swap rearranged 2 elements so that each occupies the other's former
|
||||
// position.
|
||||
func (l byConflict) Swap(i, j int) { l[i], l[j] = l[j], l[i] }
|
||||
|
||||
// Less returns true when the `i`th element is lexicographically less than
|
||||
// the `j`th element.
|
||||
func (l byConflict) Less(i, j int) bool {
|
||||
if l[i].SourceNode.name == l[j].SourceNode.name {
|
||||
if l[i].ShareCondition.origin.name == l[j].ShareCondition.origin.name {
|
||||
if l[i].ShareCondition.name == l[j].ShareCondition.name {
|
||||
if l[i].PrivacyCondition.origin.name == l[j].PrivacyCondition.origin.name {
|
||||
return l[i].PrivacyCondition.name < l[j].PrivacyCondition.name
|
||||
}
|
||||
return l[i].PrivacyCondition.origin.name < l[j].PrivacyCondition.origin.name
|
||||
}
|
||||
return l[i].ShareCondition.name < l[j].ShareCondition.name
|
||||
}
|
||||
return l[i].ShareCondition.origin.name < l[j].ShareCondition.origin.name
|
||||
}
|
||||
return l[i].SourceNode.name < l[j].SourceNode.name
|
||||
}
|
||||
|
||||
func TestConflictingSharedPrivateSource(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
roots []string
|
||||
edges []annotated
|
||||
expectedConflicts []confl
|
||||
}{
|
||||
{
|
||||
name: "firstparty",
|
||||
roots: []string{"apacheBin.meta_lic"},
|
||||
edges: []annotated{
|
||||
{"apacheBin.meta_lic", "apacheLib.meta_lic", []string{"static"}},
|
||||
},
|
||||
expectedConflicts: []confl{},
|
||||
},
|
||||
{
|
||||
name: "notice",
|
||||
roots: []string{"mitBin.meta_lic"},
|
||||
edges: []annotated{
|
||||
{"mitBin.meta_lic", "mitLib.meta_lic", []string{"static"}},
|
||||
},
|
||||
expectedConflicts: []confl{},
|
||||
},
|
||||
{
|
||||
name: "lgpl",
|
||||
roots: []string{"lgplBin.meta_lic"},
|
||||
edges: []annotated{
|
||||
{"lgplBin.meta_lic", "apacheLib.meta_lic", []string{"static"}},
|
||||
},
|
||||
expectedConflicts: []confl{},
|
||||
},
|
||||
{
|
||||
name: "proprietaryonrestricted",
|
||||
roots: []string{"proprietary.meta_lic"},
|
||||
edges: []annotated{
|
||||
{"proprietary.meta_lic", "gplLib.meta_lic", []string{"static"}},
|
||||
},
|
||||
expectedConflicts: []confl{
|
||||
{"proprietary.meta_lic", "gplLib.meta_lic:restricted", "proprietary.meta_lic:proprietary"},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "restrictedonproprietary",
|
||||
roots: []string{"gplBin.meta_lic"},
|
||||
edges: []annotated{
|
||||
{"gplBin.meta_lic", "proprietary.meta_lic", []string{"static"}},
|
||||
},
|
||||
expectedConflicts: []confl{
|
||||
{"proprietary.meta_lic", "gplBin.meta_lic:restricted", "proprietary.meta_lic:proprietary"},
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
stderr := &bytes.Buffer{}
|
||||
lg, err := toGraph(stderr, tt.roots, tt.edges)
|
||||
if err != nil {
|
||||
t.Errorf("unexpected test data error: got %w, want no error", err)
|
||||
return
|
||||
}
|
||||
expectedConflicts := toConflictList(lg, tt.expectedConflicts)
|
||||
actualConflicts := ConflictingSharedPrivateSource(lg)
|
||||
sort.Sort(byConflict(expectedConflicts))
|
||||
sort.Sort(byConflict(actualConflicts))
|
||||
if len(expectedConflicts) != len(actualConflicts) {
|
||||
t.Errorf("unexpected number of share/privacy conflicts: got %v with %d conflicts, want %v with %d conflicts",
|
||||
actualConflicts, len(actualConflicts), expectedConflicts, len(expectedConflicts))
|
||||
} else {
|
||||
for i := 0; i < len(actualConflicts); i++ {
|
||||
if !actualConflicts[i].IsEqualTo(expectedConflicts[i]) {
|
||||
t.Errorf("unexpected share/privacy conflict at element %d: got %q, want %q",
|
||||
i, actualConflicts[i].Error(), expectedConflicts[i].Error())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
})
|
||||
}
|
||||
}
|
54
tools/compliance/policy/shipped.go
Normal file
54
tools/compliance/policy/shipped.go
Normal file
@@ -0,0 +1,54 @@
|
||||
// Copyright 2021 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 compliance
|
||||
|
||||
// ShippedNodes returns the set of nodes in a license graph where the target or
|
||||
// a derivative work gets distributed. (caches result)
|
||||
func ShippedNodes(lg *LicenseGraph) *TargetNodeSet {
|
||||
lg.mu.Lock()
|
||||
shipped := lg.shippedNodes
|
||||
lg.mu.Unlock()
|
||||
if shipped != nil {
|
||||
return shipped
|
||||
}
|
||||
|
||||
tset := make(map[*TargetNode]bool)
|
||||
|
||||
WalkTopDown(lg, func(lg *LicenseGraph, tn *TargetNode, path TargetEdgePath) bool {
|
||||
if _, alreadyWalked := tset[tn]; alreadyWalked {
|
||||
return false
|
||||
}
|
||||
if len(path) > 0 {
|
||||
if !edgeIsDerivation(path[len(path)-1]) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
tset[tn] = true
|
||||
return true
|
||||
})
|
||||
|
||||
shipped = &TargetNodeSet{tset}
|
||||
|
||||
lg.mu.Lock()
|
||||
if lg.shippedNodes == nil {
|
||||
lg.shippedNodes = shipped
|
||||
} else {
|
||||
// if we end up with 2, release the later for garbage collection.
|
||||
shipped = lg.shippedNodes
|
||||
}
|
||||
lg.mu.Unlock()
|
||||
|
||||
return shipped
|
||||
}
|
130
tools/compliance/policy/shipped_test.go
Normal file
130
tools/compliance/policy/shipped_test.go
Normal file
@@ -0,0 +1,130 @@
|
||||
// Copyright 2021 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 compliance
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"sort"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestShippedNodes(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
roots []string
|
||||
edges []annotated
|
||||
expectedNodes []string
|
||||
}{
|
||||
{
|
||||
name: "singleton",
|
||||
roots: []string{"apacheLib.meta_lic"},
|
||||
edges: []annotated{},
|
||||
expectedNodes: []string{"apacheLib.meta_lic"},
|
||||
},
|
||||
{
|
||||
name: "simplebinary",
|
||||
roots: []string{"apacheBin.meta_lic"},
|
||||
edges: []annotated{
|
||||
{"apacheBin.meta_lic", "apacheLib.meta_lic", []string{"static"}},
|
||||
},
|
||||
expectedNodes: []string{"apacheBin.meta_lic", "apacheLib.meta_lic"},
|
||||
},
|
||||
{
|
||||
name: "simpledynamic",
|
||||
roots: []string{"apacheBin.meta_lic"},
|
||||
edges: []annotated{
|
||||
{"apacheBin.meta_lic", "lgplLib.meta_lic", []string{"dynamic"}},
|
||||
},
|
||||
expectedNodes: []string{"apacheBin.meta_lic"},
|
||||
},
|
||||
{
|
||||
name: "container",
|
||||
roots: []string{"apacheContainer.meta_lic"},
|
||||
edges: []annotated{
|
||||
{"apacheContainer.meta_lic", "apacheLib.meta_lic", []string{"static"}},
|
||||
{"apacheContainer.meta_lic", "gplLib.meta_lic", []string{"static"}},
|
||||
},
|
||||
expectedNodes: []string{
|
||||
"apacheContainer.meta_lic",
|
||||
"apacheLib.meta_lic",
|
||||
"gplLib.meta_lic",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "binary",
|
||||
roots: []string{"apacheBin.meta_lic"},
|
||||
edges: []annotated{
|
||||
{"apacheBin.meta_lic", "apacheLib.meta_lic", []string{"static"}},
|
||||
{"apacheBin.meta_lic", "gplLib.meta_lic", []string{"static"}},
|
||||
},
|
||||
expectedNodes: []string{
|
||||
"apacheBin.meta_lic",
|
||||
"apacheLib.meta_lic",
|
||||
"gplLib.meta_lic",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "binarydynamic",
|
||||
roots: []string{"apacheBin.meta_lic"},
|
||||
edges: []annotated{
|
||||
{"apacheBin.meta_lic", "apacheLib.meta_lic", []string{"static"}},
|
||||
{"apacheBin.meta_lic", "gplLib.meta_lic", []string{"dynamic"}},
|
||||
},
|
||||
expectedNodes: []string{
|
||||
"apacheBin.meta_lic",
|
||||
"apacheLib.meta_lic",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "containerdeep",
|
||||
roots: []string{"apacheContainer.meta_lic"},
|
||||
edges: []annotated{
|
||||
{"apacheContainer.meta_lic", "apacheBin.meta_lic", []string{"static"}},
|
||||
{"apacheBin.meta_lic", "apacheLib.meta_lic", []string{"static"}},
|
||||
{"apacheLib.meta_lic", "gplLib.meta_lic", []string{"dynamic"}},
|
||||
},
|
||||
expectedNodes: []string{
|
||||
"apacheContainer.meta_lic",
|
||||
"apacheBin.meta_lic",
|
||||
"apacheLib.meta_lic",
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
stderr := &bytes.Buffer{}
|
||||
lg, err := toGraph(stderr, tt.roots, tt.edges)
|
||||
if err != nil {
|
||||
t.Errorf("unexpected test data error: got %w, want no error", err)
|
||||
return
|
||||
}
|
||||
expectedNodes := append([]string{}, tt.expectedNodes...)
|
||||
actualNodes := ShippedNodes(lg).Names()
|
||||
sort.Strings(expectedNodes)
|
||||
sort.Strings(actualNodes)
|
||||
if len(expectedNodes) != len(actualNodes) {
|
||||
t.Errorf("unexpected number of shipped nodes: got %v with %d nodes, want %v with %d nodes",
|
||||
actualNodes, len(actualNodes), expectedNodes, len(expectedNodes))
|
||||
return
|
||||
}
|
||||
for i := 0; i < len(actualNodes); i++ {
|
||||
if expectedNodes[i] != actualNodes[i] {
|
||||
t.Errorf("unexpected node at index %d: got %q in %v, want %q in %v",
|
||||
i, actualNodes[i], actualNodes, expectedNodes[i], expectedNodes)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
76
tools/compliance/policy/walk.go
Normal file
76
tools/compliance/policy/walk.go
Normal file
@@ -0,0 +1,76 @@
|
||||
// Copyright 2021 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 compliance
|
||||
|
||||
// VisitNode is called for each root and for each walked dependency node by
|
||||
// WalkTopDown. When VisitNode returns true, WalkTopDown will proceed to walk
|
||||
// down the dependences of the node
|
||||
type VisitNode func(*LicenseGraph, *TargetNode, TargetEdgePath) bool
|
||||
|
||||
// WalkTopDown does a top-down walk of `lg` calling `visit` and descending
|
||||
// into depenencies when `visit` returns true.
|
||||
func WalkTopDown(lg *LicenseGraph, visit VisitNode) {
|
||||
path := NewTargetEdgePath(32)
|
||||
|
||||
// must be indexed for fast lookup
|
||||
lg.indexForward()
|
||||
|
||||
var walk func(f string)
|
||||
walk = func(f string) {
|
||||
visitChildren := visit(lg, lg.targets[f], *path)
|
||||
if !visitChildren {
|
||||
return
|
||||
}
|
||||
for _, edge := range lg.index[f] {
|
||||
path.Push(TargetEdge{lg, edge})
|
||||
walk(edge.dependency)
|
||||
path.Pop()
|
||||
}
|
||||
}
|
||||
|
||||
for _, r := range lg.rootFiles {
|
||||
path.Clear()
|
||||
walk(r)
|
||||
}
|
||||
}
|
||||
|
||||
// WalkResolutionsForCondition performs a top-down walk of the LicenseGraph
|
||||
// resolving all distributed works for condition `names`.
|
||||
func WalkResolutionsForCondition(lg *LicenseGraph, rs *ResolutionSet, names ConditionNames) *ResolutionSet {
|
||||
shipped := ShippedNodes(lg)
|
||||
|
||||
// rmap maps 'attachesTo' targets to the `actsOn` targets and applicable conditions
|
||||
//
|
||||
// rmap is the resulting ResolutionSet
|
||||
rmap := make(map[*TargetNode]actionSet)
|
||||
|
||||
WalkTopDown(lg, func(lg *LicenseGraph, tn *TargetNode, _ TargetEdgePath) bool {
|
||||
if _, ok := rmap[tn]; ok {
|
||||
return false
|
||||
}
|
||||
if !shipped.Contains(tn) {
|
||||
return false
|
||||
}
|
||||
if as, ok := rs.resolutions[tn]; ok {
|
||||
fas := as.byActsOn(shipped).byName(names)
|
||||
if !fas.isEmpty() {
|
||||
rmap[tn] = fas
|
||||
}
|
||||
}
|
||||
return tn.IsContainer() // descend into containers
|
||||
})
|
||||
|
||||
return &ResolutionSet{rmap}
|
||||
}
|
629
tools/compliance/policy/walk_test.go
Normal file
629
tools/compliance/policy/walk_test.go
Normal file
@@ -0,0 +1,629 @@
|
||||
// Copyright 2021 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 compliance
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestWalkResolutionsForCondition(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
condition ConditionNames
|
||||
roots []string
|
||||
edges []annotated
|
||||
expectedResolutions []res
|
||||
}{
|
||||
{
|
||||
name: "firstparty",
|
||||
condition: ImpliesNotice,
|
||||
roots: []string{"apacheBin.meta_lic"},
|
||||
edges: []annotated{
|
||||
{"apacheBin.meta_lic", "apacheLib.meta_lic", []string{"static"}},
|
||||
},
|
||||
expectedResolutions: []res{
|
||||
{"apacheBin.meta_lic", "apacheBin.meta_lic", "apacheBin.meta_lic", "notice"},
|
||||
{"apacheBin.meta_lic", "apacheLib.meta_lic", "apacheLib.meta_lic", "notice"},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "notice",
|
||||
condition: ImpliesNotice,
|
||||
roots: []string{"mitBin.meta_lic"},
|
||||
edges: []annotated{
|
||||
{"mitBin.meta_lic", "mitLib.meta_lic", []string{"static"}},
|
||||
},
|
||||
expectedResolutions: []res{
|
||||
{"mitBin.meta_lic", "mitBin.meta_lic", "mitBin.meta_lic", "notice"},
|
||||
{"mitBin.meta_lic", "mitLib.meta_lic", "mitLib.meta_lic", "notice"},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "fponlgplnotice",
|
||||
condition: ImpliesNotice,
|
||||
roots: []string{"apacheBin.meta_lic"},
|
||||
edges: []annotated{
|
||||
{"apacheBin.meta_lic", "lgplLib.meta_lic", []string{"static"}},
|
||||
},
|
||||
expectedResolutions: []res{
|
||||
{"apacheBin.meta_lic", "apacheBin.meta_lic", "apacheBin.meta_lic", "notice"},
|
||||
{"apacheBin.meta_lic", "apacheBin.meta_lic", "lgplLib.meta_lic", "restricted"},
|
||||
{"apacheBin.meta_lic", "lgplLib.meta_lic", "lgplLib.meta_lic", "restricted"},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "fponlgpldynamicnotice",
|
||||
condition: ImpliesNotice,
|
||||
roots: []string{"apacheBin.meta_lic"},
|
||||
edges: []annotated{
|
||||
{"apacheBin.meta_lic", "lgplLib.meta_lic", []string{"dynamic"}},
|
||||
},
|
||||
expectedResolutions: []res{
|
||||
{"apacheBin.meta_lic", "apacheBin.meta_lic", "apacheBin.meta_lic", "notice"},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "independentmodulenotice",
|
||||
condition: ImpliesNotice,
|
||||
roots: []string{"apacheBin.meta_lic"},
|
||||
edges: []annotated{
|
||||
{"apacheBin.meta_lic", "gplWithClasspathException.meta_lic", []string{"dynamic"}},
|
||||
},
|
||||
expectedResolutions: []res{
|
||||
{"apacheBin.meta_lic", "apacheBin.meta_lic", "apacheBin.meta_lic", "notice"},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "independentmodulerestricted",
|
||||
condition: ImpliesRestricted,
|
||||
roots: []string{"apacheBin.meta_lic"},
|
||||
edges: []annotated{
|
||||
{"apacheBin.meta_lic", "gplWithClasspathException.meta_lic", []string{"dynamic"}},
|
||||
},
|
||||
expectedResolutions: []res{},
|
||||
},
|
||||
{
|
||||
name: "independentmodulestaticnotice",
|
||||
condition: ImpliesNotice,
|
||||
roots: []string{"apacheBin.meta_lic"},
|
||||
edges: []annotated{
|
||||
{"apacheBin.meta_lic", "gplWithClasspathException.meta_lic", []string{"static"}},
|
||||
},
|
||||
expectedResolutions: []res{
|
||||
{"apacheBin.meta_lic", "apacheBin.meta_lic", "apacheBin.meta_lic", "notice"},
|
||||
{"apacheBin.meta_lic", "apacheBin.meta_lic", "gplWithClasspathException.meta_lic", "restricted"},
|
||||
{"apacheBin.meta_lic", "gplWithClasspathException.meta_lic", "gplWithClasspathException.meta_lic", "restricted"},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "independentmodulestaticrestricted",
|
||||
condition: ImpliesRestricted,
|
||||
roots: []string{"apacheBin.meta_lic"},
|
||||
edges: []annotated{
|
||||
{"apacheBin.meta_lic", "gplWithClasspathException.meta_lic", []string{"static"}},
|
||||
},
|
||||
expectedResolutions: []res{
|
||||
{"apacheBin.meta_lic", "apacheBin.meta_lic", "gplWithClasspathException.meta_lic", "restricted"},
|
||||
{"apacheBin.meta_lic", "gplWithClasspathException.meta_lic", "gplWithClasspathException.meta_lic", "restricted"},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "dependentmodulenotice",
|
||||
condition: ImpliesNotice,
|
||||
roots: []string{"dependentModule.meta_lic"},
|
||||
edges: []annotated{
|
||||
{"dependentModule.meta_lic", "gplWithClasspathException.meta_lic", []string{"dynamic"}},
|
||||
},
|
||||
expectedResolutions: []res{
|
||||
{"dependentModule.meta_lic", "dependentModule.meta_lic", "dependentModule.meta_lic", "notice"},
|
||||
{"dependentModule.meta_lic", "dependentModule.meta_lic", "gplWithClasspathException.meta_lic", "restricted"},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "dependentmodulerestricted",
|
||||
condition: ImpliesRestricted,
|
||||
roots: []string{"dependentModule.meta_lic"},
|
||||
edges: []annotated{
|
||||
{"dependentModule.meta_lic", "gplWithClasspathException.meta_lic", []string{"dynamic"}},
|
||||
},
|
||||
expectedResolutions: []res{
|
||||
{"dependentModule.meta_lic", "dependentModule.meta_lic", "gplWithClasspathException.meta_lic", "restricted"},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "lgplonfpnotice",
|
||||
condition: ImpliesNotice,
|
||||
roots: []string{"lgplBin.meta_lic"},
|
||||
edges: []annotated{
|
||||
{"lgplBin.meta_lic", "apacheLib.meta_lic", []string{"static"}},
|
||||
},
|
||||
expectedResolutions: []res{
|
||||
{"lgplBin.meta_lic", "lgplBin.meta_lic", "lgplBin.meta_lic", "restricted"},
|
||||
{"lgplBin.meta_lic", "apacheLib.meta_lic", "apacheLib.meta_lic", "notice"},
|
||||
{"lgplBin.meta_lic", "apacheLib.meta_lic", "lgplBin.meta_lic", "restricted"},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "lgplonfprestricted",
|
||||
condition: ImpliesRestricted,
|
||||
roots: []string{"lgplBin.meta_lic"},
|
||||
edges: []annotated{
|
||||
{"lgplBin.meta_lic", "apacheLib.meta_lic", []string{"static"}},
|
||||
},
|
||||
expectedResolutions: []res{
|
||||
{"lgplBin.meta_lic", "lgplBin.meta_lic", "lgplBin.meta_lic", "restricted"},
|
||||
{"lgplBin.meta_lic", "apacheLib.meta_lic", "lgplBin.meta_lic", "restricted"},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "lgplonfpdynamicnotice",
|
||||
condition: ImpliesNotice,
|
||||
roots: []string{"lgplBin.meta_lic"},
|
||||
edges: []annotated{
|
||||
{"lgplBin.meta_lic", "apacheLib.meta_lic", []string{"dynamic"}},
|
||||
},
|
||||
expectedResolutions: []res{
|
||||
{"lgplBin.meta_lic", "lgplBin.meta_lic", "lgplBin.meta_lic", "restricted"},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "lgplonfpdynamicrestricted",
|
||||
condition: ImpliesRestricted,
|
||||
roots: []string{"lgplBin.meta_lic"},
|
||||
edges: []annotated{
|
||||
{"lgplBin.meta_lic", "apacheLib.meta_lic", []string{"dynamic"}},
|
||||
},
|
||||
expectedResolutions: []res{
|
||||
{"lgplBin.meta_lic", "lgplBin.meta_lic", "lgplBin.meta_lic", "restricted"},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "gplonfpnotice",
|
||||
condition: ImpliesNotice,
|
||||
roots: []string{"gplBin.meta_lic"},
|
||||
edges: []annotated{
|
||||
{"gplBin.meta_lic", "apacheLib.meta_lic", []string{"static"}},
|
||||
},
|
||||
expectedResolutions: []res{
|
||||
{"gplBin.meta_lic", "gplBin.meta_lic", "gplBin.meta_lic", "restricted"},
|
||||
{"gplBin.meta_lic", "apacheLib.meta_lic", "apacheLib.meta_lic", "notice"},
|
||||
{"gplBin.meta_lic", "apacheLib.meta_lic", "gplBin.meta_lic", "restricted"},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "gplonfprestricted",
|
||||
condition: ImpliesRestricted,
|
||||
roots: []string{"gplBin.meta_lic"},
|
||||
edges: []annotated{
|
||||
{"gplBin.meta_lic", "apacheLib.meta_lic", []string{"static"}},
|
||||
},
|
||||
expectedResolutions: []res{
|
||||
{"gplBin.meta_lic", "gplBin.meta_lic", "gplBin.meta_lic", "restricted"},
|
||||
{"gplBin.meta_lic", "apacheLib.meta_lic", "gplBin.meta_lic", "restricted"},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "gplcontainernotice",
|
||||
condition: ImpliesNotice,
|
||||
roots: []string{"gplContainer.meta_lic"},
|
||||
edges: []annotated{
|
||||
{"gplContainer.meta_lic", "apacheLib.meta_lic", []string{"static"}},
|
||||
},
|
||||
expectedResolutions: []res{
|
||||
{"gplContainer.meta_lic", "gplContainer.meta_lic", "gplContainer.meta_lic", "restricted"},
|
||||
{"gplContainer.meta_lic", "apacheLib.meta_lic", "apacheLib.meta_lic", "notice"},
|
||||
{"gplContainer.meta_lic", "apacheLib.meta_lic", "gplContainer.meta_lic", "restricted"},
|
||||
{"apacheLib.meta_lic", "apacheLib.meta_lic", "apacheLib.meta_lic", "notice"},
|
||||
{"apacheLib.meta_lic", "apacheLib.meta_lic", "gplContainer.meta_lic", "restricted"},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "gplcontainerrestricted",
|
||||
condition: ImpliesRestricted,
|
||||
roots: []string{"gplContainer.meta_lic"},
|
||||
edges: []annotated{
|
||||
{"gplContainer.meta_lic", "apacheLib.meta_lic", []string{"static"}},
|
||||
},
|
||||
expectedResolutions: []res{
|
||||
{"gplContainer.meta_lic", "gplContainer.meta_lic", "gplContainer.meta_lic", "restricted"},
|
||||
{"gplContainer.meta_lic", "apacheLib.meta_lic", "gplContainer.meta_lic", "restricted"},
|
||||
{"apacheLib.meta_lic", "apacheLib.meta_lic", "gplContainer.meta_lic", "restricted"},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "gploncontainernotice",
|
||||
condition: ImpliesNotice,
|
||||
roots: []string{"apacheContainer.meta_lic"},
|
||||
edges: []annotated{
|
||||
{"apacheContainer.meta_lic", "apacheLib.meta_lic", []string{"static"}},
|
||||
{"apacheContainer.meta_lic", "gplLib.meta_lic", []string{"static"}},
|
||||
},
|
||||
expectedResolutions: []res{
|
||||
{"apacheContainer.meta_lic", "apacheContainer.meta_lic", "apacheContainer.meta_lic", "notice"},
|
||||
{"apacheContainer.meta_lic", "apacheContainer.meta_lic", "gplLib.meta_lic", "restricted"},
|
||||
{"apacheContainer.meta_lic", "apacheLib.meta_lic", "apacheLib.meta_lic", "notice"},
|
||||
{"apacheContainer.meta_lic", "gplLib.meta_lic", "gplLib.meta_lic", "restricted"},
|
||||
{"apacheLib.meta_lic", "apacheLib.meta_lic", "apacheLib.meta_lic", "notice"},
|
||||
{"gplLib.meta_lic", "gplLib.meta_lic", "gplLib.meta_lic", "restricted"},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "gploncontainerrestricted",
|
||||
condition: ImpliesRestricted,
|
||||
roots: []string{"apacheContainer.meta_lic"},
|
||||
edges: []annotated{
|
||||
{"apacheContainer.meta_lic", "apacheLib.meta_lic", []string{"static"}},
|
||||
{"apacheContainer.meta_lic", "gplLib.meta_lic", []string{"static"}},
|
||||
},
|
||||
expectedResolutions: []res{
|
||||
{"apacheContainer.meta_lic", "apacheContainer.meta_lic", "gplLib.meta_lic", "restricted"},
|
||||
{"apacheContainer.meta_lic", "gplLib.meta_lic", "gplLib.meta_lic", "restricted"},
|
||||
{"gplLib.meta_lic", "gplLib.meta_lic", "gplLib.meta_lic", "restricted"},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "gplonbinnotice",
|
||||
condition: ImpliesNotice,
|
||||
roots: []string{"apacheBin.meta_lic"},
|
||||
edges: []annotated{
|
||||
{"apacheBin.meta_lic", "apacheLib.meta_lic", []string{"static"}},
|
||||
{"apacheBin.meta_lic", "gplLib.meta_lic", []string{"static"}},
|
||||
},
|
||||
expectedResolutions: []res{
|
||||
{"apacheBin.meta_lic", "apacheBin.meta_lic", "apacheBin.meta_lic", "notice"},
|
||||
{"apacheBin.meta_lic", "apacheBin.meta_lic", "gplLib.meta_lic", "restricted"},
|
||||
{"apacheBin.meta_lic", "apacheLib.meta_lic", "apacheLib.meta_lic", "notice"},
|
||||
{"apacheBin.meta_lic", "apacheLib.meta_lic", "gplLib.meta_lic", "restricted"},
|
||||
{"apacheBin.meta_lic", "gplLib.meta_lic", "gplLib.meta_lic", "restricted"},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "gplonbinrestricted",
|
||||
condition: ImpliesRestricted,
|
||||
roots: []string{"apacheBin.meta_lic"},
|
||||
edges: []annotated{
|
||||
{"apacheBin.meta_lic", "apacheLib.meta_lic", []string{"static"}},
|
||||
{"apacheBin.meta_lic", "gplLib.meta_lic", []string{"static"}},
|
||||
},
|
||||
expectedResolutions: []res{
|
||||
{"apacheBin.meta_lic", "apacheBin.meta_lic", "gplLib.meta_lic", "restricted"},
|
||||
{"apacheBin.meta_lic", "apacheLib.meta_lic", "gplLib.meta_lic", "restricted"},
|
||||
{"apacheBin.meta_lic", "gplLib.meta_lic", "gplLib.meta_lic", "restricted"},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "gplonfpdynamicnotice",
|
||||
condition: ImpliesNotice,
|
||||
roots: []string{"gplBin.meta_lic"},
|
||||
edges: []annotated{
|
||||
{"gplBin.meta_lic", "apacheLib.meta_lic", []string{"dynamic"}},
|
||||
},
|
||||
expectedResolutions: []res{
|
||||
{"gplBin.meta_lic", "gplBin.meta_lic", "gplBin.meta_lic", "restricted"},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "gplonfpdynamicrestricted",
|
||||
condition: ImpliesRestricted,
|
||||
roots: []string{"gplBin.meta_lic"},
|
||||
edges: []annotated{
|
||||
{"gplBin.meta_lic", "apacheLib.meta_lic", []string{"dynamic"}},
|
||||
},
|
||||
expectedResolutions: []res{
|
||||
{"gplBin.meta_lic", "gplBin.meta_lic", "gplBin.meta_lic", "restricted"},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "gplonfpdynamicrestrictedshipped",
|
||||
condition: ImpliesRestricted,
|
||||
roots: []string{"gplBin.meta_lic", "apacheLib.meta_lic"},
|
||||
edges: []annotated{
|
||||
{"gplBin.meta_lic", "apacheLib.meta_lic", []string{"dynamic"}},
|
||||
},
|
||||
expectedResolutions: []res{
|
||||
{"gplBin.meta_lic", "gplBin.meta_lic", "gplBin.meta_lic", "restricted"},
|
||||
{"gplBin.meta_lic", "apacheLib.meta_lic", "gplBin.meta_lic", "restricted"},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "independentmodulereversenotice",
|
||||
condition: ImpliesNotice,
|
||||
roots: []string{"gplWithClasspathException.meta_lic"},
|
||||
edges: []annotated{
|
||||
{"gplWithClasspathException.meta_lic", "apacheBin.meta_lic", []string{"dynamic"}},
|
||||
},
|
||||
expectedResolutions: []res{
|
||||
{"gplWithClasspathException.meta_lic", "gplWithClasspathException.meta_lic", "gplWithClasspathException.meta_lic", "restricted"},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "independentmodulereverserestricted",
|
||||
condition: ImpliesRestricted,
|
||||
roots: []string{"gplWithClasspathException.meta_lic"},
|
||||
edges: []annotated{
|
||||
{"gplWithClasspathException.meta_lic", "apacheBin.meta_lic", []string{"dynamic"}},
|
||||
},
|
||||
expectedResolutions: []res{
|
||||
{"gplWithClasspathException.meta_lic", "gplWithClasspathException.meta_lic", "gplWithClasspathException.meta_lic", "restricted"},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "independentmodulereverserestrictedshipped",
|
||||
condition: ImpliesRestricted,
|
||||
roots: []string{"gplWithClasspathException.meta_lic", "apacheBin.meta_lic"},
|
||||
edges: []annotated{
|
||||
{"gplWithClasspathException.meta_lic", "apacheBin.meta_lic", []string{"dynamic"}},
|
||||
},
|
||||
expectedResolutions: []res{
|
||||
{"gplWithClasspathException.meta_lic", "gplWithClasspathException.meta_lic", "gplWithClasspathException.meta_lic", "restricted"},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "independentmodulereversestaticnotice",
|
||||
condition: ImpliesNotice,
|
||||
roots: []string{"gplWithClasspathException.meta_lic"},
|
||||
edges: []annotated{
|
||||
{"gplWithClasspathException.meta_lic", "apacheBin.meta_lic", []string{"static"}},
|
||||
},
|
||||
expectedResolutions: []res{
|
||||
{"gplWithClasspathException.meta_lic", "gplWithClasspathException.meta_lic", "gplWithClasspathException.meta_lic", "restricted"},
|
||||
{"gplWithClasspathException.meta_lic", "apacheBin.meta_lic", "apacheBin.meta_lic", "notice"},
|
||||
{"gplWithClasspathException.meta_lic", "apacheBin.meta_lic", "gplWithClasspathException.meta_lic", "restricted"},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "independentmodulereversestaticrestricted",
|
||||
condition: ImpliesRestricted,
|
||||
roots: []string{"gplWithClasspathException.meta_lic"},
|
||||
edges: []annotated{
|
||||
{"gplWithClasspathException.meta_lic", "apacheBin.meta_lic", []string{"static"}},
|
||||
},
|
||||
expectedResolutions: []res{
|
||||
{"gplWithClasspathException.meta_lic", "gplWithClasspathException.meta_lic", "gplWithClasspathException.meta_lic", "restricted"},
|
||||
{"gplWithClasspathException.meta_lic", "apacheBin.meta_lic", "gplWithClasspathException.meta_lic", "restricted"},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "dependentmodulereversenotice",
|
||||
condition: ImpliesNotice,
|
||||
roots: []string{"gplWithClasspathException.meta_lic"},
|
||||
edges: []annotated{
|
||||
{"gplWithClasspathException.meta_lic", "dependentModule.meta_lic", []string{"dynamic"}},
|
||||
},
|
||||
expectedResolutions: []res{
|
||||
{"gplWithClasspathException.meta_lic", "gplWithClasspathException.meta_lic", "gplWithClasspathException.meta_lic", "restricted"},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "dependentmodulereverserestricted",
|
||||
condition: ImpliesRestricted,
|
||||
roots: []string{"gplWithClasspathException.meta_lic"},
|
||||
edges: []annotated{
|
||||
{"gplWithClasspathException.meta_lic", "dependentModule.meta_lic", []string{"dynamic"}},
|
||||
},
|
||||
expectedResolutions: []res{
|
||||
{"gplWithClasspathException.meta_lic", "gplWithClasspathException.meta_lic", "gplWithClasspathException.meta_lic", "restricted"},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "dependentmodulereverserestrictedshipped",
|
||||
condition: ImpliesRestricted,
|
||||
roots: []string{"gplWithClasspathException.meta_lic", "dependentModule.meta_lic"},
|
||||
edges: []annotated{
|
||||
{"gplWithClasspathException.meta_lic", "dependentModule.meta_lic", []string{"dynamic"}},
|
||||
},
|
||||
expectedResolutions: []res{
|
||||
{"gplWithClasspathException.meta_lic", "gplWithClasspathException.meta_lic", "gplWithClasspathException.meta_lic", "restricted"},
|
||||
{"gplWithClasspathException.meta_lic", "dependentModule.meta_lic", "gplWithClasspathException.meta_lic", "restricted"},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "ponrnotice",
|
||||
condition: ImpliesNotice,
|
||||
roots: []string{"proprietary.meta_lic"},
|
||||
edges: []annotated{
|
||||
{"proprietary.meta_lic", "gplLib.meta_lic", []string{"static"}},
|
||||
},
|
||||
expectedResolutions: []res{
|
||||
{"proprietary.meta_lic", "proprietary.meta_lic", "proprietary.meta_lic", "proprietary"},
|
||||
{"proprietary.meta_lic", "proprietary.meta_lic", "gplLib.meta_lic", "restricted"},
|
||||
{"proprietary.meta_lic", "gplLib.meta_lic", "gplLib.meta_lic", "restricted"},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "ponrrestricted",
|
||||
condition: ImpliesRestricted,
|
||||
roots: []string{"proprietary.meta_lic"},
|
||||
edges: []annotated{
|
||||
{"proprietary.meta_lic", "gplLib.meta_lic", []string{"static"}},
|
||||
},
|
||||
expectedResolutions: []res{
|
||||
{"proprietary.meta_lic", "gplLib.meta_lic", "gplLib.meta_lic", "restricted"},
|
||||
{"proprietary.meta_lic", "proprietary.meta_lic", "gplLib.meta_lic", "restricted"},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "ponrproprietary",
|
||||
condition: ImpliesProprietary,
|
||||
roots: []string{"proprietary.meta_lic"},
|
||||
edges: []annotated{
|
||||
{"proprietary.meta_lic", "gplLib.meta_lic", []string{"static"}},
|
||||
},
|
||||
expectedResolutions: []res{
|
||||
{"proprietary.meta_lic", "proprietary.meta_lic", "proprietary.meta_lic", "proprietary"},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "ronpnotice",
|
||||
condition: ImpliesNotice,
|
||||
roots: []string{"gplBin.meta_lic"},
|
||||
edges: []annotated{
|
||||
{"gplBin.meta_lic", "proprietary.meta_lic", []string{"static"}},
|
||||
},
|
||||
expectedResolutions: []res{
|
||||
{"gplBin.meta_lic", "gplBin.meta_lic", "gplBin.meta_lic", "restricted"},
|
||||
{"gplBin.meta_lic", "proprietary.meta_lic", "proprietary.meta_lic", "proprietary"},
|
||||
{"gplBin.meta_lic", "proprietary.meta_lic", "gplBin.meta_lic", "restricted"},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "ronprestricted",
|
||||
condition: ImpliesRestricted,
|
||||
roots: []string{"gplBin.meta_lic"},
|
||||
edges: []annotated{
|
||||
{"gplBin.meta_lic", "proprietary.meta_lic", []string{"static"}},
|
||||
},
|
||||
expectedResolutions: []res{
|
||||
{"gplBin.meta_lic", "gplBin.meta_lic", "gplBin.meta_lic", "restricted"},
|
||||
{"gplBin.meta_lic", "proprietary.meta_lic", "gplBin.meta_lic", "restricted"},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "ronpproprietary",
|
||||
condition: ImpliesProprietary,
|
||||
roots: []string{"gplBin.meta_lic"},
|
||||
edges: []annotated{
|
||||
{"gplBin.meta_lic", "proprietary.meta_lic", []string{"static"}},
|
||||
},
|
||||
expectedResolutions: []res{
|
||||
{"gplBin.meta_lic", "proprietary.meta_lic", "proprietary.meta_lic", "proprietary"},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "noticeonb_e_onotice",
|
||||
condition: ImpliesNotice,
|
||||
roots: []string{"mitBin.meta_lic"},
|
||||
edges: []annotated{
|
||||
{"mitBin.meta_lic", "by_exception.meta_lic", []string{"static"}},
|
||||
},
|
||||
expectedResolutions: []res{
|
||||
{"mitBin.meta_lic", "mitBin.meta_lic", "mitBin.meta_lic", "notice"},
|
||||
{"mitBin.meta_lic", "by_exception.meta_lic", "by_exception.meta_lic", "by_exception_only"},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "noticeonb_e_orestricted",
|
||||
condition: ImpliesRestricted,
|
||||
roots: []string{"mitBin.meta_lic"},
|
||||
edges: []annotated{
|
||||
{"mitBin.meta_lic", "by_exception.meta_lic", []string{"static"}},
|
||||
},
|
||||
expectedResolutions: []res{},
|
||||
},
|
||||
{
|
||||
name: "noticeonb_e_ob_e_o",
|
||||
condition: ImpliesByExceptionOnly,
|
||||
roots: []string{"mitBin.meta_lic"},
|
||||
edges: []annotated{
|
||||
{"mitBin.meta_lic", "by_exception.meta_lic", []string{"static"}},
|
||||
},
|
||||
expectedResolutions: []res{
|
||||
{"mitBin.meta_lic", "by_exception.meta_lic", "by_exception.meta_lic", "by_exception_only"},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "b_e_oonnoticenotice",
|
||||
condition: ImpliesNotice,
|
||||
roots: []string{"by_exception.meta_lic"},
|
||||
edges: []annotated{
|
||||
{"by_exception.meta_lic", "mitLib.meta_lic", []string{"static"}},
|
||||
},
|
||||
expectedResolutions: []res{
|
||||
{"by_exception.meta_lic", "by_exception.meta_lic", "by_exception.meta_lic", "by_exception_only"},
|
||||
{"by_exception.meta_lic", "mitLib.meta_lic", "mitLib.meta_lic", "notice"},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "b_e_oonnoticerestricted",
|
||||
condition: ImpliesRestricted,
|
||||
roots: []string{"by_exception.meta_lic"},
|
||||
edges: []annotated{
|
||||
{"by_exception.meta_lic", "mitLib.meta_lic", []string{"static"}},
|
||||
},
|
||||
expectedResolutions: []res{},
|
||||
},
|
||||
{
|
||||
name: "b_e_oonnoticeb_e_o",
|
||||
condition: ImpliesByExceptionOnly,
|
||||
roots: []string{"by_exception.meta_lic"},
|
||||
edges: []annotated{
|
||||
{"by_exception.meta_lic", "mitLib.meta_lic", []string{"static"}},
|
||||
},
|
||||
expectedResolutions: []res{
|
||||
{"by_exception.meta_lic", "by_exception.meta_lic", "by_exception.meta_lic", "by_exception_only"},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "noticeonrecipnotice",
|
||||
condition: ImpliesNotice,
|
||||
roots: []string{"mitBin.meta_lic"},
|
||||
edges: []annotated{
|
||||
{"mitBin.meta_lic", "mplLib.meta_lic", []string{"static"}},
|
||||
},
|
||||
expectedResolutions: []res{
|
||||
{"mitBin.meta_lic", "mitBin.meta_lic", "mitBin.meta_lic", "notice"},
|
||||
{"mitBin.meta_lic", "mplLib.meta_lic", "mplLib.meta_lic", "reciprocal"},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "noticeonreciprecip",
|
||||
condition: ImpliesReciprocal,
|
||||
roots: []string{"mitBin.meta_lic"},
|
||||
edges: []annotated{
|
||||
{"mitBin.meta_lic", "mplLib.meta_lic", []string{"static"}},
|
||||
},
|
||||
expectedResolutions: []res{
|
||||
{"mitBin.meta_lic", "mplLib.meta_lic", "mplLib.meta_lic", "reciprocal"},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "reciponnoticenotice",
|
||||
condition: ImpliesNotice,
|
||||
roots: []string{"mplBin.meta_lic"},
|
||||
edges: []annotated{
|
||||
{"mplBin.meta_lic", "mitLib.meta_lic", []string{"static"}},
|
||||
},
|
||||
expectedResolutions: []res{
|
||||
{"mplBin.meta_lic", "mplBin.meta_lic", "mplBin.meta_lic", "reciprocal"},
|
||||
{"mplBin.meta_lic", "mitLib.meta_lic", "mitLib.meta_lic", "notice"},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "reciponnoticerecip",
|
||||
condition: ImpliesReciprocal,
|
||||
roots: []string{"mplBin.meta_lic"},
|
||||
edges: []annotated{
|
||||
{"mplBin.meta_lic", "mitLib.meta_lic", []string{"static"}},
|
||||
},
|
||||
expectedResolutions: []res{
|
||||
{"mplBin.meta_lic", "mplBin.meta_lic", "mplBin.meta_lic", "reciprocal"},
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
stderr := &bytes.Buffer{}
|
||||
lg, err := toGraph(stderr, tt.roots, tt.edges)
|
||||
if err != nil {
|
||||
t.Errorf("unexpected test data error: got %w, want no error", err)
|
||||
return
|
||||
}
|
||||
expectedRs := toResolutionSet(lg, tt.expectedResolutions)
|
||||
actualRs := WalkResolutionsForCondition(lg, ResolveTopDownConditions(lg), tt.condition)
|
||||
checkSame(actualRs, expectedRs, t)
|
||||
})
|
||||
}
|
||||
}
|
@@ -125,10 +125,10 @@ func TestResolutionSet_AttachedToTarget(t *testing.T) {
|
||||
|
||||
rsShare := toResolutionSet(lg, share)
|
||||
|
||||
if rsShare.AttachedToTarget(newTestNode(lg, "binc")) {
|
||||
if rsShare.AttachesToTarget(newTestNode(lg, "binc")) {
|
||||
t.Errorf("unexpected AttachedToTarget(\"binc\"): got true, want false")
|
||||
}
|
||||
if !rsShare.AttachedToTarget(newTestNode(lg, "image")) {
|
||||
if !rsShare.AttachesToTarget(newTestNode(lg, "image")) {
|
||||
t.Errorf("unexpected AttachedToTarget(\"image\"): got false want true")
|
||||
}
|
||||
}
|
||||
|
@@ -30,6 +30,85 @@ const (
|
||||
license_kinds: "SPDX-license-identifier-Apache-2.0"
|
||||
license_conditions: "notice"
|
||||
`
|
||||
|
||||
// GPL starts a test metadata file for GPL 2.0 licensing.
|
||||
GPL = `` +
|
||||
`package_name: "Free Software"
|
||||
license_kinds: "SPDX-license-identifier-GPL-2.0"
|
||||
license_conditions: "restricted"
|
||||
`
|
||||
|
||||
// Classpath starts a test metadata file for GPL 2.0 with classpath exception licensing.
|
||||
Classpath = `` +
|
||||
`package_name: "Free Software"
|
||||
license_kinds: "SPDX-license-identifier-GPL-2.0-with-classpath-exception"
|
||||
license_conditions: "restricted"
|
||||
`
|
||||
|
||||
// DependentModule starts a test metadata file for a module in the same package as `Classpath`.
|
||||
DependentModule = `` +
|
||||
`package_name: "Free Software"
|
||||
license_kinds: "SPDX-license-identifier-MIT"
|
||||
license_conditions: "notice"
|
||||
`
|
||||
|
||||
// LGPL starts a test metadata file for a module with LGPL 2.0 licensing.
|
||||
LGPL = `` +
|
||||
`package_name: "Free Library"
|
||||
license_kinds: "SPDX-license-identifier-LGPL-2.0"
|
||||
license_conditions: "restricted"
|
||||
`
|
||||
|
||||
// MPL starts a test metadata file for a module with MPL 2.0 reciprical licensing.
|
||||
MPL = `` +
|
||||
`package_name: "Reciprocal"
|
||||
license_kinds: "SPDX-license-identifier-MPL-2.0"
|
||||
license_conditions: "reciprocal"
|
||||
`
|
||||
|
||||
// MIT starts a test metadata file for a module with generic notice (MIT) licensing.
|
||||
MIT = `` +
|
||||
`package_name: "Android"
|
||||
license_kinds: "SPDX-license-identifier-MIT"
|
||||
license_conditions: "notice"
|
||||
`
|
||||
|
||||
// Proprietary starts a test metadata file for a module with proprietary licensing.
|
||||
Proprietary = `` +
|
||||
`package_name: "Android"
|
||||
license_kinds: "legacy_proprietary"
|
||||
license_conditions: "proprietary"
|
||||
`
|
||||
|
||||
// ByException starts a test metadata file for a module with by_exception_only licensing.
|
||||
ByException = `` +
|
||||
`package_name: "Special"
|
||||
license_kinds: "legacy_by_exception_only"
|
||||
license_conditions: "by_exception_only"
|
||||
`
|
||||
|
||||
)
|
||||
|
||||
var (
|
||||
// meta maps test file names to metadata file content without dependencies.
|
||||
meta = map[string]string{
|
||||
"apacheBin.meta_lic": AOSP,
|
||||
"apacheLib.meta_lic": AOSP,
|
||||
"apacheContainer.meta_lic": AOSP + "is_container: true\n",
|
||||
"dependentModule.meta_lic": DependentModule,
|
||||
"gplWithClasspathException.meta_lic": Classpath,
|
||||
"gplBin.meta_lic": GPL,
|
||||
"gplLib.meta_lic": GPL,
|
||||
"gplContainer.meta_lic": GPL + "is_container: true\n",
|
||||
"lgplBin.meta_lic": LGPL,
|
||||
"lgplLib.meta_lic": LGPL,
|
||||
"mitBin.meta_lic": MIT,
|
||||
"mitLib.meta_lic": MIT,
|
||||
"mplBin.meta_lic": MPL,
|
||||
"mplLib.meta_lic": MPL,
|
||||
"proprietary.meta_lic": Proprietary,
|
||||
"by_exception.meta_lic": ByException,
|
||||
}
|
||||
)
|
||||
|
||||
// toConditionList converts a test data map of condition name to origin names into a ConditionList.
|
||||
@@ -125,6 +204,98 @@ func (l byEdge) Less(i, j int) bool {
|
||||
return l[i].target < l[j].target
|
||||
}
|
||||
|
||||
|
||||
// annotated describes annotated test data edges to define test graphs.
|
||||
type annotated struct {
|
||||
target, dep string
|
||||
annotations []string
|
||||
}
|
||||
|
||||
func (e annotated) String() string {
|
||||
if e.annotations != nil {
|
||||
return e.target + " -> " + e.dep + " [" + strings.Join(e.annotations, ", ") + "]"
|
||||
}
|
||||
return e.target + " -> " + e.dep
|
||||
}
|
||||
|
||||
func (e annotated) IsEqualTo(other annotated) bool {
|
||||
if e.target != other.target {
|
||||
return false
|
||||
}
|
||||
if e.dep != other.dep {
|
||||
return false
|
||||
}
|
||||
if len(e.annotations) != len(other.annotations) {
|
||||
return false
|
||||
}
|
||||
a1 := append([]string{}, e.annotations...)
|
||||
a2 := append([]string{}, other.annotations...)
|
||||
for i := 0; i < len(a1); i++ {
|
||||
if a1[i] != a2[i] {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// toGraph converts a list of roots and a list of annotated edges into a test license graph.
|
||||
func toGraph(stderr io.Writer, roots []string, edges []annotated) (*LicenseGraph, error) {
|
||||
deps := make(map[string][]annotated)
|
||||
for _, root := range roots {
|
||||
deps[root] = []annotated{}
|
||||
}
|
||||
for _, edge := range edges {
|
||||
if prev, ok := deps[edge.target]; ok {
|
||||
deps[edge.target] = append(prev, edge)
|
||||
} else {
|
||||
deps[edge.target] = []annotated{edge}
|
||||
}
|
||||
if _, ok := deps[edge.dep]; !ok {
|
||||
deps[edge.dep] = []annotated{}
|
||||
}
|
||||
}
|
||||
fs := make(testFS)
|
||||
for file, edges := range deps {
|
||||
body := meta[file]
|
||||
for _, edge := range edges {
|
||||
body += fmt.Sprintf("deps: {\n file: %q\n", edge.dep)
|
||||
for _, ann := range edge.annotations {
|
||||
body += fmt.Sprintf(" annotations: %q\n", ann)
|
||||
}
|
||||
body += "}\n"
|
||||
}
|
||||
fs[file] = []byte(body)
|
||||
}
|
||||
|
||||
return ReadLicenseGraph(&fs, stderr, roots)
|
||||
}
|
||||
|
||||
|
||||
// byAnnotatedEdge orders edges by target then dep name then annotations.
|
||||
type byAnnotatedEdge []annotated
|
||||
|
||||
func (l byAnnotatedEdge) Len() int { return len(l) }
|
||||
func (l byAnnotatedEdge) Swap(i, j int) { l[i], l[j] = l[j], l[i] }
|
||||
func (l byAnnotatedEdge) Less(i, j int) bool {
|
||||
if l[i].target == l[j].target {
|
||||
if l[i].dep == l[j].dep {
|
||||
ai := append([]string{}, l[i].annotations...)
|
||||
aj := append([]string{}, l[j].annotations...)
|
||||
sort.Strings(ai)
|
||||
sort.Strings(aj)
|
||||
for k := 0; k < len(ai) && k < len(aj); k++ {
|
||||
if ai[k] == aj[k] {
|
||||
continue
|
||||
}
|
||||
return ai[k] < aj[k]
|
||||
}
|
||||
return len(ai) < len(aj)
|
||||
}
|
||||
return l[i].dep < l[j].dep
|
||||
}
|
||||
return l[i].target < l[j].target
|
||||
}
|
||||
|
||||
// res describes test data resolutions to define test resolution sets.
|
||||
type res struct {
|
||||
attachesTo, actsOn, origin, condition string
|
||||
@@ -148,6 +319,28 @@ func toResolutionSet(lg *LicenseGraph, data []res) *ResolutionSet {
|
||||
return &ResolutionSet{rmap}
|
||||
}
|
||||
|
||||
type confl struct {
|
||||
sourceNode, share, privacy string
|
||||
}
|
||||
|
||||
func toConflictList(lg *LicenseGraph, data []confl) []SourceSharePrivacyConflict {
|
||||
result := make([]SourceSharePrivacyConflict, 0, len(data))
|
||||
for _, c := range data {
|
||||
fields := strings.Split(c.share, ":")
|
||||
oshare := fields[0]
|
||||
cshare := fields[1]
|
||||
fields = strings.Split(c.privacy, ":")
|
||||
oprivacy := fields[0]
|
||||
cprivacy := fields[1]
|
||||
result = append(result, SourceSharePrivacyConflict{
|
||||
newTestNode(lg, c.sourceNode),
|
||||
LicenseCondition{cshare, newTestNode(lg, oshare)},
|
||||
LicenseCondition{cprivacy, newTestNode(lg, oprivacy)},
|
||||
})
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
// checkSameActions compares an actual action set to an expected action set for a test.
|
||||
func checkSameActions(lg *LicenseGraph, asActual, asExpected actionSet, t *testing.T) {
|
||||
rsActual := ResolutionSet{make(map[*TargetNode]actionSet)}
|
||||
|
Reference in New Issue
Block a user