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