blob: 9d8d0cabfcf7486035d86641cd1ef79d2b0bd8ad [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"
26)
27
28var (
29 horizontalRule = regexp.MustCompile("^===[=]*===$")
30)
31
Colin Crossd0f05c92022-01-27 15:40:29 -080032func TestMain(m *testing.M) {
33 // Change into the parent directory before running the tests
34 // so they can find the testdata directory.
35 if err := os.Chdir(".."); err != nil {
36 fmt.Printf("failed to change to testdata directory: %s\n", err)
37 os.Exit(1)
38 }
39 os.Exit(m.Run())
40}
41
Bob Badoure6fdd142021-12-09 22:10:43 -080042func Test(t *testing.T) {
43 tests := []struct {
Colin Crossbb45f8c2022-01-28 15:18:19 -080044 condition string
45 name string
46 roots []string
47 stripPrefix string
48 expectedOut []matcher
49 expectedDeps []string
Bob Badoure6fdd142021-12-09 22:10:43 -080050 }{
51 {
52 condition: "firstparty",
53 name: "apex",
54 roots: []string{"highest.apex.meta_lic"},
55 expectedOut: []matcher{
56 hr{},
57 library{"Android"},
58 usedBy{"highest.apex"},
59 usedBy{"highest.apex/bin/bin1"},
60 usedBy{"highest.apex/bin/bin2"},
61 usedBy{"highest.apex/lib/liba.so"},
62 usedBy{"highest.apex/lib/libb.so"},
63 firstParty{},
64 },
Colin Crossbb45f8c2022-01-28 15:18:19 -080065 expectedDeps: []string{"testdata/firstparty/FIRST_PARTY_LICENSE"},
Bob Badoure6fdd142021-12-09 22:10:43 -080066 },
67 {
68 condition: "firstparty",
69 name: "container",
70 roots: []string{"container.zip.meta_lic"},
71 expectedOut: []matcher{
72 hr{},
73 library{"Android"},
74 usedBy{"container.zip"},
75 usedBy{"container.zip/bin1"},
76 usedBy{"container.zip/bin2"},
77 usedBy{"container.zip/liba.so"},
78 usedBy{"container.zip/libb.so"},
79 firstParty{},
80 },
Colin Crossbb45f8c2022-01-28 15:18:19 -080081 expectedDeps: []string{"testdata/firstparty/FIRST_PARTY_LICENSE"},
Bob Badoure6fdd142021-12-09 22:10:43 -080082 },
83 {
84 condition: "firstparty",
85 name: "application",
86 roots: []string{"application.meta_lic"},
87 expectedOut: []matcher{
88 hr{},
89 library{"Android"},
90 usedBy{"application"},
91 firstParty{},
92 },
Colin Crossbb45f8c2022-01-28 15:18:19 -080093 expectedDeps: []string{"testdata/firstparty/FIRST_PARTY_LICENSE"},
Bob Badoure6fdd142021-12-09 22:10:43 -080094 },
95 {
96 condition: "firstparty",
97 name: "binary",
98 roots: []string{"bin/bin1.meta_lic"},
99 expectedOut: []matcher{
100 hr{},
101 library{"Android"},
102 usedBy{"bin/bin1"},
103 firstParty{},
104 },
Colin Crossbb45f8c2022-01-28 15:18:19 -0800105 expectedDeps: []string{"testdata/firstparty/FIRST_PARTY_LICENSE"},
Bob Badoure6fdd142021-12-09 22:10:43 -0800106 },
107 {
108 condition: "firstparty",
109 name: "library",
110 roots: []string{"lib/libd.so.meta_lic"},
111 expectedOut: []matcher{
112 hr{},
113 library{"Android"},
114 usedBy{"lib/libd.so"},
115 firstParty{},
116 },
Colin Crossbb45f8c2022-01-28 15:18:19 -0800117 expectedDeps: []string{"testdata/firstparty/FIRST_PARTY_LICENSE"},
Bob Badoure6fdd142021-12-09 22:10:43 -0800118 },
119 {
120 condition: "notice",
121 name: "apex",
122 roots: []string{"highest.apex.meta_lic"},
123 expectedOut: []matcher{
124 hr{},
125 library{"Android"},
126 usedBy{"highest.apex"},
127 usedBy{"highest.apex/bin/bin1"},
128 usedBy{"highest.apex/bin/bin2"},
129 usedBy{"highest.apex/lib/libb.so"},
130 firstParty{},
131 hr{},
132 library{"Device"},
133 usedBy{"highest.apex/bin/bin1"},
134 usedBy{"highest.apex/lib/liba.so"},
135 library{"External"},
136 usedBy{"highest.apex/bin/bin1"},
137 notice{},
138 },
Colin Crossbb45f8c2022-01-28 15:18:19 -0800139 expectedDeps: []string{
140 "testdata/firstparty/FIRST_PARTY_LICENSE",
141 "testdata/notice/NOTICE_LICENSE",
142 },
Bob Badoure6fdd142021-12-09 22:10:43 -0800143 },
144 {
145 condition: "notice",
146 name: "container",
147 roots: []string{"container.zip.meta_lic"},
148 expectedOut: []matcher{
149 hr{},
150 library{"Android"},
151 usedBy{"container.zip"},
152 usedBy{"container.zip/bin1"},
153 usedBy{"container.zip/bin2"},
154 usedBy{"container.zip/libb.so"},
155 firstParty{},
156 hr{},
157 library{"Device"},
158 usedBy{"container.zip/bin1"},
159 usedBy{"container.zip/liba.so"},
160 library{"External"},
161 usedBy{"container.zip/bin1"},
162 notice{},
163 },
Colin Crossbb45f8c2022-01-28 15:18:19 -0800164 expectedDeps: []string{
165 "testdata/firstparty/FIRST_PARTY_LICENSE",
166 "testdata/notice/NOTICE_LICENSE",
167 },
Bob Badoure6fdd142021-12-09 22:10:43 -0800168 },
169 {
170 condition: "notice",
171 name: "application",
172 roots: []string{"application.meta_lic"},
173 expectedOut: []matcher{
174 hr{},
175 library{"Android"},
176 usedBy{"application"},
177 firstParty{},
178 hr{},
179 library{"Device"},
180 usedBy{"application"},
181 notice{},
182 },
Colin Crossbb45f8c2022-01-28 15:18:19 -0800183 expectedDeps: []string{
184 "testdata/firstparty/FIRST_PARTY_LICENSE",
185 "testdata/notice/NOTICE_LICENSE",
186 },
Bob Badoure6fdd142021-12-09 22:10:43 -0800187 },
188 {
189 condition: "notice",
190 name: "binary",
191 roots: []string{"bin/bin1.meta_lic"},
192 expectedOut: []matcher{
193 hr{},
194 library{"Android"},
195 usedBy{"bin/bin1"},
196 firstParty{},
197 hr{},
198 library{"Device"},
199 usedBy{"bin/bin1"},
200 library{"External"},
201 usedBy{"bin/bin1"},
202 notice{},
203 },
Colin Crossbb45f8c2022-01-28 15:18:19 -0800204 expectedDeps: []string{
205 "testdata/firstparty/FIRST_PARTY_LICENSE",
206 "testdata/notice/NOTICE_LICENSE",
207 },
Bob Badoure6fdd142021-12-09 22:10:43 -0800208 },
209 {
210 condition: "notice",
211 name: "library",
212 roots: []string{"lib/libd.so.meta_lic"},
213 expectedOut: []matcher{
214 hr{},
215 library{"External"},
216 usedBy{"lib/libd.so"},
217 notice{},
218 },
Colin Crossbb45f8c2022-01-28 15:18:19 -0800219 expectedDeps: []string{"testdata/notice/NOTICE_LICENSE"},
Bob Badoure6fdd142021-12-09 22:10:43 -0800220 },
221 {
222 condition: "reciprocal",
223 name: "apex",
224 roots: []string{"highest.apex.meta_lic"},
225 expectedOut: []matcher{
226 hr{},
227 library{"Android"},
228 usedBy{"highest.apex"},
229 usedBy{"highest.apex/bin/bin1"},
230 usedBy{"highest.apex/bin/bin2"},
231 usedBy{"highest.apex/lib/libb.so"},
232 firstParty{},
233 hr{},
234 library{"Device"},
235 usedBy{"highest.apex/bin/bin1"},
236 usedBy{"highest.apex/lib/liba.so"},
237 library{"External"},
238 usedBy{"highest.apex/bin/bin1"},
239 reciprocal{},
240 },
Colin Crossbb45f8c2022-01-28 15:18:19 -0800241 expectedDeps: []string{
242 "testdata/firstparty/FIRST_PARTY_LICENSE",
243 "testdata/reciprocal/RECIPROCAL_LICENSE",
244 },
Bob Badoure6fdd142021-12-09 22:10:43 -0800245 },
246 {
247 condition: "reciprocal",
248 name: "container",
249 roots: []string{"container.zip.meta_lic"},
250 expectedOut: []matcher{
251 hr{},
252 library{"Android"},
253 usedBy{"container.zip"},
254 usedBy{"container.zip/bin1"},
255 usedBy{"container.zip/bin2"},
256 usedBy{"container.zip/libb.so"},
257 firstParty{},
258 hr{},
259 library{"Device"},
260 usedBy{"container.zip/bin1"},
261 usedBy{"container.zip/liba.so"},
262 library{"External"},
263 usedBy{"container.zip/bin1"},
264 reciprocal{},
265 },
Colin Crossbb45f8c2022-01-28 15:18:19 -0800266 expectedDeps: []string{
267 "testdata/firstparty/FIRST_PARTY_LICENSE",
268 "testdata/reciprocal/RECIPROCAL_LICENSE",
269 },
Bob Badoure6fdd142021-12-09 22:10:43 -0800270 },
271 {
272 condition: "reciprocal",
273 name: "application",
274 roots: []string{"application.meta_lic"},
275 expectedOut: []matcher{
276 hr{},
277 library{"Android"},
278 usedBy{"application"},
279 firstParty{},
280 hr{},
281 library{"Device"},
282 usedBy{"application"},
283 reciprocal{},
284 },
Colin Crossbb45f8c2022-01-28 15:18:19 -0800285 expectedDeps: []string{
286 "testdata/firstparty/FIRST_PARTY_LICENSE",
287 "testdata/reciprocal/RECIPROCAL_LICENSE",
288 },
Bob Badoure6fdd142021-12-09 22:10:43 -0800289 },
290 {
291 condition: "reciprocal",
292 name: "binary",
293 roots: []string{"bin/bin1.meta_lic"},
294 expectedOut: []matcher{
295 hr{},
296 library{"Android"},
297 usedBy{"bin/bin1"},
298 firstParty{},
299 hr{},
300 library{"Device"},
301 usedBy{"bin/bin1"},
302 library{"External"},
303 usedBy{"bin/bin1"},
304 reciprocal{},
305 },
Colin Crossbb45f8c2022-01-28 15:18:19 -0800306 expectedDeps: []string{
307 "testdata/firstparty/FIRST_PARTY_LICENSE",
308 "testdata/reciprocal/RECIPROCAL_LICENSE",
309 },
Bob Badoure6fdd142021-12-09 22:10:43 -0800310 },
311 {
312 condition: "reciprocal",
313 name: "library",
314 roots: []string{"lib/libd.so.meta_lic"},
315 expectedOut: []matcher{
316 hr{},
317 library{"External"},
318 usedBy{"lib/libd.so"},
319 notice{},
320 },
Colin Crossbb45f8c2022-01-28 15:18:19 -0800321 expectedDeps: []string{
322 "testdata/notice/NOTICE_LICENSE",
323 },
Bob Badoure6fdd142021-12-09 22:10:43 -0800324 },
325 {
326 condition: "restricted",
327 name: "apex",
328 roots: []string{"highest.apex.meta_lic"},
329 expectedOut: []matcher{
330 hr{},
331 library{"Android"},
332 usedBy{"highest.apex"},
333 usedBy{"highest.apex/bin/bin1"},
334 usedBy{"highest.apex/bin/bin2"},
335 firstParty{},
336 hr{},
337 library{"Android"},
338 usedBy{"highest.apex/bin/bin2"},
339 usedBy{"highest.apex/lib/libb.so"},
340 library{"Device"},
341 usedBy{"highest.apex/bin/bin1"},
342 usedBy{"highest.apex/lib/liba.so"},
343 restricted{},
344 hr{},
345 library{"External"},
346 usedBy{"highest.apex/bin/bin1"},
347 reciprocal{},
348 },
Colin Crossbb45f8c2022-01-28 15:18:19 -0800349 expectedDeps: []string{
350 "testdata/firstparty/FIRST_PARTY_LICENSE",
351 "testdata/reciprocal/RECIPROCAL_LICENSE",
352 "testdata/restricted/RESTRICTED_LICENSE",
353 },
Bob Badoure6fdd142021-12-09 22:10:43 -0800354 },
355 {
356 condition: "restricted",
357 name: "container",
358 roots: []string{"container.zip.meta_lic"},
359 expectedOut: []matcher{
360 hr{},
361 library{"Android"},
362 usedBy{"container.zip"},
363 usedBy{"container.zip/bin1"},
364 usedBy{"container.zip/bin2"},
365 firstParty{},
366 hr{},
367 library{"Android"},
368 usedBy{"container.zip/bin2"},
369 usedBy{"container.zip/libb.so"},
370 library{"Device"},
371 usedBy{"container.zip/bin1"},
372 usedBy{"container.zip/liba.so"},
373 restricted{},
374 hr{},
375 library{"External"},
376 usedBy{"container.zip/bin1"},
377 reciprocal{},
378 },
Colin Crossbb45f8c2022-01-28 15:18:19 -0800379 expectedDeps: []string{
380 "testdata/firstparty/FIRST_PARTY_LICENSE",
381 "testdata/reciprocal/RECIPROCAL_LICENSE",
382 "testdata/restricted/RESTRICTED_LICENSE",
383 },
Bob Badoure6fdd142021-12-09 22:10:43 -0800384 },
385 {
386 condition: "restricted",
387 name: "application",
388 roots: []string{"application.meta_lic"},
389 expectedOut: []matcher{
390 hr{},
391 library{"Android"},
392 usedBy{"application"},
393 firstParty{},
394 hr{},
395 library{"Device"},
396 usedBy{"application"},
397 restricted{},
398 },
Colin Crossbb45f8c2022-01-28 15:18:19 -0800399 expectedDeps: []string{
400 "testdata/firstparty/FIRST_PARTY_LICENSE",
401 "testdata/restricted/RESTRICTED_LICENSE",
402 },
Bob Badoure6fdd142021-12-09 22:10:43 -0800403 },
404 {
405 condition: "restricted",
406 name: "binary",
407 roots: []string{"bin/bin1.meta_lic"},
408 expectedOut: []matcher{
409 hr{},
410 library{"Android"},
411 usedBy{"bin/bin1"},
412 firstParty{},
413 hr{},
414 library{"Device"},
415 usedBy{"bin/bin1"},
416 restricted{},
417 hr{},
418 library{"External"},
419 usedBy{"bin/bin1"},
420 reciprocal{},
421 },
Colin Crossbb45f8c2022-01-28 15:18:19 -0800422 expectedDeps: []string{
423 "testdata/firstparty/FIRST_PARTY_LICENSE",
424 "testdata/reciprocal/RECIPROCAL_LICENSE",
425 "testdata/restricted/RESTRICTED_LICENSE",
426 },
Bob Badoure6fdd142021-12-09 22:10:43 -0800427 },
428 {
429 condition: "restricted",
430 name: "library",
431 roots: []string{"lib/libd.so.meta_lic"},
432 expectedOut: []matcher{
433 hr{},
434 library{"External"},
435 usedBy{"lib/libd.so"},
436 notice{},
437 },
Colin Crossbb45f8c2022-01-28 15:18:19 -0800438 expectedDeps: []string{"testdata/notice/NOTICE_LICENSE"},
Bob Badoure6fdd142021-12-09 22:10:43 -0800439 },
440 {
441 condition: "proprietary",
442 name: "apex",
443 roots: []string{"highest.apex.meta_lic"},
444 expectedOut: []matcher{
445 hr{},
446 library{"Android"},
447 usedBy{"highest.apex/bin/bin2"},
448 usedBy{"highest.apex/lib/libb.so"},
449 restricted{},
450 hr{},
451 library{"Android"},
452 usedBy{"highest.apex"},
453 usedBy{"highest.apex/bin/bin1"},
454 firstParty{},
455 hr{},
456 library{"Android"},
457 usedBy{"highest.apex/bin/bin2"},
458 library{"Device"},
459 usedBy{"highest.apex/bin/bin1"},
460 usedBy{"highest.apex/lib/liba.so"},
461 library{"External"},
462 usedBy{"highest.apex/bin/bin1"},
463 proprietary{},
464 },
Colin Crossbb45f8c2022-01-28 15:18:19 -0800465 expectedDeps: []string{
466 "testdata/firstparty/FIRST_PARTY_LICENSE",
467 "testdata/proprietary/PROPRIETARY_LICENSE",
468 "testdata/restricted/RESTRICTED_LICENSE",
469 },
Bob Badoure6fdd142021-12-09 22:10:43 -0800470 },
471 {
472 condition: "proprietary",
473 name: "container",
474 roots: []string{"container.zip.meta_lic"},
475 expectedOut: []matcher{
476 hr{},
477 library{"Android"},
478 usedBy{"container.zip/bin2"},
479 usedBy{"container.zip/libb.so"},
480 restricted{},
481 hr{},
482 library{"Android"},
483 usedBy{"container.zip"},
484 usedBy{"container.zip/bin1"},
485 firstParty{},
486 hr{},
487 library{"Android"},
488 usedBy{"container.zip/bin2"},
489 library{"Device"},
490 usedBy{"container.zip/bin1"},
491 usedBy{"container.zip/liba.so"},
492 library{"External"},
493 usedBy{"container.zip/bin1"},
494 proprietary{},
495 },
Colin Crossbb45f8c2022-01-28 15:18:19 -0800496 expectedDeps: []string{
497 "testdata/firstparty/FIRST_PARTY_LICENSE",
498 "testdata/proprietary/PROPRIETARY_LICENSE",
499 "testdata/restricted/RESTRICTED_LICENSE",
500 },
Bob Badoure6fdd142021-12-09 22:10:43 -0800501 },
502 {
503 condition: "proprietary",
504 name: "application",
505 roots: []string{"application.meta_lic"},
506 expectedOut: []matcher{
507 hr{},
508 library{"Android"},
509 usedBy{"application"},
510 firstParty{},
511 hr{},
512 library{"Device"},
513 usedBy{"application"},
514 proprietary{},
515 },
Colin Crossbb45f8c2022-01-28 15:18:19 -0800516 expectedDeps: []string{
517 "testdata/firstparty/FIRST_PARTY_LICENSE",
518 "testdata/proprietary/PROPRIETARY_LICENSE",
519 },
Bob Badoure6fdd142021-12-09 22:10:43 -0800520 },
521 {
522 condition: "proprietary",
523 name: "binary",
524 roots: []string{"bin/bin1.meta_lic"},
525 expectedOut: []matcher{
526 hr{},
527 library{"Android"},
528 usedBy{"bin/bin1"},
529 firstParty{},
530 hr{},
531 library{"Device"},
532 usedBy{"bin/bin1"},
533 library{"External"},
534 usedBy{"bin/bin1"},
535 proprietary{},
536 },
Colin Crossbb45f8c2022-01-28 15:18:19 -0800537 expectedDeps: []string{
538 "testdata/firstparty/FIRST_PARTY_LICENSE",
539 "testdata/proprietary/PROPRIETARY_LICENSE",
540 },
Bob Badoure6fdd142021-12-09 22:10:43 -0800541 },
542 {
543 condition: "proprietary",
544 name: "library",
545 roots: []string{"lib/libd.so.meta_lic"},
546 expectedOut: []matcher{
547 hr{},
548 library{"External"},
549 usedBy{"lib/libd.so"},
550 notice{},
551 },
Colin Crossbb45f8c2022-01-28 15:18:19 -0800552 expectedDeps: []string{"testdata/notice/NOTICE_LICENSE"},
Bob Badoure6fdd142021-12-09 22:10:43 -0800553 },
554 }
555 for _, tt := range tests {
556 t.Run(tt.condition+" "+tt.name, func(t *testing.T) {
557 stdout := &bytes.Buffer{}
558 stderr := &bytes.Buffer{}
559
560 rootFiles := make([]string, 0, len(tt.roots))
561 for _, r := range tt.roots {
562 rootFiles = append(rootFiles, "testdata/"+tt.condition+"/"+r)
563 }
564
Colin Crossbb45f8c2022-01-28 15:18:19 -0800565 var deps []string
566
Bob Badour49dd4f72022-02-04 14:49:01 -0800567 ctx := context{stdout, stderr, os.DirFS("."), "", []string{tt.stripPrefix}, "", &deps}
Bob Badoure6fdd142021-12-09 22:10:43 -0800568
569 err := textNotice(&ctx, rootFiles...)
570 if err != nil {
Colin Cross179ec3e2022-01-27 15:47:09 -0800571 t.Fatalf("textnotice: error = %v, stderr = %v", err, stderr)
Bob Badoure6fdd142021-12-09 22:10:43 -0800572 return
573 }
574 if stderr.Len() > 0 {
575 t.Errorf("textnotice: gotStderr = %v, want none", stderr)
576 }
577
578 t.Logf("got stdout: %s", stdout.String())
579
580 t.Logf("want stdout: %s", matcherList(tt.expectedOut).String())
581
582 out := bufio.NewScanner(stdout)
583 lineno := 0
584 for out.Scan() {
585 line := out.Text()
586 if strings.TrimLeft(line, " ") == "" {
587 continue
588 }
589 if len(tt.expectedOut) <= lineno {
590 t.Errorf("unexpected output at line %d: got %q, want nothing (wanted %d lines)", lineno+1, line, len(tt.expectedOut))
591 } else if !tt.expectedOut[lineno].isMatch(line) {
592 t.Errorf("unexpected output at line %d: got %q, want %q", lineno+1, line, tt.expectedOut[lineno].String())
593 }
594 lineno++
595 }
596 for ; lineno < len(tt.expectedOut); lineno++ {
597 t.Errorf("textnotice: missing output line %d: ended early, want %q", lineno+1, tt.expectedOut[lineno].String())
598 }
Colin Crossbb45f8c2022-01-28 15:18:19 -0800599
600 t.Logf("got deps: %q", deps)
601
602 t.Logf("want deps: %q", tt.expectedDeps)
603
604 if g, w := deps, tt.expectedDeps; !reflect.DeepEqual(g, w) {
605 t.Errorf("unexpected deps, wanted:\n%s\ngot:\n%s\n",
606 strings.Join(w, "\n"), strings.Join(g, "\n"))
607 }
Bob Badoure6fdd142021-12-09 22:10:43 -0800608 })
609 }
610}
611
612type matcher interface {
613 isMatch(line string) bool
614 String() string
615}
616
617type hr struct{}
618
619func (m hr) isMatch(line string) bool {
620 return horizontalRule.MatchString(line)
621}
622
623func (m hr) String() string {
624 return " ================================================== "
625}
626
627type library struct {
628 name string
629}
630
631func (m library) isMatch(line string) bool {
632 return strings.HasPrefix(line, m.name+" ")
633}
634
635func (m library) String() string {
636 return m.name + " used by:"
637}
638
639type usedBy struct {
640 name string
641}
642
643func (m usedBy) isMatch(line string) bool {
644 return len(line) > 0 && line[0] == ' ' && strings.HasPrefix(strings.TrimLeft(line, " "), "out/") && strings.HasSuffix(line, "/"+m.name)
645}
646
647func (m usedBy) String() string {
648 return " out/.../" + m.name
649}
650
651type firstParty struct{}
652
653func (m firstParty) isMatch(line string) bool {
654 return strings.HasPrefix(strings.TrimLeft(line, " "), "&&&First Party License&&&")
655}
656
657func (m firstParty) String() string {
658 return "&&&First Party License&&&"
659}
660
661type notice struct{}
662
663func (m notice) isMatch(line string) bool {
664 return strings.HasPrefix(strings.TrimLeft(line, " "), "%%%Notice License%%%")
665}
666
667func (m notice) String() string {
668 return "%%%Notice License%%%"
669}
670
671type reciprocal struct{}
672
673func (m reciprocal) isMatch(line string) bool {
674 return strings.HasPrefix(strings.TrimLeft(line, " "), "$$$Reciprocal License$$$")
675}
676
677func (m reciprocal) String() string {
678 return "$$$Reciprocal License$$$"
679}
680
681type restricted struct{}
682
683func (m restricted) isMatch(line string) bool {
684 return strings.HasPrefix(strings.TrimLeft(line, " "), "###Restricted License###")
685}
686
687func (m restricted) String() string {
688 return "###Restricted License###"
689}
690
691type proprietary struct{}
692
693func (m proprietary) isMatch(line string) bool {
694 return strings.HasPrefix(strings.TrimLeft(line, " "), "@@@Proprietary License@@@")
695}
696
697func (m proprietary) String() string {
698 return "@@@Proprietary License@@@"
699}
700
701type matcherList []matcher
702
703func (l matcherList) String() string {
704 var sb strings.Builder
705 for _, m := range l {
706 s := m.String()
707 if s[:3] == s[len(s)-3:] {
708 fmt.Fprintln(&sb)
709 }
710 fmt.Fprintf(&sb, "%s\n", s)
711 if s[:3] == s[len(s)-3:] {
712 fmt.Fprintln(&sb)
713 }
714 }
715 return sb.String()
716}