github.com/google/osv-scalibr@v0.4.1/extractor/filesystem/language/javascript/packagelockjson/packagelockjson-v1_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 packagelockjson_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/packagelockjson"
    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  	"github.com/google/osv-scalibr/testing/testcollector"
    29  )
    30  
    31  func TestNPMLockExtractor_Extract_V1(t *testing.T) {
    32  	tests := []extracttest.TestTableEntry{
    33  		{
    34  			Name: "invalid json",
    35  			InputConfig: extracttest.ScanInputMockConfig{
    36  				Path: "testdata/not-json.txt",
    37  			},
    38  			WantErr: extracttest.ContainsErrStr{Str: "could not extract"},
    39  		},
    40  		{
    41  			Name: "no packages",
    42  			InputConfig: extracttest.ScanInputMockConfig{
    43  				Path: "testdata/empty.v1.json",
    44  			},
    45  			WantPackages: []*extractor.Package{},
    46  		},
    47  		{
    48  			Name: "one package",
    49  			InputConfig: extracttest.ScanInputMockConfig{
    50  				Path: "testdata/one-package.v1.json",
    51  			},
    52  			WantPackages: []*extractor.Package{
    53  				{
    54  					Name:       "wrappy",
    55  					Version:    "1.0.2",
    56  					PURLType:   purl.TypeNPM,
    57  					Locations:  []string{"testdata/one-package.v1.json"},
    58  					SourceCode: &extractor.SourceCodeIdentifier{},
    59  					Metadata: osv.DepGroupMetadata{
    60  						DepGroupVals: []string{},
    61  					},
    62  				},
    63  			},
    64  		},
    65  		{
    66  			Name: "one package dev",
    67  			InputConfig: extracttest.ScanInputMockConfig{
    68  				Path: "testdata/one-package-dev.v1.json",
    69  			},
    70  			WantPackages: []*extractor.Package{
    71  				{
    72  					Name:       "wrappy",
    73  					Version:    "1.0.2",
    74  					PURLType:   purl.TypeNPM,
    75  					Locations:  []string{"testdata/one-package-dev.v1.json"},
    76  					SourceCode: &extractor.SourceCodeIdentifier{},
    77  					Metadata: osv.DepGroupMetadata{
    78  						DepGroupVals: []string{"dev"},
    79  					},
    80  				},
    81  			},
    82  		},
    83  		{
    84  			Name: "two packages",
    85  			InputConfig: extracttest.ScanInputMockConfig{
    86  				Path: "testdata/two-packages.v1.json",
    87  			},
    88  			WantPackages: []*extractor.Package{
    89  				{
    90  					Name:       "wrappy",
    91  					Version:    "1.0.2",
    92  					PURLType:   purl.TypeNPM,
    93  					Locations:  []string{"testdata/two-packages.v1.json"},
    94  					SourceCode: &extractor.SourceCodeIdentifier{},
    95  					Metadata: osv.DepGroupMetadata{
    96  						DepGroupVals: []string{},
    97  					},
    98  				},
    99  				{
   100  					Name:       "supports-color",
   101  					Version:    "5.5.0",
   102  					PURLType:   purl.TypeNPM,
   103  					Locations:  []string{"testdata/two-packages.v1.json"},
   104  					SourceCode: &extractor.SourceCodeIdentifier{},
   105  					Metadata: osv.DepGroupMetadata{
   106  						DepGroupVals: []string{},
   107  					},
   108  				},
   109  			},
   110  		},
   111  		{
   112  			Name: "scoped packages",
   113  			InputConfig: extracttest.ScanInputMockConfig{
   114  				Path: "testdata/scoped-packages.v1.json",
   115  			},
   116  			WantPackages: []*extractor.Package{
   117  				{
   118  					Name:       "wrappy",
   119  					Version:    "1.0.2",
   120  					PURLType:   purl.TypeNPM,
   121  					Locations:  []string{"testdata/scoped-packages.v1.json"},
   122  					SourceCode: &extractor.SourceCodeIdentifier{},
   123  					Metadata: osv.DepGroupMetadata{
   124  						DepGroupVals: []string{},
   125  					},
   126  				},
   127  				{
   128  					Name:       "@babel/code-frame",
   129  					Version:    "7.0.0",
   130  					PURLType:   purl.TypeNPM,
   131  					Locations:  []string{"testdata/scoped-packages.v1.json"},
   132  					SourceCode: &extractor.SourceCodeIdentifier{},
   133  					Metadata: osv.DepGroupMetadata{
   134  						DepGroupVals: []string{},
   135  					},
   136  				},
   137  			},
   138  		},
   139  		{
   140  			Name: "nested dependencies",
   141  			InputConfig: extracttest.ScanInputMockConfig{
   142  				Path: "testdata/nested-dependencies.v1.json",
   143  			},
   144  			WantPackages: []*extractor.Package{
   145  				{
   146  					Name:       "postcss",
   147  					Version:    "6.0.23",
   148  					PURLType:   purl.TypeNPM,
   149  					Locations:  []string{"testdata/nested-dependencies.v1.json"},
   150  					SourceCode: &extractor.SourceCodeIdentifier{},
   151  					Metadata: osv.DepGroupMetadata{
   152  						DepGroupVals: []string{},
   153  					},
   154  				},
   155  				{
   156  					Name:       "postcss",
   157  					Version:    "7.0.16",
   158  					PURLType:   purl.TypeNPM,
   159  					Locations:  []string{"testdata/nested-dependencies.v1.json"},
   160  					SourceCode: &extractor.SourceCodeIdentifier{},
   161  					Metadata: osv.DepGroupMetadata{
   162  						DepGroupVals: []string{},
   163  					},
   164  				},
   165  				{
   166  					Name:       "postcss-calc",
   167  					Version:    "7.0.1",
   168  					PURLType:   purl.TypeNPM,
   169  					Locations:  []string{"testdata/nested-dependencies.v1.json"},
   170  					SourceCode: &extractor.SourceCodeIdentifier{},
   171  					Metadata: osv.DepGroupMetadata{
   172  						DepGroupVals: []string{},
   173  					},
   174  				},
   175  				{
   176  					Name:       "supports-color",
   177  					Version:    "6.1.0",
   178  					PURLType:   purl.TypeNPM,
   179  					Locations:  []string{"testdata/nested-dependencies.v1.json"},
   180  					SourceCode: &extractor.SourceCodeIdentifier{},
   181  					Metadata: osv.DepGroupMetadata{
   182  						DepGroupVals: []string{},
   183  					},
   184  				},
   185  				{
   186  					Name:       "supports-color",
   187  					Version:    "5.5.0",
   188  					PURLType:   purl.TypeNPM,
   189  					Locations:  []string{"testdata/nested-dependencies.v1.json"},
   190  					SourceCode: &extractor.SourceCodeIdentifier{},
   191  					Metadata: osv.DepGroupMetadata{
   192  						DepGroupVals: []string{},
   193  					},
   194  				},
   195  			},
   196  		},
   197  		{
   198  			Name: "nested dependencies dup",
   199  			InputConfig: extracttest.ScanInputMockConfig{
   200  				Path: "testdata/nested-dependencies-dup.v1.json",
   201  			},
   202  			WantPackages: []*extractor.Package{
   203  				{
   204  					Name:       "supports-color",
   205  					Version:    "2.0.0",
   206  					PURLType:   purl.TypeNPM,
   207  					Locations:  []string{"testdata/nested-dependencies-dup.v1.json"},
   208  					SourceCode: &extractor.SourceCodeIdentifier{},
   209  					Metadata: osv.DepGroupMetadata{
   210  						DepGroupVals: []string{},
   211  					},
   212  				},
   213  				{
   214  					Name:       "postcss-normalize-display-values",
   215  					Version:    "4.0.2",
   216  					PURLType:   purl.TypeNPM,
   217  					Locations:  []string{"testdata/nested-dependencies-dup.v1.json"},
   218  					SourceCode: &extractor.SourceCodeIdentifier{},
   219  					Metadata: osv.DepGroupMetadata{
   220  						DepGroupVals: []string{},
   221  					},
   222  				},
   223  				{
   224  					Name:       "postcss-normalize-timing-functions",
   225  					Version:    "4.0.2",
   226  					PURLType:   purl.TypeNPM,
   227  					Locations:  []string{"testdata/nested-dependencies-dup.v1.json"},
   228  					SourceCode: &extractor.SourceCodeIdentifier{},
   229  					Metadata: osv.DepGroupMetadata{
   230  						DepGroupVals: []string{},
   231  					},
   232  				},
   233  				{
   234  					Name:       "postcss-normalize-string",
   235  					Version:    "4.0.2",
   236  					PURLType:   purl.TypeNPM,
   237  					Locations:  []string{"testdata/nested-dependencies-dup.v1.json"},
   238  					SourceCode: &extractor.SourceCodeIdentifier{},
   239  					Metadata: osv.DepGroupMetadata{
   240  						DepGroupVals: []string{},
   241  					},
   242  				},
   243  				{
   244  					Name:       "postcss-normalize-whitespace",
   245  					Version:    "4.0.2",
   246  					PURLType:   purl.TypeNPM,
   247  					Locations:  []string{"testdata/nested-dependencies-dup.v1.json"},
   248  					SourceCode: &extractor.SourceCodeIdentifier{},
   249  					Metadata: osv.DepGroupMetadata{
   250  						DepGroupVals: []string{},
   251  					},
   252  				},
   253  				{
   254  					Name:       "supports-color",
   255  					Version:    "6.1.0",
   256  					PURLType:   purl.TypeNPM,
   257  					Locations:  []string{"testdata/nested-dependencies-dup.v1.json"},
   258  					SourceCode: &extractor.SourceCodeIdentifier{},
   259  					Metadata: osv.DepGroupMetadata{
   260  						DepGroupVals: []string{},
   261  					},
   262  				},
   263  				{
   264  					Name:       "cssnano-preset-default",
   265  					Version:    "4.0.7",
   266  					PURLType:   purl.TypeNPM,
   267  					Locations:  []string{"testdata/nested-dependencies-dup.v1.json"},
   268  					SourceCode: &extractor.SourceCodeIdentifier{},
   269  					Metadata: osv.DepGroupMetadata{
   270  						DepGroupVals: []string{},
   271  					},
   272  				},
   273  				{
   274  					Name:       "postcss-merge-longhand",
   275  					Version:    "4.0.11",
   276  					PURLType:   purl.TypeNPM,
   277  					Locations:  []string{"testdata/nested-dependencies-dup.v1.json"},
   278  					SourceCode: &extractor.SourceCodeIdentifier{},
   279  					Metadata: osv.DepGroupMetadata{
   280  						DepGroupVals: []string{},
   281  					},
   282  				},
   283  				{
   284  					Name:       "postcss-discard-overridden",
   285  					Version:    "4.0.1",
   286  					PURLType:   purl.TypeNPM,
   287  					Locations:  []string{"testdata/nested-dependencies-dup.v1.json"},
   288  					SourceCode: &extractor.SourceCodeIdentifier{},
   289  					Metadata: osv.DepGroupMetadata{
   290  						DepGroupVals: []string{},
   291  					},
   292  				},
   293  				{
   294  					Name:       "postcss-reduce-transforms",
   295  					Version:    "4.0.2",
   296  					PURLType:   purl.TypeNPM,
   297  					Locations:  []string{"testdata/nested-dependencies-dup.v1.json"},
   298  					SourceCode: &extractor.SourceCodeIdentifier{},
   299  					Metadata: osv.DepGroupMetadata{
   300  						DepGroupVals: []string{},
   301  					},
   302  				},
   303  				{
   304  					Name:       "postcss-svgo",
   305  					Version:    "4.0.2",
   306  					PURLType:   purl.TypeNPM,
   307  					Locations:  []string{"testdata/nested-dependencies-dup.v1.json"},
   308  					SourceCode: &extractor.SourceCodeIdentifier{},
   309  					Metadata: osv.DepGroupMetadata{
   310  						DepGroupVals: []string{},
   311  					},
   312  				},
   313  				{
   314  					Name:       "postcss-ordered-values",
   315  					Version:    "4.1.2",
   316  					PURLType:   purl.TypeNPM,
   317  					Locations:  []string{"testdata/nested-dependencies-dup.v1.json"},
   318  					SourceCode: &extractor.SourceCodeIdentifier{},
   319  					Metadata: osv.DepGroupMetadata{
   320  						DepGroupVals: []string{},
   321  					},
   322  				},
   323  				{
   324  					Name:       "postcss-minify-selectors",
   325  					Version:    "4.0.2",
   326  					PURLType:   purl.TypeNPM,
   327  					Locations:  []string{"testdata/nested-dependencies-dup.v1.json"},
   328  					SourceCode: &extractor.SourceCodeIdentifier{},
   329  					Metadata: osv.DepGroupMetadata{
   330  						DepGroupVals: []string{},
   331  					},
   332  				},
   333  				{
   334  					Name:       "babel-code-frame",
   335  					Version:    "6.26.0",
   336  					PURLType:   purl.TypeNPM,
   337  					Locations:  []string{"testdata/nested-dependencies-dup.v1.json"},
   338  					SourceCode: &extractor.SourceCodeIdentifier{},
   339  					Metadata: osv.DepGroupMetadata{
   340  						DepGroupVals: []string{},
   341  					},
   342  				},
   343  				{
   344  					Name:       "css-declaration-sorter",
   345  					Version:    "4.0.1",
   346  					PURLType:   purl.TypeNPM,
   347  					Locations:  []string{"testdata/nested-dependencies-dup.v1.json"},
   348  					SourceCode: &extractor.SourceCodeIdentifier{},
   349  					Metadata: osv.DepGroupMetadata{
   350  						DepGroupVals: []string{},
   351  					},
   352  				},
   353  				{
   354  					Name:       "postcss-normalize-url",
   355  					Version:    "4.0.1",
   356  					PURLType:   purl.TypeNPM,
   357  					Locations:  []string{"testdata/nested-dependencies-dup.v1.json"},
   358  					SourceCode: &extractor.SourceCodeIdentifier{},
   359  					Metadata: osv.DepGroupMetadata{
   360  						DepGroupVals: []string{},
   361  					},
   362  				},
   363  				{
   364  					Name:       "postcss-minify-params",
   365  					Version:    "4.0.2",
   366  					PURLType:   purl.TypeNPM,
   367  					Locations:  []string{"testdata/nested-dependencies-dup.v1.json"},
   368  					SourceCode: &extractor.SourceCodeIdentifier{},
   369  					Metadata: osv.DepGroupMetadata{
   370  						DepGroupVals: []string{},
   371  					},
   372  				},
   373  				{
   374  					Name:       "supports-color",
   375  					Version:    "5.5.0",
   376  					PURLType:   purl.TypeNPM,
   377  					Locations:  []string{"testdata/nested-dependencies-dup.v1.json"},
   378  					SourceCode: &extractor.SourceCodeIdentifier{},
   379  					Metadata: osv.DepGroupMetadata{
   380  						DepGroupVals: []string{},
   381  					},
   382  				},
   383  				{
   384  					Name:       "postcss-colormin",
   385  					Version:    "4.0.3",
   386  					PURLType:   purl.TypeNPM,
   387  					Locations:  []string{"testdata/nested-dependencies-dup.v1.json"},
   388  					SourceCode: &extractor.SourceCodeIdentifier{},
   389  					Metadata: osv.DepGroupMetadata{
   390  						DepGroupVals: []string{},
   391  					},
   392  				},
   393  				{
   394  					Name:       "autoprefixer",
   395  					Version:    "9.5.1",
   396  					PURLType:   purl.TypeNPM,
   397  					Locations:  []string{"testdata/nested-dependencies-dup.v1.json"},
   398  					SourceCode: &extractor.SourceCodeIdentifier{},
   399  					Metadata: osv.DepGroupMetadata{
   400  						DepGroupVals: []string{},
   401  					},
   402  				},
   403  				{
   404  					Name:       "postcss-normalize-charset",
   405  					Version:    "4.0.1",
   406  					PURLType:   purl.TypeNPM,
   407  					Locations:  []string{"testdata/nested-dependencies-dup.v1.json"},
   408  					SourceCode: &extractor.SourceCodeIdentifier{},
   409  					Metadata: osv.DepGroupMetadata{
   410  						DepGroupVals: []string{},
   411  					},
   412  				},
   413  				{
   414  					Name:       "postcss-unique-selectors",
   415  					Version:    "4.0.1",
   416  					PURLType:   purl.TypeNPM,
   417  					Locations:  []string{"testdata/nested-dependencies-dup.v1.json"},
   418  					SourceCode: &extractor.SourceCodeIdentifier{},
   419  					Metadata: osv.DepGroupMetadata{
   420  						DepGroupVals: []string{},
   421  					},
   422  				},
   423  				{
   424  					Name:       "postcss-reduce-initial",
   425  					Version:    "4.0.3",
   426  					PURLType:   purl.TypeNPM,
   427  					Locations:  []string{"testdata/nested-dependencies-dup.v1.json"},
   428  					SourceCode: &extractor.SourceCodeIdentifier{},
   429  					Metadata: osv.DepGroupMetadata{
   430  						DepGroupVals: []string{},
   431  					},
   432  				},
   433  				{
   434  					Name:       "postcss-normalize-positions",
   435  					Version:    "4.0.2",
   436  					PURLType:   purl.TypeNPM,
   437  					Locations:  []string{"testdata/nested-dependencies-dup.v1.json"},
   438  					SourceCode: &extractor.SourceCodeIdentifier{},
   439  					Metadata: osv.DepGroupMetadata{
   440  						DepGroupVals: []string{},
   441  					},
   442  				},
   443  				{
   444  					Name:       "postcss-discard-duplicates",
   445  					Version:    "4.0.2",
   446  					PURLType:   purl.TypeNPM,
   447  					Locations:  []string{"testdata/nested-dependencies-dup.v1.json"},
   448  					SourceCode: &extractor.SourceCodeIdentifier{},
   449  					Metadata: osv.DepGroupMetadata{
   450  						DepGroupVals: []string{},
   451  					},
   452  				},
   453  				{
   454  					Name:       "postcss-loader",
   455  					Version:    "3.0.0",
   456  					PURLType:   purl.TypeNPM,
   457  					Locations:  []string{"testdata/nested-dependencies-dup.v1.json"},
   458  					SourceCode: &extractor.SourceCodeIdentifier{},
   459  					Metadata: osv.DepGroupMetadata{
   460  						DepGroupVals: []string{},
   461  					},
   462  				},
   463  				{
   464  					Name:       "cssnano",
   465  					Version:    "4.1.10",
   466  					PURLType:   purl.TypeNPM,
   467  					Locations:  []string{"testdata/nested-dependencies-dup.v1.json"},
   468  					SourceCode: &extractor.SourceCodeIdentifier{},
   469  					Metadata: osv.DepGroupMetadata{
   470  						DepGroupVals: []string{},
   471  					},
   472  				},
   473  				{
   474  					Name:       "postcss-discard-empty",
   475  					Version:    "4.0.1",
   476  					PURLType:   purl.TypeNPM,
   477  					Locations:  []string{"testdata/nested-dependencies-dup.v1.json"},
   478  					SourceCode: &extractor.SourceCodeIdentifier{},
   479  					Metadata: osv.DepGroupMetadata{
   480  						DepGroupVals: []string{},
   481  					},
   482  				},
   483  				{
   484  					Name:       "postcss-normalize-repeat-style",
   485  					Version:    "4.0.2",
   486  					PURLType:   purl.TypeNPM,
   487  					Locations:  []string{"testdata/nested-dependencies-dup.v1.json"},
   488  					SourceCode: &extractor.SourceCodeIdentifier{},
   489  					Metadata: osv.DepGroupMetadata{
   490  						DepGroupVals: []string{},
   491  					},
   492  				},
   493  				{
   494  					Name:       "postcss-convert-values",
   495  					Version:    "4.0.1",
   496  					PURLType:   purl.TypeNPM,
   497  					Locations:  []string{"testdata/nested-dependencies-dup.v1.json"},
   498  					SourceCode: &extractor.SourceCodeIdentifier{},
   499  					Metadata: osv.DepGroupMetadata{
   500  						DepGroupVals: []string{},
   501  					},
   502  				},
   503  				{
   504  					Name:       "friendly-errors-webpack-plugin",
   505  					Version:    "1.7.0",
   506  					PURLType:   purl.TypeNPM,
   507  					Locations:  []string{"testdata/nested-dependencies-dup.v1.json"},
   508  					SourceCode: &extractor.SourceCodeIdentifier{},
   509  					Metadata: osv.DepGroupMetadata{
   510  						DepGroupVals: []string{},
   511  					},
   512  				},
   513  				{
   514  					Name:       "@vue/component-compiler-utils",
   515  					Version:    "2.6.0",
   516  					PURLType:   purl.TypeNPM,
   517  					Locations:  []string{"testdata/nested-dependencies-dup.v1.json"},
   518  					SourceCode: &extractor.SourceCodeIdentifier{},
   519  					Metadata: osv.DepGroupMetadata{
   520  						DepGroupVals: []string{},
   521  					},
   522  				},
   523  				{
   524  					Name:       "postcss-merge-rules",
   525  					Version:    "4.0.3",
   526  					PURLType:   purl.TypeNPM,
   527  					Locations:  []string{"testdata/nested-dependencies-dup.v1.json"},
   528  					SourceCode: &extractor.SourceCodeIdentifier{},
   529  					Metadata: osv.DepGroupMetadata{
   530  						DepGroupVals: []string{},
   531  					},
   532  				},
   533  				{
   534  					Name:       "postcss-normalize-unicode",
   535  					Version:    "4.0.1",
   536  					PURLType:   purl.TypeNPM,
   537  					Locations:  []string{"testdata/nested-dependencies-dup.v1.json"},
   538  					SourceCode: &extractor.SourceCodeIdentifier{},
   539  					Metadata: osv.DepGroupMetadata{
   540  						DepGroupVals: []string{},
   541  					},
   542  				},
   543  				{
   544  					Name:       "postcss-minify-font-values",
   545  					Version:    "4.0.2",
   546  					PURLType:   purl.TypeNPM,
   547  					Locations:  []string{"testdata/nested-dependencies-dup.v1.json"},
   548  					SourceCode: &extractor.SourceCodeIdentifier{},
   549  					Metadata: osv.DepGroupMetadata{
   550  						DepGroupVals: []string{},
   551  					},
   552  				},
   553  				{
   554  					Name:       "postcss-minify-gradients",
   555  					Version:    "4.0.2",
   556  					PURLType:   purl.TypeNPM,
   557  					Locations:  []string{"testdata/nested-dependencies-dup.v1.json"},
   558  					SourceCode: &extractor.SourceCodeIdentifier{},
   559  					Metadata: osv.DepGroupMetadata{
   560  						DepGroupVals: []string{},
   561  					},
   562  				},
   563  				{
   564  					Name:       "cssnano-util-raw-cache",
   565  					Version:    "4.0.1",
   566  					PURLType:   purl.TypeNPM,
   567  					Locations:  []string{"testdata/nested-dependencies-dup.v1.json"},
   568  					SourceCode: &extractor.SourceCodeIdentifier{},
   569  					Metadata: osv.DepGroupMetadata{
   570  						DepGroupVals: []string{},
   571  					},
   572  				},
   573  				{
   574  					Name:       "postcss-calc",
   575  					Version:    "7.0.1",
   576  					PURLType:   purl.TypeNPM,
   577  					Locations:  []string{"testdata/nested-dependencies-dup.v1.json"},
   578  					SourceCode: &extractor.SourceCodeIdentifier{},
   579  					Metadata: osv.DepGroupMetadata{
   580  						DepGroupVals: []string{},
   581  					},
   582  				},
   583  				{
   584  					Name:       "postcss-discard-comments",
   585  					Version:    "4.0.2",
   586  					PURLType:   purl.TypeNPM,
   587  					Locations:  []string{"testdata/nested-dependencies-dup.v1.json"},
   588  					SourceCode: &extractor.SourceCodeIdentifier{},
   589  					Metadata: osv.DepGroupMetadata{
   590  						DepGroupVals: []string{},
   591  					},
   592  				},
   593  			},
   594  		},
   595  		{
   596  			Name: "commits",
   597  			InputConfig: extracttest.ScanInputMockConfig{
   598  				Path: "testdata/commits.v1.json",
   599  			},
   600  			WantPackages: []*extractor.Package{
   601  				{
   602  					Name:      "@segment/analytics.js-integration-facebook-pixel",
   603  					Version:   "",
   604  					PURLType:  purl.TypeNPM,
   605  					Locations: []string{"testdata/commits.v1.json"},
   606  					SourceCode: &extractor.SourceCodeIdentifier{
   607  						Commit: "3b1bb80b302c2e552685dc8a029797ec832ea7c9",
   608  					},
   609  					Metadata: osv.DepGroupMetadata{
   610  						DepGroupVals: []string{},
   611  					},
   612  				},
   613  				{
   614  					Name:       "ansi-styles",
   615  					Version:    "1.0.0",
   616  					PURLType:   purl.TypeNPM,
   617  					Locations:  []string{"testdata/commits.v1.json"},
   618  					SourceCode: &extractor.SourceCodeIdentifier{},
   619  					Metadata: osv.DepGroupMetadata{
   620  						DepGroupVals: []string{},
   621  					},
   622  				},
   623  				{
   624  					Name:      "babel-preset-php",
   625  					Version:   "",
   626  					PURLType:  purl.TypeNPM,
   627  					Locations: []string{"testdata/commits.v1.json"},
   628  					SourceCode: &extractor.SourceCodeIdentifier{
   629  						Commit: "c5a7ba5e0ad98b8db1cb8ce105403dd4b768cced",
   630  					},
   631  					Metadata: osv.DepGroupMetadata{
   632  						DepGroupVals: []string{},
   633  					},
   634  				},
   635  				{
   636  					Name:      "is-number-1",
   637  					Version:   "",
   638  					PURLType:  purl.TypeNPM,
   639  					Locations: []string{"testdata/commits.v1.json"},
   640  					SourceCode: &extractor.SourceCodeIdentifier{
   641  						Commit: "af885e2e890b9ef0875edd2b117305119ee5bdc5",
   642  					},
   643  					Metadata: osv.DepGroupMetadata{
   644  						DepGroupVals: []string{"dev"},
   645  					},
   646  				},
   647  				{
   648  					Name:      "is-number-1",
   649  					Version:   "",
   650  					PURLType:  purl.TypeNPM,
   651  					Locations: []string{"testdata/commits.v1.json"},
   652  					SourceCode: &extractor.SourceCodeIdentifier{
   653  						Commit: "be5935f8d2595bcd97b05718ef1eeae08d812e10",
   654  					},
   655  					Metadata: osv.DepGroupMetadata{
   656  						DepGroupVals: []string{"dev"},
   657  					},
   658  				},
   659  				{
   660  					Name:      "is-number-2",
   661  					Version:   "",
   662  					PURLType:  purl.TypeNPM,
   663  					Locations: []string{"testdata/commits.v1.json"},
   664  					SourceCode: &extractor.SourceCodeIdentifier{
   665  						Commit: "d5ac0584ee9ae7bd9288220a39780f155b9ad4c8",
   666  					},
   667  					Metadata: osv.DepGroupMetadata{
   668  						DepGroupVals: []string{},
   669  					},
   670  				},
   671  				{
   672  					Name:      "is-number-2",
   673  					Version:   "",
   674  					PURLType:  purl.TypeNPM,
   675  					Locations: []string{"testdata/commits.v1.json"},
   676  					SourceCode: &extractor.SourceCodeIdentifier{
   677  						Commit: "82dcc8e914dabd9305ab9ae580709a7825e824f5",
   678  					},
   679  					Metadata: osv.DepGroupMetadata{
   680  						DepGroupVals: []string{},
   681  					},
   682  				},
   683  				{
   684  					Name:      "is-number-3",
   685  					Version:   "",
   686  					PURLType:  purl.TypeNPM,
   687  					Locations: []string{"testdata/commits.v1.json"},
   688  					SourceCode: &extractor.SourceCodeIdentifier{
   689  						Commit: "d5ac0584ee9ae7bd9288220a39780f155b9ad4c8",
   690  					},
   691  					Metadata: osv.DepGroupMetadata{
   692  						DepGroupVals: []string{"dev"},
   693  					},
   694  				},
   695  				{
   696  					Name:      "is-number-3",
   697  					Version:   "",
   698  					PURLType:  purl.TypeNPM,
   699  					Locations: []string{"testdata/commits.v1.json"},
   700  					SourceCode: &extractor.SourceCodeIdentifier{
   701  						Commit: "82ae8802978da40d7f1be5ad5943c9e550ab2c89",
   702  					},
   703  					Metadata: osv.DepGroupMetadata{
   704  						DepGroupVals: []string{"dev"},
   705  					},
   706  				},
   707  				{
   708  					Name:      "is-number-4",
   709  					Version:   "",
   710  					PURLType:  purl.TypeNPM,
   711  					Locations: []string{"testdata/commits.v1.json"},
   712  					SourceCode: &extractor.SourceCodeIdentifier{
   713  						Commit: "af885e2e890b9ef0875edd2b117305119ee5bdc5",
   714  					},
   715  					Metadata: osv.DepGroupMetadata{
   716  						DepGroupVals: []string{"dev"},
   717  					},
   718  				},
   719  				{
   720  					Name:      "is-number-5",
   721  					Version:   "",
   722  					PURLType:  purl.TypeNPM,
   723  					Locations: []string{"testdata/commits.v1.json"},
   724  					SourceCode: &extractor.SourceCodeIdentifier{
   725  						Commit: "af885e2e890b9ef0875edd2b117305119ee5bdc5",
   726  					},
   727  					Metadata: osv.DepGroupMetadata{
   728  						DepGroupVals: []string{"dev"},
   729  					},
   730  				},
   731  				{
   732  					Name:      "is-number-6",
   733  					Version:   "",
   734  					PURLType:  purl.TypeNPM,
   735  					Locations: []string{"testdata/commits.v1.json"},
   736  					SourceCode: &extractor.SourceCodeIdentifier{
   737  						Commit: "af885e2e890b9ef0875edd2b117305119ee5bdc5",
   738  					},
   739  					Metadata: osv.DepGroupMetadata{
   740  						DepGroupVals: []string{"dev"},
   741  					},
   742  				},
   743  				{
   744  					Name:       "postcss-calc",
   745  					Version:    "7.0.1",
   746  					PURLType:   purl.TypeNPM,
   747  					Locations:  []string{"testdata/commits.v1.json"},
   748  					SourceCode: &extractor.SourceCodeIdentifier{},
   749  					Metadata: osv.DepGroupMetadata{
   750  						DepGroupVals: []string{},
   751  					},
   752  				},
   753  				{
   754  					Name:      "raven-js",
   755  					Version:   "",
   756  					PURLType:  purl.TypeNPM,
   757  					Locations: []string{"testdata/commits.v1.json"},
   758  					SourceCode: &extractor.SourceCodeIdentifier{
   759  						Commit: "c2b377e7a254264fd4a1fe328e4e3cfc9e245570",
   760  					},
   761  					Metadata: osv.DepGroupMetadata{
   762  						DepGroupVals: []string{},
   763  					},
   764  				},
   765  				{
   766  					Name:      "slick-carousel",
   767  					Version:   "",
   768  					PURLType:  purl.TypeNPM,
   769  					Locations: []string{"testdata/commits.v1.json"},
   770  					SourceCode: &extractor.SourceCodeIdentifier{
   771  						Commit: "280b560161b751ba226d50c7db1e0a14a78c2de0",
   772  					},
   773  					Metadata: osv.DepGroupMetadata{
   774  						DepGroupVals: []string{"dev"},
   775  					},
   776  				},
   777  			},
   778  		},
   779  		{
   780  			Name: "files",
   781  			InputConfig: extracttest.ScanInputMockConfig{
   782  				Path: "testdata/files.v1.json",
   783  			},
   784  			WantPackages: []*extractor.Package{
   785  				{
   786  					Name:       "lodash",
   787  					Version:    "1.3.1",
   788  					PURLType:   purl.TypeNPM,
   789  					Locations:  []string{"testdata/files.v1.json"},
   790  					SourceCode: &extractor.SourceCodeIdentifier{},
   791  					Metadata: osv.DepGroupMetadata{
   792  						DepGroupVals: []string{},
   793  					},
   794  				},
   795  				{
   796  					Name:       "other_package",
   797  					Version:    "",
   798  					PURLType:   purl.TypeNPM,
   799  					Locations:  []string{"testdata/files.v1.json"},
   800  					SourceCode: &extractor.SourceCodeIdentifier{},
   801  					Metadata: osv.DepGroupMetadata{
   802  						DepGroupVals: []string{},
   803  					},
   804  				},
   805  			},
   806  		},
   807  		{
   808  			Name: "alias",
   809  			InputConfig: extracttest.ScanInputMockConfig{
   810  				Path: "testdata/alias.v1.json",
   811  			},
   812  			WantPackages: []*extractor.Package{
   813  				{
   814  					Name:       "@babel/code-frame",
   815  					Version:    "7.0.0",
   816  					PURLType:   purl.TypeNPM,
   817  					Locations:  []string{"testdata/alias.v1.json"},
   818  					SourceCode: &extractor.SourceCodeIdentifier{},
   819  					Metadata: osv.DepGroupMetadata{
   820  						DepGroupVals: []string{},
   821  					},
   822  				},
   823  				{
   824  					Name:       "string-width",
   825  					Version:    "4.2.0",
   826  					PURLType:   purl.TypeNPM,
   827  					Locations:  []string{"testdata/alias.v1.json"},
   828  					SourceCode: &extractor.SourceCodeIdentifier{},
   829  					Metadata: osv.DepGroupMetadata{
   830  						DepGroupVals: []string{},
   831  					},
   832  				},
   833  				{
   834  					Name:       "string-width",
   835  					Version:    "5.1.2",
   836  					PURLType:   purl.TypeNPM,
   837  					Locations:  []string{"testdata/alias.v1.json"},
   838  					SourceCode: &extractor.SourceCodeIdentifier{},
   839  					Metadata: osv.DepGroupMetadata{
   840  						DepGroupVals: []string{},
   841  					},
   842  				},
   843  			},
   844  		},
   845  		{
   846  			Name: "optional package",
   847  			InputConfig: extracttest.ScanInputMockConfig{
   848  				Path: "testdata/optional-package.v1.json",
   849  			},
   850  			WantPackages: []*extractor.Package{
   851  				{
   852  					Name:       "wrappy",
   853  					Version:    "1.0.2",
   854  					PURLType:   purl.TypeNPM,
   855  					Locations:  []string{"testdata/optional-package.v1.json"},
   856  					SourceCode: &extractor.SourceCodeIdentifier{},
   857  					Metadata: osv.DepGroupMetadata{
   858  						DepGroupVals: []string{"dev", "optional"},
   859  					},
   860  				},
   861  				{
   862  					Name:       "supports-color",
   863  					Version:    "5.5.0",
   864  					PURLType:   purl.TypeNPM,
   865  					Locations:  []string{"testdata/optional-package.v1.json"},
   866  					SourceCode: &extractor.SourceCodeIdentifier{},
   867  					Metadata: osv.DepGroupMetadata{
   868  						DepGroupVals: []string{"optional"},
   869  					},
   870  				},
   871  			},
   872  		},
   873  		{
   874  			Name: "same package different groups",
   875  			InputConfig: extracttest.ScanInputMockConfig{
   876  				Path: "testdata/same-package-different-groups.v1.json",
   877  			},
   878  			WantPackages: []*extractor.Package{
   879  				{
   880  					Name:       "eslint",
   881  					Version:    "1.2.3",
   882  					PURLType:   purl.TypeNPM,
   883  					Locations:  []string{"testdata/same-package-different-groups.v1.json"},
   884  					SourceCode: &extractor.SourceCodeIdentifier{},
   885  					Metadata: osv.DepGroupMetadata{
   886  						DepGroupVals: []string{"dev"},
   887  					},
   888  				},
   889  				{
   890  					Name:       "table",
   891  					Version:    "1.0.0",
   892  					PURLType:   purl.TypeNPM,
   893  					Locations:  []string{"testdata/same-package-different-groups.v1.json"},
   894  					SourceCode: &extractor.SourceCodeIdentifier{},
   895  					Metadata: osv.DepGroupMetadata{
   896  						DepGroupVals: []string{},
   897  					},
   898  				},
   899  				{
   900  					Name:       "ajv",
   901  					Version:    "5.5.2",
   902  					PURLType:   purl.TypeNPM,
   903  					Locations:  []string{"testdata/same-package-different-groups.v1.json"},
   904  					SourceCode: &extractor.SourceCodeIdentifier{},
   905  					Metadata: osv.DepGroupMetadata{
   906  						DepGroupVals: []string{},
   907  					},
   908  				},
   909  			},
   910  		},
   911  	}
   912  
   913  	for _, tt := range tests {
   914  		t.Run(tt.Name, func(t *testing.T) {
   915  			collector := testcollector.New()
   916  			extr := packagelockjson.New(packagelockjson.Config{
   917  				Stats: collector,
   918  			})
   919  
   920  			scanInput := extracttest.GenerateScanInputMock(t, tt.InputConfig)
   921  			defer extracttest.CloseTestScanInput(t, scanInput)
   922  
   923  			got, err := extr.Extract(t.Context(), &scanInput)
   924  
   925  			if diff := cmp.Diff(tt.WantErr, err, cmpopts.EquateErrors()); diff != "" {
   926  				t.Errorf("%s.Extract(%q) error diff (-want +got):\n%s", extr.Name(), tt.InputConfig.Path, diff)
   927  				return
   928  			}
   929  
   930  			wantInv := inventory.Inventory{Packages: tt.WantPackages}
   931  			if diff := cmp.Diff(wantInv, got, cmpopts.SortSlices(extracttest.PackageCmpLess)); diff != "" {
   932  				t.Errorf("%s.Extract(%q) diff (-want +got):\n%s", extr.Name(), tt.InputConfig.Path, diff)
   933  			}
   934  
   935  			gotFileSizeMetric := collector.FileExtractedFileSize(tt.InputConfig.Path)
   936  			if gotFileSizeMetric != scanInput.Info.Size() {
   937  				t.Errorf("Extract(%s) recorded file size %v, want file size %v", tt.InputConfig.Path, gotFileSizeMetric, scanInput.Info.Size())
   938  			}
   939  		})
   940  	}
   941  }