blob: e661a44e2caaac2b625af46110b05ab1b158c65f [file] [log] [blame]
Bob Badoure6fdd142021-12-09 22:10:43 -08001// 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 main
16
17import (
18 "bufio"
19 "bytes"
20 "fmt"
21 "os"
Colin Crossbb45f8c2022-01-28 15:18:19 -080022 "reflect"
Bob Badoure6fdd142021-12-09 22:10:43 -080023 "regexp"
24 "strings"
25 "testing"
Bob Badourc778e4c2022-03-22 13:05:19 -070026
27 "android/soong/tools/compliance"
Bob Badoure6fdd142021-12-09 22:10:43 -080028)
29
30var (
31 horizontalRule = regexp.MustCompile("^===[=]*===$")
32)
33
Colin Crossd0f05c92022-01-27 15:40:29 -080034func TestMain(m *testing.M) {
35 // Change into the parent directory before running the tests
36 // so they can find the testdata directory.
37 if err := os.Chdir(".."); err != nil {
38 fmt.Printf("failed to change to testdata directory: %s\n", err)
39 os.Exit(1)
40 }
41 os.Exit(m.Run())
42}
43
Bob Badoure6fdd142021-12-09 22:10:43 -080044func Test(t *testing.T) {
45 tests := []struct {
Colin Crossbb45f8c2022-01-28 15:18:19 -080046 condition string
47 name string
Bob Badourc778e4c2022-03-22 13:05:19 -070048 outDir string
Colin Crossbb45f8c2022-01-28 15:18:19 -080049 roots []string
50 stripPrefix string
51 expectedOut []matcher
52 expectedDeps []string
Bob Badoure6fdd142021-12-09 22:10:43 -080053 }{
54 {
55 condition: "firstparty",
56 name: "apex",
57 roots: []string{"highest.apex.meta_lic"},
58 expectedOut: []matcher{
59 hr{},
60 library{"Android"},
61 usedBy{"highest.apex"},
62 usedBy{"highest.apex/bin/bin1"},
63 usedBy{"highest.apex/bin/bin2"},
64 usedBy{"highest.apex/lib/liba.so"},
65 usedBy{"highest.apex/lib/libb.so"},
66 firstParty{},
67 },
Colin Crossbb45f8c2022-01-28 15:18:19 -080068 expectedDeps: []string{"testdata/firstparty/FIRST_PARTY_LICENSE"},
Bob Badoure6fdd142021-12-09 22:10:43 -080069 },
70 {
71 condition: "firstparty",
72 name: "container",
73 roots: []string{"container.zip.meta_lic"},
74 expectedOut: []matcher{
75 hr{},
76 library{"Android"},
77 usedBy{"container.zip"},
78 usedBy{"container.zip/bin1"},
79 usedBy{"container.zip/bin2"},
80 usedBy{"container.zip/liba.so"},
81 usedBy{"container.zip/libb.so"},
82 firstParty{},
83 },
Colin Crossbb45f8c2022-01-28 15:18:19 -080084 expectedDeps: []string{"testdata/firstparty/FIRST_PARTY_LICENSE"},
Bob Badoure6fdd142021-12-09 22:10:43 -080085 },
86 {
87 condition: "firstparty",
88 name: "application",
89 roots: []string{"application.meta_lic"},
90 expectedOut: []matcher{
91 hr{},
92 library{"Android"},
93 usedBy{"application"},
94 firstParty{},
95 },
Colin Crossbb45f8c2022-01-28 15:18:19 -080096 expectedDeps: []string{"testdata/firstparty/FIRST_PARTY_LICENSE"},
Bob Badoure6fdd142021-12-09 22:10:43 -080097 },
98 {
99 condition: "firstparty",
100 name: "binary",
101 roots: []string{"bin/bin1.meta_lic"},
102 expectedOut: []matcher{
103 hr{},
104 library{"Android"},
105 usedBy{"bin/bin1"},
106 firstParty{},
107 },
Colin Crossbb45f8c2022-01-28 15:18:19 -0800108 expectedDeps: []string{"testdata/firstparty/FIRST_PARTY_LICENSE"},
Bob Badoure6fdd142021-12-09 22:10:43 -0800109 },
110 {
111 condition: "firstparty",
112 name: "library",
113 roots: []string{"lib/libd.so.meta_lic"},
114 expectedOut: []matcher{
115 hr{},
116 library{"Android"},
117 usedBy{"lib/libd.so"},
118 firstParty{},
119 },
Colin Crossbb45f8c2022-01-28 15:18:19 -0800120 expectedDeps: []string{"testdata/firstparty/FIRST_PARTY_LICENSE"},
Bob Badoure6fdd142021-12-09 22:10:43 -0800121 },
122 {
123 condition: "notice",
124 name: "apex",
125 roots: []string{"highest.apex.meta_lic"},
126 expectedOut: []matcher{
127 hr{},
128 library{"Android"},
129 usedBy{"highest.apex"},
130 usedBy{"highest.apex/bin/bin1"},
131 usedBy{"highest.apex/bin/bin2"},
132 usedBy{"highest.apex/lib/libb.so"},
133 firstParty{},
134 hr{},
135 library{"Device"},
136 usedBy{"highest.apex/bin/bin1"},
137 usedBy{"highest.apex/lib/liba.so"},
138 library{"External"},
139 usedBy{"highest.apex/bin/bin1"},
140 notice{},
141 },
Colin Crossbb45f8c2022-01-28 15:18:19 -0800142 expectedDeps: []string{
143 "testdata/firstparty/FIRST_PARTY_LICENSE",
144 "testdata/notice/NOTICE_LICENSE",
145 },
Bob Badoure6fdd142021-12-09 22:10:43 -0800146 },
147 {
148 condition: "notice",
149 name: "container",
150 roots: []string{"container.zip.meta_lic"},
151 expectedOut: []matcher{
152 hr{},
153 library{"Android"},
154 usedBy{"container.zip"},
155 usedBy{"container.zip/bin1"},
156 usedBy{"container.zip/bin2"},
157 usedBy{"container.zip/libb.so"},
158 firstParty{},
159 hr{},
160 library{"Device"},
161 usedBy{"container.zip/bin1"},
162 usedBy{"container.zip/liba.so"},
163 library{"External"},
164 usedBy{"container.zip/bin1"},
165 notice{},
166 },
Colin Crossbb45f8c2022-01-28 15:18:19 -0800167 expectedDeps: []string{
168 "testdata/firstparty/FIRST_PARTY_LICENSE",
169 "testdata/notice/NOTICE_LICENSE",
170 },
Bob Badoure6fdd142021-12-09 22:10:43 -0800171 },
172 {
173 condition: "notice",
174 name: "application",
175 roots: []string{"application.meta_lic"},
176 expectedOut: []matcher{
177 hr{},
178 library{"Android"},
179 usedBy{"application"},
180 firstParty{},
181 hr{},
182 library{"Device"},
183 usedBy{"application"},
184 notice{},
185 },
Colin Crossbb45f8c2022-01-28 15:18:19 -0800186 expectedDeps: []string{
187 "testdata/firstparty/FIRST_PARTY_LICENSE",
188 "testdata/notice/NOTICE_LICENSE",
189 },
Bob Badoure6fdd142021-12-09 22:10:43 -0800190 },
191 {
192 condition: "notice",
193 name: "binary",
194 roots: []string{"bin/bin1.meta_lic"},
195 expectedOut: []matcher{
196 hr{},
197 library{"Android"},
198 usedBy{"bin/bin1"},
199 firstParty{},
200 hr{},
201 library{"Device"},
202 usedBy{"bin/bin1"},
203 library{"External"},
204 usedBy{"bin/bin1"},
205 notice{},
206 },
Colin Crossbb45f8c2022-01-28 15:18:19 -0800207 expectedDeps: []string{
208 "testdata/firstparty/FIRST_PARTY_LICENSE",
209 "testdata/notice/NOTICE_LICENSE",
210 },
Bob Badoure6fdd142021-12-09 22:10:43 -0800211 },
212 {
213 condition: "notice",
214 name: "library",
215 roots: []string{"lib/libd.so.meta_lic"},
216 expectedOut: []matcher{
217 hr{},
218 library{"External"},
219 usedBy{"lib/libd.so"},
220 notice{},
221 },
Colin Crossbb45f8c2022-01-28 15:18:19 -0800222 expectedDeps: []string{"testdata/notice/NOTICE_LICENSE"},
Bob Badoure6fdd142021-12-09 22:10:43 -0800223 },
224 {
225 condition: "reciprocal",
226 name: "apex",
227 roots: []string{"highest.apex.meta_lic"},
228 expectedOut: []matcher{
229 hr{},
230 library{"Android"},
231 usedBy{"highest.apex"},
232 usedBy{"highest.apex/bin/bin1"},
233 usedBy{"highest.apex/bin/bin2"},
234 usedBy{"highest.apex/lib/libb.so"},
235 firstParty{},
236 hr{},
237 library{"Device"},
238 usedBy{"highest.apex/bin/bin1"},
239 usedBy{"highest.apex/lib/liba.so"},
240 library{"External"},
241 usedBy{"highest.apex/bin/bin1"},
242 reciprocal{},
243 },
Colin Crossbb45f8c2022-01-28 15:18:19 -0800244 expectedDeps: []string{
245 "testdata/firstparty/FIRST_PARTY_LICENSE",
246 "testdata/reciprocal/RECIPROCAL_LICENSE",
247 },
Bob Badoure6fdd142021-12-09 22:10:43 -0800248 },
249 {
250 condition: "reciprocal",
251 name: "container",
252 roots: []string{"container.zip.meta_lic"},
253 expectedOut: []matcher{
254 hr{},
255 library{"Android"},
256 usedBy{"container.zip"},
257 usedBy{"container.zip/bin1"},
258 usedBy{"container.zip/bin2"},
259 usedBy{"container.zip/libb.so"},
260 firstParty{},
261 hr{},
262 library{"Device"},
263 usedBy{"container.zip/bin1"},
264 usedBy{"container.zip/liba.so"},
265 library{"External"},
266 usedBy{"container.zip/bin1"},
267 reciprocal{},
268 },
Colin Crossbb45f8c2022-01-28 15:18:19 -0800269 expectedDeps: []string{
270 "testdata/firstparty/FIRST_PARTY_LICENSE",
271 "testdata/reciprocal/RECIPROCAL_LICENSE",
272 },
Bob Badoure6fdd142021-12-09 22:10:43 -0800273 },
274 {
275 condition: "reciprocal",
276 name: "application",
277 roots: []string{"application.meta_lic"},
278 expectedOut: []matcher{
279 hr{},
280 library{"Android"},
281 usedBy{"application"},
282 firstParty{},
283 hr{},
284 library{"Device"},
285 usedBy{"application"},
286 reciprocal{},
287 },
Colin Crossbb45f8c2022-01-28 15:18:19 -0800288 expectedDeps: []string{
289 "testdata/firstparty/FIRST_PARTY_LICENSE",
290 "testdata/reciprocal/RECIPROCAL_LICENSE",
291 },
Bob Badoure6fdd142021-12-09 22:10:43 -0800292 },
293 {
294 condition: "reciprocal",
295 name: "binary",
296 roots: []string{"bin/bin1.meta_lic"},
297 expectedOut: []matcher{
298 hr{},
299 library{"Android"},
300 usedBy{"bin/bin1"},
301 firstParty{},
302 hr{},
303 library{"Device"},
304 usedBy{"bin/bin1"},
305 library{"External"},
306 usedBy{"bin/bin1"},
307 reciprocal{},
308 },
Colin Crossbb45f8c2022-01-28 15:18:19 -0800309 expectedDeps: []string{
310 "testdata/firstparty/FIRST_PARTY_LICENSE",
311 "testdata/reciprocal/RECIPROCAL_LICENSE",
312 },
Bob Badoure6fdd142021-12-09 22:10:43 -0800313 },
314 {
315 condition: "reciprocal",
316 name: "library",
317 roots: []string{"lib/libd.so.meta_lic"},
318 expectedOut: []matcher{
319 hr{},
320 library{"External"},
321 usedBy{"lib/libd.so"},
322 notice{},
323 },
Colin Crossbb45f8c2022-01-28 15:18:19 -0800324 expectedDeps: []string{
325 "testdata/notice/NOTICE_LICENSE",
326 },
Bob Badoure6fdd142021-12-09 22:10:43 -0800327 },
328 {
329 condition: "restricted",
330 name: "apex",
331 roots: []string{"highest.apex.meta_lic"},
332 expectedOut: []matcher{
333 hr{},
334 library{"Android"},
335 usedBy{"highest.apex"},
336 usedBy{"highest.apex/bin/bin1"},
337 usedBy{"highest.apex/bin/bin2"},
338 firstParty{},
339 hr{},
340 library{"Android"},
341 usedBy{"highest.apex/bin/bin2"},
342 usedBy{"highest.apex/lib/libb.so"},
343 library{"Device"},
344 usedBy{"highest.apex/bin/bin1"},
345 usedBy{"highest.apex/lib/liba.so"},
346 restricted{},
347 hr{},
348 library{"External"},
349 usedBy{"highest.apex/bin/bin1"},
350 reciprocal{},
351 },
Colin Crossbb45f8c2022-01-28 15:18:19 -0800352 expectedDeps: []string{
353 "testdata/firstparty/FIRST_PARTY_LICENSE",
354 "testdata/reciprocal/RECIPROCAL_LICENSE",
355 "testdata/restricted/RESTRICTED_LICENSE",
356 },
Bob Badoure6fdd142021-12-09 22:10:43 -0800357 },
358 {
359 condition: "restricted",
360 name: "container",
361 roots: []string{"container.zip.meta_lic"},
362 expectedOut: []matcher{
363 hr{},
364 library{"Android"},
365 usedBy{"container.zip"},
366 usedBy{"container.zip/bin1"},
367 usedBy{"container.zip/bin2"},
368 firstParty{},
369 hr{},
370 library{"Android"},
371 usedBy{"container.zip/bin2"},
372 usedBy{"container.zip/libb.so"},
373 library{"Device"},
374 usedBy{"container.zip/bin1"},
375 usedBy{"container.zip/liba.so"},
376 restricted{},
377 hr{},
378 library{"External"},
379 usedBy{"container.zip/bin1"},
380 reciprocal{},
381 },
Colin Crossbb45f8c2022-01-28 15:18:19 -0800382 expectedDeps: []string{
383 "testdata/firstparty/FIRST_PARTY_LICENSE",
384 "testdata/reciprocal/RECIPROCAL_LICENSE",
385 "testdata/restricted/RESTRICTED_LICENSE",
386 },
Bob Badoure6fdd142021-12-09 22:10:43 -0800387 },
388 {
389 condition: "restricted",
390 name: "application",
391 roots: []string{"application.meta_lic"},
392 expectedOut: []matcher{
393 hr{},
394 library{"Android"},
395 usedBy{"application"},
396 firstParty{},
397 hr{},
398 library{"Device"},
399 usedBy{"application"},
400 restricted{},
401 },
Colin Crossbb45f8c2022-01-28 15:18:19 -0800402 expectedDeps: []string{
403 "testdata/firstparty/FIRST_PARTY_LICENSE",
404 "testdata/restricted/RESTRICTED_LICENSE",
405 },
Bob Badoure6fdd142021-12-09 22:10:43 -0800406 },
407 {
408 condition: "restricted",
409 name: "binary",
410 roots: []string{"bin/bin1.meta_lic"},
411 expectedOut: []matcher{
412 hr{},
413 library{"Android"},
414 usedBy{"bin/bin1"},
415 firstParty{},
416 hr{},
417 library{"Device"},
418 usedBy{"bin/bin1"},
419 restricted{},
420 hr{},
421 library{"External"},
422 usedBy{"bin/bin1"},
423 reciprocal{},
424 },
Colin Crossbb45f8c2022-01-28 15:18:19 -0800425 expectedDeps: []string{
426 "testdata/firstparty/FIRST_PARTY_LICENSE",
427 "testdata/reciprocal/RECIPROCAL_LICENSE",
428 "testdata/restricted/RESTRICTED_LICENSE",
429 },
Bob Badoure6fdd142021-12-09 22:10:43 -0800430 },
431 {
432 condition: "restricted",
433 name: "library",
434 roots: []string{"lib/libd.so.meta_lic"},
435 expectedOut: []matcher{
436 hr{},
437 library{"External"},
438 usedBy{"lib/libd.so"},
439 notice{},
440 },
Colin Crossbb45f8c2022-01-28 15:18:19 -0800441 expectedDeps: []string{"testdata/notice/NOTICE_LICENSE"},
Bob Badoure6fdd142021-12-09 22:10:43 -0800442 },
443 {
444 condition: "proprietary",
445 name: "apex",
446 roots: []string{"highest.apex.meta_lic"},
447 expectedOut: []matcher{
448 hr{},
449 library{"Android"},
450 usedBy{"highest.apex/bin/bin2"},
451 usedBy{"highest.apex/lib/libb.so"},
452 restricted{},
453 hr{},
454 library{"Android"},
455 usedBy{"highest.apex"},
456 usedBy{"highest.apex/bin/bin1"},
457 firstParty{},
458 hr{},
459 library{"Android"},
460 usedBy{"highest.apex/bin/bin2"},
461 library{"Device"},
462 usedBy{"highest.apex/bin/bin1"},
463 usedBy{"highest.apex/lib/liba.so"},
464 library{"External"},
465 usedBy{"highest.apex/bin/bin1"},
466 proprietary{},
467 },
Colin Crossbb45f8c2022-01-28 15:18:19 -0800468 expectedDeps: []string{
469 "testdata/firstparty/FIRST_PARTY_LICENSE",
470 "testdata/proprietary/PROPRIETARY_LICENSE",
471 "testdata/restricted/RESTRICTED_LICENSE",
472 },
Bob Badoure6fdd142021-12-09 22:10:43 -0800473 },
474 {
475 condition: "proprietary",
476 name: "container",
477 roots: []string{"container.zip.meta_lic"},
478 expectedOut: []matcher{
479 hr{},
480 library{"Android"},
481 usedBy{"container.zip/bin2"},
482 usedBy{"container.zip/libb.so"},
483 restricted{},
484 hr{},
485 library{"Android"},
486 usedBy{"container.zip"},
487 usedBy{"container.zip/bin1"},
488 firstParty{},
489 hr{},
490 library{"Android"},
491 usedBy{"container.zip/bin2"},
492 library{"Device"},
493 usedBy{"container.zip/bin1"},
494 usedBy{"container.zip/liba.so"},
495 library{"External"},
496 usedBy{"container.zip/bin1"},
497 proprietary{},
498 },
Colin Crossbb45f8c2022-01-28 15:18:19 -0800499 expectedDeps: []string{
500 "testdata/firstparty/FIRST_PARTY_LICENSE",
501 "testdata/proprietary/PROPRIETARY_LICENSE",
502 "testdata/restricted/RESTRICTED_LICENSE",
503 },
Bob Badoure6fdd142021-12-09 22:10:43 -0800504 },
505 {
506 condition: "proprietary",
507 name: "application",
508 roots: []string{"application.meta_lic"},
509 expectedOut: []matcher{
510 hr{},
511 library{"Android"},
512 usedBy{"application"},
513 firstParty{},
514 hr{},
515 library{"Device"},
516 usedBy{"application"},
517 proprietary{},
518 },
Colin Crossbb45f8c2022-01-28 15:18:19 -0800519 expectedDeps: []string{
520 "testdata/firstparty/FIRST_PARTY_LICENSE",
521 "testdata/proprietary/PROPRIETARY_LICENSE",
522 },
Bob Badoure6fdd142021-12-09 22:10:43 -0800523 },
524 {
525 condition: "proprietary",
526 name: "binary",
527 roots: []string{"bin/bin1.meta_lic"},
528 expectedOut: []matcher{
529 hr{},
530 library{"Android"},
531 usedBy{"bin/bin1"},
532 firstParty{},
533 hr{},
534 library{"Device"},
535 usedBy{"bin/bin1"},
536 library{"External"},
537 usedBy{"bin/bin1"},
538 proprietary{},
539 },
Colin Crossbb45f8c2022-01-28 15:18:19 -0800540 expectedDeps: []string{
541 "testdata/firstparty/FIRST_PARTY_LICENSE",
542 "testdata/proprietary/PROPRIETARY_LICENSE",
543 },
Bob Badoure6fdd142021-12-09 22:10:43 -0800544 },
545 {
546 condition: "proprietary",
547 name: "library",
548 roots: []string{"lib/libd.so.meta_lic"},
549 expectedOut: []matcher{
550 hr{},
551 library{"External"},
552 usedBy{"lib/libd.so"},
553 notice{},
554 },
Colin Crossbb45f8c2022-01-28 15:18:19 -0800555 expectedDeps: []string{"testdata/notice/NOTICE_LICENSE"},
Bob Badoure6fdd142021-12-09 22:10:43 -0800556 },
557 }
558 for _, tt := range tests {
559 t.Run(tt.condition+" "+tt.name, func(t *testing.T) {
560 stdout := &bytes.Buffer{}
561 stderr := &bytes.Buffer{}
562
563 rootFiles := make([]string, 0, len(tt.roots))
564 for _, r := range tt.roots {
565 rootFiles = append(rootFiles, "testdata/"+tt.condition+"/"+r)
566 }
567
Colin Crossbb45f8c2022-01-28 15:18:19 -0800568 var deps []string
569
Bob Badourc778e4c2022-03-22 13:05:19 -0700570 ctx := context{stdout, stderr, compliance.GetFS(tt.outDir), "", []string{tt.stripPrefix}, "", &deps}
Bob Badoure6fdd142021-12-09 22:10:43 -0800571
572 err := textNotice(&ctx, rootFiles...)
573 if err != nil {
Colin Cross179ec3e2022-01-27 15:47:09 -0800574 t.Fatalf("textnotice: error = %v, stderr = %v", err, stderr)
Bob Badoure6fdd142021-12-09 22:10:43 -0800575 return
576 }
577 if stderr.Len() > 0 {
578 t.Errorf("textnotice: gotStderr = %v, want none", stderr)
579 }
580
581 t.Logf("got stdout: %s", stdout.String())
582
583 t.Logf("want stdout: %s", matcherList(tt.expectedOut).String())
584
585 out := bufio.NewScanner(stdout)
586 lineno := 0
587 for out.Scan() {
588 line := out.Text()
589 if strings.TrimLeft(line, " ") == "" {
590 continue
591 }
592 if len(tt.expectedOut) <= lineno {
593 t.Errorf("unexpected output at line %d: got %q, want nothing (wanted %d lines)", lineno+1, line, len(tt.expectedOut))
594 } else if !tt.expectedOut[lineno].isMatch(line) {
595 t.Errorf("unexpected output at line %d: got %q, want %q", lineno+1, line, tt.expectedOut[lineno].String())
596 }
597 lineno++
598 }
599 for ; lineno < len(tt.expectedOut); lineno++ {
600 t.Errorf("textnotice: missing output line %d: ended early, want %q", lineno+1, tt.expectedOut[lineno].String())
601 }
Colin Crossbb45f8c2022-01-28 15:18:19 -0800602
603 t.Logf("got deps: %q", deps)
604
605 t.Logf("want deps: %q", tt.expectedDeps)
606
607 if g, w := deps, tt.expectedDeps; !reflect.DeepEqual(g, w) {
608 t.Errorf("unexpected deps, wanted:\n%s\ngot:\n%s\n",
609 strings.Join(w, "\n"), strings.Join(g, "\n"))
610 }
Bob Badoure6fdd142021-12-09 22:10:43 -0800611 })
612 }
613}
614
615type matcher interface {
616 isMatch(line string) bool
617 String() string
618}
619
620type hr struct{}
621
622func (m hr) isMatch(line string) bool {
623 return horizontalRule.MatchString(line)
624}
625
626func (m hr) String() string {
627 return " ================================================== "
628}
629
630type library struct {
631 name string
632}
633
634func (m library) isMatch(line string) bool {
635 return strings.HasPrefix(line, m.name+" ")
636}
637
638func (m library) String() string {
639 return m.name + " used by:"
640}
641
642type usedBy struct {
643 name string
644}
645
646func (m usedBy) isMatch(line string) bool {
647 return len(line) > 0 && line[0] == ' ' && strings.HasPrefix(strings.TrimLeft(line, " "), "out/") && strings.HasSuffix(line, "/"+m.name)
648}
649
650func (m usedBy) String() string {
651 return " out/.../" + m.name
652}
653
654type firstParty struct{}
655
656func (m firstParty) isMatch(line string) bool {
657 return strings.HasPrefix(strings.TrimLeft(line, " "), "&&&First Party License&&&")
658}
659
660func (m firstParty) String() string {
661 return "&&&First Party License&&&"
662}
663
664type notice struct{}
665
666func (m notice) isMatch(line string) bool {
667 return strings.HasPrefix(strings.TrimLeft(line, " "), "%%%Notice License%%%")
668}
669
670func (m notice) String() string {
671 return "%%%Notice License%%%"
672}
673
674type reciprocal struct{}
675
676func (m reciprocal) isMatch(line string) bool {
677 return strings.HasPrefix(strings.TrimLeft(line, " "), "$$$Reciprocal License$$$")
678}
679
680func (m reciprocal) String() string {
681 return "$$$Reciprocal License$$$"
682}
683
684type restricted struct{}
685
686func (m restricted) isMatch(line string) bool {
687 return strings.HasPrefix(strings.TrimLeft(line, " "), "###Restricted License###")
688}
689
690func (m restricted) String() string {
691 return "###Restricted License###"
692}
693
694type proprietary struct{}
695
696func (m proprietary) isMatch(line string) bool {
697 return strings.HasPrefix(strings.TrimLeft(line, " "), "@@@Proprietary License@@@")
698}
699
700func (m proprietary) String() string {
701 return "@@@Proprietary License@@@"
702}
703
704type matcherList []matcher
705
706func (l matcherList) String() string {
707 var sb strings.Builder
708 for _, m := range l {
709 s := m.String()
710 if s[:3] == s[len(s)-3:] {
711 fmt.Fprintln(&sb)
712 }
713 fmt.Fprintf(&sb, "%s\n", s)
714 if s[:3] == s[len(s)-3:] {
715 fmt.Fprintln(&sb)
716 }
717 }
718 return sb.String()
719}