github.com/kastenhq/syft@v0.0.0-20230821225854-0710af25cdbe/syft/pkg/cataloger/java/parse_pom_xml_test.go (about) 1 package java 2 3 import ( 4 "os" 5 "testing" 6 7 "github.com/stretchr/testify/assert" 8 "github.com/vifraa/gopom" 9 10 "github.com/kastenhq/syft/syft/file" 11 "github.com/kastenhq/syft/syft/pkg" 12 "github.com/kastenhq/syft/syft/pkg/cataloger/internal/pkgtest" 13 ) 14 15 func Test_parserPomXML(t *testing.T) { 16 tests := []struct { 17 input string 18 expected []pkg.Package 19 }{ 20 { 21 input: "test-fixtures/pom/pom.xml", 22 expected: []pkg.Package{ 23 { 24 Name: "joda-time", 25 Version: "2.9.2", 26 PURL: "pkg:maven/com.joda/joda-time@2.9.2", 27 Language: pkg.Java, 28 Type: pkg.JavaPkg, 29 MetadataType: pkg.JavaMetadataType, 30 Metadata: pkg.JavaMetadata{ 31 PomProperties: &pkg.PomProperties{ 32 GroupID: "com.joda", 33 ArtifactID: "joda-time", 34 }, 35 }, 36 }, 37 { 38 Name: "junit", 39 Version: "4.12", 40 PURL: "pkg:maven/junit/junit@4.12", 41 Language: pkg.Java, 42 Type: pkg.JavaPkg, 43 MetadataType: pkg.JavaMetadataType, 44 Metadata: pkg.JavaMetadata{ 45 PomProperties: &pkg.PomProperties{ 46 GroupID: "junit", 47 ArtifactID: "junit", 48 Scope: "test", 49 }, 50 }, 51 }, 52 }, 53 }, 54 } 55 56 for _, test := range tests { 57 t.Run(test.input, func(t *testing.T) { 58 for i := range test.expected { 59 test.expected[i].Locations.Add(file.NewLocation(test.input)) 60 } 61 pkgtest.TestFileParser(t, test.input, parserPomXML, test.expected, nil) 62 }) 63 } 64 } 65 66 func Test_parseCommonsTextPomXMLProject(t *testing.T) { 67 tests := []struct { 68 input string 69 expected []pkg.Package 70 }{ 71 { 72 input: "test-fixtures/pom/commons-text.pom.xml", 73 expected: []pkg.Package{ 74 { 75 Name: "commons-lang3", 76 Version: "3.12.0", 77 PURL: "pkg:maven/org.apache.commons/commons-lang3@3.12.0", 78 Language: pkg.Java, 79 Type: pkg.JavaPkg, 80 MetadataType: pkg.JavaMetadataType, 81 Metadata: pkg.JavaMetadata{ 82 PomProperties: &pkg.PomProperties{ 83 GroupID: "org.apache.commons", 84 ArtifactID: "commons-lang3", 85 }, 86 }, 87 }, 88 { 89 Name: "junit-jupiter", 90 Version: "", 91 PURL: "pkg:maven/org.junit.jupiter/junit-jupiter", 92 Language: pkg.Java, 93 Type: pkg.JavaPkg, 94 MetadataType: pkg.JavaMetadataType, 95 Metadata: pkg.JavaMetadata{ 96 PomProperties: &pkg.PomProperties{ 97 GroupID: "org.junit.jupiter", 98 ArtifactID: "junit-jupiter", 99 Scope: "test", 100 }, 101 }, 102 }, 103 { 104 Name: "assertj-core", 105 Version: "3.23.1", 106 PURL: "pkg:maven/org.assertj/assertj-core@3.23.1", 107 Language: pkg.Java, 108 Type: pkg.JavaPkg, 109 MetadataType: pkg.JavaMetadataType, 110 Metadata: pkg.JavaMetadata{ 111 PomProperties: &pkg.PomProperties{ 112 GroupID: "org.assertj", 113 ArtifactID: "assertj-core", 114 Scope: "test", 115 }, 116 }, 117 }, 118 { 119 Name: "commons-io", 120 Version: "2.11.0", 121 PURL: "pkg:maven/commons-io/commons-io@2.11.0", 122 Language: pkg.Java, 123 Type: pkg.JavaPkg, 124 MetadataType: pkg.JavaMetadataType, 125 Metadata: pkg.JavaMetadata{ 126 PomProperties: &pkg.PomProperties{ 127 GroupID: "commons-io", 128 ArtifactID: "commons-io", 129 Scope: "test", 130 }, 131 }, 132 }, 133 { 134 Name: "mockito-inline", 135 Version: "4.8.0", 136 PURL: "pkg:maven/org.mockito/mockito-inline@4.8.0", 137 Language: pkg.Java, 138 Type: pkg.JavaPkg, 139 MetadataType: pkg.JavaMetadataType, 140 Metadata: pkg.JavaMetadata{ 141 PomProperties: &pkg.PomProperties{ 142 GroupID: "org.mockito", 143 ArtifactID: "mockito-inline", 144 Scope: "test", 145 }, 146 }, 147 }, 148 { 149 Name: "js", 150 Version: "22.0.0.2", 151 PURL: "pkg:maven/org.graalvm.js/js@22.0.0.2", 152 Language: pkg.Java, 153 Type: pkg.JavaPkg, 154 MetadataType: pkg.JavaMetadataType, 155 Metadata: pkg.JavaMetadata{ 156 PomProperties: &pkg.PomProperties{ 157 GroupID: "org.graalvm.js", 158 ArtifactID: "js", 159 Scope: "test", 160 }, 161 }, 162 }, 163 { 164 Name: "js-scriptengine", 165 Version: "22.0.0.2", 166 PURL: "pkg:maven/org.graalvm.js/js-scriptengine@22.0.0.2", 167 Language: pkg.Java, 168 Type: pkg.JavaPkg, 169 MetadataType: pkg.JavaMetadataType, 170 Metadata: pkg.JavaMetadata{ 171 PomProperties: &pkg.PomProperties{ 172 GroupID: "org.graalvm.js", 173 ArtifactID: "js-scriptengine", 174 Scope: "test", 175 }, 176 }, 177 }, 178 { 179 Name: "commons-rng-simple", 180 Version: "1.4", 181 PURL: "pkg:maven/org.apache.commons/commons-rng-simple@1.4", 182 Language: pkg.Java, 183 Type: pkg.JavaPkg, 184 MetadataType: pkg.JavaMetadataType, 185 Metadata: pkg.JavaMetadata{ 186 PomProperties: &pkg.PomProperties{ 187 GroupID: "org.apache.commons", 188 ArtifactID: "commons-rng-simple", 189 Scope: "test", 190 }, 191 }, 192 }, 193 { 194 Name: "jmh-core", 195 Version: "1.35", 196 PURL: "pkg:maven/org.openjdk.jmh/jmh-core@1.35", 197 Language: pkg.Java, 198 Type: pkg.JavaPkg, 199 MetadataType: pkg.JavaMetadataType, 200 Metadata: pkg.JavaMetadata{ 201 PomProperties: &pkg.PomProperties{ 202 GroupID: "org.openjdk.jmh", 203 ArtifactID: "jmh-core", 204 Scope: "test", 205 }, 206 }, 207 }, 208 { 209 Name: "jmh-generator-annprocess", 210 Version: "1.35", 211 PURL: "pkg:maven/org.openjdk.jmh/jmh-generator-annprocess@1.35", 212 Language: pkg.Java, 213 Type: pkg.JavaPkg, 214 MetadataType: pkg.JavaMetadataType, 215 Metadata: pkg.JavaMetadata{ 216 PomProperties: &pkg.PomProperties{ 217 GroupID: "org.openjdk.jmh", 218 ArtifactID: "jmh-generator-annprocess", 219 Scope: "test", 220 }, 221 }, 222 }, 223 }, 224 }, 225 } 226 227 for _, test := range tests { 228 t.Run(test.input, func(t *testing.T) { 229 for i := range test.expected { 230 test.expected[i].Locations.Add(file.NewLocation(test.input)) 231 } 232 pkgtest.TestFileParser(t, test.input, parserPomXML, test.expected, nil) 233 }) 234 } 235 } 236 237 func Test_parsePomXMLProject(t *testing.T) { 238 tests := []struct { 239 expected pkg.PomProject 240 }{ 241 { 242 expected: pkg.PomProject{ 243 Path: "test-fixtures/pom/commons-codec.pom.xml", 244 Parent: &pkg.PomParent{ 245 GroupID: "org.apache.commons", 246 ArtifactID: "commons-parent", 247 Version: "42", 248 }, 249 GroupID: "commons-codec", 250 ArtifactID: "commons-codec", 251 Version: "1.11", 252 Name: "Apache Commons Codec", 253 Description: "The Apache Commons Codec package contains simple encoder and decoders for various formats such as Base64 and Hexadecimal. In addition to these widely used encoders and decoders, the codec package also maintains a collection of phonetic encoding utilities.", 254 URL: "http://commons.apache.org/proper/commons-codec/", 255 }, 256 }, 257 } 258 259 for _, test := range tests { 260 t.Run(test.expected.Path, func(t *testing.T) { 261 fixture, err := os.Open(test.expected.Path) 262 assert.NoError(t, err) 263 264 actual, err := parsePomXMLProject(fixture.Name(), fixture) 265 assert.NoError(t, err) 266 267 assert.Equal(t, &test.expected, actual) 268 }) 269 } 270 } 271 272 func Test_pomParent(t *testing.T) { 273 tests := []struct { 274 name string 275 input gopom.Parent 276 expected *pkg.PomParent 277 }{ 278 { 279 name: "only group ID", 280 input: gopom.Parent{ 281 GroupID: "org.something", 282 }, 283 expected: &pkg.PomParent{ 284 GroupID: "org.something", 285 }, 286 }, 287 { 288 name: "only artifact ID", 289 input: gopom.Parent{ 290 ArtifactID: "something", 291 }, 292 expected: &pkg.PomParent{ 293 ArtifactID: "something", 294 }, 295 }, 296 { 297 name: "only Version", 298 input: gopom.Parent{ 299 Version: "something", 300 }, 301 expected: &pkg.PomParent{ 302 Version: "something", 303 }, 304 }, 305 { 306 name: "empty", 307 input: gopom.Parent{}, 308 expected: nil, 309 }, 310 { 311 name: "unused field", 312 input: gopom.Parent{ 313 RelativePath: "something", 314 }, 315 expected: nil, 316 }, 317 } 318 319 for _, test := range tests { 320 t.Run(test.name, func(t *testing.T) { 321 assert.Equal(t, test.expected, pomParent(gopom.Project{}, test.input)) 322 }) 323 } 324 } 325 326 func Test_cleanDescription(t *testing.T) { 327 tests := []struct { 328 name string 329 input string 330 expected string 331 }{ 332 { 333 name: "indent + multiline", 334 input: ` The Apache Commons Codec package contains simple encoder and decoders for 335 various formats such as Base64 and Hexadecimal. In addition to these 336 widely used encoders and decoders, the codec package also maintains a 337 collection of phonetic encoding utilities.`, 338 expected: "The Apache Commons Codec package contains simple encoder and decoders for various formats such as Base64 and Hexadecimal. In addition to these widely used encoders and decoders, the codec package also maintains a collection of phonetic encoding utilities.", 339 }, 340 } 341 342 for _, test := range tests { 343 t.Run(test.name, func(t *testing.T) { 344 assert.Equal(t, test.expected, cleanDescription(test.input)) 345 }) 346 } 347 } 348 349 func Test_resolveProperty(t *testing.T) { 350 tests := []struct { 351 name string 352 property string 353 pom gopom.Project 354 expected string 355 }{ 356 { 357 name: "property", 358 property: "${version.number}", 359 pom: gopom.Project{ 360 Properties: gopom.Properties{ 361 Entries: map[string]string{ 362 "version.number": "12.5.0", 363 }, 364 }, 365 }, 366 expected: "12.5.0", 367 }, 368 { 369 name: "groupId", 370 property: "${project.groupId}", 371 pom: gopom.Project{ 372 GroupID: "org.some.group", 373 }, 374 expected: "org.some.group", 375 }, 376 { 377 name: "parent groupId", 378 property: "${project.parent.groupId}", 379 pom: gopom.Project{ 380 Parent: gopom.Parent{ 381 GroupID: "org.some.parent", 382 }, 383 }, 384 expected: "org.some.parent", 385 }, 386 } 387 388 for _, test := range tests { 389 t.Run(test.name, func(t *testing.T) { 390 resolved := resolveProperty(test.pom, test.property) 391 assert.Equal(t, test.expected, resolved) 392 }) 393 } 394 }