github.com/anchore/syft@v1.38.2/syft/pkg/cataloger/java/parse_pom_xml_test.go (about) 1 package java 2 3 import ( 4 "context" 5 "os" 6 "testing" 7 8 "github.com/stretchr/testify/assert" 9 "github.com/stretchr/testify/require" 10 11 "github.com/anchore/syft/syft/artifact" 12 "github.com/anchore/syft/syft/cataloging" 13 "github.com/anchore/syft/syft/file" 14 "github.com/anchore/syft/syft/license" 15 "github.com/anchore/syft/syft/pkg" 16 "github.com/anchore/syft/syft/pkg/cataloger/internal/pkgtest" 17 "github.com/anchore/syft/syft/pkg/cataloger/java/internal/maven" 18 maventest "github.com/anchore/syft/syft/pkg/cataloger/java/internal/maven/test" 19 "github.com/anchore/syft/syft/source" 20 "github.com/anchore/syft/syft/source/directorysource" 21 ) 22 23 func Test_parsePomXML(t *testing.T) { 24 pomLocation := file.NewLocationSet(file.NewLocation("pom.xml")) 25 26 exampleJavaAppMaven := pkg.Package{ 27 Name: "example-java-app-maven", 28 Version: "0.1.0", 29 PURL: "pkg:maven/org.anchore/example-java-app-maven@0.1.0", 30 Language: pkg.Java, 31 Type: pkg.JavaPkg, 32 FoundBy: pomCatalogerName, 33 Locations: pomLocation, 34 Metadata: pkg.JavaArchive{ 35 PomProject: &pkg.JavaPomProject{ 36 GroupID: "org.anchore", 37 ArtifactID: "example-java-app-maven", 38 Version: "0.1.0", 39 }, 40 }, 41 } 42 finalizePackage(&exampleJavaAppMaven) 43 44 jodaTime := pkg.Package{ 45 Name: "joda-time", 46 Version: "2.9.2", 47 PURL: "pkg:maven/com.joda/joda-time@2.9.2", 48 Language: pkg.Java, 49 Type: pkg.JavaPkg, 50 FoundBy: pomCatalogerName, 51 Locations: pomLocation, 52 Metadata: pkg.JavaArchive{ 53 PomProperties: &pkg.JavaPomProperties{ 54 GroupID: "com.joda", 55 ArtifactID: "joda-time", 56 }, 57 }, 58 } 59 finalizePackage(&jodaTime) 60 61 junit := pkg.Package{ 62 Name: "junit", 63 Version: "4.12", 64 PURL: "pkg:maven/junit/junit@4.12", 65 Language: pkg.Java, 66 Type: pkg.JavaPkg, 67 FoundBy: pomCatalogerName, 68 Locations: pomLocation, 69 Metadata: pkg.JavaArchive{ 70 PomProperties: &pkg.JavaPomProperties{ 71 GroupID: "junit", 72 ArtifactID: "junit", 73 Scope: "test", 74 }, 75 }, 76 } 77 finalizePackage(&junit) 78 79 tests := []struct { 80 dir string 81 expected []pkg.Package 82 expectedRelationships []artifact.Relationship 83 }{ 84 { 85 dir: "test-fixtures/pom/example-java-app-maven", 86 expected: []pkg.Package{ 87 exampleJavaAppMaven, 88 jodaTime, 89 junit, 90 }, 91 expectedRelationships: []artifact.Relationship{ 92 { 93 From: jodaTime, 94 To: exampleJavaAppMaven, 95 Type: artifact.DependencyOfRelationship, 96 }, 97 { 98 From: junit, 99 To: exampleJavaAppMaven, 100 Type: artifact.DependencyOfRelationship, 101 }, 102 }, 103 }, 104 } 105 106 for _, test := range tests { 107 t.Run(test.dir, func(t *testing.T) { 108 for i := range test.expected { 109 test.expected[i].Locations.Add(file.NewLocation("pom.xml")) 110 } 111 112 cat := NewPomCataloger(ArchiveCatalogerConfig{ 113 ArchiveSearchConfig: cataloging.ArchiveSearchConfig{ 114 IncludeIndexedArchives: true, 115 IncludeUnindexedArchives: true, 116 }, 117 }) 118 119 pkgtest.TestCataloger(t, test.dir, cat, test.expected, test.expectedRelationships) 120 }) 121 } 122 } 123 124 func Test_parseCommonsTextPomXMLProject(t *testing.T) { 125 mavenLocalRepoDir := "internal/maven/test-fixtures/maven-repo" 126 mavenBaseURL := maventest.MockRepo(t, "internal/maven/test-fixtures/maven-repo") 127 128 tests := []struct { 129 name string 130 dir string 131 config ArchiveCatalogerConfig 132 expected expected 133 }{ 134 { 135 name: "no resolution", 136 dir: "test-fixtures/pom/commons-text-1.10.0", 137 config: ArchiveCatalogerConfig{ 138 UseNetwork: false, 139 UseMavenLocalRepository: false, 140 }, 141 expected: getCommonsTextExpectedPackages(false), 142 }, 143 { 144 name: "use network", 145 dir: "test-fixtures/pom/commons-text-1.10.0", 146 config: ArchiveCatalogerConfig{ 147 UseNetwork: true, 148 MavenBaseURL: mavenBaseURL, 149 UseMavenLocalRepository: false, 150 }, 151 expected: getCommonsTextExpectedPackages(true), 152 }, 153 { 154 name: "use local repository", 155 dir: "test-fixtures/pom/commons-text-1.10.0", 156 config: ArchiveCatalogerConfig{ 157 UseNetwork: false, 158 UseMavenLocalRepository: true, 159 MavenLocalRepositoryDir: mavenLocalRepoDir, 160 }, 161 expected: getCommonsTextExpectedPackages(true), 162 }, 163 { 164 name: "transitive dependencies", 165 dir: "test-fixtures/pom/transitive-top-level", 166 config: ArchiveCatalogerConfig{ 167 UseNetwork: false, 168 UseMavenLocalRepository: true, 169 MavenLocalRepositoryDir: mavenLocalRepoDir, 170 ResolveTransitiveDependencies: true, 171 }, 172 expected: expectedTransientPackageData(), 173 }, 174 } 175 176 for _, test := range tests { 177 t.Run(test.name, func(t *testing.T) { 178 cat := NewPomCataloger(ArchiveCatalogerConfig{ 179 ArchiveSearchConfig: cataloging.ArchiveSearchConfig{ 180 IncludeIndexedArchives: true, 181 IncludeUnindexedArchives: true, 182 }, 183 UseNetwork: test.config.UseNetwork, 184 MavenBaseURL: test.config.MavenBaseURL, 185 UseMavenLocalRepository: test.config.UseMavenLocalRepository, 186 MavenLocalRepositoryDir: test.config.MavenLocalRepositoryDir, 187 ResolveTransitiveDependencies: test.config.ResolveTransitiveDependencies, 188 }) 189 pkgtest.TestCataloger(t, test.dir, cat, test.expected.packages, test.expected.relationships) 190 }) 191 } 192 } 193 194 func Test_parsePomXMLProject(t *testing.T) { 195 // TODO: ideally we would have the path to the contained pom.xml, not the jar 196 jarLocation := file.NewLocation("path/to/archive.jar") 197 ctx := context.TODO() 198 tests := []struct { 199 name string 200 project *pkg.JavaPomProject 201 licenses []pkg.License 202 }{ 203 { 204 name: "no license info", 205 project: &pkg.JavaPomProject{ 206 Path: "test-fixtures/pom/commons-codec.pom.xml", 207 Parent: &pkg.JavaPomParent{ 208 GroupID: "org.apache.commons", 209 ArtifactID: "commons-parent", 210 Version: "42", 211 }, 212 GroupID: "commons-codec", 213 ArtifactID: "commons-codec", 214 Version: "1.11", 215 Name: "Apache Commons Codec", 216 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.", 217 URL: "http://commons.apache.org/proper/commons-codec/", 218 }, 219 }, 220 { 221 name: "with license data", 222 project: &pkg.JavaPomProject{ 223 Path: "test-fixtures/pom/neo4j-license-maven-plugin.pom.xml", 224 Parent: &pkg.JavaPomParent{ 225 GroupID: "org.sonatype.oss", 226 ArtifactID: "oss-parent", 227 Version: "7", 228 }, 229 GroupID: "org.neo4j.build.plugins", 230 ArtifactID: "license-maven-plugin", 231 Version: "4-SNAPSHOT", 232 Name: "license-maven-plugin", 233 Description: "Maven 2 plugin to check and update license headers in source files", 234 URL: "http://components.neo4j.org/license-maven-plugin/4-SNAPSHOT", 235 }, 236 licenses: []pkg.License{ 237 { 238 Value: "The Apache Software License, Version 2.0", 239 SPDXExpression: "", // TODO: ideally we would parse this title to get Apache-2.0 (created issue #2210 https://github.com/anchore/syft/issues/2210) 240 Type: license.Declared, 241 URLs: []string{"http://www.apache.org/licenses/LICENSE-2.0.txt"}, 242 Locations: file.NewLocationSet(jarLocation), 243 }, 244 { 245 Value: "MIT", 246 SPDXExpression: "MIT", 247 Type: license.Declared, 248 Locations: file.NewLocationSet(jarLocation), 249 }, 250 { 251 Type: license.Declared, 252 URLs: []string{"https://opensource.org/license/unlicense/"}, 253 Locations: file.NewLocationSet(jarLocation), 254 }, 255 }, 256 }, 257 } 258 259 for _, test := range tests { 260 t.Run(test.name, func(t *testing.T) { 261 fixture, err := os.Open(test.project.Path) 262 assert.NoError(t, err) 263 r := maven.NewResolver(nil, maven.Config{}) 264 265 pom, err := maven.ParsePomXML(fixture) 266 require.NoError(t, err) 267 268 actual := newPomProject(context.Background(), r, fixture.Name(), pom) 269 assert.NoError(t, err) 270 assert.Equal(t, test.project, actual) 271 272 licenses, err := r.ResolveLicenses(context.Background(), pom) 273 //assert.NoError(t, err) 274 assert.Equal(t, test.licenses, toPkgLicenses(ctx, &jarLocation, licenses)) 275 }) 276 } 277 } 278 279 func Test_pomParent(t *testing.T) { 280 tests := []struct { 281 name string 282 input *maven.Parent 283 expected *pkg.JavaPomParent 284 }{ 285 { 286 name: "only group ID", 287 input: &maven.Parent{ 288 GroupID: ptr("org.something"), 289 }, 290 expected: &pkg.JavaPomParent{ 291 GroupID: "org.something", 292 }, 293 }, 294 { 295 name: "only artifact ID", 296 input: &maven.Parent{ 297 ArtifactID: ptr("something"), 298 }, 299 expected: &pkg.JavaPomParent{ 300 ArtifactID: "something", 301 }, 302 }, 303 { 304 name: "only Version", 305 input: &maven.Parent{ 306 Version: ptr("something"), 307 }, 308 expected: &pkg.JavaPomParent{ 309 Version: "something", 310 }, 311 }, 312 { 313 name: "nil", 314 input: nil, 315 expected: nil, 316 }, 317 { 318 name: "empty", 319 input: &maven.Parent{}, 320 expected: nil, 321 }, 322 { 323 name: "unused field", 324 input: &maven.Parent{ 325 RelativePath: ptr("something"), 326 }, 327 expected: nil, 328 }, 329 } 330 331 for _, test := range tests { 332 t.Run(test.name, func(t *testing.T) { 333 r := maven.NewResolver(nil, maven.DefaultConfig()) 334 assert.Equal(t, test.expected, pomParent(context.Background(), r, &maven.Project{Parent: test.input})) 335 }) 336 } 337 } 338 339 func Test_cleanDescription(t *testing.T) { 340 tests := []struct { 341 name string 342 input string 343 expected string 344 }{ 345 { 346 name: "indent + multiline", 347 input: ` The Apache Commons Codec package contains simple encoder and decoders for 348 various formats such as Base64 and Hexadecimal. In addition to these 349 widely used encoders and decoders, the codec package also maintains a 350 collection of phonetic encoding utilities.`, 351 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.", 352 }, 353 } 354 355 for _, test := range tests { 356 t.Run(test.name, func(t *testing.T) { 357 assert.Equal(t, test.expected, cleanDescription(test.input)) 358 }) 359 } 360 } 361 362 func Test_resolveLicenses(t *testing.T) { 363 mavenURL := maventest.MockRepo(t, "internal/maven/test-fixtures/maven-repo") 364 localM2 := "internal/maven/test-fixtures/maven-repo" 365 localDir := "internal/maven/test-fixtures/local" 366 containingDir := "internal/maven/test-fixtures/local/contains-child-1" 367 368 expectedLicenses := []pkg.License{ 369 { 370 Value: "Eclipse Public License v2.0", 371 SPDXExpression: "", 372 Type: license.Declared, 373 URLs: []string{"https://www.eclipse.org/legal/epl-v20.html"}, 374 }, 375 } 376 377 tests := []struct { 378 name string 379 scanDir string 380 cfg ArchiveCatalogerConfig 381 expected []pkg.License 382 }{ 383 { 384 name: "local no resolution", 385 scanDir: containingDir, 386 cfg: ArchiveCatalogerConfig{ 387 UseMavenLocalRepository: false, 388 UseNetwork: false, 389 MavenLocalRepositoryDir: "", 390 MavenBaseURL: "", 391 }, 392 expected: nil, 393 }, 394 { 395 name: "local all poms", 396 scanDir: localDir, 397 cfg: ArchiveCatalogerConfig{ 398 UseMavenLocalRepository: false, 399 UseNetwork: false, 400 }, 401 expected: expectedLicenses, 402 }, 403 { 404 name: "local m2 cache", 405 scanDir: containingDir, 406 cfg: ArchiveCatalogerConfig{ 407 UseMavenLocalRepository: true, 408 MavenLocalRepositoryDir: localM2, 409 UseNetwork: false, 410 MavenBaseURL: "", 411 }, 412 expected: expectedLicenses, 413 }, 414 { 415 name: "local with network", 416 scanDir: containingDir, 417 cfg: ArchiveCatalogerConfig{ 418 UseMavenLocalRepository: false, 419 UseNetwork: true, 420 MavenBaseURL: mavenURL, 421 }, 422 expected: expectedLicenses, 423 }, 424 } 425 426 for _, test := range tests { 427 t.Run(test.name, func(t *testing.T) { 428 cat := NewPomCataloger(test.cfg) 429 430 ds, err := directorysource.NewFromPath(test.scanDir) 431 require.NoError(t, err) 432 433 fr, err := ds.FileResolver(source.AllLayersScope) 434 require.NoError(t, err) 435 436 ctx := context.TODO() 437 pkgs, _, err := cat.Catalog(ctx, fr) 438 require.NoError(t, err) 439 440 var child1 pkg.Package 441 for _, p := range pkgs { 442 if p.Name == "child-one" { 443 child1 = p 444 break 445 } 446 } 447 require.Equal(t, "child-one", child1.Name) 448 449 got := child1.Licenses.ToSlice() 450 for i := 0; i < len(got); i++ { 451 // ignore locations, just check license text 452 (&got[i]).Locations = file.LocationSet{} 453 } 454 require.ElementsMatch(t, test.expected, got) 455 }) 456 } 457 } 458 459 func Test_corruptPomXml(t *testing.T) { 460 c := NewPomCataloger(DefaultArchiveCatalogerConfig()) 461 pkgtest.NewCatalogTester(). 462 FromDirectory(t, "test-fixtures/corrupt"). 463 WithError(). 464 TestCataloger(t, c) 465 } 466 467 type expected struct { 468 packages []pkg.Package 469 relationships []artifact.Relationship 470 } 471 472 func getCommonsTextExpectedPackages(resolved bool) expected { 473 pomXmlLocation := file.NewLocationSet(file.NewLocation("pom.xml")) 474 475 commonsText := pkg.Package{ 476 Name: "commons-text", 477 Version: "1.10.0", 478 PURL: "pkg:maven/org.apache.commons/commons-text@1.10.0", 479 Language: pkg.Java, 480 Type: pkg.JavaPkg, 481 FoundBy: pomCatalogerName, 482 Metadata: pkg.JavaArchive{ 483 PomProject: &pkg.JavaPomProject{ 484 Parent: &pkg.JavaPomParent{ 485 GroupID: "org.apache.commons", 486 ArtifactID: "commons-parent", 487 Version: "54", 488 }, 489 GroupID: "org.apache.commons", 490 ArtifactID: "commons-text", 491 Version: "1.10.0", 492 Name: "Apache Commons Text", 493 Description: "Apache Commons Text is a library focused on algorithms working on strings.", 494 URL: "https://commons.apache.org/proper/commons-text", 495 }, 496 }, 497 } 498 499 commonsLang3 := pkg.Package{ 500 Name: "commons-lang3", 501 Version: "3.12.0", 502 PURL: "pkg:maven/org.apache.commons/commons-lang3@3.12.0", 503 Language: pkg.Java, 504 Type: pkg.JavaPkg, 505 FoundBy: pomCatalogerName, 506 Metadata: pkg.JavaArchive{ 507 PomProperties: &pkg.JavaPomProperties{ 508 GroupID: "org.apache.commons", 509 ArtifactID: "commons-lang3", 510 }, 511 }, 512 } 513 514 junitJupiter := pkg.Package{ 515 Name: "junit-jupiter", 516 Version: "", 517 PURL: "pkg:maven/org.junit.jupiter/junit-jupiter", 518 Language: pkg.Java, 519 Type: pkg.JavaPkg, 520 FoundBy: pomCatalogerName, 521 Metadata: pkg.JavaArchive{ 522 PomProperties: &pkg.JavaPomProperties{ 523 GroupID: "org.junit.jupiter", 524 ArtifactID: "junit-jupiter", 525 Scope: "test", 526 }, 527 }, 528 } 529 530 assertjCore := pkg.Package{ 531 Name: "assertj-core", 532 Version: "3.23.1", 533 PURL: "pkg:maven/org.assertj/assertj-core@3.23.1", 534 Language: pkg.Java, 535 Type: pkg.JavaPkg, 536 FoundBy: pomCatalogerName, 537 Metadata: pkg.JavaArchive{ 538 PomProperties: &pkg.JavaPomProperties{ 539 GroupID: "org.assertj", 540 ArtifactID: "assertj-core", 541 Scope: "test", 542 }, 543 }, 544 } 545 546 commonsIO := pkg.Package{ 547 Name: "commons-io", 548 Version: "2.11.0", 549 PURL: "pkg:maven/commons-io/commons-io@2.11.0", 550 Language: pkg.Java, 551 Type: pkg.JavaPkg, 552 FoundBy: pomCatalogerName, 553 Metadata: pkg.JavaArchive{ 554 PomProperties: &pkg.JavaPomProperties{ 555 GroupID: "commons-io", 556 ArtifactID: "commons-io", 557 Scope: "test", 558 }, 559 }, 560 } 561 562 mockitoInline := pkg.Package{ 563 Name: "mockito-inline", 564 Version: "4.8.0", 565 PURL: "pkg:maven/org.mockito/mockito-inline@4.8.0", 566 Language: pkg.Java, 567 Type: pkg.JavaPkg, 568 FoundBy: pomCatalogerName, 569 Metadata: pkg.JavaArchive{ 570 PomProperties: &pkg.JavaPomProperties{ 571 GroupID: "org.mockito", 572 ArtifactID: "mockito-inline", 573 Scope: "test", 574 }, 575 }, 576 } 577 578 js := pkg.Package{ 579 Name: "js", 580 Version: "22.0.0.2", 581 PURL: "pkg:maven/org.graalvm.js/js@22.0.0.2", 582 Language: pkg.Java, 583 Type: pkg.JavaPkg, 584 FoundBy: pomCatalogerName, 585 Metadata: pkg.JavaArchive{ 586 PomProperties: &pkg.JavaPomProperties{ 587 GroupID: "org.graalvm.js", 588 ArtifactID: "js", 589 Scope: "test", 590 }, 591 }, 592 } 593 594 jsScriptengine := pkg.Package{ 595 Name: "js-scriptengine", 596 Version: "22.0.0.2", 597 PURL: "pkg:maven/org.graalvm.js/js-scriptengine@22.0.0.2", 598 Language: pkg.Java, 599 Type: pkg.JavaPkg, 600 FoundBy: pomCatalogerName, 601 Metadata: pkg.JavaArchive{ 602 PomProperties: &pkg.JavaPomProperties{ 603 GroupID: "org.graalvm.js", 604 ArtifactID: "js-scriptengine", 605 Scope: "test", 606 }, 607 }, 608 } 609 610 commonsRngSimple := pkg.Package{ 611 Name: "commons-rng-simple", 612 Version: "1.4", 613 PURL: "pkg:maven/org.apache.commons/commons-rng-simple@1.4", 614 Language: pkg.Java, 615 Type: pkg.JavaPkg, 616 FoundBy: pomCatalogerName, 617 Metadata: pkg.JavaArchive{ 618 PomProperties: &pkg.JavaPomProperties{ 619 GroupID: "org.apache.commons", 620 ArtifactID: "commons-rng-simple", 621 Scope: "test", 622 }, 623 }, 624 } 625 626 jmhCore := pkg.Package{ 627 Name: "jmh-core", 628 Version: "1.35", 629 PURL: "pkg:maven/org.openjdk.jmh/jmh-core@1.35", 630 Language: pkg.Java, 631 Type: pkg.JavaPkg, 632 FoundBy: pomCatalogerName, 633 Metadata: pkg.JavaArchive{ 634 PomProperties: &pkg.JavaPomProperties{ 635 GroupID: "org.openjdk.jmh", 636 ArtifactID: "jmh-core", 637 Scope: "test", 638 }, 639 }, 640 } 641 642 jmhGeneratorAnnprocess := pkg.Package{ 643 Name: "jmh-generator-annprocess", 644 Version: "1.35", 645 PURL: "pkg:maven/org.openjdk.jmh/jmh-generator-annprocess@1.35", 646 Language: pkg.Java, 647 Type: pkg.JavaPkg, 648 FoundBy: pomCatalogerName, 649 Metadata: pkg.JavaArchive{ 650 PomProperties: &pkg.JavaPomProperties{ 651 GroupID: "org.openjdk.jmh", 652 ArtifactID: "jmh-generator-annprocess", 653 Scope: "test", 654 }, 655 }, 656 } 657 658 if resolved { 659 junitJupiter.Version = "5.9.1" 660 } 661 662 pkgs := []pkg.Package{ 663 commonsText, 664 commonsLang3, 665 junitJupiter, 666 assertjCore, 667 commonsIO, 668 mockitoInline, 669 js, 670 jsScriptengine, 671 commonsRngSimple, 672 jmhCore, 673 jmhGeneratorAnnprocess, 674 } 675 676 var relationships []artifact.Relationship 677 for i := range pkgs { 678 p := &pkgs[i] 679 p.Locations = pomXmlLocation 680 finalizePackage(p) 681 if i == 0 { 682 continue 683 } 684 relationships = append(relationships, artifact.Relationship{ 685 From: *p, 686 To: pkgs[0], 687 Type: artifact.DependencyOfRelationship, 688 }) 689 } 690 691 return expected{pkgs, relationships} 692 } 693 694 func expectedTransientPackageData() expected { 695 epl2 := pkg.NewLicenseSet(pkg.License{ 696 Value: "Eclipse Public License v2.0", 697 Type: license.Declared, 698 URLs: []string{"https://www.eclipse.org/legal/epl-v20.html"}, 699 }) 700 transitiveTopLevel := pkg.Package{ 701 Name: "transitive-top-level", 702 Version: "99", 703 Metadata: pkg.JavaArchive{ 704 PomProject: &pkg.JavaPomProject{ 705 GroupID: "my.other.group", 706 ArtifactID: "transitive-top-level", 707 Version: "99", 708 }, 709 }, 710 } 711 childOne := pkg.Package{ 712 Name: "child-one", 713 Version: "1.3.6", 714 Licenses: epl2, 715 Metadata: pkg.JavaArchive{ 716 PomProject: &pkg.JavaPomProject{ 717 GroupID: "my.org", 718 ArtifactID: "child-one", 719 Version: "1.3.6", 720 Parent: &pkg.JavaPomParent{ 721 GroupID: "my.org", 722 ArtifactID: "parent-one", 723 Version: "3.11.0", 724 }, 725 }, 726 PomProperties: &pkg.JavaPomProperties{ 727 GroupID: "my.org", 728 ArtifactID: "child-one", 729 }, 730 }, 731 } 732 childTwo := pkg.Package{ 733 Name: "child-two", 734 Version: "2.1.90", 735 Licenses: epl2, 736 Metadata: pkg.JavaArchive{ 737 PomProject: &pkg.JavaPomProject{ 738 GroupID: "my.org", 739 ArtifactID: "child-two", 740 Version: "2.1.90", 741 Parent: &pkg.JavaPomParent{ 742 GroupID: "my.org", 743 ArtifactID: "parent-one", 744 Version: "3.11.0", 745 }, 746 }, 747 PomProperties: &pkg.JavaPomProperties{ 748 GroupID: "my.org", 749 ArtifactID: "child-two", 750 Scope: "test", 751 }, 752 }, 753 } 754 commonsLang3_113_7_8_0 := pkg.Package{ 755 Name: "commons-lang3", 756 Version: "3.113.7.8.0", 757 Metadata: pkg.JavaArchive{ 758 PomProperties: &pkg.JavaPomProperties{ 759 GroupID: "org.apache.commons", 760 ArtifactID: "commons-lang3", 761 }, 762 }, 763 } 764 commonsLang3_12_0 := pkg.Package{ 765 Name: "commons-lang3", 766 Version: "3.12.0", 767 Metadata: pkg.JavaArchive{ 768 PomProperties: &pkg.JavaPomProperties{ 769 GroupID: "org.apache.commons", 770 ArtifactID: "commons-lang3", 771 }, 772 }, 773 } 774 commonsMath3 := pkg.Package{ 775 Name: "commons-math3.11.0", 776 Version: "3.5", 777 Metadata: pkg.JavaArchive{ 778 PomProperties: &pkg.JavaPomProperties{ 779 GroupID: "org.apache.commons", 780 ArtifactID: "commons-math3.11.0", 781 }, 782 }, 783 } 784 commonsExec := pkg.Package{ 785 Name: "commons-exec", 786 Version: "1.3", 787 Metadata: pkg.JavaArchive{ 788 PomProperties: &pkg.JavaPomProperties{ 789 GroupID: "org.apache.commons", 790 ArtifactID: "commons-exec", 791 }, 792 }, 793 } 794 795 allPackages := []*pkg.Package{ 796 &transitiveTopLevel, 797 &childOne, 798 &childTwo, 799 &commonsLang3_12_0, 800 &commonsLang3_113_7_8_0, 801 &commonsMath3, 802 &commonsExec, 803 } 804 805 for _, p := range allPackages { 806 p.Language = pkg.Java 807 p.Type = pkg.JavaPkg 808 p.FoundBy = pomCatalogerName 809 p.Locations = file.NewLocationSet(file.NewLocation("pom.xml")) 810 finalizePackage(p) 811 } 812 813 pkgs := make([]pkg.Package, len(allPackages)) 814 for i := 0; i < len(allPackages); i++ { 815 pkgs[i] = *allPackages[i] 816 } 817 818 depOf := func(a, b pkg.Package) artifact.Relationship { 819 return artifact.Relationship{ 820 From: a, 821 To: b, 822 Type: artifact.DependencyOfRelationship, 823 } 824 } 825 826 return expected{ 827 packages: pkgs, 828 relationships: []artifact.Relationship{ 829 depOf(childTwo, transitiveTopLevel), 830 depOf(childOne, transitiveTopLevel), 831 depOf(commonsLang3_12_0, childOne), 832 depOf(commonsLang3_113_7_8_0, childTwo), 833 depOf(commonsMath3, childTwo), 834 depOf(commonsExec, childTwo), 835 }, 836 } 837 }