Merge "compliance package policy and resolves" am: 45deca7ff7
Original change: https://android-review.googlesource.com/c/platform/build/+/1870078 Change-Id: Ied21f22a1230f7865aad360c9bf77aadccd9fffa
This commit is contained in:
@@ -24,6 +24,14 @@ bootstrap_go_package {
|
|||||||
"condition.go",
|
"condition.go",
|
||||||
"conditionset.go",
|
"conditionset.go",
|
||||||
"graph.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",
|
"readgraph.go",
|
||||||
"resolution.go",
|
"resolution.go",
|
||||||
"resolutionset.go",
|
"resolutionset.go",
|
||||||
@@ -32,6 +40,14 @@ bootstrap_go_package {
|
|||||||
"condition_test.go",
|
"condition_test.go",
|
||||||
"conditionset_test.go",
|
"conditionset_test.go",
|
||||||
"readgraph_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",
|
"resolutionset_test.go",
|
||||||
"test_util.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)
|
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")
|
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")
|
t.Errorf("unexpected AttachedToTarget(\"image\"): got false want true")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -30,6 +30,85 @@ const (
|
|||||||
license_kinds: "SPDX-license-identifier-Apache-2.0"
|
license_kinds: "SPDX-license-identifier-Apache-2.0"
|
||||||
license_conditions: "notice"
|
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.
|
// 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
|
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.
|
// res describes test data resolutions to define test resolution sets.
|
||||||
type res struct {
|
type res struct {
|
||||||
attachesTo, actsOn, origin, condition string
|
attachesTo, actsOn, origin, condition string
|
||||||
@@ -148,6 +319,28 @@ func toResolutionSet(lg *LicenseGraph, data []res) *ResolutionSet {
|
|||||||
return &ResolutionSet{rmap}
|
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.
|
// checkSameActions compares an actual action set to an expected action set for a test.
|
||||||
func checkSameActions(lg *LicenseGraph, asActual, asExpected actionSet, t *testing.T) {
|
func checkSameActions(lg *LicenseGraph, asActual, asExpected actionSet, t *testing.T) {
|
||||||
rsActual := ResolutionSet{make(map[*TargetNode]actionSet)}
|
rsActual := ResolutionSet{make(map[*TargetNode]actionSet)}
|
||||||
|
Reference in New Issue
Block a user