github.com/google/osv-scalibr@v0.4.1/extractor/filesystem/language/javascript/packagelockjson/packagelockjson-v2_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_V2(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.v2.json",
    44  			},
    45  			WantPackages: []*extractor.Package{},
    46  		},
    47  		{
    48  			Name: "one package",
    49  			InputConfig: extracttest.ScanInputMockConfig{
    50  				Path: "testdata/one-package.v2.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.v2.json"},
    58  					SourceCode: &extractor.SourceCodeIdentifier{
    59  						Commit: "",
    60  					},
    61  					Metadata: osv.DepGroupMetadata{
    62  						DepGroupVals: []string{},
    63  					},
    64  				},
    65  			},
    66  		},
    67  		{
    68  			Name: "one package dev",
    69  			InputConfig: extracttest.ScanInputMockConfig{
    70  				Path: "testdata/one-package-dev.v2.json",
    71  			},
    72  			WantPackages: []*extractor.Package{
    73  				{
    74  					Name:      "wrappy",
    75  					Version:   "1.0.2",
    76  					PURLType:  purl.TypeNPM,
    77  					Locations: []string{"testdata/one-package-dev.v2.json"},
    78  					SourceCode: &extractor.SourceCodeIdentifier{
    79  						Commit: "",
    80  					},
    81  					Metadata: osv.DepGroupMetadata{
    82  						DepGroupVals: []string{"dev"},
    83  					},
    84  				},
    85  			},
    86  		},
    87  		{
    88  			Name: "two packages",
    89  			InputConfig: extracttest.ScanInputMockConfig{
    90  				Path: "testdata/two-packages.v2.json",
    91  			},
    92  			WantPackages: []*extractor.Package{
    93  				{
    94  					Name:      "wrappy",
    95  					Version:   "1.0.2",
    96  					PURLType:  purl.TypeNPM,
    97  					Locations: []string{"testdata/two-packages.v2.json"},
    98  					SourceCode: &extractor.SourceCodeIdentifier{
    99  						Commit: "",
   100  					},
   101  					Metadata: osv.DepGroupMetadata{
   102  						DepGroupVals: []string{},
   103  					},
   104  				},
   105  				{
   106  					Name:      "supports-color",
   107  					Version:   "5.5.0",
   108  					PURLType:  purl.TypeNPM,
   109  					Locations: []string{"testdata/two-packages.v2.json"},
   110  					SourceCode: &extractor.SourceCodeIdentifier{
   111  						Commit: "",
   112  					},
   113  					Metadata: osv.DepGroupMetadata{
   114  						DepGroupVals: []string{},
   115  					},
   116  				},
   117  			},
   118  		},
   119  		{
   120  			Name: "scoped packages",
   121  			InputConfig: extracttest.ScanInputMockConfig{
   122  				Path: "testdata/scoped-packages.v2.json",
   123  			},
   124  			WantPackages: []*extractor.Package{
   125  				{
   126  					Name:      "wrappy",
   127  					Version:   "1.0.2",
   128  					PURLType:  purl.TypeNPM,
   129  					Locations: []string{"testdata/scoped-packages.v2.json"},
   130  					SourceCode: &extractor.SourceCodeIdentifier{
   131  						Commit: "",
   132  					},
   133  					Metadata: osv.DepGroupMetadata{
   134  						DepGroupVals: []string{},
   135  					},
   136  				},
   137  				{
   138  					Name:      "@babel/code-frame",
   139  					Version:   "7.0.0",
   140  					PURLType:  purl.TypeNPM,
   141  					Locations: []string{"testdata/scoped-packages.v2.json"},
   142  					SourceCode: &extractor.SourceCodeIdentifier{
   143  						Commit: "",
   144  					},
   145  					Metadata: osv.DepGroupMetadata{
   146  						DepGroupVals: []string{},
   147  					},
   148  				},
   149  			},
   150  		},
   151  		{
   152  			Name: "nested dependencies",
   153  			InputConfig: extracttest.ScanInputMockConfig{
   154  				Path: "testdata/nested-dependencies.v2.json",
   155  			},
   156  			WantPackages: []*extractor.Package{
   157  				{
   158  					Name:      "postcss",
   159  					Version:   "6.0.23",
   160  					PURLType:  purl.TypeNPM,
   161  					Locations: []string{"testdata/nested-dependencies.v2.json"},
   162  					SourceCode: &extractor.SourceCodeIdentifier{
   163  						Commit: "",
   164  					},
   165  					Metadata: osv.DepGroupMetadata{
   166  						DepGroupVals: []string{},
   167  					},
   168  				},
   169  				{
   170  					Name:      "postcss",
   171  					Version:   "7.0.16",
   172  					PURLType:  purl.TypeNPM,
   173  					Locations: []string{"testdata/nested-dependencies.v2.json"},
   174  					SourceCode: &extractor.SourceCodeIdentifier{
   175  						Commit: "",
   176  					},
   177  					Metadata: osv.DepGroupMetadata{
   178  						DepGroupVals: []string{},
   179  					},
   180  				},
   181  				{
   182  					Name:      "postcss-calc",
   183  					Version:   "7.0.1",
   184  					PURLType:  purl.TypeNPM,
   185  					Locations: []string{"testdata/nested-dependencies.v2.json"},
   186  					SourceCode: &extractor.SourceCodeIdentifier{
   187  						Commit: "",
   188  					},
   189  					Metadata: osv.DepGroupMetadata{
   190  						DepGroupVals: []string{},
   191  					},
   192  				},
   193  				{
   194  					Name:      "supports-color",
   195  					Version:   "6.1.0",
   196  					PURLType:  purl.TypeNPM,
   197  					Locations: []string{"testdata/nested-dependencies.v2.json"},
   198  					SourceCode: &extractor.SourceCodeIdentifier{
   199  						Commit: "",
   200  					},
   201  					Metadata: osv.DepGroupMetadata{
   202  						DepGroupVals: []string{},
   203  					},
   204  				},
   205  				{
   206  					Name:      "supports-color",
   207  					Version:   "5.5.0",
   208  					PURLType:  purl.TypeNPM,
   209  					Locations: []string{"testdata/nested-dependencies.v2.json"},
   210  					SourceCode: &extractor.SourceCodeIdentifier{
   211  						Commit: "",
   212  					},
   213  					Metadata: osv.DepGroupMetadata{
   214  						DepGroupVals: []string{},
   215  					},
   216  				},
   217  			},
   218  		},
   219  		{
   220  			Name: "nested dependencies dup",
   221  			InputConfig: extracttest.ScanInputMockConfig{
   222  				Path: "testdata/nested-dependencies-dup.v2.json",
   223  			},
   224  			WantPackages: []*extractor.Package{
   225  				{
   226  					Name:      "supports-color",
   227  					Version:   "6.1.0",
   228  					PURLType:  purl.TypeNPM,
   229  					Locations: []string{"testdata/nested-dependencies-dup.v2.json"},
   230  					SourceCode: &extractor.SourceCodeIdentifier{
   231  						Commit: "",
   232  					},
   233  					Metadata: osv.DepGroupMetadata{
   234  						DepGroupVals: []string{},
   235  					},
   236  				},
   237  				{
   238  					Name:      "supports-color",
   239  					Version:   "2.0.0",
   240  					PURLType:  purl.TypeNPM,
   241  					Locations: []string{"testdata/nested-dependencies-dup.v2.json"},
   242  					SourceCode: &extractor.SourceCodeIdentifier{
   243  						Commit: "",
   244  					},
   245  					Metadata: osv.DepGroupMetadata{
   246  						DepGroupVals: []string{},
   247  					},
   248  				},
   249  			},
   250  		},
   251  		{
   252  			Name: "commits",
   253  			InputConfig: extracttest.ScanInputMockConfig{
   254  				Path: "testdata/commits.v2.json",
   255  			},
   256  			WantPackages: []*extractor.Package{
   257  				{
   258  					Name:      "@segment/analytics.js-integration-facebook-pixel",
   259  					Version:   "2.4.1",
   260  					PURLType:  purl.TypeNPM,
   261  					Locations: []string{"testdata/commits.v2.json"},
   262  					SourceCode: &extractor.SourceCodeIdentifier{
   263  						Commit: "3b1bb80b302c2e552685dc8a029797ec832ea7c9",
   264  					},
   265  					Metadata: osv.DepGroupMetadata{
   266  						DepGroupVals: []string{},
   267  					},
   268  				},
   269  				{
   270  					Name:      "ansi-styles",
   271  					Version:   "1.0.0",
   272  					PURLType:  purl.TypeNPM,
   273  					Locations: []string{"testdata/commits.v2.json"},
   274  					SourceCode: &extractor.SourceCodeIdentifier{
   275  						Commit: "",
   276  					},
   277  					Metadata: osv.DepGroupMetadata{
   278  						DepGroupVals: []string{},
   279  					},
   280  				},
   281  				{
   282  					Name:      "babel-preset-php",
   283  					Version:   "1.1.1",
   284  					PURLType:  purl.TypeNPM,
   285  					Locations: []string{"testdata/commits.v2.json"},
   286  					SourceCode: &extractor.SourceCodeIdentifier{
   287  						Commit: "c5a7ba5e0ad98b8db1cb8ce105403dd4b768cced",
   288  					},
   289  					Metadata: osv.DepGroupMetadata{
   290  						DepGroupVals: []string{"dev"},
   291  					},
   292  				},
   293  				{
   294  					Name:      "is-number-1",
   295  					Version:   "3.0.0",
   296  					PURLType:  purl.TypeNPM,
   297  					Locations: []string{"testdata/commits.v2.json"},
   298  					SourceCode: &extractor.SourceCodeIdentifier{
   299  						Commit: "af885e2e890b9ef0875edd2b117305119ee5bdc5",
   300  					},
   301  					Metadata: osv.DepGroupMetadata{
   302  						DepGroupVals: []string{"dev"},
   303  					},
   304  				},
   305  				{
   306  					Name:      "is-number-1",
   307  					Version:   "3.0.0",
   308  					PURLType:  purl.TypeNPM,
   309  					Locations: []string{"testdata/commits.v2.json"},
   310  					SourceCode: &extractor.SourceCodeIdentifier{
   311  						Commit: "be5935f8d2595bcd97b05718ef1eeae08d812e10",
   312  					},
   313  					Metadata: osv.DepGroupMetadata{
   314  						DepGroupVals: []string{"dev"},
   315  					},
   316  				},
   317  				{
   318  					Name:      "is-number-2",
   319  					Version:   "2.0.0",
   320  					PURLType:  purl.TypeNPM,
   321  					Locations: []string{"testdata/commits.v2.json"},
   322  					SourceCode: &extractor.SourceCodeIdentifier{
   323  						Commit: "d5ac0584ee9ae7bd9288220a39780f155b9ad4c8",
   324  					},
   325  					Metadata: osv.DepGroupMetadata{
   326  						DepGroupVals: []string{"dev"},
   327  					},
   328  				},
   329  				{
   330  					Name:      "is-number-2",
   331  					Version:   "2.0.0",
   332  					PURLType:  purl.TypeNPM,
   333  					Locations: []string{"testdata/commits.v2.json"},
   334  					SourceCode: &extractor.SourceCodeIdentifier{
   335  						Commit: "82dcc8e914dabd9305ab9ae580709a7825e824f5",
   336  					},
   337  					Metadata: osv.DepGroupMetadata{
   338  						DepGroupVals: []string{"dev"},
   339  					},
   340  				},
   341  				{
   342  					Name:      "is-number-3",
   343  					Version:   "2.0.0",
   344  					PURLType:  purl.TypeNPM,
   345  					Locations: []string{"testdata/commits.v2.json"},
   346  					SourceCode: &extractor.SourceCodeIdentifier{
   347  						Commit: "d5ac0584ee9ae7bd9288220a39780f155b9ad4c8",
   348  					},
   349  					Metadata: osv.DepGroupMetadata{
   350  						DepGroupVals: []string{"dev"},
   351  					},
   352  				},
   353  				{
   354  					Name:      "is-number-3",
   355  					Version:   "3.0.0",
   356  					PURLType:  purl.TypeNPM,
   357  					Locations: []string{"testdata/commits.v2.json"},
   358  					SourceCode: &extractor.SourceCodeIdentifier{
   359  						Commit: "82ae8802978da40d7f1be5ad5943c9e550ab2c89",
   360  					},
   361  					Metadata: osv.DepGroupMetadata{
   362  						DepGroupVals: []string{"dev"},
   363  					},
   364  				},
   365  				{
   366  					Name:      "is-number-4",
   367  					Version:   "3.0.0",
   368  					PURLType:  purl.TypeNPM,
   369  					Locations: []string{"testdata/commits.v2.json"},
   370  					SourceCode: &extractor.SourceCodeIdentifier{
   371  						Commit: "af885e2e890b9ef0875edd2b117305119ee5bdc5",
   372  					},
   373  					Metadata: osv.DepGroupMetadata{
   374  						DepGroupVals: []string{"dev"},
   375  					},
   376  				},
   377  				{
   378  					Name:      "is-number-5",
   379  					Version:   "3.0.0",
   380  					PURLType:  purl.TypeNPM,
   381  					Locations: []string{"testdata/commits.v2.json"},
   382  					SourceCode: &extractor.SourceCodeIdentifier{
   383  						Commit: "af885e2e890b9ef0875edd2b117305119ee5bdc5",
   384  					},
   385  					Metadata: osv.DepGroupMetadata{
   386  						DepGroupVals: []string{"dev"},
   387  					},
   388  				},
   389  				{
   390  					Name:      "postcss-calc",
   391  					Version:   "7.0.1",
   392  					PURLType:  purl.TypeNPM,
   393  					Locations: []string{"testdata/commits.v2.json"},
   394  					SourceCode: &extractor.SourceCodeIdentifier{
   395  						Commit: "",
   396  					},
   397  					Metadata: osv.DepGroupMetadata{
   398  						DepGroupVals: []string{},
   399  					},
   400  				},
   401  				{
   402  					Name:      "raven-js",
   403  					Version:   "",
   404  					PURLType:  purl.TypeNPM,
   405  					Locations: []string{"testdata/commits.v2.json"},
   406  					SourceCode: &extractor.SourceCodeIdentifier{
   407  						Commit: "c2b377e7a254264fd4a1fe328e4e3cfc9e245570",
   408  					},
   409  					Metadata: osv.DepGroupMetadata{
   410  						DepGroupVals: []string{},
   411  					},
   412  				},
   413  				{
   414  					Name:      "slick-carousel",
   415  					Version:   "1.7.1",
   416  					PURLType:  purl.TypeNPM,
   417  					Locations: []string{"testdata/commits.v2.json"},
   418  					SourceCode: &extractor.SourceCodeIdentifier{
   419  						Commit: "280b560161b751ba226d50c7db1e0a14a78c2de0",
   420  					},
   421  					Metadata: osv.DepGroupMetadata{
   422  						DepGroupVals: []string{"dev"},
   423  					},
   424  				},
   425  			},
   426  		},
   427  		{
   428  			Name: "files",
   429  			InputConfig: extracttest.ScanInputMockConfig{
   430  				Path: "testdata/files.v2.json",
   431  			},
   432  			WantPackages: []*extractor.Package{
   433  				{
   434  					Name:      "etag",
   435  					Version:   "1.8.0",
   436  					PURLType:  purl.TypeNPM,
   437  					Locations: []string{"testdata/files.v2.json"},
   438  					SourceCode: &extractor.SourceCodeIdentifier{
   439  						Commit: "",
   440  					},
   441  					Metadata: osv.DepGroupMetadata{
   442  						DepGroupVals: []string{"dev"},
   443  					},
   444  				},
   445  				{
   446  					Name:      "abbrev",
   447  					Version:   "1.0.9",
   448  					PURLType:  purl.TypeNPM,
   449  					Locations: []string{"testdata/files.v2.json"},
   450  					SourceCode: &extractor.SourceCodeIdentifier{
   451  						Commit: "",
   452  					},
   453  					Metadata: osv.DepGroupMetadata{
   454  						DepGroupVals: []string{"dev"},
   455  					},
   456  				},
   457  				{
   458  					Name:      "abbrev",
   459  					Version:   "2.3.4",
   460  					PURLType:  purl.TypeNPM,
   461  					Locations: []string{"testdata/files.v2.json"},
   462  					SourceCode: &extractor.SourceCodeIdentifier{
   463  						Commit: "",
   464  					},
   465  					Metadata: osv.DepGroupMetadata{
   466  						DepGroupVals: []string{"dev"},
   467  					},
   468  				},
   469  			},
   470  		},
   471  		{
   472  			Name: "alias",
   473  			InputConfig: extracttest.ScanInputMockConfig{
   474  				Path: "testdata/alias.v2.json",
   475  			},
   476  			WantPackages: []*extractor.Package{
   477  				{
   478  					Name:      "@babel/code-frame",
   479  					Version:   "7.0.0",
   480  					PURLType:  purl.TypeNPM,
   481  					Locations: []string{"testdata/alias.v2.json"},
   482  					SourceCode: &extractor.SourceCodeIdentifier{
   483  						Commit: "",
   484  					},
   485  					Metadata: osv.DepGroupMetadata{
   486  						DepGroupVals: []string{},
   487  					},
   488  				},
   489  				{
   490  					Name:      "string-width",
   491  					Version:   "4.2.0",
   492  					PURLType:  purl.TypeNPM,
   493  					Locations: []string{"testdata/alias.v2.json"},
   494  					SourceCode: &extractor.SourceCodeIdentifier{
   495  						Commit: "",
   496  					},
   497  					Metadata: osv.DepGroupMetadata{
   498  						DepGroupVals: []string{},
   499  					},
   500  				},
   501  				{
   502  					Name:      "string-width",
   503  					Version:   "5.1.2",
   504  					PURLType:  purl.TypeNPM,
   505  					Locations: []string{"testdata/alias.v2.json"},
   506  					SourceCode: &extractor.SourceCodeIdentifier{
   507  						Commit: "",
   508  					},
   509  					Metadata: osv.DepGroupMetadata{
   510  						DepGroupVals: []string{},
   511  					},
   512  				},
   513  			},
   514  		},
   515  		{
   516  			Name: "optional package",
   517  			InputConfig: extracttest.ScanInputMockConfig{
   518  				Path: "testdata/optional-package.v2.json",
   519  			},
   520  			WantPackages: []*extractor.Package{
   521  				{
   522  					Name:      "wrappy",
   523  					Version:   "1.0.2",
   524  					PURLType:  purl.TypeNPM,
   525  					Locations: []string{"testdata/optional-package.v2.json"},
   526  					SourceCode: &extractor.SourceCodeIdentifier{
   527  						Commit: "",
   528  					},
   529  					Metadata: osv.DepGroupMetadata{
   530  						DepGroupVals: []string{"optional"},
   531  					},
   532  				},
   533  				{
   534  					Name:      "supports-color",
   535  					Version:   "5.5.0",
   536  					PURLType:  purl.TypeNPM,
   537  					Locations: []string{"testdata/optional-package.v2.json"},
   538  					SourceCode: &extractor.SourceCodeIdentifier{
   539  						Commit: "",
   540  					},
   541  					Metadata: osv.DepGroupMetadata{
   542  						DepGroupVals: []string{"dev", "optional"},
   543  					},
   544  				},
   545  			},
   546  		},
   547  		{
   548  			Name: "same package different groups",
   549  			InputConfig: extracttest.ScanInputMockConfig{
   550  				Path: "testdata/same-package-different-groups.v2.json",
   551  			},
   552  			WantPackages: []*extractor.Package{
   553  				{
   554  					Name:      "eslint",
   555  					Version:   "1.2.3",
   556  					PURLType:  purl.TypeNPM,
   557  					Locations: []string{"testdata/same-package-different-groups.v2.json"},
   558  					SourceCode: &extractor.SourceCodeIdentifier{
   559  						Commit: "",
   560  					},
   561  					Metadata: osv.DepGroupMetadata{
   562  						DepGroupVals: []string{"dev"},
   563  					},
   564  				},
   565  				{
   566  					Name:      "table",
   567  					Version:   "1.0.0",
   568  					PURLType:  purl.TypeNPM,
   569  					Locations: []string{"testdata/same-package-different-groups.v2.json"},
   570  					SourceCode: &extractor.SourceCodeIdentifier{
   571  						Commit: "",
   572  					},
   573  					Metadata: osv.DepGroupMetadata{
   574  						DepGroupVals: []string{},
   575  					},
   576  				},
   577  				{
   578  					Name:      "ajv",
   579  					Version:   "5.5.2",
   580  					PURLType:  purl.TypeNPM,
   581  					Locations: []string{"testdata/same-package-different-groups.v2.json"},
   582  					SourceCode: &extractor.SourceCodeIdentifier{
   583  						Commit: "",
   584  					},
   585  					Metadata: osv.DepGroupMetadata{
   586  						DepGroupVals: []string{},
   587  					},
   588  				},
   589  			},
   590  		},
   591  		{
   592  			Name: "bundled_dependencies_are_grouped",
   593  			InputConfig: extracttest.ScanInputMockConfig{
   594  				Path: "testdata/bundled-dependencies.v3.json",
   595  			},
   596  			WantPackages: []*extractor.Package{
   597  				{
   598  					Name:      "ansi-regex",
   599  					Version:   "6.2.2",
   600  					PURLType:  purl.TypeNPM,
   601  					Locations: []string{"testdata/bundled-dependencies.v3.json"},
   602  					SourceCode: &extractor.SourceCodeIdentifier{
   603  						Commit: "",
   604  					},
   605  					Metadata: osv.DepGroupMetadata{
   606  						DepGroupVals: []string{"bundled"},
   607  					},
   608  				},
   609  				{
   610  					Name:      "semver",
   611  					Version:   "7.7.2",
   612  					PURLType:  purl.TypeNPM,
   613  					Locations: []string{"testdata/bundled-dependencies.v3.json"},
   614  					SourceCode: &extractor.SourceCodeIdentifier{
   615  						Commit: "",
   616  					},
   617  					Metadata: osv.DepGroupMetadata{
   618  						DepGroupVals: []string{"bundled", "dev"},
   619  					},
   620  				},
   621  				{
   622  					Name:      "strip-ansi",
   623  					Version:   "7.1.2",
   624  					PURLType:  purl.TypeNPM,
   625  					Locations: []string{"testdata/bundled-dependencies.v3.json"},
   626  					SourceCode: &extractor.SourceCodeIdentifier{
   627  						Commit: "",
   628  					},
   629  					Metadata: osv.DepGroupMetadata{
   630  						DepGroupVals: []string{},
   631  					},
   632  				},
   633  			},
   634  		},
   635  	}
   636  
   637  	for _, tt := range tests {
   638  		t.Run(tt.Name, func(t *testing.T) {
   639  			collector := testcollector.New()
   640  			extr := packagelockjson.New(packagelockjson.Config{
   641  				Stats: collector,
   642  			})
   643  
   644  			scanInput := extracttest.GenerateScanInputMock(t, tt.InputConfig)
   645  			defer extracttest.CloseTestScanInput(t, scanInput)
   646  
   647  			got, err := extr.Extract(t.Context(), &scanInput)
   648  
   649  			if diff := cmp.Diff(tt.WantErr, err, cmpopts.EquateErrors()); diff != "" {
   650  				t.Errorf("%s.Extract(%q) error diff (-want +got):\n%s", extr.Name(), tt.InputConfig.Path, diff)
   651  				return
   652  			}
   653  
   654  			wantInv := inventory.Inventory{Packages: tt.WantPackages}
   655  			if diff := cmp.Diff(wantInv, got, cmpopts.SortSlices(extracttest.PackageCmpLess)); diff != "" {
   656  				t.Errorf("%s.Extract(%q) diff (-want +got):\n%s", extr.Name(), tt.InputConfig.Path, diff)
   657  			}
   658  
   659  			gotFileSizeMetric := collector.FileExtractedFileSize(tt.InputConfig.Path)
   660  			if gotFileSizeMetric != scanInput.Info.Size() {
   661  				t.Errorf("Extract(%s) recorded file size %v, want file size %v", tt.InputConfig.Path, gotFileSizeMetric, scanInput.Info.Size())
   662  			}
   663  		})
   664  	}
   665  }