github.com/anchore/syft@v1.38.2/syft/pkg/cataloger/java/parse_jvm_release_test.go (about) 1 package java 2 3 import ( 4 "testing" 5 6 "github.com/stretchr/testify/assert" 7 8 "github.com/anchore/syft/syft/cpe" 9 "github.com/anchore/syft/syft/pkg" 10 ) 11 12 func TestJvmCpes(t *testing.T) { 13 tests := []struct { 14 name string 15 pkgVersion string 16 primaryVendor string 17 primaryProduct string 18 imageType string 19 hasJdk bool 20 expected []cpe.CPE 21 }{ 22 { 23 name: "zulu release", 24 pkgVersion: "9.0.1+20", 25 primaryVendor: "azul", 26 primaryProduct: "zulu", 27 imageType: "jdk", 28 expected: []cpe.CPE{ 29 { 30 Attributes: cpe.Attributes{ 31 Part: "a", 32 Vendor: "azul", 33 Product: "zulu", 34 Version: "9.0.1", 35 Update: "", 36 }, 37 Source: cpe.DeclaredSource, 38 }, 39 { 40 Attributes: cpe.Attributes{ 41 Part: "a", 42 Vendor: "oracle", 43 Product: "openjdk", 44 Version: "9.0.1", 45 Update: "", 46 }, 47 Source: cpe.DeclaredSource, 48 }, 49 }, 50 }, 51 { 52 name: "sun release", 53 pkgVersion: "1.6.0_322-b002", 54 primaryVendor: "sun", 55 primaryProduct: "jre", 56 imageType: "jre", 57 hasJdk: true, 58 expected: []cpe.CPE{ 59 { 60 Attributes: cpe.Attributes{ 61 Part: "a", 62 Vendor: "sun", 63 Product: "jre", 64 Version: "1.6.0", 65 Update: "update322", 66 }, 67 Source: cpe.DeclaredSource, 68 }, 69 { 70 Attributes: cpe.Attributes{ 71 Part: "a", 72 Vendor: "sun", 73 Product: "jdk", 74 Version: "1.6.0", 75 Update: "update322", 76 }, 77 Source: cpe.DeclaredSource, 78 }, 79 }, 80 }, 81 { 82 name: "oracle se release", 83 pkgVersion: "1.8.0_322-b02", 84 primaryVendor: "oracle", 85 primaryProduct: "java_se", 86 imageType: "jdk", 87 hasJdk: true, 88 expected: []cpe.CPE{ 89 { 90 Attributes: cpe.Attributes{ 91 Part: "a", 92 Vendor: "oracle", 93 Product: "java_se", 94 Version: "1.8.0", 95 Update: "update322", 96 }, 97 Source: cpe.DeclaredSource, 98 }, 99 { 100 Attributes: cpe.Attributes{ 101 Part: "a", 102 Vendor: "oracle", 103 Product: "jre", 104 Version: "1.8.0", 105 Update: "update322", 106 }, 107 Source: cpe.DeclaredSource, 108 }, 109 { 110 Attributes: cpe.Attributes{ 111 Part: "a", 112 Vendor: "oracle", 113 Product: "jdk", 114 Version: "1.8.0", 115 Update: "update322", 116 }, 117 Source: cpe.DeclaredSource, 118 }, 119 }, 120 }, 121 { 122 name: "JEP 223 version with build info", 123 pkgVersion: "9.0.1+20", 124 primaryVendor: "oracle", 125 primaryProduct: "openjdk", 126 imageType: "openjdk", 127 expected: []cpe.CPE{ 128 { 129 Attributes: cpe.Attributes{ 130 Part: "a", 131 Vendor: "oracle", 132 Product: "openjdk", 133 Version: "9.0.1", 134 Update: "", 135 }, 136 Source: cpe.DeclaredSource, 137 }, 138 }, 139 }, 140 { 141 name: "JEP 223 version without build info", 142 pkgVersion: "11.0.9", 143 primaryVendor: "oracle", 144 primaryProduct: "openjdk", 145 imageType: "openjdk", 146 expected: []cpe.CPE{ 147 { 148 Attributes: cpe.Attributes{ 149 Part: "a", 150 Vendor: "oracle", 151 Product: "openjdk", 152 Version: "11.0.9", 153 Update: "", 154 }, 155 Source: cpe.DeclaredSource, 156 }, 157 }, 158 }, 159 { 160 name: "no plus sign in version string", 161 pkgVersion: "1.8.0", 162 primaryVendor: "oracle", 163 primaryProduct: "openjdk", 164 imageType: "openjdk", 165 expected: []cpe.CPE{ 166 { 167 Attributes: cpe.Attributes{ 168 Part: "a", 169 Vendor: "oracle", 170 Product: "openjdk", 171 Version: "1.8.0", 172 Update: "", 173 }, 174 Source: cpe.DeclaredSource, 175 }, 176 }, 177 }, 178 { 179 name: "empty version string", 180 pkgVersion: "", 181 primaryVendor: "oracle", 182 primaryProduct: "", 183 imageType: "", 184 expected: nil, 185 }, 186 } 187 188 for _, tt := range tests { 189 t.Run(tt.name, func(t *testing.T) { 190 result := jvmCpes(tt.pkgVersion, tt.primaryVendor, tt.primaryProduct, tt.imageType, tt.hasJdk) 191 assert.Equal(t, tt.expected, result) 192 }) 193 } 194 } 195 196 func TestJvmVersion(t *testing.T) { 197 tests := []struct { 198 name string 199 input *pkg.JavaVMRelease 200 expected string 201 }{ 202 203 { 204 name: "JavaRuntimeVersion fallback", 205 input: &pkg.JavaVMRelease{ 206 JavaRuntimeVersion: "21.0.4+7-LTS", 207 JavaVersion: "bogus", 208 FullVersion: "bogus", 209 SemanticVersion: "bogus", 210 }, 211 expected: "21.0.4+7-LTS", 212 }, 213 { 214 name: "JavaVersion fallback", 215 input: &pkg.JavaVMRelease{ 216 JavaVersion: "21.0.4", 217 FullVersion: "bogus", 218 SemanticVersion: "bogus", 219 }, 220 expected: "21.0.4", 221 }, 222 { 223 // there is an example of this in eclipse-temurin:8u312-b07-jdk 224 name: "FullVersion is more accurate", 225 input: &pkg.JavaVMRelease{ 226 JavaVersion: "1.8.0_131", 227 FullVersion: "1.8.0_131+b08", 228 }, 229 expected: "1.8.0_131+b08", 230 }, 231 { 232 name: "empty input fields", 233 input: &pkg.JavaVMRelease{}, 234 expected: "", 235 }, 236 } 237 238 for _, tt := range tests { 239 t.Run(tt.name, func(t *testing.T) { 240 result := jvmPackageVersion(tt.input) 241 assert.Equal(t, tt.expected, result) 242 }) 243 } 244 } 245 246 func TestGetJVMVersionAndUpdate(t *testing.T) { 247 tests := []struct { 248 name string 249 version string 250 expectedVer string 251 expectedUpdate string 252 }{ 253 { 254 name: "legacy version with underscore and build", 255 version: "1.8.0_302-b08", 256 expectedVer: "1.8.0", 257 expectedUpdate: "302", 258 }, 259 { 260 name: "legacy version with underscore but no build", 261 version: "1.8.0_302", 262 expectedVer: "1.8.0", 263 expectedUpdate: "302", 264 }, 265 { 266 name: "JEP 223 version with plus sign", 267 version: "9.0.1+20", 268 expectedVer: "9.0.1", 269 expectedUpdate: "", 270 }, 271 { 272 name: "JEP 223 version with plus but no update", 273 version: "11.0.9+", 274 expectedVer: "11.0.9", 275 expectedUpdate: "", 276 }, 277 { 278 name: "modern version without plus or underscore", 279 version: "11.0.9", 280 expectedVer: "11.0.9", 281 expectedUpdate: "", 282 }, 283 { 284 name: "legacy version without underscore or plus", 285 version: "1.7.0", 286 expectedVer: "1.7.0", 287 expectedUpdate: "", 288 }, 289 { 290 name: "empty version string", 291 version: "", 292 expectedVer: "", 293 expectedUpdate: "", 294 }, 295 } 296 297 for _, tt := range tests { 298 t.Run(tt.name, func(t *testing.T) { 299 ver, update := getJVMVersionAndUpdate(tt.version) 300 assert.Equal(t, tt.expectedVer, ver) 301 assert.Equal(t, tt.expectedUpdate, update) 302 }) 303 } 304 } 305 306 func TestJvmPrimaryVendorProduct(t *testing.T) { 307 tests := []struct { 308 name string 309 implementor string 310 buildType string 311 path string 312 imageType string 313 hasJdk bool 314 expectedVendor string 315 expectedProduct string 316 }{ 317 { 318 name: "Azul implementor with Zulu in path", 319 implementor: "Azul Systems", 320 path: "/usr/lib/jvm/zulu-11-amd64/release", 321 imageType: "JDK", 322 hasJdk: true, 323 expectedVendor: "azul", 324 expectedProduct: "zulu", 325 }, 326 { 327 name: "Sun implementor with JDK", 328 implementor: "Sun Microsystems", 329 path: "/usr/lib/jvm/jdk-1.8-sun-amd64/release", 330 imageType: "JDK", 331 hasJdk: true, 332 expectedVendor: "sun", 333 expectedProduct: "jdk", 334 }, 335 { 336 name: "Oracle implementor with JRE", 337 implementor: "Oracle Corporation", 338 path: "/usr/lib/jvm/jdk-1.8-oracle-x64/release", 339 imageType: "JRE", 340 hasJdk: false, 341 expectedVendor: "oracle", 342 expectedProduct: "jre", 343 }, 344 { 345 name: "Oracle commercial build type with JRE", 346 implementor: "", 347 buildType: "commercial", 348 path: "/usr/lib/jvm/jdk8/release", 349 imageType: "JRE", 350 hasJdk: false, 351 expectedVendor: "oracle", 352 expectedProduct: "jre", 353 }, 354 { 355 name: "Oracle commercial build type with JDK", 356 implementor: "", 357 buildType: "commercial", 358 path: "/usr/lib/jvm/jdk8/release", 359 hasJdk: true, 360 expectedVendor: "oracle", 361 expectedProduct: "jdk", 362 }, 363 { 364 name: "Oracle vendor with JDK in path", 365 implementor: "", 366 path: "/usr/lib/jvm/jdk-1.8-oracle-x64/release", 367 imageType: "JDK", 368 hasJdk: true, 369 expectedVendor: "oracle", 370 expectedProduct: "jdk", 371 }, 372 { 373 name: "OpenJDK with JDK", 374 implementor: "OpenJDK", 375 path: "/opt/java/openjdk/release", 376 imageType: "JDK", 377 hasJdk: true, 378 expectedVendor: "oracle", // like temurin 379 expectedProduct: "openjdk", 380 }, 381 { 382 name: "Amazon Corretto with JDK", 383 implementor: "Amazon Corretto", 384 path: "/usr/lib/jvm/java-17-amazon-corretto/release", 385 imageType: "JDK", 386 hasJdk: true, 387 expectedVendor: "oracle", // corretto upstream is oracle openjdk 388 expectedProduct: "openjdk", 389 }, 390 { 391 name: "IBM JRE", 392 path: "/opt/ibm/java/release", 393 expectedVendor: "ibm", 394 expectedProduct: "java", 395 }, 396 { 397 name: "IBM JDK", 398 path: "/opt/ibm/java/release", 399 hasJdk: true, 400 expectedVendor: "ibm", 401 expectedProduct: "java_sdk", 402 }, 403 } 404 405 for _, tt := range tests { 406 t.Run(tt.name, func(t *testing.T) { 407 ri := pkg.JavaVMRelease{ 408 Implementor: tt.implementor, 409 BuildType: tt.buildType, 410 ImageType: tt.imageType, 411 } 412 vendor, product := jvmPrimaryVendorProduct(&ri, tt.path, tt.hasJdk) 413 assert.Equal(t, tt.expectedVendor, vendor) 414 assert.Equal(t, tt.expectedProduct, product) 415 }) 416 } 417 } 418 419 func TestJvmPurl(t *testing.T) { 420 tests := []struct { 421 name string 422 ri pkg.JavaVMRelease 423 version string 424 vendor string 425 product string 426 expectedPURL string 427 }{ 428 { 429 name: "build source repo provided", 430 ri: pkg.JavaVMRelease{ 431 BuildSourceRepo: "https://github.com/adoptium/temurin-build.git", 432 }, 433 version: "21.0.4", 434 vendor: "oracle", 435 product: "jdk", 436 expectedPURL: "pkg:generic/oracle/jdk@21.0.4?repository_url=https%3A%2F%2Fgithub.com%2Fadoptium%2Ftemurin-build.git", 437 }, 438 { 439 name: "source repo provided, no build source repo", 440 ri: pkg.JavaVMRelease{ 441 SourceRepo: "https://github.com/adoptium/jdk21u.git", 442 }, 443 version: "21.0.4", 444 vendor: "azul", 445 product: "zulu", 446 expectedPURL: "pkg:generic/azul/zulu@21.0.4?repository_url=https%3A%2F%2Fgithub.com%2Fadoptium%2Fjdk21u.git", 447 }, 448 { 449 name: "no repository URLs provided", 450 ri: pkg.JavaVMRelease{ 451 // No repository URLs provided 452 }, 453 version: "17.0.2", 454 vendor: "oracle", 455 product: "jdk", 456 expectedPURL: "pkg:generic/oracle/jdk@17.0.2", 457 }, 458 { 459 name: "JRE with source repo", 460 ri: pkg.JavaVMRelease{ 461 SourceRepo: "https://github.com/adoptium/jre-repo.git", 462 }, 463 version: "1.8.0_302", 464 vendor: "oracle", 465 product: "jre", 466 expectedPURL: "pkg:generic/oracle/jre@1.8.0_302?repository_url=https%3A%2F%2Fgithub.com%2Fadoptium%2Fjre-repo.git", 467 }, 468 } 469 470 for _, tt := range tests { 471 t.Run(tt.name, func(t *testing.T) { 472 actualPURL := jvmPurl(tt.ri, tt.version, tt.vendor, tt.product) 473 assert.Equal(t, tt.expectedPURL, actualPURL) 474 }) 475 } 476 }