diff --git a/schemas/purl-test.schema.json b/schemas/purl-test.schema.json index 4221e75d..744b09fb 100644 --- a/schemas/purl-test.schema.json +++ b/schemas/purl-test.schema.json @@ -68,6 +68,34 @@ } } }, + "purl_validation_message": { + "title": "PURL validation message", + "description": "Validation severity and message to use as a test expected output when validating a PURL.", + "type": "object", + "additionalProperties": false, + "properties": { + "severity": { + "title": "Validation severity", + "description": "Validation severity.", + "type": "string", + "enum": [ + "info", + "warning", + "error" + ], + "meta:enum": { + "info": "Informational validation message", + "warning": "Warning validation message", + "error": "Error validation message" + } + }, + "message": { + "title": "Validation message", + "description": "Validation message.", + "type": "string" + } + } + }, "purl_test": { "title": "PURL test", "description": "A PURL test with input and expected output.", @@ -104,12 +132,14 @@ "enum": [ "build", "parse", - "roundtrip" + "roundtrip", + "validation" ], "meta:enum": { "build": "A PURL building test from decoded components to a canonical PURL string.", "parse": "A PURL building test from decoded components to a canonical PURL string.", - "roundtrip": "A PURL roundtrip test, parsing then building back a PURL from a canonical string input." + "roundtrip": "A PURL roundtrip test, parsing then building back a PURL from a canonical string input.", + "validation": "A PURL validation test, checking if a PURL follows all the rules for a particular ecosystem." } }, "expected_failure": { @@ -284,6 +314,39 @@ "expected_failure_reason" ] } + }, + { + "if": { + "properties": { + "test_type": { + "const": "validation" + } + }, + "required": [ + "test_type" + ] + }, + "then": { + "properties": { + "input": { + "title": "Input test PURL", + "description": "A PURL string to use as a test input (canonical or not).", + "type": "string" + }, + "expected_output": { + "title": "Expected validation messages and severities", + "description": "List of validation objects with message and severity expected for this test. Can be an empty list.", + "type": "array", + "items": { + "$ref": "#/definitions/purl_validation_message" + } + } + }, + "required": [ + "input", + "expected_output" + ] + } } ] } diff --git a/tests/types/alpm-test.json b/tests/types/alpm-test.json index 92d75e74..71767a73 100644 --- a/tests/types/alpm-test.json +++ b/tests/types/alpm-test.json @@ -135,6 +135,58 @@ "expected_output": "pkg:alpm/arch/containers-common@1:0.47.4-4?arch=x86_64", "expected_failure": false, "expected_failure_reason": null + }, + { + "description": "Valid alpm package with arch qualifier", + "test_group": "base", + "test_type": "validation", + "input": "pkg:alpm/arch/pacman@6.0.1-1?arch=x86_64", + "expected_output": [] + }, + { + "description": "alpm package with uppercase nmamespace", + "test_group": "base", + "test_type": "validation", + "input": "pkg:alpm/Arch/pacman@6.0.1-1?arch=x86_64", + "expected_output": [ + { + "severity": "warning", + "message": "Namespace is not lowercased for purl type: 'alpm'" + } + ] + }, + { + "description": "alpm package with uppercase nmamespace (advanced)", + "test_group": "advanced", + "test_type": "validation", + "input": "pkg:alpm/Arch/pacman@6.0.1-1?arch=x86_64", + "expected_output": [] + }, + { + "description": "Valid alpm package with 'any' arch", + "test_group": "base", + "test_type": "validation", + "input": "pkg:alpm/arch/python-pip@21.0-1?arch=any", + "expected_output": [] + }, + { + "description": "Valid alpm package with epoch in version", + "test_group": "advanced", + "test_type": "validation", + "input": "pkg:alpm/arch/containers-common@1:0.47.4-4?arch=x86_64", + "expected_output": [] + }, + { + "description": "alpm package missing namespace", + "test_group": "base", + "test_type": "validation", + "input": "pkg:alpm/pacman@6.0.1-1?arch=x86_64", + "expected_output": [ + { + "severity": "error", + "message": "Namespace is required for purl type: 'alpm'" + } + ] } ] } diff --git a/tests/types/apk-test.json b/tests/types/apk-test.json index a2f4506e..ba0cd3d1 100644 --- a/tests/types/apk-test.json +++ b/tests/types/apk-test.json @@ -90,6 +90,62 @@ "expected_output": "pkg:apk/alpine/apk@2.12.9-r3?arch=x86", "expected_failure": false, "expected_failure_reason": null + }, + { + "description": "Valid apk package with arch qualifier", + "test_group": "base", + "test_type": "validation", + "input": "pkg:apk/alpine/curl@7.83.0-r0?arch=x86", + "expected_output": [] + }, + { + "description": "Valid apk package with higher version and arch qualifier", + "test_group": "base", + "test_type": "validation", + "input": "pkg:apk/alpine/apk@2.12.9-r3?arch=x86", + "expected_output": [] + }, + { + "description": "Valid apk package with openwrt vendor", + "test_group": "advanced", + "test_type": "validation", + "input": "pkg:apk/openwrt/busybox@1.35.0-r5?arch=mips", + "expected_output": [] + }, + { + "description": "apk package missing namespace", + "test_group": "base", + "test_type": "validation", + "input": "pkg:apk/curl@7.83.0-r0?arch=x86", + "expected_output": [ + { + "severity": "error", + "message": "Namespace is required for purl type: 'apk'" + } + ] + }, + { + "description": "apk package with uppercase namespace and name", + "test_group": "base", + "test_type": "validation", + "input": "pkg:apk/FOO/BAR@7.83.0-r0?arch=x86", + "expected_output": [ + { + "severity": "warning", + "message": "Namespace is not lowercased for purl type: 'apk'" + }, + { + "severity": "warning", + "message": "Name is not lowercased for purl type: 'apk'" + } + ] + }, + { + "description": "apk package with uppercase namespace and name (advanced)", + "test_group": "advanced", + "test_type": "validation", + "input": "pkg:apk/FOO/BAR@7.83.0-r0?arch=x86", + "expected_output": [] } ] } diff --git a/tests/types/bitbucket-test.json b/tests/types/bitbucket-test.json index 8bc5c017..37faaa1b 100644 --- a/tests/types/bitbucket-test.json +++ b/tests/types/bitbucket-test.json @@ -91,6 +91,39 @@ "expected_output": "pkg:bitbucket/birkenfeld/pygments-main@244fd47e07d1014f0aed9c", "expected_failure": false, "expected_failure_reason": null + }, + { + "description": "Valid Bitbucket package with commit hash as version", + "test_group": "base", + "test_type": "validation", + "input": "pkg:bitbucket/birkenfeld/pygments-main@244fd47e07d1014f0aed9c", + "expected_output": [] + }, + { + "description": "Valid Bitbucket package with subpath", + "test_group": "base", + "test_type": "validation", + "input": "pkg:bitbucket/teamname/repo-name@1.0.0#src/main", + "expected_output": [] + }, + { + "description": "Valid Bitbucket package with qualifiers", + "test_group": "base", + "test_type": "validation", + "input": "pkg:bitbucket/company/service@release-2024?arch=x86_64&os=linux", + "expected_output": [ + { + "severity": "info", + "message": "Invalid qualifiers found: arch, os. Allowed qualifiers are: repository_url" + } + ] + }, + { + "description": "Valid Bitbucket package with qualifiers", + "test_group": "advanced", + "test_type": "validation", + "input": "pkg:bitbucket/company/service@release-2024?arch=x86_64&os=linux", + "expected_output": [] } ] } diff --git a/tests/types/bitnami-test.json b/tests/types/bitnami-test.json index 497e7f1e..ef1001d6 100644 --- a/tests/types/bitnami-test.json +++ b/tests/types/bitnami-test.json @@ -184,6 +184,34 @@ "expected_output": "pkg:bitnami/wordpress@6.2.0?arch=arm64&distro=photon-4", "expected_failure": false, "expected_failure_reason": null + }, + { + "description": "Valid Bitnami package without version", + "test_group": "base", + "test_type": "validation", + "input": "pkg:bitnami/wordpress?distro=debian-12", + "expected_output": [] + }, + { + "description": "Valid Bitnami package with version and distro", + "test_group": "base", + "test_type": "validation", + "input": "pkg:bitnami/wordpress@6.2.0?distro=debian-12", + "expected_output": [] + }, + { + "description": "Valid Bitnami package with arch and distro", + "test_group": "advanced", + "test_type": "validation", + "input": "pkg:bitnami/wordpress@6.2.0?arch=arm64&distro=debian-12", + "expected_output": [] + }, + { + "description": "Valid Bitnami package with another distro", + "test_group": "advanced", + "test_type": "validation", + "input": "pkg:bitnami/wordpress@6.2.0?arch=arm64&distro=photon-4", + "expected_output": [] } ] } diff --git a/tests/types/cargo-test.json b/tests/types/cargo-test.json index d29d89f8..82fb15e1 100644 --- a/tests/types/cargo-test.json +++ b/tests/types/cargo-test.json @@ -123,6 +123,39 @@ "expected_output": "pkg:cargo/structopt@0.3.11", "expected_failure": false, "expected_failure_reason": null + }, + { + "description": "Valid Cargo package with name and version", + "test_group": "base", + "test_type": "validation", + "input": "pkg:cargo/rand@0.7.2", + "expected_output": [] + }, + { + "description": "Valid Cargo package with another example", + "test_group": "base", + "test_type": "validation", + "input": "pkg:cargo/clap@2.33.0", + "expected_output": [] + }, + { + "description": "Cargo package without version", + "test_group": "advanced", + "test_type": "validation", + "input": "pkg:cargo/structopt", + "expected_output": [] + }, + { + "description": "Cargo package with namespace (not allowed)", + "test_group": "advanced", + "test_type": "validation", + "input": "pkg:cargo/rustlang/serde@1.0.0", + "expected_output": [ + { + "severity": "error", + "message": "Namespace is prohibited for purl type: 'cargo'" + } + ] } ] } diff --git a/tests/types/cocoapods-test.json b/tests/types/cocoapods-test.json index 82ddde5f..87b980a4 100644 --- a/tests/types/cocoapods-test.json +++ b/tests/types/cocoapods-test.json @@ -164,6 +164,39 @@ "expected_output": "pkg:cocoapods/GoogleUtilities@7.5.2#NSData%2Bzlib", "expected_failure": false, "expected_failure_reason": null + }, + { + "description": "Valid CocoaPods package with name and version", + "test_group": "base", + "test_type": "validation", + "input": "pkg:cocoapods/AFNetworking@4.0.1", + "expected_output": [] + }, + { + "description": "Valid CocoaPods package with subspec in subpath", + "test_group": "base", + "test_type": "validation", + "input": "pkg:cocoapods/GoogleUtilities@7.5.2#NSData+zlib", + "expected_output": [] + }, + { + "description": "CocoaPods package without version", + "test_group": "advanced", + "test_type": "validation", + "input": "pkg:cocoapods/MapsIndoors", + "expected_output": [] + }, + { + "description": "CocoaPods package with namespace (not allowed)", + "test_group": "advanced", + "test_type": "validation", + "input": "pkg:cocoapods/apple/ShareKit@2.0#Twitter", + "expected_output": [ + { + "severity": "error", + "message": "Namespace is prohibited for purl type: 'cocoapods'" + } + ] } ] } diff --git a/tests/types/composer-test.json b/tests/types/composer-test.json index 9e37fd22..e0f3780c 100644 --- a/tests/types/composer-test.json +++ b/tests/types/composer-test.json @@ -116,6 +116,62 @@ "expected_output": "pkg:composer/laravel/laravel@5.5.0", "expected_failure": false, "expected_failure_reason": null + }, + { + "description": "Valid Composer package with vendor, name, and version", + "test_group": "base", + "test_type": "validation", + "input": "pkg:composer/laravel/laravel@5.5.0", + "expected_output": [] + }, + { + "description": "Composer package without version", + "test_group": "base", + "test_type": "validation", + "input": "pkg:composer/symfony/console", + "expected_output": [] + }, + { + "description": "Composer package with uppercase namespace (should normalize to lowercase)", + "test_group": "base", + "test_type": "validation", + "input": "pkg:composer/Laravel/Framework@10.0.0", + "expected_output": [ + { + "severity": "warning", + "message": "Namespace is not lowercased for purl type: 'composer'" + }, + { + "severity": "warning", + "message": "Name is not lowercased for purl type: 'composer'" + } + ] + }, + { + "description": "Composer package with uppercase namespace (should normalize to lowercase)", + "test_group": "advanced", + "test_type": "validation", + "input": "pkg:composer/Laravel/Framework@10.0.0", + "expected_output": [] + }, + { + "description": "Composer package missing namespace", + "test_group": "base", + "test_type": "validation", + "input": "pkg:composer/console@5.0.0", + "expected_output": [ + { + "severity": "error", + "message": "Namespace is required for purl type: 'composer'" + } + ] + }, + { + "description": "Composer package with qualifiers", + "test_group": "base", + "test_type": "validation", + "input": "pkg:composer/laravel/laravel@5.5.0?repository_url=https://packagist.org", + "expected_output": [] } ] } diff --git a/tests/types/conan-test.json b/tests/types/conan-test.json index b8dcbba2..42a8bc97 100644 --- a/tests/types/conan-test.json +++ b/tests/types/conan-test.json @@ -323,6 +323,46 @@ "expected_output": "pkg:conan/openssl.org/openssl@3.0.3?arch=x86_64&build_type=Debug&compiler=Visual%20Studio&compiler.runtime=MDd&compiler.version=16&os=Windows&prev=b429db8a0e324114c25ec387bfd8281f330d7c5c&rrev=93a82349c31917d2d674d22065c7a9ef9f380c8e&shared=True", "expected_failure": false, "expected_failure_reason": null + }, + { + "description": "Valid Conan package with name and version only", + "test_group": "base", + "test_type": "validation", + "input": "pkg:conan/openssl@3.0.3", + "expected_output": [] + }, + { + "description": "Valid Conan package with namespace (vendor) and qualifiers user+channel", + "test_group": "base", + "test_type": "validation", + "input": "pkg:conan/openssl.org/openssl@3.0.3?channel=stable&user=bincrafters", + "expected_output": [] + }, + { + "description": "Valid Conan package with namespace, complex qualifiers including rrev and prev", + "test_group": "base", + "test_type": "validation", + "input": "pkg:conan/openssl.org/openssl@3.0.3?arch=x86_64&build_type=Debug&compiler=Visual Studio&compiler.runtime=MDd&compiler.version=16&os=Windows&prev=b429db8a0e324114c25ec387bfd8281f330d7c5c&rrev=93a82349c31917d2d674d22065c7a9ef9f380c8e&shared=True", + "expected_output": [ + { + "severity": "info", + "message": "Invalid qualifiers found: arch, build_type, compiler, compiler.runtime, compiler.version, os, shared. Allowed qualifiers are: channel, prev, repository_url, rrev, user" + } + ] + }, + { + "description": "Valid Conan package with only namespace and no qualifiers", + "test_group": "base", + "test_type": "validation", + "input": "pkg:conan/openssl.org/openssl@3.0.3", + "expected_output": [] + }, + { + "description": "Conan package with unsupported qualifier key", + "test_group": "advanced", + "test_type": "validation", + "input": "pkg:conan/openssl@3.0.3?foo=bar", + "expected_output": [] } ] } diff --git a/tests/types/conda-test.json b/tests/types/conda-test.json index a148142e..6b2ef77f 100644 --- a/tests/types/conda-test.json +++ b/tests/types/conda-test.json @@ -111,6 +111,39 @@ "expected_output": "pkg:conda/absl-py@0.4.1?build=py36h06a4308_0&channel=main&subdir=linux-64&type=tar.bz2", "expected_failure": false, "expected_failure_reason": null + }, + { + "description": "Valid Conda package with name and version only", + "test_group": "base", + "test_type": "validation", + "input": "pkg:conda/absl-py@0.4.1", + "expected_output": [] + }, + { + "description": "Valid Conda package with full qualifiers (build, channel, subdir, type)", + "test_group": "base", + "test_type": "validation", + "input": "pkg:conda/absl-py@0.4.1?build=py36h06a4308_0&channel=main&subdir=linux-64&type=tar.bz2", + "expected_output": [] + }, + { + "description": "Conda package with namespace (not allowed)", + "test_group": "advanced", + "test_type": "validation", + "input": "pkg:conda/anaconda/absl-py@0.4.1", + "expected_output": [ + { + "severity": "error", + "message": "Namespace is prohibited for purl type: 'conda'" + } + ] + }, + { + "description": "Conda package with unsupported qualifier", + "test_group": "advanced", + "test_type": "validation", + "input": "pkg:conda/absl-py@0.4.1?foo=bar", + "expected_output": [] } ] } diff --git a/tests/types/cpan-test.json b/tests/types/cpan-test.json index fdbc00d8..d0817eb1 100644 --- a/tests/types/cpan-test.json +++ b/tests/types/cpan-test.json @@ -555,6 +555,84 @@ "expected_output": "pkg:cpan/URI", "expected_failure": false, "expected_failure_reason": null + }, + { + "description": "Valid CPAN module without namespace", + "test_group": "base", + "test_type": "validation", + "input": "pkg:cpan/Perl::Version@1.013", + "expected_output": [] + }, + { + "description": "Valid CPAN distribution with uppercase namespace (author ID)", + "test_group": "base", + "test_type": "validation", + "input": "pkg:cpan/DROLSKY/DateTime@1.55", + "expected_output": [] + }, + { + "description": "Valid CPAN distribution without version", + "test_group": "base", + "test_type": "validation", + "input": "pkg:cpan/GDT/URI-PackageURL", + "expected_output": [] + }, + { + "description": "Valid CPAN module with :: in name and no namespace", + "test_group": "base", + "test_type": "validation", + "input": "pkg:cpan/LWP::UserAgent", + "expected_output": [] + }, + { + "description": "CPAN distribution with lowercase namespace (must be uppercase)", + "test_group": "base", + "test_type": "validation", + "input": "pkg:cpan/oalders/libwww-perl@6.76", + "expected_output": [ + { + "severity": "warning", + "message": "Namespace must be uppercase for purl type: 'cpan'" + } + ] + }, + { + "description": "CPAN distribution with lowercase namespace (must be uppercase)", + "test_group": "advanced", + "test_type": "validation", + "input": "pkg:cpan/oalders/libwww-perl@6.76", + "expected_output": [] + }, + { + "description": "CPAN module with '-' in name (not allowed without namespace)", + "test_group": "base", + "test_type": "validation", + "input": "pkg:cpan/libwww-perl@6.76", + "expected_output": [ + { + "severity": "error", + "message": "Name must not contain '-' when Namespace is absent for purl type: 'cpan'" + } + ] + }, + { + "description": "CPAN distribution name containing '::' (not allowed with namespace)", + "test_group": "advanced", + "test_type": "validation", + "input": "pkg:cpan/TESTUSER/Bad::Dist@1.0", + "expected_output": [ + { + "severity": "error", + "message": "Name must not contain '::' when Namespace is present for purl type: 'cpan'" + } + ] + }, + { + "description": "Valid CPAN package with qualifiers (repository_url, download_url, vcs_url)", + "test_group": "advanced", + "test_type": "validation", + "input": "pkg:cpan/OALDERS/libwww-perl@6.76?download_url=https://cpan.metacpan.org/authors/id/O/OA/OALDERS/libwww-perl-6.76.tar.gz&ext=tar.gz&repository_url=https://cpan.metacpan.org&vcs_url=https://github.com/libwww-perl", + "expected_output": [] } ] } diff --git a/tests/types/cran-test.json b/tests/types/cran-test.json index d027639a..1624f53d 100644 --- a/tests/types/cran-test.json +++ b/tests/types/cran-test.json @@ -241,6 +241,39 @@ "expected_output": "pkg:cran/caret@6.0-88", "expected_failure": false, "expected_failure_reason": null + }, + { + "description": "Valid CRAN package with name and version", + "test_group": "base", + "test_type": "validation", + "input": "pkg:cran/A3@1.0.0", + "expected_output": [] + }, + { + "description": "Valid CRAN package with hyphen in version", + "test_group": "base", + "test_type": "validation", + "input": "pkg:cran/rJava@1.0-4", + "expected_output": [] + }, + { + "description": "Valid CRAN package with complex version", + "test_group": "base", + "test_type": "validation", + "input": "pkg:cran/caret@6.0-88", + "expected_output": [] + }, + { + "description": "CRAN package with namespace (not allowed)", + "test_group": "base", + "test_type": "validation", + "input": "pkg:cran/ml/caret@6.0-88", + "expected_output": [ + { + "severity": "error", + "message": "Namespace is prohibited for purl type: 'cran'" + } + ] } ] } diff --git a/tests/types/deb-test.json b/tests/types/deb-test.json index 55b5fb90..7c4d28fa 100644 --- a/tests/types/deb-test.json +++ b/tests/types/deb-test.json @@ -285,6 +285,51 @@ "expected_output": "pkg:deb/debian/attr@1:2.4.47-2%2Bb1?arch=amd64", "expected_failure": false, "expected_failure_reason": null + }, + { + "description": "Valid deb package with vendor, name, version, and arch", + "test_group": "base", + "test_type": "validation", + "input": "pkg:deb/debian/curl@7.50.3-1?arch=i386&distro=jessie", + "expected_output": [ + { + "severity": "info", + "message": "Invalid qualifiers found: distro. Allowed qualifiers are: arch, repository_url" + } + ] + }, + { + "description": "Valid deb package with vendor, name, version, without distro", + "test_group": "base", + "test_type": "validation", + "input": "pkg:deb/ubuntu/dpkg@1.19.0.4?arch=amd64", + "expected_output": [] + }, + { + "description": "Valid deb source package", + "test_group": "base", + "test_type": "validation", + "input": "pkg:deb/debian/attr@1:2.4.47-2?arch=source", + "expected_output": [] + }, + { + "description": "Deb package missing vendor", + "test_group": "advanced", + "test_type": "validation", + "input": "pkg:deb/curl@7.50.3-1?arch=amd64", + "expected_output": [ + { + "severity": "error", + "message": "Namespace is required for purl type: 'deb'" + } + ] + }, + { + "description": "deb package with unsupported qualifier", + "test_group": "advanced", + "test_type": "validation", + "input": "pkg:deb/debian/curl@7.50.3-1?foo=bar", + "expected_output": [] } ] } diff --git a/tests/types/docker-test.json b/tests/types/docker-test.json index 0ecb38df..770cf958 100644 --- a/tests/types/docker-test.json +++ b/tests/types/docker-test.json @@ -181,6 +181,46 @@ "expected_output": "pkg:docker/customer/dockerimage@sha256:244fd47e07d10?repository_url=gcr.io", "expected_failure": false, "expected_failure_reason": null + }, + { + "description": "Valid Docker image with tag only", + "test_group": "base", + "test_type": "validation", + "input": "pkg:docker/cassandra@latest", + "expected_output": [] + }, + { + "description": "Valid Docker image with namespace and sha256 digest", + "test_group": "base", + "test_type": "validation", + "input": "pkg:docker/smartentry/debian@dc437cc87d10", + "expected_output": [] + }, + { + "description": "Valid Docker image with repository_url qualifier", + "test_group": "advanced", + "test_type": "validation", + "input": "pkg:docker/customer/dockerimage@sha256:244fd47e07d10?repository_url=gcr.io", + "expected_output": [] + }, + { + "description": "Docker image with unsupported qualifier", + "test_group": "advanced", + "test_type": "validation", + "input": "pkg:docker/ubuntu@20.04?bad=value", + "expected_output": [] + }, + { + "description": "Docker image with unsupported qualifier", + "test_group": "base", + "test_type": "validation", + "input": "pkg:docker/ubuntu@20.04?bad=value", + "expected_output": [ + { + "severity": "info", + "message": "Invalid qualifiers found: bad. Allowed qualifiers are: repository_url" + } + ] } ] } diff --git a/tests/types/gem-test.json b/tests/types/gem-test.json index 0f2df1bd..0eaeb405 100644 --- a/tests/types/gem-test.json +++ b/tests/types/gem-test.json @@ -140,6 +140,46 @@ "expected_output": "pkg:gem/jruby-launcher@1.1.2?platform=java", "expected_failure": false, "expected_failure_reason": null + }, + { + "description": "Valid RubyGem with default platform", + "test_group": "base", + "test_type": "validation", + "input": "pkg:gem/ruby-advisory-db-check@0.12.4", + "expected_output": [] + }, + { + "description": "Valid RubyGem with java platform", + "test_group": "base", + "test_type": "validation", + "input": "pkg:gem/jruby-launcher@1.1.2?platform=java", + "expected_output": [] + }, + { + "description": "Subpath included", + "test_group": "base", + "test_type": "validation", + "input": "pkg:gem/nokogiri@1.14.3#lib/nokogiri.rb", + "expected_output": [] + }, + { + "description": "Extra unknown qualifier", + "test_group": "base", + "test_type": "validation", + "input": "pkg:gem/sinatra@3.1.2?unknown=value", + "expected_output": [ + { + "severity": "info", + "message": "Invalid qualifiers found: unknown. Allowed qualifiers are: platform, repository_url" + } + ] + }, + { + "description": "Extra unknown qualifier", + "test_group": "advanced", + "test_type": "validation", + "input": "pkg:gem/sinatra@3.1.2?unknown=value", + "expected_output": [] } ] } diff --git a/tests/types/generic-test.json b/tests/types/generic-test.json index cefb0062..ec9f3adc 100644 --- a/tests/types/generic-test.json +++ b/tests/types/generic-test.json @@ -133,6 +133,53 @@ "expected_output": "pkg:generic/bitwarderl?vcs_url=git%2Bhttps://git.fsfe.org/dxtr/bitwarderl%40cc55108da32", "expected_failure": false, "expected_failure_reason": null + }, + { + "description": "Valid generic package with version", + "test_group": "base", + "test_type": "validation", + "input": "pkg:generic/openssl@1.1.10g", + "expected_output": [] + }, + { + "description": "Valid generic package with download_url and checksum", + "test_group": "base", + "test_type": "validation", + "input": "pkg:generic/openssl@1.1.10g?checksum=sha256:de4d501267da&download_url=https://openssl.org/source/openssl-1.1.0g.tar.gz", + "expected_output": [] + }, + { + "description": "generic package with vcs_url", + "test_group": "base", + "test_type": "validation", + "input": "pkg:generic/bitwarderl?vcs_url=git+https://git.fsfe.org/dxtr/bitwarderl@cc55108da32", + "expected_output": [ + { + "severity": "info", + "message": "Invalid qualifiers found: vcs_url. Allowed qualifiers are: checksum, download_url" + } + ] + }, + { + "description": "Extra unknown qualifier", + "test_group": "advanced", + "test_type": "validation", + "input": "pkg:generic/mypkg@3.0.0?foo=bar", + "expected_output": [] + }, + { + "description": "Subpath included", + "test_group": "base", + "test_type": "validation", + "input": "pkg:generic/libexample@0.5.2#src/libexample.c", + "expected_output": [] + }, + { + "description": "Missing version and no qualifiers", + "test_group": "advanced", + "test_type": "validation", + "input": "pkg:generic/noversionpkg", + "expected_output": [] } ] } diff --git a/tests/types/github-test.json b/tests/types/github-test.json index fa2c8811..68fa2982 100644 --- a/tests/types/github-test.json +++ b/tests/types/github-test.json @@ -132,6 +132,32 @@ "expected_output": "pkg:github/package-url/purl-spec@244fd47e07d1004#everybody/loves/dogs", "expected_failure": false, "expected_failure_reason": null + }, + { + "description": "Valid GitHub package with namespace, name, and version", + "test_group": "base", + "test_type": "validation", + "input": "pkg:github/package-url/purl-spec@244fd47e07d1004", + "expected_output": [] + }, + { + "description": "Valid GitHub package with subpath", + "test_group": "base", + "test_type": "validation", + "input": "pkg:github/package-url/purl-spec@244fd47e07d1004#everybody/loves/dogs", + "expected_output": [] + }, + { + "description": "GitHub package missing namespace", + "test_group": "advanced", + "test_type": "validation", + "input": "pkg:github/purl-spec@244fd47e07d1004", + "expected_output": [ + { + "severity": "error", + "message": "Namespace is required for purl type: 'github'" + } + ] } ] } diff --git a/tests/types/golang-test.json b/tests/types/golang-test.json index 11da72b4..69fb2efe 100644 --- a/tests/types/golang-test.json +++ b/tests/types/golang-test.json @@ -223,6 +223,51 @@ "expected_output": "pkg:golang/github.com/gorilla/context@234fd47e07d1004f0aed9c#api", "expected_failure": false, "expected_failure_reason": null + }, + { + "description": "Valid golang package with namespace, name, and version", + "test_group": "base", + "test_type": "validation", + "input": "pkg:golang/github.com/gorilla/context@234fd47e07d1004f0aed9c", + "expected_output": [] + }, + { + "description": "Valid golang package with namespace and name only (no version)", + "test_group": "base", + "test_type": "validation", + "input": "pkg:golang/golang.org/x/crypto", + "expected_output": [] + }, + { + "description": "Valid golang package with subpath", + "test_group": "advanced", + "test_type": "validation", + "input": "pkg:golang/google.golang.org/genproto#googleapis/api/annotations", + "expected_output": [] + }, + { + "description": "Golang package with uppercase namespace", + "test_group": "base", + "test_type": "validation", + "input": "pkg:golang/GitHub.com/Gorilla/context@234fd47e07d1004f0aed9c", + "expected_output": [ + { + "severity": "warning", + "message": "Namespace is not lowercased for purl type: 'golang'" + } + ] + }, + { + "description": "Golang package with missing namespace", + "test_group": "base", + "test_type": "validation", + "input": "pkg:golang/context@234fd47e07d1004f0aed9c", + "expected_output": [ + { + "severity": "error", + "message": "Namespace is required for purl type: 'golang'" + } + ] } ] } diff --git a/tests/types/hackage-test.json b/tests/types/hackage-test.json index d8d88cfe..1b1ae555 100644 --- a/tests/types/hackage-test.json +++ b/tests/types/hackage-test.json @@ -207,6 +207,58 @@ "expected_output": "pkg:hackage/3d-graphics-examples@0.0.0.2", "expected_failure": false, "expected_failure_reason": null + }, + { + "description": "Valid Hackage package with simple kebab-case name", + "test_group": "base", + "test_type": "validation", + "input": "pkg:hackage/lens@5.0.1", + "expected_output": [] + }, + { + "description": "Valid Hackage package with uppercase letters", + "test_group": "base", + "test_type": "validation", + "input": "pkg:hackage/AC-HalfInteger@1.2.1", + "expected_output": [] + }, + { + "description": "Valid Hackage package with numbers and dots in version", + "test_group": "base", + "test_type": "validation", + "input": "pkg:hackage/3d-graphics-examples@0.0.0.2", + "expected_output": [] + }, + { + "description": "Hackage package with namespace included", + "test_group": "base", + "test_type": "validation", + "input": "pkg:hackage/haskell/text@1.2.4", + "expected_output": [ + { + "severity": "error", + "message": "Namespace is prohibited for purl type: 'hackage'" + } + ] + }, + { + "description": "Hackage package with name not in kebab-case", + "test_group": "base", + "test_type": "validation", + "input": "pkg:hackage/My_Package@0.1", + "expected_output": [ + { + "severity": "warning", + "message": "Name cannot contain underscores for purl type:'hackage'" + } + ] + }, + { + "description": "Hackage package with name not in kebab-case", + "test_group": "advanced", + "test_type": "validation", + "input": "pkg:hackage/My_Package@0.1", + "expected_output": [] } ] } diff --git a/tests/types/hex-test.json b/tests/types/hex-test.json index 5d58d636..30cc5e11 100644 --- a/tests/types/hex-test.json +++ b/tests/types/hex-test.json @@ -168,6 +168,72 @@ "expected_output": "pkg:hex/bar@1.2.3?repository_url=https://myrepo.example.com", "expected_failure": false, "expected_failure_reason": null + }, + { + "description": "Valid Hex package with lowercase name", + "test_group": "base", + "test_type": "validation", + "input": "pkg:hex/jason@1.1.2", + "expected_output": [] + }, + { + "description": "Valid Hex package with optional namespace", + "test_group": "base", + "test_type": "validation", + "input": "pkg:hex/acme/foo@2.3.0", + "expected_output": [] + }, + { + "description": "Valid Hex package with subpath", + "test_group": "base", + "test_type": "validation", + "input": "pkg:hex/phoenix_html@2.13.3#priv/static/phoenix_html.js", + "expected_output": [] + }, + { + "description": "Valid Hex package with repository_url qualifier", + "test_group": "base", + "test_type": "validation", + "input": "pkg:hex/bar@1.2.3?repository_url=https://myrepo.example.com", + "expected_output": [] + }, + { + "description": "Hex package with uppercase name", + "test_group": "base", + "test_type": "validation", + "input": "pkg:hex/Phoenix_HTML@1.0.0", + "expected_output": [ + { + "severity": "warning", + "message": "Name is not lowercased for purl type: 'hex'" + } + ] + }, + { + "description": "Hex package with uppercase name", + "test_group": "advanced", + "test_type": "validation", + "input": "pkg:hex/Phoenix_HTML@1.0.0", + "expected_output": [] + }, + { + "description": "Hex package with uppercase namespace", + "test_group": "base", + "test_type": "validation", + "input": "pkg:hex/ACME/foo@1.0.0", + "expected_output": [ + { + "severity": "warning", + "message": "Namespace is not lowercased for purl type: 'hex'" + } + ] + }, + { + "description": "Hex package with uppercase namespace", + "test_group": "advanced", + "test_type": "validation", + "input": "pkg:hex/ACME/foo@1.0.0", + "expected_output": [] } ] } diff --git a/tests/types/huggingface-test.json b/tests/types/huggingface-test.json index 4849193a..b15eba31 100644 --- a/tests/types/huggingface-test.json +++ b/tests/types/huggingface-test.json @@ -240,6 +240,39 @@ "expected_output": "pkg:huggingface/microsoft/deberta-v3-base@559062ad13d311b87b2c455e67dcd5f1c8f65111?repository_url=https://hub-ci.huggingface.co", "expected_failure": false, "expected_failure_reason": null + }, + { + "description": "Valid minimal Hugging Face model", + "test_group": "base", + "test_type": "validation", + "input": "pkg:huggingface/distilbert-base-uncased@043235d6088ecd3dd5fb5ca3592b6913fd516027", + "expected_output": [ + { + "severity": "error", + "message": "Namespace is required for purl type: 'huggingface'" + } + ] + }, + { + "description": "Valid Hugging Face model with namespace", + "test_group": "base", + "test_type": "validation", + "input": "pkg:huggingface/microsoft/deberta-v3-base@559062ad13d311b87b2c455e67dcd5f1c8f65111", + "expected_output": [] + }, + { + "description": "Valid Hugging Face model with subpath", + "test_group": "base", + "test_type": "validation", + "input": "pkg:huggingface/EleutherAI/gpt-neo-1.3B@797174552ae47f449ab70b684cabcb6603e5e85e#tokenizer/config.json", + "expected_output": [] + }, + { + "description": "Valid Hugging Face model with repository_url qualifier", + "test_group": "base", + "test_type": "validation", + "input": "pkg:huggingface/EleutherAI/gpt-neo-1.3B@797174552ae47f449ab70b684cabcb6603e5e85e?repository_url=https://hub-ci.huggingface.co", + "expected_output": [] } ] } diff --git a/tests/types/luarocks-test.json b/tests/types/luarocks-test.json index a822563f..213ff95b 100644 --- a/tests/types/luarocks-test.json +++ b/tests/types/luarocks-test.json @@ -127,6 +127,46 @@ "expected_output": "pkg:luarocks/username/packagename@0.1.0-1?repository_url=https://example.com/private_rocks_server/", "expected_failure": false, "expected_failure_reason": null + }, + { + "description": "Valid LuaRocks package with only name and version", + "test_group": "base", + "test_type": "validation", + "input": "pkg:luarocks/luasocket@3.1.0-1", + "expected_output": [] + }, + { + "description": "Valid LuaRocks package with namespace and version", + "test_group": "base", + "test_type": "validation", + "input": "pkg:luarocks/hisham/luafilesystem@1.8.0-1", + "expected_output": [] + }, + { + "description": "Valid LuaRocks package with private repository_url qualifier", + "test_group": "base", + "test_type": "validation", + "input": "pkg:luarocks/username/packagename@0.1.0-1?repository_url=https://example.com/private_rocks_server/", + "expected_output": [] + }, + { + "description": "Unsupported qualifier is provided", + "test_group": "base", + "test_type": "validation", + "input": "pkg:luarocks/username/packagename@0.1.0-1?channel=beta", + "expected_output": [ + { + "severity": "info", + "message": "Invalid qualifiers found: channel. Allowed qualifiers are: repository_url" + } + ] + }, + { + "description": "Advanced validation for name with uppercase letters", + "test_group": "advanced", + "test_type": "validation", + "input": "pkg:luarocks/LuaSocket@3.1.0-1?private_url=https://example.com/private_rocks_server/", + "expected_output": [] } ] } diff --git a/tests/types/maven-test.json b/tests/types/maven-test.json index 3fea512f..f688d812 100644 --- a/tests/types/maven-test.json +++ b/tests/types/maven-test.json @@ -898,6 +898,53 @@ "expected_output": "pkg:maven/groovy/groovy@1.0?repository_url=https://maven.google.com", "expected_failure": false, "expected_failure_reason": null + }, + { + "description": "Valid Maven package with groupId, artifactId, and version", + "test_group": "base", + "test_type": "validation", + "input": "pkg:maven/org.apache.xmlgraphics/batik-anim@1.9.1", + "expected_output": [] + }, + { + "description": "Valid Maven package with type qualifier (pom)", + "test_group": "base", + "test_type": "validation", + "input": "pkg:maven/org.apache.xmlgraphics/batik-anim@1.9.1?type=pom", + "expected_output": [] + }, + { + "description": "Valid Maven package with classifier qualifier (sources)", + "test_group": "base", + "test_type": "validation", + "input": "pkg:maven/org.apache.xmlgraphics/batik-anim@1.9.1?classifier=sources", + "expected_output": [] + }, + { + "description": "Valid Maven package with both type and classifier qualifiers", + "test_group": "base", + "test_type": "validation", + "input": "pkg:maven/org.apache.xmlgraphics/batik-anim@1.9.1?classifier=dist&type=zip", + "expected_output": [] + }, + { + "description": "Valid Maven package with repository_url qualifier", + "test_group": "base", + "test_type": "validation", + "input": "pkg:maven/groovy/groovy@1.0?repository_url=https://maven.google.com", + "expected_output": [] + }, + { + "description": "Maven package missing namespace (groupId required)", + "test_group": "advanced", + "test_type": "validation", + "input": "pkg:maven/batik-anim@1.9.1", + "expected_output": [ + { + "severity": "error", + "message": "Namespace is required for purl type: 'maven'" + } + ] } ] } diff --git a/tests/types/mlflow-test.json b/tests/types/mlflow-test.json index 9b1ed365..fdb96045 100644 --- a/tests/types/mlflow-test.json +++ b/tests/types/mlflow-test.json @@ -260,6 +260,58 @@ "expected_output": "pkg:mlflow/trafficsigns@10?model_uuid=36233173b22f4c89b451f1228d700d49&repository_url=https://adb-5245952564735461.0.azuredatabricks.net/api/2.0/mlflow&run_id=410a3121-2709-4f88-98dd-dba0ef056b0a", "expected_failure": false, "expected_failure_reason": null + }, + { + "description": "Valid MLflow package with name and version only", + "test_group": "base", + "test_type": "validation", + "input": "pkg:mlflow/creditfraud@3", + "expected_output": [] + }, + { + "description": "Valid MLflow package with repository_url qualifier", + "test_group": "base", + "test_type": "validation", + "input": "pkg:mlflow/creditfraud@3?repository_url=https://westus2.api.azureml.ms/mlflow/v1.0/subscriptions/a50f2011-fab8-4164-af23-c62881ef8c95/resourceGroups/TestResourceGroup/providers/Microsoft.MachineLearningServices/workspaces/TestWorkspace", + "expected_output": [] + }, + { + "description": "Valid MLflow package with model_uuid and run_id qualifiers", + "test_group": "base", + "test_type": "validation", + "input": "pkg:mlflow/trafficsigns@10?model_uuid=36233173b22f4c89b451f1228d700d49&repository_url=https://adb-5245952564735461.0.azuredatabricks.net/api/2.0/mlflow&run_id=410a3121-2709-4f88-98dd-dba0ef056b0a", + "expected_output": [] + }, + { + "description": "MLflow package with namespace (not allowed)", + "test_group": "advanced", + "test_type": "validation", + "input": "pkg:mlflow/azure/creditfraud@3", + "expected_output": [ + { + "severity": "error", + "message": "Namespace is prohibited for purl type: 'mlflow'" + } + ] + }, + { + "description": "MLflow package with unsupported qualifier", + "test_group": "advanced", + "test_type": "validation", + "input": "pkg:mlflow/creditfraud@3?foo=bar", + "expected_output": [] + }, + { + "description": "MLflow package with unsupported qualifier", + "test_group": "base", + "test_type": "validation", + "input": "pkg:mlflow/creditfraud@3?foo=bar", + "expected_output": [ + { + "severity": "info", + "message": "Invalid qualifiers found: foo. Allowed qualifiers are: model_uuid, repository_url, run_id" + } + ] } ] } diff --git a/tests/types/npm-test.json b/tests/types/npm-test.json index 7167f42d..4c768d10 100644 --- a/tests/types/npm-test.json +++ b/tests/types/npm-test.json @@ -254,6 +254,46 @@ "expected_output": "pkg:npm/core@2.0.1#googleapis/api/annotations", "expected_failure": false, "expected_failure_reason": null + }, + { + "description": "Valid npm package without scope", + "test_group": "base", + "test_type": "validation", + "input": "pkg:npm/foobar@12.3.1", + "expected_output": [] + }, + { + "description": "Valid npm package with scope", + "test_group": "base", + "test_type": "validation", + "input": "pkg:npm/%40angular/animation@12.3.1", + "expected_output": [] + }, + { + "description": "Valid npm package with qualifier vcs_url", + "test_group": "advanced", + "test_type": "validation", + "input": "pkg:npm/mypackage@12.4.5?vcs_url=git://host.com/path/to/repo.git%404345abcd34343", + "expected_output": [] + }, + { + "description": "npm package with uppercase name", + "test_group": "base", + "test_type": "validation", + "input": "pkg:npm/MyPackage@1.0.0", + "expected_output": [ + { + "severity": "warning", + "message": "Name is not lowercased for purl type: 'npm'" + } + ] + }, + { + "description": "npm package with uppercase name", + "test_group": "advanced", + "test_type": "validation", + "input": "pkg:npm/MyPackage@1.0.0", + "expected_output": [] } ] } diff --git a/tests/types/nuget-test.json b/tests/types/nuget-test.json index 67d97916..e8bf6d09 100644 --- a/tests/types/nuget-test.json +++ b/tests/types/nuget-test.json @@ -91,6 +91,53 @@ "expected_output": "pkg:nuget/EnterpriseLibrary.Common@6.0.1304", "expected_failure": false, "expected_failure_reason": null + }, + { + "description": "Valid NuGet package with name and version", + "test_group": "base", + "test_type": "validation", + "input": "pkg:nuget/EnterpriseLibrary.Common@6.0.1304", + "expected_output": [] + }, + { + "description": "Valid NuGet package with lowercase name", + "test_group": "base", + "test_type": "validation", + "input": "pkg:nuget/newtonsoft.json@13.0.3", + "expected_output": [] + }, + { + "description": "NuGet package without version", + "test_group": "base", + "test_type": "validation", + "input": "pkg:nuget/NUnit", + "expected_output": [] + }, + { + "description": "NuGet package with namespace (should be prohibited)", + "test_group": "base", + "test_type": "validation", + "input": "pkg:nuget/microsoft/aspnetcore.mvc@2.2.0", + "expected_output": [ + { + "severity": "error", + "message": "Namespace is prohibited for purl type: 'nuget'" + } + ] + }, + { + "description": "NuGet package with pre-release version", + "test_group": "base", + "test_type": "validation", + "input": "pkg:nuget/EntityFramework@7.0.0-preview.2", + "expected_output": [] + }, + { + "description": "NuGet package with 4-part version", + "test_group": "base", + "test_type": "validation", + "input": "pkg:nuget/System.Data.SqlClient@4.8.5.1234", + "expected_output": [] } ] } diff --git a/tests/types/oci-test.json b/tests/types/oci-test.json index 2072ed20..ce18883d 100644 --- a/tests/types/oci-test.json +++ b/tests/types/oci-test.json @@ -188,6 +188,65 @@ "expected_output": "pkg:oci/hello-wasm@sha256:244fd47e07d10?tag=v1", "expected_failure": false, "expected_failure_reason": null + }, + { + "description": "Valid OCI package with repository_url, arch, and tag", + "test_group": "base", + "test_type": "validation", + "input": "pkg:oci/debian@sha256:244fd47e07d10?arch=amd64&repository_url=docker.io/library/debian&tag=latest", + "expected_output": [] + }, + { + "description": "Valid OCI package with repository_url and tag only", + "test_group": "base", + "test_type": "validation", + "input": "pkg:oci/debian@sha256:244fd47e07d10?repository_url=ghcr.io/debian&tag=bullseye", + "expected_output": [] + }, + { + "description": "Valid OCI package without repository_url (allowed, registry agnostic)", + "test_group": "advanced", + "test_type": "validation", + "input": "pkg:oci/hello-wasm@sha256:244fd47e07d10?tag=v1", + "expected_output": [] + }, + { + "description": "OCI package with namespace provided (prohibited)", + "test_group": "base", + "test_type": "validation", + "input": "pkg:oci/library/debian@sha256:244fd47e07d10?repository_url=docker.io/library/debian", + "expected_output": [ + { + "severity": "error", + "message": "Namespace is prohibited for purl type: 'oci'" + } + ] + }, + { + "description": "OCI package with missing version (required digest)", + "test_group": "base", + "test_type": "validation", + "input": "pkg:oci/debian?repository_url=docker.io/library/debian&tag=latest", + "expected_output": [] + }, + { + "description": "OCI package with uppercase name", + "test_group": "base", + "test_type": "validation", + "input": "pkg:oci/Debian@sha256:244fd47e07d10?repository_url=docker.io/library/debian", + "expected_output": [ + { + "severity": "warning", + "message": "Name is not lowercased for purl type: 'oci'" + } + ] + }, + { + "description": "OCI package with uppercase name", + "test_group": "advanced", + "test_type": "validation", + "input": "pkg:oci/Debian@sha256:244fd47e07d10?repository_url=docker.io/library/debian", + "expected_output": [] } ] } diff --git a/tests/types/pub-test.json b/tests/types/pub-test.json index ef8daf24..428aebc1 100644 --- a/tests/types/pub-test.json +++ b/tests/types/pub-test.json @@ -82,6 +82,51 @@ "expected_output": "pkg:pub/flutter@0.0.0", "expected_failure": false, "expected_failure_reason": null + }, + { + "description": "Valid pub package with version", + "test_group": "base", + "test_type": "validation", + "input": "pkg:pub/characters@1.2.0", + "expected_output": [] + }, + { + "description": "Valid pub package without version", + "test_group": "base", + "test_type": "validation", + "input": "pkg:pub/flutter", + "expected_output": [] + }, + { + "description": "Pub package with uppercase letters", + "test_group": "base", + "test_type": "validation", + "input": "pkg:pub/Flutter@1.0.0", + "expected_output": [ + { + "severity": "warning", + "message": "Name is not lowercased for purl type: 'pub'" + } + ] + }, + { + "description": "Pub package with hyphen", + "test_group": "base", + "test_type": "validation", + "input": "pkg:pub/http-client@0.13.6", + "expected_output": [ + { + "severity": "warning", + "message": "Name contains invalid characters but should only contain letters, digits, or underscores for purl type: 'pub'" + } + ] + }, + { + "description": "Pub package with qualifiers", + "test_group": "base", + "test_type": "validation", + "input": "pkg:pub/characters@1.2.0?repository_url=https://pub.dev", + "expected_output": [] } ] } diff --git a/tests/types/pypi-test.json b/tests/types/pypi-test.json index 23eb979d..aaa4a63b 100644 --- a/tests/types/pypi-test.json +++ b/tests/types/pypi-test.json @@ -222,6 +222,53 @@ "expected_output": "pkg:pypi/django-allauth@12.23", "expected_failure": false, "expected_failure_reason": null + }, + { + "description": "Valid PyPI package with version", + "test_group": "base", + "test_type": "validation", + "input": "pkg:pypi/django@1.11.1", + "expected_output": [] + }, + { + "description": "Valid PyPI package with file_name qualifier", + "test_group": "base", + "test_type": "validation", + "input": "pkg:pypi/django@1.11.1?file_name=Django-1.11.1.tar.gz", + "expected_output": [] + }, + { + "description": "Valid PyPI package with wheel file_name", + "test_group": "base", + "test_type": "validation", + "input": "pkg:pypi/django@1.11.1?file_name=Django-1.11.1-py2.py3-none-any.whl", + "expected_output": [] + }, + { + "description": "PyPI package with name containing underscores and dots", + "test_group": "base", + "test_type": "validation", + "input": "pkg:pypi/django_allauth@12.23", + "expected_output": [ + { + "severity": "warning", + "message": "Name cannot contain underscores for purl type:'pypi'" + } + ] + }, + { + "description": "PyPI package with name containing underscores and dots", + "test_group": "advanced", + "test_type": "validation", + "input": "pkg:pypi/django_allauth@12.23", + "expected_output": [] + }, + { + "description": "Name with uppercase letters", + "test_group": "advanced", + "test_type": "validation", + "input": "pkg:pypi/Django-AllAuth@12.23", + "expected_output": [] } ] } diff --git a/tests/types/qpkg-test.json b/tests/types/qpkg-test.json index 9450bf3d..aac8d3d8 100644 --- a/tests/types/qpkg-test.json +++ b/tests/types/qpkg-test.json @@ -82,6 +82,46 @@ "expected_output": "pkg:qpkg/blackberry/com.qnx.qnx710.foo.bar.qux@0.0.4.01449T202205040833L", "expected_failure": false, "expected_failure_reason": null + }, + { + "description": "Valid QPKG with vendor and version", + "test_group": "base", + "test_type": "validation", + "input": "pkg:qpkg/blackberry/com.qnx.sdp@7.0.0.SGA201702151847", + "expected_output": [] + }, + { + "description": "Valid QPKG with complex name and version", + "test_group": "base", + "test_type": "validation", + "input": "pkg:qpkg/blackberry/com.qnx.qnx710.foo.bar.qux@0.0.4.01449T202205040833L", + "expected_output": [] + }, + { + "description": "Valid QPKG with repository_url qualifier", + "test_group": "advanced", + "test_type": "validation", + "input": "pkg:qpkg/blackberry/com.qnx.sdp@7.0.0?repository_url=https://example.com/qpkg", + "expected_output": [] + }, + { + "description": "QPKG missing vendor (namespace)", + "test_group": "base", + "test_type": "validation", + "input": "pkg:qpkg/com.qnx.sdp@7.0.0", + "expected_output": [ + { + "severity": "error", + "message": "Namespace is required for purl type: 'qpkg'" + } + ] + }, + { + "description": "Namespace should be lowercased", + "test_group": "advanced", + "test_type": "validation", + "input": "pkg:qpkg/BlackBerry/com.qnx.sdp@7.0.0", + "expected_output": [] } ] } diff --git a/tests/types/rpm-test.json b/tests/types/rpm-test.json index d940a7d8..79631ce3 100644 --- a/tests/types/rpm-test.json +++ b/tests/types/rpm-test.json @@ -152,6 +152,50 @@ "expected_output": "pkg:rpm/centerim@4.22.10-1.el6?arch=i686&distro=fedora-25&epoch=1", "expected_failure": false, "expected_failure_reason": null + }, + { + "description": "Valid RPM with vendor, name, version and arch", + "test_group": "base", + "test_type": "validation", + "input": "pkg:rpm/fedora/curl@7.50.3-1.fc25?arch=i386", + "expected_output": [] + }, + { + "description": "Valid RPM with epoch qualifier", + "test_group": "advanced", + "test_type": "validation", + "input": "pkg:rpm/fedora/centerim@4.22.10-1.el6?arch=i686&distro=fedora-25&epoch=1", + "expected_output": [] + }, + { + "description": "RPM missing vendor (namespace)", + "test_group": "base", + "test_type": "validation", + "input": "pkg:rpm/curl@7.50.3-1.fc25?arch=i386&distro=fedora-25", + "expected_output": [ + { + "severity": "error", + "message": "Namespace is required for purl type: 'rpm'" + }, + { + "severity": "info", + "message": "Invalid qualifiers found: distro. Allowed qualifiers are: arch, epoch, repository_url" + } + ] + }, + { + "description": "Valid RPM without version", + "test_group": "advanced", + "test_type": "validation", + "input": "pkg:rpm/opensuse/zsh?arch=x86_64&distro=opensuse-15.3", + "expected_output": [] + }, + { + "description": "Valid RPM with repository_url instead of distro", + "test_group": "advanced", + "test_type": "validation", + "input": "pkg:rpm/centos/vim@8.0-1.el7?arch=x86_64&repository_url=https://mirror.centos.org/centos/7/os/x86_64", + "expected_output": [] } ] } diff --git a/tests/types/swid-test.json b/tests/types/swid-test.json index 1312a6a3..d42dfd83 100644 --- a/tests/types/swid-test.json +++ b/tests/types/swid-test.json @@ -135,6 +135,48 @@ "expected_output": "pkg:swid/Adobe%2BSystems%2BIncorporated/Adobe%2BInDesign@CC?tag_id=CreativeCloud-CS6-Win-GM-MUL", "expected_failure": false, "expected_failure_reason": null + }, + { + "description": "Valid SWID with namespace, name, version and tag_id", + "test_group": "base", + "test_type": "validation", + "input": "pkg:swid/Acme/example.com/Enterprise+Server@1.0.0?tag_id=75b8c285-fa7b-485b-b199-4745e3004d0d", + "expected_output": [] + }, + { + "description": "Valid SWID with only name and tag_id (no namespace)", + "test_group": "base", + "test_type": "validation", + "input": "pkg:swid/Fedora@29?tag_id=org.fedoraproject.Fedora-29", + "expected_output": [] + }, + { + "description": "Valid SWID with tag_creator_name and tag_creator_regid qualifiers", + "test_group": "advanced", + "test_type": "validation", + "input": "pkg:swid/Adobe Systems Incorporated/Adobe InDesign@CC?tag_creator_name=AdobeCorp&tag_creator_regid=com.adobe&tag_id=CreativeCloud-CS6-Win-GM-MUL", + "expected_output": [] + }, + { + "description": "SWID missing required tag_id qualifier", + "test_group": "base", + "test_type": "validation", + "input": "pkg:swid/Acme/example.com/Enterprise+Server@1.0.0", + "expected_output": [] + }, + { + "description": "SWID with empty tag_id", + "test_group": "advanced", + "test_type": "validation", + "input": "pkg:swid/Acme/example.com/Enterprise+Server@1.0.0?tag_id=", + "expected_output": [] + }, + { + "description": "Valid SWID with optional patch and tag_version", + "test_group": "advanced", + "test_type": "validation", + "input": "pkg:swid/Acme/example.com/Enterprise+Server@1.0.0?patch=true&tag_id=75b8c285-fa7b-485b-b199-4745e3004d0d&tag_version=3", + "expected_output": [] } ] } diff --git a/tests/types/swift-test.json b/tests/types/swift-test.json index ef3d1fb1..c120cdc6 100644 --- a/tests/types/swift-test.json +++ b/tests/types/swift-test.json @@ -234,6 +234,39 @@ "expected_output": "pkg:swift/github.com/RxSwiftCommunity/RxFlow@2.12.4", "expected_failure": false, "expected_failure_reason": null + }, + { + "description": "Valid Swift package with namespace, name, and version", + "test_group": "base", + "test_type": "validation", + "input": "pkg:swift/github.com/Alamofire/Alamofire@5.4.3", + "expected_output": [] + }, + { + "description": "namespace is missing", + "test_group": "base", + "test_type": "validation", + "input": "pkg:swift/Alamofire@5.4.3", + "expected_output": [ + { + "severity": "error", + "message": "Namespace is required for purl type: 'swift'" + } + ] + }, + { + "description": "unsupported qualifier is provided", + "test_group": "base", + "test_type": "validation", + "input": "pkg:swift/github.com/Alamofire/Alamofire@5.4.3?repository_url=https://swiftpm.example.com/", + "expected_output": [] + }, + { + "description": "Valid Swift package with case-sensitive namespace and name", + "test_group": "advanced", + "test_type": "validation", + "input": "pkg:swift/GitHub.com/SomeOrg/MyLibrary@1.0.0", + "expected_output": [] } ] }