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  }