github.com/google/osv-scalibr@v0.4.1/extractor/filesystem/language/rust/cargotoml/cargotoml_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 cargotoml_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/rust/cargotoml" 24 "github.com/google/osv-scalibr/extractor/filesystem/simplefileapi" 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_FileRequired(t *testing.T) { 31 tests := []struct { 32 name string 33 inputPath string 34 want bool 35 }{ 36 { 37 name: "Empty path", 38 inputPath: "", 39 want: false, 40 }, 41 { 42 name: "", 43 inputPath: "Cargo.toml", 44 want: true, 45 }, 46 { 47 name: "", 48 inputPath: "path/to/my/Cargo.toml", 49 want: true, 50 }, 51 { 52 name: "", 53 inputPath: "path/to/my/Cargo.toml/file", 54 want: false, 55 }, 56 { 57 name: "", 58 inputPath: "path/to/my/Cargo.toml.file", 59 want: false, 60 }, 61 { 62 name: "", 63 inputPath: "path.to.my.Cargo.toml", 64 want: false, 65 }, 66 } 67 68 for _, tt := range tests { 69 t.Run(tt.name, func(t *testing.T) { 70 e := cargotoml.Extractor{} 71 got := e.FileRequired(simplefileapi.New(tt.inputPath, nil)) 72 if got != tt.want { 73 t.Errorf("FileRequired(%s, FileInfo) got = %v, want %v", tt.inputPath, got, tt.want) 74 } 75 }) 76 } 77 } 78 79 func TestExtractor_Extract(t *testing.T) { 80 tests := []extracttest.TestTableEntry{ 81 { 82 Name: "Invalid toml", 83 InputConfig: extracttest.ScanInputMockConfig{ 84 Path: "testdata/not-toml.txt", 85 }, 86 WantPackages: nil, 87 WantErr: extracttest.ContainsErrStr{Str: "could not extract"}, 88 }, 89 { 90 Name: "Invalid dependency toml", 91 InputConfig: extracttest.ScanInputMockConfig{ 92 Path: "testdata/invalid-dependency.toml", 93 }, 94 WantPackages: nil, 95 WantErr: extracttest.ContainsErrStr{Str: "could not extract"}, 96 }, 97 { 98 Name: "no dependencies", 99 InputConfig: extracttest.ScanInputMockConfig{ 100 Path: "testdata/no-dependency.toml", 101 }, 102 WantPackages: []*extractor.Package{ 103 { 104 Name: "hello_world", 105 Version: "0.1.0", 106 PURLType: purl.TypeCargo, 107 Locations: []string{"testdata/no-dependency.toml"}, 108 }, 109 }, 110 }, 111 { 112 Name: "dependency with only version specified", 113 InputConfig: extracttest.ScanInputMockConfig{ 114 Path: "testdata/only-version-dependency.toml", 115 }, 116 WantPackages: []*extractor.Package{ 117 { 118 Name: "hello_world", 119 Version: "0.1.0", 120 PURLType: purl.TypeCargo, 121 Locations: []string{"testdata/only-version-dependency.toml"}, 122 }, 123 { 124 Name: "regex", 125 Version: "0.0.1", 126 PURLType: purl.TypeCargo, 127 Locations: []string{"testdata/only-version-dependency.toml"}, 128 }, 129 }, 130 }, 131 { 132 // dependencies with only tag specified should be skipped 133 Name: "git dependency with tag specified", 134 InputConfig: extracttest.ScanInputMockConfig{ 135 Path: "testdata/git-dependency-tagged.toml", 136 }, 137 WantPackages: []*extractor.Package{ 138 { 139 Name: "hello_world", 140 Version: "0.1.0", 141 PURLType: purl.TypeCargo, 142 Locations: []string{"testdata/git-dependency-tagged.toml"}, 143 }, 144 }, 145 }, 146 { 147 Name: "git dependency with commit specified", 148 InputConfig: extracttest.ScanInputMockConfig{ 149 Path: "testdata/git-dependency-with-commit.toml", 150 }, 151 WantPackages: []*extractor.Package{ 152 { 153 Name: "hello_world", 154 Version: "0.1.0", 155 PURLType: purl.TypeCargo, 156 Locations: []string{"testdata/git-dependency-with-commit.toml"}, 157 }, 158 { 159 Name: "regex", 160 PURLType: purl.TypeCargo, 161 SourceCode: &extractor.SourceCodeIdentifier{ 162 Repo: "https://github.com/rust-lang/regex.git", 163 Commit: "0c0990399270277832fbb5b91a1fa118e6f63dba", 164 }, 165 Locations: []string{"testdata/git-dependency-with-commit.toml"}, 166 }, 167 }, 168 }, 169 { 170 Name: "git dependency with pr rev specified", 171 InputConfig: extracttest.ScanInputMockConfig{ 172 Path: "testdata/git-dependency-with-pr.toml", 173 }, 174 WantPackages: []*extractor.Package{ 175 { 176 Name: "hello_world", 177 Version: "0.1.0", 178 PURLType: purl.TypeCargo, 179 Locations: []string{"testdata/git-dependency-with-pr.toml"}, 180 }, 181 }, 182 }, 183 { 184 Name: "two dependencies", 185 InputConfig: extracttest.ScanInputMockConfig{ 186 Path: "testdata/two-dependencies.toml", 187 }, 188 WantPackages: []*extractor.Package{ 189 { 190 Name: "hello_world", 191 Version: "0.1.0", 192 PURLType: purl.TypeCargo, 193 Locations: []string{"testdata/two-dependencies.toml"}, 194 }, 195 { 196 Name: "futures", 197 Version: "0.3", 198 PURLType: purl.TypeCargo, 199 Locations: []string{"testdata/two-dependencies.toml"}, 200 }, 201 }, 202 }, 203 } 204 205 for _, tt := range tests { 206 t.Run(tt.Name, func(t *testing.T) { 207 extr := cargotoml.Extractor{} 208 209 scanInput := extracttest.GenerateScanInputMock(t, tt.InputConfig) 210 defer extracttest.CloseTestScanInput(t, scanInput) 211 212 got, err := extr.Extract(t.Context(), &scanInput) 213 214 if diff := cmp.Diff(tt.WantErr, err, cmpopts.EquateErrors()); diff != "" { 215 t.Errorf("%s.Extract(%q) error diff (-want +got):\n%s", extr.Name(), tt.InputConfig.Path, diff) 216 return 217 } 218 219 wantInv := inventory.Inventory{Packages: tt.WantPackages} 220 if diff := cmp.Diff(wantInv, got, cmpopts.SortSlices(extracttest.PackageCmpLess)); diff != "" { 221 t.Errorf("%s.Extract(%q) diff (-want +got):\n%s", extr.Name(), tt.InputConfig.Path, diff) 222 } 223 }) 224 } 225 }