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  }