github.com/google/osv-scalibr@v0.4.1/extractor/filesystem/language/javascript/pnpmlock/pnpmlock-v9_test.go (about) 1 // Copyright 2025 Google LLC 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package pnpmlock_test 16 17 import ( 18 "testing" 19 20 "github.com/google/go-cmp/cmp" 21 "github.com/google/go-cmp/cmp/cmpopts" 22 "github.com/google/osv-scalibr/extractor" 23 "github.com/google/osv-scalibr/extractor/filesystem/language/javascript/pnpmlock" 24 "github.com/google/osv-scalibr/extractor/filesystem/osv" 25 "github.com/google/osv-scalibr/inventory" 26 "github.com/google/osv-scalibr/purl" 27 "github.com/google/osv-scalibr/testing/extracttest" 28 ) 29 30 func TestExtractor_Extract_v9(t *testing.T) { 31 tests := []extracttest.TestTableEntry{ 32 { 33 Name: "no packages", 34 InputConfig: extracttest.ScanInputMockConfig{ 35 Path: "testdata/no-packages.v9.yaml", 36 }, 37 WantPackages: []*extractor.Package{}, 38 }, 39 { 40 Name: "one package", 41 InputConfig: extracttest.ScanInputMockConfig{ 42 Path: "testdata/one-package.v9.yaml", 43 }, 44 WantPackages: []*extractor.Package{ 45 { 46 Name: "acorn", 47 Version: "8.11.3", 48 PURLType: purl.TypeNPM, 49 Locations: []string{"testdata/one-package.v9.yaml"}, 50 SourceCode: &extractor.SourceCodeIdentifier{}, 51 Metadata: osv.DepGroupMetadata{ 52 DepGroupVals: []string{}, 53 }, 54 }, 55 }, 56 }, 57 { 58 Name: "one package dev", 59 InputConfig: extracttest.ScanInputMockConfig{ 60 Path: "testdata/one-package-dev.v9.yaml", 61 }, 62 WantPackages: []*extractor.Package{ 63 { 64 Name: "acorn", 65 Version: "8.11.3", 66 PURLType: purl.TypeNPM, 67 Locations: []string{"testdata/one-package-dev.v9.yaml"}, 68 SourceCode: &extractor.SourceCodeIdentifier{}, 69 Metadata: osv.DepGroupMetadata{ 70 DepGroupVals: []string{}, 71 }, 72 }, 73 }, 74 }, 75 { 76 Name: "scoped packages", 77 InputConfig: extracttest.ScanInputMockConfig{ 78 Path: "testdata/scoped-packages.v9.yaml", 79 }, 80 WantPackages: []*extractor.Package{ 81 { 82 Name: "@typescript-eslint/types", 83 Version: "5.62.0", 84 PURLType: purl.TypeNPM, 85 Locations: []string{"testdata/scoped-packages.v9.yaml"}, 86 SourceCode: &extractor.SourceCodeIdentifier{}, 87 Metadata: osv.DepGroupMetadata{ 88 DepGroupVals: []string{}, 89 }, 90 }, 91 }, 92 }, 93 { 94 Name: "peer dependencies", 95 InputConfig: extracttest.ScanInputMockConfig{ 96 Path: "testdata/peer-dependencies.v9.yaml", 97 }, 98 WantPackages: []*extractor.Package{ 99 { 100 Name: "acorn-jsx", 101 Version: "5.3.2", 102 PURLType: purl.TypeNPM, 103 Locations: []string{"testdata/peer-dependencies.v9.yaml"}, 104 SourceCode: &extractor.SourceCodeIdentifier{}, 105 Metadata: osv.DepGroupMetadata{ 106 DepGroupVals: []string{}, 107 }, 108 }, 109 { 110 Name: "acorn", 111 Version: "8.11.3", 112 PURLType: purl.TypeNPM, 113 Locations: []string{"testdata/peer-dependencies.v9.yaml"}, 114 SourceCode: &extractor.SourceCodeIdentifier{}, 115 Metadata: osv.DepGroupMetadata{ 116 DepGroupVals: []string{}, 117 }, 118 }, 119 }, 120 }, 121 { 122 Name: "peer dependencies advanced", 123 InputConfig: extracttest.ScanInputMockConfig{ 124 Path: "testdata/peer-dependencies-advanced.v9.yaml", 125 }, 126 WantPackages: []*extractor.Package{ 127 { 128 Name: "@eslint-community/eslint-utils", 129 Version: "4.4.0", 130 PURLType: purl.TypeNPM, 131 Locations: []string{"testdata/peer-dependencies-advanced.v9.yaml"}, 132 SourceCode: &extractor.SourceCodeIdentifier{}, 133 Metadata: osv.DepGroupMetadata{ 134 DepGroupVals: []string{}, 135 }, 136 }, 137 { 138 Name: "@eslint/eslintrc", 139 Version: "2.1.4", 140 PURLType: purl.TypeNPM, 141 Locations: []string{"testdata/peer-dependencies-advanced.v9.yaml"}, 142 SourceCode: &extractor.SourceCodeIdentifier{}, 143 Metadata: osv.DepGroupMetadata{ 144 DepGroupVals: []string{}, 145 }, 146 }, 147 { 148 Name: "@typescript-eslint/eslint-plugin", 149 Version: "5.62.0", 150 PURLType: purl.TypeNPM, 151 Locations: []string{"testdata/peer-dependencies-advanced.v9.yaml"}, 152 SourceCode: &extractor.SourceCodeIdentifier{}, 153 Metadata: osv.DepGroupMetadata{ 154 DepGroupVals: []string{}, 155 }, 156 }, 157 { 158 Name: "@typescript-eslint/parser", 159 Version: "5.62.0", 160 PURLType: purl.TypeNPM, 161 Locations: []string{"testdata/peer-dependencies-advanced.v9.yaml"}, 162 SourceCode: &extractor.SourceCodeIdentifier{}, 163 Metadata: osv.DepGroupMetadata{ 164 DepGroupVals: []string{}, 165 }, 166 }, 167 { 168 Name: "@typescript-eslint/type-utils", 169 Version: "5.62.0", 170 PURLType: purl.TypeNPM, 171 Locations: []string{"testdata/peer-dependencies-advanced.v9.yaml"}, 172 SourceCode: &extractor.SourceCodeIdentifier{}, 173 Metadata: osv.DepGroupMetadata{ 174 DepGroupVals: []string{}, 175 }, 176 }, 177 { 178 Name: "@typescript-eslint/typescript-estree", 179 Version: "5.62.0", 180 PURLType: purl.TypeNPM, 181 Locations: []string{"testdata/peer-dependencies-advanced.v9.yaml"}, 182 SourceCode: &extractor.SourceCodeIdentifier{}, 183 Metadata: osv.DepGroupMetadata{ 184 DepGroupVals: []string{}, 185 }, 186 }, 187 { 188 Name: "@typescript-eslint/utils", 189 Version: "5.62.0", 190 PURLType: purl.TypeNPM, 191 Locations: []string{"testdata/peer-dependencies-advanced.v9.yaml"}, 192 SourceCode: &extractor.SourceCodeIdentifier{}, 193 Metadata: osv.DepGroupMetadata{ 194 DepGroupVals: []string{}, 195 }, 196 }, 197 { 198 Name: "debug", 199 Version: "4.3.4", 200 PURLType: purl.TypeNPM, 201 Locations: []string{"testdata/peer-dependencies-advanced.v9.yaml"}, 202 SourceCode: &extractor.SourceCodeIdentifier{}, 203 Metadata: osv.DepGroupMetadata{ 204 DepGroupVals: []string{}, 205 }, 206 }, 207 { 208 Name: "eslint", 209 Version: "8.57.0", 210 PURLType: purl.TypeNPM, 211 Locations: []string{"testdata/peer-dependencies-advanced.v9.yaml"}, 212 SourceCode: &extractor.SourceCodeIdentifier{}, 213 Metadata: osv.DepGroupMetadata{ 214 DepGroupVals: []string{}, 215 }, 216 }, 217 { 218 Name: "has-flag", 219 Version: "4.0.0", 220 PURLType: purl.TypeNPM, 221 Locations: []string{"testdata/peer-dependencies-advanced.v9.yaml"}, 222 SourceCode: &extractor.SourceCodeIdentifier{}, 223 Metadata: osv.DepGroupMetadata{ 224 DepGroupVals: []string{}, 225 }, 226 }, 227 { 228 Name: "supports-color", 229 Version: "7.2.0", 230 PURLType: purl.TypeNPM, 231 Locations: []string{"testdata/peer-dependencies-advanced.v9.yaml"}, 232 SourceCode: &extractor.SourceCodeIdentifier{}, 233 Metadata: osv.DepGroupMetadata{ 234 DepGroupVals: []string{}, 235 }, 236 }, 237 { 238 Name: "tsutils", 239 Version: "3.21.0", 240 PURLType: purl.TypeNPM, 241 Locations: []string{"testdata/peer-dependencies-advanced.v9.yaml"}, 242 SourceCode: &extractor.SourceCodeIdentifier{}, 243 Metadata: osv.DepGroupMetadata{ 244 DepGroupVals: []string{}, 245 }, 246 }, 247 { 248 Name: "typescript", 249 Version: "4.9.5", 250 PURLType: purl.TypeNPM, 251 Locations: []string{"testdata/peer-dependencies-advanced.v9.yaml"}, 252 SourceCode: &extractor.SourceCodeIdentifier{}, 253 Metadata: osv.DepGroupMetadata{ 254 DepGroupVals: []string{}, 255 }, 256 }, 257 }, 258 }, 259 { 260 Name: "multiple versions", 261 InputConfig: extracttest.ScanInputMockConfig{ 262 Path: "testdata/multiple-versions.v9.yaml", 263 }, 264 WantPackages: []*extractor.Package{ 265 { 266 Name: "uuid", 267 Version: "8.0.0", 268 PURLType: purl.TypeNPM, 269 Locations: []string{"testdata/multiple-versions.v9.yaml"}, 270 SourceCode: &extractor.SourceCodeIdentifier{}, 271 Metadata: osv.DepGroupMetadata{ 272 DepGroupVals: []string{}, 273 }, 274 }, 275 { 276 Name: "uuid", 277 Version: "8.3.2", 278 PURLType: purl.TypeNPM, 279 Locations: []string{"testdata/multiple-versions.v9.yaml"}, 280 SourceCode: &extractor.SourceCodeIdentifier{}, 281 Metadata: osv.DepGroupMetadata{ 282 DepGroupVals: []string{}, 283 }, 284 }, 285 { 286 Name: "xmlbuilder", 287 Version: "11.0.1", 288 PURLType: purl.TypeNPM, 289 Locations: []string{"testdata/multiple-versions.v9.yaml"}, 290 SourceCode: &extractor.SourceCodeIdentifier{}, 291 Metadata: osv.DepGroupMetadata{ 292 DepGroupVals: []string{}, 293 }, 294 }, 295 }, 296 }, 297 { 298 Name: "commits", 299 InputConfig: extracttest.ScanInputMockConfig{ 300 Path: "testdata/commits.v9.yaml", 301 }, 302 WantPackages: []*extractor.Package{ 303 { 304 Name: "ansi-regex", 305 Version: "6.0.1", 306 PURLType: purl.TypeNPM, 307 Locations: []string{"testdata/commits.v9.yaml"}, 308 SourceCode: &extractor.SourceCodeIdentifier{ 309 Commit: "02fa893d619d3da85411acc8fd4e2eea0e95a9d9", 310 }, 311 Metadata: osv.DepGroupMetadata{ 312 DepGroupVals: []string{}, 313 }, 314 }, 315 { 316 Name: "is-number", 317 Version: "7.0.0", 318 PURLType: purl.TypeNPM, 319 Locations: []string{"testdata/commits.v9.yaml"}, 320 SourceCode: &extractor.SourceCodeIdentifier{ 321 Commit: "98e8ff1da1a89f93d1397a24d7413ed15421c139", 322 }, 323 Metadata: osv.DepGroupMetadata{ 324 DepGroupVals: []string{}, 325 }, 326 }, 327 }, 328 }, 329 { 330 Name: "mixed groups", 331 InputConfig: extracttest.ScanInputMockConfig{ 332 Path: "testdata/mixed-groups.v9.yaml", 333 }, 334 WantPackages: []*extractor.Package{ 335 { 336 Name: "ansi-regex", 337 Version: "5.0.1", 338 PURLType: purl.TypeNPM, 339 Locations: []string{"testdata/mixed-groups.v9.yaml"}, 340 SourceCode: &extractor.SourceCodeIdentifier{}, 341 Metadata: osv.DepGroupMetadata{ 342 DepGroupVals: []string{}, 343 }, 344 }, 345 { 346 Name: "uuid", 347 Version: "8.3.2", 348 PURLType: purl.TypeNPM, 349 Locations: []string{"testdata/mixed-groups.v9.yaml"}, 350 SourceCode: &extractor.SourceCodeIdentifier{}, 351 Metadata: osv.DepGroupMetadata{ 352 DepGroupVals: []string{}, 353 }, 354 }, 355 { 356 Name: "is-number", 357 Version: "7.0.0", 358 PURLType: purl.TypeNPM, 359 Locations: []string{"testdata/mixed-groups.v9.yaml"}, 360 SourceCode: &extractor.SourceCodeIdentifier{}, 361 Metadata: osv.DepGroupMetadata{ 362 DepGroupVals: []string{}, 363 }, 364 }, 365 }, 366 }, 367 } 368 369 for _, tt := range tests { 370 t.Run(tt.Name, func(t *testing.T) { 371 extr := pnpmlock.Extractor{} 372 373 scanInput := extracttest.GenerateScanInputMock(t, tt.InputConfig) 374 defer extracttest.CloseTestScanInput(t, scanInput) 375 376 got, err := extr.Extract(t.Context(), &scanInput) 377 378 if diff := cmp.Diff(tt.WantErr, err, cmpopts.EquateErrors()); diff != "" { 379 t.Errorf("%s.Extract(%q) error diff (-want +got):\n%s", extr.Name(), tt.InputConfig.Path, diff) 380 return 381 } 382 383 wantInv := inventory.Inventory{Packages: tt.WantPackages} 384 if diff := cmp.Diff(wantInv, got, cmpopts.SortSlices(extracttest.PackageCmpLess)); diff != "" { 385 t.Errorf("%s.Extract(%q) diff (-want +got):\n%s", extr.Name(), tt.InputConfig.Path, diff) 386 } 387 }) 388 } 389 }