blob: 94d0be332c00e73e146887907f6ccceabcd6c81a [file] [log] [blame]
Bob Badour9ee7d032021-10-25 16:51:48 -07001// Copyright 2021 Google LLC
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15package compliance
16
17import (
18 "bytes"
19 "fmt"
20 "sort"
21 "strings"
22 "testing"
23)
24
25func TestPolicy_edgeConditions(t *testing.T) {
26 tests := []struct {
27 name string
28 edge annotated
29 treatAsAggregate bool
30 otherCondition string
31 expectedDepActions []string
32 expectedTargetConditions []string
33 }{
34 {
35 name: "firstparty",
36 edge: annotated{"apacheBin.meta_lic", "apacheLib.meta_lic", []string{"static"}},
Bob Badour103eb0f2022-01-10 13:50:57 -080037 expectedDepActions: []string{},
Bob Badour9ee7d032021-10-25 16:51:48 -070038 expectedTargetConditions: []string{},
39 },
40 {
41 name: "notice",
42 edge: annotated{"mitBin.meta_lic", "mitLib.meta_lic", []string{"static"}},
Bob Badour103eb0f2022-01-10 13:50:57 -080043 expectedDepActions: []string{},
Bob Badour9ee7d032021-10-25 16:51:48 -070044 expectedTargetConditions: []string{},
45 },
46 {
47 name: "fponlgpl",
48 edge: annotated{"apacheBin.meta_lic", "lgplLib.meta_lic", []string{"static"}},
49 expectedDepActions: []string{
Bob Badour103eb0f2022-01-10 13:50:57 -080050 "apacheBin.meta_lic:lgplLib.meta_lic:restricted_allows_dynamic_linking",
51 "lgplLib.meta_lic:lgplLib.meta_lic:restricted_allows_dynamic_linking",
Bob Badour9ee7d032021-10-25 16:51:48 -070052 },
53 expectedTargetConditions: []string{},
54 },
55 {
56 name: "fponlgpldynamic",
57 edge: annotated{"apacheBin.meta_lic", "lgplLib.meta_lic", []string{"dynamic"}},
58 expectedDepActions: []string{},
59 expectedTargetConditions: []string{},
60 },
61 {
62 name: "fpongpl",
63 edge: annotated{"apacheBin.meta_lic", "gplLib.meta_lic", []string{"static"}},
64 expectedDepActions: []string{
65 "apacheBin.meta_lic:gplLib.meta_lic:restricted",
66 "gplLib.meta_lic:gplLib.meta_lic:restricted",
67 },
68 expectedTargetConditions: []string{},
69 },
70 {
71 name: "fpongpldynamic",
72 edge: annotated{"apacheBin.meta_lic", "gplLib.meta_lic", []string{"dynamic"}},
73 expectedDepActions: []string{
74 "apacheBin.meta_lic:gplLib.meta_lic:restricted",
75 "gplLib.meta_lic:gplLib.meta_lic:restricted",
76 },
77 expectedTargetConditions: []string{},
78 },
79 {
80 name: "independentmodule",
81 edge: annotated{"apacheBin.meta_lic", "gplWithClasspathException.meta_lic", []string{"dynamic"}},
82 expectedDepActions: []string{},
83 expectedTargetConditions: []string{},
84 },
85 {
86 name: "independentmodulestatic",
87 edge: annotated{"apacheBin.meta_lic", "gplWithClasspathException.meta_lic", []string{"static"}},
Bob Badour10f5c482022-09-20 21:44:17 -070088 expectedDepActions: []string{},
Bob Badour9ee7d032021-10-25 16:51:48 -070089 expectedTargetConditions: []string{},
90 },
91 {
92 name: "dependentmodule",
93 edge: annotated{"dependentModule.meta_lic", "gplWithClasspathException.meta_lic", []string{"dynamic"}},
Bob Badour10f5c482022-09-20 21:44:17 -070094 expectedDepActions: []string{},
Bob Badour9ee7d032021-10-25 16:51:48 -070095 expectedTargetConditions: []string{},
96 },
97
98 {
99 name: "lgplonfp",
100 edge: annotated{"lgplBin.meta_lic", "apacheLib.meta_lic", []string{"static"}},
Bob Badour103eb0f2022-01-10 13:50:57 -0800101 expectedDepActions: []string{},
102 expectedTargetConditions: []string{"lgplBin.meta_lic:restricted_allows_dynamic_linking"},
Bob Badour9ee7d032021-10-25 16:51:48 -0700103 },
104 {
105 name: "lgplonfpdynamic",
106 edge: annotated{"lgplBin.meta_lic", "apacheLib.meta_lic", []string{"dynamic"}},
107 expectedDepActions: []string{},
108 expectedTargetConditions: []string{},
109 },
110 {
111 name: "gplonfp",
112 edge: annotated{"gplBin.meta_lic", "apacheLib.meta_lic", []string{"static"}},
Bob Badour103eb0f2022-01-10 13:50:57 -0800113 expectedDepActions: []string{},
Bob Badour9ee7d032021-10-25 16:51:48 -0700114 expectedTargetConditions: []string{"gplBin.meta_lic:restricted"},
115 },
116 {
117 name: "gplcontainer",
118 edge: annotated{"gplContainer.meta_lic", "apacheLib.meta_lic", []string{"static"}},
119 treatAsAggregate: true,
Bob Badour103eb0f2022-01-10 13:50:57 -0800120 expectedDepActions: []string{},
Bob Badour9ee7d032021-10-25 16:51:48 -0700121 expectedTargetConditions: []string{"gplContainer.meta_lic:restricted"},
122 },
123 {
124 name: "gploncontainer",
125 edge: annotated{"apacheContainer.meta_lic", "apacheLib.meta_lic", []string{"static"}},
126 treatAsAggregate: true,
127 otherCondition: "gplLib.meta_lic:restricted",
128 expectedDepActions: []string{
129 "apacheContainer.meta_lic:gplLib.meta_lic:restricted",
Bob Badour9ee7d032021-10-25 16:51:48 -0700130 "apacheLib.meta_lic:gplLib.meta_lic:restricted",
131 "gplLib.meta_lic:gplLib.meta_lic:restricted",
132 },
133 expectedTargetConditions: []string{},
134 },
135 {
136 name: "gplonbin",
137 edge: annotated{"apacheBin.meta_lic", "apacheLib.meta_lic", []string{"static"}},
138 treatAsAggregate: false,
139 otherCondition: "gplLib.meta_lic:restricted",
140 expectedDepActions: []string{
141 "apacheBin.meta_lic:gplLib.meta_lic:restricted",
Bob Badour9ee7d032021-10-25 16:51:48 -0700142 "apacheLib.meta_lic:gplLib.meta_lic:restricted",
143 "gplLib.meta_lic:gplLib.meta_lic:restricted",
144 },
145 expectedTargetConditions: []string{"gplLib.meta_lic:restricted"},
146 },
147 {
148 name: "gplonfpdynamic",
149 edge: annotated{"gplBin.meta_lic", "apacheLib.meta_lic", []string{"dynamic"}},
150 expectedDepActions: []string{},
151 expectedTargetConditions: []string{"gplBin.meta_lic:restricted"},
152 },
153 {
154 name: "independentmodulereverse",
155 edge: annotated{"gplWithClasspathException.meta_lic", "apacheBin.meta_lic", []string{"dynamic"}},
156 expectedDepActions: []string{},
157 expectedTargetConditions: []string{},
158 },
159 {
160 name: "independentmodulereversestatic",
161 edge: annotated{"gplWithClasspathException.meta_lic", "apacheBin.meta_lic", []string{"static"}},
Bob Badour103eb0f2022-01-10 13:50:57 -0800162 expectedDepActions: []string{},
Bob Badour10f5c482022-09-20 21:44:17 -0700163 expectedTargetConditions: []string{},
Bob Badour9ee7d032021-10-25 16:51:48 -0700164 },
165 {
166 name: "dependentmodulereverse",
167 edge: annotated{"gplWithClasspathException.meta_lic", "dependentModule.meta_lic", []string{"dynamic"}},
168 expectedDepActions: []string{},
Bob Badour10f5c482022-09-20 21:44:17 -0700169 expectedTargetConditions: []string{},
Bob Badour9ee7d032021-10-25 16:51:48 -0700170 },
171 {
172 name: "ponr",
173 edge: annotated{"proprietary.meta_lic", "gplLib.meta_lic", []string{"static"}},
174 expectedDepActions: []string{
175 "proprietary.meta_lic:gplLib.meta_lic:restricted",
176 "gplLib.meta_lic:gplLib.meta_lic:restricted",
177 },
178 expectedTargetConditions: []string{},
179 },
180 {
181 name: "ronp",
182 edge: annotated{"gplBin.meta_lic", "proprietary.meta_lic", []string{"static"}},
Bob Badour103eb0f2022-01-10 13:50:57 -0800183 expectedDepActions: []string{},
Bob Badour9ee7d032021-10-25 16:51:48 -0700184 expectedTargetConditions: []string{"gplBin.meta_lic:restricted"},
185 },
186 {
187 name: "noticeonb_e_o",
188 edge: annotated{"mitBin.meta_lic", "by_exception.meta_lic", []string{"static"}},
Bob Badour103eb0f2022-01-10 13:50:57 -0800189 expectedDepActions: []string{},
Bob Badour9ee7d032021-10-25 16:51:48 -0700190 expectedTargetConditions: []string{},
191 },
192 {
193 name: "b_e_oonnotice",
194 edge: annotated{"by_exception.meta_lic", "mitLib.meta_lic", []string{"static"}},
Bob Badour103eb0f2022-01-10 13:50:57 -0800195 expectedDepActions: []string{},
Bob Badour9ee7d032021-10-25 16:51:48 -0700196 expectedTargetConditions: []string{},
197 },
198 {
199 name: "noticeonrecip",
200 edge: annotated{"mitBin.meta_lic", "mplLib.meta_lic", []string{"static"}},
Bob Badour103eb0f2022-01-10 13:50:57 -0800201 expectedDepActions: []string{},
Bob Badour9ee7d032021-10-25 16:51:48 -0700202 expectedTargetConditions: []string{},
203 },
204 {
205 name: "reciponnotice",
206 edge: annotated{"mplBin.meta_lic", "mitLib.meta_lic", []string{"static"}},
Bob Badour103eb0f2022-01-10 13:50:57 -0800207 expectedDepActions: []string{},
Bob Badour9ee7d032021-10-25 16:51:48 -0700208 expectedTargetConditions: []string{},
209 },
210 }
211 for _, tt := range tests {
212 t.Run(tt.name, func(t *testing.T) {
213 fs := make(testFS)
214 stderr := &bytes.Buffer{}
215 target := meta[tt.edge.target] + fmt.Sprintf("deps: {\n file: \"%s\"\n", tt.edge.dep)
216 for _, ann := range tt.edge.annotations {
217 target += fmt.Sprintf(" annotations: \"%s\"\n", ann)
218 }
219 fs[tt.edge.target] = []byte(target + "}\n")
220 fs[tt.edge.dep] = []byte(meta[tt.edge.dep])
221 lg, err := ReadLicenseGraph(&fs, stderr, []string{tt.edge.target})
222 if err != nil {
Colin Cross179ec3e2022-01-27 15:47:09 -0800223 t.Errorf("unexpected error reading graph: %s", err)
Bob Badour9ee7d032021-10-25 16:51:48 -0700224 return
225 }
Bob Badour103eb0f2022-01-10 13:50:57 -0800226 edge := lg.Edges()[0]
Bob Badour9ee7d032021-10-25 16:51:48 -0700227 // simulate a condition inherited from another edge/dependency.
228 otherTarget := ""
229 otherCondition := ""
Bob Badour103eb0f2022-01-10 13:50:57 -0800230 var otn *TargetNode
Bob Badour9ee7d032021-10-25 16:51:48 -0700231 if len(tt.otherCondition) > 0 {
232 fields := strings.Split(tt.otherCondition, ":")
233 otherTarget = fields[0]
234 otherCondition = fields[1]
Bob Badour103eb0f2022-01-10 13:50:57 -0800235 otn = &TargetNode{name: otherTarget}
Bob Badour9ee7d032021-10-25 16:51:48 -0700236 // other target must exist in graph
Bob Badour103eb0f2022-01-10 13:50:57 -0800237 lg.targets[otherTarget] = otn
238 otn.licenseConditions = LicenseConditionSet(RecognizedConditionNames[otherCondition])
239 }
240 targets := make(map[string]*TargetNode)
241 targets[edge.target.name] = edge.target
242 targets[edge.dependency.name] = edge.dependency
243 if otn != nil {
244 targets[otn.name] = otn
Bob Badour9ee7d032021-10-25 16:51:48 -0700245 }
246 if tt.expectedDepActions != nil {
Bob Badour103eb0f2022-01-10 13:50:57 -0800247 t.Run("depConditionsPropagatingToTarget", func(t *testing.T) {
248 depConditions := edge.dependency.LicenseConditions()
249 if otherTarget != "" {
250 // simulate a sub-dependency's condition having already propagated up to dep and about to go to target
251 otherCs := otn.LicenseConditions()
252 depConditions |= otherCs
Bob Badour9ee7d032021-10-25 16:51:48 -0700253 }
Bob Badour10f5c482022-09-20 21:44:17 -0700254 t.Logf("calculate target actions for edge=%s, dep conditions=%#v %s, treatAsAggregate=%v", edge.String(), depConditions, depConditions, tt.treatAsAggregate)
Bob Badour103eb0f2022-01-10 13:50:57 -0800255 csActual := depConditionsPropagatingToTarget(lg, edge, depConditions, tt.treatAsAggregate)
Bob Badour10f5c482022-09-20 21:44:17 -0700256 t.Logf("calculated target conditions as %#v %s", csActual, csActual)
Bob Badour103eb0f2022-01-10 13:50:57 -0800257 csExpected := NewLicenseConditionSet()
258 for _, triple := range tt.expectedDepActions {
259 fields := strings.Split(triple, ":")
260 expectedConditions := NewLicenseConditionSet()
261 for _, cname := range fields[2:] {
262 expectedConditions = expectedConditions.Plus(RecognizedConditionNames[cname])
263 }
264 csExpected |= expectedConditions
265 }
Bob Badour10f5c482022-09-20 21:44:17 -0700266 t.Logf("expected target conditions as %#v %s", csExpected, csExpected)
Bob Badour103eb0f2022-01-10 13:50:57 -0800267 if csActual != csExpected {
Bob Badour10f5c482022-09-20 21:44:17 -0700268 t.Errorf("unexpected license conditions: got %#v, want %#v", csActual, csExpected)
Bob Badour103eb0f2022-01-10 13:50:57 -0800269 }
270 })
Bob Badour9ee7d032021-10-25 16:51:48 -0700271 }
272 if tt.expectedTargetConditions != nil {
Bob Badour103eb0f2022-01-10 13:50:57 -0800273 t.Run("targetConditionsPropagatingToDep", func(t *testing.T) {
274 targetConditions := edge.target.LicenseConditions()
275 if otherTarget != "" {
276 targetConditions = targetConditions.Union(otn.licenseConditions)
277 }
278 t.Logf("calculate dep conditions for edge=%s, target conditions=%v, treatAsAggregate=%v", edge.String(), targetConditions.Names(), tt.treatAsAggregate)
Bob Badourc8178452022-01-31 13:05:53 -0800279 cs := targetConditionsPropagatingToDep(lg, edge, targetConditions, tt.treatAsAggregate, AllResolutions)
Bob Badour103eb0f2022-01-10 13:50:57 -0800280 t.Logf("calculated dep conditions as %v", cs.Names())
281 actual := cs.Names()
282 sort.Strings(actual)
283 expected := make([]string, 0)
284 for _, expectedDepCondition := range tt.expectedTargetConditions {
285 expected = append(expected, strings.Split(expectedDepCondition, ":")[1])
286 }
287 sort.Strings(expected)
288 if len(actual) != len(expected) {
289 t.Errorf("unexpected number of target conditions: got %v with %d conditions, want %v with %d conditions",
290 actual, len(actual), expected, len(expected))
291 } else {
292 for i := 0; i < len(actual); i++ {
293 if actual[i] != expected[i] {
294 t.Errorf("unexpected target condition at element %d: got %q, want %q",
295 i, actual[i], expected[i])
296 }
Bob Badour9ee7d032021-10-25 16:51:48 -0700297 }
298 }
Bob Badour103eb0f2022-01-10 13:50:57 -0800299 })
Bob Badour9ee7d032021-10-25 16:51:48 -0700300 }
301 })
302 }
303}