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 }