github.com/google/osv-scalibr@v0.4.1/extractor/filesystem/language/java/gradlelockfile/gradlelockfile_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 gradlelockfile_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/java/gradlelockfile" 24 "github.com/google/osv-scalibr/extractor/filesystem/language/java/javalockfile" 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 inputPath string 34 want bool 35 }{ 36 { 37 inputPath: "", 38 want: false, 39 }, 40 { 41 inputPath: "buildscript-gradle.lockfile", 42 want: true, 43 }, 44 { 45 inputPath: "path/to/my/buildscript-gradle.lockfile", 46 want: true, 47 }, 48 { 49 inputPath: "path/to/my/buildscript-gradle.lockfile/file", 50 want: false, 51 }, 52 { 53 inputPath: "path/to/my/buildscript-gradle.lockfile.file", 54 want: false, 55 }, 56 { 57 inputPath: "path.to.my.buildscript-gradle.lockfile", 58 want: false, 59 }, 60 { 61 inputPath: "gradle.lockfile", 62 want: true, 63 }, 64 { 65 inputPath: "path/to/my/gradle.lockfile", 66 want: true, 67 }, 68 { 69 inputPath: "path/to/my/gradle.lockfile/file", 70 want: false, 71 }, 72 { 73 inputPath: "path/to/my/gradle.lockfile.file", 74 want: false, 75 }, 76 { 77 inputPath: "path.to.my.gradle.lockfile", 78 want: false, 79 }, 80 } 81 for _, tt := range tests { 82 t.Run(tt.inputPath, func(t *testing.T) { 83 e := gradlelockfile.Extractor{} 84 got := e.FileRequired(simplefileapi.New(tt.inputPath, nil)) 85 if got != tt.want { 86 t.Errorf("FileRequired(%s, FileInfo) got = %v, want %v", tt.inputPath, got, tt.want) 87 } 88 }) 89 } 90 } 91 92 func TestExtractor_Extract(t *testing.T) { 93 tests := []extracttest.TestTableEntry{ 94 { 95 Name: "only comments", 96 InputConfig: extracttest.ScanInputMockConfig{ 97 Path: "testdata/only-comments", 98 }, 99 WantPackages: []*extractor.Package{}, 100 }, 101 { 102 Name: "empty statement", 103 InputConfig: extracttest.ScanInputMockConfig{ 104 Path: "testdata/only-empty", 105 }, 106 WantPackages: []*extractor.Package{}, 107 }, 108 { 109 Name: "one package", 110 InputConfig: extracttest.ScanInputMockConfig{ 111 Path: "testdata/one-pkg", 112 }, 113 WantPackages: []*extractor.Package{ 114 { 115 Name: "org.springframework.security:spring-security-crypto", 116 Version: "5.7.3", 117 PURLType: purl.TypeMaven, 118 Locations: []string{"testdata/one-pkg"}, 119 Metadata: &javalockfile.Metadata{ 120 ArtifactID: "spring-security-crypto", 121 GroupID: "org.springframework.security", 122 }, 123 }, 124 }, 125 }, 126 { 127 Name: "multiple package", 128 InputConfig: extracttest.ScanInputMockConfig{ 129 Path: "testdata/5-pkg", 130 }, 131 WantPackages: []*extractor.Package{ 132 { 133 Name: "org.springframework.boot:spring-boot-autoconfigure", 134 Version: "2.7.4", 135 PURLType: purl.TypeMaven, 136 Locations: []string{"testdata/5-pkg"}, 137 Metadata: &javalockfile.Metadata{ 138 ArtifactID: "spring-boot-autoconfigure", 139 GroupID: "org.springframework.boot", 140 }, 141 }, 142 { 143 Name: "org.springframework.boot:spring-boot-configuration-processor", 144 Version: "2.7.5", 145 PURLType: purl.TypeMaven, 146 Locations: []string{"testdata/5-pkg"}, 147 Metadata: &javalockfile.Metadata{ 148 ArtifactID: "spring-boot-configuration-processor", 149 GroupID: "org.springframework.boot", 150 }, 151 }, 152 { 153 Name: "org.springframework.boot:spring-boot-devtools", 154 Version: "2.7.6", 155 PURLType: purl.TypeMaven, 156 Locations: []string{"testdata/5-pkg"}, 157 Metadata: &javalockfile.Metadata{ 158 ArtifactID: "spring-boot-devtools", 159 GroupID: "org.springframework.boot", 160 }, 161 }, 162 { 163 Name: "org.springframework.boot:spring-boot-starter-aop", 164 Version: "2.7.7", 165 PURLType: purl.TypeMaven, 166 Locations: []string{"testdata/5-pkg"}, 167 Metadata: &javalockfile.Metadata{ 168 ArtifactID: "spring-boot-starter-aop", 169 GroupID: "org.springframework.boot", 170 }, 171 }, 172 { 173 Name: "org.springframework.boot:spring-boot-starter-data-jpa", 174 Version: "2.7.8", 175 PURLType: purl.TypeMaven, 176 Locations: []string{"testdata/5-pkg"}, 177 Metadata: &javalockfile.Metadata{ 178 ArtifactID: "spring-boot-starter-data-jpa", 179 GroupID: "org.springframework.boot", 180 }, 181 }, 182 }, 183 }, 184 { 185 Name: "with invalid lines", 186 InputConfig: extracttest.ScanInputMockConfig{ 187 Path: "testdata/with-bad-pkg", 188 }, 189 WantPackages: []*extractor.Package{ 190 { 191 Name: "org.springframework.boot:spring-boot-autoconfigure", 192 Version: "2.7.4", 193 PURLType: purl.TypeMaven, 194 Locations: []string{"testdata/with-bad-pkg"}, 195 Metadata: &javalockfile.Metadata{ 196 ArtifactID: "spring-boot-autoconfigure", 197 GroupID: "org.springframework.boot", 198 }, 199 }, 200 { 201 Name: "org.springframework.boot:spring-boot-configuration-processor", 202 Version: "2.7.5", 203 PURLType: purl.TypeMaven, 204 Locations: []string{"testdata/with-bad-pkg"}, 205 Metadata: &javalockfile.Metadata{ 206 ArtifactID: "spring-boot-configuration-processor", 207 GroupID: "org.springframework.boot", 208 }, 209 }, 210 }, 211 }, 212 } 213 214 for _, tt := range tests { 215 t.Run(tt.Name, func(t *testing.T) { 216 extr := gradlelockfile.Extractor{} 217 218 scanInput := extracttest.GenerateScanInputMock(t, tt.InputConfig) 219 defer extracttest.CloseTestScanInput(t, scanInput) 220 221 got, err := extr.Extract(t.Context(), &scanInput) 222 223 if diff := cmp.Diff(tt.WantErr, err, cmpopts.EquateErrors()); diff != "" { 224 t.Errorf("%s.Extract(%q) error diff (-want +got):\n%s", extr.Name(), tt.InputConfig.Path, diff) 225 return 226 } 227 228 wantInv := inventory.Inventory{Packages: tt.WantPackages} 229 if diff := cmp.Diff(wantInv, got, cmpopts.SortSlices(extracttest.PackageCmpLess)); diff != "" { 230 t.Errorf("%s.Extract(%q) diff (-want +got):\n%s", extr.Name(), tt.InputConfig.Path, diff) 231 } 232 }) 233 } 234 }