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