oficina / estilo Public

Clone
git clone https://amadan.net/oficina/estilo

Plain git — no account needed to clone.

Download

Download this file

1package catalog
2
3import (
4 "bytes"
5 "encoding/json"
6 "os"
7 "path/filepath"
8 "strings"
9 "testing"
10)
11
12func moduleFixture(t *testing.T, name string) *Module {
13 t.Helper()
14 root := t.TempDir()
15 if err := os.MkdirAll(filepath.Join(root, "vendorpart", "pkg"), 0700); err != nil {
16 t.Fatal(err)
17 }
18 for path, text := range map[string]string{"LICENSE": "Root copyright\nPermission retained.\n", "LICENSE-3RD-PARTY.md": "Additional copyright\n", "vendorpart/LICENSE": "Nested copyright\n", "vendorpart/pkg/not-license.go": "package pkg"} {
19 if err := os.WriteFile(filepath.Join(root, path), []byte(text), 0600); err != nil {
20 t.Fatal(err)
21 }
22 }
23 return &Module{Path: name, Version: "v1.2.3", Dir: root}
24}
25func encodePackages(t *testing.T, packages ...Package) *bytes.Buffer {
26 t.Helper()
27 var out bytes.Buffer
28 for _, p := range packages {
29 if err := json.NewEncoder(&out).Encode(p); err != nil {
30 t.Fatal(err)
31 }
32 }
33 return &out
34}
35func TestCollectIncludesNestedAndBundledNoticesOnce(t *testing.T) {
36 m := moduleFixture(t, "example.org/component")
37 packages := []Package{{Dir: filepath.Join(m.Dir, "vendorpart", "pkg"), Module: m}, {Dir: m.Dir, Module: m}, {Dir: filepath.Join(m.Dir, "vendorpart"), Module: m}}
38 got, err := Collect(encodePackages(t, packages...), nil)
39 if err != nil {
40 t.Fatal(err)
41 }
42 if len(got.Components) != 1 || len(got.MissingNotices) != 0 {
43 t.Fatal("wrong dependency inventory")
44 }
45 c := got.Components[0]
46 if len(c.Notices) != 3 {
47 t.Fatalf("notices=%d, want root, bundled and nested", len(c.Notices))
48 }
49 if c.Notices[0].Name != "LICENSE" || c.Notices[0].Text != "Root copyright\nPermission retained.\n" || c.Notices[2].Name != "vendorpart/LICENSE" {
50 t.Fatal("notice path, ordering or original bytes changed")
51 }
52 again, err := Collect(encodePackages(t, packages[2], packages[0], packages[1]), nil)
53 if err != nil {
54 t.Fatal(err)
55 }
56 a, _ := json.Marshal(got)
57 b, _ := json.Marshal(again)
58 if !bytes.Equal(a, b) {
59 t.Fatal("inventory depends on package order")
60 }
61}
62func TestCollectReportsMissingAndExcludesOnlyExplicitModules(t *testing.T) {
63 m := &Module{Path: "example.org/missing", Version: "v2.0.0", Dir: t.TempDir()}
64 owned := moduleFixture(t, "example.org/owned")
65 main := &Module{Main: true, Dir: t.TempDir()}
66 got, err := Collect(encodePackages(t, Package{Dir: m.Dir, Module: m}, Package{Dir: owned.Dir, Module: owned}, Package{Dir: main.Dir, Module: main}), map[string]bool{owned.Path: true})
67 if err != nil {
68 t.Fatal(err)
69 }
70 if len(got.Components) != 1 || len(got.MissingNotices) != 1 || got.MissingNotices[0] != m.Path {
71 t.Fatal("missing notice silently dropped")
72 }
73}
74func TestCollectRefusesUnverifiableProvenance(t *testing.T) {
75 for _, mode := range []string{"outside", "replacement", "missing-version", "symlink", "package-error"} {
76 t.Run(mode, func(t *testing.T) {
77 m := moduleFixture(t, "example.org/component")
78 p := Package{Dir: m.Dir, Module: m}
79 switch mode {
80 case "outside":
81 p.Dir = t.TempDir()
82 case "replacement":
83 m.Replace = &Module{Dir: t.TempDir()}
84 case "missing-version":
85 m.Version = ""
86 case "symlink":
87 if err := os.Symlink(filepath.Join(m.Dir, "LICENSE"), filepath.Join(m.Dir, "NOTICE")); err != nil {
88 t.Fatal(err)
89 }
90 case "package-error":
91 p.Error = &struct{ Err string }{Err: "failed"}
92 }
93 if _, err := Collect(encodePackages(t, p), nil); err == nil {
94 t.Fatal("unverifiable package accepted")
95 }
96 })
97 }
98 if _, err := Collect(strings.NewReader(`{"Module":`), nil); err == nil {
99 t.Fatal("truncated package stream accepted")
100 }
101}
102
103func TestCollectSkipsSourceAndDirectoriesButRetainsNotices(t *testing.T) {
104 m := moduleFixture(t, "example.org/component")
105 for _, name := range []string{"license.go", "NOTICE_test.go", "NOTICE.go"} {
106 if err := os.WriteFile(filepath.Join(m.Dir, name), []byte("package example"), 0600); err != nil {
107 t.Fatal(err)
108 }
109 }
110 if err := os.Mkdir(filepath.Join(m.Dir, "license-tool"), 0700); err != nil {
111 t.Fatal(err)
112 }
113 got, err := Collect(encodePackages(t, Package{Dir: m.Dir, Module: m}), nil)
114 if err != nil {
115 t.Fatal(err)
116 }
117 if len(got.Components) != 1 || len(got.Components[0].Notices) != 2 {
118 t.Fatal("source or directory was collected as notice", got)
119 }
120 if err := os.WriteFile(filepath.Join(m.Dir, "NOTICE"), []byte(" \n\t"), 0600); err != nil {
121 t.Fatal(err)
122 }
123 if _, err := Collect(encodePackages(t, Package{Dir: m.Dir, Module: m}), nil); err == nil {
124 t.Fatal("blank notice accepted")
125 }
126}
127