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