github.com/anchore/syft@v1.4.2-0.20240516191711-1bec1fc5d397/syft/pkg/cataloger/javascript/parse_package_lock_test.go (about)

     1  package javascript
     2  
     3  import (
     4  	"testing"
     5  
     6  	"github.com/anchore/syft/syft/artifact"
     7  	"github.com/anchore/syft/syft/file"
     8  	"github.com/anchore/syft/syft/pkg"
     9  	"github.com/anchore/syft/syft/pkg/cataloger/internal/pkgtest"
    10  )
    11  
    12  func TestParsePackageLock(t *testing.T) {
    13  	var expectedRelationships []artifact.Relationship
    14  	expectedPkgs := []pkg.Package{
    15  		{
    16  			Name:     "@actions/core",
    17  			Version:  "1.6.0",
    18  			PURL:     "pkg:npm/%40actions/core@1.6.0",
    19  			Language: pkg.JavaScript,
    20  			Type:     pkg.NpmPkg,
    21  			Metadata: pkg.NpmPackageLockEntry{Resolved: "https://registry.npmjs.org/@actions/core/-/core-1.6.0.tgz", Integrity: "sha512-NB1UAZomZlCV/LmJqkLhNTqtKfFXJZAUPcfl/zqG7EfsQdeUJtaWO98SGbuQ3pydJ3fHl2CvI/51OKYlCYYcaw=="},
    22  		},
    23  		{
    24  			Name:     "ansi-regex",
    25  			Version:  "3.0.0",
    26  			PURL:     "pkg:npm/ansi-regex@3.0.0",
    27  			Language: pkg.JavaScript,
    28  			Type:     pkg.NpmPkg,
    29  			Metadata: pkg.NpmPackageLockEntry{Resolved: "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", Integrity: "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg="},
    30  		},
    31  		{
    32  			Name:     "cowsay",
    33  			Version:  "1.4.0",
    34  			PURL:     "pkg:npm/cowsay@1.4.0",
    35  			Language: pkg.JavaScript,
    36  			Type:     pkg.NpmPkg,
    37  			Metadata: pkg.NpmPackageLockEntry{Resolved: "https://registry.npmjs.org/cowsay/-/cowsay-1.4.0.tgz", Integrity: "sha512-rdg5k5PsHFVJheO/pmE3aDg2rUDDTfPJau6yYkZYlHFktUz+UxbE+IgnUAEyyCyv4noL5ltxXD0gZzmHPCy/9g=="},
    38  		},
    39  		{
    40  			Name:     "get-stdin",
    41  			Version:  "5.0.1",
    42  			PURL:     "pkg:npm/get-stdin@5.0.1",
    43  			Language: pkg.JavaScript,
    44  			Type:     pkg.NpmPkg,
    45  			Metadata: pkg.NpmPackageLockEntry{Resolved: "https://registry.npmjs.org/get-stdin/-/get-stdin-5.0.1.tgz", Integrity: "sha1-Ei4WFZHiH/TFJTAwVpPyDmOTo5g="},
    46  		},
    47  		{
    48  			Name:     "is-fullwidth-code-point",
    49  			Version:  "2.0.0",
    50  			PURL:     "pkg:npm/is-fullwidth-code-point@2.0.0",
    51  			Language: pkg.JavaScript,
    52  			Type:     pkg.NpmPkg,
    53  			Metadata: pkg.NpmPackageLockEntry{Resolved: "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", Integrity: "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8="},
    54  		},
    55  		{
    56  			Name:     "minimist",
    57  			Version:  "0.0.10",
    58  			PURL:     "pkg:npm/minimist@0.0.10",
    59  			Language: pkg.JavaScript,
    60  			Type:     pkg.NpmPkg,
    61  			Metadata: pkg.NpmPackageLockEntry{Resolved: "https://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz", Integrity: "sha1-3j+YVD2/lggr5IrRoMfNqDYwHc8="},
    62  		},
    63  		{
    64  			Name:     "optimist",
    65  			Version:  "0.6.1",
    66  			PURL:     "pkg:npm/optimist@0.6.1",
    67  			Language: pkg.JavaScript,
    68  			Type:     pkg.NpmPkg,
    69  			Metadata: pkg.NpmPackageLockEntry{Resolved: "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", Integrity: "sha1-2j6nRob6IaGaERwybpDrFaAZZoY="},
    70  		},
    71  		{
    72  			Name:     "string-width",
    73  			Version:  "2.1.1",
    74  			PURL:     "pkg:npm/string-width@2.1.1",
    75  			Language: pkg.JavaScript,
    76  			Type:     pkg.NpmPkg,
    77  			Metadata: pkg.NpmPackageLockEntry{Resolved: "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", Integrity: "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw=="},
    78  		},
    79  		{
    80  			Name:     "strip-ansi",
    81  			Version:  "4.0.0",
    82  			PURL:     "pkg:npm/strip-ansi@4.0.0",
    83  			Language: pkg.JavaScript,
    84  			Type:     pkg.NpmPkg,
    85  			Metadata: pkg.NpmPackageLockEntry{Resolved: "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", Integrity: "sha1-qEeQIusaw2iocTibY1JixQXuNo8="},
    86  		},
    87  		{
    88  			Name:     "strip-eof",
    89  			Version:  "1.0.0",
    90  			PURL:     "pkg:npm/strip-eof@1.0.0",
    91  			Language: pkg.JavaScript,
    92  			Type:     pkg.NpmPkg,
    93  			Metadata: pkg.NpmPackageLockEntry{Resolved: "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", Integrity: "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8="},
    94  		},
    95  		{
    96  			Name:     "wordwrap",
    97  			Version:  "0.0.3",
    98  			PURL:     "pkg:npm/wordwrap@0.0.3",
    99  			Language: pkg.JavaScript,
   100  			Type:     pkg.NpmPkg,
   101  			Metadata: pkg.NpmPackageLockEntry{Resolved: "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz", Integrity: "sha1-o9XabNXAvAAI03I0u68b7WMFkQc="},
   102  		},
   103  	}
   104  	fixture := "test-fixtures/pkg-lock/package-lock.json"
   105  	for i := range expectedPkgs {
   106  		expectedPkgs[i].Locations.Add(file.NewLocation(fixture))
   107  	}
   108  
   109  	adapter := newGenericPackageLockAdapter(CatalogerConfig{})
   110  	pkgtest.TestFileParser(t, fixture, adapter.parsePackageLock, expectedPkgs, expectedRelationships)
   111  }
   112  
   113  func TestParsePackageLockV2(t *testing.T) {
   114  	fixture := "test-fixtures/pkg-lock/package-lock-2.json"
   115  	var expectedRelationships []artifact.Relationship
   116  	expectedPkgs := []pkg.Package{
   117  		{
   118  			Name:     "npm",
   119  			Version:  "6.14.6",
   120  			Language: pkg.JavaScript,
   121  			Type:     pkg.NpmPkg,
   122  			PURL:     "pkg:npm/npm@6.14.6",
   123  			Metadata: pkg.NpmPackageLockEntry{},
   124  		},
   125  		{
   126  			Name:     "@types/prop-types",
   127  			Version:  "15.7.5",
   128  			PURL:     "pkg:npm/%40types/prop-types@15.7.5",
   129  			Language: pkg.JavaScript,
   130  			Type:     pkg.NpmPkg,
   131  			Licenses: pkg.NewLicenseSet(
   132  				pkg.NewLicenseFromLocations("MIT", file.NewLocation(fixture)),
   133  			),
   134  			Metadata: pkg.NpmPackageLockEntry{Resolved: "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.5.tgz", Integrity: "sha1-XxnSuFqY6VWANvajysyIGUIPBc8="},
   135  		},
   136  		{
   137  			Name:     "@types/react",
   138  			Version:  "18.0.17",
   139  			PURL:     "pkg:npm/%40types/react@18.0.17",
   140  			Language: pkg.JavaScript,
   141  			Type:     pkg.NpmPkg,
   142  			Licenses: pkg.NewLicenseSet(
   143  				pkg.NewLicenseFromLocations("MIT", file.NewLocation(fixture)),
   144  			),
   145  			Metadata: pkg.NpmPackageLockEntry{Resolved: "https://registry.npmjs.org/@types/react/-/react-18.0.17.tgz", Integrity: "sha1-RYPZwyLWfv5LOak10iPtzHBQzPQ="},
   146  		},
   147  		{
   148  			Name:     "@types/scheduler",
   149  			Version:  "0.16.2",
   150  			PURL:     "pkg:npm/%40types/scheduler@0.16.2",
   151  			Language: pkg.JavaScript,
   152  			Type:     pkg.NpmPkg,
   153  			Licenses: pkg.NewLicenseSet(
   154  				pkg.NewLicenseFromLocations("MIT", file.NewLocation(fixture)),
   155  			),
   156  			Metadata: pkg.NpmPackageLockEntry{Resolved: "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.2.tgz", Integrity: "sha1-GmL4lSVyPd4kuhsBsJK/XfitTTk="},
   157  		},
   158  		{
   159  			Name:     "csstype",
   160  			Version:  "3.1.0",
   161  			PURL:     "pkg:npm/csstype@3.1.0",
   162  			Language: pkg.JavaScript,
   163  			Type:     pkg.NpmPkg,
   164  			Licenses: pkg.NewLicenseSet(
   165  				pkg.NewLicenseFromLocations("MIT", file.NewLocation(fixture)),
   166  			),
   167  			Metadata: pkg.NpmPackageLockEntry{Resolved: "https://registry.npmjs.org/csstype/-/csstype-3.1.0.tgz", Integrity: "sha1-TdysNxjXh8+d8NG30VAzklyPKfI="},
   168  		},
   169  	}
   170  	for i := range expectedPkgs {
   171  		expectedPkgs[i].Locations.Add(file.NewLocation(fixture))
   172  	}
   173  	adapter := newGenericPackageLockAdapter(CatalogerConfig{})
   174  	pkgtest.TestFileParser(t, fixture, adapter.parsePackageLock, expectedPkgs, expectedRelationships)
   175  }
   176  
   177  func TestParsePackageLockV3(t *testing.T) {
   178  	fixture := "test-fixtures/pkg-lock/package-lock-3.json"
   179  	var expectedRelationships []artifact.Relationship
   180  	expectedPkgs := []pkg.Package{
   181  		{
   182  			Name:     "lock-v3-fixture",
   183  			Version:  "1.0.0",
   184  			Language: pkg.JavaScript,
   185  			Type:     pkg.NpmPkg,
   186  			PURL:     "pkg:npm/lock-v3-fixture@1.0.0",
   187  			Metadata: pkg.NpmPackageLockEntry{},
   188  		},
   189  		{
   190  			Name:     "@types/prop-types",
   191  			Version:  "15.7.5",
   192  			Language: pkg.JavaScript,
   193  			Type:     pkg.NpmPkg,
   194  			PURL:     "pkg:npm/%40types/prop-types@15.7.5",
   195  			Metadata: pkg.NpmPackageLockEntry{Resolved: "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.5.tgz", Integrity: "sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w=="},
   196  		},
   197  		{
   198  			Name:     "@types/react",
   199  			Version:  "18.0.20",
   200  			Language: pkg.JavaScript,
   201  			Type:     pkg.NpmPkg,
   202  			PURL:     "pkg:npm/%40types/react@18.0.20",
   203  			Metadata: pkg.NpmPackageLockEntry{Resolved: "https://registry.npmjs.org/@types/react/-/react-18.0.20.tgz", Integrity: "sha512-MWul1teSPxujEHVwZl4a5HxQ9vVNsjTchVA+xRqv/VYGCuKGAU6UhfrTdF5aBefwD1BHUD8i/zq+O/vyCm/FrA=="},
   204  		},
   205  		{
   206  			Name:     "@types/scheduler",
   207  			Version:  "0.16.2",
   208  			Language: pkg.JavaScript,
   209  			Type:     pkg.NpmPkg,
   210  			PURL:     "pkg:npm/%40types/scheduler@0.16.2",
   211  			Metadata: pkg.NpmPackageLockEntry{Resolved: "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.2.tgz", Integrity: "sha512-hppQEBDmlwhFAXKJX2KnWLYu5yMfi91yazPb2l+lbJiwW+wdo1gNeRA+3RgNSO39WYX2euey41KEwnqesU2Jew=="},
   212  		},
   213  		{
   214  			Name:     "csstype",
   215  			Version:  "3.1.1",
   216  			Language: pkg.JavaScript,
   217  			Type:     pkg.NpmPkg,
   218  			PURL:     "pkg:npm/csstype@3.1.1",
   219  			Metadata: pkg.NpmPackageLockEntry{Resolved: "https://registry.npmjs.org/csstype/-/csstype-3.1.1.tgz", Integrity: "sha512-DJR/VvkAvSZW9bTouZue2sSxDwdTN92uHjqeKVm+0dAqdfNykRzQ95tay8aXMBAAPpUiq4Qcug2L7neoRh2Egw=="},
   220  		},
   221  	}
   222  	for i := range expectedPkgs {
   223  		expectedPkgs[i].Locations.Add(file.NewLocation(fixture))
   224  	}
   225  	adapter := newGenericPackageLockAdapter(CatalogerConfig{})
   226  	pkgtest.TestFileParser(t, fixture, adapter.parsePackageLock, expectedPkgs, expectedRelationships)
   227  }
   228  
   229  func TestParsePackageLockAlias(t *testing.T) {
   230  	var expectedRelationships []artifact.Relationship
   231  	commonPkgs := []pkg.Package{
   232  		{
   233  			Name:     "case",
   234  			Version:  "1.6.2",
   235  			PURL:     "pkg:npm/case@1.6.2",
   236  			Language: pkg.JavaScript,
   237  			Type:     pkg.NpmPkg,
   238  			Metadata: pkg.NpmPackageLockEntry{Resolved: "https://registry.npmjs.org/case/-/case-1.6.2.tgz", Integrity: "sha512-ll380ZRoraT7mUK2G92UbH+FJVD5AwdVIAYk9xhV1tauh0carDgYByUD1HhjCWsWgxrfQvCeHvtfj7IYR6TKeg=="},
   239  		},
   240  		{
   241  			Name:     "case",
   242  			Version:  "1.6.3",
   243  			PURL:     "pkg:npm/case@1.6.3",
   244  			Language: pkg.JavaScript,
   245  			Type:     pkg.NpmPkg,
   246  			Metadata: pkg.NpmPackageLockEntry{Resolved: "https://registry.npmjs.org/case/-/case-1.6.3.tgz", Integrity: "sha512-mzDSXIPaFwVDvZAHqZ9VlbyF4yyXRuX6IvB06WvPYkqJVO24kX1PPhv9bfpKNFZyxYFmmgo03HUiD8iklmJYRQ=="},
   247  		},
   248  		{
   249  			Name:     "@bundled-es-modules/chai",
   250  			Version:  "4.2.2",
   251  			PURL:     "pkg:npm/%40bundled-es-modules/chai@4.2.2",
   252  			Language: pkg.JavaScript,
   253  			Type:     pkg.NpmPkg,
   254  			Metadata: pkg.NpmPackageLockEntry{Resolved: "https://registry.npmjs.org/@bundled-es-modules/chai/-/chai-4.2.2.tgz", Integrity: "sha512-iGmVYw2/zJCoqyKTtWEYCtFmMyi8WmACQKtky0lpNyEKWX0YIOpKWGD7saMXL+tPpllss0otilxV0SLwyi3Ytg=="},
   255  		},
   256  	}
   257  
   258  	packageLockV1 := "test-fixtures/pkg-lock/alias-package-lock-1.json"
   259  	packageLockV2 := "test-fixtures/pkg-lock/alias-package-lock-2.json"
   260  	packageLocks := []string{packageLockV1, packageLockV2}
   261  
   262  	v2Pkg := pkg.Package{
   263  		Name:     "alias-check",
   264  		Version:  "1.0.0",
   265  		PURL:     "pkg:npm/alias-check@1.0.0",
   266  		Language: pkg.JavaScript,
   267  		Type:     pkg.NpmPkg,
   268  		Licenses: pkg.NewLicenseSet(
   269  			pkg.NewLicenseFromLocations("ISC", file.NewLocation(packageLockV2)),
   270  		),
   271  		Metadata: pkg.NpmPackageLockEntry{},
   272  	}
   273  
   274  	for _, pl := range packageLocks {
   275  		expected := make([]pkg.Package, len(commonPkgs))
   276  		copy(expected, commonPkgs)
   277  
   278  		if pl == packageLockV2 {
   279  			expected = append(expected, v2Pkg)
   280  		}
   281  
   282  		for i := range expected {
   283  			expected[i].Locations.Add(file.NewLocation(pl))
   284  		}
   285  		adapter := newGenericPackageLockAdapter(CatalogerConfig{})
   286  		pkgtest.TestFileParser(t, pl, adapter.parsePackageLock, expected, expectedRelationships)
   287  	}
   288  }
   289  
   290  func TestParsePackageLockLicenseWithArray(t *testing.T) {
   291  	fixture := "test-fixtures/pkg-lock/array-license-package-lock.json"
   292  	var expectedRelationships []artifact.Relationship
   293  	expectedPkgs := []pkg.Package{
   294  		{
   295  			Name:     "tmp",
   296  			Version:  "1.0.0",
   297  			Language: pkg.JavaScript,
   298  			Type:     pkg.NpmPkg,
   299  			Licenses: pkg.NewLicenseSet(
   300  				pkg.NewLicenseFromLocations("ISC", file.NewLocation(fixture)),
   301  			),
   302  			PURL:     "pkg:npm/tmp@1.0.0",
   303  			Metadata: pkg.NpmPackageLockEntry{},
   304  		},
   305  		{
   306  			Name:     "pause-stream",
   307  			Version:  "0.0.11",
   308  			Language: pkg.JavaScript,
   309  			Type:     pkg.NpmPkg,
   310  
   311  			Licenses: pkg.NewLicenseSet(
   312  				pkg.NewLicenseFromLocations("MIT", file.NewLocation(fixture)),
   313  				pkg.NewLicenseFromLocations("Apache2", file.NewLocation(fixture)),
   314  			),
   315  			PURL:     "pkg:npm/pause-stream@0.0.11",
   316  			Metadata: pkg.NpmPackageLockEntry{},
   317  		},
   318  		{
   319  			Name:     "through",
   320  			Version:  "2.3.8",
   321  			Language: pkg.JavaScript,
   322  			Type:     pkg.NpmPkg,
   323  			Licenses: pkg.NewLicenseSet(
   324  				pkg.NewLicenseFromLocations("MIT", file.NewLocation(fixture)),
   325  			),
   326  			PURL:     "pkg:npm/through@2.3.8",
   327  			Metadata: pkg.NpmPackageLockEntry{},
   328  		},
   329  	}
   330  	for i := range expectedPkgs {
   331  		expectedPkgs[i].Locations.Add(file.NewLocation(fixture))
   332  	}
   333  	adapter := newGenericPackageLockAdapter(CatalogerConfig{})
   334  	pkgtest.TestFileParser(t, fixture, adapter.parsePackageLock, expectedPkgs, expectedRelationships)
   335  }