github.com/anchore/syft@v1.4.2-0.20240516191711-1bec1fc5d397/syft/pkg/cataloger/golang/licenses_test.go (about) 1 package golang 2 3 import ( 4 "archive/zip" 5 "bytes" 6 "fmt" 7 "net/http" 8 "net/http/httptest" 9 "os" 10 "path" 11 "strings" 12 "testing" 13 14 "github.com/stretchr/testify/require" 15 16 "github.com/anchore/syft/syft/file" 17 "github.com/anchore/syft/syft/internal/fileresolver" 18 "github.com/anchore/syft/syft/license" 19 "github.com/anchore/syft/syft/pkg" 20 ) 21 22 func Test_LocalLicenseSearch(t *testing.T) { 23 loc1 := file.NewLocation("github.com/someorg/somename@v0.3.2/LICENSE") 24 loc2 := file.NewLocation("github.com/!cap!o!r!g/!cap!project@v4.111.5/LICENSE.txt") 25 loc3 := file.NewLocation("github.com/someorg/strangelicense@v1.2.3/LiCeNsE.tXt") 26 27 tests := []struct { 28 name string 29 version string 30 expected pkg.License 31 }{ 32 { 33 name: "github.com/someorg/somename", 34 version: "v0.3.2", 35 expected: pkg.License{ 36 Value: "Apache-2.0", 37 SPDXExpression: "Apache-2.0", 38 Type: license.Concluded, 39 Locations: file.NewLocationSet(loc1), 40 }, 41 }, 42 { 43 name: "github.com/CapORG/CapProject", 44 version: "v4.111.5", 45 expected: pkg.License{ 46 Value: "MIT", 47 SPDXExpression: "MIT", 48 Type: license.Concluded, 49 Locations: file.NewLocationSet(loc2), 50 }, 51 }, 52 { 53 name: "github.com/someorg/strangelicense", 54 version: "v1.2.3", 55 expected: pkg.License{ 56 Value: "Apache-2.0", 57 SPDXExpression: "Apache-2.0", 58 Type: license.Concluded, 59 Locations: file.NewLocationSet(loc3), 60 }, 61 }, 62 } 63 64 wd, err := os.Getwd() 65 require.NoError(t, err) 66 67 for _, test := range tests { 68 t.Run(test.name, func(t *testing.T) { 69 l := newGoLicenses( 70 "", 71 CatalogerConfig{ 72 SearchLocalModCacheLicenses: true, 73 LocalModCacheDir: path.Join(wd, "test-fixtures", "licenses", "pkg", "mod"), 74 }, 75 ) 76 licenses, err := l.getLicenses(fileresolver.Empty{}, test.name, test.version) 77 require.NoError(t, err) 78 79 require.Len(t, licenses, 1) 80 81 require.Equal(t, test.expected, licenses[0]) 82 }) 83 } 84 } 85 86 func Test_RemoteProxyLicenseSearch(t *testing.T) { 87 loc1 := file.NewLocation("github.com/someorg/somename@v0.3.2/LICENSE") 88 loc2 := file.NewLocation("github.com/!cap!o!r!g/!cap!project@v4.111.5/LICENSE.txt") 89 90 server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 91 buf := &bytes.Buffer{} 92 uri := strings.TrimPrefix(strings.TrimSuffix(r.RequestURI, ".zip"), "/") 93 94 parts := strings.Split(uri, "/@v/") 95 modPath := parts[0] 96 modVersion := parts[1] 97 98 wd, err := os.Getwd() 99 require.NoError(t, err) 100 testDir := path.Join(wd, "test-fixtures", "licenses", "pkg", "mod", processCaps(modPath)+"@"+modVersion) 101 102 archive := zip.NewWriter(buf) 103 104 entries, err := os.ReadDir(testDir) 105 require.NoError(t, err) 106 for _, f := range entries { 107 // the zip files downloaded contain a path to the repo that somewhat matches where it ends up on disk, 108 // so prefix entries with something similar 109 writer, err := archive.Create(path.Join("github.com/something/some@version", f.Name())) 110 require.NoError(t, err) 111 contents, err := os.ReadFile(path.Join(testDir, f.Name())) 112 require.NoError(t, err) 113 _, err = writer.Write(contents) 114 require.NoError(t, err) 115 } 116 117 err = archive.Close() 118 require.NoError(t, err) 119 120 w.Header().Add("Content-Length", fmt.Sprintf("%d", buf.Len())) 121 122 _, err = w.Write(buf.Bytes()) 123 require.NoError(t, err) 124 })) 125 defer server.Close() 126 127 tests := []struct { 128 name string 129 version string 130 expected pkg.License 131 }{ 132 { 133 name: "github.com/someorg/somename", 134 version: "v0.3.2", 135 expected: pkg.License{ 136 Value: "Apache-2.0", 137 SPDXExpression: "Apache-2.0", 138 Type: license.Concluded, 139 Locations: file.NewLocationSet(loc1), 140 }, 141 }, 142 { 143 name: "github.com/CapORG/CapProject", 144 version: "v4.111.5", 145 expected: pkg.License{ 146 Value: "MIT", 147 SPDXExpression: "MIT", 148 Type: license.Concluded, 149 Locations: file.NewLocationSet(loc2), 150 }, 151 }, 152 } 153 154 modDir := path.Join(t.TempDir()) 155 156 for _, test := range tests { 157 t.Run(test.name, func(t *testing.T) { 158 l := newGoLicenses( 159 "", 160 CatalogerConfig{ 161 SearchRemoteLicenses: true, 162 Proxies: []string{server.URL}, 163 LocalModCacheDir: modDir, 164 }, 165 ) 166 167 licenses, err := l.getLicenses(fileresolver.Empty{}, test.name, test.version) 168 require.NoError(t, err) 169 170 require.Len(t, licenses, 1) 171 172 require.Equal(t, test.expected, licenses[0]) 173 }) 174 } 175 } 176 177 func Test_processCaps(t *testing.T) { 178 tests := []struct { 179 name string 180 expected string 181 }{ 182 { 183 name: "CycloneDX", 184 expected: "!cyclone!d!x", 185 }, 186 { 187 name: "Azure", 188 expected: "!azure", 189 }, 190 { 191 name: "xkcd", 192 expected: "xkcd", 193 }, 194 } 195 196 for _, test := range tests { 197 t.Run(test.name, func(t *testing.T) { 198 got := processCaps(test.name) 199 200 require.Equal(t, test.expected, got) 201 }) 202 } 203 } 204 205 func Test_remotesForModule(t *testing.T) { 206 allProxies := []string{"https://somewhere.org", "direct"} 207 directProxy := []string{"direct"} 208 209 tests := []struct { 210 module string 211 noProxy string 212 expected []string 213 }{ 214 { 215 module: "github.com/anchore/syft", 216 expected: allProxies, 217 }, 218 { 219 module: "github.com/anchore/sbom-action", 220 noProxy: "*/anchore/*", 221 expected: directProxy, 222 }, 223 { 224 module: "github.com/anchore/sbom-action", 225 noProxy: "*/user/mod,*/anchore/sbom-action", 226 expected: directProxy, 227 }, 228 } 229 230 for _, test := range tests { 231 t.Run(test.module, func(t *testing.T) { 232 got := remotesForModule(allProxies, strings.Split(test.noProxy, ","), test.module) 233 require.Equal(t, test.expected, got) 234 }) 235 } 236 } 237 238 func Test_findVersionPath(t *testing.T) { 239 f := os.DirFS("test-fixtures/zip-fs") 240 vp := findVersionPath(f, ".") 241 require.Equal(t, "github.com/someorg/somepkg@version", vp) 242 }