packageurl-go icon indicating copy to clipboard operation
packageurl-go copied to clipboard

update code to honor the canonical purl encoding

Open petergardfjall opened this issue 4 months ago • 17 comments

This PR is an attempt to make the code honor the spec rules on producing a canonical purl when a PackageURL is turned into its string representation (ToString() and String()).


The old test suite (test-suite-data.json) is no longer present upstream. For now I updated the Makefile to run against the last commit where test-suite-data.json was still present in the repo (it was removed in 8a699a).

This should be removed as soon as we can migrate to the new test suite (see separate PR).

It fails on the following tests:

  • Two tests with invalid subpaths: we fail to parse these, which used to be correct before all of a sudden is_invalid for these cases was swapped from true to false in this commit without much of an explanation. These test cases appear to have been removed from the new test set though.

For the new test suite (a pull request to make use of it is up here) it currently fails on 45 and passes on 468 test cases. For the failed ones:

  • For two test cases for pkg:conan I cannot figure out why we are failing. I've opened a ticket since I suspect that the test cases might be incorrect purl-spec#643.
  • Of the remaining errors almost all are ones where the expected output in the test case is not a canonical purl/does not follow purl encoding guidelines. I've opened purl-spec#644 to better understand what's expected from library implementations.

petergardfjall avatar Aug 27 '25 12:08 petergardfjall

Pull Request Test Coverage Report for Build 17266694404

Details

  • 35 of 36 (97.22%) changed or added relevant lines in 1 file are covered.
  • No unchanged relevant lines lost coverage.
  • Overall coverage increased (+3.6%) to 85.761%

Changes Missing Coverage Covered Lines Changed/Added Lines %
packageurl.go 35 36 97.22%
<!-- Total: 35 36
Totals Coverage Status
Change from base Build 13610888770: 3.6%
Covered Lines: 265
Relevant Lines: 309

💛 - Coveralls

coveralls avatar Aug 27 '25 12:08 coveralls

@shibumi @mcombuechen ? Would anyone care to have a look?

petergardfjall avatar Oct 22 '25 07:10 petergardfjall

Barring some outstanding issues with the purl spec test suite (see below) this code now passes the entire purl-spec suite. We should first merge https://github.com/package-url/packageurl-go/pull/80 which changes the code to run against the new test suite in the purl-spec repo. When that is merged we can merge this PR.

Until these issues/PRs are fixed the code in this PR will fail to complete the entire test suite (it will fail on about 10 out of 500).

  • https://github.com/package-url/purl-spec/issues/736
    • https://github.com/package-url/purl-spec/pull/735
  • https://github.com/package-url/purl-spec/issues/731
    • https://github.com/package-url/purl-spec/pull/733
    • https://github.com/package-url/purl-spec/pull/734
  • https://github.com/package-url/purl-spec/issues/729
    • https://github.com/package-url/purl-spec/issues/644#issuecomment-3483016767

petergardfjall avatar Nov 04 '25 12:11 petergardfjall

Anyone up for reviewing?

petergardfjall avatar Nov 04 '25 13:11 petergardfjall

Anyone up for reviewing?

Bump

petergardfjall avatar Nov 24 '25 08:11 petergardfjall

Your PR relies on: https://github.com/package-url/packageurl-go/pull/80 and there we still see failing tests. :/ Do you mind incorporating that PR into yours and fixing it? Or do you want to merge it without #80?

shibumi avatar Nov 24 '25 12:11 shibumi

Your PR relies on: #80 and there we still see failing tests. :/ Do you mind incorporating that PR into yours and fixing it? Or do you want to merge it without #80?

Thanks @shibumi for taking the time to review. I rebased this PR onto #80 and reran the tests. Now there are only a dozen or so failing tests (see below). However, all of those failing test cases are incorrect.

In fact I have opened PRs in the purl-spec to fix most of them:

  • https://github.com/package-url/purl-spec/pull/735 (fixes three invalid cran-test cases)
  • https://github.com/package-url/purl-spec/pull/733 (fixes three invalid conan-test cases)
  • https://github.com/package-url/purl-spec/pull/734 (fixes three invalid conan-test cases)

There is also this PR which fixes the bazel-test cases.

  • https://github.com/package-url/purl-spec/pull/730.
$ make test | grep '\-\-\- FAIL:'
--- FAIL: TestPurlSpecFixtures (0.02s)
    --- FAIL: TestPurlSpecFixtures/bazel-test.json[1]roundtrip (0.00s)
    --- FAIL: TestPurlSpecFixtures/bazel-test.json[2]parse (0.00s)
    --- FAIL: TestPurlSpecFixtures/bazel-test.json[4]roundtrip (0.00s)
    --- FAIL: TestPurlSpecFixtures/bazel-test.json[5]parse (0.00s)
    --- FAIL: TestPurlSpecFixtures/bazel-test.json[6]build (0.00s)
    --- FAIL: TestPurlSpecFixtures/conan-test.json[9]parse (0.00s)
    --- FAIL: TestPurlSpecFixtures/conan-test.json[10]parse (0.00s)
    --- FAIL: TestPurlSpecFixtures/conan-test.json[11]build (0.00s)
    --- FAIL: TestPurlSpecFixtures/conan-test.json[12]parse (0.00s)
    --- FAIL: TestPurlSpecFixtures/conan-test.json[13]parse (0.00s)
    --- FAIL: TestPurlSpecFixtures/conan-test.json[14]build (0.00s)
    --- FAIL: TestPurlSpecFixtures/cran-test.json[8]parse (0.00s)
    --- FAIL: TestPurlSpecFixtures/cran-test.json[9]parse (0.00s)
    --- FAIL: TestPurlSpecFixtures/cran-test.json[10]build (0.00s)
make: *** [Makefile:6: test] Error 1

With those PRs applied the tests run cleanly. :tada:

git submodule update --init
git submodule update --remote
go test -v -cover ./...
=== RUN   TestQualifierValueEncoding
=== RUN   TestQualifierValueEncoding/must_percent-encode_a_qualifier_value
=== RUN   TestQualifierValueEncoding/must_not_percent-encode_colons_in_qualifier_values
=== RUN   TestQualifierValueEncoding/must_properly_percent-encode_a_plus
=== RUN   TestQualifierValueEncoding/must_order_qualifier_values_lexicographically_by_key
=== RUN   TestQualifierValueEncoding/must_percent-encode_separators_in_qualifier_value
=== RUN   TestQualifierValueEncoding/must_escape_a_qualifier_value
--- PASS: TestQualifierValueEncoding (0.00s)
    --- PASS: TestQualifierValueEncoding/must_percent-encode_a_qualifier_value (0.00s)
    --- PASS: TestQualifierValueEncoding/must_not_percent-encode_colons_in_qualifier_values (0.00s)
    --- PASS: TestQualifierValueEncoding/must_properly_percent-encode_a_plus (0.00s)
    --- PASS: TestQualifierValueEncoding/must_order_qualifier_values_lexicographically_by_key (0.00s)
    --- PASS: TestQualifierValueEncoding/must_percent-encode_separators_in_qualifier_value (0.00s)
    --- PASS: TestQualifierValueEncoding/must_escape_a_qualifier_value (0.00s)
=== RUN   TestPercentEncode
=== RUN   TestPercentEncode/must_not_percent-encode_alphanumeric_characters
=== RUN   TestPercentEncode/must_not_percent-encode_punctuation_characters
=== RUN   TestPercentEncode/must_not_percent-encode_colon
=== RUN   TestPercentEncode/must_percent-encode_separator_characters_other_than_colon
=== RUN   TestPercentEncode/must_percent-encode_a_plus
=== RUN   TestPercentEncode/must_percent-encode_a_whitespace
--- PASS: TestPercentEncode (0.00s)
    --- PASS: TestPercentEncode/must_not_percent-encode_alphanumeric_characters (0.00s)
    --- PASS: TestPercentEncode/must_not_percent-encode_punctuation_characters (0.00s)
    --- PASS: TestPercentEncode/must_not_percent-encode_colon (0.00s)
    --- PASS: TestPercentEncode/must_percent-encode_separator_characters_other_than_colon (0.00s)
    --- PASS: TestPercentEncode/must_percent-encode_a_plus (0.00s)
    --- PASS: TestPercentEncode/must_percent-encode_a_whitespace (0.00s)
=== RUN   TestPurlSpecFixtures
=== RUN   TestPurlSpecFixtures/alpm-test.json[1]parse
=== RUN   TestPurlSpecFixtures/alpm-test.json[2]roundtrip
=== RUN   TestPurlSpecFixtures/alpm-test.json[3]build
=== RUN   TestPurlSpecFixtures/alpm-test.json[4]parse
=== RUN   TestPurlSpecFixtures/alpm-test.json[5]roundtrip
=== RUN   TestPurlSpecFixtures/alpm-test.json[6]build
=== RUN   TestPurlSpecFixtures/alpm-test.json[7]parse
=== RUN   TestPurlSpecFixtures/alpm-test.json[8]roundtrip
=== RUN   TestPurlSpecFixtures/alpm-test.json[9]build
=== RUN   TestPurlSpecFixtures/apk-test.json[1]parse
=== RUN   TestPurlSpecFixtures/apk-test.json[2]roundtrip
=== RUN   TestPurlSpecFixtures/apk-test.json[3]build
=== RUN   TestPurlSpecFixtures/apk-test.json[4]parse
=== RUN   TestPurlSpecFixtures/apk-test.json[5]roundtrip
=== RUN   TestPurlSpecFixtures/apk-test.json[6]build
=== RUN   TestPurlSpecFixtures/bazel-test.json[1]roundtrip
=== RUN   TestPurlSpecFixtures/bazel-test.json[2]parse
=== RUN   TestPurlSpecFixtures/bazel-test.json[3]build
=== RUN   TestPurlSpecFixtures/bazel-test.json[4]roundtrip
=== RUN   TestPurlSpecFixtures/bazel-test.json[5]parse
=== RUN   TestPurlSpecFixtures/bazel-test.json[6]build
=== RUN   TestPurlSpecFixtures/bazel-test.json[7]roundtrip
=== RUN   TestPurlSpecFixtures/bazel-test.json[8]parse
=== RUN   TestPurlSpecFixtures/bazel-test.json[9]build
=== RUN   TestPurlSpecFixtures/bazel-test.json[10]roundtrip
=== RUN   TestPurlSpecFixtures/bazel-test.json[11]parse
=== RUN   TestPurlSpecFixtures/bazel-test.json[12]build
=== RUN   TestPurlSpecFixtures/bazel-test.json[13]roundtrip
=== RUN   TestPurlSpecFixtures/bazel-test.json[14]parse
=== RUN   TestPurlSpecFixtures/bazel-test.json[15]build
=== RUN   TestPurlSpecFixtures/bazel-test.json[16]roundtrip
=== RUN   TestPurlSpecFixtures/bazel-test.json[17]parse
=== RUN   TestPurlSpecFixtures/bazel-test.json[18]build
=== RUN   TestPurlSpecFixtures/bazel-test.json[19]roundtrip
=== RUN   TestPurlSpecFixtures/bazel-test.json[20]parse
=== RUN   TestPurlSpecFixtures/bazel-test.json[21]build
=== RUN   TestPurlSpecFixtures/bitbucket-test.json[1]roundtrip
=== RUN   TestPurlSpecFixtures/bitbucket-test.json[2]parse
=== RUN   TestPurlSpecFixtures/bitbucket-test.json[3]roundtrip
=== RUN   TestPurlSpecFixtures/bitbucket-test.json[4]build
=== RUN   TestPurlSpecFixtures/bitbucket-test.json[5]parse
=== RUN   TestPurlSpecFixtures/bitbucket-test.json[6]roundtrip
=== RUN   TestPurlSpecFixtures/bitbucket-test.json[7]build
=== RUN   TestPurlSpecFixtures/bitnami-test.json[1]parse
=== RUN   TestPurlSpecFixtures/bitnami-test.json[2]roundtrip
=== RUN   TestPurlSpecFixtures/bitnami-test.json[3]build
=== RUN   TestPurlSpecFixtures/bitnami-test.json[4]parse
=== RUN   TestPurlSpecFixtures/bitnami-test.json[5]roundtrip
=== RUN   TestPurlSpecFixtures/bitnami-test.json[6]build
=== RUN   TestPurlSpecFixtures/bitnami-test.json[7]parse
=== RUN   TestPurlSpecFixtures/bitnami-test.json[8]roundtrip
=== RUN   TestPurlSpecFixtures/bitnami-test.json[9]build
=== RUN   TestPurlSpecFixtures/bitnami-test.json[10]parse
=== RUN   TestPurlSpecFixtures/bitnami-test.json[11]roundtrip
=== RUN   TestPurlSpecFixtures/bitnami-test.json[12]build
=== RUN   TestPurlSpecFixtures/cargo-test.json[1]parse
=== RUN   TestPurlSpecFixtures/cargo-test.json[2]roundtrip
=== RUN   TestPurlSpecFixtures/cargo-test.json[3]build
=== RUN   TestPurlSpecFixtures/cargo-test.json[4]parse
=== RUN   TestPurlSpecFixtures/cargo-test.json[5]roundtrip
=== RUN   TestPurlSpecFixtures/cargo-test.json[6]build
=== RUN   TestPurlSpecFixtures/cargo-test.json[7]parse
=== RUN   TestPurlSpecFixtures/cargo-test.json[8]roundtrip
=== RUN   TestPurlSpecFixtures/cargo-test.json[9]build
=== RUN   TestPurlSpecFixtures/cocoapods-test.json[1]parse
=== RUN   TestPurlSpecFixtures/cocoapods-test.json[2]roundtrip
=== RUN   TestPurlSpecFixtures/cocoapods-test.json[3]build
=== RUN   TestPurlSpecFixtures/cocoapods-test.json[4]parse
=== RUN   TestPurlSpecFixtures/cocoapods-test.json[5]roundtrip
=== RUN   TestPurlSpecFixtures/cocoapods-test.json[6]build
=== RUN   TestPurlSpecFixtures/cocoapods-test.json[7]parse
=== RUN   TestPurlSpecFixtures/cocoapods-test.json[8]roundtrip
=== RUN   TestPurlSpecFixtures/cocoapods-test.json[9]build
=== RUN   TestPurlSpecFixtures/cocoapods-test.json[10]parse
=== RUN   TestPurlSpecFixtures/cocoapods-test.json[11]roundtrip
=== RUN   TestPurlSpecFixtures/cocoapods-test.json[12]build
=== RUN   TestPurlSpecFixtures/composer-test.json[1]roundtrip
=== RUN   TestPurlSpecFixtures/composer-test.json[2]parse
=== RUN   TestPurlSpecFixtures/composer-test.json[3]roundtrip
=== RUN   TestPurlSpecFixtures/composer-test.json[4]parse
=== RUN   TestPurlSpecFixtures/composer-test.json[5]roundtrip
=== RUN   TestPurlSpecFixtures/composer-test.json[6]build
=== RUN   TestPurlSpecFixtures/composer-test.json[7]parse
=== RUN   TestPurlSpecFixtures/composer-test.json[8]roundtrip
=== RUN   TestPurlSpecFixtures/composer-test.json[9]build
=== RUN   TestPurlSpecFixtures/conan-test.json[1]roundtrip
=== RUN   TestPurlSpecFixtures/conan-test.json[2]parse
=== RUN   TestPurlSpecFixtures/conan-test.json[3]roundtrip
=== RUN   TestPurlSpecFixtures/conan-test.json[4]build
=== RUN   TestPurlSpecFixtures/conan-test.json[5]roundtrip
=== RUN   TestPurlSpecFixtures/conan-test.json[6]parse
=== RUN   TestPurlSpecFixtures/conan-test.json[7]roundtrip
=== RUN   TestPurlSpecFixtures/conan-test.json[8]build
=== RUN   TestPurlSpecFixtures/conan-test.json[9]parse
=== RUN   TestPurlSpecFixtures/conan-test.json[10]roundtrip
=== RUN   TestPurlSpecFixtures/conan-test.json[11]build
=== RUN   TestPurlSpecFixtures/conan-test.json[12]parse
=== RUN   TestPurlSpecFixtures/conan-test.json[13]roundtrip
=== RUN   TestPurlSpecFixtures/conan-test.json[14]build
=== RUN   TestPurlSpecFixtures/conan-test.json[15]parse
=== RUN   TestPurlSpecFixtures/conan-test.json[16]roundtrip
=== RUN   TestPurlSpecFixtures/conan-test.json[17]build
=== RUN   TestPurlSpecFixtures/conda-test.json[1]roundtrip
=== RUN   TestPurlSpecFixtures/conda-test.json[2]parse
=== RUN   TestPurlSpecFixtures/conda-test.json[3]roundtrip
=== RUN   TestPurlSpecFixtures/conda-test.json[4]build
=== RUN   TestPurlSpecFixtures/conda-test.json[5]parse
=== RUN   TestPurlSpecFixtures/conda-test.json[6]roundtrip
=== RUN   TestPurlSpecFixtures/conda-test.json[7]build
=== RUN   TestPurlSpecFixtures/cpan-test.json[1]roundtrip
=== RUN   TestPurlSpecFixtures/cpan-test.json[2]parse
=== RUN   TestPurlSpecFixtures/cpan-test.json[3]roundtrip
=== RUN   TestPurlSpecFixtures/cpan-test.json[4]build
=== RUN   TestPurlSpecFixtures/cpan-test.json[5]build
=== RUN   TestPurlSpecFixtures/cpan-test.json[6]parse
=== RUN   TestPurlSpecFixtures/cpan-test.json[7]parse
=== RUN   TestPurlSpecFixtures/cpan-test.json[8]build
=== RUN   TestPurlSpecFixtures/cpan-test.json[9]roundtrip
=== RUN   TestPurlSpecFixtures/cpan-test.json[10]build
=== RUN   TestPurlSpecFixtures/cpan-test.json[11]parse
=== RUN   TestPurlSpecFixtures/cpan-test.json[12]roundtrip
=== RUN   TestPurlSpecFixtures/cpan-test.json[13]build
=== RUN   TestPurlSpecFixtures/cpan-test.json[14]parse
=== RUN   TestPurlSpecFixtures/cpan-test.json[15]roundtrip
=== RUN   TestPurlSpecFixtures/cpan-test.json[16]build
=== RUN   TestPurlSpecFixtures/cpan-test.json[17]roundtrip
=== RUN   TestPurlSpecFixtures/cpan-test.json[18]parse
=== RUN   TestPurlSpecFixtures/cpan-test.json[19]build
=== RUN   TestPurlSpecFixtures/cran-test.json[1]roundtrip
=== RUN   TestPurlSpecFixtures/cran-test.json[2]parse
=== RUN   TestPurlSpecFixtures/cran-test.json[3]roundtrip
=== RUN   TestPurlSpecFixtures/cran-test.json[4]build
=== RUN   TestPurlSpecFixtures/cran-test.json[5]parse
=== RUN   TestPurlSpecFixtures/cran-test.json[6]parse
=== RUN   TestPurlSpecFixtures/cran-test.json[7]build
=== RUN   TestPurlSpecFixtures/cran-test.json[8]parse
=== RUN   TestPurlSpecFixtures/cran-test.json[9]roundtrip
=== RUN   TestPurlSpecFixtures/cran-test.json[10]build
=== RUN   TestPurlSpecFixtures/cran-test.json[11]parse
=== RUN   TestPurlSpecFixtures/cran-test.json[12]roundtrip
=== RUN   TestPurlSpecFixtures/cran-test.json[13]build
=== RUN   TestPurlSpecFixtures/cran-test.json[14]parse
=== RUN   TestPurlSpecFixtures/cran-test.json[15]roundtrip
=== RUN   TestPurlSpecFixtures/cran-test.json[16]build
=== RUN   TestPurlSpecFixtures/deb-test.json[1]roundtrip
=== RUN   TestPurlSpecFixtures/deb-test.json[2]parse
=== RUN   TestPurlSpecFixtures/deb-test.json[3]roundtrip
=== RUN   TestPurlSpecFixtures/deb-test.json[4]build
=== RUN   TestPurlSpecFixtures/deb-test.json[5]parse
=== RUN   TestPurlSpecFixtures/deb-test.json[6]roundtrip
=== RUN   TestPurlSpecFixtures/deb-test.json[7]build
=== RUN   TestPurlSpecFixtures/deb-test.json[8]parse
=== RUN   TestPurlSpecFixtures/deb-test.json[9]roundtrip
=== RUN   TestPurlSpecFixtures/deb-test.json[10]build
=== RUN   TestPurlSpecFixtures/deb-test.json[11]parse
=== RUN   TestPurlSpecFixtures/deb-test.json[12]roundtrip
=== RUN   TestPurlSpecFixtures/deb-test.json[13]build
=== RUN   TestPurlSpecFixtures/deb-test.json[14]parse
=== RUN   TestPurlSpecFixtures/deb-test.json[15]roundtrip
=== RUN   TestPurlSpecFixtures/deb-test.json[16]build
=== RUN   TestPurlSpecFixtures/deb-test.json[17]parse
=== RUN   TestPurlSpecFixtures/deb-test.json[18]roundtrip
=== RUN   TestPurlSpecFixtures/deb-test.json[19]build
=== RUN   TestPurlSpecFixtures/docker-test.json[1]roundtrip
=== RUN   TestPurlSpecFixtures/docker-test.json[2]parse
=== RUN   TestPurlSpecFixtures/docker-test.json[3]roundtrip
=== RUN   TestPurlSpecFixtures/docker-test.json[4]build
=== RUN   TestPurlSpecFixtures/docker-test.json[5]parse
=== RUN   TestPurlSpecFixtures/docker-test.json[6]roundtrip
=== RUN   TestPurlSpecFixtures/docker-test.json[7]build
=== RUN   TestPurlSpecFixtures/docker-test.json[8]parse
=== RUN   TestPurlSpecFixtures/docker-test.json[9]roundtrip
=== RUN   TestPurlSpecFixtures/docker-test.json[10]build
=== RUN   TestPurlSpecFixtures/docker-test.json[11]parse
=== RUN   TestPurlSpecFixtures/docker-test.json[12]roundtrip
=== RUN   TestPurlSpecFixtures/docker-test.json[13]build
=== RUN   TestPurlSpecFixtures/gem-test.json[1]roundtrip
=== RUN   TestPurlSpecFixtures/gem-test.json[2]parse
=== RUN   TestPurlSpecFixtures/gem-test.json[3]roundtrip
=== RUN   TestPurlSpecFixtures/gem-test.json[4]build
=== RUN   TestPurlSpecFixtures/gem-test.json[5]parse
=== RUN   TestPurlSpecFixtures/gem-test.json[6]roundtrip
=== RUN   TestPurlSpecFixtures/gem-test.json[7]build
=== RUN   TestPurlSpecFixtures/gem-test.json[8]parse
=== RUN   TestPurlSpecFixtures/gem-test.json[9]roundtrip
=== RUN   TestPurlSpecFixtures/gem-test.json[10]build
=== RUN   TestPurlSpecFixtures/generic-test.json[1]parse
=== RUN   TestPurlSpecFixtures/generic-test.json[2]roundtrip
=== RUN   TestPurlSpecFixtures/generic-test.json[3]build
=== RUN   TestPurlSpecFixtures/generic-test.json[4]parse
=== RUN   TestPurlSpecFixtures/generic-test.json[5]roundtrip
=== RUN   TestPurlSpecFixtures/generic-test.json[6]build
=== RUN   TestPurlSpecFixtures/generic-test.json[7]parse
=== RUN   TestPurlSpecFixtures/generic-test.json[8]roundtrip
=== RUN   TestPurlSpecFixtures/generic-test.json[9]build
=== RUN   TestPurlSpecFixtures/github-test.json[1]roundtrip
=== RUN   TestPurlSpecFixtures/github-test.json[2]parse
=== RUN   TestPurlSpecFixtures/github-test.json[3]roundtrip
=== RUN   TestPurlSpecFixtures/github-test.json[4]build
=== RUN   TestPurlSpecFixtures/github-test.json[5]parse
=== RUN   TestPurlSpecFixtures/github-test.json[6]roundtrip
=== RUN   TestPurlSpecFixtures/github-test.json[7]build
=== RUN   TestPurlSpecFixtures/github-test.json[8]parse
=== RUN   TestPurlSpecFixtures/github-test.json[9]roundtrip
=== RUN   TestPurlSpecFixtures/github-test.json[10]build
=== RUN   TestPurlSpecFixtures/golang-test.json[1]roundtrip
=== RUN   TestPurlSpecFixtures/golang-test.json[2]parse
=== RUN   TestPurlSpecFixtures/golang-test.json[3]roundtrip
=== RUN   TestPurlSpecFixtures/golang-test.json[4]build
=== RUN   TestPurlSpecFixtures/golang-test.json[5]roundtrip
=== RUN   TestPurlSpecFixtures/golang-test.json[6]parse
=== RUN   TestPurlSpecFixtures/golang-test.json[7]roundtrip
=== RUN   TestPurlSpecFixtures/golang-test.json[8]build
=== RUN   TestPurlSpecFixtures/golang-test.json[9]parse
=== RUN   TestPurlSpecFixtures/golang-test.json[10]roundtrip
=== RUN   TestPurlSpecFixtures/golang-test.json[11]build
=== RUN   TestPurlSpecFixtures/golang-test.json[12]parse
=== RUN   TestPurlSpecFixtures/golang-test.json[13]roundtrip
=== RUN   TestPurlSpecFixtures/golang-test.json[14]build
=== RUN   TestPurlSpecFixtures/golang-test.json[15]parse
=== RUN   TestPurlSpecFixtures/golang-test.json[16]roundtrip
=== RUN   TestPurlSpecFixtures/golang-test.json[17]build
=== RUN   TestPurlSpecFixtures/hackage-test.json[1]roundtrip
=== RUN   TestPurlSpecFixtures/hackage-test.json[2]parse
=== RUN   TestPurlSpecFixtures/hackage-test.json[3]roundtrip
=== RUN   TestPurlSpecFixtures/hackage-test.json[4]build
=== RUN   TestPurlSpecFixtures/hackage-test.json[5]parse
=== RUN   TestPurlSpecFixtures/hackage-test.json[6]parse
=== RUN   TestPurlSpecFixtures/hackage-test.json[7]build
=== RUN   TestPurlSpecFixtures/hackage-test.json[8]parse
=== RUN   TestPurlSpecFixtures/hackage-test.json[9]roundtrip
=== RUN   TestPurlSpecFixtures/hackage-test.json[10]build
=== RUN   TestPurlSpecFixtures/hackage-test.json[11]parse
=== RUN   TestPurlSpecFixtures/hackage-test.json[12]roundtrip
=== RUN   TestPurlSpecFixtures/hackage-test.json[13]build
=== RUN   TestPurlSpecFixtures/hackage-test.json[14]parse
=== RUN   TestPurlSpecFixtures/hackage-test.json[15]roundtrip
=== RUN   TestPurlSpecFixtures/hackage-test.json[16]build
=== RUN   TestPurlSpecFixtures/hex-test.json[1]parse
=== RUN   TestPurlSpecFixtures/hex-test.json[2]roundtrip
=== RUN   TestPurlSpecFixtures/hex-test.json[3]build
=== RUN   TestPurlSpecFixtures/hex-test.json[4]parse
=== RUN   TestPurlSpecFixtures/hex-test.json[5]roundtrip
=== RUN   TestPurlSpecFixtures/hex-test.json[6]build
=== RUN   TestPurlSpecFixtures/hex-test.json[7]parse
=== RUN   TestPurlSpecFixtures/hex-test.json[8]roundtrip
=== RUN   TestPurlSpecFixtures/hex-test.json[9]build
=== RUN   TestPurlSpecFixtures/hex-test.json[10]parse
=== RUN   TestPurlSpecFixtures/hex-test.json[11]roundtrip
=== RUN   TestPurlSpecFixtures/hex-test.json[12]build
=== RUN   TestPurlSpecFixtures/huggingface-test.json[1]roundtrip
=== RUN   TestPurlSpecFixtures/huggingface-test.json[2]parse
=== RUN   TestPurlSpecFixtures/huggingface-test.json[3]roundtrip
=== RUN   TestPurlSpecFixtures/huggingface-test.json[4]build
=== RUN   TestPurlSpecFixtures/huggingface-test.json[5]roundtrip
=== RUN   TestPurlSpecFixtures/huggingface-test.json[6]parse
=== RUN   TestPurlSpecFixtures/huggingface-test.json[7]roundtrip
=== RUN   TestPurlSpecFixtures/huggingface-test.json[8]build
=== RUN   TestPurlSpecFixtures/huggingface-test.json[9]roundtrip
=== RUN   TestPurlSpecFixtures/huggingface-test.json[10]parse
=== RUN   TestPurlSpecFixtures/huggingface-test.json[11]roundtrip
=== RUN   TestPurlSpecFixtures/huggingface-test.json[12]build
=== RUN   TestPurlSpecFixtures/huggingface-test.json[13]parse
=== RUN   TestPurlSpecFixtures/huggingface-test.json[14]roundtrip
=== RUN   TestPurlSpecFixtures/huggingface-test.json[15]build
=== RUN   TestPurlSpecFixtures/huggingface-test.json[16]parse
=== RUN   TestPurlSpecFixtures/huggingface-test.json[17]roundtrip
=== RUN   TestPurlSpecFixtures/huggingface-test.json[18]build
=== RUN   TestPurlSpecFixtures/julia-test.json[1]parse
=== RUN   TestPurlSpecFixtures/julia-test.json[2]parse
=== RUN   TestPurlSpecFixtures/julia-test.json[3]parse
=== RUN   TestPurlSpecFixtures/julia-test.json[4]parse
=== RUN   TestPurlSpecFixtures/julia-test.json[5]build
=== RUN   TestPurlSpecFixtures/julia-test.json[6]build
=== RUN   TestPurlSpecFixtures/julia-test.json[7]roundtrip
=== RUN   TestPurlSpecFixtures/julia-test.json[8]roundtrip
=== RUN   TestPurlSpecFixtures/julia-test.json[9]parse
=== RUN   TestPurlSpecFixtures/julia-test.json[10]parse
=== RUN   TestPurlSpecFixtures/julia-test.json[11]build
=== RUN   TestPurlSpecFixtures/julia-test.json[12]build
=== RUN   TestPurlSpecFixtures/julia-test.json[13]parse
=== RUN   TestPurlSpecFixtures/luarocks-test.json[1]parse
=== RUN   TestPurlSpecFixtures/luarocks-test.json[2]roundtrip
=== RUN   TestPurlSpecFixtures/luarocks-test.json[3]build
=== RUN   TestPurlSpecFixtures/luarocks-test.json[4]parse
=== RUN   TestPurlSpecFixtures/luarocks-test.json[5]roundtrip
=== RUN   TestPurlSpecFixtures/luarocks-test.json[6]build
=== RUN   TestPurlSpecFixtures/luarocks-test.json[7]parse
=== RUN   TestPurlSpecFixtures/luarocks-test.json[8]roundtrip
=== RUN   TestPurlSpecFixtures/luarocks-test.json[9]build
=== RUN   TestPurlSpecFixtures/maven-test.json[1]roundtrip
=== RUN   TestPurlSpecFixtures/maven-test.json[2]parse
=== RUN   TestPurlSpecFixtures/maven-test.json[3]roundtrip
=== RUN   TestPurlSpecFixtures/maven-test.json[4]build
=== RUN   TestPurlSpecFixtures/maven-test.json[5]roundtrip
=== RUN   TestPurlSpecFixtures/maven-test.json[6]parse
=== RUN   TestPurlSpecFixtures/maven-test.json[7]roundtrip
=== RUN   TestPurlSpecFixtures/maven-test.json[8]build
=== RUN   TestPurlSpecFixtures/maven-test.json[9]roundtrip
=== RUN   TestPurlSpecFixtures/maven-test.json[10]parse
=== RUN   TestPurlSpecFixtures/maven-test.json[11]roundtrip
=== RUN   TestPurlSpecFixtures/maven-test.json[12]build
=== RUN   TestPurlSpecFixtures/maven-test.json[13]roundtrip
=== RUN   TestPurlSpecFixtures/maven-test.json[14]parse
=== RUN   TestPurlSpecFixtures/maven-test.json[15]roundtrip
=== RUN   TestPurlSpecFixtures/maven-test.json[16]build
=== RUN   TestPurlSpecFixtures/maven-test.json[17]roundtrip
=== RUN   TestPurlSpecFixtures/maven-test.json[18]parse
=== RUN   TestPurlSpecFixtures/maven-test.json[19]roundtrip
=== RUN   TestPurlSpecFixtures/maven-test.json[20]build
=== RUN   TestPurlSpecFixtures/maven-test.json[21]roundtrip
=== RUN   TestPurlSpecFixtures/maven-test.json[22]parse
=== RUN   TestPurlSpecFixtures/maven-test.json[23]roundtrip
=== RUN   TestPurlSpecFixtures/maven-test.json[24]build
=== RUN   TestPurlSpecFixtures/maven-test.json[25]roundtrip
=== RUN   TestPurlSpecFixtures/maven-test.json[26]parse
=== RUN   TestPurlSpecFixtures/maven-test.json[27]roundtrip
=== RUN   TestPurlSpecFixtures/maven-test.json[28]build
=== RUN   TestPurlSpecFixtures/maven-test.json[29]roundtrip
=== RUN   TestPurlSpecFixtures/maven-test.json[30]parse
=== RUN   TestPurlSpecFixtures/maven-test.json[31]roundtrip
=== RUN   TestPurlSpecFixtures/maven-test.json[32]build
=== RUN   TestPurlSpecFixtures/maven-test.json[33]roundtrip
=== RUN   TestPurlSpecFixtures/maven-test.json[34]parse
=== RUN   TestPurlSpecFixtures/maven-test.json[35]roundtrip
=== RUN   TestPurlSpecFixtures/maven-test.json[36]build
=== RUN   TestPurlSpecFixtures/maven-test.json[37]roundtrip
=== RUN   TestPurlSpecFixtures/maven-test.json[38]parse
=== RUN   TestPurlSpecFixtures/maven-test.json[39]roundtrip
=== RUN   TestPurlSpecFixtures/maven-test.json[40]build
=== RUN   TestPurlSpecFixtures/maven-test.json[41]parse
=== RUN   TestPurlSpecFixtures/maven-test.json[42]roundtrip
=== RUN   TestPurlSpecFixtures/maven-test.json[43]build
=== RUN   TestPurlSpecFixtures/maven-test.json[44]parse
=== RUN   TestPurlSpecFixtures/maven-test.json[45]roundtrip
=== RUN   TestPurlSpecFixtures/maven-test.json[46]build
=== RUN   TestPurlSpecFixtures/maven-test.json[47]parse
=== RUN   TestPurlSpecFixtures/maven-test.json[48]roundtrip
=== RUN   TestPurlSpecFixtures/maven-test.json[49]build
=== RUN   TestPurlSpecFixtures/maven-test.json[50]parse
=== RUN   TestPurlSpecFixtures/maven-test.json[51]roundtrip
=== RUN   TestPurlSpecFixtures/maven-test.json[52]build
=== RUN   TestPurlSpecFixtures/maven-test.json[53]parse
=== RUN   TestPurlSpecFixtures/maven-test.json[54]roundtrip
=== RUN   TestPurlSpecFixtures/maven-test.json[55]build
=== RUN   TestPurlSpecFixtures/maven-test.json[56]parse
=== RUN   TestPurlSpecFixtures/maven-test.json[57]roundtrip
=== RUN   TestPurlSpecFixtures/maven-test.json[58]build
=== RUN   TestPurlSpecFixtures/maven-test.json[59]parse
=== RUN   TestPurlSpecFixtures/maven-test.json[60]roundtrip
=== RUN   TestPurlSpecFixtures/maven-test.json[61]build
=== RUN   TestPurlSpecFixtures/mlflow-test.json[1]roundtrip
=== RUN   TestPurlSpecFixtures/mlflow-test.json[2]parse
=== RUN   TestPurlSpecFixtures/mlflow-test.json[3]roundtrip
=== RUN   TestPurlSpecFixtures/mlflow-test.json[4]build
=== RUN   TestPurlSpecFixtures/mlflow-test.json[5]roundtrip
=== RUN   TestPurlSpecFixtures/mlflow-test.json[6]parse
=== RUN   TestPurlSpecFixtures/mlflow-test.json[7]roundtrip
=== RUN   TestPurlSpecFixtures/mlflow-test.json[8]build
=== RUN   TestPurlSpecFixtures/mlflow-test.json[9]roundtrip
=== RUN   TestPurlSpecFixtures/mlflow-test.json[10]parse
=== RUN   TestPurlSpecFixtures/mlflow-test.json[11]roundtrip
=== RUN   TestPurlSpecFixtures/mlflow-test.json[12]build
=== RUN   TestPurlSpecFixtures/mlflow-test.json[13]parse
=== RUN   TestPurlSpecFixtures/mlflow-test.json[14]roundtrip
=== RUN   TestPurlSpecFixtures/mlflow-test.json[15]build
=== RUN   TestPurlSpecFixtures/mlflow-test.json[16]parse
=== RUN   TestPurlSpecFixtures/mlflow-test.json[17]roundtrip
=== RUN   TestPurlSpecFixtures/mlflow-test.json[18]build
=== RUN   TestPurlSpecFixtures/npm-test.json[1]roundtrip
=== RUN   TestPurlSpecFixtures/npm-test.json[2]parse
=== RUN   TestPurlSpecFixtures/npm-test.json[3]roundtrip
=== RUN   TestPurlSpecFixtures/npm-test.json[4]build
=== RUN   TestPurlSpecFixtures/npm-test.json[5]parse
=== RUN   TestPurlSpecFixtures/npm-test.json[6]roundtrip
=== RUN   TestPurlSpecFixtures/npm-test.json[7]build
=== RUN   TestPurlSpecFixtures/npm-test.json[8]parse
=== RUN   TestPurlSpecFixtures/npm-test.json[9]roundtrip
=== RUN   TestPurlSpecFixtures/npm-test.json[10]build
=== RUN   TestPurlSpecFixtures/npm-test.json[11]parse
=== RUN   TestPurlSpecFixtures/npm-test.json[12]roundtrip
=== RUN   TestPurlSpecFixtures/npm-test.json[13]build
=== RUN   TestPurlSpecFixtures/npm-test.json[14]roundtrip
=== RUN   TestPurlSpecFixtures/npm-test.json[15]parse
=== RUN   TestPurlSpecFixtures/npm-test.json[16]parse
=== RUN   TestPurlSpecFixtures/npm-test.json[17]roundtrip
=== RUN   TestPurlSpecFixtures/nuget-test.json[1]roundtrip
=== RUN   TestPurlSpecFixtures/nuget-test.json[2]parse
=== RUN   TestPurlSpecFixtures/nuget-test.json[3]roundtrip
=== RUN   TestPurlSpecFixtures/nuget-test.json[4]build
=== RUN   TestPurlSpecFixtures/nuget-test.json[5]parse
=== RUN   TestPurlSpecFixtures/nuget-test.json[6]roundtrip
=== RUN   TestPurlSpecFixtures/nuget-test.json[7]build
=== RUN   TestPurlSpecFixtures/oci-test.json[1]parse
=== RUN   TestPurlSpecFixtures/oci-test.json[2]roundtrip
=== RUN   TestPurlSpecFixtures/oci-test.json[3]build
=== RUN   TestPurlSpecFixtures/oci-test.json[4]parse
=== RUN   TestPurlSpecFixtures/oci-test.json[5]roundtrip
=== RUN   TestPurlSpecFixtures/oci-test.json[6]build
=== RUN   TestPurlSpecFixtures/oci-test.json[7]parse
=== RUN   TestPurlSpecFixtures/oci-test.json[8]roundtrip
=== RUN   TestPurlSpecFixtures/oci-test.json[9]build
=== RUN   TestPurlSpecFixtures/oci-test.json[10]parse
=== RUN   TestPurlSpecFixtures/oci-test.json[11]roundtrip
=== RUN   TestPurlSpecFixtures/oci-test.json[12]build
=== RUN   TestPurlSpecFixtures/pub-test.json[1]parse
=== RUN   TestPurlSpecFixtures/pub-test.json[2]roundtrip
=== RUN   TestPurlSpecFixtures/pub-test.json[3]build
=== RUN   TestPurlSpecFixtures/pub-test.json[4]parse
=== RUN   TestPurlSpecFixtures/pub-test.json[5]roundtrip
=== RUN   TestPurlSpecFixtures/pub-test.json[6]build
=== RUN   TestPurlSpecFixtures/pypi-test.json[1]roundtrip
=== RUN   TestPurlSpecFixtures/pypi-test.json[2]parse
=== RUN   TestPurlSpecFixtures/pypi-test.json[3]roundtrip
=== RUN   TestPurlSpecFixtures/pypi-test.json[4]build
=== RUN   TestPurlSpecFixtures/pypi-test.json[5]parse
=== RUN   TestPurlSpecFixtures/pypi-test.json[6]roundtrip
=== RUN   TestPurlSpecFixtures/pypi-test.json[7]build
=== RUN   TestPurlSpecFixtures/pypi-test.json[8]parse
=== RUN   TestPurlSpecFixtures/pypi-test.json[9]roundtrip
=== RUN   TestPurlSpecFixtures/pypi-test.json[10]build
=== RUN   TestPurlSpecFixtures/pypi-test.json[11]parse
=== RUN   TestPurlSpecFixtures/pypi-test.json[12]roundtrip
=== RUN   TestPurlSpecFixtures/pypi-test.json[13]build
=== RUN   TestPurlSpecFixtures/pypi-test.json[14]parse
=== RUN   TestPurlSpecFixtures/pypi-test.json[15]roundtrip
=== RUN   TestPurlSpecFixtures/pypi-test.json[16]build
=== RUN   TestPurlSpecFixtures/qpkg-test.json[1]parse
=== RUN   TestPurlSpecFixtures/qpkg-test.json[2]roundtrip
=== RUN   TestPurlSpecFixtures/qpkg-test.json[3]build
=== RUN   TestPurlSpecFixtures/qpkg-test.json[4]parse
=== RUN   TestPurlSpecFixtures/qpkg-test.json[5]roundtrip
=== RUN   TestPurlSpecFixtures/qpkg-test.json[6]build
=== RUN   TestPurlSpecFixtures/rpm-test.json[1]roundtrip
=== RUN   TestPurlSpecFixtures/rpm-test.json[2]parse
=== RUN   TestPurlSpecFixtures/rpm-test.json[3]roundtrip
=== RUN   TestPurlSpecFixtures/rpm-test.json[4]build
=== RUN   TestPurlSpecFixtures/rpm-test.json[5]parse
=== RUN   TestPurlSpecFixtures/rpm-test.json[6]roundtrip
=== RUN   TestPurlSpecFixtures/rpm-test.json[7]build
=== RUN   TestPurlSpecFixtures/rpm-test.json[8]parse
=== RUN   TestPurlSpecFixtures/rpm-test.json[9]roundtrip
=== RUN   TestPurlSpecFixtures/rpm-test.json[10]build
=== RUN   TestPurlSpecFixtures/swid-test.json[1]parse
=== RUN   TestPurlSpecFixtures/swid-test.json[2]roundtrip
=== RUN   TestPurlSpecFixtures/swid-test.json[3]build
=== RUN   TestPurlSpecFixtures/swid-test.json[4]parse
=== RUN   TestPurlSpecFixtures/swid-test.json[5]roundtrip
=== RUN   TestPurlSpecFixtures/swid-test.json[6]build
=== RUN   TestPurlSpecFixtures/swid-test.json[7]parse
=== RUN   TestPurlSpecFixtures/swid-test.json[8]roundtrip
=== RUN   TestPurlSpecFixtures/swid-test.json[9]build
=== RUN   TestPurlSpecFixtures/swift-test.json[1]roundtrip
=== RUN   TestPurlSpecFixtures/swift-test.json[2]parse
=== RUN   TestPurlSpecFixtures/swift-test.json[3]roundtrip
=== RUN   TestPurlSpecFixtures/swift-test.json[4]build
=== RUN   TestPurlSpecFixtures/swift-test.json[5]parse
=== RUN   TestPurlSpecFixtures/swift-test.json[6]parse
=== RUN   TestPurlSpecFixtures/swift-test.json[7]build
=== RUN   TestPurlSpecFixtures/swift-test.json[8]parse
=== RUN   TestPurlSpecFixtures/swift-test.json[9]parse
=== RUN   TestPurlSpecFixtures/swift-test.json[10]build
=== RUN   TestPurlSpecFixtures/swift-test.json[11]parse
=== RUN   TestPurlSpecFixtures/swift-test.json[12]parse
=== RUN   TestPurlSpecFixtures/swift-test.json[13]build
=== RUN   TestPurlSpecFixtures/swift-test.json[14]parse
=== RUN   TestPurlSpecFixtures/swift-test.json[15]roundtrip
=== RUN   TestPurlSpecFixtures/swift-test.json[16]build
=== RUN   TestPurlSpecFixtures/swift-test.json[17]parse
=== RUN   TestPurlSpecFixtures/swift-test.json[18]roundtrip
=== RUN   TestPurlSpecFixtures/swift-test.json[19]build
--- PASS: TestPurlSpecFixtures (0.03s)
    --- PASS: TestPurlSpecFixtures/alpm-test.json[1]parse (0.00s)
    --- PASS: TestPurlSpecFixtures/alpm-test.json[2]roundtrip (0.00s)
    --- PASS: TestPurlSpecFixtures/alpm-test.json[3]build (0.00s)
    --- PASS: TestPurlSpecFixtures/alpm-test.json[4]parse (0.00s)
    --- PASS: TestPurlSpecFixtures/alpm-test.json[5]roundtrip (0.00s)
    --- PASS: TestPurlSpecFixtures/alpm-test.json[6]build (0.00s)
    --- PASS: TestPurlSpecFixtures/alpm-test.json[7]parse (0.00s)
    --- PASS: TestPurlSpecFixtures/alpm-test.json[8]roundtrip (0.00s)
    --- PASS: TestPurlSpecFixtures/alpm-test.json[9]build (0.00s)
    --- PASS: TestPurlSpecFixtures/apk-test.json[1]parse (0.00s)
    --- PASS: TestPurlSpecFixtures/apk-test.json[2]roundtrip (0.00s)
    --- PASS: TestPurlSpecFixtures/apk-test.json[3]build (0.00s)
    --- PASS: TestPurlSpecFixtures/apk-test.json[4]parse (0.00s)
    --- PASS: TestPurlSpecFixtures/apk-test.json[5]roundtrip (0.00s)
    --- PASS: TestPurlSpecFixtures/apk-test.json[6]build (0.00s)
    --- PASS: TestPurlSpecFixtures/bazel-test.json[1]roundtrip (0.00s)
    --- PASS: TestPurlSpecFixtures/bazel-test.json[2]parse (0.00s)
    --- PASS: TestPurlSpecFixtures/bazel-test.json[3]build (0.00s)
    --- PASS: TestPurlSpecFixtures/bazel-test.json[4]roundtrip (0.00s)
    --- PASS: TestPurlSpecFixtures/bazel-test.json[5]parse (0.00s)
    --- PASS: TestPurlSpecFixtures/bazel-test.json[6]build (0.00s)
    --- PASS: TestPurlSpecFixtures/bazel-test.json[7]roundtrip (0.00s)
    --- PASS: TestPurlSpecFixtures/bazel-test.json[8]parse (0.00s)
    --- PASS: TestPurlSpecFixtures/bazel-test.json[9]build (0.00s)
    --- PASS: TestPurlSpecFixtures/bazel-test.json[10]roundtrip (0.00s)
    --- PASS: TestPurlSpecFixtures/bazel-test.json[11]parse (0.00s)
    --- PASS: TestPurlSpecFixtures/bazel-test.json[12]build (0.00s)
    --- PASS: TestPurlSpecFixtures/bazel-test.json[13]roundtrip (0.00s)
    --- PASS: TestPurlSpecFixtures/bazel-test.json[14]parse (0.00s)
    --- PASS: TestPurlSpecFixtures/bazel-test.json[15]build (0.00s)
    --- PASS: TestPurlSpecFixtures/bazel-test.json[16]roundtrip (0.00s)
    --- PASS: TestPurlSpecFixtures/bazel-test.json[17]parse (0.00s)
    --- PASS: TestPurlSpecFixtures/bazel-test.json[18]build (0.00s)
    --- PASS: TestPurlSpecFixtures/bazel-test.json[19]roundtrip (0.00s)
    --- PASS: TestPurlSpecFixtures/bazel-test.json[20]parse (0.00s)
    --- PASS: TestPurlSpecFixtures/bazel-test.json[21]build (0.00s)
    --- PASS: TestPurlSpecFixtures/bitbucket-test.json[1]roundtrip (0.00s)
    --- PASS: TestPurlSpecFixtures/bitbucket-test.json[2]parse (0.00s)
    --- PASS: TestPurlSpecFixtures/bitbucket-test.json[3]roundtrip (0.00s)
    --- PASS: TestPurlSpecFixtures/bitbucket-test.json[4]build (0.00s)
    --- PASS: TestPurlSpecFixtures/bitbucket-test.json[5]parse (0.00s)
    --- PASS: TestPurlSpecFixtures/bitbucket-test.json[6]roundtrip (0.00s)
    --- PASS: TestPurlSpecFixtures/bitbucket-test.json[7]build (0.00s)
    --- PASS: TestPurlSpecFixtures/bitnami-test.json[1]parse (0.00s)
    --- PASS: TestPurlSpecFixtures/bitnami-test.json[2]roundtrip (0.00s)
    --- PASS: TestPurlSpecFixtures/bitnami-test.json[3]build (0.00s)
    --- PASS: TestPurlSpecFixtures/bitnami-test.json[4]parse (0.00s)
    --- PASS: TestPurlSpecFixtures/bitnami-test.json[5]roundtrip (0.00s)
    --- PASS: TestPurlSpecFixtures/bitnami-test.json[6]build (0.00s)
    --- PASS: TestPurlSpecFixtures/bitnami-test.json[7]parse (0.00s)
    --- PASS: TestPurlSpecFixtures/bitnami-test.json[8]roundtrip (0.00s)
    --- PASS: TestPurlSpecFixtures/bitnami-test.json[9]build (0.00s)
    --- PASS: TestPurlSpecFixtures/bitnami-test.json[10]parse (0.00s)
    --- PASS: TestPurlSpecFixtures/bitnami-test.json[11]roundtrip (0.00s)
    --- PASS: TestPurlSpecFixtures/bitnami-test.json[12]build (0.00s)
    --- PASS: TestPurlSpecFixtures/cargo-test.json[1]parse (0.00s)
    --- PASS: TestPurlSpecFixtures/cargo-test.json[2]roundtrip (0.00s)
    --- PASS: TestPurlSpecFixtures/cargo-test.json[3]build (0.00s)
    --- PASS: TestPurlSpecFixtures/cargo-test.json[4]parse (0.00s)
    --- PASS: TestPurlSpecFixtures/cargo-test.json[5]roundtrip (0.00s)
    --- PASS: TestPurlSpecFixtures/cargo-test.json[6]build (0.00s)
    --- PASS: TestPurlSpecFixtures/cargo-test.json[7]parse (0.00s)
    --- PASS: TestPurlSpecFixtures/cargo-test.json[8]roundtrip (0.00s)
    --- PASS: TestPurlSpecFixtures/cargo-test.json[9]build (0.00s)
    --- PASS: TestPurlSpecFixtures/cocoapods-test.json[1]parse (0.00s)
    --- PASS: TestPurlSpecFixtures/cocoapods-test.json[2]roundtrip (0.00s)
    --- PASS: TestPurlSpecFixtures/cocoapods-test.json[3]build (0.00s)
    --- PASS: TestPurlSpecFixtures/cocoapods-test.json[4]parse (0.00s)
    --- PASS: TestPurlSpecFixtures/cocoapods-test.json[5]roundtrip (0.00s)
    --- PASS: TestPurlSpecFixtures/cocoapods-test.json[6]build (0.00s)
    --- PASS: TestPurlSpecFixtures/cocoapods-test.json[7]parse (0.00s)
    --- PASS: TestPurlSpecFixtures/cocoapods-test.json[8]roundtrip (0.00s)
    --- PASS: TestPurlSpecFixtures/cocoapods-test.json[9]build (0.00s)
    --- PASS: TestPurlSpecFixtures/cocoapods-test.json[10]parse (0.00s)
    --- PASS: TestPurlSpecFixtures/cocoapods-test.json[11]roundtrip (0.00s)
    --- PASS: TestPurlSpecFixtures/cocoapods-test.json[12]build (0.00s)
    --- PASS: TestPurlSpecFixtures/composer-test.json[1]roundtrip (0.00s)
    --- PASS: TestPurlSpecFixtures/composer-test.json[2]parse (0.00s)
    --- PASS: TestPurlSpecFixtures/composer-test.json[3]roundtrip (0.00s)
    --- PASS: TestPurlSpecFixtures/composer-test.json[4]parse (0.00s)
    --- PASS: TestPurlSpecFixtures/composer-test.json[5]roundtrip (0.00s)
    --- PASS: TestPurlSpecFixtures/composer-test.json[6]build (0.00s)
    --- PASS: TestPurlSpecFixtures/composer-test.json[7]parse (0.00s)
    --- PASS: TestPurlSpecFixtures/composer-test.json[8]roundtrip (0.00s)
    --- PASS: TestPurlSpecFixtures/composer-test.json[9]build (0.00s)
    --- PASS: TestPurlSpecFixtures/conan-test.json[1]roundtrip (0.00s)
    --- PASS: TestPurlSpecFixtures/conan-test.json[2]parse (0.00s)
    --- PASS: TestPurlSpecFixtures/conan-test.json[3]roundtrip (0.00s)
    --- PASS: TestPurlSpecFixtures/conan-test.json[4]build (0.00s)
    --- PASS: TestPurlSpecFixtures/conan-test.json[5]roundtrip (0.00s)
    --- PASS: TestPurlSpecFixtures/conan-test.json[6]parse (0.00s)
    --- PASS: TestPurlSpecFixtures/conan-test.json[7]roundtrip (0.00s)
    --- PASS: TestPurlSpecFixtures/conan-test.json[8]build (0.00s)
    --- PASS: TestPurlSpecFixtures/conan-test.json[9]parse (0.00s)
    --- PASS: TestPurlSpecFixtures/conan-test.json[10]roundtrip (0.00s)
    --- PASS: TestPurlSpecFixtures/conan-test.json[11]build (0.00s)
    --- PASS: TestPurlSpecFixtures/conan-test.json[12]parse (0.00s)
    --- PASS: TestPurlSpecFixtures/conan-test.json[13]roundtrip (0.00s)
    --- PASS: TestPurlSpecFixtures/conan-test.json[14]build (0.00s)
    --- PASS: TestPurlSpecFixtures/conan-test.json[15]parse (0.00s)
    --- PASS: TestPurlSpecFixtures/conan-test.json[16]roundtrip (0.00s)
    --- PASS: TestPurlSpecFixtures/conan-test.json[17]build (0.00s)
    --- PASS: TestPurlSpecFixtures/conda-test.json[1]roundtrip (0.00s)
    --- PASS: TestPurlSpecFixtures/conda-test.json[2]parse (0.00s)
    --- PASS: TestPurlSpecFixtures/conda-test.json[3]roundtrip (0.00s)
    --- PASS: TestPurlSpecFixtures/conda-test.json[4]build (0.00s)
    --- PASS: TestPurlSpecFixtures/conda-test.json[5]parse (0.00s)
    --- PASS: TestPurlSpecFixtures/conda-test.json[6]roundtrip (0.00s)
    --- PASS: TestPurlSpecFixtures/conda-test.json[7]build (0.00s)
    --- PASS: TestPurlSpecFixtures/cpan-test.json[1]roundtrip (0.00s)
    --- PASS: TestPurlSpecFixtures/cpan-test.json[2]parse (0.00s)
    --- PASS: TestPurlSpecFixtures/cpan-test.json[3]roundtrip (0.00s)
    --- PASS: TestPurlSpecFixtures/cpan-test.json[4]build (0.00s)
    --- PASS: TestPurlSpecFixtures/cpan-test.json[5]build (0.00s)
    --- PASS: TestPurlSpecFixtures/cpan-test.json[6]parse (0.00s)
    --- PASS: TestPurlSpecFixtures/cpan-test.json[7]parse (0.00s)
    --- PASS: TestPurlSpecFixtures/cpan-test.json[8]build (0.00s)
    --- PASS: TestPurlSpecFixtures/cpan-test.json[9]roundtrip (0.00s)
    --- PASS: TestPurlSpecFixtures/cpan-test.json[10]build (0.00s)
    --- PASS: TestPurlSpecFixtures/cpan-test.json[11]parse (0.00s)
    --- PASS: TestPurlSpecFixtures/cpan-test.json[12]roundtrip (0.00s)
    --- PASS: TestPurlSpecFixtures/cpan-test.json[13]build (0.00s)
    --- PASS: TestPurlSpecFixtures/cpan-test.json[14]parse (0.00s)
    --- PASS: TestPurlSpecFixtures/cpan-test.json[15]roundtrip (0.00s)
    --- PASS: TestPurlSpecFixtures/cpan-test.json[16]build (0.00s)
    --- PASS: TestPurlSpecFixtures/cpan-test.json[17]roundtrip (0.00s)
    --- PASS: TestPurlSpecFixtures/cpan-test.json[18]parse (0.00s)
    --- PASS: TestPurlSpecFixtures/cpan-test.json[19]build (0.00s)
    --- PASS: TestPurlSpecFixtures/cran-test.json[1]roundtrip (0.00s)
    --- PASS: TestPurlSpecFixtures/cran-test.json[2]parse (0.00s)
    --- PASS: TestPurlSpecFixtures/cran-test.json[3]roundtrip (0.00s)
    --- PASS: TestPurlSpecFixtures/cran-test.json[4]build (0.00s)
    --- PASS: TestPurlSpecFixtures/cran-test.json[5]parse (0.00s)
    --- PASS: TestPurlSpecFixtures/cran-test.json[6]parse (0.00s)
    --- PASS: TestPurlSpecFixtures/cran-test.json[7]build (0.00s)
    --- PASS: TestPurlSpecFixtures/cran-test.json[8]parse (0.00s)
    --- PASS: TestPurlSpecFixtures/cran-test.json[9]roundtrip (0.00s)
    --- PASS: TestPurlSpecFixtures/cran-test.json[10]build (0.00s)
    --- PASS: TestPurlSpecFixtures/cran-test.json[11]parse (0.00s)
    --- PASS: TestPurlSpecFixtures/cran-test.json[12]roundtrip (0.00s)
    --- PASS: TestPurlSpecFixtures/cran-test.json[13]build (0.00s)
    --- PASS: TestPurlSpecFixtures/cran-test.json[14]parse (0.00s)
    --- PASS: TestPurlSpecFixtures/cran-test.json[15]roundtrip (0.00s)
    --- PASS: TestPurlSpecFixtures/cran-test.json[16]build (0.00s)
    --- PASS: TestPurlSpecFixtures/deb-test.json[1]roundtrip (0.00s)
    --- PASS: TestPurlSpecFixtures/deb-test.json[2]parse (0.00s)
    --- PASS: TestPurlSpecFixtures/deb-test.json[3]roundtrip (0.00s)
    --- PASS: TestPurlSpecFixtures/deb-test.json[4]build (0.00s)
    --- PASS: TestPurlSpecFixtures/deb-test.json[5]parse (0.00s)
    --- PASS: TestPurlSpecFixtures/deb-test.json[6]roundtrip (0.00s)
    --- PASS: TestPurlSpecFixtures/deb-test.json[7]build (0.00s)
    --- PASS: TestPurlSpecFixtures/deb-test.json[8]parse (0.00s)
    --- PASS: TestPurlSpecFixtures/deb-test.json[9]roundtrip (0.00s)
    --- PASS: TestPurlSpecFixtures/deb-test.json[10]build (0.00s)
    --- PASS: TestPurlSpecFixtures/deb-test.json[11]parse (0.00s)
    --- PASS: TestPurlSpecFixtures/deb-test.json[12]roundtrip (0.00s)
    --- PASS: TestPurlSpecFixtures/deb-test.json[13]build (0.00s)
    --- PASS: TestPurlSpecFixtures/deb-test.json[14]parse (0.00s)
    --- PASS: TestPurlSpecFixtures/deb-test.json[15]roundtrip (0.00s)
    --- PASS: TestPurlSpecFixtures/deb-test.json[16]build (0.00s)
    --- PASS: TestPurlSpecFixtures/deb-test.json[17]parse (0.00s)
    --- PASS: TestPurlSpecFixtures/deb-test.json[18]roundtrip (0.00s)
    --- PASS: TestPurlSpecFixtures/deb-test.json[19]build (0.00s)
    --- PASS: TestPurlSpecFixtures/docker-test.json[1]roundtrip (0.00s)
    --- PASS: TestPurlSpecFixtures/docker-test.json[2]parse (0.00s)
    --- PASS: TestPurlSpecFixtures/docker-test.json[3]roundtrip (0.00s)
    --- PASS: TestPurlSpecFixtures/docker-test.json[4]build (0.00s)
    --- PASS: TestPurlSpecFixtures/docker-test.json[5]parse (0.00s)
    --- PASS: TestPurlSpecFixtures/docker-test.json[6]roundtrip (0.00s)
    --- PASS: TestPurlSpecFixtures/docker-test.json[7]build (0.00s)
    --- PASS: TestPurlSpecFixtures/docker-test.json[8]parse (0.00s)
    --- PASS: TestPurlSpecFixtures/docker-test.json[9]roundtrip (0.00s)
    --- PASS: TestPurlSpecFixtures/docker-test.json[10]build (0.00s)
    --- PASS: TestPurlSpecFixtures/docker-test.json[11]parse (0.00s)
    --- PASS: TestPurlSpecFixtures/docker-test.json[12]roundtrip (0.00s)
    --- PASS: TestPurlSpecFixtures/docker-test.json[13]build (0.00s)
    --- PASS: TestPurlSpecFixtures/gem-test.json[1]roundtrip (0.00s)
    --- PASS: TestPurlSpecFixtures/gem-test.json[2]parse (0.00s)
    --- PASS: TestPurlSpecFixtures/gem-test.json[3]roundtrip (0.00s)
    --- PASS: TestPurlSpecFixtures/gem-test.json[4]build (0.00s)
    --- PASS: TestPurlSpecFixtures/gem-test.json[5]parse (0.00s)
    --- PASS: TestPurlSpecFixtures/gem-test.json[6]roundtrip (0.00s)
    --- PASS: TestPurlSpecFixtures/gem-test.json[7]build (0.00s)
    --- PASS: TestPurlSpecFixtures/gem-test.json[8]parse (0.00s)
    --- PASS: TestPurlSpecFixtures/gem-test.json[9]roundtrip (0.00s)
    --- PASS: TestPurlSpecFixtures/gem-test.json[10]build (0.00s)
    --- PASS: TestPurlSpecFixtures/generic-test.json[1]parse (0.00s)
    --- PASS: TestPurlSpecFixtures/generic-test.json[2]roundtrip (0.00s)
    --- PASS: TestPurlSpecFixtures/generic-test.json[3]build (0.00s)
    --- PASS: TestPurlSpecFixtures/generic-test.json[4]parse (0.00s)
    --- PASS: TestPurlSpecFixtures/generic-test.json[5]roundtrip (0.00s)
    --- PASS: TestPurlSpecFixtures/generic-test.json[6]build (0.00s)
    --- PASS: TestPurlSpecFixtures/generic-test.json[7]parse (0.00s)
    --- PASS: TestPurlSpecFixtures/generic-test.json[8]roundtrip (0.00s)
    --- PASS: TestPurlSpecFixtures/generic-test.json[9]build (0.00s)
    --- PASS: TestPurlSpecFixtures/github-test.json[1]roundtrip (0.00s)
    --- PASS: TestPurlSpecFixtures/github-test.json[2]parse (0.00s)
    --- PASS: TestPurlSpecFixtures/github-test.json[3]roundtrip (0.00s)
    --- PASS: TestPurlSpecFixtures/github-test.json[4]build (0.00s)
    --- PASS: TestPurlSpecFixtures/github-test.json[5]parse (0.00s)
    --- PASS: TestPurlSpecFixtures/github-test.json[6]roundtrip (0.00s)
    --- PASS: TestPurlSpecFixtures/github-test.json[7]build (0.00s)
    --- PASS: TestPurlSpecFixtures/github-test.json[8]parse (0.00s)
    --- PASS: TestPurlSpecFixtures/github-test.json[9]roundtrip (0.00s)
    --- PASS: TestPurlSpecFixtures/github-test.json[10]build (0.00s)
    --- PASS: TestPurlSpecFixtures/golang-test.json[1]roundtrip (0.00s)
    --- PASS: TestPurlSpecFixtures/golang-test.json[2]parse (0.00s)
    --- PASS: TestPurlSpecFixtures/golang-test.json[3]roundtrip (0.00s)
    --- PASS: TestPurlSpecFixtures/golang-test.json[4]build (0.00s)
    --- PASS: TestPurlSpecFixtures/golang-test.json[5]roundtrip (0.00s)
    --- PASS: TestPurlSpecFixtures/golang-test.json[6]parse (0.00s)
    --- PASS: TestPurlSpecFixtures/golang-test.json[7]roundtrip (0.00s)
    --- PASS: TestPurlSpecFixtures/golang-test.json[8]build (0.00s)
    --- PASS: TestPurlSpecFixtures/golang-test.json[9]parse (0.00s)
    --- PASS: TestPurlSpecFixtures/golang-test.json[10]roundtrip (0.00s)
    --- PASS: TestPurlSpecFixtures/golang-test.json[11]build (0.00s)
    --- PASS: TestPurlSpecFixtures/golang-test.json[12]parse (0.00s)
    --- PASS: TestPurlSpecFixtures/golang-test.json[13]roundtrip (0.00s)
    --- PASS: TestPurlSpecFixtures/golang-test.json[14]build (0.00s)
    --- PASS: TestPurlSpecFixtures/golang-test.json[15]parse (0.00s)
    --- PASS: TestPurlSpecFixtures/golang-test.json[16]roundtrip (0.00s)
    --- PASS: TestPurlSpecFixtures/golang-test.json[17]build (0.00s)
    --- PASS: TestPurlSpecFixtures/hackage-test.json[1]roundtrip (0.00s)
    --- PASS: TestPurlSpecFixtures/hackage-test.json[2]parse (0.00s)
    --- PASS: TestPurlSpecFixtures/hackage-test.json[3]roundtrip (0.00s)
    --- PASS: TestPurlSpecFixtures/hackage-test.json[4]build (0.00s)
    --- PASS: TestPurlSpecFixtures/hackage-test.json[5]parse (0.00s)
    --- PASS: TestPurlSpecFixtures/hackage-test.json[6]parse (0.00s)
    --- PASS: TestPurlSpecFixtures/hackage-test.json[7]build (0.00s)
    --- PASS: TestPurlSpecFixtures/hackage-test.json[8]parse (0.00s)
    --- PASS: TestPurlSpecFixtures/hackage-test.json[9]roundtrip (0.00s)
    --- PASS: TestPurlSpecFixtures/hackage-test.json[10]build (0.00s)
    --- PASS: TestPurlSpecFixtures/hackage-test.json[11]parse (0.00s)
    --- PASS: TestPurlSpecFixtures/hackage-test.json[12]roundtrip (0.00s)
    --- PASS: TestPurlSpecFixtures/hackage-test.json[13]build (0.00s)
    --- PASS: TestPurlSpecFixtures/hackage-test.json[14]parse (0.00s)
    --- PASS: TestPurlSpecFixtures/hackage-test.json[15]roundtrip (0.00s)
    --- PASS: TestPurlSpecFixtures/hackage-test.json[16]build (0.00s)
    --- PASS: TestPurlSpecFixtures/hex-test.json[1]parse (0.00s)
    --- PASS: TestPurlSpecFixtures/hex-test.json[2]roundtrip (0.00s)
    --- PASS: TestPurlSpecFixtures/hex-test.json[3]build (0.00s)
    --- PASS: TestPurlSpecFixtures/hex-test.json[4]parse (0.00s)
    --- PASS: TestPurlSpecFixtures/hex-test.json[5]roundtrip (0.00s)
    --- PASS: TestPurlSpecFixtures/hex-test.json[6]build (0.00s)
    --- PASS: TestPurlSpecFixtures/hex-test.json[7]parse (0.00s)
    --- PASS: TestPurlSpecFixtures/hex-test.json[8]roundtrip (0.00s)
    --- PASS: TestPurlSpecFixtures/hex-test.json[9]build (0.00s)
    --- PASS: TestPurlSpecFixtures/hex-test.json[10]parse (0.00s)
    --- PASS: TestPurlSpecFixtures/hex-test.json[11]roundtrip (0.00s)
    --- PASS: TestPurlSpecFixtures/hex-test.json[12]build (0.00s)
    --- PASS: TestPurlSpecFixtures/huggingface-test.json[1]roundtrip (0.00s)
    --- PASS: TestPurlSpecFixtures/huggingface-test.json[2]parse (0.00s)
    --- PASS: TestPurlSpecFixtures/huggingface-test.json[3]roundtrip (0.00s)
    --- PASS: TestPurlSpecFixtures/huggingface-test.json[4]build (0.00s)
    --- PASS: TestPurlSpecFixtures/huggingface-test.json[5]roundtrip (0.00s)
    --- PASS: TestPurlSpecFixtures/huggingface-test.json[6]parse (0.00s)
    --- PASS: TestPurlSpecFixtures/huggingface-test.json[7]roundtrip (0.00s)
    --- PASS: TestPurlSpecFixtures/huggingface-test.json[8]build (0.00s)
    --- PASS: TestPurlSpecFixtures/huggingface-test.json[9]roundtrip (0.00s)
    --- PASS: TestPurlSpecFixtures/huggingface-test.json[10]parse (0.00s)
    --- PASS: TestPurlSpecFixtures/huggingface-test.json[11]roundtrip (0.00s)
    --- PASS: TestPurlSpecFixtures/huggingface-test.json[12]build (0.00s)
    --- PASS: TestPurlSpecFixtures/huggingface-test.json[13]parse (0.00s)
    --- PASS: TestPurlSpecFixtures/huggingface-test.json[14]roundtrip (0.00s)
    --- PASS: TestPurlSpecFixtures/huggingface-test.json[15]build (0.00s)
    --- PASS: TestPurlSpecFixtures/huggingface-test.json[16]parse (0.00s)
    --- PASS: TestPurlSpecFixtures/huggingface-test.json[17]roundtrip (0.00s)
    --- PASS: TestPurlSpecFixtures/huggingface-test.json[18]build (0.00s)
    --- PASS: TestPurlSpecFixtures/julia-test.json[1]parse (0.00s)
    --- PASS: TestPurlSpecFixtures/julia-test.json[2]parse (0.00s)
    --- PASS: TestPurlSpecFixtures/julia-test.json[3]parse (0.00s)
    --- PASS: TestPurlSpecFixtures/julia-test.json[4]parse (0.00s)
    --- PASS: TestPurlSpecFixtures/julia-test.json[5]build (0.00s)
    --- PASS: TestPurlSpecFixtures/julia-test.json[6]build (0.00s)
    --- PASS: TestPurlSpecFixtures/julia-test.json[7]roundtrip (0.00s)
    --- PASS: TestPurlSpecFixtures/julia-test.json[8]roundtrip (0.00s)
    --- PASS: TestPurlSpecFixtures/julia-test.json[9]parse (0.00s)
    --- PASS: TestPurlSpecFixtures/julia-test.json[10]parse (0.00s)
    --- PASS: TestPurlSpecFixtures/julia-test.json[11]build (0.00s)
    --- PASS: TestPurlSpecFixtures/julia-test.json[12]build (0.00s)
    --- PASS: TestPurlSpecFixtures/julia-test.json[13]parse (0.00s)
    --- PASS: TestPurlSpecFixtures/luarocks-test.json[1]parse (0.00s)
    --- PASS: TestPurlSpecFixtures/luarocks-test.json[2]roundtrip (0.00s)
    --- PASS: TestPurlSpecFixtures/luarocks-test.json[3]build (0.00s)
    --- PASS: TestPurlSpecFixtures/luarocks-test.json[4]parse (0.00s)
    --- PASS: TestPurlSpecFixtures/luarocks-test.json[5]roundtrip (0.00s)
    --- PASS: TestPurlSpecFixtures/luarocks-test.json[6]build (0.00s)
    --- PASS: TestPurlSpecFixtures/luarocks-test.json[7]parse (0.00s)
    --- PASS: TestPurlSpecFixtures/luarocks-test.json[8]roundtrip (0.00s)
    --- PASS: TestPurlSpecFixtures/luarocks-test.json[9]build (0.00s)
    --- PASS: TestPurlSpecFixtures/maven-test.json[1]roundtrip (0.00s)
    --- PASS: TestPurlSpecFixtures/maven-test.json[2]parse (0.00s)
    --- PASS: TestPurlSpecFixtures/maven-test.json[3]roundtrip (0.00s)
    --- PASS: TestPurlSpecFixtures/maven-test.json[4]build (0.00s)
    --- PASS: TestPurlSpecFixtures/maven-test.json[5]roundtrip (0.00s)
    --- PASS: TestPurlSpecFixtures/maven-test.json[6]parse (0.00s)
    --- PASS: TestPurlSpecFixtures/maven-test.json[7]roundtrip (0.00s)
    --- PASS: TestPurlSpecFixtures/maven-test.json[8]build (0.00s)
    --- PASS: TestPurlSpecFixtures/maven-test.json[9]roundtrip (0.00s)
    --- PASS: TestPurlSpecFixtures/maven-test.json[10]parse (0.00s)
    --- PASS: TestPurlSpecFixtures/maven-test.json[11]roundtrip (0.00s)
    --- PASS: TestPurlSpecFixtures/maven-test.json[12]build (0.00s)
    --- PASS: TestPurlSpecFixtures/maven-test.json[13]roundtrip (0.00s)
    --- PASS: TestPurlSpecFixtures/maven-test.json[14]parse (0.00s)
    --- PASS: TestPurlSpecFixtures/maven-test.json[15]roundtrip (0.00s)
    --- PASS: TestPurlSpecFixtures/maven-test.json[16]build (0.00s)
    --- PASS: TestPurlSpecFixtures/maven-test.json[17]roundtrip (0.00s)
    --- PASS: TestPurlSpecFixtures/maven-test.json[18]parse (0.00s)
    --- PASS: TestPurlSpecFixtures/maven-test.json[19]roundtrip (0.00s)
    --- PASS: TestPurlSpecFixtures/maven-test.json[20]build (0.00s)
    --- PASS: TestPurlSpecFixtures/maven-test.json[21]roundtrip (0.00s)
    --- PASS: TestPurlSpecFixtures/maven-test.json[22]parse (0.00s)
    --- PASS: TestPurlSpecFixtures/maven-test.json[23]roundtrip (0.00s)
    --- PASS: TestPurlSpecFixtures/maven-test.json[24]build (0.00s)
    --- PASS: TestPurlSpecFixtures/maven-test.json[25]roundtrip (0.00s)
    --- PASS: TestPurlSpecFixtures/maven-test.json[26]parse (0.00s)
    --- PASS: TestPurlSpecFixtures/maven-test.json[27]roundtrip (0.00s)
    --- PASS: TestPurlSpecFixtures/maven-test.json[28]build (0.00s)
    --- PASS: TestPurlSpecFixtures/maven-test.json[29]roundtrip (0.00s)
    --- PASS: TestPurlSpecFixtures/maven-test.json[30]parse (0.00s)
    --- PASS: TestPurlSpecFixtures/maven-test.json[31]roundtrip (0.00s)
    --- PASS: TestPurlSpecFixtures/maven-test.json[32]build (0.00s)
    --- PASS: TestPurlSpecFixtures/maven-test.json[33]roundtrip (0.00s)
    --- PASS: TestPurlSpecFixtures/maven-test.json[34]parse (0.00s)
    --- PASS: TestPurlSpecFixtures/maven-test.json[35]roundtrip (0.00s)
    --- PASS: TestPurlSpecFixtures/maven-test.json[36]build (0.00s)
    --- PASS: TestPurlSpecFixtures/maven-test.json[37]roundtrip (0.00s)
    --- PASS: TestPurlSpecFixtures/maven-test.json[38]parse (0.00s)
    --- PASS: TestPurlSpecFixtures/maven-test.json[39]roundtrip (0.00s)
    --- PASS: TestPurlSpecFixtures/maven-test.json[40]build (0.00s)
    --- PASS: TestPurlSpecFixtures/maven-test.json[41]parse (0.00s)
    --- PASS: TestPurlSpecFixtures/maven-test.json[42]roundtrip (0.00s)
    --- PASS: TestPurlSpecFixtures/maven-test.json[43]build (0.00s)
    --- PASS: TestPurlSpecFixtures/maven-test.json[44]parse (0.00s)
    --- PASS: TestPurlSpecFixtures/maven-test.json[45]roundtrip (0.00s)
    --- PASS: TestPurlSpecFixtures/maven-test.json[46]build (0.00s)
    --- PASS: TestPurlSpecFixtures/maven-test.json[47]parse (0.00s)
    --- PASS: TestPurlSpecFixtures/maven-test.json[48]roundtrip (0.00s)
    --- PASS: TestPurlSpecFixtures/maven-test.json[49]build (0.00s)
    --- PASS: TestPurlSpecFixtures/maven-test.json[50]parse (0.00s)
    --- PASS: TestPurlSpecFixtures/maven-test.json[51]roundtrip (0.00s)
    --- PASS: TestPurlSpecFixtures/maven-test.json[52]build (0.00s)
    --- PASS: TestPurlSpecFixtures/maven-test.json[53]parse (0.00s)
    --- PASS: TestPurlSpecFixtures/maven-test.json[54]roundtrip (0.00s)
    --- PASS: TestPurlSpecFixtures/maven-test.json[55]build (0.00s)
    --- PASS: TestPurlSpecFixtures/maven-test.json[56]parse (0.00s)
    --- PASS: TestPurlSpecFixtures/maven-test.json[57]roundtrip (0.00s)
    --- PASS: TestPurlSpecFixtures/maven-test.json[58]build (0.00s)
    --- PASS: TestPurlSpecFixtures/maven-test.json[59]parse (0.00s)
    --- PASS: TestPurlSpecFixtures/maven-test.json[60]roundtrip (0.00s)
    --- PASS: TestPurlSpecFixtures/maven-test.json[61]build (0.00s)
    --- PASS: TestPurlSpecFixtures/mlflow-test.json[1]roundtrip (0.00s)
    --- PASS: TestPurlSpecFixtures/mlflow-test.json[2]parse (0.00s)
    --- PASS: TestPurlSpecFixtures/mlflow-test.json[3]roundtrip (0.00s)
    --- PASS: TestPurlSpecFixtures/mlflow-test.json[4]build (0.00s)
    --- PASS: TestPurlSpecFixtures/mlflow-test.json[5]roundtrip (0.00s)
    --- PASS: TestPurlSpecFixtures/mlflow-test.json[6]parse (0.00s)
    --- PASS: TestPurlSpecFixtures/mlflow-test.json[7]roundtrip (0.00s)
    --- PASS: TestPurlSpecFixtures/mlflow-test.json[8]build (0.00s)
    --- PASS: TestPurlSpecFixtures/mlflow-test.json[9]roundtrip (0.00s)
    --- PASS: TestPurlSpecFixtures/mlflow-test.json[10]parse (0.00s)
    --- PASS: TestPurlSpecFixtures/mlflow-test.json[11]roundtrip (0.00s)
    --- PASS: TestPurlSpecFixtures/mlflow-test.json[12]build (0.00s)
    --- PASS: TestPurlSpecFixtures/mlflow-test.json[13]parse (0.00s)
    --- PASS: TestPurlSpecFixtures/mlflow-test.json[14]roundtrip (0.00s)
    --- PASS: TestPurlSpecFixtures/mlflow-test.json[15]build (0.00s)
    --- PASS: TestPurlSpecFixtures/mlflow-test.json[16]parse (0.00s)
    --- PASS: TestPurlSpecFixtures/mlflow-test.json[17]roundtrip (0.00s)
    --- PASS: TestPurlSpecFixtures/mlflow-test.json[18]build (0.00s)
    --- PASS: TestPurlSpecFixtures/npm-test.json[1]roundtrip (0.00s)
    --- PASS: TestPurlSpecFixtures/npm-test.json[2]parse (0.00s)
    --- PASS: TestPurlSpecFixtures/npm-test.json[3]roundtrip (0.00s)
    --- PASS: TestPurlSpecFixtures/npm-test.json[4]build (0.00s)
    --- PASS: TestPurlSpecFixtures/npm-test.json[5]parse (0.00s)
    --- PASS: TestPurlSpecFixtures/npm-test.json[6]roundtrip (0.00s)
    --- PASS: TestPurlSpecFixtures/npm-test.json[7]build (0.00s)
    --- PASS: TestPurlSpecFixtures/npm-test.json[8]parse (0.00s)
    --- PASS: TestPurlSpecFixtures/npm-test.json[9]roundtrip (0.00s)
    --- PASS: TestPurlSpecFixtures/npm-test.json[10]build (0.00s)
    --- PASS: TestPurlSpecFixtures/npm-test.json[11]parse (0.00s)
    --- PASS: TestPurlSpecFixtures/npm-test.json[12]roundtrip (0.00s)
    --- PASS: TestPurlSpecFixtures/npm-test.json[13]build (0.00s)
    --- PASS: TestPurlSpecFixtures/npm-test.json[14]roundtrip (0.00s)
    --- PASS: TestPurlSpecFixtures/npm-test.json[15]parse (0.00s)
    --- PASS: TestPurlSpecFixtures/npm-test.json[16]parse (0.00s)
    --- PASS: TestPurlSpecFixtures/npm-test.json[17]roundtrip (0.00s)
    --- PASS: TestPurlSpecFixtures/nuget-test.json[1]roundtrip (0.00s)
    --- PASS: TestPurlSpecFixtures/nuget-test.json[2]parse (0.00s)
    --- PASS: TestPurlSpecFixtures/nuget-test.json[3]roundtrip (0.00s)
    --- PASS: TestPurlSpecFixtures/nuget-test.json[4]build (0.00s)
    --- PASS: TestPurlSpecFixtures/nuget-test.json[5]parse (0.00s)
    --- PASS: TestPurlSpecFixtures/nuget-test.json[6]roundtrip (0.00s)
    --- PASS: TestPurlSpecFixtures/nuget-test.json[7]build (0.00s)
    --- PASS: TestPurlSpecFixtures/oci-test.json[1]parse (0.00s)
    --- PASS: TestPurlSpecFixtures/oci-test.json[2]roundtrip (0.00s)
    --- PASS: TestPurlSpecFixtures/oci-test.json[3]build (0.00s)
    --- PASS: TestPurlSpecFixtures/oci-test.json[4]parse (0.00s)
    --- PASS: TestPurlSpecFixtures/oci-test.json[5]roundtrip (0.00s)
    --- PASS: TestPurlSpecFixtures/oci-test.json[6]build (0.00s)
    --- PASS: TestPurlSpecFixtures/oci-test.json[7]parse (0.00s)
    --- PASS: TestPurlSpecFixtures/oci-test.json[8]roundtrip (0.00s)
    --- PASS: TestPurlSpecFixtures/oci-test.json[9]build (0.00s)
    --- PASS: TestPurlSpecFixtures/oci-test.json[10]parse (0.00s)
    --- PASS: TestPurlSpecFixtures/oci-test.json[11]roundtrip (0.00s)
    --- PASS: TestPurlSpecFixtures/oci-test.json[12]build (0.00s)
    --- PASS: TestPurlSpecFixtures/pub-test.json[1]parse (0.00s)
    --- PASS: TestPurlSpecFixtures/pub-test.json[2]roundtrip (0.00s)
    --- PASS: TestPurlSpecFixtures/pub-test.json[3]build (0.00s)
    --- PASS: TestPurlSpecFixtures/pub-test.json[4]parse (0.00s)
    --- PASS: TestPurlSpecFixtures/pub-test.json[5]roundtrip (0.00s)
    --- PASS: TestPurlSpecFixtures/pub-test.json[6]build (0.00s)
    --- PASS: TestPurlSpecFixtures/pypi-test.json[1]roundtrip (0.00s)
    --- PASS: TestPurlSpecFixtures/pypi-test.json[2]parse (0.00s)
    --- PASS: TestPurlSpecFixtures/pypi-test.json[3]roundtrip (0.00s)
    --- PASS: TestPurlSpecFixtures/pypi-test.json[4]build (0.00s)
    --- PASS: TestPurlSpecFixtures/pypi-test.json[5]parse (0.00s)
    --- PASS: TestPurlSpecFixtures/pypi-test.json[6]roundtrip (0.00s)
    --- PASS: TestPurlSpecFixtures/pypi-test.json[7]build (0.00s)
    --- PASS: TestPurlSpecFixtures/pypi-test.json[8]parse (0.00s)
    --- PASS: TestPurlSpecFixtures/pypi-test.json[9]roundtrip (0.00s)
    --- PASS: TestPurlSpecFixtures/pypi-test.json[10]build (0.00s)
    --- PASS: TestPurlSpecFixtures/pypi-test.json[11]parse (0.00s)
    --- PASS: TestPurlSpecFixtures/pypi-test.json[12]roundtrip (0.00s)
    --- PASS: TestPurlSpecFixtures/pypi-test.json[13]build (0.00s)
    --- PASS: TestPurlSpecFixtures/pypi-test.json[14]parse (0.00s)
    --- PASS: TestPurlSpecFixtures/pypi-test.json[15]roundtrip (0.00s)
    --- PASS: TestPurlSpecFixtures/pypi-test.json[16]build (0.00s)
    --- PASS: TestPurlSpecFixtures/qpkg-test.json[1]parse (0.00s)
    --- PASS: TestPurlSpecFixtures/qpkg-test.json[2]roundtrip (0.00s)
    --- PASS: TestPurlSpecFixtures/qpkg-test.json[3]build (0.00s)
    --- PASS: TestPurlSpecFixtures/qpkg-test.json[4]parse (0.00s)
    --- PASS: TestPurlSpecFixtures/qpkg-test.json[5]roundtrip (0.00s)
    --- PASS: TestPurlSpecFixtures/qpkg-test.json[6]build (0.00s)
    --- PASS: TestPurlSpecFixtures/rpm-test.json[1]roundtrip (0.00s)
    --- PASS: TestPurlSpecFixtures/rpm-test.json[2]parse (0.00s)
    --- PASS: TestPurlSpecFixtures/rpm-test.json[3]roundtrip (0.00s)
    --- PASS: TestPurlSpecFixtures/rpm-test.json[4]build (0.00s)
    --- PASS: TestPurlSpecFixtures/rpm-test.json[5]parse (0.00s)
    --- PASS: TestPurlSpecFixtures/rpm-test.json[6]roundtrip (0.00s)
    --- PASS: TestPurlSpecFixtures/rpm-test.json[7]build (0.00s)
    --- PASS: TestPurlSpecFixtures/rpm-test.json[8]parse (0.00s)
    --- PASS: TestPurlSpecFixtures/rpm-test.json[9]roundtrip (0.00s)
    --- PASS: TestPurlSpecFixtures/rpm-test.json[10]build (0.00s)
    --- PASS: TestPurlSpecFixtures/swid-test.json[1]parse (0.00s)
    --- PASS: TestPurlSpecFixtures/swid-test.json[2]roundtrip (0.00s)
    --- PASS: TestPurlSpecFixtures/swid-test.json[3]build (0.00s)
    --- PASS: TestPurlSpecFixtures/swid-test.json[4]parse (0.00s)
    --- PASS: TestPurlSpecFixtures/swid-test.json[5]roundtrip (0.00s)
    --- PASS: TestPurlSpecFixtures/swid-test.json[6]build (0.00s)
    --- PASS: TestPurlSpecFixtures/swid-test.json[7]parse (0.00s)
    --- PASS: TestPurlSpecFixtures/swid-test.json[8]roundtrip (0.00s)
    --- PASS: TestPurlSpecFixtures/swid-test.json[9]build (0.00s)
    --- PASS: TestPurlSpecFixtures/swift-test.json[1]roundtrip (0.00s)
    --- PASS: TestPurlSpecFixtures/swift-test.json[2]parse (0.00s)
    --- PASS: TestPurlSpecFixtures/swift-test.json[3]roundtrip (0.00s)
    --- PASS: TestPurlSpecFixtures/swift-test.json[4]build (0.00s)
    --- PASS: TestPurlSpecFixtures/swift-test.json[5]parse (0.00s)
    --- PASS: TestPurlSpecFixtures/swift-test.json[6]parse (0.00s)
    --- PASS: TestPurlSpecFixtures/swift-test.json[7]build (0.00s)
    --- PASS: TestPurlSpecFixtures/swift-test.json[8]parse (0.00s)
    --- PASS: TestPurlSpecFixtures/swift-test.json[9]parse (0.00s)
    --- PASS: TestPurlSpecFixtures/swift-test.json[10]build (0.00s)
    --- PASS: TestPurlSpecFixtures/swift-test.json[11]parse (0.00s)
    --- PASS: TestPurlSpecFixtures/swift-test.json[12]parse (0.00s)
    --- PASS: TestPurlSpecFixtures/swift-test.json[13]build (0.00s)
    --- PASS: TestPurlSpecFixtures/swift-test.json[14]parse (0.00s)
    --- PASS: TestPurlSpecFixtures/swift-test.json[15]roundtrip (0.00s)
    --- PASS: TestPurlSpecFixtures/swift-test.json[16]build (0.00s)
    --- PASS: TestPurlSpecFixtures/swift-test.json[17]parse (0.00s)
    --- PASS: TestPurlSpecFixtures/swift-test.json[18]roundtrip (0.00s)
    --- PASS: TestPurlSpecFixtures/swift-test.json[19]build (0.00s)
=== RUN   TestQualifiersMapConversion
--- PASS: TestQualifiersMapConversion (0.00s)
=== RUN   TestNameEscaping
=== RUN   TestNameEscaping/abc
=== RUN   TestNameEscaping/ab/c
--- PASS: TestNameEscaping (0.00s)
    --- PASS: TestNameEscaping/abc (0.00s)
    --- PASS: TestNameEscaping/ab/c (0.00s)
=== RUN   TestQualifierMissingEqual
--- PASS: TestQualifierMissingEqual (0.00s)
=== RUN   TestNormalize
=== RUN   TestNormalize/type_is_case_insensitive
=== RUN   TestNormalize/type_is_manditory
=== RUN   TestNormalize/leading_and_traling_/_on_namespace_are_trimmed
=== RUN   TestNormalize/qualifiers_with_empty_values_are_removed
=== RUN   TestNormalize/qualifiers_are_sorted_by_key
=== RUN   TestNormalize/duplicate_keys_are_invalid
=== RUN   TestNormalize/keys_are_made_lower_case
=== RUN   TestNormalize/name_is_required
=== RUN   TestNormalize/leading_and_traling_/_on_subpath_are_trimmed
=== RUN   TestNormalize/'.'_is_an_invalid_subpath_segment
=== RUN   TestNormalize/'..'_is_an_invalid_subpath_segment
=== RUN   TestNormalize/'./'_is_a_valid_subpath_prefix
=== RUN   TestNormalize/'../'_is_a_valid_subpath_prefix
=== RUN   TestNormalize/known_type_namespace_adjustments
=== RUN   TestNormalize/known_type_name_adjustments
=== RUN   TestNormalize/known_type_version_adjustments
--- PASS: TestNormalize (0.00s)
    --- PASS: TestNormalize/type_is_case_insensitive (0.00s)
    --- PASS: TestNormalize/type_is_manditory (0.00s)
    --- PASS: TestNormalize/leading_and_traling_/_on_namespace_are_trimmed (0.00s)
    --- PASS: TestNormalize/qualifiers_with_empty_values_are_removed (0.00s)
    --- PASS: TestNormalize/qualifiers_are_sorted_by_key (0.00s)
    --- PASS: TestNormalize/duplicate_keys_are_invalid (0.00s)
    --- PASS: TestNormalize/keys_are_made_lower_case (0.00s)
    --- PASS: TestNormalize/name_is_required (0.00s)
    --- PASS: TestNormalize/leading_and_traling_/_on_subpath_are_trimmed (0.00s)
    --- PASS: TestNormalize/'.'_is_an_invalid_subpath_segment (0.00s)
    --- PASS: TestNormalize/'..'_is_an_invalid_subpath_segment (0.00s)
    --- PASS: TestNormalize/'./'_is_a_valid_subpath_prefix (0.00s)
    --- PASS: TestNormalize/'../'_is_a_valid_subpath_prefix (0.00s)
    --- PASS: TestNormalize/known_type_namespace_adjustments (0.00s)
    --- PASS: TestNormalize/known_type_name_adjustments (0.00s)
    --- PASS: TestNormalize/known_type_version_adjustments (0.00s)
=== RUN   FuzzFromString
=== RUN   FuzzFromString/771e938e4458e983a736261a702e27c7a414fd660a15b63034f290b146d2f217
0=== RUN   FuzzFromString/d0a861fe9b7c443af2b649e08753442111b630dd29fcd570543db3f9351158aa
?A--- PASS: FuzzFromString (0.00s)
    --- PASS: FuzzFromString/771e938e4458e983a736261a702e27c7a414fd660a15b63034f290b146d2f217 (0.00s)
    --- PASS: FuzzFromString/d0a861fe9b7c443af2b649e08753442111b630dd29fcd570543db3f9351158aa (0.00s)
PASS
coverage: 90.1% of statements
ok  	github.com/package-url/packageurl-go	(cached)	coverage: 90.1% of statements
	github.com/package-url/packageurl-go/examples/roundtrip		coverage: 0.0% of statements

petergardfjall avatar Dec 03 '25 08:12 petergardfjall

I think this can be merged now. It includes #80.

petergardfjall avatar Dec 03 '25 08:12 petergardfjall

Unit tests are failing. Can you take a look?

shibumi avatar Dec 03 '25 10:12 shibumi

Unit tests are failing. Can you take a look?

Yes, I tried to explain that in https://github.com/package-url/packageurl-go/pull/83#issuecomment-3605570373 but maybe it went unnoticed in the wall of text. :sweat_smile:

There are still a dozen failing tests which are due to bad testcases upstream in the purl-spec. PRs are opened to fix (mostly remove) those:

  • https://github.com/package-url/purl-spec/pull/735 (fixes three invalid cran-test cases)
  • https://github.com/package-url/purl-spec/pull/733 (fixes three invalid conan-test cases)
  • https://github.com/package-url/purl-spec/pull/734 (fixes three invalid conan-test cases)
  • https://github.com/package-url/purl-spec/pull/730.

Until that happens these tests will keep failing.

petergardfjall avatar Dec 03 '25 10:12 petergardfjall

I approved all purl-spec PRs, but I am sadly not a purl-spec maintainer. This means, you will have to reach out to @pombredanne or someone else

shibumi avatar Dec 03 '25 10:12 shibumi

~One down.~ -> three down.

  • [x] https://github.com/package-url/purl-spec/pull/735
  • [x] https://github.com/package-url/purl-spec/pull/733
  • [x] https://github.com/package-url/purl-spec/pull/734
  • [x] https://github.com/package-url/purl-spec/pull/730.

petergardfjall avatar Dec 04 '25 07:12 petergardfjall

I approved all purl-spec PRs, but I am sadly not a purl-spec maintainer. This means, you will have to reach out to @pombredanne or someone else

Let me review and merge these ASAP!

but I am sadly not a purl-spec maintainer

@shibumi you have been a long time contributor.... would you want to join as a spec helper too?

pombredanne avatar Dec 04 '25 08:12 pombredanne

@shibumi you have been a long time contributor.... would you want to join as a spec helper too?

Depends how time consuming it is :) Would be an honor.

shibumi avatar Dec 06 '25 13:12 shibumi

@shibumi re:

Depends how time consuming it is

It is as consuming as you decide it to be: big to small to nothing. See:

  • https://github.com/package-url/purl-spec/issues/766

pombredanne avatar Dec 08 '25 11:12 pombredanne

@shibumi All tests from the purl-spec now pass :tada: Please review the changes before we merge.

petergardfjall avatar Dec 15 '25 07:12 petergardfjall

@shibumi @pombredanne Bump. Needs a re-review before being merged.

petergardfjall avatar Dec 18 '25 14:12 petergardfjall