github.com/nextlinux/gosbom@v0.81.1-0.20230627115839-1ff50c281391/gosbom/pkg/cataloger/common/cpe/java_test.go (about)

     1  package cpe
     2  
     3  import (
     4  	"strings"
     5  	"testing"
     6  
     7  	"github.com/nextlinux/gosbom/gosbom/pkg"
     8  	"github.com/stretchr/testify/assert"
     9  )
    10  
    11  func Test_productsFromArtifactAndGroupIDs(t *testing.T) {
    12  	tests := []struct {
    13  		groupIDs   []string
    14  		artifactID string
    15  		expected   []string
    16  	}{
    17  		{
    18  			groupIDs:   []string{"org.sonatype.nexus"},
    19  			artifactID: "nexus-extender",
    20  			expected:   []string{"nexus", "nexus-extender"},
    21  		},
    22  		{
    23  			groupIDs: []string{"org.sonatype.nexus"},
    24  			expected: []string{"nexus"},
    25  		},
    26  		{
    27  			groupIDs:   []string{"org.jenkins-ci.plugins"},
    28  			artifactID: "ant",
    29  			expected:   []string{"ant"},
    30  		},
    31  		{
    32  			groupIDs:   []string{"org.jenkins-ci.plugins"},
    33  			artifactID: "antisamy-markup-formatter",
    34  			expected:   []string{"antisamy-markup-formatter"},
    35  		},
    36  		{
    37  			groupIDs:   []string{"io.jenkins.plugins"},
    38  			artifactID: "aws-global-configuration",
    39  			expected:   []string{"aws-global-configuration"},
    40  		},
    41  		{
    42  			groupIDs:   []string{"com.cloudbees.jenkins.plugins"},
    43  			artifactID: "cloudbees-servicenow-jenkins-plugin",
    44  			expected:   []string{"cloudbees-servicenow-jenkins-plugin"},
    45  		},
    46  		{
    47  			groupIDs:   []string{"com.atlassian.confluence.plugins"},
    48  			artifactID: "confluence-mobile-plugin",
    49  			expected:   []string{"confluence-mobile-plugin"},
    50  		},
    51  		{
    52  			groupIDs:   []string{"com.atlassian.confluence.plugins"},
    53  			artifactID: "confluence-view-file-macro",
    54  			expected:   []string{"confluence-view-file-macro"},
    55  		},
    56  		{
    57  			groupIDs:   []string{"com.google.guava"},
    58  			artifactID: "failureaccess",
    59  			expected:   []string{"failureaccess"},
    60  		},
    61  	}
    62  	for _, test := range tests {
    63  		t.Run(strings.Join(test.groupIDs, ",")+":"+test.artifactID, func(t *testing.T) {
    64  			actual := productsFromArtifactAndGroupIDs(test.artifactID, test.groupIDs)
    65  			assert.ElementsMatch(t, test.expected, actual, "different products")
    66  		})
    67  	}
    68  }
    69  
    70  func Test_candidateProductsForJava(t *testing.T) {
    71  	tests := []struct {
    72  		name     string
    73  		pkg      pkg.Package
    74  		expected []string
    75  	}{
    76  		{
    77  			name: "duplicate groupID in artifactID field",
    78  			pkg: pkg.Package{
    79  				Metadata: pkg.JavaMetadata{
    80  					PomProperties: &pkg.PomProperties{
    81  						GroupID:    "org.sonatype.nexus",
    82  						ArtifactID: "org.sonatype.nexus",
    83  					},
    84  				},
    85  			},
    86  			expected: []string{"nexus"},
    87  		},
    88  		{
    89  			name: "detect groupID-like value in artifactID field",
    90  			pkg: pkg.Package{
    91  				Metadata: pkg.JavaMetadata{
    92  					PomProperties: &pkg.PomProperties{
    93  						ArtifactID: "org.sonatype.nexus",
    94  					},
    95  				},
    96  			},
    97  			expected: []string{"nexus"},
    98  		},
    99  	}
   100  	for _, test := range tests {
   101  		t.Run(test.name, func(t *testing.T) {
   102  			actual := candidateProductsForJava(test.pkg)
   103  			assert.ElementsMatch(t, test.expected, actual, "different products")
   104  		})
   105  	}
   106  }
   107  
   108  func Test_vendorsFromGroupIDs(t *testing.T) {
   109  	tests := []struct {
   110  		groupID  string
   111  		expected []string
   112  	}{
   113  		{
   114  			groupID:  "org.sonatype.nexus",
   115  			expected: []string{"sonatype", "nexus"},
   116  		},
   117  		{
   118  			groupID:  "org.jenkins-ci.plugins",
   119  			expected: []string{"jenkins-ci"},
   120  		},
   121  		{
   122  			groupID:  "io.jenkins.plugins",
   123  			expected: []string{"jenkins"},
   124  		},
   125  		{
   126  			groupID:  "com.cloudbees.jenkins.plugins",
   127  			expected: []string{"cloudbees", "jenkins"},
   128  		},
   129  		{
   130  			groupID:  "com.atlassian.confluence.plugins",
   131  			expected: []string{"atlassian", "confluence"},
   132  		},
   133  		{
   134  			groupID:  "com.google.guava",
   135  			expected: []string{"google", "guava"},
   136  		},
   137  	}
   138  	for _, test := range tests {
   139  		t.Run(test.groupID, func(t *testing.T) {
   140  			assert.ElementsMatch(t, test.expected, vendorsFromGroupIDs([]string{test.groupID}).values(), "different vendors")
   141  		})
   142  	}
   143  }
   144  
   145  func Test_groupIDsFromJavaPackage(t *testing.T) {
   146  	tests := []struct {
   147  		name    string
   148  		pkg     pkg.Package
   149  		expects []string
   150  	}{
   151  		{
   152  			name: "go case",
   153  			pkg: pkg.Package{
   154  				Metadata: pkg.JavaMetadata{
   155  					PomProperties: &pkg.PomProperties{
   156  						GroupID: "io.jenkins-ci.plugin.thing;version='[2,3)'",
   157  					},
   158  				},
   159  			},
   160  			expects: []string{"io.jenkins-ci.plugin.thing"},
   161  		},
   162  		{
   163  			name: "from artifactID",
   164  			pkg: pkg.Package{
   165  				Metadata: pkg.JavaMetadata{
   166  					PomProperties: &pkg.PomProperties{
   167  						ArtifactID: "io.jenkins-ci.plugin.thing; version='[2,3)' ; org.something.else",
   168  					},
   169  				},
   170  			},
   171  			expects: []string{"io.jenkins-ci.plugin.thing"},
   172  		},
   173  		{
   174  			name: "from main Extension-Name field",
   175  			pkg: pkg.Package{
   176  				Metadata: pkg.JavaMetadata{
   177  					Manifest: &pkg.JavaManifest{
   178  						Main: map[string]string{
   179  							"Extension-Name": "io.jenkins-ci.plugin.thing",
   180  						},
   181  					},
   182  				},
   183  			},
   184  			expects: []string{"io.jenkins-ci.plugin.thing"},
   185  		},
   186  		{
   187  			name: "from named section Extension-Name field",
   188  			pkg: pkg.Package{
   189  				Metadata: pkg.JavaMetadata{
   190  					Manifest: &pkg.JavaManifest{
   191  						NamedSections: map[string]map[string]string{
   192  							"section": {
   193  								"Extension-Name": "io.jenkins-ci.plugin.thing",
   194  							},
   195  						},
   196  					},
   197  				},
   198  			},
   199  			expects: []string{"io.jenkins-ci.plugin.thing"},
   200  		},
   201  		{
   202  			name: "from main field - tier 1",
   203  			pkg: pkg.Package{
   204  				Metadata: pkg.JavaMetadata{
   205  					Manifest: &pkg.JavaManifest{
   206  						Main: map[string]string{
   207  							// positive cases
   208  							// tier 1
   209  							"Extension-Name":           "io.jenkins-ci.plugin.1",
   210  							"Specification-Vendor":     "io.jenkins-ci.plugin.2",
   211  							"Implementation-Vendor":    "io.jenkins-ci.plugin.3",
   212  							"Bundle-SymbolicName":      "io.jenkins-ci.plugin.4",
   213  							"Implementation-Vendor-Id": "io.jenkins-ci.plugin.5",
   214  							"Implementation-Title":     "io.jenkins-ci.plugin.6",
   215  							"Bundle-Activator":         "io.jenkins-ci.plugin.7",
   216  							// tier 2
   217  							"Automatic-Module-Name": "io.jenkins-ci.plugin.8",
   218  							"Main-Class":            "io.jenkins-ci.plugin.9",
   219  							"Package":               "io.jenkins-ci.plugin.10",
   220  						},
   221  					},
   222  				},
   223  			},
   224  			expects: []string{
   225  				"io.jenkins-ci.plugin.1",
   226  				"io.jenkins-ci.plugin.2",
   227  				"io.jenkins-ci.plugin.3",
   228  				"io.jenkins-ci.plugin.4",
   229  				"io.jenkins-ci.plugin.5",
   230  				"io.jenkins-ci.plugin.6",
   231  				"io.jenkins-ci.plugin.7",
   232  			},
   233  		},
   234  		{
   235  			name: "from main field - tier 2",
   236  			pkg: pkg.Package{
   237  				Metadata: pkg.JavaMetadata{
   238  					Manifest: &pkg.JavaManifest{
   239  						Main: map[string]string{
   240  							// positive cases
   241  							"Automatic-Module-Name": "io.jenkins-ci.plugin.8",
   242  							"Main-Class":            "io.jenkins-ci.plugin.9",
   243  							"Package":               "io.jenkins-ci.plugin.10",
   244  						},
   245  					},
   246  				},
   247  			},
   248  			expects: []string{
   249  				"io.jenkins-ci.plugin.8",
   250  				"io.jenkins-ci.plugin.9",
   251  				"io.jenkins-ci.plugin.10",
   252  			},
   253  		},
   254  		{
   255  			name: "from main field - negative cases",
   256  			pkg: pkg.Package{
   257  				Metadata: pkg.JavaMetadata{
   258  					Manifest: &pkg.JavaManifest{
   259  						Main: map[string]string{
   260  							// negative cases
   261  							"Extension-Name": "not.a-group.id",
   262  							"bogus":          "io.jenkins-ci.plugin.please-dont-find-me",
   263  						},
   264  					},
   265  				},
   266  			},
   267  			expects: nil,
   268  		},
   269  		{
   270  			name: "from named section field - tier 1",
   271  			pkg: pkg.Package{
   272  				Metadata: pkg.JavaMetadata{
   273  					Manifest: &pkg.JavaManifest{
   274  						NamedSections: map[string]map[string]string{
   275  							"section": {
   276  								// positive cases
   277  								// tier 1
   278  								"Extension-Name":           "io.jenkins-ci.plugin.1",
   279  								"Specification-Vendor":     "io.jenkins-ci.plugin.2",
   280  								"Implementation-Vendor":    "io.jenkins-ci.plugin.3",
   281  								"Bundle-SymbolicName":      "io.jenkins-ci.plugin.4",
   282  								"Implementation-Vendor-Id": "io.jenkins-ci.plugin.5",
   283  								"Implementation-Title":     "io.jenkins-ci.plugin.6",
   284  								"Bundle-Activator":         "io.jenkins-ci.plugin.7",
   285  								// tier 2
   286  								"Automatic-Module-Name": "io.jenkins-ci.plugin.8",
   287  								"Main-Class":            "io.jenkins-ci.plugin.9",
   288  								"Package":               "io.jenkins-ci.plugin.10",
   289  							},
   290  						},
   291  					},
   292  				},
   293  			},
   294  			expects: []string{
   295  				"io.jenkins-ci.plugin.1",
   296  				"io.jenkins-ci.plugin.2",
   297  				"io.jenkins-ci.plugin.3",
   298  				"io.jenkins-ci.plugin.4",
   299  				"io.jenkins-ci.plugin.5",
   300  				"io.jenkins-ci.plugin.6",
   301  				"io.jenkins-ci.plugin.7",
   302  			},
   303  		},
   304  		{
   305  			name: "from named section field - negative cases",
   306  			pkg: pkg.Package{
   307  				Metadata: pkg.JavaMetadata{
   308  					Manifest: &pkg.JavaManifest{
   309  						NamedSections: map[string]map[string]string{
   310  							"section": {
   311  								// negative cases
   312  								"Extension-Name": "not.a-group.id",
   313  								"bogus":          "io.jenkins-ci.plugin.please-dont-find-me",
   314  							},
   315  						},
   316  					},
   317  				},
   318  			},
   319  			expects: nil,
   320  		},
   321  		{
   322  			name: "no manifest or pom info",
   323  			pkg: pkg.Package{
   324  				Metadata: pkg.JavaMetadata{},
   325  			},
   326  			expects: nil,
   327  		},
   328  		{
   329  			name:    "no java info",
   330  			pkg:     pkg.Package{},
   331  			expects: nil,
   332  		},
   333  	}
   334  	for _, test := range tests {
   335  		t.Run(test.name, func(t *testing.T) {
   336  			assert.ElementsMatch(t, test.expects, GroupIDsFromJavaPackage(test.pkg))
   337  		})
   338  	}
   339  }
   340  
   341  func Test_artifactIDFromJavaPackage(t *testing.T) {
   342  	tests := []struct {
   343  		name    string
   344  		pkg     pkg.Package
   345  		expects string
   346  	}{
   347  		{
   348  			name: "go case",
   349  			pkg: pkg.Package{
   350  				Metadata: pkg.JavaMetadata{
   351  					PomProperties: &pkg.PomProperties{
   352  						ArtifactID: "cloudbees-installation-manager",
   353  					},
   354  				},
   355  			},
   356  			expects: "cloudbees-installation-manager",
   357  		},
   358  		{
   359  			name: "ignore groupID-like things",
   360  			pkg: pkg.Package{
   361  				Metadata: pkg.JavaMetadata{
   362  					PomProperties: &pkg.PomProperties{
   363  						ArtifactID: "io.jenkins-ci.plugin.thing",
   364  					},
   365  				},
   366  			},
   367  			expects: "",
   368  		},
   369  		{
   370  			name:    "no java info",
   371  			pkg:     pkg.Package{},
   372  			expects: "",
   373  		},
   374  	}
   375  	for _, test := range tests {
   376  		t.Run(test.name, func(t *testing.T) {
   377  			assert.Equal(t, test.expects, artifactIDFromJavaPackage(test.pkg))
   378  		})
   379  	}
   380  }
   381  
   382  func Test_vendorsFromJavaManifestNames(t *testing.T) {
   383  	tests := []struct {
   384  		name    string
   385  		pkg     pkg.Package
   386  		expects []string
   387  	}{
   388  		{
   389  			name: "from manifest named section fields",
   390  			pkg: pkg.Package{
   391  				Metadata: pkg.JavaMetadata{
   392  					Manifest: &pkg.JavaManifest{
   393  						NamedSections: map[string]map[string]string{
   394  							"section": {
   395  								// positive cases
   396  								"Specification-Vendor":  "Alex Goodman",
   397  								"Implementation-Vendor": "William Goodman",
   398  							},
   399  						},
   400  					},
   401  				},
   402  			},
   403  			expects: []string{"alex_goodman", "william_goodman"},
   404  		},
   405  		{
   406  			name: "from manifest named section fields - negative cases",
   407  			pkg: pkg.Package{
   408  				Metadata: pkg.JavaMetadata{
   409  					Manifest: &pkg.JavaManifest{
   410  						NamedSections: map[string]map[string]string{
   411  							"section": {
   412  								// negative cases
   413  								"Specification-Vendor":     "io.jenkins-ci.plugin.thing",
   414  								"Implementation-Vendor-ID": "William Goodman",
   415  							},
   416  						},
   417  					},
   418  				},
   419  			},
   420  			expects: nil,
   421  		},
   422  	}
   423  	for _, test := range tests {
   424  		t.Run(test.name, func(t *testing.T) {
   425  			assert.ElementsMatch(t, test.expects, vendorsFromJavaManifestNames(test.pkg).values())
   426  		})
   427  	}
   428  }