github.com/google/osv-scalibr@v0.4.1/extractor/filesystem/language/rust/cargolock/cargolock_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 cargolock_test
    16  
    17  import (
    18  	"testing"
    19  
    20  	"github.com/google/go-cmp/cmp"
    21  	"github.com/google/go-cmp/cmp/cmpopts"
    22  
    23  	"github.com/google/osv-scalibr/extractor"
    24  	"github.com/google/osv-scalibr/extractor/filesystem/language/rust/cargolock"
    25  	"github.com/google/osv-scalibr/extractor/filesystem/simplefileapi"
    26  	"github.com/google/osv-scalibr/inventory"
    27  	"github.com/google/osv-scalibr/purl"
    28  	"github.com/google/osv-scalibr/testing/extracttest"
    29  )
    30  
    31  func TestExtractor_FileRequired(t *testing.T) {
    32  	tests := []struct {
    33  		name      string
    34  		inputPath string
    35  		want      bool
    36  	}{
    37  		{
    38  			name:      "Empty path",
    39  			inputPath: "",
    40  			want:      false,
    41  		},
    42  		{
    43  			name:      "",
    44  			inputPath: "Cargo.lock",
    45  			want:      true,
    46  		},
    47  		{
    48  			name:      "",
    49  			inputPath: "path/to/my/Cargo.lock",
    50  			want:      true,
    51  		},
    52  		{
    53  			name:      "",
    54  			inputPath: "path/to/my/Cargo.lock/file",
    55  			want:      false,
    56  		},
    57  		{
    58  			name:      "",
    59  			inputPath: "path/to/my/Cargo.lock.file",
    60  			want:      false,
    61  		},
    62  		{
    63  			name:      "",
    64  			inputPath: "path.to.my.Cargo.lock",
    65  			want:      false,
    66  		},
    67  	}
    68  
    69  	for _, tt := range tests {
    70  		t.Run(tt.name, func(t *testing.T) {
    71  			e := cargolock.Extractor{}
    72  			got := e.FileRequired(simplefileapi.New(tt.inputPath, nil))
    73  			if got != tt.want {
    74  				t.Errorf("FileRequired(%s, FileInfo) got = %v, want %v", tt.inputPath, got, tt.want)
    75  			}
    76  		})
    77  	}
    78  }
    79  
    80  func TestExtractor_Extract(t *testing.T) {
    81  	tests := []extracttest.TestTableEntry{
    82  		{
    83  			Name: "Invalid toml",
    84  			InputConfig: extracttest.ScanInputMockConfig{
    85  				Path: "testdata/not-toml.txt",
    86  			},
    87  			WantPackages: nil,
    88  			WantErr:      extracttest.ContainsErrStr{Str: "could not extract"},
    89  		},
    90  		{
    91  			Name: "no packages",
    92  			InputConfig: extracttest.ScanInputMockConfig{
    93  				Path: "testdata/empty.lock",
    94  			},
    95  			WantPackages: []*extractor.Package{},
    96  		},
    97  		{
    98  			Name: "one package",
    99  			InputConfig: extracttest.ScanInputMockConfig{
   100  				Path: "testdata/one-package.lock",
   101  			},
   102  			WantPackages: []*extractor.Package{
   103  				{
   104  					Name:      "addr2line",
   105  					Version:   "0.15.2",
   106  					PURLType:  purl.TypeCargo,
   107  					Locations: []string{"testdata/one-package.lock"},
   108  				},
   109  			},
   110  		},
   111  		{
   112  			Name: "two packages",
   113  			InputConfig: extracttest.ScanInputMockConfig{
   114  				Path: "testdata/two-packages.lock",
   115  			},
   116  			WantPackages: []*extractor.Package{
   117  				{
   118  					Name:      "addr2line",
   119  					Version:   "0.15.2",
   120  					PURLType:  purl.TypeCargo,
   121  					Locations: []string{"testdata/two-packages.lock"},
   122  				},
   123  				{
   124  					Name:      "syn",
   125  					Version:   "1.0.73",
   126  					PURLType:  purl.TypeCargo,
   127  					Locations: []string{"testdata/two-packages.lock"},
   128  				},
   129  			},
   130  		},
   131  		{
   132  			Name: "two packages with local",
   133  			InputConfig: extracttest.ScanInputMockConfig{
   134  				Path: "testdata/two-packages-with-local.lock",
   135  			},
   136  			WantPackages: []*extractor.Package{
   137  				{
   138  					Name:      "addr2line",
   139  					Version:   "0.15.2",
   140  					PURLType:  purl.TypeCargo,
   141  					Locations: []string{"testdata/two-packages-with-local.lock"},
   142  				},
   143  				{
   144  					Name:      "local-rust-pkg",
   145  					Version:   "0.1.0",
   146  					PURLType:  purl.TypeCargo,
   147  					Locations: []string{"testdata/two-packages-with-local.lock"},
   148  				},
   149  			},
   150  		},
   151  		{
   152  			Name: "package with build string",
   153  			InputConfig: extracttest.ScanInputMockConfig{
   154  				Path: "testdata/package-with-build-string.lock",
   155  			},
   156  			WantPackages: []*extractor.Package{
   157  				{
   158  					Name:      "wasi",
   159  					Version:   "0.10.2+wasi-snapshot-preview1",
   160  					PURLType:  purl.TypeCargo,
   161  					Locations: []string{"testdata/package-with-build-string.lock"},
   162  				},
   163  			},
   164  		},
   165  	}
   166  	for _, tt := range tests {
   167  		t.Run(tt.Name, func(t *testing.T) {
   168  			extr := cargolock.Extractor{}
   169  
   170  			scanInput := extracttest.GenerateScanInputMock(t, tt.InputConfig)
   171  			defer extracttest.CloseTestScanInput(t, scanInput)
   172  
   173  			got, err := extr.Extract(t.Context(), &scanInput)
   174  
   175  			if diff := cmp.Diff(tt.WantErr, err, cmpopts.EquateErrors()); diff != "" {
   176  				t.Errorf("%s.Extract(%q) error diff (-want +got):\n%s", extr.Name(), tt.InputConfig.Path, diff)
   177  				return
   178  			}
   179  
   180  			wantInv := inventory.Inventory{Packages: tt.WantPackages}
   181  			if diff := cmp.Diff(wantInv, got, cmpopts.SortSlices(extracttest.PackageCmpLess)); diff != "" {
   182  				t.Errorf("%s.Extract(%q) diff (-want +got):\n%s", extr.Name(), tt.InputConfig.Path, diff)
   183  			}
   184  		})
   185  	}
   186  }