github.com/google/osv-scalibr@v0.4.1/extractor/filesystem/os/ecosystem/ecosystem_test.go (about) 1 // Copyright 2025 Google LLC 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package ecosystem_test 16 17 import ( 18 "testing" 19 20 "github.com/google/go-cmp/cmp" 21 apkmeta "github.com/google/osv-scalibr/extractor/filesystem/os/apk/metadata" 22 cosmeta "github.com/google/osv-scalibr/extractor/filesystem/os/cos/metadata" 23 dpkgmeta "github.com/google/osv-scalibr/extractor/filesystem/os/dpkg/metadata" 24 "github.com/google/osv-scalibr/extractor/filesystem/os/ecosystem" 25 flatpakmeta "github.com/google/osv-scalibr/extractor/filesystem/os/flatpak/metadata" 26 nixmeta "github.com/google/osv-scalibr/extractor/filesystem/os/nix/metadata" 27 pacmanmeta "github.com/google/osv-scalibr/extractor/filesystem/os/pacman/metadata" 28 portagemeta "github.com/google/osv-scalibr/extractor/filesystem/os/portage/metadata" 29 ospurl "github.com/google/osv-scalibr/extractor/filesystem/os/purl" 30 rpmmeta "github.com/google/osv-scalibr/extractor/filesystem/os/rpm/metadata" 31 snapmeta "github.com/google/osv-scalibr/extractor/filesystem/os/snap/metadata" 32 "github.com/google/osv-scalibr/purl" 33 ) 34 35 func TestMakeEcosystemAPK(t *testing.T) { 36 tests := []struct { 37 desc string 38 metadata *apkmeta.Metadata 39 want string 40 }{ 41 { 42 desc: "OS_version_trimmed", 43 metadata: &apkmeta.Metadata{ 44 OSVersionID: "4.5.6", 45 }, 46 want: "Alpine:v4.5", 47 }, 48 { 49 desc: "short_OS_version_not_trimmed", 50 metadata: &apkmeta.Metadata{ 51 OSVersionID: "4", 52 }, 53 want: "Alpine:v4", 54 }, 55 { 56 desc: "no OS version", 57 metadata: &apkmeta.Metadata{}, 58 want: "Alpine", 59 }, 60 { 61 desc: "BellSoft 1st case", 62 metadata: &apkmeta.Metadata{ 63 OSID: "alpaquita", 64 OSVersionID: "23", 65 }, 66 want: "Alpaquita:23", 67 }, 68 { 69 desc: "BellSoft 2nd case", 70 metadata: &apkmeta.Metadata{ 71 OSID: "alpaquita", 72 OSVersionID: "stream", 73 }, 74 want: "Alpaquita:stream", 75 }, 76 { 77 desc: "BellSoft 3rd case", 78 metadata: &apkmeta.Metadata{ 79 OSID: "bellsoft-hardened-containers", 80 OSVersionID: "23", 81 }, 82 want: "BellSoft Hardened Containers:23", 83 }, 84 { 85 desc: "BellSoft 4th case", 86 metadata: &apkmeta.Metadata{ 87 OSID: "bellsoft-hardened-containers", 88 OSVersionID: "stream", 89 }, 90 want: "BellSoft Hardened Containers:stream", 91 }, 92 } 93 for _, tt := range tests { 94 t.Run(tt.desc, func(t *testing.T) { 95 got := ecosystem.MakeEcosystem(tt.metadata) 96 if diff := cmp.Diff(tt.want, got.String()); diff != "" { 97 t.Errorf("ecosystem.MakeEcosystem(%v) (-want +got):\n%s", tt.metadata, diff) 98 } 99 }) 100 } 101 } 102 103 func TestMakeEcosystemDebian(t *testing.T) { 104 tests := []struct { 105 desc string 106 metadata *dpkgmeta.Metadata 107 want string 108 }{ 109 { 110 desc: "OS_ID_present", 111 metadata: &dpkgmeta.Metadata{ 112 OSID: "debian", 113 }, 114 want: "Debian", 115 }, 116 { 117 desc: "OS ID not present", 118 metadata: &dpkgmeta.Metadata{}, 119 want: "Linux", 120 }, 121 { 122 desc: "OS_version_present", 123 metadata: &dpkgmeta.Metadata{ 124 OSID: "debian", 125 OSVersionID: "12", 126 }, 127 want: "Debian:12", 128 }, 129 { 130 desc: "OS_ID_present_(OpenWrt),_not_valid_ecosystem,_so_ecosystem_should_be_empty", 131 metadata: &dpkgmeta.Metadata{ 132 OSID: "openwrt", 133 }, 134 want: "", 135 }, 136 { 137 desc: "OS_version_present_(OpenWrt),_not_valid_ecosystem,_ecosystem_should_be_empty", 138 metadata: &dpkgmeta.Metadata{ 139 OSID: "openwrt", 140 OSVersionID: "22.03.5", 141 }, 142 want: "", 143 }, 144 { 145 desc: "OS_version_present_(Generic_Linux),_not_valid_ecosystem,_ecosystem_should_be_empty", 146 metadata: &dpkgmeta.Metadata{ 147 OSID: "linux", 148 OSVersionID: "5", 149 }, 150 want: "Linux:5", 151 }, 152 } 153 for _, tt := range tests { 154 t.Run(tt.desc, func(t *testing.T) { 155 got := ecosystem.MakeEcosystem(tt.metadata) 156 if diff := cmp.Diff(tt.want, got.String()); diff != "" { 157 t.Errorf("ecosystem.MakeEcosystem(%v) (-want +got):\n%s", tt.metadata, diff) 158 } 159 }) 160 } 161 } 162 163 func TestEcosystemPacman(t *testing.T) { 164 tests := []struct { 165 desc string 166 metadata *pacmanmeta.Metadata 167 want string 168 }{ 169 { 170 desc: "OS_ID_present", 171 metadata: &pacmanmeta.Metadata{ 172 OSID: "arch", 173 }, 174 want: "", 175 }, 176 { 177 desc: "OS ID not present", 178 metadata: &pacmanmeta.Metadata{}, 179 want: "Linux", 180 }, 181 { 182 desc: "OS_version_present", 183 metadata: &pacmanmeta.Metadata{ 184 OSID: "arch", 185 OSVersionID: "20241201.0.284684", 186 }, 187 want: "", 188 }, 189 } 190 for _, tt := range tests { 191 t.Run(tt.desc, func(t *testing.T) { 192 got := ecosystem.MakeEcosystem(tt.metadata) 193 if diff := cmp.Diff(tt.want, got.String()); diff != "" { 194 t.Errorf("ecosystem.MakeEcosystem(%v) (-want +got):\n%s", tt.metadata, diff) 195 } 196 }) 197 } 198 } 199 200 func TestEcosystemPortage(t *testing.T) { 201 tests := []struct { 202 desc string 203 metadata *portagemeta.Metadata 204 want string 205 }{ 206 { 207 desc: "OS_ID_present", 208 metadata: &portagemeta.Metadata{ 209 OSID: "gentoo", 210 }, 211 want: "", 212 }, 213 { 214 desc: "OS ID not present", 215 metadata: &portagemeta.Metadata{}, 216 want: "Linux", 217 }, 218 { 219 desc: "OS_version_present", 220 metadata: &portagemeta.Metadata{ 221 OSID: "gentoo", 222 OSVersionID: "2.17", 223 }, 224 want: "", 225 }, 226 } 227 for _, tt := range tests { 228 t.Run(tt.desc, func(t *testing.T) { 229 got := ecosystem.MakeEcosystem(tt.metadata) 230 if diff := cmp.Diff(tt.want, got.String()); diff != "" { 231 t.Errorf("ecosystem.MakeEcosystem(%v) (-want +got):\n%s", tt.metadata, diff) 232 } 233 }) 234 } 235 } 236 237 func TestEcosystemRPM(t *testing.T) { 238 tests := []struct { 239 desc string 240 metadata *rpmmeta.Metadata 241 want string 242 }{ 243 { 244 desc: "RHEL", 245 metadata: &rpmmeta.Metadata{ 246 OSID: "rhel", 247 }, 248 want: "Red Hat", 249 }, 250 { 251 desc: "RHEL_with_CPE_name", 252 metadata: &rpmmeta.Metadata{ 253 OSID: "rhel", 254 OSCPEName: "cpe:/o:redhat:enterprise_linux:9::baseos", 255 }, 256 want: "Red Hat:enterprise_linux:9::baseos", 257 }, 258 { 259 desc: "rocky", 260 metadata: &rpmmeta.Metadata{ 261 OSID: "rocky", 262 }, 263 want: "Rocky Linux", 264 }, 265 { 266 desc: "openEuler_base_version_from_pretty_name", 267 metadata: &rpmmeta.Metadata{ 268 OSID: "openEuler", 269 OSPrettyName: "openEuler 24.03", 270 }, 271 want: "openEuler:24.03", 272 }, 273 { 274 desc: "openEuler_LTS_qualifier", 275 metadata: &rpmmeta.Metadata{ 276 OSID: "openEuler", 277 OSPrettyName: "openEuler 24.03 (LTS)", 278 }, 279 want: "openEuler:24.03-LTS", 280 }, 281 { 282 desc: "openEuler_LTS_service_pack_qualifier", 283 metadata: &rpmmeta.Metadata{ 284 OSID: "openEuler", 285 OSPrettyName: "openEuler 24.03 (LTS-SP1)", 286 }, 287 want: "openEuler:24.03-LTS-SP1", 288 }, 289 { 290 desc: "openEuler_fallback_to_version_ID", 291 metadata: &rpmmeta.Metadata{ 292 OSID: "openEuler", 293 OSVersionID: "24.03", 294 }, 295 want: "openEuler:24.03", 296 }, 297 { 298 desc: "openEuler_no_version_details", 299 metadata: &rpmmeta.Metadata{ 300 OSID: "openEuler", 301 }, 302 want: "openEuler", 303 }, 304 { 305 desc: "OS ID not present", 306 metadata: &rpmmeta.Metadata{}, 307 want: "", 308 }, 309 } 310 for _, tt := range tests { 311 t.Run(tt.desc, func(t *testing.T) { 312 got := ecosystem.MakeEcosystem(tt.metadata) 313 if diff := cmp.Diff(tt.want, got.String()); diff != "" { 314 t.Errorf("ecosystem.MakeEcosystem(%v) (-want +got):\n%s", tt.metadata, diff) 315 } 316 }) 317 } 318 } 319 320 func TestEcosystemSnap(t *testing.T) { 321 tests := []struct { 322 desc string 323 metadata *snapmeta.Metadata 324 want string 325 }{ 326 { 327 desc: "OS_ID_present", 328 metadata: &snapmeta.Metadata{ 329 OSID: "ubuntu", 330 }, 331 want: "Ubuntu", 332 }, 333 { 334 desc: "OS ID not present", 335 metadata: &snapmeta.Metadata{}, 336 want: "", 337 }, 338 } 339 for _, tt := range tests { 340 t.Run(tt.desc, func(t *testing.T) { 341 got := ecosystem.MakeEcosystem(tt.metadata) 342 if diff := cmp.Diff(tt.want, got.String()); diff != "" { 343 t.Errorf("ecosystem.MakeEcosystem(%v) (-want +got):\n%s", tt.metadata, diff) 344 } 345 }) 346 } 347 } 348 349 func TestMakePackageURLFlatpak(t *testing.T) { 350 pkgname := "pkgname" 351 pkgid := "pkgid" 352 pkgversion := "1.2.3" 353 releasedate := "2024-05-02" 354 osname := "Debian GNU/Linux" 355 osid := "debian" 356 osversionid := "12" 357 osbuildid := "bookworm" 358 developer := "developer" 359 tests := []struct { 360 desc string 361 metadata *flatpakmeta.Metadata 362 want *purl.PackageURL 363 }{ 364 { 365 desc: "Both_VERSION_ID_and_BUILD_ID_is_set", 366 metadata: &flatpakmeta.Metadata{ 367 PackageName: pkgname, 368 PackageID: pkgid, 369 PackageVersion: pkgversion, 370 ReleaseDate: releasedate, 371 OSName: osname, 372 OSID: osid, 373 OSVersionID: osversionid, 374 OSBuildID: osbuildid, 375 Developer: developer, 376 }, 377 want: &purl.PackageURL{ 378 Type: purl.TypeFlatpak, 379 Name: pkgname, 380 Namespace: "debian", 381 Version: pkgversion, 382 Qualifiers: purl.QualifiersFromMap(map[string]string{ 383 purl.Distro: "debian-12", 384 }), 385 }, 386 }, 387 { 388 desc: "only_BUILD_ID_set", 389 metadata: &flatpakmeta.Metadata{ 390 PackageName: pkgname, 391 PackageID: pkgid, 392 PackageVersion: pkgversion, 393 ReleaseDate: releasedate, 394 OSName: osname, 395 OSID: osid, 396 OSBuildID: osbuildid, 397 Developer: developer, 398 }, 399 want: &purl.PackageURL{ 400 Type: purl.TypeFlatpak, 401 Name: pkgname, 402 Namespace: "debian", 403 Version: pkgversion, 404 Qualifiers: purl.QualifiersFromMap(map[string]string{ 405 purl.Distro: "debian-bookworm", 406 }), 407 }, 408 }, 409 { 410 desc: "OS_ID_not_set", 411 metadata: &flatpakmeta.Metadata{ 412 PackageName: pkgname, 413 PackageID: pkgid, 414 PackageVersion: pkgversion, 415 ReleaseDate: releasedate, 416 OSName: osname, 417 OSVersionID: osversionid, 418 OSBuildID: osbuildid, 419 Developer: developer, 420 }, 421 want: &purl.PackageURL{ 422 Type: purl.TypeFlatpak, 423 Name: pkgname, 424 Namespace: "", 425 Version: pkgversion, 426 Qualifiers: purl.QualifiersFromMap(map[string]string{ 427 purl.Distro: "12", 428 }), 429 }, 430 }, 431 } 432 for _, tt := range tests { 433 t.Run(tt.desc, func(t *testing.T) { 434 got := ospurl.MakePackageURL(pkgname, pkgversion, purl.TypeFlatpak, tt.metadata) 435 if diff := cmp.Diff(tt.want, got); diff != "" { 436 t.Errorf("ospurl.MakePackageURL(%v, %v, %v, %v): unexpected PURL (-want +got):\n%s", pkgname, pkgversion, purl.TypeFlatpak, tt.metadata, diff) 437 } 438 }) 439 } 440 } 441 442 func TestMakePackageURLAPK(t *testing.T) { 443 tests := []struct { 444 desc string 445 metadata *apkmeta.Metadata 446 want *purl.PackageURL 447 }{ 448 { 449 desc: "all_fields_present", 450 metadata: &apkmeta.Metadata{ 451 PackageName: "Name", 452 OriginName: "originName", 453 OSID: "id", 454 OSVersionID: "4.5.6", 455 }, 456 want: &purl.PackageURL{ 457 Type: purl.TypeApk, 458 Name: "name", 459 Namespace: "id", 460 Version: "1.2.3", 461 Qualifiers: purl.QualifiersFromMap(map[string]string{purl.Distro: "4.5.6", purl.Origin: "originName"}), 462 }, 463 }, 464 { 465 desc: "OS_ID_missing", 466 metadata: &apkmeta.Metadata{ 467 PackageName: "Name", 468 OriginName: "originName", 469 OSVersionID: "4.5.6", 470 }, 471 want: &purl.PackageURL{ 472 Type: purl.TypeApk, 473 Name: "name", 474 Namespace: "alpine", 475 Version: "1.2.3", 476 Qualifiers: purl.QualifiersFromMap(map[string]string{purl.Distro: "4.5.6", purl.Origin: "originName"}), 477 }, 478 }, 479 { 480 desc: "OS_version_ID_missing", 481 metadata: &apkmeta.Metadata{ 482 PackageName: "Name", 483 OriginName: "originName", 484 OSID: "id", 485 }, 486 want: &purl.PackageURL{ 487 Type: purl.TypeApk, 488 Name: "name", 489 Namespace: "id", 490 Version: "1.2.3", 491 Qualifiers: purl.QualifiersFromMap(map[string]string{purl.Origin: "originName"}), 492 }, 493 }, 494 } 495 for _, tt := range tests { 496 t.Run(tt.desc, func(t *testing.T) { 497 got := ospurl.MakePackageURL("name", "1.2.3", purl.TypeApk, tt.metadata) 498 if diff := cmp.Diff(tt.want, got); diff != "" { 499 t.Errorf("ospurl.MakePackageURL(%v): unexpected PURL (-want +got):\n%s", tt.metadata, diff) 500 } 501 }) 502 } 503 } 504 505 func TestMakePackageURLCOS(t *testing.T) { 506 tests := []struct { 507 desc string 508 metadata *cosmeta.Metadata 509 want *purl.PackageURL 510 }{ 511 { 512 desc: "both_versions_present", 513 metadata: &cosmeta.Metadata{ 514 OSVersionID: "101", 515 OSVersion: "97", 516 }, 517 want: &purl.PackageURL{ 518 Type: purl.TypeCOS, 519 Name: "name", 520 Version: "1.2.3", 521 Qualifiers: purl.QualifiersFromMap(map[string]string{purl.Distro: "cos-101"}), 522 }, 523 }, 524 { 525 desc: "only_VERSION_set", 526 metadata: &cosmeta.Metadata{ 527 OSVersion: "97", 528 }, 529 want: &purl.PackageURL{ 530 Type: purl.TypeCOS, 531 Name: "name", 532 Version: "1.2.3", 533 Qualifiers: purl.QualifiersFromMap(map[string]string{purl.Distro: "cos-97"}), 534 }, 535 }, 536 { 537 desc: "only_VERSION_ID_set", 538 metadata: &cosmeta.Metadata{ 539 OSVersionID: "101", 540 }, 541 want: &purl.PackageURL{ 542 Type: purl.TypeCOS, 543 Name: "name", 544 Version: "1.2.3", 545 Qualifiers: purl.QualifiersFromMap(map[string]string{purl.Distro: "cos-101"}), 546 }, 547 }, 548 { 549 desc: "no versions set", 550 metadata: &cosmeta.Metadata{}, 551 want: &purl.PackageURL{ 552 Type: purl.TypeCOS, 553 Name: "name", 554 Version: "1.2.3", 555 Qualifiers: purl.Qualifiers{}, 556 }, 557 }, 558 } 559 for _, tt := range tests { 560 t.Run(tt.desc, func(t *testing.T) { 561 got := ospurl.MakePackageURL("name", "1.2.3", purl.TypeCOS, tt.metadata) 562 if diff := cmp.Diff(tt.want, got); diff != "" { 563 t.Errorf("ospurl.MakePackageURL(%v): unexpected PURL (-want +got):\n%s", tt.metadata, diff) 564 } 565 }) 566 } 567 } 568 569 func TestMakePackageURLRPM(t *testing.T) { 570 pkgname := "pkgname" 571 source := "source.rpm" 572 version := "1.2.3" 573 epoch := 1 574 tests := []struct { 575 desc string 576 metadata *rpmmeta.Metadata 577 want *purl.PackageURL 578 }{ 579 { 580 desc: "version_ID_and_build_ID_present", 581 metadata: &rpmmeta.Metadata{ 582 PackageName: pkgname, 583 SourceRPM: source, 584 Epoch: epoch, 585 OSID: "fedora", 586 OSVersionID: "32", 587 OSBuildID: "asdf", 588 }, 589 want: &purl.PackageURL{ 590 Type: purl.TypeRPM, 591 Name: pkgname, 592 Namespace: "fedora", 593 Version: version, 594 Qualifiers: purl.QualifiersFromMap(map[string]string{ 595 purl.Epoch: "1", 596 purl.Distro: "fedora-32", 597 purl.SourceRPM: source, 598 }), 599 }, 600 }, 601 { 602 desc: "only_build_ID_present", 603 metadata: &rpmmeta.Metadata{ 604 PackageName: pkgname, 605 SourceRPM: source, 606 Epoch: epoch, 607 OSID: "fedora", 608 OSBuildID: "asdf", 609 }, 610 want: &purl.PackageURL{ 611 Type: purl.TypeRPM, 612 Name: pkgname, 613 Namespace: "fedora", 614 Version: version, 615 Qualifiers: purl.QualifiersFromMap(map[string]string{ 616 purl.Epoch: "1", 617 purl.Distro: "fedora-asdf", 618 purl.SourceRPM: source, 619 }), 620 }, 621 }, 622 { 623 desc: "ID_missing", 624 metadata: &rpmmeta.Metadata{ 625 PackageName: pkgname, 626 SourceRPM: source, 627 Epoch: epoch, 628 OSVersionID: "32", 629 OSBuildID: "asdf", 630 }, 631 want: &purl.PackageURL{ 632 Type: purl.TypeRPM, 633 Name: pkgname, 634 Namespace: "", 635 Version: version, 636 Qualifiers: purl.QualifiersFromMap(map[string]string{ 637 purl.Epoch: "1", 638 purl.Distro: "32", 639 purl.SourceRPM: source, 640 }), 641 }, 642 }, 643 } 644 for _, tt := range tests { 645 t.Run(tt.desc, func(t *testing.T) { 646 got := ospurl.MakePackageURL(pkgname, version, purl.TypeRPM, tt.metadata) 647 if diff := cmp.Diff(tt.want, got); diff != "" { 648 t.Errorf("ospurl.MakePackageURL(%v): unexpected PURL (-want +got):\n%s", tt.metadata, diff) 649 } 650 }) 651 } 652 } 653 654 func TestMakePackageURLSnap(t *testing.T) { 655 snapName := "testSnap" 656 snapVersion := "1.2.3" 657 snapGrade := "stable" 658 snapType := "os" 659 architectures := []string{"amd64", "arm64"} 660 osID := "debian" 661 osVersionCodename := "bookworm" 662 osVersionID := "12" 663 664 tests := []struct { 665 desc string 666 metadata *snapmeta.Metadata 667 want *purl.PackageURL 668 }{ 669 { 670 desc: "Both_VERSION_CODENAME_and_VERSION_ID_are_set", 671 metadata: &snapmeta.Metadata{ 672 Name: snapName, 673 Version: snapVersion, 674 Grade: snapGrade, 675 Type: snapType, 676 Architectures: architectures, 677 OSID: osID, 678 OSVersionCodename: osVersionCodename, 679 OSVersionID: osVersionID, 680 }, 681 want: &purl.PackageURL{ 682 Type: purl.TypeSnap, 683 Name: snapName, 684 Namespace: osID, 685 Version: snapVersion, 686 Qualifiers: purl.QualifiersFromMap(map[string]string{ 687 purl.Distro: osVersionCodename, 688 }), 689 }, 690 }, 691 { 692 desc: "Only_VERSION_ID_is_set", 693 metadata: &snapmeta.Metadata{ 694 Name: snapName, 695 Version: snapVersion, 696 Grade: snapGrade, 697 Type: snapType, 698 Architectures: architectures, 699 OSID: osID, 700 OSVersionID: osVersionID, 701 }, 702 want: &purl.PackageURL{ 703 Type: purl.TypeSnap, 704 Name: snapName, 705 Namespace: osID, 706 Version: snapVersion, 707 Qualifiers: purl.QualifiersFromMap(map[string]string{ 708 purl.Distro: osVersionID, 709 }), 710 }, 711 }, 712 { 713 desc: "OSID,_VERSION_CODENAME_and_VERSION_ID_all_are_not_set", 714 metadata: &snapmeta.Metadata{ 715 Name: snapName, 716 Version: snapVersion, 717 Grade: snapGrade, 718 Type: snapType, 719 Architectures: architectures, 720 }, 721 want: &purl.PackageURL{ 722 Type: purl.TypeSnap, 723 Name: snapName, 724 Namespace: "", 725 Version: snapVersion, 726 Qualifiers: purl.QualifiersFromMap(map[string]string{}), 727 }, 728 }, 729 } 730 for _, tt := range tests { 731 t.Run(tt.desc, func(t *testing.T) { 732 got := ospurl.MakePackageURL(snapName, snapVersion, purl.TypeSnap, tt.metadata) 733 if diff := cmp.Diff(tt.want, got); diff != "" { 734 t.Errorf("ospurl.MakePackageURL(%v): unexpected PURL (-want +got):\n%s", tt.metadata, diff) 735 } 736 }) 737 } 738 } 739 740 func TestMakePackageURLPacman(t *testing.T) { 741 pkgName := "pkgName" 742 pkgVersion := "pkgVersion" 743 PackageDependencies := "pkgDependencies1, pkgDependencies2" 744 745 tests := []struct { 746 desc string 747 metadata *pacmanmeta.Metadata 748 want *purl.PackageURL 749 }{ 750 { 751 desc: "all_fields_present", 752 metadata: &pacmanmeta.Metadata{ 753 PackageName: pkgName, 754 PackageVersion: pkgVersion, 755 OSID: "arch", 756 OSVersionID: "20241201.0.284684", 757 PackageDependencies: PackageDependencies, 758 }, 759 want: &purl.PackageURL{ 760 Type: purl.TypePacman, 761 Name: pkgName, 762 Namespace: "arch", 763 Version: pkgVersion, 764 Qualifiers: purl.QualifiersFromMap(map[string]string{ 765 purl.Distro: "20241201.0.284684", 766 purl.PackageDependencies: PackageDependencies, 767 }), 768 }, 769 }, 770 { 771 desc: "only_VERSION_ID_set", 772 metadata: &pacmanmeta.Metadata{ 773 PackageName: pkgName, 774 PackageVersion: pkgVersion, 775 OSID: "arch", 776 OSVersionID: "20241201.0.284684", 777 PackageDependencies: PackageDependencies, 778 }, 779 want: &purl.PackageURL{ 780 Type: purl.TypePacman, 781 Name: pkgName, 782 Namespace: "arch", 783 Version: pkgVersion, 784 Qualifiers: purl.QualifiersFromMap(map[string]string{ 785 purl.Distro: "20241201.0.284684", 786 purl.PackageDependencies: PackageDependencies, 787 }), 788 }, 789 }, 790 { 791 desc: "OS_ID_not_set,_fallback_to_Linux", 792 metadata: &pacmanmeta.Metadata{ 793 PackageName: pkgName, 794 PackageVersion: pkgVersion, 795 OSVersionID: "20241201.0.284684", 796 PackageDependencies: PackageDependencies, 797 }, 798 want: &purl.PackageURL{ 799 Type: purl.TypePacman, 800 Name: pkgName, 801 Namespace: "linux", 802 Version: pkgVersion, 803 Qualifiers: purl.QualifiersFromMap(map[string]string{ 804 purl.Distro: "20241201.0.284684", 805 purl.PackageDependencies: PackageDependencies, 806 }), 807 }, 808 }, 809 } 810 for _, tt := range tests { 811 t.Run(tt.desc, func(t *testing.T) { 812 got := ospurl.MakePackageURL(pkgName, pkgVersion, purl.TypePacman, tt.metadata) 813 if diff := cmp.Diff(tt.want, got); diff != "" { 814 t.Errorf("ospurl.MakePackageURL(%v): unexpected PURL (-want +got):\n%s", tt.metadata, diff) 815 } 816 }) 817 } 818 } 819 820 func TestMakePackageURLPortage(t *testing.T) { 821 pkgName := "pkgName" 822 pkgVersion := "pkgVersion" 823 824 tests := []struct { 825 desc string 826 metadata *portagemeta.Metadata 827 want *purl.PackageURL 828 }{ 829 { 830 desc: "all_fields_present", 831 metadata: &portagemeta.Metadata{ 832 PackageName: pkgName, 833 PackageVersion: pkgVersion, 834 OSID: "Gentoo", 835 OSVersionID: "20241201.0.284684", 836 }, 837 want: &purl.PackageURL{ 838 Type: purl.TypePortage, 839 Name: pkgName, 840 Namespace: "Gentoo", 841 Version: pkgVersion, 842 Qualifiers: purl.QualifiersFromMap(map[string]string{ 843 purl.Distro: "20241201.0.284684", 844 }), 845 }, 846 }, 847 { 848 desc: "only_VERSION_ID_set", 849 metadata: &portagemeta.Metadata{ 850 PackageName: pkgName, 851 PackageVersion: pkgVersion, 852 OSID: "linux", 853 OSVersionID: "2.17", 854 }, 855 want: &purl.PackageURL{ 856 Type: purl.TypePortage, 857 Name: pkgName, 858 Namespace: "linux", 859 Version: pkgVersion, 860 Qualifiers: purl.QualifiersFromMap(map[string]string{ 861 purl.Distro: "2.17", 862 }), 863 }, 864 }, 865 { 866 desc: "ID_not_set,_fallback_to_linux", 867 metadata: &portagemeta.Metadata{ 868 PackageName: pkgName, 869 PackageVersion: pkgVersion, 870 OSVersionID: "jammy", 871 }, 872 want: &purl.PackageURL{ 873 Type: purl.TypePortage, 874 Name: pkgName, 875 Namespace: "linux", 876 Version: pkgVersion, 877 Qualifiers: purl.QualifiersFromMap(map[string]string{ 878 purl.Distro: "jammy", 879 }), 880 }, 881 }, 882 } 883 for _, tt := range tests { 884 t.Run(tt.desc, func(t *testing.T) { 885 got := ospurl.MakePackageURL(pkgName, pkgVersion, purl.TypePortage, tt.metadata) 886 if diff := cmp.Diff(tt.want, got); diff != "" { 887 t.Errorf("ospurl.MakePackageURL(%v): unexpected PURL (-want +got):\n%s", tt.metadata, diff) 888 } 889 }) 890 } 891 } 892 893 func TestMakePackageURLNix(t *testing.T) { 894 pkgName := "pkgName" 895 pkgVersion := "pkgVersion" 896 pkgHash := "pkgHash" 897 pkgOutput := "pkgOutput" 898 899 tests := []struct { 900 desc string 901 metadata *nixmeta.Metadata 902 want *purl.PackageURL 903 }{ 904 { 905 desc: "all_fields_present", 906 metadata: &nixmeta.Metadata{ 907 PackageName: pkgName, 908 PackageVersion: pkgVersion, 909 PackageHash: pkgHash, 910 PackageOutput: pkgOutput, 911 OSID: "nixos", 912 OSVersionCodename: "vicuna", 913 OSVersionID: "24.11", 914 }, 915 want: &purl.PackageURL{ 916 Type: purl.TypeNix, 917 Name: pkgName, 918 Version: pkgVersion, 919 Qualifiers: purl.QualifiersFromMap(map[string]string{ 920 "distro": "vicuna", 921 }), 922 }, 923 }, 924 { 925 desc: "only_VERSION_ID_set", 926 metadata: &nixmeta.Metadata{ 927 PackageName: pkgName, 928 PackageVersion: pkgVersion, 929 PackageHash: pkgHash, 930 PackageOutput: pkgOutput, 931 OSID: "nixos", 932 OSVersionID: "24.11", 933 }, 934 want: &purl.PackageURL{ 935 Type: purl.TypeNix, 936 Name: pkgName, 937 Version: pkgVersion, 938 Qualifiers: purl.QualifiersFromMap(map[string]string{ 939 "distro": "24.11", 940 }), 941 }, 942 }, 943 { 944 desc: "OS_ID_not_set,_fallback_to_Nixos", 945 metadata: &nixmeta.Metadata{ 946 PackageName: pkgName, 947 PackageVersion: pkgVersion, 948 PackageHash: pkgHash, 949 PackageOutput: pkgOutput, 950 OSVersionCodename: "vicuna", 951 OSVersionID: "24.11", 952 }, 953 want: &purl.PackageURL{ 954 Type: purl.TypeNix, 955 Name: pkgName, 956 Version: pkgVersion, 957 Qualifiers: purl.QualifiersFromMap(map[string]string{ 958 "distro": "vicuna", 959 }), 960 }, 961 }, 962 } 963 for _, tt := range tests { 964 t.Run(tt.desc, func(t *testing.T) { 965 got := ospurl.MakePackageURL(pkgName, pkgVersion, purl.TypeNix, tt.metadata) 966 if diff := cmp.Diff(tt.want, got); diff != "" { 967 t.Errorf("ospurl.MakePackageURL(%v): unexpected PURL (-want +got):\n%s", tt.metadata, diff) 968 } 969 }) 970 } 971 }