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 }